From 231a299b164177c532ec9b8a829cddbc5a0fad64 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 25 Apr 2017 08:41:48 -0400 Subject: [PATCH] Initial commit at Tue Apr 25 08:41:48 EDT 2017 by tim on stravinsky --- .gitignore | 10 + INSTALL | 72 + Makefile | 129 + README | 374 + README.Tcl | 385 + TODO | 8 + VERSION | 1 + calma/CalmaRdcl.c | 1079 ++ calma/CalmaRdio.c | 547 + calma/CalmaRdpt.c | 1018 ++ calma/CalmaRead.c | 494 + calma/CalmaWrite.c | 2478 +++++ calma/Depend | 30 + calma/Makefile | 10 + calma/calma.h | 45 + calma/calmaInt.h | 235 + cif/CIFgen.c | 3338 ++++++ cif/CIFhier.c | 1146 ++ cif/CIFint.h | 340 + cif/CIFmain.c | 413 + cif/CIFrdcl.c | 1389 +++ cif/CIFrdpoly.c | 335 + cif/CIFrdpt.c | 765 ++ cif/CIFrdtech.c | 1383 +++ cif/CIFrdutils.c | 1664 +++ cif/CIFread.h | 201 + cif/CIFsee.c | 490 + cif/CIFtech.c | 2308 ++++ cif/CIFwrite.c | 711 ++ cif/Depend | 45 + cif/Makefile | 11 + cif/cif.h | 88 + cmwind/CMWcmmnds.c | 658 ++ cmwind/CMWmain.c | 436 + cmwind/CMWrgbhsv.c | 325 + cmwind/CMWundo.c | 210 + cmwind/Depend | 16 + cmwind/Makefile | 10 + cmwind/cmwind.h | 80 + commands/CmdAB.c | 1157 ++ commands/CmdAuto.c | 208 + commands/CmdCD.c | 4048 +++++++ commands/CmdE.c | 1200 +++ commands/CmdFI.c | 1955 ++++ commands/CmdLQ.c | 1883 ++++ commands/CmdRS.c | 2708 +++++ commands/CmdSubrs.c | 1173 +++ commands/CmdTZ.c | 2037 ++++ commands/CmdWizard.c | 1067 ++ commands/Depend | 62 + commands/Makefile | 21 + commands/commands.h | 67 + configure | 12 + database/DBbound.c | 261 + database/DBcell.c | 706 ++ database/DBcellbox.c | 852 ++ database/DBcellcopy.c | 1023 ++ database/DBcellname.c | 2093 ++++ database/DBcellsel.c | 343 + database/DBcellsrch.c | 1851 ++++ database/DBcellsubr.c | 368 + database/DBconnect.c | 933 ++ database/DBcount.c | 168 + database/DBexpand.c | 324 + database/DBio.c | 3159 ++++++ database/DBlabel.c | 1551 +++ database/DBlabel2.c | 601 ++ database/DBpaint.c | 3454 ++++++ database/DBpaint2.c | 408 + database/DBprop.c | 202 + database/DBtcontact.c | 1013 ++ database/DBtech.c | 435 + database/DBtechname.c | 777 ++ database/DBtechtype.c | 826 ++ database/DBtiles.c | 1057 ++ database/DBtimestmp.c | 295 + database/DBtpaint.c | 832 ++ database/DBtpaint2.c | 920 ++ database/DBundo.c | 1007 ++ database/Depend | 96 + database/Makefile | 20 + database/database.h.in | 1109 ++ database/databaseInt.h | 243 + database/fonts.h | 42 + dbwind/DBWbuttons.c | 404 + dbwind/DBWcommands.c | 680 ++ dbwind/DBWdisplay.c | 1781 ++++ dbwind/DBWelement.c | 1204 +++ dbwind/DBWfdback.c | 645 ++ dbwind/DBWhlights.c | 438 + dbwind/DBWprocs.c | 722 ++ dbwind/DBWtools.c | 1044 ++ dbwind/DBWundo.c | 312 + dbwind/Depend | 41 + dbwind/Makefile | 11 + dbwind/dbwind.h | 235 + dbwind/dbwtech.h | 21 + debug/Depend | 5 + debug/Makefile | 10 + debug/debug.h | 78 + debug/debugFlags.c | 237 + debug/hist.c | 242 + defs.mak | 93 + doc/Makefile | 58 + doc/html/Makefile | 14 + doc/html/addcommandentry.html | 72 + doc/html/addpath.html | 72 + doc/html/array.html | 118 + doc/html/box.html | 147 + doc/html/calma.html | 189 + doc/html/caption.html | 63 + doc/html/cellmanager.html | 169 + doc/html/cellname.html | 146 + doc/html/cellsearch.html | 113 + doc/html/center.html | 75 + doc/html/changetool.html | 150 + doc/html/channels.html | 64 + doc/html/cif.html | 193 + doc/html/clockwise.html | 78 + doc/html/closewindow.html | 74 + doc/html/closewrapper.html | 71 + doc/html/color/color.html | 82 + doc/html/color/load.html | 80 + doc/html/color/pushbutton.html | 63 + doc/html/color/save.html | 79 + doc/html/commands.html | 703 ++ doc/html/commands.list | 127 + doc/html/contact.html | 60 + doc/html/copy.html | 86 + doc/html/corner.html | 98 + doc/html/crash.html | 104 + doc/html/crashbackups.html | 68 + doc/html/crosshair.html | 57 + doc/html/cursor.html | 64 + doc/html/def.html | 84 + doc/html/delete.html | 55 + doc/html/deletecommandentry.html | 65 + doc/html/direction.html | 75 + doc/html/distance.html | 67 + doc/html/down.html | 62 + doc/html/drc.html | 135 + doc/html/dump.html | 72 + doc/html/edit.html | 54 + doc/html/element.html | 198 + doc/html/erase.html | 84 + doc/html/expand.html | 69 + doc/html/ext.html | 138 + doc/html/ext2sim.html | 161 + doc/html/ext2spice.html | 176 + doc/html/extract.html | 138 + doc/html/extresist.html | 118 + doc/html/exttosim.html | 161 + doc/html/exttospice.html | 176 + doc/html/feedback.html | 127 + doc/html/fill.html | 67 + doc/html/findbox.html | 60 + doc/html/findlabel.html | 58 + doc/html/flatten.html | 81 + doc/html/flush.html | 63 + doc/html/garoute.html | 81 + doc/html/gds.html | 189 + doc/html/get.html | 102 + doc/html/getcell.html | 102 + doc/html/getnode.html | 77 + doc/html/goto.html | 75 + doc/html/graphics/blpaper.gif | Bin 0 -> 9220 bytes doc/html/graphics/cellmgr.gif | Bin 0 -> 9375 bytes doc/html/graphics/cif_see.gif | Bin 0 -> 49244 bytes doc/html/graphics/corner1.gif | Bin 0 -> 1645 bytes doc/html/graphics/corner2.gif | Bin 0 -> 2616 bytes doc/html/graphics/email_address.png | Bin 0 -> 893 bytes doc/html/graphics/line1.gif | Bin 0 -> 302 bytes doc/html/graphics/magic_OGL_sm.gif | Bin 0 -> 8078 bytes doc/html/graphics/magic_title2.gif | Bin 0 -> 10744 bytes doc/html/graphics/techmgr.gif | Bin 0 -> 4757 bytes doc/html/graphics/toolbar.gif | Bin 0 -> 10273 bytes doc/html/graphics/writeall.gif | Bin 0 -> 3934 bytes doc/html/grid.html | 115 + doc/html/help.html | 79 + doc/html/identify.html | 62 + doc/html/imacro.html | 80 + doc/html/initialize.html | 68 + doc/html/instance.html | 103 + doc/html/invoke.html | 149 + doc/html/iroute.html | 124 + doc/html/irsim.html | 78 + doc/html/label.html | 79 + doc/html/lef.html | 138 + doc/html/load.html | 97 + doc/html/logcommands.html | 55 + doc/html/macro.html | 102 + doc/html/maketoolbar.html | 101 + doc/html/measure.html | 66 + doc/html/move.html | 86 + doc/html/netlist.html | 81 + doc/html/netlist/add.html | 59 + doc/html/netlist/cleanup.html | 67 + doc/html/netlist/cull.html | 53 + doc/html/netlist/dnet.html | 62 + doc/html/netlist/dterm.html | 62 + doc/html/netlist/extract.html | 55 + doc/html/netlist/find.html | 59 + doc/html/netlist/flush.html | 59 + doc/html/netlist/joinnets.html | 65 + doc/html/netlist/netlist.html | 60 + doc/html/netlist/print.html | 58 + doc/html/netlist/pushbutton.html | 60 + doc/html/netlist/ripup.html | 56 + doc/html/netlist/savenetlist.html | 62 + doc/html/netlist/shownet.html | 61 + doc/html/netlist/showterms.html | 62 + doc/html/netlist/trace.html | 60 + doc/html/netlist/verify.html | 55 + doc/html/netlist/writeall.html | 67 + doc/html/openwindow.html | 81 + doc/html/openwrapper.html | 73 + doc/html/paint.html | 76 + doc/html/path.html | 74 + doc/html/peekbox.html | 60 + doc/html/plot.html | 163 + doc/html/plow.html | 94 + doc/html/polygon.html | 77 + doc/html/popbox.html | 59 + doc/html/popstack.html | 63 + doc/html/port.html | 140 + doc/html/promptload.html | 74 + doc/html/promptsave.html | 72 + doc/html/property.html | 66 + doc/html/pushbox.html | 59 + doc/html/pushbutton.html | 66 + doc/html/pushstack.html | 66 + doc/html/quit.html | 63 + doc/html/redo.html | 69 + doc/html/redraw.html | 54 + doc/html/render3d.html | 59 + doc/html/resumeall.html | 68 + doc/html/rotate.html | 73 + doc/html/route.html | 91 + doc/html/ruler.html | 71 + doc/html/save.html | 65 + doc/html/scalegrid.html | 76 + doc/html/scroll.html | 75 + doc/html/search.html | 114 + doc/html/see.html | 85 + doc/html/select.html | 152 + doc/html/setpoint.html | 84 + doc/html/shell.html | 66 + doc/html/sideways.html | 61 + doc/html/sleep.html | 56 + doc/html/snap.html | 94 + doc/html/specialopen.html | 80 + doc/html/spliterase.html | 77 + doc/html/splitpaint.html | 75 + doc/html/startup.html | 63 + doc/html/straighten.html | 61 + doc/html/stretch.html | 96 + doc/html/suspendall.html | 69 + doc/html/tag.html | 116 + doc/html/tech.html | 131 + doc/html/techmanager.html | 71 + doc/html/template.html | 66 + doc/html/tk_path_name.html | 93 + doc/html/tool.html | 119 + doc/html/undo.html | 75 + doc/html/unexpand.html | 62 + doc/html/unmeasure.html | 57 + doc/html/updatedisplay.html | 67 + doc/html/upsidedown.html | 61 + doc/html/version.html | 51 + doc/html/view.html | 73 + doc/html/what.html | 67 + doc/html/wind3d/cif.html | 85 + doc/html/wind3d/closewindow.html | 71 + doc/html/wind3d/cutbox.html | 75 + doc/html/wind3d/defaults.html | 71 + doc/html/wind3d/help.html | 73 + doc/html/wind3d/level.html | 79 + doc/html/wind3d/refresh.html | 68 + doc/html/wind3d/render.html | 81 + doc/html/wind3d/scroll.html | 84 + doc/html/wind3d/see.html | 77 + doc/html/wind3d/view.html | 87 + doc/html/wind3d/zoom.html | 101 + doc/html/windowborder.html | 56 + doc/html/windowcaption.html | 57 + doc/html/windownames.html | 71 + doc/html/windowscrollbars.html | 57 + doc/html/wire.html | 114 + doc/html/wizard/coord.html | 61 + doc/html/wizard/crash.html | 53 + doc/html/wizard/extract.html | 92 + doc/html/wizard/files.html | 53 + doc/html/wizard/grstats.html | 54 + doc/html/wizard/pause.html | 53 + doc/html/wizard/plow.html | 102 + doc/html/wizard/psearch.html | 56 + doc/html/wizard/showtech.html | 61 + doc/html/wizard/tilestats.html | 56 + doc/html/wizard/tsearch.html | 59 + doc/html/wizard/watch.html | 72 + doc/html/wizard/winddebug.html | 54 + doc/html/wizard/winddump.html | 55 + doc/html/writeall.html | 93 + doc/html/xload.html | 62 + doc/html/xview.html | 59 + doc/html/zoom.html | 74 + doc/latexfiles/Makefile | 56 + doc/latexfiles/addendum6_5.tex | 203 + doc/latexfiles/copyright.tex | 40 + doc/latexfiles/introduction.tex | 266 + doc/latexfiles/maint1.tex | 646 ++ doc/latexfiles/maint2.tex | 3549 +++++++ doc/latexfiles/maint3.tex | 275 + doc/latexfiles/maint4.tex | 202 + doc/latexfiles/manual.tex | 95 + doc/latexfiles/tut1.tex | 497 + doc/latexfiles/tut10.tex | 580 + doc/latexfiles/tut11.tex | 467 + doc/latexfiles/tut2.tex | 855 ++ doc/latexfiles/tut3.tex | 544 + doc/latexfiles/tut4.tex | 603 ++ doc/latexfiles/tut5.tex | 465 + doc/latexfiles/tut6.tex | 377 + doc/latexfiles/tut7.tex | 904 ++ doc/latexfiles/tut8.tex | 996 ++ doc/latexfiles/tut9.tex | 392 + doc/latexfiles/tutscm1.tex | 700 ++ doc/latexfiles/tutscm2.tex | 269 + doc/latexfiles/tutscm3.tex | 161 + doc/latexfiles/tutscm4.tex | 78 + doc/latexfiles/tuttcl1.tex | 581 ++ doc/latexfiles/tuttcl2.tex | 64 + doc/latexfiles/tuttcl3.tex | 66 + doc/latexfiles/tuttcl4.tex | 517 + doc/latexfiles/tuttcl5.tex | 64 + doc/latexfiles/tutwrl1.tex | 247 + doc/man/Makefile | 50 + doc/man/cmap.5 | 60 + doc/man/displays.5 | 70 + doc/man/dlys.5 | 88 + doc/man/dstyle.5 | 176 + doc/man/ext.5 | 306 + doc/man/ext2sim.1 | 183 + doc/man/ext2spice.1 | 152 + doc/man/extcheck.1 | 121 + doc/man/glyphs.5 | 78 + doc/man/mag.5 | 236 + doc/man/magic.1 | 2472 +++++ doc/man/net.5 | 80 + doc/man/sim.5 | 116 + doc/man/tmac.anc | 272 + doc/psfigures/maint2.1.ps | 205 + doc/psfigures/maint2.11.ps | 167 + doc/psfigures/maint2.2.ps | 188 + doc/psfigures/maint2.3.ps | 202 + doc/psfigures/maint2.3b.ps | 251 + doc/psfigures/maint2.4.ps | 188 + doc/psfigures/maint2.5.ps | 181 + doc/psfigures/maint2.6.ps | 168 + doc/psfigures/maint2.6b.ps | 237 + doc/psfigures/maint2.7.ps | 218 + doc/psfigures/maint2.8.ps | 186 + doc/psfigures/maint2.9.ps | 279 + doc/psfigures/tut2.1.ps | 376 + doc/psfigures/tut2.2.ps | 242 + doc/psfigures/tut7.1.ps | 196 + doc/psfigures/tut7.2.ps | 258 + doc/psfigures/tut7.3.ps | 185 + doc/psfigures/tut8.1.ps | 244 + doc/psfigures/tut8.2.ps | 193 + doc/psfigures/tut8.3.ps | 215 + doc/psfigures/tut8.4.ps | 224 + doc/psfigures/tut8.5.ps | 274 + doc/psfigures/tut9.1.ps | 222 + doc/psfigures/tutcell.cif | 48 + doc/psfigures/tutcell1.mag | 59 + doc/psfigures/tutw1.1.ps | 214 + doc/psfigures/tutw1.2.ps | 176 + doc/psfiles/addendum6_5.ps | 357 + doc/psfiles/copyright.ps | 259 + doc/psfiles/introduction.ps | 492 + doc/psfiles/maint1.ps | 1292 +++ doc/psfiles/maint2.ps | 7351 +++++++++++++ doc/psfiles/maint3.ps | 501 + doc/psfiles/maint4.ps | 400 + doc/psfiles/tut1.ps | 767 ++ doc/psfiles/tut10.ps | 733 ++ doc/psfiles/tut11.ps | 652 ++ doc/psfiles/tut2.ps | 1777 ++++ doc/psfiles/tut3.ps | 769 ++ doc/psfiles/tut4.ps | 861 ++ doc/psfiles/tut5.ps | 671 ++ doc/psfiles/tut6.ps | 560 + doc/psfiles/tut7.ps | 1977 ++++ doc/psfiles/tut8.ps | 2485 +++++ doc/psfiles/tut9.ps | 869 ++ doc/psfiles/tutscm1.ps | 878 ++ doc/psfiles/tutscm2.ps | 474 + doc/psfiles/tutscm3.ps | 481 + doc/psfiles/tutscm4.ps | 232 + doc/psfiles/tuttcl1.ps | 862 ++ doc/psfiles/tuttcl2.ps | 241 + doc/psfiles/tuttcl3.ps | 244 + doc/psfiles/tuttcl4.ps | 959 ++ doc/psfiles/tuttcl5.ps | 242 + doc/psfiles/tutwrl1.ps | 820 ++ doc/textfiles/LEF.txt | 123 + doc/textfiles/default_macros.txt | 112 + doc/textfiles/hires-color.txt | 52 + doc/textfiles/locking.txt | 74 + doc/textfiles/macro_extension.txt | 270 + doc/textfiles/non-manhattan.txt | 108 + doc/textfiles/open_gl.txt | 184 + doc/textfiles/readline.txt | 71 + doc/tutcells/Makefile | 37 + doc/tutcells/m3a.mag | 25 + doc/tutcells/maint2a.mag | 24 + doc/tutcells/tut1.mag | 10 + doc/tutcells/tut11a.al | 68 + doc/tutcells/tut11a.cmd | 6 + doc/tutcells/tut11a.ext | 113 + doc/tutcells/tut11a.mag | 100 + doc/tutcells/tut11a.nodes | 72 + doc/tutcells/tut11a.sim | 280 + doc/tutcells/tut11b.ext | 47 + doc/tutcells/tut11b.mag | 70 + doc/tutcells/tut11c.ext | 44 + doc/tutcells/tut11c.mag | 74 + doc/tutcells/tut11d.ext | 101 + doc/tutcells/tut11d.mag | 327 + doc/tutcells/tut2.f1a.cif | 34 + doc/tutcells/tut2.f1b.cif | 66 + doc/tutcells/tut2a.mag | 20 + doc/tutcells/tut2b.mag | 17 + doc/tutcells/tut2c.mag | 15 + doc/tutcells/tut2d.mag | 28 + doc/tutcells/tut3a.mag | 21 + doc/tutcells/tut3b.mag | 15 + doc/tutcells/tut3c.mag | 21 + doc/tutcells/tut3d.mag | 410 + doc/tutcells/tut3e.mag | 54 + doc/tutcells/tut3f.mag | 26 + doc/tutcells/tut3g.mag | 31 + doc/tutcells/tut3h.mag | 13 + doc/tutcells/tut4a.mag | 29 + doc/tutcells/tut4x.mag | 125 + doc/tutcells/tut4y.mag | 22 + doc/tutcells/tut4z.mag | 78 + doc/tutcells/tut5a.mag | 220 + doc/tutcells/tut5b.mag | 78 + doc/tutcells/tut6a.mag | 17 + doc/tutcells/tut6b.mag | 31 + doc/tutcells/tut6c.mag | 30 + doc/tutcells/tut6x.mag | 9 + doc/tutcells/tut6y.mag | 42 + doc/tutcells/tut7a.mag | 41 + doc/tutcells/tut7b.mag | 18 + doc/tutcells/tut7b.net | 17 + doc/tutcells/tut7c.mag | 53 + doc/tutcells/tut7d.mag | 88 + doc/tutcells/tut7d.net | 17 + doc/tutcells/tut8a.mag | 24 + doc/tutcells/tut8b.mag | 28 + doc/tutcells/tut8c.mag | 32 + doc/tutcells/tut8d.mag | 9 + doc/tutcells/tut8e.mag | 90 + doc/tutcells/tut8f.mag | 14 + doc/tutcells/tut8g.mag | 90 + doc/tutcells/tut8h.mag | 32 + doc/tutcells/tut8i.mag | 8 + doc/tutcells/tut8j.mag | 8 + doc/tutcells/tut8k.mag | 22 + doc/tutcells/tut8l.mag | 107 + doc/tutcells/tut8m.mag | 41 + doc/tutcells/tut8n.mag | 20 + doc/tutcells/tut8r.mag | 162 + doc/tutcells/tut9a.mag | 49 + doc/tutcells/tut9b.mag | 11 + doc/tutcells/tut9x.mag | 57 + doc/tutcells/tut9y.mag | 59 + doc/tutcells/tuttcl1.cmd | 4 + drc/DRCarray.c | 387 + drc/DRCbasic.c | 1108 ++ drc/DRCcif.c | 1425 +++ drc/DRCcontin.c | 798 ++ drc/DRCextend.c | 527 + drc/DRCmain.c | 921 ++ drc/DRCprint.c | 186 + drc/DRCsubcell.c | 750 ++ drc/DRCtech.c | 3886 +++++++ drc/Depend | 36 + drc/Makefile | 11 + drc/drc.h | 273 + ext2sim/Depend | 6 + ext2sim/Makefile | 37 + ext2sim/ext2sim.c | 1707 +++ ext2sim/finds.c | 97 + ext2sim/sim2simp.c | 156 + ext2sim/sim2spi | 88 + ext2spice/Depend | 14 + ext2spice/Makefile | 44 + ext2spice/ext2hier.c | 1830 ++++ ext2spice/ext2spice.c | 3739 +++++++ ext2spice/ext2spice.h | 205 + ext2spice/spice2sim | 81 + extcheck/Depend | 3 + extcheck/Makefile | 22 + extcheck/extcheck.c | 173 + extflat/COMPRESS | 162 + extflat/Depend | 30 + extflat/EFargs.c | 397 + extflat/EFbuild.c | 1729 +++ extflat/EFdef.c | 266 + extflat/EFerr.c | 80 + extflat/EFflat.c | 1155 ++ extflat/EFhier.c | 741 ++ extflat/EFint.h | 321 + extflat/EFname.c | 1000 ++ extflat/EFread.c | 715 ++ extflat/EFsym.c | 203 + extflat/EFvisit.c | 905 ++ extflat/Makefile | 11 + extflat/READ_ME | 5 + extflat/extflat.h | 360 + extract/Depend | 97 + extract/ExtArray.c | 1021 ++ extract/ExtBasic.c | 3639 +++++++ extract/ExtCell.c | 406 + extract/ExtCouple.c | 1169 +++ extract/ExtHard.c | 504 + extract/ExtHier.c | 909 ++ extract/ExtInter.c | 691 ++ extract/ExtLength.c | 1033 ++ extract/ExtMain.c | 676 ++ extract/ExtNghbors.c | 375 + extract/ExtPerim.c | 183 + extract/ExtRegion.c | 454 + extract/ExtSubtree.c | 1141 ++ extract/ExtTech.c | 2968 ++++++ extract/ExtTest.c | 1431 +++ extract/ExtTimes.c | 1112 ++ extract/ExtUnique.c | 270 + extract/ExtYank.c | 264 + extract/Makefile | 13 + extract/extDebugInt.h | 40 + extract/extract.h | 89 + extract/extractInt.h | 1057 ++ extract/extractInt.h.new | 1053 ++ garouter/Depend | 46 + garouter/Makefile | 11 + garouter/OUTLINE | 36 + garouter/TODO | 18 + garouter/gaChannel.c | 629 ++ garouter/gaDebug.h | 34 + garouter/gaInternal.h | 99 + garouter/gaMain.c | 463 + garouter/gaMaze.c | 403 + garouter/gaSimple.c | 705 ++ garouter/gaStem.c | 1174 +++ garouter/gaTest.c | 416 + garouter/garouter.h | 103 + gcr/Depend | 29 + gcr/Makefile | 12 + gcr/gcr.h | 346 + gcr/gcrChannel.c | 494 + gcr/gcrColl.c | 397 + gcr/gcrDebug.c | 1024 ++ gcr/gcrEdge.c | 275 + gcr/gcrFeas.c | 248 + gcr/gcrFlags.c | 144 + gcr/gcrInit.c | 398 + gcr/gcrLib.c | 456 + gcr/gcrRiver.c | 179 + gcr/gcrRoute.c | 319 + gcr/gcrShwFlgs.c | 269 + gcr/gcrUnsplit.c | 610 ++ graphics/DEFAULT.glyphs | 349 + graphics/Depend | 138 + graphics/FreeMono.pt3 | 2837 +++++ graphics/FreeSans.pt3 | 2014 ++++ graphics/FreeSerif.pt3 | 2915 ++++++ graphics/Makefile | 60 + graphics/README.X10a | 2 + graphics/READ_ME | 21 + graphics/W3Dmain.c | 1874 ++++ graphics/X11Helper.c | 333 + graphics/bw.glyphs | 417 + graphics/color.glyphs | 417 + graphics/glyphs.h | 57 + graphics/grCMap.c | 448 + graphics/grClip.c | 1676 +++ graphics/grDStyle.c | 633 ++ graphics/grGlyphs.c | 242 + graphics/grLock.c | 216 + graphics/grMain.c | 533 + graphics/grNull.c | 285 + graphics/grOGL1.c | 1078 ++ graphics/grOGL2.c | 217 + graphics/grOGL3.c | 843 ++ graphics/grOGL4.c | 138 + graphics/grOGL5.c | 324 + graphics/grOGLInt.h | 95 + graphics/grTOGL1.c | 1451 +++ graphics/grTOGL2.c | 229 + graphics/grTOGL3.c | 705 ++ graphics/grTOGL3.c.test | 812 ++ graphics/grTOGL4.c | 133 + graphics/grTOGL5.c | 209 + graphics/grTOGLInt.h | 116 + graphics/grText.c | 375 + graphics/grTk1.c | 1794 ++++ graphics/grTk2.c | 307 + graphics/grTk3.c | 556 + graphics/grTk4.c | 129 + graphics/grTk5.c | 185 + graphics/grTkCommon.c | 1508 +++ graphics/grTkCommon.h | 46 + graphics/grTkInt.h | 92 + graphics/grX11Int.h | 118 + graphics/grX11su1.c | 1445 +++ graphics/grX11su2.c | 330 + graphics/grX11su3.c | 851 ++ graphics/grX11su4.c | 137 + graphics/grX11su5.c | 326 + graphics/grX11thread.c | 243 + graphics/graphics.h | 225 + graphics/graphicsInt.h | 92 + graphics/prcolors.c | 22 + graphics/wind3d.h | 70 + grouter/Depend | 58 + grouter/Makefile | 11 + grouter/TODO | 6 + grouter/grouteChan.c | 1098 ++ grouter/grouteCrss.c | 795 ++ grouter/grouteDebug.h | 60 + grouter/grouteDens.c | 327 + grouter/grouteMain.c | 393 + grouter/grouteMaze.c | 609 ++ grouter/grouteMult.c | 308 + grouter/grouteName.c | 131 + grouter/grouteNet.c | 1794 ++++ grouter/groutePath.c | 289 + grouter/groutePen.c | 909 ++ grouter/groutePin.c | 480 + grouter/grouteTest.c | 598 ++ grouter/grouteTile.c | 394 + grouter/grouter.h | 267 + irouter/Depend | 34 + irouter/Makefile | 10 + irouter/irCommand.c | 2670 +++++ irouter/irDebug.h | 37 + irouter/irInternal.h | 78 + irouter/irMain.c | 161 + irouter/irRoute.c | 1187 +++ irouter/irTestCmd.c | 311 + irouter/irUtils.c | 164 + irouter/irouter.h | 52 + lef/Depend | 27 + lef/Makefile | 31 + lef/defRead.c | 1439 +++ lef/defWrite.c | 1956 ++++ lef/lef.h | 24 + lef/lefCmd.c | 220 + lef/lefInt.h | 137 + lef/lefRead.c | 2067 ++++ lef/lefTech.c | 448 + lef/lefWrite.c | 1062 ++ lef/tcllef.c | 63 + lisp/Depend | 33 + lisp/Makefile | 23 + lisp/README | 23 + lisp/lisp.h | 38 + lisp/lispA-Z.c | 1572 +++ lisp/lispA-Z.h | 135 + lisp/lispArith.c | 369 + lisp/lispEval.c | 650 ++ lisp/lispFrame.c | 302 + lisp/lispGC.c | 584 ++ lisp/lispIO.c | 381 + lisp/lispInt.h | 150 + lisp/lispMagic.c | 589 ++ lisp/lispMain.c | 229 + lisp/lispParse.c | 415 + lisp/lispPrint.c | 339 + lisp/lispString.c | 434 + lisp/lispTrace.c | 186 + lisp/lispargs.h | 49 + lisp/scm/box.scm | 81 + lisp/scm/default.scm | 171 + lisp/scm/draw.scm | 90 + lisp/scm/drc.scm | 133 + lisp/scm/gate.scm | 193 + lisp/scm/help.scm | 168 + lisp/scm/label.scm | 292 + lisp/scm/layout.scm | 46 + lisp/scm/prs.scm | 1605 +++ lisp/scm/sel.scm | 154 + lisp/scm/stack.scm | 517 + magic/Depend | 1 + magic/Makefile | 70 + magic/bitmaps/down.xbm | 6 + magic/bitmaps/left.xbm | 6 + magic/bitmaps/lock.xbm | 6 + magic/bitmaps/right.xbm | 6 + magic/bitmaps/up.xbm | 6 + magic/bitmaps/zoom.xbm | 6 + magic/magicTop.c | 65 + magic/magicps.pro | 71 + magic/proto.initrc | 4 + magic/proto.magicrc.m4 | 310 + magic/symbol.map | 277 + mzrouter/Depend | 100 + mzrouter/Makefile | 13 + mzrouter/mzBlock.c | 1479 +++ mzrouter/mzDebug.c | 564 + mzrouter/mzDebug.h | 37 + mzrouter/mzEstimate.c | 2024 ++++ mzrouter/mzHint.c | 196 + mzrouter/mzInit.c | 371 + mzrouter/mzInternal.h | 482 + mzrouter/mzMain.c | 1318 +++ mzrouter/mzNumLine.c | 268 + mzrouter/mzSearch.c | 1518 +++ mzrouter/mzStart.c | 416 + mzrouter/mzSubrs.c | 817 ++ mzrouter/mzTech.c | 1397 +++ mzrouter/mzTestCmd.c | 619 ++ mzrouter/mzWalk.c | 690 ++ mzrouter/mzXtndDown.c | 634 ++ mzrouter/mzXtndLeft.c | 639 ++ mzrouter/mzXtndRght.c | 634 ++ mzrouter/mzXtndUp.c | 632 ++ mzrouter/mzrouter.h | 348 + net2ir/Depend | 2 + net2ir/Makefile | 23 + net2ir/net2ir.c | 158 + netmenu/Depend | 46 + netmenu/Makefile | 11 + netmenu/NMbutton.c | 509 + netmenu/NMcmdAK.c | 605 ++ netmenu/NMcmdLZ.c | 572 + netmenu/NMlabel.c | 654 ++ netmenu/NMmain.c | 573 + netmenu/NMnetlist.c | 1007 ++ netmenu/NMshowcell.c | 423 + netmenu/NMshowpt.c | 302 + netmenu/NMundo.c | 233 + netmenu/NMwiring.c | 1382 +++ netmenu/netmenu.h | 59 + netmenu/nmInt.h | 147 + oa/.deps/magicInit.P | 780 ++ oa/.deps/magicOA.P | 778 ++ oa/Makefile | 37 + oa/magicInit.cpp | 317 + oa/magicInit.h | 98 + oa/magicOA.cpp | 339 + oa/magicOA.h | 31 + oa/oa.c | 192 + oa/oa.h | 23 + plot/Depend | 41 + plot/Makefile | 37 + plot/plot.h | 53 + plot/plotCmd.c | 325 + plot/plotGremln.c | 834 ++ plot/plotHP.c | 352 + plot/plotInt.h | 238 + plot/plotMain.c | 649 ++ plot/plotPNM.c | 1475 +++ plot/plotPS.c | 1314 +++ plot/plotPixels.c | 1487 +++ plot/plotRutils.c | 1141 ++ plot/plotVers.c | 1476 +++ plot/tclplot.c | 74 + plow/Depend | 50 + plow/Makefile | 12 + plow/PlowCmd.c | 397 + plow/PlowJogs.c | 618 ++ plow/PlowMain.c | 2264 ++++ plow/PlowQueue.c | 588 ++ plow/PlowRandom.c | 309 + plow/PlowRules1.c | 1028 ++ plow/PlowRules2.c | 1118 ++ plow/PlowRules3.c | 400 + plow/PlowSearch.c | 1313 +++ plow/PlowTech.c | 372 + plow/PlowTest.c | 823 ++ plow/PlowWidth.c | 554 + plow/PlowYank.c | 550 + plow/TODO | 6 + plow/plow.h | 56 + plow/plowDebugInt.h | 35 + plow/plowInt.h | 258 + readline/Makefile | 25 + readline/README | 6 + readline/readline-4.3/CHANGELOG | 699 ++ readline/readline-4.3/CHANGES | 612 ++ readline/readline-4.3/COPYING | 339 + readline/readline-4.3/INSTALL | 273 + readline/readline-4.3/MANIFEST | 126 + readline/readline-4.3/Makefile.in | 520 + readline/readline-4.3/README | 172 + readline/readline-4.3/USAGE | 37 + readline/readline-4.3/aclocal.m4 | 1792 ++++ readline/readline-4.3/ansi_stdlib.h | 54 + readline/readline-4.3/bind.c | 2150 ++++ readline/readline-4.3/callback.c | 156 + readline/readline-4.3/chardefs.h | 159 + readline/readline-4.3/compat.c | 113 + readline/readline-4.3/complete.c | 2004 ++++ readline/readline-4.3/config.h.in | 200 + readline/readline-4.3/configure | 8069 ++++++++++++++ readline/readline-4.3/configure.in | 206 + readline/readline-4.3/display.c | 2198 ++++ readline/readline-4.3/doc/Makefile.in | 234 + readline/readline-4.3/doc/hist.texinfo | 110 + readline/readline-4.3/doc/history.3 | 640 ++ readline/readline-4.3/doc/hstech.texinfo | 550 + readline/readline-4.3/doc/hsuser.texinfo | 437 + readline/readline-4.3/doc/manvers.texinfo | 10 + readline/readline-4.3/doc/readline.3 | 1272 +++ readline/readline-4.3/doc/rlman.texinfo | 108 + readline/readline-4.3/doc/rltech.texinfo | 2165 ++++ readline/readline-4.3/doc/rluser.texinfo | 1796 ++++ readline/readline-4.3/doc/rluserman.texinfo | 94 + readline/readline-4.3/doc/texi2dvi | 568 + readline/readline-4.3/doc/texi2html | 5429 ++++++++++ readline/readline-4.3/doc/texinfo.tex | 5992 +++++++++++ readline/readline-4.3/emacs_keymap.c | 873 ++ readline/readline-4.3/examples/Inputrc | 81 + readline/readline-4.3/examples/Makefile.in | 104 + readline/readline-4.3/examples/excallback.c | 188 + readline/readline-4.3/examples/fileman.c | 485 + readline/readline-4.3/examples/histexamp.c | 112 + readline/readline-4.3/examples/manexamp.c | 112 + readline/readline-4.3/examples/readlinebuf.h | 139 + readline/readline-4.3/examples/rl.c | 151 + readline/readline-4.3/examples/rlcat.c | 174 + readline/readline-4.3/examples/rlfe.c | 1042 ++ readline/readline-4.3/examples/rltest.c | 87 + readline/readline-4.3/examples/rlversion.c | 43 + readline/readline-4.3/funmap.c | 253 + readline/readline-4.3/histexpand.c | 1491 +++ readline/readline-4.3/histfile.c | 479 + readline/readline-4.3/histlib.h | 82 + readline/readline-4.3/history.c | 381 + readline/readline-4.3/history.h | 246 + readline/readline-4.3/histsearch.c | 195 + readline/readline-4.3/input.c | 540 + readline/readline-4.3/isearch.c | 560 + readline/readline-4.3/keymaps.c | 150 + readline/readline-4.3/keymaps.h | 103 + readline/readline-4.3/kill.c | 652 ++ readline/readline-4.3/macro.c | 262 + readline/readline-4.3/mbutil.c | 345 + readline/readline-4.3/misc.c | 496 + readline/readline-4.3/nls.c | 225 + readline/readline-4.3/parens.c | 179 + readline/readline-4.3/posixdir.h | 57 + readline/readline-4.3/posixjmp.h | 40 + readline/readline-4.3/posixstat.h | 142 + readline/readline-4.3/readline.c | 974 ++ readline/readline-4.3/readline.h | 799 ++ readline/readline-4.3/rlconf.h | 60 + readline/readline-4.3/rldefs.h | 156 + readline/readline-4.3/rlmbutil.h | 108 + readline/readline-4.3/rlprivate.h | 284 + readline/readline-4.3/rlshell.h | 34 + readline/readline-4.3/rlstdc.h | 45 + readline/readline-4.3/rltty.c | 911 ++ readline/readline-4.3/rltty.h | 82 + readline/readline-4.3/rltypedefs.h | 88 + readline/readline-4.3/rlwinsize.h | 57 + readline/readline-4.3/savestring.c | 36 + readline/readline-4.3/search.c | 465 + readline/readline-4.3/shell.c | 196 + readline/readline-4.3/shlib/Makefile.in | 437 + readline/readline-4.3/signals.c | 398 + readline/readline-4.3/support/config.guess | 1393 +++ readline/readline-4.3/support/config.sub | 1497 +++ readline/readline-4.3/support/install.sh | 247 + readline/readline-4.3/support/mkdirs | 48 + readline/readline-4.3/support/mkdist | 120 + readline/readline-4.3/support/shlib-install | 156 + readline/readline-4.3/support/shobj-conf | 458 + readline/readline-4.3/support/wcwidth.c | 236 + readline/readline-4.3/tcap.h | 60 + readline/readline-4.3/terminal.c | 662 ++ readline/readline-4.3/text.c | 1540 +++ readline/readline-4.3/tilde.c | 458 + readline/readline-4.3/tilde.h | 78 + readline/readline-4.3/undo.c | 263 + readline/readline-4.3/util.c | 338 + readline/readline-4.3/vi_keymap.c | 877 ++ readline/readline-4.3/vi_mode.c | 1488 +++ readline/readline-4.3/xmalloc.c | 88 + readline/readline-4.3/xmalloc.h | 46 + resis/Depend | 81 + resis/Makefile | 12 + resis/ResBasic.c | 386 + resis/ResChecks.c | 153 + resis/ResConDCS.c | 540 + resis/ResDebug.c | 147 + resis/ResFract.c | 477 + resis/ResJunct.c | 162 + resis/ResMain.c | 1000 ++ resis/ResMakeRes.c | 966 ++ resis/ResMerge.c | 1064 ++ resis/ResPrint.c | 730 ++ resis/ResReadSim.c | 866 ++ resis/ResRex.c | 1666 +++ resis/ResSimple.c | 1163 +++ resis/ResUtils.c | 725 ++ resis/ResWrite.c | 229 + resis/resis.h | 685 ++ router/Depend | 68 + router/Makefile | 37 + router/router.h | 193 + router/routerInt.h | 33 + router/rtrChannel.c | 599 ++ router/rtrCmd.c | 791 ++ router/rtrDcmpose.c | 1023 ++ router/rtrDcmpose.h | 74 + router/rtrFdback.c | 236 + router/rtrHazards.c | 597 ++ router/rtrMain.c | 280 + router/rtrPaint.c | 677 ++ router/rtrPin.c | 489 + router/rtrSide.c | 483 + router/rtrStem.c | 1314 +++ router/rtrTech.c | 445 + router/rtrTravers.c | 533 + router/rtrVia.c | 576 + router/tclroute.c | 95 + rules.mak | 60 + scmos/COPYRIGHT | 37 + scmos/Makefile | 103 + scmos/README | 123 + scmos/cif_template/COPYRIGHT | 37 + scmos/cif_template/Makefile | 67 + scmos/cif_template/README | 15 + scmos/cif_template/calc.lambda | 166 + scmos/cif_template/cifin-ami16.gen | 268 + scmos/cif_template/cifin-cmos14b.gen | 140 + scmos/cif_template/cifin-cmos26b.gen | 145 + scmos/cif_template/cifin-cmos26g.gen | 143 + scmos/cif_template/cifin-cmosn.gen | 89 + scmos/cif_template/cifin-cmosn.nw | 128 + scmos/cif_template/cifin-cmosx.gen | 135 + scmos/cif_template/cifin-hp-cif.nw | 62 + scmos/cif_template/cifin-hp.nw | 90 + scmos/cif_template/cifin-ibm.gen | 139 + scmos/cif_template/cifin.c | 142 + scmos/cif_template/cifin.cascade | 91 + scmos/cif_template/cifin.gen | 227 + scmos/cif_template/cifin.nw | 212 + scmos/cif_template/cifin.oldnw | 178 + scmos/cif_template/cifin.others | 575 + scmos/cif_template/cifin.pw | 142 + scmos/cif_template/cifin26g.c | 24 + scmos/cif_template/cifout-ami16.gen | 176 + scmos/cif_template/cifout-cmos14b-sub.gen | 135 + scmos/cif_template/cifout-cmos14b.gen | 135 + scmos/cif_template/cifout-cmos26b.gen | 158 + scmos/cif_template/cifout-cmos26g.gen | 137 + scmos/cif_template/cifout-cmos26g.soi | 133 + scmos/cif_template/cifout-cmos34.gen | 164 + scmos/cif_template/cifout-cmos34.nw | 146 + scmos/cif_template/cifout-cmos34.pw | 126 + scmos/cif_template/cifout-cmosn.gen | 97 + scmos/cif_template/cifout-cmosn.nw | 123 + scmos/cif_template/cifout-cmosx.gen | 131 + scmos/cif_template/cifout-ibm.gen | 135 + scmos/cif_template/cifout-orbit.gen | 176 + scmos/cif_template/cifout-orbit.nw | 146 + scmos/cif_template/cifout-orbit.pw | 126 + scmos/cif_template/cifout.c | 116 + scmos/cif_template/cifout.gen | 180 + scmos/cif_template/cifout.gen-old | 155 + scmos/cif_template/cifout.nw | 158 + scmos/cif_template/cifout.others | 70 + scmos/cif_template/cifout.pw | 138 + scmos/cif_template/cifout.scgnw | 124 + scmos/cif_template/cifout.scgpw | 94 + scmos/cif_template/cifout.test | 124 + scmos/cif_template/cifout26g.c | 14 + scmos/cif_template/scgcifout.c | 42 + scmos/doc/scmos-hpsub-rules | 85 + scmos/doc/scmos-rules-rev7.ps | 4236 ++++++++ scmos/examples/bipolar/README | 22 + scmos/examples/bipolar/guardring-npn.mag | 82 + scmos/examples/bipolar/large_npn.mag | 442 + scmos/examples/bipolar/min.mag | 33 + scmos/examples/bipolar/min2b.mag | 59 + scmos/examples/bipolar/min2e.mag | 61 + scmos/examples/bipolar/min_npn.mag | 73 + scmos/examples/bipolar/npn12_array_core.cif | 1041 ++ scmos/examples/bipolar/npn_array.mag | 1083 ++ scmos/examples/bipolar/npn_array16.cif | 8409 +++++++++++++++ scmos/examples/bipolar/npn_array20.cif | 397 + scmos/examples/bipolar/pbase-resis.mag | 146 + scmos/examples/bipolar/vertical-pnp.mag | 24 + scmos/examples/ccd/ccd.mag | 70 + scmos/examples/ccd/ccd_array.mag | 673 ++ scmos/examples/ccd/qq.cif | 659 ++ scmos/examples/float_gate/float_gate.mag | 61 + scmos/examples/linear_capacitor/wellcap.cif | 41 + scmos/examples/linear_capacitor/wellcap.mag | 18 + .../examples/nist-mems-library/gas-sensor.cif | 2372 +++++ .../examples/nist-mems-library/gas-sensor.mag | 1101 ++ scmos/examples/nist-mems-library/memslib.cif | 718 ++ scmos/examples/nist-mems-library/memslib.mag | 700 ++ .../nist-mems-library/micro-hot-plate.cif | 2088 ++++ .../nist-mems-library/micro-hot-plate.mag | 815 ++ .../nist-mems-library/nist_mems_lib.doc | 78 + .../examples/nist-mems-library/open-80x80.cif | 16 + .../examples/nist-mems-library/open-80x80.mag | 6 + .../nist-mems-library/open-oxide-80x80.cif | 571 + .../nist-mems-library/open-oxide-80x80.mag | 117 + .../nist-mems-library/pixel-160x160.cif | 1601 +++ .../nist-mems-library/pixel-160x160.mag | 452 + .../nist-mems-library/pixel-80x80.cif | 678 ++ .../nist-mems-library/pixel-80x80.mag | 241 + .../nist-mems-library/thermal-actuator.cif | 39 + .../nist-mems-library/thermal-actuator.mag | 25 + .../nist-mems-library/thermal-converter.cif | 487 + .../nist-mems-library/thermal-converter.mag | 578 + scmos/examples/palette.mag | 239 + scmos/examples/poly_capacitor/cap_array.mag | 180 + scmos/extract_template/scmosExt.tech.in | 97 + .../extract_template/scmosExt060_orb.tech.in | 111 + scmos/extract_template/scmosExt080.tech.in | 103 + scmos/extract_template/scmosExt100.tech.in | 236 + .../extract_template/scmosExt14b-sub.tech.in | 164 + scmos/extract_template/scmosExt14b-tm.tech.in | 163 + .../extract_template/scmosExt26b-sub.tech.in | 151 + scmos/extract_template/scmosExt26b.tech.in | 156 + scmos/extract_template/scmosExt34.tech.in | 119 + scmos/extract_template/scmosExtDiag.tech.in | 53 + scmos/gdsquery.tech.m4 | 59 + scmos/minimum.tech.m4 | 55 + scmos/mos.24bit.dstyle | 434 + scmos/mos.24bit.std.cmap | 73 + scmos/mos.7bit.dstyle | 474 + scmos/mos.7bit.mraster.cmap | 65 + scmos/mos.7bit.mraster_dstyle | 82 + scmos/mos.7bit.sgi.cmap | 63 + scmos/mos.7bit.std.cmap | 69 + scmos/mos.OpenGL.dstyle | 377 + scmos/mos.OpenGL.dstyle.mark | 365 + scmos/mos.OpenGL.std.cmap | 76 + scmos/rules/all-rules.mag | 488 + scmos/rules/rule1.mag | 12 + scmos/rules/rule10.mag | 11 + scmos/rules/rule11.mag | 28 + scmos/rules/rule12.mag | 59 + scmos/rules/rule14.mag | 42 + scmos/rules/rule15.mag | 18 + scmos/rules/rule16.mag | 82 + scmos/rules/rule17.mag | 29 + scmos/rules/rule18.mag | 28 + scmos/rules/rule19.mag | 61 + scmos/rules/rule2.mag | 24 + scmos/rules/rule3.mag | 52 + scmos/rules/rule4.mag | 44 + scmos/rules/rule4_2.mag | 132 + scmos/rules/rule5a.mag | 6 + scmos/rules/rule5b.mag | 28 + scmos/rules/rule6a.mag | 24 + scmos/rules/rule6b.mag | 23 + scmos/rules/rule7.mag | 20 + scmos/rules/rule8.mag | 42 + scmos/rules/rule9.mag | 16 + scmos/scmos.tech.in | 3256 ++++++ scmos/test.out | 3256 ++++++ scripts/config.guess | 1501 +++ scripts/config.log | 905 ++ scripts/config.status | 953 ++ scripts/config.sub | 1410 +++ scripts/configure | 9296 +++++++++++++++++ scripts/configure.in | 1777 ++++ scripts/configure.in.orig | 1758 ++++ scripts/defs.mak | 93 + scripts/defs.mak.in | 93 + scripts/install-sh | 251 + scripts/magic.spec.in | 66 + scripts/makedbh | 189 + scripts/missing | 283 + scripts/mkdirs | 32 + scripts/mkinstalldirs | 40 + scripts/printmans | 9 + select/Depend | 28 + select/Makefile | 11 + select/selCreate.c | 1390 +++ select/selDisplay.c | 443 + select/selEnum.c | 909 ++ select/selInt.h | 44 + select/selOps.c | 1786 ++++ select/selUndo.c | 451 + select/selUnselect.c | 414 + select/select.h | 68 + sim/Depend | 19 + sim/Makefile | 10 + sim/SimDBstuff.c | 1060 ++ sim/SimExtract.c | 819 ++ sim/SimRsim.c | 939 ++ sim/SimSelect.c | 824 ++ sim/SimSelect.c.new | 915 ++ sim/sim.h | 31 + tcltk/Depend | 6 + tcltk/Makefile | 93 + tcltk/bsitools.tcl | 34 + tcltk/cellmgr.tcl | 356 + tcltk/console.tcl | 135 + tcltk/drc.tcl | 46 + tcltk/ext2sim.sh | 23 + tcltk/ext2sim.sh.in | 23 + tcltk/ext2spice.sh | 23 + tcltk/ext2spice.sh.in | 23 + tcltk/magic.sh.in | 64 + tcltk/magic.tcl.in | 406 + tcltk/magicdnull.c | 52 + tcltk/magicexec.c | 79 + tcltk/magicps.pro | 70 + tcltk/mazeroute.tcl | 675 ++ tcltk/socketcmd.tcl | 27 + tcltk/strip_reflibs.tcl | 41 + tcltk/tclmagic.c | 1245 +++ tcltk/tclmagic.h | 34 + tcltk/techbuilder.tcl | 113 + tcltk/texthelper.tcl | 396 + tcltk/tkcon.tcl | 5330 ++++++++++ tcltk/tkshell.tcl | 202 + tcltk/toolkit.tcl | 838 ++ tcltk/toolkit_rev0.tcl | 284 + tcltk/tools.tcl | 696 ++ tcltk/wrapper.tcl | 1586 +++ textio/Depend | 22 + textio/Makefile | 10 + textio/textio.h | 108 + textio/textioInt.h | 57 + textio/txCommands.c | 1491 +++ textio/txInput.c | 1419 +++ textio/txMain.c | 171 + textio/txMore.c | 53 + textio/txOutput.c | 492 + textio/txcommands.h | 163 + tiles/Depend | 5 + tiles/Makefile | 10 + tiles/search.c | 63 + tiles/search2.c | 234 + tiles/tile.c | 828 ++ tiles/tile.h | 323 + utils/Depend | 73 + utils/LIBdbio.c | 58 + utils/LIBmain.c | 76 + utils/LIBtextio.c | 141 + utils/Makefile | 21 + utils/args.c | 75 + utils/child.c | 264 + utils/displays.proto | 2 + utils/dqueue.c | 260 + utils/dqueue.h | 55 + utils/finddisp.c | 123 + utils/flock.c | 170 + utils/flsbuf.c | 202 + utils/fraction.c | 97 + utils/geofast.h | 189 + utils/geometry.c | 1086 ++ utils/geometry.h | 214 + utils/getrect.c | 132 + utils/hash.c | 691 ++ utils/hash.h | 135 + utils/heap.c | 556 + utils/heap.h | 143 + utils/list.c | 182 + utils/list.h | 74 + utils/lookup.c | 224 + utils/lookupany.c | 59 + utils/lookupfull.c | 128 + utils/macros.c | 657 ++ utils/macros.h | 54 + utils/magic.h | 212 + utils/magsgtty.h | 34 + utils/main.c | 1236 +++ utils/main.h | 99 + utils/malloc.c | 162 + utils/malloc.h | 29 + utils/match.c | 136 + utils/maxrect.c | 340 + utils/maxrect.h | 51 + utils/netlist.c | 394 + utils/netlist.h | 126 + utils/niceabort.c | 211 + utils/parser.c | 170 + utils/parsetest.c | 37 + utils/path.c | 692 ++ utils/paths.h | 74 + utils/pathvisit.c | 299 + utils/pathvisit.h | 44 + utils/port.c | 54 + utils/printstuff.c | 24 + utils/runstats.c | 219 + utils/runstats.h | 31 + utils/set.c | 198 + utils/show.c | 91 + utils/signals.c | 693 ++ utils/signals.h | 59 + utils/stack.c | 289 + utils/stack.h | 83 + utils/strdup.c | 166 + utils/styles.h | 202 + utils/tech.c | 992 ++ utils/tech.h | 58 + utils/touchingtypes.h | 27 + utils/touchtypes.c | 203 + utils/undo.c | 973 ++ utils/undo.h | 93 + utils/utils.h | 90 + windows/Depend | 54 + windows/Makefile | 27 + windows/vfont.B.12 | Bin 0 -> 9038 bytes windows/vfont.I.12 | Bin 0 -> 9231 bytes windows/vfont.R.8 | Bin 0 -> 5538 bytes windows/windClient.c | 828 ++ windows/windCmdAM.c | 1234 +++ windows/windCmdNR.c | 442 + windows/windCmdSZ.c | 1243 +++ windows/windDebug.c | 179 + windows/windDisp.c | 984 ++ windows/windInt.h | 86 + windows/windMain.c | 574 + windows/windMove.c | 855 ++ windows/windSearch.c | 203 + windows/windSend.c | 434 + windows/windTrans.c | 374 + windows/windView.c | 505 + windows/windows.h | 330 + windows/windows11.glyphs | 74 + windows/windows14.glyphs | 89 + windows/windows22.glyphs | 128 + windows/windows7.glyphs | 54 + wiring/Depend | 13 + wiring/Makefile | 10 + wiring/wireInt.h | 39 + wiring/wireOps.c | 916 ++ wiring/wireTech.c | 205 + wiring/wireTech.c.new | 204 + wiring/wireUndo.c | 162 + wiring/wiring.h | 94 + 1249 files changed, 520134 insertions(+) create mode 100644 .gitignore create mode 100644 INSTALL create mode 100644 Makefile create mode 100644 README create mode 100644 README.Tcl create mode 100644 TODO create mode 100644 VERSION create mode 100644 calma/CalmaRdcl.c create mode 100644 calma/CalmaRdio.c create mode 100644 calma/CalmaRdpt.c create mode 100644 calma/CalmaRead.c create mode 100644 calma/CalmaWrite.c create mode 100644 calma/Depend create mode 100644 calma/Makefile create mode 100644 calma/calma.h create mode 100644 calma/calmaInt.h create mode 100644 cif/CIFgen.c create mode 100644 cif/CIFhier.c create mode 100644 cif/CIFint.h create mode 100644 cif/CIFmain.c create mode 100644 cif/CIFrdcl.c create mode 100644 cif/CIFrdpoly.c create mode 100644 cif/CIFrdpt.c create mode 100644 cif/CIFrdtech.c create mode 100644 cif/CIFrdutils.c create mode 100644 cif/CIFread.h create mode 100644 cif/CIFsee.c create mode 100644 cif/CIFtech.c create mode 100644 cif/CIFwrite.c create mode 100644 cif/Depend create mode 100644 cif/Makefile create mode 100644 cif/cif.h create mode 100644 cmwind/CMWcmmnds.c create mode 100644 cmwind/CMWmain.c create mode 100644 cmwind/CMWrgbhsv.c create mode 100644 cmwind/CMWundo.c create mode 100644 cmwind/Depend create mode 100644 cmwind/Makefile create mode 100644 cmwind/cmwind.h create mode 100644 commands/CmdAB.c create mode 100644 commands/CmdAuto.c create mode 100644 commands/CmdCD.c create mode 100644 commands/CmdE.c create mode 100644 commands/CmdFI.c create mode 100644 commands/CmdLQ.c create mode 100644 commands/CmdRS.c create mode 100644 commands/CmdSubrs.c create mode 100644 commands/CmdTZ.c create mode 100644 commands/CmdWizard.c create mode 100644 commands/Depend create mode 100644 commands/Makefile create mode 100644 commands/commands.h create mode 100755 configure create mode 100644 database/DBbound.c create mode 100644 database/DBcell.c create mode 100644 database/DBcellbox.c create mode 100644 database/DBcellcopy.c create mode 100644 database/DBcellname.c create mode 100644 database/DBcellsel.c create mode 100644 database/DBcellsrch.c create mode 100644 database/DBcellsubr.c create mode 100644 database/DBconnect.c create mode 100644 database/DBcount.c create mode 100644 database/DBexpand.c create mode 100644 database/DBio.c create mode 100644 database/DBlabel.c create mode 100644 database/DBlabel2.c create mode 100644 database/DBpaint.c create mode 100644 database/DBpaint2.c create mode 100644 database/DBprop.c create mode 100644 database/DBtcontact.c create mode 100644 database/DBtech.c create mode 100644 database/DBtechname.c create mode 100644 database/DBtechtype.c create mode 100644 database/DBtiles.c create mode 100644 database/DBtimestmp.c create mode 100644 database/DBtpaint.c create mode 100644 database/DBtpaint2.c create mode 100644 database/DBundo.c create mode 100644 database/Depend create mode 100644 database/Makefile create mode 100644 database/database.h.in create mode 100644 database/databaseInt.h create mode 100644 database/fonts.h create mode 100644 dbwind/DBWbuttons.c create mode 100644 dbwind/DBWcommands.c create mode 100644 dbwind/DBWdisplay.c create mode 100644 dbwind/DBWelement.c create mode 100644 dbwind/DBWfdback.c create mode 100644 dbwind/DBWhlights.c create mode 100644 dbwind/DBWprocs.c create mode 100644 dbwind/DBWtools.c create mode 100644 dbwind/DBWundo.c create mode 100644 dbwind/Depend create mode 100644 dbwind/Makefile create mode 100644 dbwind/dbwind.h create mode 100644 dbwind/dbwtech.h create mode 100644 debug/Depend create mode 100644 debug/Makefile create mode 100644 debug/debug.h create mode 100644 debug/debugFlags.c create mode 100644 debug/hist.c create mode 100644 defs.mak create mode 100644 doc/Makefile create mode 100644 doc/html/Makefile create mode 100644 doc/html/addcommandentry.html create mode 100644 doc/html/addpath.html create mode 100644 doc/html/array.html create mode 100644 doc/html/box.html create mode 100644 doc/html/calma.html create mode 100644 doc/html/caption.html create mode 100644 doc/html/cellmanager.html create mode 100644 doc/html/cellname.html create mode 100644 doc/html/cellsearch.html create mode 100644 doc/html/center.html create mode 100644 doc/html/changetool.html create mode 100644 doc/html/channels.html create mode 100644 doc/html/cif.html create mode 100644 doc/html/clockwise.html create mode 100644 doc/html/closewindow.html create mode 100644 doc/html/closewrapper.html create mode 100644 doc/html/color/color.html create mode 100644 doc/html/color/load.html create mode 100644 doc/html/color/pushbutton.html create mode 100644 doc/html/color/save.html create mode 100644 doc/html/commands.html create mode 100644 doc/html/commands.list create mode 100644 doc/html/contact.html create mode 100644 doc/html/copy.html create mode 100644 doc/html/corner.html create mode 100644 doc/html/crash.html create mode 100644 doc/html/crashbackups.html create mode 100644 doc/html/crosshair.html create mode 100644 doc/html/cursor.html create mode 100644 doc/html/def.html create mode 100644 doc/html/delete.html create mode 100644 doc/html/deletecommandentry.html create mode 100644 doc/html/direction.html create mode 100644 doc/html/distance.html create mode 100644 doc/html/down.html create mode 100644 doc/html/drc.html create mode 100644 doc/html/dump.html create mode 100644 doc/html/edit.html create mode 100644 doc/html/element.html create mode 100644 doc/html/erase.html create mode 100644 doc/html/expand.html create mode 100644 doc/html/ext.html create mode 100644 doc/html/ext2sim.html create mode 100644 doc/html/ext2spice.html create mode 100644 doc/html/extract.html create mode 100644 doc/html/extresist.html create mode 100644 doc/html/exttosim.html create mode 100644 doc/html/exttospice.html create mode 100644 doc/html/feedback.html create mode 100644 doc/html/fill.html create mode 100644 doc/html/findbox.html create mode 100644 doc/html/findlabel.html create mode 100644 doc/html/flatten.html create mode 100644 doc/html/flush.html create mode 100644 doc/html/garoute.html create mode 100644 doc/html/gds.html create mode 100644 doc/html/get.html create mode 100644 doc/html/getcell.html create mode 100644 doc/html/getnode.html create mode 100644 doc/html/goto.html create mode 100644 doc/html/graphics/blpaper.gif create mode 100644 doc/html/graphics/cellmgr.gif create mode 100644 doc/html/graphics/cif_see.gif create mode 100644 doc/html/graphics/corner1.gif create mode 100644 doc/html/graphics/corner2.gif create mode 100644 doc/html/graphics/email_address.png create mode 100644 doc/html/graphics/line1.gif create mode 100644 doc/html/graphics/magic_OGL_sm.gif create mode 100644 doc/html/graphics/magic_title2.gif create mode 100644 doc/html/graphics/techmgr.gif create mode 100644 doc/html/graphics/toolbar.gif create mode 100644 doc/html/graphics/writeall.gif create mode 100644 doc/html/grid.html create mode 100644 doc/html/help.html create mode 100644 doc/html/identify.html create mode 100644 doc/html/imacro.html create mode 100644 doc/html/initialize.html create mode 100644 doc/html/instance.html create mode 100644 doc/html/invoke.html create mode 100644 doc/html/iroute.html create mode 100644 doc/html/irsim.html create mode 100644 doc/html/label.html create mode 100644 doc/html/lef.html create mode 100644 doc/html/load.html create mode 100644 doc/html/logcommands.html create mode 100644 doc/html/macro.html create mode 100644 doc/html/maketoolbar.html create mode 100644 doc/html/measure.html create mode 100644 doc/html/move.html create mode 100644 doc/html/netlist.html create mode 100644 doc/html/netlist/add.html create mode 100644 doc/html/netlist/cleanup.html create mode 100644 doc/html/netlist/cull.html create mode 100644 doc/html/netlist/dnet.html create mode 100644 doc/html/netlist/dterm.html create mode 100644 doc/html/netlist/extract.html create mode 100644 doc/html/netlist/find.html create mode 100644 doc/html/netlist/flush.html create mode 100644 doc/html/netlist/joinnets.html create mode 100644 doc/html/netlist/netlist.html create mode 100644 doc/html/netlist/print.html create mode 100644 doc/html/netlist/pushbutton.html create mode 100644 doc/html/netlist/ripup.html create mode 100644 doc/html/netlist/savenetlist.html create mode 100644 doc/html/netlist/shownet.html create mode 100644 doc/html/netlist/showterms.html create mode 100644 doc/html/netlist/trace.html create mode 100644 doc/html/netlist/verify.html create mode 100644 doc/html/netlist/writeall.html create mode 100644 doc/html/openwindow.html create mode 100644 doc/html/openwrapper.html create mode 100644 doc/html/paint.html create mode 100644 doc/html/path.html create mode 100644 doc/html/peekbox.html create mode 100644 doc/html/plot.html create mode 100644 doc/html/plow.html create mode 100644 doc/html/polygon.html create mode 100644 doc/html/popbox.html create mode 100644 doc/html/popstack.html create mode 100644 doc/html/port.html create mode 100644 doc/html/promptload.html create mode 100644 doc/html/promptsave.html create mode 100644 doc/html/property.html create mode 100644 doc/html/pushbox.html create mode 100644 doc/html/pushbutton.html create mode 100644 doc/html/pushstack.html create mode 100644 doc/html/quit.html create mode 100644 doc/html/redo.html create mode 100644 doc/html/redraw.html create mode 100644 doc/html/render3d.html create mode 100644 doc/html/resumeall.html create mode 100644 doc/html/rotate.html create mode 100644 doc/html/route.html create mode 100644 doc/html/ruler.html create mode 100644 doc/html/save.html create mode 100644 doc/html/scalegrid.html create mode 100644 doc/html/scroll.html create mode 100644 doc/html/search.html create mode 100644 doc/html/see.html create mode 100644 doc/html/select.html create mode 100644 doc/html/setpoint.html create mode 100644 doc/html/shell.html create mode 100644 doc/html/sideways.html create mode 100644 doc/html/sleep.html create mode 100644 doc/html/snap.html create mode 100644 doc/html/specialopen.html create mode 100644 doc/html/spliterase.html create mode 100644 doc/html/splitpaint.html create mode 100644 doc/html/startup.html create mode 100644 doc/html/straighten.html create mode 100644 doc/html/stretch.html create mode 100644 doc/html/suspendall.html create mode 100644 doc/html/tag.html create mode 100644 doc/html/tech.html create mode 100644 doc/html/techmanager.html create mode 100644 doc/html/template.html create mode 100644 doc/html/tk_path_name.html create mode 100644 doc/html/tool.html create mode 100644 doc/html/undo.html create mode 100644 doc/html/unexpand.html create mode 100644 doc/html/unmeasure.html create mode 100644 doc/html/updatedisplay.html create mode 100644 doc/html/upsidedown.html create mode 100644 doc/html/version.html create mode 100644 doc/html/view.html create mode 100644 doc/html/what.html create mode 100644 doc/html/wind3d/cif.html create mode 100644 doc/html/wind3d/closewindow.html create mode 100644 doc/html/wind3d/cutbox.html create mode 100644 doc/html/wind3d/defaults.html create mode 100644 doc/html/wind3d/help.html create mode 100644 doc/html/wind3d/level.html create mode 100644 doc/html/wind3d/refresh.html create mode 100644 doc/html/wind3d/render.html create mode 100644 doc/html/wind3d/scroll.html create mode 100644 doc/html/wind3d/see.html create mode 100644 doc/html/wind3d/view.html create mode 100644 doc/html/wind3d/zoom.html create mode 100644 doc/html/windowborder.html create mode 100644 doc/html/windowcaption.html create mode 100644 doc/html/windownames.html create mode 100644 doc/html/windowscrollbars.html create mode 100644 doc/html/wire.html create mode 100644 doc/html/wizard/coord.html create mode 100644 doc/html/wizard/crash.html create mode 100644 doc/html/wizard/extract.html create mode 100644 doc/html/wizard/files.html create mode 100644 doc/html/wizard/grstats.html create mode 100644 doc/html/wizard/pause.html create mode 100644 doc/html/wizard/plow.html create mode 100644 doc/html/wizard/psearch.html create mode 100644 doc/html/wizard/showtech.html create mode 100644 doc/html/wizard/tilestats.html create mode 100644 doc/html/wizard/tsearch.html create mode 100644 doc/html/wizard/watch.html create mode 100644 doc/html/wizard/winddebug.html create mode 100644 doc/html/wizard/winddump.html create mode 100644 doc/html/writeall.html create mode 100644 doc/html/xload.html create mode 100644 doc/html/xview.html create mode 100644 doc/html/zoom.html create mode 100644 doc/latexfiles/Makefile create mode 100644 doc/latexfiles/addendum6_5.tex create mode 100644 doc/latexfiles/copyright.tex create mode 100644 doc/latexfiles/introduction.tex create mode 100644 doc/latexfiles/maint1.tex create mode 100644 doc/latexfiles/maint2.tex create mode 100644 doc/latexfiles/maint3.tex create mode 100644 doc/latexfiles/maint4.tex create mode 100644 doc/latexfiles/manual.tex create mode 100644 doc/latexfiles/tut1.tex create mode 100644 doc/latexfiles/tut10.tex create mode 100644 doc/latexfiles/tut11.tex create mode 100644 doc/latexfiles/tut2.tex create mode 100644 doc/latexfiles/tut3.tex create mode 100644 doc/latexfiles/tut4.tex create mode 100644 doc/latexfiles/tut5.tex create mode 100644 doc/latexfiles/tut6.tex create mode 100644 doc/latexfiles/tut7.tex create mode 100644 doc/latexfiles/tut8.tex create mode 100644 doc/latexfiles/tut9.tex create mode 100644 doc/latexfiles/tutscm1.tex create mode 100644 doc/latexfiles/tutscm2.tex create mode 100644 doc/latexfiles/tutscm3.tex create mode 100644 doc/latexfiles/tutscm4.tex create mode 100644 doc/latexfiles/tuttcl1.tex create mode 100644 doc/latexfiles/tuttcl2.tex create mode 100644 doc/latexfiles/tuttcl3.tex create mode 100644 doc/latexfiles/tuttcl4.tex create mode 100644 doc/latexfiles/tuttcl5.tex create mode 100644 doc/latexfiles/tutwrl1.tex create mode 100644 doc/man/Makefile create mode 100644 doc/man/cmap.5 create mode 100644 doc/man/displays.5 create mode 100644 doc/man/dlys.5 create mode 100644 doc/man/dstyle.5 create mode 100644 doc/man/ext.5 create mode 100644 doc/man/ext2sim.1 create mode 100644 doc/man/ext2spice.1 create mode 100644 doc/man/extcheck.1 create mode 100644 doc/man/glyphs.5 create mode 100644 doc/man/mag.5 create mode 100644 doc/man/magic.1 create mode 100644 doc/man/net.5 create mode 100644 doc/man/sim.5 create mode 100644 doc/man/tmac.anc create mode 100644 doc/psfigures/maint2.1.ps create mode 100644 doc/psfigures/maint2.11.ps create mode 100644 doc/psfigures/maint2.2.ps create mode 100644 doc/psfigures/maint2.3.ps create mode 100644 doc/psfigures/maint2.3b.ps create mode 100644 doc/psfigures/maint2.4.ps create mode 100644 doc/psfigures/maint2.5.ps create mode 100644 doc/psfigures/maint2.6.ps create mode 100644 doc/psfigures/maint2.6b.ps create mode 100644 doc/psfigures/maint2.7.ps create mode 100644 doc/psfigures/maint2.8.ps create mode 100644 doc/psfigures/maint2.9.ps create mode 100644 doc/psfigures/tut2.1.ps create mode 100644 doc/psfigures/tut2.2.ps create mode 100644 doc/psfigures/tut7.1.ps create mode 100644 doc/psfigures/tut7.2.ps create mode 100644 doc/psfigures/tut7.3.ps create mode 100644 doc/psfigures/tut8.1.ps create mode 100644 doc/psfigures/tut8.2.ps create mode 100644 doc/psfigures/tut8.3.ps create mode 100644 doc/psfigures/tut8.4.ps create mode 100644 doc/psfigures/tut8.5.ps create mode 100644 doc/psfigures/tut9.1.ps create mode 100644 doc/psfigures/tutcell.cif create mode 100644 doc/psfigures/tutcell1.mag create mode 100644 doc/psfigures/tutw1.1.ps create mode 100644 doc/psfigures/tutw1.2.ps create mode 100644 doc/psfiles/addendum6_5.ps create mode 100644 doc/psfiles/copyright.ps create mode 100644 doc/psfiles/introduction.ps create mode 100644 doc/psfiles/maint1.ps create mode 100644 doc/psfiles/maint2.ps create mode 100644 doc/psfiles/maint3.ps create mode 100644 doc/psfiles/maint4.ps create mode 100644 doc/psfiles/tut1.ps create mode 100644 doc/psfiles/tut10.ps create mode 100644 doc/psfiles/tut11.ps create mode 100644 doc/psfiles/tut2.ps create mode 100644 doc/psfiles/tut3.ps create mode 100644 doc/psfiles/tut4.ps create mode 100644 doc/psfiles/tut5.ps create mode 100644 doc/psfiles/tut6.ps create mode 100644 doc/psfiles/tut7.ps create mode 100644 doc/psfiles/tut8.ps create mode 100644 doc/psfiles/tut9.ps create mode 100644 doc/psfiles/tutscm1.ps create mode 100644 doc/psfiles/tutscm2.ps create mode 100644 doc/psfiles/tutscm3.ps create mode 100644 doc/psfiles/tutscm4.ps create mode 100644 doc/psfiles/tuttcl1.ps create mode 100644 doc/psfiles/tuttcl2.ps create mode 100644 doc/psfiles/tuttcl3.ps create mode 100644 doc/psfiles/tuttcl4.ps create mode 100644 doc/psfiles/tuttcl5.ps create mode 100644 doc/psfiles/tutwrl1.ps create mode 100644 doc/textfiles/LEF.txt create mode 100644 doc/textfiles/default_macros.txt create mode 100644 doc/textfiles/hires-color.txt create mode 100644 doc/textfiles/locking.txt create mode 100644 doc/textfiles/macro_extension.txt create mode 100644 doc/textfiles/non-manhattan.txt create mode 100644 doc/textfiles/open_gl.txt create mode 100644 doc/textfiles/readline.txt create mode 100644 doc/tutcells/Makefile create mode 100644 doc/tutcells/m3a.mag create mode 100644 doc/tutcells/maint2a.mag create mode 100644 doc/tutcells/tut1.mag create mode 100644 doc/tutcells/tut11a.al create mode 100644 doc/tutcells/tut11a.cmd create mode 100644 doc/tutcells/tut11a.ext create mode 100644 doc/tutcells/tut11a.mag create mode 100644 doc/tutcells/tut11a.nodes create mode 100644 doc/tutcells/tut11a.sim create mode 100644 doc/tutcells/tut11b.ext create mode 100644 doc/tutcells/tut11b.mag create mode 100644 doc/tutcells/tut11c.ext create mode 100644 doc/tutcells/tut11c.mag create mode 100644 doc/tutcells/tut11d.ext create mode 100644 doc/tutcells/tut11d.mag create mode 100644 doc/tutcells/tut2.f1a.cif create mode 100644 doc/tutcells/tut2.f1b.cif create mode 100644 doc/tutcells/tut2a.mag create mode 100644 doc/tutcells/tut2b.mag create mode 100644 doc/tutcells/tut2c.mag create mode 100644 doc/tutcells/tut2d.mag create mode 100644 doc/tutcells/tut3a.mag create mode 100644 doc/tutcells/tut3b.mag create mode 100644 doc/tutcells/tut3c.mag create mode 100644 doc/tutcells/tut3d.mag create mode 100644 doc/tutcells/tut3e.mag create mode 100644 doc/tutcells/tut3f.mag create mode 100644 doc/tutcells/tut3g.mag create mode 100644 doc/tutcells/tut3h.mag create mode 100644 doc/tutcells/tut4a.mag create mode 100644 doc/tutcells/tut4x.mag create mode 100644 doc/tutcells/tut4y.mag create mode 100644 doc/tutcells/tut4z.mag create mode 100644 doc/tutcells/tut5a.mag create mode 100644 doc/tutcells/tut5b.mag create mode 100644 doc/tutcells/tut6a.mag create mode 100644 doc/tutcells/tut6b.mag create mode 100644 doc/tutcells/tut6c.mag create mode 100644 doc/tutcells/tut6x.mag create mode 100644 doc/tutcells/tut6y.mag create mode 100644 doc/tutcells/tut7a.mag create mode 100644 doc/tutcells/tut7b.mag create mode 100644 doc/tutcells/tut7b.net create mode 100644 doc/tutcells/tut7c.mag create mode 100644 doc/tutcells/tut7d.mag create mode 100644 doc/tutcells/tut7d.net create mode 100644 doc/tutcells/tut8a.mag create mode 100644 doc/tutcells/tut8b.mag create mode 100644 doc/tutcells/tut8c.mag create mode 100644 doc/tutcells/tut8d.mag create mode 100644 doc/tutcells/tut8e.mag create mode 100644 doc/tutcells/tut8f.mag create mode 100644 doc/tutcells/tut8g.mag create mode 100644 doc/tutcells/tut8h.mag create mode 100644 doc/tutcells/tut8i.mag create mode 100644 doc/tutcells/tut8j.mag create mode 100644 doc/tutcells/tut8k.mag create mode 100644 doc/tutcells/tut8l.mag create mode 100644 doc/tutcells/tut8m.mag create mode 100644 doc/tutcells/tut8n.mag create mode 100644 doc/tutcells/tut8r.mag create mode 100644 doc/tutcells/tut9a.mag create mode 100644 doc/tutcells/tut9b.mag create mode 100644 doc/tutcells/tut9x.mag create mode 100644 doc/tutcells/tut9y.mag create mode 100644 doc/tutcells/tuttcl1.cmd create mode 100644 drc/DRCarray.c create mode 100644 drc/DRCbasic.c create mode 100644 drc/DRCcif.c create mode 100644 drc/DRCcontin.c create mode 100644 drc/DRCextend.c create mode 100644 drc/DRCmain.c create mode 100644 drc/DRCprint.c create mode 100644 drc/DRCsubcell.c create mode 100644 drc/DRCtech.c create mode 100644 drc/Depend create mode 100644 drc/Makefile create mode 100644 drc/drc.h create mode 100644 ext2sim/Depend create mode 100644 ext2sim/Makefile create mode 100644 ext2sim/ext2sim.c create mode 100644 ext2sim/finds.c create mode 100644 ext2sim/sim2simp.c create mode 100755 ext2sim/sim2spi create mode 100644 ext2spice/Depend create mode 100644 ext2spice/Makefile create mode 100644 ext2spice/ext2hier.c create mode 100644 ext2spice/ext2spice.c create mode 100644 ext2spice/ext2spice.h create mode 100755 ext2spice/spice2sim create mode 100644 extcheck/Depend create mode 100644 extcheck/Makefile create mode 100644 extcheck/extcheck.c create mode 100644 extflat/COMPRESS create mode 100644 extflat/Depend create mode 100644 extflat/EFargs.c create mode 100644 extflat/EFbuild.c create mode 100644 extflat/EFdef.c create mode 100644 extflat/EFerr.c create mode 100644 extflat/EFflat.c create mode 100644 extflat/EFhier.c create mode 100644 extflat/EFint.h create mode 100644 extflat/EFname.c create mode 100644 extflat/EFread.c create mode 100644 extflat/EFsym.c create mode 100644 extflat/EFvisit.c create mode 100644 extflat/Makefile create mode 100644 extflat/READ_ME create mode 100644 extflat/extflat.h create mode 100644 extract/Depend create mode 100644 extract/ExtArray.c create mode 100644 extract/ExtBasic.c create mode 100644 extract/ExtCell.c create mode 100644 extract/ExtCouple.c create mode 100644 extract/ExtHard.c create mode 100644 extract/ExtHier.c create mode 100644 extract/ExtInter.c create mode 100644 extract/ExtLength.c create mode 100644 extract/ExtMain.c create mode 100644 extract/ExtNghbors.c create mode 100644 extract/ExtPerim.c create mode 100644 extract/ExtRegion.c create mode 100644 extract/ExtSubtree.c create mode 100644 extract/ExtTech.c create mode 100644 extract/ExtTest.c create mode 100644 extract/ExtTimes.c create mode 100644 extract/ExtUnique.c create mode 100644 extract/ExtYank.c create mode 100644 extract/Makefile create mode 100644 extract/extDebugInt.h create mode 100644 extract/extract.h create mode 100644 extract/extractInt.h create mode 100644 extract/extractInt.h.new create mode 100644 garouter/Depend create mode 100644 garouter/Makefile create mode 100644 garouter/OUTLINE create mode 100644 garouter/TODO create mode 100644 garouter/gaChannel.c create mode 100644 garouter/gaDebug.h create mode 100644 garouter/gaInternal.h create mode 100644 garouter/gaMain.c create mode 100644 garouter/gaMaze.c create mode 100644 garouter/gaSimple.c create mode 100644 garouter/gaStem.c create mode 100644 garouter/gaTest.c create mode 100644 garouter/garouter.h create mode 100644 gcr/Depend create mode 100644 gcr/Makefile create mode 100644 gcr/gcr.h create mode 100644 gcr/gcrChannel.c create mode 100644 gcr/gcrColl.c create mode 100644 gcr/gcrDebug.c create mode 100644 gcr/gcrEdge.c create mode 100644 gcr/gcrFeas.c create mode 100644 gcr/gcrFlags.c create mode 100644 gcr/gcrInit.c create mode 100644 gcr/gcrLib.c create mode 100644 gcr/gcrRiver.c create mode 100644 gcr/gcrRoute.c create mode 100644 gcr/gcrShwFlgs.c create mode 100644 gcr/gcrUnsplit.c create mode 100644 graphics/DEFAULT.glyphs create mode 100644 graphics/Depend create mode 100644 graphics/FreeMono.pt3 create mode 100644 graphics/FreeSans.pt3 create mode 100644 graphics/FreeSerif.pt3 create mode 100644 graphics/Makefile create mode 100644 graphics/README.X10a create mode 100644 graphics/READ_ME create mode 100644 graphics/W3Dmain.c create mode 100644 graphics/X11Helper.c create mode 100644 graphics/bw.glyphs create mode 100644 graphics/color.glyphs create mode 100644 graphics/glyphs.h create mode 100644 graphics/grCMap.c create mode 100644 graphics/grClip.c create mode 100644 graphics/grDStyle.c create mode 100644 graphics/grGlyphs.c create mode 100644 graphics/grLock.c create mode 100644 graphics/grMain.c create mode 100644 graphics/grNull.c create mode 100644 graphics/grOGL1.c create mode 100644 graphics/grOGL2.c create mode 100644 graphics/grOGL3.c create mode 100644 graphics/grOGL4.c create mode 100644 graphics/grOGL5.c create mode 100644 graphics/grOGLInt.h create mode 100644 graphics/grTOGL1.c create mode 100644 graphics/grTOGL2.c create mode 100644 graphics/grTOGL3.c create mode 100644 graphics/grTOGL3.c.test create mode 100644 graphics/grTOGL4.c create mode 100644 graphics/grTOGL5.c create mode 100644 graphics/grTOGLInt.h create mode 100644 graphics/grText.c create mode 100644 graphics/grTk1.c create mode 100644 graphics/grTk2.c create mode 100644 graphics/grTk3.c create mode 100644 graphics/grTk4.c create mode 100644 graphics/grTk5.c create mode 100644 graphics/grTkCommon.c create mode 100644 graphics/grTkCommon.h create mode 100644 graphics/grTkInt.h create mode 100644 graphics/grX11Int.h create mode 100644 graphics/grX11su1.c create mode 100644 graphics/grX11su2.c create mode 100644 graphics/grX11su3.c create mode 100644 graphics/grX11su4.c create mode 100644 graphics/grX11su5.c create mode 100644 graphics/grX11thread.c create mode 100644 graphics/graphics.h create mode 100644 graphics/graphicsInt.h create mode 100644 graphics/prcolors.c create mode 100644 graphics/wind3d.h create mode 100644 grouter/Depend create mode 100644 grouter/Makefile create mode 100644 grouter/TODO create mode 100644 grouter/grouteChan.c create mode 100644 grouter/grouteCrss.c create mode 100644 grouter/grouteDebug.h create mode 100644 grouter/grouteDens.c create mode 100644 grouter/grouteMain.c create mode 100644 grouter/grouteMaze.c create mode 100644 grouter/grouteMult.c create mode 100644 grouter/grouteName.c create mode 100644 grouter/grouteNet.c create mode 100644 grouter/groutePath.c create mode 100644 grouter/groutePen.c create mode 100644 grouter/groutePin.c create mode 100644 grouter/grouteTest.c create mode 100644 grouter/grouteTile.c create mode 100644 grouter/grouter.h create mode 100644 irouter/Depend create mode 100644 irouter/Makefile create mode 100644 irouter/irCommand.c create mode 100644 irouter/irDebug.h create mode 100644 irouter/irInternal.h create mode 100644 irouter/irMain.c create mode 100644 irouter/irRoute.c create mode 100644 irouter/irTestCmd.c create mode 100644 irouter/irUtils.c create mode 100644 irouter/irouter.h create mode 100644 lef/Depend create mode 100644 lef/Makefile create mode 100644 lef/defRead.c create mode 100644 lef/defWrite.c create mode 100644 lef/lef.h create mode 100644 lef/lefCmd.c create mode 100644 lef/lefInt.h create mode 100644 lef/lefRead.c create mode 100644 lef/lefTech.c create mode 100644 lef/lefWrite.c create mode 100644 lef/tcllef.c create mode 100644 lisp/Depend create mode 100644 lisp/Makefile create mode 100644 lisp/README create mode 100644 lisp/lisp.h create mode 100644 lisp/lispA-Z.c create mode 100644 lisp/lispA-Z.h create mode 100644 lisp/lispArith.c create mode 100644 lisp/lispEval.c create mode 100644 lisp/lispFrame.c create mode 100644 lisp/lispGC.c create mode 100644 lisp/lispIO.c create mode 100644 lisp/lispInt.h create mode 100644 lisp/lispMagic.c create mode 100644 lisp/lispMain.c create mode 100644 lisp/lispParse.c create mode 100644 lisp/lispPrint.c create mode 100644 lisp/lispString.c create mode 100644 lisp/lispTrace.c create mode 100644 lisp/lispargs.h create mode 100644 lisp/scm/box.scm create mode 100644 lisp/scm/default.scm create mode 100644 lisp/scm/draw.scm create mode 100644 lisp/scm/drc.scm create mode 100644 lisp/scm/gate.scm create mode 100644 lisp/scm/help.scm create mode 100644 lisp/scm/label.scm create mode 100644 lisp/scm/layout.scm create mode 100644 lisp/scm/prs.scm create mode 100644 lisp/scm/sel.scm create mode 100644 lisp/scm/stack.scm create mode 100644 magic/Depend create mode 100644 magic/Makefile create mode 100644 magic/bitmaps/down.xbm create mode 100644 magic/bitmaps/left.xbm create mode 100644 magic/bitmaps/lock.xbm create mode 100644 magic/bitmaps/right.xbm create mode 100644 magic/bitmaps/up.xbm create mode 100644 magic/bitmaps/zoom.xbm create mode 100644 magic/magicTop.c create mode 100644 magic/magicps.pro create mode 100644 magic/proto.initrc create mode 100644 magic/proto.magicrc.m4 create mode 100644 magic/symbol.map create mode 100644 mzrouter/Depend create mode 100644 mzrouter/Makefile create mode 100644 mzrouter/mzBlock.c create mode 100644 mzrouter/mzDebug.c create mode 100644 mzrouter/mzDebug.h create mode 100644 mzrouter/mzEstimate.c create mode 100644 mzrouter/mzHint.c create mode 100644 mzrouter/mzInit.c create mode 100644 mzrouter/mzInternal.h create mode 100644 mzrouter/mzMain.c create mode 100644 mzrouter/mzNumLine.c create mode 100644 mzrouter/mzSearch.c create mode 100644 mzrouter/mzStart.c create mode 100644 mzrouter/mzSubrs.c create mode 100644 mzrouter/mzTech.c create mode 100644 mzrouter/mzTestCmd.c create mode 100644 mzrouter/mzWalk.c create mode 100644 mzrouter/mzXtndDown.c create mode 100644 mzrouter/mzXtndLeft.c create mode 100644 mzrouter/mzXtndRght.c create mode 100644 mzrouter/mzXtndUp.c create mode 100644 mzrouter/mzrouter.h create mode 100644 net2ir/Depend create mode 100644 net2ir/Makefile create mode 100644 net2ir/net2ir.c create mode 100644 netmenu/Depend create mode 100644 netmenu/Makefile create mode 100644 netmenu/NMbutton.c create mode 100644 netmenu/NMcmdAK.c create mode 100644 netmenu/NMcmdLZ.c create mode 100644 netmenu/NMlabel.c create mode 100644 netmenu/NMmain.c create mode 100644 netmenu/NMnetlist.c create mode 100644 netmenu/NMshowcell.c create mode 100644 netmenu/NMshowpt.c create mode 100644 netmenu/NMundo.c create mode 100644 netmenu/NMwiring.c create mode 100644 netmenu/netmenu.h create mode 100644 netmenu/nmInt.h create mode 100644 oa/.deps/magicInit.P create mode 100644 oa/.deps/magicOA.P create mode 100644 oa/Makefile create mode 100644 oa/magicInit.cpp create mode 100644 oa/magicInit.h create mode 100644 oa/magicOA.cpp create mode 100644 oa/magicOA.h create mode 100644 oa/oa.c create mode 100644 oa/oa.h create mode 100644 plot/Depend create mode 100644 plot/Makefile create mode 100644 plot/plot.h create mode 100644 plot/plotCmd.c create mode 100644 plot/plotGremln.c create mode 100644 plot/plotHP.c create mode 100644 plot/plotInt.h create mode 100644 plot/plotMain.c create mode 100644 plot/plotPNM.c create mode 100644 plot/plotPS.c create mode 100644 plot/plotPixels.c create mode 100644 plot/plotRutils.c create mode 100644 plot/plotVers.c create mode 100644 plot/tclplot.c create mode 100644 plow/Depend create mode 100644 plow/Makefile create mode 100644 plow/PlowCmd.c create mode 100644 plow/PlowJogs.c create mode 100644 plow/PlowMain.c create mode 100644 plow/PlowQueue.c create mode 100644 plow/PlowRandom.c create mode 100644 plow/PlowRules1.c create mode 100644 plow/PlowRules2.c create mode 100644 plow/PlowRules3.c create mode 100644 plow/PlowSearch.c create mode 100644 plow/PlowTech.c create mode 100644 plow/PlowTest.c create mode 100644 plow/PlowWidth.c create mode 100644 plow/PlowYank.c create mode 100644 plow/TODO create mode 100644 plow/plow.h create mode 100644 plow/plowDebugInt.h create mode 100644 plow/plowInt.h create mode 100644 readline/Makefile create mode 100644 readline/README create mode 100644 readline/readline-4.3/CHANGELOG create mode 100644 readline/readline-4.3/CHANGES create mode 100644 readline/readline-4.3/COPYING create mode 100644 readline/readline-4.3/INSTALL create mode 100644 readline/readline-4.3/MANIFEST create mode 100644 readline/readline-4.3/Makefile.in create mode 100644 readline/readline-4.3/README create mode 100644 readline/readline-4.3/USAGE create mode 100644 readline/readline-4.3/aclocal.m4 create mode 100644 readline/readline-4.3/ansi_stdlib.h create mode 100644 readline/readline-4.3/bind.c create mode 100644 readline/readline-4.3/callback.c create mode 100644 readline/readline-4.3/chardefs.h create mode 100644 readline/readline-4.3/compat.c create mode 100644 readline/readline-4.3/complete.c create mode 100644 readline/readline-4.3/config.h.in create mode 100755 readline/readline-4.3/configure create mode 100644 readline/readline-4.3/configure.in create mode 100644 readline/readline-4.3/display.c create mode 100644 readline/readline-4.3/doc/Makefile.in create mode 100644 readline/readline-4.3/doc/hist.texinfo create mode 100644 readline/readline-4.3/doc/history.3 create mode 100644 readline/readline-4.3/doc/hstech.texinfo create mode 100644 readline/readline-4.3/doc/hsuser.texinfo create mode 100644 readline/readline-4.3/doc/manvers.texinfo create mode 100644 readline/readline-4.3/doc/readline.3 create mode 100644 readline/readline-4.3/doc/rlman.texinfo create mode 100644 readline/readline-4.3/doc/rltech.texinfo create mode 100644 readline/readline-4.3/doc/rluser.texinfo create mode 100644 readline/readline-4.3/doc/rluserman.texinfo create mode 100755 readline/readline-4.3/doc/texi2dvi create mode 100755 readline/readline-4.3/doc/texi2html create mode 100644 readline/readline-4.3/doc/texinfo.tex create mode 100644 readline/readline-4.3/emacs_keymap.c create mode 100644 readline/readline-4.3/examples/Inputrc create mode 100644 readline/readline-4.3/examples/Makefile.in create mode 100644 readline/readline-4.3/examples/excallback.c create mode 100644 readline/readline-4.3/examples/fileman.c create mode 100644 readline/readline-4.3/examples/histexamp.c create mode 100644 readline/readline-4.3/examples/manexamp.c create mode 100644 readline/readline-4.3/examples/readlinebuf.h create mode 100644 readline/readline-4.3/examples/rl.c create mode 100644 readline/readline-4.3/examples/rlcat.c create mode 100644 readline/readline-4.3/examples/rlfe.c create mode 100644 readline/readline-4.3/examples/rltest.c create mode 100644 readline/readline-4.3/examples/rlversion.c create mode 100644 readline/readline-4.3/funmap.c create mode 100644 readline/readline-4.3/histexpand.c create mode 100644 readline/readline-4.3/histfile.c create mode 100644 readline/readline-4.3/histlib.h create mode 100644 readline/readline-4.3/history.c create mode 100644 readline/readline-4.3/history.h create mode 100644 readline/readline-4.3/histsearch.c create mode 100644 readline/readline-4.3/input.c create mode 100644 readline/readline-4.3/isearch.c create mode 100644 readline/readline-4.3/keymaps.c create mode 100644 readline/readline-4.3/keymaps.h create mode 100644 readline/readline-4.3/kill.c create mode 100644 readline/readline-4.3/macro.c create mode 100644 readline/readline-4.3/mbutil.c create mode 100644 readline/readline-4.3/misc.c create mode 100644 readline/readline-4.3/nls.c create mode 100644 readline/readline-4.3/parens.c create mode 100644 readline/readline-4.3/posixdir.h create mode 100644 readline/readline-4.3/posixjmp.h create mode 100644 readline/readline-4.3/posixstat.h create mode 100644 readline/readline-4.3/readline.c create mode 100644 readline/readline-4.3/readline.h create mode 100644 readline/readline-4.3/rlconf.h create mode 100644 readline/readline-4.3/rldefs.h create mode 100644 readline/readline-4.3/rlmbutil.h create mode 100644 readline/readline-4.3/rlprivate.h create mode 100644 readline/readline-4.3/rlshell.h create mode 100644 readline/readline-4.3/rlstdc.h create mode 100644 readline/readline-4.3/rltty.c create mode 100644 readline/readline-4.3/rltty.h create mode 100644 readline/readline-4.3/rltypedefs.h create mode 100644 readline/readline-4.3/rlwinsize.h create mode 100644 readline/readline-4.3/savestring.c create mode 100644 readline/readline-4.3/search.c create mode 100644 readline/readline-4.3/shell.c create mode 100644 readline/readline-4.3/shlib/Makefile.in create mode 100644 readline/readline-4.3/signals.c create mode 100755 readline/readline-4.3/support/config.guess create mode 100644 readline/readline-4.3/support/config.sub create mode 100755 readline/readline-4.3/support/install.sh create mode 100755 readline/readline-4.3/support/mkdirs create mode 100755 readline/readline-4.3/support/mkdist create mode 100755 readline/readline-4.3/support/shlib-install create mode 100755 readline/readline-4.3/support/shobj-conf create mode 100644 readline/readline-4.3/support/wcwidth.c create mode 100644 readline/readline-4.3/tcap.h create mode 100644 readline/readline-4.3/terminal.c create mode 100644 readline/readline-4.3/text.c create mode 100644 readline/readline-4.3/tilde.c create mode 100644 readline/readline-4.3/tilde.h create mode 100644 readline/readline-4.3/undo.c create mode 100644 readline/readline-4.3/util.c create mode 100644 readline/readline-4.3/vi_keymap.c create mode 100644 readline/readline-4.3/vi_mode.c create mode 100644 readline/readline-4.3/xmalloc.c create mode 100644 readline/readline-4.3/xmalloc.h create mode 100644 resis/Depend create mode 100644 resis/Makefile create mode 100644 resis/ResBasic.c create mode 100644 resis/ResChecks.c create mode 100644 resis/ResConDCS.c create mode 100644 resis/ResDebug.c create mode 100644 resis/ResFract.c create mode 100644 resis/ResJunct.c create mode 100644 resis/ResMain.c create mode 100644 resis/ResMakeRes.c create mode 100644 resis/ResMerge.c create mode 100644 resis/ResPrint.c create mode 100644 resis/ResReadSim.c create mode 100644 resis/ResRex.c create mode 100644 resis/ResSimple.c create mode 100644 resis/ResUtils.c create mode 100644 resis/ResWrite.c create mode 100644 resis/resis.h create mode 100644 router/Depend create mode 100644 router/Makefile create mode 100644 router/router.h create mode 100644 router/routerInt.h create mode 100644 router/rtrChannel.c create mode 100644 router/rtrCmd.c create mode 100644 router/rtrDcmpose.c create mode 100644 router/rtrDcmpose.h create mode 100644 router/rtrFdback.c create mode 100644 router/rtrHazards.c create mode 100644 router/rtrMain.c create mode 100644 router/rtrPaint.c create mode 100644 router/rtrPin.c create mode 100644 router/rtrSide.c create mode 100644 router/rtrStem.c create mode 100644 router/rtrTech.c create mode 100644 router/rtrTravers.c create mode 100644 router/rtrVia.c create mode 100644 router/tclroute.c create mode 100644 rules.mak create mode 100644 scmos/COPYRIGHT create mode 100644 scmos/Makefile create mode 100644 scmos/README create mode 100644 scmos/cif_template/COPYRIGHT create mode 100644 scmos/cif_template/Makefile create mode 100644 scmos/cif_template/README create mode 100644 scmos/cif_template/calc.lambda create mode 100644 scmos/cif_template/cifin-ami16.gen create mode 100644 scmos/cif_template/cifin-cmos14b.gen create mode 100644 scmos/cif_template/cifin-cmos26b.gen create mode 100644 scmos/cif_template/cifin-cmos26g.gen create mode 100644 scmos/cif_template/cifin-cmosn.gen create mode 100644 scmos/cif_template/cifin-cmosn.nw create mode 100644 scmos/cif_template/cifin-cmosx.gen create mode 100644 scmos/cif_template/cifin-hp-cif.nw create mode 100644 scmos/cif_template/cifin-hp.nw create mode 100644 scmos/cif_template/cifin-ibm.gen create mode 100644 scmos/cif_template/cifin.c create mode 100644 scmos/cif_template/cifin.cascade create mode 100644 scmos/cif_template/cifin.gen create mode 100644 scmos/cif_template/cifin.nw create mode 100644 scmos/cif_template/cifin.oldnw create mode 100644 scmos/cif_template/cifin.others create mode 100644 scmos/cif_template/cifin.pw create mode 100644 scmos/cif_template/cifin26g.c create mode 100644 scmos/cif_template/cifout-ami16.gen create mode 100644 scmos/cif_template/cifout-cmos14b-sub.gen create mode 100644 scmos/cif_template/cifout-cmos14b.gen create mode 100644 scmos/cif_template/cifout-cmos26b.gen create mode 100644 scmos/cif_template/cifout-cmos26g.gen create mode 100644 scmos/cif_template/cifout-cmos26g.soi create mode 100644 scmos/cif_template/cifout-cmos34.gen create mode 100644 scmos/cif_template/cifout-cmos34.nw create mode 100644 scmos/cif_template/cifout-cmos34.pw create mode 100644 scmos/cif_template/cifout-cmosn.gen create mode 100644 scmos/cif_template/cifout-cmosn.nw create mode 100644 scmos/cif_template/cifout-cmosx.gen create mode 100644 scmos/cif_template/cifout-ibm.gen create mode 100644 scmos/cif_template/cifout-orbit.gen create mode 100644 scmos/cif_template/cifout-orbit.nw create mode 100644 scmos/cif_template/cifout-orbit.pw create mode 100644 scmos/cif_template/cifout.c create mode 100644 scmos/cif_template/cifout.gen create mode 100644 scmos/cif_template/cifout.gen-old create mode 100644 scmos/cif_template/cifout.nw create mode 100644 scmos/cif_template/cifout.others create mode 100644 scmos/cif_template/cifout.pw create mode 100644 scmos/cif_template/cifout.scgnw create mode 100644 scmos/cif_template/cifout.scgpw create mode 100644 scmos/cif_template/cifout.test create mode 100644 scmos/cif_template/cifout26g.c create mode 100644 scmos/cif_template/scgcifout.c create mode 100644 scmos/doc/scmos-hpsub-rules create mode 100644 scmos/doc/scmos-rules-rev7.ps create mode 100644 scmos/examples/bipolar/README create mode 100644 scmos/examples/bipolar/guardring-npn.mag create mode 100644 scmos/examples/bipolar/large_npn.mag create mode 100644 scmos/examples/bipolar/min.mag create mode 100644 scmos/examples/bipolar/min2b.mag create mode 100644 scmos/examples/bipolar/min2e.mag create mode 100644 scmos/examples/bipolar/min_npn.mag create mode 100644 scmos/examples/bipolar/npn12_array_core.cif create mode 100644 scmos/examples/bipolar/npn_array.mag create mode 100644 scmos/examples/bipolar/npn_array16.cif create mode 100644 scmos/examples/bipolar/npn_array20.cif create mode 100644 scmos/examples/bipolar/pbase-resis.mag create mode 100644 scmos/examples/bipolar/vertical-pnp.mag create mode 100644 scmos/examples/ccd/ccd.mag create mode 100644 scmos/examples/ccd/ccd_array.mag create mode 100644 scmos/examples/ccd/qq.cif create mode 100644 scmos/examples/float_gate/float_gate.mag create mode 100644 scmos/examples/linear_capacitor/wellcap.cif create mode 100644 scmos/examples/linear_capacitor/wellcap.mag create mode 100644 scmos/examples/nist-mems-library/gas-sensor.cif create mode 100644 scmos/examples/nist-mems-library/gas-sensor.mag create mode 100644 scmos/examples/nist-mems-library/memslib.cif create mode 100644 scmos/examples/nist-mems-library/memslib.mag create mode 100644 scmos/examples/nist-mems-library/micro-hot-plate.cif create mode 100644 scmos/examples/nist-mems-library/micro-hot-plate.mag create mode 100644 scmos/examples/nist-mems-library/nist_mems_lib.doc create mode 100644 scmos/examples/nist-mems-library/open-80x80.cif create mode 100644 scmos/examples/nist-mems-library/open-80x80.mag create mode 100644 scmos/examples/nist-mems-library/open-oxide-80x80.cif create mode 100644 scmos/examples/nist-mems-library/open-oxide-80x80.mag create mode 100644 scmos/examples/nist-mems-library/pixel-160x160.cif create mode 100644 scmos/examples/nist-mems-library/pixel-160x160.mag create mode 100644 scmos/examples/nist-mems-library/pixel-80x80.cif create mode 100644 scmos/examples/nist-mems-library/pixel-80x80.mag create mode 100644 scmos/examples/nist-mems-library/thermal-actuator.cif create mode 100644 scmos/examples/nist-mems-library/thermal-actuator.mag create mode 100644 scmos/examples/nist-mems-library/thermal-converter.cif create mode 100644 scmos/examples/nist-mems-library/thermal-converter.mag create mode 100644 scmos/examples/palette.mag create mode 100644 scmos/examples/poly_capacitor/cap_array.mag create mode 100644 scmos/extract_template/scmosExt.tech.in create mode 100644 scmos/extract_template/scmosExt060_orb.tech.in create mode 100644 scmos/extract_template/scmosExt080.tech.in create mode 100644 scmos/extract_template/scmosExt100.tech.in create mode 100644 scmos/extract_template/scmosExt14b-sub.tech.in create mode 100644 scmos/extract_template/scmosExt14b-tm.tech.in create mode 100644 scmos/extract_template/scmosExt26b-sub.tech.in create mode 100644 scmos/extract_template/scmosExt26b.tech.in create mode 100644 scmos/extract_template/scmosExt34.tech.in create mode 100644 scmos/extract_template/scmosExtDiag.tech.in create mode 100644 scmos/gdsquery.tech.m4 create mode 100644 scmos/minimum.tech.m4 create mode 100644 scmos/mos.24bit.dstyle create mode 100644 scmos/mos.24bit.std.cmap create mode 100644 scmos/mos.7bit.dstyle create mode 100644 scmos/mos.7bit.mraster.cmap create mode 100644 scmos/mos.7bit.mraster_dstyle create mode 100644 scmos/mos.7bit.sgi.cmap create mode 100644 scmos/mos.7bit.std.cmap create mode 100644 scmos/mos.OpenGL.dstyle create mode 100644 scmos/mos.OpenGL.dstyle.mark create mode 100644 scmos/mos.OpenGL.std.cmap create mode 100644 scmos/rules/all-rules.mag create mode 100644 scmos/rules/rule1.mag create mode 100644 scmos/rules/rule10.mag create mode 100644 scmos/rules/rule11.mag create mode 100644 scmos/rules/rule12.mag create mode 100644 scmos/rules/rule14.mag create mode 100644 scmos/rules/rule15.mag create mode 100644 scmos/rules/rule16.mag create mode 100644 scmos/rules/rule17.mag create mode 100644 scmos/rules/rule18.mag create mode 100644 scmos/rules/rule19.mag create mode 100644 scmos/rules/rule2.mag create mode 100644 scmos/rules/rule3.mag create mode 100644 scmos/rules/rule4.mag create mode 100644 scmos/rules/rule4_2.mag create mode 100644 scmos/rules/rule5a.mag create mode 100644 scmos/rules/rule5b.mag create mode 100644 scmos/rules/rule6a.mag create mode 100644 scmos/rules/rule6b.mag create mode 100644 scmos/rules/rule7.mag create mode 100644 scmos/rules/rule8.mag create mode 100644 scmos/rules/rule9.mag create mode 100644 scmos/scmos.tech.in create mode 100644 scmos/test.out create mode 100755 scripts/config.guess create mode 100644 scripts/config.log create mode 100755 scripts/config.status create mode 100755 scripts/config.sub create mode 100755 scripts/configure create mode 100644 scripts/configure.in create mode 100644 scripts/configure.in.orig create mode 100644 scripts/defs.mak create mode 100755 scripts/defs.mak.in create mode 100755 scripts/install-sh create mode 100644 scripts/magic.spec.in create mode 100755 scripts/makedbh create mode 100755 scripts/missing create mode 100755 scripts/mkdirs create mode 100755 scripts/mkinstalldirs create mode 100755 scripts/printmans create mode 100644 select/Depend create mode 100644 select/Makefile create mode 100644 select/selCreate.c create mode 100644 select/selDisplay.c create mode 100644 select/selEnum.c create mode 100644 select/selInt.h create mode 100644 select/selOps.c create mode 100644 select/selUndo.c create mode 100644 select/selUnselect.c create mode 100644 select/select.h create mode 100644 sim/Depend create mode 100644 sim/Makefile create mode 100644 sim/SimDBstuff.c create mode 100644 sim/SimExtract.c create mode 100644 sim/SimRsim.c create mode 100644 sim/SimSelect.c create mode 100644 sim/SimSelect.c.new create mode 100644 sim/sim.h create mode 100644 tcltk/Depend create mode 100644 tcltk/Makefile create mode 100644 tcltk/bsitools.tcl create mode 100644 tcltk/cellmgr.tcl create mode 100755 tcltk/console.tcl create mode 100644 tcltk/drc.tcl create mode 100644 tcltk/ext2sim.sh create mode 100755 tcltk/ext2sim.sh.in create mode 100644 tcltk/ext2spice.sh create mode 100755 tcltk/ext2spice.sh.in create mode 100755 tcltk/magic.sh.in create mode 100755 tcltk/magic.tcl.in create mode 100644 tcltk/magicdnull.c create mode 100644 tcltk/magicexec.c create mode 100644 tcltk/magicps.pro create mode 100644 tcltk/mazeroute.tcl create mode 100644 tcltk/socketcmd.tcl create mode 100755 tcltk/strip_reflibs.tcl create mode 100644 tcltk/tclmagic.c create mode 100644 tcltk/tclmagic.h create mode 100644 tcltk/techbuilder.tcl create mode 100644 tcltk/texthelper.tcl create mode 100755 tcltk/tkcon.tcl create mode 100755 tcltk/tkshell.tcl create mode 100644 tcltk/toolkit.tcl create mode 100644 tcltk/toolkit_rev0.tcl create mode 100644 tcltk/tools.tcl create mode 100644 tcltk/wrapper.tcl create mode 100644 textio/Depend create mode 100644 textio/Makefile create mode 100644 textio/textio.h create mode 100644 textio/textioInt.h create mode 100644 textio/txCommands.c create mode 100644 textio/txInput.c create mode 100644 textio/txMain.c create mode 100644 textio/txMore.c create mode 100644 textio/txOutput.c create mode 100644 textio/txcommands.h create mode 100644 tiles/Depend create mode 100644 tiles/Makefile create mode 100644 tiles/search.c create mode 100644 tiles/search2.c create mode 100644 tiles/tile.c create mode 100644 tiles/tile.h create mode 100644 utils/Depend create mode 100644 utils/LIBdbio.c create mode 100644 utils/LIBmain.c create mode 100644 utils/LIBtextio.c create mode 100644 utils/Makefile create mode 100644 utils/args.c create mode 100644 utils/child.c create mode 100644 utils/displays.proto create mode 100644 utils/dqueue.c create mode 100644 utils/dqueue.h create mode 100644 utils/finddisp.c create mode 100644 utils/flock.c create mode 100644 utils/flsbuf.c create mode 100644 utils/fraction.c create mode 100644 utils/geofast.h create mode 100644 utils/geometry.c create mode 100644 utils/geometry.h create mode 100644 utils/getrect.c create mode 100644 utils/hash.c create mode 100644 utils/hash.h create mode 100644 utils/heap.c create mode 100644 utils/heap.h create mode 100644 utils/list.c create mode 100644 utils/list.h create mode 100644 utils/lookup.c create mode 100644 utils/lookupany.c create mode 100644 utils/lookupfull.c create mode 100644 utils/macros.c create mode 100644 utils/macros.h create mode 100644 utils/magic.h create mode 100644 utils/magsgtty.h create mode 100644 utils/main.c create mode 100644 utils/main.h create mode 100644 utils/malloc.c create mode 100644 utils/malloc.h create mode 100644 utils/match.c create mode 100644 utils/maxrect.c create mode 100644 utils/maxrect.h create mode 100644 utils/netlist.c create mode 100644 utils/netlist.h create mode 100644 utils/niceabort.c create mode 100644 utils/parser.c create mode 100644 utils/parsetest.c create mode 100644 utils/path.c create mode 100644 utils/paths.h create mode 100644 utils/pathvisit.c create mode 100644 utils/pathvisit.h create mode 100644 utils/port.c create mode 100644 utils/printstuff.c create mode 100644 utils/runstats.c create mode 100644 utils/runstats.h create mode 100644 utils/set.c create mode 100644 utils/show.c create mode 100644 utils/signals.c create mode 100644 utils/signals.h create mode 100644 utils/stack.c create mode 100644 utils/stack.h create mode 100644 utils/strdup.c create mode 100644 utils/styles.h create mode 100644 utils/tech.c create mode 100644 utils/tech.h create mode 100644 utils/touchingtypes.h create mode 100644 utils/touchtypes.c create mode 100644 utils/undo.c create mode 100644 utils/undo.h create mode 100644 utils/utils.h create mode 100644 windows/Depend create mode 100644 windows/Makefile create mode 100644 windows/vfont.B.12 create mode 100644 windows/vfont.I.12 create mode 100644 windows/vfont.R.8 create mode 100644 windows/windClient.c create mode 100644 windows/windCmdAM.c create mode 100644 windows/windCmdNR.c create mode 100644 windows/windCmdSZ.c create mode 100644 windows/windDebug.c create mode 100644 windows/windDisp.c create mode 100644 windows/windInt.h create mode 100644 windows/windMain.c create mode 100644 windows/windMove.c create mode 100644 windows/windSearch.c create mode 100644 windows/windSend.c create mode 100644 windows/windTrans.c create mode 100644 windows/windView.c create mode 100644 windows/windows.h create mode 100644 windows/windows11.glyphs create mode 100644 windows/windows14.glyphs create mode 100644 windows/windows22.glyphs create mode 100644 windows/windows7.glyphs create mode 100644 wiring/Depend create mode 100644 wiring/Makefile create mode 100644 wiring/wireInt.h create mode 100644 wiring/wireOps.c create mode 100644 wiring/wireTech.c create mode 100644 wiring/wireTech.c.new create mode 100644 wiring/wireUndo.c create mode 100644 wiring/wiring.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..67222f79 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.*% +*.cdslck +.inca.db.* +inca.*.pak +*.swp +*~ +*/av_extracted*/ +.nfs* +*.cd- +*/mommdl/ diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..6794b09d --- /dev/null +++ b/INSTALL @@ -0,0 +1,72 @@ +Autoconf Capsule Summary: +---------------------------------------- + + Compile and install: + + ./configure [options] + make + make install + + Autoconf options (use "./configure --help" for a complete list): + + --prefix=DIR Indicates the install directory. Determines the + install directory of the executable. Determines the + install directory of the libraries (${prefix}/lib) + unless use of "--libdir=DIR" overrides it. Defaults + to /usr/local/. + + --libdir=DIR By default, ${prefix}/lib/. Otherwise, run-time + files used by magic are installed here, and + ${CAD_ROOT} is set to DIR. In some distributions, + this is set to /usr/share/. + + --with-interpreter=ARG + Enable one of the two interpreters. ARG may be + one of "tcl" or "scheme". + + --with-tcl Equivalent to "--with-interpreter=tcl". + Normally enabled, if available. + + --with-opengl Enable OpenGL as a graphics option. Normally + enabled, if available. + + --without-x Disable X11 as a graphics option. Normally + enabled. + + --disable-nonmanhattan + Disable non-Manhattan extensions. Normally + enabled. + + --disable-readline + Disable the GNU "readline" package. Normally + enabled. + + --disable-threads + Disable threaded X11 and OpenGL graphics. + Normally enabled. + +Notes to Magic maintainers: +-------------------------- + +This directory contains all the sources for the Magic system and related +programs. The system runs on a number of machines. You should read the +Magic Maintainer's manual as well as the introduction to Magic before +compiling the system. These documents are in the "doc" subdirectory in +PostScript, as well as the original LaTeX source. + +The "proper" way to profile the amount of CPU time spent in each procedure +is to edit "defs.mak" and add flag "-pg" to CFLAGS. Then recompile, install, +and run. Note that this doesn't work with the Tcl version; you have to +compile the standalone version. After running, magic creates a file "gmon.out". +To view the contents, run "gprof /usr/local/bin/magic > gprof.out" (the output +can be very long). + +Memory tracing in Tcl requires that Tcl and Tk be compiled with the +TCL_MEM_DEBUG option. Magic also must be compiled with TCL_MEM_DEBUG, +which can be done by adding the definition -DTCL_MEM_DEBUG to DFLAGS +in defs.mak, after running "configure". + +Magic is normally compiled without the optimization flag. This is handled +by explicitly setting CFLAGS as an environment variable in the top-level +"configure" script prior to calling scripts/configure. The top-level +configure script needs to be modified to enable compile-time optimization. diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..2e483885 --- /dev/null +++ b/Makefile @@ -0,0 +1,129 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/Makefile,v 1.1.1.1 2008/02/03 20:43:49 tim Exp $ +# + +MAGICDIR = . +PROGRAMS = magic +TECH = scmos +LIBRARIES = database utils extflat +MODULES = cmwind commands database dbwind debug drc extflat extract \ + graphics netmenu plow resis select sim textio tiles utils \ + windows wiring + +MAKEFLAGS = +INSTALL_CAD_DIRS = windows doc ${TECH} + +include defs.mak + +all: $(ALL_TARGET) + +standard: + @echo --- errors and warnings logged in file make.log + @${MAKE} mains 2>&1 | tee -a make.log | egrep -i "(.c:|Stop.|---)" + +tcl: + @echo --- errors and warnings logged in file make.log + @${MAKE} tcllibrary 2>&1 | tee -a make.log | egrep -i "(.c:|Stop.|---)" + +force: clean all + +defs.mak: + @echo No \"defs.mak\" file found. Run "configure" to make one. + +config: + ${MAGICDIR}/configure + +tcllibrary: database/database.h modules + @echo --- making Tcl shared libraries + for dir in ${PROGRAMS}; do \ + (cd $$dir && ${MAKE} tcl-main); done + +mains: database/database.h modules libs + @echo --- making main programs + for dir in ${PROGRAMS}; do \ + (cd $$dir && ${MAKE} main); done + +database/database.h: database/database.h.in + @echo --- making header file database/database.h + ${SCRIPTS}/makedbh database/database.h.in database/database.h + +modules: + @echo --- making modules + for dir in ${MODULES} ${PROGRAMS}; do \ + (cd $$dir && ${MAKE} module); done + +libs: + @echo --- making libraries + for dir in ${LIBRARIES}; do \ + (cd $$dir && ${MAKE} lib); done + +depend: database/database.h + ${RM} */Depend + for dir in ${MODULES} ${UNUSED_MODULES} ${PROGRAMS}; do \ + (cd $$dir && ${MAKE} depend); done + +install: $(INSTALL_TARGET) + +install-magic: + @echo --- installing executable to $(DESTDIR)${BINDIR} + @echo --- installing runtime files to $(DESTDIR)${LIBDIR} + @${MAKE} install-real 2>&1 >> install.log + +install-real: install-dirs + for dir in ${INSTALL_CAD_DIRS}; do \ + (cd $$dir && ${MAKE} install); done + for dir in ${PROGRAMS}; do \ + (cd $$dir && ${MAKE} install); done + +install-tcl-dirs: + ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \ + $(DESTDIR)${SYSDIR} $(DESTDIR)${TCLDIR} $(DESTDIR)${TCLDIR}/bitmaps + +install-dirs: + ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \ + $(DESTDIR)${SYSDIR} $(DESTDIR)${SCMDIR} + +install-tcl: + @echo --- installing executable to $(DESTDIR)${BINDIR} + @echo --- installing runtime files to $(DESTDIR)${LIBDIR} + @${MAKE} install-tcl-real 2>&1 >> install.log + +install-tcl-real: install-tcl-dirs + for dir in ${INSTALL_CAD_DIRS} ${PROGRAMS}; do \ + (cd $$dir && ${MAKE} install-tcl); done + +clean: + for dir in ${MODULES} ${PROGRAMS} ${TECH} ${UNUSED_MODULES}; do \ + (cd $$dir && ${MAKE} clean); done + ${RM} *.tmp */*.tmp *.sav */*.sav *.log TAGS tags + +distclean: + touch defs.mak + @${MAKE} clean + ${RM} defs.mak old.defs.mak ${MAGICDIR}/scripts/defs.mak + ${RM} ${MAGICDIR}/scripts/default.conf + ${RM} ${MAGICDIR}/scripts/config.log ${MAGICDIR}/scripts/config.status + ${RM} scripts/magic.spec magic-`cat VERSION` magic-`cat VERSION`.tgz + ${RM} *.log + +dist: + ${RM} scripts/magic.spec magic-`cat VERSION` magic-`cat VERSION`.tgz + sed -e /@VERSION@/s%@VERSION@%`cat VERSION`% \ + scripts/magic.spec.in > scripts/magic.spec + ln -nsf . magic-`cat VERSION` + tar zchvf magic-`cat VERSION`.tgz --exclude CVS \ + --exclude magic-`cat VERSION`/magic-`cat VERSION` \ + --exclude magic-`cat VERSION`/magic-`cat VERSION`.tgz \ + magic-`cat VERSION` + +clean-mains: + for dir in ${PROGRAMS}; do \ + (cd $$dir && ${RM} $$dir); done + +tags: + ${RM} tags + find . ${MODULES} ${PROGRAMS} -name "*.[ch]" -maxdepth 1 | xargs ctags -o tags + +TAGS: + ${RM} TAGS + find . ${MODULES} ${PROGRAMS} -name "*.[ch]" -maxdepth 1 | xargs etags -o TAGS diff --git a/README b/README new file mode 100644 index 00000000..2347a6ce --- /dev/null +++ b/README @@ -0,0 +1,374 @@ +1. General Information: +--------------------------------- + Use your World Wide Web browser to read: + + http://opencircuitdesign.com/magic/ + http://vlsi.csl.cornell.edu/magic/ + http://www.research.digital.com/wrl/magic/magic.html + + Primary documentation is on the opencircuitdesign.com website under + the "Documentation" link. + + The current development versions of magic are maintained by Tim Edwards + and the current distribution version is + maintained by Rajit Manohar . Please let us + know of any problems/bugs you find. Development of versions 7.2 and + newer is generously funded by MultiGiG, Inc. + +2. Compilation and Installation: +--------------------------------- + See the file "INSTALL" in this directory. + +3. Version 8.2 Release Notes: +--------------------------------- + + As of the release of version 8.2, Version 8.1 is now the new stable + distribution, and 8.2 is the development distribution. + +4. Version 8.1 Release Notes: +--------------------------------- + + As of the release of version 8.1, Version 8.0 is now the new stable + distribution, and 8.1 is the development distribution. + + What's new in 8.1: + ------------------ + 1) Substantially revised substrate handling allows for "soft + connectivity" detection, and resolves (finally) the problem of + the hack handling of nMOS bulk connections using a default + name without any understanding of a substrate node and + connectivity. + +5. Version 8.0 Release Notes: +--------------------------------- + + As of the release of version 8.0, Version 7.5 is now the new stable + distribution, and 8.0 is the development distribution. + + What's new in 8.0: + ------------------ + 1) Vector outline fonts with ability to control font, scale, rotation, + and offset. Public-license outline fonts provided by the freefont + project. + + 2) Hierarchical SPICE output for LVS. + + 3) New cifoutput operators including "net" and "maxrect", specifically + for using with the "cif paint" command. + + 4) DRC method for handling via rules specifying overlap on two + opposite sides but not on the others. + + 5) Improved DRC method that ignores errors in subcells that are + masked by the parent cell. + + 6) Improved cell manager based on methods available in Tk 8.5 + + 7) New extraction method "msubcircuit" with methods for specifying + parameter names for source/drain area and perimeter. + +6. Version 7.5 Release Notes: +--------------------------------- + + Version 7.5 is the development branch. Version 7.5.0 is the same as + 7.4.2, which is essentially the same as 7.3.123, plus some + documentation updates. Intended development is as follows: + + What's new in 7.5: + ------------------ + 1) Use a finely spaced grid for the database, but keep the concept + of "lambda" for layout. Keep backwards compatibility, and resolve + issues with layout that does not work well on the lambda grid. + Implemented in 7.5.1 by allowing a DRC "scalefactor" line, + which declares that all DRC rules are in units of (lambda / + scalefactor). Rules "in use" are scaled to lambda and rounded to + the nearest integer. The original value is retained, however, so + that any call to "scalegrid" will recompute the DRC distances based + on the current internal grid. Thus, we can define DRC rules in + fractional lambda and therefore match vendor DRC rule distances + while still maintaining magic's concept of "lambda". This means + that users working entirely within magic have scalable CMOS rules, + but if a "vendor cell" (3rd party GDS or CIF) is loaded, the DRC + rules will be correct with respect to it. + 2) Multiple DRC styles allowed in the technology file. + 3) Memory-mapped tile allocation using the mmap() function. + 4) Layer and cell instance locking + 5) Euclidean-distance measure on "cif grow" operator. + 6) "cif paint" command to automatically manipulate the database + paint using "cifoutput" rulesets. + 7) New contact-cut generation algorithm. + 8) Added the ability to define and extract MOS devices with + asymmetric source and drain. + 9) Added extraction devices "rsubcircuit" and "subcircuit" to + produce subcircuit records in SPICE output, with a method to + define parameters to be passed to the subcircuit. + 10) Added resistor corner scaling (i.e., the resistance of a + material at a corner can be set as a fraction of the resistance + of the same material on a straight path). + 11) Updated the interactive maze router, fixing many bugs, and adding + many enhancements, including a maze router GUI that can be used + to aid in interactively routing an entire netlist, or performing + a verification of a netlist against the layout. + 12) "gridlimit" keyword in the cifoutput section to prevent magic + from generating geometry beyond a specific resolution. + 13) Added the ability to specify all units in the extract section in + microns, and added a simplified method for specifying standard + parasitic capacitance extraction rules. + 14) "gds merge true" option to generate polygons in the GDS output + instead of tiles. This creates *much* smaller output files at + the expense of processing time. + 15) New "contact" function to automatically contact two layers at + an intersection. + + See the online release notes for a more thorough list of features. + +7. Version 7.4 Release Notes: +--------------------------------- + + Version 7.4 is the new stable distribution version of magic. + Apart from changes to the release notes, it is identical to + the last revision (123) of development version 7.3. Revisions + of 7.4 will be made as necessary to fix bugs in the code. All + new additions and major changes will be done to the new + development distribution, version 7.5. Therefore there will + not be a "What's new in 7.4" section, as there is not supposed + to be anything new in version 7.4. + +8. Version 7.3 Release Notes: +--------------------------------- + + Magic release 7.3 incorporates a stacked contact model which is, + for the most part, backwardly compatible with Magic releases + 7.2 and earlier. Information about this developmental release + can be found at: + + http://opencircuitdesign.com/magic/magic7_3.html + + + What's new in 7.3: + ------------------ + Provided by Tim Edwards (MultiGiG, Inc.): + 1) Stacked contact model allowing arbitrary stacking of + contact types. + 2) A separate "undo/redo" method for network selection, to + remove the memory overhead associated with selecting and + unselecting large networks. Also removes some time overhead + as well, especially when unselecting networks. + 3) Much improved "plot pnm" function. + 4) Improved transistor and resistor extraction. + 5) LEF format reader; improved LEF/DEF input/output handling + 6) New style and colormap file formats + 7) Vendor GDS read/write capability + 8) "wire segment" drawing function + 9) Handling of path records in CIF and GDS input + 10) Handling of cell scaling in GDS input + 11) Pi-network device extraction for resistors + 12) Option to write contacts as cell arrays in GDS output + 13) New "widespacing" and "maxwidth" DRC algorithms. + 14) "polygon" command + 15) New cifoutput operator "bloat-all" + 16) Backing-store for 24-bit and OpenGL graphics + 17) New "pick" tool for interactive selection move and copy + 18) New interactive "wire" tool + 19) Crosshair + 20) New cifoutput operator "slots" + 21) New fcntl-based file locking mechanism + 22) "angstroms" units supported in cifinput/cifoutput + 23) Non-Manhattan device extraction support + 24) New "feedback" mechanism + 25) Proper support for > 32 planes (up to 64) + 26) Fixed array interaction CIF/GDS generation + 27) Added executable "magicdnull" for streamlined batch-mode use + 28) New method for crash backups, including restore with "magic -r" + 29) A number of other technology file additions and enhancements + +9. Version 7.2 Release Notes: +--------------------------------- + + Magic release 7.2 incorporates the capability to run magic from the Tcl + interpreter with graphics handled by Tk. Instructions for compiling + and installing this version are in README.Tcl. Information about + this release can be found at: + + http://opencircuitdesign.com/magic/magic7_2.html + + What's new in 7.2: + ------------------ + Provided by Tim Edwards (MultiGiG, Inc., and JHU Applied Physics Lab): + + 1) Tcl interpreter extension option + 2) Cygwin compile option + 3) Memory resources cleaned up + 4) GUI interface to Tcl version of Magic + 5) Readline update to version 4.3 + 6) OpenGL fixes and refinements + 7) Nonmanhattan geometry fixes and extensions + 8) Threaded graphics in non-Tcl environments + 9) Inductance extraction + 10) CIF and GDS input/output support for deep submicron technologies + 11) Different internal and lambda grids, including automatic or + induced ("scalegrid" command) grid subdivision and expansion. + "snap" and "grid" functions and extensions aid layout when + lambda and internal units differ. + 12) Removed commands "list", "listall", "parent", and "child", + replacing them with the more general-purpose "cellname" + and "instance" commands. + 13) Added command "tech", and re-loadable technologies. + 14) Revamped the "dstyle" files and updated the dstyle version + 15) Added "element" types for layout annotation. + 16) Extended extract section of techfile to include "device" + keyword and devices "mosfet", "bjt", "capacitor", and "resistor". + New model resistor and mosfet use width/length instead of area/ + perimeter. + 17) Added 3D rendering window invoked by command "specialopen wind3d", + for the Tcl version compiled with OpenGL graphics. + 18) Added "height" keyword to tech file for height/thickness values + 19) Added "windowname" command for managing multiple wrapper windows + under Tcl. + 20) Added extraction extension for annular (ring) MOSFETs. + 21) Added "widespacing" DRC rule. + 22) Added GNU autoconf compile + 23) New command "property" for setting key:value pair properties + in cell definitions that can be interpreted by other routines + (such as LEF/DEF). + 24) General-purpose subcircuit method using the "port" command to + declare a cell to be a subcircuit and to mark the position and + orientation of connections into the subcell. This replaces a + method previously built into version 7.2 using a "subcircuit" + layer; that method is now considered obsolete. + 25) LEF and DEF format readers, LEF format writer. + 26) Improved techfile format with asterisk-notation and DRC + "surround", "overhang", and "rect_only" statements. + +10. Version 7.1 Release Notes: +--------------------------------- + + Magic release 7.1 consolidates all known patches/features + to magic version 6.5.x, and contains additional features that have + been added since the consolidation. Information about this release + is available at the magic web site: + + http://vlsi.cornell.edu/magic/ + + + What's new in 7.1: + ------------------ + Provided by Rajit Manohar (Cornell University) (formerly version 7.0): + 1) Implementation of "scheme" (a subset of lisp), a powerful method + of generating complex functions. + 2) Using CVS to facilitate source code development from multiple sites. + 3) New commands using scheme: Too many to mention here; see the + tutorials in doc/tutscm* for explanations. Functions themselves + are defined in ${CAD_ROOT}/magic/scm/*.scm + 4) Overhauled the readline interface. See doc/textfiles/readline.txt for + details. + 5) Changed tons of stuff about the build environment: + - the include paths in all files is now canonical. + - redid the make process and rewrote all Makefiles. + - tons of other small things that hopefully make the build process + nicer. + +11. Releases prior to version 7: +--------------------------------- + + What's new in 6.5.2: + -------------------- + Provided by R. Timothy Edwards (Johns Hopkins Applied Physics Laboratory): + 1) Support for OpenGL + Look at doc/open_gl.txt + 2) Minor update to :config for selection of multiple graphics + interfaces. + 3) Updates to dstyle and cmap files + 4) Always do a check to see if there is only one active layout + window: There's no need to annoy the user with complaints + of "Put the cursor in a layout window" when there is no + possibility of confusion about the matter. + + Provided by Philippe Pouliquen (Johns Hopkins University): + 5) "readline" command line editing capability + 6) Macro extensions for X11 (see doc/macro_extension.txt) + 7) Better handling of filenames on the UNIX command-line (multiple + filenames allowed, ".mag" extension not required). + 8) New commands: "child", "parent", "down", "xload", "list", "listall", + "listtop", "shell", "imacro". + 9) Command alterations: "box [+|-][dir]", "select visible", area of box + included in "box" command. + 10) Updated .magic macro file (source in magic/proto.magic, install in + ${CAD_ROOT}/magic/sys/.magic) (see doc/default_macros.txt). + + What's new in 6.5.1: + -------------------- + 1) Support for true-color displays (courtesy of Michael Godfrey) + Look into doc/hires-color.txt + 2) Minor updates in ext2sim, ext2spice + + What's new in 6.5: + ----------------- + 1) Bug fixes in the extractor propagation of attributes (SU) + + 2) New version of ext2sim ext2spice with support for hspice, spice2, + and spice3 (SU) + + 3) Integration of the port to SUN's Solaris OS (MIT) + + 4) Port to FreeBSD2.x. Thanks to John Wehle (john@jwlab.feith.com) + + 5) Integration of part of the DEC/WRL code fragments into the drc + code. Since the code is not completely trustworthy the fragments + are ifdef'd so if need be the drc will behave exactly as the old one. + (you just need to change the #define DRC_EXTENSIONS in drc/drc.h + to do that). For a description of the extensions look into + doc/tutwrl1.ps (DEC/WRL) + + 6) Integration of some patches in to the CIF code that introduce: + (i) A new cif operation squares-grid which generates contacts + on grid. + (ii) A new cif layer command min-width is added so that generated + layers have the correct min drc width when magic expands + layers in the hierarchy (like it does with wells). + + + Magic-6.5 crashes if compiled with gcc in Solaris2.x/SunOS5.x (curiously enough + it does not have that problem if compiled with Sun's cc compiler). To get + around that you need to set the flag -DUSE_SYSTEM_MALLOC flag in misc/DFLAGS + after you run make :config. The error has to do with allignment of doubles + and an alternative way to get rid of it is to change extract/extractInt.h + so that CapValue is float instead of double. Nevertheless the first method + is recomended. + + What's new in 6.4: + ------------------ + This release, magic 6.4, contains the following modifications: + + 1) A number of bug fixes from the 6.3 notes. + + 2) A version numbering facility for tech files. Please add a new + section to each tech file after the "tech" section, following + this example: + + version + version 2.0.3 + description "MOSIS CMOS 0.13u Nano-nano technology." + end + + Older versions of magic will complain about the new section, but + no harm will be done. + + 4) Various comments describing dates and versions, including the + above tech file information, are not written to the CIF file. + + 3) Support for patches and versioning: A new command called "version" + lists out the version number and patches that are installed. + A header file called patchlevel.h keeps track of a PATCHLEVEL + integer and a string in patchlevel.c keeps track of the names of + each installed patch. When posting patches to the net please be + sure your patch updates variables. See the files for details. + + 4) Ports to Alpha AXP OSF/1, SGI/IRIX (courtesy of Stefanos + Sidiropoulos) and Linux (courtesy of Harold Levy). + + 5) A change in the extractor algorithm to provide shielding for + perimeter capacitances. Also a change in ext2sim to maintain + information about the area and perimeter of diffusion and + the bulk connection of the fets (written by Stefanos + Sidiropoulos). diff --git a/README.Tcl b/README.Tcl new file mode 100644 index 00000000..58f65c79 --- /dev/null +++ b/README.Tcl @@ -0,0 +1,385 @@ +------------------------------------------------------------------- +A Tcl-wrapped version of magic +------------------------------------------------------------------- + +This file contains details on the compilation, installation, and +execution of the Tcl interpreter-based version of Magic. + +------------------------------------------------------------------- +Compiling and Installation +------------------------------------------------------------------- + +Compiling and installing have been simplified, but are not exactly the +same as the "standard" compile and install procedure, so be sure to +read these instructions first. + +1) Software prerequisites: + + You will need Tcl and Tk versions 8.2+. Testing has been done on Tcl + and Tk versions 8.3 and 8.4. Some commands are only compatible with + versions 8.2 and newer; these should be #ifdef'd sometime in the near + future to make the program compatible with Tcl versions at least back + to 8.0. For use with the wrapper GUI, it is preferable to have BLT + version 2.4 or newer to get the tree view of the cell hierarchy, + although the presence of BLT is not mandatory. For digital simulation, + you should have IRSIM version 9.6 revision 1 or newer. Presence of + IRSIM is not mandatory. Note that unlike magic versions 7.1 and older, + the IRSIM module is not selected at compile-time; in Tcl it is a + run-time loadable module. + +2) At the top level, do "./configure" and any other options (such as + "--prefix=DIR" for non-default installation location). "prefix" + determines the value $CAD_ROOT, which is set to ${prefix}/lib, + unless "--libdir=DIR" is set, in which case $CAD_ROOT is set to + this value. The "configure" script will determine + if Tcl is on the system, and enable it if it appears to be usable. + Note that if Tcl is installed in a non-standard location, it will + be necessary to pass the option "--with-tcl=" to "configure", + indicating the directory where the file "tclConfig.sh" can be found. + Likewise, the "configure" script attempts to find OpenGL include + files and libraries on the system, and enables the option if it can + find them. Again, if in a nonstandard location, it is necessary to + pass the option "--with-opengl=" indicating the directory where + OpenGL include files may be found. It is assumed that the libraries + are in a standard directory; if not, it may be necessary to make + symbolic links to them from a standard directory like /usr/X11R6/lib/. + +3) Do "make". This should complete the compilation of the Tcl-compatible + shared library file "magic/tcl/tclmagic.so". + +4) Do "make install". This should place all the necessary executables, + library files, etc., into the proper places. The main executable is + "magic" (a script). Normally, it runs Tcl from a console window + ("tkcon", at least for now). With a command-line argument "-noconsole", + it runs Tcl from the terminal (runs "magicexec", a stand-in for "wish"). + Original executables "ext2spice" and "ext2sim" have been changed to magic + command-line commands. They are available as separate packages to Tcl + and are loaded automatically by the startup Tcl script. + +5) Any other ".tcl" files (packages) for magic go in $CAD_ROOT/magic/tcl/. + Magic's Tcl startup appends this directory to Tcl's search directory for + Tcl/Tk executables. + +6) Make sure that the default .magic script and any user .magic scripts do + not have embedded control characters (see below in "Known Bugs"). The + one installed by the distribution is correct; the warning applies to + any legacy files. + +------------------------------------------------------------------- +Running Tcl-based magic +------------------------------------------------------------------- + +1) The startup script works out namespaces so that all magic commands + become directly available from the command line. A number of + commands have to be specially handled because of conflicts with + existing Tcl/Tk commands. These are: "flush", "clockwise", + "array", "load", "label", and "grid". From magic version 7.2 + revision 31, all of these commands can be run as either the + original Tcl/Tk command or as the magic command, and the + correct function will be called (because the syntax of the two + forms is mutually exclusive). + + In cases such as starting magic from another application like + irsim or netgen, all magic commands are prefixed by the + namespace "::magic::" to differentiate them from command names + in other applications. + + Note that some commands (ones which are not often used) have + simply been renamed. The command "list" has been replaced (and + its functionality extended) by commands "cellname" and "intance". + Command "split" has been changed to "splitpaint" (which matches + the "spliterase" command). + + Commands "source" and "send" are superceded by Tcl methods and + no longer exist as their former selves in magic. In particular, + "send" (sends a magic command to a window) is superceded by the + syntax of the window name followed by the magic command (see item + 4, below). Because magic extends Tcl, the "source" command is + equivalent to Tcl's "source" command). + + Commands for separate packages (namely, ext2sim and ext2spice) share + the magic namespace: magic::ext2sim and magic::ext2spice. + The magic startup script automatically loads these packages and makes + the commands available from the root namespace, i.e., "ext2sim" and + "ext2spice". + +2) Command entry works as follows: Because the underlying Tcl interpreter + is *supposed* to look and act like a normal Tcl interpreter, single-key + macros are only allowed from inside windows. The use of the ":" macro + (long-command) is implemented as faithfully as allowed by the interpreter. + When using the terminal as a console, it is not possible to enter a + command partially in the terminal or window and complete it in the + other. Also, the status of the background DRC is not reflected in the + cursor. The "tkcon" console-based version has a cursor which reflects + the DRC status, and commands may be entered partially or in full in + either the layout or the console windows. The cursor is "%" for normal + operation, "]" for DRC-in-progress, and ":" for commands initiated by + the long-command macro. Note that due to inherent limitations of the + Tk "text" widget, the insert cursor is not displayed in the console when + the cursor is in the layout window. Queries to the user force focus + into the console window; this will probably be reimplemented in dialog + boxes in the future. + +3) Tcl-magic should work with "tclreadline". The "tkcon" console-based + version has its own working readline-like capability. Note that + internally defined completion functions like cellname completion are + not available. + +4) Window commands: Note that in addition to the standard magic commands, + the Tcl/Tk version makes it possible to direct commands to a particular + window; e.g., ".magic2 paint m1" can be run from the command line in + place of putting the cursor in window ".magic2" and executing the + command "paint m1". This allows any possible magic command to be run + from a script. + + The deprecation of magic's "send" command has repercussions on window + commands, particularly when using non-layout windows. For example, the + [non-TCL-based magic] command "send netlist shownet" is supposed to + execute the "shownet" command in the context of the netlist window + ("specialopen netlist"). However, under Tk, "netlist" is not a valid + window path; the correct command is to note the window name (usually + something like ".magic2") and to use it to direct the command: + ".magic2 shownet" will execute the command "shownet" in the context of + window ".magic2". + +5) Command tags: A command called "tag" has been added with the following + syntax: + + magic::tag + + This allows an arbitrary Tcl procedure to be associated with any + magic command. The usual reason to do this is to allow GUI functions + to be updated in response to command-line entry or key macros in a + window. The method can also be used to re-organize Tcl output from + a command, or send commands to another Tcl application in response + to actions in magic. + + is a simple command name without any namespace + qualifier (e.g., "select" or "paint"). is a string + which may be either an inline procedure or a call to a defined Tcl + procedure. This string may contain certain embedded escapes which + will be substituted prior to evaluation. The escapes are: + + %W Full Tk pathname of the layout window + %R Tcl result of . The result is + absorbed. + %r Tcl result of . The result will be + returned to the calling function as usual. + %0 .. %5 Arguments passed to . + %% A single percent character. + +6) Windows can be generated as internal Tk windows instead of top-level + windows by using the command + + magic::openwindow . + + For example, the script: + + toplevel .layout + magic::openwindow "(UNNAMED)" .layout.magic1 + pack .layout.magic1 -expand true -fill both + bind .layout.magic11 {focus %W} + + generates a new window inside a toplevel frame named "layout", which + can be customized. In this case, the layout window does nothing except + contain the magic window. The fourth line ensures that the magic + window can generate keyboard events. + + Generation of full-frame GUIs is facilitated by the "-n[owindow]" + option, which brings magic up with the indicated graphics package but + no actual window displayed. It is up to the calling application to + call "magic::openwindow" and arrange the geometry and packing of the + windows. + +7) Another method for generating windows is to use the + "image create layer" method. For example, the command + 'openwindow "(UNNAMED)" .magic2' creates a new Tk window which + starts off unmapped. Followed by "image create layer img_layout + -name .magic2 -width 300 -height 300", an internal (offscreen) + pixmap is created in place of the Tk window, and will be updated + with changes to the layout just as any window would be. The + image "img_layout" can be used to drop the layout image into any Tk + widget which accepts images (such as the canvas and button widgets). + The syntax is "image create layer -name + -width -height ". Note that the Tk window is + destroyed when the image is instanced; this does not occur with the + "image create" command, but when the image is first mapped to the + screen. Here's an example which generates a button containing the + magic layout: + + openwindow "(UNNAMED)" .magic2 + image create layer img_layout -name .magic2 + toplevel .new + button .new.b1 -image img_layout + pack .new.b1 + + Layout may be painted in the window using command-line commands. + Entering the button with the cursor will refresh the layout view. + + IMPORTANT NOTE: When magic is run with OpenGL graphics ("-d OGL" + command-line option), the implementation uses the off-screen + rendering functions to draw layout onto pixmaps for the button + image feature mentioned above. There are a number of video card + drivers that do not correctly implement these functions, and will + crash magic if the toolbar is used. + +8) Some commands have been altered in the Tcl environment to return + results to the interpreter rather than simply print them as + messages on stdout. One example is "getnode", which returns the + string value of the selected node: + + set n [.magic1 getnode] + + Others implemented: "path sys|cell|search" returns a string + containing the indicated path. "box values" returns the box + coordinates. "windowcaption" returns the window title caption. + "cellname" and "instance", with the option "list", return their + results as Tcl lists. + +9) Environment variables and Tcl global variables: A few environment + variables are queried for backward compatibility; eventually all of + these should be either replaced or duplicated by Tcl global variables. + Currently, "$CAD_ROOT" is a duplicated variable. It can be set in the + UNIX shell environment prior to running Tcl-magic, and the Tcl variable + "$CAD_ROOT" will be duplicated from it. Otherwise, the Tcl variable + "$CAD_ROOT" will be set to the value determined by the "make config" + process. The use of "~cad" is completely deprecated. + + The new "make" process encourages the use of standard directory + trees such as "/usr/local/lib" for CAD_ROOT, rather than the oddball + "/home/cad/lib". The new system works well with user-installed versions + having no access to root filesystem directories for installation. + +10) Modes of operation: Tcl-based magic runs in all graphics modes, + including 8-bit PseudoColor, 16- and 24-bit TrueColor, and OpenGL. + When using a console and/or GUI wrapper in PseudoColor mode, magic + redefines all of the Tk colors in the console and the wrapper frame + so that they match the magic color scheme. The console gets the + magic layout colormap so that one can move between the layout + windows and the console without altering the colormap of either one. + +11) A "wrapper" GUI is in "wrapper.tcl" and is normally present; + it can be disabled with the command "magic -nowrapper" (or + "magic -now"). This wrapper removes magic's own title bar and + frame and replaces them with a frame managed by Tcl/Tk. + + The features of the wrapper are: + + A) Scrollbars are replaced by Tk scrollbars, but the functions + are essentially the same. + B) The caption is replaced by a Tk widget, with the same + function. + C) The box coordinates are displayed at the right-hand side + of the title bar. + D) A menubar is provided at the top left-hand corner. This + has entries "File" and "Options". "File" takes + care of many read and write functions (including CIF and + GDS). Options are: + + a) "Toolbar" enables a toolbar to the right of the + layout. This toolbar contains all of the layer types + in the technology file. Entering the button displays + the name of the layer type in the title bar. Clicking + with mouse button 2 or keystroke "p" paints the layer + type in the box on the layout window. Keystroke "e" + erases the layer type in the box. Clicking with mouse + button 3 hides the layer type in the layout window, and + clicking mouse button 1 restores it. Keystroke "s" + selects all paint of the layer type within the cursor + box. + + b) "Cell Manager" pops up a display showing the hierarchy + of layout cells in memory. This option is only available + if the BLT package for Tcl/Tk has been installed on the + system. When BLT is installed, the option will simply + appear. + + c) "Tech Manager" pops up a display showing various + properties of the currently loaded technology and provides + a convenient way to change technologies or CIF read/write + and extraction styles. + + d) "Pinout List" is a simple list widget that can search + a layout for layer type "pad", and enumerates all of + the pad instances found in the layout. This aids in + the task of generating the pin names in the final + stages of a chip design. + +12) Extraction: + + The Tcl version of magic makes use of the interpreter variable + space to work around some former deficiencies of the extractor. + Power and ground nodes can be explicitly defined by setting + variables $VDD and $GND in the Tcl global variable space + (e.g, "::set VDD VDD" and "::set GND GND"). If these are not + defined, then magic reverts to its original behavior of looking + for node names ending with "!". The Tcl variable names (or any + Tcl variable names) can be added to the techfile definition of + a device's default substrate node name (include the "$" in front + of the variable). Normally, this would use the two built-in + variables $GND and $VDD. These variables should be set in the + ".magic" file of each project directory, so that the default + device substrate connections will match the power and ground + definitions in a layout. If $GND and $VDD are defined but do + not match any node names in the layout, a warning is flagged. + +13) IRSIM simulation: + + Starting with revision 14, magic 7.2 supports interactive digital + simulation with IRSIM. It is necessary to compile IRSIM version + 9.6 or better with Tcl enabled, and it is necessary to have the Tcl + package "BLT" for the graphing window to work. IRSIM version + 9.6 has a "make" procedure which is exactly like magic's. It is + preferable to set CAD_ROOT to the same value for both programs + when doing "make config", so magic can find and automatically + load the IRSIM package when it needs to. + + The Tcl procedure "startirsim" loads and runs IRSIM. Since both + programs get loaded into the same interpreter, commands for both + magic and IRSIM can be executed on the command line. When IRSIM + is started with magic running, a number of commands are added to + the interpreter which communicate between the two packages. + Examples are "watchnode", "watchtime", and "drawnode". See the + "README" file in the IRSIM source for more information on running + IRSIM under magic and an explanation of the full set of commands + available. + +------------------------------------------------------------------ +Tcl-specific bugs and annoyances: +------------------------------------------------------------------- + +1) The Tcl prompt ("% ") appears at all times when the terminal is used + for command entry. The desired behavior is that the magic prompt + ">" (or "]" while DRC is pending) should appear when the cursor is + in a window, indicating that the input is accepting keyboard macros. + When outside of the window or after using the macro ":" to get to the + command-line entry from magic, the Tcl "%" prompt appears, indicating + that all valid Tcl commands may be entered at the prompt. + + Because it is not possible to detect if a partial Tcl command is on + the command line, it is only possible to enter part of a command in + the terminal window and complete the command in the magic window if + ":" is typed in the magic window to redirect keyboard input to the + terminal. + + The "tkcon" console-based version does not have this limitation and + operates more or less like the original magic prompt. + +2) Magic's original ".magic" file has control characters embedded. This + is the only magic command syntax which is illegal Tcl syntax. However, + magic 7.1 allows control characters to be written either as "^X" (two + characters, with a caret) or "Control_X". If the original .magic is + used (i.e., Tcl-magic is compiled and run, but not installed), + the embedded controls should be changed to printable ASCII format. + +3) There are routines which handle 8-bit pseudocolor mode by mapping + tk colors to magic colors by the magic "short name" as listed in + the dstyle file. This generally works well, except: 1) if the + cursor is inside a layout window when it comes up, the colormap + gets installed permanently; the window manager no longer reverts + to the original colormap when leaving the window. 2) there is + currently no routine to revert the console back to its original + colors and revert to the original colormap. 3) the colors could + use a bit of tweaking. + +------------------------------------------------------------------ diff --git a/TODO b/TODO new file mode 100644 index 00000000..6cb60002 --- /dev/null +++ b/TODO @@ -0,0 +1,8 @@ +I. Bugs to fix (also in magic-7.5 [stable]): + + 1. The "extresist" code only recognizes original "fet" types, not + the new "device" types in the extract file. + + 2. "plow" has been broken for some time. It should derive its rules + from the DRC decks (using the new routines that are meant for just + that sort of thing). diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..fbb9ea12 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +8.2.0 diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c new file mode 100644 index 00000000..11a8cbf4 --- /dev/null +++ b/calma/CalmaRdcl.c @@ -0,0 +1,1079 @@ +/* + * CalmaReadcell.c -- + * + * Input of Calma GDS-II stream format. + * Processing for cells. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdcl.c,v 1.5 2010/06/25 13:59:24 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "database/database.h" +#include "database/databaseInt.h" +#include "utils/malloc.h" +#include "utils/tech.h" +#include "cif/cif.h" +#include "cif/CIFint.h" +#include "cif/CIFread.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "textio/textio.h" +#include "calma/calmaInt.h" +#include "calma/calma.h" + +int calmaNonManhattan; + +extern HashTable calmaDefInitHash; + +/* forward declarations */ +int calmaElementSref(); +bool calmaParseElement(); + +/* Structure used when flattening the GDS hierarchy on read-in */ + +typedef struct { + Plane *plane; + Transform *trans; +} GDSCopyRec; + +/* Added by NP 8/11/04 */ + +/* + * ---------------------------------------------------------------------------- + * + * calmaSetPosition -- + * + * This routine sets the file pointer calmaInputFile to the start + * of the CellDefinition "sname". It starts the search from the + * current position and looks forward to find the Cell Definition + * named "sname". + * + * Results: + * Current position of file pointer before it jumps to the + * definition of cell "sname" (if it exists, otherwise, returns + * end-of-file). + * + * Side Effects: + * The file position is set to the definition of cell "sname". If + * "sname" does not exist in the GDS stream file, the pointer is + * set to the end of the file. + * + * ---------------------------------------------------------------------------- + */ + +off_t +calmaSetPosition(sname) + char *sname; +{ + off_t originalPos = 0, currentPos = 0; + int nbytes, rtype; + char *strname = NULL; + int strRecSize = 0; + bool found = FALSE; + + originalPos = ftello(calmaInputFile); + + while (feof(calmaInputFile) == 0) + { + do + { + READRH(nbytes, rtype); /* Read header */ + if (nbytes <= 0) break; + + /* Skip no of bytes in record header until + * we reach to next structure record. + */ + fseek(calmaInputFile, nbytes - CALMAHEADERLENGTH, SEEK_CUR); + } while (rtype != CALMA_BGNSTR); + if (nbytes <= 0) break; + + calmaReadStringRecord(CALMA_STRNAME, &strname); + if ((strcmp(sname, strname)) == 0) + { + /* If name if structure matches with given name, + * we got that Cell Defination. Set position of + * file to start of that structure. + */ + strRecSize = strlen(strname); + if (strRecSize & 01) strRecSize++; + fseek(calmaInputFile, -(nbytes + strRecSize + CALMAHEADERLENGTH), + SEEK_CUR); + freeMagic(strname); + return originalPos; + } + freeMagic(strname); + } + + // Ran out of file. It's possible that we were seeking ahead to a + // definition that called something that was defined between it and + // our previous position, so we will rewind the file and try again. + // If that doesn't work, then the cell is not defined in the file. + + if (originalPos != 0) + { + rewind(calmaInputFile); + calmaSetPosition(sname); + return originalPos; + } + + calmaReadError("Cell \"%s\" is used but not defined in this file.\n", sname); + + return originalPos; +} + +/* Added by NP 8/11/04 */ + +/* + * ---------------------------------------------------------------------------- + * + * calmaNextCell -- + * + * This routine sets the file pointer to next Cell Definition + * in the GDS stream. It goes only in the forward direction + * from the current position of the file pointer. + * + * Results: + * None. + * + * Side Effects: + * File pointer set to start of next Cell definition. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaNextCell() +{ + int nbytes, rtype; + + if (feof(calmaInputFile) == 0) + { + do + { + READRH(nbytes, rtype); /* Read header */ + if (nbytes <= 0) + { + /* We have reached the end of the file unexpectedly. + * try to set the file pointer somewhere sane, but + * it will likely dump an error later on. + */ + fseek(calmaInputFile, -(CALMAHEADERLENGTH), SEEK_END); + return; + } + + /* Skip no. of bytes in record header to reach the next + * structure record. + */ + fseek(calmaInputFile, nbytes - CALMAHEADERLENGTH, SEEK_CUR); + } while((rtype != CALMA_BGNSTR) && (rtype != CALMA_ENDLIB)); + + fseek(calmaInputFile, -nbytes, SEEK_CUR); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaExact -- + * + * When dictated to flatten small cells (e.g., vias which have been placed + * into their own cells to make use of GDS arrays), instead of calling + * CIFPaintCurrent(), we just transfer the planes of cifCurReadPlanes to + * the current cell, and swap the planes from the current cell into the + * pointer array for cifCurReadPlanes, so we don't have to free and + * reallocate any memory for the operation. Flag the cell as being a + * CIF cell, so that it can be destroyed after read-in and flattening. + * + * Results: + * Pointer to the plane structure created to hold the GDS data. + * + * Side Effects: + * Swaps the planes of cifReadCellDef with cifCurReadPlanes. + * + * ---------------------------------------------------------------------------- + */ + +Plane ** +calmaExact() +{ + int pNum; + Plane *newplane; + Plane **parray; + int gdsCopyPaintFunc(); /* Forward reference */ + + parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *)); + + for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + { + if (cifCurReadPlanes[pNum] != NULL) + { + GDSCopyRec gdsCopyRec; + + newplane = DBNewPlane((ClientData) TT_SPACE); + DBClearPaintPlane(newplane); + + gdsCopyRec.plane = newplane; + gdsCopyRec.trans = NULL; + DBSrPaintArea((Tile *)NULL, cifCurReadPlanes[pNum], &TiPlaneRect, + &DBAllButSpaceBits, gdsCopyPaintFunc, &gdsCopyRec); + parray[pNum] = newplane; + } + else + parray[pNum] = NULL; + } + + /* Clear out the current paint planes for the next cell */ + for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + DBClearPaintPlane(cifCurReadPlanes[pNum]); + + return parray; +} + + + +/* + * ---------------------------------------------------------------------------- + * + * calmaParseStructure -- + * + * Process a complete GDS-II structure (cell) including its closing + * CALMA_ENDSTR record. In the event of a syntax error, we skip + * ahead to the closing CALMA_ENDSTR, output a warning, and keep going. + * + * Results: + * TRUE if successful, FALSE if the next item in the input is + * not a structure. + * + * Side effects: + * Reads a new cell. + * Consumes input. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaParseStructure(filename) + char *filename; /* Name of the GDS file read */ +{ + static int structs[] = { CALMA_STRCLASS, CALMA_STRTYPE, -1 }; + int nbytes, rtype, nsrefs, osrefs, npaths; + char *strname = NULL, newname[CALMANAMELENGTH*2]; + HashEntry *he; + int suffix; + int mfactor; + off_t filepos; + bool was_called; + CellDef *def; + + /* Make sure this is a structure; if not, let the caller know we're done */ + PEEKRH(nbytes, rtype); + if (nbytes <= 0 || rtype != CALMA_BGNSTR) + return (FALSE); + + /* Read the structure name */ + if (!calmaSkipExact(CALMA_BGNSTR)) goto syntaxerror;; + if (!calmaReadStringRecord(CALMA_STRNAME, &strname)) goto syntaxerror; + TxPrintf("Reading \"%s\".\n", strname); + + if (CalmaReadOnly) + filepos = ftello(calmaInputFile); + + /* Set up the cell definition */ + he = HashFind(&calmaDefInitHash, strname); + if ((def = (CellDef *)HashGetValue(he)) != NULL) + { + if (def->cd_flags & CDPROCESSEDGDS) + { + /* If cell definition was marked as processed, then skip */ + /* (NOTE: This is probably a bad policy in general) */ + /* However, if post-ordering is set, then this cell was */ + /* probably just read earlier, so don't gripe about it. */ + + if (!CalmaPostOrder) + { + calmaReadError("Cell \"%s\" was already defined in this file.\n", + strname); + calmaReadError("Ignoring duplicate definition\n"); + } + calmaNextCell(); + return TRUE; + } + else + { + calmaReadError("Cell \"%s\" was already defined in this file.\n", + strname); + for (suffix = 1; HashGetValue(he) != NULL; suffix++) + { + (void) sprintf(newname, "%s_%d", strname, suffix); + he = HashFind(&calmaDefInitHash, newname); + } + calmaReadError("Giving this cell a new name: %s\n", newname); + strncpy(strname, newname, CALMANAMELENGTH*2); + } + } + cifReadCellDef = calmaFindCell(strname, &was_called); + DBCellClearDef(cifReadCellDef); + DBCellSetAvail(cifReadCellDef); + HashSetValue(he, cifReadCellDef); + cifCurReadPlanes = cifSubcellPlanes; + + /* Done with strname */ + if (strname != NULL) freeMagic(strname); + + /* For read-only cells, set flag in def */ + if (CalmaReadOnly) + cifReadCellDef->cd_flags |= CDVENDORGDS; + + /* Skip CALMA_STRCLASS or CALMA_STRTYPE */ + calmaSkipSet(structs); + + /* Initialize the hash table for layer errors */ + HashInit(&calmaLayerHash, 32, sizeof (CalmaLayerType) / sizeof (unsigned)); + + /* Body of structure: a sequence of elements */ + osrefs = nsrefs = 0; + npaths = 0; + calmaNonManhattan = 0; + while (calmaParseElement(filename, &nsrefs, &npaths)) + { + if (SigInterruptPending) + goto done; + if (nsrefs > osrefs && (nsrefs % 100) == 0) + TxPrintf(" %d uses\n", nsrefs); + osrefs = nsrefs; + calmaNonManhattan = 0; + } + + if (CalmaReadOnly) + { + /* Writing the file position into a string is slow, but */ + /* it prevents requiring special handling when printing */ + /* out the properties. */ + + char *fpcopy = (char *)mallocMagic(20); + char *fncopy = StrDup(NULL, filename); + sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos); + DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy); + + fpcopy = (char *)mallocMagic(20); + filepos = ftello(calmaInputFile); + sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos); + DBPropPut(cifReadCellDef, "GDS_END", (ClientData)fpcopy); + + DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)fncopy); + + /* Do not lock the cell, or else we can't save the */ + /* magic cell with its GDS pointers to disk. . . */ + /* cifReadCellDef->cd_flags |= CDNOEDIT; */ + } + + /* Make sure it ends with an ENDSTR record */ + if (!calmaSkipExact(CALMA_ENDSTR)) goto syntaxerror; + + /* + * Don't paint now, just keep the CIF planes, and flatten the + * cell by painting when instanced. But---if this cell was + * instanced before it was defined, then it can't be flattened. + */ + if (CalmaFlattenUses && (!was_called) && (npaths < 10) && (nsrefs == 0)) + { + /* To-do: If CDFLATGDS is already set, need to remove */ + /* existing planes and free memory. */ + + if (cifReadCellDef->cd_flags & CDFLATGDS) + { + Plane **cifplanes = (Plane **)cifReadCellDef->cd_client; + int pNum; + + for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + { + if (cifplanes[pNum] != NULL) + { + DBFreePaintPlane(cifplanes[pNum]); + TiFreePlane(cifplanes[pNum]); + } + } + freeMagic((char *)cifReadCellDef->cd_client); + cifReadCellDef->cd_client = (ClientData)CLIENTDEFAULT; + } + + TxPrintf("Saving contents of cell %s\n", cifReadCellDef->cd_name); + cifReadCellDef->cd_client = (ClientData) calmaExact(); + cifReadCellDef->cd_flags |= CDFLATGDS; + cifReadCellDef->cd_flags &= ~CDFLATTENED; + } + else + { + /* + * Do the geometrical processing and paint this material back into + * the appropriate cell of the database. + */ + + CIFPaintCurrent(); + } + + DBAdjustLabelsNew(cifReadCellDef, &TiPlaneRect, + (cifCurReadStyle->crs_flags & CRF_NO_RECONNECT_LABELS) ? 1 : 0); + DBReComputeBbox(cifReadCellDef); + + /* Don't bother to register with DRC if we're going to delete the */ + /* cell, or if the cell is read-only, or if "calma drcnocheck true" */ + /* has been issued. */ + + if (!CalmaReadOnly && !CalmaNoDRCCheck) + DRCCheckThis(cifReadCellDef, TT_CHECKPAINT, &cifReadCellDef->cd_bbox); + + DBWAreaChanged(cifReadCellDef, &cifReadCellDef->cd_bbox, + DBW_ALLWINDOWS, &DBAllButSpaceBits); + DBCellSetModified(cifReadCellDef, TRUE); + + /* + * Assign use-identifiers to all the cell uses. + * These identifiers are generated so as to be + * unique. + */ + DBGenerateUniqueIds(cifReadCellDef, FALSE); + cifReadCellDef->cd_flags |= CDPROCESSEDGDS; + +done: + HashKill(&calmaLayerHash); + return (TRUE); + + /* Syntax error: skip to CALMA_ENDSTR */ +syntaxerror: + HashKill(&calmaLayerHash); + return (calmaSkipTo(CALMA_ENDSTR)); +} + + +/* + * ---------------------------------------------------------------------------- + * + * calmaParseElement -- + * + * Process one element from a GDS-II structure, including its + * trailing CALMA_ENDEL record. In the event of a syntax error, we skip + * ahead to the closing CALMA_ENDEL, output a warning, and keep going. + * + * Results: + * TRUE if we processed an element, FALSE when we reach something that + * is not an element. In the latter case, we leave the non-element + * record unconsumed. + * + * Side effects: + * Consumes input. + * Depends on the kind of element encountered. + * If we process a SREF or AREF, increment *pnsrefs. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaParseElement(filename, pnsrefs, pnpaths) + char *filename; + int *pnsrefs, *pnpaths; +{ + static int node[] = { CALMA_ELFLAGS, CALMA_PLEX, CALMA_LAYER, + CALMA_NODETYPE, CALMA_XY, -1 }; + int nbytes, rtype, madeinst; + + READRH(nbytes, rtype); + if (nbytes < 0) + { + calmaReadError("Unexpected EOF.\n"); + return (FALSE); + } + + switch (rtype) + { + case CALMA_AREF: + case CALMA_SREF: + madeinst = calmaElementSref(filename); + if (madeinst >= 0) + (*pnsrefs) += madeinst; + break; + case CALMA_BOUNDARY: + calmaElementBoundary(); + (*pnpaths)++; + break; + case CALMA_BOX: + calmaElementBox(); + (*pnpaths)++; + break; + case CALMA_PATH: + calmaElementPath(); + (*pnpaths)++; + break; + case CALMA_TEXT: + calmaElementText(); + break; + case CALMA_NODE: + calmaReadError("NODE elements not supported: skipping.\n"); + calmaSkipSet(node); + break; + default: + UNREADRH(nbytes, rtype); + return (FALSE); + } + + return (calmaSkipTo(CALMA_ENDEL)); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaElementSref -- + * + * Process a structure reference (either CALMA_SREF or CALMA_AREF). + * + * Results: + * Returns 1 if an actual child instance was generated, 0 if + * only the child geometry was copied up, and -1 if an error + * occurred. + * + * Side effects: + * Consumes input. + * Adds a new cell use to the current def. + * + * ---------------------------------------------------------------------------- + */ + +int +calmaElementSref(filename) + char *filename; +{ + int nbytes, rtype, cols, rows, nref, n, i, savescale; + int xlo, ylo, xhi, yhi, xsep, ysep; + bool madeinst = FALSE; + char *sname = NULL; + bool isArray = FALSE; + Transform trans, tinv; + Point refarray[3], refunscaled[3], p; + CellUse *use; + CellDef *def; + int gdsCopyPaintFunc(); /* Forward reference */ + int gdsHasUses(); /* Forward reference */ + /* Added by NP */ + char *useid = NULL, *arraystr = NULL; + int propAttrType; + + /* Skip CALMA_ELFLAGS, CALMA_PLEX */ + calmaSkipSet(calmaElementIgnore); + + /* Read subcell name */ + if (!calmaReadStringRecord(CALMA_SNAME, &sname)) + return -1; + + /* + * Create a new cell use with this transform. If the + * cell being referenced doesn't exist, create it. + * Don't give it a use-id; we will do that only after + * we've placed all cells. + */ + + def = calmaLookCell(sname); + if (!def && (CalmaPostOrder || CalmaFlattenUses)) + { + /* Force the GDS parser to read the cell definition in + * post-order. If cellname "sname" is not defined before + * it is used, then read the cell definition by jumping + * to its position in the stream file, reading that + * instance, and then returning to the current file + * position. Note that this routine should be optimized + * for the likely case where many cells are defined at + * the end of the file; otherwise it will slow down the + * read process excessively for large GDS files by + * constantly moving from beginning to end of the file. + * + * Added by Nishit 8/16/2004 + */ + + off_t originalFilePos = calmaSetPosition(sname); + if (!feof(calmaInputFile)) + { + HashTable OrigCalmaLayerHash; + int crsMultiplier = cifCurReadStyle->crs_multiplier; + char *currentSname = cifReadCellDef->cd_name; + Plane **savePlanes; + + OrigCalmaLayerHash = calmaLayerHash; + savePlanes = calmaExact(); + + /* Read cell definition "sname". */ + calmaParseStructure(filename); + + /* Put things back to the way they were. */ + fseek(calmaInputFile, originalFilePos, SEEK_SET); + cifReadCellDef = calmaLookCell(currentSname); + def = calmaLookCell(sname); + cifCurReadPlanes = savePlanes; + calmaLayerHash = OrigCalmaLayerHash; + if (crsMultiplier != cifCurReadStyle->crs_multiplier) + { + int scalen, scaled; + if (crsMultiplier > cifCurReadStyle->crs_multiplier) + { + scalen = crsMultiplier / cifCurReadStyle->crs_multiplier; + scaled = 1; + } + else + { + scalen = 1; + scaled = cifCurReadStyle->crs_multiplier / crsMultiplier; + } + CIFScalePlanes(scalen, scaled, cifCurReadPlanes); + } + } + else + { + TxPrintf("Cell definition %s does not exist!\n", sname); + fseek(calmaInputFile, originalFilePos, SEEK_SET); + def = calmaFindCell(sname, NULL); + } + } + + if (!def) def = calmaFindCell(sname, NULL); + + if (DBIsAncestor(def, cifReadCellDef)) + { + calmaReadError("Cell %s is an ancestor of %s", + def->cd_name, cifReadCellDef->cd_name); + calmaReadError(" and can't be used as a subcell.\n"); + calmaReadError("(Use skipped)\n"); + return -1; + } + + /* Read subcell transform */ + if (!calmaReadTransform(&trans, sname)) + { + printf("Couldn't read transform.\n"); + return -1; + } + + /* Get number of columns and rows if array */ + cols = rows = 0; /* For half-smart compilers that complain otherwise. */ + READRH(nbytes, rtype); + if (nbytes < 0) return -1; + if (rtype == CALMA_COLROW) + { + isArray = TRUE; + READI2(cols); + READI2(rows); + xlo = 0; xhi = cols - 1; + ylo = 0; yhi = rows - 1; + if (feof(calmaInputFile)) return -1; + (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH - 4); + } + else + { + UNREADRH(nbytes, rtype); + } + + /* + * Read reference points. + * For subcells, there will be a single reference point. + * For arrays, there will be three; for their meanings, see below. + */ + READRH(nbytes, rtype) + if (nbytes < 0) return -1; + if (rtype != CALMA_XY) + { + calmaUnexpected(CALMA_XY, rtype); + return -1; + } + + /* Length of remainder of record */ + nbytes -= CALMAHEADERLENGTH; + + /* + * Read the reference points for the SREF/AREF. + * Scale down by cifCurReadStyle->crs_scaleFactor, but complain + * if they don't scale exactly. + * Make sure we only read three points. + */ + nref = nbytes / 8; + if (nref > 3) + { + calmaReadError("Too many points (%d) in SREF/AREF\n", nref); + nref = 3; + } + else if (nref < 1) + { + calmaReadError("Missing reference points in SREF/AREF (using 0,0)\n"); + refarray[0].p_x = refarray[0].p_y = 0; + refarray[1].p_x = refarray[1].p_y = 0; + refarray[2].p_x = refarray[2].p_y = 0; + } + + /* If this is a cell reference, then we scale to magic coordinates + * and place the cell in the magic database. However, if this is + * a cell to be flattened a la "gds flatten", then we keep the GDS + * coordinates, and don't scale to the magic database. + */ + + for (n = 0; n < nref; n++) + { + savescale = cifCurReadStyle->crs_scaleFactor; + calmaReadPoint(&refarray[n], 1); + refunscaled[n] = refarray[n]; // Save for CDFLATGDS cells + refarray[n].p_x = CIFScaleCoord(refarray[n].p_x, COORD_EXACT); + if (savescale != cifCurReadStyle->crs_scaleFactor) + { + for (i = 0; i < n; i++) + { + refarray[i].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor); + refarray[i].p_y *= (savescale / cifCurReadStyle->crs_scaleFactor); + } + savescale = cifCurReadStyle->crs_scaleFactor; + } + refarray[n].p_y = CIFScaleCoord(refarray[n].p_y, COORD_EXACT); + if (savescale != cifCurReadStyle->crs_scaleFactor) + { + for (i = 0; i < n; i++) + { + refarray[i].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor); + refarray[i].p_y *= (savescale / cifCurReadStyle->crs_scaleFactor); + } + refarray[n].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor); + } + + if (feof(calmaInputFile)) + return -1; + } + + /* Skip remainder */ + nbytes -= nref * 8; + if (nbytes) + (void) calmaSkipBytes(nbytes); + + /* Added by NP --- parse PROPATTR and PROPVALUE record types */ + /* The PROPATTR types 98 and 99 are defined internally to */ + /* magic and are used to retain information that cannot be */ + /* saved to the GDS file in any other manner. */ + + while (1) + { + READRH(nbytes, rtype); + if (nbytes < 0) return -1; + if (rtype == CALMA_PROPATTR) + { + READI2(propAttrType); + if (propAttrType == CALMA_PROP_USENAME) + { + if (!calmaReadStringRecord(CALMA_PROPVALUE, &useid)) + return -1; + } + else if (propAttrType == CALMA_PROP_ARRAY_LIMITS) + { + if (!calmaReadStringRecord(CALMA_PROPVALUE, &arraystr)) + return -1; + else if (arraystr) + { + int xl, xh, yl, yh; + if (sscanf(arraystr, "%d_%d_%d_%d", &xl, &xh, &yl, &yh) + != 4) + TxError("Malformed \"array\" property ignored: %s", + arraystr); + else + { + xlo = xl; + ylo = yl; + xhi = xh; + yhi = yh; + } + } + } + } + else + { + UNREADRH(nbytes, rtype); + break; + } + } + + /* Transform manipulation. Run through this twice if necessary. */ + /* The second time will use the unscaled transform to compute */ + /* the coordinates of saved geometry for a CD_FLATGDS cell. */ + + for (i = 0; i < 2; i++) + { + if (i == 1) + { + for (n = 0; n < nref; n++) + refarray[n] = refunscaled[n]; // Restore for CDFLATGDS cells + } + + /* + * Figure out the inter-element spacing of array elements, + * and also the translation part of the transform. + * The first reference point for both SREFs and AREFs is the + * translation of the use's or array's lower-left. + */ + + trans.t_c = refarray[0].p_x; + trans.t_f = refarray[0].p_y; + GeoInvertTrans(&trans, &tinv); + if (isArray) + { + /* + * The remaining two points for an array are displaced from + * the first reference point by: + * - the inter-column spacing times the number of columns, + * - the inter-row spacing times the number of rows. + */ + xsep = ysep = 0; + if (cols) + { + GeoTransPoint(&tinv, &refarray[1], &p); + if (p.p_x % cols) + { + n = (p.p_x + (cols+1)/2) / cols; + calmaReadError("# cols doesn't divide displacement ref pt\n"); + calmaReadError(" %d / %d -> %d\n", p.p_x, cols, n); + xsep = n; + } + else xsep = p.p_x / cols; + } + if (rows) + { + GeoTransPoint(&tinv, &refarray[2], &p); + if (p.p_y % rows) + { + n = (p.p_y + (rows+1)/2) / rows; + calmaReadError("# rows doesn't divide displacement ref pt\n"); + calmaReadError(" %d / %d -> %d\n", p.p_y, rows, n); + ysep = n; + } + ysep = p.p_y / rows; + } + } + + /* + * Check for cells which have *not* been marked for flattening + */ + + if (!(def->cd_flags & CDFLATGDS)) + { + use = DBCellNewUse(def, (useid) ? useid : (char *) NULL); + if (isArray) + DBMakeArray(use, &GeoIdentityTransform, xlo, ylo, xhi, yhi, xsep, ysep); + DBSetTrans(use, &trans); + DBPlaceCell(use, cifReadCellDef); + + break; // No need to do 2nd loop + } + + else if (i == 1) + { + Plane **gdsplanes = (Plane **)def->cd_client; + GDSCopyRec gdsCopyRec; + int pNum; + bool hasUses; + + // Mark cell as flattened (at least once) + def->cd_flags |= CDFLATTENED; + + for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + { + if (gdsplanes[pNum] != NULL) + { + gdsCopyRec.plane = cifCurReadPlanes[pNum]; + if (isArray) + { + Transform artrans; + int x, y; + + gdsCopyRec.trans = &artrans; + + for (x = 0; x < cols; x++) + for (y = 0; y < rows; y++) + { + GeoTransTranslate((x * xsep), (y * ysep), &trans, + &artrans); + DBSrPaintArea((Tile *)NULL, gdsplanes[pNum], + &TiPlaneRect, &DBAllButSpaceBits, + gdsCopyPaintFunc, &gdsCopyRec); + } + } + else + { + gdsCopyRec.trans = &trans; + DBSrPaintArea((Tile *)NULL, gdsplanes[pNum], &TiPlaneRect, + &DBAllButSpaceBits, gdsCopyPaintFunc, &gdsCopyRec); + } + } + } + } + + /* If cell has children in addition to paint to be flattened, */ + /* then also generate an instance of the cell. */ + + else + { + use = DBCellNewUse(def, (useid) ? useid : (char *) NULL); + if (isArray) + DBMakeArray(use, &GeoIdentityTransform, xlo, ylo, xhi, yhi, xsep, ysep); + DBSetTrans(use, &trans); + DBPlaceCell(use, cifReadCellDef); + madeinst = TRUE; + } + } + + /* Done with allocated variables */ + if (sname != NULL) freeMagic(sname); + if (useid != NULL) freeMagic(useid); + if (arraystr != NULL) freeMagic(arraystr); + + return ((def->cd_flags & CDFLATGDS) ? (madeinst ? 1 : 0) : 1); +} + + +/* Callback function for determining if a cell has at least one subcell */ + +int +gdsHasUses(use, clientdata) + CellUse *use; + ClientData clientdata; +{ + return 1; +} + +/* Callback function for copying paint from one CIF cell into another */ + +int +gdsCopyPaintFunc(tile, gdsCopyRec) + Tile *tile; + GDSCopyRec *gdsCopyRec; +{ + int pNum; + Rect sourceRect, targetRect; + Transform *trans = gdsCopyRec->trans; + Plane *plane = gdsCopyRec->plane; + + if (trans) + { + TiToRect(tile, &sourceRect); + GeoTransRect(trans, &sourceRect, &targetRect); + } + else + TiToRect(tile, &targetRect); + + DBNMPaintPlane(plane, TiGetTypeExact(tile), &targetRect, CIFPaintTable, + (PaintUndoInfo *)NULL); + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaFindCell -- + * + * This local procedure is used to find a cell in the subcell table, + * and create a new subcell if there isn't already one there. + * If a new subcell is created, its CDAVAILABLE is left FALSE. + * + * Results: + * The return value is a pointer to the definition for the + * cell whose name is 'name'. + * + * Side effects: + * A new CellDef may be created. + * + * ---------------------------------------------------------------------------- + */ + +CellDef * +calmaFindCell(name, was_called) + char *name; /* Name of desired cell */ + bool *was_called; /* If this cell is in the hash table, then it + * was instanced before it was defined. We + * need to know this so as to avoid flattening + * the cell if requested. + */ + +{ + HashEntry *h; + CellDef *def; + + h = HashFind(&CifCellTable, name); + if (HashGetValue(h) == 0) + { + def = DBCellLookDef(name); + if (def == NULL) + { + def = DBCellNewDef(name, (char *) NULL); + + /* + * Tricky point: call DBReComputeBbox here to make SURE + * that the cell has a valid bounding box. Otherwise, + * if the cell is used in a parent before being defined + * then it will cause a core dump. + */ + DBReComputeBbox(def); + } + HashSetValue(h, def); + if (was_called) *was_called = FALSE; + } + else + if (was_called) *was_called = TRUE; + return (CellDef *) HashGetValue(h); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaLookCell -- + * + * This procedure is like calmaFindCell above, but it will not + * create a new subcell if the named cell does not already exist. + * + * Results: + * The return value is a pointer to the definition for the + * cell whose name is 'name', or NULL if cell 'name' does + * not exist. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +CellDef * +calmaLookCell(name) + char *name; /* Name of desired cell */ +{ + HashEntry *h; + + h = HashLookOnly(&CifCellTable, name); + if (h == NULL) + return (CellDef *)NULL; + else + return (CellDef *)HashGetValue(h); +} + diff --git a/calma/CalmaRdio.c b/calma/CalmaRdio.c new file mode 100644 index 00000000..f70f19a8 --- /dev/null +++ b/calma/CalmaRdio.c @@ -0,0 +1,547 @@ +/* + * CalmaReadio.c -- + * + * Input of Calma GDS-II stream format. + * Low-level input. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdio.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "database/database.h" +#include "database/databaseInt.h" +#include "utils/malloc.h" +#include "utils/tech.h" +#include "cif/cif.h" +#include "cif/CIFint.h" +#include "cif/CIFread.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "textio/textio.h" +#include "calma/calmaInt.h" + +/* Forward declarations */ +bool calmaReadR8(); +bool calmaSkipBytes(); + + +/* + * ---------------------------------------------------------------------------- + * + * calmaReadTransform -- + * + * Read a CALMA_STRANS, CALMA_MAG, CALMA_ANGLE sequence and construct + * the corresponding geometric transform. + * + * Results: + * TRUE normally, FALSE on EOF or fatal syntax error. + * + * Side effects: + * Consumes input. + * Modifies the Transform pointed to by 'ptrans'. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaReadTransform(ptrans, name) + Transform *ptrans; /* Fill in this transform */ + char *name; /* Name of subcell (for errors) */ +{ + int nbytes, rtype, flags, angle; + double dangle; + double dmag; + Transform t; + + /* Default is the identity transform */ + *ptrans = GeoIdentityTransform; + + /* Is there any transform at all? */ + READRH(nbytes, rtype); + if (nbytes < 0) return (FALSE); + if (rtype != CALMA_STRANS) + { + UNREADRH(nbytes, rtype); + return (TRUE); + } + if (nbytes != 6) + { + (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH); + return (FALSE); + } + READI2(flags); + + /* Look for magnification and angle */ + READRH(nbytes, rtype); + if (nbytes < 0) return (FALSE); + if (rtype == CALMA_MAG) + { + if (nbytes != CALMAHEADERLENGTH + 8) + { + (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH); + return (FALSE); + } + if (!calmaReadR8(&dmag)) return (FALSE); + + if (dmag != (double)((int)(dmag + 0.5))) + { + calmaReadError("Non-integer magnification (%g) in transform\n", dmag); + calmaReadError("Rounding to %d.\n", (int)(dmag + 0.5)); + } + GeoScaleTrans(ptrans, (int)(dmag + 0.5), &t); + *ptrans = t; + } + else UNREADRH(nbytes, rtype); + + READRH(nbytes, rtype); + if (nbytes < 0) return (FALSE); + dangle = 0.0; + if (rtype == CALMA_ANGLE) + { + if (nbytes != CALMAHEADERLENGTH + 8) + { + (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH); + return (FALSE); + } + if (!calmaReadR8(&dangle)) return (FALSE); + } + else UNREADRH(nbytes, rtype); + + /* Make sure the angle is Manhattan */ + angle = (int) dangle; + while (angle < 0) angle += 360; + while (angle > 360) angle -= 360; + switch (angle) + { + case 360: + angle = 0; + break; + case 0: case 90: case 180: case 270: + break; + default: + calmaReadError("Non-Manhattan angle (%d) in transform\n", angle); + if (angle < 45) angle = 0; + else if (angle < 135) angle = 90; + else if (angle < 225) angle = 180; + else if (angle < 315) angle = 270; + else angle = 0; + calmaReadError(" Rounding to %d degrees.\n", angle); + } + + /* + * Construct the transform. + * Magic angles are clockwise; Calma angles are counterclockwise. + */ + if (flags & CALMA_STRANS_UPSIDEDOWN) + { + GeoTransTrans(ptrans, &GeoUpsideDownTransform, &t); + *ptrans = t; + } + switch (angle) + { + case 90: + GeoTransTrans(ptrans, &Geo270Transform, &t); + *ptrans = t; + break; + case 180: + GeoTransTrans(ptrans, &Geo180Transform, &t); + *ptrans = t; + break; + case 270: + GeoTransTrans(ptrans, &Geo90Transform, &t); + *ptrans = t; + break; + } + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaReadI2Record -- + * + * Read a record that should contain a two-byte integer. + * + * Results: + * TRUE on success, FALSE if the record type we read is not + * what we're expecting, or if it is of the wrong size. + * + * Side effects: + * Consumes input. + * Stores the result value in *pvalue (note that this is a normal + * int, even though we're reading only 16 bits from the input). + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaReadI2Record(type, pvalue) + int type; /* Type of record expected */ + int *pvalue; /* Store value here */ +{ + int nbytes, rtype, n; + + READRH(nbytes, rtype); + if (nbytes < 0) + goto eof; + if (type != rtype) + { + calmaUnexpected(type, rtype); + return (FALSE); + } + + /* Read the value */ + READI2(n); + if (feof(calmaInputFile)) goto eof; + *pvalue = n; + return (TRUE); + +eof: + calmaReadError("Unexpected EOF.\n"); + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaReadI4Record -- + * + * Read a record that should contain a four-byte integer. + * + * Results: + * TRUE on success, FALSE if the record type we read is not + * what we're expecting, or if it is of the wrong size. + * + * Side effects: + * Consumes input. + * Stores the result value in *pvalue. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaReadI4Record(type, pvalue) + int type; /* Type of record expected */ + int *pvalue; /* Store value here */ +{ + int nbytes, rtype, n; + + READRH(nbytes, rtype); + if (nbytes < 0) + goto eof; + if (type != rtype) + { + calmaUnexpected(type, rtype); + return (FALSE); + } + + /* Read the value */ + READI4(n); + if (feof(calmaInputFile)) goto eof; + *pvalue = n; + return (TRUE); + +eof: + calmaReadError("Unexpected EOF.\n"); + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaReadStringRecord -- + * + * Read a record that should contain an ASCII string. + * + * Results: + * TRUE on success, FALSE if the record type we read is not + * what we're expecting. + * + * Side effects: + * Consumes input. + * Allocates memory for string str (must be freed by the caller) + * Stores the result in the string pointed to by 'str'. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaReadStringRecord(type, str) + int type; + char **str; +{ + int nbytes, rtype; + + READRH(nbytes, rtype); + if (nbytes < 0) + goto eof; + + if (type != rtype) + { + calmaUnexpected(type, rtype); + return (FALSE); + } + + nbytes -= CALMAHEADERLENGTH; + *str = (char *) mallocMagic(nbytes + 1); + if (fread(*str, sizeof (char), nbytes, calmaInputFile) != nbytes) + goto eof; + + *(*str + nbytes) = '\0'; + return (TRUE); + +eof: + calmaReadError("Unexpected EOF.\n"); + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaReadR8 -- + * + * Read a single 8-byte real number in Calma stream format. + * Convert to internal double-precision format and store in + * the double pointed to by 'pd'. + * + * Results: + * TRUE on success, FALSE if EOF is encountered. + * + * Side effects: + * Consumes input. + * Stores the result in the *pd. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaReadR8(pd) + double *pd; /* Store result in *pd */ +{ + int i, exponent; + unsigned char dchars[8]; + double mantissa, d; + bool isneg; + + if (fread((char *) dchars, sizeof (char), sizeof dchars, + calmaInputFile) != sizeof dchars) + return (FALSE); + + /* Extract the sign and exponent */ + exponent = dchars[0]; + if (isneg = (exponent & 0x80)) + exponent &= ~0x80; + exponent -= 64; + + /* Construct the mantissa */ + mantissa = 0.0; + for (i = 7; i > 0; i--) + { + mantissa += dchars[i]; + mantissa /= 256.0; + } + + /* Now raise the mantissa to the exponent */ + d = mantissa; + if (exponent > 0) + { + while (exponent-- > 0) + d *= 16.0; + } + else if (exponent < 0) + { + while (exponent++ < 0) + d /= 16.0; + } + + /* Make it negative if necessary */ + if (isneg) + d = -d; + + *pd = d; + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaSkipSet -- + * + * Skip all records falling in a specified set of types. + * Leave the input stream positioned to the start of the first + * record not in the specified set. + * + * The array pointed to by 'skipwhat' contains the record types + * of all records to be skipped, terminated with -1. + * + * Results: + * None. + * + * Side effects: + * Consumes input. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaSkipSet(skipwhat) + int *skipwhat; +{ + int *skipp; + int nbytes, rtype; + + for (;;) + { + READRH(nbytes, rtype); + if (nbytes < 0) + return; + + for (skipp = skipwhat; *skipp >= 0; skipp++) + if (*skipp == rtype) + goto skipit; + + UNREADRH(nbytes, rtype); + break; + +skipit: + (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaSkipExact -- + * + * Skip a single stream record, which must be of the type 'type'. + * Leave the input positioned to the start of the record following + * this one. Complain if the record is not the one expected. + * + * Results: + * TRUE if successful, FALSE if we encountered an error and + * the caller should abort. + * + * Side effects: + * Consumes input. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaSkipExact(type) + int type; +{ + int nbytes, rtype; + + /* Eat up the record header */ + READRH(nbytes, rtype); + + if (nbytes < 0) + goto eof; + + /* Skip remainder of record */ + if (!calmaSkipBytes(nbytes - CALMAHEADERLENGTH)) + goto eof; + + if (rtype != type) + { + calmaUnexpected(type, rtype); + return (FALSE); + } + + return (TRUE); + +eof: + calmaReadError("Unexpected EOF.\n"); + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaSkipTo -- + * + * Skip to a record of a particular type. Leaves the input stream + * positioned AFTER the record whose type is given by 'what'. + * + * Results: + * TRUE if we found this record, FALSE if EOF was encountered. + * + * Side effects: + * Consumes input. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaSkipTo(what) + int what; +{ + int nbytes, rtype; + + do + { + READRH(nbytes, rtype); + if (nbytes < 0) + return (FALSE); + calmaSkipBytes(nbytes - CALMAHEADERLENGTH); + } while (rtype != what); + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaSkipBytes -- + * + * Skip 'nbytes' bytes from the input. + * WARNING: this procedure doesn't know about input saved via UNREADRH(), + * so if the caller wants this input to be discarded, it must call READRH() + * itself. + * + * Results: + * TRUE if successful, FALSE if EOF was encountered. + * + * Side effects: + * Consumes nbytes of input. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaSkipBytes(nbytes) + int nbytes; /* Skip this many bytes */ +{ + while (nbytes-- > 0) + if (getc(calmaInputFile) < 0) + return (FALSE); + + return (TRUE); +} diff --git a/calma/CalmaRdpt.c b/calma/CalmaRdpt.c new file mode 100644 index 00000000..70b8a27e --- /dev/null +++ b/calma/CalmaRdpt.c @@ -0,0 +1,1018 @@ +/* + * CalmaReadpaint.c -- + * + * Input of Calma GDS-II stream format. + * Processing of paint (paths, boxes, and boundaries) and text. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdpt.c,v 1.7 2010/08/25 17:33:54 tim Exp $"; +#endif /* not lint */ + +#include +#include /* for abs() */ +#include /* for strlen() */ +#include + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "database/database.h" +#include "database/databaseInt.h" +#include "utils/malloc.h" +#include "utils/tech.h" +#include "cif/cif.h" +#include "cif/CIFint.h" +#include "cif/CIFread.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "textio/textio.h" +#include "calma/calmaInt.h" +#include "calma/calma.h" + +extern int calmaNonManhattan; + +extern int CalmaPolygonCount; +extern HashTable calmaDefInitHash; + +extern void calmaLayerError(); +bool calmaReadPath(); + +/* + * ---------------------------------------------------------------------------- + * + * calmaInputRescale --- + * + * This routine does the same thing as CIFInputRescale(). However, + * the "gds flatten" option allows us to retain GDS layout + * information in the cd_client record of a cell def. If we + * change the GDS input scale factor, then all of these saved + * layouts need to be rescaled. + * + * Results: + * None. + * + * Side effects: + * Reallocates memory for layout planes in each of the cells in + * the database that have the CDFLATGDS flag set. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaInputRescale(n, d) + int n, d; +{ + HashEntry *h; + HashSearch hs; + CellDef *def; + + HashStartSearch(&hs); + while (TRUE) + { + h = HashNext(&CifCellTable, &hs); + if (h == NULL) break; + + def = (CellDef *) HashGetValue(h); + if (def == NULL) continue; /* shouldn't happen */ + if (def->cd_flags & CDFLATGDS) + { + /* Scale the GDS planes in this cell's cd_client record */ + Plane **gdsplanes = (Plane **)def->cd_client; + CIFScalePlanes(n, d, gdsplanes); + } + } + + CIFInputRescale(n, d); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaReadPoint --- + * + * Read a point from the input. + * We take care of scaling by calmaReadScale1/calmaReadScale2. + * Also take care of noting when the scaling results in a sub-integer + * value, and rescaling everything appropriately. "iscale" is an + * integer scaling value used to return values at, for instance, double + * the scale, as for a path centerline. + * + * Results: + * None. + * + * Side effects: + * The Point pointed to by parameter "p" is filled with the + * coordinates of the point. If a fractional integer is + * encountered, then everything in the GDS planes is rescaled + * to match. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaReadPoint(p, iscale) + Point *p; + int iscale; +{ + int rescale; + + READI4((p)->p_x); + p->p_x *= (calmaReadScale1 * iscale); + if ((iscale != 0) && (p->p_x % calmaReadScale2 != 0)) + { + rescale = calmaReadScale2 / FindGCF(calmaReadScale2, abs(p->p_x)); + if ((calmaReadScale1 * rescale) > CIFRescaleLimit) + { + calmaReadError("Warning: calma units at max scale; value rounded\n"); + if (p->p_x < 0) + p->p_x -= ((calmaReadScale2 - 1) >> 1); + else + p->p_x += (calmaReadScale2 >> 1); + } + else + { + calmaReadScale1 *= rescale; + calmaInputRescale(rescale, 1); + p->p_x *= rescale; + } + } + p->p_x /= calmaReadScale2; + + READI4((p)->p_y); + p->p_y *= (calmaReadScale1 * iscale); + if ((iscale != 0) && (p->p_y % calmaReadScale2 != 0)) + { + rescale = calmaReadScale2 / FindGCF(calmaReadScale2, abs(p->p_y)); + if ((calmaReadScale1 * rescale) > CIFRescaleLimit) + { + calmaReadError("Warning: calma units at max scale; value rounded\n"); + if (p->p_y < 0) + p->p_y -= ((calmaReadScale2 - 1) >> 1); + else + p->p_y += (calmaReadScale2 >> 1); + } + else + { + calmaReadScale1 *= rescale; + calmaInputRescale(rescale, 1); + p->p_x *= rescale; + p->p_y *= rescale; + } + } + p->p_y /= calmaReadScale2; +} + + +/* + * ---------------------------------------------------------------------------- + * + * calmaElementBoundary -- + * + * Read a polygon. + * + * Results: + * None. + * + * Side effects: + * Paints one or more rectangles into one of the CIF planes. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaElementBoundary() +{ + int dt, layer, ciftype; + CIFPath *pathheadp; + LinkedRect *rp; + Plane *plane; + CellUse *use; + CellDef *savedef, *newdef = NULL; + + /* Skip CALMA_ELFLAGS, CALMA_PLEX */ + calmaSkipSet(calmaElementIgnore); + + /* Read layer and data type */ + if (!calmaReadI2Record(CALMA_LAYER, &layer) + || !calmaReadI2Record(CALMA_DATATYPE, &dt)) + { + calmaReadError("Missing layer or datatype in boundary/box.\n"); + return; + } + + /* Set current plane */ + ciftype = CIFCalmaLayerToCifLayer(layer, dt, cifCurReadStyle); + if (ciftype < 0) + { + plane = NULL; + calmaLayerError("Unknown layer/datatype in boundary", layer, dt); + } + else + plane = cifCurReadPlanes[ciftype]; + + /* Read the path itself, building up a path structure */ + if (!calmaReadPath(&pathheadp, (plane == NULL) ? 0 : 1)) + { + if (plane != NULL) + calmaReadError("Error while reading path for boundary/box; ignored.\n"); + return; + } + + /* Note that calmaReadPath() may reallocate planes of cifCurReadPlanes */ + /* so we need to set it again. */ + if (ciftype >= 0) plane = cifCurReadPlanes[ciftype]; + + /* Convert the polygon to rectangles. */ + + if (CalmaSubcellPolygons && (calmaNonManhattan > 0)) + { + /* Place the polygon in its own subcell */ + char newname[] = "polygonXXXXX"; + HashEntry *he; + + savedef = cifReadCellDef; + + /* Make up name for cell */ + sprintf(newname + 7, "%05d", ++CalmaPolygonCount); + + he = HashFind(&calmaDefInitHash, newname); + if (!HashGetValue(he)) + { + newdef = calmaFindCell(newname, NULL); + cifReadCellDef = newdef; + DBCellClearDef(cifReadCellDef); + DBCellSetAvail(cifReadCellDef); + + /* cifEditCellPlanes is not used by the gds reader, so it's */ + /* available to be used to store the polygon. */ + + cifCurReadPlanes = cifEditCellPlanes; + if (plane != NULL) + plane = cifCurReadPlanes[ciftype]; + } + } + + rp = CIFPolyToRects(pathheadp, plane, CIFPaintTable, (PaintUndoInfo *)NULL); + CIFFreePath(pathheadp); + + /* Paint the rectangles (if any) */ + for (; rp != NULL ; rp = rp->r_next) + { + if (plane) + DBPaintPlane(plane, &rp->r_r, CIFPaintTable, (PaintUndoInfo *)NULL); + freeMagic((char *) rp); + } + + if (cifCurReadPlanes == cifEditCellPlanes) + { + CIFPaintCurrent(); + DBReComputeBbox(cifReadCellDef); + DRCCheckThis(cifReadCellDef, TT_CHECKPAINT, &cifReadCellDef->cd_bbox); + DBWAreaChanged(cifReadCellDef, &cifReadCellDef->cd_bbox, + DBW_ALLWINDOWS, &DBAllButSpaceBits); + DBCellSetModified(cifReadCellDef, TRUE); + DBGenerateUniqueIds(cifReadCellDef, FALSE); /* Is this necessary? */ + + cifCurReadPlanes = cifSubcellPlanes; + cifReadCellDef = savedef; + + use = DBCellNewUse(newdef, (char *)NULL); + DBSetTrans(use, &GeoIdentityTransform); + DBPlaceCell(use, cifReadCellDef); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaElementBox -- + * + * Read a box. + * This is an optimized version of calmaElementBoundary + * that handles rectangular polygons. These polygons each + * have five vertex points, with the first and last point + * being the same, and all sides parallel to one of the two + * coordinate axes. + * + * Results: + * None. + * + * Side effects: + * Paints one rectangle into one of the CIF planes. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaElementBox() +{ + int nbytes, rtype, npoints, savescale; + int dt, layer, ciftype; + Plane *plane; + Point p; + Rect r; + + /* Skip CALMA_ELFLAGS, CALMA_PLEX */ + calmaSkipSet(calmaElementIgnore); + + /* Read layer and data type */ + if (!calmaReadI2Record(CALMA_LAYER, &layer) + || !calmaReadI2Record(CALMA_BOXTYPE, &dt)) + { + calmaReadError("Missing layer or datatype in boundary/box.\n"); + return; + } + + /* Set current plane */ + ciftype = CIFCalmaLayerToCifLayer(layer, dt, cifCurReadStyle); + if (ciftype < 0) + { + calmaLayerError("Unknown layer/datatype in box", layer, dt); + return; + } + else plane = cifCurReadPlanes[ciftype]; + + /* + * Read the path itself. + * Since it is Manhattan, we can build our rectangle directly. + */ + r.r_xbot = r.r_ybot = INFINITY; + r.r_xtop = r.r_ytop = MINFINITY; + + /* Read the record header */ + READRH(nbytes, rtype); + if (nbytes < 0) + { + calmaReadError("EOF when reading box.\n"); + return; + } + if (rtype != CALMA_XY) + { + calmaUnexpected(CALMA_XY, rtype); + return; + } + + /* Read this many points (pairs of four-byte integers) */ + npoints = (nbytes - CALMAHEADERLENGTH) / 8; + if (npoints != 5) + { + calmaReadError("Box doesn't have 5 points.\n"); + (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH); + return; + } + while (npoints-- > 0) + { + savescale = calmaReadScale1; + calmaReadPoint(&p, 1); + if (savescale != calmaReadScale1) + { + int newscale = calmaReadScale1 / savescale; + r.r_xbot *= newscale; + r.r_xtop *= newscale; + r.r_ybot *= newscale; + r.r_ytop *= newscale; + } + if (p.p_x < r.r_xbot) r.r_xbot = p.p_x; + if (p.p_y < r.r_ybot) r.r_ybot = p.p_y; + if (p.p_x > r.r_xtop) r.r_xtop = p.p_x; + if (p.p_y > r.r_ytop) r.r_ytop = p.p_y; + } + + /* Paint the rectangle */ + DBPaintPlane(plane, &r, CIFPaintTable, (PaintUndoInfo *)NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaElementPath -- + * + * Read a centerline wire. + * + * Results: + * None. + * + * Side effects: + * May paint rectangles into CIF planes. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaElementPath() +{ + int nbytes, rtype, extend1, extend2; + int layer, dt, width, pathtype, ciftype, savescale; + int xmin, ymin, xmax, ymax, temp; + CIFPath *pathheadp, *pathp, *previousp; + Rect segment; + Plane *plane; + int first,last; + CellUse *use; + CellDef *savedef, *newdef = NULL; + + /* Skip CALMA_ELFLAGS, CALMA_PLEX */ + calmaSkipSet(calmaElementIgnore); + + /* Grab layer and datatype */ + if (!calmaReadI2Record(CALMA_LAYER, &layer)) return; + if (!calmaReadI2Record(CALMA_DATATYPE, &dt)) return; + + /* Describes the shape of the ends of the path */ + pathtype = CALMAPATH_SQUAREFLUSH; + PEEKRH(nbytes, rtype); + if (nbytes > 0 && rtype == CALMA_PATHTYPE) + if (!calmaReadI2Record(CALMA_PATHTYPE, &pathtype)) return; + + if (pathtype != CALMAPATH_SQUAREFLUSH && pathtype != CALMAPATH_SQUAREPLUS) + { + calmaReadError("Warning: pathtype %d unsupported (ignored).\n", pathtype); + pathtype = CALMAPATH_SQUAREFLUSH; + } + + /* + * Width of this path. + * Allow zero-width paths; we will ignore them later. + */ + width = 0; + PEEKRH(nbytes, rtype) + if (nbytes > 0 && rtype == CALMA_WIDTH) + { + if (!calmaReadI4Record(CALMA_WIDTH, &width)) + { + calmaReadError("Error in reading WIDTH in calmaElementPath()\n") ; + return; + } + } + width *= calmaReadScale1; + if (width % calmaReadScale2 != 0) + calmaReadError("Wire width snapped to nearest integer boundary.\n"); + + width /= calmaReadScale2; + + /* Handle BGNEXTN, ENDEXTN */ + extend1 = extend2 = 0; + PEEKRH(nbytes, rtype); + if (nbytes > 0 && rtype == CALMA_BGNEXTN) + { + if (!calmaReadI4Record(CALMA_BGNEXTN, &extend1)) + calmaReadError("Error in reading BGNEXTN in path (ignored)\n") ; + else + { + extend1 *= calmaReadScale1; + if (extend1 % calmaReadScale2 != 0) + calmaReadError("Wire extension snapped to nearest integer boundary.\n"); + extend1 *= 2; + extend1 /= calmaReadScale2; + } + } + + PEEKRH(nbytes, rtype); + if (nbytes > 0 && rtype == CALMA_ENDEXTN) + { + if (!calmaReadI4Record(CALMA_ENDEXTN, &extend2)) + calmaReadError("Error in reading ENDEXTN in path (ignored)\n") ; + else + { + extend2 *= calmaReadScale1; + if (extend2 % calmaReadScale2 != 0) + calmaReadError("Wire extension snapped to nearest integer boundary.\n"); + extend2 *= 2; + extend2 /= calmaReadScale2; + } + } + + /* Read the points in the path */ + savescale = calmaReadScale1; + if (!calmaReadPath(&pathheadp, 2)) + { + calmaReadError("Improper path; ignored.\n"); + return; + } + if (savescale != calmaReadScale1) + { + width *= (calmaReadScale1 / savescale); + extend1 *= (calmaReadScale1 / savescale); + extend2 *= (calmaReadScale1 / savescale); + } + + /* Create path end extensions */ + + if (extend1 > 0) + { + if (pathheadp->cifp_x > pathheadp->cifp_next->cifp_x) + pathheadp->cifp_x += extend1; + else if (pathheadp->cifp_x < pathheadp->cifp_next->cifp_x) + pathheadp->cifp_x -= extend1; + + if (pathheadp->cifp_y > pathheadp->cifp_next->cifp_y) + pathheadp->cifp_y += extend1; + else if (pathheadp->cifp_y < pathheadp->cifp_next->cifp_y) + pathheadp->cifp_y -= extend1; + } + + if (extend2 > 0) + { + pathp = pathheadp; + while (pathp && pathp->cifp_next && pathp->cifp_next->cifp_next) + pathp = pathp->cifp_next; + + if (pathp && pathp->cifp_next) + { + if (pathp->cifp_x > pathp->cifp_next->cifp_x) + pathp->cifp_next->cifp_x -= extend2; + else if (pathp->cifp_x < pathp->cifp_next->cifp_x) + pathp->cifp_next->cifp_x += extend2; + + if (pathp->cifp_y > pathp->cifp_next->cifp_y) + pathp->cifp_next->cifp_y -= extend2; + else if (pathp->cifp_y < pathp->cifp_next->cifp_y) + pathp->cifp_next->cifp_y += extend2; + } + } + + /* Don't process zero-width paths any further */ + if (width <= 0) + { + CIFFreePath(pathheadp); + return; + } + + /* Make sure we know about this type */ + ciftype = CIFCalmaLayerToCifLayer(layer, dt, cifCurReadStyle); + if (ciftype < 0) + { + calmaLayerError("Unknown layer/datatype in path", layer, dt); + CIFFreePath(pathheadp); + } + else + { + plane = cifCurReadPlanes[ciftype]; + + if (CalmaSubcellPolygons && (calmaNonManhattan > 0)) + { + /* Place the polygon in its own subcell */ + char newname[] = "polygonXXXXX"; + HashEntry *he; + + savedef = cifReadCellDef; + + /* Make up name for cell */ + sprintf(newname + 7, "%05d", ++CalmaPolygonCount); + + he = HashFind(&calmaDefInitHash, newname); + if (!HashGetValue(he)) + { + newdef = calmaFindCell(newname, NULL); + cifReadCellDef = newdef; + DBCellClearDef(cifReadCellDef); + DBCellSetAvail(cifReadCellDef); + + /* cifEditCellPlanes is not used by the gds reader, so it's */ + /* available to be used to store the polygon. */ + + cifCurReadPlanes = cifEditCellPlanes; + if (plane != NULL) + plane = cifCurReadPlanes[ciftype]; + } + } + + CIFPaintWirePath(pathheadp, width, + (pathtype == CALMAPATH_SQUAREFLUSH) ? FALSE : TRUE, + plane, CIFPaintTable, (PaintUndoInfo *)NULL); + + if (cifCurReadPlanes == cifEditCellPlanes) + { + CIFPaintCurrent(); + DBReComputeBbox(cifReadCellDef); + DRCCheckThis(cifReadCellDef, TT_CHECKPAINT, &cifReadCellDef->cd_bbox); + DBWAreaChanged(cifReadCellDef, &cifReadCellDef->cd_bbox, + DBW_ALLWINDOWS, &DBAllButSpaceBits); + DBCellSetModified(cifReadCellDef, TRUE); + DBGenerateUniqueIds(cifReadCellDef, FALSE); /* Is this necessary? */ + + cifCurReadPlanes = cifSubcellPlanes; + cifReadCellDef = savedef; + + use = DBCellNewUse(newdef, (char *)NULL); + DBSetTrans(use, &GeoIdentityTransform); + DBPlaceCell(use, cifReadCellDef); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaElementText -- + * + * Read labels. + * + * Results: + * None. + * + * Side effects: + * Add labels to our label list. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaElementText() +{ + static int ignore[] = { CALMA_PATHTYPE, CALMA_WIDTH, -1 }; + char *textbody = NULL; + int nbytes, rtype; + int layer, textt, cifnum; + TileType type; + Rect r; + unsigned short textpres; + double dval; + int size, angle, font, pos; + + /* Skip CALMA_ELFLAGS, CALMA_PLEX */ + calmaSkipSet(calmaElementIgnore); + + /* Grab layer and texttype */ + if (!calmaReadI2Record(CALMA_LAYER, &layer)) return; + if (!calmaReadI2Record(CALMA_TEXTTYPE, &textt)) return; + cifnum = CIFCalmaLayerToCifLayer(layer, textt, cifCurReadStyle); + if (cifnum < 0) + { + if(cifCurReadStyle->crs_flags & CRF_IGNORE_UNKNOWNLAYER_LABELS) + type = -1; + else { + calmaLayerError("Label on unknown layer/datatype", layer, textt); + type = TT_SPACE; + } + } + else type = cifCurReadStyle->crs_labelLayer[cifnum]; + + font = -1; + angle = 0; + + /* Default size is 1um */ + size = (int)((800 * cifCurReadStyle->crs_multiplier) + / cifCurReadStyle->crs_scaleFactor); + /* Default position is bottom-right (but what the spec calls "top-left"!) */ + pos = GEO_SOUTHEAST; + + /* Parse presentation and magnitude/angle part of transform */ + /* Skip pathtype and width */ + + PEEKRH(nbytes, rtype); + if (nbytes > 0 && rtype == CALMA_PRESENTATION) + { + calmaReadI2Record(CALMA_PRESENTATION, &textpres); + font = (textpres >> 4) & 0x03; + switch (textpres & 0x000f) + { + case 0x000a: + pos = GEO_NORTHWEST; + break; + case 0x0006: + pos = GEO_WEST; + break; + case 0x0002: + pos = GEO_SOUTHWEST; + break; + case 0x0009: + pos = GEO_NORTH; + break; + case 0x0005: + pos = GEO_CENTER; + break; + case 0x0001: + pos = GEO_SOUTH; + break; + case 0x0008: + pos = GEO_NORTHEAST; + break; + case 0x0004: + pos = GEO_EAST; + break; + case 0x0000: + pos = GEO_SOUTHEAST; + break; + } + } + else if (nbytes > 0 && rtype != CALMA_STRANS) + calmaSkipSet(ignore); + + READRH(nbytes, rtype); + if (nbytes > 0 && rtype == CALMA_STRANS) + { + /* We don't handle the strans record for text */ + calmaSkipBytes(nbytes - CALMAHEADERLENGTH); + + READRH(nbytes, rtype); + if (nbytes > 0 && rtype == CALMA_MAG) + { + calmaReadR8(&dval); + /* Assume that MAG is the label size in microns */ + /* "size" is the label size in 8 * (database units) */ + size = (int)((dval * 800 * cifCurReadStyle->crs_multiplier) + / cifCurReadStyle->crs_scaleFactor); + } + else + UNREADRH(nbytes, rtype); + + READRH(nbytes, rtype); + if (nbytes > 0 && rtype == CALMA_ANGLE) + { + calmaReadR8(&dval); + angle = (int)dval; + } + else + UNREADRH(nbytes, rtype); + } + else + UNREADRH(nbytes, rtype); + + + /* Coordinates of text */ + READRH(nbytes, rtype) + if (nbytes < 0) return; + if (rtype != CALMA_XY) + { + calmaUnexpected(CALMA_XY, rtype); + return; + } + nbytes -= CALMAHEADERLENGTH; + if (nbytes < 8) + { + calmaReadError("Not enough bytes in point record.\n"); + } + else + { + calmaReadPoint(&r.r_ll, 1); + nbytes -= 8; + } + if (!calmaSkipBytes(nbytes)) return; + r.r_ll.p_x /= cifCurReadStyle->crs_scaleFactor; + r.r_ll.p_y /= cifCurReadStyle->crs_scaleFactor; + r.r_ur = r.r_ll; + + /* String itself */ + if (!calmaReadStringRecord(CALMA_STRING, &textbody)) return; + + /* Eliminate characters not in the official GDSII string format set. */ + + /* NOTE: Disabling this 10/3/2014. I can think of no reason that + * other ASCII characters may not be parsed out of a non-compliant + * GDS file. If we want to generate GDS-compliant output, there's + * a flag for that in the "cifoutput" section of the techfile. + */ + +#if 0 + + { + static bool algmsg = FALSE; + bool changed = FALSE; + char *cp; + char *savstring; + for (cp = textbody; *cp; cp++) + { + if (*cp <= ' ' | *cp > '~') + { + if (!changed) + { + savstring = StrDup(NULL, textbody); + changed = TRUE; + } + if (*cp == '\r' && *(cp+1) == '\0') + *cp = '\0'; + else if (*cp == '\r') + *cp = '_'; + else if (*cp == ' ') + *cp = '_'; + else + *cp = '?'; + } + } + if (changed) { + calmaReadError("Warning: improper characters fixed in label '%s'\n", + savstring); + if (!algmsg) { + algmsg = TRUE; + calmaReadError(" (algorithm used: trailing dropped, " + " and ' ' changed to '_', \n" + " other non-printables changed to '?')\n"); + } + calmaReadError(" modified label is '%s'\n", textbody); + freeMagic(savstring); + } + } + +#endif /* 0 */ + + /* Place the label */ + if (strlen(textbody) == 0) + { + calmaReadError("Warning: Ignoring empty string label at (%d, %d)\n", + r.r_ll.p_x * cifCurReadStyle->crs_scaleFactor, + r.r_ll.p_y * cifCurReadStyle->crs_scaleFactor); + } + else if (type < 0) + { + calmaReadError("Warning: label \"%s\" at (%d, %d) is on unhandled" + " layer:purpose pair %d:%d and will be discarded.\n", textbody, + r.r_ll.p_x * cifCurReadStyle->crs_scaleFactor, + r.r_ll.p_y * cifCurReadStyle->crs_scaleFactor, layer, textt); + } + else + { + int flags, i; + + /* Find the style layer record corresponding to the label type */ + layer = -1; + for (i = 0; i < cifCurReadStyle->crs_nLayers; i++) + if (cifCurReadStyle->crs_layers[i]->crl_magicType == type) { + layer = i; + break; + } + + if (layer >= 0 && (cifCurReadStyle->crs_layers[layer]->crl_flags + & CIFR_TEXTLABELS)) + flags = LABEL_STICKY; + else if (cifCurReadStyle->crs_flags & CRF_NO_RECONNECT_LABELS) + flags = LABEL_STICKY; + else + flags = 0; + + if (font < 0) + DBPutLabel(cifReadCellDef, &r, pos, textbody, type, flags); + else + DBPutFontLabel(cifReadCellDef, &r, font, size, angle, + &GeoOrigin, pos, textbody, type, flags); + } + + /* done with textbody */ + if (textbody != NULL) freeMagic(textbody); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaReadPath -- + * + * This procedure parses a Calma path, which is an XY record + * containing one or more points. "iscale" is an internal + * scaling, usually 1, but is 2 for paths specified on a + * centerline, to avoid roundoff errors. + * + * Results: + * TRUE is returned if the path was parsed successfully, + * FALSE otherwise. + * + * Side effects: + * Modifies the parameter pathheadpp to point to the path + * that is constructed. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaReadPath(pathheadpp, iscale) + CIFPath **pathheadpp; + int iscale; +{ + CIFPath path, *pathtailp, *newpathp; + int nbytes, rtype, npoints, savescale; + bool nonManhattan = FALSE; + + *pathheadpp = (CIFPath *) NULL; + pathtailp = (CIFPath *) NULL; + path.cifp_next = (CIFPath *) NULL; + + /* Read the record header */ + READRH(nbytes, rtype); + if (nbytes < 0) + { + calmaReadError("EOF when reading path.\n"); + return (FALSE); + } + if (rtype != CALMA_XY) + { + calmaUnexpected(CALMA_XY, rtype); + return (FALSE); + } + + /* Read this many points (pairs of four-byte integers) */ + npoints = (nbytes - CALMAHEADERLENGTH) / 8; + while (npoints--) + { + savescale = calmaReadScale1; + calmaReadPoint(&path.cifp_point, iscale); + if (savescale != calmaReadScale1) + { + CIFPath *phead = *pathheadpp; + int newscale = calmaReadScale1 / savescale; + while (phead != NULL) + { + phead->cifp_x *= newscale; + phead->cifp_y *= newscale; + phead = phead->cifp_next; + } + } + if (ABS(path.cifp_x) > 0x0fffffff || ABS(path.cifp_y) > 0x0fffffff) { + calmaReadError("Warning: Very large point in path: (%d, %d)\n", + path.cifp_x, path.cifp_y); + } + if (feof(calmaInputFile)) + { + CIFFreePath(*pathheadpp); + return (FALSE); + } + + if (iscale != 0) + { + newpathp = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath))); + *newpathp = path; + + if (*pathheadpp) + { + /* + * Check that this segment is Manhattan. If not, remember the + * fact and later introduce extra stair-steps to make the path + * Manhattan. We don't do the stair-step introduction here for + * two reasons: first, the same code is also used by the Calma + * module, and second, it is important to know which side of + * the polygon is the outside when generating the stair steps. + */ + if (pathtailp->cifp_x != newpathp->cifp_x + && pathtailp->cifp_y != (newpathp->cifp_y)) + { + if (!nonManhattan) + { + calmaNonManhattan++; + nonManhattan = TRUE; + } + } + pathtailp->cifp_next = newpathp; + } + else *pathheadpp = newpathp; + pathtailp = newpathp; + } + } + return (*pathheadpp != NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaLayerError -- + * + * This procedure is called when (layer, dt) doesn't map to a valid + * Calma layer. The first time this procedure is called for a given + * (layer, dt) pair, we print an error message; on subsequent times, + * no error message is printed. + * + * Results: + * None. + * + * Side effects: + * An error message is printed if the first time for this (layer, dt). + * Adds an entry to the HashTable calmaLayerHash if one is not + * already present for this (layer, dt) pair. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaLayerError(mesg, layer, dt) + char *mesg; + int layer; + int dt; +{ + CalmaLayerType clt; + HashEntry *he; + + clt.clt_layer = layer; + clt.clt_type = dt; + he = HashFind(&calmaLayerHash, (char *) &clt); + if (HashGetValue(he) == NULL) + { + HashSetValue(he, (ClientData) 1); + calmaReadError("%s, layer=%d type=%d\n", mesg, layer, dt); + } +} diff --git a/calma/CalmaRead.c b/calma/CalmaRead.c new file mode 100644 index 00000000..534fe2f6 --- /dev/null +++ b/calma/CalmaRead.c @@ -0,0 +1,494 @@ +/* + * CalmaRead.c -- + * + * Input of Calma GDS-II stream format. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRead.c,v 1.3 2010/06/24 12:37:15 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "database/database.h" +#include "database/databaseInt.h" +#include "utils/malloc.h" +#include "utils/tech.h" +#include "cif/cif.h" +#include "cif/CIFint.h" +#include "cif/CIFread.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "textio/textio.h" +#include "calma/calmaInt.h" +#include "commands/commands.h" /* for CmdGetRootPoint */ +#include "utils/undo.h" + +/* Globals for Calma reading */ +FILE *calmaInputFile = NULL; /* Read from this stream */ +FILE *calmaErrorFile = NULL; /* Write error output here */ +bool CalmaSubcellPolygons = FALSE; /* Put non-Manhattan polygons + * in their own subcells. + */ +int CalmaPolygonCount; +bool CalmaFlattenUses = FALSE; /* If TRUE, small cells in the input + * stream are flattened when encountered + * as uses. This improves magic's + * performance when handling contacts + * saved as subcell arrays. + */ +bool CalmaReadOnly = FALSE; /* Set files to read-only and + * retain file position information + * so cells can be written verbatim. + */ +bool CalmaNoDRCCheck = FALSE; /* If TRUE, don't mark cells as needing + * a DRC check; they will be assumed + * DRC clean. + */ +bool CalmaPostOrder = FALSE; /* If TRUE, forces the GDS parser to + * read cells in post-order. It is + * necessary, e.g., when we need to + * flatten cells that are contact cuts. + * Added by Nishit 8/16/2004 + */ +extern void calmaUnexpected(); + +bool calmaParseUnits(); + +/* + * Scaling. + * Multiply all coordinates by calmaReadScale1, then divide them + * by calmaReadScale2 in order to get coordinates in centimicrons. + */ +int calmaReadScale1; +int calmaReadScale2; + +int calmaTotalErrors; + +/* + * Lookahead: calmaLApresent is TRUE when calmaLAnbytes and calmaLArtype + * are set to the record header of a record we just ungot. + */ +bool calmaLApresent; /* TRUE if lookahead input waiting */ +int calmaLAnbytes; /* # bytes in record (from header) */ +int calmaLArtype; /* Record type */ + +/* + * Hash table for errors, indexed by (layer, datatype). + * The corresponding entry in this table is created whenever + * a (layer, datatype) is seen that we don't recognize, so + * we don't output an error message more than once. + */ +HashTable calmaLayerHash; + +/* + * Hash table to keep track of all defs that have appeared + * in this file. Indexed by cell def name. + */ +HashTable calmaDefInitHash; + +/* Common stuff to ignore */ +int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 }; + +/* + * ---------------------------------------------------------------------------- + * + * CalmaReadFile -- + * + * Read an entire GDS-II stream format library from the open FILE 'file'. + * + * Results: + * None. + * + * Side effects: + * May modify the contents of cifReadCellDef by painting or adding + * new uses or labels. May also create new CellDefs. + * + * ---------------------------------------------------------------------------- + */ + +void +CalmaReadFile(file, filename) + FILE *file; /* File from which to read Calma */ + char *filename; /* The real name of the file read */ +{ + int k, version; + char *libname = NULL; + MagWindow *mw; + static int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS, + CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE, + CALMA_STYPTABLE, CALMA_GENERATIONS, -1 }; + static int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME, + CALMA_LIBSECUR, -1 }; + + /* We will use full cell names as keys in this hash table */ + CIFReadCellInit(0); + + if (CIFWarningLevel == CIF_WARN_REDIRECT) + { + if (CIFErrorFilename == NULL) + calmaErrorFile = NULL; + else + calmaErrorFile = PaOpen(CIFErrorFilename, "w", (char *)NULL, ".", + (char *)NULL, (char **)NULL); + } + + if (cifCurReadStyle == NULL) + { + TxError("Don't know how to read GDS-II:\n"); + TxError("Nothing in \"cifinput\" section of tech file.\n"); + return; + } + TxPrintf("Warning: Calma reading is not undoable! I hope that's OK.\n"); + UndoDisable(); + + calmaTotalErrors = 0; + CalmaPolygonCount = 0; + + HashInit(&calmaDefInitHash, 32, 0); + calmaLApresent = FALSE; + calmaInputFile = file; + + /* Read the GDS-II header */ + if (!calmaReadI2Record(CALMA_HEADER, &version)) goto done; + if (version < 600) + TxPrintf("Library written using GDS-II Release %d.0\n", version); + else + TxPrintf("Library written using GDS-II Release %d.%d\n", + version / 100, version % 100); + if (!calmaSkipExact(CALMA_BGNLIB)) goto done; + calmaSkipSet(skipBeforeLib); + if (!calmaReadStringRecord(CALMA_LIBNAME, &libname)) goto done; + if ((libname != NULL) && (libname[0] != '\0')) + { + /* Avoid generating a magic name with spaces in it. . . */ + /* (added by Mike Godfrey, 7/17/05) */ + + for (k = 0; k < strlen(libname); k++) + if (libname[k] == ' ') + libname[k] = '_'; + TxPrintf("Library name: %s\n", libname); + } + + /* Skip the reflibs, fonts, etc. cruft */ + calmaSkipSet(hdrSkip); + + /* Set the scale factors */ + if (!calmaParseUnits()) goto done; + + /* Main body of GDS-II input */ + while (calmaParseStructure(filename)) + if (SigInterruptPending) + goto done; + (void) calmaSkipExact(CALMA_ENDLIB); + +done: + + /* Added by Nishit, Sept. 2004---Load cell read from GDS */ + /* stream file to the magic layout window. If this fails */ + /* then we do the original action and don't do a load into */ + /* the window. Note that this follows the Magic GDS output */ + /* convention of giving the library the name of the */ + /* top-level cell, so magic-produced GDS can be read back */ + /* with the expected cell appearing in the layout window. */ + + if (libname != NULL) + { + mw = CmdGetRootPoint((Point *)NULL, (Rect *)NULL); + if (mw == NULL) + windCheckOnlyWindow(&mw, DBWclientID); + if (mw != NULL) + { + if (calmaLookCell(libname, NULL) != (CellDef *)NULL) + DBWloadWindow(mw, libname, FALSE); + } + freeMagic(libname); + } + + CIFReadCellCleanup(1); + HashKill(&calmaDefInitHash); + UndoEnable(); + + if (calmaErrorFile != NULL) fclose(calmaErrorFile); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaParseUnits -- + * + * Process the CALMA_UNITS record that sets the relationship between + * user units (stored in the stream file) and centimicrons. + * + * Results: + * TRUE if successful, FALSE if we encountered an error and + * the caller should abort. + * + * Side effects: + * Consumes input. + * Sets calmaReadScale1 to the number of centimicrons per user + * unit, and calmaReadScale2 to 1, unless calmaReadScale1 would be + * less than 1, in which case we set calmaReadScale1 to 1 and + * calmaReadScale2 to 1/calmaReadScale1. + * + * NOTE: + * We don't care about user units, only database units. The + * GDS-II stream specifies the number of meters per database + * unit, which we use to compute the number of centimicrons + * per database unit. Since database units are floating point, + * there is a possibility of roundoff unless the number of + * centimicrons per user unit is an integer value. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaParseUnits() +{ + int nbytes, rtype; + double metersPerDBUnit; + double userUnitsPerDBUnit; + double cuPerDBUnit; + + READRH(nbytes, rtype); +#ifdef lint + nbytes = nbytes; +#endif /* lint */ + + if (rtype != CALMA_UNITS) + { + calmaUnexpected(CALMA_UNITS, rtype); + return (FALSE); + } + + /* Skip user units per database unit */ + if (!calmaReadR8(&userUnitsPerDBUnit)) return (FALSE); + + /* Read meters per database unit */ + if (!calmaReadR8(&metersPerDBUnit)) return (FALSE); + +#ifdef notdef + TxPrintf("1 database unit equals %e user units\n", userUnitsPerDBUnit); + TxPrintf("1 database unit equals %e meters\n", metersPerDBUnit); + TxPrintf("1 user unit equals %e database units\n", 1.0/userUnitsPerDBUnit); + TxPrintf("1 meter equals %e database units\n", 1.0/metersPerDBUnit); +#endif /* notdef */ + + /* Meters per database unit (1.0e8 corresponds to traditional centimicrons) */ + cuPerDBUnit = metersPerDBUnit * 1.0e8 * cifCurReadStyle->crs_multiplier; + + /* + * Multiply database units by calmaReadScale1, then divide + * by calmaReadScale2 to get CIF units. The current scheme + * relies entirely on calmaReadScale1 being an integer. + */ + if (cuPerDBUnit >= 1.0) + { + calmaReadScale1 = (int)(cuPerDBUnit + 0.5); + calmaReadScale2 = 1; + } + else + { + cuPerDBUnit = 1.0 / cuPerDBUnit; + calmaReadScale1 = 1; + calmaReadScale2 = (int)(cuPerDBUnit + 0.5); + } +#ifdef notdef + TxPrintf("All units to be scaled by %d/%d\n", calmaReadScale1, calmaReadScale2); +#endif /* notdef */ + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaReadError -- + * + * This procedure is called to print out error messages during + * Calma file reading. + * + * Results: + * None. + * + * Side effects: + * An error message is printed. + * + * Note: + * You can add more arguments if 10 turns out not to be enough. + * + * ---------------------------------------------------------------------------- + */ + +void + /*VARARGS1*/ +calmaReadError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) + char *format; + char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10; +{ + calmaTotalErrors++; + if (CIFWarningLevel == CIF_WARN_NONE) return; + + if ((calmaTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT)) + { + + if (CIFWarningLevel == CIF_WARN_REDIRECT) + { + if (calmaErrorFile != NULL) + { + fprintf(calmaErrorFile, "Error while reading cell \"%s\": ", + cifReadCellDef->cd_name); + fprintf(calmaErrorFile, format, a1, a2, a3, a4, a5, a6, a7, + a8, a9, a10); + } + } + else + { + TxError("Error while reading cell \"%s\": ", cifReadCellDef->cd_name); + TxError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + } + else if ((calmaTotalErrors == 100) && (CIFWarningLevel == CIF_WARN_LIMIT)) + { + TxError("Error limit set: Remaining errors will not be reported.\n"); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaUnexpected -- + * + * Complain about a record where we expected one kind but got another. + * + * Results: + * None. + * + * Side effects: + * Prints an error message. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaUnexpected(wanted, got) + int wanted; /* Type of record we wanted */ + int got; /* Type of record we got */ +{ + calmaReadError("Unexpected record type in input: \n"); + + if (CIFWarningLevel == CIF_WARN_NONE) return; + if (calmaTotalErrors < 100 || (CIFWarningLevel != CIF_WARN_LIMIT)) + { + if (CIFWarningLevel == CIF_WARN_REDIRECT) + { + if (calmaErrorFile != NULL) + { + fprintf(calmaErrorFile," Expected %s record ", + calmaRecordName(wanted)); + fprintf(calmaErrorFile, "but got %s.\n", calmaRecordName(got)); + } + } + else + { + TxError(" Expected %s record ", calmaRecordName(wanted)); + TxError("but got %s.\n", calmaRecordName(got)); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaRecordName -- + * + * Return a pointer to the printable name of a CALMA record type. + * + * Results: + * See above. + * + * Side effects: + * May overwrite the string we returned on the previous call. + * + * ---------------------------------------------------------------------------- + */ + +char * +calmaRecordName(rtype) + int rtype; +{ + static char numeric[10]; + static char *calmaRecordNames[] = + { + "HEADER", "BGNLIB", "LIBNAME", "UNITS", + "ENDLIB", "BGNSTR", "STRNAME", "ENDSTR", + "BOUNDARY", "PATH", "SREF", "AREF", + "TEXT", "LAYER", "DATATYPE", "WIDTH", + "XY", "ENDEL", "SNAME", "COLROW", + "TEXTNODE", "NODE", "TEXTTYPE", "PRESENTATION", + "SPACING", "STRING", "STRANS", "MAG", + "ANGLE", "UINTEGER", "USTRING", "REFLIBS", + "FONTS", "PATHTYPE", "GENERATIONS", "ATTRTABLE", + "STYPTABLE", "STRTYPE", "ELFLAGS", "ELKEY", + "LINKTYPE", "LINKKEYS", "NODETYPE", "PROPATTR", + "PROPVALUE", "BOX", "BOXTYPE", "PLEX", + "BGNEXTN", "ENDEXTN", "TAPENUM", "TAPECODE", + "STRCLASS", "RESERVED", "FORMAT", "MASK", + "ENDMASKS" + }; + + if (rtype < 0 || rtype >= CALMA_NUMRECORDTYPES) + { + (void) sprintf(numeric, "%d", rtype); + return (numeric); + } + + return (calmaRecordNames[rtype]); +} + +/* + * ---------------------------------------------------------------------------- + * + * CalmaTechInit -- + * + * Prepare for a technology file. + * + * Results: + * None. + * + * Side effects: + * Error checking. + * + * ---------------------------------------------------------------------------- + */ + +void +CalmaTechInit() +{ + ASSERT(sizeof(FourByteInt)==4, "definition in calmaInt.h"); + ASSERT(sizeof(TwoByteInt)==2, "definition in calmaInt.h"); +} diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c new file mode 100644 index 00000000..0317eb0f --- /dev/null +++ b/calma/CalmaWrite.c @@ -0,0 +1,2478 @@ +/* + * CalmaWrite.c -- + * + * Output of Calma GDS-II stream format. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/calma/CalmaWrite.c,v 1.8 2010/12/22 16:29:06 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#ifdef SYSV +#include +#else +#include +#endif + +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "database/database.h" +#include "database/databaseInt.h" +#include "utils/tech.h" +#include "cif/cif.h" +#include "cif/CIFint.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "textio/textio.h" +#include "calma/calmaInt.h" +#include "utils/main.h" /* for Path and CellLibPath */ +#include "utils/stack.h" + + /* Exports */ +bool CalmaDoLabels = TRUE; /* If FALSE, don't output labels with GDS-II */ +bool CalmaDoLower = TRUE; /* If TRUE, allow lowercase labels. */ +bool CalmaFlattenArrays = FALSE; /* If TRUE, output arrays as individual uses */ + + /* Experimental stuff---not thoroughly tested (as of Sept. 2007)! */ +bool CalmaContactArrays = FALSE; /* If TRUE, output contacts as subcell arrays */ +bool CalmaMergeTiles = FALSE; /* If TRUE, merge tiles into polygons in output. */ + + /* Forward declarations */ +extern int calmaWriteInitFunc(); +extern int calmaWriteMarkFunc(); +extern int calmaWritePaintFunc(); +extern int calmaMergePaintFunc(); +extern int calmaWriteUseFunc(); +extern void calmaWriteContacts(); +extern void calmaDelContacts(); +extern void calmaOutFunc(); +extern void calmaOutStructName(); +extern void calmaWriteLabelFunc(); +extern void calmaOutHeader(); +extern void calmaOutDate(); +extern void calmaOutStringRecord(); +extern void calmaOut8(); +extern void calmaOutR8(); +extern void calmaProcessBoundary(); +extern void calmaMergeBoundaries(); +extern void calmaRemoveColinear(); +extern void calmaRemoveDegenerate(); + +/* Structure used by calmaWritePaintFunc() */ + +typedef struct { + FILE *f; /* File stream for output */ + Rect *area; /* Clipping area, in GDS coordinates */ +} calmaOutputStruct; + +/*--------------------------------------------------------------*/ +/* Structures used by the tile merging algorithm */ +/*--------------------------------------------------------------*/ + +#define GDS_PENDING 0 +#define GDS_UNPROCESSED CLIENTDEFAULT +#define GDS_PROCESSED 1 + +#define PUSHTILE(tp) \ + if ((tp)->ti_client == (ClientData) GDS_UNPROCESSED) { \ + (tp)->ti_client = (ClientData) GDS_PENDING; \ + STACKPUSH((ClientData) (tp), SegStack); \ + } + +#define LB_EXTERNAL 0 /* Polygon external edge */ +#define LB_INTERNAL 1 /* Polygon internal edge */ +#define LB_INIT 2 /* Data not yet valid */ + +typedef struct LB1 { + char lb_type; /* Boundary Type (external or internal) */ + Point lb_start; /* Start point */ + struct LB1 *lb_next; /* Next point record */ +} LinkedBoundary; + +typedef struct BT1 { + LinkedBoundary *bt_first; /* Polygon list */ + int bt_points; /* Number of points in this list */ + struct BT1 *bt_next; /* Next polygon record */ +} BoundaryTop; + +/*--------------------------------------------------------------*/ + +/* Number assigned to each cell */ +int calmaCellNum; + +/* Factor by which to scale Magic coordinates for cells and labels. */ +int calmaWriteScale; + +/* Scale factor for outputting paint: */ +int calmaPaintScale; + +/* + * Current layer number and "type". + * In GDS-II format, this is output with each rectangle. + */ +int calmaPaintLayerNumber; +int calmaPaintLayerType; + +/* Imports */ +extern time_t time(); + + +/* -------------------------------------------------------------------- */ + +/* + * Macros to output various pieces of Calma information. + * These are macros for speed. + */ + +/* -------------------------------------------------------------------- */ + +/* + * calmaOutRH -- + * + * Output a Calma record header. + * This consists of a two-byte count of the number of bytes in the + * record (including the two count bytes), a one-byte record type, + * and a one-byte data type. + */ +#define calmaOutRH(count, type, datatype, f) \ + { calmaOutI2(count, f); (void) putc(type, f); (void) putc(datatype, f); } + +/* + * calmaOutI2 -- + * + * Output a two-byte integer. + * Calma byte order is the same as the network byte order used + * by the various network library procedures. + */ +#define calmaOutI2(n, f) \ + { \ + union { short u_s; char u_c[2]; } u; \ + u.u_s = htons(n); \ + (void) putc(u.u_c[0], f); \ + (void) putc(u.u_c[1], f); \ + } +/* + * calmaOutI4 -- + * + * Output a four-byte integer. + * Calma byte order is the same as the network byte order used + * by the various network library procedures. + */ +#define calmaOutI4(n, f) \ + { \ + union { long u_i; char u_c[4]; } u; \ + u.u_i = htonl(n); \ + (void) putc(u.u_c[0], f); \ + (void) putc(u.u_c[1], f); \ + (void) putc(u.u_c[2], f); \ + (void) putc(u.u_c[3], f); \ + } + +static char calmaMapTableStrict[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, /* NUL - BEL */ + 0, 0, 0, 0, 0, 0, 0, 0, /* BS - SI */ + 0, 0, 0, 0, 0, 0, 0, 0, /* DLE - ETB */ + 0, 0, 0, 0, 0, 0, 0, 0, /* CAN - US */ + '_', '_', '_', '_', '$', '_', '_', '_', /* SP - ' */ + '_', '_', '_', '_', '_', '_', '_', '_', /* ( - / */ + '0', '1', '2', '3', '4', '5', '6', '7', /* 0 - 7 */ + '8', '9', '_', '_', '_', '_', '_', '_', /* 8 - ? */ + '_', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* @ - G */ + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* H - O */ + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* P - W */ + 'X', 'Y', 'Z', '_', '_', '_', '_', '_', /* X - _ */ + '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* ` - g */ + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* h - o */ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* p - w */ + 'x', 'y', 'z', '_', '_', '_', '_', 0, /* x - DEL */ +}; + +static char calmaMapTablePermissive[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, /* NUL - BEL */ + 0, 0, 0, 0, 0, 0, 0, 0, /* BS - SI */ + 0, 0, 0, 0, 0, 0, 0, 0, /* DLE - ETB */ + 0, 0, 0, 0, 0, 0, 0, 0, /* CAN - US */ + ' ', '!', '"', '#', '$', '&', '%', '\'', /* SP - ' */ + '(', ')', '*', '+', ',', '-', '.', '/', /* ( - / */ + '0', '1', '2', '3', '4', '5', '6', '7', /* 0 - 7 */ + '8', '9', ':', ';', '<', '=', '>', '?', /* 8 - ? */ + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* @ - G */ + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* H - O */ + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* P - W */ + 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', /* X - _ */ + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* ` - g */ + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* h - o */ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* p - w */ + 'x', 'y', 'z', '{', '|', '}', '~', 0, /* x - DEL */ +}; + + +/* + * ---------------------------------------------------------------------------- + * + * CalmaWrite -- + * + * Write out the entire tree rooted at the supplied CellDef in Calma + * GDS-II stream format, to the specified file. + * + * Results: + * TRUE if the cell could be written successfully, FALSE otherwise. + * + * Side effects: + * Writes a file to disk. + * In the event of an error while writing out the cell, + * the external integer errno is set to the UNIX error + * encountered. + * + * Algorithm: + * + * Calma names can be strings of up to CALMANAMELENGTH characters. + * Because general names won't map into Calma names, we use the + * original cell name only if it is legal Calma, and otherwise + * generate a unique numeric name for the cell. + * + * We make a depth-first traversal of the entire design tree, outputting + * each cell to the Calma file. If a given cell has not been read in + * when we visit it, we read it in ourselves. + * + * No hierarchical design rule checking or bounding box computation + * occur during this traversal -- both are explicitly avoided. + * + * ---------------------------------------------------------------------------- + */ + +bool +CalmaWrite(rootDef, f) + CellDef *rootDef; /* Pointer to CellDef to be written */ + FILE *f; /* Open output file */ +{ + int oldCount = DBWFeedbackCount, problems; + bool good; + CellUse dummy; + + /* + * Do not attempt to write anything if a CIF/GDS output style + * has not been specified in the technology file. + */ + if (!CIFCurStyle) + { + TxError("No CIF/GDS output style set!\n"); + return FALSE; + } + + /* + * Make sure that the entire hierarchy rooted at rootDef is + * read into memory and that timestamp mismatches are resolved + * (this is needed so that we know that bounding boxes are OK). + */ + + dummy.cu_def = rootDef; + DBCellReadArea(&dummy, &rootDef->cd_bbox); + DBFixMismatch(); + + /* + * Go through all cells currently having CellDefs in the + * def symbol table and mark them with negative numbers + * to show that they should be output, but haven't yet + * been. + */ + (void) DBCellSrDefs(0, calmaWriteInitFunc, (ClientData) NULL); + rootDef->cd_client = (ClientData) -1; + calmaCellNum = -2; + + /* Output the header, identifying this file */ + calmaOutHeader(rootDef, f); + + /* + * Write all contact cell definitions first + */ + if (CalmaContactArrays) calmaWriteContacts(f); + + /* + * We perform a post-order traversal of the tree rooted at 'rootDef', + * to insure that each child cell is output before it is used. The + * root cell is output last. + */ + (void) calmaProcessDef(rootDef, f); + + /* Finish up by outputting the end-of-library marker */ + calmaOutRH(4, CALMA_ENDLIB, CALMA_NODATA, f); + fflush(f); + good = !ferror(f); + + /* See if any problems occurred */ + if (problems = (DBWFeedbackCount - oldCount)) + TxPrintf("%d problems occurred. See feedback entries.\n", problems); + + /* + * Destroy all contact cell definitions + */ + if (CalmaContactArrays) calmaDelContacts(); + + return (good); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaWriteInitFunc -- + * + * Filter function called on behalf of CalmaWrite() above. + * Responsible for setting the cif number of each cell to zero. + * + * Results: + * Returns 0 to indicate that the search should continue. + * + * Side effects: + * Modify the calma numbers of the cells they are passed. + * + * ---------------------------------------------------------------------------- + */ + +int +calmaWriteInitFunc(def) + CellDef *def; +{ + def->cd_client = (ClientData) 0; + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaProcessUse -- + * calmaProcessDef -- + * + * Main loop of Calma generation. Performs a post-order, depth-first + * traversal of the tree rooted at 'def'. Only cells that have not + * already been output are processed. + * + * The procedure calmaProcessDef() is called initially; calmaProcessUse() + * is called internally by DBCellEnum(). + * + * Results: + * None. + * + * Side effects: + * Causes Calma GDS-II stream-format to be output. + * Returns when the stack is empty. + * + * ---------------------------------------------------------------------------- + */ + +int +calmaProcessUse(use, outf) + CellUse *use; /* Process use->cu_def */ + FILE *outf; /* Stream file */ +{ + return (calmaProcessDef(use->cu_def, outf)); +} + +int +calmaProcessDef(def, outf) + CellDef *def; /* Output this def's children, then the def itself */ + FILE *outf; /* Stream file */ +{ + char *filename; + bool isReadOnly, oldStyle, hasContent; + + /* Skip if already output */ + if ((int) def->cd_client > 0) + return (0); + + /* Assign it a (negative) number if it doesn't have one yet */ + if ((int) def->cd_client == 0) + def->cd_client = (ClientData) calmaCellNum--; + + /* Mark this cell */ + def->cd_client = (ClientData) (- (int) def->cd_client); + + /* Read the cell in if it is not already available. */ + if ((def->cd_flags & CDAVAILABLE) == 0) + if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) + return (0); + + /* + * Output the definitions for any of our descendants that have + * not already been output. Numbers are assigned to the subcells + * as they are output. + */ + (void) DBCellEnum(def, calmaProcessUse, (ClientData) outf); + + /* + * Check if this is a read-only file that is supposed to be copied + * verbatim from input to output. If so, do the direct copy. If + * not, or if there is any problem obtaining the original cell + * definition, resort to writing out magic's version of the def, + * and print a warning message. + * + * Treat the lack of a GDS_START property as an indication + * that we should treat this cell like a reference-only + * cell. That is, the instance will be called but no + * definition will appear in the output. + */ + + DBPropGet(def, "GDS_START", &hasContent); + filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly); + + if (isReadOnly && hasContent) + { + char *buffer, *offptr; + size_t defsize, numbytes; + off_t cellstart, cellend; + dlong cval; + FILE *fi; + + /* Use PaOpen() so the paths searched are the same as were */ + /* searched to find the .mag file that indicated this GDS file. */ + + fi = PaOpen(filename, "r", "", Path, CellLibPath, (char **)NULL); + if (fi == NULL) + { + /* This is a rare error, but if the subcell is inside */ + /* another vendor GDS, it would not normally be output. */ + + DBPropGet(def->cd_parents->cu_parent, "GDS_FILE", &isReadOnly); + if (!isReadOnly) + TxError("Calma output error: Can't find GDS file for vendor cell." + " Using magic's internal definition\n"); + else + def->cd_flags |= CDVENDORGDS; + } + else + { + offptr = (char *)DBPropGet(def, "GDS_END", NULL); + sscanf(offptr, "%"DLONG_PREFIX"d", &cval); + cellend = (off_t)cval; + offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle); + if (!oldStyle) + { + offptr = (char *)DBPropGet(def, "GDS_START", NULL); + + /* Write our own header and string name, to ensure */ + /* that the magic cell name and GDS name match. */ + + /* Output structure header */ + calmaOutRH(28, CALMA_BGNSTR, CALMA_I2, outf); + calmaOutDate(def->cd_timestamp, outf); + calmaOutDate(time((time_t *) 0), outf); + + /* Name structure the same as the magic cellname */ + calmaOutStructName(CALMA_STRNAME, def, outf); + } + + sscanf(offptr, "%"DLONG_PREFIX"d", &cval); + cellstart = (off_t)cval; + fseek(fi, cellstart, SEEK_SET); + + if (cellend < cellstart) /* Sanity check */ + { + TxError("Calma output error: Bad vendor GDS file reference!\n"); + isReadOnly = FALSE; + } + else + { + defsize = (size_t)(cellend - cellstart); + + buffer = (char *)mallocMagic(defsize); + numbytes = fread(buffer, sizeof(char), (size_t)defsize, fi); + if (numbytes == defsize) + { + numbytes = fwrite(buffer, sizeof(char), (size_t)defsize, outf); + if (numbytes <= 0) + { + TxError("Calma output error: Can't write cell from vendor GDS." + " Using magic's internal definition\n"); + isReadOnly = FALSE; + } + } + else + { + TxError("Calma output error: Can't read cell from vendor GDS." + " Using magic's internal definition\n"); + isReadOnly = FALSE; + } + freeMagic(buffer); + } + fclose(fi); + + /* Mark the definition as vendor GDS so that magic doesn't */ + /* try to generate subcell interaction or array interaction */ + /* paint for it. */ + + def->cd_flags |= CDVENDORGDS; + } + } + + /* Output this cell definition from the Magic database */ + if (!isReadOnly) + calmaOutFunc(def, outf, &TiPlaneRect); + + return (0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * calmaOutFunc -- + * + * Write out the definition for a single cell as a GDS-II stream format + * structure. We try to preserve the original cell's name if it is legal + * in GDS-II; otherwise, we generate a unique name. + * + * Results: + * None. + * + * Side effects: + * Appends to the open Calma output file. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaOutFunc(def, f, cliprect) + CellDef *def; /* Pointer to cell def to be written */ + FILE *f; /* Open output file */ + Rect *cliprect; /* Area to clip to (used for contact cells), + * in CIF/GDS coordinates. + */ +{ + Label *lab; + CIFLayer *layer; + Rect bigArea; + int type; + int dbunits; + calmaOutputStruct cos; + + cos.f = f; + cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect; + + /* Output structure begin */ + calmaOutRH(28, CALMA_BGNSTR, CALMA_I2, f); + calmaOutDate(def->cd_timestamp, f); + calmaOutDate(time((time_t *) 0), f); + + /* Output structure name */ + calmaOutStructName(CALMA_STRNAME, def, f); + + /* Since Calma database units are nanometers, multiply all units by 10, + * modified by the scale multiplier. + */ + + dbunits = (CIFCurStyle->cs_flags & CWF_ANGSTROMS) ? 100 : 10; + if ((dbunits % CIFCurStyle->cs_expander) == 0) + { + calmaWriteScale = CIFCurStyle->cs_scaleFactor * dbunits + / CIFCurStyle->cs_expander; + calmaPaintScale = dbunits / CIFCurStyle->cs_expander; + } + else + { + TxError("Calma output error: Output scale units are %2.1f nanometers.\n", + (float)dbunits / (float)CIFCurStyle->cs_expander); + TxError("Magic Calma output will be scaled incorrectly!\n"); + if ((dbunits == 10) && ((100 % CIFCurStyle->cs_expander) == 0)) + { + TxError("Please add \"units angstroms\" to the cifoutput section" + " of the techfile.\n"); + } + else + { + TxError("Magic GDS output is limited to a minimum dimension of" + " 1 angstrom.\n"); + } + /* Set expander to 10 so output scales are not zero. */ + calmaWriteScale = CIFCurStyle->cs_scaleFactor; + calmaPaintScale = 1; + } + + /* + * Output the calls that the child makes to its children. For + * arrays we output a single call, unlike CIF, since Calma + * supports the notion of arrays. + */ + (void) DBCellEnum(def, calmaWriteUseFunc, (ClientData) f); + + /* Output all the tiles associated with this cell; skip temporary layers */ + GEO_EXPAND(&def->cd_bbox, CIFCurStyle->cs_radius, &bigArea); + CIFErrorDef = def; + CIFGen(def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, (ClientData) f); + if (!CIFHierWriteDisable) + CIFGenSubcells(def, &bigArea, CIFPlanes); + if (!CIFArrayWriteDisable) + CIFGenArrays(def, &bigArea, CIFPlanes); + + for (type = 0; type < CIFCurStyle->cs_nLayers; type++) + { + layer = CIFCurStyle->cs_layers[type]; + if (layer->cl_flags & CIF_TEMP) continue; + if (!CalmaIsValidLayer(layer->cl_calmanum)) continue; + calmaPaintLayerNumber = layer->cl_calmanum; + calmaPaintLayerType = layer->cl_calmatype; + + DBSrPaintArea((Tile *) NULL, CIFPlanes[type], + cliprect, &CIFSolidBits, (CalmaMergeTiles) ? + calmaMergePaintFunc : calmaWritePaintFunc, + (ClientData) &cos); + } + + /* Output labels */ + if (CalmaDoLabels) + for (lab = def->cd_labels; lab; lab = lab->lab_next) + calmaWriteLabelFunc(lab, + CIFCurStyle->cs_labelLayer[lab->lab_type], f); + + /* End of structure */ + calmaOutRH(4, CALMA_ENDSTR, CALMA_NODATA, f); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaIsUseNameDefault -- + * + * Determine if this use name is not default; that is, it is not the name + * of the cell def followed by an underscore and a use index number. If + * it is not default, then we want to write out the use name as a property + * in the GDS stream file so that we can recover the name when the file is + * read back into magic. + * + * Results: + * TRUE if the cell use ID is a default name; FALSE if not. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +calmaIsUseNameDefault(defName, useName) + char *defName; + char *useName; +{ + int idx, slen; + char *sptr; + + if (useName == NULL) return TRUE; + slen = strlen(defName); + if (!strncmp(defName, useName, slen)) + { + sptr = useName + slen; + if (*sptr != '_') return FALSE; + else sptr++; + if (sscanf(sptr, "%d", &idx) != 1) return FALSE; + else return TRUE; + } + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaWriteUseFunc -- + * + * Filter function, called by DBCellEnum on behalf of calmaOutFunc above, + * to write out each CellUse called by the CellDef being output. If the + * CellUse is an array, we output it as a single array instead of as + * individual uses like CIF. + * + * Results: + * None. + * + * Side effects: + * Appends to the open Calma output file. + * + * ---------------------------------------------------------------------------- + */ + +int +calmaWriteUseFunc(use, f) + CellUse *use; + FILE *f; +{ + /* + * r90, r180, and r270 are Calma 8-byte real representations + * of the angles 90, 180, and 270 degrees. Because there are + * only 4 possible values, it is faster to have them pre-computed + * than to format with calmaOutR8(). + */ + static unsigned char r90[] = { 0x42, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static unsigned char r180[] = { 0x42, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static unsigned char r270[] = { 0x43, 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00 }; + unsigned char *whichangle; + int x, y, topx, topy, rows, cols, xxlate, yxlate, hdrsize; + int rectype, stransflags; + Transform *t; + bool isArray = FALSE; + Point p, p2; + + topx = use->cu_xhi - use->cu_xlo; + if (topx < 0) topx = -topx; + topy = use->cu_yhi - use->cu_ylo; + if (topy < 0) topy = -topy; + + /* + * The following translates from the abcdef transforms that + * we use internally to the rotation and mirroring specification + * used in Calma stream files. It only works because orientations + * are orthogonal in magic, and no scaling is allowed in cell use + * transforms. Thus the elements a, b, d, and e always have one + * of the following forms: + * + * a d + * b e + * + * (counterclockwise rotations of 0, 90, 180, 270 degrees) + * + * 1 0 0 1 -1 0 0 -1 + * 0 1 -1 0 0 -1 1 0 + * + * (mirrored across the x-axis before counterclockwise rotation + * by 0, 90, 180, 270 degrees): + * + * 1 0 0 1 -1 0 0 -1 + * 0 -1 1 0 0 1 -1 0 + * + * Note that mirroring must be done if either a != e, or + * a == 0 and b == d. + * + */ + t = &use->cu_transform; + stransflags = 0; + whichangle = (t->t_a == -1) ? r180 : (unsigned char *) NULL; + if (t->t_a != t->t_e || (t->t_a == 0 && t->t_b == t->t_d)) + { + stransflags |= CALMA_STRANS_UPSIDEDOWN; + if (t->t_a == 0) + { + if (t->t_b == 1) whichangle = r90; + else whichangle = r270; + } + } + else if (t->t_a == 0) + { + if (t->t_b == -1) whichangle = r90; + else whichangle = r270; + } + + if (CalmaFlattenArrays) + { + for (x = 0; x <= topx; x++) + { + for (y = 0; y <= topy; y++) + { + /* Structure reference */ + calmaOutRH(4, CALMA_SREF, CALMA_NODATA, f); + calmaOutStructName(CALMA_SNAME, use->cu_def, f); + + /* Transformation flags */ + calmaOutRH(6, CALMA_STRANS, CALMA_BITARRAY, f); + calmaOutI2(stransflags, f); + + /* Rotation if there is one */ + if (whichangle) + { + calmaOutRH(12, CALMA_ANGLE, CALMA_R8, f); + calmaOut8(whichangle, f); + } + + /* Translation */ + xxlate = t->t_c + t->t_a*(use->cu_xsep)*x + + t->t_b*(use->cu_ysep)*y; + yxlate = t->t_f + t->t_d*(use->cu_xsep)*x + + t->t_e*(use->cu_ysep)*y; + xxlate *= calmaWriteScale; + yxlate *= calmaWriteScale; + calmaOutRH(12, CALMA_XY, CALMA_I4, f); + calmaOutI4(xxlate, f); + calmaOutI4(yxlate, f); + + /* End of element */ + calmaOutRH(4, CALMA_ENDEL, CALMA_NODATA, f); + } + } + } + else + { + /* Is it an array? */ + isArray = (topx > 0 || topy > 0); + rectype = isArray ? CALMA_AREF : CALMA_SREF; + + /* Structure reference */ + calmaOutRH(4, rectype, CALMA_NODATA, f); + calmaOutStructName(CALMA_SNAME, use->cu_def, f); + + /* Transformation flags */ + calmaOutRH(6, CALMA_STRANS, CALMA_BITARRAY, f); + calmaOutI2(stransflags, f); + + /* Rotation if there is one */ + if (whichangle) + { + calmaOutRH(12, CALMA_ANGLE, CALMA_R8, f); + calmaOut8(whichangle, f); + } + + /* If array, number of columns and rows in the array */ + if (isArray) + { + calmaOutRH(8, CALMA_COLROW, CALMA_I2, f); + cols = topx + 1; + rows = topy + 1; + calmaOutI2(cols, f); + calmaOutI2(rows, f); + } + + /* Translation */ + xxlate = t->t_c * calmaWriteScale; + yxlate = t->t_f * calmaWriteScale; + hdrsize = isArray ? 28 : 12; + calmaOutRH(hdrsize, CALMA_XY, CALMA_I4, f); + calmaOutI4(xxlate, f); + calmaOutI4(yxlate, f); + + /* Array sizes if an array */ + if (isArray) + { + /* Column reference point */ + p.p_x = use->cu_xsep * cols; + p.p_y = 0; + GeoTransPoint(t, &p, &p2); + p2.p_x *= calmaWriteScale; + p2.p_y *= calmaWriteScale; + calmaOutI4(p2.p_x, f); + calmaOutI4(p2.p_y, f); + + /* Row reference point */ + p.p_x = 0; + p.p_y = use->cu_ysep * rows; + GeoTransPoint(t, &p, &p2); + p2.p_x *= calmaWriteScale; + p2.p_y *= calmaWriteScale; + calmaOutI4(p2.p_x, f); + calmaOutI4(p2.p_y, f); + } + + /* By NP */ + /* Property attributes/value pairs. */ + /* Add a CellUse ID property, if the CellUse has a non-default name */ + + if (!calmaIsUseNameDefault(use->cu_def->cd_name, use->cu_id)) + { + calmaOutRH(6, CALMA_PROPATTR, CALMA_I2, f); + calmaOutI2(CALMA_PROP_USENAME, f); + calmaOutStringRecord(CALMA_PROPVALUE, use->cu_id, f); + } + + /* Add an array limits property, if the CellUse is an array and */ + /* limits of the array (xlo, ylo) are not zero (the default). */ + + if ((use->cu_xlo != 0) || (use->cu_ylo != 0)) + { + char arraystr[128]; + sprintf(arraystr, "%d_%d_%d_%d", use->cu_xlo, use->cu_xhi, + use->cu_ylo, use->cu_yhi); + calmaOutRH(6, CALMA_PROPATTR, CALMA_I2, f); + calmaOutI2(CALMA_PROP_ARRAY_LIMITS, f); + calmaOutStringRecord(CALMA_PROPVALUE, arraystr, f); + } + + /* End of element */ + calmaOutRH(4, CALMA_ENDEL, CALMA_NODATA, f); + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaOutStructName -- + * + * Output the name of a cell def. + * If the name is legal GDS-II, use it; otherwise, generate one + * that is legal and unique. + * + * Results: + * None. + * + * Side effects: + * Writes to the disk file. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaOutStructName(type, def, f) + int type; + CellDef *def; + FILE *f; +{ + char defname[CALMANAMELENGTH+1]; + unsigned char c; + char *cp; + int calmanum; + char *table; + + if (CIFCurStyle->cs_flags & CWF_PERMISSIVE_LABELS) + { + table = calmaMapTablePermissive; + } else { + table = calmaMapTableStrict; + } + + /* Is the def name a legal Calma name? */ + for (cp = def->cd_name; c = (unsigned char) *cp; cp++) + { + if ((c > 127) || (table[c] == 0)) + goto bad; + else if ((unsigned char)table[c] != c) + { + TxError("Warning: character \'%c\' changed to \'%c\' in" + " name %s\n", (char)c, table[c], def->cd_name); + } + /* We really should ensure that the new name is unique. . . */ + } + if (cp <= def->cd_name + CALMANAMELENGTH) + { + /* Yes, it's legal: use it */ + (void) strcpy(defname, def->cd_name); + } + else + { + /* Bad name: use XXXXXcalmaNum */ +bad: + calmanum = (int) def->cd_client; + if (calmanum < 0) calmanum = -calmanum; + (void) sprintf(defname, "XXXXX%d", calmanum); + TxError("Warning: string in output unprintable; changed to \'%s\'\n", + defname); + } + + calmaOutStringRecord(type, defname, f); +} + +/* Added by NP 8/21/2004 */ +/* + * ---------------------------------------------------------------------------- + * + * calmaGetContactCell -- + * + * This routine creates [if it hasn't been created yet] a cell definition + * containing the given TileType. Cellname is "$$" + layer1_name + "_" + + * layer2_name... + "$$". Cellname contains the short name of all the + * residues of the layer "type". + * + * Results: + * Returns new celldef it doesn't exist else created one. + * + * Side effects: + * New celldef created specially for contact type if it does not exist. + * + * ---------------------------------------------------------------------------- + */ + +CellDef * +calmaGetContactCell(type, lookOnly) + TileType type; /* magic contact tile type */ + bool lookOnly; /* if true, don't generate any new cells */ +{ + TileType j; + char contactCellName[100]; + TileTypeBitMask *rMask = DBResidueMask(type); + CellDef *def; + bool first = TRUE; + + strcpy(contactCellName, "$$"); + for (j = TT_SPACE + 1; j < DBNumUserLayers; j++) + if (TTMaskHasType(rMask, j)) + { + /* Cellname starts with "$$" to make it diffrent from + * other database cells, and to be compatible with a + * number of other EDA tools. + */ + if (!first) + strcat(contactCellName, "_"); + else + first = FALSE; + strcat(contactCellName, DBTypeShortName(j)); + } + strcat(contactCellName, "$$"); + + def = DBCellLookDef(contactCellName); + if ((def == (CellDef *) NULL) && (lookOnly == FALSE)) + { + def = DBCellNewDef(contactCellName, (char *) NULL); + def->cd_flags &= ~(CDMODIFIED|CDGETNEWSTAMP); + def->cd_flags |= CDAVAILABLE; + } + return def; +} + +/* + * ---------------------------------------------------------------------------- + * + * CalmaGenerateArray -- + * + * This routine + * + * Results: + * TRUE on success, FALSE if no contact cell could be found. + * + * Side effects: + * Writes an AREF record to the GDS stream output. + * + * ---------------------------------------------------------------------------- + */ + +bool +CalmaGenerateArray(f, type, llx, lly, pitch, cols, rows) + FILE *f; /* GDS output file */ + TileType type; /* Magic tile type of contact */ + int llx, lly; /* Lower-left hand coordinate of the array + * (centered on contact cut) + */ + int pitch; /* Pitch of the array elements */ + int cols, rows; /* Number of array elements in X and Y */ +{ + CellDef *child; /* Cell definition of the contact cell */ + int xxlate, yxlate; + + child = calmaGetContactCell(type, TRUE); + if (child == NULL) return FALSE; + + /* Structure reference */ + calmaOutRH(4, CALMA_AREF, CALMA_NODATA, f); + calmaOutStructName(CALMA_SNAME, child, f); + + /* Transformation flags */ + calmaOutRH(6, CALMA_STRANS, CALMA_BITARRAY, f); + calmaOutI2(0, f); + + /* Number of columns and rows in the array */ + calmaOutRH(8, CALMA_COLROW, CALMA_I2, f); + calmaOutI2(cols, f); + calmaOutI2(rows, f); + + /* Translation */ + xxlate = llx * calmaPaintScale; + yxlate = lly * calmaPaintScale; + calmaOutRH(28, CALMA_XY, CALMA_I4, f); + calmaOutI4(xxlate, f); + calmaOutI4(yxlate, f); + + /* Column reference point */ + calmaOutI4(xxlate + pitch * cols * calmaPaintScale, f); + calmaOutI4(yxlate, f); + + /* Row reference point */ + calmaOutI4(xxlate, f); + calmaOutI4(yxlate + pitch * rows * calmaPaintScale, f); + + /* End of AREF element */ + calmaOutRH(4, CALMA_ENDEL, CALMA_NODATA, f); + + return TRUE; +} + +/* Added by NP 8/22/2004 */ +/* + * ---------------------------------------------------------------------------- + * + * calmaWriteContacts -- + * + * This routine creates a new cellDef for each contact type and writes to + * the GDS output stream file. It is called before processing all cell + * definitions while writing GDS output. + * + * Results: + * None. + * + * Side effects: + * Writes contact cell definition to the open Calma output file. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaWriteContacts(f) + FILE *f; +{ + TileType type; + TileTypeBitMask tMask, *rMask; + CellDef *def, *cellDef; + Rect area, cliprect; + int halfwidth, halfsize; + CIFOp *op; + + /* Turn off generation of contact arrays for the duration of this */ + /* subroutine, so that the contact definitions themselves will get */ + /* the proper contact cut drawn. It is turned on again at the end */ + /* of the routine. Note that this routine is not called unless */ + /* CalmaContactArrays is TRUE. */ + + CalmaContactArrays = FALSE; + + DBEnumerateTypes(&tMask); + + /* Decompose stacking types */ + for (type = DBNumUserLayers; type < DBNumTypes; type++) + if (TTMaskHasType(&tMask, type)) + { + rMask = DBResidueMask(type); + TTMaskSetMask(&tMask, rMask); + } + + for (type = TT_SPACE + 1; type < DBNumUserLayers; type++) + { + /* We need to create cell array only for contact types */ + if (DBIsContact(type) && TTMaskHasType(&tMask, type)) + { + /* Write definition of cell to GDS stream. */ + /* Get cell definition for Tiletype type */ + def = calmaGetContactCell(type, FALSE); + + /* Get clip bounds, so that residue surround is */ + /* minimum. Note that these values are in CIF/GDS */ + /* units, and the clipping rectangle passed to */ + /* calmaOutFunc is also in CIF/GDS units. */ + + halfsize = CIFGetContactSize(type, NULL, NULL, NULL) >> 1; + + /* Get minimum width for layer by rounding halfsize */ + /* to the nearest lambda value. */ + halfwidth = halfsize / CIFCurStyle->cs_scaleFactor; + if ((halfsize % CIFCurStyle->cs_scaleFactor) != 0) + halfwidth++; + + area.r_xbot = area.r_ybot = -halfwidth; + area.r_xtop = area.r_ytop = halfwidth; + UndoDisable(); + DBPaint(def, &area, type); + DBReComputeBbox(def); + TTMaskSetType(&def->cd_types, type); + + /* Clip output to the bounds of "cliprect" */ + cliprect.r_xbot = cliprect.r_ybot = -halfsize; + cliprect.r_xtop = cliprect.r_ytop = halfsize; + + calmaOutFunc(def, f, &cliprect); + UndoEnable(); + } + } + CalmaContactArrays = TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaDelContacts -- + * + * This routine removes all cell definitions generated by + * calmaWriteContacts(). + * + * Results: + * None. + * + * Side effects: + * Removes contact cell defs from the database. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaDelContacts() +{ + TileType type; + CellDef *def; + + for (type = TT_SPACE + 1; type < DBNumUserLayers; type++) + if (DBIsContact(type)) + { + def = calmaGetContactCell(type, TRUE); + if (def != (CellDef *)NULL) + DBCellDeleteDef(def); + } +} + +/* + * ---------------------------------------------------------------------------- + * calmaAddSegment --- + * + * Process a new polygon edge, inserting it into a polygon record as + * required. If the edge is between a GDS layer and TT_SPACE, then + * we insert a point record. If the edge is between two tiles of the + * same layer, then we insert a tile record. + * + * Results: + * Return 1 if an internal segment was generated, 0 if an external + * segment was generate. On error, return -1 (failure to find a + * connecting point; this shouldn't happen). + * + * Returns the current segment in the original pointer position (1st + * argument). If segments are added in counterclockwise order, then + * this should be most efficient. + * + * Side effects: + * May allocate memory. + * --------------------------------------------------------------------------- + */ + +int +calmaAddSegment(lbptr, poly_edge, p1x, p1y, p2x, p2y) + LinkedBoundary **lbptr; + bool poly_edge; + int p1x, p1y, p2x, p2y; +{ + LinkedBoundary *newseg, *curseg, *stopseg; + bool startmatch = FALSE; + bool endmatch = FALSE; + + stopseg = NULL; + for (curseg = *lbptr; curseg != stopseg; curseg = curseg->lb_next) + { + stopseg = *lbptr; + if (curseg->lb_type == LB_INIT) + { + if ((p1x == curseg->lb_start.p_x) && (p1y == curseg->lb_start.p_y)) + startmatch = TRUE; + + if ((p2x == curseg->lb_next->lb_start.p_x) && + (p2y == curseg->lb_next->lb_start.p_y)) + endmatch = TRUE; + + if (startmatch && endmatch) + { + /* Segment completes this edge */ + curseg->lb_type = (poly_edge) ? LB_EXTERNAL : LB_INTERNAL; + *lbptr = curseg; + return (int)curseg->lb_type; + } + else if (startmatch || endmatch) + { + /* Insert a new segment after curseg */ + newseg = (LinkedBoundary *)mallocMagic(sizeof(LinkedBoundary)); + newseg->lb_next = curseg->lb_next; + curseg->lb_next = newseg; + + if (startmatch) + { + newseg->lb_type = curseg->lb_type; + curseg->lb_type = (poly_edge) ? LB_EXTERNAL : LB_INTERNAL; + newseg->lb_start.p_x = p2x; + newseg->lb_start.p_y = p2y; + } + else + { + newseg->lb_type = (poly_edge) ? LB_EXTERNAL : LB_INTERNAL; + newseg->lb_start.p_x = p1x; + newseg->lb_start.p_y = p1y; + } + curseg = newseg; + *lbptr = curseg; + return (int)curseg->lb_type; + } + } + } + return -1; /* This shouldn't happen, but isn't fatal. */ +} + +/* + * ---------------------------------------------------------------------------- + * calmaRemoveDegenerate --- + * + * This routine takes lists of polygons and removes any degenerate + * segments (those that backtrack on themselves) from each one. + * + * Results: + * None. + * + * Side Effects: + * Deallocates memory for any segments that are removed. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaRemoveDegenerate(blist) + BoundaryTop *blist; +{ + bool segfound; + LinkedBoundary *stopseg, *curseg, *lastseg; + BoundaryTop *bounds; + + for (bounds = blist; bounds != NULL; bounds = bounds->bt_next) + { + segfound = TRUE; + while (segfound) + { + segfound = FALSE; + stopseg = NULL; + for (lastseg = bounds->bt_first; lastseg != stopseg;) + { + stopseg = bounds->bt_first; + curseg = lastseg->lb_next; + + if (GEO_SAMEPOINT(curseg->lb_start, + curseg->lb_next->lb_next->lb_start)) + { + segfound = TRUE; + lastseg->lb_next = curseg->lb_next->lb_next; + + freeMagic(curseg->lb_next); + freeMagic(curseg); + + /* Make sure record doesn't point to a free'd segment */ + bounds->bt_first = lastseg; + bounds->bt_points -= 2; + break; + } + else + lastseg = lastseg->lb_next; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * calmaRemoveColinear --- + * + * This routine takes lists of polygons and removes any redundant + * (colinear) points. + * + * Results: + * None. + * + * Side Effects: + * Deallocates memory for any segments that are removed. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaRemoveColinear(blist) + BoundaryTop *blist; +{ + LinkedBoundary *stopseg, *curseg, *lastseg; + BoundaryTop *bounds; + + for (bounds = blist; bounds != NULL; bounds = bounds->bt_next) + { + stopseg = NULL; + for (lastseg = bounds->bt_first; lastseg != stopseg;) + { + stopseg = bounds->bt_first; + curseg = lastseg->lb_next; + + if (((lastseg->lb_start.p_x == curseg->lb_start.p_x) && + (lastseg->lb_start.p_x == curseg->lb_next->lb_start.p_x)) || + ((lastseg->lb_start.p_y == curseg->lb_start.p_y) && + (lastseg->lb_start.p_y == curseg->lb_next->lb_start.p_y))) + { + lastseg->lb_next = curseg->lb_next; + + /* Make sure record doesn't point to a free'd segment */ + if (curseg == bounds->bt_first) bounds->bt_first = lastseg; + + freeMagic(curseg); + bounds->bt_points--; + } + else if ((lastseg->lb_start.p_x != curseg->lb_start.p_x) && + (lastseg->lb_start.p_y != curseg->lb_start.p_y) && + (curseg->lb_start.p_x != curseg->lb_next->lb_start.p_x) && + (curseg->lb_start.p_y != curseg->lb_next->lb_start.p_y)) + { + /* Check colinearity of non-Manhattan edges */ + int delx1, dely1, delx2, dely2, gcf; + + delx1 = curseg->lb_start.p_x - lastseg->lb_start.p_x; + dely1 = curseg->lb_start.p_y - lastseg->lb_start.p_y; + delx2 = curseg->lb_next->lb_start.p_x - curseg->lb_start.p_x; + dely2 = curseg->lb_next->lb_start.p_y - curseg->lb_start.p_y; + + if ((delx1 != delx2) || (dely1 != dely2)) + { + gcf = FindGCF(delx1, dely1); + if (gcf > 1) + { + delx1 /= gcf; + dely1 /= gcf; + } + } + if ((delx1 != delx2) || (dely1 != dely2)) + { + gcf = FindGCF(delx2, dely2); + if (gcf > 1) + { + delx2 /= gcf; + dely2 /= gcf; + } + } + if ((delx1 == delx2) && (dely1 == dely2)) + { + lastseg->lb_next = curseg->lb_next; + if (curseg == bounds->bt_first) bounds->bt_first = lastseg; + freeMagic(curseg); + bounds->bt_points--; + } + else + lastseg = lastseg->lb_next; + } + else + lastseg = lastseg->lb_next; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * calmaMergeSegments --- + * + * Once a tile has been disassembled into segments, and it is not a simple + * rectangle (which would have been handled already), then merge it into + * the list of boundaries. + * + * Note that this algorithm is O(N^2) and has lots of room for improvement! + * Still, each segment is never checked against more than 200 points, + * because when a boundary reaches this number (the maximum for GDS + * boundary records), the record will tend to be skipped (it should + * probably be output here. . .) + * + * Results: + * None. + * + * Side effects: + * Output, memory allocation and deallocation + * + * ---------------------------------------------------------------------------- + */ + +void +calmaMergeSegments(edge, blist, num_points) + LinkedBoundary *edge; + BoundaryTop **blist; + int num_points; +{ + LinkedBoundary *stopseg, *curseg, *lastseg; + LinkedBoundary *compstop, *compseg, *complast; + BoundaryTop *bounds, *newbounds; + + if (*blist == NULL) goto make_new_bound; + + /* Check each internal edge for an antiparallel match with */ + /* an internal edge in the boundary lists. */ + + stopseg = NULL; + for (lastseg = edge; lastseg != stopseg; lastseg = lastseg->lb_next) + { + stopseg = edge; + curseg = lastseg->lb_next; + if (curseg->lb_type == LB_EXTERNAL) continue; + + for (bounds = *blist; bounds != NULL; bounds = bounds->bt_next) + { + /* Avoid overflow on GDS boundary point limit. Note */ + /* that a merge will remove 2 points, but GDS requires */ + /* that we add the 1st point to the end of the list. */ + + if (bounds->bt_points + num_points > 201) continue; + + compstop = NULL; + for (complast = bounds->bt_first; complast != compstop; + complast = complast->lb_next) + { + compstop = bounds->bt_first; + compseg = complast->lb_next; + if (compseg->lb_type == LB_EXTERNAL) continue; + + /* Edges match antiparallel only. Rect points are *not* */ + /* canonical. r_ll and p1 are both 1st points traveling */ + /* in a counterclockwise direction along the perimeter. */ + + if (GEO_SAMEPOINT(compseg->lb_start, curseg->lb_next->lb_start) && + GEO_SAMEPOINT(compseg->lb_next->lb_start, curseg->lb_start)) + { + lastseg->lb_next = compseg->lb_next; + complast->lb_next = curseg->lb_next; + + freeMagic(compseg); + freeMagic(curseg); + + /* Make sure the record doesn't point to the free'd segment */ + if (compseg == bounds->bt_first) bounds->bt_first = complast; + bounds->bt_points += num_points - 2; + return; + } + } + } + } + + /* If still no connecting edge was found, or if we overflowed the GDS max */ + /* number of records for a boundary, then start a new entry. */ + +make_new_bound: + + newbounds = (BoundaryTop *)mallocMagic(sizeof(BoundaryTop)); + newbounds->bt_first = edge; + newbounds->bt_next = *blist; + newbounds->bt_points = num_points; + *blist = newbounds; +} + +/* + * ---------------------------------------------------------------------------- + * Process a LinkedBoundary list into a polygon and generate GDS output. + * Free the linked list when done. + * + * Results: + * None. + * + * Side effects: + * Output, memory deallocation. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaProcessBoundary(blist, cos) + BoundaryTop *blist; + calmaOutputStruct *cos; +{ + FILE *f = cos->f; + LinkedBoundary *listtop, *lbref, *lbstop, *lbfree; + BoundaryTop *bounds; + int sval; + int chkcount; /* diagnostic */ + + for (bounds = blist; bounds != NULL; bounds = bounds->bt_next) + { + /* Boundary */ + calmaOutRH(4, CALMA_BOUNDARY, CALMA_NODATA, f); + + /* Layer */ + calmaOutRH(6, CALMA_LAYER, CALMA_I2, f); + calmaOutI2(calmaPaintLayerNumber, f); + + /* Data type */ + calmaOutRH(6, CALMA_DATATYPE, CALMA_I2, f); + calmaOutI2(calmaPaintLayerType, f); + + /* Record length = ((#points + 1) * 2 values * 4 bytes) + 4 bytes header */ + calmaOutRH(4 + (bounds->bt_points + 1) * 8, CALMA_XY, CALMA_I4, f); + + /* Coordinates (repeat 1st point) */ + + listtop = bounds->bt_first; + lbstop = NULL; + chkcount = 0; + for (lbref = listtop; lbref != lbstop; lbref = lbref->lb_next) + { + lbstop = listtop; + calmaOutI4(lbref->lb_start.p_x * calmaPaintScale, f); + calmaOutI4(lbref->lb_start.p_y * calmaPaintScale, f); + chkcount++; + } + calmaOutI4(listtop->lb_start.p_x * calmaPaintScale, f); + calmaOutI4(listtop->lb_start.p_y * calmaPaintScale, f); + + if (chkcount != bounds->bt_points) + TxError("Points recorded=%d; Points written=%d\n", + bounds->bt_points, chkcount); + + /* End of element */ + calmaOutRH(4, CALMA_ENDEL, CALMA_NODATA, f); + +#ifdef DEBUG + /* Diagnostic: report the contents of the list */ + TxPrintf("Polygon path (%d points):\n", bounds->bt_points); + + listtop = bounds->bt_first; + lbstop = NULL; + + for (lbref = listtop; lbref != lbstop; lbref = lbref->lb_next) + { + if (lbref != listtop) + TxPrintf("->"); + else + lbstop = listtop; + + switch(lbref->lb_type) + { + case LB_EXTERNAL: + TxPrintf("(%d %d)", lbref->lb_start.p_x, lbref->lb_start.p_y); + break; + case LB_INTERNAL: + TxPrintf("[[%d %d]]", lbref->lb_start.p_x, lbref->lb_start.p_y); + break; + case LB_INIT: + TxPrintf("XXXXX"); + break; + } + } + TxPrintf("\n\n"); +#endif + + /* Free the LinkedBoundary list */ + + lbref = listtop; + while (lbref->lb_next != listtop) + { + freeMagic(lbref); + lbref = lbref->lb_next; + } + freeMagic(lbref); + } + + /* Free the BoundaryTop list */ + + for (bounds = blist; bounds != NULL; bounds = bounds->bt_next) + freeMagic(bounds); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaMergePaintFunc -- + * + * Results: + * None. + * + * Side effects: + * Writes to the disk file. + * + * ---------------------------------------------------------------------------- + */ + +int +calmaMergePaintFunc(tile, cos) + Tile *tile; /* Tile to be written out. */ + calmaOutputStruct *cos; /* Information needed by algorithm */ +{ + FILE *f = cos->f; + Rect *clipArea = cos->area; + Tile *t, *tp; + TileType ttype; + int i, llx, lly, urx, ury, intedges, num_points, split_type; + bool is_ext; + static Stack *SegStack = (Stack *)NULL; + + static LinkedBoundary *edge; + LinkedBoundary *lb; + BoundaryTop *bounds = NULL; + + /* Quick check for tiles that have already been processed */ + if (tile->ti_client == (ClientData)GDS_PROCESSED) return 0; + + if (SegStack == (Stack *)NULL) + SegStack = StackNew(64); + + PUSHTILE(tile); + while (!StackEmpty(SegStack)) + { + t = (Tile *) STACKPOP(SegStack); + if (t->ti_client != (ClientData)GDS_PENDING) continue; + t->ti_client = (ClientData)GDS_PROCESSED; + + split_type = -1; + if (IsSplit(t)) + { + /* If we use SplitSide, then we need to set it when the */ + /* tile is pushed. Since these are one-or-zero mask layers */ + /* I assume it is okay to just check which side is TT_SPACE */ + + /* split_type = (SplitSide(t) << 1) | SplitDirection(t); */ + split_type = SplitDirection(t); + if (TiGetLeftType(t) == TT_SPACE) split_type |= 2; + num_points = 2; + if (edge != NULL) + { + /* Remove one point from the edge record for rectangles */ + /* and relink the last entry back to the new head. */ + + lb = edge; + while (lb->lb_next != edge) lb = lb->lb_next; + lb->lb_next = edge->lb_next; + freeMagic(edge); + edge = edge->lb_next; + } + } + else + num_points = 3; + + /* Create a new linked boundary structure with 4 unknown edges. */ + /* This structure is reused when we encounter isolated tiles, */ + /* so we avoid unnecessary overhead in the case of, for */ + /* example, large contact cut arrays. */ + + if (edge == NULL) + { + edge = (LinkedBoundary *)mallocMagic(sizeof(LinkedBoundary)); + lb = edge; + + for (i = 0; i < num_points; i++) + { + lb->lb_type = LB_INIT; + lb->lb_next = (LinkedBoundary *)mallocMagic(sizeof(LinkedBoundary)); + lb = lb->lb_next; + } + lb->lb_type = LB_INIT; + lb->lb_next = edge; + } + + lb = edge; + llx = LEFT(t); + lly = BOTTOM(t); + urx = RIGHT(t); + ury = TOP(t); + intedges = 0; + + /* Initialize the "edge" record with the corner points of the */ + /* tile. */ + + if (IsSplit(t)) + { + switch (split_type) + { + case 0x0: + lb->lb_start.p_x = urx; + lb->lb_start.p_y = ury; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = llx; + lb->lb_start.p_y = ury; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = llx; + lb->lb_start.p_y = lly; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + break; + case 0x1: + lb->lb_start.p_x = llx; + lb->lb_start.p_y = ury; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = llx; + lb->lb_start.p_y = lly; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = urx; + lb->lb_start.p_y = lly; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + break; + case 0x2: + lb->lb_start.p_x = urx; + lb->lb_start.p_y = ury; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = llx; + lb->lb_start.p_y = lly; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = urx; + lb->lb_start.p_y = lly; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + break; + case 0x3: + lb->lb_start.p_x = urx; + lb->lb_start.p_y = ury; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = llx; + lb->lb_start.p_y = ury; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = urx; + lb->lb_start.p_y = lly; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + break; + } + num_points = 1; + } + else + { + lb->lb_start.p_x = urx; + lb->lb_start.p_y = ury; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = llx; + lb->lb_start.p_y = ury; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = llx; + lb->lb_start.p_y = lly; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + lb->lb_start.p_x = urx; + lb->lb_start.p_y = lly; + lb->lb_type = LB_INIT; + lb = lb->lb_next; + + num_points = 0; + } + if (split_type == 0x1) goto left_search; + + /* Search the tile boundary for connected and unconnected tiles. */ + /* Generate segments in a counterclockwise cycle. */ + + if (split_type == 0x2) + { + intedges += calmaAddSegment(&lb, TRUE, RIGHT(t), TOP(t), + LEFT(t), BOTTOM(t)); + goto bottom_search; + } + + /* Search top */ + + ttype = TiGetTopType(t); + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp), num_points++) + { + is_ext = (TiGetBottomType(tp) != ttype) ? TRUE : FALSE; + intedges += calmaAddSegment(&lb, is_ext, + MIN(RIGHT(t), RIGHT(tp)), TOP(t), + MAX(LEFT(t), LEFT(tp)), TOP(t)); + if (!is_ext) PUSHTILE(tp); + } + + if (split_type == 0x3) + { + intedges += calmaAddSegment(&lb, TRUE, LEFT(t), TOP(t), + RIGHT(t), BOTTOM(t)); + goto right_search; + } + + /* Search left */ + +left_search: + ttype = TiGetLeftType(t); + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp), num_points++) + { + is_ext = (TiGetRightType(tp) != ttype) ? TRUE : FALSE; + intedges += calmaAddSegment(&lb, is_ext, + LEFT(t), MIN(TOP(t), TOP(tp)), + LEFT(t), MAX(BOTTOM(t), BOTTOM(tp))); + if (!is_ext) PUSHTILE(tp); + } + + if (split_type == 0x0) + { + intedges += calmaAddSegment(&lb, TRUE, LEFT(t), BOTTOM(t), + RIGHT(t), TOP(t)); + goto done_searches; + } + + /* Search bottom */ + +bottom_search: + ttype = TiGetBottomType(t); + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp), num_points++) + { + is_ext = (TiGetTopType(tp) != ttype) ? TRUE : FALSE; + intedges += calmaAddSegment(&lb, is_ext, + MAX(LEFT(t), LEFT(tp)), BOTTOM(t), + MIN(RIGHT(t), RIGHT(tp)), BOTTOM(t)); + if (!is_ext) PUSHTILE(tp); + } + + if (split_type == 0x1) + { + intedges += calmaAddSegment(&lb, TRUE, RIGHT(t), BOTTOM(t), + LEFT(t), TOP(t)); + goto done_searches; + } + /* Search right */ + +right_search: + ttype = TiGetRightType(t); + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp), num_points++) + { + is_ext = (TiGetLeftType(tp) != ttype) ? TRUE : FALSE; + intedges += calmaAddSegment(&lb, is_ext, + RIGHT(t), MAX(BOTTOM(t), BOTTOM(tp)), + RIGHT(t), MIN(TOP(t), TOP(tp))); + if (!is_ext) PUSHTILE(tp); + } + + /* If tile is isolated, process it now and we're done */ + +done_searches: + if (intedges == 0) + { + calmaWritePaintFunc(t, cos); + + /* Although calmaWritePaintFunc is called only on isolated */ + /* tiles, we may have expanded it. This could use a LOT of */ + /* optimizing. 1) remove colinear points in calmaAddSegment */ + /* when both subsegments are external paths, and 2) here, */ + /* take the shortest path to making "edge" exactly 4 points.*/ + /* Note that in non-Manhattan mode, num_points may be 3. */ + + if (num_points != 4) + { + for (i = 0; i < num_points; i++) + { + freeMagic(edge); + edge = edge->lb_next; + } + edge = NULL; + } + if (!StackEmpty(SegStack)) + TxError("ERROR: Segment stack is supposed to be empty!\n"); + else + return 0; + } + else + { + /* Merge boundary into existing record */ + + calmaMergeSegments(edge, &bounds, num_points); + edge = NULL; + } + } + + /* Remove any degenerate points */ + calmaRemoveDegenerate(bounds); + + /* Remove any colinear points */ + calmaRemoveColinear(bounds); + + /* Output the boundary records */ + calmaProcessBoundary(bounds, cos); + + return 0; /* Keep the search alive. . . */ +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaWritePaintFunc -- + * + * Filter function used to write out a single paint tile. + * + * **** NOTE **** + * There are loads of Calma systems out in the world that + * don't understand CALMA_BOX, so we output CALMA_BOUNDARY + * even though CALMA_BOX is more appropriate. Bletch. + * + * Results: + * None. + * + * Side effects: + * Writes to the disk file. + * + * ---------------------------------------------------------------------------- + */ + +int +calmaWritePaintFunc(tile, cos) + Tile *tile; /* Tile to be written out. */ + calmaOutputStruct *cos; /* File for output and clipping area */ +{ + FILE *f = cos->f; + Rect *clipArea = cos->area; + Rect r, r2; + + TiToRect(tile, &r); + if (clipArea != NULL) + GeoClip(&r, clipArea); + + r.r_xbot *= calmaPaintScale; + r.r_ybot *= calmaPaintScale; + r.r_xtop *= calmaPaintScale; + r.r_ytop *= calmaPaintScale; + + /* Boundary */ + calmaOutRH(4, CALMA_BOUNDARY, CALMA_NODATA, f); + + /* Layer */ + calmaOutRH(6, CALMA_LAYER, CALMA_I2, f); + calmaOutI2(calmaPaintLayerNumber, f); + + /* Data type */ + calmaOutRH(6, CALMA_DATATYPE, CALMA_I2, f); + calmaOutI2(calmaPaintLayerType, f); + + /* The inefficient use of CALMA_BOUNDARY for rectangles actually */ + /* makes it easy to implement triangles, since they must be defined */ + /* by CALMA_BOUNDARY. */ + + if (IsSplit(tile)) + { + /* Coordinates */ + calmaOutRH(36, CALMA_XY, CALMA_I4, f); + + switch ((SplitSide(tile) << 1) | SplitDirection(tile)) + { + case 0x0: + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f); + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ytop, f); + calmaOutI4(r.r_xtop, f); calmaOutI4(r.r_ytop, f); + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f); + break; + case 0x1: + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ytop, f); + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f); + calmaOutI4(r.r_xtop, f); calmaOutI4(r.r_ybot, f); + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ytop, f); + break; + case 0x2: + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f); + calmaOutI4(r.r_xtop, f); calmaOutI4(r.r_ybot, f); + calmaOutI4(r.r_xtop, f); calmaOutI4(r.r_ytop, f); + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f); + break; + case 0x3: + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ytop, f); + calmaOutI4(r.r_xtop, f); calmaOutI4(r.r_ytop, f); + calmaOutI4(r.r_xtop, f); calmaOutI4(r.r_ybot, f); + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ytop, f); + break; + } + } + else + { + /* Coordinates */ + calmaOutRH(44, CALMA_XY, CALMA_I4, f); + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f); + calmaOutI4(r.r_xtop, f); calmaOutI4(r.r_ybot, f); + calmaOutI4(r.r_xtop, f); calmaOutI4(r.r_ytop, f); + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ytop, f); + calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f); + } + + /* End of element */ + calmaOutRH(4, CALMA_ENDEL, CALMA_NODATA, f); + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaWriteLabelFunc -- + * + * Output a single label to the stream file 'f'. + * + * The CIF type to which this label is attached is 'type'; if this + * is < 0 then the label is not output. + * + * Non-point labels are collapsed to point labels located at the center + * of the original label. + * + * Results: + * None. + * + * Side effects: + * Writes to the FILE 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaWriteLabelFunc(lab, type, f) + Label *lab; /* Label to output */ + int type; /* CIF layer number, or -1 if not attached to a layer */ + FILE *f; /* Stream file */ +{ + Point p; + int calmanum; + + if (type < 0) + return; + + calmanum = CIFCurStyle->cs_layers[type]->cl_calmanum; + if (!CalmaIsValidLayer(calmanum)) + return; + + calmaOutRH(4, CALMA_TEXT, CALMA_NODATA, f); + + calmaOutRH(6, CALMA_LAYER, CALMA_I2, f); + calmaOutI2(calmanum, f); + + calmaOutRH(6, CALMA_TEXTTYPE, CALMA_I2, f); + calmaOutI2(CIFCurStyle->cs_layers[type]->cl_calmatype, f); + + if (lab->lab_font >= 0) + { + unsigned short textpres = 0; + + /* A bit of a hack here. Magic can have any number of fonts, */ + /* but GDS only allows four of them. So we just crop the font */ + /* index to two bits. We provide no other font information, so */ + /* this is highly implementation-dependent. But it allows us */ + /* to retain font information when reading and writing our own */ + /* GDS files. */ + + textpres = (lab->lab_font & 0x03) << 4; + + switch(lab->lab_just) + { + case GEO_SOUTH: + textpres |= 0x0001; + break; + case GEO_SOUTHEAST: + textpres |= 0x0000; + break; + case GEO_EAST: + textpres |= 0x0004; + break; + case GEO_NORTHEAST: + textpres |= 0x0008; + break; + case GEO_NORTH: + textpres |= 0x0009; + break; + case GEO_NORTHWEST: + textpres |= 0x000a; + break; + case GEO_WEST: + textpres |= 0x0006; + break; + case GEO_SOUTHWEST: + textpres |= 0x0002; + break; + case GEO_CENTER: + textpres |= 0x0005; + break; + } + + calmaOutRH(6, CALMA_PRESENTATION, CALMA_BITARRAY, f); + calmaOutI2(textpres, f); + + calmaOutRH(6, CALMA_STRANS, CALMA_BITARRAY, f); + calmaOutI2(0, f); /* Any need for these bits? */ + + calmaOutRH(12, CALMA_MAG, CALMA_R8, f); + calmaOutR8(((double)lab->lab_size / 800) + * (double)CIFCurStyle->cs_scaleFactor + / (double)CIFCurStyle->cs_expander, f); + + if (lab->lab_rotate != 0) + { + calmaOutRH(12, CALMA_ANGLE, CALMA_R8, f); + calmaOutR8((double)lab->lab_rotate, f); + } + } + + p.p_x = (lab->lab_rect.r_xbot + lab->lab_rect.r_xtop) * calmaWriteScale / 2; + p.p_y = (lab->lab_rect.r_ybot + lab->lab_rect.r_ytop) * calmaWriteScale / 2; + calmaOutRH(12, CALMA_XY, CALMA_I4, f); + calmaOutI4(p.p_x, f); + calmaOutI4(p.p_y, f); + + /* Text of label */ + calmaOutStringRecord(CALMA_STRING, lab->lab_text, f); + + /* End of element */ + calmaOutRH(4, CALMA_ENDEL, CALMA_NODATA, f); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaOutHeader -- + * + * Output the header description for a Calma file. + * + * Results: + * None. + * + * Side effects: + * Writes to the FILE 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaOutHeader(rootDef, f) + CellDef *rootDef; + FILE *f; +{ + static double useru = 0.001; + static double mum = 1.0e-9; + + /* GDS II version 3.0 */ + calmaOutRH(6, CALMA_HEADER, CALMA_I2, f); + calmaOutI2(3, f); + + /* Beginning of library */ + calmaOutRH(28, CALMA_BGNLIB, CALMA_I2, f); + calmaOutDate(rootDef->cd_timestamp, f); + calmaOutDate(time((time_t *) 0), f); + + /* Library name (name of root cell) */ + calmaOutStructName(CALMA_LIBNAME, rootDef, f); + + /* + * Units. + * User units are microns; this is really unimportant. + * + * Database units are nanometers, since there are + * programs that don't understand anything else. If + * the database units are *smaller* than nanometers, use + * the actual database units. Otherwise, stick with + * nanometers, because anything larger may not input + * properly with other software. + */ + + calmaOutRH(20, CALMA_UNITS, CALMA_R8, f); + if (CIFCurStyle->cs_flags & CWF_ANGSTROMS) useru = 0.0001; + calmaOutR8(useru, f); /* User units per database unit */ + + if (CIFCurStyle->cs_flags & CWF_ANGSTROMS) mum = 1e-10; + calmaOutR8(mum, f); /* Meters per database unit */ +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaOutDate -- + * + * Output a date/time specification to the FILE 'f'. + * This consists of outputting 6 2-byte quantities, + * or a total of 12 bytes. + * + * Results: + * None. + * + * Side effects: + * Writes to the FILE 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaOutDate(t, f) + time_t t; /* Time (UNIX format) to be output */ + FILE *f; /* Stream file */ +{ + struct tm *datep = localtime(&t); + + calmaOutI2(datep->tm_year, f); + calmaOutI2(datep->tm_mon+1, f); + calmaOutI2(datep->tm_mday, f); + calmaOutI2(datep->tm_hour, f); + calmaOutI2(datep->tm_min, f); + calmaOutI2(datep->tm_sec, f); +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaOutStringRecord -- + * + * Output a complete string-type record. The actual record + * type is given by 'type'. Up to the first CALMANAMELENGTH characters + * of the string 'str' are output. Any characters in 'str' + * not in the legal Calma stream character set are output as + * 'X' instead. + * + * Results: + * None. + * + * Side effects: + * Writes to the FILE 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaOutStringRecord(type, str, f) + int type; /* Type of this record (data type is ASCII string) */ + char *str; /* String to be output (<= CALMANAMELENGTH chars) */ + FILE *f; /* Stream file */ +{ + int len; + unsigned char c; + char *table, *locstr, *origstr = NULL; + char *locstrprv; /* Added by BSI */ + + if(CIFCurStyle->cs_flags & CWF_PERMISSIVE_LABELS) + { + table = calmaMapTablePermissive; + } else { + table = calmaMapTableStrict; + } + + len = strlen(str); + locstr = str; + + /* + * Make sure length is even. + * Output at most CALMANAMELENGTH characters. + */ + if (len & 01) len++; + if (len > CALMANAMELENGTH) len = CALMANAMELENGTH; + calmaOutI2(len+4, f); /* Record length */ + (void) putc(type, f); /* Record type */ + (void) putc(CALMA_ASCII, f); /* Data type */ + + /* Output the string itself */ + while (len--) + { + locstrprv = locstr; + c = (unsigned char) *locstr++; + if (c == 0) putc('\0', f); + else + { + if ((c > 127) || (c == 0)) + { + TxError("Warning: Unprintable character changed " + "to \'X\' in label.\n"); + c = 'X'; + } + else + { + if (((unsigned char)table[c] != c) && (origstr == NULL)) + origstr = StrDup(NULL, str); + + c = table[c]; + locstrprv[0] = c; + } + if (!CalmaDoLower && islower(c)) + (void) putc(toupper(c), f); + else + (void) putc(c, f); + } + } + if (origstr != NULL) + { + TxError("Warning: characters changed in string \'%s\'; " + "modified string is \'%s\'\n", origstr, str); + freeMagic(origstr); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * calmaOutR8 -- + * + * Write an 8-byte Real value in GDS-II format to the output stream + * The value is passed as a double. + * + * Results: + * None. + * + * Side effects: + * 8-byte value written to output stream FILE 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaOutR8(d, f) + double d; /* Double value to write to output */ + FILE *f; /* Stream file */ +{ + int c, i, sign, expon; + + /* mantissa must be 64 bits for this routine to work correctly */ + uint64_t mantissa; + + mantissa = 0; + if (d == 0.0) + { + sign = 0; + expon = 0; + } + else + { + if (d > 0.0) + sign = 0; + else + { + sign = 1; + d = -d; + } + + expon = 64; + while (d >= 1.0) + { + d /= 16.0; + expon++; + } + while (d < 0.0625) + { + d *= 16.0; + expon--; + } + + for (i = 0; i < 64; i++) + { + mantissa <<= 1; + if (d >= 0.5) + { + mantissa |= 0x1; + d -= 0.5; + } + d *= 2.0; + } + } + c = (sign << 7) | expon; + (void) putc(c, f); + for (i = 1; i < 8; i++) + { + c = (int)(0xff & (mantissa >> (64 - (8 * i)))); + (void) putc(c, f); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * calmaOut8 -- + * + * Output 8 bytes. + * + * Results: + * None. + * + * Side effects: + * Writes to the FILE 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +calmaOut8(str, f) + char *str; /* 8-byte string to be output */ + FILE *f; /* Stream file */ +{ + int i; + + for (i = 0; i < 8; i++) + (void) putc(*str++, f); +} diff --git a/calma/Depend b/calma/Depend new file mode 100644 index 00000000..32ed8d2a --- /dev/null +++ b/calma/Depend @@ -0,0 +1,30 @@ +CalmaRead.o: CalmaRead.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/utils.h ../utils/hash.h ../database/database.h \ + ../database/databaseInt.h ../utils/malloc.h ../utils/tech.h ../cif/cif.h \ + ../cif/CIFint.h ../cif/CIFread.h ../utils/signals.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../textio/textio.h \ + ../calma/calmaInt.h ../commands/commands.h ../utils/undo.h +CalmaRdcl.o: CalmaRdcl.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/utils.h ../utils/hash.h ../database/database.h \ + ../database/databaseInt.h ../utils/malloc.h ../utils/tech.h ../cif/cif.h \ + ../cif/CIFint.h ../cif/CIFread.h ../utils/signals.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../textio/textio.h \ + ../calma/calmaInt.h ../calma/calma.h +CalmaRdio.o: CalmaRdio.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/utils.h ../utils/hash.h ../database/database.h \ + ../database/databaseInt.h ../utils/malloc.h ../utils/tech.h ../cif/cif.h \ + ../cif/CIFint.h ../cif/CIFread.h ../utils/signals.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../textio/textio.h \ + ../calma/calmaInt.h +CalmaRdpt.o: CalmaRdpt.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/utils.h ../utils/hash.h ../database/database.h \ + ../database/databaseInt.h ../utils/malloc.h ../utils/tech.h ../cif/cif.h \ + ../cif/CIFint.h ../cif/CIFread.h ../utils/signals.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../textio/textio.h \ + ../calma/calmaInt.h ../calma/calma.h +CalmaWrite.o: CalmaWrite.c ../utils/magic.h ../utils/malloc.h \ + ../utils/geometry.h ../tiles/tile.h ../utils/utils.h ../utils/hash.h \ + ../database/database.h ../database/databaseInt.h ../utils/tech.h \ + ../cif/cif.h ../cif/CIFint.h ../utils/signals.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../textio/textio.h \ + ../calma/calmaInt.h ../utils/main.h ../utils/stack.h diff --git a/calma/Makefile b/calma/Makefile new file mode 100644 index 00000000..1df8d4f8 --- /dev/null +++ b/calma/Makefile @@ -0,0 +1,10 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/calma/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +MODULE = calma +MAGICDIR = .. +SRCS = CalmaRead.c CalmaRdcl.c CalmaRdio.c CalmaRdpt.c CalmaWrite.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/calma/calma.h b/calma/calma.h new file mode 100644 index 00000000..c649e205 --- /dev/null +++ b/calma/calma.h @@ -0,0 +1,45 @@ +/* + * calma.h -- + * + * This file defines things that are exported by the + * calma module to the rest of the world. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/calma/calma.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _CALMA_H +#define _CALMA_H + +#include "utils/magic.h" + +/* Externally visible variables */ +extern bool CalmaSubcellPolygons; +extern bool CalmaDoLabels; +extern bool CalmaDoLower; +extern bool CalmaMergeTiles; +extern bool CalmaFlattenArrays; +extern bool CalmaNoDRCCheck; +extern bool CalmaFlattenUses; +extern bool CalmaReadOnly; +extern bool CalmaContactArrays; +extern bool CalmaPostOrder; + +/* Externally-visible procedures: */ +extern bool CalmaWrite(); +extern void CalmaReadFile(); +extern void CalmaTechInit(); +extern bool CalmaGenerateArray(); + +#endif /* _CALMA_H */ diff --git a/calma/calmaInt.h b/calma/calmaInt.h new file mode 100644 index 00000000..49b3d94c --- /dev/null +++ b/calma/calmaInt.h @@ -0,0 +1,235 @@ +/* + * calma.h -- + * + * This file defines constants used internally by the calma + * module, but not exported to the rest of the world. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/calma/calmaInt.h,v 1.2 2010/06/24 12:37:15 tim Exp $ + */ + +#ifndef _CALMAINT_H +#define _CALMAINT_H + +#include "utils/magic.h" +#include "database/database.h" + +/* Record data types */ +#define CALMA_NODATA 0 /* No data present */ +#define CALMA_BITARRAY 1 /* Bit array */ +#define CALMA_I2 2 /* 2 byte integer */ +#define CALMA_I4 3 /* 4 byte integer */ +#define CALMA_R4 4 /* 4 byte real */ +#define CALMA_R8 5 /* 8 byte real */ +#define CALMA_ASCII 6 /* ASCII string */ + +/* Record types */ +#define CALMA_HEADER 0 +#define CALMA_BGNLIB 1 +#define CALMA_LIBNAME 2 +#define CALMA_UNITS 3 +#define CALMA_ENDLIB 4 +#define CALMA_BGNSTR 5 +#define CALMA_STRNAME 6 +#define CALMA_ENDSTR 7 +#define CALMA_BOUNDARY 8 +#define CALMA_PATH 9 +#define CALMA_SREF 10 +#define CALMA_AREF 11 +#define CALMA_TEXT 12 +#define CALMA_LAYER 13 +#define CALMA_DATATYPE 14 +#define CALMA_WIDTH 15 +#define CALMA_XY 16 +#define CALMA_ENDEL 17 +#define CALMA_SNAME 18 +#define CALMA_COLROW 19 +#define CALMA_TEXTNODE 20 +#define CALMA_NODE 21 +#define CALMA_TEXTTYPE 22 +#define CALMA_PRESENTATION 23 +#define CALMA_SPACING 24 +#define CALMA_STRING 25 +#define CALMA_STRANS 26 +#define CALMA_MAG 27 +#define CALMA_ANGLE 28 +#define CALMA_UINTEGER 29 +#define CALMA_USTRING 30 +#define CALMA_REFLIBS 31 +#define CALMA_FONTS 32 +#define CALMA_PATHTYPE 33 +#define CALMA_GENERATIONS 34 +#define CALMA_ATTRTABLE 35 +#define CALMA_STYPTABLE 36 +#define CALMA_STRTYPE 37 +#define CALMA_ELFLAGS 38 +#define CALMA_ELKEY 39 +#define CALMA_LINKTYPE 40 +#define CALMA_LINKKEYS 41 +#define CALMA_NODETYPE 42 +#define CALMA_PROPATTR 43 +#define CALMA_PROPVALUE 44 +#define CALMA_BOX 45 +#define CALMA_BOXTYPE 46 +#define CALMA_PLEX 47 +#define CALMA_BGNEXTN 48 +#define CALMA_ENDEXTN 49 +#define CALMA_TAPENUM 50 +#define CALMA_TAPECODE 51 +#define CALMA_STRCLASS 52 +#define CALMA_RESERVED 53 +#define CALMA_FORMAT 54 +#define CALMA_MASK 55 +#define CALMA_ENDMASKS 56 +#define CALMA_LIBDIRSIZE 57 +#define CALMA_SRFNAME 58 +#define CALMA_LIBSECUR 59 + +#define CALMA_NUMRECORDTYPES 60 /* Number of above types */ + +/* Property types defined for magic */ +#define CALMA_PROP_USENAME 98 /* To record non-default cell use ids */ +#define CALMA_PROP_ARRAY_LIMITS 99 /* To record non-default array limits */ + +/* Flags for transforms */ +#define CALMA_STRANS_UPSIDEDOWN 0x8000 /* Mirror about X axis before rot */ +#define CALMA_STRANS_ROTATE 0x0002 /* Rotate by absolute angle */ + +/* Path types */ +#define CALMAPATH_SQUAREFLUSH 0 /* Square end flush with endpoint */ +#define CALMAPATH_ROUND 1 /* Round end */ +#define CALMAPATH_SQUAREPLUS 2 /* Square end plus half-width extent */ + +/* Largest calma layer or data type numbers */ +#define CALMA_LAYER_MAX 255 + +#define CalmaIsValidLayer(n) ((n) >= 0 && (n) <= CALMA_LAYER_MAX) + +/* Used to index hash tables of (layer, datatype) pairs */ +typedef struct +{ + int clt_layer; + int clt_type; +} CalmaLayerType; + +/* Biggest calma string */ +#define CALMANAMELENGTH 32 + +/* Length of record header */ +#define CALMAHEADERLENGTH 4 + +/* ------------------------- Input macros ----------------------------- */ + +/* Globals for Calma reading */ +extern FILE *calmaInputFile; +extern char *calmaFilename; +extern int calmaReadScale1; +extern int calmaReadScale2; +extern bool calmaLApresent; +extern int calmaLAnbytes; +extern int calmaLArtype; + +/* + * Macros for number representation conversion. + */ +#ifdef ibm032 +#include /* as macros in in.h and don't exist as routines */ +#endif + +#ifndef ntohl +# ifdef WORDS_BIGENDIAN +# define ntohl(x) (x) +# define ntohs(x) (x) +# define htonl(x) (x) +# define htons(x) (x) +# endif +#endif + +typedef union { char uc[2]; unsigned short us; } TwoByteInt; +typedef union { char uc[4]; unsigned int ul; } FourByteInt; + +/* Macro to read a 2-byte integer */ +#define READI2(z) \ + { \ + TwoByteInt u; \ + u.uc[0] = getc(calmaInputFile); \ + u.uc[1] = getc(calmaInputFile); \ + (z) = (int) ntohs(u.us); \ + } + +/* Macro to read a 4-byte integer */ +#define READI4(z) \ + { \ + FourByteInt u; \ + u.uc[0] = getc(calmaInputFile); \ + u.uc[1] = getc(calmaInputFile); \ + u.uc[2] = getc(calmaInputFile); \ + u.uc[3] = getc(calmaInputFile); \ + (z) = (int) ntohl(u.ul); \ + } + +/* Macros for reading and unreading record headers */ +#define READRH(nb, rt) \ + { \ + if (calmaLApresent) { \ + (nb) = calmaLAnbytes; \ + (rt) = calmaLArtype; \ + calmaLApresent = FALSE; \ + } else { \ + READI2(nb); \ + if (feof(calmaInputFile)) nb = -1; \ + else { \ + (rt) = getc(calmaInputFile); \ + (void) getc(calmaInputFile); \ + } \ + } \ + } + +#define UNREADRH(nb, rt) \ + { \ + ASSERT(!calmaLApresent, "UNREADRH"); \ + calmaLApresent = TRUE; \ + calmaLAnbytes = (nb); \ + calmaLArtype = (rt); \ + } + +#define PEEKRH(nb, rt) \ + { \ + READRH(nb, rt); \ + UNREADRH(nb, rt); \ + } + +/* Other commonly used globals */ +extern HashTable calmaLayerHash; +extern int calmaElementIgnore[]; +extern CellDef *calmaFindCell(); + +/* (Added by Nishit, 8/18/2004--8/24/2004) */ +extern CellDef *calmaLookCell(); +extern void calmaWriteContact(); +extern CellDef *calmaGetContactCell(); +extern bool calmaIsContactCell; + +extern char *calmaRecordName(); +extern void calmaSkipSet(); + +/* ------------------- Imports from CIF reading ----------------------- */ + +extern CellDef *cifReadCellDef; +extern Plane *cifSubcellPlanes[]; +extern Plane **cifCurReadPlanes; +extern HashTable CifCellTable; +extern Plane *cifEditCellPlanes[]; + +#endif /* _CALMAINT_H */ diff --git a/cif/CIFgen.c b/cif/CIFgen.c new file mode 100644 index 00000000..86eb3fb7 --- /dev/null +++ b/cif/CIFgen.c @@ -0,0 +1,3338 @@ +/* CIFgen.c - + * + * This file provides routines that generate CIF from Magic + * tile information, using one of the styles read from the + * technology file. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFgen.c,v 1.23 2010/06/24 20:35:54 tim Exp $"; +#endif /* not lint */ + +#include +#include /* for abs() */ +#include /* for ceil() and sqrt() */ + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "cif/CIFint.h" +#include "calma/calma.h" /* for CalmaContactArrays */ +#include "commands/commands.h" /* for CmdFindNetProc() */ +#include "select/selInt.h" /* for select use and def */ +#include "utils/stack.h" +#include "utils/malloc.h" +#include "utils/maxrect.h" + +/* TRUE to run (very slow) algorithm for optimizing non-manhattan tiles */ +/* (cuts size of output; see also the GDS "merge" option) */ +bool CIFUnfracture = FALSE; + +/* The following global arrays hold pointers to the CIF planes + * generated by the procedures in this module. There are two + * kinds of planes: real CIF, which will ostensibly be output, + * and temporary layers used to build up more complex geometric + * functions. + */ + +global Plane *CIFPlanes[MAXCIFLAYERS]; + +/* The following are paint tables used by the routines that implement + * the geometric operations on mask layers, such as AND, OR, GROW, + * etc. There are really only two tables. The first will paint + * CIF_SOLIDTYPE over anything else, and the second will paint + * space over anything else. These tables are used on planes with + * only two tile types, TT_SPACE and CIF_SOLIDTYPE, so they only + * have two entries each. + */ + +PaintResultType CIFPaintTable[] = {CIF_SOLIDTYPE, CIF_SOLIDTYPE}; +PaintResultType CIFEraseTable[] = {TT_SPACE, TT_SPACE}; + +/* The following local variables are used as a convenience to pass + * information between CIFGen and the various search functions. + */ + +static int growDistance; /* Distance to grow stuff. */ +static Plane *cifPlane; /* Plane acted on by search functions. */ +static int cifScale; /* Scale factor to use on tiles. */ + +extern void cifClipPlane(); +extern void cifGenClip(); + +/* + * ---------------------------------------------------------------------------- + * + * cifPaintFunc -- + * + * This search function is called during CIF_AND and CIF_OR + * and CIF_ANDNOT operations for each relevant tile. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * For the area of the tile, either paints or erases in + * cifNewPlane, depending on the paint table passed as parameter. + * The tile's area is scaled by cifScale first. + * ---------------------------------------------------------------------------- + */ + +int +cifPaintFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Used for painting. */ +{ + Rect area; + + TiToRect(tile, &area); + area.r_xbot *= cifScale; + area.r_xtop *= cifScale; + area.r_ybot *= cifScale; + area.r_ytop *= cifScale; + + DBNMPaintPlane(cifPlane, TiGetTypeExact(tile), &area, table, + (PaintUndoInfo *) NULL); + CIFTileOps += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifGrowGridFunc -- + * + * Called for each relevant tile during grow-grid operations. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Scales the tile by cifScale, then expands its area by the + * remainder of the distance to the nearest grid point, as + * defined by the grid distance (growDistance) in the current + * CIFOp, then paints this area into cifNewPlane using the table + * passed as parameter. + * ---------------------------------------------------------------------------- + */ + +int +cifGrowGridFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Table to be used for painting. */ +{ + Rect area; + int remainder; + + /* To be done---handle non-Manhattan geometry */ + TileType oldType = TiGetType(tile); + + TiToRect(tile, &area); + + /* In scaling the tile, watch out for infinities!! If something + * is already infinity, don't change it. */ + + if (area.r_xbot > TiPlaneRect.r_xbot) area.r_xbot *= cifScale; + if (area.r_ybot > TiPlaneRect.r_ybot) area.r_ybot *= cifScale; + if (area.r_xtop < TiPlaneRect.r_xtop) area.r_xtop *= cifScale; + if (area.r_ytop < TiPlaneRect.r_ytop) area.r_ytop *= cifScale; + + /* In scaling the tile, watch out for infinities!! If something + * is already infinity, don't change it. */ + + if (area.r_xbot > TiPlaneRect.r_xbot) + area.r_xbot -= (abs(area.r_xbot) % growDistance); + if (area.r_ybot > TiPlaneRect.r_ybot) + area.r_ybot -= (abs(area.r_ybot) % growDistance); + if (area.r_xtop < TiPlaneRect.r_xtop) + area.r_xtop += (abs(area.r_xtop) % growDistance); + if (area.r_ytop < TiPlaneRect.r_ytop) + area.r_ytop += (abs(area.r_ytop) % growDistance); + + DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL); + + CIFTileOps += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifGrowEuclideanFunc -- + * + * Called for each relevant tile during grow or shrink operations. + * For growing, these are solid tiles. For shrinking, these are + * space tiles. This routine differs from cifGrowFunc in that it + * grows the minimum distance on non-Manhattan edges necessary to + * create a euclidean distance to the edge of growDistance while + * keeping corner points on-grid. This requires a substantially + * different algorithm from cifGrowFunc. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Scales the tile by cifScale, then expands its area by the + * distance in the current CIFOp, then paints this area into + * cifNewPlane using the table passed as parameter. + * ---------------------------------------------------------------------------- + */ + +#define GROW_NORTH 0x1 +#define GROW_SOUTH 0x2 +#define GROW_EAST 0x4 +#define GROW_WEST 0x8 + +#define STOP_NW 0x1 /* WN EN */ +#define STOP_SW 0x2 /* NW +-------+ NE */ +#define STOP_NE 0x4 /* | | */ +#define STOP_SE 0x8 /* | | */ +#define STOP_WN 0x10 /* SW +-------+ SE */ +#define STOP_WS 0x20 /* WS ES */ +#define STOP_EN 0x40 +#define STOP_ES 0x80 + +int +cifGrowEuclideanFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Table to be used for painting. */ +{ + Tile *tp; + Rect area, rtmp; + TileType oldType = TiGetTypeExact(tile); + unsigned char growDirs = GROW_NORTH | GROW_SOUTH | GROW_EAST | GROW_WEST; + unsigned char cornerDirs = 0; + + TiToRect(tile, &area); + + /* In scaling the tile, watch out for infinities!! If something + * is already infinity, don't change it. */ + + if (area.r_xbot > TiPlaneRect.r_xbot) + area.r_xbot *= cifScale; + else + growDirs &= ~GROW_WEST; + if (area.r_ybot > TiPlaneRect.r_ybot) + area.r_ybot *= cifScale; + else + growDirs &= ~GROW_SOUTH; + if (area.r_xtop < TiPlaneRect.r_xtop) + area.r_xtop *= cifScale; + else + growDirs &= ~GROW_EAST; + if (area.r_ytop < TiPlaneRect.r_ytop) + area.r_ytop *= cifScale; + else + growDirs &= ~GROW_NORTH; + + /* Grow on diagonal tiles: grow rectangular tiles around the */ + /* straight edges of the right-triangle, then copy the diagonal */ + /* tile (at its original size) in the direction of the diagonal. */ + /* Note: A diagonal tile, by definition, can't have infinities. */ + + if (oldType & TT_DIAGONAL) + { + int growDistanceX, growDistanceY; + int height, width; + double hyp; + + if (oldType & TT_SIDE) + growDirs &= ~GROW_WEST; + else + growDirs &= ~GROW_EAST; + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) + growDirs &= ~GROW_SOUTH; + else + growDirs &= ~GROW_NORTH; + + /* Grow non-Manhattan edges to (the closest integer value */ + /* to) growDistance along the normal to the edge. This */ + /* will overestimate the distance only to the minimum */ + /* amount necessary to ensure on-grid endpoints. */ + + width = area.r_xtop - area.r_xbot; + height = area.r_ytop - area.r_ybot; + hyp = sqrt((double)(width * width + height * height)); + growDistanceY = ceil((growDistance * (hyp - height)) / width); + growDistanceX = ceil((growDistance * (hyp - width)) / height); + + /* Draw vertical tile to distance X */ + + rtmp = area; + if (!(growDirs & GROW_EAST)) rtmp.r_xtop = rtmp.r_xbot + growDistanceX; + if (!(growDirs & GROW_WEST)) rtmp.r_xbot = rtmp.r_xtop - growDistanceX; + if (!(growDirs & GROW_SOUTH)) rtmp.r_ybot -=growDistance; + if (!(growDirs & GROW_NORTH)) rtmp.r_ytop += growDistance; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + + /* Draw horizontal tile to distance Y */ + + rtmp = area; + if (!(growDirs & GROW_EAST)) rtmp.r_xtop += growDistance; + if (!(growDirs & GROW_WEST)) rtmp.r_xbot -= growDistance; + if (!(growDirs & GROW_SOUTH)) rtmp.r_ybot = rtmp.r_ytop - growDistanceY; + if (!(growDirs & GROW_NORTH)) rtmp.r_ytop = rtmp.r_ybot + growDistanceY; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + + /* Finally: translate, resize, and paint the diagonal tile */ + + rtmp = area; + + if (!(growDirs & GROW_NORTH)) + rtmp.r_ytop += growDistance; + else + rtmp.r_ytop -= growDistanceY; + if (!(growDirs & GROW_SOUTH)) + rtmp.r_ybot -= growDistance; + else + rtmp.r_ybot += growDistanceY; + if (!(growDirs & GROW_EAST)) + rtmp.r_xtop += growDistance; + else + rtmp.r_xtop -= growDistanceX; + if (!(growDirs & GROW_WEST)) + rtmp.r_xbot -= growDistance; + else + rtmp.r_xbot += growDistanceX; + + DBNMPaintPlane(cifPlane, oldType, &rtmp, table, (PaintUndoInfo *) NULL); + oldType = (growDirs & GROW_EAST) ? TiGetRightType(tile) : TiGetLeftType(tile); + } + else + DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL); + + /* Check tile corner areas for paint */ + + tp = TR(tile); + if (TiGetLeftType(tp) == oldType) cornerDirs |= STOP_NE; + for (; TOP(LB(tp)) > BOTTOM(tile); tp = LB(tp)); + if (TiGetLeftType(tp) == oldType) cornerDirs |= STOP_SE; + + tp = RT(tile); + if (TiGetBottomType(tp) == oldType) cornerDirs |= STOP_EN; + for (; RIGHT(BL(tp)) > LEFT(tile); tp = BL(tp)); + if (TiGetBottomType(tp) == oldType) cornerDirs |= STOP_WN; + + tp = BL(tile); + if (TiGetRightType(tp) == oldType) cornerDirs |= STOP_SW; + for (; BOTTOM(RT(tp)) < TOP(tile); tp = RT(tp)); + if (TiGetRightType(tp) == oldType) cornerDirs |= STOP_NW; + + tp = LB(tile); + if (TiGetTopType(tp) == oldType) cornerDirs |= STOP_WS; + for (; LEFT(TR(tp)) < RIGHT(tile); tp = TR(tp)); + if (TiGetTopType(tp) == oldType) cornerDirs |= STOP_ES; + + if (growDirs & GROW_NORTH) + { + rtmp = area; + rtmp.r_ybot = area.r_ytop; + rtmp.r_ytop = area.r_ytop + growDistance; + if ((cornerDirs & (STOP_EN | STOP_NE)) == 0) + if (growDirs & GROW_EAST) rtmp.r_xtop += growDistance; + if ((cornerDirs & (STOP_WN | STOP_NW)) == 0) + if (growDirs & GROW_WEST) rtmp.r_xbot -= growDistance; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + } + + if (growDirs & GROW_EAST) + { + rtmp = area; + rtmp.r_xbot = area.r_xtop; + rtmp.r_xtop = area.r_xtop + growDistance; + if ((cornerDirs & (STOP_EN | STOP_NE)) == 0) + if (growDirs & GROW_NORTH) rtmp.r_ytop += growDistance; + if ((cornerDirs & (STOP_SE | STOP_ES)) == 0) + if (growDirs & GROW_SOUTH) rtmp.r_ybot -= growDistance; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + } + + if (growDirs & GROW_SOUTH) + { + rtmp = area; + rtmp.r_ytop = area.r_ybot; + rtmp.r_ybot = area.r_ybot - growDistance; + if ((cornerDirs & (STOP_SE | STOP_ES)) == 0) + if (growDirs & GROW_EAST) rtmp.r_xtop += growDistance; + if ((cornerDirs & (STOP_SW | STOP_WS)) == 0) + if (growDirs & GROW_WEST) rtmp.r_xbot -= growDistance; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + } + + if (growDirs & GROW_WEST) + { + rtmp = area; + rtmp.r_xtop = area.r_xbot; + rtmp.r_xbot = area.r_xbot - growDistance; + if ((cornerDirs & (STOP_NW | STOP_WN)) == 0) + if (growDirs & GROW_NORTH) rtmp.r_ytop += growDistance; + if ((cornerDirs & (STOP_SW | STOP_WS)) == 0) + if (growDirs & GROW_SOUTH) rtmp.r_ybot -= growDistance; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + } + + CIFTileOps++; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifGrowFunc -- + * + * Called for each relevant tile during grow or shrink operations. + * For growing, these are solid tiles. For shrinking, these are + * space tiles. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Scales the tile by cifScale, then expands its area by the + * distance in the current CIFOp, then paints this area into + * cifNewPlane using the table passed as parameter. + * ---------------------------------------------------------------------------- + */ + +int +cifGrowFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Table to be used for painting. */ +{ + Rect area; + TileType oldType = TiGetTypeExact(tile); + + TiToRect(tile, &area); + + /* In scaling the tile, watch out for infinities!! If something + * is already infinity, don't change it. */ + + if (area.r_xbot > TiPlaneRect.r_xbot) area.r_xbot *= cifScale; + if (area.r_ybot > TiPlaneRect.r_ybot) area.r_ybot *= cifScale; + if (area.r_xtop < TiPlaneRect.r_xtop) area.r_xtop *= cifScale; + if (area.r_ytop < TiPlaneRect.r_ytop) area.r_ytop *= cifScale; + + /* Grow on diagonal tiles: grow rectangular tiles around the */ + /* straight edges of the right-triangle, then copy the diagonal */ + /* tile (at its original size) in the direction of the diagonal. */ + /* Note: A diagonal tile, by definition, can't have infinities. */ + + if (oldType & TT_DIAGONAL) + { + Rect rtmp; + + /* Grow top and bottom */ + + rtmp.r_ybot = area.r_ybot - growDistance; + rtmp.r_ytop = area.r_ytop + growDistance; + + /* Grow around left or right edge */ + + if (oldType & TT_SIDE) + { + rtmp.r_xbot = area.r_xtop - growDistance; + rtmp.r_xtop = area.r_xtop + growDistance; + } + else + { + rtmp.r_xbot = area.r_xbot - growDistance; + rtmp.r_xtop = area.r_xbot + growDistance; + } + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + + /* Now do the same for the other edge. */ + + rtmp.r_xbot = area.r_xbot - growDistance; + rtmp.r_xtop = area.r_xtop + growDistance; + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) /* top */ + { + rtmp.r_ybot = area.r_ytop - growDistance; + rtmp.r_ytop = area.r_ytop + growDistance; + } + else /* bottom */ + { + rtmp.r_ybot = area.r_ybot - growDistance; + rtmp.r_ytop = area.r_ybot + growDistance; + } + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + + /* Finally, Move and replace the diagonal tile */ + + if (oldType & TT_SIDE) + { + rtmp.r_xtop = area.r_xtop - growDistance; + rtmp.r_xbot = area.r_xbot - growDistance; + } + else + { + rtmp.r_xtop = area.r_xtop + growDistance; + rtmp.r_xbot = area.r_xbot + growDistance; + } + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) /* top */ + { + rtmp.r_ytop = area.r_ytop - growDistance; + rtmp.r_ybot = area.r_ybot - growDistance; + } + else /* bottom */ + { + rtmp.r_ytop = area.r_ytop + growDistance; + rtmp.r_ybot = area.r_ybot + growDistance; + } + DBNMPaintPlane(cifPlane, oldType, &rtmp, table, (PaintUndoInfo *) NULL); + } + else + { + + /* In scaling the tile, watch out for infinities!! If something + * is already infinity, don't change it. */ + + if (area.r_xbot > TiPlaneRect.r_xbot) area.r_xbot -= growDistance; + if (area.r_ybot > TiPlaneRect.r_ybot) area.r_ybot -= growDistance; + if (area.r_xtop < TiPlaneRect.r_xtop) area.r_xtop += growDistance; + if (area.r_ytop < TiPlaneRect.r_ytop) area.r_ytop += growDistance; + + DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL); + } + + CIFTileOps += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifBloatFunc -- + * + * Called once for each tile to be selectively bloated. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Uses the bloat table in the current CIFOp to expand the + * tile depending on which tiles it abuts, then paints the + * expanded area into the new CIF plane. The bloat table + * contains one entry for each tile type. When that tile + * type is seen next to the current tile, the area of the current + * tile is bloated by the table value in that location. The + * only exception to this rule is that internal edges (between + * two tiles of the same type) cause no bloating. + * Note: the original tile is scaled into CIF coordinates. + * ---------------------------------------------------------------------------- + */ + +int +cifBloatFunc(tile, clientData) + Tile *tile; + ClientData clientData; +{ + Rect tileArea, cifArea, bloat; + TileType oldType, type, topLeftType, bottomRightType; + Tile *t; + int tilestart, tilestop, cifstart, cifstop; + BloatData *bloats = (BloatData *)clientData; + int *bloatTable = (int *)bloats->bl_distance; + + oldType = TiGetTypeExact(tile); + TiToRect(tile, &tileArea); + + /* Output the original area of the tile. */ + + cifArea = tileArea; + cifArea.r_xbot *= cifScale; + cifArea.r_xtop *= cifScale; + cifArea.r_ybot *= cifScale; + cifArea.r_ytop *= cifScale; + + /* This is a modified version of the nonmanhattan grow function. */ + /* We grow only in the direction of the diagonal. */ + /* This will not work in all situations! Corner extensions are not */ + /* considered (but should be, for completeness). */ + + if (oldType & TT_DIAGONAL) + { + TileType otherType = (oldType & TT_SIDE) ? + TiGetLeftType(tile) : TiGetRightType(tile); + int dist = bloatTable[otherType]; + + /* The Euclidean grow function is identical to Euclidean bloat-or */ + if (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) + { + growDistance = dist; + cifGrowEuclideanFunc(tile, CIFPaintTable); + } + else + { + + /* Grow top and bottom */ + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) /* top */ + { + bloat.r_ybot = cifArea.r_ytop - dist; + bloat.r_ytop = cifArea.r_ytop; + } + else /* bottom */ + { + bloat.r_ybot = cifArea.r_ybot; + bloat.r_ytop = cifArea.r_ybot + dist; + } + + /* Grow around left or right edge */ + + if (oldType & TT_SIDE) + { + bloat.r_xbot = cifArea.r_xbot - dist; + bloat.r_xtop = cifArea.r_xtop; + } + else + { + bloat.r_xbot = cifArea.r_xbot; + bloat.r_xtop = cifArea.r_xtop + dist; + } + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, (PaintUndoInfo *) NULL); + + /* Now do the same for the left or right edge. */ + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) /* top */ + { + bloat.r_ybot = cifArea.r_ybot - dist; + bloat.r_ytop = cifArea.r_ytop; + } + else /* bottom */ + { + bloat.r_ybot = cifArea.r_ybot; + bloat.r_ytop = cifArea.r_ytop + dist; + } + + if (oldType & TT_SIDE) + { + bloat.r_xbot = cifArea.r_xtop - dist; + bloat.r_xtop = cifArea.r_xtop; + } + else + { + bloat.r_xbot = cifArea.r_xbot; + bloat.r_xtop = cifArea.r_xbot + dist; + } + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, (PaintUndoInfo *) NULL); + + /* Finally, Move and replace the diagonal tile */ + + if (oldType & TT_SIDE) + { + bloat.r_xtop = cifArea.r_xtop - dist; + bloat.r_xbot = cifArea.r_xbot - dist; + } + else + { + bloat.r_xtop = cifArea.r_xtop + dist; + bloat.r_xbot = cifArea.r_xbot + dist; + } + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) /* top */ + { + bloat.r_ytop = cifArea.r_ytop - dist; + bloat.r_ybot = cifArea.r_ybot - dist; + } + else /* bottom */ + { + bloat.r_ytop = cifArea.r_ytop + dist; + bloat.r_ybot = cifArea.r_ybot + dist; + } + DBNMPaintPlane(cifPlane, oldType, &bloat, CIFPaintTable, + (PaintUndoInfo *) NULL); + } + } + else + DBNMPaintPlane(cifPlane, oldType, &cifArea, CIFPaintTable, + (PaintUndoInfo *) NULL); + + /* Go around the tile, scanning the neighbors along each side. + * Start with the left side, and output the bloats along that + * side, if any. + */ + + tilestop = tileArea.r_ytop; + cifstop = cifArea.r_ytop; + type = oldType; + + /* If the tile type doesn't exist on the left side, skip */ + if (oldType & TT_DIAGONAL) + { + type = TiGetLeftType(tile); + if (oldType & TT_SIDE) + { + if (oldType & TT_DIRECTION) + { + topLeftType = type; + goto dotop; + } + else + { + tilestop = tileArea.r_ybot; + cifstop = cifArea.r_ybot; + type = TiGetBottomType(tile); + } + } + } + + bloat.r_ybot = cifArea.r_ybot - bloatTable[TiGetRightType(LB(tile))]; + bloat.r_xtop = cifArea.r_xbot; + for (t = BL(tile); BOTTOM(t) < TOP(tile); t = RT(t)) + { + if (BOTTOM(t) >= tilestop) continue; + topLeftType = TiGetRightType(t); + bloat.r_xbot = bloat.r_xtop - bloatTable[topLeftType]; + if (TOP(t) > tilestop) + bloat.r_ytop = cifstop; + else bloat.r_ytop = cifScale * TOP(t); + if ((bloatTable[topLeftType] != 0) && (topLeftType != type)) + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, + (PaintUndoInfo *) NULL); + bloat.r_ybot = bloat.r_ytop; + } + + /* Now do the top side. Use the type of the top-left tile to + * side-extend the left end of the top bloat in order to match + * things up at the corner. + */ + +dotop: + cifstart = cifArea.r_xtop; + tilestart = tileArea.r_xtop; + + /* If the tile type doesn't exist on the top side, skip */ + if (oldType & TT_DIAGONAL) + { + type = TiGetTopType(tile); + if (((oldType & TT_SIDE) >> 1) != (oldType & TT_DIRECTION)) + { + if (oldType & TT_SIDE) + goto doright; + else + { + cifstart = cifArea.r_xbot; + tilestart = tileArea.r_xbot; + type = TiGetLeftType(tile); + } + } + } + + bloat.r_ybot = cifArea.r_ytop; + bloat.r_xtop = cifstart; + for (t = RT(tile); RIGHT(t) > LEFT(tile); t = BL(t)) + { + TileType otherType; + if (LEFT(t) >= tilestart) continue; + otherType = TiGetBottomType(t); + bloat.r_ytop = bloat.r_ybot + bloatTable[otherType]; + if (LEFT(t) <= tileArea.r_xbot) + bloat.r_xbot = cifArea.r_xbot - bloatTable[topLeftType]; + else bloat.r_xbot = cifScale * LEFT(t); + if ((bloatTable[otherType] != 0) && (otherType != type)) + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, + (PaintUndoInfo *) NULL); + bloat.r_xtop = bloat.r_xbot; + } + + /* Now do the right side. */ + +doright: + tilestop = tileArea.r_ybot; + cifstop = cifArea.r_ybot; + + /* If the tile type doesn't exist on the right side, skip */ + if (oldType & TT_DIAGONAL) + { + type = TiGetRightType(tile); + if (!(oldType & TT_SIDE)) + { + if (oldType & TT_DIRECTION) + { + bottomRightType = type; + goto dobottom; + } + else + { + tilestop = tileArea.r_ytop; + cifstop = cifArea.r_ytop; + type = TiGetTopType(tile); + } + } + } + + bloat.r_ytop = cifArea.r_ytop + bloatTable[TiGetLeftType(RT(tile))]; + bloat.r_xbot = cifArea.r_xtop; + for (t = TR(tile); TOP(t) > BOTTOM(tile); t = LB(t)) + { + if (TOP(t) <= tilestop) continue; + bottomRightType = TiGetLeftType(t); + bloat.r_xtop = bloat.r_xbot + bloatTable[bottomRightType]; + if (BOTTOM(t) < tilestop) + bloat.r_ybot = cifstop; + else bloat.r_ybot = cifScale * BOTTOM(t); + if ((bloatTable[bottomRightType] != 0) && (bottomRightType != type)) + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, + (PaintUndoInfo *) NULL); + bloat.r_ytop = bloat.r_ybot; + } + + /* Now do the bottom side. Use the type of the bottom-right tile + * to side-extend the right end of the bottom bloat in order to match + * things up at the corner. + */ + +dobottom: + cifstart = cifArea.r_xbot; + tilestart = tileArea.r_xbot; + + /* If the tile type doesn't exist on the bottom side, skip */ + if (oldType & TT_DIAGONAL) + { + type = TiGetBottomType(tile); + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) + { + if (!(oldType & TT_DIRECTION)) + goto endbloat; + else + { + cifstart = cifArea.r_xtop; + tilestart = tileArea.r_xtop; + type = TiGetRightType(tile); + } + } + } + + bloat.r_ytop = cifArea.r_ybot; + bloat.r_xbot = cifstart; + for (t = LB(tile); LEFT(t) < RIGHT(tile); t = TR(t)) + { + TileType otherType; + if (RIGHT(t) <= tilestart) continue; + otherType = TiGetTopType(t); + bloat.r_ybot = bloat.r_ytop - bloatTable[otherType]; + if (RIGHT(t) >= tileArea.r_xtop) + bloat.r_xtop = cifArea.r_xtop + bloatTable[bottomRightType]; + else bloat.r_xtop = cifScale * RIGHT(t); + if ((bloatTable[otherType] != 0) && (otherType != type)) + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, + (PaintUndoInfo *) NULL); + bloat.r_xbot = bloat.r_xtop; + } + +endbloat: + CIFTileOps += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifBloatAllFunc -- + * + * Called once for each tile to be selectively bloated + * using the CIFOP_BLOATALL operation. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Uses the bloat table in the current CIFOp to expand the tile, + * depending on which tiles it abuts. All bordering material that + * has bl_distance = 1 is painted into the result plane. + * + * ---------------------------------------------------------------------------- + */ + +#define CIF_PENDING 0 +#define CIF_UNPROCESSED CLIENTDEFAULT +#define CIF_PROCESSED 1 +#define CIF_IGNORE 2 + +#define PUSHTILE(tp, stack) \ + if ((tp)->ti_client == (ClientData) CIF_UNPROCESSED) { \ + (tp)->ti_client = (ClientData) CIF_PENDING; \ + STACKPUSH((ClientData) (tp), stack); \ + } + +int +cifBloatAllFunc(tile, op) + Tile *tile; /* The tile to be processed. */ + CIFOp *op; /* Describes the operation to be performed */ +{ + Rect area; + TileTypeBitMask connect; + Tile *t, *tp; + TileType type; + BloatData *bloats = (BloatData *)op->co_client; + int i; + static Stack *BloatStack = (Stack *)NULL; + + /* Create a mask of all connecting types (these must be in a single + * plane), then call a search function to find all connecting material + * of these types. + */ + + TTMaskZero(&connect); + for (i = 0; i < TT_MAXTYPES; i++) + if (bloats->bl_distance[i] != 0) + TTMaskSetType(&connect, i); + + /* This search function is based on drcCheckArea */ + + if (BloatStack == (Stack *)NULL) + BloatStack = StackNew(64); + + PUSHTILE(tile, BloatStack); + while (!StackEmpty(BloatStack)) + { + t = (Tile *) STACKPOP(BloatStack); + if (t->ti_client != (ClientData)CIF_PENDING) continue; + t->ti_client = (ClientData)CIF_PROCESSED; + + /* Get the tile into CIF coordinates. */ + + TiToRect(t, &area); + area.r_xbot *= cifScale; + area.r_ybot *= cifScale; + area.r_xtop *= cifScale; + area.r_ytop *= cifScale; + + DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area, + CIFPaintTable, (PaintUndoInfo *) NULL); + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (TTMaskHasType(&connect, TiGetBottomType(tp))) + PUSHTILE(tp, BloatStack); + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (TTMaskHasType(&connect, TiGetRightType(tp))) + PUSHTILE(tp, BloatStack); + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (TTMaskHasType(&connect, TiGetTopType(tp))) + PUSHTILE(tp, BloatStack); + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (TTMaskHasType(&connect, TiGetLeftType(tp))) + PUSHTILE(tp, BloatStack); + } + + /* Clear the tiles that were processed */ + + tile->ti_client = (ClientData)CIF_UNPROCESSED; + STACKPUSH(tile, BloatStack); + while (!StackEmpty(BloatStack)) + { + t = (Tile *) STACKPOP(BloatStack); + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (tp->ti_client != (ClientData)CIF_UNPROCESSED) + { + tp->ti_client = (ClientData)CIF_UNPROCESSED; + STACKPUSH(tp, BloatStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (tp->ti_client != (ClientData)CIF_UNPROCESSED) + { + tp->ti_client = (ClientData)CIF_UNPROCESSED; + STACKPUSH(tp, BloatStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (tp->ti_client != (ClientData)CIF_UNPROCESSED) + { + tp->ti_client = (ClientData)CIF_UNPROCESSED; + STACKPUSH(tp, BloatStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (tp->ti_client != (ClientData)CIF_UNPROCESSED) + { + tp->ti_client = (ClientData)CIF_UNPROCESSED; + STACKPUSH(tp, BloatStack); + } + } + return 0; /* Keep the search alive. . . */ +} + +/*--------------------------------------------------------------*/ +/* Support routines and definitions for cifSquaresFillArea */ +/*--------------------------------------------------------------*/ + +/*------------------------------------------------------*/ +/* Data structure used for identifying contact strips */ +/*------------------------------------------------------*/ + +typedef struct _linkedStrip { + Rect area; + bool vertical; /* Tile is vertical */ + bool shrink_ld; /* Shrink left or down before creating cuts */ + bool shrink_ur; /* Shrink right or up before creating cuts */ + struct _linkedStrip *strip_next; +} linkedStrip; + +typedef struct +{ + int size; + int pitch; + linkedStrip *strips; +} StripsData; + +/* + *------------------------------------------------------- + * + * cifSquaresInitFunc -- + * + * Find the first unprocessed tile in the plane. + * + * Results: + * Return 1 to stop the search and process. + * Otherwise, return 0 to keep the search going. + * + *------------------------------------------------------- + */ + +int +cifSquaresInitFunc(tile, clientData) + Tile *tile; + ClientData clientData; +{ + if (tile->ti_client == (ClientData) CIF_UNPROCESSED) + return 1; + else + return 0; +} + +/* + *------------------------------------------------------- + * + * cifSquaresStripFunc -- + * + * Find vertical or horizontal strips of contact + * material that is between 1 and 2 contact cuts wide. + * Generate and return a list of all such strips. + * + * Results: Return 0 to keep the search going. + * + *------------------------------------------------------- + */ + +int +cifSquaresStripFunc(tile, stripsData) + Tile *tile; + StripsData *stripsData; +{ + bool vertical; + int width, height; + linkedStrip *newStrip; + Tile *tp, *tp2; + Rect bbox; + + if (IsSplit(tile)) + return 0; + TiToRect(tile, &bbox); + + /* Check if the tile is wide enough for exactly one cut */ + + width = bbox.r_xtop - bbox.r_xbot; + height = bbox.r_ytop - bbox.r_ybot; + + if (height > width) + { + vertical = TRUE; + height = width; + } + else + vertical = FALSE; + + if ((height < stripsData->size) || (height >= + (stripsData->size + stripsData->pitch))) + return 0; + + /* Ignore strips that are part of a larger */ + /* collection of non-manhattan geometry. */ + + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (IsSplit(tp)) + break; + if (BOTTOM(tp) < TOP(tile)) + return 0; + + /* Note that the max horizontal stripes rule guarantees */ + /* that a tile is always bounded on left and right by */ + /* TT_SPACE. Thus, we only need to search the top and */ + /* bottom boundaries of horizontal tiles. */ + + if (vertical) + { + newStrip = (linkedStrip *)mallocMagic(sizeof(linkedStrip)); + newStrip->area = bbox; + newStrip->vertical = TRUE; + newStrip->shrink_ur = (TTMaskHasType(&CIFSolidBits, + TiGetBottomType(RT(tile)))) ? TRUE : FALSE; + newStrip->shrink_ld = (TTMaskHasType(&CIFSolidBits, + TiGetTopType(LB(tile)))) ? TRUE : FALSE; + newStrip->strip_next = stripsData->strips; + stripsData->strips = newStrip; + } + else + { + int segstart, segend; + int matchstart, matchend; + + tp = RT(tile); + segend = RIGHT(tile); + while (RIGHT(tp) > LEFT(tile)) + { + /* Isolate segments of space along the top of the tile */ + + while ((RIGHT(tp) > LEFT(tile)) && + TTMaskHasType(&CIFSolidBits, TiGetBottomType(tp))) + tp = BL(tp); + segend = MIN(segend, RIGHT(tp)); + while ((RIGHT(tp) > LEFT(tile)) && + TTMaskHasType(&DBSpaceBits, TiGetBottomType(tp))) + tp = BL(tp); + segstart = MAX(LEFT(tile), RIGHT(tp)); + if (segend <= segstart) break; + + /* Find matching segments along the bottom of the tile */ + + for (tp2 = LB(tile); RIGHT(tp2) < segstart; tp2 = TR(tp2)); + + while (LEFT(tp2) < segend) + { + while (RIGHT(tp2) < segstart) tp2 = TR(tp2); + while ((LEFT(tp2) < segend) && + TTMaskHasType(&CIFSolidBits, TiGetTopType(tp2))) + tp2 = TR(tp2); + matchstart = MAX(LEFT(tp2), segstart); + while ((LEFT(tp2) < segend) && + TTMaskHasType(&DBSpaceBits, TiGetTopType(tp2))) + tp2 = TR(tp2); + matchend = MIN(LEFT(tp2), segend); + if (matchend <= matchstart) break; + + /* Process the strip */ + + newStrip = (linkedStrip *)mallocMagic(sizeof(linkedStrip)); + newStrip->area = bbox; + newStrip->area.r_xbot = matchstart; + newStrip->area.r_xtop = matchend; + newStrip->vertical = FALSE; + newStrip->strip_next = stripsData->strips; + newStrip->shrink_ur = (matchend != RIGHT(tile)) ? TRUE : FALSE; + newStrip->shrink_ld = (matchstart != LEFT(tile)) ? TRUE : FALSE; + + stripsData->strips = newStrip; + } + } + } + return 0; +} + + +/* + *------------------------------------------------------- + * + * cifSquaresResetFunc -- + * + * Unmark tiles + * + * Results: Return 0 to keep the search going. + * + *------------------------------------------------------- + */ + +int +cifSquaresResetFunc(tile, clientData) + Tile *tile; + ClientData clientData; /* unused */ +{ + tile->ti_client = (ClientData) CIF_UNPROCESSED; + return 0; +} + +/* + *------------------------------------------------------- + * + * cifUnconnectFunc -- + * + * Find space tiles inside a possible contact area + * + * Results: Return 1 to stop the ongoing search. + * + *------------------------------------------------------- + */ + + +int +cifUnconnectFunc(tile, clientData) + Tile *tile; + ClientData clientData; /* unused */ +{ + TileType t = TiGetTypeExact(tile); + if (t == TT_SPACE) return 1; + else if (t & TT_DIAGONAL) return 1; + else if (tile->ti_client != (ClientData)CIF_PROCESSED) return 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifRectBoundingBox -- + * + * Fill regions of the current CIF plane with rectangles that represent + * the bounding box of each unconnected area. This function "cleans + * up" areas processed by multiple rules and removes notches and + * cut-outs. + * + * Results: + * None. + * + * Side effects: + * + * ---------------------------------------------------------------------------- + */ + +void +cifRectBoundingBox(op, cellDef, plane) + CIFOp *op; + CellDef *cellDef; + Plane *plane; +{ + Tile *tile = NULL, *t, *tp; + Rect bbox, area, *maxr; + int i, j, savecount; + TileType type; + bool simple; + static Stack *BoxStack = (Stack *)NULL; + + if (BoxStack == (Stack *)NULL) + BoxStack = StackNew(64); + + while (DBSrPaintArea((Tile *)tile, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresInitFunc, (ClientData)NULL) != 0) + { + /* Now, search for (nontrivially) connected tiles in all */ + /* directions. Mark the tiles, and record the bounding box. */ + /* (Largely copied from cifSquaresFillArea) */ + + simple = TRUE; + tile = plane->pl_hint; + TiToRect(tile, &bbox); + + PUSHTILE(tile, BoxStack); + while (!StackEmpty(BoxStack)) + { + t = (Tile *) STACKPOP(BoxStack); + if (t->ti_client != (ClientData)CIF_PENDING) continue; + t->ti_client = (ClientData)CIF_PROCESSED; + + /* Adjust bounding box */ + TiToRect(t, &area); + GeoInclude(&area, &bbox); + + if (IsSplit(t)) simple = FALSE; + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetBottomType(tp))) + { + simple = FALSE; + PUSHTILE(tp, BoxStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetRightType(tp))) + { + simple = FALSE; + PUSHTILE(tp, BoxStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetTopType(tp))) + { + simple = FALSE; + PUSHTILE(tp, BoxStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetLeftType(tp))) + { + simple = FALSE; + PUSHTILE(tp, BoxStack); + } + } + + if (op->co_client == (ClientData)1) /* external */ + { + DBPaintPlane(cifPlane, &bbox, CIFPaintTable, (PaintUndoInfo *)NULL); + CIFTileOps++; + } + else /* internal */ + { + if (simple) + { + DBPaintPlane(cifPlane, &bbox, CIFPaintTable, (PaintUndoInfo *)NULL); + CIFTileOps++; + } + else + { + maxr = FindMaxRectangle2(&bbox, tile, plane); + DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *)NULL); + CIFTileOps++; + } + } + + /* Clear the tiles that were processed in this set */ + + tile->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tile, BoxStack); + while (!StackEmpty(BoxStack)) + { + t = (Tile *) STACKPOP(BoxStack); + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, BoxStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, BoxStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, BoxStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, BoxStack); + } + } + } + + /* Clear all the tiles that were processed */ + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresResetFunc, (ClientData)NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSquaresFillArea -- + * + * Fill areas in the current CIF output plane with contact cuts based on + * the SQUARES operation passed in "op". This differs from the original + * tile-based contact cut generation by collecting all connected tiles + * in an area, and placing cuts relative to that area's bounding box. + * A tile search is used to select the parts of any non-rectangular area + * inside the bounding box that allow contact cuts, which lets cuts + * be placed across tile boundaries and inside non-manhattan tiles. + * It also allows contacts to be placed inside complex structures such + * as (possibly intersecting) guardrings. + * + * Results: + * None. + * + * Side effects: + * + * ---------------------------------------------------------------------------- + */ + +void +cifSquaresFillArea(op, cellDef, plane) + CIFOp *op; + CellDef *cellDef; + Plane *plane; +{ + Tile *tile, *t, *tp; + Rect bbox, area, square, cut, llcut; + int nAcross, nUp, left, pitch, size, diff, right; + int i, j, k, savecount; + TileType type; + SquaresData *squares = (SquaresData *)op->co_client; + StripsData stripsData; + linkedStrip *stripList; + bool simple; + static Stack *CutStack = (Stack *)NULL; + + pitch = squares->sq_size + squares->sq_sep; + size = squares->sq_size + 2 * squares->sq_border; + diff = squares->sq_sep - 2 * squares->sq_border; + + if (CutStack == (Stack *)NULL) + CutStack = StackNew(64); + + /* Two-pass algorithm */ + + /* Search the plane for "strips", sections of contact that are only */ + /* wide enough for 1 cut. Process them separately, then erase the */ + /* processed areas. The purpose of this is to avoid applying the */ + /* contact matrix algorithm on non-convex spaces, such as guard */ + /* rings, where centering the matrix on the bounding box of the */ + /* contact area may produce a matrix misaligned with the contact */ + /* strips, preventing any contacts from being drawn! Due to the */ + /* maximum horizontal stripes rule for corner stitched tiles, we */ + /* need only identify vertical contact strips. After processing */ + /* and erasing them, all remaining areas will be convex. This */ + /* algorithm allows contacts to be drawn in any arbitrary geometry. */ + + stripsData.size = size; + stripsData.pitch = pitch; + stripsData.strips = NULL; + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresStripFunc, (ClientData)&stripsData); + + /* Generate cuts in each strip found, then erase the strip */ + + stripList = stripsData.strips; + while (stripList != NULL) + { + Rect stripLess = stripList->area; + + if (diff > 0) + { + if (stripList->vertical) + { + if (stripList->shrink_ur) stripLess.r_ytop -= diff; + if (stripList->shrink_ld) stripLess.r_ybot += diff; + } + else + { + if (stripList->shrink_ur) stripLess.r_xtop -= diff; + if (stripList->shrink_ld) stripLess.r_xbot += diff; + } + } + + /* Create the cuts */ + + if (op->co_opcode == CIFOP_SQUARES) + cifSquareFunc(&stripLess, op, &nUp, &nAcross, &llcut); + else if (op->co_opcode == CIFOP_SQUARES_G) + cifSquareGridFunc(&stripLess, op, &nUp, &nAcross, &llcut); + + cut.r_ybot = llcut.r_ybot; + cut.r_ytop = llcut.r_ytop; + + for (i = 0; i < nUp; i++) + { + cut.r_xbot = llcut.r_xbot; + cut.r_xtop = llcut.r_xtop; + for (j = 0; j < nAcross; j++) + { + DBPaintPlane(cifPlane, &cut, CIFPaintTable, (PaintUndoInfo *)NULL); + cut.r_xbot += pitch; + cut.r_xtop += pitch; + } + cut.r_ybot += pitch; + cut.r_ytop += pitch; + } + if (nUp == 0) + { + if (stripList->shrink_ur == 0 && stripList->shrink_ld == 0) + { + /* The following code is backwardly-compatible with the */ + /* original behavior of allowing cuts that do not have */ + /* sufficient border. Here, we restrict that to contact */ + /* areas exactly matching the cut size. There should be */ + /* a flag to allow contacts to be generated this way. */ + + if ((stripList->area.r_xtop - stripList->area.r_xbot + == squares->sq_size) && (stripList->area.r_ytop + - stripList->area.r_ybot == squares->sq_size)) + { + DBPaintPlane(cifPlane, &stripList->area, CIFPaintTable, + (PaintUndoInfo *)NULL); + CIFTileOps++; + } + else + CIFError(&stripList->area, "no room for contact cuts in area!"); + } + + /* Ad hoc rule catches problems due to contact areas of the proper */ + /* size not fitting cuts because the grid offset prohibits it. */ + else if (((stripList->area.r_ur.p_x - stripList->area.r_ll.p_x) * + (stripList->area.r_ur.p_y - stripList->area.r_ll.p_y)) > + 2 * (pitch * pitch)) + CIFError(&stripList->area, "contact strip with no room for cuts!"); + } + + DBPaintPlane(plane, &stripList->area, CIFEraseTable, + (PaintUndoInfo *) NULL); + freeMagic(stripList); + stripList = stripList->strip_next; + } + + /* 2nd pass: Search the plane for unmarked tiles */ + + while (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresInitFunc, (ClientData)NULL) != 0) + { + /* Now, search for (nontrivially) connected tiles in all */ + /* directions. Mark the tiles, and record the bounding box. */ + /* (Largely copied from cifBloatAllFunc) */ + + simple = TRUE; + tile = plane->pl_hint; + TiToRect(tile, &bbox); + + PUSHTILE(tile, CutStack); + while (!StackEmpty(CutStack)) + { + t = (Tile *) STACKPOP(CutStack); + if (t->ti_client != (ClientData)CIF_PENDING) continue; + t->ti_client = (ClientData)CIF_PROCESSED; + + /* Adjust bounding box */ + TiToRect(t, &area); + GeoInclude(&area, &bbox); + + if (IsSplit(t)) simple = FALSE; + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetBottomType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetRightType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetTopType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetLeftType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + } + + savecount = CIFTileOps; + + for (k = 0; k < 3; k++) /* prepare for up to 3 passes */ + { + /* Determine the contact cut offsets from the bounding box */ + + if (op->co_opcode == CIFOP_SQUARES) + cifSquareFunc(&bbox, op, &nUp, &nAcross, &llcut); + else if (op->co_opcode == CIFOP_SQUARES_G) + cifSquareGridFunc(&bbox, op, &nUp, &nAcross, &llcut); + + cut.r_ybot = llcut.r_ybot; + cut.r_ytop = llcut.r_ytop; + + /* For each contact cut area, check that there is */ + /* no whitespace */ + + for (i = 0; i < nUp; i++) + { + cut.r_xbot = llcut.r_xbot; + cut.r_xtop = llcut.r_xtop; + + square.r_ybot = cut.r_ybot - squares->sq_border; + square.r_ytop = cut.r_ytop + squares->sq_border; + + for (j = 0; j < nAcross; j++) + { + square.r_xbot = cut.r_xbot - squares->sq_border; + square.r_xtop = cut.r_xtop + squares->sq_border; + + /* If there is only one simple rectangle in the */ + /* area, the area is convex, so we don't have to */ + /* check for unconnected regions. */ + + if (simple || DBSrPaintArea((Tile *)tile, plane, &square, + &DBAllTypeBits, cifUnconnectFunc, + (ClientData)NULL) == 0) + { + DBPaintPlane(cifPlane, &cut, CIFPaintTable, + (PaintUndoInfo *)NULL); + CIFTileOps++; + } + cut.r_xbot += pitch; + cut.r_xtop += pitch; + } + cut.r_ybot += pitch; + cut.r_ytop += pitch; + } + if (savecount != CIFTileOps) break; + + /* In non-Manhattan regions with beveled corners, where */ + /* the bounding box has space for 2 contacts, there may not */ + /* be space in the shape itself for more than one. We will */ + /* attempt to shrink X, Y, and/or both to fit (up to 3 */ + /* passes may be necessary). */ + + if (nUp == 2) + { + int bdiff = 1 + (bbox.r_ytop - bbox.r_ybot) - + (2 * (squares->sq_size + squares->sq_border) + + squares->sq_sep); + if (bdiff & 0x1) bdiff++; /* bdiff must be even */ + bdiff >>= 1; /* take half */ + bbox.r_ytop -= bdiff; + bbox.r_ybot += bdiff; + } + else if (nAcross == 2) + { + int bdiff = 1 + (bbox.r_xtop - bbox.r_xbot) - + (2 * (squares->sq_size + squares->sq_border) + + squares->sq_sep); + if (bdiff & 0x1) bdiff++; /* bdiff must be even */ + bdiff >>= 1; /* take half */ + bbox.r_xtop -= bdiff; + bbox.r_xbot += bdiff; + } + else + break; + } + if (savecount == CIFTileOps) + CIFError(&bbox, "no room for contacts in area!"); + + /* Clear the tiles that were processed */ + + tile->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tile, CutStack); + while (!StackEmpty(CutStack)) + { + t = (Tile *) STACKPOP(CutStack); + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + } + } + + /* Clear all the tiles that were processed */ + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresResetFunc, (ClientData)NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSlotsFillArea -- + * + * Fill areas in the current CIF output plane with contact cuts based on + * the SLOTS operation passed in "op". This routine is like + * cifSquaresFillArea but handles X and Y dimensions independently. + * + * Results: + * None. + * + * Side effects: + * + * ---------------------------------------------------------------------------- + */ + +void +cifSlotsFillArea(op, cellDef, plane) + CIFOp *op; + CellDef *cellDef; + Plane *plane; +{ + Tile *tile, *t, *tp; + Rect bbox, area, square, cut, llcut; + int nAcross, nUp, left, spitch, lpitch, ssize, lsize; + int diff, right; + int xpitch, ypitch, xborder, yborder, xdiff, ydiff; + int i, j, k, savecount; + TileType type; + SlotsData *slots = (SlotsData *)op->co_client; + StripsData stripsData; + linkedStrip *stripList; + bool simple, vertical; + static Stack *CutStack = (Stack *)NULL; + + spitch = slots->sl_ssize + slots->sl_ssep; + lpitch = slots->sl_lsize + slots->sl_lsep; + ssize = slots->sl_ssize + 2 * slots->sl_sborder; + lsize = slots->sl_lsize + 2 * slots->sl_lborder; + + /* This may not be good in all cases! Amount to shorten a strip */ + /* depends on the orientation of the cuts on either side of the */ + /* connected strip edge. . . */ + diff = slots->sl_lsep - slots->sl_lborder - slots->sl_sborder; + + if (CutStack == (Stack *)NULL) + CutStack = StackNew(64); + + /* Two-pass algorithm */ + + /* Search the plane for "strips", sections of contact that are only */ + /* wide enough for 1 cut. Process them separately, then erase the */ + /* processed areas. The purpose of this is to avoid applying the */ + /* contact matrix algorithm on non-convex spaces, such as guard */ + /* rings, where centering the matrix on the bounding box of the */ + /* contact area may produce a matrix misaligned with the contact */ + /* strips, preventing any contacts from being drawn! Due to the */ + /* maximum horizontal stripes rule for corner stitched tiles, we */ + /* need only identify vertical contact strips. After processing */ + /* and erasing them, all remaining areas will be convex. This */ + /* algorithm allows contacts to be drawn in any arbitrary geometry. */ + + stripsData.size = ssize; + stripsData.pitch = spitch; + stripsData.strips = NULL; + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresStripFunc, (ClientData)&stripsData); + + /* Generate cuts in each strip found, then erase the strip */ + + stripList = stripsData.strips; + while (stripList != NULL) + { + Rect stripLess = stripList->area; + + if (diff > 0) + { + if (stripList->vertical) + { + if (stripList->shrink_ur) stripLess.r_ytop -= diff; + if (stripList->shrink_ld) stripLess.r_ybot += diff; + } + else + { + if (stripList->shrink_ur) stripLess.r_xtop -= diff; + if (stripList->shrink_ld) stripLess.r_xbot += diff; + } + } + + /* Create the cuts */ + + cifSlotFunc(&stripLess, op, &nUp, &nAcross, &llcut, stripList->vertical); + + cut = llcut; + + if (stripList->vertical) + { + for (i = 0; i < nUp; i++) + { + DBPaintPlane(cifPlane, &cut, CIFPaintTable, (PaintUndoInfo *)NULL); + cut.r_ybot += lpitch; + cut.r_ytop += lpitch; + } + } + else + { + for (i = 0; i < nAcross; i++) + { + DBPaintPlane(cifPlane, &cut, CIFPaintTable, (PaintUndoInfo *)NULL); + cut.r_xbot += lpitch; + cut.r_xtop += lpitch; + } + } + + if (nUp == 0 || nAcross == 0) + { + if (stripList->shrink_ur == 0 && stripList->shrink_ld == 0) + { + /* The following code is backwardly-compatible with the */ + /* original behavior of allowing cuts that do not have */ + /* sufficient border. Here, we restrict that to contact */ + /* areas exactly matching the cut size. There should be */ + /* a flag to allow contacts to be generated this way. */ + + if (((stripList->area.r_xtop - stripList->area.r_xbot + == slots->sl_ssize) && (stripList->area.r_ytop + - stripList->area.r_ybot == slots->sl_lsize)) || + ((stripList->area.r_xtop - stripList->area.r_xbot + == slots->sl_lsize) && (stripList->area.r_ytop + - stripList->area.r_ybot == slots->sl_ssize))) + { + DBPaintPlane(cifPlane, &stripList->area, CIFPaintTable, + (PaintUndoInfo *)NULL); + CIFTileOps++; + } + else + CIFError(&stripList->area, "no room for contact cuts in area!"); + } + + /* Ad hoc rule catches problems due to contact areas of the proper */ + /* size not fitting cuts because the grid offset prohibits it. */ + else if (((stripList->area.r_ur.p_x - stripList->area.r_ll.p_x) * + (stripList->area.r_ur.p_y - stripList->area.r_ll.p_y)) > + 2 * (lpitch * spitch)) + CIFError(&stripList->area, "contact strip with no room for cuts!"); + } + + DBPaintPlane(plane, &stripList->area, CIFEraseTable, + (PaintUndoInfo *) NULL); + freeMagic(stripList); + stripList = stripList->strip_next; + } + + /* 2nd pass: Search the plane for unmarked tiles */ + + while (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresInitFunc, (ClientData)NULL) != 0) + { + /* Now, search for (nontrivially) connected tiles in all */ + /* directions. Mark the tiles, and record the bounding box. */ + /* (Largely copied from cifBloatAllFunc) */ + + simple = TRUE; + tile = plane->pl_hint; + TiToRect(tile, &bbox); + + PUSHTILE(tile, CutStack); + while (!StackEmpty(CutStack)) + { + t = (Tile *) STACKPOP(CutStack); + if (t->ti_client != (ClientData)CIF_PENDING) continue; + t->ti_client = (ClientData)CIF_PROCESSED; + + /* Adjust bounding box */ + TiToRect(t, &area); + GeoInclude(&area, &bbox); + + if (IsSplit(t)) simple = FALSE; + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetBottomType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetRightType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetTopType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetLeftType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + } + + /* May want to attempt a second pass with the orthogonal alignment? */ + if ((bbox.r_xtop - bbox.r_xbot) > (bbox.r_ytop - bbox.r_ybot)) + vertical = FALSE; + else + vertical = TRUE; + + if (vertical) + { + xpitch = spitch; + ypitch = lpitch; + xborder = slots->sl_sborder; + yborder = slots->sl_lborder; + xdiff = 2 * (slots->sl_ssize + slots->sl_sborder) + slots->sl_ssep; + ydiff = 2 * (slots->sl_lsize + slots->sl_lborder) + slots->sl_lsep; + } + else + { + xpitch = lpitch; + ypitch = spitch; + xborder = slots->sl_lborder; + yborder = slots->sl_sborder; + xdiff = 2 * (slots->sl_lsize + slots->sl_lborder) + slots->sl_lsep; + ydiff = 2 * (slots->sl_ssize + slots->sl_sborder) + slots->sl_ssep; + } + + savecount = CIFTileOps; + + for (k = 0; k < 3; k++) /* prepare for up to 3 passes */ + { + /* Determine the contact cut offsets from the bounding box */ + + cifSlotFunc(&bbox, op, &nUp, &nAcross, &llcut, vertical); + + cut.r_ybot = llcut.r_ybot; + cut.r_ytop = llcut.r_ytop; + + /* For each contact cut area, check that there is */ + /* no whitespace */ + + for (i = 0; i < nUp; i++) + { + cut.r_xbot = llcut.r_xbot; + cut.r_xtop = llcut.r_xtop; + + square.r_ybot = cut.r_ybot - yborder; + square.r_ytop = cut.r_ytop + yborder; + + for (j = 0; j < nAcross; j++) + { + square.r_xbot = cut.r_xbot - xborder; + square.r_xtop = cut.r_xtop + xborder; + + /* If there is only one simple rectangle in the */ + /* area, the area is convex, so we don't have to */ + /* check for unconnected regions. */ + + if (simple || DBSrPaintArea((Tile *)tile, plane, &square, + &DBAllTypeBits, cifUnconnectFunc, + (ClientData)NULL) == 0) + { + DBPaintPlane(cifPlane, &cut, CIFPaintTable, + (PaintUndoInfo *)NULL); + CIFTileOps++; + } + cut.r_xbot += xpitch; + cut.r_xtop += xpitch; + } + cut.r_ybot += ypitch; + cut.r_ytop += ypitch; + } + if (savecount != CIFTileOps) break; + + /* In non-Manhattan regions with beveled corners, where */ + /* the bounding box has space for 2 contacts, there may not */ + /* be space in the shape itself for more than one. We will */ + /* attempt to shrink X, Y, and/or both to fit (up to 3 */ + /* passes may be necessary). */ + + if (nUp == 2) + { + int bdiff = 1 + (bbox.r_ytop - bbox.r_ybot) - ydiff; + if (bdiff & 0x1) bdiff++; /* bdiff must be even */ + bdiff >>= 1; /* take half */ + bbox.r_ytop -= bdiff; + bbox.r_ybot += bdiff; + } + else if (nAcross == 2) + { + int bdiff = 1 + (bbox.r_xtop - bbox.r_xbot) - xdiff; + if (bdiff & 0x1) bdiff++; /* bdiff must be even */ + bdiff >>= 1; /* take half */ + bbox.r_xtop -= bdiff; + bbox.r_xbot += bdiff; + } + else + break; + } + if (savecount == CIFTileOps) + CIFError(&bbox, "no room for contacts in area!"); + + /* Clear the tiles that were processed */ + + tile->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tile, CutStack); + while (!StackEmpty(CutStack)) + { + t = (Tile *) STACKPOP(CutStack); + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + } + } + + /* Clear all the tiles that were processed */ + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresResetFunc, (ClientData)NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifBloatMaxFunc -- + * + * Called once for each tile to be selectively bloated or + * shrunk using the CIFOP_BLOATMAX or CIFOP_BLOATMIN operation. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Uses the bloat table in the current CIFOp to expand or shrink + * the tile, depending on which tiles it abuts. The rectangular + * area of the tile is modified by moving each side in or out + * by the maximum bloat distance for any of its neighbors on + * that side. The result is a new rectangle, which is OR'ed + * into the result plane. Note: any edge between two tiles of + * same type is given a zero bloat factor. + * + * ---------------------------------------------------------------------------- + */ + +int +cifBloatMaxFunc(tile, op) + Tile *tile; /* The tile to be processed. */ + CIFOp *op; /* Describes the operation to be performed + * (all we care about is the opcode and + * bloat table). + */ +{ + Rect area; + int bloat, tmp; + Tile *t; + TileType type, otherType; + BloatData *bloats = (BloatData *)op->co_client; + + /* Get the tile into CIF coordinates. */ + + type = TiGetType(tile); + TiToRect(tile, &area); + area.r_xbot *= cifScale; + area.r_ybot *= cifScale; + area.r_xtop *= cifScale; + area.r_ytop *= cifScale; + + /* See how much to adjust the left side of the tile. */ + + if (op->co_opcode == CIFOP_BLOATMAX) bloat = -10000000; + else bloat = 10000000; + for (t = BL(tile); BOTTOM(t) < TOP(tile); t = RT(t)) + { + otherType = TiGetType(t); + if (otherType == type) continue; + tmp = bloats->bl_distance[otherType]; + if (op->co_opcode == CIFOP_BLOATMAX) + { + if (tmp > bloat) bloat = tmp; + } + else if (tmp < bloat) bloat = tmp; + } + if ((bloat < 10000000) && (bloat > -10000000)) + area.r_xbot -= bloat; + + /* Now figure out how much to adjust the top side of the tile. */ + + if (op->co_opcode == CIFOP_BLOATMAX) bloat = -10000000; + else bloat = 10000000; + for (t = RT(tile); RIGHT(t) > LEFT(tile); t = BL(t)) + { + otherType = TiGetType(t); + if (otherType == type) continue; + tmp = bloats->bl_distance[otherType]; + if (op->co_opcode == CIFOP_BLOATMAX) + { + if (tmp > bloat) bloat = tmp; + } + else if (tmp < bloat) bloat = tmp; + } + if ((bloat < 10000000) && (bloat > -10000000)) + area.r_ytop += bloat; + + /* Now the right side. */ + + if (op->co_opcode == CIFOP_BLOATMAX) bloat = -10000000; + else bloat = 10000000; + for (t = TR(tile); TOP(t) > BOTTOM(tile); t = LB(t)) + { + otherType = TiGetType(t); + if (otherType == type) continue; + tmp = bloats->bl_distance[otherType]; + if (op->co_opcode == CIFOP_BLOATMAX) + { + if (tmp > bloat) bloat = tmp; + } + else if (tmp < bloat) bloat = tmp; + } + if ((bloat < 10000000) && (bloat > -10000000)) + area.r_xtop += bloat; + + /* Lastly, do the bottom side. */ + + if (op->co_opcode == CIFOP_BLOATMAX) bloat = -10000000; + else bloat = 10000000; + for (t = LB(tile); LEFT(t) < RIGHT(tile); t = TR(t)) + { + otherType = TiGetType(t); + if (otherType == type) continue; + tmp = bloats->bl_distance[otherType]; + if (op->co_opcode == CIFOP_BLOATMAX) + { + if (tmp > bloat) bloat = tmp; + } + else if (tmp < bloat) bloat = tmp; + } + if ((bloat < 10000000) && (bloat > -10000000)) + area.r_ybot -= bloat; + + /* Make sure the tile didn't shrink into negativity. If it's + * ok, paint it into the new plane being built. + */ + + if ((area.r_xbot > area.r_xtop) || (area.r_ybot > area.r_ytop)) + { + TiToRect(tile, &area); + area.r_xbot *= cifScale; + area.r_xtop *= cifScale; + area.r_ybot *= cifScale; + area.r_ytop *= cifScale; + CIFError(&area, "tile inverted by shrink"); + } + else + DBNMPaintPlane(cifPlane, TiGetTypeExact(tile), &area, + CIFPaintTable, (PaintUndoInfo *) NULL); + + CIFTileOps += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * inside_triangle -- + * + * Test if the specified rectangle is completely inside the tile. + * Tile is presumed to be a split tile. + * + * Results: + * TRUE if inside, FALSE if outside or overlapping. + * + * Side Effects: + * None. + * + * Notes: + * This is an optimized version of the code in DBtiles.c. It + * assumes that the square is never infinite. + * + * ---------------------------------------------------------------------------- + */ + +bool +inside_triangle(rect, tile) + Rect *rect; + Tile *tile; +{ + int theight, twidth; + dlong f1, f2, f3, f4; + + theight = TOP(tile) - BOTTOM(tile); + twidth = RIGHT(tile) - LEFT(tile); + + f1 = (dlong)(TOP(tile) - rect->r_ybot) * twidth; + f2 = (dlong)(rect->r_ytop - BOTTOM(tile)) * twidth; + + if (SplitLeftType(tile) != TT_SPACE) + { + /* Inside-of-triangle check */ + f4 = (dlong)(rect->r_xbot - LEFT(tile)) * theight; + if (SplitDirection(tile) ? (f1 > f4) : (f2 > f4)) + return TRUE; + } + else + { + /* Inside-of-triangle check */ + f3 = (dlong)(RIGHT(tile) - rect->r_xtop) * theight; + if (SplitDirection(tile) ? (f2 > f3) : (f1 > f3)) + return TRUE; + } + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifContactFunc -- + * + * Called for each relevant tile when chopping up contacts into + * square cuts using the procedure of using a pre-defined cell + * definition of a single contact and arraying the cell. + * Technically, this is not a CIF function because CIF does not + * have an array method for cells, so there is no advantage to + * drawing lots of subcells in place of drawing lots of boxes. + * In GDS, however, the array method is much more compact than + * drawing individual cuts when the array size is larger than 1. + * + * Results: + * Normally returns 0 to keep the search going. Return 1 if + * the contact type cannot be found, which halts the search. + * + * Side effects: + * Stuff is painted into cifPlane. + * + * ---------------------------------------------------------------------------- + */ + +int +cifContactFunc(tile, csi) + Tile *tile; /* Tile to be diced up. */ + CIFSquaresInfo *csi; /* Describes how to generate squares. */ +{ + Rect area; + int i, nAcross, j, nUp, left, bottom, pitch, halfsize; + bool result; + SquaresData *squares = csi->csi_squares; + + /* For now, don't allow squares on non-manhattan tiles */ + if (IsSplit(tile)) + return 0; + + TiToRect(tile, &area); + pitch = squares->sq_size + squares->sq_sep; + + nAcross = (area.r_xtop - area.r_xbot + squares->sq_sep + - (2 * squares->sq_border)) / pitch; + if (nAcross == 0) + { + left = (area.r_xbot + area.r_xtop - squares->sq_size) / 2; + if (left >= area.r_xbot) nAcross = 1; + } + else + left = (area.r_xbot + area.r_xtop + squares->sq_sep + - (nAcross * pitch)) / 2; + + nUp = (area.r_ytop - area.r_ybot + squares->sq_sep + - (2 * squares->sq_border)) / pitch; + if (nUp == 0) + { + bottom = (area.r_ybot + area.r_ytop - squares->sq_size) / 2; + if (bottom >= area.r_ybot) nUp = 1; + } + else + bottom = (area.r_ybot + area.r_ytop + squares->sq_sep + - (nUp * pitch)) / 2; + + /* Lower-left coordinate should be centered on the contact cut, as + * contact definitions are centered on the origin. + */ + halfsize = (squares->sq_size / 2); + left += halfsize; + bottom += halfsize; + + result = CalmaGenerateArray((FILE *)csi->csi_client, csi->csi_type, + left, bottom, pitch, nAcross, nUp); + + return (result == TRUE) ? 0 : 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSlotFunc -- + * + * Called for each relevant tile area when chopping areas up into + * slots (rectangles). Determines how to divide up the area into + * slots, and generates the number of rows, columns, and the lower- + * left-most cut rectangle. + * + * Results: + * Always return 0 + * + * Side effects: + * Pointers "rows", "columns", and "cut" are filled with + * appropriate values. + * + * ---------------------------------------------------------------------------- + */ + +int +cifSlotFunc(area, op, numY, numX, cut, vertical) + Rect *area; /* Area to be diced up */ + CIFOp *op; /* Describes how to generate squares. */ + int *numY, *numX; /* Return values: # rows and # columns */ + Rect *cut; /* initial (lower left) cut area */ + bool vertical; /* if TRUE, slot is aligned vertically */ +{ + int i, j, xpitch, ypitch, delta; + int *axtop, *axbot, *aytop, *aybot; + int *sxtop, *sxbot, *sytop, *sybot; + int *rows, *columns; + SlotsData *slots = (SlotsData *)op->co_client; + + /* Orient to the short/long orientation of the tile */ + + /* Assume a vertical tile; if not, reorient area and remember */ + if (vertical) + { + axbot = &area->r_xbot; + aybot = &area->r_ybot; + axtop = &area->r_xtop; + aytop = &area->r_ytop; + sxbot = &cut->r_xbot; + sybot = &cut->r_ybot; + sxtop = &cut->r_xtop; + sytop = &cut->r_ytop; + rows = numY; + columns = numX; + } + else + { + axbot = &area->r_ybot; + aybot = &area->r_xbot; + axtop = &area->r_ytop; + aytop = &area->r_xtop; + sxbot = &cut->r_ybot; + sybot = &cut->r_xbot; + sxtop = &cut->r_ytop; + sytop = &cut->r_xtop; + rows = numX; + columns = numY; + } + + xpitch = slots->sl_ssize + slots->sl_ssep; + +calcX: + *columns = (*axtop - *axbot + slots->sl_ssep - (2 * slots->sl_sborder)) / xpitch; + if (*columns == 0) + { + *rows = 0; + return 0; + // *sxbot = (*axbot + *axtop - slots->sl_ssize) / 2; + // if (*sxbot >= *axbot) *columns = 1; + } + else + *sxbot = (*axbot + *axtop + slots->sl_ssep - (*columns * xpitch)) / 2; + *sxtop = *sxbot + slots->sl_ssize; + + /* Check that we are not violating any gridlimit */ + + if (CIFCurStyle && (CIFCurStyle->cs_gridLimit > 1)) + { + delta = abs(*sxbot) % CIFCurStyle->cs_gridLimit; + if (delta > 0) + { + *axtop -= 2 * delta; + goto calcX; + } + } + + if (slots->sl_lsize > 0) + { + ypitch = slots->sl_lsize + slots->sl_lsep; +calcY: + *rows = (*aytop - *aybot + slots->sl_lsep - (2 * slots->sl_lborder)) / ypitch; + if (*rows == 0) + { + return 0; + // *sybot = (*aybot + *aytop - slots->sl_lsize) / 2; + // if (*sybot >= *aybot) *rows = 1; + } + else + *sybot = (*aybot + *aytop + slots->sl_lsep - (*rows * ypitch)) / 2; + *sytop = *sybot + slots->sl_lsize; + + /* Check that we are not violating any gridlimit */ + + if (CIFCurStyle && (CIFCurStyle->cs_gridLimit > 1)) + { + delta = abs(*sybot) % CIFCurStyle->cs_gridLimit; + if (delta > 0) + { + *aytop -= 2 * delta; + goto calcY; + } + } + } + else + { + *rows = 1; + *sybot = *aybot + slots->sl_lborder; + *sytop = *aytop - slots->sl_lborder; + /* There's no space to fit a slot */ + if (*sytop - *sybot <= 0) + return 0; + } + + /* To be done---slot offsets */ + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSquareFunc -- + * + * Called for each relevant rectangle when chopping areas up into + * squares. Determines the number of rows and columns in the area + * and returns these and the area of the lower-left cut. + * + * Results: + * Always return 0 + * + * Side effects: + * Results filled in the pointer positions passed to the function + * + * ---------------------------------------------------------------------------- + */ + +int +cifSquareFunc(area, op, rows, columns, cut) + Rect *area; /* Area to be diced up */ + CIFOp *op; /* Describes how to generate squares. */ + int *rows, *columns; /* Return values: # rows and # columns, */ + Rect *cut; /* initial (lower left) cut area. */ +{ + int pitch, delta; + bool glimit; + SquaresData *squares = (SquaresData *)op->co_client; + + glimit = (CIFCurStyle && (CIFCurStyle->cs_gridLimit > 1)) ? TRUE : FALSE; + pitch = squares->sq_size + squares->sq_sep; + + /* Compute the real border to leave around the sides. If only + * one square will fit in a particular direction, center it + * regardless of the requested border size. If more than one + * square will fit, then fit it in extras only if at least the + * requested border size can be left. Also center things in the + * rectangle, so that the box's exact size doesn't matter. This + * trickiness is done so that coincident contacts from overlapping + * cells always have their squares line up, regardless of the + * orientation of the cells. + * + * Update 1/13/09: Removed the "feature" that allows contact + * cuts that violate the border requirement. The "slots" rule + * can be used if necessary to generate cuts with different + * border allowances. + */ + +sqX: + *columns = (area->r_xtop - area->r_xbot + squares->sq_sep + - (2 * squares->sq_border)) / pitch; + if (*columns == 0) + { + *rows = 0; + return 0; + + // cut->r_xbot = (area->r_xbot + area->r_xtop - squares->sq_size) / 2; + // if (cut->r_xbot >= area->r_xbot) *columns = 1; + } + else + { + cut->r_xbot = (area->r_xbot + area->r_xtop + squares->sq_sep + - (*columns * pitch)) / 2; + } + + /* Check for any gridlimit violation */ + + if (glimit) + { + delta = abs(cut->r_xbot) % CIFCurStyle->cs_gridLimit; + if (delta > 0) + { + area->r_xtop -= 2 * delta; + goto sqX; + } + } + +sqY: + *rows = (area->r_ytop - area->r_ybot + squares->sq_sep + - (2 * squares->sq_border)) / pitch; + if (*rows == 0) + { + return 0; + + // cut->r_ybot = (area->r_ybot + area->r_ytop - squares->sq_size) / 2; + // if (cut->r_ybot >= area->r_ybot) *rows = 1; + } + else + { + cut->r_ybot = (area->r_ybot + area->r_ytop + squares->sq_sep + - (*rows * pitch)) / 2; + } + + /* Check for any gridlimit violation */ + + if (glimit) + { + delta = abs(cut->r_ybot) % CIFCurStyle->cs_gridLimit; + if (delta > 0) + { + area->r_ytop -= 2 * delta; + goto sqY; + } + } + + cut->r_xtop = cut->r_xbot + squares->sq_size; + cut->r_ytop = cut->r_ybot + squares->sq_size; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSquareGridFunc -- + * + * Called for each relevant rectangle when chopping areas up into + * squares. Determines the number of rows and columns in the area + * and returns these and the area of the lower-left cut. + * + * Results: + * Always return 0 + * + * Side effects: + * Results filled in the pointer positions passed to the function + * + * ---------------------------------------------------------------------------- + */ + +int +cifSquareGridFunc(area, op, rows, columns, cut) + Rect *area; /* Area to be diced up */ + CIFOp *op; /* Describes how to generate squares. */ + int *rows, *columns; /* Return values: # rows and # columns, */ + Rect *cut; /* initial (lower left) cut area. */ +{ + Rect locarea; + int left, bottom, right, top, pitch; + int gridx, gridy, margin; + SquaresData *squares = (SquaresData *)op->co_client; + + /* + * It may be necessary to generate contacts on a specific grid; e.g., + * to avoid placing contacts at half-lambda. If this is the case, + * then the DRC section of the techfile should specify "no overlap" + * for these types. + * + * This routine has been simplified. It flags a warning when there + * is not enough space for a contact cut, rather than attempting to + * draw a cut without enough border area. The routine has also been + * extended to allow different x and y grids to be specified. This + * allows certain tricks, such as generating offset contact grids on + * a pad, as required by some processes. + */ + + pitch = squares->sq_size + squares->sq_sep; + gridx = squares->sq_gridx; + gridy = squares->sq_gridy; + + locarea.r_xtop = area->r_xtop - squares->sq_border; + locarea.r_ytop = area->r_ytop - squares->sq_border; + locarea.r_xbot = area->r_xbot + squares->sq_border; + locarea.r_ybot = area->r_ybot + squares->sq_border; + + left = locarea.r_xbot / gridx; + left *= gridx; + if (left < locarea.r_xbot) left += gridx; + + bottom = locarea.r_ybot / gridy; + bottom *= gridy; + if (bottom < locarea.r_ybot) bottom += gridy; + + *columns = (locarea.r_xtop - left + squares->sq_sep) / pitch; + if (*columns == 0) + { + *rows = 0; + return 0; + } + + *rows = (locarea.r_ytop - bottom + squares->sq_sep) / pitch; + if (*rows == 0) return 0; + + /* Center the contacts while remaining on-grid */ + right = left + *columns * squares->sq_size + (*columns - 1) * squares->sq_sep; + top = bottom + *rows * squares->sq_size + (*rows - 1) * squares->sq_sep; + margin = ((locarea.r_xtop - right) - (left - locarea.r_xbot)) / (gridx * 2); + locarea.r_xbot = left + margin * gridx; + margin = ((locarea.r_ytop - top) - (bottom - locarea.r_ybot)) / (gridy * 2); + locarea.r_ybot = bottom + margin * gridy; + + cut->r_ybot = locarea.r_ybot; + cut->r_ytop = cut->r_ybot + squares->sq_size; + cut->r_xbot = locarea.r_xbot; + cut->r_xtop = cut->r_xbot + squares->sq_size; + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * cifSrTiles -- + * + * This is a utility procedure that just calls DBSrPaintArea + * one or more times for the planes being used in processing + * one CIFOp. + * + * Results: + * None. + * + * Side effects: + * This procedure itself has no side effects. For each of the + * paint or temporary planes indicated in cifOp, we call + * DBSrPaintArea to find the desired tiles in the desired + * area for the operation. DBSrPaintArea is given func as a + * search function, and cdArg as ClientData. + * + * ---------------------------------------------------------------------------- + */ + +void +cifSrTiles(cifOp, area, cellDef, temps, func, cdArg) + CIFOp *cifOp; /* Geometric operation being processed. */ + Rect *area; /* Area of Magic paint to consider. */ + CellDef *cellDef; /* CellDef to search for paint. */ + Plane *temps[]; /* Planes to use for temporaries. */ + int (*func)(); /* Search function to pass to DBSrPaintArea. */ + ClientData cdArg; /* Client data for func. */ +{ + TileTypeBitMask maskBits; + TileType t; + int i; + BloatData *bloats; + + /* When reading data from a cell, it must first be scaled to + * CIF units. Check for CIFCurStyle, as we don't want to + * crash while reading CIF/GDS just becuase the techfile + * "cifoutput" section was blank. + */ + + cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; + + /* Bloat operations have to be in a single plane */ + + switch (cifOp->co_opcode) { + case CIFOP_BLOAT: + case CIFOP_BLOATMIN: + case CIFOP_BLOATMAX: + bloats = (BloatData *)cifOp->co_client; + i = bloats->bl_plane; + maskBits = DBPlaneTypes[i]; + TTMaskAndMask(&maskBits, &cifOp->co_paintMask); + if (!TTMaskEqual(&maskBits, &DBZeroTypeBits)) + DBSrPaintArea((Tile *) NULL, cellDef->cd_planes[i], + area, &cifOp->co_paintMask, func, cdArg); + break; + + default: + for (i = PL_DRC_CHECK; i < DBNumPlanes; i++) + { + maskBits = DBPlaneTypes[i]; + TTMaskAndMask(&maskBits, &cifOp->co_paintMask); + if (!TTMaskEqual(&maskBits, &DBZeroTypeBits)) + (void) DBSrPaintArea((Tile *) NULL, cellDef->cd_planes[i], + area, &cifOp->co_paintMask, func, cdArg); + } + break; + } + + /* When processing CIF data, use everything in the plane. */ + + cifScale = 1; + for (t = 0; t < TT_MAXTYPES; t++, temps++) + if (TTMaskHasType(&cifOp->co_cifMask, t)) + (void) DBSrPaintArea((Tile *) NULL, *temps, &TiPlaneRect, + &CIFSolidBits, func, (ClientData) cdArg); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFGenLayer -- + * + * This routine will generate one CIF layer. + * It provides the core of the CIF generator. + * + * Results: + * Returns a malloc'ed plane with tiles of type CIF_SOLIDTYPE + * marking the area of this CIF layer as built up by op. + * + * Side effects: + * None, except to create a new plane holding the CIF for the layer. + * The CIF that's generated may fall outside of area... it's what + * results from considering everything in area. In most cases the + * caller will clip the results down to the desired area. + * + * ---------------------------------------------------------------------------- + */ + +Plane * +CIFGenLayer(op, area, cellDef, temps, clientdata) + CIFOp *op; /* List of CIFOps telling how to make layer. */ + Rect *area; /* Area to consider when generating CIF. Only + * material in this area will be considered, so + * the caller should usually expand his desired + * area by one CIF radius. + */ + CellDef *cellDef; /* CellDef to search when paint layers are + * needed for operation. + */ + Plane *temps[]; /* Temporary layers to be used when needed + * for operation. + */ + ClientData clientdata; /* + * Data that may be passed to the CIF operation + * function. + */ +{ + Plane *temp; + static Plane *nextPlane, *curPlane; + Rect bbox; + CIFOp *tempOp; + CIFSquaresInfo csi; + SearchContext scx; + TileType ttype; + char *netname; + int (*cifGrowFuncPtr)() = (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) ? + cifGrowEuclideanFunc : cifGrowFunc; + + /* Set up temporary planes used during computation. One of these + * will be returned as the result (whichever is curPlane at the + * end of the computation). The other is saved for later use. + */ + + if (nextPlane == NULL) + nextPlane = DBNewPlane((ClientData) TT_SPACE); + curPlane = DBNewPlane((ClientData) TT_SPACE); + + /* Go through the geometric operations and process them one + * at a time. + */ + + for ( ; op != NULL; op = op->co_next) + { + switch (op->co_opcode) + { + /* For AND, first collect all the stuff to be anded with + * plane in a temporary plane. Then find all the places + * where there isn't any stuff, and erase from the + * current plane. + */ + + case CIFOP_AND: + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifSrTiles(op, area, cellDef, temps, cifPaintFunc, + (ClientData) CIFPaintTable); + cifPlane = curPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, nextPlane, &TiPlaneRect, + &DBSpaceBits, cifPaintFunc, + (ClientData) CIFEraseTable); + break; + + /* For OR, just use cifPaintFunc to OR the areas of all + * relevant tiles into plane. HOWEVER, if the co_client + * record is non-NULL and CalmaContactArrays is TRUE, + * then for each contact type, we do the paint function + * separately, then call the contact array generation + * procedure. + */ + + case CIFOP_OR: + cifPlane = curPlane; + cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; + + if ((op->co_client != (ClientData)NULL) + && (CalmaContactArrays == TRUE)) + { + TileTypeBitMask paintMask, errMask, *rMask; + TileType i, j; + + TTMaskZero(&errMask); + TTMaskZero(&paintMask); + TTMaskSetMask(&paintMask, &op->co_paintMask); + for (i = TT_TECHDEPBASE; i < DBNumUserLayers; i++) + { + if (TTMaskHasType(&paintMask, i)) + { + TTMaskSetOnlyType(&op->co_paintMask, i); + for (j = DBNumUserLayers; j < DBNumTypes; j++) + { + rMask = DBResidueMask(j); + if (TTMaskHasType(rMask, i)) + TTMaskSetType(&op->co_paintMask, j); + } + + cifSrTiles(op, area, cellDef, temps, cifPaintFunc, + (ClientData) CIFPaintTable); + + csi.csi_squares = (SquaresData *)op->co_client; + csi.csi_type = i; + csi.csi_client = clientdata; + + if (DBSrPaintArea((Tile *) NULL, curPlane, + &TiPlaneRect, &CIFSolidBits, + cifContactFunc, (ClientData) &csi)) + { + /* Failure of DBSrPaintArea() (returns 1) + * indicates that a contact cell type + * could not be found for magic layer i. + * Record the error for subsequent handling. + */ + TTMaskSetType(&errMask, i); + } + DBClearPaintPlane(curPlane); + } + } + if (!TTMaskIsZero(&errMask)) + { + /* + * Handle layers for which a contact cell could + * not be found in the default manner. + */ + TTMaskZero(&op->co_paintMask); + TTMaskSetMask(&op->co_paintMask, &errMask); + cifSrTiles(op, area, cellDef, temps, cifPaintFunc, + (ClientData) CIFPaintTable); + } + + /* Recover the original magic layer mask for the cifop */ + + TTMaskZero(&op->co_paintMask); + TTMaskSetMask(&op->co_paintMask, &paintMask); + } + else + { + cifSrTiles(op, area, cellDef, temps, cifPaintFunc, + (ClientData) CIFPaintTable); + } + break; + + /* For ANDNOT, do exactly the same thing as OR, except erase + * instead of paint. + */ + + case CIFOP_ANDNOT: + cifPlane = curPlane; + cifSrTiles(op, area, cellDef, temps, cifPaintFunc, + (ClientData) CIFEraseTable); + break; + + /* For GROW, just find all solid tiles in the current plane, + * and paint a larger version into a new plane. The switch + * the current and new planes. + */ + + case CIFOP_GROW: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, *cifGrowFuncPtr, (ClientData) CIFPaintTable); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + /* GROW_G grows non-uniformly to the indicated grid. */ + + case CIFOP_GROW_G: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, cifGrowGridFunc, (ClientData) CIFPaintTable); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + /* SHRINK is just like grow except work from the space tiles. */ + + case CIFOP_SHRINK: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + DBPaintPlane(nextPlane, &TiPlaneRect, CIFPaintTable, + (PaintUndoInfo *) NULL); + cifPlane = nextPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &DBSpaceBits, *cifGrowFuncPtr, (ClientData) CIFEraseTable); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + case CIFOP_BLOAT: + cifPlane = curPlane; + cifSrTiles(op, area, cellDef, temps, + cifBloatFunc, op->co_client); + break; + + case CIFOP_BLOATMAX: + case CIFOP_BLOATMIN: + cifPlane = curPlane; + cifSrTiles(op, area, cellDef, temps, + cifBloatMaxFunc, (ClientData) op); + break; + + case CIFOP_BLOATALL: + cifPlane = curPlane; + cifSrTiles(op, area, cellDef, temps, + cifBloatAllFunc, (ClientData) op); + break; + + case CIFOP_SQUARES: + if (CalmaContactArrays == FALSE) + { + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifSquaresFillArea(op, cellDef, curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + } + break; + + case CIFOP_SQUARES_G: + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifSquaresFillArea(op, cellDef, curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + case CIFOP_SLOTS: + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifSlotsFillArea(op, cellDef, curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + case CIFOP_MAXRECT: + cifPlane = curPlane; + + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifRectBoundingBox(op, cellDef, curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + case CIFOP_NET: + netname = (char *)op->co_client; + cifPlane = curPlane; + ttype = CmdFindNetProc(netname, CIFDummyUse, &bbox, FALSE); + if (ttype != TT_SPACE) + { + UndoDisable(); + DBCellClearDef(Select2Def); + scx.scx_area = bbox; + scx.scx_use = CIFDummyUse; + scx.scx_trans = GeoIdentityTransform; + DBTreeCopyConnect(&scx, &DBConnectTbl[ttype], 0, + DBConnectTbl, &TiPlaneRect, Select2Use); + cifSrTiles(op, area, Select2Def, temps, cifPaintFunc, + (ClientData) CIFPaintTable); + DBCellClearDef(Select2Def); + UndoEnable(); + } + break; + + case CIFOP_BBOX: + if (CIFErrorDef == NULL) break; + + /* co_client contains the flag (1) for top-level only */ + if ((int)op->co_client == 1) + { + /* Only generate output for the top-level cell */ + int found = 0; + CellUse *celluse; + for (celluse = CIFErrorDef->cd_parents; + celluse != (CellUse *) NULL; + celluse = celluse->cu_nextuse) + { + if (celluse->cu_parent != (CellDef *) NULL) + if ((celluse->cu_parent->cd_flags & CDINTERNAL) + != CDINTERNAL) + { + found = 1; + break; + } + } + if (found != 0) break; + } + cifPlane = curPlane; + bbox = CIFErrorDef->cd_bbox; + cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; + bbox.r_xbot *= cifScale; + bbox.r_xtop *= cifScale; + bbox.r_ybot *= cifScale; + bbox.r_ytop *= cifScale; + DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox, + CIFPaintTable, (PaintUndoInfo *)NULL); + break; + + default: + continue; + } + } + + return curPlane; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFGen -- + * + * This procedure generates a complete set of CIF layers for + * a particular area of a particular cell. NOTE: if the argument + * genAllPlanes is FALSE, only planes for those layers having + * a bit set in 'layers' are generated; the others are set + * to NULL. + * + * Results: + * None. + * + * Side effects: + * The parameters realPlanes and tempPlanes are modified + * to hold the CIF and temporary layers for area of cellDef, + * as determined by the current CIF generation rules. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFGen(cellDef, area, planes, layers, replace, genAllPlanes, clientdata) + CellDef *cellDef; /* Cell for which CIF is to be generated. */ + Rect *area; /* Any CIF overlapping this area (in coords + * of cellDef) will be generated. The CIF + * will be clipped to this area. + */ + Plane **planes; /* Pointer to array of pointers to planes + * to hold "real" CIF layers that are + * generated. Pointers may initially be + * NULL. + */ + TileTypeBitMask *layers; /* CIF layers to generate. */ + bool replace; /* TRUE means that the new CIF is to replace + * anything that was previously in planes. + * FALSE means that the new CIF is to be + * OR'ed in with the current contents of + * planes. + */ + bool genAllPlanes; /* If TRUE, generate a tile plane even for + * those layers not specified as being + * generated in the 'layers' mask above. + */ + ClientData clientdata; /* Data that may be passed along to the + * CIF operation functions. + */ +{ + int i; + Plane *new[MAXCIFLAYERS]; + Rect expanded, clip; + + /* + * Generate the area in magic coordinates to search, and the area in + * cif coordinates to use in clipping the results of CIFGenLayer(). + */ + cifGenClip(area, &expanded, &clip); + + /* + * Generate all of the new layers in a temporary place. + * If a layer isn't being generated, leave new[i] set to + * NULL to indicate this fact. + */ + for (i = 0; i < CIFCurStyle->cs_nLayers; i++) + { + if (TTMaskHasType(layers,i)) + { + CIFErrorLayer = i; + new[i] = CIFGenLayer(CIFCurStyle->cs_layers[i]->cl_ops, + &expanded, cellDef, new, clientdata); + /* Clean up the non-manhattan geometry in the plane */ + if (CIFUnfracture) DBMergeNMTiles(new[i], &expanded, + (PaintUndoInfo *)NULL); + } + else if (genAllPlanes) new[i] = DBNewPlane((ClientData) TT_SPACE); + else new[i] = (Plane *) NULL; + } + + /* + * Now mask off all the unwanted material in the new layers, and + * either OR them into the existing layers or replace the existing + * material with them. + */ + for (i = 0; i < CIFCurStyle->cs_nLayers; i += 1) + { + if (new[i]) + cifClipPlane(new[i], &clip); + + if (replace) + { + if (planes[i]) + { + DBFreePaintPlane(planes[i]); + TiFreePlane(planes[i]); + } + planes[i] = new[i]; + continue; + } + + if (planes[i]) + { + if (new[i]) + { + cifPlane = planes[i]; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, new[i], &TiPlaneRect, + &CIFSolidBits, cifPaintFunc, + (ClientData) CIFPaintTable); + DBFreePaintPlane(new[i]); + TiFreePlane(new[i]); + } + } + else planes[i] = new[i]; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * cifClipPlane -- + * + * Erase the portions of the plane 'plane' that lie outside of 'clip'. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +cifClipPlane(plane, clip) + Plane *plane; + Rect *clip; +{ + Rect r; + + if (clip->r_xtop < TiPlaneRect.r_xtop) + { + r = TiPlaneRect; + r.r_xbot = clip->r_xtop; + DBPaintPlane(plane, &r, CIFEraseTable, (PaintUndoInfo *) NULL); + } + if (clip->r_ytop < TiPlaneRect.r_ytop) + { + r = TiPlaneRect; + r.r_ybot = clip->r_ytop; + DBPaintPlane(plane, &r, CIFEraseTable, (PaintUndoInfo *) NULL); + } + if (clip->r_xbot > TiPlaneRect.r_xbot) + { + r = TiPlaneRect; + r.r_xtop = clip->r_xbot; + DBPaintPlane(plane, &r, CIFEraseTable, (PaintUndoInfo *) NULL); + } + if (clip->r_ybot > TiPlaneRect.r_ybot) + { + r = TiPlaneRect; + r.r_ytop = clip->r_ybot; + DBPaintPlane(plane, &r, CIFEraseTable, (PaintUndoInfo *) NULL); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * cifGenClip -- + * + * Compute two new areas from the original area: one ('expanded') + * is expanded by a CIF halo and is used to determine how much of + * the database to search to find what's relevant for CIF generation; + * the other ('clip') is the CIF equivalent of area and is used to + * clip the resulting CIF. This code is tricky because area may run + * off to infinity, and we have to be careful not to expand past infinity. + * + * Results: + * None. + * + * Side effects: + * Sets *expanded and *clip. + * + * ---------------------------------------------------------------------------- + */ + +void +cifGenClip(area, expanded, clip) + Rect *area; /* Any CIF overlapping this area (in coords + * of cellDef) will be generated. The CIF + * will be clipped to this area. + */ + Rect *expanded, *clip; +{ + if (area->r_xbot > TiPlaneRect.r_xbot) + { + clip->r_xbot = area->r_xbot * CIFCurStyle->cs_scaleFactor; + expanded->r_xbot = area->r_xbot - CIFCurStyle->cs_radius; + } + else clip->r_xbot = expanded->r_xbot = area->r_xbot; + if (area->r_ybot > TiPlaneRect.r_ybot) + { + clip->r_ybot = area->r_ybot * CIFCurStyle->cs_scaleFactor; + expanded->r_ybot = area->r_ybot - CIFCurStyle->cs_radius; + } + else clip->r_ybot = expanded->r_ybot = area->r_ybot; + if (area->r_xtop < TiPlaneRect.r_xtop) + { + clip->r_xtop = area->r_xtop * CIFCurStyle->cs_scaleFactor; + expanded->r_xtop = area->r_xtop + CIFCurStyle->cs_radius; + } + else clip->r_xtop = expanded->r_xtop = area->r_xtop; + if (area->r_ytop < TiPlaneRect.r_ytop) + { + clip->r_ytop = area->r_ytop * CIFCurStyle->cs_scaleFactor; + expanded->r_ytop = area->r_ytop + CIFCurStyle->cs_radius; + } + else clip->r_ytop = expanded->r_ytop = area->r_ytop; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFClearPlanes -- + * + * This procedure clears out a collection of CIF planes. + * + * Results: + * None. + * + * Side effects: + * Each of the planes in "planes" is re-initialized to point to + * an empty paint plane. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFClearPlanes(planes) + Plane **planes; /* Pointer to an array of MAXCIFLAYERS + * planes. + */ +{ + int i; + + for (i = 0; i < MAXCIFLAYERS; i++) + { + if (planes[i] == NULL) + { + planes[i] = DBNewPlane((ClientData) TT_SPACE); + } + else + { + DBClearPaintPlane(planes[i]); + } + } +} diff --git a/cif/CIFhier.c b/cif/CIFhier.c new file mode 100644 index 00000000..21be45e4 --- /dev/null +++ b/cif/CIFhier.c @@ -0,0 +1,1146 @@ +/* CIFhier.c - + * + * This module handles hierarchy as part of the CIF generator. + * Because of the nature of the geometrical operations used + * to generate CIF, such as grow and shrink, the CIF representing + * two nearby subcells (or elements of an array) may require + * more than just the combined CIF of the two subcells considered + * separately. This module computes the extra CIF that may be + * needed. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFhier.c,v 1.3 2010/06/24 12:37:15 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "cif/CIFint.h" +#include "cif/cif.h" +#include "drc/drc.h" +#include "textio/textio.h" +#include "utils/undo.h" +#include "utils/malloc.h" +#include "utils/signals.h" + +/* To compute CIF where there are interaction areas we do two things: + * 1. Compute the CIF by combining all the material in all the interacting + * cells together. CIFTotalUse and CIFTotalDef and CIFTotalPlanes + * are used to hold the flattened material and resulting CIF. + * 2. Compute the CIF that results by considering the material in each + * subtree separately and also the material in the parent separately. + * The paint for each subtree is first flattened into CIFComponentUse + * and CIFComponentDef, and the resulting CIF from each subtree is + * OR'ed together into CIFComponentPlanes. + */ + +CellUse *CIFTotalUse = NULL; +CellDef *CIFTotalDef; +CellUse *CIFComponentUse; +CellDef *CIFComponentDef; +Plane *CIFTotalPlanes[MAXCIFLAYERS]; +Plane *CIFComponentPlanes[MAXCIFLAYERS]; + +/* The following use is just used to turn a def into a use for calling + * procedures that want a use. + */ + +CellUse *CIFDummyUse; + +/* The following local variables are used to share information + * between top-level procedures and search functions. + */ + +/* Used in cifHierPaintArrayFunc: */ + +Plane *cifHierCurPlane; /* Current plane. */ +static int cifHierXSpacing, cifHierYSpacing, cifHierXCount, cifHierYCount; + +/* Used in cifGrowSliver */ +static CIFLayer *CurCifLayer; + +/* Macro for scaling boxes into CIF coordinates: */ +#define SCALE(src, scale, dst) \ + (dst)->r_xbot = (src)->r_xbot * scale; \ + (dst)->r_ybot = (src)->r_ybot * scale; \ + (dst)->r_xtop = (src)->r_xtop * scale; \ + (dst)->r_ytop = (src)->r_ytop * scale; + + +/* + * ---------------------------------------------------------------------------- + * + * CIFInitCells -- + * + * This procedure just sets up cell definitions and uses needed + * for hierarchical checking and other CIF uses. + * + * Results: + * None. + * + * Side effects: + * DRCUse, DRCDef, and DRCDummyUse are set up if they're not + * there already. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFInitCells() +{ + int i; + + if (CIFTotalUse != NULL) return; + + CIFTotalDef = DBCellLookDef("__CIF__"); + if (CIFTotalDef == (CellDef *) NULL) + { + CIFTotalDef = DBCellNewDef ("__CIF__",(char *) NULL); + ASSERT(CIFTotalDef != (CellDef *) NULL, "cifMakeCell"); + DBCellSetAvail(CIFTotalDef); + CIFTotalDef->cd_flags |= CDINTERNAL; + } + CIFTotalUse = DBCellNewUse (CIFTotalDef, (char *) NULL); + DBSetTrans (CIFTotalUse, &GeoIdentityTransform); + CIFTotalUse->cu_expandMask = CU_DESCEND_SPECIAL; /* This is always expanded. */ + + CIFComponentDef = DBCellLookDef("__CIF2__"); + if (CIFComponentDef == (CellDef *) NULL) + { + CIFComponentDef = DBCellNewDef ("__CIF2__",(char *) NULL); + ASSERT(CIFComponentDef != (CellDef *) NULL, "cifMakeCell"); + DBCellSetAvail(CIFComponentDef); + CIFComponentDef->cd_flags |= CDINTERNAL; + } + CIFComponentUse = DBCellNewUse (CIFComponentDef, (char *) NULL); + DBSetTrans (CIFComponentUse, &GeoIdentityTransform); + CIFComponentUse->cu_expandMask = CU_DESCEND_SPECIAL; /* This is always expanded. */ + + /* Clear out the planes used to collect hierarchical CIF. */ + + for (i = 0; i < MAXCIFLAYERS; i++) + { + CIFComponentPlanes[i] = NULL; + CIFTotalPlanes[i] = NULL; + } + + /* Also create a dummy cell use to use for passing to + * procedures that need a use when all we've got is a def. + */ + + CIFDummyUse = DBCellNewUse(CIFTotalDef, (char *) NULL); + DBSetTrans (CIFDummyUse, &GeoIdentityTransform); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifHierCleanup -- + * + * This procedure is called after CIF hierarchical processing + * to clean up the cells and tile planes use for hierarchy and + * release storage. + * + * Results: + * None. + * + * Side effects: + * All the CIF-related uses and planes are cleaned up. + * + * ---------------------------------------------------------------------------- + */ + +void +cifHierCleanup() +{ + int i; + + /* We can't afford for this clearing out to be interrupted, or + * it could cause the next CIF to be generated wrong. + */ + + SigDisableInterrupts(); + + DBCellClearDef(CIFTotalDef); + DBCellClearDef(CIFComponentDef); + for (i = 0; i < MAXCIFLAYERS; i++) + { + if (CIFTotalPlanes[i] != NULL) + { + DBFreePaintPlane(CIFTotalPlanes[i]); + TiFreePlane(CIFTotalPlanes[i]); + CIFTotalPlanes[i] = NULL; + } + if (CIFComponentPlanes[i] != NULL) + { + DBFreePaintPlane(CIFComponentPlanes[i]); + TiFreePlane(CIFComponentPlanes[i]); + CIFComponentPlanes[i] = NULL; + } + } + + SigEnableInterrupts(); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifHierCopyFunc -- + * + * This procedure is called to copy paint from the database into + * flattened areas for CIF generation. It's important to use + * this procedure rather than calling DBCellCopyAllPaint. The + * reason is that DBCellCopyAllPaint clips the tiles to the + * edges of the search area. When generating CIF for layers like + * contacts, the exact location of the edge of the tile is + * important. Thus, this procedure always copies WHOLE tiles. + * Information will be clipped to the edge of the CIF generation + * area later. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * The tile is copied into the definition indicated by the + * client data. + * + * ---------------------------------------------------------------------------- + */ + +int +cifHierCopyFunc(tile, cxp) + Tile *tile; /* Pointer to tile to copy. */ + TreeContext *cxp; /* Describes context of search, including + * transform and client data. + */ +{ + TileType type = TiGetTypeExact(tile); + Rect sourceRect, targetRect; + int pNum; + CellDef *def = (CellDef *) cxp->tc_filter->tf_arg; + int dinfo = 0; + + /* Ignore tiles in vendor GDS, unless this is specifically */ + /* overridden by the "see-vendor" option. */ + + if (cxp->tc_scx->scx_use->cu_def->cd_flags & CDVENDORGDS) + { + if (!CIFCurStyle) + return 0; + else if (!(CIFCurStyle->cs_flags & CWF_SEE_VENDOR)) + return 0; + } + + /* Ignore space tiles, since they won't do anything anyway. */ + + if (IsSplit(tile)) + { + dinfo = DBTransformDiagonal(type, &cxp->tc_scx->scx_trans); + type = (SplitSide(tile)) ? SplitRightType(tile) : + SplitLeftType(tile); + } + + if (type == TT_SPACE) return 0; + + /* Get the rectangular area, and transform to final coords. */ + + TiToRect(tile, &sourceRect); + GeoTransRect(&cxp->tc_scx->scx_trans, &sourceRect, &targetRect); + + for (pNum = PL_SELECTBASE; pNum < DBNumPlanes; pNum++) + { + if (DBPaintOnPlane(type, pNum)) + { + DBNMPaintPlane(def->cd_planes[pNum], dinfo, &targetRect, + DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL); + } + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifHierCellFunc -- + * + * This procedure is invoked once for each subcell overlapping + * an interaction area. It flattens the subcell and its children + * in the area of the overlap, generates CIF for that area, and + * saves it in cifHierPieces. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * A new collection of CIF planes is added to cifHierPieces. + * + * ---------------------------------------------------------------------------- + */ + +int +cifHierCellFunc(scx) + SearchContext *scx; /* Describes cell and area in cell. */ +{ + SearchContext newscx; + Rect rootArea; + + /* Do not call this function on cells that are vendor GDS */ + /* (handled in cifHierCopyFunc()) */ + /* if (scx->scx_use->cu_def->cd_flags & CDVENDORGDS) return 0; */ + + /* In order to generate CIF safely in the interaction area, we + * have to yank material in a larger area: bloats and shrinks + * may cause this material to affect CIF in the interaction area. + * This may actually be over-conservative, but it's safe. Think + * carefully before trying to optimize! + */ + + DBCellClearDef(CIFComponentDef); + newscx = *scx; + GEO_EXPAND(&scx->scx_area, CIFCurStyle->cs_radius, &newscx.scx_area); + (void) DBTreeSrTiles(&newscx, &CIFCurStyle->cs_yankLayers, 0, + cifHierCopyFunc, (ClientData) CIFComponentDef); + + /* Set CIFErrorDef to NULL to ignore errors here... these will + * get reported anyway when the cell is CIF'ed non-hierarchically, + * so there's no point in making a second report here. + */ + + CIFErrorDef = (CellDef *) NULL; + GeoTransRect(&scx->scx_trans, &scx->scx_area, &rootArea); + CIFGen(CIFComponentDef, &rootArea, CIFComponentPlanes, + &CIFCurStyle->cs_hierLayers, FALSE, TRUE); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifHierErrorFunc -- + * + * This function is invoked when the combined CIF in a parent + * is LESS than the individual CIFs of the children. This means + * there are bogus rules in the CIF rule set. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Error information is output. + * + * ---------------------------------------------------------------------------- + */ + +int +cifHierErrorFunc(tile, checkArea) + Tile *tile; /* Tile that covers area it shouldn't. */ + Rect *checkArea; /* Intersection of this and tile is error. */ +{ + Rect area; + + TiToRect(tile, &area); + + /* Space in a diagonal tile is not an error if the corner containing + * space bounds the checkArea. + */ + if (IsSplit(tile)) + if (((area.r_xbot == checkArea->r_xbot) && !SplitSide(tile)) || + ((area.r_xtop == checkArea->r_xtop) && SplitSide(tile))) + return 0; + + GeoClip(&area, checkArea); + CIFError(&area, "parent and child disagree on CIF"); + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * cifHierCheckFunc -- + * + * This function is invoked once for each CIF tile coming from + * a subcell piece. It makes sure there are no space tiles over + * its area in "plane", then deletes everything from that area + * in "plane". + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Error messages may be output. + * + * ---------------------------------------------------------------------------- + */ + +int +cifHierCheckFunc(tile, plane) + Tile *tile; /* Tile containing CIF. */ + Plane *plane; /* Plane to check against and modify. */ +{ + Rect area; + + TiToRect(tile, &area); + + if (IsSplit(tile)) + { + DBSrPaintNMArea((Tile *)NULL, plane, TiGetTypeExact(tile), + &area, &DBSpaceBits, cifHierErrorFunc, (ClientData) &area); + + DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFEraseTable, + (PaintUndoInfo *) NULL); + } + else + { + DBSrPaintArea((Tile *) NULL, plane, &area, + &DBSpaceBits, cifHierErrorFunc, (ClientData) &area); + DBPaintPlane(plane, &area, CIFEraseTable, (PaintUndoInfo *) NULL); + } + + CIFTileOps++; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifHierPaintFunc -- + * + * Called to transfer information from one CIF plane to another. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * The area of tile is painted into plane. + * + * ---------------------------------------------------------------------------- + */ + +int +cifHierPaintFunc(tile, plane) + Tile *tile; + Plane *plane; /* Plane in which to paint CIF over tile's + * area. + */ +{ + Rect area; + + TiToRect(tile, &area); + if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, &area); + if (IsSplit(tile)) + DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFPaintTable, + (PaintUndoInfo *) NULL); + else + DBPaintPlane(plane, &area, CIFPaintTable, (PaintUndoInfo *) NULL); + CIFTileOps += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifCheckAndErase -- + * + * This utility procedure processes the hierarchical pieces + * in two ways. First, it makes sure that all the CIF in + * CIFComponentPlanes is present in CIFTotalPlanes. Second, + * it erases from CIFTotalPlanes any information that's in + * CIFComponentPlanes. + * + * Results: + * None. + * + * Side effects: + * The information in CIFTotalPlanes is reduced, and error messages + * may be output. + * + * ---------------------------------------------------------------------------- + */ + +void +cifCheckAndErase(style) + CIFStyle *style; /* Describes how to make CIF. */ +{ + int i; + + /* Process all of the bits of CIF in CIFComponentPlanes. */ + + for (i=0; ics_nLayers; i++) + { + CIFErrorLayer = i; + if (CIFComponentPlanes[i] == NULL) continue; + (void) DBSrPaintArea((Tile *) NULL, CIFComponentPlanes[i], + &TiPlaneRect, &CIFSolidBits, cifHierCheckFunc, + (ClientData) CIFTotalPlanes[i]); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFGenSubcells -- + * + * This procedure computes all of the CIF that must be added to + * a given area to compensate for interactions between subcells. + * + * Results: + * None. + * + * Side effects: + * The parameter "output" is modified (by OR'ing) to hold all + * the CIF that was generated for subcells. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFGenSubcells(def, area, output) + CellDef *def; /* Parent cell for which CIF is computed. */ + Rect *area; /* All CIF in this area is interesting. */ + Plane **output; /* Array of pointers to planes into which + * the CIF output will be OR'ed (real CIF + * only). + */ +{ + int stepSize, x, y, i, radius, oldTileOps, oldTileOps2; + Rect totalArea, square, interaction; + SearchContext scx; + + UndoDisable(); + CIFInitCells(); + radius = CIFCurStyle->cs_radius; + stepSize = CIFCurStyle->cs_stepSize; + if (stepSize <= 0) + { + stepSize = 20*radius; + if (stepSize < 50) stepSize = 50; + } + CIFDummyUse->cu_def = def; + scx.scx_use = CIFDummyUse; + scx.scx_trans = GeoIdentityTransform; + + /* Any tile operations processed here get billed to hierarchy + * in addition to being added to the total. + */ + + oldTileOps = CIFTileOps; + + /* Divide the area of the cell up into squares, and step through + * the chunks. In each chunk, the first thing to do is to find + * out if there are any subcell interactions within one + * radius of the square. + */ + + totalArea = *area; + GeoClip(&totalArea, &def->cd_bbox); + for (y = totalArea.r_ybot; y < totalArea.r_ytop; y += stepSize) + for (x = totalArea.r_xbot; x < totalArea.r_xtop; x += stepSize) + { + square.r_xbot = x; + square.r_ybot = y; + square.r_xtop = x + stepSize; + square.r_ytop = y + stepSize; + if (square.r_xtop > totalArea.r_xtop) + square.r_xtop = totalArea.r_xtop; + if (square.r_ytop > totalArea.r_ytop) + square.r_ytop = totalArea.r_ytop; + GEO_EXPAND(&square, radius, &square); + if (!DRCFindInteractions(def, &square, radius, + &interaction)) continue; + + /* We've found an interaction. Flatten it into CIFTotalUse, then + * make CIF from what's flattened. Yank extra material to + * ensure that CIF is generated correctly. + */ + + GEO_EXPAND(&interaction, CIFCurStyle->cs_radius, &scx.scx_area); + (void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0, + cifHierCopyFunc, (ClientData) CIFTotalDef); + CIFErrorDef = def; + CIFGen(CIFTotalDef, &interaction, CIFTotalPlanes, + &CIFCurStyle->cs_hierLayers, TRUE, TRUE); + + /* Now go through all the subcells overlapping the area + * and generate CIF for each subcell individually. OR this + * combined CIF together into CIFComponentPlanes. + */ + + scx.scx_area = interaction; + (void) DBCellSrArea(&scx, cifHierCellFunc, (ClientData) NULL); + + /* Also generate CIF for the paint in the parent alone. Ignore + * CIF generation errors here, since they will already have been + * recorded when the parent was CIF'ed by itself. + */ + + CIFErrorDef = (CellDef *) NULL; + CIFGen(def, &interaction, CIFComponentPlanes, + &CIFCurStyle->cs_hierLayers, FALSE, TRUE); + + /* Make sure everything in the pieces is also in the overall + * CIF, then erase the piece stuff from the overall, and + * throw away the pieces. + */ + + CIFErrorDef = def; + cifCheckAndErase(CIFCurStyle); + + /* Lastly, paint everything from the pieces into the result + * planes. + */ + + oldTileOps2 = CIFTileOps; + for (i=0; ics_nLayers; i++) + { + CurCifLayer = CIFCurStyle->cs_layers[i]; /* for growSliver */ + (void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i], + &TiPlaneRect, &CIFSolidBits, cifHierPaintFunc, + (ClientData) output[i]); + } + CIFHierRects += CIFTileOps - oldTileOps2; + + cifHierCleanup(); + } + + CIFHierTileOps += CIFTileOps - oldTileOps; + UndoEnable(); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifHierElementFunc -- + * + * This function is called once for each time an array element + * overlaps one of the four areas A, B, C, or D in cifHierArrayFunc + * (see below). Its job is to yank the relevant piece of this + * cell into CIFTotalDef, and also to yank the same piece into + * CIFComponentDef and generate a piece of CIF from it. The CIF + * from the piece is OR'ed into CIFComponentPlanes for later comparison + * with the parent. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * The cell CIFTotalUse is modified, as is CIFComponentUse and + * CIFComponentPlanes. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +cifHierElementFunc(use, transform, x, y, checkArea) + CellUse *use; /* CellUse being array-checked. */ + Transform *transform; /* Transform from this instance to + * the parent. + */ + int x, y; /* Indices of this instance. */ + Rect *checkArea; /* Area (in parent coords) to be + * CIF-generated. + */ +{ + Rect defArea; + Transform tinv; + SearchContext scx; + + GeoInvertTrans(transform, &tinv); + GeoTransRect(&tinv, checkArea, &defArea); + + /* Yank extra material to ensure that CIF is generated correctly. */ + + GEO_EXPAND(&defArea, CIFCurStyle->cs_radius, &scx.scx_area); + scx.scx_trans = *transform; + scx.scx_use = use; + (void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0, + cifHierCopyFunc, (ClientData) CIFTotalDef); + + DBCellClearDef(CIFComponentDef); + (void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0, + cifHierCopyFunc, (ClientData) CIFComponentDef); + + CIFErrorDef = (CellDef *) NULL; + CIFGen(CIFComponentDef, checkArea, CIFComponentPlanes, + &CIFCurStyle->cs_hierLayers, FALSE, TRUE); + + return 0; +} + + +/* + * --------------------------------------------------------------------------- + * cifGrowSliver() -- + * + * This function is passed the address of a "sliver" rectangle. It then + * grows the shortest dimension of the sliver so that it is at least minimum + * width. The minimum width is found through the variable CurCifLayer which + * identifies the current layer being generated. A "minwidth" command has been + * added to the cifoutput section for which the minimum width of each layer + * can be specified. + * + * Results: + * Always return 0 + * + * Side effects: + * Returns the modified rectangle in "area" (pointer) + * --------------------------------------------------------------------------- + */ + +int +cifGrowSliver(tile, area) + Tile *tile; + Rect *area; +{ + int height, width, expand_up, expand_side; + + TiToRect(tile, area); + expand_up = (TiGetType(BL(tile)) != TT_SPACE) || + (TiGetType(TR(tile)) != TT_SPACE); + expand_side = (TiGetType(LB(tile)) != TT_SPACE) || + (TiGetType(RT(tile)) != TT_SPACE); + if (CurCifLayer->min_width == 0) + return 0; + + height = area->r_ytop - area->r_ybot; + width = area->r_xtop - area->r_xbot; + printf("got sliver %d %d %d %d [%d,%d]\n", + area->r_xtop, area->r_xbot, area->r_ytop, + area->r_ybot, expand_up,expand_side); + + if ((height < width) || expand_up) + { + if (height >= CurCifLayer->min_width) return 0; + area->r_ytop += (CurCifLayer->min_width - height)/2; + area->r_ybot -= (CurCifLayer->min_width - height)/2; + } + if ((width < height) || expand_side) + { + if(width >= CurCifLayer->min_width) return 0; + area->r_xtop += (CurCifLayer->min_width - width)/2; + area->r_xbot -= (CurCifLayer->min_width - width)/2; + } + printf("created sliver %d %d %d %d \n", + area->r_xtop, area->r_xbot, area->r_ytop, area->r_ybot); + + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * cifHierPaintArrayFunc -- + * + * This function is used to paint in interaction tiles from an + * array. It is called once for each tile to be copied, and + * paints the tile into cifHierCurPlane. Then the tile is + * offset by cifHierXSpacing and cifHierYSpacing, and copied + * again and again, cifHierCount times in all. The caller must + * set up these shared variables. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * The plane pointed to by cifHierCurPlane gets modified. + * + * ---------------------------------------------------------------------------- + */ + +int +cifHierPaintArrayFunc(tile) + Tile *tile; +{ + Rect area; + int i, j, xbot, xtop; + + TiToRect(tile, &area); + if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, &area); + xbot = area.r_xbot; + xtop = area.r_xtop; + for (i=0; iscx_use; + radius = CIFCurStyle->cs_radius; + if ((use->cu_xlo == use->cu_xhi) && (use->cu_ylo == use->cu_yhi)) + return 2; + + /* We only want interactions between neighboring cells, so reduce */ + /* the array size to at most 2x2, process, then restore the */ + /* original array count. */ + + xhi = use->cu_xhi; + yhi = use->cu_yhi; + + if (use->cu_xlo != use->cu_xhi) + use->cu_xhi = use->cu_xlo + ((use->cu_xlo < use->cu_xhi) ? 1 : -1); + if (use->cu_ylo != use->cu_yhi) + use->cu_yhi = use->cu_ylo + ((use->cu_ylo < use->cu_yhi) ? 1 : -1); + + /* Compute the sizes and separations of elements, in coordinates + * of the parent. If the array is 1-dimensional, we set the + * corresponding spacing to an impossibly large distance. + */ + + childArea.r_xbot = 0; + childArea.r_ybot = 0; + + /* Ensure that array width or height 1 corresponds to a separation */ + /* large enough not to satisfy any conditions A, B, C, or D. */ + + if (use->cu_xlo == use->cu_xhi) + childArea.r_xtop = radius + + (use->cu_def->cd_bbox.r_xtop - use->cu_def->cd_bbox.r_xbot); + else childArea.r_xtop = use->cu_xsep; + if (use->cu_ylo == use->cu_yhi) + childArea.r_ytop = radius + + (use->cu_def->cd_bbox.r_ytop - use->cu_def->cd_bbox.r_ybot); + + else childArea.r_ytop = use->cu_ysep; + GeoTransRect(&use->cu_transform, &childArea, &parentArea); + xsep = parentArea.r_xtop - parentArea.r_xbot; + ysep = parentArea.r_ytop - parentArea.r_ybot; + GeoTransRect(&use->cu_transform, &use->cu_def->cd_bbox, &parentArea); + xsize = parentArea.r_xtop - parentArea.r_xbot; + ysize = parentArea.r_ytop - parentArea.r_ybot; + nx = (use->cu_bbox.r_xtop - use->cu_bbox.r_xbot - xsize)/xsep; + nx += 1; + ny = (use->cu_bbox.r_ytop - use->cu_bbox.r_ybot - ysize)/ysep; + ny += 1; + + /* Process each of the four areas A, B, C, and D. For each one, + * do three things: yank the relevant material into cell + * __CIF__, and generate a piece of CIF corresponding to each + * child area contributing to the overlap. This is all handled + * by the procedure cifHierElementFunc. Then generate the CIF + * for the combined information that was yanked into __CIF__. + * Collect all of the combined CIF from all four areas together + * into CIFTotalPlanes. Note: in each case we have to yank a larger + * area than we check, in order to include material that will be + * bloated or shrunk. + */ + + /* A */ + + if (ysep < ysize + radius) + { + A.r_xbot = use->cu_bbox.r_xbot - radius; + A.r_xtop = use->cu_bbox.r_xbot + xsize + radius; + A.r_ybot = use->cu_bbox.r_ybot + ysep - radius; + A.r_ytop = use->cu_bbox.r_ybot + ysize + radius; + GEO_EXPAND(&A, CIFCurStyle->cs_radius, &expandedArea); + (void) DBArraySr(use, &expandedArea, cifHierElementFunc, + (ClientData) &A); + CIFErrorDef = use->cu_parent; + CIFGen(CIFTotalDef, &A, CIFTotalPlanes, &CIFCurStyle->cs_hierLayers, + FALSE, TRUE); + anyInteractions = TRUE; + } + + /* C */ + + if (xsep < xsize + radius) + { + C.r_xbot = use->cu_bbox.r_xtop - xsize - radius; + C.r_xtop = use->cu_bbox.r_xtop - xsep + radius; + C.r_ybot = use->cu_bbox.r_ytop - ysize - radius; + C.r_ytop = use->cu_bbox.r_ytop + radius; + GEO_EXPAND(&C, CIFCurStyle->cs_radius, &expandedArea); + (void) DBArraySr(use, &expandedArea, cifHierElementFunc, + (ClientData) &C); + CIFErrorDef = use->cu_parent; + CIFGen(CIFTotalDef, &C, CIFTotalPlanes, &CIFCurStyle->cs_hierLayers, + FALSE, TRUE); + anyInteractions = TRUE; + } + + if ((xsep < xsize + radius) && (ysep < ysize + radius)) + { + /* B */ + + B.r_xbot = use->cu_bbox.r_xbot + xsep - radius; + B.r_xtop = use->cu_bbox.r_xbot + xsize + radius; + B.r_ybot = use->cu_bbox.r_ybot - radius; + B.r_ytop = use->cu_bbox.r_ybot + ysep - radius; + GEO_EXPAND(&B, CIFCurStyle->cs_radius, &expandedArea); + (void) DBArraySr(use, &expandedArea, cifHierElementFunc, + (ClientData) &B); + CIFErrorDef = use->cu_parent; + CIFGen(CIFTotalDef, &B, CIFTotalPlanes, &CIFCurStyle->cs_hierLayers, + FALSE, TRUE); + + /* D */ + + D.r_xbot = use->cu_bbox.r_xtop - xsep + radius; + D.r_xtop = use->cu_bbox.r_xtop + radius; + D.r_ybot = use->cu_bbox.r_ytop - ysize - radius; + D.r_ytop = use->cu_bbox.r_ytop - ysep + radius; + GEO_EXPAND(&D, CIFCurStyle->cs_radius, &expandedArea); + (void) DBArraySr(use, &expandedArea, cifHierElementFunc, + (ClientData) &D); + CIFErrorDef = use->cu_parent; + CIFGen(CIFTotalDef, &D, CIFTotalPlanes, &CIFCurStyle->cs_hierLayers, + FALSE, TRUE); + } + + if (anyInteractions) + { + + /* Remove redundant CIF that's already in the children, and + * make sure everything in the kids is in the parent too. + */ + + CIFErrorDef = use->cu_parent; + cifCheckAndErase(CIFCurStyle); + + /* Lastly, paint everything back from our local planes into + * the planes of the caller. In doing this, stuff has to + * be replicated many times over to cover each of the array + * interaction areas. + */ + + oldTileOps = CIFTileOps; + for (i=0; ics_nLayers; i++) + { + int scale = CIFCurStyle->cs_scaleFactor; + Rect cifArea; + + cifHierCurPlane = output[i]; + CurCifLayer = CIFCurStyle->cs_layers[i]; /* for growSliver */ + + /* The left edge of the array (from A). */ + + if ((ny > 1) && (ysep < ysize + radius)) + { + cifHierYSpacing = ysep * scale; + cifHierXSpacing = 0; + cifHierXCount = 1; + cifHierYCount = ny-1; + SCALE(&A, scale, &cifArea); + (void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i], + &cifArea, &CIFSolidBits, cifHierPaintArrayFunc, + (ClientData) NULL); + } + + /* The top edge of the array (from C). */ + + if ((nx > 1) && (xsep < xsize + radius)) + { + cifHierXSpacing = -xsep * scale; + cifHierYSpacing = 0; + cifHierXCount = nx-1; + cifHierYCount = 1; + SCALE(&C, scale, &cifArea); + (void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i], + &cifArea, &CIFSolidBits, cifHierPaintArrayFunc, + (ClientData) NULL); + } + + if ((nx > 1) && (ny > 1) && (xsep < xsize + radius) + && (ysep < ysize + radius)) + { + /* The bottom edge of the array (from B). */ + + cifHierXSpacing = xsep * scale; + cifHierYSpacing = 0; + cifHierXCount = nx-1; + cifHierYCount = 1; + SCALE(&B, scale, &cifArea); + (void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i], + &cifArea, &CIFSolidBits, cifHierPaintArrayFunc, + (ClientData) NULL); + + /* The right edge of the array (from D). */ + + cifHierXSpacing = 0; + cifHierYSpacing = -ysep * scale; + cifHierXCount = 1; + cifHierYCount = ny-1; + SCALE(&D, scale, &cifArea); + (void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i], + &cifArea, &CIFSolidBits, cifHierPaintArrayFunc, + (ClientData) NULL); + + /* The core of the array (from A and B). This code is a bit + * tricky in order to work correctly even for arrays where + * radius < ysep. The "if" statement handles this case. + */ + + cifHierXSpacing = xsep * scale; + cifHierYSpacing = ysep * scale; + cifHierXCount = nx-1; + cifHierYCount = ny-1; + parentArea.r_xbot = A.r_xtop - xsep; + parentArea.r_ybot = A.r_ytop - ysep; + if (parentArea.r_ybot > B.r_ytop) parentArea.r_ybot = B.r_ytop; + parentArea.r_xtop = A.r_xtop; + parentArea.r_ytop = A.r_ytop; + SCALE(&parentArea, scale, &cifArea); + (void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i], + &cifArea, &CIFSolidBits, cifHierPaintArrayFunc, + (ClientData) NULL); + } + } + CIFHierRects += CIFTileOps - oldTileOps; + } + + cifHierCleanup(); + + /* Restore the array bounds of the array */ + use->cu_xhi = xhi; + use->cu_yhi = yhi; + + return 2; +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFGenArrays -- + * + * This procedure computes all of the CIF that must be added to + * a given area of a parent to compensate for interactions between + * elements of arrays in that area. + * + * Results: + * None. + * + * Side effects: + * The parameter output is modified (by OR'ing) to hold all + * the CIF that was generated for array interactions. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFGenArrays(def, area, output) + CellDef *def; /* Parent cell for which CIF is computed. */ + Rect *area; /* All CIF in this area is interesting. */ + Plane **output; /* Array of pointers to planes into which + * the CIF output will be OR'ed (real CIF + * only, temp layers won't appear). If + * output is NULL, then CIF is stored in + * CIFPlanes, and the planes are initially + * cleared. + */ +{ + SearchContext scx; + int i, oldTileOps; + + UndoDisable(); + CIFInitCells(); + + /* Bill all tile operations here to hierarchical processing in + * addition to adding to the total. + */ + + oldTileOps = CIFTileOps; + + if (output == NULL) + { + output = CIFPlanes; + for (i=0; ics_nLayers; i++) + { + if (output[i] == NULL) + output[i] = DBNewPlane((ClientData) TT_SPACE); + else DBClearPaintPlane(output[i]); + } + } + + scx.scx_area = *area; + scx.scx_use = CIFDummyUse; + CIFDummyUse->cu_def = def; + (void) DBCellSrArea(&scx, cifHierArrayFunc, (ClientData) output); + + CIFHierTileOps += CIFTileOps - oldTileOps; + UndoEnable(); +} diff --git a/cif/CIFint.h b/cif/CIFint.h new file mode 100644 index 00000000..1a60aebc --- /dev/null +++ b/cif/CIFint.h @@ -0,0 +1,340 @@ +/* + * CIFint.h -- + * + * Defines things shared internally by the cif module of Magic, + * but not generally needed outside the cif module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/cif/CIFint.h,v 1.3 2008/12/04 17:10:29 tim Exp $" + */ + +#ifndef _CIFINT_H +#define _CIFINT_H + +#include "database/database.h" + +/* The main data structure used in the cif module is a description + * of how to generate CIF layers from the Magic tiles. There may + * be several different styles for generating CIF from the same Magic + * information, e.g. for fabricating at different geometries. Each + * of these CIF styles involves three kinds of data. A "CIFStyle" + * record gives overall information such as the number of layers. + * One "CIFLayer" gives overall information for each layer, and + * then a list of one or more "CIFOp" records describes a sequence + * of geometrical operations to perform to generate the layer. This + * data structure is built up by reading the technology file. + */ + +/* A CIFOp starts from a partially-completed CIF layer, does something + * to it, which may possibly involve some existing layers or temporary + * layers, and creates the next stage of the partially-completed + * CIF layer. Example operations are to AND with some existing paint, + * or to grow by a certain amount. + */ + +typedef struct bloat_data +{ + int bl_plane; /* Plane on which a bloat or squares + * operation is valid. + */ + int bl_distance[TT_MAXTYPES]; +} BloatData; + +typedef struct squares_data +{ + int sq_border; + int sq_size; + int sq_sep; + int sq_gridx; /* Only used for "squares-grid" */ + int sq_gridy; /* Only used for "squares-grid" */ +} SquaresData; + +typedef struct slots_data +{ + int sl_sborder; /* short tile side */ + int sl_ssize; + int sl_ssep; + int sl_lborder; /* long tile side */ + int sl_lsize; + int sl_lsep; + int sl_offset; +} SlotsData; + +typedef struct cifop +{ + TileTypeBitMask co_paintMask;/* Zero or more paint layers to consider. */ + TileTypeBitMask co_cifMask; /* Zero or more other CIF layers. */ + int co_opcode; /* Which geometric operation to use. See + * below for the legal ones. + */ + int co_distance; /* Grow or shrink distance (if needed). */ + ClientData co_client; /* Pointer to a BloatData, SquaresData, or + * SlotsData structure, or NULL. + */ + struct cifop *co_next; /* Next in list of operations to perform. */ +} CIFOp; + +/* The opcodes defined so far are: + * + * CIFOP_AND - AND current results with the layers indicated by + * the masks. + * CIFOP_ANDNOT - Wherever there is material indicated by the masks, + * erase those areas from the current results. + * CIFOP_OR - OR current results with the layers indicated by + * the masks. + * CIFOP_GROW - Grow the current results uniformly by co_distance. + * CIFOP_GROW_G - Grow the current results to snap to the indicated grid. + * CIFOP_SHRINK - Shrink the current results uniformly by co_distance. + * CIFOP_BLOAT - Find layers in paintMask, then bloat selectively + * according to bl_distance, and OR the results into + * the current plane + * CIFOP_SQUARES - Generates a pattern of squares (used for making + * contact vias. Each square is co_distance large, + * the squares are separated from each other by + * co_distance, and they are inside the edge of + * the material by at least co_distance. + * CIFOP_SLOTS - Generate a pattern of rectangles (used for making + * slots and slot vias). Similar to squares except + * for different dimensions in short and long tile + * dimensions. "0" for the long size indicates that + * the slot should extend the length of the tile + * minus the long-side border length. + * CIFOP_BLOATMAX - Like CIFOP_BLOAT, except whole side of tile gets + * bloated by same amount, which is max bloat from + * anywhere along side. Bloats can be negative. + * CIFOP_BLOATMIN - Same as CIFOP_BLOAT, except use min bloat from + * anywhere along side. + * CIFOP_BLOATALL - Added 3/21/05---bloat to encompass all connected + * material of the indicated type(s). + * CIFOP_BBOX - Added 4/2/05---create a single rectangle encompassing + * the cell bounding box. This involves no magic type + * layers but may itself be acted upon with grow/shrink + * rules. + * CIFOP_NET - Added 11/3/08---pull an entire electrical net into + * the CIF layer, selectively picking layers. + * CIFOP_MAXRECT - Reduce all areas to the largest internal fitting + * rectangle. + * CIFOP_COPYUP - Added 5/5/16---make and keep a copy the resulting layer, + * which will be painted into parent cells instead of the + * current cell. This replaces the "fault" method. + */ + +#define CIFOP_AND 1 +#define CIFOP_OR 2 +#define CIFOP_GROW 3 +#define CIFOP_GROW_G 4 +#define CIFOP_SHRINK 5 +#define CIFOP_BLOAT 6 +#define CIFOP_SQUARES 7 +#define CIFOP_SLOTS 8 +#define CIFOP_BLOATMAX 9 +#define CIFOP_BLOATMIN 10 +#define CIFOP_BLOATALL 11 +#define CIFOP_ANDNOT 12 +#define CIFOP_SQUARES_G 13 +#define CIFOP_BBOX 14 +#define CIFOP_NET 15 +#define CIFOP_MAXRECT 16 +#define CIFOP_COPYUP 17 + +/* Added by Tim 10/21/2004 */ +/* The following structure is used to pass information on how to draw + * contact subcell arrays for a specific magic contact tile type. For + * the GDS write routine, the GDS file (FILE *) is passed as the client + * data. + */ + +typedef struct cifsquaresinfo +{ + SquaresData *csi_squares; /* Information on how to generate squares */ + TileType csi_type; /* Magic contact tile type */ + ClientData csi_client; /* Used to pass output file info. */ +} CIFSquaresInfo; + +/* The following data structure contains all the information about + * a particular CIF layer. + */ + +typedef struct +{ + char *cl_name; /* Name of layer. */ + CIFOp *cl_ops; /* List of operations. If NULL, layer is + * determined entirely by cl_initial. + */ + int cl_growDist; /* Largest distance material may move in + * this layer from its original Magic + * position, due to grows. Expressed + * in CIF units. If this layer uses temp + * layers, this distance must include grows + * from the temp layers. + */ + int cl_shrinkDist; /* Same as above, except for shrinks. */ + int cl_flags; /* Bunches of flags: see below. */ + int cl_calmanum; /* Number (0-63) of this layer for output as + * Calma (GDS-II stream format), or -1 if + * this layer should not be output. + */ + int cl_calmatype; /* Data type (0-63) for Calma output, or -1 + * if this layer should not be output. + */ + int min_width; /* the minimum width rule in centi-microns + * for the layer. This is used by Grow Sliver + * to generate drc correct parent slivers + */ +#ifdef THREE_D + int cl_renderStyle; /* Style to render CIF layer with */ + float cl_height; /* (rendered) height of CIF layer above substrate */ + float cl_thick; /* (rendered) thickness of CIF layer */ +#endif + +} CIFLayer; + +/* The CIFLayer flags are: + * + * CIF_TEMP: Means that this is a temporary layer used to build + * up CIF information. It isn't output in the CIF file. + * CIF_BBOX_TOP: Indicates that the bounding box rectangle should + * only be generated if the cell is a top-level cell. + */ + +#define CIF_TEMP 1 +#define CIF_BBOX_TOP 2 + +/* The following data structure describes a complete set of CIF + * layers. The number of CIF layers (MAXCIFLAYERS) must not be + * greater than the number of tile types (TT_MAXTYPES)!! + */ + +#define MAXCIFLAYERS (TT_MAXTYPES - 1) + +typedef struct cifkeep +{ + struct cifkeep *cs_next; + char *cs_name; +} CIFKeep; + +typedef struct cifstyle +{ + char cs_status; /* Status: Loaded, not loaded, or pending. */ + char *cs_name; /* Name used for this kind of CIF. */ + int cs_nLayers; /* Number of layers. */ + int cs_radius; /* Radius of interaction for hierarchical + * processing (expressed in Magic units). + */ + int cs_stepSize; /* If non-zero, user-specified step size + * for hierarchical processing (in Magic + * units). + */ + int cs_gridLimit; /* The limit of grid scaling. This limits + * the use of "scalegrid" to prevent Magic + * from generating geometry smaller than the + * process minimum grid. + */ + int cs_scaleFactor; /* Number of CIF units per Magic unit. + * CIF units are usually centimicrons, but + * see cs_expander below. + */ + int cs_reducer; /* Reduction factor (used only to reduce + * number of zeroes in CIF files and make + * file more readable). Default of 1. + * Unused for GDS input/output. + */ + int cs_expander; /* cs_scaleFactor / cs_expander = scale in + * centimicrons. Default of 1. Value 10 + * means cs_scaleFactor is measured in + * nanometers (millimicrons) + */ + + TileTypeBitMask cs_yankLayers; + /* For hierarchical processing, only these + * Magic types need to be yanked. + */ + TileTypeBitMask cs_hierLayers; + /* For hierarchical processing, only these + * CIF layers need to be generated. + */ + int cs_labelLayer[TT_MAXTYPES]; + /* Each entry corresponds to one Magic layer, + * and gives index of CIF real layer to use + * for labels attached to this Magic layer. + * -1 means no known CIF layer for this Magic + * layer. + */ + CIFLayer *cs_layers[MAXCIFLAYERS]; + /* Describes how to generate each layer.*/ + int cs_flags; /* bitmask of boolean-valued output options */ + +} CIFStyle; + +/* values for cs_flags */ +#define CWF_PERMISSIVE_LABELS 0x01 +#define CWF_GROW_SLIVERS 0x02 +#define CWF_ANGSTROMS 0x04 +#define CWF_GROW_EUCLIDEAN 0x08 +#define CWF_SEE_VENDOR 0x10 /* Override vendor GDS flag in cells */ +#define CWF_NO_ERRORS 0x20 /* Do not generate error msgs and fdbk */ + +/* procedures */ + +extern bool CIFNameToMask(); +extern void CIFGenSubcells(); +extern void CIFGenArrays(); +extern void CIFGen(); +extern void CIFClearPlanes(); +extern Plane *CIFGenLayer(); +extern void CIFInitCells(); +extern int cifHierCopyFunc(); +extern void CIFLoadStyle(); + +/* Shared variables and structures: */ + +extern Plane *CIFPlanes[]; /* Normal place to store CIF. */ +extern CIFKeep *CIFStyleList; /* List of all CIF styles. */ +extern CIFStyle *CIFCurStyle; /* Current style being used. */ +extern CellUse *CIFComponentUse; /* Flatten stuff in here if needed. */ +extern CellDef *CIFComponentDef; /* Corresponds to CIFComponentUse. */ +extern CellUse *CIFDummyUse; /* Used to dummy up a CellUse for a + * def. + */ + +/* Valid values of CIFWarningLevel (see cif.h) */ + +typedef enum {CIF_WARN_DEFAULT, CIF_WARN_NONE, CIF_WARN_ALIGN, + CIF_WARN_LIMIT, CIF_WARN_REDIRECT, CIF_WARN_END} CIFWarningTypes; + +/* Statistics counters: */ + +extern int CIFTileOps; +extern int CIFHierTileOps; +extern int CIFRects; +extern int CIFHierRects; + +/* Tables used for painting and erasing CIF. */ + +extern PaintResultType CIFPaintTable[], CIFEraseTable[]; + +/* Procedures and variables for reporting errors. */ + +extern int CIFErrorLayer; +extern CellDef *CIFErrorDef; +extern void CIFError(); + +/* The following determines the tile type used to hold the CIF + * information on its paint plane. + */ + +#define CIF_SOLIDTYPE 1 +extern TileTypeBitMask CIFSolidBits; + +#endif /* _CIFINT_H */ diff --git a/cif/CIFmain.c b/cif/CIFmain.c new file mode 100644 index 00000000..3975529e --- /dev/null +++ b/cif/CIFmain.c @@ -0,0 +1,413 @@ +/* CIFmain.c - + * + * This file contains global information for the CIF module, + * such as performance statistics. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFmain.c,v 1.3 2009/01/15 15:44:34 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "cif/CIFint.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" + +/* The following points to a list of all the CIF output styles + * currently understood: + */ + +CIFKeep *CIFStyleList; + +/* The current style being used for CIF output: */ + +CIFStyle *CIFCurStyle = NULL; + +/* The following are statistics gathered at various points in + * CIF processing. There are two versions of each statistic: + * a total number, and the number since stats were last printed. + */ + +int CIFTileOps = 0; /* Total tiles touched in geometrical + * operations. + */ +int CIFHierTileOps = 0; /* Tiles touched in geometrical operations + * as part of hierarchical processing. + */ +int CIFRects = 0; /* Total CIF rectangles output. */ +int CIFHierRects = 0; /* Rectangles stemming from interactions. */ + +static int cifTotalTileOps = 0; +static int cifTotalHierTileOps = 0; +static int cifTotalRects = 0; +static int cifTotalHierRects = 0; + +/* This file provides several procedures for dealing with errors during + * the CIF generation process. Low-level CIF artwork-manipulation + * procedures call CIFError without knowing what cell CIF is being + * generated for, or what layer is being generated. Higher-level + * routines are responsible for recording that information in the + * variables below so that CIFError can output meaningful diagnostics + * using the feedback mechanism. + */ + +global CellDef *CIFErrorDef; /* Definition in which to record errors. */ +global int CIFErrorLayer; /* Index of CIF layer associated with errors.*/ + + +/* + * ---------------------------------------------------------------------------- + * + * CIFPrintStats -- + * + * This procedure prints out CIF statistics including both + * total values and counts since the last printing. + * + * Results: + * None. + * + * Side effects: + * Several messages are printed. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFPrintStats() +{ + TxPrintf("CIF statistics (recent/total):\n"); + cifTotalTileOps += CIFTileOps; + TxPrintf(" Geometrical tile operations: %d/%d\n", + CIFTileOps, cifTotalTileOps); + CIFTileOps = 0; + cifTotalHierTileOps += CIFHierTileOps; + TxPrintf(" Tile operations for hierarchy: %d/%d\n", + CIFHierTileOps, cifTotalHierTileOps); + CIFHierTileOps = 0; + cifTotalRects += CIFRects; + TxPrintf(" CIF rectangles output: %d/%d\n", + CIFRects, cifTotalRects); + CIFRects = 0; + cifTotalHierRects += CIFHierRects; + TxPrintf(" CIF rectangles due to hierarchical interactions: %d/%d\n", + CIFHierRects, cifTotalHierRects); + CIFHierRects = 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFGetOutputScale -- + * + * This routine is given here so that the CIF output scale can be + * accessed from the "commands" directory source without declaring + * external references to CIF global variables. + * + * Results: + * Internal units-to-(nanometers * convert) conversion factor (float). + * Use convert = 1000 for centimicrons-to-microns conversion + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +float +CIFGetOutputScale(convert) + int convert; +{ + if (CIFCurStyle == NULL) return 1.0; + + return ((float)(10 * CIFCurStyle->cs_scaleFactor) / + (float)(CIFCurStyle->cs_expander * convert)); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFPrintStyle -- + * + * This procedure prints the current CIF output style or list + * of known styles. + * + * Results: + * None. + * + * Side effects: + * Output. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFPrintStyle(dolist, doforall, docurrent) + bool dolist; /* Return as a list if true */ + bool doforall; /* Print all known styles if true */ + bool docurrent; /* Print current style if true */ +{ + CIFKeep *style; + + if (docurrent) + { + if (CIFCurStyle == NULL) + TxError("Error: No style is set\n"); + else + { + if (!dolist) TxPrintf("The current style is \""); +#ifdef MAGIC_WRAPPER + if (dolist) + Tcl_SetResult(magicinterp, CIFCurStyle->cs_name, NULL); + else +#endif + TxPrintf("%s", CIFCurStyle->cs_name); + if (!dolist) TxPrintf("\".\n"); + } + } + + if (doforall) + { + if (!dolist) TxPrintf("The CIF output styles are: "); + + for (style = CIFStyleList; style != NULL; style = style->cs_next) + { + if (dolist) + { +#ifdef MAGIC_WRAPPER + Tcl_AppendElement(magicinterp, style->cs_name); +#else + if (style != CIFStyleList) TxPrintf(" "); + TxPrintf("%s", style->cs_name); +#endif + } + else + { + if (style != CIFStyleList) TxPrintf(", "); + TxPrintf("%s", style->cs_name); + } + } + if (!dolist) TxPrintf(".\n"); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFSetStyle -- + * + * This procedure changes the current CIF output style to the one + * named by the parameter. + * + * Results: + * None. + * + * Side effects: + * The current CIF style is changed. If the name doesn't match, + * or is ambiguous, then a list of all CIF styles is output. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFSetStyle(name) + char *name; /* Name of the new style. If NULL, just + * print out the valid styles. + */ +{ + CIFKeep *style, *match; + int length; + + if (name == NULL) return; + + match = NULL; + length = strlen(name); + + for (style = CIFStyleList; style != NULL; style = style->cs_next) + { + if (strncmp(name, style->cs_name, length) == 0) + { + if (match != NULL) + { + TxError("CIF output style \"%s\" is ambiguous.\n", name); + CIFPrintStyle(FALSE, TRUE, TRUE); + return; + } + match = style; + } + } + + if (match != NULL) + { + CIFLoadStyle(match->cs_name); + TxPrintf("CIF output style is now \"%s\"\n", name); + return; + } + + TxError("\"%s\" is not one of the CIF output styles Magic knows.\n", name); + CIFPrintStyle(FALSE, TRUE, TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFNameToMask -- + * + * Finds the CIF planes for a given name. + * + * Results: + * Returns TRUE on success, or FALSE if "name" failed to match any layers. + * + * Side effects: + * If there's no match, then an error message is output. + * The sets 'result' to be all types containing the CIF layer named + * "name". The current CIF style is used for the lookup. If "depend" + * is non-NULL, then it is filled with the mask of all layers on which + * the named layer depends. + * ---------------------------------------------------------------------------- + */ + +bool +CIFNameToMask(name, result, depend) + char *name; + TileTypeBitMask *result; + TileTypeBitMask *depend; +{ + int i, j; + CIFOp *op; + CIFLayer *cl; + + if (!CIFCurStyle) + { + TxError("No CIF output style set!\n"); + return FALSE; + } + + TTMaskZero(result); + for (i = 0; i < CIFCurStyle->cs_nLayers; i++) + if (strcmp(name, CIFCurStyle->cs_layers[i]->cl_name) == 0) + TTMaskSetType(result, i); + + if (!TTMaskEqual(result, &DBZeroTypeBits)) + { + /* This loop depends on the fact that templayers must */ + /* be declared in order of dependency; that is, you */ + /* can't use a layer before it is declared. Thus, the */ + /* dependent layers will always be filled in from layer */ + /* i back to zero. */ + + if (depend) + { + TTMaskZero(depend); + TTMaskSetMask(depend, result); + for (j = CIFCurStyle->cs_nLayers - 1; j >= 0; j--) + if (TTMaskHasType(depend, j)) + { + cl = CIFCurStyle->cs_layers[j]; + for (op = cl->cl_ops; op != NULL; op = op->co_next) + TTMaskSetMask(depend, &op->co_cifMask); + } + } + return TRUE; + } + + TxError("CIF name \"%s\" doesn't exist in style \"%s\".\n", name, + CIFCurStyle->cs_name); + TxError("The valid CIF layer names are: "); + for (i = 0; i < CIFCurStyle->cs_nLayers; i++) + { + if (i == 0) + TxError("%s", CIFCurStyle->cs_layers[i]->cl_name); + else + TxError(", %s", CIFCurStyle->cs_layers[i]->cl_name); + } + TxError(".\n"); + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFError -- + * + * This procedure is called by low-level CIF generation routines + * when a problem is encountered in generating CIF. This procedure + * notes the problem using the feedback mechanism. + * + * Results: + * None. + * + * Side effects: + * Feedback information is added. The caller must have set CIFErrorDef + * to point to the cell definition that area refers to. If CIFErrorDef + * is NULL, then errors are ignored. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFError(area, message) + Rect *area; /* Place in CIFErrorDef where there was a + * problem in generating CIFErrorLayer. + */ + char *message; /* Short note about what went wrong. */ +{ + char msg[200]; + + if (CIFCurStyle->cs_flags & CWF_NO_ERRORS) return; + + if (CIFErrorDef == (NULL)) return; + (void) sprintf(msg, "CIF error in cell %s, layer %s: %s", + CIFErrorDef->cd_name, CIFCurStyle->cs_layers[CIFErrorLayer]->cl_name, + message); + DBWFeedbackAdd(area, msg, CIFErrorDef, CIFCurStyle->cs_scaleFactor, + STYLE_PALEHIGHLIGHTS); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFOutputScaleFactor -- + * + * Returns current conversion factor between CIF units and + * Magic units. + * + * Results: + * The return value is the number of centimicrons per Magic + * unit in the current CIF output style. If there is no + * known CIF output style, 1 is returned. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +CIFOutputScaleFactor() +{ + if (CIFCurStyle == NULL) return 1; + return CIFCurStyle->cs_scaleFactor; +} diff --git a/cif/CIFrdcl.c b/cif/CIFrdcl.c new file mode 100644 index 00000000..0dca13c9 --- /dev/null +++ b/cif/CIFrdcl.c @@ -0,0 +1,1389 @@ +/* CIFreadcell.c - + * + * This file contains more routines to parse CIF files. In + * particular, it contains the routines to handle cells, + * both definitions and calls, and user-defined features + * like labels. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdcl.c,v 1.5 2010/08/25 17:33:55 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/undo.h" +#include "database/database.h" +#include "cif/CIFint.h" +#include "cif/CIFread.h" +#include "cif/cif.h" +#include "calma/calma.h" +#include "utils/utils.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" +#include "drc/drc.h" + +/* The following variable is made available to the outside world, + * and is the cell definition currently being modified. + */ + +CellDef *cifReadCellDef; + +/* + * The following hash table is used internally to keep track of + * of all the cells we've seen definitions for or calls on. + * The hash table entries contain pointers to cellDefs, and + * are indexed by CIF cell number. If the CDAVAILABLE bit is + * set it means we've read the cell's contents. If not set, it + * means that the cell has been called but not yet defined. + */ +HashTable CifCellTable; + +/* The following variable is used to save and restore current + * paint layer information so that we can resume the correct + * layer after a subcell definition. + */ + +Plane *cifOldReadPlane = NULL; + +/* The following boolean is TRUE if a subcell definition is being + * read. FALSE means we're working on the EditCell. + */ + +bool cifSubcellBeingRead; + +/* The following two collections of planes are used to hold CIF + * information while cells are being read in (one set for the + * outermost, unnamed cell, and one for the current subcell). + * When a cell is complete, then geometrical operations are + * performed on the layers and stuff is painted into Magic. + */ + +Plane *cifEditCellPlanes[MAXCIFRLAYERS]; +Plane *cifSubcellPlanes[MAXCIFRLAYERS]; +Plane **cifCurReadPlanes = cifEditCellPlanes; /* Set of planes currently + * in force. + */ +TileType cifCurLabelType = TT_SPACE; /* Magic layer on which to put '94' + * labels that aren't identified by + * type. + */ + +/* Structure used when flattening the CIF hierarchy on read-in */ + +typedef struct { + Plane *plane; + Transform *trans; +} CIFCopyRec; + +/* The following variable is used to hold a subcell id between + * the 91 statement and the (immediately-following?) call statement. + * The string this points to is dynamically allocated, so it must + * also be freed explicitly. + */ + +char *cifSubcellId = NULL; + +/* + * ---------------------------------------------------------------------------- + * + * CIFReadCellInit -- + * + * This procedure initializes the data structures in this + * module just prior to reading a CIF file. + * + * If ptrkeys is 0, the keys used in this hash table will + * be strings; if it is 1, the keys will be CIF numbers. + * + * Results: + * None. + * + * Side effects: + * The cell hash table is initialized, and things are set up + * to put information in the EditCell first. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFReadCellInit(ptrkeys) + int ptrkeys; +{ + int i; + + HashInit(&CifCellTable, 32, ptrkeys); + cifReadCellDef = EditCellUse->cu_def; + cifSubcellBeingRead = FALSE; + cifCurReadPlanes = cifEditCellPlanes; + for (i = 0; i < MAXCIFRLAYERS; i += 1) + { + if (cifEditCellPlanes[i] == NULL) + cifEditCellPlanes[i] = DBNewPlane((ClientData) TT_SPACE); + if (cifSubcellPlanes[i] == NULL) + cifSubcellPlanes[i] = DBNewPlane((ClientData) TT_SPACE); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * cifForgetCell -- + * + * This local procedure is used to find a cell in the subcell + * table and remove its CellDef entry. + * + * Results: + * FALSE if no such entry was found, otherwise TRUE. + * + * Side effects: + * Mucks with the CIF cell name hash table. + * + * ---------------------------------------------------------------------------- + */ + +bool +cifForgetCell(cifNum) + int cifNum; +{ + HashEntry *h; + + h = HashLookOnly(&CifCellTable, (char *)(spointertype)cifNum); + if (h == NULL) + return FALSE; + else if (HashGetValue(h) == 0) + return FALSE; + + HashSetValue(h, 0); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifUniqueCell -- + * + * Attempt to find a cell in the CIF subcell name hash table. + * If one exists, rename its definition so that it will not + * be overwritten when the cell is redefined. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +cifUniqueCell(cifNum) + int cifNum; +{ + HashEntry *h; + CellDef *def, *testdef; + char name[17]; + int reused = 0; + + h = HashLookOnly(&CifCellTable, (char *)(spointertype)cifNum); + + if ((h == NULL) || HashGetValue(h) == 0) + { + /* Cell was deleted with "DD". Don't rename anything */ + return; + } + + sprintf(name, "%d", cifNum); + def = DBCellLookDef(name); + if (def == (CellDef *)NULL) + return; + + /* Cell may have been called but not yet defined---this is okay. */ + else if ((def->cd_flags & CDAVAILABLE) == 0) + return; + + testdef = def; + while (testdef != NULL) + { + sprintf(name, "%d_%d", cifNum, ++reused); + testdef = DBCellLookDef(name); + } + DBCellRenameDef(def, name); + + h = HashFind(&CifCellTable, (char *)(spointertype)cifNum); + HashSetValue(h, 0); + + CIFReadError("Warning: cell definition %d reused.\n", cifNum); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifFindCell -- + * + * This local procedure is used to find a cell in the subcell + * table, and create a new subcell if there isn't already + * one there. If a new subcell is created, its CDAVAILABLE + * is left FALSE. + * + * Results: + * The return value is a pointer to the definition for the + * cell whose CIF number is cifNum. + * + * Side effects: + * A new CellDef may be created. + * + * ---------------------------------------------------------------------------- + */ + +CellDef * +cifFindCell(cifNum) + int cifNum; /* The CIF number of the desired cell. */ +{ + HashEntry *h; + CellDef *def, *testdef; + int reused; + + h = HashFind(&CifCellTable, (char *)(spointertype)cifNum); + + if (HashGetValue(h) == 0) + { + char name[15]; + + sprintf(name, "%d", cifNum); + def = DBCellLookDef(name); + if (def == NULL) + { + def = DBCellNewDef(name, (char *) NULL); + + /* Tricky point: call DBReComputeBbox here to make SURE + * that the cell has a valid bounding box. Otherwise, + * if the cell is used in a parent before being defined + * then it will cause a core dump. + */ + + DBReComputeBbox(def); + } + HashSetValue(h, def); + } + return (CellDef *) HashGetValue(h); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFScalePlanes -- + * + * Scale all of the CIF planes by the amount (scalen / scaled) + * + * ---------------------------------------------------------------------------- + */ + +void +CIFScalePlanes(scalen, scaled, planearray) + int scalen; + int scaled; + Plane **planearray; +{ + int pNum; + Plane *newplane; + + for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + { + if (planearray[pNum] != NULL) + { + newplane = DBNewPlane((ClientData) TT_SPACE); + DBClearPaintPlane(newplane); + dbScalePlane(planearray[pNum], newplane, pNum, + scalen, scaled, TRUE); + DBFreePaintPlane(planearray[pNum]); + TiFreePlane(planearray[pNum]); + planearray[pNum] = newplane; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFInputRescale -- + * + * Scale all CIF distances by n / d. Normally, rescaling is done in + * the upward direction (n > 1, d = 1) in response to a value in the + * CIF input that does not divide evenly into the database units of + * the CIF planes. Currently there is no call to CIFInputRescale + * with d > 1, but it is left for the possibility that scalefactors + * could be restored after finishing a subcell definition, possibly + * preventing integer overflow in large designs. + * + * Results: + * None. + * + * Side effects: + * Many. Adjusts the CIF input style scalefactor (CIF vs. magic + * units), multiplier (CIF units vs. centimicrons), distances of all + * CIF boolean operations, and the scale of all existing planes in + * the current CIF database. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFInputRescale(n, d) + int n, d; +{ + CIFReadStyle *istyle = cifCurReadStyle; + CIFReadLayer *cl; + CIFOp *op; + int i; + + /* 2-step process for efficiency */ + + if (n > 1) + { + istyle->crs_scaleFactor *= n; + istyle->crs_multiplier *= n; + + for (i = 0; i < istyle->crs_nLayers; i++) + { + cl = istyle->crs_layers[i]; + for (op = cl->crl_ops; op != NULL; op = op->co_next) + if (op->co_distance) + op->co_distance *= n; + } + } + + if (d > 1) + { + istyle->crs_scaleFactor /= d; + istyle->crs_multiplier /= d; + + for (i = 0; i < istyle->crs_nLayers; i++) + { + cl = istyle->crs_layers[i]; + for (op = cl->crl_ops; op != NULL; op = op->co_next) + if (op->co_distance) + op->co_distance /= d; + } + } + + CIFScalePlanes(n, d, cifEditCellPlanes); + if (cifEditCellPlanes != cifSubcellPlanes) + CIFScalePlanes(n, d, cifSubcellPlanes); + + CIFReadWarning("CIF style %s: units rescaled by factor of %d / %d\n", + istyle->crs_name, n, d); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseStart -- + * + * Parse the beginning of a symbol (cell) definition. + * ds ::= D { blank } S integer [ sep integer sep integer ] + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * Set up information for the new cell, including the CIF + * planes and creating a Magic cell (if one doesn't exist + * already). + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseStart() +{ + int number; + + if (cifSubcellBeingRead) + { + CIFReadError("definition start inside other definition; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + if (cifSubcellId != NULL) + { + CIFReadError("pending call identifier %s discarded.\n", cifSubcellId); + (void) StrDup(&cifSubcellId, (char *) NULL); + } + + /* Take the `S'. */ + + TAKE(); + if (!CIFParseInteger(&number)) + { + CIFReadError("definition start, but no symbol number; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + else if (number < 0) + { + CIFReadError("illegal negative symbol number; definition ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + + if (!CIFParseInteger(&cifReadScale1)) + { + cifReadScale1 = 1; + cifReadScale2 = 1; + } + else + { + cifReadScale1 *= cifCurReadStyle->crs_multiplier; /* Units not centimicrons */ + + if (!CIFParseInteger(&cifReadScale2)) + { + CIFReadError( + "only one of two scale factors given; ignored.\n"); + cifReadScale1 = 1; + cifReadScale2 = 1; + } + } + + if (cifReadScale1 <= 0 || cifReadScale2 <= 0) + { + CIFReadError("Illegal scale %d / %d changed to 1 / 1\n", + cifReadScale1, cifReadScale2); + cifReadScale1 = 1; + cifReadScale2 = 1; + } + + + /* + * Set up the cell definition. + */ + + cifUniqueCell(number); + cifReadCellDef = cifFindCell(number); + DBCellClearDef(cifReadCellDef); + DBCellSetAvail(cifReadCellDef); + + cifOldReadPlane = cifReadPlane; + cifReadPlane = (Plane *) NULL; + cifSubcellBeingRead = TRUE; + cifCurReadPlanes = cifSubcellPlanes; + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * cifCheckPaintFunc --- + * + * Callback function for checking if any paint has been generated + * on the CIF target plane for a "copyup" layer. + * ---------------------------------------------------------------------------- + */ + +int cifCheckPaintFunc(tile, clientData) + Tile *tile; + ClientData clientData; +{ + return 1; +} + +/* Callback function for copying paint from one CIF cell into another */ + +int +cifCopyPaintFunc(tile, cifCopyRec) + Tile *tile; + CIFCopyRec *cifCopyRec; +{ + int pNum; + Rect sourceRect, targetRect; + Transform *trans = cifCopyRec->trans; + Plane *plane = cifCopyRec->plane; + + if (trans) + { + TiToRect(tile, &sourceRect); + GeoTransRect(trans, &sourceRect, &targetRect); + } + else + TiToRect(tile, &targetRect); + + DBNMPaintPlane(plane, TiGetTypeExact(tile), &targetRect, CIFPaintTable, + (PaintUndoInfo *)NULL); + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFPaintCurrent -- + * + * This procedure does geometrical processing on the current + * set of CIF planes, and paints the results into the current + * CIF cell. + * + * Results: + * Return 0 + * + * Side effects: + * Lots of information gets added to the current Magic cell. + * + * ---------------------------------------------------------------------------- + */ + +int +CIFPaintCurrent() +{ + Plane *plane, *swapplane; + int i; + + for (i = 0; i < cifCurReadStyle->crs_nLayers; i++) + { + TileType type; + extern int cifPaintCurrentFunc(); /* Forward declaration. */ + CIFOp *op; + + plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops, + &TiPlaneRect, (CellDef *) NULL, cifCurReadPlanes); + + /* Generate a paint/erase table, then paint from the CIF + * plane into the current Magic cell. + */ + type = cifCurReadStyle->crs_layers[i]->crl_magicType; + + if (cifCurReadStyle->crs_layers[i]->crl_flags & CIFR_TEMPLAYER) + { + op = cifCurReadStyle->crs_layers[i]->crl_ops; + while (op) + { + if (op->co_opcode == CIFOP_COPYUP) break; + op = op->co_next; + } + + /* Quick check to see if anything was generated */ + /* on this layer. */ + + if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, + &DBAllButSpaceBits, cifCheckPaintFunc, + (ClientData)NULL) == 1)) + { + /* Copy-up function */ + + int pNum; + Plane *newplane; + Plane **parray; + extern char *(cifReadLayers[MAXCIFRLAYERS]); + + if (cifReadCellDef->cd_flags & CDFLATGDS) + parray = (Plane **)cifReadCellDef->cd_client; + else + { + parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *)); + cifReadCellDef->cd_flags |= CDFLATGDS; + cifReadCellDef->cd_flags &= ~CDFLATTENED; + cifReadCellDef->cd_client = (ClientData)parray; + for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + parray[pNum] = NULL; + } + + for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + { + if (TTMaskHasType(&op->co_cifMask, pNum)) + { + CIFCopyRec cifCopyRec; + + newplane = DBNewPlane((ClientData) TT_SPACE); + DBClearPaintPlane(newplane); + + cifCopyRec.plane = newplane; + cifCopyRec.trans = NULL; + + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, + &DBAllButSpaceBits, cifCopyPaintFunc, + &cifCopyRec); + + parray[pNum] = newplane; + } + } + } + + /* Swap planes */ + swapplane = cifCurReadPlanes[type]; + cifCurReadPlanes[type] = plane; + plane = swapplane; + } + else + { + DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect, + &CIFSolidBits, cifPaintCurrentFunc, + (ClientData)type); + } + + /* Recycle the plane, which was dynamically allocated. */ + + DBFreePaintPlane(plane); + TiFreePlane(plane); + } + + /* Now go through all the current planes and zero them out. */ + + for (i = 0; i < MAXCIFRLAYERS; i++) + DBClearPaintPlane(cifCurReadPlanes[i]); + + return 0; +} + +/* Below is the search function invoked for each CIF tile type + * found for the current layer. + */ + +int +cifPaintCurrentFunc(tile, type) + Tile *tile; /* Tile of CIF information. */ + TileType type; /* Magic type to be painted. */ +{ + Rect area; + int pNum; + int savescale; + bool snap_type = COORD_EXACT; + + /* Contact types are allowed to be on half-lambda spacing, and are */ + /* snapped to the nearest magic coordinate if the result is a */ + /* fractional magic coordinate. */ + + if (DBIsContact(type)) snap_type = COORD_HALF_U; + + /* Compute the area of the CIF tile, then scale it into + * Magic coordinates. + */ + + TiToRect(tile, &area); + area.r_xtop = CIFScaleCoord(area.r_xtop, snap_type); + savescale = cifCurReadStyle->crs_scaleFactor; + area.r_ytop = CIFScaleCoord(area.r_ytop, snap_type); + if (snap_type == COORD_HALF_U) snap_type = COORD_HALF_L; + if (savescale != cifCurReadStyle->crs_scaleFactor) + { + area.r_xtop *= (savescale / cifCurReadStyle->crs_scaleFactor); + savescale = cifCurReadStyle->crs_scaleFactor; + } + area.r_xbot = CIFScaleCoord(area.r_xbot, snap_type); + if (savescale != cifCurReadStyle->crs_scaleFactor) + { + area.r_xtop *= (savescale / cifCurReadStyle->crs_scaleFactor); + area.r_ytop *= (savescale / cifCurReadStyle->crs_scaleFactor); + savescale = cifCurReadStyle->crs_scaleFactor; + } + area.r_ybot = CIFScaleCoord(area.r_ybot, snap_type); + if (savescale != cifCurReadStyle->crs_scaleFactor) + { + area.r_xtop *= (savescale / cifCurReadStyle->crs_scaleFactor); + area.r_ytop *= (savescale / cifCurReadStyle->crs_scaleFactor); + area.r_xbot *= (savescale / cifCurReadStyle->crs_scaleFactor); + } + + /* Check for degenerate areas (from rescale limiting) before painting */ + if ((area.r_xbot == area.r_xtop) || (area.r_ybot == area.r_ytop)) + return 0; + + for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) + if (DBPaintOnPlane(type, pNum)) + { + DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile), + &area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL); + } + + return 0; /* To keep the search alive. */ +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseFinish -- + * + * This procedure is called at the end of a cell definition. + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * Process the CIF planes and paint the results into the Magic + * cell. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseFinish() +{ + if (!cifSubcellBeingRead) + { + CIFReadError("definition finish without definition start; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + if (cifSubcellId != NULL) + { + CIFReadError("pending call identifier %s discarded.\n", cifSubcellId); + (void) StrDup(&cifSubcellId, (char *) NULL); + } + + /* Take the `F'. */ + + TAKE(); + + /* Do the geometrical processing and paint this material back into + * the appropriate cell of the database. Then restore the saved + * layer info. + */ + + CIFPaintCurrent(); + + DBAdjustLabels(cifReadCellDef, &TiPlaneRect); + DBReComputeBbox(cifReadCellDef); + cifReadCellDef = EditCellUse->cu_def; + cifReadPlane = cifOldReadPlane; + cifReadScale1 = 1; + cifReadScale2 = 1; + cifSubcellBeingRead = FALSE; + cifCurReadPlanes = cifEditCellPlanes; + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseDelete -- + * + * This procedure is called to handle delete-symbol statements. + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * The mapping between numbers and cells is modified to eliminate + * some symbols. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseDelete() +{ + int number; + + /* Take the `D'. */ + + TAKE(); + if (!CIFParseInteger(&number)) + { + CIFReadError("definition delete, but no symbol number; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + + /* Unlink the hash entry from its target definition */ + cifForgetCell(number); + + CIFSkipToSemi(); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifParseName -- + * + * Parse a name, which is a string of alphabetics, numerics, + * or underscores, possibly preceded by whitespace. + * + * Results: + * The return value is a pointer to the name read from the + * CIF file. This is a statically-allocated area, so the + * caller should copy out of this area before invoking this + * procedure again. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +char * +cifParseName() +{ + char ch; + char *bufferp; + static char buffer[128]; + + /* Skip white space. */ + + for (ch = PEEK() ; ch == ' ' || ch == '\t' ; ch = PEEK()) + TAKE(); + + /* Read the string. */ + + bufferp = &buffer[0]; + for (ch = PEEK() ; (! isspace(ch)) && ch != ';' ; ch = PEEK()) + { + *bufferp++ = TAKE(); + } + *bufferp = '\0'; + return buffer; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifParseUser9 -- + * + * This procedure processes user extension 9: the name of the + * current symbol (cell) definition. + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * The current CIF symbol is renamed from its default "cifxx" name + * to the given name. + * + * ---------------------------------------------------------------------------- + */ + +bool +cifParseUser9() +{ + char *name; + + name = cifParseName(); + if (!DBCellRenameDef(cifReadCellDef, name)) + { + CIFReadError("%s already exists, so cell from CIF is named %s.\n", + name, cifReadCellDef->cd_name); + } + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseCall -- + * + * This procedure processes subcell uses. The syntax of a call is + * call ::= C integer transform + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * A subcell is added to the current Magic cell we're generating. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseCall() +{ + int called; + Transform transform; + CellUse *use; + CellDef *def; + + /* Take the `C'. */ + + TAKE(); + if (!CIFParseInteger(&called)) + { + CIFReadError("call, but no symbol number; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + + /* Get optional transformation. */ + + (void) CIFParseTransform(&transform); + + def = cifFindCell(called); + + /* avoid recursion + */ + + if (DBIsAncestor(def, cifReadCellDef)) + { + CIFReadError("attempt to place cell use inside its own definition!\n"); + CIFSkipToSemi(); + return FALSE; + } + + /* Find the use and add it to the current cell. Give it an + * id also. + */ + + use = DBCellNewUse(def, cifSubcellId); + (void) DBLinkCell(use, cifReadCellDef); + DBSetTrans(use, &transform); + DBPlaceCell(use, cifReadCellDef); + + (void) StrDup(&cifSubcellId, (char *) NULL); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifParseUser91 -- + * + * This procedure handles 91 user commands, which provide id's + * for following cell calls. The syntax is: + * 91 ::= 91 blanks name + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * The identifier is saved until the call is read. Then it is + * used as the identifier for the cell. + * + * ---------------------------------------------------------------------------- + */ + +bool +cifParseUser91() +{ + if (cifSubcellId != NULL) + { + CIFReadError("91 command with identifier %s pending; %s discarded.\n" , + cifSubcellId , cifSubcellId); + } + (void) StrDup(&cifSubcellId, cifParseName()); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifParseUser94 -- + * + * This procedure parses 94 user commands, which are labelled + * points. The syntax is: + * 94 ::= 94 blanks name point + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * A label is added to the current cell. + * + * ---------------------------------------------------------------------------- + */ + +bool +cifParseUser94() +{ + Rect rectangle; + char *name = NULL; + TileType type; + int layer, flags, i; + int savescale; + + (void) StrDup(&name, cifParseName()); + if (! CIFParsePoint(&rectangle.r_ll, 1)) + { + CIFReadError("94 command, but no location; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + + /* Scale the coordinates, then make the location into a + * rectangle. + */ + + rectangle.r_xbot = CIFScaleCoord(rectangle.r_xbot, COORD_ANY); + savescale = cifCurReadStyle->crs_scaleFactor; + rectangle.r_ybot = CIFScaleCoord(rectangle.r_ybot, COORD_ANY); + if (savescale != cifCurReadStyle->crs_scaleFactor) + rectangle.r_xbot *= (savescale / cifCurReadStyle->crs_scaleFactor); + + rectangle.r_ur = rectangle.r_ll; + + /* Get a layer, lookup the layer, then add the label to the + * current cell. Tricky business: in order for the default + * label location to be computed + */ + + CIFSkipBlanks(); + if (PEEK() != ';') + { + char *lname = cifParseName(); + layer = CIFReadNameToType(lname, FALSE); + if (layer < 0) + { + CIFReadError("label attached to unknown layer %s.\n", + lname); + type = TT_SPACE; + } + else { + type = cifCurReadStyle->crs_labelLayer[layer]; + } + } else { + type = cifCurLabelType; + + /* Should do this better, by defining cifCurLabelFlags. . . */ + layer = -1; + for (i = 0; i < cifCurReadStyle->crs_nLayers; i++) + if (cifCurReadStyle->crs_labelLayer[i] == type) { + layer = i; + break; + } + } + if (type >=0 ) + { + if (layer >= 0 && (cifCurReadStyle->crs_layers[layer]->crl_flags + & CIFR_TEXTLABELS)) + flags = LABEL_STICKY; + else + flags = 0; + (void) DBPutLabel(cifReadCellDef, &rectangle, -1, name, type, flags); + } + freeMagic(name); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifParseUser95 -- + * + * This procedure parses 95 user commands, which are labelled + * points. The syntax is: + * 95 ::= 95 blanks name length width point + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * An area label is added to the current cell. + * + * ---------------------------------------------------------------------------- + */ + +bool +cifParseUser95() +{ + Rect rectangle; + Point size, center; + char *name = NULL; + TileType type; + int layer, i; + int savescale; + + (void) StrDup(&name, cifParseName()); + if (! CIFParsePoint(&size, 1)) + { + CIFReadError("95 command, but no size; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + if (! CIFParsePoint(¢er, 1)) + { + CIFReadError("95 command, but no location; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + + /* Scale the coordinates and create the rectangular area. */ + /* Remap center and size to lowerleft and upperright, respectively, */ + /* so that half-lambda centers are resolved before remapping to */ + /* magic coordinates. */ + + center.p_x = CIFScaleCoord(center.p_x - size.p_x/2, COORD_ANY); + savescale = cifCurReadStyle->crs_scaleFactor; + center.p_y = CIFScaleCoord(center.p_y - size.p_y/2, COORD_ANY); + if (savescale != cifCurReadStyle->crs_scaleFactor) + { + center.p_x *= (savescale / cifCurReadStyle->crs_scaleFactor); + savescale = cifCurReadStyle->crs_scaleFactor; + } + size.p_x = CIFScaleCoord(center.p_x + (size.p_x - size.p_x/2), COORD_ANY); + if (savescale != cifCurReadStyle->crs_scaleFactor) + { + center.p_x *= (savescale / cifCurReadStyle->crs_scaleFactor); + center.p_y *= (savescale / cifCurReadStyle->crs_scaleFactor); + savescale = cifCurReadStyle->crs_scaleFactor; + } + size.p_y = CIFScaleCoord(center.p_y + (size.p_y - size.p_y/2), COORD_ANY); + if (savescale != cifCurReadStyle->crs_scaleFactor) + { + center.p_x *= (savescale / cifCurReadStyle->crs_scaleFactor); + center.p_y *= (savescale / cifCurReadStyle->crs_scaleFactor); + size.p_x *= (savescale / cifCurReadStyle->crs_scaleFactor); + } + rectangle.r_xbot = center.p_x; + rectangle.r_ybot = center.p_y; + rectangle.r_xtop = size.p_x; + rectangle.r_ytop = size.p_y; + + /* Get a layer, lookup the layer, then add the label to the + * current cell. Tricky business: in order for the default + * label location to be computed + */ + CIFSkipBlanks(); + if (PEEK() != ';') + { + char *name = cifParseName(); + layer = CIFReadNameToType(name, FALSE); + if (layer < 0) + { + CIFReadError("label attached to unknown layer %s.\n", + name); + type = TT_SPACE; + } + else type = cifCurReadStyle->crs_labelLayer[layer]; + } + else { + type = TT_SPACE; + layer = -1; + for (i = 0; i < cifCurReadStyle->crs_nLayers; i++) + if (cifCurReadStyle->crs_labelLayer[i] == type) { + layer = i; + break; + } + } + if (type >=0 ) + { + int flags; + if (layer >= 0 && (cifCurReadStyle->crs_layers[layer]->crl_flags + & CIFR_TEXTLABELS)) + flags = LABEL_STICKY; + else + flags = 0; + (void) DBPutLabel(cifReadCellDef, &rectangle, -1, name, type, flags); + } + + freeMagic(name); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseUser -- + * + * This procedure is called to process user-defined statements. + * The syntax is user ::= digit usertext. + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * Depends on the user command. + * + * ---------------------------------------------------------------------------- + */ +bool +CIFParseUser() +{ + char ch; + + ch = TAKE(); + switch (ch) + { + case '9': + ch = PEEK(); + switch (ch) + { + case '1': + (void) TAKE(); + return cifParseUser91(); + case '4': + (void) TAKE(); + return cifParseUser94(); + case '5': + (void) TAKE(); + return cifParseUser95(); + default: + if (isspace(ch)) return cifParseUser9(); + } + default: + CIFReadError("unimplemented user extension; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFReadCellCleanup -- + * + * This procedure is called after processing the CIF file. + * It performs various cleanup functions on the cells that + * have been read in. + * + * Results: + * None. + * + * Side effects: + * The area of each cell is DRC'ed and redisplayed. Error + * messages are output for any cells whose contents weren't + * in the CIF file. An error message is also output if + * we're still in the middle of reading a subcell. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFReadCellCleanup(type) + int type; // 0 = CIF, 1 = GDS, because routine is used by both +{ + HashEntry *h; + HashSearch hs; + CellDef *def; + MagWindow *window; + int flags; + + if (cifSubcellBeingRead) + { + if (type == 0) + CIFReadError("CIF ended partway through a symbol definition.\n"); + else + calmaReadError("GDS ended partway through a symbol definition.\n"); + (void) CIFParseFinish(); + } + + HashStartSearch(&hs); + while (TRUE) + { + h = HashNext(&CifCellTable, &hs); + if (h == NULL) break; + + def = (CellDef *) HashGetValue(h); + if (def == NULL) + { + if (type == 0) + CIFReadError("cell table has NULL entry (Magic error).\n"); + else + calmaReadError("cell table has NULL entry (Magic error).\n"); + continue; + } + flags = def->cd_flags; + if (!(flags & CDAVAILABLE)) + { + if (type == 0) + CIFReadError("cell %s was used but not defined.\n", def->cd_name); + else + calmaReadError("cell %s was used but not defined.\n", def->cd_name); + } + def->cd_flags &= ~CDPROCESSEDGDS; + + if ((type == 0 && CIFNoDRCCheck == FALSE) || + (type == 1 && CalmaNoDRCCheck == FALSE)) + DRCCheckThis(def, TT_CHECKPAINT, &def->cd_bbox); + DBWAreaChanged(def, &def->cd_bbox, DBW_ALLWINDOWS, &DBAllButSpaceBits); + DBCellSetModified(def, TRUE); + } + + /* Do geometrical processing on the top-level cell. */ + + CIFPaintCurrent(); + DBAdjustLabels(EditCellUse->cu_def, &TiPlaneRect); + DBReComputeBbox(EditCellUse->cu_def); + DBWAreaChanged(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox, + DBW_ALLWINDOWS, &DBAllButSpaceBits); + DBCellSetModified(EditCellUse->cu_def, TRUE); + + /* Clean up saved CIF/GDS planes in cd_client records of cells */ + + HashStartSearch(&hs); + while (TRUE) + { + h = HashNext(&CifCellTable, &hs); + if (h == NULL) break; + + def = (CellDef *) HashGetValue(h); + if (def == NULL) continue; + + if (def->cd_flags & CDFLATGDS) + { + /* These cells have been flattened and are no longer needed. */ + + int pNum; + Plane **cifplanes = (Plane **)def->cd_client; + + UndoDisable(); + + for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + { + if (cifplanes[pNum] != NULL) + { + DBFreePaintPlane(cifplanes[pNum]); + TiFreePlane(cifplanes[pNum]); + } + } + freeMagic((char *)def->cd_client); + def->cd_client = (ClientData)CLIENTDEFAULT; + + /* If the CDFLATTENED flag was not set, then this geometry */ + /* was never instantiated, and should generate a warning. */ + + if (!(def->cd_flags & CDFLATTENED)) + CIFReadError("%s read error: Unresolved geometry in cell" + " %s maps to no magic layers\n", + (type == 0) ? "CIF" : "GDS", def->cd_name); + +#if 0 + /* Remove the cell if it has no parents, no children, and no geometry */ + /* To-do: Check that these conditions are valid */ + + if (def->cd_parents == (CellUse *)NULL) + { + char *savename = StrDup((char **)NULL, def->cd_name); + + if (DBCellDeleteDef(def) == FALSE) + { + CIFReadError("%s read error: Unable to delete cell %s\n", + (type == 0) ? "CIF" : "GDS", savename); + } + else + { + if (type == 0) + TxPrintf("CIF read: Removed flattened cell %s\n", savename); + else + TxPrintf("GDS read: Removed flattened cell %s\n", savename); + } + freeMagic(savename); + } +#endif + UndoEnable(); + } + } + HashKill(&CifCellTable); +} diff --git a/cif/CIFrdpoly.c b/cif/CIFrdpoly.c new file mode 100644 index 00000000..109fdaeb --- /dev/null +++ b/cif/CIFrdpoly.c @@ -0,0 +1,335 @@ +/* CIFreadpoly.c - + * + * This file contains procedures that turn polygons into + * rectangles, as part of CIF file reading. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdpoly.c,v 1.3 2010/06/24 12:37:15 tim Exp $"; +#endif /* not lint */ + +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "cif/CIFint.h" +#include "cif/CIFread.h" +#include "utils/malloc.h" + +#define HEDGE 0 /* Horizontal edge */ +#define REDGE 1 /* Rising edge */ +#define FEDGE -1 /* Falling edge */ + +/* + * ---------------------------------------------------------------------------- + * + * cifLowX -- + * + * This is a comparison procedure called by qsort. + * + * Results: + * 1 if a.x > b.x, + * -1 if a.x < b.x, + * 0 otherwise. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +cifLowX(a, b) + CIFPath **a, **b; +{ + Point *p, *q; + + p = &(*a)->cifp_point; + q = &(*b)->cifp_point; + if (p->p_x < q->p_x) + return (-1); + if (p->p_x > q->p_x) + return (1); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifLowY -- + * + * This is another comparison procedure called by qsort. + * + * Results: + * 1 if a.y > b.y + * -1 if a.y < b.y + * 0 otherwise + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +cifLowY(a, b) + Point **a, **b; +{ + if ((*a)->p_y < (*b)->p_y) + return (-1); + if ((*a)->p_y > (*b)->p_y) + return (1); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifOrient -- + * + * This procedure assigns a direction to each of the edges in a + * polygon. + * + * Results: + * TRUE is returned if all of the edges are horizontal or vertical, + * FALSE is returned otherwise. If FALSE is returned, not all of + * the directions will have been filled in. + * + * Side effects: + * The parameter dir is filled in with the directions, which are + * each one of HEDGE, REDGE, or FEDGE. + * + * ---------------------------------------------------------------------------- + */ + +bool +cifOrient(edges, nedges, dir) + CIFPath *edges[]; /* Array of edges to be categorized. */ + int dir[]; /* Array to hold directions. */ + int nedges; /* Size of arrays. */ +{ + Point *p, *q; + int n; + + for (n = 0; n < nedges; n++) + { + /* note - path list should close on itself */ + p = &edges[n]->cifp_point; + q = &edges[n]->cifp_next->cifp_point; + if (p->p_y == q->p_y) + { + /* note - point may connect to itself here */ + dir[n] = HEDGE; + continue; + } + if (p->p_x == q->p_x) + { + if (p->p_y < q->p_y) + { + dir[n] = REDGE; + continue; + } + if (p->p_y > q->p_y) + { + dir[n] = FEDGE; + continue; + } + /* Point connects to itself */ + dir[n] = HEDGE; + continue; + } + /* It's not Manhattan, folks. */ + return (FALSE); + } + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifCross -- + * + * This procedure is used to see if an edge crosses a particular + * area. + * + * Results: + * TRUE is returned if edge is vertical and if it crosses the + * y-range defined by ybot and ytop. FALSE is returned otherwise. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +cifCross(edge, dir, ybot, ytop) + CIFPath *edge; /* Pointer to first of 2 path points in edge */ + int dir; /* Direction of edge */ + int ybot, ytop; /* Range of interest */ +{ + int ebot, etop; + + switch (dir) + { + case REDGE: + ebot = edge->cifp_point.p_y; + etop = edge->cifp_next->cifp_point.p_y; + return (ebot <= ybot && etop >= ytop); + + case FEDGE: + ebot = edge->cifp_next->cifp_point.p_y; + etop = edge->cifp_point.p_y; + return (ebot <= ybot && etop >= ytop); + + } + + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFPolyToRects -- + * + * Converts a manhattan polygon (specified as a path) into a + * linked list of rectangles. + * + * Results: + * The return value is a linked list of rectangles, or NULL if + * something went wrong. + * + * Side effects: + * Memory is allocated to hold the list of rectangles. It is + * the caller's responsibility to free up the memory. + * + * ---------------------------------------------------------------------------- + */ + +LinkedRect * +CIFPolyToRects(path, plane, resultTbl, ui) + CIFPath *path; /* Path describing a polygon. */ + Plane *plane; /* Plane to draw on */ + PaintResultType *resultTbl; + PaintUndoInfo *ui; +{ + int npts = 0, n, *dir, curr, wrapno; + int xbot, xtop, ybot, ytop; + Point **pts; + CIFPath *p, **edges, *tail = 0; + LinkedRect *rex = 0, *new; + + /* Close path list. */ + + for (tail = path; tail->cifp_next; tail = tail->cifp_next); + + if ((tail->cifp_x != path->cifp_x) || (tail->cifp_y != path->cifp_y)) + { + p = (CIFPath *) mallocMagic ((unsigned) sizeof (CIFPath)); + p->cifp_x = path->cifp_x; + p->cifp_y = path->cifp_y; + p->cifp_next = (CIFPath *) 0; + tail->cifp_next = p; + } + + CIFMakeManhattanPath(path, plane, resultTbl, ui); + + for (p = path; p->cifp_next; p = p->cifp_next, npts++); + pts = (Point **)mallocMagic(npts * sizeof(Point *)); + dir = (int *)mallocMagic(npts * sizeof(int)); + edges = (CIFPath **)mallocMagic(npts * sizeof(CIFPath *)); + npts = 0; + + for (p = path; p->cifp_next; p = p->cifp_next, npts++) + { + pts[npts] = &(p->cifp_point); + edges[npts] = p; + } + + if (npts < 4) + { + if (npts > 0) + CIFReadError("polygon with fewer than 4 points.\n" ); + goto done; + } + + /* Sort points by low y, edges by low x */ + + qsort ((char *) pts, npts, (int) sizeof (Point *), cifLowY); + qsort ((char *) edges, npts, (int) sizeof (CIFPath *), cifLowX); + + /* Find out which direction each edge points. */ + + if (!cifOrient (edges, npts, dir)) + { + CIFReadError("non-manhattan polygon.\n" ); + goto done; + } + + /* Scan the polygon from bottom to top. At each step, process + * a minimum-sized y-range of the polygon (i.e. a range such that + * there are no vertices inside the range). Use wrap numbers + * based on the edge orientations to determine how much of the + * x-range for this y-range should contain material. + */ + + for (curr = 1; curr < npts; curr++) + { + /* Find the next minimum-sized y-range. */ + + ybot = pts[curr-1]->p_y; + while (ybot == pts[curr]->p_y) + if (++curr >= npts) goto done; + ytop = pts[curr]->p_y; + + /* Process all the edges that cross the y-range, from left + * to right. + */ + + for (wrapno=0, n=0; n < npts; n++) + { + if (wrapno == 0) xbot = edges[n]->cifp_x; + if (!cifCross(edges[n], dir[n], ybot, ytop)) + continue; + wrapno += dir[n] == REDGE ? 1 : -1; + if (wrapno == 0) + { + xtop = edges[n]->cifp_point.p_x; + if (xbot == xtop) continue; + new = (LinkedRect *) mallocMagic(sizeof(LinkedRect)); + new->r_r.r_xbot = xbot; + new->r_r.r_ybot = ybot; + new->r_r.r_xtop = xtop; + new->r_r.r_ytop = ytop; + new->r_next = rex; + rex = new; + } + } + } + + /* Normally, the loop exits directly to done, below. It + * only falls through here if the polygon has a degenerate + * spike at its top (i.e. if there's only one point with + * highest y-coordinate). + */ + +done: + freeMagic((char *)edges); + freeMagic((char *)dir); + freeMagic((char *)pts); + return (rex); +} diff --git a/cif/CIFrdpt.c b/cif/CIFrdpt.c new file mode 100644 index 00000000..e9781faa --- /dev/null +++ b/cif/CIFrdpt.c @@ -0,0 +1,765 @@ +/* CIFreadpaint.c - + * + * This file contains more routines to parse CIF files. In + * particular, it contains the routines to handle paint, + * including rectangles, wires, flashes, and polygons. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdpt.c,v 1.2 2010/06/24 12:37:15 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include /* for wire path-to-poly path conversion */ + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "database/database.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "cif/CIFint.h" +#include "cif/CIFread.h" + + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseBox -- + * + * This procedure parses a CIF box command. + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * A box is added to the CIF information for this cell. The + * box better not have corners that fall on half-unit boundaries. + * + * Correction: + * A box may be centered on a half lambda grid but have width + * and height such that the resulting box is entirely on the lambda + * grid. So: don't divide by 2 until the last step! + * ---Tim Edwards, 4/20/00 + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseBox() +{ + Point center; + Point direction; + Rect rectangle, r2; + int savescale; + + /* Take the 'B'. */ + + TAKE(); + if (cifReadPlane == NULL) + { + CIFSkipToSemi(); + return FALSE; + } + + /* Treat length and width as a point so we can make use of the code in */ + /* CIFParsePoint(); however, before moving on, check that both values */ + /* are strictly positive. */ + + if (!CIFParsePoint(&rectangle.r_ur, 1)) + { + CIFReadError("box, but no length and/or width; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + if (rectangle.r_xtop <= 0) + { + CIFReadError("box length not strictly positive; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + if (rectangle.r_ytop <= 0) + { + CIFReadError("box width not strictly positive; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + + savescale = cifReadScale1; + + if (!CIFParsePoint(¢er, 2)) + { + CIFReadError("box, but no center; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + + /* If reading the center causes a CIF input scale to be redefined, */ + /* then the length and width must also be changed. */ + + if (savescale != cifReadScale1) + { + rectangle.r_xtop *= (cifReadScale1 / savescale); + rectangle.r_ytop *= (cifReadScale1 / savescale); + } + + rectangle.r_xbot = -rectangle.r_xtop; + rectangle.r_ybot = -rectangle.r_ytop; + + /* Optional direction vector: have to build transform to do rotate. */ + + if (CIFParseSInteger(&direction.p_x)) + { + if (!CIFParseSInteger(&direction.p_y)) + { + CIFReadError("box, direction botched; box ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + GeoTransRect(CIFDirectionToTrans(&direction), &rectangle , &r2); + } + else r2 = rectangle; + + /* Offset by center only now that rotation is complete, and divide by two. */ + + r2.r_xbot = (r2.r_xbot + center.p_x) / 2; + r2.r_ybot = (r2.r_ybot + center.p_y) / 2; + r2.r_xtop = (r2.r_xtop + center.p_x) / 2; + r2.r_ytop = (r2.r_ytop + center.p_y) / 2; + + DBPaintPlane(cifReadPlane, &r2, CIFPaintTable, (PaintUndoInfo *) NULL); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseFlash -- + * + * This routine parses and processes a roundflash command. The syntax is: + * roundflash ::= R diameter center + * + * We approximate a roundflash by a box. + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * Paint is added to the current CIF plane. + * + * Corrections: Incorrectly implemented. Now CIFParsePoint returns the + * center coordinate doubled; in this way, the center can be on the + * half-lambda grid but the resulting block on-grid, if the diameter + * is an odd number. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseFlash() +{ + int diameter; + int savescale; + Point center; + Rect rectangle; + + /* Take the 'R'. */ + + TAKE(); + if (cifReadPlane == NULL) + { + CIFSkipToSemi(); + return FALSE; + } + if (!CIFParseInteger(&diameter)) + { + CIFReadError("roundflash, but no diameter; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + diameter *= cifReadScale1; + if (diameter % cifReadScale2 != 0) + CIFReadWarning("Roundflash diameter snapped to nearest integer boundary.\n"); + + diameter /= cifReadScale2; + savescale = cifReadScale1; + if (!CIFParsePoint(¢er, 2)) + { + CIFReadError("roundflash, but no center; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + if (savescale != cifReadScale1) + diameter *= (cifReadScale1 / savescale); + + rectangle.r_xbot = (center.p_x - diameter) / 2; + rectangle.r_ybot = (center.p_y - diameter) / 2; + rectangle.r_xtop = (center.p_x + diameter) / 2; + rectangle.r_ytop = (center.p_y + diameter) / 2; + DBPaintPlane(cifReadPlane, &rectangle, CIFPaintTable, + (PaintUndoInfo *) NULL); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFPaintWirePath -- + * + * Draw a "wire path" described by the endpoints of a centerline through + * a series of segments, and a wire width. We pass the plane and paint + * table information so this routine can be used by the database for + * painting paths from the command-line. + * + * Results: + * None. + * + * Side effects: + * Paints layout into magic. The original wire path is destroyed + * (memory free'd). + * + * Notes: + * Path coordinates for wires are always assumed to be twice the + * actual value to avoid roundoff errors, since the centerline of + * a path can be halfway between two coordinates of the layout grid + * and still describe a polygon whose endpoints are all on the grid. + * + * Warning: + * It is still possible to get roundoff problems with different + * values of segment width at different angles caused by snapping + * to grid points. While this is "as it should be", it causes + * problems when process design rules demand geometry at 45 degrees + * only, and the algorithm produces points that are 1 unit off. + * A possible solution is to adjust "cwidth" to match the average + * value of "width" after snapping at entering and exiting angles. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFPaintWirePath(pathheadp, width, endcap, plane, ptable, ui) + CIFPath *pathheadp; + int width; + bool endcap; + Plane *plane; + PaintResultType *ptable; + PaintUndoInfo *ui; +{ + CIFPath *pathp, *previousp, *nextp, *polypath; + CIFPath *returnpath, *newpath, *savepath; + LinkedRect *rectp; + double theta, phi, alpha, delta, cwidth, adjwidth, testmitre, savetheta; + double xmaxoff, ymaxoff, xminoff, yminoff; + double xmin, ymin, xmax, ymax, xnext, ynext; + bool firstpoint; + + /* Get rid of any repeat points, which just screw up the algorithm */ + + previousp = pathheadp; + pathp = pathheadp->cifp_next; + if (pathp != NULL) + { + while (pathp->cifp_next != NULL) + { + if (pathp->cifp_next->cifp_x == pathp->cifp_x && + pathp->cifp_next->cifp_y == pathp->cifp_y) + { + previousp->cifp_next = pathp->cifp_next; + freeMagic(pathp); + } + else + previousp = pathp; + pathp = pathp->cifp_next; + } + } + + previousp = pathheadp; + polypath = NULL; + + /* Single-point paths are okay; just set the endpoints equal */ + if (pathheadp->cifp_next == NULL) + pathp = pathheadp; + else + pathp = pathheadp->cifp_next; + + firstpoint = TRUE; + theta = 0; + while (pathp != NULL) + { + /* Advance to the next point */ + xmin = (double)previousp->cifp_x; + xmax = (double)pathp->cifp_x; + ymin = (double)previousp->cifp_y; + ymax = (double)pathp->cifp_y; + + /* Angle of this segment */ + savetheta = theta; + theta = atan2(ymax - ymin, xmax - xmin); + + /* Look ahead to the next point */ + if (firstpoint) + { + /* Back first point up by endcap amount (width, */ + /* which is half the width of the route segment.) */ + + if (endcap) + { + xmin -= (double)width * cos(theta); + ymin -= (double)width * sin(theta); + } + xminoff = (double)width * cos(theta - 1.5708); /* 90 degrees */ + yminoff = (double)width * sin(theta - 1.5708); + firstpoint = FALSE; + + newpath = (CIFPath *)mallocMagic(sizeof(CIFPath)); + newpath->cifp_next = polypath; + polypath = newpath; + returnpath = polypath; /* returnpath is always at the end */ + newpath->cifp_x = round((xmin + xminoff) / 2); + newpath->cifp_y = round((ymin + yminoff) / 2); + + newpath = (CIFPath *)mallocMagic(sizeof(CIFPath)); + newpath->cifp_next = polypath; + polypath = newpath; + newpath->cifp_x = round((xmin - xminoff) / 2); + newpath->cifp_y = round((ymin - yminoff) / 2); + } + + nextp = pathp->cifp_next; + if (nextp != NULL) + { + xnext = (double)nextp->cifp_x; + ynext = (double)nextp->cifp_y; + phi = atan2(ynext - ymax, xnext - xmax); + } + else + { + /* Endpoint: create 1/2 width endcap */ + phi = theta; + if (endcap) + { + xmax += (double)width * cos(theta); + ymax += (double)width * sin(theta); + } + } + + alpha = 0.5 * (phi - theta); + testmitre = fabs(cos(alpha)); + + /* This routine does not (yet) do mitre limits, so for */ + /* now, we do a sanity check. In the case of an */ + /* extremely acute angle, we generate a warning and */ + /* truncate the route. The mitre limit is arbitrarily */ + /* set at 4 times the route width. Such extreme bends */ + /* are usually DRC violations, anyway. Tighter bends */ + /* than this tend to cause difficulties for the */ + /* CIFMakeManhattanPath() routine. */ + + if (testmitre < 0.25) { + if (testmitre < 1.0e-10) { + /* Wire reverses direction. Break wire here, */ + /* draw, and start new polygon. */ + + TxError("Warning: direction reversal in path.\n"); + + phi = theta; + if (endcap) + { + xmax += (double)width * cos(theta); + ymax += (double)width * sin(theta); + } + alpha = 0.5 * (phi - theta); + firstpoint = TRUE; + } + else { + TxError("Error: mitre limit exceeded at wire junction.\n"); + TxError("Route has been truncated.\n"); + break; + } + } + + delta = (0.5 * (phi + theta)) - 1.5708; + cwidth = (double)width / cos(alpha); + xmaxoff = cwidth * cos(delta); + ymaxoff = cwidth * sin(delta); + + newpath = (CIFPath *)mallocMagic(sizeof(CIFPath)); + newpath->cifp_next = polypath; + polypath = newpath; + newpath->cifp_x = round((xmax - xmaxoff) / 2); + newpath->cifp_y = round((ymax - ymaxoff) / 2); + + newpath = (CIFPath *)mallocMagic(sizeof(CIFPath)); + newpath->cifp_next = NULL; + savepath = returnpath; + returnpath->cifp_next = newpath; + returnpath = newpath; + newpath->cifp_x = round((xmax + xmaxoff) / 2); + newpath->cifp_y = round((ymax + ymaxoff) / 2); + + if (firstpoint == TRUE || nextp == NULL) + { + /* Slow draw for non-Manhattan paths: */ + /* Break the area up into triangles and rectangles */ + + rectp = CIFPolyToRects(polypath, plane, ptable, ui); + CIFFreePath(polypath); + + for (; rectp != NULL ; rectp = rectp->r_next) + { + DBPaintPlane(plane, &rectp->r_r, ptable, ui); + freeMagic((char *) rectp); + } + polypath = NULL; + } + else + { + Rect r; + double a1, a2, r2, d1; + Point newpt; + + /* Check if either of the two new segments travels opposite */ + /* to theta. If so, then we need to find the intersection */ + /* with the previous point, to avoid creating a cut-out */ + /* wedge in the path. */ + + a1 = fabs(atan2(returnpath->cifp_y - savepath->cifp_y, + returnpath->cifp_x - savepath->cifp_x) - theta); + a2 = fabs(atan2(polypath->cifp_y - polypath->cifp_next->cifp_y, + polypath->cifp_x - polypath->cifp_next->cifp_x) - theta); + if (a1 > 0.1 && a1 < 6.1) + { + /* Find new intersection point */ + d1 = cos(savetheta) * sin(phi) - sin(savetheta) * cos(phi); + if (fabs(d1) > 1.0e-4) + { + r2 = (sin(phi) * (returnpath->cifp_x - savepath->cifp_x) + - cos(phi) * (returnpath->cifp_y - savepath->cifp_y)) / d1; + savepath->cifp_x += round(r2 * cos(savetheta)); + savepath->cifp_y += round(r2 * sin(savetheta)); + } + } + else if (a2 > 0.1 && a2 < 6.1) + { + /* Find new intersection point */ + d1 = cos(savetheta) * sin(phi) - sin(savetheta) * cos(phi); + if (fabs(d1) > 1.0e-4) + { + r2 = (sin(phi) * (polypath->cifp_x - polypath->cifp_next->cifp_x) + - cos(phi) * (polypath->cifp_y - polypath->cifp_next->cifp_y)) + / d1; + polypath->cifp_next->cifp_x += round(r2 * cos(savetheta)); + polypath->cifp_next->cifp_y += round(r2 * sin(savetheta)); + } + } + } + + previousp = pathp; + pathp = pathp->cifp_next; + } + CIFFreePath(pathheadp); +} + +/* + * ---------------------------------------------------------------------------- + * + * PaintPolygon -- + * + * Convert a list of points in the form of an array of type Point to a + * CIFPath linked structure, and paint them into the database. + * + * Results: + * None. + * + * Side effects: + * Paints tiles into the layout database. Calling routine is + * responsible for free'ing memory of the pointlist, if necessary. + * + * Notes: + * This is a database routine, not a CIF routine. However, it makes + * use of the CIFPath structure, so it is included here. + * + * ---------------------------------------------------------------------------- + */ + +LinkedRect * +PaintPolygon(pointlist, number, plane, ptable, ui, keep) + Point *pointlist; /* Array of Point structures */ + int number; /* total number of points */ + Plane *plane; /* Plane structure to paint into */ + PaintResultType *ptable; /* Paint result table */ + PaintUndoInfo *ui; /* Undo record */ + bool keep; /* Return list of rects if true */ +{ + LinkedRect *rectp, *rectlist; + CIFPath *newpath, *cifpath = (CIFPath *)NULL; + int i; + + for (i = 0; i < number; i++) + { + newpath = (CIFPath *) mallocMagic((unsigned) sizeof (CIFPath)); + newpath->cifp_x = pointlist[i].p_x; + newpath->cifp_y = pointlist[i].p_y; + newpath->cifp_next = cifpath; + cifpath = newpath; + } + + rectlist = CIFPolyToRects(cifpath, plane, ptable, ui); + CIFFreePath(cifpath); + + for (rectp = rectlist; rectp != NULL ; rectp = rectp->r_next) + { + DBPaintPlane(plane, &rectp->r_r, ptable, ui); + if (!keep) freeMagic((char *) rectp); + } + return (keep) ? rectlist : (LinkedRect *)NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * PaintWireList -- + * + * Convert a list of points in the form of an array of type Point to a + * CIFPath linked structure, and paint them into the database. + * + * Results: + * None. + * + * Side effects: + * Paints tiles into the layout database. Calling routine is + * responsible for free'ing memory of the pointlist, if necessary. + * + * Notes: + * This is a database routine, not a CIF routine. However, it makes + * use of the CIFPath structure, so it is included here. + * + * ---------------------------------------------------------------------------- + */ + +void +PaintWireList(pointlist, number, width, endcap, plane, ptable, ui) + Point *pointlist; /* Array of Point structures */ + int number; /* total number of points */ + int width; /* Route width of path */ + bool endcap; /* Whether or not to add 1/2 width endcaps */ + Plane *plane; /* Plane structure to paint into */ + PaintResultType *ptable; /* Paint result table */ + PaintUndoInfo *ui; /* Undo record */ +{ + CIFPath *newpath, *cifpath = (CIFPath *)NULL; + int i; + + for (i = 0; i < number; i++) + { + newpath = (CIFPath *) mallocMagic((unsigned) sizeof (CIFPath)); + newpath->cifp_x = pointlist[i].p_x; + newpath->cifp_y = pointlist[i].p_y; + newpath->cifp_next = cifpath; + cifpath = newpath; + } + CIFPaintWirePath(cifpath, width, endcap, plane, ptable, ui); +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseWire -- + * + * This procedure parses CIF wire commands, and adds paint + * to the current CIF cell. A wire command consists of + * an integer width, then a path. + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * The current CIF planes are modified. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseWire() +{ + int width; + CIFPath *pathheadp, *polypath; + int savescale; + + /* Take the 'W'. */ + + TAKE(); + if (cifReadPlane == NULL) + { + CIFSkipToSemi(); + return FALSE; + } + if (!CIFParseInteger(&width)) + { + CIFReadError("wire, but no width; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + width *= cifReadScale1; + if (width % cifReadScale2 != 0) + CIFReadWarning("Wire width snapped to nearest integer boundary.\n"); + + width /= cifReadScale2; + savescale = cifReadScale1; + if (!CIFParsePath(&pathheadp, 2)) + { + CIFReadError("wire, but improper path; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + if (savescale != cifReadScale1) + width *= (cifReadScale1 / savescale); + + CIFPaintWirePath(pathheadp, width, TRUE, cifReadPlane, CIFPaintTable, + (PaintUndoInfo *)NULL); + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseLayer -- + * + * This procedure parses layer changes. The syntax is: + * layer ::= L { blank } processchar layerchars + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * Switches the CIF plane where paint is being saved. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseLayer() +{ +#define MAXCHARS 4 + char name[MAXCHARS+1]; + char c; + int i; + TileType type; + + /* Take the 'L'. */ + + TAKE(); + CIFSkipBlanks(); + + /* Get the layer name. */ + + for (i=0; i<=MAXCHARS; i++) + { + c = PEEK(); + if (isdigit(c) || isupper(c)) + name[i] = TAKE(); + else break; + } + name[i] = '\0'; + + /* Set current plane for use by the routines that parse geometric + * elements. + */ + + type = CIFReadNameToType(name, FALSE); + if (type < 0) + { + cifReadPlane = NULL; + cifCurLabelType = TT_SPACE; + CIFReadError("layer %s isn't known in the current style.\n", + name); + } else { + cifCurLabelType = cifCurReadStyle->crs_labelLayer[type]; + cifReadPlane = cifCurReadPlanes[type]; + } + + CIFSkipToSemi(); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParsePoly -- + * + * This procedure reads and processes a polygon command. The syntax is: + * polygon ::= path + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * Paint is added to the current CIF plane. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParsePoly() +{ + CIFPath *pathheadp; + LinkedRect *rectp; + + /* Take the 'P'. */ + + TAKE(); + if (cifReadPlane == NULL) + { + CIFSkipToSemi(); + return FALSE; + } + if (!CIFParsePath(&pathheadp, 1)) + { + CIFReadError("polygon, but improper path; ignored.\n"); + CIFSkipToSemi(); + return FALSE; + } + + /* Convert the polygon to rectangles. */ + + rectp = CIFPolyToRects(pathheadp, cifReadPlane, CIFPaintTable, + (PaintUndoInfo *)NULL); + CIFFreePath(pathheadp); + if (rectp == NULL) + { + /* The non-Manhattan geometry polygon parsing algorithm */ + /* typically leaves behind degenerate paths, so they */ + /* should not be considered erroneous. */ + CIFSkipToSemi(); + return FALSE; + } + for (; rectp != NULL ; rectp = rectp->r_next) + { + DBPaintPlane(cifReadPlane, &rectp->r_r, CIFPaintTable, + (PaintUndoInfo *) NULL); + freeMagic((char *) rectp); + } + return TRUE; +} diff --git a/cif/CIFrdtech.c b/cif/CIFrdtech.c new file mode 100644 index 00000000..be3f7293 --- /dev/null +++ b/cif/CIFrdtech.c @@ -0,0 +1,1383 @@ +/* CIFreadtech.c - + * + * This module processes the portions of technology files that + * pertain to reading CIF files, and builds the tables used by + * the CIF-reading code. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdtech.c,v 1.4 2010/09/15 15:45:30 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/tech.h" +#include "textio/textio.h" +#include "utils/utils.h" +#include "cif/CIFint.h" +#include "cif/CIFread.h" +#include "calma/calmaInt.h" +#include "utils/malloc.h" + +/* Pointer to a list of all the CIF-reading styles: */ + +CIFReadKeep *cifReadStyleList = NULL; + +/* Names of all the CIF layer types used by any read style: */ + +int cifNReadLayers = 0; +char *(cifReadLayers[MAXCIFRLAYERS]); + +/* Table mapping from Calma layer numbers to CIF layers */ +HashTable cifCalmaToCif; + +/* Variables used to keep track of progress in reading the tech file: */ + +CIFReadStyle *cifCurReadStyle = NULL; /* Current style being read. */ +CIFReadLayer *cifCurReadLayer; /* Current layer being processed. */ +CIFOp *cifCurReadOp; /* Last geometric operation seen. */ + +/* Forward declarations */ +void cifReadStyleInit(); +void CIFReadLoadStyle(); + +/* + * ---------------------------------------------------------------------------- + * + * CIFReadTechLimitScale -- + * + * Determine if the scalefactor (ns / ds), applied to the current + * grid scaling, would result in a grid finer than the minimum + * resolution allowed by the process, as set by the "gridlimit" + * statement in the "cifinput" section. + * + * Note that even if the scalefactor is larger than the minimum + * grid, it must be a MULTIPLE of the minimum grid, or else geometry + * can be generated off-grid. + * + * Results: + * TRUE if scaling by (ns / ds) would violate minimum grid resolution, + * FALSE if not. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFReadTechLimitScale(ns, ds) + int ns, ds; +{ + int gridup, scaledown; + int scale, limit, mult; + + limit = cifCurReadStyle->crs_gridLimit; + if (limit == 0) return FALSE; /* No limit */ + + scale = cifCurReadStyle->crs_scaleFactor; + mult = cifCurReadStyle->crs_multiplier; + + gridup = limit * mult * ds; + scaledown = scale * ns * 10; + + if ((scaledown / gridup) == 0) return TRUE; + if ((scaledown % gridup) != 0) return TRUE; + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFReadNameToType -- + * + * This procedure finds the type (integer index) of a given + * layer name. + * + * Results: + * The return value is the type. If we ran out of space in + * the CIF layer table, or if the layer wasn't recognized and + * it isn't OK to make a new layer, -1 gets returned. + * + * Side effects: + * If no layer exists by the given name and newOK is TRUE, a + * new layer is created. + * + * ---------------------------------------------------------------------------- + */ + +int +CIFReadNameToType(name, newOK) + char *name; /* Name of a CIF layer. */ + bool newOK; /* TRUE means OK to create a new layer if this + * name is one we haven't seen before. + */ +{ + int i; + static bool errorPrinted = FALSE; + + for (i=0; i < cifNReadLayers; i += 1) + { + /* Only accept this layer if it's in the current CIF style or + * it's OK to add new layers to the current style. + */ + + if (!TTMaskHasType(&cifCurReadStyle->crs_cifLayers, i) && !newOK) + continue; + if (strcmp(cifReadLayers[i], name) == 0) + { + if (newOK) TTMaskSetType(&cifCurReadStyle->crs_cifLayers, i); + return i; + } + } + + /* This name isn't in the table. Return an error or make a new entry. */ + + if (!newOK) return -1; + + if (cifNReadLayers == MAXCIFRLAYERS) + { + if (!errorPrinted) + { + TxError("CIF read layer table ran out of space at %d layers.\n", + MAXCIFRLAYERS); + TxError("Get your Magic maintainer to increase the table size.\n"); + errorPrinted = TRUE; + } + return -1; + } + + (void) StrDup(&(cifReadLayers[cifNReadLayers]), name); + TTMaskSetType(&cifCurReadStyle->crs_cifLayers, cifNReadLayers); + cifNReadLayers += 1; + return cifNReadLayers-1; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFCalmaLayerToCifLayer -- + * + * Find the CIF number of the layer matching the supplied Calma + * layer number and datatype. + * + * Results: + * Returns the CIF number of the above layer, or -1 if it + * can't be found. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +CIFCalmaLayerToCifLayer(layer, datatype, calmaStyle) + int layer; /* Calma layer number */ + int datatype; /* Calma datatype */ + CIFReadStyle *calmaStyle; +{ + CalmaLayerType clt; + HashEntry *he; + + clt.clt_layer = layer; + clt.clt_type = datatype; + if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt)) + return ((spointertype) HashGetValue(he)); + + /* Try wildcarding the datatype */ + clt.clt_type = -1; + if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt)) + return ((spointertype) HashGetValue(he)); + + /* Try wildcarding the layer */ + clt.clt_layer = -1; + clt.clt_type = datatype; + if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt)) + return ((spointertype) HashGetValue(he)); + + /* Try wildcarding them both, for a default value */ + clt.clt_layer = -1; + clt.clt_type = -1; + if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt)) + return ((spointertype) HashGetValue(he)); + + /* No luck */ + return (-1); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseReadLayers -- + * + * Given a comma-separated list of CIF layer names, builds a + * bit mask of all those layer names. + * + * Results: + * None. + * + * Side effects: + * Modifies the parameter pointed to by mask so that it contains + * a mask of all the CIF layers indicated. If any of the CIF + * layers didn't exist, new ones are created. If we run out + * of CIF layers, an error message is output. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFParseReadLayers(string, mask) + char *string; /* Comma-separated list of CIF layers. */ + TileTypeBitMask *mask; /* Where to store bit mask. */ +{ + int i; + char *p; + + TTMaskZero(mask); + + /* Break the string up into the chunks between commas. */ + + while (*string != 0) + { + p = strchr(string, ','); + if (p != NULL) + *p = 0; + + i = CIFReadNameToType(string, TRUE); + if (i >= 0) + TTMaskSetType(mask, i); + else + { + HashEntry *he; + TileTypeBitMask *amask; + + he = HashLookOnly(&DBTypeAliasTable, string); + if (he != NULL) + { + amask = (TileTypeBitMask *)HashGetValue(he); + TTMaskSetMask(mask, amask); + } + } + + if (p == NULL) break; + *p = ','; + for (string = p; *string == ','; string += 1) /* do nothing */; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * cifNewReadStyle -- + * + * This procedure creates a new CIF read style + * and initializes it to completely null. cifCurReadStyle is + * set to point to the new structure. + * + * Results: + * None. + * + * Side effects: + * Any information previously in cifCurReadStyle is destroyed and + * the memory allocation freed. + * + * ---------------------------------------------------------------------------- + */ + +void +cifNewReadStyle() +{ + int i; + CIFOp *op; + CIFReadLayer *layer; + + if (cifCurReadStyle != NULL) + { + /* Destroy old style and free all memory allocated to it */ + + for (i=0; icrs_layers[i]; + if (layer != NULL) + { + for (op = layer->crl_ops; op != NULL; op = op->co_next) + freeMagic((char *)op); + freeMagic((char *)layer); + } + } + + /* Destroy the calma mapping HashTable */ + HashKill(&(cifCurReadStyle->cifCalmaToCif)); + freeMagic((char *)cifCurReadStyle); + } + cifCurReadStyle = (CIFReadStyle *) mallocMagic(sizeof(CIFReadStyle)); + cifReadStyleInit(); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifReadStyleInit -- + * + * Fill in the current cif input style structure with initial values + * + * ---------------------------------------------------------------------------- + */ + +void +cifReadStyleInit() +{ + int i; + + cifCurReadStyle->crs_name = NULL; + cifCurReadStyle->crs_status = TECH_NOT_LOADED; + + cifCurReadStyle->crs_cifLayers = DBZeroTypeBits; + cifCurReadStyle->crs_nLayers = 0; + cifCurReadStyle->crs_scaleFactor = 0; + cifCurReadStyle->crs_multiplier = 1; + cifCurReadStyle->crs_gridLimit = 0; + cifCurReadStyle->crs_flags = 0; + HashInit(&(cifCurReadStyle->cifCalmaToCif), 64, + sizeof (CalmaLayerType) / sizeof (unsigned)); + for (i = 0; i < MAXCIFRLAYERS; i++) + { + cifCurReadStyle->crs_labelLayer[i] = TT_SPACE; + cifCurReadStyle->crs_layers[i] = NULL; + } +} + +/* + * + * ---------------------------------------------------------------------------- + * + * CIFReadTechInit -- + * + * Called to delete all structures associated with the CIF istyle + * tech prior to reading a new technology. + * + * Results: + * None. + * + * Side effects: + * Clears out the layer data structure. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFReadTechInit() +{ + CIFReadKeep *style; + + /* Cleanup any old info. */ + + cifNewReadStyle(); + freeMagic(cifCurReadStyle); + cifCurReadStyle = NULL; + + /* forget the list of styles */ + + for (style = cifReadStyleList; style != NULL; style = style->crs_next) + { + freeMagic(style->crs_name); + freeMagic(style); + } + cifReadStyleList = NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFReadTechStyleInit -- + * + * Called once at the beginning of technology file read-in to + * initialize data structures. + * + * Results: + * None. + * + * Side effects: + * Clears out the layer data structure. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFReadTechStyleInit() +{ + cifNReadLayers = 0; + cifCurReadLayer = NULL; + cifCurReadOp = NULL; +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFReadTechLine -- + * + * This procedure is called once by the tech module for each line + * in the "cifinput" section of the technology file. + * + * Results: + * Always return TRUE. + * + * Side effects: + * Sets up information in the tables used to read CIF, and prints + * error messages if problems arise. + * + * ---------------------------------------------------------------------------- + */ + /* ARGSUSED */ +bool +CIFReadTechLine(sectionName, argc, argv) + char *sectionName; /* Name of this section ("cifinput"). */ + int argc; /* Number of fields on line. */ + char *argv[]; /* Values of fields. */ +{ + CIFOp *newOp = NULL; + CIFReadKeep *newStyle, *p; + HashEntry *he; + CalmaLayerType clt; + int calmaLayers[CALMA_LAYER_MAX], calmaTypes[CALMA_LAYER_MAX]; + int nCalmaLayers, nCalmaTypes, l, t, j; + + if (argc <= 0) return TRUE; + else if (argc >= 2) l = strlen(argv[1]); + + /* See if we're starting a new style. If so, create it. If not, + * make sure there's already a style around, and create one if + * there isn't. + */ + + if (strcmp(argv[0], "style") == 0) + { + if (argc != 2) + { + if ((argc != 4) || (strncmp(argv[2], "variant", 7))) + { + wrongNumArgs: + TechError("Wrong number of arguments in %s statement.\n", + argv[0]); + errorReturn: + if (newOp != NULL) + freeMagic((char *) newOp); + return TRUE; + } + } + for (newStyle = cifReadStyleList; newStyle != NULL; + newStyle = newStyle->crs_next) + { + if (!strncmp(newStyle->crs_name, argv[1], l)) + break; + } + if (newStyle == NULL) + { + if (argc == 2) + { + newStyle = (CIFReadKeep *)mallocMagic(sizeof(CIFReadKeep)); + newStyle->crs_next = NULL; + newStyle->crs_name = StrDup((char **) NULL, argv[1]); + + /* Append to end of style list */ + if (cifReadStyleList == NULL) + cifReadStyleList = newStyle; + else + { + for (p = cifReadStyleList; p->crs_next; p = p->crs_next); + p->crs_next = newStyle; + } + } + else /* Handle style variants */ + { + CIFReadKeep *saveStyle = NULL; + char *tptr, *cptr; + + /* 4th argument is a comma-separated list of variants. */ + /* In addition to the default name recorded above, */ + /* record each of the variants. */ + + tptr = argv[3]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) *cptr = '\0'; + newStyle = (CIFReadKeep *)mallocMagic(sizeof(CIFReadKeep)); + newStyle->crs_next = NULL; + newStyle->crs_name = (char *)mallocMagic(strlen(argv[1]) + + strlen(tptr) + 1); + sprintf(newStyle->crs_name, "%s%s", argv[1], tptr); + + /* Remember the first variant as the default */ + if (saveStyle == NULL) saveStyle= newStyle; + + /* Append to end of style list */ + if (cifReadStyleList == NULL) + cifReadStyleList = newStyle; + else + { + for (p = cifReadStyleList; p->crs_next; p = p->crs_next); + p->crs_next = newStyle; + } + + if (cptr == NULL) + break; + else + tptr = cptr + 1; + } + newStyle = saveStyle; + } + } + + if (cifCurReadStyle == NULL) + { + cifNewReadStyle(); + cifCurReadStyle->crs_name = newStyle->crs_name; + cifCurReadStyle->crs_status = TECH_PENDING; + } + else if ((cifCurReadStyle->crs_status == TECH_PENDING) || + (cifCurReadStyle->crs_status == TECH_SUSPENDED)) + cifCurReadStyle->crs_status = TECH_LOADED; + else if (cifCurReadStyle->crs_status == TECH_NOT_LOADED) + { + if (cifCurReadStyle->crs_name == NULL) + return (FALSE); + else if (argc == 2) + { + if (!strcmp(argv[1], cifCurReadStyle->crs_name)) + cifCurReadStyle->crs_status = TECH_PENDING; + } + else if (argc == 4) + { + /* Verify that the style matches one variant */ + + char *tptr, *cptr; + + if (!strncmp(cifCurReadStyle->crs_name, argv[1], l)) + { + tptr = argv[3]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) *cptr = '\0'; + if (!strcmp(cifCurReadStyle->crs_name + l, tptr)) + { + cifCurReadStyle->crs_status = TECH_PENDING; + return TRUE; + } + if (cptr == NULL) + return TRUE; + else + tptr = cptr + 1; + } + } + } + } + return (TRUE); + } + + /* Only continue past this point if we are loading the cif input style */ + if (cifCurReadStyle == NULL) return FALSE; + if ((cifCurReadStyle->crs_status != TECH_PENDING) && + (cifCurReadStyle->crs_status != TECH_SUSPENDED)) return TRUE; + + /* Process scalefactor lines next. */ + + if (strcmp(argv[0], "scalefactor") == 0) + { + if ((argc < 2) || (argc > 4)) goto wrongNumArgs; + cifCurReadStyle->crs_scaleFactor = CIFParseScale(argv[1], + &cifCurReadStyle->crs_multiplier); + + /* + * The "nanometers" keyword multiplies the multiplier by 10. + * Keyword "calmaonly" is now ignored. + */ + + if (argc >= 3) + { + if(!strncmp(argv[argc - 1], "nanom", 5)) + cifCurReadStyle->crs_multiplier = 10; + } + + if (cifCurReadStyle->crs_scaleFactor <= 0) + { + cifCurReadStyle->crs_scaleFactor = 0; + TechError("Scalefactor must be a strictly positive value.\n"); + goto errorReturn; + } + return TRUE; + } + + /* Process "gridlimit" lines. */ + + if (strncmp(argv[0], "grid", 4) == 0) + { + if (StrIsInt(argv[1])) + { + cifCurReadStyle->crs_gridLimit = atoi(argv[1]); + if (cifCurReadStyle->crs_gridLimit < 0) + { + TechError("Grid limit must be a positive integer.\n"); + cifCurReadStyle->crs_gridLimit = 0; + } + } + else + { + TechError("Unable to parse grid limit value.\n"); + goto errorReturn; + } + return TRUE; + } + + /* Process "variant" lines next. */ + + if (strncmp(argv[0], "variant", 7) == 0) + { + int l; + char *cptr, *tptr; + + /* If our style variant is not one of the ones declared */ + /* on the line, then we ignore all input until we */ + /* either reach the end of the style, the end of the */ + /* section, or another "variant" line. */ + + if (argc != 2) goto wrongNumArgs; + tptr = argv[1]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) + { + *cptr = '\0'; + for (j = 1; isspace(*(cptr - j)); j++) + *(cptr - j) = '\0'; + } + + if (*tptr == '*') + { + cifCurReadStyle->crs_status = TECH_PENDING; + return TRUE; + } + else + { + l = strlen(cifCurReadStyle->crs_name) - strlen(tptr); + if (!strcmp(tptr, cifCurReadStyle->crs_name + l)) + { + cifCurReadStyle->crs_status = TECH_PENDING; + return TRUE; + } + } + + if (cptr == NULL) + break; + else + tptr = cptr + 1; + } + cifCurReadStyle->crs_status = TECH_SUSPENDED; + } + + /* Anything below this line is not parsed if we're in TECH_SUSPENDED mode */ + if (cifCurReadStyle->crs_status != TECH_PENDING) return TRUE; + + /* Process layer lines next. */ + + if (strcmp(argv[0], "layer") == 0) + { + TileType type; + + cifCurReadLayer = NULL; + cifCurReadOp = NULL; + if (cifCurReadStyle->crs_nLayers == MAXCIFRLAYERS) + { + TechError("Can't handle more than %d layers per style.\n", + MAXCIFRLAYERS); + TechError("Your local Magic wizard can increase the table size.\n"); + goto errorReturn; + } + if ((argc != 2) && (argc != 3)) goto wrongNumArgs; + type = DBTechNoisyNameType(argv[1]); + if (type < 0) goto errorReturn; + + cifCurReadLayer = (CIFReadLayer *) mallocMagic(sizeof(CIFReadLayer)); + cifCurReadStyle->crs_layers[cifCurReadStyle->crs_nLayers] + = cifCurReadLayer; + cifCurReadStyle->crs_nLayers += 1; + cifCurReadLayer->crl_magicType = type; + cifCurReadLayer->crl_ops = NULL; + cifCurReadLayer->crl_flags = CIFR_SIMPLE; + + /* Handle a special case of a list of layer names on the + * layer line. Turn them into an OR operation. + */ + + if (argc == 3) + { + cifCurReadOp = (CIFOp *) mallocMagic(sizeof(CIFOp)); + cifCurReadOp->co_opcode = CIFOP_OR; + cifCurReadOp->co_client = (ClientData)NULL; + CIFParseReadLayers(argv[2], &cifCurReadOp->co_cifMask); + TTMaskZero(&cifCurReadOp->co_paintMask); + cifCurReadOp->co_next = NULL; + cifCurReadOp->co_distance = 0; + cifCurReadLayer->crl_ops = cifCurReadOp; + } + return TRUE; + } + + /* Process templayer lines next. (templayers in cifinput added 5/3/09) */ + /* Fault handling deprecated 5/5/16; treat as templayer and flag a */ + /* warning. */ + + if ((strcmp(argv[0], "templayer") == 0) || (strcmp(argv[0], "fault") == 0)) + { + TileType type; + + cifCurReadLayer = NULL; + cifCurReadOp = NULL; + if (cifCurReadStyle->crs_nLayers == MAXCIFRLAYERS) + { + TechError("Can't handle more than %d layers per style.\n", + MAXCIFRLAYERS); + TechError("Your local Magic wizard can increase the table size.\n"); + goto errorReturn; + } + if ((argc != 2) && (argc != 3)) goto wrongNumArgs; + type = CIFReadNameToType(argv[1], TRUE); + if (type < 0) goto errorReturn; + + if (*argv[0] == 'f') + TechError("Error: Fault layers deprecated. Treating as templayer\n"); + + cifCurReadLayer = (CIFReadLayer *) mallocMagic(sizeof(CIFReadLayer)); + cifCurReadStyle->crs_layers[cifCurReadStyle->crs_nLayers] + = cifCurReadLayer; + cifCurReadStyle->crs_nLayers += 1; + cifCurReadLayer->crl_magicType = type; + cifCurReadLayer->crl_ops = NULL; + cifCurReadLayer->crl_flags = CIFR_TEMPLAYER | CIFR_SIMPLE; + + /* Handle a special case of a list of layer names on the + * layer line. Turn them into an OR operation. + */ + + if (argc == 3) + { + cifCurReadOp = (CIFOp *) mallocMagic(sizeof(CIFOp)); + cifCurReadOp->co_opcode = CIFOP_OR; + cifCurReadOp->co_client = (ClientData)NULL; + CIFParseReadLayers(argv[2], &cifCurReadOp->co_cifMask); + TTMaskZero(&cifCurReadOp->co_paintMask); + cifCurReadOp->co_next = NULL; + cifCurReadOp->co_distance = 0; + cifCurReadLayer->crl_ops = cifCurReadOp; + } + return TRUE; + } + + /* Process mapping between CIF layers and calma layers/types */ + if ((strcmp(argv[0], "calma") == 0) || (strncmp(argv[0], "gds", 3) == 0)) + { + int cifnum; + + if (argc != 4) goto wrongNumArgs; + cifnum = CIFReadNameToType(argv[1], FALSE); + if (cifnum < 0) + { + TechError("Unrecognized CIF layer: \"%s\"\n", argv[1]); + return TRUE; + } + nCalmaLayers = cifParseCalmaNums(argv[2], calmaLayers, CALMA_LAYER_MAX); + nCalmaTypes = cifParseCalmaNums(argv[3], calmaTypes, CALMA_LAYER_MAX); + if (nCalmaLayers <= 0 || nCalmaTypes <= 0) + return (TRUE); + + for (l = 0; l < nCalmaLayers; l++) + { + for (t = 0; t < nCalmaTypes; t++) + { + clt.clt_layer = calmaLayers[l]; + clt.clt_type = calmaTypes[t]; + he = HashFind(&(cifCurReadStyle->cifCalmaToCif), + (char *) &clt); + HashSetValue(he, (ClientData)(pointertype) cifnum); + } + } + return TRUE; + } + + /* Figure out which Magic layer should get labels from which + * CIF layers. + */ + + if (strcmp(argv[0], "labels") == 0) + { + TileTypeBitMask mask; + int i; + + if (cifCurReadLayer == NULL) + { + TechError("Must define layer before giving labels it holds.\n"); + goto errorReturn; + } + if (argc != 2) + { + if (argc == 3) + { + if (strcmp(argv[2], "text")) + goto wrongNumArgs; + } + else + goto wrongNumArgs; + } + CIFParseReadLayers(argv[1], &mask); + for (i=0; icrs_labelLayer[i] + = cifCurReadLayer->crl_magicType; + if (argc == 3) + cifCurReadStyle->crs_layers[i]->crl_flags |= CIFR_TEXTLABELS; + } + } + return TRUE; + } + + /* Parse "ignore" lines: look up the layers to enter them in + * the table of known layers, but don't do anything else. This + * will cause the layers to be ignored when encountered in + * cells. + */ + + if (strcmp(argv[0], "ignore") == 0) + { + TileTypeBitMask mask; + int i; + + if (argc != 2) goto wrongNumArgs; + CIFParseReadLayers(argv[1], &mask); + /* trash the value in crs_labelLayer so that any labels on this + layer get junked, also. dcs 4/11/90 + */ + for (i=0; i < cifNReadLayers; i++) + { + if (TTMaskHasType(&mask,i)) + { + if (cifCurReadStyle->crs_labelLayer[i] == TT_SPACE) + { + cifCurReadStyle->crs_labelLayer[i] = -1; + } + } + } + return TRUE; + } + + /* miscellaneous cif-reading boolean options */ + + if(strcmp(argv[0], "options") == 0) { + int i; + if (argc < 2) goto wrongNumArgs; + for(i = 1; i < argc; i++) { + if(strcmp(argv[i], "ignore-unknown-layer-labels") == 0) + cifCurReadStyle->crs_flags |= CRF_IGNORE_UNKNOWNLAYER_LABELS; + if(strcmp(argv[i], "no-reconnect-labels") == 0) + cifCurReadStyle->crs_flags |= CRF_NO_RECONNECT_LABELS; + } + return TRUE; + } + + /* Anything below here is a geometric operation, so we can + * do some set-up that is common to all the operations. + */ + + if (cifCurReadLayer == NULL) + { + TechError("Must define layer before specifying operations.\n"); + goto errorReturn; + } + newOp = (CIFOp *) mallocMagic(sizeof(CIFOp)); + TTMaskZero(&newOp->co_paintMask); + TTMaskZero(&newOp->co_cifMask); + newOp->co_opcode = 0; + newOp->co_distance = 0; + newOp->co_next = NULL; + newOp->co_client = (ClientData)NULL; + + if (strcmp(argv[0], "and") == 0) + newOp->co_opcode = CIFOP_AND; + else if (strcmp(argv[0], "and-not") == 0) + newOp->co_opcode = CIFOP_ANDNOT; + else if (strcmp(argv[0], "or") == 0) + newOp->co_opcode = CIFOP_OR; + else if (strcmp(argv[0], "grow") == 0) + newOp->co_opcode = CIFOP_GROW; + else if (strcmp(argv[0], "grow-grid") == 0) + newOp->co_opcode = CIFOP_GROW_G; + else if (strcmp(argv[0], "shrink") == 0) + newOp->co_opcode = CIFOP_SHRINK; + else if (strcmp(argv[0], "copyup") == 0) + newOp->co_opcode = CIFOP_COPYUP; + else + { + TechError("Unknown statement \"%s\".\n", argv[0]); + goto errorReturn; + } + + switch (newOp->co_opcode) + { + case CIFOP_AND: + case CIFOP_ANDNOT: + case CIFOP_OR: + case CIFOP_COPYUP: + if (argc != 2) goto wrongNumArgs; + CIFParseReadLayers(argv[1], &newOp->co_cifMask); + break; + + case CIFOP_GROW: + case CIFOP_GROW_G: + case CIFOP_SHRINK: + if (argc != 2) goto wrongNumArgs; + newOp->co_distance = atoi(argv[1]); + if (newOp->co_distance <= 0) + { + TechError("Grow/shrink distance must be greater than zero.\n"); + goto errorReturn; + } + break; + } + + /* Link the new CIFOp onto the list. */ + + if (cifCurReadOp == NULL) + { + cifCurReadLayer->crl_ops = newOp; + if (newOp->co_opcode != CIFOP_OR) + cifCurReadLayer->crl_flags &= ~CIFR_SIMPLE; + } + else + { + cifCurReadOp->co_next = newOp; + cifCurReadLayer->crl_flags &= ~CIFR_SIMPLE; + } + cifCurReadOp = newOp; + + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFReadTechFinal -- + * + * This procedure is invoked after all the lines of a technology + * file have been read. It checks to make sure that the information + * read in "cifinput" sections is reasonably complete. + * + * Results: + * None. + * + * Side effects: + * Error messages may be output. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFReadTechFinal() +{ + /* Reduce the scale by the multiplier, as much as possible while */ + /* keeping all CIF input ops in integer units. */ + /* Calling with scale 1:1 does no actual scaling, but does find any */ + /* common factors which can be divided out and reassigned to the */ + /* cif input multiplier factor. */ + + if (cifCurReadStyle == NULL) return; + + /* Make sure the current style has a valid scalefactor. */ + + if (cifCurReadStyle->crs_scaleFactor <= 0) + { + TechError("CIF input style \"%s\" bad scalefactor; using 1.\n", + cifCurReadStyle->crs_name); + cifCurReadStyle->crs_scaleFactor = 1; + } + + CIFTechInputScale(1, 1, TRUE); + + /* debug info --- Tim, 1/3/02 */ + TxPrintf("Input style %s: scaleFactor=%d, multiplier=%d\n", + cifCurReadStyle->crs_name, cifCurReadStyle->crs_scaleFactor, + cifCurReadStyle->crs_multiplier); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFReadLoadStyle -- + * + * Re-read the technology file to load the specified technology cif input + * style into structure cifCurReadStyle. This is much more memory-efficient than + * keeping a separate structure for each cif input style. It incurs a complete + * reading of the tech file on startup and every time the cif input style is + * changed, but we can assume that this does not happen often. The first + * style in the technology file is assumed to be default, so that re-reading + * the tech file is not necessary on startup unless the default cif input + * style is changed by a call to "cif istyle". + * + * ---------------------------------------------------------------------------- + */ +void +CIFReadLoadStyle(stylename) + char *stylename; +{ + SectionID invcifr; + + if (cifCurReadStyle->crs_name == stylename) return; + + cifNewReadStyle(); + cifCurReadStyle->crs_name = stylename; + + invcifr = TechSectionGetMask("cifinput", NULL); + TechLoad(NULL, invcifr); + + /* CIFReadTechFinal(); */ /* Taken care of by TechLoad() */ + CIFTechInputScale(DBLambda[0], DBLambda[1], TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFGetInputScale -- + * + * This routine is given here so that the CIF input scale can be + * accessed from the "commands" directory source without declaring + * external references to CIF global variables. + * + * Results: + * Internal units-to-(nanometers * convert) conversion factor (float). + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +float +CIFGetInputScale(convert) + int convert; +{ + /* Avoid divide-by-0 error if there is no cif input style */ + /* in the tech file. */ + if (!cifCurReadStyle) + { + TxError("Error: No style is set\n"); + return (float)0; + } + + /* NOTE: convert = 1000 for centimicrons to microns conversion */ + return ((float)(10 * cifCurReadStyle->crs_scaleFactor) + / (float)(cifCurReadStyle->crs_multiplier * convert)); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFPrintReadStyle -- + * + * Print the current CIF read style or a list of available styles. + * + * Results: + * None. + * + * Side effects: + * Output. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFPrintReadStyle(dolist, doforall, docurrent) + bool dolist; /* Return as a list if true */ + bool doforall; /* Return list of all styles if true */ + bool docurrent; /* Return current style if true */ +{ + CIFReadKeep *style; + + if (docurrent) + { + if (cifCurReadStyle == NULL) + TxError("Error: No style is set\n"); + else + { + if (!dolist) TxPrintf("The current style is \""); +#ifdef MAGIC_WRAPPER + if (dolist) + Tcl_SetResult(magicinterp, cifCurReadStyle->crs_name, NULL); + else +#endif + TxPrintf("%s", cifCurReadStyle->crs_name); + if (!dolist) TxPrintf("\".\n"); + } + } + + if (doforall) + { + + if (!dolist) TxPrintf("The CIF input styles are: "); + + for (style = cifReadStyleList; style != NULL; style = style->crs_next) + { + if (dolist) + { +#ifdef MAGIC_WRAPPER + Tcl_AppendElement(magicinterp, style->crs_name); +#else + if (style != cifReadStyleList) TxPrintf(" "); + TxPrintf("%s", style->crs_name); +#endif + } + else + { + if (style != cifReadStyleList) TxPrintf(", "); + TxPrintf("%s", style->crs_name); + } + } + if (!dolist) TxPrintf(".\n"); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFSetReadStyle -- + * + * This procedure changes the current style used for reading + * CIF. + * + * Results: + * None. + * + * Side effects: + * The CIF style is changed to the one specified by name. If + * there is no style by that name, then a list of all valid + * styles is output. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFSetReadStyle(name) + char *name; /* Name of the new style. If NULL, + * just print the name of the current + * style. + */ +{ + CIFReadKeep *style, *match; + int length; + + if (name == NULL) return; + + match = NULL; + length = strlen(name); + for (style = cifReadStyleList; style != NULL; style = style->crs_next) + { + if (strncmp(name, style->crs_name, length) == 0) + { + if (match != NULL) + { + TxError("CIF input style \"%s\" is ambiguous.\n", name); + CIFPrintReadStyle(FALSE, TRUE, TRUE); + return; + } + match = style; + } + } + + if (match != NULL) + { + CIFReadLoadStyle(match->crs_name); + TxPrintf("CIF input style is now \"%s\"\n", name); + return; + } + + TxError("\"%s\" is not one of the CIF input styles Magic knows.\n", name); + CIFPrintReadStyle(FALSE, TRUE, TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifParseCalmaNums -- + * + * Parse a comma-separated list of Calma numbers. Each number in + * the list must be between 0 and CALMA_LAYER_MAX, or an asterisk + * "*". Store each number in the array 'numArray', which has space + * for up to 'numNums' numbers. An asterisk is stored as -1. + * + * Results: + * Returns the number of numbers added to the array, or + * -1 on error. + * + * Side effects: + * Adds numbers to the array. If there were too many numbers, + * or some of the numbers were not legal Calma numbers, we + * print an error message. + * + * ---------------------------------------------------------------------------- + */ + +int +cifParseCalmaNums(str, numArray, numNums) + char *str; /* String to parse */ + int *numArray; /* Array to fill in */ + int numNums; /* Maximum number of entries in numArray */ +{ + int numFilled, num; + + for (numFilled = 0; numFilled < numNums; numFilled++) + { + /* Done if at end of string */ + if (*str == '\0') + return (numFilled); + + /* Is it a wild-card (*)? */ + if (*str == '*') num = -1; + else + { + num = atoi(str); + if (num < 0 || num > CALMA_LAYER_MAX) + { + TechError("Calma layer and type numbers must be 0 to %d.\n", + CALMA_LAYER_MAX); + return (-1); + } + } + + /* Skip to next number */ + while (*str && *str != ',') + { + if (*str != '*' && !isdigit(*str)) + { + TechError("Calma layer/type numbers must be numeric or '*'\n"); + return (-1); + } + str++; + } + + while (*str && *str == ',') str++; + numArray[numFilled] = num; + } + + TechError("Too many layer/type numbers in line; maximum = %d\n", numNums); + return (-1); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFTechInputScale(n, d, opt) + * + * Scale all CIF input scale factors to make them equivalent + * to reducing the magic internal unit spacing by a factor of n/d. + * + * After scaling, we attempt to reduce the ratio scaleFactor : multiplier + * if there is a common factor. If "opt" is TRUE, we reduce both values + * by this factor. If FALSE, we do not reduce multiplier below its + * original value. This is important if we are still in the process of + * reading CIF or GDS input. + * + * ---------------------------------------------------------------------------- + */ + +int +CIFTechInputScale(n, d, opt) + int n, d; + bool opt; +{ + CIFReadStyle *istyle = cifCurReadStyle; + CIFReadLayer *cl; + CIFOp *op; + int lmult, i, lgcf; + + if (istyle == NULL) return 0; + + /* fprintf(stderr, "CIF input style %s:\n", istyle->crs_name); */ + + istyle->crs_scaleFactor *= n; + istyle->crs_multiplier *= d; + + lmult = istyle->crs_multiplier; + for (i = 0; i < istyle->crs_nLayers; i++) + { + cl = istyle->crs_layers[i]; + for (op = cl->crl_ops; op != NULL; op = op->co_next) + { + if (op->co_distance) + { + op->co_distance *= d; + lgcf = FindGCF(abs(op->co_distance), istyle->crs_multiplier); + lmult = FindGCF(lmult, lgcf); + if (lmult == 1) break; + } + } + } + + /* fprintf(stderr, "All CIF units divisible by %d\n", lmult); */ + + lgcf = FindGCF(istyle->crs_scaleFactor, istyle->crs_multiplier); + if (lgcf < lmult) lmult = lgcf; + if (lmult == 0) return 0; + + /* fprintf(stderr, "Multiplier goes from %d to %d\n", istyle->crs_multiplier, + istyle->crs_multiplier / lmult); */ + + if (!opt) + { + if ((lmult % d) == 0) + lmult = d; + else + lmult = 1; + } + + if (lmult > 1) + { + istyle->crs_scaleFactor /= lmult; + istyle->crs_multiplier /= lmult; + + for (i = 0; i < istyle->crs_nLayers; i++) + { + cl = istyle->crs_layers[i]; + for (op = cl->crl_ops; op != NULL; op = op->co_next) + if (op->co_distance) + op->co_distance /= lmult; + } + } + return lmult; +} + diff --git a/cif/CIFrdutils.c b/cif/CIFrdutils.c new file mode 100644 index 00000000..c99e0622 --- /dev/null +++ b/cif/CIFrdutils.c @@ -0,0 +1,1664 @@ +/* CIFreadutils.c - + * + * This file contains routines that parse a file in CIF + * format. This file contains the top-level routine for + * reading CIF files, plus a bunch of utility routines + * for skipping white space, parsing numbers and points, etc. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdutils.c,v 1.4 2010/06/24 12:37:15 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "cif/CIFint.h" +#include "cif/CIFread.h" +#include "cif/cif.h" +#include "textio/textio.h" +#include "utils/signals.h" +#include "utils/undo.h" +#include "utils/malloc.h" + +/* The following variables are used to provide one character of + * lookahead. cifParseLaAvail is TRUE if cifParseLaChar contains + * a valid character, FALSE otherwise. The PEEK and TAKE macros + * are used to manipulate this stuff. + */ + +bool cifParseLaAvail = FALSE; +int cifParseLaChar = EOF; + +/* Below is a variable pointing to the CIF input file. It's used + * by the PEEK and TAKE macros. The other stuff is used to keep + * track of our location in the CIF file for error reporting + * purposes. + */ + +FILE *cifInputFile; +FILE *cifErrorFile; +int cifLineNumber; /* Number of current line. */ +int cifTotalWarnings; /* Number of warnings detected */ +int cifTotalErrors; /* Number of errors detected */ + +/* The variables used below hold general information about what + * we're currently working on. + */ + +int cifReadScale1; /* Scale factor: multiply by Scale1 */ +int cifReadScale2; /* then divide by Scale2. */ +int CIFRescaleLimit = CIFMAXRESCALE; /* Don't increase cifReadScale1 by more + * than this amount; internal units + * finer than this will be rounded. + */ +bool CIFRescaleAllow = TRUE; /* Don't subdivide the magic internal + * grid if this is FALSE. + */ +bool CIFNoDRCCheck = FALSE; /* If TRUE, then cell is marked DRC clean + * and not DRC checked. + */ +char *CIFErrorFilename; /* Name of file for error redirection */ + +int CifPolygonCount; /* Count of generated subcells + * containing polygons. This number + * is used to create a unique cell name. + */ +bool CIFSubcellPolygons = FALSE; /* If TRUE, each non-Manhattan polygon + * will be put in a separate subcell + * to avoid too much tile splitting + */ + +Plane *cifReadPlane; /* Plane into which to paint material + * NULL means no layer command has + * been seen for the current cell. + */ + +/* + * ---------------------------------------------------------------------------- + * + * CIFReadError -- + * + * This procedure is called to print out error messages during + * CIF file reading. + * + * Results: + * None. + * + * Side effects: + * An error message is printed. + * + * ---------------------------------------------------------------------------- + */ + + /* VARARGS1 */ +void +CIFReadError(char *format, ...) +{ + va_list args; + + cifTotalErrors++; + if (CIFWarningLevel == CIF_WARN_NONE) return; + if ((cifTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT)) + { + TxError("Error at line %d of CIF file: ", cifLineNumber); + va_start(args, format); + Vfprintf(stderr, format, args); + va_end(args); + } + else if ((cifTotalErrors == 100) && (CIFWarningLevel == CIF_WARN_LIMIT)) + { + TxError("Error limit set: Remaining errors will not be reported.\n"); + } +} + + +void +CIFReadWarning(char *format, ...) +{ + va_list args; + + cifTotalWarnings++; + if (CIFWarningLevel == CIF_WARN_NONE) return; + if ((cifTotalWarnings < 100) || (CIFWarningLevel != CIF_WARN_LIMIT)) + { + TxError("Warning at line %d of CIF file: ", cifLineNumber); + va_start(args, format); + Vfprintf(stderr, format, args); + va_end(args); + } + else if ((cifTotalWarnings == 100) && (CIFWarningLevel == CIF_WARN_LIMIT)) + { + TxError("Warning limit set: Remaining warnings will not be reported.\n"); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFScaleCoord + * + * This procedure does rounding and division to convert from + * CIF units back into Magic units. + * + * "snap_type" may be one of: + * COORD_EXACT: result must be an exact integer. If not, the + * magic grid spacing is changed such that the result will + * be an integer. + * COORD_HALF_U: twice the result must be an exact integer. If + * not, the magic grid spacing is changed as above. If the + * result is 1/2, it is rounded up to the nearest integer. + * COORD_HALF_L: same as above, but result is rounded down. + * COORD_ANY: result may be fractional, and will be snapped to + * the nearest magic grid. Generally, this is used for + * labels whose position need not be exact. + * + * Results: + * The result is the Magic unit equivalent to cifCoord. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +CIFScaleCoord(cifCoord, snap_type) + int cifCoord; /* A coordinate in CIF units. */ + int snap_type; /* How to deal with fractional results */ +{ + int result, scale, remain, denom; + int mult, mfactor; + + /* If internal grid subdivision is disallowed, always round to the */ + /* nearest grid unit. */ + + if (!CIFRescaleAllow) + snap_type = COORD_ANY; + + scale = cifCurReadStyle->crs_scaleFactor; + mult = cifCurReadStyle->crs_multiplier; + + /* Check for non-integer result and warn of fractional-lambda violation */ + + if ((remain = (cifCoord % scale)) != 0) + { + int lgcf = FindGCF(abs(cifCoord), scale); + + remain = abs(remain) / lgcf; + denom = scale / lgcf; + + if (CIFReadTechLimitScale(1, denom)) snap_type = COORD_ANY; + + switch (snap_type) + { + case COORD_EXACT: + CIFReadWarning("Input off lambda grid by %d/%d; grid redefined.\n", + remain, denom); + + CIFTechInputScale(1, denom, FALSE); + CIFTechOutputScale(1, denom); + DRCTechScale(1, denom); + PlowAfterTech(); + ExtTechScale(1, denom); + WireTechScale(1, denom); +#ifdef LEF_MODULE + LefTechScale(1, denom); +#endif +#ifdef ROUTE_MODULE + RtrTechScale(1, denom); + MZAfterTech(); + IRAfterTech(); +#endif + DBScaleEverything(denom, 1); + DBLambda[1] *= denom; + ReduceFraction(&DBLambda[0], &DBLambda[1]); + scale = cifCurReadStyle->crs_scaleFactor; + result = cifCoord / scale; + break; + case COORD_HALF_U: case COORD_HALF_L: + if (denom > 2) + { + CIFReadWarning("Input off lambda grid by %d/%d; grid redefined.\n", + remain, denom); + + /* scale to nearest half-lambda */ + if (!(denom & 0x1)) denom >>= 1; + + CIFTechInputScale(1, denom, FALSE); + CIFTechOutputScale(1, denom); + DRCTechScale(1, denom); + PlowAfterTech(); + ExtTechScale(1, denom); + WireTechScale(1, denom); + MZAfterTech(); + IRAfterTech(); +#ifdef LEF_MODULE + LefTechScale(1, denom); +#endif +#ifdef ROUTE_MODULE + RtrTechScale(1, denom); +#endif + DBScaleEverything(denom, 1); + DBLambda[1] *= denom; + ReduceFraction(&DBLambda[0], &DBLambda[1]); + scale = cifCurReadStyle->crs_scaleFactor; + } + + if (snap_type == COORD_HALF_U) + result = cifCoord + (scale >> 1); + else + result = cifCoord - (scale >> 1); + result /= scale; + + break; + case COORD_ANY: + CIFReadWarning("Input off lambda grid by %d/%d; snapped to grid.\n", + abs(remain), abs(denom)); + + /* Careful: must round down a bit more for negative numbers, in + * order to ensure that a point exactly halfway between Magic units + * always gets rounded down, rather than towards zero (this would + * result in different treatment of the same paint, depending on + * where it is in the coordinate system. + */ + + if (cifCoord < 0) + result = cifCoord - ((scale)>>1); + else + result = cifCoord + ((scale-1)>>1); + result /= scale; + break; + } + } + else + result = cifCoord / scale; + + return result; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifIsBlank -- + * + * Figures out whether a character qualifies as a blank in CIF. + * A blank is anything except a digit, an upper-case character, + * or the symbols "-", "(", "(", and ";". + * + * Results: + * Returns TRUE if ch is a CIF blank, FALSE otherwise. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +cifIsBlank(ch) + int ch; +{ + + if ( isdigit(ch) || isupper(ch) + || (ch == '-') || (ch == ';') + || (ch == '(') || (ch == ')') + || (ch == EOF)) + { + return FALSE; + } + else return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFSkipBlanks -- + * + * This procedure skips over whitespace in the CIF file, + * keeping track of the line number and other information + * for error reporting. + * + * Results: + * None. + * + * Side effects: + * Advances through the CIF file. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFSkipBlanks() +{ + + while (cifIsBlank(PEEK())) { + if (TAKE() == '\n') + { + cifLineNumber++; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFSkipSep -- + * + * Skip over separators in the CIF file. Blanks and upper-case + * characters are separators. + * + * Results: + * None. + * + * Side effects: + * Advances through the CIF file. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFSkipSep() +{ + int ch; + + for (ch = PEEK() ; isupper(ch) || cifIsBlank(ch) ; ch = PEEK()) { + if (TAKE() == '\n') + { + cifLineNumber++; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFSkipToSemi -- + * + * This procedure is called after errors. It skips everything + * in the CIF file up to the next semi-colon. + * + * Results: + * None. + * + * Side effects: + * Advances through the CIF file. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFSkipToSemi() +{ + int ch; + + for (ch = PEEK() ; ((ch != ';') && (ch != EOF)) ; ch = PEEK()) { + if (TAKE() == '\n') + { + cifLineNumber++; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFSkipSemi -- + * + * Skips a semi-colon, including blanks around the semi-colon. + * + * Results: + * None. + * + * Side effects: + * Advances through the CIF file. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFSkipSemi() +{ + + CIFSkipBlanks(); + if (PEEK() != ';') { + CIFReadError("`;\' expected.\n"); + return; + } + TAKE(); + CIFSkipBlanks(); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseSInteger -- + * + * This procedure parses a signed integer from the CIF file. + * + * Results: + * TRUE is returned if the parse completed without error, + * FALSE otherwise. + * + * Side effects: + * The integer pointed to by valuep is modified with the + * value of the signed integer. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseSInteger(valuep) + int *valuep; +{ + bool is_signed; + char buffer[ BUFSIZ ]; + char *bufferp; + + *valuep = 0; + CIFSkipSep(); + if (PEEK() == '-') + { + TAKE(); + is_signed = TRUE; + } + else is_signed = FALSE; + bufferp = &buffer[0]; + while (isdigit(PEEK())) + *bufferp++ = TAKE(); + if (bufferp == &buffer[0]) + return FALSE; + *bufferp = '\0'; + *valuep = atoi(&buffer[0]); + if (is_signed) + *valuep = -(*valuep); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseInteger -- + * + * Parses a positive integer from the CIF file. + * + * Results: + * TRUE is returned if the parse was completed successfully, + * FALSE otherwise. + * + * Side effects: + * The value pointed to by valuep is modified to hold the integer. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseInteger(valuep) + int *valuep; +{ + + if (!CIFParseSInteger(valuep)) + return FALSE; + if (*valuep < 0) + CIFReadError("negative integer not permitted.\n"); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParsePoint -- + * + * Parse a point from a CIF file. A point is two integers + * separated by CIF separators. + * parameter "iscale" (internal scale factor) is usually 1, but + * can be 2 to deal with half-lambda entries in the CIF by + * returning double the result. + * + * Results: + * TRUE is returned if the point was parsed correctly, otherwise + * FALSE is returned. + * + * Side effects: + * The parameter pointp is filled in with the coordinates of + * the point. + * + * If the CIF scalefactors are such that the result would be a + * fractional value, the definition of the CIF scale is altered + * such that the result is integer, and all geometry read so far + * is altered to match. This does not immediately affect the geometry + * in the magic database; if that also appears to have fractional + * units, it will be discovered by CIFScaleCoord and corrected. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParsePoint(pointp, iscale) + Point *pointp; + int iscale; +{ + int rescale; + + pointp->p_x = 0; + pointp->p_y = 0; + if (!CIFParseSInteger(&pointp->p_x)) + return FALSE; + pointp->p_x *= (cifReadScale1 * iscale); + if (pointp->p_x % cifReadScale2 != 0) + { + rescale = cifReadScale2 / FindGCF(cifReadScale2, abs(pointp->p_x)); + if ((cifReadScale1 * rescale) > CIFRescaleLimit) + { + CIFReadWarning("CIF units at maximum scale; value is rounded\n"); + /* prepare for nearest-integer rounding */ + if (pointp->p_x < 0) + pointp->p_x -= ((cifReadScale2 - 1) >> 1); + else + pointp->p_x += (cifReadScale2 >> 1); + } + else + { + cifReadScale1 *= rescale; + CIFInputRescale(rescale, 1); + pointp->p_x *= rescale; + } + } + pointp->p_x /= cifReadScale2; + if (!CIFParseSInteger(&pointp->p_y)) + return FALSE; + pointp->p_y *= (cifReadScale1 * iscale); + if (pointp->p_y % cifReadScale2 != 0) + { + rescale = cifReadScale2 / FindGCF(cifReadScale2, abs(pointp->p_y)); + if ((cifReadScale1 * rescale) > CIFRescaleLimit) + { + CIFReadWarning("CIF units at maximum scale; value is rounded\n"); + /* prepare for nearest-integer rounding */ + if (pointp->p_y < 0) + pointp->p_y -= ((cifReadScale2 - 1) >> 1); + else + pointp->p_y += (cifReadScale2 >> 1); + } + else + { + cifReadScale1 *= rescale; + CIFInputRescale(rescale, 1); + pointp->p_x *= rescale; + pointp->p_y *= rescale; + } + } + pointp->p_y /= cifReadScale2; + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFParsePath -- + * + * This procedure parses a CIF path, which is sequence of + * one or more points. + * + * Results: + * TRUE is returned if the path was parsed successfully, + * FALSE otherwise. + * + * Side effects: + * Modifies the parameter pathheadpp to point to the path + * that is constructed. + * + * Corrections: + * CIF coordinates are multiplied by 2 to cover the case where + * the path centerline lies on the half lambda grid but the line + * itself is on-grid. This can't be done for polygons, so a + * parameter "iscale" (internal scale) is added, and set to 1 for + * polygons, 2 for wires when calling CIFParsePath(). + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParsePath(pathheadpp, iscale) + CIFPath **pathheadpp; + int iscale; +{ + CIFPath *pathtailp, *newpathp; + bool nonManhattan = FALSE; /* diagnostic only */ + CIFPath path; + int savescale; + + *pathheadpp = NULL; + pathtailp = NULL; + path.cifp_next = NULL; + while (TRUE) + { + CIFSkipSep(); + if (PEEK() == ';') + break; + + savescale = cifReadScale1; + if (!CIFParsePoint(&path.cifp_point, iscale)) + { + CIFFreePath(*pathheadpp); + return FALSE; + } + if (savescale != cifReadScale1) + { + CIFPath *phead = *pathheadpp; + int newscale = cifReadScale1 / savescale; + while (phead != NULL) + { + phead->cifp_x *= newscale; + phead->cifp_y *= newscale; + phead = phead->cifp_next; + } + } + newpathp = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath))); + *newpathp = path; + if (*pathheadpp) + { + /* + * Check that this segment is Manhattan. If not, remember the + * fact and later introduce extra stair-steps to make the path + * Manhattan. We don't do the stair-step introduction here for + * two reasons: first, the same code is also used by the Calma + * module, and second, it is important to know which side of + * the polygon is the outside when generating the stair steps. + */ + if (pathtailp->cifp_x != newpathp->cifp_x + && pathtailp->cifp_y != (newpathp->cifp_y)) + { + nonManhattan = TRUE; + } + pathtailp->cifp_next = newpathp; + } + else *pathheadpp = newpathp; + pathtailp = newpathp; + } + return (*pathheadpp != NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * test_insideness -- + * + * Determine if a point is inside a rectangle defined by the + * first three points in the given CIF path. + * + * Results: + * TRUE if point is inside, FALSE if outside or on the border + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +bool +test_insideness(start, tpoint) + CIFPath *start; + Point *tpoint; +{ + Rect tmprect, irect; + + tmprect.r_xbot = start->cifp_x; + tmprect.r_ybot = start->cifp_y; + tmprect.r_xtop = start->cifp_next->cifp_next->cifp_x; + tmprect.r_ytop = start->cifp_next->cifp_next->cifp_y; + + GeoCanonicalRect(&tmprect, &irect); + + return ((tpoint->p_x > irect.r_xbot) + && (tpoint->p_x < irect.r_xtop) + && (tpoint->p_y > irect.r_ybot) + && (tpoint->p_y < irect.r_ytop)) ? TRUE : FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * seg_intersect -- + * + * Determine if two line segments intersect or touch + * Expects first line to be manhattan. + * + * Results: + * returns TRUE if segments intersect, FALSE otherwise + * + * Side effects: + * value of respt contains point to which segment will be + * truncated. + * + * ---------------------------------------------------------------------------- + */ + +bool +seg_intersect(tstart, bf, bs, respt) + CIFPath *tstart; + Point *bf, *bs; + Point *respt; +{ + int afx = tstart->cifp_x; + int afy = tstart->cifp_y; + int asx = tstart->cifp_next->cifp_x; + int asy = tstart->cifp_next->cifp_y; + int adx, ady; + + if (afx == asx) /* "a" is a vertical line */ + { + adx = afx + ((tstart->cifp_next->cifp_next->cifp_x > afx) ? 1 : -1); + + /* Ignore if b does not cross the x boundary of ad */ + if ((bf->p_x > adx && bs->p_x > adx) || + (bf->p_x < adx && bs->p_x < adx)) + return FALSE; + + if (bs->p_x == bf->p_x) /* nonintersecting vertical lines */ + return FALSE; + + respt->p_x = afx; + respt->p_y = bf->p_y + (int) + (((dlong)(bs->p_y - bf->p_y) * (dlong)(afx - bf->p_x)) / + (dlong)(bs->p_x - bf->p_x)); + if (((respt->p_y > afy) && (respt->p_y < asy)) || + ((respt->p_y < afy) && (respt->p_y > asy))) + return TRUE; + } + else /* (afy == asy), "a" is a horizontal line */ + { + ady = afy + ((tstart->cifp_next->cifp_next->cifp_y > afy) ? 1 : -1); + + /* Ignore if b does not cross the y boundary of ad */ + if ((bf->p_y > ady && bs->p_y > ady) || + (bf->p_y < ady && bs->p_y < ady)) + return FALSE; + + if (bs->p_y == bf->p_y) /* nonintersecting horizontal lines */ + return FALSE; + + respt->p_y = afy; + respt->p_x = bf->p_x + (int) + (((dlong)(bs->p_x - bf->p_x) * (dlong)(afy - bf->p_y)) / + (dlong)(bs->p_y - bf->p_y)); + if (((respt->p_x > afx) && (respt->p_x < asx)) || + ((respt->p_x < afx) && (respt->p_x > asx))) + return TRUE; + } + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * path_intersect -- + * + * Determine if a path intersects the given line segment. + * A path sharing a portion of the segment is not an intersection. + * + * ---------------------------------------------------------------------------- + */ + +bool +path_intersect(pathHead, start, respt) + CIFPath *pathHead, *start; + Point *respt; +{ + CIFPath *path, *segcrossed, *new; + Point tmppt; + bool does_cross = FALSE, diagonal = FALSE; + int tdist, newdist; + + tdist = newdist = INFINITY; + for (path = pathHead; path->cifp_next; path = path->cifp_next) + { + /* don't compare with self */ + if (path == start || path == start->cifp_next) continue; + + /* Does the path intersect the first line of the */ + /* right triangle, continuing in the direction of */ + /* the last point on the triangle? */ + + if (seg_intersect(start, &path->cifp_point, + &path->cifp_next->cifp_point, &tmppt)) + { + newdist = (start->cifp_x - tmppt.p_x) + (start->cifp_y - tmppt.p_y); + diagonal = TRUE; + } + + /* Is the point inside the triangle, and the path is Manhattan? */ + /* (Note that *both* tests can be true, in which case the one */ + /* with the smaller absolute distance takes precedence.) */ + + if (test_insideness(start, &path->cifp_point)) { + int tmpdist = abs(newdist); /* save this value */ + if (path->cifp_x == path->cifp_next->cifp_x || + path->cifp_y == path->cifp_next->cifp_y) + { + if (start->cifp_x == start->cifp_next->cifp_x) + { + newdist = path->cifp_y - start->cifp_y; + if (abs(newdist) < tmpdist) + { + tmppt.p_x = start->cifp_x; + tmppt.p_y = path->cifp_y; + diagonal = FALSE; + } + } + else + { + newdist = path->cifp_x - start->cifp_x; + if (abs(newdist) < tmpdist) + { + tmppt.p_y = start->cifp_y; + tmppt.p_x = path->cifp_x; + diagonal = FALSE; + } + } + } + } + else if (diagonal == FALSE) + continue; + + newdist = abs(newdist); + if ((!does_cross) || (newdist < tdist)) + { + does_cross = TRUE; + respt->p_x = tmppt.p_x; + respt->p_y = tmppt.p_y; + tdist = newdist; + segcrossed = (diagonal) ? path : NULL; + } + } + + /* If we're limited by another side of the polygon, then we're */ + /* guaranteed that we'll have to add another point there. By */ + /* doing it here, we avoid problems due to roundoff errors. */ + + if (does_cross && segcrossed) + { + new = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath))); + new->cifp_next = segcrossed->cifp_next; + segcrossed->cifp_next = new; + new->cifp_x = respt->p_x; + new->cifp_y = respt->p_y; + } + return does_cross; +} + +/* + * ---------------------------------------------------------------------------- + * + * is_clockwise -- + * + * Determine if a path is clockwise or counterclockwise. + * + * Results: + * TRUE if the path is clockwise, FALSE otherwise. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +is_clockwise(pathHead) + CIFPath *pathHead; +{ + CIFPath *path, *midx = NULL, *last; + Point *p1, *p2, *p3; + dlong sdir; + int minx = INFINITY; + + /* Find out if this is a clockwise or counterclockwise path by */ + /* finding the (a) leftmost point and assuming the polygon to fill */ + /* is to the right. */ + + for (path = pathHead; path->cifp_next; path = path->cifp_next) + { + if (path->cifp_next->cifp_x < minx) + { + minx = path->cifp_next->cifp_x; + midx = path->cifp_next; + last = path; + } + } + + if (!midx) return TRUE; /* one-point polygon? */ + + /* Rare case of colinear points (implies degenerate polygon) requires */ + /* moving along pointlist until points are not colinear and repeating */ + /* the search for the minimum. */ + + if (last->cifp_x == midx->cifp_x) + { + for (path = pathHead; path && path->cifp_x == minx; + path = path->cifp_next); + if (!path) return TRUE; /* completely degenerate; direc. irrelevant */ + minx = INFINITY; + for (; path->cifp_next; path = path->cifp_next) + { + if (path->cifp_next->cifp_x < minx) + { + minx = path->cifp_next->cifp_x; + midx = path->cifp_next; + last = path; + } + } + } + + if (!(midx->cifp_next)) midx = pathHead; + + /* p2 is the (a) leftmost point; p1 and p3 are the points before */ + /* and after in the CIF path, respectively. */ + + p1 = &(last->cifp_point); + p2 = &(midx->cifp_point); + p3 = &(midx->cifp_next->cifp_point); + + /* Find which side p3 falls on relative to the line p1-p2. This */ + /* determines whether the path is clockwise or counterclockwise. */ + /* Use type dlong to avoid integer overflow. */ + + sdir = ((dlong)(p2->p_x - p1->p_x) * (dlong)(p3->p_y - p1->p_y) - + (dlong)(p2->p_y - p1->p_y) * (dlong)(p3->p_x - p1->p_x)); + + return (sdir < 0) ? TRUE : FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFMakeManhattanPath -- + * + * Convert a non-Manhattan path into a Manhattan one by + * breaking out triangles and leaving all Manhattan edges. + * Additional points are added which reroute the CIF path + * around the triangle. In the simplest case, each non-Manhattan + * edge becomes a split tile bounding the edge endpoints. + * However, if that split tile would extend beyond the boundary + * of the CIF path, the edge is subdivided into as many + * triangles as are necessary to complete the path while remaining + * within the polygon boundary. Unfortunately, for non-45-degree + * edges, the edge subdivision might not fall on an integer lambda + * value, so the resulting edge could be off by as much as 1/2 + * lambda. In this case, flag a warning. + * + * Results: + * None. + * + * Side effects: + * May insert additional points in the path. + * May alter the intended geometry of a non-manhattan edge by as + * much as 1/2 lambda. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFMakeManhattanPath(pathHead, plane, resultTbl, ui) + CIFPath *pathHead; + Plane *plane; + PaintResultType *resultTbl; + PaintUndoInfo *ui; +{ + CIFPath *new, *new2, *next, *path; + int xinit, xdiff, xincr, xlast, x; + int yinit, ydiff, yincr, ylast, y; + + bool clockwise; + CIFPath *first, *last; + Rect tt, tr; + TileType type; + + clockwise = is_clockwise(pathHead); + + for (path = pathHead; path->cifp_next; path = path->cifp_next) + { + Point clipbase; + int edir; + next = path->cifp_next; + + /* No work if this segment is Manhattan */ + if (path->cifp_x == next->cifp_x || path->cifp_y == next->cifp_y) + continue; + + /* Otherwise, break out the triangle, then adjust as necessary */ + + new = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath))); + path->cifp_next = new; + new->cifp_next = next; + + /* Generate split tiles as necessary to reach next->cifp_y */ + + if (clockwise) + { + first = next; + last = path; + } + else + { + first = path; + last = next; + } + edir = CIFEdgeDirection(first, last); + if (edir == CIF_DIAG_DL || edir == CIF_DIAG_UR) + { + new->cifp_x = first->cifp_x; + new->cifp_y = last->cifp_y; + } + else /* edir == CIF_DIAG_DR || edir == CIF_DIAG_UL */ + { + new->cifp_x = last->cifp_x; + new->cifp_y = first->cifp_y; + } + + /* Check if the segment from first to base intersects */ + /* the polygon edge */ + + if (path_intersect(pathHead, path, &clipbase)) + { + new->cifp_x = clipbase.p_x; + new->cifp_y = clipbase.p_y; + + new2 = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath))); + new->cifp_next = new2; + new2->cifp_next = next; + + /* Use double long for the multiplication and */ + /* division, or else integer overflow can occur. */ + + if (path->cifp_x == new->cifp_x) /* vertical line */ + { + new2->cifp_y = new->cifp_y; + new2->cifp_x = path->cifp_x + (int) + ((dlong)(new2->cifp_y - path->cifp_y) + * (dlong)(next->cifp_x - path->cifp_x) + / (dlong)(next->cifp_y - path->cifp_y)); + } + else + { + new2->cifp_x = new->cifp_x; + new2->cifp_y = path->cifp_y + (int) + ((dlong)(new2->cifp_x - path->cifp_x) + * (dlong)(next->cifp_y - path->cifp_y) + / (dlong)(next->cifp_x - path->cifp_x)); + } + } + + /* Break out the diagonal tile from the polygon and paint it. */ + + type = (edir == CIF_DIAG_UR || edir == CIF_DIAG_UL) ? 0 : TT_SIDE; + type |= (edir == CIF_DIAG_UR || edir == CIF_DIAG_DL) ? 0 : TT_DIRECTION; + type |= TT_DIAGONAL; + + tt.r_ll = path->cifp_point; + tt.r_ur = path->cifp_next->cifp_next->cifp_point; + GeoCanonicalRect(&tt, &tr); + +// TxPrintf("CIF read: Triangle %s %c at (%d, %d) plane %x\n", +// (type & TT_SIDE) ? "right" : "left", (type & TT_DIRECTION) +// ? '\\' : '/', tt.r_xbot, tt.r_ybot, plane); + + /* Final check---ensure that rectangle is not degenerate */ + + if (plane && (tr.r_xtop - tr.r_xbot > 0) && (tr.r_ytop - tr.r_ybot > 0)) + DBNMPaintPlane(plane, type, &tr, resultTbl, ui); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFEdgeDirection -- + * + * This procedure assigns a direction to the given edge. + * + * Results: + * CIF_ZERO if the two points are the same + * CIF_LEFT if the edge goes left + * CIF_UP if the edge goes up + * CIF_RIGHT if the edge goes right + * CIF_DOWN if the edge goes down + * CIF_DIAG if the edge is non-manhattan + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +CIFEdgeDirection(first, last) + CIFPath *first, *last; /* Edge to be categorized. */ +{ + + if (first->cifp_x < last->cifp_x) + { + if (first->cifp_y < last->cifp_y) + return CIF_DIAG_UR; + if (first->cifp_y > last->cifp_y) + return CIF_DIAG_DR; + return CIF_RIGHT; + } + if (first->cifp_x > last->cifp_x) + { + if (first->cifp_y < last->cifp_y) + return CIF_DIAG_UL; + if (first->cifp_y > last->cifp_y) + return CIF_DIAG_DL; + return CIF_LEFT; + } + if (first->cifp_y < last->cifp_y) + return CIF_UP; + if (first->cifp_y > last->cifp_y) + return CIF_DOWN; + return CIF_ZERO; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFCleanPath -- + * + * Removes a edge in a path if it has zero length (repeated points). + * Combines two consecutive edges if their direction is the same, + * and their direction is manhattan. + * CIFCleanPath assumes that the path is closed, and will eliminate + * the last edge if its direction is the same as the first. + * + * Results: + * None. + * + * Side effects: + * May delete points in the path. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFCleanPath(pathHead) + CIFPath *pathHead; +{ + CIFPath *next, *path, *prev, *last; + int dir1, dir2; + + if (!pathHead) return; + prev = pathHead; + path = prev->cifp_next; + if (!path) return; + while((dir1 = CIFEdgeDirection(prev, path)) == CIF_ZERO) + { + /* This is a repeated point. */ + next = path->cifp_next; + prev->cifp_next = next; + freeMagic((char *) path); + path = next; + if (!path) return; + } + + while (next = path->cifp_next) + { + if ((dir2 = CIFEdgeDirection(path, next)) == CIF_ZERO) + { + /* This is a repeated point. */ + path->cifp_next = next->cifp_next; + freeMagic((char *) next); + continue; + } + + /* Skip any non-manhattan (diagonal) edges. */ + if (dir2 >= CIF_DIAG) + goto path_inc; + + if (dir1 == dir2) + { + /* The middle point must go. */ + prev->cifp_next = next; + freeMagic((char *) path); + path = next; + dir1 = CIFEdgeDirection(prev, path); + continue; + } +path_inc: + dir1 = dir2; + prev = path; + path = next; + } + + /* Ensure that the path has more than one point. */ + if (!pathHead->cifp_next) + { + /* Ensure that the resulting path is closed. */ + if ((pathHead->cifp_x != path->cifp_x) || + (pathHead->cifp_y != path->cifp_y)) + { + next = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath))); + next->cifp_x = pathHead->cifp_x; + next->cifp_y = pathHead->cifp_y; + next->cifp_next = (CIFPath *) 0; + path->cifp_next = next; + prev = path; + path = next; + dir1 = CIFEdgeDirection(prev, path); + } + if ((dir2 = CIFEdgeDirection(pathHead, pathHead->cifp_next)) < + CIF_DIAG) + { + /* We have at least two edges in the path. We have to */ + /* fix the first edge and eliminate the last edge if */ + /* the first and last edge have the same direction. */ + if (dir1 == dir2) + { + pathHead->cifp_x = prev->cifp_x; + pathHead->cifp_y = prev->cifp_y; + prev->cifp_next = (CIFPath *) 0; + freeMagic((char *) path); + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFFreePath -- + * + * This procedure frees up a path once it has been used. + * + * Results: + * None. + * + * Side effects: + * All the elements of path are returned to the storage allocator. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFFreePath(path) + CIFPath *path; /* Path to be freed. */ +{ + while (path != NULL) + { + freeMagic((char *) path); + path = path->cifp_next; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * cifCommandError -- + * + * This procedure is called when unknown CIF commands are found + * in CIF files. It skips the command and advances to the next + * command. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +cifCommandError() +{ + CIFReadError("unknown command `%c'; ignored.\n" , PEEK()); + CIFSkipToSemi(); +} + + +/* + * ---------------------------------------------------------------------------- + * + * cifParseEnd -- + * + * This procedure processes the "end" statement in a CIF file + * (it ignores it). + * + * Results: + * Always returns TRUE. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +cifParseEnd() +{ + TAKE(); + CIFSkipBlanks(); + if (PEEK() != EOF) + { + CIFReadError("End command isn't at end of file.\n"); + return FALSE; + } + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifParseComment -- + * + * This command skips over user comments in CIF files. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +cifParseComment() +{ + int opens; + int ch; + + /* + * take the '(' + */ + TAKE(); + opens = 1; + do + { + ch = TAKE(); + if (ch == '(') + opens++; + else if (ch == ')') + opens--; + else if (ch == '\n') + { + cifLineNumber++; + } + else if (ch == EOF) + { + CIFReadError("(comment) extends to end of file.\n"); + return FALSE; + } + } while (opens > 0); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFDirectionToTrans -- + * + * This procedure is used to convert from a direction vector + * to a Magic transformation. The direction vector is a point + * giving a direction from the origin. It better be along + * one of the axes. + * + * Results: + * The return value is the transformation corresponding to + * the direction, or the identity transform if the direction + * isn't along one of the axes. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +Transform * +CIFDirectionToTrans(point) + Point *point; /* Direction vector from origin. */ +{ + if ((point->p_x != 0) && (point->p_y == 0)) + { + if (point->p_x > 0) + return &GeoIdentityTransform; + else return &Geo180Transform; + } + else if ((point->p_y != 0) && (point->p_x == 0)) + { + if (point->p_y > 0) + return &Geo270Transform; + else return &Geo90Transform; + } + CIFReadError("non-manhattan direction vector (%d, %d); ignored.\n", + point->p_x, point->p_y); + return &GeoIdentityTransform; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseTransform -- + * + * This procedure is called to read in a transform from a + * CIF file. + * + * Results: + * TRUE is returned if the parse completed successfully, and + * FALSE is returned otherwise. + * + * Side effects: + * The parameter pointed to by transformp is modified to + * contain the transform indicated by the CIF file. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFParseTransform(transformp) + Transform *transformp; +{ + char ch; + Point point; + Transform tmp; + int savescale; + + *transformp = GeoIdentityTransform; + CIFSkipBlanks(); + for (ch = PEEK() ; ch != ';' ; ch = PEEK()) + { + switch (ch) + { + case 'T': + TAKE(); + if (!CIFParsePoint(&point, 1)) + { + CIFReadError("translation, but no point.\n"); + CIFSkipToSemi(); + return FALSE; + } + GeoTranslateTrans(transformp, point.p_x, point.p_y, &tmp); + *transformp = tmp; + break; + case 'M': + TAKE(); + CIFSkipBlanks(); + ch = PEEK(); + if (ch == 'X') + GeoTransTrans(transformp, &GeoSidewaysTransform, &tmp); + else if (ch == 'Y') + GeoTransTrans(transformp, &GeoUpsideDownTransform, + &tmp); + else + { + CIFReadError("mirror, but not in X or Y.\n"); + CIFSkipToSemi(); + return FALSE; + } + TAKE(); + *transformp = tmp; + break; + case 'R': + TAKE(); + if (!CIFParseSInteger(&point.p_x) || + !CIFParseSInteger(&point.p_y)) + { + CIFReadError("rotation, but no direction.\n"); + CIFSkipToSemi(); + return FALSE; + } + GeoTransTrans(transformp, CIFDirectionToTrans(&point), + &tmp); + *transformp = tmp; + break; + default: + CIFReadError("transformation expected.\n"); + CIFSkipToSemi(); + return FALSE; + } + CIFSkipBlanks(); + } + + /* Before returning, we must scale the transform into Magic units. */ + + transformp->t_c = CIFScaleCoord(transformp->t_c, COORD_EXACT); + savescale = cifCurReadStyle->crs_scaleFactor; + transformp->t_f = CIFScaleCoord(transformp->t_f, COORD_EXACT); + if (savescale != cifCurReadStyle->crs_scaleFactor) + transformp->t_c *= (savescale / cifCurReadStyle->crs_scaleFactor); + + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseCommand -- + * + * Parse one CIF command and farm it out to a routine to handle + * that command. + * + * Results: + * None. + * + * Side effects: + * May modify the contents of cifReadCellDef by painting or adding + * new uses or labels. May also create new CellDefs. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFReadFile(file) + FILE *file; /* File from which to read CIF. */ +{ + /* We will use 1-word CIF numbers as keys in this hash table */ + CIFReadCellInit(1); + + if (cifCurReadStyle == NULL) + { + TxError("Don't know how to read CIF: nothing in tech file.\n"); + return; + } + TxPrintf("Warning: CIF reading is not undoable! I hope that's OK.\n"); + UndoDisable(); + + cifTotalWarnings = 0; + cifTotalErrors = 0; + CifPolygonCount = 0; + + cifInputFile = file; + cifReadScale1 = 1; + cifReadScale2 = 1; + cifParseLaAvail = FALSE; + cifLineNumber = 1; + cifReadPlane = (Plane *) NULL; + cifCurLabelType = TT_SPACE; + while (PEEK() != EOF) + { + if (SigInterruptPending) goto done; + CIFSkipBlanks(); + switch (PEEK()) + { + case EOF: + break; + case ';': + break; + case 'B': + (void) CIFParseBox(); + break; + case 'C': + (void) CIFParseCall(); + break; + case 'D': + TAKE(); + CIFSkipBlanks(); + switch (PEEK()) + { + case 'D': + (void) CIFParseDelete(); + break; + case 'F': + (void) CIFParseFinish(); + break; + case 'S': + (void) CIFParseStart(); + break; + default: + cifCommandError(); + break; + } + break; + case 'E': + (void) cifParseEnd(); + goto done; + case 'L': + (void) CIFParseLayer(); + break; + case 'P': + (void) CIFParsePoly(); + break; + case 'R': + (void) CIFParseFlash(); + break; + case 'W': + (void) CIFParseWire(); + break; + case '(': + (void) cifParseComment(); + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + (void) CIFParseUser(); + break; + default: + cifCommandError(); + break; + } + CIFSkipSemi(); + } + + CIFReadError("no \"End\" statement.\n"); + + done: + CIFReadCellCleanup(0); + UndoEnable(); +} diff --git a/cif/CIFread.h b/cif/CIFread.h new file mode 100644 index 00000000..62402161 --- /dev/null +++ b/cif/CIFread.h @@ -0,0 +1,201 @@ +/* + * CIFread.h -- + * + * This file contains definitions used by the CIF reader, but not + * by the CIF writing code. The definitions are only used internally + * to this module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/cif/CIFread.h,v 1.3 2010/08/25 17:33:55 tim Exp $ + */ + +#ifndef _CIFREAD_H +#define _CIFREAD_H + +#include "cif/CIFint.h" + +/* The structures below are built up by CIFreadtech.c to describe + * various styles for reading CIF. + */ + +/* The following structure describes a sequence of geometric + * operations used to produce information for a single Magic + * layer. There may be several of these structures for the + * same Magic layer; in that case, the results end up being + * OR'ed together. + */ + +typedef struct +{ + TileType crl_magicType; /* Magic layer to paint results. */ + CIFOp *crl_ops; /* List of operations to generate + * info for Magic layer. + */ + int crl_flags; /* Miscellaneous flags (see below). */ +} CIFReadLayer; + +/* The CIFReadLayer flags are: + * + * CIFR_SIMPLE: Means this layer is a simple one, coming from only + * a single OR operation, so it can be handled specially. + * CIFR_TEMPLAYER: Means this layer is a temporary CIF layer, and that + * the "crl_magicType" should be interpreted as a CIF layer. + * CIFR_TEXTLABELS: Means this layer is used for text-only layers, not to + * be moved or electrically connected to any other layer. + */ + +#define CIFR_SIMPLE 1 +#define CIFR_TEMPLAYER 2 +#define CIFR_TEXTLABELS 4 + +/* The following structure defines a complete CIF read-in style. + * The constant MAXCIFRLAYERS must be less than TT_MAXTYPES, and + * is used both as the largest number of distinct CIF layer names + * in all read styles, and as the larges number of distinct "layer" + * commands in any one read style. + */ + +#define MAXCIFRLAYERS (TT_MAXTYPES - 1) + +/* + * To avoid the large memory demands of maintaining all CIF styles in + * memory, we keep only the style names and re-read the technology file + * as necessary + */ + +typedef struct cifrkeep +{ + struct cifrkeep *crs_next; + char *crs_name; +} CIFReadKeep; + +typedef struct cifrstyle +{ + char crs_status; /* Status: Loaded, not loaded, or pending. */ + char *crs_name; /* Name for this style of CIF input. */ + TileTypeBitMask crs_cifLayers; + /* Mask of CIF layers understood in + * this style. + */ + int crs_nLayers; /* Number of CIFReadLayers involved. */ + int crs_scaleFactor; /* Number of CIF units per Magic unit. */ + int crs_multiplier; /* crs_scaleFactor / crs_multiplier = + * units in traditional centimicrons. + * So if crs_multiplier = 10, CIF units + * are in nanometers (millimicrons). + */ + int crs_gridLimit; /* Input is considered off-grid if on + * a pitch less than crs_gridLimit CIF + * units, and input will be snapped to + * grid rather than scaling the grid + * to accomodate the data. 0 = no limit. + */ + + TileType crs_labelLayer[MAXCIFRLAYERS]; + /* Gives the Magic layer to use for labels + * on each possible CIF layer. + */ + CIFReadLayer *crs_layers[MAXCIFRLAYERS]; + HashTable cifCalmaToCif; /* Table mapping from Calma layer numbers to + * CIF layers + */ + int crs_flags; /* Mask of boolean cif-reading options */ +} CIFReadStyle; + +/* option bitmasks used in crs_flags */ +#define CRF_IGNORE_UNKNOWNLAYER_LABELS 1 +#define CRF_NO_RECONNECT_LABELS 2 + +/* Methods to deal with fractional results of conversion from CIF to magic */ +/* units (see routine CIFScaleCoord() for details). */ + +#define COORD_EXACT 0 +#define COORD_HALF_U 1 +#define COORD_HALF_L 2 +#define COORD_ANY 3 + +/* For parsing CIF, we need to keep track of paths (wire locations + * or polygon boundaries. These are just linked lists of points. + */ + +#define CIF_ZERO 0 +#define CIF_LEFT 1 +#define CIF_UP 2 +#define CIF_RIGHT 3 +#define CIF_DOWN 4 +#define CIF_DIAG 5 + +/* Specific diagonal directions */ +#define CIF_DIAG_UL 5 +#define CIF_DIAG_UR 6 +#define CIF_DIAG_DL 7 +#define CIF_DIAG_DR 8 + +typedef struct cifpath +{ + Point cifp_point; /* A point in the path. */ + struct cifpath *cifp_next; /* The next point in the path, or NULL. */ +} CIFPath; + +#define cifp_x cifp_point.p_x +#define cifp_y cifp_point.p_y + +/* Procedures */ + +extern bool CIFParseBox(), CIFParseWire(), CIFParsePoly(); +extern bool CIFParseFlash(), CIFParseLayer(), CIFParseStart(); +extern bool CIFParseFinish(), CIFParseDelete(), CIFParseUser(); +extern bool CIFParseCall(), CIFParseTransform(), CIFParseInteger(); +extern bool CIFParsePath(), CIFParsePoint(), CIFParseSInteger(); +extern void CIFSkipToSemi(), CIFSkipSep(), CIFSkipBlanks(); +extern void CIFFreePath(), CIFCleanPath(); +extern void CIFReadCellInit(), CIFReadCellCleanup(); +extern LinkedRect *CIFPolyToRects(); +extern Transform *CIFDirectionToTrans(); +extern int CIFReadNameToType(); + +/* Variable argument procedures require complete prototype */ + +extern void CIFReadError(char *format, ...); +extern void CIFReadWarning(char *format, ...); + +/* Variables shared by the CIF-reading modules, see CIFreadutils.c + * for more details: + */ + +extern int cifReadScale1, cifReadScale2; +extern int cifNReadLayers; +extern Plane *cifReadPlane; +extern Plane **cifCurReadPlanes; +extern TileType cifCurLabelType; +extern CIFReadStyle *cifCurReadStyle; +extern bool cifSubcellBeingRead; +extern CellDef *cifReadCellDef; +extern FILE *cifInputFile; +extern bool cifParseLaAvail; +extern int cifParseLaChar; + +/* Macros to read characters, with one-character look-ahead. */ + +#define PEEK() ( cifParseLaAvail \ + ? cifParseLaChar \ + : (cifParseLaAvail = TRUE, \ + cifParseLaChar = getc(cifInputFile))) + +#define TAKE() ( cifParseLaAvail \ + ? (cifParseLaAvail = FALSE, cifParseLaChar) \ + : (cifParseLaChar = getc(cifInputFile))) + +#endif /* _CIFREAD_H */ diff --git a/cif/CIFsee.c b/cif/CIFsee.c new file mode 100644 index 00000000..7e742fae --- /dev/null +++ b/cif/CIFsee.c @@ -0,0 +1,490 @@ +/* CIFsee.c - + * + * This file provides procedures for displaying CIF layers on + * the screen using the highlight facilities. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFsee.c,v 1.5 2010/06/24 12:37:15 tim Exp $"; +#endif /* not lint */ + +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "cif/CIFint.h" +#include "textio/textio.h" +#include "utils/undo.h" + +/* The following variable holds the CellDef into which feedback + * is to be placed for displaying CIF. + */ + +static CellDef *cifSeeDef; + +/* Verbosity of warning messages */ +global int CIFWarningLevel = CIF_WARN_DEFAULT; + +typedef struct { + CellDef *paintDef; + int layer; +} PaintLayerData; + +typedef struct { + char *text; + int layer; + int style; +} SeeLayerData; + +/* + * ---------------------------------------------------------------------------- + * + * cifPaintDBFunc -- + * + * This routine paints CIF back into the database at the inverse + * scale at which it was generated. Otherwise, it is very much like + * cifPaintCurrentFunc() in CIFrdcl.c. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Paint is generated in the cell. + * ---------------------------------------------------------------------------- + */ + +int +cifPaintDBFunc(tile, pld) + Tile *tile; /* Tile of CIF information. */ + PaintLayerData *pld; +{ + Rect area; + int pNum; + TileType type = pld->layer; /* Magic type to be painted. */ + CellDef *paintDef = pld->paintDef; /* Cell to draw into. */ + int cifScale = CIFCurStyle->cs_scaleFactor; + PaintUndoInfo ui; + + /* Compute the area of the CIF tile, then scale it into + * Magic coordinates. + */ + + TiToRect(tile, &area); + area.r_xtop /= cifScale; + area.r_xbot /= cifScale; + area.r_ytop /= cifScale; + area.r_ybot /= cifScale; + + /* Check for degenerate areas (from rescale limiting) before painting */ + if ((area.r_xbot == area.r_xtop) || (area.r_ybot == area.r_ytop)) + return 0; + + ui.pu_def = paintDef; + for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) + if (DBPaintOnPlane(type, pNum)) + { + ui.pu_pNum = pNum; + DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile), + &area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui); + } + + return 0; /* To keep the search alive. */ +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFPaintLayer -- + * + * Generates CIF over a given area of a given cell, then + * paints the CIF layer back into the cell (or optionally, + * into a separate cell) as a magic layer. + * + * Results: + * None. + * + * Side effects: + * Highlight information is drawn on the screen. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFPaintLayer(rootDef, area, cifLayer, magicLayer, paintDef) + CellDef *rootDef; /* Cell for which to generate CIF. Must be + * the rootDef of a window. + */ + Rect *area; /* Area in which to generate CIF. */ + char *cifLayer; /* CIF layer to highlight on the screen. */ + int magicLayer; /* Magic layer to paint with the result */ + CellDef *paintDef; /* CellDef to paint into (may be NULL) */ +{ + int oldCount, i; + char msg[100]; + SearchContext scx; + PaintLayerData pld; + TileTypeBitMask mask, depend; + + /* Make sure the desired layer exists. */ + + if (!CIFNameToMask(cifLayer, &mask, &depend)) return; + + /* Paint directly into the root cellDef if passed a NULL paintDef*/ + pld.paintDef = (paintDef == NULL) ? rootDef : paintDef; + pld.layer = magicLayer; + + /* Flatten the area and generate CIF for it. */ + + CIFErrorDef = rootDef; + CIFInitCells(); + UndoDisable(); + CIFDummyUse->cu_def = rootDef; + GEO_EXPAND(area, CIFCurStyle->cs_radius, &scx.scx_area); + scx.scx_use = CIFDummyUse; + scx.scx_trans = GeoIdentityTransform; + (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, + cifHierCopyFunc, (ClientData) CIFComponentDef); + oldCount = DBWFeedbackCount; + CIFGen(CIFComponentDef, area, CIFPlanes, &depend, TRUE, TRUE); + DBCellClearDef(CIFComponentDef); + + /* Report any errors that occurred. */ + + if (DBWFeedbackCount != oldCount) + { + TxPrintf("%d problems occurred. See feedback entries.\n", + DBWFeedbackCount-oldCount); + } + + /* Paint back the chosen layer. */ + + UndoEnable(); + for (i = 0; i < CIFCurStyle->cs_nLayers; i++) + if (TTMaskHasType(&mask, i)) + DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect, + &CIFSolidBits, cifPaintDBFunc, (ClientData)&pld); + + DBWAreaChanged(rootDef, area, DBW_ALLWINDOWS, &mask); + DBReComputeBbox(rootDef); + DRCCheckThis(rootDef, TT_CHECKPAINT, area); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSeeFunc -- + * + * Called once for each tile that is to be displayed as feedback. + * This procedure enters the tile as feedback. Note: the caller + * must arrange for cifSeeDef to contain a pointer to the cell + * def where feedback is to be displayed. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * A new feedback area is created over the tile. The parameter + * "text" is associated with the feedback. + * ---------------------------------------------------------------------------- + */ + +int +cifSeeFunc(tile, sld) + Tile *tile; /* Tile to be entered as feedback. */ + SeeLayerData *sld; /* Layer and explanation for the feedback. */ +{ + Rect area; + + TiToRect(tile, &area); + + if (((area.r_xbot & 0x1) || (area.r_ybot & 0x1)) + && (CIFWarningLevel == CIF_WARN_ALIGN)) + { + TxError("Warning: Corner (%.1f, %.1f) has half-lambda placement.\n", + (float)area.r_xbot / (float)CIFCurStyle->cs_scaleFactor, + (float)area.r_ybot / (float)CIFCurStyle->cs_scaleFactor); + } + + DBWFeedbackAdd(&area, sld->text, cifSeeDef, CIFCurStyle->cs_scaleFactor, + sld->style | + (TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE))); + /* (preserve information about the geometry of a diagonal tile) */ + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFSeeLayer -- + * + * Generates CIF over a given area of a given cell, then + * highlights a particular CIF layer on the screen. + * + * Results: + * None. + * + * Side effects: + * Highlight information is drawn on the screen. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFSeeLayer(rootDef, area, layer) + CellDef *rootDef; /* Cell for which to generate CIF. Must be + * the rootDef of a window. + */ + Rect *area; /* Area in which to generate CIF. */ + char *layer; /* CIF layer to highlight on the screen. */ +{ + int oldCount, i; + char msg[100]; + SearchContext scx; + SeeLayerData sld; + TileTypeBitMask mask, depend; + + /* Make sure the desired layer exists. */ + + if (!CIFNameToMask(layer, &mask, &depend)) return; + + /* Flatten the area and generate CIF for it. */ + + CIFErrorDef = rootDef; + CIFInitCells(); + UndoDisable(); + CIFDummyUse->cu_def = rootDef; + GEO_EXPAND(area, CIFCurStyle->cs_radius, &scx.scx_area); + scx.scx_use = CIFDummyUse; + scx.scx_trans = GeoIdentityTransform; + (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, + cifHierCopyFunc, (ClientData) CIFComponentDef); + oldCount = DBWFeedbackCount; + CIFGen(CIFComponentDef, area, CIFPlanes, &depend, TRUE, TRUE); + DBCellClearDef(CIFComponentDef); + + /* Report any errors that occurred. */ + + if (DBWFeedbackCount != oldCount) + { + TxPrintf("%d problems occurred. See feedback entries.\n", + DBWFeedbackCount-oldCount); + } + + /* Display the chosen layer. */ + + (void) sprintf(msg, "CIF layer \"%s\"", layer); + cifSeeDef = rootDef; + sld.text = msg; + + for (i = 0; i < CIFCurStyle->cs_nLayers; i++) + { + if (TTMaskHasType(&mask, i)) + { + sld.layer = i; +#ifdef THREE_D + sld.style = CIFCurStyle->cs_layers[i]->cl_renderStyle + + TECHBEGINSTYLES; +#else + sld.style = STYLE_PALEHIGHLIGHTS; +#endif + DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect, + &CIFSolidBits, cifSeeFunc, (ClientData)&sld); + } + } + UndoEnable(); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFSeeHierLayer -- + * + * This procedure is similar to CIFSeeLayer except that it only + * generates hierarchical interaction information. + * + * Results: + * None. + * + * Side effects: + * CIF information is highlighed on the screen. If arrays is + * TRUE, then CIF that stems from array interactions is displayed. + * if subcells is TRUE, then CIF stemming from subcell interactions + * is displayed. If both are TRUE, then both are displayed. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFSeeHierLayer(rootDef, area, layer, arrays, subcells) + CellDef *rootDef; /* Def in which to compute CIF. Must be + * the root definition of a window. + */ + Rect *area; /* Area in which to generate CIF. */ + char *layer; /* CIF layer to be highlighted. */ + bool arrays; /* TRUE means show array interactions. */ + bool subcells; /* TRUE means show subcell interactions. */ +{ + int i, oldCount; + SeeLayerData sld; + char msg[100]; + TileTypeBitMask mask; + + /* Check out the CIF layer name. */ + + if (!CIFNameToMask(layer, &mask, NULL)) return; + + CIFErrorDef = rootDef; + oldCount = DBWFeedbackCount; + CIFClearPlanes(CIFPlanes); + if (subcells) + CIFGenSubcells(rootDef, area, CIFPlanes); + if (arrays) + CIFGenArrays(rootDef, area, CIFPlanes); + + /* Report any errors that occurred. */ + + if (DBWFeedbackCount != oldCount) + { + TxPrintf("%d problems occurred. See feedback entries.\n", + DBWFeedbackCount - oldCount); + } + + (void) sprintf(msg, "CIF layer \"%s\"", layer); + cifSeeDef = rootDef; + sld.text = msg; + + for (i = 0; i < CIFCurStyle->cs_nLayers; i++) + { + if (TTMaskHasType(&mask, i)) + { + sld.layer = i; +#ifdef THREE_D + sld.style = CIFCurStyle->cs_layers[i]->cl_renderStyle + + TECHBEGINSTYLES; +#else + sld.style = STYLE_PALEHIGHLIGHTS; +#endif + DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect, + &CIFSolidBits, cifSeeFunc, (ClientData)&sld); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFCoverageLayer -- + * + * This procedure reports the total area coverage of a CIF layer + * within the bounding box of the root CellDef. + * + * Results: + * None. + * + * Side effects: + * Prints results. + * + * ---------------------------------------------------------------------------- + */ + +typedef struct { + long long coverage; + Rect bounds; +} coverstats; + +void +CIFCoverageLayer(rootDef, area, layer) + CellDef *rootDef; /* Def in which to compute CIF coverage */ + Rect *area; /* Area in which to compute coverage */ + char *layer; /* CIF layer for coverage computation. */ +{ + coverstats cstats; + int i, scale; + long long atotal, btotal; + SearchContext scx; + TileTypeBitMask mask, depend; + float fcover; + int cifCoverageFunc(); + bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE; + + /* Check out the CIF layer name. */ + + if (!CIFNameToMask(layer, &mask, &depend)) return; + + CIFErrorDef = rootDef; + CIFInitCells(); + UndoDisable(); + CIFDummyUse->cu_def = rootDef; + + GEO_EXPAND(area, CIFCurStyle->cs_radius, &scx.scx_area); + + scx.scx_use = CIFDummyUse; + scx.scx_trans = GeoIdentityTransform; + (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, + cifHierCopyFunc, (ClientData) CIFComponentDef); + CIFGen(CIFComponentDef, area, CIFPlanes, &depend, TRUE, TRUE); + DBCellClearDef(CIFComponentDef); + + cstats.coverage = 0; + cstats.bounds.r_xbot = cstats.bounds.r_xtop = 0; + cstats.bounds.r_ybot = cstats.bounds.r_ytop = 0; + + for (i = 0; i < CIFCurStyle->cs_nLayers; i++) + if (TTMaskHasType(&mask, i)) + DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect, + &CIFSolidBits, cifCoverageFunc, + (ClientData) &cstats); + + /* Print results */ + + scale = CIFCurStyle->cs_scaleFactor; + + btotal = (long long)(area->r_xtop - area->r_xbot); + btotal *= (long long)(area->r_ytop - area->r_ybot); + btotal *= (long long)(scale * scale); + fcover = 0.0; + if (btotal > 0.0) fcover = (float)cstats.coverage / (float)btotal; + + atotal = (long long)(cstats.bounds.r_xtop - cstats.bounds.r_xbot); + atotal *= (long long)(cstats.bounds.r_ytop - cstats.bounds.r_ybot); + + TxPrintf("%s Area = %lld CIF units^2\n", doBox ? "Cursor Box" : + "Cell", btotal); + TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal); + TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage); + TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" : + "cell", 100.0 * fcover); +} + +int +cifCoverageFunc(tile, arg) + Tile *tile; + ClientData *arg; +{ + coverstats *cstats = (coverstats *)arg; + Rect r; + + TiToRect(tile, &r); + cstats->coverage += (long long)((r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot)); + GeoInclude(&r, &cstats->bounds); + + return(0); +} diff --git a/cif/CIFtech.c b/cif/CIFtech.c new file mode 100644 index 00000000..ed5e834f --- /dev/null +++ b/cif/CIFtech.c @@ -0,0 +1,2308 @@ +/* CIFtech.c - + * + * This module processes the portions of technology + * files pertaining to CIF, and builds the tables + * used by the CIF generator. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFtech.c,v 1.7 2010/10/20 20:34:19 tim Exp $"; +#endif /* not lint */ + +#include +#include /* for atof() */ +#include +#include +#include /* for pow() */ + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/tech.h" +#include "utils/utils.h" +#include "utils/styles.h" +#include "cif/CIFint.h" +#include "calma/calmaInt.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "cif/cif.h" +#include "drc/drc.h" /* For WRL's DRC-CIF extensions */ + +/* The following statics are used to keep track of things between + * calls to CIFTechLine. + */ + +static CIFLayer *cifCurLayer; /* Current layer whose spec. is being read. */ +static CIFOp *cifCurOp; /* Last geometric operation read in. */ +static bool cifGotLabels; /* TRUE means some labels have been assigned + * to the current layer. + */ + +/* The following is a TileTypeBitMask array with only the CIF_SOLIDTYPE + * bit set in it. + */ +TileTypeBitMask CIFSolidBits; + +/* Forward Declarations */ + +void cifTechStyleInit(); +bool cifCheckCalmaNum(); + +/* + * ---------------------------------------------------------------------------- + * + * cifTechFreeStyle -- + * + * This procedure frees memory for the current CIF style, and + * sets the current style to NULL. + * + * Results: + * None. + * + * Side effects: + * Memory is free'd. + * + * ---------------------------------------------------------------------------- + */ + +void +cifTechFreeStyle() +{ + int i; + CIFOp *op; + CIFLayer *layer; + + if (CIFCurStyle != NULL) + { + /* Destroy old style structure and free memory allocated to it */ + + for (i = 0; i < MAXCIFLAYERS; i++) + { + layer = CIFCurStyle->cs_layers[i]; + if (layer != NULL) + { + for (op = layer->cl_ops; op != NULL; op = op->co_next) + { + if (op->co_client != (ClientData)NULL) + { + switch (op->co_opcode) + { + case CIFOP_OR: + case CIFOP_BBOX: + case CIFOP_MAXRECT: + /* These options use co_client to hold a single */ + /* integer value, so it is not allocated. */ + break; + default: + freeMagic((char *)op->co_client); + break; + } + } + freeMagic((char *)op); + } + freeMagic((char *)layer); + } + } + freeMagic(CIFCurStyle); + CIFCurStyle = NULL; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * cifTechNewStyle -- + * + * This procedure creates a new CIF style at the end of + * the list of style and initializes it to completely + * null. + * + * Results: + * None. + * + * Side effects: + * A new element is added to the end of CIFStyleList, and CIFCurStyle + * is set to point to it. + * + * ---------------------------------------------------------------------------- + */ + +void +cifTechNewStyle() +{ + cifTechFreeStyle(); + cifTechStyleInit(); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifTechStyleInit -- + * + * Fill in the current cif input style structure with initial values + * + * ---------------------------------------------------------------------------- + */ + +void +cifTechStyleInit() +{ + int i; + + if (CIFCurStyle == NULL) + CIFCurStyle = (CIFStyle *) mallocMagic(sizeof(CIFStyle)); + + CIFCurStyle->cs_name = NULL; + CIFCurStyle->cs_status = TECH_NOT_LOADED; + + CIFCurStyle->cs_nLayers = 0; + CIFCurStyle->cs_scaleFactor = 0; + CIFCurStyle->cs_stepSize = 0; + CIFCurStyle->cs_gridLimit = 0; + CIFCurStyle->cs_reducer = 0; + CIFCurStyle->cs_expander = 1; + CIFCurStyle->cs_yankLayers = DBZeroTypeBits; + CIFCurStyle->cs_hierLayers = DBZeroTypeBits; + CIFCurStyle->cs_flags = 0; + for (i=0; ics_labelLayer[i] = -1; + for (i = 0; i < MAXCIFLAYERS; i++) + CIFCurStyle->cs_layers[i] = NULL; +} + + +/* + * ---------------------------------------------------------------------------- + * + * cifParseLayers -- + * + * Takes a comma-separated list of layers and turns it into two + * masks, one of paint layers and one of previously-defined CIF + * layers. + * + * Results: + * None. + * + * Side effects: + * The masks pointed to by the paintMask and cifMask parameters + * are modified. If some of the layers are unknown, then an error + * message is printed. + * + * ---------------------------------------------------------------------------- + */ + +void +cifParseLayers(string, style, paintMask, cifMask,spaceOK) + char *string; /* List of layers. */ + CIFStyle *style; /* Gives CIF style for parsing string.*/ + TileTypeBitMask *paintMask; /* Place to store mask of paint layers. If + * NULL, then only CIF layer names are + * considered. + */ + TileTypeBitMask *cifMask; /* Place to store mask of CIF layers. If + * NULL, then only paint layer names are + * considered. + */ + int spaceOK; /* are space layers permissible in this cif + layer? + */ +{ + TileTypeBitMask curCifMask, curPaintMask; + char curLayer[40], *p, *cp; + TileType paintType; + int i; + bool allResidues; + + if (paintMask != NULL) TTMaskZero(paintMask); + if (cifMask != NULL) TTMaskZero(cifMask); + + while (*string != 0) + { + p = curLayer; + + if (*string == '*') + { + allResidues = TRUE; + string++; + } + else + allResidues = FALSE; + + while ((*string != ',') && (*string != 0)) + *p++ = *string++; + *p = 0; + while (*string == ',') string += 1; + + /* See if this is a paint type. */ + + if (paintMask != NULL) + { + paintType = DBTechNameTypes(curLayer, &curPaintMask); + if (paintType >= 0) goto okpaint; + } + else paintType = -2; + +okpaint: + /* See if this is the name of another CIF layer. Be + * careful not to let the current layer be used in + * generating itself. Exact match is requred on CIF + * layer names, but the same name can appear multiple + * times in different styles. + */ + + TTMaskZero(&curCifMask); + if (cifMask != NULL) + { + for (i = 0; i < style->cs_nLayers; i++) + { + if (style->cs_layers[i] == cifCurLayer) continue; + if (strcmp(curLayer, style->cs_layers[i]->cl_name) == 0) + { + TTMaskSetType(&curCifMask, i); + } + } + } + + /* Make sure that there's exactly one match among cif and + * paint layers together. + */ + + if ((paintType == -1) + || ((paintType >= 0) && !TTMaskEqual(&curCifMask, &DBZeroTypeBits))) + { + TechError("Ambiguous layer (type) \"%s\".\n", curLayer); + continue; + } + if (paintType >= 0) + { + if (paintType == TT_SPACE && spaceOK ==0) + TechError("\"Space\" layer not permitted in CIF rules.\n"); + else + { + TileType rtype; + TileTypeBitMask *rMask; + + TTMaskSetMask(paintMask, &curPaintMask); + + /* Add residues from '*' notation */ + if (allResidues) + for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++) + { + rMask = DBResidueMask(rtype); + if (TTMaskHasType(rMask, paintType)) + TTMaskSetType(paintMask, rtype); + } + } + } + else if (!TTMaskEqual(&curCifMask, &DBZeroTypeBits)) + { + TTMaskSetMask(cifMask, &curCifMask); + } + else + { + HashEntry *he; + TileTypeBitMask *amask; + + he = HashLookOnly(&DBTypeAliasTable, curLayer); + if (he != NULL) + { + amask = (TileTypeBitMask *)HashGetValue(he); + TTMaskSetMask(paintMask, amask); + } + else + TechError("Unrecognized layer (type) \"%s\".\n", curLayer); + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFTechInit -- + * + * Called before loading a new technology. + * + * Results: + * None. + * + * Side effects: + * Clears out list of styles and resets the current style. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFTechInit() +{ + CIFKeep *style; + + /* Cleanup any old info. */ + + cifTechFreeStyle(); + + /* forget the list of styles */ + + for (style = CIFStyleList; style != NULL; style = style->cs_next) + { + freeMagic(style->cs_name); + freeMagic(style); + } + CIFStyleList = NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFTechStyleInit -- + * + * Called once at beginning of technology file read-in to + * initialize data structures. + * + * Results: + * None. + * + * Side effects: + * Just clears out the layer data structures. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFTechStyleInit() +{ + CalmaTechInit(); + + /* Create the TileTypeBitMask array with only the CIF_SOLIDTYPE bit set */ + TTMaskZero(&CIFSolidBits); + TTMaskSetType(&CIFSolidBits, CIF_SOLIDTYPE); + + cifCurOp = NULL; + cifCurLayer = NULL; + cifGotLabels = FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFTechLimitScale -- + * + * Determine if the scalefactor (ns / ds), applied to the current + * grid scaling, would result in a grid finer than the minimum + * resolution allowed by the process, as set by the "gridlimit" + * statement in the "cifoutput" section (note that the scaling + * depends on the output style chosen, and can be subverted by + * scaling while a fine-grid output style is active, then switching + * to a coarse-grid output style). + * + * Note that even if the scalefactor is larger than the minimum + * grid, it must be a MULTIPLE of the minimum grid, or else geometry + * can be generated off-grid. + * + * Results: + * TRUE if scaling by (ns / ds) would violate minimum grid resolution, + * FALSE if not. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFTechLimitScale(ns, ds) + int ns, ds; +{ + int gridup, scaledown; + int scale, limit, expand; + + if (CIFCurStyle == NULL) return FALSE; + + scale = CIFCurStyle->cs_scaleFactor; + limit = CIFCurStyle->cs_gridLimit; + expand = CIFCurStyle->cs_expander; + + if (limit == 0) limit = 1; + + gridup = limit * expand * ds; + scaledown = scale * ns * 10; + + if ((scaledown / gridup) == 0) return TRUE; + if ((scaledown % gridup) != 0) return TRUE; + + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFParseScale -- + * + * Read a scale value and determine scaleFactor and expander values + * + * Results: + * Returns the value for cs_scaleFactor + * + * Side effects: + * Alters the value of expander (pointer to cs_expander) + * + * ---------------------------------------------------------------------------- + */ + +int +CIFParseScale(true_scale, expander) + char *true_scale; + int *expander; +{ + char *decimal; + short places; + int n, d; + + decimal = strchr(true_scale, '.'); + + if (decimal == NULL) /* true_scale is integer */ + { + *expander = 1; + return atoi(true_scale); + } + else + { + *decimal = '\0'; + places = strlen(decimal + 1); + d = pow(10,places); + n = atoi(true_scale); + *decimal = '.'; + n *= d; + n += atoi(decimal + 1); + ReduceFraction(&n, &d); + *expander = d; + return n; + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * CIFTechLine -- + * + * This procedure is called once for each line in the "cif" + * section of the technology file. + * + * Results: + * TRUE if line parsed correctly; FALSE if fatal error condition + * encountered. + * + * Side effects: + * Sets up information in the tables of CIF layers, and + * prints error messages where there are problems. + * + * ---------------------------------------------------------------------------- + */ + +bool +CIFTechLine(sectionName, argc, argv) + char *sectionName; /* The name of this section. */ + int argc; /* Number of fields on line. */ + char *argv[]; /* Values of fields. */ +{ + TileTypeBitMask mask, tempMask, bloatLayers; + int i, j, l, distance; + CIFLayer *newLayer; + CIFOp *newOp = NULL; + CIFKeep *newStyle, *p; + char **bloatArg; + BloatData *bloats; + SquaresData *squares; + SlotsData *slots; + + if (argc <= 0) return TRUE; + else if (argc >= 2) l = strlen(argv[1]); + + /* See if we're starting a new CIF style. If not, make + * sure that the current (maybe default?) CIF style has + * a name. + */ + + if (strcmp(argv[0], "style") == 0) + { + if (argc != 2) + { + if ((argc != 4) || (strncmp(argv[2], "variant", 7))) + { + wrongNumArgs: + TechError("Wrong number of arguments in %s statement.\n", + argv[0]); + errorReturn: + if (newOp != NULL) + freeMagic((char *) newOp); + return TRUE; + } + } + for (newStyle = CIFStyleList; newStyle != NULL; + newStyle = newStyle->cs_next) + { + /* Here we're only establishing existence; */ + /* break on the first variant found. */ + + if (!strncmp(newStyle->cs_name, argv[1], l)) + break; + } + if (newStyle == NULL) + { + if (argc == 2) + { + newStyle = (CIFKeep *)mallocMagic(sizeof(CIFKeep)); + newStyle->cs_next = NULL; + newStyle->cs_name = StrDup((char **) NULL, argv[1]); + + /* Append to end of style list */ + if (CIFStyleList == NULL) + CIFStyleList = newStyle; + else + { + for (p = CIFStyleList; p->cs_next; p = p->cs_next); + p->cs_next = newStyle; + } + } + else /* Handle style variants */ + { + CIFKeep *saveStyle = NULL; + char *tptr, *cptr; + + /* 4th argument is a comma-separated list of variants. */ + /* In addition to the default name recorded above, */ + /* record each of the variants. */ + + tptr = argv[3]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) *cptr = '\0'; + newStyle = (CIFKeep *)mallocMagic(sizeof(CIFKeep)); + newStyle->cs_next = NULL; + newStyle->cs_name = (char *)mallocMagic(l + + strlen(tptr) + 1); + sprintf(newStyle->cs_name, "%s%s", argv[1], tptr); + + /* Remember the first variant as the default */ + if (saveStyle == NULL) saveStyle= newStyle; + + /* Append to end of style list */ + if (CIFStyleList == NULL) + CIFStyleList = newStyle; + else + { + for (p = CIFStyleList; p->cs_next; p = p->cs_next); + p->cs_next = newStyle; + } + + if (cptr == NULL) + break; + else + tptr = cptr + 1; + } + newStyle = saveStyle; + } + } + + if (CIFCurStyle == NULL) + { + cifTechNewStyle(); + CIFCurStyle->cs_name = newStyle->cs_name; + CIFCurStyle->cs_status = TECH_PENDING; + } + else if ((CIFCurStyle->cs_status == TECH_PENDING) || + (CIFCurStyle->cs_status == TECH_SUSPENDED)) + CIFCurStyle->cs_status = TECH_LOADED; + else if (CIFCurStyle->cs_status == TECH_NOT_LOADED) + { + if (CIFCurStyle->cs_name == NULL) + return (FALSE); + else if (argc == 2) + { + if (!strcmp(argv[1], CIFCurStyle->cs_name)) + CIFCurStyle->cs_status = TECH_PENDING; + } + else if (argc == 4) + { + /* Verify that the style matches one variant */ + + char *tptr, *cptr; + + if (!strncmp(CIFCurStyle->cs_name, argv[1], l)) + { + tptr = argv[3]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) *cptr = '\0'; + if (!strcmp(CIFCurStyle->cs_name + l, tptr)) + { + CIFCurStyle->cs_status = TECH_PENDING; + return TRUE; + } + if (cptr == NULL) + return TRUE; + else + tptr = cptr + 1; + } + } + } + } + return (TRUE); + } + + /* Only continue past this point if we are loading the cif output style */ + if (CIFCurStyle == NULL) return FALSE; + if ((CIFCurStyle->cs_status != TECH_PENDING) && + (CIFCurStyle->cs_status != TECH_SUSPENDED)) + return TRUE; + + /* Process scalefactor lines next. */ + + if (strcmp(argv[0], "scalefactor") == 0) + { + if ((argc < 2) || (argc > 4)) goto wrongNumArgs; + CIFCurStyle->cs_scaleFactor = CIFParseScale(argv[1], + &CIFCurStyle->cs_expander); + + /* + * The "nanometers" keyword multiplies the expander by 10. + * Any reducer value and keyword "calmaonly" are now both ignored. + */ + + if (argc >= 3) + { + if (strncmp(argv[argc - 1], "nanom", 5) == 0) + CIFCurStyle->cs_expander *= 10; + else if (strncmp(argv[argc - 1], "angstr", 6) == 0) + CIFCurStyle->cs_expander *= 100; + } + + CIFCurStyle->cs_reducer = 1; /* initial value only */ + + if (CIFCurStyle->cs_scaleFactor <= 0) + { + CIFCurStyle->cs_scaleFactor = 0; + TechError("Scalefactor must be a strictly positive value.\n"); + goto errorReturn; + } + return TRUE; + } + + /* New for magic-7.3.100---allow GDS database units to be other */ + /* than nanometers. Really, there is only one option here, which */ + /* is "units angstroms". This option does not affect CIF output, */ + /* whose units are fixed at centimicrons. */ + + if (strcmp(argv[0], "units") == 0) + { + if (argc != 2) goto wrongNumArgs; + if (!strncmp(argv[1], "angstr", 6)) + CIFCurStyle->cs_flags |= CWF_ANGSTROMS; + return TRUE; + } + + if (strcmp(argv[0], "stepsize") == 0) + { + if (argc != 2) goto wrongNumArgs; + CIFCurStyle->cs_stepSize = atoi(argv[1]); + if (CIFCurStyle->cs_stepSize <= 0) + { + TechError("Step size must be positive integer.\n"); + CIFCurStyle->cs_stepSize = 0; + } + return TRUE; + } + + /* Process "gridlimit" line next. */ + if (strncmp(argv[0], "grid", 4) == 0) + { + if (StrIsInt(argv[1])) + { + CIFCurStyle->cs_gridLimit = atoi(argv[1]); + if (CIFCurStyle->cs_gridLimit < 0) + { + TechError("Grid limit must be a positive integer.\n"); + CIFCurStyle->cs_gridLimit = 0; + } + } + else + TechError("Unable to parse grid limit value.\n"); + + return TRUE; + } + + /* Process "variant" lines next. */ + + if (strncmp(argv[0], "variant", 7) == 0) + { + int l; + char *cptr, *tptr; + + /* If our style variant is not one of the ones declared */ + /* on the line, then we ignore all input until we */ + /* either reach the end of the style, the end of the */ + /* section, or another "variant" line. */ + + if (argc != 2) goto wrongNumArgs; + tptr = argv[1]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) + { + *cptr = '\0'; + for (j = 1; isspace(*(cptr - j)); j++) + *(cptr - j) = '\0'; + } + + if (*tptr == '*') + { + CIFCurStyle->cs_status = TECH_PENDING; + return TRUE; + } + else + { + l = strlen(CIFCurStyle->cs_name) - strlen(tptr); + if (!strcmp(tptr, CIFCurStyle->cs_name + l)) + { + CIFCurStyle->cs_status = TECH_PENDING; + return TRUE; + } + } + + if (cptr == NULL) + break; + else + tptr = cptr + 1; + } + CIFCurStyle->cs_status = TECH_SUSPENDED; + } + + /* Anything below this line is not parsed if we're in TECH_SUSPENDED mode */ + if (CIFCurStyle->cs_status != TECH_PENDING) return TRUE; + + newLayer = NULL; + if ((strcmp(argv[0], "templayer") == 0) + || (strcmp(argv[0], "layer") == 0)) + { + if (CIFCurStyle->cs_nLayers == MAXCIFLAYERS) + { + cifCurLayer = NULL; + TechError("Can't handle more than %d CIF layers.\n", MAXCIFLAYERS); + TechError("Your local Magic wizard can fix this.\n"); + goto errorReturn; + } + if (argc != 2 && argc != 3) + { + cifCurLayer = NULL; + goto wrongNumArgs; + } + newLayer = CIFCurStyle->cs_layers[CIFCurStyle->cs_nLayers] + = (CIFLayer *) mallocMagic(sizeof(CIFLayer)); + CIFCurStyle->cs_nLayers += 1; + if ((cifCurOp == NULL) && (cifCurLayer != NULL) && !cifGotLabels) + { + TechError("Layer \"%s\" contains no material.\n", + cifCurLayer->cl_name); + } + newLayer->cl_name = NULL; + (void) StrDup(&newLayer->cl_name, argv[1]); + newLayer->cl_ops = NULL; + newLayer->cl_flags = 0; + newLayer->cl_calmanum = newLayer->cl_calmatype = -1; + newLayer->min_width = 0; /* for growSlivers */ +#ifdef THREE_D + newLayer->cl_height = 0.0; + newLayer->cl_thick = 0.0; + newLayer->cl_renderStyle = STYLE_PALEHIGHLIGHTS - TECHBEGINSTYLES; +#endif + if (strcmp(argv[0], "templayer") == 0) + newLayer->cl_flags |= CIF_TEMP; + cifCurLayer = newLayer; + cifCurOp = NULL; + cifGotLabels = FALSE; + + /* Handle a special case of a list of layer names on the layer + * line. Turn them into an OR operation. + */ + + if (argc == 3) + { + cifCurOp = (CIFOp *) mallocMagic(sizeof(CIFOp)); + cifCurOp->co_opcode = CIFOP_OR; + cifParseLayers(argv[2], CIFCurStyle, &cifCurOp->co_paintMask, + &cifCurOp->co_cifMask,FALSE); + cifCurOp->co_distance = 0; + cifCurOp->co_next = NULL; + cifCurOp->co_client = (ClientData)NULL; + cifCurLayer->cl_ops = cifCurOp; + } + return TRUE; + } + + if (strcmp(argv[0], "labels") == 0) + { + if (cifCurLayer == NULL) + { + TechError("Must define layer before giving labels it holds.\n"); + goto errorReturn; + } + if (cifCurLayer->cl_flags & CIF_TEMP) + TechError("Why are you attaching labels to a temporary layer?\n"); + if (argc != 2) goto wrongNumArgs; + DBTechNoisyNameMask(argv[1], &mask); + for (i=0; ics_labelLayer[i] = CIFCurStyle->cs_nLayers-1; + } + cifGotLabels = TRUE; + return TRUE; + } + + if ((strcmp(argv[0], "calma") == 0) || (strncmp(argv[0], "gds", 3) == 0)) + { + if (cifCurLayer == NULL) + { + TechError("Must define layers before giving their Calma types.\n"); + goto errorReturn; + } + if (cifCurLayer->cl_flags & CIF_TEMP) + TechError("Why assign a Calma number to a temporary layer?\n"); + if (argc != 3) goto wrongNumArgs; + if (!cifCheckCalmaNum(argv[1]) || !cifCheckCalmaNum(argv[2])) + TechError("Calma layer and type numbers must be 0 to %d.\n", + CALMA_LAYER_MAX); + cifCurLayer->cl_calmanum = atoi(argv[1]); + cifCurLayer->cl_calmatype = atoi(argv[2]); + return TRUE; + } + if (strcmp(argv[0], "min-width") == 0) /* used in growSliver */ + { + if (cifCurLayer == NULL) + { + TechError("Must define layers before assigning a minimum width.\n"); + goto errorReturn; + } + if (argc != 2) goto wrongNumArgs; + cifCurLayer->min_width = atoi(argv[1]); + CIFCurStyle->cs_flags |= CWF_GROW_SLIVERS; + return TRUE; + } + + if (strcmp(argv[0], "render") == 0) /* used by specialopen wind3d client */ + { +#ifdef THREE_D + float height, thick; + int i, style, lcnt; + CIFLayer *layer; + + if (argc != 5) goto wrongNumArgs; + + cifCurLayer = NULL; /* This is not in a layer definition */ + + style = DBWTechParseStyle(argv[2]); + if (style < 0) + { + TechError("Error: Bad render style for CIF layer.\n"); + goto errorReturn; + } + + if (!StrIsNumeric(argv[3]) || !StrIsNumeric(argv[4])) + { + TechError("Syntax: render + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

addcommandentry

+
+Generate a new frame for command-line entry. +
+ +

Usage:

+
+ addcommandentry framename

+
+ where framename is the Tk pathname of a frame. +
+
+ +

Summary:

+
+ The addcommandentry command is used with the GUI wrapper in + magic version 7.3. It adds a narrow text entry frame to the bottom + of the window. This frame duplicates the output of the Tk console, + and can be used as an alternative console from which to enter + command-line commands. The framename is the Tk path name + of the frame holding the layout window. By default these are + named .layout1, .layout2, etc., for each call to + openwrapper.

+ + The command entry window has a prompt with the name of the Tk frame, + e.g., "layout1>", and all + window commands entered into this area will be relative to the + associated layout window. +

+ +

Implementation Notes:

+
+ addcommandentry is implemented as a Tcl procedure defined + in the GUI wrapper script. It is only available when the wrapper + is used, that is, when magic is invoked with argument -w. +
+ +

See Also:

+
+ deletecommandentry
+ openwrapper
+
+ +

+ + + +
Return to command index +
+

Last updated: October 5, 2004 at 3:19am

+ + diff --git a/doc/html/addpath.html b/doc/html/addpath.html new file mode 100644 index 00000000..9fa5ad05 --- /dev/null +++ b/doc/html/addpath.html @@ -0,0 +1,72 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

addpath

+
+Append to current search path +
+ +

Usage:

+
+ addpath [path]

+
+ where path is the path of a directory to add to the + list of directories searched for layout cells, relative to + the current working directory. +
+
+ +

Summary:

+
+ The addpath command is used to control which directories + magic searches when attempting to read an undefined cell. It + can only be used to append new directories to the existing + search path (see below). This command is most often used when + groups of subcells such as a standard-cell library or padframe + library is kept in a separate place from the rest of the layout. + In such cases it is convenient to put this command in the + .magic file in the layout directory to ensure that all + cells required by the layout are accessible at runtime. +
+ +

Implementation Notes:

+
+ addpath is a magic built-in command. It is + retained for backwards compatibility, but is superceded by + the path command, which allows complete control over + the layout search path contents, as well as other search + paths used by magic. +
+ +

See Also:

+
+ path
+ getcell
+
+ +

+ + + +
Return to command index +
+

Last updated: October 3, 2004 at 6:53am

+ + diff --git a/doc/html/array.html b/doc/html/array.html new file mode 100644 index 00000000..3b78ef85 --- /dev/null +++ b/doc/html/array.html @@ -0,0 +1,118 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

array

+
+Array everything in the current selection +
+ +

Usage:

+
+ array option

+
+ where option is one of the following: +
+
xsize ysize +
Array the selection with xsize copies in the x + (horizontal) direction and ysize copies in the y + (vertical) direction. Array pitch is determined by the + current cursor box. +
xlo xhi ylo yhi +
Array the selection with indices xlo, xhi, ylo, and + yhi inclusive. Thus, (xhi - xlo + 1) + copies will be created in the x direction and + (yhi - ylo + 1) copies will be created in the + y direction. Arrayed cell uses will be numbered according + to the indices. Array pitch is determined by the current + cursor box. +
count [[xlo] xhi [ylo] yhi] +
With no arguments, returns the array indices of the currently + selected cell. With arguments, is equivalent to the first two + options (see above). +
width [value] +
With no arguments, returns the array spacing in x of + the currently selected cell. With arguments, redefines the + spacing in x between cells in the array. +
height [value] +
With no arguments, returns the array spacing in y of + the currently selected cell. With arguments, redefines the + spacing in y between cells in the array. +
pitch [x y] +
With no arguments, returns the array spacing in x and + y of the currently selected cell. With arguments, + redefines the spacing in x and y between cells + in the array. +
position [x y] +
With no arguments, returns the position of the array origin. + With arguments, redefines the array origin. +
help +
Print help information +
+
+
+ +

Summary:

+
+ The array command creates multiple copies of the current + paint selection. In the case of selected paint, only the first + two options are available, and the function makes multiple copies + of the selected paint in the x and/or y direction(s). + In the case of selected cells, the cell is copied multiple times + but is maintained in the database as an array type, rather + than multiple individual uses. As an array type, certain + functions such as move or copy operate on the array + as a single unit, and subsequent calles to the array + command may resize the array.

+ + The cursor box defines the pitch between cells or paint copies + in the array. The height of the box is the pitch in y, + and the width of the box is the pitch in x.

+ + The Tcl version allows useful constructs on the command line + such as: +

+ array width [expr {1 + [array width]}]
+ move s [array height] +
+ The first example expands the pitch of the array by 1 unit in + the x direction without requiring explicitly sizing the + cursor box to match the array pitch. The second example moves + the array down by the y + +

Implementation Notes:

+
+ array is implemented as a magic built-in command. + Command options which return values from a selected array + generate Tcl results in the Tcl version of magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 2:20pm

+ + diff --git a/doc/html/box.html b/doc/html/box.html new file mode 100644 index 00000000..19bfe369 --- /dev/null +++ b/doc/html/box.html @@ -0,0 +1,147 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

box

+
+Move box dist units in direction or (with no arguments) show box size. +
+ +

Shortcuts:

+
+ Key macro b implements the command box (with no arguments), + which prints information about the box to the console (terminal + stdout). +
+ +

Usage:

+
+ box [option]

+
+ where option is one of the following: +
+
[direction + [distance]] +
Move the box in the indicated direction by the indicated distance. +
width [width] +
Set or return box width +
height [height] +
Set or return box height +
size [width height] +
Set or return box size +
position [llx lly] [-edit] +
Set or return box position +
values [llx lly urx ury] [-edit] +
Set or return box coordinates. +
move direction distance|cursor +
Move box position +
grow direction distance +
Expand box size +
shrink direction distance +
Shrink box size +
corner direction distance|cursor +
Reposition a box corner +
exists +
Is the cursor box present? +
help +
Print help information +
+
+
+ +

Summary:

+
+ The box command, with no arguments, prints information about + the current position and size of the cursor box to the console + (terminal stdout). The output shows the lower-left + and upper-right coordinates of the box, plus the box width, height, + and area. These coordinates and dimensions are shown both in + microns and in lambda units. If the internal grid has been + subdivided to a finer grid than lambda, then internal units will + also be reported.

+ + With arguments, the box command adjusts the position and + dimensions of the cursor box as outlined in the Usage section + (see above). The -edit switch causes coordinate values + to be reported relative to the origin of the current edit cell, + if the edit cell is not the topmost cell in the layout window.

+ + For a discussion of valid distances, see the page + distance. This includes + dimensional values such as width and height, e.g., +

+ box width 1.2um +
+ Note that because metric dimensions do not always match lambda + dimensions, the dimension may be rounded down to the nearest + lambda. This is important in case this use of box is + intended to meet some DRC requirement. For the options move + and corner, the distance may be the keyword + "cursor", indicating that the box should be moved or + the corner repositioned to the position of the cursor. + These versions of the command implement the standard mouse + button bindings for the "box tool" in layout windows.

+ + For a discussion of valid directions, see the page + direction. + Note that special cases box grow center and + box shrink center will cause the box to expand or shrink on + all sides, whereas box move center is nonfunctional. + Also, the box corner command expects the direction to be + a nonmanhattan direction (ur, bl, etc.), indicating + the corner to be repositioned. +

+ +

Implementation Notes:

+
+ box is implemented as a magic built-in command. + Command options with keywords and no arguments return Tcl results in + the Tcl version of magic. However, to be backwardly compatible + with versions of magic prior to 7.3, the box command with + no arguments prints information directly to stdout (the + command-line console). The separate option box values is + provided to return the two box coordinates (lower-left and upper-right) + as a Tcl list.

+ + The use of returned Tcl values allows various useful constructs on the + command-line, such as: +

+ box move e [box width] + box height [box width] +
+ The first example moves the box to the right by the width of the box, + while the second example makes the box square by adjusting the height + to match the width. +
+ +

See Also:

+
+ snap + scalegrid +
+ +

+ + + +
Return to command index +
+

Last updated: November 8, 2004 at 2:53pm

+ + diff --git a/doc/html/calma.html b/doc/html/calma.html new file mode 100644 index 00000000..770aa901 --- /dev/null +++ b/doc/html/calma.html @@ -0,0 +1,189 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

gds, calma

+
+Read GDSII input or generate GDSII output. +
+ +

Usage:

+
+ gds [option]

+ calma [option]

+
+ where option is one of the following: +
+
help +
Print usage information +
arrays [yes|no] +
Output arrays as individual subuses (like in CIF). Default + is "no". Normally there is no reason to do this. +
contacts [yes|no] +
Causes contacts to be written to the GDS file as subcell + arrays (experimental, introduced in version 7.3.55). This + method can produce very efficient output compared to writing + each contact cut square separately. +
flatten [yes|no] +
Flatten simple cells (e.g., contacts) on input. This helps + magic to use its contact-area representation of contacts, + and can also avoid situations where contacts are lost or + translated to "generic" types because the arrayed part of + the contacts is missing one or more residue layers. +
ordering [yes|no] +
Forces post-ordering of subcells read from a GDS file; that + is, if a cell use is encountered before it is defined, magic + will read through the remainder of the file until it finds + the definition, read it, and then return to the original file + position to continue reading. This option is always enabled + when using gds flatten. Otherwise, the default behavior + is ordering no to avoid lengthy searches through the + GDS stream file. +
labels [yes|no] +
Cause labels to be output when writing GDSII. Default + is "yes". Normally there is no reason not to do this. +
lower [yes|no] +
Allow both upper and lower case in labels. Default is "yes". +
read file +
Read GDSII format from file file into the edit cell. + If file does not have a file extension, then magic + searches for a file named file, file.gds, + file.gds2, or file.strm. +
readonly [yes|no] +
Set cell as "read-only". This has the effect of marking each + cell definition (using the property method) with the + start and end positions of the cell definition in the input + file. In subsequent output, the cell definition will be + transferred verbatim from the input to the output file. This + is useful for 3rd-party standard cells or pad cells where the + original GDS is trusted and it is desirable to bypass the + boolean operators of magic's GDS reader and writer to + prevent the layout from being altered. Note that "read-only" + layout can be written to a .mag file, but the + contents of this file are representational only. It can + be useful to keep a simplified respresentation in the case + of pad cells or digital standard cells, for example, by + reading them using a GDS input style that defines only metal + layers. +
rescale [yes|no] +
Allow or disallow internal grid subdivision while reading + GDS input. Default is "yes". Normally, one wants to allow + rescaling to ensure that the GDS is displayed exactly as it + is in the input file. Occasionally, however, the GDS input + is on a very fine scale, such as nanometers, and it is + preferable to snap the input to lambda boundaries rather + than to subsplit the internal grid to such a fine value. + The "cif limit" function may also be used to limit + grid subdivision to a minimum value. +
warning [option] +
Set warning information level. "option" may be one + of the following: +
+
default +
The default setting is equivalent to all the other + options (align, limit, redirect, + and none) being disabled. +
align +
Generate warnings during a "cif see" command + if the alignment of geometry is on fractional lambda. + Normally, magic allows contacts to be drawn at + half-lambda positions. If this violates DRC requirements + for the minimum output grid, this warning setting can be + used to detect such violations. +
limit +
Limit warnings to the first 100 warnings or errors only. +
redirect [file] +
Redirect all warnings to an output file named file. + If file is not given, then redirection is disabled. +
none +
Do not produce any warning messages on GDS input. +
+
write file +
Output GDSII format to "file" for the window's root cell. +
polygon subcells [yes|no] +
Put non-Manhattan polygons into subcells. Default is "no". + Normally this option is not needed. However, input layout + that defines a number of angled wires, particularly those + that are closely spaced, can cause magic to generate + literally millions of internal tiles. This tends to be + true in particular for corner cells in padframes for deep + submicron feature sizes, where the angled corners are + required to meet the DRC specification. When set to "yes", + each polygon encountered in the GDS input is placed in its + own uniquely-named subcell. This prevents interations with + other polygons on the same plane and so reduces tile splitting. +
+
+
+ +

Summary:

+
+ The gds command reads or produces GDSII output (also known as + "stream" output, or "calma" output after the name of the company + that invented the format), or sets various parameters affecting + the GDS input and output. In magic, the GDS read and write routines + are a subset of the CIF read and write routines, and so it is + important to note that certain cif command options (q.v.) also + affect GDS input and output. In particular, cif istyle and + cif ostyle set the input and output styles from the technology + file, respectively.

+ + If no option is given, a CALMA GDS-II stream file is produced for the + root cell, with the default name of the root cell definition and the + filename extension ".gds".

+

+ +

Implementation Notes:

+
+ gds is implemented as a built-in function in magic. + The calma command is an alias for gds and is + exactly equivalent. +
+ +

Bugs:

+
+
    +
  • The cif command options that affect GDS input and output + should really be duplicates as options of the GDS command. +
  • GDS input is "interpreted" through boolean operations in the + technology file definition, and so it is not guaranteed that + all input will be read correctly. +
  • Not all non-Manhattan geometry is read correctly. +
  • The input can be fouled up if the magic grid is rescaled during + input. This error can be avoided by scaling the grid prior + to GDS read-in. +
  • "polygon subcells" in GDS creates a duplicate image of the + layout read into the subcells; this needs to be fixed. +
+
+ +

See Also:

+
+ cif
+
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 3:17pm

+ + diff --git a/doc/html/caption.html b/doc/html/caption.html new file mode 100644 index 00000000..c48781b8 --- /dev/null +++ b/doc/html/caption.html @@ -0,0 +1,63 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

caption

+
+Configures the titlebar of the GUI wrapper on a layout window +
+ +

Usage:

+
+ caption layoutwindow

+
+ where layoutwindow is the Tk pathname of the layout + window (not the top-level frame). +
+
+ +

Summary:

+
+ The caption command is used by the GUI wrapper script and + is normally not a user command. It configures the titlebar of + the wrapper frame in a way that is similar to the titlebar in + the original (non-Tcl, non-GUI) versions of magic. + The style and contents of the titlebar may be changed by redefining + this procedure in Tcl. +
+ +

Implementation Notes:

+
+ caption is implemented as a Tcl script in the GUI wrapper. +
+ +

See Also:

+
+ windowcaption
+
+ +

+ + + +
Return to command index +
+

Last updated: October 3, 2004 at 8:01am

+ + diff --git a/doc/html/cellmanager.html b/doc/html/cellmanager.html new file mode 100644 index 00000000..eec725c6 --- /dev/null +++ b/doc/html/cellmanager.html @@ -0,0 +1,169 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

cellmanager

+
+Invoke the cell manager GUI window +
+ +

Shortcuts:

+
+ Menu option Options->Cell Manager implements the command + cellmanager create in the GUI layout window. This menu + item has a checkbox and is used both to open and to close the + Cell Manager window. +
+ +

Usage:

+
+ cellmanager [option]

+
+ where option is optional and may be one of the following: +
+
update +
The default option if no option is given. Update the + cell manager to reflect the current state of the layout. +
create +
Create the cell manager window. This option is normally + called only from the "Cell Manager" button in the + magic GUI layout window. +
+
+
+ +

Summary:

+
+ The cellmanager command is normally invoked automatically + from inside the GUI wrapper procedures and tag callbacks, and + normally should not be called directly from the command line. +
+ +
+
+
+ Figure 1. The Cell Manager Window +
+
+ +
+ The Cell Manager window (see above) is a separate top-level window + with Tk pathname ".cellmgr". It consists of a tree widget + (defined in the Tcl package "BLT") display in the center, a message + window and button on the bottom, and a row of menu buttons at the + top.

+ + The Cell Manager displays cells for everything stored in the layout + database. As such, it is only necessary to have a single cell + manager for all layout windows. However, commands such as "Load", + "Edit", etc., apply to a specific window. When a new layout window + is created, rather than generate a new Cell Manager window, the + new window is added to the list of "target windows". The currently + selected target window is displayed at the bottom of the Cell + Manager. This is also a button that can be used to select a new + target window. If only one layout window is present, the target is + declared "default" and may be left alone.

+ + The hierarchical tree view shows all of the instances (cell + uses) in a layout. When first invoked, the top-level cell only + is shown, with a "folder" icon showing that this cell contains + uses. By clicking on the "+" symbol next to the folder icon, + the tree view is expanded to show the cell instances used by the + top-level layout cell. This expansion may continue until a cell + instance is found that does not contain any descendents. Note that + the name displayed is the name of the cell definition, with + the instance number given in parentheses after the name. If + the instance name is non-default (e.g., because it came from a + 3rd party vendor database or was altered with the identify + command), the full name of the instance is shown in the + parentheses. If the instance is arrayed, the array indices are + shown in brackets ("[]") after the instance number or name. +

+ + The use of tag callbacks on commands allows the cell manager to + be updated in response to certain commands entered on the command + line. The cell manager will be updated in response to a + "load" or "getcell" command.

+ + The menu buttons perform certain functions based on the selection + made in the tree window. These functions are as follows: +

+
+
Load +
load the selected cell into the window. The load + command is invoked and passed the cell definition name + of the selected cell instance. Note that this menu + function operates on the cell definition of the + selected cell instance. +
Edit +
edit the selected cell instance. The cell instance + selected becomes the current edit cell. +
Expand +
expand (or unexpand, if already expanded) the selected + cell instance. +
Zoom +
change the current view of the layout so that it is + centered on the selected cell instance, and scaled so + that the cell instance fills the screen. +
+
+
+ +

Implementation Notes:

+
+ cellmanager is implemented as a Tcl procedure in the GUI wrapper + script. Because layouts with complicated hierarchy can cause + magic to run very slowly due to processing in the cell + manager window, this window does not exist on startup and is + deleted entirely when turned off in the "Options" menu of + the GUI wrapper layout window.

+ cellmanager uses the tree display widget from the tcl package + "BLT". Therefore, in order to see the Cell Manager window, it is + necessary to have BLT installed on the system. If BLT is not + installed, no option for "Cell Manager" will appear in the "Options" + menu of the GUI wrapper window.

+ cellmanager depends on the GUI wrapper window, as it is defined + in the wrapper script. Therefore, to use the cell manager, it is + necessary to invoke magic with the option "-w". +

+ +

Bugs:

+
+ The "Expand" function should expand everything above the selected + cell. Otherwise, if something higher up in the hierarchy is unexpanded, + the selected cell will not be expanded. +
+ +

See Also:

+
+ load
+ edit
+ expand
+ zoom
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 12:47am

+ + diff --git a/doc/html/cellname.html b/doc/html/cellname.html new file mode 100644 index 00000000..c0af2524 --- /dev/null +++ b/doc/html/cellname.html @@ -0,0 +1,146 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

cellname

+
+Operations on cell definitions. +
+ +

Usage:

+
+ cellname option

+
+ where option is one of the following: +
+
[list] children [name] +
List all of the children definitions of cell name, + or the children of the currently selected cell instance. +
[list] parent [name] +
List the parent cell definition of cell name, + or the parent of the currently selected cell instance. +
[list] exists|self [name] +
Returns the name of the cell if the cell exists, or false + (0) if the cell does not exist (is not loaded into the + database; the cell may still exist on disk). If name + is not present, returns the name of the currently selected + cell. +
[list] allcells +
List all of the cells in the database. Note that expansion + is not automatic, so cells that are not expanded are not + searched. +
[list] topcells +
List the name of the top-level cell or cells. Note that + the cells are searched in the whole database, so multiple + cells may be returned, regardless of what cell is the + topmost cell in the layout window. For that, use + cellname window (see below). +
[list] window +
List the name of the topmost cell in the window. If only + one window exists, it is implicit. If more than one + window exists, the command operates on the window from + which the command was called if the ":" macro + was used to invoke the command. Otherwise, the window + can be specified as the command (q.v. tk_path_name). +
create name +
Create a new cell definition with name name. This + is most often used with scripts, where it is not necessary + or desirable to load the cell into the window. Note that + this command does not search the layout search path for a + cell named name.mag, so it can be used to replace + a cell which exists on disk but is not currently loaded. +
rename name newname +
Change the name of the cell definition name to + newname. +
delete name +
Delete the cell definition with name name. If cell + name is a descendent of another cell, the command + will be prohibited. If the cell name is currently + the topmost cell in the window, the window will be loaded + with default cell "(UNNAMED)". +
flags +
Reports flag settings for the cell. Flags which are reported + are "available", "modified", and "readonly". Flag "available" + is true if the cell has been loaded into the database. Flag + "modified" is true if layout changes have been made to the + cell. Flag "readonly" is true if the cell has been locked to + prevent edits. +
writeable [true|false] +
Option writeable false makes the current cell + read-only and therefore prevents any edits from being + written to disk. If magic is compiled with file-locking, + then any advisory lock on the file is released. + Option writeable true makes the current cell read-write. + If magic is compiled with file-locking, then magic attempts + to grab an advisory lock on the file. If a lock is already + held on the file, then the command cannot be executed, and the + cell remains read-only. Option writeable with no other + arguments returns the state of the cell (roughly equivalent to + cellname flags readonly). +
+
+
+ +

Summary:

+
+ The cellname command performs various operations on + cell definitions. For the first four options listed above, + cellname lists cells by their relationship to cell + name, or to the current selection if no name + is given. The optional argument list returns the + result as a list. In particular, in the Tcl version of + magic, this list is a Tcl result that may be operated on + by Tcl procedures. +
+ +

Implementation Notes:

+
+ cellname is implemented as a built-in function in magic + The Tcl version of magic returns Tcl results when the "list" + option is present. instance is essentially an alias for the + cellname command, and takes the same options, but references + are to cell instances rather that cell definitions (q.v.).

+ + The command option cellname list exists is nonsensical from + the standpoint of the end-user (if the cell is selected, of course + it exists). However, it is a very useful function for Tcl scripts + to determine the name of the cell that is currently selected.

+ + The cellname command replaces a number of commands that + briefly appeared in version 7.1, such as parent, + child, and top. These commands are now options + of the cellname and instance commands. +

+ +

See Also:

+
+ instance
+ load
+ tk_path_name
+
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 5:38pm

+ + diff --git a/doc/html/cellsearch.html b/doc/html/cellsearch.html new file mode 100644 index 00000000..2369902b --- /dev/null +++ b/doc/html/cellsearch.html @@ -0,0 +1,113 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

cellsearch

+
+Execute a TCL procedure on each cell definition or instance in the hierarchy +
+ +

Usage:

+
+ cellsearch [instances] procedure

+
+ where procedure is the name of a predefined Tcl procedure + (see Summary, below). +
+
+ +

Summary:

+
+ The cellsearch command is a method for user access to + the magic database search routines. It searches the + hierarchical database for all cell definitions and applies + the callback procedure to each. If the instances + keyword is present, it searches the database for all cell + instances and applies the callback procedure to each. The + callback procedure must be defined as described below. + Note that the callback method into Tcl is inherently slow + and should only be used for non-compute-intensive tasks.

+ + The Tcl callback procedure for the instances version of + the cellsearch command is passed six values, the bounding + box coordinates of the instance, the instance use name (id), and + the name of the parent cell definition. The procedure must be + defined to accept these six arguments, as in the following + example: +

+	proc inst_callback {llx lly urx ury usename defname} {
+	   puts stdout "Instance $usename of $defname bbox $llx $lly $urx $ury"
+        }
+     
+ + The Tcl callback procedure for the cell definition search + is passed one value, the name of the cell definition. The + procedure must be defined to accept this single argument, as + in the following example: +
+	proc def_callback {defname} {
+	   puts stdout "Cell $defname"
+        }
+     
+
+ +

Implementation Notes:

+
+ cellsearch is implemented as an internal magic + command that links to an external Tcl procedure as a callback + function. This routine is experimental and subject to change + without notice. +
+ +

Bugs:

+
+ As currently implemented, there is no protection against + calling a magic command from the callback procedure + that will alter the internal cell hash table while it is + being traversed, causing a crash. The implementation + should be changed to a 2-step procedure that traverses the + cell hash table first, creating an internal list of function + arguments to pass for each cell, and then executes the + callback function on each.

+ + There are more efficient ways of executing the callback + function than Tcl_EvalEx(). In particular, the procedure + should be cast as a Tcl object and Tcl_EvalObjEx() used.

+ + The callback function should allow in-line Tcl procedures + and use the standard Tcl/Tk method of "%" escape sequences + used as arguments to the callback function that allow the + user to specify what arguments are passed to the callback + function (as is done for the tag command). +

+ +

See Also:

+
+ search
+
+ +

+ + + +
Return to command index +
+

Last updated: October 4, 2004 at 5:05am

+ + diff --git a/doc/html/center.html b/doc/html/center.html new file mode 100644 index 00000000..342af7d5 --- /dev/null +++ b/doc/html/center.html @@ -0,0 +1,75 @@ + +center [x y] + + + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

center

+
+Center the layout window view on the cursor lower-left coordinate, +or the indicated coordinate if present. +
+ +

Usage:

+
+ center [x y]

+
+ where x y is a coordinate in default magic units +
+
+ +

Summary:

+
+ Without arguments, the center command centers the layout + window on the lower-left corner of the cursor box. When values + x and y are given, the view is centered on that + coordinate. Coordinate values must be in (integer) units of + the magic internal grid. This command is similar to + the "view llx lly urx ury" command, which + centers on a box instead of a point. +
+ +

Implementation Notes:

+
+ center is implemented as a magic built-in command. +
+ +

Bugs:

+
+ Coordinate values should be any acceptable value, including + lambda, grid, and metric values, as they are for the box + command. +
+ +

See Also:

+
+ view
+
+ +

+ + + +
Return to command index +
+

Last updated: October 4, 2004 at 3:59am

+ + diff --git a/doc/html/changetool.html b/doc/html/changetool.html new file mode 100644 index 00000000..c50953d5 --- /dev/null +++ b/doc/html/changetool.html @@ -0,0 +1,150 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

tool

+
+Change the layout "tool" (button bindings). This page describes the +version of the command used by the Tcl version of magic. +
+ +

Shortcuts:

+
+ Key macro space implements the command tool.
+ Key macro shift-space implements the command tool box. +
+ +

Usage:

+
+ tool [name|info]

+
+ where name may be one of box, wiring, + netlist, or pick. +
+
+ +

Summary:

+
+ The tool command selects or queries the mode of operation + of the mouse buttons in the layout window. Each tool + type has a unique set of button bindings.

+ + Without arguments, the tool command selects the next + tool type in round-robin fashion. With a tool type as argument, + the button bindings switch to those for the indicated tool. + With the info option, a summary of the commands bound to + each mouse button is given for the current tool.

+ + The default mouse bindings for each of the three tools is as follows: +

    +
  • Box Tool +
    +
    left +
    Move the box so its lower-left corner is at cursor position +
    right +
    Resize box by moving upper-right corner to cursor position +
    middle +
    Paint box area with material underneath cursor +
    + In addition, you can move or resize the box by different corners + by pressing left or right, holding it down, moving the cursor + near a different corner and clicking the other (left or right) + button down then up without releasing the initial button. +
  • Wiring Tool +
    +
    left +
    Pick wire material and size from under the cursor and begin + interactive wire placement. +
    right +
    Cancel interactive wire placement. +
    middle +
    Place a wire at the position shown by the interactive wire + tool highlight box, and continue interactive wire placement. +
    shift-left +
    Change the type of wire to the next plane (e.g., metal1 to metal2) +
    shift-right +
    Change the type of wire to the previous plane (e.g., metal2 to metal1) +
    shift-middle +
    Place a contact at the current location and switch to the wire + type on the next plane. +
    scrollwheel up +
    Increase the wire size by one unit +
    scrollwheel down +
    Decrease the wire size by one unit +
    + Note that the methods for the wire tool differ significantly between + Tcl-based magic, with its interactive capabilities, and non-Tcl-based + magic. +
  • Netlist Tool +
    +
    left +
    Select the net containing the terminal nearest the cursor +
    right +
    Toggle the terminal nearest the cursor into/out of current net +
    middle +
    Join current net and net containing terminal nearest the cursor +
    +
  • Pick Tool +
    +
    left +
    Remove the current selection from the layout, place it + in the pick buffer, and follow the cursor. +
    right +
    Cancel the current pick buffer and stop following the + cursor. +
    middle +
    Place a copy of the pick buffer at the current location, + and continue following the cursor. +
    shift-middle +
    Make a copy of the current selection from the layout, + place it in the pick buffer, and follow the cursor. +
    + The pick tool is an interactive feature only available in the + Tcl-based version of magic. +
+
+ +

Implementation Notes:

+
+ tool is implemented as a Tcl script in the Tcl-based + version of magic. The command duplicates the function of + the original tool command, which remains for the non-Tcl + based version of magic, and which performs the function of + changing the cursor style in the window.

+ + Button functions for each "tool" may be added to or modified in + the startup scripts. The Tcl variable Opts(tool) contains + the current tool name, and may be used by a user tool + procedure overriding the default one in "tools.tcl". +

+ +

See Also:

+
+ tool (non-Tcl version) +
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 5:25pm

+ + diff --git a/doc/html/channels.html b/doc/html/channels.html new file mode 100644 index 00000000..3386bb09 --- /dev/null +++ b/doc/html/channels.html @@ -0,0 +1,64 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

channels

+
+See channels (as feedback) without doing routing. +
+ +

Usage:

+
+ channels [netlist_file]

+
+ where netlist_file is the name of a .net + file containing a routing netlist. +
+
+ +

Summary:

+
+ The channels command is part of the routing module in + magic. It shows available routing channels in the + current layout using the feedback layer mechanism. +
+ +

Implementation Notes:

+
+ channesl is implemented as a built-in command in magic + when the router modules are compiled in (which currently they are, + in the default compilation configuration). +
+ +

See Also:

+
+ route
+ iroute
+ garoute
+
+ +

+ + + +
Return to command index +
+

Last updated: October 4, 2004 at 5:13am

+ + diff --git a/doc/html/cif.html b/doc/html/cif.html new file mode 100644 index 00000000..ef218d1c --- /dev/null +++ b/doc/html/cif.html @@ -0,0 +1,193 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

cif

+
+Read CIF input or generate CIF output. +
+ +

Usage:

+
+ cif [option]

+
+ where option is one of the following: +
+
help +
Print usage information +
arealabels [yes|no] +
Enable/diable use of the CIF area label extension. The + default is "yes". Normally there is no reason not to + do this. +
coverage layer +
Report the coverage of the indicated CIF layer within the + bounds of the current edit cell. This is useful for + fabrication processes that require a minimum amount of + coverage for specific layers (usually the metal routing + layers). +
idcell [yes|no] +
Enable/diable use of the CIF cell ID extension. The + default is "yes". Normally there is no reason not to + do this. +
lambda in|out +
Report the number of microns per lambda for the current + style. If "in" is specified, the value is + reported for the current CIF/GDS input style. If + "out" is specified, the value is reported for + the current CIF/GDS output style. +
limit [value] +
Limit the amount of internal grid subdivision to the + indicated value (which is dimensionless, the ratio + of the maximum subdivision to the current lambda + value). If no value is given, the current + limit is reported. By default, the value is set to + 100, as grid subdivision smaller than this amount + can result in integer overflow on subsequent CIF or + GDS output. +
rescale [yes|no] +
Allow or disallow internal grid subdivision while reading + CIF input. Default is "yes". Normally, one wants to allow + rescaling to ensure that the CIF is displayed exactly as it + is in the input file. Occasionally, however, the CIF input + is on a very fine scale, such as nanometers, and it is + preferable to snap the input to lambda boundaries rather + than to subsplit the internal grid to such a fine value. + The limit option may also be used to limit grid + subdivision to a minimum value (see above). +
warning [option] +
Set warning information level. "option" may be one + of the following: +
+
default +
The default setting is equivalent to all the other + options (align, limit, redirect, + and none) being disabled. +
align +
Generate warnings during a "cif see" command + if the alignment of geometry is on fractional lambda. + Normally, magic allows contacts to be drawn at + half-lambda positions. If this violates DRC requirements + for the minimum output grid, this warning setting can be + used to detect such violations. +
limit +
Limit warnings to the first 100 warnings or errors only. +
redirect [file] +
Redirect all warnings to an output file named file. + If file is not given, then redirection is disabled. +
none +
Do not produce any warning messages on CIF input. +
+
polygon subcells [yes|no] +
Put non-Manhattan polygons into subcells. Default is "no". + Normally this option is not needed. However, input layout + that defines a number of angled wires, particularly those + that are closely spaced, can cause magic to generate + literally millions of internal tiles. This tends to be + true in particular for corner cells in padframes for deep + submicron feature sizes, where the angled corners are + required to meet the DRC specification. When set to "yes", + each polygon encountered in the CIF input is placed in its + own uniquely-named subcell. This prevents interations with + other polygons on the same plane and so reduces tile splitting. +
see layers +
View the CIF/GDS output layers in the comma-separated list + layers as feedback entries on the layout. This is + useful for determining what the actual foundry layer types + are doing as a result of the boolean operations in the + CIF/GDS output style. Most useful for debugging technology + file CIF/GDS output style sections, or tracing DRC error + reports from sources other than magic. CIF output + is computed and feedback is shown only inside the cursor + box area. +
+
+ Figure 1. Command cif see CSP shows the P+ + implant layer surrounding the P diffusion regions within + the cursor box area. +
+
statistics +
Print statistics from the CIF generator, including tile + operations, rectangles output, and interactions between + cells. Not especially useful to the typical end-user. +
prefix [path] +
Prepend the path name path to cell names in the + CIF output. If no path is specified, reports the + existing path name. +
[list|listall] istyle [style] +
Set the current input style to style. If no + style is specified, returns the current input + style. To get a list of all available input styles + in the current technology, use the listall + istyle option. The list istyle option + returns the current style name as a Tcl result. +
[list|listall] ostyle [style] +
Set the current output style to style. If no + style is specified, returns the current output + style. To get a list of all available output styles + in the current technology, use the listall + ostyle option. The list ostyle option + returns the current style name as a Tcl result. +
flat file +
Output CIF format to "file" for the window's root + cell, flattening the hierarchy prior to output. +
read file +
Read CIF format from file file into the edit cell. + If file does not have a file extension, then magic + searches for a file named file or file.cif. +
write file +
Output CIF format to "file" for the window's root cell. +
+
+
+ +

Summary:

+
+ The cif command reads CIF input or produces CIF input/output + ("Caltech Intermediate Format", as described in Mead & Conway), + or sets various parameters affecting the CIF (and GDS) input and + output. Certain cif command options also affect GDS input + and output.

+ + If no option is given, a CIF file is produced for the root cell, + with the default name of the root cell definition and the + filename extension ".cif".

+

+ +

Implementation Notes:

+
+ cif is implemented as a built-in function in magic. + Options list and listall cause output to be + returned as a Tcl result, rather than printed to stdout (the + console). +
+ +

See Also:

+
+ gds (calma)
+
+ +

+ + + +
Return to command index +
+

Last updated: October 4, 2004 at 8:03am

+ + diff --git a/doc/html/clockwise.html b/doc/html/clockwise.html new file mode 100644 index 00000000..3b74713c --- /dev/null +++ b/doc/html/clockwise.html @@ -0,0 +1,78 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

clockwise

+
+Rotate the selection and box clockwise +
+ +

Shortcuts:

+
+ Key macro r implements the command clockwise + (or rotate 90).
+ Key macro R implements the command clockwise 270 + (or rotate -90).
+ Key macro Control-R implements the command clockwise 180 +
+ +

Usage:

+
+ clockwise [degrees] [-origin]

+
+ where degrees is the number of degrees to rotate, and + must be a manhattan amount (90, 180, 270). +
+
+ +

Summary:

+
+ The clockwise command rotates the current selection by + the specified amount, in degrees. The default rotation is by + 90 degrees. The amount of rotation must be one of 90, 180, + or 270.

+ + If -origin is specified, the rotation is around the + origin of the selection, not around the lower left-hand + corner. +

+ +

Implementation Notes:

+
+ clockwise is implemented as a built-in magic command. + Because a "standard abbreviation" is clock and conflicts with + the Tcl command clock, this case is handled specially. + The command clock is deprecated in favor of the more general + command rotate, but is maintained for backward compatibility. +
+ +

See Also:

+
+ rotate
+
+ +

+ + + +
Return to command index +
+

Last updated: October 15, 2004 at 10:09am

+ + diff --git a/doc/html/closewindow.html b/doc/html/closewindow.html new file mode 100644 index 00000000..94176200 --- /dev/null +++ b/doc/html/closewindow.html @@ -0,0 +1,74 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

closewindow

+
+Close a (non-GUI) window +
+ +

Shortcuts:

+
+ Key macro O implements the command closewindow. This + macro is disabled when using the GUI wrapper. +
+ +

Usage:

+
+ closewindow [name]

+
+ where name is the name of a window. +
+
+ +

Summary:

+
+ The closewindow command closes a window. Without + arguments, if only one window is present, that window will + be closed. Otherwise, if multiple windows are present, the + window to be closed must be specified by name.

+ closewindow closes both layout windows created with + the openwindow command or windows created with the + specialopen command. +

+ +

Implementation Notes:

+
+ closewindow is implemented as a built-in magic + window command. It should not be used with the GUI wrapper + (invoked with magic -w); instead, the closewrapper + function should be used. +
+ +

See Also:

+
+ openwindow
+ specialopen
+ closewrapper
+
+ +

+ + + +
Return to command index +
+

Last updated: November 10, 2004 at 6:08pm

+ + diff --git a/doc/html/closewrapper.html b/doc/html/closewrapper.html new file mode 100644 index 00000000..396e85d3 --- /dev/null +++ b/doc/html/closewrapper.html @@ -0,0 +1,71 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

closewrapper

+
+Close a GUI layout window and all of its associated frames. +
+ +

Shortcuts:

+
+ Menu option File->Close implements the command closewrapper + tk_path_name in the GUI layout window. +
+ +

Usage:

+
+ closewrapper frame_name

+
+ where frame_name is the Tk path name of the top-level + layout GUI window frame. By default, this name is .layout1, + .layout2, etc., for successive windows created with + the openwrapper command. +
+
+ +

Summary:

+
+ The closewrapper command removes a layout window in the + Tcl version of magic. It is only applicable when magic is + invoked with the GUI wrapper, using magic -w, and + supercedes the built-in command closewindow. +
+ +

Implementation Notes:

+
+ closewrapper is implemented as a Tcl procedure in the + GUI wrapper script. +
+ +

See Also:

+
+ closewindow
+ openwrapper
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 12:45am

+ + diff --git a/doc/html/color/color.html b/doc/html/color/color.html new file mode 100644 index 00000000..7c66bcd1 --- /dev/null +++ b/doc/html/color/color.html @@ -0,0 +1,82 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

color

+
+Specify color to edit, or print intensities of the currently edited color +
+ +

Usage:

+
+ color [number|next|last|get|rgb] +

+
+ where number is the number of a color in the colormap list. + Historically, this number was given in octal. This has been changed + to the variable format of C syntax, in which numbers are treated as + decimal unless beginning with "0" (zero), in which case they are + treated as octal, or "0x" (zero-x), in which case they are treated + as hexidecimal. +
+
+ +

Summary:

+
+ The color command specifies the color number to edit in + the colormap window. With no arguments, prints the color + index and RGB values for the color being edited.

+ + In the Tcl-based version of magic, the "color picking" and + "color copying" functions are no longer functional. For + this reason, options color next and color last + have been added to allow scrolling through the colors in the + colormap. These commands are bound to the key macros + "+" (plus) and "-" (minus), respectively.

+ + Options color get and color rgb return subsets + of the information reported by color with no arguments. + color get returns the color index of the color, and + color rgb returns the individual red, green, and blue + intensities of the color. In the Tcl-based version of magic, + these values are returned as Tcl results.

+ + Note that color changes made in the color window do not + immediately take effect on the layout. It is necessary to pass + a refresh command to the layout window, or to type the + Control-L macro in the layout window to update + the colors. +

+ +

Implementation Notes:

+
+ color is implemented as a built-in color + window command in magic. It can only be invoked from + a window created with the specialopen color command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/color/load.html b/doc/html/color/load.html new file mode 100644 index 00000000..c4422e69 --- /dev/null +++ b/doc/html/color/load.html @@ -0,0 +1,80 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

load

+
+Load an alternate layer colormap. +
+ + +load [techStyle displayStyle monitorType] +

Usage:

+
+ load [techStyle displayStyle monitorType]

+
+ where techStyle is declared by the technology + (normally "mos"), displayStyle is determined + by the display visual (normally "7bit", "24bit", + or "OpenGL"), and monitorType is normally + "std". +
+
+ +

Summary:

+
+ The load command loads an alternative colormap file + that can be used to change the colors used by magic for + drawing layout.

+ + By default, without arguments, the filename searched for + varies according to the display visual type, but is normally +

+ mos.24bit.std.cmap for 24- and 32-bit visuals, + mos.7bit.std.cmap for 8-bit visuals, and + mos.OpenGL.std.cmap for OpenGL visuals. +
+ The current directory is searched first for local files + overriding the system colormap defaults, followed by a + search of the sys path as declared by the path + command. +
+ +

Implementation Notes:

+
+ load is implemented as a built-in color + window command in magic. It can only be invoked from + a window created with the specialopen color command. +
+ +

See Also:

+
+ save
+ path
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/color/pushbutton.html b/doc/html/color/pushbutton.html new file mode 100644 index 00000000..d7303630 --- /dev/null +++ b/doc/html/color/pushbutton.html @@ -0,0 +1,63 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

pushbutton

+
+Execute the default function associated with a mouse button event. +
+ +

Usage:

+
+ pushbutton button

+
+ where button is one of left, middle, or right. +
+
+ +

Summary:

+
+ The pushbutton command invokes the function "traditionally" + associated with the indicated mouse button. However, in Magic-7.3, + button actions are treated as macros, and so the button macros + are defined, by default, to call the pushbutton command for + the indicated button. The button actions no longer recognize + button-up events. The action taken depends on where in the + color window the button was pressed. Actions are defined for + pressing the button in one of the six color bars or the "plus" + and "minus" buttons on each side of each color bar, and changes + the color components of the current edit color accordingly. +
+ +

Implementation Notes:

+
+ pushbutton is implemented as a built-in color + window command in magic. It overrides the default + window client pushbutton command. +
+ +

+ + + +
Return to command index +
+

Last updated: November, 2004

+ + diff --git a/doc/html/color/save.html b/doc/html/color/save.html new file mode 100644 index 00000000..2e49a964 --- /dev/null +++ b/doc/html/color/save.html @@ -0,0 +1,79 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

save

+
+Save the layer colormap to a file. +
+ +

Usage:

+
+ save [techStyle displayStyle monitorType]

+
+ where techStyle is the type of "dstyle" file requested + by the technology (normally "mos"), displayStyle is + the type of display (normally NULL, but when specified should + be "24bit", "8bit", or "OpenGL" to match the type of display), + and monitorType is typically "std". +
+
+ +

Summary:

+
+ The save command saves the contents of the color map + in a file that can be retrieved with the color window + load command. This file is saved in the current working + directory and has the format +
+ techStyle.displayStyle.monType.cmap +
+ Without arguments, the default colormap filename varies according + to the display type, but is normally one of: +
+ mos.24bit.std.cmap for 24- and 32-bit display visuals
+ mos.7bit.std.cmap for 8-bit display visuals
+ mos.OpenGL.std.cmap for OpenGL displays
+
+ + Note that for the colormap to be read by magic on startup, + the filename format above must be adhered to. +
+ +

Implementation Notes:

+
+ save is implemented as a built-in color + window command in magic. It can only be invoked from + a window created with the specialopen color command. +
+ +

See Also:

+
+ load
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/commands.html b/doc/html/commands.html new file mode 100644 index 00000000..46b67531 --- /dev/null +++ b/doc/html/commands.html @@ -0,0 +1,703 @@ + + + + +Magic-7.4 Command Reference + +

Magic VLSI Layout Tool Version 7.4 + *

+ +

Magic User's Guide

+ +

Table of Contents

+

+Command-line invocation (usage)
+Script Invocation
+Magic command summary
+
+ +

Obligatory Screenshot

+ +
+ Screenshot of Magic +
+ This screenshot, from Magic version 7.2, shows off a number of + features of the Tcl version, including the cell manager window, + the tech manager window, the toolbar, the console command-line + entry window, and popup dialog boxes. Also shows off the + version 7.1+ features of the OpenGL display and the non-Manhattan + geometry extension. +
+
+ +

Magic version 7.4 Usage (command-line invocation)

+ +
+ Basic usage:

+ + + +
+ + + + +
magic + [-noc[onsole]] + [-now[rapper]] + [-d devType] + [-T technology] + [file] +
+

+ + where: +
+
+
-noconsole +
(Tcl version only) Uses the calling terminal + for terminal-based command-line input. Otherwise, a Tk + console window is used. +
-nowrapper +
(Tcl version only) Magic layout windows use + the GUI wrapper, including cell and technology manager + windows, layer toolbar, and file menu. +
-d devType +
(all versions) Select the graphics interface at runtime. + Specifying an invalid devType will result in a list + of known types. The possible values of devType are + determined at compile time, but the usual ones are + NULL (no graphics), X11, and + OpenGL. X11 is the usual default. +
-T technology +
(all versions) + Select the appropriate technology (.tech) file. + At present (this is on the to-do list), magic cannot change + technology after startup. So the technology file corresponding + to the layout to be loaded must be supplied to the command line + at startup. The default technology is scmos, which + is included with the magic source distribution. The complete + list of available technology files depends on what has been + installed on the system (see the technology + file page for details). +
file +
(all versions) Load the layout (.mag) file file + into the layout window on startup. +
+ + Other standard usage:

+ + + +
+ + + +
magic + [-dnull] + [file] +
+

+ + + +
+ + + +
magic + [-r[ecover]] +
+

+ + where options are as follows: + +
+ -recover
+
+ This option recovers a layout after a crash. Note that + crash recovery files are only automatically + created and updated by the Tcl/Tk version of magic. + A single file containing multiple layouts is placed in + the /tmp directory. Upon normal program exit, + it is removed. However, if magic terminates abnormally + due to a program bug, reception of a termination signal + from the operating system, or a system crash or shutdown, + the file will remain and can be recovered. It is + very important that you recover the file from the + same directory where it was initially created; otherwise, + if startup conditions are different (such as a different + technology specified), layout may be lost. +
+ + -dnull file
+
+ This option starts magic without graphics. It is + appropriate for running magic in batch mode from a + script. Note that there is a subtle difference between + options "-d null" and "-dnull". The + former starts magic without the ability to create a + layout window, but still invokes the graphics + initialization routines (in the Tcl/Tk version, a Tk + window may briefly appear). The latter form specifically + ignores all graphics and therefore runs with less + overhead on startup. +
+ +
+ + Complete usage information:

+ + + +
+ + + + +
magic + [-noc[onsole]] + [-now[rapper]] + [-nowindow] + [-d devType] + [-T technology] + [-m monType] + [-D] + [file] +
+

+ + where the additional options not covered above are:

+ +
+ -nowindow
+
+ (Tcl version only) Run without displaying an initial layout + window. This is used mainly for GUI wrapper scripts which + like to generate and handle their own windows. +
+ -m monType
+
+ (obscure) monType names a monitor type. + This is used in the search for the colomap file name, + which is designated + <tech>.<planes>.<mon>.cmap1. + The default is "std" (corresponding to + colormap file "mos.7bit.std.cmap1". The only other + monitor type for which colormaps exist in the distribution + is "mraster". This provides a way for users to + override the system color assignments. +
+ -D
+
+ (all versions) Run in Debug mode. +
+
+ + Obsolete usage information:

+ + + +
+ + + +
magic + [-g gPort] + [-i tabletPort] + [-F objFile saveFile] + ... +
+

+ + where the additional options not covered above are:

+ +
+ -g gPort
+
+ (largely obsolete) gPort names a device to use + for the display. This was generally used in the past with + dual-monitor systems, especially Sun systems in which the + layout display might go to /dev/fb. +
+ -i tabletPort
+
+ (largely obsolete) tabletPort names a device to use + for graphics input. This has not been tested with modern + graphics tablet devices. It is ignored by the X11 and OpenGL + display interfaces. +
+ -F objFile saveFile
+
+ (largely obsolete) Create an executable file of + the current magic process, a core image snapshot + taken after all initialization. objFile + is the name of the original executable, and the + image will be saved in saveFile. This + only works on VAXen and SUNs running an old SunOS + (using a.out executables). +
+
+ +
+ +

Script invocation

+
+ Often it is helpful to have a shell script invoke magic with specific + options to perform tasks such as generating a GDS file for tapeout. + The following example code clip imports GDS into magic as a "vendor + cell": + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + +
magic -dnull -noconsole << EOF
drc off
box 0 0 0 0
load vtop.mag -force
drc off
gds readonly true
gds rescale false
gds read ${cellname}.gds
cellname rename ${cellname} vtmp
load vtmp
select top cell
set pname [lindex [cellname list children] 0]
cellname rename \\\$pname ${cellname}
select cell \\\${pname}_0
identify ${cellname}_0
writeall force ${cellname}
quit -noprompt
EOF
+

+
+ +
+ +

General window commands (for all windows)

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
center closewindow cursor
help imacro logcommands
macro openwindow redo
redraw scroll setpoint
sleep specialopen quit
undo updatedisplay version
view windowborder windowcaption
windownames windowscrollbars xview
zoom tk_path_name
+
+ +

Layout window commands and window-less commands

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
addcommandentry + addpath + array +
box + calma + caption +
cellmanager + cellname + cellsearch +
channels + cif + clockwise +
closewrapper + contact + copy +
corner + crash + crashbackups +
crosshair + def + delete +
deletecommandentry + down + drc +
dump + edit + element +
erase + expand + ext +
ext2sim + ext2spice + extract +
extresist + exttosim + exttospice +
feedback + fill + findbox +
findlabel + flatten + flush +
garoute + gds + get +
getcell + getnode + goto +
grid + help + identify +
initialize + instance + iroute +
irsim + label + lef +
load + maketoolbar + measure +
move + openwrapper + paint +
path + peekbox + plot +
plow + polygon + popbox +
popstack + port + promptload +
promptsave + property + pushbox +
pushstack + render3d + resumeall +
rotate + route + save +
scalegrid + search + see +
select + shell + sideways +
snap + spliterase + splitpaint +
startup + straighten + stretch +
suspendall + tag + tech +
techmanager + tool (non-Tcl version) + tool (Tcl version) +
unexpand + unmeasure + upsidedown +
what + wire + writeall +
xload +
+
+ +

Netlist window commands

+
+ + + + + + + + + + + + + + + + + + +
add + cleanup + cull +
dnet + dterm + extract +
find + flush + join +
netlist + pushbutton + print +
ripup + savenetlist + shownet +
showterms + trace + verify +
writeall +
+
+ +

3D window commands

+
+ + + + + + + + + + + +
cif + closewindow + cutbox +
defaults + help + level +
refresh + render + scroll +
see + view + zoom +
+
+ +

Color window commands

+
+ + + + + + + + + +
pushbutton + color + load +
save +
+
+ +

"Wizard" (developer) layout commands

+
+ + + + + + + + + +
*bypass + *coord + *extract +
*plow + *psearch + *showtech +
*tilestats + *tsearch + *watch +
+
+ +

"Wizard" (developer) window commands

+
+ + + + + + + +
*crash + *files + *grstats +
*pause + *winddebug + *winddump +
+
+ +

User's Guide Development

+
+To be done: +
    +
  • Add some general topics, not command-specific. +
  • Incorporate a lot of the currently text-only material into HTML format. +
  • Run latex2html on all of the LaTeX distribution documentation. +
  • More information on the routers and netlists +
  • Subject index. +
+
+ +

+ + + +
email: + +
+

Last updated: December 15, 2005 at 6:59am

+ + diff --git a/doc/html/commands.list b/doc/html/commands.list new file mode 100644 index 00000000..7aab013c --- /dev/null +++ b/doc/html/commands.list @@ -0,0 +1,127 @@ +addcommandentry +addpath +array +box +calma +caption +cellmanager +cellname +cellsearch +center +channels +cif +clockwise +closewindow +closewrapper +copy +corner +cursor +def +delete +deletecommandentry +down +drc +dump +edit +element +erase +expand +ext +ext2sim +ext2spice +extract +extresist +exttosim +exttospice +feedback +fill +findbox +findlabel +flatten +flush +garoute +gds +get +getcell +getnode +gmacro +goto +grid +grow +help +identify +imacro +initialize +instance +iroute +label +lef +load +logcommands +macro +maketoolbar +move +openwindow +openwrapper +paint +path +peekbox +plot +plow +popbox +popstack +port +promptload +promptsave +property +pushbox +pushbutton +pushstack +quit +redo +redraw +render +reset +resumeall +rotate +route +save +scalegrid +scroll +search +see +select +setpoint +shell +sideways +sleep +snap +specialopen +spliterase +splitpaint +startup +straighten +stretch +suspendall +tag +tech +techmanager +tool +undo +unexpand +updatedisplay +upsidedown +version +view +what +windowborder +windowcaption +windownames +windowpositions +windowscrollbars +wire +writeall +xload +xview +zoom +tk_path_name diff --git a/doc/html/contact.html b/doc/html/contact.html new file mode 100644 index 00000000..46b48bad --- /dev/null +++ b/doc/html/contact.html @@ -0,0 +1,60 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

contact

+
+Paint a contact at the intersection of two layers. +
+ +

Usage:

+
+ contact type

+
+ +

Summary:

+
+ The contact command computes the intersection area (inside the + cursor box) of the two (or more) residue types that make up the contact + type type, and paints the contact type type on top of the + area of intersection. +
+ +

Implementation Notes:

+
+ contact is implemented as a built-in layout command in magic. + As of magic version 7.3.115 this command does not correctly translate the + cursor box for edit cells and may paint outside of the cursor box, with + random results. +
+ +

See Also:

+
+ paint
+
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 8:18pm

+ + diff --git a/doc/html/copy.html b/doc/html/copy.html new file mode 100644 index 00000000..c33c978c --- /dev/null +++ b/doc/html/copy.html @@ -0,0 +1,86 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

copy

+
+Make a copy of the selection. +
+ +

Shortcuts:

+
+ Key macro c implements the command copy. +
+ +

Usage:

+
+ copy [option]

+
+ where option is one of the following: +
+
direction + [distance] +
Copy the selection relative to the original + in the direction direction by an + amount distance. +
to x y +
Copy the selection to the coordinate location + specified by the coordinate pair x y. +
+
+
+ +

Summary:

+
+ The copy command creates a copy of the current selection. + Without arguments, the lower-left hand corner of the copied + selection is placed at the current cursor position (the X11 + cursor, not the magic "cursor box"). With arguments + direction and distance, the new copy is placed + relative to the original in the indicated direction by the + indicated amount. The default distance is 1 unit (usually + lambda; see distance for + further explication).

+ + Note that usage copy center is useful to make a copy + in the current edit cell of a selection of paint and/or + subcells in a non-edit cell. With this use, the copy will + be generated directly on top of the original. +

+ +

Implementation Notes:

+
+ copy is implemented as a built-in magic command. +
+ +

See Also:

+
+ direction
+ distance
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 12:41am

+ + diff --git a/doc/html/corner.html b/doc/html/corner.html new file mode 100644 index 00000000..32f25355 --- /dev/null +++ b/doc/html/corner.html @@ -0,0 +1,98 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

corner

+
+Make L-shaped wires inside the cursor box. +
+ +

Usage:

+
+ corner d1 d2 [layers]

+
+ where d1 and d2 are valid manhattan + directions, and + layers is an optional comma-separated list + of valid paint layers. +
+
+ +

Summary:

+
+ The corner command makes L-shaped wires inside + the cursor box, filling first in direction d1, + then in direction d2. If no layers are + specified, then the cornering algorithm is applied to + all layers crossing the cursor box boundary opposite + to direction d1. If layers is specified, + the cornering algorithm is applied only to those layers + specified. The usage of corner is similar to + that for the command fill (q.v.). +
+ +
+ Below is an example showing how the cornering algorithm + responds to the command corner n e. First it + finds layers crossing the cursor box boundary to the + south (opposite to the first specified direction, + north), and then extends these layers as wires + first to the north, then to the east. The position of + the layers leaving the box to the east is such that + the same distance is maintained from each layer to the + north side of the box at the exit point as it was + from each layer to the east side of the box at the + entrance point. + +
+ +
+ Figure 1: The cornering operation in response to the layout + shown, given magic command corner n e. +
+
+ + +

Implementation Notes:

+
+ corner is implemented as a built-in magic command. +
+ +

Bugs:

+
+ If the area in the box is not large enough for + the cornering algorithm to produce the cornered + wires, unpredictable results often result. +
+ +

See Also:

+
+ direction
+ fill
+
+ +

+ + + +
Return to command index +
+

Last updated: October 4, 2004 at 7:56am

+ + diff --git a/doc/html/crash.html b/doc/html/crash.html new file mode 100644 index 00000000..3f520671 --- /dev/null +++ b/doc/html/crash.html @@ -0,0 +1,104 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

crash

+
+Handle crash backup files +
+ +

Usage:

+
+ crash save | recover [filename]

+
+ +

Summary:

+
+ The crash command handles crash backup files. The exact + operation depends on the options, and are outlined below: +
+
crash save +
creates and writes to a single file a copy of the contents + of all modified cells. If crash save has been + called previously, then the filename specified or + generated will be used again. If this is the first + call to crash save, or if the previous call was + crash save "", then a new, unique filename of + a file in the system temporary directory (normally + "/tmp") is created and remembered for subsequent + calls to crash save. +
crash save filename +
creates and writes to the file filename a copy of + the contents of all modified cells. filename + is retained as the crash filename, so subsequent uses + of crash save without a filename specified will + also write to this file. +
crash save "" +
causes magic to forget the name of the crash file. The + next use of crash save without a filename will + revert to the behavior of generating a unique filename + in the system temporary directory. +
crash recover +
searches the system temporary directory for magic crash + recovery files. If one or more such files is found, + then the user is prompted for the action of either + recovering or ignoring the most recent file found. + If the chosen action is to recover the file, then the + contents of the saved crash file are loaded into the + database, and the file is removed. +
crash recover filename +
recovers the database from the contents of the saved crash + file filename upon successful read-in, the file + filename is removed. +
+ + If a crash file has been generated during a layout editing session, + and magic is exited normally with the "quit" command, then the + crash backup file is removed.

+ + For backward-compatibility, crash backup files are always generated + when magic receives a SIGTERM signal. In the non-Tcl version of + magic, periodic backups are not made. + +

+ +

Implementation Notes:

+
+ crash is implemented as a built-in command in magic. + The Tcl/Tk version defines various scripts in "tools.tcl" that + implement a periodic backup using the crash command. + Invoking magic on the command-line using "magic -r" is + equivalent to starting magic followed by the command + "crash recover". +
+ +

See Also:

+
+ crashbackups
+
+ +

+ + + +
Return to command index +
+

Last updated: December 7, 2005 at 3:06pm

+ + diff --git a/doc/html/crashbackups.html b/doc/html/crashbackups.html new file mode 100644 index 00000000..dbb1b74f --- /dev/null +++ b/doc/html/crashbackups.html @@ -0,0 +1,68 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

crashbackups

+
+Handle periodic backups during a layout editing session. +
+ +

Usage:

+
+ crashbackups [start|stop]

+
+ +

Summary:

+ The crashbackups procedure enables or disables the + periodic saving of crash recovery backup files. + crashbackups or crashbackups start sets the + timer for the first periodic save. After the timer times + out, backup file is generated and written in the system + temporary directory, and the timer is reset. By default, + the backup interval is 10 minutes (600000 msec). The + interval can be changed by setting the value of Tcl variable + $Opts(backupinterval) to the interval value in msec.

+ + crashbackups stop removes the timer callback and thus + prevents further writing of backup files. Note that if + crash recovery is stopped or started multiple times during + a session, the same filename is used to save the data. +
+ +

Implementation Notes:

+
+ crashbackups is implemented as a Tcl procedure in the + "tools.tcl" script file. It calls the magic command + "crash save". +
+ +

See Also:

+
+ crash
+
+ +

+ + + +
Return to command index +
+

Last updated: December 7, 2005 at 3:15pm

+ + diff --git a/doc/html/crosshair.html b/doc/html/crosshair.html new file mode 100644 index 00000000..19273be7 --- /dev/null +++ b/doc/html/crosshair.html @@ -0,0 +1,57 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

crosshair

+
+Implements a crosshair highlight on top of the layout. +
+ +

Usage:

+
+ crosshair x y

+ crosshair off

+
+ +

Summary:

+
+ The crosshair command generates, moves, or removes a crosshair + highlight in the layout window. Option off removes the crosshair, + while coordinates x y place the crosshair at a specific layout + location, creating the crosshair if it has been previously disabled. + The crosshair is disabled by default upon startup. +
+ +

Implementation Notes:

+
+ crosshair is implemented as a built-in window command in magic. + The crosshair is available as an interactive feature in the Tcl/Tk + version of magic from the "Options" menu. The commands above are + executed in response to pointer motion events. +
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 5:05pm

+ + diff --git a/doc/html/cursor.html b/doc/html/cursor.html new file mode 100644 index 00000000..10341258 --- /dev/null +++ b/doc/html/cursor.html @@ -0,0 +1,64 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

cursor

+
+Return magic internal coordinates of the cursor (X11 pointer) +
+ +

Usage:

+
+ cursor

+
+ +

Summary:

+
+ The cursor command returns the current position of the + cursor (the X11 pointer, not the magic cursor box) in + internal layout coordinates. +
+ +

Implementation Notes:

+
+ cursor is implemented as a built-in window command in magic. + In the Tcl version of magic, it returns a Tcl result (list of two + elements, x and y coordinates).

+ + Like all window commands, it reports relative to the existing window + if only one window is present, or the active window if called with + the ":" macro. Otherwise, it must be called using the + tk_path_name command to specify relative to which layout + window the cursor coordinates will be given. +

+ +

See Also:

+
+ tk_path_name
+
+ +

+ + + +
Return to command index +
+

Last updated: October 5, 2004 at 2:47am

+ + diff --git a/doc/html/def.html b/doc/html/def.html new file mode 100644 index 00000000..0103d0a4 --- /dev/null +++ b/doc/html/def.html @@ -0,0 +1,84 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

def

+
+Read or write DEF format files. +
+ +

Usage:

+
+ def option

+
+ where option is one of the following: +
+
read [filename] +
Read a DEF file filename[.def] +
write [cell] +
Write DEF for current or indicated cell named cell +
help +
Print help information (command summary) +
+
+
+ +

Summary:

+
+ The def command reads and writes DEF format files. These + files are generally assumed to be digital standard-cell based + layouts. The DEF format has no real concept of hierarchy. To + generate a valid DEF file that may be recognized by other + software, it is necessary to have a layout with standard cells + using the port method to declare input and output ports. + In particular, the port class and port use are + designed to work with the DEF read and write routines.

+ + The technology file should have a lef section + describing how LEF and DEF files should be written. However, if + an appropriate LEF file exists and is read prior to writing a + DEF format file, the technology will be initialized from the + file if it is not declared in the technology file.

+

+ +

Implementation Notes:

+
+ def is implemented as a built-in magic command. + Only the critical part of the DEF definition has been + implemented. Some uncommon forms of syntax such as + wire extensions are not implemented. This is largely due + to the incomplete nature of the LEF/DEF spec. It is unlikely + that such forms will be encountered in third-party input. +
+ +

See Also:

+
+ lef
+ port
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 1:45am

+ + diff --git a/doc/html/delete.html b/doc/html/delete.html new file mode 100644 index 00000000..43adad69 --- /dev/null +++ b/doc/html/delete.html @@ -0,0 +1,55 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

delete

+
+Delete everything in selection +
+ +

Shortcuts:

+
+ Key macro d implements the command delete. +
+ +

Usage:

+
+ delete +
+ +

Summary:

+
+ The delete command deletes whatever cells and paint are in + the current selection. +
+ +

Implementation Notes:

+
+ delete is implemented as a built-in magic command. +
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 12:48am

+ + diff --git a/doc/html/deletecommandentry.html b/doc/html/deletecommandentry.html new file mode 100644 index 00000000..d854fbaa --- /dev/null +++ b/doc/html/deletecommandentry.html @@ -0,0 +1,65 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

deletecommandentry

+
+Remove the GUI window frame for additional command-line entry. +
+ +

Usage:

+
+ deletecommandentry framename

+
+ where framename is the Tk pathname of a frame. +
+
+ +

Summary:

+
+ The deletecommandentry command is used with the GUI wrapper in + magic version 7.3. It removes the text entry frame at the bottom + of the window that duplicates the output of the Tk console. + The framename is the Tk path name of the frame holding + the layout window. By default these are named .layout1, + .layout2, etc., for each call to openwrapper. +
+ +

Implementation Notes:

+
+ deletecommandentry is implemented as a Tcl procedure defined + in the GUI wrapper script. It is only available when the wrapper + is used, that is, when magic is invoked with argument -w. +
+ +

See Also:

+
+ addcommandentry
+ openwrapper
+
+ +

+ + + +
Return to command index +
+

Last updated: October 5, 2004 at 3:17am

+ + diff --git a/doc/html/direction.html b/doc/html/direction.html new file mode 100644 index 00000000..53e241e0 --- /dev/null +++ b/doc/html/direction.html @@ -0,0 +1,75 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

direction

+
+Valid direction options in magic +
+ +

Summary:

+
+ Directions may be any valid known direction known to magic, including + the following standard directions: +
    +
  • north, up, top +
  • south, down, bottom +
  • east, right +
  • west, left +
  • center +
+ + Directions may also be one of the combinations: +
    +
  • northeast +
  • northwest +
  • southeast +
  • southwest +
+ + Directions may also be abbreviated. The following abbreviations + are explicitly defined in magic, and all other abbreviations are + accepted as long as the abbreviation can be uniquely identified + (such as r for right and l for left). +
    +
  • n, u +
  • s, d +
  • e +
  • w +
  • ne, ur, tr +
  • se, dr, br +
  • sw, dl, bl +
  • nw, ul, tl +
+
+ +

See Also:

+
+ distance +
+ +

+ + + +
Return to command index +
+

Last updated: October 4, 2004 at 7:30am

+ + diff --git a/doc/html/distance.html b/doc/html/distance.html new file mode 100644 index 00000000..b8d6576e --- /dev/null +++ b/doc/html/distance.html @@ -0,0 +1,67 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

distance

+
+Valid distance specifications in magic. +
+ +

Summary:

+
+ Distances are normally interpreted as lambda values. However, + this depends on the last use of the snap command; snap + internal changes the interpretation of units to the internal + grid, while snap user changes the interpretation of units to + the user grid. Distances may always be explicitly called out by + appending one of the following to the distance value (with no + intervening whitespace): +
+
i +
internal units +
l +
lambda units +
um +
microns +
mm +
millimeters +
cu +
centimicrons +
+ In any case where the internal grid is finer than the declared + distance measure, fractional distances may be specified; e.g., +
+ box move e 1.25um +
+ +

See Also:

+
+ direction + snap +
+ +

+ + + +
Return to command index +
+

Last updated: October 4, 2004 at 7:21am

+ + diff --git a/doc/html/down.html b/doc/html/down.html new file mode 100644 index 00000000..07169bd8 --- /dev/null +++ b/doc/html/down.html @@ -0,0 +1,62 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

down

+
+Load selected cell into a window +
+ +

Usage:

+
+ down +
+ +

Summary:

+
+ The down command loads the currently selected cell into the + window. If more than one cell is selected, the one closest to the + cursor (pointer) position will be used, or at worst, one will be + selected arbitrarily. +
+ +

Implementation Notes:

+
+ down is implemented as a built-in window command in magic. + In the Tcl version of magic, it is generally deprecated in favor of + the scripted Tcl procedure pushstack, and the "tools" script + implementation of the ">" macro to invoke pushstack + on a selected cell. +
+ +

See Also:

+
+ load
+ pushstack
+
+ +

+ + + +
Return to command index +
+

Last updated: October 5, 2004 at 3:27am

+ + diff --git a/doc/html/drc.html b/doc/html/drc.html new file mode 100644 index 00000000..8e9fdb4b --- /dev/null +++ b/doc/html/drc.html @@ -0,0 +1,135 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

drc

+
+Background design rule checker control and status. +
+ +

Usage:

+
+ drc option

+
+ where option is one of the following: +
+
catchup +
Run checker and wait for it to complete +
check +
Recheck area under box in all cells +
count [total] +
Count error tiles in each cell under box. Option total + returns the total number of DRC error tiles in the cell. +
euclidean on|off +
Enable/disable Euclidean geometry checking +
find [nth] +
Locate next (or nth) error in current cell +
help +
Print help information +
off +
Turn off background checker +
on +
Reenable background checker +
status +
Report whether the background checker is on or off. +
printrules [file] +
Print out design rules in file or to stdout +
rulestats +
Print out statistics about design rule database +
statistics +
Print out statistics gathered by checker +
why +
Print out reasons for errors under box +
*halo [value] +
Without option value, prints out the DRC halo distance, + which is the largest distance at which a DRC interaction can + occur outside of any area to be checked. Becuase large DRC + haloes can cause very long delays in the interactive DRC + checks, it can be helpful to use value to force a + smaller halo. This causes certain DRC errors to be missed, + but allows all the basic short-distance design rules to be + checked without undue processing delays. +
*stepsize [value] +
The step size is the length of a side of the area into which + the DRC checker routine breaks up larger areas for more + efficient processing. Changing this value can greatly + effect the speed of the DRC checker, although it is + difficult to predict what step size is "optimal". Without + option value, returns the current value of the + step size. +
+
+
+ +

Summary:

+
+ The drc command controls the behavior of magic's "background" + design rule checker. Normally the design rule checker is invoked + whenever the design is changed and checks all parts of the design + close to the changed area that might have been affected by the + change. The design rule checker flags areas that have been checked + as it runs. It starts whenever a layout change has been made or + after any command has been executed if areas of the layout still + need to be checked. Any macro keystroke in the layout window or + command executed on the command line will interrupt the design + rule checker pending completion of the action, at which time + the design rule checker will be reactivated.

+ + The drc on and drc off options are the main controls + for starting and stopping the design rule checker. drc status + returns the status of the background checker, either "on" or "off". + The Tcl version of magic returns a boolean value (0 or 1).

+ + The drc check option marks all areas of the layout under the + box as requiring a check and restarts the design rule checker.

+ + The drc why and drc find commands can be used to + query errors in the layout discovered by the design rule checker. + drc why reports the reason for all error regions found + inside the magic cursor box. The drc find command + can be used to find errors that may not be visible inside the + current window view, or that may be difficult to find on a large + layout.

+ + The drc euclidean on command can be useful in cases where + vendor design rules intend a Euclidean distance metric (minimum + linear distance) rather than a Manhattan distance metric (minimum + distance in either the x or y direction, evaluated + separately). The default option is "off", as most vendor rules + and design rule checkers assume Manhattan distances when checking + rules.

+ + The remaining options are relativly obscure and unlikely to be + useful to the typical end-user.

+
+ +

Implementation Notes:

+
+ drc is implemented as a built-in magic command. +
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 5:39pm

+ + diff --git a/doc/html/dump.html b/doc/html/dump.html new file mode 100644 index 00000000..e9a79404 --- /dev/null +++ b/doc/html/dump.html @@ -0,0 +1,72 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

dump

+
+Copy contents of the indicated cell into the current edit cell. +
+ +

Usage:

+
+ dump cell [child child_refpoint] + [parent parent_refpoint] +

+
+ where cell is the name of the cell whose contents are to + be copied, and optional child_refpoint and + parent_refpoint are coordinate pairs of x y values, + or keywords ll, lr, ul, or ur. The + syntax and use of the reference points is the same as for the + getcell command. +
+
+ +

Summary:

+
+ The dump command copies contents of the indicated cell + cell into the current edit cell. Without arguments, + the contents are placed such that the lower left coordinate + of cell is at the cursor box lower left corner. With + the child argument, the indicated coordinate position + child_refpoint is used instead of the lower-left corner. + With the parent argument, the indicated coordinate + position parent_refpoint is used instead of the lower-left + corner of the cursor box. +
+ +

Implementation Notes:

+
+ dump is implemented as a built-in command in magic. +
+ +

See Also:

+
+ getcell +
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 2:53am

+ + diff --git a/doc/html/edit.html b/doc/html/edit.html new file mode 100644 index 00000000..d0b41985 --- /dev/null +++ b/doc/html/edit.html @@ -0,0 +1,54 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

edit

+
+Use selected cell as new edit cell +
+ +

Shortcuts:

+
+ Key macro e implements the command edit. +
+ +

Usage:

+
+ edit

+
+ +

Summary:

+
+ The edit command makes the selected cell the new edit cell. +
+ +

Implementation Notes:

+
+ edit is implemented as a built-in magic command. +
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 12:55am

+ + diff --git a/doc/html/element.html b/doc/html/element.html new file mode 100644 index 00000000..8603355b --- /dev/null +++ b/doc/html/element.html @@ -0,0 +1,198 @@ + + + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

element

+
+Handle generic drawing elements (line, box, text) in the layout. +
+ +

Usage:

+
+ element option

+
+ where option is one of the following: +
+
add type name parameters +
Create a new element. The name is a unique name + to be assigned to the new element. The parameters + depend on the type, and are as follows: +
+
line name style x1 y1 x2 y2 +
Create a new line element, with position starting + at coordinate x1 y1 and ending at x2 y2. + The line does not need to be on a Manhattan grid. + Initial coordinates must be on internal magic grid + points (that is, must be integer). However, half-grid + units can be generated with the configure + option (see below). +
rectangle name style llx lly urx ury +
Create a new box element, with lower left corner + at coordinate llx lly and upper right corner + at coordinate urx ury. +
text name style cx cy label_text +
Create a new text label at coordinate position + cx cy with text string "label_text". +
+ For an explanation of the style parameter, see + the configure option, below. +
delete name +
Delete an existing element by name. +
configure name config_option +
Configure or query an existing element named name. + config_option may be one of the following: +
+
text [new_label_text] +
+
style [add|remove [style_type]] +
With no arguments, return the list of styles used + to draw the element. With option add or + remove, add or remove, respectively, a + style from the list of styles for + an element. Styles are the same as styles for + tile types in magic, and are defined in the + "dstyle" file in the magic install directory. + The "dstyle" file declares a "long name" for each + style type. This "long name" is what is expected + for parameter style_type. The most useful + values are the colors defined in the "dstyle" file, + such as black, white, red, + etc.

+ + Like tile types, elements may be drawn in multiple + styles. So, styles are maintained as a list and + the element configure style option takes + the keyword add or remove to add + or remove specific styles from the list. + Removing the last remaining style for an element + is prohibited. Changing styles requires first + adding the new style type, then removing the + original. +

position [x y [x2 y2]] +
With no arguments, returns the position of the + element. For text elements, this is the label + position (a single coordinate). For lines, both + endpoint coordinates are returned, and for + rectangles, the lower-left and upper-right + coordinates are returned. With one or two coordinate + specified, the position of the element is changed. + For text, a single coordinate indicates the new + position of the text. For lines and rectangles, + the two coordinates completely describe the line + or box. +
flags flag_type +
Add or change flags of an element. The specific flag + indicated is set. Valid flags are as follows. + All elements have these flags: +
+
+
temporary +
Indicates an element that is not saved to the + database with a save or writeall + command (the default flag). +
persistant +
Indicates an element that is saved to the + database with a save or writeall + command, and can be recovered with a load + command. +
+
+ Text elements have the following additional flags: +
+
+
small, medium, large, + xlarge +
One of four text sizes. +
direction +
Any valid direction specification in + magic will be translated to a text + justification; that is, the text will be + printed relative to its position in the + indicated direction. +
+
+ Line elements have the following additional flags: +
+
+
halfx, halfy +
Adjust the position of the line endpoints + by one-half unit (postive, that is, right + or up). This allows lines to be drawn on, + for example, wire centerlines. There is + no allowance for having only one endpoint + on the half-integer grid. +
exactx, exacty +
Set line endpoints on the exact coordinates + of the line position (the default flag). +
arrowleft, arrowbottom + arrowtop, arrowright +
Add arrows to the line endpoints at the + indicated end. Note that four possible + positions are allowed, although only two + will be relevant for any given line. + Arrowheads are of fixed size and may not + be visible at large zoom factors. +
plainleft, plainbottom + plaintop, plaintright +
Draw plain lines, with no arrowheads + (the default flags). +
+
+ Rectangle elements have no additional flags. +
+
names +
Print names of all elements +
inbox +
Print name of element in (or nearest) the box +
help +
Print help information +
+
+
+ +

Summary:

+
+ The element command creates and manipulates + general-purpose "elements", which are lines, rectangles, + and text that have no inherent meaning to the database. + They are positioned in units of the layout and so scale + and move with zooms and pans. They are intended to be + used for layout annotation, measurement rulers, user-defined + feedback, flylines, wire paths, and so forth. +
+ +

Implementation Notes:

+
+ element is implemented as a built-in magic command. + The syntax is complicated and is expected to be driven by Tcl + scripts with simpler syntax for specific purposes such as + annotation or measurement rulers. +
+ +

+ + + +
Return to command index +
+

Last updated: October 5, 2004 at 6:32am

+ + diff --git a/doc/html/erase.html b/doc/html/erase.html new file mode 100644 index 00000000..503fd0df --- /dev/null +++ b/doc/html/erase.html @@ -0,0 +1,84 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

erase

+
+Erase paint from the layout inside the bounds of the cursor box. +
+ +

Shortcuts:

+
+ Key macro Control-D implements the command "erase $", + which indicates to erase all paint and labels in the cursor box.
+ + Key e typed while the cursor is in a layer box in the GUI toolbar + implements the command "erase layer", passing the layer + type in the toolbar.
+ + Key Shift plus Mouse button 2 implements the command + erase cursor when using the "box tool" in a layout + window.
+
+ +

Usage:

+
+ erase [layers|cursor]

+
+ where layers is a comma-separated list of layer types + to be erased, or * to indicate all paint but not labels, + or $ to indicate both paint and labels. +
+
+ +

Summary:

+
+ The erase command erases paint inside the cursor box in the + current edit cell. Without arguments, everything inside the box + is erased. With argument layers, only the indicated layers + are erased.

+ + Note that some layer types, such as DRC paint, cannot be erased. + Feedback areas are not considered paint and should be erased + using the feedback clear command.

+ + The option "erase cursor" picks the layers at the position + of the (X11) cursor and erases these from the area of the cursor + box. +

+ +

Implementation Notes:

+
+ erase is implemented as a built-in magic command. +
+ +

See Also:

+
+ paint
+
+ +

+ + + +
Return to command index +
+

Last updated: November 8, 2004 at 3:02pm

+ + diff --git a/doc/html/expand.html b/doc/html/expand.html new file mode 100644 index 00000000..63f812d3 --- /dev/null +++ b/doc/html/expand.html @@ -0,0 +1,69 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

expand

+
+Expand everything inside or touching the cursor box, or toggle +expanded/unexpanded cells in the current selection. +
+ +

Usage:

+
+ expand [toggle]

+
+ +

Shortcuts:

+
+ Key macro x implements the command expand.
+ Key macro Control-X implements the command expand toggle. +
+ +

Summary:

+
+ The expand command expands the view of subcells to + display the contents of the subcells. Without arguments, + the expand command expands all unexpanded subcells that + touch or intersect the cursor box in the layout window.

+ + Option expand toggle operates on the current selection, + not relative to the cursor box, and will expand a selected + cell that is unexpanded, or unexpand a cell that is already + expanded. +

+ +

Implementation Notes:

+
+ expand is implemented as a built-in magic command. +
+ +

See Also:

+
+ unexpand
+
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 2:17pm

+ + diff --git a/doc/html/ext.html b/doc/html/ext.html new file mode 100644 index 00000000..c093c993 --- /dev/null +++ b/doc/html/ext.html @@ -0,0 +1,138 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

ext, extract

+
+Circuit netlist extractor +
+ +

Usage:

+
+ extract option

+
+ where option may be one of the following: +
+
all +
Extract the root cell and all its children. This bypasses + the incremental extraction and ensures that a new .ext + file is written for every cell definition. +
cell name +
Extract the indicated cell into file name +
do|no [option] +
Enable or disable an extractor option, where option + may be one of the following: +
+
+
capacitance +
+
resistance +
+
coupling +
+
length +
+
adjust +
+
all +
+
+
+ +
length [option] +
Control pathlength extraction information, where option + may be one of the following: +
+
+
driver termname +
+
receiver termname +
+
clear +
+
+
+ +
help +
Print help information +
parents +
Extract the selected cell and all its parents +
showparents +
List the cell and all parents of selected cell. Note that + this is not really an extract option and is superceded by + the cellname command. +
[list|listall] style [stylename] +
Set the current extraction style to stylename. + Without arguments, print the current extraction style. + With keyword list, return the current extraction + style as a Tcl result. With keyword listall, return + all valid extraction styles for the technology as a Tcl + list. +
unique [#] +
Generate unique names when different nodes have the same name +
warn [[no] option] +
Enable/disable reporting of non-fatal errors, where option + may be one of the following: +
+
+
fets +
+
labels +
+
dup +
+
all +
+
+
+
+
+
+ +

Summary:

+
+ With no options given, the extract command incrementally + extracts the root cell and all its children into separate + .ext files. With options, the effect is as described + in the Usage section above. +
+ +

Implementation Notes:

+
+ extract is implemented as a built-in magic command.

+ ext is an alias for command extract (allowed + abbreviation where the usage would otherwise be ambiguous). +

+ +

See Also:

+
+ extresist
+ ext2spice
+ ext2sim
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 3:16am

+ + diff --git a/doc/html/ext2sim.html b/doc/html/ext2sim.html new file mode 100644 index 00000000..ebec2710 --- /dev/null +++ b/doc/html/ext2sim.html @@ -0,0 +1,161 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

ext2sim, exttosim

+
+Convert extracted file(s) to a ".sim" format file. +
+ +

Usage:

+
+ ext2sim [option]

+
+ where option is one of the following: +
+
[run] [runtime_options] +
Run exttosim on current cell, with command-line options + (see Summary, below). +
alias on|off +
Enable/disable alias (.al) file +
labels on|off +
Enable/disable labels (.nodes) file +
default +
Reset to default values +
format MIT|SU|LBL +
Set output format +
rthresh [value] +
Set resistance threshold value. Lumped resistances + below this value will not be written to the output. The + value is in ohms, or may be the keyword infinite + to prohibit writing any lumped resistances to the output. +
cthresh [value] +
Set capacitance threshold value. The value is in femtofarads, + or may be the keyword infinite to prohibit writing + any parasitic capacitances to the output. +
merge [merge_option] +
Merge parallel devices/transistors. The valid merge options are: +
+
+
conservative +
Merge transistors and capacitors having the same device + type and node connections and having the same width and + length. Widths are summed in the final output for + transistors. Capacitor values are summed in the final + output. +
aggressive +
Merge transistors having the same node + connections and having the same length. Widths + are summed in the final output. Merge any capacitors + having the same device type and node connections. + Capacitance is summed in the final output. +
none +
Do not merge any devices. +
+
+
extresist on|off +
Incorporate output from the command extresist into + the final .sim file. +
help +
Print help information +
+ +
+
+ +

Summary:

+
+ Without options, or with the option run, + the ext2sim command converts the hierarchical extracted + netlist information produced by the extract command in + a series of .ext files into a flattened representation + in the .sim format, used for switch-level simulation.

+ + runtime_options may be passed on the command line, and + represent the original command-line options passed to the + standalone version of ext2sim. A number of the original + command-line options have been deprecated in the Tcl-based + version, and some are duplicated by other ext2sim options. + Valid runtime_options are: +

+
+
-B +
Don't output transistor or node attributes in the .sim file. + This option will also disable the output of information such + as the area and perimeter of source and drain diffusion and + the FET substrate. +
-F +
Don't output nodes that aren't connected to devices (floating + nodes). +
-tchar +
Trim characters from node names when writing the output file. + char should be either "#" or "!". The + option may be used twice if both characters require trimming. +
-y num +
Select the precision for outputting capacitors. The default is + 1 which means that the capacitors will be printed to a precision + of 0.1 fF. +
-J hier|flat +
Select the source/drain area and perimeter extraction algorithm. + If hier is selected then the areas and perimeters are + extracted only within each subcell. For each device in a + subcell the area and perimeter of its source and drain within + this subcell are output. If two or more devices share a + source/drain node then the total area and perimeter will be + output in only one of them and the other will have 0. If + flat is selected the same rules apply, only the scope + of search for area and perimeter is the whole netlist. In + general, flat (which is the default) will give accurate + results (it will take into account shared sources/drains). +
+
+ + With options, the command sets various parameters affecting the + output format and content.

+

+ +

Implementation Notes:

+
+ ext2sim is implemented as a separate loadable Tcl package, + but one which depends on the presence of the standard "tclmagic" + package. magic is set up with a placeholder command for + ext2sim, and will automatically load the Tcl package when + this command is invoked.

+ + exttosim is an alias for ext2sim, to satisfy the + grammatically anal retentive. +

+ +

See Also:

+
+ extract
+ extresist
+ ext2spice
+ irsim
+
+ +

+ + + +
Return to command index +
+

Last updated: October 12, 2005 at 9:40pm

+ + diff --git a/doc/html/ext2spice.html b/doc/html/ext2spice.html new file mode 100644 index 00000000..ca12ce67 --- /dev/null +++ b/doc/html/ext2spice.html @@ -0,0 +1,176 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

ext2spice, exttospice

+
+Convert extracted file(s) to a SPICE format file. +
+ +

Usage:

+
+ ext2spice [option]

+
+ where option is one of the following: +
+
[run] [runtime_options] +
Run ext2spice on current cell, with command-line options + (see Summary, below). +
default +
Reset to default values +
format hspice|spice2|spice3 +
Set output format. spice3 is the default, + for compatibility with tclspice. This is a + change from previous versions of magic, where the + default was hspice. +
rthresh [value] +
Set resistance threshold value. Lumped resistances + below this value will not be written to the output. The + value is in ohms, or may be the keyword infinite + to prohibit writing any lumped resistances to the output. +
cthresh [value] +
Set capacitance threshold value. The value is in femtofarads, + or may be the keyword infinite to prohibit writing + any parasitic capacitances to the output. +
merge [merge_option] +
Merge parallel devices/transistors. The valid merge options are: +
+
+
conservative +
Merge transistors and capacitors having the same device + type and node connections and having the same width and + length. Widths are summed in the final output for + transistors. Capacitor values are summed in the final + output. +
aggressive +
Merge transistors having the same node + connections and having the same length. Widths + are summed in the final output. Merge any capacitors + having the same device type and node connections. + Capacitance is summed in the final output. +
none +
Do not merge any devices. +
+
+
extresist on|off +
Incorporate output from the command extresist into + the final SPICE file. +
resistor tee [on|off] +
Model resistor capacitance as a T-network. Each resistor + device is split into two, with all substrate and overlap + capacitance placed on the node between the two half-length + devices. Without this option, resistor devices lose all + parasitic capacitance information, and ext2spice + may produce warnings about unknown nodes. However, use of + this option may conflict with LVS (layout-vs.-schematic), + when only one resistor is expected per drawn device. +
subcircuits [on|off] +
When set to on (the default), standard cells become + subcircuit calls ("X") in the SPICE output. The contents + of the standard cells are not output, and it is assumed + that a pre-characterized SPICE deck exists modeling the + behavior of each standard cell definition. Standard cells + are defined by the use of the port method for + labeling input and output ports. When set to off, + ports are ignored, and the entire circuit hierarchy is + flattened down to the device level. +
help +
Print help information. +
+
+
+ +

Summary:

+
+ Without options, or with the option run, + the ext2spice command converts the hierarchical extracted + netlist information produced by the extract command in + a series of .ext files into a flattened representation + in SPICE format, used for detailed analog simulation.

+ + runtime_options may be passed on the command line, and + represent the original command-line options passed to the + standalone version of ext2spice. A number of the original + command-line options have been deprecated in the Tcl-based + version, and some are duplicated by other ext2spice options. + Valid runtime_options are: +

+
+
-B +
Don't output transistor or node attributes in the SPICE file. + This option will also disable the output of information such + as the area and perimeter of source and drain diffusion and + the FET substrate. +
-F +
Don't output nodes that aren't connected to devices (floating + nodes). +
-tchar +
Trim characters from node names when writing the output file. + char should be either "#" or "!". The + option may be used twice if both characters require trimming. +
-y num +
Select the precision for outputting capacitors. The default is + 1 which means that the capacitors will be printed to a precision + of 0.1 fF. +
-J hier|flat +
Select the source/drain area and perimeter extraction algorithm. + If hier is selected then the areas and perimeters are + extracted only within each subcell. For each device in a + subcell the area and perimeter of its source and drain within + this subcell are output. If two or more devices share a + source/drain node then the total area and perimeter will be + output in only one of them and the other will have 0. If + flat is selected the same rules apply, only the scope + of search for area and perimeter is the whole netlist. In + general, flat (which is the default) will give accurate + results (it will take into account shared sources/drains). +
+
+ + With options, the command sets various parameters affecting the + output format and content.

+

+ +

Implementation Notes:

+
+ ext2spice is implemented as a separate loadable Tcl package, + but one which depends on the presence of the standard "tclmagic" + package. magic is set up with a placeholder command for + ext2spice, and will automatically load the Tcl package when + this command is invoked.

+ + exttospice is an alias for ext2spice, to satisfy the + grammatically anal retentive. +

+ +

See Also:

+
+ extract
+ ext2sim
+
+ +

+ + + +
Return to command index +
+

Last updated: October 12, 2005 at 9:40pm

+ + diff --git a/doc/html/extract.html b/doc/html/extract.html new file mode 100644 index 00000000..c093c993 --- /dev/null +++ b/doc/html/extract.html @@ -0,0 +1,138 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

ext, extract

+
+Circuit netlist extractor +
+ +

Usage:

+
+ extract option

+
+ where option may be one of the following: +
+
all +
Extract the root cell and all its children. This bypasses + the incremental extraction and ensures that a new .ext + file is written for every cell definition. +
cell name +
Extract the indicated cell into file name +
do|no [option] +
Enable or disable an extractor option, where option + may be one of the following: +
+
+
capacitance +
+
resistance +
+
coupling +
+
length +
+
adjust +
+
all +
+
+
+ +
length [option] +
Control pathlength extraction information, where option + may be one of the following: +
+
+
driver termname +
+
receiver termname +
+
clear +
+
+
+ +
help +
Print help information +
parents +
Extract the selected cell and all its parents +
showparents +
List the cell and all parents of selected cell. Note that + this is not really an extract option and is superceded by + the cellname command. +
[list|listall] style [stylename] +
Set the current extraction style to stylename. + Without arguments, print the current extraction style. + With keyword list, return the current extraction + style as a Tcl result. With keyword listall, return + all valid extraction styles for the technology as a Tcl + list. +
unique [#] +
Generate unique names when different nodes have the same name +
warn [[no] option] +
Enable/disable reporting of non-fatal errors, where option + may be one of the following: +
+
+
fets +
+
labels +
+
dup +
+
all +
+
+
+
+
+
+ +

Summary:

+
+ With no options given, the extract command incrementally + extracts the root cell and all its children into separate + .ext files. With options, the effect is as described + in the Usage section above. +
+ +

Implementation Notes:

+
+ extract is implemented as a built-in magic command.

+ ext is an alias for command extract (allowed + abbreviation where the usage would otherwise be ambiguous). +

+ +

See Also:

+
+ extresist
+ ext2spice
+ ext2sim
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 3:16am

+ + diff --git a/doc/html/extresist.html b/doc/html/extresist.html new file mode 100644 index 00000000..772d5a34 --- /dev/null +++ b/doc/html/extresist.html @@ -0,0 +1,118 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

extresist

+
+Patch the extraction .ext files with detailed route resistance +information. +
+ +

Usage:

+
+ extresist option

+
+ where option may be one of the following: +
+
tolerance value +
Set the ratio between resistor and transistor tolerance + for determining when to insert resistance into a network route. +
all +
Extract all the nets. +
simplify [on|off] +
Turn on/off simplification of resistor nets. +
extout [on|off] +
Turn on/off writing of the .res.ext file. +
lumped [on|off] +
Turn on/off writing of updated lumped resistances. +
silent [on|off] +
Turn off/on printing of net statistics. +
skip mask +
Don't extract types indicated in the comma-separated list mask +
box type +
Extract the signal under the cursor box on layer type +
cell cellname +
Extract the network for the cell named cellname +
geometry +
Extract network geometry and present as a collection of line + elements on the layout. +
fasthenry [freq] +
Extract subcircuit network geometry into a fasthenry-format + .fh file. If freq is specified, the file will + be customized for fasthenry analysis at the indicated + frequency (in Hz). +
help +
Print help information +
+
+
+ +

Summary:

+
+ The normal flow through layout extraction into a simulation file + treats routes as nonphysical entities, that is, with infinitesimal + impedence through the wires. Extraction for digital simulation + using irsim generates "lumped resistances", a single + resistance per network node that, along with the node capacitance + to substrate, provides an RC time constant to approximately + model the delay from point to point in the network node. The + lumped resistance model is inappropriate for analog (i.e., SPICE) + simulation, and for digital simulation, is a poor approximation + for branching networks, where the delay between endpoints is + different for each pair of endpoints in the network node.

+ + The extresist command provides a method for generating + a more detailed model of resistance, in which long network + routes and branching routes are replaced with resistor devices + and device networks.

+ + Using extresist is a multi-step process. It is first + necessary to run both extract and ext2sim to get + the initial netlist (with lumped, not detailed, resistances). + After a .sim file has been generated, the + extresist all command may be run. The output is + a file .res.ext for each cell in the hierarchy. + Finally, with the option extresist on set, + ext2sim or ext2spice will generate the final, + detailed simulation file.

+ + More details on using extresist can be found in + magic Tutorial number 8. +

+ +

Implementation Notes:

+
+ extresist is implemented as a built-in command in magic. +
+ +

See Also:

+
+ extract
+ ext2sim
+
+ +

+ + + +
Return to command index +
+

Last updated: October 21, 2004 at 10:48am

+ + diff --git a/doc/html/exttosim.html b/doc/html/exttosim.html new file mode 100644 index 00000000..ebec2710 --- /dev/null +++ b/doc/html/exttosim.html @@ -0,0 +1,161 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

ext2sim, exttosim

+
+Convert extracted file(s) to a ".sim" format file. +
+ +

Usage:

+
+ ext2sim [option]

+
+ where option is one of the following: +
+
[run] [runtime_options] +
Run exttosim on current cell, with command-line options + (see Summary, below). +
alias on|off +
Enable/disable alias (.al) file +
labels on|off +
Enable/disable labels (.nodes) file +
default +
Reset to default values +
format MIT|SU|LBL +
Set output format +
rthresh [value] +
Set resistance threshold value. Lumped resistances + below this value will not be written to the output. The + value is in ohms, or may be the keyword infinite + to prohibit writing any lumped resistances to the output. +
cthresh [value] +
Set capacitance threshold value. The value is in femtofarads, + or may be the keyword infinite to prohibit writing + any parasitic capacitances to the output. +
merge [merge_option] +
Merge parallel devices/transistors. The valid merge options are: +
+
+
conservative +
Merge transistors and capacitors having the same device + type and node connections and having the same width and + length. Widths are summed in the final output for + transistors. Capacitor values are summed in the final + output. +
aggressive +
Merge transistors having the same node + connections and having the same length. Widths + are summed in the final output. Merge any capacitors + having the same device type and node connections. + Capacitance is summed in the final output. +
none +
Do not merge any devices. +
+
+
extresist on|off +
Incorporate output from the command extresist into + the final .sim file. +
help +
Print help information +
+ +
+
+ +

Summary:

+
+ Without options, or with the option run, + the ext2sim command converts the hierarchical extracted + netlist information produced by the extract command in + a series of .ext files into a flattened representation + in the .sim format, used for switch-level simulation.

+ + runtime_options may be passed on the command line, and + represent the original command-line options passed to the + standalone version of ext2sim. A number of the original + command-line options have been deprecated in the Tcl-based + version, and some are duplicated by other ext2sim options. + Valid runtime_options are: +

+
+
-B +
Don't output transistor or node attributes in the .sim file. + This option will also disable the output of information such + as the area and perimeter of source and drain diffusion and + the FET substrate. +
-F +
Don't output nodes that aren't connected to devices (floating + nodes). +
-tchar +
Trim characters from node names when writing the output file. + char should be either "#" or "!". The + option may be used twice if both characters require trimming. +
-y num +
Select the precision for outputting capacitors. The default is + 1 which means that the capacitors will be printed to a precision + of 0.1 fF. +
-J hier|flat +
Select the source/drain area and perimeter extraction algorithm. + If hier is selected then the areas and perimeters are + extracted only within each subcell. For each device in a + subcell the area and perimeter of its source and drain within + this subcell are output. If two or more devices share a + source/drain node then the total area and perimeter will be + output in only one of them and the other will have 0. If + flat is selected the same rules apply, only the scope + of search for area and perimeter is the whole netlist. In + general, flat (which is the default) will give accurate + results (it will take into account shared sources/drains). +
+
+ + With options, the command sets various parameters affecting the + output format and content.

+

+ +

Implementation Notes:

+
+ ext2sim is implemented as a separate loadable Tcl package, + but one which depends on the presence of the standard "tclmagic" + package. magic is set up with a placeholder command for + ext2sim, and will automatically load the Tcl package when + this command is invoked.

+ + exttosim is an alias for ext2sim, to satisfy the + grammatically anal retentive. +

+ +

See Also:

+
+ extract
+ extresist
+ ext2spice
+ irsim
+
+ +

+ + + +
Return to command index +
+

Last updated: October 12, 2005 at 9:40pm

+ + diff --git a/doc/html/exttospice.html b/doc/html/exttospice.html new file mode 100644 index 00000000..ca12ce67 --- /dev/null +++ b/doc/html/exttospice.html @@ -0,0 +1,176 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

ext2spice, exttospice

+
+Convert extracted file(s) to a SPICE format file. +
+ +

Usage:

+
+ ext2spice [option]

+
+ where option is one of the following: +
+
[run] [runtime_options] +
Run ext2spice on current cell, with command-line options + (see Summary, below). +
default +
Reset to default values +
format hspice|spice2|spice3 +
Set output format. spice3 is the default, + for compatibility with tclspice. This is a + change from previous versions of magic, where the + default was hspice. +
rthresh [value] +
Set resistance threshold value. Lumped resistances + below this value will not be written to the output. The + value is in ohms, or may be the keyword infinite + to prohibit writing any lumped resistances to the output. +
cthresh [value] +
Set capacitance threshold value. The value is in femtofarads, + or may be the keyword infinite to prohibit writing + any parasitic capacitances to the output. +
merge [merge_option] +
Merge parallel devices/transistors. The valid merge options are: +
+
+
conservative +
Merge transistors and capacitors having the same device + type and node connections and having the same width and + length. Widths are summed in the final output for + transistors. Capacitor values are summed in the final + output. +
aggressive +
Merge transistors having the same node + connections and having the same length. Widths + are summed in the final output. Merge any capacitors + having the same device type and node connections. + Capacitance is summed in the final output. +
none +
Do not merge any devices. +
+
+
extresist on|off +
Incorporate output from the command extresist into + the final SPICE file. +
resistor tee [on|off] +
Model resistor capacitance as a T-network. Each resistor + device is split into two, with all substrate and overlap + capacitance placed on the node between the two half-length + devices. Without this option, resistor devices lose all + parasitic capacitance information, and ext2spice + may produce warnings about unknown nodes. However, use of + this option may conflict with LVS (layout-vs.-schematic), + when only one resistor is expected per drawn device. +
subcircuits [on|off] +
When set to on (the default), standard cells become + subcircuit calls ("X") in the SPICE output. The contents + of the standard cells are not output, and it is assumed + that a pre-characterized SPICE deck exists modeling the + behavior of each standard cell definition. Standard cells + are defined by the use of the port method for + labeling input and output ports. When set to off, + ports are ignored, and the entire circuit hierarchy is + flattened down to the device level. +
help +
Print help information. +
+
+
+ +

Summary:

+
+ Without options, or with the option run, + the ext2spice command converts the hierarchical extracted + netlist information produced by the extract command in + a series of .ext files into a flattened representation + in SPICE format, used for detailed analog simulation.

+ + runtime_options may be passed on the command line, and + represent the original command-line options passed to the + standalone version of ext2spice. A number of the original + command-line options have been deprecated in the Tcl-based + version, and some are duplicated by other ext2spice options. + Valid runtime_options are: +

+
+
-B +
Don't output transistor or node attributes in the SPICE file. + This option will also disable the output of information such + as the area and perimeter of source and drain diffusion and + the FET substrate. +
-F +
Don't output nodes that aren't connected to devices (floating + nodes). +
-tchar +
Trim characters from node names when writing the output file. + char should be either "#" or "!". The + option may be used twice if both characters require trimming. +
-y num +
Select the precision for outputting capacitors. The default is + 1 which means that the capacitors will be printed to a precision + of 0.1 fF. +
-J hier|flat +
Select the source/drain area and perimeter extraction algorithm. + If hier is selected then the areas and perimeters are + extracted only within each subcell. For each device in a + subcell the area and perimeter of its source and drain within + this subcell are output. If two or more devices share a + source/drain node then the total area and perimeter will be + output in only one of them and the other will have 0. If + flat is selected the same rules apply, only the scope + of search for area and perimeter is the whole netlist. In + general, flat (which is the default) will give accurate + results (it will take into account shared sources/drains). +
+
+ + With options, the command sets various parameters affecting the + output format and content.

+

+ +

Implementation Notes:

+
+ ext2spice is implemented as a separate loadable Tcl package, + but one which depends on the presence of the standard "tclmagic" + package. magic is set up with a placeholder command for + ext2spice, and will automatically load the Tcl package when + this command is invoked.

+ + exttospice is an alias for ext2spice, to satisfy the + grammatically anal retentive. +

+ +

See Also:

+
+ extract
+ ext2sim
+
+ +

+ + + +
Return to command index +
+

Last updated: October 12, 2005 at 9:40pm

+ + diff --git a/doc/html/feedback.html b/doc/html/feedback.html new file mode 100644 index 00000000..092cfcb3 --- /dev/null +++ b/doc/html/feedback.html @@ -0,0 +1,127 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

feedback

+
+Query or manipulate feedback entry areas. +
+ +

Usage:

+
+ feedback option

+
+ where option may be one of the following: +
+
add text [style] [x1 y1 ...] +
Create a new feedback area. If positions x1 y1 ... + are not specified, then the feedback area created + corresponds to the area of the cursor box. + The feedback entry will be associated with the text + text, which will be reported on execution of + a feedback why query. The feedback area will + be drawn in style style, which may be one of + the following: +
    +
  • dotted +
  • medium +
  • outline +
  • pale +
  • solid +
+ From magic version 7.3.110, any style from + the ".dstyle" file may be specified (e.g., "yellow1"). + If points x1 y1 ... are specified, then they + represent a polygonal area for the feedback entry. + This area may be a point, line, or polygon, and may be + specified in internal units or metric units. If the + feedback area is a point, line, or degenerate polygon + (polygon with zero internal area), then the style + must be an outlined style; otherwise, the style is changed + to style outline so that the feedback area is + ensured to be visible. +
clear [substring] +
Without the argument substring, clears all feedback info. + When substring is specified, only feedback entries + containing the text substring will be removed. For + example, if "cif see CMF" is followed by "cif see CCC", the + contact cuts will not be seen due to being overlapped by + the feedback for metal1. However, if this is followed by + "feedback clear CMF", the feedback area for metal1 will + be removed, leaving the contact cuts visible. +
count +
Count the number of feedback entries +
find [nth] +
Put the cursor box over next (or nth) entry +
help +
Print help information +
save file +
Save feedback area information into file file +
why +
Print text associated with all feedback areas under + the cursor box. +
+
+
+ +

Summary:

+
+ The feedback command queries or manipulates feedback + areas, which are areas drawn on top of the layout and may + be used for annotations and markers. Internally, magic + uses feedback areas to report CIF/GDS layers (cif see + command), and errors generated by the extract command. + CIF/GDS feedback is placed on the output (usually centimicron) + grid, which cannot be done with the feedback add + command directly from the command-line. +

+ + Feedback information and areas are not saved in the layout + file.

+

+ +

Implementation Notes:

+
+ feedback is implemented as a built-in magic command. +
+ +

Bugs:

+
+ Small feedback areas were previously drawn solid to prevent them + from disappearing entirely; however, this created bizarre results + in CIF/GDS feedback when several narrow feedback areas are tiled + together, so it was removed. This leaves the possibility that + feedback areas smaller than the spacing between feedback + crosshatch lines might not be drawn; an inconvenience, but + not a serious problem.

+ + There should be a mechanism for removing only the feedback entries + under the cursor box, or the current feedback entry.

+

+ + +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 8:32pm

+ + diff --git a/doc/html/fill.html b/doc/html/fill.html new file mode 100644 index 00000000..475f5cb5 --- /dev/null +++ b/doc/html/fill.html @@ -0,0 +1,67 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

fill

+
+Fill layers from one side of box to other. +
+ +

Usage:

+
+ fill direction [layers]

+
+ where direction is any valid Manhattan + direction in magic, and + layers is an optional comma-separated list of layers + to restrict the operation of the fill command. +
+
+ +

Summary:

+
+ The fill command extends paint from one side of the + cursor box to the other. It is most often used to fill + gaps in wire routes or fill paint between subcells. The + algorithm is to select all paint that touches or crosses + the cursor box on the side opposite the indicated direction, + and extend this paint in the indicated direction to the + other side of the cursor box. Paint that is in the cursor box + but does not touch the side of entry is not changed. +
+ +

Implementation Notes:

+
+ fill is implemented as a built-in command in magic. +
+ +

See Also:

+
+ corner
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 1:42am

+ + diff --git a/doc/html/findbox.html b/doc/html/findbox.html new file mode 100644 index 00000000..23425cda --- /dev/null +++ b/doc/html/findbox.html @@ -0,0 +1,60 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

findbox

+
+Center the window on the box and optionally zoom in. +
+ +

Shortcuts:

+
+ Key macro B implements the command findbox.
+ Key macro Control-Z implements the command findbox zoom. +
+ +

Usage:

+
+ findbox [zoom]

+
+ +

Summary:

+
+ The findbox command centers the window on the cursor box. + This is particularly useful in conjunction with other commands + such as drc find or feedback find that may move + the box to an unknown off-screen location. With the option + zoom, the window view will be centered on the cursor box + and additionally scaled so that the cursor box fills the window. +
+ +

Implementation Notes:

+
+ findbox is implemented as a built-in command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 1:46am

+ + diff --git a/doc/html/findlabel.html b/doc/html/findlabel.html new file mode 100644 index 00000000..00034d22 --- /dev/null +++ b/doc/html/findlabel.html @@ -0,0 +1,58 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

findlabel

+
+Set the cursor box to the location of the indicated label +
+ +

Usage:

+
+ findlabel label [-glob]

+
+ where label is the name of an existing label in magic. +
+
+ +

Summary:

+
+ The findlabel command can be used to center the cursor box + on a specific named label in the layout.

+ + The -glob option causes findlabel to find all labels + containing the text pattern of label. This is the way the + findlabel command worked in versions of magic prior + to 7.2. +

+ +

Implementation Notes:

+
+ findlabel is implemented as a built-in command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: November 7, 2004 at 3:32pm

+ + diff --git a/doc/html/flatten.html b/doc/html/flatten.html new file mode 100644 index 00000000..69f51faf --- /dev/null +++ b/doc/html/flatten.html @@ -0,0 +1,81 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

flatten

+
+Flatten edit cell into the indicated destination cell. +
+ +

Usage:

+
+ flatten cellname [option]

+
+ where cellname is the name of a cell definition to be + created, and into which the flattened geometry will be placed. + option may be one of -nolabels, -nosubcircuit, + or -novendor. +
+
+ +

Summary:

+
+ The flatten command creates a new cell with the indicated + name, then flattens the hierarchy of the current edit cell and + copies the result into the new cell.

+ + The options allow selective flattening, as follows: +

+
-nolabels +
Prevents magic from copying labels into the flattened cell. + Otherwise, magic flattens labels by prepending the cell + hierarchy to each label as it copies it into the flat cell. +
-nosubcircuit +
Prevents magic from flattening cells declared to be subcircuits + (by the presence of ports in the cell). These cells are + retained as subcells in the flattened version. +
-novendor +
Prevents magic from flattening cells that are vendor cells, + that is, cells that are generated by reading GDS using the + gds readonly option, or which have the appropriate + property values set. + +
+ + Note that cellname is a top-level cell but is not displayed + or saved subsequent to the flatten command. The usual + procedure is to follow the command "flatten cellname" + with "load cellname", to view the new flattened + layout. +
+ +

Implementation Notes:

+
+ flatten is implemented as a built-in command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 8:04pm

+ + diff --git a/doc/html/flush.html b/doc/html/flush.html new file mode 100644 index 00000000..f6ee5f25 --- /dev/null +++ b/doc/html/flush.html @@ -0,0 +1,63 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

flush

+
+Forget changes to the edit cell (or to the indicated cell) since the +last saved version. +
+ +

Usage:

+
+ flush [cellname]

+
+ where cellname is the name of a cell definition to be + flushed. +
+
+ +

Summary:

+
+ The flush command reverts a cell definition to the last + version saved to disk, forgetting all changes made in the + interim. Without arguments, the current edit cell is flushed. + Otherwise, the named cell is flushed.

+ + The effects of the flush command are irrevocable; the + command cannot be undone with an undo command. +

+ +

Implementation Notes:

+
+ flush is implemented as a built-in command in magic. + However, it conflicts with the Tcl flush command that + flushes an output pipe. Special processing determines which use + is intended. +
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 2:06am

+ + diff --git a/doc/html/garoute.html b/doc/html/garoute.html new file mode 100644 index 00000000..e4918e1e --- /dev/null +++ b/doc/html/garoute.html @@ -0,0 +1,81 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

garoute

+
+Gate-array router +
+ + + +

Usage:

+
+ garoute option

+
+ where option may be one of the following: +
+
channel xl yl xh yh [type] +
Define a channel, with indicated coordinates. +
channel [type] +
Define a channel +
generate h|h [file] +
Generate channel definition for a horizontal (h) + or vertical (v) routing channel. +
help +
Print help information +
nowarn +
Only warn if all locations of a terminal are unreachable. +
route [netlist] +
Route the current cell +
reset +
Clear all channel definitions +
warn +
Leave feedback for each location of a terminal that is + unreachable. +
+
+
+ +

Summary:

+
+ The garoute command controls the gate-array router. + There is currently practically no documentation for the gate-array + router. This section shall be expanded. +
+ +

Implementation Notes:

+
+ garoute is implemented as a built-in command in magic. +
+ +

See Also:

+
+ channel
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 2:35am

+ + diff --git a/doc/html/gds.html b/doc/html/gds.html new file mode 100644 index 00000000..770aa901 --- /dev/null +++ b/doc/html/gds.html @@ -0,0 +1,189 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

gds, calma

+
+Read GDSII input or generate GDSII output. +
+ +

Usage:

+
+ gds [option]

+ calma [option]

+
+ where option is one of the following: +
+
help +
Print usage information +
arrays [yes|no] +
Output arrays as individual subuses (like in CIF). Default + is "no". Normally there is no reason to do this. +
contacts [yes|no] +
Causes contacts to be written to the GDS file as subcell + arrays (experimental, introduced in version 7.3.55). This + method can produce very efficient output compared to writing + each contact cut square separately. +
flatten [yes|no] +
Flatten simple cells (e.g., contacts) on input. This helps + magic to use its contact-area representation of contacts, + and can also avoid situations where contacts are lost or + translated to "generic" types because the arrayed part of + the contacts is missing one or more residue layers. +
ordering [yes|no] +
Forces post-ordering of subcells read from a GDS file; that + is, if a cell use is encountered before it is defined, magic + will read through the remainder of the file until it finds + the definition, read it, and then return to the original file + position to continue reading. This option is always enabled + when using gds flatten. Otherwise, the default behavior + is ordering no to avoid lengthy searches through the + GDS stream file. +
labels [yes|no] +
Cause labels to be output when writing GDSII. Default + is "yes". Normally there is no reason not to do this. +
lower [yes|no] +
Allow both upper and lower case in labels. Default is "yes". +
read file +
Read GDSII format from file file into the edit cell. + If file does not have a file extension, then magic + searches for a file named file, file.gds, + file.gds2, or file.strm. +
readonly [yes|no] +
Set cell as "read-only". This has the effect of marking each + cell definition (using the property method) with the + start and end positions of the cell definition in the input + file. In subsequent output, the cell definition will be + transferred verbatim from the input to the output file. This + is useful for 3rd-party standard cells or pad cells where the + original GDS is trusted and it is desirable to bypass the + boolean operators of magic's GDS reader and writer to + prevent the layout from being altered. Note that "read-only" + layout can be written to a .mag file, but the + contents of this file are representational only. It can + be useful to keep a simplified respresentation in the case + of pad cells or digital standard cells, for example, by + reading them using a GDS input style that defines only metal + layers. +
rescale [yes|no] +
Allow or disallow internal grid subdivision while reading + GDS input. Default is "yes". Normally, one wants to allow + rescaling to ensure that the GDS is displayed exactly as it + is in the input file. Occasionally, however, the GDS input + is on a very fine scale, such as nanometers, and it is + preferable to snap the input to lambda boundaries rather + than to subsplit the internal grid to such a fine value. + The "cif limit" function may also be used to limit + grid subdivision to a minimum value. +
warning [option] +
Set warning information level. "option" may be one + of the following: +
+
default +
The default setting is equivalent to all the other + options (align, limit, redirect, + and none) being disabled. +
align +
Generate warnings during a "cif see" command + if the alignment of geometry is on fractional lambda. + Normally, magic allows contacts to be drawn at + half-lambda positions. If this violates DRC requirements + for the minimum output grid, this warning setting can be + used to detect such violations. +
limit +
Limit warnings to the first 100 warnings or errors only. +
redirect [file] +
Redirect all warnings to an output file named file. + If file is not given, then redirection is disabled. +
none +
Do not produce any warning messages on GDS input. +
+
write file +
Output GDSII format to "file" for the window's root cell. +
polygon subcells [yes|no] +
Put non-Manhattan polygons into subcells. Default is "no". + Normally this option is not needed. However, input layout + that defines a number of angled wires, particularly those + that are closely spaced, can cause magic to generate + literally millions of internal tiles. This tends to be + true in particular for corner cells in padframes for deep + submicron feature sizes, where the angled corners are + required to meet the DRC specification. When set to "yes", + each polygon encountered in the GDS input is placed in its + own uniquely-named subcell. This prevents interations with + other polygons on the same plane and so reduces tile splitting. +
+
+
+ +

Summary:

+
+ The gds command reads or produces GDSII output (also known as + "stream" output, or "calma" output after the name of the company + that invented the format), or sets various parameters affecting + the GDS input and output. In magic, the GDS read and write routines + are a subset of the CIF read and write routines, and so it is + important to note that certain cif command options (q.v.) also + affect GDS input and output. In particular, cif istyle and + cif ostyle set the input and output styles from the technology + file, respectively.

+ + If no option is given, a CALMA GDS-II stream file is produced for the + root cell, with the default name of the root cell definition and the + filename extension ".gds".

+

+ +

Implementation Notes:

+
+ gds is implemented as a built-in function in magic. + The calma command is an alias for gds and is + exactly equivalent. +
+ +

Bugs:

+
+
    +
  • The cif command options that affect GDS input and output + should really be duplicates as options of the GDS command. +
  • GDS input is "interpreted" through boolean operations in the + technology file definition, and so it is not guaranteed that + all input will be read correctly. +
  • Not all non-Manhattan geometry is read correctly. +
  • The input can be fouled up if the magic grid is rescaled during + input. This error can be avoided by scaling the grid prior + to GDS read-in. +
  • "polygon subcells" in GDS creates a duplicate image of the + layout read into the subcells; this needs to be fixed. +
+
+ +

See Also:

+
+ cif
+
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 3:17pm

+ + diff --git a/doc/html/get.html b/doc/html/get.html new file mode 100644 index 00000000..5312322b --- /dev/null +++ b/doc/html/get.html @@ -0,0 +1,102 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

get, getcell

+
+Import a cell as a subcell of the current edit cell. +
+ +

Usage:

+
+ getcell cellname [orientation]

+ getcell cellname [child child_refpoint] + [parent parent_refpoint]

+
+ where orientation may be one of the following: +
+
90 +
Load rotated by 90 degrees clockwise +
180 +
Load rotated by 180 degrees +
270 +
Load rotated by 90 degrees counterclockwise +
v +
Load flipped top to bottom +
h +
Load flipped left to right +
90v +
Load rotated 90 degrees clockwise and flipped top to bottom +
90h +
Load rotated 90 degrees clockwise and flipped left to right +
180v +
Load rotated 180 degrees and flipped top to bottom +
180h +
Load rotated 180 degrees and flipped left to right +
270v +
Load rotated 90 degrees counterclockwise and flipped top to bottom +
270h +
Load rotated 90 degrees counterclockwise and flipped left to right +
+ and child_refpoint and parent_refpoint may be + x y coordinate pairs, or one of the four keywords + ll, lr, ul, or ur, indicating + one of the four box corners. For the child, + coordinate pairs are in the coordinate system of the child, + and corners indicate cell bounding box corners. For the + parent, coordinate pairs are in the coordinate system of + the parent, and corners indicate corners of the cursor box. +
+
+ +

Summary:

+
+ The getcell command creates subcell instances within the + current edit cell. By default, with only the cellname + given, an orientation of zero is assumed, and the cell is placed + such that the lower-left corner of the cell's bounding box is + placed at the lower-left corner of the cursor box in the parent + cell.

+

+ +

Implementation Notes:

+
+ getcell is implemented as a built-in command in magic.

+ get is an alias for the command getcell (allowed + abbreviation where otherwise use would be ambiguous).

+ + Scripts will find it more convenient to place cells according to + the cell origin, with the usage "getcell cellname + child 0 0". +

+ +

See Also:

+
+ dump +
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 3:32am

+ + diff --git a/doc/html/getcell.html b/doc/html/getcell.html new file mode 100644 index 00000000..5312322b --- /dev/null +++ b/doc/html/getcell.html @@ -0,0 +1,102 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

get, getcell

+
+Import a cell as a subcell of the current edit cell. +
+ +

Usage:

+
+ getcell cellname [orientation]

+ getcell cellname [child child_refpoint] + [parent parent_refpoint]

+
+ where orientation may be one of the following: +
+
90 +
Load rotated by 90 degrees clockwise +
180 +
Load rotated by 180 degrees +
270 +
Load rotated by 90 degrees counterclockwise +
v +
Load flipped top to bottom +
h +
Load flipped left to right +
90v +
Load rotated 90 degrees clockwise and flipped top to bottom +
90h +
Load rotated 90 degrees clockwise and flipped left to right +
180v +
Load rotated 180 degrees and flipped top to bottom +
180h +
Load rotated 180 degrees and flipped left to right +
270v +
Load rotated 90 degrees counterclockwise and flipped top to bottom +
270h +
Load rotated 90 degrees counterclockwise and flipped left to right +
+ and child_refpoint and parent_refpoint may be + x y coordinate pairs, or one of the four keywords + ll, lr, ul, or ur, indicating + one of the four box corners. For the child, + coordinate pairs are in the coordinate system of the child, + and corners indicate cell bounding box corners. For the + parent, coordinate pairs are in the coordinate system of + the parent, and corners indicate corners of the cursor box. +
+
+ +

Summary:

+
+ The getcell command creates subcell instances within the + current edit cell. By default, with only the cellname + given, an orientation of zero is assumed, and the cell is placed + such that the lower-left corner of the cell's bounding box is + placed at the lower-left corner of the cursor box in the parent + cell.

+

+ +

Implementation Notes:

+
+ getcell is implemented as a built-in command in magic.

+ get is an alias for the command getcell (allowed + abbreviation where otherwise use would be ambiguous).

+ + Scripts will find it more convenient to place cells according to + the cell origin, with the usage "getcell cellname + child 0 0". +

+ +

See Also:

+
+ dump +
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 3:32am

+ + diff --git a/doc/html/getnode.html b/doc/html/getnode.html new file mode 100644 index 00000000..3d3f0cfa --- /dev/null +++ b/doc/html/getnode.html @@ -0,0 +1,77 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

getnode

+
+Get node names of all selected paint +
+ +

Usage:

+
+ getnode [option]

+
+ where option may be one of the following: +
+
abort [string] +
Stop the getnode search when the node name + string is encountered. +
alias [on|off] +
If on, reports all names found for the node. If + off, only the canonical name is returned. +
globals [on|off] +
If on, any global node name (names ending with "!") + will terminate the search, returning the global name. + If off, global names are treated like local + node names. +
fast +
Return the first name encountered, rather than finding + the canonical node name. +
+
+
+ +

Summary:

+
+ The getnode command queries areas of selected paint for + netlist node names. The converse of this command is goto. +
+ +

Implementation Notes:

+
+ getnode is implemented as a built-in command in magic. + The node name search uses the same algorithm as the netlist + connectivity selection function, and for very large networks, can + be quite slow. +
+ +

See Also:

+
+ goto
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 6:01am

+ + diff --git a/doc/html/goto.html b/doc/html/goto.html new file mode 100644 index 00000000..f5c91422 --- /dev/null +++ b/doc/html/goto.html @@ -0,0 +1,75 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

goto

+
+Goto the named node +
+ +

Usage:

+
+ goto nodename [-nocomplain]

+
+ where nodename is any valid name for a network node. +
+
+ +

Summary:

+
+ The goto command moves the cursor box to some position + representing the network node named nodename, if it + exists in the layout. Because any given area of the layout + may contain more than one unconnected network node, a layer + type is returned. The area of the cursor box plus the layer + type always uniquely identifies the node.

+ + The -nocomplain switch supresses the warning message + if the node does not exist. In the Tcl version, an empty + list is returned for nodes that cannot be found, and no + error condition is reported. +

+ +

Implementation Notes:

+
+ goto is implemented as a built-in command in magic. + The Tcl version of magic returns the layer of the node + as a Tcl result.

+ A script may make use of the return value in the following + manner: +

+ select box [goto nodename]; select more net +
+ which selects the entire network named nodename. +
+ +

See Also:

+
+ getnode
+
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 2:15pm

+ + diff --git a/doc/html/graphics/blpaper.gif b/doc/html/graphics/blpaper.gif new file mode 100644 index 0000000000000000000000000000000000000000..377bd0b5616d20e83b967cf93daeaa03d773d6b4 GIT binary patch literal 9220 zcmWleX&@7fJ^EY}d403_-cqL` zPqcv{sfa;%i45jSzipap*4~Lt7aBs~%HW;$K17uIo}+w{S%jhCZmtq28WGKv)C#Ej zTwTIedkz84u2s^v49#n3+ONBn%ECw5+JXa#NMra8BZ1|PP_i2o$hCC!@!iou3>Z>I zfsc|yTcaK7x50x0OqZOT_*5H8u(2s|;xWi059WWr>ZlRY$+FN%843b604@x=u?v(z z%3_He+v&?xfhb=Ze3QshVn)N%8t1`Pw;-E2RlynG4ML#D?E+8L0Xsap_1r*x0Dip4 zo(AvM=^iOY6;SXck|FLy-c_vLu|YS^n@SLH;rFG6wZ=OH(+zWSuz)NCM(^0&SuDx} zl~F9?e=y#T?6GV!H4pA)dPh^0`N8i-l`a&i+_I;y;(&i57mD44=ac@Y_lJ$WifDGY$W3(zVp0u zlmSblegU%p;^Dzy2Qa`pVKCCm@9lRtV(E7EyIJaM`cy4KffQflL7S}0GOQc*)dPHx z`YOjtds{G3^G|XSQ96V$J?93o5Td7I?MKYXzWP24ValWMsk5H!91Fi$iJse(+?9BN z#H`@x+JPi{uKywfYSUnCik73|1=^YFV0M${zN+_7cn23Jv0XCnEwSo#&k{kuZmhc( zI{jJwP_1#(WZUW%XnAT(t-wRr^wY{E%M1dP?}4q zX=GlGfD`8zl?XO`$H#~<4#saGKD#WMXJ{aXSKSTMv!`yyEYX4yJAX^0CTyN8Q{7Vk zd4`56x&g~e*Naz!NA9`pFd*QkDkUK1RsOT($Mj4icLdxW8RM8i+X2_nD1RhV{{FYJ$kj9PJDrtNXW zg7-O@A`z;E8|ej^40(($p2{@5;vFyS!kba)f7J)vI(A80q79afB-1O^o+Og?PU!n+ zZAfBY0<&jR>;lfo0DqVX9Ds!qL5DEiBGNkqx!$O2N&|zLR3*cI?4;{5Foty+@|*Kk zXAeEi=>GHs;^TywUSB-aVak0U3a;f(B2#o2&nKR7f!7Hq>~{Sy9enQoz~Oygl)4r*_;c-Y0+h@a*6${fl1{r9<{`^Ahra&5I~Q z;BLf;!#JLkOCR}I>5g2cU9H)&WG?kPzmEQUtps0PY^l{z0Cx_NeHkB3d(+PTgRrif zFl*+~C<#6vxlxX#&;(&Z#8IC*q#A_}nmIMyoil~=RGVP^O81DH0%OeE2qF7U!rw>FT%i@`$?dI=-fm?jz zah?|TbaG}3OS038VRifIS44yeJSi2b&~lOkYZyrazaE`iF&LMERSx(wHh-}prqJwE zEy^ZDf?UmysNaDJy2)oqGC4LZe+Z}@AMqE(y_}wp=A2JqIu03@Jp5Lk!Y{~VjUapBx(r6u-D-J9KBeQyq zuA8@KPA}qNPKWc6f`vU%Q?q-0zHhy`wSYZjQlR?T_DquT!?4`salM^2Ufi6Efs@0i z2QG@CScf09^S_?6eyAgqpeu%#ohWGZUyS+)hEdO+on0SWgD5dpq}T?OA8HM@O|$W+ z)l%h+>phx<$*=9g>mL1n7H_`>f%OyV>P+oTHP51r42cf_LhX{%-2u04zRJf`Ouf1j zKh9pHY>42p{m-n_MXCt2Csvpg5%p{4M#Y%#kU7@7hA^X~H^x3Z&MNU~Og1nXz8mCL zo}b0E(7jYFZVQbo!b0SfnjQr+XR`Pt-MH|Xk2_;rG4ogEI%wr{b-|QSRsa6dz6Sa; z)%)uw#}&24S2I)mn-?ww%YYQFP^KFIV&5^$wY6G3X$opo{zB?T-x>yz?2Wav)af|RpSfW`;A76*@55Cmhogmsl>HhuB@}Wq)4MZ7{qnaM zb3iOw=sPOhs^p)r_$KmxrUwj`pku{yzrOG(-o^AYx&098pxv(~@{ge{NwNuIaypws zz+JOjO^G+kfC4pV%K)A8ND~GH8g-$H0=o?Lhc5Qt6SGM`&eqpe}q5UNbdU7a&T#$eaiKWg{{* zh7@=YSDpj;*#yoAKFH128qbI+X3u-V^p>F^1JBZqw5ny|DgyICYOgCC{jNm$$F~KP z@SzBk@k188fX(Uruc)p{5%JNQqNprJr7bg*mEKTp<#ikFXi?~Lw!hNm#@M9pZIIX0 z z(X!fe`_4@8?lOZ~hjG%nszX1ne`s>=+ohH5TmKAojOyun>(k&E-F+(VrRm2Cx(8}D zz1F9HM8mzOAO#6|cFR1Ek{JsK?j5Sp2&Uey^{!%)l4YX5c*c#o&@=N1@%xusS1-12 zRMZ`w7~Z@TP?6^GWhEETe2^O_8IN~H#v;F}(f%FFxH_t80?_H{CfhNLbC=cF4{h>i z_t%Q`R^(t|AYo>fR{4+`NJhinD5U}kk0C1P*BQF8+F+>-hJ#_JYr}#p3*1!d%Y{zW z_~=Fh%@#gYpJ?S}_3K*(HyxDAg+G$%9R+wCczA%CX%R(t`i(_bt|`@bBOEA4GlZ^2 z1ED5UcFwJ;y35)(y0<>wZx(hya1a(!#<0ujK}7KdpA=vnx!I+B?Z@drQji``s6`$H zU6fK?f2uW8=@~U%z}NbvQq^Chrs_dX)#=OvzJ}SFT6hq3->QuP6E~}l-P?-U1WN-q zAh8G6h{S$0S(v)z_V(=<5Gq}LZ-JJ2PrQ?x%gB-{FqfDPC!#Bf3c1Cq2(Oq89r#9a zBr4a0;dorMznpjfy;J%GB>5e3-!~K~mh+I|Q#uzDpQ(uwz^)rGys6eYYF6h&e9J1* z*&cRTI&5q331-vDNFj6Ps=W>y5k&`IP#9RY#UK2EQ~$}(T|EwIN9!3F`2Yay3a}9n z*)JemXBZuP&B##GBJqF*Ec|$Z^NwYwj3*8!d*R-Sz|T#%&gJd1SlE8Czi#CT_biw* zJu}Ch5I{-jqN=L5QH&j2|5_v7Xf`lf#gCI63F+X8d4!AcrfLqISr9{-ERWZr5?yN@ zXw4@(;41b#X=J`#O(o`ZY{uv)CL>h)Zj6H~8U9!a#>Num8D=xx(dBcj0a31PZ85=E zYoCnV7>nyzO|0Kf#noco2a!KuwEGgw`-tlOUfPjMm`DoVjh@=stK-cCdn_mC13eh!o?!F5X$I@?swQARQCMfw5zO$koLCLGFp`J1Fn8E1CQJzso@nI;Czor}VyrY3*Imd2Uzd*!#u-UIEXtMWgBuC$|Y)C;K4p#mEfRA~T%YZ0z zEV{GXIFi+Hd)0kBgZJ)A%orQ;ADLqmS12CAo&=w%8aZ+&QO|umU98YpXvX4jIm?QD zs-d_y^cW;ZN$anpAdE#X*J--R*B~>%_KCkuuDado+4h*CIxe^;R(FKuc#;k^Zxq$% zCZv{|^{=VBxvT6KY81~?$6Kl0l~`Tr9!?PfSKgv)YXbkE|M$bO!P{oA&u0! z)}!}p#5eScxv*N^{VU=r2zp7kkpFYNAib2-Zb0%q~1 zcQ+KZYVmRwT9X2)o3}4^XUf4_&_O}eRuolmaiB`0z|mx*8w=&BS$_v>2y^Y0I<4p) z*X9i2a)63$?%cZ&qN)1zT;?O3dIsHXe09I7seKM8KbY2KMi(9zMF8ye9$BB*uh0B| z$+}vFZC?WwD8T8X8G++=XJ`$3)`71!E@UQYqzW`@f}j?j5ZtKRm-eK0+{5TZrQ1H| zcda((EMauowxyPb0Dfklmz9`y2geRd!zWRzY_%$Pw|sD{KgRXOh{f-9<(G`&a{}Zn zCYW80`Y&!1AG!gt|Fp%KYtvh(x*@>+wr|)`VdzK)OP=gEUe8DxDLKzFYAk|$m^V6z zRU+jVi)G+4p!mmagl-<%s;$yzVBa2cm05x7q5zK%wloz1=9QFM-wuo(_{ zv|u#$7En-#Zb+(2@^Jwu3lf)6Za(&}R}I${n%i1-T}wY$pss$vv?+beF26jWZG~db z$L@_$bzIvvHDdYdAat9^(H(g0C>Ue1Xp~3acQoD5Q)vhgVfyK3=v$V5#(X9IxhlN_ zxe#N~w0i!W{RxA|N!tVmqKDO^6oE#;{gh0bvHT2;KNSlEMzS+U;q+ikl3vgOA7EKWLJ=?4EX1= zd0LIGDS>(+PYhp>3%6a zXvHt5U!w^a{0F&y%`F6LVt2mm6ph{xPX5*@(*V(wh^bs^f`}NktQ0vy zYKp-ti;>3%%$2E#zGY4HnDuZv#IKO@Bue?CTIx>`{();~tQ8gReOM?*T~0j zb=xPMnjbdx%8hdic|+w3w^=W>*SH3p%~!##z*@(Gfr5()GDky8OW+A51YHE~*I~^? z#ESezU_Nxw!Yu&erqnk;h~n~1j&ap%6T1#7yRHr>-FK^fn52n$NVMFKs}uRfb*t(p zLAh%Uy6#?Egpr<4Ai9o_FLh2oFwxo!o#P{FBj*jaNT6c`7hKBLSBkoyI& z_-2eYlzzLhw#Grvr@OiHCj--OeAmtG+a{?5*Cb+$k27TMzebf@zU2>Ppdl0H4pNMH zg{u({;$aIi0wJQ7b;PTftLn&9yZkLn$5xeD2h^f>%mM&v*B>2lo(wI#2B0!Q1P^LY z@QX2I#o}wSRY!&|=7^SNFNQhL`Z!(DWOF|je+A6c6gnOm^xDDh7rzMx+BQe~(dpCg z8^GGRZ)3c~9Z#ebEy|OE$z|gwJl!jTf~ZqROz^kfD%_W)vg5PQUy-*>JgWG-%-clW zjEV6dQ&5l{sJK4W`}$P*D7ojm3hUpV5pqo_7g~jgm4Z$F1~Z?2O5CxU!cS6Sr({h7 zww%06{$6%G7J4Fh*_V|BQ?Df_0Pa%}XMxtd~`vQXxC0 zPqbX2C4q0e>~YOwL1AQV7HD5ncbPg8`O*O#{M8QD9(L75gDmS z50e{sF-RI9-#2utp&#Xg3;TAJ)9ilwW2O=Kf%@CA=#cZco!n>Ue2iH=2>ppYy`C6V z1N}4Eck{)Gk15?`lLb!=vx>xP7kHOs&K$mpUpak_b16}ijnHk3QxahfcA2PhMC4GjnX0*+qk$xc>Sc=cO@1nEm#-b0_4_3_ z5GD7o%>7B>B231Nh8pjCnSHkD0uVN9e|j&Ceu)61Y&FMhpYyYJVVe9<1HNRP{<)I~ zPfAl#q6JM~ZyKMWxQSRTC5JwJWgPi8Ppw}KvUTq4QjnE>s>*-4k$q9Rhu!?`i=D0} z`B;RxAT|$EPqROq`S$X|X&Pv4dM71eu6Zv0BU4Y!q0#5l>kzFlauGO4fr*(yz^ge` z%-!0pTnW`183%tLN***&lNfmTm9R?2=@;-{GRe^@kXL^S*DWm1odq(a1QkPE+-?WI z%j($WXJaV(0c}XFF23ug=0N>PKlj4U|{eCV>ji`xd*-VTB5tWHZKzJ zyx7(2BhpSG*v!IfRiBeGsYbmsPU{30BZ=1b97_B*J_{N{^WvSNmjeiU{vM2Hu|KGo z`S{Xq_~tEnmifJG@!EgrO+sx>9ZOEl=pYtgM-3%+W$c;pw4-j8AKthwE?9qUn)PYR z75gFDvQZD0UP}t??a%miQ@UNhxj(24xOVe_dgC$)hvWfvP+5v2cC8s69u z`6%H9w(LlD{$H1bh6b9MpMIIjeU+X=l;bTBxT_SSdZS4T))C>g&5%$thC^W90#ap% zCzVlT2UpKi-JHo4z(A{KqEl{mR!y3fp6-hcR}Am;_;CKDy4+Yb|G(eY#!6;qQtoc` zxo&EuXKPv)1BX4vqFw)~QN-wMwk+~l1|L&Ir9M?4cHc&OckVSz3yTfl%~vELFswy= zu(l5?{xYhKHCBbAE;W|M9~Q2V5-JD@7|c4W$7_##XsS&s=1u`_SF++yF&!0g;xcEm ze0wP{7A~*X?Wv0$G=b4Xh)Ww+sF3iJf+i(0XsQKlqRpPj!^lD6drm&2Nuw`^SJr7N zWExNDclH~GW5xgP6Agyshas{#pC3?$`s1H;% z^7uW&%v<+a*h>&u?ly2jM|QuB6L?p}$nCxzdf&w3&ke>qNAC{h?|3!H262!ZVdXuG zsYsy8yiYs$+)D=t);e5csemsGhF6)gF$U-2+Q$|Ha)lt2JVr&?uoBi_ekV@D)_B^` zx@J-meI#qXz+zWt!e?p_qF=1Eh*^rC88Dw ziu~>C-2jXvHD7c4Wb`%DCV^m0dMIM3(DkZCz7128X9l=aG+7;F_Z~5ik(_y_nuBK) zZk>E7#p z6Y9NE`F3EO^JfueQ;cnb(B%$7cvG0=L-F2ObP9<(5iu-dPo_R_o>GL;vMKmCE1d?f zWUANvWypivFK(A}@1gEjZ~4d_Rk3WqtIhxrM-@Onf)`tPl!_1>HHbna%eS_3FgoJ` zZ-?x&Uvh*sp(_`>g06vY9g|-Ucm!6}#S|!3_|?bLfxEJ$epX(re7n6X{-;gE+uTGD zS&s<+pA=@JvV=Ga7|qxFBt-rrEBwNKzt44rW4NyWzhDY9A|9f#us$V$?ON0!AgsU* z&|(tlkI<`g%UC|IBan`0@`m|1e=0QC?R_#o-Qz?Sa7+9uB)z|L6!Mp=)9QV}U~GfY|RK3G;`HGJb0NrQ=(0BT3@5a&`kH zWn1iaE$uZC?FHZ4NkAsm^=vJ>*+E&uvhe9fgShW}1I7?ls}l?O*^rQ(I5*jc({Fl{ zz&VhzCuqld)(L?5tQw0mQ_y#%GT#6INXstZ#Bl3;{o=Vl+PS(v;{gD18c4EH;APuR zf=p4hmZnymSEUYdhL^w&)YBj=xXO2_WLvm=Ni}Xa(87GeD`&{SzIU<=NS}1Ap7G_Y z|IkUm0MCcC%L0QRBCHoh#QOgC$q<=S{r73^91C#J#kFFESFvk0+aK|Zv&lXzX%xN0 z1sj}K;2a@*2Y*S{pxYcEuj8f~%a;cREb9OC3Fz5Xq{4*V146GzxUr z#-nI>pfMdc$Vq;hupOTqHx6AIHN6QsjSYy|-Z-d%Sm&M{AIK)X+YQJF3?E~Yt2Mif z{mksdP5-f*z@PSrUR5n=93z>zSlt|l3yMm#1Q)^TfLC}Ql=>zf2rG{ND0d=U%uDV( zLEIJ#5n5KYs@;>20g6-3xVJ!E8OdSAu@i#xE&4~Oj3Wzf=bapBy*PV6%I?=o-`$AP z2#Vl-s8_oqtQ^g7d#^Pp2ycwUwtNGgzv cWjPKHA=A0I6YQ;{1207y1+@T z*lgjI;r?AI+f_+9bxeGVn*P1a2gQgIX#I6#7$r-jeCN@!+Q8q6MsLowQ!&NO$<0*t zRq-b#-7-ta*`{16O4p3=p7!~8dv;`w(IKnWEjtX3f}2mSiYVQvF;m>wjKbAyXB6IZAU$M#MznDduIvtt~a*Y6N8`)uXF zL&}hx!wsi8)T$h-lt+l35|bB$y}#RsZKpK04_#wRq3BVVI$|()Fqi$y(W*myqNi-$ zrvO3MH#vPB$+>Kgg)#+@(kWBXH^lKgx)-2nJO~G%;cHztzMjVd7ftpwS4b*C zKD72ZN5)D33M;C#yg#FO^F|$68aPblWB&ID+Bx|oQ~FbRm9~T3R|ldYz%pU*(tCR8 z;XCF#e_5?-R8Ii3nPWuTZwOnTe9uBiyaE~y>UT@;=hXqxgRp~@s=u6Fd78srxyHI4CE1tf>6oAFN%K z7_8m8HM$A(c2FJmYL%|s2wi7@0oNTfsvmrWZbzJR{2+ZYG+romp7?z^wAUbp=BVa- zwt{?}8bMx=G)yiPCk|7i3+1nKywn z4I%~#_2!EDEA8C@jThojBQg;haK)z^%5>Jy8mi177we9~om>a1+ljUSwZrWWyH<0v zUYmRvYI!{mYm+jb^E{JdpkrjmXN~nv;X1b#^_xxsXUf%W`9%B&go~m^FmJ;HE7!EQ zrugA5IKj7&I{Oq|eIZ;_6iqH0@}gnuM2X9wXAx@n7k2@k z4uuUtUS}J%yfC!kIfQ<)UFMqDL^43757*6}YS=$Y)A=jn zaN!N`C(5w4OD~e5`m0Pp8%*;#EprsE_aYBnYrp+jl_{PapO>`6j+;q8)k12YSU=Ifilc25ab}4o&xf_>Y6<~zFx%x-B}{4@Nb+ L^qhbL0M7phePaur literal 0 HcmV?d00001 diff --git a/doc/html/graphics/cellmgr.gif b/doc/html/graphics/cellmgr.gif new file mode 100644 index 0000000000000000000000000000000000000000..ee316e809efad0bb6023aaa65aa5b698fed546af GIT binary patch literal 9375 zcmc(h^;gtgw8p=b45=Ve0|`{MF-Uhwx0JNQ z^}Y9xxO?p%&RXZ3{p{zn_F3yFDl3QxewP?7xtx?fPjGD;NXbiy^M^Eo}Qk* zzP{Pn+0D((I{>)r0q*Yp0em1W09Hn*PL6?|9^eum=LEp%0RTpplg!;q z0z5ovY3U=tR0rSy12iB2D}H-PsK#J{^AasD|j1OP!CKo_9(-#Ry z=Q#uP0M5^V#xWut|MZ__`7IpG9&jJ;A3?mpw|Ia%09XKkGr;KqXgC948vx`Alv@BN z%)p%m(Bo;aYIAer@(|AzkhUr2bPUq40>I1w$P$Ov1}L-#z!m_A`AnVz2g48Cw+5u4 z=9>PGAfn zm;Ye@e+AEf!vDPm0E7j=AO@xS{2w8phtCWV^#y$q4_H;Ql^O~MVrXC5E+86;;PK3I z(M?K$(t*I!x25tni6y91ZnNI(tHx4vmVm=%zj9L9aISa=F5|VSxK|eOICQ!3X3#^C^O# zvYgrcf=m9BR!2iQORV_djG6k&U=B7}VSo7ox!3LKZ1F0%kJ#)pgDecSE*}vYB&k~N zu%?Rmaaw%Q4zJiq{O|?&G2ObfVl&ged1o{0^B~t&Ht~ebR*vUp#a6EG`Oa2e;Js(t z`JvRd+Xa#AmD`1}Lc7~V2@214iUXdQ?v$ikR_>H$yYKFl<%d7pEiX>B-K{7ut*oqY z5iqx@!rtp5=2mDNZr7-3rW6Ef>kp%)Yad+^+spO})$cask!$cY4jEKdS7Q|HcE9z| zb05Hl`C@p#O%OLZR4y9a9JHo~LmaG;@9}kgzwHCo-q9V}G z=o6h>$&HuoTxMd??u_Q`AU!C50sU~=&krS@>ZJW`Upaz2-+u`_XN}_;eY4E-Y@ZFq(NK!+**Or~>ZK#I~ z@>QL8bC&77SDZbQ8HfHgF3YQ8kpjP2_RW<^=tv0e^|?$Q83+sJks9dCkNI8M` zL$SMKPufRX6<)}`uy>R&W2oaCcrkn&H`{LZqqn45>iRf7khGYYP+3VDRhbZ}TKweB z6Y)muC4fXqJ2oceH?4EXDXYk>9w(QpmORr%qTaWkq}0b+ zP&`J$_-9X2TZc;cJdkMP>yxzaq@~Xzyk09slK=!tr2=WlAxp8-jFH$?;@OXdz zVPhf0Cu3ot?ttwRXg39cIe`JKZ|5gbsoJIY1 zrnDzWBZt=?swSRv3AVfD@VU3m&;MaEZ|yv&b^GPB_*=-l6jz2#c`H@>geQf0q@+3! z8Z%!vc+s*1`(lDrUBx+N0I$ z(ThkmyH7-{Y&F=}hA@tkar$Y!E}E$N7@263NNXzAcKhfr9t@*QFU^6M;oAvOwefK7R$G{sOU?xYyKscsPpXWUd4vbU;xWQMKVc7(1#sE@63fLf82zm-FqIb)VDQv z|EZzy;U-xg`!c3)32~Z@7H{8}a+iI;$5t+TJ)e-G>4JU4^x4$prn`4apaG-l44i_y z=;Et8Etc}T0iR9A7OzfWW9M)}pQ(s@Vio+Wr(3qPYj^j&iV25Z?t~<_L_EAF9xk2a zd5CZ8KK5>SC6xe73vJ?Gc$xQN4-N9f7tQWq!*Y&?-en9!4>)2FeST+7A&U~V#=~u3 zMu&%fhO-Zs#REj-oKb?;o3u`zC0}>h!Q$9M8Of_DGAzXae37Nxv6(lD=L*Tacp$6W zHboRyIt-sU;f{CCH}gi5Ow;`-;^^AvzB?BzlPamo>x%gZwOPE$Juis3Ip9t7D#I>y zcUs*Zr$PVtm@Qs4z$N1{;^)@OlCGVhuwOA)^{0Cm9z|`?$kGjS@A&6gH>}6qGHMR` zCwJj|pMSyd&H?^*lRHQMfX`qX6Fm8(rrLM!P8FzsQf0lxftBGKjr=fPbE&{Yc zZ$wykg+fHrgOh~<5#d4bd!d>lZmL#~g_J@Bg~R02L)8#rMN>Z4_+fbAX3VYOLo&e| zP7zF;ZdTUe_O!N+w7%0VA>$WepJr^Zep?MLYrNKlvw3=?*{-^LCiq8LZGZk7ar2ZI=NKfj{<%6-BXApA82 z@x^#1U|+%GFS}7*3p1;Jj1>r*m~5RuWs|tX8U5hWKx!r=VkS|0+b+k`lVCO?a*O>D z5hbmcJ@<|#seV{MIy6Tl*|+rz6=$GuMZ9HN;^)aEIj&$4kuU+#BrUH5A)BD>@&x{A zD1(=~__UX2WSDJ4^!)o&3~h9k`fq^!T7MVqHt;M0p*l?oUz2x-QB_(q$1!~v%VQpFNT*V%u88OOU zQmE2pqWsRb46Gr2exI^N4NYd4SUH>~8zE8{OPn1;U(vo*e&b%A?5&ZMSy9|pQ5jK@ zJ(m+mTywB!Q@!b4TWZIiwj>>m#4|7MAdd{hji^f69 z^Pyf5wsX$<<;96}Rn^bRy`E*jXXD>l=Wb#Bt9DnsX@-==03A1makc+||$LqA64 zpu{*9=iG3wYv_?5E1PqAEc5o2%Y@4-YZ7Y*m5XmIi&8SeL(>Wpt%A>^YjaUCqWXp6 z%1#P%G|0-7)6BZLsciIhQTk4$RYeNjV4c2K9$8z>nTi`8H^-%l6F8=d7+m^Pyn6ep zP;U-f|EBFN!H4))oDq_4Mc$n8(>sl}kqv^P4MheG!}PhZ((K*#`lQImuxFlDicNg& z9@d#zLvvp!D%C&Fz3a$i7tegl%3Zy?TM|XA`Bz1Q6Ew`HzSEvAVDQtt=Oq2_8; zeOd)Abi_dyEa;bo-Q+pklpcu`{n;&Jp8qD*(OgX5l-FK1N^FW%YNHX4=iRIO6w}fb zmAA4BBfs<@RZ14$Yt$w2%_1pCyO-u_)r8X$!C;pIN4a&2cf|X&Dn+Hz-!!CVm8@Z{ z!;1G>fB2MX-Bd1@Cb4@rDwVY>MHVqZI=4F1&0@OgJ`@;LG~WHmDim*@Ow}Hh& zXskT=m3r31;y30x1>AZ@#lOAV4JOd<=7yArfz$7@YR+#uskz&lGYf7yf?QkeTV$#T zTc4GPYfO z$UG>kulK6Y+O1E1$V|c4UiP+J@%F*qe7{CVSNB|(RY!js@c<&FAMH`<(dJi{nU|~k zWQDrlYrZ#qs~w-H;pU@rl1CdOg!QdG_YZ@P$LP+bOjvyuon)$#e^tK)PYd>Zx}7mB z(Kfrtv90rXw~lHMo^bQ7rOG~7|I1`)M-_U|grULBzSaxJ?8TtQL;C@~v_6{7uXLTR z$%xS5)EY9?6YP`iHASaLcJ&ED5I?add{lPQb-td#-7_C88QNcREbO zQvS|2buiS`?xVloh7vM_X=TFstA^TQyBhX}y7tlRlL+ssvciShW*tms=g>k_WaNHB z{P|EF113!b<1#a#3$kmmMIE`<-p@w25(9?|$Rpo@)mu2e?GT$7(u}x1A$7PT(IIBCIHz3PB0ueQA3IFG}i^Z{J4CPv(09Ov)E zJJoj*H4}LY6F+$3v}+zHFOE0(#*s-z8&|g~`gGYz48A+SXf47FB>NHJgPo~J*w;3d z?Li3I#bj|R_ro_=p1$VW5l@K_vxaFA#)-#&$Hbl@q+z*Bws32*A3Cg|V;l$^=uuh2YRLqSGA zzt!Y6#)Z5Wn0v)LS=u$pi<#`d4Y}u#kIfw7j~Q01?EQf?nwR3$Zp9?SvJo*p)w_m0 zNnK78j8lB1)8#p7Xx^{5JY!^Yi;0X2$!c@I4Hw2Fy38^2)>c31b*ll<83WFRrvu}@ zYK>4#|3}Xy33wVPcb1j1#*BCHD=!kDSyEusrgj*1OC3ET8#z&1G34!+NyXSt)lu@r za{5}Zst2rLekmT$z7-pH6<@IL`eoGB``magHLeejZ{(%=1CH*s$+TY&{njFlmP8KM z9^P9A^R6qXuidFFs5mZEsI6-+uC>mtBvgA5TTKPc7WGH2v-2+H?@vWJ1URc90*$7h zRM! z9g=@&HWy2dRM@QFi>y;SCWfJ?)dZTSD_qOoX@_WBYoZ;XT!*83} zOS!{~1xB@@aoe(4YkX-79Ae$=jCI3t==mD7D<+~;O7jJF{q&%_Be&ZgwD^K@1xVvDucI>c!thzjVvCEkL<%+jf1ioBjzoTcgn8CL)Mqb+P zKN6C*a@7|3*lL4CwX17sW2yGn3VAiV{V&#>{1L}`AMy=7^1dat3^vT6spPM3x~tNp z$2jEMN4ZB8>^oW8tC`ooWoow|Qhm&M*!3r`58f?pu?8HmE}K*HuNBzued=E4Sw11q zIpwNdd-nE}|M5|K*>959P0~>3Igts;fD^9x6GpYo5MQcLsoj|`-Mf*eQ-9kC47a)# zkFNaC3MMBee8TwSE+4JQ*s%~Gg`yx%2^6SL9%haBOhP;cJ zR0GB3ix#r0Hq6je%(p?Y`s=v!zgV8z%H>1T!wb5e(}52MuaNkVMc8_L2bxS(v2DgBeV}IG#3iAn|mZgUa+q5fZbTFp2#> zE`HM!5S6p#0P9gG+8JmDg;vnP~8&;9CmL8BuB!>-9E;w}I*2O4`ceL)QS0-Rj zp`ts|a{JOJVncCH@0GcX$Th4d)$lYGU9 znKs)w6E3r|z!!PFS!%1JBs3X%BJ_~evfNaQTcMQ=k5;d(xm@gA1Rn85{q!xba>?b2 zK?X|CA~gV8tERI>nk8ypxQ4H13Gs7qYW>KmRt8_)QYb@AP==Y#9(uR_MstsUy^-klkIj1_PC zj3%y@#ElX(jVijuF2hDRa!;%49!vf{Jov!0tMfae4ZFR^mv|TV;ABZI)Zv0F`mP9-6S^ z;Cb?eTS&S?Z(-H4n~TggK$?o_pnSVW-{wImE=otXwp@&DI95)xaTYvJ!#NYz5NdI2 zs@KH9F7R|a%H)>yHaPUD82Q)O@6o2@MO28dk@sCl6Q3;5R=m07`r=MQ3VF0aiI^}{ z@~tY;{6l;G=6U$L*xIr6jv3bU9t}RWFZdfl>#a(fnv_AMO-~y%iD=X-8@wufjQ2aS zN)Ty(NB4AmG@ldakU=+P`kIRwW<^PIgy==uGl^mtC9*+Q_8_e@#)76OlFLZ}nvmLA z%GhQlOUL&xuIP-Nr=(P#sU$vo%=zb}MA(qI<+l%(p;Ld4%J}sPAQ^nfoO~Wczt^8< zMuZ0+<;!s2HF9Yd;uUSbdDYGzkV%pcf^91tr@Z@`D#*#`Fs+#KNHa-_s^t9BM~KB7 zWn%bqW>Kbq+@y8Cu$w;Cn=*5+Gwi7czAqO?<79zz%F6CDHWJInUr zjA4>3EY`ZyCDFxmEt%<=$y{BRdr8{WmE|rjMEI$~ene(f>B3=qQd6!&%9_p7L2I_R zSh6X(`cIrjAuakjuFciZKN~MY^ig#bW6uc&jKxOV^+Gl%iv7AaO@c)Ad81RRL(tXJ zdRY&r$uY^fzU)qAx{$@;xC&o^L$~RH`J`8=CHQAgZ8lIN#q4f&X*#uisc6H)B}ZLc zqe<^~VIQ<#>9PXlsvsGO0DCkH10gR;{89QHcQ0LUgrIE8mklnGDNt)%yZ&mUQ*vE& zc;L`Jnfr~M<#)C7a@EpxHWteX_UX}Po_nXS)g*W%An$)7N_gDXh|O7cEl2*Mn-qn4 zWyoTbI}O8=il3@YYE-3S7L!p)9b+~yWtxVBrPb$Lf9wbd+7klq3F?I2cD)eRZ0?6? zr|#@@S7_d#`h=j%qzn-=!TW_cI=o#4>5!@5aAf8?B}e1BOnX-!53! zsBY3TQ?SmReG*VznMsQ}(LcO9>CPeM41=~30&vEv;<@M5UtFcB6Q$s$_h;#Mx zuMWc);i@w$pTVfcg&IAEOV2Uy{`!J(_M9Dulhd(*+b7}d>NmU?@Y-Uk_kHqZyvrj` zDezHf{Mm|4jZvv_=X~_f)a8aqOX0qEGqGoFzsOP+&DXFxJC)~RCa;DiT7|1~^~>C| zs(5las3p5N6?|7QWLn}b^a~kCKWMoY)N?I6M@+YCoTPYp<-W<~GdS}mi@GmiqhA$Q zlVmTo)ZcOayrG5ZlCvMbO^=1U4%XnChjb9pe&6FZsgrBg zg)GOfZMj*EkXfN_S~|mVl6DcI7jlo1(1n%Uwa7Jg#6!uyS)h1Y;NnwfK?nz3RNH2G z)^L`1-3;r$Z#1tcah$Xa;6rB^BQTfAM&VmFhVB?mdY!E-^C+2!%&_tdquef&EgpRpDVN_Wg0ais;t@i!l8r&cHEpG2wV1O4`=xKY-S(bMxkzaC3q0cH zm!nxbFnqZyoM`22aOIM+HzJg4htjf`|}#M5s0*%p4K!iiikBL?$Dm ziV@LGh?ssv>;xii9r5K15s!~dphA9SLnaC$ljM=f+Q<}hWU4DNEfkrajLaxTW;P+i zl2e2CV|*8oUi-+%TcpPsiO)VVzf(C@5EZ1VQi2~CWr)hMM)~ld$|X>-q^R$Ks5om> zPByBx7*#!is$NIc6r&nKQ5E=*reu{y33PeCN{u$;n=iVu6Okv6HVi`7PoRrqA~mHsz^hX?^KY1P6+A@4L3xiRUyNqLnG@$ zgUN`hewB`X)skLj)kjT3$TQVx!=djJ@F8Ew#4UQlP;JZ=)!2{uIRTksz)VqLW+qf; zvN22e>dQkz3lnPj>zL{6p}tOthc;veUv$Q5<65!r8Z8b zf@~UI%7zS@t9wcO+#iCV<<*Ymk!4LkZznLj6F;$3KhMv80*^*;o{r$Y8o_%rg0C|| YU@>yfZG@-$STxNW9hNL7G94smoR+jaLQ`a3bQB>Vtdhi(fvr@J zhCDGuG+tC>a*Q+}AS_NxL~v@9r_CfkJzQE`Y_zIOPhL!bcq~F>jE<}wELL1Rc6>~aoIG-TM1hP% zHY`*^JgknylzObJn#@c>ScHzWTv=@_NJPxa%#?<-l$Nx7ewOUk)ZEtKq?W`yA|#A{ zsO;kOG(Jo$A{<5tbA^i94RD3GAv|fe0++kG$t!lNMb}sRiuWv zG%_^&`1%|&F0_)&L^4D?U|ei&gfvo2oT}7RP-B#luQVw)q>#ZhF+D^)P-IYW6cQAa zqRaI1^lYxAG&e;=Vw5ymWJGy{3MdLtSlldREmUjUW7bqWE3ha zjEbjpc8p9~Y-FaKG+I<#YJ_B3d31uFT$+-cinv@#XH;T%gm#>)io$eijMUcLgld$8 zmb9Fjykuf^EC2ui05Srv0RRa806PdANU)&6g9sBUT*$DY!-o(fN}NcsqQ#3CGiuz( zv7^V2AVZ2ANwTELlPFWFT**l?yw=dtnZv)#Eyq9o6F$obPRD6)JLC1#^OI|#=aplLCBU9dNnKNe3nmddBJUTS# z)234sguFU)YtXMt$3{I{^+49QUFU|qTXt{SzikV|JzV$D+* zjzUJ1$Do83YUrVeCaUP7j5g}%qmV`_>78Z5BA5-V)6@i~<1t;{yd-Lf%4 z>+H1DMknodqaJi^wcK_aRIWH8mn}lUg1exC`=xuXy6CR!ZoBZZEAPAW#!K(L_U2pf zzWDO1Z@&QlE3m%=^SAA=2p601u?!pQ@URqZ>+Qr8-y|`M7gwzD#w=wFonwrRE0D(= zmuzxK%Zi*L$tSn$@zyTM`^Upp9-Sf~u6D@SnNFS}V(M%^D z@U<$J$nwinSKZLm(nXCJ)>e1z^~ibnI$hLagZ=f{Xd^^2&NkOPbK7u79QJx?*X=T6 z2V*>U{y}oq>383N(;4{Rf)`Hs;e#h`xZ;Q}?s($`aorrmv+iy8y5-aGHR|1Ny+#QR=6@Wv;P z{PM#q-#qijH;?+!17rNWl9E5P$|Op#BudKL+|Qfe>6^1RFTP2TJgQ6oj7& zu+t10WblI)1mOTHc)vl>FCO;Gp9(Fw!Vx0yg)M|33uoxU7rw6*ILx6AcQ~jW`tXPT zKn$V~hX_On>|hPLfQ2sB(1{^9qX21u100kvMJW=Yid3{B7NrP>D^f9wUEHD;zsN-| zR&k7H3?muQ2u3ruQH*L#qZ`Wz$2qc*j%$qL8}n#KJ>pT0bqpjQ1qsM65}^PSD1i~y z0E>0#!U(V+q9i9t$x0G&4@O8LEE*68ZcLyTL8C`BXs(2ZWSqZqYl zMmeg{ka~2aA1&!ak+2L_%mNMta6k@p(Fq4o;2A!^fFl@MjB)z3n?MEUPlXy(auW5Z z)11OIsUQX)C?Osx7{VG*F$Yl2!wnEHsa8R{(v%KLpxq=WMaL@EvR>1y2PNxS*P2$e zs#T=>9BWaVX-%Wrb*Oipt6qf)0tZ;MpGYXeCX_&g6wF}_ahStBh!6l)Btx3%WNT#q zN?DIeHmm@>tY#}K(alvAi=Cu zVCWR^%G6{)=iZYzp0+Tx}Y7#Q#Y9OB^)ZcNny1t7vKZtxCj=2n}hRjpXDtIa`$ zcCz5*?svs&T=Ir@yyz`&Xgx~F9$NCf@C_meelbuSrt`izOy@vviv(4)6Oq=KLMJ9r zPjsl_w)Rc1eivNd2IJSk5UwwSC7fUiLwLduW-x{$oM8o5xWg9K@P|1};tiX4#2Q}4 z75+Pc0C&O}_4EN09$euX>vy;D&9RQ(i(?S$m%>PB0|;2$30-jG7g0n6J(dw-4+A;D zgAy@*r`+Hw|M<%J&9aTPY-KKE`NAHia);B|!wK*B%s;#@{uF+(;U)rI_`oe+u#8|xWY@j zTXLIsuG^&o72e^84Ftg%zd!{lO5ltjgu)LH7;lvRF>7#=FC5w@FSxo%PHu$``{C&o zx6EO#UiIE!0;QdKyiG3Aby9)|bVvd!56F ztjX9!7ujHoI2a)bi$w2UMh?dYWf6#Vdl zcud+1RscjVd{F^UCd1$IgP*E=*m<6@`%6 z_YQ|NIHMDBh{7BS00(r$`ty))bnHFPX(&9Hy6>~;U;chDmMaOedfSj`P*5TW1i z$Z+W2>}4lY8O&1dsL^lP}*gmza=d5~~ah;mhk zaQy@V!GMKam~zDCZh(aiVi0NZzy{n92gU$)a8L!`7I5k|bzJy{EfNglV5o9RXKqFHRR~oC zeh>gbzzM$)2RZNoy$}!cAO*7ac$YYbb+~TD_E}d~SB*D|bEkOa(-phtrZX@dhr4{Y|3yLNvX$dJmXYf}bkN{|M076*6c4z0Ij5Xo!x z=a3hvV36io?huNoFa&u9{sNiCUn}Tfv)6&XHh(mzVMu_3nTLTW8I&a%gGdku8_0Xr zx0ASse|eyU_eEvC7mU5IYMoSydUk>**@L;}eOZZ-OeudB_>(-SgQd24VtJM^cza`M zl1wOO{uO+4AcRDi20;L8q9>F;NtX2`etrN4_b>rN=SflI0|&;Hw}z8?8J7PygJ6k6 z+qZ;?shE<XqkCKnPmxyL;2U3VHSE2;8f*T0wb7yaIgwTxPybXLrz#@R+fm* zg@tf+Rhshjl3R&}>_u<43dNM=)L zo9o4M`jk&a@OwdU537~|9{_>WunAd3hbhNWcnAmXkOWr1crW*zs5Ow%*qhNtO*eO& zbf}(ih)w8-o>Hfa`PmB8rd$-@07B>uSkP?(`FQkZZ};E;#-MNf<^#!)c9`g!>=>b* z#h&)rj%`<25(=RhYKcM`p3W3~_lcwJnWL@XUIrSCNR>}br3A)V0&!pk!N7WKn2PW@ zjarumoPdo{-~idsdOEe0^;K)Jho(Karnx6(X4#b*sgn?Cf3{b96bWKz8kIyal~KS9 z++dY{AZz|ez>#UtTyb!n1rP!O00K;wfbQpg%LjkYXL~31gl_7U+DDY%m#K2frg>?5 zmU)wT+NnypkU5EzmfCCj)du6&fKeb%##fhFg#;7_e7(R8tcGXDcLmAUkOugb7ulBW zmxF!Qf%JfL75Rj&39M|Xnn3B4k@=MSbz2}10`L$8C(sSZ&<%SaV7(9m^zf8#nr2*P zs^{9KrmC)s$*eAzs=!LD#!9Ss+LMBomIUamb=sNG%9y!#VbX^LP!N1WpbOf-t$T0+ zu@wS?x?c|4enu*bx@nLUt6eCEU43Gu|Dge9xAk5IEmtTqd(iF;MiSx zpok{NqeJ@+H?RSEI0q>E3-_R%AW#Irpb9<^1o7|-ozRcYkOnWX39;66>lRscMWF_M#;Am`?;hgx9d4x#AUQZi@71|O!k!6tr>>W}lyu6F_m{lQ{wIFq zXMQ7Cgsm5A5;m{(H-Y!%s=!wOt0t>gB!Ov(m-DB*IT*d}8)iL*l%)#4nu@1}hF_y9 zy_L$pD0rvG8^4gpeH)1mt~F^>#jEJxsFd2Q&39W+pj_MF3?(pXj8<+BnSuPueMCHB;s<>Gi3)2FsA#?JDYG)3ytv!hvK&h?Qjpy;0?t71EW z1W*tFFYuSBPz<)<4r#Cf(J*6j+q7zYv6b9~=LxdusmWccvj^319ILULymKS>#*zgE zoA3pPTAkM^3qgPm^Z*QTsIQ5waol(fz{ad= z%i!#!R<{hGumK9npmzp{wkrm^OU&iGv`gwy5Q(aoS+5(cyiV!7_zSA{TfHeZex(z5sV7p(OfS5cj6#VaxEAuT9D_zC- z+nS(PsGUdwyZ5D%;11MdLHJL}G=+sU*%vDA#&A4*OR

af4lf`JfXNJ+ zFw*T1$;(jL9a>bByiMmg$eavW6B^sZEyx9>R1}-sk^YEvpx|0MkOb(*21Eb_j!;pA z9Lk7DqzC!h(Jh7Ln9gzB&+2JT!92Q(2L;i2sJ2iHs&@~5Ob?EbxYAtBOZv|nd%8-x z-;q@W#hJy-AiSZl3CV}f!;GGt%i!(J&amCFNKm>#8q70y2Gs@!vJebIXA2GxMQ(rr zt7~2T3~a<~x$XR&+2zy=xn)b-zbd_%_Jst=YQHy)VkZoI?%;sGV0_32zAW8+9Np9n z4AY!yzY{pdVf~bl){&E=R1#+`YT$2xr}nU-cL#PQk+{(Kn(CaVi`*}a5%*Nq*jWu2IIo`g$n z)sE(wMyz|B9gGD4(HzHb5=eg*iG+R4m6SPs9hm7q+|pGZmiNU9k*3w$AObIW*#Fyt z?seB-T<5Equ1dVuR~DbLdEv4h&2zj~%_iN>1OfCg53jJ*R$v8q76kJE0`CA=CiDh?nljhTicB>|E%eXdK7^&f?Pi%eq;|3xLOZOoXy<+T2}; z_o&=E3h(R4>$9!m0`9pRAI=iKRz=|cUqL_t8OO*WezTIScnzTN(~P(Kt=_r`%J3-9 z6`-In8VB<B7(=Iwjq`*p&E)si5IXN=0gNX_YL zX}zC%=VPqo3O(dn-sSZhe~_Bxn)VJpaKND$l5lX966TXW%=Mt^<})7CPuTzxhP@A6 zwo9PH-8++T-sLiW#&&AgS-1`J?aor?30H zzx%1r`b6+bx4-`E-~O^s1h*Xj@_)17kLYdeh~^h(R)1#RxG^o~$Uneg*q+;8C7i z$(}`<)+d#oY}dXO>Xs;5w^Zozq+1u;-Mf47{`DJJuVBD~4HrgCSn=V-i5Wlk+gC4N zxsfdc9Xz!1TfTwSe*Oj>8Z%tLqAhp6?AGjQ$E_Q`h78*^W3;PH-$r}5^JLbjcb8V2 zdiHSH#bX~Qj@)>1#JvCd1}>a+>CL#UUvJ*F_vN3ugF3%!7W#7X%FVaVT)jIs+t}Sd zhwm9Yb@}m6d#BG^^7P-^{r3luKLMd5P`Ldv8|}cxbenHG1>b}4tp1`)53d66TW&SE z0xVEL4+-lKMCm^KO|?86M6tvaS5(nJ5k=ha#r+14vQx217N2x7$`OhDP{t$So6*GJ>btSX?AGhCI>;*P3r4{-gfdMjon+3& z1*e3Qwjo^{{*pv2&D0OiJM#>4Pe12$bG$6?{L;!l)kJj7G!xsANg*A5^E5Oc?bAOn z1N9Tr*Ydj(u&pYjFVrPRjZsuS2gT7o{Kn+bQXf%^5JDqGYY|LXK{c~RGNmJR$5MMW z)mLGI%`?eTPn8Wn_VPGZ&!cW7^4YY0&6F=RQT-ChNVQFJt~d#OaI-R_6-75u zbAwEGTxTO4w$n=moO0FpxXt!neY>TQ(=z7^_bu_%Vzbplp_MYff9)F>y?pC^xJvJ4 zg{w<)b&YmmXxSY#R@^28w5aiTG!|IWE_B#XY*pTNUn`r1wNYEk-4aaO($!JZnnj)# zV>h|}yjEX`S+=*hi_3L)-eS*P_svxG%nQR3cWaVr?kYYwvJhPbGTw1RrWaqLBW^j_ zOPAg?W|!ZkqT!u=t~FGv5nj>0y#x(xV6pcWdgYN@6!*WQktS3yYyk%s(m`o-I_q4K z1vTcla}+aBwHfDo=*+9MJ94{&q;=UC(N;WbZ3SgP@88gyr;?=@h)=SM#Nmw_jp&574Hw@ymY2O!ph_qImi?O_+Y9MAr= z)1JS{j%|rcUhJGQUHWjUjRD9gpW~Vzcevx@)bfV)_ct25biZu)b;&OucEo5=;ZW)Y>1r27y zr_D=^-uoaHhvmU3wrqbwIshZ^JOO|*-6y3PLG8wW*8+S0~vr&2FyBBH~aF<&XChH+_X_1#QB$R zUZ$OVLFYNU`5bi;#+-7Ar%&?f7IW$ooOP+^Px9H5cAgV^fw?Cr=UJD25)_;WeW*g^ z^G=9v^Pv3vr$qIV(7kZ9ZR=#EF-7_uj|LQ=3w5Yu>N(DcvW234d8tbe+LNth^lK0# z86|C}K-a+SYDwJKB5@Tn!SE8p;-v;)SAgSt&aoiqSH?w4)i_OF;98)T^E* zo+tGxS3m02i(b{DDn)5l#oAQ6M3tW?mFZ;M%9E0Ul&)AE>qha~{#3OJ^H)R#EIs#% z)VK-;oqAR3RQrlpdfN4)&qQV`d8)3G@$x`=gWyOT+1NXFRj=-}DK_dVAFWc=u!^Mu zM@1`E)%Mf0_?&590aMVsxc079#j0pg8`Y#*CZ@VgENIbMqowM0qAfKpW2I`(nW`|G z+H6c($2!~Q8rPs_4X1Fk%h?|S%6P9d(sw_zNC6@dxx2g~(RjO9@vSwj>>(_0IcqKH zc2~9xh3j+~x?AZcw5^Vvt9&El(XTpHu>yu_eeH_i+s;Wm*R}#SFm7Y?+tG^n!);-!eD}*-BB#{HMI|kc4}4_l-m;L}yX-uBJZ2LE z`N_Qn>wHz2GaK^ka^fY}CTVsUIDXKOnZ+`FK?@%e3z@<2g>YdyTw@RS*1{|$QwCGKDaz2HR;m)AvB@@dN%S|%Gc(s@pGkJFs$NRv9j z7v3(lGmU16`WCPF13KHJCU}W8UYeU>O4hMX=F4Gr!d4TfbHN)Uwvnysi<2DM5T7o&f1T!?Yulyq zZE|hJobHJ0*wT{r_GBEsUt>Re-2)c(Mv?Axzojpzt8B2S>%HuHemJMGowuc5JmCwrufQd* z=%=q5;G9+S|6Tyx`I{Ik!ohPG)R zJJToM>1kX1)MLl}VWHmpp5HagzD6jqoqgj#`?m3^&H9ZZ4 zyEdNty+u1dmKs2B6Ev>NJOI2uDC;<&8@;DvyO`@d38{}G<172SzJXh}0KB{&L%r2g zz3pqg7Ml#U=?nXUxlF;SOKB})Gd~dgGvUKB>MA$TOTG##z>@PX;NvmfGdII?umP+% z1b$~>a!37jSJ^Qz)!#oi@Isfa!%PTr> zp&0ecsV2)qKJ2u9%Q*WhK@&_t)?+c(1E26YvFL#wJMocbyF+|xyxh}6Iy6L7)VcGs zzbN#;Slm7GyRs-eKnpxN(YmAZeoRg5XW(pfqpPYapWd-JV$a|$8c=Nctl5c zWJeh&$9GIedW1)Pv`2aV+(&=p$AG-Yf2_xWG{|`r$b~FOgdE6xyhn%x$b=+FfRspd zyhw#?NQMMRH%L4<3>jn0MxIGJY+wa9(8!5&NRGtFl@v#H`p16QigTpNnzYHA#L1l0 z$(`iMaO?+aVL78hBQvVPoccfA>W3{Dfo{--aVP^BK!qHzg{icKr<}?;ph~N>1+1J( zt=!74lmV{1O05)2ujI<76icwA%Cihhs#MFbe9N+wfve2QxrEEAv`e|9%eeH0xU9>) z#7n>=%dxaew=_$?M9je4%fnPmy}V1U%mHSYf+i?~GT4D`7=bDLLDF%=?kkuejHxZC z%pDkqahL*Tu!8=gwXgr z(F~OV_+(EFWzPx~1}9Jh8BhjW$bb{Df+U~=Zej<2XoM-qIF$>@_R+?*Aic|Y%0^&^ zFYpB&Nd5w4C8_E zHtY8HPurBEl*^EvCvw*D+C+jn=V$c1q4;m{S*dn`iEe!g<>cMZvf8) z2nAs%&t%Aj`utBX-PA-a(*ZTlPvxdMz+) z{?*rh<=21p*MQZ}WFQ6mTu#9xfB^tbix`FB>Rt&XHZUO^NNCGQ3feeUNFxY@- z00sPfRZ}%q`V3hXEm;$tReMcYloe2tT~$#1RQgO=1kHt&by)$GSN}9tTGdsZO?h|*{+24=7YEXdMP?b%SRR-m2LV7=Eo*iTZJ)l7I#!Bthl zO$Nh7+)GW|!d2Yz1YG+R+(ua3!);u~Wn9T^T+B67Kcy+u3RGnDmK}q>yD-%LdG*y` zolkCBfJU_iW+;Ye&4w&+f@t8|5(QB+yTj)Jj-re2*1lr`KUZu59T6JFjlmRAyQaT6*W2o9I1%qkr+7u;K z58cnFe2XIFOz`r|Cuuq=n1Xs;->pT|@&ttgXa_Ke)(n_}9_0jI;3gq8UgCvWd==L2 zwa=I(Pza{r3AW%8El~-EUA*6&zbez4K~qQU0DXL(FKqNEKpZ(2nIUHf>6LvnjKfW?bJ9f11HQp z`b{8dw3Q0niz)ckan0FNCD3Saf(3|HZ-`r42nJc;CQH5I8U9oUHeS5-V1c#d`K;Vk z1=vllUGg7cv|gb1}Y5(9q@%Opxxlb z-4`8ME6!EO{bJ$eWm8RA<&9(a<=c4GS==>RRxZ(ErrAk0(FX=!_ocr#eoCZfN1>y zE9lN}22xN!Q3sA(!tK>pHC()HXoh~^GL2jTonXivTyz%ZjF#ME#@h#OgoDi^6V66G zj*_-{!mXNvqOI3u&V>FY=0pwVUuB0-@CEYqhN`s%EY(s_09sGZU09~sy*<`gU1|PQ zW}=PNqQ8w@f*HvTibOI(Q=dXrpm40a&W>6xnzF@>- zw$tNuim%ej-(5B8fdy(QhUuzy0vvVJxK-n=aDp3vV#}RTA~sXOrf3WH;LPplkp18b z4pql}S#o&X&8?X~r5%u|n`c=vr|XC6)LnbtU|0Un{$ic#oyBJ=MpRI!0yTiz+4N=~ zb=PQs*Y36ASCwXD?p0uR>5V2??fu>Nl;%wMrj_Pi)3)t_1#R`@X&I>4fbPzXZ3lMv z*cz@?b4FfU1#M;yS;4hiY?Z=+^Q5$n=O!E{u8IQ^?cExlPkhd1(uU#oc3&Jw)~%=o zjP*_)_F;o|-h$O!f~92s)@@bQZ{ek3|6b@w~pw>60>*+53XZXxirEX?bA?$Dxk?_^fc;mrj!wa+q^1vY5iVlaj^mR+xo@xd-<|@zSpG z_S9Knmz-lZrOn_PvH68?O+=hrqyl=5-bsepVO{ad zU)9)tbVf&Y4@Ky~d?;nGWSwaDC0wZcpYfufxY~@-}B&3d7V{H z*p>l0z~Q+4PGtayc2$HmBG*Vpu7V01<&t6WAw!1+lVyqsksLXM1u+_Ic+p}qju91N zw0KeDMURbEb}T~$8@89&WaN?gl1d&KF=6uT3G?PopgwmFEo$^-PNFYq#++i%BFlmZ z$%QPLD`Clw4y$T?{%AGV)2CNS=E*ZLELDsYCszFEbzvhMRTh9@^TA4!93SX_2^GyB zTapIbu5HvdEvaNH4X4HEPnZ*Z|AGmX$z_Zrn91$gC(y4i~%Ipg(qBWGK6P!psLw%4Adl1@ZOu)`Mlp zXeWz}EoQ}(DWj7m6cc|Lv3f0DQ03rc*h>y?i!vl@+r5E%e0Y1STD>WhiG12ob=3)) zk)~8qrGbW;XrBG_8HEqdq|<~m)dW)M;?DKC%SkO)<=P!^S@g45Z#-BBr$wRheJ}N)_#Z!HF$+S+N%wUuZU= zgPB=)RA>=e2o#1kH5gP*AFKx7Mjn(}VRrvim zr<<(iB5H~#(w5K^W|sNWnGg;&W`to1dm5S;HU(;*5P9g8Vz?0pmW=y7%UfAdiIiAw zHfFUgt;}v4RU@Dr@P#a#+||UDoMc%Al8)`@iw?o$5Tq@^$fD0cA62#)Pi2+X)0Y)e zD6IZwr4h@k4E@*=AAD66*HyHr2FPZKAHJt&pbT4_iJYPqsNa070f%gkOmIiX2O@+K z#yFLZV@4AH1mT1-wtjlEcK?Y~@kiM0NosyO%gG;rh8<+HLnT!_U`Qx6A=84oZV7Cd zpm8a%h1@Bnp-^#jeBxOUXQkq_E;dXK$3>Ue;*u3HxsZP}8rE%N$;b^HZy(_Z*#feB zkij@C2OdT-w&>6oJL-+h+m-|4lt+f0{Yr4bSVzt^m;Uzi0aXkc2x{45v$qj^otv0v zoG5zEBvrDR4JgSOzZzE+Uw}bg2Ixlj4|)IC#mouDkmrkEfPs#BfS!x$Y0j&!`2IHN zKhxSsPBq4Ubn3Qwt}N&Y;`m`A}MyCcaH&0Ih1OcrLr9pF!J*XS2Cf zE7Dmjx$PuZ;MSx@&?r8pQp^8H;*TAHfeuNq!W7J43nKkP7UgnI25g}&fmnw(3fULH z`USZRRjxC@lAN%F5;cUqgcS=D&|t9VpXh0&POH+*YB-iN7|xAN7t7(-(lQ^hH9{Dn zU`{Y>5hQN}V>(VC$Wv}6gDk`gNX+P+k)Zf6lf>|0Jmi_joP|99s0cr4YmCU4h8wPs z4S5B5n!gyN6V#kAg%Yydn2dFkGwmb~s;N=wf+ngU>P%E;Ow|y3)1pS${w+7ILJK2D zW)Ql?&_zXz(s#mB3`Oa{7fwi=ws^z0$$UUO-bg|xO~C|(G;Uvy6BwA#S4Yb%WkVBU zN=$B`rqVSFcCC6IFolz}g;Y;4?r~n(Hgc-bF;82d;LZheX9ej+qwv`p5?$4;iRXU5Xvo+j|ImJXsE)y{{$ z5{7SANRdGt-r}=-{-!;oYMohJBtIGMk3h-e$XdvOt*jKrlKufjG&Z0QltIu68kB_^ zsvw0MdC)D^%271F;0sPXa0<-$00I}diHZ8TAOJQ9IYo53z!U$$P


Io(whxRg0whB@wC<5yN#;sEd`_qM!6-o-garR=Kh-;Q1OTpT4Dpadz1m^9)-^l5hrOG z?G&;UbLOegZ?|(Hk0y=b03C2=l^?crr|4{1-#~?!W2Ur0s0(g1_bEBHb6|K`oT&pK zM8E~U;gmU>Ue99NAyc@eEoH(-fZn=s68`np*hhtgeu~e^17wDUz0Pd^k}P=$kYoH& z1vOmIN=Z=H7ycrc*)Gm45Qn%j6JxDBzr{vIbCHfCyVD*+*wFk|A(8c+u!Z$db^SRD zvqw80DmxU2AM!^uPF7RskVjJ;gz~a?c+`pdwakY+aNP)tRx@h^6i#?68?n9`_7+ZHIDF7a>-x@w_`i~1|S^|;&Jq4Y>{Lg5QKkY@@R z;o-nLFW-|GCaeSQ&XFfj2~u200OEDW3oN&r2;&jm=>w<%a*I%8Pi^lRcS;C`3qL z9-7!1qT$+bHP%iDnTGs?E;-le0apEhnMDL%7WfExxE5WJ4NG`g3vN?&S(@+t5dVB4 zhy6+R1k(>T+$oYC)k(wx$rO1Q1HFh9cR-P{HQaxh3h-@9r|=W_P}m^89Lot;t`Wt- z98^N}90T4Uh6xyeg$w>P9m*7V!|)VO(1@6~kk|np25zAR-OPw$z~Mq@V^{>>hzSsr zIG_mmTgy$LEUBG>2vt#ifER(`(qRQiNeS+pK)Qedci@0vh|#=R45&<%+RWe+X4Tgr zBn(d37wK8qOcl^P-Kzl8v)G|V6oj~_!3k!7KGp*BiQqML)?UHWOMMDrMUJnThUd9m z6}DZM5ZNKtL}m4vLt50MRhsfSP!51q89-l3+0_lY5oj$BjI>ixhD}IVRLF5#I}u2# zJ%nia;b=+Hj6ekDnTh6I4d*?Wp^b(?^_qiG!41?5GqT@Ckiw2IhXYvA1UZpiS=LJ} zS#ZFmL>bthG5(Vb_1>_3oo?k-xcQPj^-|A(-F5kg>xje(ss&%dMYdg}K^PGdg_>)T zM_Gy4U~ZR!NfykN-!BT|zk%gsEtXSg7u=XgEy@7jWKwuBk$E%MnA?@?&90#zJQkFiuvac9pAIAe zERGW!V5k#VM|&w$3qH#u<>j9};*l!c+tBCnsbYWaS6;SBq@9G5{T^N(RexmE^eNL~ za^gw|19SL@WJ;qlWPuYf!P$|+z4eh6?%QXQPxw&|u>jmpI7NsE!#peibEN59&ElHa zXD|iWMeL7^z>RJe5F@okR3wmy90sdx3yI+7r1}q2VpMb$#Blc72(jF8vLi6+DNy7@ zKNLe(RmnIN!zn>uhB|?)&MJ4z>a04E6I6jI%tIC6s;=^?ukNZT)T*rNsuK`vuI6g~ zu+GD<%0RLHYC}Bhu10IJPOG!#Dzsi}u3GD?W^1=PL9-U?wjyg4D66)5>$dVLLP)C< zP;0XG>bY{Ot$JO&dR;CQtFV%*tRgF|YOAb<0(q!dF^t1_lmU^91JuafXu#uwMxcVW zo%-OLP_zuNK@i~xPZ`Jp@!YDv?(4aNE3y7+xQZ*hcI&j3#kYd1u2w<0f-A2k>$mP| zxt1%h3ab;$!@J7tuBPj+{%X3KLKTF9&$6u0y6n4xtF7898W6zJqJh&gEz>qF0h9&Q zKCRSRt<_d7);8_cR;|}^t=E=C*HWz~gaIuiKrE1lA*?Oisx8~Dt=qnB+_wI$GQ2I^ z)~(&ntsz*#+**Pm#I4`{E#AuQ;O?#9zOCQ(?cwHa;U;e3uI)G>t|3G&<4UgHF7Dd; zE#(rf-C{1?cJAed?&Esy-GZ(%#6kkl0wEB<)aJq0Qtj1lZPaot*v4+uYVGXiuG7*k zO^j_GbnQ3|LoAR$;EJy4cJAhWZsjs=S#+-92CnmFuH8a!^j5F+UT^gJE%m-F>n<(p zLhbi@Z&`Q(_;&C2mM{2v@A9uFa6TQ{1O29vabxAFAb|N4d3t#pRen}F#XD}4(GuLV=w}PunCKB z5m#_o2(S__F%vhj6F)H&KQRnX@%zTG3hyu#o39OfuMMZK*WU2^&TkC6@D!7;3$ri@ zqi`DUZ_Na81HbVF!?7F3F&)pb9sh3|AF&XxF(2=-AIq^G1F{l*SOZ}K1uvJvmHF84Ap_c1RE^Dh(g{vG@BF$Z%lC$j>-@F~lH zC7<#tPxBgvobbovn`7;43jM~^DiF^^D>*TCldl6Jn=e@vO7C*JBKnj zn{qf8ax_yjK67(EPczx7GAeJgIR|txpYu2uv@#1cGZXYd4|G5iu|emrLoc)idvgr; zvn}g0Mwc-??=vg6?hCVSPN1-0M3^g|1APcyVohj36Q^Z^(3{vtIBE44Z+bWtaAO>4AA!}LB=bxg1DHk0ij zWU@k!v_Ug9A)K^Ik2P5{@jY{MKgYCH!}KXna$1M}a~wysSNC!|7jRt|1@B)c2XO5E?9PK|21pRHCSUX3r96nL-RH}HgIS3 z3S079d%{ucH81D(Ysa?!0P$u&w`MbTaR)bbYqKHiPibqjYsWQgGdBdQwoa!pUw1Hg z35|B^OMWAa&_xP3=?b~CwM8~Fy)xQ%zYS^st-Besr@`80zxCQmklYqV1@ z`BEeIFL$_iyZHZ>^P6XQUN84oCwZLTIfvVJX@9f|Q~8*eGH;hLZyRt#!?}c`vvYg7 zqdPH<3%XmmBHVf)C_=95IyxTjyuY11tJHG!rzXN=`3;ewYJikXfv?F{j2s^Gfe6KV7!#h00Pkh7gy0a(z z#pi;v7yQ5*e8+!0$A^4bD1ah#d$pIm$)kL?tGu?eytTXh$(uaM%RJ1_e9EVMwCB99 z1G~=mywCqU&`W#HWBjx0`@A2$GPpd_%e%%C{I)l}$EUl}Cw;w7eZDI_)R#NfTYc4c z{kn7gxM#i8J3V0)N(M!9=Z+y+1{n$snx0}7wmj%4X z{LKgc%F{gI3x3NN{@~;M+w*+fH@@Sq{m@gr-Y-4b8@=WG`{ZAKgzV83N@CU!{ z$35e_KJxqg-N!!5m%Z21{_}^v^JjkT&;IR8Kj}k%=~MsdYkl`$|K3-=%HR6(Lw@p~ zf6vdoB9wp8U;X#nKKvtn?rS^ncYFQQ|M1&?{^LLK>%Z~m0YE4cIFMjLg9i~NJeVt& z!CcA)Dv;}7K$@8aCoL+mH%#-J1S+i%+ zrd7L^ty!vy#=ez1cOcY)O$kbD%2S!vi+exz<(rGIU%i9_8&)7VFyf7XA3Of581m%7 zg)cYG9C`C!$%i|G);yYX;?Rq&4#Z2Bb?d7TpVmZuy0Ylfw>^8zlWQYSiGs`mFDv{b z@r}kWBL5wndD)Y1L0e0})J6!Ly*tgTMXkdd(olaMO#j&lbB7GtxZU z@Ui-6)6g^yE%eZ`5kEAsL=;aOn;_XG^^J1YU4k3cNDB#%n;=o^o|GOIK%O!w}R5=tkf zdy}cuysJ}7F7dqcP6H8CPRZjA^z*6) z$4zG=vC~OuQdR%bTo24Von>}SX`vl++Gee-_E|lnT`Ex;jb%+vM5o-g+iL+VgU>(N zZTBoe2@Tg!WbG=IFI<(uS5(^Y#TP_J0R}Z-Ob4#@UrABbG}VO_ZdgQt5&o7{d08WO z+=CPLH`DsoRV&yf17+8uUCJT3-o@pYVLn;qnah#c=9p=&S?6*X+PUVQ zOU@^sdivr)=%Mo|Lm3_}$w!Kzi*EX9qL(JdX{eWO8fm4O7P_9Kmp=MyuBFDh>#2*j z8ttmDruuBN%XT~NsJ#aJZMo|vyY001W_#_s>Hb@7xcdg&Z^HkcJM6r(W_%Z|^Wixc zpZ+DM{N|fs&Rp}&Imel2%7NaQpMc$kkAMagngs=z3k4oce-ON&1_AiNt`!i39<-qUN=U*H<^zTM`6hC94n?qGMu+$ke=XY5Ptc5}uys&S5Iw4E9SaYr@kQI2@@ z$%TT_8?zxl>@~lGA`qTk2Mi z$y83}l&DfI=2zXx&=Br4r!D+xQ+XOevzB#(*p%ukZMr}No=ko6{GKS~2R}>>_I!j@ z;>*-$SeCYLri|6#<4BoQu41*AZjGu7SJ#w5HYJdpyB<`lHK>#=wed}Fy{;-_L3@$3^npNrc@4U!NFD|o*SK&gJ2fn=o zatlgV_TG1C?As|~x%k-F+P1a@Ch&o8D}(v{S9^FJW&hX;-?@617-;NlE(R&eI_}Q2 zxa+7ITQ|qnUG$70E-{Hud%F<_(!{Fuupqvd+t!Xnwt*dRYhQXr*eck4r@ZG_drHi! z)_1CKg`iHI8rdHj^r%ACX>`H6P=z8jg$|CZJ7GB7D*KP2;r*pv6S!5oDwKd@-70l~ z2~{b-63lTuYZzf^(1HSavP6a@o!{KGJFB(Mmx$zj75;3+cMh1)B1N#F3%$ueJND0{ zTW(WJnNVPs_o-=gqosdmVKt7Wjw8-=ib35+7l+!@sSUO4IQlqMuUdVVaGCg2?P^1} zcDA;y^=wN9SpOK2ooz{M|neQjl8m)VureeQV4T;89`pxILuGPDnR z+$>KOzeOf4E1!+Ttob&=rLz8s9H3nX7Sb{!dkVQiB6`8M(KduMI-`$ir6mm0Orj zsv_BFSyeN`v#Qn0viG-bg{rm5o3BU@InG9A^Lx1-=de~*h@?CxvqwnfXrG;zNB!-7 z#fxUF+d1F4aQVGqZgZN;JmxjO=iY06ce{^trmlV*0=I7Eq0-sPWMxPo8yLukKt2~1 zH~FbiENaYW{KXxnYiV7fHaXqcUh8~yTK(%r5c|Uqr?z?O z{QTa&_Yt;QJY!$*!QYzJ?XR_g0q;rv!*37J>Em8l#h=c3f3utrx3ok5Z*?@x@;Fb_ zFpl#^Zqzhy0Zr}zMeOrT&en2{dtM8rRBq<_4)EeHk!mgj?`!ZZiJ*1?>ds8~y6vFi z?&=!v%$j1qyzc0R%BJpY%Y2RD_6x0yZp@|%+HMHY+)VD6i>Z81>6Qx!w@>kyN(Py) z-GuJQ^vm0ljD?!81lP~rKv4AfPVf4z(f)1=Z_fT|Ea&zr<+zB~#A@4g5a@nTl&nVL z*a)HmP!J|h5G+m$IxX`cu;eoD<6f))`Ec`03kzjzlEfzibL__0FA=xL;NVBs4DSea z@9QXSfu0NM)(WeP>C4KD_=f(?>@?A!ysX`B$@z+`yn?FxrVj4)Y)n3$Oth5D&>Q9Luqd9FXJ+5XVT*weocH!}9O$ON4$G!&AcJq)s`0zJEP|9leg+ME_A2i>@E$cV=VmgK z?k1AEIx?rsEFUr}4*nw#4(AB8)Da!A$Mg2^9G6n#S_}|1E@fiQ{&vpv=;2l% zD|v1LVQS`zD*Em!5)TRzuhA@lE7^u{mcA*wnky3FvMn)@_a0K-aM2a9Efiak{5-MY zuIat<@7KZxyN>N7=Mukq3NVq+Fq^BK$Wp=3hbL{#{opSd;mPm}ZItT0LL-o(y~SXZj@2AV z10#vxV3INuD|WQ$lO!tx^Aq%(>l9}mJ;k4%dj0M@IU?YE5-5)IWs_o(~;zf<`Pu) zzKuJ*4JD;Ztlsd_ByU1LD-WE~95pmU9}p@P5FGa|L>md#_;Y=3jUR(kEdT8)4Nu?b z@7qYy37v_BQ1g{~3*2zA>ilxrj0-JcaF*t)FQ?HiiHz7P5g!AxG~cfLh!6Vkau%&I zx@HtfFEKl75c<@q`y39d`YJSG4@JK+A7u+ncMg8Ylpk@9A;c25T5TwWG~N#CEzNQp zORO6y&hq#WH&bgjsnW&t)KB{eHy@zJf^(7H5hn}O9_Q~s7nKYTv`kkGuw*UQK2s=H zk|gc^s}dWMuDbK~%u~;pt5ZW#%oq;{O*I9ZFGdM+A%#r|-}C6A?v#2k1y?c+LGt;A zG8YdrR#VkGDJ@NT4Y3;Q3mp|r+c6(!?m&^%SY>L_NUyO}tp-n(vZOEx)u^;q9${$A2Ez2_fckqOHlqv z4rpt$Lv=GZJFZXN$6eh~K#dbX*L7VXbu$H&7+*HfaIRyk_4#DcRIQ36CygSb3_7dS z?KtVoeidv#^~`j%&q7hX+>}#~YN_^Y>ufa$d9<$NR?2uaJUbQ2qEI6%OWzRgGh5ba z&B^U9ou(NNEN+T5#my%8m@$-8da_IyYZ`pDO;p(l zaF_6{9<7r#_}W~N>DtOUHTY|1_@L;vc?Wmhpy@ql)*i<&CyN<^PuYP>^n!!6OPAJ7 zCoxo~lV&-W+PrwvFf=wlPH4e39H(-0&p4tX*Kx~-MAaA>o0wg5&XnIcK=rMTgVz>u zwk#D-dD$zFZFvNuUqhGD%8fl4XcZsQ%s_EJp`BB%%ZB&)4uG|U=K@~gevvIZxokvq4 z;kMdzu(%-dc+1TOv+9Z!6KyGss-oEvxo-{8Fl|Tjgkd-dS(*6$l(X*KRr>OChievFk@B}CuJSYjsb`dvCOV%0TxQBBozuYY?84|f5u8a4V!h`z( zd=|NNS))u>#X8*NY#_u%e8fq7EJ*ysQ9Q*}e8o>3flgeMMw|}#>=qAZ5)Ac zd>8mY$9LSvYkbCKJjZik$9r4`a9qZLe8`tv$&viWpWMceJjrhy%Bh?ojJ(OKJjk`Y z%cDHUzud{M{L6XV%dfo1hg{5qe9Eo7&86JMNgU2ue9q~-&R1N{Mcl?vt zIepSQ{nJa`(@j0eQytYay~gd_#990d>^#I}ebz%9#z`F4MZCw+9LE`5(H9-fft}Y? zozeLK*p0o$8J*OLJ;{@O(W4yMdtKRkUD_MH*_r*f9@AC*)$>5#MSjJp?Zsul=f#4m;;KLr_{~X$#-r2uA(lvhV2|?A{e(m8t z?)l*Dah&dP9OSJ&?`@#sUL5O3oZ+E9-FLp>1t0Ja{mU7E-fKMZ2S4y}oE#ee@CpCy zC4cc1AL?U14~TyADWByFzwo1+@io8U^I-C6obe5x4-!B1T^{s1-{p}!*ZuzAXJ7C2 zzT|UV>qDFrGNCC3{@}m9_Y>ahgw}1Od9r6ib(w+bQ@yEZ$v!BNC9>w{c#B06%X?^5%U&J-P?=2tFiN5qLzv5m$ z@|B(Fi=6QRf)5`VG6XUZI4}=FJ_lteMA)z(#Do+1T71akrQW@K2xamMn6F^L zy8;g$Tr_LcqC9))Ek|j)%a&>-|k;`LU(gRb61RK-y zN7({R&yKCSwQBxy%2HD79P{C6*TZp>22K29^4h*bE3b$;w{yAE2~8i(ps41h+n-MU z4jyTC@7!f@HP8JmT4ih7W@4XKEPSy%+^V)tTQ}=md4e9^o5_Cy4#=8Zel0}KfeVGl z*j1G|$Y6wym3JOdKdqLLYZ-0C10gygMl}{?p5Rs16=hoCX@fxcNmr19Fd3R6 zcDEVkqW(#Mfw|*tedRTpf;0}f8#HIr{JGRMb_t159$f!uv-1#M6E!e9wcFZli3NOpG47XY`slZY1EWriYa4UGJeQX zqcEao7y~Yz7;u<_lB(&!5(T!fh=x^KWJQTq?BliM(v^w9B(~bHae`LLqrevNt5i|> z+6$S>GQ<2}%`*%8Sj$q{5TBQ6f#sf9sC~&LDJ@ETW5E(-ds2s|#_2SO>&6*i)RbEN z{;fciYQ5K*=1=kDG(wI>%NNf)SdAFZ zd?U^??|18w!``3c-hU5%_~MUG{`hPEKKA)*qfNW|=c}Fm?eEY3zS(c%eLwr}voHVW zsRRDMz6H>7sJq+%J!HTH7I1-_Q(yxb2tWr$5Q2Wo0|g2Azzj}Mg94Ob2QL`@qWKYk zf4A$;{Z1&t6yi^Q>SLk&R`@m)mM{-1tQ`&U)`%Ql?|Igf0S}pn8s;UVdOK_c;y@U{ z?v-zeOl+bPy~n~Brci$(d|?c&h{Y6Mv4!i)-3$9Oi21#agBaYP89zuy1R~LcWkll{ z+XzQBrtyFWq}&?sI7c?h@r`@@APm9SLNH=6i-c4m{RW9eK+3OfYa<78s`tDg^6-(4 zbYu@F*~d5zP>E0Mq$fWKI2gLkg(Ng&Aq!bQLXI$gU3}pPEtp3<@{x{uq@^s~h)Ye@ za+kN%WiK-cOj~Afe>Ws%7EOuFQ)*F!jGW;Mk&_HZM)Q))BS$nPnZy3&?a-RdKfA%5+w)^Gm(rU^7W~Zlw^XM z`@h@fcD>?TEZ&-V-Rnkng}e=;Cy?7&=;F7w{MGMs(feQLijY5|1=3oL?08SH&hy@k=E;U9o-` z!TXc(c5x`!Xfjm>kaX%^8zISLWFkQ&wry22jO4@l{xpjyrLj68s^GAmIJzz_GL=_+ zyg|Ci;97T^=^U3mP6jFPhE^tp95HW;nCgg@$Z0rwxtJF(aC? zEG~5)`|{^J1A5h}ZZ+T5mkZT`dd8v_ZCG7<<{=_yl4p+OR5PvV+-~@kqNcHL!4hNq zUA8ZKWcGfYEkS6@QrexRwv0@TPit$tji`>cimjc?`+^zKvvzVr6l zmpH@^PH>7}{NWkLc)=~+agG<<;|V9Z#xoA`k&C?HE01`~O%C&xr@Z7ZuldAdesh}> zJOZ|j^$Q8C?+;@U=!#~*7o6aPDmcL`NLRYj3DR_=FI@&wmpas|5b}!4JQoA+Pr;`l zh=hY(>|qbY*v(${v#UMrY$v?P)$Z?{i6)H=3T55C|84JKaUC0j@( zUO>i%)#F{Rm5OZ$SbG?Xa)^fwCW{Y7Sd(Om@m7nfNQru=r|4+32xP)Ii)&Vl zOb`mbKnIwp3?g6)Z14{Y@QD$Iin(wBWd>{MW@C)VRgRcwTyx)kGN)!^@xx6sE_%`kM=l#ab&ILSQ1Pz4Jh3l3+FRuBw200so%53rSkuXO?hDN6hikk_S! zcXm4&z-CG1hyFkizMun1;0?vV43#GfXsCwJbdx7(laNG*{iv4v$d+sAmTehQ#dcso zWl-42e0jhC2OlGa^MwN&1vV~r3pjQLve_Lzx@8sEi>pV@1pxtWsqV3O$%(GUs_mjqTY1!V}4 zGLVKcnTJ*WDR0Zu1jlz{Psw+S_FmiQ2_o>4Kh|!()(&961|N_CQ{ZrP00v(W4M$mN z(xjL~G>_}1mXS#gkj72q*_P+|UEryjpsAh`RXxI$cLm6ep*E1W!ygOy0ZA2DqUf4G z^hk{mn_u7y4mXClS(Gv`mO@mLNvUR))LQQ7ny@uQrx{p9G@3V9N!DauZ)k@xSxwSY zO+(a@9NLE)Dv};alg}dz8u1ToU<-qpj!qB_B)Wzx$%aD4W)}c!Rydyu<&-}+S+~<0 zDLG-JC~1?qW*QL+mKY4SPz;sF2C|R^yLpkQ@tqkOO{8F%ITTgO8Tyeubmt5SQ{voWCVv9fmgyU<<$Lo)-0)+u4|l`8=S|lMeR*K^Y8m zz#dG{W6cSg@z_I&Sw!HKW-WQ9z9^|D8DtO!o|V~}XL?OAsS(U6nxUDJyl6?6>X2b* z1x>(x7uXI501Cqxp%8jej2VoObOPiSRy}H0$tFf+kfDv5lRS8#6{V2KQ3a_gouqex zUr+^Dc~sxYrbL)S>(&T?RXtt0X71UWd)TeE$fjL7P2y=y)T6D;6Q{fiT=kiag2n*( z35%@xr;V9S4u+yZ#614M1Ybaf!C(bmX$ugk47*u97r~LBYL*E*Ny&g39ywueO8%kU zWvdegs7RHA8ak8aB~2P@l9cERve2a5w~7Cd1x~P{W|^@mJFA^KO(y_!1UaXM7L{wm zAK+N67a>GlnuI%(W#f;lTh_n4BCHe@*~wRotl ztaXPDO0Cu;hzcc_F)M4k`gaJBspB=P_3Ed3TCskGugfD02jFm=U<+n21v&5mR2T~D z2%4$Mon_0ZmD-9{d8(zEk{r8hdFZE&Dw-?^Y0U|5OC>%2kgO5NeG+MbV6Xv0id3@N zv-G-SsL7}Ex;*RwpYugfS;PRTtGcVpx~=QFtgB9a*He|?Zp8YxnMs-+{`#8NmNa^+FNjf}KoDEmmCRs<${>wn8Iz*Ruz7%#)bzC5CD15>tyuvBW!YWL{#;^ri^})8r3_=vKZ>YW@sk^@E!?1Xzl<1Se;0@-O1Hq6D z`rrhLsnp?gQHGM4qhv#>bj%;3HEcqx>xVkYq+~q zraEbi%7WEM!HqD5GVqYnIR)sb4A;pHpx}Yn+iqMMhk+Z6T1&As3PhvoUFsXSlG_{6 znE@wY1+_pBU%&)M`J4TL$)PHbn0%#;&>vKFrJ>7LjLFFxs!U+7#9OI= z1-q~dJRr-oJj=C=%eSn{w#>_KAP0GeobyGy4GO5LS*47b45W~_42n^mY>N#E26XTN z{|djHAPenK1$^w0|2zJfgXPJXDgz6!j9pm_4i}bb zc*qC4$()=Aj)ck0^U-t2(et>9;HAvvJJOYu(jq<5qSev_$jM_P0>dB)S1`+0VADK+ z(>I;dJFU|_ZPUAO1(Hw?MAB-R>xqx-sIQ@r1Rkm1-npasos;TAAx%}2G>>?`@$e>T59mhq()y{$8HE+4Q#08J%=%1xa9?QJ6eUyH`ppQEm>1 zTO3XPK#BSQvTd#3&z)=p@UF$`R1V76ES{}|TcXxY-y-g_pS#a&n+xoq;dCH|kH-dw zoy`mCnc{0rH~^SHSqz&<2U&oa%R>sqO6ru(CuquHbEt%o7bx@UcYfm76FFuP_h7fQt^A%)G18>?vW-o4sv0N$d!q zlPiH%FbwyOxrv>jq=1ad7!1Z>c+YsvCOhgpgy;IMLXQ~Ta+8;6T(*8qqB_>LZz!I7 z-N#FtwonggQElj+3xgT1l@nM7VK5F}5C&er3}+Y$W7*Hd%FM56z$S{pDQ}08+R2|R z(w8jSXZE3Nh}zLA+PD6g`ejhtxh`(IEoivSN+NIttebtRXiT^B}<3Rc5uMNduflwIM z9a^u?lka&>v-0`9p1=TQQ0*US%-4RgpYQE%2oU7R$;d@68M#IR2__WSs8Oz52Ms19 zXb>UATnrCBl!4GA$BzhQ$oK+=(}xUA$|&RXPnIk?oK~K&l7tSJFC#;OOqeiPu8utg zLfq(aVMu~S9p=iD$7557O@%hK*fbANa#Rgs6$(;nLakOGGR<=kY8g+Sni5c(hrpn= zZP%u4>Pf^d9{&7l;l*2yN8i6ZF7X|Vcko|(T=3HJ#MW_R$ONuNZakSlhMqvX4(!-a zVL^!pxqck&aA3xZ2#G#*nv9{)(3yP7HYmFh?Trj4rmmfklv0GzLV=-^#8@$AAK3hJ z`HxeQ3@0*t-~^`K0bv?RC(>*f>MJW5IPjXl# zzDJ6>VWy*s!pgJw1gcLbiB#)oKLBMACX@wa3C5e1Yzan|1)LCOA>9gO#|be0QAQc$ zEW{8&kMdhkpkzons=lA-^9dr)5(3I995b>CAshw5vB$AsQ<29XKl(AOtD1nTF0yd+ z1R}Yd{=CbtANm-qu)}uQ1xqdeDyOeLeke>y^VFlvOaequ(6fUo+OI&*^!pFRgaAaX zrv?oK%c+KZB1O-gb}H&4_)=`-AW)o8Lqc1aDaM;%=*S|JPd3|07$@LW*n$c?Cz*oGNw`Gd;fgELIfh}pAif0Rg|FC>Vus&%gJB;2 zhB43JRl#!%Gdc0~Ph0tRH7MB*k*!suWOv)s(qjXqImOU=@+X>-o-;-|<@DIV6i`x2 zc{8Lv^M{?DgR!CsD{MjaJdsnK+G?xSqnZI*QcTyPHUEq8-l0y;qeLe#g`GinSvP;m64(7kM83&9AQj}Fqr;EAN4c{ zCn~kMM);GKKO{`CKK^R_u|5^#SMwNzfe#o(Sp4xxkgz8sk!a3X6T#f{te2mc4bDKq zsKQ9tU<)%$AzXg@0z1leJ;QB=Sib6y2oJ}hM&O_dU+~)po@NE=`0W4~kX%UYl{1}m zWmXT_mqQvMIEMslBJ(lf(MEFtfw9Ul1Ry}N#se3}+~pE~IYv6T^p`AUQ80M<1{SvT z7mtm{RgPgwcgg@7q1@_PEP4?`fLJ&Q8g5^lOHghMWf~krLk-Y!;S{FB1~91M0RG_D z`;JB^+}I`)7Wv-%^7kG6Me>o6xnEn@!nHNM>5a2OTM=s(AOmUUll~`!TSELX5?|;b z306SPi2iY%$h}dPCoITE>}0)8BBfp-tdS@af+_Z}!5e0HR51J&ipYs(fDrVg9JM!; z1s$nKf@>3M_EQ?uL8Lo%fns^?(xosFMoU@R(m1tLPHlcuJKX|DCA}hO(Cq zSCkoRHiVj%Tbs22q^y07uX})M#DiXujR`r*LjPC*GRq~OVj0pR;Uimuiq#?QF!DDD zvEMr-`O&G3u`;ZJ3ntr0E8uK0f*7%(8adNa1ahPb5xO8VRuT*y_#zZc@W&2)8q?7v zLpJMT<4XA{)NG;DXgkayLUzU;I`q*D9~jXWs(=G+9R#VX{?Q0l=J+CM;>b-Y8Y{2J zc7ZZdrgf$-Cqx|NJ z_VwhX24q*g5=0}>s_~ZC^ISs8;L#**lRRzx3&ZL#hTg^Zck>koBjUS`RH@c6>QR&0 zy!X>P&bC0`jqTX>#Dq*C^f+d)1sgC_g~-hhPYyZ$TYV@@;RJ=YP8+e!es1#`KOuxc zzv5{ADtTHIw~DW1tlB00Mo(%c6^`ga?hRQ~AWSVlM9OfKHEJzN8AjIW@`hi(2tYK~q;h>=n9X@GLfbpef;^ zmIp&ZNQol#Ua-NBX^i$^5Hn<>n_e^>ttS-Hwiu+V-f!y8l)A?ZA{X;4GQR|jIYn#I zKmKs+NL<*2>2ShtS2djIfGW2Zl}ypE8E^g?3(U#VG}lmh(lx)Jx3*HQ3A*Lw%mTm= zX=Y4eL^r_)PvQ7B(GIDX$OTC+We~8wGLe$#jg0L0@)y0B^DlfUXP0(ik8hll2VZK! zsL%u%IQN&ixeU#eGYMF0jm2)n35GG0Q3mC_(g|}Ulnqp<&MJW znohc2tgct+Low)j3C0-D%>)Rvn*L(!Qim__Jrtzr#Wk3OoQ6VhKJqSYv@>c0xrRmX zxx8y&vq*a0xKE?6y6BHJzGBfP)vRW{@#2}DTmW!R&vx!h@f4%S&LM* zTTjxi_NJ9>K;aizY`&bE^8j1>eYUpUZEJMTwau>17|yY>;Dqj1BH1rQqo=i`K5W63 z+=ReeGJ`+(cw{HvH#}^$5(^ ztEaA0kO$GR3As26p#Xh=u)=CO2SSLrTR~MD4~5~kDawaoxP?2LGrT~5F#i z4*p>=?r5UP**3vSksEM=5xF3u^D*{7rmpM3)8M#Li=X#t2u7INlWr22xtph&Q8p|yiC@cr5ecLN__AYr zMOo32XX><&XpxC}xexR-%lbeL+l+-=IokM-m*YGb@r;<;L`_^jn=6(7>6-iagfGAw zWniVL;sjY32~gmdz-l{)Bbz525bRqyY>c2Y1CG(ryw!L<0%0aY5h5XEpqMHv*Mc$| zYC2}z2(F4Fq(rwIlLa;j?_2sC)ipSFsaxB1E5m{&lCkO>6@WWi_Oed&<&KwEQ3{5{&%g{81 zc`yai>`c+D0>1&xDp1W_PzKjjP1r=uDwxfA01DUSP2ZGF)cD zJk8sjhumyV+O*BmjLyJp=rcV z>VV7R1kKpI&er5j^E8FsyioO|&W+21;zZAR7}4s)O;bS5-9*vVL{AMx&I2IP6je; zRnnC(1TEdt5!q5humnTsQZEftWf)U3^-?euQ!P!?G9A+_b<;NWQZ?n$IHl7q1=BOV z(>#^aI@QuS_0vAx(=B~dJ~h)nH3UMn(=k0%Mh#RkwFDBtg#;l?8>+k4>6>SpXFJa_1U2HS&Ri)ul-uE4cm+j*2QE!$83s0u$6wS zHPRsmt;Jcm)!D0^+pPuKxD{Htty`Ye+jh;{yM0@GRTan7CiA$91N9yLGcX7F>bt`w zp8PA?Rry=H_1nDdTCu%c%oSTc*j6AN+4As?@uDt5UDkbF z*Nxr1mE75-+-5x;x;rt-xC>C-qAPJ2HoOFl;Z!^mRq+sA!fRODh26b%S8%o5%#B{@ z{aUgWR*f*4Z@tG19+Ey^5BFU*`Q;115y_h2H6HUC<--&f%C|+dD?Of|ME#%GJTT~#n(L9y%U@}(VH_lcA9%Dlu-%n2C z15RO1?pZc2<4^`;!i6U~l;8{)xIT-+DcXfvxPvWWguS>TaMTh2E|Ur_l_N%EPgZ5g zRb)m!X6ntFF`VL%GFJaNkA5sZ-B3nVPUSMj*(4_6F#c|1ZdT)F)n+rkW@0{LX3bh> zwdQ%%*D5AM{9Q+Y#e^{!3{MrO;N22h2&wvo$8OqW$pz zxn1c&83T$;kk?@r=hZ#sQ5NMD&g6?m=Zh|1n(d#AM3oG1~zbM>Z7!rWyiJ+p8;?0sOC^z*dbGUyc4^iDq6t zC}pTV-%tK$n_X%Yw(6?Jzw9kgKp*lc3252ipgt9 zVL5CSUSg`AY`T_PbH?qc?q-YaZPO0!rdHyso!{8TAA5_#%q|RY(BpPC!*Nx-}2U>{vb-#I=_xPoE`mta8W^eqfcl^i~gg{?- zVqf@Qzx;5|{A0&_%kTWn|9s9L{h7~mmoI(PPkqBrd`jnaIP~;<2>RFG^q&9uONf0L z5DZVh{i1((V`uwupZvv_{M!8W;xBv2AAUhNezZ@1t^a-J&wA-c{>f*4;D>(UclJwX z{kM;Kcene%&j-41ft0R$lfHZLzXHL(f`EVd!{7da$A0Cve&UyZt+#rz5Pki({L$Zk z&*y)D5F~J*AUgyH8a!A~VL>|%A3}_nCr`wR7B6DVcrjP5iX0tY%17*yj9ffKioB%E z| zOT>!uP+hijQQjSiD&rlzr*PlJfp=bcoM3O_$cg?Inmqcz=FEp*Hx7Myb?REZ3sTPc zw8K1uGnV4}7VcXuKi+*1c`Cm3m^T;bLgSLBn= zmv1@aOqgHF^#~wmb}1&9VxB-+ivBSN<&K2~`Q(*DB`8oi4E?E4pa-!4sG$lKD(ImH z4NB0UrHNLWq?6iV-hL5X!jVlb&1hSVtj#o1iy^r-pn*HeAVX(Z62$62uAaK5tOvm= zNUgUr87r-*s=Di}t)d$2mAwM{>#M}RD(tS8N_5dMV3spxv~Sjch+J1l;+7;eun=vw zZoYN?g#i$WC=q`uI@D^ewxYW3t;!ZFP@hL>;n_g-3Y3{3_*RCQzXI{AZ@~B3d)8=? zQkrl^bDqnQZKTdvBa0?UtWr!eS!}GX@p7DOj~cTJa;;KsJf*KEcU$7vC_TG3?M$Bg6c$%OP7iP=fjrv=qLL7EG|! ze*UX<*Hs_13m;;WJ+|3oPjt50WwX7u+ik;rHb-*Fol7}vYf9=&prXY0Oq!xJvB)xr z%t`LKg;riFDfW4^f6c&03Q<02bnF0&RT5Z`_9fzv{mr@Q{; z-sH| z(_^2#_S&B*-SWaAO-1+~CnLk~D}ciAo6!5&{ue ztBE|NUR&!Iz=DS_fw{1F%4=Z?Sr|6xSucmrYu-enr$Zk6Fo-)GA`pov#3KH17q599 z6El^I*3jf)F1ZbCT0=z|{f%Os^Pd6@*eb?tv0VlH;@~Fd#mspwjG(ih?*7iWFB9Gm zHRq}wh#XRiT}Vq>OPIv9pe3zmSR-6-8dC>H)WC|+5jCbtBO3GfIX8~5ReeGpzicSH z$+R$dnv`KBf6~cJa zc2N`XJx^1nOiB7u0wWh$EJiJHpGb}+LPyRlNL+;EG>argNcL}lW{l>_xcMq=N)w#c z9HSgZhmp2)>n-VQ0XT~0&ee?}96a00Uo7&$29EKY`J{>n0obQavhb5L1Ss%ih{=H# zkBJJ!AuoFf%!NLbp%9&@L@Ro?COQn5cH2_kHrH@RRPJy*5n!ao^=n@@h63~~spx_%oThCo)fC8fNrI2bt zWX-zB)7NYhrp5ZFB?+2I75+=0_yQ|JyJ}G3>9UrmWTh)@smfi-@~vsjC0$k7L|;A; ze5hPv6C)NX8!2N`e+w)!N7c+~Hc6)A+^IgPDNe06c8ibYXVl2ZSjysWvLVFgog7$4 z5mlp2(n3THE(op&<|7W2uwb;jASatq6R43inKxfnz<<)qs{bW1l%0YY-_S??n@_PMaF;vPPg`2KY}%A} zS+Fj9DaS>5%`8 z$S~p}7ZwbIK0M1uI(1eKFlzy5QUwgNmZsS%A4$nnX42F^Y1TXc_N>4qUO@v2HhwAe z#?Iwo9+qoe=L*`mH!dag77fu-^0m=RY&2eTqdxw>&BoGwW8X_|lPmf5mcN+;b$%gx zW!wd;yu4fFOHqws%`t}502B2|0f;zN&y1*Awn)y3_Kly}r#|*Mh5%rPAB)g#j_1Lh zY~N+o%>B+^9)^r>Ijma|U%SKtaUP@XD(JgaZT`&?K ze#D|o_s*SHJ#|Yr(F|?(p#yDha-*29jNWK2o+mLFy~LwHzI44qf}3V)ec!ZI(!Wz$ z?Ql(ogH?UDwfr)T9V1yNs&we{$`!mfnCbMx zT-*lDz!Hd7oR|h|&6)JAVbtK3on?kV(cB4&U~rM(_6dRwwpF|3oOM|qrM1<$1>y|a zV5VRf6YbR@s#2zLO8h0=`pDmHgja2}R~Vg_2gX#_`QH{b8z%Obsj6^ z;+f!5kXz3|Pq?X4qER0D-Jmnx+#uqWi#1Pmjgl)d6X|V=>CGETARVWyPfI17l|doF zO!~VUk8>E*Xg7hF;+~v6xn^98l_!%oXbNPRhSHe7BCf5na)wEQ&P%>>|n$$ zCKCSfJY zVFVq+A9UQpWT8Rq-eAU~lB68>g%u5{93HkDSbAmHz|zgBl0)6t4HjZ;nkD4bU^hAs zN1Yo-dCJ73q-($*BbHQ5d?K@L4k<2>FTxsDTIDZ7rvawatD#hKIL;~J4tDt7L+s+i z;n5UOoGg0FfHjzSj)^%m0GKo%Q8F9{?qqZ(V5{7XPZHi}Xpg4gSjOB>1nAB6 z5ay+uZ7S(ocI5RK;`iCuF1W->u%tNB$V=#DO4!Ia-b842=$+W8sNSe(qH2fQsE2Z? z{;HZ!V_8`5WMYTMu`qi`{+ zvI1(>WEX9A8xP2448q`A=4NfWB@g5v6TOCx3K1q9;Xf^P{&IBY>d6_^G&FcI>J$dHn{A`Wlti;m(XC2Pa zo{g1$2I|XUt=AAlG_D&+su+?|>-RBfqGBT~eJiA4S4l!zVCfAco{y)+h^J`EUpdiy zWtJ$aX_+1;nd+(FI%mGZ3Ifs^;WknyKEO~`N>Mt51qeVu9#xB0?o#%Q95`Ht%qYDA zZdM9oevaViG6X{yYT;dM>MFwOvTp0T?nJn5?8@%!(r)dtZZ5>`O5|=X1cCziuJ0;? zGW726DnRfK@9!Ef@fNS}D(^}hukZTL^A<1fHm?jwZ}Ji^_98FyW-s?{@AY~w@P_a5 zf^YdY@Azu3_?mC`N^kU@uk;p0`;Kq?DzE#pukzAw>vBZw?l0{wf)M_cLI4Z!026Ql z8}I=$G z`YN#y7qJ2)u@TpB`a+*H1PE(z2+wf{%ds8faUR=oAh2)>m+>FBFbun{3)8R^H?bijvJFqM8y~SEAF?AS zvKlk;B4;rqTe2iqGA1{&8nf~B2Jz|=vKRyMD4(zbgYg+>^8O@0vLx7RvI{&hG5atKE3Yx%@D?9)GcU6<>o7Av^E5{@ zGz+mbS2HzVvo&jRAtP}YBQx|?>M6~IoI<& zYjHEbGVxA>Ec^3619U(uz%IYDJFm0;wsRz_vO=eFLvQjzUou3q@+wPoMLRSlZ?g41 zv?rf&L3_099&|8!b3|V>MVoIP$N=#Q0tm0P2e-8HzO+iS^h~=nO~bTJ6ZA&|GBAU3 zJI62;yTJGc^*k4|MvJph3w2S?b5bvLQzx@IJM~dV{`Kz;buuIMRQqmKOSM(cvr$v^ zRdaP%Z*}*^v;OL|JDYM(ukKiXHC8KtR=2fS$F&0Nvj@+BK;v~@2Xs!K^%#fr>i)Gl zqpuZvHA7dgCzmwv7WO3*b|yFWVK?t%XYXPMA!0-JWM403qc3G^wq;}X`Ihx5_w^|A zv^s||@^W@&dp2sXHt+^9O3yO!*0Emyb1mz!^z!v+m$FYQLTLjvShICj1NU4Lw{W{P zTpPDsCwFka^>8nDaX0sIJ9l&|_ggPEa#J^RWA}CoFFS{}ZjW(k1M_o}cXmTJcVl%N z&-P8%bbGTmZM%0K=QeoLE*b;2eVcY-7jJ6*Z}erec1G)WW%oBm6SzqO_<$RDfg5(~ z26kZ6_ileTNh7#n*YE}3GJL~wO#iNi`!0vuv4_w1gO@UX?{9UZw~0^piEDR?v$%A- zIEugcig$I4pLdIYv04u@ev5bl^LB&VxQxU24cE2r-Zh3B`H|na3j6Vn+pc&EvVu$a zXG8f!Q+R?~d6i>%lwY})XE~K?`F(#klhba4r=Xp58 z`l=han&a_$W4fCQ^h<|0s3$@q#BQ;>t^$mLC`fM?FuU?Pd$T_~@kTqePy6pyJGEcC z?`Au;Z@U6?JGXy(xP$w+o4d55yS1mgwy(Rlx4XE%d%4Fuxzqc%kAktgF0$u)t=F!; zBlKEJx}PVySno5Z!+Dz@Jcb)Q9uNDS`#bAC{OXE=y;HpOF1y87yz*YW#%Db7ZoJ2L z{O^9e$cMb|j=ag2yt1eK$*VlZyFACgJjlm9$OYg)VJHEGWA{+w0&u+x`wlJ?U ze^0TjEB5i4N3Z|70(khs>;AFR)47uKvd;s3)t@`GC&Ij6J-e%W*He4ed%e43z1BB7 z*nj=Jn?1ItJ-4sDypMg@vpw3E{oKPnxVL?@=ey2Byx#l#-iP+U6Z)hJK60z~r7!(I zLp>gIc*8R}-z$RE-+anXeB@KU@=m_xfBWUjJmy#a<`b{x|1Rj;Jj`=G>3crSm;UMd zuIRUX>Z88uxBll#{CdK~eKmK+{MmD8 z(4#e9E_xJd8D*9UA0kQk)N8e_2_uYMo6zmrx?#(&=B$7++*DyBb|QQN|BxyfMYv!g4{w%ft)PDXA<=k1P0+T=Kln;Pa%6 z_b|Lnsa*Whk1qeR1aM0MyBzRKWe6#-!7|M}6HNmtER8b@-CXlcWis4QLpkB=F-JU0 z%(KNE{p8ceKldCIM?&>16wyN!?GsQQ88!4#wT$viwIeyK%rm4sBl1Z0nxykW)6mPz z&d&bwFbhlkzFbw+R#P4G$~0x2l~%&u^dv$!b-ne$QmOQnwLr0h5mI4`b@UKo6OHsa zWfwJeS!kbimf7j3t?^o9h09jCYf;mzQcNpbEyy)9-4NY$H+?WOP=T%NRMxa~l|NQr zt(RUhYu%UM2Hixe&0PiNb=)~I^Ho!6t5uj`Z3T_i;YJ^RHsWI^URc|5p(NMRQU~6Y zy^l>J;9UZ&JaS(B#8jEyl<~b6)-na^mu55t&Xr)1*DRT5-}q?wVxT1++TuKau6QD$ zi(Wd>qk|q1EX%@e*VmjeQ&;D!OUBs~E?Z9MKR&?x+RNJXtr_i_Z^b$5whyM1WBwsm zW}4!s?Is%HyXnSQ@4WG@J4Q`6_N-*9J9WzKt~7yq;d+xV~-umvrr=F2c7HPm4a zd1$?1KrnQm^BnDnSVSWpk%+d#-R+_=hEGrf1~KS@F@|A=S{#E5qu@Y3GLZ=$bnz6Y z*u@vSn29iYv5Q{};}>_4#xs&pji+Fv8&82oG_Em?U=$-6^=QX9!cmW7ETb9an29!e z@r{E#<017pM?}_eu^y&)#Xe%731$pq3|M%>C`M5a zQj~EQyzHh(wRwtbjI@p=J*hZJ3euLI^QDH2X-HG*(wb&+rROx`6U1r8oZ_^nr{F0_ zeTq_}vh=1hO)5=~s#Bo`^`|m@0yXp@k6KWX0BFF19#&w@qL#4}6iT|W2DGfQ zGiX@{8c=->bAq08K^Z7m25n{{7s}|t3SfYR517FywRi&z>R<;o8*T@GMUeQWTSjHIk&;c#$A>K05LIM(S9YOO;y3y`e zw5kB8D_Be5)v3b21@`QMB}l-`a#X==$R(?k$x-dHn!OCvlGaqo z(LJ+n9XsbRvl-9bw6mF4nq)AZlo(Hhfd;(N1S@<%16)|a6Uf}sF>{vy5@79rT_9;3 zi*ogMDH%DU|_!Hay%q3c78@p(DqP$2o zZ&FQwhf%yC7{(~Z4>S>j7^tDRWuz{dU2sxi+xOA;4!2Iz+f+9zQq9QSGkDRvZ+RQM zi}jwQ6eKFeR~93qdKd*B>M`DNU%aG){y1ptTyO~5oi(ijrQL!>Z3Ag{uED65!R8>$ zSY`Ayue^Tsh`(9kSLgu?GAP3jjNxHSgmaL)E+b`MTy&!wJ;s%tF)~da+Ksby<3N5o zkgrXuJhf$`P$#4ccn&0g8l``_{ z1b=j$b9zWe&;84JKQlZ3{#C-m`N>h%KrO70_F7<>8eZ*U;RoL4Hn!Q!r?{o;KweNH zTm9*vA1KKoDD5&_qjR86HRn#yMG~Lb*_i-3t7V=EQV3cDMyaAW61{?4{JM)ohwQRn zyx5*{*V)7#e(YVm^w1S}(y6=t!nHLm{Y#gQwYwml_Rae7UUL2kxCOY_4^Do-%Nq~+ zz`44AfCe<^;T4#W0(9YSaiR*m(Q+m;=DR!oQu6=0{;mA%ui(s!1Jn--*v}JU0RBv& z;*u->$nWy@@28gQq&9D~#>&7@$96XG3MQ?kLQ_f{N*LR*rLu0k2*z!dwvc zA`Hc1aKc)R;cm_-et_qKK@aYrFN!U*nhglM$+D7;`H*i2g)pDq%Gx>&fpiQCop95z zEsQ?S1)`xAoT~30D)8h^l8CDE>@>M#?+O0*6r z(=gEqqcFj)PjxouB4`GUw3NRff@4N61ca~4UVV7xXKispuB|5 z&Mfd6sZky6u8cNs+h!*rnbC+$P}EQm)6i7))UW zaPHyaOCI!r4E_wu2#<~>kFUj?&jv`X>X2x*u#Nl9fctXNtb{CfK(3+A5AgPG59P7$ z+R+?Mst2IRs*K?fv1kQ8ff!~g5b+SQrt<9~5e&U>&V=$0_b?wsQV(JP4a}g*f*}#{ z;0Yp$;I48H2k8;9vJZ{Y&TdKTdXgt+=O$$*FG0^CJ?9ih5h6K9=Qffso$dD^3nOEW zs1j4Mgzv6y@ebr6-PY{`jzJF?p$Cks*@(~hVsA5t@c4ufCi}?)T|xUsOZ!UmG^1}d zR|kol5hro!`x=U=><_!gK+YD6H%a=u5nAb07l{D2vLwxXaFN zaTH?U{;I0z1F&Ep@F3pUasbif<>8UvA?tda}e4DYnE&)CvCmvi9Kiw8cz9<3@L zt;jN;Qs7t=61fvblPVv~jU<1d%G`~Cf2gtNcQ8 zB(Z=fs!XsPl+of*0F`RlX6hQIYS5-LtJv@e$>vBBzC4T!>T68;+6h{8@FpMnG zF0D{6;Wai974(W#K2h#31ydqd4I|C8P04BITrU>_lpKRZ!PEU$wpF&(6DM@04+)3|LW*KyA=&Q!O&^}R!h|=eKS{e(;e-0 z&*FAFk82$%_u{G{!88yAH5b4Nh&{p9z+#q|;;M7(vvXKbK+y?jG14MwaWSb?28zuw zC3G``@UpfQ2CNDkst9qpU|g?h_;{cms39^Zlihf+nq;+%O74N0@c#O+v=cL73eP|l zSPL(Ss4lh7cCe7&C~-xfbSO{NUyNK1I^qD(F~g42h4yd$ntPCVB(+>Id${$hU!-J zci(t(*v`vsgR*4r5Fv*(ZQoUPMArtuG=e0ObIO1tGjc%d{JO(8nJ(U3C=%Q7}D+p;T1w#?RSAS2g* z<&sIeD6AM&L}#b1c9>-^nRH@S+DLbft+_t!%Gvf9gH6nJ*~x-IN-<&an`ZYHl@RI5 z$b`KSg~xyg?|>Q}@UB8KI6r_$8Fa8xvXn{>Lmzl^+!LV77HkFDYXKTHMT=$gl9|Oy z$f5y=&G$G3P*c$>nZ=iJyVI64=?Qv34G8g-vZ_J;wTuTi_57T86c&$)tSAQdp{rz7 zQ{|Tan$xi+b%^gaxx6=s$(V=_Pn((`J;C;;3wi@pbD+mov_eNFW%5{si9T(BE%1|P z5tEM#GwABrBcnRSNO;AVt&A=qDO)wAZ|!%r+OpKOnS5(c^&qr_DH*4?dav)T!S+Lq zC`1`rcBFCOrZSj07Np*iD)~^!LUt?Bcgdb8GVzfBfNPqbQgLhA@`SjHq+peXv`A;k zm-)J2&DWIMaTol0uhW;EBCXS?bV?Ig$5g@kj@qC5lGKv5>BMxx{xgHsw42GvP3>5N zU(Jt~&n1(uvTRNszVQc^*2Ad5emUz;e^LIM@>Z<}^@eenjTy3DYsXPPAyN&JQm2bo z`3)U;I=jW~yT6hj!V(RL)ScfzA2@&m#4eaWwx&s%2gojW(OQqlnEY-X! zdZL5)6o7Sh7J8u>lC>S^^n!?4Y4L(J(!q7=s_pojv-+}ismYFJsd_S!5tQ8PJ*71gc>oRdlC3DBUJ_q&+;^|SLEm2-*|`hXgu^Qssb(Xh-H zL0fzWTMus>;gX93>X}Fv5QgK~jK5HB&u_VK+K@b(uW$SsHZNseJeqeHnhDB{ubF}* z@&sJ2r*L)_Y1@t@oUwK`vb4#Zk^ZoZ%-WfhHsWacxPejGh|pY*aFDLHpG%Q7ckDDx z6LgK5pgVxBS$2)Z3J-v|aldz_D^TxNIf--gkfcCJT}cPM!QD_&o+FxwzxZ*TZCCy6 z)ZhCWYBb%{2MuzxmPy@Ka~d7L41mYDjxg{F>dgbMV624tbA|mq&y$8pQK?6KbDDaB zHwSg6dNH9rw(rU#(cH0id$~=4Tm5RoPjXz#RfPZ8!U6rVD0yq2H%rl-bmCgaeu=gb);S`TMc*2Oz z&L>l``O(8GoU6&*w|iUXcb<8T@v}@ky0dME7qXM1;R6Pi@~)xSQk?*E+~&M-3@pPN zFt)yuT(fW8qAyiN0o>A|9#g|;ebLPrDq|lRfefNj;RP~Zjd<0!6LYEChl{?AFZ8WK z5so7=bm&;-e3q)qsCAtc<}bVlWZ;GFIT+A8C0jC`x4P$F(sQu3#6w4uzg#cpm53H~ zSbZ`JDgNST{FM7B(D;fI3axLc!5_g_nDcv*1inXKU*Yo?(*+jOaq2*)wlcz%?fO9A z5dJ6yn3dazE<1nzSXEq_q4|N59q);$?`JlfZTqg)JZBBFj$@{yc-a>qVi+s- zLlYJ~qd3&d#E{{sYYiJdjOY;Ju87x8WxBXAQ$~gyGfj-R>tjcTCL@l-sFC8zh95az zG#N4_%$723qHM`BQ#~?w^k6~bso0oN zyZ4z>r)*>;``bnDPalAz7U@E&a@5Zm<}-z76qZ^)h8e3BV-&SdJzX+A`SK!EkyIU~ z7digvc!@mS3yv<|<@)IGm*bCW-}(BF#C);>3>u(;#xQ2oatsXAaPS^~ey#M>dIU(o z7Hy|kSlcPN+2)FFs$6K>6>>4K+KDF0bxj#@*(F0BHuTjHV9VuF*l9L~mI+}z2*`y7 zwJ764f}C)%!Y7welp|)EopzdMPA(_fXr@Uy+Lfeba^hUCrTCU_U=j!Bm}L4!9B^l3 z(*7Hoy+zZ-gX~G=6iRsLBTp~`{eVUcdaPgyF$}rz-=I3`G?jC3LRAt@Hz6t~RWrdE zQ-q0D>L_Y9nfIQik9O*lDUNl4#t%ke@y087JTWCr5^XBdAYcj#<|)RNX)AAPZn>qG za^ag(jhT%L%Gq#g~$2ahw^89CCgo*ViL8FvQS>F~eA)i3VJZ{_+H% zDkXZ#Fut*Q@0ene8FW^wq3b2DbgiftjBlO5(6kXjO-v6fG^+_XO>8HRGBWgl^Iw4} ziEPwkUzBaR<#Ma7xZh40uG-#iYi_!9ts9qGx~-L!-e;sW8(D4f%{Omio)W9!JwG9i zXxF$vj0x1}10)&*nDK!IefD7J=8%${^T|7TTH2&2f8LZvr#Wot>4K3SI^z<1-l)bF zQ40E@;x!~iV==@4nNhVMgog>VXTmdBwDP@G@@%PfA>huN#T8s<=xV(SEXtJ!uy6@$ zEJG%6{YEWg5Tr@7ub8sXUt>3PS!anc!~;mvhLr7Oj0ZLCGqZ@MA!ypEMi(-g?8D?OH!9-vNTGDcswv7H|D0BJBUDnbJ#W2Gx zf7#2**^(K>xMVJwAp&38G6RFm048a^~Cm~n~Oa7wz{Y#0CojyBkJaYx+~@GcQe!6=tj4^j16ge&8yt?x|hA| zb#GY7yIX9m6|HJzBz_&a-~Hm1u5zubMKemu#qJifuchsOAv@T+!nMJ{4eWv)T-lZ` z_P?aXt8QKE*UIJ=w~h61hCeLZ%~F=cn?-Sn{zGfw2e;V6Exzo9;mYC;)7Z2c#xaRS zyy4kK*RH_@@P7fE(Y#_Zz64HkbJJ^BgT3g%+FdD(^Nib8G@~^gT?tRR(~E}ms8{Xb zRG<36h*q*}g^Wofdw8tNeRF&(ed##Q_q!qWHD0M4U1D=N4`L1_u?4$q0+2VmX1;Zs z+1u%Am-yOkhOwKk9o#a{cgta=^L^|7tYP)ZN-SD1tsW(mUdE5Kl z^2Rr>?;Y=b>l@Sg?l-{wEpSWoJKzW>c)Mk5>QEne_7?g@+1;+LyByXm zbGgbNw=&2(9$qk)T+I~SHp*4b@|C~Y&Cd?Ex$RtTJhOGq_H}V;A8z9}8~ootFL=Fy zK6IfUT;WI`xYC23@TC{M=}b?0)SZ5GPp@~{a78m?NxJPq`+A}=2m5!AUF@;{8ob3W zxw5U>@`|_J?1*mKTsDL6@dZibA|3`iiIDzjKcIRhzdAE1!2T5tQdHi>O#fN_& zSbri|f+2Wjq+(k!-KmX*1}3GzfvxWp-fKdD4Y!7U+T!ID{0a zgEU8Td&hwoc!X)zWB#iZTQc@sQW%9)2!&Sogjl$9RhWgO#f46&g;xlMUKoQ@7=~Ra zhG=+(YWRgh*oJ1Pad5VP&L)QmIEST|T^x6MKj?;hNQ811gg2Lg?01BdgjSTZUTm0% zWVnTCsEB1ahL6~Yi)e<9$cSq=iI8ZCl}L%0C|Z5!g3t$hb69q|wsxiXdZb8wsrZ8d z=!c)kdgbSXgy>dEXmfi9Uz?bToEV9h$cwosiN4s0y{L)8_>051i^Ld=yy%K@2Yqsw zhYT2U(inP)RfljGgv|Jg|L1amxP-R2ggD26h**r|sEo;Yj>wpfy10(Oh>q-djPGcS z@(5zt_;${C{)){OhxmAXCWm%pcWfetjoMg`uV{q(MT<$8XH>9X7H5v?*p3egj}RG; z<>-zRd65#Ck@M(~??{j>7mDEJfYm69&=_TR=zVDiegnCZMA(fQ2#yJfemUoU6&aBm zX^|RPlN8C37 zaoAa&+-aWZxtZt5naH`G#i@hNIeTrDm96NW_L-jed7t`;o&A`f!g-sWgoNO^f#LX) zRN$ZcnV<-|pbC1L$jP8-xpD?Mi$|DuD6fTKE^qi4XQz@Vc&3Zy)G2Eah0MtY=3nxy_p zx};3nq)z&zP#UFD+N9`$E?hLFSgNEpnx$OYrEjsNKN>G$IwoFPre=DkXqu*Kx~5rb zrEGepTl%JQx+PmWrgrKZbDF1mx~F{Fr+)gUQ5vU!%B5AxB}@|+WuhkWqNrptsE+!m zkQ%9I>ZX#)rGi?iZ8|`Q3Kxt@97CffiW;hf^DgajE~a{=HefVxaWt#is&B!nuj;Bc z0IRbqtF(HnwwkN4x~sLytGMc`y4tJ4TBxW>tf_jc$6Bn&`m4gqtj-#&&kC&4+N{B9 ztj3C}0%WbrDy!P6tlpZe;M%R=TBDnasc339tzj!ebEiaOuI~D-@EWi38vdw<8m-hi zt@fI)&?>9^x*ByFLGj|LqzWdvGOq@Eun4QC*Gj1gORf#8q)6i$iu;vo#B|IJ>ht z3$7x2uR!Z1H`}vATeLZAv^=Y-Bg?BNYdr*nv_yNfQk%3>Yoz~rv7|aQL8B#2+qGW% zwIvc45sR=U3$`b+E?&|b0z0r}vaaoFws0G_20OMLTeeNhuo4R!cIvjaQnj=SwSZf- zflIZ78@1mmw1S(ssQR~xYq*X(xR0B&h+DXLn?;9Pt&I!0#JVn({tLF7JF#rrK%q+< z1uM6vd%BQ{x1DRSf;zd8OSzfrw@7-m@3OXh8@fc3v8cPdyz8f{o3J)Yw;y)Ub@uiLXAyRG2+ zz2Td_;;X&fD!FqZyy#oL>ie^9inehpzh4TvYKyVAdn?Nuzyh45!mGdVnj(TqzV+L_ z>)XJcJGOO7y;y6#xH7;Ne8E!Mya)Td`MbY*+qV5X!N`iiBwWHtYQWB0t{R-Mx?4B= z3$Xti!W7)XJj=MSd&A|cxv`7G$>);!#M20C&I); zEW}@;rA*@`5`4W`%d)+ps3zRSUYxBbTfC^tu(W%;0Q|*hT*7XO!t$yv6DzC@OR1{s z#E4qGVFEP0u^KjPzD3-}QXIvAyuI@a#YTL&e@w`JJgh$ zEX%sQ%e>snzWmF;9L&Nz%*0&G#(d1koXpC+%*_1DFT%^uyvots%+w6b)6Bu{8p^_3 z&D`A0-u%tr9M0lA&g5Lq=6ue>Y`F;=%1rygW_5*BIK9Mlfi$`s$%mZCa6GQM zvbq(G$8Q_d8J*Nhz0?K0$zsa41kKb^J=I9M#%9YaNJF;=UAtVZ$z#H`b#cl+J=Ug7 z)`)D@VqMm1eb#H8)@)tR^}MH6inoNsR|G&gg@o6M^hlCKi;yHqeN9P$ok)CD*mZr_ zx|Y}?W!Q?%*o%$WkKNdi?bwt(*_JKYnEoBvnqAqM&DooM*`M9npzYbDJ=&%%+Nd4c zs$JTt&DyIC*@T2rxi;IhUE8*O+qhjwWHwfIZB~B$+rZ6t8TEpwg;B=sSRjSmN4DI@ zo!rjN+{)eD(EZ%fUER@r-PDcU)4ko+o!#Ee-P+yV;Qig=UEbk+-sFwmmfQAy-_9rBo)wtKncNsfpuzpyi}cvLU7Lwjn-O>5DvIEVJ>Lp`iVPm% z3qIixPT>!J;SQeR2Cm@=&fyKd;UM1OA^zbaUg9Kv;u2orDvseJp5iQS;x6vtF|Oa} zWnSk+aX6miI=5s1I zoZg3m{^?5gq2zbw-?@PYspp%X>YcvosxImHO@si*Uh{e8>Sv*Y*y^mF>$vXcpx*03 zIO+l_d*WGVdAIAje(c7s<*xqZE_mWBXQHQG>u7#+$X@NqZtZ{G>tF7MqYmJIX`*^p UpV)rwjqW}N^ literal 0 HcmV?d00001 diff --git a/doc/html/graphics/corner1.gif b/doc/html/graphics/corner1.gif new file mode 100644 index 0000000000000000000000000000000000000000..000d97c1ce196c39de25baa723b5a2b99b01d70d GIT binary patch literal 1645 zcmV-z29o(lNk%v~VUq!K0r3C;XPfKD$jJZy{{R30EC2ui0Fwc80RRI2jE||y?GK}z zwAzca-n{z{hT=$;=82~2%C_zc$MQ_q_KoNI&iDQg3<`(DqVb4KDwoWr^9hYgr_`$T zip^@b+^+Wv4vWX+viXcotJmzd`wfrF=k&V$j?e4&{J#GW7$`VMSZEj_kf^xG*y#8O z87VnQS!sERnW?$S+3ESYcm_I3T55WVnyR`ADJpOXo08}nTU#<~hHJa~p-bk=8=L_w zMl5_hVGO2>+}yzI1?@b2AkAe>?ToFpoqgPm1@6r&ZdE>BdrqZ}e#kEM-cA?~MK2#{ z@05SD<}B8c@yRvs7vo)eOUDC&}nh^ zj`=(In&N$vFMmEf`Z3utv|pcW`;qtX5y_8Rf9U-p^#1cZ=uZKF{w*M&1O*O=z=04b zh+qH={3dg9BQ~0EYQ#r~rrXd6*!D5+WsH5Fny=q5&z2x8jQ5wOHbaR>k;( zi`>B|BW~m6xDJhl@puJ}KrZHE4>n#W&n{hw(sT|Z*ub*%j~@zsH?Ag^@^bDZT$9Y z!N3Fu_^)#Zlbi3t1t**?#Aq7q@PZPvTd}<0W~>3l9A|hjb|G)+@yDMwZ1Mvor(Dg* z)ww+7$}BqwGoCZ=TeH76dh+OsQO(h z;GPPOY|a-1EF0mKDqgMO5BuD);}szO-WubJT23hD=1Pt*#KJ@`s*R~9J=Oy+O8+=cj_)D?{E6PCh!xtZlCO~$8J2$w0kamn9Y0nJjujc zoILf&8y~%u*~dJ+%H1QlJ(S@$IlhwR4|zV2>GQaLj_u3%{)q8QIDdonga3W$)qB4@ zfFKHSh(s)+5JzCd zBr4H}D3RL|pLj$OKyiviY$E;-Z9v5(A~B0uv?2~az{MnPF^o|3;tx+i#wtoNjZZYA z>S(~mA&xPQOeBdD=?H*1;!%!vykZUZsK-49(T(Z(BOU`ONJ6p)Qh;2eAo=)_JJJ!6 zjf|up;dn?#K5~$K{Gtac34%>RQX`U#BPBCwNmsC9m8@)~D_;rARjM+Uw5+8qZ;4A) z1O${|6eTBnm;qjX(wBJzW-w71N@5!Gn3L4xCYOl;VRnF+#e`-Bq{#tlTGIm9+<-Q> zNr7%^;G5u-fH;{c%5qNNoY7RKIwQc&3y|}j4u~f=-AT`SBD0si%;y8_c};x!a{&Mi zr$7gqfP${`pa^ZKLrfnE(TGZPq7<#DMK6lcjB0eF9POw_KMK;2igctTEvZRQiqe#- rbfqk9sY_o9)0oP1rZlaoO>c_Roa%I^JngAZe+tx~3U#RaD*ymHeV#=! literal 0 HcmV?d00001 diff --git a/doc/html/graphics/corner2.gif b/doc/html/graphics/corner2.gif new file mode 100644 index 0000000000000000000000000000000000000000..cc251a17ca821a75308ed8d25d56517f44ecdd7d GIT binary patch literal 2616 zcmV-83di+FNk%v~VV41Y0r3C;XPfKD$jJZy{{R30EC2ui0G9!M0RRI2jE||y?GK}z zwAzca-n{z{hT=$;=82~2%C_zc$MQ_q_KoNI&iDQg3<`(DqVb4KDwoWr^9hYgr_`$T zip^@b+^+Wv4vWX+viXcotJmzd`wfrF=k&V$j?e4&{J#GW7$`VMSZH{Nn5ekO*y#8O z87VnQS!sERnW?$S+3EQS8Y((UT55WVnyR|W+UoiW8!J0YTWfoZo2$Fa+w1!a94tKC zAz*xroUFXe-0b`e9W6agU2T1hovppijl9+k9xgskUT%Jl-ux{<3}?LF{`RgmAJ0~g zhHsyyZ`Qx>j~zXM0QnKjcd%eUcnT3RY`AbB#54cMRGjGLq8R>-7`Jc)^RXkAkQoz- zEcx){7m{6As+8i=qsfsx`uPN!+(G=9+a&cZgjid-JyF3m30n zAb_O`9_*tq5ygm2Fur=Y@s7tqC`%4unQP?BI5H>R%-M$L9-~8RC_Ndp=^3bXv|e4| zb!XMEVaQ%fyS9tlqI2tJ!MjHA-wcMc_Dwv6@w&*9pI9CPy7K_iUsO+i{crQ>B(ekF z&RvA}6|w=CKaW1W`t|JFyMGTqzWn+0>)XGNKY#u4D*npr{|{h*0uD%Efd+7+~ zlD2IE%)aI91kko;Ek)fT@U2?mN-!>a*wQTdlUh&H!>$ zA~!%X045Km@qIIM5%bM5)oh>6H}PEG2(NDXa&aEF%;M0M7QH~uA}GDI$G8DapU_Y{ z%CrJbhj2C4Qujvnd{%cYXx0gA4FcJRnvDS3AE;gS*TNm0E!S}K$@T$mdvG`2a?`MP z2YvVX_iFd=50XW94JmFZz0Nd32_4?E33ou8#8QmfH^L$}%9`Bk#AzZrkiO*Dk!3xW`*}+R0>zWib0elQTAoD5_N0=~e2dO~0+6zBp5Hp+pdfM5$G7=Z&Nuz%nAU$g=^zfV|@ z1sJ3h1xGQ$6_oG+8hjuJ$-};?fv|EYd|`iLD7G2uu7pbhr0fIk$`2}O}Y z6|B$!Ev%po734v3>5z6#9OC{0iZtns~-KCi0Gp98e=QnMO#`Pm&@Gq>2W4uR^x(kmf?=zEmkgR>CWkii{*9x9G_7 ziSluOoTMpd1jo?9GKaFvS1?<*J5S;gl#i_CC~sNJez~$>!;E7z4>rw*Ra2PPjF=tg zh(~B<5|Omzq%D=%&59ipfXNilC&}4Nb3PND<80+O4H-^)wvme$RHOb#=?O}nz>>@A zWhwbdLVs2Oll#o2{QhMer? z^p`uz=Eb&&%zDl;p5W}HJC_O1ipuk%68)${eF#w_l5`U$B>_s&rP7SDlt}CRU^@f! zPJ3>$rsuqAIx}|9Rp!&GGBu`4O9oSRc2$~LjpbIMic_hUldALN>O^z;P>V)XpFX8% zTz5KGx7HP|K$WXdd+JM&Dp8~j9I7UYDmu3El&*pODG`I3MZg}^u~&rb7bUw=!Sa!? z6Etil5F6H)KJ}=I0PSeaYE!gcwPRnES!kuW+LKKcpQ$BnB20T$t=5*al)&w7iJ4p8 zPQtfUrEPI-{)-6Ww$-@HMeZS#yI95MRkdTqW?6yzTfdfcsY_~YVyXL9wbGQi(FN~b z#j8{4{*|$lwQFDTx?a6D*1eC_?q%7VS;}_NvTMYwQZ-vi;j%EP+Xe7I1sTLn)(LjDBvwsmUW>ZZq(<*u zsm*Eg&bQQpR=2C!oosr8+TP6uH>RPTsbXvM*mrLCOw(I%JLkC&=w5fi`7CcGyZgQH zX7#J9t?y;?JKGm$G`A`3?Q;8D)c`M*z(qUlhkHEZ*WUQIJHBm}ciZJ6hk3X^F6;h~ zzj)-f_BFwsn({bH{NV3axyA8~@rg6J;^{{E%9UYUXOHK(+kWO!zxwKT4{W{5x%R-1dfa`l`{K8l_^;o*@|S-6 zet-V?)UUqvuaEugYk&LP@4olH5B~6rfBfVxzxmIP{`9MV{p@eQ``-`$_#4ZA{`9ZE a{qK+e{Of=J{O`a2{||rxD1d%Y002ApCT9Ww literal 0 HcmV?d00001 diff --git a/doc/html/graphics/email_address.png b/doc/html/graphics/email_address.png new file mode 100644 index 0000000000000000000000000000000000000000..5df1d08c9d3873a8e975b908c8f7de5d33e581f8 GIT binary patch literal 893 zcmV-@1A_dCP)~19ib+WC-VVoE+2QS7&3KWE-KuQE8lt6|^$*76EZ9)Mw6ohO6XhaiY{>6WNfr<4CR&Zh)y zKN|#yhJpnUvF+HbykEwmmpLUfEUWoQ4W$$6rwR(d>H# z#0l7zt|2r$8~Ajq7*#cEqxoP8Cr-y_FV5Yrx74aJ;e+wo72Vkw4`^G5y=~ON-ZJ`6O*Z!d^&39lDaO9Y_(2?Um>JbRW T^3cJy00000NkvXXu0mjf7~Ghi literal 0 HcmV?d00001 diff --git a/doc/html/graphics/line1.gif b/doc/html/graphics/line1.gif new file mode 100644 index 0000000000000000000000000000000000000000..52f5f24d495ec49f77df9b70c4820241d2b445b0 GIT binary patch literal 302 zcmV+}0nz?PNk%v~VNwGF0HFW?0002stN>tSVEFt1EC2ui08#@300091gdLfO8VuZH z5?1PL#!7d-fYWi2oB5%kIyR}h!fkZQUQE9^UfSY4>+OQIA@KN1vXD!quL*rhjZSLR zIu&Y*TV0pO4SU77ESWe?gVpG@yA5ZW*>bGCE6585e7-*4=l2&l@V6IeNSKH?$f&2- z*taMdDfs9JhYI@($~sj9i^8v9BMduqF@+sn%P>su?F z8*Ds$T#US|+>HA?8x0CQEiDVmOntq5Yu#N9&JCRHJ?>mitevd=EuN0P4o@E5UT@BR zFMm#-&;RZp58ym^0SOMY_s`%yh4>O8EcozXKZcqlI-D4BVa5oC5HWhZ=&%3)I|vbs AVE_OC literal 0 HcmV?d00001 diff --git a/doc/html/graphics/magic_OGL_sm.gif b/doc/html/graphics/magic_OGL_sm.gif new file mode 100644 index 0000000000000000000000000000000000000000..a4ddff73722e16c0f1c5d2029da7b8db863163cd GIT binary patch literal 8078 zcmb7oF#cp?oMeISUMz@=l9%u z|ABix^I~3{IdkU4yqJ-dlM&!I>H(&KTL3^oMSB6leen_xpX3b@5h)4&Thdo}q_n)G z^ulC>APN#3YF2g{Zkl%#EVT6WA82{$>Dd@a*%_F)82<}aekOWO=6C!b-*U51ad1#` zaM4k6adGj`(ecs}2(plh>*!0GNlFQ7$tWr+$XY8Z>MDORRpHWC{bHi3ZU05dSY66a zUB>AfhuOC;c3PrFhGK?>nieJ|CZ=E^^XOUgv{MT?IcpgjdqsW+FqNY+g`*aiXL+S( zv!z%5j&EaI&}dMwV@-5iT699@&(zePrSRVgDTxsiiNDH{ex)SG%%|k`r~WUR(`=?P z3P!R_+Ow)Evdb%>1u$qWG$*4hr+y5NMG%fF8K<&f$W`p^GtqM=sPhcK!2qs_foBlV2|&^T8E=3H0|0@99c+VR0ZgL* zQsAr)z)%K=i2#&Y2mrYSu$}>lPT(E_1l$6s&%hUN6qG9fcn1DcU;_Tb4-^0Z1Aqzu z5dG%`02}}y7I-ECIza%f1q9{t7I=OJIy=4XAAueafJO#LNC09eJCg@0m&*T_hXZl| z{Z|7J%}$~~F8`l4(1iw!{Ga)p(Sb|gpC;sos|*Gzk%Yv5J^uf|^1t-|-30)I1irVC zf~%n2{L$+KTCmu^-C>wI?w0R<;=ap-QwsZ1$kptm$G%re>$Bi8>P=?G zmd`)v&wZ1`tmYYA{8ec*o8Idl{hp9PE}5MYwH#7=s05YryP=aO-kB|dV7^z94`z(6 zH0*x$bNH+Ie67jEm$fwKV~t|_pfn8~Ue>k1$QOreBbw}al6I)rB&&^8ekl9VNOJi+3%Q=Xwy+ej3C!*~!^DP9wz)#9SH@f^2w$ zzJND<{>gz2{3)#7QU~*TfO5m=xInpYJ`4{+L(q%`v?C~9K(->@OQmf6e3*i~k9s0DzuorZjw#BC6QD1qjSxdD!1Ny5iDY7O*~#Z9slQ`CkyviW znOilRCh1kcpegKeqGj)`f@fQqIn`Ffwq5mU0qp(ux?eT-S&4(?O`iu~4p8 zo<%v4@6!$fgl{wn-0?ruX?x6O{-N?(DCdvYdo){CeK_!JnJV;v=rJd#hS8hL6^ta-R8D>Q6tAGasBqd1t(Y&p8+67AReV z9+9d|i|&`@ZZFMNY@3$BwPSY^3m2ZrtIh^gf`cBy9!RC~LThedJg_faF zzW4i4f7+|@)xe0}mCOMp(|yQ>n8%z+0y6H<@L$g>GAX7jvn;W+diV#iboKD@_U3!^^}*_XbtHC8_O25WUkZ#Sv- z(Jv+Qb#jE)9+yePsCiCtCt5SEP~SAcFgQ#Ttv3-(4Arf={unek@37ebk*W||Z!C2v z3U#0as!)JK@uijz$7UeeG65PQDhFVK@YbeQxgxEr7CRzL4xL@ACwGYogFfmtbbU&7S8cb9f4&Ul1H))f1*9U`gUutwB(03Y< z0vJlJQQ>KM*p#1&`h@wS^-+a)+p)I5Y*IBYCDFTWR1FnmlYf&!n+n+6iWOug-_f?= z6mlGL$kWkJB{fn6aU~7~nF`gWj++#6yJ->V%Q)doMw{_v7c1&FOvf2W&{H;fjM=iy zWK6T{^A0+Mx?D(PG*g(d`@JOeSayn$N9N}V%nhm7vL&RUSDT3s9je%iT|gh`ilinE z$3tbD@DC`^L{2;u3{Vqtdw9&mT4PoH@P6lf2M#3MNvGmlX3{skO=KnEQ%P(*nIo%c ze3gP~k=k`xZ*li9e#5?!gwNztCl-P?43(fQSJ|z7{%_h30uyVl3b=8t)DxLzikWK* zZ`uw&Ig*Xyv~89eKEcI)Vrfv}Xh2PTtoYrA0?3-K%kAb&wT-mDg~jBQd|NXWsg<87 zcXUa%1eFlzmsFDw<&8>zMX?h(v*&LdnQ#U;Iax$ zU};Y+^XA7E99!aBYmdkf*YcepkIV!WFemUD>f(7BEL}X*=jfA4%f?QuQV*9?FW6Gj zc*8}+Ygi$}uXKyOD;nGA*WgJ1q{)zNut(}@KUPBXgJXqDo{k<|`?h)UX+HVJDdeUl znNag>tk?dEKI*?pEGC_${#a8e{-b9vggsK zjgMWL9mEx<{)i))cS+|KA!uh|q9VqCkm@I$8KW?zwyoDxir|)k0t_Nzh+$ip}^Cydmxwm7m*Q-zipZ-BgGiuj@udUW8P7 zMt{!^K4{#f!>sab?4?E?=i+2DeHZA}Wc!*lCD6QyOA31%oV{4*w#7*vGqFJK2>lx- zDpA{vWmmzK!5_W*?1AU2TS1UgT!JmX@dH6$ z!=+Yqf8o);i?sF*KHe&|%ziw#hu-&yhN}KCE5c7xD<&-GjdQR8M#r+{Q&!%FH{~aS zqH$esg*gI8)~NIUuGsK>m+mkvul6}gCj?ETbg(VNjy|0n<6N+?dMNECG;6JVnWrhb$KU8WZrOI3gZ6Z!h~K(6$QDv8 zPWkt%tnh4N%vnux`w1t%@WdROQ!)M%Ttv3}rLsRNTZSR3@~CIqM#lM_qW`I-A zd$oai^mywxyYGB9<@-g}!!OWx?~ilGg6C|q-))>9!3iT7%zqbRv=~Sa z3FQQZnuLeGW()!6$o>%2z6NukY{u%W5A#e57jXAbgc@|urShLFx9*D zM!p89#rA!E4!VCi^8jGJISdhj;hyJ>9#6^P@WzPbMn9m)Io86dP1ECA76k_sa3<+> zcJ7&S=l9yeBdy3e4;Jvt-5+A^`NaXVi7_1iE;x}fP**mP0_LVs6|OxQu65=c2ae1Q z_Zw%7#IpEL*7syEqSwNAq{)AnF|y~Dfq3!fCio}ef#399P#Z&(ty>JtJSu?^LpRoM z6!eSpHh@wfT=Q+T7GnqvEQC1)gZCit9vmvj7>gno`>801D<#30c<~!Sp(<^adtpcTFe8OUJS$>!|r3 zas(MYOd0f=83P^}u+)s<=8S=Vj+BGx^M72tnc|CNWO_X^M^iJGk76 z7(#!)D>gz2<)r06UHAvk(ijqi8J-p!VAE%xH*;N*a$gra{1g1K@4@}hY=BFWMJOX< z0kzp7%?xQYh8Jh`q-K43@d-c8c=E=EaM^e(&-mjv;Zd0!Dta3+66xAd;rLMKH&8s? za&i%gN%s)+V;VZR&{*-Cc-??yI$xgr3+qY}lag=NTvq1F^WWtzO}0IJ%2R!q?uA&F zp>h(Ifo7H&-^?0rEJ_CQO$yCVxeK_M3mWNj4I4P6meb#w=lczC$}Q)r=8O0@6nyn8 z45qj6+AFlTD)4A1w6rp}#rp0NY5mz1nonW_PD5wGDpG*wBQ+umGD$2;U5hBcSsJ<) zL|_$YrI|%|iqj7N>2NhMWiDdZ&fyd)ZZMPNiOjR4E#YX%%URC5xy<7qmU$tc-;oL( zY=HJ2Lh0yj-U#Kq(#{!dFnQaOgP6}5Pb#H)kqeu*lR+zlFc$8=C>ZPTnLVJlRC9#|La^;&23Pzovt`q<9W zs>!_cDORef9;yi**p`Ad%|0j+eXQ=~(K2*EH=IP)uwlRG`JlnMqEq;xwpXK;X9TSu zLut}PtJk?k+EgWUu7>5I#?Zgk#k5vFy_R3NR*qchq)%mRrghK8A!=F(NIZ&XcBzOqbf4XamUq)wA#YjfI4v&`q3BWKM@ zje4u7`epUzB!$L|sHRedhLj_nBx1GbC~eEAuNOpWcBS?=+Of$|3$~yL)rC1CqU6f<<`lT-1#uoLD$oH z_OT0RwF^+}f-5-Qr@zOF&cyTXew&erUWQIlhVIzaEeu7!)ByPUK>R!gJSLxbgHf)C zdni}CWehR6M0&p&qO-4dvw8OlKK2Ml_wwWPh?k*@;`E7&^hr_l$z=3_+xkAY^-+)Z zN*{L%h!|A#f%MR2m^Sq*ocj%8`w=dE{JOn7BE9mfeP(67iqQk+IQ`bgy|xtnHe~~j zqrEDl18lm3@5}msne@l(^lMInk-Dq>ml%WcG`*Z61BN1lc4e^ORagYYU~C&K?igk| z3j4L%ZPwNIE_zViyPy8}v+tu4R0QTA(ii&*E_(vBSCnYc98<592*?emNHPUB-*=o@ zbmACv5j4DNc0d--BCoT_F0-|y4b?JdpO$77aiM~=P{@g+?)Pc*^BMYcUPjtd zTp`pJcqz%UO;g%DMWjuGP>KE8d|S)B6|JpQFmLlVnwZiIGjoxAOR<}6i3Gg3NXWVX zYe9NGC$QXvJg6l8Y$X*qU` zGhV6v_mfeo=Tau?a;eO6N$*m2W?s~Cena`vqvan0k`j;hWr@E+ZkNk!%ir@$7Wqm{ zLNZqaelGey6%Qj%@}z`H%1RdWGg%W@ZA{v8&Gbs&!gCr+O1H}AH+|-Ru$J}8EcBJ+ z3^1?iCwv~&o<+7AFOro{-^P(B z{rJ7@(y@>9Lhezc>`3+Q2afOgA}N)9NrJKtto08FP!2?q2eB2~ZZUf^*oR5V+wm17 zWq~LeF(}}!LtpPM9u9cEK0I$7ttbmF3ZR$ap%b3LtEi3$4N>d#j~aZBnzD{sI*!`b zkJ{Ldy4K-6<8UR_;{pBS-f?&r65gSF1c4qY6kyI~d^a+N&nu&qWWjsvP*o;R){!Ue z$dfHG#Ew2<&lj;ph1jP;9a26Xv^zc-KiNhct%+goQk~3nxI{ag6lR?ib(|ddBH&bK z=-G%i{j=S1#0e5{mUVm)bGC*!o-Sat0CGu=& z{0xRTqdPshQAXU^o!@7j=Xaa~ofmwkCnI=A{GFF7h8Mjt7fJ-D{2LeB$cr31YA!!G zQvXtf{Q}b-LA!Cafw=6!yOOfMlx9cBsAOJMpUSCRQuj{|;>u4r@$P(*)dZW-VXgWr%o$;^A6dnk#29JutFz z#~Eitk$&Ad%jQb9LB*Hher8-9EKe9>)*LAfq%6q5B(i{tB5j$DG-3g3j~ zka;$0BDmgIztmgsnX)K_*P^e$>y&D(<#4;c$LE&RhVay8tie8v?m(yU$7W%%!R`Gb z=jkCUeq14QoX5#8pKNwj+Z^dPW=@K7vmjwtOQK@D*^Wm%cUaULL1?*fQmfwM1uK)7wezJt+)0gufy^KUc5)c z_(~TqZ=ImTyQb(g#=o}eAVcp*TTz6K|0#xPmvMSR<()amS(OYcgiZ9CL}PYJhV=7S z4MAEAHQ~HH#pBlOo^AD!cI4H?2pz7HihzcWDesi*OosXwQ}G1$Zj(2)D)f(zxQ?{H zTCU>NpN)yiAnLy`-i(=^=GPaZef1({Alz`A%(dD$0|SzhnQsCN6!fO+)Y~cN7kRS1 zlUCz}%D6WPa^4g6=>1F3RDXYh%iY9JNswb4_1QrJ4c8=A@;kZBCap;vN^!!byn_Cb zNusGyoL|xF}p!kH2>wY%7j>T&wXBN%j5!`uVL?keNL}D!v3@nQE4j8AEDS ztmK;pFDlOx+)evFa-Ln@sc*A{kEac>w)cNOl;Tyq9NHUYX?uZz*rk8E(BD z|6#^-d+cOny#YAuOZD#w@=JFrk=y3{OzM7-C*VqsXu6cqvLEB#Z?kL@-)}XMx?1OP z$T%c+F~ag{j8{d?!mIGp%G+GJD|Kl66X=Tz5Dnrm>*nXUVqPu@YWY5n=T zX*TU)au$5jtBu``EX1+fAXQw#AKt75{RHZWmB~mK-II4h5~N|P2?)xE&HC(YuX~m8 zv^`hi^)jPbbN{zh7uV#UQIuSz75s6KHh;QAHfb#1tz=!p86-C~RDB&_+4HaVc!@|W z^uu*B`^boemvF}btYEak$gPGrB@W-)Rzn;kM((1e=pez5ul{*9q-%IcV2VE);Wxe{PVUB zr9QJ$GFJ%c1?L^Lfl9ezj!YELgy4|!Y?Hw| zo6LY@gnn3J%DRj=`zHU~wTaU|j zl2dj+@EChW`Ql#|#K3>sEcdyl7N;Rl?p)^O(3cmEIap8o?7~Bes$0^(_e7>5Yk1MT z@v1UcM2dyxjCt+Gxjxj_70PPwRH02m^IQ9hK50be80KEF_IXEeit;w4=2jH)&sj=+ z)gG`Ysg>m}-cv1S{E```o-V8h|D1p^9uiYax4T25;bbuvWX78Z(IX*cPy3SuCCq=+ znxZC@_@;MHRPI&~FTPZa9BjaH&JBtx#XJ<^3$~i8kT*5{G)ntsN917VvhP)mgc2|#95DK*l~luArXXJ*V$uS<(r)f6|n zv?ZGx$^MbJkR$`LGy zBL(Vxb>F%vS=ZfdE714up2G-BHl>F+=`7^I&a5 z(XS@_V1LeN!T``ODJZ1xqic2On<;QH;{xrn=(J}&cE=+3eF~4&Xv(F_21nzY~0>8c%aujQz||4x_#lk&p#jeBZB?w-v$*AguJg0 z$!-Y4AHQm@f7P-V>HjgZIX4h}{l3vRw0Zbr3yIu0{kxZw zb68b%jKdwTEgzr#JpOrla(;34``-@&;n%{#ucPBXhlf{JS0~38S6BA!?Z7o~KG4w% zuzLYuK#&{^0386p4gg>>QQ&_@4gd}j;PWFE`ztWeemfro^a6m_|HA(_Q4$QCcK}!H zKsy-tl?|L616Nl7hXV+>004Uc-~@xe0xawR7!1I90l*dj3;}=v_>~Ww^a592Ksx|{ zz)wIOfdIQR0QLibAOQH!y8}P~FyIUv^8i=QKzs0+o_jmFKOGQIV&@Y%;0mzw0ALp~ ze|MnK3ovsA03J~OJ@VfBfR`Hp_&P~?19i@T^L+sHAC5Nw+y?+Bz|I*M2n4`hfZlz8 z{J-FT&AAphxr@p=0*3!3AOKothB^nfe0!kR74Z76(9vZ3>G$J+xhr?|_5k423uyQc zQ{v6C`(dxk9Q!?W@I$~300yuCyV)DP3`tV3eNYVge|3m-Z=>XtMz!S`= zU02u{4Q3Rv9;maA0n;F<7nUZ#m^>5P7a`$Bt_mjmJKS)y; z*3YEY)`Q-SwV{ts+FwnbX2heu9kxAm`*lt!v>ZV}gXDJFIY4l_0l&8H_)}^Lt;8@L z2HH7Z6VYZ1O_13xe9d4cw2BnS`Z5(8zEf`RCHt$VFrHh*Z8aG>>Bj%!o%0ty%l(3h zq9mVAwqmQL1-JEg+IKC;5`%WW6hGlKBXdesXOY=RO%$%&$g*Y`5U>$ZdB7HLYUys3 zV}6&)?!8yjPMQDHw2hK%Lmi9FOtVipE>^s4J6j(k(pa_-{)xXGGgXWdwm)c6?QR#R zO3Ml%>=PePCuLt|3m2Q7-QFoLjH{X`F=xJTDsYhw-mJ=BY$~g`tm_j&!As1Xci)IF zR_>K~ugrKD)((s8*ELLvn3iUJnBf1Aa6Y(?LGIpmtm`rJ^e*gEcp+Lde3D!KIWQ`( ztb8iVQ{w%MMB_oCQ^RZ#POa+?%5ZDavo>vqCf2I~Zgj1t7WjT4QNF(DdDMApGieO; zSE6FOh~c4FJ%*&SXZH>~MA6+R>9j8uLbHUu-+o22Ut1>h@vms({pb7AbV5i4&`pbF z`%|K95^wJfzOa2rzLjzz*|6qXe)P-z9K*BGrxm+r9q@j|+FaSrI_Mou`Mc^Qi${$z zB%=WVDiW8kAUUJIb!z~N^SwqYl9aKG?6CLM-wY;?t!lYTl0`)sh@`y5e4?+mpVCj- zYc`Kxxf_(%uqN{JLbUmzwQ{#3>?ap9BaHgGG0DnXHD*Ouw>}ci5n-FT8>o>fyHm%w zAmdTIq|~2az0xYTnkP=%!4~Ih_`HXS@#EG}^~ zzL8F{Bp1zmJ(A1&Vwzi-Znbw7larpTSYLY_q&&_b75-&x@FyKLrE_I6eaR{L`sQ@| zz{I;ZD;~_&!$`FONs`O1F%57G@5`o>_AyoK-1BLQ6IrC7N^){C;7g$X_IM+e%4&_s zu){3%%20s=o5Qe2{xBDi^7Yod!(xZPCvbfW4pg@l{b3$yyeO6$zT(J|bMgo}*pozw z9i*aiR~R>JNRyM|CP$I$<#Fw2INcVI2-oOPUoFjmG_Mj@0m@H}&y78JX8&bvQYle+ zy$&Q4U%63r1!|S$n0pRV3C*bGxQ)8xUZMtt_k@{L6w>a#4p=fdOo$Jg-Akl8piwFZ zslKxH7wzu>F|{OM{8sD45l9fJs~IX&xKn>15ZoB}tiCOge*LXJqhzTDNOGL*xfL zX;M-rA1+xY6v196vA4(b31j6_q|Jw=euMQiuyR?_CNz)FEL!-~1$RbcS>)f>I82!*wNpwoQl)x6 z+#ux4Gs`ynOom#OHjDVORMhdBZh8Y+>I31nF<%mO?qp1wM2e08<#YyQ^~_%rM||lXJyf0eWX(&bT?!%%0+cc_D>R7k zn=FJ8s+CzZop<&M{*EUj6T?b08G-z!dpYzk4ruB7gkaz2Zk7sU5r91V z8%onJT@zh)91ASOT@qIw`)e|Le?M>*Y&!)IE)UM9c(#967wyu0%6 zO$KBf1+c#C5oNZ|#+jn>K%@!5G$ORK8WDTHhXpESoy+npP5DglNF>ikl9a}2_NmuY zWL8YZtjwC(dr?t@Beia&$r?-6f8*J^$+8unf<4SF{kz&Gb6MqnyQN;LE1~@7x)QHc zEam1KEu;>Jm$_62iVq6i*ny6Z$MDt52QQKXI{0aa`{OE9CS>okdUXcyc($r3h(zbh z*Yqb_Zd$8%vbL_&AQdSr;P;+%)hs}vHETOe;cD? zPd2kVYKTTV`NrnH%2VAG=Q)l)rFxhDWZmRFcki94-HFm~!e_fl)z&@5Wm;78RNDo|q+zh-J~pMksQUcdAS_K$6OwNAS8G z)k=^|(+W~Dkb{{aR<_vp{Jnc#zk=-Xs|UO<%+!)#7%E%0Km}eq)0HH{PEGMrMnpy= zGhp)IxlUw&&hu4{WvLC&Xw70xqW&Pd7m5roc zlyxk;87!BcXet?_>&P)?23_BTe$V#4)0OZx*um#Hr3yH_sR*ju?N&&l@Zh&Sa*8mj z50K?0?*k*Xf|w(Ny%aT)p)0mt2$$Q!%=?(w`%gj{GL5sqn(k0WH%EK0YWCyN7cO>z(JGPMQT%45ZlRrd6%UK%d>@J?#*X+fOQFeVw*&;z|5MA$+Rk~t#bSOt+>`-?fFwqjiJBi} za!iPS-~I?d{1I#3E@@FP$KZr|zhPn60fqWRC6g1fK+`yjVXDZso(yst5TfCAX~t~j z#HuY|sf{&5ocVBz#A?LYz7S-3ZDP#$i`i?y5nS$$yj?6;oYGEhCPTv}lA7~R?X5f} z@1q6Ny?f?&qB0W@Mtl=2Oh=TcWA=rC4 zcD$dUAjRRY*|{5K&+ExR!HlC7AGR9{bc<}Ii{7Y9Wn9V}KYyy`5#s&?lJH9nj(COmLFrOR<)d2V5lv})D_8E3 zsl#m4?%CV;AQ}18%9a)seiqd_ORniiiSwY;G$wDetYn2l`&-b2DwNeFVj$ z3LTq8x8B|RWB&iWzN>hJEEuAYvm!e)0VaJ{RJOFpkaet7I!Hkct7ZCJf+s6tjW)_-a4(@D;2rjC~p{9e&8071zyIuaZFHiBeW zm+MuNDp@=sUAdJzi4a&Qx+4**Hix~%17Z)A;psp<3WZ$FV(II!a_Lxe&&qGR6lOfs zb(k8Q0ya3J{(V)WtVaENk2+a?>IIJ`C(lZsBx(c>eLjdfNTjx&Ys86=4Gvbnp#6MS zRpXrmiJ7a53$5IE3EA5HY(v{H-vT;_jPW6rK(?#sqcFci9@#IK))~9LPx5XpO*L{h z%}=1doMCZmsZCX^i%hCa357hwp~?Q#)$Y}^GBk$ZP`?v#=Ak%N+Gf^ekVBFR_|Ip} z(=QD}*c_TK^4)l%2wpZFpLt2sDhK)8>d`crRN3zdam&NK_h{lws-E_Qj1Hm4lc>Lj zwgsoQHCdtGS5?dLgH}1PX+zZuWT*#-0IzhO$up!iop*98+~UEW;Lx{*I&qfOw7OmIcRS}3yT#|xie3<9>q;GTx8`XN+`3y! zukLqJbw*xl(q_B7F_Uu@nU8%TLzp1dHN}8b(91q(f>b9AL%Dn_vD@@6oh1}!L8&N7 zewVHdF^}f;YQ4O5)Edk~Z6elfHs3#;+Z7&KSwDw`Id-dwk_qFXes+{9JRoD-=cN3~ zP^-3Nj#gYt+XAYSW3H1Nht}W!3QdMIhW6q;A-bIH)N|Dw=)q5VL#1Io<;erwx^-6h zY(^fCbGHUr4MG=xmaZ{%0<5pV-2drO!epRNt9mXBL|M1qHy$Tcr~_Th>d$2Fl7kH5 zy#_H}m3yexaUEy^2UcZd_<(b0p`|Tv9$24i)C_~{?boN_p>}Wz6*&2-*Z_BOEp8qd z*B!uJ3pAGeAUkq05qd1Z~GhdG2@twiIS3=bY-2yIikTgF#;+j;Mt28{F+dD0C z*-)rfm99+)uFDMEXK|aQLO8Tc{P)uCGZOam)EbD`#78RO5UCEHU)oS9WdD1Sfeo)w z9D7f&Y7-w9sm-!c^S_4tKT{<2wCs*EDc6~Vcjt3`^9(h{qs2-ODOt>FcA&uuEniQ|OCQA;{@KiQ(^@tK06g3hze z-jP6M5_J$h!!)%ej++0wn;}ncI1H5P9T_8T1SE&a^uHtnT4zx<12&#bY;!##gq}O} z*gAUbR{n@)^dyDo9B851fS$^kh>}N>aEaYtbz5t6M}5Q59QgScM6|)B_k6iBK0LYm zl&*^?PP!PJmyaHjTWk4=Z;ES0BU7pqI-7_4rZu}8(!>ST3K9}-E(J@D3q_YT?eJd9 zHB~u&bALg6*PFua9gtZi`}d_xO-dtQc;lM)=P1!y^U%3FsF87-N;aDnio7nbx%#Ml zs%v)!kvQ~xXloRHWwCm4`eK6HdY+Kmg;!V&M^8+%PZO$E?@9C!J=We|Omy2Uw!B;< zR*k~!QMPCk7=)nm&g5!N)Grz09HG>dD|AUuBt;Ryzjb6&AOezX6g9G|`;Dw&?T~qZ zcYdwS66&H-XHAdgs=?3c*SX!nKJ{J|+Q-M`w`R`v%={x>`nLT?l9B9|HiAdf%)vOf zL>sT(R-4XRN%FTE;`VULml|)9${|X15#5d-6YF0L;qOp+*MhR5d}0ZGkSbjGuiZFp zL%z6yPMs{Xb@5;E4p^0qvQQSk0Q|v2pDtpfb-y)=uTIW3%8N}1U+!fkF4S`EtI>{j zEKasrPV=R#WL@+VcgH~sU&Vd)Z|4n#qsQHA7IeeWlfz%54^V4wDqkc`WL~bR?K$W& z?!K##)d~(rV506wN2l2cy5gbF=-9`tp+U=q6u&8JeP*0T^PaTb_DEl7@NT?KAiaLI zjo%&LJ*;<8oLd;2d~<2t*g2ju9@_u$ke5Z*Nv^Sw0WUWh-n z$FleJ4)Vvo5L>%Ggt2#C(K_xQp8l$7X%Txz>3qIwMEK(|jQ`|yUYGF4ZJVLbK7Sy&_2Uq&cLUoOBDLXfVYPQSPJ!a2e&ZzNVhTojuYeI3qvUl6~^{d$m zPM*K|1@k}cw>`W)e@Yzu=e-2*9R2fYJ6YVl%<*<+g^_z))sw4OgxB@Arxn51EX zbjii7c+NNrcO&SWQ5OOW4VUz~X?mzDO6NMP|JBUi{JrDQDRLf@(u(nqJN=T2At_yG>t;w1#{T_UH7?APS8_E`LMWe2qgL#Pm%5J%*_ywwS~rW+ zH?`R1bYI>Dn)TGuei{m2UIl5?Cuma50D(5ikIkE3tfD*m`nbrg>fZR8FU4{^4s}Aw z@m?J~CGsM(e6sJfqYR7a6~lxzW7mazYJhaKb{x2%M2KD#z5VSI^i7q!&XodF`d}=Y zK&$n@5-hyQ*2+~ghnvxQ&O>67Y~O^Q>5rn|6gfanZG=$HE5)6}k#Vq<2=9ysA z6SK@`1BXps59dtFU!YL#qOkX+z)f-Pd;N=A)Jd0c0^MN&Io~LKW(iYRdz`uG85SPNt`~{eYROZ)Gt?pSB)P(VD=D{&R!cND*dtsg;9E0Dy_eH zwAeS$yS7BQuoTYln7=cKooa;YXNkhKl`oUwX53i* zR!^}suZFfOOIq^x0KtnBmz%QxiGu7>0~``*x;}@a@3$%3RJTS;x2}yBQWHNa@Qw{j zN*KMnvB04@UXG59DEXLuc2`{{5#FlmUd&A?ETZ3M5NCViL#-13g=~~m;_8YcYs%U~ z4TUiW+YTCvmX2?1FyjyBP$3!{*T?=~qNffdmmvoXdrC7V;4)tRa2q*qV@FNf}HQ+)*H(0e~T5P}>cS+87ZrGAOpskxZ-2Fk`-uN1q& zJoWmd@1owA3K)jCjekni0xgJwGzx)O&bkh=+=4Z?7gnm-Hrp{cN(uKL_YmW6-l06h zHu|2;JsGB&YW^1MW2!qhz51rU<{3`(=KHxPomx}4CCcw=cUQ$b4z+{h>ja^&tmAc zmwPjQb|esdG-Vs?s2okYxT&5a^|e-dt>qi9-JyT2nEaSJX}b4*T)n~FI^dFhYPwIZ z@A;b-$!iSRzbdL*?}j3hzk>Fs2OeqprDfus?#j)4eG=!FQL5xDf|waZ^!a5q;+-Xe zW`?W}0kR$?7wPvi1Xr!o9N*DpZ|v+cvqF5Gv8iQ1r$;$ zyQ#Czj>KyPd}40hhJB16xx4ts-6Yt{-!lZ>_63y5w7MGv&5nJfdQkyW-ZfO59rJvH z%?mN#ksr(%uZ??wc2@SZoSL2d+$Te(7rtw<7bJu3TQBuj_HtmIo9@>NY{*>LvI)us zwNBnCjii@G+@G7B>I-aYZ1wipYo004dQtm8`aqrrH@Bq~)H2cP6L{%*F;~FyIq~bl z7mv?#i$D8<+I|!q2Kisic(tifZF=v7v(7J5KML;BRo;EZ{fo-sdPhfP^|M68{3>hz zuYy1HzVYc6z%9A7W)cB(2d_FNAQw_$_~BT(Hh<%Oe8^|H>)SVu>}Y6n$ZzOHY{n^` zQ*lb3_Ny7BzI$JQ=kk(pjp0QlVqv%cL&(R6&*IYZJIOt?4!(_X zKA#sUnRioZ$*vsU!p?;p7(YRNn!En9to!dlL7D!?5Qd+qpREfPOQ(yB(iDu6ssx7M zP9kHPpY)X#>P9(ahRieYCvz*o`=k2sKcyfA*ALWAn_)#;har{emv_cPmN3`UzXwhF zavX)QD6#TLp2T$6pF1ChKzN_J7ClknJ!JfygIL;HS!(_jsq$*?sW+MYawJu#%d3;j zhvAOxm&4rJU{<=1n}T$g1UhEL524>o28RYuy0&nIr4P4$Fh2Y@{$2+3r7cDo5fKuh(BK4h`dk{Q^29P)D23#)&})__&Ky4YOD%L>QKgY1fV*+ z_SzuRZAu*ETSKb<_&Z~1p%dMp3l!#to!Uqe?t?Khr2{FF%8~pVU*Qh9Io~N3pr&L8u)~$)&B^=x70$-g$$2#X8f!pw@tfTsiRH*S9KM7f;9l1d zrRae&;(1jufBv-J`P(UiS3gtK5Lxe(Fi}zhG^DJ%A#>gPe>7;BG}U8zH1t|yMl_X* z$<#PIZ#lu9tUXkqRZ~jsR?<}*M5-Y>!1t$79C|I=y5Ktk0Ii*7;`Cj z-TjP2h6HM?Mv`{#SsqT&2@GR`c$W0pu4^bQ_bL#&e0rL15V}>-8s6jT!x-So5iFk# z`?40LYYm<&hS0L9LKr(#I3e~}upLz6>E&6U8y4)9uOV&KpZKg_HThAD08Gg-V$--& z3G+x^5^w6&n-n0Y=BNqusJ3~2u^LbQULPI143lT**IDo81ymXBdUVMnVyDUV$pDkb zU>+pBkkZ3QrD#@3yo6Y{IJ(>2nq2j7#3Ai~et=rKz*j#)mkN_cmL3x6G#I6+QwY^o z`Kw74Os10G8@o(Sx&BCrX8`KhLr>`IRm5jlKh_FsD^Yq}B%o7#*57>Ei=NlP2DGS9 z=xTB5GW3965-{;SAWE!uGE@&13OmnJwbW~W2Kp*uj+C_SW>SKY!|@i_hf2%$qTopB z0Wn}CA|`@=TIivhKtx!{z@>CvpEp|LivN++S_?$-k$(xHilBZ&07K{j>07ssHCS><`t86?$?3g{<%EN@)z28X-%i`=|tnOG95V0c{Y+ zM^z@sIBWz9mMDh)_R|>Iw6FFZqXVbtr|BJGEgZ?x1z#g}1!bsERj419!2f2b<0*7D z_23Yz5o0e!dgdVrqtZ1~Fhlq^1zhtE9@DxOMP>7idjWf{iQ~vreWuxH750T$ravwj z_C^e|slhp{cL{d+`z=ooJjRJh$sjd(D)NLy#$iVU>5a?%N4q%;>3)!w^d1&Nb^nDa z3jQELAUgL_U{YR2(C7gf0oZ-Yu_~uAMrO@IuYsEaPn3<7<)4k7QH;ViAiT;DmHjb= zHGFDM^wA#i=UF=x*DO(CBuWW?m)f?X(W&5tGmP!I&oxThYVwRzMI!vkQq0KNTKANu zf;@8Uhlbi~FO_3~2t61kZ_lub6Jp%k!>c+WB^Y7BWn=|2wr_>>7Eb_PDmMyrv>GQh z{Y@ao_(4q!%a7q}VX`uf?!PQ`i?5Qd-m7pJpgn78)kY1(0lxL~A`jFXmWgP`aO;x&9 zj%|cffnHRKd_d;t6H4F#?F0wRz{p0AwlGqVpf^-J z%K(j7Eu_hW9GVp=KBGQDCJ)o7i<0lfJbKt=KxoCjhO@-<1*sZeRS|$u`p7^m^S@sP=iDj}Szg2dh2?KW zb1h9LCCvcXOz-@9zf7dPfzoZ;^`xT~XHx2kU!J-M5V+pRv|t)=n|-P^6ZyVoG=>CCZ*G23f& s@if=nYl_?ZlC`Imx7X6Nhr8SOxo@v^bFXburk!fPgT>3277Qr<;as;C!*fP!8@N&pQ45C(c+oxAnkVGP2V*>~TV1Zcr0#F3N9suU%TE~t7 zK0a{k*5U9_09FB@YEHlIo_9SC;XojuFc;W8)ICvA(Kjo>{}!1OfXV`86lYpYZ$HDHuqXvv!u!U2Ps-@7OImk|0$hUA2(APW?#xUY1?WOYK6$pWQ5@g5Rd zas({*fWV=;LO`_?06Iq1WF2gL(gdyDfbBSdA^?ol{2p)-1tN;D(j)ii2y2t|wGGbE zS+L{|AcsOg0nCy`2!IR#uUgL0+vIn;{YH4 z)E9{Tn*j?9*bu;>`ry#oLjxvD!5$qzm;ga#g@KKGfGG;7hrS8{-wYro`Y$0xlV!ad zFpq;#nq`z3;NSpI2*d`1Vfl|wP-x4YZE%Dmmp;87G|%LKP;VXb{4d4je~0~d7XXw2 zPC-v2OW!vIK>4H}wU?&1gz$>%CL_x-KH-JrY)9M6GTS20Y2Z%lkh3~sggLl)&mk`A zCCH#!J*D_^x)YUb=8`+sX$EO(&g=(L{JGyUkXY$6pEqUPWw7Mehd{p0 zK$Vr^BW)3)Bl?u;XD_2dj|=v6xs_XeN>TUe?=m^}qJvEwt)=gJy}z}1o))L(x@j?7 z?JUXP{m^;&YhwW9?2TH7*|tLQq+t7p%1uMAXl+usXzlD=ul?Em$Mq^(%gqgp5RS6~ zOY?tb(w=@vY~0-3N+^2xMTWViKKc98)Y&gSRG)(*r%6vdW;(PcockICe!A5D;7D`c zVj=ttJkT*YAH;0BVD98n2iJtMtw zLDyI!@I``E4lz4%$4hx431c5*9?Ij`A(4ot*;tvqBDW?#8t$;MNWm=GSf_`M>%>O; z#!E>)b(avy%ZM>P`aP3inLnG8{B~}Z^gdX6E;lP)_ui4*ocy``!m7Es0!C@8^n77O zzwLYxg_b{GTu+~yFZsZJX`%F^0D7UUU7}!tTq8EIQ2zDyrNxTx#^}Y$LCb>0s?oRe zi`5gsmzF5M_aoia<47jD z{D*M_|!+1k-8h{47; zhn9t{uYT()lwT1J2TB8hD#a>`_>cnnumy>GewotUy z<-V}h(^%0{vo5=Xx*QZJ6uJ9Ea2QdcM-ScFg`}Yzk``K5Tg1Vj^l_T_Qpstv@>Do4u6Z0!1E|*AkSsS1e z$M!81v^aaLp7kYv%zJVkyOUhqO~@1NdD{>;tG3_)M(Pra6e2^=|xd8GkRLJ_m_(+3I+d^ zm?Q}sr}G#$aL7u%I(2M-1J9R#G5o3%-mJ5S$ED#+<%}d#sQ*L~#$rUR40nZnhZVVODphL`Jq-m3qn|T)U>k_O{y)w}rqgvXtN54$IUaSNd9ir0^1PUU>6&TEQ>G z1x-7K$mF<~Ld{X`vd)V!Yg{C*;&X=Gw!hG3j73_gCSQJy>!i^-XGs-pyiB-D^GW7n zYGKojsi-bpm-7DFgi}`nmOD*UD$-++9{`Vtle<7#mVH7qQrpdJ6XFv8rOO81JM=AB zOg#52>GyfXp`KhCIbZUOm4btC-&T2APTi(FiM#Z(Kb@QvfVBDa#>~u`=llsR*hj-F zj!yA3xi8OCW=*dM_u^WeGa*HD!)0azEn@TvREm}6@(!ky_P)G??fT$pJ=mwG zdZDzi6m`~g(y;>5B+sx5BSlT2cm&%SY6ff3N&CNHcWXYQdYt@EP5ikUS<_{8!};~M zeVS5;TPG)RJ+<>Ri^5jTSHDJQ^~U|bpyz6W;K5gKX4rYA|;abIw z8@Y;JbMfD=ed<)DM_k%_B+jg=ug-o0K?crqlZ;1x^3Zj0XCB)eSE^qtwrf1=JNq=V zZYY}#Q^I*8Cepy=#F@v_ND^@sKTt=%JvQg$oVZrEH&HK2rs$^Q75durf!eae`1}z^kLmdyd9=RI`5z&_ zH%$-Jf1{FiHc$sEX?8wqTR(SZNMKIVeF1fSNzfO9@nD1LtPePBhWI?DquU2Oi`!o9 zD|n|=xpPUn9{vdK9PVc*-ia6N{%pM@(a_NxeisS;Mlp7rf}X|Nn%~}fvqt&WqkJFI zy^o&oF>#f9IdIiX@q}u-pW#5jpGj8;U!WNB4GS#rn04R{%-^~&|DV@_SfN2)FM^H= zxoCw3d2Bf82nIh_3Vxv!td0t{CIsJ|2^us4w%fs$CPA;2LeTBOZ!sYlLWnyh#B(sj zdppEeDAZpmG|(h8c-w*jLD{v@0|cvW0#LFiBwy|HDU{uYn_rNPBKTNY$-1&%vj_>~ z;+HXsl`9*NJzf3s{h-xYuLkD6qDO!_F&CFbd7ESH9WLbk^BQhC01<)l$;h#12Kyfq zbb|`IZCJ{f-j~mt((<)XxBdwCfxzj`8r>Q%{ex{IU0)Sf`B%Ml8T0%_ese+7KS#f2wT=r-~i+6u<8h_7LHS<68==$neR2t=<`{Ql*=2&RXOC?tc@kKT3M=biDk4!to4Y zr^O@E2k~v%3`eG*!);pRBHbNH2-}^B5@5Y)$r}E(JW8Y{CPoQw>WnU^vX^|}dl4DK zmxtlsiRLtoI5vxSZ1ZX|k!jM7{uzqZbc<5miOY^r--5-;yF^A~9A{yk(}P}r*uyTm z`2||y6Q-iy2nP+d`e!M4g!9EvTH*=?<2Lx>1C%3oVCc@b4%hkNA=s#W6RahN?eO-y zST{cp(|4QkGSJu?hBY?4*yv~?I&r`s4~xPjc+e#x&9RYvp*OXZ!^83j@f1SIEcOo3 zEi^t9RC_jWV-$DLiL;2r%y&cLgqQ3{K33u>&Y(Q&2v7dV<(Z)Folx)Cu!7v=5JJi@ zqb6l^C}n&nWkNW0QaSavX)4Vvb%vNaSChIhl)AK&x+0wBmYc+_gKl-hy;Mwj!TG9_ z^JOU=K6MhGW0~BKeD7uT{_Cye+8KO@0-k3sxk5;m*p3@iRzuXNmu=(j3#89CNAuzm zIXZ3_?cj}vUQ6vnmI%HE0}<@i*wZ_5`N{-=9j&~)^g^l3@|~z3LeXp$No-iR`rz%qtS%iBUW4T3wde7Bs>VBnL+EVn_+wO1kBm zBdf@$Qkp!Y}RFs^b3swe>C8*_TJ-5tM5DEXncXPWxQajK3=(Nu>_oTrP zKWWpnCS{ojoYi!D)?HkF8zuJ6+ZYz<_zKS4=d(CL9O1!ko{DWO)-_)jTi_&2io?cO zROh5fq_t2fIImWs3?s;hM*ZiHs~*{0|X5qDq&>5aLO8yEL}&wJi;K$?vbyGmS0mTmw#BU z;8CuWR1U8zR~;$8u~)u8&ZSV&uPRskzLx$@*l}PA_iHZheN1|Xjn^+IZd)g%ZdZn1 z#ImV23Z_9Y86mBaJf(Isv)mGQ-8C=6wQXFIh}{iSf|YV9 zHp^#t+IQ2|eKR-%JyP_2yXep7Y8%d!mi)}0yV=ds)!8u=eKZoEUv>OgqCK1xXGVHj zkdA>D%js7Ck|;D}e}9rcslv2&PpC#XUpvk?(eA!=hoo&yRiW5iNyc!&6P0*J6|53} zJ-#E%TB;`Bqc}X)^Y~zVYfcxa?tm3c_-x`g@N zghBUMJz>IWm4=8U5_T`PFmq(jr_nSvg@&c9r16acF2><{9 literal 0 HcmV?d00001 diff --git a/doc/html/graphics/toolbar.gif b/doc/html/graphics/toolbar.gif new file mode 100644 index 0000000000000000000000000000000000000000..26f6f3b5c93e5613b60a56c30f192411333057c0 GIT binary patch literal 10273 zcmbW5EabV=9H-3@}&NOyO4$j~62(hS3Se(S9B z51h~1FZP>#?Q5-l-)}BOWd$KYiyYuR@*VI$kYNA@9UTT8J&2VJw1D)AgX0wkC+4fS zm~>2-Yna%qTsZ7Jxbz%vXgS_eG7yn75>c=aQL+%x@)9#}ky3M#(hHK&(2>3SuLQ{$ zn8*Tx$lr00GmBHua#7H7Q_%BKut`&4F;g?KQnPctW8rwm#q+MPgdT^R5to;-4u$DQ z91E??`+^4EWnRJmSQZotDH7+g5ce*UmX?*V4^@gr2PV}mYd_(`>^7BLBplN8_$Nz8-Fn1rcp0l_tBusW1!y59hiJ7x@nV z$KSsrZ>;9u87$&hF1@l|Sy|cHvEB~}1p;I>0gVX&AOQdnAO;11 zTL5?gfG$rl!+*f_3-HnfbPdP>gA)K6E&!4Om{H9&0atQ>36L=v9y8d%U0%#Tj(&Ya$(kzGcZvuG11z>+|5{v;13;=|JlH=(K=<5UIPr#073vIAPOaDeort6pVed-TF@7cM+eSU z`dv5xA>p-$4gW40ildQ@qEN0a9!X->`DHRvTQZi$Z8e&$TxTOM?DBS-qWQa}28$#% zI`$~Z?$7x&*qASY%lkxBGlGRJDe^qAV$1yGbpH%P_=y9jFpT-~wS)=7rDV_g1 zhi;wIYNUMMS9seO;YJAM>3a|(bC{oA8bc)bTSu3dPLjp#0Y_filTMzZo{NP(nrmP4mWt&8+*@K~Q|9j;fOzKW2yTbH8%?II$wfA-* z2?C?EC2x#>*_4(sD(_@DH*`4ZNCMNMK41OAVac-DaYaS9i)cktNf0?_-46Qk*Yv_c z)-Ubz0(PgZ6ZWeP?foKlm5Dbzo?M;nM=G>k{}#zEf>7|Y?c2J0KR9$@BSa6Ieu}^^ zes#H@{Aw8}gjBSWS=l=U(>$@c)Y7L#ABQd><6-a7r*%J7>t1 z&gr@N7Z~7b?+m_1s;8^EE-jz-rgKieb455+O<+HDddKC^_e^;Bw`IiEn{F#yuf}qZ zI59|_EQ!SRPTDubVQ**Pv!>z!a$IL$~Wa@gruJI3R+ju<7??MP`x>rBt z0bYVqFv95okT=C0K}7Aj{DEJ?5oO4*hxjA*w_u9-S;{|mG_Rkh(g+bdk5 zl%J?kJ(}D1L*s)GQpveDM2dZz!pC7kx&>GFL$cJJ+!6SdW)D%#;`EH~r7KbL?rG`! zSU#Wo3aD-pes7lH=#7J*6~n$oEd`?dR0?PcyVE%IxZDNm=Y~m}MVEw4#0| zt%zi?>P3Q+tFBTk9IVH$+zUH8CQ==DirJTJ1lw=krb&wIaps|p$jg)`3=!C{=1spYlWI`b#33Vqc&ge}5w%W)u{vp8 zh-oTt*-Z)Q;_DMwmk~0wlt+_+a?wuggr&)}-D8vEB1Ox2t4MWH3cnR{oc>iIB-P1a zwaaFxKUDjftdqlvpK_jkC|2&JS@?Ip@XqHzvjnU|L`eASsEAd>ro!s%m5y$qKqEx1}RE&@r_K<0pWeij_OC9LmE{$T%LW1RT* zJJkOafoE>5VwCP}uhG1KUy0~mU4Oi7`Vp`|7^VVa`&7`}KY?tl_p=x#vSi7QT%z1I+uwF?noFs6s)CqYz4d4dKd$z0Bd@uL5;W`M|K^eaG3zS#=yoPx$gP0-^ede%cP{29cywyBnS zP5Ums^PiaEcnG!7#AZh1sBB;8-*v61IZx|nuM%l^v~!n!Gg&)ihW{NIJg-`a)L`Gq znz?T~<>z+W68&_N>oEjB`5jl_gTcUMH2hERBFSNFZdILhxO)%ki*NENjnYfQ98rac z9Ex7!Nn>xM$o!IxmNmZkN1!%p;ZrWxXWLwL0f+F=6AN*O{3IFKmk`eN0%FqwIbx0a zZn##l$GmOJtV@Gq-*tSm<6+H+mu%i5UNR<_4lVt0zD&IV*?b^OzwL1WYJ*a#j*Y6v zmcRJZy>2l1)3I5Nh}mzP#tK_MhYvd<$hK6`k122brJ%dM zy&fGq9OwFTS$|3;1iF_PF1{T!O#Gdqip#z`l1{v4Ds*PI>Uq&R*@%L)YR5U2jM#S8BW>BMcd=(Qsd z(FWUBziS=KNzr4ff}H`t46@XDlZmMP1CB8V-0vcYnuGocCqhC9aTy;6-)S(vuY`!~ zkJ`*s^x-*9lAC~|&r$FdG#+QOa$ou7!?%od!xq~RH&CwNq2DF+hCb`JdFNUO8dE;A zKRd7ZqB<^2C4HP{m=~Ki;8SkjXlL$n@47xdQ-(>xxA%|lC2Ho*@(@2B57;6fdz&QM zpww>Df_YDC2G4grxIUM}(QtObA3HPOyw5T6o@+c_s_m!3cH92E{PFO=-uF53_;J7F z{n+$AbIBet6!4Gn$E09DnL$9MM*xV~)dKAY_VN#YMbCdsf%qU_Lc73M5v=gLA3140 zR3w2Yc0cGm0~pd-m?DCPn|#?oLGPITh&%(+!(A{9{m1VD-yQ_bH3h%7l z-igHF@o8b9JMIz@w$X}S-p%2@%i$H_wn2BceoNsYh7sXE-4R|G9_~#MkO+_1Mfd1b z&w9SkyfTqImf>I01v80MQx9kzg;+B_i}hJqe6u{*<`{xU;`l;Zv@$FxVp zt$Rk@62@LAMPCWU)iFaF%i@~s;!l?u5%+O5B=N{baZtrN*!jHQ67ZBvy&}6U7^m034tPDaENlzS^FkpyCTxL#UHezFIiG2XYz?scyU&Spd zB^kuWu(ZSoj>L+tn2WQ-?t+r{g_7|zlA4zjBY0y-R^knB;~784$+9FoGN&k9C1Q zrKlpi^uQ7NlJZb?857oc)884<;9iK$X0*9emVyymy-*hNVHUqvy1N%fA6hoF+)Chc zR&#mQ00~fckUemdCR9joV4gi-1W}KKv?5xfn^;U(HDfnel4e^(_!3S3l4dtVW*xO8 zlN(ulCbiu2%3aRLK01tk`#1G$CDZCY^C~iX)G+V%F#cXRH@Pow$jh{@JZ7~#yM5SV zE7D|3IiF4@2jg`?y)xaOmTc_IG>oX|x`)*Ba?4AjoLbVHm6m+c)-0XbEF(6yEv9F%~;1-vZ@Z&_*Wy>mb!B_x@}ir@sC zhx`G;f_EZT)*{87k+Djx`DCwtBB<qz63|Kij$cqPs(0l_#SX8-p^E zjmr~O(jz@HvaB<5?TzwUJOa{GN<`>WTk|qWGMRZYdAG~NyfS}fWPTT5a03;Mmd7=X zBzmzxxqJLnd0IC%nskSr&Ih6t*ts zT!j9F9u}KEM#G}e*I!pCl~-warJfkY^?0YAcvsp8{51KTddE_Fpj`8PCFSbThQzqW z{dK9uXerApsD9=zO>c}f?Pif$Xc?z*ne<2+Ddcxc zMAbcACF!q(xnVZJh+agu+Y-#&Z&^Y_rW7f2ft;L2dr5tPx=oQ7yA`QphHK$&2Pxdv0K3`r$ z8j&0t3|9-S%M2tKuZ+Q8 z9(}E{C@qIapF@o*qKp}!qIK#+-*u2txSeR)pV~Ud+MwI${U6!~ecHcD)lSQ}avHF; zlec#}&~*7oKhf6HBD|f^E$vq-fYmlV_N(^Ur?w9APHw3V466>`s1E1+j^nY8)8h^g zpwpSAb4RqRmt4!*txYzoji;&YMx|?7w0&5#yT77+wYPm7o$U&UZ!VlwevN+Yn#0LeyoSv`#W8954}m}rA#-fV|PbTcV}bo zZdMOxd(ZxA&*8D_JFH%>5_+NNJ{$^Oym66AiKGO3|e*8Cb6z zyq7z=okx|H59XjY-mU4|D~eSFuI#rk>BUwZ#EtIMh4-jL4_@;0b5IPZp%q0QHHVBe z2d8)@J`Ev)6-v`Zh69$%3);Z>KEu{Ut);I&m-$3Sk4MIxL{?V_dcvA(!EN5KG99rR zyKQs~Ubx<<60VWXv`qp$Nvp+RU+im_U;F~jMBPr9Q8*<(dmT~*nmo$aGU zmGsOs$Sj)UgTCVf?8waKV|CXft1%eDo1M22DgZoSr;CnLw~lU7sl5 zMo-Q7j&{Muy4zjBJktQj^lz~#MY!{KoyjT3NyrZRpRpO(@k|NDI3LgS%gH2^VhZ0B zF}>n4Ls~V~jWWxOK&=>7BI_VI#WM1dlx-3EB5sXHjTA5Rd<3)OM_gmI`j2p zgnxSuR5dL_IWKoQu_`tOUK>GpPpenW=p;@oRZf05_}-+;57RV6{@u zwYdxOS!#~Cl+$TC>}C1W$++hTv6$&;_-v}$N-{QEKWw5FHc6X58<#o)`OrqtTUHsl zK$O*DNLTJ1wwld09JjI>2#<)09uA{`L9kYmghsL>VY#1SUB$3MqY*pP)mp^ZP~pL! zILsoZ__aSBYcM}#Xd&t*<@&bxIv8O4BaX7>hkQ`AR{6z^T?RmL0}gi->8S6Wnz~EJ?#XuUnc(bfJ@0|dcPtRQhKMc4+_eMKJw&`8#;3`@%vZ3J8OqJE_<|8N4T8Z!C&`m%>EYp@0xS&Z*m-iErAA!J@SD4j<4J2 z#D^bp_w3g9wqg#tIZu9a?rC>!m#EwI%UJhRR{%iuq`#W~oRq~)bL->%xdKHHC(+@_8_@0;JWrP`9=1c-1h zb~twMrnhWkk0Jg5PR+?v(?}imswi(8CsJiN9TL&42D3>T=8Q8M zH#MHjp-qWq=`xVAxfu>m(lLc(FAb3$U!ytVmpYyAU>4q&6tM`FCVb)vreR)a(zf5V4- zyqR-NwtfSZxs?ZQ)IXwHro3tckSk_tcD#eE2nW-SLsF3m2a8?OE^TVc=WPc`RI6 zVn?9*Zt?{_!}VOr1<#O#>(o5YVDAp)-6>ZeZslC>{CFgBLei9c*3o|MtwADlx&bV< zaR^yGwkhP&HMeBKuqh=%ND{Uvr2@`;H50Xz<0Nd z=(oRe1x@~zbbHN_u6t_Sh~LAbmx%IJH=eXS6V=BJtY691Hd`P0{pTjL_0+6mmf_`0 z3F)5wxY82mW;^?h@!uoD8u=cpKqAB~DZ!=XYzeV|KbCOqd>cR8znDm`D4V5h=^s>Z zd=9O-4rMO4Um`_HtyNXMu`wC$=2Okz&u=MBf2+ljhkl5A9at-$HezMl0ex22*tb-( zBjGUh)6U{w>k2<(5LisQe;@g3W#*g%*BP(-XmL%q_D- zYvLsH8h3X>8k=yoMiy5Rb*2wnQI%N^UqkM_#9ITga$4e#A@2wOSQaM?k~;LisU%c( zd_P1c`0sLvJUHZi6{Vo#lpI{$L|d6I&ULyJzqGg(%%*`?6H1i6sjb4*@~KzlGL@!I zm3PX-Qj+!qV*q}2T9_}y9VLRo9KvV zp$Y|HFqZBn&MFH|>$Ibi#Pg|gHSM~fNeuAT>u_sW2ZgJWI@U{OVRa{CsBo-p0*o?v zae;&~@z*+0n>2D&}EH~I=6ZcZ2Q?bkL(jeqjdED`DM^(^ViPP-Vwr3@`G z@Z6mOT_9?h`@<)v37B*cXj+bV^S>NeX`j{0eF>cZ1)Oo9 zW?iN}zt9&bavkH6h0DoZA;ycijc!9d@wVlh2m`@ zITr#11%^zQ!vSap{gy;^%qW-91(^B=y~KSa3fxi7SYVTFX)1Z7=I4Cvui3iT`ffZ# zPFqnT?M0Nwc8aJGwh>nBv~Px(<@ic3^<0t(DZVKQy@tocdiU>8{TmLF*v5!fAlRmf zxgU_>ywsBnNX51`WFsZ|7AJB24iio?OxLI#pX0m5w5k_Os$P-2EzH2`RR)HKyh)P( zWKCj$_}m-FVF4Bckb2$oxfx07JVEiF_~UYfWhWzrWChK=-CYTIX!OEH#YvryTo z<0r=N?u{TKCR875F;|oG*&T-KkRr6dH_uzMJ}-}&(_ZFqsuq3t#R#sPsSUg9*Wmo8 zJYjbAFAWjGgd%CgBFtlf;+UOGzK5PFqOP6k3uB`BAw2vel{^3E2q^^@Sj&vVrHJV8 zK#|F4B*{o8z7tj~faI;sh*NKh>bAsz-#TqteN|9B{z(q|UirhMQ!2=hUhC3sUXAuL z6TG+4o!Y`}<#Llg;#;a(k};XTQlHZ^U#{#Gg_orYpl*j8_oilu!;}AIQ(2dZOo<@0 zJuC_R+2PZV#>)~+r{Ag^Q>c+H@45#5PC>(Cf?o*OjF8ZwwedM1RDOumc&<%d9>12Y zFkdfmV0=(1!>kqVDjjYVw4v-K!Po%O+l#y?8-!iyxMZJne69a#yG7fnoSsU6V5xaX zo|7EzEs^EaO-CK@)wSda3FIUt_BB(-9al;oPQTPPX!`ZK>>rY{b%@GeYZ;TjBz#Ie z*q+^e^D5_>u;6JyoZE(Po?cA^lozi%4pJa=!RQsKooP;uiCq3Gnj2^vO+AllrdISt zne!w}wx`|($GZz_=ibD<$qrb$#j^y>hMr$Y7B9jy7A{ zQHDdpp&Rd2#jwz8gGu3A-Qtt&V)qfh5D+U$Cammt%qwxBV%BK*!e8DkM&Qr@NL!oB z_7_JhQxRj9yT)GjhVIddM}=>=&QH`x^_{1OO>BtIZ#lq1-*7-gDOcM@og%#1tF(ID zNUL%^(v#nEy#A1Iq6u|8?*)3jj5qc+sOe*>I0fU1Tk~$P_m_`cMXbWAbF8a9ze{}m zDH=xBETzEn#fI{4p_{!fvB3foIZ5JW_PXhq5UPs>74IukXfPq}Os2wZ)xyFe9=vJE zQ=!)VLRK6FpUg*l-8F^KPkYrJ)YQbl{-o<*`&M1xcS_ZUwLHWS8G!>`OSL{}U3qQn z&84}1Gw9*JTct2-8Q(w^QWZDYap0fCy(#2Uh3=-}^f;f|xP8{>-$<#M#oWD3Jmfh@ zNJAAvza>Jo1ac}T2;NNe1&`Y35Ab)oKp;acROy_q7C381W_M~%_5tqX-D{!W$=Qh{ zLDM@lt_2VbWU7OIUPZ4DkHcrFgyA68sl|NU7uc? zlOA!^s8O}^rTM4c_;RSHD>}z#7OY<=cP;XZomY)DHWSV)zhOV+JjS(N**(Qp#)jqI z41DX@vr2MCx2tquB(b1>pnd46UII2L{Wk=h#dab)orl>FJs_pYz(ln?Ge!+obalp+ zW2U_apBLYA((|^rQq|U+$GHzi6nWxH+~xx_oXZGv#(Cy#&EOgIri59TyzQ0qNzk7B}q%(QhnD9R3W`4hndQT#q5 zk#F1%YjoyYyw?2JHWJa7|FKiBX!*4cVK^_BCl(= z-9Z|$;-T6UJKjnhC#O155gj1!n8wVD{?E})!(37IMTP{vYez^yMQ%}ZI5|6^OLG{$ z;0v3etEk{0xXIJ1+r1ByF+^~Pr_(p7_b#HBB^x0_d(sr#_lBdAhMl4yq>Y9f>s|Y? z^gDP@#8}+7e*#o|^iXb2{tHeaR4#b85V@hSD3(;#eGr#sfcQzD_^zxZtPj(XK-LOH zSdLS!o?oQ0Pjp-sDiq9r5yT%a2QKbcuI%Tf>F0mX$1laFvCF5>FY-Di;9 zEKna|{GmVT-JoTAu+_=HCzHXCumr4PE*>GiZ@QdtA&@9c#KlDHQd2=+Zcu7ofk>-; zn-+!DD%dl6F#nYZxs#Z$m?B(C-V7$Mhxnu*a7{1B&MEKPr)wn#>FbOBFsw5_;0EuL zz*6FI9efb!7b@oc>?jx0CmS9;?10rDN#FZ`EDvWL!N4CFpc|OsmG{>jGD979-+dF5 zJ)k*1d>Sn28lt2J8{mo`dGks^mt4V8Og^GtL4rUT-B-bm0*tY%Sfr|mrZoCzmF69a zA`OZn3$J3qDtJ~jqik1M8m>(5HRP47=#4d$)H3ATFA|3}mX%@{TQUZQ88>tHR??@3SiU>6LzmQ>V zUTwWHcp+qB>yz3__5^GB1Tzu@CRRO1p|&%twneYL%s06s)?!1U1d*DUb5uVoMmfw@ zU#e6;R-Huu{YsR3Vjea*TaR*qHMQN3dt9G*<(jgmI(6EvAz-Hg_ncaynA$1U5I}<5 z_)c!SsL#4i-NC0;u%>T>rjREz4q#JBhZ>jB8V?klC-dW?=IS@P8nfBc`Q_7#CYoFJ znuj; z5UD9b2F+)B?QOo<2RVfH*IEt6i76s92yx5=W{MVd3{IAv_5p=9!gq#Qev&1IiJVY} zf?t!p0mQ*SN18HDFaL%=x!LKdr=3r*cXx~~q?ch{MdDP4sZwU3vPp(tciK`lAb1?p zMU~WOp4)exxMh4fQ-^hJoc~0%RZjLvN+%K-lN)bAi(x?<4dqfQNLOz`&svWj50^P$ z!7ydPC={7XFH4kr!Gu!pvOAFcV&Nm2zWD&sWf`(Dzdmyr@`qFGtZ6+{!Z`9~wv56+ z1CA);=lPP?3pV@{CDvC0eTdOFo2pm-$G)GfVxkmz+BmD{Bpc_zgos=|jayou3W7 zpJT#1mRzlu^xX{L0ZX1K3tnHAyJnZa?=AY3Ea(4TjsTWb)N~*;hQ8vYb^{e{$V*Yy z%K#W5B1%{B%lw=%Y#wYfmaR)%K2MQg>^Lzmx~4mMGXKbI^jBN#`i){y zJkNBM2_n1-Jlmi+gKaubsXSQ z-!Cz{k~h76HoIM0pXE2Y6#sbc_wnDe*$wu_al^*rz{W$$#%;;RlFfAx=4Kd)*~`L4 zf=NN^0Bj;A4hj9e!Rx)lO{PE{6GjG1wFj497hm7kvx$?baLhgtr1)_|jVh zI0=L{Te!|!#Aop&sTO`an`8=a$ObJ4Tec{_Zc*J@kf3kV=5990MY*gq(9Go literal 0 HcmV?d00001 diff --git a/doc/html/graphics/writeall.gif b/doc/html/graphics/writeall.gif new file mode 100644 index 0000000000000000000000000000000000000000..96308503077a2e72975b5a0ed34e7420a999dc53 GIT binary patch literal 3934 zcmdT@`8yPT)cs6DMwSXO8EyJ9BT2GW(qzfq88BnQ!!2@9f2o-=s z$JkG2IlNFP3)o!;NCc1w3>3Ds1PBB$=18$vdSo)-c09AL|t8*@3FO(0BhM{~>=2qqi1j3IM^WS^~P$4iL_%g`b1_&yE zL5}H>X8|u1puj$J01*Ez0zfAawu4zp($&Ot;$VCEU}zYIXCw*u3js-hf`I>nqBP*k z>?JCd8aX5eXX1FEd?=Kixj9lA?zt-uIf9UYz+mdXHFjZ^MiAQ&81)uz0M7IVFms^L z2>={umI1I9sEJtyD=oU9wG;5}1u!%~@z|LIUj&d;N0sd|UqicMmf0)(Lo*n1gKupzcHq2i!CjWP|&^IGEJ%I-t-@_bs-QJqIph85305m6S!H$PQOwn3n~c*5m~ zQynCAkFmF(d4yG`=v-RVpRoi@vEMAxsjj)obvpoe?CH7TqekE3=c9oA7 zB&%l(fa|wnlR1%N1Le0z(-OC;PyMX-S#JC3VRi3zV<2Qp=y#3$$Ew&bl00RPl|EEK z4;)De@h)>}A_<883bFQa`AohPEc~Zd#Vr?qyhNNqvYVsv%UBTp)aA{5q3F#uzT5J> z`|Ew^I#)r{-TixsP>&@uXpK!TJ<#r4GE{EE=#>x|)@lg$Vh+FKN*vkytRb+TMm~Of zQSzMMDluO;CGc-NW{5r@ov1-wZW= zT!M%M<~)@2CynBzA}G06W~ykv+~cw^`OjwzR)5 zSXVgW!@0xf5P!h3@G;>6n?6B2dwJ%0iWHYJV$Uo$xbZ|u{DC7*LXu}P#Zk>|isW)N zPBv(-%*)9~o$oF?`YoEcWM}P$^ zyrZAG%6a}HM>c<+X*w(SJlkl`i3qIP?%a&cxaT9ux&G&h3%O-=k|hQFdBv_bMBbg4 zdtJI#T=Hgo^u&DGM{$q&a=L8Ed_{-a+?SiSN&0eGpWi zXEpEBKe_Z#%*u1A1@7`{sZ}aqeu;Jzf09lAC*70%Nm#%Rw4JP(XSbiGom}ov>GNFf z+*gvY{8@8-ez^RMG}1pQMR6Iwc^8DS*|-vvvBHg|a7G})J+=*qP- zKEs;Ly=GF4E#pMog*B~ovx-gW%55(e(_--*Ynh5`?Clc0_-=7<@ksgd=GISU3?Djr zvg=M;{Igwr{TG=^UO{{*{SXPpdwy-!!`+TYx6hE81PJ#Oq$Y0jPFtacEMG+(7aZOF zhp!xV?hVef{z$K}#(SW)FQ!KzcXzP*r9+miP_D*M&c0}RGh%jc$iB8;%eL&1!pGyV z{f2r<6_4!|1)u-kjD@o=BoiYv?Zx=x+O9IML>DxSA3b*P(`L(=*gQw4A=He@RJ2GM zMKDLyFz%zOT32k5@5D(n*H%mWuSt5E|D0ChZ!<8pAoVrai}Pz3{A;6(yLZESsE1^- zsweueU9(^XxVHO?EZbjcm{czBr)nF0BeS?~WswJJjcx9qCU5CZA8Fc9y``3z$@x8e z(Hq_#9q}rbc}-STh}>-KS^M zv`$BByl~lf5o4h=xGzI`ep+AYgkkaE@~c}W9?0f%Uw&JAC1|}kYB*kJQe&h_d@49K zAZVl(F=g_`2I|?)lVPTKnefJ8+2f~JyGpB8O4-Ykvv;lpQL^g{?-8!sIQLnfX@5vpMEAk@ z^TS;KnwSGObmHPKjKADpt9OFI$#XiOCBA$1E3;0= z!4WP&xkeQBEuM>Z-IMLoL}ITzd8WF!&@KO#Rm{!+LbIA1wU=w9*)PxZ%J{AR(BO(J zBnxAu)s+wapZ}ycO2rt8%%-bWj`st?C z73rPx&gZuVx(U^93rrT=Z)^?rf3B{s>0G!Qy!C^2nM9$PFz;v7W8RzA{PHbj`a5*? zF$wG6`xO?0(i6O@+iDuuI~Q>t1HTem*V#bW^I>~!L)0solF_Nv z_A)I`RW|8Ar7zzxidD|(%4AecZqRwyJ}=@EX0Xb2Eg_96`H@nN=K4>2d%jxP64+SKF1qJmRx;E9-Fi+j!e4tFHQ=#9Qp# z(NKnoVo1-%vr03cy{t%@^LNP#QI)P3m*Kaix~@p$P5+2HY|9Ij+~-&s zbA5fekH5WPPbg+PWvJpd*S%R&w;q2C)2CUlJBNuyhKZ$x9dro&fe&Q{7$0>A9S#Ur zY_U~W(Wc9Un@xK-%UbyJUUj8~i;jnTRz0-fF%_ZUcTo4tPSij2Xz40LLs*P3C;-9!(gINcMfad3)I8!y5hZJ?RNJE;5nz`3@%Bp z#UeGLdwoq);dU7KBVl6XaZ2n-11Be*n^)oIk|}X1aH}-T!-B%#lp3Wn2EHZ5t~B;h zM^A(^JX&x3k&tpsJLM79KOvZI{1Fvz8)%Z<@AE4?KEKexk`XVYgZHDw+0x^G^e4~@ zAAY477_8&_Nt<;MvS+`z!#PiQp1%9@y%1CQVF zaT6wx31XB7616)QhDkzWg)l^9Gf|E~tX)g;gb{TNlP6u1*XZXJcBg2dQUn5%9Yo`f z6~!NyBR(Y&RmM~7VX23jQ)3yau0BNRTD5D|DNYB8yRC6bMaiYe)GvJLym~2$ zHVkCEFY=5yc$IiCv)?k~v`c2M+Woc-&yIo2`m;XWXS1FdW`^=Bd(?UtnZ + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

grid

+
+Toggle the grid lines on or off, and set grid parameters +
+ +

Shortcuts:

+
+ Key macro g implements the command grid (with no arguments). + Key macro G implements the command grid 2. +
+ +

Usage:

+
+ grid [option]

+
+ where option may be one of the following: +
+
x_spacing [y_spacing [x_origin + y_origin]] +
set the grid to the indicated spacing, where all + spacing and origin values are any valid magic + distance value. +
on|off +
Set the visibility of the grid on or off, as indicated. +
state +
Report the state (on or off) of the grid. In the Tcl + version, this is returned as a boolean value (0 or 1). +
box +
Report the box (rectangle) of the unit grid, in magic + internal coordinates. +
help +
Print usage information on the grid command. +
+
+
+ +

Summary:

+
+ The grid command has two purposes: to draw a reference grid + on the screen as an aid to layout placement, and to define a snap + grid of arbitrary (and not necessarily square) units. This second + use works in conjunction with the snap command; with the + invocation of snap grid (or, equivalently, snap user), + standard magic dimensions for commands such as move, copy, + box, stretch, and mouse-button movement of the cursor + box are parsed as integer divisions of the user grid. The grid does + not have to be visible ("grid on") for the snap function to be + enabled.

+ + Note that the grid has both spacing values and an offset; unlike the + lambda grid, which is always aligned to the internal coordinate system, + the user grid may be any value; for grid spacings that are not a + multiple of internal or lambda values, the grid may need to be + offset from the origin to get the desired alignment. To do this, + specify the x_origin and y_origin values, which + describe the offset of the grid origin from the internal coordinate + system origin.

+ + Usually there is no reason to have different x_spacing and + y_spacing values (only one spacing value is required for + both). However, occasionally it may be useful to define something + like the following: +

+ grid 150um 3l; snap grid +
+ This example makes it easy to draw a number of horizontal routing + lines aligned to a pad cell spacing of 150 microns.

+ + Note that even when the grid is set to visible, at a large enough + zoom factor, where the grid lines become dense, the grid will not + be drawn.

+ + grid with no arguments toggles the visibility of the grid + lines on the screen. +

+ +

Implementation Notes:

+
+ grid is implemented as a built-in window command in magic. +
+ +

See Also:

+
+ snap
+
+ +

+ + + +
Return to command index +
+

Last updated: November 7, 2004 at 3:24pm

+ + diff --git a/doc/html/help.html b/doc/html/help.html new file mode 100644 index 00000000..9e2e0d6b --- /dev/null +++ b/doc/html/help.html @@ -0,0 +1,79 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

help

+
+Print out synopses for all commands valid in the current window (or +restrict output to those containing the indicated pattern) +
+ +

Usage:

+
+ help [pattern]

+
+ where pattern is any keyword or text string. +
+
+ +

Summary:

+
+ The help command invokes the built-in help function in + magic, which lists the summary usage information that + has been compiled into magic for each command. The summary + help information is usually only a single line of text. + Commands that have complicated sets of options have their + own help option, which is not part of the help + command.

+ + Without arguments, help reports a summary usage for + every command in magic. With arguments, magic filters the + output to report only those commands matching the indicated + text pattern.

+ + The output is divided into + general-purpose and window-specific sections. The window-specfic + section depends on the active window. For instance, with a + single layout window present, help cleanup returns no + information. However, the command specialopen netlist + followed by help cleanup will report the usage of the + command cleanup, which is a command that can only be + invoked from the netlist window.

+

+ +

Implementation Notes:

+
+ help is implemented as a built-in command in magic. + Note that there is no general-purpose command-line-based help + method for Tcl commands, so the help command will not + provide any information about magic commands written as Tcl + procedures, such as openwrapper or pushstack. + The general convention is for each Tcl procedure to allow the + option help and provide its own usage information. +
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 7:02pm

+ + diff --git a/doc/html/identify.html b/doc/html/identify.html new file mode 100644 index 00000000..880dd0ec --- /dev/null +++ b/doc/html/identify.html @@ -0,0 +1,62 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

identify

+
+Set the use identifier of the selected cell +
+ +

Usage:

+
+ identify use_id

+
+ where use_id is a unique name to identify the cell use. +
+
+ +

Summary:

+
+ The identify command renames cell uses in magic. By + default, magic names cell uses with the name of the cell + definition followed by an underscore, followed by a unique index + number for the cell use in the parent cell. This is merely a + convention, and any unique identifier suffices to name the cell + use. +
+ +

Implementation Notes:

+
+ identify is implemented as a built-in command in magic. +
+ +

See Also:

+
+ instance
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 9:32pm

+ + diff --git a/doc/html/imacro.html b/doc/html/imacro.html new file mode 100644 index 00000000..153eb6e3 --- /dev/null +++ b/doc/html/imacro.html @@ -0,0 +1,80 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

imacro

+
+Define or print an interactive macro. +
+ +

Usage:

+
+ imacro [window_type] key value

+
+ where key is a valid name for a keyboard key and + value is the command to be printed to the console, + pending completion. If present, window_type must + be one of the window types recognized by the specialopen + command: layout, color, netlist, or + wind3d. If omitted, the layout window type is + assumed, unless the command was called from inside a window + using the colon or semicolon escape to the command-line, in + which case the type of the calling window is assumed. +
+
+ +

Summary:

+
+ The imacro command allows a variant of the macro + command in which the bound command, rather than being immediately + executed, is instead printed to the console as the beginning + portion of a command, awaiting completion. It can be used to + simplify typing of commands by pre-formatting the command line + with the command and possibly some options. For example, +
+ imacro p "paint " +
+ will allow the single keystroke "p" to automatically format + the command "paint " on the command line, waiting for the + user to enter the type to paint and execute the command.

+ + Unlike the macro command, commands entered by imacro + are ultimately evaluated by the Tcl interpreter, and so may + contain Tcl commands as well as magic commands.

+

+ +

Implementation Notes:

+
+ imacro is implemented as a built-in window command in magic. +
+ +

See Also:

+
+ macro
+
+ +

+ + + +
Return to command index +
+

Last updated: November 9, 2004 at 10:13am

+ + diff --git a/doc/html/initialize.html b/doc/html/initialize.html new file mode 100644 index 00000000..5100b74b --- /dev/null +++ b/doc/html/initialize.html @@ -0,0 +1,68 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

initialize

+
+Initialization of magic from the Tcl interpreter. +
+ +

Usage:

+
+ initialize [arguments]

+
+ where arguments is the list of arguments passed to + magic on the UNIX command-line. +
+
+ +

Summary:

+
+ The initialize command is part of the procedure for starting + magic from inside the Tcl interpreter. It is not a user command. + Other Tcl-based packages that wish to use magic directly + should follow this procedure: +
    +
  • Load the tclmagic.so object file. +
  • Call initialize with arguments passed to magic + on the command line. +
  • Call startup +
+
+ +

Implementation Notes:

+
+ initialize is implemented as a built-in command in magic, + but only in the Tcl version. +
+ +

See Also:

+
+ startup
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 7:59am

+ + diff --git a/doc/html/instance.html b/doc/html/instance.html new file mode 100644 index 00000000..22ffaed9 --- /dev/null +++ b/doc/html/instance.html @@ -0,0 +1,103 @@ + + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

instance

+
+Operations on cell instances (uses). +
+ +

Usage:

+
+ instance option

+
+ where option is one of the following: +
+
[list] children [name] +
List all of the children definitions of cell use name, + or the children of the currently selected cell instance. +
[list] parent [name] +
List the parent cell definition of cell use name, + or the parent of the currently selected cell instance. +
[list] exists|self [name] +
Returns the name of the instance if the cell exists, or false + (0) if the instance does not exist (is not loaded into the + database; the cell may still exist on disk). If name + is not present, returns the name of the currently selected + instance. +
[list] allcells +
List all of the cell instances in the database. Note that + expansion is not automatic, so cells that are not expanded + are not searched. +
+
+
+ +

Summary:

+
+ The instance command performs various operations on + cell uses, or instances. For the first four options listed + above, instance lists cells by their relationship to + cell use name, or to the current selection if no + name is given. The optional argument list + returns the result as a list. In particular, in the Tcl + version of magic, this list is a Tcl result that may be + operated on by Tcl procedures.

+

+ +

Implementation Notes:

+
+ instance is implemented as a built-in function in magic + The Tcl version of magic returns Tcl results when the "list" + option is present. instance is essentially an alias for the + cellname command, and takes many of the same options, but + references are to cell instances rather that cell definitions + (q.v.). A number of options to cellname are meaningless + for instances.

+ + The command option instance list exists is nonsensical from + the standpoint of the end-user (if the cell is selected, of course + it exists). However, it is a very useful function for Tcl scripts + to determine the name of the cell instance that is currently + selected. +

+ +

Bugs:

+
+ Technically, instance rename should be implemented as a + replacement for the command identify. +
+ +

See Also:

+
+ cellname
+ load
+ tk_path_name
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 8:06am

+ + diff --git a/doc/html/invoke.html b/doc/html/invoke.html new file mode 100644 index 00000000..ad90a028 --- /dev/null +++ b/doc/html/invoke.html @@ -0,0 +1,149 @@ +

Magic version 7.3 Usage

+ +
+ Basic usage:

+ + + +
+ + + + +
magic + [-noc[onsole]] + [-w[rapper]] + [-d devType] + [-T technology] + [file] +
+

+ + where:

+
+ -noconsole
+
+ (Tcl version only) Uses the calling terminal + for terminal-based command-line input. Otherwise, a Tk + console window is used. +
+ -wrapper
+
+ (Tcl version only) Magic layout windows use + the GUI wrapper, including cell and technology manager + windows, layer toolbar, and file menu. +
+ -d devType
+

+ (all versions) Select the graphics interface at runtime. + Specifying an invalid devType will result in a list + of known types. The possible values of devType are + determined at compile time, but the usual ones are + NULL (no graphics), X11, and + OpenGL. X11 is the usual default. +
+ -T technology
+
+ (all versions) + Select the appropriate technology (.tech27) file. + At present (this is on the to-do list), magic cannot change + technology after startup. So the technology file corresponding + to the layout to be loaded must be supplied to the command line + at startup. The default technology is scmos, which + is included with the magic source distribution. The complete + list of available technology files depends on what has been + installed on the system (see the technology + file page for details). +
+ file
+
+ (all versions) Load the layout (.mag) file file + into the layout window on startup. +
+
+ + Complete usage information:

+ +
+ + magic + [-noc[onsole]] + [-w[rapper]] + [-nowindow] + [-d devType] + [-T technology] + [-m monType] + [-D] + [file]
+
+ + where the additional options not covered above are:

+ +
+ -nowindow
+
+ (Tcl version only) Run without displaying an initial layout + window. This is used mainly for GUI wrapper scripts which + like to generate and handle their own windows. +
+ -m monType
+
+ (obscure) monType names a monitor type. + This is used in the search for the colomap file name, + which is designated + <tech>.<planes>.<mon>.cmap1. + The default is "std" (corresponding to + colormap file "mos.7bit.std.cmap1". The only other + monitor type for which colormaps exist in the distribution + is "mraster". This provides a way for users to + override the system color assignments. +
+ -D
+
+ (all versions) Run in Debug mode. +
+
+ + Obsolete usage information:

+ +
+ magic + [-g gPort] + [-i tabletPort] + [-F objFile saveFile] + ...
+
+ + where the additional options not covered above are:

+ +
+ -g gPort
+
+ (largely obsolete) gPort names a device to use + for the display. This was generally used in the past with + dual-monitor systems, especially Sun systems in which the + layout display might go to /dev/fb. +
+ -i tabletPort
+
+ (largely obsolete) tabletPort names a device to use + for graphics input. This has not been tested with modern + graphics tablet devices. It is ignored by the X11 and OpenGL + display interfaces. +
+ -F objFile saveFile
+
+ (largely obsolete) Create an executable file of + the current magic process, a core image snapshot + taken after all initialization. objFile + is the name of the original executable, and the + image will be saved in saveFile. This + only works on VAXen and SUNs running an old SunOS + (using a.out executables). +
+
+ +
+ diff --git a/doc/html/iroute.html b/doc/html/iroute.html new file mode 100644 index 00000000..fe2f5936 --- /dev/null +++ b/doc/html/iroute.html @@ -0,0 +1,124 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

iroute

+
+Do interactive point-to-point routing from the pointer cursor to the +cursor box +
+ +

Usage:

+
+ iroute option

+
+ where option may be one of the following: +
+
contacts [type] [parameter] [value...] +
Set route-contact parameters. parameter may be one of + the following keywords: +
+
active +
+
width +
+
cost +
+
+
help [option_name] +
Summarize iroute subcommands +
layers [type] [parameter] [value...] +
Set route-layer parameters. parameter may be one of + the following keywords: +
+
active +
+
width +
+
hCost +
+
vCost +
+
jogCost +
+
hintCost +
+
+
route node_name... +
Connect point to named node(s) +
saveParameters +
Write out all irouter parameters. These are written out + as command calls so they can be read back with the Tcl + source command. +
search rate|width +
Set parameters controlling the internal search for routes +
spacings type +
Set minimum spacing between route-type and arbitrary type +
verbosity level +
Control the amount of messages printed +
version +
Identify irouter version +
wizard parameter +
Set miscellaneous parameters. parameter may be one of + the following keywords: +
+
bloom +
+
boundsIncrement +
+
estimate +
+
expandDests +
+
penalty +
+
penetration +
+
window +
+
+
+
+
+ +

Summary:

+
+ The iroute command is. . . +
+ +

Implementation Notes:

+
+ iroute is implemented as a built-in command in magic. +
+ +

See Also:

+
+ route
+ garoute
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 11:11pm

+ + diff --git a/doc/html/irsim.html b/doc/html/irsim.html new file mode 100644 index 00000000..9606fd1e --- /dev/null +++ b/doc/html/irsim.html @@ -0,0 +1,78 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

irsim

+
+Invoke the irsim switch-level digital simulator. +
+ +

Usage:

+
+ irsim [args]

+
+ where args are any arguments to be passed to the irsim + program as they would from the command line. See the irsim + documentation for an explanation of its valid command-line + arguments. +
+
+ +

Summary:

+
+ The irsim command starts the irsim simulator. While + previous versions of magic did this by forking the irsim + process, Tcl-based magic can load the Tcl-based irsim + as a package directly into the interpreter. Commands for irsim + are added to the Tcl namespace and are available directly from the the + magic command line.

+ + As a Tcl script, the irsim command attempts to set up the + simulation arguments to ensure proper startup. It also checks for + a valid .sim file matching the layout, and generates one + if it does not already exist.

+ + A number of commands are available for viewing signal values directly + on the layout. For a complete description of these commands and + the Tcl-based irsim simulation environment, see the documentation + on irsim.

+

+ +

Implementation Notes:

+
+ irsim is implemented as a Tcl procedure that loads the Tcl-package + based version of irsim, then executes its startup procedure. The + irsim Tcl package itself is compiled and installed separately + from magic. +
+ +

See Also:

+
+ ext2sim
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 1:01am

+ + diff --git a/doc/html/label.html b/doc/html/label.html new file mode 100644 index 00000000..5e1b220a --- /dev/null +++ b/doc/html/label.html @@ -0,0 +1,79 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

command_name

+
+Place a label in the layout +
+ +

Usage:

+
+ label string [position [layer]]

+
+ where string is the text of the label, position + may be any valid direction + in magic, and layer may be any valid layer in + the technology. +
+
+ +

Summary:

+
+ The label command places a label on the layout. The label + is marked by a point, line, or rectangle, depending on the size + of the cursor box. If the area under the cursor box contains + exactly one type, the label will be "attached" to that type; that + is, the label will name the network of the node containing that + type. If the area under the cursor box contains multiple layers, + one will be chosen for attachment to the label. If there are + multiple network nodes under the cursor box, the result may not + be what the user intended; in such cases, the user should specify + which layer the label should be attached to, so that the + appropriate network node will be labeled.

+ + The label text is placed to one side of the marker in the + direction indicated by the position argument. For + example, "label text north" will draw the label string + "text" to the north (above) the marker.

+ + Labels cannot be directly modified; modifications should be + handled by first erasing the label with "erase label" + and then redrawing. +

+ +

Implementation Notes:

+
+ label is implemented as a built-in command in magic. +
+ +

See Also:

+
+ port
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 1:11am

+ + diff --git a/doc/html/lef.html b/doc/html/lef.html new file mode 100644 index 00000000..f7e2fb46 --- /dev/null +++ b/doc/html/lef.html @@ -0,0 +1,138 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

lef

+
+LEF-format input and output +
+ +

Usage:

+
+ lef option

+
+ where option may be one of the following: +
+
read [filename] +
Read a LEF file named filename[.lef] +
[filename] -import +
Read a LEF file. Import standard cells from .mag + files +
write [cell] +
Write LEF for the current or indicated cell. +
writeall +
Write all cells including the top-level cell. This might + be appropriate if the top-level cell is a compendium of + standard cells. +
writeall -notop +
write all subcells of the top-level cell, but not the top-level + cell itself. This is appropriate for generating a LEF library + from a layout, for which the layout itself would be written to + a DEF file. +
help +
Print help information +
+
+
+ +

Summary:

+
+ The lef command writes LEF-format files, which are files + containing technology information and information about the content + of standard cells. It is used in conjunction with the def + command to read databases of routed digital standard-cell layouts. + The .lef file shares some information with the technology + file in magic. At a minimum, to read .lef files + from third-party sources, the technology file should have a + lef section that maps magic layers to layer names that are + found in the .lef and .def files. Without + this information, magic will attempt to make an educated + guess about the routing layers, which normally will be named + in an obvious manner such as "metal1", "metal2", etc. The + technology file section may be necessary to handle more complicated + input such as obstruction layers. Most other aspects of a + technology will be contained within the .lef file. + When writing .lef files, magic will use internal + layer names for the routing layers if no other information is + present in the lef section of the technology file.

+ + Because the lef format allows standard cells to be minimally + defined (for purposes of protecting intellectual property), often + the .lef file contains no actual layout information for + the standard cells. magic provides a command option + "-import". When specified, for each macro cell in the + input .lef file, magic will look for a .mag + file of the same name. If found, it will be loaded and used in + preference to the definition in the lef file.

+ + Magic uses the port mechanism for labels to determine + what are the standard cells in a design. All cells containing + port labels will be considered standard cells when writing + a .lef file. Ports retain various bits of information + used by the LEF/DEF definition, including the port use and + direction. See the port documentation for more information.

+ + Macro cell properties common to the LEF/DEF definition but that + have no corresponding database interpretation in magic + are retained using the cell property method in magic. + There are specific property names associated with the LEF format. + These are as follows: +

+
LEFclass +
Corresponds to the value of CLASS for a macro + cell in the LEF format. +
LEFsource +
Corresponds to the value of SOURCE for a macro + cell in the LEF format. +
LEFsymmetry +
Corresponds to the vlaue of SYMMETRY for a macro + cell in the LEF format. +
+ + Normally, when importing a LEF/DEF layout into magic, one + will first execute a lef read command followed by a + def read command. Likewise, when writing a layout, one + will first execute a lef writeall -notop command followed + by a def write command. +
+ +

Implementation Notes:

+
+ lef is implemented as a built-in command in magic. + Only the critical portion of the LEF syntax has been implemented. + In particular, simulation-specific properties of the technology + and of macro cells are not implemented. +
+ +

See Also:

+
+ def
+ port
+ property
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 1:43am

+ + diff --git a/doc/html/load.html b/doc/html/load.html new file mode 100644 index 00000000..b6841d50 --- /dev/null +++ b/doc/html/load.html @@ -0,0 +1,97 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

load

+
+Load a cell into the layout window +
+ +

Usage:

+
+ load [cellname [scaled n [d]]] + [-force]

+
+ where cellname is the name of a cell that presumably + exists either in the database memory or on disk as a + .mag file. n and d + are the numerator and denominator, respectively, of a + magnification factor, if it is desired to load the cell at a + different scale than it was written. d defaults to 1 + if not specified. +
+
+ +

Summary:

+
+ The load command loads a cell into the database and + displays it in the current layout window (if available). If + the cell is not already in the database memory, it is loaded + from disk. If it cannot be found on disk, then a new cell + definition of name cellname is created and loaded + into the window.

+ + By default, magic loads a cell from disk only if the + technology name matches the current technology. Historically, + this has led to most technologies being named "scmos" which + undermines the purpose of having a technology name in the + first place. In magic-7.2 and 7.3, this behavior can be + overridden with the -force option. magic will + read the cell to the extent that layer names match between + the current technology and the technology of the file.

+ + The -force option and scaled option can be + used together to port layouts from one technology to + another. The scaled option implements a scale + conversion during input by redefining the ratio of lambda + to internal units during the load. This is useful if + a cell was written in a lambda-based technology but needs + to be read into a vendor-rules-based technology with a + fine internal scale such as 0.1 micron per internal unit. + The scaled option may also be used simply to resize + cell geometry, although this is generally only useful to + do for layout such as logos and text lettering drawn in + routing layers.

+ + Note that if it is not desired to have cellname + created if not found on disk (e.g., because the path for + the cell was missing from the search path), the database + can be updated with the flush command or the + cellname delete command. +

+ +

Implementation Notes:

+
+ load is implemented as a built-in command in magic. +
+ +

See Also:

+
+ xload
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 2:02am

+ + diff --git a/doc/html/logcommands.html b/doc/html/logcommands.html new file mode 100644 index 00000000..9e4ec4ca --- /dev/null +++ b/doc/html/logcommands.html @@ -0,0 +1,55 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

logcommands

+
+Log all commands into a file +
+ +

Usage:

+
+ logcommands [file [update]]

+
+ where file is the name of the log file to write to. +
+
+ +

Summary:

+
+ The logcommands command tells magic to write all + command-line commands and button pushes to the log file + named file. If update is specified, a + screen update is generated after each command executes. +
+ +

Implementation Notes:

+
+ logcommands is implemented as a built-in command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 2:06am

+ + diff --git a/doc/html/macro.html b/doc/html/macro.html new file mode 100644 index 00000000..ea790a3d --- /dev/null +++ b/doc/html/macro.html @@ -0,0 +1,102 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

macro

+
+Define or print a macro called char +
+ +

Usage:

+
+ macro [window_type] [key [value]]

+
+ where key is the name of a valid key (see below), and + value is a magic command-line command. If + present, window_type must be one of the four window + types accepted by the specialopen command: layout, + color, netlist, and wind3d. If omitted, + the layout window is assumed by default, unless the command has + been called from inside a window (using the colon or semicolon + escape to the command-line), in which case that window type is + assumed. +
+
+ +

Summary:

+
+ The macro command translates keystrokes typed into + a layout window into magic command-line commands. + When the key key is pressed in a layout window, the + command stored in value is executed relative to that + layout window. The default bindings are specified in the + system .magic file, read at startup. These macros + may be arbitrarily rebound using the macro command.

+ + A key macro may be unbound from a command by + passing an empty string ("") for the value.

+ + key is any valid name for a keyboard keypress event. + In its simplest form, this may just be the name of the key, + such as "g" or "X". The space bar key must be quoted in + double-quotes; most other characters may be unquoted. + Control characters may be specified by the two-character + combination of the carat ("^") key followed by a capital + letter, such as "^Z". The use of embedded control characters + is deprecated, as it is incompatible with Tcl syntax.

+ + key may also be specified as any valid X11 name for + a key as defined in the include file keysymdef.h + on UNIX systems. This allows specification of function + keys such as "XK_F8" or keypad keys such as "XK_KP_Right".

+ + Buttons are treated just like keys for the purpose of + defining macros. While the official names for buttons + in keysymdef.h are "XK_Pointer_Button_1", + etc., the macro command accepts the abbreviated + forms Button1, and so forth.

+ + + Finally, key modifiers may be prepended to the key name. + Valid key modifiers are Shift_, Control_, + Alt_, and Meta_, and may be coupled in any + combination. Mouse buttons may also be combined with key + modifiers, so, for example, Shift_Button1 is a legal, + unique binding.

+

+ +

Implementation Notes:

+
+ macro is implemented as a built-in window command in magic. +
+ +

See Also:

+
+ imacro
+
+ +

+ + + +
Return to command index +
+

Last updated: November 10, 2004 at 10:34am

+ + diff --git a/doc/html/maketoolbar.html b/doc/html/maketoolbar.html new file mode 100644 index 00000000..f65844d6 --- /dev/null +++ b/doc/html/maketoolbar.html @@ -0,0 +1,101 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

maketoolbar

+
+Generate the GUI layout window toolbar. +
+ +

Shortcuts:

+
+ Menu item Options->Toolbar implements the command + maketoolbar. +
+ +

Usage:

+
+ maketoolbar frame_name

+
+ where frame_name is the Tk path name of a GUI layout + window frame (e.g., ".layout1", ".layout2"). +
+
+ +

Summary:

+
+ The maketoolbar command generates the toolbar for the + GUI layout window. The toolbar contains a set of buttons + representing each layer type in the technology file. + Each toolbar button has bindings for mouse buttons and + keys to implement shortcut commands in magic. + While the mouse pointer is inside the boundary of the + toolbar button, the name of the layer represented by the + toolbar is printed in the title bar of the window.

+ +

+
+
+ Figure 1. The GUI toolbar for the default scmos technology. +
+
+ + The default bindings for the toolbar buttons and the magic + commands they invoke are as follows: +
+
+
Button-1 +
see layername +
Button-3 +
see no layername +
Button-2 +
paint layername +
Shift-Button-2 +
erase layername +
Key-p +
paint layername +
Key-e +
erase layername +
Key-s +
select more area layername +
Key-S +
select less area layername +
+
+ + The toolbar is not present on window startup due to timing + problems with several window managers that prevents the + correct measurement of window height. +
+ +

Implementation Notes:

+
+ maketoolbar is implemented as a Tcl procedure in the + GUI wrapper script. +
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 3:12am

+ + diff --git a/doc/html/measure.html b/doc/html/measure.html new file mode 100644 index 00000000..7c2d9a95 --- /dev/null +++ b/doc/html/measure.html @@ -0,0 +1,66 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

measure

+
+Create a ruler to measure the distance between two points on a layout. +
+ +

Usage:

+
+ measure [orient]

+
+ +

Summary:

+
+ The measure command is a script that creates a ruler + to measure the distance between two points on a layout. The + ruler is positioned within the bounds of the cursor box. The + option orient may be "horizontal", "vertical", + or "auto", and determines whether the ruler measures + a width or a height. Without any option, orientation auto + is assumed. Automatic orientation chooses the longer dimension + of the cursor box as the dimension to measure. Dimensions are + printed in microns. +
+ +

Implementation Notes:

+
+ measure is implemented as a Tcl procedure in the "tools" + script. The ruler itself is implemented as elements (see the + element command), including line elements for the ruler + and a text element for the printed dimension. +
+ +

See Also:

+
+ unmeasure
+ element
+
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 9:12pm

+ + diff --git a/doc/html/move.html b/doc/html/move.html new file mode 100644 index 00000000..36daa736 --- /dev/null +++ b/doc/html/move.html @@ -0,0 +1,86 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

move

+
+Move the cursor box and the selection. +
+ +

Shortcuts:

+
+ Key macro m implements the command move (no arguments).
+ Key macro Keypad-8 implements the command move n 1
+ Key macro Keypad-6 implements the command move e 1
+ (and so forth for all 8 compass rose directions). +
+ +

Usage:

+
+ move [option]

+
+ where option is one of the following: +
+
direction + [distance] +
Move the selection relative to the original + position in the direction direction by + an amount distance. +
to x y +
Move the selection to the coordinate location + specified by the coordinate pair x y. +
+
+
+ +

Summary:

+
+ The move command erases the current selection from + its current position and moves it according to the command + arguments. + Without arguments, the lower-left hand corner of the + selection is moved to the current cursor position (the X11 + cursor, not the magic "cursor box"). With arguments + direction and distance, the selection is moved + relative to the original in the indicated direction by the + indicated amount. The default distance is 1 unit (usually + lambda; see distance for + further explication).

+

+ +

Implementation Notes:

+
+ move is implemented as a built-in magic command. +
+ +

See Also:

+
+ direction
+ distance
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 3:19am

+ + diff --git a/doc/html/netlist.html b/doc/html/netlist.html new file mode 100644 index 00000000..5e843cb0 --- /dev/null +++ b/doc/html/netlist.html @@ -0,0 +1,81 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

netlist

+
+Netlist operations for use with the "netlist tool" in a layout window. +
+ +

Usage:

+
+ netlist option

+
+ wher option may be one of the following: +
+
help +
Print usage information +
select +
Select the network nearest the cursor +
join +
Join the current network and the network containing the + terminal nearest the cursor. +
terminal +
Toggle the terminal nearest the cursor into or out of the + current network. +
+
+
+ +

Summary:

+
+ The netlist command works with the "netlist tool" and is the + interface between the layout window and the netlist window as + generated by the "specialopen netlist" command. The + command options, outlined above, allow interactive creation of + netlists from a layout. Note that this is only interface code; + most manipulation of the netlist is handled by the netlist + window commands (see the section in the + table of contents on the netlist window + command set). +
+ +

Implementation Notes:

+
+ netlist is implemented as a built-in command in magic. + Prior to magic-7.3 revision 61, these functions were only available + as built-in button callbacks. They have been changed to command-line + commands with the switch to handling buttons like keys, with macro + bindings. +
+ +

See Also:

+
+ specialopen netlist
+
+ +

+ + + +
Return to command index +
+

Last updated: November 10, 2004 at 10:44am

+ + diff --git a/doc/html/netlist/add.html b/doc/html/netlist/add.html new file mode 100644 index 00000000..cb64f7aa --- /dev/null +++ b/doc/html/netlist/add.html @@ -0,0 +1,59 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

add

+
+Add the indicated terminal to the net of the other indicated terminal. +
+ +

Usage:

+
+ add term1 term2

+
+ where term1 and term2 are the names of netlist + terminals. +
+
+ +

Summary:

+
+ The add command adds an additional terminal term1 + to a network. The network is specified by identifying a second + terminal term2 belonging to the network. If term1 + previously belonged to another network, it is removed from that + network. +
+ +

Implementation Notes:

+
+ add is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/cleanup.html b/doc/html/netlist/cleanup.html new file mode 100644 index 00000000..37b14c42 --- /dev/null +++ b/doc/html/netlist/cleanup.html @@ -0,0 +1,67 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

cleanup

+
+Interactively clean up the netlist +
+ +

Usage:

+
+ cleanup +
+ +

Summary:

+
+ The cleanup command performs an interactive netlist cleanup. + It checks the current netlist for terminals that aren't present in + the design and for nets with only one terminal. When found, + the user is informed and an action requested.

+ + Requested actions are as follows: +

+
dterm +
Delete the terminal +
dnet +
Delete the net +
skip +
Take no action on this problem +
abort +
End the cleanup command immediately with no + further checks, requests, or actions. +
+
+ +

Implementation Notes:

+
+ cleanup is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/cull.html b/doc/html/netlist/cull.html new file mode 100644 index 00000000..88626d69 --- /dev/null +++ b/doc/html/netlist/cull.html @@ -0,0 +1,53 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

cull

+
+Remove fully-wired nets from the current netlist +
+ +

Usage:

+
+ cull +
+ +

Summary:

+
+ The cull command checks the current netlist against + routing in the edit cell and removes nets that are already + wired correctly. +
+ +

Implementation Notes:

+
+ cull is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/dnet.html b/doc/html/netlist/dnet.html new file mode 100644 index 00000000..2688feb2 --- /dev/null +++ b/doc/html/netlist/dnet.html @@ -0,0 +1,62 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

dnet

+
+Delete the net(s) containing the indicated name(s), or the +current net if no name is given. +
+ +

Usage:

+
+ dnet name1 name2 ...

+
+ where name1, name2, etc., are net names. +
+
+ +

Summary:

+
+ The dnet command removes networks from the current + netlist. The networks are specified by names of terminals + that are part of the network. +
+ +

Implementation Notes:

+
+ dnet is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

See Also:

+
+ dterm
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/dterm.html b/doc/html/netlist/dterm.html new file mode 100644 index 00000000..56cf6b27 --- /dev/null +++ b/doc/html/netlist/dterm.html @@ -0,0 +1,62 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

dterm

+
+Delete terminals from nets +
+ +

Usage:

+
+ dterm name1 name2 ...

+
+ where name1, name2, etc., are the + names of netlist terminals. +
+
+ +

Summary:

+
+ The dterm command removes terminals from a network + in the current netlist. The terminals are specified by + name. +
+ +

Implementation Notes:

+
+ dterm is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

See Also:

+
+ dnet
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/extract.html b/doc/html/netlist/extract.html new file mode 100644 index 00000000..7de3442a --- /dev/null +++ b/doc/html/netlist/extract.html @@ -0,0 +1,55 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

extract

+
+Generate a net for terminals connected to box +
+ +

Usage:

+
+ extract +
+ +

Summary:

+
+ Starting from paint underneath the box, the extract + command finds all electrically-connected material in the + edit cell, locates terminals touched by the material, and + puts the terminals into a new network in the current + netlist. +
+ +

Implementation Notes:

+
+ extract is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/find.html b/doc/html/netlist/find.html new file mode 100644 index 00000000..a3213386 --- /dev/null +++ b/doc/html/netlist/find.html @@ -0,0 +1,59 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

find

+
+Find all occurrences of any labels matching the indicated pattern +beneath the box (on layers, if specified) and leave as feedback. +
+ +

Usage:

+
+ find pattern [layers]

+
+ where pattern is a text pattern to match to labels, + and layers is an optional list of layers on which + to restrict the search for connected labels. +
+
+ +

Summary:

+
+ The find command creates feedback areas for all instances + of labels containing the indicated pattern that lie beneath the + box. +
+ +

Implementation Notes:

+
+ find is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/flush.html b/doc/html/netlist/flush.html new file mode 100644 index 00000000..d365ae59 --- /dev/null +++ b/doc/html/netlist/flush.html @@ -0,0 +1,59 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

flush

+
+Short summary. +Flush changes to the indicated netlist, or the current netlist if +unspecified. +
+ +

Usage:

+
+ flush [netlist]

+
+ where netlist is the name of a netlist. +
+
+ +

Summary:

+
+ The flush command flushes changes to the indicated + netlist, reverting the netlist to the last form read from + the netlist file. If the netlist is unspecified, the + current netlist is flushed. +
+ +

Implementation Notes:

+
+ flush is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/joinnets.html b/doc/html/netlist/joinnets.html new file mode 100644 index 00000000..de468e44 --- /dev/null +++ b/doc/html/netlist/joinnets.html @@ -0,0 +1,65 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

joinnets

+
+Join the nets containing the two indicated terminals. +
+ +

Usage:

+
+ joinnets term1 term2

+
+ where term1 and term2 are names of netlist + terminals. +
+
+ +

Summary:

+
+ The joinnets command joins two networks together into a single + network. The two networks are specified by naming a terminal on + each network. If either terminal is not connected to a network, + no action is taken (use the add command to add an + unconnected terminal to a network). +
+ +

Implementation Notes:

+
+ joinnets is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. + This command was previously called join, and may be + used as that abbreviation in the non-Tcl version of magic. + However, the command name join conflicts with the Tcl + command of the same name, and its syntax is not distinct. + Therefore, in Tcl-based magic, the command name join + is interpreted as the Tcl command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/netlist.html b/doc/html/netlist/netlist.html new file mode 100644 index 00000000..4823eba2 --- /dev/null +++ b/doc/html/netlist/netlist.html @@ -0,0 +1,60 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

netlist

+
+Switch current netlist to the netlist with the given filename, or +if unspecified, the edit cell name with the file suffix .net. +
+ +

Usage:

+
+ netlist [name]

+
+ where name is the filename of a netlist, with or without + the file suffix .net. +
+
+ +

Summary:

+
+ The netlist command sets the indicated name to be the + current netlist. It searches for a file of the name + name.net and loads the contents of this file. + If no name is specified, then the name of the current + edit cell is used. +
+ +

Implementation Notes:

+
+ netlist is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/print.html b/doc/html/netlist/print.html new file mode 100644 index 00000000..5604622f --- /dev/null +++ b/doc/html/netlist/print.html @@ -0,0 +1,58 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

print

+
+Print all terminals in the indicated net, or in the current net +if the name is unspecified. +
+ +

Usage:

+
+ print [name]

+
+ where name is the name of a network. +
+
+ +

Summary:

+
+ The print command reports all terminals connected + to the indicated network. If no network name is specified, + then all terminals connected to the current network are + listed. +
+ +

Implementation Notes:

+
+ print is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/pushbutton.html b/doc/html/netlist/pushbutton.html new file mode 100644 index 00000000..07f89c46 --- /dev/null +++ b/doc/html/netlist/pushbutton.html @@ -0,0 +1,60 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

pushbutton

+
+Execute the default function associated with a mouse button event. +
+ +

Usage:

+
+ pushbutton button

+
+ where button is one of left, middle, or right. +
+
+ +

Summary:

+
+ The pushbutton command invokes the function "traditionally" + associated with the indicated mouse button. However, in Magic-7.3, + button actions are treated as macros, and so the button macros + are defined, by default, to call the pushbutton command for + the indicated button. The button actions no longer recognize + button-up events. The action taken by the command depends on where + in the netlist window the button was pressed. +
+ +

Implementation Notes:

+
+ pushbutton is implemented as a built-in netlist + window command in magic. It overrides the default + window client pushbutton command. +
+ +

+ + + +
Return to command index +
+

Last updated: November, 2004

+ + diff --git a/doc/html/netlist/ripup.html b/doc/html/netlist/ripup.html new file mode 100644 index 00000000..ec180882 --- /dev/null +++ b/doc/html/netlist/ripup.html @@ -0,0 +1,56 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

ripup

+
+Rip up edit cell paint connected to paint under box, or rip up the +current netlist if invokes as "ripup netlist" +
+ +

Usage:

+
+ ripup [netlist] +
+ +

Summary:

+
+ The ripup command performs one of two functions. Invoked + as ripup netlist, it removes the painted material routing + all nets in the current netlist. Invoked as ripup, it + removes the painted material connected to any paint found under + the box. +
+ +

Implementation Notes:

+
+ ripup is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/savenetlist.html b/doc/html/netlist/savenetlist.html new file mode 100644 index 00000000..2c637fd7 --- /dev/null +++ b/doc/html/netlist/savenetlist.html @@ -0,0 +1,62 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

savenetlist

+
+Write out the current netlist to a .net file. +
+ +

Usage:

+
+ savenetlist [file]

+
+ where file is the optional filename to write output to. +
+
+ +

Summary:

+
+ The savenetlist command writes the current netlist + to the indicated .net file file. If unspecified, + and the netlist was read from a file, then the netlist is saved + back to that file. +
+ +

Implementation Notes:

+
+ savenetlist is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

See Also:

+
+ writeall
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/shownet.html b/doc/html/netlist/shownet.html new file mode 100644 index 00000000..98e98aad --- /dev/null +++ b/doc/html/netlist/shownet.html @@ -0,0 +1,61 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

shownet

+
+Highlight edit cell paint connected to paint under the box. +
+ +

Usage:

+
+ shownet [erase] +
+ +

Summary:

+
+ The shownet command highlights (using highlights) + the network connected to any painted material under the box. + Although the highlights look like feedback entries, they are + actually separate, and cannot be removed by the + "feedback clear". The command option + "shownet erase" will remove the highlighted entries. +
+ +

Implementation Notes:

+
+ shownet is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

See Also:

+
+ showterms
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/showterms.html b/doc/html/netlist/showterms.html new file mode 100644 index 00000000..751a9eba --- /dev/null +++ b/doc/html/netlist/showterms.html @@ -0,0 +1,62 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

showterms

+
+Generate feedback for all terminals in netlist +
+ +

Usage:

+
+ showterms +
+ +

Summary:

+
+ The showterms command highlights (using feedback highlights) + all terminals in the current netlist. These feedback entries may + be cleared with the "feedback clear" command. Note, + however, that while the showterms command must be executed + from the netlist window, the feedback command must be + executed from the layout window. +
+ +

Implementation Notes:

+
+ showterms is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

See Also:

+
+ shownet
+ feedback +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/trace.html b/doc/html/netlist/trace.html new file mode 100644 index 00000000..328e8b57 --- /dev/null +++ b/doc/html/netlist/trace.html @@ -0,0 +1,60 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

trace

+
+Highlight material connected to the terminals of the +indicated network, or of the current network if no network name +is specified. +
+ +

Usage:

+
+ trace [name]

+
+ where name is the name of a network. +
+
+ +

Summary:

+
+ The trace command highlights (using feedback highlights) + the network connected to the terminals of the indicated + network, where the network is indicated by name. If + no network name is specified, then the current network is + highlighted. +
+ +

Implementation Notes:

+
+ trace is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/verify.html b/doc/html/netlist/verify.html new file mode 100644 index 00000000..27ab99c2 --- /dev/null +++ b/doc/html/netlist/verify.html @@ -0,0 +1,55 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

verify

+
+Make sure the current netlist is correctly wired +
+ +

Usage:

+
+ verify +
+ +

Summary:

+
+ The verify command checks the current netlist against + routing in the edit cell to ensure that all the nets are + implemented exactly as specified by the netlist. If correctly + verified, no action is taken. If problems are found, these + are highlighted with feedback entries. +
+ +

Implementation Notes:

+
+ verify is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/netlist/writeall.html b/doc/html/netlist/writeall.html new file mode 100644 index 00000000..17cfb329 --- /dev/null +++ b/doc/html/netlist/writeall.html @@ -0,0 +1,67 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

writeall

+
+Write out all modified netlists. +
+ +

Usage:

+
+ writeall +
+ +

Summary:

+
+ The writeall command scans through all the netlists that + are loaded, finds any that have been modified, and queries the + user for an action. The actions are: +
+
write +
Write the netlist file. +
skip +
Ignore the network and do not update its netlist file. +
abort +
Terminate the writeall command with no further + files modified. +
+
+ +

Implementation Notes:

+
+ writeall is implemented as a built-in netlist + window command in magic. It can only be invoked from + a window created with the specialopen netlist command. +
+ +

See Also:

+
+ savenetlist
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/openwindow.html b/doc/html/openwindow.html new file mode 100644 index 00000000..21754f0e --- /dev/null +++ b/doc/html/openwindow.html @@ -0,0 +1,81 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

openwindow

+
+Open a new (non-GUI) layout window with indicated name, bound to indicated cell +
+ +

Shortcuts:

+
+ Key macro o implements the command openwindow. This + macro is disabled when using the GUI wrapper. +
+ +

Usage:

+
+ openwindow [cell] [name]

+
+ where cell is the name of a cell to be loaded into the + new window, and name is the Tk path name of a top-level + window (see below). An empty string or Tcl NULL list "{}" for + cell will cause the default cell "(UNNAMED)" to be loaded. +
+
+ +

Summary:

+
+ The openwindow command opens a new layout window. Without + arguments, a new layout window named "magicn" is created, + where n is the index of the nth window to be + created. Without a named cell, the new window is loaded with + a copy of the cell that was present in the last generated layout + window.

+ + The use of parameter name is used in conjunction with a + wrapper script to attach the layout window to an existing Tk + frame window. +

+ +

Implementation Notes:

+
+ openwindow is implemented as a built-in magic + window command. It should not be used with the GUI wrapper + (invoked with magic -w); instead, the openwrapper + function should be used. Note that it is possible to use + this command in batch mode, although there is no useful + reason to do so. +
+ +

See Also:

+
+ closewindow
+ openwrapper
+
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 9:03pm

+ + diff --git a/doc/html/openwrapper.html b/doc/html/openwrapper.html new file mode 100644 index 00000000..d88b4e81 --- /dev/null +++ b/doc/html/openwrapper.html @@ -0,0 +1,73 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

openwrapper

+
+Open a GUI layout window and all of its associated frames. +
+ +

Shortcuts:

+
+ Menu option File->New window implements the command + openwrapper in the GUI layout window. +
+ +

Usage:

+
+ openwrapper [cellname] frame_name]]

+
+ where frame_name is the Tk path name of the top-level + layout GUI window frame. By default, this name is .layout1, + .layout2, etc., for successive layout windows. + cellname is the name of a cell to be loaded into the + window. Options behave the same was as they do for the non-GUI + openwindow command. +
+
+ +

Summary:

+
+ The openwrapper command creates a new layout window in the + Tcl version of magic. It is only applicable when magic is + invoked with the GUI wrapper, using magic -w, and + supercedes the built-in command openwindow. +
+ +

Implementation Notes:

+
+ openwrapper is implemented as a Tcl procedure in the + GUI wrapper script. +
+ +

See Also:

+
+ openwindow
+ closewrapper
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 5:40am

+ + diff --git a/doc/html/paint.html b/doc/html/paint.html new file mode 100644 index 00000000..0db2b4d5 --- /dev/null +++ b/doc/html/paint.html @@ -0,0 +1,76 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

paint

+
+Paint mask information into the current edit cell +
+ +

Shortcuts:

+
+ Key interactive macro p implements the command paint and + waits for input of the layer type.
+ Mouse button 2 implements the command paint cursor when using + the "box tool" in a layout window.
+
+ +

Usage:

+
+ paint layers|cursor

+
+ where layers is a comma-separated list of types to paint. +
+
+ +

Summary:

+
+ The paint command paints layer types in the current edit + cell inside the area of the cursor box.

+ + Note that some layers, such as DRC layers, cannot be painted. + Elements are painted with the element command and + feedback areas are painted using the feedback command.

+ + The "paint cursor" option picks the layers underneath the + position of the (X11) cursor and fills the cursor box with these + types. However, when no material (e.g., "space") is present under + the cursor, then all material and labels are erased from the + area of the cursor box. +

+ +

Implementation Notes:

+
+ paint is implemented as a built-in command in magic. +
+ +

See Also:

+
+ erase
+
+ +

+ + + +
Return to command index +
+

Last updated: November 8, 2004 at 3:02pm

+ + diff --git a/doc/html/path.html b/doc/html/path.html new file mode 100644 index 00000000..41138c7f --- /dev/null +++ b/doc/html/path.html @@ -0,0 +1,74 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

path

+
+Modify or query magic's search paths +
+ +path [search|cell|sys] [[+]path] + +

Usage:

+
+ path [search|cell|sys] + [[+]path]

+
+
+ +

Summary:

+
+ The path command queries and manipulates the various + search paths used by magic. Without arguments, path + search is assumed. The three search paths are: +
+
search +
The search path for layout files. +
cell +
Search path for tutorial cells. +
sys +
Search path for technology files. +
+
+ + The + option allows the path component path to be + appended to the indicated search path. Otherwise, the indicated + search path is replaced by the contents of path. + +

Implementation Notes:

+
+ path is implemented as a built-in command in magic. + The use path search +path supercedes the addpath + command, as the path command is more general. +
+ +

See Also:

+
+ addpath
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 5:54am

+ + diff --git a/doc/html/peekbox.html b/doc/html/peekbox.html new file mode 100644 index 00000000..1924f937 --- /dev/null +++ b/doc/html/peekbox.html @@ -0,0 +1,60 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

peekbox

+
+Query the last saved cursor box position +
+ +

Usage:

+
+ peekbox

+
+ +

Summary:

+
+ The peekbox command sets the cursor box to the position + of the box last saved with the pushbox command. This + is like the popbox command except that the box is left + on the stack. +
+ +

Implementation Notes:

+
+ peekbox is implemented as a Tcl procedure in the "tools" + script. It is useful when writing automated layout-generating + Tcl scripts. +
+ +

See Also:

+
+ pushbox
+ popbox
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 5:59am

+ + diff --git a/doc/html/plot.html b/doc/html/plot.html new file mode 100644 index 00000000..2bcc1e88 --- /dev/null +++ b/doc/html/plot.html @@ -0,0 +1,163 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

plot

+
+Hardcopy plotting +
+ +

Usage:

+
+ plot option

+
+ where option may be one of the following: +
+
postscript file [layers] +
Generate a PostScript file of layout underneath the box. +
pnm file [scale [layers]] +
Generate a .pnm ("portable anymap") file of + layout underneath the box. The output size is propotional + to scale, where a scale of 1 is one output pixel per + magic internal unit. The default scale + value, if unspecified, is 0.5. +
parameters [name value] +
Set or print out plotting parameters (see Summary below). +
help +
Print help information +
+
+
+ +

Summary:

+
+ The plot command generates hardcopy plots of a layout. + The use of plot for any particular output format requires + that the parameters of the format be defined in the plot + section of the technology file. However, from magic-7.3.56, the + PNM handler will create a default set of output styles from the + existing layout styles for the technology. This makes plot + pnm compatible with all technology files, regardless + of whether or not a section exists for "style pnm".

+ + Each plot format has its own set of parameters, but all + parameters are controlled with the plot parameters option. + Valid parameters and their defaults are as follows: +

+ General parameters: + + + +
parameter name default value
showCellNames true
+ PostScript parameters: + + + + + + + + + + + + + + + + + + + + + + + +
parameter name default value explanation
PS_cellIdFont /Helvetica Font used for writing cell use IDs
PS_cellNameFont /HelveticaBold Font used for writing cell definition names
PS_labelFont /Helvetica Font used for writing label text
PS_cellIdSize 8 Font size for writing cell use IDs (in points)
PS_cellNameSize 12 Font size for writing cell definition names (in points)
PS_labelSize 12 Font size for writing label text (in points)
PS_boundary true Whether to draw boundaries around layers in addition to + fill patterns
PS_width 612 (8.5in) Page width of the target output
PS_height 792 (11in) Page height of the target output
PS_margin 72 (1in) Minimum margin to allow on all sides of the output page
+ PNM parameters: + + + + + + + + + +
parameter name default value explanation
pnmmaxmem 65536 Maximum memory (in KB) to use to generate output. Larger + values allow larger chunks of the layout to be processed + at a time. Normally, anything larger than the default + will just take a long time to render, so it's better + to leave it alone and let the plot pnm routine + downsample the image to fit in memory if the size + of the layout requires it.
pnmbackground 255 Value of the background, where 0=black and 255=white. + White is default to match the printed page, which is + where the plots usually end up. A value of 200 is + approximately the default background color in magic. +
pnmdownsample 0 Number of bits to downsample the original layout. + In the first pass, one pixel is generated for each + n magic internal units in each of x and y, + where n is the downsampling value. + Each downsampling bit therefore represents a factor + of 4 in decreased computation time. + Generally speaking, downsampling causes information to + be lost in the translation from layout to the PNM file. + However, if the grid has been scaled from the original + lambda, then downsampling up to the scale factor will + have no impact on the output other than speeding up + the rendering (because the minimum feature size is + still in lambda, so no feature will be overstepped by + the downsampling). For example, for a grid scaling + of 1:10 the proper downsampling would be 3 bits. + Note that layouts that are too large for the allocated + memory blocksize pnmmaxmem will force + downsampling regardless of the value of + pnmdownsample.
+
+ + PostScript plotting is best suited for drawing small layouts with + relatively few components. PNM plotting is best suited for drawing + large layouts. For chip-size layouts, the PNM plots are virtually + identical to chip photographs. From magic version 7.3.56, plotting + PNM files requires no special entries in the technology file. + Although such entries can fine-tune the output, this is usually + not necessary. Also, since version 7.3.56, magic makes intelligent + decisions about memory usage, so it's generally not necessary to + change the PNM plot parameters. +
+ +

Implementation Notes:

+
+ plot is implemented as a built-in command in magic.

+ Original plot styles versatec and gremlin have been + removed, but shells of the code are retained so that magic doesn't + complain when encountering styles for these types in a technology + file. +

+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 3:24pm

+ + diff --git a/doc/html/plow.html b/doc/html/plow.html new file mode 100644 index 00000000..be49aa27 --- /dev/null +++ b/doc/html/plow.html @@ -0,0 +1,94 @@ + + + + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

plow

+
+Layout stretching and compaction +
+ +

Usage:

+
+ plow option

+
+ where option may be one of the following: +
+
direction +
Where direction may be any valid Manhattan + direction, and + causes the plow to be moved in that direction. +
boundary +
Set boundary around area plowing may affect +
help +
Print help information +
horizon n +
Set the horizon for jog introduction to n lambda units. +
jogs +
Reenable jog insertion (set horizon to 0) +
selection [direction [distance]] +
Plow the selection in the indicated + direction for the indicated + distance. +
straighten +
Automatically straighten jogs after each plow +
noboundary +
Remove boundary around area plowing may affect +
nojogs +
Disable jog insertion (infinite jog horizon) +
nostraighten +
Don't automatically straighten jogs after each plow +
+
+
+ +

Summary:

+
+ The plow command implements a sophisticated method of + stretching and compacting layout. The cursor box can be + used to shove layout in one direction or another, preserving + net connectivity through the modifications.

+ + Results of plow are usually messier than most VLSI + designers care to cope with. The best cell compaction is + realized with careful floorplanning considerations, not + brute force pushing and shoving. +

+ +

Implementation Notes:

+
+ plow is implemented as a built-in command in magic. +
+ +

See Also:

+
+ straighten
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 8:32pm

+ + diff --git a/doc/html/polygon.html b/doc/html/polygon.html new file mode 100644 index 00000000..60c0d12e --- /dev/null +++ b/doc/html/polygon.html @@ -0,0 +1,77 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

polygon

+
+Generate polygons from the command line. +
+ +

Shortcuts:

+
+ None. +
+ +

Usage:

+
+ polygon type x1 y1 x2 y2 ... xn yn

+
+ where type is a tile type to draw, and x1 y1 ... + xn yn are n vertices of a polygon. +
+
+ +

Summary:

+
+ The polygon command allows generation of polygons on the + layout from the command line, similarly to the wire segment + command. The polygon command automatically generates the + proper tile geometry for the polygon as specified by vertices. + Vertex points are pairs of X Y coordinates, and may take any + dimensional value (default lambda, but may be internal units or + metric units). Note that polygons should be convex; the tile + generation algorithm is not guaranteed to work with non-convex + geometries.

+ + While simple non-Manhattan structures (triangles) can be generated + with the "splitpaint" and "spliterase" commands using macros, there + is no convenient interactive method for generating complex polygon + geometry. The polygon command is best used in scripts to + create specific patterns based on known geometry. +

+ +

Implementation Notes:

+
+ polygon is implemented as a built-in command in magic. +
+ +

See Also:

+
+ wire
+
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 8:39pm

+ + diff --git a/doc/html/popbox.html b/doc/html/popbox.html new file mode 100644 index 00000000..8cc9aa3a --- /dev/null +++ b/doc/html/popbox.html @@ -0,0 +1,59 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

popbox

+
+Retrieve the last saved cursor box position +
+ +

Usage:

+
+ popbox

+
+ +

Summary:

+
+ The popbox command sets the cursor box to the position + of the box last saved with the pushbox command, removing + the saved position from the stack. +
+ +

Implementation Notes:

+
+ popbox is implemented as a Tcl procedure in the "tools" + script. It is useful when writing automated layout-generating + Tcl scripts. +
+ +

See Also:

+
+ pushbox
+ peekbox
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 6:07am

+ + diff --git a/doc/html/popstack.html b/doc/html/popstack.html new file mode 100644 index 00000000..e2987a45 --- /dev/null +++ b/doc/html/popstack.html @@ -0,0 +1,63 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

popstack

+
+Return from editing a cell that was loaded using pushstack. +
+ +

Shortcuts:

+
+ Key macro < implements the command popstack. +
+ +

Usage:

+
+ popstack

+
+ +

Summary:

+
+ The popstack command returns from editing a cell that was + loaded using the pushstack command, reverting the layout + window to the cell that was loaded prior to the pushstack + call. This is implemented as a stack, and calls may be nested. +
+ +

Implementation Notes:

+
+ popstack is implemented as a Tcl procedure in the "tools" + script. +
+ +

See Also:

+
+ pushstack
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 11:47pm

+ + diff --git a/doc/html/port.html b/doc/html/port.html new file mode 100644 index 00000000..cdb7b880 --- /dev/null +++ b/doc/html/port.html @@ -0,0 +1,140 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

port

+
+Declare a label to be a subcircuit port, or manipulate port parameters. +
+ +

Usage:

+
+ port option

+
+ where option may be one of the following: +
+
index directions +
Declare a label to be a port with order number + index and with allowed connection directions + specified by the list directions. This is + equivalent to the make option, except that + the index and direction must be specified. +
class [type] +
Get [set] port class type (see Summary, below). +
use [type] +
Get [set] port use type (see Summary, below). +
index [number] +
Get [set] port number +
equivalent [number] +
Make the port equivalent to the (other) port numbered + number. +
connections [directions] +
Get [set] port connection directions +
make [index] [directions] +
Declare a label to be a port with order number + index and with allowed connection directions + specified by the list directions. If not + specified, the index is set to the first unused + number, starting with 1, and the direction defaults + to the direction of the label text. That is, if the + label text is drawn to the right of the port, then + connections are allowed to the right side of the + port. +
remove +
Turn a port back into an ordinary label, removing + all of its port properties. +
help +
Print help information +
+
+
+ +

Summary:

+
+ The port command turns labels into ports and + manipulates the properties of those ports. The port + command gives magic some understanding of "standard + cells". A cell definition that contains declared ports is + treated specially by the extract, ext2spice, + lef, and def commands. All other commands + interpret ports as ordinary labels. ext2spice only + interprets ports specially if the option ext2spice subcircuits + on is enabled. Cells that contain port labels are assumed + in these cases to be standard cells, that is, cells + which are pre-characterized, and for which the layout is not + to be interpreted as a physical circuit. When writing SPICE + output, a cell containing port labels that is a descendent cell + of the top-level layout is written as a subcircuit call, that + is, an "X" record. If the top-level cell in the layout + contains ports, then the SPICE output is written as a subcircuit + definition, that is, wrapped in a ".subckt . . . .ends" pair. + For LEF files, a cell that contains ports is written as a + macro cell, and the ports are the declared PINs of the macro. + For DEF files, a cell that contains ports is written as a + COMPONENT.

+ + The "index" property of the port is used only when the + cell is written into a SPICE deck as a subcircuit entry, + when the ext2spice subcircuit on option is enabled + (which it is by default). In that case, the subcircuit + call parameters (nodes) are written in the order of the port + indices, which are then assumed to match the definition for + the subcircuit. Likewise, if the circuit is written as a + subcircuit to a SPICE file, the order of parameters in the + subcircuit definition will match the order of the port + indices. Note that the actual port numbers are ignored; + the port values will be written in ascending order starting + with the lowest numbered port and ending with the highest + numbered port.

+ + The "direction" property of the port has no particular + meaning to magic but may be used by other programs to control + the allowed direction of routes into a standard cell.

+ + The "class" and "use" properties of the port have no + internal meaning to magic but are used by the LEF and DEF + format read and write routines, and match the LEF/DEF + CLASS and USE properties for macro cell pins. Valid + classes are: default, input, output, + tristate, bidirectional, inout, + feedthrough, and feedthru. Valid uses are: + default, analog, signal, digital, + power, ground, and clock. +

+ +

Implementation Notes:

+
+ port is implemented as a built-in command in magic. +
+ +

See Also:

+
+ label
+ lef
+
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 2:10pm

+ + diff --git a/doc/html/promptload.html b/doc/html/promptload.html new file mode 100644 index 00000000..ffbf02e8 --- /dev/null +++ b/doc/html/promptload.html @@ -0,0 +1,74 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

promptload

+
+Invoke the load-file widget in the GUI version of magic, prompting for +a file to load. +
+ +

Shortcuts:

+
+ Menu item File->Load layout implements the command + promptload magic.
+ Menu item File->Read CIF implements the command promptload cif.
+ Menu item File->Read GDS implements the command promptload gds. +
+ +

Usage:

+
+ promptload magic|cif|gds

+
+ +

Summary:

+
+ The promptload command handles input of various file formats + for the GUI layout window in the Tcl-based version of magic when + invoked with the magic -w option. The handling is more + sophisticated than the underlying magic calls. The gds + read function will attempt to find the top-level GDS cell and + load it into the current window. Likewise, the cif read + function will name the top-level cell with the root name of the + file being read. The magic load will append the path of + the indicated file to the search path, so that if the file + makes calls to additional cells in the same directory, they will + be found and loaded. +
+ +

Implementation Notes:

+
+ promptload is implemented as a Tcl procedure in the "wrapper" + script. It calls the tk_getOpenFile widget in Tk. +
+ +

See Also:

+
+ promptsave
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 12:30am

+ + diff --git a/doc/html/promptsave.html b/doc/html/promptsave.html new file mode 100644 index 00000000..aef9eac1 --- /dev/null +++ b/doc/html/promptsave.html @@ -0,0 +1,72 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

promptsave

+
+Invoke the load-file widget in the GUI version of magic, prompting for +a file to load. +
+ +

Shortcuts:

+
+ Menu item File->Save layout implements the command + promptsave magic.
+ Menu item File->Write CIF implements the command promptsave cif.
+ Menu item File->Write GDS implements the command promptsave gds. +
+ +

Usage:

+
+ promptsave magic|cif|gds

+
+ +

Summary:

+
+ The promptsave command handles output of various file formats + for the GUI layout window in the Tcl-based version of magic when + invoked with the magic -w option. The handling of CIF and + GDS formats merely makes calls to the cif and gds + write routines. The handling of magic (.mag) + format appends the destination path to the search path. If the + destination filename is changed in the Tk file window, the save + command is invoked to rename the top-level layout appropriately before + writing the output. +
+ +

Implementation Notes:

+
+ promptsave is implemented as a Tcl procedure in the "wrapper" + script. It calls the tk_getSaveFile widget in Tk. +
+ +

See Also:

+
+ promptload
+
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 2:09pm

+ + diff --git a/doc/html/property.html b/doc/html/property.html new file mode 100644 index 00000000..d8c7a126 --- /dev/null +++ b/doc/html/property.html @@ -0,0 +1,66 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

property

+
+Attach a "property" (string key and value pair) to the edit cell +
+ +

Usage:

+
+ property [key [value]]

+
+ where key and value are any text strings. +
+
+ +

Summary:

+
+ The property command implements a general-purpose method + of attaching information to a cell definition. Except for a + few properties known to the lef and gds commands + (q.v.), properties have no inherent meaning to magic but may be + used with other programs or scripts to add additional information + about a cell definition.

+ + With no arguments, all properties of the current edit cell are + listed. With only the key argument, the value associated + with the key is returned. With both arguments, the string + value is associated with the string key as a + property of the cell. If key is an existing key, then + its original value will be overwritten. +

+ +

Implementation Notes:

+
+ property is implemented as a built-in command in magic. + The property structure itself is implemented as a hash table in + the cell definition structure. +
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 8:05pm

+ + diff --git a/doc/html/pushbox.html b/doc/html/pushbox.html new file mode 100644 index 00000000..5d4d65ff --- /dev/null +++ b/doc/html/pushbox.html @@ -0,0 +1,59 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

pushbox

+
+Save the cursor box position on a stack for later restoring. +
+ +

Usage:

+
+ pushbox

+
+ +

Summary:

+
+ The pushbox command saves the position of the cursor + box onto a stack, where it may be retrieved or queried using + the popbox and peekbox commands, respectively. +
+ +

Implementation Notes:

+
+ pushbox is implemented as a Tcl procedure in the "tools" + script. It is useful when writing automated layout-generating + Tcl scripts. +
+ +

See Also:

+
+ popbox
+ peekbox
+
+ +

+ + + +
Return to command index +
+

Last updated: October 7, 2004 at 6:00am

+ + diff --git a/doc/html/pushbutton.html b/doc/html/pushbutton.html new file mode 100644 index 00000000..f75e0823 --- /dev/null +++ b/doc/html/pushbutton.html @@ -0,0 +1,66 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

pushbutton

+
+Emulate a mouse button event. +
+ +

Usage:

+
+ pushbutton button action

+
+ where button is one of left, middle, or + right, and action is is one of up or + down. +
+
+ +

Summary:

+
+ The pushbutton command is a way of invoking the actions + associated with mouse buttons from the command-line, or from + a Tcl script. +
+ +

Implementation Notes:

+
+ pushbutton is implemented as a built-in window command + in magic. However, it is functionally equivalent to + calling the Tk function event generate. +
+ +

Bugs:

+
+ This is all backwards! There should be commands implemented to + generate the actions that are caused by button pushes in each + tool, and these commands should be bound to the button events. + Presumably the existing setup is a holdover from pre-X11 days. +
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 12:44am

+ + diff --git a/doc/html/pushstack.html b/doc/html/pushstack.html new file mode 100644 index 00000000..4c02a446 --- /dev/null +++ b/doc/html/pushstack.html @@ -0,0 +1,66 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

pushstack

+
+Load the selected cell and remember the action for later recall +using popstack. +
+ +

Shortcuts:

+
+ Key macro > implements the command pushstack. +
+ +

Usage:

+
+ pushstack

+
+ +

Summary:

+
+ The pushstack command loads the selected cell into the + layout window. However, unlike the load command, the + pushstack command remembers the action by saving the + currently loaded cell on a stack, so it can be recalled with + the popstack command. Due to the stack implemention, + calls may be nested. +
+ +

Implementation Notes:

+
+ pushstack is implemented as a Tcl procedure in the "tools" + script. +
+ +

See Also:

+
+ popstack
+
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 2:08pm

+ + diff --git a/doc/html/quit.html b/doc/html/quit.html new file mode 100644 index 00000000..fd0b6f71 --- /dev/null +++ b/doc/html/quit.html @@ -0,0 +1,63 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

quit

+
+Exit magic +
+ +

Shortcuts:

+
+ Key macro Control-Shift-q implements the command + quit. +
+ +

Usage:

+
+ quit

+
+ +

Summary:

+
+ The quit command implements a resonably gentle exit from + magic, first prompting the user if layouts with changes have not + yet been committed to disk.

+ + Note that in the Tcl version, if the magic package is unable to + load for some reason, the quit command will not be present, + and the Tcl exit command is required to quit the program. + The Tcl exit command will always exit magic + immediately, without prompting or cleanup or any other niceties.

+

+ +

Implementation Notes:

+
+ quit is implemented as a built-in window command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 1:00am

+ + diff --git a/doc/html/redo.html b/doc/html/redo.html new file mode 100644 index 00000000..b7fe393f --- /dev/null +++ b/doc/html/redo.html @@ -0,0 +1,69 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

redo

+
+Redo commands +
+ +

Shortcuts:

+
+ Key macro U implements the command redo. +
+ +

Usage:

+
+ redo [print [count]]

+
+ where count indicates a number of events to be redone + (default 1 event), and must be a nonzero positive integer. +
+
+ +

Summary:

+
+ The redo command reverses the effect of an undo + command, returning the layout in a specific window to the state + it was in prior to execution of the undo command.

+ + The print option allows stack tracing for the redo + command, printing the top count events on the event + stack in excruciating detail. +

+ +

Implementation Notes:

+
+ redo is implemented as a built-in window command in magic. +
+ +

See Also:

+
+ undo
+
+ +

+ + + +
Return to command index +
+

Last updated: October 15, 2004 at 5:54am

+ + diff --git a/doc/html/redraw.html b/doc/html/redraw.html new file mode 100644 index 00000000..bf71f47e --- /dev/null +++ b/doc/html/redraw.html @@ -0,0 +1,54 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

redraw

+
+Redraw the display. +
+ +

Usage:

+
+ redraw

+
+ +

Summary:

+
+ The redraw command completely redraws the layout window. + Normally, magic records regions that require updating and + redraws those portions of the layout. However, key and button + events are allowed to interrupt the redraw, so on occasion it + may be necessary to force a refresh of the display. +
+ +

Implementation Notes:

+
+ redraw is implemented as a built-in window + command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 1:07am

+ + diff --git a/doc/html/render3d.html b/doc/html/render3d.html new file mode 100644 index 00000000..f744a482 --- /dev/null +++ b/doc/html/render3d.html @@ -0,0 +1,59 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

render3d

+
+Create a top-level GUI frame for handling the 3D display window. +
+ +

Usage:

+
+ render3d

+
+ +

Summary:

+
+ The render3d command creates a Tk top-level window + for handling the 3D display window. Currently, the + window is rudimentary and does essentially nothing more + than the specialopen wind3d command does.

+

+ +

Implementation Notes:

+
+ render3d is implemented as a Tcl procedure in the "wrapper" + script. This is basically a placeholder for a more complete + GUI frame for manipulating the 3D view. +
+ +

See Also:

+
+ specialopen
+
+ +

+ + + +
Return to command index +
+

Last updated: November 10, 2004 at 1:09pm

+ + diff --git a/doc/html/resumeall.html b/doc/html/resumeall.html new file mode 100644 index 00000000..850388fd --- /dev/null +++ b/doc/html/resumeall.html @@ -0,0 +1,68 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

resumeall

+
+Resume normal display refresh on all windows. +
+ +

Usage:

+
+ resumeall

+
+ +

Summary:

+
+ The resumeall command is a script that invokes the command + update resume on all layout windows. It is used in + conjunction with the suspendall command and is intended + for use in Tcl scripts that perform multiple manipulations on + layout in a window, where it is desired to have the entire + display refresh at one time at the end of the script rather than + for each command within the script.

+ + Because calls to update can be nested, calls to suspendall + and resumeall are likewise nested. The resumeall + command will have no effect until the same number of resumeall + calls has been encountered as the number of suspendall calls + made. +

+ +

Implementation Notes:

+
+ resumeall is implemented as a Tcl procedure in the "tools" + script. +
+ +

See Also:

+
+ update
+ suspendall
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 1:25am

+ + diff --git a/doc/html/rotate.html b/doc/html/rotate.html new file mode 100644 index 00000000..69e21b42 --- /dev/null +++ b/doc/html/rotate.html @@ -0,0 +1,73 @@ + +rotate [+/-][deg] + rotate selection and box (counter)clockwise + only manhattan rotations (90, 180, 270) are + supported + + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

rotate

+
+Rotate the selection and box clockwise by the indicated amount. +
+ +

Usage:

+
+ rotate [+|-][degrees] [-origin]

+
+ where degrees is the number of degrees to rotate, and + must be a manhattan amount (90, 180, 270). +
+
+ +

Summary:

+
+ The rotate command rotates the current selection by + the specified amount, in degrees. The default rotation is by + 90 degrees. The amount of rotation can be positive or negative, + but must be one of the Manhattan rotations 90, 180, or 270.

+ + If -origin is specified, the rotation is around the + origin of the selection, not around the lower left-hand + corner. +

+ +

Implementation Notes:

+
+ rotate is implemented as a built-in magic command. + It is equivalent to the clockwise command but allows + negative values to represent counterclockwise rotation. +
+ +

See Also:

+
+ clockwise
+
+ +

+ + + +
Return to command index +
+

Last updated: October 15, 2004 at 10:10am

+ + diff --git a/doc/html/route.html b/doc/html/route.html new file mode 100644 index 00000000..1a216f43 --- /dev/null +++ b/doc/html/route.html @@ -0,0 +1,91 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

route

+
+Route the current cell +
+ +

Usage:

+
+ route option

+
+ where option may be one of the following: +
+
end value +
Set channel router end constant. value type is real, + and defaults to 1.0. +
help +
Print help information +
jog length +
Set minimum jog length (integer grid units) +
metal +
Toggle metal maximization (default is "on"). +
netlist file +
Set current netlist (default NULL) +
obstacle value +
Set obstacle constant. value type is real, + and defaults to 0.7. +
origin [x y] +
Print or set routing grid origin +
stats +
Print and clear previous route statistics +
settings +
Show router parameters +
steady value +
Set steady net constant. value type is integer, + and defaults to 1. +
tech +
Show router parameters read from the technology file. +
vias value +
Set metal maximization via limit (grid units). value + type is integer, and defaults to 2. +
viamin +
Via minimization +
+
+
+ +

Summary:

+
+ The route command performs standard routing of networks + in a netlist. +
+ +

Implementation Notes:

+
+ route is implemented as a built-in command in magic. +
+ +

See Also:

+
+ iroute
+ garoute
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 1:47am

+ + diff --git a/doc/html/ruler.html b/doc/html/ruler.html new file mode 100644 index 00000000..ec3560ed --- /dev/null +++ b/doc/html/ruler.html @@ -0,0 +1,71 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

ruler

+
+Create ruler markings inside the box with indicated text. +
+ +

Usage:

+
+ ruler [text [orient]]

+ +
+ where orient is either vertical, + horizontal, or auto (the default), and + where text is any string. If the string + contains whitespace, it must be quoted. +
+
+ +

Summary:

+
+ The ruler command generates a "ruler", a set of lines indicating + a dimension. It is used to annotate layouts with the indicated text. + If no orientation is given, then automatic orientation it used, in + which the presented dimension (the line or lines with arrowheads) + is whichever box dimension (width or height) is longer. The ruler + may be removed with the unmeasure command. The measure + command is a specific type of ruler where the text is set to the + presented box dimension. +
+ +

Implementation Notes:

+
+ ruler is implemented as a Tcl procedure defined + in the "tools" script. It generates a set of elements (lines and + text) with the element add command. +
+ +

See Also:

+
+ measure
+ unmeasure
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/save.html b/doc/html/save.html new file mode 100644 index 00000000..362801ee --- /dev/null +++ b/doc/html/save.html @@ -0,0 +1,65 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

save

+
+Save edit cell on disk +
+ +

Usage:

+
+ save [filename]

+
+ where filename is a new name for the cell as well as + the root name of the .mag file to be saved. +
+
+ +

Summary:

+
+ The save command saves the current edit cell to disk. + If filename is specified, then the layout will be + saved to "filename.mag", and the current edit + cell will be renamed to filename.

+ + The save command differs from writeall in several + ways: save does not descend the hierarchy, and does not + prompt the user for an action. +

+ +

Implementation Notes:

+
+ save is implemented as a built-in command in magic. +
+ +

See Also:

+
+ writeall
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 2:05am

+ + diff --git a/doc/html/scalegrid.html b/doc/html/scalegrid.html new file mode 100644 index 00000000..f88bcd2c --- /dev/null +++ b/doc/html/scalegrid.html @@ -0,0 +1,76 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

scalegrid

+
+Set the ratio of magic internal units to lambda units +
+ +

Usage:

+
+ scalegrid a b

+
+ where a and b are integers. +
+
+ +

Summary:

+
+ The scalegrid command sets the ratio of magic internal + units to lambda units by rescaling the internal database and + appropriate technology parameters. The values a and + b are interpreted to mean that all positions in the + database should be multiplied by the factor b / a. + An equivalent meaning is that there should be b internal + units per a lambda units in the database. For example, +
+ scalegrid 1 2 +
+ means 2 internal units per lambda, or an internal grid that is + twice as finely spaced as the default. The grid scaling can + be queried using the tech lambda command. Grid scaling + is interpreted relative to the current scale, so +
+ scalegrid 1 2
+ scalegrid 1 2 +
+ results in 4 internal units per lambda. +
+ +

Implementation Notes:

+
+ scalegrid is implemented as a built-in command in magic. +
+ +

See Also:

+
+ snap
+ tech
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 2:14am

+ + diff --git a/doc/html/scroll.html b/doc/html/scroll.html new file mode 100644 index 00000000..32fed637 --- /dev/null +++ b/doc/html/scroll.html @@ -0,0 +1,75 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

scroll

+
+Scroll the window +
+ +

Shortcuts:

+
+ The keyboard arrow keys implement the command. Without modifiers, the + window scrolls by 1/10 width in the indicated direction. With Shift, + the window scrolls by one width in the indicated direction. +
+ +

Usage:

+
+ scroll direction [amount [units]]

+
+ where direction is a valid Manhattan + direction, and amount + by default is an absolute distance + in any acceptable units. If units is + w, then the amount is interpreted as + a fraction of the screen width. If units ls + l, then the amount is interpreted as + a fraction of the layout width. Note that units of + distance for amount, such as "um" for microns or + "i" for internal units, are attached to the value with + no intervening space, whereas the two units + keywords accepted by the scroll command are + a separate argument and separated from amount by + whitespace. +
+
+ +

Summary:

+
+ The scroll command implements a pan of the layout in the + window in the indicated direction by the indicated amount. + The interpretation of amount is described above in the + Usage section. +
+ +

Implementation Notes:

+
+ scroll is implemented as a built-in window command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 2:45am

+ + diff --git a/doc/html/search.html b/doc/html/search.html new file mode 100644 index 00000000..38332cc3 --- /dev/null +++ b/doc/html/search.html @@ -0,0 +1,114 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

search

+
+Execute a TCL procedure on each tile in the current edit cell definition. +
+ +

Usage:

+
+ search [layers] procedure

+
+ where layers is a comma-separated list of layer types + to generate a mask to limit the tile search, and procedure + is the name of a predefined Tcl procedure (see Summary, below). +
+
+ +

Summary:

+
+ The search command is a method for user access to + the magic database search routines. It searches the + tile database of the current edit cell definition and its + hierarchy of descendents and applies the callback procedure + to each. The callback procedure must be defined as described + below.

+ + Note that the callback method into Tcl is inherently slow + and should only be used for non-compute-intensive tasks. + In particular, unless it is known that the cell definition + being traversed has relatively few structures, the layers + argument should be used to severely limit the scope of the + search. This function can be useful in certain situations, + such as parsing a layout for layer "pad" to enumerate the number + of pads in a design.

+ + The Tcl callback procedure is passed five values, the four + coordinates of the tile, and the layer type of the tile. + The procedure must be defined to accept these five arguments, + as in the following example: +

+	proc tile_callback {llx lly urx ury ttype} {
+	   puts stdout "Tile type $ttype at $llx $lly $urx $ury"
+        }
+     
+ + When non-manhattan tiles are parsed, the type $ttype is passed + as a list of two string elements, the type on the left side of + the diagonal split, and the type on the right side of the + diagonal split. + +
+ +

Implementation Notes:

+
+ search is implemented as an internal magic + command that links to an external Tcl procedure as a callback + function. This routine is experimental and subject to change + without notice. +
+ +

Bugs:

+
+ As currently implemented, there is no protection against + calling a magic command from the callback procedure + that will alter the internal tile structures while the tile + plane is being traversed, causing a crash. The implementation + should be changed to a 2-step procedure that traverses the + tile plane first, creating an internal list of function + arguments to pass for each tile, and then executes the + callback function on each.

+ + There are more efficient ways of executing the callback + function than Tcl_EvalEx(). In particular, the procedure + should be cast as a Tcl object and Tcl_EvalObjEx() used.

+ + The callback function should allow in-line Tcl procedures + and use the standard Tcl/Tk method of "%" escape sequences + used as arguments to the callback function that allow the + user to specify what arguments are passed to the callback + function (as is done for the tag command). +

+ +

See Also:

+
+ cellsearch
+
+ +

+ + + +
Return to command index +
+

Last updated: October 4, 2004 at 5:05am

+ + diff --git a/doc/html/see.html b/doc/html/see.html new file mode 100644 index 00000000..00034fb7 --- /dev/null +++ b/doc/html/see.html @@ -0,0 +1,85 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

see

+
+Change what layers are displayed in the window +
+ +

Shortcuts:

+
+ Mouse buttons 1 and 3 pressed in the GUI window toolbar implement the + see and see no commands for the layer represented by + the toolbar button. +
+ +

Usage:

+
+ see [no] layers|allSame

+
+ where layers is a comma-separated list of layers + in the technology, and may also be the character * + indicating all layers but not labels, $ indicating + all layers including labels, labels indicating + only labels, error indicating DRC error paint, + and subcell indicating subcells. +
+
+ +

Summary:

+
+ The see command allows various layers in the layout + to be made visible, including labels and error paint. + With the keyword no, the command causes these layers + to be made invisible on the display.

+ + The keyword allSame is a special use and indicates that + non-edit cells should be drawn in the same manner as the edit + cell, rather than being drawn in the "pale" styles.

+ + Undisplayed layers generally do not respond to commands such + as erase or select. However, network selection + will select across invisible layers, and copying or moving + such a network selection will alter the invisible layers as + well as the visible. +

+ +

Implementation Notes:

+
+ see is implemented as a built-in command in magic. +
+ +

Bugs:

+
+ It should be enforced everywhere in the code that invisible + layers cannot be altered. This may require removing invisible + layers from a selection after doing a network connectivity + search. +
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 2:02pm

+ + diff --git a/doc/html/select.html b/doc/html/select.html new file mode 100644 index 00000000..a19b0f84 --- /dev/null +++ b/doc/html/select.html @@ -0,0 +1,152 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

select

+
+Select or unselect portions of the layout according to the options, or +create a new cell definition from a selection. +
+ +

Shortcuts:

+
+ Key macro , (comma) implements the command select clear.
+ Key macro s implements the command select.
+ Key macro S implements the command select more.
+ Key macro Control-S implements the + command select less.
+ Key macro a implements the command select visible.
+ Key macro A implements the command select more visible.
+ Key macro Control-A implements the + command select less visible.
+ Key macro i implements the command select cell.
+ Key macro I implements the command select more cell.
+ Key macro Control-I implements the + command select less cell. +
+ +

Usage:

+
+ select option

+
+ where option may be one of the following: +
+
[more | less] [layers] +
[De]select material under cursor, or + [de]select a subcell if the cursor is over space. +
nocycle [layers] +
Select material without cycling through different tile + types when "select" is called from the same cursor position + more than once. +
[more | less] area [layers] +
[De]select all material under box in layers layers +
[more | less] visible [layers] +
[De]select all visible material under box in layers layers. +
[more | less] box [layers] +
[De]select material specified by the boundary of the cursor box +
[more | less] chunk [layers] +
[De]select a network chunk (largest rectangle) specified by + the lower left corner of the cursor box +
[more | less] region [layers] +
[De]select a network region specified by + the lower left corner of the cursor box +
[more | less] net [layers] +
[De]select an entire electrical network specified by + the lower left corner of the cursor box +
[more | less] cell [name] +
[De]select the cell under cursor, or the cell use (instance) + named name. +
top cell +
Select the topmost cell in the window, which does not have + an instance name and therefore cannot be selected with the + select cell command. +
save cell +
Save selection as cell named cell, which is also + saved to disk as cell.mag. +
clear +
Clear selection +
pick +
Remove the selection from the layout, but retain the + selection buffer for interactive processing. +
keep +
Copy the selection from the layout into the selection + buffer, and keep the selection buffer for interactive + processing. +
move x y +
Move the selection buffer to position x y, + relative to the cell definition origin. +
help +
Print help information +
+
+
+ +

Summary:

+
+ The select command changes what material is in the current + selection. magic maintains a separate cell definition + that represents the current selection. Without the options + more or less, the selection is cleared prior to + executing the new selection command. Otherwise, more + adds to the existing selection and less subtracts from + it.

+ + Network selection differs from other types of selection in + that magic uses a sophisticated algorithm to determine + what is electrically connected together throughout the layout. + A chunk is the largest rectangle containing a single + layer type. A region is the largest network area + containing a single layer type. The region stops where the + net connects to a different layer type. The net is + the entire electrical network.

+ + The select save options differs from the rest in that it + does not alter the current selection, but creates a new cell + definition from the current selection. Note that this cell + is created as a top-level cell, and does not replace the current + selection as a use in the edit cell. To do that requires + "select save cell" followed by "delete" + and "getcell child 0 0 parent 0 0". The last command + syntax is used because the bounds of the selection may differ + from the cursor box. +

+ +

Implementation Notes:

+
+ select is implemented as a built-in command in magic. + The select keep, select move, and select pick + are interactive functions used by the "pick" tool. +
+ +

Bugs:

+
+ To be consistent, select save should be a separate command, + since like other commands it operates on the selection rather than + alter what is in the selection. +
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 5:06pm

+ + diff --git a/doc/html/setpoint.html b/doc/html/setpoint.html new file mode 100644 index 00000000..e2297ff8 --- /dev/null +++ b/doc/html/setpoint.html @@ -0,0 +1,84 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

setpoint

+
+Set the value of the cursor reference point in a specific window. +
+ +

Usage:

+
+ setpoint [x y [window_id]

+
+ where x and y are screen coordinates and + window_id is the identifying number for a layout + window. +
+
+ +

Summary:

+
+ The setpoint command forces the reference point for a specific + window. Each command that executes relative to a window must be able + to translate from the pointer position to a layout coordinate. + Commands that are executed from a script or from the command-line + may not have access to the pointer, but can set the reference point + with this command so that the effect of the command is predictable.

+ + Normally, in interactive this command is not used. However, + scripts that open more than one window need to specify which one + is to take the action of the command. In the Tcl/Tk version, this + can be done by using the tk_path_name command to pass a + command to a specific window. The non-Tcl/Tk version, and the Tcl/Tk + version using the "-dnull" option on the command line (i.e., no + graphics package initialized) must use the setpoint command + to track windows. Although possible, it is generally a bad idea + for a script running in batch mode ("-dnull") to create and access + multiple windows, since the window structures have no useful + function outside of a graphics environment. Nevertheless, it is + important to realize that the openwindow command will + generate multiple virtual windows in a batch-mode environment, and + these can only be separately accessed using the setpoint + command. +

+ +

Implementation Notes:

+
+ setpoint is implemented as a built-in window command in magic. +
+ +

Bugs:

+
+ The use of the window ID number is unique to this command and should + be a window name like every other window-related command. Likewise, + scripts would best make use of this command if the position were in + layout coordinates, and magic translated them back to screen + coordinates in the indicated window to set the reference point. +
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 9:02pm

+ + diff --git a/doc/html/shell.html b/doc/html/shell.html new file mode 100644 index 00000000..4bd031e9 --- /dev/null +++ b/doc/html/shell.html @@ -0,0 +1,66 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

shell

+
+Execute a command in a UNIX subshell +
+ +

Usage:

+
+ shell [command]

+
+ where command is a valid UNIX command-line command. +
+
+ +

Summary:

+
+ The shell command allows UNIX commands to be executed from + the magic command line. This use is superceded by the Tcl + interpreter, which executes shell commands directly from the + interpreter prompt. Differences between the two uses is noted + below. +
+ +

Implementation Notes:

+
+ shell is implemented as a built-in command in magic. + This is similar to the Tcl interpreter execution of shell commands + directly from the Tcl command-line. The primary difference is that + results from the shell interpreter are printed to the calling + terminal with shell, and are printed to the console when + invoked directly from Tcl. For example, note the difference in + the output target for: +
+ ls -l
           
vs.
+ shell ls -l +
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 3:55am

+ + diff --git a/doc/html/sideways.html b/doc/html/sideways.html new file mode 100644 index 00000000..411e7916 --- /dev/null +++ b/doc/html/sideways.html @@ -0,0 +1,61 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

sideways

+
+Flip selection and box sideways +
+ +

Shortcuts:

+
+ Key macro f implements the command sideways. +
+ +

Usage:

+
+ sideways

+
+ +

Summary:

+
+ The sideways command flips the selection from left to right. + Flipping is done such that the lower left-hand corner of the + selection remains in the same place through the flip. +
+ +

Implementation Notes:

+
+ sideways is implemented as a built-in command in magic. +
+ +

See Also:

+
+ upsidedown
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 6:02am

+ + diff --git a/doc/html/sleep.html b/doc/html/sleep.html new file mode 100644 index 00000000..1d0b69a3 --- /dev/null +++ b/doc/html/sleep.html @@ -0,0 +1,56 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

sleep

+
+Sleep for a number of seconds +
+ +

Usage:

+
+ sleep seconds

+
+ where seconds is the number of seconds to sleep. +
+
+ +

Summary:

+
+ The sleep command implements the UNIX system sleep() + call to suspend the process for a number of seconds. This + function is only particularly useful for demonstration + purposes. In the Tcl version of magic, it is effectively + superceded by the Tcl after command. +
+ +

Implementation Notes:

+
+ sleep is implemented as a built-in command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 6:28am

+ + diff --git a/doc/html/snap.html b/doc/html/snap.html new file mode 100644 index 00000000..3e40e5a3 --- /dev/null +++ b/doc/html/snap.html @@ -0,0 +1,94 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

snap

+
+Cause box to snap to the selected grid when moved by the cursor. Also, +cause distance measurements to be interpreted by default as measurments +in the selected grid. +
+ +

Usage:

+
+ snap [internal|lambda|user]

+
+ +

Summary:

+
+ The snap command causes the cursor box to snap to the + selected grid when moved by pointer button events. The selected + grids are internal, the size of the internal database, + lambda, the lambda grid based on the technology minimum + feature size, and user, based on the value given by the + user to the grid command.

+ + In addition to changing the behavior of the box to mouse + button events, the snap command also changes the way + that distance measurements are + interpreted in commands that take distance arguments, such + as move, copy, and stretch. An integer + number with no other identifying units is interpreted as a + measurement in the current snap grid. All other measurements + must have an identifying unit: i for internal units, + l for lambda units, and g for user grid units + (as well as the usual metric units). Even when snap + is set to the larger lambda or user grids, it is possible to + move the cursor box to finer grid positions from the command + line. See the reference page on + distance measures for a complete + description of distance values.

+ + snap with no arguments returns the current snap grid + type.

+ + By default, the internal and lambda grids are the same. However, + CIF, GDS, or LEF/DEF input on a finer scale can cause the internal + grid to be set finer than the lambda grid. Also, the scalegrid + command can be used to separate the internal and lambda grids. + Note that the use of "lambda" is merely a convention. Traditionally, + scalable CMOS rules were based on units of "lambda", equal to + one-half the minimum feature size of the technology. Many + technology files are still based on lambda rules, which are usually + more conservative than vendor rules. However, some technology files + may be based on exactly implementing vendor rules, and may set + the internal grid spacing to a finer resolution, such as 0.1 micron + or smaller. In such cases, the use of the term "lambda" is a + misnomer. +

+ +

Implementation Notes:

+
+ snap is implemented as a built-in command in magic. +
+ +

See Also:

+
+ grid
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 7:16am

+ + diff --git a/doc/html/specialopen.html b/doc/html/specialopen.html new file mode 100644 index 00000000..70311e21 --- /dev/null +++ b/doc/html/specialopen.html @@ -0,0 +1,80 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

specialopen

+
+Open a window of a specific type. +
+ +

Usage:

+
+ specialopen type [arguments]

+
+ where type may be one of the following: +
+
layout +
Open a layout window. Equivalent to the + openwindow command. +
wind3d tk_path_name +
Generate the 3D window. Only available when using + OpenGL graphics ("magic -d OGL"). The + tk_path_name argument allows the window to + be inserted into a Tk frame instead of generated + directly on the desktop. +
color +
Open a window allowing layout colors to be edited. +
netlist +
Open a window allowing interactive definition of + netlists. +
+
+
+ +

Summary:

+
+ The specialopen command opens one of several special-purpose + windows known to magic, as well as the default layout window. + Each window has a set of commands associated with it. The layout + window commands are listed in this reference guide along with the + general-purpose commands, because the layout window is the most + common type. For the command sets of the other special-purpose + windows, see the sections on the colormap, netlist, and 3D + rendering. +
+ +

Implementation Notes:

+
+ specialopen is implemented as a built-in window command in magic. +
+ +

See Also:

+
+ openwindow
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 7:29am

+ + diff --git a/doc/html/spliterase.html b/doc/html/spliterase.html new file mode 100644 index 00000000..9a72ead8 --- /dev/null +++ b/doc/html/spliterase.html @@ -0,0 +1,77 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

spliterase

+
+Paint into the cursor box, splitting the box diagonally with one layer +forming a right triangle in one corner and space or another layer in +the other. +
+ +

Usage:

+
+ spliterase dir layer

+
+ where dir is a valid non-Manhattan direction indicating + the direction of the right angle corner of the right triangle + to be erased. Any paint of layer type layer is erased + from this triangular area. +
+
+ +

Summary:

+
+ The spliterase command implements a form of non-Manhattan + geometry that conforms to the corner-stitched tile database + format used by magic for painting and searching operations + in a plane. It lets a rectangular area, as defined by the + position of the cursor box, be split diagonally, with one half + containing one layer type, and the other half containing + another. While the splitpaint command generates + non-Manhattan areas by adding paint in a triangular area, + spliterase creates non-Manhattan areas by subtracting + paint from a triangular area.

+ + Note that spliterase, like splitpaint, is somewhat + cumbersome to use; to generate diagonal wires, use the wire + segment command instead, which is also able to compute mitred + joints between segments at different angles.

+

+ +

Implementation Notes:

+
+ spliterase is implemented as a built-in command in magic. +
+ +

See Also:

+
+ splitpaint
+ wire
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 7:41am

+ + diff --git a/doc/html/splitpaint.html b/doc/html/splitpaint.html new file mode 100644 index 00000000..36a23905 --- /dev/null +++ b/doc/html/splitpaint.html @@ -0,0 +1,75 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

splitpaint

+
+Paint into the cursor box, splitting the box diagonally with one layer +forming a right triangle in one corner and space or another layer in +the other. +
+ +

Usage:

+
+ splitpaint dir layer [layer2]

+
+ where dir is a valid non-Manhattan direction indicating + the direction of the right angle corner of the right triangle + to be painted. This triangle is painted with layer type + layer. If specified, the opposite triangle is painted + with layer type layer2; otherwise, it is unpainted. +
+
+ +

Summary:

+
+ The splitpaint command implements a form of non-Manhattan + geometry that conforms to the corner-stitched tile database + format used by magic for painting and searching operations + in a plane. It lets a rectangular area, as defined by the + position of the cursor box, be split diagonally, with one half + containing one layer type, and the other half containing + another.

+ + Note that splitpaint is somewhat cumbersome to use; + to generate diagonal wires, use the wire segment command, + which is also able to compute mitred joints between segments at + different angles.

+

+ +

Implementation Notes:

+
+ splitpaint is implemented as a built-in command in magic. +
+ +

See Also:

+
+ spliterase
+ wire
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 7:38am

+ + diff --git a/doc/html/startup.html b/doc/html/startup.html new file mode 100644 index 00000000..33c9be3d --- /dev/null +++ b/doc/html/startup.html @@ -0,0 +1,63 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

startup

+
+Start magic from inside the Tcl interpreter. +
+ +

Usage:

+
+ startup

+
+ +

Summary:

+
+ The startup command is not a user command. It is called + by Tcl packages that wish to use magic from the interpreter. + The procedure for starting magic is as follows: +
    +
  • Load the tclmagic.so object file. +
  • Call initialize with arguments passed to magic + on the command line. +
  • Call startup +
+
+ +

Implementation Notes:

+
+ startup is implemented as a built-in command in magic, + but only defined by the Tcl version. +
+ +

See Also:

+
+ initialize
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 8:00am

+ + diff --git a/doc/html/straighten.html b/doc/html/straighten.html new file mode 100644 index 00000000..0935ae0f --- /dev/null +++ b/doc/html/straighten.html @@ -0,0 +1,61 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

straighten

+
+Straighten jogs by pulling in direction +
+ +

Usage:

+
+ straighten direction

+
+ where direction is any valid Manhattan + direction in magic. +
+
+ +

Summary:

+
+ The straighten command attempts to straighten jogs + in wire paths. It is part of the plow method, and + helps to clean up areas that have been altered using the + plow command. +
+ +

Implementation Notes:

+
+ straighten is implemented as a built-in command in magic. +
+ +

See Also:

+
+ plow
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 8:34pm

+ + diff --git a/doc/html/stretch.html b/doc/html/stretch.html new file mode 100644 index 00000000..bd4f8403 --- /dev/null +++ b/doc/html/stretch.html @@ -0,0 +1,96 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

stretch

+
+Stretch the cursor box and the selection. +
+ +

Shortcuts:

+
+ Key macro M implements the command move (no arguments).
+ Key macro Shift-Keypad-8 implements the + command stretch n 1
+ Key macro Shift-Keypad-6 implements the + command stretch e 1
+ (and so forth for all 8 compass rose directions). +
+ +

Usage:

+
+ stretch [direction [distance]]

+
+ where direction is any valid + direction specification in magic, and distance + is any valid distance + specification. + +
+
+ +

Summary:

+
+ The stretch command moves the current selection from + its current position according to the command arguments, + and fills in behind with material such that electrical + connections are maintained across the area in between the + original and final positions.

+ + Without arguments, the lower-left hand corner of the + selection is moved to the current cursor position (the X11 + cursor, not the magic "cursor box"). With arguments + direction and distance, the selection is moved + relative to the original in the indicated direction by the + indicated amount. The default distance is 1 unit (usually + lambda; see distance for + further explication).

+ + The stretching algorithm fills in with the material that + crosses or touches the cursor box in the opposite direction + to the direction being stretched. If two different materials + are on opposite sides of this boundary, the effect depends + on the material types. Contact types will not be stretched + unless the contact material is on both sides of the cursor + box boundary. If two different contact types are on opposite + sides of the boundary, then the material that electrically + connects those two contacts (if any) will be filled in the + stretch area. +

+ +

Implementation Notes:

+
+ stretch is implemented as a built-in magic command. +
+ +

See Also:

+
+ direction
+ distance
+
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 2:00pm

+ + diff --git a/doc/html/suspendall.html b/doc/html/suspendall.html new file mode 100644 index 00000000..4a0c8fd7 --- /dev/null +++ b/doc/html/suspendall.html @@ -0,0 +1,69 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

suspendall

+
+Suspend normal display refresh on all windows until the invocation +of a corresponding resumeall command. +
+ +

Usage:

+
+ suspendall

+
+ +

Summary:

+
+ The suspendall command is a script that invokes the command + update suspend on all layout windows. It is used in + conjunction with the resumeall command and is intended + for use in Tcl scripts that perform multiple manipulations on + layout in a window, where it is desired to have the entire + display refresh at one time at the end of the script rather than + for each command within the script.

+ + Because the update command can be nested, calls to + suspendall and resumeall are likewise nested. + resumeall does not resume the window refresh until + it has been called the same number of times as suspendall + was called. +

+ +

Implementation Notes:

+
+ suspendall is implemented as a Tcl procedure in the "tools" + script. +
+ +

See Also:

+
+ resumeall
+ update
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 1:24am

+ + diff --git a/doc/html/tag.html b/doc/html/tag.html new file mode 100644 index 00000000..c65e7896 --- /dev/null +++ b/doc/html/tag.html @@ -0,0 +1,116 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

tag

+
+Register a tag callback command. +
+ +

Usage:

+
+ tag command_name [procedure]

+
+ where command_name is the name of any magic + command, and procedure is any valid Tcl procedure. +
+
+ +

Summary:

+
+ The tag command is registers callback procedures to be + executed after the indicated magic command has been + executed. The primary use of the tag command is to + register procedures that update the GUI window in response + to commands that are typed on the command line or generated + from macro calls.

+ + In keeping with standard methods for Tcl callback functions, + certain "escape sequences" beginning with the percent ("%") + character are allowed to be embedded in the callback function + procedure, and are substituted prior to execution, with + the substitutions defined as follows: +

+
+
%W +
Substitute the Tk path of the layout window from which + or in reference to which command_name was invoked. +
%r +
Substitute the previous Tcl result string, but do not reset + the Tcl result of the execution of procedure. +
%R +
Substitute the previous Tcl result string and reset the Tcl + result from the execution of procedure such that the + the result of command_name becomes the result of + procedure. +
%[0-5] +
Substitute the zeroth to fifth argument to the original command. +
%% +
Substitute a single percent character. +
%char +
where char is any character not defined above: No action, + print exactly as written. +
+
+ + When a tag callback is used, the return value seen by the interpreter + is the return value of the function procedure, not the return + value of the tagged command command_name. The escape sequence + %R can be used to force the result of command_name to + become the result of procedure (unless procedure + produces an error condition, in which case the error is returned). + The escape sequence %r passes the result of command_name + as an argument to the procedure, which may choose to return it as + a result, or not.

+ + If no procedure is present, then the tag command + returns whatever procedure string is attached to the indicated + command_name, if any. This can be used as a way to prevent + infinite recursion inside a tag callback; for example, +

+ set savetag [tag callback command]
+ (procedure calls, which may include a call to command)
+ tag command $savetag +
+ + Another way to avoid infinite recursion is to check the procedure + depth from within the tag callback procedure using the Tcl command + "info level", to avoid executing the callback procedure if + the level is not zero.

+ + Only one tag callback is allowed per command name. However, only + one is needed as that procedure may call as many other procedures + as it wants to. +

+ +

Implementation Notes:

+
+ tag is implemented as a built-in command in magic, + but only in the Tcl version. +
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 10:15pm

+ + diff --git a/doc/html/tech.html b/doc/html/tech.html new file mode 100644 index 00000000..8f0a511f --- /dev/null +++ b/doc/html/tech.html @@ -0,0 +1,131 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

tech

+
+Query properties of the current technology, or change the current +technology. +
+ +

Usage:

+
+ tech option

+
+ where option may be one of the following: +
+
load filename [-noprompt][-nooverride] +
Load a new technology from the file filename[.tech]. +
help +
Display help information +
name +
Show current technology name +
filename +
Show current technology filename +
version +
Show current technology version and description strings +
lambda +
Show internal units per lambda +
planes +
Show defined planes +
layers [layer] +
Show defined layers +
drc option +
Query the DRC ruleset, where option is one of the + following: +
+
width layer +
Return the minimum allowed width for the indicated + layer type. +
spacing layer1 [layer2] +
Return the minimum allowed spacing between + layer1 and layer2, if layer2 + is specified, or between layer1 and itself, + if not. +
+
+
+
+ +

Summary:

+
+ The tech command queries aspects of the current + technology, and can also be used to change the current + technology. The tech load command completely + replaces the technology. Normally a call to tech load + generates a dialog window asking the user for confirmation, + since the tech load command is potentially destructive + and can cause loss of an existing layout. The -noprompt + option forces a technology load without presenting a dialog. + This is particularly useful to put a "tech load name + -noprompt" command in a .magic startup + file in the directory of a project, so that it is not necessary to + specify the technology on the command line when invoking magic. + However, occasionally one may want to run magic from the same + project directory with a different technology. + The -nooverride option prevents the tech load command + from overriding a technology name entered on the UNIX + command line when starting magic.

+ + Technology file reloading is especially useful when + developing a technology file, to immediately see the + results of a change made to the file. The current + technology can be reloaded with the simple Tcl command + "tech load [tech filename]".

+ + Note that there is a slightly different meaning between + the command "tech layers" and "tech layers "*"". + The former prints a formatted list of layers, including all + aliases for each layer, to the console. The second returns + a Tcl list of all layers, with only the primary name for + each layer.

+ + A few aspects of the technology must be queried from other + commands. The CIF/GDS input and output styles are given + by the cif istyle and cif ostyle commands, while + the extraction style is given by the extract style + command.

+ + The drc option is intended for use by Tcl scripted + procedures that wish to place layout while satisfying the + DRC rules. The two accepted rule options are + spacing and width. +

+ +

Implementation Notes:

+
+ tech is implemented as a built-in command in magic. + The command replaces the original techinfo command, which + no longer exists. +
+ +

Bugs:

+
+ tech drc may not return the correct value in all cases. +
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 1:59pm

+ + diff --git a/doc/html/techmanager.html b/doc/html/techmanager.html new file mode 100644 index 00000000..209e672f --- /dev/null +++ b/doc/html/techmanager.html @@ -0,0 +1,71 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

techmanager

+
+Generate the technology manager GUI window. +
+ +

Shortcuts:

+
+ Menu item Options->Technology manager implements the command + techmanager. +
+ +

Usage:

+
+ techmanager

+
+ +

Summary:

+
+ The techmanager command generates the "technology manager" + GUI window (see Figure 1 below). This window shows the current + technology along with its version and description strings + shows the internal grid scaling, the current and available CIF/GDS + input and output styles, and the current and available extraction + styles. It also shows the known technology files by searching + the system search path (see the command path for + more information). It allows a new technology to be loaded, or + the CIF/GDS and extraction styles to be changed, as well as + allowing internal grid rescaling by specifying the internal units + per lambda.

+ +

+
+ Figure 1. The technology manager GUI window. +
+
+ +

Implementation Notes:

+
+ techmanager is implemented as a Tcl procedure in the + "wrapper" script. +
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 11:09pm

+ + diff --git a/doc/html/template.html b/doc/html/template.html new file mode 100644 index 00000000..288e491d --- /dev/null +++ b/doc/html/template.html @@ -0,0 +1,66 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

command_name

+
+Short summary. +
+ +

Shortcuts:

+
+ Key macro k implements the command command_name option. +
+ +

Usage:

+
+ command_name option

+
+ where option may be one of the following: +
+
option_1 +
+
+
+
+ +

Summary:

+
+ The command_name command is. . . +
+ +

Implementation Notes:

+
+ command_name is implemented as a built-in command in magic. +
+ +

See Also:

+
+ other_command
+
+ +

+ + + +
Return to command index +
+

Last updated: October 6, 2004 at 12:21am

+ + diff --git a/doc/html/tk_path_name.html b/doc/html/tk_path_name.html new file mode 100644 index 00000000..55019fd8 --- /dev/null +++ b/doc/html/tk_path_name.html @@ -0,0 +1,93 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

tk_path_name

+
+Execute a window command in the indicated window. +
+ +

Shortcuts:

+
+ Key macro : (colon) implements the command tk_path_name + by prepending the window name to the command typed on the command + line when the command is executed. This action is, however, + transparent to the end user. +
+ +

Usage:

+
+ tk_path_name command_name

+
+ where command_name is any valid window command + for the type of window indicated by tk_path_name. +
+
+ +

Summary:

+
+ The tk_path_name command is unique for each window + that is created in magic. The name of the window is + registered as a command name with the Tcl interpreter. + When the window name is used as a command, the arguments + of the command are passed to the magic command + interpreter to be executed in the context of that + specific window. Effectively, it is the same as typing + the macro ":" (colon) in a layout window, and then + typing the command on the command line.

+ + For example, the default first window that is created in + the Tcl GUI version of magic is .layout1.magic. + Upon creation, the command name .layout1.magic is + registered with the Tcl interpreter. Subsequently, any + command on the command-line will be executed in relation + to that window if it is specified as an option to the + .layout1.magic command: +

+ .layout1.magic box 0 0 10 10 +
+ which is exactly the same as putting the X11 pointer + cursor in the layout window, typing the ":" + (colon) macro, then typing the command box 0 0 10 10 + into the command line and hitting the return key.

+ + Similarly to layout windows, windows created with the + specialopen command have their Tk path names registered + as commands with the Tcl interpreter, and can be passed + commands recognized by the specific window type (e.g., + netlist commands in the netlist special window). +

+ +

Implementation Notes:

+
+ tk_path_name is implemented as a built-in command + in magic which is registered with the Tcl interpreter + when the window is created and unregistered when the + window is destroyed. +
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 1:54pm

+ + diff --git a/doc/html/tool.html b/doc/html/tool.html new file mode 100644 index 00000000..995beb7e --- /dev/null +++ b/doc/html/tool.html @@ -0,0 +1,119 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

tool

+
+Change layout tool or print information about what the +button bindings are for the current tool. This page describes the +tool command as implemented in the non-Tcl version of magic. +
+ +

Shortcuts:

+
+ Key macro space implements the command tool.
+ Key macro shift-space implements the command tool box. +
+ +

Usage:

+
+ tool [name|info]

+
+ where name may be one of box, wiring, + netlist, or rsim. +
+
+ +

Summary:

+
+ The tool command selects or queries the mode of operation + of the mouse buttons in the layout window. Each tool + type has a unique set of button bindings.

+ + Without arguments, the tool command selects the next + tool type in round-robin fashion. With a tool type as argument, + the button bindings switch to those for the indicated tool. + With the info option, a summary of the mouse buttons is + given for the current tool.

+ + The mouse bindings for each of the three tools is as follows: +

    +
  • Box Tool +
    +
    left +
    Move the box so its lower-left corner is at cursor position +
    right +
    Resize box by moving upper-right corner to cursor position +
    middle +
    Paint box area with material underneath cursor +
    + In addition, you can move or resize the box by different corners + by pressing left or right, holding it down, moving the cursor + near a different corner and clicking the other (left or right) + button down then up without releasing the initial button. +
  • Wiring Tool +
    +
    left +
    Pick a wiring layer and width (same as "wire type") +
    right +
    Add a leg to the wire (same as "wire leg") +
    middle +
    Place a contact to switch layers (same as "wire switch") +
    +
  • Netlist Tool +
    +
    left +
    Select the net containing the terminal nearest the cursor +
    right +
    Toggle the terminal nearest the cursor into/out of current net +
    middle +
    Join current net and net containing terminal nearest the cursor +
    +
  • Rsim Tool +
    +
    left +
    +
    right +
    +
    middle +
    +
    +
+
+ +

Implementation Notes:

+
+ tool is implemented as a built-in command in the non-Tcl + version of magic. +
+ +

See Also:

+
+ tool (Tcl version) +
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 5:11pm

+ + diff --git a/doc/html/undo.html b/doc/html/undo.html new file mode 100644 index 00000000..5362d367 --- /dev/null +++ b/doc/html/undo.html @@ -0,0 +1,75 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

undo

+
+Undo commands +
+ +

Shortcuts:

+
+ Key macro U implements the command undo. +
+ +

Usage:

+
+ undo [print [count]]

+
+ where count indicates a number of events to be undone + (default 1 event), and must be a nonzero positive integer. +
+
+ +

Summary:

+
+ The undo command reverses the effect of the last + executed command (command-line, script, or macro-invoked), + returning the layout to the state it was in prior to + execution of that command.

+ + Certain commands in magic disable the undo mechanism, + thus preventing the command from being undone. These include + layout reads and writes, CIF, GDS, and LEF/DEF reads and + writes. + + The print option generates a stack trace of the top + count events in the undo stack, in excruciating + detail. +

+ +

Implementation Notes:

+
+ undo is implemented as a built-in window command in magic. +
+ +

See Also:

+
+ redo
+
+ +

+ + + +
Return to command index +
+

Last updated: October 15, 2004 at 5:55am

+ + diff --git a/doc/html/unexpand.html b/doc/html/unexpand.html new file mode 100644 index 00000000..bc6adc15 --- /dev/null +++ b/doc/html/unexpand.html @@ -0,0 +1,62 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

unexpand

+
+Unexpand everything inside or touching the cursor box. +
+ +

Usage:

+
+ unexpand

+
+ +

Shortcuts:

+
+ Key macro X implements the command unexpand.
+
+ +

Summary:

+
+ The unexpand command unexpands the view of subcells to + hide the contents of the subcells and show the bounding box + outline only. The unexpand command unexpands all subcells + that touch or intersect the cursor box in the layout window.

+

+ +

Implementation Notes:

+
+ unexpand is implemented as a built-in magic command. +
+ +

See Also:

+
+ expand
+
+ +

+ + + +
Return to command index +
+

Last updated: October 16, 2004 at 1:58pm

+ + diff --git a/doc/html/unmeasure.html b/doc/html/unmeasure.html new file mode 100644 index 00000000..a24acef9 --- /dev/null +++ b/doc/html/unmeasure.html @@ -0,0 +1,57 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

unmeasure

+
+Remove a ruler generated with the measure script. +
+ +

Usage:

+
+ unmeasure

+
+ +

Summary:

+
+ The unmeasure command is a script that removes a ruler + that was created with the corresponding measure command. + Any ruler that is found within the cursor box will be removed. +
+ +

Implementation Notes:

+
+ unmeasure is implemented as a Tcl procedure in the "tools" + script. +
+ +

See Also:

+
+ measure
+
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 9:20pm

+ + diff --git a/doc/html/updatedisplay.html b/doc/html/updatedisplay.html new file mode 100644 index 00000000..e1a369de --- /dev/null +++ b/doc/html/updatedisplay.html @@ -0,0 +1,67 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

updatedisplay

+
+Force display update, or suspend/resume updates +
+ +

Usage:

+
+ updatedisplay [suspend|resume]

+
+ +

Summary:

+
+ The updatedisplay command allows the display redraw to + be suspended and resumed. The main situation where this is + useful is inside a script or series of commands, where it is + not desired to have the display refresh at each step. Areas + needing to be redrawn will accumulate and be processed all at + once when updatedisplay resume is called.

+ + Calls to updatedisplay suspend can be nested, so that + the display will not update until the same number of calls + to updatedisplay resume have been encountered.

+ + Without arguments, updatedisplay forces an immediate + display redraw. +

+ +

Implementation Notes:

+
+ updatedisplay is implemented as a built-in window command in magic. +
+ +

See Also:

+
+ suspendall
+ resumeall
+
+ +

+ + + +
Return to command index +
+

Last updated: October 9, 2004 at 1:45am

+ + diff --git a/doc/html/upsidedown.html b/doc/html/upsidedown.html new file mode 100644 index 00000000..d82bb1bd --- /dev/null +++ b/doc/html/upsidedown.html @@ -0,0 +1,61 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

upsidedown

+
+Flip selection and box upside down +
+ +

Shortcuts:

+
+ Key macro F implements the command upsidedown. +
+ +

Usage:

+
+ upsidedown

+
+ +

Summary:

+
+ The upsidedown command flips the selection from top to bottom. + Flipping is done such that the lower left-hand corner of the + selection remains in the same place through the flip. +
+ +

Implementation Notes:

+
+ upsidedown is implemented as a built-in command in magic. +
+ +

See Also:

+
+ sideways
+
+ +

+ + + +
Return to command index +
+

Last updated: October 8, 2004 at 6:17am

+ + diff --git a/doc/html/version.html b/doc/html/version.html new file mode 100644 index 00000000..2e04dc41 --- /dev/null +++ b/doc/html/version.html @@ -0,0 +1,51 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

version

+
+Print version and revision info +
+ +

Usage:

+
+ version

+
+ +

Summary:

+
+ The version command prints the version number and revision + number of magic, and + the compilation date and time. +
+ +

Implementation Notes:

+
+ version is implemented as a built-in command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 3:19pm

+ + diff --git a/doc/html/view.html b/doc/html/view.html new file mode 100644 index 00000000..2bc64671 --- /dev/null +++ b/doc/html/view.html @@ -0,0 +1,73 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

view

+
+Zoom window out so everything is visible, or zoom window to the specified +area bounds. +
+ +

Shortcuts:

+
+ Key macro v implements the command view. +
+ +view [get|bbox|llx lly urx ury] +

Usage:

+
+ view [get|bbox|llx lly urx ury

+
+ where llx lly urx ury are layout dimensions to become + the screen view limits. +
+
+ +

Summary:

+
+ The view command is most often used without arguments to + center and scale the screen view of the layout window to fit the layout.

+ + view bbox returns the bounding box dimensions of the layout, + in the coordinate system of the layout.

+ + view get returns the coordinates of the screen limits in + the coordinate system of the layout (internal database units).

+ + view llx lly urx ury sets the view so that the + corners of the screen are at the indicated positions in the + coordinate system of the layout. Where the dimensions do not + match exactly to the screen aspect ratio, the view will be + centered on the indicated coordinates. +

+ +

Implementation Notes:

+
+ view is implemented as a built-in command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 9, 2004 at 1:59am

+ + diff --git a/doc/html/what.html b/doc/html/what.html new file mode 100644 index 00000000..d03c5105 --- /dev/null +++ b/doc/html/what.html @@ -0,0 +1,67 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

what

+
+Print out information about what material is in the current selection. +Short summary. +
+ +

Shortcuts:

+
+ Key macro / (slash) implements the command what. +
+ +

Usage:

+
+ what [-list]

+
+ +

Summary:

+
+ The what command queries what material is in the current + selection. This includes a report on layers, labels, and subcell + instances that are selected.

+ + In the Tcl version of magic, the -list option + returns the result as a Tcl list containing three sub-lists. + The first sub-list contains the types found, the second contains + the labels found, and the third contains the subcells found. + Each label in the second sub-list is itself a list of three + items: The label text, the layer the label is attached to, and + the cell def containing the label. Each subcell in the third + sub-list is itself a list of two items: The subcell instance + ID name, and the cell definition name. +

+ +

Implementation Notes:

+
+ what is implemented as a built-in command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 15, 2004 at 6:25am

+ + diff --git a/doc/html/wind3d/cif.html b/doc/html/wind3d/cif.html new file mode 100644 index 00000000..552ec989 --- /dev/null +++ b/doc/html/wind3d/cif.html @@ -0,0 +1,85 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

cif

+
+Switch to/from CIF layers display +
+ +

Shortcuts:

+
+ Key macro C implements the command cif. +
+ +

Usage:

+
+ cif

+
+ +

Summary:

+
+ The cif command toggles between the view of the layout + as CIF (equivalently, GDS) layers, and the magic database + layers. The view of CIF/GDS layers is default, because the + representation of contacts is much clearer in the CIF/GDS + view.

+ + To view CIF/GDS layers in the 3D rendering window, it is + necessary to have rendering information in the technology + file for each CIF/GDS layer, presented in the cifoutput + section with the render keyword. This information + includes the style with which to render the layer, and + height and thickness information for each layer. Note that + this height and thickness is currently used only for rendering + purposes, and so values are effectively arbitrary. Height + and thickness values corresponding to the magic + database layers can be provided in the extract section + of the technology file, and is used for three-dimensional + geometry extraction as well as the 3D window viewing of the + magic database layers. +

+ +

Implementation Notes:

+
+ cif is implemented as a built-in wind3d + window command in magic. It can only be invoked from + a window created with the specialopen wind3d command, + or the render procedure. Note that the wind3d + window is only available when magic is compiled with the OpenGL + graphics option and invoked with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". +

+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/closewindow.html b/doc/html/wind3d/closewindow.html new file mode 100644 index 00000000..09840069 --- /dev/null +++ b/doc/html/wind3d/closewindow.html @@ -0,0 +1,71 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

closewindow

+
+Close the 3D display +
+ +

Usage:

+
+ closewindow +
+ +

Summary:

+
+ The closewindow command closes the 3D display window. + Note that the syntax of closewindow is different for + the 3D display window than for other windows, which use the + default window client closewindow command. +
+ +

Implementation Notes:

+
+ closewindow is implemented as a built-in wind3d + window command in magic. It overrides the default + window client closewindow command. Note that the + wind3d window is only available when magic is + compiled with the OpenGL graphics option and invoked with + magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". When invoked with the Tcl procedure + render, the default window name is ".render.magic". +

+ +

See Also:

+
+ closewindow
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/cutbox.html b/doc/html/wind3d/cutbox.html new file mode 100644 index 00000000..e1df3fea --- /dev/null +++ b/doc/html/wind3d/cutbox.html @@ -0,0 +1,75 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

cutbox

+
+Set a clipping rectangle for the 3D view. +
+ +

Usage:

+
+ cutbox [none|box|llx lly urx ury]

+
+ where llx lly urx ury are points of a rectangle in the + coordinate system of magic. +
+
+ +

Summary:

+
+ The cutbox command generates a clipping rectangle on the + layout. This is used for two purposes: Limiting the amount of + output to generate for a large layout, and to create vertical + or orthogonal cross-sections of a layout.

+ + cutbox none removes any existing cutbox. cutbox box + creates a cutbox equal to the cursor box boundary. Otherwise, + cutbox is followed by two coordinate pairs representing + the cutbox lower-left and upper-right corners, in magic + (not CIF/GDS) units.

+

+ +

Implementation Notes:

+
+ cutbox is implemented as a built-in wind3d + window command in magic. It can only be invoked from + a window created with the specialopen wind3d command, + or the render procedure. Note that the wind3d + window is only available when magic is compiled with the OpenGL + graphics option and invoked with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". +

+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/defaults.html b/doc/html/wind3d/defaults.html new file mode 100644 index 00000000..ec418a9b --- /dev/null +++ b/doc/html/wind3d/defaults.html @@ -0,0 +1,71 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

defaults

+
+Revert to default view scale and position. +
+ +

Shortcuts:

+
+ Key macro space implements the command defaults. +
+ +

Usage:

+
+ defaults

+
+ +

Summary:

+
+ The defaults command reverts the scale and angle + settings of the view to the default values. The default + scale fits the layout to the size of the 3D viewing window. + The default rotation is a view from directly above the + layout, which matches the view in the layout window. +
+ +

Implementation Notes:

+
+ defaults is implemented as a built-in wind3d + window command in magic. It can only be invoked from + a window created with the specialopen wind3d command, + or the render procedure. Note that the wind3d + window is only available when magic is compiled with the OpenGL + graphics option and invoked with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". +

+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/help.html b/doc/html/wind3d/help.html new file mode 100644 index 00000000..799956b8 --- /dev/null +++ b/doc/html/wind3d/help.html @@ -0,0 +1,73 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

help

+
+Print the command list and usage for all of the 3D viewing window commands. +
+ +

Shortcuts:

+
+ Key macros ? and h implement the command + help. +
+ +

Usage:

+
+ help +
+ +

Summary:

+
+ The help command prints the command list for commands + known to the wind3d window, along with a line of text + summarizing the command usage. It is separate from the help + procedure for magic as invoked from the console + (terminal). It does not, for instance, accept a "pattern" + argument. +
+ +

Implementation Notes:

+
+ help is implemented as a built-in wind3d + window command in magic. It can only be invoked from + a window created with the specialopen wind3d command, + or the render procedure. Note that the wind3d + window is only available when magic is compiled with the OpenGL + graphics option and invoked with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". +

+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/level.html b/doc/html/wind3d/level.html new file mode 100644 index 00000000..50c76db4 --- /dev/null +++ b/doc/html/wind3d/level.html @@ -0,0 +1,79 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

level

+
+Set the rendering level +
+ +

Shortcuts:

+
+ Key macro L raises the rendering level by 1.
+ Key macro l lowers the rendering level by 1. +
+ +

Usage:

+
+ level [n]

+
+ where n is a non-zero, positive integer. +
+
+ +

Summary:

+
+ The level command sets the rendering level to n, + if given, or else returns the current rendering level. + There are two rendering levels in this implementation. + Rendering level 1 (one) uses OpenGL line and polygon + antialiasing. Rendering level 0 (zero) does not use + antialiasing, so yields a coarser but faster rendering. + The wish-list for the future includes higher rendering + levels to represent rounded edges on wells and diffusion, + and a more accurate vertical profile. +
+ +

Implementation Notes:

+
+ level is implemented as a built-in wind3d + window command in magic. It can only be invoked from + a window created with the specialopen wind3d command, + or the render procedure. Note that the wind3d + window is only available when magic is compiled with the OpenGL + graphics option and invoked with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". +

+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/refresh.html b/doc/html/wind3d/refresh.html new file mode 100644 index 00000000..342abddc --- /dev/null +++ b/doc/html/wind3d/refresh.html @@ -0,0 +1,68 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

refresh

+
+Refresh the 3D display +
+ +

Usage:

+
+ refresh +
+ +

Summary:

+
+ The refresh command clears and redraws the 3D window + display. The 3D display does not maintain areas requiring + updates like the layout window (this is very difficult to + do in 3 dimensions), so updating the view to reflect changes + made to the layout often requires a manual refresh. + However, all commands that change any aspect of the 3D + display will also cause a refresh. +
+ +

Implementation Notes:

+
+ refresh is implemented as a built-in wind3d + window command in magic. It can only be invoked from + a window created with the specialopen wind3d command, + or the render procedure. Note that the wind3d + window is only available when magic is compiled with the OpenGL + graphics option and invoked with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". +

+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/render.html b/doc/html/wind3d/render.html new file mode 100644 index 00000000..fb32732c --- /dev/null +++ b/doc/html/wind3d/render.html @@ -0,0 +1,81 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

render

+
+Specify properties of CIF layer rendering +
+ render name [height thick [style]] + +

Usage:

+
+ render name [height thick [style]]

+
+ where name is the CIF name of a CIF or GDS layer, + height and thick are values for the height + above substrate of the layer bottom, and the total layer + thickness, and style is a known display style from + the .dstyle file. +
+
+ +

Summary:

+
+ The render command can be used to replace or complement + the render lines in the cifoutput section of a + magic technology file. These lines specify, for each + CIF/GDS layer to be drawn, a height and thickness value, and + a style to use when drawing the layer.

+ + Note that normally, magic styles are used to draw + internal tile types, not CIF/GDS layers. Thus, each of these + layers must be mapped to a style before magic can draw them. + Without specification, the style defaults to zero (actual output + dependent on the contents of the .dstyle file), and + height and thickness also default to zero. +

+ +

Implementation Notes:

+
+ render is implemented as a built-in wind3d + window command in magic. It can only be invoked from + a window created with the specialopen wind3d command, + or the render procedure. Note that the wind3d + window is only available when magic is compiled with the OpenGL + graphics option and invoked with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". +

+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/scroll.html b/doc/html/wind3d/scroll.html new file mode 100644 index 00000000..741abee7 --- /dev/null +++ b/doc/html/wind3d/scroll.html @@ -0,0 +1,84 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

scroll

+
+Specify the 3D viewpoint position +
+ + scroll [x y z] + +

Shortcuts:

+
+ The arrow keys implement different aspects of the scroll + command, panning in the x and y directions relative to + the normal layout view. +
+ +

Usage:

+
+ scroll [x y z]

+
+ where x, y, and z represent the viewpoint + position in each of the axes. +
+
+ +

Summary:

+
+ The scroll command sets the 3D viewpoint position on + each of the axes, where the x and y origins are + equal to the layout origin, and the z origin is on the + substrate. Without arguments, returns the current viewpoint + position in the three axes. +
+ +

Implementation Notes:

+
+ scroll is implemented as a built-in wind3d + window command in magic. It overrides the default + window client scroll command. Note that the wind3d + window is only available when magic is compiled with the OpenGL + graphics option and invoked with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". +

+ +

See Also:

+
+ view
+ zoom
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/see.html b/doc/html/wind3d/see.html new file mode 100644 index 00000000..8e67712f --- /dev/null +++ b/doc/html/wind3d/see.html @@ -0,0 +1,77 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

see

+
+View or hide layers from the 3D view +
+ +

Usage:

+
+ see [no] layer

+
+ where layer is a magic layer type if the + current view is of magic layers, and is a + CIF layer name if the view is of CIF/GDS layers. +
+
+ +

Summary:

+
+ The see command is similar to the see command + in the layout window. It adds or subtracts layers from what + is viewed in the 3D window. By default, all layers are + displayed. The "see layer" command causes + layers to be displayed, while "see no layer" + causes them to be hidden. +
+ +

Implementation Notes:

+
+ see is implemented as a built-in wind3d + window command in magic. It can only be invoked from + a window created with the specialopen wind3d command, + or the render procedure. Note that the wind3d + window is only available when magic is compiled with the OpenGL + graphics option and invoked with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". +

+ +

See Also:

+
+ cif
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/view.html b/doc/html/wind3d/view.html new file mode 100644 index 00000000..a1704512 --- /dev/null +++ b/doc/html/wind3d/view.html @@ -0,0 +1,87 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

view

+
+Specify the 3D viewpoint angle +
+ +

Shortcuts:

+
+ Keys 1,2 [7,8] implement + x-axis coarse [fine] rotation.
+ Keys 3,4 [9,0] implement + y-axis coarse [fine] rotation.
+ Keys 5,6 [-,=] implement + z-axis coarse [fine] rotation. +
+ +

Usage:

+
+ view [x y z]

+
+ where x, y, and z are rotations + (in degrees) about each of the indicated axes. +
+
+ +

Summary:

+
+ The view command sets the viewing angle of the + 3D rendering window with respect to each of the primary + axes. +
+ +

Implementation Notes:

+
+ view is implemented as a built-in wind3d + window command in magic. It overrides the default + window client view command. Note that the wind3d + window is only available when magic is compiled with the OpenGL + graphics option and invoked with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d".

+ + Without arguments, the view command returns the + current viewing angle in degrees for each of the three + axes. +

+ +

See Also:

+
+ scroll
+ zoom
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wind3d/zoom.html b/doc/html/wind3d/zoom.html new file mode 100644 index 00000000..7bc4d400 --- /dev/null +++ b/doc/html/wind3d/zoom.html @@ -0,0 +1,101 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

zoom

+
+Specify rendering scale. +
+ +

Shortcuts:

+
+ Key macro Z implements a zoom-out function.
+ Key macro z implements a zoom-in function.
+ Key macro < decreases the vertical scale.
+ Key macro > increases the vertical scale. +
+ +

Usage:

+
+ zoom [xy z]

+
+ where xy is the scale in both x and y + dimensions (which cannot be set differently from each other), + and z is the scale in the z (vertical) direction. +
+
+ +

Summary:

+
+ The zoom command changes the scale of the 3D rendering, + effectively moving the viewpoint closer to or farther away from + the vertical axis origin.

+ + Three-dimensional rendered views of layout usually exaggerate + the vertical axis (like topographical maps of the Earth) to + allow the vertical structure to be more readily viewed and + understood. The vertical axis scaling is therefore arbritrary, + and may be set independently of the other axes.

+ + Note that the z-axis value is represented such that + it is independent of changes in the xy zooming. + Key macros implementing zoom-in and zoom-out functions + effectively change the scaling factor of all three + viewing axes simultaneously, so that the vertical scale + remains proportional to the horizontal scales. This does + not change the zoom value of z reported by the + zoom command.

+ + Without arguments, zoom returns the current scalefactors + in both the xy axes (combined) and z axis. +

+ +

Implementation Notes:

+
+ zoom is implemented as a built-in wind3d + window command in magic. It overrides the + default window client zoom command. Note that the + wind3d window is only available when magic is + compiled with the OpenGL graphics option and invoked + with magic -d OGL.

+ + Note that macros of the wind3d window are hard-coded, + and cannot be changed with the macro, gmacro, or + imacro commands. There is no ":" macro for + entering commands; to enter commands from the command-line, + use the tk_path_name + command. The default Tk path name of the wind3d window + is ".magic3d". +

+ +

See Also:

+
+ scroll
+ view
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/windowborder.html b/doc/html/windowborder.html new file mode 100644 index 00000000..4b935c7b --- /dev/null +++ b/doc/html/windowborder.html @@ -0,0 +1,56 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

windowborder

+
+Toggle border drawing for new windows +
+ +

Usage:

+
+ windowborder [on|off]

+
+ +

Summary:

+
+ The windowborder command turns the drawing of the window + border on or off. Normally, this will be on in the non-GUI + version of magic, and off in the GUI version, where the + border area is handled by the Tk frame window. + + Note that the command does not affect the current layout windows, + but takes effect for all windows created after the command has + been called. +
+ +

Implementation Notes:

+
+ windowborder is implemented as a built-in window command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 9, 2004 at 2:20am

+ + diff --git a/doc/html/windowcaption.html b/doc/html/windowcaption.html new file mode 100644 index 00000000..db87461b --- /dev/null +++ b/doc/html/windowcaption.html @@ -0,0 +1,57 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

windowcaption

+
+Toggle title caption for new windows +
+ +

Usage:

+
+ windowcaption [on|off]

+
+ +

Summary:

+
+ The windocaption command turns the drawing of the window + title area (caption) on or off. Normally, this will be on + in the non-GUI version of magic, and off in the GUI version, + where the title area is handled by the Tk frame window and the + caption procedure.

+ + Note that the command does not affect the current layout windows, + but takes effect for all windows created after the command has + been called. +

+ +

Implementation Notes:

+
+ windocaption is implemented as a built-in command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 9, 2004 at 2:21am

+ + diff --git a/doc/html/windownames.html b/doc/html/windownames.html new file mode 100644 index 00000000..df73f760 --- /dev/null +++ b/doc/html/windownames.html @@ -0,0 +1,71 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

windownames

+
+Get name of current or all windows +
+ +

Usage:

+
+ windownames [all|type]

+
+ where type is one of the window types known + to the specialopen command, which are: + layout, wind3d, color, and netlist. +
+
+ +

Summary:

+
+ The windownames command returns a list of magic + windows as specified by the command options. No options is + equivalent to option all, and prints the names of all + existing windows. Otherwise, windows can be listed by type, + where type is the type of window as understood by the + specialopen command.

+ + The Tcl/Tk version of magic returns the full Tk path name of each + window, including any parent frames. The non-Tcl/Tk version of + magic returns window IDs (the ID is an integer number used by the + setpoint command. +

+ +

See Also:

+
+ setpoint
+
+ +

Implementation Notes:

+
+ windownames is implemented as a built-in command in magic. + The Tcl version returns a Tcl list of Tk path names for each window. + The non-Tcl version of magic writes the window list to standard output. +
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 8:40pm

+ + diff --git a/doc/html/windowscrollbars.html b/doc/html/windowscrollbars.html new file mode 100644 index 00000000..e0dc0f87 --- /dev/null +++ b/doc/html/windowscrollbars.html @@ -0,0 +1,57 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

windowscrollbars

+
+Toggle scroll bars for new windows +
+ +

Usage:

+
+ windowscrollbars [on|off]

+
+ +

Summary:

+
+ The windowscrollbars command turns the drawing of the window + scrollbars on or off. Normally, this will be on in the non-GUI + version of magic, and off in the GUI version, where the + scrollbars are handled by the Tk frame window and the GUI "wrapper" + script.

+ + Note that the command does not affect the current layout windows, + but takes effect for all windows created after the command has + been called. +

+ +

Implementation Notes:

+
+ windowscrollbars is implemented as a built-in window command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October 9, 2004 at 2:22am

+ + diff --git a/doc/html/wire.html b/doc/html/wire.html new file mode 100644 index 00000000..f9f11cbe --- /dev/null +++ b/doc/html/wire.html @@ -0,0 +1,114 @@ + +

See Also:

+
+ wire
+
+ + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

wire

+
+Generate wires from the command line. +
+ +

Shortcuts:

+
+ Mouse buttons in conjunction with the wire tool implement + various wire commands (see the tool command + reference). +
+ +

Usage:

+
+ wire option

+
+ where option may be one of the following: +
+
help +
Print help information +
horizontal +
Add a new horizontal wire leg +
leg +
Add a new horizontal or vertical leg +
switch [layer width] +
Place contact and switch layers +
type [layer width] +
Select the type and size of wires +
vertical +
add a new vertical wire leg +
segment layer width x1 y1 x2 y2... [-noendcap] +
Paint one or more wire segments +
show +
Determine where the next wire leg will be according to + the rules for wire leg, but place the result in + the selection buffer rather than directly on the layout. +
increment layer +
Change the layer type used for wires to the wire type on + the plane above the plane of the current wire type. +
decrement layer +
Change the layer type used for wires to the wire type on + the plane below the plane of the current wire type. +
increment width +
Increment the width of the current wire by 1 internal unit. +
decrement width +
Decrement the width of the current wire by 1 internal unit. +
+
+
+ +

Summary:

+
+ The wire command allows quick generation of wires on the + layout. Some of these commands are bound to mouse button events + in the wire tool, making a convenient interface for fast wiring + where full netlist routing is not required. Due to the presence + of the wire tool, most of these commands are not typically called + from the command line.

+ + The wire segment command can generate non-Manhattan segments. + All other wiring commands generate only Manhattan routes. This + command places wire segments in relation to the centerline + coordinates specified by x1 y1, x2 y2, and so forth. + By default, wires are drawn with an endcap extension of one-half + the wire width. The -noendcap option causes the wire to + end at the coordinate, with no extension. The wire segment + command is intended to be used from Tcl scripts for automatic + layout generation. +

+ +

Implementation Notes:

+
+ wire is implemented as a built-in command in magic. +
+ +

See Also:

+
+ polygon
+
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 8:38pm

+ + diff --git a/doc/html/wizard/coord.html b/doc/html/wizard/coord.html new file mode 100644 index 00000000..00aa77a3 --- /dev/null +++ b/doc/html/wizard/coord.html @@ -0,0 +1,61 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*coord

+
+Show coordinates of setpoint, cursor box, root cell, and edit cell. +
+ + +

Usage:

+
+ *coord +
+ +

Summary:

+
+ The *coord command shows coordinates of the current set + point (point tool), cursor box (box tool), root cell, and edit cell. + Coordinate values are prefixed as follows: +
+
e +
Edit cell coordinate system +
r +
Root cell coordinate system +
+ If the cursor is not in the window in which the command has been + executed, then the point is not reported. If the box + does not exist in the window, then the box is not reported. +
+ +

Implementation Notes:

+
+ *coord is implemented as a built-in "wizard" command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/crash.html b/doc/html/wizard/crash.html new file mode 100644 index 00000000..63a6dcf7 --- /dev/null +++ b/doc/html/wizard/crash.html @@ -0,0 +1,53 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*crash

+
+Cause a core dump. +
+ + +

Usage:

+
+ *crash +
+ +

Summary:

+
+ The *crash command calls the niceabort() routine, + thereby causing an immediate program crash. If no limits + are set by the shell, the core is dumped. +
+ +

Implementation Notes:

+
+ *crash is implemented as a built-in window "wizard" + command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/extract.html b/doc/html/wizard/extract.html new file mode 100644 index 00000000..5101c35e --- /dev/null +++ b/doc/html/wizard/extract.html @@ -0,0 +1,92 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*extract

+
+Debug the circuit extractor +
+ +

Usage:

+
+ *extract option

+
+ where option may be one of the following: +
+
clrdebug [flags] +
+
clrlength +
+
driver terminalname +
+
interactions [halo [bloat]] +
+
intercount [halo [filename]] +
+
parents +
+
reciever terminalname +
+
setdebug [flags] +
+
showdebug +
+
showparents +
+
showtech [filename | -] +
Display the technology-specific tables maintained for circuit + extraction in a human-readable format. Intended mainly for + debugging technology files. If the argument filename + is "-", the output is to the standard output; otherwise, + it is to the file whose name is filename. +
stats +
+
step [stepsize] +
Set or report interaction step size. +
times [filename] +
+
+
+
+ +

Summary:

+
+ The *extract command gives assorted detailed information + about the operation of the circuit extractor. +
+ +

Implementation Notes:

+
+ *extract is implemented as a built-in "wizard" command in magic. +
+ +

See Also:

+
+ extract
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/files.html b/doc/html/wizard/files.html new file mode 100644 index 00000000..cf365797 --- /dev/null +++ b/doc/html/wizard/files.html @@ -0,0 +1,53 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*files

+
+Printe out currently open files. +
+ + +

Usage:

+
+ *files +
+ +

Summary:

+
+ The *files command reports on all files that magic + is currently holding open, reporting the file type and + file descriptor. +
+ +

Implementation Notes:

+
+ *files is implemented as a built-in window "wizard" + command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/grstats.html b/doc/html/wizard/grstats.html new file mode 100644 index 00000000..7df5b433 --- /dev/null +++ b/doc/html/wizard/grstats.html @@ -0,0 +1,54 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*grstats

+
+Print out statistics on graphics. +
+ + +

Usage:

+
+ *grstats count [style]

+ where count and style are integers. +
+ +

Summary:

+
+ The *grstats command does a screen update and + reports on the number of rectangles drawn, and gives + an estimate of the rendering speed for rectangle drawing. +
+ +

Implementation Notes:

+
+ *grstats is implemented as a built-in window "wizard" + command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/pause.html b/doc/html/wizard/pause.html new file mode 100644 index 00000000..7f1ee2d6 --- /dev/null +++ b/doc/html/wizard/pause.html @@ -0,0 +1,53 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*pause

+
+Print arguments and wait for the return key to be pressed. +
+ + +

Usage:

+
+ *pause [args] +
+ +

Summary:

+
+ The *pause command prints out the arguments passed + to the command and waits for the carriage-return to be + pressed, effectively suspending the program. +
+ +

Implementation Notes:

+
+ *pause is implemented as a built-in window "wizard" + command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/plow.html b/doc/html/wizard/plow.html new file mode 100644 index 00000000..7000f65c --- /dev/null +++ b/doc/html/wizard/plow.html @@ -0,0 +1,102 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*plow

+
+Debug the plowing mechanism +
+ +

Usage:

+
+ *plow option

+
+ where option may be one of the following: +
+
clrdebug flags +
+
help +
+
jogreduce +
+
lwidth layers +
+
lshadow layers +
+
mergedown +
+
mergeup +
+
move +
+
outline direction layers +
+
plow direction [layers] +
+
print +
+
random +
+
setdebug flags +
+
shadow layers +
+
showdebug +
+
split +
+
techshow [file] +
+
trail [value] +
+
whenbot [xbot ybot] +
+
whentop [xtop ytop] +
+
width layers +
+
+
+
+ +

Summary:

+
+ The *plow command reports assorted information about the + plow mechanism. +
+ +

Implementation Notes:

+
+ *plow is implemented as a built-in "wizard" command in magic. +
+ +

See Also:

+
+ plow
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/psearch.html b/doc/html/wizard/psearch.html new file mode 100644 index 00000000..9b3d5e39 --- /dev/null +++ b/doc/html/wizard/psearch.html @@ -0,0 +1,56 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*psearch

+
+Invoke point search over box area +
+ +

Usage:

+
+ *psearch plane count

+
+ where plane is a valid plane name for the + current technology, and count is the number of + searches to perform. +
+
+ +

Summary:

+
+ The *psearch command runs a point search a specified number + of times from the point at the lower-left corner of the box tool to + each point in the edit cell. +
+ +

Implementation Notes:

+
+ *psearch is implemented as a built-in "wizard" command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/showtech.html b/doc/html/wizard/showtech.html new file mode 100644 index 00000000..6ad15827 --- /dev/null +++ b/doc/html/wizard/showtech.html @@ -0,0 +1,61 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*showtech

+
+Print internal technology tables. +
+ +

Usage:

+
+ *showtech [-v] [file]

+
+ where file is the name of a file to which to direct output. +
+
+ +

Summary:

+
+ The *showtech command prints information from the current + technology, including information from the layers, planes, + connect, compose, and contact sections. + The "-v" flag, if specified, prints detailed information + about the paint and erase tables (which can be very large). +
+ +

Implementation Notes:

+
+ *showtech is implemented as a built-in "wizard" command in magic. +
+ +

See Also:

+
+ tech
+
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/tilestats.html b/doc/html/wizard/tilestats.html new file mode 100644 index 00000000..1c86c065 --- /dev/null +++ b/doc/html/wizard/tilestats.html @@ -0,0 +1,56 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*tilestats

+
+Print statistics on tile utilization +
+ +

Usage:

+
+ *tilestats [-a] [file]

+
+ where file is the name of a file to which to redirect output. +
+
+ +

Summary:

+
+ The *tilestats command reports various statistics on tile + plane utilization. + The "-a" switch, if specified, causes output to be generated + for all cells in the database. Otherwise, output is generated for + only the currently selected cell. +
+ +

Implementation Notes:

+
+ *tilestats is implemented as a built-in "wizard" command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/tsearch.html b/doc/html/wizard/tsearch.html new file mode 100644 index 00000000..b484b406 --- /dev/null +++ b/doc/html/wizard/tsearch.html @@ -0,0 +1,59 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*tsearch

+
+Invoke an area search over box area +
+ +

Usage:

+
+ *tsearch plane count [mask [mayo|new]]

+
+ where plane is a valid plane name in the current + technology, and count is the number of searches to + be performed. mask is a layer list to restrict the + scope of the search, and the remaining optional arguments + implement different search algorithms. +
+
+ +

Summary:

+
+ The *tsearch command calls the internal hierarchical tile + search routine a specified number of times over an area the size + and shape specified by the box, each time over a different area in + the edit cell. +
+ +

Implementation Notes:

+
+ *tsearch is implemented as a built-in "wizard" command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/watch.html b/doc/html/wizard/watch.html new file mode 100644 index 00000000..c4ff3242 --- /dev/null +++ b/doc/html/wizard/watch.html @@ -0,0 +1,72 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*watch

+
+Enable (disable) annotated tile plane display +
+ +

Usage:

+
+ *watch [plane] [demo] [types]

+
+ where plane is a valid plane name in the current + technology. +
+
+ +

Summary:

+
+ The *watch command generates an annotated layout display + which shows the structure of the tile plane in the corner-stitched + database representation.

+ + The demo option produces arrows at the stitch corners + illustrating which tiles are directly referenced by pointers + in the database tile structure.

+ + The types option shows the name of the tile type for + each tile, instead of the default display, which is the memory + address (in hexidecimal) of the tile, in large print, and the + memory address of the four stitched tiles, in small print.

+ + *watch without arguments clears the display of annotations + and returns to the normal layout view. Note that *watch + only allows one plane at a time to be annotated. Also note that + some commands such as edit will cause the annotation not + to be synchronized with the current display or current edit cell, + and may require the *watch to be executed again to display + the correct tiles. +

+ +

Implementation Notes:

+
+ *watch is implemented as a built-in "wizard" command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/winddebug.html b/doc/html/wizard/winddebug.html new file mode 100644 index 00000000..984de44a --- /dev/null +++ b/doc/html/wizard/winddebug.html @@ -0,0 +1,54 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*winddebug

+
+Set debugging mode. +
+ + +

Usage:

+
+ *winddebug +
+ +

Summary:

+
+ The *winddebug command sets the debugging mode, which + reports on each command generated through the WindSend() + routine. This does not include Tcl commands or + commands generated on the command-line. +
+ +

Implementation Notes:

+
+ *winddebug is implemented as a built-in window "wizard" + command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/wizard/winddump.html b/doc/html/wizard/winddump.html new file mode 100644 index 00000000..5bdaee17 --- /dev/null +++ b/doc/html/wizard/winddump.html @@ -0,0 +1,55 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

*winddump

+
+Printe out debugging information. +
+ + +

Usage:

+
+ *winddump +
+ +

Summary:

+
+ The *winddump command prints the list of window clients + and the pointers to their create, delete, and redisplay routines, + and the pointer to the client's command array. It also prints + a list of the windows open and reports the surface area, origin, + and scale of each. +
+ +

Implementation Notes:

+
+ *winddump is implemented as a built-in window "wizard" + command in magic. +
+ +

+ + + +
Return to command index +
+

Last updated: October, 2004

+ + diff --git a/doc/html/writeall.html b/doc/html/writeall.html new file mode 100644 index 00000000..5f3ba554 --- /dev/null +++ b/doc/html/writeall.html @@ -0,0 +1,93 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

writeall

+
+Write out all modified cells to disk +
+ +

Shortcuts:

+
+ Key macro w implements the command writeall.
+ Key macro W implements the command writeall force. +
+ +

Usage:

+
+ writeall [force cell1 cell2...]

+
+ +

Summary:

+
+ The writeall command generates a popup dialog prompting + for action on writing each cell definition in the layout + hierarchy to disk. As shown in the figure below, the popup + dialog presents five choices: +
+
write +
Writes the single cell and continues the prompting for + the next cell. +
flush +
Reverts the cell to what was originally on the disk, like + the flush command. Continues prompting for the + next cell. +
skip +
No action for the indicated cell definition; continue + prompting for the next cell. +
abort +
Stop all writing and terminate the command with no further + prompting or processing. +
autowrite +
Write all the cells, with no further prompting. +
+ +
+
+
+ Figure 1. The popup dialog of the writeall command. +
+
+ + With the option write force, the command writes all cells + in the hierarchy with no prompting. If one or more cell names + follows write force, the cells listed will be written + (action "write") and all other cells will be ignored (action + "skip"). +
+ +

Implementation Notes:

+
+ writeall is implemented as a built-in command in magic. +
+ +

See Also:

+
+ save
+
+ +

+ + + +
Return to command index +
+

Last updated: December 4, 2005 at 8:09pm

+ + diff --git a/doc/html/xload.html b/doc/html/xload.html new file mode 100644 index 00000000..285f4655 --- /dev/null +++ b/doc/html/xload.html @@ -0,0 +1,62 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

command_name

+
+Load a cell into a window unexpanded +
+ +

Usage:

+
+ xload cellname

+
+ where cellname is the name of a layout cell in the + database memory or on disk. +
+
+ +

Summary:

+
+ The xload command works exactly like the load + command, but keeps the top-level cell cellname + unexpanded. This can be useful for large layouts where + the expanded view takes a long time to redraw. +
+ +

Implementation Notes:

+
+ xload is implemented as a built-in command in magic. +
+ +

See Also:

+
+ load
+ xview
+
+ +

+ + + +
Return to command index +
+

Last updated: October 9, 2004 at 7:17am

+ + diff --git a/doc/html/xview.html b/doc/html/xview.html new file mode 100644 index 00000000..887f22d1 --- /dev/null +++ b/doc/html/xview.html @@ -0,0 +1,59 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

xview

+
+Change the view in the current layout window so that everything is +visible but unexpanded. +
+ +

Usage:

+
+ xview

+
+ +

Summary:

+
+ The xview command changes the view so that the layout + fits the window, as in the view command, but ensures + that all cells are unexpanded. This is useful for large + layouts where the full view can take a long time to refresh. +
+ +

Implementation Notes:

+
+ xview is implemented as a built-in command in magic. +
+ +

See Also:

+
+ view
+ xload
+
+ +

+ + + +
Return to command index +
+

Last updated: October 9, 2004 at 7:17am

+ + diff --git a/doc/html/zoom.html b/doc/html/zoom.html new file mode 100644 index 00000000..54eec620 --- /dev/null +++ b/doc/html/zoom.html @@ -0,0 +1,74 @@ + + + + +Magic-7.3 Command Reference + +

Magic VLSI Layout Tool Version 7.3 + *

+ +

zoom

+
+Zoom window by specified magnification factor. +
+ +

Shortcuts:

+
+ Key macro z implements the command zoom 0.5 (zoom out + by a factor of 2).
+ Key macro Z implements the command zoom 2 (zoom in + by a factor of 2). +
+ +

Usage:

+
+ zoom factor

+
+ where factor is any real value. Values larger than 1 + indicate a zoom in, while values smaller than 1 indicate a + zoom out. +
+
+ +

Summary:

+
+ The zoom command implements view scaling in the layout + window in and out by the indicated magnification factor.

+ + Note that several other commands effect a change in the view scale + factor, including findbox zoom and view with + coordinate arguments. +

+ +

Implementation Notes:

+
+ zoom is implemented as a built-in window command in magic. +
+ +

See Also:

+
+ center
+ view
+ findbox
+
+ +

+ + + +
Return to command index +
+

Last updated: October 9, 2004 at 7:23am

+ + diff --git a/doc/latexfiles/Makefile b/doc/latexfiles/Makefile new file mode 100644 index 00000000..5b0ba47a --- /dev/null +++ b/doc/latexfiles/Makefile @@ -0,0 +1,56 @@ +MAGICDIR = ../.. + +include $(MAGICDIR)/defs.mak + +PS_SRCDIR=../psfiles +PS_INSTDIR=$(LIBDIR)/magic/doc + +.SUFFIXES: .dvi .tex .ps + +GENDVI=tut1.dvi tut2.dvi tut3.dvi tut4.dvi tut5.dvi tut6.dvi \ + tut7.dvi tut8.dvi tut9.dvi tut10.dvi tut11.dvi \ + maint1.dvi maint2.dvi maint3.dvi maint4.dvi \ + introduction.dvi copyright.dvi addendum6_5.dvi \ + tutscm1.dvi tutscm2.dvi tutscm3.dvi tutscm4.dvi \ + tuttcl1.dvi tuttcl2.dvi tuttcl3.dvi tuttcl4.dvi tuttcl5.dvi \ + tutwrl1.dvi + +GENPS=tut1.ps tut2.ps tut3.ps tut4.ps tut5.ps tut6.ps \ + tut7.ps tut8.ps tut9.ps tut10.ps tut11.ps \ + maint1.ps maint2.ps maint3.ps maint4.ps \ + introduction.ps copyright.ps addendum6_5.ps \ + tutscm1.ps tutscm2.ps tutscm3.ps tutscm4.ps \ + tuttcl1.ps tuttcl2.ps tuttcl3.ps tuttcl4.ps tuttcl5.ps \ + tutwrl1.ps + +SRC_GENPS= $(GENPS:%=${PS_SRCDIR}/%) +INST_GENPS= $(GENPS:%=$(DESTDIR)${PS_INSTDIR}/%) + +all: $(SRC_GENPS) + @${RM} $(GENDVI) *.log *.aux + +install: $(DESTDIR)${PS_INSTDIR} ${INST_GENPS} + +$(DESTDIR)${PS_INSTDIR}: make-doc-dir + +make-doc-dir: + ${SCRIPTS}/mkdirs $(DESTDIR)${PS_INSTDIR} + +$(DESTDIR)${PS_INSTDIR}/%: ${PS_SRCDIR}/% $(DESTDIR)${PS_INSTDIR} + ${CP} ${PS_SRCDIR}/$* $(DESTDIR)${PS_INSTDIR}/$* + +.tex.ps: + @echo "Converting $*.tex -> $*.dvi" + @latex $*.tex < /dev/null > /dev/null + @if grep 'LaTeX Warn' $*.log; \ + then \ + echo "Detected warnings, doing second pass for $*...";\ + latex $*.tex < /dev/null > /dev/null; \ + (grep 'LaTeX Warn' $*.log || (echo > /dev/null)); \ + echo; \ + fi + @echo "Converting $*.dvi -> $(PS_SRCDIR)/$*.ps" + @dvips -t letter $*.dvi -o $(PS_SRCDIR)/$*.ps > /dev/null + +clean: + ${RM} $(GENDVI) $(SRC_GENPS) *.log *.aux diff --git a/doc/latexfiles/addendum6_5.tex b/doc/latexfiles/addendum6_5.tex new file mode 100644 index 00000000..8b3b5c89 --- /dev/null +++ b/doc/latexfiles/addendum6_5.tex @@ -0,0 +1,203 @@ +%---------------------------------------------------------------------------- +% Magic Addendum: Version 6.5 differences +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Addendum: Version 6.5 differences} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Stefanos Sidiropoulos} \\ + \vspace*{0.5in} + Center for Integrated Systems \\ + Stanford University \\ + Stanford, CA 94305 \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Affected Documents:} +\starti + \> Magic Tutorial \#6: Design-Rule Checking \\ + \> Magic Tutorial \#9: Format Conversion for CIF and Calma \\ + \> Magic Tutorial \#W-1: Design-Rule Extensions \\ + \> Magic Maintainer's Manual \#2: The Technology File \\ + \> Magic man pages: ext2sim(1), ext2spice(1), extflat(3), ext(5). +\endi + +\vspace*{0.25in} +\section{Introduction} + +Magic 6.5 has some significant modifications that make some of the +original version 6 documents obsolete. The purpose of this addendum +is to highlight these differences so that users can take advantage +of the new features. + +\section{Extractor Extensions} + +The 6.5 extractor uses double precision floating point numbers +to represent capacitances. Therefore all the capacitances +in (aF/sq-lambda) associated with +the {\itshape areacap, perimc, sidewall, sideoverlap} keywords +in the extract section of the technology file can be {\itshape floating point +numbers}. + +Additionally the extension of the capacitance to floating point numbers +affects the manual pages of ext2sim(1), ext2spice(1), extflat(3), ext(5) +which can be found in your local system under CAD{\_}HOME/man + +The 6.5 extractor shields the perimeter capacitance from layer to layer. +To facilitate this two new commands {\itshape planeorder, noplaneordering} +have been introduced and the {\itshape sideoverlap} command has been modified. +The syntax for the new commands is: + +\starti + \ii {\bfseries planeorder} {\itshape plane num } +\endi + +Where {\itshape plane} is one of the defined planes and {\itshape num} is a positive +integer indicating the ordering of this plane from lower to higher. So for +example the metal1 plane has order 3 while metal2 has order 4. + +In case you dont want to specify the order of the planes the extractor +will complain and assume a default one. If you want to suppress the +warning you just have to issue the keyword: + +\starti + \ii {\bfseries noplaneordering } +\endi + + +The {\itshape sideoverlap} keyword syntax has been altered to: + +\starti + \ii {\bfseries sideoverlap} {\itshape intypes outtypes ovtypes cap shieldtypes} +\endi + +where {\itshape intypes}, {\itshape outtypes}, and {\itshape ovtypes} are type-lists +and {\itshape cap} is capacitance in attofarads per lambda. +This is the capacitance associated with an edge with a type +in {\itshape intypes} on its inside and a type in {\itshape outtypes} on +its outside, that overlaps a tile whose type is in {\itshape ovtypes}. +If the {\itshape shieldtypes} is present however this shields the capacitance. +So for example to shield metal-2 to poly capacitance use: + +\starti + \ii {\bfseries sideoverlap} M2Cap \~{}M2Cap PolyCap 19.41 M1Cap +\endi + +\section{DRC Extensions} + +This version includes code fragments implemented in DEC-WRL by Don Stark +which enable to implement more complicated DRC rules. For a description +of these enhancements look in the magic tutorial \#W1 which can be +found in the file doc/tutwrl1.ps under the magic source tree. + +\section{CIF extensions} + +Two new commands have been integrated in the cif output section courtesy +of Steven Tell and Fred Heaton at UNC. + +The first new command is a command that +enables the generation of DRC correct layers at the top level (such as +the nwell in the SCMOS tech files). The syntax is: + +\starti + \ii {\bfseries min-width} {\itshape width } +\endi + +The width argument is in centimicrons. This command should be specified +within a layer sub-section of the cifoutput section of the technology +file. + +The second command is an extension to the squares cif output command. +Its syntax is: + +\starti + \ii {\bfseries squares-grid} {\itshape border size separation grid} +\endi + +The added argument is {\itshape grid}. It is +in units of centi-microns. In some technologies, all features +must fall on a specified grid. In our case, this was a .05 +micron grid. In the original implementation of magic, if lambda +was not set to some integral multiple of the grid one could +generate contacts that did not fall on grid boundaries. By +specifying the grid spacing, the new enhancement to the contact +generation code will allow contacts to be generated on grid. +This does introduce some problems. In particular, some odd +size contacts will not be able to generate a CIF contact structure +that is centered on its corresponding magic contact. This is +not a problem in most cases, except where an odd size contact +is shared between two cells. In this case, the CIF contact +strucuture might be shifted to the left during CIF generation +to get it on grid and the other cell might be shifted to the +right. The superposition of these two structures may create +an illegal contact size or spacing. Use with extreme care or combine +it with cifwidth and cifspacing rules to verify correct operation. + +\section{New commands} + +Three new commands have been introduced (based on the WRL code fragments +by Bob Mayo): + +\starti + \ii {\bfseries goto} {\itshape nodename} +\endi + +Places the box/cross over the node named {\itshape nodename}. + +\starti + \ii {\bfseries findlabel} {\itshape labelname} +\endi + +Places the box/cross over the label {\itshape nodename}. + +\starti + \ii {\bfseries flatten} {\itshape destname} +\endi + +Flattens the cell in the current layout window and places it in the cell +named {\itshape cellname}. The labels are changed to retain their hierarchical +prefixes. + +\end{document} diff --git a/doc/latexfiles/copyright.tex b/doc/latexfiles/copyright.tex new file mode 100644 index 00000000..1e044d3e --- /dev/null +++ b/doc/latexfiles/copyright.tex @@ -0,0 +1,40 @@ +%---------------------------------------------------------------------------- +% Magic copyright +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +%---------------------------------------------------------------------------- + +\begin{document} + +\pagestyle{empty} + + +\begin{center} +\vspace*{6.0in} +Copyright \copyright 1985, 1989, 1990 Regents of the University of California, \\ +Lawrence Livermore National Labs, Stanford University, and Digital \\ +Equipment Corporation. Permission to use, copy, modify, and distribute \\ +this software and its documentation for any purpose and without fee is \\ +hereby granted, provided that the above copyright notice appears in all \\ +copies. The copyright holders make no representations about the \\ +suitability of this software for any purpose. It is provided ``as is'' \\ +without express or implied warranty. Export of this software outside \\ +of the United States of America may require an export license. +\end{center} + +\end{document} diff --git a/doc/latexfiles/introduction.tex b/doc/latexfiles/introduction.tex new file mode 100644 index 00000000..213e2d8b --- /dev/null +++ b/doc/latexfiles/introduction.tex @@ -0,0 +1,266 @@ +%---------------------------------------------------------------------------- +% Magic Overview +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Overview of the DECWRL/Livermore Magic Release (Version~6)} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +\section{Introduction} + +This version of Magic, version 6, +gathers together work done by numerous people at +several institutions since Magic version 4 was released from Berkeley +on the 1986 VLSI tools tape. +This is a release of Magic and IRSIM only. You'll probably want to obtain +other tools by ordering the 1986 VLSI Tools Tape from Berkeley. + +This release has been prepared with the assistance of several groups. +Much of the new software came from Walter Scott's group at +the Lawrence Livermore National Labs (LLNL). +LLNL also provided partial funding to help prepare the release. +Digital Equipment Corporation's Western Research Lab (DECWRL) +helped out by providing computer equipment, a place to work, and +the services of one of us (Robert Mayo). Don Stark, Michael Arnold, and +Gordon Hamachi also worked on the release at DECWRL. +Stanford donated significant pieces of new code, including a simulation +system called IRSIM. +Other individuals and institutions have also contributed code and assistance +in ways too numerous to detail here. + +New features in Magic Version 6 include: + +\begin{itemize} +\item New and Improved Routing---{\itshape Michael Arnold and + Walter Scott of LLNL} \\ +Three major routing improvements have been made in this version of Magic. +There is a new, improved, global router courtesy of Walter Scott (of LLNL). +Walter Scott has also added a gate array router. See the ``garoute'' command +in the manual page for details. +Michael Arnold (of LLNL) has written an interactive maze router that allows +the user to specify hints to control the routing. See the documentation +for the ``iroute'' command. + +\item Extractor Enhancements---{\itshape Don Stark of Stanford and + Walter Scott of LLNL} \\ +The new ``extresis'' command, developed by Don Stark, provides +substantially better resistance extraction. Magic's +normal extraction (``extract'') lumps resistances on a +node into a single value. +In branching networks, this approximation is often not acceptable. +Resis was written to solve this problem. Walter Scott added accurate path +length extraction, an important feature when dealing with high speed +circuits, such as ECL. + +\item New contact structure---{\itshape Walter Scott and + Michael Arnold of LLNL and Don Stark of Stanford} \\ +Multilayer contacts are handled better. +In the previous version of Magic, there needed to be a separate contact type +for each possible combination of contact layers over a given point. This +caused a combinatorial explosion of tile types for multi-layer technologies +with stacked contacts. Under the new scheme, there are only a couple of +tile types for each layer: one that connects up, one that connects down, +and one that connects in both directions. + +\item Simulator Interface to IRSIM---{\itshape Stanford} \\ +A simulator interface is provided courtesy of Stanford. +See the commands ``startrsim'', ``simcmd'', and ``rsim''. +The irsim simulator, Stanford's much improved rewrite of esim, is included +in this distribution. +Credit goes to Mike Chow, Arturo Salz, and Mark Horowitz. + +\item New device/machine Support---{\itshape Various} \\ +X11 is fully supported in this release, and is the preferred interface. Older +drivers for graphics terminals and X10 are also included, but X11 is the +preferred interface (meaning it is better supported and you'll have lots of +company). Magic's X11 driver has a long history, starting with an X10 driver +by Doug Pan at Stanford. Brown University, the University of +Southern California, the University of Washington, and Lawrence Livermore +National Labs all prepared improved versions, some of them for X11. Don +Stark of Stanford took on the task of pulling these together and producing +the X11 driver in this release. + +Magic runs on a number of workstations, such as the DECstation 3100 and Sun's +SPARC processors. Partial Unix System V support is provided, via the +compilation flags mentioned below. The system also runs on the MacII. +Don Stark gets credit for the System V mods and support for HP machines, while +Mike Chow helped get it running on the MacII. + +To assist people with small machines (such as the Mac II), Magic can now be +compiled without some of its fancy features. Compilation flags are provided, +as indicated below, to eliminate things like routing, plotting, or calma output. +This is courtesy of Don Stark. + +\item Reorganization of Magic Source Directory \\ +Magic, as previously distributed, was set up with the assumption that lots of +people would be changing the code at the same time. As a result, the makefiles +did all sorts of paranoid things like making extra copies of the source code +whenever a module was re-installed. + +Since Magic is more stable now, this copying is no longer needed. Instead, +each makefile invokes the script {\bfseries ../:instclean} after installing a module. +This script, +by default, doesn't copy the source code but does leave the .o files around. +This cuts down on the disk space needed by a factor of two. +You can change the script if you want the copying, +or if you want to delete unused .o files to save even more disk space. + +\item Lots of bug fixes---{\itshape Various} \\ +Lots of bugs have been fixed in this release. We'd like to thank everybody +that has reported bugs in the past. If you find a new bug, please report +it as mentioned below. +\end{itemize} + +\section{Distribution Information} + +This version of Magic is available via FTP. Contact +``{\ttfamily magic@decwrl.dec.com}'' for information. + +For a handling fee, this version of Magic may be obtained on magnetic tape from: + +\starti + \ii EECS/ERL Industrial Liaison Program \\ + \ii 479 Cory Hall \\ + \ii University of California at Berkeley \\ + \ii Berkeley, CA 94720 +\endi + +\section{Bug Reports} + +Maintenance of Magic is a volunteer effort. Please send descriptions +of bugs via InterNet e-mail to ``{\ttfamily magic@decwrl.dec.com}'' +or via Uucp e-mail to ``{\ttfamily decwrl!magic}''. If you develop a +fix for the problem, please send that too! + +\section{Changes for Magic maintainers} + +Previous releases of Magic expected to find their +system files in the home directory of the user {\bfseries cad}. +The default behavior of version 6 is no different, but it +is possible to put the files in another directory by setting the +{\bfseries CAD{\_}HOME} +shell environment variable. If this variable is set, magic will use that +location instead of the \~{}cad it finds in the password file. + +\subsection{INSTALLING MAGIC} + +The distribution tape contains a version of Magic ready to run on Digital's +line of Ultrix RISC workstations, such as the DECstation 3100. For other +machines, read ahead. +In any event, all users should set their shell environment variable +CAD{\_}HOME to point to the place where the tape is loaded, unless that place +is \~{}cad, in which case things will default correctly. + +Before installing Magic, you should set your shell environment variable +CAD{\_}HOME to point to the place where you loaded the tape. +If you ``cd'' to the magic source directory (\${CAD{\_}HOME}/src/magic) you will find +a makefile. A ``{\bfseries make config}'' will run a configuration script that asks +questions about your configuration and sets up magic to be compiled for your +local environment. + +After running a ``make config'', you can run a ``{\bfseries make force}'' to force +a complete +recompilation of magic. A "{\bfseries make install}" will then copy the binaries to +the \${CAD{\_}HOME}/bin area, as well as install things in \${CAD{\_}HOME}/lib +and \${CAD{\_}HOME}/man. + +Included in this documentation +is a set of Magic maintainer's manuals. These should be read by anybody +interested in modifying Magic or by anybody that is having difficulty +installing it on their system. + +\subsection{Technology file changes} + +Users of Magic 4 should have little trouble switching to Magic 6. + +A new section, the {\bfseries mzrouter} section needs to be added to your technology +files. See the mzrouter section of the +tutorial {\itshape Magic Maintainer's Manual \#2: The Technology File} +for details. + +Display styles must be defined in the {\itshape .tech} file +for the mzrouter hint layers magnet, fence and rotate. We +suggest copying this information from the styles section of the +scmos technology file on the distribution tape. You'll also need to include +these display styles in your {\itshape .dstyle} file. + +\section{Beta-test Sites} + +We'd like to thank the beta-test sites that tried out this version of Magic, +reported bugs and fixes in a timely manner, and ported the code to new +machines: + +\starti +\> Mike Chow, Apple Computer \\ +\> Arun Rao, Arizona State University \\ +\> Richard Hughey, Brown University \\ +\> Rick Carley, Carnegie-Mellon University \\ +\> Hank Walker, Carnegie-Mellon University \\ +\> Christos Zoulas, Cornell University \\ +\> Andreas Andreou, John Hopkins University \\ +\> George Entenman, The Microelectronics Center of North Carolina \\ +\> Shih-Lien Lu, The MOSIS Service \\ +\> Jen-I Pi, The MOSIS Service \\ +\> Guntram Wolski, Silicon Engineering, Inc. \\ +\> Don Stark, Stanford University \\ +\> Gregory Frazier, University of California at Los Angeles \\ +\> Yuval Tamir, University of California at Los Angeles \\ +\> Steven Parkes, University of Illinois \\ +\> Larry McMurchie, University of Washington \\ +\> Tim Heldt, Washington State University \\ +\> David Lee, Xerox Palo Alto Research Center \\ +\endi + +Martin Harriman of Silicon Engineering wrote a ``select less'' command for +Magic during the beta-test phase. ``Select less'' has been a +much-requested feature. + +In addition to the persons named above, there were many other beta-test +users of Magic at these and other sites---too many to list here. We +appreciate their help. We also acknowledge the help of the pre-release +sites, who tested a version that included most of the fixes from the beta-test +phase. + +\end{document} diff --git a/doc/latexfiles/maint1.tex b/doc/latexfiles/maint1.tex new file mode 100644 index 00000000..550c08d7 --- /dev/null +++ b/doc/latexfiles/maint1.tex @@ -0,0 +1,646 @@ +%---------------------------------------------------------------------------- +% Magic Maintainer's Manual number 1: Installation and Development +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\= + \hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Maintainer's Manual \#1: Installation and Development} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape John Ousterhout} \\ + {\itshape Walter Scott} \\ + \vspace*{0.5in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + {\itshape Tim Edwards} \\ + MultiGiG, Inc. \\ + Scotts Valley, CA 95014 \\ + \vspace*{0.25in} + This manual corresponds to Magic version 7.4 \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Preferably all of them. +\endi + +{\noindent\bfseries\large Commands introduced in this manual:} +\starti + \> {\itshape (None)} +\endi + +{\noindent\bfseries\large Macros introduced in this manual:} + +\starti + \> {\itshape (None)} +\endi + +\vspace*{0.75in} +\section{Introduction} + +This document provides some information to help system administrators +and would-be Magic maintainers learn about the system. +Before doing anything to the internals of Magic, you should read at +least the first, and perhaps all four, of the papers on Magic that +appeared together in the {\itshape 1984 Design Automation Conference}. +In addition, the following portions of magic have their own papers: + +\starti + \> {\bfseries extractor} \ii {\itshape 1985 Design Automation + Conference}, page 286. \\ + \> {\bfseries channel router} \ii {\itshape 1985 Chapel Hill Conference + on VLSI}, page 145. \\ + \> {\bfseries irouter and mzrouter} \ii {\itshape 1988 Design + Automation Conference}, page 672. \\ + \> {\bfseries resistance extractor} \ii {\itshape 1987 Design + Automation Conference}, page 570. +\endi + +These documents are available from the Magic websites, which are another +useful source of information regarding the program: + +\starti + \> {\bfseries\ttfamily http://vlsi.cornell.edu/magic} \\ + \> {\bfseries\ttfamily http://opencircuitdesign.com/magic} +\endi + +The source for Magic can be downloaded from either website. Currently, +the stable distribution release of Magic is version 7.4, and +development version is 7.5. This +documentation refers to features of the stable distribution version. For +compilation instructions for the development version, please refer to the +documentation in that distribution. This document corresponds specifically +to version 7.4. + +\section{Compiling and Installing Magic} + +The download file comes in tarred, gzipped format. Normally, one will +follow the standard procedure to uncompress and expand: + +\starti + \ii tar xzf magic-7.4.0.tar.gz \\ + \ii cd magic-7.4.0 +\endi + +\section{Magic-7.4 Compile and Install} + +Magic 7.4 has a GNU ``autoconf'' method which automates most of the +configuration process. The compile and install process is thereby +simplified to the following: + +\starti + \ii ./configure \\ + \ii make \\ + \ii make install +\endi + +The autoconf process makes an effort to find the libraries and +include files needed, including Tcl/Tk and OpenGL, and will compile +Magic with support for these options unless they are specifically +prohibited by an option to the {\ttfamily configure} script. Options +may also be used to specify where libraries and include files may +be found, if they are in a nonstandard location and the +{\ttfamily configure} script is unable to find them. A full list +of available options can be obtained by typing: + +\starti + \ii ./configure --help +\endi + +The Tcl interpreter makes Magic a {\itshape package extension} of the +Tcl language, rather than being embedded. Tcl is largely compatible +with Magic's existing command-line syntax, so Magic's command-line +parser is simply given over to Tcl, and its graphics given over to Tk, +the graphics interface for Tcl. The Tcl version makes a GUI available +for Magic, and provides numerous extensions to the program. However, +all critical functions are available with or without any compiled +interpreter. + +The shell environment variable {\bfseries CAD{\_}HOME} exists as an +override to the install path, so that Magic can be redirected to find its +runtime files in a directory other than the location specified at +compile time. Generally, unless you know what you're doing, having an +environment variable {\bfseries CAD{\_}HOME} is probably a bad idea. +In versions prior to 7.2, it was necessary to have this set before running +the program, so on systems that have had an older version of magic +installed, user's startup files may contain such variable declarations, +which should be removed. + +\section{Source Directory Structure} \label{structure} + +There are many source subdirectories in Magic. +Most of these consist of modules of source code for the system, +for example {\bfseries database}, {\bfseries cif}, and {\bfseries utils}. +See Section~\ref{modules} of this document for brief descriptions of +what's in each source directory. Besides the source code, +the other subdirectories are: + +\begin{itemize} +\item {\bfseries doc} \\ +Contains sources for all the documentation, including {\itshape man} +pages, tutorials, and maintenance manuals. +Subdirectories of {\bfseries doc}, e.g. {\bfseries doc/scmos}, +contain some (outdated) technology manuals. +The Makefile in each directory can be used to run +off the documentation. The tutorials, maintenance manuals, +and technology manuals all use LaTeX, which means that you will need +the LaTeX package to recompile the manuals from source. Documentation +is also available online in HTML format. + +\item {\bfseries magic} \\ +In addition to the source main() routine used for the non-Tcl-based +compile option, this directory is where the modules of Magic are +linked to form the executable version of the system. +\end{itemize} + +Magic is a relatively large system: there are around 575 source files, +and 250,000 lines of C code. +In order to make all +of this manageable, we've organized the sources in a two-level +structure. Each module has its own subdirectory, and you can +make changes to the module and recompile it by working +within that subdirectory. + +There are two mailing lists associated with Magic development: +\begin{enumerate} + \item {\ttfamily magic-hackers@csl.cornell.edu} is for general news + and discussions about the development process. + \item {\ttfamily magic-dev@csl.cornell.edu} is for developers only + and provides feedback on any CVS changes made in the repository. +\end{enumerate} + +\section{Compiling and Installing } + +The top-level Makefile (\~{}cad/src/magic/Makefile) provides many options. + +The most useful Makefile options are: + +\begin{itemize} +\item {\bfseries make magic} \\ + Make a version of Magic. All sub-modules are remade, if needed, + and then the final magic binary is produced. + +\item {\bfseries make everything} \\ + Same as ``make magic''. Both options make auxilary programs like + {\bfseries ext2sim} and {\bfseries ext2spice}. + +\item {\bfseries make force} \\ + Force recompilation. Like a ``make everything'', except that object + files are first removed to force complete recompilation from scratch. + +\item {\bfseries make clean} \\ + Delete files that can be remade, such as binaries, object, and + library files. + +\item {\bfseries make veryclean} \\ + A more complete cleanup, that removes the current configuration + in addition to the files removed int the {\bfseries make clean} + step. + +\item {\bfseries make install} \\ + Install the Magic binaries and run-time library files. + For Tcl, install the Magic shared-object files in the lib + directory, and install a shell script as the ``magic'' + executable. +\end{itemize} + +Putting together a runnable Magic system proceeds in two steps +after a source file has been modified. First, the source file +is compiled, and all the files in its module are linked together +into a single file {\itshape xyz}{\bfseries .o}, where {\itshape xyz} +is the name of the module. Then all of the modules are linked together +to form an executable version of Magic. +The command {\bfseries make} in each source directory will compile and +link the module locally; {\bfseries make install} will compile and +link it. All Makefiles are set up to use the compiler flags found +in the source top-level directory file {\bfseries defs.mak}. + +\section{Summary of Magic Modules} \label{modules} + +This section contains brief summaries of what is in each of the Magic +source subdirectories. A number of files and directories were shifted +around in the development of version 7.4, so this list has been +updated accordingly. + +\begin{itemize} +\item {\bfseries calma} \\ +Contains code to read and write Calma (GDS-II) Stream-format files. It +uses many of the procedures in the {\bfseries cif} module. + +\item {\bfseries cif} \\ +Contains code to process the CIF sections of technology +files, and to generate CIF files from Magic. + +\item {\bfseries cmwind} \\ +Contains code to implement special windows for editing color maps. + +\item {\bfseries commands} \\ +The procedures in this module contain the top-level command +routines for layout commands (commands that are +valid in all windows are handled in the {\bfseries windows} module). +These routines generally just parse the commands, check for +errors, and call other routines to carry out the actions. + +\item {\bfseries database} \\ +This is the largest and most important Magic module. It +implements the hierarchical corner-stitched database, and +reads and writes Magic files. + +\item {\bfseries dbwind} \\ +Provides display functions specific to layout windows, including managing +the box, redisplaying layout, and displaying highlights and feedback. + +\item {\bfseries debug} \\ +There's not much in this module, just a few routines used for +debugging purposes. + +\item {\bfseries drc} \\ +This module contains the incremental design-rule checker. It +contains code to read the {\bfseries drc} sections of technology files, +record areas to be rechecked, and recheck those areas in +a hierarchical fashion. + +\item {\bfseries ext2sim} \\ +This is another self-contained program. It's +a self-contained program that flattens the hierarchical {\bfseries .ext} +files generated by Magic's extractor into a single file in {\bfseries .sim} +format. See the manual page {\bfseries ext2sim~(1)}. + +\item {\bfseries ext2spice} \\ +This is another self-contained program. It converts {\bfseries .ext} +files into single file in spice format. +See the manual page {\bfseries ext2spice~(1)}. + +\item {\bfseries extcheck} \\ +Yet another independent program. This one checks the {\bfseries .ext} +files for global node connectivity and summarizes the number of FETs, +nodes, etc. See the manual page {\bfseries extcheck~(1)}. + +\item {\bfseries extflat} \\ +Contains code that is used by the {\bfseries extract} module and the +{\bfseries ext2\dots} +programs. The module produces a library that is linked in with the above +programs. + +\item {\bfseries extract} \\ +Contains code to read the {\bfseries extract} sections of technology files, +and to generate hierarchical circuit descriptions ({\bfseries .ext} files) +from Magic layouts. + +\item {\bfseries gcr} \\ +Contains the channel router, which is an extension of Rivest's +greedy router that can handle switchboxes and obstacles in the +channels. + +\item {\bfseries graphics} \\ +This is the lowest-level graphics module. It contains driver +routines for X11 and OpenGL as well as the equivalent versions +for use with Tk graphics under the Tcl-interpreter based version +of Magic. If you want to make Magic run on a new kind of +display, this is the only module that should have to change. + +\item {\bfseries grouter} \\ +The files in this module implement the global router, which +computes the sequence of channels that each net is to pass +through. + +\item {\bfseries irouter} \\ +Contains the interactive router written by Michael Arnold at Lawrence +Livermore National Labs. This router allows the user to route nets +interactively, using special hint layers to control the routing. + +\item {\bfseries lef} \\ +This module contains the LEF and DEF file format handling routines. + +\item {\bfseries lisp} \\ +This module contains code which, if the SCHEME option is chosen at +compile time, implements the lisp-like ``scheme'' interpreter. +Scheme enables magic commands to be executed in a programming +language framework, so complex functions can be defined. + +\item {\bfseries magic} \\ +Contains the C {\bfseries main()} routine, and, alternatively, the +Tcl initialization functions which replace it in the Tcl shared-object +extensions. Also contains all of the Tcl interpreter supporting code, +such as the GUI wrapper, and the shell script which launches Magic. + +\item {\bfseries mzrouter} \\ +Contains maze routing routines that are used by the irouter and garouter +modules. + +\item {\bfseries net2ir} \\ +Contains a program to convert a netlist into irouter commands. + +\item {\bfseries netmenu} \\ +Implements netlists and the special netlist-editing windows. + +\item {\bfseries oa} \\ +A very spare framework for an experimental interface to the OpenAccess +database. This is barely functional and is not enabled by the default +configuration. + +\item {\bfseries plot} \\ +The internals of the {\bfseries plot} command. Code to write +PostScript and rendered PNM output formats. Disabled legacy +code exists for the raw pixel, versatec, and gremlin formats, +which may be compiled in by adding the appropriate definitions +to the {\bfseries defs.mak} file. + +\item {\bfseries plow} \\ +This module contains the code to support the {\bfseries :plow} +and {\bfseries :straighten} commands. + +\item {\bfseries readline} \\ +``readline'' is an independent library of routines implementing +command-line history and editing. Version 7.4 of magic uses GNU +readline-4.3. + +\item {\bfseries resis} \\ +Resis is a module that does better resistance extraction via +the :extresis command. Courtesy of Don Stark of Stanford. + +\item {\bfseries router} \\ +Contains the top-level routing code, including procedures +to read the router sections of technology files, +chop free space up into channels, analyze obstacles, and paint +back the results produced by the channel router. + +\item {\bfseries scripts} \\ +This is not a module, but contains all of the shell scripts used +by the make process. + +\item {\bfseries select} \\ +This module contains files that manage the selection. The routines +here provide facilities for making a selection, enumerating what's +in the selection, and manipulating the selection in several ways, +such as moving it or copying it. + +\item {\bfseries sim} \\ +Provides an interactive interface to the simulator rsim. Courtesy of +Mike Chow of Stanford. + +\item {\bfseries tcltk} \\ +Contains the principle code used for the interface to the Tcl/Tk +interpreter, the Tcl scripts that are used by the interface, and +the startup scripts. Note that much of the Tcl/Tk calls are +scattered throughout the code, especially in the {\bfseries +graphics} and {\bfseries commands} subdirectories. + +\item {\bfseries textio} \\ +The top-level command interpreter. This module grabs commands +from the keyboard or mouse and sends them to the window module +for processing. Also provides routines for message and error +printout, and to manage the prompt on the screen. + +\item {\bfseries tiles} \\ +Implements basic corner-stitched tile planes. This module was +separated from {\bfseries database} in order to allow other clients +to use tile planes without using the other database facilities +too. + +\item {\bfseries utils} \\ +This module implements a whole bunch of utility procedures, +including a geometry package for dealing with rectangles and +points and transformations, a heap package, a hash table package, +a stack package, a revised memory allocator, the argument parser +(formerly in module ``parser''), the initialization routines +(formerly in module ``main''), the netlist handler (not associated +with the ``netmenu'' module), the undo/redo handler, the technology +reading code (formerly in module ``tech''), and lots of other stuff. + +\item {\bfseries windows} \\ +This is the overall window manager. It keeps track of windows +and calls clients (like {\bfseries dbwind} and {\bfseries cmwind}) to process +window-specific operations such as redisplaying or processing +commands. Commands that are valid in all windows, such as +resizing or moving windows, are implemented here. + +\item {\bfseries wiring} \\ +The files in this directory implement the {\bfseries :wire} command. +There are routines to select wiring material, add wire legs, +and place contacts. +\end{itemize} + +\section{Portability Issues} \label{porting} + +Magic runs on a variety of machines. Running ``configure'' in the top-level +source directory sets the compile-time options. +If you are porting Magic, you will probably need to modify the file +{\bfseries scripts/configure.in} to define the proper compile-time flags +for your machine. No changes should be made that would hamper Magic's +operation on other machines. Process the {\bfseries configure.in} file +by doing {\bfseries cd scripts; autoconf}. Note that the {\bfseries +automake} program is not used in this process. The {\bfseries configure} +script is directed to produce not a Makefile, as usual, but to produce +the {\bfseries defs.mak} file which is included by the Makefile. + +The top-level directory script {\bfseries configure} is a shell script +wrapper for the actual autoconf-generated file {\bfseries +scripts/configure}. The indirect call serves two purposes: All of +the extra scripts required by autoconf can be kept in the {\bfseries +scripts} subdirectory, and also the {\bfseries CFLAGS} environment +variable can be set, allowing the compiler optimization flag to be +disabled, resulting in an executable which is probably marginally +slower, but much easier to debug. + +\section{Technology and Other Support Files} + +Besides the source code files, there are a number of other +files that must be managed by Magic maintainers, including +color maps, technology files, and other stuff. Below is +a listing of those files and where they are located. + +\subsection{Technology Files} + +See ``Magic Maintainer's Manual\ \#2: The Technology File'' for information on +the contents of technology files. +The sources for technology files are contained in the subdirectory +{\bfseries tech}, in files like {\bfseries scmos.tech} and {\bfseries nmos.tech}. +The technology files that Magic actually uses at runtime are kept in the +directory {\bfseries /usr/local/lib/magic/sys};%$ +{\bfseries make install} in {\bfseries tech} +will copy the sources to {\bfseries /usr/local/lib/magic/sys}.%$ +The installed versions of technology files have the extension {\bfseries .tech}. + +Historically, the techfile format version was embedded in the filename. +The last version number to use this (27), is still accepted as a valid +techfile filename (for example, {\bfseries nmos.tech27}, where {\bfseries 27} is a +version number). Now, the format number appears in the ``tech'' section of the +tech file (the first section declared) as, e.g., ``format 28''. Future +changes to the tech version are expected to be backwardly compatible to version +27, should query the format version from the file, and make adjustments as +necessary to the read-in for backward compatibility. + +The technology files that are compiled and installed with the magic +distribution are long outdated and useful mainly for demonstration purposes. +A set of technology files corresponding to existing fabrication processes +is available from Jeff Sondeen at ISI. Others are available from the Magic +website, and from MOSIS. + +\subsection{Display Styles} + +The display style file sources are contained in the source directory +{\bfseries graphics}. See ``Magic Maintainer's Manual\ \#3: The Display Style +and Glyph Files'' and the manual page {\itshape dstyle}~(5) +for a description of their contents. +{\bfseries Make install} in {\bfseries graphics} will copy the files to +{\bfseries /usr/local/lib/magic/sys}, which is where Magic looks +for them when it executes. + +\subsection{Glyph Files} + +Glyph files are described in Maintainer's Manual\ \#3 and the +manual page {\itshape glyphs}~(5); they define patterns that +appear in the cursor. The sources for glyph +files appear in two places: some of them are in {\bfseries graphics}, +in files like {\bfseries color.glyphs}, and some others are defined +in {\bfseries windows/window}{\itshape XX}{\bfseries .glyphs}. +When you {\bfseries make install} in +those directories, the glyphs are copied to +{\bfseries /usr/local/lib/magic/sys},%$ +which is where Magic looks for them when it executes. + +\subsection{Color Maps} + +The color map sources are also contained in the source directory {\bfseries graphics}. +Color maps have names like {\bfseries mos.7bit.std.cmap}, +where {\bfseries mos} is the name of the technology style to which the color +map applies, +{\bfseries 7bit} is the display style, +and {\bfseries std} is a type of monitor. +If monitors +have radically different phosphors, they may require different +color maps to achieve the same affects. Right now we only support +the {\bfseries std} kind of monitor. When Magic executes, it looks for +color maps in {\bfseries /usr/local/lib/magic/sys};%$ +{\bfseries make install} in {\bfseries graphics} +will copy them there. Although color map files are textual, +editing by hand is undesirable; use Magic's color map editing +window instead. + +\section{New Display Drivers} + +The most common kind of change that will be +made to Magic is probably to adapt it for new kinds of color displays. +Each display driver contains a standard collection of +procedures to perform basic functions such as placing text, +drawing filled rectangles, or changing the shape of the cursor. +A table (defined in {\bfseries graphics/grMain.c}) holds the addresses +of the routines for the current display driver. At initialization +time this table is filled in with the addresses of the routines +for the particular display being used. All graphics calls pass +through the table. + +If you have a display other than the ones currently defined +(X11 and OpenGL/GLX), and you want to build a +new display driver, we recommend starting with the routines for +the X11 (all the files in {\bfseries graphics} named +{\bfseries grX11su}{\itshape n}{\bfseries .c}). +Copy the files into a new set for your display, +change the names of the routines, and modify them to perform +the equivalent functions on your display. Write an initialization +routine like {\bfseries x11suSetDisplay}, and add information to the +display type tables in {\bfseries graphics/grMain.c}. At this point +you should be all set. There shouldn't be any need to modify +anything outside of the graphics module. + +\section{Debugging} + +Magic works fine under GNU {\bfseries gdb}. The Makefiles are set +up to compile all files with the {\bfseries -g} switch, which creates +debugging information. + +When Magic is compiled under the Tcl interpreter, however, +one cannot run, e.g., ``{\bfseries gdb magic},'' because the +magic executable is a script. The proper way to run Tcl-based +magic under a debugger is the following: + +\starti + \ii set pid=`ps --no-headers -o pid= -C wish` \\ + \ii gdb program $pid +\endi + +which is a simple invocation for Linux systems. If it is not +possible to get {\bf ps} to return a single process ID, the +process ID can be obtained visually from the {\bf ps} command +and given to {\bf gdb} as the process ID to attach to: + +\starti + \ii ps -C wish + \ii gdb program {\itshape process_ID} +\endi + +wher the first command returns {\itshape process_ID}, the process ID of +the {\bfseries wish} process. If the +version of {\bfseries ps} on your system does not support the {\bfseries +-C} option, there are other options that will report the {\bfseries wish} +process. + +Because this method attaches to an already running program, this method +does not work for capturing errors that occur during program startup. +Note, however, that errors occurring during technology loading can be +captured by attaching to the running process, then giving the command +``{\bfseries tech load [tech filename]}'' to magic. Otherwise, the +procedure to attach to the process prior to initialization is the +following: + +\starti + \ii gdb wish + \ii run + \ii set argc 3 + \ii set argv \{-w -d OGL\} + \ii source /usr/local/lib/magic/tcl/magic.tcl +\endi + +Note the necessity of setting variables {\bfseries argc} and {\bfseries +argv} within Tcl to get the startup script to process them as if they +were command-line arguments passed from the shell. Any valid command-line +arguments may be passed in this manner. The debugger prompt can be reached +by typing Ctrl-C. Note that the Tk console window is not available when +debugging, a minor inconvenience. + +\end{document} diff --git a/doc/latexfiles/maint2.tex b/doc/latexfiles/maint2.tex new file mode 100644 index 00000000..501cb899 --- /dev/null +++ b/doc/latexfiles/maint2.tex @@ -0,0 +1,3549 @@ +%---------------------------------------------------------------------------- +% Magic Maintainer's Manual #2 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times,pifont} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\I{\hinch} +\def\II{\I\I} +\def\vns{\vspace*{-0.05in}} +\def\mytitle{Magic Maintainer's Manual \#2: The Technology File} +\def\q{\special{ps:(") show}\hspace*{0.6em}} +\def\grt{\hspace*{0.3em}\special{ps:(>) show}\hspace*{0.3em}} +\def\bk{\special{ps:/bksp 2 string def bksp 0 92 put bksp show}\hspace*{0.4em}} +\def\vbar{$|$} + +\newcommand{\micro}{\Pifont{psy}m} +\newcommand{\ohms}{\Pifont{psy}W} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Walter Scott} \\ + \vspace*{0.25in} + Special Studies Program \\ + Lawrence Livermore National Laboratory \\ + P.O. Box 808, L-270 \\ + Livermore, CA 94550 \\ + \vspace*{0.25in} + {\itshape John Ousterhout} \\ + \vspace*{0.25in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + {\itshape (Updated by others, too.)} \\ + \vspace*{0.25in} + This manual corresponds to Magic version 7.4 + and technology format 30 +\end{center} +\vspace*{0.25in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection \\ + \> Magic Tutorial \#6: Design-Rule Checking \\ + \> Magic Tutorial \#8: Circuit Extraction \\ + \> Magic Tutorial \#9: Format Conversion for CIF and Calma +\endi +\noindent You should also read at least the first, and probably all four, +of the papers on Magic that appeared in the {\itshape ACM IEEE 21st +Design Automation Conference}, and the paper ``Magic's Circuit Extractor'', +which appeared in the {\itshape ACM IEEE 22nd Design +Automation Conference}. The overview paper from the +DAC was also reprinted in {\itshape IEEE Design and Test} magazine in +the February 1985 issue. +The circuit extractor paper also appeared in the +February 1986 issue of {\itshape IEEE Design and Test} magazine. + +{\noindent\bfseries\large Commands introduced in this manual:} +\starti + \> path + \> tech + \> *watch +\endi + +{\noindent\bfseries\large Macros introduced in this manual:} + +\starti + \> {\itshape (None)} +\endi + +{\noindent\bfseries\large Changes since Magic version 7.2:} +\begin{itemize} +\item Support for stacked contacts. +\item ``variants'' option for the cifinput, cifoutput, and extract + sections, allowing an efficient description of different + styles having minor variations. +\item Supports names for layer drawing styles in addition to the usual + numbers. +\item Section name {\bfseries images} duplicates the {\bfseries contacts} + section, allowing a less-restrictive definition of images that + exist, like contacts, on multiple planes. +\item Support for multi-line technology descriptions. +\item ``include'' statement to divide technology files into parts. +\item ``alias'' statements to replace the original cpp-style macros +\item Support for {\itshape angstroms} in the scalefactor line of + cifinput and cifoutput. +\item Additional DRC types ``surround'', ``overhang'', and ``rect\_only''. +\item Additional cifoutput operators ``slots'' and ``bloat-all''. +\item Additional cifoutput statement ``render'' for 3-D information +\item Asterisk syntax for layers that expands to the layer and all of + the contacts containing that layer as a residue. +\item The technology file syntax for the PNM format was changed in + magic 7.3.56, and the {\bfseries plot pnm} command will + use a default style derived from the layout styles if no + section is present in the technology file. +\end{itemize} + +{\noindent\bfseries\large Changes since Magic version 6.5:} +\begin{itemize} +\item Moved technology format from the filename to the ``tech'' section +\item Added subdirectory searching to the path search for technology files. +\item Support for technology file re-loading after Magic starts up, and + support for re-loading of individual sections of the technology + file. +\item Scalefactors can now be any number whatsoever, for both CIF and GDS. + For example, a scalefactor of 6.5 corresponds to a 0.13 micron + process. +\item A parameter {\itshape nanometers} has been added to the scalefactor + specification for both cifinput and cifoutput sections. This + parameter declares that all numbers in the style description are + in nanometers instead of centimicrons. +\item The {\itshape calmaonly} parameter to the scalefactor specification is + deprecated (ignored if found). +\item The scale reducer parameter is deprecated (generated automatically, + and ignored if found in the techfile). +\item The magic grid spacing is no longer assumed to be equal to the process + lambda. It may be rescaled with the ``scalegrid'' command, and CIF + and Calma reads may alter the value of magic units per lambda. +\item Support for PNM and PostScript graphics in the ``plot'' section. +\item Full support for bipolar junction transistors, capacitors, and + resistors with the ``extract'' section keyword ``device'' +\item Support for three-dimensional modeling and geometry extraction +\item Support for the DRC widespacing rule +\item Handling of contacts in the extraction section is capable of + matching the CIF output section by specifying border, size, + and spacing. +\end{itemize} + +\vspace*{0.25in} +\section{Introduction} + +Magic is a technology-independent layout editor. +All technology-specific information comes from a +{\itshape technology file}. This file includes such information +as layer types used, electrical connectivity between types, +design rules, rules for mask generation, and rules for +extracting netlists for circuit simulation. + +This manual describes the use, contents, and syntax of Magic's +technology file format, and gives hints for building a new one or +(more typically) rewriting an existing one for a new fabrication +process. References to specific files in the Magic distribution +assume that your current working directory is the Magic source +top-level directory. + +\section{Downloads and Installation} + +Typically, there is a different technology file for each fabrication +process supported by Magic. Scalable technologies, which are +(within limits) independent of feature size, will typically have +one technology file for all processes supporting the same set of +lambda-based (scalable) DRC rules. +That said, modern technologies (post-1980's, more or less) tend to +be more restrictive in their design rules, and consequently not +scalable. This is particularly true of processes which push the +envelope on feature sizes. + +The Magic source distribution +is packaged with a ``standard'' set of scalable SCMOS rules, which +is the technology loaded by default. Default settings are for +1\,{\micro}m technology, which is out of date. However, the +variety and availability of processes means that the ``definitive'' +set of technology files is prohibitively large to be included +with the Magic source. In addition, process refinements generally +require technology file updates on a regular basis. Because of +this, the basic collection of technology files is handled by the +MOSIS foundation, not by the Magic development team. This +collection represents all processes which are available for +fabriction through the MOSIS foundation. Most other vendors have +proprietary process specifications, requiring tool maintainers to +write their own technology files or modify an existing one to +match the proprietary process. + +The standard technology file set can be downloaded from an FTP +server at the MOSIS foundation. These files are regularly +updated, but there is usually a symbolic link called ``current'' +to the most recent stable revision. The download URL is the +following: + +\starti + \> {\ttfamily\bfseries ftp://ftp.mosis.edu/pub/sondeen/magic/new/beta/current.tar.gz} +\endi + +Assuming that the install destination for magic is +{\bfseries /usr/local}, this file should be put either in {\bfseries +/usr/local/lib/magic/sys} or (preferably) in {\bfseries +/usr/local/lib/magic/sys/current}. Other destinations may +be used, if the system search path is appropriately specified +on startup (see Section~\ref{commandline}, below). + +The technology file collection is in tarred, gzipped format, +and should be installed with the following commands: + +\starti + \ii {\ttfamily\bfseries cd /usr/local/lib/magic/sys/current} \\ + \ii {\ttfamily\bfseries gunzip current.tar.gz} \\ + \ii {\ttfamily\bfseries tar xf current.tar} +\endi + +Once unpacked, these files are ready to be used in Magic. + +\section{Command-Line Invocation} \label{commandline} + +You can run Magic with a different technology by +specifying the {\bfseries -T}{\itshape techfile} flag on the command +line you use to start Magic, where +{\itshape techfile} is the name of a file of the form +{\itshape techname}{\bfseries .tech}, searched for in one +of the following directories (listed by search order): +\begin{enumerate} + \item The current directory + \item The library directory /usr/local/lib/magic/sys + \item The library directory /usr/local/lib/magic/current +\end{enumerate} +This search order is not fixed and can be altered by the command +{\bfseries path sys}, which may be redefined in the system or +user {\bfseries .magic} startup script file. In addition, the +startup script may load a new techfile, regardless of what was +specified on the command line, or may load a new techfile provided +that one has not been specified on the command line (the +{\bfseries -nooverride} option. The {\bfseries -noprompt} switch +causes the technology to be loaded without first prompting the +user for confirmation. + +\starti + \ii {\bfseries tech load} {\itshape filename} {\bfseries -noprompt} + [{\bfseries -nooverride}] +\endi + +\section{Technology File Format Overview} + +A technology file is organized into sections, each of which +begins with a line containing a single keyword +and ends with a line containing the single word {\bfseries end}. +If you examine one of the Magic technology files in the +installation directory +{\bfseries \$}\{{\bfseries CAD\_HOME}\}{\bfseries /lib/magic/sys/}, +{\itshape e.g.}, {\bfseries scmos.tech}, +you can see that it contains the following sections: + +\starti + \ii {\bfseries tech} \\ + \ii {\bfseries planes} \\ + \ii {\bfseries types} \\ + \ii {\bfseries styles} \\ + \ii {\bfseries contact} \\ + \ii {\bfseries compose} \\ + \ii {\bfseries connect} \\ + \ii {\bfseries cifoutput} \\ + \ii {\bfseries cifinput} \\ + \ii {\bfseries mzrouter} \\ + \ii {\bfseries drc} \\ + \ii {\bfseries extract} \\ + \ii {\bfseries wiring} \\ + \ii {\bfseries router} \\ + \ii {\bfseries plowing} \\ + \ii {\bfseries plot} +\endi + +These sections must appear in this order in all technology files. +Every technology file must have all of the sections, although the sections +need not have any lines between the section header and the {\bfseries end} line. + +Historically, technology files were written in a C-language context which +was processed by the C preprocessor. This allows the use of C-language +comments (``{\bfseries /*} \dots {\bfseries */}'') and the use of +preprocessing definitions (``{\bfseries \#define} \dots'') and +conditionals (``{\bfseries \#ifdef} \dots {\bfseries \#endif}''). +The technology files were generated from a Makefile with the preprocessor +constructs used to generate different sections of the technology file +at different lambda scales. The decreasing use of scalable processes, +however, has made this method largely obsolete, and the standard +collection of technology files from MOSIS does not use them at all. +Technology files are now written in their final form, not in preprocessed +form. Information regarding preprocessor constructs is not included below, +but can of course be obtained from the manual pages for the preprocessor +itself ({\bfseries gcc} or {\bfseries cpp}). But also note that the use +of C preprocessors for processing text files other than source code is +now generally discouraged in favor of using a macro definition processor +like {\bfseries m4} (see the manual page for {\bfseries m4} for details). +On the other hand, macro definition processors are almost universally +despised, so many preprocessor functions have been written into the +technology file syntax. + +The default {\bfseries scmos} set of technology files included with the +Magic distribution is still processed via the C preprocessor. Preprocessed +files have the extension ``{\bfseries .tech.in}''. +Technology files written specifically for Magic version 7.3 tend to +make use of additional features of the technology file syntax that +subsume most of the functions of the C preprocessor and M4 processor +normally used to generate technology files. + +Each section in a technology file consists of a series of lines. +Each line consists of a series of words, separated by spaces or tabs. +If a line ends with the character ``{\bk}'', the ``{\bk}'' is ignored +and the following newline is treated as an ordinary blank. +For example, + +\starti + \ii {\bfseries width allDiff 2 {\bk}} \\ + \ii\> {\itshape {\q}Diffusion width must be at least 2{\q}} +\endi + +is treated as though it had all appeared on a single line +with no intervening ``{\bk}''. On the other hand, for the purposes +of tracking errors in technology file input, the technology file +parser treats these as separate lines, so that when magic reports +an error on a specific line of the technology file, it will agree +with the line numbering of the editor used to edit the file. + +Comments may be embedded in the technology file. Magic's technology +file parser will ignore all text beginning with the character +{\bfseries \#} through the end of the line. + +The rest of this part of the manual will describe +each of the technology file sections in turn. + +\section{Tech section} + +Magic stores the technology of a cell in the cell's file on disk. +When reading a cell back in to Magic from disk, the cell's +technology must match the name of the current technology, +which appears as a single word in the {\bfseries tech} section +of the technology file. See Table~1 for an example. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|l|} \hline + {\bfseries tech} \\ + format 30 \\ + scmos \\ + {\bfseries end} \\ \hline + \end{tabular} + \caption {{\bfseries Tech} section} + \end{center} + \label{tech} +\end{table} + +The name of the technology declared in the {\bfseries tech} +section is meaningful to Magic, whereas the name of the file +itself is not. Typically the name of the file will be the +same as the name of the technology, to avoid confusion, but +this need not be the case. + +Versions of magic prior to 7.2 embedded the format version +of the technology in the file name, {\itshape e.g.}, +{\bfseries scmos.tech27}. The last format version to use +this syntax, 27, is still accepted as a valid filename +extension. Many technology files still use this notation, +including (at the time of writing) the collection from MOSIS. +Now the format is declared inside the {\bfseries tech} +section. + +\section{A short tutorial on ``corner stitching''} + +The {\bfseries planes}, {\bfseries types}, and {\bfseries contact} sections +are used to define the layers used in the technology. +Magic uses a data structure called {\itshape corner-stitching} to represent +layouts. Corner-stitching represents mask information +as a collection of non-overlapping rectangular {\itshape tiles}. +Each tile has a type that corresponds to a single Magic layer. +An individual corner-stitched data structure is referred to as a {\itshape plane}. + +Magic allows you to see the corner-stitched planes it uses to store a layout. +We'll use this facility to see how several corner-stitched planes +are used to store the layers of a layout. +Enter Magic to edit the cell {\bfseries maint2a}. +Type the command {\bfseries *watch active demo}. +You are now looking at the {\bfseries active} plane. +Each of the boxes outlined in black is a tile. +(The arrows are {\itshape stitches}, but are unimportant to this discussion.) +You can see that some tiles contain layers +(polysilicon, ndiffusion, ndcontact, polycontact, and ntransistor), +while others contain empty space. +Corner-stitching is unusual in that it represents empty space explicitly. +Each tile contains exactly one type of material, or space. + +You have probably noticed that metal1 does not seem to have +a tile associated with it, but instead appears right in the middle +of a space tile. +This is because metal1 is stored on a different plane, the {\bfseries metal1} plane. +Type the command {\bfseries :*watch metal1 demo}. +Now you can see that there are metal1 tiles, +but the polysilicon, diffusion, and transistor tiles have disappeared. +The two contacts, polycontact and ndcontact, still appear to be tiles. + +The reason Magic uses several planes to store mask information +is that corner-stitching can only represent non-overlapping rectangles. +If a layout were to consist of only a single layer, such +as polysilicon, then only two types of tiles would be necessary: +polysilicon and space. +As more layers are added, overlaps can be +represented by creating a special tile type for +each kind of overlap area. +For example, when polysilicon overlaps +ndiffusion, the overlap area is marked with the tile type +ntransistor. + +Although some overlaps correspond to actual electrical constructs +(e.g., transistors), other overlaps have little electrical significance. +For example, metal1 can overlap polysilicon without changing the +connectivity of the circuit or creating any new devices. +The only consequence of the overlap is possibly a change in +parasitic capacitance. +To create new tile types for all possible overlapping combinations of metal1 +with polysilicon, diffusion, transistors, etc. +would be wasteful, since these new overlapping combinations +would have no electrical significance. + +Instead, Magic partitions the layers into separate planes. +Layers whose overlaps have electrical significance must be +stored in a single plane. +For example, polysilicon, diffusion, and their overlaps (transistors) +are all stored in the {\bfseries active} plane. +Metal1 does not interact with any of these tile types, so it is stored +in its own plane, the {\bfseries metal1} plane. +Similarly, in the scmos technology, metal2 doesn't interact with either +metal1 or the active layers, so is stored in yet another plane, {\bfseries metal2}. + +Contacts between layers in one plane and layers in another are a special +case and are represented on {\itshape both} planes. +This explains why the pcontact and ndcontact +tiles appeared on both the +{\bfseries active} plane and on the {\bfseries metal1} plane. +Later in this section, when the {\bfseries contacts} section of the +technology file is introduced, we'll see how to define contacts +and the layers they connect. + +\section{Planes, types, and contact sections} + +The {\bfseries planes} +section of the technology file specifies how many planes will be +used to store tiles in a given technology, and gives each plane +a name. +Each line in this section +defines a plane by giving a comma-separated +list of the names by which it is known. +Any name may be used in referring to the plane in later +sections, or in commands like the +{\bfseries *watch} command indicated in the tutorial above. +Table~\ref{planes} gives the {\bfseries planes} section from the +scmos technology file. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|l|} \hline + {\bfseries planes} \\ + well,w \\ + active,diffusion,polysilicon,a \\ + metal1,m1 \\ + metal2,m2 \\ + oxide,ox \\ + {\bfseries end} \\ \hline + \end{tabular} + \caption{{\bfseries Planes} section} + \label{planes} + \end{center} +\end{table} + +Magic uses a number other planes internally. +The {\bfseries subcell} +plane is used for storing cell instances rather than storing +mask layers. +The {\bfseries designRuleCheck} and {\bfseries designRuleError} +planes are used by the design rule checker to store +areas to be re-verified, and areas containing design rule +violations, respectively. +Finally, the {\bfseries mhint}, {\bfseries fhint}, and {\bfseries rhint} planes are +used for by the interactive +router (the {\bfseries iroute} command) for designer-specified graphic hints. + +There is a limit on the maximum number of planes in a technology, +including the internal planes. This limit is currently 64. +To increase the limit, it is necessary to change {\bfseries MAXPLANES} +in the file +{\bfseries database/database.h.in} and then recompile all +of Magic as described in ``Maintainer's Manual\ \#1''. Each additional +plane involves additional storage space in every cell and some additional +processing time for searches, so we recommend that you keep the number +of planes as small as you can do cleanly. + +The {\bfseries types} section identifies the technology-specific +tile types used by Magic. +Table~\ref{types} gives this section for the scmos technology file. +Each line in this section is of the following form: + +\starti + \ii {\itshape plane names} +\endi + +Each type defined in this section is allowed to appear on exactly +one of the planes defined in the {\bfseries planes} section, namely +that given by the {\itshape plane} field above. +For contacts types such as {\bfseries pcontact}, the plane +listed is considered to be the contact's {\itshape home} plane; +in Magic 7.3 this is a largely irrelevant distinction. However, +it is preferable to maintain a standard of listing the lowest plane +connected to a contact as it's ``home plane'' (as they appear in +the table). + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|ll|} \hline + {\bfseries types} & \\ + active & polysilicon,red,poly,p \\ + active & ndiffusion,green,ndiff \\ + active & pdiffusion,brown,pdiff \\ + metal1 & metal1,m1,blue \\ + metal2 & metal2,m2,purple \\ + well & pwell,pw \\ + well & nwell,nw \\ + active & polycontact,pcontact,pc \\ + active & ndcontact,ndc \\ + active & pdcontact,pdc \\ + metal1 & m2contact,m2c,via,v \\ + active & ntransistor,nfet \\ + active & ptransistor,pfet \\ + active & psubstratepcontact,ppcontact,ppcont,psc,ppc,pwc,pwcontact \\ + active & nsubstratencontact,nncontact,nncont,nsc,nnc,nwc,nwcontact \\ + active & psubstratepdiff,psd,ppdiff,ppd,pohmic \\ + active & nsubstratendiff,nsd,nndiff,nnd,nohmic \\ + metal2 & pad \\ + oxide & glass \\ + {\bfseries end} & \\ \hline + \end{tabular} + \caption{{\bfseries Types} section} + \label{types} + \end{center} +\end{table} + +The {\itshape names} field is a comma-separated list of names. +The first name in the list is the ``long'' name for the type; +it appears in the {\bfseries .mag} file and whenever error messages involving +that type are printed. +Any unique abbreviation of any of a type's names is sufficient +to refer to that type, both from within the technology file +and in any commands such as +{\bfseries paint} or {\bfseries erase}. + +Magic has certain built-in types as shown in Table~\ref{builtins}. +Empty space ({\bfseries space}) +is special in that it can appear on any plane. +The types {\bfseries error{\_}p}, {\bfseries error{\_}s}, and {\bfseries error{\_}ps} +record design rule violations. +The types {\bfseries checkpaint} and {\bfseries checksubcell} +record areas still to be design-rule checked. +Types {\bfseries magnet}, {\bfseries fence}, and {\bfseries rotate} are the types +used by designers to indicate hints for the irouter. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|l|l|} \hline + Tile type & Plane \\ \hline\hline + space & {\itshape all} \\ + error{\_}p, EP & designRuleError \\ + error{\_}s, ES & designRuleError \\ + error{\_}ps, EPS & designRuleError \\ + checkpaint, CP & designRuleCheck \\ + checksubcell, CS & designRuleCheck \\ + magnet, mag & mhint \\ + fence, f & fhint \\ + rotate, r & rhint \\ \hline + \end{tabular} + \caption{Built-in Magic types} + \label{builtins} + \end{center} +\end{table} + +There is a limit on the maximum number of types in a technology, including +all the built-in types. Currently, the limit is 256 tile types. +To increase the limit, you'll have to +change the value of {\bfseries TT{\_}MAXTYPES} in the file +{\bfseries database/database.h.in} and then recompile all +of Magic as described in ``Maintainer's Manual\ \#1''. +Because there are a number of tables whose size is determined by +the square of {\bfseries TT{\_}MAXTYPES}, it is very expensive to increase +{\bfseries TT{\_}MAXTYPES}. Magic version 7.2 greatly reduced the +number of these tables, so the problem is not as bad as it once was. +Most internal tables depend on a {\itshape bitmask} of types, the +consequence of which is that the internal memory usage greatly +increases whenever {\bfseries TT{\_}MAXTYPES} exceeds a +factor of 32 (the size of an integer, on 32-bit systems). +Magic version 7.3 further alleviates the problem by reducing the +number of ``derived'' tile types that magic generates internally, +so that the total number of types is not much larger than the number +declared in the {\bfseries types} section. Magic-7.4 only generates +extra types for pairs of stackable contact types. For a typical +process, the number of these derived stacked contact pairs is +around 15 to 20. + +The declaration of tile types may be followed by a block of alias +declarations. This is similar to the ``macro'' definitions used +by preprocessors, except that the definitions are not only significant +to the technology file parser, but extend to the user as well. Thus +the statement ``{\bfseries alias metalstack m1,m2,m3}'' may be a convenient +shorthand where metal layers 1, 2, and 3 appear simultaneously, but +the end-user can type the command ``{\bfseries paint metalstack}'' and +get the expected result of all three metal layers painted. The +{\bfseries alias} statement has the additional function of allowing +backward-compatibility for technology files making use of stackable +contacts (see below) with older layouts, and cross-compatibility +between similar technologies that may have slight differences in layer +names. + +The {\bfseries contact} section lets Magic know which types are contacts, +and the planes and component types to which they are connected. + +Each line in the {\bfseries contact} +section begins with a tile type, {\itshape base}, which is thereby +defined to be a contact. +This type is also referred to as a contact's {\itshape base type}. +The remainder of each line is a list of non-contact tile types +that are connected by the contact. +These tile types are referred to as the {\itshape residues} +of the contact, and are the layers that would be present if there +were no electrical connection ({\itshape i.e.}, no via hole). +In Table~\ref{contacts}, for example, the type +{\bfseries pcontact} is the base type of a contact connecting +the residue layers {\bfseries polysilicon} on the active plane +with {\bfseries metal1} on the metal1 plane. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|llll|} \hline + {\bfseries contact} &&& \\ + pcontact & poly & metal1 & \\ + ndcontact & ndiff & metal1 & \\ + pdcontact & pdiff & metal1 & \\ + ppcontact & ppdiff & metal1 & \\ + nncontact & nndiff & metal1 & \\ + m2contact & metal2 & metal1 & \\ + pad & metal1 & metal2 & glass \\ + {\bfseries end} &&& \\ \hline + \end{tabular} + \caption{{\bfseries Contact} section} + \label{contacts} + \end{center} +\end{table} + +In Magic-7.3 and above, any number of types can be connected, and those +types may exist on any planes. It is the duty of the technology file +developer to ensure that these connections make sense, especially +if the planes are not contiguous. However, because Magic-7.3 handles +stacked contacts explicitly, it is generally better to define contacts +only between two adjacent planes, and use the {\bfseries stackable} +keyword (see below) to allow types to be stacked upon one another. +The multiple-plane representation exists for backward compatibility +with technology files written for versions of Magic prior to 7.3. +Stackable contacts in older technology files take the form: + +\starti + \ii {\bfseries contact pc polysilicon metal1} \\ + \ii {\bfseries contact m2c metal1 metal2} \\ + \ii {\bfseries contact pm12c polysilicon metal1 metal2} +\endi + +In Magic version 7.3, the above line would be represented as: + +\starti + \ii {\bfseries contact pc polysilicon metal1} \\ + \ii {\bfseries contact m2c metal1 metal2} \\ + \ii {\bfseries stackable pc m2c pm12c} +\endi + +where the third line declares that contact types m2c and pc may be +stacked together, and that type name ``pm12c'' is a valid alias for +the combination of ``pc'' and ``m2c''. + +Each contact has an {\itshape image} on all the planes it connects. +Figure~\ref{contacttiles} depicts the situation graphically. In later +sections of the technology file, it is sometimes useful to refer +separately to the various images of contact. A special +notation using a slash character (``/'') is used for this. If a tile type +{\itshape aaa/bbb} is specified in the technology file, this refers +to the image of contact {\itshape aaa} on plane {\itshape bbb}. For example, +{\bfseries pcontact/metal1} refers to the image of the pcontact that +lies on the metal1 plane, and {\bfseries pcontact/active} refers to the +image on the active plane, which is the same as {\bfseries pcontact}. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/maint2.1.ps, width=0.7\columnwidth} + \caption{A different tile type is used to represent a contact + on each plane that it connects. Here, a contact between poly + on the {\bfseries active} plane and metal1 on the {\bfseries metal1} + plane is stored as two tile types. One, {\bfseries pcontact}, + is specified in the technology file as residing on the {\bfseries + active} plane; the other is automatically-generated for the + {\bfseries metal1} plane.} + \label{contacttiles} + \end{center} +\end{figure} + +\section{Specifying Type-lists} \label{typelists} + +In several places in the technology file you'll need to specify +groups of tile types. For example, in the {\bfseries connect} section +you'll specify groups of tiles that are mutually connected. These +are called {\itshape type-lists} and there are several ways to specify +them. The simplest form for a type-list is a comma-separated list +of tile types, for example + +\starti + \ii poly,ndiff,pcontact,ndc +\endi + +The null list (no tiles at all) is indicated by zero, i.e., + +\starti + \ii 0 +\endi + +There must not be any spaces in the type-list. Type-lists may also +use tildes (``\~{}'') to select all tiles but a specified set, and +parentheses for grouping. For example, + +\starti + \ii \~{}(pcontact,ndc) +\endi + +selects all tile types but pcontact and ndc. When a contact name appears +in a type-list, it selects {\itshape all} images of the contact unless +a ``/'' is used to indicate a particular one. The example +above will not select any of the images of pcontact or ndc. +Slashes can also be used in conjunction with parentheses and tildes. +For example, + +\starti + \ii \~{}(pcontact,ndc)/active,metal1 +\endi + +selects all of the tile types on the active plane except for +pcontact and ndc, and also selects metal1. Tildes have higher operator +precedence than slashes, and commas have lowest precedence of +all. + +A special notation using the asterisk (``*'') is a convenient way +to abbreviate the common situation where a rule requires the inclusion +of a tile type and also all contacts that define that tile type as one +of their residue layers, a common occurrence. The notation + +\starti + \ii *metal1 +\endi + +expands to metal1 plus all of the contact types associated with +metal1, such as ndc, pdc, nsc, m2c, and so forth. + +Note: in the CIF sections of the technology file, only simple +comma-separated names are permitted; tildes and parentheses are +not understood. However, everywhere else in the technology file +the full generality can be used. The ``*'' notation for inclusion +of contact residues may be present in any section. + +\section{Styles section} + +Magic can be run on several different types of graphical displays. +Although it would have been possible to incorporate display-specific +information into the technology file, +a different technology file would have been required for each display type. +Instead, the technology file gives one or more display-independent +{\itshape styles} for each type that is to be displayed, +and uses a per-display-type styles file to map to +colors and stipplings specific to the display being used. The +styles file is described in +Magic Maintainer's Manual\ \#3: ``Styles and Colors'', +so we will not describe it further here. + +Table~\ref{styles} shows part of the {\bfseries styles} +section from the scmos technology file. +The first line specifies the type of style file +for use with this technology, which in this +example is {\bfseries mos}. +Each subsequent line consists of a tile type and a style number +(an integer between 1 and 63). +The style number is nothing more than a reference between the technology +file and the styles file. +Notice that a given tile type can have several styles +(e.g., pcontact uses styles \#1, \#20, and \#32), +and that a given style may be +used to display several different tiles +(e.g., style \#2 is used in ndiff and ndcontact). +If a tile type should not be displayed, +it has no entry in the {\bfseries styles} section. + +It is no longer necessary to have one style per line, a restriction +of format 27 and earlier. Multiple styles for a tile type can be +placed on the same line, separated by spaces. Styles may be +specified by number, or by the ``long name'' in the style file. + + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|ll|} \hline + {\bfseries styles} & \\ + styles & \\ + styletype mos & \\ + poly & 1 \\ + ndiff & 2 \\ + pdiff & 4 \\ + nfet & 6 \\ + nfet & 7 \\ + pfet & 8 \\ + pfet & 9 \\ + metal1 & 20 \\ + metal2 & 21 \\ + pcontact & 1 \\ + pcontact & 20 \\ + pcontact & 32 \\ + ndcontact & 2 \\ + ndcontact & 20 \\ + ndcontact & 32 \\ + pdcontact & 4 \\ + pdcontact & 20 \\ + pdcontact & 32 \\ + m2contact & 20 \\ + m2contact & 21 \\ + m2contact & 33 \\ + {\bfseries end} & \\ \hline + \end{tabular} + \caption{Part of the {\bfseries styles} section} + \label{styles} + \end{center} +\end{table} + +\section{Compose section} + +The semantics of Magic's paint operation are defined by a collection +of rules of the form, ``given material {\itshape HAVE} on plane {\itshape PLANE}, +if we paint {\itshape PAINT}, then +we get {\itshape Z}'', plus a similar set of rules for the erase operation. +The default paint and erase rules are simple. Assume that we +are given material {\itshape HAVE} on plane {\itshape PLANE}, and are painting +or erasing material {\itshape PAINT}. + +\begin{enumerate} + \item {\itshape You get what you paint.} \\ + If the home plane of {\itshape PAINT} is {\itshape PLANE}, or + {\itshape PAINT} is space, you get {\itshape PAINT}; otherwise, nothing + changes and you get {\itshape HAVE}. + \item {\itshape You can erase all or nothing.} \\ + Erasing space or {\itshape PAINT} from {\itshape PAINT} will give space; + erasing anything else has no effect. +\end{enumerate} + +These rules apply for contacts as well. +Painting the base type of a contact paints the base type +on its home plane, and each image type on its home plane. +Erasing the base type of a contact erases both the base type +and the image types. + +It is sometimes desirable for certain tile types to behave as +though they were ``composed'' of other, more fundamental ones. +For example, painting poly over ndiffusion in scmos +produces ntransistor, instead of ndiffusion. +Also, painting either poly or ndiffusion +over ntransistor leaves ntransistor, +erasing poly from ntransistor leaves ndiffusion, +and erasing ndiffusion leaves poly. +The semantics for ntransistor +are a result of the following rule in the +{\bfseries compose} section of the scmos technology file: + +\starti + \ii {\bfseries compose} ntransistor poly ndiff +\endi + +Sometimes, not all of the ``component'' layers of a type are layers +known to magic. +As an example, in the {\bfseries nmos} technology, there are two types +of transistors: {\bfseries enhancement-fet} and {\bfseries depletion-fet}. +Although both contain polysilicon and diffusion, +depletion-fet can be thought of as also containing +implant, which is not a tile type. +So while we can't construct depletion-fet by painting poly and then +diffusion, we'd still like it to behave as though it contained +both materials. +Painting poly or diffusion over a depletion-fet should not change it, and +erasing either poly or diffusion should give the other. +These semantics are the result of the following rule: + +\starti + \ii {\bfseries decompose} dfet poly diff +\endi + +The general syntax of both types of composition rules, +{\bfseries compose} and {\bfseries decompose}, +is: + +\starti + \ii {\bfseries compose} {\itshape\ \ \ type \ a1 b1 \ a2 b2 \ \dots} \\ + \ii {\bfseries decompose} {\itshape type \ a1 b1 \ a2 b2 \ \dots} +\endi + +The idea is that each of the pairs {\itshape a1 b1}, {\itshape a2 b2}, etc +comprise {\itshape type}. +In the case of a {\bfseries compose} rule, +painting any {\itshape a} atop its corresponding {\itshape b} +will give {\itshape type}, as well as vice-versa. +In both {\bfseries compose} and {\bfseries decompose} rules, erasing {\itshape a} from +{\itshape type} gives {\itshape b}, erasing {\itshape b} from {\itshape type} gives +{\itshape a}, and painting either {\itshape a} or {\itshape b} over {\itshape type} +leaves {\itshape type} unchanged. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|llll|} \hline + {\bfseries compose} \\ + compose & nfet & poly & ndiff \\ + compose & pfet & poly & pdiff \\ + paint & pwell & nwell & nwell \\ + paint & nwell & pwell & pwell \\ + paint & pdc/active & pwell & ndc/active \\ + paint & pdc/m1 & pwell & ndc/m1 \\ + paint & pfet & pwell & nfet \\ + paint & pdiff & pwell & ndiff \\ + paint & nsd & pwell & psd \\ + paint & nsc/active & pwell & psc/active \\ + paint & nsc/m1 & pwell & psc/m1 \\ + paint & ndc/active & nwell & pdc/active \\ + paint & ndc/m1 & nwell & pdc/m1 \\ + paint & nfet & nwell & pfet \\ + paint & ndiff & nwell & pdiff \\ + paint & psd & nwell & nsd \\ + paint & psc/active & nwell & nsc/active \\ + paint & psc/m1 & nwell & nsc/m1 \\ + {\bfseries end} &&& \\ \hline + \end{tabular} + \caption{{\bfseries Compose} section} + \label{compose} + \end{center} +\end{table} + +Contacts are implicitly composed of their component types, +so the result obtained when painting a type {\itshape PAINT} over a contact +type {\itshape CONTACT} will by default depend only on +the component types of {\itshape CONTACT}. +If painting {\itshape PAINT} doesn't affect the component +types of the contact, then it is considered not to affect the +contact itself either. If painting {\itshape PAINT} does affect any of +the component types, then the result is as though the contact +had been replaced by its component types in the layout before type +{\itshape PAINT} was painted. Similar rules hold for erasing. + +A pcontact has component types poly and metal1. +Since painting poly doesn't affect either poly or metal1, it +doesn't affect a pcontact either. +Painting ndiffusion does affect +poly: it turns it into an ntransistor. +Hence, painting ndiffusion over a pcontact breaks up +the contact, leaving ntransistor on the +active plane and metal1 on the metal1 plane. + +The {\bfseries compose} and {\bfseries decompose} rules +are normally sufficient to specify the desired semantics +of painting or erasing. +In unusual cases, however, it may be necessary to provide +Magic with explicit {\bfseries paint} or {\bfseries erase} rules. +For example, +to specify that painting pwell over pdiffusion switches its +type to ndiffusion, the technology file contains the +rule: + +\starti + \ii {\bfseries paint} pdiffusion pwell ndiffusion +\endi + +This rule could not have been written as a {\bfseries decompose} rule; +erasing ndiffusion from pwell does not yield pdiffusion, +nor does erasing pdiffusion from ndiffusion yield pwell. +The general syntax for these explicit rules is: + +\starti + \ii {\bfseries paint} {\itshape have t result }[{\itshape p}] \\ + \ii {\bfseries erase} {\itshape have t result }[{\itshape p}] +\endi + +Here, {\itshape have} is the type already present, on plane {\itshape p} +if it is specified; otherwise, on the home plane of {\itshape have}. +Type {\itshape t} is being painted or erased, and the result is type {\itshape result}. +Table~\ref{compose} gives the {\bfseries compose} section for scmos. + +It's easiest to think of the paint and erase rules as being built +up in four passes. +The first pass generates the default rules for all non-contact types, +and the second pass replaces these as specified by the {\bfseries compose}, +{\bfseries decompose}, etc. rules, also for non-contact types. +At this point, the behavior of the component types of contacts has +been completely determined, so the third pass can generate the +default rules for all contact types, and the fourth pass +can modify these as per any {\bfseries compose}, etc. rules for contacts. + +\section{Connect section} + +For circuit extraction, routing, and some of the net-list operations, +Magic needs to know what types are electrically connected. +Magic's model of electrical connectivity used is based on signal propagation. +Two types should be marked as connected if a signal will +{\itshape always} +pass between the two types, in either direction. +For the most part, this will mean that all non-space types within a plane +should be marked as connected. +The exceptions to this rule are devices (transistors). +A transistor should be considered electrically +connected to adjacent polysilicon, but not to adjacent diffusion. +This models the fact that polysilicon connects to the gate of +the transistor, but that the transistor acts as a switch +between the diffusion areas on either side of the channel of the transistor. + +The lines in the {\bfseries connect} +section of a technology file, as shown in Table~\ref{connect}, +each contain a pair of type-lists in the format described in +Section~\ref{typelists}. +Each type in the first list connects to each type in the second list. +This does not imply that the types in the first list are themselves +connected to each other, or that the types in the second list are +connected to each other. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|l@{\hspace*{1.5in}}l|} \hline + {\bfseries connect} & \\ + \multicolumn{2}{|l|}{\#define allMetal2 m2,m2c/m2,pad/m2} \\ + \multicolumn{2}{|l|}{\#define allMetal1 + m1,m2c/m1,pc/m1,ndc/m1,pdc/m1,ppcont/m1,nncont/m1,pad/m1} \\ + \multicolumn{2}{|l|}{\#define allPoly poly,pc/a,nfet,pfet} \\ + allMetal2 & allMetal2 \\ + allMetal1 & allMetal1 \\ + allPoly & allPoly \\ + ndiff & ndc \\ + pdiff & pdc \\ + nwell,nnc,nsd & nwell,nnc,nsd \\ + pwell,ppc,psd & pwell,ppc,psd \\ + nnc & pdc \\ + ppc & ndc \\ + {\bfseries end} & \\ \hline + \end{tabular} + \caption{{\bfseries Connect} section} + \label{connect} + \end{center} +\end{table} + +Because connectivity is a symmetric relationship, only one of +the two possible orders of two tile types need be specified. +Tiles of the same type +are always considered to be connected. +Contacts are treated specially; they should be specified as +connecting to material in all planes spanned by the contact. +For example, pcontact is shown as connecting to +several types in the active plane, as well as several types +in the metal1 plane. +The connectivity of a contact should usually be that +of its component types, +so pcontact should connect +to everything connected to poly, and +to everything connected to metal1. + +\section{Cifoutput section} + +The layers stored by Magic do not always correspond to physical +mask layers. For example, there is no physical layer corresponding +to (the scmos technology file layer) ntransistor; instead, the actual +circuit must be built up by overlapping poly and diffusion over pwell. +When writing CIF (Caltech Intermediate Form) or Calma GDS-II files, +Magic generates the actual +geometries that will appear on the masks used to fabricate the +circuit. The {\bfseries cifoutput} section of the technology file +describes how to generate mask layers from Magic's abstract layers. + +\begin{table}[ht!] + \begin{center} + \begin{tabular}{|l|} \hline + {\bfseries cifoutput} \\ + style lambda=1.0(gen) \\ + \I scalefactor 100 \\ + \I layer CWN nwell \\ + \II bloat-or pdiff,pdc,pfet * 600 \\ + \II bloat-or nsc,nnd * 300 \\ + \II grow 300 \\ + \II shrink 300 \\ + \II gds 42 1 \\ + \I layer CWP pwell \\ + \II bloat-or ndiff,ndc,nfet * 600 \\ + \II bloat-or psc,ppd * 300 \\ + \II grow 300 \\ + \II shrink 300 \\ + \II gds 41 1 \\ + \I layer CMS allMetal2 \\ + \II labels m2 \\ + \II gds 51 1 \\ + \I layer CAA allDiff \\ + \II labels ndiff,pdiff \\ + \II gds 43 1 \\ + \I layer CCA ndc,pdc \\ + \II squares 200 \\ + \II gds 48 1 \\ + \I layer CCA nncont,ppcont \\ + \II squares 200 \\ + \II gds 48 1 \\ + \I layer CCP pc \\ + \II squares 200 \\ + \II gds 47 1 \\ + {\bfseries end} \\ \hline + \end{tabular} + \caption{Part of the {\bfseries cifoutput} section for style + lambda=1.0(gen) only.} + \label{cifoutput} + \end{center} +\end{table} + +\subsection{CIF and GDS styles} + +From the 1990's, the CIF format has largely been replaced by the +GDS format. However, they describe the same layout geometry, +and the formats are similar enough that magic makes use of the CIF +generation code as the basis for the GDS write routines. The +technology file also uses CIF layer declarations as the basis +for GDS output. So even a technology file that only expects to +generate GDS output needs a ``{\bfseries cifoutput}'' section +declaring CIF layer names. If only GDS output is required, these +names may be longer and therefore more descriptive than allowed +by CIF format syntax. + +The technology file can contain several different specifications +of how to generate CIF. Each of these is called a CIF +{\itshape style}. Different styles may be used for fabrication at +different feature sizes, or for totally different purposes. For +example, some of the Magic technology files contain a style +``plot'' that generates CIF pseudo-layers that have exactly the +same shapes as the Magic layers. This style is used for generating +plots that look just like what appears on the color display; it +makes no sense for fabrication. Lines of the form + +\starti + \ii {\bfseries style} {\itshape name} +\endi + +are used to end the description of the previous style and start +the description of a new style. The Magic command +{\bfseries :cif ostyle} {\itshape name} is typed by users to change +the current style used for output. The first style in the +technology file is used by default for CIF output if the +designer doesn't issue a {\bfseries :cif style} command. +If the first line of the {\bfseries cifoutput} +section isn't a {\bfseries style} line, then Magic uses an initial style +name of {\bfseries default}. + +\subsection{Scaling} + +Each style must contain a line of the form + +\starti + \ii {\bfseries scalefactor} {\itshape scale} + [{\bfseries nanometers}\vbar {\bfseries angstroms}] +\endi + +that tells how to scale Magic coordinates into CIF coordinates. +The argument {\itshape scale} indicates how many hundredths of a +micron correspond to one Magic unit. {\itshape scale} may be any +number, including decimals. However, all units in the style description +must be integer. Because deep submicron processes may require CIF +operations in units of less than one centimicron, the optional parameter +{\bfseries nanometers} declares that all units (including the {\itshape +scale} parameter) are measured in units of nanometers. Likewise, the +units may all be specified in {\bfseries angstroms}. However unlikely +the dimensions may seem, the problem is that magic needs to place some +objects, like contacts, on half-lambda positions to ensure correct +overlap of contact cuts between subcells. A feature size such as, +for example, 45 nanometers, has a half-lambda value of 22.5 nanometers. +Since this is not an integer, magic will complain about this scalefactor. +This is true even if the process doesn't {\itshape allow} sub-nanometer +coordinates, and magic uses the {\itshape squares-grid} statement to +enforce this restriction. In such a case, it is necessary to declare +a scalefactor of 450 angstroms rather than 45 nanometers. + +Versions of {\itshape magic} prior to 7.1 allowed an optional second +(integer) parameter, {\itshape reducer}, or the keyword {\bfseries calmaonly}. +The use of {\itshape reducer} is integral to CIF output, which uses the value +to ensure that output values are reduced to the smallest common denominator. +For example, if all CIF values are divisible by 100, then the reducer is set +to 100 and all output values are divided by the same factor, thus reducing +the size of the CIF output file. Now the reducer is calculated automatically, +avoiding any problems resulting from an incorrectly specified reducer value, +and any value found after {\itshape scale} is ignored. +The {\bfseries calmaonly} keyword specified that the {\itshape scale} was +an odd integer. This limitation has been removed, so any such keyword is +ignored, and correct output may be generated for either CIF or Calma at all +output scales. + +In addition to specifying a scale factor, each style can specify +the size in which chunks will be processed when generating CIF +hierarchically. This is particularly important when the average +design size is much larger than the maximum bloat or shrink (e.g, +more than 3 orders of magnitude difference). +The step size is specified by a line of the following form: + +\starti + \ii {\bfseries stepsize} {\itshape stepsize} +\endi + +where {\itshape stepsize} is in Magic units. For example, if you plan +to generate CIF for designs that will typically be 100,000 Magic +units on a side, it might make sense for {\itshape stepsize} to be +10000 or more. + +\subsection{Layer descriptions} + +The main body of information for each CIF style is a set of layer +descriptions. Each layer description consists of one or more +{\itshape operations} describing how to generate the CIF for a +single layer. The first line of each description is one of + +\starti + \ii {\bfseries layer} {\itshape name} [{\itshape layers}] +\endi +or +\starti + \ii {\bfseries templayer} {\itshape name} [{\itshape layers}] +\endi + +These statements are identical, except that templayers are not +output in the CIF file. They are used only to build up intermediate +results used in generating the ``real'' layers. In each case, +{\itshape name} is the CIF name to be used for the layer. If {\itshape layers} +is specified, it consists of a comma-separated list of Magic layers and +previously-defined CIF layers in this style; these layers form +the initial contents of the new CIF layer (note: the layer lists +in this section are less general than what was described in +Section~\ref{typelists}; tildes and parentheses are not allowed). +If {\itshape layers} is +not specified, then the new CIF layer is initially empty. The +following statements are used to modify the contents of a CIF +layer before it is output. + +After the {\bfseries layer} or {\bfseries templayer} statement come several +statements specifying geometrical operations to apply in building +the CIF layer. Each statement takes the current contents of the +layer, applies some operation to it, and produces the new contents +of the layer. The last geometrical operation for the layer determines +what is actually output in the CIF file. The most common geometrical +operations are: + +\starti + \ii {\bfseries or} {\itshape layers} \\ + \ii {\bfseries and} {\itshape layers} \\ + \ii {\bfseries and-not} {\itshape layers} \\ + \ii {\bfseries grow} {\itshape amount} \\ + \ii {\bfseries shrink} {\itshape amount} \\ + \ii {\bfseries bloat-or} {\itshape layers layers2 amount layers2 amount \dots} \\ + \ii {\bfseries squares} {\itshape size} \\ + \ii {\bfseries squares} {\itshape border size separation} \\ +\endi + +Some more obscure operations are: + +\starti + \ii {\bfseries grow-grid} {\itshape amount} \\ + \ii {\bfseries bloat-max} {\itshape layers layers2 amount layers2 amount \dots} \\ + \ii {\bfseries bloat-min} {\itshape layers layers2 amount layers2 amount \dots} \\ + \ii {\bfseries bloat-all} {\itshape layers layers2} \\ + \ii {\bfseries squares-grid} {\itshape border size separation x y} \\ + \ii {\bfseries slots} {\itshape border size separation} \\ + \ii {\bfseries slots} {\itshape border size separation border\_long} \\ + \ii {\bfseries slots} {\itshape border size separation border\_long + size\_long sep\_long} [{\itshape offset}]] \\ + \ii {\bfseries bbox} [{\bfseries top}] +\endi + +The operation {\bfseries or} takes all the {\itshape layers} (which may be +either Magic layers or previously-defined CIF layers), and or's +them with the material already in the CIF layer. The operation +{\bfseries and} is similar to {\bfseries or}, except that it and's the layers +with the material in the CIF layer (in other words, any CIF +material that doesn't lie under material in {\itshape layers} is +removed from the CIF layer). {\bfseries And-not} finds all areas covered +by {\itshape layers} and erases current CIF material from those areas. +{\bfseries Grow} and {\bfseries shrink} will +uniformly grow or shrink the current CIF layer by {\itshape amount} +units, where {\itshape amount} is specified in CIF units, not Magic +units. The {\bfseries grow-grid} operator grows layers non-uniformly +to snap to the grid spacing indicated by {\itshape amount}. This can be +used to ensure that features fall on a required minimum grid. + +The three ``bloat'' operations {\bfseries bloat-or}, +{\bfseries bloat-min}, and {\bfseries bloat-max}, provide selective forms +of growing. In these statements, all the layers must be Magic +layers. Each operation examines all the tiles in {\itshape layers}, +and grows the tiles by a different distance on each side, depending +on the rest of the line. Each pair {\itshape layers2 amount} specifies +some tile types and a distance (in CIF units). Where a tile of +type {\itshape layers} abuts a tile of type {\itshape layers2}, the first +tile is grown on that side by {\itshape amount}. The result is or'ed +with the current contents of the CIF plane. The layer ``{\bfseries *}'' may +be used as {\itshape layers2} to indicate all tile types. Where tiles +only have a single type of neighbor on each side, all three forms +of {\bfseries bloat} are identical. Where the neighbors are different, +the three forms are slightly different, as illustrated in Figure~\ref{bloat}. +Note: all the layers specified in any given {\bfseries bloat} +operation must lie on a single Magic plane. For {\bfseries bloat-or} +all distances must be positive. In {\bfseries bloat-max} and {\bfseries bloat-min} +the distances may be negative to provide a selective form of +shrinking. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/maint2.2.ps, width=\columnwidth} + \caption{The three different forms of {\bfseries bloat} behave + slightly differently when two different bloat distances apply + along the same side of a tile. In each of the above examples, + the CIF that would be generated is shown in bold outline. + If {\bfseries bloat-or} is specified, a jagged edge may + be generated, as on the left. If {\bfseries bloat-max} is used, + the largest bloat distance for each side is applied uniformly to + the side, as in the center. If {\bfseries bloat-min} is used, the + smallest bloat distance for each side is applied uniformly to the + side, as on the right.} + \end{center} + \label{bloat} +\end{figure} + +In retrospect, it's not clear that {\bfseries bloat-max} and {\bfseries bloat-min} +are very useful operations. The problem is that they operate on tiles, +not regions. This can cause unexpected behavior on concave regions. +For example, if the region being bloated is in the shape of a ``T'', a +single bloat factor will be applied to the underside of the horizontal +bar. If you use {\bfseries bloat-max} or {\bfseries bloat-min}, you should +probably specify design-rules that require the shapes being bloated to +be convex. + +The fourth bloat operation {\bfseries bloat-all} takes all tiles of +types {\itshape layers}, and grows to include all neighboring tiles of +types {\itshape layers2}. This is very useful to generate marker layers +or implant layers for specific devices, where the marker or implant must +cover both the device and its contacts. Take the material of the device +and use {\bfseries bloat-all} to expand into the contact areas. + +An important geometric operation for creating contact cuts is +{\bfseries squares}. It examines +each tile on the CIF plane, and replaces that tile with one or +more squares of material. Each square is {\itshape size} CIF units +across, and squares are separated by {\itshape separation} units. A border +of at least {\itshape border} units is left around the edge of the original +tile, if possible. This operation is used to generate contact vias, as in +Figure~\ref{squares}. If only one argument is given in the {\bfseries squares} +statement, then {\itshape separation} defaults to {\itshape size} and +{\itshape border} defaults to {\itshape size}/2. If a tile doesn't hold an +integral number of squares, extra space is left around the edges of +the tile and the squares are centered in the tile. If the tile is +so small that not even a single square can fit and still leave enough +border, then the border is reduced. If a square won't fit in the +tile, even with no border, then no material is generated. +The {\bfseries squares} operation +must be used with some care, in conjunction with the design rules. +For example, if there are several adjacent skinny tiles, there +may not be enough room in any of the tiles for a square, so no +material will be generated at all. Whenever you use the {\bfseries squares} +operator, you should use design rules to prohibit adjacent contact +tiles, and you should always use the {\bfseries no{\_}overlap} rule to prevent +unpleasant hierarchical interactions. The problems with hierarchy +are discussed in Section~\ref{hierarchy} below, and design rules are discussed +in Section~\ref{s_mzrouter}. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/maint2.3.ps, width=0.33\columnwidth} + \caption{The {\bfseries squares} operator chops each tile up + into squares, as determined by the {\itshape border}, {\itshape size}, + and {\itshape separation} parameters. In the example, the bold + lines show the CIF that would be generated by a {\bfseries squares} + operation. The squares of material are always centered so that + the borders on opposite sides are the same.} + \label{squares} + \end{center} +\end{figure} + +The {\bfseries squares-grid} operator is similar to {\bfseries squares} and +takes the same arguments, except for the additional optional {\itshape x} and +{\itshape y} offsets (which default to 1). Where the {\bfseries squares} +operator places contacts on the half-lambda grid, the {\bfseries squares-grid} +operator places contacts on an integer grid of {\itshape x} and {\itshape y}. +This is helpful where manufacturing grid limitations do not allow half-lambda +coordinates. However, it is necessary then to enforce a ``no-overlap'' rule +for contacts in the DRC section to prevent incorrect contacts cuts from +being generated in overlapping subcells. The {\bfseries squares-grid} +operator can also be used with {\itshape x} and {\itshape y} values to +generate fill geometry, or to generate offset contact cut arrays for pad +vias. + +The {\bfseries slots} operator is similar to {\bfseries squares} operator, +but as the name implies, the resulting shapes generated are rectangular, +not (necessarily) square. Slots are generated inside individual tiles, +like the squares operator, so each slots operation is separately oriented +relative to the tile's long and short edges. Separate border, size, and +separation values can be specified for the short and long dimensions of +the tile. This operator can be used in a number of situations: + +\begin{enumerate} + \item Generate square contact cuts with different border requirements on + the short and long sides, as required for a number of deep submicron + processes like 90 nanometer. + \item Automatically generate slots in large metal areas, which most + processes require. Note, however, that it is impossible to + correctly generate all slots, so this cannot completely replace + the widespacing DRC rule. + \item Generate slot contacts. + \item Generate fill geometry. + \item Generate marker layers for resitors that abut the position of + contacts, a generally-accepted way to define a resistor area + boundary. +\end{enumerate} + +Note that the {\bfseries slots} operator comes in three different forms +with different numbers of arguments. With only three arguments (short +side description only), the {\bfseries slots} operator creates stripes +that extend to the edge of the tile. With four arguments (short side +description plus long side border dimension only), the {\bfseries slots} +operator create stripes that extend to the edge of the tile, with +an appropriate border spacing at each end. In these two cases, the +slots have variable length that is set by the size of the tile. In the +final form, all short and long side dimensions are declared. The +generated slots are of fixed size, and like the {\bfseries squares} +operator, their positions will be adjusted to center them on the tile. +The {\itshape offset} is intended to let each row of slots be offset +from the previous one by a fixed amount, but is currently unimplemented +and has no effect. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/maint2.3b.ps, width=0.6\columnwidth} + \caption{The {\bfseries slots} operator chops each tile up + into rectangles.} + \label{slots} + \end{center} +\end{figure} + +The {\bfseries bbox} operator generates a single rectangle that encompasses +the bounding box of the cell. This is useful for the occasional process +that requires marker or implant layers covering an entire design. The +variant {\bfseries bbox top} will generate a rectangle encompassing the +bounding box of the cell, but will only do so for the top-level cell of the +design. + +\subsection{Labels} + +There is an additional statement permitted in the {\bfseries cifoutput} +section as part of a layer description: + +\starti + \ii {\bfseries labels} {\itshape Magiclayers} +\endi + +This statement tells Magic that labels attached to Magic layers +{\itshape Magiclayers} are to be associated with the current CIF layer. +Each Magic layer should only appear in one such statement for +any given CIF style. If a Magic layer doesn't appear in any +{\bfseries labels} statement, then it is not attached to a specific +layer when output in CIF. + +\subsection{Calma (GDS II Stream format) layers} + +Each layer description in the {\bfseries cifoutput} section may also +contain one of the following statements: + +\starti + \ii {\bfseries gds} {\itshape gdsNumber} {\itshape gdsType} \\ + \ii {\bfseries calma} {\itshape gdsNumber} {\itshape gdsType} +\endi + +Although the format is rarely referred to as ``Calma'' anymore, the +keyword is retained for backwards compatibility with format 27 (and +earlier) files. + +This statement tells Magic which layer number and data type +to use when the {\bfseries gds} command outputs GDS II Stream format +for this defined CIF layer. +Both {\itshape gdsNumber} and {\itshape gdsType} should be positive +integers, between 0 and 63. +Each CIF layer should have a different {\itshape gdsNumber}. +If there is no {\bfseries gds} line for a given CIF layer, then +that layer will not be output by the ``{\bfseries gds write}'' command. +The reverse is not true: every generated output layer must have a +defined CIF layer type, even if the foundry only supports GDS format. +In such case, the CIF layer name may violate the restrictive 4-character +format required by the CIF syntax specification, and may be used to +provide a reasonable, human-readable descriptive name of the GDS layer. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/maint2.4.ps, width=0.85\columnwidth} + \caption{If the operator {\bfseries grow 100} is applied to the + shapes in (a), the merged shape in (b) results. If the operator + {\bfseries shrink 100} is applied to (b), the result is (c). However, + if the two original shapes in (a) belong to different cells, and + if CIF is generated separately in each cell, the result will be + the same as in (a). Magic handles this by outputting additional + information in the parent of the subcells to fill in the gap between + the shapes.} + \label{growshrink} + \end{center} +\end{figure} + +\subsection{Hierarchy} \label{hierarchy} + +Hierarchical designs make life especially difficult for the +CIF generator. The CIF corresponding +to a collection of subcells may not necessarily be the same +as the sum of the CIF's of the individual cells. For example, +if a layer is generated by growing and then shrinking, nearby +features from different cells may merge together so that they +don't shrink back to their original shapes (see Figure~\ref{growshrink}). +If Magic +generates CIF separately for each cell, the interactions between +cells will not be reflected properly. The CIF generator attempts +to avoid these problems. Although it generates CIF in a +hierarchical representation that matches the Magic cell structure, +it tries to ensure that the resulting CIF patterns are exactly the same +as if the entire Magic design had been flattened into a single cell +and then CIF were generated from the flattened design. It does this +by looking in each cell for places where subcells are close enough +to interact with each other or with paint in the parent. Where this +happens, Magic flattens the interaction area and generates CIF for +it; then Magic flattens each of the subcells separately and generates +CIF for them. Finally, it compares the CIF from the subcells with the +CIF from the flattened parent. Where there is a difference, Magic +outputs extra CIF in the parent to compensate. + +Magic's hierarchical approach only works if the overall CIF for the +parent ends up covering at least as much area as the CIFs for the +individual components, so all compensation can be done by adding +extra CIF to the parent. In mathematical terms, this requires +each geometric operation to obey the rule + +\starti + \ii Op(A $\cup$ B) $\supseteq$ Op(A) $\cup$ Op(B) +\endi + +The operations {\bfseries and}, {\bfseries or}, {\bfseries grow}, and +{\bfseries shrink} all +obey this rule. Unfortunately, the {\bfseries and-not}, {\bfseries bloat}, +and {\bfseries squares} +operations do not. For example, if there are two partially-overlapping +tiles in different cells, the squares generated from one of the cells +may fall in the separations between squares in the other cell, resulting +in much larger areas of material than expected. +There are two ways around this problem. One +way is to use the design rules to prohibit problem situations from +arising. This applies mainly to the {\bfseries squares} operator. Tiles +from which squares are made should never be allowed to overlap +other such tiles in different cells unless the overlap is exact, +so each cell will generate squares in the same place. You can +use the {\bfseries exact{\_}overlap} design rule for this. + +The second approach is to leave things up to the designer. +When generating CIF, Magic issues warnings where there is less material +in the children than the parent. The designer can locate these problems +and eliminate the interactions that cause the trouble. Warning: +Magic does not check the {\bfseries squares} operations for hierarchical +consistency, so you absolutely must use {\bfseries exact{\_}overlap} design +rule checks! Right now, the {\bfseries cifoutput} section of the +technology is one of the trickiest things in the whole file, particularly +since errors here may not show up until your chip comes back and doesn't +work. Be extremely careful when writing this part! + +\begin{table}[ht!] + \begin{center} + \begin{tabular}{|l|} \hline + {\bfseries cifinput} \\ + style lambda=1.0(gen) \\ + \I scalefactor 100 \\ + \I layer m1 CMF \\ + \II labels CMF \\ + \I layer ndiff CSN \\ + \II and CAA \\ + \I layer nsd CWN \\ + \II and CSN \\ + \II and CAA \\ + \I layer nfet CPG \\ + \II and CAA \\ + \II and CSN \\ + \I layer ndc CCA \\ + \II grow 100 \\ + \II and CAA \\ + \II and CWP \\ + \II and CSN \\ + \II and CMF \\ + \I layer nncont CCA \\ + \II grow 100 \\ + \II and CAA \\ + \II and CSN \\ + \II and CWN \\ + \II and CMF \\ + \I calma CAA 1 * \\ + \I calma CCA 2 * \\ + \I calma CMF 4 * \\ + \I calma CPG 7 * \\ + \I calma CSN 8 * \\ + \I calma CWN 11 * \\ + \I calma CWP 12 * \\ + {\bfseries end} \\ \hline + \end{tabular} + \caption{Part of the {\bfseries cifinput} section. The order of + the layers is important, since each Magic layer overrides the + previous ones just as if they were painted by hand.} + \label{cifinput} + \end{center} +\end{table} + +Another problem with hierarchical generation is that it can be very +slow, especially when there are a number of rules in the cifoutput +section with very large grow or shrink distances, such that magic +must always expand its area of interest by this amount to be sure +of capturing all possible layer interactions. When this ``halo'' +distance becomes larger than the average subcell, much of the +design may end up being processed multiple times. Noticeably slow +output generation is usually indicative of this problem. It can +be alleviated by keeping output rules simple. Note that basic AND +and OR operations do not interact between subcells, so that rules +made from only these operators will not be processed during subcell +interaction generation. Remember that typically, subcell interaction +paint will only be generated for layers that have a ``grow'' operation +followed by a ``shrink'' operation. This common ruleset lets layers +that are too closely spaced to be merged together, thus eliminating +the need for a spacing rule between the layers. But consider carefully +before implementing such a rule. Implementing a DRC spacing rule +instead may eliminate a huge amount of output processing. Usually +this situation crops up for auto-generated layers such as implants and +wells, to prevent magic from auto-generating DRC spacing violations. +But again, consider carefully whether it might be better to require +the layout engineer to draw the layers instead of attempting to +auto-generate them. + +\subsection{Render statements} + +At the end of each style in the {\bfseries cifoutput} section, one may +include {\bfseries render} statements, one per defined CIF/GDS layer. +These {\bfseries render} statements are used by the 3-D drawing window +in the OpenGL graphics version of magic, and are also used by the +``{\bfseries cif see}'' command to set the style painted. The syntax +for the statement is as follows: + +\starti + \ii {\bfseries render} {\itshape cif\_layer style\_name height thickness} +\endi + +The {\itshape cif\_layer} is any valid layer name defined in the same +{\bfseries cifoutput} section where the {\bfseries render} statement occurs. +The {\itshape style\_name} is the name or number of a style in the styles +file. The names are the same as used in the {\bfseries styles} section of +the technology file. {\itshape height} and {\itshape thickness} are +effectively dimensionless units and are used for relative placement and +scaling of the three-dimensional layout view (such views generally have +a greatly expanded z-axis scaling). By default, all layers are given the +same style and a zero height and thickness, so effectively nothing useful +can be seen in the 3-D view without a complete set of {\bfseries render} +statements. + +\section{Cifinput section} + +In addition to writing CIF, Magic can also read in CIF files using +the {\bfseries :cif read} {\itshape file} command. The {\bfseries cifinput} +section of the technology file describes how to convert from CIF mask layers +to Magic tile types. +In addition, it provides information to the Calma reader to allow +it to read in Calma GDS II Stream format files. +The {\bfseries cifinput} section is very similar to the {\bfseries cifoutput} +section. It can contain several styles, with a line of the form + +\starti + \ii {\bfseries style} {\itshape name} +\endi + +used to end the description of the previous style (if any), and start a +new CIF input style called {\itshape name}. If no initial style name is +given, the name {\bfseries default} is assigned. Each style must have a +statement of the form + +\starti + \ii {\bfseries scalefactor} {\itshape scale} {\bfseries [nanometers]} +\endi + +to indicate the output scale relative to Magic units. Without the +optional keyword {\bfseries nanometers}, {\itshape scale} describes how +many hundredths of a micron correspond to one unit in Magic. With +{\bfseries nanometers} declared, {\itshape scale} describes how many +nanometers correspond to one unit in Magic. + +Like the {\bfseries cifoutput} section, each style consists of a number +of layer descriptions. A layer description contains one +or more lines describing a series of geometric operations to be +performed on CIF layers. The result of all these operations is +painted on a particular Magic layer just as if the user had +painted that information by hand. +A layer description begins with a statement of the form + +\starti + \ii {\bfseries layer} {\itshape magicLayer }[{\itshape layers}] +\endi + +In the {\bfseries layer} statement, {\itshape magicLayer} is the Magic layer +that will be painted after performing the geometric operations, +and {\itshape layers} is an optional list of CIF layers. If +{\itshape layers} is specified, it is the initial value for the layer +being built up. If {\itshape layers} isn't specified, the layer starts +off empty. As in the {\bfseries cifoutput} section, each line after +the {\itshape layer} statement gives a geometric operation that is applied +to the previous contents of the layer being built in order to generate +new contents for the layer. The result of the last geometric operation +is painted into the Magic database. + +The geometric operations that are allowed in the {\bfseries cifinput} section +are a subset of those permitted in the {\bfseries cifoutput} section: + +\starti + \ii {\bfseries or} {\itshape layers} \\ + \ii {\bfseries and} {\itshape layers} \\ + \ii {\bfseries and-not} {\itshape layers} \\ + \ii {\bfseries grow} {\itshape amount} \\ + \ii {\bfseries shrink} {\itshape amount} +\endi + +In these commands the {\itshape layers} must all be CIF layers, and the +{\itshape amounts} are all CIF distances (centimicrons, unless the keyword +{\bfseries nanometers} has been used in the {\bfseries scalefactor} +specification). As with the +{\bfseries cifoutput} section, layers can only be specified in simple +comma-separated lists: tildes and slashes are not permitted. + +When CIF files are read, all the mask information is read for a cell +before performing any of the geometric processing. After the cell +has been completely read in, the Magic layers are produced and +painted in the order they appear in the technology file. In +general, the order that the layers are processed is important +since each layer will usually override the previous ones. For +example, in the scmos tech file shown in Table~\ref{cifinput} the commands +for {\bfseries ndiff} will result in the {\bfseries ndiff} layer being generated +not only where there is only ndiffusion +but also where there are +ntransistors and ndcontacts. +The descriptions +for {\bfseries ntransistor} and {\bfseries ndcontact} appear later in the section, +so those layers will replace the {\bfseries ndiff} material that was originally +painted. + +Labels are handled in the {\bfseries cifinput} section just like in the +{\bfseries cifoutput} section. A line of the form + +\starti + \ii {\bfseries labels} {\itshape layers} +\endi + +means that the current Magic layer is to receive all CIF labels +on {\itshape layers}. This is actually just an initial layer assignment +for the labels. Once a CIF cell has been read in, Magic scans the +label list and re-assigns labels if necessary. In the example of +Table~\ref{cifinput}, if a label is attached to the CIF layer CPG then it will +be assigned to the Magic layer {\bfseries poly}. However, the polysilicon +may actually be part of a poly-metal contact, which is Magic layer +{\bfseries pcontact}. After all the mask information has been processed, +Magic checks the material underneath the layer, and adjusts the +label's layer to match that material ({\bfseries pcontact} in this case). +This is the same as what would happen if a designer painted {\bfseries poly} +over an area, attached a label to the material, then painted {\bfseries pcontact} +over the area. + +No hierarchical mask processing is done for CIF input. Each cell +is read in and its layers are processed independently +from all other cells; Magic assumes that there +will not be any unpleasant interactions between cells as happens +in CIF output (and so far, at least, this seems to be a valid +assumption). + +If Magic encounters a CIF layer name that doesn't appear +in any of the lines for the current CIF input style, it +issues a warning message and ignores the information associated +with the layer. If you would like Magic to ignore certain +layers without issuing any warning messages, insert a line +of the form + +\starti + \ii {\bfseries ignore} {\itshape cifLayers} +\endi + +where {\itshape cifLayers} is a comma-separated list of one or +more CIF layer names. + +Calma layers are specified via {\bfseries calma} lines, which should appear +at the end of the {\bfseries cifinput} section. They are of the form: + +\starti + \ii {\bfseries calma} {\itshape cifLayer} {\itshape calmaLayers} + {\itshape calmaTypes} +\endi + +The {\itshape cifLayer} is one of the CIF types mentioned in the {\bfseries cifinput} +section. Both {\itshape calmaLayers} and {\itshape calmaTypes} are one or more +comma-separated integers between 0 and 63. The interpretation of +a {\bfseries calma} line is that any Calma geometry whose layer is any +of the layers in {\itshape calmaLayers}, and whose type is any of the +types in {\itshape calmaTypes}, should be treated as the CIF layer +{\itshape cifLayer}. +Either or both of {\itshape calmaLayers} and {\itshape calmaTypes} may be +the character {\bfseries *} instead of a comma-separated list of integers; +this character means {\itshape all} layers or types respectively. +It is commonly used for {\itshape calmaTypes} to indicate that the +Calma type of a piece of geometry should be ignored. + +Just as for CIF, Magic also issues warnings if it encounters +unknown Calma layers while reading Stream files. If there are +layers that you'd like Magic to ignore without issuing warnings, +assign them to a dummy CIF layer and ignore the CIF layer. + +\section{Lef section} + +This section defines a mapping between magic layers and layers that may +be found in LEF and DEF format files. Without the section, magic cannot +read a LEF or DEF file. The LEF and DEF layer declarations are usually +simple and straightforward (as they typically define metal layers only), +so often it will suffice to insert a plain vanilla {\bfseries lef} section +into a technology file if one is missing. The {\bfseries lef} section +was introduced in technology file format 28, and is therefore absent from +all {\ttfamily .tech27} technology files. All of the statements in +the {\bfseries lef} section have the same format: + +\starti + \ii {\bfseries layer} {\itshape magic-type lefdef-type} \dots \\ + \ii {\bfseries cut} {\itshape magic-type lefdef-type} \dots \\ + \ii {\bfseries route}\vbar {\bfseries routing} {\itshape magic-type lefdef-type} + \dots \\ + \ii {\bfseries obstruction} {\itshape magic-type lefdef-type} \dots \\ + \ii {\bfseries masterslice} {\itshape magic-type lefdef-type} \dots \\ + \ii {\bfseries overlap} {\itshape magic-type lefdef-type} \dots +\endi + +Each statement defines a mapping between a Magic layer type +{\itshape magic-type} and one or more type names {\itshape lefdef-type} +(space-separated) that might be encountered in a LEF or DEF file. The +different command names all refer to different type classes defined +by the LEF/DEF specification. For most purposes, it is only necessary +to use the {\bfseries layer} statement. If the magic type is a contact +type, then the {\bfseries layer} statement is equivalent to specifying +{\bfseries cut}; otherwise, it is equivalent to {\bfseries route}. + +Table \ref{lefdef} is a typical {\bfseries lef} section for a 5-metal technology, +which encompasses the most commonly used layer names found in LEF and DEF files. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|lllllll|} \hline + {\bfseries lef} &&&&&& \\ + & masterslice & ndiff & diffusion & active && \\ + & masterslice & poly & poly & POLY1 & pl & \\ + & routing & m1 & m1 & metal1 & METAL1 & METAL\_1 \\ + & routing & m2 & m2 & metal2 & METAL2 & METAL\_2 \\ + & routing & m3 & m3 & metal3 & METAL3 & METAL\_3 \\ + & routing & m4 & m4 & metal4 & METAL4 & METAL\_4 \\ + & routing & m5 & m5 & metal5 & METAL5 & METAL\_5 \\ + &&&&&&\\ + & cut & pc & cont1 & pl-m1 && \\ + & cut & m2c & via1 & cont2 & VIA12 & m1-m2 \\ + & cut & m3c & via2 & cont3 & VIA23 & m2-m3 \\ + & cut & m4c & via3 & cont4 & VIA34 & m3-m4 \\ + & cut & m5c & via4 & cont5 & VIA45 & m4-m5 \\ + &&&&&& \\ + & overlap & comment & overlap & OVERLAP && \\ + {\bfseries end} &&&&&& \\ \hline + \end{tabular} + \caption{A plain vanilla lef section.} + \label{lefdef} + \end{center} +\end{table} + +\section{Mzrouter section} \label{s_mzrouter} + +This section defines the layers and contacts available to the Magic maze router, {\itshape mzrouter}, and assigns default costs for each type. Default widths +and spacings are +derived from the {\bfseries drc} section of the technology file (described below) +but can be overridden in this +section. Other mzrouter parameters, for example, search rate and width, +can also be specified in this section. The syntax and function of the +lines in the {\bfseries mzrouter} section of the technology file +are specified in the subsections below. Each +set of specifications should be headed by a {\bfseries style} line. +{\bfseries Routelayer} +and {\bfseries routecontact} specifications should precede references to them. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|llllll|} \hline + {\bfseries mzrouter} &&&&& \\ + style & irouter &&&& \\ + layer & m2 & 32 & 64 & 256 & 1 \\ + layer & m1 & 64 & 32 & 256 & 1 \\ + layer & poly & 128 & 128 & 512 & 1 \\ + contact & m2contact & metal1 & metal2 & 1024 & \\ + contact & pcontact & metal1 & poly & 2056 & \\ + notactive & poly & pcontact &&& \\ + style & garouter &&&& \\ + layer & m2 & 32 & 64 & 256 & 1 \\ + layer & m1 & 64 & 32 & 256 & 1 \\ + contact & m2contact & metal1 & metal2 & 1024 & \\ + {\bfseries end} &&&&& \\ \hline + \end{tabular} + \caption{Mzrouter section for the scmos technology.} + \label{mzrouter} + \end{center} +\end{table} + +\subsection{Styles} + +The mzrouter is currently used in two contexts, +interactively via the {\bfseries iroute} command, and as a subroutine to the garouter +for stem generation. To permit distinct parameters for these two +uses, the lines in the {\bfseries mzrouter} section are grouped into {\itshape styles}. +The lines pertaining to the irouter should be preceded by + +\starti + \ii {\bfseries style irouter} +\endi + +and those pertaining to the garouter should be preceded by the specification + +\starti + \ii {\bfseries style garouter} +\endi + +Other styles can be specified, but are currently not used. +Table~\ref{mzrouter} shows the mzrouter section from the scmos technology. + +\subsection{Layers} + +Layer lines +define the route-layers available to the maze router in that style. They +have the following form: + +\starti + \ii {\bfseries layer} {\itshape type hCost vCost jogCost hintCost} +\endi + +Here {\itshape type} is the name of the tiletype of the layer and {\itshape hCost}, +{\itshape vCost}, {\itshape jogCost} and {\itshape hintCost}, are non-negative integers +specifying the cost per unit horizontal distance, +cost per unit vertical distance, cost per jog, and +cost per unit area of deviation from magnets, respectively. Route layers +for any given style must lie in distinct planes. + +\subsection{Contacts} + +Contact lines specify +the route-contacts available to the mzrouter in the current +style. They have the following form: + +\starti + \ii {\bfseries contact} {\itshape type routeLayer1 routeLayer2 cost} +\endi + +Here {\itshape type} is the tiletype of the contact, {\itshape routeLayer1} and +{\itshape routeLayer2} are the two layers connected by the contact, and {\itshape cost} +is a nonnegative integer specifying the cost per contact. + +\subsection{Notactive} + +It maybe desirable to have a layer or contact available to the maze router, +but default to off, i.e., not be used by the mzrouter until explicitly +made active. Route-types (route-layers or route-contacts) can be made to +default to off with the following specification: + +\starti + \ii {\bfseries notactive} {\itshape route-type} \dots [{\bfseries route-typen}] +\endi + +\subsection{Search} + +The search {\bfseries rate}, {\bfseries width}, and {\bfseries penalty} parameters can +be set with a specification of the form: + +\starti + \ii {\bfseries search} {\itshape rate width penalty} +\endi + +Here {\itshape rate} and {\itshape width} are positive integers. And {\itshape penalty} +is a positive rational (it may include a decimal point). See the irouter +tutorial for a discussion of these parameters. (Note that {\bfseries penalty} +is a ``wizardly'' parameter, i.e., it is interactively +set and examined via {\bfseries iroute wizard} not {\bfseries iroute search}). +If no {\bfseries search} line +is given for a style, the overall mzrouter defaults are used. + +\subsection{Width} + +Appropriate widths for route-types are normally derived from the {\bfseries drc} +section +of the technology file. These can be overridden with width specifications +of the following form: + +\starti + \ii {\bfseries width} {\itshape route-type width} +\endi + +Here {\itshape width} is a positive integer. + +\subsection{Spacing} + +Minimum spacings between routing on a route-type and other types are +derived from the design rules. These values can be overridden by explicit +spacing specifications in the {\bfseries mzrouter} section. Spacing +specifications have the following form: + +\starti + \ii {\bfseries spacing} {\itshape routetype type1 spacing1 } \dots + [{\itshape typen spacingn}] +\endi + +Spacing values must be nonnegative integers or {\bfseries NIL}. The special type +{\bfseries SUBCELL} can be used to specify minimum spacing to unexpanded subcells. + +\section{Drc section} + +The design rules used by Magic's design rule checker +come entirely from the technology file. +We'll look first at two simple kinds of rules, +{\bfseries width} and and {\bfseries spacing}. +Most of the rules in the {\bfseries drc} +section are one or the other of these kinds of rules. + +\subsection{Width rules} + +The minimum width of a collection of types, taken together, +is expressed by a {\bfseries width} rule. +Such a rule has the form: + +\starti + \ii {\bfseries width} {\itshape type-list width error} +\endi + +where {\itshape type-list} is a set of tile types +(see Section~\ref{typelists} for syntax), +{\itshape width} is an integer, and {\itshape error} +is a string, enclosed in double quotes, +that can be printed by the command {\bfseries :drc why} +if the rule is violated. +A width rule requires that all regions containing any types +in the set {\itshape types} must be wider than {\itshape w} in both dimensions. +For example, in Table~\ref{drcwidth}, the rule + +\starti + \ii {\bfseries width} nwell 6 {\itshape {\q}N-Well width must be at least 6 + (MOSIS rule \#1.1){\q}} +\endi + +means that nwells must be at least 6 units +wide whenever they appear. +The {\itshape type-list} +field may contain more than a single type, as in the following rule: + +\starti + \ii {\bfseries width} allDiff 2 {\itshape {\q}Diffusion width must + be at least 2 (MOSIS rule \#2.1){\q}} +\endi + +which means that all regions consisting of the types +containing any kind of diffusion +be at least 2 units wide. +Because many of the rules in the {\bfseries drc} section refer to the +same sets of layers, the {\bfseries \#define} facility of the C preprocessor +is used to define a number of macros for these sets of layers. +Table~\ref{drctiles} gives a complete list. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|lll|} \hline + \#define & allDiff & ndiff,pdiff,ndc/a,pdc/a,ppcont/a,nncont/a,pfet,nfet,psd,nsd + \\ + \#define & extPoly & poly,pcontact \\ + \#define & extM1 & metal1,pcontact/m1,ndc/m1,ppcont/m1,pdc/m1,nncont/m1 \\ + \#define & extM2 & metal2,m2contact/m2 \\ \hline + \end{tabular} + \caption{Abbreviations for sets of tile types.} + \label{drctiles} + \end{center} +\end{table} + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|llll|} \hline + width & pwell & 6 & {\q}P-Well width must be at least 6 + (MOSIS rule \#1.1){\q} \\ + width & nwell & 6 & {\q}N-Well width must be at least 6 + (MOSIS rule \#1.1){\q} \\ + width & allDiff & 2 & {\q}Diffusion width must be at least 2 + (MOSIS rule \#2.1){\q} \\ + width & allPoly & 2 & {\q}Polysilicon width must be at least 2 + (MOSIS rule \#3.1){\q} \\ \hline + \end{tabular} + \caption{Some width rules in the {\bfseries drc} section.} + \label{drcwidth} + \end{center} +\end{table} + +All of the layers named in any one width rule must lie on the +same plane. However, if some of the layers are contacts, Magic +will substitute a different contact image if the named image +isn't on the same plane as the other layers. + +\subsection{Spacing rules} + +The second simple kind of design rule is a {\bfseries spacing} rule. +It comes in two flavors: +{\bfseries touching{\_}ok}, and {\bfseries touching{\_}illegal}, +both with the following syntax: + +\starti + \ii {\bfseries spacing} {\itshape types1 types2 distance flavor error} +\endi + +The first flavor, {\bfseries touching{\_}ok}, does not prohibit +{\itshape types1} and {\itshape types2} from being immediately adjacent. +It merely requires that any type in the set {\itshape types1} +must be separated by a ``Manhattan'' distance of at least +{\itshape distance} units from any type in the set {\itshape types2} +that is not immediately adjacent to the first type. +See Figure~\ref{distance} for an illustration of Manhattan distance +for design rules. +As an example, consider the metal1 separation rule: + +\starti + \ii {\bfseries spacing} allPoly allPoly 2 {\bfseries touching{\_}ok} {\bk} \\ + \ii\> {\itshape {\q}Polysilicon spacing must be at least 2 (MOSIS rule \#3.2){\q}} +\endi + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/maint2.5.ps, width=0.4\columnwidth} + \caption{For design rule checking, the Manhattan distance between + two horizontally or vertically aligned points is just the normal + Euclidean distance. If they are not so aligned, then the Manhattan + distance is the length of the longest side of the right triangle + forming the diagonal line between the points.} + \end{center} + \label{distance} +\end{figure} + +This rule is symmetric ({\itshape types1} is equal to {\itshape types2}), +and requires, for example, that a pcontact +be separated by at least 2 units from a piece of polysilicon. +However, this rule does not prevent the pcontact +from touching a piece of poly. In {\bfseries touching{\_}ok} rules, +all of the layers in both {\itshape types1} and {\itshape types2} must be stored +on the same plane (Magic will substitute different contact +images if necessary). + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|lllll|} \hline + spacing & allPoly & allPoly & 2 & touching{\_}ok {\bk} \\ + & \multicolumn{4}{l|}{{\itshape {\q}Polysilicon spacing must be + at least 2 (MOSIS rule \#3.2){\q}}} \\ + spacing & pfet & nncont,nnd & 3 & touching{\_}illegal {\bk} \\ + & \multicolumn{4}{l|}{{\itshape {\q}Transistors must be separated + from substrate contacts by 3 (MOSIS rule \#4.1){\q}}} \\ + spacing & pc & allDiff & 1 & touching{\_}illegal {\bk} \\ + & \multicolumn{4}{l|}{{\itshape {\q}Poly contact must be 1 unit + from diffusion (MOSIS rule \#5B.6){\q}}} \\ \hline + \end{tabular} + \caption{Some spacing rules in the {\bfseries drc} section.} + \label{drcspacing} + \end{center} +\end{table} + +{\bfseries TOUCHING{\_}OK SPACING} RULES DO NOT WORK +FOR VERY LARGE SPACINGS (RELATIVE TO THE TYPES INVOLVED). SEE FIGURE 6 +FOR AN EXPLANATION. If the spacing to be checked is greater +than the width of one of the types involved plus either its self-spacing or +spacing to a second involved type, +{\bfseries touching{\_}ok spacing} may not work properly: a violation can +be masked by an intervening touching type. In such cases the rule +should be written using the {\bfseries edge4way} construct described below. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/maint2.6.ps, width=0.5\columnwidth} + \caption{The {\bfseries touching{\_}ok} rules cancels spacing checks + if the material is touching. This means that even distant material + won't be checked for spacing. If the rule applied at edge A is a + touching{\_}ok rule between material t1 and t2, then no check will + be made between the t1 material and the t2 material on the far right + side of the diagram. If this check was desired, it could be + accomplished in this case by a {\bfseries edge4way} check from edge + B. This would not work in general, though, because that check + could also be masked by material of type t2, causing the touching{\_}ok + rule to be invoked.} + \label{touchingok} + \end{center} +\end{figure} + +The second flavor of spacing rule, {\bfseries touching{\_}illegal}, disallows +adjacency. It is used for rules where {\itshape types1} and {\itshape types2} +can never touch, as in the following: + +\starti + \ii {\bfseries spacing} pc allDiff 1 {\bfseries touching{\_}illegal} {\bk} \\ + \ii\> {\itshape {\q}Poly contact must be 1 unit from diffusion + (MOSIS rule \#5B.6){\q}} +\endi + +Pcontacts and any type of diffusion must be at least 1 unit apart; +they cannot touch. +In {\bfseries touching{\_}illegal} +rules {\itshape types1} and {\itshape types2} may not have any types in common: +it would be rather strange not to permit a type to touch itself. In +{\bfseries touching{\_}illegal} rules, {\itshape types1} +and {\itshape types2} may be spread across multiple planes; Magic will find +violations between material on different planes. + +\subsection{Wide material spacing rules} + +Many fabrications processes require a larger distance between layers when +the width and length of one of those layers exceeds a certain minimum +dimension. For instance, a process might declare that the normal spacing +between metal1 lines is 3 microns. However, if a metal1 line exceeds +a width of 100 microns, then the spacing to other unrelated metal1 lines +must increase to 10 microns. This situation is covered by the +{\bfseries widespacing} rule. The syntax for {\bfseries widespacing} is as +follows: + +\starti + \ii {\bfseries widespacing} {\itshape types1 wwidth types2 distance flavor error} +\endi + +The {\bfseries widespacing} rule matches the syntax of {\bfseries spacing} in all +respects except for the addition of the parameter {\itshape wwidth}, which declares +the minimum width of layers of type(s) {\itshape types1} that triggers the rule. +So for the example above, the correct {\bfseries widespacing} rule would be +(assuming 1 magic unit = 1 micron): + +\starti + \ii {\bfseries widespacing} allMetal1 100 allMetal1 10 {\bfseries touching{\_}ok} {\bk} \\ + \ii\> {\itshape {\q}Space to wide Metal1 (length and width \grt 100) must be at least 10{\q}} +\endi + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/maint2.6b.ps, width=0.8\columnwidth} + \caption{The {\bfseries widespacing} rule covers situations like that + shown above, in which material of type {\itshape t1} normally must + be {\itshape dist} units away from type {\itshape t2} (situation A). + However, if both dimensions of material type {\itshape t1} are + larger than or equal to some width {\itshape wwidth} (situation B), + then the spacing must be increased to {\itshape wdist}.} + \label{widespacing} + \end{center} +\end{figure} + +\subsection{Surround rule} + +The {\bfseries surround} rule specifies what distance a layer must surround +another, and whether the presence of the surrounding material is optional or +mandatory. This rule is designed for materials which must {\itshape completely} +surround another, such as metal around a contact cut or MiM capacitor layer. +The syntax is: + +\starti + \ii {\bfseries surround} {\itshape types1 types2 distance presence error} +\endi + +and states that the layers in {\itshape types2} must surround the layers +in {\itshape types1} by an amound {\itshape distance} lambda units. The +value of {\itshape presence} must be one of the keywords {\bfseries +absence\_ok} or {\bfseries absence\_illegal}. When {\itshape presence} is +{\bfseries absence\_illegal}, then types {\itshape types2} must always be +present when types {\itshape types1} are present. When {\itshape presence} +is {\bfseries absence\_ok}, types {\itshape types1} may exist outside of +types {\itshape types2} without error, but where they coincide, types +{\itshape types2} must overlap {\itshape types1} by the amount +{\itshape distance}. + +\subsection{Overhang rule} rule specifies what distance a layer must overhang +another at an intersection. This is used, for example, to specify the length +of polysilicon end-caps on transistors, which is the distance that the +polysilicon gate must extend beyond the defined gate area of the transistor +to ensure a correctly operating device. The syntax is: + +\starti + \ii {\bfseries overhang} {\itshape types1 types2 distance error} +\endi + +and states that layers in {\itshape types1} must overhang layers in +{\itshape types2} by an amount {\itshape distance} lambda units. The +rule flags the complete absence of types {\itshape types1}, but does not +prohibit the use of {\itshape types1} as a bridge (that is, with +types {\itshape types2} on either side of {\itshape types1}, which +will generally be covered by a separate spacing rule, and which may +have a different spacing requirement). + +\subsection{Rectangle-only rule} + +The {\bfseries rect\_only} rule is used to denote layers that must be +rectangular; that is, they cannot bend, or have notches or tabs. +Generally, this is used for contacts, so that the CIF output operator +{\bfseries squares} will be guaranteed to generate a correct contact. +This is due to magic's corner-stitching tile database, where bends, +notches, tabs, and slots will break up an otherwise continuous patch +of material into potentially many small tiles, each one of which +might be too small to fit a contact cut. + +\starti + \ii {\bfseries rect\_only} {\itshape types error} +\endi + +\subsection{Edge rules} + +The width and spacing rules just described are actually translated +by Magic into an underlying, edge-based rule format. This underlying +format can handle rules more general than simple widths and spacings, +and is accessible to the writer of a technology file via {\bfseries edge} rules. +These rules are applied at boundaries between material of +two different types, in any of four directions as shown in Figure~\ref{tileedge}. +The design rule table contains a separate list of rules for each possible +combination of materials on the two sides of an edge. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/maint2.7.ps, width=0.4\columnwidth} + \caption{Design rules are applied at the edges between tiles in + the same plane. A rule is specified in terms of type {\itshape t1} + and type {\itshape t2}, the materials on either side of the edge. + Each rule may be applied in any of four directions, as shown by + the arrows. The simplest rules require that only certain mask types + can appear within distance {\itshape d} on {\itshape t2}'s side of + the edge.} + \label{tileedge} + \end{center} +\end{figure} + +In its simplest form, a rule specifies a distance +and a set of mask types: only the given types are permitted +within that distance on {\itshape type2}'s side of the edge. +This area is referred to as the {\itshape constraint region}. +Unfortunately, this simple scheme will miss errors +in corner regions, such as the case shown in Figure~\ref{cornererror}. +To eliminate these problems, the full rule format allows the constraint +region to be extended past the ends of the edge under some +circumstances. +See Figure~\ref{cornerextend} for an illustration of the +corner rules and how they work. +Table~\ref{edgerules1} gives a complete +description of the information in each design rule. + +\begin{figure}[hb!] + \begin{center} + \epsfig{file=../psfigures/maint2.8.ps, width=0.7\columnwidth} + \caption{If only the simple rules from Figure~\ref{tileedge} are used, errors + may go unnoticed in corner regions. For example, the polysilicon + spacing rule in (a) will fail to detect the error in (b).} + \label{cornererror} + \end{center} +\end{figure} + +\begin{figure}[ht!] + \begin{center} + \epsfig{file=../psfigures/maint2.9.ps, width=0.75\columnwidth} + \caption{The complete design rule format is illustrated in (a). + Whenever an edge has {\itshape type1} on its left side and + {\itshape type2} on its right side, the area A is checked to be + sure that only {\itshape OKTypes} are present. If the material + just above and to the left of the edge is one of + {\itshape cornerTypes}, then area B is also checked to be + sure that it contains only {\itshape OKTypes}. A similar + corner check is made at the bottom of the edge. Figure (b) + shows a polysilicon spacing rule, (c) shows a situation where + corner extension is performed on both ends of the edge, and + (d) shows a situation where corner extension is made only at + the bottom of the edge. If the rule described in (d) were to + be written as an {\bfseries edge} rule, it would look like:} + \starti + \ii {\bfseries edge} poly space 2 \~{}poly \~{}poly 2 {\bk} \\ + \ii\> {\itshape {\q}Poly-poly separation must be at least 2{\q}} + \endi + \label{cornerextend} + \end{center} +\end{figure} + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|l|p{0.5\columnwidth}|} \hline + Parameter & Meaning \\ \hline \hline + type1 & Material on first side of edge. \\ \hline + type2 & Material on second side of edge. \\ \hline + d & Distance to check on second side of edge. \\ \hline + OKTypes & List of layers that are permitted within + {\itshape d} units on second side of edge. + ({\itshape OKTypes}={\bfseries 0} means never OK) \\ \hline + cornerTypes & List of layers that cause corner extension. + ({\itshape cornerTypes}={\bfseries 0} means no + corner extension) \\ \hline + cornerDist & Amount to extend constraint area when + {\itshape cornerTypes} matches. \\ \hline + plane & Plane on which to check constraint region (defaults + to same plane as {\itshape type1} and {\itshape type2} + and {\itshape cornerTypes}). \\ \hline + \end{tabular} + \caption{The parts of an edge-based rule.} + \label{edgerules1} + \end{center} +\end{table} + +Edge rules are specified in the technology file using the following syntax: + +\starti + \ii {\bfseries edge} {\itshape types1 types2 d OKTypes cornerTypes + cornerDist error} [{\itshape plane}] +\endi + +Both {\itshape types1} and {\itshape types2} are type-lists. +An edge rule is generated for each pair consisting of a type from +{\itshape types1} and a type from {\itshape types2}. All the types in +{\itshape types1}, {\itshape types2}, and {\itshape cornerTypes} must lie +on a single plane. See Figure~\ref{cornerextend} for an example edge rule. +It is sometimes +useful to specify a null list, i.e., {\bfseries 0}, for {\itshape OKTypes} +or {\itshape CornerTypes}. Null {\itshape OKTypes} means no edges between +{\itshape types1} and {\itshape types2} are OK. Null {\itshape CornerTypes} +means no corner extensions are to be checked (corner extensions are explained +below). + +Some of the edge rules in Magic have the property that if a rule +is violated between two pieces of geometry, the violation can be +discovered looking from either piece of geometry toward the other. +To capitalize on this, Magic normally applies an edge +rule only in two of the four possible directions: bottom-to-top +and left-to-right, reducing the work it has to do by a factor of two. +Also, the corner extension is only performed to one side of the edge: +to the top for a left-to-right rule, and to the left for a bottom-to-top +rule. All of the width and spacing rules translate neatly into edge +rules. + +However, you'll probably find it easiest when you're writing +edge rules to insist that they be checked in all directions. +To do this, write the rule the same way except use the keyword +{\bfseries edge4way} instead of {\bfseries edge}: + +\starti + \ii {\bfseries edge4way} nfet ndiff 2 ndiff,ndc ndiff 2 {\bk} \\ + \ii\> {\itshape {\q}Diffusion must overhang transistor by at least 2{\q}} +\endi + +Not only are {\bfseries edge4way} rules checked in all four directions, +but the corner extension is performed on {\itshape both} sides of the +edge. For example, when checking a rule from left-to-right, +the corner extension is performed both to the top and to the bottom. +{\bfseries Edge4way} rules take twice as much time to check as {\bfseries edge} +rules, so it's to your advantage to use {\bfseries edge} rules wherever +you can. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|lllllll|} \hline + edge4way & ppcont,ppd & ndiff,ndc,nfet & 3 & ndiff,ndc,nfet & + ndiff,ndc,nfet & 3 {\bk} \\ + & \multicolumn{5}{l}{{\itshape {\q}Ndiff must be 3 wide if it abuts + ppcont or ppd (MOSIS rule \#??){\q}}} & \\ + edge4way & allPoly & \~{}(allPoly)/active & 3 & \~{}pc/active & + \~{}(allPoly)/active & 3 {\bk} \\ + & \multicolumn{5}{l}{{\itshape {\q}Poly contact must be at least 3 from + other poly (MOSIS rule \#5B.4,5){\q}}} & \\ + edge4way & allPoly & \~{}(allPoly)/active & 1 & \~{}m2c/metal2 & + \~{}(allPoly)/active & 1 {\bk} \\ + & \multicolumn{5}{l}{{\itshape {\q}Via must be on a flat surface + (MOSIS rule \#8.4,5){\q}} metal2} & \\ \hline + \end{tabular} + \caption{Some edge rules in the {\bfseries drc} section.} + \label{edgerules2} + \end{center} +\end{table} + +Normally, an edge rule is checked completely within a single plane: +both the edge that triggers the rule and the constraint area to check +fall in the same plane. However, the {\itshape plane} argument can be +specified in an edge rule to force Magic to perform the constraint +check on a plane different from the one containing the triggering +edge. In this case, {\itshape OKTypes} must all be tile types in {\itshape plane}. +This feature is used, for example, to ensure that +polysilicon and diffusion edges don't lie underneath metal2 contacts: + +\starti + \ii {\bfseries edge4way} allPoly \~{}(allPoly)/active 1 \~{}m2c/metal2 + \~{}(allPoly)/active 1 {\bk} \\ + \ii\> {\itshape {\q}Via must be on a flat surface (MOSIS rule \#8.4,5){\q}} metal2 +\endi + +Magic versions using techfile formats more recent than 28 are generally +more clever about determining the correct plane from {\itshape OKTypes} +when they differ from the triggering types, and the situation is +unambiguous (use of ``space'' in rules tends to introduce ambiguity, since +space tiles appear on all planes). + +\subsection{Subcell Overlap Rules} + +In order for CIF generation and circuit extraction to work properly, +certain kinds of overlaps between subcells must be prohibited. The +design-rule checker provides two kinds of rules for restricting +overlaps. They are + +\starti + \ii {\bfseries exact{\_}overlap} {\itshape type-list} \\ + \ii {\bfseries no{\_}overlap} {\itshape type-list1 type-list2} +\endi + +In the {\bfseries exact{\_}overlap} rule, {\itshape type-list} +indicates one or more tile types. +If a cell contains a tile of one of these types and that tile is +overlapped by another tile of the same type from a different cell, +then the overlap must be exact: the tile in each cell must cover +exactly the same area. Abutment between tiles from different cells +is considered to be a partial overlap, so it is prohibited too. +This rule is used to ensure that the CIF {\bfseries squares} operator +will work correctly, as described in Section~\ref{hierarchy}. +See Table~\ref{exactoverlap} for the {\bfseries exact{\_}overlap} +rule from the standard scmos technology file. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|lll|} \hline + exact{\_}overlap & \multicolumn{2}{l|}{m2c,ndc,pdc,pc,ppcont,nncont} \\ + no{\_}overlap & pfet,nfet & pfet,nfet \\ \hline + \end{tabular} + \caption{Exact{\_}overlap rule in the {\bfseries drc} section.} + \label{exactoverlap} + \end{center} +\end{table} + +The {\bfseries no{\_}overlap} rule makes illegal any overlap between a tile in +{\itshape type-list1} and a tile in {\itshape type-list2}. You should rarely, +if ever, need to specify {\bfseries no{\_}overlap} rules, since +Magic automatically prohibits many kinds of overlaps between +subcells. After reading the technology file, Magic examines the paint +table and applies the following rule: if two tile types A and +B are such that the result of painting A over B +is neither A nor B, or the result of painting B over A isn't +the same as the result of painting A over B, then A and B +are not allowed to overlap. +Such overlaps are prohibited because they change the +structure of the circuit. Overlaps are supposed only to connect +things without making structural changes. Thus, for example, poly can +overlap pcontact without violating the above rules, but +poly may not overlap diffusion because the result is efet, which +is neither poly nor diffusion. The only {\bfseries no{\_}overlap} rules +you should need to specify are rules to keep transistors from +overlapping other transistors of the same type. + +\subsection{Background checker step size} + +Magic's background design-rule checker breaks large cells up into +smaller pieces, checking each piece independently. For very large +designs, the number of pieces can get to be enormous. +If designs are large but sparse, the performance of the design-rule +checker can be improved tremendously by telling it to use a larger +step size for breaking up cells. This is done as follows: + +\starti + \ii {\bfseries stepsize} {\itshape stepsize} +\endi + +which causes each cell to be processed in square pieces +of at most {\itshape stepsize} by {\itshape stepsize} units. +It is generally a good idea to pick a large {\itshape stepsize}, but +one that is small enough so each piece will contain no more than +100 to 1000 rectangles. + +Note that the distances declared in the DRC section are used to determine +the ``halo'' of possible interactions around a tile edge. Magic must +consider all paint in all cells simultaneously; thus for each edge in +the design, magic must flatten the hierarchy around it to a distance +equal to the interaction halo. Clearly this has a huge impact on +processing time. Because the DRC is interactive, the performance hit +can be noticeable to downright irritating. Often this performance hit +can be greatly reduced by removing rules with large distance measures, +such as rules involving distances to pads, and widespacing rules. +If this is a problem, consider using one technology file for layout, +and one which can be used ``offline'' to do a slow, non-interactive +DRC check for pad and widespacing rules on an entire project layout. + +\section{Extract section} + +The {\bfseries extract} section of a technology file contains the parameters +used by Magic's circuit extractor. +Each line in this section begins +with a keyword that determines the interpretation of the remainder of +the line. +Table~\ref{extract} gives an example {\bfseries extract} section. + +\begin{table}[ht!p] + \begin{center} + \begin{tabular}{|ll|} \hline + {\bfseries extract} & \\ + style & lambda=0.7 \\ + lambda & 70 \\ + step & 100 \\ + sidehalo & 4 \\ \vns + & \\ + resist & poly,pfet,nfet 60000 \\ + resist & pc/a 50000 \\ + resist & pdiff,ppd 120000 \\ + resist & ndiff,nnd 120000 \\ + resist & m2contact/m1 1200 \\ + resist & metal1 200 \\ + resist & metal2,pad/m1 60 \\ + resist & ppc/a,pdc/a 100000 \\ + resist & nnc/a,ndc/a 100000 \\ + resist & nwell,pwell 3000000 \\ \vns + & \\ + areacap & poly 33 \\ + areacap & metal1 17 \\ + areacap & metal2,pad/m1 11 \\ + areacap & ndiff,nsd 350 \\ + areacap & pdiff,psd 200 \\ + areacap & ndc/a,nsc/a 367 \\ + areacap & pdc/a,psc/a 217 \\ + areacap & pcontact/a 50 \\ \vns + & \\ + perimc & allMetal1 space 56 \\ + perimc & allMetal2 space 55 \\ \vns + & \\ + overlap & metal1 pdiff,ndiff,psd,nsd 33 \\ + overlap & metal2 pdiff,ndiff,psd,nsd 17 metal1 \\ + overlap & metal1 poly 33 \\ + overlap & metal2 poly 17 metal1 \\ + overlap & metal2 metal1 33 \\ \vns + & \\ + sideoverlap & allMetal1 space allDiff 64 \\ + sideoverlap & allMetal2 space allDiff 60 \\ + sideoverlap & allMetal1 space poly 64 \\ + sideoverlap & allMetal2 space poly 60 \\ + sideoverlap & allMetal2 space allMetal1 70 \\ \vns + & \\ + fet & pfet pdiff,pdc/a 2 pfet Vdd! nwell 0 0 \\ + fet & nfet ndiff,ndc/a 2 nfet GND! pwell 0 0 \\ + {\bfseries end} & \\ \hline + \end{tabular} + \caption{{\bfseries Extract} section.} + \label{extract} + \end{center} +\end{table} + +This section is like the {\bfseries cifinput} and {\bfseries cifoutput} sections +in that it supports multiple extraction styles. Each style is +preceded by a line of the form + +\starti + \ii {\bfseries style} {\itshape stylename} +\endi + +All subsequent lines up to the next {\bfseries style} line or the end +of the section are interpreted as belonging to extraction style +{\itshape stylename}. +If there is no initial {\bfseries style} line, the first +style will be named ``default''. + +The keywords {\bfseries areacap}, {\bfseries perimcap}, +and {\bfseries resist} define the capacitance to substrate +and the sheet resistivity of each of the Magic layers in a layout. +All capacitances that appear in the {\bfseries extract} section are +specified as an integral number of attofarads (per unit area or perimeter), +and all resistances as an integral number of milliohms per square. + +The {\bfseries areacap} keyword is followed by a list of types +and a capacitance to substrate, as follows: + +\starti + \ii {\bfseries areacap} {\itshape types} {\itshape C} +\endi + +Each of the types listed in {\itshape types} has a capacitance to substrate +of {\itshape C} attofarads per square lambda. +Each type can appear in at most one {\bfseries areacap} line. +If a type does not appear in any {\bfseries areacap} line, +it is considered to have zero +capacitance to substrate per unit area. +Since most analysis tools compute transistor gate capacitance directly +from the area of the transistor's gate, Magic should produce node +capacitances that do not include gate capacitances. To ensure +this, all transistors should have zero {\bfseries areacap} values. + +The {\bfseries perimcap} keyword is followed by two type-lists +and a capacitance to substrate, as follows: + +\starti + \ii {\bfseries perimcap} {\itshape intypes} {\itshape outtypes} {\itshape C} +\endi + +Each edge that has one of the types in {\itshape intypes} +on its inside, and one of the types in {\itshape outtypes} on its outside, +has a capacitance to substrate of {\itshape C} attofarads per lambda. +This can also be used as an approximation of the effects due +to the sidewalls of diffused areas. +As for {\bfseries areacap}, each unique combination of an {\itshape intype} +and an {\itshape outtype} may appear at most once in a {\bfseries perimcap} line. +Also as for {\bfseries areacap}, if a combination of {\itshape intype} and +{\itshape outtype} does not appear in any {\bfseries perimcap} line, its +perimeter capacitance per unit length is zero. + +The {\bfseries resist} keyword is followed by a type-list +and a resistance as follows: + +\starti + \ii {\bfseries resist} {\itshape types} {\itshape R} +\endi + +The sheet resistivity of each of the types in {\itshape types} is +{\itshape R} milliohms per square. + +Each {\bfseries resist} line in fact defines a ``resistance class''. +When the extractor outputs the area and perimeter of nodes in +the {\bfseries .ext} file, it does so for each resistance class. +Normally, each resistance class consists of all types with +the same resistance. +However, if you wish to obtain the perimeter and area of each +type separately in the {\bfseries .ext} file, you should make each +into its own resistance class by using a separate {\bfseries resist} +line for each type. + +In addition to sheet resistivities, there are two other ways +of specifying resistances. Neither is used by the normal +Magic extractor, but both are used by the resistance extractor. +Contacts have a resistance that is inversely proportional to +the number of via holes in the contact, which is proportional +(albeit with quantization) to the area of the contact. The +{\bfseries contact} keyword allows the resistance for a single +via hole to be specified: + +\starti + \ii {\bfseries contact} {\itshape types size R} \\ + \ii {\bfseries contact} {\itshape types size border separation R} +\endi + +where {\itshape types} is a comma-separated list of types, {\itshape size} +is in lambda, and {\itshape R} is in milliohms. {\itshape Size} is interpreted +as a hole-size quantum; the number of holes in a contact is equal to +its width divided by {\itshape size} times its length divided by {\itshape size}, +with both quotients rounded down to the nearest integer. The resistance +of a contact is {\itshape R} divided by the number of holes. + +Note that the {\itshape size} alone may not compute the same number of +contact cuts as would be generated by the {\itshape cifoutput} command, +since it has no understaning of border and separation, and therefore may +compute an incorrect contact resistance. To avoid this problem, the +second form provides a way to give values for {\itshape border} and +{\itshape separation}, again in units of lambda. There is no automatic +check to guarantee that the extract and cifoutput sections agree on the +number of contact cuts for a given contact area. + +Transistors also have resistance information associated with them. +However, a transistor's resistance may vary depending on a number +of variables, so a single parameter is generally insufficient to +describe it. The {\bfseries fetresist} line allows sheet resistivities +to be given for a variety of different configurations: + +\starti + \ii {\bfseries fetresist} {\itshape fettypes region R} +\endi + +where {\itshape fettypes} is a comma-separated list of transistor types +(as defined in {\bfseries fet} lines below), {\itshape region} is a string +used to distinguish between resistance values for a fet if more +than one is provided (the special {\itshape region} value of ``{\bfseries linear}'' +is required for the resistance extractor), and {\itshape R} is the on-resistance +of the transistor in ohms per square ({\itshape not} milliohms; there would +otherwise be too many zeroes). + +Magic also extracts internodal coupling capacitances, as +illustrated in Figure~\ref{capextract}. +The keywords +{\bfseries overlap}, {\bfseries sidewall}, {\bfseries sideoverlap}, +and {\bfseries sidehalo} provide the parameters needed to do this. + +Overlap capacitance is between pairs of tile types, +and is described by the {\bfseries overlap} keyword as follows: + +\starti + \ii {\bfseries overlap} {\itshape toptypes bottomtypes cap} [{\itshape shieldtypes}] +\endi + +where {\itshape toptypes}, {\itshape bottomtypes}, and optionally +{\itshape shieldtypes} are type-lists and {\itshape cap} +is a capacitance in attofarads per square lambda. +The extractor searches for tiles whose types are in {\itshape toptypes} +that overlap tiles whose types are in {\itshape bottomtypes}, and +that belong to different electrical nodes. +(The planes of {\itshape toptypes} and {\itshape bottomtypes} must be disjoint). +When such an overlap is found, the capacitance to substrate +of the node of the tile in {\itshape toptypes} is deducted for the +area of the overlap, +and replaced by a capacitance to the node of the tile in {\itshape bottomtypes}. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tut8.4.ps, width=0.6\columnwidth} + \caption{Magic extracts three kinds of internodal coupling + capacitance. This figure is a side view of a set of masks that shows + all three kinds of capacitance. {\itshape Overlap} capacitance is + parallel-plate capacitance between two different kinds of material + when they overlap. {\itshape Parallel wire} capacitance is + fringing-field capacitance between the parallel vertical edges + of two pieces of material. {\itshape Sidewall overlap} capacitance + is fringing-field capacitance between the vertical edge of one piece + of material and the horizontal surface of another piece of material + that overlaps the vertical edge.} + \label{capextract} + \end{center} +\end{figure} + +If {\itshape shieldtypes} are specified, overlaps between {\itshape toptypes} +and {\itshape bottomtypes} that also overlap a type in {\itshape shieldtypes} +are not counted. +The types in {\itshape shieldtypes} must appear on a different plane +(or planes) than any of the types in {\itshape toptypes} or {\itshape bottomtypes}. + +\begin{figure}[ht!] + \begin{center} + \epsfig{file=../psfigures/maint2.11.ps, width=0.33\columnwidth} + \caption{Parallel wire capacitance is between pairs of edges. + The capacitance applies between the tiles {\itshape tinside} + and {\itshape tfar} above, where {\itshape tinside}'s type is + one of {\itshape intypes}, and {\itshape tfar}'s type is + one of {\itshape fartypes}.} + \label{wirecap} + \end{center} +\end{figure} + +Parallel wire capacitance is between pairs of edges, and +is described by the {\bfseries sidewall} keyword: + +\starti + \ii {\bfseries sidewall} {\itshape intypes outtypes neartypes fartypes cap} +\endi + +where {\itshape intypes}, {\itshape outtypes}, {\itshape neartypes}, +and {\itshape fartypes} are all type-lists, described in +Figure~\ref{wirecap}. {\itshape Cap} is half the capacitance +in attofarads per lambda when the edges are 1 lambda apart. +Parallel wire coupling capacitance is computed as being +inversely proportional to the +distance between two edges: at 2 lambda separation, it is equal +to the value {\itshape cap}; at 4 lambda separation, it is half of {\itshape cap}. +This approximation is not very good, in that it tends to overestimate +the coupling capacitance between wires that are farther apart. + +To reduce the amount of searching done by Magic, there is a +threshold distance beyond which the effects of parallel wire +coupling capacitance are ignored. +This is set as follows: + +\starti + \ii {\bfseries sidehalo} {\itshape distance} +\endi + +where {\itshape distance} is the maximum distance between two edges +at which Magic considers them to have parallel wire coupling capacitance. +{\bfseries If this number is not set explicitly in the technology file, +it defaults to 0, with the result that no parallel wire +coupling capacitance is computed.} + +Sidewall overlap capacitance is between material on the inside +of an edge and overlapping material of a different type. +It is described by the {\bfseries sideoverlap} keyword: + +\starti + \ii {\bfseries sideoverlap} {\itshape intypes outtypes ovtypes cap} +\endi + +where {\itshape intypes}, {\itshape outtypes}, and {\itshape ovtypes} are type-lists +and {\itshape cap} is capacitance in attofarads per lambda. +This is the capacitance associated with an edge with a type +in {\itshape intypes} on its inside and a type in {\itshape outtypes} on +its outside, that overlaps a tile whose type is in {\itshape ovtypes}. +See Figure~\ref{capextract}. + +Devices are represented in Magic by explicit tile types. +The extraction of a device is determined by the declared device type +and the information about types which comprise the various +independent {\itshape terminals} of the device. + +\starti + \ii {\bfseries device mosfet} {\itshape model gate\_types sd\_types + subs\_types subs\_node\_name} {\bk} \\ + \ii\> [{\itshape perim\_cap} [{\itshape area\_cap}]] \\ + \ii {\bfseries device capacitor} {\itshape model top\_types bottom\_types} + [{\itshape perim\_cap}] {\itshape area\_cap} \\ + \ii {\bfseries device resistor} {\itshape model resist\_types term\_types} \\ + \ii {\bfseries device bjt} {\itshape model base\_types emitter\_types + collector\_types} \\ + \ii {\bfseries device diode} {\itshape model pos\_types neg\_types} \\ + \ii {\bfseries device subcircuit} {\itshape model gate\_types} + [{\itshape term\_types} [{\itshape subs\_types}]] \\ + \ii {\bfseries device rsubcircuit} {\itshape model id\_types term\_types} +\endi + +Arguments are as follows: + +\begin{itemize} + \item {\itshape model} The SPICE model name of the device. In the case of + a subcircuit, it is the subcircuit name. For resistor and capacitor + devices for which a simple, unmodeled device type is needed, the + {\itshape model} can be the keyword {\bfseries None}. + \item {\itshape gate\_types} Layer types that form the gate region of a + MOSFET transistor. + \item {\itshape sd\_types} Layer types that form the source and drain + regions of a MOSFET transistor. Currently there is no way to specify + a device with asymmetric source and drain. + \item {\itshape subs\_types} Layer types that form the bulk (well or + substrate) region under the device. This can be the keyword + {\itshape None} for a device such as an nFET that has no identifiable + substrate layer type (``space'' cannot be used as a layer type here). + \item {\itshape top\_types} Layer types that form the top plate of a + capacitor. + \item {\itshape bottom\_types} Layer types that form the bottom plate of + a capacitor. + \item {\itshape resist\_types} Layer types that represent the primary + characterized resistive portion of a resistor device. + \item {\itshape term\_types} Layer types that represent the ends of a + resistor. Normally this is a contact type, but in the case of + silicide block or high-resistance implants, it may be normal salicided + polysilicon or diffusion. + \item {\itshape base\_types} Layer types that represent the base region + of a bipolar junction transistor. + \item {\itshape emitter\_types} Layer types that represent the emitter + region of a bipolar junction transistor. + \item {\itshape collector\_types} Layer types that represent the collector + region of a bipolar junction transistor. + \item {\itshape pos\_types} Layer types that represent the positive (anode) + terminal of a diode or P-N junction. + \item {\itshape neg\_types} Layer types that represent the negative (cathode) + terminal of a diode or P-N junction. + \item {\itshape id\_types} Identifier layers that identify a specific + resistor type. + \item {\itshape subs\_node\_name} The default name of a substrate node in + cases where a 4-terminal MOSFET device is missing an identifiable + bulk terminal, or when the {\itshape subs\_type} is the keyword + {\bfseries None}. + \item {\itshape perim\_cap} A value for perimeter capacitance in units of + attoFarads per lambda + \item {\itshape area\_cap} A value for area capacitance in units of + attoFarads per lambda squared. +\end{itemize} + +The {\itshape subs\_node\_name} can be a Tcl variable name (beginning with ``\$'') +in the Tcl-based version of magic. Thus, instead of hard-coding a global net +name into the general-purpose, project-independent technology file, the +technology file can contain a default global power and ground net variable, +normally {\bfseries \$VDD} and {\bfseries \$VSS}. Each project should then +set these variables (in the {\ttfamily .magicrc} file, for example) to the +correct value for the project's default global power and ground networks. + +SPICE has two formats for resistors and capacitors: one uses a model, and +the other does not. The model implies a semiconductor resistor or +capacitor, and takes a length and width value. The resistivity or +capacitance per unit area of the devices is assumed to be declared in +the model, so these values are not generated as part of the SPICE +netlist output. + +Magic technology file formats 27 and earlier only understood one device +type, the FET transistor. The extraction of a fet (with gate, sources, and +drains) from a collection of transistor tiles is governed by the +information in a {\bfseries fet} line. This keyword and syntax is +retained for backward compatibility. This line has the following +format: + +\starti + \ii {\bfseries fet} {\itshape types dtypes min-nterms name snode } + [{\itshape stypes}]{\itshape gscap gccap} +\endi + +{\itshape Types} is a list of those tiletypes that +make up this type of transistor. Normally, there will be only +one type in this list, since Magic usually represents each +type of transistor with a different tiletype. + +{\itshape Dtypes} is a list of those tiletypes +that connect to the diffusion terminals of the fet. +Each transistor of this type must have at least {\itshape min-nterms} +distinct diffusion terminals; otherwise, the extractor will +generate an error message. +For example, an {\bfseries efet} in the scmos technology must have +a source and drain in addition to its gate; {\itshape min-nterms} +for this type of fet is 2. +The tiletypes connecting to the gate of the fet are the same +as those specified in the {\bfseries connect} section as connecting +to the fet tiletype itself. + +{\itshape Name} is a string used to identify this type of transistor +to simulation programs. + +The substrate terminal of a transistor is determined in one +of two ways. +If {\itshape stypes} +(a comma-separated list of tile types) is given, and +a particular transistor overlaps one of those types, +the substrate terminal will be connected to the node +of the overlapped material. +Otherwise, the substrate terminal will be connected +to the node with the global name of {\itshape snode} +(which {\itshape must} be a global name, i.e., end in +an exclamation point). + +{\itshape Gscap} is the capacitance between the transistor's gate +and its diffusion terminals, in attofarads per lambda. +Finally, {\itshape gccap} is the capacitance between the gate +and the channel, in attofarads per square lambda. +Currently, {\itshape gscap} and {\itshape gccap} are unused by the extractor. + +In technology format 27 files, devices such as resistors, capacitors, +and bipolar junction transistors could be extracted by treating them +like FETs, using a ``{\bfseries fet}'' line in the extract file, and +assigning the terminal classes (somewhat arbitrarily) to the FET +terminal classes gate, source/drain, and bulk. Resistors are rather +cumbersome using this method, because the ``gate'' terminal maps to +nothing physical, and a dummy layer must be drawn. The ``ext2spice'' +command generates an ``M'' spice record for all devices declared with +a {\bfseries fet} line, so an output SPICE deck must be post-processed +to produce the correct SPICE devices for simulation. One important +other difference between the older form and the newer is the ability +of the ``{\bfseries device}'' records to handle devices with bends or +other irregular geometry, including annular (ring-shaped) FETs. + +Often the units in the extracted circuit for a cell will always +be multiples of certain basic units larger than centimicrons +for distance, attofarads for capacitance, or milliohms for resistance. +To allow larger units to be used in the {\bfseries .ext} file for this +technology, thereby reducing the file's size, +the {\bfseries extract} section may specify a scale +for any of the three units, as follows: + +\starti + \ii {\bfseries cscale} {\itshape c} \\ + \ii {\bfseries lambda} {\itshape l} \\ + \ii {\bfseries rscale} {\itshape r} +\endi + +In the above, {\itshape c} is the number of attofarads per unit capacitance +appearing in the {\bfseries .ext} files, {\itshape l} is the number of centimicrons +per unit length, and {\itshape r} is the number of milliohms per unit +resistance. All three must be integers; +{\itshape r} should divide evenly all the resistance-per-square values +specified as part of {\bfseries resist} lines, +and {\itshape c} should divide evenly all the capacitance-per-unit values. + +Magic's extractor breaks up large cells into chunks +for hierarchical extraction, to avoid having to process too +much of a cell all at once and possibly run out of memory. +The size of these chunks is determined by the {\bfseries step} +keyword: + +\starti + \ii {\bfseries step} {\itshape step} +\endi + +This specifies that chunks of {\itshape step} units by {\itshape step} units +will be processed during hierarchical extraction. The default +is {\bfseries 100} units. +Be careful about changing {\itshape step}; if it is too small then +the overhead of hierarchical processing will increase, and if +it is too large then more area will be processed during +hierarchical extraction than necessary. +It should rarely be necessary to change {\itshape step} unless the +minimum feature size changes dramatically; if so, a value of about +50 times the minimum feature size appears to work fairly well. + +Magic has the capability to generate a geometry-only extraction of a +network, useful for 3-D simulations of electric fields necessary to +rigorously determine inductance and capacitance. When this feature +is used, it is necessary for the field-equation solver to know the +vertical stackup of the layout. The extract section takes care of +this by allowing each magic layer to be given a definition of +height and thickness of the fabricated layer type: + +\starti + \ii {\bfseries height} {\itshape layers height thickness} +\endi + +where {\itshape layers} is a comma-separated list of magic layers +sharing the same height and thickness, and {\itshape height} and +{\itshape thickness} are floating-point numbers giving the height +of the bottom of the layer above the substrate, and the thickness +of the layer, respectively, in units of lambda. + +\section{Wiring section} + +The {\bfseries wiring} section provides information used by the +{\bfseries :wire switch} command to generate contacts. +See Table~\ref{wiring} for the {\bfseries wiring} section from the scmos +technology file. Each line in the section has the syntax + +\starti + \ii {\bfseries contact} {\itshape type minSize layer1 surround1 layer2 surround2} \\ +\endi + +{\itshape Type} is the name of a contact layer, and {\itshape layer1} and +{\itshape layer2} +are the two wiring layers that it connects. {\itshape MinSize} is the +minimum size of contacts of this type. If {\itshape Surround1} is non-zero, +then additional material of type {\itshape layer1} will be painted for +{\itshape surround1} units around contacts of {\itshape type}. If {\itshape surround2} +is non-zero, it indicates an overlap distance for {\itshape layer2}. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|lllllll|} \hline + {\bfseries wiring} &&&&&& \\ + {\bfseries contact} & pdcontact & 4 & metal1 & 0 & pdiff & 0 \\ + {\bfseries contact} & ndcontact & 4 & metal1 & 0 & ndiff & 0 \\ + {\bfseries contact} & pcontact & 4 & metal1 & 0 & poly & 0 \\ + {\bfseries contact} & m2contact & 4 & metal1 & 0 & metal2 & 0 \\ + {\bfseries end} &&&&&& \\ \hline + \end{tabular} + \caption{{\bfseries Wiring} section} + \label{wiring} + \end{center} +\end{table} + +During {\bfseries :wire switch} commands, Magic scans the wiring information +to find a contact whose {\itshape layer1} and {\itshape layer2} correspond to the +previous and desired new wiring materials (or vice versa). +If a match is found, a contact is generated according to {\itshape type}, +{\itshape minSize}, {\itshape surround1}, and {\itshape surround2}. + +\section{Router section} + +The {\bfseries router} section of a technology file provides information +used to guide the automatic routing tools. The section contains four +lines. See Table~\ref{router} for an example {\bfseries router} section. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|lllllll|} \hline + {\bfseries router} &&&&&& \\ + {\bfseries layer1} & metal1 & 3 & allMetal1 & 3 && \\ + {\bfseries layer2} & metal2 & 3 & allMetal2 & 4 & allPoly,allDiff & 1 \\ + {\bfseries contacts} & m2contact & 4 &&&& \\ + {\bfseries gridspacing} & 8 &&&& \\ + {\bfseries end} &&&&&& \\ \hline + \end{tabular} + \caption{{\bfseries Router} section} + \label{router} + \end{center} +\end{table} + +The first two lines have the keywords {\bfseries layer1} and {\bfseries layer2} +and the following format: + +\starti + \ii {\bfseries layer1} {\itshape wireType wireWidth type-list distance + type-list distance} \dots +\endi + +They define the two layers used for routing. After the {\bfseries layer1} +or {\bfseries layer2} keyword are two fields giving the name of the material +to be used for routing that layer and the width to use for its wires. +The remaining fields are used by Magic to avoid routing over existing +material in the channels. Each pair of fields contains a list of +types and a distance. The distance indicates how far away the given +types must be from routing on that layer. Layer1 and layer2 +are not symmetrical: wherever possible, Magic will try to +route on layer1 in preference to layer2. Thus, in a single-metal +process, metal should always be used for layer1. + +The third line provides information about contacts. It has the format + +\starti + \ii {\bfseries contacts} {\itshape contactType size } + [{\itshape surround1 surround2}] +\endi + +The tile type {\itshape contactType} +will be used to make contacts between layer1 and layer2. Contacts +will be {\itshape size} units square. In order to avoid placing contacts +too close to hand-routed material, Magic assumes that both the layer1 +and layer2 rules will apply to contacts. If {\itshape surround1} and +{\itshape surround2} are present, they specify overlap distances around +contacts for layer1 and layer2: additional layer1 material will be +painted for {\itshape surround1} units around each contact, and additional +layer2 material will be painted for {\itshape surround2} units around +contacts. + +The last line of the {\bfseries routing} section indicates the size of +the grid on which to route. It has the format + +\starti + \ii {\bfseries gridspacing} {\itshape distance} +\endi + +The {\itshape distance} must be chosen large enough that +contacts and/or wires on adjacent grid lines will not generate +any design rule violations. + +\section{Plowing section} + +The {\bfseries plowing} section of a technology file identifies those types +of tiles whose sizes and shapes should not be changed as a result of plowing. +Typically, these types will be transistors and buried contacts. +The section currently contains three kinds of lines: + +\starti + \ii {\bfseries fixed} {\itshape types} \\ + \ii {\bfseries covered} {\itshape types} \\ + \ii {\bfseries drag} {\itshape types} +\endi + +where {\itshape types} is a type-list. +Table~\ref{plowing} gives this section for the scmos technology file. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|ll|} \hline + {\bfseries plowing} & \\ + {\bfseries fixed} & pfet,nfet,glass,pad \\ + {\bfseries covered} & pfet,nfet \\ + {\bfseries drag} & pfet,nfet \\ + {\bfseries end} & \\ \hline + \end{tabular} + \caption{{\bfseries Plowing} section} + \label{plowing} + \end{center} +\end{table} + +In a {\bfseries fixed} line, +each of {\itshape types} is considered to be fixed-size; +regions consisting of tiles of these types are not deformed by plowing. +Contact types are always considered to be fixed-size, so need not +be included in {\itshape types}. + +In a {\bfseries covered} line, +each of {\itshape types} will remain ``covered'' by plowing. +If a face of a covered type is covered with a given type +before plowing, it will remain so afterwards. +For example, if a face of a transistor is covered by diffusion, +the diffusion won't be allowed to slide along the transistor +and expose the channel to empty space. +Usually, you should make all fixed-width types covered +as well, except for contacts. + +In a {\bfseries drag} line, +whenever material of a type in {\itshape types} moves, it will drag +with it any minimum-width material on its trailing side. This +can be used, for example, to insure that when a transistor moves, +the poly-overlap forming its gate gets dragged along in its entirety, +instead of becoming elongated. + +\section{Plot section} + +The {\bfseries plot} section of the technology file contains information +used by Magic to generate hardcopy plots of layouts. Plots can +be generated in different styles, which correspond to different +printing mechanisms. For each style of printing, there is a separate +subsection within the {\bfseries plot} section. Each subsection is +preceded by a line of the form + +\starti + \ii {\bfseries style} {\itshape styleName} +\endi + +Magic version 6.5 and earlier supported {\bfseries gremlin}, +{\bfseries versatec}, and {\bfseries colorversatec} styles. As these +are thoroughly obsolete, versions 7 and above instead implement +two formats {\bfseries postscript} and {\bfseries pnm}. Generally, +the {\bfseries pnm} format is best for printouts of entire chips, and +the {\bfseries postscript} format is best for small cells. The +PostScript output includes labels, whereas the PNM output does not. +The PostScript output is vector-drawn with stipple fills, whereas the +PNM output is pixel-drawn, with antialiasing. Small areas of layout +tend to look artificially pixellated in the PNM format, while large +areas look almost photographic. The PostScript output is a perfect +rendering of the Magic layout, but the files become very large and +take long spans of time to render for large areas of layout. + +%-------------------------------------------------- + +\begin{table}[p] + \renewcommand{\baselinestretch}{0.9} + \normalsize + \begin{center} + \begin{tabular}{|llll|} \hline + {\bfseries plot} &&& \\ + {\bfseries style} & {\bfseries postscript} && \\ + +& 5 & \multicolumn{2}{l|}{FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF \dots} \\ +& 7 & \multicolumn{2}{l|}{18181818 30303030 60606060 C0C0C0C0 \dots} \\ +& 9 & \multicolumn{2}{l|}{18181818 3C3C3C3C 3C3C3C3C 18181818 \dots} \\ +& 10 & \multicolumn{2}{l|}{F0F0F0F0 60606060 06060606 0F0F0F0F \dots} \\ +& 13 & \multicolumn{2}{l|}{00000000 00000000 33333333 33333333 \dots} \\ +&&& \\ +& 1 & 47 95 111 0 & \\ +& 9 & 223 47 223 0 & \\ +& 10 & 0 255 255 0 & \\ +& 12 & 191 127 0 0 & \\ +& 13 & 95 223 63 0 & \\ +& 14 & 0 0 0 255 & \\ +& 16 & 111 151 244 0 & \\ +& 17 & 23 175 183 0 & \\ +&&& \\ +& \multicolumn{2}{l}{pc,ndc,pdc,psc,nsc} & 14 X \\ +& m2c && 14 B \\ +& m2c && 14 13 \\ +& m2,m2c && 13 10 \\ +& \multicolumn{2}{l}{pdc,ndc,psc,nsc,pc,m1,m2c} & 12 9 \\ +& poly,pc && 10 5 \\ +& nfet && 9 7 \\ +& nfet && 16 5 \\ +& pfet && 1 7 \\ +& pfet && 17 5 \\ +& pdiff,pdc && 1 5 \\ +& ndiff,ndc && 9 5 \\ +&&& \\ + {\bfseries style} & {\bfseries pnm} && \\ +& draw & metal1 & \\ +& draw & metal2 & \\ +& draw & polysilicon & \\ +& draw & ndiffusion & \\ +& draw & pdiffusion & \\ +& draw & ntransistor & \\ +& draw & ptransistor & \\ +& map & psubstratepdiff pdiffusion & \\ +& map & nsubstratendiff ndiffusion & \\ +& map & polycontact polysilicon metal1 & \\ +& map & m2contact metal1 metal2 & \\ +& map & ndcontact ndiffusion metal1 & \\ +& map & pdcontact pdiffusion metal1 & \\ + + {\bfseries end} &&& \\ \hline + \end{tabular} + \caption{Sample {\bfseries plot} section (for an SCMOS process). PostScript + stipple patterns have been truncated due to space limitations.} + \end{center} + \renewcommand{\baselinestretch}{1.0} +\end{table} + +The {\bfseries postscript} style requires three separate sections. The +first section defines the stipple patterns used: + +\starti + \ii {\itshape index} {\itshape pattern-bytes}\dots +\endi + +The {\itshape index} values are arbitrary but must be a positive integer and +must be unique to each line. The indices will be referenced in the third +section. The {\itshape pattern-bytes} are always exactly 8 sets of 8-digit +hexidecimal numbers (4 bytes) representing a total of 16 bits by 16 lines of +pattern data. If a solid color is intended, then it is necessary to declare +a stipple pattern of all ones. The actual PostScript output will implement +a solid color, not a stipple pattern, for considerably faster rendering. + +The second section defines the colors used in standard printer CMYK notation +(Cyan, Magenta, Yellow, blacK): + +\starti + \ii {\itshape index C M Y K} +\endi + +Like the first section, each {\itshape index} must be a unique positive +integer, and the color values each range from 0 to 255. + +The third section assigns colors and stipple patterns to each style: + +\starti + \ii {\itshape type-list color-index stipple-index}\vbar + {\bfseries X}\vbar {\bfseries B} +\endi + +The {\itshape type-list} is a comma-separated list of magic layer types +that collectively use the same color and style. The {\itshape color-index} +refers to one of the colors defined in the second section, and the +{\itshape stipple-index} refers to one of the stipple patterns defined in +the first section. In addition to the stipple pattern indices, two characters +are recognized: {\bfseries B} declares that a border will be drawn around +the layer boundary, and {\bfseries X} declares that the layout boundary will +be printed over with a cross in the same manner as contact areas are drawn +in the Magic layout. + +To get a proper PostScript plot, it is necessary to have a properly defined +{\bfseries plot postscript} section in the technology file. Without such +a defined set, the {\bfseries plot postscript} command will generate blank +output. + +The {\bfseries pnm} style declarations are as follows: + +\starti + \ii {\bfseries draw} {\itshape magic-type} \\ + \ii {\bfseries map} {\itshape magic-type} {\itshape draw-type}\dots +\endi + +where both {\itshape magic-type} and {\itshape draw-type} represent +a magic layer name. The {\bfseries draw} command states that a specific +magic type will be output exactly as drawn on the layout. The {\bfseries +map} statement declares that a specific magic type will be drawn as +being composed of other layers declared as {\bfseries draw} types. +The colors of the {\bfseries draw} types will be blended to generate +the mapped layer color. Colors are defined by the style set used for +layout and defined in the {\bfseries styles} section of the technology +file. Stipple patterns, borders, and cross-hatches used by those styles +are ignored. When multiple styles are used for a layer type, the PNM +output blends the base color of each of those styles. Thus, contact +areas by default tend to show up completely black, as the ``X'' pattern +is usually defined as black, and black blended with other colors +remains black. This is why the above example re-defines all of the +contact types as mapped type blends. Contact cuts are not represented, +which is generally desired if the plot being made represents a large +area of layout. + +Unlike the PostScript section, the PNM plot section does {\itshape not} +have to be declared. Magic will set up a default style for PNM plots +that matches (more or less) the colors of the layout as specified by +the {\bfseries styles} section of the technology file. The {\bfseries +plot pnm} section can be used to tweak this default setup. Normally +this is not necessary. The default setup is helpful in that it allows +the {\bfseries plot pnm} command to be used with all technology files, +including those written before the {\itshape plot pnm} command option +was implemented. + +\section{Conditionals, File Inclusions, and Macro Definitions} + +The ``raw'' technology files in the {\bfseries scmos} subdirectory of +the Magic distribution were written for a C preprocessor and cannot be +read directly by Magic. The C preprocessor must first be used +to eliminate comments and expand macros in a technology file before it gets +installed, which is done during the ``{\bfseries make install}'' step when +compiling and installing Magic from source. +Macro definitions can be made with the preprocessor {\bfseries \#define} +statement, and ``conditional compilation'' can be specified using +{\bfseries \#ifdef}. Also, the technology file can be split into parts +using the {\bfseries \#include} statement to read in different parts +of the files. +However, this has for the most part proven to be a poor method for +maintaining technology files. End-users often end up making modifications +to the technology files for one purpose or another. They should not +need to be making changes to the source code distribution, they often +do not have write access to the source distribution, and furthermore, +the elimination of comments and macros from the file makes the actual +technology file used difficult to read and understand. + +Technology file formats more recent that 27 include several built-in +mechanisms that take the place of preprocessor statements, and allow +the technology file source to be directly edited without the need to +re-process. This includes the {\bfseries include} statement, which may +be used anywhere in the technology file, the {\bfseries alias} statement +in the {\bfseries types} section, and the {\bfseries variant} statement, +which may be used in the {\bfseries cifoutput}, {\bfseries cifinput}, +or {\bfseries extract} sections. The {\bfseries alias} statements +appear in the {\bfseries types} section, covered above. The {\bfseries +include} statement may appear anywhere in the file, and takes the form + +\starti + \ii {\bfseries include} {\itshape filename} +\endi + +Assuming that the included files exist in the search path Magic uses +for finding system files (see command {\bfseries path sys}), then no +absolute path needs to be speficied for {\itshape filename}. Note +that the file contents will be included verbatim; section names and +{\bfseries end} statements that appear in the included file should not +exist in the file that includes it, and vice versa. + +%--------------------------------------------------------------------- + +The most common use of ``\#ifdef'' preprocessor statements in the default +``scmos'' technology is to selectively define different cifoutput, +cifinput, and extract files for process variants. The result is that +these sections become quite large and repeat many definitions that are +common to all process variations. Technology file format 30 defines +the {\bfseries variants} option to the {\bfseries style} statement for +all three sections {\bfseries cifinput}, {\bfseries cifoutput}, and +{\bfseries extract}. This statment option takes the form: + +\starti + \ii {\bfseries style} {\itshape stylename} {\bfseries variants} {\itshape + variantname,\dots} +\endi + +where {\itshape stylename} is a base name used for all variants, and one +of the comma-separated list of {\itshape variantname}s is a suffix appended +to the {\itshape stylename} to get the actual name as it would be used in, +for example, a {\bfseries cif ostyle} command. For example, the statement + +\starti + \ii {\bfseries style scmos0.18 variants (p),(c),(pc),()} +\endi + +defines four similar styles named {\bfseries scmos0.18(p)}, +{\bfseries scmos0.18(c)}, {\bfseries scmos0.18(pc)}, and +{\bfseries scmos0.18()}. All of the variants are assumed to be +minor variations on the base style. Within each style description, +statements may apply to a single variant, a group of variants, or +all variants. After the {\bfseries style} statement has been +processed, all following lines are assumed to refer to all variants +of the base style until a {\bfseries variant} statment is encountered. +This statment takes the form: + +\starti + \ii {\bfseries variant} {\itshape variantname,\dots} +\endi + +to refer to one or more variants in a comma-separated list. All lines +following the {\bfseries variant} statment will apply only to the +specific process variants in the list, until another {\bfseries variant} +statement is encountered. The special character ``{\bfseries *}'' can +be used as a shorthand notation for specifying all process variants: + +\starti + \ii {\bfseries variant *} +\endi + +\end{document} diff --git a/doc/latexfiles/maint3.tex b/doc/latexfiles/maint3.tex new file mode 100644 index 00000000..a82481c2 --- /dev/null +++ b/doc/latexfiles/maint3.tex @@ -0,0 +1,275 @@ +%---------------------------------------------------------------------------- +% Magic Maintainer's Manual #3 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Maintainer's Manual \#3: Display Styles, Colormaps, and Glyphs} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Robert N. Mayo} \\ + {\itshape John Ousterhout} \\ + \vspace*{0.5in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> All of them. +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> {\itshape (None)} +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (None)} +\endi + +\vspace*{0.75in} +\section{Introduction} + +This document gives overall information about +the files that tell Magic how to display information +on the screen. There are three types of files that +contain display information: display styles files, +color-map files, and glyph files. + +\section{Display Styles} + +Display styles files describe how to draw rectangular areas +and text. A single file contains a large number of display +styles. Each display style contains two kinds of +information: a) how to modify pixels (which bits of +the pixel should be changed and what their new value(s) should +be); and b) which pixels to modify. Part b) consists of +things like ``fill the entire area,'' or ``modify only those +pixels in the area that are given by a particular stipple pattern,'' +or ``draw a dashed-line around the area's outline.'' +In the case of text, ``which pixels to modify'' is determined +by the font for the text, which is not part of the display +style, so the display style information for this is ignored. +See the manual page {\bfseries dstyle~(5)} for details on the format +of display styles files. + +Display styles are designed to take into account both the characteristics +of certain technologies and the characteristics of certain displays. +For example, a bipolar process may require information to be displayed +very differently than a MOS process, and a black-and-white display +will be used much differently than a color display. Thus there can +be many different display styles files, each corresponding to a particular +class of technologies and a class of displays. The names of styles +files reflect these classes: each display styles file has a name of +the form {\itshape x}{\bfseries .}{\itshape y}{\bfseries .dstyle}, +where {\itshape x} is the technology +class (given by the {\bfseries styletype} line in the {\bfseries styles} +section of the technology file), and {\itshape y} is the class of display. +Each display driver knows its display class; the driver initialization +routine sets an internal Magic variable with the display class to +use. Right now we have two display styles files: {\bfseries mos.7bit.dstyle} +and {\bfseries mos.bw.dstyle}. Both files contain enough different +styles to handle a variety of MOS processes, including both nMOS +and CMOS (hence the {\bfseries mos} field). {\bfseries Mos.7bit.dstyle} is +designed for color displays with at least seven bits of color per +pixel, while {\bfseries mos.bw.dstyle} is for black-and-white displays +(stipple patterns are used instead of colors). + +\section{Color Maps} + +The display styles file tells how to modify pixels, but this doesn't +completely specify the color that will be displayed on the screen +(unless the screen is black-and-white). For color displays, the +pixel values are used to index into a {\itshape color map}, which contains +the red, green, and blue intensity values to use for each pixel +value. The values for color maps are stored in color-map files +and can be edited using the color-map-editing window in Magic. +See {\bfseries cmap~(5)} for details on the format of color-map files. + +Each display styles file uses a separate color map. Unfortunately, +some monitors have slightly different phosphors than others; this +will result in different colors if the same intensity values are used +for them. To compensate for monitor differences, Magic +supports multiple color maps for each display style, depending on +the monitor being used. The monitor type can be specified with +the {\bfseries -m} command line switch to Magic, with {\bfseries std} +as the default. Color-map files have names +of the form {\itshape x}{\bfseries .}{\itshape y}{\bfseries .}{\itshape z} +{\bfseries .cmap}, where {\itshape x} and +{\itshape y} have the same meaning as for display styles and {\itshape z} is +the monitor type. Over the last few years monitor phosphors appear +to have standardized quite a bit, so almost all monitors now work +well with the {\bfseries std} monitor type. The color map {\bfseries mos.7bit.std.cmap} +is the standard one used at Berkeley. + +\section{Transparent and Opaque Layers} + +One of the key decisions in defining a set of display styles +for a color display is how to use the bits of a pixel (this section +doesn't apply to black-and-white displays). One option is to use +a separate bit of each pixel (called a {\itshape bit plane}) for each mask +layer. The advantage of this is that each possible combination of +layer overlaps results in a different pixel value, and hence +a different color (if you wish). Thus, for example, if metal +and poly are represented with different bit planes, poly-without-metal, +metal-without-poly, poly-and-metal, and neither-poly-nor-metal will +each cause a different value to be stored in the pixel. A different +color can be used to display each of these combinations. Typically, +the colors are chosen to present an illusion of transparency: the +poly-and-metal color is chosen to make it appear as if metal were +a transparent colored foil placed on top of poly. You can see this +effect if you paint polysilicon, metal1, and metal2 on top of each +other in our standard technologies. + +The problem with transparent layers is that they require many bits +per pixel. Most color displays don't have enough planes to use +a different one for each mask layer. Another option is to use +a group of planes together. For example, three bits of a pixel +can be used to store seven mask layers plus background, with +each mask layer corresponding to one of the combinations of +the three bits. The problem with this scheme is that there +is no way to represent overlaps: where there is an overlap, +one of the layers must be displayed at the expense of the +others. We call this scheme an {\itshape opaque} one since when it +is used it appears as if each layer is an opaque foil, with +the foils lying on top of each other in some priority order. +This makes it harder to see what's going on when there are +several mask layers in an area. + +The display styles files we've designed for Magic use a combination +of these techniques to get as much transparency as possible. +For example, our {\bfseries mos.7bit.dstyle} file uses three bits +of the pixel in an opaque scheme to represent polysilicon, +diffusion, and various combinations of them such as transistors. +Two additional bits are used, one each, for the two metal layers, +so they are transparent with respect to each other and the +poly-diff combinations. Thus, although only one poly-diff combination +can appear at each point, it's possible to see the overlaps between +each of these combinations and each combination of metal1 and metal2. +Furthermore, all of these styles are overridden if the +sixth bit of the pixel is set. In this case the low +order five bits no longer correspond to mask layers; they are +used for opaque layers for things like labels and cell bounding +boxes, and override any mask information. Thus, for example, +when metal1 is displayed it only affects one bit plane, but +when labels are displayed, the entire low-order six bits of the +pixel are modified. It's important that the opaque layers like +labels are drawn after the transparent things that they blot out; +this is guaranteed by giving them higher style numbers in +the display styles files. + +Finally, the seventh bit of the pixel is used for +highlights like the box and the selection. All 64 entries +in the color map corresponding to pixel values with this +bit set contain the same value, namely pure white. This makes +the highlights appear opaque with respect to everything +else. However, since they have their own bit plane which +is completely independent of anything else, they can be +drawn and erased without having to redraw any of the mask +information underneath. This is why the box can be moved +relatively quickly. On the other hand, if Magic erases +a label it must redraw all the mask information in the area +because the label shared pixel bits with the mask information. + +Thus, the scheme we've been using for Magic is a hierarchical +combination of transparent and opaque layers. This scheme is +defined almost entirely by the styles file, so you can try +other schemes if you wish. However, you're likely to have problems +if you try anything too radically different; we haven't tried +any schemes but the one currently being used so there are probably +some code dependencies on it. + +For more information on transparent and opaque layers, see +the paper ``The User Interface and Implementation of an IC Layout +Editor,'' which appeared in {\itshape IEEE Transactions on CAD} in +July 1984. + + +\section{Glyphs} + +Glyphs are small rectangular bit patterns that are used in two +places in Magic. The primary use for glyphs is for programmable +cursors, such as the shapes that show you which corner of the +box you're moving and the various tools described in Tutorial \#3. +Each programmable cursor is stored as a glyph describing the +pattern to be displayed in the cursor. The second use of glyphs +is by the window package: the little arrow icons appearing at the +ends of scroll bars are stored as glyphs, as is the zoom box in +the lower-left corner of the window. We may eventually use glyphs +in a menu interface (but don't hold your breath). + +Glyphs are stored in ASCII glyph files, each of which can hold +one or more glyph patterns. Each glyph is represented as a +pattern of characters representing the pixels in the glyph. +Each character selects a display style from the current +display styles file; the display style indicates the color to use for +that pixel. See the manual page {\bfseries glyphs~(5)} +for details on the syntax of glyphs files. + +The window glyphs are stored in files of the form +{\bfseries windows}{\itshape XX}{\bfseries .glyphs}. +The {\itshape XX} indicates how wide the glyphs are, and is set by the graphics +driver for a particular display. We started out with a {\bfseries windows7.glyphs} +and a {\bfseries windows11.glyphs}. Since then, display resolution has +increased greatly so we have also created a {\bfseries windows14.glyphs} and a +{\bfseries windows22.glyphs}. The positions of the various glyphs in +these files is important, and is defined in the {\bfseries window} module of +Magic. + +Programmable cursors are stored in files named +{\itshape x}{\bfseries .glyphs}, where {\itshape x} is determined by +the device driver +for the display. Displays capable of supporting full-color cursors +use {\bfseries color.glyphs}; displays that can only support monochrome +cursors used {\bfseries bw.glyphs}. The order of the various glyphs +in these files is important. It is defined by the files {\bfseries styles.h} +in the {\bfseries misc} module of Magic. + +\end{document} diff --git a/doc/latexfiles/maint4.tex b/doc/latexfiles/maint4.tex new file mode 100644 index 00000000..0a37af3f --- /dev/null +++ b/doc/latexfiles/maint4.tex @@ -0,0 +1,202 @@ +%---------------------------------------------------------------------------- +% Magic Maintainer's Manual number 4 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Maintainer's Manual \#4: Using Magic Under X Windows} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Don Stark} \\ + \vspace*{0.5in} + Computer Systems Laboratory \\ + Stanford University \\ + Stanford, CA 94305 \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> {\itshape (None)} +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (None)} +\endi +\section{Introduction} + +This document provides information on Magic's X drivers that may be of help +to system maintainers. + +\section{Compiling the Correct X Driver for your system.} + +Unfortunately, it is not possible to link with both the X10 and X11 +libraries, so you will have to compile Magic differently depending +on the version of X that you are running. + +\subsection{Compiling for X11} + +\begin{enumerate} +\item Add the flag -DX11 to misc/DFLAGS +\item Add -lX11 to magic/LIBS +\item Change the SRCS line in graphics/Makefile to \${BASE{\_}SRCS} \${X11{\_}SRCS} +\item Change the OBJS line to \${BASE{\_}OBJS} \${X11{\_}OBJS} +\item Change the POBJS line to \${BASE{\_}POBJS} \${X11{\_}POBJS} +\item Change the HELPER{\_}SRCS line \${X11HELPER{\_}SRCS} +\item Change the HELPER{\_}SRCS line \${X11HELPER{\_}PROG} +\item Compile the module graphics.o +\item Relink magic +\end{enumerate} + +\subsection{Compiling for X10} + +\begin{enumerate} +\item Add the flag -DX10 to misc/DFLAGS +\item Add -lX10 to magic/LIBS +\item Change the SRCS line in graphics/Makefile to \${BASE{\_}SRCS} \${X10{\_}SRCS} +\item Change the OBJS line to \${BASE{\_}SRCS} \${X10{\_}OBJS} +\item Change the POBJS line to \${BASE{\_}SRCS} \${X10{\_}POBJS} +\item Change the HELPER{\_}SRCS line \${X10HELPER{\_}SRCS} +\item Change the HELPER{\_}SRCS line \${X10HELPER{\_}PROG} +\item Compile the module graphics.o +\item Relink magic +\end{enumerate} + +\section{Troubleshooting the X Drivers} + +The following is a list of problems sometimes encountered in running Magic +under X and some suggestions about how to get around the problem. + +\subsection{X11 Driver} + +\begin{itemize} +\item Fonts \\ +We have tried to pick a set of fonts that most machines running +X11 Revision 3 will have, but there is nothing to guarantee that +a given machine will have a font. If you're getting "unable to load font" +messages, you will need to change the fonts that Magic uses. The simplest +way to do this is to specify them in your .Xdefaults file as described in +section 2.1. To change the default values that Magic uses, change the +"fontnames" array in the file grX11su3.c of the graphics module. +The program {\itshape xlsfonts} will tell you what fonts are available on your +machine. + +\item Strange Color Effects \\ +Magic often co-exists rather uneasily with +other X applications because it is picky about which colors it is allocated. +If possible, it tries to allocate the colors it requires out of the +display's default colormap because this perturbs other applications the least. +If this fails, however, Magic makes its own colormap. When this colormap +gets installed is a function of the window manager; most window managers +install it when the cursor is in the magic window. Unfortunately, there is +no way to guarantee that the window manager installs the magic colormap +correctly; if you get erratic colormap behavior, try using a lower number +of planes or reducing the number of colors that other applications use. + +\item +When magic's colormap is being used, other windows may change color, +possibly to some unusable combination such as black on black or white +on white. This problem can sometimes be ameliorated by changing the +constants X{\_}COLORMAP{\_}BASE and X{\_}COLORMAP{\_}RESERVED in grX11su2.c; +a more complete +description of what these constants do is included in that file. +Values for these constants that are incompatible with your machine +will sometimes generate Xerrors in XQueryColors. + +\item Failure to prompt user for window position \\ +Whether or not the +designer is prompted for a window's location is dependent on the window +manager. Certain window managers, notably {\itshape twm}, do not always +do this. +\end{itemize} + +\subsection{X10 Driver} + +In general, the Version 10 driver is less reliable than the X11 one. +If you have the choice, you are better off running under X11. + +\begin{itemize} +\item grX2.GrXSetCMap: Failed to get color cells \\ +Magic gives this +error when it can't get sufficient colors to run. This can be caused +by running Magic on a machine with an insufficient number of planes +(8 planes are generally required to run a 7 bit dstyles file), or by +having too many colors already used by other applications. Try +using only black and white xterms, xclocks, etc., and see if the problem +goes away. + +\item Couldn\'t get 7 planes; allocating by color \\ +Certain X10 servers, +most notably the VaxstationII-GPX, allocate colors in such a way that +Magic can never get the 7 color planes that it wants. When this +happens, Magic instead allocates 128 colors. This is better than nothing, +but not by much; strange colors often result when layers overlap. +\end{itemize} + +\section{Acknowledgments} + +Many people share the credit (and the blame) for the Magic X drivers. +The original X10 port was done by Mark Linton and Doug Pan at Stanford +University. Walter Scott and Eric Lunow of Lawrence Livermore +National Laboratories modified the driver and the windows module +so that magic windows act like normal X windows. Meanwhile, Dave Durfee and +Markus G. Wloka of Brown University improved the reliability of the Stanford +X10 driver and added support for a variable number of planes. Marco Papa +of USC converted the Brown X10 driver to X11. Concurrently, someone at +the University of Washington converted the Stanford X10 driver to X11. +The X11 driver in this distribution is predominantly a merge of the UW +driver with the multiwindow features of the LLNL driver. Some of the ideas +for supporting differing plane counts were borrowed from the USC/Brown work. +Thanks to the Digital Equipment Corporation Western Research Laboratory +(DECWRL) for use of their computer facilities, and to Mike Chow of +Apple Computer for the Macintosh II-specific changes. + +\end{document} diff --git a/doc/latexfiles/manual.tex b/doc/latexfiles/manual.tex new file mode 100644 index 00000000..f1facbd2 --- /dev/null +++ b/doc/latexfiles/manual.tex @@ -0,0 +1,95 @@ +%---------------------------------------------------------------------------- +% Magic User's Manual +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{book} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#X: Title_goes_here} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} + +\begin{frontmatter} + +\tableofcontents + +\listoffigures + +\listoftables + +\end{frontmatter} + +\chapter Overview +\input{introduction.tex} + +\chapter Manual Pages---Section 1 (Programs) + +\chapter Manual Pages---Section 3 (Libraries) + +\chapter Manual Pages---Section 5 (File Formats) + +\chapter Manual Pages---Section 8 (System Maintenance) + +\chapter Tutorials +\input{tut1.tex} +\input{tut2.tex} +\input{tut3.tex} +\input{tut4.tex} +\input{tut5.tex} +\input{tut6.tex} +\input{tut7.tex} +\input{tut8.tex} +\input{tut9.tex} +\input{tut10.tex} +\input{tut11.tex} +\input{tutwrl1.tex} +\input{tutscm1.tex} +\input{tutscm2.tex} +\input{tutscm3.tex} +\input{tutscm4.tex} + +\chapter Maintainer's Manuals +\input{maint1.tex} +\input{maint2.tex} +\input{maint3.tex} +\input{maint4.tex} + +\chapter Technology Manuals + +\appendix + +\chapter Other Reports In This Series + +\end{document} diff --git a/doc/latexfiles/tut1.tex b/doc/latexfiles/tut1.tex new file mode 100644 index 00000000..9bbdb361 --- /dev/null +++ b/doc/latexfiles/tut1.tex @@ -0,0 +1,497 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 1 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#1: Getting Started} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape John Ousterhout} \\ + \vspace*{0.5in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + {\itshape (Updated by others, too.)} \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +\section{What is Magic?} + +Magic is an interactive system for creating and modifying +VLSI circuit layouts. With Magic, you use a color graphics +display and a mouse or graphics tablet +to design basic cells and to combine them +hierarchically into large structures. Magic is different from +other layout editors you may have used. The most important +difference is that Magic is more than just a color painting +tool: it understands quite a bit about the nature of circuits +and uses this information to provide you with +additional operations. +For example, Magic has built-in knowledge of layout rules; as +you are editing, it continuously checks for rule violations. +Magic also knows about connectivity and transistors, and +contains a built-in hierarchical +circuit extractor. Magic also has a {\itshape plow} +operation that you can use to stretch or compact +cells. Lastly, Magic has routing tools that you can +use to make the global interconnections in your circuits. + +Magic is based on the Mead-Conway style of design. This means +that it uses simplified design rules and circuit structures. +The simplifications make it easier for you to design circuits +and permit Magic to provide powerful assistance that would +not be possible otherwise. However, they +result in slightly less dense circuits than you could get with +more complex rules and structures. For example, Magic permits +only {\itshape Manhattan} designs (those whose edges are +vertical or horizontal). Circuit designers tell us that our +conservative design rules cost 5-10\% in density. We +think that the density sacrifice is compensated for +by reduced design time. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|l|} \hline + Magic Tutorial \#1: Getting Started \\ + Magic Tutorial \#2: Basic Painting and Selection \\ + Magic Tutorial \#3: Advanced Painting (Wiring and Plowing) \\ + Magic Tutorial \#4: Cell Hierarchies \\ + Magic Tutorial \#5: Multiple Windows \\ + Magic Tutorial \#6: Design-Rule Checking \\ + Magic Tutorial \#7: Netlists and Routing \\ + Magic Tutorial \#8: Circuit Extraction \\ + Magic Tutorial \#9: Format Conversion for CIF and Calma \\ + Magic Tutorial \#10: The Interactive Route \\ + Magic Tutorial \#11: Using RSIM with Magic \\ \hline + Magic Maintainer's Manual \#1: Hints for System Maintainers \\ + Magic Maintainer's Manual \#2: The Technology File \\ + Magic Maintainer's Manual \#3: Display Styles, Color Maps, and Glyphs \\ + Magic Maintainer's Manual \#4: Using Magic Under X Windows \\ \hline + Magic Technology Manual \#1: NMOS \\ + Magic Technology Manual \#2: SCMOS \\ \hline + \end{tabular} + \end{center} + \caption{The Magic tutorials, maintenance manuals, and technology manuals.} + \label{tutorials} +\end{table} + +\section{How to Get Help and Report Problems} + +There are several ways you can get help about Magic. +If you are trying to learn about the system, you should start +off with the Magic tutorials, of which this is the first. +Each tutorial introduces a particular set of facilities in Magic. +There is also a set of manuals intended for system maintainers. +These describe things like how to create new technologies. +Finally, there is a set of technology manuals. Each one of +the technology manuals describes the features peculiar to +a particular technology, such as layer names and design rules. +Table~\ref{tutorials} lists all of the Magic manuals. +The tutorials are designed to be read while you are running Magic, +so that you can try out the new commands as they are explained. +You needn't read all the tutorials at once; each tutorial +lists the other tutorials that you should read first. + +The tutorials are not necessarily complete. Each one +is designed to introduce a set of facilities, but it doesn't +necessarily cover every possibility. The ultimate authority +on how Magic works is the reference manual, which is a standard +Unix {\itshape man} page. The {\itshape man} page gives concise +and complete descriptions of all the Magic commands. +Once you have a general idea how a command works, the {\itshape man} +page is probably easier to consult than the tutorial. However, +the {\itshape man} page may not make much sense until after you've +read the tutorial. + +A third way of getting help is available on-line through Magic +itself. The {\bfseries :help} command will print +out one line for each Magic command, giving the command's syntax +and an extremely brief description of the command. +This facility is useful if you've forgotten the name or exact +syntax of a command. After each +screenful of help information, {\bfseries :help} stops and prints ``--More--''. +If you type a space, the next screenful of data will be output, and +if you type {\bfseries q} the rest of the output will be skipped. +If you're interested in information about a particular subject, +you can type + +\starti + \ii {\bfseries :help} {\itshape subject} +\endi + +This command will print out each command description that +contains the {\itshape subject} string. + +If you have a question or problem that can't be answered +with any of the above approaches, you may contact the Magic authors +by sending mail to {\ttfamily magic@ucbarpa.Berkeley.EDU}. +This will log your message in a file (so we can't forget about it) and +forward the message to the Magic maintainers. +Magic maintenance is a mostly volunteer effort, so +when you report a bug or ask a question, {\itshape please} be specific. +Obviously, the more specific you are, the more likely we can answer your +question or reproduce the bug you found. +We'll tend to answer the specific bug reports first, since they involve less +time on our part. Try to describe +the exact sequence of events that led to the problem, what you +expected to happen, and what actually happened. If possible, +find a small example that reproduces the problem and +send us the relevant (small!) files so we can make it happen here. +Or best of all, send us a bug fix along with a small example of the problem. + +\section{Graphics Configuration} + +Magic can be run with different graphics hardware. The most common +configuration is to run Magic under X11 on a workstation. Another way +to run Magic is under SunView on a Sun workstation, or under OpenGL +(in an X11 environment) on an SGI workstation or Linux box with +accelerated 3D video hardware and drivers. Legacy code exists +supporting AED graphics terminals and X10 (the forerunner of X11). +The rest of this section concerns X11. + +Before starting up magic, make sure that your {\ttfamily DISPLAY} variable is +set correctly. If you are running magic and your X server on the same +machine, set it to {\ttfamily unix:0}: + +\starti + \ii {\bfseries setenv} {\ttfamily DISPLAY unix:0} +\endi + +The Magic window is an ordinary X window, and can be moved and resized using +the window manager. + +For now, you can skip to the next major section: "Running Magic". + +\section{Advanced X Use} + +The X11 driver can read in window sizing and font preferences from +your {\itshape .Xdefaults} file. The following specifications are recognized: + +\starti + \> {\bfseries magic.window:} \ii 1000x600+10+10 \\ + \> {\bfseries magic.newwindow:} \ii 300x300+400+100 \\ + \> {\bfseries magic.small:} \ii helvetica8 \\ + \> {\bfseries magic.medium:} \ii helvetica12 \\ + \> {\bfseries magic.large:} \ii helvetica18 \\ + \> {\bfseries magic.xlarge:} \ii helvetica24 +\endi + +{\bfseries magic.window} is the size and position of the initial window, +while {\bfseries magic.newwindow} is the size and position of subsequent +windows. If these are left blank, you will be prompted to give +the window's position and size. {\bfseries small}, {\bfseries medium}, +{\bfseries large}, and {\bfseries xlarge} are various fonts magic uses +for labels. +Some X11 servers read the {\ttfamily .Xdefaults} file only when you initially +log in; you may have to run {\ttfamily xrdb -load \~{}/.Xdefaults} +for the changes to take +effect. + +Under X11, Magic can run on a display of any depth for which there are +colormap and dstyle files. Monochrome, 4 bit, 6 bit, 7 bit, and 24 bit +files for MOS are distributed in this release. You can explicitly specify +how many planes Magic is to use by adding a suffix numeral between +1 and 7 to ``XWIND'' when used with Magic's ``-d'' option. +For example, ``magic -d XWIND1'' runs magic on a monochrome +display and ``magic -d XWIND7'' runs magic on a 7 plane display. +If this number is not specified, magic checks the depth of the display +and picks the largest number in the set \{1, 4, 6, 7, 16, 24\} that the display +will support. +Another way to force the display type is to set an environment variable +called {\ttfamily MAGIC\_COLOR} to one of the strings ``8bit'', ``16bit'', +or ``24bit''. + +\medskip +\noindent {\bfseries \itshape Linux note:} \\ +Magic's ``native'' display (except when using the OpenGL interface) +is the 8-bit PseudoColor visual type. 24-bit TrueColor visuals prevent +Magic from allocating colors for bit-plane logical operations, so the +24-bit interface is visually somewhat sub-par, requiring stipple +patterns on all metal layers, for instance. Under Linux, a few +(commercial) X drivers will support 8-bit overlays on top of 24-bit +TrueColor when using 32-bit color. This is the ideal way to use +magic, because the colormap for the rest of the display is preserved +when the cursor is inside the Magic window. Otherwise, the X session +may have to be started using ``{\ttfamily startx --bpp 8}'' to force +it to use the 8-bit PseudoColor visual. + +\medskip +\noindent {\bfseries \itshape X11 remote usage note:} \\ +When running Magic remotely on an X terminal, the colormap allocation +may differ for the local machine compared to the remote machine. In +some cases, this can cause the background of magic to appear black, +usually with a black-on-black cursor. This is known to be true of +X11 drivers for Windows (such as PC-XWare), due to the way the Windows +8-bit PseudoColor colormap is set up. This behavior can be corrected +by setting two environment variables on the remote machine as follows: + +\starti + \ii {\bfseries setenv} {\ttfamily X\_COLORMAP\_BASE 128} \\ + \ii {\bfseries setenv} {\ttfamily X\_COLORMAP\_DEFAULT 0} \\ +\endi + +This causes Magic to avoid trying to allocate the first color +in the colormap, which under Windows is fixed as black. + +\section{Running Magic} + +From this point on, you should be sitting at a Magic workstation +so you can experiment with the program as you read the manuals. +Starting up Magic is usually pretty simple. Just log in and, if needed, +start up your favorite window system. Then type the shell command + +\starti + \ii {\bfseries magic tut1} +\endi + +{\bfseries Tut1} is the name of a library cell that you will play +with in this tutorial. +At this point, several colored rectangles should appear +on the color display along with a white box and a cursor. +A message will be printed on the text display to tell you that +{\bfseries tut1} isn't writable (it's in a read-only library), +and a ``$>$'' prompt should appear. +If this has happened, then you can skip the rest of this +section (except for the note below) and go directly to Section 5. + +Note: in the tutorials, when you see things printed in boldface, +for example, {\bfseries magic tut1} from above, they refer to things +you type exactly, such as command names and file names. These +are usually case sensitive ({\bfseries A} is different from {\bfseries a}). +When you see things printed in italics, they refer to classes of +things you might type. Arguments in square brackets are optional. +For example, a more complete description +of the shell command for Magic is + +\starti + \ii {\bfseries magic} [{\itshape file}] +\endi + +You could type any file name for {\itshape file}, and +Magic would start editing that file. It turns out that {\bfseries tut1} +is just a file in Magic's cell library. If you didn't type a +file name, Magic would load a new blank cell. + +If things didn't happen as they should have when you tried to +run Magic, any of several things could be wrong. If a message +of the form ``magic: Command not found'' appears on your screen +it is because the shell couldn't find the Magic program. The +most stable version of Magic is the directory {\ttfamily \~{}cad/bin}, +and the newest public version is in {\ttfamily \~{}cad/new}. You should +make sure that both these directories are in your shell path. +Normally, {\ttfamily \~{}cad/new} should appear before {\ttfamily \~{}cad/bin}. +If this sounds like gibberish, find a Unix hacker and have him or her +explain to you about paths. If worst comes to worst, you can invoke +Magic by typing its full name: + +\starti + \ii {\bfseries \~{}cad/bin/magic tut1} +\endi + +Another possible problem is that +Magic might not know what kind of display you are using. +To solve this, use magic's {\bfseries -d} flag: +\starti + \ii {\bfseries magic -d} {\itshape display} {\bfseries tut1} +\endi +{\itshape Display} is usually the model number of the workstation you are using or +the +name of your window system. Look in the manual page for a list of valid +names, or just guess something. Magic will print out the list of valid names +if you guess wrong. + +If you are using a graphics terminal (not a workstation), +it is possible that Magic doesn't know which serial line to use. To learn +how to fix +this, read about the {\bfseries -g} switch in the magic(1) manual page. Also read +the displays(5) manual page. + +\section{The Box and the Cursor} + +Two things, called the {\itshape box} and the {\itshape cursor}, are used +to select things on the color display. As you move the +mouse, the cursor moves on the screen. The cursor starts out +with a crosshair shape, but you'll see later that its shape +changes as you work to provide feedback about what you're +doing. The left and right +mouse buttons are used to position the box. If you press the +left mouse button and then release it, the box will move so +that its lower left corner is at the cursor position. If +you press and release the right mouse button, the upper right +corner of the box will move to the cursor position, but the +lower left corner will not change. These two buttons are +enough to position the box anywhere on the screen. Try using +the buttons to place the box around each of the colored rectangles +on the screen. + +Sometimes it is convenient to move the box by a corner other +than the lower left. To do this, press the left mouse button +and {\itshape hold it down}. The cursor shape changes to show you +that you are moving the box by its lower left corner: + +\begin{center} + \begin{tabular}{|c|} \hline + \hspace*{0.1in} \\ \hline + \end{tabular} +\end{center} + +While +holding the button down, move the cursor near the lower right +corner of the box, and now click the right mouse button (i.e. +press and release it, while still holding down the left +button). The cursor's shape will change to indicate that +you are now moving the box by its lower right corner. Move +the cursor to a different place on the screen and release +the left button. The box should move so that its lower right +corner is at the cursor position. Try using this feature to +move the box so that it is almost entirely off-screen to the +left. Try moving the box by each of its corners. + +You can also reshape the box by corners other than the upper +right. To do this, press the right mouse button and hold +it down. The cursor shape shows you that you are reshaping +the box by its upper right corner: + +\begin{center} + \begin{tabular}{c|} \hline + \hspace*{0.1in} \\ + \end{tabular} +\end{center} + +Now move the cursor +near some other corner of the box and click the left button, +all the while holding the right button down. The cursor +shape will change to show you that now you are reshaping the +box by a different corner. When you release the right button, +the box will reshape so that the selected corner is at +the cursor position but the diagonally opposite corner is unchanged. +Try reshaping the box by each of its corners. + +\section{Invoking Commands} + +Commands can be invoked in Magic in three ways: by pressing +buttons on the mouse; by typing single keystrokes on the +text keyboard (these are called +{\itshape macros}); or by typing longer commands on the text +keyboard (these are called {\itshape long commands}). Many of the +commands use the box and cursor to help guide the command. + +To see how commands can be invoked from the buttons, first +position the box over a small blank area in the middle of the +screen. Then move the cursor over the red rectangle and +press the middle mouse button. At this point, the area of the box should +get painted red. Now move the cursor over empty space and +press the middle button again. The red paint should go away. +Note how this command uses both the cursor and box locations +to control what happens. + +As an example of a macro, type the {\bfseries g} key on +the text keyboard. A grid will appear on the color display, along +with a small black box marking the origin of the cell. +If you type {\bfseries g} again, the grid will go away. You +may have noticed earlier that the box corners didn't move to +the exact cursor position: you can see now that the box is +forced to fall on grid points. + +Long commands are invoked by typing a colon (``:'') or +semi-colon (``;''). After you +type the colon or semi-colon, the ``$>$'' prompt on the text +screen will be replaced by a ``:'' prompt. This indicates +that Magic is waiting for a long command. At this point +you should type a line of text, followed by a return. +When the long command has been processed, the ``$>$'' prompt +reappears on the text display. Try typing semi-colon followed by +return to see how this works. Occasionally a ``]'' (right bracket) +prompt will appear. This means that the design-rule checker is reverifying +part of your design. For now you can just ignore this and treat +``]'' like ``$>$''. + +Each long command consists of the name of the command followed +by arguments, if any are needed by that command. The command +name can be abbreviated, just as long as you type enough +characters to distinguish it from all other long commands. +For example, {\bfseries :h} and {\bfseries :he} may be used as abbreviations for +{\bfseries :help}. On the other hand, {\bfseries :u} may not be used as an +abbreviation for {\bfseries :undo} because there is another command, +{\bfseries :upsidedown}, that has the same abbreviation. Try typing +{\bfseries :u}. + +As an example of a long command, put the box over empty space on +the color display, then invoke the long command + +\starti + \ii {\bfseries :paint red} +\endi + +The box should fill with the red color, just as if you had +used the middle mouse button to paint it. Everything you can +do in Magic can be invoked with a long command. It turns out that +the macros are just conveniences that are expanded into long +commands and executed. For example, the long command equivalent +to the {\bfseries g} macro is + +\starti + \ii {\bfseries :grid} +\endi + +Magic permits you to define new macros if you wish. Once you've +become familiar with Magic you'll almost certainly want to add +your own macros so that you can invoke quickly the commands you +use most frequently. See the +{\itshape magic(1)} man page under the command {\bfseries :macro}. + +One more long command is of immediate use to you. It is + +\starti + \ii {\bfseries :quit} +\endi + +Invoke this command. Note that before exiting, Magic will +give you one last chance to save the information that you've +modified. Type {\bfseries y} to exit without saving anything. + +\end{document} diff --git a/doc/latexfiles/tut10.tex b/doc/latexfiles/tut10.tex new file mode 100644 index 00000000..8b80c78c --- /dev/null +++ b/doc/latexfiles/tut10.tex @@ -0,0 +1,580 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 10 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#10: The Interactive Router} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Michael Arnold} \\ + \vspace*{0.5in} + O Division \\ + Lawrence Livermore National Laboratory \\ + Livermore, CA 94550 \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection \\ + \> Magic Tutorial \#4: Cell Hierarchies +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :iroute +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> \^{}R, \^{}N +\endi + +\vspace*{0.25in} +\section{Introduction} + +The Magic interactive router, {\itshape Irouter}, provides an interactive interface +to Magic's internal maze router. It is intended as an aid to manual +routing. Routing is done one connection at a time, the user specifying +a starting point and destination areas prior to each connection. The user +determines the order in which signals are routed and how multi-point nets +are decomposed into point-to-area connections. In addition parameters and +special Magic {\itshape hint} layers permit the user to control the nature +of the routes. Typically the user determines the overall path of a connection, +and leaves the details of satisfying the design-rules, and detouring around or +over minor obstacles, to the router. + +The interactive router is not designed for fully +automatic routing: interactions between nets +are not considered, and net decomposition is +not automatic. Thus netlists are generally +not suitable input for the Irouter. However it can be convenient to obtain +endpoint information from netlists. The {\itshape Net2ir} program uses +netlist information to generate commands +to the Irouter with appropriate endpoints for specified +signals. Typically a user might +setup parameters and hints to river-route a set of connections, +and then generate Irouter commands with the appropriate endpoints via +Net2ir. For details on Net2ir see the +manual page {\itshape net2ir(1)}. + +This tutorial provides detailed information on the use +of the Irouter. On-line help, Irouter +subcommands, Irouter parameters, and hint-layers are explained. + +\section{Getting Started---`Cntl-R', `Cntl-N', `:iroute' and `:iroute help'} + +To make a connection with the Irouter, place the cursor over one +end of the desired connection (the {\itshape start-point}) and the box at the +other end (the {\itshape destination-area}). Then type + +\starti + \ii {\bfseries Cntl-R} +\endi + +Note that the box must be big +enough to allow the route to terminate entirely within it. A +design-rule correct connection between the cursor and the box should +appear. The macro + +\starti + \ii {\bfseries Cntl-R} +\endi + +and the long commands + +\starti + \ii {\bfseries :iroute} \\ + \ii {\bfseries :iroute route} +\endi + +are all equivalent. They invoke the Irouter to connect the cursor with +the interior of the box. Note that the last connection is always left +selected. This allows further terminals to be +connected to the route with the second Irouter macro, {\bfseries Cntl-N}. Try +typing + +\starti + \ii {\bfseries Cntl-N} +\endi + +A connection between the cursor and the previous route should appear. In +general {\bfseries Cntl-N} routes from the cursor to the selection. + +There are a number of commands to set parameters and otherwise interact with +the Irouter. These commands have the general form + +\starti + \ii {\bfseries :iroute}{\itshape subcommand }[{\itshape arguments}] +\endi + +For a list of subcommands and a short description of each, type + +\starti + \ii {\bfseries :iroute help} +\endi + +Usage information on a subcommand can be obtained by typing + +\starti + \ii {\bfseries :iroute help }[{\itshape subcommand}] +\endi + +As with Magic in general, unique abbreviations of subcommands and most of their +arguments are permitted. Case is generally ignored. + +\section{:Undo and Cntl-C} + +As with other Magic commands, the results of {\bfseries :iroute} can be undone +with {\bfseries :undo}, and if the Irouter is taking too long it can be interrupted +with {\bfseries Cntl-C}. This makes it easy to refine the results of the Irouter +by trial and error. If you don't like the +results of a route, undo it, tweak the Irouter parameters or hints you are +using and try again. If the Irouter is taking too long, you can very +likely speed things up by interrupting it, resetting +performance related parameters, and trying again. The details of +parameters and +hints are described later in this document. + +\section{More about Making Connections---`:iroute route'} + +Start points for routes can be specified via the cursor, +labels, or coordinates. Destination areas can be specified via the box, +labels, coordinates or the selection. In addition start and destination +layers can be specified explicitly. For the syntax of all these options +type + +\starti + \ii {\bfseries :iroute help route} +\endi + +When a start point lies on top of existing geometry +it is assumed that a connection to that material is desired. If this is +not the case, the desired starting layer must be explicitly +specified. When routing to the selection it is assumed that connection +to the selected material is desired. By default, routes to the box +may terminate on any active route layer. If you are having trouble connecting +to a large region, it may +be because the connection point or area is too far in the interior of the +region. Try moving it toward the edge. (Alternately see the discussion +of the {\itshape penetration} parameter in the wizard section below.) + +\section{Hints} + +Magic has three built-in layers for graphical +control of the Irouter, {\bfseries fence} ({\bfseries f}), +{\bfseries magnet} ({\bfseries mag}), and {\bfseries rotate} +({\bfseries r}). These layers +can be painted and erased just like other Magic layers. The effect +each has on the Irouter is described below. + +\subsection{The Fence Layer} + +The Irouter won't cross fence boundaries. Thus the fence layer is useful +both for carving out routing-regions and for blocking routing in given +areas. It is frequently useful to indicate the broad path of one or +a series of routes with fence. In addition to guiding the route, the +use of fences can greatly speed up the router by limiting the search. + +\subsection{The Magnet Layer} + +Magnets attract the route. They can be used to pull routes in a +given direction, e.g., towards one edge of a channel. Over use of +magnets can make routing slow. In particular magnets that are long and +far away from the actual route can cause performance problems. (If +you are having problems with magnets and performance, see also the +discussion of the {\itshape penalty} parameter in the wizard section below.) + +\subsection{The Rotate Layer} + +The Irouter associates different weights with horizontal and vertical +routes (see the layer-parameter section below). This is so that +a preferred routing direction can be established for each layer. When +two good route-layers are available (as in a two-layer-metal process) +interference between routes can be minimized by assigning opposite +preferred directions to the layers. + +The rotate layer locally inverts the preferred directions. An example +use of the rotate layer might involve an {\bfseries L}-shaped bus. +The natural preferred directions on one leg of the {\bfseries L} are the opposite +from the other, and thus one leg needs to be +marked with the rotate layer. + +\section{Subcells} + +As with painting and other operations in Magic, the Irouter's +output is written to the cell being edited. What the router sees, that +is which features act as obstacles, is determined by the +window the route is issued to (or other designated reference window - +see the wizard +section.) The contents of subcells expanded in the route window +are visible to the Irouter, but it only sees the bounding boxes +of unexpanded subcells. These bounding boxes appear on a special +{\bfseries SUBCELL} pseudo-layer. The spacing parameters to the {\bfseries SUBCELL} +layer determine exactly how the Irouter treats unexpanded subcells. +(See the section on spacing parameters below.) By default, the +spacings to the {\bfseries SUBCELL} layer are large enough to guarantee that +no design-rules will be violated, regardless of the contents of +unexpanded subcells. Routes can be terminated +at unexpanded subcells in the same fashion that connections to +other pre-existing features are made. + +\section{Layer Parameters---`:iroute layers'} + +{\itshape Route-layers}, specified in the {\bfseries mzrouter} section of the +technology file, are the layers potentially available +to the Irouter for routing. The {\bfseries layer} subcommand gives access +to parameters associated with these route-layers. Many of the +parameters are weights for factors in the Irouter cost-function. The +Irouter strives for the cheapest possible route. Thus the balance between +the factors in the cost-function determines the character of the +routes: which layers are used in which directions, and the number of +contacts and jogs can be controlled in this way. But +be careful! Changes in these parameters can also +profoundly influence performance. Other parameters determine +which of the route-layers are actually available for routing and +the width of routes on each layer. It is a good idea to inactivate +route-layers not being used anyway, as this speeds up routing. + +The layers subcommand takes a variable number of arguments. + +\starti + \ii {\bfseries :iroute layers} +\endi + +prints a table with one row for each route-layer giving all parameter +values. + +\starti + \ii {\bfseries :iroute layers}{\itshape type} +\endi + +prints all parameters associated with route-layer {\itshape type}. + +\starti + \ii {\bfseries :iroute layers}{\itshape type parameter} +\endi + +prints the value of {\itshape parameter} for layer {\itshape type}. +If {\itshape type} is `{\bfseries *}', the value of {\itshape parameter} +is printed for all layers. + +\starti + \ii {\bfseries :iroute layers} {\itshape type parameter value} +\endi + +sets {\itshape parameter} to {\itshape value} on layer {\itshape type}. +If {\itshape type} is `{\bfseries *}', {\itshape parameter} is set to +{\itshape value} on all layers. + +\starti + \ii {\bfseries :iroute layers} {\itshape type} {\bfseries *} + {\itshape value1 value2 }\dots{\itshape valuen} +\endi + +sets a row in the parameter table. + +\starti + \ii {\bfseries :iroute layers *}{\itshape parameter value1 \dots valuen} +\endi + +sets a column in the table. + +There are six layer parameters. + +\begin{itemize} + \item {\bfseries active} \\ + Takes the value of {\bfseries YES} (the default) or {\bfseries NO}. Only + active layers are used by the Irouter. + + \item {\bfseries width} \\ + Width of routing created by the Irouter on the given layer. The + default is the minimum width permitted by the design rules. + + \item {\bfseries hcost} \\ + Cost per unit-length for horizontal segments on this layer. + + \item {\bfseries vcost} \\ + Cost per unit-length for vertical segments. + + \item {\bfseries jogcost} \\ + Cost per jog (transition from horizontal to vertical segment). + + \item {\bfseries hintcost} \\ + Cost per unit-area between actual route and magnet segment. +\end{itemize} + +\section{Contact Parameters---`:iroute contacts'} + +The {\bfseries contacts} subcommand gives access to a table of parameters for +contact-types used in routing, one row of parameters per type. The syntax is +identical to that of the {\bfseries layers} subcommand described above, and +parameters are printed and set in the same way. + +There are three contact-parameters. + +\begin{itemize} + \item {\bfseries active} \\ + Takes the value of {\bfseries YES} (the default) or {\bfseries NO}. Only + active contact types are used by the Irouter. + + \item {\bfseries width} \\ + Diameter of contacts of this type created by the Irouter. The + default is the minimum width permitted by the design-rules. + + \item {\bfseries cost} \\ + Cost per contact charged by the Irouter cost-function. +\end{itemize} + +\section{Spacing Parameters---`:iroute spacing'} + +The spacing parameters specify minimum +spacings between the route-types +(route-layers and route-contacts) and arbitrary Magic types. +These spacings are the design-rules +used internally by the Irouter during routing. Default +values are derived from the {\bfseries drc} section +of the technology file. These values can be +overridden in the {\bfseries mzrouter} section of the +technology file. (See the {\itshape Magic Maintainers Manual on Technology Files} +for details.) Spacings can be examined and changed at any +time with the {\bfseries spacing} subcommand. Spacing values can +be {\bfseries nil}, {\bfseries 0}, or positive integers. A value of {\bfseries nil} +means there is no spacing constraint between the route-layer and the given type. A +value of {\bfseries 0} means the route-layer may not overlap the given type. If +a positive value is specified, the Irouter will maintain the +given spacing between new routing on the specified +route-layer and pre-existing features of the specified type (except when +connecting to the type at an end-point of the new route). + +The {\bfseries spacing} subcommand takes several forms. + +\starti + \ii {\bfseries :iroute spacing} +\endi + +prints spacings for all route-types. (Nil spacings are omitted.) + +\starti + \ii {\bfseries :iroute spacing} {\itshape route-type} +\endi + +prints spacings for {\itshape route-type}. (Nil spacings are omitted.) + +\starti + \ii {\bfseries :iroute spacing} {\itshape route-type type} +\endi + +prints the spacing between {\itshape route-type} and {\itshape type}. + +\starti + \ii {\bfseries :iroute spacing} {\itshape route-type type value} +\endi + +sets the spacing between {\itshape route-type} and {\itshape type} to {\itshape value}. + +The spacings associated with each route-type are +the ones that are observed when the +Irouter places that route-type. To change the spacing between two +route-types, two spacing parameters must be changed: the spacing to +the first type when routing on the second, and the spacing to +the second type when routing on the first. + +Spacings to the {\bfseries SUBCELL} pseudo-type give the minimum spacing between +a route-type and unexpanded subcells. The {\bfseries SUBCELL} spacing for a given +route-layer defaults to the maximum spacing to the route-layer required +by the design-rules (in the +{\bfseries drc} section of the technology file). This ensures that +no design-rules will be violated regardless of the contents of the +subcell. If subcell designs are constrained in a fashion that permits +closer spacings to some layers, the {\bfseries SUBCELL} spacings can be +changed to take advantage of this. + +\section{Search Parameters---`:search'} + +The Mzrouter search is windowed. Early in the search only partial paths +near the start point are considered; as the search progresses the window +is moved towards the goal. This prevents combinatorial explosion during +the search, but still permits the exploration of alternatives at all stages. +The {\bfseries search} subcommand permits access to two parameters +controlling the windowed search, {\bfseries rate}, and {\bfseries width}. The {\bfseries rate} +parameter determines how fast the window is shifted towards the goal, and +the {\bfseries width} parameter gives the width of the window. The units are +comparable with those used in the cost parameters. If the router is taking +too long to complete, try increasing {\bfseries rate}. If the router is +choosing poor routes, try decreasing {\bfseries rate}. The window width should +probably be at least twice the rate. + +The subcommand has this form: + +\starti + \ii {\bfseries :iroute search} [{\itshape parameter}] [{\itshape value}] +\endi + +If {\itshape value} is omitted, the current value is printed, if {\itshape parameter} +is omitted as well, both parameter values are printed. + +\section{Messages---`:iroute verbosity'} + +The number of messages printed by the Irouter is controlled by + +\starti + \ii {\bfseries :iroute verbosity}{\itshape value} +\endi + +If verbosity is set to {\bfseries 0}, only errors and warnings +are printed. A value +of {\bfseries 1} (the default) results in short messages. +A value of {\bfseries 2} causes statistics to be printed. + +\section{Version---`:iroute version'} + +The subcommand + +\starti + \ii {\bfseries :iroute version} +\endi + +prints the Irouter version in use. + +\section{Saving and Restoring Parameters---`:iroute save'} + +The command + +\starti + \ii {\bfseries :iroute save} {\itshape file}{\bfseries .ir} +\endi + +saves away the current settings of all the Irouter parameters in file +{\itshape file}{\bfseries .ir}. Parameters can be reset to these values +at any time with the command + +\starti + \ii {\bfseries :source} {\itshape file}{\bfseries .ir} +\endi + +This feature can be used to setup parameter-sets appropriate to different +routing contexts. Note that the extension {\bfseries .ir} is recommended +for Irouter parameter-files. + +\section{Wizard Parameters---`:iroute wizard'} + +Miscellaneous parameters that are probably not of interest +to the casual user are +accessed via the {\bfseries wizard} subcommand. The parameters are as follows: + +\begin{itemize} +\item {\bfseries bloom} +Takes on a non-negative integer value. This controls the amount of +compulsory searching from a focus, before the next focus is picked +based on the cost-function and window position. In practice {\bfseries 1} +(the default value) +seems to be the best value. This parameter may be removed in the future. + +\item {\bfseries boundsIncrement} +Takes on the value {\bfseries AUTOMATIC} or a positive integer. Determines in +what size chunks the layout is preprocessed for routing. This +preprocessing (blockage generation) takes a significant fraction of the +routing time, thus performance may well be improved by experimenting with +this parameter. + +\item {\bfseries estimate} +Takes on a boolean value. If {\bfseries ON} (the default) an estimation plane +is generated prior to each route that permits +cost-to-completion estimates to factor in subcells and fence regions. This +can be very important to efficient routing. Its rarely useful to turn +estimation off. + +\item {\bfseries expandDests} +Takes on a boolean value. If {\bfseries ON} (not the default) destination areas +are expanded to include all of any nodes they overlap. This is particularly +useful if the Irouter is being invoked from a script, since it is +difficult to determine optimal destination areas automatically. + +\item {\bfseries penalty} +Takes on a rational value (default is 1024.0). It is not strictly +true that the router searches only within its window. Paths behind +the window are also considered, but with cost penalized by the +product of their distance to the window +and the penalty factor. It was originally thought that small +penalties might be desirable, but experience, so far, has shown that large +penalties work better. In particular it is important that the ratio between +the actual cost of a route and the initial estimate is less than the +value of {\bfseries penalty}, otherwise the search can explode (take +practically forever). If you suspect this is happening, you can set +{\bfseries verbosity} to {\bfseries 2} to check, or just increase the value +of {\bfseries penalty}. In summary it appears that the value of penalty doesn't +matter much as long as it is large (but not so large as to cause +overflows). It will probably be removed in the future. + +\item {\bfseries penetration} +This parameter takes the value {\bfseries AUTOMATIC} or a positive integer. It +determines how far into a blocked area the router will +penetrate to make a connection. Note however the router will in no case +violate spacing constraints to nodes not involved in the route. + +\item {\bfseries window} +This parameter takes the value {\bfseries COMMAND} (the default) or a window id +(small integers). It determines the reference window for routes. The router +sees the world as it appears in the reference window, e.g., it sees the +contents of subcells expanded in the reference window. If {\bfseries window} +is set to {\bfseries COMMAND} the reference window is the one that contained the +cursor when the route was invoked. To set the reference window to a fixed +window, place the cursor in that window and type: +\starti + \ii {\bfseries :iroute wizard window .} +\endi +\end{itemize} + +\begin{thebibliography}{1} + \bibitem{arnold} M.H. Arnold and W.S. Scott, + \newblock ``An Interactive Maze Router with Hints'', + \newblock {\itshape Proceedings of the 25th Design Automation Conference}, + \newblock June 1988, pp. 672--676. +\end{thebibliography} + +\end{document} diff --git a/doc/latexfiles/tut11.tex b/doc/latexfiles/tut11.tex new file mode 100644 index 00000000..99b8ae54 --- /dev/null +++ b/doc/latexfiles/tut11.tex @@ -0,0 +1,467 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 11 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#11: Using IRSIM and RSIM with Magic} +\def\_{\rule{0.6em}{0.5pt}} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Michael Chow} \\ + {\itshape Mark Horowitz} \\ + \vspace*{0.5in} + Computer Systems Laboratory \\ + Center for Integrated Systems \\ + Stanford University \\ + Stanford, CA 94305 \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection \\ + \> Magic Tutorial \#4: Cell Hierarchies \\ + \> Magic Tutorial \#8: Circuit Extraction +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :getnode, :rsim, :simcmd, :startrsim +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (None)} +\endi + +\vspace*{0.25in} +\section{Introduction} + +This tutorial explains how to use Magic's interface to the +switch-level circuit simulators, RSIM and IRSIM. +The interface is the same for both these simulators and, except +where noted, RSIM refers to IRSIM as well. +This interface eliminates +the tedium of mapping node +names to objects in the layout and typing node names as RSIM input. +It allows the user to +select nodes using the mouse and apply RSIM commands to them or to display +the node values determined by RSIM in the layout itself. +You should already be familiar +with using both RSIM and Magic's circuit extractor. +Section 2 describes how to prepare the files +necessary to simulate a circuit. Section 3 describes how to run +RSIM interactively under Magic. Section 4 explains how to +determine the node names that RSIM uses. Lastly, section 5 explains how to +use the RSIM tool in Magic to simulate a circuit. + +\section{Preparations for Simulation} + +Magic uses the RSIM input file when it simulates the circuit. Before +proceeding any further, make sure you have the correct versions of the +programs {\bfseries ext2sim} and {\bfseries rsim} installed on your system. +Important +changes have been made to these programs to support simulation within +Magic. To try out +this tool on an example, copy all the {\bfseries tut11{\itshape x}} cells to your +current directory with the following command: + +\starti + \ii {\bfseries cp \~{}cad/lib/magic/tutorial/tut11* .} +\endi + +The {\bfseries tut11a} cell is a simple 4-bit counter using the Magic scmos +technology file. +Start Magic on the cell {\bfseries tut11a}, and extract the +entire cell using the command: + +\starti + \ii {\bfseries :extract all} +\endi + +When this command completes, several {\bfseries .ext} files will be created +in your current directory by the extractor. The next step is to flatten +the hierarchy into a single representation. Return to the Unix c-shell +by quitting Magic. + +The program {\bfseries ext2sim} is used to flatten the hierarchy. Run this +program from the C-shell by typing: + +\starti + \ii {\bfseries ext2sim -L -R -c 20 tut11a} +\endi + +This program will create the file {\bfseries tut11a.sim} in your current directory. + +If you are running IRSIM, the {\bfseries tut11a.sim} can be used directly as +input to the simulator and you should skip the next step. Instead, if +you will be using RSIM, +the last step is to create the binary representation of the flattened +hierarchy by using the program {\bfseries presim}. To do this, type: + +\starti + \ii {\bfseries presim tut11a.sim tut11a.rsm + \~{}cad/lib/scmos100.prm -nostack -nodrops} +\endi + +The third file is the parameter file used by presim for this circuit. +The convention +at Stanford is to use the suffix {\itshape .rsm} when naming the RSIM input file. +The file {\bfseries tut11a.rsm} can also be used as input for running RSIM +alone. + +\section{Using RSIM} + +Re-run Magic again to edit the cell {\bfseries tut11a}. We'll first learn how to +run RSIM in interactive mode under Magic. To simulate the circuit of +tut11a, using IRSIM type the command: + +\starti + \ii {\bfseries :rsim scmos100.prm tut11a.sim} +\endi + +To simulate the circuit of tut11a, using RSIM type the command: + +\starti + \ii {\bfseries :rsim tut11a.rsm} +\endi + +You should see the RSIM header displayed, followed by the standard RSIM +prompt ({\bfseries rsim$>$} or {\bfseries irsim$>$}, depending on the simulator) in +place of the usual +Magic prompt; this means keyboard input is now directed to RSIM. This mode +is very similar to running RSIM alone; one difference is that +the user can escape RSIM and then return to Magic. +Also, the mouse has no effect when RSIM is run interactively under Magic. + +Only one instance of RSIM may be running at any time under Magic. +The simulation running need not correspond to the Magic layout; however, +as we shall see later, they must correspond for the RSIM tool to work. +All commands typed to the RSIM prompt should be RSIM commands. +We'll first run RSIM, then escape to Magic, and then return back to RSIM. +Type the RSIM command + +\starti + \ii {\bfseries @ tut11a.cmd} +\endi + +to initialize the simulation. (Note there is a `` '' after the @.) Now type +{\bfseries c} to clock the circuit. You should see some information about +some nodes displayed, followed by the time. Set two of the nodes +to a logic ``1'' by typing {\bfseries h RESET{\_}B hold}. Step the clock again +by typing {\bfseries c}, and RSIM should show that these two nodes now have the +value ``1''. + +You can return to Magic without quitting RSIM and then later return to +RSIM in the same state in which it was left. Escape to Magic by typing: + +\starti + \ii {\bfseries . } +\endi + +(a single period) to the RSIM prompt. Next, +type a few Magic commands to show you're really back in Magic +(signified by the Magic prompt). + +You can return to RSIM by typing the Magic command {\bfseries rsim} without any +arguments. Type: + +\starti + \ii {\bfseries :rsim} +\endi + +The RSIM prompt will be displayed again, and you are now back in RSIM +in the state you left it in. Experiment with RSIM by typing some +commands. To quit RSIM and return to Magic, type: + +\starti + \ii {\bfseries q} +\endi + +in response to the RSIM prompt. You'll know you're back in Magic when +the Magic prompt is redisplayed. If you should interrupt RSIM +(typing a control-C), you'll probably kill it and then have +to restart it. RSIM running standalone will also be killed if you +interrupt it. If you interrupt IRSIM (typing a control-C), the simulator +will abort whatever it's doing (a long simulation run, for example) and +return to the command interpreter by prompting again with {\bfseries irsim$>$}. + +\section{Node Names} + +It's easy to determine node names under Magic. First, locate the +red square region in the middle right side of the circuit. Move +the cursor over this region and select it by typing {\bfseries s}. To find out +the name for this node, type: + +\starti + \ii {\bfseries :getnode} +\endi + +Magic should print that the node name is {\itshape RESET{\_}B}. +The command {\bfseries getnode} prints the names of all nodes in the current +selection. Move the cursor over the square blue region +in the upper right corner and add this +node to the current selection by typing {\bfseries S}. Type {\bfseries :getnode} again, +and Magic should print the names of two nodes; the blue node is named +{\itshape hold}. You can also print aliases for the selected nodes. +Turn on name-aliasing by typing: + +\starti + \ii {\bfseries :getnode alias on} +\endi + +Select the red node again, and type {\bfseries :getnode}. Several names will +be printed; the last name printed is the one RSIM uses, so you should use +this name for RSIM. +Note that {\bfseries getnode} is not guaranteed to print all aliases for a node. +Only those alises generated when the RSIM node name is computed are printed. +However, most of the alaiases will usually be printed. +Printing aliases is also useful to monitor the name search, since +{\bfseries getnode} can take several seconds on large nodes. Turn off aliasing +by typing: + +\starti + \ii {\bfseries :getnode alias off} +\endi + +{\bfseries getnode} works by extracting a single node. Consequently, it can take +a long time to compute the name for large nodes, such as {\itshape Vdd} or +{\itshape GND}. Select the horizontal blue strip on top of the circuit and +run {\bfseries :getnode} on this. You'll find that this will take about six +seconds for {\bfseries getnode} to figure out that this is {\itshape Vdd}. You can +interrupt {\bfseries getnode} by typing {\bfseries \^{}C} (control-C), and {\bfseries getnode} will +return the ``best'' name found so far. There is no way to tell if this +is an alias or the name RSIM expects unless {\bfseries getnode} is allowed +to complete. To prevent these long name searches, you can tell {\bfseries getnode} +to quit its search when certain names are encountered. Type: + +\starti + \ii {\bfseries :getnode abort Vdd} +\endi + +Select the blue strip on top of the circuit and type {\bfseries :getnode}. +You'll notice that the name was found very quickly this time, and {\bfseries getnode} +tells you it aborted the search of {\itshape Vdd}. +The name returned may be an alias instead of the the one RSIM expects. +In this example, the abort option to {\bfseries getnode} +will abort the name search on any name found where the last component of +the node name is {\itshape Vdd}. That is, {\bfseries getnode} will stop if a name such as +``miasma/crock/{\itshape Vdd}'' or ``hooha/{\itshape Vdd}'' is found. + +You can abort the +search on more than one name; now type {\bfseries :getnode abort GND}. Select the +bottom horizontal blue strip in the layout, and type {\bfseries :getnode}. The +search will end almost immediately, since this node is {\itshape GND}. +{\bfseries getnode} will now abort any node name search when either {\itshape Vdd} +or {\itshape GND} is found. The search can be aborted on any name; just +supply the name as an argument to {\bfseries getnode abort}. +Remember that only the last part of the name counts when aborting +the name search. To cancel all name aborts and resume normal name +searches, type: + +\starti + \ii {\bfseries :getnode abort} +\endi + +{\bfseries getnode} will no longer abort the search on any names, and it will +churn away unless interrupted by the user. + +\section{RSIM Tool} + +You can also use the mouse to help you run RSIM under Magic. Instead +of typing node names, you can just select nodes with the mouse, tell +RSIM what to do with these nodes, and let Magic do the rest. Change +tools by typing: + +\starti + \ii {\bfseries :tool rsim} +\endi + +or hit the space bar until the cursor changes to a pointing hand. The +RSIM tool is active when the cursor is this hand. The left and +right mouse buttons have the same have the same function as the box +tool. You use these buttons along with the select +command to select the nodes. The middle button is +different from the box tool. Clicking the middle button will cause +all nodes in the selection to have their logical values displayed in the +layout and printed in the text window. +We need to +have RSIM running in order to use this tool. Start RSIM by typing: + +\starti + \ii {\bfseries :startrsim tut11a.rsm} +\endi + +The {\bfseries .rsm} file you simulate must correspond to the root cell +of the layout. If not, Magic will generate node names that +RSIM will not understand and things won't work properly. +If any paint is changed in the circuit, +the circuit must be re-extracted and a new {\bfseries .rsm} file must be +created to reflect the changes in the circuit. + +Magic will print the RSIM header, but you return to Magic instead +of remaining in RSIM. This is an alternate way of starting up RSIM, +and it is +equivalent to the command {\bfseries rsim tut11a.rsm} and typing a period ({\bfseries .}) +to the RSIM prompt, escaping to Magic. We need to initialize RSIM, so +get to RSIM by typing {\bfseries :rsim} and you'll see the RSIM prompt again. +As before, type {\bfseries @ tut11a.cmd} to the RSIM prompt to initialize +everything. Type a period ({\bfseries .}) to return to Magic. We are now +ready to use the RSIM tool. + +As mentioned earlier, {\bfseries tut11a} is a 4-bit counter. We'll reset +the counter and then step it using the RSIM tool. Locate the square +blue area on the top right corner of the circuit. Place the cursor over this +region and select it. Now click the middle button, and the RSIM value +for this node will be printed in both the text window and in the +layout. Magic/RSIM will report that the node is named {\itshape hold} +and that its current value is {\itshape X}. +You may not be able to see the node value in the layout if you +are zoomed out too far. Zoom in closer about this node if necessary. +Try selecting other nodes, singly or in groups and click the middle +button to display their values. This is an easy way to probe nodes +when debugging a circuit. + +Select {\itshape hold} again (the blue square). +This node must be a ``1'' before resetting the circuit. Make sure this is +the only node in the current selection. Type: + +\starti + \ii {\bfseries :simcmd h} +\endi + +to set it to a ``1''. Step the clock by typing: + +\starti + \ii {\bfseries :simcmd c} +\endi + +Click the middle button and you will see that the node has been +set to a ``1.'' The Magic command {\bfseries simcmd} will take the selected +nodes and use them as RSIM input. These uses of {\bfseries simcmd} +are like typing the RSIM commands {\itshape h hold} followed by +{\itshape c}. The arguments given to {\bfseries simcmd} are normal RSIM commands, and +{\bfseries simcmd} will apply the specified RSIM command to each node in +the current selection. +Try RSIM commands on this node (such as +{\itshape ?} or {\itshape d}) by using the command as an +argument to {\bfseries simcmd}. + +You can enter RSIM interactively +at any time +by simply typing {\bfseries :rsim}. To continue using the RSIM tool, +escape to Magic by typing a period ({\bfseries .}) to the RSIM prompt. + +The node {\itshape RESET{\_}B} must be set to a ``0''. This node is the +red square area at the middle right of the circuit. Place the cursor +over this node and select it. Type +the Magic commands {\bfseries :simcmd l} followed by {\bfseries :simcmd c} to +set the selected node to a ``0''. Click the middle mouse button to +check that this node is now ``0''. Step the clock once more to +ensure the counter is reset. Do this using the {\bfseries :simcmd c} +command. + +The outputs of this counter are the four vertical purple strips at the +bottom of the circuit. +Zoom in if necessary, select each of these +nodes, and click the middle button to check that all are ``0''. Each of +these four nodes is labeled {\itshape bit{\_}x}. If they are all not ``0'', +check the circuit to make sure {\itshape hold=1} and {\itshape RESET{\_}B=0}. +Assuming these nodes are at their correct value, you can now +simulate the counter. Set {\itshape RESET{\_}B} to a ``1'' by selecting it (the +red square) and then typing {\bfseries :simcmd h}. Step the +clock by typing {\bfseries :simcmd c}. Using the same procedure, set +the node {\itshape hold} (the blue square) to a ``0''. + +We'll watch the output bits of this counter as it runs. Place the +box around all four outputs (purple strips at the bottom) and zoom +in so their labels are visible. Select one of the outputs by +placing the cursor over it and typing {\bfseries s}. Add the other +three outputs to the selection by placing the cursor over each +and typing {\bfseries S}. These four nodes should be the only +ones in the selection. Click the middle mouse button to display +the node values. Step the clock by typing {\bfseries :simcmd c}. Click +the middle button again to check the nodes. Repeat stepping +the clock and displaying the outputs several times, and you'll +see the outputs sequence as a counter. If you also follow the text on +the screen, you'll also see that the outputs are also being watched. + +You may have +noticed that the results are printed very quickly +if the middle button is clicked a second time without +changing the selection. This +is because the node names +do not have to be recomputed if the selection remains unchanged. +Thus, you can increase the performance of this tool by minimizing +selection changes. +This can be accomplished by adding other nodes to the current selection +that you are intending to check. + +To erase all the RSIM value labels from the layout, clear the +selection by typing: + +\starti + \ii {\bfseries :select clear} +\endi + +and then click the middle mouse button. The RSIM labels do not +affect the cell modified flag, nor will they be written in the {\bfseries .mag} +file. When you're finished using RSIM, resume +RSIM by typing {\bfseries :rsim} and then quit it by typing +a {\bfseries q} to the RSIM prompt. +Quitting Magic before quitting RSIM will also quit RSIM. + +We've used a few macros to lessen the typing necessary for the RSIM tool. +The ones commonly used are: + +\starti + \ii {\bfseries :macro h ``simcmd h''} \\ + \ii {\bfseries :macro l ``simcmd l''} \\ + \ii {\bfseries :macro k ``simcmd c''} +\endi + +\end{document} diff --git a/doc/latexfiles/tut2.tex b/doc/latexfiles/tut2.tex new file mode 100644 index 00000000..e368bc2f --- /dev/null +++ b/doc/latexfiles/tut2.tex @@ -0,0 +1,855 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 2 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#2: Basic Painting and Selection} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape John Ousterhout} \\ + \vspace*{0.5in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + {\itshape (Updated by others, too.)} \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :box, :clockwise, :copy, :erase, :findbox :grid, :label, \\ + \> :layers, :macro, :move, :paint, :redo, :save, :select, \\ + \>:sideways, :undo, :upsidedown, :view, :what, :writeall, :zoom +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> a, A, c, d, \^{}D, e, E, g, G, q, Q, r, R, s, S, t, T, u, U, v, w, W, z, Z, 4 +\endi + +\vspace*{0.75in} +\section{Cells and Paint} + +In Magic, a circuit layout is a hierarchical collection +of {\itshape cells}. Each cell contains three things: +colored shapes, called {\itshape paint}, that define the circuit's structure; +textual {\itshape labels} attached to the paint; and +{\itshape subcells}, which are instances of other cells. The paint +is what determines the eventual function of the VLSI circuit. Labels +and subcells are a convenience for you in managing +the layout and provide a way of communicating information +between various synthesis and analysis tools. This tutorial +explains how to create and edit paint and labels in simple +single-cell designs, using the basic painting commands. +``Magic Tutorial \#3: Advanced Painting (Wiring and Plowing)'' +describes some more advanced features for manipulating paint. +For information on how to build up cell +hierarchies, see ``Magic Tutorial \#4: Cell Hierarchies''. + +\section{Painting and Erasing} + +Enter Magic to edit the cell {\bfseries tut2a} (type {\bfseries magic tut2a} +to the Unix shell; follow the directions in ``Tutorial \#1: Getting +Started'' if you have any problems with this). The {\bfseries tut2a} +cell is a sort of palette: it shows a splotch of each of several +paint layers and gives the names that Magic uses for the layers. + +The two basic layout operations are painting and erasing. They +can be invoked using the {\bfseries :paint} and {\bfseries :erase} +long commands, or using the buttons. The easiest way to paint +and erase is with the mouse buttons. To paint, +position the box over the area +you'd like to paint, then move the cursor over a color +and click the middle mouse button. To erase +everything in an area, place the box over the area, move the +cursor over a blank spot, and click the middle mouse button. +Try painting and erasing various colors. If the screen gets +totally messed up, you can always exit Magic and restart it. +While you're painting, white dots may occasionally appear +and disappear. These are design rule violations detected +by Magic, and will be explained in ``Magic Tutorial \#6: Design +Rule Checking''. You can ignore them for now. + +It's completely legal to paint one layer on top of another. +When this happens, one of three things may occur. In some +cases, the layers are independent, so what you'll see is +a combination of the two, as if each were a transparent colored +foil. This happens, for example, if you paint metal1 (blue) on +top of polysilicon (red). In other cases, when you paint one +layer on top of another you'll get something different from +either of the two original layers. For example, painting +poly on top of ndiff produces ntransistor (try +this). In still other cases the +new layer replaces the old one: this happens, for example, +if you paint a pcontact on top of ntransistor. +Try painting different layers on top of each other to see +what happens. The meaning of the various layers is discussed +in more detail in Section 11 below. + +There is a second way of erasing paint that allows you to +erase some layers without affecting others. This is the +macro {\bfseries \^{}D} (control-D, for ``{\bfseries D}elete paint''). To use it, +position the box over the area to be erased, then move +the crosshair over a splotch of paint containing the +layer(s) you'd like to erase. Type {\bfseries \^{}D} key on +the text keyboard: the colors underneath the cursor will +be erased from the area underneath the box, but no other +layers will be affected. Experiment around with the {\bfseries \^{}D} +macro to try different combinations of paints and erases. +If the cursor is over empty space then the {\bfseries \^{}D} +macro is equivalent to the middle mouse button: it erases +everything. + +You can also paint and erase using the long commands + +\starti + \ii {\bfseries :paint} {\itshape layers} \\ + \ii {\bfseries :erase} {\itshape layers} +\endi + +In each of these commands {\itshape layers} is one or more layer +names separated by commas (you can also use spaces for separators, +but only if you enclose the entire list in double-quotes). Any +layer can be abbreviated as long as the abbreviation is +unambiguous. For example, {\bfseries :paint poly,metal1} will +paint the polysilicon and metal1 layers. The macro {\bfseries \^{}D} +is predefined by Magic to be {\bfseries :erase \$} ({\bfseries \$} is a +pseudo-layer that means ``all layers underneath the cursor''). + +\section{Undo} + +There are probably going to be times when you'll do things that +you'll later wish you hadn't. Fortunately, Magic has an +undo facility that you can use to restore things after you've +made mistakes. The command + +\starti + \ii {\bfseries :undo} +\endi + +(or, alternatively, the macro {\bfseries u}) will undo the effects of +the last command you invoked. +If you made a mistake several commands back, you can type +{\bfseries :undo} several times to undo successive commands. +However, there is a limit to all this: Magic only remembers +how to undo the last ten or so commands. If you +undo something and then decide you wanted it after all, you +can undo the undo with the command + +\starti + \ii {\bfseries :redo} +\endi + +({\bfseries U} is a macro for this command). Try making a few paints +and erases, then use {\bfseries :undo} and {\bfseries :redo} to work +backwards and forwards through the changes you made. + +\section{The Selection} + +Once you have painted a piece of layout, there are several commands +you can invoke to modify the layout. Many of them are based on +the {\itshape selection}: you select one or more pieces of the design, +and then perform operations such as copying, deletion, and rotation +on the selected things. +To see how the selection works, load cell {\bfseries tut2b}. You +can do this by typing {\bfseries :load tut2b} if you're still in Magic, +or by starting up Magic with the shell command {\bfseries magic tut2b}. + +The first thing to do is to learn how to select. +Move the cursor over the upper portion of the +L-shaped blue area in {\bfseries tut2b}, and type {\bfseries s}, which +is a macro for {\bfseries :select}. The box +will jump over to cover the vertical part of the ``L''. This +operation selected a chunk of material. Move the box away from +the chunk, and you'll see that a thin white outline is left +around the chunk to show that it's selected. Now move the cursor +over the vertical red bar on the right of the cell and type {\bfseries s}. +The box will move over that bar, and the selection highlighting will +disappear from the blue area. + +If you type {\bfseries s} several times without moving the cursor, +each command selects a slightly larger piece of material. Move the +cursor back over the top of the blue ``L'', and type {\bfseries s} three +times without moving the cursor. The first {\bfseries s} selects a +chunk (a rectangular region all of the same type of material). The +second {\bfseries s} selects a {\itshape region} (all of the +blue material in the region underneath the cursor, rectangular or not). +The third {\bfseries s} selects a {\itshape net} (all of the material that is +electrically connected to the original chunk; this includes the +blue metal, the red polysilicon, and the contact that connects them). + +The macro {\bfseries S} (short for {\bfseries :select more}) is just like {\bfseries s} +except that it adds on to the selection, rather than replacing it. +Move the cursor over the vertical red bar on the right +and type {\bfseries S} to see how this works. You can also type {\bfseries S} +multiple times to add regions and nets to the selection. + +If you accidentally type {\bfseries s} or {\bfseries S} when the cursor is +over space, you'll select a cell ({\bfseries tut2b} in this case). +You can just undo this for now. Cell selection will be discussed +in ``Magic Tutorial \#4: Cell Hierarchies''. + +You can also select material by area: place the box +around the material you'd like to select and type {\bfseries a} (short +for {\bfseries :select area}). This will select all of the material +underneath the box. +You can use the macro {\bfseries A} to add material to the selection +by area, and you can use the long command + +\starti + \ii {\bfseries :select }[{\bfseries more}]{\bfseries area} {\itshape layers} +\endi + +to select only material on certain layers. Place the box around +everything in {\bfseries tut2b} and type {\bfseries :select area metal1} +followed by {\bfseries :select more area poly}. + +If you'd like to clear out the selection without modifying any +of the selected material, you can use the command + +\starti + \ii {\bfseries :select clear} +\endi + +or type the macro {\bfseries C}. You can clear out just a portion of +the selection by typing {\bfseries :select less} or {\bfseries :select less +area} {\itshape layers}; the former deselects paint in the order that +{\bfseries :select} selects paint, while the latter deselects +paint under the box (just as {\bfseries :select area} selects paint +under the box). +For a synopsis of all the options +to the {\bfseries :select} command, type + +\starti + \ii {\bfseries :select help} +\endi + + +\section{Operations on the Selection} + +Once you've made a selection, there are a number of operations you +can perform on it: + +\starti + \ii {\bfseries :delete} \\ + \ii {\bfseries :move }[{\itshape direction} [{\itshape distance}]] \\ + \ii {\bfseries :stretch }[{\itshape direction} [{\itshape distance}]] \\ + \ii {\bfseries :copy} \\ + \ii {\bfseries :upsidedown} \\ + \ii {\bfseries :sideways} \\ + \ii {\bfseries :clockwise }[{\itshape degrees}] \\ +\endi + +The {\bfseries :delete} command deletes everything that's selected. +Watch out: {\bfseries :delete} is different from {\bfseries :erase}, which erases +paint from the area underneath the box. +Select the red bar on the right in {\bfseries tut2b} and type {\bfseries d}, +which is a macro for {\bfseries :delete}. Undo the deletion with the +{\bfseries u} macro. + +The {\bfseries :move} command picks up both the box +and the selection and moves them so that the lower-left corner of +the box is at the cursor location. Select the red bar on the right +and move it so that it falls on top of the vertical part of +the blue ``L''. You can use {\bfseries t} (``{\bfseries t}ranslate'') as a macro +for {\bfseries :move}. Practice moving various things around the screen. +The command {\bfseries :copy} and its macro {\bfseries c} are just like +{\bfseries :move} except that a copy of the selection is left behind at +the original position. + +There is also a longer form of the {\bfseries :move} command that you +can use to move the selection a precise amount. For example, +{\bfseries :move up 10} will move the selection (and the box) up +10 units. The +{\itshape direction} argument can be any direction like {\bfseries left}, +{\bfseries south}, {\bfseries down}, etc. See the Magic manual page for +a complete list of the legal directions. The macros {\bfseries q}, +{\bfseries w}, {\bfseries e}, and {\bfseries r} are defined to move the selection +left, down, up, and right (respectively) by one unit. + +The {\bfseries :stretch} command is similar to {\bfseries :move} except that +it stretches and erases as it moves. {\bfseries :stretch} does not +operate diagonally, so if you use the cursor to indicate where +to stretch to, Magic will either stretch up, down, left, or right, +whichever is closest. The {\bfseries :stretch} command moves the selection +and also does two additional things. First, for each piece of paint +that moves, {\bfseries :stretch} will erase that layer from the region that +the paint passes through as it moves, in order to clear material out +of its way. Second, if the back edge of a piece of selected paint touches +non-selected material, one of the two pieces of paint is stretched to +maintain the connection. The macros {\bfseries Q}, {\bfseries W}, {\bfseries E}, and {\bfseries R} +just like +the macros {\bfseries q}, etc. described above for {\bfseries :move}. The macro +{\bfseries T} is predefined to {\bfseries :stretch}. +To see how stretching works, select the horizontal +piece of the green wire in {\bfseries tut2b} and type {\bfseries W}, then {\bfseries E}. +Stretching only worries about material in front of and behind the +selection; it ignores material to the sides (try the {\bfseries Q} and {\bfseries R} +macros to see). You can use plowing (described in Tutorial \#3) if this is a +problem. + +The command {\bfseries :upsidedown} will flip the selection upside +down, and {\bfseries :sideways} flips the selection sideways. Both +commands leave the selection so it occupies the same total area +as before, but with the contents flipped. The command +{\bfseries :clockwise} will rotate the selection clockwise, leaving the +lower-left corner of the new selection at the same place as the +lower-left corner of the old selection. {\itshape Degrees} +must be a multiple of 90, and defaults to 90. + +At this point you know enough to do quite a bit of damage +to the {\bfseries tut2b} cell. Experiment with the selection +commands. Remember that you can use {\bfseries :undo} to back +out of trouble. + +\section{Labels} + +Labels are pieces of text attached to the paint of a cell. +They are used to provide information to other tools that will +process the circuit. Most labels are node names: they provide +an easy way of referring to nodes in tools such as routers, simulators, +and timing analyzers. Labels may also be used for other purposes: +for example, some labels are treated as {\itshape attributes} that +give Crystal, the timing analyzer, information about the +direction of signal flow through transistors. + +Load the cell {\bfseries tut2c} and place a cross in the middle of +the red chunk (to make a cross, position the lower-left corner +of the box with the left button and then click the right button +to place the upper-right corner on top of the lower-left corner). +Then type +type the command {\bfseries :label test}. A new label will appear +at the position of the box. The complete syntax of the {\bfseries :label} +command is + +\starti + \ii {\bfseries :label }[{\itshape text }[{\itshape position }[{\itshape layer}]]] +\endi + +{\itshape Text} must be supplied, but the other arguments can be +defaulted. If {\itshape text} has any spaces in it, then it must +be enclosed in double quotes. {\itshape Position} tells where +the text should be displayed, relative to the point of the +label. It may be any of {\bfseries north}, {\bfseries south}, {\bfseries east}, +{\bfseries west}, {\bfseries top}, {\bfseries bottom}, {\bfseries left}, +{\bfseries right}, {\bfseries up}, {\bfseries down}, {\bfseries center}, +{\bfseries northeast}, {\bfseries ne}, {\bfseries southeast}, {\bfseries se}, +{\bfseries southwest}, {\bfseries sw}, {\bfseries northwest}, {\bfseries nw}. +For example, if {\bfseries ne} is given, the text will be displayed above and +to the right of the label point. If no {\itshape position} is given, +Magic will pick a position for you. {\itshape Layer} tells which paint +layer to attach the label to. If {\itshape layer} covers the entire +area of the label, then the label will be associated with the +particular layer. If {\itshape layer} is omitted, or if it doesn't +cover the label's area, Magic initially associates the label with +the ``space'' layer, then checks to see if there's a layer that covers the +whole area. If there is, Magic moves the label to that layer. +It is generally a bad idea to place labels +at points where there are several paint layers, since it will +be hard to tell which layer the label is attached to. +As you edit, Magic will ensure that labels are only +attached to layers that exist everywhere under the label. +To see how this works, +paint the layer pdiff (brown) over the label you just +created: the label will +switch layers. Finally, erase poly over the area, and +the label will move again. + +Although many labels are point labels, this need not be the case. +You can label any rectangular area by setting the box to that +area before invoking the label command. This feature is used for +labelling terminals for the router (see below), and for labelling tiles used +by Mpack, the tile packing program. {\bfseries Tut2c} has examples of +point, line, and rectangular labels. + +All of the selection commands apply to labels as well as paint. +Whenever you select paint, the labels attached to that paint +will also be selected. Selected labels are highlighted in white. +Select some of the chunks of paint in {\bfseries tut2c} +to see how the labels are selected too. When you use +area selection, labels will only be selected if they are completely +contained in the area being selected. If you'd like to select +{\itshape just} a label without any paint, make the box into a cross +and put the cross on the label: {\bfseries s} and {\bfseries S} will select +just the label. + +There are several ways to erase a label. One way is to select and then +delete it. Another way is to erase the paint that the label is attached +to. If the paint is erased all around the label, then Magic will delete +the label too. Try attaching a +label to a red area, then paint blue over the red. +If you erase blue the label stays (since it's attached +to red), but if you erase the red then the label is deleted. + +You can also erase labels using the {\bfseries :erase} command +and the pseudo-layer {\bfseries labels}. The command + +\starti + \ii {\bfseries :erase labels} +\endi + +will erase all labels that lie completely within the area of the box. +Finally, you can erase a label by making +the box into a cross on top of the label, then clicking the middle +button with the cursor over empty space. Technically, this will +erase all paint layers and labels too. However, since the +box has zero area, erasing paint has no effect: only the labels +are erased. + +\section{Labelling Conventions} + +When creating labels, Magic will permit you +to use absolutely any text whatsoever. However, many +other tools, and even parts of Magic, expect label names +to observe certain conventions. Except for the special cases +described below, labels shouldn't contain any of the characters +``/\$@!\^{}''. Spaces, control characters, or parentheses +within labels are probably a bad idea too. +Many of the programs that process Magic output +have their own restrictions on label names, so you should +find out about the restrictions that apply at your site. +Most labels are node +names: each one gives a unique identification to a set of things that +are electrically connected. There are two kinds of node +names, local and global. Any label that ends in ``!'' +is treated as a global node name; it will be assumed +that all nodes by this name, anywere in any cell in a layout, are +electrically connected. The most common global names are +{\bfseries Vdd!} and {\bfseries GND!}, the power rails. You should +always use these names exactly, since many other tools +require them. Nobody knows why ``GND!'' is all in capital letters +and ``Vdd!'' isn't. + +Any label that does not end in ``!'' or any of the other +special characters discussed below is a local node name. +It refers to a node within that particular cell. Local +node names should be unique within the cell: there shouldn't +be two electrically distinct nodes with the same name. +On the other hand, it is perfectly legal, and sometimes +advantageous, to give more than one name to the same node. +It is also legal to use the same local node name in different +cells: the tools will be able to distinguish between them +and will not assume that they are electrically connected. + +The only other labels currently understood by the tools +are {\itshape attributes}. Attributes are pieces of text associated +with a particular piece of the circuit: they are not node +names, and need not be unique. For example, an attribute +might identify a node as a chip input, or it might identify +a transistor terminal +as the source of information for that transistor. Any label +whose last character is ``@'', ``\$'', or ``\^{}'' is an attribute. There +are three different kinds of attributes. Node attributes are +those ending with ``@''; they are associated with particular +nodes. Transistor source/drain attributes are those ending in ``\$''; +they are associated with particular terminals of a transistor. +A source or drain attribute must be attached to the channel region +of the transistor and must fall exactly on the source or drain +edge of the transistor. The third kind of attribute is a +transistor gate attribute. It ends in ``\^{}'' and is attached to +the channel region of the transistor. +To see examples of attributes and node names, edit the cell +{\bfseries tut2d} in Magic. + +Special conventions apply to labels for routing terminals. The standard +Magic router (invoked by {\bfseries :route}) +ignores all labels except for those on the edges of cells. (This restriction +does not apply to the gate-array router, Garoute, or to the interactive +router, Iroute). If you expect to use the +standard router to connect to a particular node, +you should place the label for that node on its outermost edge. +The label should not be a point label, but should instead be +a horizontal or vertical line covering the entire edge of the +wire. The router will choose a connection point somewhere +along the label. +A good rule of thumb is to label all nodes that enter or leave +the cell in this way. For more details on how labels are used +by the standard router, see ``Magic Tutorial \#7: Netlists and Routing''. +Other labeling conventions are used by the Garouter and Irouter, consult +their respective tutorials for details. + +\section{Files and Formats} + +Magic provides a variety of ways to save your cells on +disk. Normally, things are saved in a special +Magic format. Each +cell is a separate file, and the name of the file is +just the name of the cell with {\bfseries .mag} appended. For +example, the cell {\bfseries tut2a} is saved in file +{\bfseries tut2a.mag}. To save cells on disk, invoke the +command + +\starti + \ii {\bfseries :writeall} +\endi + +This command will run through each of the cells that you have +modified in this editing session, and ask you what to do with +the cell. Normally, you'll type {\bfseries write}, or just hit the +return key, in which case the cell will be written back +to the disk file from which it was read (if this is a new cell, +then you'll be asked for a name for the cell). If you type +{\bfseries autowrite}, then Magic will write out all the cells that have +changed without asking you what to do on a cell-by-cell basis. +{\bfseries Flush} will cause Magic to delete its internal copy of the cell +and reload the cell from the disk copy, thereby expunging all edits +that you've made. {\bfseries Skip} will pass on to the next cell without +writing this cell (but Magic still remembers that it has +changed, so the next time you invoke {\bfseries :writeall} Magic +will ask about this cell again). {\bfseries Abort} will stop +the command immediately without writing or checking any more cells. + +{\bfseries IMPORTANT NOTE:} Unlike vi and other text editors, Magic +doesn't keep checkpoint files. This means that if the system +should crash in the middle of a session, you'll lose all changes +since the last time you wrote out cells. It's a good idea to +save your cells frequently during long editing sessions. + +You can also save the cell you're currently editing with the command + +\starti + \ii {\bfseries :save} {\itshape name} +\endi + +This command will append ``.mag'' to {\itshape name} and save the cell you +are editing in that location. If you don't provide a +name, Magic will use the cell's name (plus the ``.mag'' +extension) as the file name, and it will prompt you for +a name if the cell hasn't yet been named. + +Once a cell has been saved on disk you can edit it by +invoking Magic with the command + +\starti + \ii {\bfseries magic} {\itshape name} +\endi + +where {\itshape name} is the same name you used to save the +cell (no ``.mag'' extension). + +Magic can also read and write files in CIF and Calma Stream formats. +See ``Magic Tutorial \#9: Format Conversion for CIF and Calma'' +for details. + +\section{Plotting} + +Magic can generate hardcopy plots of layouts in four ways: postscript +(color), versatec (black-and-white or color), gremlin, and pixels +(a generalized pixel-file that can be massaged in many ways). +To plot part of your design in PostScript, place the box around the +part you'd like to plot and type + +\starti + \ii {\bfseries :plot postscript} +\endi + +This will generate a plot of the area of the box. Everything +visible underneath the box will appear in more-or-less the same way +in the plot. {\itshape Width} specifies how wide the plot will be, in +inches. Magic will scale the plot so that the area of the box comes +out this wide. The default for {\itshape width} is the width of the +plotter (if {\itshape width} is larger than the plotter width, it's +reduced to the plotter width). If {\itshape layers} is given, it +specifies exactly what information is to be plotted. Only those +layers will appear in the plot. The special ``layer'' {\bfseries labels} +will enable label plotting. + +The second form is for driving printers like color Versatecs. +It is enabled by setting the {\itshape color} plot parameter to +{\itshape true}. A table of stipples for the primary colors (black, cyan, +magenta abd yellow) is given in the technology file. When the +{\itshape plot} command is given, four rasters (one for each of the colors) +are generated, separated with the proper control sequences for the printer. +Otherwise, operation is exactly as for the black-and-white case. + +The third form of plotting is for generating Gremlin-format files, +which can then be edited with the Gremlin drawing system or +included in documents processed by Grn and Ditroff. The command +to get Gremlin files is + +\starti + \ii {\bfseries :plot gremlin} {\itshape file }[{\itshape layers}] +\endi + +It will generate a Gremlin-format file in {\itshape file} that describes +everything underneath the box. If {\itshape layers} is specified, it +indicates which layers are to appear in the file; otherwise everything +visible on the screen is output. The Gremlin file is output without +any particular scale; use the {\bfseries width} or {\bfseries height} commands +in Grn to scale the plot when it's printed. You should use the {\bfseries mg} +stipples when printing Magic Gremlin plots; these will produce the +same stipple patterns as {\bfseries :plot versatec}. + +Finally, the ``pixels'' style of plotting generates a file of pixel +values for the region to be plotted. This can be useful for input to +other image tools, or for generation of slides and viewgraphs for +presentations. The file consists of a sequence of bytes, three for +each pixel, written from left to right and top to bottom. Each three +bytes represent the red, green and blue values used to display the +pixel. Thus, if the upper-left-most pixel were to be red, the first +three bytes of the file would have values of 255, 0 and 0. + +The resolution of the generated file is normally 512, but can be +controlled by setting the plot parameter {\itshape pixWidth}. It must be a +multiple of 8; Magic will round up if an inappropriate value is +entered. +The height +of the file is determined by the shape of the box. In any case, the +actual resolution of the file is appended to the file name. For +example, plotting a square region, 2048 pixels across, will result in +a file named something like ``magicPlot1234a-2048-2048''. + +There are several plotting parameters used internally to Magic, such +as the width of the Versatec printer and the number of dots per inch +on the Versatec printer. You can modify most of these to work with +different printers. For details, read about the various {\bfseries :plot} +command options in the {\itshape man} page. + +\section{Utility Commands} + +There are several additional commands that you will probably find useful +once you start working on real cells. The command + +\starti + \ii {\bfseries :grid }[{\itshape spacing}] \\ + \ii {\bfseries :grid }{\itshape xSpacing ySpacing} \\ + \ii {\bfseries :grid }{\itshape xSpacing ySpacing xOrigin yOrigin} \\ + \ii {\bfseries :grid off} +\endi + +will display a grid over your layout. Initially, the grid has +a one-unit spacing. Typing {\bfseries :grid} with no arguments +will toggle the grid on and off. +If a single numerical argument is given, the grid +will be turned on, and the grid lines will be {\itshape spacing} +units apart. The +macro {\bfseries g} provides a short form for {\bfseries :grid} and {\bfseries G} +is short for {\bfseries :grid 2}. If you provide two arguments to +{\bfseries :grid}, they are the x- and y-spacings, which may be different. +If you provide four arguments, the last two specify a reference +point through which horizontal and vertical grid lines pass; the +default is to use (0,0) as the grid origin. The command {\bfseries :grid off} +always turns the grid off, regardless of whether or not is was +previously on. +When the grid is on, a small black box is displayed to mark the +(0,0) coordinate of the cell you're editing. + +If you want to create a cell that doesn't fit on the screen, +you'll need to know how to change the screen view. This +can be done with three commands: + +\starti + \ii {\bfseries :zoom }{\itshape factor} \\ + \ii {\bfseries :findbox }[{\bfseries zoom}] \\ + \ii {\bfseries :view} +\endi + +If {\itshape factor} is given to the zoom command, +it is a zoom-out factor. For example, +the command {\bfseries :zoom 2} will change the view so that there are +twice as many units across the screen as there used to be ({\bfseries Z} +is a macro for this). The +new view will have the same center as the old one. The command +{\bfseries :zoom .5} will increase the magnification so that +only half as much of the circuit is visible. + +The {\bfseries :findbox} command is used to change the view according to the box. +The command alone just moves the view (without changing the scale +factor) so that the box is in the center of the screen. If the {\bfseries zoom} +argument is given then the magnification is changed too, so that the area of +the box nearly fills the screen. {\bfseries z} is a macro for {\bfseries :findbox zoom} +and {\bfseries B} is a macro for {\bfseries :findbox}. + +The command {\bfseries :view} resets the view so that the entire cell is visible +in the window. It comes in handy if you get lost in a big layout. +The macro {\bfseries v} is equivalent to {\bfseries :view}. + +The command {\bfseries :box} prints out the size and location of the box +in case you'd like to measure something in your layout. The macro +{\bfseries b} is predefined to {\bfseries :box}. The {\bfseries :box} command can also +be used to set the box to a particular location, height, or +width. See the man page for details. + +The command + +\starti + \ii {\bfseries :what} +\endi + +will print out information about what's selected. This may be helpful +if you're not sure what layer a particular piece of material is, or +what layer a particular label is attached to. + +If you forget what a macro means, you can invoke the command + +\starti + \ii {\bfseries :macro }[{\itshape char}] +\endi + +This command will print out the long command that's associated +with the macro {\itshape char}. If you omit {\itshape char}, Magic will +print out all of the macro associations. The command + +\starti + \ii {\bfseries :macro} {\itshape char command} +\endi + +We set up {\itshape char} to be a macro for {\itshape command}, replacing the old +{\itshape char} macro if there was one. If {\itshape command} contains any spaces +then it must be enclosed in double-quotes. To see how this works, type +the command {\bfseries :macro} {\ttfamily 1 "echo You just typed the 1 key."}, +then type the 1 key. + +One of the macros, ``{\bfseries .}'', has special meaning in Magic. This +macro is always defined by the system to be the last long command +you typed. Whenever you'd like to repeat a long command, all you +have to do is use the dot macro. + +\section{What the Layers Mean} + +The paint layers available in Magic are different from those +that you may be used to in Caesar and other systems because +they don't correspond +exactly to the masks used in fabrication. We call them +{\itshape abstract layers} because they correspond to constructs +such as wires and contacts, rather than mask layers. We +also call them {\itshape logs} because they look like sticks +except that the geometry is drawn fully fleshed instead of +as lines. In Magic there +is one paint layer for each kind of conducting material +(polysilicon, ndiffusion, metal1, etc.), +plus one additional paint layer for each kind of transistor +(ntransistor, ptransistor, etc.), and, finally, one further +paint layer for each kind of contact (pcontact, ndcontact, +m2contact, etc.) Each +layer has one or more names that are +used to refer to that layer in commands. To find out the +layers available in the current technology, type the command + +\starti + \ii {\bfseries :layers} +\endi + +In addition to the mask layers, there are a few pseudo-layers +that are valid in all technologies; these are listed in +Table~\ref{pseudolayers}. +Each Magic technology also has a technology manual describing +the features of that technology, such as design rules, routing +layers, CIF styles, etc. If you haven't seen any of the technology +manuals yet, this is a good time to take a look at the one for +your process. + +\begin{table}[hb] + \begin{center} + \begin{tabular}{|l|} \hline + {\bfseries errors} (design-rule violations) \\ + {\bfseries labels} \\ + {\bfseries subcells} \\ + {\bfseries \*} (all mask layers) \\ + {\bfseries \$} (all mask layers visible under cursor) \\ \hline + \end{tabular} + \end{center} + \caption{Pseudo-layers available in all technologies.} + \label{pseudolayers} +\end{table} + +If you're used to designing with mask layers (e.g. you've +been reading the Mead-Conway book), Magic's log style +will take some getting used to. +One of the reasons for logs is to +save you work. In Magic you don't draw implants, wells, buried +windows, or contact via holes. Instead, you draw the primary +conducting layers and paint some of their overlaps with +special types such as n-transistor or polysilicon contact. +For transistors, you draw only the +actual area of the transistor channel. Magic will generate +the polysilicon and diffusion, plus any +necessary implants, when it creates a CIF file. For contacts, +you paint the contact layer in the area of overlap between +the conducting layers. Magic +will generate each of the constituent mask layers plus +vias and buried windows when it writes the CIF file. +Figure~\ref{layers1} +shows a simple cell drawn with both mask layers (as in Caesar) +and with logs (as in Magic). If you're curious about what +the masks will look like for a particular layout, you can use +the {\bfseries :cif see} command to view the mask information. + +\begin{figure}[ht] + \begin{center} + \begin{minipage}{0.3\columnwidth} + \epsfig{file=../psfigures/tut2.2.ps, height=5in} + \end{minipage} \hspace*{0.5in} + \begin{minipage}{0.5\columnwidth} + \epsfig{file=../psfigures/tut2.1.ps, height=4.0in} + \end{minipage} + \caption {An example of how the logs are used. The figure on + the left shows actual mask layers for an CMOS inverter + cell, and the figure on the right shows the layers used + to represent the cell in Magic.} + \label{layers1} + \end{center} +\end{figure} + +An advantage of the logs used in Magic is +that they simplify the design rules. Most of the formation +rules (e.g. contact structure) go away, since Magic automatically +generates correctly-formed structures when it writes CIF. +All that are left are minimum size and spacing rules, and +Magic's abstract layers result in fewer of these than there +would be otherwise. This helps to make Magic's built-in +design rule checker very fast (see ``Magic Tutorial \#6: +Design Rule Checking''), and is one of the reasons +plowing is possible. + +\end{document} diff --git a/doc/latexfiles/tut3.tex b/doc/latexfiles/tut3.tex new file mode 100644 index 00000000..66be526b --- /dev/null +++ b/doc/latexfiles/tut3.tex @@ -0,0 +1,544 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 3 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#3: Advanced Painting (Wiring and Plowing)} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape John Ousterhout} \\ + {\itshape Walter Scott} \\ + \vspace*{0.5in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + {\itshape (Updated by others, too.)} \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :array, :corner, :fill, :flush, :plow, :straighten, :tool, :wire +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> $<$space$>$ +\endi + +\vspace*{0.5in} +\section{Introduction} + +Tutorial \#2 showed you the basic facilities for placing paint and +labels, selecting, and manipulating the things that are +selected. This tutorial describes two additional facilities for +manipulating paint: wiring and plowing. These commands aren't +absolutely necessary, since you can achieve the same effect with +the simpler commands of Tutorial \#2; however, wiring and plowing +allow you to perform certain kinds of manipulations much more quickly +than you could otherwise. Wiring is described in Section 2; it +allows you to place wires by pointing at the ends of legs rather +than by positioning the box, and also provides for convenient contact +placement. Plowing is the subject of Section 3. It allows you to +re-arrange pieces of your circuit without having to worry about +design-rule violations being created: plowing automatically moves +things out of the way to avoid trouble. + +\section{Wiring} + +The box-and-painting paradigm described in Tutorial \#2 is sufficient +to create any possible layout, but it's relatively inefficient +since three keystrokes are required to paint each new area: two +button clicks to position the box and one more to paint the material. +This section describes a different painting mechanism based on +{\itshape wires}. At any given time, there is a current wiring material +and wire thickness. With the wiring interface you can create a new +area of material with a single button click: this paints a straight-line +segment of the current material and width +between the end of the previous wire segment and the cursor location. +Each additional button click adds an additional segment. The wiring +interface also makes it easy for you to place contacts. +\section{Tools} + +Before learning about wiring, you'll need to learn about tools. +Until now, when you've pressed mouse buttons in layout windows the +buttons have caused the box to change or material to be painted. +The truth is that buttons can mean different things at different times. +The meaning of the mouse buttons depends on the {\itshape current tool}. +Each tool is identified by a particular cursor shape and a +particular interpretation of the mouse buttons. Initially, the current +tool is the box tool; when the box tool is active the cursor has +the shape of a crosshair. To get information about the current tool, +you can type the long command + +\starti + \ii {\bfseries :tool info} +\endi + +This command prints out the name of the current tool and the meaning +of the buttons. Run Magic on the cell {\bfseries tut3a} and type {\bfseries :tool info}. + +The {\bfseries :tool} command can also be used to switch tools. Try this +out by typing the command + +\starti + \ii {\bfseries :tool} +\endi + +Magic will print out a message telling you that you're using the +wiring tool, and the cursor will change to an arrow shape. Use +the {\bfseries :tool info} command to see what the buttons mean now. You'll +be using the wiring tool for most of the rest of this section. The +macro `` '' (space) corresponds to {\bfseries :tool}. Try typing the space key +a few times: Magic will cycle circularly through all of the +available tools. There are three tools in Magic right now: the +box tool, which you already know about, the wiring tool, which +you'll learn about in this tutorial, and the netlist tool, which has a square +cursor shape and is used for netlist editing. ``Tutorial \#7: +Netlists and Routing'' will show you how to use the netlist tool. + +The current tool affects only the meanings of the mouse +buttons. It does not change the meanings of the long commands +or macros. This means, for example, that you can still use +all the selection commands while the wiring tool is active. +Switch tools to the wiring tool, point +at some paint in {\bfseries tut3a}, and type the {\bfseries s} macro. +A chunk gets selected just as it does with the box tool. + +\section{Basic Wiring} + +There are three basic wiring commands: selecting the wiring material, +adding a leg, and adding a contact. This section describes the +first two commands. At this point you should be editing the +cell {\bfseries tut3a} with the wiring tool active. The first step +in wiring is to pick the material and width to use for wires. +This can be done in two ways. The easiest way is to find a piece +of material of the right type and width, point to it with the +cursor, and click the left mouse button. Try this in {\bfseries tut3a} +by pointing to the label {\bfseries 1} and left-clicking. Magic prints out +the material and width that it chose, selects a square of that +material and width around the cursor, and places the box around +the square. Try pointing to various places in {\bfseries tut3a} and +left-clicking. + +Once you've selected the wiring material, the right +button paints legs of a wire. Left-click on label {\bfseries 1} to +select the red material, then move the cursor over label +{\bfseries 2} and right-click. This will paint a red wire between +{\bfseries 1} and {\bfseries 2}. The new wire leg is selected so that you +can modify it with selection commands, and the box is placed +over the tip of the leg to show you the starting point for the +next wire leg. Add more legs to the wire by right-clicking +at {\bfseries 3} and then {\bfseries 4}. Use the mouse buttons to paint +another wire in blue from {\bfseries 5} to {\bfseries 6} to {\bfseries 7}. + +Each leg of a wire must be either horizontal or vertical. If you +move the cursor diagonally, Magic will still paint a horizontal +or vertical line (whichever results in the longest new wire leg). +To see how this works, left-click on {\bfseries 8} in {\bfseries tut3a}, +then right-click on {\bfseries 9}. You'll get a horizontal leg. Now +undo the new leg and right-click on {\bfseries 10}. This time you'll +get a vertical leg. You can force Magic to paint the next +leg in a particular direction with the commands + +\starti + \ii {\bfseries :wire horizontal} \\ + \ii {\bfseries :wire vertical} +\endi + +Try out this feature by left-clicking on {\bfseries 8} in {\bfseries tut3a}, +moving the cursor over {\bfseries 10}, and typing {\bfseries :wire ho} +(abbreviations work for {\bfseries :wire} command options just as +they do elsewhere in Magic). This command will generate a +short horizontal leg instead of a longer vertical one. + +\section{Contacts} + +When the wiring tool is active, the middle mouse button places +contacts. Undo all of your changes to {\bfseries tut3a} by typing +the command {\bfseries :flush} and answering {\bfseries yes} to the +question Magic asks. This throws away all of the changes made to the +cell and re-loads it from disk. Draw a red wire leg from +{\bfseries 1} to {\bfseries 2}. Now move the cursor over the blue area and +click the middle mouse button. This has several effects. It +places a contact at the end of the current wire leg, selects the +contact, and moves the box over the selection. In addition, it changes +the wiring material and thickness to match the material you +middle-clicked. Move the cursor over {\bfseries 3} and right-click +to paint a blue leg, then make a contact to purple by middle-clicking +over the purple material. Continue by drawing a purple leg to {\bfseries 4}. + +Once you've drawn the purple leg to {\bfseries 4}, move the cursor over +red material and middle-click. This time, Magic prints an error +message and treats the click just like a left-click. +Magic only knows how to make contacts between certain combinations of +layers, which are specified in the technology file +(see ``Magic Maintainer's Manual \#2: The Technology File''). For +this technology, Magic doesn't know how to make contacts directly +between purple and red. + +\section{Wiring and the Box} + +In the examples so far, each new wire leg appeared to be +drawn from the end of the +previous leg to the cursor position. In fact, however, the new +material was drawn from the {\itshape box} to the cursor position. Magic +automatically repositions the box on each button click to help set +things up for the next leg. Using the box as the starting point +for wire legs makes it easy to start wires in places that don't +already have material of the right type and width. Suppose that you want +to start a new wire in the middle of an empty area. You can't +left-click to get the wire started there. Instead, you can left-click +some other place where there's the right material for the wire, +type the space bar twice to get back the box tool, move the box where +you'd like the wire to start, hit the space bar once more to get back +the wiring tool, and then right-click to paint the wire. Try this +out on {\bfseries tut3a}. + +When you first start wiring, you may not be able to find the right +kind of material anywhere on the screen. When this happens, you +can select the wiring material and width with the command + +\starti + \ii {\bfseries :wire type} {\itshape layer} {\itshape width} +\endi + +Then move the box where you'd like the wire to start, switch +to the wiring tool, and right-click to add legs. + +\section{Wiring and the Selection} + +Each time you paint a new wire leg or contact using the wiring +commands, Magic selects the new material just as if you had placed +the cursor over it and typed {\bfseries s}. This makes it +easy for you to adjust its position if you didn't get it right +initially. The {\bfseries :stretch} command is particularly useful +for this. In {\bfseries tut3a}, paint a wire leg in blue from {\bfseries 5} +to {\bfseries 6} (use {\bfseries :flush} to reset the cell if you've made +a lot of changes). Now type {\bfseries R} two or three times to stretch +the leg over to the right. Middle-click over purple material, +then use {\bfseries W} to stretch the contact downward. + +It's often hard to position the cursor +so that a wire leg comes out right the first time, but it's usually +easy to tell whether the leg is right once it's painted. If it's +wrong, then you can use the stretching commands to shift it over +one unit at a time until it's correct. + +\section{Bundles of Wires} + +Magic provides two additional commands that are useful for +running {\itshape bundles} of parallel wires. The commands are: + +\starti + \ii {\bfseries fill} {\itshape direction }[{\itshape layers}] \\ + \ii {\bfseries corner} {\itshape direction1 direction2 }[{\itshape layers}] +\endi + +To see how they work, load the cell {\bfseries tut3b}. The +{\bfseries :fill} comand extends a whole bunch of paint in a given direction. +It finds all paint touching +one side of the box and extends that paint to the opposite +side of the box. For example, {\bfseries :fill left} will look underneath +the right edge of the box for paint, and will extend that paint +to the left side of the box. The effect is just as if all the colors +visible underneath that edge of the box constituted a paint brush; +Magic sweeps the brush across the box in the given direction. +Place the box over the label ``Fill here'' in {\bfseries tut3b} and +type {\bfseries :fill left}. + +The {\bfseries :corner} command is similar to {\bfseries :fill} except that +it generates L-shaped wires that follow two sides of the box, +travelling first in {\itshape direction1} and then in {\itshape direction2}. +Place the box over the label ``Corner here'' in {\bfseries tut3b} and +type {\bfseries :corner right up}. + +In both {\bfseries :fill} and {\bfseries :corner}, +if {\itshape layers} isn't specified then all layers are filled. +If {\itshape layers} is given then only those layers are painted. +Experiment on {\bfseries tut3b} with the {\bfseries :fill} and {\bfseries :corner} +commands. + +When you're painting bundles of wires, it would be nice if there +were a convenient way to place contacts across the whole bundle +in order to switch to a different layer. There's no single +command to do this, but you can place one contact by hand and +then use the {\bfseries :array} command to +replicate a single contact across the whole bundle. +Load the cell {\bfseries tut3c}. This contains a bundle of wires +with a single contact already painted by hand on the bottom +wire. Type {\bfseries s} with the cursor over the contact, and +type {\bfseries S} with the cursor over the stub of purple wiring +material next to it. +Now place the box over the label ``Array'' and type the command +{\bfseries :array 1 10}. This will copy the selected contact across +the whole bundle. + +The syntax of the {\bfseries :array} command is + +\starti + \ii {\bfseries :array} {\itshape xsize ysize} +\endi + +This command makes the selection into an array of identical elements. +{\itshape Xsize} specifies how many total instances there should be +in the x-direction when the command is finished and {\itshape ysize} +specifies how many total instances there should be in the +y-direction. In the {\bfseries tut3c} example, {\bfseries xsize} was one, +so no additional copies were created in that direction; {\bfseries ysize} +was 10, so 9 additional copies were created. The box is used to +determine how far apart the elements should be: the width of the +box determines the x-spacing and the height determines the y-spacing. +The new material always appears above and to the right of the original +copy. + +In {\bfseries tut3c}, use {\bfseries :corner} to extend the purple wires and +turn them up. Then paint a contact back to blue on the leftmost +wire, add a stub of blue paint above it, and use {\bfseries :array} to +copy them across the top of the bundle. Finally, +use {\bfseries :fill} again to extend the blue bundle farther up. + +\section{Plowing} + +Magic contains a facility called {\itshape plowing} that you can +use to stretch and compact cells. The basic plowing command +has the syntax + +\starti + \ii {\bfseries :plow} {\itshape direction }[{\itshape layers}] +\endi + +where {\itshape direction} is a Manhattan direction like {\bfseries left} and +{\itshape layers} is an optional, comma-separated list of mask layers. +The plow command +treats one side of the box as if it were a plow, and shoves +the plow over to the other side of the box. For example, +{\bfseries :plow up} treats the bottom side of the box as a plow, +and moves the plow to the top of the box. + +As the plow moves, +every edge in its path is pushed ahead of it (if {\itshape layers} +is specified, then only edges on those layers are moved). +Each edge that is pushed by the plow pushes other edges ahead +of it in a way that preserves design rules, connectivity, +and transistor and contact sizes. This means that material +ahead of the plow gets compacted down to the minimum spacing +permitted by the design rules, and material that crossed the +plow's original position gets stretched behind the plow. + +You can compact a cell by placing a large plow off to one side of +the cell and plowing across the whole cell. You can open up +space in the middle of a cell by dragging a small plow across +the area where you want more space. + +To try out plowing, edit +the cell {\bfseries tut3d}, place the box over the rectangle +that's labelled ``Plow here'', and try plowing in various +directions. Also, try plowing only certain layers. +For example, with the box over the ``Plow here'' label, +try + +\starti + \ii {\bfseries :plow right metal2} +\endi + +Nothing happens. This is because there are no metal2 +{\itshape edges} in the path of the plow. If instead you had +typed + +\starti + \ii {\bfseries :plow right metal1} +\endi + +only the metal would have been plowed to the right. + +In addition to plowing with the box, you can plow the +selection. The command to do this has the following +syntax: + +\starti + \ii {\bfseries :plow selection }[{\itshape direction }[{\itshape distance}]] +\endi + +This is very similar to the {\bfseries :stretch} command: it +picks up the selection and the box and moves both so that +the lower-left corner of the box is at the cursor location. +Unlike the {\bfseries :stretch} command, though, {\bfseries :plow selection} +insures that design rule correctness and connectivity are +preserved. + +Load the cell {\bfseries tut3e} and +use {\bfseries a} to select the area underneath the label that +says ``select me''. +Then point with the cursor to the +point labelled ``point here'' and type {\bfseries :plow selection}. +Practice selecting things and plowing them. +Like the {\bfseries :stretch} command, there is also a longer +form of {\bfseries :plow selection}. For example, {\bfseries :plow selection down 5} +will plow the selection and the box down 10 units. + +Selecting a cell and plowing it is a good way to move the cell. +Load {\bfseries tut3f} and select the cell {\bfseries tut3e}. +Point to the label ``point here'' and plow the selection with +{\bfseries :plow selection}. +Notice that all connections to the cell have remained attached. +The cell you select must be in the edit cell, however. + +The plowing operation is implemented in a way that tries to +keep your design as compact as possible. To do this, it +inserts jogs in wires around the plow. In many cases, though, +the additional jogs are more trouble than they're worth. To +reduce the number of jogs inserted by plowing, type the +command + +\starti + \ii {\bfseries :plow nojogs} +\endi + +From now on, Magic will insert as few jogs as possible when +plowing, even if this means moving more material. You +can re-enable jog insertion with the command + +\starti + \ii {\bfseries :plow jogs} +\endi + +Load the cell +{\bfseries tut3d} again and try plowing it both with and without jog insertion. + +There is another way to reduce the number of jogs introduced +by plowing. +Instead of avoiding jogs in the +first place, plowing can introduce them freely but clean them +up as much as possible afterward. +This results in more dense +layouts, but possibly more jogs than if you had enabled +{\bfseries :plow nojogs}. +To take advantage of this second method +for jog reduction, re-enable jog insertion ({\bfseries :plow jogs}) +and enable jog cleanup with the command + +\starti + \ii {\bfseries :plow straighten} +\endi + +From now on, Magic will attempt to straighten out jogs after +each plow operation. To disable straightening, use the +command + +\starti + \ii {\bfseries :plow nostraighten} +\endi + +It might seem pointless to disable jog introduction +with {\bfseries :plow nojogs} at the same time +straightening is enabled with {\bfseries :plow straighten}. +While it is true that {\bfseries :plow nojogs} won't introduce +any new jogs for {\bfseries :plow straighten} to clean up, +plowing will straighten out any existing jogs after +each operation. + +In fact, there is a separate command that is sometimes +useful for cleaning up layouts with many jogs, namely +the command + +\starti + \ii {\bfseries :straighten} {\itshape direction} +\endi + +where {\itshape direction} is a Manhattan direction, e.g., {\bfseries up}, +{\bfseries down}, {\bfseries right}, or {\bfseries left}. This command +will start from one side of the box and pull jogs toward +that side to straighten them. +Load the cell {\bfseries tut3g}, +place the box over the label ``put box here'', +and type {\bfseries :straighten left}. Undo the last command +and type {\bfseries :straighten right} instead. Play around +with the {\bfseries :straighten} command. + +There is one more feature of plowing that is sometimes useful. +If you are working on a large cell and want to make sure that +plowing never affects any geometry outside of a certain area, +you can place a {\itshape boundary} around the area you want to +affect with the command + +\starti + \ii {\bfseries :plow boundary} +\endi + +The box is used to specify the area you want to affect. +After this command, subsequent plows will only affect the +area inside this boundary. + +Load the cell {\bfseries tut3h} place the box over the label +``put boundary here'', and type {\bfseries :plow boundary}. +Now move the box away. You will see the boundary +highlighted with dotted lines. Now place the box +over the area labelled ``put plow here'' and plow up. +This plow would cause geometry +outside of the boundary to be affected, so Magic +reduces the plow distance enough to prevent +this and warns you of this fact. +Now undo the last plow and remove the boundary with + +\starti + \ii {\bfseries :plow noboundary} +\endi + +Put the box over the ``put plow here'' label and plow up again. +This time there was no boundary to stop the plow, so everything +was moved as far as the height of the box. Experiment with placing +the boundary around an area of this cell and plowing. + +\end{document} diff --git a/doc/latexfiles/tut4.tex b/doc/latexfiles/tut4.tex new file mode 100644 index 00000000..66619157 --- /dev/null +++ b/doc/latexfiles/tut4.tex @@ -0,0 +1,603 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 4 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#4: Cell Hierarchies} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape John Ousterhout} \\ + \vspace*{0.5in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + {\itshape (Updated by others, too.)} \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :array, :edit, :expand, :flush, :getcell, :identify, :load, :path, + :see, :unexpand +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> x, X, \^{}X +\endi + +\vspace*{0.75in} +\section{Introduction} + +In Magic, a layout is a hierarchical collection of cells. +Each cell contains three things: paint, labels, and +subcells. Tutorial \#2 showed +you how to create and edit paint and labels. This tutorial describes +Magic's facilities for building up cell hierarchies. Strictly speaking, +hierarchical structure isn't necessary: any design that can be +represented hierarchically can also be represented ``flat'' (with +all the paint and labels in a single cell). However, many +things are greatly improved if you use a hierarchical +structure, including the +efficiency of the design tools, the speed with which you can enter +the design, and the ease with which you can modify it later. + +\section{Selecting and Viewing Hierarchical Designs} + +``Hierarchical structure'' means that each cell can +contain other cells as components. +To look at an example of a hierarchical layout, enter Magic +with the shell command {\bfseries magic tut4a}. The cell {\bfseries tut4a} +contains four subcells plus some blue paint. Two of the subcells +are instances of cell {\bfseries tut4x} and two are instances of +{\bfseries tut4y}. Initially, each subcell +is displayed in {\itshape unexpanded} form. This means that +no details of the subcell are displayed; all you see is the +cell's bounding box, plus two names inside the +bounding box. The top name is the name of the subcell (the +name you would type when invoking Magic to edit the cell). The +cell's contents are stored in a file with this name plus a {\bfseries .mag} +extension. The bottom name inside each bounding box is called an +{\itshape instance identifier}, and is used to distinguish different +instances of the same subcell. Instance id's are used for +routing and circuit extraction, and are discussed in Section 6. + +Subcells can be manipulated using the same selection mechanism +that you learned in Tutorial \#2. To select a subcell, place the +cursor over the subcell and type {\bfseries f} (``{\bfseries f}ind cell''), +which is a macro for {\bfseries :select cell}. You can also select a cell +by typing {\bfseries s} when the cursor is over a location where there's +no paint; {\bfseries f} is probably more convenient, particularly for +cells that are completely covered with paint. When you select +a cell the box will be set to the cell's bounding box, the cell's +name will be highlighted, and +a message will be printed on the text display. +All the selection operations ({\bfseries :move}, +{\bfseries :copy}, {\bfseries :delete}, etc.) apply to subcells. Try selecting +and moving the top subcell in {\bfseries tut4a}. You can also select +subcells using area selection (the {\bfseries a} and {\bfseries A} macros): +any unexpanded subcells that intersect the area of the box will +be selected. + +To see what's inside a cell instance, you must {\itshape expand} it. +Select one of the instances of {\bfseries tut4y}, then type the command + +\starti + \ii {\bfseries :expand toggle} +\endi + +or invoke the macro {\bfseries \^{}X} +which is equivalent. This causes the internals of that instance +of {\bfseries tut4y} to be displayed. If you type {\bfseries \^{}X} again, the +instance is unexpanded so you only see a bounding box again. +The {\bfseries :expand toggle} command expands all of the selected cells +that are unexpanded, and unexpands all those that are expanded. +Type {\bfseries \^{}X} a third time so that {\bfseries tut4y} is expanded. + +As you can see now, {\bfseries tut4y} +contains an array of {\bfseries tut4x} cells plus some additional +paint. In Magic, an array is a special +kind of instance containing multiple copies of the same subcell spaced +at fixed intervals. Arrays can be one-dimensional or two-dimensional. +The whole array is always treated +as a single instance: any command that operates on one element of +the array also operates on all the other elements simultaneously. +The instance identifiers for the elements of the array +are the same except for an index. Now select one of the elements +of the array and expand it. Notice that the entire array is +expanded at the same time. + +When you have expanded the array, you'll see that the paint +in the top-level cell {\bfseries tut4a} is displayed more brightly than the paint +in the {\bfseries tut4x} instances. {\bfseries Tut4a} is called +the {\itshape edit cell}, because its contents are currently editable. +The paint in the edit cell is normally displayed more brightly than other +paint to make it clear that you can change it. As long as {\bfseries tut4a} +is the edit cell, you cannot modify the paint in {\bfseries tut4x}. Try +erasing paint from the area of one of the {\bfseries tut4x} instances: +nothing will be changed. Section 4 tells how to switch the +edit cell. + +Place the cursor over one of the {\bfseries tut4x} array elements again. +At this point, the cursor is actually over three different +cells: {\bfseries tut4x} (an element of an array +instance within {\bfseries tut4y}), {\bfseries tut4y} (an +instance within {\bfseries tut4a}), and {\bfseries tut4}. +Even the topmost cell in the hierarchy is treated as an instance +by Magic. When you press +the {\bfseries s} key to select a cell, Magic initially chooses +the smallest instance visible underneath the cursor, {\bfseries tut4x} +in this case. However, if you invoke the {\bfseries s} macro +again (or type {\bfseries :select}) without moving the cursor, Magic +will step through all of the instances under the cursor in order. +Try this out. +The same is true of the {\bfseries f} macro and {\bfseries :select cell}. + +When there are many different expanded cells on the screen, +you can use the selection commands to select paint from any +of them. You can select anything that's visible, regardless of +which cell it's in. However, as mentioned above, you can only +modify paint in the edit cell. If you use {\bfseries :move} or +{\bfseries :upsidedown} or similar commands when you've selected +information outside the edit cell, the information outside +the edit cell is removed from the selection before performing +the operation. + +There are two additional commands you can use for expanding and +unexpanding cells: + +\starti + \ii {\bfseries :expand} \\ + \ii {\bfseries :unexpand} +\endi + +Both of these commands operate on the area underneath the box. +The {\bfseries :expand} command will recursively +expand every cell that intersects the box until there are no +unexpanded cells left under the box. The {\bfseries :unexpand} +command will unexpand every cell whose area intersects the box +but doesn't completely contain it. The macro {\bfseries x} is +equivalent to {\bfseries :expand}, and {\bfseries X} is +equivalent to {\bfseries :unexpand}. Try out the various expansion +and unexpansion facilities on {\bfseries tut4a}. + +\section{Manipulating Subcells} + +There are a few other commands, in addition to the selection +commands already described, that you'll need in order to +manipulate subcells. The command + +\starti + \ii {\bfseries :getcell} {\itshape name} +\endi + +will find the file {\itshape name}{\bfseries .mag} on disk, read the cell +it contains, and create an instance of that cell with +its lower-left corner aligned with +the lower-left corner of the box. +Use the {\bfseries getcell} +command to get an instance of the cell {\bfseries tut4z}. +After the {\bfseries getcell} command, the new instance is selected +so you can move it or copy it or delete it. The {\bfseries getcell} command +recognizes additional arguments that permit the cell to be positioned +using labels and/or explicit coordinates. See +the {\itshape man} page for details. + +To turn a normal instance into an array, select the +instance and then invoke the {\bfseries :array} +command. It has two forms: + +\starti + \ii {\bfseries :array} {\itshape xsize ysize} \\ + \ii {\bfseries :array} {\itshape xlo xhi ylo yhi} +\endi + +In the first form, {\itshape xsize} indicates how many elements +the array should have in the x-direction, and {\itshape ysize} +indicates how many elements it should have in the y-direction. +The spacing between elements is controlled by the box's +width (for the x-direction) and height (for the y-direction). +By changing the box size, you can space elements so that they +overlap, abut, or have gaps between them. +The elements are given indices from 0 to {\itshape xsize}-1 in +the x-direction and from 0 to {\itshape ysize}-1 in the +y-direction. The second form of the command is identical +to the first except that the elements are given indices +from {\itshape xlo} to {\itshape xhi} in the x-direction and from +{\itshape ylo} to {\itshape yhi} in the y-direction. Try making +a 4x4 array out of the {\bfseries tut4z} cell with gaps between +the cells. + +You can also invoke the {\bfseries :array} command on an +existing array to change the number of elements or +spacing. Use a size of 1 for {\itshape xsize} or {\itshape ysize} +in order to get a one-dimensional array. If there are +several cells selected, the {\bfseries :array} command will make +each of them into an array of the same size and spacing. +It also works on paint and labels: if paint and labels +are selected when you invoke {\bfseries :array}, they will be +copied many times over to create the array. Try using the array +command to replicate a small strip of paint. + +\section{Switching the Edit Cell} + +At any given time, you are editing the definition of a single +cell. This definition is called the {\itshape edit cell}. You +can modify paint and labels in the edit cell, and you can +re-arrange its subcells. You may not re-arrange or delete +the subcells of any cells other than the edit cell, nor may +you modify the paint or labels of any cells except the edit +cell. You may, however, copy information from other cells into +the edit cell, using the selection commands. +To help clarify what is and isn't modifiable, Magic +displays the paint of the edit cell in brighter colors than +other paint. + +When you rearrange subcells of the edit cell, you aren't changing the +subcells themselves. All you can do is change the way they are +used in the edit cell (location, orientation, etc.). When you +delete a subcell, nothing happens to the file containing the +subcell; the command merely deletes the instance from the edit cell. + +Besides the edit cell, there is one other special cell in Magic. +It's called the {\itshape root cell} and is the topmost cell in +the hierarchy, the one you named when you ran Magic ({\bfseries tut4a} +in this case). As you will see in Tutorial \#5, there can +actually be several root cells at any given time, one in each window. +For now, there is only a single window on the +screen, and thus only a single root cell. The window caption at +the top of the color display contains the name of the window's root +cell and also the name of the edit cell. + +Up until now, the root cell and the edit cell have been +the same. However, this need not always be the case. You can +switch the edit cell to any cell in the hierarchy by selecting +an instance of the definition you'd like to edit, and then +typing the command + +\starti + \ii {\bfseries :edit} +\endi + +Use this command to switch the edit cell to one of the {\bfseries tut4x} +instances in {\bfseries tut4a}. Its paint brightens, while +the paint in {\bfseries tut4a} becomes dim. If you want to edit +an element of an array, select the array, place the +cursor over the element you'd like to edit, then type {\bfseries :edit}. +The particular element underneath the cursor becomes the edit cell. + +When you edit a cell, you are editing the master definition of that +cell. This means that if the cell is used in several places in +your design, the edits will be reflected in all those places. +Try painting and erasing in the {\bfseries tut4x} cell that you just made +the edit cell: the modifications will appear in all of its instances. + +There is a second way to change the edit cell. This is the command + +\starti + \ii {\bfseries :load} {\itshape name} +\endi + +The {\bfseries :load} command loads a new hierarchy into the window +underneath the cursor. {\itshape Name} is the name of the root cell in +the hierarchy. If no {\itshape name} is given, a new unnamed cell is +loaded and you start editing from scratch. The {\bfseries :load} +command only changes the edit cell if there is not already +an edit cell in another window. + +\section{Subcell Usage Conventions} + +Overlaps between cells are occasionally useful to share busses +and control lines running along the edges. However, overlaps +cause the analysis tools to work much harder than they would if +there were no overlaps: wherever cells overlap, the tools have +to combine the information from the two separate cells. Thus, +you shouldn't use overlaps any more than absolutely necessary. For example, +suppose you want to create a one-dimensional array of cells that +alternates between two cell types, A and B: ``ABABABABABAB''. One +way to do this is first to make an array of A instances with large +gaps between them (``A A A A A A''), then make an array of +B instances with large gaps between them (``B B B B B B''), +and finally place one array on top of the other so that the B's +nestle in between the A's. The problem with this approach is that +the two arrays overlap almost completely, so Magic will have to +go to a lot of extra work to handle the overlaps (in this case, there +isn't much overlap of actual paint, but Magic won't know this +and will spend a lot of time worrying about it). A better solution +is to create a new cell that contains one instance of A and one +instance of B, side by side. Then make an array of the new cell. +This approach makes it clear to Magic that there isn't any real +overlap between the A's and B's. + +If you do create overlaps, you should use the overlaps only to +connect the two cells together, and not to change their structure. +This means that the overlap should not cause transistors to appear, +disappear, or change size. The result of overlapping the two subcells +should be the same electrically as if you placed the two cells apart +and then ran wires to hook parts of one cell to parts of the other. The +convention is necessary in order to be able to do hierarchical +circuit extraction easily (it makes it possible for each subcell +to be circuit-extracted independently). + +Three kinds of overlaps +are flagged as errors by the design-rule checker. First, you may +not overlap polysilicon in one subcell with diffusion in another +cell in order to create transistors. Second, you may not overlap +transistors or contacts in one cell with different kinds of transistors +or contacts in another cell (there are a few exceptions to this rule +in some technologies). Third, if contacts from different cells overlap, +they must be the same type of contact and must coincide exactly: +you may not have partial overlaps. This rule is necessary +in order to guarantee that Magic can generate CIF for fabrication. + +You will make life a lot easier on yourself (and on Magic) +if you spend a bit of time to choose a clean hierarchical structure. +In general, the less cell overlap the better. If you use extensive +overlaps you'll find that the tools run very slowly and that it's +hard to make modifications to the circuit. + +\section{Instance Identifiers} + +Instance identifiers are used to distinguish the different subcells +within a single parent. The cell definition names cannot be +used for this purpose because there could be many instances +of a single definition. Magic will create default instance +id's for you when you create new instances with the {\bfseries :get} +or {\bfseries :copy} commands. The default id for an instance will +be the name of the definition with a unique integer added on. +You can change an id by selecting +an instance (which must be a child of the edit cell) and invoking the command + +\starti + \ii {\bfseries :identify} {\itshape newid} +\endi + +where {\itshape newid} is the identifier you would like the instance +to have. {\itshape Newid} must not already be used as an instance +identifier of any subcell within the edit cell. + +Any node or instance can be described uniquely by listing a +path of instance identifiers, starting from the root cell. The +standard form of such names is similar to Unix file names. For +example, if {\bfseries id1} is the name of an instance within the +root cell, {\bfseries id2} is an instance within {\bfseries id1}, and +{\bfseries node} is a node name within {\bfseries id2}, then +{\bfseries id1/id2/node} can be used unambiguously to refer to the node. +When you select a cell, Magic prints out the complete path name +of the instance. + +Arrays are treated specially. When you use {\bfseries :identify} to +give an array an instance identifier, each element of the array +is given the instance identifier you specified, followed +by one or two array subscripts enclosed in square brackets, +e.g, {\bfseries id3[2]} or {\bfseries id4[3][7]}. When the array is +one-dimensional, there is a single subscript; when it is +two-dimensional, the first subscript is for the y-dimension +and the second for the x-dimension. + +\section{Writing and Flushing Cells} + +When you make changes to your circuit in Magic, there is +no immediate effect on the disk files that hold the cells. +You must explicitly save each cell that has changed, using +either the {\bfseries :save} command or the {\bfseries :writeall} command. +Magic keeps track of the cells that +have changed since the last time they were saved +on disk. If you try to leave Magic without saving all the +cells that have changed, the system will warn you and give +you a chance to return to Magic to save them. Magic never +flushes cells behind your back, and never throws away +definitions that it has read in. Thus, if you edit a cell +and then use {\bfseries :load} to edit another cell, the first +cell is still saved in Magic even though it doesn't appear +anywhere on the screen. If you then invoke {\bfseries :load} +a second time to go back to the first cell, you'll get the +edited copy. + +If you decide that you'd really like to discard the edits +you've made to a cell and recover the old version, there +are two ways you can do it. The first way is using the +{\bfseries flush} option in {\bfseries :writeall}. The second way is +to use the command + +\starti + \ii {\bfseries :flush }[{\itshape cellname}] +\endi + +If no {\itshape cellname} is given, then the edit cell is flushed. +Otherwise, the cell named {\itshape cellname} is flushed. The +{\bfseries :flush} command will expunge Magic's internal copy of the +cell and replace it with the disk copy. + +When you are editing large chips, Magic may claim that cells +have changed even though you haven't modified them. Whenever +you modify a cell, Magic makes changes in the parents of the +cell, and their parents, and so on up to the root of the +hierarchy. These changes record new design-rule violations, +as well as timestamp and bounding box information used by +Magic to keep track of design changes and enable fast cell +read-in. Thus, whenever you change one cell you'll generally +need to write out new copies of its parents and grandparents. +If you don't write out the parents, or if you edit a child +``out of context'' (by itself, without the parents loaded), +then you'll incur extra overhead the next time you try to edit +the parents. ``Timestamp mismatch'' warnings are printed +when you've edited cells out of context and then later go back +and read in the cell as part of its parent. These aren't serious +problems; they just mean that Magic is doing extra work to +update information in the parent to reflect the child's new state. + +\section{Search Paths} + +When many people are working on a large design, the design +will probably be more manageable if different pieces of it +can be located in different directories of the file system. +Magic provides a simple mechanism for managing designs spread +over several directories. The system maintains a {\itshape search path} +that tells which directories to search when trying to read in +cells. By default, the search path is ``.'', which means that +Magic looks only in the working directory. You can change the +path using the command + +\starti + \ii {\bfseries :path }[{\itshape searchpath}] +\endi + +where {\itshape searchpath} is the new path that Magic should use. +{\itshape Searchpath} consists of a list of directories separated +by colons. For example, the path ``.:\~{}ouster/x:a/b'' means +that if Magic is trying to read in a cell named ``foo'', it +will first look for a file named ``foo.mag'' in the current directory. +If it doesn't find the file there, it will look for a file named +``\~{}ouster/x/foo.mag'', and if that doesn't exist, then it will try +``a/b/foo.mag'' last. To find out what the current path is, type +{\bfseries :path} with no arguments. In addition to your path, this command +will print out the system cell library path (where Magic looks for +cells if it can't find them anywhere in your path), and the system +search path (where Magic looks for files like colormaps and technology +files if it can't find them in your current directory). + +If you're working on a large design, you should use the search +path mechanism to spread your layout over several directories. +A typical large chip will contain a few hundred cells; if you +try to place all of them in the same directory there will just +be too many things to manage. For example, place the datapath in one +directory, the control unit in another, the instruction buffer in +a third, and so on. Try to keep the size of each directory down +to a few dozen files. You can place the {\bfseries :path} command in +a {\bfseries .magic} file in your home directory or the directory you +normally run Magic from; this will save you from having to +retype it each time you start up (see the Magic man page to +find out about {\bfseries .magic} files). +If all you want to do is add another directory onto the end of the search +path, you can use the {\bfseries :addpath }[{\itshape directory}] command. + +Because there is only a single search path that is used everywhere +in Magic, you must be careful not to re-use the same cell name in +different portions of the chip. A common problem with large +designs is that different designers use the same name for different +cells. This works fine as long as the designers are working separately, +but when the two pieces of the design are put together using a search +path, a single copy of the cell (the one that is found first in the search +path) gets used everywhere. + +There's another caveat in the use of search paths. Magic looks for system +files in \~{}cad, but sometimes it is helpful to put Magic's system files +elsewhere. If the {\bfseries CAD{\_}HOME} shell environment variable is set, then +Magic uses that as the location of \~{}cad instead of the location in the +password file. This overrides all uses of \~{}cad within magic, including +the \~{}cad seen in the search paths printed out by {\bfseries :path}. + +\section{Additional Commands} + +This section describes a few additional cell-related commands that +you may find useful. One of them is the command + +\starti + \ii {\bfseries :select save} {\itshape file} +\endi + +This command takes the selection and writes it to disk as a new +Magic cell in the file {\itshape file}{\bfseries .mag}. You can use this command +to break up a big file into smaller ones, or to extract pieces from +an existing cell. + +The command + +\starti + \ii {\bfseries :dump} {\itshape cellName} [{\itshape labelName}] +\endi + +does the opposite of {\bfseries select save}: it copies the contents of +cell {\itshape cellName} into the edit cell, such that the lower-left +corner of label {\itshape labelName} is at the lower-left corner of the +box. The new material will also be selected. This command is similar +in form to the {\bfseries getcell} command except that it copies the contents +of the cell instead of using the cell as a subcell. There are several +forms of {\bfseries dump}; see the {\itshape man} page for details. + +The main purpose of {\bfseries dump} is to +allow you to create a library of cells representing +commonly-used structures such as standard transistor shapes +or special contact arrangements. You can then define macros +that invoke the {\bfseries dump} command to place the cells. The result +is that a single keystroke is all you need to copy one of them into the +edit cell. + +As mentioned earlier, Magic normally displays the edit cell in +brighter colors than non-edit cells. This helps to distinguish +what is editable from what is not, but may make it hard for +you to view non-edit paint since it appears paler. If you +type the command + +\starti + \ii {\bfseries :see allSame} +\endi + +you'll turn off this feature: all paint everywhere will be +displayed in the bright colors. The word {\bfseries allSame} must +be typed just that way, with one capital letter. If you'd +like to restore the different display styles, type the +command + +\starti + \ii {\bfseries :see no allSame} +\endi + +You can also use the {\bfseries :see} command to selectively disable +display of various mask layers in order to make the other ones +easier to see. For details, read about {\bfseries :see} in the +Magic man page. + +\end{document} diff --git a/doc/latexfiles/tut5.tex b/doc/latexfiles/tut5.tex new file mode 100644 index 00000000..40803492 --- /dev/null +++ b/doc/latexfiles/tut5.tex @@ -0,0 +1,465 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 5 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#5: Multiple Windows} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Robert N. Mayo} \\ + \vspace*{0.5in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + {\itshape (Updated by others, too.)} \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :center :closewindow, :openwindow, :over, :specialopen, :under, + :windowpositions +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> o, O, ``,'' +\endi + +\vspace*{0.75in} +\section{Introduction} + +A window is a rectangular viewport. +You can think of it as a magnifying glass that may be moved around +on your chip. +Magic initially displays a single window on the screen. +This tutorial will show you how +to create new windows and how to move old ones around. +Multiple windows allow you +to view several portions of a circuit at the same time, or even +portions of different circuits. + +Some operations are easier with multiple +windows. For example, let's say that you want to paint a very long line, +say 3 units by 800 units. With a single window it is hard to align +the box accurately since the magnification is not great enough. +With multiple windows, one window can show the big +picture while other windows show magnified views of the areas where the +box needs to be aligned. The box can then be positioned accurately +in these magnified windows. + +\section{Manipulating Windows} + +\subsection{Opening and Closing Windows} + +Initially Magic displays one large window. The + +\starti + \ii {\bfseries :openwindow }[{\itshape cellname}] +\endi + +command opens another window and loads the given cell. To give +this a try, start up Magic with the command {\bfseries magic tut5a}. +Then point anywhere in a Magic window and type the command +{\bfseries :openwindow tut5b} (make sure you're pointing to a +Magic window). A new window will appear and it will +contain the cell {\bfseries tut5b}. If you don't +give a {\itshape cellname} argument to {\bfseries :openwindow}, it will +open a new window on the cell containing the box, and will zoom +in on the box. The macro {\bfseries o} is predefined to {\bfseries :openwindow}. +Try this +out by placing the box around an area of {\bfseries tut5b} and then +typing {\bfseries o}. Another window will appear. You now have +three windows, all of which display pieces of layout. There +are other kinds of windows in Magic besides layout windows: you'll +learn about them later. Magic doesn't care how many windows +you have (within reason) nor how they overlap. + +To get rid of a window, point to it and type + +\starti + \ii {\bfseries :closewindow} +\endi + +or use the macro {\bfseries O}. +Point to a portion of the original window and close it. + +\subsection{Resizing and Moving Windows} + +If you have been experimenting with Magic while reading this you +will have noticed that windows opened by {\bfseries :openwindow} are all +the same size. If you'd prefer a different arrangement you can +resize your windows or move them around on the screen. The techniques +used for this are different, however, depending on what kind of +display you're using. If you are using a workstation, then you are also +running a window system such as X11 or SunView. In this case Magic's +windows are moved and resized just like the other windows you have displayed, +and you can skip the rest of this section. + +For displays like the AED family, which don't have a built-in window +package, Magic implements its own window manager. To re-arrange +windows on the screen you +can use techniques similar to those you +learned for moving the box for painting operations. +Point somewhere in the border area of a window, except for the lower left +corner, and press and hold the right button. The +cursor will change to a shape like this: + +\begin{center} + \begin{tabular}{c|c|}\hline + \hspace*{0.1in} & \hspace*{0.1in} \\ \hline + \hspace*{0.1in} & \hspace*{0.1in} \\ + \end{tabular} +\end{center} + +This indicates that you have hold of the upper right corner of the +window. Point to a new location for this corner and release the +button. The window will change shape so that the corner moves. +Now point to the border area and press and hold the left button. +The cursor will now look like: + +\begin{center} + \begin{tabular}{|c|c|}\hline + \hspace*{0.1in} & \hspace*{0.1in} \\ \hline + \hspace*{0.1in} & \hspace*{0.1in} \\ \hline + \end{tabular} +\end{center} + +This indicates that you have hold of the entire window by its lower left +window. Move the cursor and release the button. The window will move so that +its lower left corner is where you pointed. + +The other button commands for positioning the box by any of its corners +also work for windows. Just remember to point to the border of a window +before pushing the buttons. + +The middle button can be used to grow a window up to full-screen size. +To try this, click the middle button over the caption of the window. +The window will now fill the entire screen. Click in the caption again +and the window will shrink back to its former size. + +\subsection{Shuffling Windows} + +By now you know how to open, close, and resize windows. This is sufficient +for most purposes, but sometimes you want to look at a window that is covered +up by another window. The {\bfseries :underneath} and {\bfseries :over} commands help +with this. + +The {\bfseries :underneath} command moves the window that you are pointing at +underneath all of the other windows. The {\bfseries :over} command moves the +window on top of the rest. Create a few windows that overlap and then +use these commands to move them around. You'll see that overlapping windows +behave just like sheets of paper: the ones on top obscure portions of +the ones underneath. + +\subsection{Scrolling Windows} + +Some of the windows have thick bars on the left and bottom borders. +These are called {\itshape scroll bars}, and the slugs within them +are called {\itshape elevators}. The size and position of an elevator +indicates how much of the layout (or whatever is in the window) +is currently visible. +If an elevator fills its scroll bar, then all of the layout is visible +in that window. If an elevator fills only a portion of the scroll bar, +then only that portion of the layout is visible. The position of the elevator +indicates which part is visible---if it is near the bottom, +you are viewing the bottom part of the layout; +if it is near the top, you are viewing the top part of the layout. +There are scroll bars for both the vertical direction (the left scroll bar) +and the horizontal direction (the bottom scroll bar). + +Besides indicating how much is visible, the scroll bars can be used to +change the view of the window. Clicking the middle mouse button in a +scroll bar moves the elevator to that position. For example, if you +are viewing the lower half of a chip (elevator near the bottom) and you +click the middle button near the top of the scroll bar, the elevator will +move up to that position and you will be viewing the top part of your chip. +The little squares with arrows in them at the ends of the scroll bars +will scroll the view by one screenful when the middle button is clicked +on them. They are useful when you want to move exactly one screenful. +The {\bfseries :scroll} command can also be used to scroll the view +(though we don't think it's as easy to use as the scroll bars). See +the man page for information on it. + +If you only want to make a small adjustment in a window's view, you +can use the command + +\starti + \ii {\bfseries :center} +\endi + +It will move the view in the window so that the point that used to +be underneath the cursor is now in the middle of the window. The +macro {\bfseries ,} is predefined to {\bfseries :center}. + +The bull's-eye in the lower left corner of a window is used to zoom the +view in and out. Clicking the left mouse button zooms the view out +by a factor of 2, and clicking the right mouse button zooms in by a factor +of 2. Clicking the middle button here makes everything in the window +visible and is equivalent to the {\bfseries :view} command. + +\subsection{Saving Window Configurations} + +After setting up a bunch of windows you may want to save the configuration +(for example, you may be partial to a set of 3 non-overlapping windows). +To do this, type: + +\starti + \ii {\bfseries :windowpositions} {\itshape filename} +\endi + +A set of commands will be written to the file. This file can be used +with the {\bfseries :source} command to recreate the window configuration +later. (However, this only works well if you stay on the same kind +of display; if you create a file under X11 and then {\bfseries :source} +it under SunView, you might not get the same positions since the coordinate +systems may vary.) + +\section{How Commands Work Inside of Windows} + +Each window has a caption at the top. Here is an example: + +\starti + \ii {\bfseries mychip EDITING shiftcell} +\endi + +This indicates that the window contains the root cell {\bfseries mychip}, and that +a subcell of it called {\bfseries shiftcell} is being edited. You may +remember from the Tutorial \#4 that at any given +time Magic is editing exactly one cell. +If the edit cell is in another window then the caption on +this window will read: + +\starti + \ii {\bfseries mychip [NOT BEING EDITED]} +\endi + +Let's do an example to see how commands are executed within windows. +Close any layout windows that you may have on the screen and open two new +windows, each containing the cell {\bfseries tut5a}. (Use the {\bfseries :closewindow} +and {\bfseries :openwindow tut5a} commands to do this.) +Try moving the box around in one of the windows. Notice +that the box also moves in the other window. +Windows containing the same root cell are equivalent as far as +the box is concerned: if it appears in one it will appear in all, +and it can be manipulated from them interchangeably. +If you change {\bfseries tut5a} by painting or erasing portions of it you will +see the changes in both windows. +This is because both +windows are looking at the same thing: the cell {\bfseries tut5a}. +Go ahead and try some painting and erasing until you feel comfortable +with it. Try positioning one corner of the box in one window and another +corner in another window. You'll find it doesn't matter which window +you point to, all Magic knows is that you are pointing to {\bfseries tut5a}. + +These windows are independent in some respects, however. +For example, you may scroll one window around +without affecting the other window. Use the scrollbars +to give this a try. You can also expand and unexpand cells +independently in different windows. + +We have seen how Magic behaves when both windows view a single cell. +What happens when windows view different cells? To try this +out load {\bfseries tut5b} into one of the windows +(point to a window and type {\bfseries :load tut5b}). +You will see the captions on the windows change---only one +window contains the cell currently being edited. The box cannot +be positioned by placing one corner in one window and another corner +in the other window because that doesn't really make sense (try it). +However, the selection commands work between windows: you can select +information in one window and then copy it into another (this +only works if the window +you're copying into contains the edit cell; if not, you'll have +to use the {\bfseries :edit} command first). + +The operation of many Magic commands is dependent upon which window you +are pointing at. If you are used to using Magic with only one window +you may, at first, forget to point to the window that you want the +operation performed upon. For instance, if there are several windows +on the screen you will have to point to one before executing a +command like {\bfseries :grid}---otherwise you may not affect the window +that you intended! + +\section{Special Windows} + +In addition to providing multiple windows on different areas of +a layout, Magic provides several special types of windows that +display things other than layouts. For example, there are special +window types to edit netlists and to +adjust the colors displayed on the screen. One of the +special window types is described in the section below; +others are +described in the other tutorials. +The + +\starti + \ii {\bfseries :specialopen} {\itshape type }[{\itshape args}] +\endi + +command is used to create these +sorts of windows. The {\itshape type} argument tells what sort of window +you want, and {\itshape args} describe what you want loaded into that window. +The {\bfseries :openwindow} {\itshape cellname} command is really just short for the +command {\bfseries :specialopen layout} {\itshape cellname}. + +Each different type of window (layout, color, etc.) has its own +command set. If you type {\bfseries :help} in different window types, +you'll see that the commands are different. Some of the commands, +such as those to manipulate windows, are valid in all windows, but +for other commands you must make sure you're pointing to the right +kind of window or the command may be misinterpreted. For example, +the {\bfseries :extract} command means one thing in a layout window and +something totally different in a netlist window. + +\section{Color Editing} + +Special windows of type {\bfseries color} are used to edit the red, green, +and blue intensities of the colors displayed on the screen. To +create a color editing window, invoke the command + +\starti + \ii {\bfseries :specialopen color }[{\itshape number}] +\endi + +{\itshape Number} is optional; if present, it gives the octal value of +the color number whose intensities are to be edited. If {\itshape number} +isn't given, 0 is used. Try opening a color window on color 0. + +A color editing window contains 6 ``color bars'', 12 ``color pumps'' +(one on each side of each bar), plus a large rectangle at the top +of the window that displays a swatch of the color being edited +(called the ``current color'' from now on). +The color bars display the components of the current color in +two different ways. The three bars on the left display the +current color in terms of its red, green, and blue intensities +(these intensities are the values actually sent to the display). +The three bars on the right display the current color in terms +of hue, saturation, and value. Hue selects a color of +the spectrum. Saturation indicates how diluted the color is +(high saturation corresponds to a pure color, low saturation +corresponds to a color that is diluted with gray, and a saturation +of 0 results in gray regardless of hue). Value +indicates the overall brightness (a value of 0 corresponds to black, +regardless of hue or saturation). + +There are several ways to modify the current color. First, try +pressing any mouse button while the cursor is over one of the +color bars. The length of the bar, and the current color, +will be modified to reflect the mouse position. The color map +in the display is also changed, so the colors will change everywhere +on the screen that the current color is displayed. Color 0, which +you should currently be editing, is the background color. You +can also modify the current color by pressing a button while the +cursor is over one of the ``color pumps'' next to the bars. If +you button a pump with ``+'' in it, the value of the bar next +to it will be incremented slightly, and if you button the ``-'' +pump, the bar will be decremented slightly. The left button causes +a change of about 1\% in the value of the bar, and the right button +will pump the bar up or down by about 5\%. Try adjusting the bars +by buttoning the bars and the pumps. + +If you press a button while the cursor is over the current color +box at the top of the window, one of two things will happen. +In either case, nothing happens until you release the button. +Before releasing the button, move the cursor so it is over a +different color somewhere on the screen. If you pressed the +left button, then when the button is released the color underneath +the cursor becomes the new current color, and all future editing +operations will affect this color. Try using this feature to +modify the color used for window borders. If you pressed the right +button, then when the button is released +the value of the current color is copied from whatever color is +present underneath the cursor. + +There are only a few commands you can type in color windows, aside from +those that are valid in all windows. The command + +\starti + \ii {\bfseries :color }[{\itshape number}] +\endi + +will change the current color to {\itshape number}. If no {\itshape number} +is given, this command will print out the current color and its +red, green, and blue intensities. The command + +\starti + \ii {\bfseries :save }[{\itshape techStyle displayStyle monitorType}] +\endi + +will save the current color map in a file named +{\itshape techStyle}.{\itshape displayStyle}.{\itshape monitorType}{\bfseries .cmap}, +where {\itshape techStyle} is the type of technology (e.g., {\bfseries mos}), +{\itshape displayStyle} is the kind of display specified by +a {\bfseries styletype} in the {\bfseries style} section of a technology file +(e.g., {\bfseries 7bit}), and {\itshape monitorType} is the type of +the current monitor (e.g., {\bfseries std}). +If no arguments are given, +the current technology style, display style, and monitor type +are used. +The command + +\starti + \ii {\bfseries :load }[{\itshape techStyle displayStyle monitorType}] +\endi + +will load the color map from the file named +{\itshape techStyle}.{\itshape displayStyle}.{\itshape monitorType}{\bfseries .cmap} +as above. +If no arguments are given, +the current technology style, display style, and monitor type +are used. When loading color +maps, Magic looks first in the current directory, then in the +system library. + +\end{document} diff --git a/doc/latexfiles/tut6.tex b/doc/latexfiles/tut6.tex new file mode 100644 index 00000000..cfb1b928 --- /dev/null +++ b/doc/latexfiles/tut6.tex @@ -0,0 +1,377 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 6 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#6: Design-Rule Checking} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape John Ousterhout} \\ + \vspace*{0.5in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + {\itshape (Updated by others, too.)} \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection \\ + \> Magic Tutorial \#4: Cell Hierarchies +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :drc +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> y +\endi + +\vspace*{0.75in} +\section{Continuous Design-Rule Checking} + +When you are editing a layout with Magic, the system automatically +checks design rules on your behalf. Every time you paint or +erase, and every time you move a cell or change an array structure, +Magic rechecks the area you changed to be sure you haven't +violated any of the layout rules. If you do violate rules, +Magic will display little white dots in the vicinity of the +violation. This error paint will stay around until you +fix the problem; when the violation is corrected, the error paint +will go away automatically. Error paint is written to disk +with your cells and will re-appear the next time the cell is +read in. There is no way to get rid of it except to fix the +violation. + +Continuous design-rule checking means that +you always have an up-to-date picture +of design-rule errors in your layout. There is never any need +to run a massive check over the whole design unless you +change your design rules. When you +make small changes to an existing layout, you will find out +immediately if you've introduced errors, without +having to completely recheck the entire layout. + +To see how the checker works, run Magic on the +cell {\bfseries tut6a}. This cell contains several +areas of metal (blue), some of which are too close to each +other or too narrow. Try painting and erasing metal to make +the error paint go away and re-appear again. + +\section{Getting Information about Errors} + +In many cases, the reason for a design-rule violation will +be obvious to you as soon as you see the error paint. +However, Magic provides several commands for you to use +to find violations and figure what's wrong in case it +isn't obvious. All of the design-rule checking commands +have the form + +\starti + \ii {\bfseries :drc} {\itshape option} +\endi + +where {\itshape option} selects one of several commands understood +by the design-rule checker. If you're not sure why error +paint has suddenly appeared, place the box around the error paint +and invoke the command + +\starti + \ii {\bfseries :drc why} +\endi + +This command will recheck the area underneath the box, and print +out the reasons for any violations that were found. You can +also use the macro {\bfseries y} to do the same thing. Try this +on some of the errors in {\bfseries tut6a}. It's a good +idea to place the box right around the area of the error paint: +{\bfseries :drc why} rechecks the entire area under the box, so it +may take a long time if the box is very large. + +If you're working in a large cell, it may be hard to see the +error paint. To help locate the errors, select a cell +and then use the command + +\starti + \ii {\bfseries :drc find} [{\itshape nth}] +\endi + +If you don't provide the {\itshape nth} argument, the command +will place the box around one of the errors in the selected +cell, and print out the reason for the error, just as if you +had typed {\bfseries :drc why}. If you invoke the command repeatedly, +it will step through all of the errors in the selected cell. +(remember, the ``.'' macro can be used to repeat the last long +command; this will save you from having to retype {\bfseries :drc find} +over and over again). Try this out on the errors in {\bfseries tut6a}. +If you type a number for {\itshape nth}, the command will go to the +{\itshape nth} error in the selected cell, instead of the next one. +If you invoke this command with no cell selected, it searches +the edit cell. + +A third drc command is provided to give you summary information +about errors in hierarchical designs. The command is + +\starti + \ii {\bfseries :drc count} +\endi + +This command will search every cell (visible or not) that +lies underneath the box to see if any have errors in them. +For each cell with errors, {\bfseries :drc count} will print out +a count of the number of error areas. + + +\section{Errors in Hierarchical Layouts} + +The design-rule checker works on hierarchical layouts as well +as single cells. There are three overall rules that describe the +way that Magic checks hierarchical designs: + +\begin{enumerate} + \item The paint in each cell must obey all the design rules by itself, + without considering the paint in any other cells, including + its children. + + \item The combined paint of each cell and all of its descendants + (subcells, sub-subcells, etc.) must be consistent. If a + subcell interacts with paint or with other subcells in a way + that introduces a design-rule violation, an error will appear + in the parent. In designs with many levels of + hierarchy, this rule is applied separately to each + cell and its descendants. + + \item Each array must be consistent by itself, without considering + any other subcells or paint in its parent. If the neighboring + elements of an array interact to produce a design-rule violation, + the violation will appear in the parent. +\end{enumerate} + +To see some examples of interaction errors, edit the cell +{\bfseries tut6b}. This cell doesn't make sense electrically, +but illustrates the features of the hierarchical checker. +On the left are two subcells that are +too close together. In addition, the subcells are too close to +the red paint in the top-level cell. Move the subcells and/or +modify the paint to make the +errors go away and reappear. On the right side of {\bfseries tut6b} is +an array whose elements interact to produce a design-rule +violation. Edit an element of the array to make the +violation go away. When there are interaction errors between +the elements of an array, the errors always appear near one of the +four corner elements of the array (since the array spacing is uniform, +Magic only checks interactions near the corners; if these +elements are correct, all the ones in the middle must be correct +too). + +It's important to remember that each of the three overall rules +must be satisfied independently. This may sometimes result in +errors where it doesn't seem like there should be any. Edit +the cell {\bfseries tut6c} for some examples of this. On the +left side of the cell there is a sliver of paint in the parent +that extends paint in a subcell. Although the +overall design is correct, the sliver of paint in the parent +is not correct by itself, as required by the first overall +rule above. On the right side of {\bfseries tut6c} is an array +with spacing violations between the array elements. Even though the +paint in the parent masks some of the problems, +the array is not consistent by itself so errors +are flagged. The three overall rules are more conservative +than strictly necessary, but +they reduce the amount of rechecking Magic must do. For example, +the array rule allows Magic to deduce the correctness of an +array by looking only at the corner elements; if paint from the +parent had to be considered in checking arrays, it would be necessary +to check the entire array since there might be parent paint masking +some errors but not all (as, for example, in {\bfseries tut6c}). + +Error paint appears in different cells in the hierarchy, depending +on what kind of error was found. Errors resulting from paint in +a single cell cause error paint to appear +in that cell. Errors resulting from interactions and arrays appear +in the parent of the interacting cells or array. Because of the +way Magic makes interaction checks, errors can sometimes ``bubble +up'' through the hierarchy and appear in multiple cells. When +two cells overlap, Magic checks this area by copying all the paint +in that area from both cells (and their descendants) into a buffer +and then checking the buffer. Magic is unable to tell the difference +between an error from one of the subcells and an error that comes +about because the two subcells overlap incorrectly. This means that +errors in an interaction area of a cell may also appear in the +cell's parent. Fixing the error in the subcell will cause the error +in the parent to go away also. + +\section{Turning the Checker Off} + +We hope that in most cases the checker will run so quickly and +quietly that you hardly know it's there. However, there will +probably be some situations where the checker is irksome. This +section describes several ways to keep the checker out of your +hair. + +If you're working on a cell with lots of design-rule violations +the constant redisplay caused by design-rule checking may get +in your way more than it helps. This is particularly true if +you're in the middle of a large series of changes and don't care +about design-rule violations until the changes are finished. +You can stop the redisplay using the command + +\starti + \ii {\bfseries :see no errors} +\endi + +After this command is typed, design-rule errors will no longer +be displayed on the screen. The design-rule checker will continue +to run and will store error information internally, but it won't +bother you by displaying it on the screen. When you're +ready to see errors again, type + +\starti + \ii {\bfseries :see errors} +\endi + +There can also be times when it's not the redisplay that's +bothersome, but the amount of CPU time the checker takes to recheck +what you've changed. +For example, if a large subcell is moved to overlap +another large subcell, the entire overlap area will have to be +rechecked, and this could take several minutes. If the prompt +on the text screen is a ``]'' character, it means that the +command has completed but the checker hasn't caught up +yet. You can invoke new commands while the checker is +running, and the checker will suspend itself long +enough to process the new commands. + +If the checker takes too long to interrupt itself and +respond to your commands, you have several options. +First, you can hit the interrupt key (often \^{}C) on the keyboard. +This will stop the checker immediately and wait for your next +command. As soon as you issue a command or push a mouse button, +the checker will start up again. To turn the checker off +altogether, type the command + +\starti + \ii {\bfseries :drc off} +\endi + +From this point on, the checker will not run. Magic will +record the areas that need rechecking but won't do the +rechecks. If you save your file and quit Magic, the information +about areas to recheck will be saved on disk. The next time +you read in the cell, Magic will recheck those areas, unless +you've still got the checker turned off. There is nothing +you can do to make Magic forget about areas to recheck; +{\bfseries :drc off} merely postpones the recheck operation to a +later time. + +Once you've turned the checker off, you have two ways to make +sure everything has been rechecked. The first is to type the +command + +\starti + \ii {\bfseries :drc catchup} +\endi + +This command will run the checker and wait until everything +has been rechecked and errors are completely up to date. +When the command completes, the checker will still be enabled +or disabled just as it was before the command. +If you get tired of waiting for {\bfseries :drc catchup}, +you can always hit the interrupt key to abort the command; +the recheck areas will be remembered for later. To turn the +checker back on permanently, invoke the command + +\starti + \ii {\bfseries :drc on} +\endi + +\section{Porting Layouts from Other Systems} + +You should not need to read this section if you've created +your layout from scratch using Magic or have read it from +CIF using Magic's CIF or Calma reader. However, if you are +bringing into Magic a layout that was created using a +different editor or an old version of Magic that didn't +have continuous checking, read on. You may also need to +read this section if you've changed the design rules in +the technology file. + +In order to find out about errors in a design that wasn't +created with Magic, you must force Magic +to recheck everything in the design. Once this global recheck +has been done, Magic will use its continuous checker to deal +with any changes you make to the design; you should +only need to do the global recheck once. To make the global recheck, +load your design, place the box around the entire design, +and type + +\starti + \ii {\bfseries :drc check} +\endi + +This will cause Magic to act as if the entire area under the +box had just been modified: it will recheck that entire area. +Furthermore, it will work its way down through the hierarchy; +for every subcell found underneath the box, it will recheck +that subcell over the area of the box. + +If you get nervous that a design-rule violation might somehow have been +missed, you can use {\bfseries :drc check} to force any area +to be rechecked at any time, even for cells that were +created with Magic. However, this should never be +necessary unless you've changed the design rules. If the +number of errors in the layout ever changes +because of a {\bfseries :drc check}, it is a bug in Magic and you +should notify us immediately. + +\end{document} diff --git a/doc/latexfiles/tut7.tex b/doc/latexfiles/tut7.tex new file mode 100644 index 00000000..108f4a37 --- /dev/null +++ b/doc/latexfiles/tut7.tex @@ -0,0 +1,904 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 7 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#7: Netlists and Routing} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape John Ousterhout} \\ + \vspace*{0.5in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + {\itshape (Updated by others, too.)} \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection \\ + \> Magic Tutorial \#3: Advanced Painting (Wiring and Plowing) \\ + \> Magic Tutorial \#4: Cell Hierarchies \\ + \> Magic Tutorial \#5: Multiple Windows \\ +\endi + +{\noindent\bfseries\large Netlist Commands introduced in this tutorial:} +\starti + \> :extract, :flush, :ripup, :savenetlist, :trace, :writeall +\endi + +{\noindent\bfseries\large Layout Commands introduced in this tutorial:} +\starti + \> :channel, :route +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (none)} +\endi + +\vspace*{0.75in} +\section{Introduction} + +This tutorial describes how to use Magic's automatic routing +tools to make interconnections between subcells in a design. In +addition to the standard Magic router, which is invoked by the {\bfseries route} +command and covered in this tutorial, two +other routing tools are available. A gate-array router {\itshape Garouter} +permits user specified channel definitions, terminals in the interior +of cells, and route-throughs across cells. To learn about the gate-array +router read this first then +``Magic Tutorial \#12: Routing Gate Arrays''. Finally Magic +provides an interactive maze-router that takes graphic hints, the +{\itshape Irouter}, that +permits the user to control the overall path of routes while leaving +the tedious details to Magic. The {\itshape Irouter} is documented in +``Magic Tutorial \#10: The Interactive Router''. + +The standard Magic router provides an {\itshape obstacle-avoidance} +capability: if there is mask material in +the routing areas, the router can work under, over, or +around that material to complete the connections. This means +that you can pre-route key signals by hand and have Magic +route the less important signals automatically. In addition, +you can route power and ground by hand (right now we don't have +any power-ground routing tools, so you {\itshape have} +to route them by hand). + +The router {\itshape only} makes connections between +subcells; to make point-to-point connections between pieces of layout within +a single cell you should use the wiring command described +in ``Magic Tutorial \#3: Advanced Painting (Wiring and Plowing) '' or +the maze router described in ``Magic Tutorial \#10: The Interactive Router''. +If you only need to make a few connections you are probably better off doing +them manually. + +The first step in routing is to tell Magic what should be connected +to what. This information is contained in a file called a {\itshape netlist}. +Sections 2, 3, 4, and 5 describe how to create and modify netlists using +Magic's interactive netlist editing tools. +Once you've created a netlist, the next step is to invoke the +router. Section 6 shows how to do this, and gives a brief summary +of what goes on inside the routing tools. Unless your design is +very simple and has lots of free space, the routing probably won't +succeed the first time. Section 7 describes the feedback provided +by the routing tools. Sections 8 and 9 discuss how you can modify your design +in light of this feedback to improve its routability. +You'll probably need to iterate a few times until the routing is successful. + +\section{Terminals and Netlists} + +A netlist is a file that describes a set of desired connections. +It contains one or more {\itshape nets}. Each net names a +set of {\itshape terminals} that should all be wired together. +A terminal is simply a label attached to a piece of mask material within +a subcell; it is distinguishable from ordinary labels within a subcell by its +presence within a netlist file and by certain characteristics +common to terminals, as described below. + +The first step in building a netlist is to label the terminals in +your design. Figure 1 shows an example. Each label should +be a line or rectangle running along the edge of the cell (point terminals +are not allowed). +The router will make a connection to the cell somewhere along a +terminal's length. +If the label isn't at the edge of the cell, +Magic will route recklessly across the cell to reach the terminal, +taking the shortest path between the terminal and a routing channel. +It's almost always a good idea to arrange for terminal labels to +be at cell edges. The label must be at least as wide as the minimum width +of the routing material; the wider you make the label, the more flexibility +you give the router to choose a good point to connect to the terminal. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tut7.1.ps, width=0.5\columnwidth} + \caption{An example of terminal labels. Each terminal + should be labeled with a line or rectangle along the + edge of the cell.} + \end{center} +\end{figure} + +Terminal labels must be attached to mask material that connects +directly to one of Magic's two routing layers (Routing layers are defined +in Magic's technology file). +For example, in the SCMOS process +where the routing layers are metal1 and metal2, diffusion +may not be used as a terminal since neither of the routing +layers will connect directly to it. On the other hand, a terminal +may be attached to diffusion-metal1 contact, since the metal1 routing layer +will connect properly to it. +Terminals can have arbitrary names, except that they should not +contain slashes (``/'') or the substring ``feedthrough'', and should not +end in ``@'', ``\$'', or ``\^{}''. +See Tutorial \#2 for a complete description of labeling conventions. + +For an example of good and bad terminals, edit the cell {\bfseries tut7a}. +The cell doesn't +make any electrical sense, but contains several good and bad +terminals. +All the terminals with names like {\bfseries bad1} are incorrect or +undesirable for one of the reasons given above, and those with +names like {\bfseries good4} are acceptable. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tut7.2.ps, width=0.7\columnwidth} + \caption{The netlist menu.} + \end{center} +\end{figure} + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|l|l|} \hline + Button & Action \\ \hline + Current Text & Left-click: prompt for more labels \\ + & Right-click: advance to next label \\ \hline + Placer & Left-click: place label \\ + & Right-click: change label text position \\ \hline + Pumps & Left-click: decrement number \\ + & Right-click: increment number \\ \hline + Find & Search under box, highlight labels \\ + & matching current text \\ \hline + Current Netlist & Left-click: prompt for new netlist name \\ + & Right-click: use edit cell name as netlist name \\ \hline + Verify & Check that wiring matches netlist (same as \\ + & typing {\bfseries :verify} command) \\ \hline + Print & Print names of all terminals in selected net \\ + & (same as typing {\bfseries :print} command) \\ \hline + Terms & Place feedback areas on screen to identify all terminals \\ + & in current netlist (same as {\bfseries :showterms} command) \\ + \hline + Cleanup & Check current netlist for missing labels and nets \\ + & with less than two terminals (same as typing \\ \hline + & {\bfseries :cleanup} command) \\ + No Net & Delete selected net (same as {\bfseries :dnet} command) \\ + \hline + Show & Highlight paint connected to material under box \\ + & (same as typing {\bfseries :shownet} command) \\ \hline + \end{tabular} + \caption{A summary of all the netlist menu button actions.} + \end{center} +\end{table} + +If you create two or more terminal labels with the same name in the same cell +the router will assume that they are electrically equivalent (connected +together within the cell). +Because of this, when routing the net it will feel free to connect to +whichever one of the terminals is most convenient, and ignore the others. +In some cases the router may take advantage of electrically equivalent +terminals by using {\itshape feed throughs}: entering a cell at one terminal to make +one connection, and exiting through an equivalent terminal on the way to make +another connection for the same net. + +\section{Menu for Label Editing} + +Magic provides a special menu facility to assist you in placing terminal labels +and editing netlists. To make the menu appear, invoke the Magic command + +\starti + \ii {\bfseries :specialopen netlist} +\endi + +A new window will appear in the lower-left corner of the screen, +containing several rectangular areas on a purple background. Each +of the rectangular areas is called a {\itshape button}. Clicking +mouse buttons inside the menu buttons will invoke various +commands to edit labels and netlists. +Figure 2 shows a diagram of the netlist menu and Table I summarizes +the meaning of button clicks in various menu items. +The netlist menu can be grown, shrunk, and moved just like any other +window; see ``Magic Tutorial \#5: Multiple Windows'' for details. +It also has its own private set of commands. To see what commands +you can type in the netlist menu, move the cursor over the menu and +type + +\starti + \ii {\bfseries :help} +\endi + +You shouldn't need to type commands in the netlist menu very often, +since almost everything you'll need to do can be done using +the menu. See Section 9 for a description of a few of the commands you +can type; the complete set is described in the manual +page {\itshape magic(1)}. One of the best uses for the commands is so +that you can define macros for them and avoid having to go back and +forth to the menu; look up the {\bfseries :send} command in the man page +to see how to do this. +The top half of the +menu is for placing labels and the bottom half is for editing +netlists. This section describes the +label facilities, and Section 4 describes the netlist facilities. + +The label menu makes it easy for you to enter lots +of labels, particularly when there are many labels that are the +same except for a number, e.g. {\bfseries bus1}, {\bfseries bus2}, {\bfseries bus3}, +etc. There are four sections to the label menu: the current text, +the placer, two pumps, and the {\bfseries Find} button. To place labels, +first click the left mouse button over the current text rectangle. +Then type one or more labels on the keyboard, one per +line. You can use this mechanism to enter several labels at once. +Type return twice to signal the end of +the list. At this point, the first of the labels you typed will +appear in the current text rectangle. + +To place a label, position the box over the area you want to label, +then click the left mouse button inside one of the squares of the +placer area. A label will be created with the current text. +Where you click in the placer determines where the label text +will appear relative to the label box: for example, clicking the left-center +square causes the text to be centered just to the left of the box. +You can place many copies of the same label by moving the box and +clicking the placer area again. You can +re-orient the text of a label by clicking the right mouse button +inside the placer area. For example, if you would like to +move a label's text so that it appears centered above the label, +place the box over the label and right-click the top-center placer +square. + +If you entered several labels at once, only the first appears in +the current text area. However, you can advance to the next label +by right-clicking inside the current text area. In this way you +can place a long series of labels entirely with the mouse. Try +using this mechanism to add labels to {\bfseries tut7a}. + +The two small buttons underneath the right side of the current +text area are called pumps. To see how these work, enter a label +name containing a number into the current text area, for example, +{\bfseries bus1}. When you do this, the ``1'' appears in the left +pump. Right-clicking the pump causes the number to increment, +and left-clicking the pump causes the number to decrement. This +makes it easy for you to enter a series of numbered signal names. +If a name has two numbers in it, the second number will appear in +the second pump, and it can be incremented or decremented too. +Try using the pumps to place a series of numbered names. + +The last entry in the label portion of the menu is the {\bfseries Find} +button. This can be used to locate a label by searching for +a given pattern. If you click the {\bfseries Find} button, Magic +will use the current text as a pattern and +search the area underneath the box for a label whose name +contains the pattern. Pattern-matching is done in the same +way as in {\itshape csh}, using the special characters ``*'', +``?'', ``\\'', ``['', and ``]''. Try this on {\bfseries tut7a}: +enter ``good*'' into the current text area, place the box around +the whole cell, then click on the ``Find'' button. For each of +the good labels, a feedback area will be created with white +stripes to highlight the area. The {\bfseries :feedback find} command +can be used to step through the areas, and {\bfseries :feedback clear} +will erase the feedback information from the screen. The {\bfseries :feedback} +command has many of the same options as {\bfseries :drc} for getting +information about feedback areas; see the Magic manual page for +details, or type {\bfseries :feedback help} for a synopsis of the options. + + +\section{Netlist Editing} + +After placing terminal labels, the next step is to specify the connections +between them; this is called netlist editing. +The bottom half of the netlist menu is used for editing netlists. +The first thing you must do is to specify the netlist you want +to edit. Do this by clicking in the current netlist box. If +you left-click, Magic will prompt you for the netlist name and +you can type it at the keyboard. If you right-click, Magic will +use the name of the edit cell as the current netlist name. In +either case, Magic will read the netlist from disk if it exists +and will create a new netlist if there isn't currently a netlist +file with the given name. Netlist +files are stored on disk with a ``.net'' extension, which is +added by Magic when it reads and writes files. You can +change the current netlist by clicking the current +netlist button again. Startup +Magic on the cell {\bfseries tut7b}, open the netlist +menu, and set the current netlist to {\bfseries tut7b}. Then +expand the subcells in {\bfseries tut7b} so that you can see +their terminals. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|l|l|} \hline + Button & Action \\ \hline + Left & Select net, using nearest terminal to cursor. \\ \hline + Right & Toggle nearest terminal into or out of \\ + & current net. \\ \hline + Middle & Find nearest terminal, join its net with the \\ + & current net. \\ \hline + \end{tabular} + \caption{The actions of the mouse buttons when the terminal tool is in use.} + \end{center} +\end{table} + +Netlist editing is done with the netlist tool. If you haven't +already read ``Tutorial \#3: Advanced Painting (Wiring and Plowing)'', +you should read it now, up through Section 2.1. Tutorial \#3 +explained how to change the current tool by using the space macro +or by typing {\bfseries :tool}. Switch tools to the netlist tool (the +cursor will appear as a thick square). + +When the netlist tool is in use the left, right, and middle +buttons invoke select, toggle, and join operations respectively +(see Table II). +To see how they work, move the cursor over the terminal +{\bfseries right4} in the top subcell of {\bfseries tut7b} and click +the left mouse button (you may have to zoom in a bit to see the +labels; terminals are numbered in clockwise order: {\bfseries right4} +is the fourth terminal from the top on the right side). This +causes the net containing that +terminal to be selected. Three hollow white squares will appear +over the layout, marking the terminals that are supposed +to be wired together into {\bfseries right4}'s net. Left-click +over the {\bfseries left3} terminal in the same subcell to select its net, +then select the {\bfseries right4} net again. + +The right button is used to toggle terminals into or out of the +current net. If you right-click over a terminal that is in the +current net, then it is removed from the current net. If you +right-click over a terminal that isn't in the current net, it +is added to the current net. A single terminal can only be in +one net at a time, so if a terminal is already in a net when +you toggle it into another net then Magic will +remove it from the old net. Toggle the terminal {\bfseries top4} +in the bottom cell out of, then back into, the net containing +{\bfseries right4}. Now toggle {\bfseries left3} in the bottom cell +into this net. Magic warns you because it had to remove {\bfseries left3} +from another net in order to add it to {\bfseries right4}'s net. Type +{\bfseries u} to undo this change, then left-click on {\bfseries left3} to +make sure it got restored to its old net by the undo. All of +the netlist-editing operations are undo-able. + +The middle button is used to merge two nets together. If you +middle-click over a terminal, all the terminals in its net are +added to the current net. Play around with the three buttons +to edit the netlist {\bfseries tut7b}. + +Note: the router does not make connections to terminals in the +top level cell. +It only works with terminals in subcells, or sub-subcells, etc. +Because of this, the netlist editor does not permit you to select +terminals in the top level cell. +If you click over such a terminal Magic prints an error message +and refuses to make the selection. + +If you left-click over a terminal that is not currently in a net, +Magic creates a new net automatically. If you didn't +really want to make a new net, you have several choices. Either +you can toggle the terminal out of its own net, you can undo the +select operation, or you can click the {\bfseries No Net} button in +the netlist menu (you can do this even while the cursor is +in the square shape). The {\bfseries No Net} button removes all terminals +from the current net and destroys the net. It's a bad idea to +leave single-net terminals in the netlist: the router will treat +them as errors. + +There are two ways to save netlists on disk; these are similar +to the ways you can save layout cells. If you type + +\starti + \ii {\bfseries :savenetlist }[{\itshape name}] +\endi + +with the cursor over the netlist menu, +the current netlist will be saved on disk in the file {\itshape name}.{\bfseries net}. +If no {\itshape name} is typed, the name of the current netlist is used. +If you type the command + +\starti + \ii {\bfseries :writeall} +\endi + +then Magic will step through all the netlists that have been +modified since they were last written, asking you if +you'd like them to be written out. If you try to leave Magic +without saving all the modified netlists, Magic will warn you +and give you a chance to write them out. + +If you make changes to a netlist and then decide you don't want them, +you can use the {\bfseries :flush} netlist command to throw away +all of the changes and re-read the netlist from its disk file. +If you create netlists using a text editor or some other program, +you can use {\bfseries :flush} after you've modified the netlist file +in order to make sure that Magic is using the most up-to-date +version. + +The {\bfseries Print} button in the netlist menu will print out on +the text screen the names of all the terminals in the current +net. Try this for some of the nets in {\bfseries tut7b}. +The official name of a terminal looks +a lot like a Unix file name, consisting of a bunch of fields +separated by slashes. Each field except the last is the +id of a subcell, and the last field is the name of the terminal. +These hierarchical names provide unique names for each terminal, +even if the same terminal name is re-used in different cells or +if there are multiple copies of the same cell. + +The {\bfseries Verify} button will check the paint of the edit cell +to be sure it implements the connections specified in the +current netlist. Feedback areas are created to show +nets that are incomplete or nets that are shorted together. + +The {\bfseries Terms} button will cause Magic to generate a feedback +area over each of the terminals in the current netlist, so +that you can see which terminals are included in the netlist. +If you type the command {\bfseries :feedback clear} in a layout +window then the feedback will be erased. + +The {\bfseries Cleanup} button is there as a convenience to help +you cleanup your netlists. If you click on it, Magic will +scan through the current netlist to make sure it is reasonable. +{\bfseries Cleanup} looks for two error conditions: terminal names +that don't correspond to any labels in the design, and nets +that don't have at least two terminals. When it finds either +of these conditions it prints a message and gives you the +chance to either delete the offending terminal (if you type +{\bfseries dterm}), delete the offending net ({\bfseries dnet}), skip the +current problem without modifying the netlist and continue +looking for other problems ({\bfseries skip}), or abort the {\bfseries Cleanup} +command without making any more changes ({\bfseries abort}). + +The {\bfseries Show} button provides an additional mechanism for displaying +the paint in the net. If you place the box over a piece +of paint and click on {\bfseries Show}, Magic will highlight all of the +paint in the net under the box. This is similar to pointing at the net and +typing {\bfseries s} three times to select the net, except that {\bfseries Show} +doesn't select the net (it uses a different mechanism to highlight it), +and {\bfseries Show} will trace through all cells, expanded or not (the +selection mechanism only considers paint in expanded cells). Once you've +used {\bfseries Show} to highlight a net, the only way to make the highlighting +go away is to place the box over empty space and invoke {\bfseries Show} again. +{\bfseries Show} is an old command that pre-dates the selection interface, +but we've left it in Magic because some people find it useful. + + +\section{Netlist Files} + +Netlists are stored on disk in ordinary text files. +You are welcome to edit those files by hand or to +write programs that generate the netlists automatically. +For example, a netlist might be generated by a schematic +editor or by a high-level simulator. See the manual page +{\itshape net(5)} for a description of netlist file format. + + +\section{Running the Router} + +Once you've created a netlist, it is relatively easy to invoke +the router. First, place the box around the area you'd like +Magic to consider for routing. No terminals outside this area +will be considered, and Magic will not generate any paint more than +a few units outside this area (Magic may use the next routing +grid line outside the area). Load {\bfseries tut7d}, {\bfseries :flush} the +netlist if you made any changes to it, set the box to the bounding +box of the cell, and then invoke the router using the command: + +\starti + \ii {\bfseries :route} +\endi + +When the command completes, the netlist should be routed. +Click the {\bfseries Verify} netlist button to make sure the connections +were made correctly. Try deleting a piece from one of the +wires and verify again. Feedback areas should appear to +indicate where the routing was incorrect. Use the {\bfseries :feedback} +command to step through the areas and, eventually, to delete +the feedback ({\bfseries :feedback help} gives a synopsis of the command +options). + +If the router is unable to complete the connections, it will +report errors to you. +Errors may be reported in several ways. For some +errors, such as non-existent terminal names, messages will +be printed. For other errors, cross-hatched feedback +areas will be created. Most of the feedback areas have +messages similar to ``Net shifter/bit[0]/phi1: Can't make +bottom connection.'' To see the message associated with a feedback +area, place the box over the feedback area and type {\bfseries :feedback why}. +In this case the message means that for some +reason the router was unable to connect the specified net (named +by one of its terminals) within one of the routing channel. The +terms ``bottom'', ``top'', etc. may be misnomers because Magic +sometimes rotates channels before routing: the names refer to the +direction at the time the channel was routed, not the direction in +the circuit. However, the location of the feedback area indicates +where the connection was supposed to have been made. + +You've probably noticed by now that the router sometimes +generates unnecessary wiring, such as inserting extra +jogs and U-shapes in wires (look next to {\bfseries right3} in +the top cell). These jogs are particularly noticeable in small examples. +However, the router actually does {\itshape better} on larger +examples: there will still be a bit of extra wire, but it's +negligible in comparison to the total wire length on a large +chip. +Some of this wire is necessary and important: +it helps the router to avoid several problem situations that would cause +it to fail on more difficult examples. +However, you can use the {\bfseries straighten} command described +in ``Magic Tutorial \#3: Advanced Painting (Wiring and Plowing)'' +to remove unnecessary jogs. +Please don't judge the +router by its behavior on small examples. On the other hand, if +it does awful things on big examples, we'd like to know about it. + +All of the wires placed by the router are of the same width, +so the router won't be very useful for power and ground wiring. + +When using the Magic router, +you can wire power and ground by hand before +running the router. The router will be able to work around +your hand-placed connections to make the connections in the +netlist. If there are certain key signals that you want to +wire carefully by hand, you can do this too; the router will +work around them. Signals that you route by hand should not +be in the netlist. {\bfseries Tutorial7b} has an example of ``hand +routing'' in the form of a piece of metal in the middle of +the circuit. Undo the routing, and try modifying the metal +and/or adding more hand +routing of your own to see how it affects the routing. + +The Magic router has a number of options useful for +getting information about the routing and setting routing parameters. +You need to invoke the {\bfseries route} command once for each option you +want to specify; then type {\bfseries :route} with no options to +start up the router with whatever parameters you've set. The {\bfseries viamin}, +option which invokes a routing post-pass is, of course, +invoked AFTER routing. +Type {\bfseries :route netlist} {\itshape file} to specify a netlist for the routing +without having to open up the netlist menu. +The {\bfseries metal} option lets you toggle metal maximization on and off; +if metal maximization is turned on, the router converts routing +from the alternate routing layer (``poly'') to the +preferred routing layer (``metal'') wherever possible. +The {\bfseries vias} option controls metal maximization by specifying how many +grid units of ``metal'' conversion make it worthwhile to place vias; +setting this to 5 means that metal maximization will add extra vias only +if 5 or more grid units of ``poly'' can be converted to ``metal''. +View the current technology's router parameters with the {\bfseries tech} option. +The {\bfseries jog}, {\bfseries obstacle}, and {\bfseries steady} options let you view and +change parameters to control the channel router (this feature is for +advanced users). +The {\bfseries viamin} option invokes a via minimization algorithm +which reduces the number of vias in a routed layout. +This can be used as a post-processing step to improve the quality +of the routing. This may be useful even when using another router +to do the actual routing. Finally, show all parameter values +with the {\bfseries settings} option. +The options and their actions are summarized in Table III. + + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|l|l|} \hline + Option & Action \\ \hline + {\bfseries end} & + Print the channel router end constant \\ + {\bfseries end}{\itshape real} & + Set the channel router end constant \\ \hline + {\bfseries help} & + Print a summary of the router options \\ \hline + {\bfseries jog} & + Print the channel router minimum jog length \\ + {\bfseries jog} {\itshape int} & + Set the minimum jog length, measured in grid units \\ \hline + {\bfseries metal} & + Toggle metal maximization on or off \\ \hline + {\bfseries netlist} & + Print the name of the current net list \\ + {\bfseries netlist} {\itshape file} & + Set the current net list \\ \hline + {\bfseries obstacle} & + Print the channel router obstacle constant \\ + {\bfseries obstacle} {\itshape real} & + Set the obstacle constant \\ \hline + {\bfseries settings} & + Print a list of all router parameters \\ \hline + {\bfseries steady} & + Print the channel router steady net constant \\ + {\bfseries steady} {\itshape int} & + Set the steady net constant, measured in grid units \\ \hline + {\bfseries tech} & + Print router technology information \\ \hline + {\bfseries vias} & + Print the metal maximization via limit \\ + {\bfseries vias} {\itshape int} & + Set the via limit \\ \hline + {\bfseries viamin} & + Minimize vias in a routed layout. \\ \hline + \end{tabular} + \end{center} + \caption{A summary of all of Magic router options.} +\end{table} + + +\section{How the Router Works} + +In order to make the router produce the best possible results, it +helps to know a little bit about how it works. +The router runs in three stages, called {\itshape channel definition}, +{\itshape global routing}, and {\itshape channel routing}. In the channel +definition phase, Magic divides the area of the edit cell +into rectangular routing areas called channels. The channels +cover all the space under the box except the areas occupied by +subcells. +All of Magic's routing goes in the channel areas, except that +stems (Section 8.2) may extend over subcells. + +To see the channel structure that Magic chose, place +the box in {\bfseries tut7d} as if you were going to route, then type the command + +\starti + \ii {\bfseries :channel} +\endi + +in the layout window. +Magic will compute the channel structure +and display it on the screen as a collection of feedback areas. +The channel structure is displayed as white rectangles. +Type {\bfseries :feedback clear} when you're through looking at them. + +The second phase of routing is global routing. In the global +routing phase, Magic considers each net in turn and chooses +the sequence of channels the net must pass through in order +to connect its terminals. The {\itshape crossing points} (places +where the net crosses from one channel to another) are chosen +at this point, but not the exact path through each channel. + +In the third phase, each channel is considered separately. +All the nets passing through that channel are examined at once, +and the exact path of each net is decided. Once the routing +paths have been determined, paint is added to the edit cell +to implement the routing. + +The router is grid-based: all wires are placed on +a uniform grid. For the standard nMOS process the grid spacing +is 7 units, and for the standard SCMOS process it is 8 units. +If you type {\bfseries :grid 8} after routing {\bfseries tut7b}, you'll +see that all of the routing lines up with its lower and left +sides on grid lines. Fortunately, you don't have to make +your cell terminals line up on even grid boundaries. During +the routing Magic generates {\itshape stems} that connect your +terminals up to grid lines at the edges of channels. Notice +that there's space left by Magic between the subcells and +the channels; this space is used by the stem generator. + + +\section{What to do When the Router Fails} + +Don't be surprised if the router is unable to make all the connections +the first time you try it on a large circuit. Unless you have +extra routing space in your chip, you may have to make slight +re-arrangements to help the router out. The paragraphs below describe +things you can do to make life easier for the router. This section +is not very well developed, so we'd like to hear about +techniques you use to improve routability. If you discover new techniques, +send us mail and we'll add them to this section. + +\subsection{Channel Structure} + +One of the first things to check when the router fails is the +channel structure. If using the Magic router, type {\bfseries :channel} to look at +the channels. +One common mistake is to have some of the desired +routing area covered by subcells; Magic only runs wires where +there are no subcells. Check to be sure that there are channels +everywhere that you're expecting wires to run. If you place cells too close +together, there may not be enough room to have a channel +between the cells; when this happens Magic will route willy-nilly +across the tops of cells to bring terminals out to channels, and will probably +generate shorts or design-rule violations. To solve the problem, +move the cells farther apart. If there are many skinny channels, +it will be difficult for the router to produce good routing. +Try to re-arrange the cell structure to line up edges of +nearby cells so that there are as few channels as possible +and they are as large as possible (before doing this you'll +probably want to get rid of the existing routing by undo-ing +or by flushing the edit cell). + +\subsection{Stems} + +Another problem has to do with the stem generator. Stems are the +pieces of wiring that connect terminals up to grid points on the +edges of channels. The current stem generation code doesn't know about +connectivity or design rules. +It simply finds the nearest routing grid point and wires out +to that point, without considering any other terminals. If a +terminal is not on the edge of the cell, the stem runs straight +across the cell to the nearest channel, without any consideration +for other material in the cell. If two +terminals are too close together, Magic may decide to route them +both to the same grid point. When this happens, you have two +choices. Either you can move the cell so that the terminals +have different nearest grid points (for example, you can line +its terminals up with the grid lines), or if this doesn't work +you'll have to modify the cell to make the terminals farther +apart. + +The place where stems cause the most trouble is in PLAs, many of +which have been optimized to space the outputs as closely together +as possible. In some cases the outputs are closer together than +the routing grid, which is an impossible situation for the stem +generator. In this case, we think the best approach is to change +the PLA templates to space the outputs farther apart. Either space +them exactly the same as the router grid (in which case you can +line the PLAs up before routing so the terminals are already on +the grid), or space the outputs at least 1.5 grid units apart so the stem +generator won't have troubles. Having tightly-spaced PLA outputs +is false economy: it makes it more difficult to design the PLAs +and results in awful routing problems. Even if Magic could +river-route out from tightly-spaced terminals to grid lines (which +it can't), it would require $N^2$ space to route out +$N$ lines; it takes less area to stretch the PLA. + +\subsection{Obstacles} + +The router tends to have special difficulties with +obstacles running along the edges of channels. When you've placed +a power wire or other hand-routing along the edge of a channel, +the channel router will often run material under your wiring in +the other routing layer, thereby blocking both routing layers +and making it impossible to complete the routing. Where this +occurs, you can increase the chances of successful routing by +moving the hand-routing away from the channel edges. It's +especially important to keep hand-routing away from terminals. +The stem generator will not pay any attention to hand-routing +when it generates stems (it just makes a bee-line for the nearest +grid point), so it may accidentally short a terminal to nearby +hand-routing. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tut7.3.ps, width=0.4\columnwidth} + \caption{When placing hand routing, it is best to place + wires with their left and bottom edges along grid lines, and + contacts centered on the wires. In this fashion, the hand routing + will block as few routing grid lines as possible.} + \end{center} +\end{figure} + +When placing hand-routing, you can get better routing results +by following the advice illustrated in Figure 3. First, display +the routing grid. For example, if the router is using a 8-unit +grid (which is true for the standard SCMOS technology), type +{\bfseries :grid 8}. Then place all your hand routing with its left +and bottom edges along the grid lines. Because of the way the +routing tools work, this approach results in the least possible +amount of lost routing space. + +\section{More Netlist Commands} + +In addition to the netlist menu buttons and commands described +in Section 4, there are a number of other netlist commands you +can invoke by typing in the netlist window. Many of these +commands are textual equivalents of the menu buttons. However, +they allow you to deal with terminals by typing the hierarchical +name of the terminal rather than by pointing to it. If you +don't know where a terminal is, or if you have deleted a label +from your design so that there's nothing to point to, you'll +have to use the textual commands. Commands that don't just +duplicate menu buttons are described below; see the +{\itshape magic(1)} manual page for details on the others. + +The netlist command + +\starti + \ii {\bfseries :extract} +\endi + +will generate a net from existing wiring. It looks under the +box for paint, then traces out all the material in the edit cell +that is connected electrically to that paint. Wherever the +material touches subcells it looks for terminals in the subcells, +and all the terminals it finds are placed into a new net. Warning: +there is also an {\bfseries extract} command for layout windows, and it +is totally different from the {\bfseries extract} command in netlist +windows. Make sure you've got the cursor over the netlist window +when you invoke this command! + +The netlist editor provides two commands for ripping up existing +routing (or other material). They are + +\starti + \ii {\bfseries :ripup} \\ + \ii {\bfseries :ripup netlist} +\endi + +The first command starts by finding any paint in the edit cell +that lies underneath the box. It then works outward from that +paint to find all paint in the edit cell that is electrically +connected to the starting paint. All of this paint is erased. +({\bfseries :ripup} isn't really necessary, since the same effect can +be achieved by selecting all the paint in the net and deleting +the selection; it's a hangover from olden days when there was +no selection). +The second form of the command, {\bfseries :ripup netlist}, is similar +to the first except that it starts from each of the terminals +in the current netlist instead of the box. Any paint in +the edit cell that is electrically connected to a terminal +is erased. The {\bfseries :ripup netlist} command may be useful to +ripup existing routing before rerouting. + +The command + +\starti + \ii {\bfseries :trace} [{\itshape name}] +\endi + +provides an additional facility for examining +router feedback. It highlights all paint connected +to each terminal in the net containing {\itshape name}, +much as the {\bfseries Show} menu button does for paint +connected to anything under the box. The net to be highlighted +may be specified by naming one of its terminals, for example, +{\bfseries :trace shifter/bit[0]/phi1}. +Use the trace command in conjunction with the nets specified in +router feedback to see the partially completed wiring for a net. +Where no net is specified, the {\bfseries :trace} command highlights the +currently selected net. + +\end{document} diff --git a/doc/latexfiles/tut8.tex b/doc/latexfiles/tut8.tex new file mode 100644 index 00000000..cb3c539f --- /dev/null +++ b/doc/latexfiles/tut8.tex @@ -0,0 +1,996 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 8 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#8: Circuit Extraction} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Walter Scott} \\ + \vspace*{0.5in} + Special Studies Program \\ + Lawrence Livermore National Laboratory \\ + P.O. Box 808, L-270 \\ + Livermore, CA 94550 \\ + \vspace*{0.25in} + {\itshape (Updated by others, too.)} \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection \\ + \> Magic Tutorial \#4: Cell Hierarchies +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :extract +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + {\itshape (none)} +\endi + +{\bfseries Changes since Magic version 4:} + +\starti + \> New form of {\bfseries :extract unique} \\ + \> Path length extraction with {\bfseries :extract length} \\ + \> Accurate resistance extraction with {\bfseries :extresis} \\ + \> Extraction of well connectivity and substrate nodes \\ + \> Checking for global net connectedness in {\itshape ext2sim}~(1) \\ + \> New programs: {\itshape ext2spice}~(1) and {\itshape extcheck}~(1) \\ +\endi + +\section{Introduction} + +This tutorial covers the use of Magic's +circuit extractor. +The extractor computes from the layout the information needed +to run simulation tools such as {\itshape crystal}~(1) and {\itshape esim}~(1). +This information includes the sizes and shapes of transistors, +and the connectivity, resistance, and parasitic capacitance of nodes. +Both capacitance to substrate and several kinds of internodal +coupling capacitances are extracted. + +Magic's extractor is both incremental and hierarchical: +only part of the entire layout must be re-extracted after each change, +and the structure of the extracted +circuit parallels the structure of the layout being extracted. +The extractor produces a separate {\bfseries .ext} file +for each {\bfseries .mag} file in a hierarchical design. +This is in contrast to previous extractors, such as Mextra, +which produces a single {\bfseries .sim} file that represents +the flattened (fully-instantiated) layout. + +Sections 2 through 4 introduce Magic's {\bfseries :extract} command +and some of its more advanced features. +Section 5 describes what information actually gets extracted, and +discusses limitations and inaccuracies. +Section 6 talks about extraction styles. +Although the hierarchical {\itshape ext}~(5) format fully describes the +circuit implemented by a layout, very few tools currently accept it. +It is normally necessary to flatten the extracted circuit using +one of the programs discussed in Section 7, such as {\itshape ext2sim}~(1), +{\itshape ext2spice}~(1), or {\itshape extcheck}~(1). + +\section{Basic Extraction} + +You can use Magic's extractor in one of several ways. +Normally it is not necessary to extract all cells in a layout. +To extract only those cells that have changed since they were extracted, use: + +\starti + \ii {\bfseries :load} {\itshape root} \\ + \ii {\bfseries :extract} +\endi + +The extractor looks for a {\bfseries .ext} file for every cell in the tree +that descends from the cell {\itshape root}. +The {\bfseries .ext} file is searched for in the same directory that +contains the cell's {\bfseries .mag} file. +Any cells that have been modified since they were last extracted, +and all of their parents, are re-extracted. +Cells having no {\bfseries .ext} files are also re-extracted. + +To try out the extractor on an example, copy all the {\bfseries tut8}{\itshape x} +cells to your current directory with the following shell commands: + +\starti + \ii {\bfseries cp \~{}cad/lib/magic/tutorial/tut8*.mag\ \ .} +\endi + +Start magic on the cell {\bfseries tut8a} and type {\bfseries :extract}. +Magic will print the name of each cell ({\bfseries tut8a}, {\bfseries tut8b}, +{\bfseries tut8c}, and {\bfseries tut8d}) as it is extracted. +Now type {\bfseries :extract} a second time. This time nothing gets +printed, since Magic didn't have to re-extract any cells. +Now delete the piece of poly labelled ``{\bfseries delete me}'' +and type {\bfseries :extract} again. This time, only the cell +{\bfseries tut8a} is extracted as it is the only one that changed. +If you make a change to cell {\bfseries tut8b} (do it) and then +extract again, both {\bfseries tut8b} and {\bfseries tut8a} will be re-extracted, +since {\bfseries tut8a} is the parent of {\bfseries tut8b}. + +To force all cells in the subtree rooted at cell {\itshape root} +to be re-extracted, use {\bfseries :extract\ all}: + +\starti + \ii {\bfseries :load}{\itshape root} \\ + \ii {\bfseries :extract all} +\endi + +Try this also on {\bfseries tut8a}. + +You can also use the {\bfseries :extract} command to extract a single cell +as follows: + +\starti + \ii {\bfseries :extract cell} {\itshape name} +\endi + +will extract just the selected (current) cell, and place the output +in the file {\itshape name}. +Select the cell {\bfseries tut8b} ({\bfseries tut8b{\_}0}) and type +{\bfseries :extract cell differentFile} to try this out. +After this command, the file {\bfseries differentFile.ext} will +contain the extracted circuit for the cell {\bfseries tut8b}. +The children of {\bfseries tut8b} (in this case, the single cell {\bfseries tut8d}) +will not be re-extracted by this command. +If more than one cell is selected, the upper-leftmost one is extracted. + +You should be careful about using {\bfseries :extract cell}, +since even though you may only make a change to a child +cell, all of its parents may have to be re-extracted. +To re-extract all of the parents of the selected cell, you may use + +\starti + \ii {\bfseries :extract parents} +\endi + +Try this out with {\bfseries tut8b} still selected. Magic will extract +only the cell {\bfseries tut8a}, since it is the only one that uses the +cell {\bfseries tut8b}. +To see what cells would be extracted by {\bfseries :extract parents} +without actually extracting them, use + +\starti + \ii {\bfseries :extract showparents} +\endi + +Try this command as well. + +\section{Feedback: Errors and Warnings} + +When the extractor encounters problems, it leaves feedback in the form +of stippled white rectangular areas on the screen. +Each area covers the portion of the layout that caused the error. +Each area also has an error message associated with it, which you can see +by using the {\bfseries :feedback} command. +Type {\bfseries :feedback help} while +in Magic for assistance in using the {\bfseries :feedback} command. + +The extractor will always report extraction {\itshape errors}. +These are problems in +the layout that may cause the output of the extractor to be incorrect. +The layout should be fixed to eliminate extraction errors +before attempting to simulate the circuit; otherwise, the +results of the simulation may not reflect reality. + +Extraction errors can come from violations of transistor rules. +There are two rules about the formation of transistors: +no transistor can be formed, and none can be destroyed, +as a result of cell overlaps. +For example, it +is illegal to have poly in one cell overlap diffusion in another cell, +as that would form a transistor in the parent where none was present +in either child. It is also illegal to have a buried contact in one +cell overlap a transistor in another, as this would destroy the transistor. +Violating these transistor rules will cause design-rule violations +as well as extraction errors. +These errors only relate to circuit extraction: the fabricated +circuit may still work; it just won't be extracted correctly. + +In general, it is an error for material of two types on the same plane +to overlap or abut if they don't connect to each other. For example, +in CMOS it is illegal for p-diffusion and n-diffusion to overlap or abut. + +In addition to errors, the extractor can give {\itshape warnings}. +If only warnings are present, the extracted circuit can still be +simulated. +By default, only some types of warnings are reported and displayed as feedback. +To cause all warnings to be displayed, use + +\starti + \ii {\bfseries :extract warn all} +\endi + +The command + +\starti + \ii {\bfseries :extract warn} {\itshape warning} +\endi + +may be used to enable specific warnings selectively; see below. +To cause no warnings to be displayed, or to disable display +of a particular {\itshape warning}, use respectively + +\starti + \ii {\bfseries :extract warn no all} or \\ + \ii {\bfseries :extract warn no} {\itshape warning} +\endi + +Three different kinds of warnings are generated. +The {\bfseries dup} warning checks to see whether you +have two electrically unconnected nodes in the same +cell labelled with the same name. +If so, you are warned because the two unconnected +nodes will appear to be connected in the resulting {\bfseries .ext} file, +which means that the extracted circuit would not represent the actual layout. +This is bad if you're simulating the circuit to see if it will work +correctly: the simulator will think the two nodes are connected, +but since there's no physical wire between them, the electrons won't! +When two unconnected nodes share the same label (name), the extractor leaves +feedback squares over each instance of the shared name. + +It's an excellent idea to avoid labelling two unconnected nodes with the same +name within a cell. Instead, use the "correct" name for one of the +nodes, and some mnemonic but textually distinct name for the other nodes. +For example, in a cell with multiple power rails, you might use +{\bfseries Vdd!} for one of the rails, and names like {\bfseries Vdd\#1} for the +others. As an example, load the cell {\bfseries tut8e}. +If the two nodes are connected in a higher-level cell +they will eventually be merged when the extracted circuit is flattened. +If you want to simulate a cell out +of context, but still want the higher-level nodes to be hooked up, +you can always create a dummy parent cell that hooks them together, +either with wire or by using the same name for pieces of paint that +lie over the terminals to be connected; see the cell {\bfseries tut8f} +for an example of this latter technique. + +You can use the command + +\starti + \ii {\bfseries :extract unique} +\endi + +as an automatic means +of labelling nodes in the manner described above. Run this command on +the cell {\bfseries tut8g}. A second version of this command is provided +for compatibility with previous versions of Magic. +Running + +\starti + \ii {\bfseries :extract unique \#} +\endi + +will only +append a unique numeric suffix to labels that end with a ``{\bfseries \#}''. +Any other duplicate nodenames that also don't end in a ``{\bfseries !}'' +(the global nodename suffix as described in Section 5) +are flagged by feedback. + +A second type of warning, {\bfseries fets}, checks to see whether any transistors +have fewer diffusion terminals than the minimum for their types. +For example, the transistor type ``{\bfseries dfet}'' is defined in +the {\bfseries nmos} technology file as requiring two diffusion terminals: +a source and a drain. +If a capacitor with only one diffusion terminal is desired in this +technology, the type {\bfseries dcap} should be used instead. +The {\bfseries fets} warning is a consistency check for transistors +whose diffusion terminals have been accidentally shorted together, +or for transistors with insufficiently many diffusion terminals. + +The third warning, {\bfseries labels}, +is generated if you violate the following +guideline for placement of labels: +Whenever geometry from two subcells abuts or overlaps, +it's a good idea to make sure that +there is a label attached to the geometry in each subcell +{\itshape in the area of the overlap or along the line of abutment}. +Following this guideline isn't necessary for the extractor to work, +but it will result in noticeably faster extraction. + +By default, the {\bfseries dup} and {\bfseries fets} warnings are enabled, +and the {\bfseries labels} warning is disabled. + +Load the cell {\bfseries tut8h}, expand all its children ({\bfseries tut8i} and +{\bfseries tut8j}), and enable +all extractor warnings with {\bfseries :extract warn all}. +Now extract {\bfseries tut8h} and all of its children with +{\bfseries :extract}, and examine the feedback for examples of +fatal errors and warnings. + +\section{Advanced Circuit Extraction} + +\subsection{Lengths} + +The Magic extractor has a rudimentary ability to compute wire lengths +between specific named points in a circuit. This feature is intended for +use with technologies where the wire length between two points is +more important than the total capacitance on the net; this may +occur, for example, when extracting circuits with very long wires +being driven at high speeds ({\itshape e.g.}, bipolar circuits). +Currently, you must indicate to Magic which pairs of points are +to have distances computed. You do this by providing two lists: +one of {\itshape drivers} and one of {\itshape receivers}. The extractor +computes the distance between each driver and each receiver +that it is connected to. + +Load the cell {\bfseries tut8k}. There are five labels: two are drivers +({\bfseries driver1} and {\bfseries driver2}) and three are receivers +({\bfseries receiverA}, {\bfseries receiverB}, and {\bfseries receiverC}). +Type the commands: + +\starti + \ii {\bfseries :extract length driver driver1 driver2} \\ + \ii {\bfseries :extract length receiver receiverA receiverB receiverC} +\endi + +Now enable extraction of lengths with {\bfseries :extract do length} +and then extract the cell ({\bfseries :extract}). +If you examine {\bfseries tut8k.ext}, you will see several {\bfseries distance} +lines, corresponding to the driver-receiver distances described +above. These distances are through the centerlines of wires +connecting the two labels; where multiple paths exist, the +shortest is used. + +Normally the driver and receiver tables will be built by using +{\bfseries :source} to read a file of {\bfseries :extract length driver} +and {\bfseries :extract length receiver} commands. Once these tables +are created in Magic, they remain until you leave Magic or type +the command + +\starti + \ii {\bfseries :extract length clear} +\endi + +which wipes out both tables. + +Because extraction of wire lengths is {\itshape not} performed hierarchically, +it should only be done in the root cell of a design. Also, because +it's not hierarchical, it can take a long time for long, complex wires such +as power and ground nets. This feature is still experimental and +subject to change. + +\subsection{Resistance} + +Magic provides for more accurate resistance extraction using the +{\bfseries :extresis }command. {\bfseries :extresis} provides a detailed +resistance/capacitance +description for nets where parasitic resistance is likely to significantly +affect circuit timing. + +\subsubsection{Tutorial Introduction} + +To try out the resistance extractor, load in the cell {\bfseries tut8r}. Extract it +using {\bfseries :extract}, pause magic, and run ext2sim on the cell with the command + +\starti + \ii {\bfseries ext2sim tut8r} +\endi + +This should produce {\bfseries tut8r.sim}, {\bfseries tut8r.nodes}, +and {\bfseries tut8r.al}. Restart magic and type + +\starti + \ii {\bfseries :extresis tolerance 10} \\ + \ii {\bfseries :extresis} +\endi + +This will +extract interconnect resistances for any net where the interconnect delay +is at least one-tenth of the transistor delay. Magic should give the messages: + +\starti + \ii {\bfseries :extresis tolerance 10} \\ + \ii {\bfseries :extresis} \\ + \ii {\bfseries Adding net2; Tnew = 0.428038ns,Told = 0.3798ns} \\ + \ii {\bfseries Adding net1; Tnew = 0.529005ns,Told = 0.4122ns} \\ + \ii {\bfseries Total Nets: 7} \\ + \ii {\bfseries Nets extracted: 2 (0.285714)} \\ + \ii {\bfseries Nets output: 2 (0.285714)} +\endi + +These may vary slightly depending on your technology parameters. +The {\bfseries Adding [net]} lines describe which networks for which magic produced +resistor networks. {\bfseries Tnew} is the estimated delay on the net including the +resistor parasitics, while {\bfseries Told} is the delay without parasitics. +The next line describes where magic thinks the slowest node in the net is. +The final 3 +lines give a brief summary of the total number of nets, the nets requiring +extraction, and the number for which resistors were added to the output. + +Running the resistance extractor also produced the file {\bfseries cell.res.ext}. To +produce a {\bfseries .sim} file containing resistors, quit magic and type: + +\starti + \ii {\bfseries cat tut8r.ext tut8r.res.ext $>$tut8r.2.ext} \\ + \ii {\bfseries ext2sim -R -t! -t\# tut8r.2} +\endi + +Comparing the two files, {\bfseries tut8r.sim} and {\bfseries tut8r.2.sim}, shows +that the latter has the nodes net1 and net2 split into several parts, with +resistors added to connect the new nodes together. + +\subsubsection{General Notes on using the resistance extractor} + +To use {\bfseries :extresis}, the circuit must first be extracted using +{\bfseries :extract} and flattened using ext2sim. When ext2sim is run, +do not use the {\bfseries -t\#} and {\bfseries -t!} flags (i.e. don't +trim the trailing "\#" and "!" characters) or the {\bfseries -R} flag +because {\bfseries :extresis} needs the {\bfseries .sim} and {\bfseries .ext} +names to correspond exactly, and it needs the lumped resistance values that +the extractor produces. Also, do not delete or rename the {\bfseries .nodes} +file; {\bfseries :extresis} needs this to run. Once the {\bfseries .sim} and +{\bfseries .nodes} files have been produced, type the command +{\bfseries :extresis} while running magic on the root cell. As the +resistance extractor runs, it will identify which nets (if any) for +which it is producing RC networks, and will +identify what it thinks is the "slowest" point in the network. When it +completes, it will print a brief summary of how many nets it extracted and +how many required supplemental networks. The resistance networks are placed +in the file {\bfseries root.res.ext}. To produce a {\bfseries .sim} file +with the supplemental +resistors, type {\bfseries cat root.ext root.res.ext $>$newname.ext}, and then rerun +{\bfseries ext2sim} on the new file. During this second {\bfseries ext2sim} run, the +{\bfseries -t} flag may be used. + +Like extraction of wire lengths, resistance extraction is {\itshape not} performed +hierarchically; it should only be done in the root cell of a design and +can take a long time for complex wires. + +\subsubsection{Options, Features, Caveats and Bugs} + +The following is a list of command line options and the arguments that they +take. + +\begin{itemize} + \item {\bfseries tolerance [value]} \\ This controls how large the + resistance in a network must be before it is added to the + output description. {\bfseries value} is defined as the minimum + ratio of transistor resistance to interconnect resistance that + requires a resistance network. The default value is 1; values + less than 1 will cause fewer resistors to be output and will make + the program run faster, while values greater than 1 will produce + more a larger, more accurate description but will run slower. + + \item {\bfseries all} \\ Causes all nets in the circuit to be extracted; + no comparison between transistor size and lumped resistance is + performed. This option is not recommended for large designs. + + \item {\bfseries simplify [on/off]} \\ Turns on/off the resistance network + simplification routines. Magic normally simplifies the resistance + network it extracts by removing small resistors; specifying this flag + turns this feature off. + + \item {\bfseries extout [on/off]} \\ Turns on and off the writing of the + {\ttfamily root.res.ext} file. The default value is on. + + \item {\bfseries lumped [on/off]} \\ Turns on the writing of + {\ttfamily root.res.lump}. This file contains an updated + value of the lumped resistance for each net that + {\bfseries :extresis} extracts. + + \item {\bfseries silent [on/off]} \\ This option suppresses printing + of the name and location of nets for which resistors are produced. + + \item {\bfseries skip mask} \\ Specifies a list of layers that the + resistance extractor is to ignore. + + \item {\bfseries help} \\ Print brief list of options. +\end{itemize} + +Attribute labels may also be used to specify certain extractor options. For +a description of attributes and how they work, see tutorial 2. Following is +a description of {\bfseries :extresis} attributes. + +\begin{itemize} + \item {\bfseries res:skip@} \\ + Causes this net to be skipped. This is useful for avoiding + extraction of power supplies or other DC signals that are not + labeled Vdd or GND. + + \item {\bfseries res:force@} \\ + Forces extraction of this net regardless of its lumped + resistance value. Nets with both skip and force labels attached + will cause the extractor to complain. + + \item {\bfseries res:min=[value]@} \\ Sets the smallest resistor size + for this net. The default value is the resistance of the largest + driving transistor divided by the tolerance described above. + + \item {\bfseries res:drive@} - Nets with no driving transistors will normally + not be extracted. This option allows the designer to specify from + where in the net the signal is driven. This is primarily useful + when extracting subcells, where the transistors driving a given signal + may be located in a different cell. +\end{itemize} + +\subsubsection{Technology File Changes} + +Certain changes must be made in the extract section of the technology file +to support resistance extraction. These include the {\bfseries fetresist} and {\bfseries contact} +lines, plus a small change to the fet line. Full details can be found in +Magic Maintainer's Manual \#2. The only thing to note is that, contrary to +the documentation, the {\bfseries gccap} and {\bfseries gscap} parts of the fet line MUST +be set; the resistance extractor uses them to calculate RC time constants for +the circuit. + +\section{Extraction Details and Limitations} + +This section explores in greater depth what gets extracted by Magic, +as well as the limitations of the circuit extractor. +A detailed explanation of the format of the {\bfseries .ext} files +output by Magic may be found in the manual page {\itshape ext}~(5). +``Magic Maintainer's Manual\ \#2: The Technology File'' +describes how extraction parameters are specified for the extractor. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tut8.1.ps, width=0.33\columnwidth} + \caption{Each node extracted by Magic has a lumped resistance + {\itshape R} and a lumped capacitance {\itshape C} to the + substrate. These lumped values can be interpreted as in the + diagram above, in which each device connected to the node is + attached to one of the points {\itshape 1}, {\itshape 2}, + \dots, {\itshape N}.} + \end{center} +\end{figure} + +\subsection{Nodes} + +Magic approximates the pieces of interconnect between transistors +as ``nodes''. A node is like an equipotential region, but +also includes a lumped resistance and capacitance to substrate. +Figure 1 shows how these lumped values are intended to be interpreted by +the analysis programs that use the extracted circuit. + +Each node in an extracted circuit has a name, which is either +one of the labels attached to the geometry in the node if any exist, +or automatically generated by the extractor. These latter names +are always of the form {\itshape p{\_}x{\_}y\#}, where +{\itshape p}, {\itshape x}, and {\itshape y} are integers, +{\itshape e.g.}, {\bfseries 3{\_}104{\_}17\#}. +If a label ending in the character ``{\bfseries !}'' is attached to a +node, the node is considered to be a ``global''. Post-processing +programs such as {\itshape ext2sim}~(1) will check to ensure that +nodes in different cells that are labelled with the same global +name are electrically connected. + +Nodes may have attributes attached to them as well as names. +Node attributes are labels ending in the special character +``{\bfseries @}'', and provide a mechanism for passing information +to analysis programs such as {\itshape crystal}~(1). The man +page {\itshape ext}~(5) provides additional information about +node attributes. + +\subsection{Resistance} + +Magic extracts a lumped resistance for each node, rather than a +point-to-point resistance between each pair of devices connected +to that node. The result is that all such +point-to-point resistances are approximated by the +worst-case resistance between any two points in that node. + +By default, +node resistances are approximated rather than computed exactly. +For a node comprised entirely of a single type of material, +Magic will compute the node's total perimeter and area. +It then solves a quadratic equation to find the width and height of a simple +rectangle with this same perimeter and area, and approximates the +resistance of the node as the resistance of this ``equivalent'' +rectangle. The resistance is always taken in +the longer dimension of the rectangle. +When a node contains more than a single type of material, Magic +computes an equivalent rectangle for each type, and then sums +the resistances as though the rectangles were laid end-to-end. + +This approximation for resistance does not take into account any +branching, so it can be significantly in error for nodes that have +side branches. Figure 2 gives an example. +For global signal trees such as clocks or power, Magic's estimate of +resistance will likely be several times higher than the actual +resistance between two points. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tut8.2.ps, width=0.8\columnwidth} + \caption{Magic approximates the resistance of a node by + assuming that it is a simple wire. The length and width + of the wire are estimated from the node's perimeter and area. + (a) For non-branching nodes, this approximation is a good one. + (b) The computed resistance for this node is the same as for + (a) because the side branches are counted, yet the actual + resistance between points 1 and 2 is significantly less + than in (a).} + \end{center} +\end{figure} + +The approximated resistance also does not lend itself well to +hierarchical adjustments, as does capacitance. To allow programs +like {\bfseries ext2sim} to incorporate hierarchical adjustments into +a resistance approximation, each node in the {\bfseries .ext} file +also contains a perimeter and area for each ``resistance class'' +that was defined in the technology file (see ``Maintainer's +Manual \#2: The Technology File,'' and {\itshape ext}~(5)). +When flattening a circuit, {\bfseries ext2sim} uses this information +along with adjustments to perimeter and area +to produce the value it actually uses for node resistance. + +If you wish to disable the extraction of resistances and node +perimeters and areas, use +the command + +\starti + \ii {\bfseries :extract no resistance} +\endi + +which will cause all node resistances, perimeters, and areas in +the {\bfseries .ext} file to be zero. +To re-enable extraction of resistance, use +the command + +\starti + \ii {\bfseries :extract do resistance}. +\endi + +Sometimes it's important that resistances be computed more accurately +than is possible using the lumped approximation above. +Magic's {\bfseries :extresist} command does this by computing explicit +two-terminal resistors and modifying the circuit network to +include them so it reflects more exactly the topology of the layout. +See the section on {\bfseries Advanced Extraction} for more details +on explicit resistance extraction with {\bfseries :extresist}. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tut8.3.ps, width=0.5\columnwidth} + \caption{Each type of edge has capacitance to substrate per + unit length. Here, the diffusion-space perimeter of 13 units + has one value per unit length, and the diffusion-buried perimeter + of 3 units another. In addition, each type of material has + capacitance per unit area.} + \end{center} +\end{figure} + +\subsection{Capacitance} + +Capacitance to substrate comes from two different sources. +Each type of material has a capacitance to substrate per unit area. +Each type of edge (i.e, each pair of types) has a capacitance +to substrate per unit length. See Figure 3. +The computation of capacitance may be disabled with + +\starti + \ii {\bfseries :extract no capacitance} +\endi + +which causes all +substrate capacitance values in the {\bfseries .ext} file +to be zero. It may be re-enabled with + +\starti + \ii {\bfseries :extract do capacitance}. +\endi + +Internodal capacitance comes from three sources, as shown in Figure 4. +When materials of two different types overlap, the capacitance to +substrate of the one on top (as determined by the technology) is +replaced by an internodal capacitance to the one on the bottom. +Its computation may be disabled with + +\starti + \ii {\bfseries :extract no coupling} +\endi + +which will also cause the extractor to run 30\% to 50\% faster. +Extraction of coupling capacitances can be re-enabled with + +\starti + \ii {\bfseries :extract do coupling}. +\endi + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tut8.4.ps, width=0.75\columnwidth} + \caption{Magic extracts three kinds of internodal coupling + capacitance. This figure is a cross-section (side view, not + a top view) of a set of masks that shows all three kinds of + capacitance. {\itshape Overlap} capacitance is parallel-plate + capacitance between two different kinds of material when they + overlap. {\itshape Sidewall} capacitance is parallel-plate + capacitance between the vertical edges of two pieces of the + same kind of material. {\itshape Sidewall overlap} capacitance + is orthogonal-plate capacitance between the vertical edge of one + piece of material and the horizontal surface of another piece of + material that overlaps the first edge.} + \end{center} +\end{figure} + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tut8.5.ps, width=0.75\columnwidth} + \caption{ + (a) When transistors are rectangular, it is possible to + compute $L / W$ exactly. Here {\itshape gateperim}$=4$, + {\itshape srcperim}$=6$, {\itshape drainperim}$=6$, and + $L/W = 2/6$. + (b) The $L/W$ of non-branching transistors can be approximated. + Here {\itshape gateperim}$=4$, {\itshape srcperim}$=6$, + {\itshape drainperim}$=10$. By averaging {\itshape srcperim} + and {\itshape drainperim} we get $L/W = 2/8$. + (c) The $L/W$ of branching transistors is not well approximated. + Here {\itshape gateperim}$=16$, {\itshape srcperim}$=2$, + {\itshape drainperim}$=2$. Magic's estimate of $L/W$ is $8/2$, + whereas in fact because of current spreading, $W$ is effectively + larger than $2$ and $L$ effectively smaller than $8$, so $L/W$ is + overestimated.} + \end{center} +\end{figure} + +Whenever material from two subcells overlaps or abuts, the extractor +computes adjustments to substrate capacitance, coupling +capacitance, and node perimeter and area. Often, these adjustments +make little difference to the type of analysis you are performing, +as when you wish only to compare netlists. Even when running +Crystal for timing analysis, the adjustments can make less than +a 5\% difference in the timing of critical paths in designs with +only a small amount of inter-cell overlap. +To disable the computation of these adjustments, use + +\starti + \ii {\bfseries :extract no adjustment} +\endi + +which will result in +approximately 50\% faster extraction. This speedup is +not entirely additive with the speedup resulting from +{\bfseries :extract no coupling}. To re-enable computation of adjustments, use +{\bfseries :extract do adjustment}. + +\subsection{Transistors} + +Like the resistances of nodes, the lengths and widths of transistors are +approximated. Magic computes the contribution to the total perimeter +by each of the terminals of the transistor. See Figure 5. +For rectangular transistors, this yields an exact \$L / W\$. +For non-branching, non-rectangular transistors, it is still +possible to approximate \$L / W\$ fairly well, but substantial +inaccuracies can be introduced if the channel of a transistor contains +branches. +Since most transistors are rectangular, however, Magic's approximation +works well in practice. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|ccccccc|} \hline + Type & Loc & A P & Subs & Gate & Source & Drain \\ \hline + fet nfet & 59 1 60 2 & 8 12 & GND! & Mid2 4 {\bfseries N3} + & Out 4 0 & Vss\#0 4 0 \\ + fet nfet & 36 1 37 2 & 8 12 & Float & Mid1 4 {\bfseries N2} + & Mid2 4 0 & Vss\#0 4 0 \\ + fet nfet & 4 1 5 2 & 8 12 & Vss\#0 & In 4 {\bfseries N1} + & Mid1 4 0 & Vss\#0 4 0 \\ + fet pfet & 59 25 60 26 & 8 12 & Vdd! & Mid2 4 {\bfseries P3} + & Vdd\#0 4 0 & Out 4 0 \\ + fet pfet & 36 25 37 26 & 8 12 & VBias & Mid1 4 {\bfseries P2} + & Vdd\#0 4 0 & Mid2 4 0 \\ + fet pfet & 4 25 5 26 & 8 12 & Vdd\#0 & In 4 {\bfseries P1} + & Vdd\#0 4 0 & Mid1 4 0 \\ \hline + \end{tabular} + \caption{The transistor section of {\bfseries tut8l.ext}.} + \end{center} +\end{table} + +In addition to having gate, source, and drain terminals, MOSFET +transistors also have a substrate terminal. By default, +this terminal is connected to a global node that depends +on the transistor's type. For example, p-channel transistors +might have a substrate terminal of {\bfseries Vdd!}, while n-channel +transistors would have one of {\bfseries GND!}. +However, when a transistor is surrounded by explicit ``well'' material +(as defined in the technology file), Magic will override the +default substrate terminal with the node to which the well +material is connected. This has several advantages: it allows +simulation of analog circuits in which wells are biased to +different potentials, and it provides a form of checking +to ensure that wells in a CMOS process are explicitly tied +to the appropriate DC voltage. + +Transistor substrate nodes are discovered by the extractor only if +the transistor and the overlapping well layer are in the same cell. +If they appear in different cells, the transistor's substrate terminal +will be set to the default for the type of transistor. + +Load the cell {\bfseries tut8l}, extract it, and look at the file +{\bfseries tut8l.ext}. Table 1 shows the lines for the six +transistors in the file. You'll notice that the substrate terminals +(the {\itshape Subs} column) for all transistors are different. +Since each transistor in this design has a different gate attribute attached +to it (shown in bold in the table, {\itshape e.g.}, {\bfseries N1}, +{\bfseries P2}, etc), we'll use them in the following discussion. + +The simplest two transistors are {\bfseries N3} and {\bfseries P3}, which don't +appear in any explicitly drawn wells. The substrate terminals for +these are {\bfseries GND!} and {\bfseries Vdd!} respectively, since that's what +the technology file says is the default for the two types of transistors. +{\bfseries N1} and {\bfseries P1} are standard transistors that lie in wells tied +to the ground and power rails, labelled in this cell as {\bfseries Vss\#0} +and {\bfseries Vdd\#0} respectively. (They're not labelled {\bfseries GND!} and +{\bfseries Vdd!} so you'll see the difference between {\bfseries N1} and {\bfseries N3}). +{\bfseries P2} lies in a well that is tied to a different bias voltage, +{\bfseries VBias}, such as might occur in an analog design. +Finally, {\bfseries N2} is in a well that isn't tied to any wire. +The substrate node appears as {\bfseries Float} because that's the label that +was attached to the well surrounding {\bfseries N2}. + +The ability to extract transistor substrate nodes allows you to perform +a simple check for whether or not transistors are in properly connected +({\itshape e.g.}, grounded) wells. In a p-well CMOS process, for example, you +might set the default substrate node for n-channel transistors to be +some distinguished global node other than ground, {\itshape e.g.}, +{\bfseries NSubstrateNode!}. You could then extract the circuit, flatten +it using {\itshape ext2spice}~(1) (which preserves substrate nodes, +unlike {\itshape ext2sim}~(1) which ignores them), and +look at the substrate node fields of all the n-channel transistors: +if there were any whose substrate nodes weren't connected to {\bfseries GND!}, +then these transistors appear either outside of any explicit well +(their substrate nodes will be the default of {\bfseries NSubstrateNode}), +or in a well that isn't tied to {\bfseries GND!} with a substrate contact. + +\section{Extraction styles} + +Magic usually knows several different ways to extract +a circuit from a given layout. +Each of these ways is called a {\itshape style}. +Different styles can be used to handle different +fabrication facilities, which may differ in the parameters +they have for parasitic capacitance and resistance. +For a scalable technology, such as the default {\bfseries scmos}, +there can be a different extraction style for each scale factor. +The exact number and nature of the extraction styles is +described in the technology file that Magic reads when it starts. +At any given time, there is one current extraction style. + +To print a list of the extraction styles available, type +the command + +\starti + \ii {\bfseries :extract style}. +\endi + +The {\bfseries scmos} technology currently has the styles {\bfseries lambda=1.5}, +{\bfseries lambda=1.0}, and {\bfseries lambda=0.6}, though this changes over time as +technology evolves. +To change the extraction style +to {\itshape style}, use the command + +\starti + \ii {\bfseries :extract style}{\itshape style} +\endi + +Each style has a specific scale factor between Magic units and +physical units ({\itshape e.g.}, microns); you can't use a +particular style with a different scale factor. To change +the scalefactor, you'll have to edit the appropriate +style in the {\bfseries extract} section of the technology file. +This process is described in +``Magic Maintainer's Manual \#2: The Technology File.'' + +\section{Flattening Extracted Circuits} + +Unfortunately, very few tools exist to +take advantage of the {\itshape ext}~(5) format +files produced by Magic's extractor. +To use these files for simulation +or timing analysis, +you will most likely need to convert them to a flattened +format, such as {\itshape sim}~(5) or {\itshape spice}~(5). + +There are several programs for flattening {\itshape ext}~(5) files. +{\itshape Ext2sim}~(1) produces {\itshape sim}~(5) files suitable +for use with {\itshape crystal}~(1), {\itshape esim}~(1), or {\itshape rsim}~(1). +{\itshape Ext2spice}~(1) is used to produce {\itshape spice}~(5) files +for use with the circuit-level simulator {\itshape spice}~(1). +Finally, {\itshape extcheck}~(1) can be used to perform connectivity +checking and will summarize the number of flattened nodes, +transistors, capacitors, and resistors in a circuit. +All of these programs make use of a library known as +{\itshape extflat}~(3), so the conventions for each and the +checks they perform are virtually identical. The documentation +for {\itshape extcheck} covers the options common to all of +these programs. + +To see how {\itshape ext2sim} works, load the cell {\bfseries tut8n} +and expand all the {\bfseries tutm} subcells. +Notice how the {\bfseries GND!} bus is +completely wired, but the {\bfseries Vdd!} bus is in three +disconnected pieces. +Now extract everything with {\bfseries :extract}, then +exit Magic and run {\bfseries ext2sim tut8n}. +You'll see the following sort of output: + +\ttfamily +\starti + \> *** Global name Vdd! not fully connected: \\ + \> One portion contains the names: \\ + \> \> left/Vdd! \\ + \> The other portion contains the names: \\ + \> \> center/Vdd! \\ + \> I'm merging the two pieces into a single node, but you \\ + \> should be sure eventually to connect them in the layout. \\ \\ + + \> *** Global name Vdd! not fully connected: \\ + \> One portion contains the names: \\ + \> \> left/Vdd! \\ + \> \> center/Vdd! \\ + \> The other portion contains the names: \\ + \> \> right/Vdd! \\ + \> I'm merging the two pieces into a single node, but you \\ + \> should be sure eventually to connect them in the layout. \\ \\ + + \> Memory used: 56k +\endi +\rmfamily + +The warning messages are telling you that the global name +{\bfseries Vdd!} isn't completely wired in the layout. The flattener +warns you, but goes ahead and connects the pieces together +anyway to allow you to simulate the circuit as though it +had been completely wired. +The output of {\itshape ext2sim} will be three files: +{\bfseries tut8n.sim}, {\bfseries tut8n.al}, and {\bfseries tut8n.nodes}; +see {\itshape ext2sim}~(1) or {\itshape sim}~(5) for more information +on the contents of these files. +``{\bfseries Magic Tutorial \#11: Using RSIM with Magic}'' explains how to use the +output of {\itshape ext2sim} with the switch-level simulator, +{\itshape rsim}~(1). + +\end{document} diff --git a/doc/latexfiles/tut9.tex b/doc/latexfiles/tut9.tex new file mode 100644 index 00000000..728a23d0 --- /dev/null +++ b/doc/latexfiles/tut9.tex @@ -0,0 +1,392 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number 9 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#9: Format Conversion for CIF and Calma} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape John Ousterhout} \\ + \vspace*{0.5in} + Computer Science Division \\ + Electrical Engineering and Computer Sciences \\ + University of California \\ + Berkeley, CA 94720 \\ + \vspace*{0.25in} + {\itshape (Updated by others, too.)} \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection \\ + \> Magic Tutorial \#4: Cell Hierarchies +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :calma, :cif +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (None)} +\endi + +\vspace*{0.75in} +\section{Basics} + +CIF (Caltech Intermediate Form) and Calma Stream Format are +standard layout description languages used to transfer mask-level layouts +between organizations and design tools. This tutorial describes +how Magic can be used to read and write files in CIF and Stream +formats. The version of CIF that Magic supports is CIF 2.0; it +is the most popular layout language in the university design +community. The Calma format that Magic supports is GDS II Stream +format, version 3.0, corresponding to GDS II Release 5.1. This +is probably the most popular layout description language for the +industrial design community. + +To write out a CIF file, place the cursor over a layout window +and type the command + +\starti + \ii {\bfseries :cif} +\endi + +This will generate a CIF file called {\itshape name}{\bfseries .cif}, where +{\itshape name} is the name of the root cell in the window. The CIF +file will contain a description of the entire cell +hierarchy in that window. If you wish to use a name different +from the root cell, type the command + +\starti + \ii {\bfseries :cif write} {\itshape file} +\endi + +This will store the CIF in {\itshape file}{\bfseries .cif}. Start Magic up +to edit {\bfseries tut9a} and +generate CIF for that cell. The CIF file +will be in ASCII format, so you can use Unix commands +like {\bfseries more} and {\bfseries vi} to see what it contains. + +To read a CIF file into Magic, place the cursor over a layout window +and type the command + +\starti + \ii {\bfseries :cif read} {\itshape file} +\endi + +This will read the file {\itshape file}{\bfseries .cif} (which must be in +CIF format), generate Magic cells for the hierarchy described +in the file, make the entire hierarchy a subcell of the +edit cell, and run the design-rule checker to verify everything +read from the file. Information in the top-level cell (usually +just a call on the ``main'' cell of the layout) will be placed +into the edit cell. Start Magic up afresh and read in {\bfseries tut9a.cif}, +which you created above. It will be easier if you always read +CIF when Magic has just been started up: if some of the cells +already exist, the CIF reader will not overwrite them, but will +instead use numbers for cell names. + +To read and write Stream-format files, use the commands +{\bfseries :calma read} and {\bfseries :calma}, respectively. These commands +have the same effect as the CIF commands, except that they +operate on files with {\bfseries .strm} extensions. Stream is a binary +format, so you can't examine {\bfseries .strm} files with a text editor. + +Stream files do not identify a top-level cell, so you won't see +anything on the screen after you've used the {\bfseries :calma read} +command. You'll have to use the {\bfseries :load} command to look at +the cells you read. However, if Magic was used to write the +Calma file being read, the library name reported by the +{\bfseries :calma read} command is the same as the name of the +root cell for that library. + +Also, Calma format places some limitations on the names of cells: +they can only contain alphanumeric characters, ``\$'', and ``{\_}'', +and can be at most 32 characters long. If the name of a cell does +not meet these limitations, {\bfseries :calma write} converts it to a +unique name of the form \rule{0.25in}{0.5pt}{\itshape n}, where +{\itshape n} is a small +integer. To avoid any possible conflicts, you should avoid using +names like these for your own cells. + +You shouldn't need to know much more than what's above in order +to read and write CIF and Stream. The sections below describe the different +styles of CIF/Calma that Magic can generate and the limitations +of the CIF/Calma facilities (you may have noticed that when you +wrote and read CIF above you didn't quite get back what you started +with; Section 3 describes the differences that can occur). +Although the discussion mentions +only CIF, the same features and problems apply to Calma. + +\section{Styles} + +Magic usually knows several different ways to generate +CIF/Calma from a given layout. Each of these ways is called a {\itshape style}. +Different styles can be used to handle different +fabrication facilities, which may differ in the names they use for +layers or in the exact mask set required for fabrication. +Different styles can be also used to write out CIF/Calma with slightly +different feature sizes or design rules. CIF/Calma +styles are described in the technology file that Magic reads when +it starts up; the exact number and nature of the styles is +determined by whoever wrote your technology file. There are separate +styles for reading and writing CIF/Calma; at any given time, there +is one current input style and one current output style. + +The standard SCMOS technology file provides an example of how +different styles can be used. Start up Magic with the +SCMOS technology ({\bfseries magic -Tscmos}). Then type the commands + +\starti + \ii {\bfseries :cif ostyle} \\ + \ii {\bfseries :cif istyle} +\endi + +The first command will print out a list of all the styles in +which Magic can write CIF/Calma (in this technology) and the second +command prints out the styles in which Magic can read CIF/Calma. +You use the {\bfseries :cif} command to change the current styles, but +the styles are used for both CIF and Calma format conversion. +The SCMOS technology file provides several output styles. +The initial (default) style for writing CIF is {\bfseries lambda=1.0(gen)}. +This style generates mask layers for the MOSIS scalable +CMOS process, where each Magic unit corresponds to 1 micron and +both well polarities are generated. See the technology manual +for more information on the various styles that are available. +You can change the output style with the command + +\starti + \ii {\bfseries :cif ostyle} {\itshape newStyle} +\endi + +where {\itshape newStyle} is the new style you'd like to use for output. +After this command, any future CIF or Calma files will be generated +with the new style. The {\bfseries :cif istyle} command can be used +in the same way to see the available styles for reading CIF and +to change the current style. + +Each style has a specific scalefactor; you can't use a +particular style with a different scalefactor. To change +the scalefactor, you'll have to edit the appropriate +style in the {\bfseries cifinput} or {\bfseries cifoutput} section +of the technology file. This process is described in +``Magic Maintainer's Manual \#2: The Technology +File.'' + +\section{Rounding} + +The units used for coordinates in Magic are generally different +from those in CIF files. In Magic, most technology files use +lambda-based units, where one unit is typically half the minimum +feature size. In CIF files, the units are centimicrons (hundredths +of a micron). When +reading CIF and Calma files, an integer scalefactor is used to +convert from centimicrons to Magic units. If the CIF file contains +coordinates that don't scale exactly to integer Magic units, +Magic rounds the coordinates up or down to the closest integer +Magic units. A CIF coordinate exactly halfway between two Magic +units is rounded down. The final authority on rounding is the +procedure CIFScaleCoord in the file cif/CIFreadutils.c +When rounding occurs, the resulting Magic file will +not match the CIF file exactly. + +Technology files usually specify geometrical operations such as +bloating, shrinking, and-ing, and or-ing to be performed on +CIF geometries when they are read into Magic. These geometrical +operations are all performed in the CIF coordinate system (centimicrons) +so there is no rounding or loss of accuracy in the operations. +Rounding occurs only AFTER the geometrical operations, at the last +possible instant before entering paint into the Magic database. + +\section{Non-Manhattan Geometries} + +Magic only supports Manhattan features. When CIF or Calma files +contain non-Manhattan features, they are approximated with +Manhattan ones. The approximations occur for wires (if the +centerline contains non-Manhattan segments) and polygons +(if the outline contains non-Manhattan segments). In +these cases, the non-Manhattan segments are replaced with one +or more horizontal and vertical segments before the figure is +processed. Conversion is done by inserting a one-unit stairstep +on a 45-degree angle until a point is reached where a horizontal +or vertical line can reach the segment's endpoint. Some +examples are illustrated in the figure below: in each case, the +figure on the left is the one specified in the CIF file, and the +figure on the right is what results in Magic. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tut9.1.ps, width=0.55\columnwidth} + \end{center} +\end{figure} + +The shape of the Magic stairstep depends on the order in which +vertices appear in the CIF or Calma file. The stairstep is made +by first incrementing or decrementing the x-coordinate, then +incrementing or decrementing the y-coordinate, then x, then y, +and so on. For example, in the figure above, the polygon was +specified in counter-clockwise order; if it had been specified +in clockwise order the result would have been slightly different. + +An additional approximation occurs for wires. The CIF wire figure +assumes that round caps will be generated at each end of the wire. +In Magic, square caps are generated instead. The top example +of the figure above illustrates this approximation. + + +\section{Other Problems with Reading and Writing CIF} + +You may have noticed that when you wrote out CIF for {\bfseries tut9a} +and read it back in again, you didn't get back quite what you +started with. Although the differences shouldn't cause any serious +problems, this section describes what they are so you'll know what +to expect. There are three areas where there may be discrepancies: +labels, arrays, and contacts. These are illustrated in {\bfseries tut9b}. +Load this cell, then generate CIF, then read the CIF +back in again. When the CIF is read in, you'll get a couple of +warning messages because Magic won't allow the CIF to overwrite +existing cells: it uses new numbered cells instead (this is +why you should normally read CIF with a ``clean slate''; in +this case it's convenient to have both the original and +reconstructed infromation present at the same time; just +ignore the warnings). The information +from the CIF cell appears as a subcell named {\bfseries 1} right on +top of the old contents of {\bfseries tut9b}; select {\bfseries 1}, +move it below {\bfseries tut9b}, and expand it so you can compare +its contents to {\bfseries tut9b}. + +The first problem area is that CIF normally allows only point labels. By +default, where you have line or box labels in Magic, +CIF labels are generated at the center of the Magic labels. +The label {\bfseries in} in {\bfseries tut9y} is an example of a line label +that gets smashed in the CIF processing. The command + +\starti + \ii {\bfseries :cif arealabels yes} +\endi + +sets a switch telling Magic to use an extension to cif to output +area-labels. This is not the default since many programs that +take CIF as input do not understand this extension. + +If you are reading a CIF file created by a tool other than Magic, +there is an additional problems with labels. The CIF label construct +(``{\bfseries 94} {\itshape label x y layer}'') has an optional {\itshape layer} field +that indicates the layer to which a label is attached. If reading +a CIF file generated by Magic, this field is always present and so +a label's layer is unambiguous. However, if the field is absent, +Magic must decide which layer to use. It does this by looking to +see what Magic layers lie beneath the label after the CIF has been +read in. When there are several layers, it chooses the one appearing +LATEST in the {\bfseries types} section of the technology file. Usually, +it's possible to ensure that the right layer is used by placing +signal layers (such as metal, diffusion, and poly) later in the +types section than layers such as pwell or nplus. However, sometimes +Magic will still pick the wrong layer, and it will be up to you to +move the label to the right layer yourself. + +The second problem is with arrays. CIF has no standard array +construct, so when Magic outputs arrays it does it as a collection +of cell instances. When the CIF file is read back in, each array +element comes back as a separate subcell. +The array of {\bfseries tut9y} cells is an example of this. +Most designs only have +a few arrays that are large enough to matter; where this is the +case, you should go back after reading the CIF and replace the +multiple instances with a single array. +Calma format does have an array construct, so it +doesn't have this problem. + +The third discrepancy is that where there are large contact areas, +when CIF is read and written the area of the contact may be +reduced slightly. This happened to the large poly contact in +{\bfseries tut9b}. The shrink doesn't reduce the effective area of +the contact; it just reduces the area drawn in Magic. +To see what's happening here, place +the box around {\bfseries tut9b} and {\bfseries 1}, expand everything, +then type + +\starti + \ii {\bfseries :cif see CCP} +\endi + +This causes feedback to be displayed showing CIF layer ``CCP'' +(contact cut to poly). You may have to zoom in a bit to +distinguish the individual via holes. Magic generates lots of +small contact vias over +the area of the contact, and if contacts aren't exact multiples +of the hole size and spacing then extra space is left around +the edges. When the CIF is read back in, this extra space isn't +turned back into contact. The circuit that is read in is +functionally identical to the original circuit, even though +the Magic contact appears slightly smaller. + +There is an additional problem with generating CIF having to +do with the cell hierarchy. When Magic generates CIF, it performs +geometric operations such as ``grow'' and ``shrink''on the mask +layers. Some of these operations are not guaranteed to work +perfectly on hierarchical designs. Magic detects when there are +problems and creates feedback areas to mark the trouble spots. +When you write CIF, Magic will warn you that there were troubles. +These should almost never happen if you generate CIF from designs +that don't have any design-rule errors. If they do occur, you +can get around them by writing cif with the following command + +\starti + \ii {\bfseries :cif flat} {\itshape fileName} +\endi + +This command creates an internal version of the design with hierarchy +removed, before outputing CIF as in {\bfseries cif write}. An alternative +approach that does not require flattening is to modify the technology +file in use. Read ``Magic Maintainers Manual \#2: The Technology File'', +if you want to try this approach. + +\end{document} diff --git a/doc/latexfiles/tutscm1.tex b/doc/latexfiles/tutscm1.tex new file mode 100644 index 00000000..9d31b9f4 --- /dev/null +++ b/doc/latexfiles/tutscm1.tex @@ -0,0 +1,700 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number S-1 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\q{\special{ps:(") show}\hspace*{0.6em}} +\def\mytitle{Magic Tutorial \#S-1: The scheme command-line interpreter} +\def\bk{\special{ps:/bksp 2 string def bksp 0 92 put bksp show}\hspace*{0.4em}} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Rajit Manohar} \\ + \vspace*{0.5in} + Department of Computer Science \\ + California Institute of Technology \\ + Pasadena, CA 91125 \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Read reference \cite{sussman} +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :scm-echo-result, :eval, lots of scheme functions +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (None)} +\endi + +\vspace*{0.75in} +\section{Introduction} + +Magic's original command-line interpreter has some limitations. Some of +these include the absence of definitions with arguments, block structure, +the ability to define complex functions. We describe an extension which +is almost completely backward compatible with the existing magic +command-line syntax, but permits the use of Scheme on the command-line. + +\section{Backward compatibility} + +To permit existing magic source files to work within the scheme interpreter, +we have had to sacrifice one feature of the magic command-line syntax. Single +quotes can only be used to quote a single character. The reason for this +limitation is that {\itshape unmatched} quotes are used by scheme to stop +evaluation of the next input symbol. + +Parentheses are used by the scheme interpreter. If you use parentheses +outside single or double quotes in your magic source files, you might +find that the source files don't work properly. To circumvent this +problem, simply put your parentheses in double quotes. You can also +use backslashes to quote parentheses as in: + +\starti + \ii {\bfseries :macro {\bk}( {\q}echo hello{\q}} +\endi + +Another thing +you may notice is that floating-point numbers are parsed as such, and +therefore a command such as + +\starti + \ii {\bfseries :echo 5.3} +\endi + +would display the string {\bfseries 5.300000}. If you really want the string +{\bfseries 5.3}, use: + +\starti + \ii {\bfseries :echo {\q}5.3{\q}} +\endi + +If this difference is undesirable, the scheme interpreter can be +turned off at compile-time. Talk to your local magic maintainer if you +want this done. We feel that the minor trouble taken in modifying +existing magic source files will be outweighed by the advantage of +using a more powerful layout language. + + +\section{The scheme interpreter} + +The interpreter supports a subset of the scheme language. The features +of scheme that are missing include character types, +vector types, file input/output, complex numbers, the distinction +between exact and inexact arithmetic, quasi-quotations, and +continuations. + +\subsection{Command-line interaction} + +When +interacting with the command-line of magic, the interpreter implicitly +parenthesizes its input. For example, the command + +\starti + \ii {\bfseries :paint poly} +\endi + +would be interpreted as the scheme expression + +\starti + \ii {\bfseries (paint poly)} +\endi + +This has exactly the same effect as the original expression, because +all existing magic command-line functions are also scheme functions. +Since the valid magic commands vary from window to window, the return +value of the function is a boolean that indicates whether the command +was valid for the current window. + +The boolean {\bfseries scm-echo-result} controls whether or not the result +of the evaluation is displayed. If the variable does not exist, or the +variable is not boolean-valued, the result of evaluation is not +echoed. Since the input is implicitly parenthesized, typing in + +\starti + \ii {\bfseries :scm-echo-result} +\endi + +would not display the value of the variable, since it would be +evaluated as: + +\starti + \ii {\bfseries (scm-echo-result)} +\endi + +To display the value of a variable, use the built-in procedure +{\bfseries eval} as follows: + +\starti + \ii {\bfseries :eval scm-echo-result} +\endi + +This would result in the expression: + +\starti + \ii {\bfseries (eval scm-echo-result)} +\endi + +which would have the desired effect (note that for this to actually +display anything, the value of {\bfseries scm-echo-result} must be {\bfseries \#t}, +and so examining its value is really a futile exercise---which is why +it is an example, of course!). + +\subsection{Types of arguments} + +Since scheme expressions are typed, we may need to examine the +type of a particular expression. The following functions return +booleans, and can be used to determine the type of an object. + +{\bfseries \#t} and {\bfseries \#f} are constants representing the booleans true and +false. A standard scheme convention is to name functions that return +booleans with a name ending with ``?''. The built-in functions conform +to this convention. + +The expression {\itshape expr} is evaluated, and the type of the result of +evaluation is checked. + + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (boolean?} {\itshape expr}{\bfseries )} & + {\bfseries \#t} if {\itshape expr} is a boolean \\ \hline + {\bfseries (symbol?} {\itshape expr}{\bfseries )} & + {\bfseries \#t} if {\itshape expr} is a symbol \\ \hline + {\bfseries (list?} {\itshape expr}{\bfseries )} & + {\bfseries \#t} if {\itshape expr} is a list \\ \hline + {\bfseries (pair?} {\itshape expr}{\bfseries )} & + {\bfseries \#t} if {\itshape expr} is a pair \\ \hline + {\bfseries (number?} {\itshape expr}{\bfseries )} & + {\bfseries \#t} if {\itshape expr} is a number \\ \hline + {\bfseries (string?} {\itshape expr}{\bfseries )} & + {\bfseries \#t} if {\itshape expr} is a string \\ \hline + {\bfseries (procedure?} {\itshape expr}{\bfseries )} & + {\bfseries \#t} if {\itshape expr} is a procedure \\ \hline + \end{tabular} +\end{center} + +For example, + +\starti + \ii {\bfseries (boolean? \#t)}{\itshape $=>$ \#t} \\ + \ii {\bfseries (number? \#t)}{\itshape $=>$ \#f} +\endi + +\subsection{Lists and pairs} + +A pair is a record structure with two fields, called the car and cdr +fields (for historical reasons). Pairs are used primarily to represent +lists. A list can be defined recursively as either the empty list, or +a pair whose cdr field is a list. The following functions are used to +extract these fields and to construct new pairs and lists. + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (car} {\itshape pair}{\bfseries )} & + the car field of {\itshape pair} \\ \hline + {\bfseries (cdr} {\itshape pair}{\bfseries )}& + the cdr field {\itshape pair} \\ \hline + {\bfseries (cons} {\itshape obj1 obj2}{\bfseries )} & + a new pair whose car field is + {\itshape obj1} and cdr field is {\itshape obj2} \\ \hline + {\bfseries (list} {\itshape arg1 \dots}{\bfseries )} & + a new list consisting of its arguments \\ \hline + {\bfseries (null?} {\itshape list}{\bfseries )} & + {\bfseries \#t} if {\itshape list} is the empty list \\ \hline + {\bfseries (length} {\itshape list}{\bfseries )} & + the number of elements in {\itshape list} \\ \hline + \end{tabular} +\end{center} + +For example, + +\starti + \ii {\bfseries (car '(a b c))}{\itshape =$>$ a} \\ + \ii {\bfseries (cdr '(a b c))}{\itshape =$>$ (b c)} \\ + \ii {\bfseries (cons 'a '(b c))}{\itshape =$>$ (a b c)} \\ + \ii {\bfseries (list 'a 'b 'c)}{\itshape =$>$ (a b c)} \\ + \ii {\bfseries (null? '(a b))}{\itshape =$>$ \#f} \\ + \ii {\bfseries (null? ())}{\itshape =$>$ \#t} +\endi + +The car field and cdr field of a pair can be set using the following two +functions. + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (set-car!} {\itshape pair obj}{\bfseries )} & + sets the car field of {\itshape pair} to + {\itshape obj}. It returns the new pair \\ \hline + {\bfseries (set-cdr!} {\itshape pair obj}{\bfseries )} & + sets the cdr field of {\itshape pair} to + {\itshape obj}. It returns the new pair \\ \hline + \end{tabular} +\end{center} + +These two functions have {\itshape side-effects}, another feature that +distinguishes scheme from pure lisp. Another naming convention +followed is that functions that have side-effects end in ``!''. + +Try the following sequence in magic: + +\starti + \ii {\bfseries (define x '(a b))}{\itshape =$>$ (a b)} \\ + \ii {\bfseries (set-car! x 'c)}{\itshape =$>$ (c b)} \\ + \ii {\bfseries (set-cdr! x '(q))}{\itshape =$>$ (c q)} \\ + \ii {\bfseries (set-cdr! x 'q)}{\itshape =$>$ (c . q)} \\ +\endi + +After the last statement, the value of x is no longer a list but a +pair. + +\subsection{Arithmetic} + +The interpreter supports both floating-point and integer +arithmetic. The basic arithmetic functions are supported. + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (+ }{\itshape num1 num2}{\bfseries )} & + the sum {\itshape num1}+{\itshape num2} \\ \hline + {\bfseries (- }{\itshape num1 num2}{\bfseries )} & + the difference {\itshape num1}-{\itshape num2} \\ \hline + {\bfseries (* }{\itshape num1 num2}{\bfseries )} & + the product {\itshape num1}*{\itshape num2} \\ \hline + {\bfseries (/ }{\itshape num1 num2}{\bfseries )} & + the quotient {\itshape num1}/{\itshape num2} \\ \hline + {\bfseries (truncate }{\itshape num}{\bfseries )} & + the integer part of {\itshape num} \\ \hline + \end{tabular} +\end{center} + +The division operator checks for division by zero, and promotes +integers to floating-point if deemed necessary. Floating-point numbers +can be converted into integers by truncation. The range of a number +can be checked using the following predicates: + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (zero? }{\itshape num}{\bfseries )} & + {\bfseries \#t} if {\itshape num} is zero \\ \hline + {\bfseries (positive? }{\itshape num}{\bfseries )} & + {\bfseries \#t} if {\itshape num} is positive \\ \hline + {\bfseries (negative? }{\itshape num}{\bfseries )} & + {\bfseries \#t} if {\itshape num} is negative \\ \hline + \end{tabular} +\end{center} + +\subsection{Strings} + +The interpreter supports string manipulation. String manipulation can +be useful for interaction with the user as well as constructing names +for labels. + +\begin{center} + \begin{tabular}{|l|p{0.6\columnwidth}|} \hline + {\bfseries (string-append }{\itshape str1 str2}{\bfseries )} & + the string formed by concatenating + {\itshape str1} and {\itshape str2} \\ \hline + {\bfseries (string-length }{\itshape str}{\bfseries )} & + the length of string {\itshape str} \\ \hline + {\bfseries (string-compare }{\itshape str1 str2}{\bfseries )} & + a positive, zero, or negative number depending on whether + {\itshape str1} is lexicographically greater, equal to, + or less than {\itshape str2} \\ \hline + {\bfseries (string-ref }{\itshape str int}{\bfseries )} & + the numerical value of the character stored at position + {\itshape int} in {\itshape str} (The first character + is at position 0.) \\ \hline + {\bfseries (string-set! }{\itshape str int1 int2}{\bfseries )} & + sets character in string {\itshape str} at position + {\itshape int1} to {\itshape int2} \\ \hline + {\bfseries (substring }{\itshape str int1 int2}{\bfseries )} & + returns substring of {\itshape str} from position + {\itshape int1} (inclusive) to {\itshape int2} (exclusive) \\ \hline + \end{tabular} +\end{center} + +Strings can be used to convert to and from various types. + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (number-$>$string }{\itshape num}{\bfseries )} & + the string corresponding to the representation of + {\itshape num} \\ \hline + {\bfseries (string-$>$number }{\itshape str}{\bfseries )} & + the number corresponding to {\itshape str} \\ \hline + {\bfseries (string-$>$symbol }{\itshape str}{\bfseries )} & + a symbol named {\itshape str} \\ \hline + {\bfseries (symbol$->$string }{\itshape sym}{\bfseries )} & + the string corresponding to the name of {\itshape sym} \\ \hline + \end{tabular} +\end{center} + +\subsection{Bindings and functions} + +An object (more accurately, the {\itshape location} where the object is +stored) can be bound to a symbol using the following two functions: + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (define }{\itshape sym expr}{\bfseries )} & + bind {\itshape expr} to {\itshape sym}, creating + a new symbol if necessary and return {\itshape expr} \\ \hline + {\bfseries (set! }{\itshape sym expr}{\bfseries )} & + bind {\itshape expr} to an existing symbol {\itshape sym} + and return {\itshape expr} \\ \hline + \end{tabular} \\ + (Note: these functions do not evaluate their first argument.) +\end{center} + +The difference between the two is that {\bfseries define} introduces a new +binding, whereas {\bfseries set!} modifies an existing binding. In both +cases, {\itshape expr} is evaluated, and the result is bound to the symbol +{\itshape sym}. The result of the evaluation is also returned. + +\starti + \ii {\bfseries (define x 4)}{\itshape $=>$ 4} +\endi + +Functions can be defined using lambda expressions. Typically a +function is bound to a variable. If required, a lambda expression or +built-in function can be applied to a list. + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (lambda }{\itshape list obj}{\bfseries )} & + a new function \\ \hline + \end{tabular} \\ + (Note: a lambda does not evaluate its arguments.) +\end{center} + +{\itshape list} is a list of symbol names, and {\itshape obj} is the expression +that corresponds to the body of the function. For example, + +\starti + \ii {\bfseries (lambda (x y z) (+ (+ x y) z))}{\itshape $=>$ \#proc} +\endi + +is a function that takes three arguments and returns their sum. It can +be bound to a symbol using {\bfseries define}. + +\starti + \ii {\bfseries (define sum3 (lambda (x y z) (+ (+ x y) z)))}{\itshape $=>$ \#proc} +\endi + +Now, we can use {\bfseries sum3} like any other function. + +\starti + \ii {\bfseries (sum3 5 3 8)}{\itshape $=>$ 16} +\endi + +A function can be applied to a list using {\bfseries apply}. + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (apply }{\itshape proc list}{\bfseries )} & + apply {\itshape proc} to {\itshape list} \\ \hline + \end{tabular} \\ + (Note: both {\itshape proc} and {\itshape list} are evaluated before + application.) +\end{center} + +{\itshape list} is used as the list of arguments for the function. For +instance, an alternative way to sum the three numbers in the example +above is: + +\starti + \ii {\bfseries (apply sum3 '(3 5 8))}{\itshape $=>$ 16} +\endi + +An alternative method for creating bindings is provided by the +{\bfseries let} mechanism. + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (let }{\itshape binding-list expr}{\bfseries )} & + evaluate {\itshape expr} after the bindings have + been performed \\ \hline + {\bfseries (let* }{\itshape binding-list expr}{\bfseries )} & + evaluate {\itshape expr} after the bindings have + been performed \\ \hline + {\bfseries (letrec }{\itshape binding-list expr}{\bfseries )} & + evaluate {\itshape expr} after the bindings have + been performed \\ \hline + \end{tabular} +\end{center} + +The {\itshape binding-list} is a list of bindings. Each binding is a list +containing a symbol and an expression. The expression is evaluated and +bound to the symbol. In the case of {\bfseries let}, all the expressions are +evaluated before binding them to any symbol; {\bfseries let*}, on the other +hand, evaluates an expression and binds it to the symbol before +evaluating the next expression. {\bfseries letrec} permits bindings to refer +to each other, permitting mutually recursive function definitions. +The evaluation order is defined to be from left to right in all +cases. After performing the bindings, {\itshape expr} is evaluated with the +new bindings in effect and the result is returned. + +{\bfseries let} bindings can be used in interesting ways. An example of +their use is provided later. + +Scheme is an eager language, and only a few functions do not evaluate +all their arguments (definitions and conditionals). Evaluation can be +controlled to some degree using the following two functions: + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (quote }{\itshape obj}{\bfseries )} & + the unevaluated object {\itshape obj} \\ \hline + {\bfseries (eval }{\itshape obj}{\bfseries )} & + evaluates object {\itshape obj} \\ \hline + \end{tabular} +\end{center} + + +\subsection{Control structures} + +Since scheme is a functional programming language, functions that are +usually written using loops are written using recursion. Conditional +constructs are used to terminate the recursion. These constructs are +slightly different in that they do not evaluate all their arguments +(otherwise recursive functions would not terminate!). + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (if }{\itshape expr arg1 arg2}{\bfseries )} & + evaluate {\itshape expr} and evaluate one + of {\itshape arg1} or {\itshape arg2} \\ \hline + \end{tabular} +\end{center} + +The {\bfseries if} construct evaluates its first argument (which must result +in a boolean), and if the result is {\bfseries \#t} evaluates {\itshape arg1} and +returns the result; otherwise {\itshape arg2} is evaluated and returned. + +For instance, the standard factorial function might be written as: + +\starti + \ii {\bfseries (define fact (lambda (x) (if (positive? x) + (* x (fact (- x 1))) 1)))} +\endi + +A more complicated form of conditional behavior is provided by {\bfseries cond}. + + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (cond }{\itshape arg1 arg2 ...}{\bfseries )} & + generalized conditional \\ \hline + \end{tabular} +\end{center} + +Each argument consists of a list which contains two expressions. The +first expression is evaluated (and must evaluate to a boolean), and if +it is true the second expression is evaluated and returned as the +result of the entire expression. If the result was false, the next +argument is examined and the above procedure is repeated. If all +arguments evaluate to false, the result is undefined. + +For instance if {\bfseries x} was a list, the expression + +\starti + \ii {\bfseries (cond ((null? x) x) ((list? x) (car x)) (\#t (echo {\q}error{\q})))} +\endi + +would return the empty list if {\bfseries x} was the empty list and the +first element from the list otherwise. When {\bfseries x} is not a list, an +error message is displayed. Note that {\bfseries echo} is a standard magic +command. + +Often one needs to evaluate a number of expressions in +sequence (since the language has side-effects). The {\bfseries begin} +construct can be used for this purpose. + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (begin }{\itshape arg1 arg2 \dots}{\bfseries )} & + sequencing construct \\ \hline + \end{tabular} +\end{center} + +{\bfseries begin} evaluates each of its arguments in sequence, and returns +the result of evaluating its last argument. + +\subsection{Interaction with layout} + +All standard magic commands are also scheme functions. This permits +one to write scheme functions that interact with the layout +directly. Apart from the standard magic commands, the following scheme +functions are provided so as to enable the user to edit layout. + +\begin{center} + \begin{tabular}{|l|p{0.6\columnwidth}|} \hline + {\bfseries (getbox)} & + a list containing four members (llx lly urx ury) \\ \hline + {\bfseries (getpaint }{\itshape str}{\bfseries )} & + a list containing the boxes from layer {\itshape str} + under the current box that have paint in them \\ \hline + {\bfseries (getlabel }{\itshape str}{\bfseries )} & + a list containing the labels under the current box that + match {\itshape str} \\ \hline + {\bfseries (magic }{\itshape sym}{\bfseries )} & + forces {\itshape sym} to be interpreted as a + magic command \\ \hline + \end{tabular} +\end{center} + +The pairs (llx,lly) and (urx,ury) correspond to magic coordinates for +the lower left and upper right corner of the current +box. {\bfseries getpaint} returns a list of boxes (llx lly urx ury), and +{\bfseries getlabel} returns a list of tagged boxes (label llx lly urx ury) +which contain the label string. {\bfseries magic} can be used to force the +scheme interpreter to interpret a symbol as a magic procedure. The +evaluation returns the specified magic command. + + +\subsection{Miscellaneous} + +Some additional functions are provided to enable the user to debug +functions. + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (showframe)} & + display the current list of bindings \\ \hline + {\bfseries (display-object }{\itshape obj}{\bfseries )} & + display the type and value of {\itshape obj} \\ \hline + {\bfseries (error }{\itshape str}{\bfseries )} & + display error message and abort evaluation \\ \hline + {\bfseries (eqv? }{\itshape obj1 obj2}{\bfseries )} & + checks if two objects are equal \\ \hline + {\bfseries (collect-garbage)} & + force garbage collection \\ \hline + \end{tabular} +\end{center} + +The following is a complete list of the built-in scheme variables that +can be used to control the interpreter. + +\begin{center} + \begin{tabular}{|l|p{0.6\columnwidth}|} \hline + {\bfseries scm-library-path} & + a colon-separated path string \\ \hline + {\bfseries scm-echo-result} & + a boolean used to determine if the result of evaluation + should be displayed \\ \hline + {\bfseries scm-trace-magic} & + controls display of actual magic commands \\ \hline + {\bfseries scm-echo-parser-input} & + controls display of the string sent to the scheme parser \\ \hline + {\bfseries scm-echo-parser-output} & + controls display of the result of parsing \\ \hline + {\bfseries scm-stack-display-depth} & + controls the number of frames displayed in the stack trace + output when an error occurs during evaluation \\ \hline + {\bfseries scm-gc-frequency} & + controls the frequency of garbage collection \\ \hline + \end{tabular} +\end{center} + +\subsection{Libraries} + +The following function loads in a file and evaluates its contents in order. + +\begin{center} + \begin{tabular}{|l|l|} \hline + {\bfseries (load-scm }{\itshape str}{\bfseries )} & + reads scheme commands in from the named file \\ \hline + {\bfseries (save-scm }{\itshape str obj}{\bfseries )} & + appends {\itshape obj} to the file {\itshape str}, + creating a new file if necessary \\ \hline + \end{tabular} +\end{center} + +The file can be in the current directory, or in any of the +locations specified by a string containing a colon-separated list of +directory names stored in {\bfseries scm-library-path}. + +The format of these files differs from standard magic source files +because the contents of a line are not implicitly +parenthesized. In addition, semicolons are used as a comment +character; everything following a semicolon to the end of the current +line is treated as a comment. + +For instance, + +\starti + \ii {\bfseries define f (lambda (x) x)} +\endi + +would define {\bfseries f} to be the identity function when placed in a +magic source file (so as to provide backward compatibility). The same +definition would result in an error if placed in a scheme source +file. + +\starti + \ii {\bfseries (define f (lambda (x) x))} +\endi + +The above expression should be used in the scheme file to achieve the +same effect. + +\begin{thebibliography}{2} + +\bibitem{sussman} +H. Abelson and G.J. Sussman, +\newblock {\itshape Structure and Interpretation of Computer Programs}. + +\bibitem{abelson} +H. Abelson {\itshape et al.}, +\newblock {\itshape Revised Report on the Algorithmic Language Scheme}. +\end{thebibliography} + +\end{document} diff --git a/doc/latexfiles/tutscm2.tex b/doc/latexfiles/tutscm2.tex new file mode 100644 index 00000000..6d8531ee --- /dev/null +++ b/doc/latexfiles/tutscm2.tex @@ -0,0 +1,269 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number S-2 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\=\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\q{\special{ps:(") show}\hspace*{0.6em}} +\def\mytitle{Magic Tutorial \#S-2: Boxes and labels} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Rajit Manohar} \\ + \vspace*{0.5in} + Department of Computer Science \\ + California Institute of Technology \\ + Pasadena, CA 91125 \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#S-1: The scheme command-line interpreter +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :getbox, :box.push, :box.pop, :box.move, :label.vert, :label.horiz, \\ + \> :label.rename, :label.search, :label.find-next +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (None)} +\endi + +\vspace*{0.25in} +\section{The current box} + +The fundamental way scheme programs interact with magic layout is by +using magic's {\bfseries box} command. For instance, + +\starti + \ii {\bfseries (box 1 1 2 2)} +\endi + +changes the current box to the rectangle defined by the coordinates +(1,1) and (2,2) in the current edit cell. This is the standard magic +{\bfseries :box} command. After moving the box to a particular position in +the layout, the area can be painted, erased, selected, etc. + + +The scheme function {\bfseries getbox} returns the current box as a list of +four integers. For instance, + +\starti + \ii {\bfseries (box 1 1 2 2)} \\ + \ii {\bfseries (define x (getbox))} +\endi + + +will bind the list {\bfseries (1 1 2 2)} to variable {\bfseries x}. + +\section{Saving and restoring the box} + +If a scheme function moves the current box around, it is good practice +to restore the box back to its original position. This is especially +useful when writing a function that the user is likely to type on the +command line. + +{\bfseries box.push} can be used to push a box onto the current stack of +boxes. {\bfseries box.pop} restores the box to the one on the top of the box +stack. The sequence + +\starti + \ii {\bfseries (box.push (getbox))} \\ + \ii {\bfseries (box 1 1 5 4)} \\ + \ii {\bfseries (paint poly)} \\ + \ii {\bfseries (box.pop)} +\endi + +will paint a rectangle of polysilicon from (1,1) to (5,4), restoring +the original position of the box. + +\section{Moving the box} + +Magic's built-in {\bfseries move} command is not entirely +reliable. Sometimes move commands are ignored, with disastrous +effects. (Think about what might happen if a move command was ignored +in the middle of drawing a stack of twenty transistors . . .) The +scheme function {\bfseries box.move} moves the box relative to the current +position. + +\starti + \ii {\bfseries (box.move 5 3)} +\endi + +will move the box right 5 lambda and up 3 lambda. + +\section{Labelling vertical and horizontal wires} + +Datapaths are usually designed by designing cells for a single bit of +the datapath, and then arraying those cells to obtain the complete +datapath. When simulating such designs, it is usually desirable to +label wires in the datapath with names like ``name0'', ``name1'', up to +``nameN.'' + +There are two functions that can be used to perform such a task. The +function {\bfseries label.vert} returns a function that can be used as a +labeller for vertically arrayed nodes. {\bfseries label.horiz} returns a +function that can be used as a labeller for horizontally arrayed +nodes. + +\starti + \ii {\bfseries (define lbl (label.vert {\q}name{\q} 6)} +\endi + +The command above defines a new function {\bfseries lbl} that can be used to +generate labels beginning with {\q}name0{\q} for nodes that are vertically +spaced by 6 lambda. The simplest way to use this function is to bind +it to a macro as follows: + +\starti + \ii {\bfseries (macro 1 {\q}lbl{\q})} +\endi + +Place the box over the lowest node. Every time key ``1'' is pressed, a +new label ``nameM'' is created and the box is moved up by 6 +lambda. {\bfseries label.horiz} can be used in a similar fashion for +labelling nodes that are horizontally arrayed. + +\section{Finding and renaming existing labels} + +The label macros provide functionality to search for all labels +that match a particular string. Place the box over the region of +interest. Type: + +\starti + \ii {\bfseries (label.search {\q}label{\q})} +\endi + +To place the box over the first occurrence of the label you searched +for, type: + +\starti + \ii {\bfseries (label.find-next)} +\endi + +Repeatedly executing this function causes the box to move to all the +labels that match the search pattern. Typically, one would bind +{\bfseries label.find-next} to a macro. + +The command {\bfseries label.rename} can be used to rename all labels with a +particular name. To use this command, place the box over the region of +interest. Then type + +\starti + \ii {\bfseries (label.rename {\q}label1{\q} {\q}label2{\q})} +\endi + + +All occurrences of label ``label1'' in the current box will be +renamed to ``label2''. + +\section{Writing these functions} + +The functions discussed in this tutorial are not built-in. They are +user-defined functions in the default scheme file loaded in when magic +starts. + +As you begin to use magic with the scheme command-line interpreter, +you will observe that commands for drawing paint on the screen are +extremely slow. This time interval is not normally noticeable because +editing is interactive. However, when one can write a scheme program +to draw twenty transistors on the screen, this delay becomes +noticeable. It is worthwhile to minimize the number of magic commands +executed, even if this involves writing more scheme code. The +{\bfseries box-pop} command has been tuned a little to not execute the +{\bfseries box} command if the box would not move as a result. + +\bfseries +\starti +\> (define box.list ()) \\ \\ + +\> (define box.move \\ +\>\> (lambda (dx dy) \\ +\ii (let* ((x (getbox)) \\ +\ii\> (nllx (+ dx (car x))) \\ +\ii\> (nlly (+ dy (cadr x))) \\ +\ii\> (nurx (+ dx (caddr x))) \\ +\ii\> (nury (+ dy (cadddr x)))) \\ +\ii (box nllx nlly nurx nury) \\ +\ii ) \\ +\>\> ) \\ +\> ) \\ \\ + +\> (define box.=? \\ +\>\> (lambda (b1 b2) \\ +\ii (and (and (=? (car b1) (car b2)) (=? (cadr b1) (cadr b2))) \\ +\ii\> (and (=? (caddr b1) (caddr b2)) (=? (caddr b1) (caddr b2))) \\ +\ii ) \\ +\>\> ) \\ +\> ) \\ \\ + +\> (define box.push \\ +\>\> (lambda (pos) \\ +\ii (set! box.list (cons pos box.list)) \\ +\>\> ) \\ +\> ) +\endi + + +\starti +\> (define box.pop \\ +\>\> (lambda () \\ +\ii (if (null? box.list) \\ +\ii\> (echo {\q}Box list is empty{\q}) \\ +\ii\> (let ((x (car box.list))) \\ +\ii\>\> (begin \\ +\ii\>\> (set! box.list (cdr box.list)) \\ +\ii\>\> (if (box.=? x (getbox)) \#t (eval (cons 'box x))) \\ +\ii\>\> ) \\ +\ii\> ) \\ +\ii ) \\ +\>\> ) \\ +\> ) +\endi + +\end{document} diff --git a/doc/latexfiles/tutscm3.tex b/doc/latexfiles/tutscm3.tex new file mode 100644 index 00000000..2bab3ec1 --- /dev/null +++ b/doc/latexfiles/tutscm3.tex @@ -0,0 +1,161 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number S-3 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#S-3: Transistor stacks} +\def\q{\special{ps:(") show}\hspace*{0.6em}} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Rajit Manohar} \\ + \vspace*{0.5in} + Department of Computer Science \\ + California Institute of Technology \\ + Pasadena, CA 91125 \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#S-1: The scheme command-line interpreter +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :stack.p, :stack.n, :stack.tallp, :stack.talln, :prs.draw, :prs.mgn, \\ + \> :prs.talldraw, :prs.tallmgn +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (None)} +\endi + +\vspace*{0.75in} +\section{Stacks} + +The first step in laying out a gate/operator using magic tends to +involve drawing the transistor stacks without any wiring, labelling +all the important nodes in the circuit. Since the extractor pretends +that nodes that have the same label are electrically connected, the +extracted circuit can be simulated using SPICE to obtain some +indication of the power/speed of the circuit. + +{\bfseries stack.tallp} and {\bfseries stack.talln} can be used to draw such +transistor stacks and place contacts where required. These two +functions take a transistor width and a list of strings that represent +the stack as their arguments, and draw the stack vertically (gates run +horizontally) at the current box. For example, + +\starti + \ii {\bfseries (stack.tallp 40 '(({\q}Vdd{\q}) {\q}a{\q} {\q}b{\q} + ({\q}Inode{\q}) {\q}d{\q} ({\q}out{\q})))} +\endi + +draws a vertical stack of p-transistors with the diffusion being 40 +lambda wide. The stack begins with a contact labelled ``Vdd'', followed +by two gates labelled ``a'' and ``b'', followed by a contact labelled +``Inode'', followed by a gate labelled ``d'', followed by a contact +labelled ``out''. Contacts are indicated by placing the string for the +label in parenthesis. Note the presence of the quote that prevents the +interpreter from attempting to evaluate the list. + +The contact width and contact-gate spacing together amount to more +than the spacing between adjacent gates. Often it is desired to +eliminate this extra space by jogging the poly wires so that the +amount of internal diffusion capacitance is minimized. The functions +{\bfseries stack.p} and {\bfseries stack.n} can be used to do so. Typing + +\starti + \ii {\bfseries (stack.tallp 40 '(({\q}Vdd{\q}) {\q}a{\q} {\q}b{\q} + ({\q}Inode{\q}) {\q}d{\q} ({\q}out{\q})))} +\endi + + +will draw the same stack and jog the poly wires corresponding to the +gate for ``d''. + +\section{Production rules} + +The functions {\bfseries prs.draw} and {\bfseries prs.mgn} can be used to draw the +transistor stacks that implement a production rule. For instance, + +\starti + \ii {\bfseries (prs.draw 40 {\q}x \& y $->$ z-{\q})} +\endi + +will draw the stack required to implement the specified production +rule with width 20. The function takes a gate width and a single +production rule as its arguments. Note that the production rules must +be in negation normal form, i.e., all negations must be on variables. + +Contacts can be shared between operators by providing a list of +production rules as input to {\bfseries prs.mgn}, as follows: + +\starti + \ii {\bfseries (prs.mgn 40 20 {\q}x \& y $->$ z-{\q} + {\q}u \& v $->$ w-{\q} {\q}\~{}x \& \~{}y $->$ z+{\q})} +\endi + +The contact to GND will be shared between the pull-down stacks for z +and w. + +Both production-rule drawing function ensure that the variable order +in the production rule (from left to right) corresponds to the gate +order in the transistor stacks (from power supply to output). + +It is not always possible to directly draw a production rule in a +single stack with no additional internal contacts. In this case, the +function creates an internal node name of the form ``{\_}'' followed by a +number. You can search for these using {\bfseries (label.search {\q}{\_}*{\q})}, +followed by {\bfseries (label.find-next)}. To complete the implementation, +you will have to wire up these internal contacts as well. + +Both {\bfseries prs.mgn} and {\bfseries prs.draw} draw the transistor stacks using +{\bfseries stack.p} and {\bfseries stack.n}. The variants {\bfseries prs.tallmgn} and +{\bfseries prs.talldraw} use {\bfseries stack.tallp} and {\bfseries stack.talln} +instead. + +\end{document} diff --git a/doc/latexfiles/tutscm4.tex b/doc/latexfiles/tutscm4.tex new file mode 100644 index 00000000..8624c2d9 --- /dev/null +++ b/doc/latexfiles/tutscm4.tex @@ -0,0 +1,78 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number S-4 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#S-4: The design rule file} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Rajit Manohar} \\ + \vspace*{0.5in} + Deparment of Computer Science \\ + California Institute of Technology \\ + Pasadena, CA 91125 \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#S-1: The scheme command-line interpreter +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> :drc.\* +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (None)} +\endi + +\vspace*{0.25in} +\section{Introduction} + +\end{document} diff --git a/doc/latexfiles/tuttcl1.tex b/doc/latexfiles/tuttcl1.tex new file mode 100644 index 00000000..82999c2a --- /dev/null +++ b/doc/latexfiles/tuttcl1.tex @@ -0,0 +1,581 @@ +%---------------------------------------------------------------------------- +% Magic Tcl tutorial number 1 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ig{\>} +\def\ih{\>\>} +\def\ii{\>\>\>} +\def\mytitle{Magic Tcl Tutorial \#1: Introduction} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape R. Timothy Edwards} \\ + \vspace*{0.5in} + Space Department \\ + Johns Hopkins University \\ + Applied Physics Laboratory \\ + Laurel, MD 20723 \\ + \vspace*{0.25in} + This tutorial corresponds to Tcl-based Magic version 7.2 \\ +\end{center} +\vspace*{0.5in} + +\section{What is Tcl-based Magic, and Why?} + +In Magic version 7.0, Rajit Manohar incorporated a SCHEME interpreter into +the Magic source, noting the limitation of magic to handle definitions +and variables, conditionals, and block structures. By embedding an +interpreter into the code, the interpreter's functions are made available +on the magic command line, making magic extensible. The SCHEME interpreter +and various extensions incorporated into loadable scripts are outlined +in the tutorials {\ttfamily tutscm1.ps} through {\ttfamily tutscm4.ps}. + +While making Magic considerably more flexible, the embedded SCHEME +interpreter had some notable drawbacks. The primary one is that the +SCHEME language is syntactically different from Magic's command-line +syntax. Also, the interpreter is largely disconnected from the code, +and does not affect or extend the graphics or handle results from magic +commands. + +Beginning in Magic version 7.2, Magic has been recast into a framework +called {\it ScriptEDA}, in which existing applications become +{\bfseries extensions} of an interpreter rather than having an interpreter +embedded in the application. The main advantage of extending over +embedding is that the application becomes a module of the interpreter +language, which does not preclude the use of additional, unrelated +modules in the same interpretive environment. For example, in Tcl-based +Magic, graphics are handled by Tk (the primary graphics package for +use with Tcl), and applications such as IRSIM (the digital simulator) +can be run as if they were an extension of magic itself. Commands for +Tcl, Tk, IRSIM, BLT, and any other Tcl-based package can be mixed on +the magic command line. + +While {\it ScriptEDA} suggests the use of the {\bfseries SWIG} package to give +applications the ability to be compiled as extensions of any interpreter +(Tcl, Python, SCHEME, Perl, etc.), there are specific advantages to +targeting Tcl. Foremost, the syntax of Tcl is virtually 100\% compatible +with that of Magic. This is not coincidentally because both Magic and +Tcl were written by John Ousterhout! Many ideas from the development of +Magic were incorporated into the overall concept and design of the Tcl +interpreter language. + +Largely due to the syntactical compatibility, Tcl-based magic is +completely backwardly-compatible with the non-interpreter version of +magic. Either can be selected at compile-time, in addition to compiling +with embedded SCHEME, which has been retained in full as an option. +A few minor issues, such as the appearance of the cursor when magic is +used without a Tk console window, are addressed below. + +Magic extensions under Tcl are considerable, and explanations of the +features have been split into several tutorial files, as listed in +Table~\ref{tutorials}. + +\begin{table}[ht] + \begin{center} + \begin{tabular}{|l|} \hline + Magic Tcl Tutorial \#1: Introduction \\ + Magic Tcl Tutorial \#2: The GUI Wrapper \\ + Magic Tcl Tutorial \#3: Extraction and Netlisting \\ + Magic Tcl Tutorial \#4: Simulation with IRSIM \\ + Magic Tcl Tutorial \#5: Writing Tcl Scripts for Magic \\ \hline + \end{tabular} + \end{center} + \caption{The Magic Tcl tutorials and other documentation.} + \label{tutorials} +\end{table} + +\section{Features of Tcl-based Magic} + +In summary, the features of Tcl-based Magic (corresponding to Magic version +7.2, revision 31) are as follows: + +\begin{enumerate} + \item The command name {\bfseries magic} itself is a script, not a compiled + executable. The script launches Tcl and gives it the name of a Tcl + script to evaluate ({\ttfamily magic.tcl}). The Tcl script loads + Magic as an extension of Tcl and performs all other operations + necessary to start up the application. + \item Command-line arguments passed to Magic have been changed. Some older, + unused arguments have been removed. Several arguments have been + added, as follows: + \begin{enumerate} + \item {\ttfamily -noconsole} Normally, under Tcl/Tk, Magic starts + by launching a Tk-based console window ({\ttfamily tkcon.tcl}) + which is the window that accepts magic commands. Previous + versions of Magic accepted commands from the calling terminal. + The former style of running commands from the calling terminal + can be selected by choosing this argument at runtime. Note, + however, that due to fundamental differences in the underlying + input routines between Tcl and magic, the terminal-based + command entry does not exactly match the original behavior + of magic. In particular, the background DRC function does + not change the prompt. In addition, ``Xterm'' consoles + must select option ``Allow SendEvents'' for keystrokes to + be echoed from the layout window into the terminal. For + security reasons, the application cannot change this option + on the terminal. + \item {\ttfamily -wrapper} To enforce backward-compatibility, + magic appears as it would without the Tcl interpreter + (apart from the text entry console) when launched with the + same arguments. However, most users will want to make use + of the extensions and convenience functions provided by + the ``wrapper'' GUI. These functions are detailed in a + separate tutorial (see Tutorial~\#2). + \end{enumerate} + \item Magic-related programs ``ext2spice'' and ``ext2sim'' have been + recast as magic commands instead of standalone executables. This + makes a good deal of sense, as both programs make heavy use of + the magic internal database. Most values required to produce + netlists were passed through the intermediary file format {\ttfamily + .ext}. However, not all necessary values were included in the + {\ttfamily .ext} file format specification, and some of these + missing values were hard-coded into the programs where they have + since become mismatched to the magic database. This has been + corrected so that all netlist output corresponds to the technology + file used by a layout. + + Both commands ``ext2spice'' and ``ext2sim'' allow all of the + command-line arguments previously accepted by the standalone + programs. Some of the more common functions, however, have + been duplicated as command options in the usual format of + magic commands. For instance, one may use the magic command: + \starti + \ii {\bfseries ext2sim help} + \endi + to get more information on {\ttfamily ext2sim} command-line + options. + \item All Tcl interpreter procedures may be freely mixed with magic + commands on the command line. For instance, a user can use + Tcl to compute arithmetic expressions on the command line: + \starti + \ii {\bfseries copy e [expr\{276 * 5 + 4\}]} + \endi + \item A number of magic commands pass values back to the interpreter. + For instance, the command + \starti + \ii {\bfseries box values} + \endi + returns the lower left- and upper right-hand coordinates of the + cursor box in magic internal units. This return value can be + incorporated into an expression, such as the one below which + moves the box to the left by the value of its own width: + \starti + \ii {\bfseries set bbox [box values]} \\ + \ii {\bfseries set bwidth \[expr \{[lindex \$bbox 2] - [lindex + \$bbox 0]\}]} \\ + \ii {\bfseries move e \$bwidth} + \endi + \item Magic prompts for text have been recast as Tk dialog boxes. + For instance, the command {\bfseries writeall} will pop up a + dialog box with five buttons, one for each of the available + choices (write, flush, skip, abort, and auto). + \item IRSIM is no longer available as a ``mode'' reached by switching + tools by command or the space-bar macro. Instead, IRSIM (version + 9.6) can be compiled as a Tcl extension in the same manner as + Magic, at compile time. When this is done, IRSIM is invoked + simply by typing + \starti + \ii {\bfseries irsim} + \endi + on the Magic command line. IRSIM is loaded as a Tcl package, + and IRSIM and Magic commands may be freely mixed on the Magic + command line: + \starti + \ii {\bfseries assert [getnode]} + \endi + IRSIM does not require the name of a file to start. Without + arguments, it will assume the currently loaded cell is to be + simulated, and it will generate the {\ttfamily .sim} file if + it does not already exist. + + \item In addition to IRSIM, programs {\bf xcircuit} and {\bf + netgen} can be compiled as Tcl extensions and provide + cabability for schematic capture and layout-vs.-schematic, + respectively. + + \item Tcl-based Magic makes use of the Tcl variable space. For + instance, it keeps track of the installation directory + through the variable {\ttfamily CAD\_HOME}, which mirrors + the value of the shell environment variable of the same + name. In addition, it makes use of variables {\ttfamily + VDD} and {\tt GND} in the technology file to aid in the + extraction of substrate- and well-connected nodes on + transistors. + + \item Magic input files, such as the {\ttfamily .magic} startup + file, are sourced as Tcl scripts, and so may themselves + contain a mixture of Tcl and magic commands. + +\end{enumerate} + +\section{Compilation and Installation} + + Magic is selected for compilation as a Tcl extention when running + the + \starti + \ii {\bfseries make config} + \endi + script. The first question asks whether magic should be compiled + as a Tcl extension, with the SCHEME interpreter embedded, or as + the original version with no interpreter. Subsequent to choosing + Tcl as the interpreter and answering the remaining configuration + questions, Tcl should be compiled and installed using the commands + \starti + \ii {\bfseries make tcl} + \endi + and + \starti + \ii {\bfseries make install-tcl} + \endi + Note that if magic is to be compiled under different interpreters, + it is necessary to perform + \starti + \ii {\bfseries make clean} + \endi + between the compilations, so that all references to the last + compiled version are deleted. + +\section{Dual-Source Input and Backward Compatibility} + +From its inception, Magic has used an unsual but very effective interface +in which commands may be passed to the program from two different sources, +the layout window, and the calling terminal. Keystrokes in the layout +window are handled by the graphics package. These are interpreted as +{\itshape macros}. The keystroke values are expanded into magic command-line +commands and executed by the command-line command dispatcher routine. Two +macros, `{\ttfamily .}' and `{\ttfamily :}' are reserved: The period +expands to the last command executed from the command line ({\itshape not} +from a macro expansion), and the colon initiates a redirection of keystrokes +from the layout window into the calling terminal. Magic users quickly +get used to the combination of keystrokes, mouse functions, and +command-line commands. + +In the Tcl-based version of Magic, the command-line dispatching is given +over entirely to Tcl, and the dispatching of keystroke events in the layout +window is given over entirely to Tk. Unfortunately, in relinquishing +these duties, Magic loses some of the effectiveness of its dual-source +input model. One aspect of this is that Tcl is a line-based interpreter, +and does not recognize anything on the command line until the return key +has been pressed and the entire line is passed to the command dispatcher +routine. Without any understanding of character-based input, it is +difficult to impossible to directly edit the command line from outside the +calling terminal, because it is the terminal, and not Tcl, which interprets +keystrokes on a character-by-character basis. + +The way around this problem is to use a {\itshape console}, which is an +application that runs in the manner usually expected by Tk, in that it is +a GUI-driven application. The interpreter is split into {\itshape master} +and {\itshape slave} interpreters (see the Tcl documentation on the +{\bfseries interp} command), with the master interpreter running the +console application and the slave interpreter running the application. +The master interpreter then has character-based control over the command +line, and the Magic dual-source input model can be implemented exactly as +originally designed. The background DRC function can change the command +line cursor from `{\itshape \%}' to `{\itshape ]}' to indicate that the +DRC is in progress, and user input can be redirected from the layout +window to the console with the `{\bfseries :}' keystroke. + +In addition to these functions, the console makes use of Tcl's ability +to rename commands to recast the basic Tcl output function +`{\bfseries puts}' in such a way that output to {\ttfamily stdout} and +{\ttfamily stdin} can be handled differently. In the {\bfseries TkCon} +console, output to {\ttfamily stdout} is printed in blue, while output +to {\ttfamily stderr} is printed in red. Magic makes use of Tcl's +output procedures so that returned values and information are printed +in blue, while warnings and error messages are printed in red. The +console also implements command-line history and cut-and-paste methods. +The console command-line history replaces the embedded {\itshape readline} +implementation in magic. + +The {\bfseries TkCon} console is a placeholder for what is intended to +be a ``project manager'' console, with functions more appropriate to +the Electronic Design Automation suite of Tcl-based tools. In general, +the menu functions which are displayed on the TkCon console are not +of particular interest to the Magic user, with the exception of the +{\bfseries History} menu, which can be used to re-enter previously +executed commands, and the {\bfseries Prefs} menu, which includes +highlighting options and a very useful calculator mode. + +\section{Tk Graphics Methods} + +Because the graphics under Tcl are managed by the Tk package, the only +graphics options which can be compiled are the X11 and the OpenGL +options. There are numerous differences between these graphics +interfaces as they exist under Tcl and under the non-Tcl-based version. +The two primary differences are the way windows are generated and the +way commands are sent to specific windows. In Tcl-based magic, a +layout window does not have to be a top-level application window. +by using the command syntax +\starti + \ii {\bfseries openwindow} {\itshape cellname tk\_pathname} +\endi + +An unmapped window can be generated, corresponding to the Tk window +hierarchy specified by {\itshape tk\_pathname} (see the Tk documentation +for the specifics of Tk window path name syntax). This window is then +mapped and managed by Tk commands. Using this method, a magic window +can be embedded inside a ``wrapper'' application, an example of which +has been done with the GUI wrapper invoked with the ``{\ttfamily -w}'' +command-line argument. Extensions of magic window commands have been +added so that the wrapper can control the window frame, including the +scrollbars and title. + +Whenever a window is created, Magic creates a Tcl/Tk command with the +same name as the window (this is conventional practice with Tk widgets). +Magic and Tcl commands can be passed as arguments to the window +command. Such commands are executed relative to the specific window. +This applies to all of magic's window-based commands, including +instructions such as {\bfseries move}, {\bfseries load}, and so forth. +Commands which apply to all windows will automatically be sent to all +windows. These commands are used primarly by the wrapper GUI, but are +also called (transparently to the end user) whenever a command is +executed from a layout window via any macro, including the +`{\bfseries :}' command-line entry. In addition, however, +they may be called from the command line to perform an action +in a specific window. By default (in the absence of a wrapper GUI), +magic's windows are named {\itshape .magic1}, {\itshape .magic2}, and +so forth, in order of appearance, and these names are reflected in the +title bar of the window. So it is equivalent to do +\starti + \ii {\bfseries :move s 10} +\endi +from layout window `{\itshape .magic2}' (where the colon indicates the +key macro for command-line entry), and +\starti + \ii {\bfseries .magic2 move s 10} +\endi +typed in the console. + +\section{Tutorial Examples} + +Example sessions of running magic in various modes are presented below, +along with examples of methods specific to each mode. In the examples +below, prompts are shown to indicate the context of each command. +The {\itshape \#} sign indicates the shell prompt, {\itshape (gdb)} +indicates the GNU debugger prompt, and {\itshape \%} indicates the Tcl +(i.e., Magic) prompt. + +\medskip +\noindent {\bfseries \itshape Example 1: Standard Magic Execution} \\ + +Run Tcl-based magic in its most basic form by doing the following: +\starti + \ii {\itshape \#} {\bfseries magic -noconsole tut2a} \\ +\endi + +Magic looks generally like its traditional form, except that the +command-line prompt is the Tcl `{\itshape \%}' prompt. It should be +possible to write commands from either the terminal or using the +colon keystroke, and it is possible to partially type a command +after the colon keystroke and finish the command inside the terminal, +but not vice versa. Enabling the colon keystroke may require setting +``Allow SendEvents'' mode on the calling terminal. + +\medskip +\noindent {\bfseries \itshape Example 2: Console-based Magic Execution} \\ + +Run the TkCon console-based magic by doing the following: +\starti + \ii {\itshape \#} {\bfseries magic tut2a} \\ +\endi + +The layout window will still look like the usual, basic form. However, +the calling terminal will be suspended (unless the application is +backgrounded; however, if backgrounding the application, be aware that +any output sent to the terminal will hang the application until it is +foregrounded) and the Tcl prompt will appear in a new window, which is +the {\bf console}. The console may have a slightly different appearance +depending on the graphics mode used. For instance, magic has historically +had difficulties running in 8-bit (PseudoColor) graphics mode, because +it installs its own colormap. Because it does not share the colormap +with the calling terminal, the calling terminal gets repainted in random +colors from magic's colormap when the cursor is in the layout window. In +unlucky setups, text and background may be unreadable. + +In the TkCon console setup, the console is mapped prior to determining +the graphics mode required, so it also does not share the colormap. +However, it is possible to query Magic's colormap to find the location +of specific colors, and repaint the text and background of the console +accordingly. Thus, the Magic console can be used when the display is +in 8-bit PseudoColor mode, without extreme color remappings in the +console which make it potentially impossible to read the console when +the cursor is in a layout window. + +If compiled with both OpenGL and X11 graphics capability, magic will +start in X11 mode by default. The OpenGL interface can only be +enabled at startup by specifying: +\starti + \ii {\itshape \#} {\bfseries magic -d OGL tut4x} \\ +\endi +The OpenGL interface, in addition to having more solid, vibrant +colors, has an additional feature which draws three-dimensional views +of a layout. This is discussed in Tutorial~\#??. + +\medskip +\noindent {\bfseries \itshape Example 4: The Magic Wrapper GUI} \\ + +The magic GUI interface is invoked by starting magic with the {\bfseries +-w} option: +\starti + \ii {\itshape \#} {\bfseries magic -w tut2b} \\ +\endi + +The immediately noticeable differences are the layer toolbar on the side, +and the menu and redesigned title bar on the top. Experimenting with +some mouse clicks, the user will note that the magic coordinates of the +cursor box are displayed on the right-hand side of the titlebar. + +The toolbar contains one example of each layer defined in the magic +technology file. Position a box on the screen, then put the cursor +over a layer icon and press the middle mouse button. This paints the +layer into the box. You will also notice that the name of the layer +is printed in the title bar while the cursor is over the layer icon. + +The icons have other responses, too. The first and third mouse buttons +respectively show and hide the layer in the layout. This works with +labels, subcell boundaries, and error paint (the top three layer icons) +as well as with regular paintable layers. In addition to mouse button +responses, the buttons invoke various commands in reponse to keystrokes. +Key `p' paints the layer; key `e' erases it. Key `s' selects the layer +in the box while key `S' unselects it. + +The menubar has three items, {\bfseries File}, {\bfseries Cell}, and +{\bfseries Tech}. Button {\bfseries File} pops up a menu with options +to read and write layout, read and write CIF or GDS output, open a new +layout window or close the existing one, or flush the current edit cell. +Buttons {\bfseries Cell} and {\bfseries Tech} reveal transient windows +showing information about the cell hierarchy and the technology file, +respectively. The cell hierarchy view is only available if the Tcl/Tk +package {\bfseries BLT} has been compiled and installed on the system. +If so, it gives a tree view of the cell hierarchy and allows specific +cells to be loaded, edited, and expanded, or viewed to fit the window. +This can be expecially useful for querying the cell hierarchy of GDS +files, which do not declare top-level cells like CIF files do. + +The technology manager window reports the current technology file, its +version and description, and the current CIF input and output styles, +the current extraction style, and the current value of lambda in microns. +The technology file and the CIF input and output styles and extraction +style are also buttons which can be used to select a new style or technology +from those currently available. Clicking on the current extract style, for +instance, gives a list of the styles which have been specified in the +current technology file. Clicking on one of the entries in the list makes +it the new current extract style. + +Cell hierarchy and technology manager windows should be closed by clicking +on the ``Close'' button at the bottom, not by invoking any titlebar functions +(which will probably cause the whole application to exit). + +\medskip +\noindent {\bfseries \itshape Example 5: Batch-mode Magic} \\ + +Unlike previous versions of magic, it is not necessary to have a layout +window present to run magic. Magic may be invoked in ``batch mode'' by +the following command-line: +\starti + \ii {\itshape \#} {\bfseries magic -nowindow tut2b} \\ +\endi + +Note however, that most magic commands expect a window to be present to +execute the function. The main use for batch mode is for wrapper-type +applications to delay opening a layout window until one is requested. +For example: +\starti + \ii {\itshape \#} {\bfseries magic -nowindow tut2b} \\ + \ii {\itshape \%} {\bfseries toplevel .myframe} \\ + \ii {\itshape \%} {\bfseries openwindow tut2b .myframe.mylayout} \\ + \ii {\itshape \%} {\bfseries pack .myframe.mylayout} \\ + \ii {\itshape \%} {\bfseries .myframe.mylayout box 0 0 12 12} \\ + \ii {\itshape \%} {\bfseries .myframe.mylayout select area poly} \\ + \ii {\itshape \%} {\bfseries wm withdraw .myframe} \\ + \ii {\itshape \%} {\bfseries wm deiconify .myframe} \\ + \ii {\itshape \%} {\bfseries .myframe.mylayout closewindow} \\ +\endi + +Note that this is the basic setup of the standard GUI wrapper, albeit with +much greater sophistication. The standard GUI wrapper is generated +entirely by script, which can be found in the library directory +{\bfseries \$\{CAD\_HOME\}/lib/magic/tcl/wrapper.tcl}. + +\medskip +\noindent {\bfseries \itshape Example 6: Tcl-Magic under the Debugger} \\ + +When running under Tcl, Magic cannot be debugged in the usual +manner of executing, for instance, ``{\bfseries gdb magic}'', +because the main executable is actually the program ``{\bfseries +wish}''. To run Magic with debugging capability, it is necessary +to do the steps below. In the following, it is assumed that +Magic has been installed in the default location {\ttfamily +CAD\_HOME=/usr/local/}, and that the GNU debugger {\ttfamily gdb} +is the debugger of choice. +\starti + \ih {\itshape \#} {\bfseries gdb wish} \\ + \ih {\itshape (gdb)} {\bfseries run} \\ + \ih {\itshape \%} {\bfseries source /usr/local/lib/magic/tcl/magic.tcl} \\ + \ii . \\ + \ii . \\ + \ii . \\ + \ih {\itshape \%} {\itshape (type Control-C in the terminal window)} \\ + \ih {\itshape (gdb)} {\bfseries break TxTclDispatch} \\ + \ih {\itshape (gdb)} {\bfseries cont} \\ + \ih {\itshape \%} {\bfseries paint m1} \\ + \ih \\ + \ih {\ttfamily Breakpoint 1, TxTclDispath (clientData=0x0, argc=2,}\\ + \ii {\ttfamily argv=0xbffff400)}\\ + \ih {\ttfamily \ \ \ \ \ at txCommands.c:1146} \\ + \ih {\ttfamily 1146 \ \ \ \ \ \ \ \ DRCBreak();} \\ + \ih {\itshape (gdb)} \\ +\endi + +Command-line arguments can be passed to magic through the Tcl +variables {\ttfamily argc} and {\ttfamily argv}. The integer +value {\ttfamily argc} must match the number of entries passed +in the {\ttfamily argv} list. For example, do the following: +\starti + \ii {\itshape \#} {\bfseries gdb wish} \\ + \ii {\itshape (gdb)} {\bfseries run} \\ + \ii {\itshape \%} {\bfseries set argc 4} \\ + \ii {\itshape \%} {\bfseries set argv \{-w -d OGL tut1 \}} \\ + \ii {\itshape \%} {\bfseries source /usr/local/lib/magic/tcl/magic.tcl} \\ +\endi + +\end{document} diff --git a/doc/latexfiles/tuttcl2.tex b/doc/latexfiles/tuttcl2.tex new file mode 100644 index 00000000..19971586 --- /dev/null +++ b/doc/latexfiles/tuttcl2.tex @@ -0,0 +1,64 @@ +%---------------------------------------------------------------------------- +% Magic Tcl tutorial number 2 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ig{\>} +\def\ih{\>\>} +\def\ii{\>\>\>} +\def\mytitle{Magic Tcl Tutorial \#2: The Wrapper GUI} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape R. Timothy Edwards} \\ + \vspace*{0.5in} + Space Department \\ + Johns Hopkins University \\ + Applied Physics Laboratory \\ + Laurel, MD 20723 \\ + \vspace*{0.25in} + This tutorial corresponds to Tcl-based Magic version 7.2 \\ +\end{center} +\vspace*{0.5in} + +\section{The Wrapper GUI} + +\end{document} diff --git a/doc/latexfiles/tuttcl3.tex b/doc/latexfiles/tuttcl3.tex new file mode 100644 index 00000000..2c1fdb01 --- /dev/null +++ b/doc/latexfiles/tuttcl3.tex @@ -0,0 +1,66 @@ +%---------------------------------------------------------------------------- +% Magic Tcl tutorial number 3 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ig{\>} +\def\ih{\>\>} +\def\ii{\>\>\>} +\def\mytitle{Magic Tcl Tutorial \#3: Extracting and Netlisting} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape R. Timothy Edwards} \\ + \vspace*{0.5in} + Space Department \\ + Johns Hopkins University \\ + Applied Physics Laboratory \\ + Laurel, MD 20723 \\ + \vspace*{0.25in} + This tutorial corresponds to Tcl-based Magic version 7.2 \\ +\end{center} +\vspace*{0.5in} + +\section{Tech file extensions for extraction} + +\section{Commands exttospice and exttosim} + +\end{document} diff --git a/doc/latexfiles/tuttcl4.tex b/doc/latexfiles/tuttcl4.tex new file mode 100644 index 00000000..d0a2a4ea --- /dev/null +++ b/doc/latexfiles/tuttcl4.tex @@ -0,0 +1,517 @@ +%---------------------------------------------------------------------------- +% Magic Tcl tutorial number 4 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ig{\>} +\def\ih{\>\>} +\def\ii{\>\>\>} +\def\ij{\>\>\>\>} +\def\tf{\ttfamily} +\def\bstf{\bfseries\ttfamily} +\def\mytitle{Magic Tcl Tutorial \#4: Simulation with IRSIM} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape R. Timothy Edwards} \\ + \vspace*{0.5in} + Space Department \\ + Johns Hopkins University \\ + Applied Physics Laboratory \\ + Laurel, MD 20723 \\ + \vspace*{0.25in} + This tutorial corresponds to Tcl-based Magic version 7.2 \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#1: Getting Started \\ + \> Magic Tutorial \#2: Basic Painting and Selection \\ + \> Magic Tutorial \#4: Cell Hierarchies \\ + \> Magic Tutorial \#8: Circuit Extraction \\ + \> Magic Tutorial \#11: Using IRSIM and RSIM with Magic +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> irsim , getnode, goto \\ + \> graphnode, watchnode, unwatchnode \\ + \> movenode, watchtime, unwatchtime, movetime \\ + \> {\itshape (plus the standard IRSIM command set)} +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (None)} +\endi + +\vspace*{0.25in} +\section{IRSIM Version 9.6} + +In version 9.6, IRSIM has been redesigned to work under the Tcl interpreter, +in the same manner as Magic version 7.2 does. Like Magic version 7.2, +section of Tcl as an interpreter is specified at compile-time, along with +various use options. The ``{\bfseries make}'' method has been rewritten to +match the one which Magic uses, so IRSIM can be compiled and installed in +a similar manner: +\starti + \ii {\bstf make config} \\ + \ii {\bstf make tcl} \\ + \ii {\bstf make install-tcl} +\endi + +Tcl-based IRSIM, like its non-interpreter version, can be run as a +standalone product, and will simulate a circuit from a {\ttfamily .sim} +format file. However, it is specifically designed to be operated in +conjunction with magic, with methods for providing feedback directly +into the layout from the simulation, and vice versa. There are a +number of {\itshape cross-application commands}, detailed below, which +belong to neither Magic or IRSIM, but are applicable when both are +running in the Tcl interpreter at the same time. + +The cross-application commands highlight the usefulness of the method +of compiling each application as a loadable Tcl object module. + +In addition to cross-application commands, Tcl-based IRSIM allows the +use of interpreter variables, conditionals, and control structures to +set up detailed simulation environments. A random number generator +has been added to the Tcl-based version, allowing generation of +random bit vectors for statistically-based coverage of input pattern +spaces. + +\section{Invoking IRSIM from Magic} + +Within the Tcl/Tk environment, IRSIM is easier than ever to invoke. +For tutorial purposes, we will use the same cell used for the original +Tutorial \#11. Unlike the original version, Magic 7.2 requires no +preparation for simulation and can operate directly off of the +tutorial directory input. Start magic with the command-line + +\starti + \ii {\itshape \# }{\bstf magic -w -d OGL tut11a} +\endi + +Note that the OpenGL interface and Wrapper environment specified +above are optional, and do not affect the descriptions in this +tutorial. + +It is not necessary to extract! The scripts which invoke IRSIM +are capable of looking for a netlist file to simulate for the +currently-loaded cell. Because these exist for the tutorial +cells, they will be used. IRSIM is therefore simply invoked by: + +\starti + \ii {\itshape \% }{\bstf irsim} +\endi + +You will see a slew of output that looks like the following: + +\starti + \> \tf Warning: irsim command 'time' use fully-qualified name '::irsim::time' \\ + \> \tf Warning: irsim command 'start' use fully-qualified name '::irsim::start' \\ + \> \tf Warning: irsim command 'help' use fully-qualified name '::irsim::help' \\ + \> \tf Warning: irsim command 'path' use fully-qualified name '::irsim::path' \\ + \> \tf Warning: irsim command 'clear' use fully-qualified name '::irsim::clear' \\ + \> \tf Warning: irsim command 'alias' use fully-qualified name '::irsim::alias' \\ + \> \tf Warning: irsim command 'set' use fully-qualified name '::irsim::set' \\ + \> \tf Warning: irsim command 'exit' use fully-qualified name '::irsim::exit' \\ + \> \tf Starting irsim under Tcl interpreter \\ + \> \tf IRSIM 9.6 compiled on Thu Mar 20 17:19:00 EST 2003 \\ + \> \tf Warning: Aliasing nodes 'GND' and 'Gnd' \\ + \> \tf /usr/local/lib/magic/tutorial/tut11a.sim: Ignoring lumped-resistance \\ + \>\> \tf ('R' construct) \\ \\ + \> \tf Read /usr/local/lib/magic/tutorial/tut11a.sim lambda:1.00u format:MIT \\ + \> \tf 68 nodes; transistors: n-channel=56 p-channel=52 \\ + \> \tf parallel txtors:none \\ + \> {\itshape \% } +\endi + +These comments require some explanation. The warning messages all have to do +with the fact that certain command names are used both by IRSIM and Magic, or +by IRSIM and Tcl or one of its loaded packages (such as Tk). There are +several ways to work around the unfortunate consequences of multiply defining +command names, but the easiest is to make use of the Tcl concept of +{\itshape namespaces}. A complete description of Tcl namespaces is beyond +the scope of this tutorial; however, a simple description suffices. By +prefixing a ``scope'' to the command, the command can only be executed when +the complete name (scope plus the double colon `::' plus the command name) +is entered. + +In general, the EDA tools make an attempt to allow commands to be entered +without the scope prefix at the command line. As long as command names +are unique, this is done without comment. However, when commands overlap, +the easiest solution is to require the scope prefix. Therefore, the command +`{\bfseries set}' would refer to the Tcl {\bfseries set} command (i.e., to set +a variable), while `{\bfseries irsim::set}' would refer to the IRSIM command. +Some attempt is made to overload commands which conflict but which have +unique syntax, so that it is possible to determine which use is intended +when the command is dispatched by the interpreter. + +In addition to the warnings, there are a few standard warnings about +global name aliases and lumped resistance, and some information about the +{\ttfamily .sim} file which was read. + +\section{IRSIM Command Set} + +In addition to the exceptions noted above for fully-qualified namespace +commands, there are several IRSIM commands which are not compatible with +Tcl syntax, and these have been renamed. The old and new commands are +as follows (see the IRSIM documentation for the full set of commands): + +\begin{center} +\begin{tabular}{|lll|} \hline + > & savestate & save network state \\ + < & restorestate & restore network state \\ + << & restoreall & restore network and input state \\ + ? & querysource & get info regarding source/drain connections \\ + ! & querygate & get info regarding gate connections \\ + \@ & source \itshape{(Tcl command)} & source a command file \\ \hline +\end{tabular} +\end{center} + +Note that the `{\bfseries \@}' command is simply superceded by the Tcl +`{\bfseries source}' command, which is more general in that it allows +a mixture of Tcl and IRSIM commands (and commands for any other loaded +package, such as Magic) to be combined in the command file. + +Once loaded into Tcl alongside Magic via the {\bfseries irsim} command, +the IRSIM commands are typed directly into the Magic command line, and +will execute the appropriate IRSIM function. By repeating the contents +of Tutorial \#11 in the Tcl environment, this method should become +clear, as will the benefits of using the interpreter environment for +simulation. + +To setup the simulation, the equivalent instruction to that of Tutorial +\#11 is the following: + +\starti + \ii {\itshape \% } + {\bstf source \$}\{{\bstf CAD\_HOME}\}{\bstf /lib/magic/tutorial/tut11a.cmd} +\endi + +Note that because the {\bfseries source} command is a Tcl command, not +a Magic or IRSIM command, it it necessary to specify the complete +path to the file, as Tcl does not understand the search path for Magic +cells, which includes the tutorial directory. + +As most common commands are not among the set that cause conflicts with +Magic and Tcl commands, the tutorial command file loads and executes +without comment. + +Following the example of Tutorial~\#11, type {\bfseries c} (IRSIM +clock command) on the magic command line to clock the circuit. +Values for the watched nodes, which were declared in the tutorial +command file, are displayed in the console window. Likewise, +\starti + \ii {\bstf h RESET\_B hold} +\endi +will set the nodes {\bstf RESET\_B} and {\bstf hold} to value 1. + +\section{Feedback to Magic} + +The cross-application commands reveal the usefulness of having both +applications as extensions of the same Tcl interpreter. + +While Magic and IRSIM are active and file {\ttfamily tut11a} is loaded, +execute the following commands from the command line: +\starti + \ii {\bstf stepsize 100} \\ + \ii {\bstf watchnode RESET\_B} \\ + \ii {\bstf watchnode hold} +\endi +Note that the nodes and values are immediately printed in the magic +window, making use of the magic ``{\bfseries element}'' command. +These values are persisent in the sense that they will remain +through various transformations, openings, and closings of the +layout window, but they are temporary in the sense that they will +not be saved along with the layout if the file is written (however, +this behavior can be modified). + +The {\bfseries watchnode} command requires no special action for +placing the label elements in the layout because magic uses the +labels or other node information to pinpoint a position in the +layout belonging to that node, and places the label element there. +It is possible to use {\bfseries watchnode} with vectors. However, +as no location can be pinpointed for a vector, the magic cursor box +position will be used to place the label element. + +Move the magic cursor box to a empty space in the layout window, +and type +\starti + \ii {\bstf watchnode bits} +\endi + +Now move the cursor box to another empty space and type +\starti + \ii {\bstf watchtime} +\endi +Now all of the simulation values of interest are displayed directly +on the Magic layout. + +The display of any node can be removed with the command +{\bstf unwatchnode}, with the same syntax as +{\bstf watchnode}, and similarly, the display of +simulation time can be removed with the command +{\bstf unwatchtime}. + +If the position of a label is not in a good position to read, or +the relative position of two labels places them on top of one +another, making them difficult to read, the labels can be moved +using the {\bfseries movenode} command. For instance, the node +{\ttfamily RESET\_B} is not exactly on the polysilicon pad. To +center it exactly on the pad, select the square pad, so that the +box cursor is on it, then do +\starti + \ii {\bstf movenode RESET\_B} +\endi +The label will be moved so that it is centered on the center of +the cursor box. The equivalent method can be applied to the +time value using the {\bstf movetime} command. + +It is not necessary to know the name of a node in order to query +or display its simulation value. For instance, unexpand the +layout of {\ttfamily tut11a.mag}, select an unlabeled node, +and use a mixture of IRSIM and magic commands to watch its +value: +\starti + \ii {\bstf box 93 -104 94 -102} \\ + \ii {\bstf select area} \\ + \ii {\bstf watchnode [getnode]} \\ +\endi +In this example, both the node +({\ttfamily bit\_1/tut11d\_0/a\_39\_n23\#}) and its value are +displayed. Likewise, the {\bfseries getnode} command can be +combined with other IRSIM commands to setup clocks and vectors +from unlabeled nodes. This can be particularly useful in +situations where it may not be obvious which nodes in a design +need to be examined prior to running the simulation. + +\section{Analyzer Display} + +Tcl-based IRSIM has a graphical node display which is derived from +functions available in the ``{\bfseries BLT}'' graphics package. +These functions are not particularly well-suited for display of +logic values, and so this will probably be replaced in the future +with a more appropriate interface. However, it accomplishes most +of the functions of the former X11-based analyzer display. + +In the Tcl-based IRSIM, no special command is needed to initialize +the analyzer display. One command sets up signals to be displayed +in the analyzer window. This is: +\starti + \ii {\bstf graphnode} {\itshape name} + [{\itshape row}] [{\itshape offset}] +\endi +For display of multiple signals in the window, the optional arguments +{\itshape row} and {\itshape offset} are provided. Each signal which +declares a new {\itshape row} (default zero) will appear in a separate +graph in the display. Signals which appear in the same graph, however, +may declare a non-zero {\itshape offset} which will set them at a +different vertical placement on the graph, for cases in which this +provides better viewing than having the signals directly overlapping. + +The analyzer display updates at the end of each simulation cycle. +Logic values are displayed as 0 or 1, with undefined (value 'X') values +displayed as 1/2. Note that the BLT-based interface prohibits the +display of multi-bit values, and only nodes, not vectors, can be passed +to the {\bstf graphnode} command. + +\section{Wildcards} + +The original IRSIM used ``wildcard'' characters in the form of standard +UNIX ``regular expressions'' to perform operations on multiple nodes +with one command. Unfortunately, there was a syntactical collision +between IRSIM and Magic over the use of brackets (`{\bstf [}' +and `{\bstf ]}'). Brackets represent groupings in regular expression +syntax. However, Magic uses brackets to represent arrays of subcells. +Because Tcl itself implements regular expressions in the form of the +Tcl ``{\bstf regexp}'' command, there is a way around this problem in +the Tcl version of IRSIM. IRSIM's parsing of regular expressions has +been disabled. In place of it, Tcl lists may be passed as arguments +to any command which previously would accept wildcard characters. In +addition, Tcl-IRSIM defines a command +\starti + \ii {\bstf listnodes} +\endi +which returns a Tcl list of all the nodes defined in the netlist +input file. This list can be searched by Tcl regular expression +commands, and the resulting sub-lists passed as node arguments to +IRSIM commands. For example, the following script sets all nodes +in the circuit (except for {\ttfamily Vdd}, which is fixed) to +zero, then releases them: +\starti + \ii {\bstf set nl [listnodes]} \\ + \ii {\bstf l \$nl} \\ + \ii {\bstf s} \\ + \ii {\bstf x \$nl} +\endi + +Brackets in individual node names are treated as-is by IRSIM, as are +other Magic-generated characters such as the slash, underscore, and +hash mark. Note, however, that because Tcl itself defines brackets +as representing command groupings which return an immediate result, +the following is illegal: +\starti + \ii {\itshape \%} {\bstf l multcell5\_0[1,0]/a\_13\_n21\#} \\ + \ii {\ttfamily invalid command name "1,0"} +\endi +Instead, node names containing brackets should be surrounded by +braces (`\{' and `\}'), which effectively turns +a node name into a list of node names which happens to contain +exactly one entry: +\starti + \ii {\itshape \%} {\bstf l }\{{\bstf multcell5\_0[1,0]/a\_13\_n21\#}\} \\ +\endi +The Tcl versions of Magic and IRSIM are set up in such a way that +when they return results containing node names, these names are +automatically treated as lists. Therefore, the command +\starti + \ii {\itshape \%} {\bstf select area [goto }\{{\bstf multcell5\_0[1,0]/a\_13\_n21\#}\} + {\bstf ]} \\ + \ii {\itshape \%} {\bstf l [getnode]} +\endi +does not produce any error when the arrayed node name is passed to the +IRSIM ``{\bstf l}'' command, and sets the value of the node to zero as +expected. It is only when node names are entered in a script or from +the command line that precautions must be taken to list-enclose names +which contain brackets. + +\section{Scripting IRSIM Command Sequences} + +A consequence of placing IRSIM in an interpreter environment is +the ability to use interpreter features such as variables, +conditionals, and loops to set up complicated simulation +environments. + +\section{Deterministic Bit Vector Generation} + +A convenience function has been added to Tcl-IRSIM to aid in +generating deterministic sequences of inputs. This is the +command +\starti + \ii {\bstf bconvert} {\itshape value} {\itshape bits} [{\itshape dir}] +\endi +where {\itshape value} is an integer decimal value, {\itshape bits} +is the length of the bit vector to hold the conversion, and {\itshape +dir} is an optional direction flag. If {\itshape dir} is 1, then the +bit vector is defined with the most significant bit (MSB) on the right. +The {\bstf bconvert} command returns the string value of the bit +vector containing {\ttfamily 0} and {\ttfamily 1} characters. For +example: + +\starti + \ii {\itshape \%} {\bstf bconvert 20 5} \\ + \ii {\ttfamily 10100} \\ + \ii {\itshape \%} {\bstf bconvert 20 5 1} \\ + \ii {\ttfamily 00101} +\endi + +\section{Random Bit Vector Generation} + +The tutorial examples are small by design, but real systems (such as +a microprocessor) are often so complex that generating and simulating +an exhaustive set of all possible states of the circuit is impossible, +and instead simulations rely on the generation of a set of +randomly-generated inputs to test a representative set of states. + +Random number generation is not a built-in feature of the Tcl language, +but several open-source packages exist, one of which has been +incorporated into the IRSIM 9.6 source. The pseudorandom number +generator is compiled as a separate Tcl package, but is loaded by +the IRSIM startup script. It contains one command, {\bstf random}, +with the following arguments: +\starti + \ii {\bstf random} {\itshape option} +\endi +where {\itshape option} may be one of: +\begin{itemize} + \item [] {\bstf -reset} will cause the generator to be reseeded using + current pid and current time. + + \item [] {\bstf -seed} {\itshape n} will reseed the generator with the + integer value {\itshape n}. + + \item [] {\bstf -integer} {\itshape ...} will cause the number returned + to be rounded down to the largest integer less than or equal to the + number which would otherwise be returned. + + \item [] {\bstf -normal} {\itshape m s} will cause the number returned + to be taken from a gaussian with mean {\itshape m} and standard + deviation {\itshape s}. + + \item [] {\bstf -exponential} {\itshape m} will cause the number + returned to be taken from an exponential distribution with mean + {\itshape m}. + + \item [] {\bstf -uniform} {\itshape low high} will cause the number + returned to be taken from uniform distribution on {\itshape [a,b)}. + + \item [] {\bstf -chi2} {\itshape n} will cause the number returned to be + taken from the chi2 distribution with {\itshape n} degrees of freedom. + + \item [] {\bstf -select} {\itshape n list} will cause {\itshape n} elements + to be selected at random from the list {\itshape list} with replacement. + + \item [] {\bstf -choose} {\itshape n list} will cause {\itshape n} elements + to be selected at random from the list {\itshape list} without replacement. + + \item [] {\bstf -permutation} {\itshape n} will return a permutation + of $0\dots n-1$ if {\itshape n} is a number and will return a permutation + of its elements if {\itshape n} is a list. +\end{itemize} + +The following script clocks a random serial bit vector into a state machine, +assuming that {\bstf bit\_in} is the node to set, and that the proper clock +vectors have already been set up: +\starti + \ih for \{set i 0\} \{\$i < 100\} \{incr i\} \{ \\ + \ii if \{[random] < 0.5\} \{ \\ + \ij l bit\_in \\ + \ii \} else \{ \\ + \ij h bit\_in \\ + \ii \} \\ + \ii c \\ + \ih \} +\endi + +\end{document} diff --git a/doc/latexfiles/tuttcl5.tex b/doc/latexfiles/tuttcl5.tex new file mode 100644 index 00000000..e2d2d3c9 --- /dev/null +++ b/doc/latexfiles/tuttcl5.tex @@ -0,0 +1,64 @@ +%---------------------------------------------------------------------------- +% Magic Tcl tutorial number 5 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ig{\>} +\def\ih{\>\>} +\def\ii{\>\>\>} +\def\mytitle{Magic Tcl Tutorial \#5: Writing Tcl Scripts for Magic} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape R. Timothy Edwards} \\ + \vspace*{0.5in} + Space Department \\ + Johns Hopkins University \\ + Applied Physics Laboratory \\ + Laurel, MD 20723 \\ + \vspace*{0.25in} + This tutorial corresponds to Tcl-based Magic version 7.2 \\ +\end{center} +\vspace*{0.5in} + +\section{Scripting in Magic} + +\end{document} diff --git a/doc/latexfiles/tutwrl1.tex b/doc/latexfiles/tutwrl1.tex new file mode 100644 index 00000000..1fbaec40 --- /dev/null +++ b/doc/latexfiles/tutwrl1.tex @@ -0,0 +1,247 @@ +%---------------------------------------------------------------------------- +% Magic tutorial number W-1 +%---------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e}[1994/12/01] +\documentclass[letterpaper,twoside,12pt]{article} +\usepackage{epsfig,times} + +\setlength{\textwidth}{8.5in} +\addtolength{\textwidth}{-2.0in} +\setlength{\textheight}{11.0in} +\addtolength{\textheight}{-2.0in} +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0pt} +\setlength{\topmargin}{-0.5in} +\setlength{\headheight}{0.2in} +\setlength{\headsep}{0.3in} +\setlength{\topskip}{0pt} + +\def\hinch{\hspace*{0.5in}} +\def\starti{\begin{center}\begin{tabbing}\hinch\=\hinch\=\hinch\=hinch\hinch\=\kill} +\def\endi{\end{tabbing}\end{center}} +\def\ii{\>\>\>} +\def\mytitle{Magic Tutorial \#W-1: Design-Rule Extensions} +\def\q{\special{ps:(") show}\hspace*{0.6em}} +\def\bk{\special{ps:/bksp 2 string def bksp 0 92 put bksp show}\hspace*{0.4em}} + +%---------------------------------------------------------------------------- + +\begin{document} + +\makeatletter +\newcommand{\ps@magic}{% + \renewcommand{\@oddhead}{\mytitle\hfil\today}% + \renewcommand{\@evenhead}{\today\hfil\mytitle}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\newcommand{\ps@mplain}{% + \renewcommand{\@oddhead}{}% + \renewcommand{\@evenhead}{}% + \renewcommand{\@evenfoot}{\hfil\textrm{--{\thepage}--}\hfil}% + \renewcommand{\@oddfoot}{\@evenfoot}} +\makeatother +\pagestyle{magic} +\thispagestyle{mplain} + + +\begin{center} + {\bfseries \Large \mytitle} \\ + \vspace*{0.5in} + {\itshape Don Stark} \\ + \vspace*{0.5in} + Western Research Laboratory \\ + Digital Equipment Corporation \\ + Palo Alto, CA 94301 \\ + \vspace*{0.25in} + This tutorial corresponds to Magic version 7. \\ +\end{center} +\vspace*{0.5in} + +{\noindent\bfseries\large Tutorials to read first:} +\starti + \> Magic Tutorial \#6: Design-Rule Checking \\ + \> Magic Tutorial \#9: Format Conversion for CIF and Calma \\ + \> Magic Maintainer's Manual \#2: The Technology File +\endi + +{\noindent\bfseries\large Commands introduced in this tutorial:} +\starti + \> {\itshape (None)} +\endi + +{\noindent\bfseries\large Macros introduced in this tutorial:} + +\starti + \> {\itshape (None)} +\endi + +\vspace*{0.25in} +\section{Introduction} + +Magic's original design rule checker has proved inadequate to implement all +the rules found in advanced technologies. The rules described +in this section allow more complicated configurations to be analyzed. +Two new rules check a region's area and its maximum width. In addition, +width, spacing, area, and maxwidth checks may now be performed on cif layers. + +\section{Area Rules} + +The {\bfseries area} rule is used to check the minimum area of a region. Its +syntax is: + +\starti + \ii {\bfseries area} {\itshape types minarea minedge why} +\endi + +{\itshape Types} is a list of types that compose the region, all of which must +be on the same plane. +{\itshape Minarea} is the minimum area that a region must have, while {\itshape minedge} +is the minimum length of an edge for the region. This second dimension +is basically +an optimization to make the design rule checker run faster; without it, +the checker has to assume that a region 1 lambda wide and {\itshape minarea} +long is legal, and it must examine a much larger area when checking the +interaction between cells. Specifying {\itshape minedge} reduces this +interaction distance. An example rule is: + +\starti + \ii {\bfseries area (emitter,em1c)/npoly 6 2 {\q}emitter must be at least 2x3{\q}} +\endi + + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tutw1.2.ps, width = 0.65\columnwidth} + \caption{Example of the area rule.} + \end{center} +\end{figure} + + +\section{Maxwidth Rules} + +Sometimes a technology requires that a region not be wider than a +certain value. The {\bfseries maxwidth} rule can be used to check this. + +\starti + \ii {\bfseries maxwidth} {\itshape layers mwidth bends why} +\endi + +{\itshape Layers}, the types that compose the region, must all be in the +same plane. The region must be less than {\itshape mwidth} wide in either the +horizontal or vertical dimension. {\itshape Bends} takes one of two values, +{\bfseries bend{\_}illegal} and {\bfseries bend{\_}ok}. For +{\bfseries bend{\_}illegal} rules, the +checker forms a bounding box around all contiguous tiles of the correct type, +then checks this box's width. For example: + +\starti + \ii {\bfseries maxwidth (emitter,em1c)/npoly 2 bend{\_}illegal\ {\bk}} \\ + \ii \> {\bfseries {\q}emitter width cannot be over 2{\q}} +\endi + +{\bfseries bend{\_}ok} rules are used to check structures where the region +must be locally less than maxwidth, but may contain bends, +T's, and X's. + +\starti + \ii {\bfseries maxwidth trench 2 bend{\_}ok {\q}trench must be exactly 2 wide{\q}} +\endi + +{\bfseries Warning:} the bend{\_}ok rule is basically a kludge, and may fail for +regions composed of more than one type, or for intersections more +complicated than T's or X's. +Figure~\ref{maxwidth} shows some examples of both types of rules. + +\begin{figure}[ht] + \begin{center} + \epsfig{file=../psfigures/tutw1.1.ps, width=\columnwidth} + \label{maxwidth} + \caption{Examples of the maxwidth rule. The dogleg at the left would + be ok in a {\bfseries bend{\_}ok} rule, but fails in a + {\bfseries bend{\_}illegal} one, where the region's bounding + box is checked. For {\bfseries bend{\_}ok} rules, each tile + in the region is checked. The left shape fails in two places: + the top horizontal part is too thick and the stub at the bottom + intersects the region in a shape other than a T or X.} + \end{center} +\end{figure} + +\section{Rules on CIF layers} + +For technologies with complicated generated layers, it is often difficult +to check design rules on the abstract types that are drawn in Magic. To +ameliorate this problem, the extended checker allows simple checks to be +performed on cif layers. The rules that can be checked are width, +spacing, area, and maxarea. Since checking rules on the cif layers +requires that these layers be generated, these checks are considerably +slower than the normal ones, and should only be used when absolutely +necessary. + +\subsection{Setting the CIF style} + +The {\bfseries cifstyle} rule is used to select which {\bfseries cifoutput} +style is used. + +\starti + \ii {\bfseries cifstyle} {\itshape cif{\_}style} +\endi + +{\itshape Cif{\_}style} must be one of the cif styles included in the cifoutput +section. In the current implementation, the cif checker generates all the +layers in the style regardless of whether they are actually used in +design-rule checks; for speed, defining a separate cif style for design +rule checking it may be worthwhile when only a few layers are checked. +Any layer in the cif style, defined by either a {\itshape layer} or a +{\itshape templayer} rule, may be checked. + +\subsection{Width Checks} + +The syntax for {\bfseries cifwidth} is analogous to that of the regular width +rule: + +\starti + \ii {\bfseries cifwidth} {\itshape layer width why} +\endi + +{\itshape Layer} is a single cif layer. (To do width checks with more than one cif +layer, {\bfseries or} all the layers into a new {\itshape templayer}). {\itshape Width} +is the minimum width of the region in centimicrons. + +\subsection{Spacing Checks} + +The {\bfseries cifspacing} rule is also very similar to the regular rule: + +\starti + \ii {\bfseries cifspacing} {\itshape layer1 layer2 separation adjacency why} +\endi + +{\itshape Layer1} and {\itshape layer2} are both cif layers. If +{\itshape adjacency} is {\bfseries touching{\_}ok}, then layer1 must +equal layer2. For {\bfseries touching{\_}illegal} rules, {\itshape layer1} +and {\itshape layer2} may be any two cif layers. {\itshape Separation} is +given in centimicrons. + +\subsection{Area Checks} + +The area rule is: + +\starti + \ii {\bfseries cifarea} {\itshape layer minarea minedge why} +\endi + +{\itshape Layer} is again a single cif layer. {\itshape minedge} is expressed in +centimicrons, and {\itshape minarea} is given in square centimicrons. + +\subsection{Maxwidth Checks} + +The maxwidth rule is: + +\starti + \ii {\bfseries cifmaxwidth} {\itshape layer mwidth bends why} +\endi + +Again, {\itshape layer} is a single cif layer, and {\itshape mwidth} is given in +centimicrons. + +\end{document} diff --git a/doc/man/Makefile b/doc/man/Makefile new file mode 100644 index 00000000..ebf937ba --- /dev/null +++ b/doc/man/Makefile @@ -0,0 +1,50 @@ +# +# makefile for Magic documentation +# + +MAGICDIR = ../.. + +MANMACS= tmac.anc +TROFF=ditroff -h +TTROFF=ditroff -Ppsc -t +PSDIT=psdit +GRN=grn -Ppsc +TBL=tbl -Ppsc +EQN=eqn -Ppsc + +include ${MAGICDIR}/defs.mak + +MANFILES = \ + $(DESTDIR)${MANDIR}/man1/ext2spice.1 \ + $(DESTDIR)${MANDIR}/man1/extcheck.1 \ + $(DESTDIR)${MANDIR}/man1/ext2sim.1 \ + $(DESTDIR)${MANDIR}/man1/magic.1 \ + $(DESTDIR)${MANDIR}/man5/cmap.5 \ + $(DESTDIR)${MANDIR}/man5/displays.5 \ + $(DESTDIR)${MANDIR}/man5/dlys.5 \ + $(DESTDIR)${MANDIR}/man5/dstyle.5 \ + $(DESTDIR)${MANDIR}/man5/ext.5 \ + $(DESTDIR)${MANDIR}/man5/glyphs.5 \ + $(DESTDIR)${MANDIR}/man5/mag.5 \ + $(DESTDIR)${MANDIR}/man5/net.5 \ + $(DESTDIR)${MANDIR}/man5/sim.5 + +install: ${MANFILES} + +$(DESTDIR)${MANDIR}: + ${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR} + +$(DESTDIR)${MANDIR}/man1: $(DESTDIR)${MANDIR} + ${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR}/man1 + +$(DESTDIR)${MANDIR}/man1/%: % $(DESTDIR)${MANDIR}/man1 + ${CP} $* $(DESTDIR)${MANDIR}/man1/$* + +$(DESTDIR)${MANDIR}/man5: $(DESTDIR)${MANDIR} + ${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR}/man5 + +$(DESTDIR)${MANDIR}/man5/%: % $(DESTDIR)${MANDIR}/man5 + ${CP} $* $(DESTDIR)${MANDIR}/man5/$* + +mans: + ${SCRIPTS}/printmans "${TROFF} ${MANMACS} -" *.1 *.5 diff --git a/doc/man/cmap.5 b/doc/man/cmap.5 new file mode 100644 index 00000000..c1257356 --- /dev/null +++ b/doc/man/cmap.5 @@ -0,0 +1,60 @@ +.\" sccsid @(#)cmap.5 4.2 (Berkeley) 10/17/85 +.\" +.\" CONVENTIONS: +.\" italics: things that are substituted for +.\" boldface: characters that are typed as-is +.\" +.\" EXAMPLE: \fIfilename\fB.mag\fR +.\" or: \fBcif \fR[\fIfile\fR] +.\" +.TH CMAP 5 +.UC 4 +.SH NAME +cmap \- format of .cmap files (color maps) + +.SH DESCRIPTION +.PP +Color-map files define the mapping between eight-bit color numbers +and red, green and blue intensities used for those numbers. +They are read by Magic as part of system startup, and also +by the \fB:load\fR and \fB:save\fR commands in color-map windows. +Color-map file names usually have the form \fIx\fB.\fIy\fB.\fIz\fB.cmap\fIn\fR, +where \fIx\fR is a class of technology files, \fIy\fR is a class of displays, +\fIz\fR is a class of monitors, and \fIn\fR is a version +number (currently \fB1\fR). +The version number will change in the future +if the format of color-map files ever changes. +Normally, \fIx\fR and \fIy\fR correspond to the corresponding parts of a +display styles file. +For example, the color map file \fBmos.7bit.std.cmap1\fR is used today for most +nMOS and CMOS technology files using displays that support at least seven +bits of color per pixel and standard-phosphor monitors. +It corresponds to the display styles file \fBmos.7bit.dstyle5\fR. +.PP +Color-map files are stored in ASCII form, with each line containing +four decimal integers separated by white space. +The first three integers are red, green, and blue intensities, and the +fourth field is a color number. +For current displays the intensities must be integers between 0 and 255. +The color numbers must increase from line to line, and the last line must have +a color number of 255. +The red, green, and blue intensities on the first line are used for +all colors from 0 up to and including the color number on that line. +For other lines, the intensities on that line are used for all colors +starting one color above the color number on the previous line and +continuing up and through the color number on the current line. +For example, consider the color map below: +.nf +.ta 2c 4c 6c 8c + +255 0 0 2 +0 0 255 3 +255 255 255 256 + +.fi +.LP +This color map indicates that colors 0, 1, and 2 are to be red, +color 3 is to be blue, and all other colors are to be white. + +.SH "SEE ALSO" +magic\|(1), dstyle\|(5) diff --git a/doc/man/displays.5 b/doc/man/displays.5 new file mode 100644 index 00000000..aefb532a --- /dev/null +++ b/doc/man/displays.5 @@ -0,0 +1,70 @@ +.\" sccsid @(#)displays.5 4.1 MAGIC (Berkeley) 11/29/85 +.\" +.\" CONVENTIONS: +.\" italics: things that are substituted for +.\" boldface: characters that are typed as-is +.\" +.\" EXAMPLE: \fIfilename\fB.mag\fR +.\" or: \fBcif \fR[\fIfile\fR] +.\" +.TH DISPLAYS 5 2/19/85 +.UC +.SH NAME +displays \- Display Configuration File +.SH DESCRIPTION +The interactive graphics programs Caesar, Magic, +and Gremlin use two separate terminals: +a text terminal from which commands are +issued, and a color graphics terminal on which graphical output is displayed. +These programs use a +.B displays +file to associate their text terminal with its corresponding display device. +.PP +The +.B displays +file is an ASCII text file with one line for each +text terminal/graphics terminal pair. +Each line contains 4 items separated by spaces: +the name of the port attached to a text terminal, +the name of the port attached to the associated graphics terminal, +the phosphor type of the graphics terminal's monitor, +and the type of graphics terminal. +.PP +An applications program may use the phosphor type +to select a color map tuned to the monitor's characteristics. +Only the \fBstd\fR phosphor type is supported at UC Berkeley. +.PP +The graphics terminal type specifies the device driver +a program should use when communicating with its graphics terminal. +Magic supports types \fBUCB512\fR, \fBAED1024\fR, and \fBSUN120\fR. +Other programs may recognize different display types. +See the manual entry for your specific application for more information. +.PP +A sample displays file is: +.sp +.in +0.5i +.B +.br +/dev/ttyi1 /dev/ttyi0 std UCB512 +.br +/dev/ttyj0 /dev/ttyj1 std UCB512 +.br +/dev/ttyjf /dev/ttyhf std UCB512 +.br +/dev/ttyhb /dev/ttyhc std UCB512 +.br +/dev/ttyhc /dev/ttyhb std UCB512 +.R +.in -0.5i +.br +.PP +In this example, \fB/dev/ttyi1\fR connects to a text terminal. +An associated \fBUCB512\fR graphics terminal with +standard phosphor is connected to \fB/dev/ttyi0\fR. + +.SH "FILES" +Magic uses the displays file ~cad/lib/displays. +Gremlin looks in /usr/local/displays. + +.SH "SEE ALSO" +magic(1) diff --git a/doc/man/dlys.5 b/doc/man/dlys.5 new file mode 100644 index 00000000..68967988 --- /dev/null +++ b/doc/man/dlys.5 @@ -0,0 +1,88 @@ +.TH DLYS 5 +.SH NAME +dlys \- format of .dlys files read by the SCALD simulator and timing verifier + +.SH DESCRIPTION +The SCALD simulator and timing verifier can accept information about +the actual delays of wires in a circuit. +This delay information is described in a \fB.dlys\fR file, which consists of a +sequence of records, one for each electrical net. +Each record begins with the signal name for the net (note that this is the +SCALD signal name, i.e., the name given by the user to the entire net, +and not usually the name of one of the pins in the net), +followed by an \fB=\fR, then a +comma-separated list of the terminals in the net and their associated +delay, with the list terminated by a semicolon. +The end of the file is marked with a second semicolon. +.PP +The elements of the comma-separated list for each net take the form +.sp +.ti +8 +\fIlocation\fB [\fImin\fB:\fImax\fB]\fR +.sp +where \fIlocation\fR is the full hierarchical SCALD name of the physical +pin to which the delay is computed, and \fImin\fR and \fImax\fR are the +best-case and worst-case wire delay in nanoseconds (both are floating-point +numbers). +The assumption is that only a single driver exists per net, so all delays +are computed from this driver. +If a net has multiple drivers, then the +interpretation of delays is up to the program reading this file (e.g, +\fImin\fR delays are taken from the fastest driver, \fImax\fR from the +slowest). +.PP +Here is an example \fB.dlys\fR file: +.sp +.na +.nf +.ta +0.3i +2.0i +\fC +(APS )ALU STATUS BITS I1<0> = + (APS MR 3V6 R1 1P )IN#63 [ 0.3 : 0.4 ], + (APS APS 4RI RFC RF )OUT [ 0.5 : 0.7 ]; +(APS )ALU STATUS BITS I1<1> = + (APS APS 4ALUD DCD )AN#12 [ 1.4 : 1.6 ], + (APS APS 4ALUD DCD )AN#8 [ 1.1 : 1.3 ], + (APS APS 4ALUD DCD )AN#9 [ 1.1 : 1.3 ], + (APS APS 4ALUD DCD )AN#10 [ 1.1 : 1.3 ], + (APS APS 4ALUD DCD )AN#11 [ 1.1 : 1.3 ], + (APS MR 3V2 R1 1P )#23 [ 0.6 : 0.8 ], + (APS MR 3V6 R1 1P )#62 [ 0.3 : 0.4 ], + (APS APS 4ALUD DCD ) [ 0.4 : 0.6 ], + (APS APS 4ALUD DCD )#1 [ 0.4 : 0.6 ], + (APS APS 4ALUD DCD )#2 [ 0.4 : 0.6 ], + (APS APS 4ALUD DCD )#3 [ 0.4 : 0.6 ], + (APS APS 4ALUD DCD )#4 [ 0.7 : 0.8 ], + (APS APS 4ALUD DCD )#5 [ 0.7 : 0.8 ]; +; +\fR +.fi +.ad +.PP +Although it is not good practice, it is possible to omit the actual +pin names from the \fIlocation\fR names and only give the path to the +part; the example above shows several cases where the final pin name +is missing. +Since the timing verifier and simulator have the original +SCALD netlist available, they are usually able to use the signal name +to determine the net, and then use the part's path to identify which +pin of the net is meant. +This is accurate when a net connects to +at most one pin per part; if it connects to more than one pin per +part then there is ambiguity over which pin is meant. +Usually, though, this ambiguity results in only a small inaccuracy, since +the delay to different pins on the same part is usually similar. +Also, if delay is capacitive, the delay to all pins in a net will +be the same anyway, so there is no inaccuracy. + +.SH "SEE ALSO" +ext2dlys\|(1), ext\|(5), sim\|(5) + +.SH BUGS +There should be some way to specify which pins are drivers and which +are receivers in a net. +.PP +The ability to omit pin names is dangerous; although it usually works +it can introduce large inaccuracies when the parts are large compared +to the sizes of the wires used to connect them, as might be the case +on a silicon PCB. diff --git a/doc/man/dstyle.5 b/doc/man/dstyle.5 new file mode 100644 index 00000000..71fb32b9 --- /dev/null +++ b/doc/man/dstyle.5 @@ -0,0 +1,176 @@ +.\" sccsid @(#)dstyle.5 4.6 (Berkeley) 10/20/85 +.\" +.\" CONVENTIONS: +.\" italics: things that are substituted for +.\" boldface: characters that are typed as-is +.\" +.\" EXAMPLE: \fIfilename\fB.mag\fR +.\" or: \fBcif \fR[\fIfile\fR] +.\" +.TH DSTYLE 5 +.UC 4 +.SH NAME +dstyle \- format of .dstyle files (display styles) + +.SH DESCRIPTION +.PP +Display styles indicate how to render information on a screen. +Each style describes one way of rendering information, for example +as a solid area in red or as a dotted outline in purple. +Different +styles correspond to mask layers, highlights, labels, menus, window +borders, and so on. +See ``Magic Maintainer's Manual #3: Display Styles, +Color Maps, and Glyphs'' for more information on how the styles are +used. +.PP +Dstyle files usually have names of the form \fIx\fB.\fIy\fB.dstyle\fIn\fR, +where \fIx\fR is a class of technologies, \fIy\fR is a class of +displays, and \fIn\fR is a version number (currently \fB5\fR). +The version number may increase in the future if the format +of dstyle files changes. +For example, the display style file \fBmos.7bit.dstyle5\fR provides +all the rendering information for our nMOS and CMOS technologies +for color displays with at least 7 bits of color. +.PP +Dstyle files are stored in ASCII as a series of lines. +Lines beginning with ``#'' are considered to be comments and are ignored. +The rest of the lines of the file are divided up into two sections +separated by blank lines. +There should not be any blank lines within a section. +.SH "DISPLAY_STYLES SECTION" +The first section begins with a line +.DS L +\fBdisplay_styles\fR \fIplanes\fR +.DE +where \fIplanes\fR is the number of bits of color information per +pixel on the screen (between 1 and 8). +Each line after that describes one display style +and contains eight fields separated by white space: +.DS L +\fIstyle writeMask color outline fill stipple shortName longName\fR +.DE +The meanings of the fields are: +.TP +\fIstyle\fR +The number of this style, in decimal. +Styles 1 through 64 are used to display mask layers in the edit cell. +The style number(s) to use for +each mask layer is (are) specified in the technology file. +Styles 65-128 are used for displaying mask layers in non-edit cells. +If style \fIx\fR is used for a mask layer in the edit cell, style +\fIx\fR+64 is used for the same mask layer in non-edit cells. +Styles above 128 are used by the Magic code for various things like menus +and highlights. +See the file \fIstyles.h\fR in Magic for how styles above 128 are used. +When redisplaying, the styles are drawn in order starting at 1, so the order +of styles may affect what appears on the screen. +.TP +\fIwriteMask\fR +This is an octal number specifying which bit-planes are to be +modified when this style is rendered. +For example, 1 means only information in bit-plane 0 will be affected, and 377 +means all eight bit-planes are affected. +.TP +\fIcolor\fR +An octal number specifying the new values to be written into +the bit-planes that are modified. +This is used along with \fIwriteMask\fR to determine the new value of each +pixel that's being modified: +.DS C +newPixel = (oldPixel & \(apwriteMask) | (color & writeMask) +.DE +The red, green, and blue intensities displayed for each pixel +are not deterimined directly by the value of the pixel; they +come from a color map that maps the eight-bit pixel values +into red, green, and blue intensities. +Color maps are stored in separate files. +.TP +\fIoutline\fR +If this field is zero, then no outline is drawn. +If the field is non-zero, it specifies that outlines are to be drawn around +the rectangular areas rendered in this style, and the octal +value gives an eight-bit pattern telling how to draw the outline. +For example, 377 means to draw a solid line, 252 means to draw +a dotted line, 360 specifies long dashes, etc. +This field only +indicates \fIwhich\fR pixels will be modified: the \fIwriteMask\fR +and \fIcolor\fR fields indicate how the pixels are modified. +.TP +\fIfill\fR +This is a text string specifying how the areas drawn in this +style should be filled. +It must have one of the values \fBsolid\fR, +\fBstipple\fR, \fBcross\fR, \fBoutline\fR, \fBgrid\fR. +\fBSolid\fR +means that every pixel in the area is to modified according to +\fIwriteMask\fR and \fIcolor\fR. +\fBStipple\fR means that the area should be stippled: the stipple +pattern given by \fIstipple\fR is used to determine which pixels +in the area are to be modified. +\fBCross\fR means that an X +is drawn in a solid line between the diagonally-opposite corners +of the area being rendered. +\fBOutline\fR means that the area +should not be filled at all; only an outline is drawn (if +specified by \fIoutline\fR). +\fBGrid\fR is a special style +used to draw a grid in the line style given by \fIoutline\fR. +The styles \fBcross\fR and \fBstipple\fR may be supplemented +with an outline by giving a non-zero \fIoutline\fR field. +The \fBoutline\fR and \fBgrid\fR styles don't make sense without +an an outline, and \fBsolid\fR doesn't make sense with an +outline (since all the pixels are modified anyway). +.TP +\fIstipple\fR +Used when \fIfill\fR is \fBstipple\fR to specify (in decimal) the +stipple number to use. +.TP +\fIshortName\fR +This is a one-character name for this style. +These names +are used in the specification of glyphs and also in a few +places in the Magic source code. +Most styles have no short +name; use a ``-'' in this field for them. +.TP +\fIlongName\fR +A more human-readable name for the style. +It's not used at +all by Magic. +.SH "STIPPLES SECTION" +.PP +The second section of a dstyle file is separated from the +first by a blank line. +The first line of the second +section must be +.DS L +\fBstipples\fR +.DE +and each additional line specifies one stipple pattern with +the syntax +.DS L +\fInumber pattern name\fR +.DE +\fINumber\fR is a decimal number used to name the stipple +in the \fIstipple\fR fields of style lines. +\fINumber\fR +must be no less than 1 and must be no greater than a device-dependent +upper limit. +Most devices support at least 15 stipple +patterns. +\fIPattern\fR +consists of eight octal numbers, each from 0-377 and separated +by white space. +The +numbers form an 8-by-8 array of bits indicating which +pixels are to be modified when the stipple is used. +The +\fIname\fR field is just a human-readable description of +the stipple; it isn't used by Magic. + +.SH "FILES" +\(apcad/lib/magic/sys/mos.7bit.dstyle5 + +.SH "SEE ALSO" +magic\|(1), cmap\|(5), glyphs\|(5) diff --git a/doc/man/ext.5 b/doc/man/ext.5 new file mode 100644 index 00000000..04cc5573 --- /dev/null +++ b/doc/man/ext.5 @@ -0,0 +1,306 @@ +.\" sccsid @(#)ext.5 4.2 MAGIC (Berkeley) 11/30/85 +.\" +.\" CONVENTIONS: +.\" italics: things that are substituted for +.\" boldface: characters that are typed as-is +.\" +.\" EXAMPLE: \fIfilename\fB.mag\fR +.\" or: \fBcif \fR[\fIfile\fR] +.\" +.TH EXT 5 +.UC 4 +.SH NAME +ext \- format of .ext files produced by Magic's hierarchical extractor + +.SH DESCRIPTION +Magic's extractor produces a \fB.ext\fP file for +each cell in a hierarchical design. +The \fB.ext\fP file for cell \fIname\fP is \fIname\fB.ext\fR. +This file contains three kinds of information: +environmental information (scaling, timestamps, etc), +the extracted circuit corresponding to the mask geometry of cell \fIname\fP, +and the connections between this mask geometry and the subcells of \fIname\fP. +.LP +A \fB.ext\fP file consists of a series of lines, each of which begins +with a keyword. +The keyword beginning a line determines how the remainder +of the line is interpreted. +The following set of keywords define +the environmental information: +.TP +.B "tech\ \fItechname\fR" +Identifies the technology of cell \fIname\fP +as \fItechname\fP, e.g, \fBnmos\fP, \fBcmos\fP. +.TP +.B "timestamp\ \fItime\fR" +Identifies the time when cell \fIname\fP was last modified. +The value \fItime\fP is the time stored by Unix, i.e, seconds +since 00:00 GMT January 1, 1970. +Note that this is \fInot\fP the time \fIname\fR was extracted, but rather +the timestamp value stored in the \fB.mag\fP file. +The incremental extractor compares the timestamp in each \fB.ext\fP +file with the timestamp in each \fB.mag\fP file in +a design; if they differ, that cell is re-extracted. +.TP +.B "version\ \fIversion\fR" +Identifies the version of \fB.ext\fR format used to write +\fIname\fB.ext\fR. +The current version is \fB5.1\fR. +.TP +.B "style\ \fIstyle\fR" +Identifies the style that the cell has been extracted with. +.TP +.B "scale\ \fIrscale\ cscale\ lscale\fR" +Sets the scale to be used in interpreting resistance, capacitance, +and linear dimension values in the remainder of the \fB.ext\fP file. +Each resistance value must be multiplied by \fIrscale\fP to give +the real resistance in milliohms. +Each capacitance value must be +multiplied by \fIcscale\fP to give the real capacitance in attofarads. +Each linear dimension (e.g, width, height, transform coordinates) +must be multiplied by \fIlscale\fP to give the real linear dimension +in centimicrons. +Also, each area dimension (e.g, transistor channel area) +must be multiplied by \fIscale*scale\fP to give the real area +in square centimicrons. +At most one \fBscale\fP line may appear in a \fB.ext\fP file. +If none appears, all of \fIrscale\fP, \fIcscale\fP, and \fIlscale\fP +default to 1. +.TP +.B "resistclasses\ \fIr1 r2 ...\fR" +Sets the resistance per square for the various resistance classes +appearing in the technology file. +The values \fIr1\fR, \fIr2\fR, etc. are in milliohms; they +are not scaled by the value of \fIrscale\fR specified in the +\fBscale\fR line above. +Each node in a \fB.ext\fR file has a perimeter and area for +each resistance class; the values \fIr1\fR, \fIr2\fR, etc. +are used to convert these perimeters and areas into actual +node resistances. +See ``Magic Tutorial #8: Circuit Extraction'' +for a description of how resistances are computed from +perimeters and areas by the program \fBext2sim\fR. +.PP +The following keywords define the circuit formed by +the mask information in cell \fIname\fP. +This circuit is +extracted independently of any subcells; its connections +to subcells are handled by the keywords in the section after +this one. +.TP +.B "node \fIname R C x y type a1 p1 a2 p2 ... aN pN\fR" +Defines an electrical node in \fIname\fP. +This node is referred to by +the name \fIname\fP in subsequent \fBequiv\fP lines, connections to +the terminals of transistors in \fBfet\fP lines, +and hierarchical connections or adjustments +using \fBmerge\fP or \fBadjust\fP. +The node has a total capacitance to ground of \fIC\fP attofarads, +and a lumped resistance of \fIR\fP milliohms. +For purposes of going back from the node name to the geometry +defining the node, \fI(x,\|y)\fP is the coordinate +of a point inside the node, and \fItype\fR is the layer +on which this point appears. +The values \fIa1\fR, \fIp1\fR, ... \fIaN\fR, \fIpN\fR are +the area and perimeter for the material in +each of the resistance classes described by the +\fBresistclasses\fR line at the beginning of the \fB.ext\fR file; +these values are used to compute adjusted hierarchical +resistances more accurately. +\fBNOTE:\fR +since many analysis tools compute transistor gate capacitance themselves +from the transistor's area and perimeter, +the capacitance between a node and substrate (GND!) normally +does not include the capacitance from transistor gates connected +to that node. +If the \fB.sim\fR file was produced by \fIext2sim\fR\|(1), check +the technology file that was used to produce the original \fB.ext\fR +files to see whether transistor gate capacitance is included or +excluded; +see ``Magic Maintainer's Manual #2: The Technology File'' for details. +.TP +.B "attr \fIname xl yl xh yh type text\fR" +One of these lines appears for each label +ending in the character ``\fB@\fR'' +that was attached to geometry in the node \fIname\fR. +The location of each attribute label (\fIxl yl xh yh\fR) +and the type of material to which it was attached (\fItype\fR) +are given along with the text of the label minus the trailing +``\fB@\fR'' character (\fItext\fR). +.TP +.B "equiv\ \fInode1\ node2\fR" +Defines two node names in cell \fIname\fP as being equivalent: +\fInode1\fP and \fInode2\fP. +In a collection of node names +related by \fBequiv\fP lines, exactly one must be defined +by a \fBnode\fP line described above. +.TP +.B "fet\ \fItype\ xl\ yl\ xh\ yh\ area\ perim\ sub\ GATE\ T1\ T2\ ...\fR" +Defines a transistor in \fIname\fP. +The kind of transistor is \fItype\fP, +a string that comes from the technology file and is intended to have +meaning to simulation programs. +The coordinates of a square entirely contained in +the gate region of the transistor are \fI(xl,\ yl)\fP for its lower-left +and \fI(xh,\ yh)\fP for its upper-right. +All four coordinates are in +the \fIname\fP's coordinate space, and are subject to scaling as described +in \fBscale\fP above. +The gate region of the transistor has area \fIarea\fP square centimicrons +and perimeter \fIperim\fP centimicrons. +The substrate of the transistor +is connected to node \fIsub\fP. +.sp +The remainder of a \fBfet\fP line consists of a series of triples: +\fIGATE\fP, \fIT1\fP, .... +Each describes one of the terminals of the transistor; the first describes +the gate, and the remainder describe the transistor's +non-gate terminals (e.g, source and drain). +Each triple consists of the name of a node connecting to that terminal, +a terminal length, and an attribute list. +The terminal length is in centimicrons; it is the length of that +segment of the channel perimeter connecting to adjacent material, +such as polysilicon for the gate or diffusion for a source or drain. +.sp +The attribute list is either the single token ``0'', meaning no attributes, +or a comma-separated list of strings. +The strings in the attribute list come from labels attached to the transistor. +Any label ending in the character ``\fB^\fR'' is considered a gate attribute +and appears on the gate's attribute list, minus the trailing +``\fB^\fR''. +Gate attributes may lie either along the border of a channel or in its interior. +Any label ending in the character ``\fB$\fR'' is considered a non-gate +attribute. +It appears on the list of the terminal along which it lies, +also minus the trailing ``\fB$\fR''. +Non-gate attributes may only lie on the border of the channel. +.PP +The keywords in this section describe information that is not processed +hierarchically: path lengths and accurate resistances that are computed +by flattening an entire node and then producing a value for the flattened +node. +.TP +.B "killnode\ \fInode\fR" +During resistance extraction, it is sometimes necessary to break a node +up into several smaller nodes. +The appearance of a \fBkillnode\fR line +during the processing of a \fB.ext\fR file means that all information +currently accumulated about \fInode\fR, along with all fets that have +a terminal connected to \fInode\fR, should be thrown out; it will be +replaced by information later in the \fB.ext\fR file. +The order of +processing \fB.ext\fR files is important in order for this to work +properly: children are processed before their parents, so a \fBkillnode\fR +in a parent overrides one in a child. +.TP +.B "resist\ \fInode1\ node2\ R\fR" +Defines a resistor of \fIR\fR milliohms between the two nodes +\fInode1\fR and \fInode2\fR. +Both names are hierarchical. +.TP +.B "distance\ \fIname1\ name2\ dmin\ dmax\fR" +Gives the distance between two electrical terminals \fIname1\fR +(a driver) and \fIname2\fR (a receiver). +Note that these are +terminals and not nodes: the names (which are hierarchical +label names) are used to specify two different locations on the same +electrical node. +The two distances, \fIdmin\fR and \fIdmax\fR, are the lengths +(in lambda) of the shortest and longest acyclic paths between the driver +and receiver. +.PP +The keywords in this last section describe the subcells used +by \fIname\fP, and how connections are made to and between them. +.TP +.B "use\ \fIdef\ use-id\ TRANSFORM\fR" +Specifies that cell \fIdef\fP with instance identifier \fIuse-id\fP +is a subcell of cell \fIname\fP. +If cell \fIdef\fP is arrayed, then \fIuse-id\fP will be followed +by two bracketed subscript ranges of the form: +\fB[\fIlo\fB,\fIhi\fB,\fIsep\fB]\fR. +The first range is for x, and the second for y. +The subscripts for a given dimension are +\fIlo\fP through \fIhi\fP inclusive, and the separation between +adjacent array elements is \fIsep\fP centimicrons. +.sp +\fITRANSFORM\fP is a set of six +integers that describe how coordinates in \fIdef\fP are to be +transformed to coordinates in the parent \fIname\fP. +It is used +by \fIext2sim\fP\|(1) in transforming transistor locations to +coordinates in the root of a design. +The six integers of \fITRANSFORM\fP (\fIta,\ tb,\ tc,\ td,\ te,\ tf\fR) are +interpreted as components in the following transformation matrix, +by which all coordinates in \fIdef\fP are post-multiplied to get +coordinates in \fIname\fP: +.sp +.in +2i +.nf +.ta +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +\fIta\fR \fItd\fR 0 +\fItb\fR \fIte\fR 0 +\fItc\fR \fItf\fR 1 +.fi +.in -2i +.TP +.B "merge\ \fIpath1\ path2\ C\ a1\ p1\ a2\ p2 \ ...\ aN\ pN\fR" +Used to specify a connection between two subcells, or between +a subcell and mask information of \fIname\fP. +Both \fIpath1\fP and \fIpath2\fP are hierarchical node names. +To refer to a node in cell \fIname\fP itself, its pathname is +just its node name. +To refer to a node in a subcell of \fIname\fP, its pathname consists +of the \fIuse-id\fP of the subcell (as it appeared in a \fBuse\fP line +above), followed by a slash\ (\fI/\fR), +followed by the node name in the subcell. +For example, if \fIname\fP contains subcell \fIsub\fP with use identifier +\fIsub-id\fP, and \fIsub\fP contains node \fIn\fP, the full pathname +of node \fIn\fP relative to \fIname\fP will be \fIsub-id/n\fP. +.PP +Connections between adjacent elements of an array are represented +using a special syntax that takes advantage of the regularity of arrays. +A use-id in a path may optionally be followed by a range of the form +\fB[\fIlo\fB:\fIhi\fB]\fR (before the following slash). +Such a use-id +is interpreted as the elements \fIlo\fP through \fIhi\fP inclusive +of a one-dimensional array. +An element of a two-dimensional array may +be subscripted with two such ranges: first the y range, then the x range. +.PP +Whenever one \fIpath\fP in a \fBmerge\fP line contains such a subscript +range, the other must contain one of comparable size. +For example, +.sp +.ti +1i +\fBmerge\fP\ \ sub-id[1:4,2:8]/a\ \ sub-id[2:5,1:7]/b +.sp +is acceptable because the range 1:4 is the same size as 2:5, +and the range 2:8 is the same size as 1:7. +.sp +When a connection occurs between nodes in different cells, +it may be that some +resistance and capacitance has been recorded redundantly. +For example, polysilicon in one cell may overlap polysilicon in another, +so the capacitance to substrate will have been recorded twice. +The values \fIC\fP, \fIa1\fR, \fIp1\fR, etc. in a \fBmerge\fP line provide a +way of compensating for such overlap. +Each of \fIa1\fR, \fIp1\fR, etc. (usually negative) +are added to the area and perimeter +for material of each resistance class +to give an adjusted area and perimeter +for the aggregate node. +The value \fIC\fP attofarads (also usually negative) is added to the +sum of the capacitances (to substrate) of nodes \fIpath1\fP and +\fIpath2\fP to give the capacitance of the aggregate node. +.TP +.B "cap\ \fInode1\ node2\ C\fR" +Defines a capacitor between the nodes \fInode1\fP and \fInode2\fP, +with capacitance \fIC\fP. +This construct is used to specify both internodal capacitance +within a single cell and between cells. + +.SH AUTHOR +Walter Scott + +.SH "SEE ALSO" +ext2sim\|(1), magic\|(1) diff --git a/doc/man/ext2sim.1 b/doc/man/ext2sim.1 new file mode 100644 index 00000000..98e8381d --- /dev/null +++ b/doc/man/ext2sim.1 @@ -0,0 +1,183 @@ +.TH EXT2SIM 1 +.UC 4 +.SH NAME +ext2sim \- convert hierarchical \fIext\fR\|(5) extracted-circuit files +to flat \fIsim\fR\|(5) files +.SH SYNOPSIS +.B ext2sim +[ +.B \-a +.I aliasfile +] [ +.B \-l +.I labelsfile +] [ +.B \-o +.I simfile +] [ +.B \-A +] [ +.B \-B +] [ +.B \-F +] [ +.B \-L +] [ +.B \-t +] [ +.I "extcheck-options" +] [ +.I -y num +] [ +.I -f mit|lbl|su +] [ +.I -J hier|flat +] [ +.I -j device:sdRclass[/subRclass]/defaultSubstrate +] +.I root + +.SH DESCRIPTION +Ext2sim will convert an extracted circuit from the hierarchical +\fIext\fR\|(5) representation produced by Magic to the +flat \fIsim\fR\|(5) representation required by many simulation tools. +The root of the tree to be extracted is the file \fIroot\fB.ext\fR; +it and all the files it references are recursively flattened. +The result is a single, flat representation of the circuit that is +written to the file \fIroot\fB.sim\fR, a list of node aliases +written to the file \fIroot\fB.al\fR, and a list of the locations +of all nodenames in CIF format, suitable for plotting, to the +file \fIroot\fB.nodes\fR. +The file \fIroot\fB.sim\fR is +suitable for use with programs such as +\fIcrystal\fP\|(1), \fIesim\fP\|(1), or \fIsim2spice\fP\|(1). +.LP +The following options are recognized: +.TP 1.0i +.B \-a\ \fIaliasfile\fP +Instead of leaving node aliases in the file \fIroot\fB.al\fR, leave it +in \fIaliasfile\fP. +.TP 1.0i +.B \-l\ \fIlabelfile\fP +Instead of leaving a CIF file with the locations of all node names +in the file \fIroot\fB.nodes\fR, leave it in \fIlabelfile\fP. +.TP 1.0i +.B \-o\ \fIoutfile\fP +Instead of leaving output in the file \fIroot\fB.sim\fR, leave it +in \fIoutfile\fP. +.TP 1.0i +.B \-A +Don't produce the aliases file. +.TP 1.0i +.B \-B +Don't output transistor or node attributes in the \fB.sim\fR file. +This option will also disable the output of information such as +the area and perimeter of source and drain diffusion and the +fet substrate. For compatibitlity reasons the latest version of ext2sim +outputs this information as node attibutes. +This option is necessary when preparing input for programs that +don't know about attributes, such as \fIsim2spice\fR\|(1) (which is +actually made obsolete by \fIext2spice\fR\|(1), anyway), +or \fIrsim\fR\|(1). +.TP 1.0i +.B \-F +Don't output nodes that aren't connected to fets (floating nodes). +.TP 1.0i +.B \-L +Don't produce the label file. +.TP 1.0i +.B \-t\fIchar\fR +Trim characters from node names when writing the output file. +\fIChar\fR +should be either "#" or "!". +The option may be used twice if both characters +are desired. +.TP 1.0i +.B \-f \fIMIT|LBL|SU\fR +Select the output format. MIT is the traditional \fIsim\fR(5) format. +LBL is a variant of it understood by \fIgemini\fR(1) which includes the +substrate connection as a fourth terminal before length and width. +SU is the internal Stanford format which is described also in \fIsim\fR(5) +and includes areas and perimeters of fet sources, drains and substrates. +.TP 1.0i +.B \-y \fInum\fR +Select the precision for outputing capacitors. The default is 1 which means +that the capacitors will be printed to a precision of .1 fF. +.TP 1.0i +.B \-J \fIhier|flat\fR +Select the source/drain area and perimeter extraction algorithm. If +\fIhier\fR is selected then the areas and perimeters are extracted +\fIonly within each subcell\fR. For each fet in a subcell the area +and perimeter of its source and drain within this subcell are output. +If two or more fets share a source/drain node then the total area and +perimeter will be output in only one of them and the other will have 0. +If \fIflat\fR is selected the same rules apply only that the scope of +search for area and perimeter is the whole netlist. In general \fIflat\fR +(which is the default) will give accurate results (it will take into +account shared sources/drains) but hier is provided for backwards +compatibility with version 6.4.5. On top of this selection you can +individually control how a terminal of a specific fet will be extracted +if you put a source/drain attribute. \fIext:aph\fR makes the extraction +for that specific terminal hierarchical and \fIext:apf\fR makes the +extraction flat (see the magic tutorial about attaching attribute labels). +Additionaly to ease extraction of bipolar transistors the gate attribute +\fIext:aps\fR forces the output of the substrate area and perimeter for +a specific fet (in flat mode only). +.TP 1.0i +.B \-j \fIdevice:sdRclass[/subRclass]/defaultSubstrate\fR +Gives ext2sim information about the source/drain resistance class of the +fet type \fIdevice\fR. Makes \fIdevice\fR to have \fIsdRclass\fR source +drain resistance class, \fIsubRclass\fR substrate (well) resistance class +and the node named \fIdefaultSubstrate\fR as its default substrate. +The defaults are nfet:0/Gnd\! and pfet:1/6/Vdd\! which correspond to the +MOSIS technology file but things might vary in your site. Ask your local +cad administrator. + +.PP +The way the extraction of node area and perimeter works in magic the total +area and perimeter of the source/drain junction is summed up on a single node. +That is why all the junction areas and perimeters are summed up on a single +node (this should not affect simulation results however). +.PP +\fISpecial care must be taken when the substrate of a fet is tied to a +node other than the default substrate\fR (eg in a bootstraping charge +pump). +To get the correct substrate info in these cases the fet(s) with +separate wells should be in their own separate subcell with ext:aph attributes +attached to their sensitive terminals (also all the transistors which share +sensistive terminals with these should be in another subcell with the same +attributes). + + +.PP +In addition, all of the options of \fIextcheck\fR\|(1) are accepted. + +.SH "SCALING AND UNITS" +If all of the \fB.ext\fR files in the tree read by \fIext2sim\fP have the +same geometrical scale (specified in the \fBscale\fP +line in each \fB.ext\fR file), +this scale is reflected through to the output, resulting in substantially +smaller \fB.sim\fR files. +Otherwise, the geometrical unit in the output \fB.sim\fR file +is a centimicron. +.PP +Resistance and capacitance are always output in ohms and femptofarads, +respectively. + +.SH "SEE ALSO" +extcheck\|(1), ext2dlys\|(1), ext2spice\|(1), +magic\|(1), rsim\|(1), ext\|(5), sim\|(5) + +.SH AUTHOR +Walter Scott additions/fixes by Stefanos Sidiropoulos. + +.SH BUGS +Transistor gate capacitance is typically not included in node +capacitances, as most analysis tools compute the gate capacitance directly +from the gate area. +The \fB-c\fR flag therefore provides a limit only on non-gate capacitance. +The areas and perimeters of fet sources and drains work only with the +simple extraction algorith and not with the extresis flow. So you have +to model them as linear capacitors (create a special extraction style) +if you want to extract parasitic resistances with extresis. + diff --git a/doc/man/ext2spice.1 b/doc/man/ext2spice.1 new file mode 100644 index 00000000..a371f0ab --- /dev/null +++ b/doc/man/ext2spice.1 @@ -0,0 +1,152 @@ +.TH EXT2SPICE 1 +.UC 4 +.SH NAME +ext2spice \- convert hierarchical \fIext\fR\|(5) extracted-circuit files +to flat \fIspice\fR\| files +.SH SYNOPSIS +.B ext2spice +[ +.B \-B +] [ +.I "extcheck-options" +] [ +.I -M|m +] [ +.I -y num +] [ +.I -f hspice|spice3|spice2 +] [ +.I -J hier|flat +] [ +.I -j device:sdRclass[/subRclass]/defaultSubstrate +] +.I root + +.SH DESCRIPTION +Ext2spice will convert an extracted circuit from the hierarchical +\fIext\fR\|(5) representation produced by Magic to a flat spice +file which can be accepted by spice2, spice3, hspice and other +simulation tools. +The root of the tree to be extracted is the file \fIroot\fB.ext\fR; +it and all the files it references are recursively flattened. +The result is a single, flat representation of the circuit that is +written to the file \fIroot\fB.spice\fR . +.LP +The following options are recognized: +.TP 1.0i +.B \-o\ \fIoutfile\fP +Instead of leaving output in the file \fIroot\fB.spice\fR, leave it +in \fIoutfile\fP. +.TP 1.0i +.B \-B +Don't output transistor or node attributes in the spice file. +Usually the attributes of a node or a device are output as +special comments **fetattr and **nodeatrr which can be processed +further to create things such a initial conditions etc. +.TP 1.0i +.B \-F +Don't output nodes that aren't connected to fets (floating nodes). +Normally capacitance from these nodes is output with the comment +**FLOATING attached on the same line. +.TP 1.0i +.B \-t\fIchar\fR +Trim characters from node names when writing the output file. +\fIChar\fR +should be either "#" or "!". +The option may be used twice if both characters +are desired. Trimming "#" and "!" is enabled by default when the format is +hspice. +.TP 1.0i +.B -\fIM|m\fR +Merge parallel fets. \fI-m\fR means conservative merging of fets that have +equal widths only (usefull with hspice format multiplier if delta W +effects need to be taken care of). -M means aggressive merging: the fets +are merged if they have the same terminals and the same length. +.TP 1.0i +.B \-y \fInum\fR +Select the precision for outputing capacitors. The default is 1 which means +that the capacitors will be printed to a precision of .1 fF. +.TP 1.0i +.B \-f \fIhspice|spice2|spice3\fR +Select the output format. Spice3 is the the format understood by the +latest version of berkeley spice. Node names have the same names as they +would in a \fIsim\fR(5) file and no special constructs are used. +Spice2 is the format understood by the older version of spice (which +usually has better convergence). Node names are numbers and a dictionary +of number and corresponding node is output in the end. +HSPICE is a format understood by meta-software's hspice and other +commercial tools. In this format node names cannot be longer than 15 +characters long (blame the fortran code): so if a hierarchical node name +is longer it is truncated to something like x1234/name where x1234 is +an alias of the normal node hierarchical prefix and name its hierarchical +postfix (a dictionary mapping prefixes to real hierarchical paths is output +at the end of the spice file). If the node name is still longer than 15 +characters long (again blame the fortran code) it is translated to something +like z@1234 and the equivalent name is output as a comment. In addition since +hspice supports scaling and multipliers so the output dimensions are in +lambdas and if parallel fets are merged the hspice construct \fIM\fR is used. +.TP 1.0i +.B \-J \fIhier|flat\fR +Select the source/drain area and perimeter extraction algorithm. If +\fIhier\fR is selected then the areas and perimeters are extracted +\fIonly within each subcell\fR. For each fet in a subcell the area +and perimeter of its source and drain within this subcell are output. +If two or more fets share a source/drain node then the total area and +perimeter will be output in only one of them and the other will have 0. +If \fIflat\fR is selected the same rules apply only that the scope of +search for area and perimeter is the whole netlist. In general \fIflat\fR +(which is the default) will give accurate results (it will take into +account shared sources/drains) but hier is provided for backwards +compatibility with version 6.4.5. On top of this selection you can +individually control how a terminal of a specific fet will be extracted +if you put a source/drain attribute. \fIext:aph\fR makes the extraction +for that specific terminal hierarchical and \fIext:apf\fR makes the +extraction flat (see the magic tutorial about attaching attribute labels). +Additionaly to ease extraction of bipolar transistors the gate attribute +\fIext:aps\fR forces the output of the substrate area and perimeter for +a specific fet (in flat mode only). +.TP 1.0i +.B \-j \fIdevice:sdRclass[/subRclass]/defaultSubstrate\fR +Gives ext2sim information about the source/drain resistance class of the +fet type \fIdevice\fR. Makes \fIdevice\fR to have \fIsdRclass\fR source +drain resistance class, \fIsubRclass\fR substrate (well) resistance class +and the node named \fIdefaultSubstrate\fR as its default substrate. +The defaults are nfet:0/Gnd\! and pfet:1/6/Vdd\! which correspond to the +MOSIS technology file but things might vary in your site. Ask your local +cad administrator. + +.PP +The way the extraction of node area and perimeter works in magic the total +area and perimeter of the source/drain junction is summed up on a single node. +That is why all the junction areas and perimeters are summed up on a single +node (this should not affect simulation results however). +.PP +\fISpecial care must be taken when the substrate of a fet is tied to a +node other than the default substrate\fR (eg in a bootstraping charge +pump). +To get the correct substrate info in these cases the fet(s) with +separate wells should be in their own separate subcell with ext:aph attributes +attached to their sensitive terminals (also all the transistors which share +sensistive terminals with these should be in another subcell with the same +attributes). + + +.PP +In addition, all of the options of \fIextcheck\fR\|(1) are accepted. + +.PP +The awk filter spice2sim is provided with the current distribution for +debugging purposes. + +.SH "SEE ALSO" +extcheck\|(1), ext2spice\|(1), +magic\|(1), rsim\|(1), ext\|(5), sim\|(5) + +.SH AUTHOR +Stefanos Sidiropoulos. + +.SH BUGS +The areas and perimeters of fet sources and drains work only with the +simple extraction algorith and not with the extresis flow. So you have +to model them as linear capacitors (create a special extraction style) +if you want to extract parasitic resistances with extresis. diff --git a/doc/man/extcheck.1 b/doc/man/extcheck.1 new file mode 100644 index 00000000..f262d83c --- /dev/null +++ b/doc/man/extcheck.1 @@ -0,0 +1,121 @@ +.TH EXTCHECK 1 +.SH NAME +extcheck \- check hierarchical \fIext\fR\|(5) files for global node +connectivity and summarize number of fets, nodes, etc. +.SH SYNOPSIS +.B extcheck +[ +.B \-c +.I cthresh +] [ +.B \-p +.I path +] [ +.B \-r +.I rthresh +] [ +.B \-s +\fIsym\fB=\fIvalue\fR +] [ +.B \-C +] [ +.B \-R +] [ +.B \-S +.I symfile +] [ +.B \-T +.I tech +] +.I root + +.SH DESCRIPTION +\fIExtcheck\fR will read an extracted circuit in the hierarchical \fIext\fR\|(5) +representation produced by Magic, check to ensure +that all global nodes (those to which a label ending in an +exclamantion point is attached) are fully connected in +the layout, and then print a count of the number of various +items (nodes, fets, etc) encountered while flattening the +circuit. +The root of the tree to be processed is the file \fIroot\fB.ext\fR; +it and all the files it references are recursively flattened. +.PP +The following options are recognized: +.TP +.B \-c\ \fIcthresh\fP +Set the capacitance threshold to \fIcthresh\fP femtofarads. +\fIExtcheck\fR will count the number of explicit internodal capacitors +greater than \fIcthresh\fR, the number of nodes whose capacitance +is greater than \fIcthresh\fR, as well as the total number of +nodes. +(Other programs such as \fIext2sim\fR\|(1) use this +option as a threshold value below which a capacitor will not +be output). +The default value for \fIcthresh\fP is 10 femtofarads. +.TP +.B \-p\ \fIpath\fP +Normally, the path to search for \fB.ext\fP files is determined by +looking for \fBpath\fP commands in first ~cad/lib/magic/sys/.magic, +then ~/.magic, then .magic in the current directory. +If \fB\-p\fP +is specified, the colon-separated list of directories specified +by \fIpath\fP is used instead. +Each of these directories is searched +in turn for the \fB.ext\fP files in a design. +.TP +.B \-r\ \fIrthresh\fP +Set the resistance threshold to \fIrthresh\fP ohms. +Similar in function +to \fB\-c\fR, but for resistances. +The default value for \fIrthresh\fP is 10 ohms. +.TP +.B \-s\ \fIsym\fB=\fIvalue\fP +It's possible to use special attributes attached to transistor gates +to control the length and width of transistors explicitly, rather than +allowing them to be determined by the extractor. +These attributes +are of the form \fBext:w=\fIwidth\fB^\fR or \fBext:l=\fIlength\fB^\fR, +where \fIwidth\fR or \fIlength\fR can either be numeric, or textual. +(The trailing ``\fB^\fR'' indicates that these are transistor +gate attributes). +If textual, they are treated as symbols which can be assigned a numeric +value at the time \fIext2sim\fR is run. +The \fB\-s\fR flag is used to +assign numeric values to symbols. +If a textual symbol appears in one +of the above attributes, but isn't given a numeric value via \fB\-s\fR +(or \fB\-S\fR below), then it is ignored; otherwise, the transistor's +length or width is set to the numeric value defined for that symbol. +\fI(This option is not currently used by extcheck, +but it is common to ext2sim\|(1) and other +tools that are written using the extflat\|(3) library)\fR +.TP +.B \-C +Set the capacitance threshold to infinity. +Because this avoids any internodal capacitance processing, +all tools will run faster when this flag is given. +.TP +.B \-R +Set the resistance threshold to infinity. +.TP +.B \-S\ \fIsymfile\fP +Each line in the file \fIsymfile\fR is of the form \fIsym\fB=\fIvalue\fR, +just like the argument to the \fB\-s\fR flag above; the lines are interpreted +in the same fashion. +\fI(This option is not currently used by extcheck, +but it is common to ext2sim et. al.)\fR +.TP +.B \-T\ \fItech\fP +Set the technology in the output \fB.sim\fR file to \fItech\fP. +This overrides any technology specified in the root \fB.ext\fR file. + +.SH "SEE ALSO" +ext2dlys\|(1), ext2sim\|(1), ext2spice\|(1), magic\|(1), +rsim\|(1), sim2spice\|(1), ext\|(5), sim\|(5) + +.SH AUTHOR +Walter Scott + +.SH BUGS +The \fB\-s\fR mechanism is incomplete; it should allow quantities other than +transistor lengths and widths to be specified. diff --git a/doc/man/glyphs.5 b/doc/man/glyphs.5 new file mode 100644 index 00000000..8129cc51 --- /dev/null +++ b/doc/man/glyphs.5 @@ -0,0 +1,78 @@ +.\" sccsid @(#)glyphs.5 4.2 (Berkeley) 10/17/85 +.\" +.\" CONVENTIONS: +.\" italics: things that are substituted for +.\" boldface: characters that are typed as-is +.\" +.\" EXAMPLE: \fIfilename\fB.mag\fR +.\" or: \fBcif \fR[\fIfile\fR] +.\" +.TH GLYPHS 5 +.UC 4 +.SH NAME +glyphs \- format of .glyphs files + +.SH DESCRIPTION +.PP +Glyph files (``.glyph'' extension) are used to store commonly-used +bit patterns (glyphs) for Magic. +Right now, the bit patterns are used +for two purposes in Magic. +First, they specify patterns for +programmable cursors: each cursor shape (e.g. the arrow used for +the wiring tool) is read in as a glyph from a glyph file. +Second, glyphs +are used by the window manager to represent the icons displayed +at the ends of scroll bars. +Glyph file names normally have the +extension \fB.glyph\fR. +.PP +Glyph files are stored in ASCII format. +Lines beginning with +``#'' are considered to be comments and are ignored. +Blank lines +are also ignored. +The first non-comment line in a glyph file +must have the syntax +.DS L +\fBsize \fInGlyphs width height\fR +.DE +The \fInGlyphs\fR field must be a number giving the total number +of glyphs stored in the file. +The \fIwidth\fR and \fIheight\fR +fields give the dimensions of each glyph in pixels. +All glyphs +in the same file must have the same size. +.PP +The \fBsize\fR line is followed by a description for each of +the glyphs. +Each glyph consists of \fIheight\fR lines each +containing 2\(mu\fIwidth\fR characters. Each pair of characters +corresponds to a bit position in the glyph, with the leftmost +pair on the topmost line corresponding to the upper-left pixel +in the glyph. +.PP +The first character of each pair specifies the +color to appear in that pixel. +The color is represented as +as a single character, which must be the short name +of a display style in the current display style file. +Some +commonly-used characters are \fBK\fR for black, \fBW\fR for +white, and \fB.\fR for the background color (when \fB.\fR is +used in a cursor, it means that that pixel position is +transparent: the underlying picture appears through the cursor). +See ``Magic Maintainer's Manual #3: Display Styles, Color Maps, +and Glyphs'' for more information. +.PP +The second character of each pair is normally blank, except for +one pixel per glyph which may contain a ``*'' in the second +character. +The ``*'' is used for programmable cursors to +indicate the hot-spot: the pixel corresponding to the ``*'' +is the one that the cursor is considered to point to. +.PP +For an example of a glyph file, see \(apcad/lib/magic/sys/color.glyphs. + +.SH "SEE ALSO" +magic\|(1), dstyle\|(5) diff --git a/doc/man/mag.5 b/doc/man/mag.5 new file mode 100644 index 00000000..7423db12 --- /dev/null +++ b/doc/man/mag.5 @@ -0,0 +1,236 @@ +.\" sccsid @(#)magic.5 4.1 MAGIC (Berkeley) 11/29/85 +.\" +.\" CONVENTIONS: +.\" italics: things that are substituted for +.\" boldface: characters that are typed as-is +.\" +.\" EXAMPLE: \fIfilename\fB.mag\fR +.\" or: \fBcif \fR[\fIfile\fR] +.\" +.de (X +.sp +.nf +.in +1i +.. +.de )X +.in -1i +.sp +.fi +.. +.TH MAGIC 5 +.UC 4 +.SH NAME +magic \- format of \fB.mag\fR files read/written by Magic + +.SH DESCRIPTION +Magic uses its own internal ASCII format for storing cells in disk files. +Each cell \fIname\fP is stored in its own file, named \fIname\fB.mag\fR. +.LP +The first line in a \fB.mag\fP file is the string +.(X +\fBmagic\fP +.)X +to identify this as a Magic file. +.LP +The next line is optional and is used to identify the technology +in which a cell was designed. +If present, it should be of the form +.(X +\fBtech\fP \fItechname\fP +.)X +If absent, the technology defaults to a system-wide standard, +currently \fBnmos\fP. +.LP +The next line is also optional and gives a timestamp for the cell. +The line is of the format +.(X +\fBtimestamp\fP \fIstamp\fP +.)X +where \fIstamp\fP is a number of seconds since 00:00 GMT +January 1, 1970 (i.e, the Unix time returned by the library +function \fItime()\fP). +It should be the last time this cell or any of its children changed. +The timestamp is used to detect when a child is edited outside the +context of its parent (the parent stores the last timestamp it saw +for each of its children; see below). +When this occurs, the +design-rule checker must recheck the entire area of the child for +subcell interaction errors. +If this field is omitted in a cell, Magic +supplies a default value that forces the rechecks. +.LP +Next come lines describing the contents of the cell. +There are three kinds of groups of lines, describing +mask rectangles, subcell uses, and labels. +Each group must appear contiguously in the file, +but the order between groups is arbitrary. +.LP +Each group of mask rectangles is headed with a line of the format +.(X +\fB<<\ \fIlayer\fB\ >>\fR +.)X +where \fIlayer\fP is a layername known in the current technology +(see the \fBtech\fP line above). +Each line after this header +has the format +.(X +\fBrect\fI xbot ybot xtop ytop\fR +.)X +where \fI(xbot,\ ybot)\fR is the lower-left corner of the rectangle +in Magic (lambda) coordinates, and \fI(xtop,\ ytop)\fR is +the upper-right corner. +Degenerate rectangles are not allowed; \fIxbot\fP must be strictly +less than \fIxtop\fP, and \fIybot\fP strictly less than \fIytop\fP. +The smallest legal value of \fIxbot\fP or \fIybot\fP is +\fB\(mi67108858\fP, +and the largest legal value for \fIxtop\fP or \fIytop\fP is +\fB67108858\fP. +Values that approach these limits (within a factor +of 100 or 1000) may cause numerical overflows in Magic even though +they are not strictly illegal. +We recommend using coordinates around +zero as much as possible. +.PP +Rectangles should be non-overlapping, although this is not +essential. +They should also already have been merged into maximal +horizontal strips (the neighbor to the right or left of a rectangle +should not be of the same type), but this is also not essential. +.PP +The second kind of line group describes a single cell use. +Each cell use group is of the following form: +.(X +\fBuse\fI filename use-id\fR +\fBarray\fI xlo xhi xsep ylo yhi ysep\fR +\fBtimestamp\fI stamp\fR +\fBtransform\fI a b c d e f\fR +\fBbox\fI xbot ybot xtop ytop\fR +.)X +A group specifies a single instance of the cell named \fIfilename\fP, +with instance-identifier \fIuse-id\fP. +The instance-identifier \fIuse-id\fP must be unique among all cells +used by this \fB.mag\fP file. +If \fIuse-id\fP is not specified, a unique one is generated automatically. +.LP +The \fBarray\fP line need only be present if the cell is an array. +If so, the X indices run from \fIxlo\fP to \fIxhi\fP inclusive, +with elements being separated from each other in the X dimension +by \fIxsep\fP lambda. +The Y indices run from \fIylo\fP to \fIyhi\fP inclusive, +with elements being separated from each other in the Y dimension +by \fIysep\fP lambda. +If \fIxlo\fP and \fIxhi\fP are equal, \fIxsep\fP is ignored; similarly +if \fIylo\fP and \fIyhi\fP are equal, \fIysep\fP is ignored. +.LP +The \fBtimestamp\fP line is optional; if present, it gives the +last time this cell was aware that the child \fIfilename\fP changed. +If there is no \fBtimestamp\fP line, a timestamp of 0 is assumed. +When the subcell is read in, this value is compared to the actual value +at the beginning of the child cell. +If there is a difference, the +``timestamp mismatch'' message is printed, and Magic rechecks +design-rules around the child. +.LP +The \fBtransform\fP line gives the geometric transform from coordinates +of the child \fIfilename\fP into coordinates of the cell being read. +The six integers \fIa\fP, \fIb\fP, +\fIc\fP, \fId\fP, \fIe\fP, and \fIf\fP +are part of the following transformation matrix, +which is used to postmultiply all coordinates in the child \fIfilename\fP +whenever their coordinates in the parent are required: +.sp +.in +2i +.nf +.ta +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +\fIa\fR \fId\fR 0 +\fIb\fR \fIe\fR 0 +\fIc\fR \fIf\fR 1 +.fi +.in -2i +.LP +Finally, \fBbox\fP gives an estimate of the bounding box of cell +\fIfilename\fP (covering all the elements of the array if an \fBarray\fP +line was present), in coordinates of the cell being read. +.LP +The third kind of line group in a \fB.mag\fP file is a +list of labels. +It begins with the line +.(X +\fB<<\ labels\ >>\fR +.)X +and is followed by zero or more lines of the following form: +.(X +\fBrlabel\fI layer xbot ybot xtop ytop position text\fR +.)X +Here \fIlayer\fP is the name of one of the layers specified in +the technology file for this cell. +The label is attached to material +of this type. +\fILayer\fP may be \fBspace\fP, in which case the +label is not considered to be attached to any layer. +.LP +Labels are rectangular. +The lower-left corner of the label (the part +attached to any geometry if \fIlayer\fP is non-\fBspace\fR) is +at \fI(xbot,\ ybot)\fR, and the upper-right corner at \fI(xtop,\ ytop)\fR. +The width of the rectangle or its height may be zero. +In fact, most +labels in Magic have a lower-left equal to their upper right. +.LP +The text of the label, \fItext\fP, may be any sequence of characters not +including a newline. +This text is located at one of nine possible orientations +relative to the center of the label's rectangle. +\fIPosition\fP is an integer between 0 and 8, +each of which corresponds to a different orientation: +.(X +.ta +0.5i +0.5i +\fB0\fR center +\fB1\fR north +\fB2\fR northeast +\fB3\fR east +\fB4\fR southeast +\fB5\fR south +\fB6\fR southwest +\fB7\fR west +\fB8\fR northwest +.)X +.LP +A \fB.mag\fP file is terminated by the line +.(X +\fB<<\ end\ >>\fR +.)X +Everything following this line is ignored. +.LP +Any line beginning with a pound sigh (``\fB#\fR'') is considered +to be a comment and ignored. +Beware, however, that these comments +are discarded by Magic when it reads a cell, so if that cell is written +again by Magic, the comments will be lost. + +.SH "NOTE FOR PROGRAMS THAT GENERATE MAGIC FILES" +Magic's incremental design rule checker expects that every cell +is either completely checked, or contains information to tell the +checker which areas of the cell have yet to be +examined for design-rule violations. +To make sure that the design-rule checker verifies all the +material that has been generated for a cell, programs +that generate \fB.mag\fP files should place the following rectangle +in each file: +.(X +\fB<< checkpaint >>\fR +\fBrect \fIxbot ybot xtop ytop\fR +.)X +This rectangle may appear anywhere a list of rectangles is allowed; +immediately following the \fBtimestamp\fP line at the beginning of +a \fB.mag\fP file is a good place. +The coordinates \fIxbot\fR +etc. should be large enough to completely cover anything in the +cell, and must surround all this material by at least one lambda. +Be careful, however, not to make this area too ridiculously large. +For example, if you use the maximum and minimum legal tile coordinates, +it will take the design-rule checker an extremely long time +to recheck the area. + +.SH "SEE ALSO" +magic\|(1) diff --git a/doc/man/magic.1 b/doc/man/magic.1 new file mode 100644 index 00000000..58b271b3 --- /dev/null +++ b/doc/man/magic.1 @@ -0,0 +1,2472 @@ +.\" rcsid "$Header" +.\" +.\" CONVENTIONS: +.\" italics: things that are substituted for +.\" boldface: characters that are typed as-is +.\" +.\" EXAMPLE: \fIfilename\fB.mag\fR +.\" or: \fBcif write \fR[\fIfile\fR] +.\" +.TH MAGIC 1 +.UC 4 +.SH NAME +magic \- VLSI layout editor +.SH SYNOPSIS +.B magic +[ +.BI \-T \ technology +] [ +.BI \-d \ device_type +] [ +.BI \-g \ graphics_port +] [ +.BI \-m \ monitor_type +] [ +.B \-D +] [ +\fIfile\fP ] +.br + +.SH DESCRIPTION +Magic is an interactive editor for VLSI layouts that runs under all variants +of UNIX, including Mac OS-X and Cygwin. +This man page is a reference manual; if you are a first-time user, you should +use the Magic tutorials to get acquainted with the system (see the online +resources links below). +.PP +Magic uses two windows: one for text and a separate window for displaying +layouts. +Magic runs under the window system X11 (use under Cygwin requires +the presence of an X11 server in Windows; the server that comes packaged +with Cygwin works well). +The command line switch "-d" can be used to tell +Magic which kind of display you are running. +Specifically, this is useful +to tell magic to use OpenGL graphics instead of plain X11 ("-d OGL"), or +to use 24 bit plane graphics instead of 8 bit planes ("-d 24BITS") if +both are available on a video card with overlay support. +.PP +Here are the options accepted by Magic: +.TP +.B \-T +The next argument is the name of a technology. +The tile types, display information, and design rules for this technology +are read by Magic from a technology file when it starts up. +The technology defaults to ``scmos''. +.TP +.B \-d +The next argument is the type of workstation or graphics display being used. +Magic supports these types: +.RS +.TP +.B NULL +A null device for running Magic without using +a graphics display, such as a batch job. +Note that the special case +"-dnull" (lowercase, no space) has a more streamlined startup specifically +for batch processing. +.TP +.B X11 +X-windows, version 11. +The is the preferred interface. +Magic acts as a client to the X window server +and interfaces to all graphics terminals supported +by the X server. +.TP +.B OGL +OpenGL graphics running under X11. +This is the preferred interface on +systems having hardware-accelerated 3D graphics video cards and drivers. +.IP +Addition information on Magic's X11 driver, including options for .Xdefaults +files, may be +found in ``Magic Maintainer's Manual #4: Using Magic Under X Windows''. +.TP +.B XWIND +Simply another name for the X11 driver. +.RE +If no device is specified, Magic tries to guess which driver is appropriate +(by checking the environment variables and by poking around in /dev). +.LP +When Magic starts up it looks for a command file in +${CAD_ROOT}/magic/sys/.magicrc and processes it if it exists. +Then Magic looks for a file with the +name ``.magicrc'' in the home directory and processes it if +it exists. +Finally, Magic looks for a .magicrc file in the +current directory and reads it as a command file if +it exists. +The .magicrc file format is described under the +\fBsource\fR command. +If magic is compiled with Tcl/Tk support, then +any magic or Tcl/Tk commands may be used inside the startup file. +The startup file name was changed to ".magicrc" to avoid conflicts +with a common system file named ".magic". +However, the name ".magic" +will be searched after ".magicrc" for backward compatibility. + +.SH "COMMANDS -- GENERAL INFORMATION" +.PP +Magics uses types of commands: Key macros and long commands. +The first form consists of single-key (or button) abbreviations called +``macros''; macros are invoked by pressing a single key or mouse +button. +Certain macros are predefined in the systemwide +${CAD_ROOT}/magic/sys/.magicrc file, but you can override them and +add your own macros using the \fBmacro\fR command (described below +under COMMANDS FOR ALL WINDOWS). +The special macro "." is reserved +to mean "execute the last typed long command". + +You can enter long commands in the terminal console at the console +prompt, or from the layout window by typing a \fB:\fR or \fB;\fR +key, which are the two other reserved macros meaning "switch keyboard +focus to the console window". +After typing the \fB:\fR or \fB;\fR +key, type the text of the command, which will be written to the +terminal window. +Multiple commands may be specified on one line by +separating them with semicolons. + +.PP +Most commands deal with the window underneath the cursor, +so if a command doesn't do what you expect make sure that you +are pointing to the correct place on the screen. +There are several +different kinds of windows in Magic (layout, color, and netlist); +each window has a different command set, described in a separate +section below. + +.SH "MOUSE BUTTONS FOR LAYOUT WINDOWS" +.PP +Magic uses a three button mouse. +The buttons are interpreted in a way that +depends on the current tool, as indicated by the shape of the +cursor (see the \fBtool\fR command). +The +various tools are described below. +The initial tool is \fBbox\fR. +These interpretations apply only when mouse buttons are pressed +in the interior of a layout window. +.TP +.B "Box Tool" +This is the default tool, and is indicated by a crosshair cursor. +It is used to position the box and to +paint and erase: +.RS +.TP +\fBleft\fR +This button is used to move the box by one of its corners. +Normally, this button picks up the box by its lower-left corner. +To pick the box up by a different corner, click the right button while +the left button is down. +This switches the pick-up point to the +corner nearest the cursor. +When the button +is released, the box is moved to position the corner at +the cursor location. +If the box has been set to snap to +the window's grid (see the \fB:snap\fR command), then +the box corner is left aligned with the grid that the +user has chosen for the window with the \fB:grid\fR command, +even if that grid is not visible. +.TP +\fBright\fR +Change the size of the box by moving one corner. +Normally +this button moves the upper-right corner of the box. +To move a +different corner, click the left button while the right +button is down. +This switches the corner to the one nearest +the cursor. +When you release the button, three corners of the +box move in order to place the selected corner at the cursor +location (the corner opposite the one you picked up remains fixed). +Snapping to the window's grid is handled as for the left button. +.TP +\fBmiddle (bottom)\fR +Used to paint or erase. +If the crosshair is over paint, then +the area of the box is painted with the layer(s) underneath the +crosshair. +If the crosshair is over white space, then the +area of the box is erased. +.RE +.TP +.B "Wiring Tool" +The wiring tool, indicated by an arrow cursor, +is used to provide an efficient interface to the +wiring commands: +.RS +.TP +\fBleft\fR +Same as the long command \fBwire type\fR. +.TP +\fBright\fR +Same as the long command \fBwire leg\fR. +.TP +\fBmiddle (bottom) \fR +Same as the long command \fBwire switch\fR. +.RE +.TP +.B "Netlist Tool" +This tool is used to edit netlists interactively. +It is indicated by +a thick box cursor. +.RS +.TP +\fBleft\fR +Select the net associated with the terminal nearest the cursor. +.TP +\fBright\fR +Find the terminal nearest the cursor, and toggle it into the +current net (if it wasn't already in the current net) or out +of the current net (if it was previously in the net). +.TP +\fBmiddle (bottom) \fR +Find the terminal nearest the cursor, and join its net with +the current net. +.RE +.TP +.B "Rsim Tool" +Used when running the IRSIM simulator under Magic. +A pointing hand is used as the cursor. +.RS +.TP +\fBleft\fR +Moves the box just like the box tool. +.TP +\fBright\fR +Moves the box just like the box tool. +.TP +\fBmiddle (bottom) \fR +Displays the Rsim node values of the selected paint. +.RE +.SH "LONG COMMANDS FOR LAYOUT WINDOWS" +.PP +These commands work if you are pointing to the interior of a layout +window. +Commands are invoked by typing a colon (``:'') or semi-colon (``;''), +followed by a line containing a command name and zero or more parameters. +In addition, macros may be used to invoke commands with single +keystrokes. +Useful default macros are set in the global \fB.magicrc\fR file +(in \fB${CAD_ROOT}/magic/sys\fR, normally \fB/usr/local/lib/magic/sys\fR). +You can list all current macros with the \fBmacro\fR +command, described under ``LONG COMMANDS FOR ALL WINDOWS''. +Unique +abbreviations are acceptable for +all keywords in commands. +The commands are: +.TP +.B "addpath \fIsearchpath\fR" +Add more directories to the end of Magic's cell search path. +See the +documentation for the \fBpath\fR command for an explanation of the search +path. +.TP +.B "array \fIxsize ysize\fP" +Make many copies of the selection. +There will be \fIxsize\fR +instances in the x-direction and \fIysize\fR instances in the +y-direction. +Paint and labels are arrayed by copying them. +Subcells are not copied, but instead each instance is turned into +an array instance with elements +numbered from 0 to \fIxsize\fR-1 in the x-direction, and +from 0 to \fIysize\fR-1 in the y-direction. +The spacing between elements of the array is determined by the box +x- and y-dimensions. +.TP +.B "array \fIxlo ylo xhi yhi\fP" +Identical to the form of \fBarray\fR above, except that the elements +of arrayed cells are numbered left-to-right +from \fIxlo\fR to \fIxhi\fR +and bottom-to-top from \fIylo\fR to \fIyhi\fR. +It is legal for \fIxlo\fR to be greater than \fIxhi\fR, and +also for \fIylo\fR to be greater than \fIyhi\fR. +.TP +.B "box \fR[\fIargs\fR]" +Used to change the size of the box or to find out its size. +There are +several sorts of arguments that may be given to this command: +.RS +.TP +.I (No arguments.) +Show the box size and its location in the edit cell, +or root cell of its window if the edit cell isn't in that window. +.TP +\fIdirection\fR [\fIdistance\fR] +Move the box +.I distance +units in \fIdirection\fR, +which may be one of \fBleft\fR, \fBright\fR, \fBup\fR, or \fBdown\fR. +\fIDistance\fR defaults to the width of the box if \fIdirection\fP +is \fBright\fP or \fBleft\fP, and to the height of the box +if \fIdirection\fP is \fBup\fP or \fBdown\fP. +.TP +\fBwidth [\fIsize\fR] +.TP +\fBheight [\fIsize\fR] +Set the box to the width or height indicated. +If \fIsize\fR is not +specified the width or height is reported. +.TP +\fIx1 y1 x2 y2\fR +Move the box to the coordinates specified (these are in edit cell coordinates +if the edit cell is in the window under the cursor; otherwise these +are in the root coordinates of the window). \fIx1\fR +and \fIy1\fR are the coordinates of the lower left corner of the box, +while \fIx2\fR and \fIy2\fR are the upper right corner. +The coordinates +must all be integers. +.RE +.TP +\fBcalma \fR[\fIoption\fR] [\fIargs\fR] +This command is used to read and write files in Calma GDS II Stream format +(version 3.0, corresponding to GDS II Release 5.1). +This format is like CIF, in that it describes physical mask layers +instead of Magic layers. +In fact, the technology file specifies a correspondence +between CIF and Calma layers. +The current CIF output style (see \fBcif\ ostyle\fR) controls +how Calma stream layers are generated from Magic layers. +If no arguments are given, +the \fBcalma\fR command generates a Calma stream +file for the layout in the window +beneath the cursor in \fIfile\fB.strm\fR, where \fIfile\fR is the +name of the root cell. +This stream file describes the entire cell hierarchy in the window. +The name of the library is the same as the name of the root cell. +\fIOption\fR and \fIargs\fR may be used +to invoke one of several additional operations: +.RS +.TP +\fBcalma flatten\fR +Ordinarily, Magic arrays are output using the Calma ARRAY construct. +After a \fBcalma flatten\fR command, though, arrays will be output +instead as a collection of individual cell uses, as occurs when writing CIF. +.TP +\fBcalma help\fR +Print a short synopsis of all of the \fBcalma\fR command options. +.TP +\fBcalma labels\fR +Output labels whenever writing a Calma output file. +.TP +\fBcalma lower\fR +Allow both upper and lower case to be output for label text. +This is the default behavior; \fBcalma nolower\fR causes lower case +to be converted to upper case on output. +.TP +\fBcalma noflatten\fR +Undoes the effect of a prior \fB:calma flatten\fR command, +re-enabling the output of Magic arrays using the Calma ARRAY +construct. +.TP +\fBcalma nolabels\fR +Don't output labels when writing a Calma output file. +.TP +\fBcalma nolower\fR +Convert lower to upper case when outputting labels. +.TP +\fBcalma read \fIfile\fR +The file \fIfile\fR.\fBstrm\fR is read in Calma format and converted to +a collection of Magic cells. +The current CIF input style determines +how the Calma layers are converted to Magic layers. +The new cells are marked for design-rule checking. +Calma format doesn't identify the root of the collection +of cells read in, so none of the cells read will appear on the display; +use \fBload\fR to make them visible. +If the Calma file had been produced by Magic, then the name of the +root cell is the same as the library name printed by the \fB:calma read\fR +command. +.TP +\fBcalma write \fIfileName\fR +Writes a stream file just as if no arguments had been entered, except that +the output is written into \fIfileName\fB.strm\fR instead of using the +root cell name for the file name. +.RE +.TP +\fBchannels\fR +This command will run just the channel decomposition part of the +Magic router, deriving channels for the area under the box. +The channels +will be displayed as outlined feedback areas over the edit cell. +.TP +\fBcif \fR[\fIoption\fR] [\fIargs\fR] +Read or write files in Caltech +Intermediate Form (CIF). +If no arguments +are given, this command generates a CIF file for the window +beneath the cursor in \fIfile\fB.cif\fR, where \fIfile\fR is the +name of the root cell. +The CIF file describes the entire cell +hierarchy in the window. +\fIOption\fR and \fIargs\fR may be used +to invoke one of several additional CIF operations: +.RS +.TP +\fBcif arealabels \fR[\fByes \fR|\fB no]\fR +Enables/disables the cif area-label extension. +If enabled, area +labels are written via the \fB95\fR cif extension. +If disabled, labels +are collapsed to points when writing cif and the \fB94\fR cif +construct is used. +Area-labels are disabled by default (many programs +don't understand cif area-labels). +.TP +\fBcif help\fR +Print a short synopsis of all of the cif command options. +.TP +\fBcif istyle \fR[\fIstyle\fR] +Select the style to be used for CIF input. +If no \fIstyle\fR +argument is provided, then Magic prints the names of all CIF +input styles defined in the technology file and identifies +the current style. +If \fIstyle\fR is provided, it is made +the current style. +.TP +\fBcif ostyle \fR[\fIstyle\fR] +Select the style to be used for CIF output. +If no \fIstyle\fR +argument is provided, then Magic prints the names of all CIF +output styles defined in the technology file and identifies +the current style. +If \fIstyle\fR is provided, it is made +the current style. +.TP +\fBcif read \fIfile\fR +The file \fIfile\fR.\fBcif\fR is read in CIF format and converted to +a collection of Magic cells. +The current input style determines +how the CIF layers are converted to Magic layers. +The new cells are +marked for design-rule checking. +Any information in the top-level +CIF cell is copied into the edit cell. +Note: this command is not +undo-able (it would waste too much space and time to save information +for undoing). +.TP +\fBcif see \fIlayer\fR +In this command \fIlayer\fR must be the CIF name for a layer in the +current output style. +Magic will display on the screen all the CIF +for that layer that falls under the box, using stippled feedback +areas. +It's a bad +idea to look at CIF over a large area, +since this command requires +the area under the box to be flattened and +therefore is slow. +.TP +\fBcif statistics\fR +Prints out statistics gathered by the CIF generator as it operates. +This is probably not useful to anyone except system maintainers. +.TP +\fBcif write \fIfileName\fR +Writes out CIF just as if no arguments had been entered, except that +the CIF is written into \fIfileName\fB.cif\fR instead of using the +root cell name for the file name. +The current output style controls +how CIF layers are generated from Magic layers. +.TP +\fBcif flat \fIfileName\fR +Writes out CIF as in the \fBcif write\fR command, but flattens the +design first (e.g. creates an internal version with the cell hierarchy +removed). +This +is useful if one wishes to use the \fBand-not\fR +feature of the CIF output styles, but is having problems with interactions +of overlapping cells. +.RE +.TP +\fBclockwise \fR[\fIdegrees\fR] +Rotate the selection by \fB90\fR, \fB180\fR or \fB270\fR degrees. +After the rotation, the lower-left +corner of the selection's bounding box will be in the same place +as the lower-left corner of the bounding box before the rotation. +\fIDegrees\fR defaults to \fB90\fR. +If the box +is in the same window as the selection, it is rotated too. +Only +material in the edit cell is affected. +.TP +.B "copy \fR[\fIdirection \fR[\fIamount\fR]]" +.TP +.B "copy to \fIx y\fR" +If no arguments are given, a copy of the selection is picking up +at the point lying underneath the box lower-left +corner, and placed so that this point lies at the cursor +position. +If \fIdirection\fR is given, +it must be a Manhattan direction (e.g. \fBnorth\fR, see the ``DIRECTIONS'' +section below). +The copy of the +selection is moved in that direction by \fIamount\fR. +If the +box is in the same window as the selection, it is moved too. +\fIAmount\fR defaults to \fB1\fR. +The second form of the command behaves as though the cursor +were pointing to (\fIx,\ y\fR) in the edit cell; a copy of the selection +is picked up by the point beneath the lower-left corner of +the box and placed so that this point lies at (\fIx\fR,\fI\ y\fR). +.TP +.B "corner \fIdirection1 direction2 \fR[layers\fR]" +This command is similar to \fBfill\fR, except that it generates L-shaped +wires that travel across the box first in +\fIdirection1\fR and then in \fIdirection2\fR. +For example, \fBcorner north east\fR finds all paint under the +bottom edge of the box and extends it up to the top of the box and +then across to the right side of the box, generating neat corners at +the top of the box. +The box should be at least as tall as it is wide +for this command to work correctly. +\fIDirection1\fR and \fIdirection2\fR must be +Manhattan directions (see the section DIRECTIONS below) and must +be orthogonal to each other. +If \fIlayers\fR is specified then only +those layers are used; otherwise all layers are considered. +.TP +.B "delete" +Delete all the information in the current selection that is in +the edit cell. +When cells are deleted, only the selected use(s) of the +cell is (are) deleted: other uses of the cell remain intact, as does +the disk file containing the cell. +Selected material outside the edit cell is not deleted. +.TP +\fBdrc option \fR[\fIargs\fR] +This command is used to interact with the design rule checker. +\fIOption\fR and \fIargs\fR (if needed) are used to invoke a \fBdrc\fR command +in one of the following ways: +.RS +.TP +\fBdrc catchup\fR +Let the checker process all the areas that need rechecking. +This +command will not return until design-rule checking is complete or +an interrupt is typed. +The checker will run even if the background +checker has been disabled with \fBdrc off\fR. +.TP +\fBdrc check\fR +Mark the area under the box for rechecking in all cells that intersect +the box. +The recheck will occur in background after the command +completes. +This command is not normally necessary, since Magic +automatically remembers which areas need to be rechecked. +It +should only be needed if the design rules are changed. +.TP +\fBdrc count\fR +Print the number of errors in each cell under the box. +Cells with no errors are skipped. +.TP +\fBdrc find\fR [\fInth\fR] +Place the box over the \fInth\fR error area in the selected cell +or edit cell, and +print out information about the error just as if \fBdrc why\fR +had been typed. +If \fInth\fR isn't given (or is less than 1), +the command moves to the next error area. +Successive invocations of \fBdrc find\fR +cycle through all the error tiles in the cell. +If multiple cells are selected, this command uses the upper-leftmost one. +If no cells are selected, this command uses the edit cell. +.TP +\fBdrc help\fR +Print a short synopsis of all the drc command options. +.TP +\fBdrc off\fR +Turn off the background checker. +From now on, Magic will not +recheck design rules immediately after each command (but it +will record the areas that need to be rechecked; the command +\fBdrc on\fR can be used to restart the checker). +.TP +\fBdrc on\fR +Turn on the background checker. +The checker will check whatever modifications +have not already been checked. +From now on, the checker will reverify +modified areas as they result from commands. +The checker is run +in the background, not synchronously with commands, so it may get +temporarily behind if massive changes are made. +.TP +\fBdrc printrules \fR[\fIfile\fR] +Print out the compiled rule set in \fIfile\fR, or on the text +terminal if \fIfile\fR isn't given. +For system maintenance only. +.TP +\fBdrc rulestats\fR +Print out summary statistics about the compiled rule set. +This +is primarily for use in writing technology files. +.TP +\fBdrc statistics\fR +Print out statistics kept by the design-rule checker. +For each +statistic, two values are printed: the count since the last time +\fBdrc statistics\fR was invoked, and the total count in this +editing session. +This command is intended primarily for system +maintenance purposes. +.TP +\fBdrc why\fR +Recheck the area underneath the box and print out the reason +for each violation found. +Since this command causes a recheck, +the box should normally be placed around a small area (such as +an error area). +.RE +.TP +.B "dump \fIcellName \fR[\fBchild\fI refPointC\fR] [\fBparent\fI refPointP\fR]" +Copy the contents of cell \fIcellName\fR into the edit cell +so that \fIrefPointC\fR in the child is positioned at point \fIrefPointP\fR +in the edit cell. +The reference points can either be the name of a label, +in which case the lower-left corner of the label's box is used as the reference +point, +or as a pair of numbers giving the (\fIx\fR,\ \fIy\fR) coordinates of a point +explicitly. +If \fIrefPointC\fR is not specified, the lower-left corner of \fIcellName\fR +cell is used. +If \fIrefPointP\fR is not specified, the lower-left corner of the box +tool is used (the box must be in a window on the edit cell). +After this command completes, the new information is selected. +.TP +.B "edit" +Make the selected cell the edit cell, and edit it in context. +The +edit cell is normally displayed in brighter colors than other cells +(see the \fBsee\fR command to change this). +If +more than one cell is selected, +or if the selected cell is an array, the cursor +position is used to select one of those cells as the new +edit cell. +Generally, Magic commands modify only the current edit cell. +.TP +.B "erase \fR[\fIlayers\fR]" +For the area enclosed by the box, erase all paint in \fIlayers\fR. +(See the ``LAYERS'' section for the syntax of layer lists). +If +\fIlayers\fR is omitted it defaults to \fB*,labels\fR. +See your +technology manual, or use the \fBlayers\fR command, to find out about +the available layer names. +.TP +.B "expand \fR[\fBtoggle\fR]" +If the keyword \fBtoggle\fR is supplied, all of the selected cells +that are unexpanded are expanded, and all of the selected cells +that are expanded are unexpanded. +If \fBtoggle\fR isn't specified, +then all of the cells underneath +the box are expanded recursively until +there is nothing but paint under the box. +.TP +\fBextract \fIoption\fR [\fIargs\fR] +Extract a layout, producing one or +more hierarchical \fB.ext\fP files that describe the electrical circuit +implemented by the layout. +The current extraction style (see \fBextract style\fR below) determines +the parameters for parasitic resistance, capacitance, etc. that +will be used. +The \fBextract\fP command with no +parameters +checks timestamps and re-extracts as needed to bring +all \fB.ext\fR files up-to-date for the cell in the +window beneath the crosshair, and all cells beneath it. +Magic displays any errors encountered during circuit +extraction using stippled feedback areas over the area of +the error, along with a message describing the type of error. +Option\fR and \fIargs\fR are used in the following ways: +.RS +.TP +\fBextract all\fR +All cells in the window beneath the cursor +are re-extracted regardless of whether they +have changed since last being extracted. +.TP +\fBextract cell \fIname\fR +Extract only the currently selected cell, placing the output +in the file \fIname\fP. +If more than one cell is selected, +this command uses the upper-leftmost one. +.TP +\fBextract do \fR[ \fIoption\fR ] +.TP +\fBextract no \fIoption\fR +Enable or disable various options governing how the extractor +will work. +Use \fB:extract do\fR with no arguments to print +a list of available options and their current settings. +When the \fBadjust\fR option is enabled, the extractor will +compute compensating capacitance and resistance whenever cells +overlap or abut; if disabled, the extractor will not compute +these adjustments but will run faster. +If \fBcapacitance\fR is enabled, node capacitances to substrate +(perimeter and area) are computed; otherwise, all node capacitances +are set to zero. +Similarly, \fBresistance\fR governs whether or +not node resistances are computed. +The \fBcoupling\fR option controls whether coupling capacitances +are computed or not; if disabled, flat extraction is significantly +faster than if coupling capacitance computation is enabled. +Finally, the \fBlength\fR option determines whether or not pathlengths +in the root cell are computed (see \fBextract length\fR below). +.TP +\fBextract help\fR +Prints a short synopsis of all the \fBextract\fR command options. +.TP +\fBextract length\fR [ \fIoption args\fR ] +Provides several options for controlling which point-to-point path lengths +are extracted explicitly. +The extractor maintains two internal tables, one of \fIdrivers\fR, or +places where a signal is generated, and one of \fIreceivers\fR, or +places where a signal is sent. +The components of each table are hierarchical label names, defined +by means of the two commands \fBextract length driver \fIname1 \fR[\fIname2 ...\fR] +and \fBextract length receiver \fIname1 \fR[\fIname2 ...\fR]. +If extraction of pathlengths is enabled (``\fB:extract do length\fR''), +then when the root cell +in an extract command is being extracted, the extractor will +compute the shortest and longest path between each driver and +each receiver on the same electrical net, and output it to the \fB.ext\fR file +for the root cell. +Normally, one should create a file of these Magic commands for the circuit +drivers and receivers of interest, and use \fBsource\fR to read it in prior +to circuit extraction. +\fBExtract length clear\fR removes all the entries from +both the driver and receiver tables. +.TP +\fBextract parents\fR +Extract the currently selected cell and all of its parents. +All of its parents must be loaded in order for +this to work correctly. +If more than one cell is selected, +this command uses the upper-leftmost one. +.TP +\fBextract showparents\fR +Like \fBextract parents\fP, but only print the cells that would +be extracted; don't actually extract them. +.TP +\fBextract style \fR[\fIstyle\fR] +Select the style to be used for extraction parameters. +If no \fIstyle\fR +argument is provided, then Magic prints the names of all extraction +parameter styles defined in the technology file and identifies +the current style. +If \fIstyle\fR is provided, it is made +the current style. +.TP +\fBextract unique \fR[\fB#\fR] +For each cell in the window beneath the cursor, check to insure +that no label is attached to more than one node. +If the \fB#\fR +keyword was not specified, whenever a label is attached to more than +one node, the labels in all but one of the nodes are changed by +appending a numeric suffix to make them unique. +If the \fB#\fR keyword is specified, only names that +end in a ``\fB#\fR'' are made unique; +any other duplicate nodenames that don't end in a ``\fB!\fR'' +are reported by leaving a warning feedback area. +This command is provided for converting old designs that +were intended for extraction with Mextra, which would +automatically append unique suffixes to node names +when they appeared more than once. +.TP +\fBextract warn\fR [ [\fBno\fR] \fIoption\fR | [\fBno\fR] \fBall\fR ] +The extractor always reports fatal errors. +This command controls +the types of warnings that are reported. +\fIOption\fR may be one +of the following: \fBdup\fR, to warn about two or more unconnected +nodes in the same cell that have the same name, \fBfets\fR, to warn +about transistors with fewer than the minimum number of terminals, +and \fBlabels\fR, to warn when nodes are not labeled in the area of +cell overlap. +In addition, \fBall\fR may be used to refer to all warnings. +If a warning is preceded by \fBno\fR, it is disabled. +To disable all warnings, use ``\fBextract warn no all\fR''. +To see +which warning options are in effect, use ``\fBextract warn\fR''. +.RE +.TP +\fBextresist [\fIcell\fR [\fIthreshold\fR] ] +Postprocessor for improving on the resistance calculation performed by +the circuit extractor. +To use this command, you first have to extract +the design rooted at \fIcell\fR with \fB:extract\ \fIcell\fR, and then +flatten the design using \fIext2sim\fR\|(1), producing the files +\fIcell\fB.sim\fR and \fIcell\fB.nodes\fR. +Then run +\fB:extresist\fI\ cell\fR to produce a file, \fIcell\fB.res.ext\fR, +containing differences +between the network described by the \fB.ext\fR files produced the +first time around, and a new network that incorporates explicit +two-point resistors where appropriate (see below). +This file may be appended to \fIcell\fB.ext\fR, and then \fIext2sim\fR\ +run for a second time, to produce a new network with explicit resistors. +The \fIthreshold\fR parameter is used to control which nodes are turned +into resistor networks: any node whose total resistance exceeds +\fIthreshold\fR times the smallest on-resistance of any transistor +connected to that node will be approximated as a resistor network. +.TP +\fBfeedback \fIoption\fR [\fIargs\fR] +Examine feedback information that is +created by several of the Magic commands to report problems +or highlight certain things for users. +\fIOption\fR and +\fIargs\fR are used in the following ways: +.RS +.TP +\fBfeedback add \fItext\fR [\fIstyle\fR] +Used to create a feedback area manually at the location of the box. +This is intended as a way for other programs like Crystal to +highlight things on a layout. +They can generate +a command file consisting of a \fBfeedback clear\fR command, and a +sequence of \fBbox\fR and \fBfeedback add\fR commands. +\fIText\fR +is associated with the feedback (it will be printed by \fBfeedback why\fR +and \fBfeedback find\fR). +\fIStyle\fR tells how to display the feedback, +and is one of \fBdotted\fR, \fBmedium\fR, \fBoutline\fR, \fBpale\fR, and +\fBsolid\fR (if unspecified, \fIstyle\fR defaults to \fBpale\fR). +.TP +\fBfeedback clear\fR +Clears all existing feedback information from the screen. +.TP +\fBfeedback count\fR +Prints out a count of the current number of feedback areas. +.TP +\fBfeedback find \fR[\fInth\fR] +Used to locate a particular feedback area. +If \fInth\fR is +specified, the box is moved to the location of the \fInth\fR +feedback area. +If \fInth\fR isn't specified, then the box +is moved to the next sequential feedback area after the last +one located with \fBfeedback find\fR. +In either event, the +explanation associated with the feedback area is printed. +.TP +\fBfeedback help\fR +Prints a short synopsis of all the \fBfeedback\fR command options. +.TP +\fBfeedback save \fIfile\fR +This option will save information about all existing feedback areas +in \fIfile\fR. +The information is stored as a collection of Magic +commands, so that it can be recovered with the command +\fBsource \fIfile\fR. +.TP +\fBfeedback why\fR +Prints out the explanations associated with all feedback areas +underneath the box. +.RE +.TP +.B "fill \fIdirection\fR [\fIlayers\fR]" +\fIDirection\fR is a Manhattan direction (see the section DIRECTIONS +below). +The paint visible under one edge of the box is sampled. +Everywhere that the edge touches paint, the paint is extended +in the given direction to the opposite side of the box. +For example, +if \fIdirection\fR is \fBnorth\fR, then paint is sampled under the +bottom edge of the box and extended to the top edge. +If \fIlayers\fR is specified, then only the given layers +are considered; if \fIlayers\fR isn't specified, then all layers +are considered. +.TP +.B "findbox \fR[\fBzoom\fR]" +Center the view on the box. +If the optional \fBzoom\fR argument is present, zoom into the area specified +by the box. +This command will complain if the box is not in the window +you are pointing to. +.TP +.B "flush \fR[\fIcellname\fR]" +Cell \fIcellname\fR is reloaded from disk. +All changes +made to the cell since it was last saved are discarded. +If \fIcellname\fR is not given, the edit cell is flushed. +.TP +\fBgaroute \fIoption\fR [\fIargs\fR] +This command, with no \fIoption\fR or \fIarg\fR, +is like the \fBroute\fR command: it generates routing in the +edit cell to make connections specified in the current netlist. +(See the \fBroute\fR command for further information). +Unlike the \fBroute\fR command, this command is intended to be +used for routing types of circuits, such as gate-arrays, whose +routing channels can be determined in advance, and which require +the ability to river-route across the tops of cells. +The channels must have been predefined using \fBgaroute\ channel\fR +commands prior to this command being invoked. +Unlike the \fBroute\fR +command, where the box indicates the routing area, this command +ignores the box entirely. +The new wires are placed in the edit cell. +The netlist used is that selected by the \fBroute netlist\fR +command, or the current netlist being edited in a \fBnetlist\fR +window if no \fBroute netlist\fR command has been given. +\fIOptions\fR and \fIargs\fR have the following effects: +.RS +.TP +\fBgaroute channel \fR[\fItype\fR] +.TP +\fBgaroute channel \fIxlo ylo xhi yhi \fR[\fItype]\fR +Define a channel. +If \fIxlo\fR, \fIylo\fR, \fIxhi\fR, and \fIyhi\fR +are provided, they are interpreted as the coordinates of the lower-left +and upper-right of the bounding box for the channel respectively. +Otherwise, the coordinates of the box are used. +The boundary of each channel is adjusted inward to lie halfway +between routing grid lines if it does not lie there already; +if the channel is adjusted, a warning message is printed. +The channel defined is an ordinary routing channel if \fItype\fR is +not specified; such channels are identical to those used by the +router of the \fBroute\fR command. +If \fItype\fR is given, it must +be either \fBh\fR or \fBv\fR. +The channel thereby created will be +a \fIriver-routing\fR channel inside which only left-to-right routes +are possible (``\fBh\fR'') or top-to-bottom (``\fBv\fR''). +Unlike a normal channel, a river-routing channel +may contain terminals in its interior. +.TP +\fBgaroute generate\fI type \fR[\fIfile\fR] +Provides a primitive form of channel decomposition for regular +structures such as gate-array or standard-cell layouts. +Generates a collection of \fBgaroute channel\fR commands, either to +the standard output, or to \fIfile\fR if the latter is specified. +The \fItype\fR parameter must be either \fBh\fR or \fBv\fR. +The entire area contained within the box is turned into routing channels. +Each cell inside this area has its bounding box computed for purposes +of routing by looking only at those layers considered to be ``obstacles'' +to routing (see ``Tutorial #7: Netlists and Routing'' for details). +The bounding box just computed is then extended all the way to the +sides of the area of the box tool, vertically if \fItype\fR is \fBh\fR +or horizontally if \fItype\fR is \fBv\fR. +This extended area is then +marked as belonging to a river-routing channel of type \fItype\fR; +adjacent channels of this type are merged into a single channel. +After all cells are processed, the areas not marked as being +river-routing channels are output as normal channels. +.TP +\fBgaroute help\fR +Print a short synopsis of all the \fBgaroute\fR command options. +.TP +\fBgaroute nowarn\fR +If a given terminal appears in more than one place inside a cell, +the router can leave feedback if it is not possible +to route to all of the places where the terminal appears. +The \fBgaroute nowarn\fR command instructs the router to leave feedback +only if it is not possible to route to \fIany\fR of the locations of +a terminal. +(This is the default behavior of \fBgaroute\fR router). +.TP +\fBgaroute route\fR [\fInetlist\fR] +Route the edit cell. +If \fInetlist\fR is not specified, the netlist used is the same as +when \fBgaroute\fR is given with no options. +If \fInetlist\fR is +given, then it is used instead. +.TP +\fBgaroute reset\fR +Clear all channels defined by \fBgaroute channel\fR in preparation +for redefining a new set of channels. +.TP +\fBgaroute warn\fR +The opposite of \fBgaroute nowarn\fR, this command instructs +the router to leave feedback if it is not possible to route to +all of the places where a terminal appears when a terminal has +more than one location, even if not all of those locations are +actually selected for routing by the global router. +.RE +.TP +.B "getcell \fIcellName \fR[\fBchild\fI refPointC\fR] [\fBparent\fI refPointP\fR]" +This command adds a child cell instance to the edit cell. +The instance refers to the cell \fIcellName\fR; it is positioned +so that \fIrefPointC\fR in the child is at point \fIrefPointP\fR +in the edit cell. +The reference points can either be the name of a label, +in which case the lower-left corner of the label's box is used as the reference +point, +or as a pair of numbers giving the (\fIx\fR,\ \fIy\fR) coordinates of a point +explicitly. +If \fIrefPointC\fR is not specified, the lower-left corner of \fIcellName\fR +cell is used. +If \fIrefPointP\fR is not specified, the lower-left corner of the box +tool is used (the box must be in a window on the edit cell). +The new subcell is selected. +The +difference between this command and \fBdump\fR is that \fBdump\fR copies +the contents of the cell, while \fBgetcell\fR simply makes a reference +to the original cell. +\fICellname\fR must not be the edit cell or +one of its ancestors. +.TP +.B "getnode \fR[\fBalias on\fR | \fBalias off\fR] +.TP +.B "getnode \fR[\fBabort \fR[\fIstr\fR]] +Getnode prints out the node names (used by the extractor) for all selected +paint. +If aliasing turned on, +getnode prints all the names it finds for a given node. +It may not print +every name that exists, however. +When turned off, it just prints one name. +The abort option allows the user to tell getnode that it is not important +to completely search nodes that have certain names. +For example, +\fBgetnode abort Vdd\fR will tell getnode not to continue searching the +node if it determines that one of its names is Vdd. +A \fBgetnode abort\fR, without a string argument, will erase the list of +names previously created by calling \fBgetnode abort\fR with string arguments. +Getnode can be safely aborted at any time by typing the interrupt character, +usually ^C. +See \fITutorial #11: Using IRSIM and RSIM with Magic\fR for more information +on this command. +.TP +.B "grid \fR[\fIxSpacing\fR [\fIySpacing \fR[\fIxOrigin yOrigin\fR]]]" +.TP +.B "grid off" +If no arguments are given, a one-unit grid is toggled on or off in the +window underneath the cursor. +\fBGrid off\fR always turns the grid +off, regardless of whether it was on or off previously. +If numerical arguments are given, +the arguments determine the grid spacing +and origin for the window under the cursor. +In its +most general form, \fBgrid\fR +takes four integer arguments. +\fBXOrigin\fR and \fByOrigin\fR +specify an origin for the grid: horizontal and vertical grid lines +will pass through this point. +\fBXSpacing\fR and \fBySpacing\fR +determine the number of units between adjacent grid lines. +If \fBxOrigin\fR +and \fByOrigin\fR are omitted, they default to 0. +If \fBySpacing\fR +is also omitted, the xSpacing value is used for both spacings. +Grid parameters will be retained for +a window until explicitly changed by another \fIgrid\fR +command. +When the grid is displayed, a solid box is drawn to +show the origin of the edit cell. +.TP +.B "identify \fIinstance_id" +Set the instance identifier of the selected cell use to +\fIinstance_id\fR. +\fIInstance_id\fR must be unique among +all instance identifiers in the parent of the selected cell. +Initially, Magic guarantees uniqueness of identifiers by +giving each cell an initial identifier consisting of the cell +definition name followed by an underscore and a small integer. +.TP +.B "iroute \fIsubcommand\fR [\fIargs\fR]" +This command provides an interactive interface to the Magic +maze-router. +Routing +is done one connection at a time. +Three internal \fIhint\fR layers, +\fBmagnet\fR, \fBfence\fR, and \fBrotate\fR, allow the user to guide routing +graphically. +Routes are chosen close to magnets (if possible), routing +does not cross fence boundaries, and rotate areas reverse the +preferred routing directions for each layer. +The maze-router +seeks to find a lowest-cost path. +Parameters +specifying costs for horizontal and vertical routing on +each layer, cost for jogs and contacts, and cost (per unit area) for distance +between a path and magnets, help determine the nature of +the routes. +Several \fIsearch\fR parameters permit tuning +to achieve acceptable +routes in as short a time as possible. +Routing can +always be interrupted with \fB^C\fR. +The iroute subcommands are +as follows: +.RS +.TP +\fBiroute\fR +Routes from cursor to inside box. +.TP +\fBiroute contact \fR[\fItype\fR] [\fIparameter\fR] [\fIvalue1\fR] ... [\fIvaluen\fR] +An asterisk, \fB*\fR, can be used for \fItype\fR and \fIparameter\fR. +This command is for setting and examining parameters related to contacts. +.TP +\fBiroute help \fR[\fIsubcommand\fR] +Summarizes irouter commands. +If a \fIsubcommand\fR is given, usage +information for that subcommand is printed. +.TP +\fBiroute layers \fR[\fItype\fR] [\fIparameter\fR] [\fIvalue1\fR] ... [\fIvaluen\fR] +An asterisk, \fB*\fR, can be used for \fItype\fR and \fIparameter\fR. +This command is for setting and examining parameters related to route layers. +.TP +\fBiroute route \fR[\fIoptions\fR] +Invokes the router. +Options are as follows: +.in +5 +.nf +\fB-sLayers\fI layers\fR = layers route may start on +\fB-sCursor\fR = start route at cursor (DEFAULT) +\fB-sLabel \fIname\fR = start route at label of given name +\fB-sPoint \fIx y\fR = start route at given coordinates +\fB-dLayers\fI layers\fR = layers route may end on +\fB-dBox\fR = route to box (DEFAULT) +\fB-dLabel\fI name\fR = route to label of given name +\fB-dRect\fI xbot ybot xtop ytop\fR = route to rectangle of given coordinates +\fB-dSelection\fI = route to selection +.in -5 +.fi +.TP +\fBiroute saveParameters \fR<\fIfilename\fR> +Saves all current irouter parameter settings. +The parameters can be restored +to these values with the command ``\fBsource \fIfilename\fR''. +.TP +\fBiroute search \fR[\fIsearchParameter\fR] [\fIvalue\fR] +Allows parameters controlling the search to be modified. +If routing is too +slow try increasing \fBrate\fR. +If the router is producing bad results, try +reducing \fBrate\fR. +Its a good idea to make \fBwidth\fR at least twice as +big as \fBrate\fR. +.TP +\fBiroute spacings \fR[\fIroute-type\fR] [\fItype\fR] [\fIspacing\fR] ... [\fItypen spacingn\fR] +Default minimum spacings between a route-type placed by the router and other +types are derived from the \fBdrc\fR section of the technology file. +The +defaults can be overridden by this command. +The special type \fBSUBCELL\fR +is used to specify minimum spacing to unexpanded subcells. +.TP +\fBiroute verbosity \fR[\fIlevel\fR] +Controls the number of messages printed during routing: +.in +5 +.nf +\fB0\fR = errors and warnings only, +\fB1\fR = brief, +\fB2\fR = lots of statistics. +.in -5 +.fi +.TP +\fBiroute version\fR +Prints irouter version information. +.TP +\fBiroute wizard \fR[\fIwizardparameter\fR] [\fIvalue\fR] +Used to examine and set miscellaneous parameters. +Most of these are best +left alone by the unadventurous user. +.RE +.TP +.B "label \fIstring \fR[\fIpos \fR[\fIlayer\fR]]" +A label with text \fIstring\fR +is positioned at the box location. +Labels may cover points, lines, or areas, and are associated +with specific layers. +Normally the +box is collapsed to either a point or to a line (when labeling +terminals on the edges of cells). +Normally also, the area under +the box is occupied by a single layer. +If no \fIlayer\fR argument is specified, then the label is attached to +the layer under the box, or space if no layer covers the entire +area of the box. +If \fIlayer\fR is specified but \fIlayer\fR +doesn't cover the entire area of the box, the label will be +moved to another layer or space. +Labels attached to space will be considered by CIF processing +programs to be attached to all layers overlapping the area +of the label. +\fIPos\fR is optional, and specifies where the label text is to be +displayed relative to the box (e.g. ``north''). +If \fIpos\fR isn't given, Magic will pick a position to +ensure that the label text doesn't stick out past the edge of the +cell. +.TP +.B "layers" +Prints out the names of all the layers defined for the +current technology. +.TP +.B "load \fR[\fIfile\fR]" +Load the cell hierarchy rooted at \fIfile\fB.mag\fR into the window +underneath the cursor. +If no \fIfile\fR +is supplied, a new unnamed cell is created. +The root cell of the hierarchy is made the edit cell unless there is +already an edit cell in a different window. +.TP +.B "move \fR[\fIdirection \fR[\fIamount\fR]]" +.TP +.B "move to \fIx y\fR" +If no arguments are given, the selection is picked up by the +point underneath the lower-left corner of the box and moved +so that this point lies at the cursor location. +If \fIdirection\fR is given, +it must be a Manhattan direction (e.g. \fBnorth\fR). +The +selection is moved in that direction by \fIamount\fR. +If the +box is in the same window as the selection, it is moved too. +\fIAmount\fR defaults to 1. +Selected material that is not +in the edit cell, is not affected. +The +second form of the command is as though the cursor +were pointing to (\fIx,\ y\fR) in the edit cell; the selection +is picked up by the point beneath the lower-left corner of +the box and moved so that this point lies at (\fIx\fR,\fI\ y\fR). +.TP +.B "paint \fIlayers" +The area underneath the box is painted in \fIlayers\fR. +.TP +.B "path \fR[\fIsearchpath\fR]" +This command tells Magic where to look for cells. +\fISearchpath\fR +contains a list of directories separated by colons or spaces (if +spaces are used, then \fIsearchpath\fR must be surrounded by +quotes). +When looking for a cell, Magic will check each directory in +the path in order, until the cell is found. +If the cell is not +found anywhere in the path, Magic will look in the system library +for it. +If the \fIpath\fR command is invoked with no arguments, +the current search path is printed. +.TP +.B "plot \fIoption\fR [\fIargs\fR]" +Used to generate hardcopy plots direct from Magic. +\fIOptions\fR +and \fIargs\fR are used in the following ways: +.RS +.TP +\fBplot gremlin \fIfile\fR [\fIlayers\fR] +Generate a Gremlin-format description of everything under the +box, and write the description in \fIfile\fR. +If \fIlayers\fR +isn't specified, paint, labels, and unexpanded subcells are +all included in the Gremlin file just as they appear on the +screen. +If \fIlayers\fR is specified, then just the indicated layers +are output in the Gremlin file. +\fILayers\fR may include the +special layers \fBlabels\fR and \fBsubcell\fR. +The Gremlin +file is scaled to have a total size between 256 and 512 units; +you should use the \fBwidth\fR and/or \fBheight\fR Grn commands +to ensure that the printed version is the size you want. +Use +the \fBmg\fR stipples in Grn. +No plot parameters are +used in Gremlin plotting. +.TP +\fBplot help\fR +Print a short synopsis of all the \fBplot\fR command options. +.TP +\fBplot parameters [\fIname value\fR] +If \fBplot parameters\fR is invoked with no additional arguments, the values +for all of the plot parameters are printed. +If \fIname\fR and +\fIvalue\fR are provided, then \fIname\fR is the name of a plot +parameter and \fIvalue\fR is a new value for it. +Plot parameters +are used to control various aspects of plotting; all of them have +``reasonable'' initial values. +Most of the parameters available +now are used to control Versatec-style plotting. +They are: +.RS +.TP +\fBcellIdFont\fR +The name of the font to use for cell instance ids in Versatec plots. +This must be a file in Vfont format. +.TP +\fBcellNameFont\fR +The name of the font to use for cell names in Versatec plots. +This must be a file in Vfont format. +.TP +\fBcolor\fR +If this is set to \fBtrue\fR, the \fB:plot versatec\fR command will +generate output suitable for a four-color Versatec plotter, using +the styles defined in the \fBcolorversatec\fR style of the \fBplot\fR +section of the technology file. +If \fBcolor\fR is \fBfalse\fR (the default), then \fB:plot versatec\fR +generates normal black-and-white plots. +.TP +\fBdirectory\fR +The name of the directory in which to create raster files for +the Versatec. +The raster files have names of the form +\fBmagicPlotXXXXXX\fR, where \fBXXXXXX\fR is a process-specific +identifier. +.TP +\fBdotsPerInch\fR +Indicates how many dots per inch there are on the Versatec printer. +This parameter is used only for computing the scale factor for plotting. +Must be an integer greater than zero. +.TP +\fBlabelFont\fR +The name of the font to use for labels in Versatec plots. +This must be a file in Vfont format. +.TP +\fBprinter\fR +The name of the printer to which to spool Versatec raster files. +.TP +\fBshowcellnames\fR +If ``true'' (the default) then the name and instance-identifier of +each unexpanded subcell is displayed inside its bounding box. +If +this parameter is ``false'' then only the bounding box of the cell +is displayed. +.TP +\fBspoolCommand\fR +The command used to spool Versatec raster files. +This must be +a text string containing two ``%s'' formatting fields. +The first +``%s'' will be replaced with the printer name, and the second one +will be replaced with the name of the raster file. +.TP +\fBswathHeight\fR +How many raster lines of Versatec output to generate in memory at one time. +The raster file is generated in swaths in order to keep the memory +requirements reasonable. +This parameter determines the size of +the swaths. +It must be an integer greater than zero, and should +be a multiple of 16 in order to avoid misalignment of stipple patterns. +.TP +\fBwidth\fR +The number of pixels across the Versatec printer. +Must be an integer +greater than 0, and must be an even multiple of 32. +.RE +.TP +\fBplot versatec \fR[\fIsize\fR [\fIlayers\fR]] +Generate a raster file describing all the the information underneath the +box in a format suitable for printing on Versatec black-and-white +or color printers, and spool the file for printing. +See the plot parameters +above for information about the parameters that are used to control +Versatec plotting. \fISize\fR is used to scale the plot: a scalefactor +is chosen so that the area of the box is \fIsize\fR inches across on +the printed page. +\fISize\fR defaults to the width of the printer. +\fILayers\fR selects which layers (including labels +and subcells) to plot; it defaults to everything visible on the screen. +.RE +.TP +.B "plow \fIdirection\fR [\fIlayers\fR]" +.TP +.B "plow \fIoption\fR [\fIargs\fR]" +The first form of this command invokes the plowing operation +to stretch and/or compact a cell. +\fIDirection\fR is a Manhattan direction. +\fILayers\fR is an optional collection of mask layers, +which defaults to \fB*\fR. +One of the edges of the box is treated as a plow and dragged to the +opposite edge of the box (e.g. the left edge is used as the plow +when \fBplow right\fR is invoked). +All edges on \fIlayers\fR that +lie in the plow's path are pushed ahead of it, and they push other +edges ahead of them to maintain design rules, connectivity, and +transistor and contact sizes. +Subcells are moved in their +entirety without being modified internally. +Any mask information overlapping a subcell moved by plowing +is also moved by the same amount. +\fIOption\fR and \fIargs\fR are used in the following ways: +.RS +.TP +\fBplow boundary\fR +The box specifies the area that may be modified by plowing. +This area is highlighted with a pale stipple outline. +Subsequent plows are not allowed to modify any area outside that +specified by the box; if they do, the distance the plow moves +is reduced by an amount sufficient to insure that no geometry +outside the boundary gets affected. +.TP +\fBplow help\fR +Prints a short synopsis of all the \fBplow\fR command options. +.TP +\fBplow horizon\fI\ n\fR +.TP +\fBplow horizon\fR +The first form sets the plowing jog horizon to \fIn\fR units. +The second form simply prints the value of the jog horizon. +Every time plowing considers introducing a jog in a piece of +material, it looks up and down that piece of material for a +distance equal to the jog horizon. +If it finds an existing +jog within this distance, it uses it. +Only if no jog is found +within the jog horizon does plowing introduce one of its own. +A jog horizon of zero means that plowing will always introduce +new jogs where needed. +A jog horizon of infinity (\fBplow nojogs\fR) +means that plowing will not introduce any new jogs of its own. +.TP +\fBplow jogs\fR +Re-enable jog insertion with a horizon of 0. +This command +is equivalent to \fBplow horizon 0\fR. +.TP +\fBplow noboundary\fR +Remove any boundary specified with a previous \fBplow boundary\fR +command. +.TP +\fBplow nojogs\fR +Sets the jog horizon to infinity. +This means that plowing will +not introduce any jogs of its own; it will only use existing ones. +.TP +\fBplow nostraighten\fR +Don't straighten jogs automatically after each plow operation. +.TP +\fBplow selection \fR[\fIdirection \fR[\fIdistance\fR]] +Like the \fBmove\fR or \fBstretch\fR commands, this moves all the +material in the selection that belongs to the edit cell. +However, any material not in the selection is pushed out of +its way, just as though each piece of the selection were plowed +individually. +If no arguments are given, the selection is picked up by the +point underneath the lower-left corner of the box and plowed +so that this point lies at the cursor location. +The box is +moved along with the selection. +If \fIdirection\fR is given, +it must be a Manhattan direction (e.g. \fBnorth\fR). +The +selection is moved in that direction by \fIamount\fR. +If the +box is in the same window as the selection, it is moved too. +\fIAmount\fR defaults to 1. +If there is selected material that +isn't in the edit cell, it is ignored (note that this is different +from \fBselect\fR and \fBmove\fR). +If \fIdirection\fR isn't given and the +cursor isn't exactly left, right, up, or down from the box +corner, then Magic first rounds the cursor position off to a +position that is one of those (whichever is closest). +.TP +\fBplow straighten\fR +Straighten jogs automatically after each plow operation. +The effect will be as though the \fBstraighten\fR command were +invoked after each plow operation, with the same direction, +and over the area changed by plowing. +.RE +.TP +\fBresist \fIcell\fR [\fItolerance\fR] +This command is similar to \fBextresist\fR above, but used for extracting +resistance networks for individual nodes. +Only the node underneath the box is processed. +The network for this node is output to the file +\fIcell\fB.res.ext\fR. +See the description for \fBextresist\fR for an explanation of \fItolerance\fR. +.TP +\fBroute \fIoption\fR [\fIargs\fR] +This command, with no \fIoption\fR or \fIarg\fR, +is used to generate routing using the Magic router +in the edit cell to make connections specified +in the current netlist. +The box is used to indicate the routing area: no routing will be +placed outside the area of the box. +The new wires are +placed in the edit cell. +\fIOptions\fR and \fIargs\fR have the following effects: +.RS +.TP +\fBroute end \fR[\fIreal\fR] +Print the value of the channel end constant used by the channel router. +If a value is supplied, the channel end constant is set to that value. +The channel end constant is a dimensionless multiplier used to compute +how far from the end of a channel to begin preparations to make +end connections. +.TP +\fBroute help\fR +Print a short synopsis of all the \fBroute\fR command options. +.TP +\fBroute jog \fR[\fIint\fR] +Print the value of the minimum jog length used by the channel router. +If a value is supplied, the minimum jog length is set to that value. +The channel router makes no vertical jogs shorter than the minimum jog length, +measured in router grid units. +Higher values for this constant may improve the quality of the routing by +removing unnecessary jogs; however, prohibiting short jogs may make some +channels unroutable. +.TP +\fBroute metal\fR +Toggle metal maximization on or off. +The route command routes the +preferred routing layer (termed ``metal'') horizontally and the alternate +routing layer vertically. +By default wires on the alternate routing layer are then converted, as much as +possible, to the preferred layer before being painted into the layout. +Enabling metal maximization improves the quality of the resulting +routing, since the preferred routing layer generally has better electrical +characteristics; however, designers wishing to do hand routing after automatic +routing may find it easier to disable metal maximization and deal with a +layer-per-direction layout. +.TP +\fBroute netlist \fR[\fIfile\fR] +Print the name of the current netlist. +If a file name is specified, it +is opened if possible, and the new netlist is loaded. +This option is +provided primarily as a convenience so you need not open the netlist menu +before routing. +.TP +\fBroute obstacle \fR[\fIreal\fR] +Print the obstacle constant used by the channel router. +If a value is +supplied, set the channel router obstacle constant to that value. +The obstacle constant is a dimensionless multiplier used in deciding how +far in front of an obstacle the channel router should begin jogging nets +out of the way. +Larger values mean that nets will jog out of the way earlier; +however, if nets jog out of the way too early routing area is wasted. +.TP +\fBroute origin \fR[\fIx y\fR] +Print the x- and y-coordinates of the origin of the routing grid. +By default, the routing grid starts from (0,0). +However, by supplying +an \fIx\fR and \fIy\fR coordinate to the \fBroute origin\fR command, +the origin can be set to any other value. +This command is primarily +useful when routing a chip that has been designed with routing on +the same pitch as the router will use, but where the left and bottom +edges of the pre-existing routing don't line up with the routing grid +lines (for example, the pre-existing routing might have been centered +on routing grid lines). +The alternative to specifying a different +origin for the routing grid would be to translate all the material +in the cell to be routed so that the prewiring lined up properly with +routing grid lines. +.TP +\fBroute settings\fR +Print the values of all router parameters. +.TP +\fBroute steady \fR[\fIint\fR] +Print the value of the channel router's steady net constant. +If a value +is supplied, set the steady net constant to the value. +The steady net constant, measured in router grid units, +specifies how far beyond the next terminal the +channel router should look for a conflicting terminal before deciding that +a net is rising or falling. +Larger values mean that the net rises and falls +less often. +.TP +\fBroute tech\fR +Print the router technology information. +This includes information such as +the names of the preferred and alternate routing layers, their wire widths, +the router grid spacing, and the contact size. +.TP +\fBroute viamin\fR +Minimize vias in (previously) routed netlist. +This subcommand +removes unnecessary layer +changes in all nets in the current netlist to minimize via count. +The +preferred routing layer, \fBlayer1\fR in the \fBrouter\fR section +of the technology file, is favored by the algorithm. +Note that +``\fBroute viamin\fR'' is +an independent routing postpass that can be applied even if the routing +was not generated by the \fBroute\fR command, provided the +layers +and widths agree with the \fBrouter\fR section +of the technology file. +.TP +\fBroute vias \fR[\fIint\fR] +Print the value of the metal maximization via constant. +If a value +is supplied, set the via constant to the value. +The via constant, measured in router grid units, represents the tradeoff +between metal maximization and +the via count. +In many cases it is possible to convert wiring on the +alternate routing layer into routing on the preferred routing layer (``metal'') +at the expense of introducing one or two vias. +The via constant specifies the amount of converted wiring that makes it +worthwhile to add vias to the routing. +.RE +.TP +.B \fBrsim \fR[\fIoptions\fR]\fR [\fIfilename\fR] +Runs rsim under Magic. +See \fITutorial #11: Using IRSIM and RSIM with Magic\fR for more information +on what options and files are required by rsim. +Normally, IRSIM requires a parameter file for the technology and a \fB.sim\fR +file describing the circuit. +.IP +The \fBrsim\fR command without any options can be used to interact with +a previously-started rsim. +Type \fBrsim\fR and you will see the rsim prompt. +To get back to magic, type \fBq\fR. +.TP +.B "save \fR[\fIname\fR]" +Save the edit cell on disk. +If the edit cell is currently the +``(UNNAMED)'' cell, \fIname\fR must be specified; in this case +the edit cell is renamed to \fIname\fR as well as being saved +in the file \fIname\fR.\fBmag\fR. +Otherwise, \fIname\fR is optional. +If specified, the edit cell +is saved in the file \fIname\fR.\fBmag\fR; otherwise, it is saved +in the file from which it was originally read. +.TP +.B "see \fIoption\fR" +This command is used to control which layers are to be displayed +in the window under the cursor. +It has several forms: +.RS +.TP +\fBsee no \fIlayers\fR +Do not display the given layers in the window under the +cursor. +If \fBlabels\fR is given as a layer name, don't +display labels in that window either. +If \fBerrors\fR is +given as a layer, no design-rule violations will be displayed +(the checker will continue to run, though). +If \fIlayers\fR +is given as "*", all mask layers will be disabled, but errors and +labels will still be shown. +See the "LAYERS" section at the end of +this manual page for an explanation of layer naming in Magic. +.TP +\fBsee \fIlayers\fR +Reenable display of the given \fIlayers\fR. +Note that "*" expands to all mask layers, but does not include the label +or error layers. +See the "LAYERS" section at the end of this manual page for details. +.TP +\fBsee no\fR +Don't display any mask layers or labels. +Only subcell bounding +boxes will be displayed. +.TP +\fBsee\fR +Reenable display of all mask layers, labels, and errors. +.TP +\fBsee allSame\fR +Display all cells the same way. +This disables the facility +where the edit cell is displayed in bright colors and non-edit +cells are in paler colors. +After \fBsee allSame\fR, all mask +information will be displayed in bright colors. +.TP +\fBsee no allSame\fR +Reenable the facility where non-edit cells are drawn in paler +colors. +.RE +.TP +.B "select \fIoption\fR" +This command is used to select paint, labels, and subcells before +operating on them with commands like \fBmove\fR and \fBcopy\fR +and \fBdelete\fR. +It has several forms: +.RS +.TP +.B "select" +If the cursor is over empty space, then this command is identical +to \fBselect cell\fR. +Otherwise, paint is selected. The first +time the command is invoked, a chunk of paint is selected: the +largest rectangular area of material of the same type visible underneath +the cursor. +If the command is invoked again without moving the +cursor, the selection is extended to include all material of the same +type, regardless of shape. +If the command is invoked a third time, +the selection is extended again to include all material that is +visible and electrically connected to the point underneath the cursor. +.TP +.B "select more" +This command is identical to \fBselect\fR except that the selection +is not first cleared. +The result is to add the newly-selected material +to what is already in the selection. +.TP +.B "select less" +This chooses material just as \fBselect\fR does, but the material +is removed from the selection, rather than added to it. +The result is to deselect the chosen material. +.TP +.B "select \fR[\fBmore\fR | \fBless\fR] \fBarea\fI layers\fR" +Select material by area. +If \fIlayers\fR are not specified, then +all paint, labels, and unexpanded subcells visible underneath the +box are selected. +If \fIlayers\fR is specified, then only those +layers are selected. +If \fBmore\fR is specified, the new material +is added to the current selection rather than replacing it. +If \fBless\fR is specified, the new material is removed from the +selection (deselected). +.TP +.B "select \fR[\fBmore\fR | \fBless\fR] \fBcell\fI name\fR" +Select a subcell. +If \fIname\fR isn't given, this command finds a +subcell that is visible underneath the cursor and selects it. +If +the command is repeated without moving the cursor then it will step +through all the subcells under the cursor. +If \fIname\fR is given, +it is treated as a hierarchical instance identifier starting from the +root of the window underneath the cursor. +The named cell is selected. +If \fBmore\fR is specified, the new subcell is added to the current +selection instead of replacing it. +If \fBless\fR is specified, the new subcell is removed from the +selection (deselected). +.TP +.B "select clear" +Clear out the selection. +This does not affect the layout; it +merely deselects everything. +.TP +.B "select help" +Print a short synopsis of the selection commands. +.TP +.B "select save \fIcell\fR" +Save all the information in the selection as a Magic cell on disk. +The selection will be saved in file \fIcell\fB.mag\fR. +.TP +.I "select and the see command" +Select interacts with the \fBsee\fR command. +When selecting individual pieces of material, only visible layers +are candidates for selection. +When selecting an entire area, however, both visible and non-visible +material is selected. +This behavior allows entire regions of material +to be moved, even if \fBsee\fR has been used to turn off the display of +some of the layers. +.RE +.TP +.B "sideways\fR" +Flip the selection left-to-right about a vertical axis running +through the center of the selection's area. +If the box is +in the same window +as the selection, it is flipped too. +Selected material not in +the edit cell is not affected. +.TP +.B "simcmd \fIcmd\fR" +Sends the command \fIcmd\fR to rsim for execution. +See \fITutorial #11: Using IRSIM and RSIM with Magic\fR for more information. +.TP +.B "snap \fR[\fBon\fR]" +.TP +.B "snap \fR[\fBoff\fR]" +Control whether the box and point are snapped to the grid selected +for the windows in which they appear +(the grid was set by the \fBgrid\fR command), or to the standard 1x1 grid. +The default is for snapping to be \fBoff\fR, i.e., snapping to a 1x1 grid. +With no arguments, \fBsnap\fR prints whether snapping is enabled or not. +.TP +.B \fBstartrsim \fR[\fIoptions\fR]\fR [\fIfilename\fR] +Similar to the \fBrsim\fR command, except it returns to Magic as soon as +rsim is started. +See \fITutorial #11: Using IRSIM and RSIM with Magic\fR for more information. +.TP +.B "straighten \fIdirection\fR" +Straighten jogs in wires underneath the box by pulling them in \fIdirection\fR. +Jogs are only straightened if doing so will cause no additional geometry +to move. +.TP +.B "stretch \fR[\fIdirection \fR[\fIamount\fR]]" +This command is identical to \fBmove\fR except that simple +stretching occurs as the selection is moved. +Each piece of +paint in the selection causes the area through which it's +moved to be erased in that layer. +Also, each piece of paint +in the selection that touches unselected material along its +back side causes extra material to be painted to fill in the +gap left by the move. +If \fIdirection\fR isn't given and the +cursor isn't exactly left, right, up, or down from the box +corner, then Magic first rounds the cursor position off to a +position that is one of those (whichever is closest). +.TP +.B "tool \fR[\fIname\fR | \fBinfo\fR]" +Change the current tool. +The result is that the cursor shape is +different and the mouse buttons mean different things. +The +command \fBtool info\fR prints out the meanings of the buttons +for the current tool. +\fBTool \fIname\fR changes the current +tool to \fIname\fR, where \fIname\fR is one of \fBbox\fR, \fBwiring\fR, +or \fBnetlist\fR. +If \fBtool\fR is invoked with no arguments, +it picks a new tool in circular sequence: multiple invocations +will cycle through all of the available tools. +.TP +.B "unexpand" +Unexpand all cells +that touch the box but don't completely contain it. +.TP +.B "upsidedown\fR" +Flip the selection upside down about a horizontal axis running +through the center of the selection's area. +If the box is in the same window +as the selection then it is flipped too. +Selected material that is not +in the edit cell is not changed. +.TP +.B "what" +Print out information about all the things that are selected. +.TP +.B "wire \fIoption \fR[\fIargs\fR]" +This command provides a centerline-wiring style user interface. +\fIOption\fR and \fIargs\fR specify a particular wiring option, +as described below. +Some of the options can be invoked via +mouse buttons when the \fBwiring\fR tool is active. +.RS +.TP +.B "wire help" +Print out a synopsis of the various wiring commands. +.TP +.B "wire horizontal" +Just like \fBwire leg\fR except that the new segment is forced to +be horizontal. +.TP +.B "wire leg" +Paint a horizontal or vertical segment of wire from one side of the box +over to the cursor's x- or y-location (respectively). +The direction +(horizontal or vertical) is chosen so as to produce the longest +possible segment. +The segment is painted in the current wiring material +and thickness. +The new segment is selected, and the box is placed at +its tip. +.TP +.B "wire switch \fB[\fIlayer width\fR]" +Switch routing layers and place a contact at the box location. +The +contact type is chosen to +connect the old and new routing materials. +The box is placed at +the position of the contact, and the contact is selected. +If \fIlayer\fR and \fIwidth\fR are specified, they are used as +the new routing material and width, respectively. +If they are not +specified, the new material and width are chosen to correspond to +the material underneath the cursor. +.TP +.B "wire type \fB[\fIlayer width\fR]" +Pick a material and width for wiring. +If \fIlayer\fR and \fIwidth\fR +are not given, then they are chosen from the material underneath +the cursor, a square chunk of material is selected to indicate the +layer and width that were chosen, and the box is placed over this +chunk. +If \fIlayer\fR and \fIwidth\fR are given, then this command +does not modify the box position. +.TP +.B "wire vertical" +Just like \fBwire leg\fR except that the new segment is forced to be +vertical. +.RE +.TP +.B "writeall \fR[\fBforce\fR]" +This command steps through all the cells that have been modified +in this edit session and gives you a chance to write them out. +If the \fBforce\fR option is specified, then ``autowrite'' mode +is used: all modified cells are automatically written without +asking for permission. + +.SH "COMMANDS FOR ALL WINDOWS" +These commands are not used for layout, but are instead used for +overall, housekeeping functions. +They are valid in all +windows. +.TP +.B "closewindow" +The window under the cursor is closed. +That area of the screen will +now show other windows or the background. +.TP +\fBecho \fR[\fB-n\fR] \fIstr1 str2 ... strN\fR +Prints \fIstr1 str2 ... strN\fR in the text window, separated by +spaces and followed by a newline. +If the \fB-n\fR switch is given, no newline is output +after the command. +.TP +\fBhelp\fR [\fIpattern\fR] +Displays a synopsis of commands that apply to the window you +are pointing to. +If \fIpattern\fR is given then only +command descriptions containing the pattern are printed. +\fIPattern\fR +may contain '*' and '?' characters, which match a string of non-blank +characters or a single non-blank character (respectively). +.TP +.B "logcommands \fR[\fIfile \fR[\fBupdate\fR]]]" +If \fIfile\fR is given, all further commands are logged to that +file. +If no arguments are given, command logging is terminated. +If the keyword \fBupdate\fR is present, commands are +output to the file to cause the screen to be updated after each +command when the command file is read back in. +.TP +.B "macro \fR[\fIchar \fR[\fIcommand\fR]]" +\fICommand\fR is associated with \fIchar\fR such +that typing \fIchar\fR on the keyboard is equivalent to typing +``:'' followed by \fIcommand\fR. +If \fIcommand\fR is omitted, +the current macro for \fIchar\fR is printed. +If \fIchar\fR is +also omitted, then all current macros are printed. +If \fIcommand\fR contains spaces, tabs, or semicolons then it must be placed +in quotes. +The semicolon acts as a command separator allowing multiple +commands to be combined in a single macro. +.TP +.B "openwindow \fR[\fIcell\fR]" +Open a new, empty window at the cursor position. +Placement, sizing, and methods of manipulation are determined by +the conventions of the window system in use. +If +\fIcell\fR is specified, then that cell is displayed +in the new window. +Otherwise the area of the box will be displayed +in the new window. +.TP +.B "pushbutton \fIbutton action\fR" +Simulates a button push. +Button should be \fBleft\fR, \fBmiddle\fR, +or \fBright\fR. +Action is one of \fBup\fR, or \fBdown\fR. +This command is normally invoked only from command scripts +produced by the \fBlogcommands\fR command. +.TP +.B "quit" +Exit Magic and return to the shell. +If any cells, colormaps, or netlists +have changed since they were last saved on disk, you +are given a chance to abort the command and continue in Magic. +.TP +.B "redo \fR[\fIn\fR]" +Redo the last \fIn\fR commands that were undone using \fBundo\fR (see below). +The number of commands to redo defaults to 1 if \fIn\fR is not specified. +.TP +.B "redraw" +Redraw the graphics screen. +.TP +.B "scroll \fIdirection \fR[\fIamount\fR]" +The window under the cursor is moved by +\fIamount\fR screenfulls in \fIdirection\fR +relative to the circuit. +If \fIamount\fR is omitted, +it defaults to 0.5. +.TP +.B "send \fItype command\fR" +Send a \fIcommand\fR to the window client named by \fItype\fR. +The +result is just as if \fIcommand\fR had been typed in a window +of type \fItype\fR. +See \fBspecialopen\fR, below, +for the allowable types of windows. +.TP +.B "setpoint [\fIx y\fR [\fIwindowID\fR]]" +Fakes the location of the cursor up until after the +next interactive command. +Without arguments, just prints out the current point location. +This command is normally invoked only from command scripts. +.IP +If \fIwindowID\fR is given, then the point is assumed to be in that +window's screen coordinate system rather than absolute screen +coordinates. +.TP +.B "sleep \fIn" +Causes Magic to go to sleep for \fIn\fR seconds. +.TP +.B "source \fIfilename" +Each line of \fIfilename\fR is read and processed as one +command. +Any line whose last +character is backslash is joined to the following line. +The commands \fBsetpoint\fR, \fBpushbutton\fR, \fBecho\fR, +\fBsleep\fR, and \fBupdatedisplay\fR are useful in command files, +and seldom used elsewhere. +.TP +.B "specialopen \fR[\fIx1 y1 x2 y2\fR] \fItype\fR [\fIargs\fR]" +Open a window of type \fItype\fR. +If the optional \fIx1 y1 x2 y2\fR +coordinates are given, then the new window will have its lower +left corner at screen coordinates (\fIx1\fR, \fIy1\fR) and its upper right +corner at screen coordinates (\fIx2\fR, \fIy2\fR). +The \fIargs\fR arguments are interpreted +differently depending upon the type of the window. +These +types are known: +.RS +.TP +.B layout +This type of window is used to edit a VLSI cell. +The command takes a single argument +which is used as the name of a cell to be loaded. +The command +.ce +\fBopen \fIfilename\fR +is a shorthand for the command +.ce +\fBspecialopen layout \fIfilename\fR. +.TP +.B color +This type of window allows the color map to be edited. +See the +section COMMANDS FOR COLORMAP EDITING below. +.TP +.B netlist +This type of window presents a menu that can be used to place labels, +and to generate and edit net-lists. +See the section +COMMANDS FOR NETLIST EDITING below. +.RE +.TP +.B "underneath" +Move the window pointed at so that it lies underneath the rest of the windows. +.TP +.B "undo \fR[\fIcount\fR]" +Undoes the last \fIcount\fR commands. +Almost all commands in Magic +are now undo-able. +The only holdouts left are cell expansion/unexpansion, +and window modifications (change of size, zooming, etc.). +If \fIcount\fR is unspecified, it defaults to 1. +.TP +.B "updatedisplay" +Update the display. +This command is normally invoked only from command scripts. +Scripts +that do not contain this command update the screen only at the end of +the script. +.TP +.B "view" +Choose a view for the window underneath the cursor so that everything in +the window is visible. +.TP +.B "windscrollbars \fR[\fIon\fR|\fIoff\fR]" +Set the flag that determines if new windows will have scroll bars. +.TP +.B "windowpositions \fR[\fIfile\fR]" +Write out the positions of the windows in a format suitable +for the \fBsource\fR command. +If \fIfile\fR is specified, then write it +out to that file instead of to the terminal. +.TP +.B "zoom \fR[\fIfactor\fR]" +Zoom the view in the window underneath the cursor +by \fIfactor\fR. +If \fIfactor\fR is less than 1, we zoom in; +if it is greater than one, we zoom out. + +.SH "MOUSE BUTTONS FOR NETLIST WINDOWS" +.PP +When the netlist menu is opened using the command \fBspecial netlist\fR, +a menu appears on the screen. +The colored areas on the menu can be clicked +with various mouse buttons to perform various actions, such as placing +labels and editing netlists. +For details on how to use the menu, +see ``Magic Tutorial #7: Netlists and Routing''. +The menu buttons all +correspond to commands that could be typed in netlist or layout windows. + +.SH "COMMANDS FOR NETLIST WINDOWS" +.PP +The commands described below work if you are pointing to the +interior of the netlist menu. +They may also be invoked when +you are pointing at another window by using the \fBsend netlist\fR +command. +Terminal names in all of the commands below are +hierarchical names consisting of zero or more cell use ids separated +by slashes, followed by the label name, e.g. \fBtoplatch/shiftcell_1/in\fR. +When processing the terminal paths, the search always starts in the +edit cell. +.TP +\fBadd \fIterm1 term2\fR +Add the terminal named \fIterm1\fR to the net containing +terminal \fIterm2\fR. +If \fIterm2\fR isn't in a net yet, +make a new net containing just \fIterm1\fR and \fIterm2\fR. +.TP +\fBcleanup\fR +Check the netlist to make sure that for every +terminal named in the list there is at least one label in +the design. +Also check to make sure +that every net contains at least two distinct terminals, +or one terminal with several labels by the same name. +When +errors are found, give the user an opportunity to delete +offending terminals and nets. +This command can also be +invoked by clicking the ``Cleanup'' menu button. +.TP +\fBcull\fR +Examine the current netlist and the routing in the edit cell, and remove +those nets from the netlist that are already routed. +This command is often used +after pre-routing nets by hand, so the router won't try to implement them +again. +.TP +\fBdnet \fIname name\fR ... +For each \fIname\fR given, delete the net containing that terminal. +If no \fIname\fR is given, delete the currently-selected net, just +as happens when the ``No Net'' menu button is clicked. +.TP +\fBdterm \fIname name\fR ... +For each \fIname\fR given, delete that terminal from its net. +.TP +\fBextract\fR +Pick a piece of paint in the edit cell that lies under the box. +Starting from this, trace out all the electrically-connected +material in the edit cell. +Where this material touches subcells, +find any terminals in the subcells and make a new net containing +those terminals. +Note: this is a different command from the +\fBextract\fR command in layout windows. +.TP +\fBfind \fIpattern \fR[\fIlayers\fR] +Search the area beneath the box for labels matching \fIpattern\fR, +which may contain the regular-expression characters ``\fB*\fR'' +``\fB?\fR'', +``\fB[\fR'', +``\fB]\fR'', and +``\fB\e\fR'' (as matched by \fIcsh\fR\|(1); +see the description of the \fBfind\fR button in +``Magic Tutorial #7: Netlists and Routing''). +For each label found, leave feedback whose text is the layer +on which the label appears, followed by a semicolon, followed +by the full hierarchical pathname of the label. +The feedback surrounds the area of the label by one unit on all sides. +(The reason for the one-unit extension is that feedback +rectangles must have positive area, while labels may have +zero width or height). +If \fIlayers\fR are given, only labels attached to those layers +are considered. +.TP +\fBflush \fR[\fInetlist\fR] +The netlist named \fInetlist\fR is reloaded from the disk file +\fInetlist\fB.net\fR. +Any changes made to the netlist since the +last time it was written are discarded. +If \fInetlist\fR isn't +given, the current netlist is flushed. +.TP +\fBjoin \fIterm1 term2\fR +Join together the nets containing terminals \fIterm1\fR and +\fIterm2\fR. +The result is a single net containing all the +terminals from both the old nets. +.TP +\fBnetlist \fR[\fIname\fR] +Select a netlist to work on. +If \fIname\fR is provided, read +\fIname\fR.\fBnet\fR (if it hasn't already been read before) and make +it the current netlist. +If \fIname\fR +isn't provided, use the name of the edit cell instead. +.TP +\fBprint \fR[\fIname\fR] +Print the names of all the terminals in the net containing \fIname\fR. +If \fIname\fR isn't provided, print the terminals in the current +net. +This command has the same effect as clicking on the ``Print'' +menu button. +.TP +\fBripup \fR[\fBnetlist\fR] +This command has two forms. +If \fBnetlist\fR isn't typed as an +argument, then find a piece of paint in the edit cell under the +box. +Trace out all paint in the edit cell that is electrically +connected to the starting piece, and delete all of this paint. +If \fBnetlist\fR is typed, find all paint in the edit cell that +is electrically connected to any of the terminals in the current +netlist, and delete all of this paint. +.TP +\fBsavenetlist \fR[\fIfile\fR] +Save the current netlist on disk. +If \fIfile\fR is given, write +the netlist in \fIfile\fR.\fBnet\fR. +Otherwise, write the netlist +back to the place from which it was read. +.TP +\fBshownet\fR +Find a piece of paint in any cell underneath the box. +Starting +from this paint, trace out all paint in all cells that is +electrically connected to the starting piece and highlight +this paint on the screen. +To make the highlights go away, +invoke the command with the box over empty space. +This command +has the same effect as clicking on the ``Show'' menu button. +.TP +\fBshowterms\fR +Find the labels corresponding to each of the terminals in the +current netlist, and generate a feedback area over each. +This +command has the same effect as clicking on the ``Terms'' menu +button. +.TP +\fBtrace\fR [\fIname\fR] +This command is similar to \fBshownet\fR except that instead +of starting from a piece of paint under the box, it starts +from each of the terminals in the net containing \fIname\fR +(or the current net if no \fIname\fR is given). +All connected +paint in all cells is highlighted. +.TP +\fBverify\fR +Compare the current netlist against the wiring in the edit cell +to make sure that the nets are implemented exactly as specified +in the netlist. +If there are discrepancies, feedback areas are +created to describe them. +This command can also be invoked by +clicking the ``Verify'' menu button. +.TP +\fBwriteall\fR +Scan through all the netlists that have been read during this +editing session. +If any have been modified, ask the user whether +or not to write them out. + +.SH "MOUSE BUTTONS FOR COLORMAP WINDOWS" +.PP +Color windows display two sets of colored bars and a swatch +of the color being edited. +The left set of color bars is +labeled Red, Green, and Blue; these correspond to the proportion +of red, green, and blue in the color being edited. +The right +set of bars is labeled Hue, Saturation, and Value; these +correspond to the same color but in a space whose axes are +hue (spectral color), saturation (spectral purity vs. dilution +with white), and value (light vs. dark). +.PP +The value of a color is changed by pointing inside the +region spanned by one of the color bars and clicking any mouse button. +The color bar will change so that it extends to the point +selected by the crosshair when the button was pressed. +The color +can also be changed by clicking a button over one of the ``pumps'' +next to a color bar. +A left-button click makes a 1% increment or decrement, +and a right-button click makes a 5% change. +.PP +The color being edited can be +changed by pressing the left button over the current color box in +the editing window, then moving the mouse and releasing the button over +a point on the screen that contains the color to be edited. +A +color value can be copied from an existing color to the current color +by pressing the right mouse button over the current color box, then +releasing the button when the cursor is over the color whose value +is to be copied into the current color. + +.SH "COMMANDS FOR COLORMAP WINDOWS" +.PP +These commands work if you are pointing to the interior of a colormap +window. +The commands are: +.TP +.B "color \fR[\fInumber\fR]" +Load \fInumber\fR as the color being edited in the window. +\fINumber\fR must be an octal number between 0 and 377; +it corresponds to the entry in the color map that is to be edited. +If no \fInumber\fR is given, this command prints out the value of +the color currently being edited. +.TP +.B "load \fR[\fItechStyle displayStyle monitorType\fR]" +Load a new color map. +If no arguments are specified, the color map for the +current technology style (e.g, \fBmos\fR), +display style (e.g, \fB7bit\fR), and monitor type (e.g, \fBstd\fR) +is re-loaded. +Otherwise, the color map +is read from the file +\fItechStyle\fR.\fIdisplayStyle\fR.\fImonitorType\fB.cmap\fR +in the current directory or in the system library directory. +.TP +.B "save \fR[\fItechStyle displayStyle monitorType\fR]" +Save the current color map. +If no arguments are specified, save the color map in a +file determined by the current technology style, display +style, and monitor type as above. +Otherwise, save it in the file +\fItechStyle\fR.\fIdisplayStyle\fR.\fImonitorType\fB.cmap\fR +in the current directory or in the system library directory. + +.SH "DIRECTIONS" +.PP +Many of the commands take a direction as an argument. +The valid +direction names are \fBnorth\fR, \fBsouth\fR, \fBeast\fR, \fBwest\fR, +\fBtop\fR, \fBbottom\fR, \fBup\fR, \fBdown\fR, \fBleft\fR, \fBright\fR, +\fBnortheast\fR, \fBne\fR, \fBsoutheast\fR, \fBse\fR, \fBnorthwest\fR, +\fBnw\fR, \fBsouthwest\fR, \fBsw\fR, and \fBcenter\fR. +In some +cases, only Manhattan directions are permitted, which means only +\fBnorth\fR, \fBsouth\fR, \fBeast\fR, \fBwest\fR, and their synonyms, +are allowed. + +.SH "LAYERS" +.PP +The mask layers are different for each technology, and are +described in the technology manuals. +The layers below +are defined in all technologies: +.TP +.B "*" +All mask layers. +Does not include special layers like the label layer +and the error layer (see below). +.TP +.B "$" +All layers underneath the cursor. +.TP +.B "errors" +Design-rule violations (useful primarily in the \fBsee\fR command). +.TP +.B "labels" +Label layer. +.TP +.B "subcell" +Subcell layer. +.PP +Layer masks may be formed by constructing comma-separated lists +of individual layer names. +The individual layer names may be +abbreviated, as long as the abbreviations are unique. +For example, to indicate polysilicon and n-diffusion, use +\fBpoly,ndiff\fR or \fBndiff,poly\fR. +The special character \fB\-\fR causes all +subsequent layers to be subtracted from the layer mask. +For +example, \fB*\-p\fR means ``all layers but polysilicon''. +The special character \fB\+\fR reverses the effect of a previous +\fB\-\fR; all subsequent layers are once again added to the layer +mask. + +.SH "SEE ALSO" +.PP +ext2sim(1), ext2spice(1), cmap(5), dstyle(5), ext(5), sim(5), +glyphs(5), magic(5), displays(5), net(5) +.sp +Online documentation can be found at the following URLs: +.br +http://opencircuitdesign.com/magic/ +.br +http://vlsi.cornell.edu/magic/ +.br +The OpenCircuitDesign website contains HTML versions of all the +documentation found in the Magic "doc" subdirectory, including +tutorials, technology file manual; download, compile and install +instructions, and command reference. + +.SH "FILES" +.PP +.ta 5c +.nf +${CAD_ROOT}/magic/sys/.magic startup file to create default macros +.br +~/.magic user-specific startup command file +.br +${CAD_ROOT}/magic/nmos/* some standard nmos cells +.br +${CAD_ROOT}/magic/scmos/* some standard scmos cells +.br +${CAD_ROOT}/magic/sys/*.cmap colormap files, see CMAP(5) man page +.br +${CAD_ROOT}/magic/sys/*.dstyle display style files, see DSTYLE(5) man page +.br +${CAD_ROOT}/magic/sys/*.glyphs cursor and window bitmap files, see GLYPH(5) man page +.br +${CAD_ROOT}/magic/sys/*.tech technology files, see ``Maintainer's Manual + #2: The Technology File'' +.br +${CAD_ROOT}/displays configuration file for Magic serial-line displays +.fi +.PP +\fICAD_ROOT variable.\fR If the shell environment variable \fBCAD_ROOT\fR is set, +Magic uses that location instead of the installed location (/usr/local/lib, by +default). +Normally one would change the search path (see below) rather than +redirect the entire \fBCAD_ROOT\fR location. +.PP +\fISearch path.\fR Magic's system and library files, such as technology files +and display-style files, normally are placed in the ${CAD_ROOT}/magic area. +However, Magic first tries to find them in the user's current directory. +This +makes it easier for an individual user to override installed system files. +The search path is defined by the Magic command \fBpath\fR, + +.SH AUTHORS +\fBOriginal\fR: Gordon Hamachi, Robert Mayo, John Ousterhout, Walter Scott, +George Taylor +.sp +\fBContributors\fR: Michael Arnold (Magic maze-router and Irouter +command), Don Stark (new contact scheme, X11 interface, various other things), +Mike Chow (Rsim interface). +The X11 driver is the work of several +people, including Don Stark, Walter Scott, and Doug Pan. +.sp +\fBDevelopers\fR: Ongoing development (magic version 6.5 and higher) +made possible by Stefanos Sidiropolous, Tim Edwards, Rajit Manohar, +Philippe Pouliquen, Michael Godfrey, and others. +.sp +Many other people have contributed to Magic, but it is impossible to list +them all here. +We appreciate their help! +.SH BUGS +.PP +If Magic gets stuck for some reason, first try typing Control-C into the +terminal window (in the Tcl/Tk version, this is the \fIoriginal\fR +terminal, not the Tk console window). +Most of Magic's lengthy database +searches are interruptible. +If this doesn't work, kill the process. +The Tcl/Tk version automatically creates periodic backups that may be +recovered with "magic -r". +.PP +Report bugs to \fBmagic-dev@csl.cornell.edu\fR. +Please be specific: +tell us exactly what you did to cause the problem, what you expected +to happen, and what happened instead. +If possible send along small +files that we can use to reproduce the bug. +A list of known bugs and +fixes is also available from the above address. +Tell us which version +of magic you are running. diff --git a/doc/man/net.5 b/doc/man/net.5 new file mode 100644 index 00000000..3ff5ee7c --- /dev/null +++ b/doc/man/net.5 @@ -0,0 +1,80 @@ +.\" sccsid @(#)net.5 4.1 MAGIC (Berkeley) 11/29/85 +.\" +.\" CONVENTIONS: +.\" italics: things that are substituted for +.\" boldface: characters that are typed as-is +.\" +.\" EXAMPLE: \fIfilename\fB.mag\fR +.\" or: \fBcif \fR[\fIfile\fR] +.\" +.TH NET 5 +.UC 4 +.SH NAME +net \- format of .net files read/written by Magic's netlist editor + +.SH DESCRIPTION +.PP +Netlist files are read and written by Magic's netlist editor +in a very simple ASCII format. +The first line contains +the characters ``\ \ Netlist File'' (the leading blank is +important). +After that comes a blank line and then +the descriptions of one or +more nets. +Each net contains one or more lines, where each +line contains a single terminal name. +The nets are separated +by blank lines. +Any line that is blank or whose first character +is blank is considered to be a separator line and the rest of its +contents are ignored. +.PP +Each terminal name is a path, much like a file path name in Unix. +It consists of one or more fields separated by slashes. +The last +field in the path is the name of a label in a cell. +The other +fields (if any), are cell instance identifiers that form a path +from the edit cell down to the label. +The first instance identifier +must name a subcell of the edit cell, the second must be a subcell +of the first, and so on. +.PP +Instance identifiers are unique within their parent cells, so a +terminal path selects a unique cell to contain the label. +However, +the same label may appear multiple times within its cell. +When +this occurs, Magic assumes that the identical labels identify +electrically equivalent terminals; it will choose the closest of them +when routing to that terminal. +Further, after connecting to one of these +terminals Magic may take advantage of the internal wiring connecting them +together and route through a cell to complete the net's wiring. +.PP +An example netlist file follows below. +It contains three distinct nets. +.nf + +.cs R 22 +\l'10c\&\(em' +.RS + Netlist File + +alu/bit_1/cout +alu/bit_2/cin + + +regcell[21,2]/output +latch[2]/input + This line starts with a blank, so it's a separator. +opcode_pla/out6 +shifter/drivers/shift2 +.RE +\l'10c\&\(em' +.cs R +.fi + +.SH "SEE ALSO" +magic\|(1) diff --git a/doc/man/sim.5 b/doc/man/sim.5 new file mode 100644 index 00000000..f2a75e61 --- /dev/null +++ b/doc/man/sim.5 @@ -0,0 +1,116 @@ +.\" sccsid @(#)sim.5 4.1 MAGIC (Berkeley) 11/29/85 +.\" +.\" CONVENTIONS: +.\" italics: things that are substituted for +.\" boldface: characters that are typed as-is +.\" +.\" EXAMPLE: \fIfilename\fB.mag\fR +.\" or: \fBcif \fR[\fIfile\fR] +.\" +.TH SIM 5 +.UC 4 +.SH NAME +sim \- format of .sim files read by esim, crystal, etc. + +.SH DESCRIPTION +The simulation tools \fIcrystal\fP\|(1) and \fIesim\fP\|(1) accept +a circuit description in \fB.sim\fP format. +There is a single \fB.sim\fP file for the entire circuit, unlike +Magic's \fIext\fP\|(5) format in which there is a \fB.ext\fP file +for every cell in a hierarchical design. +.LP +A \fB.sim\fP file consists of a series of lines, each of which begins +with a key letter. +The key letter beginning a line determines how the remainder +of the line is interpreted. +The following are the list of key letters understood. +.TP +.B "|\ units: \fIs\fB tech: \fItech\fR format: \fIMIT|LBL|SU\fR" +If present, this must be the first line in the \fB.sim\fP file. +It identifies the technology of this circuit as \fItech\fP and +gives a scale factor for units of linear dimension as \fIs\fP. +All linear dimensions appearing in the \fB.sim\fP file are +multiplied by \fIs\fP to give centimicrons. The format field +signifies the sim variant. MIT and SU are compatible and understood +by all tools. LBL is understood only by gemini(1). +.TP +.I "type g s d l w x y \fBg=\fIgattrs \fBs=\fIsattrs \fBd=\fIdattrs" +Defines a transistor of type \fItype\fP. +Currently, \fItype\fP may be +\fBe\fP or \fBd\fP for NMOS, or \fBp\fP or \fBn\fP for CMOS. +The name of the node to which the gate, source, and drain of the +transistor are connected are given by \fIg\fP, \fIs\fP, and \fId\fP +respectively. +The length and width of the transistor are \fIl\fP and \fIw\fP. +The next two tokens, \fIx\fP and \fIy\fP, are optional. +If present, +they give the location of a point inside the gate region of the transistor. +The last three tokens are the attribute lists for the transistor +gate, source, and drain. +If no attributes are present for a particular +terminal, the corresponding attribute list may be absent (i.e, there +may be no \fBg=\fP field at all). +The attribute lists \fIgattrs\fP, etc. are comma-separated lists of +labels. +The label names should not include any spaces, although some +tools can accept label names with spaces if they are enclosed +in double quotes. +.B "In version 6.4.5 and later" +the default format produced by ext2sim is SU. In this format the attribute +of the gate starting with S_ is the substrate node of the fet. The attributes +of the gate, and source and substrate starting with A_, P_ are the area and +perimeter (summed for that node only once) of the source and drain respectively. +This addition to the format is backwards compatible. +.TP +.B "C \fIn1 n2 cap\fR" +Defines a capacitor between nodes \fIn1\fP and \fIn2\fP. +The value of the capacitor is \fIcap\fP femtofarads. +\fBNOTE:\fR +since many analysis tools compute transistor gate capacitance themselves +from the transistor's area and perimeter, +the capacitance between a node and substrate (GND!) normally +does not include the capacitance from transistor gates connected +to that node. +If the \fB.sim\fR file was produced by \fIext2sim\fR\|(1), check +the technology file that was used to produce the original \fB.ext\fR +files to see whether transistor gate capacitance is included or +excluded; +see ``Magic Maintainer's Manual #2: The Technology File'' for details. +.TP +.B "R \fInode res\fR" +Defines the lumped resistance of node \fInode\fP to be \fIres\fP ohms. +This construct is only interpreted by a few programs. +.TP +.B "r \fInode1 node2 res\fR" +Defines an explicit resistor between nodes \fInode1\fP and +\fInode2\fR of resistance \fIres\fP ohms. +This construct is only interpreted by a few programs. +.TP +.B "N \fInode darea dperim parea pperim marea mperim" +As an alternative to computed capacitances, some tools expect +the total perimeter and area of the polysilicon, diffusion, and +metal in each node to be reported in the \fB.sim\fP file. +The \fBN\fP construct associates diffusion area \fIdarea\fP +(in square centimicrons) and diffusion perimeter \fIdperim\fP (in centimicrons) +with node \fInode\fP, polysilicon area \fIparea\fP and perimeter +\fIpperim\fP, and metal area \fImarea\fP and perimeter \fImperim\fP. +.I "This construct is technology dependent and obsolete." +.TP +.B "A \fInode attr\fR" +Associates attribute \fIattr\fP for node \fInode\fP. +The string +\fIattr\fP should contain no blanks. +.TP +.B "= \fInode1 node2\fR" +Each node in a \fB.sim\fP file is named implicitly by having it appear in +a transistor definition. +All node names appearing in a \fB.sim\fP file +are assumed to be distinct. +Some tools, such as \fIesim\fP\|(1), recognize aliases for node names. +The \fB=\fR construct allows the name \fInode2\fP to be +defined as an alias for the name \fInode1\fP. +Aliases defined +by means of this construct may not appear anywhere else in the \fB.sim\fP file. + +.SH "SEE ALSO" +crystal\|(1), esim\|(1), ext2sim\|(1), sim2spice\|(1), ext\|(5) diff --git a/doc/man/tmac.anc b/doc/man/tmac.anc new file mode 100644 index 00000000..675ed478 --- /dev/null +++ b/doc/man/tmac.anc @@ -0,0 +1,272 @@ + +' # month name +.if t .tr ~\(ap +.if "\nd"0" .nr m \n(mo-1 +.if "\nm"0" .ds ]m January +.if "\nm"1" .ds ]m February +.if "\nm"2" .ds ]m March +.if "\nm"3" .ds ]m April +.if "\nm"4" .ds ]m May +.if "\nm"5" .ds ]m June +.if "\nm"6" .ds ]m July +.if "\nm"7" .ds ]m August +.if "\nm"8" .ds ]m September +.if "\nm"9" .ds ]m October +.if "\nm"10" .ds ]m November +.if "\nm"11" .ds ]m December +' # set the date +.if n \{.nr m \nm+1 +. ie \nd .ds ]W Modified \nm/\nd/\ny +. el .ds ]W Printed \n(mo/\n(dy/\n(yr\} +.if t \{.ie \nd .ds ]W \*(]m \nd, 19\ny +. el .ds ]W \*(]m \n(dy, 19\n(yr\} +.de UC +.if t .ds ]W 1990 DECWRL/Livermore Magic +.. +' # reset the basic page layout +.de }E +.}f +.in \\n()Ru+\\n(INu +.ll \\n(LLu +.. +' # default tabs +.de DT +'ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i +.. +' # set type font and size +.de }f +.ps 10 +.ft 1 +.. +' # handle the head of the page +.de }H +.ev 1 +.}C +'sp .5i +.ft 1 +.ps 10 +.tl @\\*(]H@\\*(]D@\\*(]H@ +'sp .5i +.ev +.ns +.. +' # handle the foot of the page +.de }F +.ev 1 +.ft 1 +.ps 10 +'sp .5i +.tl @\\*(]W@\\*(]L@%@ +'bp +.ev +.. +' # the cut mark +.if n .ig +.de }C +.po .1i +.tl '-' +.po +.. +' # the final cut mark +.de }M +.}N +.wh -1p }C +.ll \\n(LLu +.. +' # no runout unless there was a .TH +.de }K +.}N +.pl 1 +.ll \\n(LLu +.. +.em }K +' # set title and heading +.de TH +.if t .ds ]W 1990 DECWRL/Livermore Magic +.PD +.if n .nr IN .5i +.if t .nr IN .5i +.nr LL \\n(.l +.ds ]H \\$1\|(\|\\$2\|) +.ds ]D CAD Tool User's Manual +.wh 0 }H +.if t .wh -1i }F +.if n .wh -1.167i }F +.em }M +.if \\n(nl .bp 1 +.ds ]L \\$3 +.}E +.DT +.nr )I .5i +.nr )R 0 +.if n .na +.. +' # section heading +.de SH +.}X 0 +.nr )E 2 +\&\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6 +.. +' # sub section heading +.de SS +.}X \\n()Ru+\\n(INu +\&\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6 +.br +.. +' # subroutine for section heading +.de }X +.}E +.ti \\$1 +.sp \\n()Pu +.ne 2 +.nr )R 0 +.fi +.it 1 }N +.SM +.B +.. +' # end of SH (cf }X above and }N below) +.de }2 +.nr )E 0 +.}E +.nr )I .5i +.ns +.. +' # italic +.de I +.ft 2 +.it 1 }N +.if !"\\$1"" \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 +.. +' # bold +.de B +.ft 3 +.it 1 }N +.if !"\\$1"" \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 +.. +' # small +.de SM +.ps 9 +.it 1 }N +.if !"\\$1"" \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 +.. +' # combinations of Roman, italic, bold +.de RI +.}S 1 2 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" +.. +.de RB +.}S 1 3 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" +.. +.de IR +.}S 2 1 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" +.. +.de IB +.}S 2 3 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" +.. +.de BR +.}S 3 1 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" +.. +.de BI +.}S 3 2 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" +.. +' # make special case of shift out of italic +.de }S +.ds ]F +.if "\\$1"2" .if !"\\$5"" .ds ]F\^ +.ie !"\\$4"" .}S \\$2 \\$1 "\\$3\f\\$1\\$4\\*(]F" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.el \\$3 +.}f +.. +' # paragraph +.de LP +.PP +.. +.de PP +.sp \\n()Pu +.ne 2 +.}E +.nr )I .5i +.ns +.. +' # paragraph distance +.de PD +.if t .nr )P .4v +.if n .nr )P 1v +.if !"\\$1"" .nr )P \\$1v +.. +' # hanging indent +.de HP +.sp \\n()Pu +.ne 2 +.if !"\\$1"" .nr )I \\$1n +.ll \\n(LLu +.in \\n()Ru+\\n(INu+\\n()Iu +.ti \\n()Ru+\\n(INu +.}f +.. +' # indented paragraph +.de IP +.TP \\$2 +\&\\$1 +.. +' # hanging label +.de TP +.if !"\\$1"" .nr )I \\$1n +.sp \\n()Pu +.in \\n()Ru +.nr )E 1 +.ns +.it 1 }N +.di ]B +.. +' # end of TP (cf }N below) +.de }1 +.ds ]X \&\\*(]B\\ +.nr )E 0 +.if !"\\$1"" .nr )I \\$1n +.}f +.ll \\n(LLu +.in \\n()Ru+\\n(INu+\\n()Iu +.ti \\n(INu +.ie !\\n()Iu+\\n()Ru-\w@\\*(]X@u-3p \{\\*(]X +.br\} +.el \\*(]X\h@|\\n()Iu+\\n()Ru@\c +.}f +.. +' # handle end of 1-line features +.de }N +.if \\n()E .br +.di +.if "\\n()E"0" .}f +.if "\\n()E"1" .}1 +.if "\\n()E"2" .}2 +.nr )E 0 +.. +' # increase relative indent +.de RS +.nr ]\\n+()p \\n()I +.nr )\\n()p \\n()R +.ie !"\\$1"" .nr )R +\\$1n +.el .nr )R +\\n()I +.nr )I .5i +.}E +.. +' # decrease relative indent +.de RE +.if !"\\$1"" \{.ie "\\$1"0" .nr )p 1 1 +. el .nr )p \\$1 1\} +.ds ]i \\*(]I\\n()p +.ds ]r \\*(]R\\n()p +.nr )I \\*(]i +.nr )R \\*(]r +.if \\n()p .nr )p -1 +.}E +.. +.nr )p 0 1 +.ds ]I \\\\n(] +.ds ]R \\\\n() +.bd S 3 3 +.if t .ds R \(rg +.if n .ds R (Reg.) +.ds S \s10 +.hy 14 diff --git a/doc/psfigures/maint2.1.ps b/doc/psfigures/maint2.1.ps new file mode 100644 index 00000000..55dc7a44 --- /dev/null +++ b/doc/psfigures/maint2.1.ps @@ -0,0 +1,205 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.1.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:08:34 2000 +%%Pages: 1 +%%BoundingBox: 68 68 523 220 +%%DocumentNeededResources: font Helvetica font Helvetica-Bold +%%+ font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrow { +% -12 -40 24 80 bbox +begingate +1 0.80 0 -40 0 20 2 polygon +1.00 0 0 40 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 544 352 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.753 0.333 0.502 scb +240 1.00 192 224 192 192 512 192 672 320 672 352 384 352 6 polygon +sce +0.490 0.651 0.980 scb +240 1.00 192 448 192 416 512 416 672 544 672 576 384 576 6 polygon +sce +0 1.00 192 416 192 448 512 448 512 416 4 polygon +1 1.00 192 448 384 576 2 polygon +1 1.00 512 448 672 576 2 polygon +1 1.00 384 576 672 576 2 polygon +1 1.00 512 416 672 544 2 polygon +1 1.00 672 576 672 544 2 polygon +1 1.00 192 448 672 576 2 polygon +1 1.00 384 576 512 448 2 polygon +0 1.00 192 192 192 224 512 224 512 192 4 polygon +1 1.00 192 224 384 352 2 polygon +1 1.00 512 224 672 352 2 polygon +1 1.00 384 352 672 352 2 polygon +1 1.00 512 192 672 320 2 polygon +1 1.00 672 352 672 320 2 polygon +1 1.00 192 224 672 352 2 polygon +1 1.00 384 352 512 224 2 polygon +1 1.00 672 528 672 368 2 polygon +1 1.00 512 400 512 240 2 polygon +1 1.00 192 400 192 240 2 polygon +1 1.00 384 368 384 416 2 polygon +(plane) {/Helvetica 1.000 cf} (metal1 ) {/Helvetica-Bold 1.000 cf} 4 20 0 704 560 label +(plane) {/Helvetica 1.000 cf} (active ) {/Helvetica-Bold 1.000 cf} 4 20 0 704 336 label +1.00 75 640 240 arrow +1.00 75 656 480 arrow +(: pcontact) {/Helvetica 1.000 cf} (drawn) {/Helvetica-Oblique 1.000 cf} 4 20 0 704 224 label +(: pcontact/m1) {/Helvetica 1.000 cf} (automatically generated) {/Helvetica-Oblique 1.000 cf} 4 20 0 720 464 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.11.ps b/doc/psfigures/maint2.11.ps new file mode 100644 index 00000000..b21dfd74 --- /dev/null +++ b/doc/psfigures/maint2.11.ps @@ -0,0 +1,167 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.11.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 12:05:00 2000 +%%Pages: 1 +%%BoundingBox: 68 68 292 268 +%%DocumentNeededResources: font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 672 288 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.490 0.651 0.980 scb +240 1.00 320 480 320 704 608 704 608 480 4 polygon +sce +0.745 0.600 0.871 scb +240 1.00 192 192 192 320 768 320 768 192 4 polygon +sce +1 1.00 320 704 320 480 608 480 608 704 4 polygon +1 1.00 192 192 192 320 768 320 768 192 4 polygon +(tfar) {/Helvetica-Oblique 1.000 cf} 2 21 0 464 592 label +(fartypes) {/Helvetica-Oblique 1.000 cf} 2 24 0 336 496 label +(neartypes) {/Helvetica-Oblique 1.000 cf} 2 28 0 336 464 label +(outtypes) {/Helvetica-Oblique 1.000 cf} 2 24 0 240 336 label +(intypes) {/Helvetica-Oblique 1.000 cf} 2 28 0 240 304 label +(tinside) {/Helvetica-Oblique 1.000 cf} 2 21 0 448 224 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.2.ps b/doc/psfigures/maint2.2.ps new file mode 100644 index 00000000..7945d99a --- /dev/null +++ b/doc/psfigures/maint2.2.ps @@ -0,0 +1,188 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.2.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:16:25 2000 +%%Pages: 1 +%%BoundingBox: 68 68 856 261 +%%DocumentNeededResources: font Helvetica +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/tiles { +% -304 -188 608 380 bbox +begingate +1 1.00 176 64 176 -96 2 polygon +1 1.00 -176 64 -176 -96 2 polygon +1 1.00 -16 64 -16 192 2 polygon +(A) {/Helvetica 1.000 cf} 2 21 0 -16 -16 label +(C) {/Helvetica 1.000 cf} 2 21 0 224 -16 label +(B) {/Helvetica 1.000 cf} 2 23 0 -240 -16 label +(D) {/Helvetica 1.000 cf} 2 29 0 -16 -160 label +1 1.00 -304 -96 304 -96 2 polygon +1 1.00 -304 64 304 64 2 polygon +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 992 398 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.745 0.600 0.871 scb +241 1.00 1744 606 1744 350 2240 350 2240 606 1744 606 5 polygon +241 1.00 1008 654 1008 350 1504 350 1504 654 1008 654 5 polygon +240 1.00 480 654 272 654 272 350 768 350 768 606 480 606 6 polygon +sce +1 1.00 480 654 272 654 272 350 768 350 768 606 480 606 6 polygon +1.00 0 496 494 tiles +1.00 0 1232 494 tiles +1.00 0 1968 494 tiles +1 1.00 1008 654 1008 350 1504 350 1504 654 1008 654 5 polygon +1 1.00 1744 606 1744 350 2240 350 2240 606 1744 606 5 polygon +(E) {/Helvetica 1.000 cf} 2 21 0 368 622 label +(B) {/Helvetica 1.000 cf} 2 25 0 624 622 label +(E) {/Helvetica 1.000 cf} 2 29 0 1104 638 label +(B) {/Helvetica 1.000 cf} 2 29 0 1376 638 label +(E) {/Helvetica 1.000 cf} 2 25 0 1840 622 label +(B) {/Helvetica 1.000 cf} 2 25 0 2080 622 label +(bloat-or A * 100 C,E 200) {/Helvetica 1.000 cf} 2 21 0 512 206 label +(bloat-max A * 100 C,E 200) {/Helvetica 1.000 cf} 2 21 0 1248 206 label +(bloat-min A * 100 C,E 200) {/Helvetica 1.000 cf} 2 21 0 2000 206 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.3.ps b/doc/psfigures/maint2.3.ps new file mode 100644 index 00000000..8dfcee93 --- /dev/null +++ b/doc/psfigures/maint2.3.ps @@ -0,0 +1,202 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.3.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:18:51 2000 +%%Pages: 1 +%%BoundingBox: 68 68 304 253 +%%DocumentNeededResources: font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 800 460 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.753 0.333 0.502 scb +240 1.00 224 300 224 556 608 556 608 300 4 polygon +sce +0 1.00 224 300 224 556 608 556 608 300 4 polygon +240 1.00 256 332 256 396 320 396 320 332 4 polygon +240 1.00 256 460 256 524 320 524 320 460 4 polygon +240 1.00 384 332 384 396 448 396 448 332 4 polygon +240 1.00 384 460 384 524 448 524 448 460 4 polygon +240 1.00 512 332 512 396 576 396 576 332 4 polygon +240 1.00 512 460 512 524 576 524 576 460 4 polygon +1 1.00 320 572 320 620 2 polygon +1 1.00 384 572 384 620 2 polygon +1 1.00 624 332 672 332 2 polygon +1 1.00 624 300 672 300 2 polygon +1 1.00 256 316 256 236 2 polygon +1 1.00 320 316 320 236 2 polygon +1 1.00 256 604 304 604 2 polygon +1 1.00 400 604 448 604 2 polygon +1 1.00 656 348 656 396 2 polygon +1 1.00 656 284 656 220 2 polygon +1 1.00 336 252 384 252 2 polygon +1 1.00 240 252 192 252 2 polygon +1.00 0 336 252 arrowhead90 +1.00 0 400 604 arrowhead90 +1.00 -1 304 604 arrowhead90 +1.00 -1 240 252 arrowhead90 +1.00 -91 656 348 arrowhead90 +1.00 270 656 284 arrowhead90 +(separation) {/Helvetica-Oblique 1.000 cf} 2 25 0 352 636 label +(size) {/Helvetica-Oblique 1.000 cf} 2 29 0 288 220 label +(border) {/Helvetica-Oblique 1.000 cf} 2 20 0 688 316 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.3b.ps b/doc/psfigures/maint2.3b.ps new file mode 100644 index 00000000..d0b016e9 --- /dev/null +++ b/doc/psfigures/maint2.3b.ps @@ -0,0 +1,251 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.3b +%%Creator: XCircuit v3.6 rev4 +%%CreationDate: Mon Feb 13 12:33:32 2006 +%%Pages: 1 +%%BoundingBox: 68 68 523 247 +%%DocumentNeededResources: font Helvetica font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 3.3 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--7/13/05 (tim.edwards@multigig.com) +% The Johns Hopkins University (1993-2004) +% MultiGiG, Inc. (2004-present) +% +%%BeginResource: procset XCIRCproc 3.3 0 +% +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/ul { dup type /stringtype eq showflag 1 eq and { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave currentpoint newpath moveto true charpath flattenpath + pathbbox pop exch pop sub grestore } def +/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs + 0 currentpoint pop put} def +/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def +/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt + {currentpoint exch pop moveto exit} {pop} ifelse } for } def +/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt + {currentpoint exch pop moveto exit} {pop} ifelse } for } def +/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def +/hS { qS qS } def +/pspc 0 def +/cf0 { scalefont setfont } bind def +/Kn { dup kY add /kY exch def rmoveto } bind def +/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul + 0.33 mul neg Kn} def +/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul + 0.67 mul Kn } def +/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def +/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def +/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq + { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def} + {fscale0 mul fscale mul cf0} ifelse } def +/ctmk { counttomark dup 2 add -1 roll pop } bind def +/label { gsave translate 0 0 moveto dup scale neg /rotval exch def + /just exch def just 384 and 0 gt {/mshow {pop} def} {/mshow {show} + def} ifelse just 16 and 0 gt {gsave rotval rotate 0 1 dtransform + gsave pagemat setmatrix idtransform exch grestore 1 0 dtransform + gsave pagemat setmatrix idtransform exch grestore dup abs 1e-9 lt + {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse grestore {-1 /rotval + rotval neg def /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse + exch -1e-9 lt {-1 /rotval rotval neg def /just just dup 12 and + 4 ne {12 xor} if def} {1} ifelse scale } if /showflag 0 def + /fspc pspc def /Bline 0 def /Tabs 0 array def /fscale 1.0 def + /kY 0 def gsave dup 1 add copy 0 exch 1 0 dtransform exch atan rotate + {exch dup type /stringtype eq {true charpath flattenpath} {dup type + /arraytype eq {exec} {12 string cvs true charpath flattenpath} ifelse} + ifelse} repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll just + 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub 0.5 + mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch just 4 + and 0 gt {just 8 and 0 gt {exch pop neg fspc sub} {add 0.5 mul neg} + ifelse} {pop neg fspc add} ifelse rotval rotate Kn currentpoint + translate /showflag 1 def /Bline 0 def /Tabs 0 array def /fscale + 1.0 def /kY 0 def {dup type /stringtype eq {mshow} {dup type + /arraytype eq {exec} {12 string cvs mshow} ifelse} ifelse} repeat + grestore } def +/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 10 def label + /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def +/graphic { gsave 4 index cvx exec /DataSource get resetfile translate + 0 0 moveto neg rotate dup scale cvx exec image grestore } def + +/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def +/cRedef {/defColor currentcolor 3 array astore def} def +/begingate {dup type /dicttype ne {1 dict} if begin % default params + dup type /dicttype ne {1 dict} if begin % instanced params + /hlevel hlevel 1 add def /defColor currentcolor sce 3 array + astore def gsave sce translate 0 0 moveto neg rotate dup abs scale + } bind def +/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef + scb end end} bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + gsave style 16 and 0 gt { style 224 and -5 bitshift style 256 and 0 gt { + 7 exch sub 8 div dup 1 exch sub currentrgbcolor 3 array astore + {3 copy mul add 4 1 roll pop} forall pop pop setrgbcolor eofill} + {dup 7 lt {gar exch get ppaint} {pop eofill} ifelse} ifelse} + {style 256 and 0 gt {1 setgray eofill} if} ifelse grestore style 8 and 0 gt + style 512 eq or {newpath} {stroke} ifelse grestore} def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def +/psinsertion {/PSobj save def /showpage {} def /setpagedevice {pop} def bop + rotate translate dup scale} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +%%BeginSetup + +/arrowhead { +% trivial +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +begingate +1.00 270 -16 0 arrowhead +endgate +} def + +/arrow { +% trivial +begingate +1 0.80 0 -40 0 20 2 polygon +1.00 0 0 40 arrowhead +endgate +} def + + +%%EndSetup + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +1.0000 inchscale +2.6000 setlinewidth 1058 -16 translate + +0.753 0.333 0.502 scb +240 1.00 -576 272 -576 528 48 528 48 272 4 polygon +sce +1 1.00 -288 512 -288 592 2 polygon +1 1.00 -240 512 -240 592 2 polygon +1 1.00 -352 576 -304 576 2 polygon +1 1.00 -224 576 -176 576 2 polygon +-1.00 0 -304 576 arrowhead90 +(sep_long) {/Helvetica-Oblique cf} 2 25 0 1.00 -256 608 label +0 1.00 -576 272 -576 528 48 528 48 272 4 polygon +240 1.00 -496 432 -496 496 -288 496 -288 432 4 polygon +240 1.00 -496 304 -496 368 -32 368 -32 304 4 polygon +240 1.00 -240 432 -240 496 -32 496 -32 432 4 polygon +(given) {CR} (separation) {CR} (no size or) {/Helvetica cf} 6 20 0 1.00 144 272 +label +1.00 0 -224 576 arrowhead90 +1 1.00 -496 544 -496 624 2 polygon +1 1.00 -576 544 -576 624 2 polygon +1 1.00 -480 608 -432 608 2 polygon +1.00 0 -480 608 arrowhead90 +1 1.00 -592 528 -736 528 2 polygon +1 1.00 -592 496 -736 496 2 polygon +1 1.00 -16 496 96 496 2 polygon +1 1.00 -16 432 96 432 2 polygon +1 1.00 -32 416 -32 224 2 polygon +1 1.00 -240 416 -240 224 2 polygon +1 1.00 -16 240 32 240 2 polygon +1.00 0 -16 240 arrowhead90 +1 1.00 -256 240 -304 240 2 polygon +-1.00 0 -256 240 arrowhead90 +(size_long) {/Helvetica-Oblique cf} 2 29 0 1.00 -144 240 label +1 1.00 -640 608 -592 608 2 polygon +-1.00 0 -592 608 arrowhead90 +(border_long) {/Helvetica-Oblique cf} 2 25 0 1.00 -544 640 label +(border) {/Helvetica-Oblique cf} 2 23 0 1.00 -752 512 label +1 1.00 -704 544 -704 592 2 polygon +-1.00 90 -704 544 arrowhead90 +1 1.00 -704 480 -704 432 2 polygon +1.00 90 -704 480 arrowhead90 +1 1.00 80 512 80 560 2 polygon +-1.00 90 80 512 arrowhead90 +1 1.00 80 416 80 352 2 polygon +1.00 90 80 416 arrowhead90 +-1.00 300 96 288 arrow +(size) {/Helvetica-Oblique cf} 2 20 0 1.00 96 464 label +1 1.00 -592 432 -640 432 2 polygon +1 1.00 -592 368 -640 368 2 polygon +1 1.00 -624 448 -624 480 2 polygon +-1.00 90 -624 448 arrowhead90 +1 1.00 -624 352 -624 320 2 polygon +1.00 90 -624 352 arrowhead90 +(sep) {/Helvetica-Oblique cf} 2 23 0 1.00 -608 400 label +1.000 1.000 1.000 scb +1 1.00 -240 304 -240 368 2 polygon +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.4.ps b/doc/psfigures/maint2.4.ps new file mode 100644 index 00000000..ecdb1404 --- /dev/null +++ b/doc/psfigures/maint2.4.ps @@ -0,0 +1,188 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.4.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:22:46 2000 +%%Pages: 1 +%%BoundingBox: 68 68 712 297 +%%DocumentNeededResources: font Helvetica +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 1056 334 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.490 0.651 0.980 scb +240 1.00 800 270 800 718 1312 718 1312 270 4 polygon +240 1.00 1504 334 1504 654 1888 654 1888 334 4 polygon +240 1.00 192 334 192 654 320 654 320 334 4 polygon +240 1.00 448 334 448 654 576 654 576 334 4 polygon +sce +0 1.00 192 334 192 654 320 654 320 334 4 polygon +0 1.00 448 334 448 654 576 654 576 334 4 polygon +0 1.00 1504 334 1504 654 1888 654 1888 334 4 polygon +0 1.00 800 270 800 718 1312 718 1312 270 4 polygon +2 1.00 864 334 864 654 992 654 992 334 4 polygon +2 1.00 1120 334 1120 654 1248 654 1248 334 4 polygon +2 1.00 1504 334 1504 654 1632 654 1632 334 4 polygon +2 1.00 1760 334 1760 654 1888 654 1888 334 4 polygon +1 1.00 784 654 704 654 2 polygon +1 1.00 784 718 704 718 2 polygon +1 1.00 736 638 736 590 2 polygon +1 1.00 736 734 736 782 2 polygon +1.00 0 736 654 arrowhead +1.00 -181 736 718 arrowhead +(100) {/Helvetica 1.000 cf} 2 21 0 736 686 label +(\(a\)) {/Helvetica 1.000 cf} 2 21 0 352 206 label +(\(b\)) {/Helvetica 1.000 cf} 2 21 0 1056 206 label +(\(c\)) {/Helvetica 1.000 cf} 2 21 0 1696 206 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.5.ps b/doc/psfigures/maint2.5.ps new file mode 100644 index 00000000..2b887eee --- /dev/null +++ b/doc/psfigures/maint2.5.ps @@ -0,0 +1,181 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.5.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:25:42 2000 +%%Pages: 1 +%%BoundingBox: 68 68 346 316 +%%DocumentNeededResources: font Helvetica +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 691 480 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.745 0.600 0.871 scb +240 1.00 211 192 211 448 403 448 403 192 4 polygon +240 1.00 563 608 563 832 755 832 755 608 4 polygon +sce +1 1.00 211 448 403 448 403 192 3 polygon +1 1.00 563 832 563 608 755 608 3 polygon +1 1.00 419 464 451 496 2 polygon +1 1.00 419 448 627 448 2 polygon +1 1.00 595 496 595 464 2 polygon +1.00 0 595 608 arrowhead +1.00 -181 595 448 arrowhead +1.00 135 403 448 arrowhead +1.00 -46 563 608 arrowhead +1 1.00 595 560 595 592 2 polygon +1 1.00 499 544 547 592 2 polygon +(Manhattan distance) {/Helvetica 1.000 cf} 2 21 0 739 528 label +(Euclidean distance) {/Helvetica 1.000 cf} 2 21 0 355 528 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.6.ps b/doc/psfigures/maint2.6.ps new file mode 100644 index 00000000..76676ebf --- /dev/null +++ b/doc/psfigures/maint2.6.ps @@ -0,0 +1,168 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.6.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:27:49 2000 +%%Pages: 1 +%%BoundingBox: 68 68 436 289 +%%DocumentNeededResources: font Helvetica font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 832 124 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.133 0.545 0.133 scb +240 1.00 192 252 192 700 384 700 384 252 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 960 252 960 700 1152 700 1152 252 4 polygon +240 1.00 384 252 384 700 576 700 576 252 4 polygon +sce +0 1.00 192 252 192 700 384 700 384 252 4 polygon +0 1.00 384 252 384 700 576 700 576 252 4 polygon +0 1.00 960 252 960 700 1152 700 1152 252 4 polygon +(t1) {/Helvetica-Oblique 1.000 cf} 2 29 0 288 220 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 29 0 480 220 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 29 0 1056 220 label +(A) {/Helvetica 1.000 cf} 2 25 0 384 732 label +(B) {/Helvetica 1.000 cf} 2 25 0 1056 732 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.6b.ps b/doc/psfigures/maint2.6b.ps new file mode 100644 index 00000000..119fad33 --- /dev/null +++ b/doc/psfigures/maint2.6b.ps @@ -0,0 +1,237 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.6b.ps +%%Creator: Xcircuit v2.5 +%%CreationDate: Tue Jan 8 13:16:19 2002 +%%Pages: 1 +%%BoundingBox: 68 68 637 323 +%%DocumentNeededResources: font Helvetica font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.4 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--5/16/01 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.4 1 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/ul { dup type /stringtype eq showflag 1 eq and { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave currentpoint newpath moveto true charpath flattenpath + pathbbox pop exch pop sub grestore } def +/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs + 0 currentpoint pop put} def +/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def +/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt + {currentpoint exch pop moveto exit} {pop} ifelse } for } def +/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt + {currentpoint exch pop moveto exit} {pop} ifelse } for } def +/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def +/hS { qS qS } def +/pspc 0 def +/cf0 { scalefont setfont } bind def +/Kn { dup kY add /kY exch def rmoveto } bind def +/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul + 0.33 mul neg Kn} def +/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul + 0.67 mul Kn } def +/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def +/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def +/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq + { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def} + {fscale0 mul fscale mul cf0} ifelse } def +/ctmk { counttomark dup 2 add -1 roll pop } bind def +/label { gsave translate 0 0 moveto dup scale neg /rotval exch def + /just exch def just 16 and 0 gt {gsave rotval rotate 0 1 dtransform + gsave pagemat setmatrix idtransform exch grestore 1 0 dtransform + gsave pagemat setmatrix idtransform exch grestore dup abs 1e-9 lt + {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse grestore {-1 /rotval + rotval neg def /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse + exch -1e-9 lt {-1 /rotval rotval neg def /just just dup 12 and + 4 ne {12 xor} if def} {1} ifelse scale } if /showflag 0 def + /fspc pspc def /Bline 0 def /Tabs 0 array def /fscale 1.0 def + /kY 0 def gsave dup 1 add copy 0 exch 1 0 dtransform exch atan rotate + {exch dup type /stringtype eq {true charpath flattenpath} {exec} + ifelse } repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll just + 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub 0.5 + mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch just 4 + and 0 gt {just 8 and 0 gt {exch pop neg fspc sub} {add 0.5 mul neg} + ifelse} {pop neg fspc add} ifelse rotval rotate Kn currentpoint + translate /showflag 1 def /Bline 0 def /Tabs 0 array def /fscale + 1.0 def /kY 0 def {dup type /stringtype eq {show}{exec} ifelse} + repeat grestore } def +/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 20 def label + /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def +/cRedef {/defColor currentcolor 3 array astore def} def +/begingate { /hlevel hlevel 1 add def /defColor currentcolor sce 3 array + astore def gsave sce translate 0 0 moveto neg rotate dup abs scale + } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef + scb} bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt style 512 eq or { newpath } { stroke } ifelse grestore } def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +% trivial +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +% trivial +begingate +1.00 270 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 1024 186 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.494 0.753 0.933 scb +240 1.00 880 298 880 746 1264 746 1264 298 4 polygon +240 1.00 480 298 480 746 672 746 672 298 4 polygon +240 1.00 1360 298 1360 746 1552 746 1552 298 4 polygon +sce +0 1.00 880 298 880 746 1264 746 1264 298 4 polygon +0 1.00 1360 298 1360 746 1552 746 1552 298 4 polygon +0 1.00 480 298 480 746 672 746 672 298 4 polygon +(t1) {/Helvetica-Oblique cf} 2 29 0 1.00 1072 266 label +(t2) {/Helvetica-Oblique cf} 2 29 0 1.00 1456 266 label +(t2) {/Helvetica-Oblique cf} 2 29 0 1.00 576 266 label +(A) {/Helvetica cf} 2 29 0 1.00 432 218 label +(B) {/Helvetica cf} 2 29 0 1.00 1232 218 label +0.494 0.753 0.933 scb +240 1.00 192 298 192 746 384 746 384 298 4 polygon +sce +0 1.00 192 298 192 746 384 746 384 298 4 polygon +(t1) {/Helvetica-Oblique cf} 2 29 0 1.00 272 266 label +1 1.00 1264 826 1264 762 2 polygon +1 1.00 1424 762 1424 826 2 polygon +1 1.00 880 762 880 826 2 polygon +1 1.00 880 810 1424 810 2 polygon +1.00 0 896 810 arrowhead90 +-1.00 0 1248 810 arrowhead90 +-1.00 0 1408 810 arrowhead90 +1.00 0 1280 810 arrowhead90 +(wwidth) {/Helvetica-Oblique cf} 2 17 0 1.00 1056 826 label +(wdist) {/Helvetica-Oblique cf} 2 17 0 1.00 1344 826 label +1.000 1.000 1.000 scb +1 1.00 1360 746 1424 682 2 polygon +1 1.00 1360 714 1424 650 2 polygon +1 1.00 1360 682 1424 618 2 polygon +1 1.00 1360 650 1424 586 2 polygon +1 1.00 1360 618 1424 554 2 polygon +1 1.00 1360 586 1424 522 2 polygon +1 1.00 1360 554 1424 490 2 polygon +1 1.00 1360 522 1424 458 2 polygon +1 1.00 1360 490 1424 426 2 polygon +1 1.00 1360 458 1424 394 2 polygon +1 1.00 1360 426 1424 362 2 polygon +1 1.00 1360 394 1424 330 2 polygon +1 1.00 1360 362 1424 298 2 polygon +1 1.00 1360 330 1392 298 2 polygon +1 1.00 1392 746 1424 714 2 polygon +sce +1 1.00 1360 794 1360 762 2 polygon +1 1.00 1360 778 1488 778 2 polygon +1.00 0 1440 778 arrowhead90 +1.00 0 1376 778 arrowhead90 +(error area) {/Helvetica cf} 2 20 0 1.00 1504 778 label +1 1.00 480 762 480 826 2 polygon +1 1.00 384 810 480 810 2 polygon +-1.00 0 464 810 arrowhead90 +1.00 0 400 810 arrowhead90 +(dist) {/Helvetica-Oblique cf} 2 17 0 1.00 432 826 label +1 1.00 384 826 384 762 2 polygon +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.7.ps b/doc/psfigures/maint2.7.ps new file mode 100644 index 00000000..fc7e3b00 --- /dev/null +++ b/doc/psfigures/maint2.7.ps @@ -0,0 +1,218 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.7.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:32:42 2000 +%%Pages: 1 +%%BoundingBox: 68 68 412 400 +%%DocumentNeededResources: font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 704 544 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.745 0.600 0.871 scb +240 1.00 832 736 832 1056 1024 1056 1024 736 4 polygon +240 1.00 256 256 256 448 576 448 576 256 4 polygon +240 1.00 256 736 256 1056 448 1056 448 736 4 polygon +240 1.00 704 256 704 448 1024 448 1024 256 4 polygon +sce +0 1.00 256 736 256 1056 448 1056 448 736 4 polygon +0 1.00 832 736 832 1056 1024 1056 1024 736 4 polygon +0 1.00 256 256 256 448 576 448 576 256 4 polygon +0 1.00 704 256 704 448 1024 448 1024 256 4 polygon +1 1.00 192 896 320 896 2 polygon +1 1.00 1088 896 960 896 2 polygon +1 1.00 416 192 416 320 2 polygon +1 1.00 864 512 864 384 2 polygon +1.00 0 416 336 arrowhead +1.00 -181 864 368 arrowhead +1.00 -271 944 896 arrowhead +1.00 270 336 896 arrowhead +(t1) {/Helvetica-Oblique 1.000 cf} 2 25 0 224 928 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 25 0 288 928 label +(t1) {/Helvetica-Oblique 1.000 cf} 2 25 0 1056 928 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 25 0 976 928 label +(t1) {/Helvetica-Oblique 1.000 cf} 2 25 0 896 480 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 25 0 896 400 label +(t1) {/Helvetica-Oblique 1.000 cf} 2 25 0 368 208 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 25 0 368 288 label +(d) {/Helvetica-Oblique 1.000 cf} 2 21 0 352 688 label +1 1.00 256 720 256 672 2 polygon +1 1.00 448 720 448 672 2 polygon +(d) {/Helvetica-Oblique 1.000 cf} 2 21 0 928 688 label +1 1.00 832 720 832 672 2 polygon +1 1.00 1024 720 1024 672 2 polygon +(d) {/Helvetica-Oblique 1.000 cf} 2 21 0 208 352 label +1 1.00 240 448 192 448 2 polygon +1 1.00 240 256 192 256 2 polygon +(d) {/Helvetica-Oblique 1.000 cf} 2 21 0 1072 352 label +1 1.00 1088 448 1040 448 2 polygon +1 1.00 1088 256 1040 256 2 polygon +1 1.00 1072 384 1072 432 2 polygon +1 1.00 1072 320 1072 272 2 polygon +1 1.00 208 384 208 432 2 polygon +1 1.00 208 320 208 272 2 polygon +1 1.00 272 688 320 688 2 polygon +1 1.00 384 688 432 688 2 polygon +1 1.00 848 688 896 688 2 polygon +1 1.00 960 688 1008 688 2 polygon +1.00 0 208 448 arrowhead +1.00 0 1072 448 arrowhead +1.00 -181 1072 256 arrowhead +1.00 -181 208 256 arrowhead +1.00 -271 256 688 arrowhead +1.00 -271 832 688 arrowhead +1.00 -91 1024 688 arrowhead +1.00 -91 448 688 arrowhead +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.8.ps b/doc/psfigures/maint2.8.ps new file mode 100644 index 00000000..fe62246f --- /dev/null +++ b/doc/psfigures/maint2.8.ps @@ -0,0 +1,186 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.8.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:46:16 2000 +%%Pages: 1 +%%BoundingBox: 68 68 604 369 +%%DocumentNeededResources: font Helvetica font Helvetica-Bold +%%+ font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 928 590 offsets +1.0000 inchscale +2.6000 setlinewidth + +1.000 0.000 0.000 scb +240 1.00 832 270 832 590 1184 590 1184 270 4 polygon +240 1.00 1248 654 1248 974 1600 974 1600 654 4 polygon +240 1.00 192 270 192 590 320 590 320 270 4 polygon +sce +0 1.00 320 270 320 590 512 590 512 270 4 polygon +(space) {/Helvetica-Bold 1.000 cf} 2 21 0 416 430 label +(poly) {/Helvetica-Bold 1.000 cf} 2 21 0 256 430 label +(poly) {/Helvetica-Bold 1.000 cf} (= not ) {/Helvetica 1.000 cf} (OKTypes ) {/Helvetica-Oblique 1.000 cf} +6 25 0 416 686 label +1 1.00 416 670 416 558 2 polygon +1.00 -181 416 542 arrowhead +(\(a\)) {/Helvetica 1.000 cf} 2 21 0 416 206 label +0 1.00 832 270 832 590 1184 590 1184 270 4 polygon +0 1.00 1248 654 1248 974 1600 974 1600 654 4 polygon +1 1.00 832 590 832 782 1184 782 1184 590 1376 590 1376 270 1184 270 7 polygon +1 1.00 1600 654 1600 462 1248 462 1248 654 1056 654 1056 974 1248 974 +7 polygon +(poly) {/Helvetica-Bold 1.000 cf} 2 21 0 1424 830 label +(poly) {/Helvetica-Bold 1.000 cf} 2 21 0 992 430 label +(\(b\)) {/Helvetica 1.000 cf} 2 21 0 1216 206 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/maint2.9.ps b/doc/psfigures/maint2.9.ps new file mode 100644 index 00000000..e8e9b0d5 --- /dev/null +++ b/doc/psfigures/maint2.9.ps @@ -0,0 +1,279 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.9.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 12:02:16 2000 +%%Pages: 1 +%%BoundingBox: 68 68 583 490 +%%DocumentNeededResources: font Helvetica font Helvetica-Bold +%%+ font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 1150 782 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.800 0.800 0.800 scb +240 1.00 478 1166 478 1230 542 1230 542 1166 4 polygon +sce +0.898 0.898 0.898 scb +240 1.00 542 1166 542 1294 670 1294 670 1166 4 polygon +sce +0.800 0.800 0.800 scb +240 1.00 542 910 542 1166 670 1166 670 910 4 polygon +240 1.00 1182 1166 1182 1230 1246 1230 1246 1166 4 polygon +sce +1.000 0.000 0.000 scb +240 1.00 1118 910 1118 1166 1246 1166 1246 910 4 polygon +sce +0.898 0.898 0.898 scb +240 1.00 1246 1166 1246 1294 1374 1294 1374 1166 4 polygon +sce +0 1.00 542 910 542 1166 670 1166 670 910 4 polygon +0 1.00 542 1166 542 1294 670 1294 670 1166 4 polygon +0 1.00 478 1166 478 1230 542 1230 542 1166 4 polygon +0 1.00 1246 910 1246 1166 1374 1166 1374 910 4 polygon +0 1.00 1246 1166 1246 1294 1374 1294 1374 1166 4 polygon +0 1.00 1182 1166 1182 1230 1246 1230 1246 1166 4 polygon +(B) {/Helvetica 1.000 cf} 2 21 0 606 1230 label +(A) {/Helvetica 1.000 cf} 2 25 0 606 942 label +(cornerTypes) {/Helvetica-Oblique 1.000 cf} 2 23 0 414 1198 label +(cornerDist) {/Helvetica-Oblique 1.000 cf} 2 20 0 702 1238 label +(OKTypes) {/Helvetica-Oblique 1.000 cf} 2 20 0 702 1102 label +(t1) {/Helvetica-Oblique 1.000 cf} 2 21 0 510 1006 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 21 0 574 1006 label +1 1.00 478 1038 606 1038 2 polygon +1 1.00 638 1102 686 1102 2 polygon +1 1.00 702 1118 638 1182 2 polygon +1 1.00 718 1278 718 1254 2 polygon +1 1.00 718 1214 718 1182 2 polygon +1 1.00 430 1198 510 1198 2 polygon +1 1.00 558 878 590 878 2 polygon +1 1.00 622 878 654 878 2 polygon +1 1.00 542 894 542 846 2 polygon +1 1.00 670 894 670 846 2 polygon +1.00 0 718 1294 arrowhead +1.00 -181 718 1166 arrowhead +1.00 -91 526 1198 arrowhead +1.00 -91 622 1038 arrowhead +1.00 -91 670 878 arrowhead +1.00 90 542 878 arrowhead +1.00 90 622 1102 arrowhead +1.00 45 622 1198 arrowhead +(d) {/Helvetica-Oblique 1.000 cf} 2 21 0 602 878 label +(\(a\)) {/Helvetica 1.000 cf} 2 21 0 606 798 label +1 1.00 1422 1210 1422 1182 2 polygon +1.00 -181 1422 1166 arrowhead +1 1.00 1422 1278 1422 1254 2 polygon +1.00 0 1422 1294 arrowhead +1 1.00 1406 1118 1342 1182 2 polygon +1.00 45 1326 1198 arrowhead +1 1.00 1342 1102 1390 1102 2 polygon +1.00 90 1326 1102 arrowhead +1 1.00 1182 1038 1310 1038 2 polygon +1.00 -91 1326 1038 arrowhead +1 1.00 1326 878 1358 878 2 polygon +1 1.00 1374 894 1374 846 2 polygon +1.00 -91 1374 878 arrowhead +1 1.00 1262 878 1294 878 2 polygon +1 1.00 1246 894 1246 846 2 polygon +1.00 90 1246 878 arrowhead +(\(b\)) {/Helvetica 1.000 cf} 2 21 0 1310 798 label +1 1.00 1134 1198 1214 1198 2 polygon +1.00 -91 1230 1198 arrowhead +1 1.00 686 1294 734 1294 2 polygon +1 1.00 686 1166 734 1166 2 polygon +1 1.00 1390 1294 1438 1294 2 polygon +1 1.00 1390 1166 1438 1166 2 polygon +(poly) {/Helvetica-Bold 1.000 cf} (not) {/Helvetica 1.000 cf} 4 23 0 1118 1198 label +(poly) {/Helvetica-Bold 1.000 cf} (not) {/Helvetica 1.000 cf} 4 20 0 1422 1102 label +(2) {/Helvetica 1.000 cf} 2 21 0 1310 878 label +(2) {/Helvetica 1.000 cf} 2 21 0 1422 1234 label +(poly) {/Helvetica-Bold 1.000 cf} 2 31 0 1214 1022 label +(space) {/Helvetica-Bold 1.000 cf} 2 28 0 1262 1022 label +1.000 0.000 0.000 scb +240 1.00 414 398 414 590 542 590 542 398 4 polygon +sce +0.800 0.800 0.800 scb +240 1.00 542 270 542 718 670 718 670 270 4 polygon +sce +0 1.00 542 270 542 718 670 718 670 270 4 polygon +(poly) {/Helvetica-Bold 1.000 cf} 2 25 0 494 510 label +(poly) {/Helvetica-Bold 1.000 cf} (not) {/Helvetica 1.000 cf} 4 20 0 734 462 label +1 1.00 718 462 638 462 2 polygon +1 1.00 494 494 574 494 2 polygon +1.00 0 638 462 arrowhead90 +1.00 -1 574 494 arrowhead90 +1.000 0.000 0.000 scb +240 1.00 1022 398 1022 590 1150 590 1150 398 4 polygon +240 1.00 1022 590 1022 718 1374 718 1374 590 4 polygon +sce +0.800 0.800 0.800 scb +240 1.00 1150 270 1150 590 1278 590 1278 270 4 polygon +sce +0 1.00 1150 270 1150 590 1278 590 1278 270 4 polygon +(poly) {/Helvetica-Bold 1.000 cf} (not) {/Helvetica 1.000 cf} 4 20 0 1342 462 label +1 1.00 1326 462 1246 462 2 polygon +1.00 0 1246 462 arrowhead90 +(poly) {/Helvetica-Bold 1.000 cf} 2 25 0 1182 638 label +1 1.00 1102 510 1182 510 2 polygon +1.00 -1 1182 510 arrowhead90 +(\(c\)) {/Helvetica 1.000 cf} 2 21 0 542 206 label +(\(d\)) {/Helvetica 1.000 cf} 2 21 0 1198 206 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tut2.1.ps b/doc/psfigures/tut2.1.ps new file mode 100644 index 00000000..8b55caa7 --- /dev/null +++ b/doc/psfigures/tut2.1.ps @@ -0,0 +1,376 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 72 72 540 560 +%%DocumentNeededResources: font /Helveticafont /HelveticaBold +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from magic plot +% Version: 1.0 +% written by Tim Edwards 4/05/00 JHU Applied Physics Laboratory +% +%%BeginResource: procset MAGICproc 1.0 1 +% supporting definitions + +/MAGICsave save def + +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/minit { /nChars matrix defaultmatrix 0 get abs 72 8.5 mul mul 64 div ceiling + cvi def 1 1 dtransform abs dup 1 exch div /onePix exch def + dup /resY exch def 1 exch div /iresY exch def + abs dup /resX exch def 1 exch div /iresX exch def + /bX 64 iresX mul def /bY 64 iresY mul def + /pattFont StipplePattern definefont pop + /patterns /pattFont findfont [iresX 64 mul 0 0 iresY 64 mul 0 0] makefont def + /ca nChars 1 add string def + } def +/StipplePattern 45 dict def +StipplePattern begin + /FontType 3 def + /FontMatrix [1 0 0 1 0 0] def + /FontBBox [0 0 1 1] def + /Encoding 256 array def + /PattName (P0) def + /tmpStr 1 string def + /NoPatt {<00>} def + 0 1 255 { Encoding exch /NoPatt put } for + /BuildChar { + 1 0 0 0 1 1 setcachedevice exch begin Encoding exch get load + 64 64 true [64 0 0 64 0 0] 5 -1 roll imagemask end } def +end +/dp { StipplePattern begin dup 30 tmpStr cvrs PattName exch 1 exch + putinterval PattName cvn dup Encoding exch 4 -1 roll exch put exch + store end } def +/sf { findfont exch scalefont setfont } bind def +/sp { patterns setfont 2 setlinewidth } def +/lb { gsave translate 0 0 moveto /just exch def gsave dup true charpath + flattenpath pathbbox grestore exch 4 -1 roll exch sub 3 1 roll sub + just 4 and 0 gt {just 8 and 0 eq {0.5 mul} if}{pop 0} ifelse exch + just 1 and 0 gt {just 2 and 0 eq {0.5 mul} if}{pop 0} ifelse exch + rmoveto show grestore } def +/sl { 0 1 nChars { exch dup 3 1 roll ca 3 1 roll put } for pop } def +/sc { setcmykcolor } bind def +/l1 { onePix setlinewidth } def +/l2 { onePix 2 mul setlinewidth } def +/l3 { onePix 3 mul setlinewidth } def +/ml { moveto lineto stroke } bind def +/vl { moveto 0 exch rlineto stroke } bind def +/hl { moveto 0 rlineto stroke } bind def +/mr { rectstroke } bind def +/mx { 4 copy rectstroke 4 -1 roll 4 -1 roll 4 copy moveto rlineto stroke + 3 -1 roll dup neg 4 1 roll add moveto rlineto stroke } bind def +/pl { gsave translate /d exch def 0 d neg moveto 0 d lineto stroke + d neg 0 moveto d 0 lineto stroke grestore } bind def +/fb {/h exch def /w exch def /y exch def /x exch def gsave newpath + x y moveto w y lineto w h lineto x h lineto closepath clip + x resX mul cvi 63 not and dup iresX mul exch + w resX mul sub abs 63 add cvi 64 idiv /w exch def + y resY mul cvi 63 not and dup iresY mul exch + h resY mul sub abs 63 add cvi 64 idiv /h exch def + /ch ca 0 w getinterval def + moveto h { ch gsave show grestore 0 bY rmoveto } repeat grestore } def + +/f1 { 1.440 /Helvetica sf } def +/f2 { 0.960 /HelveticaBold sf } def +/f3 { 0.640 /Helvetica sf } def +/col17 {0.090 0.686 0.718 0.000 sc} bind def +/col16 {0.435 0.592 0.957 0.000 sc} bind def +/col15 {0.749 0.498 0.247 0.000 sc} bind def +/col14 {0.000 0.000 0.000 255.000 sc} bind def +/col13 {0.373 0.875 0.247 0.000 sc} bind def +/col12 {0.749 0.498 0.000 0.000 sc} bind def +/col11 {0.000 0.000 1.000 0.000 sc} bind def +/col10 {0.000 1.000 1.000 0.000 sc} bind def +/col9 {0.875 0.184 0.875 0.000 sc} bind def +/col8 {0.000 0.000 0.000 127.000 sc} bind def +/col7 {1.000 0.247 1.000 0.000 sc} bind def +/col6 {0.247 0.373 0.749 0.000 sc} bind def +/col5 {0.122 0.435 1.000 0.000 sc} bind def +/col4 {0.122 0.435 0.122 0.000 sc} bind def +/col3 {0.000 0.000 0.000 192.000 sc} bind def +/col2 {0.875 0.122 0.875 0.000 sc} bind def +/col1 {0.184 0.373 0.435 0.000 sc} bind def +{<000000000000000000000000000000003333333333333333333333333333333300000000000000000000000000000000cccccccccccccccccccccccccccccccc>} 13 dp +{<00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>} 12 dp +{<010000800100008002000040020000400c0000300c000030f000000ff000000f000ff000000ff00000300c0000300c0000400200004002000080010000800100>} 11 dp +{} 10 dp +{<18181818181818183c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c18181818181818188181818181818181c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c38181818181818181>} 9 dp +{<18181818181818180c0c0c0c0c0c0c0c060606060606060603030303030303038181818181818181c0c0c0c0c0c0c0c060606060606060603030303030303030>} 8 dp +{<181818181818181830303030303030306060606060606060c0c0c0c0c0c0c0c08181818181818181030303030303030306060606060606060c0c0c0c0c0c0c0c>} 7 dp +{<07070707070707070e0e0e0e0e0e0e0e1c1c1c1c1c1c1c1c38383838383838387070707070707070e0e0e0e0e0e0e0e0c1c1c1c1c1c1c1c18383838383838383>} 6 dp +{} 5 dp +{<00000000000000000000000000000000c0c0c0c0c0c0c0c00000000000000000000000000000000000000000000000000c0c0c0c0c0c0c0c0000000000000000>} 4 dp +{<0003000300030003000c000c000c000c003000300030003000c000c000c000c003000300030003000c000c000c000c003000300030003000c000c000c000c000>} 3 dp +{} 2 dp +{} 1 dp +%%EndResource +%%EndProlog + +%%Page: 1 1 +/pgsave save def bop +% 0 0 offsets +72 85 translate +12.500 12.500 scale +minit +0 0 26 37 gsave rectclip +l2 +sp + +col2 +4 sl +col1 +4 sl +col9 +5 sl +l1 +4 21 16 hl +4 21 16 vl +4 21 20 hl +21 16 25 20 fb +4 25 16 vl +1 8 10 hl +4 5 10 vl +4 5 14 hl +3 9 11 vl +5 10 9 14 fb +4 9 10 vl +4 21 11 hl +4 21 11 vl +1 21 14 vl +4 21 15 hl +% 21 11 25 15 fb +4 25 11 vl +3 5 8 hl +6 5 8 vl +5 8 8 10 fb +2 8 8 vl +2 5 4 vl +3 5 6 hl +1 8 5 vl +5 4 8 6 fb +2 8 4 vl +4 5 0 hl +6 5 0 vl +1 8 4 hl +3 9 1 vl +5 0 9 4 fb +4 9 0 vl +col1 +5 sl +1 8 33 hl +4 5 33 vl +4 5 37 hl +5 33 9 37 fb +4 9 33 vl +3 5 32 hl +5 5 32 vl +5 32 8 33 fb +1 8 32 vl +1 5 29 vl +3 5 30 hl +5 29 8 30 fb +1 8 29 vl +4 5 25 hl +5 5 25 vl +1 8 29 hl +3 9 26 vl +5 25 9 29 fb +4 9 25 vl +4 21 21 hl +4 21 21 vl +4 21 25 hl +21 21 25 25 fb +4 25 21 vl +col17 +5 sl +3 5 30 hl +2 5 30 vl +3 5 32 hl +5 30 8 32 fb +2 8 30 vl +4 21 6 hl +4 21 6 vl +2 21 8 vl +4 21 10 hl +21 6 25 10 fb +4 25 6 vl +col16 +5 sl +3 5 6 hl +2 5 6 vl +3 5 8 hl +5 6 8 8 fb +2 8 6 vl +4 21 1 hl +4 21 1 vl +1 21 4 vl +4 21 5 hl +21 1 25 5 fb +4 25 1 vl +col10 +5 sl +5 0 30 hl +2 0 30 vl +5 0 32 hl +0 30 5 32 fb +2 5 30 vl +4 8 30 hl +2 8 30 vl +4 8 32 hl +8 30 12 32 fb +2 12 30 vl +4 21 26 hl +4 21 26 vl +1 21 29 vl +4 21 30 hl +21 26 25 30 fb +4 25 26 vl +5 0 6 hl +2 0 6 vl +5 0 8 hl +0 6 5 8 fb +2 5 6 vl +3 8 6 hl +2 8 6 vl +3 8 8 hl +8 6 11 8 fb +2 11 6 vl +col1 +7 sl +3 5 30 hl +2 5 30 vl +3 5 32 hl +5 30 8 32 fb +2 8 30 vl +4 21 6 hl +4 21 6 vl +2 21 8 vl +4 21 10 hl +21 6 25 10 fb +4 25 6 vl +col9 +8 sl +3 5 6 hl +2 5 6 vl +3 5 8 hl +5 6 8 8 fb +2 8 6 vl +4 21 1 hl +4 21 1 vl +1 21 4 vl +4 21 5 hl +21 1 25 5 fb +4 25 1 vl +col6 +1 sl +col7 +1 sl +col11 +7 sl +col12 +9 sl +4 5 33 hl +4 5 33 vl +4 5 37 hl +5 33 9 37 fb +4 9 33 vl +4 5 25 hl +5 5 25 vl +4 5 29 hl +3 9 26 vl +5 25 9 29 fb +4 9 25 vl +4 5 10 hl +4 5 10 vl +4 5 14 hl +3 9 11 vl +5 10 9 14 fb +4 9 10 vl +4 21 11 hl +4 21 11 vl +1 21 14 vl +4 21 15 hl +% 21 11 25 15 fb +4 25 11 vl +4 5 0 hl +6 5 0 vl +4 5 4 hl +3 9 1 vl +5 0 9 4 fb +4 9 0 vl +5 0 34 hl +3 0 34 vl +5 0 37 hl +0 34 5 37 fb +3 5 34 vl +5 9 34 hl +3 9 34 vl +5 9 37 hl +2 14 35 vl +9 34 14 37 fb +3 14 34 vl +4 21 31 hl +4 21 31 vl +2 21 33 vl +1 21 34 vl +4 21 35 hl +21 31 25 35 fb +4 25 31 vl +7 5 22 vl +4 5 25 hl +5 22 9 25 fb +7 9 22 vl +5 9 18 hl +11 5 18 vl +5 9 22 hl +5 18 14 22 fb +4 14 18 vl +4 5 14 hl +15 5 14 vl +3 9 15 vl +5 14 9 18 fb +4 9 14 vl +5 0 0 hl +3 0 0 vl +5 0 3 hl +0 0 5 3 fb +4 5 0 vl +5 9 0 hl +4 9 0 vl +5 9 3 hl +9 0 14 3 fb +3 14 0 vl +col13 +10 sl +col14 +13 sl +col14 +11 sl +col14 +col14 +l2 +5 33 4 4 mx +5 25 4 4 mx +5 10 4 4 mx +21 11 4 4 mx +5 0 4 4 mx +21 31 4 4 mr +21 26 4 4 mr +21 21 4 4 mr +21 16 4 4 mr +21 11 4 4 mr +21 6 4 4 mr +21 1 4 4 mr +grestore +f1 0 setgray +(Metal) 4 26 33 lb +(Polysilicon) 4 26 28 lb +(P-Diffusion) 4 26 23 lb +(N-Diffusion) 4 26 18 lb +(Contact) 4 26 13 lb +(P-Fet) 4 26 8 lb +(N-Fet) 4 26 3 lb +pgsave restore showpage + +%%Trailer +MAGICsave restore +%%EOF diff --git a/doc/psfigures/tut2.2.ps b/doc/psfigures/tut2.2.ps new file mode 100644 index 00000000..278ac292 --- /dev/null +++ b/doc/psfigures/tut2.2.ps @@ -0,0 +1,242 @@ +%!PS-Adobe-2.0 EPSF-1.2 +%%Title: tut2.2.ps +%%CreationDate: +%%DocumentFonts: Helvetica +%%Pages: 1 +%%BoundingBox: 190 28 420 764 +%%EndComments + +/INIT { + 72 exch div dup dup scale + div exch findfont exch scalefont /TxFont exch def + /BoxOutline exch def /#copies exch def + TxFont dup /FontBBox get exch /FontMatrix get + exch aload pop 4 index transform /bbhi exch def pop 3 -1 roll + transform /bblow exch def /bbx exch def /bbhi bbhi bblow sub def + /nChars matrix defaultmatrix 0 get abs 72 8.5 mul mul 64 div ceiling cvi def + 1 1 dtransform abs dup 1 exch div /onePix exch def + dup /resY exch def 1 exch div /iresY exch def + abs dup /resX exch def 1 exch div /iresX exch def + /bX 64 iresX mul def /bY 64 iresY mul def + /pattFont StipplePattern definefont pop + /patterns /pattFont findfont [iresX 64 mul 0 0 iresY 64 mul 0 0] makefont def + /CA nChars 1 add string def +} def + +/StipplePattern 45 dict def + +StipplePattern begin + /FontType 3 def + /FontMatrix [1 0 0 1 0 0] def + /FontBBox [0 0 1 1] def + /Encoding 256 array def + /PattName (P0) def + /tmpStr 1 string def + /NoPatt {<00>} def + + 0 1 255 { Encoding exch /NoPatt put } for + + /BuildChar { + 1 0 0 0 1 1 setcachedevice exch begin Encoding exch get load + 64 64 true [64 0 0 64 0 0] 5 -1 roll imagemask end + } def +end + +/DefPatt { + StipplePattern begin + dup 30 tmpStr cvrs PattName exch 1 exch putinterval PattName cvn dup + Encoding exch 4 -1 roll exch put exch store + end +} def + +/HEADER { 4 onePix mul add moveto show } def + +/SL { 0 1 nChars { exch dup 3 1 roll CA 3 1 roll put } for pop } def +/SC { 0 1 nChars { exch dup 3 1 roll CA 3 1 roll put } for 4 mul + colors exch 4 getinterval aload pop setcmykcolor } def + +/SP { patterns setfont 2 setlinewidth } def + +/ST { TxFont setfont onePix 2 mul setlinewidth } def + +/V { newpath moveto 0 exch rlineto stroke } def + +/H { newpath moveto 0 rlineto stroke } def + +/B { + /h exch def /w exch def + /y exch def /x exch def + + gsave + newpath x y moveto w y lineto w h lineto x h lineto closepath clip + x resX mul cvi 63 not and dup iresX mul exch + w resX mul sub abs 63 add cvi 64 idiv /w exch def + y resY mul cvi 63 not and dup iresY mul exch + h resY mul sub abs 63 add cvi 64 idiv /h exch def + /CH CA 0 w getinterval def + moveto h { CH gsave show grestore 0 bY rmoveto } repeat + grestore +} def + +/L { + gsave newpath dup bblow add 2 index bbx add exch moveto + 0 bbhi rlineto + 2 index stringwidth pop bbx abs 2 mul add 0 rlineto + 0 bbhi neg rlineto + closepath 1.0 setgray fill grestore moveto show +} def + +/BB { + /h exch def /w exch def + /y exch def /x exch def + grestore + gsave + newpath + x y moveto + w y lineto + w h lineto + x h lineto + closepath + BoxOutline 1 eq { gsave stroke grestore } if clip +} def + +/BS { + 4 copy BB exch pop exch pop exch bbhi add exch bbhi sub onePix sub L +} def + +/MSAV { /Mstat save def } def +/MRES { Mstat restore } def + +%%EndProlog +%%Page: 1 1 + +{<000000000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0>} 0 DefPatt +{<000000000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0>} 1 DefPatt +{<00000000000000000c0c0c0c0c0c0c0c000000000000000000000000000000000000000000000000c0c0c0c0c0c0c0c000000000000000000000000000000000>} 5 DefPatt +{<00000000000000000c0c0c0c0c0c0c0c000000000000000000000000000000000000000000000000c0c0c0c0c0c0c0c000000000000000000000000000000000>} 6 DefPatt +{} 8 DefPatt +{<8383838383838383c1c1c1c1c1c1c1c1e0e0e0e0e0e0e0e0707070707070707038383838383838381c1c1c1c1c1c1c1c0e0e0e0e0e0e0e0e0707070707070707>} 9 DefPatt +{<8181818181818181c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3818181818181818118181818181818183c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c1818181818181818>} 11 DefPatt +{} 16 DefPatt +/colors [0.18 0.37 0.43 0.00 0.87 0.12 0.87 0.00 0.00 0.00 0.00 0.75 0.12 0.43 0.12 0.00 0.12 0.43 1.00 0.00 0.25 0.37 0.75 0.00 1.00 0.25 1.00 0.00 0.00 0.00 0.00 0.50 0.87 0.18 0.87 0.00 0.00 1.00 1.00 0.00 0.00 0.00 1.00 0.00 0.75 0.50 0.00 0.00 0.37 0.87 0.25 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 0.75 0.75 0.50 0.25 0.00 ] def +1 1 /Helvetica 10.0 300.000000 INIT +% ST (tutcell.cif Scale: 0.212766 \(5404X\) Size: 14 x 47 microns ) 828 3150 HEADER +SP 828 150 translate +0 SC +1532 0 0 V +894 0 0 H +1532 894 0 V +894 0 1532 H +0 0 894 1532 B +1 SC +1404 0 1596 V +894 0 1596 H +1404 894 1596 V +894 0 3000 H +0 1596 894 3000 B +5 SC +1022 191 1787 V +511 191 1787 H +1022 702 1787 V +511 191 2809 H +191 1787 702 2809 B +6 SC +1149 191 191 V +511 191 191 H +1149 702 191 V +511 191 1340 H +191 191 702 1340 B +8 SC +894 319 319 V +766 319 1915 V +383 511 574 V +319 319 511 1213 B +256 511 2170 V +319 1915 511 2681 B +255 319 319 H +255 574 319 V +63 511 574 H +511 319 574 574 B +63 511 957 H +256 574 957 V +255 319 1213 H +511 957 574 1213 B +255 319 1915 H +255 574 1915 V +63 511 2170 H +511 1915 574 2170 B +63 511 2426 H +255 574 2426 V +255 319 2681 H +511 2426 574 2681 B +9 SC +128 0 702 V +128 0 2234 V +702 0 702 H +128 702 702 V +702 0 830 H +0 702 702 830 B +766 0 2234 H +128 766 2234 V +766 0 2362 H +0 2234 766 2362 B +11 SC +192 0 319 V +192 0 2489 V +319 0 511 H +0 319 319 511 B +63 319 511 V +1213 319 957 V +63 319 2426 V +319 0 2489 H +0 2489 319 2681 B +63 574 511 V +255 319 574 H +319 319 574 574 B +255 319 957 H +511 574 957 V +447 574 1723 V +255 319 2170 H +319 957 574 2170 B +255 319 2426 H +63 574 2426 V +319 2426 574 2681 B +894 0 319 H +192 894 319 V +320 574 511 H +574 319 894 511 B +320 574 1468 H +255 894 1468 V +320 574 1723 H +574 1468 894 1723 B +320 574 2489 H +192 894 2489 V +894 0 2681 H +574 2489 894 2681 B +16 SC +128 383 383 V +128 383 1021 V +127 383 1979 V +128 383 2489 V +128 383 383 H +128 511 383 V +128 383 511 H +383 383 511 511 B +128 383 1021 H +128 511 1021 V +128 383 1149 H +383 1021 511 1149 B +128 383 1979 H +127 511 1979 V +128 383 2106 H +383 1979 511 2106 B +128 383 2489 H +128 511 2489 V +128 383 2617 H +383 2489 511 2617 B +ST gsave +% (tutcell1) 0 0 894 3000 BS +% 0 0 894 3000 BB +grestore showpage + +%%Trailer diff --git a/doc/psfigures/tut7.1.ps b/doc/psfigures/tut7.1.ps new file mode 100644 index 00000000..b864ca8e --- /dev/null +++ b/doc/psfigures/tut7.1.ps @@ -0,0 +1,196 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: ../psfiles/tut7.1.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 13:29:20 2000 +%%Pages: 1 +%%BoundingBox: 68 68 364 190 +%%DocumentNeededResources: font Helvetica font Times-Roman +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrow { +% -12 -40 24 80 bbox +begingate +1 0.80 0 -40 0 20 2 polygon +1.00 0 0 40 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 480 256 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.800 0.800 0.800 scb +240 1.00 192 192 192 496 960 496 960 192 4 polygon +sce +0.490 0.651 0.980 scb +240 1.00 672 224 672 320 800 320 800 224 4 polygon +240 1.00 384 192 384 384 512 384 512 192 4 polygon +sce +1 1.00 256 192 256 384 800 384 800 192 4 polygon +1.000 1.000 0.000 scb +(Input) {/Helvetica 1.000 cf} 2 29 0 448 376 label +sce +(Cell Boundary) {/Times-Roman 1.000 cf} 2 27 0 848 444 label +1.000 1.000 0.000 scb +(Output) {/Helvetica 1.000 cf} 2 20 0 808 272 label +sce +1 1.00 672 224 800 224 2 polygon +1 1.00 672 320 800 320 2 polygon +1 1.00 512 384 512 192 2 polygon +1 1.00 384 384 384 192 2 polygon +1.000 1.000 0.000 scb +1 1.00 800 224 800 320 2 polygon +0 1.00 384 320 384 384 512 384 512 320 4 polygon +sce +1.00 135 580 412 arrow +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tut7.2.ps b/doc/psfigures/tut7.2.ps new file mode 100644 index 00000000..5ea114cf --- /dev/null +++ b/doc/psfigures/tut7.2.ps @@ -0,0 +1,258 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tut7.2.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 13:50:28 2000 +%%Pages: 1 +%%BoundingBox: 68 68 535 385 +%%DocumentNeededResources: font Helvetica font Times-Italic +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 1117 536 offsets +% 32.00 8.00 gridspace +1.0000 inchscale +2.6000 setlinewidth + +0.545 0.137 0.137 scb +240 1.00 317 192 317 1016 1149 1016 1149 192 4 polygon +sce +0.804 0.000 0.804 scb +240 1.00 333 208 333 968 1133 968 1133 208 4 polygon +sce +1.000 0.647 0.000 scb +240 1.00 749 640 749 704 973 704 973 640 4 polygon +sce +0.898 0.898 0.898 scb +240 1.00 493 648 493 792 637 792 637 648 4 polygon +sce +0.824 0.706 0.549 scb +240 1.00 493 808 493 872 973 872 973 808 4 polygon +240 1.00 749 728 749 792 845 792 845 728 4 polygon +240 1.00 877 728 877 792 973 792 973 728 4 polygon +sce +0.753 1.000 0.753 scb +240 1.00 493 480 493 544 973 544 973 480 4 polygon +sce +0.490 0.651 0.980 scb +240 1.00 749 400 749 464 973 464 973 400 4 polygon +sce +1.000 0.502 0.502 scb +240 1.00 749 320 749 384 973 384 973 320 4 polygon +sce +1.000 1.000 0.753 scb +240 1.00 749 240 749 304 973 304 973 240 4 polygon +sce +0.800 0.800 0.800 scb +240 1.00 493 240 493 304 717 304 717 240 4 polygon +sce +1.000 0.753 0.753 scb +240 1.00 493 320 493 384 717 384 717 320 4 polygon +sce +0.753 1.000 1.000 scb +240 1.00 493 400 493 464 717 464 717 400 4 polygon +sce +1.000 1.000 1.000 scb +(NETLIST MENU) {/Helvetica 0.800 cf} 2 25 0 733 984 label +(Label) {/Helvetica 1.000 cf} 2 25 0 733 904 label +sce +(BusBit13) {/Helvetica 1.000 cf} 2 21 0 733 840 label +0 1.00 317 192 317 1016 1149 1016 1149 192 4 polygon +0 1.00 333 208 333 968 1133 968 1133 208 4 polygon +0 1.00 493 808 493 872 973 872 973 808 4 polygon +0 1.00 877 728 877 792 973 792 973 728 4 polygon +0 1.00 749 728 749 792 845 792 845 728 4 polygon +0 1.00 749 640 749 704 973 704 973 640 4 polygon +0 1.00 493 480 493 544 973 544 973 480 4 polygon +1.000 1.000 1.000 scb +(Netlist) {/Helvetica 1.000 cf} 2 25 0 733 584 label +sce +(Find) {/Helvetica 1.000 cf} 2 21 0 853 672 label +(13) {/Helvetica 1.000 cf} 2 21 0 797 760 label +0 1.00 493 648 493 792 637 792 637 648 4 polygon +1 1.00 541 648 541 792 2 polygon +1 1.00 589 792 589 648 2 polygon +1 1.00 493 744 637 744 2 polygon +1 1.00 493 696 637 696 2 polygon +1 1.00 557 720 573 720 2 polygon +1 1.00 565 728 565 712 2 polygon +(Placer) {/Times-Italic 1.000 cf} 2 23 0 293 728 label +(Current Netlist) {/Times-Italic 1.000 cf} 2 20 0 1165 512 label +(Pumps) {/Times-Italic 1.000 cf} 2 20 0 1165 760 label +(Current Text) {/Times-Italic 1.000 cf} 2 20 0 1165 840 label +0 1.00 493 400 493 464 717 464 717 400 4 polygon +0 1.00 749 400 749 464 973 464 973 400 4 polygon +0 1.00 493 320 493 384 717 384 717 320 4 polygon +0 1.00 749 320 749 384 973 384 973 320 4 polygon +0 1.00 493 240 493 304 717 304 717 240 4 polygon +0 1.00 749 240 749 304 973 304 973 240 4 polygon +(Print) {/Helvetica 1.000 cf} 2 21 0 861 432 label +(Cleanup) {/Helvetica 1.000 cf} 2 21 0 861 352 label +(Show) {/Helvetica 1.000 cf} 2 21 0 861 272 label +(No Net) {/Helvetica 1.000 cf} 2 21 0 605 272 label +(Terms) {/Helvetica 1.000 cf} 2 21 0 605 352 label +(Verify) {/Helvetica 1.000 cf} 2 21 0 605 432 label +1.00 0 989 840 arrowhead90 +1.00 0 989 760 arrowhead90 +1.00 0 989 512 arrowhead90 +1.00 -1 477 720 arrowhead90 +1 1.00 989 840 1165 840 2 polygon +1 1.00 989 760 1165 760 2 polygon +1 1.00 989 512 1165 512 2 polygon +1 1.00 469 720 301 720 2 polygon +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tut7.3.ps b/doc/psfigures/tut7.3.ps new file mode 100644 index 00000000..a8f2dc71 --- /dev/null +++ b/doc/psfigures/tut7.3.ps @@ -0,0 +1,185 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: ../psfiles/tut7.3.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 13:21:10 2000 +%%Pages: 1 +%%BoundingBox: 68 68 304 304 +%%DocumentNeededResources: +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/mgrid { +% -304 -304 608 608 bbox +begingate +1 1.00 -256 304 -256 -304 2 polygon +1 1.00 -128 304 -128 -304 2 polygon +1 1.00 -304 224 304 224 2 polygon +1 1.00 -304 64 304 64 2 polygon +1 1.00 0 304 0 -304 2 polygon +1 1.00 256 304 256 -304 2 polygon +1 1.00 128 304 128 -304 2 polygon +1 1.00 -304 -256 304 -256 2 polygon +1 1.00 -304 -96 304 -96 2 polygon +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 848 560 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.490 0.651 0.980 scb +240 1.00 240 400 688 400 688 768 624 768 624 464 240 464 6 polygon +sce +0.745 0.600 0.871 scb +240 1.00 496 224 496 384 560 384 560 224 4 polygon +sce +0 1.00 496 224 496 384 560 384 560 224 4 polygon +0 1.00 240 400 688 400 688 768 624 768 624 464 240 464 6 polygon +0.616 0.624 0.925 scb +240 1.00 480 384 480 480 576 480 576 384 4 polygon +sce +0 1.00 480 384 480 480 576 480 576 384 4 polygon +1 1.00 480 480 576 384 2 polygon +1 1.00 576 480 480 384 2 polygon +0.800 0.800 0.800 scb +1.00 0 496 496 mgrid +sce +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tut8.1.ps b/doc/psfigures/tut8.1.ps new file mode 100644 index 00000000..f625d279 --- /dev/null +++ b/doc/psfigures/tut8.1.ps @@ -0,0 +1,244 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tut8.1 +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 14:46:45 2000 +%%Pages: 1 +%%BoundingBox: 68 68 246 247 +%%DocumentNeededResources: font Times-Roman font Times-Bold font Times-Italic +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/resistor { +% -14 -64 28 128 bbox +begingate +% fundamental +1 1.00 0 64 0 36 2 polygon +1 1.00 0 -64 0 -36 2 polygon +1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon +1.000 0.000 0.000 scb +(r.1) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel +(r.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel +sce +(spice:R%i %pr.1 %pr.2 1.0K) {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel +(sim:r %pr.1 %pr.2) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel +endgate +} def + +/capacitor { +% -32 -64 64 128 bbox +begingate +% fundamental +1 1.00 0 -64 0 -6 2 polygon +1 1.00 0 64 0 6 2 polygon +1 1.00 -32 6 32 6 2 polygon +1 1.00 -32 -6 32 -6 2 polygon +1.000 0.000 0.000 scb +(c.1) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel +(c.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel +sce +(spice:C%i %pc.1 %pc.2 1.0P) {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel +(sim:c %pc.1 %pc.2) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel +endgate +} def + +/circle { +% -6 -12 28 24 bbox +begingate +1 1.00 16 0 6 0.00 360.00 xcarc +1 1.00 0 0 10 0 2 polygon +1.000 0.000 0.000 scb +(out) {/Times-Roman 1.000 cf} 2 4 0 16 0 pinlabel +(out) {/Times-Roman 1.000 cf} 2 7 0 0 0 pinlabel +sce +endgate +} def + +/gnd { +% -32 -60 64 68 bbox +begingate +1 1.00 0 0 0 -32 2 polygon +1 1.00 -32 -32 32 -32 2 polygon +1 1.00 -18 -46 18 -46 2 polygon +1 1.00 -4 -60 4 -60 2 polygon +1.000 0.000 0.000 scb +(GND) {/Times-Roman 1.000 cf} 2 1 0 0 0 pinglobal +sce +endgate +} def + +/dot { +% -10 -10 20 20 bbox +begingate +248 1.00 0 0 6 0.00 360.00 xcarc +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 430 412 offsets +1.0000 inchscale +2.6000 setlinewidth + +1.00 0 430 508 resistor +1.00 315 504 486 resistor +1.00 270 526 412 resistor +1.00 270 334 412 resistor +1.00 0 430 316 capacitor +1 1.00 430 380 430 444 2 polygon +1 1.00 398 412 462 412 2 polygon +1 1.00 430 412 462 444 2 polygon +1.00 0 590 412 circle +1.00 45 550 532 circle +1.00 90 430 572 circle +1.00 180 270 412 circle +(C) {/Times-Italic 1.000 cf} 2 20 0 478 316 label +(/2) {/Times-Roman 1.000 cf} (R) {/Times-Italic 1.000 cf} 4 29 0 526 388 label +(1) {/Times-Roman 1.000 cf} 2 20 0 630 412 label +(2) {/Times-Roman 1.000 cf} 2 24 0 574 556 label +(3) {/Times-Roman 1.000 cf} 2 25 0 430 620 label +(N) {/Times-Italic 1.000 cf} 2 23 0 222 412 label +(/2) {/Times-Roman 1.000 cf} (R) {/Times-Italic 1.000 cf} 4 29 0 334 388 label +(/2) {/Times-Roman 1.000 cf} (R) {/Times-Italic 1.000 cf} 4 28 0 526 484 label +(/2) {/Times-Roman 1.000 cf} (R) {/Times-Italic 1.000 cf} 4 23 0 398 540 label +1.00 0 430 252 gnd +1.00 0 430 412 dot +(.) {/Times-Bold 1.000 cf} 2 21 0 364 486 label +(.) {/Times-Bold 1.000 cf} 2 21 0 387 506 label +(.) {/Times-Bold 1.000 cf} 2 21 0 350 460 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tut8.2.ps b/doc/psfigures/tut8.2.ps new file mode 100644 index 00000000..a033d8d6 --- /dev/null +++ b/doc/psfigures/tut8.2.ps @@ -0,0 +1,193 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tut8.2 +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 14:51:18 2000 +%%Pages: 1 +%%BoundingBox: 68 68 652 303 +%%DocumentNeededResources: font Helvetica font Times-Roman +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/dot { +% -10 -10 20 20 bbox +begingate +248 1.00 0 0 6 0.00 360.00 xcarc +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 992 510 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.800 0.800 0.800 scb +240 1.00 192 254 192 798 1728 798 1728 254 4 polygon +sce +0.490 0.651 0.980 scb +240 1.00 1152 510 1408 510 1408 382 1248 382 1248 350 1568 350 1568 382 1440 +382 1440 510 1568 510 1568 542 1344 542 1344 638 1664 638 1664 766 1632 766 +1632 670 1312 670 1312 542 1152 542 20 polygon +240 1.00 256 510 448 510 448 318 672 318 672 638 800 638 800 510 960 510 960 +542 832 542 832 670 640 670 640 350 480 350 480 542 256 542 16 polygon +sce +0 1.00 256 510 448 510 448 318 672 318 672 638 800 638 800 510 960 510 960 542 +832 542 832 670 640 670 640 350 480 350 480 542 256 542 16 polygon +0 1.00 1152 510 1408 510 1408 382 1248 382 1248 350 1568 350 1568 382 1440 382 +1440 510 1568 510 1568 542 1344 542 1344 638 1664 638 1664 766 1632 766 1632 +670 1312 670 1312 542 1152 542 20 polygon +1.000 1.000 0.000 scb +1 1.00 256 526 464 526 464 334 656 334 656 654 816 654 816 526 960 526 +8 polygon +1 1.00 1152 526 1568 526 2 polygon +1 1.00 1248 366 1568 366 2 polygon +1 1.00 1424 366 1424 526 2 polygon +1 1.00 1328 526 1328 654 1648 654 1648 766 4 polygon +1.00 0 256 526 dot +1.00 0 960 526 dot +1.00 0 1152 526 dot +1.00 0 1568 526 dot +sce +(1) {/Helvetica 1.000 cf} 2 23 0 224 526 label +(2) {/Helvetica 1.000 cf} 2 20 0 976 526 label +(1) {/Helvetica 1.000 cf} 2 23 0 1120 526 label +(2) {/Helvetica 1.000 cf} 2 20 0 1600 526 label +(\(a\)) {/Times-Roman 1.000 cf} 2 21 0 560 206 label +(\(b\)) {/Times-Roman 1.000 cf} 2 21 0 1424 206 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tut8.3.ps b/doc/psfigures/tut8.3.ps new file mode 100644 index 00000000..e424c2dd --- /dev/null +++ b/doc/psfigures/tut8.3.ps @@ -0,0 +1,215 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tut8.3 +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 15:01:57 2000 +%%Pages: 1 +%%BoundingBox: 68 68 498 352 +%%DocumentNeededResources: font Times-Roman +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/mgrid { +% -304 -368 736 736 bbox +begingate +1 1.00 -256 368 -256 -368 2 polygon +1 1.00 -128 368 -128 -368 2 polygon +1 1.00 -304 192 432 192 2 polygon +1 1.00 -304 64 432 64 2 polygon +1 1.00 0 368 0 -368 2 polygon +1 1.00 256 368 256 -368 2 polygon +1 1.00 128 368 128 -368 2 polygon +1 1.00 -304 -192 432 -192 2 polygon +1 1.00 -304 -64 432 -64 2 polygon +1 1.00 -304 -320 432 -320 2 polygon +1 1.00 -304 320 432 320 2 polygon +1 1.00 384 368 384 -368 2 polygon +endgate +} def + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrow { +% -12 -40 24 80 bbox +begingate +1 0.80 0 -40 0 20 2 polygon +1.00 0 0 40 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 720 464 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.133 0.545 0.133 scb +240 1.00 368 624 368 880 752 880 752 624 4 polygon +sce +0.439 1.000 0.314 scb +241 1.00 240 240 880 240 880 496 752 496 752 624 368 624 368 496 240 496 +8 polygon +1 1.00 752 864 752 880 2 polygon +sce +0.800 0.800 0.800 scb +1.00 0 496 560 mgrid +sce +0 1.00 368 624 368 880 752 880 752 624 4 polygon +1.000 1.000 1.000 scb +(buried) {/Times-Roman 1.000 cf} 2 21 0 560 752 label +sce +(diffusion) {/Times-Roman 1.000 cf} 2 21 0 544 400 label +(diff-space perimeter) {/Times-Roman 1.000 cf} 2 28 0 976 224 label +(diff-buried perimeter) {/Times-Roman 1.000 cf} 2 21 0 944 704 label +3 1.00 368 624 368 496 240 496 240 240 880 240 880 496 752 496 752 624 +8 polygon +1.00 60 928 256 arrow +1.000 1.000 1.000 scb +3 1.00 368 624 752 624 2 polygon +1.00 135 720 656 arrow +sce +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tut8.4.ps b/doc/psfigures/tut8.4.ps new file mode 100644 index 00000000..96a3262d --- /dev/null +++ b/doc/psfigures/tut8.4.ps @@ -0,0 +1,224 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tut8.4 +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 15:06:26 2000 +%%Pages: 1 +%%BoundingBox: 68 68 484 244 +%%DocumentNeededResources: font Times-Roman font Times-Italic +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 928 256 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.490 0.651 0.980 scb +192 480 beginpath +544 608 544 480 2 polyc +512 608 32 0.00 90.00 arc +192 640 1 polyc +240 1.00 endpath +1280 480 beginpath +928 608 928 480 2 polyc +960 608 32 180.00 90.00 arcn +1280 640 1 polyc +240 1.00 endpath +sce +1.000 0.000 0.000 scb +192 192 beginpath +1120 320 1120 192 2 polyc +1088 320 32 0.00 90.00 arc +192 352 1 polyc +240 1.00 endpath +sce +192 480 beginpath +544 608 544 480 2 polyc +512 608 32 0.00 90.00 arc +192 640 1 polyc +1 1.00 endpath +1280 480 beginpath +928 608 928 480 2 polyc +960 608 32 180.00 90.00 arcn +1280 640 1 polyc +1 1.00 endpath +192 192 beginpath +1120 320 1120 192 2 polyc +1088 320 32 0.00 90.00 arc +192 352 1 polyc +1 1.00 endpath +(\(metal\)) {/Times-Roman 1.000 cf} 2 21 0 352 560 label +(\(metal\)) {/Times-Roman 1.000 cf} 2 21 0 1120 560 label +(\(poly\)) {/Times-Roman 1.000 cf} 2 21 0 656 272 label +(sidewall overlap) {/Times-Italic 1.000 cf} 2 21 0 688 448 label +(sidewall) {/Times-Italic 1.000 cf} 2 21 0 720 576 label +(overlap) {/Times-Roman 1.000 cf} 2 21 0 352 424 label +(\(oxide\)) {/Times-Roman 1.000 cf} 2 21 0 1024 416 label +1.00 0 560 576 arrowhead90 +1.00 -1 912 576 arrowhead90 +1.00 0 560 512 arrowhead90 +1.00 -91 688 368 arrowhead90 +1 1.00 560 576 640 576 2 polygon +1 1.00 912 576 800 576 2 polygon +1 1.00 560 512 688 512 688 480 3 polygon +1 1.00 688 416 688 368 2 polygon +1.00 -91 352 368 arrowhead90 +1.00 270 352 464 arrowhead90 +1 1.00 352 432 352 464 2 polygon +1 1.00 352 368 352 400 2 polygon +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tut8.5.ps b/doc/psfigures/tut8.5.ps new file mode 100644 index 00000000..6ba18dd7 --- /dev/null +++ b/doc/psfigures/tut8.5.ps @@ -0,0 +1,274 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tut8.5.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 15:16:43 2000 +%%Pages: 1 +%%BoundingBox: 68 68 467 364 +%%DocumentNeededResources: font Times-Roman +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 916 480 offsets +1.0000 inchscale +2.6000 setlinewidth + +1.000 0.000 0.000 scb +240 1.00 260 736 260 800 324 800 324 736 4 polygon +240 1.00 516 736 516 800 580 800 580 736 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 324 800 324 896 516 896 516 800 4 polygon +240 1.00 324 640 324 736 516 736 516 640 4 polygon +sce +0.133 0.545 0.133 scb +240 1.00 324 736 324 800 516 800 516 736 4 polygon +sce +1.000 0.000 0.000 scb +240 1.00 260 320 260 384 324 384 324 320 4 polygon +240 1.00 516 320 516 384 580 384 580 320 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 324 384 324 512 516 512 516 384 4 polygon +240 1.00 324 192 324 320 516 320 516 192 4 polygon +sce +0.133 0.545 0.133 scb +240 1.00 324 320 324 384 516 384 516 320 4 polygon +sce +1.000 0.000 0.000 scb +240 1.00 852 736 852 800 916 800 916 736 4 polygon +240 1.00 1012 544 1012 608 1076 608 1076 544 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 916 800 916 896 1172 896 1172 800 4 polygon +sce +0.133 0.545 0.133 scb +240 1.00 916 736 916 800 1076 800 1076 736 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 916 608 916 736 1012 736 1012 608 4 polygon +sce +0.133 0.545 0.133 scb +240 1.00 1012 608 1012 736 1076 736 1076 608 4 polygon +240 1.00 388 288 388 416 452 416 452 288 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 1076 608 1076 800 1172 800 1172 608 4 polygon +sce +(6) {/Times-Roman 1.000 cf} 2 21 0 420 928 label +(6) {/Times-Roman 1.000 cf} 2 21 0 420 544 label +(6) {/Times-Roman 1.000 cf} 2 21 0 1204 704 label +(2) {/Times-Roman 1.000 cf} 2 21 0 1044 512 label +(2) {/Times-Roman 1.000 cf} 2 21 0 820 768 label +(2) {/Times-Roman 1.000 cf} 2 21 0 612 768 label +(2) {/Times-Roman 1.000 cf} 2 21 0 612 352 label +(1) {/Times-Roman 1.000 cf} 2 25 0 612 464 label +(4) {/Times-Roman 1.000 cf} 2 21 0 884 672 label +(\(a\)) {/Times-Roman 1.000 cf} 2 21 0 212 768 label +(\(c\)) {/Times-Roman 1.000 cf} 2 21 0 212 352 label +(\(b\)) {/Times-Roman 1.000 cf} 2 21 0 756 768 label +1 1.00 836 800 804 800 2 polygon +1 1.00 836 736 804 736 2 polygon +1.00 0 820 736 arrowhead +1.00 -181 820 800 arrowhead +1 1.00 1012 528 1012 480 2 polygon +1 1.00 1076 528 1076 480 2 polygon +1 1.00 1188 608 1236 608 2 polygon +1 1.00 1188 800 1236 800 2 polygon +1 1.00 852 608 900 608 2 polygon +1 1.00 596 384 644 384 2 polygon +1 1.00 596 320 644 320 2 polygon +1 1.00 532 416 644 416 2 polygon +1 1.00 596 736 644 736 2 polygon +1 1.00 596 800 644 800 2 polygon +1 1.00 324 912 324 960 2 polygon +1 1.00 516 912 516 960 2 polygon +1 1.00 324 528 324 576 2 polygon +1 1.00 516 528 516 576 2 polygon +1 1.00 452 544 500 544 2 polygon +1 1.00 388 544 340 544 2 polygon +1 1.00 388 928 340 928 2 polygon +1 1.00 452 928 500 928 2 polygon +1 1.00 612 816 612 848 2 polygon +1 1.00 612 720 612 688 2 polygon +1 1.00 820 816 820 864 2 polygon +1 1.00 820 720 820 672 2 polygon +1 1.00 612 400 612 448 2 polygon +1 1.00 612 304 612 256 2 polygon +1 1.00 996 512 948 512 2 polygon +1 1.00 1092 512 1140 512 2 polygon +1 1.00 1204 624 1204 672 2 polygon +1 1.00 1204 736 1204 784 2 polygon +1 1.00 884 640 884 624 2 polygon +1 1.00 884 704 884 720 2 polygon +1.00 0 612 736 arrowhead +1.00 0 612 320 arrowhead +1.00 0 1204 800 arrowhead +1.00 0 884 736 arrowhead +1.00 -181 884 608 arrowhead +1.00 -181 1204 608 arrowhead +1.00 -181 612 800 arrowhead +1.00 -181 612 384 arrowhead +1.00 -181 612 416 arrowhead +1.00 0 340 928 arrowhead90 +1.00 0 340 544 arrowhead90 +1.00 0 1092 512 arrowhead90 +1.00 -1 996 512 arrowhead90 +1.00 -1 500 544 arrowhead90 +1.00 -1 500 928 arrowhead90 +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tut9.1.ps b/doc/psfigures/tut9.1.ps new file mode 100644 index 00000000..2a2bb225 --- /dev/null +++ b/doc/psfigures/tut9.1.ps @@ -0,0 +1,222 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tut9.1.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 15:43:22 2000 +%%Pages: 1 +%%BoundingBox: 68 68 403 447 +%%DocumentNeededResources: font Helvetica +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/dot { +% -10 -10 20 20 bbox +begingate +248 1.00 0 0 6 0.00 360.00 xcarc +endgate +} def + +/cifwire { +% -272 -32 400 64 bbox +begingate +0.490 0.651 0.980 scb +96 -32 beginpath +96 0 32 -90.00 90.00 arc +-240 32 1 polyc +-240 0 32 90.00 270.00 arc +96 -32 1 polyc +241 1.00 endpath +sce +1 1.00 -240 0 96 0 2 polygon +1.00 0 96 0 dot +1.00 0 -240 0 dot +96 -32 beginpath +96 0 32 -90.00 90.00 arc +-240 32 1 polyc +-240 0 32 90.00 270.00 arc +96 -32 1 polyc +1 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 800 1038 offsets +% 32.00 8.00 gridspace +1.0000 inchscale +2.6000 setlinewidth + +0.800 0.800 0.800 scb +241 1.00 672 302 800 302 1056 430 1056 558 928 686 736 654 672 590 672 302 +8 polygon +sce +0.490 0.651 0.980 scb +241 1.00 192 302 320 302 576 430 576 558 448 686 256 654 192 590 192 302 +8 polygon +sce +0.616 0.624 0.925 scb +241 1.00 672 302 864 302 864 366 928 366 928 430 1056 430 1056 558 992 558 992 +622 928 622 928 686 864 686 864 622 672 622 672 302 15 polygon +sce +0.490 0.651 0.980 scb +240 1.00 688 862 800 862 800 926 864 926 864 990 928 990 928 1054 992 1054 992 +1182 928 1182 928 1118 864 1118 864 1054 800 1054 800 990 736 990 736 926 688 +926 18 polygon +sce +1.00 45 464 1070 cifwire +0 1.00 688 862 800 862 800 926 864 926 864 990 928 990 928 1054 992 1054 992 +1182 928 1182 928 1118 864 1118 864 1054 800 1054 800 990 736 990 736 926 688 +926 18 polygon +1 1.00 720 894 768 894 768 958 832 958 832 1022 896 1022 896 1086 960 1086 960 +1150 9 polygon +1.00 0 960 1150 dot +1.00 0 720 894 dot +1 1.00 192 302 320 302 576 430 576 558 448 686 256 654 192 590 192 302 +8 polygon +0.490 0.651 0.980 scb +241 1.00 800 302 864 302 864 334 800 302 4 polygon +240 1.00 672 590 704 622 672 622 3 polygon +240 1.00 864 678 928 686 864 686 3 polygon +sce +1 1.00 672 302 864 302 864 366 928 366 928 430 1056 430 1056 558 992 558 992 +622 928 622 928 686 864 686 864 622 672 622 672 302 15 polygon +(CIF Wire) {/Helvetica 1.000 cf} 2 21 0 320 782 label +(Resulting Magic Shape) {/Helvetica 1.000 cf} 2 21 0 864 782 label +(CIF Polygon) {/Helvetica 1.000 cf} 2 21 0 352 206 label +(Resulting Magic Shape) {/Helvetica 1.000 cf} 2 21 0 864 206 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tutcell.cif b/doc/psfigures/tutcell.cif new file mode 100644 index 00000000..7b8010c2 --- /dev/null +++ b/doc/psfigures/tutcell.cif @@ -0,0 +1,48 @@ +( @@user : tim ); +( @@machine : stravinsky.jhuapl.edu ); +( @@source : tutcell1.mag ); +( @@tool : Magic 7.1 ); +( @@patch : 0 ); +( @@patchnames : release-6.5b1, linux1, solaris1, SU-WRL-extract, WRL-DRC-X, UNC-CIF-X ); +( @@compiled : Tue Apr 11 16:16:29 EDT 2000 ); +( @@technology : scmos ); +( @@version : 8.2.8 ); +( @@techdesc : MOSIS Scalable CMOS Technology for Standard Rules ); +( @@style : lambda=1.0(gen) ); +( @@date : Wed Apr 12 16:25:21 2000 ); +DS 1 50 2; +9 tutcell1; +L CWN; + B 56 88 32 124; +L CWP; + B 56 96 32 28; +L CMF; + B 56 12 32 142; + B 16 4 32 134; + B 16 28 32 102; + B 36 16 42 80; + B 16 32 32 56; + B 16 4 32 14; + B 56 12 32 6; +L CPG; + B 48 8 28 124; + B 44 8 26 28; +L CAA; + B 16 16 32 140; + B 12 16 30 124; + B 16 16 32 108; + B 16 16 32 48; + B 12 24 30 28; + B 16 16 32 8; +L CCA; + B 8 8 32 140; + B 8 8 32 108; + B 8 8 32 48; + B 8 8 32 8; +L CSN; + B 32 72 32 28; +L CSP; + B 32 64 32 124; +DF; +C 1; +End diff --git a/doc/psfigures/tutcell1.mag b/doc/psfigures/tutcell1.mag new file mode 100644 index 00000000..43581649 --- /dev/null +++ b/doc/psfigures/tutcell1.mag @@ -0,0 +1,59 @@ +magic +tech scmos +timestamp 955571370 +<< error_p >> +rect 22 21 26 25 +rect 22 16 26 18 +rect 22 12 26 15 +rect 22 10 26 11 +rect 21 6 22 10 +rect 26 6 27 10 +rect 22 5 26 6 +rect 21 1 22 5 +rect 26 1 27 5 +rect 22 0 26 1 +<< polysilicon >> +rect 1 30 6 32 +rect 9 30 13 32 +rect 22 26 26 30 +rect 1 6 6 8 +rect 9 6 12 8 +<< ndiffusion >> +rect 22 16 26 20 +rect 6 8 9 10 +rect 6 4 9 6 +<< pdiffusion >> +rect 6 32 9 33 +rect 6 29 9 30 +rect 22 21 26 25 +<< metal1 >> +rect 1 34 6 37 +rect 10 34 15 37 +rect 22 31 26 35 +rect 6 22 10 25 +rect 6 18 15 22 +rect 6 14 10 18 +rect 1 0 6 3 +rect 10 0 15 3 +<< ntransistor >> +rect 6 6 9 8 +rect 22 1 26 5 +<< ptransistor >> +rect 6 30 9 32 +rect 22 6 26 10 +<< ndcontact >> +rect 6 10 10 14 +rect 22 11 26 15 +rect 6 0 10 4 +<< pdcontact >> +rect 6 33 10 37 +rect 6 25 10 29 +<< labels >> +rlabel metal1 22 31 26 35 3 Metal +rlabel polysilicon 22 26 26 30 3 Polysilicon +rlabel pdiffusion 22 21 26 25 3 P-Diffusion +rlabel ndiffusion 22 16 26 20 3 N-Diffusion +rlabel ndcontact 22 11 26 15 3 Contact +rlabel ptransistor 22 6 26 10 3 P-Fet +rlabel ntransistor 22 1 26 5 3 N-Fet +<< end >> diff --git a/doc/psfigures/tutw1.1.ps b/doc/psfigures/tutw1.1.ps new file mode 100644 index 00000000..8495fb38 --- /dev/null +++ b/doc/psfigures/tutw1.1.ps @@ -0,0 +1,214 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tutw1.1.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 16:43:40 2000 +%%Pages: 1 +%%BoundingBox: 68 68 862 365 +%%DocumentNeededResources: font Times-Roman +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 1200 357 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.800 0.800 0.800 scb +240 1.00 192 261 192 965 1072 965 1072 261 4 polygon +240 1.00 1136 261 1136 965 2288 965 2288 261 4 polygon +sce +0.745 0.600 0.871 scb +240 1.00 720 549 720 645 912 645 912 549 4 polygon +241 1.00 496 581 368 581 368 677 592 677 592 485 496 485 496 581 7 polygon +sce +0 1.00 720 549 720 645 912 645 912 549 4 polygon +0.490 0.651 0.980 scb +241 1.00 1232 389 1616 389 1616 901 1232 901 1232 485 1168 485 1168 421 1232 +421 1232 389 1296 453 1296 805 1552 805 1552 453 1296 453 14 polygon +241 1.00 1840 389 1840 613 1744 613 1744 677 1840 677 1840 901 2192 901 2192 +581 2256 581 2256 517 2192 517 2192 389 1840 389 1904 453 2128 453 2128 517 +2064 517 2064 581 2128 581 2128 837 1904 837 1904 453 22 polygon +sce +0 1.00 1296 453 1296 805 1552 805 1552 453 4 polygon +1 1.00 1904 453 1904 837 2128 837 2128 581 2064 581 2064 517 2128 517 2128 453 +1904 453 9 polygon +1 1.00 2192 389 1840 389 1840 613 1744 613 1744 677 1840 677 1840 901 2192 901 +2192 581 2256 581 2256 517 2192 517 2192 389 13 polygon +1 1.00 1232 485 1232 901 1616 901 1616 389 1232 389 1232 421 1168 421 1168 485 +1232 485 9 polygon +1 1.00 496 581 368 581 368 677 592 677 592 485 496 485 496 581 7 polygon +(mwidth) {/Times-Roman 1.000 cf} 2 23 0 336 629 label +(mwidth) {/Times-Roman 1.000 cf} 2 23 0 416 437 label +(mwidth) {/Times-Roman 1.000 cf} 2 20 0 928 597 label +1 1.00 928 645 1008 645 2 polygon +1 1.00 928 549 1008 549 2 polygon +1 1.00 960 661 960 709 2 polygon +1 1.00 960 533 960 485 2 polygon +1 1.00 352 581 272 581 2 polygon +1 1.00 320 565 320 517 2 polygon +1 1.00 352 677 272 677 2 polygon +1 1.00 320 693 320 741 2 polygon +1 1.00 496 469 496 405 2 polygon +1 1.00 592 469 592 405 2 polygon +1 1.00 576 437 432 437 2 polygon +1.00 0 960 549 arrowhead +1.00 0 320 581 arrowhead +1.00 -181 320 677 arrowhead +1.00 -181 960 645 arrowhead +1.00 -91 592 437 arrowhead +1.00 -91 496 437 arrowhead +(invalid) {/Times-Roman 1.250 cf} 2 21 0 464 325 label +(valid) {/Times-Roman 1.250 cf} 2 21 0 816 325 label +(invalid) {/Times-Roman 1.250 cf} 2 21 0 1424 325 label +(valid) {/Times-Roman 1.250 cf} 2 21 0 2016 325 label +(bend_ok) {/Times-Roman 1.500 cf} 2 21 0 1728 213 label +(bend_illegal) {/Times-Roman 1.500 cf} 2 21 0 608 213 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfigures/tutw1.2.ps b/doc/psfigures/tutw1.2.ps new file mode 100644 index 00000000..fe9cfe26 --- /dev/null +++ b/doc/psfigures/tutw1.2.ps @@ -0,0 +1,176 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tutw1.2.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 16:35:19 2000 +%%Pages: 1 +%%BoundingBox: 68 68 331 211 +%%DocumentNeededResources: font Times-Roman +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 576 260 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.439 1.000 0.314 scb +240 1.00 192 196 192 548 704 548 704 196 4 polygon +sce +(minarea) {/Times-Roman 1.000 cf} 2 21 0 448 372 label +0 1.00 192 196 192 548 704 548 704 196 4 polygon +(minedge) {/Times-Roman 1.000 cf} 2 20 0 736 372 label +1 1.00 720 548 800 548 2 polygon +1 1.00 720 196 800 196 2 polygon +1 1.00 768 532 768 404 2 polygon +1 1.00 768 340 768 212 2 polygon +1.00 0 768 548 arrowhead +1.00 -181 768 196 arrowhead +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF diff --git a/doc/psfiles/addendum6_5.ps b/doc/psfiles/addendum6_5.ps new file mode 100644 index 00000000..7561f250 --- /dev/null +++ b/doc/psfiles/addendum6_5.ps @@ -0,0 +1,357 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: addendum6_5.dvi +%%Pages: 3 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips addendum6_5.dvi -o addendum6_5.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (addendum6_5.dvi) +@start /Fa 136[72 50 55 33 39 44 55 55 50 55 83 28 2[28 +55 50 1[44 55 1[55 50 51[33 41[55 55 2[{ TeXBase1Encoding ReEncodeFont } +22 100.000003 /Times-Bold rf /Fb 138[66 40 47 3[60 66 +100 6[40 53 66 53 30[86 2[86 6[40 58[{ TeXBase1Encoding ReEncodeFont } +13 119.999948 /Times-Bold rf /Fc 103[33 1[50 27[44 50 +50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 50 +33 44 50 44 50 44 9[94 72 72 61 55 66 1[55 72 72 89 61 +2[33 72 1[55 61 72 66 66 72 6[28 50 1[50 50 50 50 50 +50 50 50 28 25 33 25 2[33 33 33 3[50 31[55 55 2[{ + TeXBase1Encoding ReEncodeFont }67 100.000003 /Times-Roman +rf /Fd 133[39 44 1[66 44 50 28 39 39 1[50 50 50 72 28 +2[28 50 50 28 44 50 44 50 50 13[50 38[25 40[50 3[{ + TeXBase1Encoding ReEncodeFont }25 100.000003 /Times-Italic +rf /Fe 135[72 104 1[80 48 56 64 2[72 80 120 3[40 1[72 +48 64 80 64 1[72 10[104 3[104 3[104 135 3[56 2[88 96 +104 104 1[104 6[48 3[72 72 72 72 72 72 2[36 46[{ + TeXBase1Encoding ReEncodeFont }34 143.999997 /Times-Bold +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 661 99 a Fe(Magic)35 b(Addendum:)42 b(V)-14 b(ersion)34 +b(6.5)h(differ)m(ences)1516 519 y Fd(Stefanos)24 b(Sidir)l(opoulos)1354 +940 y Fc(Center)i(for)f(Inte)o(grated)f(Systems)1558 +1060 y(Stanford)h(Uni)n(v)o(ersity)1547 1180 y(Stanford,)g(CA)h(94305) +1053 1451 y(This)e(tutorial)g(corresponds)g(to)g(Magic)h(v)o(ersion)e +(7.)0 1964 y Fb(Affected)30 b(Documents:)300 2157 y Fc(Magic)24 +b(T)l(utorial)g(#6:)30 b(Design-Rule)25 b(Checking)300 +2277 y(Magic)f(T)l(utorial)g(#9:)30 b(F)o(ormat)24 b(Con)l(v)o(ersion)g +(for)h(CIF)h(and)f(Calma)300 2398 y(Magic)f(T)l(utorial)g(#W)-6 +b(-1:)30 b(Design-Rule)24 b(Extensions)300 2518 y(Magic)g(Maintainer') +-5 b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)300 2638 y(Magic)g(man)h(pages:)30 b(e)o(xt2sim\(1\),)23 +b(e)o(xt2spice\(1\),)h(e)o(xt\003at\(3\),)h(e)o(xt\(5\).)0 +3198 y Fe(1)143 b(Intr)m(oduction)0 3421 y Fc(Magic)25 +b(6.5)g(has)h(some)e(signi\002cant)h(modi\002cations)f(that)h(mak)o(e)g +(some)g(of)h(the)f(original)g(v)o(ersion)f(6)h(documents)0 +3542 y(obsolete.)57 b(The)35 b(purpose)e(of)h(this)f(addendum)g(is)h +(to)g(highlight)e(these)h(dif)n(ferences)i(so)e(that)h(users)g(can)g +(tak)o(e)0 3662 y(adv)n(antage)24 b(of)h(the)g(ne)n(w)f(features.)0 +4000 y Fe(2)143 b(Extractor)34 b(Extensions)0 4223 y +Fc(The)19 b(6.5)h(e)o(xtractor)f(uses)g(double)f(precision)h +(\003oating)g(point)g(numbers)f(to)h(represent)h(capacitances.)29 +b(Therefore)0 4344 y(all)f(the)g(capacitances)g(in)g(\(aF/sq-lambda\))g +(associated)f(with)h(the)f Fd(ar)l(eacap,)i(perimc,)g(side)o(wall,)e +(sideo)o(verlap)0 4464 y Fc(k)o(e)o(yw)o(ords)d(in)g(the)h(e)o(xtract)f +(section)g(of)h(the)g(technology)f(\002le)h(can)g(be)g +Fd(\003oating)e(point)h(number)o(s)p Fc(.)146 4584 y(Additionally)37 +b(the)i(e)o(xtension)f(of)h(the)g(capacitance)h(to)f(\003oating)f +(point)g(numbers)h(af)n(fects)g(the)g(manual)0 4705 y(pages)23 +b(of)h(e)o(xt2sim\(1\),)d(e)o(xt2spice\(1\),)i(e)o(xt\003at\(3\),)g(e)o +(xt\(5\))g(which)g(can)h(be)f(found)g(in)g(your)g(local)g(system)f +(under)0 4825 y(CAD)p 216 4825 30 4 v 36 w(HOME/man)146 +4946 y(The)31 b(6.5)f(e)o(xtractor)g(shields)f(the)i(perimeter)f +(capacitance)h(from)f(layer)h(to)f(layer)-5 b(.)48 b(T)-8 +b(o)30 b(f)o(acilitate)g(this)g(tw)o(o)0 5066 y(ne)n(w)c(commands)f +Fd(planeor)l(der)-11 b(,)26 b(noplaneor)l(dering)e Fc(ha)n(v)o(e)i +(been)h(introduced)e(and)i(the)f Fd(sideo)o(verlap)f +Fc(command)0 5186 y(has)g(been)g(modi\002ed.)30 b(The)25 +b(syntax)f(for)h(the)f(ne)n(w)h(commands)e(is:)900 5400 +y Fa(planeorder)j Fd(plane)f(num)1875 5649 y Fc(\2261\226)p +eop +%%Page: 2 2 +2 1 bop 0 -180 a Fc(September)25 b(26,)f(2001)1400 b(Magic)25 +b(Addendum:)k(V)-11 b(ersion)25 b(6.5)f(dif)n(ferences)146 +68 y(Where)k Fd(plane)e Fc(is)h(one)g(of)g(the)g(de\002ned)g(planes)g +(and)g Fd(num)f Fc(is)h(a)g(positi)n(v)o(e)e(inte)o(ger)h(indicating)g +(the)g(ordering)0 189 y(of)h(this)g(plane)g(from)g(lo)n(wer)g(to)f +(higher)-5 b(.)38 b(So)27 b(for)h(e)o(xample)e(the)h(metal1)g(plane)g +(has)g(order)h(3)f(while)g(metal2)f(has)0 309 y(order)f(4.)146 +429 y(In)e(case)g(you)f(dont)g(w)o(ant)h(to)f(specify)g(the)h(order)g +(of)f(the)h(planes)f(the)h(e)o(xtractor)f(will)g(complain)f(and)i +(assume)0 550 y(a)i(def)o(ault)g(one.)30 b(If)c(you)e(w)o(ant)h(to)f +(suppress)g(the)h(w)o(arning)f(you)g(just)g(ha)n(v)o(e)h(to)f(issue)g +(the)h(k)o(e)o(yw)o(ord:)900 776 y Fa(noplaneordering)146 +1003 y Fc(The)g Fd(sideo)o(verlap)f Fc(k)o(e)o(yw)o(ord)g(syntax)g(has) +h(been)g(altered)g(to:)900 1229 y Fa(sideo)o(v)o(erlap)g +Fd(intypes)f(outtypes)g(o)o(vtypes)h(cap)g(shieldtypes)146 +1456 y Fc(where)39 b Fd(intypes)p Fc(,)h Fd(outtypes)p +Fc(,)h(and)d Fd(o)o(vtypes)g Fc(are)g(type-lists)f(and)h +Fd(cap)g Fc(is)f(capacitance)i(in)f(attof)o(arads)g(per)0 +1576 y(lambda.)h(This)26 b(is)i(the)f(capacitance)h(associated)g(with)e +(an)i(edge)g(with)f(a)h(type)f(in)g Fd(intypes)g Fc(on)h(its)e(inside)h +(and)h(a)0 1697 y(type)i(in)g Fd(outtypes)g Fc(on)g(its)f(outside,)i +(that)f(o)o(v)o(erlaps)f(a)h(tile)g(whose)g(type)g(is)g(in)g +Fd(o)o(vtypes)p Fc(.)47 b(If)31 b(the)f Fd(shieldtypes)g +Fc(is)0 1817 y(present)24 b(ho)n(we)n(v)o(er)f(this)g(shields)g(the)h +(capacitance.)32 b(So)24 b(for)h(e)o(xample)e(to)h(shield)f(metal-2)h +(to)g(poly)f(capacitance)0 1938 y(use:)900 2164 y Fa(sideo)o(v)o(erlap) +i Fc(M2Cap)g(\230M2Cap)g(PolyCap)g(19.41)f(M1Cap)0 2504 +y Fe(3)143 b(DRC)35 b(Extensions)0 2727 y Fc(This)30 +b(v)o(ersion)f(includes)h(code)h(fragments)f(implemented)f(in)h +(DEC-WRL)h(by)g(Don)f(Stark)h(which)f(enable)g(to)0 2847 +y(implement)35 b(more)h(complicated)g(DRC)h(rules.)66 +b(F)o(or)37 b(a)g(description)e(of)i(these)f(enhancements)g(look)g(in)g +(the)0 2968 y(magic)24 b(tutorial)g(#W1)h(which)f(can)h(be)g(found)g +(in)f(the)h(\002le)g(doc/tutwrl1.ps)e(under)h(the)h(magic)f(source)h +(tree.)0 3307 y Fe(4)143 b(CIF)35 b(extensions)0 3531 +y Fc(T)-8 b(w)o(o)22 b(ne)n(w)f(commands)g(ha)n(v)o(e)h(been)g(inte)o +(grated)f(in)g(the)h(cif)g(output)f(section)g(courtesy)h(of)g(Ste)n(v)o +(en)f(T)-7 b(ell)21 b(and)h(Fred)0 3651 y(Heaton)j(at)f(UNC.)146 +3771 y(The)h(\002rst)g(ne)n(w)f(command)g(is)g(a)h(command)f(that)g +(enables)h(the)g(generation)f(of)h(DRC)g(correct)h(layers)e(at)h(the)0 +3892 y(top)f(le)n(v)o(el)g(\(such)h(as)f(the)h(nwell)f(in)h(the)f +(SCMOS)i(tech)f(\002les\).)31 b(The)25 b(syntax)f(is:)900 +4118 y Fa(min-width)i Fd(width)146 4345 y Fc(The)39 b(width)e(ar)n +(gument)h(is)g(in)g(centimicrons.)69 b(This)38 b(command)f(should)g(be) +i(speci\002ed)f(within)f(a)i(layer)0 4465 y(sub-section)24 +b(of)h(the)f(cifoutput)g(section)g(of)h(the)g(technology)e(\002le.)146 +4586 y(The)i(second)g(command)f(is)g(an)h(e)o(xtension)e(to)i(the)f +(squares)h(cif)g(output)e(command.)30 b(Its)25 b(syntax)f(is:)900 +4812 y Fa(squar)n(es-grid)i Fd(bor)l(der)e(size)h(separ)o(ation)d(grid) +146 5039 y Fc(The)28 b(added)f(ar)n(gument)h(is)f Fd(grid)p +Fc(.)38 b(It)27 b(is)g(in)g(units)g(of)g(centi-microns.)38 +b(In)28 b(some)f(technologies,)f(all)i(features)0 5159 +y(must)20 b(f)o(all)i(on)f(a)g(speci\002ed)h(grid.)29 +b(In)22 b(our)f(case,)i(this)d(w)o(as)i(a)f(.05)g(micron)g(grid.)29 +b(In)22 b(the)f(original)g(implementation)0 5280 y(of)28 +b(magic,)h(if)g(lambda)e(w)o(as)i(not)f(set)g(to)g(some)g(inte)o(gral)f +(multiple)g(of)h(the)g(grid)g(one)h(could)f(generate)h(contacts)0 +5400 y(that)g(did)g(not)g(f)o(all)g(on)g(grid)g(boundaries.)44 +b(By)30 b(specifying)e(the)i(grid)f(spacing,)h(the)f(ne)n(w)g +(enhancement)g(to)g(the)1875 5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fc(Magic)24 b(Addendum:)30 b(V)-11 b(ersion)24 +b(6.5)g(dif)n(ferences)1401 b(September)25 b(26,)g(2001)0 +68 y(contact)35 b(generation)f(code)h(will)f(allo)n(w)f(contacts)i(to)f +(be)h(generated)g(on)f(grid.)60 b(This)34 b(does)h(introduce)f(some)0 +188 y(problems.)29 b(In)24 b(particular)l(,)f(some)g(odd)g(size)h +(contacts)f(will)f(not)h(be)h(able)g(to)f(generate)h(a)f(CIF)i(contact) +e(structure)0 309 y(that)30 b(is)h(centered)g(on)g(its)f(corresponding) +g(magic)g(contact.)49 b(This)30 b(is)g(not)h(a)g(problem)f(in)g(most)g +(cases,)i(e)o(xcept)0 429 y(where)i(an)g(odd)g(size)g(contact)f(is)h +(shared)g(between)g(tw)o(o)f(cells.)58 b(In)34 b(this)f(case,)j(the)e +(CIF)h(contact)f(strucuture)0 549 y(might)g(be)i(shifted)f(to)g(the)h +(left)f(during)g(CIF)i(generation)e(to)g(get)h(it)f(on)g(grid)h(and)f +(the)h(other)f(cell)h(might)e(be)0 670 y(shifted)25 b(to)h(the)g +(right.)33 b(The)26 b(superposition)e(of)i(these)g(tw)o(o)f(structures) +h(may)f(create)i(an)f(ille)o(gal)e(contact)i(size)g(or)0 +790 y(spacing.)38 b(Use)28 b(with)e(e)o(xtreme)h(care)i(or)e(combine)g +(it)g(with)g(cifwidth)g(and)g(cifspacing)g(rules)g(to)g(v)o(erify)g +(correct)0 911 y(operation.)0 1250 y Fe(5)143 b(New)35 +b(commands)0 1474 y Fc(Three)25 b(ne)n(w)g(commands)e(ha)n(v)o(e)i +(been)g(introduced)f(\(based)h(on)f(the)h(WRL)g(code)g(fragments)f(by)h +(Bob)g(Mayo\):)900 1702 y Fa(goto)g Fd(nodename)146 1930 +y Fc(Places)h(the)e(box/cross)g(o)o(v)o(er)g(the)h(node)f(named)h +Fd(nodename)p Fc(.)900 2159 y Fa(\002ndlabel)h Fd(labelname)146 +2387 y Fc(Places)g(the)e(box/cross)g(o)o(v)o(er)g(the)h(label)f +Fd(nodename)p Fc(.)900 2615 y Fa(\003atten)i Fd(destname)146 +2844 y Fc(Flattens)32 b(the)f(cell)h(in)f(the)g(current)h(layout)f +(windo)n(w)f(and)i(places)f(it)h(in)f(the)g(cell)h(named)f +Fd(cellname)p Fc(.)51 b(The)0 2964 y(labels)24 b(are)i(changed)f(to)f +(retain)h(their)f(hierarchical)i(pre\002x)o(es.)1875 +5649 y(\2263\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/copyright.ps b/doc/psfiles/copyright.ps new file mode 100644 index 00000000..fd7aca48 --- /dev/null +++ b/doc/psfiles/copyright.ps @@ -0,0 +1,259 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: copyright.dvi +%%Pages: 1 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips copyright.dvi -o copyright.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Roman +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (copyright.dvi) +@start /Fa 1 14 df<0000000003FFE00000000000000000007FFFFF00000000000000 +0003FFFFFFE0000000000000000FFFFFFFF8000000000000007FFE003FFF000000000000 +00FFC00001FF80000000000003FE0000003FE000000000000FF80000000FF80000000000 +1FC000000001FC00000000003F8000000000FE0000000000FE00000000003F8000000001 +FC00000000001FC000000003F0000000000007E000000007E0000000000003F00000000F +C0000000000001F80000001F80000000000000FC0000003F000000000000007E0000007E +000000000000003F0000007C000000000000001F000000F8000000000000000F800001F8 +000000000000000FC00001F00000000000000007C00003E00000000000000003E00003E0 +0000000000000003E00007C00000000000000001F0000FC00000000000000001F8000F80 +0000000000000000F8000F00000000000000000078001F0000000000000000007C001F00 +00000000000000007C003E0000000000000000003E003E0000000000000000003E003C00 +00000000000000001E003C0000000000000000001E007C0000000000000000001F007C00 +00000000000000001F00780000000000000000000F00780000000000000000000F00F800 +00000000000000000F80F80000000000000000000F80F00000000000000000000780F000 +00000000000000000780F00000000000000000000780F00000000000000000000780F000 +00000000000000000780F00000000000000000000780F00000000000000000000780F000 +00000000000000000780F00000000000000000000780F00000000000000000000780F000 +00000000000000000780F00000000000000000000780F80000000000000000000F80F800 +00000000000000000F80780000000000000000000F00780000000000000000000F007C00 +00000000000000001F007C0000000000000000001F003C0000000000000000001E003C00 +00000000000000001E003E0000000000000000003E003E0000000000000000003E001F00 +00000000000000007C001F0000000000000000007C000F00000000000000000078000F80 +0000000000000000F8000FC00000000000000001F80007C00000000000000001F00003E0 +0000000000000003E00003E00000000000000003E00001F00000000000000007C00001F8 +000000000000000FC00000F8000000000000000F8000007C000000000000001F0000007E +000000000000003F0000003F000000000000007E0000001F80000000000000FC0000000F +C0000000000001F800000007E0000000000003F000000003F0000000000007E000000001 +FC00000000001FC000000000FE00000000003F80000000003F8000000000FE0000000000 +1FC000000001FC00000000000FF80000000FF8000000000003FE0000003FE00000000000 +00FFC00001FF800000000000007FFE003FFF000000000000000FFFFFFFF8000000000000 +0003FFFFFFE000000000000000007FFFFF00000000000000000003FFE00000000000595C +7BC664>13 D E /Fb 107[44 44 25[50 50 72 50 50 28 39 33 +50 50 50 50 78 28 50 1[28 50 50 33 44 50 44 50 44 11[72 +61 55 66 1[55 1[72 1[61 2[33 3[61 72 66 1[72 7[50 50 +2[50 3[50 50 1[25 1[25 44[{ TeXBase1Encoding ReEncodeFont }45 +100.000003 /Times-Roman rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 536 3720 a Fb(Cop)o(yright)992 3717 y(c)964 3720 +y Fa(\015)p Fb(1985,)24 b(1989,)g(1990)g(Re)o(gents)h(of)g(the)f(Uni)n +(v)o(ersity)f(of)i(California,)579 3841 y(La)o(wrence)g(Li)n(v)o +(ermore)e(National)h(Labs,)h(Stanford)g(Uni)n(v)o(ersity)-6 +b(,)22 b(and)j(Digital)519 3961 y(Equipment)e(Corporation.)30 +b(Permission)24 b(to)g(use,)h(cop)o(y)-6 b(,)24 b(modify)-6 +b(,)23 b(and)i(distrib)n(ute)550 4082 y(this)f(softw)o(are)h(and)f(its) +g(documentation)f(for)j(an)o(y)e(purpose)g(and)h(without)e(fee)j(is)546 +4202 y(hereby)f(granted,)f(pro)o(vided)g(that)g(the)h(abo)o(v)o(e)f +(cop)o(yright)g(notice)g(appears)h(in)g(all)663 4322 +y(copies.)30 b(The)25 b(cop)o(yright)f(holders)g(mak)o(e)h(no)f +(representations)g(about)g(the)668 4443 y(suitability)e(of)j(this)f +(softw)o(are)h(for)g(an)o(y)f(purpose.)31 b(It)24 b(is)h(pro)o(vided)e +(\223as)i(is\224)591 4563 y(without)e(e)o(xpress)h(or)h(implied)e(w)o +(arranty)-6 b(.)31 b(Export)24 b(of)h(this)f(softw)o(are)h(outside)704 +4683 y(of)g(the)g(United)f(States)h(of)g(America)g(may)f(require)h(an)g +(e)o(xport)f(license.)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/introduction.ps b/doc/psfiles/introduction.ps new file mode 100644 index 00000000..f6d87a57 --- /dev/null +++ b/doc/psfiles/introduction.ps @@ -0,0 +1,492 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: introduction.dvi +%%Pages: 4 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Roman Times-Bold Times-Italic Courier +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips introduction.dvi -o introduction.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Roman +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (introduction.dvi) +@start /Fa 134[60 5[47 3[60 66 1[33 3[66 60 1[53 1[53 +1[60 12[80 66 4[86 113 80 2[47 1[93 3[86 1[86 12[60 1[60 +60 2[30 43[66 2[{ TeXBase1Encoding ReEncodeFont }24 119.999948 +/Times-Bold rf /Fb 136[60 4[60 2[60 1[60 60 2[60 1[60 +1[60 60 60 1[60 32[60 17[60 12[60 33[{ TeXBase1Encoding ReEncodeFont } +14 100.000003 /Courier rf /Fc 133[44 4[55 33 39 44 2[50 +55 83 28 55 1[28 1[50 33 44 55 44 1[50 17[78 1[94 4[78 +2[66 72 72 1[72 6[33 10[28 25 43[55 2[{ TeXBase1Encoding ReEncodeFont } +28 100.000003 /Times-Bold rf /Fd 134[44 3[50 28 39 39 +2[50 50 1[28 44 1[28 50 50 28 44 50 44 1[50 9[83 61 1[55 +50 4[66 83 55 5[61 1[72 2[61 6[33 7[50 3[25 6[33 3[50 +35[{ TeXBase1Encoding ReEncodeFont }32 100.000003 /Times-Italic +rf /Fe 1 16 df<0001FF0000000FFFE000003FFFF800007FFFFC0001FFFFFF0003FFFF +FF8007FFFFFFC00FFFFFFFE01FFFFFFFF01FFFFFFFF03FFFFFFFF87FFFFFFFFC7FFFFFFF +FC7FFFFFFFFCFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFE +FFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFE7FFFFFFFFC7FFFFFFFFC7FFFFFFFFC3F +FFFFFFF81FFFFFFFF01FFFFFFFF00FFFFFFFE007FFFFFFC003FFFFFF8001FFFFFF00007F +FFFC00003FFFF800000FFFE0000001FF000027267BAB32>15 D E +/Ff 138[80 48 56 64 1[80 72 80 120 3[40 80 72 48 64 80 +64 80 72 13[80 104 4[135 3[56 4[104 104 96 12[72 72 72 +72 72 3[48 45[{ TeXBase1Encoding ReEncodeFont }30 143.999997 +/Times-Bold rf /Fg 103[33 100 50 1[44 44 24[44 50 50 +72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 50 33 +44 50 44 50 44 6[61 72 72 94 72 72 61 55 66 1[55 72 72 +89 61 1[39 33 72 72 55 61 72 66 66 72 6[28 50 50 50 50 +1[50 50 50 50 50 28 25 33 25 2[33 33 33 2[50 2[33 29[55 +55 2[{ TeXBase1Encoding ReEncodeFont }76 100.000003 /Times-Roman +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 1053 68 a Fg(This)24 b(tutorial)g(corresponds)g(to)g(Magic)h(v) +o(ersion)e(7.)0 780 y Ff(1)143 b(Intr)m(oduction)0 1004 +y Fg(This)24 b(v)o(ersion)g(of)h(Magic,)g(v)o(ersion)f(6,)h(gathers)g +(together)f(w)o(ork)h(done)g(by)g(numerous)f(people)h(at)g(se)n(v)o +(eral)f(insti-)0 1124 y(tutions)i(since)h(Magic)h(v)o(ersion)e(4)i(w)o +(as)f(released)h(from)g(Berk)o(ele)o(y)f(on)h(the)f(1986)g(VLSI)h +(tools)f(tape.)39 b(This)27 b(is)g(a)0 1245 y(release)e(of)f(Magic)f +(and)h(IRSIM)h(only)-6 b(.)29 b(Y)-11 b(ou')o(ll)23 b(probably)h(w)o +(ant)f(to)h(obtain)f(other)h(tools)f(by)g(ordering)h(the)g(1986)0 +1365 y(VLSI)h(T)-8 b(ools)24 b(T)-8 b(ape)25 b(from)g(Berk)o(ele)o(y)-6 +b(.)146 1485 y(This)21 b(release)h(has)g(been)g(prepared)g(with)f(the)g +(assistance)g(of)h(se)n(v)o(eral)f(groups.)29 b(Much)21 +b(of)g(the)h(ne)n(w)f(softw)o(are)0 1606 y(came)33 b(from)g(W)-8 +b(alter)33 b(Scott')-5 b(s)33 b(group)f(at)h(the)g(La)o(wrence)g(Li)n +(v)o(ermore)f(National)g(Labs)h(\(LLNL\).)g(LLNL)g(also)0 +1726 y(pro)o(vided)i(partial)g(funding)h(to)f(help)h(prepare)h(the)f +(release.)65 b(Digital)35 b(Equipment)f(Corporation')-5 +b(s)35 b(W)-8 b(estern)0 1847 y(Research)38 b(Lab)f(\(DECWRL\))h +(helped)f(out)f(by)h(pro)o(viding)e(computer)h(equipment,)j(a)e(place)h +(to)e(w)o(ork,)k(and)0 1967 y(the)29 b(services)g(of)g(one)g(of)h(us)e +(\(Robert)i(Mayo\).)43 b(Don)29 b(Stark,)i(Michael)d(Arnold,)i(and)f +(Gordon)g(Hamachi)g(also)0 2087 y(w)o(ork)o(ed)e(on)g(the)h(release)g +(at)f(DECWRL.)h(Stanford)g(donated)e(signi\002cant)h(pieces)g(of)h(ne)n +(w)f(code,)h(including)e(a)0 2208 y(simulation)21 b(system)h(called)h +(IRSIM.)h(Other)g(indi)n(viduals)c(and)j(institutions)e(ha)n(v)o(e)i +(also)g(contrib)n(uted)f(code)h(and)0 2328 y(assistance)h(in)h(w)o(ays) +f(too)h(numerous)e(to)i(detail)f(here.)146 2449 y(Ne)n(w)h(features)g +(in)f(Magic)h(V)-11 b(ersion)24 b(6)h(include:)145 2646 +y Fe(\017)49 b Fg(Ne)n(w)24 b(and)h(Impro)o(v)o(ed)e(Routing\227)p +Fd(Mic)o(hael)g(Arnold)h(and)g(W)-9 b(alter)24 b(Scott)g(of)h(LLNL)244 +2766 y Fg(Three)e(major)f(routing)f(impro)o(v)o(ements)f(ha)n(v)o(e)i +(been)h(made)g(in)f(this)f(v)o(ersion)h(of)h(Magic.)29 +b(There)23 b(is)f(a)h(ne)n(w)-6 b(,)244 2887 y(impro)o(v)o(ed,)34 +b(global)g(router)g(courtesy)g(of)g(W)-8 b(alter)35 b(Scott)f(\(of)g +(LLNL\).)g(W)-8 b(alter)35 b(Scott)f(has)g(also)g(added)244 +3007 y(a)g(gate)g(array)h(router)-5 b(.)59 b(See)35 b(the)f +(\223garoute\224)g(command)g(in)f(the)i(manual)e(page)i(for)f(details.) +59 b(Michael)244 3128 y(Arnold)22 b(\(of)h(LLNL\))f(has)h(written)f(an) +h(interacti)n(v)o(e)e(maze)i(router)g(that)f(allo)n(ws)g(the)h(user)f +(to)h(specify)f(hints)244 3248 y(to)i(control)g(the)h(routing.)30 +b(See)25 b(the)g(documentation)e(for)i(the)g(\223iroute\224)g(command.) +145 3444 y Fe(\017)49 b Fg(Extractor)24 b(Enhancements\227)p +Fd(Don)g(Stark)g(of)g(Stanfor)l(d)g(and)g(W)-9 b(alter)24 +b(Scott)g(of)g(LLNL)244 3564 y Fg(The)29 b(ne)n(w)h(\223e)o +(xtresis\224)f(command,)g(de)n(v)o(eloped)f(by)i(Don)f(Stark,)i(pro)o +(vides)d(substantially)g(better)h(resis-)244 3684 y(tance)37 +b(e)o(xtraction.)64 b(Magic')-5 b(s)36 b(normal)g(e)o(xtraction)f +(\(\223e)o(xtract\224\))i(lumps)f(resistances)g(on)g(a)h(node)f(into) +244 3805 y(a)f(single)g(v)n(alue.)61 b(In)36 b(branching)e(netw)o +(orks,)j(this)e(approximation)e(is)i(often)g(not)g(acceptable.)62 +b(Resis)244 3925 y(w)o(as)33 b(written)g(to)g(solv)o(e)f(this)g +(problem.)55 b(W)-8 b(alter)34 b(Scott)f(added)g(accurate)h(path)f +(length)g(e)o(xtraction,)h(an)244 4046 y(important)23 +b(feature)j(when)e(dealing)h(with)f(high)g(speed)g(circuits,)h(such)f +(as)h(ECL.)145 4241 y Fe(\017)49 b Fg(Ne)n(w)20 b(contact)g +(structure\227)p Fd(W)-9 b(alter)18 b(Scott)i(and)g(Mic)o(hael)f +(Arnold)g(of)h(LLNL)i(and)d(Don)h(Stark)g(of)f(Stanfor)l(d)244 +4362 y Fg(Multilayer)25 b(contacts)g(are)i(handled)e(better)-5 +b(.)34 b(In)26 b(the)g(pre)n(vious)e(v)o(ersion)h(of)h(Magic,)g(there)g +(needed)g(to)g(be)244 4482 y(a)31 b(separate)g(contact)f(type)g(for)h +(each)g(possible)e(combination)g(of)i(contact)f(layers)h(o)o(v)o(er)e +(a)i(gi)n(v)o(en)e(point.)244 4602 y(This)21 b(caused)h(a)h +(combinatorial)d(e)o(xplosion)h(of)h(tile)f(types)h(for)g(multi-layer)f +(technologies)g(with)g(stack)o(ed)244 4723 y(contacts.)29 +b(Under)23 b(the)f(ne)n(w)g(scheme,)h(there)g(are)g(only)f(a)h(couple)f +(of)h(tile)f(types)g(for)g(each)h(layer:)30 b(one)23 +b(that)244 4843 y(connects)h(up,)h(one)g(that)f(connects)g(do)n(wn,)g +(and)h(one)g(that)f(connects)g(in)h(both)f(directions.)145 +5039 y Fe(\017)49 b Fg(Simulator)24 b(Interf)o(ace)i(to)e(IRSIM\227)p +Fd(Stanfor)l(d)244 5159 y Fg(A)e(simulator)e(interf)o(ace)j(is)e(pro)o +(vided)g(courtesy)g(of)h(Stanford.)30 b(See)23 b(the)e(commands)g +(\223startrsim\224,)h(\223sim-)244 5280 y(cmd\224,)35 +b(and)e(\223rsim\224.)55 b(The)34 b(irsim)e(simulator)l(,)h(Stanford') +-5 b(s)33 b(much)g(impro)o(v)o(ed)e(re)n(write)i(of)g(esim,)i(is)d(in-) +244 5400 y(cluded)24 b(in)h(this)f(distrib)n(ution.)k(Credit)d(goes)f +(to)h(Mik)o(e)f(Cho)n(w)-6 b(,)24 b(Arturo)g(Salz,)i(and)f(Mark)f(Horo) +n(witz.)1875 5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fg(September)25 b(26,)f(2001)482 b(Ov)o(ervie)n(w)24 +b(of)h(the)g(DECWRL/Li)n(v)o(ermore)e(Magic)i(Release)h(\(V)-11 +b(ersion)24 b(6\))145 68 y Fe(\017)49 b Fg(Ne)n(w)24 +b(de)n(vice/machine)g(Support\227)p Fd(V)-11 b(arious)244 +188 y Fg(X11)24 b(is)f(fully)h(supported)f(in)g(this)g(release,)i(and)f +(is)g(the)g(preferred)h(interf)o(ace.)31 b(Older)24 b(dri)n(v)o(ers)f +(for)h(graph-)244 309 y(ics)34 b(terminals)f(and)g(X10)h(are)h(also)e +(included,)j(b)n(ut)d(X11)h(is)f(the)h(preferred)h(interf)o(ace)g +(\(meaning)e(it)h(is)244 429 y(better)c(supported)g(and)g(you')o(ll)g +(ha)n(v)o(e)g(lots)g(of)g(compan)o(y\).)47 b(Magic')-5 +b(s)30 b(X11)g(dri)n(v)o(er)g(has)g(a)h(long)f(history)-6 +b(,)244 549 y(starting)29 b(with)h(an)h(X10)f(dri)n(v)o(er)f(by)h(Doug) +g(P)o(an)h(at)f(Stanford.)48 b(Bro)n(wn)30 b(Uni)n(v)o(ersity)-6 +b(,)30 b(the)g(Uni)n(v)o(ersity)e(of)244 670 y(Southern)e(California,)g +(the)f(Uni)n(v)o(ersity)f(of)i(W)-8 b(ashington,)24 b(and)i(La)o +(wrence)g(Li)n(v)o(ermore)e(National)h(Labs)244 790 y(all)k(prepared)h +(impro)o(v)o(ed)e(v)o(ersions,)h(some)g(of)h(them)f(for)h(X11.)44 +b(Don)30 b(Stark)g(of)f(Stanford)h(took)f(on)g(the)244 +911 y(task)24 b(of)h(pulling)e(these)i(together)f(and)h(producing)f +(the)h(X11)f(dri)n(v)o(er)g(in)g(this)g(release.)244 +1107 y(Magic)31 b(runs)g(on)g(a)h(number)f(of)g(w)o(orkstations,)g +(such)g(as)h(the)f(DECstation)g(3100)f(and)i(Sun')-5 +b(s)31 b(SP)-9 b(ARC)244 1227 y(processors.)33 b(P)o(artial)25 +b(Unix)g(System)g(V)h(support)e(is)h(pro)o(vided,)g(via)g(the)h +(compilation)d(\003ags)j(mentioned)244 1348 y(belo)n(w)-6 +b(.)29 b(The)24 b(system)e(also)h(runs)h(on)f(the)h(MacII.)g(Don)f +(Stark)h(gets)f(credit)h(for)g(the)g(System)f(V)g(mods)g(and)244 +1468 y(support)h(for)h(HP)g(machines,)f(while)g(Mik)o(e)h(Cho)n(w)f +(helped)g(get)h(it)f(running)g(on)h(the)f(MacII.)244 +1664 y(T)-8 b(o)37 b(assist)e(people)i(with)f(small)g(machines)g +(\(such)h(as)g(the)f(Mac)h(II\),)h(Magic)e(can)h(no)n(w)f(be)h +(compiled)244 1785 y(without)30 b(some)h(of)h(its)e(f)o(anc)o(y)i +(features.)51 b(Compilation)30 b(\003ags)i(are)g(pro)o(vided,)g(as)g +(indicated)f(belo)n(w)-6 b(,)31 b(to)244 1905 y(eliminate)24 +b(things)f(lik)o(e)h(routing,)g(plotting,)f(or)i(calma)g(output.)k +(This)24 b(is)g(courtesy)h(of)g(Don)f(Stark.)145 2178 +y Fe(\017)49 b Fg(Reor)n(ganization)24 b(of)h(Magic)g(Source)g +(Directory)244 2298 y(Magic,)30 b(as)g(pre)n(viously)e(distrib)n(uted,) +h(w)o(as)h(set)f(up)h(with)f(the)g(assumption)f(that)h(lots)g(of)h +(people)f(w)o(ould)244 2418 y(be)h(changing)g(the)g(code)h(at)f(the)g +(same)h(time.)46 b(As)30 b(a)h(result,)g(the)f(mak)o(e\002les)g(did)g +(all)g(sorts)g(of)g(paranoid)244 2539 y(things)23 b(lik)o(e)i(making)e +(e)o(xtra)i(copies)g(of)f(the)h(source)g(code)g(whene)n(v)o(er)f(a)h +(module)f(w)o(as)h(re-installed.)244 2735 y(Since)32 +b(Magic)e(is)h(more)g(stable)g(no)n(w)-6 b(,)31 b(this)g(cop)o(ying)f +(is)h(no)g(longer)f(needed.)51 b(Instead,)32 b(each)g(mak)o(e\002le)244 +2855 y(in)l(v)n(ok)o(es)21 b(the)g(script)h Fc(../:instclean)g +Fg(after)g(installing)e(a)i(module.)29 b(This)21 b(script,)g(by)h(def)o +(ault,)g(doesn')n(t)f(cop)o(y)244 2976 y(the)26 b(source)h(code)f(b)n +(ut)g(does)g(lea)n(v)o(e)h(the)f(.o)g(\002les)h(around.)35 +b(This)26 b(cuts)g(do)n(wn)f(on)h(the)g(disk)g(space)h(needed)244 +3096 y(by)33 b(a)h(f)o(actor)g(of)g(tw)o(o.)57 b(Y)-11 +b(ou)33 b(can)h(change)g(the)g(script)f(if)g(you)h(w)o(ant)f(the)h(cop) +o(ying,)g(or)g(if)g(you)f(w)o(ant)g(to)244 3217 y(delete)25 +b(unused)f(.o)g(\002les)h(to)g(sa)n(v)o(e)f(e)n(v)o(en)g(more)h(disk)f +(space.)145 3489 y Fe(\017)49 b Fg(Lots)24 b(of)h(b)n(ug)f(\002x)o +(es\227)p Fd(V)-11 b(arious)244 3609 y Fg(Lots)25 b(of)i(b)n(ugs)e(ha)n +(v)o(e)h(been)h(\002x)o(ed)f(in)f(this)h(release.)35 +b(W)-8 b(e')j(d)27 b(lik)o(e)f(to)g(thank)f(e)n(v)o(erybody)g(that)h +(has)g(reported)244 3730 y(b)n(ugs)e(in)g(the)h(past.)30 +b(If)c(you)e(\002nd)h(a)g(ne)n(w)f(b)n(ug,)h(please)g(report)f(it)h(as) +g(mentioned)e(belo)n(w)-6 b(.)0 4157 y Ff(2)143 b(Distrib)m(ution)33 +b(Inf)l(ormation)0 4410 y Fg(This)27 b(v)o(ersion)g(of)g(Magic)h(is)f +(a)n(v)n(ailable)g(via)h(FTP)-11 b(.)28 b(Contact)g(\223)p +Fb(magic@decwrl.dec.com)p Fg(\224)23 b(for)28 b(informa-)0 +4530 y(tion.)146 4664 y(F)o(or)d(a)g(handling)f(fee,)h(this)f(v)o +(ersion)g(of)h(Magic)f(may)h(be)g(obtained)f(on)g(magnetic)g(tape)h +(from:)900 5003 y(EECS/ERL)g(Industrial)f(Liaison)g(Program)900 +5123 y(479)g(Cory)i(Hall)900 5244 y(Uni)n(v)o(ersity)d(of)h(California) +h(at)g(Berk)o(ele)o(y)900 5364 y(Berk)o(ele)o(y)-6 b(,)24 +b(CA)i(94720)1875 5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fg(Ov)o(ervie)n(w)24 b(of)h(the)f(DECWRL/Li)n(v)o +(ermore)g(Magic)g(Release)i(\(V)-11 b(ersion)25 b(6\))482 +b(September)25 b(26,)g(2001)0 99 y Ff(3)143 b(Bug)35 +b(Reports)0 327 y Fg(Maintenance)29 b(of)g(Magic)g(is)f(a)i(v)n +(olunteer)e(ef)n(fort.)44 b(Please)29 b(send)g(descriptions)f(of)h(b)n +(ugs)f(via)h(InterNet)g(e-mail)0 448 y(to)22 b(\223)p +Fb(magic@decwrl.dec.com)p Fg(\224)d(or)j(via)h(Uucp)f(e-mail)g(to)g +(\223)p Fb(decwrl!magic)p Fg(\224.)28 b(If)23 b(you)f(de)n(v)o(elop)f +(a)i(\002x)0 568 y(for)i(the)g(problem,)f(please)g(send)h(that)f(too!)0 +923 y Ff(4)143 b(Changes)34 b(f)l(or)i(Magic)f(maintainers)0 +1151 y Fg(Pre)n(vious)e(releases)h(of)g(Magic)f(e)o(xpected)g(to)g +(\002nd)h(their)f(system)g(\002les)h(in)f(the)g(home)h(directory)f(of)h +(the)f(user)0 1271 y Fc(cad)p Fg(.)41 b(The)28 b(def)o(ault)g(beha)n +(vior)g(of)g(v)o(ersion)f(6)h(is)g(no)g(dif)n(ferent,)g(b)n(ut)g(it)f +(is)h(possible)f(to)h(put)f(the)h(\002les)g(in)g(another)0 +1392 y(directory)22 b(by)h(setting)e(the)i Fc(CAD)p 1160 +1392 30 4 v 35 w(HOME)f Fg(shell)g(en)l(vironment)g(v)n(ariable.)29 +b(If)23 b(this)f(v)n(ariable)g(is)g(set,)h(magic)f(will)0 +1512 y(use)j(that)f(location)g(instead)g(of)h(the)g(\230cad)g(it)f +(\002nds)h(in)f(the)h(passw)o(ord)f(\002le.)0 1823 y +Fa(4.1)119 b(INST)-11 b(ALLING)30 b(MA)-7 b(GIC)0 2015 +y Fg(The)34 b(distrib)n(ution)e(tape)i(contains)g(a)g(v)o(ersion)g(of)g +(Magic)g(ready)g(to)g(run)g(on)g(Digital')-5 b(s)33 b(line)h(of)g +(Ultrix)g(RISC)0 2135 y(w)o(orkstations,)21 b(such)h(as)g(the)g +(DECstation)g(3100.)29 b(F)o(or)22 b(other)g(machines,)g(read)h(ahead.) +31 b(In)22 b(an)o(y)g(e)n(v)o(ent,)f(all)h(users)0 2256 +y(should)32 b(set)i(their)f(shell)g(en)l(vironment)f(v)n(ariable)i(CAD) +p 1984 2256 V 36 w(HOME)f(to)g(point)g(to)g(the)g(place)h(where)g(the)g +(tape)g(is)0 2376 y(loaded,)24 b(unless)g(that)h(place)g(is)f(\230cad,) +h(in)g(which)f(case)i(things)d(will)h(def)o(ault)h(correctly)-6 +b(.)146 2499 y(Before)26 b(installing)d(Magic,)h(you)g(should)f(set)h +(your)h(shell)f(en)l(vironment)f(v)n(ariable)h(CAD)p +3245 2499 V 36 w(HOME)g(to)g(point)0 2619 y(to)18 b(the)h(place)g +(where)h(you)e(loaded)g(the)h(tape.)29 b(If)19 b(you)g(\223cd\224)g(to) +f(the)h(magic)g(source)f(directory)h(\($CAD)p 3453 2619 +V 36 w(HOME/src/magic\))0 2740 y(you)k(will)f(\002nd)h(a)h(mak)o +(e\002le.)30 b(A)23 b(\223)p Fc(mak)o(e)h(con\002g)p +Fg(\224)g(will)f(run)g(a)g(con\002guration)g(script)f(that)h(asks)g +(questions)f(about)0 2860 y(your)j(con\002guration)f(and)g(sets)h(up)f +(magic)h(to)f(be)h(compiled)f(for)h(your)f(local)h(en)l(vironment.)146 +2983 y(After)g(running)f(a)h(\223mak)o(e)g(con\002g\224,)g(you)f(can)h +(run)f(a)h(\223)p Fc(mak)o(e)h(f)n(or)n(ce)p Fg(\224)f(to)f(force)i(a)f +(complete)f(recompilation)0 3103 y(of)k(magic.)41 b(A)28 +b(\224)p Fc(mak)o(e)i(install)p Fg(\224)d(will)h(then)g(cop)o(y)g(the)g +(binaries)g(to)g(the)g($CAD)p 2779 3103 V 36 w(HOME/bin)f(area,)j(as)e +(well)g(as)0 3224 y(install)23 b(things)h(in)g($CAD)p +905 3224 V 36 w(HOME/lib)f(and)i($CAD)p 1821 3224 V 36 +w(HOME/man.)146 3346 y(Included)k(in)f(this)f(documentation)g(is)h(a)h +(set)f(of)h(Magic)f(maintainer')-5 b(s)27 b(manuals.)41 +b(These)29 b(should)e(be)i(read)0 3467 y(by)f(an)o(ybody)f(interested)h +(in)g(modifying)e(Magic)i(or)h(by)f(an)o(ybody)f(that)h(is)f(ha)n(ving) +h(dif)n(\002culty)f(installing)g(it)g(on)0 3587 y(their)e(system.)0 +3897 y Fa(4.2)119 b(T)-11 b(echnology)30 b(\002le)h(changes)0 +4090 y Fg(Users)25 b(of)g(Magic)f(4)h(should)e(ha)n(v)o(e)i(little)f +(trouble)g(switching)f(to)h(Magic)h(6.)146 4213 y(A)39 +b(ne)n(w)f(section,)j(the)d Fc(mzr)n(outer)i Fg(section)e(needs)g(to)h +(be)f(added)h(to)f(your)g(technology)f(\002les.)72 b(See)39 +b(the)0 4333 y(mzrouter)25 b(section)f(of)h(the)f(tutorial)g +Fd(Ma)o(gic)g(Maintainer')l(s)g(Manual)f(#2:)31 b(The)25 +b(T)-9 b(ec)o(hnolo)o(gy)25 b(F)l(ile)e Fg(for)j(details.)146 +4456 y(Display)h(styles)h(must)e(be)j(de\002ned)f(in)g(the)g +Fd(.tec)o(h)f Fg(\002le)i(for)f(the)g(mzrouter)g(hint)f(layers)h +(magnet,)g(fence)h(and)0 4576 y(rotate.)46 b(W)-8 b(e)30 +b(suggest)f(cop)o(ying)g(this)g(information)g(from)g(the)h(styles)f +(section)g(of)h(the)g(scmos)f(technology)g(\002le)0 4697 +y(on)c(the)f(distrib)n(ution)f(tape.)30 b(Y)-11 b(ou')o(ll)24 +b(also)h(need)g(to)f(include)g(these)h(display)f(styles)g(in)g(your)h +Fd(.dstyle)f Fg(\002le.)0 5051 y Ff(5)143 b(Beta-test)34 +b(Sites)0 5280 y Fg(W)-8 b(e')j(d)24 b(lik)o(e)f(to)g(thank)g(the)g +(beta-test)g(sites)g(that)g(tried)g(out)g(this)f(v)o(ersion)h(of)g +(Magic,)h(reported)f(b)n(ugs)g(and)g(\002x)o(es)g(in)0 +5400 y(a)i(timely)f(manner)l(,)g(and)h(ported)g(the)f(code)h(to)g(ne)n +(w)f(machines:)1875 5649 y(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fg(September)25 b(26,)f(2001)482 b(Ov)o(ervie)n(w)24 +b(of)h(the)g(DECWRL/Li)n(v)o(ermore)e(Magic)i(Release)h(\(V)-11 +b(ersion)24 b(6\))300 84 y(Mik)o(e)g(Cho)n(w)-6 b(,)24 +b(Apple)g(Computer)300 205 y(Arun)h(Rao,)g(Arizona)g(State)g(Uni)n(v)o +(ersity)300 325 y(Richard)g(Hughe)o(y)-6 b(,)24 b(Bro)n(wn)g(Uni)n(v)o +(ersity)300 445 y(Rick)h(Carle)o(y)-6 b(,)25 b(Carne)o(gie-Mellon)f +(Uni)n(v)o(ersity)300 566 y(Hank)h(W)-8 b(alk)o(er)l(,)25 +b(Carne)o(gie-Mellon)f(Uni)n(v)o(ersity)300 686 y(Christos)g(Zoulas,)g +(Cornell)h(Uni)n(v)o(ersity)300 807 y(Andreas)g(Andreou,)f(John)g +(Hopkins)g(Uni)n(v)o(ersity)300 927 y(Geor)n(ge)h(Entenman,)f(The)h +(Microelectronics)f(Center)h(of)g(North)g(Carolina)300 +1047 y(Shih-Lien)f(Lu,)h(The)g(MOSIS)g(Service)300 1168 +y(Jen-I)g(Pi,)g(The)g(MOSIS)g(Service)300 1288 y(Guntram)f(W)-8 +b(olski,)24 b(Silicon)g(Engineering,)g(Inc.)300 1408 +y(Don)g(Stark,)i(Stanford)f(Uni)n(v)o(ersity)300 1529 +y(Gre)o(gory)f(Frazier)l(,)i(Uni)n(v)o(ersity)d(of)i(California)g(at)f +(Los)h(Angeles)300 1649 y(Y)-11 b(uv)n(al)24 b(T)-8 b(amir)l(,)24 +b(Uni)n(v)o(ersity)f(of)i(California)g(at)f(Los)h(Angeles)300 +1770 y(Ste)n(v)o(en)f(P)o(ark)o(es,)h(Uni)n(v)o(ersity)e(of)h(Illinois) +300 1890 y(Larry)h(McMurchie,)f(Uni)n(v)o(ersity)f(of)i(W)-8 +b(ashington)300 2010 y(T)m(im)23 b(Heldt,)i(W)-8 b(ashington)23 +b(State)i(Uni)n(v)o(ersity)300 2131 y(Da)n(vid)f(Lee,)i(Xerox)e(P)o +(alo)h(Alto)f(Research)i(Center)146 2479 y(Martin)i(Harriman)g(of)g +(Silicon)g(Engineering)f(wrote)h(a)g(\223select)h(less\224)f(command)f +(for)h(Magic)g(during)f(the)0 2600 y(beta-test)d(phase.)31 +b(\223Select)26 b(less\224)e(has)h(been)g(a)g(much-requested)f +(feature.)146 2720 y(In)e(addition)d(to)i(the)g(persons)g(named)g(abo)o +(v)o(e,)g(there)g(were)h(man)o(y)e(other)h(beta-test)g(users)g(of)g +(Magic)g(at)g(these)0 2841 y(and)k(other)h(sites\227too)d(man)o(y)i(to) +g(list)f(here.)33 b(W)-8 b(e)26 b(appreciate)g(their)f(help.)32 +b(W)-8 b(e)26 b(also)f(ackno)n(wledge)g(the)g(help)g(of)0 +2961 y(the)g(pre-release)h(sites,)d(who)i(tested)f(a)h(v)o(ersion)f +(that)g(included)g(most)g(of)h(the)g(\002x)o(es)f(from)h(the)g +(beta-test)f(phase.)1875 5649 y(\2264\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/maint1.ps b/doc/psfiles/maint1.ps new file mode 100644 index 00000000..9d49f0e6 --- /dev/null +++ b/doc/psfiles/maint1.ps @@ -0,0 +1,1292 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: maint1.dvi +%%Pages: 17 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman Courier +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips maint1.dvi -o maint1.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (maint1.dvi) +@start /Fa 3 104 df<0001FF0000000FFFE000003FFFF800007FFFFC0001FFFFFF0003 +FFFFFF8007FFFFFFC00FFFFFFFE01FFFFFFFF01FFFFFFFF03FFFFFFFF87FFFFFFFFC7FFF +FFFFFC7FFFFFFFFCFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFF +FFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFE7FFFFFFFFC7FFFFFFFFC7FFFFFFF +FC3FFFFFFFF81FFFFFFFF01FFFFFFFF00FFFFFFFE007FFFFFFC003FFFFFF8001FFFFFF00 +007FFFFC00003FFFF800000FFFE0000001FF000027267BAB32>15 +D<0000000FE0000000FFE0000003FC0000000FE00000003FC00000007F80000000FF0000 +0000FE00000001FC00000001FC00000003F800000003F800000003F800000003F8000000 +03F800000003F800000003F800000003F800000003F800000003F800000003F800000003 +F800000003F800000003F800000003F800000003F800000003F800000003F800000003F8 +00000003F800000003F800000003F800000003F800000003F800000003F800000003F800 +000003F800000003F800000003F800000003F800000003F800000007F000000007F00000 +000FE00000001FE00000003FC00000007F80000000FE00000007F8000000FFE0000000FF +E000000007F800000000FE000000007F800000003FC00000001FE00000000FE000000007 +F000000007F000000003F800000003F800000003F800000003F800000003F800000003F8 +00000003F800000003F800000003F800000003F800000003F800000003F800000003F800 +000003F800000003F800000003F800000003F800000003F800000003F800000003F80000 +0003F800000003F800000003F800000003F800000003F800000003F800000003F8000000 +03F800000003F800000003F800000003F800000001FC00000001FC00000000FE00000000 +FF000000007F800000003FC00000000FE000000003FC00000000FFE00000000FE0236479 +CA32>102 DI E /Fb 1 61 df<00000000000001C000000000000007E000000000 +00001FE00000000000007FC0000000000001FF00000000000007FC0000000000001FF000 +00000000007FC0000000000001FF0000000000000FFC0000000000003FF0000000000000 +FFC0000000000003FF0000000000000FF80000000000003FE0000000000000FF80000000 +000003FE0000000000001FF80000000000007FE0000000000001FF80000000000007FE00 +00000000001FF00000000000007FC0000000000001FF00000000000007FC000000000000 +1FF00000000000007FC0000000000000FF00000000000000FF000000000000007FC00000 +000000001FF000000000000007FC00000000000001FF000000000000007FC00000000000 +001FF000000000000007FE00000000000001FF800000000000007FE00000000000001FF8 +00000000000003FE00000000000000FF800000000000003FE00000000000000FF8000000 +00000003FF00000000000000FFC00000000000003FF00000000000000FFC000000000000 +01FF000000000000007FC00000000000001FF000000000000007FC00000000000001FF00 +0000000000007FC00000000000001FE000000000000007E000000000000001C03B3878B4 +4C>60 D E /Fc 137[60 60 1[60 60 2[60 60 60 60 60 1[60 +60 60 1[60 60 60 1[60 13[60 6[60 4[60 60 2[60 1[60 60 +16[60 60 60 45[{ TeXBase1Encoding ReEncodeFont }26 100.000003 +/Courier rf /Fd 103[33 29[44 50 50 72 50 55 33 39 44 +1[55 50 55 83 28 55 1[28 55 50 33 44 55 44 55 50 7[72 +72 100 72 72 66 55 72 1[61 78 72 94 66 2[39 78 78 61 +66 72 72 66 72 1[50 4[33 1[50 50 50 1[50 1[50 50 50 28 +25 33 2[50 33 33 3[50 32[55 55 2[{ TeXBase1Encoding ReEncodeFont }65 +100.000003 /Times-Bold rf /Fe 134[60 2[60 66 40 47 53 +1[66 60 66 100 33 2[33 66 60 40 53 66 53 66 60 12[80 +66 3[93 1[113 3[47 1[93 73 1[86 86 8[40 1[60 60 2[60 +60 60 60 1[33 30 40 42[66 2[{ TeXBase1Encoding ReEncodeFont }40 +119.999948 /Times-Bold rf /Ff 103[33 100 50 1[44 44 24[44 +50 50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 +50 33 44 50 44 50 44 6[61 72 72 94 72 72 61 55 66 1[55 +72 72 89 61 1[39 33 72 72 55 61 72 66 66 72 92 4[28 28 +50 50 50 50 50 50 50 50 50 50 28 25 33 25 1[50 33 33 +33 3[50 31[55 55 2[{ TeXBase1Encoding ReEncodeFont }79 +100.000003 /Times-Roman rf /Fg 133[39 44 44 66 44 50 +28 39 39 1[50 50 50 72 28 2[28 50 50 28 44 50 44 1[50 +8[61 83 61 1[55 50 3[72 66 1[55 1[44 33 72 2[61 72 66 +1[61 7[50 50 50 1[50 50 2[50 3[33 3[33 33 36[50 3[{ + TeXBase1Encoding ReEncodeFont }47 100.000003 /Times-Italic +rf /Fh 133[64 72 1[104 72 80 48 56 64 1[80 72 80 120 +40 2[40 80 72 48 64 80 64 80 72 9[143 2[96 80 2[88 112 +104 135 96 2[56 1[112 88 1[104 104 1[104 6[48 72 72 72 +72 72 72 72 72 72 72 2[48 5[48 3[72 35[{ TeXBase1Encoding ReEncodeFont } +50 143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 49 101 a Fh(Magic)36 b(Maintainer')-5 b(s)33 +b(Manual)i(#1:)44 b(Installation)33 b(and)i(De)n(v)o(elopment)1618 +521 y Fg(J)n(ohn)24 b(Ousterhout)1707 641 y(W)-9 b(alter)24 +b(Scott)1401 1062 y Ff(Computer)g(Science)i(Di)n(vision)1020 +1182 y(Electrical)f(Engineering)f(and)h(Computer)f(Sciences)1473 +1303 y(Uni)n(v)o(ersity)f(of)i(California)1544 1423 y(Berk)o(ele)o(y)-6 +b(,)24 b(CA)h(94720)1687 1693 y Fg(T)-5 b(im)25 b(Edwar)l(ds)863 +1814 y Ff(Johns)f(Hopkins)g(Uni)n(v)o(ersity)e(Applied)i(Physics)g +(Laboratory)1578 1934 y(Laurel,)h(MD)f(20723)1053 2205 +y(This)g(tutorial)g(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.)0 +2736 y Fe(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 +2942 y Ff(All)24 b(of)h(them.)0 3147 y Fe(Commands)k(intr)n(oduced)j +(in)f(this)f(tutorial:)300 3353 y Ff(:*pro\002le,)24 +b(:*runstats,)g(:*see\003ags,)g(:*w)o(atch)0 3559 y Fe(Macr)n(os)29 +b(intr)n(oduced)i(in)g(this)f(tutorial:)300 3791 y Fg(\(None\))0 +4694 y Fh(1)143 b(Intr)m(oduction)0 4918 y Ff(This)39 +b(document)g(pro)o(vides)f(some)h(information)g(to)g(help)g(system)g +(administrators)f(and)h(w)o(ould-be)g(Magic)0 5039 y(maintainers)28 +b(learn)i(about)e(the)h(system.)43 b(Before)30 b(doing)f(an)o(ything)e +(to)i(the)g(internals)f(of)i(Magic,)g(you)e(should)0 +5159 y(read)k(at)g(least)g(the)g(\002rst,)h(and)f(perhaps)g(all)f(four) +l(,)j(of)e(the)f(papers)h(on)g(Magic)g(that)f(appeared)h(together)g(in) +f(the)0 5280 y Fg(1984)25 b(Design)g(A)n(utomation)f(Confer)l(ence)p +Ff(.)34 b(In)26 b(addition,)f(the)g(follo)n(wing)f(portions)h(of)h +(magic)f(ha)n(v)o(e)g(their)h(o)n(wn)0 5400 y(papers:)1875 +5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Ff(September)25 b(26,)f(2001)630 b(Magic)24 +b(Maintainer')-5 b(s)24 b(Manual)g(#1:)30 b(Installation)23 +b(and)i(De)n(v)o(elopment)300 84 y Fd(extractor)729 b +Fg(1985)25 b(Design)f(A)n(utomation)f(Confer)l(ence)p +Ff(,)i(page)g(286.)300 205 y Fd(channel)h(r)n(outer)496 +b Fg(1985)25 b(Chapel)f(Hill)g(Confer)l(ence)i(on)e(VLSI)p +Ff(,)h(page)g(145.)300 325 y Fd(ir)n(outer)h(and)f(mzr)n(outer)219 +b Fg(1988)25 b(Design)f(A)n(utomation)f(Confer)l(ence)p +Ff(,)i(page)g(672.)300 445 y Fd(r)n(esistance)h(extractor)285 +b Fg(1987)25 b(Design)f(A)n(utomation)f(Confer)l(ence)p +Ff(,)i(page)g(570.)0 797 y Fh(2)143 b(Compiling)34 b(and)h(Installing)f +(Magic)0 1024 y Ff(If)h(you')-5 b(v)o(e)33 b(do)n(wnloaded)g(Magic)h +(via)g(FTP)-11 b(,)35 b(then)f(it)g(shouldn')n(t)f(tak)o(e)h(much)g(w)o +(ork)g(to)g(get)g(it)g(running.)58 b(Y)-11 b(ou)0 1144 +y(should)36 b(\002rst)i(pick)e(a)i(location)e(for)i(Magic')-5 +b(s)36 b(directory)h(tree.)69 b(Normally)36 b(\230cad)i(is)f(chosen,)j +(meaning)d(that)0 1265 y(\223cad\224)30 b(is)f(a)h(username)f(on)g(the) +g(system)g(with)f(a)i(home)f(directory)g(typically)f(something)g(lik)o +(e)h(/home/cad/)f(or)0 1385 y(/usr/local/cad/,)g(b)n(ut)f(you)h(might)f +(w)o(ant)h(to)g(pick)g(some)f(other)h(location)g(to)f(start,)i +(particularly)f(if)g(you)g(do)g(not)0 1505 y(ha)n(v)o(e)33 +b(root)f(pri)n(vile)o(ge)g(to)g(create)i(or)f(write)g(into)f(the)h +(\230cad)h(directory)-6 b(.)54 b(If)34 b(you)e(choose)h(a)g(dif)n +(ferent)g(location,)0 1626 y(set)28 b(your)f(shell)g(en)l(vironment)g +(v)n(ariable)g Fd(CAD)p 1661 1626 30 4 v 35 w(HOME)h +Ff(to)f(that)g(location)g(and)h(mentally)f(translate)g(the)h(\230cad)0 +1746 y(references)e(in)f(this)e(document)h(to)h(the)f(location)g(you)h +(chose.)146 1868 y(The)j(do)n(wnload)e(\002le)h(comes)g(in)g(tarred,)h +(gzipped)f(format.)38 b(F)o(ollo)n(w)26 b(the)h(standard)g(procedure)h +(to)f(uncom-)0 1989 y(press)e(and)f(e)o(xpand:)900 2232 +y(tar)h(xzf)g(magic-7.1.tar)-5 b(.gz)900 2352 y(cd)25 +b(magic-7.1)146 2593 y(F)o(ollo)n(wed)f(by)900 2836 y(mak)o(e)h +(con\002g)146 3077 y(The)32 b(\002rst)f(prompt)g(asks)g(for)h +(selection)e(of)i(the)f(graphics)g(interf)o(ace\(s\).)51 +b(Magic)32 b(is)f(designed)f(to)h(link)g(its)0 3197 y(generic)24 +b(graphics)f(calls)g(to)g(speci\002c)h(dri)n(v)o(er)e(calls)h(at)h +(runtime,)e(so)h(an)o(y)g(combination)f(of)h(choices)h(is)f(possible.)0 +3318 y(Choose)32 b(more)h(than)f(one)g(option)g(with)f(a)i +(space-separated)g(list)f(of)h(option)e(numbers)g(at)i(the)f(prompt.)53 +b(The)0 3438 y(choices)25 b(are)g(as)g(follo)n(ws:)120 +3679 y(1.)49 b Fd(X11)36 b Ff(for)h(all)f(v)o(ersions)f(of)i(X11)f +(\(currently)g(X11R6)g(is)g(standard\).)66 b(Se)n(v)o(eral)36 +b(other)h(magic)f(options)244 3799 y(mak)o(e)27 b(use)h(of)f(X11)g +(calls,)h(such)f(as)h(the)f(e)o(xtended)g(macro)g(package,)i(which)e +(uses)g(the)g(X)h(serv)o(er')-5 b(s)27 b(k)o(e)o(y)244 +3920 y(symbol)c(lookup)g(to)i(allo)n(w)e(macro)i(de\002nitions)e(on)i +(function)e(and)i(k)o(e)o(ypad)f(k)o(e)o(ys,)g(so)g(the)g(X11)h +(package)244 4040 y(is)f(preferred.)120 4253 y(2.)49 +b Fd(OpenGL)42 b Ff(for)f(systems)f(ha)n(ving)h(OpenGL)g(capability)f +(under)i(X11.)80 b(Generally)-6 b(,)44 b(this)d(applies)f(to)244 +4373 y(SGI)c(hardw)o(are,)i(and)d(Linux)f(systems)g(with)h(accelerated) +h(3D)f(video)g(hardw)o(are)g(implementing)e(the)244 4493 +y(OpenGL)39 b(API,)h(and)f(an)h(OpenGL-capable)f(accelerated)i(X)e +(serv)o(er)-5 b(.)74 b(This)39 b(option)f(is)h Fg(not)g +Ff(recom-)244 4614 y(mended)29 b(for)h(non-hardw)o(are-accelerated)h +(\(i.e.,)f(softw)o(are-implemented\))e(OpenGL)i(or)f(compatible)244 +4734 y(\(e.g.,)d(Mesa\))g(serv)o(ers,)f(because)i(the)e(interf)o(ace)i +(mak)o(es)e(hea)n(vy)h(use)g(of)f(color)h(blending,)f(implemented)244 +4855 y(in)f(softw)o(are)h(by)g(dreadfully)f(slo)n(w)g(\003ood)g +(\002lls.)120 5067 y(3.)49 b Fd(SunV)l(iew)30 b Ff(for)e(Sun)h(W)-8 +b(orkstations.)40 b(This)28 b(option)f(is)h(rather)h(out)f(of)h(date,)g +(because)g(although)e(Solaris)244 5188 y(still)c(supports)h(SunV)-6 +b(ie)n(w)g(,)24 b(it)g(also)g(supports)g(the)g(superior)h(X11)f +(protocol.)120 5400 y(4.)49 b Fd(X10)24 b Ff(is)h(le)o(gac)o(y)e(code)i +(for)g(support)f(of)h(X10,)f(the)h(precursor)g(of)g(X11.)1875 +5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Ff(Magic)24 b(Maintainer')-5 b(s)24 +b(Manual)g(#1:)30 b(Installation)24 b(and)g(De)n(v)o(elopment)628 +b(September)25 b(26,)g(2001)120 69 y(5.)49 b Fd(AED)21 +b(graphics)g(terminals)f Ff(is)h(le)o(gac)o(y)e(code)i(for)f(support)g +(of)h(ancient)f(serial-line)g(graphics)g(terminals.)244 +189 y(The)o(y)k(were)h(great)h(machines,)e(once)h(long)f(ago)g(\(see)i +(Appendix)e(A\).)146 427 y(The)f(ne)o(xt)e(prompt)g(asks)h(for)h(the)f +(tar)n(get)g(operating)g(system.)28 b(Most)22 b(modern)f(UNIX)i(types)e +(are)i(supported,)0 547 y(and)35 b(an)o(y)f(others)g(usually)g(f)o(all) +g(under)h(the)g(cate)o(gory)f(of)h(BSD-)g(or)g(SYSV)-10 +b(-compatible.)60 b(At)35 b(w)o(orst,)h(an)f(un-)0 667 +y(supported)27 b(system)h(may)g(require)g(tweaking)g(the)g(compiler)g +(\003ags,)h(which)f(is)g(best)g(done)g(directly)g(to)g(the)g(\002le)0 +788 y Fc(misc/CFLAGS)j Ff(after)i(running)f(\223mak)o(e)h +(con\002g\224.)56 b(Magic)32 b(can)i(be)f(compiled)f(for)h(only)f(one)h +(system)f(at)h(a)0 908 y(time.)d(Select)25 b(one)g(of)g(the)g(follo)n +(wing)d(options:)120 1146 y(1.)49 b Fd(Linux)120 1356 +y Ff(2.)g Fd(NetBSD)26 b(1.x)120 1566 y Ff(3.)49 b Fd(Fr)n(eeBSD)26 +b(2.x)120 1776 y Ff(4.)49 b Fd(OSF/1)24 b Ff(for)h(64-bit)f(systems)f +(such)i(as)g(the)g(Digital)e(Alpha)i(AXP)120 1986 y(5.)49 +b Fd(Solaris)24 b(2.x)120 2196 y Ff(6.)49 b Fd(SunOS)26 +b(4.x)e Ff(for)h(pre-Solaris)g(Suns.)120 2406 y(7.)49 +b Fd(SGI)24 b(IRIX)h Ff(for)g(Silicon)f(Graphics)h(systems)e(before)i +(SGI)h(mo)o(v)o(ed)d(to)h(the)h(Linux/68000)e(platform)120 +2616 y(8.)49 b Fd(OS/2)24 b(W)-6 b(ar)o(p)25 b Ff(IBM')-5 +b(s)24 b(much-too-late)g(attempt)g(to)g(o)o(v)o(erthro)n(w)f(the)i +(Bill)f(Gates)h(empire)120 2826 y(9.)49 b Fd(BSD)26 b(Unix)e(systems)h +Ff(for)g(Ultrix)f(and)g(v)n(arious)g(Berk)o(ele)o(y)h(BSD)h(4.3-based)e +(systems.)71 3036 y(10.)48 b Fd(SYSV)28 b(Unix)f(systems)f +Ff(for)i(HPUX,)f(Apple')-5 b(s)26 b(defunct)h(A/UX,)g(and)g(v)n(arious) +f(other)g(System)h(V)-10 b(-based)244 3156 y(systems.)146 +3393 y(The)36 b(third)f(prompt)g(asks)g(for)h(machine)f(architecture)h +(for)g(an)o(y)f(machines)h(requiring)f(special)g(compile)0 +3514 y(\003ags.)c(The)o(y)24 b(are)i(the)e(follo)n(wing:)120 +3751 y(1.)49 b Fd(Intel)27 b(80x86-based)g(w)o(orkstations)h +Ff(for)f(Intel)g(and)g(AMD)g(platforms)f(\(Linux,)h(NetBSD,)g(FreeBSD,) +244 3872 y(OS/2)e(W)-8 b(arp\))120 4082 y(2.)49 b Fd(HP)24 +b(68000-based)h(w)o(orkstations)120 4292 y Ff(3.)49 b +Fd(HP/P)-7 b(A-based)24 b(w)o(orkstations)120 4502 y +Ff(4.)49 b Fd(MIPS)25 b(w)o(orkstation)g Ff(\(RISCos4.0;)g(not)g +(DECStations\))120 4712 y(5.)49 b Fd(An)25 b(A)n(pple)g(MacII)g +Ff(\(A/UX\))120 4922 y(6.)49 b Fd(None)25 b(of)g(the)h(abo)o(v)o(e)f +Ff(for)g(e)n(v)o(erything)e(else)i(\(Suns,)f(SGIs,)h(DECStations,)g +(DEC)g(Alpha\))146 5159 y(The)42 b(\002nal)f(set)h(of)f(prompts)f +(selects)h(v)n(arious)g(optional)f(modules.)79 b(On)41 +b(modern)g(systems)f(with)h(v)n(ast)0 5280 y(amounts)d(of)i(memory)e +(and)h(disk)g(space,)k(the)c(best)g(choice)h(is)f(to)f(use)i(all)f(of)g +(them.)74 b(Systems)38 b(with)h(lo)n(w)0 5400 y(memory)24 +b(o)o(v)o(erhead)g(\()p Fb(<)h Ff(128MB\))f(may)h(w)o(ant)g(to)f(a)n(v) +n(oid)g(SCM)i(\(the)e(scheme)h(interpreter\).)1875 5649 +y(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Ff(September)25 b(26,)f(2001)630 b(Magic)24 +b(Maintainer')-5 b(s)24 b(Manual)g(#1:)30 b(Installation)23 +b(and)i(De)n(v)o(elopment)120 69 y(1.)49 b Fd(CALMA)p +Ff(\227module)18 b(which)g(enables)h(reading)f(and)h(writing)f(GDS-II)i +(\(otherwise)e(kno)n(wn)g(as)h(CALMA)244 189 y(or)25 +b(\223streams\224\))g(format)f(\002les.)120 394 y(2.)49 +b Fd(CIF)p Ff(\227module)29 b(which)h(enables)g(reading)h(and)f +(writing)g(Caltech)h(Intermediate)f(F)o(ormat)g(\(CIF\))i(\002les.)244 +514 y(Magic)f(only)g(kno)n(ws)f(ho)n(w)h(to)g(write)h(CIF)h(and)e +(GDS-II,)i(so)e(at)h(least)f(one)h(of)f(these)h(tw)o(o)f(ought)g(to)g +(be)244 635 y(selected.)120 840 y(3.)49 b Fd(PLO)l(T)p +Ff(\227module)25 b(for)h(graphics)g(output.)33 b(Supports)25 +b(PostScript,)h(direct)g(pix)o(el)f(output,)g(v)o(ersatec,)h(and)244 +960 y(gremlin)e(formats.)120 1165 y(4.)49 b Fd(READLINE)p +Ff(\227module)39 b(incorporating)g(the)h(GNU)h(\223readline\224)f +(package)h(\(v)o(ersion)e(4.1\))h(into)f(the)244 1286 +y(magic)24 b(command-line)g(interf)o(ace.)31 b(Readline)25 +b(implements)e(command-line)g(history)h(and)h(editing.)120 +1491 y(5.)49 b Fd(R)m(OUTE)p Ff(\227module)26 b(which)h(supports)f(v)n +(arious)g(routing)h(tools)f(\(standard)h(router)l(,)h(interacti)n(v)o +(e)e(router)l(,)244 1611 y(maze)f(router)l(,)g(channel)f(router)l(,)h +(gate-array)g(router)l(,)g(and)g(global)f(router\).)120 +1816 y(6.)49 b Fd(SCM)p Ff(\227module)26 b(implementing)g(the)h +(\223scheme\224)h(command-line)e(interpreter)l(,)i(a)g(lisp-lik)o(e)e +(program-)244 1936 y(ming)e(language)g(for)h(creating)g(ne)n(w)f +(commands)g(and)h(procedures.)120 2142 y(7.)49 b Fd(SIM)p +Ff(\227the)24 b(interacti)n(v)o(e)g(interf)o(ace)h(to)g(Stanford)g +(irsim)e(\(rsim\))i(digital)e(switch)h(simulator)-5 b(.)120 +2347 y(8.)49 b Fd(.magic)p Ff(\227Choice)25 b(of)g(using)g(either)g +(the)g(old)g(or)h(the)f(ne)n(w)g(style)g(of)h(system)e(startup)h +(\(.magic\))g(\002le.)33 b(The)244 2467 y(old)23 b(style)f(retains)h +(compatibility;)e(the)i(ne)n(w)g(\002le)g(mak)o(es)g(use)g(of)h +(interacti)n(v)o(e)d(macro)j(capability)-6 b(,)22 b(and,)h(if)244 +2587 y(compiled)h(under)g(X11,)h(e)o(xtended)f(macro)h(capability)e +(for)j(function,)d(cursor)l(,)i(and)g(k)o(e)o(ypad)f(k)o(e)o(ys.)146 +2818 y(After)h(con\002guration,)g(compile)e(and)i(install)f(using)900 +3049 y(mak)o(e)h(force)900 3169 y(mak)o(e)g(install)146 +3400 y(The)h(remaining)f(sections)g(of)g(this)g(manual)g(deal)h(with)f +(technical)h(issues)e(related)i(to)g(Magic)f(source)h(code)0 +3520 y(and)f(its)f(de)n(v)o(elopment.)0 3862 y Fh(3)143 +b(Sour)m(ce)35 b(Dir)m(ectory)f(Structur)m(e)0 4086 y +Ff(There)h(are)h(49)e(source)h(subdirectories)f(in)g(Magic.)61 +b(Most)33 b(of)i(these)g(consist)f(of)h(modules)e(of)i(source)g(code)0 +4206 y(for)30 b(the)g(system,)f(for)i(e)o(xample)d Fd(database)p +Ff(,)k Fd(main)p Ff(,)f(and)f Fd(utils)p Ff(.)45 b(See)31 +b(Section)f(5)f(of)h(this)f(document)g(for)h(brief)0 +4327 y(descriptions)d(of)i(what')-5 b(s)28 b(in)g(each)h(source)g +(directory)-6 b(.)41 b(Besides)29 b(the)f(source)h(code,)g(the)g(other) +f(subdirectories)0 4447 y(are:)145 4678 y Fa(\017)49 +b Fd(doc)244 4798 y Ff(Contains)22 b(sources)g(for)h(all)f(the)g +(documentation,)g(including)f Fg(man)h Ff(pages,)h(tutorials,)e(and)h +(maintenance)244 4918 y(manuals.)71 b(Subdirectories)39 +b(of)g Fd(doc)p Ff(,)j(e.g.)73 b Fd(doc/scmos)p Ff(,)41 +b(contain)d(the)h(technology)f(manuals.)71 b(The)244 +5039 y(Mak)o(e\002le)32 b(in)f(each)h(directory)g(can)g(be)g(used)f(to) +h(run)f(of)n(f)h(the)f(documentation.)50 b(The)32 b(tutorials,)g(main-) +244 5159 y(tenance)f(manuals,)g(and)g(technology)f(manuals)g(all)h(use) +f(LaT)-7 b(eX,)31 b(which)g(means)f(that)h(you)f(will)g(need)244 +5280 y(the)c(LaT)-7 b(eX)27 b(package)g(to)f(recompile)g(the)g(manuals) +g(from)g(source.)36 b(Documentation)25 b(is)h(also)g(a)n(v)n(ailable) +244 5400 y(online)e(in)g(HTML)g(format.)1875 5649 y(\2264\226)p +eop +%%Page: 5 5 +5 4 bop 0 -180 a Ff(Magic)24 b(Maintainer')-5 b(s)24 +b(Manual)g(#1:)30 b(Installation)24 b(and)g(De)n(v)o(elopment)628 +b(September)25 b(26,)g(2001)145 69 y Fa(\017)49 b Fd(include)244 +189 y Ff(Contains)24 b(copies)g(of)h(all)g(the)g(header)g(\002les)g +(\(*.h\))g(from)f(all)h(the)g(modules.)145 396 y Fa(\017)49 +b Fd(lib)244 516 y Ff(Contains)24 b(copies)g(of)h(each)h(of)f(the)f +(compiled)g(and)h(link)o(ed)f(modules)f(\(*.o)i(and)g(*.a\).)145 +723 y Fa(\017)49 b Fd(magic)244 843 y Ff(In)32 b(addition)f(to)g(the)h +(source)g(main\(\))g(routine,)h(this)e(directory)g(is)h(where)g(the)g +(modules)f(of)h(Magic)f(are)244 964 y(link)o(ed)24 b(to)g(form)h(the)f +(e)o(x)o(ecutable)g(v)o(ersion)g(of)h(the)g(system.)146 +1196 y(Magic)31 b(is)f(a)i(relati)n(v)o(ely)d(lar)n(ge)j(system:)41 +b(there)32 b(are)f(around)g(575)g(source)g(\002les,)h(and)f(250,000)f +(lines)g(of)i(C)0 1317 y(code.)e(In)22 b(order)g(to)f(mak)o(e)h(all)g +(of)g(this)f(manageable,)h(we')-5 b(v)o(e)22 b(or)n(ganized)f(the)h +(sources)g(in)f(a)h(tw)o(o-le)n(v)o(el)f(structure.)0 +1437 y(Each)27 b(module)e(has)i(its)e(o)n(wn)h(subdirectory)-6 +b(,)26 b(and)g(you)g(can)h(mak)o(e)g(changes)f(to)g(the)h(module)e(and) +i(recompile)f(it)0 1558 y(by)31 b(w)o(orking)g(within)f(that)h +(subdirectory)-6 b(.)50 b(The)31 b(CVS)i(method)d(of)i(softw)o(are)f +(project)h(v)o(ersion)e(management)0 1678 y(has)h(been)h(implemented)e +(to)h(mak)o(e)h(it)f(possible)f(for)i(se)n(v)o(eral)f(maintainers)f(to) +h(w)o(ork)h(in)f(parallel.)51 b(The)31 b(CVS)0 1798 y(repository)f(for) +h(magic)f(is)h(k)o(ept)f(at)h(host)f Fd(csl.cor)o(nell.edu)h +Ff(in)g(directory)f Fd(/ufs/r)n(epository)p Ff(.)49 b(P)o(articipation) +29 b(in)0 1919 y(Magic)36 b(de)n(v)o(elopment)f(requires)h(a)h(remote)f +(CVS)i(username)e(and)h(passw)o(ord)f(on)g(serv)o(er)g +Fd(csl)p Ff(.)66 b(Logging)35 b(in)0 2039 y(simply)23 +b(requires)i(the)g(e)o(x)o(ecution)e(of)i(the)f(follo)n(wing)f(CVS)j +(command:)300 2273 y(cvs)f(-d)g(:pserv)o(er:)p Fg(cvslo)o(gin)p +Ff(@csl.cornell.edu:/ufs/repository)19 b(login)146 2506 +y(T)-8 b(o)25 b(do)n(wnload)e(the)i(latest)f(release)i(of)f(magic,)f +(use)300 2739 y(cvs)h(-d)g(:pserv)o(er:)p Fg(cvslo)o(gin)p +Ff(@csl.cornell.edu:/ufs/repository)19 b(check)o(out)25 +b(magic)146 2972 y(This)j(will)f(create)i(a)f(directory)g(called)g +(\223)p Fd(magic)p Ff(\224.)40 b(It)28 b(contains)g(the)g(entire)g +(magic)f(distrib)n(ution.)38 b(Once)28 b(in)0 3092 y(the)f +Fd(magic/)f Ff(directory)-6 b(,)26 b(the)g Fd(-d)i Ff(option)d(to)h +(CVS)i(is)e(no)h(longer)f(required.)36 b(See)28 b(the)e +Fd(cvs)h(\(1\))g Ff(manual)f(page)h(for)0 3213 y(details.)49 +b(The)31 b(critical)g(CVS)h(commands)e(are)i(\223cvs)f(add\224)h(to)e +(introduce)h(ne)n(w)g(\002les)g(to)g(the)g(repository)-6 +b(,)31 b(\223cvs)0 3333 y(delete\224)h(to)f(remo)o(v)o(e)f(them,)i +(\223cvs)g(update\224)f(to)g(mer)n(ge)g(in)g(an)o(y)g(ne)n(w)g(changes) +h(found)e(in)h(the)h(repository)-6 b(,)31 b(and)0 3454 +y(\223cvs)26 b(commit\224)e(to)i(send)f(local)h(changes)f(back)h(to)g +(the)f(repository)-6 b(.)32 b(Simultaneous)25 b(changes)g(to)h(the)f +(same)h(\002le)0 3574 y(are)33 b(mer)n(ged)f(mer)n(ged)g(by)f +(heuristic;)k(con\003icts)c(are)i(\003agged,)h(to)d(be)h(resolv)o(ed)f +(by)h(hand)g(on)f(a)h(case)h(by)f(case)0 3694 y(basis.)146 +3815 y(There)26 b(are)f(tw)o(o)f(mailing)g(lists)f(associated)i(with)f +(Magic)g(de)n(v)o(elopment:)120 4022 y(1.)49 b Fc +(magic-hackers@csl.cornell.edu)31 b Ff(is)38 b(for)g(general)g(ne)n(ws) +f(and)h(discussions)e(about)h(the)244 4142 y(de)n(v)o(elopment)22 +b(process.)120 4349 y(2.)49 b Fc(magic-dev@csl.cornell.edu)26 +b Ff(is)32 b(for)g(de)n(v)o(elopers)e(only)h(and)h(pro)o(vides)f +(feedback)h(on)g(an)o(y)244 4470 y(CVS)26 b(changes)e(made)h(in)f(the)h +(repository)-6 b(.)0 4813 y Fh(4)143 b(Compiling)34 b(and)h(Installing) +0 5038 y Ff(The)25 b(top-le)n(v)o(el)f(Mak)o(e\002le)h +(\(\230cad/src/magic/Mak)o(e\002le\))g(pro)o(vides)f(man)o(y)h +(options.)30 b(Before)d(using)d(the)h(Mak)o(e-)0 5159 +y(\002le,)30 b(be)f(sure)g(to)g(set)f(your)h(CAD)p 1174 +5159 30 4 v 36 w(HOME)f(shell)g(en)l(vironment)g(v)n(ariable)g(to)h +(the)f(location)g(of)h(your)g(top-le)n(v)o(el)0 5279 +y(cad)c(directory)g(\(if)g(it)f(is)g(not)h(the)f(standard)h(\230cad\).) +146 5400 y(The)g(most)f(useful)g(Mak)o(e\002le)h(options)f(are:)1875 +5649 y(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Ff(September)25 b(26,)f(2001)630 b(Magic)24 +b(Maintainer')-5 b(s)24 b(Manual)g(#1:)30 b(Installation)23 +b(and)i(De)n(v)o(elopment)145 69 y Fa(\017)49 b Fd(mak)o(e)25 +b(con\002g)244 189 y Ff(Con\002gure)30 b(the)g(Magic)g(system)f(for)h +(a)h(particular)e(type)h(of)g(display)f(or)h(operating)g(system.)45 +b(This)29 b(just)244 309 y(runs)f(the)g Fd(:con\002g)h +Ff(shell)f(script)f(to)h(set)g(up)g(a)h(couple)f(of)g(\002les.)41 +b(The)29 b(curious)e(may)h(e)o(xamine)g(the)g(script)244 +430 y(directly)-6 b(.)63 b(If)36 b(your)g(con\002guration)f(isn')n(t)g +(handled)h(by)f(this)g(script,)j(then)e(you)f(can)i(use)e(it)h(simply)e +(as)244 550 y(a)g(guide)g(as)g(to)g(what)f(to)h(do.)58 +b(Much)34 b(of)g(the)g(con\002guration)f(is)h(done)g(with)f +(compilation)f(\003ags.)59 b(See)244 671 y(Section)25 +b Fd(??)f Ff(for)h(a)g(full)g(listing)e(of)i(them.)145 +868 y Fa(\017)49 b Fd(mak)o(e)25 b(magic)244 989 y Ff(Mak)o(e)j(a)g(v)o +(ersion)e(of)i(Magic.)39 b(All)27 b(sub-modules)f(are)i(remade,)h(if)f +(needed,)g(and)g(then)f(the)h(\002nal)g(magic)244 1109 +y(binary)c(is)h(produced.)145 1307 y Fa(\017)49 b Fd(mak)o(e)25 +b(e)o(v)o(erything)244 1427 y Ff(Same)g(as)g(\223mak)o(e)g(magic\224.) +30 b(Both)25 b(options)e(mak)o(e)i(auxilary)g(programs)f(lik)o(e)g +Fd(ext2sim)g Ff(and)h Fd(ext2spice)p Ff(.)145 1625 y +Fa(\017)49 b Fd(mak)o(e)25 b(f)n(or)n(ce)244 1745 y Ff(F)o(orce)i +(recompilation.)35 b(Lik)o(e)26 b(a)i(\223mak)o(e)e(e)n(v)o +(erything\224,)g(e)o(xcept)g(that)h(object)f(\002les)h(are)g(\002rst)g +(remo)o(v)o(ed)e(to)244 1866 y(force)g(complete)g(recompilation)e(from) +h(scratch.)145 2064 y Fa(\017)49 b Fd(mak)o(e)25 b(clean)244 +2184 y Ff(Delete)g(\002les)g(that)f(can)h(be)g(remade,)g(such)g(as)g +(binaries,)f(object,)g(and)h(library)f(\002les.)145 2382 +y Fa(\017)49 b Fd(mak)o(e)25 b(install)244 2502 y Ff(Install)f(the)g +(Magic)h(binaries)f(in)h Fd(\230cad/bin)g Ff(\(or)g Fd($)p +Fa(f)p Fd(CAD)p 2223 2502 30 4 v 36 w(HOME)p Fa(g)p Fd(/bin)f +Ff(if)h(you)f(ha)n(v)o(e)h(that)f(set\).)146 2708 y(Putting)33 +b(together)g(a)g(runnable)g(Magic)g(system)f(proceeds)i(in)f(tw)o(o)f +(steps)h(after)h(a)g(source)f(\002le)h(has)f(been)0 2828 +y(modi\002ed.)69 b(First,)41 b(the)c(source)h(\002le)g(is)g(compiled,)h +(and)f(all)g(the)f(\002les)h(in)f(its)g(module)g(are)i(link)o(ed)e +(together)0 2949 y(into)29 b(a)h(single)f(\002le)i Fg(xyz)p +Fd(.o)p Ff(,)g(where)g Fg(xyz)f Ff(is)f(the)h(name)g(of)g(the)g +(module.)45 b(Then)30 b(all)g(of)g(the)g(modules)e(are)j(link)o(ed)0 +3069 y(together)h(to)f(form)h(an)h(e)o(x)o(ecutable)e(v)o(ersion)g(of)h +(Magic.)53 b(The)32 b(command)f Fd(mak)o(e)i Ff(in)e(each)i(source)f +(directory)0 3190 y(will)f(compile)f(and)i(link)e(the)i(module)e +(locally;)k Fd(mak)o(e)e(install)f Ff(will)g(compile)f(and)i(link)e +(it,)j(and)e(also)g(install)0 3310 y(it)37 b(in)h(the)f +Fd(include)i Ff(and)f Fd(lib)g Ff(directories.)69 b(All)38 +b(Mak)o(e\002les)g(are)g(set)g(up)f(to)h(use)g(the)f(compiler)g +(\003ags)i(found)0 3430 y(in)30 b Fd(\230cad/sr)n(c/magic/misc/DFLA)-5 +b(GS)29 b Ff(and)i Fd(\230cad/sr)n(c/magic/misc/CFLA)-5 +b(GS)p Ff(.)29 b(A)i(list)e(of)i(\003ags)g(appears)f(in)0 +3551 y(Section)25 b Fd(??)o Ff(.)146 3671 y(The)32 b(command)f +Fd(mak)o(e)h Ff(in)g(the)f(subdirectory)g Fd(magic)h +Ff(will)f(produce)h(a)g(runnable)f(v)o(ersion)g(of)h(Magic)f(in)0 +3791 y(that)26 b(directory)-6 b(,)26 b(using)f(the)h(installed)f(v)o +(ersions)g(of)h(all)g(modules.)34 b(T)-8 b(o)26 b(w)o(ork)g(with)f(the) +h(uninstalled)f(v)o(ersion)g(of)0 3912 y(a)k(module,)e(create)i +(another)g(subdirectory)e(identical)g(to)h Fd(magic)p +Ff(,)h(and)f(modify)f(the)h(Mak)o(e\002le)g(so)g(that)g(it)f(uses)0 +4032 y(uninstalled)33 b(v)o(ersions)h(of)h(the)g(rele)n(v)n(ant)f +(modules.)60 b(F)o(or)35 b(e)o(xample,)i(the)e(Magic)g(team)f(uses)h +(subdirectories)0 4153 y Fd(hamachitest)p Ff(,)43 b Fd(may)n(otest)p +Ff(,)f Fd(mhatest)p Ff(,)g Fd(oustertest)p Ff(,)i(and)39 +b Fd(wsstest)f Ff(that)h(we)g(use)f(to)h(test)f(ne)n(w)h(v)o(ersions)e +(of)0 4273 y(modules)21 b(before)i(installing)d(them.)29 +b(If)23 b(you)f(w)o(ant)g(to)g(remak)o(e)h(the)f(entire)g(system,)g +(type)g(\223mak)o(e)g(magic\224)g(in)g(the)0 4393 y(top-le)n(v)o(el)h +(directory)i(\()p Fd(\230cad/sr)n(c/magic)p Ff(\).)0 +4730 y Fh(5)143 b(Summary)34 b(of)h(Magic)g(Modules)0 +4953 y Ff(This)24 b(section)g(contains)g(brief)h(summaries)f(of)h(what) +f(is)h(in)f(each)h(of)g(the)g(Magic)f(source)h(subdirectories.)145 +5159 y Fa(\017)49 b Fd(calma)244 5280 y Ff(Contains)26 +b(code)h(to)g(read)h(and)f(write)f(Calma)i(Stream-format)f(\002les.)37 +b(It)27 b(uses)g(man)o(y)f(of)h(the)g(procedures)244 +5400 y(in)d(the)h Fd(cif)g Ff(module.)1875 5649 y(\2266\226)p +eop +%%Page: 7 7 +7 6 bop 0 -180 a Ff(Magic)24 b(Maintainer')-5 b(s)24 +b(Manual)g(#1:)30 b(Installation)24 b(and)g(De)n(v)o(elopment)628 +b(September)25 b(26,)g(2001)145 69 y Fa(\017)49 b Fd(cif)244 +189 y Ff(Contains)22 b(code)i(to)f(process)g(the)g(CIF)h(sections)e(of) +h(technology)f(\002les,)i(and)f(to)g(generate)h(CIF)g(\002les)f(from) +244 309 y(Magic.)145 518 y Fa(\017)49 b Fd(cmwind)244 +638 y Ff(Contains)24 b(code)h(to)f(implement)g(special)g(windo)n(ws)f +(for)i(editing)f(color)h(maps.)145 846 y Fa(\017)49 b +Fd(commands)244 966 y Ff(The)22 b(procedures)g(in)g(this)g(module)f +(contain)g(the)h(top-le)n(v)o(el)f(command)g(routines)g(for)i(layout)e +(commands)244 1087 y(\(commands)28 b(that)g(are)i(v)n(alid)e(in)h(all)f +(windo)n(ws)g(are)i(handled)e(in)h(the)g Fd(windo)o(ws)g +Ff(module\).)42 b(These)29 b(rou-)244 1207 y(tines)21 +b(generally)h(just)g(parse)g(the)g(commands,)g(check)g(for)h(errors,)g +(and)f(call)g(other)h(routines)e(to)h(carry)h(out)244 +1328 y(the)i(actions.)145 1536 y Fa(\017)49 b Fd(database)244 +1656 y Ff(This)23 b(is)h(the)g(lar)n(gest)g(and)g(most)e(important)h +(Magic)h(module.)29 b(It)24 b(implements)e(the)i(hierarchical)g(corner) +n(-)244 1776 y(stitched)g(database,)h(and)f(reads)h(and)g(writes)g +(Magic)f(\002les.)145 1984 y Fa(\017)49 b Fd(dbwind)244 +2105 y Ff(Pro)o(vides)30 b(display)g(functions)g(speci\002c)h(to)g +(layout)f(windo)n(ws,)h(including)e(managing)h(the)h(box,)h(redis-)244 +2225 y(playing)24 b(layout,)g(and)g(displaying)f(highlights)g(and)i +(feedback.)145 2433 y Fa(\017)49 b Fd(deb)n(ug)244 2554 +y Ff(There')-5 b(s)25 b(not)f(much)g(in)g(this)g(module,)g(just)g(a)h +(fe)n(w)g(routines)f(used)g(for)h(deb)n(ugging)f(purposes.)145 +2762 y Fa(\017)49 b Fd(dr)n(c)244 2882 y Ff(This)28 b(module)f +(contains)h(the)g(incremental)g(design-rule)g(check)o(er)-5 +b(.)42 b(It)29 b(contains)f(code)g(to)g(read)i(the)e +Fd(dr)n(c)244 3003 y Ff(sections)c(of)i(technology)e(\002les,)i(record) +g(areas)g(to)f(be)h(recheck)o(ed,)g(and)g(recheck)g(those)f(areas)h(in) +f(a)h(hier)n(-)244 3123 y(archical)f(f)o(ashion.)145 +3331 y Fa(\017)49 b Fd(ext2dlys)244 3451 y Ff(The)27 +b Fd(ext2dlys)f Ff(directory)g(isn')n(t)h(part)f(of)h(Magic)f(itself.) +36 b(It')-5 b(s)26 b(a)h(self-contained)f(program)h(that)f(uses)g(the) +244 3572 y(hierarchical)g Fd(.ext)g Ff(\002les)g(generated)h(by)e +(Magic')-5 b(s)25 b(e)o(xtractor)h(and)g(an)g(optional)f(netlist)f +(\002le)j(designating)244 3692 y(net)f(pinouts)g(\(for)h(purposes)f(of) +h(counting)e(I/O)i(loads\),)f(and)h(produces)g(a)g(wire-delay)f +(\002le.)37 b(Also)26 b(com-)244 3813 y(piles)h(an)h(e)o(x)o(ecutable)f +Fd(sim2dlys)g Ff(for)i(delay)f(calculations)f(from)g +Fd(.sim)h Ff(\002les.)40 b(These)28 b(programs)g(are)g(no)244 +3933 y(longer)c(compiled)g(and)h(the)f(module)g(has)h(been)g(commented) +f(out)g(in)g(the)h(top-le)n(v)o(el)e Fd(Mak)o(e\002le)p +Ff(.)145 4141 y Fa(\017)49 b Fd(ext2sim)244 4261 y Ff(This)28 +b(is)h(another)h(self-contained)e(program.)44 b(It')-5 +b(s)29 b(a)h(self-contained)f(program)g(that)f(\003attens)i(the)f(hier) +n(-)244 4382 y(archical)j Fd(.ext)f Ff(\002les)h(generated)f(by)g +(Magic')-5 b(s)31 b(e)o(xtractor)f(into)h(a)h(single)e(\002le)i(in)e +Fd(.sim)h Ff(format.)50 b(See)32 b(the)244 4502 y(manual)24 +b(page)h Fd(ext2sim)f(\(1\))p Ff(.)145 4710 y Fa(\017)49 +b Fd(ext2spice)244 4831 y Ff(This)26 b(is)g(another)g(self-contained)g +(program.)36 b(It)26 b(con)l(v)o(erts)g Fd(.ext)h Ff(\002les)g(into)e +(single)h(\002le)h(in)f(spice)g(format.)244 4951 y(See)g(the)e(manual)g +(page)h Fd(ext2spice)h(\(1\))p Ff(.)145 5159 y Fa(\017)49 +b Fd(extcheck)244 5280 y Ff(Y)-10 b(et)22 b(another)f(independent)g +(program.)30 b(This)21 b(one)g(checks)i(the)e Fd(.ext)h +Ff(\002les)g(for)g(global)f(node)h(connecti)n(vity)244 +5400 y(and)j(summarizes)e(the)i(number)f(of)h(FETs,)g(nodes,)f(etc.)31 +b(See)26 b(the)f(manual)f(page)h Fd(extcheck)h(\(1\))p +Ff(.)1875 5649 y(\2267\226)p eop +%%Page: 8 8 +8 7 bop 0 -180 a Ff(September)25 b(26,)f(2001)630 b(Magic)24 +b(Maintainer')-5 b(s)24 b(Manual)g(#1:)30 b(Installation)23 +b(and)i(De)n(v)o(elopment)145 69 y Fa(\017)49 b Fd(ext\003at)244 +189 y Ff(Contains)31 b(code)g(that)g(is)g(used)g(by)g(the)h +Fd(extract)g Ff(module)e(and)h(the)h Fd(ext2.)15 b(.)g(.)65 +b Ff(programs.)50 b(The)31 b(module)244 309 y(produces)24 +b(a)i(library)e(that)g(is)h(link)o(ed)f(in)g(with)g(the)h(abo)o(v)o(e)f +(programs.)145 542 y Fa(\017)49 b Fd(extract)244 662 +y Ff(Contains)28 b(code)h(to)g(read)g(the)g Fd(extract)g +Ff(sections)f(of)h(technology)f(\002les,)i(and)f(to)f(generate)i +(hierarchical)244 782 y(circuit)24 b(descriptions)g(\()p +Fd(.ext)h Ff(\002les\))g(from)g(Magic)f(layouts.)145 +1015 y Fa(\017)49 b Fd(fsleeper)244 1135 y Ff(Lik)o(e)29 +b Fd(ext2sim)p Ff(,)g(this)g(directory)f(is)h(a)h(self-contained)e +(program)h(that)g(allo)n(ws)e(a)j(graphics)f(terminal)f(at-)244 +1255 y(tached)20 b(to)g(one)h(machine)e(to)h(be)h(used)f(with)f(Magic)h +(running)g(on)g(a)g(dif)n(ferent)g(machine.)29 b(See)22 +b(the)e(manual)244 1376 y(page)25 b Fd(fsleeper)h(\(1\))p +Ff(.)145 1608 y Fa(\017)49 b Fd(gar)n(outer)244 1728 +y Ff(Contains)24 b(the)h(gate)f(array)i(router)e(from)h(La)o(wrence)g +(Li)n(v)o(ermore)f(National)g(Labs.)145 1960 y Fa(\017)49 +b Fd(gcr)244 2081 y Ff(Contains)25 b(the)h(channel)g(router)l(,)g +(which)f(is)h(an)g(e)o(xtension)e(of)i(Ri)n(v)o(est')-5 +b(s)25 b(greedy)h(router)g(that)f(can)h(handle)244 2201 +y(switchbox)o(es)d(and)i(obstacles)f(in)g(the)h(channels.)145 +2433 y Fa(\017)49 b Fd(graphics)244 2554 y Ff(This)23 +b(is)g(the)g(lo)n(west-le)n(v)o(el)e(graphics)j(module.)29 +b(It)23 b(contains)g(dri)n(v)o(er)g(routines)f(for)i(X11)f(and)h +(OpenGL)f(as)244 2674 y(well)f(as)h(le)o(gac)o(y)f(dri)n(v)o(ers)g(for) +h(the)g(AED)g(f)o(amily)f(of)h(display)f(terminals,)g(Sun)h(W)l(indo)n +(ws,)e(and)i(X10.)30 b(The)244 2795 y(code)24 b(here)g(does)f(basic)h +(clipping)e(and)h(dra)o(wing.)30 b(If)24 b(you)f(w)o(ant)g(to)h(mak)o +(e)f(Magic)g(run)h(on)f(a)h(ne)n(w)f(kind)g(of)244 2915 +y(display)-6 b(,)23 b(this)h(is)g(the)h(only)f(module)g(that)g(should)g +(ha)n(v)o(e)g(to)h(change.)145 3147 y Fa(\017)49 b Fd(gr)n(outer)244 +3267 y Ff(The)24 b(\002les)h(in)f(this)f(module)g(implement)g(the)h +(global)g(router)l(,)g(which)g(computes)g(the)g(sequence)g(of)h(chan-) +244 3388 y(nels)f(that)h(each)g(net)g(is)f(to)g(pass)h(through.)145 +3620 y Fa(\017)49 b Fd(ir)n(outer)244 3740 y Ff(Contains)28 +b(the)g(interacti)n(v)o(e)f(router)h(written)g(by)g(Michael)f(Arnold)h +(at)g(La)o(wrence)h(Li)n(v)o(ermore)e(National)244 3861 +y(Labs.)68 b(This)37 b(router)g(allo)n(ws)f(the)h(user)h(to)f(route)g +(nets)g(interacti)n(v)o(ely)-6 b(,)38 b(using)e(special)i(hint)e +(layers)h(to)244 3981 y(control)24 b(the)h(routing.)145 +4213 y Fa(\017)49 b Fd(lisp)244 4334 y Ff(This)24 b(module)g(contains)g +(code)i(which,)e(if)h(the)g(SCHEME)g(option)f(is)h(chosen)f(at)i +(compile)e(time,)g(imple-)244 4454 y(ments)k(the)h(lisp-lik)o(e)f +(\223scheme\224)i(interpreter)-5 b(.)43 b(Scheme)30 b(enables)f(magic)g +(commands)f(to)h(be)g(e)o(x)o(ecuted)244 4574 y(in)24 +b(a)h(programming)f(language)g(frame)n(w)o(ork,)h(so)f(comple)o(x)g +(functions)f(can)j(be)e(de\002ned.)145 4807 y Fa(\017)49 +b Fd(macr)n(os)244 4927 y Ff(Implements)23 b(simple)h(k)o(e)o(yboard)g +(macros.)145 5159 y Fa(\017)49 b Fd(magicusage)244 5280 +y Ff(Lik)o(e)28 b Fd(ext2sim)p Ff(,)i(this)d(is)i(also)f(a)h +(self-contained)f(program.)42 b(It)29 b(searches)g(through)f(a)h +(layout)f(to)h(\002nd)f(all)244 5400 y(the)d(\002les)g(that)f(are)h +(used)g(in)f(it.)31 b(See)25 b Fd(magicusage)g Ff(\(1\).)1875 +5649 y(\2268\226)p eop +%%Page: 9 9 +9 8 bop 0 -180 a Ff(Magic)24 b(Maintainer')-5 b(s)24 +b(Manual)g(#1:)30 b(Installation)24 b(and)g(De)n(v)o(elopment)628 +b(September)25 b(26,)g(2001)145 69 y Fa(\017)49 b Fd(main)244 +189 y Ff(This)23 b(module)g(contains)g(the)h(main)f(program)g(for)h +(Magic,)g(which)g(parses)g(command-line)e(parameters,)244 +309 y(initializes)h(the)i(w)o(orld,)f(and)h(then)f(transfers)h(control) +f(to)h Fd(textio)p Ff(.)145 507 y Fa(\017)49 b Fd(misc)244 +627 y Ff(A)25 b(fe)n(w)f(small)g(things)g(that)g(didn')n(t)g(belong)g +(an)o(yplace)h(else.)145 824 y Fa(\017)49 b Fd(mpack)244 +944 y Ff(Contains)22 b(routines)g(that)g(implement)f(the)i(Tpack)f +(tile-packing)g(interf)o(ace)h(using)f(the)h(Magic)f(database.)244 +1065 y(\(not)i(supported\))145 1262 y Fa(\017)49 b Fd(mzr)n(outer)244 +1382 y Ff(Contains)24 b(maze)h(routing)f(routines)g(that)g(are)i(used)e +(by)h(the)f(irouter)h(and)g(garouter)f(modules.)145 1579 +y Fa(\017)49 b Fd(net2ir)244 1700 y Ff(Contains)24 b(a)h(program)g(to)f +(con)l(v)o(ert)g(a)h(netlist)f(into)g(irouter)g(commands.)145 +1897 y Fa(\017)49 b Fd(netlist)244 2017 y Ff(Netlist)23 +b(manipulation)g(routines.)145 2214 y Fa(\017)49 b Fd(netmenu)244 +2335 y Ff(Implements)23 b(netlists)g(and)i(the)g(special)f +(netlist-editing)f(windo)n(ws.)145 2532 y Fa(\017)49 +b Fd(parser)244 2652 y Ff(Contains)24 b(the)h(code)g(that)f(parses)h +(command)f(lines)g(into)g(ar)n(guments.)145 2849 y Fa(\017)49 +b Fd(plot)244 2970 y Ff(The)38 b(internals)g(of)h(the)f +Fd(:plot)h Ff(command.)70 b(Code)39 b(to)f(write)h(PostScript,)i(ra)o +(w)e(pix)o(el,)h(v)o(ersatec,)i(and)244 3090 y(gremlin)24 +b(formats.)145 3287 y Fa(\017)49 b Fd(plo)o(w)244 3408 +y Ff(This)24 b(module)g(contains)g(the)g(code)h(to)g(support)f(the)g +Fd(:plo)o(w)h Ff(and)g Fd(:straighten)h Ff(commands.)145 +3605 y Fa(\017)49 b Fd(prleak)244 3725 y Ff(Also)35 b(not)f(part)i(of)f +(Magic)g(itself.)62 b(Prleak)36 b(is)f(a)h(self-contained)f(program)g +(intended)g(for)g(use)h(in)f(de-)244 3846 y(b)n(ugging)25 +b(Magic')-5 b(s)25 b(memory)h(allocator)-5 b(.)34 b(It)26 +b(analyzes)h(a)f(trace)h(of)f(mallocs/frees)g(to)g(look)f(for)i(memory) +244 3966 y(leaks.)j(See)c(the)f(manual)f(page)h Fd(prleak)h(\(8\))f +Ff(for)g(information)e(on)i(what)f(the)h(program)f(does.)145 +4163 y Fa(\017)49 b Fd(r)n(eadline)244 4283 y Ff(\223readline\224)38 +b(is)g(an)g(independent)f(library)g(of)h(routines)f(implementing)f +(command-line)g(history)h(and)244 4404 y(editing.)29 +b(V)-11 b(ersion)25 b(7.1)f(of)h(magic)f(uses)h(GNU)g(readline-4.1.)145 +4601 y Fa(\017)49 b Fd(r)n(esis)244 4721 y Ff(Resis)25 +b(is)f(a)h(module)f(that)h(does)f(better)h(resistance)g(e)o(xtraction)f +(via)g(the)h(:e)o(xtresis)e(command.)30 b(Courtesy)244 +4842 y(of)25 b(Don)f(Stark)h(of)g(Stanford.)145 5039 +y Fa(\017)49 b Fd(r)n(outer)244 5159 y Ff(Contains)22 +b(the)i(top-le)n(v)o(el)d(routing)h(code,)i(including)e(procedures)h +(to)g(read)h(the)f(router)g(sections)g(of)g(tech-)244 +5280 y(nology)j(\002les,)i(chop)f(free)h(space)f(up)g(into)f(channels,) +i(analyze)f(obstacles,)g(and)g(paint)g(back)g(the)g(results)244 +5400 y(produced)d(by)h(the)g(channel)f(router)-5 b(.)1875 +5649 y(\2269\226)p eop +%%Page: 10 10 +10 9 bop 0 -180 a Ff(September)25 b(26,)f(2001)630 b(Magic)24 +b(Maintainer')-5 b(s)24 b(Manual)g(#1:)30 b(Installation)23 +b(and)i(De)n(v)o(elopment)145 67 y Fa(\017)49 b Fd(select)244 +187 y Ff(This)23 b(module)f(contains)h(\002les)g(that)g(manage)h(the)f +(selection.)30 b(The)23 b(routines)g(here)h(pro)o(vide)e(f)o(acilities) +h(for)244 308 y(making)30 b(a)h(selection,)g(enumerating)f(what')-5 +b(s)30 b(in)h(the)g(selection,)g(and)g(manipulating)e(the)h(selection)g +(in)244 428 y(se)n(v)o(eral)24 b(w)o(ays,)g(such)h(as)g(mo)o(ving)e(it) +h(or)h(cop)o(ying)f(it.)145 684 y Fa(\017)49 b Fd(signals)244 +804 y Ff(Handles)24 b(signals)g(such)g(as)h(the)g(interrupt)f(k)o(e)o +(y)g(and)h(control-Z.)145 1060 y Fa(\017)49 b Fd(sim)244 +1180 y Ff(Pro)o(vides)24 b(an)h(interacti)n(v)o(e)e(interf)o(ace)j(to)e +(the)h(simulator)e(rsim.)30 b(Courtesy)25 b(of)g(Mik)o(e)f(Cho)n(w)g +(of)h(Stanford.)145 1436 y Fa(\017)49 b Fd(tech)244 1557 +y Ff(This)24 b(module)h(contains)f(the)h(top-le)n(v)o(el)e(technology)h +(\002le)i(reading)f(code,)h(and)f(the)g(current)g(technology)244 +1677 y(\002les.)51 b(The)31 b(code)h(does)f(little)g(e)o(xcept)g(to)g +(read)h(technology)e(\002le)i(lines,)h(parse)e(them)g(into)g(ar)n +(guments,)244 1797 y(and)25 b(pass)f(them)g(of)n(f)h(to)f(clients)g(in) +h(other)f(modules)g(\(such)h(as)f Fd(dr)n(c)i Ff(or)f +Fd(database)p Ff(\).)145 2053 y Fa(\017)49 b Fd(textio)244 +2173 y Ff(The)37 b(top-le)n(v)o(el)d(command)i(interpreter)-5 +b(.)66 b(This)36 b(module)f(grabs)i(commands)e(from)i(the)f(k)o(e)o +(yboard)g(or)244 2294 y(mouse)e(and)h(sends)f(them)g(to)h(the)g(windo)n +(w)e(module)h(for)h(processing.)60 b(Also)34 b(pro)o(vides)g(routines)g +(for)244 2414 y(message)24 b(and)h(error)h(printout,)d(and)i(to)f +(manage)h(the)f(prompt)g(on)h(the)f(screen.)145 2670 +y Fa(\017)49 b Fd(tiles)244 2790 y Ff(Implements)27 b(basic)h(corner)n +(-stitched)g(tile)f(planes.)41 b(This)28 b(module)f(w)o(as)h(separated) +h(from)f Fd(database)g Ff(in)244 2911 y(order)d(to)f(allo)n(w)g(other)h +(clients)f(to)g(use)h(tile)f(planes)h(without)e(using)h(the)g(other)h +(database)g(f)o(acilities)f(too.)145 3167 y Fa(\017)49 +b Fd(undo)244 3287 y Ff(The)32 b Fd(undo)i Ff(module)d(pro)o(vides)g +(the)i(o)o(v)o(erall)e(frame)n(w)o(ork)h(for)h(undo)e(and)i(redo)f +(operations,)i(in)e(that)g(it)244 3407 y(stores)38 b(lists)f(of)i +(actions.)71 b(Ho)n(we)n(v)o(er)l(,)41 b(all)d(the)h(speci\002c)g +(actions)f(are)h(managed)g(by)f(clients)g(such)g(as)244 +3528 y Fd(database)25 b Ff(or)g Fd(netmenu)p Ff(.)145 +3783 y Fa(\017)49 b Fd(utils)244 3904 y Ff(This)22 b(module)g +(implements)g(a)h(whole)g(b)n(unch)g(of)g(utility)e(procedures,)j +(including)e(a)h(geometry)g(package)244 4024 y(for)37 +b(dealing)e(with)h(rectangles)g(and)h(points)e(and)h(transformations,)i +(a)e(heap)h(package,)j(a)c(hash)g(table)244 4145 y(package,)25 +b(a)g(stack)g(package,)g(a)g(re)n(vised)f(memory)g(allocator)l(,)h(and) +f(lots)g(of)h(other)g(stuf)n(f.)145 4400 y Fa(\017)49 +b Fd(windo)o(ws)244 4521 y Ff(This)20 b(is)g(the)h(o)o(v)o(erall)e +(windo)n(w)g(manager)-5 b(.)29 b(It)21 b(k)o(eeps)g(track)g(of)f(windo) +n(ws)f(and)i(calls)f(clients)g(\(lik)o(e)h Fd(dbwind)244 +4641 y Ff(and)f Fd(cmwind)p Ff(\))h(to)f(process)g(windo)n +(w-speci\002c)f(operations)g(such)h(as)g(redisplaying)f(or)h +(processing)f(com-)244 4762 y(mands.)42 b(Commands)27 +b(that)i(are)g(v)n(alid)f(in)g(all)g(windo)n(ws,)g(such)h(as)g +(resizing)f(or)h(mo)o(ving)d(windo)n(ws,)i(are)244 4882 +y(implemented)23 b(here.)145 5138 y Fa(\017)49 b Fd(wiring)244 +5258 y Ff(The)23 b(\002les)g(in)f(this)g(directory)h(implement)e(the)i +Fd(:wir)n(e)g Ff(command.)30 b(There)23 b(are)h(routines)e(to)g(select) +h(wiring)244 5378 y(material,)h(add)h(wire)g(le)o(gs,)f(and)g(place)i +(contacts.)1850 5649 y(\22610\226)p eop +%%Page: 11 11 +11 10 bop 0 -180 a Ff(Magic)24 b(Maintainer')-5 b(s)24 +b(Manual)g(#1:)30 b(Installation)24 b(and)g(De)n(v)o(elopment)628 +b(September)25 b(26,)g(2001)0 99 y Fh(6)143 b(P)m(ortability)34 +b(Issues)0 325 y Ff(Magic)23 b(runs)g(on)g(a)g(v)n(ariety)g(of)g +(machines.)30 b(Running)23 b(\223mak)o(e)g(con\002g\224)h(in)e(the)i +(top-le)n(v)o(el)d(source)j(directory)f(sets)0 446 y(the)h(compiletime) +f(options.)28 b(If)d(you)f(are)h(porting)e(Magic,)h(you)g(should)f +(modify)g(the)h(con\002guration)g(section)f(at)0 566 +y(the)i(end)h(of)g(\002le)g(\224misc/magic.h\224)e(to)h(suit)g(your)h +(machine,)f(by)g(testing)g(compiler)g(\003ags.)33 b(No)26 +b(changes)f(should)0 687 y(be)g(made)g(that)f(w)o(ould)g(hamper)h +(Magic')-5 b(s)24 b(operation)g(on)g(other)h(machines.)0 +1035 y Fh(7)143 b(Compilation)33 b(Switches)0 1262 y +Fd(??)146 1384 y Ff(Ov)o(er)c(the)g(years)g(Magic)g(has)g(acquired)g(a) +h(number)e(of)h(compilation)e(switches.)43 b(While)29 +b(it')-5 b(s)28 b(undesirable)0 1504 y(to)23 b(ha)n(v)o(e)f(so)h(man)o +(y)-6 b(,)22 b(it)g(seems)h(una)n(v)n(oidable)f(since)h(people)f(use)h +(Magic)g(on)g(such)f(a)i(wide)e(v)n(ariety)h(of)g(machines.)0 +1625 y(The)30 b(\002le)h(\230cad/src/magic/misc/DFLA)l(GS)d(should)h +(contain)h(the)g(compile)f(switches)g(that)h(you)f(wish)h(to)f(use)0 +1745 y(at)i(your)g(site.)50 b(All)30 b(mak)o(e\002les)h(for)h(Magic)f +(reference)h(the)g(common)e(DFLA)l(GS)h(\002le.)51 b(The)31 +b(switches)f(in)h(this)0 1865 y(release)25 b(are)h(sho)n(wn)e(belo)n(w) +-6 b(.)146 1987 y(These)23 b(\003ags)h(are)g(normally)e(setup)g(by)h +(running)f(the)h(\224mak)o(e)g(con\002g\224)h(script)e(in)h +(\230cad/src/magic.)30 b(Some)23 b(of)0 2108 y(them)h(are)i(turned)e +(on)h(in)f(\224magic.h\224)h(when)f(a)i(particular)e(machine)h +(con\002guration)f(is)g(detected.)0 2412 y Fe(7.1)119 +b(Machine/OS)32 b(Compiletime)e(Options)0 2603 y Ff(The)24 +b(follo)n(wing)d(switches)i(should)g(be)h(de\002ned)g(automatically)e +(by)h(the)h Fd(:con\002g)g Ff(script)g(upon)f(selection)f(of)i(the)0 +2723 y(tar)n(get)h(hardw)o(are)g(and)g(OS.)145 2962 y +Fa(\017)49 b Ff(mips)244 3082 y(F)o(or)25 b(mips)e(processors,)i(such)f +(as)h(the)g(DECstation.)145 3293 y Fa(\017)49 b Ff(MIPSEL)244 +3413 y(F)o(or)25 b(little-endian)e(mips)h(processors,)g(such)h(as)f +(the)h(DECstation)f(3100.)145 3624 y Fa(\017)49 b Ff(MIPSEB)244 +3744 y(F)o(or)25 b(big-endian)f(mips)f(processors.)145 +3955 y Fa(\017)49 b Ff(sun)244 4076 y(F)o(or)25 b(Sun)g(machines.)145 +4286 y Fa(\017)49 b Ff(mc68000)244 4407 y(F)o(or)25 b(machines)f(which) +g(ha)n(v)o(e)h(a)g(v)o(ersion)f(of)h(the)f(68000)g(as)h(the)g +(processor)-5 b(.)145 4617 y Fa(\017)49 b Ff(sparc)244 +4738 y(Sparc-based)26 b(machines.)145 4949 y Fa(\017)49 +b Ff(i386)244 5069 y(F)o(or)25 b(Intel)f(x86-based)h(machines.)145 +5280 y Fa(\017)49 b Ff(linux)244 5400 y(F)o(or)25 b(Linux)f(systems.) +1850 5649 y(\22611\226)p eop +%%Page: 12 12 +12 11 bop 0 -180 a Ff(September)25 b(26,)f(2001)630 b(Magic)24 +b(Maintainer')-5 b(s)24 b(Manual)g(#1:)30 b(Installation)23 +b(and)i(De)n(v)o(elopment)145 45 y Fa(\017)49 b Ff(v)n(ax)244 +166 y(F)o(or)25 b(V)-13 b(AX)24 b(machines)g(\(le)o(gac)o(y\).)145 +379 y Fa(\017)49 b Ff(lint)244 499 y(Used)25 b(to)f(bypass)g(things)g +(that)g(lint)g(complains)f(about.)30 b(Don')n(t)25 b(turn)f(this)g(on.) +31 b(Lint)23 b(turns)i(it)f(on)g(itself.)146 740 y(If)i(needed,)f(you)f +(can)h(put)f(the)h(follo)n(wing)e(switches)h(in)g(the)h(DFLA)l(GS)g +(\002le:)145 982 y Fa(\017)49 b Ff(macII)244 1102 y(F)o(or)25 +b(the)f(Apple)h(Mac-II)g(\(running)f(A/UX\))h(\(le)o(gac)o(y\).)145 +1315 y Fa(\017)49 b Ff(SUNVIEW)244 1435 y(Used)25 b(when)f(including)f +(Magic')-5 b(s)24 b(SunV)-6 b(ie)n(w)25 b(graphics)f(dri)n(v)o(ers.)145 +1648 y Fa(\017)49 b Ff(SUN120)244 1769 y(F)o(or)25 b(the)f(Sun120)h +(machine)f(\(le)o(gac)o(y\).)145 1982 y Fa(\017)49 b +Ff(BSD4)p 493 1982 30 4 v 36 w(2)244 2102 y(Used)31 b(in)f(the)h(utils) +f(module)g(to)g(patch)h(around)g(a)g(brok)o(en)g(v)o(ersion)f(of)h +(\003sb)n(uf\(\))g(that)g(is)f(needed)i(in)e(the)244 +2222 y(V)-13 b(AX)31 b(v)o(ersion)f(of)h(Unix)g(4.2)g(BSD)i(systems.)49 +b(This)30 b(is)h(rarely)h(needed,)h(since)e(almost)g(all)g(v)o(ersion)f +(of)244 2343 y(Unix)24 b(no)n(w)g(ha)n(v)o(e)h(this)e(b)n(ug)i(\002x)o +(ed)f(\(le)o(gac)o(y\).)145 2555 y Fa(\017)49 b Ff(F)-7 +b(ASYNC)244 2676 y(Hack)25 b(for)g(some)f(v)o(ersions)g(of)h(Sun2)f +(softw)o(are)h(\(le)o(gac)o(y\).)145 2889 y Fa(\017)49 +b Ff(NO)p 394 2889 V 36 w(V)-13 b(ARARGS)244 3009 y(Hack)25 +b(for)g(machines)f(without)g(a)h(V)-13 b(ARARGS)25 b(package.)145 +3222 y Fa(\017)49 b Ff(SYSV)244 3342 y(F)o(or)25 b(Unix)f(System)g(V) +-13 b(.)146 3584 y(Flags)25 b(de\002ned,)g(if)g(needed,)g(in)f +(\224magic.h\224)h(based)g(on)f(other)h(\003ags.)145 +3825 y Fa(\017)49 b Ff(BIG)p 421 3825 V 36 w(ENDIAN)244 +3946 y(Indicates)24 b(big)h(endian)f(byte)h(ordering)f(is)g(being)h +(used.)145 4158 y Fa(\017)49 b Ff(LITTLE)p 588 4158 V +35 w(ENDIAN)244 4279 y(Indicates)24 b(little)g(endian)h(byte)f +(ordering)g(is)h(being)f(used.)145 4492 y Fa(\017)49 +b Ff(NEED)p 516 4492 V 35 w(MONCNTL)244 4612 y(Hack)25 +b(for)g(machines)f(without)g(a)h(moncontrol)e(procedure.)145 +4825 y Fa(\017)49 b Ff(NEED)p 516 4825 V 35 w(VFPRINTF)244 +4945 y(Hack)25 b(for)g(machines)f(without)g(a)h(vfprintf)f(procedure.) +145 5158 y Fa(\017)49 b Ff(SIG)p 410 5158 V 36 w(RETURNS)p +899 5158 V 37 w(INT)244 5278 y(De\002ned)25 b(in)f(magic.h)f(for)i +(systems)e(that)h(e)o(xpect)g(a)h(signal)e(handler)h(to)g(return)h(an)f +(inte)o(ger)g(rather)h(than)f(a)244 5399 y(v)n(oid.)1850 +5649 y(\22612\226)p eop +%%Page: 13 13 +13 12 bop 0 -180 a Ff(Magic)24 b(Maintainer')-5 b(s)24 +b(Manual)g(#1:)30 b(Installation)24 b(and)g(De)n(v)o(elopment)628 +b(September)25 b(26,)g(2001)0 82 y Fe(7.2)119 b(Graphics)31 +b(Dri)o(v)o(er)f(Compile-time)g(Options)145 272 y Fa(\017)49 +b Ff(X11)244 392 y(Used)25 b(in)f(the)h(graphics)f(module)g(for)h(the)g +(X11)f(dri)n(v)o(er)-5 b(.)145 601 y Fa(\017)49 b Ff(OpenGL)244 +721 y(Used)25 b(in)f(the)h(graphics)f(module)g(for)h(the)g(OpenGL/GLX)e +(dri)n(v)o(er)-5 b(.)145 930 y Fa(\017)49 b Ff(XLIB)244 +1050 y(Used)19 b(for)g(all)g(graphics)g(modules)e(based)i(on)g(an)g(X)h +(serv)o(er)f(\(currently)-6 b(,)19 b(that)g(means)g(X11)f(and)h +(OpenGL\).)145 1259 y Fa(\017)49 b Ff(X10)244 1379 y(Used)25 +b(in)f(the)h(graphics)f(module)g(for)h(the)g(X10)f(dri)n(v)o(er)g(\(le) +o(gac)o(y\).)145 1588 y Fa(\017)49 b Ff(AED)244 1708 +y(Used)25 b(in)f(the)h(graphics)f(module)g(when)g(compiling)f(for)j +(AED)e(displays)g(\(le)o(gac)o(y\).)145 1916 y Fa(\017)49 +b Ff(GTCO)244 2037 y(Used)25 b(in)f(the)h(graphics)f(module)g(when)g +(using)g(a)h(GTCO)h(bitpad)d(with)i(an)f(AED)h(display)f(\(le)o(gac)o +(y\).)0 2339 y Fe(7.3)119 b(Compile-time)30 b(Options)g(f)m(or)g +(Module)h(Inclusion)145 2528 y Fa(\017)49 b Ff(NO)p 394 +2528 30 4 v 36 w(CALMA)244 2649 y(Flag)25 b(to)f(eliminate)g(the)h +(calma)f(module,)g(to)h(reduce)g(the)g(size)f(of)h(Magic.)145 +2857 y Fa(\017)49 b Ff(NO)p 394 2857 V 36 w(CIF)244 2978 +y(Flag)25 b(to)f(eliminate)g(the)h(cif)g(module,)e(to)i(reduce)g(the)g +(size)g(of)g(Magic.)145 3186 y Fa(\017)49 b Ff(NO)p 394 +3186 V 36 w(EXT)244 3306 y(Flag)25 b(to)g(eliminate)g(the)g(e)o(xt)g +(module,)f(to)h(reduce)h(the)f(size)h(of)f(Magic)g(\(le)o(gac)o(y;)f +(not)h(among)g(con\002gura-)244 3427 y(tion)f(choices\).)145 +3635 y Fa(\017)49 b Ff(NO)p 394 3635 V 36 w(PLO)l(T)244 +3756 y(Flag)25 b(to)f(eliminate)g(the)h(plot)f(module,)f(to)i(reduce)g +(the)g(size)g(of)f(Magic.)145 3964 y Fa(\017)49 b Ff(NO)p +394 3964 V 36 w(R)l(OUTE)244 4085 y(Flag)25 b(to)f(eliminate)g(the)h +(router)f(modules,)g(to)g(reduce)i(the)e(size)h(of)g(Magic.)145 +4293 y Fa(\017)49 b Ff(NO)p 394 4293 V 36 w(SIM)244 4413 +y(Flag)25 b(to)f(eliminate)g(the)h(sim)f(module,)f(to)i(reduce)g(the)g +(size)g(of)f(Magic.)145 4622 y Fa(\017)49 b Ff(NO)p 394 +4622 V 36 w(SCHEME)p 834 4622 V 36 w(INTERPRETER)244 +4742 y(Flag)25 b(to)f(eliminate)g(the)h(\223scheme\224)g(command-line)e +(interpreter)-5 b(.)145 4951 y Fa(\017)49 b Ff(USE)p +438 4951 V 36 w(READLINE)244 5071 y(Flag)25 b(to)f(include)h(the)f(GNU) +h(\223readline\224)g(package.)145 5280 y Fa(\017)49 b +Ff(OLD)p 455 5280 V 35 w(DO)l(T)p 691 5280 V 36 w(MA)l(GIC)244 +5400 y(Flag)25 b(indicating)e(use)i(of)g(the)g(original)e(\(backw)o +(ardly)i(compatible\))f(system)g(startup)g(\223)p Fd(.magic)p +Ff(\224)h(\002le.)1850 5649 y(\22613\226)p eop +%%Page: 14 14 +14 13 bop 0 -180 a Ff(September)25 b(26,)f(2001)630 b(Magic)24 +b(Maintainer')-5 b(s)24 b(Manual)g(#1:)30 b(Installation)23 +b(and)i(De)n(v)o(elopment)145 67 y Fa(\017)49 b Ff(LLNL)244 +187 y(Flag)30 b(to)f(incorporate)g(La)o(wrence)h(Li)n(v)o(ermore)e(e)o +(xtensions,)h(including)f(an)h(area)i(router)l(,)f(ne)n(w)f(channel)244 +307 y(router)l(,)c(and)f(stretch)h(graphs)f(\(e)o(xperimental;)g(not)g +(among)g(con\002guration)g(choices\).)0 670 y Fe(7.4)119 +b(Deb)n(ugging)31 b(Compiletime)f(Options)145 879 y Fa(\017)49 +b Ff(CELLDEB)o(UG)244 1000 y(Deb)n(ugging)24 b(\003ag)h(for)g(the)g +(database)g(module.)145 1256 y Fa(\017)49 b Ff(COUNTWIDTHCALLS)244 +1376 y(Deb)n(ugging)24 b(\003ag)h(for)g(the)g(plo)n(w)e(module.)145 +1632 y Fa(\017)49 b Ff(DEB)o(UGWIDTH)244 1752 y(Deb)n(ugging)24 +b(\003ag)h(for)g(the)g(plo)n(w)e(module.)145 2008 y Fa(\017)49 +b Ff(DRCR)l(ULESHIST)n(O)244 2129 y(Deb)n(ugging/tuning)22 +b(\003ag)j(for)g(the)g(drc)g(module.)145 2385 y Fa(\017)49 +b Ff(FREEDEB)o(UG)244 2505 y(Memory)24 b(allocation)g(deb)n(ugging)f +(\003ag.)145 2761 y Fa(\017)49 b Ff(MALLOCMEASURE)244 +2881 y(Memory)24 b(allocation)g(deb)n(ugging)f(\003ag.)145 +3137 y Fa(\017)49 b Ff(MALLOCTRA)l(CE)244 3258 y(Memory)24 +b(allocation)g(deb)n(ugging)f(\003ag.)145 3514 y Fa(\017)49 +b Ff(NOMA)l(CR)l(OS)244 3634 y(Memory)24 b(allocation)g(deb)n(ugging)f +(\003ag.)145 3890 y Fa(\017)49 b Ff(P)-9 b(AINTDEB)o(UG)244 +4010 y(Deb)n(ugging)24 b(\003ag)h(for)g(the)g(database)g(painting)e +(routines.)145 4266 y Fa(\017)49 b Ff(P)-9 b(ARANOID)244 +4387 y(Flag)32 b(to)f(enable)g(consistenc)o(y)f(checking.)51 +b(W)l(ith)30 b(a)i(system)e(the)i(comple)o(xity)d(of)j(Magic,)g(you)f +(should)244 4507 y(al)o(w)o(ays)24 b(lea)n(v)o(e)h(this)f(\003ag)h +(turned)g(on)f(\(set)h(automatically)e(by)i(the)f Fd(:con\002g)i +Ff(script\).)0 4914 y Fh(8)143 b(T)-13 b(echnology)33 +b(and)i(Other)g(Support)f(Files)0 5159 y Ff(Besides)e(the)h(source)f +(code)h(\002les,)h(there)f(are)g(a)g(number)f(of)g(other)h(\002les)f +(that)g(must)g(be)g(managed)g(by)g(Magic)0 5280 y(maintainers,)i +(including)e(color)h(maps,)i(technology)d(\002les,)j(and)e(other)g +(stuf)n(f.)56 b(Belo)n(w)33 b(is)f(a)i(listing)d(of)j(those)0 +5400 y(\002les)25 b(and)g(where)g(the)o(y)f(are)i(located.)1850 +5649 y(\22614\226)p eop +%%Page: 15 15 +15 14 bop 0 -180 a Ff(Magic)24 b(Maintainer')-5 b(s)24 +b(Manual)g(#1:)30 b(Installation)24 b(and)g(De)n(v)o(elopment)628 +b(September)25 b(26,)g(2001)0 82 y Fe(8.1)119 b(T)-11 +b(echnology)30 b(Files)0 270 y Ff(See)36 b(\223Magic)f(Maintainer')-5 +b(s)34 b(Manual)h(#2:)51 b(The)35 b(T)-7 b(echnology)35 +b(File\224)g(for)h(information)e(on)h(the)g(contents)f(of)0 +390 y(technology)29 b(\002les.)45 b(The)30 b(sources)g(for)g +(technology)f(\002les)h(are)g(contained)f(in)h(the)f(subdirectory)g +Fd(tech)p Ff(,)k(in)c(\002les)0 511 y(lik)o(e)38 b Fd(scmos.tech)i +Ff(and)e Fd(nmos.tech)p Ff(.)74 b(The)39 b(technology)e(\002les)i(that) +g(Magic)f(actually)g(uses)h(at)g(runtime)e(are)0 631 +y(k)o(ept)30 b(in)g(the)g(directory)h Fd($)p Fa(f)p Fd(CAD)p +1174 631 30 4 v 35 w(HOME)p Fa(g)p Fd(/lib/magic/sys)p +Ff(;)p Fd(mak)o(e)d(install)h Ff(in)i Fd(tech)g Ff(will)f(cop)o(y)g +(the)g(sources)0 752 y(to)g Fd($)p Fa(f)p Fd(CAD)p 430 +752 V 36 w(HOME)p Fa(g)p Fd(/lib/magic/sys)p Ff(.T)-7 +b(echnology)27 b(\002le)k(formats)f(ha)n(v)o(e)g(e)n(v)n(olv)o(ed)g +(rapidly)g(during)g(Magic')-5 b(s)0 872 y(life,)40 b(so)c(we)i(use)f(v) +o(ersion)e(numbers)i(to)f(allo)n(w)g(multiple)f(formats)i(of)g +(technology)f(\002les)h(to)f(e)o(xist)g(at)h(once.)0 +992 y(The)e(installed)f(v)o(ersions)g(of)i(technology)e(\002les)h(ha)n +(v)o(e)g(names)g(lik)o(e)g Fd(nmos.tech27)p Ff(,)k(where)d +Fd(27)f Ff(is)g(a)g(v)o(ersion)0 1113 y(number)-5 b(.)61 +b(The)35 b(current)h(v)o(ersion)e(is)h(de\002ned)h(in)e(the)i(Mak)o +(e\002le)f(for)h Fd(tech)p Ff(,)j(and)c(should)f(be)h(incremented)g(if) +0 1233 y(you)29 b(e)n(v)o(er)g(change)h(the)f(format)g(of)h(technology) +e(\002les;)k(if)d(you)g(install)f(a)i(ne)n(w)f(format)g(without)f +(changing)h(the)0 1353 y(v)o(ersion)24 b(number)l(,)g(pre-e)o(xisting)f +(v)o(ersions)g(of)i(Magic)f(w)o(on')n(t)h(be)g(able)f(to)h(read)g(the)f +(\002les.)31 b(After)25 b(incrementing)0 1474 y(the)39 +b(v)o(ersion)f(number)l(,)k(you')o(ll)c(also)g(ha)n(v)o(e)h(to)f +(re-mak)o(e)i(the)f Fd(tech)h Ff(module)e(since)g(the)h(v)o(ersion)f +(number)h(is)0 1594 y(referenced)26 b(by)f(the)f(code)h(that)g(reads)g +(the)g(\002les.)0 1887 y Fe(8.2)119 b(Display)30 b(Styles)0 +2074 y Ff(The)g(display)f(style)g(\002le)i(sources)f(are)h(contained)e +(in)h(the)g(source)g(directory)g Fd(graphics)p Ff(.)47 +b(See)31 b(\223Magic)f(Main-)0 2195 y(tainer')-5 b(s)28 +b(Manual)f(#3:)37 b(The)29 b(Display)e(Style)h(and)g(Glyph)g(Files\224) +g(and)g(the)g(manual)g(page)g Fg(dstyle)g Ff(\(5\))h(for)f(a)h(de-)0 +2315 y(scription)18 b(of)h(their)f(contents.)28 b Fd(Mak)o(e)19 +b(install)f Ff(in)h Fd(graphics)g Ff(will)f(cop)o(y)h(the)f(\002les)h +(to)g Fd($)p Fa(f)p Fd(CAD)p 3208 2315 V 35 w(HOME)p +Fa(g)p Fd(/lib/magic/sys)p Ff(,)0 2435 y(which)24 b(is)h(where)g(Magic) +f(looksfor)g(them)h(when)f(it)h(e)o(x)o(ecutes.)0 2728 +y Fe(8.3)119 b(Glyph)31 b(Files)0 2915 y Ff(Glyph)d(\002les)g(are)i +(described)e(in)g(Maintainer')-5 b(s)28 b(Manual)g(#3)g(and)g(the)h +(manual)f(page)h Fg(glyphs)e Ff(\(5\);)k(the)o(y)d(de\002ne)0 +3036 y(patterns)e(that)h(appear)h(in)e(the)h(cursor)-5 +b(.)37 b(The)27 b(sources)f(for)i(glyph)e(\002les)h(appear)g(in)g(tw)o +(o)f(places:)35 b(some)27 b(of)g(them)0 3156 y(are)20 +b(in)e Fd(graphics)p Ff(,)i(in)f(\002les)g(lik)o(e)f +Fd(color)-10 b(.glyphs)p Ff(,)20 b(and)f(some)f(others)g(are)i +(de\002ned)f(in)f Fd(windo)o(ws/windo)o(w)p Fg(XX)p Fd(.glyphs)p +Ff(.)0 3276 y(When)h(you)f Fd(mak)o(e)i(install)e Ff(in)g(those)g +(directories,)i(the)f(glyphs)e(are)j(copied)e(to)h Fd($)p +Fa(f)p Fd(CAD)p 3015 3276 V 35 w(HOME)p Fa(g)p Fd(/lib/magic/sys)p +Ff(,which)0 3397 y(is)24 b(where)i(Magic)e(looks)g(for)h(them)f(when)h +(it)f(e)o(x)o(ecutes.)0 3689 y Fe(8.4)119 b(Color)30 +b(Maps)0 3877 y Ff(The)38 b(color)g(map)g(sources)g(are)h(also)f +(contained)g(in)g(the)g(source)g(directory)g Fd(graphics)p +Ff(.)71 b(Color)39 b(maps)e(ha)n(v)o(e)0 3997 y(names)26 +b(lik)o(e)g Fd(mos.7bit.std.cmap)p Ff(,)h(where)g Fd(mos)f +Ff(is)g(the)g(name)g(of)h(the)f(technology)f(style)h(to)g(which)g(the)g +(color)0 4117 y(map)35 b(applies,)j Fd(7bit)e Ff(is)f(the)g(display)g +(style,)j(and)d Fd(std)h Ff(is)f(a)h(type)g(of)g(monitor)-5 +b(.)61 b(If)36 b(monitors)e(ha)n(v)o(e)h(radically)0 +4238 y(dif)n(ferent)j(phosphors,)i(the)o(y)d(may)h(require)g(dif)n +(ferent)g(color)g(maps)f(to)h(achie)n(v)o(e)f(the)h(same)g(af)n(fects.) +71 b(Right)0 4358 y(no)n(w)31 b(we)g(only)g(support)f(the)i +Fd(std)g Ff(kind)e(of)i(monitor)-5 b(.)49 b(When)31 b(Magic)g(e)o(x)o +(ecutes,)h(it)f(looks)g(for)g(color)h(maps)e(in)0 4479 +y Fd($)p Fa(f)p Fd(CAD)p 322 4479 V 35 w(HOME)p Fa(g)p +Fd(/lib/magic/sys)p Ff(;)p Fd(mak)o(e)e(install)i Ff(in)g +Fd(graphics)h Ff(will)f(cop)o(y)g(them)g(there.)48 b(Although)29 +b(color)0 4599 y(map)19 b(\002les)g(are)h(te)o(xtual,)f(editing)e(by)i +(hand)g(is)g(undesirable;)h(use)f(Magic')-5 b(s)18 b(color)h(map)f +(editing)g(windo)n(w)g(instead.)0 4936 y Fh(9)143 b(New)35 +b(Display)f(Dri)o(v)o(ers)0 5159 y Ff(The)24 b(most)e(common)g(kind)h +(of)h(change)f(that)h(will)e(be)i(made)f(to)g(Magic)h(is)f(probably)g +(to)g(adapt)g(it)g(for)h(ne)n(w)f(kinds)0 5280 y(of)37 +b(color)g(displays.)67 b(Each)37 b(display)f(dri)n(v)o(er)g(contains)g +(a)i(standard)f(collection)f(of)h(procedures)g(to)g(perform)0 +5400 y(basic)24 b(functions)f(such)h(as)g(placing)g(te)o(xt,)f(dra)o +(wing)g(\002lled)h(rectangles,)g(or)h(changing)e(the)h(shape)g(of)h +(the)f(cursor)-5 b(.)1850 5649 y(\22615\226)p eop +%%Page: 16 16 +16 15 bop 0 -180 a Ff(September)25 b(26,)f(2001)630 b(Magic)24 +b(Maintainer')-5 b(s)24 b(Manual)g(#1:)30 b(Installation)23 +b(and)i(De)n(v)o(elopment)0 69 y(A)h(table)f(\(de\002ned)h(in)g +Fd(graphics/grMain.c)p Ff(\))g(holds)f(the)g(addresses)h(of)f(the)h +(routines)f(for)h(the)f(current)h(display)0 189 y(dri)n(v)o(er)-5 +b(.)28 b(At)20 b(initialization)e(time)h(this)g(table)h(is)g(\002lled)g +(in)g(with)f(the)h(addresses)g(of)g(the)h(routines)e(for)h(the)g +(particular)0 309 y(display)k(being)g(used.)30 b(All)25 +b(graphics)f(calls)h(pass)f(through)g(the)h(table.)146 +430 y(If)f(you)f(ha)n(v)o(e)g(a)g(display)f(other)i(than)e(the)i(ones)f +(currently)g(de\002ned)g(\(X11,)g(OpenGL/GLX,)g(SunV)-6 +b(ie)n(w)g(,)22 b(and)0 550 y(the)f(le)o(gac)o(y)f(X10)h(and)g(AED)g +(dri)n(v)o(ers\),)f(and)i(you)e(w)o(ant)h(to)g(b)n(uild)f(a)i(ne)n(w)e +(display)g(dri)n(v)o(er)l(,)h(we)h(recommend)e(start-)0 +671 y(ing)k(with)g(the)g(routines)g(for)h(the)f(X11)g(\(all)h(the)f +(\002les)h(in)f Fd(graphics)h Ff(named)f Fd(grX11su)p +Fg(n)p Fd(.c)p Ff(\),)h(or)f(the)h(Sun)f(\(named)0 791 +y Fd(grSunW)p Fg(n)p Fd(.c)p Ff(\).)32 b(Cop)o(y)25 b(the)f(\002les)h +(into)f(a)h(ne)n(w)g(set)f(for)h(your)g(display)-6 b(,)23 +b(change)i(the)f(names)h(of)g(the)f(routines,)g(and)0 +911 y(modify)30 b(them)f(to)i(perform)f(the)h(equi)n(v)n(alent)d +(functions)i(on)g(your)h(display)-6 b(.)46 b(Write)31 +b(an)f(initialization)f(routine)0 1032 y(lik)o(e)i Fd(x11suSetDisplay)p +Ff(,)h(and)f(add)g(information)f(to)g(the)h(display)f(type)h(tables)g +(in)f Fd(graphics/grMain.c)p Ff(.)50 b(At)0 1152 y(this)31 +b(point)g(you)h(should)f(be)i(all)f(set.)52 b(There)33 +b(shouldn')n(t)e(be)h(an)o(y)g(need)g(to)g(modify)f(an)o(ything)g +(outside)g(of)h(the)0 1272 y(graphics)24 b(module.)146 +1393 y(The)i(signi\002cant)f(dif)n(ference)h(between)g(the)g(X11)f(dri) +n(v)o(er)g(and)h(the)g(Sun)g(dri)n(v)o(er)f(depends)g(on)g(the)h +(nature)g(of)0 1513 y(the)d(serv)o(er:)29 b(The)23 b(X11)g(serv)o(er)g +(polls)e(for)j(ne)n(w)e(e)n(v)o(ents,)g(and)h(the)g(typical)f(\223main) +g(loop\224)h(of)g(an)g(X11)f(application)0 1634 y(is)28 +b(a)h(call)g(to)f Fd(XtMainLoop\(\))i Ff(which)f(ne)n(v)o(er)f(e)o +(xits.)41 b(This)28 b(presents)g(a)h(problem)f(for)h(Magic,)h(which)e +(is)g(inter)n(-)0 1754 y(rupt)i(dri)n(v)o(en,)h(a)h(choice)f(made)f +(due)h(to)g(the)g(lar)n(ge)g(amount)f(of)h(internal)f(processing)g +(\(e.g.,)j(interacti)n(v)o(e)c(DRC)0 1874 y(checking\))34 +b(as)h(compared)f(to)g(the)g(small)g(amount)f(of)i(user)f(input)g +(\(e.g.,)i(k)o(e)o(ystrok)o(es)e(and)g(mouse)g(b)n(uttons\).)0 +1995 y(Magic)24 b(has)h(its)f(o)n(wn)g(blocking)f(loop,)h(which)g(is)h +(a)g(call)f(to)h Fd(select)p Ff(\),)g(a)g(routine)f(which)g +(continuously)f(polls)g(I/O)0 2115 y(de)n(vices)f(for)h(interrupts.)28 +b(Because)c(X11)e(\(at)h(least)f(up)g(to)g(and)g(including)f(the)h(R6)h +(v)o(ersion\))f(is)g(not)g(thread-safe,)0 2236 y(these)29 +b(tw)o(o)f(loops)g(cannot)h(be)g(threads.)43 b(The)29 +b(only)f(remaining)g(possibility)e(is)j(to)f(mak)o(e)h(the)g(X11)g +(main)f(loop)0 2356 y(run)k(as)h(a)g(separate)f(process)h(\(in)f(the)g +(case)h(of)g(X11,)g(called)g(\223X11Helper\224\),)h(capture)f(rele)n(v) +n(ant)f(X)g(protocol)0 2476 y(messages)h(for)h(the)g(Magic)f(windo)n(w) +-6 b(,)34 b(and)f(transmit)g(the)g(information)g(to)g(the)g(Magic)h +(process)f(through)g(an)0 2597 y(I/O)f(pipe)h(\(the)f(use)h(of)f(which) +g(triggers)g(the)h(I/O)f(interrupt)g(and)h(breaks)f(the)h +Fd(select\(\))g Ff(loop\).)53 b(This)32 b(method)0 2717 +y(has)24 b(certain)h(dra)o(wbacks,)e(the)h(main)g(one)g(being)g(that)g +(if)g(Magic)g(crashes)g(for)h(an)o(y)e(reason,)i(the)f(helper)g +(process)0 2837 y(remains)g(hanging)g(until)g(killed)g(by)g(hand)h(or)g +(by)f(a)h(system)f(reboot.)146 2958 y(The)k(Sun)h(interf)o(ace)f(mak)o +(es)g(graphics)g(calls)g(as)g(requested,)h(which)f(mak)o(es)f +(implementation)f(for)i(Magic)0 3078 y(much)i(simpler)g(than)h(X11,)h +(b)n(ut)f(consequently)f(pre)n(v)o(ents)f(remote)i(display)f(operation) +g(and)h(ef)n(\002cient)g(multi-)0 3199 y(tasking,)24 +b(the)g(major)h(reasons)f(for)h(X11')-5 b(s)24 b(success.)146 +3319 y(Note)32 b(that)g(an)o(y)f(graphics)h(interf)o(aces)g(based)g(on) +g Fg(thr)l(ead-safe)f Ff(graphics)h(systems)e(\(e.g.,)k(W)l(indo)n(ws)d +(NT)-7 b(,)0 3439 y(and)25 b(hopefully)f(X11R7,)h(if)g(it)f(e)n(v)o(er) +h(happens\))f(can)i(reduce)f(the)g(graphics)g(interf)o(ace)g(comple)o +(xity)e(by)i(running)0 3560 y(the)g(X11)f(e)n(v)o(ent)g(handler)h(as)f +(a)i(detached)f(thread.)0 3895 y Fh(10)143 b(Deb)m(ugging)34 +b(and)h(W)m(izard)g(Commands)0 4119 y Ff(Magic)h(w)o(orks)g(\002ne)g +(under)g(the)g(latest)g(v)o(ersions)f(of)h(dbx)g(and)g(GNU)g(gdb)l(.)64 +b(The)37 b(Mak)o(e\002les)f(are)h(set)f(up)f(to)0 4239 +y(compile)24 b(all)g(\002les)h(with)f(the)h Fd(-g)g Ff(switch,)f(which) +g(creates)i(deb)n(ugging)d(information.)146 4359 y(In)k(the)f(past,)g +(memory)g(and)g(speed)g(limitations)e(made)i(it)g(useful)g(to)g +(include)f(a)i(\003ag,)g(found)f(in)g(script)g Fd(:in-)0 +4480 y(stmodule)p Ff(,)d(to)f(strip)g(the)g(deb)n(ugging)f(symbols)f +(from)i(the)g(object)g(\002les)g(when)g(linking)f(the)h(Magic)g(e)o(x)o +(ecutable.)0 4600 y(Modern)h(systems)e(are)j(f)o(ast)f(and)g(ha)n(v)o +(e)g(copious)f(amounts)g(of)h(both)f(system)g(memory)g(and)h(disk)g +(space,)g(so)g(this)0 4721 y(option)h(is)g(set)g(to)h(\223NO\224)g(in)g +(the)f(script.)146 4841 y(There)h(are)f(a)g(number)g(of)g(commands)e +(that)i(we)g(implemented)e(in)i(Magic)f(to)h(assist)f(in)g(deb)n +(ugging.)29 b(These)0 4961 y(commands)f(are)j(called)e +Fg(wizar)l(d)g(commands)p Ff(,)h(and)g(aren')n(t)g(visible)e(to)h +(normal)g(Magic)h(users.)44 b(The)o(y)29 b(all)g(start)0 +5082 y(with)j(\223)p Fd(*)p Ff(\224.)54 b(T)-8 b(o)33 +b(get)f(terse)h(online)f(help)g(for)h(the)f(wizard)h(commands,)g(type)g +Fd(:help)g(wizard)g Ff(to)f(Magic.)54 b(The)0 5202 y(wizard)25 +b(commands)f(aren')n(t)h(documented)f(v)o(ery)g(well.)31 +b(Some)25 b(of)f(the)h(more)g(useful)f(ones)h(are:)145 +5400 y Fa(\017)49 b Fd(*watch)25 b Fg(plane)1850 5649 +y Ff(\22616\226)p eop +%%Page: 17 17 +17 16 bop 0 -180 a Ff(Magic)24 b(Maintainer')-5 b(s)24 +b(Manual)g(#1:)30 b(Installation)24 b(and)g(De)n(v)o(elopment)628 +b(September)25 b(26,)g(2001)244 68 y(This)30 b(causes)h(Magic)g(to)f +(display)g(on)h(the)f(screen)i(the)f(corner)n(-stitched)f(tile)h +(structure)f(for)h(one)g(of)g(the)244 188 y(planes)25 +b(of)g(the)f(edit)h(cell.)31 b(F)o(or)25 b(e)o(xample,)f +Fd(*watch)i(subcell)f Ff(will)f(display)g(the)h(structure)g(of)g(the)g +(subcell)244 309 y(tile)19 b(plane,)h(including)e(the)h(address)h(of)f +(the)g(record)h(for)g(each)g(tile)f(and)g(the)g(v)n(alues)g(of)h(its)e +(corner)i(stitches.)244 429 y(W)l(ithout)26 b(this)g(command)h(it)g(w)o +(ould)f(ha)n(v)o(e)h(been)h(virtually)e(impossible)f(to)i(deb)n(ug)g +(the)g(database)h(mod-)244 549 y(ule.)145 753 y Fa(\017)49 +b Fd(*pr)n(o\002le)26 b(on)p Ff(\227)p Fd(off)244 873 +y Ff(If)31 b(you')-5 b(re)30 b(using)g(the)g(Unix)f(pro\002ling)h +(tools)f(to)h(\002gure)h(out)f(where)h(the)f(c)o(ycles)g(are)h(going,)g +(this)e(com-)244 994 y(mand)20 b(can)g(be)h(used)f(to)g(turn)g +(pro\002ling)f(of)n(f)h(for)h(e)n(v)o(erything)d(e)o(xcept)i(the)h +(particular)f(operation)f(you)h(w)o(ant)244 1114 y(to)31 +b(measure.)53 b(This)31 b(command)g(doesn')n(t)g(w)o(ork)h(on)g(man)o +(y)f(systems,)h(because)g(the)g(operating)f(system)244 +1234 y(doesn')n(t)24 b(support)g(selecti)n(v)o(e)g(enabling)g(and)g +(disabling)g(of)g(pro\002ling.)145 1438 y Fa(\017)49 +b Fd(*runstats)244 1558 y Ff(This)22 b(command)g(prints)g(out)g(the)h +(CPU)g(time)f(usage)h(since)g(the)f(last)h(in)l(v)n(ocation)e(of)i +(this)f(command,)g(and)244 1679 y(also)i(the)h(total)f(since)h +(starting)e(Magic.)145 1882 y Fa(\017)49 b Fd(*see\003ags)25 +b Fg(\003a)o(g)244 2002 y Ff(If)j(you')-5 b(re)27 b(w)o(orking)g(on)g +(the)h(router)l(,)g(this)e(command)h(allo)n(ws)f(you)h(to)g(see)h(the)f +(v)n(arious)g(channel)g(router)244 2123 y(\003ags)19 +b(by)g(displaying)e(them)i(as)g(feedback)h(areas.)29 +b(The)19 b(cursor)g(should)f(\002rst)i(be)f(placed)g(o)o(v)o(er)f(the)h +(channel)244 2243 y(whose)24 b(\003ags)h(you)g(w)o(ant)f(to)h(see.)0 +2583 y Fh(A)143 b(Serial-Line)33 b(Graphics)h(Displays)0 +2806 y Ff(This)h(section)f(remains)h(for)h(information)e(re)o(garding)g +(the)h(serial-line)g(graphics)g(dri)n(v)o(er)-5 b(.)61 +b(Although)33 b(totally)0 2927 y(outdated,)g(these)e(are)i(the)f +(simplest)e(graphics)h(dri)n(v)o(er)g(routines,)i(and)f(at)g(least)f +(for)i(no)n(w)e(are)h(w)o(orth)g(k)o(eeping)0 3047 y(around)25 +b(for)g(reference,)h(particularly)e(when)h(attempting)e(to)h(implement) +f(a)j(ne)n(w)e(graphics)g(dri)n(v)o(er)-5 b(.)146 3167 +y(Serial-line)39 b(displays)e(require)i(some)f(additional)f(setup.)71 +b(If)39 b(the)g(display)e(is)h(an)h(AED512)f(or)g(similar)0 +3288 y(display)-6 b(,)31 b(it)g(will)g(be)g(attached)g(to)g(the)g +(mainframe)g(via)h(an)f(RS232)h(port.)50 b(Magic)31 b(needs)g(to)g(be)g +(able)h(to)f(read)0 3408 y(from)d(this)g(port,)h(and)f(there)h(are)g +(tw)o(o)f(w)o(ays)g(to)g(do)g(this.)41 b(The)28 b(\002rst)h(is)f +(simply)f(to)h(ha)n(v)o(e)g(no)g(login)g(process)g(for)0 +3528 y(that)h(port)f(and)h(ha)n(v)o(e)g(your)f(system)g(administrator)g +(change)h(the)g(protection)f(to)g(allo)n(w)g(all)h(processes)g(to)g +(read)0 3649 y(from)34 b(the)h(port)f(and)g(write)h(to)f(it.)59 +b(The)35 b(second)f(w)o(ay)h(is)f(to)g(ha)n(v)o(e)g(users)h(log)f(in)g +(on)g(the)g(display)g(and)g(run)h(a)0 3769 y(process)c(that)f(changes)h +(the)g(protection)f(of)h(the)g(display)-6 b(.)47 b(There)32 +b(is)e(a)h(program)g(called)g Fd(sleeper)h Ff(distrib)n(uted)0 +3890 y(with)h(Magic)g(v)o(ersions)g(6.5.1)g(and)g(earlier;)39 +b(if)33 b(it')-5 b(s)33 b(run)h(from)f(an)h(AED)f(port)h(it)f(will)g +(set)g(e)n(v)o(erything)f(up)h(so)0 4010 y(Magic)25 b(can)i(use)e(the)h +(port.)33 b Fd(sleeper)27 b Ff(is)e(clumsy)g(to)g(use,)h(so)g(we)g +(recommend)f(that)g(you)h(use)f(the)h(\002rst)g(solution)0 +4130 y(\(no)f(login)e(process\).)146 4251 y(When)35 b(you')-5 +b(re)35 b(running)e(on)i(mainframes,)h(Magic)e(will)g(need)h(to)f(kno)n +(w)f(which)h(color)h(display)e(port)h(to)0 4371 y(use)e(from)g(each)h +(terminal)e(port.)53 b(Users)32 b(can)h(type)f(this)f(information)g(as) +h(command-line)f(switches)g(b)n(ut)h(it')-5 b(s)0 4492 +y(clumsy)f(.)28 b(T)-8 b(o)23 b(simplify)e(things,)h(Magic)h(checks)g +(the)f(\002le)h Fd(\230cad/lib/displays)g Ff(when)f(it)h(starts)f(up.) +30 b(The)22 b(displays)0 4612 y(\002le)32 b(tells)f(which)h(color)f +(display)g(port)h(to)f(use)h(for)g(which)g(te)o(xt)e(terminal)h(port)h +(and)g(also)f(tells)g(what)h(kind)f(of)0 4732 y(display)21 +b(is)h(attached.)30 b(Once)22 b(this)f(\002le)i(is)f(set)g(up,)g(users) +g(can)g(run)h(Magic)e(without)g(w)o(orrying)h(about)f(the)h(system)0 +4853 y(con\002guration.)30 b(See)c(the)f(manual)f(page)h(for)g +Fg(displays)e Ff(\(5\).)146 4973 y(One)g(last)e(note:)29 +b(if)23 b(you')-5 b(re)22 b(running)f(on)h(an)h(AED)f(display)-6 +b(,)21 b(you')o(ll)g(need)i(to)f(set)g(communication)e(switches)0 +5093 y(3-4-5)25 b(to)f(up-do)n(wn-up.)1850 5649 y(\22617\226)p +eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/maint2.ps b/doc/psfiles/maint2.ps new file mode 100644 index 00000000..3fb127f8 --- /dev/null +++ b/doc/psfiles/maint2.ps @@ -0,0 +1,7351 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.92b Copyright 2002 Radical Eye Software +%%Title: maint2.dvi +%%Pages: 53 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman CMSY10 Symbol +%%+ Courier-Bold Helvetica font Helvetica-Bold Helvetica-Oblique Courier +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips maint2 -o +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2006.02.13:1406 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% File 8r.enc as of 2002-03-12 for PSNFSS 9 +% +% This is the encoding vector for Type1 and TrueType fonts to be used +% with TeX. This file is part of the PSNFSS bundle, version 9 +% +% Authors: S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry, W. Schmidt +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida + Euro. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +% (6) /Euro is assigned to 128, as in Windows ANSI +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /Euro /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: bbad153f.enc +% Thomas Esser, Dec 2002. public domain +% +% Encoding for: +% cmsy10 cmsy5 cmsy6 cmsy7 cmsy8 cmsy9 +% +/TeXbbad153fEncoding [ +/minus /periodcentered /multiply /asteriskmath /divide /diamondmath +/plusminus /minusplus /circleplus /circleminus /circlemultiply +/circledivide /circledot /circlecopyrt /openbullet /bullet +/equivasymptotic /equivalence /reflexsubset /reflexsuperset /lessequal +/greaterequal /precedesequal /followsequal /similar /approxequal +/propersubset /propersuperset /lessmuch /greatermuch /precedes /follows +/arrowleft /arrowright /arrowup /arrowdown /arrowboth /arrownortheast +/arrowsoutheast /similarequal /arrowdblleft /arrowdblright /arrowdblup +/arrowdbldown /arrowdblboth /arrownorthwest /arrowsouthwest /proportional +/prime /infinity /element /owner /triangle /triangleinv /negationslash +/mapsto /universal /existential /logicalnot /emptyset /Rfractur /Ifractur +/latticetop /perpendicular /aleph /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /union /intersection +/unionmulti /logicaland /logicalor /turnstileleft /turnstileright +/floorleft /floorright /ceilingleft /ceilingright /braceleft /braceright +/angbracketleft /angbracketright /bar /bardbl /arrowbothv /arrowdblbothv +/backslash /wreathproduct /radical /coproduct /nabla /integral +/unionsq /intersectionsq /subsetsqequal /supersetsqequal /section +/dagger /daggerdbl /paragraph /club /diamond /heart /spade /arrowleft +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/minus /periodcentered /multiply /asteriskmath /divide /diamondmath +/plusminus /minusplus /circleplus /circleminus /.notdef /.notdef +/circlemultiply /circledivide /circledot /circlecopyrt /openbullet +/bullet /equivasymptotic /equivalence /reflexsubset /reflexsuperset +/lessequal /greaterequal /precedesequal /followsequal /similar +/approxequal /propersubset /propersuperset /lessmuch /greatermuch +/precedes /follows /arrowleft /spade /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +] def + +%%EndProcSet +%%BeginProcSet: texnansi.enc +% @psencodingfile{ +% author = "Y&Y, Inc.", +% version = "1.1", +% date = "1 December 1996", +% filename = "texnansi.enc", +% email = "help@YandY.com", +% address = "45 Walden Street // Concord, MA 01742, USA", +% codetable = "ISO/ASCII", +% checksum = "xx", +% docstring = "Encoding for fonts in Adobe Type 1 format for use with TeX." +% } +% +% The idea is to have all 228 characters normally included in Type 1 text +% fonts (plus a few more) available for typesetting. This is effectively +% the character set in Adobe Standard Encoding, ISO Latin 1, plus a few more. +% +% Character code assignments were made as follows: +% +% (1) The character layout largely matches `ASCII' in the 32 -- 126 range, +% except for `circumflex' in 94 and `tilde' in 126, to match `TeX text' +% (`asciicircumflex' and `asciitilde' appear in 158 and 142 instead). +% +% (2) The character layout matches `Windows ANSI' in almost all places, +% except for `quoteright' in 39 and `quoteleft' in 96 to match ASCII +% (`quotesingle' and `grave' appear in 129 and 18 instead). +% +% (3) The character layout matches `TeX typewriter' used by CM text fonts +% in most places (except for discordant positions such as hungarumlaut +% (instead of braceright), dotaccent (instead of underscore) etc. +% +% (4) Remaining characters are assigned arbitrarily to the `control character' +% range (0 -- 31), avoiding 0, 9, 10 and 13 in case we meet dumb software +% - similarly one should really avoid 127 and 128 if possible. +% In addition, the 8 open slots in Windows ANSI between 128 and 159 are used. +% +% (5) Y&Y Lucida Bright includes some extra ligatures and such; ff, ffi, ffl, +% and `dotlessj,' these are included 11 -- 15, and 17. +% +% (6) Hyphen appears both at 45 and 173 for compatibility with both ASCII +% and Windows ANSI. +% +% (7) It doesn't really matter where ligatures appear (both real, such as ffi, +% and pseudo such as ---) since these should not be accessed directly, only +% via ligature information in the TFM file. +% +% SAMPLE USAGE (in `psfonts.map' file for DVIPS): +% +% lbr LucidaBright "TeXnANSIEncoding ReEncodeFont" } imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrow { +% -12 -40 24 80 bbox +begingate +1 0.80 0 -40 0 20 2 polygon +1.00 0 0 40 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 544 352 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.753 0.333 0.502 scb +240 1.00 192 224 192 192 512 192 672 320 672 352 384 352 6 polygon +sce +0.490 0.651 0.980 scb +240 1.00 192 448 192 416 512 416 672 544 672 576 384 576 6 polygon +sce +0 1.00 192 416 192 448 512 448 512 416 4 polygon +1 1.00 192 448 384 576 2 polygon +1 1.00 512 448 672 576 2 polygon +1 1.00 384 576 672 576 2 polygon +1 1.00 512 416 672 544 2 polygon +1 1.00 672 576 672 544 2 polygon +1 1.00 192 448 672 576 2 polygon +1 1.00 384 576 512 448 2 polygon +0 1.00 192 192 192 224 512 224 512 192 4 polygon +1 1.00 192 224 384 352 2 polygon +1 1.00 512 224 672 352 2 polygon +1 1.00 384 352 672 352 2 polygon +1 1.00 512 192 672 320 2 polygon +1 1.00 672 352 672 320 2 polygon +1 1.00 192 224 672 352 2 polygon +1 1.00 384 352 512 224 2 polygon +1 1.00 672 528 672 368 2 polygon +1 1.00 512 400 512 240 2 polygon +1 1.00 192 400 192 240 2 polygon +1 1.00 384 368 384 416 2 polygon +(plane) {/Helvetica 1.000 cf} (metal1 ) {/Helvetica-Bold 1.000 cf} 4 20 0 704 560 label +(plane) {/Helvetica 1.000 cf} (active ) {/Helvetica-Bold 1.000 cf} 4 20 0 704 336 label +1.00 75 640 240 arrow +1.00 75 656 480 arrow +(: pcontact) {/Helvetica 1.000 cf} (drawn) {/Helvetica-Oblique 1.000 cf} 4 20 0 704 224 label +(: pcontact/m1) {/Helvetica 1.000 cf} (automatically generated) {/Helvetica-Oblique 1.000 cf} 4 20 0 720 464 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 1115 a(Figure)j(1:)38 b(A)28 b(dif)n(ferent)g(tile)g +(type)f(is)h(used)g(to)g(represent)h(a)f(contact)g(on)g(each)h(plane)f +(that)g(it)g(connects.)41 b(Here,)0 1236 y(a)32 b(contact)f(between)g +(poly)g(on)g(the)g Fd(acti)o(v)o(e)h Fg(plane)f(and)g(metal1)g(on)g +(the)g Fd(metal1)g Fg(plane)g(is)g(stored)g(as)h(tw)o(o)f(tile)0 +1356 y(types.)38 b(One,)27 b Fd(pcontact)p Fg(,)j(is)c(speci\002ed)i +(in)f(the)g(technology)f(\002le)i(as)f(residing)g(on)g(the)g +Fd(acti)o(v)o(e)g Fg(plane;)h(the)f(other)0 1477 y(is)d +(automatically-generated)g(for)h(the)g Fd(metal1)f Fg(plane.)0 +1872 y Fi(8)143 b(Specifying)34 b(T)-11 b(ype-lists)0 +2097 y Fg(In)31 b(se)n(v)o(eral)f(places)h(in)g(the)g(technology)f +(\002le)h(you')o(ll)f(need)h(to)g(specify)g(groups)f(of)h(tile)f +(types.)49 b(F)o(or)31 b(e)o(xample,)0 2217 y(in)25 b(the)h +Fd(connect)h Fg(section)e(you')o(ll)g(specify)h(groups)f(of)h(tiles)f +(that)g(are)h(mutually)e(connected.)34 b(These)26 b(are)g(called)0 +2337 y Fh(type-lists)c Fg(and)h(there)g(are)h(se)n(v)o(eral)e(w)o(ays)h +(to)f(specify)h(them.)30 b(The)23 b(simplest)e(form)i(for)g(a)g +(type-list)f(is)g(a)i(comma-)0 2458 y(separated)h(list)f(of)h(tile)f +(types,)g(for)h(e)o(xample)900 2690 y(poly)-6 b(,ndif)n(f,pcontact,ndc) +146 2922 y(The)25 b(null)f(list)g(\(no)h(tiles)f(at)g(all\))h(is)f +(indicated)h(by)f(zero,)h(i.e.,)900 3155 y(0)146 3387 +y(There)k(must)e(not)g(be)h(an)o(y)g(spaces)g(in)f(the)h(type-list.)39 +b(T)-8 b(ype-lists)27 b(may)g(also)h(use)g(tildes)f(\(\223\230\224\))i +(to)e(select)h(all)0 3507 y(tiles)c(b)n(ut)g(a)h(speci\002ed)g(set,)g +(and)g(parentheses)f(for)h(grouping.)30 b(F)o(or)25 b(e)o(xample,)900 +3740 y(\230\(pcontact,ndc\))146 3972 y(selects)d(all)h(tile)e(types)h +(b)n(ut)g(pcontact)g(and)h(ndc.)30 b(When)22 b(a)h(contact)f(name)g +(appears)h(in)f(a)h(type-list,)e(it)h(selects)0 4092 +y Fh(all)k Fg(images)g(of)h(the)g(contact)f(unless)g(a)h(\223/\224)g +(is)f(used)h(to)f(indicate)g(a)i(particular)e(one.)37 +b(The)26 b(e)o(xample)g(abo)o(v)o(e)g(will)0 4213 y(not)36 +b(select)g(an)o(y)f(of)i(the)e(images)h(of)g(pcontact)g(or)g(ndc.)65 +b(Slashes)36 b(can)h(also)e(be)i(used)e(in)h(conjunction)f(with)0 +4333 y(parentheses)25 b(and)f(tildes.)30 b(F)o(or)25 +b(e)o(xample,)900 4566 y(\230\(pcontact,ndc\)/acti)n(v)o(e,metal1)146 +4798 y(selects)34 b(all)g(of)g(the)f(tile)h(types)f(on)h(the)f(acti)n +(v)o(e)g(plane)h(e)o(xcept)f(for)i(pcontact)e(and)h(ndc,)i(and)e(also)f +(selects)0 4918 y(metal1.)d(T)m(ildes)22 b(ha)n(v)o(e)i(higher)f +(operator)h(precedence)h(than)f(slashes,)f(and)h(commas)f(ha)n(v)o(e)g +(lo)n(west)g(precedence)0 5038 y(of)i(all.)146 5159 y(A)h(special)g +(notation)e(using)h(the)g(asterisk)g(\(\223*\224\))i(is)e(a)h(con)l(v)o +(enient)e(w)o(ay)i(to)g(abbre)n(viate)f(the)g(common)g(situ-)0 +5280 y(ation)e(where)h(a)g(rule)g(requires)g(the)f(inclusion)f(of)i(a)g +(tile)f(type)h(and)f(also)h(all)f(contacts)h(that)f(de\002ne)h(that)f +(tile)g(type)0 5400 y(as)i(one)g(of)g(their)f(residue)h(layers,)f(a)i +(common)d(occurrence.)32 b(The)25 b(notation)1850 5649 +y(\22611\226)p eop end +%%Page: 12 12 +TeXDict begin 12 11 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)900 84 y(*metal1)146 +293 y(e)o(xpands)k(to)h(metal1)f(plus)g(all)h(of)g(the)g(contact)g +(types)f(associated)g(with)h(metal1,)g(such)g(as)g(ndc,)g(pdc,)h(nsc,)0 +413 y(m2c,)24 b(and)h(so)g(forth.)146 534 y(Note:)59 +b(in)39 b(the)g(CIF)i(sections)d(of)i(the)f(technology)f(\002le,)43 +b(only)38 b(simple)g(comma-separated)h(names)g(are)0 +654 y(permitted;)24 b(tildes)g(and)i(parentheses)f(are)h(not)f +(understood.)31 b(Ho)n(we)n(v)o(er)l(,)24 b(e)n(v)o(erywhere)h(else)g +(in)g(the)g(technology)0 774 y(\002le)37 b(the)f(full)f(generality)h +(can)h(be)f(used.)65 b(The)36 b(\223*\224)h(notation)e(for)h(inclusion) +f(of)h(contact)g(residues)g(may)g(be)0 895 y(present)25 +b(in)f(an)o(y)g(section.)0 1232 y Fi(9)143 b(Styles)35 +b(section)0 1455 y Fg(Magic)c(can)h(be)g(run)f(on)g(se)n(v)o(eral)g +(dif)n(ferent)g(types)g(of)h(graphical)f(displays.)50 +b(Although)30 b(it)h(w)o(ould)g(ha)n(v)o(e)g(been)0 1576 +y(possible)21 b(to)h(incorporate)g(display-speci\002c)g(information)f +(into)g(the)h(technology)f(\002le,)j(a)e(dif)n(ferent)g(technology)0 +1696 y(\002le)j(w)o(ould)e(ha)n(v)o(e)h(been)g(required)g(for)h(each)g +(display)e(type.)30 b(Instead,)24 b(the)g(technology)f(\002le)h(gi)n(v) +o(es)f(one)h(or)g(more)0 1816 y(display-independent)g +Fh(styles)i Fg(for)g(each)h(type)f(that)g(is)g(to)f(be)i(displayed,)e +(and)h(uses)g(a)h(per)n(-display-type)e(styles)0 1937 +y(\002le)k(to)e(map)h(to)g(colors)g(and)g(stipplings)e(speci\002c)i(to) +g(the)g(display)f(being)h(used.)40 b(The)29 b(styles)e(\002le)i(is)e +(described)0 2057 y(in)d(Magic)h(Maintainer')-5 b(s)23 +b(Manual)i(#3:)30 b(\223Styles)25 b(and)f(Colors\224,)h(so)g(we)g(will) +f(not)g(describe)h(it)f(further)h(here.)146 2177 y(T)-8 +b(able)25 b(6)g(sho)n(ws)e(part)i(of)f(the)h Fd(styles)f +Fg(section)g(from)g(the)h(scmos)f(technology)f(\002le.)31 +b(The)25 b(\002rst)g(line)f(speci\002es)0 2298 y(the)j(type)f(of)i +(style)e(\002le)h(for)g(use)g(with)g(this)f(technology)-6 +b(,)25 b(which)i(in)f(this)h(e)o(xample)f(is)g Fd(mos)p +Fg(.)37 b(Each)27 b(subsequent)0 2418 y(line)g(consists)e(of)j(a)f +(tile)g(type)g(and)g(a)g(style)g(number)f(\(an)i(inte)o(ger)e(between)h +(1)h(and)f(63\).)37 b(The)27 b(style)g(number)g(is)0 +2539 y(nothing)f(more)i(than)g(a)g(reference)h(between)f(the)g +(technology)f(\002le)h(and)g(the)f(styles)g(\002le.)40 +b(Notice)28 b(that)f(a)i(gi)n(v)o(en)0 2659 y(tile)24 +b(type)g(can)h(ha)n(v)o(e)f(se)n(v)o(eral)g(styles)f(\(e.g.,)i +(pcontact)f(uses)g(styles)f(#1,)h(#20,)g(and)h(#32\),)f(and)g(that)g(a) +h(gi)n(v)o(en)e(style)0 2779 y(may)h(be)g(used)g(to)g(display)f(se)n(v) +o(eral)g(dif)n(ferent)h(tiles)f(\(e.g.,)h(style)g(#2)g(is)f(used)h(in)g +(ndif)n(f)f(and)i(ndcontact\).)30 b(If)24 b(a)h(tile)0 +2900 y(type)f(should)g(not)g(be)h(displayed,)f(it)g(has)h(no)f(entry)h +(in)g(the)f Fd(styles)g Fg(section.)146 3020 y(It)40 +b(is)f(no)g(longer)g(necessary)h(to)f(ha)n(v)o(e)g(one)g(style)g(per)g +(line,)k(a)d(restriction)e(of)i(format)f(27)g(and)g(earlier)-5 +b(.)0 3141 y(Multiple)26 b(styles)g(for)i(a)g(tile)f(type)g(can)h(be)f +(placed)h(on)f(the)g(same)g(line,)h(separated)g(by)f(spaces.)39 +b(Styles)27 b(may)g(be)0 3261 y(speci\002ed)e(by)g(number)l(,)f(or)h +(by)f(the)h(\223long)f(name\224)h(in)f(the)h(style)f(\002le.)0 +3598 y Fi(10)143 b(Compose)34 b(section)0 3821 y Fg(The)29 +b(semantics)e(of)i(Magic')-5 b(s)27 b(paint)h(operation)g(are)i +(de\002ned)e(by)h(a)g(collection)e(of)i(rules)f(of)h(the)f(form,)h +(\223gi)n(v)o(en)0 3942 y(material)k Fh(HA)-10 b(VE)33 +b Fg(on)g(plane)h Fh(PLANE)p Fg(,)g(if)g(we)g(paint)f +Fh(P)-9 b(AINT)p Fg(,)34 b(then)f(we)h(get)g Fh(Z)p Fg(\224,)g(plus)f +(a)h(similar)e(set)i(of)f(rules)0 4062 y(for)f(the)f(erase)i +(operation.)50 b(The)32 b(def)o(ault)f(paint)g(and)h(erase)g(rules)f +(are)i(simple.)50 b(Assume)30 b(that)h(we)h(are)h(gi)n(v)o(en)0 +4182 y(material)24 b Fh(HA)-10 b(VE)24 b Fg(on)h(plane)g +Fh(PLANE)p Fg(,)g(and)g(are)g(painting)f(or)h(erasing)f(material)h +Fh(P)-9 b(AINT)p Fg(.)120 4391 y(1.)49 b Fh(Y)-9 b(ou)25 +b(g)o(et)f(what)h(you)g(paint.)244 4511 y Fg(If)c(the)g(home)f(plane)h +(of)g Fh(P)-9 b(AINT)22 b Fg(is)e Fh(PLANE)p Fg(,)i(or)f +Fh(P)-9 b(AINT)21 b Fg(is)g(space,)h(you)e(get)h Fh(P)-9 +b(AINT)p Fg(;)22 b(otherwise,)f(nothing)244 4632 y(changes)k(and)f(you) +h(get)f Fh(HA)-10 b(VE)p Fg(.)120 4830 y(2.)49 b Fh(Y)-9 +b(ou)25 b(can)f(er)o(ase)h(all)f(or)g(nothing)o(.)244 +4951 y Fg(Erasing)g(space)h(or)g Fh(P)-9 b(AINT)26 b +Fg(from)e Fh(P)-9 b(AINT)26 b Fg(will)e(gi)n(v)o(e)g(space;)g(erasing)h +(an)o(ything)e(else)i(has)g(no)f(ef)n(fect.)146 5159 +y(These)i(rules)g(apply)g(for)g(contacts)g(as)g(well.)35 +b(P)o(ainting)24 b(the)i(base)h(type)e(of)i(a)f(contact)g(paints)f(the) +h(base)g(type)0 5280 y(on)21 b(its)f(home)h(plane,)h(and)f(each)h +(image)f(type)f(on)h(its)g(home)f(plane.)30 b(Erasing)21 +b(the)g(base)g(type)g(of)g(a)h(contact)f(erases)0 5400 +y(both)j(the)h(base)g(type)f(and)h(the)g(image)f(types.)1850 +5649 y(\22612\226)p eop end +%%Page: 13 13 +TeXDict begin 13 12 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)p 1525 3 850 4 +v 1523 124 4 121 v 1575 88 a Fd(styles)p 2373 124 V 1523 +244 V 1575 208 a Fg(styles)p 2373 244 V 1523 364 V 1575 +328 a(styletype)f(mos)p 2373 364 V 1523 485 V 1575 449 +a(poly)472 b(1)p 2373 485 V 1523 605 V 1575 569 a(ndif)n(f)458 +b(2)p 2373 605 V 1523 726 V 1575 689 a(pdif)n(f)g(4)p +2373 726 V 1523 846 V 1575 810 a(nfet)495 b(6)p 2373 +846 V 1523 966 V 1575 930 a(nfet)g(7)p 2373 966 V 1523 +1087 V 1575 1051 a(pfet)g(8)p 2373 1087 V 1523 1207 V +1575 1171 a(pfet)g(9)p 2373 1207 V 1523 1328 V 1575 1291 +a(metal1)378 b(20)p 2373 1328 V 1523 1448 V 1575 1412 +a(metal2)g(21)p 2373 1448 V 1523 1568 V 1575 1532 a(pcontact)312 +b(1)p 2373 1568 V 1523 1689 V 1575 1653 a(pcontact)g(20)p +2373 1689 V 1523 1809 V 1575 1773 a(pcontact)g(32)p 2373 +1809 V 1523 1929 V 1575 1893 a(ndcontact)262 b(2)p 2373 +1929 V 1523 2050 V 1575 2014 a(ndcontact)g(20)p 2373 +2050 V 1523 2170 V 1575 2134 a(ndcontact)g(32)p 2373 +2170 V 1523 2291 V 1575 2254 a(pdcontact)g(4)p 2373 2291 +V 1523 2411 V 1575 2375 a(pdcontact)g(20)p 2373 2411 +V 1523 2531 V 1575 2495 a(pdcontact)g(32)p 2373 2531 +V 1523 2652 V 1575 2616 a(m2contact)234 b(20)p 2373 2652 +V 1523 2772 V 1575 2736 a(m2contact)g(21)p 2373 2772 +V 1523 2892 V 1575 2856 a(m2contact)g(33)p 2373 2892 +V 1523 3013 V 1575 2977 a Fd(end)p 2373 3013 V 1525 3016 +850 4 v 1285 3175 a Fg(T)-8 b(able)25 b(6:)30 b(P)o(art)25 +b(of)g(the)g Fd(styles)f Fg(section)146 3547 y(It)31 +b(is)f(sometimes)f(desirable)h(for)h(certain)g(tile)f(types)g(to)g +(beha)n(v)o(e)h(as)f(though)g(the)o(y)g(were)h(\223composed\224)f(of)0 +3668 y(other)l(,)41 b(more)d(fundamental)f(ones.)70 b(F)o(or)37 +b(e)o(xample,)k(painting)36 b(poly)i(o)o(v)o(er)f(ndif)n(fusion)f(in)h +(scmos)g(produces)0 3788 y(ntransistor)l(,)31 b(instead)e(of)i(ndif)n +(fusion.)46 b(Also,)31 b(painting)e(either)i(poly)e(or)i(ndif)n(fusion) +e(o)o(v)o(er)g(ntransistor)h(lea)n(v)o(es)0 3908 y(ntransistor)l(,)40 +b(erasing)d(poly)g(from)g(ntransistor)g(lea)n(v)o(es)g(ndif)n(fusion,)i +(and)f(erasing)f(ndif)n(fusion)f(lea)n(v)o(es)h(poly)-6 +b(.)0 4029 y(The)22 b(semantics)g(for)h(ntransistor)e(are)i(a)g(result) +f(of)g(the)g(follo)n(wing)f(rule)h(in)g(the)h Fd(compose)f +Fg(section)g(of)h(the)f(scmos)0 4149 y(technology)i(\002le:)900 +4416 y Fd(compose)h Fg(ntransistor)f(poly)g(ndif)n(f)146 +4678 y(Sometimes,)d(not)e(all)i(of)f(the)h(\223component\224)e(layers)i +(of)g(a)f(type)h(are)g(layers)f(kno)n(wn)g(to)g(magic.)29 +b(As)20 b(an)h(e)o(xam-)0 4798 y(ple,)30 b(in)e(the)h +Fd(nmos)g Fg(technology)-6 b(,)28 b(there)h(are)g(tw)o(o)g(types)f(of)h +(transistors:)37 b Fd(enhancement-fet)32 b Fg(and)d Fd(depletion-)0 +4918 y(fet)p Fg(.)40 b(Although)26 b(both)g(contain)h(polysilicon)f +(and)h(dif)n(fusion,)g(depletion-fet)g(can)h(be)f(thought)g(of)g(as)h +(also)f(con-)0 5039 y(taining)21 b(implant,)h(which)g(is)g(not)g(a)h +(tile)f(type.)30 b(So)23 b(while)f(we)h(can')n(t)g(construct)f +(depletion-fet)f(by)i(painting)e(poly)0 5159 y(and)26 +b(then)f(dif)n(fusion,)f(we')-5 b(d)26 b(still)f(lik)o(e)g(it)g(to)g +(beha)n(v)o(e)h(as)g(though)e(it)i(contained)f(both)g(materials.)32 +b(P)o(ainting)25 b(poly)0 5280 y(or)k(dif)n(fusion)e(o)o(v)o(er)h(a)h +(depletion-fet)f(should)g(not)g(change)h(it,)h(and)f(erasing)f(either)h +(poly)f(or)h(dif)n(fusion)e(should)0 5400 y(gi)n(v)o(e)c(the)i(other)-5 +b(.)30 b(These)25 b(semantics)f(are)h(the)g(result)f(of)h(the)g(follo)n +(wing)e(rule:)1850 5649 y(\22613\226)p eop end +%%Page: 14 14 +TeXDict begin 14 13 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)900 84 y Fd(decompose)i +Fg(dfet)f(poly)f(dif)n(f)146 315 y(The)h(general)g(syntax)f(of)h(both)f +(types)g(of)h(composition)e(rules,)h Fd(compose)h Fg(and)g +Fd(decompose)p Fg(,)h(is:)900 546 y Fd(compose)100 b +Fh(type)50 b(a1)24 b(b1)50 b(a2)24 b(b2)50 b(.)15 b(.)g(.)900 +666 y Fd(decompose)26 b Fh(type)50 b(a1)24 b(b1)50 b(a2)24 +b(b2)49 b(.)15 b(.)g(.)146 897 y Fg(The)31 b(idea)h(is)e(that)h(each)h +(of)f(the)g(pairs)g Fh(a1)g(b1)p Fg(,)h Fh(a2)f(b2)p +Fg(,)h(etc)g(comprise)e Fh(type)p Fg(.)50 b(In)31 b(the)g(case)h(of)f +(a)h Fd(compose)0 1017 y Fg(rule,)24 b(painting)e(an)o(y)h +Fh(a)g Fg(atop)g(its)g(corresponding)f Fh(b)h Fg(will)g(gi)n(v)o(e)f +Fh(type)p Fg(,)h(as)h(well)f(as)g(vice-v)o(ersa.)31 b(In)23 +b(both)g Fd(compose)0 1138 y Fg(and)h Fd(decompose)i +Fg(rules,)e(erasing)h Fh(a)f Fg(from)g Fh(type)h Fg(gi)n(v)o(es)e +Fh(b)p Fg(,)h(erasing)h Fh(b)f Fg(from)g Fh(type)h Fg(gi)n(v)o(es)e +Fh(a)p Fg(,)h(and)h(painting)e(either)0 1258 y Fh(a)i +Fg(or)g Fh(b)f Fg(o)o(v)o(er)g Fh(type)h Fg(lea)n(v)o(es)g +Fh(type)f Fg(unchanged.)p 1052 1401 1797 4 v 1050 1521 +4 121 v 1102 1485 a Fd(compose)p 1050 1641 V 1102 1605 +a Fg(compose)110 b(nfet)350 b(poly)143 b(ndif)n(f)p 2846 +1641 V 1050 1762 V 1102 1726 a(compose)110 b(pfet)350 +b(poly)143 b(pdif)n(f)p 2846 1762 V 1050 1882 V 1102 +1846 a(paint)265 b(pwell)283 b(nwell)99 b(nwell)p 2846 +1882 V 1050 2003 V 1102 1966 a(paint)265 b(nwell)283 +b(pwell)99 b(pwell)p 2846 2003 V 1050 2123 V 1102 2087 +a(paint)265 b(pdc/acti)n(v)o(e)98 b(pwell)h(ndc/acti)n(v)o(e)p +2846 2123 V 1050 2243 V 1102 2207 a(paint)265 b(pdc/m1)205 +b(pwell)99 b(ndc/m1)p 2846 2243 V 1050 2364 V 1102 2328 +a(paint)265 b(pfet)350 b(pwell)99 b(nfet)p 2846 2364 +V 1050 2484 V 1102 2448 a(paint)265 b(pdif)n(f)313 b(pwell)99 +b(ndif)n(f)p 2846 2484 V 1050 2605 V 1102 2568 a(paint)265 +b(nsd)366 b(pwell)99 b(psd)p 2846 2605 V 1050 2725 V +1102 2689 a(paint)265 b(nsc/acti)n(v)o(e)109 b(pwell)99 +b(psc/acti)n(v)o(e)p 2846 2725 V 1050 2845 V 1102 2809 +a(paint)265 b(nsc/m1)216 b(pwell)99 b(psc/m1)p 2846 2845 +V 1050 2966 V 1102 2930 a(paint)265 b(ndc/acti)n(v)o(e)98 +b(nwell)h(pdc/acti)n(v)o(e)p 2846 2966 V 1050 3086 V +1102 3050 a(paint)265 b(ndc/m1)205 b(nwell)99 b(pdc/m1)p +2846 3086 V 1050 3206 V 1102 3170 a(paint)265 b(nfet)350 +b(nwell)99 b(pfet)p 2846 3206 V 1050 3327 V 1102 3291 +a(paint)265 b(ndif)n(f)313 b(nwell)99 b(pdif)n(f)p 2846 +3327 V 1050 3447 V 1102 3411 a(paint)265 b(psd)366 b(nwell)99 +b(nsd)p 2846 3447 V 1050 3568 V 1102 3531 a(paint)265 +b(psc/acti)n(v)o(e)109 b(nwell)99 b(nsc/acti)n(v)o(e)p +2846 3568 V 1050 3688 V 1102 3652 a(paint)265 b(psc/m1)216 +b(nwell)99 b(nsc/m1)p 2846 3688 V 1050 3808 V 1102 3772 +a Fd(end)p 2846 3808 V 1052 3812 1797 4 v 1424 3972 a +Fg(T)-8 b(able)25 b(7:)30 b Fd(Compose)25 b Fg(section)146 +4316 y(Contacts)g(are)h(implicitly)c(composed)i(of)h(their)g(component) +f(types,)g(so)g(the)h(result)g(obtained)f(when)h(paint-)0 +4437 y(ing)32 b(a)g(type)g Fh(P)-9 b(AINT)33 b Fg(o)o(v)o(er)f(a)g +(contact)g(type)g Fh(CONT)-5 b(A)m(CT)34 b Fg(will)e(by)g(def)o(ault)g +(depend)g(only)f(on)h(the)g(component)0 4557 y(types)23 +b(of)h Fh(CONT)-5 b(A)m(CT)p Fg(.)26 b(If)f(painting)d +Fh(P)-9 b(AINT)25 b Fg(doesn')n(t)f(af)n(fect)g(the)g(component)f +(types)g(of)h(the)g(contact,)g(then)f(it)h(is)0 4677 +y(considered)k(not)f(to)h(af)n(fect)h(the)f(contact)g(itself)f(either) +-5 b(.)41 b(If)28 b(painting)f Fh(P)-9 b(AINT)29 b Fg(does)f(af)n(fect) +h(an)o(y)e(of)i(the)f(compo-)0 4798 y(nent)23 b(types,)g(then)h(the)f +(result)g(is)h(as)f(though)g(the)g(contact)h(had)f(been)h(replaced)g +(by)g(its)e(component)h(types)g(in)g(the)0 4918 y(layout)h(before)h +(type)g Fh(P)-9 b(AINT)25 b Fg(w)o(as)g(painted.)30 b(Similar)25 +b(rules)f(hold)g(for)h(erasing.)146 5039 y(A)c(pcontact)f(has)g +(component)f(types)h(poly)g(and)g(metal1.)29 b(Since)21 +b(painting)e(poly)h(doesn')n(t)g(af)n(fect)g(either)h(poly)0 +5159 y(or)i(metal1,)g(it)g(doesn')n(t)g(af)n(fect)h(a)g(pcontact)f +(either)-5 b(.)29 b(P)o(ainting)23 b(ndif)n(fusion)e(does)i(af)n(fect)h +(poly:)29 b(it)23 b(turns)g(it)f(into)h(an)0 5280 y(ntransistor)-5 +b(.)46 b(Hence,)32 b(painting)d(ndif)n(fusion)f(o)o(v)o(er)i(a)g +(pcontact)g(breaks)h(up)f(the)g(contact,)i(lea)n(ving)d(ntransistor)0 +5400 y(on)c(the)f(acti)n(v)o(e)g(plane)h(and)f(metal1)h(on)f(the)h +(metal1)f(plane.)1850 5649 y(\22614\226)p eop end +%%Page: 15 15 +TeXDict begin 15 14 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)146 68 y(The)h +Fd(compose)f Fg(and)h Fd(decompose)g Fg(rules)f(are)h(normally)e(suf)n +(\002cient)h(to)g(specify)g(the)g(desired)h(semantics)e(of)0 +188 y(painting)f(or)i(erasing.)30 b(In)25 b(unusual)e(cases,)i(ho)n(we) +n(v)o(er)l(,)e(it)h(may)g(be)h(necessary)f(to)g(pro)o(vide)g(Magic)g +(with)g(e)o(xplicit)0 309 y Fd(paint)j Fg(or)f Fd(erase)h +Fg(rules.)35 b(F)o(or)26 b(e)o(xample,)g(to)g(specify)g(that)g +(painting)f(pwell)g(o)o(v)o(er)h(pdif)n(fusion)e(switches)i(its)f(type) +0 429 y(to)f(ndif)n(fusion,)f(the)i(technology)f(\002le)h(contains)f +(the)g(rule:)900 658 y Fd(paint)h Fg(pdif)n(fusion)e(pwell)i(ndif)n +(fusion)146 887 y(This)e(rule)g(could)g(not)f(ha)n(v)o(e)h(been)h +(written)f(as)g(a)g Fd(decompose)i Fg(rule;)e(erasing)g(ndif)n(fusion)f +(from)h(pwell)f(does)0 1007 y(not)27 b(yield)h(pdif)n(fusion,)e(nor)i +(does)g(erasing)f(pdif)n(fusion)f(from)i(ndif)n(fusion)e(yield)h +(pwell.)40 b(The)28 b(general)g(syntax)0 1128 y(for)d(these)g(e)o +(xplicit)e(rules)i(is:)900 1357 y Fd(paint)g Fh(have)g(t)g(r)l(esult)f +Fg([)p Fh(p)p Fg(])900 1477 y Fd(erase)h Fh(have)g(t)g(r)l(esult)f +Fg([)p Fh(p)p Fg(])146 1706 y(Here,)f Fh(have)e Fg(is)f(the)h(type)f +(already)h(present,)h(on)e(plane)h Fh(p)g Fg(if)g(it)f(is)g +(speci\002ed;)j(otherwise,)e(on)f(the)h(home)f(plane)0 +1826 y(of)26 b Fh(have)p Fg(.)32 b(T)-8 b(ype)26 b Fh(t)f +Fg(is)g(being)g(painted)g(or)h(erased,)g(and)f(the)g(result)g(is)g +(type)h Fh(r)l(esult)p Fg(.)32 b(T)-8 b(able)25 b(7)h(gi)n(v)o(es)d +(the)j Fd(compose)0 1947 y Fg(section)e(for)h(scmos.)146 +2067 y(It')-5 b(s)28 b(easiest)f(to)h(think)e(of)i(the)g(paint)f(and)h +(erase)h(rules)e(as)h(being)g(b)n(uilt)e(up)i(in)f(four)h(passes.)40 +b(The)27 b(\002rst)h(pass)0 2188 y(generates)22 b(the)g(def)o(ault)f +(rules)h(for)g(all)g(non-contact)f(types,)h(and)f(the)h(second)g(pass)f +(replaces)h(these)g(as)g(speci\002ed)0 2308 y(by)27 b(the)g +Fd(compose)p Fg(,)h Fd(decompose)p Fg(,)g(etc.)38 b(rules,)28 +b(also)e(for)i(non-contact)e(types.)38 b(At)26 b(this)h(point,)f(the)h +(beha)n(vior)g(of)0 2428 y(the)k(component)e(types)h(of)h(contacts)f +(has)h(been)g(completely)f(determined,)h(so)f(the)h(third)f(pass)g(can) +i(generate)0 2549 y(the)e(def)o(ault)g(rules)g(for)g(all)g(contact)g +(types,)h(and)f(the)g(fourth)g(pass)g(can)g(modify)f(these)h(as)h(per)f +(an)o(y)g Fd(compose)p Fg(,)0 2669 y(etc.)h(rules)25 +b(for)g(contacts.)0 3009 y Fi(11)143 b(Connect)34 b(section)0 +3233 y Fg(F)o(or)j(circuit)f(e)o(xtraction,)j(routing,)g(and)e(some)f +(of)h(the)g(net-list)f(operations,)j(Magic)d(needs)h(to)f(kno)n(w)g +(what)0 3353 y(types)27 b(are)i(electrically)e(connected.)40 +b(Magic')-5 b(s)27 b(model)g(of)h(electrical)g(connecti)n(vity)e(used)h +(is)h(based)f(on)h(signal)0 3474 y(propagation.)45 b(T)-8 +b(w)o(o)30 b(types)g(should)f(be)h(mark)o(ed)g(as)h(connected)f(if)g(a) +g(signal)g(will)f Fh(always)h Fg(pass)g(between)g(the)0 +3594 y(tw)o(o)j(types,)i(in)f(either)f(direction.)57 +b(F)o(or)33 b(the)h(most)e(part,)k(this)d(will)g(mean)g(that)g(all)h +(non-space)f(types)g(within)0 3714 y(a)f(plane)g(should)f(be)i(mark)o +(ed)f(as)g(connected.)52 b(The)32 b(e)o(xceptions)f(to)h(this)f(rule)h +(are)h(de)n(vices)e(\(transistors\).)52 b(A)0 3835 y(transistor)28 +b(should)g(be)h(considered)g(electrically)g(connected)g(to)g(adjacent)g +(polysilicon,)f(b)n(ut)h(not)f(to)h(adjacent)0 3955 y(dif)n(fusion.)42 +b(This)29 b(models)f(the)h(f)o(act)g(that)g(polysilicon)e(connects)i +(to)g(the)g(gate)g(of)g(the)g(transistor)l(,)g(b)n(ut)g(that)f(the)0 +4076 y(transistor)21 b(acts)h(as)g(a)g(switch)f(between)h(the)g(dif)n +(fusion)e(areas)j(on)f(either)g(side)f(of)h(the)g(channel)g(of)g(the)g +(transistor)-5 b(.)146 4196 y(The)28 b(lines)e(in)h(the)g +Fd(connect)i Fg(section)e(of)g(a)h(technology)e(\002le,)i(as)f(sho)n +(wn)f(in)h(T)-8 b(able)27 b(8,)h(each)g(contain)e(a)i(pair)0 +4316 y(of)23 b(type-lists)f(in)h(the)g(format)g(described)g(in)f +(Section)i(8.)30 b(Each)23 b(type)g(in)g(the)g(\002rst)g(list)f +(connects)h(to)g(each)h(type)e(in)0 4437 y(the)i(second)h(list.)k(This) +24 b(does)h(not)f(imply)f(that)h(the)g(types)g(in)h(the)f(\002rst)h +(list)e(are)j(themselv)o(es)d(connected)h(to)g(each)0 +4557 y(other)l(,)h(or)f(that)h(the)f(types)h(in)f(the)h(second)f(list)g +(are)i(connected)e(to)h(each)g(other)-5 b(.)146 4678 +y(Because)31 b(connecti)n(vity)e(is)g(a)i(symmetric)e(relationship,)g +(only)h(one)g(of)g(the)g(tw)o(o)f(possible)g(orders)h(of)h(tw)o(o)0 +4798 y(tile)20 b(types)g(need)h(be)f(speci\002ed.)30 +b(T)m(iles)19 b(of)i(the)f(same)g(type)h(are)g(al)o(w)o(ays)f +(considered)g(to)g(be)h(connected.)29 b(Contacts)0 4918 +y(are)i(treated)g(specially;)h(the)o(y)d(should)g(be)i(speci\002ed)f +(as)h(connecting)f(to)f(material)h(in)g(all)g(planes)g(spanned)g(by)0 +5039 y(the)e(contact.)40 b(F)o(or)28 b(e)o(xample,)g(pcontact)f(is)h +(sho)n(wn)f(as)h(connecting)f(to)g(se)n(v)o(eral)h(types)f(in)h(the)f +(acti)n(v)o(e)g(plane,)i(as)0 5159 y(well)22 b(as)g(se)n(v)o(eral)g +(types)g(in)g(the)g(metal1)g(plane.)29 b(The)23 b(connecti)n(vity)d(of) +j(a)f(contact)h(should)e(usually)g(be)i(that)e(of)i(its)0 +5280 y(component)29 b(types,)j(so)e(pcontact)g(should)f(connect)h(to)h +(e)n(v)o(erything)d(connected)j(to)f(poly)-6 b(,)30 b(and)h(to)f(e)n(v) +o(erything)0 5400 y(connected)25 b(to)f(metal1.)1850 +5649 y(\22615\226)p eop end +%%Page: 16 16 +TeXDict begin 16 15 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)p 225 3 3451 4 +v 223 124 4 121 v 274 88 a Fd(connect)p 3674 124 V 223 +244 V 274 208 a Fg(#de\002ne)i(allMetal2)d(m2,m2c/m2,pad/m2)p +3674 244 V 223 364 V 274 328 a(#de\002ne)j(allMetal1)d +(m1,m2c/m1,pc/m1,ndc/m1,pdc/m1,ppcont/)o(m1,n)o(ncont/m)o(1,pad/)o(m1)p +3674 364 V 223 485 V 274 449 a(#de\002ne)j(allPoly)e(poly)-6 +b(,pc/a,nfet,pfet)p 3674 485 V 223 605 V 274 569 a(allMetal2)1071 +b(allMetal2)p 3674 605 V 223 726 V 274 689 a(allMetal1)g(allMetal1)p +3674 726 V 223 846 V 274 810 a(allPoly)1171 b(allPoly)p +3674 846 V 223 966 V 274 930 a(ndif)n(f)1262 b(ndc)p +3674 966 V 223 1087 V 274 1051 a(pdif)n(f)g(pdc)p 3674 +1087 V 223 1207 V 274 1171 a(nwell,nnc,nsd)899 b(nwell,nnc,nsd)p +3674 1207 V 223 1328 V 274 1291 a(pwell,ppc,psd)g(pwell,ppc,psd)p +3674 1328 V 223 1448 V 274 1412 a(nnc)1310 b(pdc)p 3674 +1448 V 223 1568 V 274 1532 a(ppc)g(ndc)p 3674 1568 V +223 1689 V 274 1653 a Fd(end)p 3674 1689 V 225 1692 3451 +4 v 1443 1852 a Fg(T)-8 b(able)25 b(8:)30 b Fd(Connect)d +Fg(section)0 2244 y Fi(12)143 b(Cif)l(output)34 b(section)0 +2487 y Fg(The)25 b(layers)g(stored)g(by)g(Magic)g(do)g(not)f(al)o(w)o +(ays)h(correspond)g(to)g(physical)f(mask)h(layers.)31 +b(F)o(or)26 b(e)o(xample,)e(there)0 2607 y(is)35 b(no)g(physical)g +(layer)h(corresponding)e(to)h(\(the)h(scmos)f(technology)f(\002le)i +(layer\))g(ntransistor;)k(instead,)d(the)0 2727 y(actual)31 +b(circuit)g(must)f(be)h(b)n(uilt)f(up)h(by)g(o)o(v)o(erlapping)e(poly)i +(and)g(dif)n(fusion)e(o)o(v)o(er)i(pwell.)49 b(When)31 +b(writing)f(CIF)0 2848 y(\(Caltech)k(Intermediate)f(F)o(orm\))f(or)i +(Calma)f(GDS-II)h(\002les,)i(Magic)c(generates)i(the)f(actual)g +(geometries)g(that)0 2968 y(will)24 b(appear)h(on)g(the)f(masks)g(used) +h(to)f(f)o(abricate)h(the)g(circuit.)30 b(The)25 b Fd(cif)n(output)h +Fg(section)e(of)h(the)f(technology)g(\002le)0 3088 y(describes)h(ho)n +(w)f(to)g(generate)h(mask)g(layers)f(from)h(Magic')-5 +b(s)24 b(abstract)h(layers.)0 3441 y Ff(12.1)119 b(CIF)30 +b(and)g(GDS)h(styles)0 3647 y Fg(From)j(the)f(1990')-5 +b(s,)35 b(the)e(CIF)i(format)f(has)f(lar)n(gely)h(been)g(replaced)g(by) +g(the)f(GDS)h(format.)57 b(Ho)n(we)n(v)o(er)l(,)35 b(the)o(y)0 +3767 y(describe)c(the)h(same)f(layout)f(geometry)-6 b(,)32 +b(and)g(the)f(formats)g(are)h(similar)e(enough)h(that)g(magic)g(mak)o +(es)g(use)g(of)0 3888 y(the)j(CIF)g(generation)g(code)g(as)g(the)f +(basis)g(for)h(the)g(GDS)g(write)g(routines.)56 b(The)34 +b(technology)f(\002le)h(also)f(uses)0 4008 y(CIF)28 b(layer)e +(declarations)g(as)h(the)f(basis)g(for)h(GDS)f(output.)35 +b(So)26 b(e)n(v)o(en)g(a)h(technology)e(\002le)i(that)f(only)g(e)o +(xpects)f(to)0 4128 y(generate)i(GDS)g(output)e(needs)h(a)h(\223)p +Fd(cif)n(output)p Fg(\224)h(section)e(declaring)g(CIF)h(layer)g(names.) +35 b(If)27 b(only)f(GDS)g(output)0 4249 y(is)d(required,)g(these)h +(names)e(may)h(be)h(longer)f(and)g(therefore)h(more)f(descripti)n(v)o +(e)f(than)h(allo)n(wed)f(by)h(CIF)h(format)0 4369 y(syntax.)146 +4498 y(The)31 b(technology)e(\002le)i(can)g(contain)f(se)n(v)o(eral)g +(dif)n(ferent)g(speci\002cations)g(of)g(ho)n(w)g(to)g(generate)h(CIF)-8 +b(.)32 b(Each)0 4619 y(of)24 b(these)f(is)g(called)h(a)g(CIF)g +Fh(style)p Fg(.)30 b(Dif)n(ferent)24 b(styles)e(may)h(be)h(used)f(for)h +(f)o(abrication)f(at)h(dif)n(ferent)f(feature)h(sizes,)0 +4739 y(or)k(for)f(totally)f(dif)n(ferent)h(purposes.)38 +b(F)o(or)28 b(e)o(xample,)f(some)g(of)g(the)g(Magic)g(technology)g +(\002les)g(contain)g(a)h(style)0 4860 y(\223plot\224)20 +b(that)f(generates)h(CIF)i(pseudo-layers)d(that)h(ha)n(v)o(e)f(e)o +(xactly)h(the)g(same)f(shapes)h(as)g(the)g(Magic)g(layers.)29 +b(This)0 4980 y(style)c(is)g(used)h(for)g(generating)f(plots)g(that)g +(look)g(just)g(lik)o(e)g(what)g(appears)h(on)g(the)f(color)h(display;)f +(it)g(mak)o(es)g(no)0 5100 y(sense)g(for)g(f)o(abrication.)30 +b(Lines)24 b(of)h(the)g(form)900 5400 y Fd(style)g Fh(name)1850 +5649 y Fg(\22616\226)p eop end +%%Page: 17 17 +TeXDict begin 17 16 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)p 1036 3 1829 +4 v 1034 124 4 121 v 1085 88 a Fd(cif)n(output)p 2863 +124 V 1034 244 V 1085 208 a Fg(style)g(lambda=1.0\(gen\))p +2863 244 V 1034 364 V 1385 328 a(scalef)o(actor)h(100)p +2863 364 V 1034 485 V 1385 449 a(layer)f(CWN)h(nwell)p +2863 485 V 1034 605 V 1685 569 a(bloat-or)f(pdif)n(f,pdc,pfet)e(*)i +(600)p 2863 605 V 1034 726 V 1685 689 a(bloat-or)g(nsc,nnd)f(*)h(300)p +2863 726 V 1034 846 V 1685 810 a(gro)n(w)g(300)p 2863 +846 V 1034 966 V 1685 930 a(shrink)f(300)p 2863 966 V +1034 1087 V 1685 1051 a(gds)h(42)f(1)p 2863 1087 V 1034 +1207 V 1385 1171 a(layer)h(CWP)h(pwell)p 2863 1207 V +1034 1328 V 1685 1291 a(bloat-or)f(ndif)n(f,ndc,nfet)e(*)i(600)p +2863 1328 V 1034 1448 V 1685 1412 a(bloat-or)g(psc,ppd)f(*)h(300)p +2863 1448 V 1034 1568 V 1685 1532 a(gro)n(w)g(300)p 2863 +1568 V 1034 1689 V 1685 1653 a(shrink)f(300)p 2863 1689 +V 1034 1809 V 1685 1773 a(gds)h(41)f(1)p 2863 1809 V +1034 1929 V 1385 1893 a(layer)h(CMS)h(allMetal2)p 2863 +1929 V 1034 2050 V 1685 2014 a(labels)f(m2)p 2863 2050 +V 1034 2170 V 1685 2134 a(gds)g(51)f(1)p 2863 2170 V +1034 2291 V 1385 2254 a(layer)h(CAA)h(allDif)n(f)p 2863 +2291 V 1034 2411 V 1685 2375 a(labels)f(ndif)n(f,pdif)n(f)p +2863 2411 V 1034 2531 V 1685 2495 a(gds)g(43)f(1)p 2863 +2531 V 1034 2652 V 1385 2616 a(layer)h(CCA)h(ndc,pdc)p +2863 2652 V 1034 2772 V 1685 2736 a(squares)f(200)p 2863 +2772 V 1034 2892 V 1685 2856 a(gds)g(48)f(1)p 2863 2892 +V 1034 3013 V 1385 2977 a(layer)h(CCA)h(nncont,ppcont)p +2863 3013 V 1034 3133 V 1685 3097 a(squares)f(200)p 2863 +3133 V 1034 3254 V 1685 3218 a(gds)g(48)f(1)p 2863 3254 +V 1034 3374 V 1385 3338 a(layer)h(CCP)i(pc)p 2863 3374 +V 1034 3494 V 1685 3458 a(squares)e(200)p 2863 3494 V +1034 3615 V 1685 3579 a(gds)g(47)f(1)p 2863 3615 V 1034 +3735 V 1085 3699 a Fd(end)p 2863 3735 V 1036 3738 1829 +4 v 567 3898 a Fg(T)-8 b(able)25 b(9:)30 b(P)o(art)25 +b(of)g(the)f Fd(cif)n(output)i Fg(section)e(for)h(style)g +(lambda=1.0\(gen\))f(only)-6 b(.)146 4245 y(are)33 b(used)f(to)g(end)f +(the)h(description)f(of)h(the)g(pre)n(vious)f(style)g(and)h(start)g +(the)g(description)f(of)h(a)g(ne)n(w)g(style.)0 4366 +y(The)22 b(Magic)g(command)f Fd(:cif)i(ostyle)e Fh(name)h +Fg(is)g(typed)g(by)f(users)h(to)g(change)g(the)g(current)h(style)e +(used)h(for)g(output.)0 4486 y(The)k(\002rst)g(style)g(in)f(the)h +(technology)f(\002le)i(is)e(used)h(by)g(def)o(ault)g(for)g(CIF)h +(output)e(if)h(the)g(designer)g(doesn')n(t)g(issue)0 +4606 y(a)e Fd(:cif)g(style)g Fg(command.)29 b(If)c(the)f(\002rst)g +(line)f(of)h(the)g Fd(cif)n(output)h Fg(section)e(isn')n(t)g(a)h +Fd(style)g Fg(line,)f(then)h(Magic)f(uses)h(an)0 4727 +y(initial)f(style)i(name)f(of)h Fd(default)p Fg(.)0 5017 +y Ff(12.2)119 b(Scaling)0 5205 y Fg(Each)25 b(style)f(must)g(contain)g +(a)h(line)g(of)f(the)h(form)900 5400 y Fd(scalefactor)g +Fh(scale)g Fg([)p Fd(nanometers)p Fe(j)p Fd(angstr)n(oms)p +Fg(])1850 5649 y(\22617\226)p eop end +%%Page: 18 18 +TeXDict begin 18 17 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)146 68 y(that)29 +b(tells)f(ho)n(w)h(to)g(scale)g(Magic)g(coordinates)g(into)f(CIF)i +(coordinates.)44 b(The)29 b(ar)n(gument)g Fh(scale)g +Fg(indicates)0 189 y(ho)n(w)38 b(man)o(y)g(hundredths)g(of)h(a)h +(micron)e(correspond)h(to)g(one)g(Magic)g(unit.)72 b +Fh(scale)39 b Fg(may)g(be)g(an)o(y)g(number)l(,)0 309 +y(including)c(decimals.)65 b(Ho)n(we)n(v)o(er)l(,)39 +b(all)d(units)f(in)i(the)f(style)g(description)f(must)h(be)g(inte)o +(ger)-5 b(.)65 b(Because)38 b(deep)0 429 y(submicron)20 +b(processes)i(may)f(require)h(CIF)h(operations)e(in)g(units)g(of)g +(less)h(than)f(one)h(centimicron,)f(the)g(optional)0 +550 y(parameter)i Fd(nanometers)g Fg(declares)g(that)f(all)g(units)f +(\(including)g(the)i Fh(scale)f Fg(parameter\))h(are)g(measured)f(in)g +(units)0 670 y(of)38 b(nanometers.)69 b(Lik)o(e)n(wise,)40 +b(the)e(units)f(may)g(all)h(be)g(speci\002ed)g(in)g Fd(angstr)n(oms)p +Fg(.)70 b(Ho)n(we)n(v)o(er)37 b(unlik)o(ely)f(the)0 790 +y(dimensions)31 b(may)h(seem,)j(the)e(problem)f(is)g(that)g(magic)h +(needs)g(to)f(place)h(some)g(objects,)h(lik)o(e)e(contacts,)i(on)0 +911 y(half-lambda)d(positions)f(to)i(ensure)g(correct)g(o)o(v)o(erlap)f +(of)h(contact)g(cuts)f(between)h(subcells.)52 b(A)32 +b(feature)g(size)0 1031 y(such)23 b(as,)g(for)g(e)o(xample,)f(45)h +(nanometers,)g(has)f(a)i(half-lambda)e(v)n(alue)g(of)h(22.5)g +(nanometers.)29 b(Since)23 b(this)f(is)h(not)0 1152 y(an)e(inte)o(ger)l +(,)g(magic)g(will)f(complain)g(about)h(this)f(scalef)o(actor)-5 +b(.)29 b(This)21 b(is)f(true)i(e)n(v)o(en)e(if)h(the)g(process)g +(doesn')n(t)g Fh(allow)0 1272 y Fg(sub-nanometer)27 b(coordinates,)h +(and)f(magic)h(uses)f(the)h Fh(squar)l(es-grid)e Fg(statement)h(to)g +(enforce)h(this)f(restriction.)0 1392 y(In)d(such)g(a)h(case,)g(it)f +(is)g(necessary)g(to)g(declare)h(a)g(scalef)o(actor)g(of)f(450)g +(angstroms)f(rather)i(than)f(45)g(nanometers.)146 1514 +y(V)-11 b(ersions)27 b(of)g Fh(ma)o(gic)g Fg(prior)g(to)f(7.1)h(allo)n +(wed)f(an)i(optional)d(second)i(\(inte)o(ger\))g(parameter)l(,)h +Fh(r)l(educer)p Fg(,)g(or)f(the)0 1634 y(k)o(e)o(yw)o(ord)f +Fd(calmaonly)p Fg(.)37 b(The)28 b(use)f(of)g Fh(r)l(educer)g +Fg(is)g(inte)o(gral)f(to)h(CIF)h(output,)e(which)h(uses)g(the)g(v)n +(alue)f(to)h(ensure)0 1754 y(that)22 b(output)f(v)n(alues)g(are)i +(reduced)g(to)f(the)g(smallest)f(common)g(denominator)-5 +b(.)28 b(F)o(or)22 b(e)o(xample,)g(if)h(all)f(CIF)h(v)n(alues)0 +1875 y(are)31 b(di)n(visible)d(by)h(100,)i(then)f(the)g(reducer)g(is)g +(set)g(to)f(100)h(and)g(all)g(output)e(v)n(alues)h(are)i(di)n(vided)e +(by)g(the)h(same)0 1995 y(f)o(actor)l(,)g(thus)e(reducing)g(the)h(size) +g(of)f(the)h(CIF)h(output)d(\002le.)43 b(No)n(w)28 b(the)h(reducer)g +(is)g(calculated)f(automatically)-6 b(,)0 2115 y(a)n(v)n(oiding)26 +b(an)o(y)g(problems)g(resulting)f(from)i(an)g(incorrectly)g +(speci\002ed)g(reducer)g(v)n(alue,)g(and)g(an)o(y)f(v)n(alue)h(found)0 +2236 y(after)j Fh(scale)g Fg(is)f(ignored.)46 b(The)29 +b Fd(calmaonly)h Fg(k)o(e)o(yw)o(ord)f(speci\002ed)h(that)f(the)h +Fh(scale)f Fg(w)o(as)h(an)g(odd)f(inte)o(ger)-5 b(.)45 +b(This)0 2356 y(limitation)20 b(has)i(been)h(remo)o(v)o(ed,)f(so)g(an)o +(y)f(such)i(k)o(e)o(yw)o(ord)e(is)h(ignored,)g(and)h(correct)g(output)e +(may)h(be)h(generated)0 2477 y(for)i(either)g(CIF)h(or)f(Calma)g(at)g +(all)f(output)g(scales.)146 2598 y(In)33 b(addition)e(to)h(specifying)g +(a)h(scale)g(f)o(actor)l(,)i(each)e(style)f(can)g(specify)h(the)f(size) +h(in)f(which)g(chunks)g(will)0 2718 y(be)26 b(processed)g(when)g +(generating)g(CIF)h(hierarchically)-6 b(.)33 b(This)26 +b(is)f(particularly)g(important)g(when)h(the)g(a)n(v)o(erage)0 +2838 y(design)c(size)g(is)g(much)g(lar)n(ger)h(than)f(the)g(maximum)e +(bloat)i(or)h(shrink)e(\(e.g,)i(more)f(than)g(3)h(orders)f(of)g +(magnitude)0 2959 y(dif)n(ference\).)31 b(The)25 b(step)f(size)h(is)g +(speci\002ed)g(by)f(a)h(line)g(of)g(the)f(follo)n(wing)f(form:)900 +3193 y Fd(stepsize)i Fh(stepsize)146 3426 y Fg(where)g +Fh(stepsize)e Fg(is)g(in)g(Magic)h(units.)29 b(F)o(or)24 +b(e)o(xample,)f(if)h(you)f(plan)h(to)f(generate)i(CIF)g(for)f(designs)f +(that)g(will)0 3547 y(typically)h(be)h(100,000)e(Magic)i(units)e(on)i +(a)g(side,)f(it)h(might)e(mak)o(e)i(sense)f(for)i Fh(stepsize)d +Fg(to)i(be)g(10000)f(or)h(more.)0 3847 y Ff(12.3)119 +b(Lay)o(er)29 b(descriptions)0 4036 y Fg(The)24 b(main)g(body)g(of)g +(information)f(for)i(each)g(CIF)g(style)f(is)g(a)h(set)f(of)g(layer)h +(descriptions.)k(Each)24 b(layer)h(descrip-)0 4156 y(tion)g(consists)f +(of)h(one)h(or)f(more)h Fh(oper)o(ations)d Fg(describing)i(ho)n(w)f(to) +h(generate)h(the)g(CIF)g(for)g(a)g(single)f(layer)-5 +b(.)32 b(The)0 4277 y(\002rst)25 b(line)f(of)h(each)h(description)d(is) +i(one)f(of)900 4511 y Fd(lay)o(er)h Fh(name)f Fg([)p +Fh(layer)o(s)p Fg(])0 4744 y(or)900 4952 y Fd(templay)o(er)h +Fh(name)g Fg([)p Fh(layer)o(s)p Fg(])146 5159 y(These)j(statements)e +(are)i(identical,)f(e)o(xcept)h(that)f(templayers)f(are)i(not)f(output) +g(in)g(the)g(CIF)h(\002le.)40 b(The)o(y)26 b(are)0 5280 +y(used)f(only)g(to)h(b)n(uild)e(up)i(intermediate)f(results)g(used)g +(in)h(generating)f(the)g(\223real\224)i(layers.)34 b(In)25 +b(each)i(case,)f Fh(name)0 5400 y Fg(is)k(the)h(CIF)h(name)f(to)f(be)h +(used)f(for)h(the)g(layer)-5 b(.)48 b(If)32 b Fh(layer)o(s)e +Fg(is)g(speci\002ed,)j(it)d(consists)f(of)i(a)g(comma-separated)1850 +5649 y(\22618\226)p eop end +%%Page: 19 19 +TeXDict begin 19 18 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)0 68 y(list)31 +b(of)i(Magic)f(layers)h(and)f(pre)n(viously-de\002ned)g(CIF)h(layers)g +(in)f(this)f(style;)36 b(these)c(layers)h(form)f(the)g(initial)0 +188 y(contents)d(of)g(the)h(ne)n(w)f(CIF)i(layer)e(\(note:)40 +b(the)30 b(layer)f(lists)g(in)g(this)f(section)h(are)i(less)e(general)h +(than)f(what)g(w)o(as)0 309 y(described)e(in)f(Section)h(8;)h(tildes)e +(and)h(parentheses)g(are)g(not)g(allo)n(wed\).)36 b(If)28 +b Fh(layer)o(s)e Fg(is)h(not)f(speci\002ed,)i(then)e(the)0 +429 y(ne)n(w)31 b(CIF)i(layer)f(is)f(initially)f(empty)-6 +b(.)50 b(The)31 b(follo)n(wing)f(statements)g(are)j(used)e(to)g(modify) +g(the)g(contents)g(of)h(a)0 549 y(CIF)26 b(layer)f(before)g(it)g(is)f +(output.)146 670 y(After)k(the)f Fd(lay)o(er)h Fg(or)f +Fd(templay)o(er)i Fg(statement)d(come)h(se)n(v)o(eral)g(statements)f +(specifying)h(geometrical)g(oper)n(-)0 790 y(ations)j(to)h(apply)f(in)g +(b)n(uilding)g(the)g(CIF)i(layer)-5 b(.)49 b(Each)31 +b(statement)f(tak)o(es)h(the)g(current)g(contents)f(of)h(the)g(layer)l +(,)0 911 y(applies)21 b(some)g(operation)g(to)h(it,)f(and)h(produces)f +(the)h(ne)n(w)f(contents)g(of)h(the)f(layer)-5 b(.)30 +b(The)21 b(last)h(geometrical)f(oper)n(-)0 1031 y(ation)e(for)g(the)h +(layer)f(determines)g(what)g(is)g(actually)g(output)f(in)i(the)f(CIF)h +(\002le.)30 b(The)19 b(most)f(common)h(geometrical)0 +1151 y(operations)24 b(are:)900 1371 y Fd(or)h Fh(layer)o(s)900 +1491 y Fd(and)h Fh(layer)o(s)900 1612 y Fd(and-not)g +Fh(layer)o(s)900 1732 y Fd(gr)n(o)o(w)f Fh(amount)900 +1852 y Fd(shrink)h Fh(amount)900 1973 y Fd(bloat-or)f +Fh(layer)o(s)f(layer)o(s2)h(amount)e(layer)o(s2)i(amount)e(.)15 +b(.)g(.)900 2093 y Fd(squar)n(es)26 b Fh(size)900 2214 +y Fd(squar)n(es)g Fh(bor)l(der)e(size)g(separ)o(ation)146 +2553 y Fg(Some)h(more)g(obscure)g(operations)f(are:)900 +2773 y Fd(gr)n(o)o(w-grid)h Fh(amount)900 2893 y Fd(bloat-max)g +Fh(layer)o(s)f(layer)o(s2)g(amount)g(layer)o(s2)g(amount)g(.)15 +b(.)g(.)900 3014 y Fd(bloat-min)25 b Fh(layer)o(s)f(layer)o(s2)h +(amount)e(layer)o(s2)i(amount)e(.)15 b(.)g(.)900 3134 +y Fd(bloat-all)24 b Fh(layer)o(s)h(layer)o(s2)900 3254 +y Fd(squar)n(es-grid)h Fh(bor)l(der)e(size)h(separ)o(ation)d(x)j(y)900 +3375 y Fd(slots)f Fh(bor)l(der)g(size)h(separ)o(ation)900 +3495 y Fd(slots)f Fh(bor)l(der)g(size)h(separ)o(ation)d(bor)l(der)p +2303 3495 30 4 v 36 w(long)900 3616 y Fd(slots)i Fh(bor)l(der)g(size)h +(separ)o(ation)d(bor)l(der)p 2303 3616 V 36 w(long)i(size)p +2691 3616 V 35 w(long)g(sep)p 3061 3616 V 36 w(long)g +Fg([)p Fh(of)n(fset)p Fg(]])900 3736 y Fd(b)o(box)h Fg([)p +Fd(top)p Fg(])146 3955 y(The)i(operation)f Fd(or)g Fg(tak)o(es)h(all)f +(the)g Fh(layer)o(s)g Fg(\(which)g(may)g(be)h(either)f(Magic)g(layers)h +(or)f(pre)n(viously-de\002ned)0 4076 y(CIF)g(layers\),)f(and)g(or')-5 +b(s)24 b(them)g(with)g(the)h(material)f(already)i(in)e(the)h(CIF)h +(layer)-5 b(.)30 b(The)25 b(operation)f Fd(and)i Fg(is)e(similar)0 +4196 y(to)31 b Fd(or)p Fg(,)j(e)o(xcept)e(that)f(it)h(and')-5 +b(s)31 b(the)h(layers)f(with)h(the)f(material)h(in)f(the)h(CIF)h(layer) +f(\(in)g(other)f(w)o(ords,)j(an)o(y)d(CIF)0 4317 y(material)22 +b(that)h(doesn')n(t)f(lie)g(under)h(material)f(in)h Fh(layer)o(s)f +Fg(is)g(remo)o(v)o(ed)f(from)i(the)f(CIF)i(layer\).)31 +b Fd(And-not)24 b Fg(\002nds)e(all)0 4437 y(areas)29 +b(co)o(v)o(ered)f(by)g Fh(layer)o(s)g Fg(and)g(erases)h(current)g(CIF)g +(material)f(from)g(those)g(areas.)42 b Fd(Gr)n(o)o(w)28 +b Fg(and)h Fd(shrink)g Fg(will)0 4557 y(uniformly)23 +b(gro)n(w)h(or)h(shrink)f(the)g(current)h(CIF)h(layer)f(by)g +Fh(amount)e Fg(units,)h(where)h Fh(amount)f Fg(is)g(speci\002ed)h(in)f +(CIF)0 4678 y(units,)h(not)h(Magic)g(units.)34 b(The)26 +b Fd(squar)n(es-grid)i Fg(operator)e(gro)n(ws)g(layers)g(non-uniformly) +f(to)g(snap)h(to)g(the)h(grid)0 4798 y(spacing)e(indicated)g(by)g +Fh(amount)p Fg(.)32 b(This)25 b(can)h(be)f(used)h(to)f(ensure)g(that)g +(features)h(f)o(all)g(on)f(a)h(required)f(minimum)0 4918 +y(grid.)146 5039 y(The)30 b(three)f(\223bloat\224)g(operations)f +Fd(bloat-or)p Fg(,)j Fd(bloat-min)p Fg(,)f(and)f Fd(bloat-max)p +Fg(,)h(pro)o(vide)e(selecti)n(v)o(e)g(forms)h(of)0 5159 +y(gro)n(wing.)g(In)24 b(these)g(statements,)f(all)h(the)g(layers)g +(must)f(be)h(Magic)g(layers.)31 b(Each)24 b(operation)f(e)o(xamines)g +(all)h(the)0 5280 y(tiles)31 b(in)g Fh(layer)o(s)p Fg(,)i(and)e(gro)n +(ws)g(the)h(tiles)f(by)g(a)h(dif)n(ferent)f(distance)g(on)h(each)g +(side,)h(depending)e(on)g(the)g(rest)h(of)0 5400 y(the)c(line.)39 +b(Each)28 b(pair)g Fh(layer)o(s2)f(amount)g Fg(speci\002es)h(some)f +(tile)g(types)g(and)h(a)g(distance)f(\(in)h(CIF)h(units\).)38 +b(Where)1850 5649 y(\22619\226)p eop end +%%Page: 20 20 +TeXDict begin 20 19 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)0 68 y(a)j(tile)f(of)g(type)h +Fh(layer)o(s)f Fg(ab)n(uts)g(a)h(tile)f(of)g(type)g Fh(layer)o(s2)p +Fg(,)h(the)f(\002rst)h(tile)f(is)g(gro)n(wn)f(on)i(that)f(side)g(by)g +Fh(amount)p Fg(.)35 b(The)0 189 y(result)25 b(is)g(or'ed)h(with)f(the)g +(current)h(contents)f(of)g(the)h(CIF)g(plane.)33 b(The)26 +b(layer)g(\223)p Fd(*)p Fg(\224)g(may)f(be)h(used)f(as)h +Fh(layer)o(s2)e Fg(to)0 309 y(indicate)f(all)h(tile)f(types.)30 +b(Where)25 b(tiles)e(only)g(ha)n(v)o(e)h(a)g(single)f(type)h(of)g +(neighbor)f(on)h(each)g(side,)g(all)f(three)i(forms)0 +429 y(of)i Fd(bloat)h Fg(are)f(identical.)38 b(Where)27 +b(the)h(neighbors)e(are)i(dif)n(ferent,)f(the)g(three)h(forms)e(are)i +(slightly)e(dif)n(ferent,)h(as)0 550 y(illustrated)e(in)h(Figure)g +(12.3.)34 b(Note:)f(all)26 b(the)g(layers)g(speci\002ed)h(in)f(an)o(y)f +(gi)n(v)o(en)g Fd(bloat)h Fg(operation)g(must)f(lie)h(on)g(a)0 +670 y(single)g(Magic)h(plane.)37 b(F)o(or)28 b Fd(bloat-or)f +Fg(all)g(distances)f(must)g(be)h(positi)n(v)o(e.)36 b(In)27 +b Fd(bloat-max)g Fg(and)g Fd(bloat-min)g Fg(the)0 790 +y(distances)d(may)h(be)g(ne)o(gati)n(v)o(e)d(to)i(pro)o(vide)g(a)h +(selecti)n(v)o(e)f(form)g(of)h(shrinking.)0 1863 y @beginspecial +68 @llx 68 @lly 856 @urx 261 @ury 4680 @rwi @setspecial +%%BeginDocument: ../psfigures/maint2.2.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.2.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:16:25 2000 +%%Pages: 1 +%%BoundingBox: 68 68 856 261 +%%DocumentNeededResources: font Helvetica +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/tiles { +% -304 -188 608 380 bbox +begingate +1 1.00 176 64 176 -96 2 polygon +1 1.00 -176 64 -176 -96 2 polygon +1 1.00 -16 64 -16 192 2 polygon +(A) {/Helvetica 1.000 cf} 2 21 0 -16 -16 label +(C) {/Helvetica 1.000 cf} 2 21 0 224 -16 label +(B) {/Helvetica 1.000 cf} 2 23 0 -240 -16 label +(D) {/Helvetica 1.000 cf} 2 29 0 -16 -160 label +1 1.00 -304 -96 304 -96 2 polygon +1 1.00 -304 64 304 64 2 polygon +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 992 398 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.745 0.600 0.871 scb +241 1.00 1744 606 1744 350 2240 350 2240 606 1744 606 5 polygon +241 1.00 1008 654 1008 350 1504 350 1504 654 1008 654 5 polygon +240 1.00 480 654 272 654 272 350 768 350 768 606 480 606 6 polygon +sce +1 1.00 480 654 272 654 272 350 768 350 768 606 480 606 6 polygon +1.00 0 496 494 tiles +1.00 0 1232 494 tiles +1.00 0 1968 494 tiles +1 1.00 1008 654 1008 350 1504 350 1504 654 1008 654 5 polygon +1 1.00 1744 606 1744 350 2240 350 2240 606 1744 606 5 polygon +(E) {/Helvetica 1.000 cf} 2 21 0 368 622 label +(B) {/Helvetica 1.000 cf} 2 25 0 624 622 label +(E) {/Helvetica 1.000 cf} 2 29 0 1104 638 label +(B) {/Helvetica 1.000 cf} 2 29 0 1376 638 label +(E) {/Helvetica 1.000 cf} 2 25 0 1840 622 label +(B) {/Helvetica 1.000 cf} 2 25 0 2080 622 label +(bloat-or A * 100 C,E 200) {/Helvetica 1.000 cf} 2 21 0 512 206 label +(bloat-max A * 100 C,E 200) {/Helvetica 1.000 cf} 2 21 0 1248 206 label +(bloat-min A * 100 C,E 200) {/Helvetica 1.000 cf} 2 21 0 2000 206 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 203 x(Figure)31 b(2:)41 b(The)30 b(three)h(dif)n(ferent)f +(forms)f(of)i Fd(bloat)f Fg(beha)n(v)o(e)g(slightly)e(dif)n(ferently)i +(when)g(tw)o(o)g(dif)n(ferent)g(bloat)0 2187 y(distances)f(apply)g +(along)f(the)i(same)f(side)g(of)g(a)h(tile.)44 b(In)29 +b(each)h(of)f(the)h(abo)o(v)o(e)e(e)o(xamples,)h(the)h(CIF)g(that)f(w)o +(ould)0 2307 y(be)i(generated)f(is)g(sho)n(wn)g(in)g(bold)f(outline.)47 +b(If)31 b Fd(bloat-or)f Fg(is)g(speci\002ed,)j(a)d(jagged)g(edge)h(may) +f(be)h(generated,)0 2428 y(as)25 b(on)g(the)g(left.)31 +b(If)26 b Fd(bloat-max)f Fg(is)f(used,)h(the)g(lar)n(gest)g(bloat)f +(distance)h(for)g(each)h(side)f(is)f(applied)h(uniformly)e(to)0 +2548 y(the)k(side,)g(as)g(in)g(the)f(center)-5 b(.)38 +b(If)27 b Fd(bloat-min)g Fg(is)g(used,)g(the)g(smallest)f(bloat)g +(distance)h(for)g(each)h(side)e(is)h(applied)0 2668 y(uniformly)c(to)i +(the)f(side,)h(as)g(on)f(the)h(right.)146 2992 y(In)39 +b(retrospect,)i(it')-5 b(s)37 b(not)h(clear)h(that)f +Fd(bloat-max)g Fg(and)g Fd(bloat-min)g Fg(are)h(v)o(ery)f(useful)g +(operations.)70 b(The)0 3113 y(problem)25 b(is)g(that)h(the)o(y)e +(operate)j(on)e(tiles,)g(not)g(re)o(gions.)33 b(This)25 +b(can)h(cause)g(une)o(xpected)f(beha)n(vior)h(on)f(conca)n(v)o(e)0 +3233 y(re)o(gions.)k(F)o(or)c(e)o(xample,)f(if)g(the)g(re)o(gion)g +(being)g(bloated)g(is)g(in)g(the)g(shape)h(of)f(a)h(\223T\224,)g(a)g +(single)e(bloat)h(f)o(actor)h(will)0 3354 y(be)j(applied)e(to)h(the)h +(underside)f(of)g(the)g(horizontal)g(bar)-5 b(.)38 b(If)28 +b(you)f(use)g Fd(bloat-max)h Fg(or)f Fd(bloat-min)p Fg(,)h(you)f +(should)0 3474 y(probably)d(specify)h(design-rules)f(that)g(require)h +(the)g(shapes)f(being)g(bloated)h(to)f(be)h(con)l(v)o(e)o(x.)146 +3594 y(The)36 b(fourth)f(bloat)g(operation)h Fd(bloat-all)f +Fg(tak)o(es)g(all)h(tiles)f(of)g(types)g Fh(layer)o(s)p +Fg(,)j(and)e(gro)n(ws)f(to)g(include)g(all)0 3715 y(neighboring)26 +b(tiles)g(of)h(types)g Fh(layer)o(s2)p Fg(.)37 b(This)27 +b(is)f(v)o(ery)h(useful)g(to)g(generate)g(mark)o(er)h(layers)f(or)g +(implant)f(layers)0 3835 y(for)d(speci\002c)h(de)n(vices,)e(where)i +(the)f(mark)o(er)g(or)g(implant)e(must)h(co)o(v)o(er)g(both)h(the)f(de) +n(vice)h(and)g(its)f(contacts.)30 b(T)-8 b(ak)o(e)0 3955 +y(the)25 b(material)f(of)h(the)g(de)n(vice)f(and)h(use)f +Fd(bloat-all)h Fg(to)f(e)o(xpand)g(into)g(the)h(contact)f(areas.)146 +4076 y(An)31 b(important)f(geometric)g(operation)h(for)g(creating)g +(contact)g(cuts)f(is)h Fd(squar)n(es)p Fg(.)50 b(It)31 +b(e)o(xamines)f(each)i(tile)0 4196 y(on)c(the)g(CIF)h(plane,)f(and)g +(replaces)h(that)e(tile)h(with)f(one)h(or)g(more)g(squares)g(of)g +(material.)40 b(Each)28 b(square)g(is)g Fh(size)0 4317 +y Fg(CIF)c(units)e(across,)h(and)f(squares)h(are)h(separated)f(by)f +Fh(separ)o(ation)f Fg(units.)29 b(A)22 b(border)h(of)g(at)g(least)g +Fh(bor)l(der)f Fg(units)g(is)0 4437 y(left)i(around)f(the)g(edge)h(of)g +(the)g(original)e(tile,)i(if)f(possible.)29 b(This)23 +b(operation)g(is)g(used)h(to)f(generate)h(contact)g(vias,)0 +4557 y(as)31 b(in)g(Figure)g(3.)49 b(If)32 b(only)e(one)h(ar)n(gument)f +(is)h(gi)n(v)o(en)e(in)i(the)g Fd(squar)n(es)h Fg(statement,)f(then)g +Fh(separ)o(ation)e Fg(def)o(aults)0 4678 y(to)34 b Fh(size)f +Fg(and)h Fh(bor)l(der)g Fg(def)o(aults)f(to)h Fh(size)p +Fg(/2.)57 b(If)34 b(a)h(tile)e(doesn')n(t)h(hold)f(an)h(inte)o(gral)f +(number)g(of)h(squares,)i(e)o(xtra)0 4798 y(space)c(is)e(left)i(around) +f(the)g(edges)g(of)g(the)g(tile)g(and)g(the)g(squares)g(are)h(centered) +g(in)f(the)g(tile.)49 b(If)32 b(the)f(tile)g(is)f(so)0 +4918 y(small)22 b(that)i(not)e(e)n(v)o(en)h(a)h(single)f(square)g(can)h +(\002t)g(and)f(still)g(lea)n(v)o(e)g(enough)g(border)l(,)h(then)f(the)g +(border)h(is)f(reduced.)0 5039 y(If)31 b(a)f(square)h(w)o(on')n(t)f +(\002t)g(in)g(the)h(tile,)g(e)n(v)o(en)e(with)h(no)g(border)l(,)h(then) +f(no)h(material)e(is)h(generated.)48 b(The)30 b Fd(squar)n(es)0 +5159 y Fg(operation)23 b(must)g(be)h(used)g(with)f(some)g(care,)i(in)f +(conjunction)f(with)g(the)g(design)h(rules.)30 b(F)o(or)24 +b(e)o(xample,)f(if)h(there)0 5280 y(are)j(se)n(v)o(eral)e(adjacent)g +(skinn)o(y)g(tiles,)g(there)h(may)f(not)h(be)f(enough)h(room)f(in)g(an) +o(y)h(of)f(the)h(tiles)f(for)h(a)g(square,)g(so)0 5400 +y(no)21 b(material)f(will)g(be)h(generated)h(at)f(all.)29 +b(Whene)n(v)o(er)20 b(you)h(use)f(the)h Fd(squar)n(es)h +Fg(operator)l(,)g(you)e(should)g(use)h(design)1850 5649 +y(\22620\226)p eop end +%%Page: 21 21 +TeXDict begin 21 20 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)0 68 y(rules)j(to)g(prohibit)f +(adjacent)h(contact)g(tiles,)h(and)f(you)g(should)f(al)o(w)o(ays)h(use) +g(the)g Fd(no)p 2938 68 30 4 v 37 w(o)o(v)o(erlap)g Fg(rule)g(to)g(pre) +n(v)o(ent)0 188 y(unpleasant)k(hierarchical)h(interactions.)53 +b(The)32 b(problems)g(with)g(hierarchy)g(are)h(discussed)f(in)g +(Section)h(12.6)0 309 y(belo)n(w)-6 b(,)23 b(and)i(design)f(rules)h +(are)g(discussed)f(in)g(Section)h(15.)1306 1465 y @beginspecial +68 @llx 68 @lly 304 @urx 253 @ury 1544 @rwi @setspecial +%%BeginDocument: ../psfigures/maint2.3.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.3.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:18:51 2000 +%%Pages: 1 +%%BoundingBox: 68 68 304 253 +%%DocumentNeededResources: font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 800 460 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.753 0.333 0.502 scb +240 1.00 224 300 224 556 608 556 608 300 4 polygon +sce +0 1.00 224 300 224 556 608 556 608 300 4 polygon +240 1.00 256 332 256 396 320 396 320 332 4 polygon +240 1.00 256 460 256 524 320 524 320 460 4 polygon +240 1.00 384 332 384 396 448 396 448 332 4 polygon +240 1.00 384 460 384 524 448 524 448 460 4 polygon +240 1.00 512 332 512 396 576 396 576 332 4 polygon +240 1.00 512 460 512 524 576 524 576 460 4 polygon +1 1.00 320 572 320 620 2 polygon +1 1.00 384 572 384 620 2 polygon +1 1.00 624 332 672 332 2 polygon +1 1.00 624 300 672 300 2 polygon +1 1.00 256 316 256 236 2 polygon +1 1.00 320 316 320 236 2 polygon +1 1.00 256 604 304 604 2 polygon +1 1.00 400 604 448 604 2 polygon +1 1.00 656 348 656 396 2 polygon +1 1.00 656 284 656 220 2 polygon +1 1.00 336 252 384 252 2 polygon +1 1.00 240 252 192 252 2 polygon +1.00 0 336 252 arrowhead90 +1.00 0 400 604 arrowhead90 +1.00 -1 304 604 arrowhead90 +1.00 -1 240 252 arrowhead90 +1.00 -91 656 348 arrowhead90 +1.00 270 656 284 arrowhead90 +(separation) {/Helvetica-Oblique 1.000 cf} 2 25 0 352 636 label +(size) {/Helvetica-Oblique 1.000 cf} 2 29 0 288 220 label +(border) {/Helvetica-Oblique 1.000 cf} 2 20 0 688 316 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 1669 a(Figure)g(3:)32 b(The)25 b Fd(squar)n(es)h +Fg(operator)f(chops)g(each)g(tile)g(up)g(into)f(squares,)h(as)h +(determined)e(by)h(the)g Fh(bor)l(der)p Fg(,)g Fh(size)p +Fg(,)0 1789 y(and)c Fh(separ)o(ation)f Fg(parameters.)29 +b(In)22 b(the)f(e)o(xample,)g(the)h(bold)e(lines)h(sho)n(w)g(the)g(CIF) +h(that)f(w)o(ould)g(be)h(generated)f(by)0 1909 y(a)29 +b Fd(squar)n(es)g Fg(operation.)40 b(The)28 b(squares)g(of)g(material)g +(are)h(al)o(w)o(ays)f(centered)h(so)f(that)f(the)h(borders)g(on)g +(opposite)0 2030 y(sides)c(are)i(the)e(same.)146 2364 +y(The)38 b Fd(squar)n(es-grid)i Fg(operator)e(is)f(similar)g(to)h +Fd(squar)n(es)h Fg(and)f(tak)o(es)g(the)g(same)g(ar)n(guments,)i(e)o +(xcept)e(for)0 2484 y(the)33 b(additional)f(optional)h +Fh(x)g Fg(and)h Fh(y)g Fg(of)n(fsets)e(\(which)i(def)o(ault)f(to)g +(1\).)57 b(Where)34 b(the)f Fd(squar)n(es)i Fg(operator)e(places)0 +2604 y(contacts)24 b(on)g(the)g(half-lambda)f(grid,)h(the)g +Fd(squar)n(es-grid)i Fg(operator)e(places)g(contacts)g(on)g(an)g(inte)o +(ger)g(grid)f(of)i Fh(x)0 2725 y Fg(and)g Fh(y)p Fg(.)33 +b(This)25 b(is)g(helpful)g(where)h(manuf)o(acturing)e(grid)i +(limitations)c(do)k(not)e(allo)n(w)h(half-lambda)g(coordinates.)0 +2845 y(Ho)n(we)n(v)o(er)l(,)34 b(it)g(is)f(necessary)h(then)f(to)g +(enforce)h(a)g(\223no-o)o(v)o(erlap\224)f(rule)h(for)f(contacts)g(in)h +(the)f(DRC)i(section)d(to)0 2966 y(pre)n(v)o(ent)f(incorrect)h +(contacts)g(cuts)g(from)g(being)f(generated)i(in)f(o)o(v)o(erlapping)e +(subcells.)52 b(The)32 b Fd(squar)n(es-grid)0 3086 y +Fg(operator)22 b(can)h(also)e(be)i(used)f(with)f Fh(x)h +Fg(and)g Fh(y)h Fg(v)n(alues)e(to)h(generate)h(\002ll)f(geometry)-6 +b(,)21 b(or)h(to)g(generate)h(of)n(fset)e(contact)0 3206 +y(cut)k(arrays)g(for)g(pad)g(vias.)146 3329 y(The)h Fd(slots)e +Fg(operator)h(is)g(similar)f(to)h Fd(squar)n(es)h Fg(operator)l(,)f(b)n +(ut)g(as)g(the)g(name)h(implies,)d(the)i(resulting)f(shapes)0 +3449 y(generated)i(are)g(rectangular)l(,)g(not)e(\(necessarily\))i +(square.)33 b(Slots)24 b(are)j(generated)e(inside)g(indi)n(vidual)e +(tiles,)i(lik)o(e)0 3570 y(the)32 b(squares)h(operator)l(,)h(so)e(each) +h(slots)f(operation)g(is)g(separately)g(oriented)g(relati)n(v)o(e)g(to) +g(the)g(tile')-5 b(s)31 b(long)h(and)0 3690 y(short)f(edges.)50 +b(Separate)33 b(border)l(,)g(size,)g(and)e(separation)g(v)n(alues)g +(can)h(be)f(speci\002ed)h(for)f(the)h(short)e(and)i(long)0 +3811 y(dimensions)23 b(of)i(the)f(tile.)30 b(This)24 +b(operator)h(can)h(be)e(used)h(in)f(a)i(number)e(of)h(situations:)120 +4056 y(1.)49 b(Generate)25 b(square)g(contact)g(cuts)g(with)f(dif)n +(ferent)g(border)h(requirements)f(on)h(the)g(short)f(and)h(long)f +(sides,)244 4176 y(as)h(required)g(for)g(a)g(number)f(of)h(deep)g +(submicron)f(processes)g(lik)o(e)h(90)f(nanometer)-5 +b(.)120 4392 y(2.)49 b(Automatically)22 b(generate)i(slots)f(in)g(lar)n +(ge)h(metal)f(areas,)i(which)e(most)g(processes)h(require.)30 +b(Note,)24 b(ho)n(w-)244 4512 y(e)n(v)o(er)l(,)e(that)g(it)g(is)g +(impossible)e(to)i(correctly)h(generate)g(all)f(slots,)f(so)h(this)g +(cannot)g(completely)f(replace)i(the)244 4633 y(widespacing)h(DRC)i +(rule.)120 4848 y(3.)49 b(Generate)25 b(slot)f(contacts.)120 +5064 y(4.)49 b(Generate)25 b(\002ll)g(geometry)-6 b(.)120 +5280 y(5.)49 b(Generate)32 b(mark)o(er)f(layers)g(for)g(resitors)g +(that)f(ab)n(ut)h(the)g(position)e(of)i(contacts,)h(a)g +(generally-accepted)244 5400 y(w)o(ay)25 b(to)f(de\002ne)i(a)f +(resistor)f(area)i(boundary)-6 b(.)1850 5649 y(\22621\226)p +eop end +%%Page: 22 22 +TeXDict begin 22 21 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)146 68 y(Note)37 +b(that)f(the)g Fd(slots)g Fg(operator)g(comes)g(in)h(three)f(dif)n +(ferent)g(forms)g(with)g(dif)n(ferent)g(numbers)g(of)h(ar)n(gu-)0 +188 y(ments.)44 b(W)l(ith)29 b(only)g(three)h(ar)n(guments)f(\(short)g +(side)g(description)g(only\),)h(the)f Fd(slots)g Fg(operator)h(creates) +g(stripes)0 309 y(that)c(e)o(xtend)g(to)g(the)h(edge)g(of)f(the)h +(tile.)35 b(W)l(ith)26 b(four)h(ar)n(guments)f(\(short)g(side)h +(description)e(plus)h(long)g(side)g(bor)n(-)0 429 y(der)33 +b(dimension)d(only\),)j(the)g Fd(slots)e Fg(operator)h(create)i +(stripes)d(that)h(e)o(xtend)f(to)h(the)g(edge)h(of)f(the)g(tile,)h +(with)f(an)0 549 y(appropriate)f(border)g(spacing)f(at)h(each)g(end.)49 +b(In)31 b(these)g(tw)o(o)f(cases,)j(the)e(slots)e(ha)n(v)o(e)i(v)n +(ariable)f(length)g(that)h(is)0 670 y(set)e(by)f(the)h(size)g(of)g(the) +g(tile.)43 b(In)29 b(the)g(\002nal)g(form,)h(all)e(short)h(and)g(long)f +(side)h(dimensions)e(are)i(declared.)44 b(The)0 790 y(generated)29 +b(slots)e(are)i(of)f(\002x)o(ed)g(size,)h(and)f(lik)o(e)g(the)g +Fd(squar)n(es)h Fg(operator)l(,)g(their)f(positions)e(will)i(be)g +(adjusted)f(to)0 911 y(center)i(them)e(on)i(the)f(tile.)40 +b(The)29 b Fh(of)n(fset)e Fg(is)h(intended)g(to)g(let)g(each)g(ro)n(w)g +(of)h(slots)e(be)h(of)n(fset)g(from)g(the)g(pre)n(vious)0 +1031 y(one)d(by)f(a)h(\002x)o(ed)g(amount,)f(b)n(ut)g(is)g(currently)h +(unimplemented)e(and)h(has)h(no)g(ef)n(fect.)780 2112 +y @beginspecial 68 @llx 68 @lly 523 @urx 247 @ury 2808 +@rwi @setspecial +%%BeginDocument: ../psfigures/maint2.3b.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.3b +%%Creator: XCircuit v3.6 rev4 +%%CreationDate: Mon Feb 13 12:33:32 2006 +%%Pages: 1 +%%BoundingBox: 68 68 523 247 +%%DocumentNeededResources: font Helvetica font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 3.3 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--7/13/05 (tim.edwards@multigig.com) +% The Johns Hopkins University (1993-2004) +% MultiGiG, Inc. (2004-present) +% +%%BeginResource: procset XCIRCproc 3.3 0 +% +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/ul { dup type /stringtype eq showflag 1 eq and { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave currentpoint newpath moveto true charpath flattenpath + pathbbox pop exch pop sub grestore } def +/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs + 0 currentpoint pop put} def +/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def +/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt + {currentpoint exch pop moveto exit} {pop} ifelse } for } def +/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt + {currentpoint exch pop moveto exit} {pop} ifelse } for } def +/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def +/hS { qS qS } def +/pspc 0 def +/cf0 { scalefont setfont } bind def +/Kn { dup kY add /kY exch def rmoveto } bind def +/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul + 0.33 mul neg Kn} def +/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul + 0.67 mul Kn } def +/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def +/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def +/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq + { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def} + {fscale0 mul fscale mul cf0} ifelse } def +/ctmk { counttomark dup 2 add -1 roll pop } bind def +/label { gsave translate 0 0 moveto dup scale neg /rotval exch def + /just exch def just 384 and 0 gt {/mshow {pop} def} {/mshow {show} + def} ifelse just 16 and 0 gt {gsave rotval rotate 0 1 dtransform + gsave pagemat setmatrix idtransform exch grestore 1 0 dtransform + gsave pagemat setmatrix idtransform exch grestore dup abs 1e-9 lt + {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse grestore {-1 /rotval + rotval neg def /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse + exch -1e-9 lt {-1 /rotval rotval neg def /just just dup 12 and + 4 ne {12 xor} if def} {1} ifelse scale } if /showflag 0 def + /fspc pspc def /Bline 0 def /Tabs 0 array def /fscale 1.0 def + /kY 0 def gsave dup 1 add copy 0 exch 1 0 dtransform exch atan rotate + {exch dup type /stringtype eq {true charpath flattenpath} {dup type + /arraytype eq {exec} {12 string cvs true charpath flattenpath} ifelse} + ifelse} repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll just + 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub 0.5 + mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch just 4 + and 0 gt {just 8 and 0 gt {exch pop neg fspc sub} {add 0.5 mul neg} + ifelse} {pop neg fspc add} ifelse rotval rotate Kn currentpoint + translate /showflag 1 def /Bline 0 def /Tabs 0 array def /fscale + 1.0 def /kY 0 def {dup type /stringtype eq {mshow} {dup type + /arraytype eq {exec} {12 string cvs mshow} ifelse} ifelse} repeat + grestore } def +/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 10 def label + /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def +/graphic { gsave 4 index cvx exec /DataSource get resetfile translate + 0 0 moveto neg rotate dup scale cvx exec image grestore } def + +/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def +/cRedef {/defColor currentcolor 3 array astore def} def +/begingate {dup type /dicttype ne {1 dict} if begin % default params + dup type /dicttype ne {1 dict} if begin % instanced params + /hlevel hlevel 1 add def /defColor currentcolor sce 3 array + astore def gsave sce translate 0 0 moveto neg rotate dup abs scale + } bind def +/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef + scb end end} bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + gsave style 16 and 0 gt { style 224 and -5 bitshift style 256 and 0 gt { + 7 exch sub 8 div dup 1 exch sub currentrgbcolor 3 array astore + {3 copy mul add 4 1 roll pop} forall pop pop setrgbcolor eofill} + {dup 7 lt {gar exch get ppaint} {pop eofill} ifelse} ifelse} + {style 256 and 0 gt {1 setgray eofill} if} ifelse grestore style 8 and 0 gt + style 512 eq or {newpath} {stroke} ifelse grestore} def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def +/psinsertion {/PSobj save def /showpage {} def /setpagedevice {pop} def bop + rotate translate dup scale} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +%%BeginSetup + +/arrowhead { +% trivial +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +begingate +1.00 270 -16 0 arrowhead +endgate +} def + +/arrow { +% trivial +begingate +1 0.80 0 -40 0 20 2 polygon +1.00 0 0 40 arrowhead +endgate +} def + + +%%EndSetup + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +1.0000 inchscale +2.6000 setlinewidth 1058 -16 translate + +0.753 0.333 0.502 scb +240 1.00 -576 272 -576 528 48 528 48 272 4 polygon +sce +1 1.00 -288 512 -288 592 2 polygon +1 1.00 -240 512 -240 592 2 polygon +1 1.00 -352 576 -304 576 2 polygon +1 1.00 -224 576 -176 576 2 polygon +-1.00 0 -304 576 arrowhead90 +(sep_long) {/Helvetica-Oblique cf} 2 25 0 1.00 -256 608 label +0 1.00 -576 272 -576 528 48 528 48 272 4 polygon +240 1.00 -496 432 -496 496 -288 496 -288 432 4 polygon +240 1.00 -496 304 -496 368 -32 368 -32 304 4 polygon +240 1.00 -240 432 -240 496 -32 496 -32 432 4 polygon +(given) {CR} (separation) {CR} (no size or) {/Helvetica cf} 6 20 0 1.00 144 272 +label +1.00 0 -224 576 arrowhead90 +1 1.00 -496 544 -496 624 2 polygon +1 1.00 -576 544 -576 624 2 polygon +1 1.00 -480 608 -432 608 2 polygon +1.00 0 -480 608 arrowhead90 +1 1.00 -592 528 -736 528 2 polygon +1 1.00 -592 496 -736 496 2 polygon +1 1.00 -16 496 96 496 2 polygon +1 1.00 -16 432 96 432 2 polygon +1 1.00 -32 416 -32 224 2 polygon +1 1.00 -240 416 -240 224 2 polygon +1 1.00 -16 240 32 240 2 polygon +1.00 0 -16 240 arrowhead90 +1 1.00 -256 240 -304 240 2 polygon +-1.00 0 -256 240 arrowhead90 +(size_long) {/Helvetica-Oblique cf} 2 29 0 1.00 -144 240 label +1 1.00 -640 608 -592 608 2 polygon +-1.00 0 -592 608 arrowhead90 +(border_long) {/Helvetica-Oblique cf} 2 25 0 1.00 -544 640 label +(border) {/Helvetica-Oblique cf} 2 23 0 1.00 -752 512 label +1 1.00 -704 544 -704 592 2 polygon +-1.00 90 -704 544 arrowhead90 +1 1.00 -704 480 -704 432 2 polygon +1.00 90 -704 480 arrowhead90 +1 1.00 80 512 80 560 2 polygon +-1.00 90 80 512 arrowhead90 +1 1.00 80 416 80 352 2 polygon +1.00 90 80 416 arrowhead90 +-1.00 300 96 288 arrow +(size) {/Helvetica-Oblique cf} 2 20 0 1.00 96 464 label +1 1.00 -592 432 -640 432 2 polygon +1 1.00 -592 368 -640 368 2 polygon +1 1.00 -624 448 -624 480 2 polygon +-1.00 90 -624 448 arrowhead90 +1 1.00 -624 352 -624 320 2 polygon +1.00 90 -624 352 arrowhead90 +(sep) {/Helvetica-Oblique cf} 2 23 0 1.00 -608 400 label +1.000 1.000 1.000 scb +1 1.00 -240 304 -240 368 2 polygon +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 703 2315 a(Figure)g(4:)31 b(The)25 b Fd(slots)f +Fg(operator)g(chops)h(each)g(tile)f(up)h(into)f(rectangles.)146 +2682 y(The)h Fd(b)o(box)g Fg(operator)f(generates)h(a)g(single)e +(rectangle)i(that)f(encompasses)f(the)i(bounding)e(box)g(of)i(the)f +(cell.)0 2803 y(This)j(is)g(useful)g(for)g(the)g(occasional)g(process)h +(that)f(requires)g(mark)o(er)h(or)f(implant)f(layers)i(co)o(v)o(ering)e +(an)h(entire)0 2923 y(design.)i(The)23 b(v)n(ariant)f +Fd(b)o(box)h(top)h Fg(will)e(generate)h(a)g(rectangle)g(encompassing)e +(the)i(bounding)e(box)i(of)g(the)f(cell,)0 3043 y(b)n(ut)i(will)g(only) +g(do)h(so)f(for)h(the)g(top-le)n(v)o(el)e(cell)i(of)g(the)f(design.)0 +3375 y Ff(12.4)119 b(Labels)0 3574 y Fg(There)25 b(is)g(an)g +(additional)e(statement)h(permitted)f(in)i(the)g Fd(cif)n(output)g +Fg(section)g(as)f(part)h(of)g(a)g(layer)g(description:)900 +3847 y Fd(labels)f Fh(Ma)o(giclayer)o(s)146 4115 y Fg(This)c(statement) +g(tells)g(Magic)g(that)h(labels)f(attached)h(to)f(Magic)g(layers)h +Fh(Ma)o(giclayer)o(s)f Fg(are)h(to)g(be)g(associated)0 +4235 y(with)32 b(the)g(current)g(CIF)i(layer)-5 b(.)53 +b(Each)32 b(Magic)g(layer)h(should)e(only)h(appear)g(in)g(one)h(such)f +(statement)f(for)i(an)o(y)0 4356 y(gi)n(v)o(en)25 b(CIF)j(style.)36 +b(If)27 b(a)g(Magic)f(layer)h(doesn')n(t)g(appear)g(in)f(an)o(y)g +Fd(labels)h Fg(statement,)f(then)g(it)g(is)h(not)f(attached)g(to)0 +4476 y(a)f(speci\002c)g(layer)g(when)g(output)f(in)g(CIF)-8 +b(.)0 4807 y Ff(12.5)119 b(Calma)29 b(\(GDS)i(II)e(Str)n(eam)g(f)m +(ormat\))g(lay)o(ers)0 5006 y Fg(Each)c(layer)g(description)f(in)g(the) +h Fd(cif)n(output)h Fg(section)e(may)g(also)h(contain)f(one)h(of)g(the) +f(follo)n(wing)f(statements:)900 5280 y Fd(gds)i Fh(gdsNumber)f(gdsT)-7 +b(ype)900 5400 y Fd(calma)24 b Fh(gdsNumber)h(gdsT)-7 +b(ype)1850 5649 y Fg(\22622\226)p eop end +%%Page: 23 23 +TeXDict begin 23 22 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)146 68 y(Although)36 +b(the)h(format)g(is)f(rarely)i(referred)h(to)d(as)i(\223Calma\224)f(an) +o(ymore,)j(the)d(k)o(e)o(yw)o(ord)f(is)h(retained)g(for)0 +188 y(backw)o(ards)25 b(compatibility)d(with)i(format)h(27)f(\(and)h +(earlier\))h(\002les.)146 309 y(This)k(statement)g(tells)g(Magic)g +(which)g(layer)h(number)f(and)h(data)f(type)h(to)f(use)g(when)h(the)f +Fd(gds)h Fg(command)0 429 y(outputs)g(GDS)i(II)g(Stream)g(format)f(for) +h(this)f(de\002ned)h(CIF)g(layer)-5 b(.)54 b(Both)32 +b Fh(gdsNumber)g Fg(and)h Fh(gdsT)-7 b(ype)32 b Fg(should)0 +549 y(be)i(positi)n(v)o(e)e(inte)o(gers,)k(between)e(0)g(and)g(63.)59 +b(Each)34 b(CIF)i(layer)e(should)f(ha)n(v)o(e)h(a)g(dif)n(ferent)g +Fh(gdsNumber)p Fg(.)59 b(If)0 670 y(there)33 b(is)g(no)f +Fd(gds)h Fg(line)g(for)g(a)g(gi)n(v)o(en)f(CIF)i(layer)l(,)h(then)d +(that)h(layer)g(will)f(not)g(be)h(output)f(by)h(the)f(\223)p +Fd(gds)h(write)p Fg(\224)0 790 y(command.)55 b(The)34 +b(re)n(v)o(erse)f(is)g(not)f(true:)48 b(e)n(v)o(ery)33 +b(generated)g(output)f(layer)i(must)e(ha)n(v)o(e)h(a)h(de\002ned)f(CIF) +i(layer)0 911 y(type,)24 b(e)n(v)o(en)f(if)i(the)f(foundry)f(only)h +(supports)f(GDS)i(format.)30 b(In)24 b(such)g(case,)h(the)f(CIF)h +(layer)g(name)f(may)g(violate)0 1031 y(the)36 b(restricti)n(v)o(e)e +(4-character)j(format)e(required)h(by)f(the)h(CIF)g(syntax)f +(speci\002cation,)j(and)e(may)f(be)h(used)f(to)0 1151 +y(pro)o(vide)24 b(a)h(reasonable,)g(human-readable)f(descripti)n(v)o(e) +f(name)i(of)g(the)g(GDS)g(layer)-5 b(.)292 2457 y @beginspecial +68 @llx 68 @lly 712 @urx 297 @ury 3978 @rwi @setspecial +%%BeginDocument: ../psfigures/maint2.4.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.4.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:22:46 2000 +%%Pages: 1 +%%BoundingBox: 68 68 712 297 +%%DocumentNeededResources: font Helvetica +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 1056 334 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.490 0.651 0.980 scb +240 1.00 800 270 800 718 1312 718 1312 270 4 polygon +240 1.00 1504 334 1504 654 1888 654 1888 334 4 polygon +240 1.00 192 334 192 654 320 654 320 334 4 polygon +240 1.00 448 334 448 654 576 654 576 334 4 polygon +sce +0 1.00 192 334 192 654 320 654 320 334 4 polygon +0 1.00 448 334 448 654 576 654 576 334 4 polygon +0 1.00 1504 334 1504 654 1888 654 1888 334 4 polygon +0 1.00 800 270 800 718 1312 718 1312 270 4 polygon +2 1.00 864 334 864 654 992 654 992 334 4 polygon +2 1.00 1120 334 1120 654 1248 654 1248 334 4 polygon +2 1.00 1504 334 1504 654 1632 654 1632 334 4 polygon +2 1.00 1760 334 1760 654 1888 654 1888 334 4 polygon +1 1.00 784 654 704 654 2 polygon +1 1.00 784 718 704 718 2 polygon +1 1.00 736 638 736 590 2 polygon +1 1.00 736 734 736 782 2 polygon +1.00 0 736 654 arrowhead +1.00 -181 736 718 arrowhead +(100) {/Helvetica 1.000 cf} 2 21 0 736 686 label +(\(a\)) {/Helvetica 1.000 cf} 2 21 0 352 206 label +(\(b\)) {/Helvetica 1.000 cf} 2 21 0 1056 206 label +(\(c\)) {/Helvetica 1.000 cf} 2 21 0 1696 206 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 2660 a(Figure)27 b(5:)34 b(If)27 b(the)g(operator)g +Fd(gr)n(o)o(w)g(100)f Fg(is)g(applied)g(to)g(the)h(shapes)f(in)h +(\(a\),)h(the)e(mer)n(ged)h(shape)g(in)f(\(b\))h(results.)0 +2781 y(If)j(the)f(operator)g Fd(shrink)h(100)f Fg(is)g(applied)f(to)h +(\(b\),)h(the)f(result)g(is)g(\(c\).)44 b(Ho)n(we)n(v)o(er)l(,)29 +b(if)g(the)g(tw)o(o)g(original)f(shapes)0 2901 y(in)j(\(a\))i(belong)e +(to)g(dif)n(ferent)h(cells,)h(and)e(if)h(CIF)h(is)e(generated)h +(separately)g(in)g(each)g(cell,)h(the)f(result)f(will)g(be)0 +3022 y(the)h(same)h(as)f(in)g(\(a\).)55 b(Magic)32 b(handles)g(this)g +(by)g(outputting)e(additional)h(information)h(in)g(the)g(parent)h(of)f +(the)0 3142 y(subcells)24 b(to)g(\002ll)h(in)f(the)h(gap)f(between)h +(the)g(shapes.)0 3647 y Ff(12.6)119 b(Hierar)n(ch)n(y)0 +3835 y Fg(Hierarchical)23 b(designs)f(mak)o(e)g(life)h(especially)f +(dif)n(\002cult)g(for)h(the)g(CIF)g(generator)-5 b(.)30 +b(The)23 b(CIF)h(corresponding)d(to)0 3955 y(a)28 b(collection)e(of)h +(subcells)g(may)g(not)g(necessarily)g(be)g(the)g(same)g(as)h(the)f(sum) +f(of)i(the)f(CIF')-5 b(s)28 b(of)f(the)g(indi)n(vidual)0 +4076 y(cells.)53 b(F)o(or)32 b(e)o(xample,)h(if)g(a)f(layer)h(is)f +(generated)g(by)g(gro)n(wing)f(and)i(then)f(shrinking,)g(nearby)h +(features)f(from)0 4196 y(dif)n(ferent)38 b(cells)h(may)f(mer)n(ge)h +(together)f(so)h(that)f(the)o(y)g(don')n(t)g(shrink)g(back)h(to)f +(their)g(original)g(shapes)h(\(see)0 4317 y(Figure)28 +b(5\).)38 b(If)28 b(Magic)f(generates)h(CIF)h(separately)e(for)h(each)g +(cell,)g(the)f(interactions)f(between)i(cells)f(will)g(not)0 +4437 y(be)h(re\003ected)g(properly)-6 b(.)38 b(The)27 +b(CIF)i(generator)e(attempts)f(to)i(a)n(v)n(oid)e(these)i(problems.)37 +b(Although)26 b(it)h(generates)0 4557 y(CIF)35 b(in)e(a)g(hierarchical) +h(representation)f(that)g(matches)g(the)g(Magic)g(cell)h(structure,)h +(it)e(tries)g(to)g(ensure)h(that)0 4678 y(the)g(resulting)e(CIF)j +(patterns)f(are)g(e)o(xactly)f(the)h(same)g(as)f(if)h(the)g(entire)g +(Magic)f(design)g(had)h(been)g(\003attened)0 4798 y(into)29 +b(a)i(single)e(cell)h(and)h(then)f(CIF)h(were)g(generated)f(from)g(the) +g(\003attened)h(design.)46 b(It)30 b(does)g(this)g(by)g(looking)0 +4918 y(in)c(each)g(cell)g(for)g(places)g(where)h(subcells)e(are)i +(close)e(enough)h(to)f(interact)h(with)f(each)i(other)f(or)g(with)f +(paint)g(in)0 5039 y(the)j(parent.)41 b(Where)29 b(this)f(happens,)g +(Magic)g(\003attens)g(the)h(interaction)e(area)i(and)g(generates)f(CIF) +i(for)e(it;)h(then)0 5159 y(Magic)24 b(\003attens)g(each)h(of)f(the)g +(subcells)f(separately)h(and)g(generates)h(CIF)g(for)g(them.)k(Finally) +-6 b(,)24 b(it)f(compares)h(the)0 5280 y(CIF)29 b(from)f(the)g +(subcells)g(with)f(the)h(CIF)h(from)f(the)g(\003attened)h(parent.)41 +b(Where)28 b(there)h(is)f(a)g(dif)n(ference,)h(Magic)0 +5400 y(outputs)23 b(e)o(xtra)i(CIF)h(in)e(the)h(parent)g(to)f +(compensate.)1850 5649 y(\22623\226)p eop end +%%Page: 24 24 +TeXDict begin 24 23 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)146 68 y(Magic')-5 +b(s)25 b(hierarchical)g(approach)h(only)e(w)o(orks)h(if)g(the)g(o)o(v)o +(erall)f(CIF)i(for)g(the)f(parent)g(ends)g(up)g(co)o(v)o(ering)f(at)0 +188 y(least)h(as)h(much)f(area)h(as)g(the)f(CIFs)i(for)e(the)h(indi)n +(vidual)d(components,)h(so)h(all)h(compensation)e(can)h(be)h(done)f(by) +0 309 y(adding)k(e)o(xtra)h(CIF)h(to)e(the)h(parent.)46 +b(In)30 b(mathematical)f(terms,)h(this)f(requires)h(each)h(geometric)e +(operation)g(to)0 429 y(obe)o(y)24 b(the)h(rule)900 676 +y(Op\(A)g Fe([)g Fg(B\))h Fe(\023)f Fg(Op\(A\))g Fe([)g +Fg(Op\(B\))146 920 y(The)c(operations)g Fd(and)p Fg(,)h +Fd(or)p Fg(,)g Fd(gr)n(o)o(w)p Fg(,)g(and)f Fd(shrink)h +Fg(all)e(obe)o(y)h(this)f(rule.)29 b(Unfortunately)-6 +b(,)20 b(the)h Fd(and-not)p Fg(,)i Fd(bloat)p Fg(,)0 +1041 y(and)f Fd(squar)n(es)g Fg(operations)f(do)h(not.)29 +b(F)o(or)21 b(e)o(xample,)h(if)g(there)g(are)g(tw)o(o)f(partially-o)o +(v)o(erlapping)e(tiles)i(in)g(dif)n(ferent)0 1161 y(cells,)32 +b(the)f(squares)g(generated)h(from)f(one)g(of)g(the)g(cells)g(may)f(f)o +(all)h(in)g(the)g(separations)f(between)i(squares)e(in)0 +1282 y(the)23 b(other)g(cell,)h(resulting)e(in)g(much)h(lar)n(ger)h +(areas)g(of)f(material)g(than)g(e)o(xpected.)30 b(There)24 +b(are)f(tw)o(o)g(w)o(ays)g(around)0 1402 y(this)i(problem.)35 +b(One)26 b(w)o(ay)h(is)f(to)g(use)g(the)g(design)g(rules)g(to)g +(prohibit)f(problem)h(situations)e(from)i(arising.)35 +b(This)0 1522 y(applies)19 b(mainly)g(to)g(the)g Fd(squar)n(es)i +Fg(operator)-5 b(.)29 b(T)m(iles)18 b(from)i(which)f(squares)h(are)g +(made)g(should)e(ne)n(v)o(er)h(be)h(allo)n(wed)0 1643 +y(to)29 b(o)o(v)o(erlap)f(other)h(such)g(tiles)f(in)h(dif)n(ferent)g +(cells)f(unless)h(the)g(o)o(v)o(erlap)f(is)h(e)o(xact,)h(so)e(each)i +(cell)f(will)g(generate)0 1763 y(squares)c(in)f(the)h(same)f(place.)31 +b(Y)-11 b(ou)25 b(can)g(use)g(the)f Fd(exact)p 1948 1763 +30 4 v 37 w(o)o(v)o(erlap)g Fg(design)g(rule)h(for)g(this.)146 +1886 y(The)g(second)g(approach)h(is)e(to)h(lea)n(v)o(e)g(things)e(up)i +(to)g(the)g(designer)-5 b(.)30 b(When)25 b(generating)g(CIF)-8 +b(,)26 b(Magic)f(issues)0 2006 y(w)o(arnings)e(where)h(there)g(is)f +(less)g(material)g(in)g(the)g(children)g(than)h(the)f(parent.)30 +b(The)24 b(designer)f(can)h(locate)f(these)0 2127 y(problems)f(and)h +(eliminate)g(the)g(interactions)f(that)h(cause)h(the)f(trouble.)29 +b(W)-8 b(arning:)30 b(Magic)23 b(does)g(not)g(check)g(the)0 +2247 y Fd(squar)n(es)j Fg(operations)f(for)h(hierarchical)g(consistenc) +o(y)-6 b(,)23 b(so)i(you)g(absolutely)f(must)h(use)g +Fd(exact)p 3265 2247 V 36 w(o)o(v)o(erlap)h Fg(design)0 +2367 y(rule)e(checks!)31 b(Right)23 b(no)n(w)-6 b(,)23 +b(the)h Fd(cif)n(output)h Fg(section)f(of)g(the)f(technology)g(is)h +(one)g(of)g(the)g(trickiest)f(things)g(in)g(the)0 2488 +y(whole)i(\002le,)i(particularly)e(since)h(errors)g(here)g(may)g(not)f +(sho)n(w)g(up)g(until)g(your)h(chip)f(comes)h(back)g(and)f(doesn')n(t)0 +2608 y(w)o(ork.)31 b(Be)25 b(e)o(xtremely)f(careful)h(when)g(writing)f +(this)g(part!)146 2731 y(Another)f(problem)g(with)g(hierarchical)h +(generation)f(is)g(that)g(it)g(can)h(be)f(v)o(ery)g(slo)n(w)-6 +b(,)22 b(especially)h(when)h(there)0 2851 y(are)30 b(a)g(number)f(of)h +(rules)f(in)g(the)h(cifoutput)e(section)h(with)g(v)o(ery)g(lar)n(ge)h +(gro)n(w)f(or)h(shrink)e(distances,)i(such)g(that)0 2972 +y(magic)f(must)f(al)o(w)o(ays)h(e)o(xpand)g(its)f(area)j(of)e(interest) +g(by)g(this)f(amount)g(to)h(be)h(sure)f(of)h(capturing)e(all)h +(possible)0 3092 y(layer)23 b(interactions.)29 b(When)23 +b(this)f(\223halo\224)h(distance)g(becomes)g(lar)n(ger)g(than)g(the)g +(a)n(v)o(erage)g(subcell,)g(much)f(of)h(the)0 3212 y(design)28 +b(may)g(end)g(up)h(being)f(processed)g(multiple)f(times.)41 +b(Noticeably)27 b(slo)n(w)h(output)f(generation)h(is)g(usually)0 +3333 y(indicati)n(v)o(e)j(of)j(this)e(problem.)56 b(It)33 +b(can)h(be)f(alle)n(viated)g(by)g(k)o(eeping)g(output)f(rules)h +(simple.)55 b(Note)33 b(that)g(basic)0 3453 y(AND)k(and)g(OR)g +(operations)g(do)f(not)h(interact)g(between)g(subcells,)i(so)e(that)f +(rules)h(made)g(from)g(only)f(these)0 3573 y(operators)d(will)g(not)g +(be)g(processed)h(during)e(subcell)h(interaction)g(generation.)56 +b(Remember)34 b(that)f(typically)-6 b(,)0 3694 y(subcell)30 +b(interaction)f(paint)h(will)g(only)g(be)g(generated)h(for)g(layers)f +(that)g(ha)n(v)o(e)g(a)h(\223gro)n(w\224)f(operation)g(follo)n(wed)0 +3814 y(by)c(a)g(\223shrink\224)g(operation.)35 b(This)25 +b(common)g(ruleset)h(lets)f(layers)i(that)e(are)i(too)f(closely)f +(spaced)i(to)f(be)g(mer)n(ged)0 3935 y(together)l(,)32 +b(thus)e(eliminating)e(the)j(need)g(for)g(a)g(spacing)f(rule)h(between) +g(the)f(layers.)49 b(But)31 b(consider)f(carefully)0 +4055 y(before)25 b(implementing)e(such)h(a)i(rule.)31 +b(Implementing)22 b(a)k(DRC)f(spacing)g(rule)g(instead)f(may)g +(eliminate)g(a)h(huge)0 4175 y(amount)34 b(of)i(output)e(processing.)62 +b(Usually)34 b(this)g(situation)g(crops)h(up)g(for)h(auto-generated)g +(layers)f(such)g(as)0 4296 y(implants)d(and)i(wells,)h(to)e(pre)n(v)o +(ent)g(magic)g(from)h(auto-generating)f(DRC)h(spacing)g(violations.)55 +b(But)34 b(again,)0 4416 y(consider)k(carefully)g(whether)g(it)f(might) +g(be)h(better)f(to)h(require)g(the)g(layout)f(engineer)h(to)g(dra)o(w)f +(the)h(layers)0 4536 y(instead)24 b(of)h(attempting)e(to)i +(auto-generate)g(them.)0 4846 y Ff(12.7)119 b(Render)31 +b(statements)0 5039 y Fg(At)k(the)h(end)g(of)f(each)i(style)e(in)g(the) +h Fd(cif)n(output)g Fg(section,)i(one)e(may)f(include)g +Fd(r)n(ender)j Fg(statements,)f(one)f(per)0 5159 y(de\002ned)h(CIF/GDS) +g(layer)-5 b(.)65 b(These)36 b Fd(r)n(ender)j Fg(statements)c(are)i +(used)f(by)g(the)g(3-D)g(dra)o(wing)f(windo)n(w)g(in)h(the)0 +5280 y(OpenGL)31 b(graphics)f(v)o(ersion)g(of)h(magic,)h(and)f(are)g +(also)g(used)g(by)f(the)h(\223)p Fd(cif)g(see)p Fg(\224)h(command)e(to) +g(set)h(the)g(style)0 5400 y(painted.)f(The)25 b(syntax)f(for)h(the)g +(statement)e(is)i(as)g(follo)n(ws:)1850 5649 y(\22624\226)p +eop end +%%Page: 25 25 +TeXDict begin 25 24 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)p 1366 3 1168 +4 v 1364 124 4 121 v 1416 88 a Fd(ci\002nput)p 2532 124 +V 1364 244 V 1416 208 a Fg(style)f(lambda=1.0\(gen\))p +2532 244 V 1364 364 V 1716 328 a(scalef)o(actor)i(100)p +2532 364 V 1364 485 V 1716 449 a(layer)f(m1)f(CMF)p 2532 +485 V 1364 605 V 2016 569 a(labels)g(CMF)p 2532 605 V +1364 726 V 1716 689 a(layer)h(ndif)n(f)f(CSN)p 2532 726 +V 1364 846 V 2016 810 a(and)h(CAA)p 2532 846 V 1364 966 +V 1716 930 a(layer)g(nsd)f(CWN)p 2532 966 V 1364 1087 +V 2016 1051 a(and)h(CSN)p 2532 1087 V 1364 1207 V 2016 +1171 a(and)g(CAA)p 2532 1207 V 1364 1328 V 1716 1291 +a(layer)g(nfet)g(CPG)p 2532 1328 V 1364 1448 V 2016 1412 +a(and)g(CAA)p 2532 1448 V 1364 1568 V 2016 1532 a(and)g(CSN)p +2532 1568 V 1364 1689 V 1716 1653 a(layer)g(ndc)g(CCA)p +2532 1689 V 1364 1809 V 2016 1773 a(gro)n(w)f(100)p 2532 +1809 V 1364 1929 V 2016 1893 a(and)h(CAA)p 2532 1929 +V 1364 2050 V 2016 2014 a(and)g(CWP)p 2532 2050 V 1364 +2170 V 2016 2134 a(and)g(CSN)p 2532 2170 V 1364 2291 +V 2016 2254 a(and)g(CMF)p 2532 2291 V 1364 2411 V 1716 +2375 a(layer)g(nncont)f(CCA)p 2532 2411 V 1364 2531 V +2016 2495 a(gro)n(w)g(100)p 2532 2531 V 1364 2652 V 2016 +2616 a(and)h(CAA)p 2532 2652 V 1364 2772 V 2016 2736 +a(and)g(CSN)p 2532 2772 V 1364 2892 V 2016 2856 a(and)g(CWN)p +2532 2892 V 1364 3013 V 2016 2977 a(and)g(CMF)p 2532 +3013 V 1364 3133 V 1716 3097 a(calma)g(CAA)g(1)g(*)p +2532 3133 V 1364 3254 V 1716 3218 a(calma)g(CCA)h(2)e(*)p +2532 3254 V 1364 3374 V 1716 3338 a(calma)h(CMF)g(4)g(*)p +2532 3374 V 1364 3494 V 1716 3458 a(calma)g(CPG)h(7)e(*)p +2532 3494 V 1364 3615 V 1716 3579 a(calma)h(CSN)h(8)e(*)p +2532 3615 V 1364 3735 V 1716 3699 a(calma)h(CWN)g(11)g(*)p +2532 3735 V 1364 3856 V 1716 3819 a(calma)g(CWP)h(12)e(*)p +2532 3856 V 1364 3976 V 1416 3940 a Fd(end)p 2532 3976 +V 1366 3979 1168 4 v 0 4139 a Fg(T)-8 b(able)24 b(10:)30 +b(P)o(art)25 b(of)f(the)h Fd(ci\002nput)h Fg(section.)k(The)24 +b(order)h(of)f(the)g(layers)h(is)f(important,)f(since)h(each)h(Magic)f +(layer)0 4260 y(o)o(v)o(errides)g(the)g(pre)n(vious)g(ones)g(just)g(as) +h(if)g(the)o(y)f(were)h(painted)g(by)f(hand.)900 4651 +y Fd(r)n(ender)j Fh(cif)p 1317 4651 30 4 v 35 w(layer)e(style)p +1765 4651 V 35 w(name)g(height)f(thic)n(kness)146 4918 +y Fg(The)k Fh(cif)p 435 4918 V 36 w(layer)g Fg(is)f(an)o(y)h(v)n(alid)f +(layer)h(name)g(de\002ned)h(in)e(the)h(same)g Fd(cif)n(output)h +Fg(section)f(where)g(the)g Fd(r)n(ender)0 5039 y Fg(statement)22 +b(occurs.)30 b(The)23 b Fh(style)p 1087 5039 V 35 w(name)g +Fg(is)f(the)h(name)g(or)g(number)f(of)h(a)g(style)f(in)h(the)g(styles)f +(\002le.)30 b(The)23 b(names)f(are)0 5159 y(the)30 b(same)g(as)g(used)f +(in)h(the)g Fd(styles)f Fg(section)g(of)h(the)g(technology)f(\002le.)46 +b Fh(height)30 b Fg(and)g Fh(thic)n(kness)f Fg(are)h(ef)n(fecti)n(v)o +(ely)0 5280 y(dimensionless)19 b(units)g(and)i(are)h(used)f(for)g +(relati)n(v)o(e)f(placement)g(and)h(scaling)g(of)g(the)f +(three-dimensional)g(layout)0 5400 y(vie)n(w)h(\(such)g(vie)n(ws)g +(generally)h(ha)n(v)o(e)f(a)h(greatly)f(e)o(xpanded)g(z-axis)h +(scaling\).)29 b(By)22 b(def)o(ault,)g(all)g(layers)f(are)i(gi)n(v)o +(en)1850 5649 y(\22625\226)p eop end +%%Page: 26 26 +TeXDict begin 26 25 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)0 68 y(the)f(same)g(style)f(and)h +(a)h(zero)f(height)g(and)g(thickness,)f(so)h(ef)n(fecti)n(v)o(ely)e +(nothing)h(useful)h(can)g(be)g(seen)g(in)g(the)g(3-D)0 +188 y(vie)n(w)h(without)f(a)j(complete)e(set)g(of)h Fd(r)n(ender)i +Fg(statements.)0 556 y Fi(13)143 b(Ci\002nput)34 b(section)0 +789 y Fg(In)26 b(addition)e(to)h(writing)f(CIF)-8 b(,)27 +b(Magic)e(can)h(also)f(read)h(in)f(CIF)h(\002les)g(using)e(the)i +Fd(:cif)g(r)n(ead)g Fh(\002le)f Fg(command.)32 b(The)0 +909 y Fd(ci\002nput)24 b Fg(section)d(of)g(the)h(technology)f(\002le)h +(describes)f(ho)n(w)g(to)h(con)l(v)o(ert)f(from)g(CIF)i(mask)e(layers)h +(to)f(Magic)h(tile)0 1030 y(types.)44 b(In)29 b(addition,)g(it)g(pro)o +(vides)f(information)g(to)h(the)g(Calma)h(reader)g(to)f(allo)n(w)f(it)h +(to)g(read)h(in)f(Calma)h(GDS)0 1150 y(II)c(Stream)g(format)g(\002les.) +33 b(The)26 b Fd(ci\002nput)h Fg(section)e(is)h(v)o(ery)f(similar)g(to) +g(the)g Fd(cif)n(output)i Fg(section.)33 b(It)26 b(can)g(contain)0 +1271 y(se)n(v)o(eral)e(styles,)g(with)g(a)h(line)f(of)h(the)g(form)900 +1534 y Fd(style)g Fh(name)146 1794 y Fg(used)g(to)f(end)h(the)g +(description)e(of)i(the)g(pre)n(vious)e(style)h(\(if)h(an)o(y\),)g(and) +f(start)h(a)g(ne)n(w)f(CIF)i(input)e(style)g(called)0 +1914 y Fh(name)p Fg(.)63 b(If)36 b(no)g(initial)e(style)h(name)h(is)f +(gi)n(v)o(en,)i(the)f(name)f Fd(default)i Fg(is)e(assigned.)63 +b(Each)36 b(style)f(must)f(ha)n(v)o(e)i(a)0 2034 y(statement)24 +b(of)h(the)f(form)900 2298 y Fd(scalefactor)h Fh(scale)g +Fd([nanometers])146 2558 y Fg(to)33 b(indicate)f(the)h(output)f(scale)h +(relati)n(v)o(e)f(to)h(Magic)g(units.)54 b(W)l(ithout)31 +b(the)i(optional)f(k)o(e)o(yw)o(ord)g Fd(nanome-)0 2678 +y(ters)p Fg(,)k Fh(scale)d Fg(describes)g(ho)n(w)g(man)o(y)f +(hundredths)g(of)i(a)f(micron)g(correspond)g(to)g(one)g(unit)g(in)g +(Magic.)56 b(W)l(ith)0 2798 y Fd(nanometers)26 b Fg(declared,)f +Fh(scale)g Fg(describes)f(ho)n(w)g(man)o(y)g(nanometers)g(correspond)h +(to)f(one)h(unit)f(in)g(Magic.)146 2923 y(Lik)o(e)39 +b(the)f Fd(cif)n(output)i Fg(section,)i(each)d(style)f(consists)f(of)i +(a)g(number)f(of)h(layer)g(descriptions.)71 b(A)39 b(layer)0 +3044 y(description)23 b(contains)g(one)h(or)g(more)g(lines)f +(describing)g(a)h(series)g(of)g(geometric)f(operations)g(to)h(be)g +(performed)0 3164 y(on)f(CIF)i(layers.)30 b(The)24 b(result)f(of)g(all) +g(these)h(operations)e(is)h(painted)g(on)h(a)f(particular)h(Magic)f +(layer)h(just)e(as)i(if)f(the)0 3284 y(user)h(had)f(painted)g(that)g +(information)f(by)h(hand.)30 b(A)24 b(layer)g(description)e(be)o(gins)g +(with)h(a)h(statement)e(of)i(the)f(form)900 3548 y Fd(lay)o(er)i +Fh(ma)o(gicLayer)g Fg([)p Fh(layer)o(s)p Fg(])146 3808 +y(In)g(the)f Fd(lay)o(er)g Fg(statement,)f Fh(ma)o(gicLayer)i +Fg(is)f(the)g(Magic)g(layer)g(that)g(will)g(be)g(painted)g(after)h +(performing)e(the)0 3928 y(geometric)31 b(operations,)i(and)f +Fh(layer)o(s)f Fg(is)h(an)g(optional)f(list)f(of)i(CIF)h(layers.)52 +b(If)33 b Fh(layer)o(s)e Fg(is)h(speci\002ed,)h(it)f(is)f(the)0 +4048 y(initial)26 b(v)n(alue)i(for)g(the)f(layer)h(being)g(b)n(uilt)e +(up.)40 b(If)28 b Fh(layer)o(s)f Fg(isn')n(t)g(speci\002ed,)i(the)f +(layer)g(starts)f(of)n(f)h(empty)-6 b(.)38 b(As)27 b(in)0 +4169 y(the)22 b Fd(cif)n(output)g Fg(section,)g(each)h(line)e(after)h +(the)g Fh(layer)f Fg(statement)g(gi)n(v)o(es)f(a)j(geometric)e +(operation)g(that)g(is)h(applied)0 4289 y(to)g(the)g(pre)n(vious)f +(contents)h(of)g(the)h(layer)f(being)g(b)n(uilt)f(in)h(order)h(to)f +(generate)h(ne)n(w)f(contents)g(for)g(the)g(layer)-5 +b(.)30 b(The)0 4409 y(result)24 b(of)h(the)g(last)f(geometric)g +(operation)h(is)f(painted)g(into)g(the)h(Magic)f(database.)146 +4534 y(The)c(geometric)g(operations)f(that)h(are)h(allo)n(wed)e(in)h +(the)g Fd(ci\002nput)h Fg(section)f(are)h(a)f(subset)f(of)i(those)e +(permitted)0 4655 y(in)24 b(the)h Fd(cif)n(output)h Fg(section:)900 +4918 y Fd(or)f Fh(layer)o(s)900 5039 y Fd(and)h Fh(layer)o(s)900 +5159 y Fd(and-not)g Fh(layer)o(s)900 5280 y Fd(gr)n(o)o(w)f +Fh(amount)900 5400 y Fd(shrink)h Fh(amount)1850 5649 +y Fg(\22626\226)p eop end +%%Page: 27 27 +TeXDict begin 27 26 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)146 68 y(In)33 +b(these)f(commands)f(the)h Fh(layer)o(s)g Fg(must)f(all)h(be)g(CIF)i +(layers,)g(and)e(the)g Fh(amounts)f Fg(are)i(all)f(CIF)i(distances)0 +189 y(\(centimicrons,)22 b(unless)f(the)i(k)o(e)o(yw)o(ord)e +Fd(nanometers)j Fg(has)e(been)h(used)f(in)g(the)h Fd(scalefactor)g +Fg(speci\002cation\).)29 b(As)0 309 y(with)21 b(the)h +Fd(cif)n(output)g Fg(section,)g(layers)g(can)g(only)f(be)h(speci\002ed) +f(in)h(simple)e(comma-separated)i(lists:)27 b(tildes)21 +b(and)0 429 y(slashes)j(are)i(not)e(permitted.)146 550 +y(When)d(CIF)i(\002les)e(are)h(read,)g(all)f(the)g(mask)f(information)g +(is)h(read)g(for)h(a)f(cell)g(before)h(performing)e(an)o(y)h(of)g(the)0 +670 y(geometric)29 b(processing.)44 b(After)30 b(the)f(cell)g(has)h +(been)g(completely)e(read)i(in,)g(the)f(Magic)h(layers)f(are)h +(produced)0 790 y(and)j(painted)f(in)g(the)h(order)g(the)o(y)f(appear)h +(in)f(the)h(technology)e(\002le.)55 b(In)33 b(general,)i(the)d(order)h +(that)g(the)f(layers)0 911 y(are)d(processed)f(is)f(important)g(since)h +(each)g(layer)g(will)g(usually)e(o)o(v)o(erride)i(the)f(pre)n(vious)g +(ones.)40 b(F)o(or)28 b(e)o(xample,)0 1031 y(in)36 b(the)g(scmos)f +(tech)h(\002le)g(sho)n(wn)f(in)h(T)-8 b(able)36 b(10)g(the)g(commands)e +(for)j Fd(ndiff)g Fg(will)e(result)g(in)h(the)g Fd(ndiff)h +Fg(layer)0 1152 y(being)29 b(generated)g(not)g(only)g(where)g(there)h +(is)f(only)f(ndif)n(fusion)g(b)n(ut)g(also)h(where)h(there)f(are)h +(ntransistors)e(and)0 1272 y(ndcontacts.)46 b(The)31 +b(descriptions)e(for)h Fd(ntransistor)h Fg(and)f Fd(ndcontact)i +Fg(appear)f(later)g(in)f(the)g(section,)h(so)f(those)0 +1392 y(layers)25 b(will)f(replace)h(the)g Fd(ndiff)h +Fg(material)e(that)g(w)o(as)h(originally)f(painted.)146 +1513 y(Labels)h(are)g(handled)g(in)f(the)h Fd(ci\002nput)h +Fg(section)e(just)g(lik)o(e)h(in)f(the)h Fd(cif)n(output)h +Fg(section.)k(A)24 b(line)h(of)g(the)f(form)900 1739 +y Fd(labels)g Fh(layer)o(s)146 1966 y Fg(means)29 b(that)f(the)h +(current)g(Magic)g(layer)g(is)f(to)h(recei)n(v)o(e)g(all)f(CIF)i +(labels)f(on)f Fh(layer)o(s)p Fg(.)43 b(This)28 b(is)h(actually)f(just) +0 2086 y(an)f(initial)f(layer)h(assignment)e(for)i(the)g(labels.)37 +b(Once)27 b(a)g(CIF)h(cell)f(has)g(been)g(read)g(in,)g(Magic)g(scans)g +(the)f(label)0 2207 y(list)g(and)g(re-assigns)g(labels)h(if)f +(necessary)-6 b(.)36 b(In)27 b(the)f(e)o(xample)g(of)h(T)-8 +b(able)27 b(10,)f(if)h(a)g(label)f(is)h(attached)f(to)g(the)h(CIF)0 +2327 y(layer)e(CPG)g(then)f(it)f(will)h(be)g(assigned)g(to)f(the)i +(Magic)e(layer)i Fd(poly)p Fg(.)30 b(Ho)n(we)n(v)o(er)l(,)23 +b(the)h(polysilicon)f(may)h(actually)0 2447 y(be)f(part)h(of)f(a)h +(poly-metal)e(contact,)h(which)g(is)f(Magic)h(layer)h +Fd(pcontact)p Fg(.)31 b(After)24 b(all)f(the)g(mask)f(information)g +(has)0 2568 y(been)32 b(processed,)i(Magic)e(checks)h(the)f(material)g +(underneath)g(the)g(layer)l(,)i(and)e(adjusts)f(the)i(label')-5 +b(s)31 b(layer)h(to)0 2688 y(match)c(that)h(material)f(\()p +Fd(pcontact)j Fg(in)d(this)g(case\).)43 b(This)29 b(is)f(the)h(same)f +(as)h(what)g(w)o(ould)f(happen)g(if)h(a)g(designer)0 +2809 y(painted)24 b Fd(poly)h Fg(o)o(v)o(er)f(an)h(area,)g(attached)g +(a)g(label)g(to)f(the)h(material,)f(then)h(painted)f +Fd(pcontact)i Fg(o)o(v)o(er)e(the)h(area.)146 2929 y(No)k(hierarchical) +g(mask)g(processing)f(is)g(done)h(for)g(CIF)h(input.)43 +b(Each)29 b(cell)g(is)f(read)i(in)e(and)h(its)f(layers)h(are)0 +3049 y(processed)c(independently)f(from)h(all)g(other)g(cells;)g(Magic) +f(assumes)h(that)g(there)g(will)f(not)h(be)g(an)o(y)g(unpleasant)0 +3170 y(interactions)k(between)h(cells)g(as)h(happens)e(in)h(CIF)i +(output)d(\(and)h(so)g(f)o(ar)l(,)i(at)e(least,)h(this)f(seems)g(to)f +(be)i(a)f(v)n(alid)0 3290 y(assumption\).)146 3410 y(If)22 +b(Magic)g(encounters)f(a)h(CIF)h(layer)f(name)g(that)f(doesn')n(t)g +(appear)i(in)e(an)o(y)g(of)h(the)f(lines)g(for)h(the)g(current)g(CIF)0 +3531 y(input)28 b(style,)i(it)f(issues)f(a)i(w)o(arning)f(message)g +(and)h(ignores)e(the)i(information)e(associated)h(with)f(the)h(layer)-5 +b(.)45 b(If)0 3651 y(you)25 b(w)o(ould)g(lik)o(e)g(Magic)h(to)f(ignore) +g(certain)h(layers)g(without)e(issuing)h(an)o(y)g(w)o(arning)g +(messages,)g(insert)h(a)g(line)0 3772 y(of)f(the)g(form)900 +3998 y Fd(ignor)n(e)g Fh(cifLayer)o(s)146 4225 y Fg(where)h +Fh(cifLayer)o(s)e Fg(is)h(a)g(comma-separated)f(list)g(of)h(one)g(or)g +(more)f(CIF)i(layer)f(names.)146 4345 y(Calma)37 b(layers)f(are)h +(speci\002ed)f(via)g Fd(calma)g Fg(lines,)i(which)e(should)f(appear)i +(at)f(the)g(end)g(of)g(the)g Fd(ci\002nput)0 4465 y Fg(section.)30 +b(The)o(y)24 b(are)i(of)f(the)f(form:)900 4692 y Fd(calma)g +Fh(cifLayer)h(calmaLayer)o(s)g(calmaT)-7 b(ypes)146 4918 +y Fg(The)25 b Fh(cifLayer)g Fg(is)g(one)g(of)g(the)f(CIF)i(types)f +(mentioned)e(in)i(the)g Fd(ci\002nput)h Fg(section.)31 +b(Both)24 b Fh(calmaLayer)o(s)h Fg(and)0 5039 y Fh(calmaT)-7 +b(ypes)32 b Fg(are)g(one)g(or)g(more)g(comma-separated)g(inte)o(gers)f +(between)h(0)f(and)h(63.)52 b(The)32 b(interpretation)f(of)0 +5159 y(a)k Fd(calma)f Fg(line)g(is)g(that)h(an)o(y)f(Calma)g(geometry)g +(whose)h(layer)f(is)h(an)o(y)f(of)g(the)h(layers)f(in)g +Fh(calmaLayer)o(s)p Fg(,)j(and)0 5280 y(whose)22 b(type)f(is)h(an)o(y)f +(of)h(the)g(types)g(in)f Fh(calmaT)-7 b(ypes)p Fg(,)22 +b(should)f(be)h(treated)g(as)g(the)g(CIF)h(layer)g Fh(cifLayer)p +Fg(.)29 b(Either)22 b(or)0 5400 y(both)j(of)i Fh(calmaLayer)o(s)f +Fg(and)g Fh(calmaT)-7 b(ypes)26 b Fg(may)g(be)g(the)g(character)h +Fd(*)f Fg(instead)g(of)g(a)h(comma-separated)f(list)f(of)1850 +5649 y(\22627\226)p eop end +%%Page: 28 28 +TeXDict begin 28 27 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)0 68 y(inte)o(gers;)f(this)g +(character)i(means)e Fh(all)g Fg(layers)h(or)g(types)f(respecti)n(v)o +(ely)-6 b(.)29 b(It)23 b(is)h(commonly)e(used)h(for)h +Fh(calmaT)-7 b(ypes)0 189 y Fg(to)24 b(indicate)h(that)f(the)h(Calma)g +(type)f(of)h(a)g(piece)g(of)g(geometry)f(should)g(be)h(ignored.)146 +309 y(Just)f(as)h(for)g(CIF)-8 b(,)25 b(Magic)f(also)h(issues)e(w)o +(arnings)h(if)h(it)f(encounters)g(unkno)n(wn)f(Calma)i(layers)f(while)g +(read-)0 430 y(ing)c(Stream)h(\002les.)29 b(If)21 b(there)f(are)h +(layers)g(that)f(you')-5 b(d)20 b(lik)o(e)g(Magic)g(to)g(ignore)g +(without)f(issuing)f(w)o(arnings,)j(assign)0 550 y(them)j(to)h(a)g +(dummy)e(CIF)j(layer)f(and)g(ignore)f(the)h(CIF)h(layer)-5 +b(.)0 892 y Fi(14)143 b(Lef)35 b(section)0 1116 y Fg(This)19 +b(section)g(de\002nes)h(a)g(mapping)e(between)i(magic)f(layers)h(and)g +(layers)f(that)h(may)f(be)h(found)f(in)g(LEF)h(and)g(DEF)0 +1237 y(format)28 b(\002les.)40 b(W)l(ithout)27 b(the)h(section,)g +(magic)f(cannot)h(read)h(a)f(LEF)g(or)g(DEF)h(\002le.)40 +b(The)28 b(LEF)h(and)f(DEF)g(layer)0 1357 y(declarations)c(are)i +(usually)e(simple)g(and)g(straightforw)o(ard)h(\(as)g(the)o(y)f +(typically)f(de\002ne)j(metal)e(layers)h(only\),)f(so)0 +1477 y(often)h(it)g(will)g(suf)n(\002ce)h(to)f(insert)g(a)g(plain)g(v)n +(anilla)f Fd(lef)i Fg(section)f(into)f(a)i(technology)f(\002le)g(if)h +(one)f(is)g(missing.)31 b(The)0 1598 y Fd(lef)24 b Fg(section)f(w)o(as) +h(introduced)f(in)g(technology)g(\002le)h(format)g(28,)f(and)h(is)g +(therefore)g(absent)f(from)h(all)g Fa(.tech27)0 1718 +y Fg(technology)g(\002les.)31 b(All)24 b(of)h(the)f(statements)g(in)g +(the)h Fd(lef)g Fg(section)f(ha)n(v)o(e)h(the)f(same)h(format:)900 +1950 y Fd(lay)o(er)g Fh(ma)o(gic-type)f(lefdef-type)h +Fg(.)15 b(.)g(.)900 2070 y Fd(cut)26 b Fh(ma)o(gic-type)e(lefdef-type)h +Fg(.)15 b(.)g(.)900 2190 y Fd(r)n(oute)p Fe(j)p Fd(r)n(outing)26 +b Fh(ma)o(gic-type)f(lefdef-type)f Fg(.)15 b(.)g(.)900 +2311 y Fd(obstruction)26 b Fh(ma)o(gic-type)f(lefdef-type)f +Fg(.)15 b(.)g(.)900 2431 y Fd(masterslice)25 b Fh(ma)o(gic-type)f +(lefdef-type)h Fg(.)15 b(.)g(.)900 2551 y Fd(o)o(v)o(erlap)25 +b Fh(ma)o(gic-type)f(lefdef-type)h Fg(.)15 b(.)g(.)146 +2782 y(Each)21 b(statement)e(de\002nes)i(a)g(mapping)e(between)h(a)h +(Magic)f(layer)h(type)f Fh(ma)o(gic-type)g Fg(and)g(one)h(or)f(more)g +(type)0 2903 y(names)k Fh(lefdef-type)g Fg(\(space-separated\))h(that)f +(might)f(be)h(encountered)g(in)g(a)h(LEF)f(or)h(DEF)f(\002le.)31 +b(The)24 b(dif)n(ferent)0 3023 y(command)e(names)h(all)g(refer)h(to)f +(dif)n(ferent)f(type)h(classes)g(de\002ned)g(by)g(the)g(LEF/DEF)g +(speci\002cation.)30 b(F)o(or)23 b(most)0 3144 y(purposes,)k(it)h(is)f +(only)g(necessary)g(to)h(use)f(the)h Fd(lay)o(er)f Fg(statement.)38 +b(If)28 b(the)g(magic)f(type)g(is)g(a)h(contact)g(type,)f(then)0 +3264 y(the)e Fd(lay)o(er)f Fg(statement)g(is)g(equi)n(v)n(alent)f(to)i +(specifying)f Fd(cut)p Fg(;)h(otherwise,)f(it)h(is)f(equi)n(v)n(alent)f +(to)h Fd(r)n(oute)p Fg(.)146 3385 y(T)-8 b(able)31 b(11)e(is)h(a)h +(typical)e Fd(lef)i Fg(section)e(for)i(a)f(5-metal)g(technology)-6 +b(,)30 b(which)g(encompasses)f(the)h(most)f(com-)0 3505 +y(monly)24 b(used)g(layer)h(names)g(found)f(in)g(LEF)h(and)g(DEF)g +(\002les.)0 3847 y Fi(15)143 b(Mzr)m(outer)35 b(section)0 +4071 y Fg(This)h(section)h(de\002nes)g(the)g(layers)g(and)g(contacts)g +(a)n(v)n(ailable)f(to)h(the)g(Magic)f(maze)i(router)l(,)i +Fh(mzr)l(outer)p Fg(,)e(and)0 4192 y(assigns)27 b(def)o(ault)h(costs)f +(for)i(each)f(type.)41 b(Def)o(ault)28 b(widths)e(and)j(spacings)e(are) +i(deri)n(v)o(ed)e(from)h(the)f Fd(dr)n(c)j Fg(section)0 +4312 y(of)36 b(the)g(technology)f(\002le)h(\(described)h(belo)n(w\))e +(b)n(ut)g(can)i(be)f(o)o(v)o(erridden)f(in)g(this)h(section.)63 +b(Other)36 b(mzrouter)0 4433 y(parameters,)21 b(for)e(e)o(xample,)h +(search)g(rate)g(and)g(width,)f(can)h(also)f(be)h(speci\002ed)g(in)f +(this)g(section.)28 b(The)19 b(syntax)g(and)0 4553 y(function)k(of)i +(the)e(lines)h(in)g(the)g Fd(mzr)n(outer)h Fg(section)f(of)g(the)g +(technology)f(\002le)i(are)f(speci\002ed)h(in)f(the)g(subsections)0 +4673 y(belo)n(w)-6 b(.)36 b(Each)28 b(set)f(of)g(speci\002cations)g +(should)f(be)h(headed)h(by)e(a)i Fd(style)f Fg(line.)37 +b Fd(Routelay)o(er)28 b Fg(and)f Fd(r)n(outecontact)0 +4794 y Fg(speci\002cations)d(should)g(precede)i(references)g(to)e +(them.)0 5091 y Ff(15.1)119 b(Styles)0 5280 y Fg(The)34 +b(mzrouter)g(is)f(currently)h(used)g(in)f(tw)o(o)h(conte)o(xts,)h +(interacti)n(v)o(ely)d(via)i(the)g Fd(ir)n(oute)g Fg(command,)i(and)e +(as)g(a)0 5400 y(subroutine)29 b(to)h(the)g(garouter)f(for)i(stem)e +(generation.)46 b(T)-8 b(o)30 b(permit)g(distinct)e(parameters)j(for)f +(these)g(tw)o(o)g(uses,)1850 5649 y(\22628\226)p eop +end +%%Page: 29 29 +TeXDict begin 29 28 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)p 307 3 3287 4 +v 305 124 4 121 v 357 88 a Fd(lef)p 3591 124 V 305 244 +V 611 208 a Fg(masterslice)99 b(ndif)n(f)279 b(dif)n(fusion)97 +b(acti)n(v)o(e)p 3591 244 V 305 364 V 611 328 a(masterslice)i(poly)293 +b(poly)278 b(POL)-10 b(Y1)255 b(pl)p 3591 364 V 305 485 +V 611 449 a(routing)k(m1)343 b(m1)328 b(metal1)283 b(MET)-9 +b(AL1)98 b(MET)-9 b(AL)p 3465 449 30 4 v 35 w(1)p 3591 +485 4 121 v 305 605 V 611 569 a(routing)259 b(m2)343 +b(m2)328 b(metal2)283 b(MET)-9 b(AL2)98 b(MET)-9 b(AL)p +3465 569 30 4 v 35 w(2)p 3591 605 4 121 v 305 726 V 611 +689 a(routing)259 b(m3)343 b(m3)328 b(metal3)283 b(MET)-9 +b(AL3)98 b(MET)-9 b(AL)p 3465 689 30 4 v 35 w(3)p 3591 +726 4 121 v 305 846 V 611 810 a(routing)259 b(m4)343 +b(m4)328 b(metal4)283 b(MET)-9 b(AL4)98 b(MET)-9 b(AL)p +3465 810 30 4 v 35 w(4)p 3591 846 4 121 v 305 966 V 611 +930 a(routing)259 b(m5)343 b(m5)328 b(metal5)283 b(MET)-9 +b(AL5)98 b(MET)-9 b(AL)p 3465 930 30 4 v 35 w(5)p 3591 +966 4 121 v 305 1087 V 3591 1087 V 305 1207 V 611 1171 +a(cut)426 b(pc)377 b(cont1)234 b(pl-m1)p 3591 1207 V +305 1328 V 611 1291 a(cut)426 b(m2c)299 b(via1)284 b(cont2)333 +b(VIA12)206 b(m1-m2)p 3591 1328 V 305 1448 V 611 1412 +a(cut)426 b(m3c)299 b(via2)284 b(cont3)333 b(VIA23)206 +b(m2-m3)p 3591 1448 V 305 1568 V 611 1532 a(cut)426 b(m4c)299 +b(via3)284 b(cont4)333 b(VIA34)206 b(m3-m4)p 3591 1568 +V 305 1689 V 611 1653 a(cut)426 b(m5c)299 b(via4)284 +b(cont5)333 b(VIA45)206 b(m4-m5)p 3591 1689 V 305 1809 +V 3591 1809 V 305 1929 V 611 1893 a(o)o(v)o(erlap)251 +b(comment)99 b(o)o(v)o(erlap)159 b(O)-5 b(VERLAP)p 3591 +1929 V 305 2050 V 357 2014 a Fd(end)p 3591 2050 V 307 +2053 3287 4 v 1223 2212 a Fg(T)d(able)25 b(11:)30 b(A)25 +b(plain)f(v)n(anilla)g(lef)h(section.)0 2585 y(the)e(lines)g(in)g(the)h +Fd(mzr)n(outer)h Fg(section)e(are)h(grouped)f(into)g +Fh(styles)p Fg(.)30 b(The)23 b(lines)g(pertaining)g(to)g(the)g(irouter) +g(should)0 2705 y(be)i(preceded)g(by)900 2970 y Fd(style)g(ir)n(outer) +146 3229 y Fg(and)g(those)f(pertaining)g(to)h(the)f(garouter)h(should)e +(be)i(preceded)h(by)e(the)h(speci\002cation)900 3494 +y Fd(style)g(gar)n(outer)146 3753 y Fg(Other)i(styles)f(can)i(be)f +(speci\002ed,)h(b)n(ut)e(are)i(currently)f(not)f(used.)38 +b(T)-8 b(able)27 b(12)f(sho)n(ws)g(the)h(mzrouter)g(section)0 +3874 y(from)e(the)f(scmos)g(technology)-6 b(.)0 4198 +y Ff(15.2)119 b(Lay)o(ers)0 4395 y Fg(Layer)25 b(lines)e(de\002ne)i +(the)f(route-layers)g(a)n(v)n(ailable)g(to)f(the)i(maze)f(router)g(in)g +(that)g(style.)30 b(The)o(y)23 b(ha)n(v)o(e)h(the)g(follo)n(w-)0 +4515 y(ing)g(form:)900 4779 y Fd(lay)o(er)h Fh(type)g(hCost)f(vCost)h +(jo)o(gCost)f(hintCost)146 5039 y Fg(Here)39 b Fh(type)f +Fg(is)f(the)h(name)g(of)g(the)f(tiletype)g(of)h(the)g(layer)g(and)g +Fh(hCost)p Fg(,)i Fh(vCost)p Fg(,)i Fh(jo)o(gCost)37 +b Fg(and)g Fh(hintCost)p Fg(,)0 5159 y(are)g(non-ne)o(gati)n(v)o(e)d +(inte)o(gers)h(specifying)g(the)h(cost)g(per)h(unit)e(horizontal)g +(distance,)k(cost)d(per)g(unit)g(v)o(ertical)0 5280 y(distance,)24 +b(cost)h(per)g(jog,)g(and)g(cost)f(per)h(unit)g(area)h(of)f(de)n +(viation)e(from)i(magnets,)f(respecti)n(v)o(ely)-6 b(.)29 +b(Route)c(layers)0 5400 y(for)g(an)o(y)f(gi)n(v)o(en)g(style)g(must)f +(lie)i(in)f(distinct)g(planes.)1850 5649 y(\22629\226)p +eop end +%%Page: 30 30 +TeXDict begin 30 29 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)p 816 3 2268 4 +v 814 124 4 121 v 866 88 a Fd(mzr)n(outer)p 3082 124 +V 814 244 V 866 208 a Fg(style)307 b(irouter)p 3082 244 +V 814 364 V 866 328 a(layer)297 b(m2)387 b(32)337 b(64)271 +b(256)149 b(1)p 3082 364 V 814 485 V 866 449 a(layer)297 +b(m1)387 b(64)337 b(32)271 b(256)149 b(1)p 3082 485 V +814 605 V 866 569 a(layer)297 b(poly)337 b(128)287 b(128)221 +b(512)149 b(1)p 3082 605 V 814 726 V 866 689 a(contact)208 +b(m2contact)99 b(metal1)165 b(metal2)99 b(1024)p 3082 +726 V 814 846 V 866 810 a(contact)208 b(pcontact)177 +b(metal1)165 b(poly)193 b(2056)p 3082 846 V 814 966 V +866 930 a(notacti)n(v)o(e)133 b(poly)337 b(pcontact)p +3082 966 V 814 1087 V 866 1051 a(style)307 b(garouter)p +3082 1087 V 814 1207 V 866 1171 a(layer)297 b(m2)387 +b(32)337 b(64)271 b(256)149 b(1)p 3082 1207 V 814 1328 +V 866 1291 a(layer)297 b(m1)387 b(64)337 b(32)271 b(256)149 +b(1)p 3082 1328 V 814 1448 V 866 1412 a(contact)208 b(m2contact)99 +b(metal1)165 b(metal2)99 b(1024)p 3082 1448 V 814 1568 +V 866 1532 a Fd(end)p 3082 1568 V 816 1572 2268 4 v 886 +1731 a Fg(T)-8 b(able)25 b(12:)30 b(Mzrouter)25 b(section)f(for)h(the)g +(scmos)f(technology)-6 b(.)0 2114 y Ff(15.3)119 b(Contacts)0 +2307 y Fg(Contact)30 b(lines)f(specify)g(the)g(route-contacts)h(a)n(v)n +(ailable)e(to)i(the)f(mzrouter)g(in)h(the)f(current)h(style.)44 +b(The)o(y)29 b(ha)n(v)o(e)0 2427 y(the)c(follo)n(wing)e(form:)900 +2677 y Fd(contact)j Fh(type)f(r)l(outeLayer1)f(r)l(outeLayer2)g(cost) +146 2923 y Fg(Here)32 b Fh(type)e Fg(is)h(the)f(tiletype)g(of)h(the)f +(contact,)i Fh(r)l(outeLayer1)e Fg(and)g Fh(r)l(outeLayer2)g +Fg(are)i(the)e(tw)o(o)g(layers)h(con-)0 3044 y(nected)25 +b(by)f(the)h(contact,)g(and)f Fh(cost)h Fg(is)f(a)h(nonne)o(gati)n(v)o +(e)d(inte)o(ger)i(specifying)g(the)h(cost)f(per)h(contact.)0 +3355 y Ff(15.4)119 b(Notacti)o(v)o(e)0 3548 y Fg(It)22 +b(maybe)g(desirable)g(to)f(ha)n(v)o(e)h(a)h(layer)f(or)g(contact)g(a)n +(v)n(ailable)f(to)h(the)g(maze)g(router)l(,)h(b)n(ut)e(def)o(ault)h(to) +g(of)n(f,)g(i.e.,)h(not)0 3669 y(be)k(used)g(by)g(the)g(mzrouter)g +(until)g(e)o(xplicitly)e(made)i(acti)n(v)o(e.)37 b(Route-types)27 +b(\(route-layers)g(or)g(route-contacts\))0 3789 y(can)e(be)g(made)g(to) +f(def)o(ault)h(to)f(of)n(f)h(with)f(the)h(follo)n(wing)d +(speci\002cation:)900 4038 y Fd(notacti)o(v)o(e)j Fh(r)l(oute-type)f +Fg(.)15 b(.)g(.)g([)p Fd(r)n(oute-typen)p Fg(])0 4350 +y Ff(15.5)119 b(Sear)n(ch)0 4543 y Fg(The)25 b(search)g +Fd(rate)p Fg(,)g Fd(width)p Fg(,)h(and)f Fd(penalty)g +Fg(parameters)g(can)g(be)g(set)g(with)f(a)h(speci\002cation)f(of)h(the) +g(form:)900 4792 y Fd(sear)n(ch)h Fh(r)o(ate)e(width)g(penalty)146 +5039 y Fg(Here)30 b Fh(r)o(ate)e Fg(and)g Fh(width)g +Fg(are)i(positi)n(v)o(e)c(inte)o(gers.)42 b(And)28 b +Fh(penalty)g Fg(is)g(a)h(positi)n(v)o(e)e(rational)h(\(it)g(may)h +(include)f(a)0 5159 y(decimal)j(point\).)51 b(See)33 +b(the)e(irouter)h(tutorial)e(for)i(a)g(discussion)e(of)i(these)g +(parameters.)52 b(\(Note)31 b(that)g Fd(penalty)0 5280 +y Fg(is)g(a)i(\223wizardly\224)e(parameter)l(,)j(i.e.,)g(it)d(is)g +(interacti)n(v)o(ely)f(set)i(and)g(e)o(xamined)e(via)i +Fd(ir)n(oute)h(wizard)f Fg(not)f Fd(ir)n(oute)0 5400 +y(sear)n(ch)p Fg(\).)h(If)25 b(no)g Fd(sear)n(ch)g Fg(line)g(is)f(gi)n +(v)o(en)f(for)i(a)h(style,)e(the)g(o)o(v)o(erall)g(mzrouter)g(def)o +(aults)h(are)g(used.)1850 5649 y(\22630\226)p eop end +%%Page: 31 31 +TeXDict begin 31 30 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)0 82 y Ff(15.6)119 +b(W)n(idth)0 275 y Fg(Appropriate)32 b(widths)g(for)g(route-types)g +(are)i(normally)d(deri)n(v)o(ed)h(from)g(the)g Fd(dr)n(c)i +Fg(section)e(of)h(the)f(technology)0 395 y(\002le.)f(These)25 +b(can)g(be)g(o)o(v)o(erridden)f(with)g(width)f(speci\002cations)i(of)g +(the)f(follo)n(wing)f(form:)900 642 y Fd(width)i Fh(r)l(oute-type)f +(width)146 887 y Fg(Here)i Fh(width)e Fg(is)h(a)g(positi)n(v)o(e)d +(inte)o(ger)-5 b(.)0 1197 y Ff(15.7)119 b(Spacing)0 1389 +y Fg(Minimum)29 b(spacings)h(between)h(routing)f(on)g(a)h(route-type)g +(and)g(other)g(types)f(are)i(deri)n(v)o(ed)d(from)i(the)g(design)0 +1510 y(rules.)41 b(These)29 b(v)n(alues)e(can)i(be)g(o)o(v)o(erridden)e +(by)h(e)o(xplicit)f(spacing)h(speci\002cations)g(in)g(the)g +Fd(mzr)n(outer)i Fg(section.)0 1630 y(Spacing)25 b(speci\002cations)f +(ha)n(v)o(e)h(the)f(follo)n(wing)f(form:)900 1877 y Fd(spacing)i +Fh(r)l(outetype)f(type1)g(spacing1)49 b Fg(.)15 b(.)g(.)g([)p +Fh(typen)24 b(spacingn)p Fg(])146 2122 y(Spacing)g(v)n(alues)e(must)h +(be)g(nonne)o(gati)n(v)o(e)e(inte)o(gers)h(or)i Fd(NIL)p +Fg(.)g(The)f(special)g(type)g Fd(SUBCELL)j Fg(can)e(be)f(used)0 +2242 y(to)h(specify)h(minimum)d(spacing)j(to)f(une)o(xpanded)g +(subcells.)0 2596 y Fi(16)143 b(Dr)m(c)35 b(section)0 +2825 y Fg(The)20 b(design)g(rules)g(used)g(by)g(Magic')-5 +b(s)20 b(design)f(rule)i(check)o(er)g(come)f(entirely)g(from)g(the)g +(technology)f(\002le.)30 b(W)-8 b(e')o(ll)0 2945 y(look)23 +b(\002rst)h(at)g(tw)o(o)f(simple)g(kinds)f(of)i(rules,)g +Fd(width)g Fg(and)g(and)g Fd(spacing)p Fg(.)30 b(Most)23 +b(of)h(the)f(rules)h(in)f(the)h Fd(dr)n(c)h Fg(section)0 +3066 y(are)h(one)e(or)h(the)g(other)f(of)h(these)g(kinds)f(of)h(rules.) +0 3376 y Ff(16.1)119 b(W)n(idth)30 b(rules)0 3568 y Fg(The)c(minimum)f +(width)g(of)i(a)f(collection)g(of)g(types,)h(tak)o(en)f(together)l(,)g +(is)g(e)o(xpressed)g(by)g(a)h Fd(width)g Fg(rule.)36 +b(Such)27 b(a)0 3688 y(rule)e(has)g(the)f(form:)900 3935 +y Fd(width)h Fh(type-list)f(width)h(err)l(or)146 4180 +y Fg(where)33 b Fh(type-list)d Fg(is)i(a)g(set)f(of)h(tile)f(types)g +(\(see)h(Section)g(8)g(for)g(syntax\),)g Fh(width)g Fg(is)f(an)h(inte)o +(ger)l(,)g(and)g Fh(err)l(or)0 4300 y Fg(is)27 b(a)g(string,)g +(enclosed)g(in)g(double)g(quotes,)g(that)g(can)g(be)h(printed)f(by)g +(the)g(command)f Fd(:dr)n(c)j(wh)o(y)e Fg(if)g(the)g(rule)h(is)0 +4421 y(violated.)j(A)25 b(width)f(rule)h(requires)h(that)e(all)h(re)o +(gions)f(containing)g(an)o(y)h(types)f(in)h(the)g(set)g +Fh(types)g Fg(must)f(be)h(wider)0 4541 y(than)f Fh(w)i +Fg(in)e(both)g(dimensions.)29 b(F)o(or)c(e)o(xample,)f(in)g(T)-8 +b(able)25 b(14,)f(the)h(rule)900 4788 y Fd(width)g Fg(nwell)g(6)1489 +4788 y +(") show + 1489 4788 a 60 w Fh(N-W)-9 b(ell)25 b(width)g(must)f(be)h(at)f +(least)g(6)h(\(MOSIS)g(rule)f(#1.1\))3555 4788 y +(") show + 3555 +4788 a 146 5033 a Fg(means)j(that)g(nwells)f(must)g(be)i(at)f(least)g +(6)g(units)f(wide)h(whene)n(v)o(er)f(the)o(y)h(appear)-5 +b(.)38 b(The)27 b Fh(type-list)f Fg(\002eld)h(may)0 5153 +y(contain)d(more)h(than)f(a)h(single)f(type,)h(as)g(in)f(the)h(follo)n +(wing)e(rule:)900 5400 y Fd(width)i Fg(allDif)n(f)g(2)1531 +5400 y +(") show + 1531 5400 a 60 w Fh(Dif)n(fusion)e(width)h(must)g(be)h(at)g +(least)f(2)h(\(MOSIS)f(rule)h(#2.1\))3693 5400 y +(") show + 3693 +5400 a 1850 5649 a Fg(\22631\226)p eop end +%%Page: 32 32 +TeXDict begin 32 31 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)p 333 3 3234 4 +v 331 124 4 121 v 383 88 a(#de\002ne)100 b(allDif)n(f)139 +b(ndif)n(f,pdif)n(f,ndc/a,pdc/a,ppcont/a,nncont/a,pfet,nfet,psd,nsd)p +3565 124 V 331 244 V 383 208 a(#de\002ne)100 b(e)o(xtPoly)f(poly)-6 +b(,pcontact)p 3565 244 V 331 364 V 383 328 a(#de\002ne)100 +b(e)o(xtM1)143 b(metal1,pcontact/m1,ndc/m1,ppcont/m1,pdc/m)o(1,nn)o +(cont/m)o(1)p 3565 364 V 331 485 V 383 449 a(#de\002ne)100 +b(e)o(xtM2)143 b(metal2,m2contact/m2)p 3565 485 V 333 +488 3234 4 v 1050 647 a(T)-8 b(able)25 b(13:)30 b(Abbre)n(viations)23 +b(for)i(sets)f(of)h(tile)g(types.)p 316 877 3269 4 v +314 997 4 121 v 365 961 a(width)99 b(pwell)160 b(6)1223 +961 y +(") show + 1223 961 a 60 w Fg(P-W)-8 b(ell)25 b(width)f(must)g(be)h(at)g +(least)f(6)h(\(MOSIS)g(rule)g(#1.1\))3301 961 y +(") show + 3301 +961 a 3583 997 4 121 v 314 1118 V 365 1082 a Fg(width)99 +b(nwell)160 b(6)1223 1082 y +(") show + 1223 1082 a 60 w Fg(N-W)-8 +b(ell)25 b(width)f(must)f(be)i(at)g(least)g(6)f(\(MOSIS)i(rule)f +(#1.1\))3318 1082 y +(") show + 3318 1082 a 3583 1118 4 121 v 314 +1238 V 365 1202 a Fg(width)99 b(allDif)n(f)118 b(2)1223 +1202 y +(") show + 1223 1202 a 60 w Fg(Dif)n(fusion)23 b(width)h(must)g(be)h(at)g +(least)f(2)h(\(MOSIS)g(rule)g(#2.1\))3406 1202 y +(") show + 3406 +1202 a 3583 1238 4 121 v 314 1358 V 365 1322 a Fg(width)99 +b(allPoly)g(2)1223 1322 y +(") show + 1223 1322 a 60 w Fg(Polysilicon)23 +b(width)h(must)g(be)h(at)g(least)f(2)h(\(MOSIS)h(rule)e(#3.1\))3475 +1322 y +(") show + 3475 1322 a 3583 1358 4 121 v 316 1362 3269 4 +v 1026 1521 a Fg(T)-8 b(able)25 b(14:)30 b(Some)25 b(width)f(rules)h +(in)f(the)h Fd(dr)n(c)h Fg(section.)146 1861 y(which)d(means)f(that)h +(all)f(re)o(gions)g(consisting)f(of)i(the)f(types)h(containing)e(an)o +(y)h(kind)g(of)h(dif)n(fusion)f(be)h(at)f(least)0 1982 +y(2)33 b(units)f(wide.)55 b(Because)34 b(man)o(y)e(of)i(the)f(rules)f +(in)h(the)g Fd(dr)n(c)h Fg(section)f(refer)h(to)f(the)f(same)h(sets)g +(of)g(layers,)i(the)0 2102 y Fd(#de\002ne)25 b Fg(f)o(acility)e(of)h +(the)g(C)g(preprocessor)g(is)f(used)g(to)h(de\002ne)g(a)g(number)f(of)h +(macros)g(for)g(these)f(sets)g(of)h(layers.)0 2223 y(T)-8 +b(able)25 b(13)f(gi)n(v)o(es)g(a)h(complete)f(list.)146 +2343 y(All)h(of)f(the)h(layers)g(named)f(in)h(an)o(y)f(one)h(width)e +(rule)i(must)f(lie)g(on)h(the)f(same)h(plane.)31 b(Ho)n(we)n(v)o(er)l +(,)23 b(if)i(some)f(of)0 2463 y(the)g(layers)h(are)g(contacts,)f(Magic) +g(will)g(substitute)e(a)j(dif)n(ferent)f(contact)g(image)g(if)h(the)f +(named)g(image)g(isn')n(t)g(on)0 2584 y(the)h(same)f(plane)h(as)g(the)g +(other)f(layers.)0 2878 y Ff(16.2)119 b(Spacing)31 b(rules)0 +3066 y Fg(The)22 b(second)h(simple)e(kind)h(of)g(design)g(rule)g(is)h +(a)f Fd(spacing)h Fg(rule.)30 b(It)22 b(comes)g(in)h(tw)o(o)f(\003a)n +(v)n(ors:)29 b Fd(touching)p 3572 3066 30 4 v 37 w(ok)p +Fg(,)23 b(and)0 3186 y Fd(touching)p 376 3186 V 37 w(illegal)p +Fg(,)g(both)h(with)g(the)h(follo)n(wing)e(syntax:)900 +3409 y Fd(spacing)i Fh(types1)f(types2)h(distance)f(\003avor)g(err)l +(or)146 3631 y Fg(The)39 b(\002rst)f(\003a)n(v)n(or)l(,)k +Fd(touching)p 1200 3631 V 37 w(ok)p Fg(,)f(does)d(not)g(prohibit)f +Fh(types1)g Fg(and)h Fh(types2)g Fg(from)g(being)g(immediately)0 +3751 y(adjacent.)52 b(It)32 b(merely)g(requires)g(that)g(an)o(y)f(type) +h(in)g(the)f(set)h Fh(types1)g Fg(must)f(be)h(separated)g(by)g(a)g +(\223Manhattan\224)0 3872 y(distance)27 b(of)g(at)g(least)g +Fh(distance)g Fg(units)f(from)h(an)o(y)g(type)f(in)h(the)g(set)g +Fh(types2)g Fg(that)g(is)g(not)g(immediately)e(adjacent)0 +3992 y(to)i(the)h(\002rst)f(type.)39 b(See)29 b(Figure)e(16.2)g(for)h +(an)g(illustration)d(of)j(Manhattan)f(distance)g(for)h(design)f(rules.) +39 b(As)27 b(an)0 4112 y(e)o(xample,)d(consider)g(the)h(metal1)f +(separation)g(rule:)900 4335 y Fd(spacing)h Fg(allPoly)f(allPoly)g(2)h +Fd(touching)p 2311 4335 V 37 w(ok)2472 4335 y +/bksp 2 string def bksp 0 92 put bksp show + 2472 4335 +a 1200 4455 a +(") show + 1200 4455 a 60 w Fh(P)-8 b(olysilicon)23 +b(spacing)h(must)g(be)h(at)f(least)g(2)h(\(MOSIS)g(rule)f(#3.2\))3521 +4455 y +(") show + 3521 4455 a 146 4678 a Fg(This)31 b(rule)g(is)g(symmetric)f(\()p +Fh(types1)h Fg(is)g(equal)g(to)g Fh(types2)p Fg(\),)i(and)e(requires,)i +(for)f(e)o(xample,)g(that)f(a)g(pcontact)0 4798 y(be)g(separated)h(by)e +(at)h(least)g(2)g(units)f(from)h(a)g(piece)h(of)f(polysilicon.)47 +b(Ho)n(we)n(v)o(er)l(,)32 b(this)e(rule)h(does)g(not)f(pre)n(v)o(ent)0 +4918 y(the)e(pcontact)g(from)h(touching)e(a)i(piece)g(of)f(poly)-6 +b(.)41 b(In)28 b Fd(touching)p 2264 4918 30 4 v 37 w(ok)h +Fg(rules,)g(all)f(of)h(the)f(layers)h(in)f(both)f Fh(types1)0 +5039 y Fg(and)35 b Fh(types2)g Fg(must)g(be)g(stored)g(on)g(the)h(same) +f(plane)g(\(Magic)g(will)g(substitute)e(dif)n(ferent)i(contact)g +(images)g(if)0 5159 y(necessary\).)146 5280 y Fd(T)n(OUCHING)p +705 5280 V 35 w(OK)k(SP)-7 b(A)i(CING)38 b Fg(R)l(ULES)i(DO)g(NO)l(T)f +(W)o(ORK)h(FOR)g(VER)-6 b(Y)40 b(LARGE)g(SP)-9 b(A)l(CINGS)0 +5400 y(\(RELA)e(TIVE)32 b(T)n(O)f(THE)g(TYPES)h(INV)l(OL)-10 +b(VED\).)31 b(SEE)h(FIGURE)g(6)f(FOR)i(AN)e(EXPLAN)m(A)-11 +b(TION.)30 b(If)i(the)1850 5649 y(\22632\226)p eop end +%%Page: 33 33 +TeXDict begin 33 32 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)1170 1392 y @beginspecial +68 @llx 68 @lly 346 @urx 316 @ury 1872 @rwi @setspecial +%%BeginDocument: ../psfigures/maint2.5.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.5.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:25:42 2000 +%%Pages: 1 +%%BoundingBox: 68 68 346 316 +%%DocumentNeededResources: font Helvetica +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 691 480 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.745 0.600 0.871 scb +240 1.00 211 192 211 448 403 448 403 192 4 polygon +240 1.00 563 608 563 832 755 832 755 608 4 polygon +sce +1 1.00 211 448 403 448 403 192 3 polygon +1 1.00 563 832 563 608 755 608 3 polygon +1 1.00 419 464 451 496 2 polygon +1 1.00 419 448 627 448 2 polygon +1 1.00 595 496 595 464 2 polygon +1.00 0 595 608 arrowhead +1.00 -181 595 448 arrowhead +1.00 135 403 448 arrowhead +1.00 -46 563 608 arrowhead +1 1.00 595 560 595 592 2 polygon +1 1.00 499 544 547 592 2 polygon +(Manhattan distance) {/Helvetica 1.000 cf} 2 21 0 739 528 label +(Euclidean distance) {/Helvetica 1.000 cf} 2 21 0 355 528 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 1595 a(Figure)g(6:)31 b(F)o(or)25 b(design)f(rule)h +(checking,)g(the)f(Manhattan)h(distance)f(between)h(tw)o(o)g +(horizontally)e(or)i(v)o(ertically)0 1715 y(aligned)e(points)f(is)i +(just)e(the)i(normal)f(Euclidean)g(distance.)30 b(If)24 +b(the)o(y)f(are)h(not)f(so)h(aligned,)f(then)g(the)h(Manhattan)0 +1836 y(distance)f(is)g(the)g(length)f(of)h(the)h(longest)e(side)h(of)g +(the)g(right)g(triangle)f(forming)h(the)g(diagonal)f(line)h(between)g +(the)0 1956 y(points.)p 85 2231 3730 4 v 83 2351 4 121 +v 135 2315 a(spacing)99 b(allPoly)g(allPoly)262 b(2)100 +b(touching)p 1972 2315 30 4 v 34 w(ok)2125 2315 y +/bksp 2 string def bksp 0 92 put bksp show + 2125 +2315 a 3813 2351 4 121 v 83 2472 V 539 2436 a +(") show + 539 2436 +a 60 w Fh(P)-8 b(olysilicon)23 b(spacing)h(must)g(be)h(at)g(least)f(2)g +(\(MOSIS)h(rule)g(#3.2\))2861 2436 y +(") show + 2861 2436 a 3813 +2472 4 121 v 83 2592 V 135 2556 a Fg(spacing)99 b(pfet)227 +b(nncont,nnd)98 b(3)i(touching)p 1972 2556 30 4 v 34 +w(ille)o(gal)2272 2556 y +/bksp 2 string def bksp 0 92 put bksp show + 2272 2556 a 3813 2592 4 121 +v 83 2712 V 539 2676 a +(") show + 539 2676 a 60 w Fh(T)-5 b(r)o(ansistor)o(s)22 +b(must)i(be)h(separ)o(ated)e(fr)l(om)h(substr)o(ate)f(contacts)h(by)h +(3)f(\(MOSIS)h(rule)f(#4.1\))3705 2676 y +(") show + 3705 2676 a +3813 2712 4 121 v 83 2833 V 135 2797 a Fg(spacing)99 +b(pc)288 b(allDif)n(f)281 b(1)100 b(touching)p 1972 2797 +30 4 v 34 w(ille)o(gal)2272 2797 y +/bksp 2 string def bksp 0 92 put bksp show + 2272 2797 a 3813 2833 +4 121 v 83 2953 V 539 2917 a +(") show + 539 2917 a 60 w Fh(P)-8 +b(oly)25 b(contact)f(must)g(be)h(1)g(unit)e(fr)l(om)h(dif)n(fusion)f +(\(MOSIS)i(rule)f(#5B.6\))3084 2917 y +(") show + 3084 2917 a 3813 +2953 4 121 v 85 2957 3730 4 v 988 3116 a Fg(T)-8 b(able)24 +b(15:)31 b(Some)24 b(spacing)h(rules)f(in)h(the)f Fd(dr)n(c)i +Fg(section.)0 3522 y(spacing)32 b(to)g(be)h(check)o(ed)g(is)f(greater)h +(than)g(the)f(width)g(of)g(one)h(of)g(the)f(types)g(in)l(v)n(olv)o(ed)f +(plus)h(either)g(its)g(self-)0 3642 y(spacing)k(or)g(spacing)f(to)h(a)h +(second)e(in)l(v)n(olv)o(ed)g(type,)j Fd(touching)p 2296 +3642 30 4 v 37 w(ok)e(spacing)h Fg(may)f(not)f(w)o(ork)h(properly:)53 +b(a)0 3762 y(violation)24 b(can)j(be)f(mask)o(ed)f(by)h(an)g(interv)o +(ening)e(touching)h(type.)33 b(In)26 b(such)g(cases)g(the)g(rule)g +(should)f(be)h(written)0 3883 y(using)e(the)g Fd(edge4way)h +Fg(construct)g(described)f(belo)n(w)-6 b(.)146 4024 y(The)32 +b(second)f(\003a)n(v)n(or)h(of)f(spacing)g(rule,)i Fd(touching)p +1940 4024 V 37 w(illegal)p Fg(,)e(disallo)n(ws)f(adjacenc)o(y)-6 +b(.)49 b(It)32 b(is)f(used)g(for)g(rules)0 4145 y(where)25 +b Fh(types1)g Fg(and)g Fh(types2)f Fg(can)h(ne)n(v)o(er)f(touch,)h(as)f +(in)h(the)f(follo)n(wing:)900 4542 y Fd(spacing)h Fg(pc)g(allDif)n(f)f +(1)h Fd(touching)p 2104 4542 V 36 w(illegal)2414 4542 +y +/bksp 2 string def bksp 0 92 put bksp show + 2414 4542 a 1200 4663 a +(") show + 1200 4663 a 60 w Fh(P)-8 b(oly)24 +b(contact)h(must)f(be)h(1)f(unit)g(fr)l(om)g(dif)n(fusion)f(\(MOSIS)i +(rule)f(#5B.6\))3745 4663 y +(") show + 3745 4663 a 146 5039 a Fg(Pcontacts)j(and)f +(an)o(y)g(type)h(of)f(dif)n(fusion)f(must)h(be)g(at)h(least)f(1)h(unit) +e(apart;)j(the)o(y)d(cannot)i(touch.)35 b(In)27 b Fd(touch-)0 +5159 y(ing)p 139 5159 30 4 v 36 w(illegal)d Fg(rules)i +Fh(types1)f Fg(and)h Fh(types2)g Fg(may)f(not)h(ha)n(v)o(e)f(an)o(y)h +(types)f(in)g(common:)32 b(it)25 b(w)o(ould)g(be)h(rather)g(strange)0 +5280 y(not)32 b(to)h(permit)f(a)i(type)e(to)h(touch)g(itself.)54 +b(In)33 b Fd(touching)p 1983 5280 V 37 w(illegal)f Fg(rules,)j +Fh(types1)d Fg(and)h Fh(types2)g Fg(may)g(be)g(spread)0 +5400 y(across)25 b(multiple)e(planes;)h(Magic)h(will)e(\002nd)i +(violations)e(between)i(material)g(on)f(dif)n(ferent)g(planes.)1850 +5649 y(\22633\226)p eop end +%%Page: 34 34 +TeXDict begin 34 33 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)975 1171 y @beginspecial +68 @llx 68 @lly 436 @urx 289 @ury 2340 @rwi @setspecial +%%BeginDocument: ../psfigures/maint2.6.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.6.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:27:49 2000 +%%Pages: 1 +%%BoundingBox: 68 68 436 289 +%%DocumentNeededResources: font Helvetica font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 832 124 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.133 0.545 0.133 scb +240 1.00 192 252 192 700 384 700 384 252 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 960 252 960 700 1152 700 1152 252 4 polygon +240 1.00 384 252 384 700 576 700 576 252 4 polygon +sce +0 1.00 192 252 192 700 384 700 384 252 4 polygon +0 1.00 384 252 384 700 576 700 576 252 4 polygon +0 1.00 960 252 960 700 1152 700 1152 252 4 polygon +(t1) {/Helvetica-Oblique 1.000 cf} 2 29 0 288 220 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 29 0 480 220 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 29 0 1056 220 label +(A) {/Helvetica 1.000 cf} 2 25 0 384 732 label +(B) {/Helvetica 1.000 cf} 2 25 0 1056 732 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 1374 a(Figure)19 b(7:)27 b(The)19 b Fd(touching)p +934 1374 30 4 v 37 w(ok)g Fg(rules)g(cancels)g(spacing)f(checks)h(if)g +(the)g(material)f(is)h(touching.)27 b(This)18 b(means)h(that)0 +1495 y(e)n(v)o(en)26 b(distant)f(material)i(w)o(on')n(t)f(be)h(check)o +(ed)g(for)g(spacing.)36 b(If)28 b(the)e(rule)h(applied)f(at)h(edge)g(A) +f(is)h(a)g(touching)p 3772 1495 V 34 w(ok)0 1615 y(rule)33 +b(between)g(material)f(t1)g(and)h(t2,)h(then)f(no)f(check)h(will)f(be)h +(made)g(between)g(the)f(t1)h(material)f(and)h(the)f(t2)0 +1736 y(material)23 b(on)g(the)h(f)o(ar)g(right)f(side)g(of)h(the)f +(diagram.)30 b(If)24 b(this)e(check)i(w)o(as)g(desired,)f(it)g(could)g +(be)h(accomplished)e(in)0 1856 y(this)h(case)h(by)f(a)h +Fd(edge4way)f Fg(check)h(from)g(edge)f(B.)h(This)f(w)o(ould)g(not)g(w)o +(ork)g(in)g(general,)h(though,)f(because)h(that)0 1976 +y(check)h(could)g(also)f(be)h(mask)o(ed)f(by)h(material)f(of)h(type)f +(t2,)h(causing)f(the)h(touching)p 2876 1976 V 34 w(ok)g(rule)g(to)f(be) +h(in)l(v)n(ok)o(ed.)0 2355 y Ff(16.3)119 b(W)n(ide)30 +b(material)f(spacing)i(rules)0 2544 y Fg(Man)o(y)22 b(f)o(abrications)h +(processes)g(require)g(a)g(lar)n(ger)h(distance)f(between)g(layers)g +(when)g(the)g(width)f(and)h(length)f(of)0 2665 y(one)29 +b(of)f(those)g(layers)h(e)o(xceeds)g(a)f(certain)h(minimum)e +(dimension.)40 b(F)o(or)29 b(instance,)g(a)g(process)f(might)f(declare) +0 2785 y(that)k(the)g(normal)g(spacing)g(between)g(metal1)g(lines)g(is) +g(3)g(microns.)50 b(Ho)n(we)n(v)o(er)l(,)32 b(if)f(a)h(metal1)e(line)h +(e)o(xceeds)h(a)0 2906 y(width)20 b(of)i(100)e(microns,)h(then)g(the)g +(spacing)g(to)g(other)g(unrelated)g(metal1)f(lines)h(must)f(increase)h +(to)g(10)g(microns.)0 3026 y(This)j(situation)f(is)i(co)o(v)o(ered)f +(by)g(the)h Fd(widespacing)g Fg(rule.)31 b(The)25 b(syntax)f(for)h +Fd(widespacing)g Fg(is)f(as)h(follo)n(ws:)900 3259 y +Fd(widespacing)g Fh(types1)g(wwidth)g(types2)f(distance)g(\003avor)g +(err)l(or)146 3492 y Fg(The)j Fd(widespacing)h Fg(rule)f(matches)g(the) +f(syntax)h(of)g Fd(spacing)g Fg(in)g(all)f(respects)h(e)o(xcept)g(for)g +(the)g(addition)f(of)0 3612 y(the)g(parameter)h Fh(wwidth)p +Fg(,)g(which)f(declares)h(the)f(minimum)e(width)i(of)g(layers)h(of)f +(type\(s\))h Fh(types1)f Fg(that)g(triggers)0 3732 y(the)d(rule.)31 +b(So)24 b(for)f(the)h(e)o(xample)f(abo)o(v)o(e,)f(the)i(correct)g +Fd(widespacing)g Fg(rule)g(w)o(ould)e(be)i(\(assuming)e(1)i(magic)f +(unit)0 3853 y(=)i(1)g(micron\):)900 4086 y Fd(widespacing)g +Fg(allMetal1)f(100)g(allMetal1)g(10)h Fd(touching)p 2934 +4086 V 36 w(ok)3095 4086 y +/bksp 2 string def bksp 0 92 put bksp show + 3095 4086 a 1200 4206 a +(") show + 1200 +4206 a 60 w Fh(Space)g(to)f(wide)h(Metal1)f(\(length)g(and)h(width)2903 +4206 y +(>) show + 2903 4206 a 30 w Fh(100\))f(must)h(be)f(at)h(least)f(10)3888 +4206 y +(") show + 3888 4206 a 0 4617 a Ff(16.4)119 b(Surr)n(ound)32 +b(rule)0 4806 y Fg(The)20 b Fd(surr)n(ound)i Fg(rule)e(speci\002es)h +(what)f(distance)f(a)i(layer)f(must)f(surround)g(another)l(,)i(and)f +(whether)h(the)f(presence)0 4926 y(of)33 b(the)g(surrounding)f +(material)h(is)g(optional)f(or)h(mandatory)-6 b(.)55 +b(This)32 b(rule)h(is)g(designed)f(for)i(materials)f(which)0 +5046 y(must)22 b Fh(completely)h Fg(surround)f(another)l(,)i(such)f(as) +g(metal)g(around)g(a)g(contact)g(cut)g(or)h(MiM)e(capacitor)h(layer)-5 +b(.)30 b(The)0 5167 y(syntax)24 b(is:)900 5400 y Fd(surr)n(ound)j +Fh(types1)d(types2)h(distance)f(pr)l(esence)h(err)l(or)1850 +5649 y Fg(\22634\226)p eop end +%%Page: 35 35 +TeXDict begin 35 34 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)390 1398 y @beginspecial +68 @llx 68 @lly 637 @urx 323 @ury 3744 @rwi @setspecial +%%BeginDocument: ../psfigures/maint2.6b.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.6b.ps +%%Creator: Xcircuit v2.5 +%%CreationDate: Tue Jan 8 13:16:19 2002 +%%Pages: 1 +%%BoundingBox: 68 68 637 323 +%%DocumentNeededResources: font Helvetica font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.4 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--5/16/01 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.4 1 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/ul { dup type /stringtype eq showflag 1 eq and { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { dup type /stringtype eq showflag 1 eq and { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave currentpoint newpath moveto true charpath flattenpath + pathbbox pop exch pop sub grestore } def +/Ts {mark Tabs aload pop counttomark 1 add array astore /Tabs exch def Tabs + 0 currentpoint pop put} def +/Tbn {mark Tabs aload pop counttomark dup 2 add 1 roll cleartomark 1 sub} def +/Tb { 0 1 Tbn {Tabs exch get dup currentpoint pop lt + {currentpoint exch pop moveto exit} {pop} ifelse } for } def +/Tf { Tbn -1 0 {Tabs exch get dup currentpoint pop gt + {currentpoint exch pop moveto exit} {pop} ifelse } for } def +/qS { (aa) stW (a a) stW sub 4 div 0 Kn } def +/hS { qS qS } def +/pspc 0 def +/cf0 { scalefont setfont } bind def +/Kn { dup kY add /kY exch def rmoveto } bind def +/ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul + 0.33 mul neg Kn} def +/Ss { /fscale fscale 0.67 mul def currentfont 0.67 cf0 0 fscale0 fscale mul + 0.67 mul Kn } def +/ns { 0 kY neg Kn /kY 0 def /fscale 1.0 def xfont0 1.0 cf0 } def +/CR { ns 0 /Bline Bline fscale0 neg add def Bline moveto } def +/cf { dup type /realtype ne {1.0} if exch findfont exch kY 0 eq + { 40 mul dup /fscale0 exch def cf0 /xfont0 currentfont def} + {fscale0 mul fscale mul cf0} ifelse } def +/ctmk { counttomark dup 2 add -1 roll pop } bind def +/label { gsave translate 0 0 moveto dup scale neg /rotval exch def + /just exch def just 16 and 0 gt {gsave rotval rotate 0 1 dtransform + gsave pagemat setmatrix idtransform exch grestore 1 0 dtransform + gsave pagemat setmatrix idtransform exch grestore dup abs 1e-9 lt + {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse grestore {-1 /rotval + rotval neg def /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse + exch -1e-9 lt {-1 /rotval rotval neg def /just just dup 12 and + 4 ne {12 xor} if def} {1} ifelse scale } if /showflag 0 def + /fspc pspc def /Bline 0 def /Tabs 0 array def /fscale 1.0 def + /kY 0 def gsave dup 1 add copy 0 exch 1 0 dtransform exch atan rotate + {exch dup type /stringtype eq {true charpath flattenpath} {exec} + ifelse } repeat pop pathbbox grestore 3 -1 roll pop 3 1 roll just + 1 and 0 gt {just 2 and 0 gt {exch pop neg fspc sub} {exch sub 0.5 + mul neg} ifelse} {pop neg fspc add} ifelse exch Bline exch just 4 + and 0 gt {just 8 and 0 gt {exch pop neg fspc sub} {add 0.5 mul neg} + ifelse} {pop neg fspc add} ifelse rotval rotate Kn currentpoint + translate /showflag 1 def /Bline 0 def /Tabs 0 array def /fscale + 1.0 def /kY 0 def {dup type /stringtype eq {show}{exec} ifelse} + repeat grestore } def +/pinlabel { 4 index 32 and 0 ne hlevel 0 eq or { /pspc 20 def label + /pspc 0 def } { pop pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/scb { setrgbcolor } bind def /sce { defColor aload pop scb } bind def +/cRedef {/defColor currentcolor 3 array astore def} def +/begingate { /hlevel hlevel 1 add def /defColor currentcolor sce 3 array + astore def gsave sce translate 0 0 moveto neg rotate dup abs scale + } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore defColor aload pop cRedef + scb} bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt style 512 eq or { newpath } { stroke } ifelse grestore } def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 0 0 scb cRedef } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +% trivial +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +% trivial +begingate +1.00 270 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 1024 186 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.494 0.753 0.933 scb +240 1.00 880 298 880 746 1264 746 1264 298 4 polygon +240 1.00 480 298 480 746 672 746 672 298 4 polygon +240 1.00 1360 298 1360 746 1552 746 1552 298 4 polygon +sce +0 1.00 880 298 880 746 1264 746 1264 298 4 polygon +0 1.00 1360 298 1360 746 1552 746 1552 298 4 polygon +0 1.00 480 298 480 746 672 746 672 298 4 polygon +(t1) {/Helvetica-Oblique cf} 2 29 0 1.00 1072 266 label +(t2) {/Helvetica-Oblique cf} 2 29 0 1.00 1456 266 label +(t2) {/Helvetica-Oblique cf} 2 29 0 1.00 576 266 label +(A) {/Helvetica cf} 2 29 0 1.00 432 218 label +(B) {/Helvetica cf} 2 29 0 1.00 1232 218 label +0.494 0.753 0.933 scb +240 1.00 192 298 192 746 384 746 384 298 4 polygon +sce +0 1.00 192 298 192 746 384 746 384 298 4 polygon +(t1) {/Helvetica-Oblique cf} 2 29 0 1.00 272 266 label +1 1.00 1264 826 1264 762 2 polygon +1 1.00 1424 762 1424 826 2 polygon +1 1.00 880 762 880 826 2 polygon +1 1.00 880 810 1424 810 2 polygon +1.00 0 896 810 arrowhead90 +-1.00 0 1248 810 arrowhead90 +-1.00 0 1408 810 arrowhead90 +1.00 0 1280 810 arrowhead90 +(wwidth) {/Helvetica-Oblique cf} 2 17 0 1.00 1056 826 label +(wdist) {/Helvetica-Oblique cf} 2 17 0 1.00 1344 826 label +1.000 1.000 1.000 scb +1 1.00 1360 746 1424 682 2 polygon +1 1.00 1360 714 1424 650 2 polygon +1 1.00 1360 682 1424 618 2 polygon +1 1.00 1360 650 1424 586 2 polygon +1 1.00 1360 618 1424 554 2 polygon +1 1.00 1360 586 1424 522 2 polygon +1 1.00 1360 554 1424 490 2 polygon +1 1.00 1360 522 1424 458 2 polygon +1 1.00 1360 490 1424 426 2 polygon +1 1.00 1360 458 1424 394 2 polygon +1 1.00 1360 426 1424 362 2 polygon +1 1.00 1360 394 1424 330 2 polygon +1 1.00 1360 362 1424 298 2 polygon +1 1.00 1360 330 1392 298 2 polygon +1 1.00 1392 746 1424 714 2 polygon +sce +1 1.00 1360 794 1360 762 2 polygon +1 1.00 1360 778 1488 778 2 polygon +1.00 0 1440 778 arrowhead90 +1.00 0 1376 778 arrowhead90 +(error area) {/Helvetica cf} 2 20 0 1.00 1504 778 label +1 1.00 480 762 480 826 2 polygon +1 1.00 384 810 480 810 2 polygon +-1.00 0 464 810 arrowhead90 +1.00 0 400 810 arrowhead90 +(dist) {/Helvetica-Oblique cf} 2 17 0 1.00 432 826 label +1 1.00 384 826 384 762 2 polygon +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 1602 a(Figure)g(8:)30 b(The)25 b Fd(widespacing)g +Fg(rule)f(co)o(v)o(ers)g(situations)e(lik)o(e)j(that)f(sho)n(wn)f(abo)o +(v)o(e,)g(in)i(which)f(material)g(of)g(type)0 1722 y +Fh(t1)32 b Fg(normally)g(must)f(be)i Fh(dist)f Fg(units)f(a)o(w)o(ay)i +(from)f(type)g Fh(t2)h Fg(\(situation)e(A\).)i(Ho)n(we)n(v)o(er)l(,)g +(if)f(both)g(dimensions)f(of)0 1842 y(material)23 b(type)h +Fh(t1)f Fg(are)i(lar)n(ger)f(than)g(or)g(equal)g(to)f(some)g(width)g +Fh(wwidth)h Fg(\(situation)e(B\),)j(then)e(the)h(spacing)f(must)0 +1963 y(be)i(increased)g(to)f Fh(wdist)p Fg(.)146 2304 +y(and)29 b(states)f(that)g(the)h(layers)g(in)f Fh(types2)g +Fg(must)g(surround)g(the)g(layers)h(in)f Fh(types1)h +Fg(by)f(an)h(amound)f Fh(distance)0 2425 y Fg(lambda)d(units.)31 +b(The)25 b(v)n(alue)g(of)g Fh(pr)l(esence)h Fg(must)e(be)i(one)f(of)g +(the)g(k)o(e)o(yw)o(ords)g Fd(absence)p 2983 2425 30 +4 v 37 w(ok)g Fg(or)h Fd(absence)p 3590 2425 V 36 w(illegal)p +Fg(.)0 2545 y(When)33 b Fh(pr)l(esence)g Fg(is)g Fd(absence)p +1091 2545 V 37 w(illegal)p Fg(,)g(then)g(types)f Fh(types2)g +Fg(must)g(al)o(w)o(ays)h(be)g(present)f(when)h(types)f +Fh(types1)0 2665 y Fg(are)25 b(present.)31 b(When)24 +b Fh(pr)l(esence)h Fg(is)f Fd(absence)p 1555 2665 V 37 +w(ok)p Fg(,)h(types)e Fh(types1)h Fg(may)h(e)o(xist)e(outside)g(of)i +(types)e Fh(types2)i Fg(without)0 2786 y(error)l(,)g(b)n(ut)g(where)g +(the)o(y)f(coincide,)g(types)g Fh(types2)h Fg(must)f(o)o(v)o(erlap)f +Fh(types1)i Fg(by)f(the)h(amount)f Fh(distance)p Fg(.)0 +3080 y Ff(16.5)119 b(Ov)o(erhang)30 b(rule)0 3268 y Fg(rule)35 +b(speci\002es)g(what)g(distance)g(a)g(layer)g(must)f(o)o(v)o(erhang)g +(another)h(at)g(an)g(intersection.)60 b(This)34 b(is)h(used,)i(for)0 +3388 y(e)o(xample,)23 b(to)h(specify)f(the)h(length)f(of)h(polysilicon) +e(end-caps)i(on)f(transistors,)g(which)g(is)h(the)f(distance)h(that)f +(the)0 3509 y(polysilicon)30 b(gate)i(must)f(e)o(xtend)g(be)o(yond)g +(the)h(de\002ned)h(gate)f(area)h(of)f(the)g(transistor)f(to)h(ensure)g +(a)h(correctly)0 3629 y(operating)24 b(de)n(vice.)31 +b(The)24 b(syntax)g(is:)900 3852 y Fd(o)o(v)o(erhang)h +Fh(types1)g(types2)f(distance)g(err)l(or)146 4075 y Fg(and)k(states)g +(that)f(layers)h(in)f Fh(types1)h Fg(must)f(o)o(v)o(erhang)f(layers)i +(in)g Fh(types2)f Fg(by)h(an)g(amount)f Fh(distance)g +Fg(lambda)0 4196 y(units.)35 b(The)27 b(rule)g(\003ags)g(the)f +(complete)g(absence)h(of)g(types)f Fh(types1)p Fg(,)h(b)n(ut)f(does)g +(not)g(prohibit)g(the)g(use)h(of)f Fh(types1)0 4316 y +Fg(as)g(a)h(bridge)f(\(that)g(is,)h(with)e(types)h Fh(types2)g +Fg(on)g(either)h(side)f(of)g Fh(types1)p Fg(,)g(which)g(will)g +(generally)g(be)h(co)o(v)o(ered)e(by)0 4436 y(a)g(separate)g(spacing)g +(rule,)f(and)h(which)g(may)f(ha)n(v)o(e)h(a)g(dif)n(ferent)f(spacing)g +(requirement\).)0 4731 y Ff(16.6)119 b(Rectangle-only)30 +b(rule)0 4918 y Fg(The)35 b Fd(r)n(ect)p 359 4918 V 37 +w(only)g Fg(rule)g(is)f(used)h(to)g(denote)f(layers)h(that)g(must)f(be) +h(rectangular;)40 b(that)35 b(is,)i(the)o(y)d(cannot)g(bend,)0 +5039 y(or)40 b(ha)n(v)o(e)g(notches)f(or)i(tabs.)76 b(Generally)-6 +b(,)43 b(this)c(is)g(used)h(for)h(contacts,)i(so)d(that)f(the)h(CIF)h +(output)e(operator)0 5159 y Fd(squar)n(es)31 b Fg(will)e(be)h +(guaranteed)g(to)g(generate)g(a)g(correct)h(contact.)46 +b(This)29 b(is)h(due)g(to)f(magic')-5 b(s)29 b(corner)n(-stitching)0 +5280 y(tile)24 b(database,)h(where)g(bends,)f(notches,)f(tabs,)i(and)f +(slots)f(will)h(break)h(up)f(an)h(otherwise)f(continuous)f(patch)h(of)0 +5400 y(material)e(into)f(potentially)g(man)o(y)g(small)g(tiles,)h(each) +h(one)g(of)f(which)g(might)f(be)h(too)g(small)f(to)h(\002t)h(a)f +(contact)g(cut.)1850 5649 y(\22635\226)p eop end +%%Page: 36 36 +TeXDict begin 36 35 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)900 84 y Fd(r)n(ect)p +1069 84 30 4 v 37 w(only)h Fh(types)f(err)l(or)0 383 +y Ff(16.7)119 b(Edge)30 b(rules)0 572 y Fg(The)j(width)f(and)i(spacing) +e(rules)h(just)g(described)g(are)h(actually)e(translated)h(by)g(Magic)g +(into)f(an)h(underlying,)0 692 y(edge-based)25 b(rule)g(format.)32 +b(This)24 b(underlying)g(format)g(can)i(handle)f(rules)f(more)h +(general)h(than)e(simple)g(widths)0 813 y(and)31 b(spacings,)h(and)f +(is)g(accessible)g(to)g(the)g(writer)g(of)g(a)h(technology)e(\002le)i +(via)f Fd(edge)h Fg(rules.)49 b(These)31 b(rules)g(are)0 +933 y(applied)d(at)g(boundaries)g(between)h(material)f(of)g(tw)o(o)g +(dif)n(ferent)g(types,)h(in)f(an)o(y)g(of)h(four)f(directions)g(as)g +(sho)n(wn)0 1053 y(in)c(Figure)g(9.)30 b(The)24 b(design)f(rule)i +(table)e(contains)g(a)i(separate)f(list)f(of)h(rules)g(for)g(each)h +(possible)e(combination)f(of)0 1174 y(materials)i(on)h(the)f(tw)o(o)h +(sides)f(of)h(an)g(edge.)1170 2819 y @beginspecial 68 +@llx 68 @lly 412 @urx 400 @ury 1872 @rwi @setspecial +%%BeginDocument: ../psfigures/maint2.7.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.7.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:32:42 2000 +%%Pages: 1 +%%BoundingBox: 68 68 412 400 +%%DocumentNeededResources: font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 704 544 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.745 0.600 0.871 scb +240 1.00 832 736 832 1056 1024 1056 1024 736 4 polygon +240 1.00 256 256 256 448 576 448 576 256 4 polygon +240 1.00 256 736 256 1056 448 1056 448 736 4 polygon +240 1.00 704 256 704 448 1024 448 1024 256 4 polygon +sce +0 1.00 256 736 256 1056 448 1056 448 736 4 polygon +0 1.00 832 736 832 1056 1024 1056 1024 736 4 polygon +0 1.00 256 256 256 448 576 448 576 256 4 polygon +0 1.00 704 256 704 448 1024 448 1024 256 4 polygon +1 1.00 192 896 320 896 2 polygon +1 1.00 1088 896 960 896 2 polygon +1 1.00 416 192 416 320 2 polygon +1 1.00 864 512 864 384 2 polygon +1.00 0 416 336 arrowhead +1.00 -181 864 368 arrowhead +1.00 -271 944 896 arrowhead +1.00 270 336 896 arrowhead +(t1) {/Helvetica-Oblique 1.000 cf} 2 25 0 224 928 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 25 0 288 928 label +(t1) {/Helvetica-Oblique 1.000 cf} 2 25 0 1056 928 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 25 0 976 928 label +(t1) {/Helvetica-Oblique 1.000 cf} 2 25 0 896 480 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 25 0 896 400 label +(t1) {/Helvetica-Oblique 1.000 cf} 2 25 0 368 208 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 25 0 368 288 label +(d) {/Helvetica-Oblique 1.000 cf} 2 21 0 352 688 label +1 1.00 256 720 256 672 2 polygon +1 1.00 448 720 448 672 2 polygon +(d) {/Helvetica-Oblique 1.000 cf} 2 21 0 928 688 label +1 1.00 832 720 832 672 2 polygon +1 1.00 1024 720 1024 672 2 polygon +(d) {/Helvetica-Oblique 1.000 cf} 2 21 0 208 352 label +1 1.00 240 448 192 448 2 polygon +1 1.00 240 256 192 256 2 polygon +(d) {/Helvetica-Oblique 1.000 cf} 2 21 0 1072 352 label +1 1.00 1088 448 1040 448 2 polygon +1 1.00 1088 256 1040 256 2 polygon +1 1.00 1072 384 1072 432 2 polygon +1 1.00 1072 320 1072 272 2 polygon +1 1.00 208 384 208 432 2 polygon +1 1.00 208 320 208 272 2 polygon +1 1.00 272 688 320 688 2 polygon +1 1.00 384 688 432 688 2 polygon +1 1.00 848 688 896 688 2 polygon +1 1.00 960 688 1008 688 2 polygon +1.00 0 208 448 arrowhead +1.00 0 1072 448 arrowhead +1.00 -181 1072 256 arrowhead +1.00 -181 208 256 arrowhead +1.00 -271 256 688 arrowhead +1.00 -271 832 688 arrowhead +1.00 -91 1024 688 arrowhead +1.00 -91 448 688 arrowhead +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 3023 a(Figure)g(9:)31 b(Design)24 b(rules)g(are)i +(applied)e(at)h(the)g(edges)f(between)h(tiles)f(in)h(the)f(same)h +(plane.)31 b(A)25 b(rule)f(is)h(speci\002ed)0 3143 y(in)h(terms)h(of)f +(type)h Fh(t1)f Fg(and)h(type)f Fh(t2)p Fg(,)h(the)f(materials)g(on)h +(either)f(side)h(of)g(the)f(edge.)37 b(Each)27 b(rule)f(may)h(be)g +(applied)0 3263 y(in)22 b(an)o(y)f(of)i(four)f(directions,)g(as)g(sho)n +(wn)f(by)h(the)g(arro)n(ws.)29 b(The)22 b(simplest)f(rules)h(require)g +(that)g(only)f(certain)i(mask)0 3384 y(types)h(can)h(appear)h(within)d +(distance)i Fh(d)f Fg(on)h Fh(t2)p Fg(')-5 b(s)24 b(side)g(of)h(the)g +(edge.)146 3731 y(In)e(its)e(simplest)g(form,)i(a)f(rule)h(speci\002es) +f(a)h(distance)f(and)g(a)h(set)f(of)g(mask)g(types:)29 +b(only)22 b(the)g(gi)n(v)o(en)f(types)g(are)0 3851 y(permitted)i +(within)g(that)h(distance)f(on)h Fh(type2)p Fg(')-5 b(s)24 +b(side)f(of)h(the)g(edge.)31 b(This)23 b(area)i(is)f(referred)i(to)d +(as)h(the)g Fh(constr)o(aint)0 3971 y(r)l(e)l(gion)p +Fg(.)k(Unfortunately)-6 b(,)19 b(this)f(simple)g(scheme)i(will)e(miss)g +(errors)i(in)e(corner)i(re)o(gions,)f(such)g(as)h(the)f(case)g(sho)n +(wn)0 4092 y(in)29 b(Figure)g(10.)44 b(T)-8 b(o)29 b(eliminate)g(these) +g(problems,)g(the)g(full)g(rule)g(format)g(allo)n(ws)f(the)h +(constraint)g(re)o(gion)f(to)h(be)0 4212 y(e)o(xtended)c(past)h(the)g +(ends)g(of)g(the)g(edge)h(under)f(some)f(circumstances.)35 +b(See)27 b(Figure)f(11)g(for)h(an)f(illustration)e(of)0 +4333 y(the)29 b(corner)h(rules)g(and)f(ho)n(w)g(the)o(y)f(w)o(ork.)45 +b(T)-8 b(able)29 b(16)h(gi)n(v)o(es)e(a)h(complete)g(description)g(of)g +(the)g(information)f(in)0 4453 y(each)d(design)f(rule.)146 +4574 y(Edge)h(rules)g(are)g(speci\002ed)g(in)g(the)f(technology)g +(\002le)h(using)f(the)h(follo)n(wing)d(syntax:)900 4807 +y Fd(edge)k Fh(types1)e(types2)g(d)h(OKT)-7 b(ypes)26 +b(cornerT)-7 b(ypes)24 b(cornerDist)g(err)l(or)f Fg([)p +Fh(plane)p Fg(])146 5039 y(Both)30 b Fh(types1)f Fg(and)h +Fh(types2)f Fg(are)h(type-lists.)44 b(An)30 b(edge)f(rule)h(is)f +(generated)h(for)g(each)h(pair)e(consisting)f(of)i(a)0 +5159 y(type)h(from)g Fh(types1)g Fg(and)g(a)h(type)e(from)h +Fh(types2)p Fg(.)50 b(All)31 b(the)g(types)f(in)h Fh(types1)p +Fg(,)i Fh(types2)p Fg(,)f(and)f Fh(cornerT)-7 b(ypes)31 +b Fg(must)0 5280 y(lie)d(on)f(a)h(single)f(plane.)40 +b(See)28 b(Figure)g(11)g(for)g(an)g(e)o(xample)f(edge)h(rule.)39 +b(It)28 b(is)f(sometimes)f(useful)i(to)f(specify)h(a)0 +5400 y(null)e(list,)h(i.e.,)h Fd(0)p Fg(,)g(for)f Fh(OKT)-7 +b(ypes)28 b Fg(or)g Fh(CornerT)-7 b(ypes)p Fg(.)38 b(Null)27 +b Fh(OKT)-7 b(ypes)27 b Fg(means)g(no)g(edges)h(between)f +Fh(types1)g Fg(and)1850 5649 y(\22636\226)p eop end +%%Page: 37 37 +TeXDict begin 37 36 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)0 68 y Fh(types2)d +Fg(are)h(OK.)f(Null)f Fh(CornerT)-7 b(ypes)22 b Fg(means)g(no)g(corner) +h(e)o(xtensions)d(are)j(to)f(be)g(check)o(ed)h(\(corner)g(e)o +(xtensions)0 188 y(are)j(e)o(xplained)d(belo)n(w\).)146 +309 y(Some)i(of)f(the)g(edge)g(rules)g(in)g(Magic)g(ha)n(v)o(e)g(the)g +(property)g(that)g(if)g(a)h(rule)f(is)g(violated)f(between)h(tw)o(o)g +(pieces)0 429 y(of)35 b(geometry)-6 b(,)37 b(the)e(violation)e(can)j +(be)f(disco)o(v)o(ered)f(looking)g(from)h(either)g(piece)g(of)g +(geometry)g(to)n(w)o(ard)f(the)0 549 y(other)-5 b(.)39 +b(T)-8 b(o)28 b(capitalize)g(on)f(this,)h(Magic)g(normally)e(applies)i +(an)g(edge)g(rule)g(only)f(in)g(tw)o(o)h(of)g(the)f(four)h(possible)0 +670 y(directions:)h(bottom-to-top)23 b(and)h(left-to-right,)g(reducing) +g(the)h(w)o(ork)f(it)g(has)h(to)f(do)h(by)f(a)h(f)o(actor)g(of)g(tw)o +(o.)30 b(Also,)0 790 y(the)g(corner)g(e)o(xtension)f(is)g(only)g +(performed)h(to)g(one)f(side)h(of)g(the)g(edge:)40 b(to)30 +b(the)g(top)f(for)h(a)g(left-to-right)f(rule,)0 911 y(and)22 +b(to)g(the)f(left)h(for)g(a)h(bottom-to-top)c(rule.)30 +b(All)22 b(of)g(the)f(width)g(and)h(spacing)g(rules)g(translate)f +(neatly)h(into)f(edge)0 1031 y(rules.)146 1151 y(Ho)n(we)n(v)o(er)l(,) +31 b(you')o(ll)f(probably)g(\002nd)h(it)g(easiest)f(when)h(you')-5 +b(re)31 b(writing)e(edge)i(rules)g(to)f(insist)g(that)g(the)o(y)g(be)0 +1272 y(check)o(ed)21 b(in)f(all)h(directions.)28 b(T)-8 +b(o)21 b(do)f(this,)g(write)h(the)f(rule)h(the)g(same)f(w)o(ay)h(e)o +(xcept)f(use)h(the)f(k)o(e)o(yw)o(ord)g Fd(edge4way)0 +1392 y Fg(instead)k(of)h Fd(edge)p Fg(:)900 1601 y Fd(edge4way)g +Fg(nfet)g(ndif)n(f)f(2)h(ndif)n(f,ndc)e(ndif)n(f)i(2)2486 +1601 y +/bksp 2 string def bksp 0 92 put bksp show + 2486 1601 a 1200 1721 a +(") show + 1200 1721 a 60 w Fh(Dif)n(fusion)e(must) +h(o)o(verhang)g(tr)o(ansistor)e(by)j(at)f(least)h(2)3163 +1721 y +(") show + 3163 1721 a 146 1929 a Fg(Not)33 b(only)g(are)h +Fd(edge4way)f Fg(rules)g(check)o(ed)h(in)f(all)g(four)h(directions,)g +(b)n(ut)f(the)g(corner)h(e)o(xtension)e(is)h(per)n(-)0 +2050 y(formed)23 b(on)h Fh(both)f Fg(sides)g(of)g(the)h(edge.)30 +b(F)o(or)24 b(e)o(xample,)f(when)g(checking)g(a)h(rule)g(from)f +(left-to-right,)g(the)h(corner)0 2170 y(e)o(xtension)d(is)h(performed)g +(both)g(to)g(the)g(top)g(and)h(to)f(the)g(bottom.)28 +b Fd(Edge4way)23 b Fg(rules)g(tak)o(e)f(twice)g(as)h(much)f(time)0 +2291 y(to)i(check)i(as)f Fd(edge)g Fg(rules,)g(so)f(it')-5 +b(s)24 b(to)g(your)h(adv)n(antage)f(to)g(use)h Fd(edge)h +Fg(rules)e(where)n(v)o(er)h(you)f(can.)146 2411 y(Normally)-6 +b(,)22 b(an)i(edge)g(rule)f(is)g(check)o(ed)h(completely)f(within)f(a)i +(single)e(plane:)30 b(both)23 b(the)g(edge)h(that)f(triggers)0 +2531 y(the)d(rule)h(and)g(the)f(constraint)g(area)i(to)e(check)h(f)o +(all)f(in)h(the)f(same)h(plane.)29 b(Ho)n(we)n(v)o(er)l(,)20 +b(the)h Fh(plane)f Fg(ar)n(gument)g(can)h(be)0 2652 y(speci\002ed)27 +b(in)f(an)h(edge)g(rule)g(to)f(force)h(Magic)g(to)f(perform)h(the)f +(constraint)g(check)h(on)f(a)h(plane)g(dif)n(ferent)f(from)0 +2772 y(the)g(one)h(containing)e(the)i(triggering)e(edge.)37 +b(In)26 b(this)g(case,)h Fh(OKT)-7 b(ypes)28 b Fg(must)d(all)h(be)h +(tile)f(types)g(in)g Fh(plane)p Fg(.)36 b(This)0 2893 +y(feature)d(is)g(used,)h(for)f(e)o(xample,)h(to)e(ensure)h(that)f +(polysilicon)f(and)i(dif)n(fusion)e(edges)i(don')n(t)f(lie)g +(underneath)0 3013 y(metal2)24 b(contacts:)900 3221 y +Fd(edge4way)h Fg(allPoly)f(\230\(allPoly\)/acti)n(v)o(e)g(1)g +(\230m2c/metal2)g(\230\(allPoly\)/acti)n(v)o(e)f(1)3662 +3221 y +/bksp 2 string def bksp 0 92 put bksp show + 3662 3221 a 585 4947 a @beginspecial 68 @llx 68 +@lly 604 @urx 369 @ury 3276 @rwi @setspecial +%%BeginDocument: ../psfigures/maint2.8.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.8.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 11:46:16 2000 +%%Pages: 1 +%%BoundingBox: 68 68 604 369 +%%DocumentNeededResources: font Helvetica font Helvetica-Bold +%%+ font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 928 590 offsets +1.0000 inchscale +2.6000 setlinewidth + +1.000 0.000 0.000 scb +240 1.00 832 270 832 590 1184 590 1184 270 4 polygon +240 1.00 1248 654 1248 974 1600 974 1600 654 4 polygon +240 1.00 192 270 192 590 320 590 320 270 4 polygon +sce +0 1.00 320 270 320 590 512 590 512 270 4 polygon +(space) {/Helvetica-Bold 1.000 cf} 2 21 0 416 430 label +(poly) {/Helvetica-Bold 1.000 cf} 2 21 0 256 430 label +(poly) {/Helvetica-Bold 1.000 cf} (= not ) {/Helvetica 1.000 cf} (OKTypes ) {/Helvetica-Oblique 1.000 cf} +6 25 0 416 686 label +1 1.00 416 670 416 558 2 polygon +1.00 -181 416 542 arrowhead +(\(a\)) {/Helvetica 1.000 cf} 2 21 0 416 206 label +0 1.00 832 270 832 590 1184 590 1184 270 4 polygon +0 1.00 1248 654 1248 974 1600 974 1600 654 4 polygon +1 1.00 832 590 832 782 1184 782 1184 590 1376 590 1376 270 1184 270 7 polygon +1 1.00 1600 654 1600 462 1248 462 1248 654 1056 654 1056 974 1248 974 +7 polygon +(poly) {/Helvetica-Bold 1.000 cf} 2 21 0 1424 830 label +(poly) {/Helvetica-Bold 1.000 cf} 2 21 0 992 430 label +(\(b\)) {/Helvetica 1.000 cf} 2 21 0 1216 206 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 5150 a Fg(Figure)36 b(10:)52 b(If)36 b(only)f(the)g +(simple)g(rules)g(from)g(Figure)h(9)g(are)g(used,)i(errors)e(may)f(go)h +(unnoticed)e(in)i(corner)0 5271 y(re)o(gions.)30 b(F)o(or)24 +b(e)o(xample,)g(the)h(polysilicon)e(spacing)h(rule)h(in)f(\(a\))i(will) +e(f)o(ail)g(to)h(detect)f(the)h(error)h(in)e(\(b\).)1850 +5649 y(\22637\226)p eop end +%%Page: 38 38 +TeXDict begin 38 37 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)488 2397 y @beginspecial +68 @llx 68 @lly 583 @urx 490 @ury 3510 @rwi @setspecial +%%BeginDocument: ../psfigures/maint2.9.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.9.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 12:02:16 2000 +%%Pages: 1 +%%BoundingBox: 68 68 583 490 +%%DocumentNeededResources: font Helvetica font Helvetica-Bold +%%+ font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 1150 782 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.800 0.800 0.800 scb +240 1.00 478 1166 478 1230 542 1230 542 1166 4 polygon +sce +0.898 0.898 0.898 scb +240 1.00 542 1166 542 1294 670 1294 670 1166 4 polygon +sce +0.800 0.800 0.800 scb +240 1.00 542 910 542 1166 670 1166 670 910 4 polygon +240 1.00 1182 1166 1182 1230 1246 1230 1246 1166 4 polygon +sce +1.000 0.000 0.000 scb +240 1.00 1118 910 1118 1166 1246 1166 1246 910 4 polygon +sce +0.898 0.898 0.898 scb +240 1.00 1246 1166 1246 1294 1374 1294 1374 1166 4 polygon +sce +0 1.00 542 910 542 1166 670 1166 670 910 4 polygon +0 1.00 542 1166 542 1294 670 1294 670 1166 4 polygon +0 1.00 478 1166 478 1230 542 1230 542 1166 4 polygon +0 1.00 1246 910 1246 1166 1374 1166 1374 910 4 polygon +0 1.00 1246 1166 1246 1294 1374 1294 1374 1166 4 polygon +0 1.00 1182 1166 1182 1230 1246 1230 1246 1166 4 polygon +(B) {/Helvetica 1.000 cf} 2 21 0 606 1230 label +(A) {/Helvetica 1.000 cf} 2 25 0 606 942 label +(cornerTypes) {/Helvetica-Oblique 1.000 cf} 2 23 0 414 1198 label +(cornerDist) {/Helvetica-Oblique 1.000 cf} 2 20 0 702 1238 label +(OKTypes) {/Helvetica-Oblique 1.000 cf} 2 20 0 702 1102 label +(t1) {/Helvetica-Oblique 1.000 cf} 2 21 0 510 1006 label +(t2) {/Helvetica-Oblique 1.000 cf} 2 21 0 574 1006 label +1 1.00 478 1038 606 1038 2 polygon +1 1.00 638 1102 686 1102 2 polygon +1 1.00 702 1118 638 1182 2 polygon +1 1.00 718 1278 718 1254 2 polygon +1 1.00 718 1214 718 1182 2 polygon +1 1.00 430 1198 510 1198 2 polygon +1 1.00 558 878 590 878 2 polygon +1 1.00 622 878 654 878 2 polygon +1 1.00 542 894 542 846 2 polygon +1 1.00 670 894 670 846 2 polygon +1.00 0 718 1294 arrowhead +1.00 -181 718 1166 arrowhead +1.00 -91 526 1198 arrowhead +1.00 -91 622 1038 arrowhead +1.00 -91 670 878 arrowhead +1.00 90 542 878 arrowhead +1.00 90 622 1102 arrowhead +1.00 45 622 1198 arrowhead +(d) {/Helvetica-Oblique 1.000 cf} 2 21 0 602 878 label +(\(a\)) {/Helvetica 1.000 cf} 2 21 0 606 798 label +1 1.00 1422 1210 1422 1182 2 polygon +1.00 -181 1422 1166 arrowhead +1 1.00 1422 1278 1422 1254 2 polygon +1.00 0 1422 1294 arrowhead +1 1.00 1406 1118 1342 1182 2 polygon +1.00 45 1326 1198 arrowhead +1 1.00 1342 1102 1390 1102 2 polygon +1.00 90 1326 1102 arrowhead +1 1.00 1182 1038 1310 1038 2 polygon +1.00 -91 1326 1038 arrowhead +1 1.00 1326 878 1358 878 2 polygon +1 1.00 1374 894 1374 846 2 polygon +1.00 -91 1374 878 arrowhead +1 1.00 1262 878 1294 878 2 polygon +1 1.00 1246 894 1246 846 2 polygon +1.00 90 1246 878 arrowhead +(\(b\)) {/Helvetica 1.000 cf} 2 21 0 1310 798 label +1 1.00 1134 1198 1214 1198 2 polygon +1.00 -91 1230 1198 arrowhead +1 1.00 686 1294 734 1294 2 polygon +1 1.00 686 1166 734 1166 2 polygon +1 1.00 1390 1294 1438 1294 2 polygon +1 1.00 1390 1166 1438 1166 2 polygon +(poly) {/Helvetica-Bold 1.000 cf} (not) {/Helvetica 1.000 cf} 4 23 0 1118 1198 label +(poly) {/Helvetica-Bold 1.000 cf} (not) {/Helvetica 1.000 cf} 4 20 0 1422 1102 label +(2) {/Helvetica 1.000 cf} 2 21 0 1310 878 label +(2) {/Helvetica 1.000 cf} 2 21 0 1422 1234 label +(poly) {/Helvetica-Bold 1.000 cf} 2 31 0 1214 1022 label +(space) {/Helvetica-Bold 1.000 cf} 2 28 0 1262 1022 label +1.000 0.000 0.000 scb +240 1.00 414 398 414 590 542 590 542 398 4 polygon +sce +0.800 0.800 0.800 scb +240 1.00 542 270 542 718 670 718 670 270 4 polygon +sce +0 1.00 542 270 542 718 670 718 670 270 4 polygon +(poly) {/Helvetica-Bold 1.000 cf} 2 25 0 494 510 label +(poly) {/Helvetica-Bold 1.000 cf} (not) {/Helvetica 1.000 cf} 4 20 0 734 462 label +1 1.00 718 462 638 462 2 polygon +1 1.00 494 494 574 494 2 polygon +1.00 0 638 462 arrowhead90 +1.00 -1 574 494 arrowhead90 +1.000 0.000 0.000 scb +240 1.00 1022 398 1022 590 1150 590 1150 398 4 polygon +240 1.00 1022 590 1022 718 1374 718 1374 590 4 polygon +sce +0.800 0.800 0.800 scb +240 1.00 1150 270 1150 590 1278 590 1278 270 4 polygon +sce +0 1.00 1150 270 1150 590 1278 590 1278 270 4 polygon +(poly) {/Helvetica-Bold 1.000 cf} (not) {/Helvetica 1.000 cf} 4 20 0 1342 462 label +1 1.00 1326 462 1246 462 2 polygon +1.00 0 1246 462 arrowhead90 +(poly) {/Helvetica-Bold 1.000 cf} 2 25 0 1182 638 label +1 1.00 1102 510 1182 510 2 polygon +1.00 -1 1182 510 arrowhead90 +(\(c\)) {/Helvetica 1.000 cf} 2 21 0 542 206 label +(\(d\)) {/Helvetica 1.000 cf} 2 21 0 1198 206 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 2600 a(Figure)f(11:)29 b(The)23 b(complete)f(design)g +(rule)h(format)g(is)f(illustrated)f(in)i(\(a\).)31 b(Whene)n(v)o(er)22 +b(an)h(edge)g(has)g Fh(type1)f Fg(on)h(its)0 2721 y(left)g(side)g(and)g +Fh(type2)g Fg(on)g(its)g(right)f(side,)h(the)g(area)h(A)g(is)e(check)o +(ed)i(to)f(be)g(sure)g(that)g(only)g Fh(OKT)-7 b(ypes)23 +b Fg(are)h(present.)0 2841 y(If)35 b(the)g(material)f(just)g(abo)o(v)o +(e)f(and)i(to)f(the)h(left)f(of)h(the)g(edge)g(is)f(one)g(of)h +Fh(cornerT)-7 b(ypes)p Fg(,)37 b(then)d(area)i(B)f(is)g(also)0 +2961 y(check)o(ed)25 b(to)g(be)g(sure)g(that)g(it)f(contains)g(only)h +Fh(OKT)-7 b(ypes)p Fg(.)31 b(A)25 b(similar)f(corner)i(check)f(is)g +(made)g(at)g(the)g(bottom)e(of)0 3082 y(the)f(edge.)31 +b(Figure)22 b(\(b\))h(sho)n(ws)f(a)g(polysilicon)f(spacing)h(rule,)h +(\(c\))g(sho)n(ws)f(a)h(situation)d(where)j(corner)h(e)o(xtension)0 +3202 y(is)k(performed)h(on)f(both)g(ends)g(of)g(the)h(edge,)g(and)g +(\(d\))f(sho)n(ws)g(a)g(situation)f(where)i(corner)g(e)o(xtension)e(is) +h(made)0 3323 y(only)i(at)g(the)g(bottom)f(of)h(the)g(edge.)48 +b(If)31 b(the)f(rule)g(described)g(in)g(\(d\))h(were)g(to)f(be)g +(written)g(as)g(an)h Fd(edge)g Fg(rule,)h(it)0 3443 y(w)o(ould)24 +b(look)g(lik)o(e:)900 3671 y Fd(edge)i Fg(poly)e(space)h(2)g(\230poly)f +(\230poly)g(2)2187 3671 y +/bksp 2 string def bksp 0 92 put bksp show + 2187 3671 a 1200 3792 a +(") show + 1200 +3792 a 60 w Fh(P)-8 b(oly-poly)24 b(separ)o(ation)f(must)h(be)h(at)f +(least)g(2)2811 3792 y +(") show + 2811 3792 a 1200 4409 a +(") show + 1200 4409 +a 60 w Fh(V)-7 b(ia)24 b(must)g(be)h(on)f(a)h(\003at)f(surface)g +(\(MOSIS)h(rule)g(#8.4,5\))3232 4409 y +(") show + 3232 4409 a 84 +w Fg(metal2)146 5039 y(Magic)37 b(v)o(ersions)e(using)h(tech\002le)h +(formats)f(more)g(recent)h(than)g(28)f(are)i(generally)e(more)g(cle)n +(v)o(er)h(about)0 5159 y(determining)29 b(the)i(correct)g(plane)g(from) +g Fh(OKT)-7 b(ypes)31 b Fg(when)f(the)o(y)g(dif)n(fer)h(from)g(the)f +(triggering)g(types,)i(and)e(the)0 5280 y(situation)g(is)h(unambiguous) +f(\(use)h(of)h(\223space\224)g(in)f(rules)h(tends)f(to)g(introduce)g +(ambiguity)-6 b(,)31 b(since)g(space)h(tiles)0 5400 y(appear)25 +b(on)g(all)f(planes\).)1850 5649 y(\22638\226)p eop end +%%Page: 39 39 +TeXDict begin 39 38 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)p 630 3 2640 4 +v 628 124 4 121 v 680 88 a(P)o(arameter)p 1218 124 V +188 w(Meaning)p 3268 124 V 630 127 2640 4 v 630 144 V +628 264 4 121 v 680 228 a(type1)p 1218 264 V 368 w(Material)f(on)h +(\002rst)g(side)f(of)h(edge.)p 3268 264 V 630 267 2640 +4 v 628 388 4 121 v 680 352 a(type2)p 1218 388 V 368 +w(Material)f(on)h(second)f(side)h(of)g(edge.)p 3268 388 +V 630 391 2640 4 v 628 511 4 121 v 680 475 a(d)p 1218 +511 V 540 w(Distance)f(to)h(check)g(on)f(second)h(side)f(of)h(edge.)p +3268 511 V 630 515 2640 4 v 628 876 4 362 v 680 599 a(OKT)-8 +b(ypes)p 1218 876 V 210 w(List)24 b(of)g(layers)h(that)f(are)i +(permitted)e(within)f Fh(d)i Fg(units)e(on)1270 719 y(second)35 +b(side)h(of)f(edge.)64 b(\()p Fh(OKT)-7 b(ypes)p Fg(=)p +Fd(0)36 b Fg(means)g(ne)n(v)o(er)1270 840 y(OK\))p 3268 +876 V 630 879 2640 4 v 628 1120 4 241 v 680 963 a(cornerT)-8 +b(ypes)p 1218 1120 V 100 w(List)31 b(of)h(layers)g(that)g(cause)h +(corner)f(e)o(xtension.)52 b(\()p Fh(cor)n(-)1270 1084 +y(nerT)-7 b(ypes)p Fg(=)p Fd(0)25 b Fg(means)f(no)h(corner)g(e)o +(xtension\))p 3268 1120 V 630 1123 2640 4 v 628 1364 +4 241 v 680 1208 a(cornerDist)p 1218 1364 V 169 w(Amount)33 +b(to)i(e)o(xtend)f(constraint)g(area)i(when)f Fh(corner)n(-)1270 +1328 y(T)-7 b(ypes)25 b Fg(matches.)p 3268 1364 V 630 +1367 2640 4 v 628 1729 4 362 v 680 1452 a(plane)p 1218 +1729 V 374 w(Plane)39 b(on)f(which)g(to)g(check)g(constraint)g(re)o +(gion)f(\(de-)1270 1572 y(f)o(aults)29 b(to)g(same)g(plane)g(as)h +Fh(type1)f Fg(and)g Fh(type2)g Fg(and)h Fh(cor)n(-)1270 +1692 y(nerT)-7 b(ypes)p Fg(\).)p 3268 1729 V 630 1732 +2640 4 v 1110 1891 a(T)f(able)25 b(16:)30 b(The)25 b(parts)f(of)h(an)g +(edge-based)g(rule.)p 105 2128 3691 4 v 103 2248 4 121 +v 155 2212 a(edge4w)o(ay)99 b(ppcont,ppd)f(ndif)n(f,ndc,nfet)202 +b(3)100 b(ndif)n(f,ndc,nfet)e(ndif)n(f,ndc,nfet)356 b(3)3706 +2212 y +/bksp 2 string def bksp 0 92 put bksp show + 3706 2212 a 3794 2248 4 121 v 103 2368 V 657 2332 +a +(") show + 657 2332 a 60 w Fh(Ndif)n(f)24 b(must)g(be)h(3)g(wide)g(if)f(it)h(ab) +n(uts)f(ppcont)g(or)g(ppd)g(\(MOSIS)h(rule)g(#??\))3257 +2332 y +(") show + 3257 2332 a 3794 2368 4 121 v 103 2489 V 155 2453 +a Fg(edge4w)o(ay)99 b(allPoly)262 b(\230\(allPoly\)/acti)n(v)o(e)98 +b(3)i(\230pc/acti)n(v)o(e)249 b(\230\(allPoly\)/acti)n(v)o(e)j(3)3706 +2453 y +/bksp 2 string def bksp 0 92 put bksp show + 3706 2453 a 3794 2489 4 121 v 103 2609 V 657 2573 +a +(") show + 657 2573 a 60 w Fh(P)-8 b(oly)24 b(contact)h(must)f(be)h(at)f(least)g +(3)h(fr)l(om)e(other)i(poly)f(\(MOSIS)h(rule)f(#5B.4,5\))3472 +2573 y +(") show + 3472 2573 a 3794 2609 4 121 v 103 2730 V 155 2693 +a Fg(edge4w)o(ay)99 b(allPoly)262 b(\230\(allPoly\)/acti)n(v)o(e)98 +b(1)i(\230m2c/metal2)134 b(\230\(allPoly\)/acti)n(v)o(e)252 +b(1)3706 2693 y +/bksp 2 string def bksp 0 92 put bksp show + 3706 2693 a 3794 2730 4 121 v 103 2850 +V 657 2814 a +(") show + 657 2814 a 60 w Fh(V)-7 b(ia)24 b(must)g(be)h(on)f(a)h +(\003at)f(surface)g(\(MOSIS)h(rule)g(#8.4,5\))2689 2814 +y +(") show + 2689 2814 a 84 w Fg(metal2)p 3794 2850 4 121 v 105 +2853 3691 4 v 1046 3013 a(T)-8 b(able)24 b(17:)31 b(Some)25 +b(edge)g(rules)f(in)h(the)f Fd(dr)n(c)i Fg(section.)0 +3395 y Ff(16.8)119 b(Subcell)32 b(Ov)o(erlap)e(Rules)0 +3586 y Fg(In)g(order)g(for)g(CIF)h(generation)f(and)g(circuit)f(e)o +(xtraction)g(to)g(w)o(ork)h(properly)-6 b(,)30 b(certain)g(kinds)f(of)h +(o)o(v)o(erlaps)f(be-)0 3707 y(tween)34 b(subcells)f(must)f(be)i +(prohibited.)56 b(The)34 b(design-rule)f(check)o(er)i(pro)o(vides)d(tw) +o(o)h(kinds)g(of)h(rules)f(for)h(re-)0 3827 y(stricting)23 +b(o)o(v)o(erlaps.)30 b(The)o(y)24 b(are)900 4072 y Fd(exact)p +1127 4072 30 4 v 36 w(o)o(v)o(erlap)h Fh(type-list)900 +4192 y Fd(no)p 1011 4192 V 36 w(o)o(v)o(erlap)g Fh(type-list1)f +(type-list2)146 4435 y Fg(In)k(the)f Fd(exact)p 633 4435 +V 37 w(o)o(v)o(erlap)g Fg(rule,)h Fh(type-list)f Fg(indicates)g(one)g +(or)h(more)g(tile)f(types.)38 b(If)28 b(a)g(cell)f(contains)g(a)h(tile) +f(of)0 4555 y(one)e(of)g(these)g(types)f(and)h(that)g(tile)f(is)h(o)o +(v)o(erlapped)f(by)h(another)f(tile)h(of)g(the)g(same)g(type)f(from)h +(a)h(dif)n(ferent)e(cell,)0 4676 y(then)29 b(the)g(o)o(v)o(erlap)f +(must)g(be)h(e)o(xact:)39 b(the)29 b(tile)f(in)h(each)h(cell)f(must)f +(co)o(v)o(er)h(e)o(xactly)f(the)h(same)g(area.)44 b(Ab)n(utment)0 +4796 y(between)39 b(tiles)f(from)g(dif)n(ferent)g(cells)h(is)f +(considered)g(to)h(be)f(a)h(partial)g(o)o(v)o(erlap,)i(so)d(it)g(is)g +(prohibited)g(too.)0 4916 y(This)g(rule)h(is)f(used)g(to)h(ensure)g +(that)f(the)h(CIF)g Fd(squar)n(es)h Fg(operator)f(will)f(w)o(ork)g +(correctly)-6 b(,)42 b(as)d(described)f(in)0 5037 y(Section)25 +b(12.6.)30 b(See)c(T)-8 b(able)24 b(18)h(for)g(the)g +Fd(exact)p 1606 5037 V 36 w(o)o(v)o(erlap)g Fg(rule)g(from)f(the)h +(standard)f(scmos)g(technology)g(\002le.)146 5159 y(The)19 +b Fd(no)p 431 5159 V 36 w(o)o(v)o(erlap)g Fg(rule)g(mak)o(es)g(ille)o +(gal)e(an)o(y)h(o)o(v)o(erlap)g(between)h(a)g(tile)g(in)f +Fh(type-list1)g Fg(and)h(a)g(tile)g(in)f Fh(type-list2)p +Fg(.)0 5280 y(Y)-11 b(ou)29 b(should)f(rarely)-6 b(,)30 +b(if)g(e)n(v)o(er)l(,)g(need)f(to)g(specify)g Fd(no)p +1828 5280 V 36 w(o)o(v)o(erlap)h Fg(rules,)g(since)f(Magic)g +(automatically)f(prohibits)0 5400 y(man)o(y)g(kinds)g(of)h(o)o(v)o +(erlaps)e(between)i(subcells.)42 b(After)29 b(reading)g(the)g +(technology)f(\002le,)i(Magic)e(e)o(xamines)g(the)1850 +5649 y(\22639\226)p eop end +%%Page: 40 40 +TeXDict begin 40 39 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)p 970 3 1960 4 +v 968 124 4 121 v 1020 88 a(e)o(xact)p 1235 88 30 4 v +35 w(o)o(v)o(erlap)99 b(m2c,ndc,pdc,pc,ppcont,nncont)p +2928 124 4 121 v 968 244 V 1020 208 a(no)p 1126 208 30 +4 v 35 w(o)o(v)o(erlap)208 b(pfet,nfet)99 b(pfet,nfet)p +2928 244 4 121 v 970 247 1960 4 v 1006 407 a(T)-8 b(able)25 +b(18:)30 b(Exact)p 1641 407 30 4 v 36 w(o)o(v)o(erlap)23 +b(rule)i(in)f(the)h Fd(dr)n(c)h Fg(section.)0 777 y(paint)34 +b(table)h(and)g(applies)f(the)h(follo)n(wing)e(rule:)51 +b(if)35 b(tw)o(o)g(tile)f(types)g(A)h(and)g(B)h(are)g(such)e(that)h +(the)g(result)f(of)0 897 y(painting)h(A)i(o)o(v)o(er)e(B)i(is)f +(neither)g(A)h(nor)f(B,)h(or)g(the)f(result)g(of)g(painting)f(B)i(o)o +(v)o(er)f(A)g(isn')n(t)g(the)g(same)h(as)f(the)0 1017 +y(result)24 b(of)h(painting)e(A)i(o)o(v)o(er)f(B,)h(then)g(A)f(and)h(B) +g(are)h(not)e(allo)n(wed)g(to)g(o)o(v)o(erlap.)30 b(Such)25 +b(o)o(v)o(erlaps)e(are)i(prohibited)0 1138 y(because)36 +b(the)o(y)e(change)h(the)g(structure)g(of)g(the)g(circuit.)61 +b(Ov)o(erlaps)35 b(are)g(supposed)f(only)h(to)f(connect)h(things)0 +1258 y(without)20 b(making)g(structural)h(changes.)29 +b(Thus,)21 b(for)h(e)o(xample,)f(poly)f(can)i(o)o(v)o(erlap)e(pcontact) +h(without)f(violating)0 1379 y(the)k(abo)o(v)o(e)f(rules,)g(b)n(ut)h +(poly)f(may)g(not)g(o)o(v)o(erlap)g(dif)n(fusion)f(because)j(the)e +(result)h(is)f(efet,)h(which)g(is)f(neither)h(poly)0 +1499 y(nor)k(dif)n(fusion.)40 b(The)29 b(only)e Fd(no)p +1085 1499 V 36 w(o)o(v)o(erlap)i Fg(rules)f(you)g(should)f(need)i(to)f +(specify)g(are)i(rules)e(to)g(k)o(eep)g(transistors)0 +1619 y(from)d(o)o(v)o(erlapping)d(other)j(transistors)f(of)g(the)h +(same)g(type.)0 1936 y Ff(16.9)119 b(Backgr)n(ound)31 +b(check)o(er)g(step)e(size)0 2130 y Fg(Magic')-5 b(s)28 +b(background)g(design-rule)g(check)o(er)i(breaks)f(lar)n(ge)g(cells)g +(up)f(into)g(smaller)g(pieces,)i(checking)e(each)0 2250 +y(piece)36 b(independently)-6 b(.)62 b(F)o(or)36 b(v)o(ery)g(lar)n(ge)g +(designs,)i(the)e(number)f(of)h(pieces)g(can)g(get)g(to)g(be)g +(enormous.)63 b(If)0 2371 y(designs)26 b(are)h(lar)n(ge)g(b)n(ut)f +(sparse,)h(the)g(performance)g(of)g(the)f(design-rule)g(check)o(er)i +(can)f(be)g(impro)o(v)o(ed)d(tremen-)0 2491 y(dously)g(by)g(telling)g +(it)g(to)g(use)h(a)g(lar)n(ger)h(step)e(size)h(for)g(breaking)f(up)h +(cells.)30 b(This)24 b(is)h(done)f(as)h(follo)n(ws:)900 +2746 y Fd(stepsize)g Fh(stepsize)146 2997 y Fg(which)30 +b(causes)h(each)f(cell)h(to)f(be)g(processed)g(in)g(square)h(pieces)f +(of)g(at)h(most)e Fh(stepsize)g Fg(by)h Fh(stepsize)f +Fg(units.)0 3117 y(It)e(is)f(generally)g(a)h(good)g(idea)f(to)h(pick)f +(a)h(lar)n(ge)g Fh(stepsize)p Fg(,)f(b)n(ut)g(one)h(that)f(is)h(small)e +(enough)h(so)h(each)g(piece)g(will)0 3238 y(contain)d(no)h(more)f(than) +h(100)f(to)h(1000)f(rectangles.)146 3361 y(Note)d(that)e(the)i +(distances)e(declared)i(in)f(the)h(DRC)g(section)f(are)h(used)f(to)g +(determine)g(the)g(\223halo\224)h(of)f(possible)0 3482 +y(interactions)35 b(around)g(a)h(tile)f(edge.)63 b(Magic)35 +b(must)g(consider)g(all)g(paint)g(in)g(all)h(cells)f(simultaneously;)j +(thus)0 3602 y(for)h(each)h(edge)g(in)e(the)i(design,)h(magic)e(must)f +(\003atten)i(the)f(hierarchy)g(around)g(it)f(to)h(a)h(distance)e(equal) +h(to)0 3722 y(the)e(interaction)g(halo.)68 b(Clearly)37 +b(this)g(has)g(a)h(huge)f(impact)g(on)g(processing)f(time.)68 +b(Because)38 b(the)f(DRC)i(is)0 3843 y(interacti)n(v)o(e,)28 +b(the)g(performance)h(hit)e(can)i(be)f(noticeable)g(to)g(do)n(wnright)e +(irritating.)40 b(Often)28 b(this)g(performance)0 3963 +y(hit)c(can)g(be)h(greatly)e(reduced)i(by)f(remo)o(ving)f(rules)h(with) +f(lar)n(ge)i(distance)f(measures,)g(such)g(as)g(rules)g(in)l(v)n +(olving)0 4084 y(distances)k(to)g(pads,)h(and)f(widespacing)g(rules.)42 +b(If)28 b(this)g(is)g(a)h(problem,)f(consider)g(using)g(one)g +(technology)g(\002le)0 4204 y(for)h(layout,)g(and)g(one)g(which)g(can)g +(be)g(used)g(\223of)n(\003ine\224)g(to)f(do)h(a)g(slo)n(w)-6 +b(,)29 b(non-interacti)n(v)o(e)e(DRC)j(check)f(for)g(pad)0 +4324 y(and)c(widespacing)f(rules)g(on)h(an)g(entire)g(project)f +(layout.)0 4685 y Fi(17)143 b(Extract)34 b(section)0 +4915 y Fg(The)25 b Fd(extract)g Fg(section)f(of)h(a)g(technology)e +(\002le)i(contains)f(the)h(parameters)f(used)h(by)f(Magic')-5 +b(s)24 b(circuit)g(e)o(xtractor)-5 b(.)0 5036 y(Each)25 +b(line)f(in)g(this)f(section)h(be)o(gins)f(with)h(a)h(k)o(e)o(yw)o(ord) +f(that)g(determines)f(the)i(interpretation)e(of)i(the)f(remainder)0 +5156 y(of)h(the)g(line.)30 b(T)-8 b(able)25 b(19)f(gi)n(v)o(es)f(an)i +(e)o(xample)f Fd(extract)i Fg(section.)146 5280 y(This)k(section)g(is)h +(lik)o(e)f(the)h Fd(ci\002nput)h Fg(and)f Fd(cif)n(output)h +Fg(sections)e(in)g(that)g(it)h(supports)e(multiple)g(e)o(xtraction)0 +5400 y(styles.)h(Each)25 b(style)f(is)g(preceded)i(by)e(a)h(line)g(of)g +(the)f(form)1850 5649 y(\22640\226)p eop end +%%Page: 41 41 +TeXDict begin 41 40 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)p 854 7 2192 4 +v 852 127 4 121 v 904 91 a Fd(extract)p 3044 127 V 852 +248 V 904 212 a Fg(style)367 b(lambda=0.7)p 3044 248 +V 852 368 V 904 332 a(lambda)262 b(70)p 3044 368 V 852 +488 V 904 452 a(step)395 b(100)p 3044 488 V 852 609 V +904 573 a(sidehalo)223 b(4)p 3044 609 V 852 729 V 3044 +729 V 852 820 V 904 783 a(resist)345 b(poly)-6 b(,pfet,nfet)23 +b(60000)p 3044 820 V 852 940 V 904 904 a(resist)345 b(pc/a)25 +b(50000)p 3044 940 V 852 1060 V 904 1024 a(resist)345 +b(pdif)n(f,ppd)23 b(120000)p 3044 1060 V 852 1181 V 904 +1145 a(resist)345 b(ndif)n(f,nnd)23 b(120000)p 3044 1181 +V 852 1301 V 904 1265 a(resist)345 b(m2contact/m1)23 +b(1200)p 3044 1301 V 852 1421 V 904 1385 a(resist)345 +b(metal1)24 b(200)p 3044 1421 V 852 1542 V 904 1506 a(resist)345 +b(metal2,pad/m1)23 b(60)p 3044 1542 V 852 1662 V 904 +1626 a(resist)345 b(ppc/a,pdc/a)24 b(100000)p 3044 1662 +V 852 1783 V 904 1747 a(resist)345 b(nnc/a,ndc/a)24 b(100000)p +3044 1783 V 852 1903 V 904 1867 a(resist)345 b(nwell,pwell)24 +b(3000000)p 3044 1903 V 852 2023 V 3044 2023 V 852 2114 +V 904 2078 a(areacap)253 b(poly)24 b(33)p 3044 2114 V +852 2234 V 904 2198 a(areacap)253 b(metal1)24 b(17)p +3044 2234 V 852 2355 V 904 2318 a(areacap)253 b(metal2,pad/m1)23 +b(11)p 3044 2355 V 852 2475 V 904 2439 a(areacap)253 +b(ndif)n(f,nsd)23 b(350)p 3044 2475 V 852 2595 V 904 +2559 a(areacap)253 b(pdif)n(f,psd)23 b(200)p 3044 2595 +V 852 2716 V 904 2680 a(areacap)253 b(ndc/a,nsc/a)24 +b(367)p 3044 2716 V 852 2836 V 904 2800 a(areacap)253 +b(pdc/a,psc/a)24 b(217)p 3044 2836 V 852 2956 V 904 2920 +a(areacap)253 b(pcontact/a)24 b(50)p 3044 2956 V 852 +3077 V 3044 3077 V 852 3167 V 904 3131 a(perimc)279 b(allMetal1)24 +b(space)h(56)p 3044 3167 V 852 3288 V 904 3251 a(perimc)279 +b(allMetal2)24 b(space)h(55)p 3044 3288 V 852 3408 V +3044 3408 V 852 3498 V 904 3462 a(o)o(v)o(erlap)259 b(metal1)24 +b(pdif)n(f,ndif)n(f,psd,nsd)e(33)p 3044 3498 V 852 3619 +V 904 3583 a(o)o(v)o(erlap)259 b(metal2)24 b(pdif)n(f,ndif)n(f,psd,nsd) +e(17)i(metal1)p 3044 3619 V 852 3739 V 904 3703 a(o)o(v)o(erlap)259 +b(metal1)24 b(poly)g(33)p 3044 3739 V 852 3860 V 904 +3823 a(o)o(v)o(erlap)259 b(metal2)24 b(poly)g(17)h(metal1)p +3044 3860 V 852 3980 V 904 3944 a(o)o(v)o(erlap)259 b(metal2)24 +b(metal1)g(33)p 3044 3980 V 852 4100 V 3044 4100 V 852 +4191 V 904 4155 a(sideo)o(v)o(erlap)98 b(allMetal1)24 +b(space)h(allDif)n(f)f(64)p 3044 4191 V 852 4311 V 904 +4275 a(sideo)o(v)o(erlap)98 b(allMetal2)24 b(space)h(allDif)n(f)f(60)p +3044 4311 V 852 4431 V 904 4395 a(sideo)o(v)o(erlap)98 +b(allMetal1)24 b(space)h(poly)f(64)p 3044 4431 V 852 +4552 V 904 4516 a(sideo)o(v)o(erlap)98 b(allMetal2)24 +b(space)h(poly)f(60)p 3044 4552 V 852 4672 V 904 4636 +a(sideo)o(v)o(erlap)98 b(allMetal2)24 b(space)h(allMetal1)f(70)p +3044 4672 V 852 4793 V 3044 4793 V 852 4883 V 904 4847 +a(fet)451 b(pfet)25 b(pdif)n(f,pdc/a)f(2)g(pfet)h(Vdd!)31 +b(nwell)24 b(0)h(0)p 3044 4883 V 852 5003 V 904 4967 +a(fet)451 b(nfet)25 b(ndif)n(f,ndc/a)f(2)g(nfet)h(GND!)g(pwell)f(0)h(0) +p 3044 5003 V 852 5124 V 904 5088 a Fd(end)p 3044 5124 +V 854 5127 2192 4 v 1423 5286 a Fg(T)-8 b(able)24 b(19:)31 +b Fd(Extract)25 b Fg(section.)1850 5649 y(\22641\226)p +eop end +%%Page: 42 42 +TeXDict begin 42 41 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)900 84 y Fd(style)h +Fh(stylename)146 297 y Fg(All)32 b(subsequent)f(lines)h(up)g(to)g(the)g +(ne)o(xt)g Fd(style)g Fg(line)g(or)g(the)g(end)h(of)f(the)g(section)g +(are)h(interpreted)f(as)h(be-)0 418 y(longing)27 b(to)h(e)o(xtraction)f +(style)h Fh(stylename)p Fg(.)41 b(If)29 b(there)f(is)g(no)g(initial)f +Fd(style)h Fg(line,)h(the)f(\002rst)h(style)e(will)h(be)g(named)0 +538 y(\223def)o(ault\224.)146 658 y(The)d(k)o(e)o(yw)o(ords)f +Fd(ar)n(eacap)p Fg(,)i Fd(perimcap)p Fg(,)g(and)e Fd(r)n(esist)h +Fg(de\002ne)h(the)f(capacitance)g(to)g(substrate)f(and)h(the)f(sheet)0 +779 y(resisti)n(vity)f(of)j(each)h(of)e(the)h(Magic)f(layers)h(in)f(a)h +(layout.)33 b(All)25 b(capacitances)i(that)e(appear)h(in)g(the)f +Fd(extract)i Fg(sec-)0 899 y(tion)20 b(are)h(speci\002ed)g(as)f(an)h +(inte)o(gral)e(number)h(of)h(attof)o(arads)g(\(per)g(unit)e(area)j(or)e +(perimeter\),)i(and)e(all)g(resistances)0 1020 y(as)25 +b(an)g(inte)o(gral)f(number)g(of)h(milliohms)d(per)j(square.)146 +1140 y(The)g Fd(ar)n(eacap)h Fg(k)o(e)o(yw)o(ord)e(is)g(follo)n(wed)g +(by)g(a)h(list)f(of)h(types)f(and)h(a)g(capacitance)h(to)e(substrate,)g +(as)h(follo)n(ws:)900 1353 y Fd(ar)n(eacap)h Fh(types)e(C)146 +1566 y Fg(Each)40 b(of)g(the)g(types)f(listed)g(in)h +Fh(types)f Fg(has)h(a)g(capacitance)h(to)e(substrate)h(of)g +Fh(C)g Fg(attof)o(arads)g(per)g(square)0 1686 y(lambda.)67 +b(Each)38 b(type)f(can)g(appear)h(in)f(at)g(most)f(one)h +Fd(ar)n(eacap)h Fg(line.)68 b(If)37 b(a)h(type)f(does)f(not)h(appear)h +(in)f(an)o(y)0 1807 y Fd(ar)n(eacap)i Fg(line,)j(it)c(is)g(considered)h +(to)f(ha)n(v)o(e)g(zero)i(capacitance)f(to)f(substrate)g(per)h(unit)f +(area.)73 b(Since)39 b(most)0 1927 y(analysis)32 b(tools)f(compute)h +(transistor)f(gate)h(capacitance)h(directly)f(from)g(the)h(area)g(of)g +(the)f(transistor')-5 b(s)31 b(gate,)0 2048 y(Magic)25 +b(should)g(produce)g(node)g(capacitances)i(that)e(do)g(not)g(include)g +(gate)g(capacitances.)34 b(T)-8 b(o)25 b(ensure)h(this,)e(all)0 +2168 y(transistors)f(should)h(ha)n(v)o(e)h(zero)g Fd(ar)n(eacap)h +Fg(v)n(alues.)146 2288 y(The)c Fd(perimcap)g Fg(k)o(e)o(yw)o(ord)f(is)g +(follo)n(wed)f(by)h(tw)o(o)g(type-lists)f(and)h(a)h(capacitance)g(to)f +(substrate,)g(as)h(follo)n(ws:)900 2501 y Fd(perimcap)k +Fh(intypes)e(outtypes)g(C)146 2714 y Fg(Each)32 b(edge)f(that)g(has)g +(one)g(of)h(the)f(types)f(in)h Fh(intypes)g Fg(on)g(its)f(inside,)i +(and)f(one)g(of)g(the)h(types)e(in)h Fh(outtypes)0 2835 +y Fg(on)h(its)g(outside,)i(has)e(a)h(capacitance)h(to)e(substrate)g(of) +h Fh(C)g Fg(attof)o(arads)g(per)g(lambda.)53 b(This)32 +b(can)h(also)g(be)f(used)0 2955 y(as)h(an)h(approximation)d(of)i(the)g +(ef)n(fects)h(due)f(to)f(the)h(side)n(w)o(alls)f(of)h(dif)n(fused)g +(areas.)56 b(As)33 b(for)g Fd(ar)n(eacap)p Fg(,)j(each)0 +3076 y(unique)22 b(combination)g(of)h(an)g Fh(intype)f +Fg(and)h(an)g Fh(outtype)g Fg(may)f(appear)i(at)f(most)f(once)h(in)g(a) +g Fd(perimcap)h Fg(line.)30 b(Also)0 3196 y(as)g(for)f +Fd(ar)n(eacap)p Fg(,)j(if)d(a)h(combination)e(of)h Fh(intype)g +Fg(and)h Fh(outtype)f Fg(does)g(not)g(appear)h(in)f(an)o(y)g +Fd(perimcap)i Fg(line,)f(its)0 3316 y(perimeter)25 b(capacitance)g(per) +g(unit)f(length)g(is)h(zero.)146 3437 y(The)g Fd(r)n(esist)g +Fg(k)o(e)o(yw)o(ord)f(is)g(follo)n(wed)g(by)h(a)g(type-list)e(and)i(a)g +(resistance)g(as)g(follo)n(ws:)900 3650 y Fd(r)n(esist)g +Fh(types)g(R)146 3863 y Fg(The)g(sheet)g(resisti)n(vity)d(of)j(each)h +(of)e(the)h(types)f(in)h Fh(types)f Fg(is)h Fh(R)f Fg(milliohms)f(per)i +(square.)146 3983 y(Each)32 b Fd(r)n(esist)f Fg(line)g(in)g(f)o(act)h +(de\002nes)g(a)f(\223resistance)h(class\224.)50 b(When)32 +b(the)f(e)o(xtractor)g(outputs)f(the)h(area)h(and)0 4104 +y(perimeter)d(of)g(nodes)g(in)g(the)g Fd(.ext)h Fg(\002le,)g(it)f(does) +g(so)g(for)h(each)g(resistance)f(class.)44 b(Normally)-6 +b(,)28 b(each)i(resistance)0 4224 y(class)e(consists)f(of)h(all)g +(types)g(with)g(the)g(same)g(resistance.)41 b(Ho)n(we)n(v)o(er)l(,)28 +b(if)g(you)g(wish)g(to)g(obtain)f(the)h(perimeter)0 4344 +y(and)c(area)g(of)g(each)g(type)g(separately)f(in)h(the)f +Fd(.ext)h Fg(\002le,)g(you)g(should)e(mak)o(e)i(each)g(into)f(its)g(o)n +(wn)g(resistance)g(class)0 4465 y(by)i(using)e(a)i(separate)h +Fd(r)n(esist)f Fg(line)f(for)h(each)h(type.)146 4585 +y(In)33 b(addition)f(to)h(sheet)f(resisti)n(vities,)h(there)g(are)h(tw) +o(o)e(other)h(w)o(ays)g(of)g(specifying)f(resistances.)55 +b(Neither)0 4705 y(is)36 b(used)g(by)g(the)g(normal)g(Magic)g(e)o +(xtractor)l(,)i(b)n(ut)e(both)g(are)h(used)f(by)g(the)g(resistance)g(e) +o(xtractor)-5 b(.)64 b(Contacts)0 4826 y(ha)n(v)o(e)27 +b(a)h(resistance)f(that)g(is)g(in)l(v)o(ersely)g(proportional)f(to)h +(the)g(number)g(of)h(via)f(holes)g(in)g(the)h(contact,)f(which)h(is)0 +4946 y(proportional)d(\(albeit)h(with)f(quantization\))g(to)h(the)h +(area)g(of)f(the)g(contact.)35 b(The)27 b Fd(contact)g +Fg(k)o(e)o(yw)o(ord)e(allo)n(ws)g(the)0 5067 y(resistance)g(for)g(a)g +(single)f(via)g(hole)h(to)f(be)h(speci\002ed:)900 5280 +y Fd(contact)h Fh(types)e(size)h(R)900 5400 y Fd(contact)h +Fh(types)e(size)h(bor)l(der)f(separ)o(ation)f(R)1850 +5649 y Fg(\22642\226)p eop end +%%Page: 43 43 +TeXDict begin 43 42 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)146 68 y(where)k +Fh(types)g Fg(is)f(a)h(comma-separated)f(list)f(of)i(types,)g +Fh(size)f Fg(is)g(in)g(lambda,)h(and)g Fh(R)f Fg(is)g(in)g(milliohms.) +40 b Fh(Size)0 188 y Fg(is)23 b(interpreted)h(as)g(a)g(hole-size)g +(quantum;)f(the)g(number)h(of)g(holes)f(in)h(a)g(contact)g(is)f(equal)h +(to)f(its)h(width)f(di)n(vided)0 309 y(by)30 b Fh(size)f +Fg(times)g(its)g(length)g(di)n(vided)f(by)i Fh(size)p +Fg(,)g(with)g(both)f(quotients)f(rounded)h(do)n(wn)g(to)h(the)f +(nearest)h(inte)o(ger)-5 b(.)0 429 y(The)25 b(resistance)g(of)f(a)i +(contact)e(is)h Fh(R)f Fg(di)n(vided)g(by)g(the)h(number)f(of)h(holes.) +146 549 y(Note)h(that)f(the)h Fh(size)g Fg(alone)f(may)h(not)f(compute) +g(the)h(same)g(number)f(of)h(contact)g(cuts)f(as)h(w)o(ould)f(be)i +(gener)n(-)0 670 y(ated)20 b(by)h(the)f Fh(cifoutput)e +Fg(command,)j(since)f(it)g(has)g(no)g(understaning)f(of)i(border)f(and) +g(separation,)h(and)f(therefore)0 790 y(may)29 b(compute)g(an)h +(incorrect)g(contact)f(resistance.)45 b(T)-8 b(o)30 b(a)n(v)n(oid)f +(this)f(problem,)i(the)g(second)f(form)g(pro)o(vides)g(a)0 +911 y(w)o(ay)35 b(to)f(gi)n(v)o(e)f(v)n(alues)h(for)g +Fh(bor)l(der)g Fg(and)h Fh(separ)o(ation)p Fg(,)g(again)f(in)g(units)f +(of)i(lambda.)59 b(There)35 b(is)f(no)g(automatic)0 1031 +y(check)24 b(to)f(guarantee)h(that)g(the)f(e)o(xtract)h(and)f +(cifoutput)g(sections)g(agree)h(on)g(the)f(number)g(of)h(contact)g +(cuts)f(for)h(a)0 1151 y(gi)n(v)o(en)f(contact)i(area.)146 +1272 y(T)m(ransistors)38 b(also)h(ha)n(v)o(e)g(resistance)h +(information)e(associated)h(with)f(them.)74 b(Ho)n(we)n(v)o(er)l(,)42 +b(a)e(transistor')-5 b(s)0 1392 y(resistance)23 b(may)f(v)n(ary)g +(depending)g(on)g(a)h(number)f(of)h(v)n(ariables,)f(so)g(a)h(single)f +(parameter)h(is)f(generally)h(insuf)n(\002-)0 1513 y(cient)h(to)f +(describe)h(it.)30 b(The)24 b Fd(fetr)n(esist)h Fg(line)e(allo)n(ws)g +(sheet)h(resisti)n(vities)d(to)j(be)g(gi)n(v)o(en)f(for)h(a)g(v)n +(ariety)f(of)h(dif)n(ferent)0 1633 y(con\002gurations:)900 +1859 y Fd(fetr)n(esist)i Fh(fettypes)e(r)l(e)l(gion)g(R)146 +2086 y Fg(where)38 b Fh(fettypes)f Fg(is)f(a)i(comma-separated)f(list)f +(of)h(transistor)f(types)h(\(as)g(de\002ned)h(in)f Fd(fet)g +Fg(lines)g(belo)n(w\),)0 2206 y Fh(r)l(e)l(gion)20 b +Fg(is)g(a)h(string)e(used)h(to)h(distinguish)c(between)k(resistance)f +(v)n(alues)g(for)h(a)f(fet)h(if)g(more)f(than)g(one)g(is)g(pro)o(vided) +0 2327 y(\(the)38 b(special)g Fh(r)l(e)l(gion)g Fg(v)n(alue)g(of)g +(\223)p Fd(linear)p Fg(\224)h(is)f(required)g(for)g(the)g(resistance)h +(e)o(xtractor\),)i(and)d Fh(R)g Fg(is)g(the)g(on-)0 2447 +y(resistance)25 b(of)h(the)f(transistor)f(in)h(ohms)g(per)g(square)h +(\()p Fh(not)f Fg(milliohms;)e(there)i(w)o(ould)g(otherwise)g(be)g(too) +g(man)o(y)0 2568 y(zeroes\).)146 2688 y(Magic)c(also)g(e)o(xtracts)g +(internodal)g(coupling)f(capacitances,)i(as)g(illustrated)e(in)h +(Figure)g(12.)30 b(The)21 b(k)o(e)o(yw)o(ords)0 2808 +y Fd(o)o(v)o(erlap)p Fg(,)k Fd(sidewall)p Fg(,)f Fd(sideo)o(v)o(erlap)p +Fg(,)h(and)f Fd(sidehalo)h Fg(pro)o(vide)f(the)h(parameters)g(needed)g +(to)f(do)h(this.)146 2929 y(Ov)o(erlap)f(capacitance)i(is)e(between)h +(pairs)f(of)h(tile)f(types,)g(and)h(is)f(described)g(by)h(the)f +Fd(o)o(v)o(erlap)h Fg(k)o(e)o(yw)o(ord)f(as)0 3049 y(follo)n(ws:)900 +3276 y Fd(o)o(v)o(erlap)h Fh(toptypes)f(bottomtypes)f(cap)i +Fg([)p Fh(shieldtypes)p Fg(])146 3502 y(where)h Fh(toptypes)p +Fg(,)f Fh(bottomtypes)p Fg(,)f(and)h(optionally)f Fh(shieldtypes)g +Fg(are)i(type-lists)e(and)h Fh(cap)h Fg(is)f(a)g(capacitance)0 +3623 y(in)k(attof)o(arads)g(per)g(square)g(lambda.)43 +b(The)29 b(e)o(xtractor)g(searches)h(for)f(tiles)g(whose)f(types)h(are) +h(in)e Fh(toptypes)h Fg(that)0 3743 y(o)o(v)o(erlap)i(tiles)g(whose)h +(types)g(are)h(in)f Fh(bottomtypes)p Fg(,)g(and)g(that)g(belong)g(to)f +(dif)n(ferent)h(electrical)h(nodes.)52 b(\(The)0 3863 +y(planes)28 b(of)h Fh(toptypes)f Fg(and)g Fh(bottomtypes)f +Fg(must)h(be)g(disjoint\).)41 b(When)28 b(such)g(an)h(o)o(v)o(erlap)f +(is)g(found,)h(the)f(capac-)0 3984 y(itance)j(to)f(substrate)h(of)g +(the)f(node)h(of)g(the)g(tile)f(in)h Fh(toptypes)f Fg(is)g(deducted)h +(for)g(the)g(area)h(of)f(the)g(o)o(v)o(erlap,)g(and)0 +4104 y(replaced)25 b(by)g(a)g(capacitance)h(to)e(the)h(node)f(of)h(the) +g(tile)f(in)g Fh(bottomtypes)p Fg(.)146 4225 y(If)g Fh(shieldtypes)d +Fg(are)j(speci\002ed,)f(o)o(v)o(erlaps)f(between)h Fh(toptypes)f +Fg(and)g Fh(bottomtypes)g Fg(that)g(also)h(o)o(v)o(erlap)e(a)i(type)0 +4345 y(in)d Fh(shieldtypes)g Fg(are)h(not)f(counted.)29 +b(The)21 b(types)f(in)g Fh(shieldtypes)g Fg(must)g(appear)h(on)f(a)h +(dif)n(ferent)g(plane)f(\(or)h(planes\))0 4465 y(than)j(an)o(y)h(of)g +(the)f(types)g(in)h Fh(toptypes)f Fg(or)h Fh(bottomtypes)p +Fg(.)146 4586 y(P)o(arallel)g(wire)g(capacitance)h(is)e(between)h +(pairs)f(of)h(edges,)g(and)g(is)f(described)h(by)f(the)h +Fd(sidewall)f Fg(k)o(e)o(yw)o(ord:)900 4812 y Fd(sidewall)g +Fh(intypes)g(outtypes)g(neartypes)g(fartypes)g(cap)146 +5039 y Fg(where)j Fh(intypes)p Fg(,)e Fh(outtypes)p Fg(,)g +Fh(neartypes)p Fg(,)h(and)g Fh(fartypes)f Fg(are)i(all)e(type-lists,)g +(described)g(in)h(Figure)g(13.)34 b Fh(Cap)0 5159 y Fg(is)28 +b(half)g(the)h(capacitance)g(in)f(attof)o(arads)g(per)h(lambda)f(when)g +(the)g(edges)h(are)g(1)f(lambda)g(apart.)42 b(P)o(arallel)28 +b(wire)0 5280 y(coupling)37 b(capacitance)j(is)e(computed)g(as)g(being) +g(in)l(v)o(ersely)g(proportional)f(to)h(the)h(distance)f(between)h(tw)o +(o)0 5400 y(edges:)48 b(at)34 b(2)f(lambda)g(separation,)j(it)d(is)g +(equal)h(to)f(the)g(v)n(alue)h Fh(cap)p Fg(;)j(at)d(4)g(lambda)f +(separation,)i(it)e(is)g(half)h(of)1850 5649 y(\22643\226)p +eop end +%%Page: 44 44 +TeXDict begin 44 43 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)780 990 y @beginspecial +68 @llx 68 @lly 484 @urx 244 @ury 2808 @rwi @setspecial +%%BeginDocument: ../psfigures/tut8.4.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tut8.4 +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 15:06:26 2000 +%%Pages: 1 +%%BoundingBox: 68 68 484 244 +%%DocumentNeededResources: font Times-Roman font Times-Italic +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 928 256 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.490 0.651 0.980 scb +192 480 beginpath +544 608 544 480 2 polyc +512 608 32 0.00 90.00 arc +192 640 1 polyc +240 1.00 endpath +1280 480 beginpath +928 608 928 480 2 polyc +960 608 32 180.00 90.00 arcn +1280 640 1 polyc +240 1.00 endpath +sce +1.000 0.000 0.000 scb +192 192 beginpath +1120 320 1120 192 2 polyc +1088 320 32 0.00 90.00 arc +192 352 1 polyc +240 1.00 endpath +sce +192 480 beginpath +544 608 544 480 2 polyc +512 608 32 0.00 90.00 arc +192 640 1 polyc +1 1.00 endpath +1280 480 beginpath +928 608 928 480 2 polyc +960 608 32 180.00 90.00 arcn +1280 640 1 polyc +1 1.00 endpath +192 192 beginpath +1120 320 1120 192 2 polyc +1088 320 32 0.00 90.00 arc +192 352 1 polyc +1 1.00 endpath +(\(metal\)) {/Times-Roman 1.000 cf} 2 21 0 352 560 label +(\(metal\)) {/Times-Roman 1.000 cf} 2 21 0 1120 560 label +(\(poly\)) {/Times-Roman 1.000 cf} 2 21 0 656 272 label +(sidewall overlap) {/Times-Italic 1.000 cf} 2 21 0 688 448 label +(sidewall) {/Times-Italic 1.000 cf} 2 21 0 720 576 label +(overlap) {/Times-Roman 1.000 cf} 2 21 0 352 424 label +(\(oxide\)) {/Times-Roman 1.000 cf} 2 21 0 1024 416 label +1.00 0 560 576 arrowhead90 +1.00 -1 912 576 arrowhead90 +1.00 0 560 512 arrowhead90 +1.00 -91 688 368 arrowhead90 +1 1.00 560 576 640 576 2 polygon +1 1.00 912 576 800 576 2 polygon +1 1.00 560 512 688 512 688 480 3 polygon +1 1.00 688 416 688 368 2 polygon +1.00 -91 352 368 arrowhead90 +1.00 270 352 464 arrowhead90 +1 1.00 352 432 352 464 2 polygon +1 1.00 352 368 352 400 2 polygon +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 1193 a(Figure)e(12:)28 b(Magic)21 b(e)o(xtracts)g(three) +g(kinds)g(of)g(internodal)g(coupling)f(capacitance.)30 +b(This)20 b(\002gure)i(is)f(a)h(side)f(vie)n(w)0 1314 +y(of)30 b(a)g(set)f(of)h(masks)f(that)g(sho)n(ws)g(all)g(three)h(kinds) +f(of)h(capacitance.)46 b Fh(Overlap)30 b Fg(capacitance)g(is)f +(parallel-plate)0 1434 y(capacitance)e(between)g(tw)o(o)f(dif)n(ferent) +g(kinds)f(of)i(material)e(when)i(the)o(y)e(o)o(v)o(erlap.)35 +b Fh(P)-8 b(ar)o(allel)24 b(wir)l(e)j Fg(capacitance)0 +1555 y(is)22 b(fringing-\002eld)g(capacitance)i(between)f(the)f +(parallel)h(v)o(ertical)f(edges)h(of)g(tw)o(o)f(pieces)h(of)g +(material.)29 b Fh(Side)o(wall)0 1675 y(o)o(verlap)21 +b Fg(capacitance)i(is)e(fringing-\002eld)g(capacitance)i(between)e(the) +h(v)o(ertical)f(edge)h(of)g(one)g(piece)g(of)g(material)0 +1795 y(and)j(the)f(horizontal)g(surf)o(ace)i(of)f(another)f(piece)i(of) +e(material)h(that)f(o)o(v)o(erlaps)g(the)g(v)o(ertical)g(edge.)1306 +3160 y @beginspecial 68 @llx 68 @lly 292 @urx 268 @ury +1544 @rwi @setspecial +%%BeginDocument: ../psfigures/maint2.11.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: maint2.11.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Tue Apr 18 12:05:00 2000 +%%Pages: 1 +%%BoundingBox: 68 68 292 268 +%%DocumentNeededResources: font Helvetica-Oblique +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 672 288 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.490 0.651 0.980 scb +240 1.00 320 480 320 704 608 704 608 480 4 polygon +sce +0.745 0.600 0.871 scb +240 1.00 192 192 192 320 768 320 768 192 4 polygon +sce +1 1.00 320 704 320 480 608 480 608 704 4 polygon +1 1.00 192 192 192 320 768 320 768 192 4 polygon +(tfar) {/Helvetica-Oblique 1.000 cf} 2 21 0 464 592 label +(fartypes) {/Helvetica-Oblique 1.000 cf} 2 24 0 336 496 label +(neartypes) {/Helvetica-Oblique 1.000 cf} 2 28 0 336 464 label +(outtypes) {/Helvetica-Oblique 1.000 cf} 2 24 0 240 336 label +(intypes) {/Helvetica-Oblique 1.000 cf} 2 28 0 240 304 label +(tinside) {/Helvetica-Oblique 1.000 cf} 2 21 0 448 224 label +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 3364 a(Figure)30 b(13:)39 b(P)o(arallel)29 +b(wire)g(capacitance)h(is)f(between)h(pairs)f(of)g(edges.)44 +b(The)29 b(capacitance)h(applies)f(between)0 3484 y(the)35 +b(tiles)f Fh(tinside)f Fg(and)i Fh(tfar)f Fg(abo)o(v)o(e,)i(where)f +Fh(tinside)p Fg(')-5 b(s)33 b(type)h(is)h(one)f(of)h +Fh(intypes)p Fg(,)i(and)d Fh(tfar)p Fg(')-5 b(s)34 b(type)g(is)g(one)h +(of)0 3604 y Fh(fartypes)p Fg(.)0 3953 y Fh(cap)p Fg(.)30 +b(This)24 b(approximation)e(is)h(not)h(v)o(ery)f(good,)h(in)f(that)h +(it)g(tends)f(to)h(o)o(v)o(erestimate)e(the)i(coupling)e(capacitance)0 +4074 y(between)j(wires)g(that)f(are)h(f)o(arther)h(apart.)146 +4194 y(T)-8 b(o)26 b(reduce)g(the)f(amount)g(of)g(searching)h(done)f +(by)g(Magic,)h(there)g(is)f(a)g(threshold)g(distance)g(be)o(yond)g +(which)0 4314 y(the)g(ef)n(fects)g(of)f(parallel)h(wire)g(coupling)f +(capacitance)h(are)h(ignored.)k(This)24 b(is)g(set)h(as)g(follo)n(ws:) +900 4516 y Fd(sidehalo)g Fh(distance)146 4717 y Fg(where)f +Fh(distance)f Fg(is)g(the)g(maximum)f(distance)h(between)g(tw)o(o)g +(edges)g(at)h(which)f(Magic)g(considers)g(them)f(to)0 +4838 y(ha)n(v)o(e)31 b(parallel)f(wire)i(coupling)d(capacitance.)50 +b Fd(If)31 b(this)g(number)i(is)d(not)i(set)f(explicitly)g(in)g(the)h +(technology)0 4958 y(\002le,)25 b(it)g(defaults)g(to)g(0,)g(with)g(the) +h(r)n(esult)f(that)h(no)f(parallel)f(wir)n(e)i(coupling)f(capacitance)h +(is)e(computed.)146 5078 y Fg(Side)n(w)o(all)37 b(o)o(v)o(erlap)e +(capacitance)j(is)f(between)g(material)f(on)h(the)g(inside)f(of)h(an)g +(edge)g(and)g(o)o(v)o(erlapping)0 5199 y(material)24 +b(of)h(a)g(dif)n(ferent)g(type.)30 b(It)25 b(is)f(described)h(by)g(the) +f Fd(sideo)o(v)o(erlap)h Fg(k)o(e)o(yw)o(ord:)900 5400 +y Fd(sideo)o(v)o(erlap)g Fh(intypes)f(outtypes)g(o)o(vtypes)h(cap)1850 +5649 y Fg(\22644\226)p eop end +%%Page: 45 45 +TeXDict begin 45 44 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)146 68 y(where)39 +b Fh(intypes)p Fg(,)h Fh(outtypes)p Fg(,)h(and)d Fh(o)o(vtypes)g +Fg(are)g(type-lists)f(and)h Fh(cap)g Fg(is)f(capacitance)i(in)f(attof)o +(arads)g(per)0 188 y(lambda.)h(This)26 b(is)i(the)f(capacitance)h +(associated)g(with)e(an)i(edge)g(with)f(a)h(type)f(in)g +Fh(intypes)g Fg(on)h(its)e(inside)h(and)h(a)0 309 y(type)c(in)h +Fh(outtypes)f Fg(on)g(its)g(outside,)g(that)g(o)o(v)o(erlaps)g(a)h +(tile)f(whose)h(type)f(is)g(in)h Fh(o)o(vtypes)p Fg(.)30 +b(See)c(Figure)f(12.)146 429 y(De)n(vices)36 b(are)h(represented)g(in)e +(Magic)h(by)g(e)o(xplicit)f(tile)h(types.)64 b(The)36 +b(e)o(xtraction)f(of)i(a)f(de)n(vice)g(id)g(ster)n(-)0 +549 y(mined)d(by)g(the)h(declared)g(de)n(vice)g(type)f(and)h(the)f +(information)g(about)g(types)g(which)h(comprise)f(the)g(v)n(arious)0 +670 y(independent)24 b Fh(terminals)f Fg(of)i(the)g(de)n(vice.)900 +898 y Fd(de)o(vice)g(mosfet)g Fh(model)f(gate)p 1942 +898 30 4 v 36 w(types)h(sd)p 2297 898 V 35 w(types)g(subs)p +2740 898 V 35 w(types)f(subs)p 3182 898 V 35 w(node)p +3411 898 V 36 w(name)3681 898 y +/bksp 2 string def bksp 0 92 put bksp show + 3681 898 a 1200 1019 +a Fg([)p Fh(perim)p 1472 1019 30 4 v 35 w(cap)h Fg([)p +Fh(ar)l(ea)p 1888 1019 V 36 w(cap)p Fg(]])900 1139 y +Fd(de)o(vice)g(capacitor)g Fh(model)g(top)p 2015 1139 +V 35 w(types)g(bottom)p 2558 1139 V 34 w(types)g Fg([)p +Fh(perim)p 3088 1139 V 35 w(cap)p Fg(])g Fh(ar)l(ea)p +3504 1139 V 36 w(cap)900 1260 y Fd(de)o(vice)g(r)n(esistor)g +Fh(model)f(r)l(esist)p 2020 1260 V 35 w(types)h(term)p +2468 1260 V 36 w(types)900 1380 y Fd(de)o(vice)g(bjt)h +Fh(model)e(base)p 1793 1380 V 36 w(types)g(emitter)p +2341 1380 V 35 w(types)h(collector)p 2961 1380 V 35 w(types)900 +1500 y Fd(de)o(vice)g(diode)g Fh(model)g(pos)p 1860 1500 +V 35 w(types)g(ne)l(g)p 2265 1500 V 35 w(types)900 1621 +y Fd(de)o(vice)g(subcir)n(cuit)h Fh(model)f(gate)p 2085 +1621 V 35 w(types)g Fg([)p Fh(term)p 2566 1621 V 35 w(types)g +Fg([)p Fh(subs)p 3042 1621 V 35 w(types)p Fg(]])900 1741 +y Fd(de)o(vice)g(rsubcir)n(cuit)i Fh(model)d(id)p 2035 +1741 V 35 w(types)h(term)p 2483 1741 V 35 w(types)146 +1970 y Fg(Ar)n(guments)f(are)i(as)f(follo)n(ws:)145 2198 +y Fe(\017)49 b Fh(model)27 b Fg(The)g(SPICE)i(model)d(name)h(of)h(the)f +(de)n(vice.)37 b(In)28 b(the)f(case)h(of)f(a)h(subcircuit,)e(it)h(is)g +(the)g(subcircuit)244 2318 y(name.)73 b(F)o(or)39 b(resistor)g(and)g +(capacitor)g(de)n(vices)g(for)g(which)f(a)i(simple,)h(unmodeled)d(de)n +(vice)h(type)g(is)244 2439 y(needed,)25 b(the)f Fh(model)h +Fg(can)g(be)g(the)g(k)o(e)o(yw)o(ord)f Fd(None)p Fg(.)145 +2642 y Fe(\017)49 b Fh(gate)p 422 2642 V 35 w(types)25 +b Fg(Layer)g(types)f(that)h(form)f(the)h(gate)f(re)o(gion)g(of)h(a)g +(MOSFET)g(transistor)-5 b(.)145 2846 y Fe(\017)49 b Fh(sd)p +339 2846 V 35 w(types)30 b Fg(Layer)f(types)g(that)g(form)g(the)g +(source)h(and)f(drain)h(re)o(gions)e(of)h(a)h(MOSFET)g(transistor)-5 +b(.)42 b(Cur)n(-)244 2966 y(rently)24 b(there)h(is)g(no)f(w)o(ay)h(to)f +(specify)h(a)g(de)n(vice)g(with)f(asymmetric)f(source)i(and)g(drain.) +145 3170 y Fe(\017)49 b Fh(subs)p 428 3170 V 35 w(types)29 +b Fg(Layer)g(types)f(that)h(form)f(the)h(b)n(ulk)f(\(well)h(or)g +(substrate\))f(re)o(gion)g(under)h(the)f(de)n(vice.)43 +b(This)244 3290 y(can)21 b(be)g(the)g(k)o(e)o(yw)o(ord)f +Fh(None)i Fg(for)f(a)g(de)n(vice)g(such)g(as)g(an)g(nFET)g(that)g(has)f +(no)h(identi\002able)g(substrate)f(layer)244 3411 y(type)k +(\(\223space\224)i(cannot)f(be)g(used)f(as)h(a)g(layer)g(type)g +(here\).)145 3614 y Fe(\017)49 b Fh(top)p 378 3614 V +35 w(types)25 b Fg(Layer)g(types)f(that)g(form)h(the)g(top)f(plate)h +(of)f(a)i(capacitor)-5 b(.)145 3818 y Fe(\017)49 b Fh(bottom)p +528 3818 V 34 w(types)25 b Fg(Layer)g(types)g(that)f(form)h(the)f +(bottom)f(plate)i(of)g(a)g(capacitor)-5 b(.)145 4021 +y Fe(\017)49 b Fh(r)l(esist)p 463 4021 V 35 w(types)20 +b Fg(Layer)g(types)g(that)f(represent)i(the)e(primary)h(characterized)h +(resisti)n(v)o(e)d(portion)h(of)h(a)h(resistor)244 4142 +y(de)n(vice.)145 4345 y Fe(\017)49 b Fh(term)p 433 4345 +V 35 w(types)27 b Fg(Layer)g(types)f(that)g(represent)h(the)f(ends)h +(of)g(a)g(resistor)-5 b(.)35 b(Normally)25 b(this)h(is)g(a)h(contact)g +(type,)244 4465 y(b)n(ut)39 b(in)g(the)g(case)h(of)f(silicide)g(block)f +(or)i(high-resistance)e(implants,)k(it)d(may)g(be)g(normal)g(salicided) +244 4586 y(polysilicon)23 b(or)i(dif)n(fusion.)145 4789 +y Fe(\017)49 b Fh(base)p 433 4789 V 35 w(types)25 b Fg(Layer)g(types)f +(that)h(represent)g(the)f(base)h(re)o(gion)f(of)h(a)g(bipolar)g +(junction)e(transistor)-5 b(.)145 4993 y Fe(\017)49 b +Fh(emitter)p 533 4993 V 35 w(types)25 b Fg(Layer)g(types)f(that)g +(represent)h(the)g(emitter)f(re)o(gion)g(of)h(a)g(bipolar)f(junction)g +(transistor)-5 b(.)145 5196 y Fe(\017)49 b Fh(collector)p +605 5196 V 35 w(types)21 b Fg(Layer)g(types)g(that)g(represent)g(the)g +(collector)g(re)o(gion)f(of)h(a)h(bipolar)e(junction)g(transistor)-5 +b(.)145 5400 y Fe(\017)49 b Fh(pos)p 389 5400 V 35 w(types)22 +b Fg(Layer)g(types)f(that)h(represent)g(the)f(positi)n(v)o(e)f +(\(anode\))i(terminal)f(of)h(a)g(diode)f(or)h(P-N)h(junction.)1850 +5649 y(\22645\226)p eop end +%%Page: 46 46 +TeXDict begin 46 45 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)145 68 y Fe(\017)49 +b Fh(ne)l(g)p 390 68 30 4 v 36 w(types)25 b Fg(Layer)h(types)f(that)g +(represent)h(the)g(ne)o(gati)n(v)o(e)d(\(cathode\))j(terminal)f(of)g(a) +h(diode)f(or)h(P-N)g(junc-)244 188 y(tion.)145 391 y +Fe(\017)49 b Fh(id)p 328 391 V 35 w(types)25 b Fg(Identi\002er)g +(layers)g(that)f(identify)g(a)h(speci\002c)g(resistor)g(type.)145 +593 y Fe(\017)49 b Fh(subs)p 428 593 V 35 w(node)p 657 +593 V 35 w(name)23 b Fg(The)f(def)o(ault)g(name)h(of)f(a)h(substrate)f +(node)g(in)g(cases)h(where)g(a)f(4-terminal)g(MOSFET)244 +713 y(de)n(vice)i(is)h(missing)e(an)i(identi\002able)f(b)n(ulk)g +(terminal,)g(or)h(when)f(the)h Fh(subs)p 2806 713 V 35 +w(type)g Fg(is)f(the)h(k)o(e)o(yw)o(ord)f Fd(None)p Fg(.)145 +915 y Fe(\017)49 b Fh(perim)p 483 915 V 35 w(cap)25 b +Fg(A)g(v)n(alue)f(for)h(perimeter)g(capacitance)g(in)g(units)e(of)i +(attoF)o(arads)g(per)g(lambda)145 1118 y Fe(\017)49 b +Fh(ar)l(ea)p 429 1118 V 36 w(cap)24 b Fg(A)h(v)n(alue)f(for)i(area)f +(capacitance)h(in)e(units)g(of)h(attoF)o(arads)f(per)h(lambda)g +(squared.)146 1341 y(The)34 b Fh(subs)p 519 1341 V 35 +w(node)p 748 1341 V 35 w(name)g Fg(can)f(be)h(a)g(Tcl)f(v)n(ariable)g +(name)g(\(be)o(ginning)f(with)h(\223$\224\))g(in)h(the)f(Tcl-based)g(v) +o(er)n(-)0 1462 y(sion)28 b(of)i(magic.)43 b(Thus,)30 +b(instead)e(of)i(hard-coding)e(a)i(global)e(net)h(name)h(into)e(the)h +(general-purpose,)h(project-)0 1582 y(independent)k(technology)f +(\002le,)k(the)e(technology)e(\002le)i(can)g(contain)f(a)h(def)o(ault)f +(global)g(po)n(wer)g(and)h(ground)0 1702 y(net)42 b(v)n(ariable,)j +(normally)c Fd($VDD)g Fg(and)h Fd($VSS)p Fg(.)g(Each)g(project)g +(should)e(then)i(set)f(these)h(v)n(ariables)f(\(in)g(the)0 +1823 y Fa(.magicrc)19 b Fg(\002le,)j(for)g(e)o(xample\))e(to)g(the)h +(correct)h(v)n(alue)e(for)h(the)g(project')-5 b(s)20 +b(def)o(ault)h(global)f(po)n(wer)h(and)g(ground)0 1943 +y(netw)o(orks.)146 2064 y(SPICE)28 b(has)f(tw)o(o)f(formats)g(for)h +(resistors)e(and)i(capacitors:)34 b(one)26 b(uses)g(a)h(model,)f(and)h +(the)f(other)h(does)f(not.)0 2184 y(The)g(model)g(implies)e(a)j +(semiconductor)e(resistor)h(or)g(capacitor)l(,)h(and)f(tak)o(es)g(a)h +(length)e(and)h(width)g(v)n(alue.)34 b(The)0 2304 y(resisti)n(vity)29 +b(or)i(capacitance)h(per)f(unit)g(area)h(of)f(the)g(de)n(vices)f(is)h +(assumed)f(to)h(be)g(declared)h(in)f(the)g(model,)g(so)0 +2425 y(these)25 b(v)n(alues)f(are)h(not)f(generated)i(as)e(part)h(of)g +(the)g(SPICE)h(netlist)d(output.)146 2545 y(Magic)30 +b(technology)f(\002le)h(formats)g(27)f(and)h(earlier)h(only)e +(understood)g(one)h(de)n(vice)f(type,)i(the)f(FET)g(tran-)0 +2665 y(sistor)-5 b(.)42 b(The)29 b(e)o(xtraction)g(of)g(a)g(fet)h +(\(with)e(gate,)i(sources,)g(and)f(drains\))g(from)g(a)g(collection)g +(of)g(transistor)f(tiles)0 2786 y(is)33 b(go)o(v)o(erned)e(by)i(the)g +(information)e(in)i(a)g Fd(fet)h Fg(line.)55 b(This)32 +b(k)o(e)o(yw)o(ord)g(and)h(syntax)f(is)h(retained)g(for)g(backw)o(ard)0 +2906 y(compatibility)-6 b(.)28 b(This)c(line)g(has)h(the)f(follo)n +(wing)f(format:)900 3130 y Fd(fet)i Fh(types)g(dtypes)g(min-nterms)e +(name)i(snode)49 b Fg([)p Fh(stypes)p Fg(])p Fh(gscap)24 +b(gccap)146 3354 y(T)-7 b(ypes)32 b Fg(is)g(a)g(list)f(of)g(those)h +(tiletypes)e(that)h(mak)o(e)h(up)g(this)f(type)g(of)h(transistor)-5 +b(.)50 b(Normally)-6 b(,)32 b(there)g(will)f(be)0 3474 +y(only)g(one)i(type)e(in)h(this)f(list,)i(since)f(Magic)g(usually)f +(represents)i(each)f(type)g(of)g(transistor)g(with)f(a)h(dif)n(ferent)0 +3594 y(tiletype.)146 3715 y Fh(Dtypes)23 b Fg(is)g(a)g(list)f(of)h +(those)f(tiletypes)g(that)h(connect)g(to)f(the)h(dif)n(fusion)e +(terminals)h(of)h(the)g(fet.)30 b(Each)24 b(transis-)0 +3835 y(tor)i(of)g(this)f(type)h(must)f(ha)n(v)o(e)h(at)g(least)g +Fh(min-nterms)f Fg(distinct)g(dif)n(fusion)f(terminals;)i(otherwise,)f +(the)h(e)o(xtractor)0 3955 y(will)g(generate)h(an)g(error)g(message.)36 +b(F)o(or)26 b(e)o(xample,)g(an)h Fd(efet)g Fg(in)g(the)f(scmos)g +(technology)f(must)h(ha)n(v)o(e)g(a)h(source)0 4076 y(and)j(drain)g(in) +f(addition)g(to)h(its)f(gate;)j Fh(min-nterms)d Fg(for)h(this)f(type)h +(of)g(fet)g(is)f(2.)47 b(The)30 b(tiletypes)e(connecting)h(to)0 +4196 y(the)h(gate)g(of)g(the)g(fet)g(are)h(the)f(same)g(as)g(those)g +(speci\002ed)g(in)g(the)g Fd(connect)i Fg(section)d(as)i(connecting)e +(to)h(the)g(fet)0 4317 y(tiletype)24 b(itself.)146 4437 +y Fh(Name)i Fg(is)e(a)h(string)f(used)h(to)f(identify)g(this)g(type)g +(of)h(transistor)f(to)g(simulation)f(programs.)146 4557 +y(The)31 b(substrate)e(terminal)h(of)g(a)h(transistor)e(is)h +(determined)g(in)g(one)g(of)h(tw)o(o)f(w)o(ays.)47 b(If)31 +b Fh(stypes)f Fg(\(a)h(comma-)0 4678 y(separated)k(list)g(of)g(tile)g +(types\))f(is)h(gi)n(v)o(en,)h(and)f(a)h(particular)f(transistor)f(o)o +(v)o(erlaps)g(one)h(of)h(those)e(types,)j(the)0 4798 +y(substrate)30 b(terminal)f(will)h(be)g(connected)g(to)g(the)g(node)h +(of)f(the)g(o)o(v)o(erlapped)f(material.)47 b(Otherwise,)31 +b(the)f(sub-)0 4918 y(strate)21 b(terminal)e(will)h(be)h(connected)g +(to)f(the)h(node)f(with)g(the)h(global)f(name)g(of)h +Fh(snode)f Fg(\(which)h Fh(must)f Fg(be)h(a)g(global)0 +5039 y(name,)k(i.e.,)f(end)h(in)f(an)h(e)o(xclamation)f(point\).)146 +5159 y Fh(Gscap)h Fg(is)g(the)g(capacitance)h(between)f(the)g +(transistor')-5 b(s)24 b(gate)h(and)g(its)g(dif)n(fusion)e(terminals,)h +(in)h(attof)o(arads)0 5280 y(per)k(lambda.)42 b(Finally)-6 +b(,)28 b Fh(gccap)h Fg(is)f(the)g(capacitance)i(between)f(the)f(gate)g +(and)h(the)f(channel,)i(in)e(attof)o(arads)h(per)0 5400 +y(square)c(lambda.)30 b(Currently)-6 b(,)24 b Fh(gscap)h +Fg(and)f Fh(gccap)h Fg(are)h(unused)e(by)g(the)h(e)o(xtractor)-5 +b(.)1850 5649 y(\22646\226)p eop end +%%Page: 47 47 +TeXDict begin 47 46 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)146 68 y(In)30 +b(technology)e(format)g(27)h(\002les,)i(de)n(vices)d(such)h(as)g +(resistors,)g(capacitors,)i(and)e(bipolar)f(junction)g(tran-)0 +188 y(sistors)d(could)i(be)g(e)o(xtracted)f(by)h(treating)f(them)g(lik) +o(e)g(FETs,)h(using)f(a)h(\223)p Fd(fet)p Fg(\224)h(line)e(in)h(the)f +(e)o(xtract)h(\002le,)g(and)g(as-)0 309 y(signing)e(the)h(terminal)f +(classes)h(\(some)n(what)f(arbitrarily\))h(to)g(the)g(FET)h(terminal)e +(classes)h(gate,)h(source/drain,)0 429 y(and)j(b)n(ulk.)46 +b(Resistors)29 b(are)i(rather)g(cumbersome)e(using)g(this)g(method,)i +(because)f(the)g(\223gate\224)g(terminal)g(maps)0 549 +y(to)f(nothing)f(physical,)h(and)g(a)h(dummy)e(layer)h(must)g(be)g(dra) +o(wn.)44 b(The)29 b(\223e)o(xt2spice\224)g(command)f(generates)i(an)0 +670 y(\223M\224)f(spice)g(record)g(for)h(all)e(de)n(vices)h(declared)g +(with)f(a)i Fd(fet)f Fg(line,)h(so)e(an)i(output)d(SPICE)k(deck)e(must) +f(be)h(post-)0 790 y(processed)k(to)g(produce)g(the)g(correct)h(SPICE)g +(de)n(vices)f(for)g(simulation.)54 b(One)33 b(important)f(other)h(dif)n +(ference)0 911 y(between)25 b(the)g(older)h(form)f(and)g(the)g(ne)n +(wer)g(is)g(the)g(ability)f(of)i(the)f(\223)p Fd(de)o(vice)p +Fg(\224)h(records)f(to)g(handle)g(de)n(vices)g(with)0 +1031 y(bends)f(or)h(other)g(irre)o(gular)f(geometry)-6 +b(,)24 b(including)f(annular)i(\(ring-shaped\))f(FETs.)146 +1154 y(Often)i(the)g(units)f(in)g(the)h(e)o(xtracted)g(circuit)f(for)h +(a)h(cell)f(will)f(al)o(w)o(ays)g(be)h(multiples)e(of)i(certain)g +(basic)g(units)0 1274 y(lar)n(ger)32 b(than)e(centimicrons)g(for)h +(distance,)h(attof)o(arads)f(for)g(capacitance,)j(or)d(milliohms)d(for) +j(resistance.)49 b(T)-8 b(o)0 1394 y(allo)n(w)23 b(lar)n(ger)i(units)e +(to)h(be)g(used)g(in)g(the)g Fd(.ext)h Fg(\002le)f(for)h(this)e +(technology)-6 b(,)23 b(thereby)h(reducing)g(the)g(\002le')-5 +b(s)24 b(size,)g(the)0 1515 y Fd(extract)i Fg(section)e(may)g(specify)h +(a)g(scale)g(for)g(an)o(y)f(of)h(the)g(three)g(units,)f(as)g(follo)n +(ws:)900 1761 y Fd(cscale)h Fh(c)900 1882 y Fd(lambda)g +Fh(l)900 2002 y Fd(rscale)g Fh(r)146 2247 y Fg(In)j(the)g(abo)o(v)o(e,) +f Fh(c)h Fg(is)f(the)h(number)f(of)h(attof)o(arads)f(per)h(unit)f +(capacitance)h(appearing)g(in)f(the)h Fd(.ext)g Fg(\002les,)g +Fh(l)g Fg(is)0 2367 y(the)g(number)g(of)h(centimicrons)e(per)i(unit)e +(length,)i(and)f Fh(r)g Fg(is)g(the)h(number)f(of)g(milliohms)e(per)j +(unit)e(resistance.)0 2487 y(All)f(three)h(must)f(be)h(inte)o(gers;)f +Fh(r)h Fg(should)e(di)n(vide)g(e)n(v)o(enly)h(all)g(the)h +(resistance-per)n(-square)g(v)n(alues)f(speci\002ed)h(as)0 +2608 y(part)e(of)g Fd(r)n(esist)g Fg(lines,)f(and)g Fh(c)i +Fg(should)d(di)n(vide)h(e)n(v)o(enly)f(all)i(the)f(capacitance-per)n +(-unit)i(v)n(alues.)146 2730 y(Magic')-5 b(s)25 b(e)o(xtractor)g +(breaks)g(up)g(lar)n(ge)h(cells)f(into)g(chunks)f(for)i(hierarchical)g +(e)o(xtraction,)e(to)h(a)n(v)n(oid)g(ha)n(ving)0 2851 +y(to)f(process)g(too)g(much)g(of)g(a)h(cell)f(all)g(at)g(once)h(and)f +(possibly)f(run)h(out)g(of)g(memory)-6 b(.)29 b(The)c(size)f(of)h +(these)f(chunks)0 2971 y(is)g(determined)g(by)h(the)g +Fd(step)g Fg(k)o(e)o(yw)o(ord:)900 3218 y Fd(step)g Fh(step)146 +3462 y Fg(This)38 b(speci\002es)g(that)g(chunks)g(of)h +Fh(step)e Fg(units)h(by)g Fh(step)g Fg(units)f(will)g(be)i(processed)f +(during)g(hierarchical)0 3583 y(e)o(xtraction.)57 b(The)34 +b(def)o(ault)g(is)f Fd(100)h Fg(units.)57 b(Be)34 b(careful)h(about)e +(changing)h Fh(step)p Fg(;)k(if)33 b(it)h(is)f(too)h(small)f(then)g +(the)0 3703 y(o)o(v)o(erhead)k(of)h(hierarchical)g(processing)f(will)g +(increase,)k(and)d(if)g(it)f(is)h(too)f(lar)n(ge)h(then)g(more)f(area)i +(will)e(be)0 3823 y(processed)32 b(during)f(hierarchical)h(e)o +(xtraction)f(than)g(necessary)-6 b(.)52 b(It)32 b(should)e(rarely)i(be) +g(necessary)g(to)g(change)0 3944 y Fh(step)g Fg(unless)g(the)g(minimum) +f(feature)i(size)g(changes)f(dramatically;)k(if)c(so,)i(a)f(v)n(alue)f +(of)h(about)f(50)h(times)e(the)0 4064 y(minimum)22 b(feature)k(size)f +(appears)g(to)f(w)o(ork)h(f)o(airly)g(well.)146 4187 +y(Magic)30 b(has)f(the)g(capability)g(to)g(generate)h(a)g +(geometry-only)f(e)o(xtraction)f(of)i(a)g(netw)o(ork,)g(useful)f(for)h +(3-D)0 4307 y(simulations)22 b(of)i(electric)g(\002elds)g(necessary)h +(to)f(rigorously)e(determine)i(inductance)g(and)g(capacitance.)31 +b(When)0 4427 y(this)25 b(feature)h(is)f(used,)h(it)f(is)g(necessary)h +(for)g(the)g(\002eld-equation)f(solv)o(er)g(to)g(kno)n(w)g(the)g(v)o +(ertical)g(stackup)g(of)h(the)0 4548 y(layout.)31 b(The)25 +b(e)o(xtract)g(section)g(tak)o(es)g(care)h(of)f(this)f(by)h(allo)n +(wing)f(each)i(magic)e(layer)i(to)f(be)g(gi)n(v)o(en)f(a)h +(de\002nition)0 4668 y(of)g(height)f(and)h(thickness)e(of)i(the)g(f)o +(abricated)g(layer)g(type:)900 4915 y Fd(height)h Fh(layer)o(s)e +(height)g(thic)n(kness)146 5159 y Fg(where)i Fh(layer)o(s)g +Fg(is)f(a)h(comma-separated)f(list)g(of)g(magic)g(layers)h(sharing)f +(the)h(same)f(height)g(and)g(thickness,)0 5280 y(and)32 +b Fh(height)f Fg(and)h Fh(thic)n(kness)f Fg(are)h(\003oating-point)f +(numbers)g(gi)n(ving)f(the)h(height)g(of)h(the)g(bottom)e(of)i(the)g +(layer)0 5400 y(abo)o(v)o(e)24 b(the)g(substrate,)g(and)h(the)g +(thickness)f(of)g(the)h(layer)l(,)g(respecti)n(v)o(ely)-6 +b(,)23 b(in)h(units)g(of)h(lambda.)1850 5649 y(\22647\226)p +eop end +%%Page: 48 48 +TeXDict begin 48 47 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)0 99 y Fi(18)143 +b(W)m(iring)36 b(section)0 323 y Fg(The)25 b Fd(wiring)f +Fg(section)g(pro)o(vides)f(information)g(used)h(by)h(the)f +Fd(:wir)n(e)h(switch)g Fg(command)e(to)i(generate)g(contacts.)0 +444 y(See)30 b(T)-8 b(able)30 b(20)f(for)h(the)f Fd(wiring)h +Fg(section)e(from)i(the)f(scmos)g(technology)f(\002le.)45 +b(Each)30 b(line)f(in)g(the)g(section)g(has)0 564 y(the)c(syntax)900 +797 y Fd(contact)h Fh(type)f(minSize)e(layer1)i(surr)l(ound1)d(layer2)j +(surr)l(ound2)146 1149 y(T)-7 b(ype)36 b Fg(is)f(the)g(name)g(of)g(a)g +(contact)g(layer)l(,)j(and)d Fh(layer1)g Fg(and)g Fh(layer2)g +Fg(are)h(the)f(tw)o(o)f(wiring)h(layers)g(that)g(it)0 +1269 y(connects.)54 b Fh(MinSize)32 b Fg(is)g(the)g(minimum)f(size)h +(of)h(contacts)f(of)h(this)f(type.)54 b(If)33 b Fh(Surr)l(ound1)e +Fg(is)h(non-zero,)i(then)0 1390 y(additional)28 b(material)h(of)h(type) +f Fh(layer1)g Fg(will)g(be)g(painted)g(for)h Fh(surr)l(ound1)d +Fg(units)i(around)g(contacts)g(of)h Fh(type)p Fg(.)45 +b(If)0 1510 y Fh(surr)l(ound2)23 b Fg(is)h(non-zero,)h(it)f(indicates)g +(an)h(o)o(v)o(erlap)f(distance)g(for)h Fh(layer2)p Fg(.)p +893 1653 2115 4 v 891 1774 4 121 v 943 1738 a Fd(wiring)p +3005 1774 V 891 1894 V 943 1858 a(contact)100 b Fg(pdcontact)127 +b(4)99 b(metal1)g(0)h(pdif)n(f)178 b(0)p 3005 1894 V +891 2015 V 943 1978 a Fd(contact)100 b Fg(ndcontact)127 +b(4)99 b(metal1)g(0)h(ndif)n(f)178 b(0)p 3005 2015 V +891 2135 V 943 2099 a Fd(contact)100 b Fg(pcontact)177 +b(4)99 b(metal1)g(0)h(poly)192 b(0)p 3005 2135 V 891 +2255 V 943 2219 a Fd(contact)100 b Fg(m2contact)f(4)g(metal1)g(0)h +(metal2)e(0)p 3005 2255 V 891 2376 V 943 2340 a Fd(end)p +3005 2376 V 893 2379 2115 4 v 1444 2539 a Fg(T)-8 b(able)25 +b(20:)30 b Fd(W)n(iring)25 b Fg(section)146 2884 y(During)k +Fd(:wir)n(e)h(switch)f Fg(commands,)g(Magic)g(scans)g(the)g(wiring)g +(information)f(to)g(\002nd)i(a)f(contact)g(whose)0 3005 +y Fh(layer1)23 b Fg(and)h Fh(layer2)f Fg(correspond)g(to)g(the)g(pre)n +(vious)g(and)g(desired)h(ne)n(w)f(wiring)f(materials)h(\(or)h(vice)g(v) +o(ersa\).)30 b(If)24 b(a)0 3125 y(match)g(is)h(found,)f(a)h(contact)g +(is)f(generated)h(according)g(to)f Fh(type)p Fg(,)h Fh(minSize)p +Fg(,)f Fh(surr)l(ound1)p Fg(,)e(and)j Fh(surr)l(ound2)p +Fg(.)0 3468 y Fi(19)143 b(Router)34 b(section)0 3693 +y Fg(The)29 b Fd(r)n(outer)g Fg(section)f(of)h(a)g(technology)e(\002le) +i(pro)o(vides)e(information)g(used)h(to)g(guide)g(the)h(automatic)e +(routing)0 3813 y(tools.)j(The)24 b(section)h(contains)e(four)i(lines.) +30 b(See)c(T)-8 b(able)25 b(21)f(for)i(an)e(e)o(xample)g +Fd(r)n(outer)j Fg(section.)p 597 3956 2706 4 v 595 4077 +4 121 v 647 4040 a Fd(r)n(outer)p 3301 4077 V 595 4197 +V 647 4161 a(lay)o(er1)333 b Fg(metal1)242 b(3)100 b(allMetal1)e(3)p +3301 4197 V 595 4317 V 647 4281 a Fd(lay)o(er2)333 b +Fg(metal2)242 b(3)100 b(allMetal2)e(4)i(allPoly)-6 b(,allDif)n(f)97 +b(1)p 3301 4317 V 595 4438 V 647 4402 a Fd(contacts)250 +b Fg(m2contact)98 b(4)p 3301 4438 V 595 4558 V 647 4522 +a Fd(gridspacing)i Fg(8)p 595 4678 V 647 4642 a Fd(end)p +3301 4678 V 597 4682 2706 4 v 1446 4841 a Fg(T)-8 b(able)25 +b(21:)30 b Fd(Router)c Fg(section)146 5168 y(The)f(\002rst)g(tw)o(o)f +(lines)h(ha)n(v)o(e)f(the)h(k)o(e)o(yw)o(ords)e Fd(lay)o(er1)i +Fg(and)g Fd(lay)o(er2)f Fg(and)h(the)g(follo)n(wing)e(format:)900 +5400 y Fd(lay)o(er1)i Fh(wir)l(eT)-7 b(ype)25 b(wir)l(eW)-5 +b(idth)24 b(type-list)g(distance)g(type-list)g(distance)g +Fg(.)15 b(.)g(.)1850 5649 y(\22648\226)p eop end +%%Page: 49 49 +TeXDict begin 49 48 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)146 69 y(The)o(y)g(de\002ne)h +(the)f(tw)o(o)g(layers)g(used)g(for)g(routing.)31 b(After)26 +b(the)f Fd(lay)o(er1)g Fg(or)g Fd(lay)o(er2)g Fg(k)o(e)o(yw)o(ord)f +(are)i(tw)o(o)f(\002elds)0 189 y(gi)n(ving)f(the)i(name)f(of)h(the)g +(material)f(to)h(be)g(used)f(for)h(routing)f(that)h(layer)g(and)f(the)h +(width)f(to)g(use)h(for)g(its)f(wires.)0 309 y(The)33 +b(remaining)f(\002elds)h(are)h(used)f(by)f(Magic)h(to)g(a)n(v)n(oid)f +(routing)g(o)o(v)o(er)g(e)o(xisting)f(material)i(in)g(the)g(channels.)0 +430 y(Each)26 b(pair)g(of)g(\002elds)f(contains)g(a)h(list)f(of)h +(types)f(and)g(a)h(distance.)33 b(The)26 b(distance)f(indicates)g(ho)n +(w)g(f)o(ar)i(a)o(w)o(ay)e(the)0 550 y(gi)n(v)o(en)g(types)i(must)f(be) +h(from)g(routing)e(on)i(that)g(layer)-5 b(.)37 b(Layer1)27 +b(and)g(layer2)g(are)h(not)e(symmetrical:)33 b(where)n(v)o(er)0 +671 y(possible,)22 b(Magic)i(will)e(try)i(to)f(route)g(on)h(layer1)f +(in)g(preference)i(to)f(layer2.)30 b(Thus,)23 b(in)g(a)h(single-metal)e +(process,)0 791 y(metal)i(should)g(al)o(w)o(ays)g(be)h(used)g(for)g +(layer1.)146 913 y(The)g(third)f(line)h(pro)o(vides)e(information)g +(about)i(contacts.)30 b(It)25 b(has)f(the)h(format)900 +1151 y Fd(contacts)g Fh(contactT)-7 b(ype)25 b(size)49 +b Fg([)p Fh(surr)l(ound1)23 b(surr)l(ound2)p Fg(])146 +1389 y(The)29 b(tile)g(type)g Fh(contactT)-7 b(ype)28 +b Fg(will)g(be)i(used)e(to)h(mak)o(e)g(contacts)g(between)g(layer1)g +(and)g(layer2.)43 b(Contacts)0 1509 y(will)18 b(be)h +Fh(size)g Fg(units)f(square.)29 b(In)19 b(order)h(to)e(a)n(v)n(oid)h +(placing)f(contacts)h(too)g(close)f(to)h(hand-routed)g(material,)g +(Magic)0 1629 y(assumes)28 b(that)g(both)g(the)h(layer1)g(and)g(layer2) +f(rules)h(will)f(apply)g(to)h(contacts.)42 b(If)29 b +Fh(surr)l(ound1)e Fg(and)h Fh(surr)l(ound2)0 1750 y Fg(are)c(present,)f +(the)o(y)g(specify)g(o)o(v)o(erlap)f(distances)h(around)g(contacts)f +(for)i(layer1)f(and)g(layer2:)30 b(additional)22 b(layer1)0 +1870 y(material)32 b(will)f(be)h(painted)g(for)g Fh(surr)l(ound1)e +Fg(units)h(around)h(each)h(contact,)g(and)g(additional)d(layer2)j +(material)0 1990 y(will)24 b(be)h(painted)f(for)h Fh(surr)l(ound2)e +Fg(units)g(around)i(contacts.)146 2112 y(The)j(last)g(line)g(of)g(the)g +Fd(r)n(outing)h Fg(section)e(indicates)h(the)g(size)g(of)g(the)g(grid)g +(on)f(which)h(to)g(route.)40 b(It)28 b(has)g(the)0 2233 +y(format)900 2471 y Fd(gridspacing)d Fh(distance)146 +2708 y Fg(The)d Fh(distance)f Fg(must)g(be)h(chosen)g(lar)n(ge)g +(enough)f(that)h(contacts)f(and/or)h(wires)g(on)f(adjacent)h(grid)g +(lines)f(will)0 2829 y(not)j(generate)i(an)o(y)e(design)g(rule)h +(violations.)0 3177 y Fi(20)143 b(Plo)o(wing)34 b(section)0 +3403 y Fg(The)i Fd(plo)o(wing)f Fg(section)g(of)h(a)g(technology)e +(\002le)i(identi\002es)f(those)g(types)h(of)f(tiles)g(whose)g(sizes)h +(and)f(shapes)0 3523 y(should)25 b(not)i(be)f(changed)h(as)g(a)g +(result)f(of)h(plo)n(wing.)34 b(T)-8 b(ypically)i(,)25 +b(these)i(types)f(will)g(be)h(transistors)e(and)h(b)n(uried)0 +3644 y(contacts.)k(The)25 b(section)f(currently)h(contains)f(three)h +(kinds)f(of)g(lines:)900 3882 y Fd(\002xed)i Fh(types)900 +4003 y Fd(co)o(v)o(er)n(ed)g Fh(types)900 4123 y Fd(drag)f +Fh(types)146 4360 y Fg(where)h Fh(types)e Fg(is)h(a)g(type-list.)k(T)-8 +b(able)25 b(22)f(gi)n(v)o(es)g(this)g(section)g(for)h(the)f(scmos)g +(technology)g(\002le.)p 1318 4507 1264 4 v 1316 4627 +4 121 v 1368 4591 a Fd(plo)o(wing)p 2580 4627 V 1316 +4747 V 1368 4711 a(\002xed)232 b Fg(pfet,nfet,glass,pad)p +2580 4747 V 1316 4868 V 1368 4832 a Fd(co)o(v)o(er)n(ed)109 +b Fg(pfet,nfet)p 2580 4868 V 1316 4988 V 1368 4952 a +Fd(drag)237 b Fg(pfet,nfet)p 2580 4988 V 1316 5109 V +1368 5072 a Fd(end)p 2580 5109 V 1318 5112 1264 4 v 1424 +5272 a Fg(T)-8 b(able)25 b(22:)30 b Fd(Plo)o(wing)24 +b Fg(section)1850 5649 y(\22649\226)p eop end +%%Page: 50 50 +TeXDict begin 50 49 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)146 69 y(In)j(a)h +Fd(\002xed)f Fg(line,)g(each)h(of)f Fh(types)g Fg(is)f(considered)h(to) +f(be)h(\002x)o(ed-size;)h(re)o(gions)e(consisting)f(of)i(tiles)f(of)h +(these)0 189 y(types)f(are)h(not)e(deformed)h(by)g(plo)n(wing.)33 +b(Contact)26 b(types)g(are)h(al)o(w)o(ays)f(considered)g(to)f(be)i +(\002x)o(ed-size,)f(so)g(need)0 309 y(not)e(be)h(included)f(in)h +Fh(types)p Fg(.)146 430 y(In)i(a)f Fd(co)o(v)o(er)n(ed)i +Fg(line,)e(each)h(of)g Fh(types)f Fg(will)f(remain)i(\223co)o(v)o +(ered\224)f(by)g(plo)n(wing.)34 b(If)26 b(a)h(f)o(ace)g(of)g(a)g(co)o +(v)o(ered)e(type)0 550 y(is)k(co)o(v)o(ered)g(with)g(a)g(gi)n(v)o(en)f +(type)h(before)h(plo)n(wing,)f(it)g(will)f(remain)i(so)f(afterw)o +(ards.)45 b(F)o(or)29 b(e)o(xample,)h(if)f(a)h(f)o(ace)0 +671 y(of)e(a)g(transistor)f(is)g(co)o(v)o(ered)g(by)g(dif)n(fusion,)g +(the)h(dif)n(fusion)e(w)o(on')n(t)h(be)h(allo)n(wed)f(to)g(slide)g +(along)h(the)f(transistor)0 791 y(and)c(e)o(xpose)f(the)h(channel)g(to) +g(empty)f(space.)31 b(Usually)-6 b(,)22 b(you)g(should)g(mak)o(e)h(all) +g(\002x)o(ed-width)f(types)h(co)o(v)o(ered)f(as)0 911 +y(well,)i(e)o(xcept)h(for)g(contacts.)146 1032 y(In)j(a)g +Fd(drag)f Fg(line,)h(whene)n(v)o(er)f(material)g(of)g(a)h(type)f(in)g +Fh(types)g Fg(mo)o(v)o(es,)g(it)g(will)f(drag)i(with)e(it)h(an)o(y)g +(minimum-)0 1152 y(width)g(material)g(on)g(its)g(trailing)g(side.)38 +b(This)27 b(can)h(be)g(used,)g(for)g(e)o(xample,)f(to)g(insure)h(that)f +(when)g(a)h(transistor)0 1272 y(mo)o(v)o(es,)k(the)g(poly-o)o(v)o +(erlap)e(forming)h(its)h(gate)f(gets)h(dragged)g(along)g(in)f(its)h +(entirety)-6 b(,)32 b(instead)g(of)g(becoming)0 1393 +y(elongated.)0 1730 y Fi(21)143 b(Plot)35 b(section)0 +1953 y Fg(The)28 b Fd(plot)h Fg(section)f(of)g(the)g(technology)f +(\002le)i(contains)f(information)e(used)i(by)h(Magic)e(to)h(generate)h +(hardcop)o(y)0 2074 y(plots)e(of)g(layouts.)39 b(Plots)27 +b(can)h(be)g(generated)g(in)f(dif)n(ferent)h(styles,)f(which)g +(correspond)h(to)f(dif)n(ferent)g(printing)0 2194 y(mechanisms.)h(F)o +(or)22 b(each)h(style)e(of)h(printing,)f(there)h(is)f(a)i(separate)f +(subsection)e(within)h(the)h Fd(plot)g Fg(section.)29 +b(Each)0 2314 y(subsection)24 b(is)g(preceded)h(by)g(a)g(line)f(of)h +(the)g(form)900 2522 y Fd(style)g Fh(styleName)146 2730 +y Fg(Magic)e(v)o(ersion)g(6.5)g(and)g(earlier)i(supported)d +Fd(gr)n(emlin)p Fg(,)i Fd(v)o(ersatec)p Fg(,)g(and)g +Fd(color)o(v)o(ersatec)g Fg(styles.)29 b(As)23 b(these)0 +2850 y(are)f(thoroughly)e(obsolete,)h(v)o(ersions)f(7)i(and)f(abo)o(v)o +(e)f(instead)h(implement)f(tw)o(o)h(formats)g Fd(postscript)h +Fg(and)f Fd(pnm)p Fg(.)0 2971 y(Generally)-6 b(,)31 b(the)f +Fd(pnm)h Fg(format)f(is)f(best)h(for)g(printouts)f(of)h(entire)g +(chips,)h(and)f(the)g Fd(postscript)h Fg(format)f(is)g(best)0 +3091 y(for)35 b(small)f(cells.)60 b(The)35 b(PostScript)g(output)e +(includes)h(labels,)j(whereas)e(the)g(PNM)g(output)e(does)i(not.)60 +b(The)0 3211 y(PostScript)27 b(output)g(is)g(v)o(ector)n(-dra)o(wn)f +(with)h(stipple)f(\002lls,)i(whereas)g(the)f(PNM)h(output)e(is)h(pix)o +(el-dra)o(wn,)g(with)0 3332 y(antialiasing.)55 b(Small)32 +b(areas)i(of)g(layout)e(tend)h(to)g(look)g(arti\002cially)g(pix)o +(ellated)e(in)i(the)g(PNM)h(format,)h(while)0 3452 y(lar)n(ge)d(areas)g +(look)e(almost)g(photographic.)49 b(The)31 b(PostScript)g(output)f(is)h +(a)g(perfect)h(rendering)f(of)g(the)g(Magic)0 3573 y(layout,)36 +b(b)n(ut)e(the)h(\002les)g(become)g(v)o(ery)f(lar)n(ge)h(and)g(tak)o(e) +g(long)f(spans)g(of)h(time)f(to)g(render)h(for)g(lar)n(ge)h(areas)f(of) +0 3693 y(layout.)146 3813 y(The)29 b Fd(postscript)f +Fg(style)g(requires)g(three)h(separate)f(sections.)40 +b(The)29 b(\002rst)f(section)f(de\002nes)i(the)f(stipple)f(pat-)0 +3934 y(terns)e(used:)900 4142 y Fh(inde)n(x)g(pattern-bytes)p +Fg(.)15 b(.)g(.)146 4349 y(The)29 b Fh(inde)n(x)f Fg(v)n(alues)g(are)h +(arbitrary)g(b)n(ut)f(must)f(be)i(a)g(positi)n(v)o(e)d(inte)o(ger)i +(and)g(must)g(be)h(unique)e(to)h(each)i(line.)0 4470 +y(The)k(indices)f(will)h(be)g(referenced)h(in)f(the)g(third)f(section.) +58 b(The)34 b Fh(pattern-bytes)f Fg(are)h(al)o(w)o(ays)g(e)o(xactly)g +(8)g(sets)0 4590 y(of)k(8-digit)f(he)o(xidecimal)f(numbers)h(\(4)i +(bytes\))e(representing)h(a)g(total)f(of)h(16)g(bits)f(by)g(16)h(lines) +f(of)h(pattern)0 4711 y(data.)44 b(If)30 b(a)f(solid)f(color)h(is)g +(intended,)h(then)f(it)f(is)h(necessary)h(to)f(declare)h(a)f(stipple)f +(pattern)h(of)g(all)g(ones.)44 b(The)0 4831 y(actual)26 +b(PostScript)g(output)f(will)g(implement)g(a)h(solid)f(color)l(,)i(not) +e(a)i(stipple)e(pattern,)h(for)g(considerably)g(f)o(aster)0 +4951 y(rendering.)146 5072 y(The)20 b(second)g(section)f(de\002nes)i +(the)e(colors)h(used)g(in)f(standard)h(printer)g(CMYK)f(notation)g +(\(Cyan,)j(Magenta,)0 5192 y(Y)-10 b(ello)n(w)k(,)23 +b(blacK\):)900 5400 y Fh(inde)n(x)i(C)g(M)g(Y)g(K)1850 +5649 y Fg(\22650\226)p eop end +%%Page: 51 51 +TeXDict begin 51 50 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)p 498 64 2905 +4 v 496 172 4 109 v 547 140 a Fd(plot)p 3401 172 V 496 +280 V 547 248 a(style)100 b(postscript)p 3401 280 V 496 +389 V 841 356 a Fg(5)470 b(FFFFFFFF)28 b(FFFFFFFF)g(FFFFFFFF)g +(FFFFFFFF)g(.)15 b(.)g(.)p 3401 389 V 496 497 V 841 465 +a(7)470 b(18181818)23 b(30303030)h(60606060)f(C0C0C0C0)j(.)15 +b(.)g(.)p 3401 497 V 496 605 V 841 573 a(9)470 b(18181818)23 +b(3C3C3C3C)j(3C3C3C3C)g(18181818)e(.)15 b(.)g(.)p 3401 +605 V 496 714 V 841 681 a(10)420 b(F0F0F0F0)26 b(60606060)d(06060606)g +(0F0F0F0F)j(.)15 b(.)g(.)p 3401 714 V 496 822 V 841 790 +a(13)420 b(00000000)23 b(00000000)h(33333333)f(33333333)h(.)15 +b(.)g(.)p 3401 822 V 496 930 V 3401 930 V 496 1039 V +841 1006 a(1)470 b(47)24 b(95)h(111)f(0)p 3401 1039 V +496 1147 V 841 1115 a(9)470 b(223)24 b(47)h(223)f(0)p +3401 1147 V 496 1256 V 841 1223 a(10)420 b(0)25 b(255)f(255)g(0)p +3401 1256 V 496 1364 V 841 1331 a(12)420 b(191)24 b(127)h(0)f(0)p +3401 1364 V 496 1472 V 841 1440 a(13)420 b(95)24 b(223)h(63)f(0)p +3401 1472 V 496 1581 V 841 1548 a(14)420 b(0)25 b(0)f(0)h(255)p +3401 1581 V 496 1689 V 841 1656 a(16)420 b(111)24 b(151)h(244)f(0)p +3401 1689 V 496 1797 V 841 1765 a(17)420 b(23)24 b(175)h(183)f(0)p +3401 1797 V 496 1906 V 3401 1906 V 496 2014 V 841 1981 +a(pc,ndc,pdc,psc,nsc)1100 b(14)25 b(X)p 3401 2014 V 496 +2122 V 841 2090 a(m2c)1676 b(14)25 b(B)p 3401 2122 V +496 2231 V 841 2198 a(m2c)1676 b(14)25 b(13)p 3401 2231 +V 496 2339 V 841 2306 a(m2,m2c)1523 b(13)25 b(10)p 3401 +2339 V 496 2447 V 841 2415 a(pdc,ndc,psc,nsc,pc,m1,m2c)750 +b(12)25 b(9)p 3401 2447 V 496 2556 V 841 2523 a(poly)-6 +b(,pc)1557 b(10)25 b(5)p 3401 2556 V 496 2664 V 841 2631 +a(nfet)1693 b(9)25 b(7)p 3401 2664 V 496 2772 V 841 2740 +a(nfet)1693 b(16)25 b(5)p 3401 2772 V 496 2881 V 841 +2848 a(pfet)1693 b(1)25 b(7)p 3401 2881 V 496 2989 V +841 2956 a(pfet)1693 b(17)25 b(5)p 3401 2989 V 496 3097 +V 841 3065 a(pdif)n(f,pdc)1487 b(1)25 b(5)p 3401 3097 +V 496 3206 V 841 3173 a(ndif)n(f,ndc)1487 b(9)25 b(5)p +3401 3206 V 496 3314 V 3401 3314 V 496 3422 V 547 3390 +a Fd(style)100 b(pnm)p 3401 3422 V 496 3531 V 841 3498 +a Fg(dra)o(w)322 b(metal1)p 3401 3531 V 496 3639 V 841 +3607 a(dra)o(w)g(metal2)p 3401 3639 V 496 3747 V 841 +3715 a(dra)o(w)g(polysilicon)p 3401 3747 V 496 3856 V +841 3823 a(dra)o(w)g(ndif)n(fusion)p 3401 3856 V 496 +3964 V 841 3932 a(dra)o(w)g(pdif)n(fusion)p 3401 3964 +V 496 4072 V 841 4040 a(dra)o(w)g(ntransistor)p 3401 +4072 V 496 4181 V 841 4148 a(dra)o(w)g(ptransistor)p +3401 4181 V 496 4289 V 841 4257 a(map)348 b(psubstratepdif)n(f)23 +b(pdif)n(fusion)p 3401 4289 V 496 4397 V 841 4365 a(map)348 +b(nsubstratendif)n(f)23 b(ndif)n(fusion)p 3401 4397 V +496 4506 V 841 4473 a(map)348 b(polycontact)24 b(polysilicon)e(metal1)p +3401 4506 V 496 4614 V 841 4582 a(map)348 b(m2contact)24 +b(metal1)g(metal2)p 3401 4614 V 496 4722 V 841 4690 a(map)348 +b(ndcontact)24 b(ndif)n(fusion)f(metal1)p 3401 4722 V +496 4831 V 841 4798 a(map)348 b(pdcontact)24 b(pdif)n(fusion)f(metal1)p +3401 4831 V 496 4939 V 547 4907 a Fd(end)p 3401 4939 +V 498 4942 2905 4 v 0 5102 a Fg(T)-8 b(able)35 b(23:)52 +b(Sample)35 b Fd(plot)h Fg(section)e(\(for)i(an)g(SCMOS)g(process\).)63 +b(PostScript)35 b(stipple)f(patterns)h(ha)n(v)o(e)g(been)0 +5210 y(truncated)25 b(due)f(to)h(space)g(limitations.)1850 +5649 y(\22651\226)p eop end +%%Page: 52 52 +TeXDict begin 52 51 bop 0 -180 a Fg(February)26 b(13,)e(2006)1042 +b(Magic)24 b(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)146 68 y(Lik)o(e)30 +b(the)f(\002rst)h(section,)f(each)i Fh(inde)n(x)e Fg(must)f(be)i(a)g +(unique)f(positi)n(v)o(e)e(inte)o(ger)l(,)j(and)f(the)g(color)h(v)n +(alues)e(each)0 189 y(range)d(from)g(0)f(to)h(255.)146 +309 y(The)g(third)f(section)g(assigns)g(colors)h(and)f(stipple)g +(patterns)g(to)h(each)g(style:)900 538 y Fh(type-list)f(color)n(-inde)n +(x)g(stipple-inde)n(x)p Fe(j)p Fd(X)p Fe(j)p Fd(B)146 +767 y Fg(The)e Fh(type-list)g Fg(is)f(a)i(comma-separated)e(list)g(of)h +(magic)g(layer)g(types)g(that)g(collecti)n(v)o(ely)e(use)h(the)h(same)g +(color)0 887 y(and)h(style.)29 b(The)23 b Fh(color)n(-inde)n(x)f +Fg(refers)h(to)g(one)f(of)h(the)g(colors)f(de\002ned)h(in)f(the)h +(second)g(section,)f(and)h(the)f Fh(stipple-)0 1008 y(inde)n(x)35 +b Fg(refers)h(to)e(one)h(of)g(the)g(stipple)f(patterns)h(de\002ned)g +(in)g(the)f(\002rst)h(section.)61 b(In)35 b(addition)f(to)g(the)h +(stipple)0 1128 y(pattern)28 b(indices,)g(tw)o(o)g(characters)h(are)g +(recognized:)38 b Fd(B)29 b Fg(declares)g(that)e(a)i(border)g(will)e +(be)h(dra)o(wn)g(around)g(the)0 1248 y(layer)k(boundary)-6 +b(,)31 b(and)h Fd(X)f Fg(declares)h(that)f(the)g(layout)g(boundary)f +(will)h(be)h(printed)e(o)o(v)o(er)h(with)f(a)i(cross)f(in)g(the)0 +1369 y(same)25 b(manner)f(as)h(contact)g(areas)g(are)h(dra)o(wn)e(in)h +(the)f(Magic)h(layout.)146 1489 y(T)-8 b(o)20 b(get)g(a)g(proper)g +(PostScript)f(plot,)h(it)g(is)f(necessary)h(to)g(ha)n(v)o(e)f(a)h +(properly)g(de\002ned)g Fd(plot)g(postscript)h Fg(section)0 +1610 y(in)f(the)g(technology)e(\002le.)30 b(W)l(ithout)19 +b(such)g(a)i(de\002ned)f(set,)h(the)f Fd(plot)g(postscript)h +Fg(command)e(will)g(generate)i(blank)0 1730 y(output.)146 +1850 y(The)k Fd(pnm)h Fg(style)e(declarations)g(are)i(as)f(follo)n(ws:) +900 2079 y Fd(draw)g Fh(ma)o(gic-type)900 2200 y Fd(map)g +Fh(ma)o(gic-type)g(dr)o(aw-type)p Fg(.)15 b(.)g(.)146 +2429 y(where)38 b(both)f Fh(ma)o(gic-type)g Fg(and)h +Fh(dr)o(aw-type)f Fg(represent)h(a)g(magic)f(layer)h(name.)68 +b(The)38 b Fd(draw)g Fg(command)0 2549 y(states)24 b(that)g(a)h +(speci\002c)g(magic)f(type)g(will)g(be)h(output)e(e)o(xactly)h(as)g +(dra)o(wn)g(on)h(the)f(layout.)30 b(The)24 b Fd(map)h +Fg(statement)0 2669 y(declares)40 b(that)f(a)h(speci\002c)f(magic)g +(type)g(will)g(be)h(dra)o(wn)f(as)g(being)g(composed)f(of)i(other)f +(layers)h(declared)0 2790 y(as)28 b Fd(draw)g Fg(types.)39 +b(The)28 b(colors)f(of)h(the)g Fd(draw)g Fg(types)f(will)g(be)h +(blended)f(to)h(generate)g(the)g(mapped)f(layer)h(color)-5 +b(.)0 2910 y(Colors)19 b(are)i(de\002ned)e(by)h(the)f(style)g(set)g +(used)g(for)h(layout)f(and)g(de\002ned)h(in)f(the)g Fd(styles)h +Fg(section)e(of)i(the)f(technology)0 3030 y(\002le.)39 +b(Stipple)27 b(patterns,)g(borders,)h(and)f(cross-hatches)g(used)g(by)g +(those)g(styles)g(are)h(ignored.)37 b(When)28 b(multiple)0 +3151 y(styles)21 b(are)h(used)f(for)h(a)g(layer)g(type,)g(the)g(PNM)f +(output)g(blends)g(the)g(base)h(color)f(of)h(each)g(of)g(those)f +(styles.)29 b(Thus,)0 3271 y(contact)i(areas)h(by)f(def)o(ault)g(tend)g +(to)g(sho)n(w)f(up)h(completely)f(black,)j(as)e(the)g(\223X\224)h +(pattern)f(is)g(usually)f(de\002ned)0 3392 y(as)g(black,)i(and)e(black) +g(blended)f(with)h(other)g(colors)f(remains)h(black.)47 +b(This)29 b(is)h(why)f(the)h(abo)o(v)o(e)f(e)o(xample)g(re-)0 +3512 y(de\002nes)e(all)g(of)h(the)f(contact)f(types)h(as)g(mapped)g +(type)g(blends.)37 b(Contact)27 b(cuts)f(are)i(not)f(represented,)h +(which)f(is)0 3632 y(generally)e(desired)f(if)h(the)g(plot)f(being)g +(made)h(represents)f(a)h(lar)n(ge)h(area)g(of)e(layout.)146 +3753 y(Unlik)o(e)j(the)h(PostScript)g(section,)g(the)f(PNM)h(plot)f +(section)g(does)h Fh(not)f Fg(ha)n(v)o(e)h(to)f(be)h(declared.)40 +b(Magic)28 b(will)0 3873 y(set)22 b(up)g(a)g(def)o(ault)g(style)f(for)h +(PNM)g(plots)f(that)h(matches)f(\(more)h(or)g(less\))g(the)g(colors)g +(of)g(the)g(layout)f(as)h(speci\002ed)0 3994 y(by)38 +b(the)h Fd(styles)f Fg(section)g(of)h(the)f(technology)g(\002le.)73 +b(The)38 b Fd(plot)h(pnm)h Fg(section)e(can)h(be)g(used)f(to)g(tweak)h +(this)0 4114 y(def)o(ault)25 b(setup.)32 b(Normally)24 +b(this)g(is)h(not)g(necessary)-6 b(.)32 b(The)26 b(def)o(ault)f(setup)f +(is)h(helpful)g(in)g(that)g(it)g(allo)n(ws)f(the)h Fd(plot)0 +4234 y(pnm)32 b Fg(command)f(to)g(be)h(used)f(with)g(all)g(technology)g +(\002les,)i(including)d(those)h(written)g(before)h(the)g +Fh(plot)e(pnm)0 4355 y Fg(command)24 b(option)f(w)o(as)i(implemented.)0 +4695 y Fi(22)143 b(Conditionals,)33 b(File)i(Inclusions,)f(and)h(Macr)m +(o)g(De\002nitions)0 4918 y Fg(The)c(\223ra)o(w\224)h(technology)e +(\002les)i(in)e(the)i Fd(scmos)f Fg(subdirectory)f(of)h(the)g(Magic)g +(distrib)n(ution)e(were)j(written)f(for)0 5039 y(a)j(C)g(preprocessor)g +(and)g(cannot)g(be)f(read)i(directly)e(by)h(Magic.)57 +b(The)34 b(C)g(preprocessor)g(must)f(\002rst)g(be)h(used)0 +5159 y(to)e(eliminate)f(comments)g(and)i(e)o(xpand)f(macros)g(in)g(a)h +(technology)e(\002le)i(before)g(it)f(gets)g(installed,)h(which)f(is)0 +5280 y(done)h(during)f(the)i(\223)p Fd(mak)o(e)g(install)p +Fg(\224)e(step)h(when)g(compiling)f(and)h(installing)e(Magic)i(from)g +(source.)56 b(Macro)0 5400 y(de\002nitions)31 b(can)h(be)g(made)g(with) +g(the)g(preprocessor)g Fd(#de\002ne)h Fg(statement,)g(and)f +(\223conditional)f(compilation\224)1850 5649 y(\22652\226)p +eop end +%%Page: 53 53 +TeXDict begin 53 52 bop 0 -180 a Fg(Magic)24 b(Maintainer')-5 +b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 b(echnology)24 +b(File)1043 b(February)25 b(13,)g(2006)0 70 y(can)k(be)g(speci\002ed)g +(using)e Fd(#ifdef)p Fg(.)43 b(Also,)29 b(the)f(technology)g(\002le)h +(can)g(be)g(split)e(into)h(parts)g(using)g(the)g Fd(#include)0 +190 y Fg(statement)i(to)g(read)h(in)g(dif)n(ferent)f(parts)g(of)h(the)g +(\002les.)48 b(Ho)n(we)n(v)o(er)l(,)31 b(this)f(has)g(for)h(the)g(most) +e(part)i(pro)o(v)o(en)f(to)g(be)0 311 y(a)f(poor)f(method)f(for)i +(maintaining)d(technology)h(\002les.)42 b(End-users)28 +b(often)g(end)g(up)g(making)g(modi\002cations)e(to)0 +431 y(the)32 b(technology)f(\002les)i(for)f(one)h(purpose)e(or)i +(another)-5 b(.)52 b(The)o(y)32 b(should)f(not)h(need)h(to)e(be)i +(making)e(changes)h(to)0 551 y(the)i(source)g(code)g(distrib)n(ution,)g +(the)o(y)f(often)h(do)g(not)f(ha)n(v)o(e)h(write)g(access)h(to)e(the)h +(source)g(distrib)n(ution,)g(and)0 672 y(furthermore,)e(the)e +(elimination)f(of)i(comments)e(and)i(macros)f(from)g(the)h(\002le)g +(mak)o(es)f(the)h(actual)f(technology)0 792 y(\002le)25 +b(used)g(dif)n(\002cult)f(to)g(read)h(and)g(understand.)146 +913 y(T)-7 b(echnology)27 b(\002le)i(formats)e(more)h(recent)g(that)g +(27)f(include)h(se)n(v)o(eral)f(b)n(uilt-in)f(mechanisms)h(that)g(tak)o +(e)h(the)0 1033 y(place)23 b(of)f(preprocessor)g(statements,)g(and)g +(allo)n(w)f(the)h(technology)g(\002le)g(source)h(to)f(be)g(directly)g +(edited)g(without)0 1153 y(the)29 b(need)g(to)g(re-process.)44 +b(This)28 b(includes)h(the)g Fd(include)h Fg(statement,)f(which)g(may)f +(be)i(used)f(an)o(ywhere)g(in)f(the)0 1274 y(technology)33 +b(\002le,)j(the)e Fd(alias)f Fg(statement)g(in)g(the)h +Fd(types)h Fg(section,)g(and)f(the)g Fd(v)o(ariant)g +Fg(statement,)h(which)e(may)0 1394 y(be)e(used)f(in)g(the)g +Fd(cif)n(output)p Fg(,)j Fd(ci\002nput)p Fg(,)h(or)d +Fd(extract)g Fg(sections.)47 b(The)30 b Fd(alias)g Fg(statements)f +(appear)i(in)f(the)h Fd(types)0 1515 y Fg(section,)22 +b(co)o(v)o(ered)f(abo)o(v)o(e.)28 b(The)22 b Fd(include)h +Fg(statement)e(may)g(appear)h(an)o(ywhere)g(in)f(the)h(\002le,)h(and)e +(tak)o(es)h(the)f(form)900 1707 y Fd(include)26 b Fh(\002lename)146 +1899 y Fg(Assuming)19 b(that)h(the)g(included)g(\002les)h(e)o(xist)e +(in)h(the)g(search)h(path)g(Magic)f(uses)g(for)h(\002nding)f(system)f +(\002les)i(\(see)0 2020 y(command)31 b Fd(path)h(sys)p +Fg(\),)h(then)e(no)h(absolute)f(path)g(needs)h(to)f(be)h(spe\002cied)g +(for)g Fh(\002lename)p Fg(.)51 b(Note)31 b(that)g(the)h(\002le)0 +2140 y(contents)26 b(will)g(be)i(included)e(v)o(erbatim;)h(section)f +(names)h(and)g Fd(end)h Fg(statements)e(that)h(appear)g(in)g(the)g +(included)0 2260 y(\002le)e(should)f(not)g(e)o(xist)g(in)g(the)h +(\002le)g(that)f(includes)g(it,)g(and)h(vice)g(v)o(ersa.)146 +2381 y(The)i(most)f(common)g(use)g(of)h(\223#ifdef)5 +b(\224)28 b(preprocessor)f(statements)f(in)g(the)h(def)o(ault)g +(\223scmos\224)f(technology)0 2501 y(is)c(to)h(selecti)n(v)o(ely)d +(de\002ne)k(dif)n(ferent)e(cifoutput,)g(ci\002nput,)g(and)h(e)o(xtract) +g(\002les)f(for)h(process)g(v)n(ariants.)29 b(The)23 +b(result)0 2621 y(is)d(that)g(these)g(sections)g(become)g(quite)g(lar)n +(ge)h(and)f(repeat)h(man)o(y)e(de\002nitions)h(that)g(are)h(common)e +(to)h(all)g(process)0 2742 y(v)n(ariations.)28 b(T)-7 +b(echnology)20 b(\002le)i(format)f(30)f(de\002nes)i(the)f +Fd(v)o(ariants)g Fg(option)f(to)h(the)g Fd(style)f Fg(statement)h(for)g +(all)g(three)0 2862 y(sections)j Fd(ci\002nput)p Fg(,)i +Fd(cif)n(output)p Fg(,)g(and)f Fd(extract)p Fg(.)31 b(This)24 +b(statment)g(option)g(tak)o(es)g(the)h(form:)900 3055 +y Fd(style)g Fh(stylename)f Fd(v)o(ariants)g Fh(variantname)o(,.)15 +b(.)g(.)146 3247 y Fg(where)30 b Fh(stylename)f Fg(is)g(a)h(base)f +(name)g(used)g(for)h(all)f(v)n(ariants,)g(and)h(one)f(of)g(the)h +(comma-separated)f(list)f(of)0 3367 y Fh(variantname)p +Fg(s)e(is)i(a)g(suf)n(\002x)f(appended)h(to)f(the)h Fh(stylename)f +Fg(to)h(get)g(the)f(actual)h(name)g(as)g(it)f(w)o(ould)g(be)h(used)g +(in,)0 3488 y(for)d(e)o(xample,)f(a)h Fd(cif)g(ostyle)f +Fg(command.)30 b(F)o(or)25 b(e)o(xample,)f(the)g(statement)900 +3680 y Fd(style)h(scmos0.18)e(v)o(ariants)i(\(p\),\(c\),\(pc\),\(\))146 +3872 y Fg(de\002nes)19 b(four)g(similar)f(styles)g(named)g +Fd(scmos0.18\(p\))p Fg(,)i Fd(scmos0.18\(c\))p Fg(,)g +Fd(scmos0.18\(pc\))p Fg(,)g(and)e Fd(scmos0.18\(\))p +Fg(.)0 3993 y(All)23 b(of)h(the)g(v)n(ariants)f(are)i(assumed)e(to)g +(be)h(minor)f(v)n(ariations)g(on)g(the)h(base)g(style.)30 +b(W)l(ithin)22 b(each)j(style)e(descrip-)0 4113 y(tion,)29 +b(statements)e(may)h(apply)g(to)g(a)h(single)f(v)n(ariant,)h(a)g(group) +f(of)g(v)n(ariants,)h(or)g(all)f(v)n(ariants.)41 b(After)29 +b(the)f Fd(style)0 4233 y Fg(statement)i(has)i(been)f(processed,)i(all) +e(follo)n(wing)e(lines)i(are)h(assumed)f(to)g(refer)h(to)f(all)g(v)n +(ariants)f(of)i(the)f(base)0 4354 y(style)24 b(until)g(a)h +Fd(v)o(ariant)g Fg(statment)e(is)i(encountered.)30 b(This)24 +b(statment)g(tak)o(es)g(the)h(form:)900 4546 y Fd(v)o(ariant)g +Fh(variantname)o(,.)15 b(.)g(.)146 4738 y Fg(to)36 b(refer)g(to)g(one)f +(or)h(more)f(v)n(ariants)g(in)g(a)h(comma-separated)g(list.)62 +b(All)35 b(lines)g(follo)n(wing)f(the)h Fd(v)o(ariant)0 +4859 y Fg(statment)24 b(will)g(apply)g(only)g(to)h(the)f(speci\002c)i +(process)f(v)n(ariants)f(in)g(the)h(list,)f(until)f(another)i +Fd(v)o(ariant)g Fg(statement)0 4979 y(is)31 b(encountered.)51 +b(The)32 b(special)f(character)i(\223)p Fd(*)p Fg(\224)f(can)g(be)f +(used)g(as)h(a)g(shorthand)f(notation)f(for)i(specifying)e(all)0 +5100 y(process)25 b(v)n(ariants:)900 5292 y Fd(v)o(ariant)g(*)1850 +5649 y Fg(\22653\226)p eop end +%%Trailer + +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/maint3.ps b/doc/psfiles/maint3.ps new file mode 100644 index 00000000..c137c44c --- /dev/null +++ b/doc/psfiles/maint3.ps @@ -0,0 +1,501 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: maint3.dvi +%%Pages: 4 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips maint3.dvi -o maint3.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (maint3.dvi) +@start /Fa 134[50 1[72 2[33 39 44 1[55 50 55 83 28 2[28 +55 50 1[44 55 44 55 50 19[94 21[50 1[50 50 1[50 50 2[25 +33 3[33 33 40[{ TeXBase1Encoding ReEncodeFont }28 100.000003 +/Times-Bold rf /Fb 138[66 40 47 53 2[60 66 100 33 2[33 +66 2[53 66 53 1[60 12[80 6[113 9[86 8[40 55[66 2[{ + TeXBase1Encoding ReEncodeFont }19 119.999948 /Times-Bold +rf /Fc 105[50 1[44 44 24[44 50 50 72 50 50 28 39 33 50 +50 50 50 78 28 50 1[28 50 50 33 44 50 44 50 44 7[72 1[94 +1[72 61 55 66 1[55 72 1[89 61 1[39 33 72 72 55 61 72 +66 66 72 5[28 28 50 50 50 50 1[50 50 50 50 50 1[25 33 +25 2[33 33 33 3[50 31[55 55 2[{ TeXBase1Encoding ReEncodeFont }68 +100.000003 /Times-Roman rf /Fd 133[39 44 44 2[50 28 39 +39 50 50 50 50 72 28 2[28 50 2[44 1[44 50 50 8[61 3[55 +1[61 2[72 66 83 2[44 33 3[61 72 66 1[61 18[25 4[33 33 +40[{ TeXBase1Encoding ReEncodeFont }34 100.000003 /Times-Italic +rf /Fe 134[72 3[80 48 56 64 80 80 72 80 120 40 2[40 80 +72 1[64 80 64 1[72 12[96 80 3[112 1[135 96 2[56 1[112 +2[104 104 8[48 4[72 72 72 72 72 4[36 4[48 3[72 35[{ + TeXBase1Encoding ReEncodeFont }36 143.999997 /Times-Bold +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 0 101 a Fe(Magic)35 b(Maintainer')-5 b(s)32 b(Manual)j(#3:)43 +b(Display)33 b(Styles,)h(Colormaps,)f(and)1731 237 y(Glyphs)1630 +657 y Fd(Robert)24 b(N.)i(Mayo)1618 778 y(J)n(ohn)e(Ousterhout)1401 +1198 y Fc(Computer)g(Science)i(Di)n(vision)1020 1319 +y(Electrical)f(Engineering)f(and)h(Computer)f(Sciences)1473 +1439 y(Uni)n(v)o(ersity)f(of)i(California)1544 1559 y(Berk)o(ele)o(y)-6 +b(,)24 b(CA)h(94720)1053 1830 y(This)f(tutorial)g(corresponds)g(to)g +(Magic)h(v)o(ersion)e(7.)0 2351 y Fb(T)-11 b(utorials)30 +b(to)f(r)n(ead)h(\002rst:)300 2549 y Fc(All)24 b(of)h(them.)0 +2747 y Fb(Commands)k(intr)n(oduced)j(in)f(this)f(tutorial:)300 +2945 y Fd(\(None\))0 3143 y Fb(Macr)n(os)f(intr)n(oduced)i(in)g(this)f +(tutorial:)300 3364 y Fd(\(None\))0 4253 y Fe(1)143 b(Intr)m(oduction)0 +4477 y Fc(This)23 b(document)g(gi)n(v)o(es)f(o)o(v)o(erall)h +(information)f(about)h(the)h(\002les)g(that)f(tell)g(Magic)h(ho)n(w)e +(to)i(display)f(information)0 4597 y(on)28 b(the)h(screen.)42 +b(There)29 b(are)g(three)g(types)f(of)g(\002les)h(that)f(contain)g +(display)g(information:)36 b(display)27 b(styles)h(\002les,)0 +4718 y(color)n(-map)c(\002les,)h(and)g(glyph)f(\002les.)0 +5056 y Fe(2)143 b(Display)34 b(Styles)0 5280 y Fc(Display)26 +b(styles)g(\002les)h(describe)g(ho)n(w)f(to)g(dra)o(w)g(rectangular)i +(areas)f(and)g(te)o(xt.)36 b(A)26 b(single)g(\002le)i(contains)e(a)h +(lar)n(ge)0 5400 y(number)f(of)g(display)f(styles.)33 +b(Each)27 b(display)e(style)g(contains)g(tw)o(o)h(kinds)f(of)h +(information:)32 b(a\))26 b(ho)n(w)f(to)h(modify)1875 +5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fc(September)25 b(26,)f(2001)233 b(Magic)24 +b(Maintainer')-5 b(s)24 b(Manual)g(#3:)30 b(Display)24 +b(Styles,)g(Colormaps,)g(and)h(Glyphs)0 68 y(pix)o(els)j(\(which)h +(bits)f(of)h(the)g(pix)o(el)f(should)g(be)h(changed)g(and)h(what)e +(their)h(ne)n(w)g(v)n(alue\(s\))g(should)f(be\);)j(and)e(b\))0 +188 y(which)d(pix)o(els)g(to)g(modify)-6 b(.)36 b(P)o(art)27 +b(b\))g(consists)e(of)i(things)f(lik)o(e)g(\223\002ll)h(the)g(entire)g +(area,)-7 b(\224)29 b(or)e(\223modify)f(only)g(those)0 +309 y(pix)o(els)f(in)h(the)h(area)g(that)f(are)h(gi)n(v)o(en)e(by)i(a)g +(particular)f(stipple)f(pattern,)-7 b(\224)27 b(or)g(\223dra)o(w)f(a)h +(dashed-line)f(around)g(the)0 429 y(area')-5 b(s)25 b(outline.)-7 +b(\224)30 b(In)25 b(the)g(case)g(of)g(te)o(xt,)f(\223which)h(pix)o(els) +e(to)i(modify\224)f(is)g(determined)h(by)f(the)h(font)f(for)h(the)g(te) +o(xt,)0 549 y(which)j(is)g(not)f(part)i(of)f(the)g(display)f(style,)h +(so)g(the)g(display)g(style)f(information)g(for)h(this)g(is)g(ignored.) +40 b(See)29 b(the)0 670 y(manual)24 b(page)h Fa(dstyle)g(\(5\))g +Fc(for)g(details)f(on)h(the)g(format)f(of)h(display)f(styles)f +(\002les.)146 790 y(Display)g(styles)f(are)j(designed)e(to)g(tak)o(e)g +(into)g(account)g(both)g(the)h(characteristics)f(of)h(certain)f +(technologies)0 911 y(and)g(the)g(characteristics)h(of)f(certain)h +(displays.)29 b(F)o(or)23 b(e)o(xample,)f(a)i(bipolar)f(process)g(may)g +(require)h(information)0 1031 y(to)29 b(be)g(displayed)g(v)o(ery)g(dif) +n(ferently)f(than)h(a)h(MOS)f(process,)h(and)g(a)f(black-and-white)g +(display)f(will)h(be)g(used)0 1151 y(much)g(dif)n(ferently)f(than)h(a)g +(color)g(display)-6 b(.)42 b(Thus)29 b(there)g(can)h(be)f(man)o(y)f +(dif)n(ferent)h(display)f(styles)g(\002les,)i(each)0 +1272 y(corresponding)i(to)g(a)h(particular)f(class)g(of)h(technologies) +e(and)i(a)f(class)h(of)f(displays.)53 b(The)32 b(names)g(of)h(styles)0 +1392 y(\002les)k(re\003ect)h(these)e(classes:)54 b(each)38 +b(display)d(styles)h(\002le)h(has)g(a)g(name)g(of)g(the)f(form)h +Fd(x)p Fa(.)p Fd(y)p Fa(.dstyle5)p Fc(,)j(where)d Fd(x)0 +1513 y Fc(is)c(the)g(technology)e(class)i(\(gi)n(v)o(en)f(by)h(the)g +Fa(styletype)g Fc(line)g(in)g(the)g Fa(styles)f Fc(section)h(of)g(the)g +(technology)f(\002le\),)0 1633 y(and)e Fd(y)g Fc(is)g(the)f(class)h(of) +g(display)-6 b(.)45 b(Each)30 b(display)f(dri)n(v)o(er)g(kno)n(ws)f +(its)i(display)f(class;)j(the)d(dri)n(v)o(er)g(initialization)0 +1753 y(routine)37 b(sets)h(an)g(internal)f(Magic)h(v)n(ariable)g(with)f +(the)h(display)e(class)i(to)g(use.)70 b(Right)37 b(no)n(w)h(we)g(ha)n +(v)o(e)g(tw)o(o)0 1874 y(display)d(styles)g(\002les:)54 +b Fa(mos.7bit.dstyle5)35 b Fc(and)h Fa(mos.bw)-7 b(.dstyle5)p +Fc(.)65 b(Both)36 b(\002les)g(contain)g(enough)f(dif)n(ferent)0 +1994 y(styles)d(to)h(handle)g(a)h(v)n(ariety)e(of)h(MOS)h(processes,)h +(including)c(both)i(nMOS)g(and)g(CMOS)h(\(hence)f(the)g +Fa(mos)0 2114 y Fc(\002eld\).)46 b Fa(Mos.7bit.dstyle5)29 +b Fc(is)g(designed)g(for)h(color)g(displays)e(with)h(at)h(least)f(se)n +(v)o(en)g(bits)g(of)h(color)f(per)h(pix)o(el,)0 2235 +y(while)24 b Fa(mos.bw)-7 b(.dstyle5)24 b Fc(is)g(for)h +(black-and-white)f(displays)g(\(stipple)f(patterns)h(are)i(used)e +(instead)g(of)g(colors\).)0 2571 y Fe(3)143 b(Color)35 +b(Maps)0 2794 y Fc(The)23 b(display)f(styles)h(\002le)g(tells)g(ho)n(w) +f(to)h(modify)f(pix)o(els,)g(b)n(ut)h(this)f(doesn')n(t)h(completely)f +(specify)h(the)g(color)h(that)0 2915 y(will)e(be)h(displayed)e(on)i +(the)f(screen)i(\(unless)e(the)g(screen)i(is)e(black-and-white\).)30 +b(F)o(or)22 b(color)h(displays,)f(the)g(pix)o(el)0 3035 +y(v)n(alues)j(are)h(used)f(to)g(inde)o(x)f(into)h(a)g +Fd(color)g(map)p Fc(,)g(which)g(contains)g(the)g(red,)h(green,)g(and)f +(blue)g(intensity)f(v)n(alues)0 3155 y(to)33 b(use)g(for)h(each)g(pix)o +(el)e(v)n(alue.)55 b(The)34 b(v)n(alues)e(for)i(color)f(maps)g(are)h +(stored)f(in)g(color)n(-map)f(\002les)i(and)f(can)h(be)0 +3276 y(edited)d(using)f(the)h(color)n(-map-editing)e(windo)n(w)h(in)h +(Magic.)49 b(See)32 b Fa(cmap)g(\(5\))g Fc(for)f(details)f(on)h(the)g +(format)g(of)0 3396 y(color)n(-map)24 b(\002les.)146 +3516 y(Each)i(display)f(styles)g(\002le)h(uses)f(a)h(separate)g(color)g +(map.)33 b(Unfortunately)-6 b(,)24 b(some)i(monitors)e(ha)n(v)o(e)h +(slightly)0 3637 y(dif)n(ferent)i(phosphors)g(than)h(others;)g(this)f +(will)g(result)g(in)h(dif)n(ferent)f(colors)h(if)g(the)f(same)h +(intensity)e(v)n(alues)h(are)0 3757 y(used)33 b(for)g(them.)54 +b(T)-8 b(o)32 b(compensate)h(for)g(monitor)e(dif)n(ferences,)k(Magic)d +(supports)g(multiple)f(color)i(maps)f(for)0 3878 y(each)c(display)f +(style,)h(depending)f(on)g(the)h(monitor)e(being)h(used.)39 +b(The)28 b(monitor)e(type)i(can)g(be)g(speci\002ed)g(with)0 +3998 y(the)e Fa(-m)g Fc(command)f(line)h(switch)f(to)h(Magic,)g(with)f +Fa(std)h Fc(as)h(the)e(def)o(ault.)35 b(Color)n(-map)25 +b(\002les)i(ha)n(v)o(e)e(names)h(of)g(the)0 4118 y(form)e +Fd(x)p Fa(.)p Fd(y)p Fa(.)p Fd(z)h Fa(.cmap1)p Fc(,)g(where)g +Fd(x)f Fc(and)h Fd(y)g Fc(ha)n(v)o(e)f(the)g(same)g(meaning)g(as)h(for) +f(display)g(styles)f(and)i Fd(z)f Fc(is)g(the)g(monitor)0 +4239 y(type.)30 b(Ov)o(er)25 b(the)g(last)f(fe)n(w)h(years)g(monitor)e +(phosphors)h(appear)h(to)g(ha)n(v)o(e)f(standardized)g(quite)h(a)g +(bit,)f(so)g(almost)0 4359 y(all)j(monitors)f(no)n(w)g(w)o(ork)h(well)g +(with)g(the)g Fa(std)h Fc(monitor)e(type.)38 b(The)27 +b(color)g(map)g Fa(mos.7bit.std.cmap1)g Fc(is)g(the)0 +4480 y(standard)d(one)h(used)g(at)g(Berk)o(ele)o(y)-6 +b(.)0 4815 y Fe(4)143 b(T)-11 b(ranspar)m(ent)34 b(and)h(Opaque)f(Lay)o +(ers)0 5039 y Fc(One)24 b(of)f(the)h(k)o(e)o(y)f(decisions)f(in)h +(de\002ning)g(a)h(set)f(of)h(display)e(styles)h(for)h(a)g(color)f +(display)f(is)h(ho)n(w)g(to)g(use)h(the)f(bits)0 5159 +y(of)j(a)g(pix)o(el)f(\(this)g(section)h(doesn')n(t)f(apply)h(to)f +(black-and-white)h(displays\).)33 b(One)26 b(option)e(is)i(to)f(use)h +(a)h(separate)0 5280 y(bit)21 b(of)h(each)g(pix)o(el)e(\(called)i(a)g +Fd(bit)f(plane)p Fc(\))g(for)h(each)g(mask)f(layer)-5 +b(.)30 b(The)21 b(adv)n(antage)h(of)f(this)g(is)g(that)g(each)h +(possible)0 5400 y(combination)i(of)i(layer)h(o)o(v)o(erlaps)d(results) +h(in)h(a)g(dif)n(ferent)g(pix)o(el)f(v)n(alue,)g(and)h(hence)h(a)f(dif) +n(ferent)g(color)f(\(if)i(you)1875 5649 y(\2262\226)p +eop +%%Page: 3 3 +3 2 bop 0 -180 a Fc(Magic)24 b(Maintainer')-5 b(s)24 +b(Manual)g(#3:)30 b(Display)24 b(Styles,)h(Colormaps,)f(and)g(Glyphs) +232 b(September)25 b(26,)g(2001)0 68 y(wish\).)k(Thus,)22 +b(for)g(e)o(xample,)g(if)g(metal)f(and)h(poly)f(are)i(represented)f +(with)f(dif)n(ferent)h(bit)f(planes,)h(poly-without-)0 +188 y(metal,)k(metal-without-poly)-6 b(,)24 b(poly-and-metal,)i(and)h +(neither)n(-poly-nor)n(-metal)e(will)g(each)j(cause)f(a)f(dif)n(ferent) +0 309 y(v)n(alue)c(to)h(be)g(stored)f(in)h(the)f(pix)o(el.)29 +b(A)23 b(dif)n(ferent)f(color)h(can)g(be)g(used)g(to)f(display)g(each)i +(of)f(these)f(combinations.)0 429 y(T)-8 b(ypically)i(,)32 +b(the)g(colors)g(are)g(chosen)g(to)g(present)g(an)g(illusion)e(of)i +(transparenc)o(y:)45 b(the)31 b(poly-and-metal)g(color)0 +549 y(is)c(chosen)g(to)g(mak)o(e)h(it)f(appear)h(as)f(if)h(metal)e +(were)j(a)e(transparent)h(colored)f(foil)g(placed)g(on)h(top)e(of)i +(poly)-6 b(.)37 b(Y)-11 b(ou)0 670 y(can)24 b(see)h(this)e(ef)n(fect)h +(if)g(you)f(paint)g(polysilicon,)f(metal1,)i(and)g(metal2)f(on)g(top)h +(of)g(each)g(other)g(in)g(our)f(standard)0 790 y(technologies.)146 +918 y(The)30 b(problem)g(with)f(transparent)h(layers)g(is)f(that)h(the) +o(y)f(require)h(man)o(y)f(bits)g(per)i(pix)o(el.)45 b(Most)29 +b(color)h(dis-)0 1038 y(plays)h(don')n(t)g(ha)n(v)o(e)g(enough)g +(planes)g(to)h(use)f(a)h(dif)n(ferent)f(one)h(for)f(each)h(mask)f +(layer)-5 b(.)51 b(Another)31 b(option)f(is)h(to)0 1158 +y(use)c(a)g(group)f(of)h(planes)g(together)-5 b(.)35 +b(F)o(or)27 b(e)o(xample,)g(three)g(bits)e(of)i(a)h(pix)o(el)d(can)i +(be)g(used)g(to)f(store)h(se)n(v)o(en)f(mask)0 1279 y(layers)35 +b(plus)f(background,)j(with)d(each)i(mask)e(layer)i(corresponding)e(to) +g(one)h(of)g(the)g(combinations)e(of)i(the)0 1399 y(three)25 +b(bits.)k(The)c(problem)f(with)g(this)f(scheme)i(is)f(that)g(there)h +(is)f(no)g(w)o(ay)h(to)f(represent)h(o)o(v)o(erlaps:)k(where)c(there)0 +1520 y(is)e(an)h(o)o(v)o(erlap,)f(one)h(of)f(the)h(layers)g(must)e(be)i +(displayed)f(at)h(the)f(e)o(xpense)g(of)h(the)g(others.)30 +b(W)-8 b(e)24 b(call)f(this)g(scheme)0 1640 y(an)f Fd(opaque)g +Fc(one)g(since)g(when)g(it)f(is)h(used)g(it)f(appears)i(as)f(if)g(each) +h(layer)f(is)f(an)i(opaque)f(foil,)g(with)f(the)h(foils)f(lying)0 +1760 y(on)h(top)g(of)h(each)g(other)g(in)f(some)g(priority)g(order)-5 +b(.)30 b(This)22 b(mak)o(es)g(it)g(harder)h(to)f(see)h(what')-5 +b(s)22 b(going)g(on)g(when)h(there)0 1881 y(are)j(se)n(v)o(eral)e(mask) +g(layers)h(in)f(an)h(area.)146 2008 y(The)g(display)e(styles)h(\002les) +g(we')-5 b(v)o(e)25 b(designed)e(for)i(Magic)f(use)g(a)h(combination)e +(of)h(these)h(techniques)e(to)h(get)0 2129 y(as)33 b(much)g +(transparenc)o(y)g(as)g(possible.)54 b(F)o(or)33 b(e)o(xample,)i(our)e +Fa(mos.7bit.dstyle5)f Fc(\002le)i(uses)e(three)i(bits)e(of)h(the)0 +2249 y(pix)o(el)c(in)h(an)g(opaque)h(scheme)f(to)g(represent)g +(polysilicon,)g(dif)n(fusion,)g(and)g(v)n(arious)f(combinations)f(of)j +(them)0 2369 y(such)g(as)g(transistors.)48 b(T)-8 b(w)o(o)31 +b(additional)e(bits)h(are)i(used,)h(one)e(each,)i(for)e(the)g(tw)o(o)f +(metal)h(layers,)h(so)f(the)o(y)f(are)0 2490 y(transparent)j(with)g +(respect)g(to)g(each)h(other)g(and)f(the)g(poly-dif)n(f)f +(combinations.)55 b(Thus,)34 b(although)f(only)f(one)0 +2610 y(poly-dif)n(f)d(combination)f(can)j(appear)g(at)f(each)h(point,)f +(it')-5 b(s)29 b(possible)g(to)h(see)g(the)g(o)o(v)o(erlaps)f(between)h +(each)h(of)0 2730 y(these)e(combinations)f(and)i(each)g(combination)e +(of)h(metal1)g(and)h(metal2.)44 b(Furthermore,)31 b(all)e(of)h(these)f +(styles)0 2851 y(are)36 b(o)o(v)o(erridden)f(if)g(the)h(sixth)e(bit)h +(of)h(the)g(pix)o(el)e(is)h(set.)63 b(In)36 b(this)f(case)h(the)f(lo)n +(w)g(order)h(\002)n(v)o(e)f(bits)g(no)g(longer)0 2971 +y(correspond)24 b(to)f(mask)g(layers;)h(the)o(y)f(are)i(used)e(for)h +(opaque)g(layers)g(for)g(things)e(lik)o(e)i(labels)f(and)h(cell)g +(bounding)0 3092 y(box)o(es,)31 b(and)g(o)o(v)o(erride)f(an)o(y)g(mask) +g(information.)47 b(Thus,)32 b(for)f(e)o(xample,)g(when)g(metal1)f(is)g +(displayed)g(it)g(only)0 3212 y(af)n(fects)h(one)f(bit)g(plane,)h(b)n +(ut)f(when)h(labels)f(are)h(displayed,)f(the)h(entire)f(lo)n(w-order)g +(six)g(bits)f(of)i(the)f(pix)o(el)f(are)0 3332 y(modi\002ed.)51 +b(It')-5 b(s)32 b(important)e(that)i(the)g(opaque)f(layers)h(lik)o(e)g +(labels)f(are)i(dra)o(wn)e(after)i(the)f(transparent)f(things)0 +3453 y(that)22 b(the)o(y)f(blot)h(out;)g(this)f(is)h(guaranteed)g(by)g +(gi)n(ving)f(them)h(higher)f(style)h(numbers)g(in)f(the)i(display)e +(styles)g(\002les.)146 3580 y(Finally)-6 b(,)33 b(the)f(se)n(v)o(enth)e +(bit)i(of)g(the)f(pix)o(el)g(is)h(used)g(for)g(highlights)e(lik)o(e)h +(the)h(box)f(and)h(the)g(selection.)52 b(All)0 3701 y(64)27 +b(entries)g(in)g(the)g(color)h(map)f(corresponding)f(to)h(pix)o(el)f(v) +n(alues)h(with)f(this)h(bit)f(set)i(contain)e(the)i(same)f(v)n(alue,)0 +3821 y(namely)38 b(pure)h(white.)73 b(This)38 b(mak)o(es)g(the)h +(highlights)d(appear)k(opaque)e(with)h(respect)g(to)f(e)n(v)o(erything) +f(else.)0 3941 y(Ho)n(we)n(v)o(er)l(,)31 b(since)g(the)o(y)g(ha)n(v)o +(e)f(their)h(o)n(wn)g(bit)f(plane)h(which)g(is)f(completely)g +(independent)h(of)g(an)o(ything)e(else,)0 4062 y(the)o(y)f(can)h(be)f +(dra)o(wn)h(and)f(erased)h(without)e(ha)n(ving)h(to)g(redra)o(w)h(an)o +(y)f(of)h(the)f(mask)g(information)f(underneath.)0 4182 +y(This)e(is)h(why)f(the)h(box)f(can)i(be)f(mo)o(v)o(ed)e(relati)n(v)o +(ely)h(quickly)-6 b(.)33 b(On)26 b(the)f(other)h(hand,)g(if)g(Magic)g +(erases)g(a)h(label)f(it)0 4302 y(must)e(redra)o(w)h(all)f(the)h(mask)f +(information)f(in)h(the)h(area)h(because)f(the)f(label)h(shared)g(pix)o +(el)e(bits)h(with)g(the)h(mask)0 4423 y(information.)146 +4550 y(Thus,)40 b(the)e(scheme)f(we')-5 b(v)o(e)38 b(been)f(using)g +(for)h(Magic)f(is)g(a)h(hierarchical)g(combination)e(of)h(transparent)0 +4671 y(and)29 b(opaque)g(layers.)42 b(This)29 b(scheme)f(is)h +(de\002ned)g(almost)f(entirely)g(by)h(the)f(styles)g(\002le,)i(so)f +(you)f(can)i(try)e(other)0 4791 y(schemes)k(if)f(you)h(wish.)51 +b(Ho)n(we)n(v)o(er)l(,)32 b(you')-5 b(re)32 b(lik)o(ely)f(to)h(ha)n(v)o +(e)f(problems)g(if)h(you)f(try)h(an)o(ything)e(too)h(radically)0 +4911 y(dif)n(ferent;)21 b(we)g(ha)n(v)o(en')n(t)f(tried)g(an)o(y)g +(schemes)g(b)n(ut)g(the)h(one)f(currently)h(being)e(used)i(so)f(there)h +(are)g(probably)f(some)0 5032 y(code)25 b(dependencies)g(on)f(it.)146 +5159 y(F)o(or)h(more)g(information)f(on)g(transparent)h(and)g(opaque)g +(layers,)f(see)i(the)e(paper)i(\223The)f(User)g(Interf)o(ace)h(and)0 +5280 y(Implementation)k(of)i(an)g(IC)h(Layout)e(Editor)l(,)-7 +b(\224)33 b(which)f(appeared)g(in)g Fd(IEEE)g(T)-5 b(r)o(ansactions)29 +b(on)j(CAD)g Fc(in)g(July)0 5400 y(1984.)1875 5649 y(\2263\226)p +eop +%%Page: 4 4 +4 3 bop 0 -180 a Fc(September)25 b(26,)f(2001)233 b(Magic)24 +b(Maintainer')-5 b(s)24 b(Manual)g(#3:)30 b(Display)24 +b(Styles,)g(Colormaps,)g(and)h(Glyphs)0 99 y Fe(5)143 +b(Glyphs)0 322 y Fc(Glyphs)30 b(are)i(small)e(rectangular)h(bit)g +(patterns)f(that)h(are)h(used)e(in)h(tw)o(o)g(places)g(in)f(Magic.)50 +b(The)31 b(primary)f(use)0 443 y(for)25 b(glyphs)f(is)h(for)h +(programmable)e(cursors,)h(such)g(as)g(the)g(shapes)g(that)g(sho)n(w)f +(you)h(which)f(corner)i(of)g(the)f(box)0 563 y(you')-5 +b(re)25 b(mo)o(ving)d(and)j(the)g(v)n(arious)e(tools)h(described)g(in)g +(T)l(utorial)g(#3.)30 b(Each)25 b(programmable)f(cursor)g(is)h(stored)0 +683 y(as)h(a)h(glyph)e(describing)h(the)g(pattern)g(to)g(be)g +(displayed)g(in)f(the)i(cursor)-5 b(.)34 b(The)27 b(second)f(use)g(of)g +(glyphs)f(is)h(by)g(the)0 804 y(windo)n(w)d(package:)31 +b(the)24 b(little)f(arro)n(w)h(icons)g(appearing)g(at)h(the)f(ends)g +(of)g(scroll)g(bars)g(are)i(stored)d(as)i(glyphs,)e(as)0 +924 y(is)k(the)g(zoom)g(box)f(in)h(the)g(lo)n(wer)n(-left)g(corner)h +(of)f(the)g(windo)n(w)-6 b(.)36 b(W)-8 b(e)28 b(may)f(e)n(v)o(entually) +e(use)i(glyphs)f(in)h(a)h(menu)0 1045 y(interf)o(ace)d(\(b)n(ut)g(don') +n(t)f(hold)g(your)h(breath\).)146 1165 y(Glyphs)32 b(are)h(stored)f(in) +g(ASCII)h(glyph)f(\002les,)i(each)f(of)g(which)f(can)h(hold)e(one)i(or) +f(more)g(glyph)g(patterns.)0 1285 y(Each)j(glyph)g(is)g(represented)g +(as)g(a)h(pattern)f(of)g(characters)h(representing)f(the)g(pix)o(els)f +(in)h(the)g(glyph.)61 b(Each)0 1406 y(character)28 b(selects)f(a)g +(display)f(style)h(from)f(the)h(current)h(display)d(styles)i(\002le;)h +(the)f(display)f(style)g(indicates)g(the)0 1526 y(color)e(to)f(use)g +(for)h(that)g(pix)o(el.)29 b(See)c(the)e(manual)g(page)h +Fa(glyphs)g(\(5\))g Fc(for)g(details)f(on)g(the)h(syntax)f(of)h(glyphs) +e(\002les.)146 1647 y(The)27 b(windo)n(w)f(glyphs)g(are)h(stored)g(in)f +(\002les)i(of)f(the)f(form)h Fa(windo)o(ws)p Fd(XX)p +Fa(.glyphs)p Fc(.)37 b(The)27 b Fd(XX)g Fc(indicates)f(ho)n(w)0 +1767 y(wide)38 b(the)g(glyphs)f(are,)42 b(and)c(is)g(set)g(by)g(the)g +(graphics)g(dri)n(v)o(er)f(for)h(a)h(particular)f(display)-6 +b(.)69 b(W)-8 b(e)39 b(started)f(out)0 1887 y(with)30 +b(a)h Fa(windo)o(ws7.glyphs)g Fc(and)f(a)i Fa(windo)o(ws11.glyphs)p +Fc(.)48 b(Since)31 b(then,)h(display)e(resolution)f(has)i(increased)0 +2008 y(greatly)d(so)h(we)g(ha)n(v)o(e)f(also)h(created)g(a)g +Fa(windo)o(ws14.glyphs)f Fc(and)h(a)g Fa(windo)o(ws22.glyphs)p +Fc(.)42 b(The)28 b(positions)f(of)0 2128 y(the)e(v)n(arious)e(glyphs)h +(in)g(these)h(\002les)g(is)f(important,)g(and)g(is)h(de\002ned)g(in)f +(the)h Fa(windo)o(w)g Fc(module)f(of)h(Magic.)146 2248 +y(Programmable)g(cursors)g(are)h(stored)f(in)f(\002les)i(named)e +Fd(x)p Fa(.glyphs)p Fc(,)i(where)f Fd(x)h Fc(is)e(determined)h(by)g +(the)f(de)n(vice)0 2369 y(dri)n(v)o(er)f(for)i(the)g(display)-6 +b(.)29 b(Displays)23 b(capable)i(of)f(supporting)f(full-color)h +(cursors)g(use)g Fa(color)-10 b(.glyphs)p Fc(;)24 b(displays)0 +2489 y(that)33 b(can)g(only)g(support)f(monochrome)g(cursors)h(used)g +Fa(bw)-7 b(.glyphs)p Fc(.)56 b(The)33 b(order)h(of)f(the)g(v)n(arious)f +(glyphs)g(in)0 2610 y(these)25 b(\002les)g(is)f(important.)29 +b(It)c(is)f(de\002ned)i(by)e(the)h(\002les)g Fa(styles.h)f +Fc(in)h(the)f Fa(misc)h Fc(module)f(of)h(Magic.)1875 +5649 y(\2264\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/maint4.ps b/doc/psfiles/maint4.ps new file mode 100644 index 00000000..39afc4d1 --- /dev/null +++ b/doc/psfiles/maint4.ps @@ -0,0 +1,400 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: maint4.dvi +%%Pages: 4 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips maint4.dvi -o maint4.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (maint4.dvi) +@start /Fa 1 16 df<0001FF0000000FFFE000003FFFF800007FFFFC0001FFFFFF0003 +FFFFFF8007FFFFFFC00FFFFFFFE01FFFFFFFF01FFFFFFFF03FFFFFFFF87FFFFFFFFC7FFF +FFFFFC7FFFFFFFFCFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFF +FFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFE7FFFFFFFFC7FFFFFFFFC7FFFFFFF +FC3FFFFFFFF81FFFFFFFF01FFFFFFFF00FFFFFFFE007FFFFFFC003FFFFFF8001FFFFFF00 +007FFFFC00003FFFF800000FFFE0000001FF000027267BAB32>15 +D E /Fb 137[60 66 40 47 53 1[66 60 66 100 33 2[33 66 +60 40 53 66 53 1[60 8[86 3[80 6[113 8[86 86 8[40 6[60 +60 60 60 1[30 43[66 2[{ TeXBase1Encoding ReEncodeFont }30 +119.999948 /Times-Bold rf /Fc 75[33 29[50 1[44 26[50 +50 72 50 50 28 39 33 50 50 50 50 78 28 50 1[28 50 50 +33 44 50 44 50 44 8[72 94 72 72 61 55 66 72 55 72 72 +89 61 1[39 33 72 72 55 61 72 66 66 72 5[28 28 50 50 50 +50 50 50 50 50 50 50 28 25 33 25 2[33 33 33 2[50 50 31[55 +55 2[{ TeXBase1Encoding ReEncodeFont }73 100.000003 /Times-Roman +rf /Fd 135[44 66 2[28 39 39 2[50 50 72 28 44 4[28 44 +3[50 13[50 4[66 9[72 26[33 33 40[{ TeXBase1Encoding ReEncodeFont }18 +100.000003 /Times-Italic rf /Fe 134[72 1[104 72 80 48 +56 64 1[80 72 80 120 40 80 1[40 80 72 48 64 80 64 80 +72 8[104 143 1[104 96 6[135 3[56 4[104 104 1[104 6[48 +5[72 72 72 72 2[36 6[48 3[72 35[{ TeXBase1Encoding ReEncodeFont }39 +143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 285 101 a Fe(Magic)35 b(Maintainer')-5 b(s)34 +b(Manual)h(#4:)43 b(Using)35 b(Magic)g(Under)g(X)1665 +237 y(W)m(indo)o(ws)1747 657 y Fd(Don)24 b(Stark)1338 +1078 y Fc(Computer)h(Systems)f(Laboratory)1558 1198 y(Stanford)h(Uni)n +(v)o(ersity)1547 1319 y(Stanford,)g(CA)h(94305)1053 1589 +y(This)e(tutorial)g(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.)0 +2115 y Fb(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 +2316 y Fc(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)0 2517 y Fb(Commands)29 b(intr)n(oduced)j(in)f(this)f +(tutorial:)300 2719 y Fd(\(None\))0 2920 y Fb(Macr)n(os)f(intr)n +(oduced)i(in)g(this)f(tutorial:)300 3146 y Fd(\(None\))0 +3485 y Fe(1)143 b(Intr)m(oduction)0 3709 y Fc(This)22 +b(document)g(pro)o(vides)g(information)g(on)g(Magic')-5 +b(s)23 b(X)g(dri)n(v)o(ers)e(that)i(may)g(be)g(of)g(help)g(to)f(system) +g(maintain-)0 3829 y(ers.)0 4168 y Fe(2)143 b(Compiling)34 +b(the)h(Corr)m(ect)f(X)h(Dri)o(v)o(er)f(f)l(or)h(y)l(our)g(system.)0 +4392 y Fc(Unfortunately)-6 b(,)30 b(it)f(is)h(not)f(possible)g(to)h +(link)f(with)g(both)g(the)h(X10)g(and)g(X11)g(libraries,)g(so)g(you)g +(will)f(ha)n(v)o(e)g(to)0 4512 y(compile)24 b(Magic)g(dif)n(ferently)g +(depending)g(on)h(the)f(v)o(ersion)g(of)h(X)g(that)f(you)h(are)g +(running.)0 4807 y Fb(2.1)119 b(Compiling)31 b(f)m(or)f(X11)120 +4995 y Fc(1.)49 b(Add)24 b(the)h(\003ag)g(-DX11)g(to)f(misc/DFLA)l(GS) +120 5197 y(2.)49 b(Add)24 b(-lX11)h(to)f(magic/LIBS)120 +5400 y(3.)49 b(Change)25 b(the)g(SRCS)h(line)f(in)f(graphics/Mak)o +(e\002le)g(to)h($B)m(ASE)p 2418 5400 30 4 v 36 w(SRCS)h($X11)p +2944 5400 V 36 w(SRCS)1875 5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fc(September)25 b(26,)f(2001)516 b(Magic)25 +b(Maintainer')-5 b(s)23 b(Manual)h(#4:)31 b(Using)23 +b(Magic)i(Under)g(X)g(W)l(indo)n(ws)120 73 y(4.)49 b(Change)25 +b(the)g(OBJS)g(line)g(to)f($B)m(ASE)p 1561 73 30 4 v +36 w(OBJS)h($X11)p 2076 73 V 35 w(OBJS)120 287 y(5.)49 +b(Change)25 b(the)g(POBJS)h(line)e(to)g($B)m(ASE)p 1616 +287 V 36 w(POBJS)i($X11)p 2187 287 V 35 w(POBJS)120 501 +y(6.)49 b(Change)25 b(the)g(HELPER)p 1102 501 V 36 w(SRCS)i(line)d +($X11HELPER)p 2179 501 V 36 w(SRCS)120 715 y(7.)49 b(Change)25 +b(the)g(HELPER)p 1102 715 V 36 w(SRCS)i(line)d($X11HELPER)p +2179 715 V 36 w(PR)l(OG)120 929 y(8.)49 b(Compile)24 +b(the)h(module)e(graphics.o)120 1143 y(9.)49 b(Relink)24 +b(magic)0 1451 y Fb(2.2)119 b(Compiling)31 b(f)m(or)f(X10)120 +1643 y Fc(1.)49 b(Add)24 b(the)h(\003ag)g(-DX10)g(to)f(misc/DFLA)l(GS) +120 1857 y(2.)49 b(Add)24 b(-lX10)h(to)f(magic/LIBS)120 +2071 y(3.)49 b(Change)25 b(the)g(SRCS)h(line)f(in)f(graphics/Mak)o +(e\002le)g(to)h($B)m(ASE)p 2418 2071 V 36 w(SRCS)h($X10)p +2944 2071 V 36 w(SRCS)120 2285 y(4.)49 b(Change)25 b(the)g(OBJS)g(line) +g(to)f($B)m(ASE)p 1561 2285 V 36 w(SRCS)i($X10)p 2087 +2285 V 36 w(OBJS)120 2499 y(5.)49 b(Change)25 b(the)g(POBJS)h(line)e +(to)g($B)m(ASE)p 1616 2499 V 36 w(SRCS)j($X10)p 2143 +2499 V 35 w(POBJS)120 2713 y(6.)49 b(Change)25 b(the)g(HELPER)p +1102 2713 V 36 w(SRCS)i(line)d($X10HELPER)p 2179 2713 +V 36 w(SRCS)120 2927 y(7.)49 b(Change)25 b(the)g(HELPER)p +1102 2927 V 36 w(SRCS)i(line)d($X10HELPER)p 2179 2927 +V 36 w(PR)l(OG)120 3141 y(8.)49 b(Compile)24 b(the)h(module)e +(graphics.o)120 3355 y(9.)49 b(Relink)24 b(magic)0 3708 +y Fe(3)143 b(T)-11 b(r)m(oubleshooting)33 b(the)i(X)h(Dri)o(v)o(ers)0 +3936 y Fc(The)31 b(follo)n(wing)e(is)h(a)i(list)e(of)h(problems)f +(sometimes)f(encountered)i(in)f(running)g(Magic)h(under)g(X)g(and)g +(some)0 4057 y(suggestions)23 b(about)h(ho)n(w)g(to)h(get)f(around)h +(the)f(problem.)0 4365 y Fb(3.1)119 b(X11)30 b(Dri)o(v)o(er)145 +4557 y Fa(\017)49 b Fc(F)o(onts)244 4678 y(W)-8 b(e)21 +b(ha)n(v)o(e)g(tried)g(to)f(pick)h(a)g(set)g(of)g(fonts)f(that)h(most)f +(machines)g(running)g(X11)h(Re)n(vision)e(3)i(will)f(ha)n(v)o(e,)i(b)n +(ut)244 4798 y(there)i(is)g(nothing)f(to)h(guarantee)g(that)g(a)h(gi)n +(v)o(en)d(machine)i(will)f(ha)n(v)o(e)h(a)h(font.)30 +b(If)25 b(you')-5 b(re)24 b(getting)f(\224unable)244 +4918 y(to)f(load)h(font\224)g(messages,)f(you)h(will)f(need)h(to)f +(change)h(the)g(fonts)f(that)h(Magic)f(uses.)30 b(The)23 +b(simplest)e(w)o(ay)244 5039 y(to)30 b(do)h(this)f(is)h(to)f(specify)h +(them)f(in)h(your)g(.Xdef)o(aults)f(\002le)h(as)g(described)g(in)g +(section)f(2.1.)49 b(T)-8 b(o)31 b(change)244 5159 y(the)f(def)o(ault)f +(v)n(alues)h(that)f(Magic)h(uses,)h(change)f(the)g(\224fontnames\224)f +(array)i(in)f(the)f(\002le)i(grX11su3.c)e(of)244 5280 +y(the)k(graphics)g(module.)56 b(The)33 b(program)g Fd(xlsfonts)f +Fc(will)h(tell)f(you)h(what)h(fonts)e(are)j(a)n(v)n(ailable)d(on)h +(your)244 5400 y(machine.)1875 5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fc(Magic)24 b(Maintainer')-5 b(s)24 +b(Manual)g(#4:)30 b(Using)24 b(Magic)h(Under)g(X)f(W)l(indo)n(ws)515 +b(September)25 b(26,)g(2001)145 68 y Fa(\017)49 b Fc(Strange)25 +b(Color)g(Ef)n(fects)244 188 y(Magic)35 b(often)h(co-e)o(xists)e +(rather)j(uneasily)d(with)h(other)h(X)g(applications)e(because)i(it)g +(is)f(pick)o(y)g(about)244 309 y(which)c(colors)g(it)g(is)g(allocated.) +50 b(If)32 b(possible,)g(it)f(tries)g(to)g(allocate)g(the)g(colors)h +(it)e(requires)i(out)f(of)g(the)244 429 y(display')-5 +b(s)33 b(def)o(ault)h(colormap)g(because)h(this)f(perturbs)g(other)h +(applications)e(the)i(least.)60 b(If)35 b(this)f(f)o(ails,)244 +549 y(ho)n(we)n(v)o(er)l(,)d(Magic)g(mak)o(es)g(its)f(o)n(wn)h +(colormap.)49 b(When)31 b(this)f(colormap)h(gets)g(installed)f(is)g(a)i +(function)244 670 y(of)f(the)g(windo)n(w)f(manager;)k(most)d(windo)n(w) +e(managers)j(install)d(it)i(when)g(the)g(cursor)h(is)f(in)f(the)i +(magic)244 790 y(windo)n(w)-6 b(.)45 b(Unfortunately)-6 +b(,)29 b(there)i(is)e(no)h(w)o(ay)g(to)g(guarantee)g(that)g(the)g +(windo)n(w)f(manager)h(installs)e(the)244 911 y(magic)c(colormap)f +(correctly;)i(if)f(you)g(get)g(erratic)h(colormap)f(beha)n(vior)l(,)g +(try)g(using)f(a)i(lo)n(wer)e(number)h(of)244 1031 y(planes)g(or)h +(reducing)g(the)f(number)h(of)g(colors)f(that)g(other)h(applications)e +(use.)145 1244 y Fa(\017)49 b Fc(When)29 b(magic')-5 +b(s)27 b(colormap)h(is)g(being)g(used,)i(other)e(windo)n(ws)f(may)h +(change)h(color)l(,)h(possibly)c(to)j(some)244 1365 y(unusable)19 +b(combination)e(such)i(as)h(black)f(on)g(black)h(or)f(white)g(on)g +(white.)29 b(This)18 b(problem)h(can)h(sometimes)244 +1485 y(be)f(ameliorated)f(by)h(changing)f(the)g(constants)g(X)p +1957 1485 30 4 v 36 w(COLORMAP)p 2546 1485 V 36 w(B)m(ASE)h(and)g(X)p +3087 1485 V 36 w(COLORMAP)p 3676 1485 V 36 w(RESER)-8 +b(VED)244 1605 y(in)31 b(grX11su2.c;)i(a)f(more)f(complete)g +(description)f(of)h(what)h(these)f(constants)f(do)h(is)g(included)g(in) +g(that)244 1726 y(\002le.)68 b(V)-11 b(alues)37 b(for)g(these)g +(constants)f(that)h(are)g(incompatible)f(with)g(your)h(machine)g(will)f +(sometimes)244 1846 y(generate)25 b(Xerrors)g(in)g(XQueryColors.)145 +2059 y Fa(\017)49 b Fc(F)o(ailure)25 b(to)f(prompt)g(user)h(for)g +(windo)n(w)e(position)244 2180 y(Whether)e(or)g(not)f(the)g(designer)h +(is)f(prompted)g(for)h(a)g(windo)n(w')-5 b(s)19 b(location)h(is)g +(dependent)g(on)h(the)f(windo)n(w)244 2300 y(manager)-5 +b(.)30 b(Certain)25 b(windo)n(w)f(managers,)g(notably)g +Fd(twm)p Fc(,)h(do)g(not)f(al)o(w)o(ays)g(do)h(this.)0 +2608 y Fb(3.2)119 b(X10)30 b(Dri)o(v)o(er)0 2800 y Fc(In)c(general,)h +(the)g(V)-11 b(ersion)25 b(10)i(dri)n(v)o(er)e(is)h(less)g(reliable)g +(than)g(the)g(X11)g(one.)36 b(If)26 b(you)g(ha)n(v)o(e)g(the)h(choice,) +f(you)g(are)0 2920 y(better)f(of)n(f)f(running)g(under)h(X11.)145 +3162 y Fa(\017)49 b Fc(grX2.GrXSetCMap:)31 b(F)o(ailed)24 +b(to)g(get)h(color)g(cells)244 3283 y(Magic)37 b(gi)n(v)o(es)g(this)g +(error)h(when)g(it)f(can')n(t)i(get)f(suf)n(\002cient)f(colors)g(to)h +(run.)70 b(This)37 b(can)h(be)g(caused)g(by)244 3403 +y(running)29 b(Magic)h(on)f(a)i(machine)e(with)h(an)g(insuf)n +(\002cient)f(number)g(of)h(planes)g(\(8)g(planes)g(are)g(generally)244 +3523 y(required)37 b(to)f(run)h(a)g(7)g(bit)f(dstyles)f(\002le\),)41 +b(or)36 b(by)h(ha)n(ving)f(too)g(man)o(y)g(colors)g(already)h(used)g +(by)f(other)244 3644 y(applications.)48 b(T)m(ry)30 b(using)g(only)g +(black)h(and)g(white)g(xterms,)g(xclocks,)h(etc.,)h(and)e(see)g(if)g +(the)g(problem)244 3764 y(goes)24 b(a)o(w)o(ay)-6 b(.)145 +3978 y Fa(\017)49 b Fc(Couldn)535 3965 y(\264)538 3978 +y(t)24 b(get)h(7)f(planes;)g(allocating)g(by)h(color)244 +4098 y(Certain)i(X10)g(serv)o(ers,)h(most)e(notably)g(the)h(V)-11 +b(axstationII-GPX,)26 b(allocate)h(colors)g(in)g(such)g(a)g(w)o(ay)h +(that)244 4218 y(Magic)35 b(can)h(ne)n(v)o(er)e(get)i(the)f(7)g(color)g +(planes)h(that)e(it)h(w)o(ants.)62 b(When)36 b(this)e(happens,)k(Magic) +d(instead)244 4339 y(allocates)23 b(128)g(colors.)30 +b(This)22 b(is)h(better)g(than)g(nothing,)g(b)n(ut)f(not)h(by)g(much;)g +(strange)g(colors)g(often)h(result)244 4459 y(when)h(layers)f(o)o(v)o +(erlap.)0 4811 y Fe(4)143 b(Ackno)o(wledgments)0 5039 +y Fc(Man)o(y)35 b(people)h(share)h(the)f(credit)g(\(and)g(the)h +(blame\))f(for)g(the)g(Magic)g(X)g(dri)n(v)o(ers.)64 +b(The)36 b(original)g(X10)g(port)0 5159 y(w)o(as)f(done)g(by)f(Mark)h +(Linton)f(and)g(Doug)h(P)o(an)g(at)f(Stanford)i(Uni)n(v)o(ersity)-6 +b(.)58 b(W)-8 b(alter)35 b(Scott)f(and)h(Eric)g(Luno)n(w)0 +5280 y(of)i(La)o(wrence)g(Li)n(v)o(ermore)e(National)h(Laboratories)h +(modi\002ed)f(the)g(dri)n(v)o(er)g(and)h(the)g(windo)n(ws)e(module)g +(so)0 5400 y(that)26 b(magic)g(windo)n(ws)f(act)i(lik)o(e)f(normal)f(X) +i(windo)n(ws.)34 b(Meanwhile,)26 b(Da)n(v)o(e)g(Durfee)i(and)e(Markus)g +(G.)g(Wloka)1875 5649 y(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fc(September)25 b(26,)f(2001)516 b(Magic)25 +b(Maintainer')-5 b(s)23 b(Manual)h(#4:)31 b(Using)23 +b(Magic)i(Under)g(X)g(W)l(indo)n(ws)0 68 y(of)30 b(Bro)n(wn)g(Uni)n(v)o +(ersity)d(impro)o(v)o(ed)h(the)i(reliability)e(of)i(the)g(Stanford)g +(X10)f(dri)n(v)o(er)g(and)h(added)g(support)f(for)h(a)0 +188 y(v)n(ariable)i(number)g(of)g(planes.)53 b(Marco)33 +b(P)o(apa)f(of)h(USC)g(con)l(v)o(erted)f(the)g(Bro)n(wn)g(X10)g(dri)n +(v)o(er)g(to)g(X11.)53 b(Con-)0 309 y(currently)-6 b(,)38 +b(someone)d(at)h(the)f(Uni)n(v)o(ersity)f(of)i(W)-8 b(ashington)34 +b(con)l(v)o(erted)h(the)h(Stanford)g(X10)f(dri)n(v)o(er)g(to)h(X11.)0 +429 y(The)26 b(X11)h(dri)n(v)o(er)e(in)h(this)g(distrib)n(ution)e(is)i +(predominantly)e(a)j(mer)n(ge)g(of)g(the)f(UW)g(dri)n(v)o(er)g(with)g +(the)g(multiwin-)0 549 y(do)n(w)32 b(features)g(of)h(the)f(LLNL)g(dri)n +(v)o(er)-5 b(.)52 b(Some)33 b(of)f(the)g(ideas)h(for)f(supporting)f +(dif)n(fering)h(plane)g(counts)f(were)0 670 y(borro)n(wed)26 +b(from)g(the)h(USC/Bro)n(wn)g(w)o(ork.)36 b(Thanks)26 +b(to)g(the)h(Digital)e(Equipment)g(Corporation)h(W)-8 +b(estern)27 b(Re-)0 790 y(search)34 b(Laboratory)e(\(DECWRL\))i(for)g +(use)e(of)i(their)e(computer)h(f)o(acilities,)h(and)f(to)f(Mik)o(e)h +(Cho)n(w)f(of)i(Apple)0 911 y(Computer)24 b(for)h(the)g(Macintosh)f +(II-speci\002c)h(changes.)1875 5649 y(\2264\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut1.ps b/doc/psfiles/tut1.ps new file mode 100644 index 00000000..63b70cc9 --- /dev/null +++ b/doc/psfiles/tut1.ps @@ -0,0 +1,767 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tut1.dvi +%%Pages: 7 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman Courier +%%+ Times-BoldItalic +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tut1.dvi -o tut1.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1433 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut1.dvi) +@start /Fa 1 63 df<7000000000000000FC00000000000000FF000000000000007FC0 +0000000000001FF000000000000007FC00000000000001FF000000000000007FC0000000 +0000001FF000000000000007FE00000000000001FF800000000000007FE0000000000000 +1FF800000000000003FE00000000000000FF800000000000003FE00000000000000FF800 +000000000003FF00000000000000FFC00000000000003FF00000000000000FFC00000000 +000001FF000000000000007FC00000000000001FF000000000000007FC00000000000001 +FF000000000000007FC00000000000001FE00000000000001FE00000000000007FC00000 +00000001FF00000000000007FC0000000000001FF00000000000007FC0000000000001FF +0000000000000FFC0000000000003FF0000000000000FFC0000000000003FF0000000000 +000FF80000000000003FE0000000000000FF80000000000003FE0000000000001FF80000 +000000007FE0000000000001FF80000000000007FE0000000000001FF00000000000007F +C0000000000001FF00000000000007FC0000000000001FF00000000000007FC000000000 +0000FF00000000000000FC0000000000000070000000000000003B3878B44C>62 +D E /Fb 135[50 2[55 28 39 39 2[50 55 78 3[28 1[50 1[44 +3[50 8[66 11[61 17[33 8[50 49[{ TeXBase1Encoding ReEncodeFont }16 +100.000003 /Times-BoldItalic rf /Fc 2 104 df<0000000FE0000000FFE0000003 +FC0000000FE00000003FC00000007F80000000FF00000000FE00000001FC00000001FC00 +000003F800000003F800000003F800000003F800000003F800000003F800000003F80000 +0003F800000003F800000003F800000003F800000003F800000003F800000003F8000000 +03F800000003F800000003F800000003F800000003F800000003F800000003F800000003 +F800000003F800000003F800000003F800000003F800000003F800000003F800000003F8 +00000003F800000003F800000007F000000007F00000000FE00000001FE00000003FC000 +00007F80000000FE00000007F8000000FFE0000000FFE000000007F800000000FE000000 +007F800000003FC00000001FE00000000FE000000007F000000007F000000003F8000000 +03F800000003F800000003F800000003F800000003F800000003F800000003F800000003 +F800000003F800000003F800000003F800000003F800000003F800000003F800000003F8 +00000003F800000003F800000003F800000003F800000003F800000003F800000003F800 +000003F800000003F800000003F800000003F800000003F800000003F800000003F80000 +0003F800000001FC00000001FC00000000FE00000000FF000000007F800000003FC00000 +000FE000000003FC00000000FFE00000000FE0236479CA32>102 +DI E /Fd 103[60 30[60 60 60 1[60 60 60 60 1[60 60 +60 60 60 60 1[60 1[60 60 60 60 60 60 60 7[60 60 2[60 +60 60 60 1[60 60 1[60 60 2[60 1[60 60 60 60 60 60 60 +60 5[60 1[60 5[60 60 60 60 60 60 45[{ TeXBase1Encoding ReEncodeFont }49 +100.000003 /Courier rf /Fe 103[33 30[50 50 72 50 55 33 +39 44 55 55 50 55 83 28 2[28 55 50 1[44 55 44 55 50 12[66 +18[72 6[33 8[50 1[28 25 33 45[{ TeXBase1Encoding ReEncodeFont }30 +100.000003 /Times-Bold rf /Ff 105[50 1[44 44 24[44 50 +50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 50 +33 44 50 44 50 44 3[33 1[33 1[72 72 94 72 72 61 55 66 +1[55 72 72 89 61 1[39 33 72 72 55 61 72 66 66 72 5[28 +28 50 50 50 50 50 50 50 50 50 50 1[25 33 25 56 1[33 33 +33 1[83 1[50 1[33 29[55 55 2[{ TeXBase1Encoding ReEncodeFont }78 +100.000003 /Times-Roman rf /Fg 134[44 44 66 1[50 28 39 +39 1[50 50 50 72 28 1[28 28 50 50 28 44 50 44 50 50 8[61 +2[72 5[72 1[83 2[44 5[72 18[50 2[25 1[25 2[33 33 37[50 +2[{ TeXBase1Encoding ReEncodeFont }34 100.000003 /Times-Italic +rf /Fh 135[72 104 72 80 48 56 64 1[80 72 80 120 40 80 +1[40 80 72 1[64 80 64 80 72 8[104 143 1[104 96 80 104 +1[88 2[135 3[56 112 112 3[104 96 104 1[72 4[48 2[72 72 +72 72 72 72 72 13[72 32[80 2[{ TeXBase1Encoding ReEncodeFont }46 +143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 880 101 a Fh(Magic)36 b(T)-13 b(utorial)34 b(#1:)43 +b(Getting)34 b(Started)1618 521 y Fg(J)n(ohn)24 b(Ousterhout)1401 +941 y Ff(Computer)g(Science)i(Di)n(vision)1020 1062 y(Electrical)f +(Engineering)f(and)h(Computer)f(Sciences)1473 1182 y(Uni)n(v)o(ersity)f +(of)i(California)1544 1303 y(Berk)o(ele)o(y)-6 b(,)24 +b(CA)h(94720)1448 1573 y Fg(\(Updated)f(by)h(other)o(s,)f(too.\))1053 +1843 y Ff(This)g(tutorial)g(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.) +0 2569 y Fh(1)143 b(What)36 b(is)f(Magic?)0 2793 y Ff(Magic)26 +b(is)g(an)h(interacti)n(v)o(e)e(system)h(for)g(creating)h(and)f +(modifying)f(VLSI)i(circuit)f(layouts.)35 b(W)l(ith)26 +b(Magic,)h(you)0 2913 y(use)j(a)g(color)g(graphics)g(display)f(and)h(a) +h(mouse)e(or)h(graphics)g(tablet)f(to)h(design)f(basic)h(cells)g(and)g +(to)g(combine)0 3034 y(them)35 b(hierarchically)g(into)f(lar)n(ge)i +(structures.)62 b(Magic)35 b(is)f(dif)n(ferent)h(from)g(other)h(layout) +e(editors)h(you)f(may)0 3154 y(ha)n(v)o(e)f(used.)55 +b(The)34 b(most)e(important)f(dif)n(ference)j(is)f(that)f(Magic)h(is)g +(more)g(than)g(just)f(a)h(color)g(painting)f(tool:)0 +3275 y(it)k(understands)g(quite)h(a)g(bit)f(about)g(the)h(nature)g(of)g +(circuits)f(and)h(uses)g(this)f(information)f(to)i(pro)o(vide)f(you)0 +3395 y(with)e(additional)f(operations.)60 b(F)o(or)35 +b(e)o(xample,)h(Magic)f(has)g(b)n(uilt-in)e(kno)n(wledge)h(of)g(layout) +g(rules;)40 b(as)35 b(you)0 3515 y(are)c(editing,)g(it)f(continuously)f +(checks)i(for)g(rule)f(violations.)46 b(Magic)31 b(also)f(kno)n(ws)f +(about)h(connecti)n(vity)f(and)0 3636 y(transistors,)g(and)g(contains)f +(a)h(b)n(uilt-in)f(hierarchical)h(circuit)g(e)o(xtractor)-5 +b(.)43 b(Magic)29 b(also)f(has)h(a)h Fg(plow)f Ff(operation)0 +3756 y(that)h(you)h(can)g(use)f(to)h(stretch)f(or)h(compact)g(cells.)48 +b(Lastly)-6 b(,)31 b(Magic)f(has)h(routing)e(tools)h(that)g(you)h(can)g +(use)f(to)0 3876 y(mak)o(e)25 b(the)f(global)g(interconnections)g(in)g +(your)h(circuits.)146 3997 y(Magic)f(is)g(based)g(on)g(the)g(Mead-Conw) +o(ay)g(style)g(of)g(design.)30 b(This)23 b(means)h(that)g(it)f(uses)h +(simpli\002ed)f(design)0 4117 y(rules)g(and)f(circuit)h(structures.)29 +b(The)23 b(simpli\002cations)e(mak)o(e)h(it)h(easier)g(for)g(you)f(to)h +(design)f(circuits)g(and)h(permit)0 4238 y(Magic)28 b(to)g(pro)o(vide)f +(po)n(werful)g(assistance)h(that)f(w)o(ould)h(not)f(be)i(possible)d +(otherwise.)41 b(Ho)n(we)n(v)o(er)l(,)27 b(the)o(y)h(result)0 +4358 y(in)36 b(slightly)f(less)h(dense)g(circuits)g(than)h(you)f(could) +g(get)g(with)g(more)g(comple)o(x)g(rules)g(and)h(structures.)65 +b(F)o(or)0 4478 y(e)o(xample,)32 b(Magic)g(permits)f(only)f +Fg(Manhattan)h Ff(designs)f(\(those)i(whose)f(edges)h(are)g(v)o +(ertical)f(or)h(horizontal\).)0 4599 y(Circuit)23 b(designers)g(tell)g +(us)g(that)g(our)g(conserv)n(ati)n(v)o(e)e(design)i(rules)g(cost)g +(5-10\045)g(in)g(density)-6 b(.)28 b(W)-8 b(e)24 b(think)e(that)h(the)0 +4719 y(density)h(sacri\002ce)i(is)e(compensated)g(for)h(by)g(reduced)g +(design)f(time.)0 5056 y Fh(2)143 b(Ho)o(w)35 b(to)g(Get)g(Help)g(and)g +(Report)f(Pr)m(oblems)0 5280 y Ff(There)27 b(are)g(se)n(v)o(eral)f(w)o +(ays)g(you)g(can)g(get)h(help)f(about)f(Magic.)35 b(If)27 +b(you)f(are)h(trying)f(to)g(learn)g(about)g(the)g(system,)0 +5400 y(you)j(should)e(start)i(of)n(f)g(with)f(the)h(Magic)f(tutorials,) +h(of)g(which)g(this)f(is)g(the)h(\002rst.)43 b(Each)30 +b(tutorial)e(introduces)g(a)1875 5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Ff(September)25 b(26,)f(2001)1715 b(Magic)24 +b(T)l(utorial)g(#1:)30 b(Getting)24 b(Started)p 449 3 +3003 4 v 447 124 4 121 v 498 88 a(Magic)h(T)l(utorial)e(#1:)30 +b(Getting)24 b(Started)p 3450 124 V 447 244 V 498 208 +a(Magic)h(T)l(utorial)e(#2:)30 b(Basic)c(P)o(ainting)d(and)i(Selection) +p 3450 244 V 447 364 V 498 328 a(Magic)g(T)l(utorial)e(#3:)30 +b(Adv)n(anced)25 b(P)o(ainting)e(\(W)l(iring)i(and)f(Plo)n(wing\))p +3450 364 V 447 485 V 498 449 a(Magic)h(T)l(utorial)e(#4:)30 +b(Cell)25 b(Hierarchies)p 3450 485 V 447 605 V 498 569 +a(Magic)g(T)l(utorial)e(#5:)30 b(Multiple)24 b(W)l(indo)n(ws)p +3450 605 V 447 726 V 498 689 a(Magic)h(T)l(utorial)e(#6:)30 +b(Design-Rule)25 b(Checking)p 3450 726 V 447 846 V 498 +810 a(Magic)g(T)l(utorial)e(#7:)30 b(Netlists)24 b(and)h(Routing)p +3450 846 V 447 966 V 498 930 a(Magic)g(T)l(utorial)e(#8:)30 +b(Circuit)25 b(Extraction)p 3450 966 V 447 1087 V 498 +1051 a(Magic)g(T)l(utorial)e(#9:)30 b(F)o(ormat)25 b(Con)l(v)o(ersion)e +(for)j(CIF)f(and)g(Calma)p 3450 1087 V 447 1207 V 498 +1171 a(Magic)g(T)l(utorial)e(#10:)30 b(The)25 b(Interacti)n(v)o(e)f +(Route)p 3450 1207 V 447 1328 V 498 1291 a(Magic)h(T)l(utorial)e(#11:) +30 b(Using)24 b(RSIM)i(with)e(Magic)p 3450 1328 V 449 +1331 3003 4 v 447 1451 4 121 v 498 1415 a(Magic)h(Maintainer')-5 +b(s)23 b(Manual)i(#1:)30 b(Hints)24 b(for)h(System)f(Maintainers)p +3450 1451 V 447 1572 V 498 1535 a(Magic)h(Maintainer')-5 +b(s)23 b(Manual)i(#2:)30 b(The)25 b(T)-7 b(echnology)23 +b(File)p 3450 1572 V 447 1692 V 498 1656 a(Magic)i(Maintainer')-5 +b(s)23 b(Manual)i(#3:)30 b(Display)24 b(Styles,)g(Color)h(Maps,)f(and)h +(Glyphs)p 3450 1692 V 447 1812 V 498 1776 a(Magic)g(Maintainer')-5 +b(s)23 b(Manual)i(#4:)30 b(Using)24 b(Magic)g(Under)h(X)g(W)l(indo)n +(ws)p 3450 1812 V 449 1816 3003 4 v 447 1936 4 121 v +498 1900 a(Magic)g(T)-7 b(echnology)24 b(Manual)g(#1:)30 +b(NMOS)p 3450 1936 V 447 2056 V 498 2020 a(Magic)25 b(T)-7 +b(echnology)24 b(Manual)g(#2:)30 b(SCMOS)p 3450 2056 +V 449 2060 3003 4 v 404 2327 a(T)-8 b(able)25 b(1:)30 +b(The)25 b(Magic)g(tutorials,)e(maintenance)i(manuals,)e(and)i +(technology)f(manuals.)0 2573 y(particular)e(set)h(of)g(f)o(acilities)e +(in)h(Magic.)30 b(There)23 b(is)f(also)g(a)h(set)g(of)f(manuals)g +(intended)g(for)h(system)e(maintainers.)0 2694 y(These)33 +b(describe)f(things)g(lik)o(e)g(ho)n(w)g(to)g(create)h(ne)n(w)g +(technologies.)53 b(Finally)-6 b(,)33 b(there)g(is)f(a)h(set)g(of)f +(technology)0 2814 y(manuals.)k(Each)28 b(one)e(of)i(the)e(technology)g +(manuals)g(describes)h(the)g(features)g(peculiar)g(to)g(a)g(particular) +g(tech-)0 2934 y(nology)-6 b(,)23 b(such)i(as)g(layer)g(names)f(and)h +(design)f(rules.)31 b(T)-8 b(able)25 b(1)f(lists)g(all)g(of)h(the)g +(Magic)g(manuals.)30 b(The)24 b(tutorials)0 3055 y(are)g(designed)e(to) +g(be)h(read)g(while)g(you)f(are)i(running)d(Magic,)i(so)g(that)f(you)g +(can)i(try)e(out)g(the)h(ne)n(w)f(commands)g(as)0 3175 +y(the)o(y)k(are)i(e)o(xplained.)37 b(Y)-11 b(ou)27 b(needn')n(t)g(read) +h(all)f(the)g(tutorials)f(at)h(once;)i(each)e(tutorial)f(lists)g(the)h +(other)g(tutorials)0 3295 y(that)d(you)h(should)e(read)j(\002rst.)146 +3416 y(The)e(tutorials)f(are)i(not)e(necessarily)h(complete.)30 +b(Each)24 b(one)g(is)f(designed)h(to)f(introduce)h(a)g(set)g(of)g(f)o +(acilities,)0 3536 y(b)n(ut)c(it)g(doesn')n(t)h(necessarily)f(co)o(v)o +(er)g(e)n(v)o(ery)g(possibility)-6 b(.)26 b(The)21 b(ultimate)f +(authority)f(on)i(ho)n(w)e(Magic)i(w)o(orks)f(is)g(the)0 +3657 y(reference)28 b(manual,)e(which)g(is)g(a)h(standard)f(Unix)g +Fg(man)g Ff(page.)35 b(The)27 b Fg(man)f Ff(page)g(gi)n(v)o(es)f +(concise)h(and)h(complete)0 3777 y(descriptions)i(of)i(all)g(the)g +(Magic)f(commands.)47 b(Once)32 b(you)e(ha)n(v)o(e)g(a)i(general)f +(idea)g(ho)n(w)f(a)h(command)f(w)o(orks,)0 3897 y(the)24 +b Fg(man)g Ff(page)g(is)g(probably)g(easier)g(to)g(consult)f(than)h +(the)g(tutorial.)29 b(Ho)n(we)n(v)o(er)l(,)23 b(the)h +Fg(man)g Ff(page)h(may)f(not)f(mak)o(e)0 4018 y(much)h(sense)h(until)f +(after)h(you')-5 b(v)o(e)24 b(read)h(the)g(tutorial.)146 +4138 y(A)h(third)e(w)o(ay)h(of)h(getting)e(help)g(is)h(a)n(v)n(ailable) +g(on-line)f(through)g(Magic)h(itself.)31 b(The)26 b Fe(:help)g +Ff(command)e(will)0 4259 y(print)i(out)g(one)h(line)f(for)h(each)h +(Magic)e(command,)g(gi)n(ving)g(the)g(command')-5 b(s)25 +b(syntax)h(and)h(an)g(e)o(xtremely)f(brief)0 4379 y(description)k(of)h +(the)f(command.)48 b(This)30 b(f)o(acility)h(is)f(useful)g(if)h(you')-5 +b(v)o(e)30 b(for)n(gotten)h(the)f(name)h(or)g(e)o(xact)g(syntax)0 +4499 y(of)26 b(a)h(command.)33 b(After)27 b(each)g(screenful)f(of)g +(help)g(information,)f Fe(:help)i Ff(stops)e(and)h(prints)f +(\223\226More\226\224.)35 b(If)27 b(you)0 4620 y(type)e(a)h(space,)h +(the)e(ne)o(xt)g(screenful)h(of)g(data)g(will)e(be)i(output,)f(and)g +(if)h(you)f(type)h Fe(q)g Ff(the)g(rest)f(of)h(the)g(output)e(will)0 +4740 y(be)h(skipped.)30 b(If)25 b(you')-5 b(re)25 b(interested)f(in)h +(information)e(about)h(a)h(particular)g(subject,)f(you)g(can)i(type)900 +4950 y Fe(:help)g Fg(subject)146 5159 y Ff(This)e(command)g(will)g +(print)g(out)g(each)i(command)e(description)f(that)i(contains)f(the)g +Fg(subject)g Ff(string.)146 5280 y(If)32 b(you)g(ha)n(v)o(e)f(a)h +(question)e(or)i(problem)f(that)g(can')n(t)h(be)f(answered)h(with)f(an) +o(y)g(of)h(the)f(abo)o(v)o(e)g(approaches,)0 5400 y(you)37 +b(may)h(contact)f(the)h(Magic)f(authors)g(by)h(sending)f(mail)g(to)g +Fd(magic@ucbarpa.Berkeley.EDU)p Ff(.)1875 5649 y(\2262\226)p +eop +%%Page: 3 3 +3 2 bop 0 -180 a Ff(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)1715 b(September)25 b(26,)g(2001)0 68 y(This)k(will)g(log)h +(your)g(message)f(in)h(a)h(\002le)f(\(so)g(we)g(can')n(t)h(for)n(get)f +(about)g(it\))f(and)h(forw)o(ard)h(the)f(message)g(to)f(the)0 +188 y(Magic)34 b(maintainers.)59 b(Magic)35 b(maintenance)f(is)g(a)h +(mostly)e(v)n(olunteer)h(ef)n(fort,)j(so)d(when)h(you)f(report)h(a)g(b) +n(ug)0 309 y(or)f(ask)f(a)i(question,)f Fg(please)g Ff(be)f +(speci\002c.)58 b(Ob)o(viously)-6 b(,)34 b(the)f(more)h(speci\002c)g +(you)f(are,)k(the)c(more)h(lik)o(ely)f(we)0 429 y(can)c(answer)h(your)e +(question)g(or)h(reproduce)g(the)g(b)n(ug)g(you)f(found.)43 +b(W)-8 b(e')o(ll)29 b(tend)g(to)f(answer)h(the)g(speci\002c)h(b)n(ug)0 +549 y(reports)c(\002rst,)h(since)f(the)o(y)g(in)l(v)n(olv)o(e)f(less)g +(time)h(on)g(our)g(part.)36 b(T)m(ry)26 b(to)g(describe)g(the)g(e)o +(xact)g(sequence)h(of)f(e)n(v)o(ents)0 670 y(that)32 +b(led)g(to)g(the)g(problem,)h(what)f(you)g(e)o(xpected)g(to)f(happen,)j +(and)e(what)g(actually)g(happened.)53 b(If)33 b(possible,)0 +790 y(\002nd)25 b(a)g(small)f(e)o(xample)g(that)h(reproduces)g(the)f +(problem)h(and)f(send)h(us)g(the)f(rele)n(v)n(ant)g(\(small!\))31 +b(\002les)25 b(so)g(we)g(can)0 911 y(mak)o(e)g(it)f(happen)h(here.)31 +b(Or)25 b(best)f(of)h(all,)g(send)f(us)h(a)g(b)n(ug)f(\002x)h(along)f +(with)h(a)g(small)e(e)o(xample)h(of)h(the)g(problem.)0 +1256 y Fh(3)143 b(Graphics)34 b(Con\002guration)0 1481 +y Ff(Magic)h(can)h(be)g(run)f(with)g(dif)n(ferent)g(graphics)g(hardw)o +(are.)63 b(The)36 b(most)e(common)g(con\002guration)h(is)g(to)g(run)0 +1601 y(Magic)26 b(under)h(X11)f(on)g(a)h(w)o(orkstation.)34 +b(Another)26 b(w)o(ay)h(to)f(run)g(Magic)g(is)g(under)h(SunV)-6 +b(ie)n(w)25 b(on)i(a)f(Sun)h(w)o(ork-)0 1722 y(station,)g(or)h(under)g +(OpenGL)g(\(in)g(an)g(X11)f(en)l(vironment\))g(on)h(an)g(SGI)g(w)o +(orkstation)f(or)h(Linux)f(box)g(with)g(ac-)0 1842 y(celerated)h(3D)g +(video)f(hardw)o(are)h(and)g(dri)n(v)o(ers.)37 b(Le)o(gac)o(y)27 +b(code)h(e)o(xists)e(supporting)g(AED)h(graphics)g(terminals)0 +1962 y(and)e(X10)f(\(the)h(forerunner)g(of)g(X11\).)31 +b(The)25 b(rest)f(of)h(this)f(section)g(concerns)h(X11.)146 +2084 y(Before)32 b(starting)e(up)g(magic,)h(mak)o(e)g(sure)g(that)f +(your)g Fd(DISPLAY)f Ff(v)n(ariable)h(is)g(set)h(correctly)-6 +b(.)47 b(If)31 b(you)f(are)0 2204 y(running)24 b(magic)g(and)h(your)g +(X)f(serv)o(er)h(on)g(the)f(same)h(machine,)f(set)h(it)f(to)h +Fd(unix:0)p Ff(:)900 2439 y Fe(seten)l(v)h Fd(DISPLAY)58 +b(unix:0)146 2673 y Ff(The)25 b(Magic)f(windo)n(w)f(is)h(an)g(ordinary) +g(X)h(windo)n(w)-6 b(,)22 b(and)j(can)g(be)f(mo)o(v)o(ed)f(and)h +(resized)h(using)e(the)h(windo)n(w)0 2794 y(manager)-5 +b(.)146 2915 y(F)o(or)25 b(no)n(w)-6 b(,)24 b(you)g(can)h(skip)f(to)g +(the)h(ne)o(xt)f(major)g(section:)30 b(\224Running)25 +b(Magic\224.)0 3260 y Fh(4)143 b(Adv)o(anced)33 b(X)j(Use)0 +3485 y Ff(The)f(X11)f(dri)n(v)o(er)g(can)h(read)g(in)f(windo)n(w)g +(sizing)g(and)g(font)g(preferences)i(from)f(your)f Fg(.Xdefaults)f +Ff(\002le.)61 b(The)0 3606 y(follo)n(wing)23 b(speci\002cations)h(are)i +(recognized:)300 3841 y Fe(magic.windo)o(w:)477 b Ff(1000x600+10+10)300 +3961 y Fe(magic.newwindo)o(w:)306 b Ff(300x300+400+100)300 +4081 y Fe(magic.small:)580 b Ff(helv)o(etica8)300 4202 +y Fe(magic.medium:)460 b Ff(helv)o(etica12)300 4322 y +Fe(magic.lar)o(ge:)593 b Ff(helv)o(etica18)300 4443 y +Fe(magic.xlar)o(ge:)543 b Ff(helv)o(etica24)146 4677 +y Fe(magic.windo)o(w)28 b Ff(is)g(the)g(size)g(and)h(position)d(of)i +(the)g(initial)f(windo)n(w)-6 b(,)27 b(while)h Fe(magic.newwindo)o(w)g +Ff(is)g(the)0 4797 y(size)e(and)g(position)e(of)i(subsequent)f(windo)n +(ws.)33 b(If)27 b(these)e(are)i(left)f(blank,)g(you)g(will)f(be)h +(prompted)f(to)h(gi)n(v)o(e)e(the)0 4918 y(windo)n(w')-5 +b(s)29 b(position)g(and)h(size.)49 b Fe(small)p Ff(,)31 +b Fe(medium)p Ff(,)i Fe(lar)o(ge)p Ff(,)f(and)f Fe(xlar)o(ge)f +Ff(are)h(v)n(arious)f(fonts)g(magic)g(uses)h(for)0 5038 +y(labels.)e(Some)22 b(X11)f(serv)o(ers)g(read)h(the)f +Fd(.Xdefaults)f Ff(\002le)i(only)e(when)i(you)f(initially)e(log)i(in;)h +(you)f(may)g(ha)n(v)o(e)0 5158 y(to)j(run)h Fd(xrdb)59 +b(-load)g(\230/.Xdefaults)22 b Ff(for)j(the)g(changes)f(to)h(tak)o(e)g +(ef)n(fect.)146 5280 y(Under)j(X11,)f(Magic)g(can)h(run)f(on)g(a)g +(display)f(of)i(an)o(y)f(depth)f(for)i(which)f(there)g(are)h(colormap)f +(and)g(dstyle)0 5400 y(\002les.)37 b(Monochrome,)26 b(4)g(bit,)h(6)f +(bit,)h(7)f(bit,)h(and)g(24)f(bit)g(\002les)h(for)g(MOS)g(are)g +(distrib)n(uted)e(in)h(this)g(release.)37 b(Y)-11 b(ou)1875 +5649 y(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Ff(September)25 b(26,)f(2001)1715 b(Magic)24 +b(T)l(utorial)g(#1:)30 b(Getting)24 b(Started)0 68 y(can)i(e)o +(xplicitly)d(specify)i(ho)n(w)g(man)o(y)f(planes)h(Magic)g(is)g(to)g +(use)g(by)g(adding)g(a)h(suf)n(\002x)f(numeral)f(between)i(1)f(and)0 +188 y(7)35 b(to)f(\223XWIND\224)h(when)g(used)g(with)f(Magic')-5 +b(s)33 b(\223-d\224)j(option.)59 b(F)o(or)35 b(e)o(xample,)h(\223magic) +f(-d)g(XWIND1\224)f(runs)0 309 y(magic)23 b(on)g(a)h(monochrome)e +(display)g(and)i(\223magic)f(-d)g(XWIND7\224)h(runs)f(magic)g(on)g(a)h +(7)f(plane)h(display)-6 b(.)28 b(If)c(this)0 429 y(number)h(is)f(not)h +(speci\002ed,)g(magic)g(checks)g(the)g(depth)g(of)g(the)g(display)f +(and)h(picks)g(the)g(lar)n(gest)g(number)g(in)f(the)0 +549 y(set)g Fc(f)p Ff(1,)g(4,)g(6,)h(7,)f(16,)g(24)p +Fc(g)g Ff(that)g(the)g(display)f(will)g(support.)30 b(Another)24 +b(w)o(ay)g(to)g(force)h(the)f(display)g(type)g(is)f(to)h(set)0 +670 y(an)h(en)l(vironment)e(v)n(ariable)i(called)g Fd(MAGIC)p +1556 670 30 4 v 34 w(COLOR)f Ff(to)h(one)f(of)h(the)g(strings)e +(\2238bit\224,)i(\22316bit\224,)f(or)h(\22324bit\224.)0 +835 y Fb(Linux)g(note:)0 955 y Ff(Magic')-5 b(s)29 b(\223nati)n(v)o +(e\224)f(display)h(\(e)o(xcept)h(when)f(using)g(the)g(OpenGL)h(interf)o +(ace\))g(is)f(the)h(8-bit)f(PseudoColor)g(vi-)0 1076 +y(sual)38 b(type.)71 b(24-bit)38 b(T)m(rueColor)g(visuals)f(pre)n(v)o +(ent)h(Magic)g(from)g(allocating)f(colors)h(for)h(bit-plane)f(logical)0 +1196 y(operations,)32 b(so)g(the)f(24-bit)g(interf)o(ace)h(is)f +(visually)f(some)n(what)h(sub-par)l(,)i(requiring)e(stipple)f(patterns) +h(on)g(all)0 1316 y(metal)26 b(layers,)h(for)h(instance.)36 +b(Under)27 b(Linux,)f(a)h(fe)n(w)g(\(commercial\))f(X)h(dri)n(v)o(ers)f +(will)g(support)f(8-bit)h(o)o(v)o(erlays)0 1437 y(on)k(top)f(of)h +(24-bit)f(T)m(rueColor)h(when)g(using)f(32-bit)g(color)-5 +b(.)45 b(This)29 b(is)h(the)g(ideal)f(w)o(ay)i(to)e(use)h(magic,)h +(because)0 1557 y(the)c(colormap)g(for)h(the)g(rest)f(of)h(the)g +(display)e(is)h(preserv)o(ed)h(when)f(the)h(cursor)f(is)h(inside)e(the) +i(Magic)f(windo)n(w)-6 b(.)0 1678 y(Otherwise,)23 b(the)h(X)f(session)g +(may)g(ha)n(v)o(e)h(to)f(be)h(started)f(using)g(\223)p +Fd(startx)58 b(--bpp)h(8)p Ff(\224)24 b(to)f(force)h(it)f(to)h(use)f +(the)0 1798 y(8-bit)h(PseudoColor)h(visual.)0 1963 y +Fb(X11)g(remote)f(usage)h(note:)0 2083 y Ff(When)i(running)f(Magic)h +(remotely)f(on)h(an)g(X)g(terminal,)g(the)g(colormap)f(allocation)g +(may)h(dif)n(fer)g(for)g(the)g(local)0 2204 y(machine)e(compared)f(to)h +(the)g(remote)f(machine.)31 b(In)25 b(some)f(cases,)h(this)f(can)h +(cause)h(the)e(background)h(of)g(magic)0 2324 y(to)h(appear)h(black,)f +(usually)g(with)f(a)i(black-on-black)f(cursor)-5 b(.)35 +b(This)25 b(is)h(kno)n(wn)f(to)h(be)h(true)f(of)h(X11)f(dri)n(v)o(ers)f +(for)0 2444 y(W)l(indo)n(ws)32 b(\(such)h(as)h(PC-XW)-8 +b(are\),)37 b(due)d(to)f(the)g(w)o(ay)g(the)h(W)l(indo)n(ws)e(8-bit)g +(PseudoColor)i(colormap)e(is)h(set)0 2565 y(up.)d(This)23 +b(beha)n(vior)g(can)h(be)f(corrected)h(by)f(setting)g(tw)o(o)g(en)l +(vironment)f(v)n(ariables)g(on)i(the)f(remote)g(machine)g(as)0 +2685 y(follo)n(ws:)900 2893 y Fe(seten)l(v)j Fd(X)p 1253 +2893 V 35 w(COLORMAP)p 1768 2893 V 34 w(BASE)59 b(128)900 +3013 y Fe(seten)l(v)26 b Fd(X)p 1253 3013 V 35 w(COLORMAP)p +1768 3013 V 34 w(DEFAULT)58 b(0)146 3341 y Ff(This)39 +b(causes)g(Magic)f(to)h(a)n(v)n(oid)f(trying)g(to)h(allocate)g(the)g +(\002rst)g(color)f(in)h(the)g(colormap,)j(which)c(under)0 +3462 y(W)l(indo)n(ws)23 b(is)i(\002x)o(ed)f(as)h(black.)0 +3798 y Fh(5)143 b(Running)34 b(Magic)0 4022 y Ff(From)29 +b(this)e(point)h(on,)h(you)g(should)e(be)i(sitting)e(at)i(a)g(Magic)f +(w)o(orkstation)f(so)i(you)f(can)h(e)o(xperiment)e(with)h(the)0 +4142 y(program)i(as)g(you)f(read)h(the)g(manuals.)45 +b(Starting)30 b(up)f(Magic)h(is)f(usually)g(pretty)h(simple.)44 +b(Just)29 b(log)h(in)f(and,)i(if)0 4263 y(needed,)25 +b(start)f(up)h(your)f(f)o(a)n(v)n(orite)h(windo)n(w)f(system.)29 +b(Then)c(type)f(the)h(shell)f(command)900 4470 y Fe(magic)g(tut1)146 +4678 y(T)-9 b(ut1)28 b Ff(is)f(the)g(name)g(of)g(a)h(library)f(cell)g +(that)f(you)h(will)f(play)h(with)g(in)f(this)h(tutorial.)36 +b(At)27 b(this)f(point,)h(se)n(v)o(eral)0 4798 y(colored)36 +b(rectangles)g(should)f(appear)i(on)f(the)g(color)g(display)f(along)h +(with)g(a)g(white)g(box)g(and)g(a)g(cursor)-5 b(.)65 +b(A)0 4918 y(message)29 b(will)g(be)h(printed)f(on)h(the)g(te)o(xt)f +(display)f(to)i(tell)f(you)g(that)h Fe(tut1)g Ff(isn')n(t)f(writable)h +(\(it')-5 b(s)29 b(in)g(a)h(read-only)0 5039 y(library\),)e(and)g(a)h +(\223)p Fa(>)p Ff(\224)f(prompt)f(should)f(appear)-5 +b(.)41 b(If)28 b(this)f(has)h(happened,)g(then)g(you)f(can)h(skip)f +(the)h(rest)g(of)g(this)0 5159 y(section)c(\(e)o(xcept)h(for)g(the)f +(note)h(belo)n(w\))f(and)h(go)f(directly)h(to)f(Section)h(5.)146 +5280 y(Note:)36 b(in)27 b(the)g(tutorials,)f(when)i(you)e(see)i(things) +e(printed)h(in)g(boldf)o(ace,)h(for)f(e)o(xample,)g Fe(magic)g(tut1)h +Ff(from)0 5400 y(abo)o(v)o(e,)j(the)o(y)f(refer)i(to)e(things)f(you)h +(type)h(e)o(xactly)-6 b(,)30 b(such)h(as)f(command)g(names)g(and)h +(\002le)g(names.)48 b(These)30 b(are)1875 5649 y(\2264\226)p +eop +%%Page: 5 5 +5 4 bop 0 -180 a Ff(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)1715 b(September)25 b(26,)g(2001)0 69 y(usually)h(case)h +(sensiti)n(v)o(e)d(\()p Fe(A)j Ff(is)g(dif)n(ferent)f(from)g +Fe(a)p Ff(\).)37 b(When)27 b(you)f(see)h(things)e(printed)h(in)h +(italics,)f(the)o(y)g(refer)h(to)0 189 y(classes)e(of)g(things)e(you)i +(might)f(type.)31 b(Ar)n(guments)24 b(in)g(square)h(brack)o(ets)g(are)h +(optional.)k(F)o(or)25 b(e)o(xample,)f(a)h(more)0 309 +y(complete)f(description)g(of)h(the)f(shell)g(command)g(for)h(Magic)g +(is)900 550 y Fe(magic)f Ff([)p Fg(\002le)p Ff(])146 +788 y(Y)-11 b(ou)28 b(could)f(type)h(an)o(y)g(\002le)g(name)g(for)g +Fg(\002le)p Ff(,)h(and)e(Magic)h(w)o(ould)f(start)h(editing)f(that)g +(\002le.)41 b(It)28 b(turns)f(out)h(that)0 909 y Fe(tut1)i +Ff(is)f(just)f(a)h(\002le)h(in)f(Magic')-5 b(s)28 b(cell)h(library)-6 +b(.)44 b(If)29 b(you)g(didn')n(t)g(type)f(a)i(\002le)g(name,)g(Magic)f +(w)o(ould)f(load)h(a)h(ne)n(w)0 1029 y(blank)24 b(cell.)146 +1151 y(If)i(things)e(didn')n(t)h(happen)g(as)g(the)o(y)g(should)f(ha)n +(v)o(e)h(when)g(you)g(tried)g(to)g(run)g(Magic,)g(an)o(y)f(of)i(se)n(v) +o(eral)e(things)0 1271 y(could)k(be)h(wrong.)42 b(If)29 +b(a)g(message)f(of)h(the)f(form)h(\223magic:)38 b(Command)27 +b(not)h(found\224)h(appears)g(on)f(your)h(screen)0 1392 +y(it)h(is)f(because)i(the)f(shell)f(couldn')n(t)h(\002nd)g(the)g(Magic) +g(program.)46 b(The)30 b(most)f(stable)h(v)o(ersion)f(of)h(Magic)g(is)f +(the)0 1512 y(directory)36 b Fd(\230cad/bin)p Ff(,)h(and)f(the)g(ne)n +(west)g(public)f(v)o(ersion)g(is)h(in)f Fd(\230cad/new)p +Ff(.)63 b(Y)-11 b(ou)36 b(should)f(mak)o(e)h(sure)0 1632 +y(that)h(both)f(these)h(directories)g(are)h(in)e(your)h(shell)g(path.) +67 b(Normally)-6 b(,)38 b Fd(\230cad/new)e Ff(should)g(appear)i(before) +0 1753 y Fd(\230cad/bin)p Ff(.)g(If)29 b(this)e(sounds)g(lik)o(e)g +(gibberish,)h(\002nd)g(a)g(Unix)g(hack)o(er)g(and)g(ha)n(v)o(e)g(him)f +(or)h(her)g(e)o(xplain)f(to)h(you)0 1873 y(about)c(paths.)30 +b(If)c(w)o(orst)e(comes)g(to)h(w)o(orst,)f(you)g(can)h(in)l(v)n(ok)o(e) +g(Magic)f(by)h(typing)e(its)h(full)g(name:)900 2113 y +Fe(\230cad/bin/magic)h(tut1)146 2352 y Ff(Another)31 +b(possible)e(problem)i(is)f(that)h(Magic)f(might)g(not)g(kno)n(w)g +(what)h(kind)f(of)h(display)f(you)h(are)g(using.)0 2472 +y(T)-8 b(o)25 b(solv)o(e)e(this,)h(use)h(magic')-5 b(s)24 +b Fe(-d)h Ff(\003ag:)900 2685 y Fe(magic)f(-d)i Fg(display)e +Fe(tut1)0 2895 y Fg(Display)e Ff(is)h(usually)f(the)h(model)f(number)h +(of)g(the)g(w)o(orkstation)f(you)g(are)i(using)e(or)h(the)g(name)g(of)h +(your)e(windo)n(w)0 3016 y(system.)48 b(Look)31 b(in)f(the)h(manual)g +(page)g(for)g(a)h(list)e(of)h(v)n(alid)f(names,)i(or)f(just)f(guess)h +(something.)47 b(Magic)31 b(will)0 3136 y(print)24 b(out)g(the)h(list)f +(of)h(v)n(alid)e(names)i(if)g(you)f(guess)g(wrong.)146 +3258 y(If)h(you)f(are)h(using)f(a)g(graphics)g(terminal)g(\(not)g(a)g +(w)o(orkstation\),)f(it)h(is)g(possible)f(that)h(Magic)g(doesn')n(t)g +(kno)n(w)0 3378 y(which)i(serial)h(line)g(to)f(use.)37 +b(T)-8 b(o)27 b(learn)g(ho)n(w)f(to)h(\002x)g(this,)f(read)i(about)e +(the)h Fe(-g)g Ff(switch)f(in)g(the)h(magic\(1\))g(manual)0 +3499 y(page.)k(Also)24 b(read)h(the)g(displays\(5\))f(manual)g(page.)0 +3848 y Fh(6)143 b(The)35 b(Box)g(and)g(the)g(Cursor)0 +4074 y Ff(T)-8 b(w)o(o)30 b(things,)g(called)g(the)f +Fg(box)h Ff(and)g(the)g Fg(cur)o(sor)p Ff(,)g(are)h(used)f(to)f(select) +h(things)f(on)h(the)f(color)h(display)-6 b(.)45 b(As)30 +b(you)0 4195 y(mo)o(v)o(e)24 b(the)i(mouse,)f(the)g(cursor)h(mo)o(v)o +(es)e(on)h(the)h(screen.)34 b(The)26 b(cursor)f(starts)g(out)h(with)e +(a)i(crosshair)g(shape,)g(b)n(ut)0 4315 y(you')o(ll)i(see)i(later)f +(that)g(its)g(shape)g(changes)g(as)g(you)g(w)o(ork)g(to)g(pro)o(vide)f +(feedback)i(about)f(what)g(you')-5 b(re)29 b(doing.)0 +4435 y(The)g(left)g(and)g(right)g(mouse)f(b)n(uttons)g(are)i(used)f(to) +g(position)e(the)i(box.)43 b(If)30 b(you)f(press)g(the)g(left)g(mouse)f +(b)n(utton)0 4556 y(and)g(then)f(release)h(it,)g(the)g(box)f(will)g(mo) +o(v)o(e)f(so)h(that)h(its)f(lo)n(wer)g(left)g(corner)i(is)e(at)h(the)f +(cursor)h(position.)37 b(If)29 b(you)0 4676 y(press)c(and)h(release)g +(the)f(right)g(mouse)g(b)n(utton,)f(the)h(upper)h(right)e(corner)i(of)g +(the)f(box)g(will)g(mo)o(v)o(e)f(to)h(the)g(cursor)0 +4797 y(position,)k(b)n(ut)g(the)h(lo)n(wer)f(left)g(corner)h(will)f +(not)g(change.)46 b(These)29 b(tw)o(o)h(b)n(uttons)e(are)i(enough)f(to) +g(position)f(the)0 4917 y(box)k(an)o(ywhere)g(on)g(the)g(screen.)54 +b(T)m(ry)32 b(using)g(the)g(b)n(uttons)f(to)h(place)g(the)h(box)e +(around)i(each)g(of)f(the)g(colored)0 5037 y(rectangles)25 +b(on)f(the)h(screen.)146 5159 y(Sometimes)j(it)h(is)g(con)l(v)o(enient) +f(to)g(mo)o(v)o(e)g(the)h(box)g(by)f(a)i(corner)g(other)e(than)h(the)g +(lo)n(wer)g(left.)43 b(T)-8 b(o)29 b(do)g(this,)0 5280 +y(press)e(the)g(left)g(mouse)g(b)n(utton)f(and)h Fg(hold)g(it)g(down)p +Ff(.)38 b(The)27 b(cursor)g(shape)h(changes)f(to)g(sho)n(w)f(you)h +(that)g(you)f(are)0 5400 y(mo)o(ving)d(the)i(box)f(by)g(its)g(lo)n(wer) +h(left)f(corner:)1875 5649 y(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Ff(September)25 b(26,)f(2001)1715 b(Magic)24 +b(T)l(utorial)g(#1:)30 b(Getting)24 b(Started)p 1870 +3 160 4 v 1868 124 4 121 v 2028 124 V 1870 127 160 4 +v 146 307 a(While)c(holding)f(the)h(b)n(utton)f(do)n(wn,)h(mo)o(v)o(e)e +(the)i(cursor)h(near)f(the)g(lo)n(wer)g(right)f(corner)i(of)f(the)g +(box,)h(and)f(no)n(w)0 428 y(click)j(the)g(right)f(mouse)g(b)n(utton)g +(\(i.e.)31 b(press)22 b(and)i(release)f(it,)g(while)g(still)e(holding)h +(do)n(wn)g(the)h(left)g(b)n(utton\).)29 b(The)0 548 y(cursor')-5 +b(s)28 b(shape)g(will)g(change)g(to)g(indicate)g(that)g(you)g(are)h(no) +n(w)e(mo)o(ving)g(the)h(box)g(by)g(its)g(lo)n(wer)f(right)h(corner)-5 +b(.)0 668 y(Mo)o(v)o(e)21 b(the)h(cursor)g(to)g(a)h(dif)n(ferent)f +(place)g(on)g(the)g(screen)h(and)g(release)f(the)h(left)f(b)n(utton.)28 +b(The)23 b(box)f(should)f(mo)o(v)o(e)0 789 y(so)h(that)h(its)f(lo)n +(wer)g(right)g(corner)h(is)f(at)h(the)g(cursor)g(position.)28 +b(T)m(ry)22 b(using)g(this)f(feature)j(to)e(mo)o(v)o(e)f(the)i(box)f +(so)h(that)0 909 y(it)h(is)h(almost)e(entirely)i(of)n(f-screen)g(to)f +(the)h(left.)30 b(T)m(ry)25 b(mo)o(ving)e(the)h(box)h(by)f(each)h(of)g +(its)f(corners.)146 1030 y(Y)-11 b(ou)27 b(can)h(also)f(reshape)g(the)g +(box)g(by)g(corners)g(other)g(than)g(the)g(upper)g(right.)37 +b(T)-8 b(o)27 b(do)g(this,)g(press)g(the)g(right)0 1150 +y(mouse)e(b)n(utton)f(and)h(hold)g(it)g(do)n(wn.)32 b(The)25 +b(cursor)h(shape)f(sho)n(ws)f(you)h(that)g(you)g(are)h(reshaping)f(the) +h(box)f(by)g(its)0 1270 y(upper)g(right)f(corner:)p 1870 +1406 V 2028 1526 4 121 v 146 1708 a(No)n(w)h(mo)o(v)o(e)g(the)g(cursor) +h(near)g(some)g(other)f(corner)i(of)e(the)h(box)f(and)h(click)g(the)f +(left)h(b)n(utton,)f(all)g(the)h(while)0 1829 y(holding)c(the)h(right)f +(b)n(utton)g(do)n(wn.)30 b(The)23 b(cursor)g(shape)g(will)g(change)g +(to)g(sho)n(w)f(you)h(that)g(no)n(w)f(you)h(are)h(reshap-)0 +1949 y(ing)k(the)g(box)f(by)h(a)h(dif)n(ferent)f(corner)-5 +b(.)41 b(When)28 b(you)g(release)h(the)f(right)f(b)n(utton,)h(the)g +(box)g(will)f(reshape)i(so)f(that)0 2069 y(the)h(selected)g(corner)g +(is)g(at)g(the)f(cursor)h(position)e(b)n(ut)i(the)g(diagonally)e +(opposite)h(corner)h(is)g(unchanged.)43 b(T)m(ry)0 2190 +y(reshaping)24 b(the)h(box)f(by)h(each)g(of)g(its)f(corners.)0 +2528 y Fh(7)143 b(In)-6 b(v)o(oking)34 b(Commands)0 2752 +y Ff(Commands)28 b(can)h(be)g(in)l(v)n(ok)o(ed)f(in)g(Magic)g(in)h +(three)g(w)o(ays:)38 b(by)28 b(pressing)g(b)n(uttons)f(on)i(the)f +(mouse;)i(by)e(typing)0 2872 y(single)i(k)o(e)o(ystrok)o(es)f(on)h(the) +g(te)o(xt)g(k)o(e)o(yboard)g(\(these)g(are)h(called)g +Fg(macr)l(os)p Ff(\);)h(or)f(by)f(typing)f(longer)h(commands)0 +2992 y(on)f(the)h(te)o(xt)e(k)o(e)o(yboard)h(\(these)g(are)i(called)e +Fg(long)g(commands)p Ff(\).)44 b(Man)o(y)28 b(of)i(the)f(commands)f +(use)i(the)f(box)g(and)0 3113 y(cursor)c(to)f(help)h(guide)f(the)h +(command.)146 3233 y(T)-8 b(o)35 b(see)g(ho)n(w)g(commands)e(can)j(be)f +(in)l(v)n(ok)o(ed)f(from)g(the)h(b)n(uttons,)h(\002rst)f(position)e +(the)i(box)g(o)o(v)o(er)f(a)h(small)0 3354 y(blank)27 +b(area)h(in)e(the)h(middle)f(of)i(the)e(screen.)39 b(Then)27 +b(mo)o(v)o(e)e(the)i(cursor)g(o)o(v)o(er)g(the)f(red)i(rectangle)f(and) +g(press)g(the)0 3474 y(middle)32 b(mouse)g(b)n(utton.)53 +b(At)33 b(this)f(point,)i(the)e(area)i(of)f(the)g(box)f(should)g(get)g +(painted)h(red.)55 b(No)n(w)32 b(mo)o(v)o(e)f(the)0 3594 +y(cursor)e(o)o(v)o(er)g(empty)f(space)i(and)f(press)g(the)g(middle)g(b) +n(utton)f(again.)43 b(The)29 b(red)h(paint)f(should)f(go)h(a)o(w)o(ay) +-6 b(.)43 b(Note)0 3715 y(ho)n(w)24 b(this)g(command)g(uses)g(both)g +(the)h(cursor)g(and)f(box)h(locations)e(to)i(control)f(what)h(happens.) +146 3835 y(As)f(an)g(e)o(xample)f(of)h(a)g(macro,)g(type)g(the)f +Fe(g)h Ff(k)o(e)o(y)f(on)h(the)g(te)o(xt)f(k)o(e)o(yboard.)29 +b(A)24 b(grid)g(will)f(appear)h(on)g(the)f(color)0 3955 +y(display)-6 b(,)27 b(along)g(with)g(a)i(small)d(black)i(box)g(marking) +f(the)g(origin)g(of)h(the)g(cell.)40 b(If)28 b(you)g(type)f +Fe(g)h Ff(again,)g(the)g(grid)0 4076 y(will)h(go)h(a)o(w)o(ay)-6 +b(.)46 b(Y)-11 b(ou)30 b(may)f(ha)n(v)o(e)h(noticed)g(earlier)g(that)g +(the)g(box)f(corners)i(didn')n(t)e(mo)o(v)o(e)g(to)g(the)h(e)o(xact)g +(cursor)0 4196 y(position:)f(you)24 b(can)h(see)g(no)n(w)f(that)h(the)f +(box)h(is)f(forced)h(to)g(f)o(all)f(on)h(grid)f(points.)146 +4317 y(Long)30 b(commands)f(are)j(in)l(v)n(ok)o(ed)d(by)h(typing)g(a)g +(colon)g(\(\223:\224\))43 b(or)31 b(semi-colon)e(\(\223;\224\).)48 +b(After)31 b(you)f(type)g(the)0 4437 y(colon)i(or)h(semi-colon,)g(the)g +(\223)p Fa(>)p Ff(\224)g(prompt)e(on)i(the)f(te)o(xt)g(screen)h(will)f +(be)h(replaced)g(by)f(a)h(\223:\224)47 b(prompt.)53 b(This)0 +4557 y(indicates)28 b(that)h(Magic)f(is)h(w)o(aiting)f(for)h(a)g(long)g +(command.)42 b(At)28 b(this)g(point)g(you)h(should)f(type)g(a)i(line)e +(of)h(te)o(xt,)0 4678 y(follo)n(wed)d(by)h(a)g(return.)37 +b(When)27 b(the)g(long)g(command)f(has)h(been)g(processed,)g(the)g +(\223)p Fa(>)p Ff(\224)h(prompt)e(reappears)h(on)0 4798 +y(the)h(te)o(xt)f(display)-6 b(.)39 b(T)m(ry)27 b(typing)g(semi-colon)g +(follo)n(wed)g(by)h(return)g(to)g(see)g(ho)n(w)f(this)g(w)o(orks.)40 +b(Occasionally)28 b(a)0 4918 y(\223]\224)f(\(right)f(brack)o(et\))i +(prompt)d(will)h(appear)-5 b(.)36 b(This)26 b(means)g(that)h(the)f +(design-rule)g(check)o(er)i(is)e(re)n(v)o(erifying)f(part)0 +5039 y(of)g(your)f(design.)30 b(F)o(or)25 b(no)n(w)f(you)g(can)i(just)d +(ignore)i(this)f(and)h(treat)g(\223]\224)g(lik)o(e)f(\223)p +Fa(>)p Ff(\224.)146 5159 y(Each)30 b(long)e(command)g(consists)f(of)i +(the)g(name)g(of)g(the)g(command)e(follo)n(wed)h(by)h(ar)n(guments,)g +(if)g(an)o(y)f(are)0 5280 y(needed)23 b(by)f(that)f(command.)29 +b(The)23 b(command)e(name)h(can)h(be)f(abbre)n(viated,)g(just)g(as)g +(long)g(as)g(you)g(type)g(enough)0 5400 y(characters)30 +b(to)f(distinguish)d(it)j(from)g(all)g(other)g(long)f(commands.)42 +b(F)o(or)29 b(e)o(xample,)h Fe(:h)f Ff(and)g Fe(:he)h +Ff(may)f(be)g(used)1875 5649 y(\2266\226)p eop +%%Page: 7 7 +7 6 bop 0 -180 a Ff(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)1715 b(September)25 b(26,)g(2001)0 68 y(as)32 +b(abbre)n(viations)d(for)j Fe(:help)p Ff(.)52 b(On)31 +b(the)g(other)g(hand,)i Fe(:u)f Ff(may)f(not)g(be)h(used)f(as)g(an)h +(abbre)n(viation)e(for)i Fe(:undo)0 188 y Ff(because)25 +b(there)g(is)g(another)f(command,)g Fe(:upsidedo)o(wn)p +Ff(,)i(that)f(has)f(the)h(same)g(abbre)n(viation.)k(T)m(ry)24 +b(typing)g Fe(:u)p Ff(.)146 309 y(As)32 b(an)g(e)o(xample)e(of)i(a)g +(long)f(command,)i(put)e(the)g(box)g(o)o(v)o(er)g(empty)g(space)h(on)g +(the)f(color)h(display)-6 b(,)31 b(then)0 429 y(in)l(v)n(ok)o(e)24 +b(the)h(long)f(command)900 657 y Fe(:paint)i(r)n(ed)146 +886 y Ff(The)f(box)f(should)f(\002ll)i(with)f(the)g(red)h(color)l(,)g +(just)e(as)i(if)f(you)h(had)f(used)g(the)h(middle)e(mouse)h(b)n(utton)g +(to)g(paint)0 1006 y(it.)54 b(Ev)o(erything)32 b(you)g(can)h(do)g(in)f +(Magic)h(can)g(be)g(in)l(v)n(ok)o(ed)f(with)g(a)h(long)g(command.)53 +b(It)33 b(turns)g(out)f(that)g(the)0 1126 y(macros)c(are)h(just)f(con)l +(v)o(eniences)f(that)h(are)h(e)o(xpanded)f(into)f(long)h(commands)f +(and)h(e)o(x)o(ecuted.)41 b(F)o(or)28 b(e)o(xample,)0 +1247 y(the)d(long)f(command)g(equi)n(v)n(alent)e(to)j(the)g +Fe(g)f Ff(macro)h(is)900 1475 y Fe(:grid)146 1703 y Ff(Magic)c(permits) +e(you)h(to)g(de\002ne)i(ne)n(w)e(macros)g(if)h(you)f(wish.)28 +b(Once)21 b(you')-5 b(v)o(e)20 b(become)h(f)o(amiliar)f(with)f(Magic)0 +1824 y(you')o(ll)i(almost)g(certainly)g(w)o(ant)h(to)g(add)g(your)f(o)n +(wn)h(macros)f(so)h(that)f(you)h(can)g(in)l(v)n(ok)o(e)g(quickly)f(the) +g(commands)0 1944 y(you)j(use)h(most)f(frequently)-6 +b(.)30 b(See)25 b(the)g Fg(ma)o(gic\(1\))f Ff(man)h(page)g(under)g(the) +f(command)g Fe(:macr)n(o)p Ff(.)146 2065 y(One)h(more)g(long)f(command) +g(is)g(of)h(immediate)e(use)i(to)g(you.)30 b(It)25 b(is)900 +2293 y Fe(:quit)146 2521 y Ff(In)l(v)n(ok)o(e)d(this)g(command.)29 +b(Note)22 b(that)f(before)i(e)o(xiting,)e(Magic)h(will)g(gi)n(v)o(e)f +(you)g(one)i(last)e(chance)i(to)f(sa)n(v)o(e)g(the)0 +2642 y(information)h(that)i(you')-5 b(v)o(e)24 b(modi\002ed.)30 +b(T)-8 b(ype)25 b Fe(y)f Ff(to)h(e)o(xit)e(without)h(sa)n(ving)g(an)o +(ything.)1875 5649 y(\2267\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut10.ps b/doc/psfiles/tut10.ps new file mode 100644 index 00000000..de0761c2 --- /dev/null +++ b/doc/psfiles/tut10.ps @@ -0,0 +1,733 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tut10.dvi +%%Pages: 9 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tut10.dvi -o tut10.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut10.dvi) +@start /Fa 1 16 df<0001FF0000000FFFE000003FFFF800007FFFFC0001FFFFFF0003 +FFFFFF8007FFFFFFC00FFFFFFFE01FFFFFFFF01FFFFFFFF03FFFFFFFF87FFFFFFFFC7FFF +FFFFFC7FFFFFFFFCFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFF +FFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFE7FFFFFFFFC7FFFFFFFFC7FFFFFFF +FC3FFFFFFFF81FFFFFFFF01FFFFFFFF00FFFFFFFE007FFFFFFC003FFFFFF8001FFFFFF00 +007FFFFC00003FFFF800000FFFE0000001FF000027267BAB32>15 +D E /Fb 133[44 50 50 72 50 55 33 39 44 1[55 50 55 83 +28 1[33 28 55 50 33 44 55 44 55 50 7[72 3[72 66 55 72 +2[78 72 94 66 2[39 3[66 72 72 66 72 6[33 7[50 50 50 1[25 +33 2[50 42[{ TeXBase1Encoding ReEncodeFont }46 100.000003 +/Times-Bold rf /Fc 134[60 3[66 40 47 53 2[60 66 100 33 +2[33 66 60 1[53 66 53 1[60 12[80 1[86 4[113 80 5[73 2[86 +8[40 4[60 1[60 60 60 2[30 43[66 2[{ TeXBase1Encoding ReEncodeFont }29 +119.999948 /Times-Bold rf /Fd 105[50 1[44 44 10[33 13[44 +50 50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 +50 33 44 50 44 50 44 33 2[33 1[33 3[94 1[72 61 55 66 +1[55 72 72 89 61 1[39 33 72 72 55 61 72 66 66 72 5[28 +28 50 50 50 50 50 50 50 50 50 50 1[25 33 25 2[33 33 33 +3[50 1[33 29[55 55 2[{ TeXBase1Encoding ReEncodeFont }75 +100.000003 /Times-Roman rf /Fe 134[44 2[44 50 28 39 39 +1[50 50 50 72 28 2[28 50 50 28 44 50 44 50 50 12[55 1[61 +1[61 1[66 83 3[33 2[61 1[72 66 1[61 11[50 2[50 50 2[25 +33 3[33 33 37[50 2[{ TeXBase1Encoding ReEncodeFont }38 +100.000003 /Times-Italic rf /Ff 104[143 28[64 72 1[104 +72 80 48 56 64 1[80 72 80 120 40 80 1[40 80 72 48 64 +80 64 80 72 48 8[143 104 104 96 80 104 1[88 1[104 135 +96 2[56 112 112 3[104 8[48 72 72 72 72 72 72 72 72 72 +72 2[48 36 4[48 3[72 35[{ TeXBase1Encoding ReEncodeFont }54 +143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 617 101 a Ff(Magic)35 b(T)-13 b(utorial)34 b(#10:)44 +b(The)35 b(Interacti)o(v)o(e)d(Router)1637 521 y Fe(Mic)o(hael)24 +b(Arnold)1731 941 y Fd(O)h(Di)n(vision)1116 1062 y(La)o(wrence)g(Li)n +(v)o(ermore)e(National)h(Laboratory)1511 1182 y(Li)n(v)o(ermore,)f(CA)i +(94550)1053 1453 y(This)f(tutorial)g(corresponds)g(to)g(Magic)h(v)o +(ersion)e(7.)0 1979 y Fc(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:) +300 2182 y Fd(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)300 2302 y(Magic)g(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)300 2423 y(Magic)f(T)l(utorial)g(#4:)30 +b(Cell)25 b(Hierarchies)0 2625 y Fc(Commands)k(intr)n(oduced)j(in)f +(this)f(tutorial:)300 2827 y Fd(:iroute)0 3030 y Fc(Macr)n(os)f(intr)n +(oduced)i(in)g(this)f(tutorial:)300 3256 y Fd(\210R,)25 +b(\210N)0 3852 y Ff(1)143 b(Intr)m(oduction)0 4076 y +Fd(The)33 b(Magic)f(interacti)n(v)o(e)g(router)l(,)j +Fe(Ir)l(outer)p Fd(,)e(pro)o(vides)f(an)h(interacti)n(v)o(e)f(interf)o +(ace)h(to)f(Magic')-5 b(s)32 b(internal)h(maze)0 4196 +y(router)-5 b(.)47 b(It)31 b(is)f(intended)g(as)g(an)h(aid)f(to)h +(manual)f(routing.)46 b(Routing)30 b(is)g(done)g(one)h(connection)f(at) +g(a)h(time,)g(the)0 4317 y(user)22 b(specifying)e(a)i(starting)f(point) +f(and)i(destination)e(areas)i(prior)f(to)h(each)g(connection.)29 +b(The)21 b(user)h(determines)0 4437 y(the)27 b(order)h(in)f(which)f +(signals)g(are)i(routed)f(and)h(ho)n(w)e(multi-point)f(nets)i(are)h +(decomposed)e(into)g(point-to-area)0 4557 y(connections.)49 +b(In)31 b(addition)f(parameters)h(and)g(special)g(Magic)f +Fe(hint)h Fd(layers)g(permit)f(the)h(user)g(to)g(control)f(the)0 +4678 y(nature)25 b(of)h(the)f(routes.)31 b(T)-8 b(ypically)24 +b(the)h(user)h(determines)e(the)h(o)o(v)o(erall)f(path)h(of)g(a)h +(connection,)e(and)h(lea)n(v)o(es)g(the)0 4798 y(details)f(of)h +(satisfying)e(the)i(design-rules,)f(and)g(detouring)g(around)h(or)g(o)o +(v)o(er)f(minor)g(obstacles,)g(to)g(the)h(router)-5 b(.)146 +4918 y(The)23 b(interacti)n(v)o(e)f(router)g(is)h(not)f(designed)g(for) +h(fully)f(automatic)g(routing:)28 b(interactions)22 b(between)h(nets)f +(are)0 5039 y(not)32 b(considered,)h(and)f(net)g(decomposition)e(is)i +(not)f(automatic.)52 b(Thus)31 b(netlists)g(are)i(generally)f(not)f +(suitable)0 5159 y(input)e(for)i(the)f(Irouter)-5 b(.)47 +b(Ho)n(we)n(v)o(er)29 b(it)g(can)i(be)f(con)l(v)o(enient)g(to)f(obtain) +h(endpoint)f(information)g(from)h(netlists.)0 5280 y(The)25 +b Fe(Net2ir)f Fd(program)g(uses)g(netlist)f(information)g(to)h +(generate)h(commands)f(to)g(the)g(Irouter)h(with)e(appropriate)0 +5400 y(endpoints)j(for)i(speci\002ed)f(signals.)38 b(T)-8 +b(ypically)26 b(a)i(user)g(might)e(setup)h(parameters)g(and)h(hints)e +(to)h(ri)n(v)o(er)n(-route)g(a)1875 5649 y(\2261\226)p +eop +%%Page: 2 2 +2 1 bop 0 -180 a Fd(September)25 b(26,)f(2001)1373 b(Magic)25 +b(T)l(utorial)e(#10:)30 b(The)25 b(Interacti)n(v)o(e)f(Router)0 +68 y(set)g(of)g(connections,)f(and)h(then)g(generate)g(Irouter)h +(commands)d(with)i(the)g(appropriate)g(endpoints)e(via)i(Net2ir)-5 +b(.)0 188 y(F)o(or)25 b(details)f(on)g(Net2ir)h(see)g(the)g(manual)f +(page)h Fe(net2ir\(1\))p Fd(.)146 310 y(This)38 b(tutorial)g(pro)o +(vides)f(detailed)h(information)f(on)i(the)f(use)g(of)h(the)g(Irouter) +-5 b(.)71 b(On-line)38 b(help,)k(Irouter)0 430 y(subcommands,)23 +b(Irouter)i(parameters,)g(and)f(hint-layers)g(are)i(e)o(xplained.)0 +777 y Ff(2)143 b(Getting)26 b(Started\227`Cntl-R',)d(`Cntl-N',)i(`:ir)m +(oute')h(and)g(`:ir)m(oute)g(help')0 1003 y Fd(T)-8 b(o)22 +b(mak)o(e)h(a)f(connection)g(with)g(the)g(Irouter)l(,)h(place)f(the)h +(cursor)f(o)o(v)o(er)g(one)g(end)g(of)h(the)f(desired)g(connection)g +(\(the)0 1123 y Fe(start-point)p Fd(\))h(and)i(the)f(box)h(at)f(the)h +(other)g(end)f(\(the)h Fe(destination-ar)l(ea)p Fd(\).)k(Then)c(type) +900 1360 y Fb(Cntl-R)146 1596 y Fd(Note)36 b(that)g(the)g(box)f(must)g +(be)h(big)g(enough)f(to)h(allo)n(w)f(the)h(route)g(to)f(terminate)h +(entirely)f(within)g(it.)64 b(A)0 1717 y(design-rule)24 +b(correct)i(connection)e(between)h(the)f(cursor)h(and)g(the)f(box)h +(should)e(appear)-5 b(.)31 b(The)25 b(macro)900 1954 +y Fb(Cntl-R)146 2190 y Fd(and)g(the)g(long)f(commands)900 +2427 y Fb(:ir)n(oute)900 2547 y(:ir)n(oute)i(r)n(oute)146 +2784 y Fd(are)32 b(all)e(equi)n(v)n(alent.)46 b(The)o(y)30 +b(in)l(v)n(ok)o(e)g(the)g(Irouter)h(to)f(connect)g(the)h(cursor)f(with) +g(the)h(interior)f(of)g(the)h(box.)0 2904 y(Note)25 b(that)g(the)g +(last)g(connection)f(is)h(al)o(w)o(ays)g(left)g(selected.)33 +b(This)24 b(allo)n(ws)g(further)i(terminals)e(to)h(be)g(connected)0 +3024 y(to)f(the)h(route)g(with)f(the)g(second)h(Irouter)g(macro,)g +Fb(Cntl-N)p Fd(.)g(T)m(ry)f(typing)900 3262 y Fb(Cntl-N)146 +3498 y Fd(A)37 b(connection)f(between)h(the)g(cursor)g(and)g(the)g(pre) +n(vious)e(route)i(should)f(appear)-5 b(.)67 b(In)37 b(general)g +Fb(Cntl-N)0 3618 y Fd(routes)24 b(from)h(the)g(cursor)f(to)h(the)g +(selection.)146 3739 y(There)36 b(are)g(a)f(number)f(of)i(commands)d +(to)i(set)g(parameters)g(and)g(otherwise)f(interact)h(with)g(the)f +(Irouter)-5 b(.)0 3860 y(These)25 b(commands)e(ha)n(v)o(e)i(the)g +(general)g(form)900 4097 y Fb(:ir)n(oute)p Fe(subcommand)g +Fd([)p Fe(ar)l(guments)p Fd(])146 4333 y(F)o(or)g(a)g(list)f(of)h +(subcommands)e(and)i(a)g(short)f(description)g(of)g(each,)i(type)900 +4570 y Fb(:ir)n(oute)g(help)146 4806 y Fd(Usage)f(information)f(on)g(a) +h(subcommand)e(can)j(be)f(obtained)f(by)g(typing)900 +5044 y Fb(:ir)n(oute)i(help)f Fd([)p Fe(subcommand)p +Fd(])146 5280 y(As)h(with)g(Magic)f(in)h(general,)h(unique)e(abbre)n +(viations)f(of)j(subcommands)d(and)i(most)f(of)h(their)g(ar)n(guments)0 +5400 y(are)g(permitted.)j(Case)d(is)e(generally)h(ignored.)1875 +5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#10:)30 +b(The)25 b(Interacti)n(v)o(e)f(Router)1373 b(September)25 +b(26,)g(2001)0 99 y Ff(3)143 b(:Undo)35 b(and)g(Cntl-C)0 +322 y Fd(As)k(with)g(other)h(Magic)f(commands,)j(the)d(results)g(of)h +Fb(:ir)n(oute)g Fd(can)g(be)g(undone)f(with)g Fb(:undo)p +Fd(,)44 b(and)c(if)f(the)0 443 y(Irouter)24 b(is)g(taking)g(too)g(long) +f(it)h(can)h(be)f(interrupted)g(with)f Fb(Cntl-C)p Fd(.)i(This)e(mak)o +(es)h(it)g(easy)h(to)e(re\002ne)j(the)e(results)0 563 +y(of)29 b(the)f(Irouter)g(by)h(trial)f(and)g(error)-5 +b(.)42 b(If)29 b(you)e(don')n(t)i(lik)o(e)e(the)i(results)e(of)i(a)g +(route,)g(undo)f(it,)g(tweak)h(the)f(Irouter)0 683 y(parameters)21 +b(or)g(hints)f(you)h(are)h(using)e(and)h(try)g(again.)28 +b(If)22 b(the)f(Irouter)g(is)g(taking)f(too)g(long,)h(you)g(can)g(v)o +(ery)g(lik)o(ely)0 804 y(speed)j(things)f(up)h(by)g(interrupting)f(it,) +h(resetting)f(performance)i(related)f(parameters,)h(and)f(trying)f +(again.)30 b(The)0 924 y(details)24 b(of)h(parameters)g(and)g(hints)e +(are)j(described)f(later)f(in)h(this)f(document.)0 1257 +y Ff(4)143 b(Mor)m(e)36 b(about)f(Making)g(Connections\227`:ir)m(oute)d +(r)m(oute')0 1481 y Fd(Start)25 b(points)f(for)h(routes)g(can)g(be)g +(speci\002ed)g(via)g(the)g(cursor)l(,)g(labels,)f(or)h(coordinates.)31 +b(Destination)23 b(areas)j(can)0 1601 y(be)c(speci\002ed)f(via)h(the)f +(box,)h(labels,)f(coordinates)g(or)h(the)f(selection.)29 +b(In)21 b(addition)g(start)g(and)g(destination)f(layers)0 +1722 y(can)25 b(be)g(speci\002ed)g(e)o(xplicitly)-6 b(.)28 +b(F)o(or)d(the)g(syntax)f(of)h(all)f(these)h(options)e(type)900 +1903 y Fb(:ir)n(oute)j(help)f(r)n(oute)146 2085 y Fd(When)38 +b(a)f(start)g(point)f(lies)h(on)g(top)f(of)h(e)o(xisting)f(geometry)g +(it)h(is)g(assumed)f(that)h(a)g(connection)g(to)g(that)0 +2205 y(material)31 b(is)g(desired.)50 b(If)31 b(this)g(is)g(not)f(the)i +(case,)h(the)e(desired)g(starting)f(layer)i(must)e(be)i(e)o(xplicitly)d +(speci\002ed.)0 2325 y(When)36 b(routing)f(to)h(the)g(selection)f(it)h +(is)g(assumed)f(that)h(connection)f(to)h(the)g(selected)g(material)g +(is)f(desired.)0 2446 y(By)d(def)o(ault,)g(routes)f(to)g(the)g(box)g +(may)g(terminate)g(on)g(an)o(y)g(acti)n(v)o(e)f(route)h(layer)-5 +b(.)50 b(If)32 b(you)f(are)h(ha)n(ving)f(trouble)0 2566 +y(connecting)21 b(to)h(a)g(lar)n(ge)h(re)o(gion,)e(it)h(may)g(be)g +(because)g(the)g(connection)f(point)g(or)h(area)h(is)f(too)f(f)o(ar)i +(in)f(the)g(interior)0 2687 y(of)31 b(the)g(re)o(gion.)48 +b(T)m(ry)31 b(mo)o(ving)e(it)h(to)n(w)o(ard)g(the)h(edge.)50 +b(\(Alternately)30 b(see)h(the)g(discussion)e(of)i(the)g +Fe(penetr)o(ation)0 2807 y Fd(parameter)25 b(in)g(the)f(wizard)h +(section)f(belo)n(w)-6 b(.\))0 3140 y Ff(5)143 b(Hints)0 +3364 y Fd(Magic)29 b(has)g(three)g(b)n(uilt-in)e(layers)i(for)h +(graphical)e(control)h(of)g(the)g(Irouter)l(,)h Fb(fence)g +Fd(\()p Fb(f)p Fd(\),)h Fb(magnet)e Fd(\()p Fb(mag)p +Fd(\),)h(and)0 3484 y Fb(r)n(otate)24 b Fd(\()p Fb(r)p +Fd(\).)30 b(These)23 b(layers)g(can)g(be)g(painted)f(and)h(erased)g +(just)f(lik)o(e)g(other)h(Magic)f(layers.)30 b(The)23 +b(ef)n(fect)g(each)g(has)0 3604 y(on)i(the)f(Irouter)h(is)g(described)f +(belo)n(w)-6 b(.)0 3893 y Fc(5.1)119 b(The)30 b(F)m(ence)h(Lay)o(er)0 +4081 y Fd(The)38 b(Irouter)f(w)o(on')n(t)h(cross)f(fence)h(boundaries.) +69 b(Thus)37 b(the)g(fence)h(layer)g(is)f(useful)h(both)e(for)i +(carving)g(out)0 4201 y(routing-re)o(gions)20 b(and)j(for)f(blocking)f +(routing)h(in)g(gi)n(v)o(en)e(areas.)31 b(It)22 b(is)g(frequently)g +(useful)g(to)g(indicate)g(the)g(broad)0 4322 y(path)k(of)g(one)g(or)g +(a)g(series)g(of)g(routes)g(with)f(fence.)35 b(In)26 +b(addition)e(to)i(guiding)f(the)g(route,)h(the)g(use)g(of)g(fences)h +(can)0 4442 y(greatly)e(speed)f(up)h(the)g(router)f(by)h(limiting)d +(the)j(search.)0 4731 y Fc(5.2)119 b(The)30 b(Magnet)g(Lay)o(er)0 +4918 y Fd(Magnets)f(attract)g(the)g(route.)45 b(The)o(y)29 +b(can)g(be)h(used)f(to)g(pull)g(routes)g(in)g(a)h(gi)n(v)o(en)d +(direction,)j(e.g.,)h(to)n(w)o(ards)d(one)0 5039 y(edge)c(of)f(a)h +(channel.)30 b(Ov)o(er)23 b(use)h(of)f(magnets)g(can)h(mak)o(e)f +(routing)g(slo)n(w)-6 b(.)28 b(In)c(particular)f(magnets)g(that)g(are)h +(long)0 5159 y(and)j(f)o(ar)g(a)o(w)o(ay)g(from)f(the)h(actual)f(route) +h(can)g(cause)g(performance)g(problems.)35 b(\(If)28 +b(you)e(are)h(ha)n(ving)f(problems)0 5280 y(with)37 b(magnets)f(and)h +(performance,)k(see)d(also)f(the)g(discussion)f(of)h(the)g +Fe(penalty)g Fd(parameter)h(in)f(the)g(wizard)0 5400 +y(section)24 b(belo)n(w)-6 b(.\))1875 5649 y(\2263\226)p +eop +%%Page: 4 4 +4 3 bop 0 -180 a Fd(September)25 b(26,)f(2001)1373 b(Magic)25 +b(T)l(utorial)e(#10:)30 b(The)25 b(Interacti)n(v)o(e)f(Router)0 +82 y Fc(5.3)119 b(The)30 b(Rotate)g(Lay)o(er)0 270 y +Fd(The)21 b(Irouter)f(associates)h(dif)n(ferent)f(weights)f(with)h +(horizontal)g(and)h(v)o(ertical)f(routes)g(\(see)h(the)f(layer)n +(-parameter)0 390 y(section)g(belo)n(w\).)29 b(This)20 +b(is)h(so)g(that)f(a)i(preferred)g(routing)e(direction)g(can)i(be)f +(established)f(for)h(each)h(layer)-5 b(.)29 b(When)0 +511 y(tw)o(o)f(good)g(route-layers)h(are)g(a)n(v)n(ailable)f(\(as)h(in) +f(a)h(tw)o(o-layer)n(-metal)g(process\))f(interference)i(between)f +(routes)0 631 y(can)c(be)g(minimized)e(by)i(assigning)e(opposite)h +(preferred)i(directions)d(to)i(the)f(layers.)146 752 +y(The)35 b(rotate)f(layer)h(locally)f(in)l(v)o(erts)f(the)i(preferred)g +(directions.)59 b(An)34 b(e)o(xample)g(use)g(of)h(the)f(rotate)h(layer) +0 872 y(might)18 b(in)l(v)n(olv)o(e)g(an)h Fb(L)p Fd(-shaped)h(b)n(us.) +28 b(The)19 b(natural)g(preferred)i(directions)d(on)h(one)g(le)o(g)g +(of)g(the)g Fb(L)h Fd(are)g(the)f(opposite)0 992 y(from)25 +b(the)f(other)l(,)h(and)g(thus)f(one)g(le)o(g)g(needs)h(to)g(be)g(mark) +o(ed)f(with)g(the)h(rotate)g(layer)-5 b(.)0 1331 y Ff(6)143 +b(Subcells)0 1555 y Fd(As)33 b(with)g(painting)f(and)h(other)g +(operations)g(in)g(Magic,)i(the)e(Irouter')-5 b(s)33 +b(output)f(is)h(written)g(to)g(the)g(cell)h(being)0 1675 +y(edited.)j(What)27 b(the)g(router)g(sees,)h(that)e(is)h(which)g +(features)g(act)h(as)f(obstacles,)g(is)f(determined)h(by)g(the)f(windo) +n(w)0 1795 y(the)c(route)g(is)g(issued)f(to)h(\(or)g(other)g +(designated)g(reference)h(windo)n(w)e(-)i(see)f(the)g(wizard)g +(section.\))30 b(The)22 b(contents)0 1916 y(of)29 b(subcells)f(e)o +(xpanded)g(in)g(the)h(route)g(windo)n(w)e(are)j(visible)d(to)i(the)f +(Irouter)l(,)i(b)n(ut)f(it)f(only)g(sees)h(the)g(bounding)0 +2036 y(box)o(es)34 b(of)h(une)o(xpanded)f(subcells.)61 +b(These)35 b(bounding)f(box)o(es)g(appear)h(on)g(a)h(special)e +Fb(SUBCELL)k Fd(pseudo-)0 2157 y(layer)-5 b(.)56 b(The)34 +b(spacing)f(parameters)g(to)g(the)h Fb(SUBCELL)h Fd(layer)f(determine)f +(e)o(xactly)g(ho)n(w)f(the)i(Irouter)f(treats)0 2277 +y(une)o(xpanded)28 b(subcells.)41 b(\(See)29 b(the)g(section)f(on)g +(spacing)g(parameters)h(belo)n(w)-6 b(.\))40 b(By)29 +b(def)o(ault,)g(the)g(spacings)e(to)0 2397 y(the)21 b +Fb(SUBCELL)j Fd(layer)e(are)g(lar)n(ge)g(enough)f(to)g(guarantee)h +(that)g(no)f(design-rules)f(will)h(be)h(violated,)f(re)o(gardless)0 +2518 y(of)31 b(the)f(contents)g(of)h(une)o(xpanded)e(subcells.)47 +b(Routes)31 b(can)g(be)f(terminated)g(at)h(une)o(xpanded)e(subcells)h +(in)g(the)0 2638 y(same)25 b(f)o(ashion)f(that)g(connections)g(to)g +(other)h(pre-e)o(xisting)e(features)j(are)f(made.)0 2977 +y Ff(7)143 b(Lay)o(er)34 b(P)o(arameters\227`:ir)m(oute)e(lay)o(ers')0 +3200 y Fe(Route-layer)o(s)p Fd(,)i(speci\002ed)e(in)g(the)h +Fb(mzr)n(outer)h Fd(section)e(of)g(the)h(technology)e(\002le,)k(are)e +(the)f(layers)h(potentially)0 3321 y(a)n(v)n(ailable)26 +b(to)g(the)h(Irouter)g(for)g(routing.)36 b(The)27 b Fb(lay)o(er)f +Fd(subcommand)g(gi)n(v)o(es)f(access)i(to)g(parameters)g(associated)0 +3441 y(with)20 b(these)h(route-layers.)30 b(Man)o(y)20 +b(of)h(the)g(parameters)g(are)h(weights)f(for)g(f)o(actors)g(in)g(the)g +(Irouter)g(cost-function.)0 3562 y(The)g(Irouter)f(stri)n(v)o(es)f(for) +i(the)f(cheapest)h(possible)e(route.)29 b(Thus)20 b(the)g(balance)h +(between)g(the)f(f)o(actors)h(in)f(the)g(cost-)0 3682 +y(function)k(determines)g(the)g(character)i(of)f(the)g(routes:)30 +b(which)24 b(layers)h(are)g(used)f(in)h(which)f(directions,)g(and)g +(the)0 3802 y(number)37 b(of)g(contacts)g(and)h(jogs)e(can)i(be)f +(controlled)g(in)g(this)f(w)o(ay)-6 b(.)68 b(But)38 b(be)f(careful!)70 +b(Changes)37 b(in)g(these)0 3923 y(parameters)28 b(can)g(also)f +(profoundly)g(in\003uence)h(performance.)40 b(Other)27 +b(parameters)h(determine)f(which)g(of)h(the)0 4043 y(route-layers)i +(are)i(actually)e(a)n(v)n(ailable)f(for)i(routing)f(and)g(the)g(width)g +(of)g(routes)h(on)f(each)h(layer)-5 b(.)47 b(It)31 b(is)f(a)h(good)0 +4164 y(idea)25 b(to)f(inacti)n(v)n(ate)g(route-layers)g(not)h(being)f +(used)g(an)o(yw)o(ay)-6 b(,)24 b(as)h(this)f(speeds)g(up)h(routing.)146 +4284 y(The)g(layers)g(subcommand)e(tak)o(es)i(a)g(v)n(ariable)f(number) +h(of)f(ar)n(guments.)900 4507 y Fb(:ir)n(oute)i(lay)o(ers)146 +4730 y Fd(prints)e(a)h(table)g(with)f(one)h(ro)n(w)f(for)h(each)h +(route-layer)e(gi)n(ving)g(all)g(parameter)h(v)n(alues.)900 +4954 y Fb(:ir)n(oute)h(lay)o(ers)p Fe(type)146 5177 y +Fd(prints)e(all)h(parameters)g(associated)f(with)g(route-layer)h +Fe(type)p Fd(.)900 5400 y Fb(:ir)n(oute)h(lay)o(ers)p +Fe(type)e(par)o(ameter)1875 5649 y Fd(\2264\226)p eop +%%Page: 5 5 +5 4 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#10:)30 +b(The)25 b(Interacti)n(v)o(e)f(Router)1373 b(September)25 +b(26,)g(2001)146 69 y(prints)f(the)h(v)n(alue)f(of)h +Fe(par)o(ameter)e Fd(for)i(layer)g Fe(type)p Fd(.)31 +b(If)25 b Fe(type)g Fd(is)f(`)p Fb(*)p Fd(',)h(the)f(v)n(alue)g(of)h +Fe(par)o(ameter)f Fd(is)g(printed)g(for)0 189 y(all)h(layers.)900 +374 y Fb(:ir)n(oute)h(lay)o(ers)e Fe(type)h(par)o(ameter)f(value)146 +559 y Fd(sets)h Fe(par)o(ameter)e Fd(to)i Fe(value)f +Fd(on)h(layer)g Fe(type)p Fd(.)31 b(If)25 b Fe(type)g +Fd(is)f(`)p Fb(*)p Fd(',)h Fe(par)o(ameter)f Fd(is)g(set)g(to)h +Fe(value)g Fd(on)f(all)h(layers.)900 744 y Fb(:ir)n(oute)h(lay)o(ers)e +Fe(type)h Fb(*)g Fe(value1)f(value2)h Fd(.)15 b(.)g(.)g +Fe(valuen)146 928 y Fd(sets)25 b(a)g(ro)n(w)f(in)h(the)f(parameter)h +(table.)900 1113 y Fb(:ir)n(oute)h(lay)o(ers)e(*)p Fe(par)o(ameter)g +(value1)g(.)15 b(.)g(.)g(valuen)146 1298 y Fd(sets)25 +b(a)g(column)f(in)g(the)h(table.)146 1418 y(There)h(are)f(six)f(layer)h +(parameters.)145 1603 y Fa(\017)49 b Fb(acti)o(v)o(e)244 +1724 y Fd(T)-8 b(ak)o(es)25 b(the)f(v)n(alue)h(of)f Fb(YES)i +Fd(\(the)f(def)o(ault\))g(or)g Fb(NO)p Fd(.)f(Only)g(acti)n(v)o(e)g +(layers)h(are)g(used)g(by)f(the)h(Irouter)-5 b(.)145 +1916 y Fa(\017)49 b Fb(width)244 2037 y Fd(W)l(idth)22 +b(of)g(routing)g(created)h(by)f(the)h(Irouter)f(on)g(the)h(gi)n(v)o(en) +e(layer)-5 b(.)30 b(The)22 b(def)o(ault)g(is)h(the)f(minimum)e(width) +244 2157 y(permitted)k(by)g(the)h(design)f(rules.)145 +2350 y Fa(\017)49 b Fb(hcost)244 2470 y Fd(Cost)24 b(per)i(unit-length) +d(for)i(horizontal)f(se)o(gments)f(on)h(this)g(layer)-5 +b(.)145 2662 y Fa(\017)49 b Fb(vcost)244 2783 y Fd(Cost)24 +b(per)i(unit-length)d(for)i(v)o(ertical)f(se)o(gments.)145 +2975 y Fa(\017)49 b Fb(jogcost)244 3096 y Fd(Cost)24 +b(per)i(jog)e(\(transition)f(from)i(horizontal)f(to)g(v)o(ertical)g(se) +o(gment\).)145 3288 y Fa(\017)49 b Fb(hintcost)244 3409 +y Fd(Cost)24 b(per)i(unit-area)f(between)f(actual)h(route)g(and)g +(magnet)f(se)o(gment.)0 3742 y Ff(8)143 b(Contact)34 +b(P)o(arameters\227`:ir)m(oute)d(contacts')0 3966 y Fd(The)25 +b Fb(contacts)g Fd(subcommand)f(gi)n(v)o(es)f(access)i(to)g(a)g(table)f +(of)h(parameters)g(for)g(contact-types)f(used)h(in)f(routing,)0 +4086 y(one)c(ro)n(w)g(of)h(parameters)f(per)h(type.)29 +b(The)20 b(syntax)g(is)g(identical)g(to)g(that)g(of)g(the)g +Fb(lay)o(ers)g Fd(subcommand)f(described)0 4207 y(abo)o(v)o(e,)24 +b(and)g(parameters)h(are)h(printed)e(and)h(set)g(in)f(the)h(same)f(w)o +(ay)-6 b(.)146 4327 y(There)26 b(are)f(three)g(contact-parameters.)145 +4512 y Fa(\017)49 b Fb(acti)o(v)o(e)244 4632 y Fd(T)-8 +b(ak)o(es)20 b(the)g(v)n(alue)g(of)g Fb(YES)i Fd(\(the)e(def)o(ault\))g +(or)h Fb(NO)p Fd(.)e(Only)h(acti)n(v)o(e)f(contact)i(types)e(are)i +(used)f(by)g(the)g(Irouter)-5 b(.)145 4825 y Fa(\017)49 +b Fb(width)244 4945 y Fd(Diameter)28 b(of)h(contacts)f(of)h(this)f +(type)g(created)h(by)g(the)f(Irouter)-5 b(.)42 b(The)29 +b(def)o(ault)f(is)g(the)h(minimum)d(width)244 5066 y(permitted)e(by)g +(the)h(design-rules.)145 5258 y Fa(\017)49 b Fb(cost)244 +5378 y Fd(Cost)24 b(per)i(contact)e(char)n(ged)i(by)e(the)h(Irouter)g +(cost-function.)1875 5649 y(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Fd(September)25 b(26,)f(2001)1373 b(Magic)25 +b(T)l(utorial)e(#10:)30 b(The)25 b(Interacti)n(v)o(e)f(Router)0 +99 y Ff(9)143 b(Spacing)34 b(P)o(arameters\227`:ir)m(oute)e(spacing')0 +322 y Fd(The)43 b(spacing)f(parameters)h(specify)g(minimum)e(spacings)h +(between)h(the)g(route-types)f(\(route-layers)h(and)0 +443 y(route-contacts\))38 b(and)f(arbitrary)h(Magic)g(types.)69 +b(These)38 b(spacings)f(are)i(the)f(design-rules)f(used)g(internally)0 +563 y(by)31 b(the)f(Irouter)h(during)f(routing.)48 b(Def)o(ault)30 +b(v)n(alues)g(are)i(deri)n(v)o(ed)d(from)i(the)g Fb(dr)n(c)h +Fd(section)e(of)h(the)f(technology)0 683 y(\002le.)g(These)22 +b(v)n(alues)f(can)h(be)g(o)o(v)o(erridden)f(in)g(the)h +Fb(mzr)n(outer)h Fd(section)e(of)h(the)g(technology)f(\002le.)30 +b(\(See)23 b(the)e Fe(Ma)o(gic)0 804 y(Maintainer)o(s)27 +b(Manual)i(on)g(T)-9 b(ec)o(hnolo)o(gy)28 b(F)l(iles)g +Fd(for)i(details.\))43 b(Spacings)29 b(can)h(be)f(e)o(xamined)g(and)g +(changed)g(at)0 924 y(an)o(y)21 b(time)h(with)f(the)h +Fb(spacing)g Fd(subcommand.)28 b(Spacing)22 b(v)n(alues)f(can)h(be)h +Fb(nil)p Fd(,)f Fb(0)p Fd(,)g(or)g(positi)n(v)o(e)e(inte)o(gers.)29 +b(A)22 b(v)n(alue)0 1045 y(of)k Fb(nil)g Fd(means)f(there)i(is)e(no)h +(spacing)f(constraint)g(between)h(the)g(route-layer)g(and)g(the)g(gi)n +(v)o(en)e(type.)34 b(A)26 b(v)n(alue)f(of)0 1165 y Fb(0)g +Fd(means)g(the)f(route-layer)h(may)g(not)g(o)o(v)o(erlap)e(the)i(gi)n +(v)o(en)f(type.)31 b(If)25 b(a)g(positi)n(v)o(e)e(v)n(alue)h(is)h +(speci\002ed,)g(the)g(Irouter)0 1285 y(will)g(maintain)g(the)h(gi)n(v)o +(en)e(spacing)h(between)h(ne)n(w)g(routing)f(on)h(the)f(speci\002ed)i +(route-layer)f(and)g(pre-e)o(xisting)0 1406 y(features)21 +b(of)h(the)f(speci\002ed)g(type)g(\(e)o(xcept)f(when)h(connecting)g(to) +f(the)h(type)g(at)g(an)g(end-point)f(of)i(the)f(ne)n(w)f(route\).)146 +1526 y(The)25 b Fb(spacing)g Fd(subcommand)e(tak)o(es)i(se)n(v)o(eral)f +(forms.)900 1745 y Fb(:ir)n(oute)i(spacing)146 1963 y +Fd(prints)e(spacings)g(for)h(all)g(route-types.)30 b(\(Nil)24 +b(spacings)g(are)i(omitted.\))900 2181 y Fb(:ir)n(oute)g(spacing)f +Fe(r)l(oute-type)146 2400 y Fd(prints)f(spacings)g(for)h +Fe(r)l(oute-type)p Fd(.)30 b(\(Nil)24 b(spacings)g(are)i(omitted.\))900 +2618 y Fb(:ir)n(oute)g(spacing)f Fe(r)l(oute-type)f(type)146 +2837 y Fd(prints)g(the)h(spacing)f(between)h Fe(r)l(oute-type)f +Fd(and)h Fe(type)p Fd(.)900 3055 y Fb(:ir)n(oute)h(spacing)f +Fe(r)l(oute-type)f(type)h(value)146 3273 y Fd(sets)g(the)f(spacing)h +(between)f Fe(r)l(oute-type)g Fd(and)h Fe(type)g Fd(to)f +Fe(value)p Fd(.)146 3394 y(The)30 b(spacings)e(associated)h(with)g +(each)h(route-type)f(are)h(the)f(ones)h(that)f(are)h(observ)o(ed)e +(when)i(the)f(Irouter)0 3514 y(places)j(that)g(route-type.)53 +b(T)-8 b(o)33 b(change)f(the)g(spacing)g(between)h(tw)o(o)f +(route-types,)h(tw)o(o)f(spacing)g(parameters)0 3634 +y(must)26 b(be)i(changed:)36 b(the)27 b(spacing)g(to)g(the)g(\002rst)h +(type)f(when)g(routing)f(on)i(the)f(second,)h(and)f(the)g(spacing)g(to) +g(the)0 3755 y(second)e(type)f(when)h(routing)e(on)i(the)g(\002rst.)146 +3875 y(Spacings)j(to)f(the)g Fb(SUBCELL)j Fd(pseudo-type)d(gi)n(v)o(e)f +(the)h(minimum)e(spacing)j(between)f(a)h(route-type)f(and)0 +3996 y(une)o(xpanded)32 b(subcells.)54 b(The)33 b Fb(SUBCELL)i +Fd(spacing)d(for)h(a)g(gi)n(v)o(en)e(route-layer)i(def)o(aults)g(to)f +(the)h(maximum)0 4116 y(spacing)28 b(to)g(the)g(route-layer)h(required) +g(by)f(the)g(design-rules)g(\(in)g(the)h Fb(dr)n(c)g +Fd(section)f(of)h(the)f(technology)g(\002le\).)0 4236 +y(This)18 b(ensures)i(that)e(no)h(design-rules)g(will)f(be)h(violated)g +(re)o(gardless)f(of)h(the)g(contents)g(of)g(the)g(subcell.)28 +b(If)20 b(subcell)0 4357 y(designs)30 b(are)i(constrained)f(in)f(a)i(f) +o(ashion)e(that)h(permits)f(closer)i(spacings)e(to)h(some)f(layers,)j +(the)e Fb(SUBCELL)0 4477 y Fd(spacings)24 b(can)h(be)g(changed)g(to)f +(tak)o(e)h(adv)n(antage)g(of)g(this.)0 4815 y Ff(10)143 +b(Sear)m(ch)35 b(P)o(arameters\227`:sear)m(ch')0 5039 +y Fd(The)c(Mzrouter)g(search)g(is)f(windo)n(wed.)48 b(Early)31 +b(in)f(the)h(search)g(only)f(partial)h(paths)f(near)h(the)g(start)g +(point)e(are)0 5159 y(considered;)c(as)g(the)h(search)f(progresses)g +(the)g(windo)n(w)f(is)h(mo)o(v)o(ed)f(to)n(w)o(ards)g(the)h(goal.)32 +b(This)25 b(pre)n(v)o(ents)f(combi-)0 5280 y(natorial)29 +b(e)o(xplosion)f(during)i(the)g(search,)h(b)n(ut)f(still)e(permits)h +(the)h(e)o(xploration)e(of)j(alternati)n(v)o(es)d(at)i(all)g(stages.)0 +5400 y(The)23 b Fb(sear)n(ch)h Fd(subcommand)d(permits)h(access)h(to)f +(tw)o(o)h(parameters)g(controlling)e(the)i(windo)n(wed)e(search,)j +Fb(rate)p Fd(,)1875 5649 y(\2266\226)p eop +%%Page: 7 7 +7 6 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#10:)30 +b(The)25 b(Interacti)n(v)o(e)f(Router)1373 b(September)25 +b(26,)g(2001)0 69 y(and)30 b Fb(width)p Fd(.)45 b(The)30 +b Fb(rate)g Fd(parameter)g(determines)f(ho)n(w)g(f)o(ast)g(the)h(windo) +n(w)e(is)h(shifted)g(to)n(w)o(ards)f(the)i(goal,)g(and)0 +189 y(the)e Fb(width)g Fd(parameter)g(gi)n(v)o(es)e(the)i(width)f(of)g +(the)h(windo)n(w)-6 b(.)38 b(The)27 b(units)g(are)h(comparable)g(with)f +(those)g(used)g(in)0 309 y(the)h(cost)f(parameters.)40 +b(If)28 b(the)g(router)g(is)f(taking)g(too)g(long)h(to)f(complete,)h +(try)f(increasing)h Fb(rate)p Fd(.)40 b(If)28 b(the)g(router)0 +430 y(is)e(choosing)f(poor)h(routes,)g(try)g(decreasing)h +Fb(rate)p Fd(.)35 b(The)27 b(windo)n(w)d(width)i(should)f(probably)g +(be)i(at)f(least)g(twice)0 550 y(the)f(rate.)146 673 +y(The)g(subcommand)e(has)i(this)f(form:)900 923 y Fb(:ir)n(oute)i(sear) +n(ch)g Fd([)p Fe(par)o(ameter)p Fd(])d([)p Fe(value)p +Fd(])146 1171 y(If)i Fe(value)e Fd(is)h(omitted,)f(the)g(current)h(v)n +(alue)g(is)f(printed,)h(if)f Fe(par)o(ameter)g Fd(is)g(omitted)g(as)h +(well,)g(both)f(parameter)0 1291 y(v)n(alues)h(are)i(printed.)0 +1648 y Ff(11)143 b(Messages\227`:ir)m(oute)33 b(v)o(erbosity')0 +1877 y Fd(The)25 b(number)f(of)h(messages)f(printed)g(by)h(the)f +(Irouter)h(is)g(controlled)f(by)900 2127 y Fb(:ir)n(oute)i(v)o +(erbosity)p Fe(value)146 2375 y Fd(If)i(v)o(erbosity)d(is)i(set)g(to)g +Fb(0)p Fd(,)g(only)f(errors)i(and)f(w)o(arnings)f(are)i(printed.)37 +b(A)27 b(v)n(alue)g(of)g Fb(1)g Fd(\(the)g(def)o(ault\))g(results)0 +2495 y(in)d(short)h(messages.)30 b(A)24 b(v)n(alue)h(of)g +Fb(2)f Fd(causes)h(statistics)e(to)i(be)g(printed.)0 +2852 y Ff(12)143 b(V)-14 b(ersion\227`:ir)m(oute)33 b(v)o(ersion')0 +3081 y Fd(The)25 b(subcommand)900 3331 y Fb(:ir)n(oute)h(v)o(ersion)146 +3578 y Fd(prints)e(the)h(Irouter)g(v)o(ersion)f(in)g(use.)0 +3935 y Ff(13)143 b(Sa)l(ving)35 b(and)g(Restoring)e(P)o +(arameters\227`:ir)m(oute)f(sa)l(v)o(e')0 4164 y Fd(The)25 +b(command)900 4415 y Fb(:ir)n(oute)h(sa)n(v)o(e)e Fe(\002le)p +Fb(.ir)146 4662 y Fd(sa)n(v)o(es)31 b(a)o(w)o(ay)g(the)g(current)h +(settings)e(of)h(all)h(the)f(Irouter)g(parameters)h(in)f(\002le)h +Fe(\002le)p Fb(.ir)p Fd(.)50 b(P)o(arameters)31 b(can)h(be)0 +4782 y(reset)25 b(to)f(these)h(v)n(alues)f(at)h(an)o(y)f(time)g(with)g +(the)h(command)900 5032 y Fb(:sour)n(ce)h Fe(\002le)p +Fb(.ir)146 5280 y Fd(This)d(feature)h(can)f(be)g(used)g(to)g(setup)g +(parameter)n(-sets)g(appropriate)g(to)g(dif)n(ferent)f(routing)h(conte) +o(xts.)28 b(Note)0 5400 y(that)c(the)h(e)o(xtension)e +Fb(.ir)i Fd(is)f(recommended)h(for)g(Irouter)g(parameter)n(-\002les.) +1875 5649 y(\2267\226)p eop +%%Page: 8 8 +8 7 bop 0 -180 a Fd(September)25 b(26,)f(2001)1373 b(Magic)25 +b(T)l(utorial)e(#10:)30 b(The)25 b(Interacti)n(v)o(e)f(Router)0 +99 y Ff(14)143 b(W)m(izard)35 b(P)o(arameters\227`:ir)m(oute)d(wizard') +0 323 y Fd(Miscellaneous)27 b(parameters)i(that)f(are)i(probably)d(not) +h(of)h(interest)f(to)g(the)h(casual)g(user)f(are)i(accessed)f(via)f +(the)0 444 y Fb(wizard)d Fd(subcommand.)k(The)c(parameters)g(are)h(as)f +(follo)n(ws:)145 675 y Fa(\017)49 b Fb(bloom)40 b Fd(T)-8 +b(ak)o(es)40 b(on)g(a)g(non-ne)o(gati)n(v)o(e)d(inte)o(ger)i(v)n(alue.) +76 b(This)39 b(controls)h(the)f(amount)g(of)i(compulsory)244 +795 y(searching)26 b(from)h(a)g(focus,)g(before)g(the)g(ne)o(xt)e +(focus)i(is)f(pick)o(ed)h(based)f(on)h(the)f(cost-function)g(and)g +(win-)244 916 y(do)n(w)k(position.)48 b(In)31 b(practice)h +Fb(1)f Fd(\(the)g(def)o(ault)g(v)n(alue\))f(seems)h(to)g(be)g(the)g +(best)f(v)n(alue.)49 b(This)31 b(parameter)244 1036 y(may)24 +b(be)h(remo)o(v)o(ed)f(in)g(the)h(future.)145 1242 y +Fa(\017)49 b Fb(boundsIncr)n(ement)43 b Fd(T)-8 b(ak)o(es)39 +b(on)h(the)g(v)n(alue)f Fb(A)-5 b(UT)n(OMA)c(TIC)39 b +Fd(or)h(a)g(positi)n(v)o(e)d(inte)o(ger)-5 b(.)75 b(Determines)244 +1362 y(in)34 b(what)g(size)g(chunks)g(the)g(layout)g(is)g(preprocessed) +g(for)h(routing.)58 b(This)33 b(preprocessing)h(\(blockage)244 +1483 y(generation\))e(tak)o(es)h(a)g(signi\002cant)f(fraction)g(of)h +(the)g(routing)e(time,)j(thus)e(performance)h(may)g(well)f(be)244 +1603 y(impro)o(v)o(ed)23 b(by)h(e)o(xperimenting)f(with)h(this)g +(parameter)-5 b(.)145 1809 y Fa(\017)49 b Fb(estimate)35 +b Fd(T)-8 b(ak)o(es)35 b(on)g(a)g(boolean)g(v)n(alue.)60 +b(If)36 b Fb(ON)e Fd(\(the)h(def)o(ault\))g(an)g(estimation)e(plane)i +(is)g(generated)244 1929 y(prior)27 b(to)g(each)h(route)g(that)f +(permits)f(cost-to-completion)g(estimates)g(to)h(f)o(actor)h(in)f +(subcells)g(and)g(fence)244 2049 y(re)o(gions.)40 b(This)28 +b(can)g(be)h(v)o(ery)f(important)f(to)h(ef)n(\002cient)g(routing.)40 +b(Its)28 b(rarely)h(useful)f(to)g(turn)g(estimation)244 +2170 y(of)n(f.)145 2375 y Fa(\017)49 b Fb(expandDests)35 +b Fd(T)-8 b(ak)o(es)33 b(on)h(a)g(boolean)f(v)n(alue.)57 +b(If)34 b Fb(ON)f Fd(\(not)g(the)h(def)o(ault\))f(destination)f(areas)j +(are)f(e)o(x-)244 2496 y(panded)g(to)h(include)f(all)h(of)f(an)o(y)h +(nodes)f(the)o(y)g(o)o(v)o(erlap.)60 b(This)34 b(is)g(particularly)g +(useful)h(if)f(the)h(Irouter)244 2616 y(is)g(being)h(in)l(v)n(ok)o(ed)f +(from)h(a)g(script,)i(since)e(it)g(is)f(dif)n(\002cult)g(to)h +(determine)f(optimal)g(destination)f(areas)244 2737 y(automatically)-6 +b(.)145 2942 y Fa(\017)49 b Fb(penalty)33 b Fd(T)-8 b(ak)o(es)33 +b(on)f(a)i(rational)e(v)n(alue)g(\(def)o(ault)h(is)f(1024.0\).)54 +b(It)32 b(is)h(not)f(strictly)f(true)i(that)g(the)f(router)244 +3063 y(searches)k(only)e(within)g(its)h(windo)n(w)-6 +b(.)60 b(P)o(aths)34 b(behind)h(the)g(windo)n(w)f(are)i(also)f +(considered,)i(b)n(ut)e(with)244 3183 y(cost)27 b(penalized)g(by)h(the) +f(product)g(of)h(their)f(distance)g(to)g(the)h(windo)n(w)e(and)h(the)h +(penalty)f(f)o(actor)-5 b(.)39 b(It)27 b(w)o(as)244 3303 +y(originally)e(thought)g(that)g(small)h(penalties)f(might)g(be)h +(desirable,)h(b)n(ut)e(e)o(xperience,)i(so)f(f)o(ar)l(,)h(has)f(sho)n +(wn)244 3424 y(that)f(lar)n(ge)g(penalties)g(w)o(ork)g(better)-5 +b(.)31 b(In)25 b(particular)g(it)g(is)g(important)e(that)i(the)g(ratio) +g(between)g(the)g(actual)244 3544 y(cost)f(of)h(a)g(route)g(and)g(the)g +(initial)e(estimate)h(is)g(less)h(than)f(the)h(v)n(alue)f(of)h +Fb(penalty)p Fd(,)h(otherwise)e(the)h(search)244 3665 +y(can)20 b(e)o(xplode)g(\(tak)o(e)g(practically)g(fore)n(v)o(er\).)29 +b(If)20 b(you)g(suspect)g(this)f(is)h(happening,)g(you)g(can)g(set)g +Fb(v)o(erbosity)244 3785 y Fd(to)27 b Fb(2)g Fd(to)f(check,)i(or)g +(just)e(increase)h(the)g(v)n(alue)g(of)g Fb(penalty)p +Fd(.)38 b(In)28 b(summary)e(it)g(appears)i(that)f(the)f(v)n(alue)h(of) +244 3905 y(penalty)e(doesn')n(t)g(matter)h(much)f(as)h(long)f(as)h(it)f +(is)g(lar)n(ge)h(\(b)n(ut)g(not)f(so)g(lar)n(ge)i(as)e(to)h(cause)g(o)o +(v)o(er\003o)n(ws\).)32 b(It)244 4026 y(will)24 b(probably)g(be)h(remo) +o(v)o(ed)e(in)i(the)f(future.)145 4231 y Fa(\017)49 b +Fb(penetration)34 b Fd(This)d(parameter)i(tak)o(es)f(the)g(v)n(alue)g +Fb(A)-5 b(UT)n(OMA)c(TIC)32 b Fd(or)h(a)f(positi)n(v)o(e)e(inte)o(ger) +-5 b(.)52 b(It)33 b(deter)n(-)244 4352 y(mines)j(ho)n(w)g(f)o(ar)i +(into)e(a)i(block)o(ed)e(area)i(the)f(router)g(will)f(penetrate)i(to)e +(mak)o(e)h(a)h(connection.)66 b(Note)244 4472 y(ho)n(we)n(v)o(er)30 +b(the)h(router)g(will)g(in)g(no)g(case)h(violate)e(spacing)h +(constraints)f(to)h(nodes)g(not)g(in)l(v)n(olv)o(ed)e(in)i(the)244 +4592 y(route.)145 4798 y Fa(\017)49 b Fb(windo)o(w)32 +b Fd(This)g(parameter)h(tak)o(es)f(the)g(v)n(alue)g Fb(COMMAND)f +Fd(\(the)i(def)o(ault\))f(or)g(a)h(windo)n(w)e(id)h(\(small)244 +4918 y(inte)o(gers\).)i(It)26 b(determines)g(the)g(reference)i(windo)n +(w)d(for)h(routes.)35 b(The)26 b(router)g(sees)h(the)f(w)o(orld)g(as)g +(it)g(ap-)244 5039 y(pears)d(in)f(the)g(reference)j(windo)n(w)-6 +b(,)21 b(e.g.,)i(it)f(sees)g(the)h(contents)f(of)g(subcells)g(e)o +(xpanded)g(in)g(the)g(reference)244 5159 y(windo)n(w)-6 +b(.)44 b(If)30 b Fb(windo)o(w)g Fd(is)f(set)h(to)f Fb(COMMAND)g +Fd(the)h(reference)h(windo)n(w)e(is)g(the)h(one)f(that)h(contained)244 +5280 y(the)22 b(cursor)f(when)h(the)g(route)g(w)o(as)f(in)l(v)n(ok)o +(ed.)29 b(T)-8 b(o)22 b(set)f(the)h(reference)i(windo)n(w)c(to)h(a)i +(\002x)o(ed)e(windo)n(w)-6 b(,)21 b(place)244 5400 y(the)k(cursor)f(in) +h(that)f(windo)n(w)g(and)g(type:)1875 5649 y(\2268\226)p +eop +%%Page: 9 9 +9 8 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#10:)30 +b(The)25 b(Interacti)n(v)o(e)f(Router)1373 b(September)25 +b(26,)g(2001)1144 84 y Fb(:ir)n(oute)h(wizard)f(windo)o(w)g(.)0 +424 y Ff(Refer)m(ences)0 647 y Fd([1])49 b(M.H.)30 b(Arnold)g(and)h(W) +-9 b(.S.)31 b(Scott,)56 b(\223)-8 b(An)30 b(Interacti)n(v)o(e)g(Maze)h +(Router)g(with)f(Hints\224,)56 b Fe(Pr)l(oceedings)29 +b(of)h(the)165 768 y(25th)24 b(Design)g(A)n(utomation)f(Confer)l(ence)p +Fd(,)36 b(June)25 b(1988,)f(pp.)g(672\226676.)1875 5649 +y(\2269\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut11.ps b/doc/psfiles/tut11.ps new file mode 100644 index 00000000..21c26f03 --- /dev/null +++ b/doc/psfiles/tut11.ps @@ -0,0 +1,652 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tut11.dvi +%%Pages: 7 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman Times-BoldItalic +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tut11.dvi -o tut11.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut11.dvi) +@start /Fa 1 63 df<7000000000000000FC00000000000000FF000000000000007FC0 +0000000000001FF000000000000007FC00000000000001FF000000000000007FC0000000 +0000001FF000000000000007FE00000000000001FF800000000000007FE0000000000000 +1FF800000000000003FE00000000000000FF800000000000003FE00000000000000FF800 +000000000003FF00000000000000FFC00000000000003FF00000000000000FFC00000000 +000001FF000000000000007FC00000000000001FF000000000000007FC00000000000001 +FF000000000000007FC00000000000001FE00000000000001FE00000000000007FC00000 +00000001FF00000000000007FC0000000000001FF00000000000007FC0000000000001FF +0000000000000FFC0000000000003FF0000000000000FFC0000000000003FF0000000000 +000FF80000000000003FE0000000000000FF80000000000003FE0000000000001FF80000 +000000007FE0000000000001FF80000000000007FE0000000000001FF00000000000007F +C0000000000001FF00000000000007FC0000000000001FF00000000000007FC000000000 +0000FF00000000000000FC0000000000000070000000000000003B3878B44C>62 +D E /Fb 135[50 120[{ TeXBase1Encoding ReEncodeFont }1 +100.000003 /Times-BoldItalic rf /Fc 103[33 3[50 50 10[33 +15[50 2[55 33 39 44 55 55 50 55 83 28 55 1[28 55 50 33 +44 55 44 55 50 10[72 1[66 55 72 3[72 1[66 4[78 1[66 72 +72 66 1[93 5[33 7[50 50 50 28 25 33 2[50 42[{ + TeXBase1Encoding ReEncodeFont }45 100.000003 /Times-Bold +rf /Fd 138[66 40 47 53 2[60 66 100 33 2[33 66 2[53 66 +53 1[60 12[80 6[113 9[86 8[40 55[66 2[{ TeXBase1Encoding ReEncodeFont } +19 119.999948 /Times-Bold rf /Fe 105[50 1[44 44 24[44 +50 50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 +50 33 44 50 44 50 44 6[61 72 1[94 1[72 61 55 66 72 55 +72 72 89 61 2[33 72 72 55 61 72 66 66 72 92 4[28 28 50 +50 50 50 50 50 50 50 50 50 28 25 33 25 2[33 33 33 3[50 +31[55 55 2[{ TeXBase1Encoding ReEncodeFont }74 100.000003 +/Times-Roman rf /Ff 133[39 1[44 66 2[28 39 39 2[50 50 +72 28 44 1[28 50 2[44 50 44 50 50 8[61 1[61 1[55 50 61 +3[66 83 4[72 72 1[61 72 66 61 2[50 1[67 11[50 50 1[25 +4[33 33 40[{ TeXBase1Encoding ReEncodeFont }38 100.000003 +/Times-Italic rf /Fg 136[104 1[80 48 56 64 1[80 72 80 +120 40 2[40 80 72 48 64 80 64 1[72 11[104 96 80 104 1[88 +1[104 135 3[56 14[48 4[72 72 72 72 72 13[72 35[{ + TeXBase1Encoding ReEncodeFont }33 143.999997 /Times-Bold +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 211 101 a Fg(Magic)35 b(T)-13 b(utorial)34 b(#11:)43 +b(Using)35 b(IRSIM)g(and)g(RSIM)h(with)f(Magic)1659 521 +y Ff(Mic)o(hael)24 b(Chow)1646 641 y(Mark)h(Hor)l(owitz)1338 +1062 y Fe(Computer)g(Systems)f(Laboratory)1354 1182 y(Center)i(for)f +(Inte)o(grated)f(Systems)1558 1303 y(Stanford)h(Uni)n(v)o(ersity)1547 +1423 y(Stanford,)g(CA)h(94305)1053 1693 y(This)e(tutorial)g +(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.)0 2220 y +Fd(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 +2423 y Fe(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)300 2543 y(Magic)g(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)300 2663 y(Magic)f(T)l(utorial)g(#4:)30 +b(Cell)25 b(Hierarchies)300 2784 y(Magic)f(T)l(utorial)g(#8:)30 +b(Circuit)25 b(Extraction)0 2986 y Fd(Commands)k(intr)n(oduced)j(in)f +(this)f(tutorial:)300 3188 y Fe(:getnode,)24 b(:rsim,)g(:simcmd,)f +(:startrsim)0 3391 y Fd(Macr)n(os)29 b(intr)n(oduced)i(in)g(this)f +(tutorial:)300 3618 y Ff(\(None\))0 4213 y Fg(1)143 b(Intr)m(oduction)0 +4437 y Fe(This)20 b(tutorial)g(e)o(xplains)f(ho)n(w)h(to)g(use)h +(Magic')-5 b(s)20 b(interf)o(ace)h(to)f(the)h(switch-le)n(v)o(el)e +(circuit)h(simulators,)g(RSIM)h(and)0 4557 y(IRSIM.)27 +b(The)g(interf)o(ace)g(is)g(the)f(same)h(for)g(both)e(these)i +(simulators)e(and,)i(e)o(xcept)f(where)h(noted,)g(RSIM)g(refers)0 +4678 y(to)i(IRSIM)i(as)f(well.)45 b(This)29 b(interf)o(ace)i +(eliminates)d(the)i(tedium)f(of)h(mapping)e(node)i(names)f(to)h +(objects)f(in)g(the)0 4798 y(layout)f(and)h(typing)f(node)g(names)h(as) +g(RSIM)g(input.)42 b(It)29 b(allo)n(ws)f(the)g(user)h(to)g(select)g +(nodes)f(using)g(the)h(mouse)0 4918 y(and)36 b(apply)f(RSIM)i(commands) +e(to)g(them)g(or)h(to)g(display)f(the)g(node)h(v)n(alues)f(determined)g +(by)h(RSIM)h(in)e(the)0 5039 y(layout)26 b(itself.)38 +b(Y)-11 b(ou)27 b(should)f(already)h(be)h(f)o(amiliar)e(with)h(using)f +(both)h(RSIM)h(and)f(Magic')-5 b(s)26 b(circuit)h(e)o(xtractor)-5 +b(.)0 5159 y(Section)32 b(2)g(describes)g(ho)n(w)f(to)h(prepare)g(the)g +(\002les)g(necessary)h(to)e(simulate)g(a)h(circuit.)52 +b(Section)32 b(3)g(describes)0 5280 y(ho)n(w)24 b(to)h(run)g(RSIM)g +(interacti)n(v)o(ely)e(under)i(Magic.)31 b(Section)25 +b(4)g(e)o(xplains)f(ho)n(w)g(to)g(determine)h(the)g(node)f(names)0 +5400 y(that)e(RSIM)h(uses.)29 b(Lastly)-6 b(,)21 b(section)h(5)g(e)o +(xplains)f(ho)n(w)g(to)h(use)g(the)g(RSIM)h(tool)f(in)f(Magic)h(to)g +(simulate)f(a)i(circuit.)1875 5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fe(September)25 b(26,)f(2001)813 b(Magic)24 +b(T)l(utorial)g(#11:)30 b(Using)23 b(IRSIM)j(and)f(RSIM)g(with)f(Magic) +0 99 y Fg(2)143 b(Pr)m(eparations)33 b(f)l(or)j(Simulation)0 +327 y Fe(Magic)23 b(uses)h(the)f(RSIM)i(input)e(\002le)h(when)f(it)h +(simulates)e(the)h(circuit.)30 b(Before)25 b(proceeding)f(an)o(y)f +(further)l(,)h(mak)o(e)0 447 y(sure)34 b(you)f(ha)n(v)o(e)g(the)g +(correct)i(v)o(ersions)d(of)h(the)h(programs)f Fc(ext2sim)g +Fe(and)g Fc(rsim)h Fe(installed)e(on)h(your)g(system.)0 +567 y(Important)26 b(changes)i(ha)n(v)o(e)f(been)g(made)g(to)g(these)g +(programs)g(to)g(support)f(simulation)f(within)h(Magic.)38 +b(T)-8 b(o)27 b(try)0 688 y(out)g(this)f(tool)g(on)h(an)h(e)o(xample,)f +(cop)o(y)g(all)g(the)g Fc(tut11)p Fb(x)g Fe(cells)g(to)g(your)g +(current)g(directory)g(with)g(the)g(follo)n(wing)0 808 +y(command:)900 1053 y Fc(cp)f(\230cad/lib/magic/tutorial/tut11*)d(.)146 +1296 y Fe(The)29 b Fc(tut11a)g Fe(cell)f(is)g(a)h(simple)e(4-bit)h +(counter)g(using)f(the)i(Magic)f(scmos)f(technology)h(\002le.)42 +b(Start)28 b(Magic)0 1416 y(on)d(the)f(cell)h Fc(tut11a)p +Fe(,)g(and)g(e)o(xtract)f(the)h(entire)g(cell)f(using)g(the)h(command:) +900 1661 y Fc(:extract)h(all)146 1904 y Fe(When)k(this)e(command)h +(completes,)h(se)n(v)o(eral)e Fc(.ext)i Fe(\002les)g(will)e(be)i +(created)g(in)f(your)g(current)h(directory)f(by)0 2024 +y(the)i(e)o(xtractor)-5 b(.)48 b(The)31 b(ne)o(xt)f(step)h(is)f(to)h +(\003atten)g(the)g(hierarchy)f(into)h(a)g(single)f(representation.)48 +b(Return)32 b(to)e(the)0 2145 y(Unix)24 b(c-shell)h(by)f(quitting)f +(Magic.)146 2267 y(The)32 b(program)f Fc(ext2sim)g Fe(is)g(used)g(to)g +(\003atten)h(the)f(hierarchy)-6 b(.)50 b(Run)32 b(this)e(program)h +(from)h(the)f(C-shell)g(by)0 2387 y(typing:)900 2632 +y Fc(ext2sim)24 b(-L)i(-R)f(-c)g(20)g(tut11a)146 2875 +y Fe(This)f(program)h(will)f(create)h(the)g(\002le)g +Fc(tut11a.sim)g Fe(in)f(your)h(current)g(directory)-6 +b(.)146 2997 y(If)22 b(you)f(are)h(running)e(IRSIM,)i(the)f +Fc(tut11a.sim)f Fe(can)i(be)f(used)g(directly)g(as)g(input)f(to)h(the)g +(simulator)e(and)j(you)0 3118 y(should)27 b(skip)h(the)g(ne)o(xt)g +(step.)41 b(Instead,)29 b(if)f(you)g(will)g(be)g(using)g(RSIM,)h(the)f +(last)g(step)g(is)g(to)g(create)h(the)f(binary)0 3238 +y(representation)c(of)h(the)g(\003attened)g(hierarchy)f(by)h(using)f +(the)g(program)h Fc(pr)n(esim)p Fe(.)31 b(T)-8 b(o)25 +b(do)f(this,)g(type:)900 3483 y Fc(pr)n(esim)h(tut11a.sim)g(tut11a.rsm) +g(\230cad/lib/scmos100.prm)f(-nostack)i(-nodr)n(ops)146 +3726 y Fe(The)j(third)e(\002le)i(is)f(the)g(parameter)h(\002le)g(used)f +(by)g(presim)g(for)h(this)e(circuit.)41 b(The)29 b(con)l(v)o(ention)d +(at)j(Stanford)0 3846 y(is)24 b(to)f(use)h(the)g(suf)n(\002x)f +Ff(.r)o(sm)h Fe(when)g(naming)f(the)g(RSIM)i(input)e(\002le.)31 +b(The)24 b(\002le)g Fc(tut11a.rsm)g Fe(can)h(also)e(be)h(used)g(as)0 +3967 y(input)g(for)h(running)f(RSIM)h(alone.)0 4319 y +Fg(3)143 b(Using)35 b(RSIM)0 4547 y Fe(Re-run)27 b(Magic)f(again)f(to)h +(edit)g(the)g(cell)g Fc(tut11a)p Fe(.)35 b(W)-8 b(e')o(ll)26 +b(\002rst)g(learn)g(ho)n(w)g(to)f(run)h(RSIM)h(in)f(interacti)n(v)o(e)f +(mode)0 4668 y(under)g(Magic.)30 b(T)-8 b(o)25 b(simulate)e(the)i +(circuit)f(of)h(tut11a,)f(using)g(IRSIM)i(type)e(the)h(command:)900 +4912 y Fc(:rsim)g(scmos100.prm)f(tut11a.sim)146 5155 +y Fe(T)-8 b(o)25 b(simulate)e(the)i(circuit)g(of)f(tut11a,)g(using)g +(RSIM)i(type)e(the)h(command:)900 5400 y Fc(:rsim)g(tut11a.rsm)1875 +5649 y Fe(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fe(Magic)24 b(T)l(utorial)g(#11:)30 +b(Using)24 b(IRSIM)h(and)g(RSIM)h(with)e(Magic)812 b(September)25 +b(26,)g(2001)146 69 y(Y)-11 b(ou)32 b(should)f(see)h(the)g(RSIM)g +(header)h(displayed,)f(follo)n(wed)f(by)h(the)f(standard)h(RSIM)g +(prompt)f(\()p Fc(rsim)p Fa(>)0 189 y Fe(or)c Fc(irsim)p +Fa(>)p Fe(,)g(depending)f(on)h(the)g(simulator\))f(in)g(place)i(of)f +(the)g(usual)f(Magic)h(prompt;)g(this)f(means)h(k)o(e)o(yboard)0 +309 y(input)g(is)h(no)n(w)f(directed)i(to)f(RSIM.)h(This)e(mode)h(is)g +(v)o(ery)g(similar)f(to)h(running)f(RSIM)i(alone;)g(one)g(dif)n +(ference)0 430 y(is)h(that)g(the)h(user)f(can)h(escape)g(RSIM)h(and)e +(then)h(return)f(to)g(Magic.)48 b(Also,)31 b(the)g(mouse)e(has)i(no)f +(ef)n(fect)h(when)0 550 y(RSIM)25 b(is)g(run)g(interacti)n(v)o(ely)e +(under)h(Magic.)146 671 y(Only)i(one)f(instance)h(of)g(RSIM)h(may)e(be) +h(running)f(at)h(an)o(y)g(time)f(under)h(Magic.)33 b(The)26 +b(simulation)e(running)0 791 y(need)i(not)g(correspond)f(to)h(the)g +(Magic)f(layout;)h(ho)n(we)n(v)o(er)l(,)f(as)h(we)g(shall)f(see)i +(later)l(,)f(the)o(y)f(must)g(correspond)h(for)0 911 +y(the)32 b(RSIM)h(tool)e(to)g(w)o(ork.)53 b(All)31 b(commands)g(typed)g +(to)h(the)g(RSIM)h(prompt)e(should)g(be)h(RSIM)g(commands.)0 +1032 y(W)-8 b(e')o(ll)28 b(\002rst)g(run)g(RSIM,)g(then)g(escape)h(to)e +(Magic,)h(and)g(then)g(return)g(back)g(to)g(RSIM.)g(T)-8 +b(ype)28 b(the)g(RSIM)g(com-)0 1152 y(mand)900 1374 y +Fc(@)d(tut11a.cmd)146 1597 y Fe(to)k(initialize)f(the)g(simulation.)41 +b(\(Note)29 b(there)g(is)g(a)g(\223)g(\224)g(after)h(the)f(@.\))43 +b(No)n(w)28 b(type)g Fc(c)i Fe(to)e(clock)h(the)g(circuit.)0 +1717 y(Y)-11 b(ou)29 b(should)g(see)g(some)g(information)f(about)h +(some)g(nodes)g(displayed,)h(follo)n(wed)e(by)i(the)f(time.)44 +b(Set)30 b(tw)o(o)f(of)0 1837 y(the)24 b(nodes)g(to)g(a)h(logic)e +(\2231\224)i(by)f(typing)f Fc(h)i(RESET)p 1768 1837 60 +5 v 61 w(B)g(hold)p Fe(.)31 b(Step)24 b(the)h(clock)f(again)f(by)h +(typing)g Fc(c)p Fe(,)g(and)g(RSIM)0 1958 y(should)g(sho)n(w)f(that)i +(these)f(tw)o(o)h(nodes)f(no)n(w)g(ha)n(v)o(e)g(the)h(v)n(alue)f +(\2231\224.)146 2078 y(Y)-11 b(ou)23 b(can)g(return)g(to)f(Magic)g +(without)g(quitting)f(RSIM)i(and)g(then)f(later)h(return)g(to)f(RSIM)i +(in)e(the)h(same)f(state)0 2199 y(in)i(which)h(it)f(w)o(as)h(left.)31 +b(Escape)25 b(to)f(Magic)g(by)h(typing:)900 2421 y Fc(.)146 +2643 y Fe(\(a)e(single)e(period\))h(to)f(the)h(RSIM)h(prompt.)28 +b(Ne)o(xt,)22 b(type)g(a)g(fe)n(w)g(Magic)g(commands)f(to)g(sho)n(w)g +(you')-5 b(re)22 b(really)0 2763 y(back)j(in)f(Magic)h(\(signi\002ed)f +(by)h(the)f(Magic)h(prompt\).)146 2884 y(Y)-11 b(ou)25 +b(can)g(return)g(to)f(RSIM)i(by)e(typing)g(the)g(Magic)h(command)f +Fc(rsim)g Fe(without)g(an)o(y)g(ar)n(guments.)30 b(T)-8 +b(ype:)900 3106 y Fc(:rsim)146 3328 y Fe(The)25 b(RSIM)g(prompt)e(will) +g(be)i(displayed)e(again,)h(and)g(you)g(are)h(no)n(w)e(back)i(in)e +(RSIM)i(in)f(the)g(state)g(you)g(left)0 3449 y(it)f(in.)30 +b(Experiment)23 b(with)g(RSIM)i(by)e(typing)g(some)g(commands.)29 +b(T)-8 b(o)24 b(quit)f(RSIM)h(and)g(return)g(to)f(Magic,)h(type:)900 +3671 y Fc(q)146 3893 y Fe(in)29 b(response)g(to)f(the)h(RSIM)g(prompt.) +42 b(Y)-11 b(ou')o(ll)29 b(kno)n(w)f(you')-5 b(re)29 +b(back)g(in)f(Magic)h(when)g(the)g(Magic)f(prompt)0 4014 +y(is)e(redisplayed.)37 b(If)27 b(you)f(should)g(interrupt)g(RSIM)i +(\(typing)d(a)i(control-C\),)g(you')o(ll)f(probably)g(kill)g(it)h(and)f +(then)0 4134 y(ha)n(v)o(e)i(to)f(restart)h(it.)39 b(RSIM)29 +b(running)e(standalone)g(will)g(also)g(be)h(killed)f(if)h(you)g +(interrupt)f(it.)39 b(If)28 b(you)g(interrupt)0 4254 +y(IRSIM)23 b(\(typing)e(a)i(control-C\),)f(the)g(simulator)e(will)i +(abort)g(whate)n(v)o(er)f(it')-5 b(s)21 b(doing)g(\(a)i(long)e +(simulation)f(run,)j(for)0 4375 y(e)o(xample\))h(and)h(return)g(to)f +(the)h(command)f(interpreter)g(by)h(prompting)e(again)h(with)g +Fc(irsim)p Fa(>)p Fe(.)0 4713 y Fg(4)143 b(Node)35 b(Names)0 +4937 y Fe(It')-5 b(s)28 b(easy)i(to)e(determine)h(node)g(names)f(under) +h(Magic.)43 b(First,)30 b(locate)f(the)g(red)g(square)h(re)o(gion)e(in) +g(the)h(middle)0 5057 y(right)d(side)f(of)i(the)f(circuit.)35 +b(Mo)o(v)o(e)24 b(the)j(cursor)f(o)o(v)o(er)f(this)h(re)o(gion)f(and)h +(select)g(it)g(by)g(typing)f Fc(s)p Fe(.)35 b(T)-8 b(o)26 +b(\002nd)h(out)e(the)0 5178 y(name)g(for)g(this)f(node,)g(type:)900 +5400 y Fc(:getnode)1875 5649 y Fe(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fe(September)25 b(26,)f(2001)813 b(Magic)24 +b(T)l(utorial)g(#11:)30 b(Using)23 b(IRSIM)j(and)f(RSIM)g(with)f(Magic) +146 68 y(Magic)j(should)f(print)h(that)f(the)h(node)g(name)g(is)g +Ff(RESET)p 2108 68 60 5 v 60 w(B)p Fe(.)g(The)g(command)f +Fc(getnode)i Fe(prints)e(the)h(names)0 188 y(of)c(all)h(nodes)e(in)h +(the)h(current)f(selection.)30 b(Mo)o(v)o(e)22 b(the)h(cursor)g(o)o(v)o +(er)g(the)g(square)h(blue)f(re)o(gion)f(in)h(the)g(upper)h(right)0 +309 y(corner)35 b(and)f(add)g(this)f(node)h(to)f(the)h(current)h +(selection)e(by)h(typing)f Fc(S)p Fe(.)h(T)-8 b(ype)34 +b Fc(:getnode)i Fe(again,)f(and)f(Magic)0 429 y(should)27 +b(print)h(the)g(names)g(of)h(tw)o(o)f(nodes;)h(the)f(blue)g(node)g(is)g +(named)g Ff(hold)p Fe(.)41 b(Y)-11 b(ou)28 b(can)h(also)f(print)g +(aliases)g(for)0 549 y(the)d(selected)f(nodes.)31 b(T)l(urn)24 +b(on)g(name-aliasing)g(by)h(typing:)900 827 y Fc(:getnode)h(alias)e(on) +146 1098 y Fe(Select)35 b(the)e(red)h(node)g(again,)h(and)f(type)f +Fc(:getnode)p Fe(.)59 b(Se)n(v)o(eral)33 b(names)h(will)e(be)i +(printed;)j(the)d(last)f(name)0 1219 y(printed)f(is)h(the)f(one)h(RSIM) +h(uses,)g(so)f(you)f(should)g(use)h(this)f(name)g(for)i(RSIM.)f(Note)g +(that)f Fc(getnode)i Fe(is)f(not)0 1339 y(guaranteed)27 +b(to)g(print)f(all)h(aliases)g(for)g(a)g(node.)37 b(Only)27 +b(those)f(alises)h(generated)g(when)g(the)g(RSIM)g(node)g(name)0 +1460 y(is)32 b(computed)f(are)i(printed.)51 b(Ho)n(we)n(v)o(er)l(,)33 +b(most)e(of)h(the)g(alaiases)g(will)f(usually)g(be)h(printed.)52 +b(Printing)31 b(aliases)0 1580 y(is)26 b(also)h(useful)f(to)h(monitor)e +(the)i(name)g(search,)g(since)g Fc(getnode)h Fe(can)f(tak)o(e)g(se)n(v) +o(eral)f(seconds)h(on)f(lar)n(ge)i(nodes.)0 1700 y(T)l(urn)c(of)n(f)h +(aliasing)f(by)g(typing:)900 1978 y Fc(:getnode)i(alias)e(off)146 +2249 y(getnode)30 b Fe(w)o(orks)d(by)h(e)o(xtracting)f(a)i(single)e +(node.)41 b(Consequently)-6 b(,)27 b(it)h(can)h(tak)o(e)f(a)g(long)g +(time)f(to)h(compute)0 2370 y(the)23 b(name)g(for)h(lar)n(ge)f(nodes,)g +(such)g(as)g Ff(Vdd)g Fe(or)h Ff(GND)p Fe(.)f(Select)h(the)f +(horizontal)f(blue)h(strip)g(on)f(top)h(of)g(the)g(circuit)0 +2490 y(and)32 b(run)f Fc(:getnode)j Fe(on)d(this.)51 +b(Y)-11 b(ou')o(ll)31 b(\002nd)h(that)f(this)g(will)g(tak)o(e)h(about)f +(six)g(seconds)g(for)h Fc(getnode)h Fe(to)f(\002gure)0 +2611 y(out)27 b(that)g(this)f(is)h Ff(Vdd)p Fe(.)39 b(Y)-11 +b(ou)27 b(can)h(interrupt)e Fc(getnode)j Fe(by)e(typing)f +Fc(\210C)i Fe(\(control-C\),)g(and)f Fc(getnode)i Fe(will)d(return)0 +2731 y(the)h(\223best\224)g(name)h(found)e(so)h(f)o(ar)-5 +b(.)39 b(There)27 b(is)g(no)g(w)o(ay)h(to)f(tell)f(if)h(this)g(is)g(an) +g(alias)g(or)g(the)h(name)f(RSIM)h(e)o(xpects)0 2851 +y(unless)23 b Fc(getnode)i Fe(is)f(allo)n(wed)f(to)g(complete.)30 +b(T)-8 b(o)24 b(pre)n(v)o(ent)e(these)i(long)f(name)h(searches,)h(you)e +(can)i(tell)e Fc(getnode)0 2972 y Fe(to)h(quit)g(its)g(search)i(when)e +(certain)h(names)g(are)g(encountered.)31 b(T)-8 b(ype:)900 +3249 y Fc(:getnode)26 b(abort)f(Vdd)146 3521 y Fe(Select)30 +b(the)f(blue)g(strip)g(on)g(top)g(of)g(the)g(circuit)g(and)h(type)f +Fc(:getnode)p Fe(.)45 b(Y)-11 b(ou')o(ll)29 b(notice)g(that)g(the)g +(name)g(w)o(as)0 3641 y(found)20 b(v)o(ery)f(quickly)h(this)f(time,)h +(and)g Fc(getnode)h Fe(tells)f(you)f(it)h(aborted)g(the)g(search)h(of)f +Ff(Vdd)p Fe(.)29 b(The)20 b(name)g(returned)0 3761 y(may)25 +b(be)g(an)g(alias)g(instead)g(of)g(the)g(the)g(one)g(RSIM)h(e)o +(xpects.)31 b(In)25 b(this)f(e)o(xample,)g(the)h(abort)g(option)f(to)h +Fc(getnode)0 3882 y Fe(will)f(abort)g(the)h(name)f(search)i(on)e(an)o +(y)g(name)h(found)f(where)h(the)f(last)h(component)e(of)i(the)f(node)h +(name)f(is)h Ff(Vdd)p Fe(.)0 4002 y(That)g(is,)f Fc(getnode)i +Fe(will)e(stop)g(if)g(a)i(name)e(such)h(as)g(\223miasma/crock/)p +Ff(Vdd)p Fe(\224)e(or)i(\223hooha/)p Ff(Vdd)p Fe(\224)f(is)g(found.)146 +4129 y(Y)-11 b(ou)38 b(can)h(abort)f(the)g(search)h(on)f(more)g(than)g +(one)g(name;)45 b(no)n(w)37 b(type)h Fc(:getnode)i(abort)f(GND)p +Fe(.)f(Select)0 4249 y(the)f(bottom)e(horizontal)h(blue)h(strip)f(in)h +(the)g(layout,)i(and)e(type)g Fc(:getnode)p Fe(.)69 b(The)37 +b(search)g(will)f(end)h(almost)0 4369 y(immediately)-6 +b(,)27 b(since)h(this)g(node)g(is)g Ff(GND)p Fe(.)h Fc(getnode)h +Fe(will)d(no)n(w)h(abort)g(an)o(y)g(node)g(name)h(search)g(when)f +(either)0 4490 y Ff(Vdd)20 b Fe(or)g Ff(GND)h Fe(is)f(found.)28 +b(The)21 b(search)g(can)f(be)h(aborted)f(on)g(an)o(y)g(name;)h(just)e +(supply)g(the)i(name)f(as)g(an)h(ar)n(gument)0 4610 y(to)29 +b Fc(getnode)i(abort)p Fe(.)45 b(Remember)30 b(that)f(only)f(the)i +(last)f(part)g(of)h(the)f(name)g(counts)g(when)g(aborting)g(the)g(name) +0 4731 y(search.)i(T)-8 b(o)25 b(cancel)g(all)g(name)f(aborts)h(and)g +(resume)f(normal)g(name)h(searches,)g(type:)900 5008 +y Fc(:getnode)h(abort)146 5280 y(getnode)c Fe(will)e(no)h(longer)f +(abort)h(the)f(search)i(on)e(an)o(y)g(names,)i(and)e(it)h(will)f(churn) +g(a)o(w)o(ay)h(unless)f(interrupted)0 5400 y(by)25 b(the)f(user)-5 +b(.)1875 5649 y(\2264\226)p eop +%%Page: 5 5 +5 4 bop 0 -180 a Fe(Magic)24 b(T)l(utorial)g(#11:)30 +b(Using)24 b(IRSIM)h(and)g(RSIM)h(with)e(Magic)812 b(September)25 +b(26,)g(2001)0 99 y Fg(5)143 b(RSIM)36 b(T)-13 b(ool)0 +335 y Fe(Y)i(ou)31 b(can)g(also)g(use)f(the)h(mouse)f(to)h(help)g(you)f +(run)h(RSIM)h(under)e(Magic.)49 b(Instead)31 b(of)g(typing)f(node)h +(names,)0 455 y(you)23 b(can)h(just)e(select)h(nodes)g(with)g(the)g +(mouse,)g(tell)g(RSIM)h(what)f(to)g(do)g(with)g(these)g(nodes,)g(and)g +(let)g(Magic)g(do)0 576 y(the)i(rest.)30 b(Change)c(tools)d(by)i +(typing:)900 852 y Fc(:tool)g(rsim)146 1123 y Fe(or)h(hit)g(the)g +(space)g(bar)g(until)f(the)h(cursor)g(changes)g(to)g(a)g(pointing)f +(hand.)34 b(The)26 b(RSIM)g(tool)g(is)f(acti)n(v)o(e)g(when)0 +1243 y(the)32 b(cursor)h(is)f(this)f(hand.)54 b(The)32 +b(left)h(and)f(right)g(mouse)f(b)n(uttons)g(ha)n(v)o(e)i(the)f(same)g +(ha)n(v)o(e)g(the)h(same)f(function)0 1363 y(as)h(the)f(box)g(tool.)53 +b(Y)-11 b(ou)32 b(use)h(these)f(b)n(uttons)f(along)h(with)g(the)h +(select)f(command)g(to)g(select)g(the)h(nodes.)53 b(The)0 +1484 y(middle)23 b(b)n(utton)g(is)g(dif)n(ferent)h(from)g(the)g(box)f +(tool.)30 b(Clicking)23 b(the)h(middle)f(b)n(utton)g(will)g(cause)h +(all)g(nodes)g(in)f(the)0 1604 y(selection)30 b(to)g(ha)n(v)o(e)g +(their)g(logical)g(v)n(alues)g(displayed)f(in)h(the)h(layout)e(and)i +(printed)f(in)g(the)g(te)o(xt)g(windo)n(w)-6 b(.)46 b(W)-8 +b(e)0 1724 y(need)25 b(to)f(ha)n(v)o(e)h(RSIM)g(running)f(in)h(order)g +(to)f(use)h(this)f(tool.)30 b(Start)25 b(RSIM)g(by)g(typing:)900 +2001 y Fc(:startrsim)g(tut11a.rsm)146 2271 y Fe(The)31 +b Fc(.rsm)g Fe(\002le)g(you)g(simulate)f(must)f(correspond)i(to)f(the)h +(root)g(cell)f(of)h(the)g(layout.)48 b(If)32 b(not,)f(Magic)g(will)0 +2392 y(generate)d(node)e(names)h(that)g(RSIM)g(will)f(not)h(understand) +f(and)h(things)f(w)o(on')n(t)g(w)o(ork)h(properly)-6 +b(.)37 b(If)27 b(an)o(y)g(paint)0 2512 y(is)k(changed)g(in)f(the)h +(circuit,)h(the)f(circuit)g(must)f(be)h(re-e)o(xtracted)g(and)g(a)h(ne) +n(w)e Fc(.rsm)h Fe(\002le)h(must)e(be)h(created)g(to)0 +2632 y(re\003ect)26 b(the)f(changes)f(in)h(the)f(circuit.)146 +2759 y(Magic)f(will)f(print)g(the)g(RSIM)i(header)l(,)g(b)n(ut)e(you)g +(return)h(to)g(Magic)f(instead)g(of)h(remaining)f(in)g(RSIM.)i(This)0 +2879 y(is)g(an)g(alternate)h(w)o(ay)f(of)g(starting)f(up)h(RSIM,)h(and) +g(it)e(is)h(equi)n(v)n(alent)e(to)i(the)g(command)g Fc(rsim)g +(tut11a.rsm)g Fe(and)0 3000 y(typing)h(a)i(period)f(\()p +Fc(.)p Fe(\))35 b(to)26 b(the)g(RSIM)h(prompt,)f(escaping)g(to)g +(Magic.)34 b(W)-8 b(e)27 b(need)g(to)e(initialize)h(RSIM,)g(so)g(get)g +(to)0 3120 y(RSIM)j(by)e(typing)g Fc(:rsim)h Fe(and)g(you')o(ll)f(see)i +(the)f(RSIM)g(prompt)f(again.)40 b(As)28 b(before,)h(type)f +Fc(@)g(tut11a.cmd)g Fe(to)0 3240 y(the)e(RSIM)h(prompt)e(to)h +(initialize)f(e)n(v)o(erything.)33 b(T)-8 b(ype)26 b(a)g(period)g(\()p +Fc(.)p Fe(\))35 b(to)26 b(return)g(to)g(Magic.)34 b(W)-8 +b(e)27 b(are)f(no)n(w)g(ready)0 3361 y(to)e(use)h(the)g(RSIM)g(tool.) +146 3487 y(As)k(mentioned)f(earlier)l(,)j Fc(tut11a)f +Fe(is)e(a)i(4-bit)e(counter)-5 b(.)44 b(W)-8 b(e')o(ll)29 +b(reset)g(the)g(counter)h(and)f(then)g(step)f(it)h(using)0 +3608 y(the)e(RSIM)g(tool.)36 b(Locate)26 b(the)h(square)g(blue)f(area)i +(on)e(the)h(top)f(right)g(corner)h(of)g(the)g(circuit.)36 +b(Place)27 b(the)g(cursor)0 3728 y(o)o(v)o(er)f(this)f(re)o(gion)g(and) +i(select)f(it.)35 b(No)n(w)26 b(click)g(the)g(middle)f(b)n(utton,)g +(and)i(the)f(RSIM)h(v)n(alue)f(for)g(this)g(node)g(will)0 +3848 y(be)35 b(printed)f(in)g(both)f(the)i(te)o(xt)e(windo)n(w)g(and)i +(in)f(the)g(layout.)59 b(Magic/RSIM)35 b(will)e(report)i(that)f(the)g +(node)h(is)0 3969 y(named)24 b Ff(hold)g Fe(and)h(that)f(its)g(current) +h(v)n(alue)f(is)h Ff(X)p Fe(.)f(Y)-11 b(ou)24 b(may)h(not)f(be)h(able)g +(to)f(see)h(the)f(node)h(v)n(alue)f(in)g(the)h(layout)0 +4089 y(if)32 b(you)g(are)h(zoomed)f(out)f(too)h(f)o(ar)-5 +b(.)53 b(Zoom)31 b(in)h(closer)g(about)g(this)f(node)h(if)g(necessary) +-6 b(.)53 b(T)m(ry)32 b(selecting)f(other)0 4209 y(nodes,)25 +b(singly)g(or)h(in)f(groups)g(and)h(click)g(the)f(middle)g(b)n(utton)f +(to)i(display)f(their)g(v)n(alues.)33 b(This)25 b(is)g(an)h(easy)g(w)o +(ay)0 4330 y(to)e(probe)h(nodes)g(when)f(deb)n(ugging)g(a)h(circuit.) +146 4456 y(Select)h Ff(hold)d Fe(again)h(\(the)h(blue)f(square\).)31 +b(This)24 b(node)g(must)g(be)h(a)g(\2231\224)f(before)i(resetting)d +(the)i(circuit.)30 b(Mak)o(e)0 4577 y(sure)25 b(this)f(is)g(the)h(only) +f(node)g(in)h(the)f(current)h(selection.)30 b(T)-8 b(ype:)900 +4853 y Fc(:simcmd)25 b(h)146 5124 y Fe(to)g(set)f(it)h(to)f(a)h +(\2231\224.)31 b(Step)25 b(the)g(clock)g(by)f(typing:)900 +5400 y Fc(:simcmd)h(c)1875 5649 y Fe(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Fe(September)25 b(26,)f(2001)813 b(Magic)24 +b(T)l(utorial)g(#11:)30 b(Using)23 b(IRSIM)j(and)f(RSIM)g(with)f(Magic) +146 68 y(Click)39 b(the)f(middle)f(b)n(utton)h(and)g(you)g(will)g(see)g +(that)g(the)h(node)f(has)g(been)h(set)f(to)g(a)h(\2231.)-7 +b(\224)72 b(The)38 b(Magic)0 188 y(command)19 b Fc(simcmd)g +Fe(will)g(tak)o(e)g(the)h(selected)f(nodes)g(and)h(use)f(them)g(as)h +(RSIM)g(input.)28 b(These)19 b(uses)g(of)h Fc(simcmd)0 +309 y Fe(are)32 b(lik)o(e)e(typing)g(the)g(RSIM)i(commands)e +Ff(h)h(hold)f Fe(follo)n(wed)f(by)i Ff(c)p Fe(.)49 b(The)31 +b(ar)n(guments)f(gi)n(v)o(en)g(to)g Fc(simcmd)h Fe(are)0 +429 y(normal)e(RSIM)i(commands,)f(and)g Fc(simcmd)g Fe(will)f(apply)g +(the)h(speci\002ed)g(RSIM)h(command)e(to)g(each)i(node)e(in)0 +549 y(the)23 b(current)h(selection.)29 b(T)m(ry)23 b(RSIM)h(commands)e +(on)h(this)g(node)g(\(such)g(as)h Ff(?)30 b Fe(or)23 +b Ff(d)p Fe(\))h(by)f(using)f(the)i(command)e(as)0 670 +y(an)j(ar)n(gument)f(to)h Fc(simcmd)p Fe(.)146 790 y(Y)-11 +b(ou)30 b(can)g(enter)g(RSIM)h(interacti)n(v)o(ely)d(at)i(an)o(y)f +(time)g(by)h(simply)e(typing)h Fc(:rsim)p Fe(.)46 b(T)-8 +b(o)29 b(continue)g(using)g(the)0 911 y(RSIM)c(tool,)f(escape)i(to)e +(Magic)h(by)f(typing)g(a)h(period)f(\()p Fc(.)p Fe(\))31 +b(to)25 b(the)f(RSIM)i(prompt.)146 1031 y(The)i(node)g +Ff(RESET)p 839 1031 60 5 v 59 w(B)g Fe(must)f(be)h(set)f(to)h(a)g +(\2230\224.)40 b(This)27 b(node)h(is)f(the)h(red)g(square)g(area)h(at)e +(the)h(middle)f(right)0 1151 y(of)f(the)h(circuit.)35 +b(Place)27 b(the)f(cursor)h(o)o(v)o(er)e(this)h(node)g(and)g(select)h +(it.)35 b(T)-8 b(ype)26 b(the)g(Magic)g(commands)g Fc(:simcmd)g(l)0 +1272 y Fe(follo)n(wed)g(by)g Fc(:simcmd)h(c)g Fe(to)f(set)h(the)g +(selected)f(node)h(to)f(a)h(\2230\224.)37 b(Click)27 +b(the)f(middle)g(mouse)g(b)n(utton)f(to)i(check)0 1392 +y(that)i(this)f(node)h(is)g(no)n(w)f(\2230\224.)45 b(Step)29 +b(the)g(clock)h(once)f(more)g(to)g(ensure)g(the)g(counter)h(is)e +(reset.)45 b(Do)29 b(this)f(using)0 1513 y(the)d Fc(:simcmd)g(c)g +Fe(command.)146 1633 y(The)f(outputs)d(of)j(this)e(counter)h(are)h(the) +f(four)h(v)o(ertical)e(purple)h(strips)g(at)g(the)g(bottom)f(of)h(the)g +(circuit.)30 b(Zoom)0 1753 y(in)h(if)g(necessary)-6 b(,)33 +b(select)e(each)h(of)g(these)f(nodes,)h(and)g(click)f(the)g(middle)f(b) +n(utton)g(to)h(check)h(that)f(all)g(are)h(\2230\224.)0 +1874 y(Each)f(of)g(these)g(four)g(nodes)g(is)f(labeled)h +Ff(bit)p 1563 1874 V 59 w(x)p Fe(.)50 b(If)31 b(the)o(y)g(are)g(all)g +(not)g(\2230\224,)h(check)g(the)f(circuit)f(to)h(mak)o(e)g(sure)0 +1994 y Ff(hold=1)26 b Fe(and)h Ff(RESET)p 780 1994 V +59 w(B=0)p Fe(.)36 b(Assuming)25 b(these)i(nodes)f(are)h(at)g(their)g +(correct)g(v)n(alue,)f(you)g(can)i(no)n(w)d(simulate)0 +2114 y(the)32 b(counter)-5 b(.)51 b(Set)32 b Ff(RESET)p +971 2114 V 60 w(B)g Fe(to)f(a)i(\2231\224)f(by)g(selecting)f(it)g +(\(the)h(red)g(square\))g(and)g(then)g(typing)e Fc(:simcmd)j(h)p +Fe(.)0 2235 y(Step)22 b(the)g(clock)g(by)g(typing)f Fc(:simcmd)i(c)p +Fe(.)30 b(Using)21 b(the)h(same)g(procedure,)h(set)f(the)g(node)g +Ff(hold)f Fe(\(the)h(blue)g(square\))0 2355 y(to)i(a)i(\2230\224.)146 +2476 y(W)-8 b(e')o(ll)34 b(w)o(atch)f(the)h(output)e(bits)h(of)g(this)g +(counter)g(as)h(it)f(runs.)57 b(Place)34 b(the)f(box)g(around)h(all)f +(four)h(outputs)0 2596 y(\(purple)29 b(strips)f(at)i(the)f(bottom\))f +(and)h(zoom)g(in)f(so)h(their)g(labels)g(are)h(visible.)43 +b(Select)30 b(one)f(of)g(the)h(outputs)d(by)0 2716 y(placing)f(the)g +(cursor)g(o)o(v)o(er)g(it)g(and)g(typing)f Fc(s)p Fe(.)36 +b(Add)26 b(the)g(other)g(three)h(outputs)e(to)h(the)g(selection)f(by)h +(placing)g(the)0 2837 y(cursor)31 b(o)o(v)o(er)f(each)h(and)g(typing)f +Fc(S)p Fe(.)h(These)g(four)g(nodes)f(should)g(be)h(the)f(only)g(ones)h +(in)f(the)h(selection.)48 b(Click)0 2957 y(the)30 b(middle)e(mouse)i(b) +n(utton)e(to)i(display)e(the)i(node)g(v)n(alues.)45 b(Step)30 +b(the)g(clock)f(by)h(typing)f Fc(:simcmd)h(c)p Fe(.)46 +b(Click)0 3077 y(the)27 b(middle)f(b)n(utton)g(again)g(to)h(check)h +(the)e(nodes.)38 b(Repeat)27 b(stepping)f(the)h(clock)g(and)g +(displaying)f(the)h(outputs)0 3198 y(se)n(v)o(eral)g(times,)h(and)g +(you')o(ll)g(see)g(the)g(outputs)f(sequence)h(as)h(a)f(counter)-5 +b(.)40 b(If)29 b(you)e(also)h(follo)n(w)f(the)h(te)o(xt)f(on)h(the)0 +3318 y(screen,)d(you')o(ll)f(also)h(see)g(that)f(the)h(outputs)e(are)j +(also)e(being)g(w)o(atched.)146 3439 y(Y)-11 b(ou)29 +b(may)g(ha)n(v)o(e)g(noticed)g(that)f(the)h(results)g(are)h(printed)e +(v)o(ery)h(quickly)f(if)h(the)h(middle)e(b)n(utton)g(is)g(click)o(ed)0 +3559 y(a)i(second)f(time)g(without)f(changing)h(the)g(selection.)45 +b(This)28 b(is)h(because)h(the)g(node)f(names)g(do)h(not)f(ha)n(v)o(e)g +(to)g(be)0 3679 y(recomputed)i(if)g(the)h(selection)e(remains)h +(unchanged.)50 b(Thus,)33 b(you)e(can)g(increase)h(the)g(performance)g +(of)f(this)0 3800 y(tool)j(by)h(minimizing)e(selection)i(changes.)62 +b(This)34 b(can)i(be)f(accomplished)f(by)h(adding)g(other)g(nodes)f(to) +h(the)0 3920 y(current)25 b(selection)f(that)g(you)h(are)g(intending)f +(to)g(check.)146 4041 y(T)-8 b(o)25 b(erase)g(all)g(the)g(RSIM)g(v)n +(alue)f(labels)h(from)f(the)h(layout,)f(clear)h(the)g(selection)f(by)h +(typing:)900 4253 y Fc(:select)g(clear)146 4465 y Fe(and)i(then)f +(click)g(the)g(middle)f(mouse)h(b)n(utton.)34 b(The)26 +b(RSIM)h(labels)f(do)g(not)g(af)n(fect)g(the)h(cell)f(modi\002ed)g +(\003ag,)0 4586 y(nor)35 b(will)e(the)o(y)h(be)h(written)f(in)h(the)f +Fc(.mag)h Fe(\002le.)60 b(When)35 b(you')-5 b(re)35 b(\002nished)f +(using)g(RSIM,)h(resume)g(RSIM)g(by)0 4706 y(typing)29 +b Fc(:rsim)h Fe(and)g(then)g(quit)f(it)h(by)g(typing)f(a)i +Fc(q)f Fe(to)g(the)g(RSIM)h(prompt.)46 b(Quitting)28 +b(Magic)i(before)h(quitting)0 4826 y(RSIM)25 b(will)f(also)h(quit)f +(RSIM.)146 4947 y(W)-8 b(e')j(v)o(e)21 b(used)e(a)i(fe)n(w)f(macros)g +(to)f(lessen)h(the)g(typing)e(necessary)j(for)f(the)g(RSIM)h(tool.)28 +b(The)20 b(ones)g(commonly)0 5067 y(used)25 b(are:)900 +5280 y Fc(:macr)n(o)g(h)h(\223simcmd)e(h\224)900 5400 +y(:macr)n(o)h(l)g(\223simcmd)g(l\224)1875 5649 y Fe(\2266\226)p +eop +%%Page: 7 7 +7 6 bop 0 -180 a Fe(Magic)24 b(T)l(utorial)g(#11:)30 +b(Using)24 b(IRSIM)h(and)g(RSIM)h(with)e(Magic)812 b(September)25 +b(26,)g(2001)900 84 y Fc(:macr)n(o)g(k)h(\223simcmd)e(c\224)1875 +5649 y Fe(\2267\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut2.ps b/doc/psfiles/tut2.ps new file mode 100644 index 00000000..034f10c0 --- /dev/null +++ b/doc/psfiles/tut2.ps @@ -0,0 +1,1777 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tut2.dvi +%%Pages: 12 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman Courier +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tut2.dvi -o tut2.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +%%BeginProcSet: special.pro +TeXDict begin /SDict 200 dict N SDict begin /@SpecialDefaults{/hs 612 N +/vs 792 N /ho 0 N /vo 0 N /hsc 1 N /vsc 1 N /ang 0 N /CLIP 0 N /rwiSeen +false N /rhiSeen false N /letter{}N /note{}N /a4{}N /legal{}N}B +/@scaleunit 100 N /@hscale{@scaleunit div /hsc X}B /@vscale{@scaleunit +div /vsc X}B /@hsize{/hs X /CLIP 1 N}B /@vsize{/vs X /CLIP 1 N}B /@clip{ +/CLIP 2 N}B /@hoffset{/ho X}B /@voffset{/vo X}B /@angle{/ang X}B /@rwi{ +10 div /rwi X /rwiSeen true N}B /@rhi{10 div /rhi X /rhiSeen true N}B +/@llx{/llx X}B /@lly{/lly X}B /@urx{/urx X}B /@ury{/ury X}B /magscale +true def end /@MacSetUp{userdict /md known{userdict /md get type +/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup +length 20 add dict copy def}if end md begin /letter{}N /note{}N /legal{} +N /od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath +clippath mark{transform{itransform moveto}}{transform{itransform lineto} +}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{ +itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{ +closepath}}pathforall newpath counttomark array astore /gc xdf pop ct 39 +0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}N +/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 +scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get +ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip +not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 +TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{noflips{TR +pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 +-1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg +TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg +sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr +0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add +2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N /cp +{pop pop showpage pm restore}N end}if}if}N /normalscale{Resolution 72 +div VResolution 72 div neg scale magscale{DVImag dup scale}if 0 setgray} +N /psfts{S 65781.76 div N}N /startTexFig{/psf$SavedState save N userdict +maxlength dict begin /magscale true def normalscale currentpoint TR +/psf$ury psfts /psf$urx psfts /psf$lly psfts /psf$llx psfts /psf$y psfts +/psf$x psfts currentpoint /psf$cy X /psf$cx X /psf$sx psf$x psf$urx +psf$llx sub div N /psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy +scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR +/showpage{}N /erasepage{}N /copypage{}N /p 3 def @MacSetUp}N /doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N /endTexFig{end psf$SavedState restore}N /@beginspecial{SDict +begin /SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count /ocount X /dcount countdictstack N}N /@setspecial +{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if /showpage{}N /erasepage{}N /copypage{}N newpath +}N /@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{ +end}repeat grestore SpecialSave restore end}N /@defspecial{SDict begin} +N /@fedspecial{end}B /li{lineto}B /rl{rlineto}B /rc{rcurveto}B /np{ +/SaveX currentpoint /SaveY X N 1 setlinecap newpath}N /st{stroke SaveX +SaveY moveto}N /fil{fill SaveX SaveY moveto}N /ellipse{/endangle X +/startangle X /yrad X /xrad X /savematrix matrix currentmatrix N TR xrad +yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut2.dvi) +@start /Fa 134[60 3[60 60 60 2[60 60 3[60 60 1[60 2[60 +60 60 9[60 39[60 2[60 11[60 34[{ TeXBase1Encoding ReEncodeFont }16 +100.000003 /Courier rf /Fb 119[33 13[44 50 50 72 50 55 +33 39 44 55 55 50 55 83 28 55 1[28 55 50 33 44 55 44 +55 50 6[66 2[100 72 72 66 55 72 78 61 78 72 94 3[39 1[78 +61 66 72 72 66 72 6[33 4[50 2[50 50 50 1[25 1[25 7[50 +2[33 30[55 2[{ TeXBase1Encoding ReEncodeFont }56 100.000003 +/Times-Bold rf /Fc 138[66 40 47 53 2[60 66 100 33 2[33 +66 2[53 66 53 1[60 12[80 6[113 9[86 8[40 55[66 2[{ + TeXBase1Encoding ReEncodeFont }19 119.999948 /Times-Bold +rf /Fd 105[50 1[44 44 10[33 13[44 50 50 72 50 50 28 39 +33 50 50 50 50 78 28 50 28 28 50 50 33 44 50 44 50 44 +3[33 1[33 61 72 1[94 72 72 61 55 66 72 55 72 72 89 61 +2[33 72 72 55 61 72 66 66 72 92 4[28 28 50 50 50 50 50 +50 50 50 50 50 28 25 33 25 2[33 33 33 2[50 50 1[33 29[55 +55 2[{ TeXBase1Encoding ReEncodeFont }80 100.000003 /Times-Roman +rf /Fe 134[44 44 66 1[50 28 39 39 1[50 50 50 72 28 1[28 +28 50 50 28 44 50 44 50 50 9[83 1[72 55 50 2[61 72 2[55 +1[44 5[72 21[25 1[25 2[33 33 37[50 2[{ TeXBase1Encoding ReEncodeFont } +36 100.000003 /Times-Italic rf /Ff 134[72 2[72 80 48 +56 64 1[80 72 80 120 40 2[40 80 72 1[64 80 64 80 72 9[143 +1[104 96 80 2[88 112 1[135 96 5[88 96 1[104 96 7[48 72 +72 72 72 72 72 72 72 72 72 12[72 35[{ TeXBase1Encoding ReEncodeFont }43 +143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 490 101 a Ff(Magic)36 b(T)-13 b(utorial)34 b(#2:)43 +b(Basic)35 b(P)o(ainting)f(and)h(Selection)1618 521 y +Fe(J)n(ohn)24 b(Ousterhout)1401 941 y Fd(Computer)g(Science)i(Di)n +(vision)1020 1062 y(Electrical)f(Engineering)f(and)h(Computer)f +(Sciences)1473 1182 y(Uni)n(v)o(ersity)f(of)i(California)1544 +1303 y(Berk)o(ele)o(y)-6 b(,)24 b(CA)h(94720)1448 1573 +y Fe(\(Updated)f(by)h(other)o(s,)f(too.\))1053 1843 y +Fd(This)g(tutorial)g(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.)0 +2317 y Fc(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 +2479 y Fd(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)0 2641 y Fc(Commands)29 b(intr)n(oduced)j(in)f(this)f +(tutorial:)300 2803 y Fd(:box,)24 b(:clockwise,)g(:cop)o(y)-6 +b(,)24 b(:erase,)h(:\002ndbox)f(:grid,)g(:label,)300 +2923 y(:layers,)g(:macro,)h(:mo)o(v)o(e,)e(:paint,)h(:redo,)g(:sa)n(v)o +(e,)g(:select,)300 3043 y(:side)n(w)o(ays,)f(:undo,)h(:upsidedo)n(wn,)f +(:vie)n(w)-6 b(,)23 b(:what,)h(:writeall,)g(:zoom)0 3205 +y Fc(Macr)n(os)29 b(intr)n(oduced)i(in)g(this)f(tutorial:)300 +3379 y Fd(a,)25 b(A,)g(c,)g(d,)f(\210D,)h(e,)g(E,)g(g,)g(G,)f(q,)h(Q,)g +(r)l(,)g(R,)g(s,)g(S,)g(t,)f(T)-7 b(,)25 b(u,)f(U,)h(v)-6 +b(,)24 b(w)-6 b(,)25 b(W)-9 b(,)24 b(z,)h(Z,)g(4)0 4213 +y Ff(1)143 b(Cells)35 b(and)g(P)o(aint)0 4437 y Fd(In)i(Magic,)h(a)f +(circuit)f(layout)g(is)g(a)g(hierarchical)h(collection)f(of)g +Fe(cells)p Fd(.)65 b(Each)37 b(cell)f(contains)g(three)h(things:)0 +4557 y(colored)26 b(shapes,)g(called)g Fe(paint)p Fd(,)f(that)g +(de\002ne)h(the)g(circuit')-5 b(s)25 b(structure;)h(te)o(xtual)f +Fe(labels)g Fd(attached)h(to)f(the)h(paint;)0 4678 y(and)c +Fe(subcells)p Fd(,)g(which)g(are)h(instances)f(of)h(other)f(cells.)30 +b(The)22 b(paint)g(is)g(what)g(determines)g(the)g(e)n(v)o(entual)f +(function)0 4798 y(of)33 b(the)g(VLSI)h(circuit.)55 b(Labels)33 +b(and)g(subcells)g(are)g(a)h(con)l(v)o(enience)f(for)g(you)g(in)g +(managing)f(the)h(layout)f(and)0 4918 y(pro)o(vide)c(a)i(w)o(ay)f(of)g +(communicating)e(information)h(between)h(v)n(arious)f(synthesis)g(and)h +(analysis)f(tools.)43 b(This)0 5039 y(tutorial)23 b(e)o(xplains)f(ho)n +(w)h(to)g(create)i(and)f(edit)f(paint)g(and)h(labels)f(in)g(simple)g +(single-cell)g(designs,)f(using)h(the)h(ba-)0 5159 y(sic)h(painting)g +(commands.)32 b(\223Magic)26 b(T)l(utorial)e(#3:)32 b(Adv)n(anced)25 +b(P)o(ainting)g(\(W)l(iring)g(and)g(Plo)n(wing\)\224)g(describes)0 +5280 y(some)35 b(more)h(adv)n(anced)f(features)h(for)h(manipulating)c +(paint.)63 b(F)o(or)36 b(information)e(on)i(ho)n(w)f(to)g(b)n(uild)g +(up)g(cell)0 5400 y(hierarchies,)25 b(see)g(\223Magic)g(T)l(utorial)e +(#4:)30 b(Cell)25 b(Hierarchies\224.)1875 5649 y(\2261\226)p +eop +%%Page: 2 2 +2 1 bop 0 -180 a Fd(September)25 b(26,)f(2001)1180 b(Magic)24 +b(T)l(utorial)f(#2:)31 b(Basic)25 b(P)o(ainting)e(and)i(Selection)0 +99 y Ff(2)143 b(P)o(ainting)34 b(and)h(Erasing)0 374 +y Fd(Enter)e(Magic)g(to)g(edit)g(the)g(cell)g Fb(tut2a)h +Fd(\(type)f Fb(magic)g(tut2a)g Fd(to)g(the)g(Unix)g(shell;)j(follo)n(w) +c(the)h(directions)f(in)0 495 y(\223T)l(utorial)i(#1:)50 +b(Getting)34 b(Started\224)h(if)g(you)f(ha)n(v)o(e)h(an)o(y)f(problems) +g(with)g(this\).)60 b(The)35 b Fb(tut2a)g Fd(cell)g(is)f(a)i(sort)e(of) +0 615 y(palette:)g(it)26 b(sho)n(ws)g(a)h(splotch)e(of)i(each)g(of)g +(se)n(v)o(eral)f(paint)g(layers)h(and)g(gi)n(v)o(es)e(the)h(names)h +(that)f(Magic)g(uses)h(for)0 736 y(the)e(layers.)146 +881 y(The)d(tw)o(o)f(basic)h(layout)f(operations)f(are)j(painting)d +(and)i(erasing.)29 b(The)o(y)21 b(can)h(be)g(in)l(v)n(ok)o(ed)f(using)g +(the)g Fb(:paint)0 1001 y Fd(and)31 b Fb(:erase)h Fd(long)f(commands,)g +(or)h(using)e(the)h(b)n(uttons.)49 b(The)31 b(easiest)g(w)o(ay)h(to)f +(paint)f(and)i(erase)g(is)f(with)f(the)0 1122 y(mouse)e(b)n(uttons.)41 +b(T)-8 b(o)28 b(paint,)h(position)e(the)h(box)h(o)o(v)o(er)e(the)i +(area)h(you')-5 b(d)28 b(lik)o(e)g(to)g(paint,)h(then)f(mo)o(v)o(e)g +(the)g(cursor)0 1242 y(o)o(v)o(er)34 b(a)i(color)f(and)g(click)g(the)g +(middle)f(mouse)h(b)n(utton.)61 b(T)-8 b(o)35 b(erase)h(e)n(v)o +(erything)d(in)i(an)g(area,)k(place)c(the)h(box)0 1363 +y(o)o(v)o(er)25 b(the)h(area,)h(mo)o(v)o(e)e(the)h(cursor)g(o)o(v)o(er) +f(a)h(blank)g(spot,)f(and)h(click)g(the)g(middle)f(mouse)g(b)n(utton.) +33 b(T)m(ry)25 b(painting)0 1483 y(and)31 b(erasing)h(v)n(arious)e +(colors.)50 b(If)32 b(the)f(screen)h(gets)f(totally)f(messed)h(up,)i +(you)e(can)g(al)o(w)o(ays)h(e)o(xit)e(Magic)h(and)0 1603 +y(restart)j(it.)58 b(While)33 b(you')-5 b(re)34 b(painting,)h(white)f +(dots)f(may)g(occasionally)g(appear)i(and)f(disappear)-5 +b(.)57 b(These)34 b(are)0 1724 y(design)g(rule)g(violations)e(detected) +j(by)f(Magic,)i(and)e(will)g(be)g(e)o(xplained)f(in)h(\223Magic)h(T)l +(utorial)e(#6:)49 b(Design)0 1844 y(Rule)25 b(Checking\224.)31 +b(Y)-11 b(ou)24 b(can)i(ignore)e(them)g(for)h(no)n(w)-6 +b(.)146 1990 y(It')h(s)34 b(completely)g(le)o(gal)f(to)i(paint)f(one)g +(layer)h(on)g(top)f(of)h(another)-5 b(.)59 b(When)35 +b(this)f(happens,)i(one)f(of)g(three)0 2110 y(things)21 +b(may)g(occur)-5 b(.)30 b(In)22 b(some)f(cases,)i(the)f(layers)g(are)h +(independent,)e(so)h(what)g(you')o(ll)f(see)h(is)f(a)i(combination)d +(of)0 2230 y(the)26 b(tw)o(o,)f(as)h(if)g(each)g(were)h(a)f +(transparent)g(colored)f(foil.)34 b(This)25 b(happens,)g(for)h(e)o +(xample,)f(if)h(you)g(paint)f(metal1)0 2351 y(\(blue\))e(on)f(top)g(of) +g(polysilicon)f(\(red\).)30 b(In)23 b(other)f(cases,)h(when)g(you)f +(paint)g(one)g(layer)h(on)f(top)g(of)h(another)f(you')o(ll)0 +2471 y(get)29 b(something)e(dif)n(ferent)h(from)g(either)h(of)g(the)g +(tw)o(o)f(original)g(layers.)42 b(F)o(or)29 b(e)o(xample,)g(painting)e +(poly)h(on)h(top)0 2591 y(of)e(ndif)n(f)f(produces)h(ntransistor)e +(\(try)i(this\).)36 b(In)27 b(still)f(other)h(cases)g(the)f(ne)n(w)h +(layer)g(replaces)g(the)g(old)f(one:)35 b(this)0 2712 +y(happens,)d(for)f(e)o(xample,)g(if)g(you)f(paint)h(a)g(pcontact)f(on)h +(top)f(of)h(ntransistor)-5 b(.)47 b(T)m(ry)30 b(painting)g(dif)n +(ferent)g(layers)0 2832 y(on)c(top)g(of)h(each)g(other)g(to)f(see)h +(what)g(happens.)35 b(The)27 b(meaning)f(of)h(the)f(v)n(arious)g +(layers)g(is)g(discussed)g(in)g(more)0 2953 y(detail)e(in)h(Section)f +(11)h(belo)n(w)-6 b(.)146 3098 y(There)29 b(is)f(a)h(second)f(w)o(ay)h +(of)f(erasing)g(paint)g(that)g(allo)n(ws)f(you)h(to)g(erase)h(some)f +(layers)g(without)f(af)n(fecting)0 3218 y(others.)45 +b(This)29 b(is)h(the)f(macro)h Fb(\210D)g Fd(\(control-D,)f(for)h(\223) +p Fb(D)p Fd(elete)g(paint\224\).)46 b(T)-8 b(o)29 b(use)h(it,)g +(position)e(the)i(box)f(o)o(v)o(er)g(the)0 3339 y(area)24 +b(to)g(be)f(erased,)h(then)f(mo)o(v)o(e)f(the)i(crosshair)f(o)o(v)o(er) +g(a)g(splotch)g(of)g(paint)g(containing)f(the)i(layer\(s\))g(you')-5 +b(d)23 b(lik)o(e)0 3459 y(to)28 b(erase.)43 b(T)-8 b(ype)28 +b Fb(\210D)h Fd(k)o(e)o(y)e(on)i(the)f(te)o(xt)g(k)o(e)o(yboard:)37 +b(the)28 b(colors)g(underneath)g(the)h(cursor)f(will)g(be)g(erased)h +(from)0 3580 y(the)f(area)h(underneath)f(the)h(box,)f(b)n(ut)g(no)g +(other)g(layers)g(will)g(be)g(af)n(fected.)42 b(Experiment)27 +b(around)h(with)g(the)g Fb(\210D)0 3700 y Fd(macro)c(to)f(try)h(dif)n +(ferent)f(combinations)e(of)j(paints)f(and)h(erases.)31 +b(If)24 b(the)f(cursor)h(is)f(o)o(v)o(er)g(empty)g(space)h(then)f(the)0 +3820 y Fb(\210D)i Fd(macro)g(is)f(equi)n(v)n(alent)f(to)i(the)f(middle) +g(mouse)g(b)n(utton:)29 b(it)24 b(erases)i(e)n(v)o(erything.)146 +3966 y(Y)-11 b(ou)25 b(can)g(also)f(paint)h(and)f(erase)i(using)e(the)g +(long)g(commands)900 4394 y Fb(:paint)i Fe(layer)o(s)900 +4515 y Fb(:erase)f Fe(layer)o(s)146 4918 y Fd(In)j(each)h(of)e(these)h +(commands)f Fe(layer)o(s)g Fd(is)g(one)h(or)g(more)f(layer)h(names)g +(separated)g(by)f(commas)g(\(you)h(can)0 5039 y(also)f(use)g(spaces)h +(for)f(separators,)h(b)n(ut)f(only)f(if)i(you)f(enclose)g(the)g(entire) +g(list)f(in)h(double-quotes\).)37 b(An)o(y)27 b(layer)0 +5159 y(can)h(be)g(abbre)n(viated)f(as)h(long)f(as)h(the)f(abbre)n +(viation)g(is)g(unambiguous.)37 b(F)o(or)28 b(e)o(xample,)g +Fb(:paint)g(poly)-5 b(,metal1)0 5280 y Fd(will)26 b(paint)h(the)g +(polysilicon)f(and)h(metal1)f(layers.)39 b(The)27 b(macro)g +Fb(\210D)h Fd(is)f(prede\002ned)h(by)f(Magic)g(to)g(be)g +Fb(:erase)h($)0 5400 y Fd(\()p Fb($)d Fd(is)f(a)h(pseudo-layer)g(that)f +(means)h(\223all)f(layers)h(underneath)g(the)f(cursor\224\).)1875 +5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)1179 b(September)25 b(26,)g(2001)0 +99 y Ff(3)143 b(Undo)0 322 y Fd(There)26 b(are)f(probably)g(going)f(to) +h(be)g(times)f(when)h(you')o(ll)f(do)h(things)f(that)g(you')o(ll)g +(later)i(wish)e(you)h(hadn')n(t.)31 b(F)o(or)n(-)0 443 +y(tunately)-6 b(,)23 b(Magic)h(has)h(an)g(undo)f(f)o(acility)g(that)g +(you)g(can)h(use)f(to)h(restore)f(things)g(after)h(you')-5 +b(v)o(e)24 b(made)g(mistak)o(es.)0 563 y(The)h(command)900 +789 y Fb(:undo)146 1015 y Fd(\(or)l(,)k(alternati)n(v)o(ely)-6 +b(,)27 b(the)h(macro)g Fb(u)p Fd(\))h(will)e(undo)h(the)g(ef)n(fects)g +(of)g(the)g(last)f(command)h(you)f(in)l(v)n(ok)o(ed.)40 +b(If)29 b(you)0 1135 y(made)36 b(a)h(mistak)o(e)e(se)n(v)o(eral)h +(commands)f(back,)k(you)d(can)h(type)f Fb(:undo)h Fd(se)n(v)o(eral)f +(times)f(to)h(undo)f(successi)n(v)o(e)0 1256 y(commands.)41 +b(Ho)n(we)n(v)o(er)l(,)29 b(there)g(is)f(a)h(limit)e(to)h(all)h(this:) +37 b(Magic)29 b(only)f(remembers)g(ho)n(w)g(to)g(undo)g(the)h(last)f +(ten)0 1376 y(or)d(so)g(commands.)30 b(If)25 b(you)g(undo)f(something)g +(and)h(then)f(decide)i(you)e(w)o(anted)h(it)g(after)g(all,)g(you)f(can) +i(undo)e(the)0 1496 y(undo)g(with)g(the)h(command)900 +1722 y Fb(:r)n(edo)146 1948 y Fd(\()p Fb(U)34 b Fd(is)f(a)h(macro)g +(for)g(this)f(command\).)56 b(T)m(ry)33 b(making)g(a)h(fe)n(w)g(paints) +e(and)i(erases,)i(then)e(use)f Fb(:undo)i Fd(and)0 2068 +y Fb(:r)n(edo)26 b Fd(to)e(w)o(ork)h(backw)o(ards)g(and)g(forw)o(ards)g +(through)f(the)g(changes)h(you)f(made.)0 2408 y Ff(4)143 +b(The)35 b(Selection)0 2631 y Fd(Once)23 b(you)e(ha)n(v)o(e)h(painted)g +(a)h(piece)f(of)h(layout,)f(there)g(are)h(se)n(v)o(eral)f(commands)f +(you)h(can)h(in)l(v)n(ok)o(e)e(to)h(modify)f(the)0 2752 +y(layout.)31 b(Man)o(y)25 b(of)g(them)g(are)h(based)f(on)g(the)g +Fe(selection)p Fd(:)31 b(you)25 b(select)g(one)g(or)h(more)f(pieces)g +(of)g(the)h(design,)e(and)0 2872 y(then)g(perform)g(operations)g(such)g +(as)g(cop)o(ying,)g(deletion,)f(and)h(rotation)g(on)g(the)g(selected)g +(things.)29 b(T)-8 b(o)24 b(see)h(ho)n(w)0 2992 y(the)e(selection)g(w)o +(orks,)g(load)g(cell)g Fb(tut2b)p Fd(.)31 b(Y)-11 b(ou)23 +b(can)h(do)e(this)h(by)g(typing)f Fb(:load)h(tut2b)h +Fd(if)f(you')-5 b(re)24 b(still)e(in)h(Magic,)0 3113 +y(or)i(by)f(starting)g(up)h(Magic)f(with)g(the)h(shell)f(command)g +Fb(magic)g(tut2b)p Fd(.)146 3233 y(The)31 b(\002rst)g(thing)f(to)g(do)h +(is)f(to)g(learn)i(ho)n(w)d(to)i(select.)48 b(Mo)o(v)o(e)30 +b(the)g(cursor)h(o)o(v)o(er)f(the)h(upper)g(portion)e(of)i(the)0 +3354 y(L-shaped)d(blue)g(area)i(in)e Fb(tut2b)p Fd(,)i(and)f(type)f +Fb(s)p Fd(,)h(which)f(is)g(a)h(macro)f(for)h Fb(:select)p +Fd(.)42 b(The)29 b(box)f(will)f(jump)h(o)o(v)o(er)f(to)0 +3474 y(co)o(v)o(er)d(the)h(v)o(ertical)g(part)g(of)g(the)g(\223L)-9 +b(\224.)25 b(This)f(operation)g(selected)h(a)h(chunk)e(of)h(material.) +31 b(Mo)o(v)o(e)24 b(the)h(box)f(a)o(w)o(ay)0 3594 y(from)29 +b(the)h(chunk,)g(and)f(you')o(ll)g(see)h(that)f(a)h(thin)e(white)h +(outline)f(is)i(left)f(around)g(the)h(chunk)f(to)g(sho)n(w)f(that)h +(it')-5 b(s)0 3715 y(selected.)30 b(No)n(w)23 b(mo)o(v)o(e)f(the)h +(cursor)h(o)o(v)o(er)e(the)i(v)o(ertical)e(red)i(bar)g(on)f(the)g +(right)g(of)h(the)f(cell)g(and)h(type)f Fb(s)p Fd(.)30 +b(The)24 b(box)0 3835 y(will)g(mo)o(v)o(e)f(o)o(v)o(er)h(that)h(bar)l +(,)g(and)f(the)h(selection)f(highlighting)e(will)i(disappear)h(from)f +(the)h(blue)f(area.)146 3955 y(If)29 b(you)e(type)g Fb(s)h +Fd(se)n(v)o(eral)f(times)g(without)f(mo)o(ving)g(the)i(cursor)l(,)h +(each)f(command)f(selects)g(a)i(slightly)c(lar)n(ger)0 +4076 y(piece)39 b(of)g(material.)72 b(Mo)o(v)o(e)37 b(the)i(cursor)g +(back)g(o)o(v)o(er)f(the)g(top)g(of)h(the)g(blue)f(\223L)-9 +b(\224,)39 b(and)g(type)f Fb(s)h Fd(three)g(times)0 4196 +y(without)24 b(mo)o(ving)f(the)h(cursor)-5 b(.)31 b(The)25 +b(\002rst)g Fb(s)g Fd(selects)g(a)g(chunk)g(\(a)g(rectangular)h(re)o +(gion)e(all)h(of)g(the)g(same)f(type)h(of)0 4317 y(material\).)k(The)21 +b(second)f Fb(s)g Fd(selects)h(a)g Fe(r)l(e)l(gion)f +Fd(\(all)g(of)h(the)f(blue)h(material)f(in)g(the)h(re)o(gion)e +(underneath)i(the)f(cursor)l(,)0 4437 y(rectangular)32 +b(or)g(not\).)52 b(The)32 b(third)g Fb(s)f Fd(selects)h(a)g +Fe(net)g Fd(\(all)g(of)g(the)g(material)g(that)f(is)h(electrically)g +(connected)f(to)0 4557 y(the)c(original)f(chunk;)i(this)f(includes)f +(the)h(blue)g(metal,)h(the)f(red)g(polysilicon,)f(and)h(the)g(contact)h +(that)e(connects)0 4678 y(them\).)146 4798 y(The)f(macro)g +Fb(S)g Fd(\(short)g(for)g Fb(:select)g(mor)n(e)p Fd(\))h(is)e(just)g +(lik)o(e)h Fb(s)f Fd(e)o(xcept)h(that)f(it)g(adds)h(on)g(to)f(the)h +(selection,)f(rather)0 4918 y(than)i(replacing)g(it.)34 +b(Mo)o(v)o(e)24 b(the)i(cursor)g(o)o(v)o(er)f(the)h(v)o(ertical)g(red)g +(bar)g(on)g(the)g(right)f(and)i(type)e Fb(S)i Fd(to)e(see)i(ho)n(w)e +(this)0 5039 y(w)o(orks.)30 b(Y)-11 b(ou)25 b(can)g(also)f(type)h +Fb(S)g Fd(multiple)e(times)h(to)g(add)h(re)o(gions)f(and)h(nets)f(to)g +(the)h(selection.)146 5159 y(If)i(you)f(accidentally)g(type)f +Fb(s)i Fd(or)f Fb(S)h Fd(when)f(the)g(cursor)g(is)g(o)o(v)o(er)f +(space,)i(you')o(ll)f(select)g(a)g(cell)h(\()p Fb(tut2b)g +Fd(in)f(this)0 5280 y(case\).)32 b(Y)-11 b(ou)24 b(can)i(just)e(undo)g +(this)g(for)h(no)n(w)-6 b(.)30 b(Cell)25 b(selection)f(will)g(be)h +(discussed)f(in)g(\223Magic)h(T)l(utorial)f(#4:)30 b(Cell)0 +5400 y(Hierarchies\224.)1875 5649 y(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fd(September)25 b(26,)f(2001)1180 b(Magic)24 +b(T)l(utorial)f(#2:)31 b(Basic)25 b(P)o(ainting)e(and)i(Selection)146 +68 y(Y)-11 b(ou)24 b(can)h(also)e(select)h(material)g(by)g(area:)31 +b(place)24 b(the)g(box)g(around)g(the)g(material)f(you')-5 +b(d)24 b(lik)o(e)f(to)h(select)g(and)0 188 y(type)g Fb(a)h +Fd(\(short)f(for)i Fb(:select)f(ar)n(ea)p Fd(\).)31 b(This)24 +b(will)g(select)h(all)f(of)h(the)g(material)f(underneath)h(the)f(box.) +31 b(Y)-11 b(ou)24 b(can)h(use)0 309 y(the)g(macro)g +Fb(A)f Fd(to)h(add)g(material)f(to)g(the)h(selection)f(by)h(area,)g +(and)g(you)f(can)i(use)e(the)h(long)f(command)900 526 +y Fb(:select)h Fd([)p Fb(mor)n(e)p Fd(])p Fb(ar)n(ea)h +Fe(layer)o(s)146 743 y Fd(to)32 b(select)g(only)g(material)g(on)g +(certain)g(layers.)53 b(Place)34 b(the)e(box)f(around)i(e)n(v)o +(erything)d(in)i Fb(tut2b)h Fd(and)f(type)0 863 y Fb(:select)25 +b(ar)n(ea)h(metal1)e Fd(follo)n(wed)g(by)g Fb(:select)i(mor)n(e)f(ar)n +(ea)g(poly)p Fd(.)146 984 y(If)h(you')-5 b(d)25 b(lik)o(e)g(to)h(clear) +g(out)f(the)g(selection)g(without)f(modifying)g(an)o(y)h(of)h(the)f +(selected)g(material,)h(you)f(can)0 1104 y(use)g(the)f(command)900 +1321 y Fb(:select)h(clear)146 1539 y Fd(or)j(type)f(the)g(macro)h +Fb(C)p Fd(.)f(Y)-11 b(ou)28 b(can)g(clear)g(out)f(just)f(a)i(portion)f +(of)g(the)h(selection)e(by)i(typing)e Fb(:select)i(less)f +Fd(or)0 1659 y Fb(:select)g(less)e(ar)n(ea)i Fe(layer)o(s)p +Fd(;)f(the)g(former)g(deselects)g(paint)f(in)h(the)g(order)g(that)g +Fb(:select)g Fd(selects)g(paint,)g(while)f(the)0 1779 +y(latter)d(deselects)f(paint)g(under)h(the)g(box)f(\(just)g(as)h +Fb(:select)h(ar)n(ea)f Fd(selects)g(paint)f(under)h(the)f(box\).)30 +b(F)o(or)22 b(a)g(synopsis)0 1900 y(of)j(all)f(the)h(options)e(to)i +(the)f Fb(:select)i Fd(command,)e(type)900 2117 y Fb(:select)h(help)0 +2455 y Ff(5)143 b(Operations)34 b(on)h(the)g(Selection)0 +2678 y Fd(Once)25 b(you')-5 b(v)o(e)24 b(made)h(a)g(selection,)f(there) +h(are)h(a)f(number)f(of)h(operations)f(you)g(can)h(perform)g(on)g(it:) +900 2896 y Fb(:delete)900 3016 y(:mo)o(v)o(e)g Fd([)p +Fe(dir)l(ection)f Fd([)p Fe(distance)p Fd(]])900 3136 +y Fb(:str)n(etch)i Fd([)p Fe(dir)l(ection)f Fd([)p Fe(distance)p +Fd(]])900 3257 y Fb(:copy)900 3377 y(:upsidedo)o(wn)900 +3497 y(:sideways)900 3618 y(:clockwise)g Fd([)p Fe(de)l(gr)l(ees)p +Fd(])146 3955 y(The)k Fb(:delete)i Fd(command)d(deletes)g(e)n(v)o +(erything)f(that')-5 b(s)28 b(selected.)44 b(W)-8 b(atch)29 +b(out:)38 b Fb(:delete)30 b Fd(is)f(dif)n(ferent)f(from)0 +4076 y Fb(:erase)p Fd(,)37 b(which)c(erases)i(paint)e(from)h(the)g +(area)h(underneath)f(the)g(box.)58 b(Select)35 b(the)f(red)g(bar)g(on)g +(the)g(right)f(in)0 4196 y Fb(tut2b)26 b Fd(and)f(type)f +Fb(d)p Fd(,)h(which)g(is)f(a)h(macro)g(for)g Fb(:delete)p +Fd(.)32 b(Undo)24 b(the)h(deletion)f(with)g(the)h Fb(u)g +Fd(macro.)146 4317 y(The)c Fb(:mo)o(v)o(e)g Fd(command)f(picks)g(up)g +(both)g(the)h(box)f(and)h(the)f(selection)g(and)h(mo)o(v)o(es)e(them)h +(so)h(that)f(the)g(lo)n(wer)n(-)0 4437 y(left)25 b(corner)h(of)f(the)g +(box)g(is)g(at)g(the)g(cursor)g(location.)31 b(Select)26 +b(the)f(red)g(bar)h(on)f(the)g(right)f(and)i(mo)o(v)o(e)d(it)i(so)g +(that)g(it)0 4557 y(f)o(alls)j(on)g(top)f(of)i(the)f(v)o(ertical)f +(part)i(of)f(the)g(blue)g(\223L)-9 b(\224.)28 b(Y)-11 +b(ou)28 b(can)h(use)f Fb(t)g Fd(\(\223)p Fb(t)p Fd(ranslate\224\))h(as) +g(a)f(macro)h(for)f Fb(:mo)o(v)o(e)p Fd(.)0 4678 y(Practice)k(mo)o +(ving)d(v)n(arious)h(things)g(around)h(the)g(screen.)50 +b(The)31 b(command)f Fb(:copy)i Fd(and)f(its)g(macro)g +Fb(c)g Fd(are)h(just)0 4798 y(lik)o(e)24 b Fb(:mo)o(v)o(e)h +Fd(e)o(xcept)g(that)f(a)h(cop)o(y)g(of)g(the)f(selection)g(is)h(left)f +(behind)h(at)f(the)h(original)f(position.)146 4918 y(There)32 +b(is)e(also)h(a)g(longer)g(form)g(of)g(the)g Fb(:mo)o(v)o(e)g +Fd(command)f(that)h(you)f(can)i(use)e(to)h(mo)o(v)o(e)f(the)g +(selection)h(a)0 5039 y(precise)24 b(amount.)30 b(F)o(or)24 +b(e)o(xample,)f Fb(:mo)o(v)o(e)h(up)h(10)f Fd(will)f(mo)o(v)o(e)g(the)h +(selection)f(\(and)h(the)g(box\))g(up)g(10)g(units.)29 +b(The)0 5159 y Fe(dir)l(ection)21 b Fd(ar)n(gument)g(can)h(be)f(an)o(y) +g(direction)g(lik)o(e)g Fb(left)p Fd(,)i Fb(south)p Fd(,)g +Fb(do)o(wn)p Fd(,)f(etc.)30 b(See)23 b(the)e(Magic)g(manual)g(page)h +(for)0 5280 y(a)k(complete)e(list)h(of)g(the)g(le)o(gal)f(directions.) +32 b(The)25 b(macros)g Fb(q)p Fd(,)h Fb(w)p Fd(,)f Fb(e)p +Fd(,)h(and)f Fb(r)h Fd(are)g(de\002ned)g(to)f(mo)o(v)o(e)f(the)h +(selection)0 5400 y(left,)g(do)n(wn,)e(up,)i(and)g(right)f(\(respecti)n +(v)o(ely\))f(by)i(one)g(unit.)1875 5649 y(\2264\226)p +eop +%%Page: 5 5 +5 4 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)1179 b(September)25 b(26,)g(2001)146 +68 y(The)39 b Fb(:str)n(etch)i Fd(command)c(is)i(similar)e(to)i +Fb(:mo)o(v)o(e)g Fd(e)o(xcept)f(that)g(it)g(stretches)h(and)g(erases)g +(as)g(it)f(mo)o(v)o(es.)0 188 y Fb(:str)n(etch)25 b Fd(does)e(not)f +(operate)h(diagonally)-6 b(,)22 b(so)h(if)g(you)f(use)h(the)g(cursor)g +(to)g(indicate)g(where)g(to)g(stretch)g(to,)f(Magic)0 +309 y(will)j(either)i(stretch)f(up,)g(do)n(wn,)f(left,)i(or)f(right,)g +(whiche)n(v)o(er)f(is)h(closest.)34 b(The)27 b Fb(:str)n(etch)g +Fd(command)f(mo)o(v)o(es)e(the)0 429 y(selection)30 b(and)h(also)g +(does)g(tw)o(o)f(additional)g(things.)48 b(First,)32 +b(for)g(each)f(piece)h(of)f(paint)f(that)h(mo)o(v)o(es,)f +Fb(:str)n(etch)0 549 y Fd(will)j(erase)h(that)f(layer)h(from)g(the)f +(re)o(gion)g(that)g(the)g(paint)g(passes)h(through)e(as)i(it)f(mo)o(v)o +(es,)h(in)f(order)h(to)f(clear)0 670 y(material)26 b(out)g(of)g(its)g +(w)o(ay)-6 b(.)35 b(Second,)27 b(if)g(the)f(back)g(edge)h(of)g(a)f +(piece)h(of)f(selected)h(paint)f(touches)f(non-selected)0 +790 y(material,)34 b(one)e(of)g(the)g(tw)o(o)g(pieces)g(of)g(paint)g +(is)g(stretched)f(to)h(maintain)f(the)h(connection.)52 +b(The)33 b(macros)f Fb(Q)p Fd(,)0 911 y Fb(W)p Fd(,)d +Fb(E)p Fd(,)i(and)f Fb(R)f Fd(just)g(lik)o(e)h(the)f(macros)h +Fb(q)p Fd(,)h(etc.)46 b(described)30 b(abo)o(v)o(e)f(for)h +Fb(:mo)o(v)o(e)p Fd(.)46 b(The)30 b(macro)g Fb(T)g Fd(is)f +(prede\002ned)0 1031 y(to)j Fb(:str)n(etch)p Fd(.)55 +b(T)-8 b(o)32 b(see)h(ho)n(w)f(stretching)f(w)o(orks,)j(select)e(the)h +(horizontal)e(piece)i(of)f(the)h(green)f(wire)h(in)f +Fb(tut2b)0 1151 y Fd(and)26 b(type)f Fb(W)p Fd(,)g(then)g +Fb(E)p Fd(.)h(Stretching)f(only)g(w)o(orries)h(about)f(material)g(in)g +(front)g(of)h(and)f(behind)g(the)h(selection;)f(it)0 +1272 y(ignores)j(material)g(to)f(the)i(sides)e(\(try)i(the)f +Fb(Q)g Fd(and)g Fb(R)g Fd(macros)g(to)g(see\).)42 b(Y)-11 +b(ou)28 b(can)g(use)h(plo)n(wing)d(\(described)i(in)0 +1392 y(T)l(utorial)23 b(#3\))i(if)g(this)f(is)g(a)h(problem.)146 +1513 y(The)g(command)e Fb(:upsidedo)o(wn)j Fd(will)d(\003ip)i(the)f +(selection)f(upside)h(do)n(wn,)f(and)h Fb(:sideways)g +Fd(\003ips)h(the)f(selec-)0 1633 y(tion)g(side)n(w)o(ays.)29 +b(Both)c(commands)e(lea)n(v)o(e)h(the)h(selection)e(so)i(it)f(occupies) +g(the)g(same)h(total)e(area)j(as)f(before,)g(b)n(ut)0 +1753 y(with)c(the)g(contents)f(\003ipped.)30 b(The)21 +b(command)g Fb(:clockwise)g Fd(will)g(rotate)g(the)g(selection)g +(clockwise,)g(lea)n(ving)g(the)0 1874 y(lo)n(wer)n(-left)g(corner)h(of) +g(the)f(ne)n(w)g(selection)g(at)g(the)h(same)f(place)h(as)g(the)f(lo)n +(wer)n(-left)g(corner)h(of)g(the)f(old)g(selection.)0 +1994 y Fe(De)l(gr)l(ees)k Fd(must)f(be)h(a)g(multiple)e(of)i(90,)f(and) +h(def)o(aults)f(to)h(90.)146 2114 y(At)i(this)e(point)h(you)g(kno)n(w)f +(enough)h(to)g(do)g(quite)g(a)h(bit)f(of)g(damage)h(to)f(the)g +Fb(tut2b)i Fd(cell.)35 b(Experiment)26 b(with)0 2235 +y(the)f(selection)f(commands.)29 b(Remember)c(that)g(you)f(can)h(use)g +Fb(:undo)h Fd(to)e(back)h(out)g(of)f(trouble.)0 2573 +y Ff(6)143 b(Labels)0 2797 y Fd(Labels)30 b(are)i(pieces)e(of)h(te)o +(xt)f(attached)g(to)h(the)f(paint)g(of)h(a)g(cell.)48 +b(The)o(y)30 b(are)h(used)g(to)f(pro)o(vide)f(information)g(to)0 +2917 y(other)d(tools)g(that)g(will)g(process)g(the)g(circuit.)36 +b(Most)25 b(labels)i(are)g(node)f(names:)34 b(the)o(y)25 +b(pro)o(vide)h(an)h(easy)f(w)o(ay)h(of)0 3037 y(referring)j(to)g(nodes) +f(in)g(tools)g(such)g(as)h(routers,)h(simulators,)e(and)h(timing)e +(analyzers.)46 b(Labels)29 b(may)h(also)f(be)0 3158 y(used)i(for)h +(other)f(purposes:)43 b(for)31 b(e)o(xample,)h(some)f(labels)g(are)h +(treated)g(as)f Fe(attrib)n(utes)f Fd(that)g(gi)n(v)o(e)g(Crystal,)j +(the)0 3278 y(timing)23 b(analyzer)l(,)i(information)f(about)g(the)h +(direction)f(of)h(signal)f(\003o)n(w)g(through)g(transistors.)146 +3398 y(Load)i(the)g(cell)f Fb(tut2c)i Fd(and)f(place)g(a)g(cross)g(in)f +(the)h(middle)f(of)g(the)h(red)g(chunk)g(\(to)f(mak)o(e)h(a)g(cross,)g +(position)0 3519 y(the)34 b(lo)n(wer)n(-left)g(corner)g(of)g(the)g(box) +g(with)f(the)h(left)g(b)n(utton)f(and)h(then)g(click)g(the)g(right)f(b) +n(utton)g(to)h(place)g(the)0 3639 y(upper)n(-right)d(corner)i(on)e(top) +h(of)g(the)f(lo)n(wer)n(-left)h(corner\).)52 b(Then)32 +b(type)g(type)f(the)h(command)f Fb(:label)h(test)p Fd(.)52 +b(A)0 3760 y(ne)n(w)24 b(label)h(will)f(appear)h(at)g(the)g(position)e +(of)i(the)f(box.)31 b(The)24 b(complete)h(syntax)f(of)g(the)h +Fb(:label)g Fd(command)f(is)900 3978 y Fb(:label)h Fd([)p +Fe(te)n(xt)g Fd([)p Fe(position)e Fd([)p Fe(layer)p Fd(]]])146 +4196 y Fe(T)-9 b(e)n(xt)32 b Fd(must)e(be)h(supplied,)g(b)n(ut)g(the)g +(other)g(ar)n(guments)f(can)h(be)h(def)o(aulted.)49 b(If)31 +b Fe(te)n(xt)g Fd(has)g(an)o(y)g(spaces)g(in)g(it,)0 +4317 y(then)20 b(it)g(must)f(be)i(enclosed)f(in)g(double)g(quotes.)28 +b Fe(P)-8 b(osition)19 b Fd(tells)h(where)g(the)h(te)o(xt)e(should)g +(be)i(displayed,)f(relati)n(v)o(e)0 4437 y(to)28 b(the)h(point)f(of)g +(the)h(label.)42 b(It)29 b(may)f(be)h(an)o(y)g(of)f Fb(north)p +Fd(,)j Fb(south)p Fd(,)f Fb(east)p Fd(,)g Fb(west)p Fd(,)g +Fb(top)p Fd(,)g Fb(bottom)p Fd(,)g Fb(left)p Fd(,)g Fb(right)p +Fd(,)g Fb(up)p Fd(,)0 4557 y Fb(do)o(wn)p Fd(,)c Fb(center)p +Fd(,)g Fb(northeast)p Fd(,)g Fb(ne)p Fd(,)g Fb(southeast)p +Fd(,)g Fb(se)p Fd(,)f Fb(southwest)p Fd(,)h Fb(sw)p Fd(,)e +Fb(northwest)p Fd(,)j Fb(nw)p Fd(.)32 b(F)o(or)25 b(e)o(xample,)f(if)h +Fb(ne)h Fd(is)0 4678 y(gi)n(v)o(en,)i(the)h(te)o(xt)f(will)g(be)h +(displayed)f(abo)o(v)o(e)g(and)h(to)g(the)f(right)h(of)g(the)f(label)h +(point.)42 b(If)29 b(no)g Fe(position)e Fd(is)i(gi)n(v)o(en,)0 +4798 y(Magic)j(will)f(pick)g(a)i(position)d(for)i(you.)52 +b Fe(Layer)32 b Fd(tells)g(which)f(paint)h(layer)g(to)f(attach)h(the)g +(label)g(to.)52 b(If)32 b Fe(layer)0 4918 y Fd(co)o(v)o(ers)h(the)g +(entire)g(area)h(of)g(the)f(label,)i(then)e(the)g(label)h(will)e(be)i +(associated)e(with)h(the)g(particular)h(layer)-5 b(.)56 +b(If)0 5039 y Fe(layer)26 b Fd(is)f(omitted,)f(or)i(if)g(it)f(doesn')n +(t)h(co)o(v)o(er)f(the)h(label')-5 b(s)25 b(area,)h(Magic)g(initially)e +(associates)h(the)h(label)f(with)g(the)0 5159 y(\223space\224)32 +b(layer)l(,)g(then)f(checks)g(to)f(see)i(if)f(there')-5 +b(s)30 b(a)h(layer)g(that)g(co)o(v)o(ers)f(the)h(whole)f(area.)50 +b(If)31 b(there)h(is,)f(Magic)0 5280 y(mo)o(v)o(es)f(the)i(label)g(to)f +(that)h(layer)-5 b(.)52 b(It)32 b(is)f(generally)h(a)h(bad)e(idea)i(to) +e(place)h(labels)g(at)g(points)f(where)h(there)g(are)0 +5400 y(se)n(v)o(eral)d(paint)f(layers,)j(since)e(it)g(will)f(be)i(hard) +f(to)g(tell)g(which)g(layer)g(the)g(label)h(is)e(attached)i(to.)44 +b(As)29 b(you)g(edit,)1875 5649 y(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Fd(September)25 b(26,)f(2001)1180 b(Magic)24 +b(T)l(utorial)f(#2:)31 b(Basic)25 b(P)o(ainting)e(and)i(Selection)0 +68 y(Magic)h(will)g(ensure)h(that)f(labels)g(are)h(only)f(attached)g +(to)g(layers)h(that)f(e)o(xist)f(e)n(v)o(erywhere)i(under)f(the)h +(label.)35 b(T)-8 b(o)0 188 y(see)34 b(ho)n(w)f(this)g(w)o(orks,)j +(paint)d(the)g(layer)i(pdif)n(f)e(\(bro)n(wn\))g(o)o(v)o(er)g(the)h +(label)f(you)h(just)e(created:)50 b(the)33 b(label)h(will)0 +309 y(switch)24 b(layers.)31 b(Finally)-6 b(,)23 b(erase)j(poly)e(o)o +(v)o(er)g(the)h(area,)g(and)g(the)g(label)f(will)g(mo)o(v)o(e)f(again.) +146 429 y(Although)f(man)o(y)h(labels)g(are)i(point)d(labels,)h(this)g +(need)h(not)f(be)h(the)f(case.)31 b(Y)-11 b(ou)23 b(can)h(label)g(an)o +(y)f(rectangular)0 549 y(area)32 b(by)f(setting)f(the)h(box)g(to)f +(that)h(area)h(before)g(in)l(v)n(oking)d(the)i(label)g(command.)49 +b(This)30 b(feature)i(is)f(used)g(for)0 670 y(labelling)19 +b(terminals)g(for)h(the)f(router)h(\(see)h(belo)n(w\),)f(and)g(for)g +(labelling)f(tiles)g(used)g(by)h(Mpack,)g(the)g(tile)g(packing)0 +790 y(program.)30 b Fb(T)-9 b(ut2c)26 b Fd(has)f(e)o(xamples)f(of)g +(point,)g(line,)g(and)h(rectangular)g(labels.)146 911 +y(All)g(of)h(the)f(selection)g(commands)f(apply)h(to)g(labels)f(as)i +(well)f(as)h(paint.)31 b(Whene)n(v)o(er)25 b(you)g(select)g(paint,)g +(the)0 1031 y(labels)i(attached)h(to)f(that)h(paint)f(will)g(also)g(be) +h(selected.)39 b(Selected)29 b(labels)e(are)h(highlighted)e(in)i +(white.)39 b(Select)0 1151 y(some)31 b(of)g(the)h(chunks)e(of)i(paint)f +(in)g Fb(tut2c)h Fd(to)f(see)h(ho)n(w)f(the)g(labels)g(are)h(selected)f +(too.)50 b(When)32 b(you)f(use)g(area)0 1272 y(selection,)d(labels)g +(will)f(only)h(be)g(selected)h(if)f(the)o(y)f(are)i(completely)e +(contained)h(in)g(the)g(area)h(being)f(selected.)0 1392 +y(If)d(you')-5 b(d)24 b(lik)o(e)g(to)g(select)g Fe(just)f +Fd(a)i(label)f(without)f(an)o(y)h(paint,)f(mak)o(e)i(the)f(box)g(into)f +(a)i(cross)f(and)g(put)g(the)g(cross)g(on)0 1513 y(the)h(label:)30 +b Fb(s)25 b Fd(and)f Fb(S)i Fd(will)e(select)g(just)g(the)h(label.)146 +1633 y(There)k(are)h(se)n(v)o(eral)e(w)o(ays)g(to)h(erase)g(a)g(label.) +42 b(One)29 b(w)o(ay)g(is)f(to)g(select)h(and)g(then)f(delete)h(it.)42 +b(Another)28 b(w)o(ay)0 1753 y(is)k(to)g(erase)g(the)g(paint)g(that)g +(the)g(label)g(is)f(attached)i(to.)52 b(If)33 b(the)f(paint)f(is)h +(erased)h(all)f(around)g(the)g(label,)h(then)0 1874 y(Magic)26 +b(will)f(delete)i(the)f(label)g(too.)34 b(T)m(ry)26 b(attaching)f(a)i +(label)f(to)g(a)g(red)h(area,)g(then)f(paint)g(blue)g(o)o(v)o(er)f(the) +h(red.)36 b(If)0 1994 y(you)28 b(erase)g(blue)g(the)g(label)f(stays)h +(\(since)g(it')-5 b(s)27 b(attached)h(to)f(red\),)j(b)n(ut)d(if)h(you)f +(erase)i(the)f(red)g(then)g(the)g(label)g(is)0 2114 y(deleted.)146 +2235 y(Y)-11 b(ou)19 b(can)g(also)g(erase)g(labels)g(using)f(the)g +Fb(:erase)i Fd(command)e(and)g(the)h(pseudo-layer)g Fb(labels)p +Fd(.)28 b(The)19 b(command)900 2453 y Fb(:erase)25 b(labels)146 +2671 y Fd(will)d(erase)i(all)e(labels)g(that)g(lie)h(completely)e +(within)h(the)g(area)i(of)f(the)f(box.)30 b(Finally)-6 +b(,)22 b(you)g(can)h(erase)g(a)g(label)0 2792 y(by)i(making)f(the)i +(box)f(into)f(a)i(cross)f(on)g(top)g(of)h(the)f(label,)g(then)g +(clicking)g(the)g(middle)f(b)n(utton)g(with)h(the)g(cursor)0 +2912 y(o)o(v)o(er)j(empty)h(space.)45 b(T)-7 b(echnically)h(,)29 +b(this)f(will)h(erase)h(all)f(paint)g(layers)g(and)g(labels)g(too.)44 +b(Ho)n(we)n(v)o(er)l(,)29 b(since)g(the)0 3033 y(box)24 +b(has)h(zero)g(area,)h(erasing)f(paint)f(has)h(no)f(ef)n(fect:)31 +b(only)24 b(the)h(labels)f(are)i(erased.)0 3371 y Ff(7)143 +b(Labelling)34 b(Con)-6 b(v)o(entions)0 3594 y Fd(When)20 +b(creating)f(labels,)h(Magic)f(will)g(permit)f(you)h(to)h(use)f +(absolutely)f(an)o(y)h(te)o(xt)g(whatsoe)n(v)o(er)-5 +b(.)27 b(Ho)n(we)n(v)o(er)l(,)19 b(man)o(y)0 3715 y(other)i(tools,)g +(and)h(e)n(v)o(en)f(parts)g(of)h(Magic,)g(e)o(xpect)f(label)g(names)h +(to)f(observ)o(e)g(certain)h(con)l(v)o(entions.)27 b(Except)22 +b(for)0 3835 y(the)k(special)g(cases)g(described)g(belo)n(w)-6 +b(,)25 b(labels)g(shouldn')n(t)g(contain)g(an)o(y)h(of)g(the)g +(characters)h(\223/$@!\210\224.)34 b(Spaces,)0 3955 y(control)23 +b(characters,)h(or)g(parentheses)f(within)f(labels)h(are)h(probably)f +(a)h(bad)f(idea)h(too.)29 b(Man)o(y)23 b(of)g(the)h(programs)0 +4076 y(that)f(process)h(Magic)g(output)e(ha)n(v)o(e)i(their)f(o)n(wn)g +(restrictions)g(on)h(label)f(names,)h(so)f(you)h(should)e(\002nd)i(out) +g(about)0 4196 y(the)38 b(restrictions)f(that)h(apply)f(at)h(your)g +(site.)71 b(Most)37 b(labels)g(are)i(node)f(names:)57 +b(each)39 b(one)f(gi)n(v)o(es)e(a)j(unique)0 4317 y(identi\002cation)23 +b(to)h(a)h(set)f(of)h(things)e(that)h(are)h(electrically)f(connected.) +31 b(There)24 b(are)i(tw)o(o)d(kinds)h(of)g(node)h(names,)0 +4437 y(local)k(and)h(global.)44 b(An)o(y)28 b(label)h(that)g(ends)h(in) +f(\223!\224)45 b(is)29 b(treated)h(as)g(a)f(global)g(node)g(name;)j(it) +d(will)f(be)i(assumed)0 4557 y(that)e(all)g(nodes)g(by)g(this)f(name,)i +(an)o(ywere)f(in)g(an)o(y)g(cell)g(in)g(a)h(layout,)f(are)h +(electrically)f(connected.)41 b(The)28 b(most)0 4678 +y(common)e(global)g(names)h(are)h Fb(Vdd!)38 b Fd(and)27 +b Fb(GND!)p Fd(,)g(the)g(po)n(wer)g(rails.)37 b(Y)-11 +b(ou)27 b(should)f(al)o(w)o(ays)h(use)g(these)f(names)0 +4798 y(e)o(xactly)-6 b(,)27 b(since)g(man)o(y)g(other)g(tools)f +(require)i(them.)38 b(Nobody)27 b(kno)n(ws)f(why)h(\223GND!\224)h(is)f +(all)g(in)g(capital)h(letters)0 4918 y(and)d(\223Vdd!\224)31 +b(isn')n(t.)146 5039 y(An)o(y)e(label)f(that)h(does)g(not)f(end)h(in)g +(\223!\224)44 b(or)29 b(an)o(y)g(of)g(the)g(other)f(special)h +(characters)h(discussed)e(belo)n(w)g(is)h(a)0 5159 y(local)23 +b(node)g(name.)30 b(It)23 b(refers)h(to)e(a)i(node)f(within)e(that)i +(particular)g(cell.)30 b(Local)23 b(node)g(names)g(should)f(be)h +(unique)0 5280 y(within)e(the)h(cell:)30 b(there)22 b(shouldn')n(t)f +(be)i(tw)o(o)f(electrically)g(distinct)f(nodes)h(with)g(the)g(same)g +(name.)30 b(On)22 b(the)g(other)0 5400 y(hand,)30 b(it)e(is)h +(perfectly)g(le)o(gal,)g(and)g(sometimes)e(adv)n(antageous,)i(to)g(gi)n +(v)o(e)e(more)i(than)g(one)g(name)g(to)f(the)h(same)1875 +5649 y(\2266\226)p eop +%%Page: 7 7 +7 6 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)1179 b(September)25 b(26,)g(2001)0 +68 y(node.)46 b(It)29 b(is)h(also)f(le)o(gal)g(to)g(use)h(the)g(same)f +(local)h(node)f(name)h(in)g(dif)n(ferent)f(cells:)40 +b(the)30 b(tools)f(will)g(be)h(able)f(to)0 188 y(distinguish)22 +b(between)j(them)f(and)h(will)f(not)g(assume)g(that)h(the)o(y)f(are)h +(electrically)g(connected.)146 309 y(The)35 b(only)e(other)i(labels)e +(currently)i(understood)e(by)h(the)g(tools)f(are)i Fe(attrib)n(utes)p +Fd(.)58 b(Attrib)n(utes)33 b(are)i(pieces)0 429 y(of)g(te)o(xt)e +(associated)h(with)g(a)h(particular)g(piece)g(of)f(the)h(circuit:)49 +b(the)o(y)34 b(are)h(not)f(node)h(names,)h(and)f(need)g(not)0 +549 y(be)30 b(unique.)44 b(F)o(or)30 b(e)o(xample,)g(an)g(attrib)n(ute) +f(might)f(identify)h(a)h(node)f(as)h(a)g(chip)f(input,)h(or)g(it)f +(might)f(identify)h(a)0 670 y(transistor)e(terminal)g(as)g(the)h +(source)g(of)g(information)e(for)i(that)f(transistor)-5 +b(.)38 b(An)o(y)27 b(label)g(whose)h(last)f(character)0 +790 y(is)e(\223@\224,)h(\223$\224,)g(or)g(\223\210\224)g(is)g(an)f +(attrib)n(ute.)33 b(There)26 b(are)g(three)g(dif)n(ferent)f(kinds)g(of) +g(attrib)n(utes.)32 b(Node)26 b(attrib)n(utes)e(are)0 +911 y(those)c(ending)f(with)h(\223@\224;)h(the)o(y)f(are)h(associated)e +(with)h(particular)g(nodes.)29 b(T)m(ransistor)18 b(source/drain)i +(attrib)n(utes)0 1031 y(are)30 b(those)f(ending)g(in)g(\223$\224;)j +(the)o(y)c(are)i(associated)f(with)g(particular)g(terminals)g(of)g(a)h +(transistor)-5 b(.)43 b(A)29 b(source)h(or)0 1151 y(drain)25 +b(attrib)n(ute)f(must)h(be)g(attached)g(to)g(the)g(channel)g(re)o(gion) +g(of)g(the)g(transistor)f(and)h(must)g(f)o(all)g(e)o(xactly)f(on)h(the) +0 1272 y(source)31 b(or)h(drain)f(edge)h(of)f(the)g(transistor)-5 +b(.)49 b(The)32 b(third)e(kind)h(of)g(attrib)n(ute)g(is)g(a)g +(transistor)g(gate)g(attrib)n(ute.)49 b(It)0 1392 y(ends)22 +b(in)h(\223\210\224)g(and)g(is)f(attached)h(to)f(the)h(channel)g(re)o +(gion)f(of)g(the)h(transistor)-5 b(.)28 b(T)-8 b(o)23 +b(see)g(e)o(xamples)f(of)g(attrib)n(utes)g(and)0 1513 +y(node)j(names,)f(edit)g(the)h(cell)g Fb(tut2d)h Fd(in)e(Magic.)146 +1633 y(Special)j(con)l(v)o(entions)d(apply)h(to)h(labels)f(for)i +(routing)d(terminals.)34 b(The)26 b(standard)f(Magic)h(router)g(\(in)l +(v)n(ok)o(ed)0 1753 y(by)37 b Fb(:r)n(oute)p Fd(\))j(ignores)d(all)g +(labels)g(e)o(xcept)g(for)h(those)f(on)h(the)f(edges)h(of)g(cells.)69 +b(\(This)37 b(restriction)f(does)i(not)0 1874 y(apply)31 +b(to)g(the)h(gate-array)g(router)l(,)h(Garoute,)h(or)d(to)h(the)f +(interacti)n(v)o(e)f(router)l(,)k(Iroute\).)51 b(If)32 +b(you)g(e)o(xpect)f(to)g(use)0 1994 y(the)c(standard)h(router)f(to)h +(connect)f(to)g(a)h(particular)g(node,)g(you)f(should)f(place)i(the)g +(label)f(for)h(that)f(node)h(on)f(its)0 2114 y(outermost)21 +b(edge.)30 b(The)22 b(label)g(should)g(not)f(be)i(a)f(point)g(label,)g +(b)n(ut)g(should)f(instead)h(be)g(a)h(horizontal)e(or)i(v)o(ertical)0 +2235 y(line)31 b(co)o(v)o(ering)g(the)h(entire)g(edge)g(of)g(the)f +(wire.)52 b(The)32 b(router)g(will)f(choose)h(a)g(connection)f(point)g +(some)n(where)0 2355 y(along)c(the)h(label.)39 b(A)28 +b(good)f(rule)h(of)f(thumb)g(is)g(to)g(label)h(all)f(nodes)h(that)f +(enter)h(or)g(lea)n(v)o(e)f(the)h(cell)f(in)h(this)f(w)o(ay)-6 +b(.)0 2476 y(F)o(or)20 b(more)h(details)e(on)h(ho)n(w)g(labels)g(are)h +(used)f(by)g(the)g(standard)g(router)l(,)h(see)g(\223Magic)f(T)l +(utorial)f(#7:)28 b(Netlists)19 b(and)0 2596 y(Routing\224.)29 +b(Other)23 b(labeling)e(con)l(v)o(entions)g(are)i(used)f(by)g(the)g +(Garouter)g(and)h(Irouter)l(,)g(consult)e(their)h(respecti)n(v)o(e)0 +2716 y(tutorials)h(for)j(details.)0 3055 y Ff(8)143 b(Files)35 +b(and)g(F)l(ormats)0 3278 y Fd(Magic)22 b(pro)o(vides)e(a)i(v)n(ariety) +g(of)g(w)o(ays)f(to)h(sa)n(v)o(e)f(your)h(cells)g(on)f(disk.)29 +b(Normally)-6 b(,)21 b(things)g(are)h(sa)n(v)o(ed)g(in)f(a)h(special)0 +3398 y(Magic)34 b(format.)58 b(Each)35 b(cell)f(is)g(a)g(separate)h +(\002le,)i(and)d(the)g(name)g(of)g(the)g(\002le)h(is)f(just)f(the)h +(name)g(of)g(the)g(cell)0 3519 y(with)23 b Fb(.mag)h +Fd(appended.)31 b(F)o(or)24 b(e)o(xample,)f(the)h(cell)g +Fb(tut2a)h Fd(is)f(sa)n(v)o(ed)f(in)h(\002le)h Fb(tut2a.mag)p +Fd(.)30 b(T)-8 b(o)24 b(sa)n(v)o(e)g(cells)g(on)g(disk,)0 +3639 y(in)l(v)n(ok)o(e)g(the)h(command)900 3857 y Fb(:writeall)146 +4076 y Fd(This)d(command)g(will)g(run)h(through)f(each)h(of)g(the)g +(cells)g(that)f(you)g(ha)n(v)o(e)h(modi\002ed)f(in)h(this)f(editing)f +(session,)0 4196 y(and)33 b(ask)f(you)h(what)f(to)g(do)h(with)f(the)g +(cell.)55 b(Normally)-6 b(,)33 b(you')o(ll)f(type)g Fb(write)p +Fd(,)j(or)e(just)f(hit)g(the)g(return)h(k)o(e)o(y)-6 +b(,)33 b(in)0 4317 y(which)f(case)g(the)g(cell)h(will)e(be)h(written)g +(back)g(to)g(the)g(disk)f(\002le)i(from)f(which)f(it)h(w)o(as)g(read)h +(\(if)f(this)f(is)h(a)h(ne)n(w)0 4437 y(cell,)23 b(then)g(you')o(ll)g +(be)g(ask)o(ed)h(for)f(a)h(name)f(for)h(the)f(cell\).)30 +b(If)24 b(you)f(type)g Fb(auto)o(write)p Fd(,)h(then)f(Magic)g(will)g +(write)g(out)0 4557 y(all)30 b(the)g(cells)g(that)f(ha)n(v)o(e)h +(changed)g(without)f(asking)g(you)h(what)g(to)g(do)f(on)h(a)h +(cell-by-cell)f(basis.)46 b Fb(Flush)30 b Fd(will)0 4678 +y(cause)f(Magic)f(to)h(delete)f(its)g(internal)g(cop)o(y)h(of)g(the)f +(cell)h(and)g(reload)f(the)h(cell)f(from)h(the)f(disk)g(cop)o(y)-6 +b(,)29 b(thereby)0 4798 y(e)o(xpunging)f(all)h(edits)g(that)g(you')-5 +b(v)o(e)29 b(made.)45 b Fb(Skip)30 b Fd(will)f(pass)g(on)g(to)g(the)h +(ne)o(xt)e(cell)i(without)e(writing)h(this)f(cell)0 4918 +y(\(b)n(ut)g(Magic)g(still)g(remembers)g(that)g(it)g(has)h(changed,)g +(so)f(the)h(ne)o(xt)f(time)f(you)i(in)l(v)n(ok)o(e)e +Fb(:writeall)i Fd(Magic)f(will)0 5039 y(ask)d(about)g(this)f(cell)h +(again\).)32 b Fb(Abort)26 b Fd(will)e(stop)g(the)h(command)g +(immediately)e(without)h(writing)g(or)h(checking)0 5159 +y(an)o(y)f(more)h(cells.)146 5280 y Fb(IMPOR)l(T)-9 b(ANT)28 +b(NO)l(TE:)g Fd(Unlik)o(e)f(vi)g(and)h(other)g(te)o(xt)e(editors,)i +(Magic)f(doesn')n(t)g(k)o(eep)h(checkpoint)f(\002les.)0 +5400 y(This)d(means)g(that)g(if)h(the)f(system)g(should)f(crash)i(in)f +(the)h(middle)e(of)i(a)g(session,)e(you')o(ll)h(lose)g(all)h(changes)f +(since)1875 5649 y(\2267\226)p eop +%%Page: 8 8 +8 7 bop 0 -180 a Fd(September)25 b(26,)f(2001)1180 b(Magic)24 +b(T)l(utorial)f(#2:)31 b(Basic)25 b(P)o(ainting)e(and)i(Selection)0 +68 y(the)h(last)f(time)g(you)g(wrote)h(out)g(cells.)33 +b(It')-5 b(s)25 b(a)h(good)g(idea)g(to)f(sa)n(v)o(e)h(your)f(cells)h +(frequently)f(during)g(long)g(editing)0 188 y(sessions.)146 +309 y(Y)-11 b(ou)25 b(can)g(also)f(sa)n(v)o(e)h(the)g(cell)f(you')-5 +b(re)25 b(currently)g(editing)e(with)h(the)h(command)900 +544 y Fb(:sa)n(v)o(e)f Fe(name)146 777 y Fd(This)k(command)g(will)f +(append)i(\223.mag\224)f(to)h Fe(name)f Fd(and)h(sa)n(v)o(e)f(the)g +(cell)h(you)f(are)h(editing)f(in)g(that)g(location.)0 +897 y(If)d(you)f(don')n(t)h(pro)o(vide)e(a)i(name,)g(Magic)f(will)g +(use)h(the)f(cell')-5 b(s)24 b(name)h(\(plus)f(the)g(\223.mag\224)h(e)o +(xtension\))e(as)i(the)g(\002le)0 1018 y(name,)g(and)f(it)h(will)f +(prompt)f(you)i(for)g(a)g(name)g(if)f(the)h(cell)g(hasn')n(t)f(yet)h +(been)g(named.)146 1139 y(Once)g(a)h(cell)e(has)h(been)g(sa)n(v)o(ed)f +(on)h(disk)f(you)g(can)h(edit)g(it)f(by)h(in)l(v)n(oking)e(Magic)h +(with)g(the)h(command)900 1373 y Fb(magic)f Fe(name)146 +1606 y Fd(where)i Fe(name)e Fd(is)h(the)f(same)h(name)g(you)f(used)h +(to)f(sa)n(v)o(e)g(the)h(cell)g(\(no)g(\223.mag\224)f(e)o(xtension\).) +146 1727 y(Magic)f(can)h(also)f(read)g(and)g(write)g(\002les)h(in)f +(CIF)h(and)f(Calma)h(Stream)f(formats.)30 b(See)24 b(\223Magic)f(T)l +(utorial)f(#9:)0 1848 y(F)o(ormat)i(Con)l(v)o(ersion)g(for)h(CIF)h(and) +f(Calma\224)g(for)g(details.)0 2192 y Ff(9)143 b(Plotting)0 +2417 y Fd(Magic)21 b(can)i(generate)f(hardcop)o(y)g(plots)e(of)i +(layouts)f(in)g(four)h(w)o(ays:)29 b(postscript)21 b(\(color\),)h(v)o +(ersatec)g(\(black-and-)0 2537 y(white)k(or)g(color\),)g(gremlin,)g +(and)g(pix)o(els)f(\(a)h(generalized)h(pix)o(el-\002le)e(that)h(can)g +(be)h(massaged)e(in)h(man)o(y)f(w)o(ays\).)0 2658 y(T)-8 +b(o)25 b(plot)f(part)g(of)h(your)g(design)f(in)g(PostScript,)h(place)g +(the)f(box)h(around)f(the)h(part)g(you')-5 b(d)24 b(lik)o(e)h(to)f +(plot)g(and)h(type)900 2892 y Fb(:plot)g(postscript)146 +3125 y Fd(This)33 b(will)f(generate)i(a)g(plot)f(of)g(the)g(area)i(of)e +(the)h(box.)56 b(Ev)o(erything)31 b(visible)i(underneath)g(the)g(box)g +(will)0 3246 y(appear)i(in)f(more-or)n(-less)h(the)f(same)h(w)o(ay)f +(in)h(the)f(plot.)59 b Fe(W)-5 b(idth)33 b Fd(speci\002es)i(ho)n(w)f +(wide)g(the)h(plot)f(will)f(be,)k(in)0 3366 y(inches.)k(Magic)28 +b(will)f(scale)h(the)g(plot)g(so)g(that)f(the)i(area)g(of)f(the)g(box)g +(comes)g(out)g(this)f(wide.)41 b(The)28 b(def)o(ault)g(for)0 +3486 y Fe(width)d Fd(is)g(the)g(width)g(of)g(the)g(plotter)g(\(if)g +Fe(width)g Fd(is)g(lar)n(ger)h(than)f(the)g(plotter)g(width,)g(it')-5 +b(s)24 b(reduced)i(to)f(the)g(plotter)0 3607 y(width\).)37 +b(If)28 b Fe(layer)o(s)f Fd(is)g(gi)n(v)o(en,)f(it)h(speci\002es)h(e)o +(xactly)e(what)h(information)f(is)h(to)g(be)h(plotted.)37 +b(Only)26 b(those)h(layers)0 3727 y(will)d(appear)h(in)g(the)f(plot.)30 +b(The)25 b(special)g(\223layer\224)g Fb(labels)g Fd(will)f(enable)g +(label)h(plotting.)146 3848 y(The)k(second)f(form)g(is)g(for)g(dri)n +(ving)f(printers)h(lik)o(e)f(color)i(V)-11 b(ersatecs.)41 +b(It)28 b(is)g(enabled)g(by)g(setting)g(the)g Fe(color)0 +3969 y Fd(plot)21 b(parameter)i(to)f Fe(true)p Fd(.)29 +b(A)22 b(table)g(of)h(stipples)d(for)j(the)f(primary)f(colors)h +(\(black,)h(c)o(yan,)f(magenta)g(abd)g(yello)n(w\))0 +4089 y(is)34 b(gi)n(v)o(en)g(in)g(the)h(technology)e(\002le.)61 +b(When)35 b(the)f Fe(plot)g Fd(command)g(is)g(gi)n(v)o(en,)i(four)f +(rasters)g(\(one)g(for)g(each)g(of)0 4209 y(the)29 b(colors\))f(are)h +(generated,)h(separated)f(with)f(the)h(proper)g(control)f(sequences)g +(for)h(the)g(printer)-5 b(.)42 b(Otherwise,)0 4330 y(operation)24 +b(is)h(e)o(xactly)f(as)h(for)g(the)f(black-and-white)h(case.)146 +4451 y(The)36 b(third)g(form)f(of)h(plotting)f(is)g(for)h(generating)g +(Gremlin-format)f(\002les,)k(which)c(can)i(then)e(be)i(edited)0 +4571 y(with)32 b(the)h(Gremlin)f(dra)o(wing)h(system)e(or)j(included)e +(in)h(documents)e(processed)i(by)g(Grn)g(and)g(Ditrof)n(f.)55 +b(The)0 4692 y(command)24 b(to)g(get)h(Gremlin)f(\002les)h(is)900 +4926 y Fb(:plot)g(gr)n(emlin)g Fe(\002le)g Fd([)p Fe(layer)o(s)p +Fd(])146 5159 y(It)31 b(will)f(generate)h(a)h(Gremlin-format)d(\002le)j +(in)e Fe(\002le)h Fd(that)f(describes)h(e)n(v)o(erything)e(underneath)i +(the)f(box.)49 b(If)0 5280 y Fe(layer)o(s)28 b Fd(is)g(speci\002ed,)h +(it)e(indicates)h(which)g(layers)g(are)h(to)f(appear)g(in)g(the)g +(\002le;)i(otherwise)e(e)n(v)o(erything)e(visible)0 5400 +y(on)i(the)h(screen)g(is)g(output.)41 b(The)29 b(Gremlin)f(\002le)h(is) +f(output)g(without)f(an)o(y)h(particular)h(scale;)h(use)f(the)g +Fb(width)g Fd(or)1875 5649 y(\2268\226)p eop +%%Page: 9 9 +9 8 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)1179 b(September)25 b(26,)g(2001)0 +69 y Fb(height)h Fd(commands)e(in)h(Grn)g(to)g(scale)h(the)f(plot)f +(when)h(it')-5 b(s)25 b(printed.)31 b(Y)-11 b(ou)25 b(should)f(use)h +(the)g Fb(mg)g Fd(stipples)f(when)0 189 y(printing)f(Magic)i(Gremlin)f +(plots;)f(these)i(will)f(produce)h(the)f(same)h(stipple)e(patterns)i +(as)g Fb(:plot)g(v)o(ersatec)p Fd(.)146 316 y(Finally)-6 +b(,)22 b(the)g(\223pix)o(els\224)f(style)h(of)g(plotting)f(generates)h +(a)h(\002le)f(of)h(pix)o(el)e(v)n(alues)g(for)i(the)f(re)o(gion)f(to)h +(be)g(plotted.)0 436 y(This)31 b(can)g(be)h(useful)f(for)g(input)f(to)h +(other)g(image)g(tools,)h(or)f(for)h(generation)f(of)g(slides)f(and)i +(vie)n(wgraphs)e(for)0 557 y(presentations.)51 b(The)31 +b(\002le)i(consists)d(of)i(a)g(sequence)g(of)g(bytes,)h(three)f(for)g +(each)h(pix)o(el,)f(written)f(from)h(left)f(to)0 677 +y(right)26 b(and)h(top)g(to)f(bottom.)36 b(Each)27 b(three)g(bytes)g +(represent)g(the)g(red,)h(green)f(and)g(blue)g(v)n(alues)f(used)h(to)f +(display)0 797 y(the)j(pix)o(el.)44 b(Thus,)30 b(if)f(the)g(upper)n +(-left-most)g(pix)o(el)f(were)i(to)f(be)h(red,)h(the)e(\002rst)h(three) +f(bytes)g(of)h(the)f(\002le)h(w)o(ould)0 918 y(ha)n(v)o(e)25 +b(v)n(alues)e(of)i(255,)g(0)f(and)h(0.)146 1045 y(The)30 +b(resolution)e(of)i(the)f(generated)h(\002le)g(is)g(normally)e(512,)i +(b)n(ut)f(can)h(be)g(controlled)f(by)g(setting)g(the)g(plot)0 +1165 y(parameter)36 b Fe(pixW)-5 b(idth)p Fd(.)60 b(It)35 +b(must)f(be)h(a)h(multiple)d(of)i(8;)40 b(Magic)35 b(will)f(round)h(up) +g(if)g(an)g(inappropriate)g(v)n(alue)0 1285 y(is)d(entered.)53 +b(The)32 b(height)f(of)h(the)g(\002le)h(is)f(determined)f(by)h(the)g +(shape)g(of)g(the)g(box.)53 b(In)32 b(an)o(y)g(case,)i(the)e(actual)0 +1406 y(resolution)g(of)i(the)f(\002le)h(is)f(appended)g(to)g(the)h +(\002le)f(name.)57 b(F)o(or)33 b(e)o(xample,)i(plotting)d(a)h(square)h +(re)o(gion,)h(2048)0 1526 y(pix)o(els)23 b(across,)i(will)f(result)g +(in)h(a)g(\002le)g(named)g(something)e(lik)o(e)h +(\223magicPlot1234a-2048-2048\224.)146 1653 y(There)c(are)h(se)n(v)o +(eral)e(plotting)e(parameters)j(used)f(internally)g(to)g(Magic,)h(such) +g(as)f(the)h(width)e(of)i(the)g(V)-11 b(ersatec)0 1774 +y(printer)28 b(and)h(the)f(number)g(of)g(dots)g(per)h(inch)f(on)g(the)g +(V)-11 b(ersatec)29 b(printer)-5 b(.)41 b(Y)-11 b(ou)28 +b(can)h(modify)e(most)h(of)g(these)g(to)0 1894 y(w)o(ork)c(with)f(dif)n +(ferent)g(printers.)30 b(F)o(or)24 b(details,)f(read)h(about)g(the)f(v) +n(arious)g Fb(:plot)h Fd(command)f(options)f(in)i(the)f +Fe(man)0 2014 y Fd(page.)0 2396 y Ff(10)143 b(Utility)34 +b(Commands)0 2633 y Fd(There)28 b(are)h(se)n(v)o(eral)e(additional)f +(commands)h(that)g(you)h(will)f(probably)g(\002nd)h(useful)f(once)h +(you)f(start)h(w)o(orking)0 2753 y(on)d(real)g(cells.)30 +b(The)25 b(command)900 3033 y Fb(:grid)g Fd([)p Fe(spacing)p +Fd(])900 3154 y Fb(:grid)g Fe(xSpacing)f(ySpacing)900 +3274 y Fb(:grid)h Fe(xSpacing)f(ySpacing)g(xOrigin)g(yOrigin)900 +3395 y Fb(:grid)h(off)146 3668 y Fd(will)32 b(display)f(a)i(grid)f(o)o +(v)o(er)f(your)h(layout.)53 b(Initially)-6 b(,)32 b(the)g(grid)g(has)g +(a)h(one-unit)f(spacing.)52 b(T)-8 b(yping)32 b Fb(:grid)0 +3789 y Fd(with)g(no)h(ar)n(guments)g(will)f(toggle)g(the)h(grid)g(on)g +(and)g(of)n(f.)55 b(If)34 b(a)f(single)g(numerical)f(ar)n(gument)h(is)g +(gi)n(v)o(en,)g(the)0 3909 y(grid)25 b(will)f(be)h(turned)f(on,)h(and)g +(the)f(grid)h(lines)f(will)g(be)h Fe(spacing)f Fd(units)g(apart.)31 +b(The)25 b(macro)g Fb(g)g Fd(pro)o(vides)f(a)h(short)0 +4030 y(form)34 b(for)h Fb(:grid)g Fd(and)f Fb(G)g Fd(is)h(short)e(for)i +Fb(:grid)g(2)p Fd(.)60 b(If)35 b(you)f(pro)o(vide)f(tw)o(o)h(ar)n +(guments)g(to)g Fb(:grid)p Fd(,)j(the)o(y)d(are)h(the)0 +4150 y(x-)29 b(and)g(y-spacings,)h(which)e(may)h(be)g(dif)n(ferent.)44 +b(If)29 b(you)g(pro)o(vide)f(four)h(ar)n(guments,)h(the)f(last)f(tw)o +(o)h(specify)g(a)0 4270 y(reference)f(point)e(through)g(which)g +(horizontal)g(and)h(v)o(ertical)f(grid)g(lines)g(pass;)h(the)g(def)o +(ault)f(is)g(to)h(use)f(\(0,0\))h(as)0 4391 y(the)h(grid)h(origin.)41 +b(The)29 b(command)e Fb(:grid)i(off)g Fd(al)o(w)o(ays)g(turns)f(the)g +(grid)g(of)n(f,)i(re)o(gardless)d(of)i(whether)g(or)f(not)h(is)0 +4511 y(w)o(as)22 b(pre)n(viously)e(on.)29 b(When)22 b(the)g(grid)f(is)h +(on,)g(a)g(small)f(black)g(box)h(is)f(displayed)g(to)g(mark)h(the)g +(\(0,0\))f(coordinate)0 4632 y(of)k(the)g(cell)f(you')-5 +b(re)25 b(editing.)146 4758 y(If)30 b(you)g(w)o(ant)f(to)g(create)i(a)f +(cell)g(that)f(doesn')n(t)g(\002t)h(on)f(the)h(screen,)h(you')o(ll)e +(need)h(to)f(kno)n(w)g(ho)n(w)g(to)g(change)0 4879 y(the)c(screen)g +(vie)n(w)-6 b(.)29 b(This)c(can)g(be)g(done)f(with)g(three)h(commands:) +900 5159 y Fb(:zoom)g Fe(factor)900 5280 y Fb(:\002ndbox)h +Fd([)p Fb(zoom)p Fd(])900 5400 y Fb(:view)1875 5649 y +Fd(\2269\226)p eop +%%Page: 10 10 +10 9 bop 0 -180 a Fd(September)25 b(26,)f(2001)1180 b(Magic)24 +b(T)l(utorial)f(#2:)31 b(Basic)25 b(P)o(ainting)e(and)i(Selection)146 +68 y(If)32 b Fe(factor)e Fd(is)g(gi)n(v)o(en)f(to)i(the)f(zoom)h +(command,)g(it)f(is)h(a)g(zoom-out)f(f)o(actor)-5 b(.)48 +b(F)o(or)31 b(e)o(xample,)g(the)g(command)0 189 y Fb(:zoom)25 +b(2)g Fd(will)f(change)i(the)f(vie)n(w)f(so)h(that)g(there)g(are)h +(twice)f(as)g(man)o(y)f(units)g(across)h(the)g(screen)h(as)f(there)g +(used)0 309 y(to)d(be)g(\()p Fb(Z)h Fd(is)f(a)g(macro)g(for)h(this\).) +29 b(The)22 b(ne)n(w)g(vie)n(w)f(will)h(ha)n(v)o(e)g(the)g(same)g +(center)g(as)g(the)h(old)e(one.)30 b(The)22 b(command)0 +429 y Fb(:zoom)j(.5)g Fd(will)e(increase)j(the)e(magni\002cation)g(so)h +(that)f(only)g(half)h(as)g(much)f(of)h(the)g(circuit)f(is)g(visible.) +146 550 y(The)i Fb(:\002ndbox)i Fd(command)d(is)g(used)h(to)g(change)g +(the)g(vie)n(w)f(according)h(to)g(the)f(box.)34 b(The)26 +b(command)f(alone)0 670 y(just)20 b(mo)o(v)o(es)f(the)h(vie)n(w)g +(\(without)g(changing)g(the)g(scale)h(f)o(actor\))h(so)e(that)g(the)h +(box)f(is)g(in)h(the)f(center)h(of)g(the)g(screen.)0 +790 y(If)31 b(the)g Fb(zoom)f Fd(ar)n(gument)g(is)h(gi)n(v)o(en)e(then) +h(the)h(magni\002cation)e(is)i(changed)f(too,)i(so)e(that)g(the)h(area) +g(of)g(the)g(box)0 911 y(nearly)25 b(\002lls)f(the)h(screen.)31 +b Fb(z)25 b Fd(is)g(a)g(macro)g(for)g Fb(:\002ndbox)h(zoom)f +Fd(and)g Fb(B)g Fd(is)f(a)h(macro)g(for)g Fb(:\002ndbox)p +Fd(.)146 1031 y(The)g(command)e Fb(:view)i Fd(resets)f(the)g(vie)n(w)g +(so)g(that)g(the)g(entire)h(cell)f(is)g(visible)f(in)h(the)g(windo)n(w) +-6 b(.)29 b(It)24 b(comes)g(in)0 1152 y(handy)g(if)h(you)g(get)f(lost)g +(in)g(a)i(big)e(layout.)30 b(The)24 b(macro)h Fb(v)g +Fd(is)f(equi)n(v)n(alent)f(to)i Fb(:view)p Fd(.)146 1272 +y(The)32 b(command)e Fb(:box)h Fd(prints)g(out)g(the)g(size)g(and)g +(location)g(of)g(the)g(box)g(in)g(case)h(you')-5 b(d)30 +b(lik)o(e)h(to)g(measure)0 1392 y(something)21 b(in)h(your)h(layout.)29 +b(The)23 b(macro)f Fb(b)i Fd(is)e(prede\002ned)h(to)f +Fb(:box)p Fd(.)31 b(The)22 b Fb(:box)h Fd(command)f(can)h(also)g(be)f +(used)0 1513 y(to)i(set)h(the)g(box)f(to)g(a)i(particular)e(location,)g +(height,)g(or)h(width.)30 b(See)25 b(the)g(man)f(page)h(for)g(details.) +146 1633 y(The)g(command)900 1827 y Fb(:what)146 2020 +y Fd(will)k(print)g(out)f(information)g(about)h(what')-5 +b(s)29 b(selected.)44 b(This)29 b(may)g(be)g(helpful)g(if)h(you')-5 +b(re)29 b(not)g(sure)g(what)0 2141 y(layer)c(a)g(particular)g(piece)g +(of)g(material)f(is,)h(or)f(what)h(layer)g(a)g(particular)g(label)f(is) +h(attached)g(to.)146 2261 y(If)h(you)e(for)n(get)h(what)g(a)g(macro)g +(means,)f(you)g(can)h(in)l(v)n(ok)o(e)g(the)f(command)900 +2455 y Fb(:macr)n(o)h Fd([)p Fe(c)o(har)p Fd(])146 2649 +y(This)i(command)g(will)f(print)h(out)g(the)h(long)e(command)h(that')-5 +b(s)26 b(associated)i(with)e(the)i(macro)f Fe(c)o(har)p +Fd(.)39 b(If)28 b(you)0 2769 y(omit)c Fe(c)o(har)p Fd(,)g(Magic)g(will) +g(print)g(out)g(all)h(of)g(the)f(macro)h(associations.)k(The)c(command) +900 2963 y Fb(:macr)n(o)g Fe(c)o(har)f(command)146 3156 +y Fd(W)-8 b(e)28 b(set)g(up)f Fe(c)o(har)g Fd(to)g(be)h(a)g(macro)g +(for)g Fe(command)p Fd(,)g(replacing)f(the)h(old)f Fe(c)o(har)f +Fd(macro)i(if)g(there)g(w)o(as)f(one.)40 b(If)0 3277 +y Fe(command)28 b Fd(contains)f(an)o(y)h(spaces)g(then)g(it)g(must)f +(be)h(enclosed)g(in)g(double-quotes.)39 b(T)-8 b(o)28 +b(see)h(ho)n(w)e(this)h(w)o(orks,)0 3397 y(type)19 b(the)h(command)f +Fb(:macr)n(o)h Fa(1)60 b("echo)e(You)h(just)g(typed)g(the)g(1)h(key.")p +Fd(,)19 b(then)h(type)f(the)h(1)f(k)o(e)o(y)-6 b(.)146 +3517 y(One)33 b(of)f(the)g(macros,)i(\223)p Fb(.)p Fd(\224,)g(has)e +(special)g(meaning)f(in)h(Magic.)53 b(This)31 b(macro)h(is)g(al)o(w)o +(ays)g(de\002ned)g(by)g(the)0 3638 y(system)c(to)h(be)g(the)g(last)g +(long)g(command)f(you)h(typed.)43 b(Whene)n(v)o(er)29 +b(you')-5 b(d)29 b(lik)o(e)g(to)f(repeat)i(a)g(long)e(command,)0 +3758 y(all)d(you)f(ha)n(v)o(e)g(to)h(do)f(is)h(use)f(the)h(dot)f +(macro.)0 4093 y Ff(11)143 b(What)36 b(the)f(Lay)o(ers)e(Mean)0 +4317 y Fd(The)24 b(paint)g(layers)g(a)n(v)n(ailable)f(in)h(Magic)g(are) +h(dif)n(ferent)f(from)g(those)f(that)h(you)g(may)g(be)g(used)g(to)g(in) +g(Caesar)h(and)0 4437 y(other)20 b(systems)g(because)h(the)o(y)f(don')n +(t)g(correspond)g(e)o(xactly)g(to)g(the)h(masks)f(used)g(in)g(f)o +(abrication.)29 b(W)-8 b(e)21 b(call)g(them)0 4557 y +Fe(abstr)o(act)h(layer)o(s)h Fd(because)h(the)o(y)f(correspond)g(to)g +(constructs)g(such)g(as)h(wires)g(and)f(contacts,)g(rather)h(than)g +(mask)0 4678 y(layers.)60 b(W)-8 b(e)35 b(also)f(call)h(them)f +Fe(lo)o(gs)f Fd(because)i(the)o(y)f(look)g(lik)o(e)g(sticks)g(e)o +(xcept)g(that)g(the)g(geometry)g(is)h(dra)o(wn)0 4798 +y(fully)f(\003eshed)h(instead)g(of)g(as)g(lines.)60 b(In)35 +b(Magic)g(there)g(is)f(one)h(paint)f(layer)h(for)h(each)f(kind)f(of)h +(conducting)0 4918 y(material)h(\(polysilicon,)g(ndif)n(fusion,)h +(metal1,)h(etc.\),)h(plus)c(one)h(additional)f(paint)g(layer)h(for)g +(each)h(kind)e(of)0 5039 y(transistor)21 b(\(ntransistor)l(,)g +(ptransistor)l(,)g(etc.\),)i(and,)g(\002nally)-6 b(,)21 +b(one)h(further)h(paint)e(layer)h(for)g(each)h(kind)e(of)h(contact)0 +5159 y(\(pcontact,)36 b(ndcontact,)f(m2contact,)h(etc.\))58 +b(Each)34 b(layer)h(has)e(one)h(or)g(more)g(names)g(that)f(are)i(used)e +(to)h(refer)0 5280 y(to)h(that)h(layer)g(in)f(commands.)62 +b(T)-8 b(o)36 b(\002nd)g(out)f(the)g(layers)h(a)n(v)n(ailable)f(in)h +(the)f(current)h(technology)-6 b(,)37 b(type)e(the)0 +5400 y(command)1850 5649 y(\22610\226)p eop +%%Page: 11 11 +11 10 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#2:)30 +b(Basic)25 b(P)o(ainting)f(and)h(Selection)1179 b(September)25 +b(26,)g(2001)900 84 y Fb(:lay)o(ers)146 313 y Fd(In)i(addition)f(to)g +(the)h(mask)f(layers,)h(there)g(are)g(a)h(fe)n(w)e(pseudo-layers)g +(that)h(are)g(v)n(alid)f(in)g(all)h(technologies;)0 433 +y(these)k(are)g(listed)f(in)g(T)-8 b(able)31 b(1.)48 +b(Each)31 b(Magic)f(technology)g(also)g(has)h(a)g(technology)e(manual)h +(describing)g(the)0 553 y(features)22 b(of)g(that)g(technology)-6 +b(,)20 b(such)i(as)g(design)f(rules,)h(routing)f(layers,)h(CIF)h +(styles,)f(etc.)30 b(If)22 b(you)f(ha)n(v)o(en')n(t)h(seen)0 +674 y(an)o(y)i(of)h(the)g(technology)e(manuals)h(yet,)h(this)f(is)g(a)h +(good)f(time)h(to)f(tak)o(e)h(a)g(look)f(at)h(the)f(one)h(for)g(your)g +(process.)p 1123 815 1655 4 v 1121 935 4 121 v 1173 899 +a Fb(err)n(ors)g Fd(\(design-rule)f(violations\))p 2776 +935 V 1121 1056 V 1173 1019 a Fb(labels)p 2776 1056 V +1121 1176 V 1173 1140 a(subcells)p 2776 1176 V 1121 1296 +V 1197 1260 a Fd(\(all)h(mask)f(layers\))p 2776 1296 +V 1121 1417 V 1173 1381 a Fb($)g Fd(\(all)h(mask)f(layers)h(visible)f +(under)g(cursor\))p 2776 1417 V 1123 1420 1655 4 v 914 +1687 a(T)-8 b(able)25 b(1:)30 b(Pseudo-layers)25 b(a)n(v)n(ailable)f +(in)h(all)f(technologies.)146 1924 y(If)38 b(you')-5 +b(re)37 b(used)g(to)f(designing)g(with)g(mask)g(layers)h(\(e.g.)68 +b(you')-5 b(v)o(e)36 b(been)h(reading)g(the)g(Mead-Conw)o(ay)0 +2044 y(book\),)25 b(Magic')-5 b(s)25 b(log)g(style)g(will)f(tak)o(e)i +(some)f(getting)f(used)i(to.)32 b(One)26 b(of)g(the)f(reasons)g(for)h +(logs)f(is)g(to)g(sa)n(v)o(e)h(you)0 2165 y(w)o(ork.)53 +b(In)32 b(Magic)g(you)g(don')n(t)g(dra)o(w)g(implants,)g(wells,)h(b)n +(uried)f(windo)n(ws,)h(or)f(contact)g(via)g(holes.)52 +b(Instead,)0 2285 y(you)21 b(dra)o(w)h(the)g(primary)f(conducting)g +(layers)h(and)g(paint)f(some)g(of)h(their)g(o)o(v)o(erlaps)e(with)h +(special)h(types)f(such)h(as)0 2405 y(n-transistor)27 +b(or)i(polysilicon)d(contact.)41 b(F)o(or)28 b(transistors,)g(you)f +(dra)o(w)i(only)e(the)h(actual)g(area)i(of)e(the)g(transistor)0 +2526 y(channel.)60 b(Magic)35 b(will)e(generate)j(the)e(polysilicon)f +(and)h(dif)n(fusion,)i(plus)e(an)o(y)g(necessary)h(implants,)g(when)0 +2646 y(it)30 b(creates)i(a)f(CIF)g(\002le.)49 b(F)o(or)31 +b(contacts,)g(you)g(paint)f(the)g(contact)h(layer)g(in)f(the)g(area)i +(of)f(o)o(v)o(erlap)f(between)g(the)0 2767 y(conducting)g(layers.)49 +b(Magic)30 b(will)g(generate)i(each)f(of)g(the)g(constituent)e(mask)h +(layers)h(plus)f(vias)h(and)f(b)n(uried)0 2887 y(windo)n(ws)21 +b(when)i(it)g(writes)f(the)h(CIF)h(\002le.)31 b(Figure)23 +b(1)g(sho)n(ws)e(a)j(simple)e(cell)g(dra)o(wn)h(with)f(both)g(mask)h +(layers)g(\(as)0 3007 y(in)i(Caesar\))h(and)f(with)f(logs)g(\(as)i(in)e +(Magic\).)31 b(If)26 b(you')-5 b(re)25 b(curious)f(about)h(what)g(the)f +(masks)h(will)f(look)g(lik)o(e)g(for)i(a)0 3128 y(particular)f(layout,) +f(you)g(can)h(use)g(the)f Fb(:cif)i(see)f Fd(command)f(to)g(vie)n(w)g +(the)h(mask)f(information.)146 3248 y(An)35 b(adv)n(antage)f(of)h(the)f +(logs)g(used)h(in)f(Magic)g(is)g(that)h(the)o(y)e(simplify)g(the)i +(design)f(rules.)60 b(Most)33 b(of)i(the)0 3368 y(formation)c(rules)h +(\(e.g.)53 b(contact)31 b(structure\))h(go)g(a)o(w)o(ay)-6 +b(,)33 b(since)f(Magic)g(automatically)e(generates)j(correctly-)0 +3489 y(formed)g(structures)f(when)h(it)g(writes)f(CIF)-8 +b(.)35 b(All)d(that)h(are)g(left)g(are)h(minimum)d(size)i(and)g +(spacing)f(rules,)j(and)0 3609 y(Magic')-5 b(s)25 b(abstract)g(layers)g +(result)g(in)g(fe)n(wer)h(of)g(these)f(than)g(there)h(w)o(ould)e(be)i +(otherwise.)32 b(This)24 b(helps)h(to)g(mak)o(e)0 3730 +y(Magic')-5 b(s)28 b(b)n(uilt-in)g(design)g(rule)h(check)o(er)g(v)o +(ery)g(f)o(ast)g(\(see)g(\223Magic)g(T)l(utorial)f(#6:)38 +b(Design)29 b(Rule)g(Checking\224\),)0 3850 y(and)c(is)f(one)h(of)g +(the)f(reasons)h(plo)n(wing)e(is)h(possible.)1850 5649 +y(\22611\226)p eop +%%Page: 12 12 +12 11 bop 0 -180 a Fd(September)25 b(26,)f(2001)1180 +b(Magic)24 b(T)l(utorial)f(#2:)31 b(Basic)25 b(P)o(ainting)e(and)i +(Selection)215 3935 y @beginspecial 190 @llx 28 @lly +420 @urx 764 @ury 3600 @rhi @setspecial +%%BeginDocument: ../psfigures/tut2.2.ps + +/INIT { + 72 exch div dup dup scale + div exch findfont exch scalefont /TxFont exch def + /BoxOutline exch def /#copies exch def + TxFont dup /FontBBox get exch /FontMatrix get + exch aload pop 4 index transform /bbhi exch def pop 3 -1 roll + transform /bblow exch def /bbx exch def /bbhi bbhi bblow sub def + /nChars matrix defaultmatrix 0 get abs 72 8.5 mul mul 64 div ceiling cvi def + 1 1 dtransform abs dup 1 exch div /onePix exch def + dup /resY exch def 1 exch div /iresY exch def + abs dup /resX exch def 1 exch div /iresX exch def + /bX 64 iresX mul def /bY 64 iresY mul def + /pattFont StipplePattern definefont pop + /patterns /pattFont findfont [iresX 64 mul 0 0 iresY 64 mul 0 0] makefont def + /CA nChars 1 add string def +} def + +/StipplePattern 45 dict def + +StipplePattern begin + /FontType 3 def + /FontMatrix [1 0 0 1 0 0] def + /FontBBox [0 0 1 1] def + /Encoding 256 array def + /PattName (P0) def + /tmpStr 1 string def + /NoPatt {<00>} def + + 0 1 255 { Encoding exch /NoPatt put } for + + /BuildChar { + 1 0 0 0 1 1 setcachedevice exch begin Encoding exch get load + 64 64 true [64 0 0 64 0 0] 5 -1 roll imagemask end + } def +end + +/DefPatt { + StipplePattern begin + dup 30 tmpStr cvrs PattName exch 1 exch putinterval PattName cvn dup + Encoding exch 4 -1 roll exch put exch store + end +} def + +/HEADER { 4 onePix mul add moveto show } def + +/SL { 0 1 nChars { exch dup 3 1 roll CA 3 1 roll put } for pop } def +/SC { 0 1 nChars { exch dup 3 1 roll CA 3 1 roll put } for 4 mul + colors exch 4 getinterval aload pop setcmykcolor } def + +/SP { patterns setfont 2 setlinewidth } def + +/ST { TxFont setfont onePix 2 mul setlinewidth } def + +/V { newpath moveto 0 exch rlineto stroke } def + +/H { newpath moveto 0 rlineto stroke } def + +/B { + /h exch def /w exch def + /y exch def /x exch def + + gsave + newpath x y moveto w y lineto w h lineto x h lineto closepath clip + x resX mul cvi 63 not and dup iresX mul exch + w resX mul sub abs 63 add cvi 64 idiv /w exch def + y resY mul cvi 63 not and dup iresY mul exch + h resY mul sub abs 63 add cvi 64 idiv /h exch def + /CH CA 0 w getinterval def + moveto h { CH gsave show grestore 0 bY rmoveto } repeat + grestore +} def + +/L { + gsave newpath dup bblow add 2 index bbx add exch moveto + 0 bbhi rlineto + 2 index stringwidth pop bbx abs 2 mul add 0 rlineto + 0 bbhi neg rlineto + closepath 1.0 setgray fill grestore moveto show +} def + +/BB { + /h exch def /w exch def + /y exch def /x exch def + grestore + gsave + newpath + x y moveto + w y lineto + w h lineto + x h lineto + closepath + BoxOutline 1 eq { gsave stroke grestore } if clip +} def + +/BS { + 4 copy BB exch pop exch pop exch bbhi add exch bbhi sub onePix sub L +} def + +/MSAV { /Mstat save def } def +/MRES { Mstat restore } def + + +{<000000000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0>} 0 DefPatt +{<000000000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0>} 1 DefPatt +{<00000000000000000c0c0c0c0c0c0c0c000000000000000000000000000000000000000000000000c0c0c0c0c0c0c0c000000000000000000000000000000000>} 5 DefPatt +{<00000000000000000c0c0c0c0c0c0c0c000000000000000000000000000000000000000000000000c0c0c0c0c0c0c0c000000000000000000000000000000000>} 6 DefPatt +{} 8 DefPatt +{<8383838383838383c1c1c1c1c1c1c1c1e0e0e0e0e0e0e0e0707070707070707038383838383838381c1c1c1c1c1c1c1c0e0e0e0e0e0e0e0e0707070707070707>} 9 DefPatt +{<8181818181818181c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3818181818181818118181818181818183c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c1818181818181818>} 11 DefPatt +{} 16 DefPatt +/colors [0.18 0.37 0.43 0.00 0.87 0.12 0.87 0.00 0.00 0.00 0.00 0.75 0.12 0.43 0.12 0.00 0.12 0.43 1.00 0.00 0.25 0.37 0.75 0.00 1.00 0.25 1.00 0.00 0.00 0.00 0.00 0.50 0.87 0.18 0.87 0.00 0.00 1.00 1.00 0.00 0.00 0.00 1.00 0.00 0.75 0.50 0.00 0.00 0.37 0.87 0.25 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 0.75 0.75 0.50 0.25 0.00 ] def +1 1 /Helvetica 10.0 300.000000 INIT +% ST (tutcell.cif Scale: 0.212766 \(5404X\) Size: 14 x 47 microns ) 828 3150 HEADER +SP 828 150 translate +0 SC +1532 0 0 V +894 0 0 H +1532 894 0 V +894 0 1532 H +0 0 894 1532 B +1 SC +1404 0 1596 V +894 0 1596 H +1404 894 1596 V +894 0 3000 H +0 1596 894 3000 B +5 SC +1022 191 1787 V +511 191 1787 H +1022 702 1787 V +511 191 2809 H +191 1787 702 2809 B +6 SC +1149 191 191 V +511 191 191 H +1149 702 191 V +511 191 1340 H +191 191 702 1340 B +8 SC +894 319 319 V +766 319 1915 V +383 511 574 V +319 319 511 1213 B +256 511 2170 V +319 1915 511 2681 B +255 319 319 H +255 574 319 V +63 511 574 H +511 319 574 574 B +63 511 957 H +256 574 957 V +255 319 1213 H +511 957 574 1213 B +255 319 1915 H +255 574 1915 V +63 511 2170 H +511 1915 574 2170 B +63 511 2426 H +255 574 2426 V +255 319 2681 H +511 2426 574 2681 B +9 SC +128 0 702 V +128 0 2234 V +702 0 702 H +128 702 702 V +702 0 830 H +0 702 702 830 B +766 0 2234 H +128 766 2234 V +766 0 2362 H +0 2234 766 2362 B +11 SC +192 0 319 V +192 0 2489 V +319 0 511 H +0 319 319 511 B +63 319 511 V +1213 319 957 V +63 319 2426 V +319 0 2489 H +0 2489 319 2681 B +63 574 511 V +255 319 574 H +319 319 574 574 B +255 319 957 H +511 574 957 V +447 574 1723 V +255 319 2170 H +319 957 574 2170 B +255 319 2426 H +63 574 2426 V +319 2426 574 2681 B +894 0 319 H +192 894 319 V +320 574 511 H +574 319 894 511 B +320 574 1468 H +255 894 1468 V +320 574 1723 H +574 1468 894 1723 B +320 574 2489 H +192 894 2489 V +894 0 2681 H +574 2489 894 2681 B +16 SC +128 383 383 V +128 383 1021 V +127 383 1979 V +128 383 2489 V +128 383 383 H +128 511 383 V +128 383 511 H +383 383 511 511 B +128 383 1021 H +128 511 1021 V +128 383 1149 H +383 1021 511 1149 B +128 383 1979 H +127 511 1979 V +128 383 2106 H +383 1979 511 2106 B +128 383 2489 H +128 511 2489 V +128 383 2617 H +383 2489 511 2617 B +ST gsave +% (tutcell1) 0 0 894 3000 BS +% 0 0 894 3000 BB +grestore showpage + +%%EndDocument + @endspecial 1735 3635 a @beginspecial 72 @llx 72 @lly +540 @urx 560 @ury 2880 @rhi @setspecial +%%BeginDocument: ../psfigures/tut2.1.ps +% +% PostScript prolog for output from magic plot +% Version: 1.0 +% written by Tim Edwards 4/05/00 JHU Applied Physics Laboratory +% +% supporting definitions + +/MAGICsave save def + +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/minit { /nChars matrix defaultmatrix 0 get abs 72 8.5 mul mul 64 div ceiling + cvi def 1 1 dtransform abs dup 1 exch div /onePix exch def + dup /resY exch def 1 exch div /iresY exch def + abs dup /resX exch def 1 exch div /iresX exch def + /bX 64 iresX mul def /bY 64 iresY mul def + /pattFont StipplePattern definefont pop + /patterns /pattFont findfont [iresX 64 mul 0 0 iresY 64 mul 0 0] makefont def + /ca nChars 1 add string def + } def +/StipplePattern 45 dict def +StipplePattern begin + /FontType 3 def + /FontMatrix [1 0 0 1 0 0] def + /FontBBox [0 0 1 1] def + /Encoding 256 array def + /PattName (P0) def + /tmpStr 1 string def + /NoPatt {<00>} def + 0 1 255 { Encoding exch /NoPatt put } for + /BuildChar { + 1 0 0 0 1 1 setcachedevice exch begin Encoding exch get load + 64 64 true [64 0 0 64 0 0] 5 -1 roll imagemask end } def +end +/dp { StipplePattern begin dup 30 tmpStr cvrs PattName exch 1 exch + putinterval PattName cvn dup Encoding exch 4 -1 roll exch put exch + store end } def +/sf { findfont exch scalefont setfont } bind def +/sp { patterns setfont 2 setlinewidth } def +/lb { gsave translate 0 0 moveto /just exch def gsave dup true charpath + flattenpath pathbbox grestore exch 4 -1 roll exch sub 3 1 roll sub + just 4 and 0 gt {just 8 and 0 eq {0.5 mul} if}{pop 0} ifelse exch + just 1 and 0 gt {just 2 and 0 eq {0.5 mul} if}{pop 0} ifelse exch + rmoveto show grestore } def +/sl { 0 1 nChars { exch dup 3 1 roll ca 3 1 roll put } for pop } def +/sc { setcmykcolor } bind def +/l1 { onePix setlinewidth } def +/l2 { onePix 2 mul setlinewidth } def +/l3 { onePix 3 mul setlinewidth } def +/ml { moveto lineto stroke } bind def +/vl { moveto 0 exch rlineto stroke } bind def +/hl { moveto 0 rlineto stroke } bind def +/mr { rectstroke } bind def +/mx { 4 copy rectstroke 4 -1 roll 4 -1 roll 4 copy moveto rlineto stroke + 3 -1 roll dup neg 4 1 roll add moveto rlineto stroke } bind def +/pl { gsave translate /d exch def 0 d neg moveto 0 d lineto stroke + d neg 0 moveto d 0 lineto stroke grestore } bind def +/fb {/h exch def /w exch def /y exch def /x exch def gsave newpath + x y moveto w y lineto w h lineto x h lineto closepath clip + x resX mul cvi 63 not and dup iresX mul exch + w resX mul sub abs 63 add cvi 64 idiv /w exch def + y resY mul cvi 63 not and dup iresY mul exch + h resY mul sub abs 63 add cvi 64 idiv /h exch def + /ch ca 0 w getinterval def + moveto h { ch gsave show grestore 0 bY rmoveto } repeat grestore } def + +/f1 { 1.440 /Helvetica sf } def +/f2 { 0.960 /HelveticaBold sf } def +/f3 { 0.640 /Helvetica sf } def +/col17 {0.090 0.686 0.718 0.000 sc} bind def +/col16 {0.435 0.592 0.957 0.000 sc} bind def +/col15 {0.749 0.498 0.247 0.000 sc} bind def +/col14 {0.000 0.000 0.000 255.000 sc} bind def +/col13 {0.373 0.875 0.247 0.000 sc} bind def +/col12 {0.749 0.498 0.000 0.000 sc} bind def +/col11 {0.000 0.000 1.000 0.000 sc} bind def +/col10 {0.000 1.000 1.000 0.000 sc} bind def +/col9 {0.875 0.184 0.875 0.000 sc} bind def +/col8 {0.000 0.000 0.000 127.000 sc} bind def +/col7 {1.000 0.247 1.000 0.000 sc} bind def +/col6 {0.247 0.373 0.749 0.000 sc} bind def +/col5 {0.122 0.435 1.000 0.000 sc} bind def +/col4 {0.122 0.435 0.122 0.000 sc} bind def +/col3 {0.000 0.000 0.000 192.000 sc} bind def +/col2 {0.875 0.122 0.875 0.000 sc} bind def +/col1 {0.184 0.373 0.435 0.000 sc} bind def +{<000000000000000000000000000000003333333333333333333333333333333300000000000000000000000000000000cccccccccccccccccccccccccccccccc>} 13 dp +{<00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>} 12 dp +{<010000800100008002000040020000400c0000300c000030f000000ff000000f000ff000000ff00000300c0000300c0000400200004002000080010000800100>} 11 dp +{} 10 dp +{<18181818181818183c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c18181818181818188181818181818181c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c38181818181818181>} 9 dp +{<18181818181818180c0c0c0c0c0c0c0c060606060606060603030303030303038181818181818181c0c0c0c0c0c0c0c060606060606060603030303030303030>} 8 dp +{<181818181818181830303030303030306060606060606060c0c0c0c0c0c0c0c08181818181818181030303030303030306060606060606060c0c0c0c0c0c0c0c>} 7 dp +{<07070707070707070e0e0e0e0e0e0e0e1c1c1c1c1c1c1c1c38383838383838387070707070707070e0e0e0e0e0e0e0e0c1c1c1c1c1c1c1c18383838383838383>} 6 dp +{} 5 dp +{<00000000000000000000000000000000c0c0c0c0c0c0c0c00000000000000000000000000000000000000000000000000c0c0c0c0c0c0c0c0000000000000000>} 4 dp +{<0003000300030003000c000c000c000c003000300030003000c000c000c000c003000300030003000c000c000c000c003000300030003000c000c000c000c000>} 3 dp +{} 2 dp +{} 1 dp + +/pgsave save def bop +% 0 0 offsets +72 85 translate +12.500 12.500 scale +minit +0 0 26 37 gsave rectclip +l2 +sp + +col2 +4 sl +col1 +4 sl +col9 +5 sl +l1 +4 21 16 hl +4 21 16 vl +4 21 20 hl +21 16 25 20 fb +4 25 16 vl +1 8 10 hl +4 5 10 vl +4 5 14 hl +3 9 11 vl +5 10 9 14 fb +4 9 10 vl +4 21 11 hl +4 21 11 vl +1 21 14 vl +4 21 15 hl +% 21 11 25 15 fb +4 25 11 vl +3 5 8 hl +6 5 8 vl +5 8 8 10 fb +2 8 8 vl +2 5 4 vl +3 5 6 hl +1 8 5 vl +5 4 8 6 fb +2 8 4 vl +4 5 0 hl +6 5 0 vl +1 8 4 hl +3 9 1 vl +5 0 9 4 fb +4 9 0 vl +col1 +5 sl +1 8 33 hl +4 5 33 vl +4 5 37 hl +5 33 9 37 fb +4 9 33 vl +3 5 32 hl +5 5 32 vl +5 32 8 33 fb +1 8 32 vl +1 5 29 vl +3 5 30 hl +5 29 8 30 fb +1 8 29 vl +4 5 25 hl +5 5 25 vl +1 8 29 hl +3 9 26 vl +5 25 9 29 fb +4 9 25 vl +4 21 21 hl +4 21 21 vl +4 21 25 hl +21 21 25 25 fb +4 25 21 vl +col17 +5 sl +3 5 30 hl +2 5 30 vl +3 5 32 hl +5 30 8 32 fb +2 8 30 vl +4 21 6 hl +4 21 6 vl +2 21 8 vl +4 21 10 hl +21 6 25 10 fb +4 25 6 vl +col16 +5 sl +3 5 6 hl +2 5 6 vl +3 5 8 hl +5 6 8 8 fb +2 8 6 vl +4 21 1 hl +4 21 1 vl +1 21 4 vl +4 21 5 hl +21 1 25 5 fb +4 25 1 vl +col10 +5 sl +5 0 30 hl +2 0 30 vl +5 0 32 hl +0 30 5 32 fb +2 5 30 vl +4 8 30 hl +2 8 30 vl +4 8 32 hl +8 30 12 32 fb +2 12 30 vl +4 21 26 hl +4 21 26 vl +1 21 29 vl +4 21 30 hl +21 26 25 30 fb +4 25 26 vl +5 0 6 hl +2 0 6 vl +5 0 8 hl +0 6 5 8 fb +2 5 6 vl +3 8 6 hl +2 8 6 vl +3 8 8 hl +8 6 11 8 fb +2 11 6 vl +col1 +7 sl +3 5 30 hl +2 5 30 vl +3 5 32 hl +5 30 8 32 fb +2 8 30 vl +4 21 6 hl +4 21 6 vl +2 21 8 vl +4 21 10 hl +21 6 25 10 fb +4 25 6 vl +col9 +8 sl +3 5 6 hl +2 5 6 vl +3 5 8 hl +5 6 8 8 fb +2 8 6 vl +4 21 1 hl +4 21 1 vl +1 21 4 vl +4 21 5 hl +21 1 25 5 fb +4 25 1 vl +col6 +1 sl +col7 +1 sl +col11 +7 sl +col12 +9 sl +4 5 33 hl +4 5 33 vl +4 5 37 hl +5 33 9 37 fb +4 9 33 vl +4 5 25 hl +5 5 25 vl +4 5 29 hl +3 9 26 vl +5 25 9 29 fb +4 9 25 vl +4 5 10 hl +4 5 10 vl +4 5 14 hl +3 9 11 vl +5 10 9 14 fb +4 9 10 vl +4 21 11 hl +4 21 11 vl +1 21 14 vl +4 21 15 hl +% 21 11 25 15 fb +4 25 11 vl +4 5 0 hl +6 5 0 vl +4 5 4 hl +3 9 1 vl +5 0 9 4 fb +4 9 0 vl +5 0 34 hl +3 0 34 vl +5 0 37 hl +0 34 5 37 fb +3 5 34 vl +5 9 34 hl +3 9 34 vl +5 9 37 hl +2 14 35 vl +9 34 14 37 fb +3 14 34 vl +4 21 31 hl +4 21 31 vl +2 21 33 vl +1 21 34 vl +4 21 35 hl +21 31 25 35 fb +4 25 31 vl +7 5 22 vl +4 5 25 hl +5 22 9 25 fb +7 9 22 vl +5 9 18 hl +11 5 18 vl +5 9 22 hl +5 18 14 22 fb +4 14 18 vl +4 5 14 hl +15 5 14 vl +3 9 15 vl +5 14 9 18 fb +4 9 14 vl +5 0 0 hl +3 0 0 vl +5 0 3 hl +0 0 5 3 fb +4 5 0 vl +5 9 0 hl +4 9 0 vl +5 9 3 hl +9 0 14 3 fb +3 14 0 vl +col13 +10 sl +col14 +13 sl +col14 +11 sl +col14 +col14 +l2 +5 33 4 4 mx +5 25 4 4 mx +5 10 4 4 mx +21 11 4 4 mx +5 0 4 4 mx +21 31 4 4 mr +21 26 4 4 mr +21 21 4 4 mr +21 16 4 4 mr +21 11 4 4 mr +21 6 4 4 mr +21 1 4 4 mr +grestore +f1 0 setgray +(Metal) 4 26 33 lb +(Polysilicon) 4 26 28 lb +(P-Diffusion) 4 26 23 lb +(N-Diffusion) 4 26 18 lb +(Contact) 4 26 13 lb +(P-Fet) 4 26 8 lb +(N-Fet) 4 26 3 lb +pgsave restore showpage + +MAGICsave restore +%%EndDocument + @endspecial 0 4095 a(Figure)30 b(1:)40 b(An)29 b(e)o(xample)g(of)h(ho) +n(w)f(the)g(logs)g(are)h(used.)45 b(The)30 b(\002gure)g(on)f(the)h +(left)f(sho)n(ws)f(actual)i(mask)f(layers)0 4215 y(for)24 +b(an)g(CMOS)g(in)l(v)o(erter)f(cell,)h(and)f(the)h(\002gure)g(on)g(the) +f(right)g(sho)n(ws)f(the)i(layers)g(used)f(to)g(represent)h(the)g(cell) +f(in)0 4335 y(Magic.)1850 5649 y(\22612\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut3.ps b/doc/psfiles/tut3.ps new file mode 100644 index 00000000..72265b9b --- /dev/null +++ b/doc/psfiles/tut3.ps @@ -0,0 +1,769 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tut3.dvi +%%Pages: 7 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tut3.dvi -o tut3.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut3.dvi) +@start /Fa 133[44 50 50 72 50 55 33 39 44 1[55 50 55 +83 28 1[33 28 55 50 33 44 55 44 55 50 9[100 3[55 72 23[33 +50 50 50 50 50 50 50 50 50 50 44[55 55 2[{ + TeXBase1Encoding ReEncodeFont }40 100.000003 /Times-Bold +rf /Fb 2 63 df<00000000000001C000000000000007E00000000000001FE000000000 +00007FC0000000000001FF00000000000007FC0000000000001FF00000000000007FC000 +0000000001FF0000000000000FFC0000000000003FF0000000000000FFC0000000000003 +FF0000000000000FF80000000000003FE0000000000000FF80000000000003FE00000000 +00001FF80000000000007FE0000000000001FF80000000000007FE0000000000001FF000 +00000000007FC0000000000001FF00000000000007FC0000000000001FF0000000000000 +7FC0000000000000FF00000000000000FF000000000000007FC00000000000001FF00000 +0000000007FC00000000000001FF000000000000007FC00000000000001FF00000000000 +0007FE00000000000001FF800000000000007FE00000000000001FF800000000000003FE +00000000000000FF800000000000003FE00000000000000FF800000000000003FF000000 +00000000FFC00000000000003FF00000000000000FFC00000000000001FF000000000000 +007FC00000000000001FF000000000000007FC00000000000001FF000000000000007FC0 +0000000000001FE000000000000007E000000000000001C03B3878B44C>60 +D<7000000000000000FC00000000000000FF000000000000007FC00000000000001FF000 +000000000007FC00000000000001FF000000000000007FC00000000000001FF000000000 +000007FE00000000000001FF800000000000007FE00000000000001FF800000000000003 +FE00000000000000FF800000000000003FE00000000000000FF800000000000003FF0000 +0000000000FFC00000000000003FF00000000000000FFC00000000000001FF0000000000 +00007FC00000000000001FF000000000000007FC00000000000001FF000000000000007F +C00000000000001FE00000000000001FE00000000000007FC0000000000001FF00000000 +000007FC0000000000001FF00000000000007FC0000000000001FF0000000000000FFC00 +00000000003FF0000000000000FFC0000000000003FF0000000000000FF8000000000000 +3FE0000000000000FF80000000000003FE0000000000001FF80000000000007FE0000000 +000001FF80000000000007FE0000000000001FF00000000000007FC0000000000001FF00 +000000000007FC0000000000001FF00000000000007FC0000000000000FF000000000000 +00FC0000000000000070000000000000003B3878B44C>62 D E /Fc +138[66 40 47 53 2[60 66 100 33 2[33 66 2[53 66 53 1[60 +12[80 6[113 9[86 8[40 55[66 2[{ TeXBase1Encoding ReEncodeFont }19 +119.999948 /Times-Bold rf /Fd 105[50 1[44 44 24[44 50 +50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 50 +33 44 50 44 50 44 3[33 1[33 1[72 1[94 1[72 61 55 66 1[55 +72 72 89 61 2[33 1[72 55 61 72 66 66 72 5[28 28 50 1[50 +50 50 50 50 50 50 50 1[25 33 25 2[33 33 33 3[50 31[55 +55 2[{ TeXBase1Encoding ReEncodeFont }70 100.000003 /Times-Roman +rf /Fe 133[39 44 44 66 1[50 28 39 39 1[50 50 50 1[28 +2[28 50 50 1[44 50 44 50 50 8[61 83 1[72 1[50 3[72 4[44 +23[50 50 2[25 1[25 2[33 33 40[{ TeXBase1Encoding ReEncodeFont }32 +100.000003 /Times-Italic rf /Ff 135[72 104 72 80 48 56 +64 2[72 80 1[40 2[40 80 72 48 64 80 64 1[72 9[143 2[96 +80 2[88 2[135 3[56 5[104 96 104 6[48 72 72 72 72 72 72 +72 72 72 7[48 48 4[72 35[{ TeXBase1Encoding ReEncodeFont }40 +143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 93 101 a Ff(Magic)35 b(T)-13 b(utorial)34 b(#3:)43 +b(Adv)o(anced)34 b(P)o(ainting)f(\(W)m(iring)j(and)f(Plo)o(wing\))1618 +521 y Fe(J)n(ohn)24 b(Ousterhout)1707 641 y(W)-9 b(alter)24 +b(Scott)1401 1062 y Fd(Computer)g(Science)i(Di)n(vision)1020 +1182 y(Electrical)f(Engineering)f(and)h(Computer)f(Sciences)1473 +1303 y(Uni)n(v)o(ersity)f(of)i(California)1544 1423 y(Berk)o(ele)o(y)-6 +b(,)24 b(CA)h(94720)1448 1693 y Fe(\(Updated)f(by)h(other)o(s,)f +(too.\))1053 1964 y Fd(This)g(tutorial)g(corresponds)g(to)g(Magic)h(v)o +(ersion)e(7.)0 2442 y Fc(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:) +300 2607 y Fd(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)300 2728 y(Magic)g(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)0 2893 y Fc(Commands)k(intr)n(oduced)j +(in)f(this)f(tutorial:)300 3059 y Fd(:array)-6 b(,)25 +b(:corner)l(,)g(:\002ll,)f(:\003ush,)g(:plo)n(w)-6 b(,)23 +b(:straighten,)g(:tool,)h(:wire)0 3225 y Fc(Macr)n(os)29 +b(intr)n(oduced)i(in)g(this)f(tutorial:)300 3403 y Fb(<)p +Fd(space)p Fb(>)0 4093 y Ff(1)143 b(Intr)m(oduction)0 +4317 y Fd(T)l(utorial)20 b(#2)i(sho)n(wed)e(you)h(the)h(basic)f(f)o +(acilities)g(for)h(placing)f(paint)g(and)g(labels,)h(selecting,)g(and)f +(manipulating)0 4437 y(the)j(things)f(that)h(are)h(selected.)31 +b(This)23 b(tutorial)h(describes)g(tw)o(o)g(additional)f(f)o(acilities) +g(for)i(manipulating)d(paint:)0 4557 y(wiring)39 b(and)h(plo)n(wing.)73 +b(These)40 b(commands)e(aren')n(t)j(absolutely)d(necessary)-6 +b(,)43 b(since)d(you)f(can)h(achie)n(v)o(e)f(the)0 4678 +y(same)25 b(ef)n(fect)h(with)f(the)g(simpler)f(commands)h(of)g(T)l +(utorial)f(#2;)h(ho)n(we)n(v)o(er)l(,)f(wiring)h(and)h(plo)n(wing)d +(allo)n(w)i(you)f(to)0 4798 y(perform)31 b(certain)g(kinds)f(of)h +(manipulations)d(much)i(more)h(quickly)f(than)g(you)h(could)f +(otherwise.)48 b(W)l(iring)31 b(is)0 4918 y(described)d(in)g(Section)h +(2;)h(it)e(allo)n(ws)f(you)h(to)g(place)h(wires)f(by)g(pointing)f(at)i +(the)f(ends)g(of)h(le)o(gs)e(rather)i(than)f(by)0 5039 +y(positioning)i(the)h(box,)j(and)e(also)f(pro)o(vides)g(for)h(con)l(v)o +(enient)f(contact)h(placement.)52 b(Plo)n(wing)30 b(is)i(the)g(subject) +0 5159 y(of)k(Section)h(3.)64 b(It)37 b(allo)n(ws)e(you)g(to)h +(re-arrange)i(pieces)e(of)g(your)g(circuit)g(without)f(ha)n(ving)h(to)f +(w)o(orry)i(about)0 5280 y(design-rule)26 b(violations)g(being)g +(created:)36 b(plo)n(wing)26 b(automatically)f(mo)o(v)o(es)h(things)g +(out)g(of)i(the)f(w)o(ay)g(to)g(a)n(v)n(oid)0 5400 y(trouble.)1875 +5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fd(September)25 b(26,)f(2001)671 b(Magic)25 +b(T)l(utorial)e(#3:)30 b(Adv)n(anced)24 b(P)o(ainting)g(\(W)l(iring)g +(and)h(Plo)n(wing\))0 99 y Ff(2)143 b(W)m(iring)0 345 +y Fd(The)24 b(box-and-painting)e(paradigm)i(described)g(in)g(T)l +(utorial)e(#2)i(is)g(suf)n(\002cient)f(to)h(create)h(an)o(y)e(possible) +g(layout,)0 466 y(b)n(ut)h(it')-5 b(s)24 b(relati)n(v)o(ely)g(inef)n +(\002cient)g(since)h(three)g(k)o(e)o(ystrok)o(es)f(are)h(required)g(to) +g(paint)f(each)i(ne)n(w)e(area:)32 b(tw)o(o)24 b(b)n(utton)0 +586 y(clicks)32 b(to)g(position)e(the)j(box)f(and)g(one)g(more)g(to)g +(paint)g(the)g(material.)53 b(This)32 b(section)g(describes)g(a)g(dif)n +(ferent)0 707 y(painting)23 b(mechanism)g(based)h(on)g +Fe(wir)l(es)p Fd(.)31 b(At)24 b(an)o(y)f(gi)n(v)o(en)g(time,)g(there)i +(is)f(a)g(current)h(wiring)e(material)h(and)g(wire)0 +827 y(thickness.)55 b(W)l(ith)33 b(the)g(wiring)g(interf)o(ace)h(you)f +(can)h(create)g(a)g(ne)n(w)f(area)h(of)g(material)e(with)h(a)h(single)e +(b)n(utton)0 947 y(click:)k(this)27 b(paints)g(a)h(straight-line)e(se)o +(gment)g(of)i(the)g(current)g(material)f(and)h(width)e(between)i(the)g +(end)f(of)h(the)0 1068 y(pre)n(vious)33 b(wire)h(se)o(gment)f(and)i +(the)f(cursor)g(location.)58 b(Each)35 b(additional)e(b)n(utton)g +(click)h(adds)g(an)g(additional)0 1188 y(se)o(gment.)29 +b(The)c(wiring)f(interf)o(ace)i(also)e(mak)o(es)g(it)h(easy)g(for)g +(you)f(to)h(place)g(contacts.)0 1599 y Ff(3)143 b(T)-13 +b(ools)0 1845 y Fd(Before)33 b(learning)f(about)g(wiring,)h(you')o(ll)e +(need)i(to)f(learn)g(about)g(tools.)52 b(Until)31 b(no)n(w)-6 +b(,)33 b(when)f(you')-5 b(v)o(e)31 b(pressed)0 1965 y(mouse)36 +b(b)n(uttons)f(in)h(layout)f(windo)n(ws)g(the)h(b)n(uttons)f(ha)n(v)o +(e)h(caused)h(the)f(box)g(to)g(change)g(or)h(material)f(to)g(be)0 +2086 y(painted.)e(The)26 b(truth)g(is)f(that)h(b)n(uttons)f(can)h(mean) +g(dif)n(ferent)g(things)f(at)h(dif)n(ferent)g(times.)34 +b(The)26 b(meaning)f(of)h(the)0 2206 y(mouse)d(b)n(uttons)f(depends)i +(on)f(the)h Fe(curr)l(ent)f(tool)p Fd(.)30 b(Each)24 +b(tool)f(is)g(identi\002ed)g(by)h(a)g(particular)g(cursor)f(shape)h +(and)0 2327 y(a)h(particular)g(interpretation)f(of)h(the)f(mouse)g(b)n +(uttons.)30 b(Initially)-6 b(,)23 b(the)h(current)h(tool)f(is)h(the)f +(box)h(tool;)f(when)g(the)0 2447 y(box)f(tool)g(is)h(acti)n(v)o(e)e +(the)i(cursor)g(has)g(the)f(shape)h(of)g(a)g(crosshair)-5 +b(.)30 b(T)-8 b(o)23 b(get)h(information)e(about)h(the)h(current)g +(tool,)0 2567 y(you)g(can)i(type)e(the)h(long)f(command)900 +2884 y Fa(:tool)h(inf)n(o)146 3190 y Fd(This)33 b(command)f(prints)g +(out)h(the)f(name)h(of)h(the)f(current)g(tool)f(and)h(the)g(meaning)g +(of)g(the)g(b)n(uttons.)54 b(Run)0 3310 y(Magic)24 b(on)h(the)g(cell)f +Fa(tut3a)i Fd(and)e(type)h Fa(:tool)f(inf)n(o)p Fd(.)146 +3442 y(The)h Fa(:tool)g Fd(command)f(can)h(also)f(be)h(used)g(to)f +(switch)g(tools.)30 b(T)m(ry)24 b(this)g(out)g(by)h(typing)e(the)i +(command)900 3759 y Fa(:tool)146 4065 y Fd(Magic)e(will)f(print)g(out)g +(a)i(message)e(telling)g(you)g(that)g(you')-5 b(re)24 +b(using)d(the)i(wiring)f(tool,)g(and)h(the)g(cursor)g(will)0 +4185 y(change)k(to)f(an)h(arro)n(w)g(shape.)36 b(Use)27 +b(the)f Fa(:tool)h(inf)n(o)f Fd(command)g(to)g(see)h(what)g(the)f(b)n +(uttons)f(mean)i(no)n(w)-6 b(.)35 b(Y)-11 b(ou')o(ll)0 +4305 y(be)27 b(using)f(the)g(wiring)h(tool)e(for)j(most)d(of)i(the)g +(rest)g(of)g(this)e(section.)37 b(The)26 b(macro)h(\223)g(\224)h +(\(space\))f(corresponds)f(to)0 4426 y Fa(:tool)p Fd(.)k(T)m(ry)22 +b(typing)f(the)h(space)h(k)o(e)o(y)f(a)h(fe)n(w)f(times:)28 +b(Magic)22 b(will)g(c)o(ycle)g(circularly)g(through)g(all)g(of)h(the)f +(a)n(v)n(ailable)0 4546 y(tools.)38 b(There)28 b(are)g(three)g(tools)f +(in)g(Magic)g(right)g(no)n(w:)36 b(the)27 b(box)g(tool,)h(which)f(you)g +(already)h(kno)n(w)f(about,)g(the)0 4667 y(wiring)c(tool,)g(which)g +(you')o(ll)g(learn)h(about)f(in)h(this)f(tutorial,)f(and)i(the)g +(netlist)e(tool,)h(which)g(has)h(a)g(square)g(cursor)0 +4787 y(shape)g(and)g(is)g(used)g(for)g(netlist)f(editing.)30 +b(\223T)l(utorial)23 b(#7:)29 b(Netlists)23 b(and)h(Routing\224)g(will) +f(sho)n(w)g(you)h(ho)n(w)f(to)h(use)0 4907 y(the)h(netlist)e(tool.)146 +5039 y(The)j(current)f(tool)g(af)n(fects)g(only)f(the)i(meanings)e(of)h +(the)g(mouse)g(b)n(uttons.)30 b(It)c(does)f(not)f(change)i(the)f(mean-) +0 5159 y(ings)35 b(of)i(the)e(long)h(commands)f(or)h(macros.)64 +b(This)36 b(means,)i(for)f(e)o(xample,)h(that)d(you)h(can)h(still)d +(use)i(all)g(the)0 5280 y(selection)26 b(commands)f(while)h(the)g +(wiring)g(tool)f(is)h(acti)n(v)o(e.)35 b(Switch)26 b(tools)f(to)h(the)g +(wiring)g(tool,)g(point)f(at)i(some)0 5400 y(paint)d(in)h +Fa(tut3a)p Fd(,)g(and)g(type)f(the)h Fa(s)f Fd(macro.)31 +b(A)25 b(chunk)f(gets)h(selected)f(just)g(as)h(it)g(does)f(with)g(the)h +(box)f(tool.)1875 5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#3:)30 b(Adv)n(anced)24 +b(P)o(ainting)g(\(W)l(iring)g(and)h(Plo)n(wing\))670 +b(September)25 b(26,)g(2001)0 99 y Ff(4)143 b(Basic)35 +b(W)m(iring)0 329 y Fd(There)d(are)g(three)g(basic)g(wiring)e +(commands:)43 b(selecting)31 b(the)g(wiring)g(material,)i(adding)e(a)h +(le)o(g,)g(and)g(adding)0 449 y(a)c(contact.)41 b(This)27 +b(section)g(describes)h(the)g(\002rst)g(tw)o(o)g(commands.)39 +b(At)28 b(this)f(point)g(you)g(should)g(be)h(editing)f(the)0 +569 y(cell)h Fa(tut3a)g Fd(with)f(the)h(wiring)f(tool)g(acti)n(v)o(e.) +38 b(The)28 b(\002rst)g(step)f(in)h(wiring)f(is)g(to)g(pick)h(the)g +(material)f(and)h(width)e(to)0 690 y(use)h(for)h(wires.)38 +b(This)27 b(can)h(be)f(done)g(in)g(tw)o(o)g(w)o(ays.)39 +b(The)27 b(easiest)g(w)o(ay)g(is)g(to)g(\002nd)h(a)g(piece)f(of)h +(material)f(of)g(the)0 810 y(right)f(type)h(and)g(width,)f(point)g(to)h +(it)f(with)g(the)h(cursor)l(,)g(and)g(click)g(the)g(left)g(mouse)f(b)n +(utton.)36 b(T)m(ry)26 b(this)g(in)h Fa(tut3a)0 930 y +Fd(by)g(pointing)f(to)i(the)f(label)h Fa(1)g Fd(and)f(left-clicking.)39 +b(Magic)27 b(prints)g(out)g(the)h(material)f(and)h(width)f(that)g(it)g +(chose,)0 1051 y(selects)22 b(a)h(square)g(of)f(that)g(material)g(and)h +(width)e(around)i(the)f(cursor)l(,)h(and)f(places)h(the)f(box)g(around) +h(the)f(square.)0 1171 y(T)m(ry)i(pointing)f(to)i(v)n(arious)e(places)i +(in)g Fa(tut3a)g Fd(and)g(left-clicking.)146 1295 y(Once)k(you')-5 +b(v)o(e)27 b(selected)h(the)h(wiring)e(material,)h(the)g(right)g(b)n +(utton)f(paints)g(le)o(gs)g(of)i(a)f(wire.)41 b(Left-click)28 +b(on)0 1415 y(label)d Fa(1)g Fd(to)f(select)h(the)g(red)g(material,)g +(then)g(mo)o(v)o(e)e(the)i(cursor)g(o)o(v)o(er)f(label)h +Fa(2)g Fd(and)g(right-click.)30 b(This)25 b(will)f(paint)0 +1535 y(a)j(red)g(wire)g(between)g Fa(1)g Fd(and)f Fa(2)p +Fd(.)37 b(The)27 b(ne)n(w)f(wire)h(le)o(g)f(is)h(selected)f(so)h(that)f +(you)h(can)g(modify)f(it)g(with)g(selection)0 1656 y(commands,)e(and)h +(the)g(box)g(is)g(placed)h(o)o(v)o(er)e(the)h(tip)g(of)g(the)g(le)o(g)g +(to)g(sho)n(w)f(you)h(the)g(starting)f(point)g(for)i(the)f(ne)o(xt)0 +1776 y(wire)30 b(le)o(g.)46 b(Add)30 b(more)g(le)o(gs)f(to)h(the)g +(wire)g(by)g(right-clicking)e(at)i Fa(3)g Fd(and)g(then)g +Fa(4)p Fd(.)47 b(Use)30 b(the)g(mouse)f(b)n(uttons)f(to)0 +1897 y(paint)c(another)h(wire)g(in)f(blue)h(from)f Fa(5)h +Fd(to)f Fa(6)h Fd(to)g Fa(7)p Fd(.)146 2020 y(Each)34 +b(le)o(g)f(of)h(a)g(wire)f(must)g(be)h(either)f(horizontal)g(or)g(v)o +(ertical.)57 b(If)34 b(you)f(mo)o(v)o(e)f(the)h(cursor)h(diagonally)-6 +b(,)0 2140 y(Magic)28 b(will)f(still)g(paint)h(a)g(horizontal)g(or)g(v) +o(ertical)g(line)f(\(whiche)n(v)o(er)h(results)f(in)h(the)g(longest)f +(ne)n(w)h(wire)h(le)o(g\).)0 2261 y(T)-8 b(o)28 b(see)h(ho)n(w)f(this)g +(w)o(orks,)h(left-click)f(on)h Fa(8)f Fd(in)g Fa(tut3a)p +Fd(,)i(then)f(right-click)e(on)i Fa(9)p Fd(.)42 b(Y)-11 +b(ou')o(ll)28 b(get)g(a)h(horizontal)f(le)o(g.)0 2381 +y(No)n(w)j(undo)h(the)f(ne)n(w)h(le)o(g)f(and)h(right-click)f(on)h +Fa(10)p Fd(.)52 b(This)31 b(time)g(you')o(ll)g(get)h(a)g(v)o(ertical)g +(le)o(g.)51 b(Y)-11 b(ou)32 b(can)g(force)0 2501 y(Magic)24 +b(to)h(paint)f(the)h(ne)o(xt)f(le)o(g)g(in)g(a)h(particular)g +(direction)f(with)g(the)h(commands)900 2754 y Fa(:wir)n(e)g(horizontal) +900 2874 y(:wir)n(e)g(v)o(ertical)146 3123 y Fd(T)m(ry)f(out)g(this)f +(feature)i(by)f(left-clicking)g(on)g Fa(8)g Fd(in)g Fa(tut3a)p +Fd(,)h(mo)o(ving)d(the)i(cursor)h(o)o(v)o(er)e Fa(10)p +Fd(,)h(and)g(typing)g Fa(:wir)n(e)0 3244 y(ho)37 b Fd(\(abbre)n +(viations)e(w)o(ork)h(for)h Fa(:wir)n(e)g Fd(command)f(options)f(just)g +(as)i(the)o(y)e(do)i(else)n(where)f(in)g(Magic\).)66 +b(This)0 3364 y(command)24 b(will)g(generate)h(a)g(short)f(horizontal)g +(le)o(g)g(instead)h(of)f(a)i(longer)e(v)o(ertical)g(one.)0 +3723 y Ff(5)143 b(Contacts)0 3952 y Fd(When)23 b(the)g(wiring)g(tool)f +(is)h(acti)n(v)o(e,)f(the)i(middle)e(mouse)g(b)n(utton)g(places)h +(contacts.)30 b(Undo)23 b(all)g(of)g(your)g(changes)0 +4073 y(to)g Fa(tut3a)g Fd(by)g(typing)e(the)i(command)f +Fa(:\003ush)i Fd(and)f(answering)f Fa(y)o(es)h Fd(to)g(the)f(question)g +(Magic)g(asks.)30 b(This)22 b(thro)n(ws)0 4193 y(a)o(w)o(ay)27 +b(all)h(of)g(the)f(changes)h(made)f(to)g(the)h(cell)f(and)h(re-loads)g +(it)f(from)g(disk.)38 b(Dra)o(w)28 b(a)g(red)g(wire)g(le)o(g)f(from)g +Fa(1)g Fd(to)0 4314 y Fa(2)p Fd(.)47 b(No)n(w)30 b(mo)o(v)o(e)e(the)i +(cursor)h(o)o(v)o(er)e(the)h(blue)g(area)h(and)g(click)f(the)g(middle)f +(mouse)g(b)n(utton.)46 b(This)30 b(has)g(se)n(v)o(eral)0 +4434 y(ef)n(fects.)g(It)24 b(places)f(a)g(contact)h(at)f(the)g(end)g +(of)h(the)f(current)g(wire)h(le)o(g,)e(selects)h(the)g(contact,)h(and)f +(mo)o(v)o(es)e(the)j(box)0 4554 y(o)o(v)o(er)i(the)i(selection.)37 +b(In)27 b(addition,)g(it)g(changes)g(the)g(wiring)f(material)h(and)g +(thickness)g(to)g(match)f(the)i(material)0 4675 y(you)22 +b(middle-click)o(ed.)29 b(Mo)o(v)o(e)20 b(the)j(cursor)f(o)o(v)o(er)g +Fa(3)g Fd(and)g(right-click)g(to)g(paint)f(a)i(blue)f(le)o(g,)g(then)g +(mak)o(e)h(a)f(contact)0 4795 y(to)i(purple)h(by)f(middle-clicking)f(o) +o(v)o(er)h(the)h(purple)f(material.)31 b(Continue)24 +b(by)g(dra)o(wing)g(a)h(purple)g(le)o(g)f(to)g Fa(4)p +Fd(.)146 4918 y(Once)33 b(you')-5 b(v)o(e)32 b(dra)o(wn)f(the)i(purple) +e(le)o(g)h(to)g Fa(4)p Fd(,)i(mo)o(v)o(e)d(the)h(cursor)g(o)o(v)o(er)g +(red)g(material)g(and)g(middle-click.)0 5039 y(This)i(time,)i(Magic)f +(prints)f(an)h(error)g(message)f(and)h(treats)g(the)f(click)h(just)f +(lik)o(e)g(a)h(left-click.)60 b(Magic)35 b(only)0 5159 +y(kno)n(ws)c(ho)n(w)g(to)g(mak)o(e)h(contacts)g(between)g(certain)g +(combinations)e(of)i(layers,)h(which)f(are)h(speci\002ed)f(in)f(the)0 +5280 y(technology)24 b(\002le)h(\(see)g(\223Magic)g(Maintainer')-5 +b(s)24 b(Manual)g(#2:)31 b(The)25 b(T)-7 b(echnology)23 +b(File\224\).)32 b(F)o(or)25 b(this)f(technology)-6 b(,)0 +5400 y(Magic)24 b(doesn')n(t)h(kno)n(w)f(ho)n(w)g(to)g(mak)o(e)h +(contacts)f(directly)g(between)h(purple)g(and)f(red.)1875 +5649 y(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fd(September)25 b(26,)f(2001)671 b(Magic)25 +b(T)l(utorial)e(#3:)30 b(Adv)n(anced)24 b(P)o(ainting)g(\(W)l(iring)g +(and)h(Plo)n(wing\))0 99 y Ff(6)143 b(W)m(iring)36 b(and)f(the)g(Box)0 +322 y Fd(In)29 b(the)g(e)o(xamples)f(so)h(f)o(ar)l(,)h(each)g(ne)n(w)f +(wire)g(le)o(g)f(appeared)i(to)f(be)g(dra)o(wn)f(from)h(the)g(end)g(of) +g(the)g(pre)n(vious)f(le)o(g)0 443 y(to)k(the)g(cursor)g(position.)51 +b(In)32 b(f)o(act,)i(ho)n(we)n(v)o(er)l(,)e(the)g(ne)n(w)g(material)g +(w)o(as)g(dra)o(wn)g(from)f(the)h Fe(box)g Fd(to)g(the)g(cursor)0 +563 y(position.)c(Magic)23 b(automatically)f(repositions)f(the)i(box)g +(on)g(each)h(b)n(utton)e(click)h(to)f(help)h(set)g(things)f(up)h(for)g +(the)0 683 y(ne)o(xt)g(le)o(g.)30 b(Using)23 b(the)h(box)f(as)h(the)g +(starting)f(point)g(for)h(wire)h(le)o(gs)e(mak)o(es)g(it)h(easy)g(to)f +(start)h(wires)g(in)g(places)g(that)0 804 y(don')n(t)h(already)h(ha)n +(v)o(e)f(material)f(of)i(the)f(right)f(type)h(and)h(width.)31 +b(Suppose)25 b(that)g(you)g(w)o(ant)g(to)g(start)f(a)i(ne)n(w)f(wire)0 +924 y(in)h(the)h(middle)e(of)i(an)g(empty)f(area.)37 +b(Y)-11 b(ou)26 b(can')n(t)h(left-click)g(to)f(get)h(the)f(wire)h +(started)f(there.)37 b(Instead,)27 b(you)f(can)0 1045 +y(left-click)d(some)f(other)h(place)h(where)f(there')-5 +b(s)23 b(the)g(right)f(material)h(for)g(the)g(wire,)h(type)f(the)g +(space)g(bar)h(twice)e(to)0 1165 y(get)i(back)h(the)f(box)g(tool,)f(mo) +o(v)o(e)g(the)h(box)g(where)h(you')-5 b(d)24 b(lik)o(e)g(the)g(wire)h +(to)e(start,)h(hit)g(the)g(space)h(bar)g(once)f(more)0 +1285 y(to)g(get)h(back)g(the)g(wiring)f(tool,)g(and)g(then)h +(right-click)f(to)g(paint)g(the)h(wire.)31 b(T)m(ry)24 +b(this)g(out)g(on)h Fa(tut3a)p Fd(.)146 1406 y(When)f(you)g(\002rst)g +(start)f(wiring,)g(you)h(may)f(not)h(be)g(able)g(to)f(\002nd)h(the)g +(right)f(kind)g(of)h(material)g(an)o(ywhere)f(on)0 1526 +y(the)i(screen.)31 b(When)25 b(this)f(happens,)g(you)g(can)h(select)g +(the)g(wiring)f(material)g(and)h(width)f(with)g(the)g(command)900 +1733 y Fa(:wir)n(e)h(type)h Fe(layer)f(width)146 1940 +y Fd(Then)f(mo)o(v)o(e)f(the)g(box)h(where)g(you')-5 +b(d)24 b(lik)o(e)f(the)h(wire)g(to)g(start,)f(switch)g(to)h(the)g +(wiring)f(tool,)g(and)h(right-click)0 2060 y(to)g(add)h(le)o(gs.)0 +2397 y Ff(7)143 b(W)m(iring)36 b(and)f(the)g(Selection)0 +2620 y Fd(Each)26 b(time)f(you)g(paint)g(a)h(ne)n(w)g(wire)g(le)o(g)f +(or)h(contact)f(using)g(the)g(wiring)g(commands,)g(Magic)g(selects)h +(the)g(ne)n(w)0 2741 y(material)33 b(just)g(as)g(if)h(you)f(had)h +(placed)f(the)h(cursor)f(o)o(v)o(er)g(it)g(and)h(typed)f +Fa(s)p Fd(.)57 b(This)33 b(mak)o(es)g(it)g(easy)h(for)f(you)g(to)0 +2861 y(adjust)c(its)g(position)f(if)i(you)f(didn')n(t)g(get)h(it)f +(right)g(initially)-6 b(.)44 b(The)30 b Fa(:str)n(etch)h +Fd(command)e(is)g(particularly)h(useful)0 2982 y(for)f(this.)41 +b(In)28 b Fa(tut3a)p Fd(,)i(paint)e(a)g(wire)h(le)o(g)f(in)g(blue)g +(from)g Fa(5)h Fd(to)f Fa(6)g Fd(\(use)h Fa(:\003ush)g +Fd(to)g(reset)f(the)h(cell)f(if)g(you')-5 b(v)o(e)28 +b(made)0 3102 y(a)f(lot)e(of)i(changes\).)35 b(No)n(w)26 +b(type)g Fa(R)h Fd(tw)o(o)e(or)i(three)g(times)e(to)h(stretch)g(the)g +(le)o(g)g(o)o(v)o(er)f(to)h(the)h(right.)34 b(Middle-click)0 +3222 y(o)o(v)o(er)24 b(purple)g(material,)h(then)f(use)h +Fa(W)f Fd(to)h(stretch)f(the)h(contact)g(do)n(wnw)o(ard.)146 +3343 y(It')-5 b(s)31 b(often)g(hard)h(to)f(position)e(the)j(cursor)f +(so)g(that)g(a)h(wire)f(le)o(g)g(comes)g(out)g(right)f(the)i(\002rst)f +(time,)h(b)n(ut)f(it')-5 b(s)0 3463 y(usually)30 b(easy)g(to)h(tell)f +(whether)g(the)h(le)o(g)f(is)g(right)g(once)h(it')-5 +b(s)29 b(painted.)48 b(If)31 b(it')-5 b(s)30 b(wrong,)h(then)g(you)f +(can)h(use)f(the)0 3583 y(stretching)24 b(commands)f(to)i(shift)f(it)g +(o)o(v)o(er)g(one)h(unit)f(at)h(a)g(time)f(until)f(it')-5 +b(s)24 b(correct.)0 3920 y Ff(8)143 b(Bundles)34 b(of)i(W)m(ir)m(es)0 +4144 y Fd(Magic)e(pro)o(vides)g(tw)o(o)g(additional)g(commands)f(that)i +(are)g(useful)g(for)g(running)f Fe(b)n(undles)g Fd(of)h(parallel)f +(wires.)0 4264 y(The)25 b(commands)e(are:)900 4471 y +Fa(\002ll)i Fe(dir)l(ection)f Fd([)p Fe(layer)o(s)p Fd(])900 +4591 y Fa(cor)o(ner)i Fe(dir)l(ection1)d(dir)l(ection2)h +Fd([)p Fe(layer)o(s)p Fd(])146 4798 y(T)-8 b(o)31 b(see)f(ho)n(w)g(the) +o(y)g(w)o(ork,)h(load)f(the)h(cell)f Fa(tut3b)p Fd(.)49 +b(The)30 b Fa(:\002ll)h Fd(comand)f(e)o(xtends)f(a)i(whole)f(b)n(unch)g +(of)h(paint)0 4918 y(in)g(a)i(gi)n(v)o(en)d(direction.)51 +b(It)32 b(\002nds)f(all)h(paint)f(touching)g(one)g(side)h(of)g(the)f +(box)h(and)g(e)o(xtends)e(that)i(paint)f(to)g(the)0 5039 +y(opposite)26 b(side)g(of)i(the)e(box.)37 b(F)o(or)27 +b(e)o(xample,)g Fa(:\002ll)g(left)h Fd(will)e(look)g(underneath)h(the)g +(right)f(edge)h(of)g(the)g(box)g(for)0 5159 y(paint,)33 +b(and)f(will)f(e)o(xtend)g(that)g(paint)h(to)f(the)h(left)g(side)f(of)h +(the)g(box.)52 b(The)32 b(ef)n(fect)g(is)f(just)g(as)h(if)g(all)g(the)g +(colors)0 5280 y(visible)c(underneath)g(that)h(edge)g(of)f(the)h(box)f +(constituted)g(a)h(paint)f(brush;)i(Magic)e(sweeps)h(the)g(brush)f +(across)0 5400 y(the)d(box)f(in)g(the)h(gi)n(v)o(en)e(direction.)30 +b(Place)c(the)f(box)f(o)o(v)o(er)g(the)h(label)f(\223Fill)h(here\224)g +(in)g Fa(tut3b)h Fd(and)e(type)h Fa(:\002ll)g(left)p +Fd(.)1875 5649 y(\2264\226)p eop +%%Page: 5 5 +5 4 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#3:)30 b(Adv)n(anced)24 +b(P)o(ainting)g(\(W)l(iring)g(and)h(Plo)n(wing\))670 +b(September)25 b(26,)g(2001)146 69 y(The)e Fa(:cor)o(ner)h +Fd(command)e(is)h(similar)e(to)i Fa(:\002ll)g Fd(e)o(xcept)g(that)f(it) +h(generates)g(L-shaped)g(wires)f(that)h(follo)n(w)f(tw)o(o)0 +189 y(sides)28 b(of)h(the)f(box,)i(tra)n(v)o(elling)d(\002rst)i(in)f +Fe(dir)l(ection1)g Fd(and)g(then)h(in)f Fe(dir)l(ection2)p +Fd(.)41 b(Place)30 b(the)f(box)f(o)o(v)o(er)g(the)g(label)0 +309 y(\223Corner)e(here\224)f(in)g Fa(tut3b)h Fd(and)e(type)h +Fa(:cor)o(ner)h(right)f(up)p Fd(.)146 433 y(In)e(both)e +Fa(:\002ll)h Fd(and)g Fa(:cor)o(ner)p Fd(,)i(if)e Fe(layer)o(s)g +Fd(isn')n(t)g(speci\002ed)g(then)g(all)g(layers)g(are)h(\002lled.)30 +b(If)22 b Fe(layer)o(s)g Fd(is)g(gi)n(v)o(en)e(then)0 +553 y(only)k(those)g(layers)h(are)h(painted.)k(Experiment)23 +b(on)i Fa(tut3b)h Fd(with)e(the)h Fa(:\002ll)f Fd(and)h +Fa(:cor)o(ner)h Fd(commands.)146 676 y(When)21 b(you')-5 +b(re)21 b(painting)f(b)n(undles)g(of)g(wires,)i(it)e(w)o(ould)g(be)h +(nice)g(if)g(there)g(were)h(a)f(con)l(v)o(enient)e(w)o(ay)i(to)g(place) +0 797 y(contacts)g(across)h(the)f(whole)g(b)n(undle)g(in)g(order)h(to)f +(switch)g(to)g(a)h(dif)n(ferent)f(layer)-5 b(.)30 b(There')-5 +b(s)21 b(no)g(single)g(command)0 917 y(to)26 b(do)g(this,)g(b)n(ut)g +(you)h(can)g(place)f(one)h(contact)f(by)h(hand)f(and)g(then)h(use)f +(the)h Fa(:array)f Fd(command)g(to)g(replicate)h(a)0 +1037 y(single)22 b(contact)i(across)f(the)g(whole)g(b)n(undle.)30 +b(Load)23 b(the)g(cell)g Fa(tut3c)p Fd(.)31 b(This)23 +b(contains)f(a)i(b)n(undle)f(of)g(wires)g(with)g(a)0 +1158 y(single)f(contact)h(already)g(painted)f(by)g(hand)h(on)g(the)f +(bottom)g(wire.)30 b(T)-8 b(ype)22 b Fa(s)h Fd(with)f(the)h(cursor)g(o) +o(v)o(er)f(the)g(contact,)0 1278 y(and)30 b(type)g Fa(S)h +Fd(with)f(the)g(cursor)g(o)o(v)o(er)g(the)g(stub)f(of)i(purple)f +(wiring)f(material)h(ne)o(xt)g(to)f(it.)47 b(No)n(w)30 +b(place)g(the)h(box)0 1399 y(o)o(v)o(er)i(the)h(label)f(\223)-8 +b(Array\224)35 b(and)f(type)f(the)h(command)f Fa(:array)h(1)g(10)p +Fd(.)57 b(This)33 b(will)g(cop)o(y)h(the)f(selected)h(contact)0 +1519 y(across)25 b(the)g(whole)f(b)n(undle.)146 1642 +y(The)h(syntax)f(of)h(the)g Fa(:array)g Fd(command)f(is)900 +1893 y Fa(:array)h Fe(xsize)g(ysize)146 2141 y Fd(This)34 +b(command)f(mak)o(es)h(the)g(selection)g(into)g(an)g(array)h(of)g +(identical)e(elements.)59 b Fe(Xsize)33 b Fd(speci\002es)i(ho)n(w)0 +2262 y(man)o(y)d(total)g(instances)g(there)h(should)e(be)i(in)f(the)h +(x-direction)f(when)h(the)f(command)g(is)g(\002nished)h(and)f +Fe(ysize)0 2382 y Fd(speci\002es)27 b(ho)n(w)g(man)o(y)f(total)g +(instances)g(there)i(should)e(be)h(in)g(the)g(y-direction.)36 +b(In)28 b(the)f Fa(tut3c)h Fd(e)o(xample,)e Fa(xsize)0 +2502 y Fd(w)o(as)c(one,)g(so)f(no)g(additional)g(copies)g(were)h +(created)g(in)g(that)f(direction;)g Fa(ysize)h Fd(w)o(as)g(10,)f(so)h +(9)f(additional)f(copies)0 2623 y(were)26 b(created.)33 +b(The)25 b(box)g(is)g(used)g(to)g(determine)f(ho)n(w)h(f)o(ar)h(apart)f +(the)g(elements)g(should)f(be:)31 b(the)26 b(width)e(of)h(the)0 +2743 y(box)k(determines)g(the)g(x-spacing)g(and)g(the)g(height)g +(determines)g(the)g(y-spacing.)44 b(The)29 b(ne)n(w)g(material)g(al)o +(w)o(ays)0 2864 y(appears)c(abo)o(v)o(e)f(and)h(to)f(the)h(right)f(of)h +(the)f(original)g(cop)o(y)-6 b(.)146 2987 y(In)29 b Fa(tut3c)p +Fd(,)h(use)e Fa(:cor)o(ner)h Fd(to)f(e)o(xtend)g(the)g(purple)g(wires)g +(and)h(turn)e(them)h(up.)41 b(Then)28 b(paint)g(a)h(contact)f(back)0 +3107 y(to)d(blue)g(on)g(the)h(leftmost)e(wire,)i(add)f(a)h(stub)e(of)i +(blue)f(paint)g(abo)o(v)o(e)f(it,)h(and)h(use)f Fa(:array)h +Fd(to)f(cop)o(y)g(them)g(across)0 3228 y(the)g(top)f(of)h(the)f(b)n +(undle.)30 b(Finally)-6 b(,)24 b(use)h Fa(:\002ll)g Fd(again)f(to)g(e)o +(xtend)g(the)h(blue)f(b)n(undle)g(f)o(arther)i(up.)0 +3585 y Ff(9)143 b(Plo)o(wing)0 3815 y Fd(Magic)28 b(contains)f(a)i(f)o +(acility)f(called)g Fe(plowing)f Fd(that)h(you)g(can)h(use)f(to)g +(stretch)g(and)g(compact)g(cells.)41 b(The)28 b(basic)0 +3935 y(plo)n(wing)23 b(command)h(has)h(the)f(syntax)900 +4186 y Fa(:plo)o(w)h Fe(dir)l(ection)f Fd([)p Fe(layer)o(s)p +Fd(])146 4434 y(where)30 b Fe(dir)l(ection)d Fd(is)i(a)g(Manhattan)f +(direction)g(lik)o(e)g Fa(left)h Fd(and)g Fe(layer)o(s)f +Fd(is)g(an)h(optional,)f(comma-separated)0 4554 y(list)d(of)i(mask)f +(layers.)35 b(The)26 b(plo)n(w)g(command)f(treats)h(one)h(side)e(of)i +(the)f(box)g(as)g(if)h(it)f(were)h(a)f(plo)n(w)-6 b(,)25 +b(and)i(sho)o(v)o(es)0 4675 y(the)d(plo)n(w)e(o)o(v)o(er)h(to)g(the)h +(other)g(side)f(of)h(the)f(box.)30 b(F)o(or)24 b(e)o(xample,)f +Fa(:plo)o(w)h(up)g Fd(treats)g(the)g(bottom)e(side)h(of)h(the)g(box)0 +4795 y(as)h(a)g(plo)n(w)-6 b(,)23 b(and)i(mo)o(v)o(es)e(the)i(plo)n(w)e +(to)i(the)f(top)h(of)f(the)h(box.)146 4918 y(As)e(the)g(plo)n(w)f(mo)o +(v)o(es,)g(e)n(v)o(ery)h(edge)g(in)g(its)f(path)h(is)g(pushed)g(ahead)g +(of)h(it)e(\(if)i Fe(layer)o(s)f Fd(is)f(speci\002ed,)i(then)f(only)0 +5039 y(edges)i(on)g(those)g(layers)g(are)h(mo)o(v)o(ed\).)31 +b(Each)26 b(edge)f(that)g(is)g(pushed)f(by)h(the)h(plo)n(w)e(pushes)g +(other)h(edges)h(ahead)0 5159 y(of)c(it)g(in)g(a)h(w)o(ay)f(that)g +(preserv)o(es)g(design)g(rules,)g(connecti)n(vity)-6 +b(,)20 b(and)j(transistor)e(and)h(contact)g(sizes.)30 +b(This)21 b(means)0 5280 y(that)32 b(material)g(ahead)g(of)h(the)f(plo) +n(w)f(gets)h(compacted)f(do)n(wn)h(to)f(the)i(minimum)c(spacing)j +(permitted)f(by)h(the)0 5400 y(design)24 b(rules,)h(and)f(material)h +(that)f(crossed)h(the)f(plo)n(w')-5 b(s)23 b(original)h(position)f +(gets)i(stretched)f(behind)g(the)h(plo)n(w)-6 b(.)1875 +5649 y(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Fd(September)25 b(26,)f(2001)671 b(Magic)25 +b(T)l(utorial)e(#3:)30 b(Adv)n(anced)24 b(P)o(ainting)g(\(W)l(iring)g +(and)h(Plo)n(wing\))146 68 y(Y)-11 b(ou)28 b(can)h(compact)f(a)g(cell)g +(by)g(placing)g(a)g(lar)n(ge)h(plo)n(w)e(of)n(f)h(to)f(one)h(side)g(of) +g(the)g(cell)h(and)f(plo)n(wing)e(across)0 188 y(the)g(whole)f(cell.)33 +b(Y)-11 b(ou)26 b(can)g(open)f(up)h(space)g(in)f(the)h(middle)e(of)i(a) +g(cell)g(by)f(dragging)g(a)h(small)f(plo)n(w)f(across)i(the)0 +309 y(area)g(where)f(you)f(w)o(ant)h(more)g(space.)146 +434 y(T)-8 b(o)30 b(try)f(out)g(plo)n(wing,)g(edit)g(the)g(cell)h +Fa(tut3d)p Fd(,)i(place)d(the)h(box)f(o)o(v)o(er)g(the)g(rectangle)h +(that')-5 b(s)28 b(labelled)h(\223Plo)n(w)0 555 y(here\224,)i(and)e +(try)f(plo)n(wing)g(in)g(v)n(arious)g(directions.)42 +b(Also,)30 b(try)e(plo)n(wing)f(only)i(certain)g(layers.)43 +b(F)o(or)29 b(e)o(xample,)0 675 y(with)24 b(the)h(box)f(o)o(v)o(er)g +(the)h(\223Plo)n(w)f(here\224)i(label,)e(try)900 946 +y Fa(:plo)o(w)h(right)g(metal2)146 1212 y Fd(Nothing)g(happens.)34 +b(This)25 b(is)h(because)g(there)g(are)h(no)f(metal2)f +Fe(edg)o(es)h Fd(in)f(the)h(path)g(of)g(the)g(plo)n(w)-6 +b(.)32 b(If)27 b(instead)0 1332 y(you)d(had)h(typed)900 +1603 y Fa(:plo)o(w)g(right)g(metal1)146 1868 y Fd(only)f(the)h(metal)f +(w)o(ould)g(ha)n(v)o(e)h(been)g(plo)n(wed)e(to)i(the)g(right.)146 +1994 y(In)j(addition)e(to)h(plo)n(wing)f(with)h(the)g(box,)h(you)f(can) +h(plo)n(w)e(the)i(selection.)38 b(The)28 b(command)e(to)h(do)h(this)e +(has)0 2114 y(the)f(follo)n(wing)e(syntax:)900 2385 y +Fa(:plo)o(w)i(selection)g Fd([)p Fe(dir)l(ection)f Fd([)p +Fe(distance)p Fd(]])146 2651 y(This)i(is)g(v)o(ery)g(similar)f(to)h +(the)g Fa(:str)n(etch)i Fd(command:)k(it)26 b(picks)g(up)g(the)g +(selection)f(and)i(the)f(box)g(and)g(mo)o(v)o(es)0 2771 +y(both)21 b(so)g(that)g(the)h(lo)n(wer)n(-left)f(corner)h(of)f(the)h +(box)f(is)g(at)h(the)f(cursor)h(location.)29 b(Unlik)o(e)20 +b(the)i Fa(:str)n(etch)h Fd(command,)0 2891 y(though,)h +Fa(:plo)o(w)g(selection)i Fd(insures)e(that)g(design)g(rule)h +(correctness)g(and)g(connecti)n(vity)e(are)i(preserv)o(ed.)146 +3017 y(Load)36 b(the)f(cell)h Fa(tut3e)h Fd(and)e(use)h +Fa(a)f Fd(to)h(select)f(the)h(area)g(underneath)g(the)f(label)h(that)f +(says)g(\223select)h(me\224.)0 3138 y(Then)31 b(point)g(with)g(the)g +(cursor)h(to)f(the)g(point)g(labelled)g(\223point)g(here\224)h(and)g +(type)f Fa(:plo)o(w)h(selection)p Fd(.)51 b(Practice)0 +3258 y(selecting)35 b(things)f(and)h(plo)n(wing)f(them.)62 +b(Lik)o(e)35 b(the)g Fa(:str)n(etch)i Fd(command,)g(there)f(is)f(also)g +(a)h(longer)f(form)g(of)0 3378 y Fa(:plo)o(w)28 b(selection)p +Fd(.)40 b(F)o(or)27 b(e)o(xample,)h Fa(:plo)o(w)g(selection)g(do)o(wn)g +(5)g Fd(will)e(plo)n(w)h(the)h(selection)f(and)g(the)h(box)f(do)n(wn)0 +3499 y(10)e(units.)146 3624 y(Selecting)k(a)g(cell)g(and)g(plo)n(wing)e +(it)h(is)h(a)g(good)f(w)o(ay)h(to)g(mo)o(v)o(e)e(the)i(cell.)42 +b(Load)29 b Fa(tut3f)h Fd(and)f(select)f(the)h(cell)0 +3745 y Fa(tut3e)p Fd(.)58 b(Point)34 b(to)f(the)h(label)f(\223point)g +(here\224)i(and)e(plo)n(w)g(the)g(selection)g(with)g +Fa(:plo)o(w)h(selection)p Fd(.)58 b(Notice)34 b(that)0 +3865 y(all)f(connections)f(to)h(the)g(cell)g(ha)n(v)o(e)g(remained)g +(attached.)56 b(The)33 b(cell)g(you)g(select)g(must)f(be)i(in)e(the)h +(edit)g(cell,)0 3986 y(ho)n(we)n(v)o(er)-5 b(.)146 4111 +y(The)31 b(plo)n(wing)e(operation)h(is)g(implemented)f(in)i(a)g(w)o(ay) +g(that)f(tries)g(to)h(k)o(eep)f(your)h(design)f(as)h(compact)f(as)0 +4232 y(possible.)f(T)-8 b(o)24 b(do)h(this,)e(it)h(inserts)f(jogs)h(in) +g(wires)g(around)g(the)h(plo)n(w)-6 b(.)29 b(In)24 b(man)o(y)f(cases,)i +(though,)e(the)i(additional)0 4352 y(jogs)h(are)i(more)e(trouble)h +(than)f(the)o(y')-5 b(re)27 b(w)o(orth.)36 b(T)-8 b(o)27 +b(reduce)h(the)e(number)h(of)g(jogs)f(inserted)g(by)h(plo)n(wing,)e +(type)0 4472 y(the)g(command)900 4743 y Fa(:plo)o(w)g(nojogs)146 +5009 y Fd(From)37 b(no)n(w)f(on,)k(Magic)d(will)f(insert)g(as)h(fe)n(w) +g(jogs)g(as)g(possible)e(when)i(plo)n(wing,)h(e)n(v)o(en)e(if)h(this)f +(means)0 5129 y(mo)o(ving)23 b(more)i(material.)30 b(Y)-11 +b(ou)24 b(can)h(re-enable)h(jog)e(insertion)g(with)g(the)g(command)900 +5400 y Fa(:plo)o(w)h(jogs)1875 5649 y Fd(\2266\226)p +eop +%%Page: 7 7 +7 6 bop 0 -180 a Fd(Magic)24 b(T)l(utorial)g(#3:)30 b(Adv)n(anced)24 +b(P)o(ainting)g(\(W)l(iring)g(and)h(Plo)n(wing\))670 +b(September)25 b(26,)g(2001)146 69 y(Load)g(the)g(cell)f +Fa(tut3d)i Fd(again)e(and)h(try)g(plo)n(wing)e(it)h(both)g(with)g(and)h +(without)e(jog)i(insertion.)146 189 y(There)h(is)e(another)h(w)o(ay)g +(to)g(reduce)g(the)g(number)g(of)g(jogs)f(introduced)g(by)h(plo)n +(wing.)k(Instead)c(of)g(a)n(v)n(oiding)0 309 y(jogs)30 +b(in)g(the)h(\002rst)g(place,)h(plo)n(wing)d(can)i(introduce)f(them)h +(freely)g(b)n(ut)f(clean)h(them)f(up)h(as)f(much)h(as)f(possible)0 +430 y(afterw)o(ard.)65 b(This)35 b(results)g(in)h(more)f(dense)h +(layouts,)i(b)n(ut)d(possibly)f(more)i(jogs)f(than)h(if)g(you)f(had)h +(enabled)0 550 y Fa(:plo)o(w)28 b(nojogs)p Fd(.)38 b(T)-8 +b(o)28 b(tak)o(e)f(adv)n(antage)g(of)h(this)e(second)i(method)e(for)i +(jog)f(reduction,)g(re-enable)h(jog)f(insertion)0 671 +y(\()p Fa(:plo)o(w)e(jogs)p Fd(\))g(and)f(enable)h(jog)g(cleanup)f +(with)g(the)h(command)900 899 y Fa(:plo)o(w)g(straighten)146 +1127 y Fd(From)j(no)n(w)e(on,)i(Magic)f(will)f(attempt)h(to)g +(straighten)f(out)h(jogs)g(after)h(each)g(plo)n(w)e(operation.)38 +b(T)-8 b(o)27 b(disable)0 1248 y(straightening,)c(use)i(the)f(command) +900 1476 y Fa(:plo)o(w)h(nostraighten)146 1704 y Fd(It)d(might)f(seem)g +(pointless)f(to)i(disable)f(jog)g(introduction)f(with)h +Fa(:plo)o(w)h(nojogs)g Fd(at)g(the)f(same)h(time)f(straight-)0 +1825 y(ening)31 b(is)h(enabled)g(with)f Fa(:plo)o(w)h(straighten)p +Fd(.)52 b(While)32 b(it)f(is)h(true)g(that)f Fa(:plo)o(w)h(nojogs)g +Fd(w)o(on')n(t)f(introduce)h(an)o(y)0 1945 y(ne)n(w)24 +b(jogs)f(for)h Fa(:plo)o(w)g(straighten)h Fd(to)f(clean)g(up,)g(plo)n +(wing)e(will)h(straighten)g(out)h(an)o(y)f(e)o(xisting)g(jogs)g(after)h +(each)0 2065 y(operation.)146 2186 y(In)e(f)o(act,)g(there)g(is)f(a)h +(separate)f(command)g(that)g(is)g(sometimes)e(useful)i(for)h(cleaning)f +(up)g(layouts)f(with)h(man)o(y)0 2306 y(jogs,)j(namely)g(the)h(command) +900 2534 y Fa(:straighten)h Fe(dir)l(ection)146 2763 +y Fd(where)32 b Fe(dir)l(ection)f Fd(is)g(a)h(Manhattan)f(direction,)h +(e.g.,)h Fa(up)p Fd(,)h Fa(do)o(wn)p Fd(,)g Fa(right)p +Fd(,)g(or)d Fa(left)p Fd(.)52 b(This)30 b(command)h(will)0 +2883 y(start)21 b(from)g(one)h(side)f(of)g(the)g(box)g(and)h(pull)e +(jogs)h(to)n(w)o(ard)g(that)f(side)h(to)h(straighten)e(them.)29 +b(Load)21 b(the)g(cell)h Fa(tut3g)p Fd(,)0 3003 y(place)i(the)f(box)g +(o)o(v)o(er)f(the)h(label)h(\223put)f(box)f(here\224,)j(and)e(type)g +Fa(:straighten)h(left)p Fd(.)31 b(Undo)23 b(the)g(last)g(command)f(and) +0 3124 y(type)i Fa(:straighten)i(right)f Fd(instead.)30 +b(Play)c(around)e(with)g(the)h Fa(:straighten)h Fd(command.)146 +3244 y(There)j(is)g(one)f(more)h(feature)g(of)g(plo)n(wing)e(that)h(is) +g(sometimes)f(useful.)42 b(If)29 b(you)f(are)h(w)o(orking)f(on)h(a)g +(lar)n(ge)0 3365 y(cell)e(and)g(w)o(ant)g(to)g(mak)o(e)g(sure)g(that)f +(plo)n(wing)g(ne)n(v)o(er)g(af)n(fects)h(an)o(y)g(geometry)f(outside)g +(of)h(a)h(certain)f(area,)i(you)0 3485 y(can)c(place)g(a)g +Fe(boundary)f Fd(around)h(the)f(area)i(you)f(w)o(ant)f(to)h(af)n(fect)g +(with)f(the)g(command)900 3713 y Fa(:plo)o(w)h(boundary)146 +3942 y Fd(The)h(box)g(is)g(used)g(to)f(specify)h(the)g(area)h(you)f(w)o +(ant)g(to)g(af)n(fect.)35 b(After)26 b(this)f(command,)h(subsequent)e +(plo)n(ws)0 4062 y(will)g(only)g(af)n(fect)h(the)g(area)h(inside)d +(this)h(boundary)-6 b(.)146 4182 y(Load)19 b(the)g(cell)g +Fa(tut3h)g Fd(place)h(the)e(box)h(o)o(v)o(er)f(the)g(label)h(\223put)g +(boundary)f(here\224,)j(and)d(type)h Fa(:plo)o(w)g(boundary)p +Fd(.)0 4303 y(No)n(w)25 b(mo)o(v)o(e)g(the)h(box)f(a)o(w)o(ay)-6 +b(.)34 b(Y)-11 b(ou)26 b(will)f(see)i(the)f(boundary)f(highlighted)f +(with)h(dotted)h(lines.)34 b(No)n(w)25 b(place)h(the)0 +4423 y(box)f(o)o(v)o(er)g(the)g(area)i(labelled)e(\223put)g(plo)n(w)f +(here\224)i(and)g(plo)n(w)e(up.)33 b(This)24 b(plo)n(w)h(w)o(ould)f +(cause)i(geometry)f(outside)0 4544 y(of)35 b(the)f(boundary)g(to)h(be)f +(af)n(fected,)k(so)c(Magic)g(reduces)h(the)g(plo)n(w)e(distance)i +(enough)f(to)g(pre)n(v)o(ent)f(this)h(and)0 4664 y(w)o(arns)25 +b(you)f(of)h(this)f(f)o(act.)31 b(No)n(w)24 b(undo)g(the)h(last)f(plo)n +(w)g(and)h(remo)o(v)o(e)e(the)i(boundary)f(with)900 4892 +y Fa(:plo)o(w)h(noboundary)146 5121 y Fd(Put)e(the)f(box)g(o)o(v)o(er)f +(the)i(\223put)f(plo)n(w)f(here\224)i(label)f(and)h(plo)n(w)e(up)h +(again.)29 b(This)22 b(time)g(there)g(w)o(as)h(no)f(boundary)0 +5241 y(to)h(stop)f(the)h(plo)n(w)-6 b(,)22 b(so)h(e)n(v)o(erything)e(w) +o(as)i(mo)o(v)o(ed)f(as)h(f)o(ar)h(as)f(the)g(height)f(of)i(the)f(box.) +29 b(Experiment)22 b(with)h(placing)0 5361 y(the)i(boundary)f(around)g +(an)h(area)h(of)f(this)f(cell)h(and)f(plo)n(wing.)1875 +5649 y(\2267\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut4.ps b/doc/psfiles/tut4.ps new file mode 100644 index 00000000..5fa93535 --- /dev/null +++ b/doc/psfiles/tut4.ps @@ -0,0 +1,861 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tut4.dvi +%%Pages: 8 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tut4.dvi -o tut4.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut4.dvi) +@start /Fa 119[33 13[44 50 50 72 50 55 33 39 44 1[55 +50 55 83 28 2[28 55 50 33 44 55 44 1[50 3[33 1[33 2[72 +3[66 55 3[78 1[94 4[78 2[66 72 72 1[72 6[33 2[50 2[50 +50 50 50 1[28 25 42[55 3[{ TeXBase1Encoding ReEncodeFont }44 +100.000003 /Times-Bold rf /Fb 138[66 40 47 53 2[60 66 +100 33 2[33 66 2[53 66 53 1[60 12[80 6[113 9[86 8[40 +55[66 2[{ TeXBase1Encoding ReEncodeFont }19 119.999948 +/Times-Bold rf /Fc 103[33 1[50 1[44 44 10[33 13[44 50 +50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 50 +33 44 50 44 50 44 3[33 1[33 1[72 72 94 1[72 61 55 2[55 +72 72 89 3[33 72 72 55 61 72 66 66 72 5[28 28 50 50 50 +50 50 50 50 50 50 50 28 25 33 25 2[33 33 33 3[50 31[55 +55 2[{ TeXBase1Encoding ReEncodeFont }74 100.000003 /Times-Roman +rf /Fd 133[39 44 44 66 1[50 28 39 39 1[50 50 50 72 28 +2[28 50 2[44 50 44 50 50 11[72 1[50 3[72 66 3[44 27[25 +1[25 2[33 33 37[50 2[{ TeXBase1Encoding ReEncodeFont }30 +100.000003 /Times-Italic rf /Fe 136[104 72 80 48 56 64 +1[80 72 80 120 40 2[40 80 72 1[64 80 64 80 72 9[143 104 +104 96 80 2[88 2[135 3[56 112 1[88 96 104 104 1[104 6[48 +72 72 72 72 72 72 72 72 72 13[72 32[80 2[{ + TeXBase1Encoding ReEncodeFont }45 143.999997 /Times-Bold +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 858 101 a Fe(Magic)35 b(T)-13 b(utorial)34 b(#4:)44 +b(Cell)35 b(Hierar)m(chies)1618 521 y Fd(J)n(ohn)24 b(Ousterhout)1401 +941 y Fc(Computer)g(Science)i(Di)n(vision)1020 1062 y(Electrical)f +(Engineering)f(and)h(Computer)f(Sciences)1473 1182 y(Uni)n(v)o(ersity)f +(of)i(California)1544 1303 y(Berk)o(ele)o(y)-6 b(,)24 +b(CA)h(94720)1448 1573 y Fd(\(Updated)f(by)h(other)o(s,)f(too.\))1053 +1843 y Fc(This)g(tutorial)g(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.) +0 2374 y Fb(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 +2580 y Fc(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)300 2701 y(Magic)g(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)0 2907 y Fb(Commands)k(intr)n(oduced)j +(in)f(this)f(tutorial:)300 3113 y Fc(:array)-6 b(,)25 +b(:edit,)f(:e)o(xpand,)f(:\003ush,)i(:getcell,)f(:identify)-6 +b(,)23 b(:load,)h(:path,)g(:see,)h(:une)o(xpand)0 3318 +y Fb(Macr)n(os)k(intr)n(oduced)i(in)g(this)f(tutorial:)300 +3550 y Fc(x,)25 b(X,)f(\210X)0 4453 y Fe(1)143 b(Intr)m(oduction)0 +4678 y Fc(In)21 b(Magic,)g(a)g(layout)f(is)h(a)g(hierarchical)g +(collection)f(of)h(cells.)29 b(Each)21 b(cell)g(contains)f(three)h +(things:)27 b(paint,)21 b(labels,)0 4798 y(and)e(subcells.)28 +b(T)l(utorial)18 b(#2)h(sho)n(wed)f(you)h(ho)n(w)f(to)h(create)h(and)g +(edit)e(paint)h(and)g(labels.)29 b(This)18 b(tutorial)g(describes)0 +4918 y(Magic')-5 b(s)34 b(f)o(acilities)h(for)g(b)n(uilding)f(up)h +(cell)g(hierarchies.)62 b(Strictly)35 b(speaking,)i(hierarchical)f +(structure)f(isn')n(t)0 5039 y(necessary:)43 b(an)o(y)31 +b(design)f(that)g(can)i(be)f(represented)g(hierarchically)g(can)g(also) +g(be)g(represented)g(\223\003at\224)h(\(with)0 5159 y(all)c(the)h +(paint)f(and)h(labels)f(in)g(a)h(single)f(cell\).)43 +b(Ho)n(we)n(v)o(er)l(,)28 b(man)o(y)g(things)f(are)j(greatly)e(impro)o +(v)o(ed)f(if)i(you)f(use)h(a)0 5280 y(hierarchical)i(structure,)g +(including)e(the)h(ef)n(\002cienc)o(y)g(of)h(the)f(design)f(tools,)i +(the)f(speed)g(with)g(which)g(you)g(can)0 5400 y(enter)25 +b(the)g(design,)f(and)g(the)h(ease)g(with)f(which)h(you)f(can)h(modify) +f(it)g(later)-5 b(.)1875 5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fc(September)25 b(26,)f(2001)1671 b(Magic)24 +b(T)l(utorial)g(#4:)30 b(Cell)25 b(Hierarchies)0 99 y +Fe(2)143 b(Selecting)34 b(and)h(V)-5 b(iewing)34 b(Hierar)m(chical)f +(Designs)0 327 y Fc(\223Hierarchical)26 b(structure\224)f(means)g(that) +g(each)g(cell)h(can)f(contain)g(other)g(cells)g(as)g(components.)30 +b(T)-8 b(o)25 b(look)g(at)g(an)0 447 y(e)o(xample)c(of)h(a)g +(hierarchical)g(layout,)g(enter)g(Magic)f(with)h(the)f(shell)g(command) +g Fa(magic)h(tut4a)p Fc(.)30 b(The)22 b(cell)g Fa(tut4a)0 +567 y Fc(contains)31 b(four)h(subcells)f(plus)g(some)g(blue)g(paint.)51 +b(T)-8 b(w)o(o)32 b(of)g(the)g(subcells)f(are)h(instances)f(of)h(cell)g +Fa(tut4x)g Fc(and)0 688 y(tw)o(o)f(are)h(instances)f(of)g +Fa(tut4y)p Fc(.)51 b(Initially)-6 b(,)31 b(each)h(subcell)f(is)g +(displayed)g(in)g Fd(une)n(xpanded)g Fc(form.)50 b(This)30 +b(means)0 808 y(that)c(no)g(details)g(of)g(the)g(subcell)g(are)h +(displayed;)f(all)g(you)g(see)h(is)f(the)g(cell')-5 b(s)26 +b(bounding)f(box,)h(plus)g(tw)o(o)f(names)0 929 y(inside)e(the)h +(bounding)f(box.)30 b(The)25 b(top)e(name)h(is)g(the)g(name)h(of)f(the) +g(subcell)g(\(the)g(name)g(you)g(w)o(ould)f(type)h(when)0 +1049 y(in)l(v)n(oking)f(Magic)i(to)f(edit)h(the)f(cell\).)31 +b(The)25 b(cell')-5 b(s)24 b(contents)g(are)i(stored)f(in)f(a)h(\002le) +g(with)g(this)e(name)i(plus)f(a)h Fa(.mag)0 1169 y Fc(e)o(xtension.)31 +b(The)25 b(bottom)e(name)j(inside)e(each)i(bounding)e(box)g(is)h +(called)g(an)h Fd(instance)e(identi\002er)p Fc(,)g(and)i(is)e(used)0 +1290 y(to)g(distinguish)f(dif)n(ferent)h(instances)g(of)h(the)g(same)g +(subcell.)30 b(Instance)25 b(id')-5 b(s)24 b(are)h(used)g(for)g +(routing)f(and)g(circuit)0 1410 y(e)o(xtraction,)g(and)g(are)i +(discussed)e(in)g(Section)h(6.)146 1533 y(Subcells)i(can)h(be)f +(manipulated)f(using)g(the)h(same)g(selection)g(mechanism)f(that)g(you) +h(learned)h(in)e(T)l(utorial)0 1653 y(#2.)33 b(T)-8 b(o)26 +b(select)g(a)g(subcell,)f(place)h(the)g(cursor)f(o)o(v)o(er)g(the)h +(subcell)f(and)h(type)f Fa(f)h Fc(\(\223)p Fa(f)p Fc(ind)g(cell\224\),) +g(which)g(is)f(a)h(macro)0 1773 y(for)33 b Fa(:select)g(cell)p +Fc(.)55 b(Y)-11 b(ou)32 b(can)i(also)e(select)h(a)g(cell)g(by)f(typing) +g Fa(s)g Fc(when)h(the)g(cursor)f(is)h(o)o(v)o(er)f(a)h(location)f +(where)0 1894 y(there')-5 b(s)29 b(no)f(paint;)i Fa(f)f +Fc(is)g(probably)f(more)g(con)l(v)o(enient,)h(particularly)f(for)h +(cells)g(that)f(are)i(completely)e(co)o(v)o(ered)0 2014 +y(with)g(paint.)41 b(When)28 b(you)g(select)h(a)g(cell)f(the)g(box)g +(will)g(be)h(set)f(to)g(the)g(cell')-5 b(s)28 b(bounding)f(box,)i(the)f +(cell')-5 b(s)28 b(name)0 2135 y(will)d(be)h(highlighted,)e(and)h(a)h +(message)g(will)f(be)g(printed)h(on)f(the)h(te)o(xt)e(display)-6 +b(.)32 b(All)25 b(the)h(selection)f(operations)0 2255 +y(\()p Fa(:mo)o(v)o(e)p Fc(,)h Fa(:copy)p Fc(,)h Fa(:delete)p +Fc(,)g(etc.\))34 b(apply)25 b(to)g(subcells.)33 b(T)m(ry)25 +b(selecting)g(and)h(mo)o(ving)e(the)h(top)g(subcell)g(in)h +Fa(tut4a)p Fc(.)0 2375 y(Y)-11 b(ou)29 b(can)g(also)f(select)h +(subcells)f(using)g(area)i(selection)e(\(the)h Fa(a)g +Fc(and)f Fa(A)h Fc(macros\):)39 b(an)o(y)28 b(une)o(xpanded)g(subcells) +0 2496 y(that)c(intersect)h(the)f(area)i(of)f(the)g(box)f(will)g(be)h +(selected.)146 2618 y(T)-8 b(o)28 b(see)g(what')-5 b(s)28 +b(inside)f(a)h(cell)g(instance,)g(you)g(must)f Fd(e)n(xpand)g +Fc(it.)40 b(Select)29 b(one)e(of)i(the)e(instances)h(of)g +Fa(tut4y)p Fc(,)0 2739 y(then)c(type)h(the)g(command)900 +2984 y Fa(:expand)h(toggle)146 3227 y Fc(or)g(in)l(v)n(ok)o(e)f(the)h +(macro)f Fa(\210X)h Fc(which)g(is)f(equi)n(v)n(alent.)31 +b(This)25 b(causes)h(the)g(internals)f(of)g(that)h(instance)f(of)h +Fa(tut4y)0 3347 y Fc(to)g(be)g(displayed.)34 b(If)27 +b(you)e(type)h Fa(\210X)g Fc(again,)g(the)g(instance)g(is)g(une)o +(xpanded)f(so)h(you)f(only)h(see)g(a)h(bounding)e(box)0 +3468 y(again.)50 b(The)31 b Fa(:expand)i(toggle)e Fc(command)f(e)o +(xpands)h(all)g(of)g(the)h(selected)f(cells)g(that)g(are)h(une)o +(xpanded,)g(and)0 3588 y(une)o(xpands)24 b(all)g(those)g(that)h(are)g +(e)o(xpanded.)30 b(T)-8 b(ype)25 b Fa(\210X)g Fc(a)g(third)f(time)g(so) +h(that)f Fa(tut4y)h Fc(is)g(e)o(xpanded.)146 3710 y(As)37 +b(you)f(can)h(see)g(no)n(w)-6 b(,)38 b Fa(tut4y)f Fc(contains)f(an)g +(array)i(of)e Fa(tut4x)h Fc(cells)g(plus)e(some)h(additional)g(paint.) +65 b(In)0 3831 y(Magic,)23 b(an)h(array)g(is)f(a)h(special)f(kind)g(of) +h(instance)f(containing)f(multiple)g(copies)h(of)g(the)h(same)f +(subcell)g(spaced)0 3951 y(at)k(\002x)o(ed)g(interv)n(als.)37 +b(Arrays)27 b(can)h(be)f(one-dimensional)f(or)h(tw)o(o-dimensional.)36 +b(The)27 b(whole)g(array)h(is)e(al)o(w)o(ays)0 4072 y(treated)h(as)f(a) +h(single)e(instance:)34 b(an)o(y)26 b(command)f(that)h(operates)h(on)f +(one)g(element)g(of)h(the)f(array)h(also)f(operates)0 +4192 y(on)f(all)h(the)g(other)f(elements)g(simultaneously)-6 +b(.)31 b(The)25 b(instance)h(identi\002ers)f(for)h(the)f(elements)g(of) +h(the)g(array)g(are)0 4312 y(the)j(same)g(e)o(xcept)f(for)i(an)f(inde)o +(x.)42 b(No)n(w)29 b(select)g(one)g(of)g(the)g(elements)f(of)h(the)g +(array)h(and)f(e)o(xpand)f(it.)43 b(Notice)0 4433 y(that)24 +b(the)h(entire)g(array)g(is)g(e)o(xpanded)f(at)h(the)f(same)h(time.)146 +4555 y(When)40 b(you)f(ha)n(v)o(e)h(e)o(xpanded)f(the)g(array)-6 +b(,)44 b(you')o(ll)39 b(see)h(that)f(the)h(paint)f(in)g(the)h(top-le)n +(v)o(el)e(cell)h Fa(tut4a)i Fc(is)0 4676 y(displayed)23 +b(more)g(brightly)g(than)g(the)h(paint)f(in)h(the)f Fa(tut4x)i +Fc(instances.)k Fa(T)-9 b(ut4a)25 b Fc(is)e(called)h(the)f +Fd(edit)h(cell)p Fc(,)g(because)0 4796 y(its)30 b(contents)f(are)j +(currently)e(editable.)48 b(The)30 b(paint)g(in)g(the)h(edit)f(cell)g +(is)g(normally)g(displayed)f(more)h(brightly)0 4916 y(than)22 +b(other)f(paint)g(to)h(mak)o(e)g(it)f(clear)i(that)e(you)g(can)i +(change)f(it.)29 b(As)22 b(long)f(as)h Fa(tut4a)g Fc(is)g(the)f(edit)h +(cell,)g(you)f(cannot)0 5037 y(modify)27 b(the)i(paint)e(in)i +Fa(tut4x)p Fc(.)42 b(T)m(ry)28 b(erasing)g(paint)g(from)g(the)g(area)i +(of)e(one)h(of)f(the)h Fa(tut4x)f Fc(instances:)38 b(nothing)0 +5157 y(will)24 b(be)h(changed.)31 b(Section)24 b(4)h(tells)f(ho)n(w)g +(to)g(switch)h(the)f(edit)h(cell.)146 5280 y(Place)f(the)f(cursor)g(o)o +(v)o(er)f(one)h(of)g(the)f Fa(tut4x)i Fc(array)f(elements)f(again.)30 +b(At)22 b(this)g(point,)g(the)h(cursor)g(is)g(actually)0 +5400 y(o)o(v)o(er)i(three)h(dif)n(ferent)f(cells:)32 +b Fa(tut4x)26 b Fc(\(an)h(element)e(of)h(an)f(array)i(instance)e +(within)g Fa(tut4y)p Fc(\),)h Fa(tut4y)g Fc(\(an)h(instance)1875 +5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#4:)30 b(Cell)25 +b(Hierarchies)1671 b(September)25 b(26,)g(2001)0 69 y(within)f +Fa(tut4a)p Fc(\),)i(and)g Fa(tut4)p Fc(.)33 b(Ev)o(en)24 +b(the)i(topmost)d(cell)j(in)f(the)g(hierarchy)g(is)g(treated)g(as)h(an) +f(instance)g(by)h(Magic.)0 189 y(When)35 b(you)g(press)g(the)g +Fa(s)g Fc(k)o(e)o(y)g(to)g(select)g(a)h(cell,)h(Magic)e(initially)f +(chooses)g(the)i(smallest)d(instance)i(visible)0 309 +y(underneath)j(the)h(cursor)l(,)j Fa(tut4x)d Fc(in)f(this)g(case.)73 +b(Ho)n(we)n(v)o(er)l(,)40 b(if)f(you)f(in)l(v)n(ok)o(e)g(the)g +Fa(s)h Fc(macro)g(again)f(\(or)g(type)0 430 y Fa(:select)p +Fc(\))24 b(without)e(mo)o(ving)g(the)h(cursor)l(,)h(Magic)f(will)g +(step)g(through)f(all)h(of)h(the)f(instances)g(under)h(the)f(cursor)g +(in)0 550 y(order)-5 b(.)31 b(T)m(ry)24 b(this)g(out.)30 +b(The)25 b(same)f(is)h(true)f(of)h(the)g Fa(f)g Fc(macro)g(and)g +Fa(:select)g(cell)p Fc(.)146 671 y(When)31 b(there)h(are)g(man)o(y)e +(dif)n(ferent)g(e)o(xpanded)h(cells)g(on)g(the)g(screen,)i(you)d(can)i +(use)f(the)g(selection)f(com-)0 791 y(mands)23 b(to)g(select)g(paint)g +(from)h(an)o(y)f(of)g(them.)30 b(Y)-11 b(ou)23 b(can)h(select)f(an)o +(ything)f(that')-5 b(s)23 b(visible,)f(re)o(gardless)h(of)h(which)0 +912 y(cell)37 b(it')-5 b(s)36 b(in.)68 b(Ho)n(we)n(v)o(er)l(,)39 +b(as)f(mentioned)e(abo)o(v)o(e,)j(you)e(can)h(only)e(modify)g(paint)h +(in)g(the)g(edit)g(cell.)68 b(If)38 b(you)0 1032 y(use)c +Fa(:mo)o(v)o(e)g Fc(or)f Fa(:upsidedo)o(wn)j Fc(or)e(similar)e +(commands)h(when)g(you')-5 b(v)o(e)34 b(selected)f(information)g +(outside)f(the)0 1153 y(edit)25 b(cell,)g(the)g(information)f(outside)g +(the)h(edit)g(cell)g(is)g(remo)o(v)o(ed)f(from)h(the)g(selection)g +(before)h(performing)e(the)0 1273 y(operation.)146 1394 +y(There)i(are)f(tw)o(o)f(additional)g(commands)f(you)i(can)g(use)g(for) +g(e)o(xpanding)e(and)i(une)o(xpanding)e(cells:)900 1626 +y Fa(:expand)900 1746 y(:unexpand)146 1978 y Fc(Both)38 +b(of)h(these)f(commands)f(operate)h(on)g(the)g(area)h(underneath)f(the) +g(box.)70 b(The)39 b Fa(:expand)g Fc(command)0 2099 y(will)30 +b(recursi)n(v)o(ely)f(e)o(xpand)i(e)n(v)o(ery)f(cell)h(that)f +(intersects)g(the)h(box)f(until)g(there)h(are)g(no)g(une)o(xpanded)f +(cells)g(left)0 2219 y(under)e(the)g(box.)39 b(The)28 +b Fa(:unexpand)j Fc(command)c(will)g(une)o(xpand)g(e)n(v)o(ery)g(cell)h +(whose)f(area)i(intersects)f(the)g(box)0 2339 y(b)n(ut)j(doesn')n(t)f +(completely)g(contain)h(it.)49 b(The)32 b(macro)f Fa(x)g +Fc(is)g(equi)n(v)n(alent)e(to)i Fa(:expand)p Fc(,)j(and)d +Fa(X)g Fc(is)g(equi)n(v)n(alent)e(to)0 2460 y Fa(:unexpand)p +Fc(.)k(T)m(ry)24 b(out)g(the)h(v)n(arious)f(e)o(xpansion)f(and)i(une)o +(xpansion)e(f)o(acilities)h(on)g Fa(tut4a)p Fc(.)0 2802 +y Fe(3)143 b(Manipulating)34 b(Subcells)0 3027 y Fc(There)f(are)f(a)h +(fe)n(w)f(other)g(commands,)h(in)e(addition)g(to)h(the)g(selection)f +(commands)g(already)i(described,)h(that)0 3147 y(you')o(ll)24 +b(need)h(in)f(order)h(to)g(manipulate)f(subcells.)29 +b(The)c(command)900 3380 y Fa(:getcell)g Fd(name)146 +3611 y Fc(will)f(\002nd)i(the)f(\002le)g Fd(name)p Fa(.mag)f +Fc(on)h(disk,)f(read)i(the)f(cell)g(it)f(contains,)h(and)g(create)h(an) +f(instance)f(of)i(that)e(cell)0 3732 y(with)j(its)g(lo)n(wer)n(-left)g +(corner)i(aligned)e(with)g(the)h(lo)n(wer)n(-left)f(corner)i(of)e(the)h +(box.)40 b(Use)27 b(the)h Fa(getcell)g Fc(command)0 3852 +y(to)k(get)h(an)g(instance)f(of)h(the)g(cell)f Fa(tut4z)p +Fc(.)56 b(After)33 b(the)f Fa(getcell)h Fc(command,)h(the)f(ne)n(w)f +(instance)g(is)h(selected)f(so)0 3972 y(you)i(can)i(mo)o(v)o(e)d(it)h +(or)h(cop)o(y)g(it)f(or)h(delete)g(it.)60 b(The)35 b +Fa(getcell)g Fc(command)e(recognizes)i(additional)f(ar)n(guments)0 +4093 y(that)25 b(permit)f(the)h(cell)h(to)e(be)i(positioned)d(using)h +(labels)h(and/or)g(e)o(xplicit)f(coordinates.)31 b(See)26 +b(the)g Fd(man)e Fc(page)i(for)0 4213 y(details.)146 +4334 y(T)-8 b(o)32 b(turn)f(a)i(normal)e(instance)g(into)g(an)h(array) +-6 b(,)34 b(select)e(the)g(instance)f(and)h(then)f(in)l(v)n(ok)o(e)h +(the)f Fa(:array)h Fc(com-)0 4454 y(mand.)e(It)25 b(has)g(tw)o(o)f +(forms:)900 4687 y Fa(:array)h Fd(xsize)g(ysize)900 4807 +y Fa(:array)g Fd(xlo)g(xhi)f(ylo)h(yhi)146 5039 y Fc(In)30 +b(the)f(\002rst)h(form,)h Fd(xsize)e Fc(indicates)g(ho)n(w)g(man)o(y)f +(elements)h(the)g(array)i(should)d(ha)n(v)o(e)h(in)h(the)f +(x-direction,)0 5159 y(and)34 b Fd(ysize)g Fc(indicates)g(ho)n(w)f(man) +o(y)h(elements)f(it)h(should)f(ha)n(v)o(e)h(in)g(the)g(y-direction.)59 +b(The)34 b(spacing)g(between)0 5280 y(elements)25 b(is)g(controlled)g +(by)g(the)h(box')-5 b(s)24 b(width)h(\(for)h(the)g(x-direction\))f(and) +h(height)e(\(for)j(the)e(y-direction\).)33 b(By)0 5400 +y(changing)e(the)h(box)f(size,)j(you)d(can)h(space)g(elements)f(so)h +(that)f(the)o(y)g(o)o(v)o(erlap,)h(ab)n(ut,)i(or)e(ha)n(v)o(e)f(gaps)g +(between)1875 5649 y(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fc(September)25 b(26,)f(2001)1671 b(Magic)24 +b(T)l(utorial)g(#4:)30 b(Cell)25 b(Hierarchies)0 68 y(them.)36 +b(The)26 b(elements)g(are)i(gi)n(v)o(en)d(indices)h(from)h(0)f(to)h +Fd(xsize)p Fc(-1)f(in)g(the)h(x-direction)f(and)h(from)f(0)h(to)f +Fd(ysize)p Fc(-1)g(in)0 188 y(the)h(y-direction.)37 b(The)27 +b(second)g(form)g(of)g(the)g(command)f(is)g(identical)h(to)f(the)h +(\002rst)h(e)o(xcept)e(that)h(the)g(elements)0 309 y(are)36 +b(gi)n(v)o(en)e(indices)h(from)g Fd(xlo)h Fc(to)f Fd(xhi)g +Fc(in)g(the)g(x-direction)g(and)g(from)h Fd(ylo)f Fc(to)g +Fd(yhi)g Fc(in)g(the)h(y-direction.)62 b(T)m(ry)0 429 +y(making)24 b(a)h(4x4)f(array)i(out)e(of)h(the)g Fa(tut4z)g +Fc(cell)g(with)f(gaps)g(between)h(the)g(cells.)146 553 +y(Y)-11 b(ou)19 b(can)h(also)f(in)l(v)n(ok)o(e)f(the)h +Fa(:array)h Fc(command)e(on)h(an)g(e)o(xisting)f(array)h(to)g(change)h +(the)f(number)g(of)g(elements)0 673 y(or)29 b(spacing.)43 +b(Use)28 b(a)i(size)f(of)g(1)f(for)i Fd(xsize)e Fc(or)h +Fd(ysize)g Fc(in)g(order)g(to)f(get)h(a)g(one-dimensional)f(array)-6 +b(.)43 b(If)29 b(there)g(are)0 794 y(se)n(v)o(eral)d(cells)g(selected,) +h(the)g Fa(:array)g Fc(command)e(will)h(mak)o(e)h(each)g(of)f(them)g +(into)g(an)h(array)g(of)g(the)g(same)f(size)0 914 y(and)31 +b(spacing.)47 b(It)31 b(also)f(w)o(orks)g(on)h(paint)f(and)g(labels:)42 +b(if)30 b(paint)g(and)h(labels)f(are)h(selected)g(when)g(you)f(in)l(v)n +(ok)o(e)0 1034 y Fa(:array)p Fc(,)f(the)o(y)f(will)f(be)i(copied)e(man) +o(y)h(times)f(o)o(v)o(er)g(to)h(create)i(the)e(array)-6 +b(.)41 b(T)m(ry)28 b(using)f(the)h(array)h(command)e(to)0 +1155 y(replicate)e(a)g(small)f(strip)g(of)h(paint.)0 +1516 y Fe(4)143 b(Switching)34 b(the)h(Edit)g(Cell)0 +1746 y Fc(At)28 b(an)o(y)f(gi)n(v)o(en)g(time,)g(you)h(are)h(editing)e +(the)g(de\002nition)g(of)h(a)h(single)e(cell.)40 b(This)27 +b(de\002nition)g(is)h(called)g(the)g Fd(edit)0 1867 y(cell)p +Fc(.)i(Y)-11 b(ou)23 b(can)h(modify)f(paint)f(and)i(labels)f(in)g(the)g +(edit)g(cell,)h(and)f(you)g(can)h(re-arrange)h(its)e(subcells.)29 +b(Y)-11 b(ou)23 b(may)0 1987 y(not)28 b(re-arrange)h(or)g(delete)f(the) +g(subcells)g(of)g(an)o(y)g(cells)g(other)g(than)g(the)g(edit)g(cell,)h +(nor)f(may)g(you)g(modify)f(the)0 2107 y(paint)j(or)g(labels)g(of)h(an) +o(y)f(cells)g(e)o(xcept)g(the)g(edit)h(cell.)47 b(Y)-11 +b(ou)30 b(may)-6 b(,)31 b(ho)n(we)n(v)o(er)l(,)g(cop)o(y)f(information) +f(from)h(other)0 2228 y(cells)25 b(into)f(the)h(edit)f(cell,)h(using)g +(the)f(selection)h(commands.)30 b(T)-8 b(o)25 b(help)g(clarify)g(what)g +(is)f(and)h(isn')n(t)g(modi\002able,)0 2348 y(Magic)f(displays)g(the)h +(paint)f(of)h(the)f(edit)h(cell)f(in)h(brighter)f(colors)h(than)f +(other)h(paint.)146 2472 y(When)h(you)f(rearrange)h(subcells)f(of)g +(the)h(edit)f(cell,)g(you)g(aren')n(t)h(changing)f(the)g(subcells)g +(themselv)o(es.)31 b(All)0 2592 y(you)26 b(can)h(do)f(is)g(change)h +(the)f(w)o(ay)h(the)o(y)e(are)i(used)g(in)f(the)g(edit)g(cell)g +(\(location,)h(orientation,)e(etc.\).)36 b(When)27 b(you)0 +2713 y(delete)k(a)f(subcell,)i(nothing)d(happens)h(to)g(the)g(\002le)h +(containing)e(the)i(subcell;)h(the)f(command)e(merely)h(deletes)0 +2833 y(the)25 b(instance)f(from)h(the)f(edit)h(cell.)146 +2957 y(Besides)33 b(the)f(edit)g(cell,)i(there)f(is)f(one)h(other)f +(special)g(cell)g(in)h(Magic.)53 b(It')-5 b(s)32 b(called)g(the)h +Fd(r)l(oot)e(cell)h Fc(and)h(is)0 3077 y(the)26 b(topmost)e(cell)i(in)f +(the)h(hierarchy)-6 b(,)25 b(the)h(one)g(you)f(named)h(when)g(you)f +(ran)h(Magic)g(\()p Fa(tut4a)g Fc(in)g(this)f(case\).)34 +b(As)0 3198 y(you)28 b(will)g(see)g(in)g(T)l(utorial)f(#5,)i(there)g +(can)g(actually)f(be)g(se)n(v)o(eral)g(root)g(cells)g(at)h(an)o(y)f(gi) +n(v)o(en)f(time,)h(one)g(in)g(each)0 3318 y(windo)n(w)-6 +b(.)50 b(F)o(or)31 b(no)n(w)-6 b(,)32 b(there)g(is)g(only)e(a)j(single) +d(windo)n(w)h(on)g(the)h(screen,)i(and)d(thus)g(only)g(a)h(single)f +(root)g(cell.)0 3438 y(The)23 b(windo)n(w)e(caption)h(at)g(the)h(top)f +(of)g(the)h(color)f(display)f(contains)h(the)g(name)h(of)g(the)f(windo) +n(w')-5 b(s)21 b(root)h(cell)g(and)0 3559 y(also)i(the)h(name)g(of)g +(the)f(edit)h(cell.)146 3682 y(Up)f(until)f(no)n(w)-6 +b(,)22 b(the)i(root)g(cell)g(and)f(the)h(edit)g(cell)g(ha)n(v)o(e)f +(been)h(the)g(same.)30 b(Ho)n(we)n(v)o(er)l(,)23 b(this)g(need)h(not)f +(al)o(w)o(ays)0 3803 y(be)i(the)f(case.)31 b(Y)-11 b(ou)24 +b(can)h(switch)e(the)i(edit)f(cell)g(to)g(an)o(y)g(cell)g(in)g(the)g +(hierarchy)g(by)h(selecting)e(an)i(instance)f(of)g(the)0 +3923 y(de\002nition)g(you')-5 b(d)24 b(lik)o(e)h(to)f(edit,)g(and)h +(then)f(typing)g(the)h(command)900 4178 y Fa(:edit)146 +4430 y Fc(Use)38 b(this)f(command)f(to)i(switch)f(the)g(edit)g(cell)h +(to)f(one)h(of)g(the)f Fa(tut4x)h Fc(instances)f(in)h +Fa(tut4a)p Fc(.)69 b(Its)38 b(paint)0 4551 y(brightens,)24 +b(while)h(the)g(paint)f(in)h Fa(tut4a)h Fc(becomes)f(dim.)31 +b(If)26 b(you)e(w)o(ant)h(to)g(edit)g(an)g(element)g(of)g(an)h(array)-6 +b(,)25 b(select)0 4671 y(the)37 b(array)-6 b(,)41 b(place)d(the)f +(cursor)g(o)o(v)o(er)g(the)g(element)g(you')-5 b(d)37 +b(lik)o(e)g(to)g(edit,)j(then)d(type)g Fa(:edit)p Fc(.)69 +b(The)37 b(particular)0 4791 y(element)24 b(underneath)h(the)g(cursor)f +(becomes)h(the)g(edit)f(cell.)146 4915 y(When)k(you)g(edit)g(a)g(cell,) +h(you)f(are)h(editing)e(the)h(master)g(de\002nition)f(of)h(that)g +(cell.)40 b(This)28 b(means)f(that)h(if)g(the)0 5035 +y(cell)35 b(is)f(used)g(in)g(se)n(v)o(eral)g(places)h(in)f(your)h +(design,)h(the)e(edits)g(will)g(be)h(re\003ected)h(in)e(all)g(those)g +(places.)61 b(T)m(ry)0 5156 y(painting)21 b(and)i(erasing)f(in)g(the)g +Fa(tut4x)h Fc(cell)g(that)f(you)g(just)f(made)i(the)f(edit)g(cell:)29 +b(the)23 b(modi\002cations)e(will)g(appear)0 5276 y(in)j(all)h(of)g +(its)f(instances.)146 5400 y(There)i(is)e(a)h(second)g(w)o(ay)g(to)f +(change)h(the)g(edit)f(cell.)31 b(This)24 b(is)g(the)h(command)1875 +5649 y(\2264\226)p eop +%%Page: 5 5 +5 4 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#4:)30 b(Cell)25 +b(Hierarchies)1671 b(September)25 b(26,)g(2001)900 84 +y Fa(:load)g Fd(name)146 522 y Fc(The)e Fa(:load)f Fc(command)g(loads)g +(a)h(ne)n(w)f(hierarchy)g(into)g(the)h(windo)n(w)e(underneath)h(the)h +(cursor)-5 b(.)29 b Fd(Name)23 b Fc(is)f(the)0 642 y(name)27 +b(of)g(the)f(root)h(cell)g(in)f(the)h(hierarchy)-6 b(.)36 +b(If)27 b(no)g Fd(name)f Fc(is)h(gi)n(v)o(en,)e(a)j(ne)n(w)e(unnamed)g +(cell)h(is)f(loaded)h(and)g(you)0 762 y(start)e(editing)f(from)g +(scratch.)32 b(The)25 b Fa(:load)g Fc(command)f(only)g(changes)h(the)g +(edit)f(cell)h(if)g(there)h(is)e(not)h(already)g(an)0 +883 y(edit)f(cell)h(in)g(another)f(windo)n(w)-6 b(.)0 +1413 y Fe(5)143 b(Subcell)35 b(Usage)f(Con)-6 b(v)o(entions)0 +1699 y Fc(Ov)o(erlaps)24 b(between)h(cells)g(are)h(occasionally)e +(useful)g(to)h(share)g(b)n(usses)f(and)h(control)g(lines)f(running)g +(along)g(the)0 1819 y(edges.)46 b(Ho)n(we)n(v)o(er)l(,)30 +b(o)o(v)o(erlaps)f(cause)h(the)g(analysis)f(tools)g(to)h(w)o(ork)g +(much)f(harder)i(than)e(the)o(y)h(w)o(ould)f(if)h(there)0 +1940 y(were)d(no)e(o)o(v)o(erlaps:)32 b(where)n(v)o(er)25 +b(cells)h(o)o(v)o(erlap,)f(the)h(tools)f(ha)n(v)o(e)g(to)h(combine)f +(the)h(information)e(from)i(the)g(tw)o(o)0 2060 y(separate)e(cells.)30 +b(Thus,)23 b(you)f(shouldn')n(t)h(use)g(o)o(v)o(erlaps)f(an)o(y)h(more) +g(than)g(absolutely)f(necessary)-6 b(.)30 b(F)o(or)23 +b(e)o(xample,)0 2180 y(suppose)f(you)h(w)o(ant)h(to)f(create)h(a)g +(one-dimensional)d(array)j(of)g(cells)f(that)g(alternates)g(between)h +(tw)o(o)e(cell)i(types,)0 2301 y(A)k(and)g(B:)h(\223)-8 +b(AB)m(AB)m(AB)m(AB)m(AB)m(AB\224.)29 b(One)f(w)o(ay)g(to)g(do)g(this)f +(is)h(\002rst)g(to)g(mak)o(e)g(an)h(array)g(of)f(A)g(instances)g(with)0 +2421 y(lar)n(ge)34 b(gaps)f(between)h(them)f(\(\223)-8 +b(A)34 b(A)f(A)h(A)g(A)f(A)-11 b(\224\),)34 b(then)f(mak)o(e)h(an)g +(array)g(of)g(B)g(instances)f(with)g(lar)n(ge)h(gaps)0 +2542 y(between)f(them)g(\(\223B)i(B)f(B)g(B)g(B)g(B\224\),)g(and)f +(\002nally)g(place)h(one)g(array)g(on)f(top)g(of)g(the)g(other)h(so)f +(that)g(the)g(B')-5 b(s)0 2662 y(nestle)31 b(in)g(between)g(the)g(A)-11 +b(')-5 b(s.)49 b(The)32 b(problem)e(with)g(this)h(approach)g(is)g(that) +g(the)g(tw)o(o)f(arrays)i(o)o(v)o(erlap)e(almost)0 2782 +y(completely)-6 b(,)32 b(so)g(Magic)g(will)g(ha)n(v)o(e)g(to)g(go)g(to) +g(a)g(lot)g(of)g(e)o(xtra)g(w)o(ork)g(to)g(handle)g(the)g(o)o(v)o +(erlaps)f(\(in)h(this)g(case,)0 2903 y(there)f(isn')n(t)e(much)h(o)o(v) +o(erlap)g(of)g(actual)g(paint,)h(b)n(ut)f(Magic)g(w)o(on')n(t)g(kno)n +(w)g(this)f(and)i(will)e(spend)h(a)h(lot)e(of)i(time)0 +3023 y(w)o(orrying)23 b(about)g(it\).)29 b(A)24 b(better)f(solution)f +(is)h(to)g(create)h(a)g(ne)n(w)f(cell)g(that)g(contains)g(one)g +(instance)g(of)g(A)h(and)f(one)0 3144 y(instance)28 b(of)h(B,)g(side)g +(by)f(side.)42 b(Then)29 b(mak)o(e)g(an)g(array)g(of)g(the)g(ne)n(w)f +(cell.)42 b(This)28 b(approach)h(mak)o(es)g(it)f(clear)h(to)0 +3264 y(Magic)24 b(that)h(there)g(isn')n(t)f(an)o(y)g(real)i(o)o(v)o +(erlap)d(between)i(the)g(A)-11 b(')-5 b(s)24 b(and)h(B')-5 +b(s.)146 3414 y(If)30 b(you)f(do)g(create)h(o)o(v)o(erlaps,)f(you)g +(should)f(use)i(the)f(o)o(v)o(erlaps)f(only)g(to)h(connect)h(the)f(tw)o +(o)g(cells)g(together)l(,)0 3535 y(and)39 b(not)e(to)i(change)f(their)h +(structure.)71 b(This)38 b(means)g(that)g(the)h(o)o(v)o(erlap)e(should) +g(not)h(cause)h(transistors)e(to)0 3655 y(appear)l(,)31 +b(disappear)l(,)f(or)f(change)h(size.)43 b(The)30 b(result)e(of)i(o)o +(v)o(erlapping)d(the)i(tw)o(o)g(subcells)f(should)g(be)h(the)g(same)0 +3775 y(electrically)24 b(as)g(if)g(you)f(placed)h(the)g(tw)o(o)g(cells) +f(apart)i(and)e(then)h(ran)g(wires)g(to)g(hook)f(parts)h(of)g(one)g +(cell)g(to)f(parts)0 3896 y(of)30 b(the)g(other)-5 b(.)46 +b(The)31 b(con)l(v)o(ention)d(is)i(necessary)g(in)g(order)h(to)e(be)i +(able)f(to)g(do)g(hierarchical)g(circuit)g(e)o(xtraction)0 +4016 y(easily)24 b(\(it)h(mak)o(es)f(it)h(possible)e(for)i(each)h +(subcell)e(to)g(be)h(circuit-e)o(xtracted)f(independently\).)146 +4166 y(Three)33 b(kinds)e(of)h(o)o(v)o(erlaps)f(are)h(\003agged)h(as)f +(errors)g(by)g(the)g(design-rule)f(check)o(er)-5 b(.)53 +b(First,)33 b(you)f(may)g(not)0 4287 y(o)o(v)o(erlap)24 +b(polysilicon)g(in)g(one)i(subcell)e(with)h(dif)n(fusion)f(in)h +(another)g(cell)g(in)g(order)h(to)f(create)h(transistors.)31 +b(Sec-)0 4407 y(ond,)g(you)f(may)g(not)g(o)o(v)o(erlap)f(transistors)g +(or)h(contacts)g(in)g(one)g(cell)h(with)e(dif)n(ferent)h(kinds)g(of)g +(transistors)f(or)0 4527 y(contacts)j(in)h(another)g(cell)f(\(there)i +(are)f(a)g(fe)n(w)g(e)o(xceptions)f(to)g(this)g(rule)h(in)f(some)g +(technologies\).)54 b(Third,)34 b(if)0 4648 y(contacts)h(from)g(dif)n +(ferent)g(cells)g(o)o(v)o(erlap,)i(the)o(y)d(must)h(be)g(the)g(same)g +(type)g(of)h(contact)f(and)g(must)f(coincide)0 4768 y(e)o(xactly:)29 +b(you)24 b(may)f(not)h(ha)n(v)o(e)f(partial)h(o)o(v)o(erlaps.)29 +b(This)23 b(rule)h(is)f(necessary)i(in)e(order)h(to)g(guarantee)g(that) +f(Magic)0 4889 y(can)i(generate)h(CIF)f(for)h(f)o(abrication.)146 +5039 y(Y)-11 b(ou)26 b(will)e(mak)o(e)h(life)h(a)g(lot)e(easier)i(on)g +(yourself)f(\(and)g(on)h(Magic\))f(if)g(you)g(spend)g(a)h(bit)f(of)h +(time)e(to)h(choose)0 5159 y(a)36 b(clean)h(hierarchical)f(structure.) +64 b(In)37 b(general,)i(the)d(less)f(cell)h(o)o(v)o(erlap)f(the)h +(better)-5 b(.)64 b(If)37 b(you)e(use)h(e)o(xtensi)n(v)o(e)0 +5280 y(o)o(v)o(erlaps)29 b(you')o(ll)g(\002nd)h(that)f(the)h(tools)f +(run)h(v)o(ery)f(slo)n(wly)f(and)i(that)g(it')-5 b(s)29 +b(hard)h(to)f(mak)o(e)h(modi\002cations)f(to)g(the)0 +5400 y(circuit.)1875 5649 y(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Fc(September)25 b(26,)f(2001)1671 b(Magic)24 +b(T)l(utorial)g(#4:)30 b(Cell)25 b(Hierarchies)0 99 y +Fe(6)143 b(Instance)34 b(Identi\002ers)0 328 y Fc(Instance)d +(identi\002ers)g(are)h(used)f(to)g(distinguish)e(the)i(dif)n(ferent)g +(subcells)f(within)g(a)h(single)g(parent.)50 b(The)31 +b(cell)0 448 y(de\002nition)22 b(names)g(cannot)h(be)g(used)f(for)h +(this)f(purpose)g(because)h(there)g(could)f(be)h(man)o(y)f(instances)g +(of)h(a)g(single)0 568 y(de\002nition.)34 b(Magic)26 +b(will)f(create)i(def)o(ault)f(instance)g(id')-5 b(s)25 +b(for)i(you)f(when)g(you)f(create)i(ne)n(w)f(instances)g(with)f(the)0 +689 y Fa(:get)k Fc(or)g Fa(:copy)g Fc(commands.)40 b(The)29 +b(def)o(ault)f(id)g(for)h(an)f(instance)h(will)e(be)i(the)f(name)h(of)f +(the)g(de\002nition)g(with)g(a)0 809 y(unique)d(inte)o(ger)g(added)h +(on.)33 b(Y)-11 b(ou)26 b(can)g(change)g(an)g(id)f(by)g(selecting)h(an) +f(instance)h(\(which)f(must)g(be)h(a)g(child)f(of)0 930 +y(the)g(edit)f(cell\))h(and)g(in)l(v)n(oking)e(the)i(command)900 +1178 y Fa(:identify)h Fd(ne)o(wid)146 1424 y Fc(where)k +Fd(ne)o(wid)f Fc(is)g(the)g(identi\002er)g(you)f(w)o(ould)h(lik)o(e)f +(the)h(instance)g(to)g(ha)n(v)o(e.)43 b Fd(Ne)o(wid)30 +b Fc(must)e(not)g(already)i(be)0 1544 y(used)25 b(as)f(an)h(instance)g +(identi\002er)f(of)h(an)o(y)g(subcell)f(within)f(the)i(edit)f(cell.)146 +1667 y(An)o(y)d(node)g(or)g(instance)g(can)h(be)f(described)g(uniquely) +f(by)h(listing)f(a)h(path)g(of)h(instance)f(identi\002ers,)g(starting)0 +1788 y(from)29 b(the)g(root)f(cell.)44 b(The)29 b(standard)f(form)h(of) +g(such)g(names)g(is)g(similar)e(to)i(Unix)f(\002le)i(names.)43 +b(F)o(or)29 b(e)o(xample,)0 1908 y(if)f Fa(id1)h Fc(is)f(the)g(name)h +(of)f(an)h(instance)f(within)f(the)h(root)g(cell,)h Fa(id2)g +Fc(is)f(an)g(instance)h(within)e Fa(id1)p Fc(,)i(and)f +Fa(node)i Fc(is)e(a)0 2029 y(node)f(name)h(within)f Fa(id2)p +Fc(,)h(then)f Fa(id1/id2/node)h Fc(can)g(be)g(used)g(unambiguously)d +(to)i(refer)i(to)e(the)h(node.)39 b(When)0 2149 y(you)24 +b(select)h(a)g(cell,)g(Magic)f(prints)g(out)g(the)h(complete)f(path)h +(name)f(of)h(the)g(instance.)146 2272 y(Arrays)34 b(are)g(treated)g +(specially)-6 b(.)55 b(When)33 b(you)g(use)h Fa(:identify)g +Fc(to)f(gi)n(v)o(e)f(an)i(array)g(an)f(instance)g(identi\002er)l(,)0 +2392 y(each)h(element)g(of)g(the)g(array)g(is)g(gi)n(v)o(en)e(the)i +(instance)f(identi\002er)h(you)f(speci\002ed,)k(follo)n(wed)32 +b(by)i(one)g(or)g(tw)o(o)0 2513 y(array)39 b(subscripts)e(enclosed)i +(in)f(square)g(brack)o(ets,)k(e.g,)g Fa(id3[2])d Fc(or)g +Fa(id4[3][7])p Fc(.)72 b(When)38 b(the)h(array)g(is)f(one-)0 +2633 y(dimensional,)31 b(there)h(is)f(a)h(single)e(subscript;)k(when)d +(it)g(is)g(tw)o(o-dimensional,)g(the)g(\002rst)h(subscript)e(is)h(for)h +(the)0 2753 y(y-dimension)23 b(and)i(the)f(second)h(for)g(the)g +(x-dimension.)0 3109 y Fe(7)143 b(Writing)35 b(and)g(Flushing)f(Cells)0 +3338 y Fc(When)22 b(you)f(mak)o(e)g(changes)h(to)f(your)h(circuit)f(in) +g(Magic,)h(there)g(is)f(no)h(immediate)e(ef)n(fect)i(on)f(the)h(disk)f +(\002les)h(that)0 3458 y(hold)f(the)g(cells.)30 b(Y)-11 +b(ou)21 b(must)f(e)o(xplicitly)g(sa)n(v)o(e)h(each)h(cell)g(that)f(has) +g(changed,)i(using)d(either)i(the)f Fa(:sa)n(v)o(e)g +Fc(command)0 3579 y(or)g(the)h Fa(:writeall)f Fc(command.)28 +b(Magic)21 b(k)o(eeps)h(track)f(of)h(the)f(cells)g(that)g(ha)n(v)o(e)g +(changed)g(since)g(the)h(last)e(time)h(the)o(y)0 3699 +y(were)30 b(sa)n(v)o(ed)f(on)g(disk.)44 b(If)30 b(you)f(try)g(to)g(lea) +n(v)o(e)g(Magic)g(without)f(sa)n(ving)h(all)g(the)g(cells)h(that)f(ha)n +(v)o(e)g(changed,)h(the)0 3819 y(system)24 b(will)h(w)o(arn)h(you)f +(and)g(gi)n(v)o(e)f(you)h(a)h(chance)g(to)f(return)h(to)f(Magic)g(to)g +(sa)n(v)o(e)g(them.)32 b(Magic)25 b(ne)n(v)o(er)g(\003ushes)0 +3940 y(cells)33 b(behind)g(your)g(back,)j(and)d(ne)n(v)o(er)g(thro)n +(ws)f(a)o(w)o(ay)h(de\002nitions)f(that)h(it)g(has)g(read)h(in.)56 +b(Thus,)35 b(if)f(you)f(edit)0 4060 y(a)f(cell)g(and)g(then)g(use)g +Fa(:load)g Fc(to)g(edit)f(another)h(cell,)i(the)e(\002rst)g(cell)g(is)g +(still)f(sa)n(v)o(ed)g(in)h(Magic)f(e)n(v)o(en)h(though)f(it)0 +4181 y(doesn')n(t)d(appear)h(an)o(ywhere)f(on)g(the)h(screen.)42 +b(If)29 b(you)f(then)g(in)l(v)n(ok)o(e)f Fa(:load)i Fc(a)g(second)f +(time)f(to)h(go)h(back)f(to)g(the)0 4301 y(\002rst)d(cell,)g(you')o(ll) +f(get)g(the)h(edited)f(cop)o(y)-6 b(.)146 4424 y(If)31 +b(you)e(decide)h(that)f(you')-5 b(d)29 b(really)h(lik)o(e)f(to)h +(discard)f(the)h(edits)f(you')-5 b(v)o(e)29 b(made)h(to)f(a)h(cell)g +(and)g(reco)o(v)o(er)f(the)0 4544 y(old)d(v)o(ersion,)g(there)g(are)i +(tw)o(o)e(w)o(ays)g(you)g(can)h(do)f(it.)35 b(The)27 +b(\002rst)f(w)o(ay)h(is)f(using)f(the)i Fa(\003ush)g +Fc(option)e(in)h Fa(:writeall)p Fc(.)0 4665 y(The)f(second)f(w)o(ay)h +(is)g(to)f(use)h(the)f(command)900 4913 y Fa(:\003ush)i +Fc([)p Fd(cellname)p Fc(])146 5159 y(If)34 b(no)f Fd(cellname)g +Fc(is)g(gi)n(v)o(en,)h(then)f(the)g(edit)g(cell)g(is)g(\003ushed.)56 +b(Otherwise,)35 b(the)e(cell)g(named)g Fd(cellname)h +Fc(is)0 5280 y(\003ushed.)48 b(The)31 b Fa(:\003ush)h +Fc(command)e(will)f(e)o(xpunge)h(Magic')-5 b(s)30 b(internal)g(cop)o(y) +h(of)f(the)h(cell)g(and)f(replace)i(it)e(with)0 5400 +y(the)25 b(disk)f(cop)o(y)-6 b(.)1875 5649 y(\2266\226)p +eop +%%Page: 7 7 +7 6 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#4:)30 b(Cell)25 +b(Hierarchies)1671 b(September)25 b(26,)g(2001)146 68 +y(When)k(you)f(are)h(editing)e(lar)n(ge)i(chips,)g(Magic)f(may)g(claim) +g(that)g(cells)g(ha)n(v)o(e)g(changed)h(e)n(v)o(en)e(though)h(you)0 +188 y(ha)n(v)o(en')n(t)h(modi\002ed)f(them.)43 b(Whene)n(v)o(er)28 +b(you)h(modify)e(a)j(cell,)g(Magic)e(mak)o(es)h(changes)g(in)g(the)f +(parents)h(of)g(the)0 309 y(cell,)24 b(and)f(their)g(parents,)h(and)f +(so)g(on)h(up)f(to)g(the)g(root)g(of)h(the)f(hierarchy)-6 +b(.)30 b(These)23 b(changes)h(record)g(ne)n(w)f(design-)0 +429 y(rule)f(violations,)e(as)i(well)g(as)f(timestamp)f(and)i(bounding) +e(box)i(information)e(used)i(by)f(Magic)h(to)f(k)o(eep)h(track)g(of)0 +549 y(design)k(changes)h(and)g(enable)f(f)o(ast)h(cell)g(read-in.)37 +b(Thus,)26 b(whene)n(v)o(er)h(you)f(change)h(one)g(cell)f(you')o(ll)g +(generally)0 670 y(need)f(to)g(write)g(out)g(ne)n(w)g(copies)g(of)g +(its)f(parents)h(and)g(grandparents.)32 b(If)26 b(you)e(don')n(t)h +(write)g(out)g(the)g(parents,)g(or)0 790 y(if)k(you)g(edit)g(a)g(child) +g(\223out)g(of)g(conte)o(xt\224)f(\(by)i(itself,)f(without)f(the)h +(parents)g(loaded\),)h(then)f(you')o(ll)f(incur)h(e)o(xtra)0 +911 y(o)o(v)o(erhead)i(the)g(ne)o(xt)f(time)h(you)g(try)g(to)g(edit)f +(the)i(parents.)50 b(\223T)m(imestamp)29 b(mismatch\224)h(w)o(arnings)h +(are)h(printed)0 1031 y(when)f(you')-5 b(v)o(e)31 b(edited)g(cells)h +(out)e(of)i(conte)o(xt)e(and)i(then)f(later)h(go)f(back)h(and)f(read)h +(in)f(the)h(cell)f(as)h(part)f(of)h(its)0 1151 y(parent.)52 +b(These)32 b(aren')n(t)h(serious)e(problems;)j(the)o(y)e(just)f(mean)g +(that)h(Magic)g(is)f(doing)g(e)o(xtra)h(w)o(ork)g(to)f(update)0 +1272 y(information)23 b(in)i(the)f(parent)h(to)g(re\003ect)h(the)e +(child')-5 b(s)24 b(ne)n(w)g(state.)0 1610 y Fe(8)143 +b(Sear)m(ch)35 b(P)o(aths)0 1833 y Fc(When)29 b(man)o(y)e(people)i(are) +g(w)o(orking)f(on)g(a)h(lar)n(ge)g(design,)g(the)f(design)g(will)g +(probably)g(be)h(more)f(manageable)0 1954 y(if)j(dif)n(ferent)g(pieces) +h(of)f(it)g(can)h(be)f(located)h(in)f(dif)n(ferent)g(directories)g(of)g +(the)g(\002le)h(system.)49 b(Magic)31 b(pro)o(vides)0 +2074 y(a)d(simple)f(mechanism)g(for)i(managing)e(designs)g(spread)h(o)o +(v)o(er)g(se)n(v)o(eral)f(directories.)40 b(The)29 b(system)e +(maintains)0 2195 y(a)33 b Fd(sear)l(c)o(h)f(path)g Fc(that)g(tells)g +(which)g(directories)h(to)f(search)h(when)g(trying)e(to)i(read)g(in)f +(cells.)54 b(By)33 b(def)o(ault,)h(the)0 2315 y(search)c(path)f(is)h +(\223.)-7 b(\224,)31 b(which)e(means)g(that)g(Magic)g(looks)g(only)g +(in)g(the)h(w)o(orking)e(directory)-6 b(.)45 b(Y)-11 +b(ou)29 b(can)h(change)0 2435 y(the)25 b(path)f(using)g(the)h(command) +900 2654 y Fa(:path)h Fc([)p Fd(sear)l(c)o(hpath)p Fc(])146 +2872 y(where)40 b Fd(sear)l(c)o(hpath)e Fc(is)h(the)g(ne)n(w)g(path)g +(that)g(Magic)g(should)f(use.)74 b Fd(Sear)l(c)o(hpath)38 +b Fc(consists)g(of)h(a)h(list)e(of)0 2992 y(directories)d(separated)h +(by)g(colons.)63 b(F)o(or)36 b(e)o(xample,)h(the)f(path)f +(\223.:\230ouster/x:a/b\224)g(means)g(that)g(if)h(Magic)g(is)0 +3113 y(trying)d(to)g(read)h(in)f(a)h(cell)f(named)g(\223foo\224,)j(it)d +(will)g(\002rst)h(look)e(for)i(a)g(\002le)g(named)f(\223foo.mag\224)g +(in)h(the)f(current)0 3233 y(directory)-6 b(.)57 b(If)34 +b(it)g(doesn')n(t)f(\002nd)h(the)g(\002le)g(there,)i(it)d(will)g(look)g +(for)i(a)f(\002le)g(named)f(\223\230ouster/x/foo.mag\224,)i(and)0 +3354 y(if)29 b(that)g(doesn')n(t)g(e)o(xist,)g(then)g(it)g(will)f(try)h +(\223a/b/foo.mag\224)g(last.)44 b(T)-8 b(o)29 b(\002nd)g(out)g(what)g +(the)g(current)h(path)f(is,)g(type)0 3474 y Fa(:path)k +Fc(with)f(no)g(ar)n(guments.)53 b(In)32 b(addition)f(to)h(your)g(path,) +i(this)d(command)h(will)f(print)h(out)g(the)g(system)f(cell)0 +3594 y(library)k(path)g(\(where)i(Magic)e(looks)f(for)i(cells)f(if)h +(it)f(can')n(t)h(\002nd)f(them)g(an)o(ywhere)h(in)f(your)g(path\),)j +(and)d(the)0 3715 y(system)23 b(search)h(path)g(\(where)g(Magic)g +(looks)e(for)j(\002les)f(lik)o(e)f(colormaps)g(and)h(technology)e +(\002les)j(if)e(it)h(can')n(t)g(\002nd)0 3835 y(them)g(in)h(your)f +(current)h(directory\).)146 3955 y(If)h(you')-5 b(re)25 +b(w)o(orking)g(on)g(a)g(lar)n(ge)h(design,)e(you)h(should)f(use)h(the)g +(search)h(path)f(mechanism)f(to)h(spread)g(your)0 4076 +y(layout)h(o)o(v)o(er)g(se)n(v)o(eral)g(directories.)36 +b(A)26 b(typical)g(lar)n(ge)i(chip)e(will)g(contain)g(a)h(fe)n(w)g +(hundred)f(cells;)h(if)g(you)f(try)g(to)0 4196 y(place)f(all)f(of)h +(them)f(in)g(the)h(same)f(directory)h(there)f(will)g(just)g(be)h(too)f +(man)o(y)f(things)h(to)g(manage.)30 b(F)o(or)25 b(e)o(xample,)0 +4317 y(place)f(the)g(datapath)g(in)f(one)h(directory)-6 +b(,)23 b(the)h(control)f(unit)h(in)f(another)l(,)h(the)g(instruction)e +(b)n(uf)n(fer)i(in)g(a)g(third,)f(and)0 4437 y(so)28 +b(on.)43 b(T)m(ry)28 b(to)h(k)o(eep)g(the)f(size)h(of)g(each)g +(directory)g(do)n(wn)f(to)g(a)h(fe)n(w)g(dozen)g(\002les.)43 +b(Y)-11 b(ou)28 b(can)h(place)g(the)g Fa(:path)0 4557 +y Fc(command)e(in)h(a)h Fa(.magic)f Fc(\002le)h(in)f(your)g(home)g +(directory)g(or)g(the)g(directory)g(you)g(normally)f(run)i(Magic)f +(from;)0 4678 y(this)d(will)g(sa)n(v)o(e)h(you)g(from)g(ha)n(ving)f(to) +h(retype)g(it)g(each)g(time)g(you)f(start)h(up)g(\(see)g(the)g(Magic)g +(man)g(page)g(to)g(\002nd)0 4798 y(out)k(about)f Fa(.magic)h +Fc(\002les\).)47 b(If)31 b(all)f(you)f(w)o(ant)h(to)g(do)g(is)g(add)g +(another)g(directory)g(onto)f(the)h(end)g(of)h(the)f(search)0 +4918 y(path,)24 b(you)h(can)g(use)g(the)f Fa(:addpath)j +Fc([)p Fd(dir)l(ectory)p Fc(])e(command.)146 5039 y(Because)c(there)f +(is)g(only)f(a)h(single)f(search)i(path)e(that)h(is)f(used)h(e)n(v)o +(erywhere)f(in)h(Magic,)g(you)g(must)e(be)i(careful)0 +5159 y(not)28 b(to)f(re-use)i(the)f(same)g(cell)g(name)g(in)g(dif)n +(ferent)g(portions)e(of)j(the)f(chip.)40 b(A)28 b(common)f(problem)g +(with)h(lar)n(ge)0 5280 y(designs)23 b(is)h(that)f(dif)n(ferent)h +(designers)f(use)h(the)g(same)g(name)g(for)g(dif)n(ferent)g(cells.)30 +b(This)23 b(w)o(orks)h(\002ne)h(as)f(long)f(as)0 5400 +y(the)i(designers)g(are)i(w)o(orking)d(separately)-6 +b(,)25 b(b)n(ut)g(when)h(the)f(tw)o(o)g(pieces)h(of)g(the)f(design)g +(are)h(put)f(together)g(using)1875 5649 y(\2267\226)p +eop +%%Page: 8 8 +8 7 bop 0 -180 a Fc(September)25 b(26,)f(2001)1671 b(Magic)24 +b(T)l(utorial)g(#4:)30 b(Cell)25 b(Hierarchies)0 68 y(a)34 +b(search)g(path,)i(a)e(single)e(cop)o(y)i(of)g(the)f(cell)h(\(the)g +(one)f(that)g(is)h(found)f(\002rst)h(in)f(the)g(search)i(path\))e(gets) +g(used)0 188 y(e)n(v)o(erywhere.)146 309 y(There')-5 +b(s)34 b(another)g(ca)n(v)o(eat)g(in)g(the)f(use)h(of)g(search)h +(paths.)58 b(Magic)33 b(looks)g(for)h(system)f(\002les)h(in)g(\230cad,) +j(b)n(ut)0 429 y(sometimes)26 b(it)h(is)h(helpful)f(to)h(put)f(Magic') +-5 b(s)27 b(system)f(\002les)i(else)n(where.)40 b(If)29 +b(the)e Fa(CAD)p 2977 429 30 4 v 36 w(HOME)g Fc(shell)g(en)l(viron-)0 +549 y(ment)35 b(v)n(ariable)g(is)g(set,)j(then)e(Magic)f(uses)g(that)g +(as)h(the)g(location)e(of)i(\230cad)g(instead)f(of)h(the)f(location)g +(in)g(the)0 670 y(passw)o(ord)28 b(\002le.)44 b(This)28 +b(o)o(v)o(errides)f(all)i(uses)f(of)h(\230cad)h(within)d(magic,)j +(including)d(the)i(\230cad)g(seen)g(in)g(the)g(search)0 +790 y(paths)24 b(printed)g(out)h(by)f Fa(:path)p Fc(.)0 +1130 y Fe(9)143 b(Additional)34 b(Commands)0 1353 y Fc(This)c(section)h +(describes)g(a)h(fe)n(w)f(additional)f(cell-related)h(commands)f(that)h +(you)g(may)g(\002nd)g(useful.)50 b(One)31 b(of)0 1474 +y(them)24 b(is)h(the)f(command)900 1702 y Fa(:select)h(sa)n(v)o(e)f +Fd(\002le)146 1930 y Fc(This)g(command)g(tak)o(es)h(the)f(selection)g +(and)h(writes)g(it)f(to)g(disk)g(as)h(a)g(ne)n(w)f(Magic)h(cell)g(in)f +(the)h(\002le)g Fd(\002le)p Fa(.mag)p Fc(.)0 2051 y(Y)-11 +b(ou)32 b(can)g(use)g(this)f(command)g(to)h(break)g(up)g(a)g(big)f +(\002le)i(into)e(smaller)g(ones,)j(or)e(to)f(e)o(xtract)h(pieces)g +(from)g(an)0 2171 y(e)o(xisting)23 b(cell.)146 2291 y(The)i(command)900 +2520 y Fa(:dump)h Fd(cellName)f Fc([)p Fd(labelName)p +Fc(])146 2748 y(does)h(the)f(opposite)g(of)g Fa(select)h(sa)n(v)o(e)p +Fc(:)32 b(it)25 b(copies)g(the)h(contents)f(of)g(cell)h +Fd(cellName)g Fc(into)f(the)g(edit)h(cell,)f(such)0 2868 +y(that)20 b(the)f(lo)n(wer)n(-left)h(corner)g(of)g(label)g +Fd(labelName)g Fc(is)g(at)g(the)f(lo)n(wer)n(-left)h(corner)g(of)g(the) +g(box.)29 b(The)20 b(ne)n(w)g(material)0 2989 y(will)h(also)g(be)h +(selected.)30 b(This)21 b(command)f(is)i(similar)e(in)i(form)f(to)g +(the)h Fa(getcell)g Fc(command)f(e)o(xcept)g(that)g(it)g(copies)0 +3109 y(the)j(contents)f(of)h(the)g(cell)g(instead)f(of)h(using)f(the)h +(cell)g(as)g(a)h(subcell.)k(There)c(are)g(se)n(v)o(eral)e(forms)g(of)i +Fa(dump)p Fc(;)g(see)0 3230 y(the)g Fd(man)f Fc(page)h(for)g(details.) +146 3350 y(The)g(main)f(purpose)g(of)h Fa(dump)h Fc(is)e(to)h(allo)n(w) +e(you)i(to)f(create)i(a)f(library)f(of)h(cells)f(representing)h +(commonly-)0 3470 y(used)19 b(structures)g(such)g(as)h(standard)f +(transistor)f(shapes)i(or)f(special)h(contact)f(arrangements.)29 +b(Y)-11 b(ou)19 b(can)h(then)f(de-)0 3591 y(\002ne)24 +b(macros)g(that)f(in)l(v)n(ok)o(e)g(the)g Fa(dump)i Fc(command)e(to)g +(place)h(the)f(cells.)30 b(The)24 b(result)f(is)g(that)g(a)h(single)f +(k)o(e)o(ystrok)o(e)0 3711 y(is)h(all)h(you)f(need)h(to)g(cop)o(y)f +(one)h(of)g(them)f(into)g(the)h(edit)f(cell.)146 3831 +y(As)35 b(mentioned)e(earlier)l(,)k(Magic)d(normally)f(displays)g(the)i +(edit)f(cell)g(in)g(brighter)g(colors)g(than)g(non-edit)0 +3952 y(cells.)i(This)26 b(helps)h(to)f(distinguish)e(what)j(is)f +(editable)g(from)h(what)g(is)f(not,)h(b)n(ut)f(may)g(mak)o(e)h(it)f +(hard)h(for)g(you)f(to)0 4072 y(vie)n(w)e(non-edit)g(paint)g(since)h +(it)f(appears)h(paler)-5 b(.)31 b(If)25 b(you)f(type)h(the)f(command) +900 4301 y Fa(:see)h(allSame)146 4529 y Fc(you')o(ll)19 +b(turn)h(of)n(f)g(this)f(feature:)29 b(all)19 b(paint)h(e)n(v)o +(erywhere)g(will)f(be)h(displayed)f(in)h(the)f(bright)h(colors.)28 +b(The)20 b(w)o(ord)0 4649 y Fa(allSame)29 b Fc(must)f(be)h(typed)g +(just)f(that)h(w)o(ay)-6 b(,)29 b(with)g(one)g(capital)g(letter)-5 +b(.)43 b(If)29 b(you')-5 b(d)29 b(lik)o(e)f(to)h(restore)h(the)e(dif)n +(ferent)0 4770 y(display)c(styles,)f(type)i(the)g(command)900 +4998 y Fa(:see)g(no)g(allSame)146 5226 y Fc(Y)-11 b(ou)34 +b(can)h(also)f(use)g(the)h Fa(:see)g Fc(command)e(to)h(selecti)n(v)o +(ely)f(disable)g(display)h(of)g(v)n(arious)f(mask)h(layers)g(in)0 +5347 y(order)25 b(to)g(mak)o(e)f(the)h(other)g(ones)f(easier)h(to)g +(see.)31 b(F)o(or)24 b(details,)g(read)i(about)e Fa(:see)h +Fc(in)g(the)f(Magic)h(man)f(page.)1875 5649 y(\2268\226)p +eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut5.ps b/doc/psfiles/tut5.ps new file mode 100644 index 00000000..9b74d495 --- /dev/null +++ b/doc/psfiles/tut5.ps @@ -0,0 +1,671 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tut5.dvi +%%Pages: 6 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tut5.dvi -o tut5.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut5.dvi) +@start /Fa 134[50 50 72 50 55 33 39 44 1[55 50 55 83 +28 2[28 55 50 33 44 55 44 55 50 3[33 1[33 6[66 4[78 72 +4[39 1[78 1[66 72 1[66 7[33 2[50 1[50 6[25 1[25 44[{ + TeXBase1Encoding ReEncodeFont }37 100.000003 /Times-Bold +rf /Fb 133[53 2[86 60 66 40 47 53 1[66 60 66 100 33 2[33 +66 60 40 53 66 53 1[60 9[120 2[80 66 86 2[93 1[113 9[86 +8[40 4[60 60 60 60 60 2[30 42[66 66 2[{ TeXBase1Encoding ReEncodeFont } +36 119.999948 /Times-Bold rf /Fc 104[100 50 1[44 44 24[44 +50 50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 +50 33 44 50 44 50 44 3[33 1[33 1[72 72 94 72 72 61 55 +2[55 72 72 89 61 1[39 33 72 72 55 61 72 66 66 72 1[44 +3[28 28 50 50 50 50 50 50 50 50 50 50 1[25 33 25 56 1[33 +33 33 1[83 1[50 1[33 29[55 55 2[{ TeXBase1Encoding ReEncodeFont }79 +100.000003 /Times-Roman rf /Fd 134[44 2[44 50 28 39 39 +1[50 50 50 72 28 2[28 50 50 1[44 50 44 50 50 11[72 55 +50 61 3[66 83 30[25 1[25 2[33 33 37[50 2[{ + TeXBase1Encoding ReEncodeFont }30 100.000003 /Times-Italic +rf /Fe 136[104 1[80 48 56 64 1[80 72 80 120 40 80 1[40 +1[72 48 64 80 64 1[72 9[143 2[96 80 5[135 3[56 112 2[96 +1[104 8[48 4[72 72 72 72 72 13[72 35[{ TeXBase1Encoding ReEncodeFont } +33 143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 791 101 a Fe(Magic)35 b(T)-13 b(utorial)34 b(#5:)43 +b(Multiple)35 b(W)m(indo)o(ws)1630 521 y Fd(Robert)24 +b(N.)i(Mayo)1401 941 y Fc(Computer)e(Science)i(Di)n(vision)1020 +1062 y(Electrical)f(Engineering)f(and)h(Computer)f(Sciences)1473 +1182 y(Uni)n(v)o(ersity)f(of)i(California)1544 1303 y(Berk)o(ele)o(y)-6 +b(,)24 b(CA)h(94720)1448 1573 y Fd(\(Updated)f(by)h(other)o(s,)f +(too.\))1053 1843 y Fc(This)g(tutorial)g(corresponds)g(to)g(Magic)h(v)o +(ersion)e(7.)0 2336 y Fb(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:) +300 2513 y Fc(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)300 2633 y(Magic)g(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)0 2810 y Fb(Commands)k(intr)n(oduced)j +(in)f(this)f(tutorial:)300 2987 y Fc(:center)25 b(:close)n(windo)n(w)-6 +b(,)22 b(:openwindo)n(w)-6 b(,)22 b(:o)o(v)o(er)l(,)i(:specialopen,)f +(:under)l(,)i(:windo)n(wpositions)0 3164 y Fb(Macr)n(os)k(intr)n +(oduced)i(in)g(this)f(tutorial:)300 3356 y Fc(o,)25 b(O,)f(\223,)-7 +b(\224)0 4213 y Fe(1)143 b(Intr)m(oduction)0 4437 y Fc(A)25 +b(windo)n(w)f(is)h(a)g(rectangular)h(vie)n(wport.)31 +b(Y)-11 b(ou)25 b(can)g(think)f(of)i(it)f(as)g(a)g(magnifying)f(glass)h +(that)g(may)f(be)i(mo)o(v)o(ed)0 4557 y(around)32 b(on)h(your)f(chip.) +53 b(Magic)32 b(initially)f(displays)g(a)i(single)f(windo)n(w)f(on)h +(the)g(screen.)55 b(This)32 b(tutorial)f(will)0 4678 +y(sho)n(w)23 b(you)h(ho)n(w)g(to)g(create)h(ne)n(w)f(windo)n(ws)f(and)h +(ho)n(w)g(to)g(mo)o(v)o(e)e(old)i(ones)g(around.)31 b(Multiple)22 +b(windo)n(ws)h(allo)n(w)0 4798 y(you)h(to)h(vie)n(w)f(se)n(v)o(eral)g +(portions)f(of)i(a)g(circuit)g(at)g(the)f(same)h(time,)f(or)h(e)n(v)o +(en)f(portions)f(of)i(dif)n(ferent)g(circuits.)146 4918 +y(Some)34 b(operations)f(are)i(easier)f(with)f(multiple)f(windo)n(ws.) +56 b(F)o(or)34 b(e)o(xample,)h(let')-5 b(s)33 b(say)g(that)h(you)f(w)o +(ant)g(to)0 5039 y(paint)c(a)h(v)o(ery)f(long)g(line,)i(say)e(3)h +(units)e(by)i(800)f(units.)44 b(W)l(ith)29 b(a)h(single)f(windo)n(w)f +(it)i(is)f(hard)h(to)f(align)g(the)h(box)0 5159 y(accurately)g(since)e +(the)h(magni\002cation)f(is)h(not)g(great)g(enough.)43 +b(W)l(ith)28 b(multiple)g(windo)n(ws,)g(one)h(windo)n(w)f(can)0 +5280 y(sho)n(w)c(the)g(big)g(picture)h(while)f(other)g(windo)n(ws)f +(sho)n(w)h(magni\002ed)g(vie)n(ws)g(of)g(the)h(areas)g(where)g(the)g +(box)f(needs)0 5400 y(to)g(be)h(aligned.)30 b(The)25 +b(box)g(can)g(then)f(be)h(positioned)e(accurately)j(in)e(these)h +(magni\002ed)f(windo)n(ws.)1875 5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fc(September)25 b(26,)f(2001)1577 b(Magic)25 +b(T)l(utorial)e(#5:)30 b(Multiple)24 b(W)l(indo)n(ws)0 +99 y Fe(2)143 b(Manipulating)34 b(W)m(indo)o(ws)0 356 +y Fb(2.1)119 b(Opening)31 b(and)g(Closing)f(W)n(indo)o(ws)0 +548 y Fc(Initially)23 b(Magic)i(displays)e(one)i(lar)n(ge)g(windo)n(w) +-6 b(.)29 b(The)900 793 y Fa(:openwindo)o(w)d Fc([)p +Fd(cellname)p Fc(])146 1036 y(command)31 b(opens)h(another)g(windo)n(w) +e(and)i(loads)g(the)g(gi)n(v)o(en)e(cell.)52 b(T)-8 b(o)32 +b(gi)n(v)o(e)f(this)g(a)h(try)-6 b(,)33 b(start)f(up)f(Magic)0 +1157 y(with)24 b(the)i(command)e Fa(magic)h(tut5a)p Fc(.)32 +b(Then)25 b(point)g(an)o(ywhere)g(in)g(a)g(Magic)g(windo)n(w)f(and)h +(type)g(the)g(command)0 1277 y Fa(:openwindo)o(w)i(tut5b)h +Fc(\(mak)o(e)e(sure)g(you')-5 b(re)26 b(pointing)e(to)i(a)h(Magic)e +(windo)n(w\).)34 b(A)26 b(ne)n(w)g(windo)n(w)e(will)h(appear)0 +1398 y(and)j(it)f(will)f(contain)h(the)h(cell)f Fa(tut5b)p +Fc(.)40 b(If)28 b(you)f(don')n(t)h(gi)n(v)o(e)e(a)i Fd(cellname)f +Fc(ar)n(gument)g(to)g Fa(:openwindo)o(w)p Fc(,)j(it)d(will)0 +1518 y(open)33 b(a)g(ne)n(w)f(windo)n(w)g(on)g(the)h(cell)g(containing) +f(the)g(box,)j(and)e(will)f(zoom)g(in)g(on)h(the)g(box.)54 +b(The)33 b(macro)g Fa(o)0 1638 y Fc(is)28 b(prede\002ned)i(to)e +Fa(:openwindo)o(w)p Fc(.)44 b(T)m(ry)28 b(this)g(out)g(by)g(placing)g +(the)h(box)f(around)h(an)f(area)i(of)f Fa(tut5b)h Fc(and)e(then)0 +1759 y(typing)e Fa(o)p Fc(.)37 b(Another)26 b(windo)n(w)g(will)g +(appear)-5 b(.)37 b(Y)-11 b(ou)27 b(no)n(w)f(ha)n(v)o(e)h(three)g +(windo)n(ws,)f(all)h(of)g(which)f(display)g(pieces)0 +1879 y(of)g(layout.)34 b(There)27 b(are)g(other)f(kinds)f(of)i(windo)n +(ws)d(in)i(Magic)g(besides)g(layout)f(windo)n(ws:)32 +b(you')o(ll)25 b(learn)i(about)0 1999 y(them)21 b(later)-5 +b(.)30 b(Magic)21 b(doesn')n(t)h(care)h(ho)n(w)e(man)o(y)g(windo)n(ws)f +(you)i(ha)n(v)o(e)f(\(within)g(reason\))h(nor)g(ho)n(w)f(the)o(y)g(o)o +(v)o(erlap.)146 2122 y(T)-8 b(o)25 b(get)g(rid)f(of)h(a)g(windo)n(w)-6 +b(,)23 b(point)h(to)g(it)h(and)f(type)900 2367 y Fa(:closewindo)o(w)146 +2610 y Fc(or)h(use)g(the)g(macro)f Fa(O)p Fc(.)h(Point)f(to)g(a)i +(portion)d(of)i(the)g(original)f(windo)n(w)f(and)i(close)g(it.)0 +2919 y Fb(2.2)119 b(Resizing)31 b(and)f(Mo)o(ving)g(W)n(indo)o(ws)0 +3111 y Fc(If)24 b(you)f(ha)n(v)o(e)g(been)h(e)o(xperimenting)d(with)i +(Magic)g(while)g(reading)g(this)f(you)h(will)g(ha)n(v)o(e)g(noticed)g +(that)g(windo)n(ws)0 3232 y(opened)33 b(by)f Fa(:openwindo)o(w)i +Fc(are)f(all)g(the)f(same)h(size.)54 b(If)33 b(you')-5 +b(d)33 b(prefer)g(a)g(dif)n(ferent)g(arrangement)f(you)h(can)0 +3352 y(resize)21 b(your)f(windo)n(ws)f(or)i(mo)o(v)o(e)e(them)h(around) +g(on)g(the)h(screen.)29 b(The)21 b(techniques)f(used)g(for)h(this)e +(are)j(dif)n(ferent,)0 3472 y(ho)n(we)n(v)o(er)l(,)g(depending)g(on)h +(what)g(kind)f(of)h(display)f(you')-5 b(re)23 b(using.)29 +b(If)23 b(you)g(are)h(using)e(a)h(w)o(orkstation,)f(then)h(you)0 +3593 y(are)35 b(also)e(running)g(a)i(windo)n(w)d(system)h(such)h(as)g +(X11)f(or)h(SunV)-6 b(ie)n(w)g(.)57 b(In)34 b(this)f(case)i(Magic')-5 +b(s)33 b(windo)n(ws)f(are)0 3713 y(mo)o(v)o(ed)20 b(and)i(resized)h +(just)e(lik)o(e)g(the)h(other)g(windo)n(ws)e(you)i(ha)n(v)o(e)g +(displayed,)f(and)h(you)g(can)g(skip)f(the)h(rest)g(of)g(this)0 +3834 y(section.)146 3956 y(F)o(or)36 b(displays)e(lik)o(e)h(the)g(AED)g +(f)o(amily)-6 b(,)37 b(which)e(don')n(t)g(ha)n(v)o(e)g(a)h(b)n(uilt-in) +e(windo)n(w)g(package,)39 b(Magic)c(im-)0 4076 y(plements)27 +b(its)g(o)n(wn)g(windo)n(w)g(manager)-5 b(.)39 b(T)-8 +b(o)28 b(re-arrange)h(windo)n(ws)d(on)i(the)g(screen)g(you)g(can)g(use) +g(techniques)0 4197 y(similar)g(to)h(those)g(you)g(learned)h(for)g(mo)o +(ving)d(the)j(box)f(for)g(painting)g(operations.)43 b(Point)29 +b(some)n(where)g(in)g(the)0 4317 y(border)d(area)g(of)g(a)g(windo)n(w) +-6 b(,)23 b(e)o(xcept)j(for)f(the)h(lo)n(wer)f(left)g(corner)l(,)h(and) +g(press)f(and)h(hold)e(the)i(right)e(b)n(utton.)32 b(The)0 +4438 y(cursor)25 b(will)f(change)h(to)f(a)h(shape)g(lik)o(e)f(this:)p +1790 4596 320 4 v 1948 4716 4 121 v 2108 4716 V 1790 +4719 320 4 v 1948 4840 4 121 v 2108 4840 V 146 5039 a(This)36 +b(indicates)g(that)g(you)g(ha)n(v)o(e)g(hold)f(of)i(the)f(upper)h +(right)e(corner)i(of)g(the)f(windo)n(w)-6 b(.)64 b(Point)36 +b(to)g(a)h(ne)n(w)0 5159 y(location)29 b(for)h(this)f(corner)h(and)g +(release)g(the)g(b)n(utton.)44 b(The)29 b(windo)n(w)g(will)g(change)h +(shape)f(so)h(that)f(the)h(corner)0 5280 y(mo)o(v)o(es.)j(No)n(w)25 +b(point)h(to)f(the)h(border)h(area)g(and)f(press)g(and)g(hold)f(the)h +(left)g(b)n(utton.)34 b(The)26 b(cursor)g(will)g(no)n(w)f(look)0 +5400 y(lik)o(e:)1875 5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#5:)30 b(Multiple)23 +b(W)l(indo)n(ws)1576 b(September)25 b(26,)g(2001)p 1790 +3 320 4 v 1788 124 4 121 v 1948 124 V 2108 124 V 1790 +127 320 4 v 1788 247 4 121 v 1948 247 V 2108 247 V 1790 +251 320 4 v 146 465 a(This)34 b(indicates)f(that)h(you)f(ha)n(v)o(e)h +(hold)g(of)g(the)g(entire)g(windo)n(w)f(by)h(its)f(lo)n(wer)h(left)g +(windo)n(w)-6 b(.)57 b(Mo)o(v)o(e)32 b(the)0 586 y(cursor)h(and)g +(release)g(the)g(b)n(utton.)53 b(The)33 b(windo)n(w)e(will)h(mo)o(v)o +(e)g(so)g(that)h(its)f(lo)n(wer)g(left)h(corner)g(is)f(where)i(you)0 +706 y(pointed.)146 831 y(The)d(other)g(b)n(utton)f(commands)g(for)h +(positioning)e(the)i(box)f(by)h(an)o(y)g(of)g(its)f(corners)i(also)e(w) +o(ork)h(for)g(win-)0 951 y(do)n(ws.)f(Just)24 b(remember)g(to)h(point)e +(to)i(the)g(border)f(of)h(a)g(windo)n(w)f(before)h(pushing)f(the)g(b)n +(uttons.)146 1076 y(The)29 b(middle)e(b)n(utton)h(can)h(be)g(used)f(to) +g(gro)n(w)g(a)h(windo)n(w)e(up)i(to)f(full-screen)g(size.)43 +b(T)-8 b(o)28 b(try)g(this,)h(click)f(the)0 1196 y(middle)22 +b(b)n(utton)g(o)o(v)o(er)g(the)h(caption)g(of)g(the)g(windo)n(w)-6 +b(.)29 b(The)23 b(windo)n(w)f(will)g(no)n(w)g(\002ll)h(the)g(entire)h +(screen.)30 b(Click)23 b(in)0 1316 y(the)i(caption)f(again)g(and)h(the) +f(windo)n(w)g(will)g(shrink)g(back)h(to)f(its)g(former)h(size.)0 +1639 y Fb(2.3)119 b(Shuf\003ing)32 b(W)n(indo)o(ws)0 +1836 y Fc(By)21 b(no)n(w)f(you)h(kno)n(w)e(ho)n(w)h(to)h(open,)g +(close,)h(and)e(resize)i(windo)n(ws.)27 b(This)20 b(is)h(suf)n +(\002cient)f(for)h(most)f(purposes,)h(b)n(ut)0 1956 y(sometimes)i(you)h +(w)o(ant)g(to)g(look)g(at)h(a)f(windo)n(w)g(that)g(is)g(co)o(v)o(ered)g +(up)g(by)g(another)g(windo)n(w)-6 b(.)29 b(The)c Fa(:under)o(neath)0 +2077 y Fc(and)g Fa(:o)o(v)o(er)g Fc(commands)f(help)g(with)g(this.)146 +2201 y(The)30 b Fa(:under)o(neath)i Fc(command)c(mo)o(v)o(es)f(the)j +(windo)n(w)e(that)h(you)f(are)j(pointing)c(at)j(underneath)f(all)g(of)g +(the)0 2322 y(other)d(windo)n(ws.)34 b(The)26 b Fa(:o)o(v)o(er)g +Fc(command)g(mo)o(v)o(es)e(the)i(windo)n(w)f(on)h(top)g(of)g(the)g +(rest.)36 b(Create)27 b(a)g(fe)n(w)f(windo)n(ws)0 2442 +y(that)38 b(o)o(v)o(erlap)g(and)g(then)h(use)f(these)g(commands)g(to)g +(mo)o(v)o(e)f(them)h(around.)72 b(Y)-11 b(ou')o(ll)38 +b(see)h(that)f(o)o(v)o(erlapping)0 2563 y(windo)n(ws)21 +b(beha)n(v)o(e)i(just)f(lik)o(e)g(sheets)g(of)h(paper:)30 +b(the)23 b(ones)f(on)h(top)f(obscure)h(portions)e(of)i(the)g(ones)f +(underneath.)0 2885 y Fb(2.4)119 b(Scr)n(olling)31 b(W)n(indo)o(ws)0 +3082 y Fc(Some)25 b(of)g(the)g(windo)n(ws)f(ha)n(v)o(e)h(thick)f(bars)i +(on)f(the)g(left)g(and)g(bottom)e(borders.)32 b(These)25 +b(are)h(called)f Fd(scr)l(oll)f(bar)o(s)p Fc(,)0 3202 +y(and)j(the)f(slugs)g(within)f(them)h(are)h(called)g +Fd(ele)o(vator)o(s)p Fc(.)35 b(The)27 b(size)f(and)h(position)e(of)i +(an)f(ele)n(v)n(ator)g(indicates)g(ho)n(w)0 3323 y(much)f(of)h(the)f +(layout)g(\(or)h(whate)n(v)o(er)f(is)g(in)h(the)f(windo)n(w\))g(is)g +(currently)h(visible.)32 b(If)26 b(an)g(ele)n(v)n(ator)e(\002lls)i(its) +f(scroll)0 3443 y(bar)l(,)k(then)e(all)h(of)f(the)h(layout)f(is)g +(visible)g(in)g(that)h(windo)n(w)-6 b(.)37 b(If)28 b(an)g(ele)n(v)n +(ator)f(\002lls)g(only)g(a)i(portion)d(of)i(the)g(scroll)0 +3563 y(bar)l(,)c(then)f(only)f(that)h(portion)g(of)g(the)g(layout)g(is) +g(visible.)29 b(The)23 b(position)f(of)h(the)g(ele)n(v)n(ator)g +(indicates)f(which)h(part)0 3684 y(is)28 b(visible\227if)f(it)h(is)h +(near)g(the)g(bottom,)f(you)g(are)h(vie)n(wing)f(the)g(bottom)f(part)i +(of)g(the)f(layout;)i(if)f(it)f(is)g(near)h(the)0 3804 +y(top,)c(you)g(are)h(vie)n(wing)e(the)i(top)e(part)i(of)f(the)h +(layout.)32 b(There)26 b(are)g(scroll)f(bars)g(for)h(both)f(the)g(v)o +(ertical)g(direction)0 3925 y(\(the)g(left)g(scroll)f(bar\))h(and)g +(the)g(horizontal)e(direction)h(\(the)h(bottom)f(scroll)g(bar\).)146 +4049 y(Besides)29 b(indicating)f(ho)n(w)g(much)h(is)f(visible,)h(the)g +(scroll)g(bars)g(can)g(be)g(used)g(to)g(change)g(the)g(vie)n(w)f(of)h +(the)0 4170 y(windo)n(w)-6 b(.)32 b(Clicking)26 b(the)f(middle)g(mouse) +g(b)n(utton)g(in)h(a)g(scroll)f(bar)i(mo)o(v)o(es)d(the)i(ele)n(v)n +(ator)f(to)g(that)h(position.)32 b(F)o(or)0 4290 y(e)o(xample,)d(if)g +(you)f(are)i(vie)n(wing)d(the)i(lo)n(wer)f(half)h(of)g(a)g(chip)g +(\(ele)n(v)n(ator)f(near)h(the)g(bottom\))e(and)i(you)g(click)f(the)0 +4410 y(middle)23 b(b)n(utton)h(near)h(the)f(top)g(of)h(the)f(scroll)g +(bar)l(,)h(the)g(ele)n(v)n(ator)e(will)h(mo)o(v)o(e)f(up)h(to)g(that)h +(position)d(and)j(you)f(will)0 4531 y(be)f(vie)n(wing)e(the)h(top)g +(part)h(of)f(your)h(chip.)29 b(The)23 b(little)e(squares)h(with)g(arro) +n(ws)g(in)h(them)e(at)i(the)f(ends)h(of)f(the)h(scroll)0 +4651 y(bars)32 b(will)f(scroll)h(the)g(vie)n(w)f(by)h(one)g(screenful)g +(when)g(the)g(middle)f(b)n(utton)g(is)g(click)o(ed)h(on)g(them.)52 +b(The)o(y)31 b(are)0 4772 y(useful)g(when)g(you)f(w)o(ant)h(to)g(mo)o +(v)o(e)f(e)o(xactly)g(one)h(screenful.)50 b(The)31 b +Fa(:scr)n(oll)g Fc(command)f(can)i(also)e(be)i(used)e(to)0 +4892 y(scroll)c(the)g(vie)n(w)g(\(though)g(we)h(don')n(t)f(think)f(it') +-5 b(s)26 b(as)g(easy)h(to)f(use)h(as)f(the)h(scroll)f(bars\).)36 +b(See)27 b(the)g(man)f(page)h(for)0 5012 y(information)c(on)i(it.)146 +5137 y(If)h(you)e(only)g(w)o(ant)h(to)f(mak)o(e)h(a)g(small)f +(adjustment)f(in)h(a)h(windo)n(w')-5 b(s)23 b(vie)n(w)-6 +b(,)24 b(you)g(can)h(use)g(the)g(command)900 5400 y Fa(:center)1875 +5649 y Fc(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fc(September)25 b(26,)f(2001)1577 b(Magic)25 +b(T)l(utorial)e(#5:)30 b(Multiple)24 b(W)l(indo)n(ws)146 +68 y(It)29 b(will)e(mo)o(v)o(e)g(the)h(vie)n(w)g(in)g(the)g(windo)n(w)f +(so)h(that)g(the)g(point)f(that)h(used)g(to)g(be)h(underneath)f(the)g +(cursor)h(is)0 188 y(no)n(w)24 b(in)g(the)h(middle)f(of)h(the)f(windo)n +(w)-6 b(.)29 b(The)c(macro)g Fa(,)g Fc(is)f(prede\002ned)h(to)g +Fa(:center)p Fc(.)146 309 y(The)19 b(b)n(ull')-5 b(s-e)o(ye)18 +b(in)h(the)g(lo)n(wer)f(left)h(corner)h(of)f(a)h(windo)n(w)e(is)g(used) +h(to)g(zoom)f(the)h(vie)n(w)g(in)f(and)i(out.)28 b(Clicking)0 +429 y(the)34 b(left)f(mouse)g(b)n(utton)g(zooms)g(the)g(vie)n(w)g(out)h +(by)f(a)h(f)o(actor)g(of)g(2,)i(and)e(clicking)f(the)g(right)g(mouse)g +(b)n(utton)0 549 y(zooms)23 b(in)f(by)h(a)h(f)o(actor)g(of)f(2.)30 +b(Clicking)23 b(the)g(middle)f(b)n(utton)g(here)i(mak)o(es)f(e)n(v)o +(erything)e(in)i(the)g(windo)n(w)f(visible)0 670 y(and)j(is)f(equi)n(v) +n(alent)f(to)i(the)f Fa(:view)h Fc(command.)0 963 y Fb(2.5)119 +b(Sa)m(ving)30 b(W)n(indo)o(w)h(Con\002gurations)0 1151 +y Fc(After)i(setting)e(up)h(a)h(b)n(unch)e(of)i(windo)n(ws)e(you)h(may) +g(w)o(ant)g(to)g(sa)n(v)o(e)g(the)g(con\002guration)g(\(for)g(e)o +(xample,)i(you)0 1271 y(may)24 b(be)h(partial)g(to)f(a)h(set)g(of)g(3)g +(non-o)o(v)o(erlapping)d(windo)n(ws\).)29 b(T)-8 b(o)25 +b(do)f(this,)g(type:)900 1484 y Fa(:windo)o(wpositions)h +Fd(\002lename)146 1698 y Fc(A)g(set)g(of)g(commands)e(will)h(be)h +(written)f(to)h(the)f(\002le.)31 b(This)25 b(\002le)g(can)g(be)g(used)f +(with)g(the)h Fa(:sour)n(ce)h Fc(command)0 1818 y(to)e(recreate)h(the)f +(windo)n(w)f(con\002guration)g(later)-5 b(.)31 b(\(Ho)n(we)n(v)o(er)l +(,)23 b(this)g(only)g(w)o(orks)h(well)g(if)g(you)g(stay)f(on)h(the)g +(same)0 1939 y(kind)j(of)i(display;)f(if)g(you)g(create)h(a)f(\002le)h +(under)f(X11)g(and)g(then)f Fa(:sour)n(ce)j Fc(it)d(under)h(SunV)-6 +b(ie)n(w)g(,)28 b(you)g(might)f(not)0 2059 y(get)e(the)f(same)h +(positions)e(since)h(the)h(coordinate)f(systems)g(may)g(v)n(ary)-6 +b(.\))0 2397 y Fe(3)143 b(Ho)o(w)35 b(Commands)e(W)-11 +b(ork)36 b(Inside)e(of)i(W)m(indo)o(ws)0 2620 y Fc(Each)25 +b(windo)n(w)e(has)i(a)g(caption)g(at)f(the)h(top.)30 +b(Here)c(is)e(an)h(e)o(xample:)900 2834 y Fa(mychip)g(EDITING)g +(shiftcell)146 3047 y Fc(This)33 b(indicates)g(that)g(the)g(windo)n(w)f +(contains)g(the)i(root)f(cell)g Fa(mychip)p Fc(,)j(and)d(that)g(a)h +(subcell)f(of)g(it)g(called)0 3167 y Fa(shiftcell)27 +b Fc(is)f(being)g(edited.)36 b(Y)-11 b(ou)26 b(may)h(remember)f(from)h +(the)f(T)l(utorial)g(#4)g(that)g(at)h(an)o(y)f(gi)n(v)o(en)f(time)h +(Magic)h(is)0 3288 y(editing)e(e)o(xactly)g(one)h(cell.)34 +b(If)27 b(the)f(edit)f(cell)h(is)g(in)f(another)h(windo)n(w)f(then)g +(the)h(caption)g(on)f(this)g(windo)n(w)g(will)0 3408 +y(read:)900 3622 y Fa(mychip)g([NO)l(T)g(BEING)g(EDITED])146 +3835 y Fc(Let')-5 b(s)33 b(do)g(an)h(e)o(xample)e(to)h(see)h(ho)n(w)e +(commands)g(are)i(e)o(x)o(ecuted)f(within)f(windo)n(ws.)55 +b(Close)33 b(an)o(y)g(layout)0 3955 y(windo)n(ws)d(that)h(you)h(may)f +(ha)n(v)o(e)h(on)f(the)h(screen)g(and)g(open)f(tw)o(o)h(ne)n(w)f(windo) +n(ws,)h(each)g(containing)f(the)g(cell)0 4076 y Fa(tut5a)p +Fc(.)54 b(\(Use)32 b(the)h Fa(:closewindo)o(w)f Fc(and)h +Fa(:openwindo)o(w)g(tut5a)g Fc(commands)e(to)h(do)g(this.\))53 +b(T)m(ry)32 b(mo)o(ving)e(the)0 4196 y(box)25 b(around)g(in)g(one)g(of) +g(the)h(windo)n(ws.)k(Notice)25 b(that)g(the)g(box)g(also)g(mo)o(v)o +(es)e(in)i(the)g(other)g(windo)n(w)-6 b(.)31 b(W)l(indo)n(ws)0 +4317 y(containing)h(the)i(same)g(root)f(cell)h(are)g(equi)n(v)n(alent)e +(as)i(f)o(ar)h(as)e(the)h(box)f(is)h(concerned:)49 b(if)33 +b(it)h(appears)g(in)f(one)0 4437 y(it)e(will)g(appear)h(in)g(all,)h +(and)f(it)f(can)h(be)g(manipulated)e(from)i(them)f(interchangeably)-6 +b(.)50 b(If)32 b(you)g(change)g Fa(tut5a)0 4557 y Fc(by)g(painting)f +(or)h(erasing)g(portions)f(of)h(it)f(you)h(will)f(see)i(the)f(changes)g +(in)f(both)h(windo)n(ws.)51 b(This)31 b(is)h(because)0 +4678 y(both)c(windo)n(ws)e(are)k(looking)d(at)h(the)g(same)g(thing:)37 +b(the)28 b(cell)h Fa(tut5a)p Fc(.)42 b(Go)28 b(ahead)h(and)f(try)g +(some)g(painting)f(and)0 4798 y(erasing)k(until)e(you)h(feel)h +(comfortable)g(with)f(it.)48 b(T)m(ry)30 b(positioning)e(one)j(corner)g +(of)g(the)f(box)g(in)h(one)f(windo)n(w)0 4918 y(and)g(another)g(corner) +g(in)g(another)f(windo)n(w)-6 b(.)45 b(Y)-11 b(ou')o(ll)29 +b(\002nd)h(it)f(doesn')n(t)h(matter)f(which)h(windo)n(w)e(you)i(point)f +(to,)0 5039 y(all)c(Magic)f(kno)n(ws)g(is)g(that)g(you)h(are)g +(pointing)e(to)i Fa(tut5a)p Fc(.)146 5159 y(These)j(windo)n(ws)e(are)j +(independent)e(in)g(some)g(respects,)i(ho)n(we)n(v)o(er)-5 +b(.)38 b(F)o(or)27 b(e)o(xample,)h(you)f(may)h(scroll)f(one)0 +5280 y(windo)n(w)f(around)h(without)f(af)n(fecting)h(the)g(other)g +(windo)n(w)-6 b(.)36 b(Use)28 b(the)f(scrollbars)f(to)h(gi)n(v)o(e)f +(this)h(a)g(try)-6 b(.)38 b(Y)-11 b(ou)27 b(can)0 5400 +y(also)d(e)o(xpand)h(and)f(une)o(xpand)g(cells)h(independently)e(in)h +(dif)n(ferent)h(windo)n(ws.)1875 5649 y(\2264\226)p eop +%%Page: 5 5 +5 4 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#5:)30 b(Multiple)23 +b(W)l(indo)n(ws)1576 b(September)25 b(26,)g(2001)146 +68 y(W)-8 b(e)40 b(ha)n(v)o(e)f(seen)g(ho)n(w)g(Magic)g(beha)n(v)o(es)g +(when)g(both)f(windo)n(ws)g(vie)n(w)g(a)i(single)e(cell.)74 +b(What)40 b(happens)0 188 y(when)35 b(windo)n(ws)e(vie)n(w)h(dif)n +(ferent)h(cells?)61 b(T)-8 b(o)35 b(try)f(this)g(out)h(load)f +Fa(tut5b)i Fc(into)e(one)h(of)g(the)g(windo)n(ws)e(\(point)0 +309 y(to)38 b(a)h(windo)n(w)d(and)j(type)f Fa(:load)g(tut5b)p +Fc(\).)73 b(Y)-11 b(ou)38 b(will)f(see)i(the)f(captions)f(on)h(the)g +(windo)n(ws)f(change\227only)0 429 y(one)e(windo)n(w)f(contains)g(the)h +(cell)g(currently)g(being)f(edited.)61 b(The)35 b(box)g(cannot)f(be)i +(positioned)d(by)i(placing)0 549 y(one)i(corner)h(in)f(one)g(windo)n(w) +f(and)h(another)g(corner)g(in)g(the)g(other)g(windo)n(w)f(because)i +(that)e(doesn')n(t)h(really)0 670 y(mak)o(e)d(sense)g(\(try)h(it\).)58 +b(Ho)n(we)n(v)o(er)l(,)36 b(the)e(selection)f(commands)g(w)o(ork)i +(between)f(windo)n(ws:)48 b(you)33 b(can)i(select)0 790 +y(information)c(in)h(one)g(windo)n(w)f(and)i(then)f(cop)o(y)g(it)g +(into)f(another)h(\(this)g(only)f(w)o(orks)h(if)h(the)f(windo)n(w)f +(you')-5 b(re)0 911 y(cop)o(ying)24 b(into)g(contains)g(the)g(edit)h +(cell;)f(if)h(not,)f(you')o(ll)g(ha)n(v)o(e)h(to)f(use)h(the)f +Fa(:edit)i Fc(command)e(\002rst\).)146 1032 y(The)30 +b(operation)g(of)g(man)o(y)f(Magic)h(commands)f(is)h(dependent)f(upon)h +(which)g(windo)n(w)e(you)i(are)h(pointing)0 1152 y(at.)45 +b(If)30 b(you)f(are)h(used)f(to)g(using)g(Magic)g(with)g(only)f(one)i +(windo)n(w)e(you)h(may)-6 b(,)30 b(at)f(\002rst,)i(for)n(get)f(to)f +(point)f(to)h(the)0 1273 y(windo)n(w)21 b(that)h(you)g(w)o(ant)h(the)f +(operation)g(performed)h(upon.)29 b(F)o(or)23 b(instance,)f(if)h(there) +f(are)i(se)n(v)o(eral)d(windo)n(ws)g(on)0 1393 y(the)30 +b(screen)i(you)e(will)f(ha)n(v)o(e)i(to)f(point)f(to)h(one)h(before)g +(e)o(x)o(ecuting)e(a)i(command)f(lik)o(e)g Fa(:grid)p +Fc(\227otherwise)g(you)0 1513 y(may)24 b(not)h(af)n(fect)g(the)g(windo) +n(w)e(that)h(you)h(intended!)0 1858 y Fe(4)143 b(Special)34 +b(W)m(indo)o(ws)0 2084 y Fc(In)c(addition)e(to)h(pro)o(viding)f +(multiple)g(windo)n(ws)g(on)h(dif)n(ferent)g(areas)i(of)e(a)h(layout,)g +(Magic)g(pro)o(vides)e(se)n(v)o(eral)0 2204 y(special)34 +b(types)g(of)g(windo)n(ws)e(that)i(display)f(things)g(other)h(than)g +(layouts.)58 b(F)o(or)34 b(e)o(xample,)i(there)e(are)h(special)0 +2324 y(windo)n(w)28 b(types)g(to)g(edit)h(netlists)e(and)i(to)g(adjust) +f(the)g(colors)h(displayed)f(on)g(the)h(screen.)44 b(One)29 +b(of)g(the)f(special)0 2445 y(windo)n(w)23 b(types)i(is)f(described)h +(in)f(the)h(section)f(belo)n(w;)f(others)i(are)g(described)g(in)f(the)h +(other)g(tutorials.)k(The)900 2680 y Fa(:specialopen)d +Fd(type)f Fc([)p Fd(ar)l(gs)p Fc(])146 2914 y(command)19 +b(is)h(used)g(to)g(create)h(these)f(sorts)f(of)h(windo)n(ws.)28 +b(The)20 b Fd(type)g Fc(ar)n(gument)g(tells)f(what)h(sort)f(of)h(windo) +n(w)0 3035 y(you)25 b(w)o(ant,)f(and)h Fd(ar)l(gs)g Fc(describe)g(what) +f(you)h(w)o(ant)g(loaded)f(into)g(that)h(windo)n(w)-6 +b(.)29 b(The)c Fa(:openwindo)o(w)h Fd(cellname)0 3155 +y Fc(command)e(is)g(really)h(just)f(short)g(for)h(the)g(command)f +Fa(:specialopen)h(lay)n(out)f Fd(cellname)p Fc(.)146 +3276 y(Each)h(dif)n(ferent)f(type)g(of)h(windo)n(w)e(\(layout,)h(color) +l(,)g(etc.\))31 b(has)25 b(its)e(o)n(wn)h(command)g(set.)30 +b(If)25 b(you)f(type)g Fa(:help)0 3396 y Fc(in)32 b(dif)n(ferent)h +(windo)n(w)e(types,)k(you')o(ll)d(see)h(that)f(the)h(commands)f(are)h +(dif)n(ferent.)55 b(Some)33 b(of)g(the)f(commands,)0 +3517 y(such)26 b(as)g(those)g(to)g(manipulate)f(windo)n(ws,)g(are)i(v)n +(alid)e(in)h(all)g(windo)n(ws,)f(b)n(ut)h(for)g(other)g(commands)f(you) +h(must)0 3637 y(mak)o(e)33 b(sure)h(you')-5 b(re)33 b(pointing)f(to)h +(the)g(right)g(kind)f(of)i(windo)n(w)e(or)h(the)h(command)e(may)h(be)h +(misinterpreted.)0 3758 y(F)o(or)e(e)o(xample,)h(the)e +Fa(:extract)i Fc(command)e(means)h(one)f(thing)g(in)h(a)g(layout)f +(windo)n(w)f(and)i(something)e(totally)0 3878 y(dif)n(ferent)24 +b(in)h(a)g(netlist)e(windo)n(w)-6 b(.)0 4223 y Fe(5)143 +b(Color)35 b(Editing)0 4448 y Fc(Special)e(windo)n(ws)e(of)i(type)f +Fa(color)g Fc(are)i(used)e(to)g(edit)h(the)f(red,)j(green,)g(and)d +(blue)h(intensities)d(of)j(the)g(colors)0 4569 y(displayed)24 +b(on)g(the)h(screen.)31 b(T)-8 b(o)25 b(create)h(a)f(color)f(editing)g +(windo)n(w)-6 b(,)23 b(in)l(v)n(ok)o(e)h(the)h(command)900 +4804 y Fa(:specialopen)h(color)e Fc([)p Fd(number)p Fc(])146 +5038 y Fd(Number)32 b Fc(is)f(optional;)h(if)g(present,)g(it)f(gi)n(v)o +(es)f(the)h(octal)g(v)n(alue)g(of)g(the)g(color)g(number)g(whose)g +(intensities)0 5158 y(are)26 b(to)e(be)h(edited.)30 b(If)25 +b Fd(number)g Fc(isn')n(t)f(gi)n(v)o(en,)f(0)i(is)f(used.)31 +b(T)m(ry)24 b(opening)g(a)h(color)g(windo)n(w)e(on)i(color)f(0.)146 +5280 y(A)30 b(color)f(editing)f(windo)n(w)g(contains)g(6)i(\223color)f +(bars\224,)i(12)e(\223color)g(pumps\224)g(\(one)g(on)g(each)h(side)f +(of)g(each)0 5400 y(bar\),)23 b(plus)f(a)h(lar)n(ge)f(rectangle)h(at)f +(the)h(top)e(of)i(the)f(windo)n(w)f(that)h(displays)f(a)i(sw)o(atch)f +(of)g(the)g(color)h(being)f(edited)1875 5649 y(\2265\226)p +eop +%%Page: 6 6 +6 5 bop 0 -180 a Fc(September)25 b(26,)f(2001)1577 b(Magic)25 +b(T)l(utorial)e(#5:)30 b(Multiple)24 b(W)l(indo)n(ws)0 +68 y(\(called)33 b(the)f(\223current)h(color\224)f(from)g(no)n(w)g +(on\).)53 b(The)32 b(color)g(bars)h(display)e(the)h(components)f(of)i +(the)f(current)0 188 y(color)26 b(in)f(tw)o(o)h(dif)n(ferent)f(w)o +(ays.)34 b(The)26 b(three)g(bars)g(on)f(the)h(left)g(display)f(the)g +(current)h(color)g(in)f(terms)h(of)g(its)f(red,)0 309 +y(green,)j(and)f(blue)g(intensities)f(\(these)h(intensities)e(are)j +(the)f(v)n(alues)g(actually)g(sent)f(to)h(the)g(display\).)38 +b(The)27 b(three)0 429 y(bars)34 b(on)f(the)h(right)f(display)f(the)i +(current)f(color)h(in)f(terms)g(of)h(hue,)i(saturation,)f(and)e(v)n +(alue.)57 b(Hue)33 b(selects)h(a)0 549 y(color)23 b(of)h(the)f +(spectrum.)29 b(Saturation)24 b(indicates)e(ho)n(w)h(diluted)f(the)h +(color)g(is)g(\(high)g(saturation)g(corresponds)f(to)0 +670 y(a)29 b(pure)h(color)l(,)f(lo)n(w)f(saturation)g(corresponds)h(to) +g(a)g(color)g(that)f(is)h(diluted)f(with)g(gray)-6 b(,)30 +b(and)f(a)g(saturation)f(of)h(0)0 790 y(results)d(in)g(gray)g(re)o +(gardless)g(of)g(hue\).)36 b(V)-11 b(alue)27 b(indicates)e(the)i(o)o(v) +o(erall)e(brightness)g(\(a)i(v)n(alue)f(of)g(0)h(corresponds)0 +911 y(to)d(black,)h(re)o(gardless)f(of)h(hue)f(or)h(saturation\).)146 +1031 y(There)i(are)f(se)n(v)o(eral)f(w)o(ays)h(to)f(modify)g(the)h +(current)g(color)-5 b(.)33 b(First,)26 b(try)g(pressing)f(an)o(y)g +(mouse)g(b)n(utton)g(while)0 1151 y(the)38 b(cursor)g(is)g(o)o(v)o(er)f +(one)h(of)g(the)g(color)g(bars.)71 b(The)38 b(length)f(of)i(the)e(bar)l +(,)42 b(and)c(the)g(current)h(color)l(,)i(will)c(be)0 +1272 y(modi\002ed)24 b(to)h(re\003ect)h(the)f(mouse)g(position.)30 +b(The)25 b(color)g(map)f(in)h(the)g(display)f(is)h(also)g(changed,)g +(so)g(the)g(colors)0 1392 y(will)19 b(change)i(e)n(v)o(erywhere)f(on)g +(the)g(screen)g(that)g(the)g(current)h(color)f(is)f(displayed.)29 +b(Color)20 b(0,)h(which)f(you)f(should)0 1513 y(currently)30 +b(be)h(editing,)f(is)g(the)g(background)g(color)-5 b(.)46 +b(Y)-11 b(ou)30 b(can)h(also)f(modify)f(the)h(current)h(color)f(by)g +(pressing)0 1633 y(a)e(b)n(utton)e(while)h(the)g(cursor)h(is)f(o)o(v)o +(er)g(one)g(of)h(the)f(\223color)h(pumps\224)e(ne)o(xt)h(to)g(the)g +(bars.)39 b(If)28 b(you)f(b)n(utton)f(a)i(pump)0 1753 +y(with)d(\223+\224)h(in)g(it,)f(the)g(v)n(alue)g(of)h(the)g(bar)g(ne)o +(xt)e(to)i(it)f(will)g(be)g(incremented)h(slightly)-6 +b(,)23 b(and)j(if)f(you)g(b)n(utton)g(the)g(\223-\224)0 +1874 y(pump,)32 b(the)g(bar)g(will)e(be)i(decremented)g(slightly)-6 +b(.)49 b(The)31 b(left)h(b)n(utton)e(causes)i(a)g(change)g(of)f(about)h +(1\045)f(in)g(the)0 1994 y(v)n(alue)23 b(of)i(the)e(bar)l(,)i(and)f +(the)g(right)f(b)n(utton)g(will)g(pump)g(the)h(bar)g(up)g(or)g(do)n(wn) +f(by)h(about)f(5\045.)30 b(T)m(ry)24 b(adjusting)e(the)0 +2114 y(bars)j(by)f(b)n(uttoning)f(the)i(bars)g(and)g(the)f(pumps.)146 +2235 y(If)31 b(you)f(press)h(a)g(b)n(utton)e(while)h(the)h(cursor)f(is) +g(o)o(v)o(er)g(the)h(current)f(color)h(box)f(at)h(the)f(top)g(of)h(the) +f(windo)n(w)-6 b(,)0 2355 y(one)24 b(of)g(tw)o(o)f(things)g(will)g +(happen.)30 b(In)24 b(either)g(case,)g(nothing)f(happens)g(until)g(you) +g(release)i(the)f(b)n(utton.)29 b(Before)0 2476 y(releasing)22 +b(the)g(b)n(utton,)f(mo)o(v)o(e)g(the)h(cursor)h(so)e(it)h(is)g(o)o(v)o +(er)f(a)i(dif)n(ferent)f(color)g(some)n(where)f(on)h(the)g(screen.)31 +b(If)23 b(you)0 2596 y(pressed)28 b(the)g(left)g(b)n(utton,)g(then)g +(when)g(the)g(b)n(utton)f(is)h(released)h(the)f(color)g(underneath)g +(the)g(cursor)g(becomes)0 2716 y(the)d(ne)n(w)g(current)g(color)l(,)g +(and)g(all)g(future)g(editing)f(operations)g(will)g(af)n(fect)i(this)e +(color)-5 b(.)31 b(T)m(ry)24 b(using)g(this)g(feature)0 +2837 y(to)f(modify)f(the)h(color)g(used)g(for)g(windo)n(w)f(borders.)30 +b(If)24 b(you)f(pressed)g(the)g(right)f(b)n(utton,)g(then)h(when)g(the) +g(b)n(utton)0 2957 y(is)29 b(released)h(the)f(v)n(alue)f(of)i(the)f +(current)h(color)f(is)g(copied)g(from)g(whate)n(v)o(er)f(color)h(is)g +(present)g(underneath)g(the)0 3077 y(cursor)-5 b(.)146 +3198 y(There)24 b(are)g(only)f(a)h(fe)n(w)f(commands)f(you)h(can)h +(type)f(in)g(color)g(windo)n(ws,)f(aside)h(from)g(those)g(that)g(are)h +(v)n(alid)0 3318 y(in)g(all)h(windo)n(ws.)k(The)c(command)900 +3521 y Fa(:color)g Fc([)p Fd(number)p Fc(])146 3724 y(will)d(change)h +(the)f(current)h(color)f(to)g Fd(number)p Fc(.)30 b(If)23 +b(no)f Fd(number)g Fc(is)g(gi)n(v)o(en,)g(this)f(command)h(will)f +(print)h(out)g(the)0 3844 y(current)j(color)g(and)f(its)g(red,)i +(green,)f(and)f(blue)h(intensities.)k(The)c(command)900 +4047 y Fa(:sa)n(v)o(e)f Fc([)p Fd(tec)o(hStyle)g(displayStyle)g +(monitorT)-7 b(ype)p Fc(])146 4250 y(will)19 b(sa)n(v)o(e)f(the)i +(current)f(color)g(map)g(in)g(a)g(\002le)h(named)f Fd(tec)o(hStyle)p +Fc(.)p Fd(displayStyle)p Fc(.)p Fd(monitorT)-7 b(ype)p +Fa(.cmap)p Fc(,)17 b(where)0 4371 y Fd(tec)o(hStyle)31 +b Fc(is)g(the)g(type)g(of)h(technology)e(\(e.g.,)k Fa(mos)p +Fc(\),)e Fd(displayStyle)f Fc(is)g(the)g(kind)g(of)g(display)g +(speci\002ed)h(by)f(a)0 4491 y Fa(styletype)f Fc(in)g(the)g +Fa(style)g Fc(section)f(of)h(a)h(technology)e(\002le)h(\(e.g.,)h +Fa(7bit)p Fc(\),)h(and)e Fd(monitorT)-7 b(ype)29 b Fc(is)h(the)f(type)h +(of)g(the)0 4611 y(current)e(monitor)f(\(e.g.,)i Fa(std)p +Fc(\).)42 b(If)28 b(no)g(ar)n(guments)g(are)h(gi)n(v)o(en,)e(the)h +(current)h(technology)e(style,)h(display)f(style,)0 4732 +y(and)e(monitor)e(type)i(are)g(used.)31 b(The)24 b(command)900 +4935 y Fa(:load)h Fc([)p Fd(tec)o(hStyle)f(displayStyle)f(monitorT)-7 +b(ype)p Fc(])146 5138 y(will)20 b(load)h(the)f(color)h(map)f(from)h +(the)f(\002le)h(named)g Fd(tec)o(hStyle)p Fc(.)p Fd(displayStyle)p +Fc(.)p Fd(monitorT)-7 b(ype)p Fa(.cmap)17 b Fc(as)k(abo)o(v)o(e.)0 +5258 y(If)29 b(no)g(ar)n(guments)f(are)h(gi)n(v)o(en,)g(the)f(current)h +(technology)f(style,)h(display)e(style,)i(and)g(monitor)f(type)g(are)h +(used.)0 5378 y(When)c(loading)f(color)g(maps,)g(Magic)h(looks)f +(\002rst)h(in)f(the)h(current)g(directory)-6 b(,)24 b(then)g(in)g(the)h +(system)f(library)-6 b(.)1875 5649 y(\2266\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut6.ps b/doc/psfiles/tut6.ps new file mode 100644 index 00000000..dded64e6 --- /dev/null +++ b/doc/psfiles/tut6.ps @@ -0,0 +1,560 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tut6.dvi +%%Pages: 5 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tut6.dvi -o tut6.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut6.dvi) +@start /Fa 134[50 1[72 1[55 33 39 44 1[55 50 55 2[55 +2[55 1[33 44 55 44 55 50 38[33 3[50 51[55 2[{ + TeXBase1Encoding ReEncodeFont }20 100.000003 /Times-Bold +rf /Fb 138[66 40 47 53 2[60 66 100 33 2[33 66 2[53 66 +53 1[60 12[80 6[113 9[86 8[40 55[66 2[{ TeXBase1Encoding ReEncodeFont } +19 119.999948 /Times-Bold rf /Fc 105[50 1[44 44 10[33 +14[50 50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 +50 50 33 44 50 44 50 44 3[33 1[33 1[72 1[94 1[72 61 55 +66 1[55 72 1[89 3[33 72 72 55 61 72 66 66 72 5[28 28 +50 1[50 50 50 50 50 50 50 50 28 25 33 25 2[33 33 33 3[50 +31[55 55 2[{ TeXBase1Encoding ReEncodeFont }70 100.000003 +/Times-Roman rf /Fd 134[44 3[50 28 39 39 1[50 50 50 4[28 +50 2[44 50 1[50 50 11[72 5[72 4[44 27[25 1[25 2[33 33 +40[{ TeXBase1Encoding ReEncodeFont }21 100.000003 /Times-Italic +rf /Fe 134[72 3[80 48 56 64 2[72 80 120 40 80 1[40 80 +72 48 64 1[64 80 72 12[96 80 104 1[88 112 1[135 96 2[56 +112 112 1[96 104 104 8[48 3[72 72 72 72 72 72 3[48 9[72 +35[{ TeXBase1Encoding ReEncodeFont }40 143.999997 /Times-Bold +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 673 101 a Fe(Magic)35 b(T)-13 b(utorial)34 b(#6:)44 +b(Design-Rule)33 b(Checking)1618 521 y Fd(J)n(ohn)24 +b(Ousterhout)1401 941 y Fc(Computer)g(Science)i(Di)n(vision)1020 +1062 y(Electrical)f(Engineering)f(and)h(Computer)f(Sciences)1473 +1182 y(Uni)n(v)o(ersity)f(of)i(California)1544 1303 y(Berk)o(ele)o(y)-6 +b(,)24 b(CA)h(94720)1448 1573 y Fd(\(Updated)f(by)h(other)o(s,)f +(too.\))1053 1843 y Fc(This)g(tutorial)g(corresponds)g(to)g(Magic)h(v)o +(ersion)e(7.)0 2356 y Fb(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:) +300 2547 y Fc(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)300 2668 y(Magic)g(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)300 2788 y(Magic)f(T)l(utorial)g(#4:)30 +b(Cell)25 b(Hierarchies)0 2979 y Fb(Commands)k(intr)n(oduced)j(in)f +(this)f(tutorial:)300 3171 y Fc(:drc)0 3362 y Fb(Macr)n(os)f(intr)n +(oduced)i(in)g(this)f(tutorial:)300 3575 y Fc(y)0 4454 +y Fe(1)143 b(Continuous)34 b(Design-Rule)f(Checking)0 +4678 y Fc(When)28 b(you)f(are)h(editing)f(a)h(layout)e(with)h(Magic,)h +(the)f(system)g(automatically)f(checks)i(design)f(rules)g(on)g(your)0 +4798 y(behalf.)j(Ev)o(ery)22 b(time)g(you)h(paint)f(or)h(erase,)h(and)e +(e)n(v)o(ery)h(time)f(you)g(mo)o(v)o(e)f(a)i(cell)g(or)g(change)g(an)g +(array)h(structure,)0 4918 y(Magic)d(rechecks)h(the)f(area)i(you)e +(changed)g(to)g(be)h(sure)f(you)g(ha)n(v)o(en')n(t)g(violated)g(an)o(y) +g(of)g(the)h(layout)e(rules.)30 b(If)22 b(you)0 5039 +y(do)g(violate)f(rules,)h(Magic)g(will)f(display)g(little)g(white)h +(dots)f(in)h(the)g(vicinity)e(of)j(the)f(violation.)28 +b(This)21 b(error)i(paint)0 5159 y(will)j(stay)h(around)g(until)f(you)h +(\002x)g(the)g(problem;)h(when)f(the)g(violation)e(is)i(corrected,)i +(the)e(error)g(paint)g(will)f(go)0 5280 y(a)o(w)o(ay)h(automatically)-6 +b(.)35 b(Error)27 b(paint)g(is)f(written)g(to)h(disk)f(with)g(your)h +(cells)g(and)g(will)f(re-appear)i(the)f(ne)o(xt)f(time)0 +5400 y(the)f(cell)f(is)h(read)g(in.)30 b(There)c(is)e(no)h(w)o(ay)f(to) +h(get)g(rid)f(of)h(it)f(e)o(xcept)h(to)f(\002x)h(the)g(violation.)1875 +5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fc(September)25 b(26,)f(2001)1411 b(Magic)24 +b(T)l(utorial)f(#6:)31 b(Design-Rule)24 b(Checking)146 +68 y(Continuous)h(design-rule)h(checking)g(means)g(that)g(you)g(al)o(w) +o(ays)g(ha)n(v)o(e)g(an)g(up-to-date)g(picture)g(of)h(design-)0 +188 y(rule)i(errors)g(in)f(your)g(layout.)41 b(There)29 +b(is)f(ne)n(v)o(er)g(an)o(y)g(need)h(to)f(run)g(a)h(massi)n(v)o(e)e +(check)i(o)o(v)o(er)e(the)i(whole)f(design)0 309 y(unless)21 +b(you)g(change)h(your)f(design)g(rules.)29 b(When)22 +b(you)f(mak)o(e)g(small)g(changes)g(to)g(an)h(e)o(xisting)e(layout,)h +(you)g(will)0 429 y(\002nd)27 b(out)g(immediately)e(if)i(you')-5 +b(v)o(e)26 b(introduced)g(errors,)i(without)e(ha)n(ving)g(to)h +(completely)e(recheck)j(the)f(entire)0 549 y(layout.)146 +670 y(T)-8 b(o)25 b(see)h(ho)n(w)f(the)g(check)o(er)h(w)o(orks,)f(run)g +(Magic)g(on)g(the)g(cell)g Fa(tut6a)p Fc(.)33 b(This)25 +b(cell)g(contains)f(se)n(v)o(eral)h(areas)h(of)0 790 +y(metal)31 b(\(blue\),)i(some)d(of)i(which)e(are)i(too)f(close)g(to)g +(each)h(other)f(or)g(too)g(narro)n(w)-6 b(.)49 b(T)m(ry)31 +b(painting)f(and)h(erasing)0 911 y(metal)24 b(to)h(mak)o(e)f(the)h +(error)h(paint)e(go)g(a)o(w)o(ay)h(and)g(re-appear)h(again.)0 +1245 y Fe(2)143 b(Getting)34 b(Inf)l(ormation)g(about)g(Err)m(ors)0 +1469 y Fc(In)f(man)o(y)f(cases,)j(the)e(reason)g(for)g(a)g(design-rule) +g(violation)e(will)h(be)h(ob)o(vious)e(to)i(you)f(as)h(soon)f(as)h(you) +g(see)0 1589 y(the)28 b(error)g(paint.)39 b(Ho)n(we)n(v)o(er)l(,)27 +b(Magic)g(pro)o(vides)g(se)n(v)o(eral)g(commands)f(for)i(you)f(to)h +(use)f(to)g(\002nd)h(violations)e(and)0 1709 y(\002gure)k(what')-5 +b(s)28 b(wrong)h(in)g(case)h(it)f(isn')n(t)g(ob)o(vious.)42 +b(All)29 b(of)g(the)g(design-rule)g(checking)g(commands)f(ha)n(v)o(e)h +(the)0 1830 y(form)900 2020 y Fa(:dr)n(c)d Fd(option)146 +2211 y Fc(where)d Fd(option)d Fc(selects)h(one)h(of)g(se)n(v)o(eral)f +(commands)f(understood)h(by)g(the)h(design-rule)f(check)o(er)-5 +b(.)30 b(If)22 b(you')-5 b(re)0 2331 y(not)30 b(sure)g(why)f(error)i +(paint)e(has)h(suddenly)f(appeared,)j(place)f(the)f(box)g(around)f(the) +h(error)h(paint)f(and)g(in)l(v)n(ok)o(e)0 2451 y(the)25 +b(command)900 2642 y Fa(:dr)n(c)h(wh)o(y)146 2832 y Fc(This)36 +b(command)g(will)g(recheck)h(the)g(area)g(underneath)g(the)f(box,)j +(and)e(print)f(out)g(the)g(reasons)h(for)g(an)o(y)0 2953 +y(violations)21 b(that)i(were)h(found.)30 b(Y)-11 b(ou)23 +b(can)h(also)f(use)g(the)g(macro)h Fa(y)f Fc(to)g(do)g(the)h(same)f +(thing.)29 b(T)m(ry)23 b(this)f(on)h(some)g(of)0 3073 +y(the)k(errors)h(in)g Fa(tut6a)p Fc(.)39 b(It')-5 b(s)27 +b(a)h(good)f(idea)g(to)h(place)f(the)h(box)f(right)g(around)g(the)h +(area)g(of)g(the)f(error)h(paint:)36 b Fa(:dr)n(c)0 3194 +y(wh)o(y)25 b Fc(rechecks)g(the)g(entire)f(area)i(under)f(the)g(box,)f +(so)g(it)h(may)f(tak)o(e)h(a)g(long)f(time)g(if)h(the)g(box)f(is)g(v)o +(ery)h(lar)n(ge.)146 3314 y(If)f(you')-5 b(re)24 b(w)o(orking)f(in)g(a) +h(lar)n(ge)g(cell,)f(it)g(may)h(be)f(hard)h(to)f(see)h(the)f(error)i +(paint.)k(T)-8 b(o)24 b(help)f(locate)g(the)h(errors,)0 +3434 y(select)h(a)g(cell)g(and)f(then)h(use)g(the)f(command)900 +3625 y Fa(:dr)n(c)i(\002nd)g Fc([)p Fd(nth)p Fc(])146 +3815 y(If)38 b(you)f(don')n(t)g(pro)o(vide)f(the)h Fd(nth)g +Fc(ar)n(gument,)j(the)d(command)f(will)h(place)h(the)f(box)g(around)g +(one)g(of)g(the)0 3936 y(errors)26 b(in)f(the)g(selected)g(cell,)g(and) +g(print)g(out)f(the)h(reason)h(for)f(the)g(error)l(,)h(just)f(as)g(if)g +(you)g(had)g(typed)g Fa(:dr)n(c)h(wh)o(y)p Fc(.)0 4056 +y(If)33 b(you)g(in)l(v)n(ok)o(e)f(the)h(command)f(repeatedly)-6 +b(,)35 b(it)e(will)f(step)g(through)g(all)h(of)g(the)g(errors)h(in)e +(the)h(selected)g(cell.)0 4176 y(\(remember)l(,)g(the)e(\223.)-7 +b(\224)50 b(macro)32 b(can)f(be)h(used)e(to)h(repeat)h(the)f(last)g +(long)f(command;)j(this)d(will)h(sa)n(v)o(e)g(you)f(from)0 +4297 y(ha)n(ving)d(to)g(retype)h Fa(:dr)n(c)h(\002nd)g +Fc(o)o(v)o(er)d(and)i(o)o(v)o(er)f(again\).)38 b(T)m(ry)27 +b(this)g(out)g(on)g(the)h(errors)g(in)f Fa(tut6a)p Fc(.)39 +b(If)28 b(you)g(type)f(a)0 4417 y(number)g(for)g Fd(nth)p +Fc(,)h(the)f(command)f(will)h(go)g(to)g(the)g Fd(nth)g +Fc(error)h(in)f(the)g(selected)g(cell,)h(instead)f(of)h(the)f(ne)o(xt)f +(one.)0 4538 y(If)f(you)g(in)l(v)n(ok)o(e)f(this)g(command)f(with)h(no) +h(cell)g(selected,)f(it)h(searches)g(the)g(edit)f(cell.)146 +4658 y(A)f(third)f(drc)h(command)e(is)h(pro)o(vided)g(to)g(gi)n(v)o(e)f +(you)h(summary)g(information)f(about)h(errors)h(in)f(hierarchical)0 +4778 y(designs.)30 b(The)24 b(command)g(is)900 4969 y +Fa(:dr)n(c)i(count)146 5159 y Fc(This)h(command)f(will)g(search)h(e)n +(v)o(ery)g(cell)g(\(visible)f(or)h(not\))f(that)h(lies)f(underneath)h +(the)g(box)g(to)f(see)i(if)f(an)o(y)0 5280 y(ha)n(v)o(e)g(errors)i(in)e +(them.)39 b(F)o(or)28 b(each)g(cell)g(with)f(errors,)i +Fa(:dr)n(c)g(count)g Fc(will)e(print)g(out)g(a)h(count)f(of)h(the)g +(number)f(of)0 5400 y(error)e(areas.)1875 5649 y(\2262\226)p +eop +%%Page: 3 3 +3 2 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#6:)30 b(Design-Rule)25 +b(Checking)1410 b(September)25 b(26,)g(2001)0 99 y Fe(3)143 +b(Err)m(ors)35 b(in)g(Hierar)m(chical)f(Lay)l(outs)0 +322 y Fc(The)j(design-rule)g(check)o(er)h(w)o(orks)e(on)h(hierarchical) +h(layouts)e(as)h(well)g(as)g(single)f(cells.)67 b(There)38 +b(are)g(three)0 443 y(o)o(v)o(erall)24 b(rules)g(that)g(describe)h(the) +g(w)o(ay)g(that)f(Magic)h(checks)g(hierarchical)g(designs:)120 +671 y(1.)49 b(The)26 b(paint)g(in)g(each)h(cell)f(must)f(obe)o(y)h(all) +g(the)g(design)f(rules)i(by)f(itself,)f(without)g(considering)h(the)g +(paint)244 792 y(in)e(an)o(y)h(other)f(cells,)h(including)e(its)h +(children.)120 995 y(2.)49 b(The)23 b(combined)f(paint)h(of)g(each)h +(cell)f(and)g(all)g(of)g(its)f(descendants)h(\(subcells,)g +(sub-subcells,)f(etc.\))30 b(must)244 1116 y(be)24 b(consistent.)29 +b(If)c(a)f(subcell)g(interacts)g(with)f(paint)h(or)g(with)f(other)h +(subcells)g(in)f(a)i(w)o(ay)f(that)g(introduces)244 1236 +y(a)33 b(design-rule)f(violation,)g(an)h(error)g(will)f(appear)h(in)f +(the)h(parent.)54 b(In)32 b(designs)g(with)f(man)o(y)h(le)n(v)o(els)f +(of)244 1356 y(hierarchy)-6 b(,)24 b(this)g(rule)h(is)f(applied)g +(separately)h(to)f(each)i(cell)f(and)f(its)g(descendants.)120 +1560 y(3.)49 b(Each)23 b(array)h(must)f(be)g(consistent)f(by)h(itself,) +g(without)f(considering)g(an)o(y)h(other)g(subcells)f(or)h(paint)g(in)g +(its)244 1680 y(parent.)46 b(If)31 b(the)f(neighboring)e(elements)i(of) +g(an)g(array)h(interact)e(to)h(produce)g(a)g(design-rule)g(violation,) +244 1801 y(the)25 b(violation)e(will)h(appear)h(in)f(the)h(parent.)146 +2029 y(T)-8 b(o)30 b(see)g(some)f(e)o(xamples)f(of)i(interaction)f +(errors,)i(edit)e(the)g(cell)h Fa(tut6b)p Fc(.)46 b(This)29 +b(cell)h(doesn')n(t)f(mak)o(e)g(sense)0 2150 y(electrically)-6 +b(,)37 b(b)n(ut)d(illustrates)f(the)i(features)g(of)g(the)g +(hierarchical)g(check)o(er)-5 b(.)62 b(On)34 b(the)h(left)g(are)h(tw)o +(o)e(subcells)0 2270 y(that)29 b(are)h(too)f(close)g(together)-5 +b(.)43 b(In)29 b(addition,)g(the)g(subcells)g(are)h(too)e(close)i(to)e +(the)i(red)f(paint)g(in)g(the)g(top-le)n(v)o(el)0 2390 +y(cell.)39 b(Mo)o(v)o(e)26 b(the)h(subcells)g(and/or)g(modify)f(the)i +(paint)f(to)g(mak)o(e)g(the)h(errors)f(go)h(a)o(w)o(ay)f(and)h +(reappear)-5 b(.)39 b(On)27 b(the)0 2511 y(right)33 b(side)h(of)f +Fa(tut6b)i Fc(is)f(an)g(array)g(whose)g(elements)f(interact)g(to)h +(produce)g(a)g(design-rule)f(violation.)56 b(Edit)0 2631 +y(an)27 b(element)f(of)h(the)f(array)i(to)e(mak)o(e)h(the)f(violation)f +(go)h(a)o(w)o(ay)-6 b(.)36 b(When)27 b(there)g(are)g(interaction)f +(errors)h(between)0 2752 y(the)37 b(elements)f(of)h(an)g(array)-6 +b(,)40 b(the)c(errors)h(al)o(w)o(ays)g(appear)g(near)h(one)f(of)f(the)h +(four)g(corner)g(elements)f(of)h(the)0 2872 y(array)25 +b(\(since)f(the)h(array)g(spacing)f(is)f(uniform,)h(Magic)g(only)f +(checks)i(interactions)e(near)i(the)f(corners;)h(if)f(these)0 +2992 y(elements)g(are)i(correct,)f(all)g(the)f(ones)h(in)f(the)h +(middle)e(must)h(be)h(correct)h(too\).)146 3113 y(It')-5 +b(s)25 b(important)f(to)h(remember)g(that)g(each)h(of)g(the)f(three)h +(o)o(v)o(erall)e(rules)h(must)f(be)i(satis\002ed)f(independently)-6 +b(.)0 3233 y(This)28 b(may)g(sometimes)f(result)h(in)g(errors)h(where)f +(it)g(doesn')n(t)h(seem)f(lik)o(e)g(there)h(should)e(be)h(an)o(y)-6 +b(.)41 b(Edit)28 b(the)g(cell)0 3353 y Fa(tut6c)g Fc(for)g(some)f(e)o +(xamples)f(of)h(this.)38 b(On)27 b(the)g(left)h(side)f(of)g(the)g(cell) +h(there)f(is)g(a)h(sli)n(v)o(er)e(of)h(paint)g(in)g(the)g(parent)0 +3474 y(that)33 b(e)o(xtends)g(paint)g(in)g(a)h(subcell.)56 +b(Although)32 b(the)i(o)o(v)o(erall)e(design)h(is)g(correct,)k(the)c +(sli)n(v)o(er)f(of)i(paint)f(in)g(the)0 3594 y(parent)k(is)g(not)f +(correct)i(by)f(itself,)i(as)e(required)g(by)g(the)g(\002rst)g(o)o(v)o +(erall)f(rule)h(abo)o(v)o(e.)66 b(On)37 b(the)g(right)f(side)h(of)0 +3715 y Fa(tut6c)d Fc(is)g(an)f(array)i(with)d(spacing)h(violations)f +(between)i(the)f(array)i(elements.)56 b(Ev)o(en)33 b(though)f(the)i +(paint)e(in)0 3835 y(the)d(parent)f(masks)g(some)g(of)h(the)g +(problems,)f(the)h(array)g(is)g(not)f(consistent)f(by)i(itself)f(so)g +(errors)h(are)h(\003agged.)0 3955 y(The)g(three)g(o)o(v)o(erall)e +(rules)i(are)g(more)g(conserv)n(ati)n(v)o(e)e(than)h(strictly)g +(necessary)-6 b(,)31 b(b)n(ut)e(the)o(y)g(reduce)h(the)g(amount)0 +4076 y(of)25 b(rechecking)h(Magic)e(must)h(do.)31 b(F)o(or)25 +b(e)o(xample,)g(the)g(array)h(rule)f(allo)n(ws)f(Magic)h(to)f(deduce)i +(the)f(correctness)0 4196 y(of)f(an)g(array)h(by)f(looking)e(only)h(at) +i(the)e(corner)i(elements;)e(if)h(paint)f(from)h(the)g(parent)g(had)g +(to)g(be)g(considered)f(in)0 4317 y(checking)k(arrays,)i(it)e(w)o(ould) +g(be)h(necessary)g(to)g(check)g(the)f(entire)h(array)g(since)g(there)g +(might)e(be)i(parent)g(paint)0 4437 y(masking)c(some)g(errors)h(b)n(ut) +f(not)g(all)h(\(as,)g(for)g(e)o(xample,)f(in)g Fa(tut6c)p +Fc(\).)146 4557 y(Error)36 b(paint)e(appears)i(in)e(dif)n(ferent)h +(cells)g(in)f(the)h(hierarchy)-6 b(,)37 b(depending)d(on)h(what)g(kind) +f(of)h(error)h(w)o(as)0 4678 y(found.)46 b(Errors)30 +b(resulting)f(from)h(paint)g(in)f(a)i(single)e(cell)h(cause)g(error)h +(paint)f(to)f(appear)i(in)f(that)f(cell.)47 b(Errors)0 +4798 y(resulting)21 b(from)h(interactions)f(and)h(arrays)g(appear)h(in) +f(the)g(parent)g(of)g(the)g(interacting)f(cells)h(or)g(array)-6 +b(.)30 b(Because)0 4918 y(of)g(the)h(w)o(ay)f(Magic)g(mak)o(es)g +(interaction)g(checks,)i(errors)f(can)f(sometimes)f(\223b)n(ubble)h +(up\224)g(through)g(the)g(hier)n(-)0 5039 y(archy)i(and)g(appear)h(in)f +(multiple)f(cells.)52 b(When)33 b(tw)o(o)e(cells)h(o)o(v)o(erlap,)h +(Magic)f(checks)g(this)g(area)h(by)f(cop)o(ying)0 5159 +y(all)g(the)g(paint)f(in)h(that)f(area)i(from)f(both)f(cells)h(\(and)g +(their)g(descendants\))f(into)g(a)i(b)n(uf)n(fer)f(and)g(then)f +(checking)0 5280 y(the)26 b(b)n(uf)n(fer)-5 b(.)35 b(Magic)26 +b(is)g(unable)g(to)g(tell)g(the)g(dif)n(ference)g(between)h(an)f(error) +h(from)f(one)h(of)f(the)g(subcells)g(and)g(an)0 5400 +y(error)j(that)f(comes)h(about)f(because)h(the)f(tw)o(o)g(subcells)g(o) +o(v)o(erlap)f(incorrectly)-6 b(.)42 b(This)27 b(means)i(that)f(errors)h +(in)f(an)1875 5649 y(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fc(September)25 b(26,)f(2001)1411 b(Magic)24 +b(T)l(utorial)f(#6:)31 b(Design-Rule)24 b(Checking)0 +68 y(interaction)k(area)j(of)e(a)h(cell)f(may)g(also)g(appear)h(in)f +(the)g(cell')-5 b(s)28 b(parent.)45 b(Fixing)28 b(the)h(error)h(in)f +(the)g(subcell)g(will)0 188 y(cause)c(the)g(error)g(in)g(the)f(parent)h +(to)g(go)f(a)o(w)o(ay)h(also.)0 556 y Fe(4)143 b(T)-13 +b(ur)n(ning)34 b(the)h(Check)o(er)e(Off)0 788 y Fc(W)-8 +b(e)29 b(hope)g(that)g(in)g(most)e(cases)j(the)f(check)o(er)h(will)e +(run)h(so)f(quickly)g(and)h(quietly)f(that)h(you)f(hardly)h(kno)n(w)f +(it')-5 b(s)0 909 y(there.)31 b(Ho)n(we)n(v)o(er)l(,)23 +b(there)i(will)e(probably)h(be)h(some)e(situations)g(where)i(the)f +(check)o(er)h(is)f(irksome.)30 b(This)24 b(section)0 +1029 y(describes)h(se)n(v)o(eral)f(w)o(ays)g(to)h(k)o(eep)g(the)f +(check)o(er)i(out)e(of)h(your)g(hair)-5 b(.)146 1154 +y(If)26 b(you')-5 b(re)25 b(w)o(orking)f(on)h(a)h(cell)f(with)f(lots)g +(of)i(design-rule)e(violations)f(the)i(constant)g(redisplay)f(caused)h +(by)0 1274 y(design-rule)h(checking)f(may)h(get)g(in)g(your)g(w)o(ay)g +(more)g(than)g(it)g(helps.)34 b(This)25 b(is)h(particularly)g(true)g +(if)g(you')-5 b(re)26 b(in)0 1395 y(the)21 b(middle)f(of)h(a)h(lar)n +(ge)f(series)g(of)h(changes)f(and)g(don')n(t)g(care)h(about)e +(design-rule)h(violations)e(until)h(the)h(changes)0 1515 +y(are)26 b(\002nished.)k(Y)-11 b(ou)24 b(can)i(stop)e(the)g(redisplay)g +(using)g(the)h(command)900 1778 y Fa(:see)g(no)g(err)n(ors)146 +2037 y Fc(After)g(this)e(command)h(is)g(typed,)f(design-rule)h(errors)h +(will)e(no)h(longer)g(be)h(displayed)e(on)h(the)g(screen.)31 +b(The)0 2158 y(design-rule)h(check)o(er)i(will)f(continue)f(to)h(run)g +(and)g(will)f(store)h(error)h(information)e(internally)-6 +b(,)33 b(b)n(ut)g(it)f(w)o(on')n(t)0 2278 y(bother)24 +b(you)h(by)f(displaying)f(it)i(on)f(the)h(screen.)31 +b(When)25 b(you')-5 b(re)25 b(ready)g(to)f(see)i(errors)f(again,)f +(type)900 2541 y Fa(:see)h(err)n(ors)146 2800 y Fc(There)j(can)f(also)f +(be)h(times)f(when)h(it')-5 b(s)26 b(not)g(the)h(redisplay)f(that')-5 +b(s)26 b(bothersome,)g(b)n(ut)h(the)f(amount)g(of)h(CPU)0 +2921 y(time)21 b(the)h(check)o(er)h(tak)o(es)f(to)g(recheck)h(what)f +(you')-5 b(v)o(e)21 b(changed.)30 b(F)o(or)22 b(e)o(xample,)g(if)g(a)g +(lar)n(ge)h(subcell)e(is)h(mo)o(v)o(ed)e(to)0 3041 y(o)o(v)o(erlap)i +(another)i(lar)n(ge)g(subcell,)f(the)g(entire)g(o)o(v)o(erlap)g(area)h +(will)f(ha)n(v)o(e)g(to)g(be)h(recheck)o(ed,)g(and)g(this)e(could)h +(tak)o(e)0 3161 y(se)n(v)o(eral)h(minutes.)30 b(If)25 +b(the)g(prompt)f(on)g(the)h(te)o(xt)f(screen)i(is)e(a)h(\223]\224)h +(character)l(,)g(it)e(means)h(that)f(the)h(command)f(has)0 +3282 y(completed)f(b)n(ut)g(the)h(check)o(er)h(hasn')n(t)e(caught)h(up) +f(yet.)30 b(Y)-11 b(ou)24 b(can)g(in)l(v)n(ok)o(e)f(ne)n(w)h(commands)e +(while)i(the)f(check)o(er)0 3402 y(is)h(running,)g(and)h(the)g(check)o +(er)g(will)f(suspend)g(itself)g(long)g(enough)g(to)h(process)f(the)h +(ne)n(w)g(commands.)146 3527 y(If)d(the)f(check)o(er)h(tak)o(es)f(too)f +(long)h(to)g(interrupt)f(itself)g(and)h(respond)g(to)g(your)g +(commands,)f(you)h(ha)n(v)o(e)g(se)n(v)o(eral)0 3647 +y(options.)33 b(First,)26 b(you)f(can)i(hit)e(the)h(interrupt)f(k)o(e)o +(y)h(\(often)g(\210C\))h(on)e(the)h(k)o(e)o(yboard.)34 +b(This)25 b(will)g(stop)g(the)h(check)o(er)0 3768 y(immediately)f(and)h +(w)o(ait)g(for)g(your)g(ne)o(xt)g(command.)34 b(As)26 +b(soon)g(as)g(you)g(issue)f(a)i(command)e(or)i(push)e(a)i(mouse)0 +3888 y(b)n(utton,)c(the)i(check)o(er)h(will)e(start)g(up)h(again.)30 +b(T)-8 b(o)24 b(turn)h(the)f(check)o(er)i(of)n(f)f(altogether)l(,)f +(type)g(the)h(command)900 4151 y Fa(:dr)n(c)h(off)146 +4410 y Fc(From)g(this)g(point)f(on,)h(the)g(check)o(er)h(will)e(not)h +(run.)34 b(Magic)26 b(will)f(record)i(the)f(areas)h(that)f(need)g +(rechecking)0 4530 y(b)n(ut)32 b(w)o(on')n(t)g(do)g(the)h(rechecks.)54 +b(If)33 b(you)f(sa)n(v)o(e)g(your)g(\002le)h(and)f(quit)g(Magic,)i(the) +e(information)f(about)h(areas)h(to)0 4651 y(recheck)27 +b(will)e(be)h(sa)n(v)o(ed)f(on)h(disk.)33 b(The)26 b(ne)o(xt)f(time)g +(you)h(read)g(in)g(the)g(cell,)g(Magic)f(will)g(recheck)i(those)e +(areas,)0 4771 y(unless)j(you')-5 b(v)o(e)28 b(still)g(got)g(the)h +(check)o(er)g(turned)g(of)n(f.)43 b(There)29 b(is)f(nothing)g(you)g +(can)i(do)e(to)h(mak)o(e)f(Magic)h(for)n(get)0 4892 y(about)24 +b(areas)i(to)e(recheck;)i Fa(:dr)n(c)g(off)f Fc(merely)f(postpones)g +(the)g(recheck)i(operation)e(to)h(a)g(later)g(time.)146 +5016 y(Once)38 b(you')-5 b(v)o(e)36 b(turned)h(the)g(check)o(er)h(of)n +(f,)i(you)d(ha)n(v)o(e)g(tw)o(o)f(w)o(ays)h(to)g(mak)o(e)g(sure)g(e)n +(v)o(erything)f(has)h(been)0 5137 y(recheck)o(ed.)32 +b(The)24 b(\002rst)h(is)g(to)f(type)h(the)f(command)900 +5400 y Fa(:dr)n(c)i(catchup)1875 5649 y Fc(\2264\226)p +eop +%%Page: 5 5 +5 4 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#6:)30 b(Design-Rule)25 +b(Checking)1410 b(September)25 b(26,)g(2001)146 68 y(This)c(command)g +(will)f(run)i(the)f(check)o(er)i(and)e(w)o(ait)g(until)g(e)n(v)o +(erything)e(has)j(been)f(recheck)o(ed)i(and)e(errors)h(are)0 +188 y(completely)g(up)h(to)f(date.)30 b(When)23 b(the)g(command)f +(completes,)g(the)h(check)o(er)h(will)e(still)g(be)h(enabled)g(or)g +(disabled)0 309 y(just)29 b(as)g(it)h(w)o(as)f(before)h(the)g(command.) +44 b(If)30 b(you)f(get)h(tired)f(of)h(w)o(aiting)f(for)h +Fa(:dr)n(c)h(catchup)p Fc(,)h(you)d(can)h(al)o(w)o(ays)0 +429 y(hit)23 b(the)g(interrupt)f(k)o(e)o(y)h(to)g(abort)g(the)g +(command;)g(the)g(recheck)h(areas)g(will)e(be)i(remembered)f(for)h +(later)-5 b(.)29 b(T)-8 b(o)24 b(turn)0 549 y(the)h(check)o(er)g(back)g +(on)g(permanently)-6 b(,)23 b(in)l(v)n(ok)o(e)h(the)h(command)900 +778 y Fa(:dr)n(c)h(on)0 1117 y Fe(5)143 b(P)m(orting)34 +b(Lay)l(outs)h(fr)m(om)g(Other)f(Systems)0 1341 y Fc(Y)-11 +b(ou)30 b(should)f(not)h(need)g(to)g(read)h(this)e(section)h(if)g(you') +-5 b(v)o(e)30 b(created)h(your)f(layout)g(from)g(scratch)g(using)f +(Magic)0 1461 y(or)i(ha)n(v)o(e)g(read)g(it)g(from)g(CIF)h(using)e +(Magic')-5 b(s)30 b(CIF)i(or)f(Calma)h(reader)-5 b(.)50 +b(Ho)n(we)n(v)o(er)l(,)31 b(if)g(you)f(are)i(bringing)e(into)0 +1582 y(Magic)23 b(a)h(layout)f(that)g(w)o(as)g(created)h(using)f(a)g +(dif)n(ferent)h(editor)f(or)g(an)h(old)f(v)o(ersion)f(of)i(Magic)f +(that)g(didn')n(t)f(ha)n(v)o(e)0 1702 y(continuous)g(checking,)h(read)h +(on.)30 b(Y)-11 b(ou)23 b(may)g(also)f(need)i(to)f(read)h(this)e +(section)h(if)g(you')-5 b(v)o(e)22 b(changed)i(the)f(design)0 +1822 y(rules)i(in)f(the)h(technology)e(\002le.)146 1943 +y(In)33 b(order)g(to)g(\002nd)g(out)f(about)g(errors)h(in)g(a)g(design) +f(that)g(w)o(asn')n(t)h(created)g(with)f(Magic,)i(you)f(must)e(force)0 +2063 y(Magic)g(to)g(recheck)h(e)n(v)o(erything)d(in)i(the)g(design.)49 +b(Once)32 b(this)e(global)g(recheck)i(has)f(been)h(done,)g(Magic)f +(will)0 2184 y(use)24 b(its)f(continuous)g(check)o(er)i(to)e(deal)i +(with)e(an)o(y)g(changes)i(you)e(mak)o(e)h(to)g(the)g(design;)f(you)h +(should)f(only)g(need)0 2304 y(to)g(do)g(the)h(global)e(recheck)j +(once.)30 b(T)-8 b(o)24 b(mak)o(e)f(the)g(global)g(recheck,)i(load)e +(your)g(design,)g(place)h(the)f(box)g(around)0 2424 y(the)i(entire)f +(design,)g(and)h(type)900 2653 y Fa(:dr)n(c)h(check)146 +2881 y Fc(This)h(will)f(cause)i(Magic)f(to)f(act)i(as)f(if)g(the)g +(entire)h(area)g(under)f(the)g(box)g(had)g(just)f(been)i(modi\002ed:)34 +b(it)27 b(will)0 3001 y(recheck)i(that)f(entire)g(area.)42 +b(Furthermore,)29 b(it)e(will)h(w)o(ork)g(its)f(w)o(ay)h(do)n(wn)g +(through)f(the)h(hierarchy;)h(for)g(e)n(v)o(ery)0 3122 +y(subcell)24 b(found)g(underneath)h(the)g(box,)f(it)g(will)g(recheck)i +(that)e(subcell)g(o)o(v)o(er)g(the)h(area)h(of)f(the)f(box.)146 +3242 y(If)j(you)f(get)h(nerv)n(ous)f(that)g(a)h(design-rule)f +(violation)e(might)i(someho)n(w)f(ha)n(v)o(e)h(been)h(missed,)e(you)h +(can)h(use)0 3362 y Fa(:dr)n(c)35 b(check)g Fc(to)e(force)i(an)o(y)e +(area)i(to)e(be)h(recheck)o(ed)g(at)g(an)o(y)f(time,)i(e)n(v)o(en)e +(for)h(cells)f(that)g(were)i(created)f(with)0 3483 y(Magic.)52 +b(Ho)n(we)n(v)o(er)l(,)33 b(this)e(should)g(ne)n(v)o(er)g(be)h +(necessary)h(unless)e(you')-5 b(v)o(e)31 b(changed)h(the)g(design)g +(rules.)52 b(If)32 b(the)0 3603 y(number)25 b(of)h(errors)g(in)g(the)g +(layout)e(e)n(v)o(er)i(changes)g(because)g(of)g(a)g Fa(:dr)n(c)h(check) +p Fc(,)h(it)d(is)g(a)i(b)n(ug)e(in)g(Magic)h(and)g(you)0 +3724 y(should)e(notify)g(us)g(immediately)-6 b(.)1875 +5649 y(\2265\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut7.ps b/doc/psfiles/tut7.ps new file mode 100644 index 00000000..4f9aca0a --- /dev/null +++ b/doc/psfiles/tut7.ps @@ -0,0 +1,1977 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: tut7.dvi +%%Pages: 13 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman Helvetica font +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -t letter tut7.dvi -o ../psfiles/tut7.ps +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2006.04.12:1203 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: texps.pro +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type/integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics/Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{ +dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 +roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def +dup[exch{dup CharStrings exch known not{pop/.notdef/Encoding true def} +if}forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def} +def end + +%%EndProcSet +%%BeginProcSet: special.pro +%! +TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N +/vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N +/rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N +/@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{ +/hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho +X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B +/@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{ +/urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known +{userdict/md get type/dicttype eq{userdict begin md length 10 add md +maxlength ge{/md md dup length 20 add dict copy def}if end md begin +/letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S +atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{ +itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll +transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll +curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf +pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack} +if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 +-1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 +get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip +yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub +neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{ +noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop +90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get +neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr +1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr +2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 +-1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S +TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{ +Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale +}if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState +save N userdict maxlength dict begin/magscale true def normalscale +currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts +/psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x +psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx +psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub +TR/showpage{}N/erasepage{}N/copypage{}N/p 3 def @MacSetUp}N/doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N/endTexFig{end psf$SavedState restore}N/@beginspecial{SDict +begin/SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count/ocount X/dcount countdictstack N}N/@setspecial{ +CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if/showpage{}N/erasepage{}N/copypage{}N newpath}N +/@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{end} +repeat grestore SpecialSave restore end}N/@defspecial{SDict begin}N +/@fedspecial{end}B/li{lineto}B/rl{rlineto}B/rc{rcurveto}B/np{/SaveX +currentpoint/SaveY X N 1 setlinecap newpath}N/st{stroke SaveX SaveY +moveto}N/fil{fill SaveX SaveY moveto}N/ellipse{/endangle X/startangle X +/yrad X/xrad X/savematrix matrix currentmatrix N TR xrad yrad scale 0 0 +1 startangle endangle arc savematrix setmatrix}N end + +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut7.dvi) +@start +%DVIPSBitmapFont: Fa cmr8 8 1 +/Fa 1 51 df50 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fb cmmi12 12 1 +/Fb 1 79 df<91B500C0020FB5128082A2DA007F9239007FE00070ED1F8074C7FCDBEFF8 +150E15CF03C7160C70151C1401DB83FE1518A2DB81FF1538140303001630831A704A6D7E +02061760163F7114E0140E020C6D6C5CA2706C1301141C021801075D83190302386D7E02 +3094C8FC1601715B147002606DEB8006A294387FC00E14E04A023F130C18E0191C0101ED +1FF04A1618170FF0F838130391C83807FC30A2943803FE705B01060301136018FF19E001 +0E81010C5F187FA2131C0118705A1338181F137801FC70C9FCEA03FFB512F88418065144 +7CC34E>78 D E +%EndDVIPSBitmapFont +/Fc 134[50 50 72 50 55 33 39 44 1[55 50 55 83 28 55 33 +28 55 50 33 44 55 44 55 50 3[33 1[33 4[72 1[66 55 2[61 +1[72 7[61 2[72 8[33 1[50 50 2[50 50 50 50 50 28 43[55 +55 2[{TeXBase1Encoding ReEncodeFont}44 99.6264 /Times-Bold +rf /Fd 134[60 3[66 40 47 53 2[60 66 100 33 2[33 66 2[53 +66 53 66 60 12[80 66 3[93 86 113 80 8[86 8[40 1[60 4[60 +60 60 2[30 43[66 2[{TeXBase1Encoding ReEncodeFont}30 +119.552 /Times-Bold rf /Fe 105[50 1[44 44 10[33 13[44 +50 50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 +50 33 44 50 44 50 44 3[33 1[33 1[72 1[94 72 72 61 55 +66 1[55 72 72 89 61 2[33 72 72 55 61 72 66 66 72 92 44 +3[28 28 50 50 50 50 50 50 50 50 50 50 28 25 33 25 1[50 +33 33 33 2[50 50 1[33 29[55 55 2[{TeXBase1Encoding ReEncodeFont}80 +99.6264 /Times-Roman rf /Ff 134[44 2[44 50 28 39 39 1[50 +50 50 72 28 2[28 50 50 28 44 50 44 50 50 11[72 5[72 4[44 +33 1[72 17[50 3[50 2[25 33 25 2[33 33 37[50 2[{ +TeXBase1Encoding ReEncodeFont}33 99.6264 /Times-Italic +rf /Fg 136[104 1[80 48 56 64 2[72 80 120 40 80 1[40 80 +72 48 64 80 64 80 72 9[143 2[96 1[104 3[104 135 96 2[56 +112 1[88 96 1[104 8[48 72 72 72 72 72 72 72 72 72 13[72 +35[{TeXBase1Encoding ReEncodeFont}41 143.462 /Times-Bold +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%BeginPaperSize: Letter +letter +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 731 101 a Fg(Magic)35 b(T)-13 b(utorial)34 b(#7:)44 +b(Netlists)34 b(and)h(Routing)1618 521 y Ff(J)n(ohn)24 +b(Ousterhout)1401 941 y Fe(Computer)g(Science)i(Di)n(vision)1020 +1062 y(Electrical)f(Engineering)f(and)h(Computer)f(Sciences)1473 +1182 y(Uni)n(v)o(ersity)f(of)i(California)1544 1303 y(Berk)o(ele)o(y)-6 +b(,)24 b(CA)h(94720)1448 1573 y Ff(\(Updated)f(by)h(other)o(s,)f +(too.\))1053 1843 y Fe(This)g(tutorial)g(corresponds)g(to)g(Magic)h(v)o +(ersion)e(7.)0 2415 y Fd(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:) +300 2662 y Fe(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)300 2782 y(Magic)g(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)300 2903 y(Magic)f(T)l(utorial)g(#3:)30 +b(Adv)n(anced)24 b(P)o(ainting)g(\(W)l(iring)g(and)h(Plo)n(wing\))300 +3023 y(Magic)f(T)l(utorial)g(#4:)30 b(Cell)25 b(Hierarchies)300 +3143 y(Magic)f(T)l(utorial)g(#5:)30 b(Multiple)23 b(W)l(indo)n(ws)0 +3503 y Fd(Netlist)30 b(Commands)f(intr)n(oduced)j(in)f(this)e +(tutorial:)300 3750 y Fe(:e)o(xtract,)24 b(:\003ush,)g(:ripup,)g(:sa)n +(v)o(enetlist,)f(:trace,)i(:writeall)0 3990 y Fd(Lay)m(out)k(Commands)h +(intr)n(oduced)h(in)g(this)f(tutorial:)300 4237 y Fe(:channel,)24 +b(:route)0 4476 y Fd(Macr)n(os)29 b(intr)n(oduced)i(in)g(this)f +(tutorial:)300 4763 y Ff(\(none\))1875 5649 y Fe(\2261\226)p +eop +%%Page: 2 2 +2 1 bop 0 -180 a Fe(April)24 b(12,)h(2006)1717 b(Magic)24 +b(T)l(utorial)g(#7:)30 b(Netlists)23 b(and)i(Routing)0 +99 y Fg(1)143 b(Intr)m(oduction)0 331 y Fe(This)31 b(tutorial)f +(describes)i(ho)n(w)e(to)h(use)h(Magic')-5 b(s)31 b(automatic)f +(routing)h(tools)f(to)h(mak)o(e)h(interconnections)e(be-)0 +451 y(tween)23 b(subcells)g(in)f(a)i(design.)29 b(In)24 +b(addition)e(to)h(the)g(standard)g(Magic)f(router)l(,)i(which)f(is)g +(in)l(v)n(ok)o(ed)f(by)h(the)g Fc(r)n(oute)0 572 y Fe(command)31 +b(and)g(co)o(v)o(ered)h(in)f(this)g(tutorial,)h(tw)o(o)f(other)h +(routing)e(tools)h(are)i(a)n(v)n(ailable.)50 b(A)32 b(gate-array)g +(router)0 692 y Ff(Gar)l(outer)f Fe(permits)g(user)h(speci\002ed)h +(channel)f(de\002nitions,)g(terminals)g(in)f(the)h(interior)g(of)g +(cells,)i(and)e(route-)0 813 y(throughs)23 b(across)i(cells.)30 +b(T)-8 b(o)24 b(learn)h(about)f(the)g(gate-array)h(router)f(read)h +(this)f(\002rst)g(then)h(\223Magic)f(T)l(utorial)f(#12:)0 +933 y(Routing)h(Gate)i(Arrays\224.)32 b(Finally)24 b(Magic)h(pro)o +(vides)f(an)h(interacti)n(v)o(e)f(maze-router)i(that)e(tak)o(es)h +(graphic)g(hints,)0 1053 y(the)35 b Ff(Ir)l(outer)p Fe(,)h(that)f +(permits)f(the)h(user)g(to)f(control)h(the)f(o)o(v)o(erall)g(path)h(of) +g(routes)f(while)h(lea)n(ving)f(the)h(tedious)0 1174 +y(details)24 b(to)g(Magic.)31 b(The)25 b Ff(Ir)l(outer)e +Fe(is)i(documented)e(in)i(\223Magic)g(T)l(utorial)e(#10:)30 +b(The)25 b(Interacti)n(v)o(e)f(Router\224.)146 1298 y(The)f(standard)e +(Magic)h(router)g(pro)o(vides)f(an)i Ff(obstacle-avoidance)d +Fe(capability:)29 b(if)22 b(there)g(is)g(mask)g(material)0 +1419 y(in)39 b(the)g(routing)f(areas,)43 b(the)c(router)g(can)h(w)o +(ork)f(under)l(,)k(o)o(v)o(er)l(,)e(or)f(around)f(that)f(material)h(to) +g(complete)f(the)0 1539 y(connections.)29 b(This)24 b(means)g(that)f +(you)h(can)h(pre-route)f(k)o(e)o(y)g(signals)f(by)h(hand)g(and)g(ha)n +(v)o(e)g(Magic)g(route)g(the)g(less)0 1659 y(important)i(signals)g +(automatically)-6 b(.)35 b(In)27 b(addition,)g(you)f(can)i(route)f(po)n +(wer)f(and)h(ground)g(by)g(hand)f(\(right)h(no)n(w)0 +1780 y(we)e(don')n(t)f(ha)n(v)o(e)h(an)o(y)f(po)n(wer)n(-ground)g +(routing)g(tools,)f(so)i(you)f Ff(have)h Fe(to)g(route)f(them)g(by)h +(hand\).)146 1904 y(The)30 b(router)g Ff(only)f Fe(mak)o(es)g +(connections)g(between)h(subcells;)h(to)e(mak)o(e)h(point-to-point)d +(connections)i(be-)0 2025 y(tween)20 b(pieces)g(of)g(layout)f(within)f +(a)j(single)e(cell)g(you)h(should)f(use)g(the)h(wiring)f(command)g +(described)h(in)f(\223Magic)0 2145 y(T)l(utorial)g(#3:)28 +b(Adv)n(anced)19 b(P)o(ainting)g(\(W)l(iring)h(and)g(Plo)n(wing\))f +(\224)h(or)g(the)g(maze)h(router)f(described)g(in)g(\223Magic)g(T)l(u-) +0 2265 y(torial)25 b(#10:)32 b(The)26 b(Interacti)n(v)o(e)f +(Router\224.)34 b(If)27 b(you)e(only)g(need)h(to)f(mak)o(e)h(a)g(fe)n +(w)g(connections)f(you)g(are)i(probably)0 2386 y(better)e(of)n(f)f +(doing)g(them)g(manually)-6 b(.)146 2510 y(The)30 b(\002rst)g(step)f +(in)g(routing)g(is)g(to)g(tell)g(Magic)g(what)h(should)e(be)i +(connected)g(to)f(what.)45 b(This)29 b(information)0 +2631 y(is)j(contained)g(in)g(a)g(\002le)h(called)f(a)h +Ff(netlist)p Fe(.)52 b(Sections)32 b(2,)i(3,)g(4,)g(and)f(5)f(describe) +g(ho)n(w)g(to)g(create)h(and)f(modify)0 2751 y(netlists)26 +b(using)g(Magic')-5 b(s)26 b(interacti)n(v)o(e)g(netlist)f(editing)h +(tools.)37 b(Once)27 b(you')-5 b(v)o(e)27 b(created)h(a)f(netlist,)f +(the)h(ne)o(xt)g(step)0 2871 y(is)d(to)f(in)l(v)n(ok)o(e)h(the)g +(router)-5 b(.)30 b(Section)24 b(6)g(sho)n(ws)e(ho)n(w)i(to)f(do)h +(this,)f(and)h(gi)n(v)o(es)f(a)h(brief)h(summary)e(of)h(what)g(goes)f +(on)0 2992 y(inside)k(the)i(routing)e(tools.)40 b(Unless)28 +b(your)g(design)g(is)f(v)o(ery)h(simple)g(and)g(has)g(lots)g(of)g(free) +h(space,)h(the)e(routing)0 3112 y(probably)j(w)o(on')n(t)g(succeed)h +(the)f(\002rst)g(time.)50 b(Section)31 b(7)g(describes)h(the)f +(feedback)h(pro)o(vided)e(by)h(the)g(routing)0 3233 y(tools.)d +(Sections)20 b(8)g(and)g(9)g(discuss)f(ho)n(w)g(you)g(can)i(modify)e +(your)h(design)f(in)g(light)g(of)h(this)g(feedback)g(to)g(impro)o(v)o +(e)0 3353 y(its)k(routability)-6 b(.)29 b(Y)-11 b(ou')o(ll)24 +b(probably)g(need)h(to)f(iterate)h(a)g(fe)n(w)g(times)f(until)f(the)i +(routing)f(is)g(successful.)0 3719 y Fg(2)143 b(T)-13 +b(erminals)34 b(and)h(Netlists)0 3951 y Fe(A)24 b(netlist)f(is)g(a)h +(\002le)g(that)g(describes)g(a)g(set)g(of)g(desired)f(connections.)30 +b(It)24 b(contains)f(one)g(or)h(more)g Ff(nets)p Fe(.)30 +b(Each)24 b(net)0 4072 y(names)30 b(a)h(set)f(of)h Ff(terminals)e +Fe(that)h(should)f(all)i(be)f(wired)h(together)-5 b(.)47 +b(A)30 b(terminal)g(is)g(simply)f(a)i(label)f(attached)0 +4192 y(to)k(a)g(piece)h(of)f(mask)f(material)h(within)f(a)h(subcell;)k +(it)c(is)f(distinguishable)f(from)i(ordinary)f(labels)h(within)f(a)0 +4312 y(subcell)27 b(by)g(its)g(presence)h(within)f(a)h(netlist)e +(\002le)i(and)g(by)f(certain)h(characteristics)f(common)g(to)g +(terminals,)g(as)0 4433 y(described)e(belo)n(w)-6 b(.)146 +4557 y(The)37 b(\002rst)g(step)f(in)h(b)n(uilding)e(a)i(netlist)e(is)h +(to)h(label)f(the)h(terminals)e(in)i(your)f(design.)66 +b(Figure)37 b(1)f(sho)n(ws)0 4678 y(an)f(e)o(xample.)61 +b(Each)35 b(label)g(should)e(be)i(a)h(line)e(or)h(rectangle)h(running)e +(along)g(the)h(edge)g(of)g(the)g(cell)g(\(point)0 4798 +y(terminals)i(are)i(not)e(allo)n(wed\).)70 b(The)38 b(router)g(will)f +(mak)o(e)h(a)h(connection)e(to)h(the)g(cell)g(some)n(where)f(along)h(a) +0 4918 y(terminal')-5 b(s)29 b(length.)46 b(If)30 b(the)g(label)g(isn') +n(t)g(at)g(the)g(edge)g(of)g(the)g(cell,)h(Magic)f(will)f(route)h +(recklessly)g(across)g(the)0 5039 y(cell)25 b(to)g(reach)g(the)g +(terminal,)f(taking)h(the)f(shortest)g(path)h(between)g(the)g(terminal) +f(and)h(a)h(routing)d(channel.)32 b(It')-5 b(s)0 5159 +y(almost)27 b(al)o(w)o(ays)h(a)g(good)f(idea)h(to)g(arrange)h(for)f +(terminal)f(labels)g(to)h(be)g(at)g(cell)g(edges.)40 +b(The)28 b(label)g(must)f(be)h(at)0 5280 y(least)21 b(as)h(wide)g(as)g +(the)f(minimum)f(width)h(of)g(the)h(routing)f(material;)h(the)f(wider)h +(you)f(mak)o(e)h(the)g(label,)g(the)f(more)0 5400 y(\003e)o(xibility)i +(you)h(gi)n(v)o(e)g(the)g(router)h(to)g(choose)f(a)h(good)g(point)e(to) +i(connect)f(to)h(the)f(terminal.)1875 5649 y(\2262\226)p +eop +%%Page: 3 3 +3 2 bop 0 -180 a Fe(Magic)24 b(T)l(utorial)g(#7:)30 b(Netlists)23 +b(and)i(Routing)1717 b(April)24 b(12,)h(2006)975 804 +y @beginspecial 68 @llx 68 @lly 364 @urx 190 @ury 2340 +@rwi @setspecial +%%BeginDocument: ../psfigures/tut7.1.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: ../psfiles/tut7.1.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 13:29:20 2000 +%%Pages: 1 +%%BoundingBox: 68 68 364 190 +%%DocumentNeededResources: font Helvetica font Times-Roman +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrow { +% -12 -40 24 80 bbox +begingate +1 0.80 0 -40 0 20 2 polygon +1.00 0 0 40 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 480 256 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.800 0.800 0.800 scb +240 1.00 192 192 192 496 960 496 960 192 4 polygon +sce +0.490 0.651 0.980 scb +240 1.00 672 224 672 320 800 320 800 224 4 polygon +240 1.00 384 192 384 384 512 384 512 192 4 polygon +sce +1 1.00 256 192 256 384 800 384 800 192 4 polygon +1.000 1.000 0.000 scb +(Input) {/Helvetica 1.000 cf} 2 29 0 448 376 label +sce +(Cell Boundary) {/Times-Roman 1.000 cf} 2 27 0 848 444 label +1.000 1.000 0.000 scb +(Output) {/Helvetica 1.000 cf} 2 20 0 808 272 label +sce +1 1.00 672 224 800 224 2 polygon +1 1.00 672 320 800 320 2 polygon +1 1.00 512 384 512 192 2 polygon +1 1.00 384 384 384 192 2 polygon +1.000 1.000 0.000 scb +1 1.00 800 224 800 320 2 polygon +0 1.00 384 320 384 384 512 384 512 320 4 polygon +sce +1.00 135 580 412 arrow +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 1007 a(Figure)h(1:)33 b(An)26 b(e)o(xample)f(of)i +(terminal)e(labels.)34 b(Each)26 b(terminal)f(should)g(be)h(labeled)g +(with)g(a)g(line)g(or)g(rectangle)0 1127 y(along)e(the)h(edge)g(of)g +(the)f(cell.)146 1499 y(T)-7 b(erminal)35 b(labels)h(must)e(be)i +(attached)g(to)f(mask)g(material)g(that)h(connects)f(directly)g(to)h +(one)f(of)h(Magic')-5 b(s)0 1620 y(tw)o(o)33 b(routing)f(layers)i +(\(Routing)f(layers)g(are)h(de\002ned)g(in)f(Magic')-5 +b(s)33 b(technology)f(\002le\).)57 b(F)o(or)34 b(e)o(xample,)g(in)f +(the)0 1740 y(SCMOS)e(process)e(where)i(the)e(routing)g(layers)h(are)g +(metal1)f(and)h(metal2,)h(dif)n(fusion)d(may)h(not)g(be)h(used)g(as)g +(a)0 1860 y(terminal)21 b(since)h(neither)g(of)g(the)g(routing)f +(layers)h(will)g(connect)g(directly)f(to)h(it.)29 b(On)22 +b(the)g(other)g(hand,)g(a)h(terminal)0 1981 y(may)k(be)h(attached)g(to) +g(dif)n(fusion-metal1)d(contact,)k(since)e(the)h(metal1)f(routing)g +(layer)h(will)f(connect)g(properly)0 2101 y(to)h(it.)40 +b(T)-7 b(erminals)27 b(can)i(ha)n(v)o(e)f(arbitrary)g(names,)h(e)o +(xcept)e(that)h(the)o(y)g(should)f(not)g(contain)h(slashes)f +(\(\223/\224\))i(or)f(the)0 2222 y(substring)g(\223feedthrough\224,)j +(and)f(should)f(not)g(end)h(in)f(\223@\224,)i(\223$\224,)h(or)d +(\223\210\224.)47 b(See)31 b(T)l(utorial)d(#2)i(for)g(a)g(complete)0 +2342 y(description)24 b(of)h(labeling)e(con)l(v)o(entions.)146 +2467 y(F)o(or)37 b(an)f(e)o(xample)f(of)h(good)g(and)g(bad)g +(terminals,)i(edit)e(the)g(cell)g Fc(tut7a)p Fe(.)65 +b(The)37 b(cell)f(doesn')n(t)g(mak)o(e)g(an)o(y)0 2587 +y(electrical)c(sense,)i(b)n(ut)e(contains)g(se)n(v)o(eral)f(good)h(and) +g(bad)g(terminals.)52 b(All)32 b(the)g(terminals)f(with)h(names)g(lik)o +(e)0 2707 y Fc(bad1)f Fe(are)h(incorrect)f(or)g(undesirable)f(for)h +(one)g(of)g(the)g(reasons)f(gi)n(v)o(en)g(abo)o(v)o(e,)h(and)g(those)f +(with)g(names)h(lik)o(e)0 2828 y Fc(good4)25 b Fe(are)g(acceptable.)585 +4835 y @beginspecial 68 @llx 68 @lly 535 @urx 385 @ury +3276 @rwi @setspecial +%%BeginDocument: ../psfigures/tut7.2.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: tut7.2.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 13:50:28 2000 +%%Pages: 1 +%%BoundingBox: 68 68 535 385 +%%DocumentNeededResources: font Helvetica font Times-Italic +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 1117 536 offsets +% 32.00 8.00 gridspace +1.0000 inchscale +2.6000 setlinewidth + +0.545 0.137 0.137 scb +240 1.00 317 192 317 1016 1149 1016 1149 192 4 polygon +sce +0.804 0.000 0.804 scb +240 1.00 333 208 333 968 1133 968 1133 208 4 polygon +sce +1.000 0.647 0.000 scb +240 1.00 749 640 749 704 973 704 973 640 4 polygon +sce +0.898 0.898 0.898 scb +240 1.00 493 648 493 792 637 792 637 648 4 polygon +sce +0.824 0.706 0.549 scb +240 1.00 493 808 493 872 973 872 973 808 4 polygon +240 1.00 749 728 749 792 845 792 845 728 4 polygon +240 1.00 877 728 877 792 973 792 973 728 4 polygon +sce +0.753 1.000 0.753 scb +240 1.00 493 480 493 544 973 544 973 480 4 polygon +sce +0.490 0.651 0.980 scb +240 1.00 749 400 749 464 973 464 973 400 4 polygon +sce +1.000 0.502 0.502 scb +240 1.00 749 320 749 384 973 384 973 320 4 polygon +sce +1.000 1.000 0.753 scb +240 1.00 749 240 749 304 973 304 973 240 4 polygon +sce +0.800 0.800 0.800 scb +240 1.00 493 240 493 304 717 304 717 240 4 polygon +sce +1.000 0.753 0.753 scb +240 1.00 493 320 493 384 717 384 717 320 4 polygon +sce +0.753 1.000 1.000 scb +240 1.00 493 400 493 464 717 464 717 400 4 polygon +sce +1.000 1.000 1.000 scb +(NETLIST MENU) {/Helvetica 0.800 cf} 2 25 0 733 984 label +(Label) {/Helvetica 1.000 cf} 2 25 0 733 904 label +sce +(BusBit13) {/Helvetica 1.000 cf} 2 21 0 733 840 label +0 1.00 317 192 317 1016 1149 1016 1149 192 4 polygon +0 1.00 333 208 333 968 1133 968 1133 208 4 polygon +0 1.00 493 808 493 872 973 872 973 808 4 polygon +0 1.00 877 728 877 792 973 792 973 728 4 polygon +0 1.00 749 728 749 792 845 792 845 728 4 polygon +0 1.00 749 640 749 704 973 704 973 640 4 polygon +0 1.00 493 480 493 544 973 544 973 480 4 polygon +1.000 1.000 1.000 scb +(Netlist) {/Helvetica 1.000 cf} 2 25 0 733 584 label +sce +(Find) {/Helvetica 1.000 cf} 2 21 0 853 672 label +(13) {/Helvetica 1.000 cf} 2 21 0 797 760 label +0 1.00 493 648 493 792 637 792 637 648 4 polygon +1 1.00 541 648 541 792 2 polygon +1 1.00 589 792 589 648 2 polygon +1 1.00 493 744 637 744 2 polygon +1 1.00 493 696 637 696 2 polygon +1 1.00 557 720 573 720 2 polygon +1 1.00 565 728 565 712 2 polygon +(Placer) {/Times-Italic 1.000 cf} 2 23 0 293 728 label +(Current Netlist) {/Times-Italic 1.000 cf} 2 20 0 1165 512 label +(Pumps) {/Times-Italic 1.000 cf} 2 20 0 1165 760 label +(Current Text) {/Times-Italic 1.000 cf} 2 20 0 1165 840 label +0 1.00 493 400 493 464 717 464 717 400 4 polygon +0 1.00 749 400 749 464 973 464 973 400 4 polygon +0 1.00 493 320 493 384 717 384 717 320 4 polygon +0 1.00 749 320 749 384 973 384 973 320 4 polygon +0 1.00 493 240 493 304 717 304 717 240 4 polygon +0 1.00 749 240 749 304 973 304 973 240 4 polygon +(Print) {/Helvetica 1.000 cf} 2 21 0 861 432 label +(Cleanup) {/Helvetica 1.000 cf} 2 21 0 861 352 label +(Show) {/Helvetica 1.000 cf} 2 21 0 861 272 label +(No Net) {/Helvetica 1.000 cf} 2 21 0 605 272 label +(Terms) {/Helvetica 1.000 cf} 2 21 0 605 352 label +(Verify) {/Helvetica 1.000 cf} 2 21 0 605 432 label +1.00 0 989 840 arrowhead90 +1.00 0 989 760 arrowhead90 +1.00 0 989 512 arrowhead90 +1.00 -1 477 720 arrowhead90 +1 1.00 989 840 1165 840 2 polygon +1 1.00 989 760 1165 760 2 polygon +1 1.00 989 512 1165 512 2 polygon +1 1.00 469 720 301 720 2 polygon +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 1406 5039 a(Figure)g(2:)30 b(The)25 b(netlist)f(menu.)146 +5400 y(If)40 b(you)f(create)i(tw)o(o)e(or)g(more)g(terminal)g(labels)g +(with)g(the)g(same)g(name)h(in)f(the)g(same)g(cell)h(the)f(router)1875 +5649 y(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fe(April)24 b(12,)h(2006)1717 b(Magic)24 +b(T)l(utorial)g(#7:)30 b(Netlists)23 b(and)i(Routing)p +457 3 2986 4 v 455 124 4 121 v 507 88 a(Button)p 1150 +124 V 423 w(Action)p 3441 124 V 457 127 2986 4 v 455 +247 4 121 v 507 211 a(Current)g(T)-7 b(e)o(xt)p 1150 +247 V 191 w(Left-click:)30 b(prompt)24 b(for)h(more)g(labels)p +3441 247 V 455 368 V 1150 368 V 1202 332 a(Right-click:)30 +b(adv)n(ance)24 b(to)h(ne)o(xt)f(label)p 3441 368 V 457 +371 2986 4 v 455 491 4 121 v 507 455 a(Placer)p 1150 +491 V 447 w(Left-click:)30 b(place)25 b(label)p 3441 +491 V 455 612 V 1150 612 V 1202 576 a(Right-click:)30 +b(change)25 b(label)f(te)o(xt)g(position)p 3441 612 V +457 615 2986 4 v 455 736 4 121 v 507 699 a(Pumps)p 1150 +736 V 423 w(Left-click:)30 b(decrement)25 b(number)p +3441 736 V 455 856 V 1150 856 V 1202 820 a(Right-click:)30 +b(increment)24 b(number)p 3441 856 V 457 859 2986 4 v +455 980 4 121 v 507 944 a(Find)p 1150 980 V 512 w(Search)i(under)e +(box,)h(highlight)d(labels)p 3441 980 V 455 1100 V 1150 +1100 V 1202 1064 a(matching)h(current)i(te)o(xt)p 3441 +1100 V 457 1103 2986 4 v 455 1224 4 121 v 507 1188 a(Current)g(Netlist) +p 1150 1224 V 99 w(Left-click:)30 b(prompt)24 b(for)h(ne)n(w)f(netlist) +g(name)p 3441 1224 V 455 1344 V 1150 1344 V 1202 1308 +a(Right-click:)30 b(use)24 b(edit)h(cell)f(name)h(as)g(netlist)e(name)p +3441 1344 V 457 1347 2986 4 v 455 1468 4 121 v 507 1432 +a(V)-11 b(erify)p 1150 1468 V 446 w(Check)25 b(that)g(wiring)f(matches) +g(netlist)f(\(same)i(as)p 3441 1468 V 455 1588 V 1150 +1588 V 1202 1552 a(typing)e Fc(:v)o(erify)i Fe(command\))p +3441 1588 V 457 1592 2986 4 v 455 1712 4 121 v 507 1676 +a(Print)p 1150 1712 V 501 w(Print)f(names)h(of)g(all)f(terminals)g(in)g +(selected)h(net)p 3441 1712 V 455 1832 V 1150 1832 V +1202 1796 a(\(same)g(as)f(typing)g Fc(:print)i Fe(command\))p +3441 1832 V 457 1836 2986 4 v 455 1956 4 121 v 507 1920 +a(T)-7 b(erms)p 1150 1956 V 447 w(Place)25 b(feedback)h(areas)f(on)g +(screen)g(to)g(identify)f(all)g(terminals)p 3441 1956 +V 455 2076 V 1150 2076 V 1202 2040 a(in)g(current)h(netlist)f(\(same)g +(as)h Fc(:sho)o(wterms)h Fe(command\))p 3441 2076 V 457 +2080 2986 4 v 455 2200 4 121 v 507 2164 a(Cleanup)p 1150 +2200 V 363 w(Check)f(current)g(netlist)f(for)h(missing)e(labels)h(and)h +(nets)p 3441 2200 V 455 2320 V 1150 2320 V 1202 2284 +a(with)f(less)g(than)h(tw)o(o)f(terminals)g(\(same)g(as)h(typing)p +3441 2320 V 457 2324 2986 4 v 455 2444 4 121 v 1150 2444 +V 1202 2408 a Fc(:cleanup)h Fe(command\))p 3441 2444 +V 455 2565 V 507 2528 a(No)f(Net)p 1150 2565 V 404 w(Delete)g(selected) +f(net)h(\(same)g(as)g Fc(:dnet)h Fe(command\))p 3441 +2565 V 457 2568 2986 4 v 455 2688 4 121 v 507 2652 a(Sho)n(w)p +1150 2688 V 470 w(Highlight)d(paint)h(connected)h(to)f(material)g +(under)h(box)p 3441 2688 V 455 2809 V 1150 2809 V 1202 +2773 a(\(same)g(as)f(typing)g Fc(:sho)o(wnet)i Fe(command\))p +3441 2809 V 457 2812 2986 4 v 788 2971 a(T)-8 b(able)25 +b(1:)31 b(A)24 b(summary)g(of)h(all)g(the)f(netlist)g(menu)g(b)n(utton) +f(actions.)0 3328 y(will)29 b(assume)g(that)g(the)o(y)f(are)j +(electrically)e(equi)n(v)n(alent)f(\(connected)h(together)h(within)e +(the)h(cell\).)45 b(Because)31 b(of)0 3448 y(this,)k(when)f(routing)f +(the)g(net)h(it)g(will)f(feel)h(free)h(to)e(connect)h(to)g(whiche)n(v)o +(er)e(one)i(of)g(the)g(terminals)f(is)g(most)0 3568 y(con)l(v)o +(enient,)k(and)e(ignore)g(the)h(others.)62 b(In)36 b(some)f(cases)g +(the)h(router)f(may)g(tak)o(e)h(adv)n(antage)f(of)g(electrically)0 +3689 y(equi)n(v)n(alent)17 b(terminals)i(by)g(using)f +Ff(feed)h(thr)l(oughs)p Fe(:)26 b(entering)19 b(a)g(cell)h(at)f(one)g +(terminal)g(to)g(mak)o(e)g(one)g(connection,)0 3809 y(and)32 +b(e)o(xiting)e(through)h(an)g(equi)n(v)n(alent)f(terminal)h(on)h(the)f +(w)o(ay)h(to)f(mak)o(e)h(another)g(connection)f(for)h(the)f(same)0 +3929 y(net.)0 4267 y Fg(3)143 b(Menu)36 b(f)l(or)f(Label)g(Editing)0 +4491 y Fe(Magic)25 b(pro)o(vides)e(a)i(special)g(menu)f(f)o(acility)g +(to)h(assist)f(you)g(in)h(placing)f(terminal)g(labels)g(and)h(editing)f +(netlists.)0 4611 y(T)-8 b(o)25 b(mak)o(e)f(the)h(menu)f(appear)l(,)i +(in)l(v)n(ok)o(e)e(the)g(Magic)h(command)900 4825 y Fc(:specialopen)h +(netlist)146 5039 y Fe(A)c(ne)n(w)f(windo)n(w)g(will)g(appear)h(in)f +(the)h(lo)n(wer)n(-left)f(corner)h(of)g(the)g(screen,)g(containing)f +(se)n(v)o(eral)g(rectangular)0 5159 y(areas)32 b(on)g(a)g(purple)f +(background.)51 b(Each)32 b(of)f(the)h(rectangular)g(areas)g(is)f +(called)h(a)g Ff(b)n(utton)p Fe(.)50 b(Clicking)31 b(mouse)0 +5280 y(b)n(uttons)23 b(inside)g(the)i(menu)f(b)n(uttons)e(will)i(in)l +(v)n(ok)o(e)g(v)n(arious)f(commands)g(to)h(edit)g(labels)g(and)h +(netlists.)k(Figure)24 b(2)0 5400 y(sho)n(ws)19 b(a)h(diagram)f(of)h +(the)g(netlist)f(menu)g(and)h(T)-8 b(able)20 b(I)g(summarizes)f(the)h +(meaning)f(of)h(b)n(utton)e(clicks)i(in)f(v)n(arious)1875 +5649 y(\2264\226)p eop +%%Page: 5 5 +5 4 bop 0 -180 a Fe(Magic)24 b(T)l(utorial)g(#7:)30 b(Netlists)23 +b(and)i(Routing)1717 b(April)24 b(12,)h(2006)0 68 y(menu)k(items.)42 +b(The)30 b(netlist)e(menu)g(can)i(be)f(gro)n(wn,)g(shrunk,)h(and)f(mo)o +(v)o(ed)e(just)i(lik)o(e)f(an)o(y)h(other)g(windo)n(w;)h(see)0 +188 y(\223Magic)e(T)l(utorial)g(#5:)38 b(Multiple)26 +b(W)l(indo)n(ws\224)i(for)h(details.)41 b(It)29 b(also)f(has)g(its)g(o) +n(wn)g(pri)n(v)n(ate)f(set)i(of)f(commands.)0 309 y(T)-8 +b(o)25 b(see)g(what)f(commands)g(you)g(can)h(type)g(in)f(the)h(netlist) +e(menu,)i(mo)o(v)o(e)e(the)i(cursor)f(o)o(v)o(er)g(the)h(menu)f(and)h +(type)900 561 y Fc(:help)146 810 y Fe(Y)-11 b(ou)28 b(shouldn')n(t)e +(need)i(to)f(type)g(commands)f(in)h(the)h(netlist)e(menu)h(v)o(ery)g +(often,)h(since)g(almost)e(e)n(v)o(erything)0 931 y(you')o(ll)33 +b(need)i(to)f(do)g(can)h(be)f(done)g(using)f(the)i(menu.)58 +b(See)36 b(Section)e(9)g(for)h(a)f(description)g(of)g(a)h(fe)n(w)f(of)g +(the)0 1051 y(commands)29 b(you)g(can)i(type;)h(the)d(complete)h(set)g +(is)f(described)h(in)g(the)f(manual)h(page)g Ff(ma)o(gic\(1\))p +Fe(.)46 b(One)30 b(of)g(the)0 1172 y(best)24 b(uses)g(for)g(the)h +(commands)e(is)h(so)g(that)f(you)h(can)h(de\002ne)g(macros)f(for)h +(them)e(and)i(a)n(v)n(oid)e(ha)n(ving)h(to)g(go)g(back)0 +1292 y(and)32 b(forth)f(to)h(the)g(menu;)i(look)d(up)h(the)f +Fc(:send)i Fe(command)e(in)g(the)h(man)g(page)g(to)f(see)h(ho)n(w)f(to) +h(do)f(this.)51 b(The)0 1412 y(top)29 b(half)h(of)g(the)g(menu)f(is)g +(for)h(placing)g(labels)f(and)h(the)f(bottom)g(half)g(is)h(for)g +(editing)f(netlists.)44 b(This)29 b(section)0 1533 y(describes)c(the)f +(label)h(f)o(acilities,)f(and)h(Section)f(4)h(describes)g(the)f +(netlist)g(f)o(acilities.)146 1656 y(The)j(label)f(menu)h(mak)o(es)f +(it)g(easy)h(for)g(you)f(to)g(enter)h(lots)f(of)h(labels,)f +(particularly)g(when)h(there)g(are)g(man)o(y)0 1777 y(labels)i(that)g +(are)h(the)f(same)g(e)o(xcept)g(for)g(a)h(number)l(,)f(e.g.)45 +b Fc(b)n(us1)p Fe(,)30 b Fc(b)n(us2)p Fe(,)h Fc(b)n(us3)p +Fe(,)g(etc.)44 b(There)30 b(are)g(four)f(sections)0 1897 +y(to)h(the)f(label)h(menu:)41 b(the)29 b(current)i(te)o(xt,)f(the)g +(placer)l(,)i(tw)o(o)d(pumps,)h(and)g(the)g Fc(Find)g +Fe(b)n(utton.)46 b(T)-8 b(o)29 b(place)i(labels,)0 2017 +y(\002rst)f(click)g(the)g(left)g(mouse)f(b)n(utton)g(o)o(v)o(er)g(the)h +(current)g(te)o(xt)f(rectangle.)46 b(Then)30 b(type)g(one)g(or)g(more)g +(labels)f(on)0 2138 y(the)23 b(k)o(e)o(yboard,)f(one)h(per)g(line.)29 +b(Y)-11 b(ou)23 b(can)g(use)f(this)g(mechanism)g(to)g(enter)h(se)n(v)o +(eral)f(labels)h(at)f(once.)30 b(T)-8 b(ype)23 b(return)0 +2258 y(twice)k(to)f(signal)g(the)g(end)h(of)g(the)f(list.)36 +b(At)26 b(this)g(point,)g(the)h(\002rst)g(of)f(the)h(labels)f(you)h +(typed)f(will)g(appear)h(in)f(the)0 2378 y(current)f(te)o(xt)f +(rectangle.)146 2502 y(T)-8 b(o)33 b(place)h(a)g(label,)h(position)c +(the)j(box)e(o)o(v)o(er)h(the)g(area)h(you)f(w)o(ant)g(to)g(label,)i +(then)e(click)g(the)h(left)f(mouse)0 2622 y(b)n(utton)c(inside)h(one)g +(of)h(the)f(squares)g(of)h(the)f(placer)h(area.)49 b(A)30 +b(label)g(will)g(be)g(created)i(with)d(the)h(current)h(te)o(xt.)0 +2743 y(Where)25 b(you)f(click)h(in)f(the)g(placer)h(determines)f(where) +h(the)g(label)f(te)o(xt)g(will)f(appear)i(relati)n(v)o(e)f(to)g(the)h +(label)f(box:)0 2863 y(for)f(e)o(xample,)g(clicking)f(the)h +(left-center)g(square)g(causes)h(the)f(te)o(xt)f(to)g(be)h(centered)h +(just)e(to)h(the)g(left)g(of)g(the)g(box.)0 2983 y(Y)-11 +b(ou)22 b(can)h(place)f(man)o(y)g(copies)g(of)g(the)g(same)g(label)g +(by)g(mo)o(ving)f(the)h(box)g(and)g(clicking)g(the)g(placer)h(area)g +(again.)0 3104 y(Y)-11 b(ou)26 b(can)i(re-orient)e(the)h(te)o(xt)f(of)h +(a)g(label)f(by)h(clicking)f(the)g(right)g(mouse)g(b)n(utton)g(inside)g +(the)g(placer)i(area.)37 b(F)o(or)0 3224 y(e)o(xample,)25 +b(if)g(you)h(w)o(ould)e(lik)o(e)i(to)f(mo)o(v)o(e)f(a)i(label')-5 +b(s)25 b(te)o(xt)f(so)i(that)f(it)g(appears)h(centered)g(abo)o(v)o(e)f +(the)g(label,)h(place)0 3344 y(the)f(box)f(o)o(v)o(er)g(the)h(label)f +(and)h(right-click)f(the)h(top-center)f(placer)i(square.)146 +3468 y(If)k(you)f(entered)h(se)n(v)o(eral)f(labels)g(at)h(once,)h(only) +d(the)i(\002rst)g(appears)f(in)h(the)f(current)h(te)o(xt)e(area.)46 +b(Ho)n(we)n(v)o(er)l(,)0 3588 y(you)23 b(can)g(adv)n(ance)g(to)g(the)f +(ne)o(xt)h(label)f(by)h(right-clicking)f(inside)g(the)h(current)g(te)o +(xt)f(area.)31 b(In)23 b(this)f(w)o(ay)h(you)g(can)0 +3709 y(place)32 b(a)f(long)g(series)g(of)g(labels)g(entirely)g(with)f +(the)i(mouse.)49 b(T)m(ry)31 b(using)f(this)g(mechanism)h(to)f(add)i +(labels)e(to)0 3829 y Fc(tut7a)p Fe(.)146 3952 y(The)20 +b(tw)o(o)g(small)f(b)n(uttons)f(underneath)i(the)f(right)h(side)f(of)h +(the)g(current)g(te)o(xt)f(area)i(are)f(called)g(pumps.)28 +b(T)-8 b(o)20 b(see)0 4073 y(ho)n(w)30 b(these)h(w)o(ork,)h(enter)g(a)f +(label)g(name)g(containing)e(a)j(number)e(into)g(the)h(current)g(te)o +(xt)f(area,)k(for)d(e)o(xample,)0 4193 y Fc(b)n(us1)p +Fe(.)54 b(When)33 b(you)f(do)g(this,)i(the)e(\2231\224)h(appears)g(in)f +(the)h(left)f(pump.)53 b(Right-clicking)32 b(the)g(pump)g(causes)g(the) +0 4314 y(number)d(to)f(increment,)i(and)f(left-clicking)g(the)g(pump)f +(causes)h(the)g(number)g(to)g(decrement.)43 b(This)29 +b(mak)o(es)g(it)0 4434 y(easy)34 b(for)h(you)f(to)g(enter)g(a)h(series) +f(of)g(numbered)g(signal)g(names.)58 b(If)35 b(a)g(name)f(has)g(tw)o(o) +g(numbers)f(in)h(it,)i(the)0 4554 y(second)22 b(number)f(will)g(appear) +i(in)f(the)f(second)h(pump,)g(and)g(it)f(can)i(be)f(incremented)f(or)h +(decremented)g(too.)30 b(T)m(ry)0 4675 y(using)24 b(the)g(pumps)g(to)g +(place)i(a)f(series)f(of)h(numbered)g(names.)146 4798 +y(The)h(last)g(entry)g(in)g(the)f(label)h(portion)f(of)h(the)g(menu)g +(is)g(the)f Fc(Find)i Fe(b)n(utton.)33 b(This)26 b(can)g(be)g(used)g +(to)g(locate)g(a)0 4918 y(label)e(by)g(searching)g(for)g(a)h(gi)n(v)o +(en)d(pattern.)31 b(If)24 b(you)g(click)g(the)g Fc(Find)h +Fe(b)n(utton,)d(Magic)i(will)g(use)g(the)g(current)g(te)o(xt)0 +5039 y(as)30 b(a)h(pattern)f(and)g(search)h(the)f(area)i(underneath)e +(the)g(box)g(for)g(a)h(label)f(whose)g(name)g(contains)f(the)h +(pattern.)0 5159 y(P)o(attern-matching)24 b(is)g(done)h(in)f(the)h +(same)f(w)o(ay)h(as)g(in)f Ff(csh)p Fe(,)h(using)f(the)h(special)f +(characters)i(\223*\224,)f(\223?\224,)g(\223)0 5280 y(\224,)e +(\223[\224,)h(and)e(\223]\224.)31 b(T)m(ry)22 b(this)g(on)g +Fc(tut7a)p Fe(:)30 b(enter)23 b(\223good*\224)f(into)g(the)g(current)h +(te)o(xt)f(area,)h(place)g(the)g(box)f(around)g(the)0 +5400 y(whole)29 b(cell,)i(then)e(click)h(on)f(the)g(\223Find\224)h(b)n +(utton.)44 b(F)o(or)30 b(each)g(of)g(the)f(good)g(labels,)h(a)g +(feedback)h(area)f(will)f(be)1875 5649 y(\2265\226)p +eop +%%Page: 6 6 +6 5 bop 0 -180 a Fe(April)24 b(12,)h(2006)1717 b(Magic)24 +b(T)l(utorial)g(#7:)30 b(Netlists)23 b(and)i(Routing)0 +69 y(created)h(with)f(white)h(stripes)f(to)g(highlight)f(the)h(area.)35 +b(The)26 b Fc(:feedback)i(\002nd)f Fe(command)e(can)h(be)g(used)f(to)h +(step)0 189 y(through)h(the)h(areas,)i(and)e Fc(:feedback)i(clear)f +Fe(will)e(erase)i(the)f(feedback)g(information)f(from)h(the)g(screen.) +41 b(The)0 309 y Fc(:feedback)26 b Fe(command)d(has)g(man)o(y)g(of)h +(the)g(same)f(options)f(as)i Fc(:dr)n(c)h Fe(for)f(getting)f +(information)f(about)h(feedback)0 430 y(areas;)h(see)g(the)g(Magic)f +(manual)g(page)h(for)f(details,)g(or)h(type)f Fc(:feedback)j(help)e +Fe(for)g(a)g(synopsis)e(of)h(the)h(options.)0 782 y Fg(4)143 +b(Netlist)34 b(Editing)0 1010 y Fe(After)j(placing)f(terminal)f +(labels,)k(the)d(ne)o(xt)g(step)g(is)g(to)g(specify)g(the)g +(connections)f(between)i(them;)k(this)36 b(is)0 1130 +y(called)22 b(netlist)f(editing.)28 b(The)22 b(bottom)f(half)h(of)g +(the)g(netlist)e(menu)i(is)f(used)h(for)g(editing)f(netlists.)28 +b(The)22 b(\002rst)g(thing)0 1251 y(you)h(must)g(do)g(is)g(to)g +(specify)h(the)f(netlist)f(you)h(w)o(ant)h(to)f(edit.)30 +b(Do)23 b(this)g(by)g(clicking)g(in)g(the)h(current)f(netlist)g(box.)0 +1371 y(If)g(you)g(left-click,)g(Magic)f(will)g(prompt)g(you)g(for)h +(the)g(netlist)f(name)g(and)h(you)g(can)g(type)f(it)h(at)g(the)f(k)o(e) +o(yboard.)30 b(If)0 1491 y(you)24 b(right-click,)g(Magic)h(will)f(use)h +(the)f(name)h(of)g(the)g(edit)f(cell)h(as)g(the)g(current)g(netlist)e +(name.)31 b(In)25 b(either)g(case,)0 1612 y(Magic)f(will)g(read)h(the)g +(netlist)e(from)h(disk)g(if)h(it)f(e)o(xists)f(and)h(will)g(create)i(a) +e(ne)n(w)h(netlist)e(if)h(there)h(isn')n(t)f(currently)0 +1732 y(a)j(netlist)f(\002le)h(with)f(the)g(gi)n(v)o(en)f(name.)37 +b(Netlist)25 b(\002les)i(are)h(stored)e(on)h(disk)f(with)g(a)h +(\223.net\224)g(e)o(xtension,)e(which)i(is)0 1853 y(added)g(by)g(Magic) +g(when)h(it)e(reads)i(and)f(writes)g(\002les.)39 b(Y)-11 +b(ou)27 b(can)g(change)h(the)f(current)h(netlist)e(by)h(clicking)f(the) +0 1973 y(current)32 b(netlist)f(b)n(utton)g(again.)52 +b(Startup)32 b(Magic)g(on)g(the)g(cell)g Fc(tut7b)p Fe(,)j(open)d(the)g +(netlist)f(menu,)i(and)f(set)g(the)0 2093 y(current)25 +b(netlist)f(to)g Fc(tut7b)p Fe(.)32 b(Then)24 b(e)o(xpand)g(the)h +(subcells)f(in)g Fc(tut7b)i Fe(so)f(that)f(you)g(can)i(see)f(their)f +(terminals.)p 849 2243 2203 4 v 847 2363 4 121 v 899 +2327 a(Button)p 1234 2363 V 115 w(Action)p 3050 2363 +V 849 2366 2203 4 v 847 2487 4 121 v 899 2451 a(Left)p +1234 2487 V 221 w(Select)h(net,)g(using)f(nearest)h(terminal)f(to)g +(cursor)-5 b(.)p 3050 2487 V 849 2490 2203 4 v 847 2610 +4 121 v 899 2574 a(Right)p 1234 2610 V 165 w(T)d(oggle)24 +b(nearest)h(terminal)f(into)g(or)h(out)f(of)p 3050 2610 +V 847 2731 V 1234 2731 V 1286 2695 a(current)h(net.)p +3050 2731 V 849 2734 2203 4 v 847 2854 4 121 v 899 2818 +a(Middle)p 1234 2854 V 98 w(Find)g(nearest)g(terminal,)e(join)h(its)g +(net)h(with)f(the)p 3050 2854 V 847 2975 V 1234 2975 +V 1286 2939 a(current)h(net.)p 3050 2975 V 849 2978 2203 +4 v 465 3137 a(T)-8 b(able)24 b(2:)31 b(The)25 b(actions)f(of)h(the)f +(mouse)g(b)n(uttons)g(when)g(the)h(terminal)f(tool)g(is)g(in)h(use.)146 +3470 y(Netlist)d(editing)h(is)g(done)g(with)f(the)h(netlist)f(tool.)30 +b(If)24 b(you)e(ha)n(v)o(en')n(t)h(already)h(read)g(\223T)l(utorial)e +(#3:)30 b(Adv)n(anced)0 3590 y(P)o(ainting)37 b(\(W)l(iring)h(and)g +(Plo)n(wing\)\224,)j(you)d(should)f(read)i(it)f(no)n(w)-6 +b(,)40 b(up)f(through)e(Section)h(2.1.)71 b(T)l(utorial)37 +b(#3)0 3711 y(e)o(xplained)22 b(ho)n(w)f(to)h(change)h(the)g(current)f +(tool)g(by)g(using)g(the)g(space)h(macro)g(or)g(by)f(typing)f +Fc(:tool)p Fe(.)30 b(Switch)22 b(tools)0 3831 y(to)i(the)h(netlist)f +(tool)f(\(the)i(cursor)g(will)f(appear)h(as)g(a)h(thick)e(square\).)146 +3953 y(When)h(the)g(netlist)f(tool)g(is)g(in)h(use)f(the)h(left,)g +(right,)f(and)h(middle)f(b)n(uttons)f(in)l(v)n(ok)o(e)h(select,)h +(toggle,)f(and)h(join)0 4074 y(operations)32 b(respecti)n(v)o(ely)e +(\(see)j(T)-8 b(able)33 b(II\).)g(T)-8 b(o)32 b(see)h(ho)n(w)e(the)o(y) +h(w)o(ork,)i(mo)o(v)o(e)d(the)h(cursor)g(o)o(v)o(er)g(the)g(terminal)0 +4194 y Fc(right4)c Fe(in)f(the)g(top)g(subcell)g(of)g +Fc(tut7b)i Fe(and)e(click)h(the)f(left)g(mouse)g(b)n(utton)f(\(you)i +(may)f(ha)n(v)o(e)g(to)g(zoom)g(in)g(a)h(bit)0 4315 y(to)j(see)h(the)f +(labels;)k(terminals)30 b(are)i(numbered)g(in)f(clockwise)g(order:)44 +b Fc(right4)32 b Fe(is)f(the)g(fourth)h(terminal)e(from)0 +4435 y(the)23 b(top)g(on)h(the)f(right)g(side\).)30 b(This)23 +b(causes)h(the)f(net)g(containing)g(that)g(terminal)g(to)g(be)g +(selected.)31 b(Three)24 b(hollo)n(w)0 4555 y(white)34 +b(squares)h(will)f(appear)h(o)o(v)o(er)f(the)g(layout,)j(marking)c(the) +i(terminals)f(that)g(are)h(supposed)f(to)g(be)h(wired)0 +4676 y(together)30 b(into)f Fc(right4)p Fe(')-5 b(s)31 +b(net.)47 b(Left-click)30 b(o)o(v)o(er)g(the)g Fc(left3)h +Fe(terminal)e(in)h(the)g(same)h(subcell)e(to)h(select)h(its)e(net,)0 +4796 y(then)24 b(select)h(the)g Fc(right4)g Fe(net)g(again.)146 +4918 y(The)d(right)g(b)n(utton)f(is)g(used)h(to)g(toggle)f(terminals)g +(into)h(or)g(out)f(of)h(the)g(current)h(net.)29 b(If)23 +b(you)f(right-click)f(o)o(v)o(er)0 5039 y(a)26 b(terminal)e(that)h(is)g +(in)g(the)g(current)h(net,)f(then)g(it)g(is)g(remo)o(v)o(ed)f(from)h +(the)h(current)f(net.)33 b(If)25 b(you)g(right-click)g(o)o(v)o(er)0 +5159 y(a)h(terminal)g(that)f(isn')n(t)h(in)f(the)h(current)g(net,)h(it) +e(is)h(added)g(to)f(the)h(current)h(net.)34 b(A)26 b(single)f(terminal) +g(can)i(only)e(be)0 5280 y(in)31 b(one)g(net)g(at)h(a)f(time,)i(so)e +(if)g(a)g(terminal)g(is)g(already)g(in)g(a)h(net)f(when)g(you)g(toggle) +g(it)g(into)f(another)h(net)g(then)0 5400 y(Magic)h(will)f(remo)o(v)o +(e)g(it)g(from)h(the)g(old)g(net.)52 b(T)-8 b(oggle)31 +b(the)h(terminal)g Fc(top4)g Fe(in)g(the)g(bottom)e(cell)i(out)g(of,)h +(then)1875 5649 y(\2266\226)p eop +%%Page: 7 7 +7 6 bop 0 -180 a Fe(Magic)24 b(T)l(utorial)g(#7:)30 b(Netlists)23 +b(and)i(Routing)1717 b(April)24 b(12,)h(2006)0 69 y(back)d(into,)g(the) +g(net)f(containing)g Fc(right4)p Fe(.)30 b(No)n(w)21 +b(toggle)h Fc(left3)g Fe(in)f(the)h(bottom)f(cell)h(into)f(this)g(net.) +29 b(Magic)22 b(w)o(arns)0 189 y(you)29 b(because)i(it)e(had)h(to)f +(remo)o(v)o(e)g Fc(left3)h Fe(from)g(another)g(net)f(in)h(order)g(to)f +(add)h(it)g(to)f Fc(right4)p Fe(')-5 b(s)30 b(net.)45 +b(T)-8 b(ype)30 b Fc(u)g Fe(to)0 309 y(undo)23 b(this)f(change,)i(then) +f(left-click)g(on)g Fc(left3)g Fe(to)g(mak)o(e)g(sure)h(it)f(got)f +(restored)i(to)f(its)f(old)h(net)g(by)g(the)g(undo.)30 +b(All)0 430 y(of)25 b(the)g(netlist-editing)d(operations)i(are)h +(undo-able.)146 550 y(The)i(middle)f(b)n(utton)g(is)h(used)g(to)f(mer)n +(ge)i(tw)o(o)f(nets)f(together)-5 b(.)37 b(If)27 b(you)g(middle-click)f +(o)o(v)o(er)g(a)i(terminal,)e(all)0 671 y(the)h(terminals)g(in)g(its)f +(net)i(are)g(added)f(to)g(the)h(current)f(net.)39 b(Play)27 +b(around)h(with)e(the)i(three)f(b)n(uttons)f(to)h(edit)g(the)0 +791 y(netlist)c Fc(tut7b)p Fe(.)146 911 y(Note:)46 b(the)33 +b(router)f(does)g(not)g(mak)o(e)h(connections)f(to)g(terminals)f(in)h +(the)h(top)f(le)n(v)o(el)f(cell.)54 b(It)33 b(only)f(w)o(orks)0 +1032 y(with)27 b(terminals)g(in)h(subcells,)f(or)h(sub-subcells,)g +(etc.)40 b(Because)29 b(of)f(this,)g(the)g(netlist)e(editor)i(does)f +(not)h(permit)0 1152 y(you)c(to)h(select)f(terminals)g(in)h(the)f(top)g +(le)n(v)o(el)g(cell.)31 b(If)25 b(you)f(click)h(o)o(v)o(er)f(such)g(a)h +(terminal)f(Magic)h(prints)e(an)i(error)0 1272 y(message)f(and)h +(refuses)g(to)g(mak)o(e)f(the)h(selection.)146 1393 y(If)33 +b(you)g(left-click)f(o)o(v)o(er)g(a)h(terminal)f(that)g(is)g(not)g +(currently)g(in)h(a)g(net,)h(Magic)e(creates)i(a)f(ne)n(w)f(net)g +(auto-)0 1513 y(matically)-6 b(.)42 b(If)29 b(you)g(didn')n(t)f(really) +h(w)o(ant)g(to)g(mak)o(e)g(a)g(ne)n(w)g(net,)h(you)e(ha)n(v)o(e)h(se)n +(v)o(eral)f(choices.)44 b(Either)28 b(you)h(can)0 1634 +y(toggle)e(the)h(terminal)f(out)g(of)h(its)f(o)n(wn)g(net,)h(you)g(can) +g(undo)f(the)h(select)g(operation,)f(or)h(you)g(can)g(click)g(the)f +Fc(No)0 1754 y(Net)h Fe(b)n(utton)d(in)i(the)g(netlist)f(menu)g(\(you)h +(can)h(do)f(this)f(e)n(v)o(en)g(while)h(the)g(cursor)g(is)f(in)h(the)g +(square)g(shape\).)38 b(The)0 1874 y Fc(No)29 b(Net)h +Fe(b)n(utton)f(remo)o(v)o(es)f(all)h(terminals)g(from)g(the)h(current)f +(net)h(and)f(destro)o(ys)g(the)h(net.)44 b(It')-5 b(s)29 +b(a)h(bad)g(idea)f(to)0 1995 y(lea)n(v)o(e)c(single-net)e(terminals)h +(in)h(the)f(netlist:)29 b(the)c(router)g(will)f(treat)h(them)f(as)h +(errors.)146 2115 y(There)k(are)f(tw)o(o)g(w)o(ays)f(to)h(sa)n(v)o(e)f +(netlists)f(on)i(disk;)g(these)g(are)g(similar)f(to)h(the)f(w)o(ays)h +(you)f(can)h(sa)n(v)o(e)g(layout)0 2236 y(cells.)i(If)c(you)e(type)900 +2455 y Fc(:sa)n(v)o(enetlist)g Fe([)p Ff(name)p Fe(])146 +2674 y(with)41 b(the)g(cursor)g(o)o(v)o(er)g(the)g(netlist)f(menu,)45 +b(the)c(current)g(netlist)f(will)h(be)g(sa)n(v)o(ed)g(on)g(disk)g(in)g +(the)g(\002le)0 2795 y Ff(name)p Fe(.)p Fc(net)p Fe(.)31 +b(If)26 b(no)e Ff(name)h Fe(is)f(typed,)g(the)h(name)g(of)g(the)f +(current)h(netlist)f(is)g(used.)30 b(If)c(you)e(type)h(the)f(command) +900 3014 y Fc(:writeall)146 3233 y Fe(then)19 b(Magic)g(will)f(step)h +(through)f(all)h(the)g(netlists)f(that)g(ha)n(v)o(e)h(been)h +(modi\002ed)e(since)h(the)o(y)f(were)i(last)f(written,)0 +3354 y(asking)30 b(you)g(if)g(you')-5 b(d)30 b(lik)o(e)g(them)g(to)g +(be)h(written)f(out.)47 b(If)31 b(you)f(try)h(to)f(lea)n(v)o(e)g(Magic) +g(without)f(sa)n(ving)h(all)g(the)0 3474 y(modi\002ed)24 +b(netlists,)f(Magic)i(will)f(w)o(arn)h(you)f(and)h(gi)n(v)o(e)e(you)i +(a)g(chance)g(to)g(write)f(them)h(out.)146 3594 y(If)k(you)e(mak)o(e)h +(changes)g(to)g(a)g(netlist)f(and)h(then)f(decide)h(you)g(don')n(t)g(w) +o(ant)f(them,)h(you)g(can)g(use)g(the)g Fc(:\003ush)0 +3715 y Fe(netlist)e(command)h(to)g(thro)n(w)g(a)o(w)o(ay)g(all)g(of)h +(the)g(changes)f(and)h(re-read)g(the)g(netlist)e(from)h(its)g(disk)g +(\002le.)40 b(If)28 b(you)0 3835 y(create)f(netlists)d(using)g(a)j(te)o +(xt)d(editor)i(or)f(some)g(other)h(program,)g(you)f(can)h(use)f +Fc(:\003ush)i Fe(after)g(you')-5 b(v)o(e)25 b(modi\002ed)0 +3955 y(the)g(netlist)e(\002le)i(in)g(order)g(to)f(mak)o(e)h(sure)g +(that)f(Magic)h(is)f(using)g(the)g(most)g(up-to-date)h(v)o(ersion.)146 +4076 y(The)f Fc(Print)f Fe(b)n(utton)f(in)h(the)g(netlist)f(menu)g +(will)h(print)f(out)h(on)g(the)g(te)o(xt)f(screen)i(the)f(names)f(of)i +(all)f(the)g(termi-)0 4196 y(nals)g(in)g(the)g(current)g(net.)30 +b(T)m(ry)23 b(this)f(for)i(some)e(of)i(the)f(nets)f(in)h +Fc(tut7b)p Fe(.)31 b(The)24 b(of)n(\002cial)f(name)g(of)g(a)h(terminal) +e(looks)0 4317 y(a)27 b(lot)g(lik)o(e)g(a)g(Unix)f(\002le)i(name,)g +(consisting)d(of)i(a)g(b)n(unch)g(of)g(\002elds)h(separated)f(by)g +(slashes.)37 b(Each)27 b(\002eld)g(e)o(xcept)0 4437 y(the)21 +b(last)f(is)h(the)g(id)f(of)h(a)g(subcell,)g(and)g(the)g(last)g +(\002eld)g(is)f(the)h(name)g(of)g(the)g(terminal.)28 +b(These)21 b(hierarchical)g(names)0 4557 y(pro)o(vide)f(unique)g(names) +g(for)i(each)f(terminal,)g(e)n(v)o(en)f(if)h(the)f(same)h(terminal)f +(name)h(is)f(re-used)h(in)g(dif)n(ferent)f(cells)0 4678 +y(or)25 b(if)g(there)g(are)g(multiple)e(copies)i(of)g(the)f(same)h +(cell.)146 4798 y(The)g Fc(V)-10 b(erify)25 b Fe(b)n(utton)f(will)g +(check)h(the)f(paint)h(of)f(the)h(edit)f(cell)h(to)g(be)f(sure)h(it)g +(implements)d(the)j(connections)0 4918 y(speci\002ed)g(in)f(the)g +(current)g(netlist.)29 b(Feedback)d(areas)f(are)g(created)g(to)f(sho)n +(w)f(nets)h(that)g(are)h(incomplete)e(or)i(nets)0 5039 +y(that)f(are)i(shorted)e(together)-5 b(.)146 5159 y(The)29 +b Fc(T)-9 b(erms)28 b Fe(b)n(utton)f(will)h(cause)g(Magic)g(to)g +(generate)h(a)g(feedback)f(area)i(o)o(v)o(er)d(each)i(of)f(the)g +(terminals)f(in)0 5280 y(the)h(current)g(netlist,)f(so)h(that)g(you)f +(can)i(see)f(which)f(terminals)g(are)i(included)e(in)h(the)g(netlist.) +39 b(If)28 b(you)g(type)f(the)0 5400 y(command)d Fc(:feedback)j(clear)e +Fe(in)f(a)h(layout)f(windo)n(w)g(then)g(the)h(feedback)g(will)f(be)h +(erased.)1875 5649 y(\2267\226)p eop +%%Page: 8 8 +8 7 bop 0 -180 a Fe(April)24 b(12,)h(2006)1717 b(Magic)24 +b(T)l(utorial)g(#7:)30 b(Netlists)23 b(and)i(Routing)146 +69 y(The)30 b Fc(Cleanup)h Fe(b)n(utton)d(is)i(there)g(as)f(a)h(con)l +(v)o(enience)g(to)f(help)h(you)f(cleanup)g(your)h(netlists.)44 +b(If)30 b(you)f(click)0 189 y(on)d(it,)g(Magic)f(will)g(scan)i(through) +e(the)g(current)i(netlist)d(to)i(mak)o(e)g(sure)g(it)g(is)f +(reasonable.)35 b Fc(Cleanup)27 b Fe(looks)e(for)0 309 +y(tw)o(o)31 b(error)h(conditions:)42 b(terminal)31 b(names)g(that)g +(don')n(t)g(correspond)g(to)g(an)o(y)g(labels)g(in)g(the)g(design,)h +(and)g(nets)0 430 y(that)27 b(don')n(t)g(ha)n(v)o(e)g(at)g(least)g(tw)o +(o)g(terminals.)38 b(When)27 b(it)g(\002nds)g(either)g(of)h(these)f +(conditions)f(it)g(prints)h(a)g(message)0 550 y(and)33 +b(gi)n(v)o(es)e(you)h(the)h(chance)g(to)g(either)g(delete)f(the)h(of)n +(fending)f(terminal)g(\(if)h(you)f(type)g Fc(dterm)p +Fe(\),)k(delete)d(the)0 671 y(of)n(fending)25 b(net)g(\()p +Fc(dnet)p Fe(\),)j(skip)d(the)g(current)h(problem)f(without)f +(modifying)g(the)i(netlist)e(and)i(continue)f(looking)0 +791 y(for)39 b(other)f(problems)g(\()p Fc(skip)p Fe(\),)k(or)d(abort)f +(the)h Fc(Cleanup)g Fe(command)f(without)f(making)h(an)o(y)g(more)g +(changes)0 911 y(\()p Fc(abort)p Fe(\).)146 1032 y(The)27 +b Fc(Sho)o(w)g Fe(b)n(utton)f(pro)o(vides)f(an)i(additional)f +(mechanism)f(for)i(displaying)e(the)i(paint)f(in)g(the)h(net.)36 +b(If)28 b(you)0 1153 y(place)35 b(the)g(box)f(o)o(v)o(er)g(a)h(piece)g +(of)g(paint)f(and)g(click)h(on)f Fc(Sho)o(w)p Fe(,)k(Magic)c(will)g +(highlight)f(all)h(of)h(the)f(paint)g(in)0 1273 y(the)j(net)f(under)h +(the)g(box.)66 b(This)36 b(is)g(similar)g(to)h(pointing)e(at)h(the)h +(net)g(and)g(typing)e Fc(s)i Fe(three)g(times)f(to)g(select)0 +1393 y(the)25 b(net,)h(e)o(xcept)f(that)g Fc(Sho)o(w)h +Fe(doesn')n(t)g(select)f(the)h(net)f(\(it)g(uses)h(a)f(dif)n(ferent)h +(mechanism)e(to)h(highlight)f(it\),)h(and)0 1514 y Fc(Sho)o(w)d +Fe(will)e(trace)i(through)e(all)h(cells,)g(e)o(xpanded)g(or)g(not)g +(\(the)g(selection)f(mechanism)g(only)h(considers)f(paint)g(in)0 +1634 y(e)o(xpanded)j(cells\).)31 b(Once)24 b(you')-5 +b(v)o(e)23 b(used)h Fc(Sho)o(w)g Fe(to)g(highlight)e(a)i(net,)g(the)g +(only)f(w)o(ay)h(to)f(mak)o(e)h(the)g(highlighting)0 +1754 y(go)k(a)o(w)o(ay)h(is)f(to)g(place)h(the)g(box)f(o)o(v)o(er)g +(empty)f(space)i(and)g(in)l(v)n(ok)o(e)f Fc(Sho)o(w)h +Fe(again.)42 b Fc(Sho)o(w)29 b Fe(is)f(an)h(old)f(command)0 +1875 y(that)23 b(pre-dates)i(the)e(selection)h(interf)o(ace,)g(b)n(ut)g +(we')-5 b(v)o(e)23 b(left)h(it)g(in)f(Magic)h(because)g(some)g(people)f +(\002nd)h(it)g(useful.)0 2218 y Fg(5)143 b(Netlist)34 +b(Files)0 2442 y Fe(Netlists)25 b(are)i(stored)f(on)g(disk)g(in)g +(ordinary)g(te)o(xt)f(\002les.)35 b(Y)-11 b(ou)26 b(are)i(welcome)e(to) +g(edit)g(those)f(\002les)i(by)f(hand)g(or)g(to)0 2562 +y(write)h(programs)g(that)g(generate)g(the)h(netlists)d(automatically) +-6 b(.)37 b(F)o(or)27 b(e)o(xample,)g(a)g(netlist)f(might)g(be)i +(generated)0 2683 y(by)d(a)g(schematic)f(editor)h(or)g(by)f(a)i +(high-le)n(v)o(el)d(simulator)-5 b(.)29 b(See)d(the)e(manual)h(page)g +Ff(net\(5\))g Fe(for)g(a)g(description)f(of)0 2803 y(netlist)f(\002le)j +(format.)0 3146 y Fg(6)143 b(Running)34 b(the)h(Router)0 +3371 y Fe(Once)27 b(you')-5 b(v)o(e)26 b(created)h(a)f(netlist,)g(it)g +(is)g(relati)n(v)o(ely)f(easy)h(to)g(in)l(v)n(ok)o(e)g(the)g(router)-5 +b(.)36 b(First,)26 b(place)h(the)f(box)g(around)0 3491 +y(the)21 b(area)g(you')-5 b(d)21 b(lik)o(e)f(Magic)g(to)h(consider)f +(for)h(routing.)28 b(No)21 b(terminals)f(outside)f(this)h(area)i(will)e +(be)h(considered,)0 3611 y(and)26 b(Magic)f(will)g(not)h(generate)g(an) +o(y)f(paint)h(more)f(than)h(a)g(fe)n(w)g(units)f(outside)f(this)h(area) +i(\(Magic)f(may)f(use)h(the)0 3732 y(ne)o(xt)g(routing)g(grid)h(line)f +(outside)g(the)h(area\).)38 b(Load)27 b Fc(tut7d)p Fe(,)i +Fc(:\003ush)f Fe(the)f(netlist)f(if)h(you)f(made)h(an)o(y)f(changes)h +(to)0 3852 y(it,)d(set)h(the)f(box)h(to)f(the)h(bounding)e(box)h(of)h +(the)g(cell,)g(and)f(then)h(in)l(v)n(ok)o(e)f(the)h(router)g(using)e +(the)i(command:)900 4084 y Fc(:r)n(oute)146 4316 y Fe(When)j(the)f +(command)f(completes,)h(the)g(netlist)f(should)g(be)i(routed.)38 +b(Click)27 b(the)g Fc(V)-10 b(erify)27 b Fe(netlist)f(b)n(utton)g(to)0 +4436 y(mak)o(e)31 b(sure)h(the)f(connections)f(were)i(made)f(correctly) +-6 b(.)50 b(T)m(ry)31 b(deleting)g(a)g(piece)h(from)f(one)g(of)h(the)f +(wires)g(and)0 4557 y(v)o(erify)e(again.)45 b(Feedback)31 +b(areas)g(should)d(appear)j(to)e(indicate)g(where)h(the)g(routing)f(w)o +(as)h(incorrect.)45 b(Use)30 b(the)0 4677 y Fc(:feedback)h +Fe(command)c(to)h(step)h(through)e(the)i(areas)g(and,)g(e)n(v)o +(entually)-6 b(,)27 b(to)i(delete)f(the)h(feedback)g(\()p +Fc(:feedback)0 4798 y(help)d Fe(gi)n(v)o(es)d(a)i(synopsis)e(of)i(the)g +(command)e(options\).)146 4918 y(If)28 b(the)g(router)f(is)h(unable)f +(to)g(complete)g(the)g(connections,)h(it)f(will)g(report)g(errors)h(to) +f(you.)39 b(Errors)28 b(may)f(be)0 5039 y(reported)g(in)f(se)n(v)o +(eral)g(w)o(ays.)36 b(F)o(or)27 b(some)f(errors,)h(such)g(as)g(non-e)o +(xistent)e(terminal)g(names,)i(messages)f(will)g(be)0 +5159 y(printed.)44 b(F)o(or)29 b(other)g(errors,)i(cross-hatched)e +(feedback)h(areas)g(will)e(be)i(created.)45 b(Most)28 +b(of)h(the)g(feedback)h(ar)n(-)0 5280 y(eas)d(ha)n(v)o(e)f(messages)g +(similar)g(to)g(\223Net)h(shifter/bit[0]/phi1:)32 b(Can')n(t)27 +b(mak)o(e)g(bottom)e(connection.)-7 b(\224)36 b(T)-8 +b(o)26 b(see)h(the)0 5400 y(message)c(associated)f(with)h(a)g(feedback) +h(area,)g(place)g(the)f(box)f(o)o(v)o(er)g(the)h(feedback)h(area)g(and) +f(type)g Fc(:feedback)1875 5649 y Fe(\2268\226)p eop +%%Page: 9 9 +9 8 bop 0 -180 a Fe(Magic)24 b(T)l(utorial)g(#7:)30 b(Netlists)23 +b(and)i(Routing)1717 b(April)24 b(12,)h(2006)0 68 y Fc(wh)o(y)p +Fe(.)52 b(In)31 b(this)g(case)i(the)e(message)h(means)f(that)h(for)g +(some)f(reason)h(the)g(router)g(w)o(as)f(unable)h(to)f(connect)h(the)0 +188 y(speci\002ed)e(net)g(\(named)f(by)h(one)g(of)f(its)g(terminals\))g +(within)g(one)h(of)f(the)h(routing)f(channel.)45 b(The)30 +b(terms)f(\223bot-)0 309 y(tom\224,)k(\223top\224,)h(etc.)53 +b(may)32 b(be)g(misnomers)e(because)j(Magic)f(sometimes)e(rotates)i +(channels)g(before)g(routing:)0 429 y(the)26 b(names)f(refer)i(to)e +(the)h(direction)e(at)i(the)g(time)f(the)g(channel)h(w)o(as)g(routed,)f +(not)g(the)h(direction)f(in)g(the)h(circuit.)0 549 y(Ho)n(we)n(v)o(er)l +(,)i(the)h(location)f(of)g(the)h(feedback)g(area)h(indicates)e(where)h +(the)g(connection)f(w)o(as)g(supposed)g(to)g(ha)n(v)o(e)0 +670 y(been)d(made.)146 919 y(Y)-11 b(ou')-5 b(v)o(e)24 +b(probably)f(noticed)h(by)f(no)n(w)h(that)f(the)h(router)g(sometimes)f +(generates)h(unnecessary)g(wiring,)f(such)0 1040 y(as)36 +b(inserting)f(e)o(xtra)h(jogs)g(and)g(U-shapes)g(in)g(wires)g(\(look)f +(ne)o(xt)h(to)g Fc(right3)g Fe(in)g(the)g(top)g(cell\).)65 +b(These)36 b(jogs)0 1160 y(are)31 b(particularly)f(noticeable)g(in)g +(small)g(e)o(xamples.)46 b(Ho)n(we)n(v)o(er)l(,)31 b(the)f(router)h +(actually)f(does)g Ff(better)g Fe(on)g(lar)n(ger)0 1281 +y(e)o(xamples:)37 b(there)29 b(will)f(still)f(be)i(a)g(bit)f(of)g(e)o +(xtra)h(wire,)g(b)n(ut)f(it')-5 b(s)28 b(ne)o(gligible)f(in)h +(comparison)f(to)i(the)f(total)g(wire)0 1401 y(length)g(on)h(a)g(lar)n +(ge)h(chip.)43 b(Some)29 b(of)g(this)f(wire)h(is)g(necessary)g(and)g +(important:)38 b(it)29 b(helps)f(the)h(router)g(to)g(a)n(v)n(oid)0 +1521 y(se)n(v)o(eral)j(problem)f(situations)g(that)h(w)o(ould)f(cause)i +(it)f(to)g(f)o(ail)g(on)g(more)h(dif)n(\002cult)e(e)o(xamples.)53 +b(Ho)n(we)n(v)o(er)l(,)33 b(you)0 1642 y(can)i(use)g(the)g +Fc(straighten)h Fe(command)e(described)h(in)f(\223Magic)h(T)l(utorial)f +(#3:)50 b(Adv)n(anced)35 b(P)o(ainting)f(\(W)l(iring)0 +1762 y(and)26 b(Plo)n(wing\)\224)f(to)g(remo)o(v)o(e)g(unnecessary)h +(jogs.)33 b(Please)27 b(don')n(t)e(judge)h(the)f(router)h(by)g(its)f +(beha)n(vior)h(on)f(small)0 1882 y(e)o(xamples.)30 b(On)24 +b(the)h(other)g(hand,)f(if)h(it)f(does)h(a)o(wful)f(things)f(on)i(big)f +(e)o(xamples,)g(we')-5 b(d)25 b(lik)o(e)f(to)h(kno)n(w)e(about)i(it.) +146 2132 y(All)i(of)g(the)f(wires)h(placed)g(by)g(the)f(router)h(are)h +(of)f(the)f(same)h(width,)f(so)h(the)g(router)f(w)o(on')n(t)h(be)g(v)o +(ery)g(useful)0 2252 y(for)e(po)n(wer)f(and)h(ground)f(wiring.)146 +2502 y(When)37 b(using)e(the)h(Magic)g(router)l(,)j(you)d(can)g(wire)h +(po)n(wer)e(and)i(ground)e(by)h(hand)g(before)h(running)e(the)0 +2622 y(router)-5 b(.)34 b(The)26 b(router)g(will)g(be)g(able)g(to)g(w)o +(ork)g(around)g(your)g(hand-placed)g(connections)f(to)h(mak)o(e)g(the)g +(connec-)0 2743 y(tions)c(in)i(the)f(netlist.)29 b(If)24 +b(there)g(are)g(certain)g(k)o(e)o(y)f(signals)f(that)h(you)g(w)o(ant)g +(to)h(wire)f(carefully)h(by)f(hand,)h(you)f(can)0 2863 +y(do)j(this)f(too;)h(the)f(router)i(will)e(w)o(ork)h(around)f(them.)34 +b(Signals)26 b(that)f(you)h(route)g(by)f(hand)h(should)f(not)g(be)i(in) +e(the)0 2984 y(netlist.)k Fc(T)-9 b(utorial7b)26 b Fe(has)e(an)h(e)o +(xample)f(of)h(\223hand)g(routing\224)f(in)g(the)h(form)g(of)g(a)g +(piece)g(of)g(metal)f(in)h(the)f(middle)0 3104 y(of)k(the)f(circuit.)38 +b(Undo)27 b(the)g(routing,)g(and)g(try)h(modifying)d(the)j(metal)e +(and/or)i(adding)e(more)h(hand)h(routing)e(of)0 3224 +y(your)f(o)n(wn)e(to)i(see)g(ho)n(w)f(it)g(af)n(fects)h(the)g(routing.) +146 3474 y(The)g(Magic)f(router)g(has)g(a)h(number)f(of)g(options)f +(useful)h(for)h(getting)e(information)g(about)h(the)g(routing)f(and)0 +3594 y(setting)g(routing)g(parameters.)31 b(Y)-11 b(ou)24 +b(need)g(to)g(in)l(v)n(ok)o(e)f(the)h Fc(r)n(oute)i Fe(command)d(once)h +(for)h(each)g(option)e(you)g(w)o(ant)0 3715 y(to)g(specify;)h(then)f +(type)h Fc(:r)n(oute)h Fe(with)e(no)g(options)f(to)i(start)f(up)h(the)f +(router)h(with)f(whate)n(v)o(er)g(parameters)h(you')-5 +b(v)o(e)0 3835 y(set.)36 b(The)27 b Fc(viamin)p Fe(,)f(option)g(which)g +(in)l(v)n(ok)o(es)g(a)h(routing)e(post-pass)h(is,)g(of)h(course,)g(in)l +(v)n(ok)o(ed)f(AFTER)h(routing.)0 3955 y(T)-8 b(ype)34 +b Fc(:r)n(oute)h(netlist)f Ff(\002le)f Fe(to)g(specify)h(a)g(netlist)e +(for)i(the)g(routing)e(without)h(ha)n(ving)g(to)g(open)g(up)h(the)f +(netlist)0 4076 y(menu.)54 b(The)33 b Fc(metal)f Fe(option)g(lets)g +(you)g(toggle)g(metal)g(maximization)f(on)h(and)h(of)n(f;)j(if)d(metal) +f(maximization)0 4196 y(is)c(turned)h(on,)g(the)g(router)f(con)l(v)o +(erts)g(routing)g(from)g(the)h(alternate)g(routing)e(layer)i +(\(\223poly\224\))g(to)f(the)h(preferred)0 4317 y(routing)d(layer)i +(\(\223metal\224\))g(where)n(v)o(er)f(possible.)38 b(The)27 +b Fc(vias)g Fe(option)f(controls)h(metal)g(maximization)f(by)h(spec-)0 +4437 y(ifying)k(ho)n(w)g(man)o(y)g(grid)h(units)f(of)h(\223metal\224)g +(con)l(v)o(ersion)f(mak)o(e)h(it)f(w)o(orthwhile)g(to)h(place)g(vias;)j +(setting)c(this)0 4557 y(to)c(5)h(means)f(that)g(metal)g(maximization)f +(will)g(add)i(e)o(xtra)f(vias)g(only)g(if)h(5)f(or)h(more)f(grid)g +(units)g(of)g(\223poly\224)h(can)0 4678 y(be)33 b(con)l(v)o(erted)g(to) +g(\223metal\224.)56 b(V)-6 b(ie)n(w)32 b(the)h(current)h(technology')-5 +b(s)31 b(router)i(parameters)h(with)e(the)h Fc(tech)h +Fe(option.)0 4798 y(The)28 b Fc(jog)p Fe(,)g Fc(obstacle)p +Fe(,)g(and)g Fc(steady)f Fe(options)f(let)i(you)f(vie)n(w)g(and)g +(change)h(parameters)g(to)f(control)g(the)g(channel)0 +4918 y(router)21 b(\(this)e(feature)j(is)e(for)h(adv)n(anced)f +(users\).)29 b(The)21 b Fc(viamin)f Fe(option)f(in)l(v)n(ok)o(es)h(a)h +(via)f(minimization)f(algorithm)0 5039 y(which)24 b(reduces)h(the)f +(number)g(of)h(vias)f(in)g(a)h(routed)f(layout.)30 b(This)24 +b(can)h(be)g(used)f(as)g(a)h(post-processing)e(step)h(to)0 +5159 y(impro)o(v)o(e)k(the)h(quality)f(of)i(the)f(routing.)44 +b(This)28 b(may)h(be)h(useful)f(e)n(v)o(en)g(when)g(using)f(another)i +(router)f(to)g(do)g(the)0 5280 y(actual)f(routing.)39 +b(Finally)-6 b(,)27 b(sho)n(w)g(all)h(parameter)g(v)n(alues)f(with)g +(the)h Fc(settings)g Fe(option.)38 b(The)28 b(options)f(and)g(their)0 +5400 y(actions)d(are)i(summarized)e(in)g(T)-8 b(able)25 +b(III.)1875 5649 y(\2269\226)p eop +%%Page: 10 10 +10 9 bop 0 -180 a Fe(April)24 b(12,)h(2006)1717 b(Magic)24 +b(T)l(utorial)g(#7:)30 b(Netlists)23 b(and)i(Routing)p +563 3 2775 4 v 561 124 4 121 v 612 88 a(Option)p 1185 +124 V 347 w(Action)p 3336 124 V 563 127 2775 4 v 561 +247 4 121 v 612 211 a Fc(end)p 1185 247 V 471 w Fe(Print)g(the)f +(channel)h(router)g(end)g(constant)p 3336 247 V 561 368 +V 612 332 a Fc(end)p Ff(r)l(eal)p 1185 368 V 314 w Fe(Set)g(the)g +(channel)f(router)h(end)g(constant)p 3336 368 V 563 371 +2775 4 v 561 491 4 121 v 612 455 a Fc(help)p 1185 491 +V 443 w Fe(Print)g(a)g(summary)e(of)i(the)g(router)g(options)p +3336 491 V 563 495 2775 4 v 561 615 4 121 v 612 579 a +Fc(jog)p 1185 615 V 492 w Fe(Print)g(the)f(channel)h(router)g(minimum)d +(jog)i(length)p 3336 615 V 561 736 V 612 699 a Fc(jog)h +Ff(int)p 1185 736 V 361 w Fe(Set)g(the)g(minimum)d(jog)i(length,)g +(measured)h(in)f(grid)h(units)p 3336 736 V 563 739 2775 +4 v 561 859 4 121 v 612 823 a Fc(metal)p 1185 859 V 387 +w Fe(T)-8 b(oggle)24 b(metal)g(maximization)f(on)i(or)g(of)n(f)p +3336 859 V 563 863 2775 4 v 561 983 4 121 v 612 947 a +Fc(netlist)p 1185 983 V 365 w Fe(Print)g(the)f(name)h(of)g(the)f +(current)h(net)g(list)p 3336 983 V 561 1103 V 612 1067 +a Fc(netlist)g Ff(\002le)p 1185 1103 V 218 w Fe(Set)g(the)g(current)g +(net)f(list)p 3336 1103 V 563 1107 2775 4 v 561 1227 +4 121 v 612 1191 a Fc(obstacle)p 1185 1227 V 282 w Fe(Print)h(the)f +(channel)h(router)g(obstacle)f(constant)p 3336 1227 V +561 1347 V 612 1311 a Fc(obstacle)h Ff(r)l(eal)p 1185 +1347 V 100 w Fe(Set)g(the)g(obstacle)f(constant)p 3336 +1347 V 563 1351 2775 4 v 561 1471 4 121 v 612 1435 a +Fc(settings)p 1185 1471 V 304 w Fe(Print)h(a)g(list)e(of)i(all)g +(router)g(parameters)p 3336 1471 V 563 1474 2775 4 v +561 1595 4 121 v 612 1559 a Fc(steady)p 1185 1595 V 354 +w Fe(Print)g(the)f(channel)h(router)g(steady)f(net)h(constant)p +3336 1595 V 561 1715 V 612 1679 a Fc(steady)h Ff(int)p +1185 1715 V 222 w Fe(Set)f(the)g(steady)f(net)h(constant,)f(measured)g +(in)h(grid)f(units)p 3336 1715 V 563 1719 2775 4 v 561 +1839 4 121 v 612 1803 a Fc(tech)p 1185 1839 V 449 w Fe(Print)h(router)f +(technology)g(information)p 3336 1839 V 563 1842 2775 +4 v 561 1963 4 121 v 612 1927 a Fc(vias)p 1185 1963 V +458 w Fe(Print)h(the)f(metal)g(maximization)f(via)i(limit)p +3336 1963 V 561 2083 V 612 2047 a Fc(vias)f Ff(int)p +1185 2083 V 328 w Fe(Set)h(the)g(via)f(limit)p 3336 2083 +V 563 2086 2775 4 v 561 2207 4 121 v 612 2171 a Fc(viamin)p +1185 2207 V 331 w Fe(Minimize)f(vias)i(in)f(a)h(routed)g(layout.)p +3336 2207 V 563 2210 2775 4 v 927 2477 a(T)-8 b(able)25 +b(3:)30 b(A)25 b(summary)f(of)h(all)f(of)h(Magic)g(router)g(options.)0 +2764 y Fg(7)143 b(Ho)o(w)35 b(the)g(Router)f(W)-11 b(orks)0 +2991 y Fe(In)24 b(order)g(to)g(mak)o(e)f(the)h(router)g(produce)g(the)f +(best)h(possible)e(results,)i(it)f(helps)g(to)h(kno)n(w)f(a)h(little)e +(bit)i(about)f(ho)n(w)0 3111 y(it)32 b(w)o(orks.)55 b(The)32 +b(router)h(runs)g(in)f(three)h(stages,)h(called)f Ff(c)o(hannel)f +(de\002nition)p Fe(,)h Ff(global)f(r)l(outing)p Fe(,)g(and)h +Ff(c)o(hannel)0 3232 y(r)l(outing)p Fe(.)51 b(In)33 b(the)f(channel)g +(de\002nition)f(phase,)k(Magic)d(di)n(vides)e(the)i(area)i(of)e(the)g +(edit)g(cell)g(into)g(rectangular)0 3352 y(routing)i(areas)h(called)g +(channels.)60 b(The)35 b(channels)f(co)o(v)o(er)h(all)f(the)h(space)g +(under)f(the)h(box)f(e)o(xcept)h(the)f(areas)0 3472 y(occupied)25 +b(by)g(subcells.)31 b(All)25 b(of)g(Magic')-5 b(s)25 +b(routing)f(goes)h(in)g(the)g(channel)g(areas,)h(e)o(xcept)f(that)g +(stems)f(\(Section)0 3593 y(8.2\))h(may)f(e)o(xtend)g(o)o(v)o(er)g +(subcells.)146 3715 y(T)-8 b(o)28 b(see)h(the)f(channel)g(structure)g +(that)g(Magic)g(chose,)h(place)f(the)g(box)g(in)g Fc(tut7d)h +Fe(as)f(if)h(you)e(were)i(going)e(to)0 3835 y(route,)e(then)f(type)g +(the)h(command)900 4075 y Fc(:channel)146 4314 y Fe(in)30 +b(the)g(layout)g(windo)n(w)-6 b(.)45 b(Magic)30 b(will)f(compute)h(the) +g(channel)g(structure)g(and)g(display)g(it)f(on)h(the)h(screen)0 +4434 y(as)j(a)f(collection)g(of)g(feedback)h(areas.)58 +b(The)33 b(channel)h(structure)f(is)g(displayed)f(as)i(white)f +(rectangles.)56 b(T)-8 b(ype)0 4554 y Fc(:feedback)27 +b(clear)e Fe(when)g(you')-5 b(re)25 b(through)f(looking)f(at)i(them.) +146 4676 y(The)32 b(second)g(phase)g(of)g(routing)f(is)h(global)f +(routing.)51 b(In)32 b(the)g(global)f(routing)g(phase,)j(Magic)e +(considers)0 4797 y(each)22 b(net)f(in)g(turn)g(and)g(chooses)g(the)g +(sequence)h(of)f(channels)h(the)f(net)g(must)f(pass)h(through)g(in)g +(order)g(to)g(connect)0 4917 y(its)28 b(terminals.)41 +b(The)28 b Ff(cr)l(ossing)f(points)g Fe(\(places)i(where)g(the)f(net)h +(crosses)f(from)h(one)f(channel)h(to)f(another\))g(are)0 +5037 y(chosen)d(at)f(this)g(point,)g(b)n(ut)g(not)g(the)h(e)o(xact)g +(path)f(through)g(each)h(channel.)146 5159 y(In)36 b(the)f(third)g +(phase,)j(each)e(channel)g(is)f(considered)g(separately)-6 +b(.)62 b(All)35 b(the)g(nets)h(passing)e(through)h(that)0 +5280 y(channel)30 b(are)h(e)o(xamined)e(at)h(once,)i(and)e(the)g(e)o +(xact)g(path)g(of)h(each)f(net)g(is)g(decided.)47 b(Once)31 +b(the)f(routing)f(paths)0 5400 y(ha)n(v)o(e)c(been)g(determined,)f +(paint)g(is)g(added)h(to)f(the)h(edit)f(cell)h(to)f(implement)g(the)g +(routing.)1850 5649 y(\22610\226)p eop +%%Page: 11 11 +11 10 bop 0 -180 a Fe(Magic)24 b(T)l(utorial)g(#7:)30 +b(Netlists)23 b(and)i(Routing)1717 b(April)24 b(12,)h(2006)146 +68 y(The)20 b(router)g(is)g(grid-based:)27 b(all)20 b(wires)g(are)h +(placed)f(on)f(a)i(uniform)e(grid.)28 b(F)o(or)20 b(the)g(standard)f +(nMOS)h(process)0 188 y(the)28 b(grid)g(spacing)g(is)g(7)h(units,)f +(and)g(for)h(the)f(standard)g(SCMOS)h(process)g(it)f(is)g(8)g(units.)40 +b(If)29 b(you)f(type)g Fc(:grid)h(8)0 309 y Fe(after)h(routing)d +Fc(tut7b)p Fe(,)k(you')o(ll)d(see)i(that)e(all)h(of)g(the)f(routing)g +(lines)h(up)f(with)g(its)g(lo)n(wer)h(and)g(left)g(sides)f(on)h(grid)0 +429 y(lines.)55 b(F)o(ortunately)-6 b(,)34 b(you)e(don')n(t)h(ha)n(v)o +(e)g(to)g(mak)o(e)g(your)f(cell)h(terminals)g(line)f(up)h(on)g(e)n(v)o +(en)f(grid)h(boundaries.)0 549 y(During)24 b(the)h(routing)e(Magic)i +(generates)g Ff(stems)f Fe(that)g(connect)h(your)f(terminals)g(up)g(to) +h(grid)f(lines)g(at)h(the)f(edges)0 670 y(of)31 b(channels.)50 +b(Notice)32 b(that)e(there')-5 b(s)31 b(space)h(left)f(by)g(Magic)g +(between)h(the)f(subcells)g(and)g(the)g(channels;)j(this)0 +790 y(space)25 b(is)g(used)f(by)h(the)f(stem)g(generator)-5 +b(.)0 1178 y Fg(8)143 b(What)36 b(to)f(do)h(When)f(the)g(Router)f(F)l +(ails)0 1417 y Fe(Don')n(t)27 b(be)h(surprised)f(if)h(the)f(router)h +(is)f(unable)g(to)h(mak)o(e)f(all)g(the)h(connections)f(the)g(\002rst)h +(time)f(you)g(try)g(it)g(on)h(a)0 1538 y(lar)n(ge)i(circuit.)45 +b(Unless)29 b(you)h(ha)n(v)o(e)f(e)o(xtra)h(routing)e(space)j(in)e +(your)g(chip,)i(you)e(may)h(ha)n(v)o(e)f(to)g(mak)o(e)h(slight)e(re-)0 +1658 y(arrangements)23 b(to)g(help)g(the)g(router)g(out.)30 +b(The)23 b(paragraphs)h(belo)n(w)e(describe)i(things)e(you)g(can)i(do)f +(to)g(mak)o(e)g(life)0 1778 y(easier)h(for)g(the)g(router)-5 +b(.)30 b(This)23 b(section)g(is)h(not)f(v)o(ery)h(well)f(de)n(v)o +(eloped,)g(so)g(we')-5 b(d)24 b(lik)o(e)g(to)f(hear)i(about)e +(techniques)0 1899 y(you)28 b(use)h(to)f(impro)o(v)o(e)f(routability)-6 +b(.)39 b(If)30 b(you)e(disco)o(v)o(er)f(ne)n(w)h(techniques,)h(send)f +(us)g(mail)g(and)h(we')o(ll)f(add)h(them)0 2019 y(to)24 +b(this)g(section.)0 2363 y Fd(8.1)119 b(Channel)32 b(Structur)n(e)0 +2566 y Fe(One)d(of)h(the)f(\002rst)g(things)f(to)h(check)h(when)f(the)h +(router)f(f)o(ails)g(is)g(the)g(channel)g(structure.)44 +b(If)30 b(using)e(the)h(Magic)0 2686 y(router)l(,)c(type)f +Fc(:channel)i Fe(to)e(look)g(at)h(the)g(channels.)30 +b(One)25 b(common)e(mistak)o(e)h(is)g(to)g(ha)n(v)o(e)h(some)f(of)h +(the)f(desired)0 2807 y(routing)32 b(area)i(co)o(v)o(ered)f(by)f +(subcells;)37 b(Magic)32 b(only)h(runs)f(wires)h(where)h(there)f(are)h +(no)f(subcells.)55 b(Check)33 b(to)0 2927 y(be)e(sure)g(that)f(there)h +(are)g(channels)g(e)n(v)o(erywhere)f(that)g(you')-5 b(re)31 +b(e)o(xpecting)f(wires)g(to)h(run.)48 b(If)31 b(you)f(place)h(cells)0 +3047 y(too)d(close)g(together)l(,)g(there)h(may)f(not)g(be)g(enough)g +(room)f(to)h(ha)n(v)o(e)g(a)h(channel)f(between)g(the)g(cells;)i(when)e +(this)0 3168 y(happens)33 b(Magic)g(will)f(route)h(willy-nilly)e +(across)i(the)g(tops)f(of)i(cells)f(to)f(bring)h(terminals)f(out)h(to)g +(channels,)0 3288 y(and)28 b(will)f(probably)h(generate)h(shorts)e(or)h +(design-rule)g(violations.)39 b(T)-8 b(o)28 b(solv)o(e)f(the)h +(problem,)g(mo)o(v)o(e)e(the)i(cells)0 3409 y(f)o(arther)g(apart.)38 +b(If)28 b(there)f(are)h(man)o(y)e(skinn)o(y)g(channels,)h(it)g(will)f +(be)i(dif)n(\002cult)e(for)h(the)g(router)h(to)f(produce)g(good)0 +3529 y(routing.)i(T)m(ry)24 b(to)g(re-arrange)h(the)f(cell)g(structure) +g(to)g(line)g(up)g(edges)g(of)g(nearby)g(cells)g(so)g(that)g(there)g +(are)h(as)f(fe)n(w)0 3649 y(channels)31 b(as)g(possible)e(and)i(the)o +(y)f(are)i(as)f(lar)n(ge)g(as)g(possible)f(\(before)i(doing)e(this)g +(you')o(ll)g(probably)g(w)o(ant)g(to)0 3770 y(get)25 +b(rid)f(of)h(the)g(e)o(xisting)e(routing)g(by)i(undo-ing)f(or)h(by)f +(\003ushing)g(the)h(edit)f(cell\).)0 4113 y Fd(8.2)119 +b(Stems)0 4317 y Fe(Another)30 b(problem)g(has)h(to)f(do)g(with)g(the)h +(stem)f(generator)-5 b(.)48 b(Stems)30 b(are)i(the)e(pieces)h(of)g +(wiring)f(that)g(connect)0 4437 y(terminals)i(up)h(to)f(grid)h(points)e +(on)i(the)g(edges)g(of)g(channels.)54 b(The)33 b(current)h(stem)e +(generation)g(code)h(doesn')n(t)0 4557 y(kno)n(w)c(about)g(connecti)n +(vity)f(or)i(design)f(rules.)46 b(It)30 b(simply)e(\002nds)i(the)f +(nearest)h(routing)f(grid)h(point)e(and)i(wires)0 4678 +y(out)f(to)g(that)h(point,)f(without)g(considering)f(an)o(y)h(other)h +(terminals.)44 b(If)30 b(a)g(terminal)f(is)h(not)f(on)g(the)h(edge)f +(of)h(the)0 4798 y(cell,)37 b(the)d(stem)f(runs)h(straight)f(across)i +(the)f(cell)g(to)g(the)g(nearest)h(channel,)h(without)d(an)o(y)h +(consideration)f(for)0 4918 y(other)26 b(material)f(in)g(the)h(cell.)33 +b(If)26 b(tw)o(o)f(terminals)g(are)h(too)f(close)h(together)l(,)f +(Magic)h(may)f(decide)h(to)f(route)h(them)0 5039 y(both)i(to)g(the)h +(same)f(grid)h(point.)41 b(When)29 b(this)e(happens,)i(you)g(ha)n(v)o +(e)f(tw)o(o)g(choices.)43 b(Either)28 b(you)g(can)h(mo)o(v)o(e)e(the)0 +5159 y(cell)e(so)g(that)f(the)h(terminals)f(ha)n(v)o(e)h(dif)n(ferent)f +(nearest)i(grid)e(points)g(\(for)h(e)o(xample,)f(you)h(can)g(line)g +(its)f(terminals)0 5280 y(up)h(with)f(the)g(grid)h(lines\),)f(or)h(if)g +(this)f(doesn')n(t)g(w)o(ork)h(you')o(ll)f(ha)n(v)o(e)g(to)h(modify)f +(the)g(cell)h(to)g(mak)o(e)f(the)h(terminals)0 5400 y(f)o(arther)g +(apart.)1850 5649 y(\22611\226)p eop +%%Page: 12 12 +12 11 bop 0 -180 a Fe(April)24 b(12,)h(2006)1717 b(Magic)24 +b(T)l(utorial)g(#7:)30 b(Netlists)23 b(and)i(Routing)146 +68 y(The)f(place)h(where)f(stems)f(cause)i(the)e(most)g(trouble)h(is)f +(in)h(PLAs,)g(man)o(y)f(of)h(which)g(ha)n(v)o(e)f(been)h(optimized)0 +188 y(to)j(space)h(the)g(outputs)e(as)i(closely)f(together)g(as)g +(possible.)38 b(In)28 b(some)f(cases)h(the)f(outputs)g(are)h(closer)g +(together)0 309 y(than)35 b(the)g(routing)e(grid,)38 +b(which)c(is)h(an)g(impossible)e(situation)g(for)i(the)g(stem)g +(generator)-5 b(.)61 b(In)35 b(this)f(case,)k(we)0 429 +y(think)28 b(the)h(best)g(approach)g(is)g(to)g(change)h(the)f(PLA)g +(templates)f(to)h(space)h(the)f(outputs)f(f)o(arther)h(apart.)45 +b(Either)0 549 y(space)33 b(them)g(e)o(xactly)f(the)h(same)g(as)h(the)f +(router)g(grid)f(\(in)h(which)g(case)h(you)e(can)i(line)f(the)g(PLAs)g +(up)g(before)0 670 y(routing)28 b(so)h(the)f(terminals)g(are)i(already) +f(on)g(the)g(grid\),)g(or)h(space)f(the)g(outputs)e(at)i(least)g(1.5)f +(grid)h(units)f(apart)0 790 y(so)g(the)g(stem)g(generator)g(w)o(on')n +(t)g(ha)n(v)o(e)g(troubles.)40 b(Ha)n(ving)28 b(tightly-spaced)f(PLA)h +(outputs)f(is)h(f)o(alse)g(economy:)0 911 y(it)c(mak)o(es)g(it)g(more)g +(dif)n(\002cult)g(to)g(design)f(the)h(PLAs)h(and)f(results)g(in)g(a)o +(wful)g(routing)f(problems.)29 b(Ev)o(en)24 b(if)g(Magic)0 +1031 y(could)k(ri)n(v)o(er)n(-route)g(out)g(from)g(tightly-spaced)f +(terminals)h(to)g(grid)g(lines)g(\(which)h(it)f(can')n(t\),)i(it)e(w)o +(ould)g(require)0 1151 y Fb(N)88 1115 y Fa(2)153 1151 +y Fe(space)d(to)f(route)h(out)f Fb(N)36 b Fe(lines;)24 +b(it)g(tak)o(es)g(less)h(area)h(to)e(stretch)h(the)f(PLA.)0 +1441 y Fd(8.3)119 b(Obstacles)0 1629 y Fe(The)32 b(router)h(tends)f(to) +g(ha)n(v)o(e)g(special)g(dif)n(\002culties)f(with)h(obstacles)g +(running)f(along)h(the)h(edges)f(of)h(channels.)0 1749 +y(When)27 b(you')-5 b(v)o(e)27 b(placed)g(a)g(po)n(wer)g(wire)h(or)f +(other)g(hand-routing)f(along)g(the)h(edge)h(of)f(a)h(channel,)f(the)g +(channel)0 1870 y(router)i(will)f(often)h(run)g(material)f(under)h +(your)g(wiring)f(in)h(the)f(other)h(routing)f(layer)l(,)i(thereby)f +(blocking)f(both)0 1990 y(routing)38 b(layers)h(and)g(making)f(it)g +(impossible)f(to)i(complete)f(the)h(routing.)72 b(Where)40 +b(this)e(occurs,)k(you)d(can)0 2110 y(increase)f(the)f(chances)g(of)g +(successful)g(routing)f(by)h(mo)o(ving)e(the)i(hand-routing)f(a)o(w)o +(ay)h(from)g(the)g(channel)0 2231 y(edges.)55 b(It')-5 +b(s)32 b(especially)g(important)g(to)g(k)o(eep)h(hand-routing)f(a)o(w)o +(ay)h(from)f(terminals.)54 b(The)33 b(stem)f(generator)0 +2351 y(will)24 b(not)h(pay)g(an)o(y)f(attention)g(to)h(hand-routing)e +(when)i(it)g(generates)g(stems)f(\(it)h(just)f(mak)o(es)h(a)g(bee-line) +g(for)g(the)0 2471 y(nearest)g(grid)f(point\),)g(so)h(it)f(may)g +(accidentally)h(short)f(a)h(terminal)f(to)g(nearby)h(hand-routing.)1170 +4150 y @beginspecial 68 @llx 68 @lly 304 @urx 304 @ury +1872 @rwi @setspecial +%%BeginDocument: ../psfigures/tut7.3.ps +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: ../psfiles/tut7.3.ps +%%Creator: Xcircuit v2.0 +%%CreationDate: Fri Apr 14 13:21:10 2000 +%%Pages: 1 +%%BoundingBox: 68 68 304 304 +%%DocumentNeededResources: +%%EndComments +%%BeginProlog +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +%%BeginResource: procset XCIRCproc 2.0 2 +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + +%%EndResource +%%EndProlog + +% XCircuit output starts here. + +/mgrid { +% -304 -304 608 608 bbox +begingate +1 1.00 -256 304 -256 -304 2 polygon +1 1.00 -128 304 -128 -304 2 polygon +1 1.00 -304 224 304 224 2 polygon +1 1.00 -304 64 304 64 2 polygon +1 1.00 0 304 0 -304 2 polygon +1 1.00 256 304 256 -304 2 polygon +1 1.00 128 304 128 -304 2 polygon +1 1.00 -304 -256 304 -256 2 polygon +1 1.00 -304 -96 304 -96 2 polygon +endgate +} def + +%%Page: 1 1 +%%PageOrientation: Portrait +/pgsave save def bop +% 848 560 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.490 0.651 0.980 scb +240 1.00 240 400 688 400 688 768 624 768 624 464 240 464 6 polygon +sce +0.745 0.600 0.871 scb +240 1.00 496 224 496 384 560 384 560 224 4 polygon +sce +0 1.00 496 224 496 384 560 384 560 224 4 polygon +0 1.00 240 400 688 400 688 768 624 768 624 464 240 464 6 polygon +0.616 0.624 0.925 scb +240 1.00 480 384 480 480 576 480 576 384 4 polygon +sce +0 1.00 480 384 480 480 576 480 576 384 4 polygon +1 1.00 480 480 576 384 2 polygon +1 1.00 576 480 480 384 2 polygon +0.800 0.800 0.800 scb +1.00 0 496 496 mgrid +sce +pgsave restore showpage + +%%Trailer +XCIRCsave restore +%%EOF + +%%EndDocument + @endspecial 0 4353 a(Figure)34 b(3:)48 b(When)34 b(placing)f(hand)h +(routing,)h(it)e(is)g(best)h(to)f(place)h(wires)g(with)f(their)g(left)h +(and)g(bottom)e(edges)0 4473 y(along)24 b(grid)h(lines,)f(and)g +(contacts)h(centered)g(on)f(the)h(wires.)30 b(In)25 b(this)f(f)o +(ashion,)g(the)h(hand)f(routing)g(will)g(block)g(as)0 +4594 y(fe)n(w)h(routing)e(grid)i(lines)f(as)h(possible.)146 +4918 y(When)33 b(placing)f(hand-routing,)h(you)f(can)h(get)g(better)f +(routing)g(results)g(by)g(follo)n(wing)f(the)h(advice)h(illus-)0 +5039 y(trated)28 b(in)f(Figure)h(3.)40 b(First,)28 b(display)f(the)g +(routing)g(grid.)39 b(F)o(or)28 b(e)o(xample,)f(if)h(the)g(router)f(is) +h(using)f(a)h(8-unit)f(grid)0 5159 y(\(which)21 b(is)g(true)g(for)h +(the)f(standard)g(SCMOS)i(technology\),)e(type)g Fc(:grid)g(8)p +Fe(.)30 b(Then)21 b(place)h(all)f(your)g(hand)g(routing)0 +5280 y(with)j(its)f(left)i(and)f(bottom)f(edges)i(along)f(the)g(grid)g +(lines.)30 b(Because)25 b(of)g(the)f(w)o(ay)h(the)f(routing)f(tools)h +(w)o(ork,)g(this)0 5400 y(approach)h(results)f(in)g(the)h(least)g +(possible)e(amount)h(of)h(lost)f(routing)f(space.)1850 +5649 y(\22612\226)p eop +%%Page: 13 13 +13 12 bop 0 -180 a Fe(Magic)24 b(T)l(utorial)g(#7:)30 +b(Netlists)23 b(and)i(Routing)1717 b(April)24 b(12,)h(2006)0 +99 y Fg(9)143 b(Mor)m(e)36 b(Netlist)e(Commands)0 322 +y Fe(In)22 b(addition)e(to)i(the)g(netlist)e(menu)i(b)n(uttons)e(and)i +(commands)e(described)i(in)g(Section)f(4,)i(there)f(are)g(a)h(number)e +(of)0 443 y(other)k(netlist)f(commands)f(you)i(can)g(in)l(v)n(ok)o(e)g +(by)g(typing)e(in)i(the)g(netlist)f(windo)n(w)-6 b(.)29 +b(Man)o(y)24 b(of)h(these)g(commands)0 563 y(are)33 b(te)o(xtual)e +(equi)n(v)n(alents)f(of)j(the)f(menu)g(b)n(uttons.)51 +b(Ho)n(we)n(v)o(er)l(,)33 b(the)o(y)e(allo)n(w)h(you)f(to)h(deal)h +(with)e(terminals)g(by)0 683 y(typing)23 b(the)h(hierarchical)h(name)f +(of)g(the)g(terminal)g(rather)h(than)e(by)h(pointing)f(to)h(it.)30 +b(If)25 b(you)e(don')n(t)h(kno)n(w)g(where)0 804 y(a)32 +b(terminal)e(is,)j(or)e(if)g(you)g(ha)n(v)o(e)g(deleted)h(a)f(label)h +(from)f(your)g(design)f(so)h(that)g(there')-5 b(s)31 +b(nothing)f(to)h(point)g(to,)0 924 y(you')o(ll)g(ha)n(v)o(e)g(to)g(use) +h(the)g(te)o(xtual)e(commands.)50 b(Commands)31 b(that)g(don')n(t)g +(just)g(duplicate)g(menu)g(b)n(uttons)f(are)0 1045 y(described)25 +b(belo)n(w;)e(see)i(the)g Ff(ma)o(gic\(1\))g Fe(manual)f(page)h(for)g +(details)f(on)g(the)h(others.)146 1165 y(The)g(netlist)f(command)900 +1393 y Fc(:extract)146 1622 y Fe(will)f(generate)h(a)g(net)g(from)f(e)o +(xisting)f(wiring.)30 b(It)23 b(looks)g(under)h(the)f(box)g(for)h +(paint,)f(then)h(traces)g(out)f(all)g(the)0 1742 y(material)k(in)g(the) +h(edit)f(cell)g(that)g(is)g(connected)h(electrically)f(to)g(that)g +(paint.)39 b(Where)n(v)o(er)27 b(the)h(material)f(touches)0 +1862 y(subcells)i(it)h(looks)f(for)h(terminals)g(in)f(the)h(subcells,)h +(and)f(all)g(the)g(terminals)f(it)h(\002nds)g(are)g(placed)h(into)e(a)i +(ne)n(w)0 1983 y(net.)f(W)-8 b(arning:)29 b(there)22 +b(is)g(also)f(an)i Fc(extract)g Fe(command)e(for)h(layout)f(windo)n +(ws,)g(and)h(it)g(is)g(totally)f(dif)n(ferent)g(from)0 +2103 y(the)j Fc(extract)g Fe(command)f(in)h(netlist)e(windo)n(ws.)29 +b(Mak)o(e)24 b(sure)f(you')-5 b(v)o(e)24 b(got)f(the)g(cursor)h(o)o(v)o +(er)f(the)h(netlist)e(windo)n(w)0 2224 y(when)j(you)f(in)l(v)n(ok)o(e)g +(this)g(command!)146 2344 y(The)30 b(netlist)f(editor)g(pro)o(vides)g +(tw)o(o)g(commands)g(for)h(ripping)f(up)h(e)o(xisting)e(routing)h(\(or) +h(other)f(material\).)0 2464 y(The)o(y)24 b(are)900 2693 +y Fc(:ripup)900 2813 y(:ripup)i(netlist)146 3041 y Fe(The)31 +b(\002rst)f(command)g(starts)g(by)g(\002nding)g(an)o(y)g(paint)g(in)g +(the)g(edit)g(cell)g(that)g(lies)g(underneath)h(the)f(box.)47 +b(It)0 3162 y(then)25 b(w)o(orks)g(outw)o(ard)f(from)h(that)g(paint)f +(to)h(\002nd)g(all)g(paint)g(in)f(the)h(edit)g(cell)g(that)g(is)g +(electrically)f(connected)h(to)0 3282 y(the)j(starting)g(paint.)42 +b(All)28 b(of)g(this)g(paint)g(is)g(erased.)43 b(\()p +Fc(:ripup)30 b Fe(isn')n(t)e(really)h(necessary)-6 b(,)29 +b(since)g(the)f(same)h(ef)n(fect)0 3402 y(can)24 b(be)g(achie)n(v)o(ed) +e(by)i(selecting)e(all)i(the)f(paint)g(in)g(the)h(net)f(and)h(deleting) +e(the)i(selection;)f(it')-5 b(s)22 b(a)i(hango)o(v)o(er)e(from)0 +3523 y(olden)34 b(days)g(when)g(there)g(w)o(as)h(no)f(selection\).)58 +b(The)34 b(second)g(form)g(of)h(the)f(command,)h Fc(:ripup)h(netlist)p +Fe(,)h(is)0 3643 y(similar)30 b(to)g(the)g(\002rst)h(e)o(xcept)f(that)g +(it)h(starts)f(from)g(each)h(of)g(the)g(terminals)e(in)h(the)h(current) +g(netlist)e(instead)h(of)0 3764 y(the)24 b(box.)30 b(An)o(y)24 +b(paint)g(in)g(the)g(edit)g(cell)g(that)g(is)g(electrically)g +(connected)h(to)f(a)h(terminal)e(is)h(erased.)31 b(The)25 +b Fc(:ripup)0 3884 y(netlist)g Fe(command)f(may)g(be)h(useful)g(to)f +(ripup)g(e)o(xisting)f(routing)h(before)h(rerouting.)146 +4004 y(The)g(command)900 4233 y Fc(:trace)h Fe([)p Ff(name)p +Fe(])146 4461 y(pro)o(vides)f(an)h(additional)e(f)o(acility)h(for)h(e)o +(xamining)e(router)i(feedback.)34 b(It)26 b(highlights)d(all)j(paint)f +(connected)0 4581 y(to)30 b(each)h(terminal)e(in)h(the)h(net)f +(containing)f Ff(name)p Fe(,)i(much)f(as)h(the)f Fc(Sho)o(w)h +Fe(menu)f(b)n(utton)f(does)h(for)g(paint)g(con-)0 4702 +y(nected)25 b(to)f(an)o(ything)f(under)h(the)h(box.)30 +b(The)25 b(net)f(to)g(be)h(highlighted)e(may)h(be)h(speci\002ed)g(by)f +(naming)g(one)g(of)h(its)0 4822 y(terminals,)e(for)g(e)o(xample,)g +Fc(:trace)i(shifter/bit[0]/phi1)p Fe(.)31 b(Use)23 b(the)h(trace)g +(command)e(in)h(conjunction)g(with)f(the)0 4943 y(nets)29 +b(speci\002ed)h(in)f(router)g(feedback)h(to)f(see)h(the)f(partially)f +(completed)h(wiring)g(for)g(a)h(net.)44 b(Where)30 b(no)f(net)h(is)0 +5063 y(speci\002ed,)25 b(the)g Fc(:trace)g Fe(command)f(highlights)f +(the)h(currently)h(selected)g(net.)1850 5649 y(\22613\226)p +eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut8.ps b/doc/psfiles/tut8.ps new file mode 100644 index 00000000..6bead863 --- /dev/null +++ b/doc/psfiles/tut8.ps @@ -0,0 +1,2485 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tut8.dvi +%%Pages: 15 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman Courier +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tut8.dvi -o tut8.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +%%BeginProcSet: special.pro +TeXDict begin /SDict 200 dict N SDict begin /@SpecialDefaults{/hs 612 N +/vs 792 N /ho 0 N /vo 0 N /hsc 1 N /vsc 1 N /ang 0 N /CLIP 0 N /rwiSeen +false N /rhiSeen false N /letter{}N /note{}N /a4{}N /legal{}N}B +/@scaleunit 100 N /@hscale{@scaleunit div /hsc X}B /@vscale{@scaleunit +div /vsc X}B /@hsize{/hs X /CLIP 1 N}B /@vsize{/vs X /CLIP 1 N}B /@clip{ +/CLIP 2 N}B /@hoffset{/ho X}B /@voffset{/vo X}B /@angle{/ang X}B /@rwi{ +10 div /rwi X /rwiSeen true N}B /@rhi{10 div /rhi X /rhiSeen true N}B +/@llx{/llx X}B /@lly{/lly X}B /@urx{/urx X}B /@ury{/ury X}B /magscale +true def end /@MacSetUp{userdict /md known{userdict /md get type +/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup +length 20 add dict copy def}if end md begin /letter{}N /note{}N /legal{} +N /od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath +clippath mark{transform{itransform moveto}}{transform{itransform lineto} +}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{ +itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{ +closepath}}pathforall newpath counttomark array astore /gc xdf pop ct 39 +0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}N +/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 +scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get +ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip +not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 +TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{noflips{TR +pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 +-1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg +TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg +sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr +0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add +2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N /cp +{pop pop showpage pm restore}N end}if}if}N /normalscale{Resolution 72 +div VResolution 72 div neg scale magscale{DVImag dup scale}if 0 setgray} +N /psfts{S 65781.76 div N}N /startTexFig{/psf$SavedState save N userdict +maxlength dict begin /magscale true def normalscale currentpoint TR +/psf$ury psfts /psf$urx psfts /psf$lly psfts /psf$llx psfts /psf$y psfts +/psf$x psfts currentpoint /psf$cy X /psf$cx X /psf$sx psf$x psf$urx +psf$llx sub div N /psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy +scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR +/showpage{}N /erasepage{}N /copypage{}N /p 3 def @MacSetUp}N /doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N /endTexFig{end psf$SavedState restore}N /@beginspecial{SDict +begin /SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count /ocount X /dcount countdictstack N}N /@setspecial +{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if /showpage{}N /erasepage{}N /copypage{}N newpath +}N /@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{ +end}repeat grestore SpecialSave restore end}N /@defspecial{SDict begin} +N /@fedspecial{end}B /li{lineto}B /rl{rlineto}B /rc{rcurveto}B /np{ +/SaveX currentpoint /SaveY X N 1 setlinecap newpath}N /st{stroke SaveX +SaveY moveto}N /fil{fill SaveX SaveY moveto}N /ellipse{/endangle X +/startangle X /yrad X /xrad X /savematrix matrix currentmatrix N TR xrad +yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut8.dvi) +@start /Fa 7 62 df<0000FF00000007FFE000001F81F800003E007C0000FC003F0001 +F8001F8001F0000F8003E00007C007C00003E007C00003E00FC00003F00F800001F01F80 +0001F81F800001F83F800001FC3F800001FC3F800001FC3F000000FC7F000000FE7F0000 +00FE7F000000FE7F000000FE7F000000FEFF000000FFFF000000FFFF000000FFFF000000 +FFFF000000FFFF000000FFFF000000FFFF000000FFFF000000FFFF000000FFFF000000FF +FF000000FFFF000000FFFF000000FFFF000000FFFF000000FFFF000000FFFF000000FFFF +000000FFFF000000FFFF000000FFFF000000FF7F000000FE7F000000FE7F000000FE7F00 +0000FE7F000000FE7F800001FE3F800001FC3F800001FC3F800001FC1F800001F81F8000 +01F80FC00003F00FC00003F00FC00003F007E00007E003E00007C003F0000FC001F8001F +8000FC003F00003E007C00001F81F8000007FFE0000000FF000028447CC131>48 +D<000030000000F0000001F0000003F000001FF00000FFF000FFFFF000FFE7F000FF07F0 +000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 +000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 +000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 +000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 +000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 +000007F0000007F0000007F0000007F0000007F0000007F0000007F000000FF800001FFC +007FFFFFFF7FFFFFFF7FFFFFFF204278C131>I<0003FE0000001FFFC000007FFFF00001 +F80FFC0003C001FE00078000FF000E00007F801C00003FC01C00001FE03800001FF03000 +000FF07000000FF860000007F86C000007F8FF000007FCFF800007FCFFC00007FCFFC000 +03FCFFC00003FCFFC00003FCFFC00003FC7F800007FC3F000007FC00000007FC00000007 +F800000007F80000000FF80000000FF00000001FF00000001FE00000001FE00000003FC0 +0000007F800000007F00000000FF00000000FE00000001FC00000003F800000007F00000 +0007E00000000FC00000001F800000003F000000007C00000000F800000000F000000001 +E000000003C000000007800000000F00000C001E00000C003C00000C0038000018007000 +001800E000001801C0000018038000003807000000300E000000701FFFFFFFF01FFFFFFF +F03FFFFFFFF07FFFFFFFF0FFFFFFFFE0FFFFFFFFE0FFFFFFFFE026427BC131>I<000000 +0380000000000380000000000780000000000F80000000000F80000000001F8000000000 +3F80000000003F80000000007F8000000000FF8000000000FF8000000001FF8000000003 +BF80000000033F80000000073F80000000063F800000000C3F800000001C3F8000000018 +3F80000000303F80000000703F80000000603F80000000C03F80000001C03F8000000180 +3F80000003003F80000007003F80000006003F8000000C003F8000001C003F8000001800 +3F80000030003F80000070003F80000060003F800000E0003F800001C0003F8000018000 +3F80000380003F80000300003F80000600003F80000E00003F80000C00003F8000180000 +3F80003800003F80003000003F80006000003F8000E000003F8000FFFFFFFFFFC0FFFFFF +FFFFC0FFFFFFFFFFC00000003F80000000003F80000000003F80000000003F8000000000 +3F80000000003F80000000003F80000000003F80000000003F80000000003F8000000000 +3F80000000003F80000000003F8000000000FFE00000007FFFFFC000007FFFFFC000007F +FFFFC02A437DC231>52 D<000007FC0000003FFF000000FFFFC00003FC03E00007E000F0 +001FC00038003F000058007E0001FC00FE0003FC00FC0007FC01F80007FC03F00007FC03 +F00007FC07E00003F80FE00001F00FE00000001FC00000001FC00000001FC00000003F80 +0000003F800000003F800000007F800000007F800000007F007F80007F01FFF0007F0780 +FC00FF0E003E00FF1C001F80FF38000FC0FF700007E0FF600007E0FFE00003F0FFC00003 +F8FFC00001F8FFC00001FCFF800001FCFF800000FEFF800000FEFF800000FEFF000000FF +FF000000FFFF000000FFFF000000FF7F000000FF7F000000FF7F000000FF7F000000FF7F +000000FF7F800000FF3F800000FF3F800000FF3F800000FE1F800000FE1F800001FE1FC0 +0001FC0FC00001FC0FC00003F807E00003F807E00007F003F00007E001F8000FC000FC00 +1F80007E003F00003F80FE00000FFFF8000003FFE0000000FF800028447CC131>54 +D<0000FF00000007FFE000001FFFF800007F00FE0000FC003F0001F0001F8003E0000FC0 +03C00007E007C00003F00F800001F00F800001F00F000001F81F000000F81F000000F81F +000000F81F000000F81F800000F81F800000F81FC00001F81FC00001F01FE00001F00FF0 +0003E00FFC0003E007FE0007C007FF800F8003FFC01F0001FFF03E0001FFF87800007FFE +F000003FFFC000001FFFC0000007FFE0000003FFF8000007FFFC00001E7FFF00007C1FFF +8000F80FFFC001E003FFE003C001FFF007C0007FF80F80003FFC1F00000FFC3E000007FE +3E000001FE7C000000FE7C000000FF7C0000007FF80000003FF80000003FF80000001FF8 +0000001FF80000001FF80000001FF80000001FFC0000001E7C0000003E7C0000003E7E00 +00003C3E0000007C1F000000F81F800001F00FC00003E007E00007C003F8001F8000FF00 +FF00003FFFFC00000FFFF0000001FF800028447CC131>56 D<7FFFFFFFFFFFFFFF00FFFF +FFFFFFFFFFFF80FFFFFFFFFFFFFFFF807FFFFFFFFFFFFFFF000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFF00FFFF +FFFFFFFFFFFF80FFFFFFFFFFFFFFFF807FFFFFFFFFFFFFFF0041187BA44C>61 +D E /Fb 134[60 60 60 60 60 60 60 60 1[60 60 60 60 60 +60 1[60 60 60 60 60 60 60 60 60 10[60 1[60 4[60 1[60 +3[60 1[60 12[60 3[60 60 5[60 60 1[60 1[60 2[60 5[60 33[{ + TeXBase1Encoding ReEncodeFont }38 100.000003 /Courier +rf /Fc 1 16 df<0001FF0000000FFFE000003FFFF800007FFFFC0001FFFFFF0003FFFF +FF8007FFFFFFC00FFFFFFFE01FFFFFFFF01FFFFFFFF03FFFFFFFF87FFFFFFFFC7FFFFFFF +FC7FFFFFFFFCFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFE +FFFFFFFFFEFFFFFFFFFEFFFFFFFFFEFFFFFFFFFE7FFFFFFFFC7FFFFFFFFC7FFFFFFFFC3F +FFFFFFF81FFFFFFFF01FFFFFFFF00FFFFFFFE007FFFFFFC003FFFFFF8001FFFFFF00007F +FFFC00003FFFF800000FFFE0000001FF000027267BAB32>15 D E +/Fd 4 88 df<0000000018000000003C000000007C000000007C000000007800000000F8 +00000000F800000000F000000001F000000001F000000001E000000003E000000003E000 +000003C000000007C000000007C000000007800000000F800000000F800000001F000000 +001F000000001E000000003E000000003E000000003C000000007C000000007C00000000 +7800000000F800000000F800000000F000000001F000000001F000000003E000000003E0 +00000003C000000007C000000007C000000007800000000F800000000F800000000F0000 +00001F000000001F000000001E000000003E000000003E000000003C000000007C000000 +007C00000000F800000000F800000000F000000001F000000001F000000001E000000003 +E000000003E000000003C000000007C000000007C000000007800000000F800000000F80 +0000000F000000001F000000001F000000003E000000003E000000003C000000007C0000 +00007C000000007800000000F800000000F800000000F000000001F000000001F0000000 +01E000000003E000000003E000000007C000000007C000000007800000000F800000000F +800000000F000000001F000000001F000000001E000000003E000000003E000000003C00 +0000007C000000007C000000007800000000F800000000F800000000F000000000600000 +000026647BCA31>61 D<7000000000000000FC00000000000000FF000000000000007FC0 +0000000000001FF000000000000007FC00000000000001FF000000000000007FC0000000 +0000001FF000000000000007FE00000000000001FF800000000000007FE0000000000000 +1FF800000000000003FE00000000000000FF800000000000003FE00000000000000FF800 +000000000003FF00000000000000FFC00000000000003FF00000000000000FFC00000000 +000001FF000000000000007FC00000000000001FF000000000000007FC00000000000001 +FF000000000000007FC00000000000001FE00000000000001FE00000000000007FC00000 +00000001FF00000000000007FC0000000000001FF00000000000007FC0000000000001FF +0000000000000FFC0000000000003FF0000000000000FFC0000000000003FF0000000000 +000FF80000000000003FE0000000000000FF80000000000003FE0000000000001FF80000 +000000007FE0000000000001FF80000000000007FE0000000000001FF00000000000007F +C0000000000001FF00000000000007FC0000000000001FF00000000000007FC000000000 +0000FF00000000000000FC0000000000000070000000000000003B3878B44C>I<0000FF +FFFFF800000000FFFFFFF800000000FFFFFFF80000000000FFE00000000000007FC00000 +00000000FF80000000000000FF80000000000000FF00000000000000FF00000000000000 +FF00000000000001FF00000000000001FE00000000000001FE00000000000001FE000000 +00000003FE00000000000003FC00000000000003FC00000000000003FC00000000000007 +FC00000000000007F800000000000007F800000000000007F80000000000000FF8000000 +0000000FF00000000000000FF00000000000000FF00000000000001FF00000000000001F +E00000000000001FE00000000000001FE00000000000003FE00000000000003FC0000000 +0000003FC00000000000003FC00000000000007FC00000000000007F800000000000007F +800000000000007F80000000000000FF80000000000000FF00000000000000FF00000000 +000000FF00000000000001FF00000000000001FE00000000C00001FE00000000C00001FE +00000001C00003FE00000001800003FC00000003800003FC00000003000003FC00000003 +000007FC00000007000007F800000006000007F80000000E000007F80000001E00000FF8 +0000001C00000FF00000003C00000FF00000003800000FF00000007800001FF0000000F8 +00001FE0000001F000001FE0000003F000003FE000000FF000003FE000001FE000003FC0 +0000FFE00000FFC00007FFC000FFFFFFFFFFFFC000FFFFFFFFFFFFC000FFFFFFFFFFFF80 +003A447CC342>76 D87 +D E /Fe 103[33 30[50 50 72 50 55 33 39 44 55 55 50 55 +83 28 55 33 28 55 50 33 44 55 44 55 50 3[33 1[33 4[72 +72 66 55 72 1[61 78 72 94 3[39 1[78 61 66 72 72 66 72 +93 2[57 1[33 33 50 50 50 50 50 50 50 50 50 50 28 25 33 +25 1[50 33 33 4[50 1[33 33[{ TeXBase1Encoding ReEncodeFont }68 +100.000003 /Times-Bold rf /Ff 138[66 40 47 53 1[66 60 +66 100 33 2[33 66 60 1[53 66 53 1[60 12[80 1[86 3[86 +113 80 8[86 8[40 4[60 60 60 60 60 2[30 43[66 2[{ + TeXBase1Encoding ReEncodeFont }30 119.999948 /Times-Bold +rf /Fg 105[50 1[44 44 24[44 50 50 72 50 50 28 39 33 50 +50 50 50 78 28 50 28 28 50 50 33 44 50 44 50 44 7[72 +1[94 72 72 61 55 66 1[55 72 72 89 61 2[33 72 72 55 61 +72 66 66 72 5[28 28 50 50 50 50 50 50 50 50 50 50 28 +25 33 25 2[33 33 33 1[83 50 50 1[33 29[55 55 2[{ + TeXBase1Encoding ReEncodeFont }75 100.000003 /Times-Roman +rf /Fh 134[44 44 66 44 50 28 39 39 1[50 50 50 72 28 44 +1[28 50 50 28 44 50 44 50 50 9[83 1[72 1[50 61 2[72 66 +8[61 1[66 16[50 50 2[25 1[25 2[33 33 4[50 31[50 3[{ + TeXBase1Encoding ReEncodeFont }39 100.000003 /Times-Italic +rf /Fi 134[72 72 1[72 80 48 56 64 2[72 80 120 40 80 1[40 +1[72 1[64 80 64 80 72 9[143 2[96 6[135 96 2[56 2[88 96 +104 104 96 104 6[48 1[72 72 72 72 72 72 72 72 13[72 35[{ + TeXBase1Encoding ReEncodeFont }40 143.999997 /Times-Bold +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 794 101 a Fi(Magic)35 b(T)-13 b(utorial)34 b(#8:)44 +b(Cir)m(cuit)34 b(Extraction)1707 521 y Fh(W)-9 b(alter)24 +b(Scott)1460 941 y Fg(Special)h(Studies)g(Program)1116 +1062 y(La)o(wrence)g(Li)n(v)o(ermore)e(National)h(Laboratory)1538 +1182 y(P)-11 b(.O.)25 b(Box)g(808,)f(L-270)1511 1303 +y(Li)n(v)o(ermore,)f(CA)i(94550)1448 1573 y Fh(\(Updated)f(by)h(other)o +(s,)f(too.\))1053 1843 y Fg(This)g(tutorial)g(corresponds)g(to)g(Magic) +h(v)o(ersion)e(7.)0 2434 y Ff(T)-11 b(utorials)30 b(to)f(r)n(ead)h +(\002rst:)300 2700 y Fg(Magic)24 b(T)l(utorial)g(#1:)30 +b(Getting)24 b(Started)300 2820 y(Magic)g(T)l(utorial)g(#2:)30 +b(Basic)25 b(P)o(ainting)f(and)h(Selection)300 2941 y(Magic)f(T)l +(utorial)g(#4:)30 b(Cell)25 b(Hierarchies)0 3196 y Ff(Commands)k(intr)n +(oduced)j(in)f(this)f(tutorial:)300 3462 y Fg(:e)o(xtract)0 +3717 y Ff(Macr)n(os)f(intr)n(oduced)i(in)g(this)f(tutorial:)0 +4029 y Fh(\(none\))146 4330 y Fe(Changes)c(since)f(Magic)f(v)o(ersion)h +(4:)300 4642 y Fg(Ne)n(w)g(form)f(of)h Fe(:extract)h(unique)300 +4762 y Fg(P)o(ath)f(length)f(e)o(xtraction)f(with)h Fe(:extract)i +(length)300 4882 y Fg(Accurate)f(resistance)g(e)o(xtraction)f(with)g +Fe(:extr)n(esis)300 5003 y Fg(Extraction)g(of)h(well)f(connecti)n(vity) +f(and)i(substrate)f(nodes)300 5123 y(Checking)h(for)g(global)f(net)g +(connectedness)h(in)f Fh(e)n(xt2sim)g Fg(\(1\))300 5244 +y(Ne)n(w)h(programs:)k Fh(e)n(xt2spice)c Fg(\(1\))g(and)g +Fh(e)n(xtc)o(hec)n(k)g Fg(\(1\))1875 5649 y(\2261\226)p +eop +%%Page: 2 2 +2 1 bop 0 -180 a Fg(September)25 b(26,)f(2001)1604 b(Magic)25 +b(T)l(utorial)e(#8:)30 b(Circuit)25 b(Extraction)0 99 +y Fi(1)143 b(Intr)m(oduction)0 322 y Fg(This)29 b(tutorial)g(co)o(v)o +(ers)h(the)f(use)h(of)h(Magic')-5 b(s)29 b(circuit)h(e)o(xtractor)-5 +b(.)45 b(The)30 b(e)o(xtractor)g(computes)f(from)h(the)g(layout)0 +443 y(the)e(information)e(needed)i(to)g(run)g(simulation)e(tools)g +(such)i(as)g Fh(crystal)f Fg(\(1\))h(and)g Fh(esim)g +Fg(\(1\).)40 b(This)28 b(information)0 563 y(includes)f(the)h(sizes)f +(and)h(shapes)f(of)h(transistors,)f(and)h(the)g(connecti)n(vity)-6 +b(,)26 b(resistance,)i(and)g(parasitic)f(capaci-)0 683 +y(tance)21 b(of)g(nodes.)29 b(Both)21 b(capacitance)h(to)e(substrate)h +(and)g(se)n(v)o(eral)f(kinds)g(of)h(internodal)f(coupling)g +(capacitances)0 804 y(are)26 b(e)o(xtracted.)146 924 +y(Magic')-5 b(s)29 b(e)o(xtractor)g(is)g(both)g(incremental)f(and)i +(hierarchical:)40 b(only)28 b(part)i(of)f(the)h(entire)f(layout)g(must) +f(be)0 1045 y(re-e)o(xtracted)j(after)f(each)h(change,)h(and)e(the)g +(structure)g(of)g(the)g(e)o(xtracted)g(circuit)g(parallels)g(the)g +(structure)g(of)0 1165 y(the)38 b(layout)g(being)f(e)o(xtracted.)71 +b(The)38 b(e)o(xtractor)g(produces)g(a)h(separate)g Fe(.ext)f +Fg(\002le)h(for)f(each)h Fe(.mag)f Fg(\002le)h(in)f(a)0 +1285 y(hierarchical)31 b(design.)47 b(This)30 b(is)g(in)g(contrast)g +(to)g(pre)n(vious)g(e)o(xtractors,)h(such)f(as)h(Me)o(xtra,)g(which)f +(produces)h(a)0 1406 y(single)24 b Fe(.sim)g Fg(\002le)h(that)g +(represents)g(the)f(\003attened)h(\(fully-instantiated\))e(layout.)146 +1526 y(Sections)36 b(2)h(through)e(4)i(introduce)e(Magic')-5 +b(s)36 b Fe(:extract)h Fg(command)f(and)g(some)g(of)g(its)g(more)g(adv) +n(anced)0 1647 y(features.)52 b(Section)31 b(5)h(describes)f(what)h +(information)e(actually)h(gets)g(e)o(xtracted,)j(and)d(discusses)g +(limitations)0 1767 y(and)c(inaccuracies.)36 b(Section)27 +b(6)g(talks)f(about)g(e)o(xtraction)f(styles.)36 b(Although)25 +b(the)h(hierarchical)i Fh(e)n(xt)e Fg(\(5\))h(format)0 +1887 y(fully)19 b(describes)h(the)f(circuit)h(implemented)e(by)i(a)g +(layout,)g(v)o(ery)f(fe)n(w)h(tools)f(currently)g(accept)i(it.)28 +b(It)20 b(is)f(normally)0 2008 y(necessary)26 b(to)f(\003atten)g(the)g +(e)o(xtracted)g(circuit)g(using)g(one)g(of)g(the)g(programs)g +(discussed)f(in)h(Section)h(7,)f(such)g(as)0 2128 y Fh(e)n(xt2sim)f +Fg(\(1\),)h Fh(e)n(xt2spice)g Fg(\(1\),)g(or)g Fh(e)n(xtc)o(hec)n(k)g +Fg(\(1\).)0 2465 y Fi(2)143 b(Basic)35 b(Extraction)0 +2688 y Fg(Y)-11 b(ou)29 b(can)h(use)f(Magic')-5 b(s)29 +b(e)o(xtractor)g(in)g(one)h(of)f(se)n(v)o(eral)g(w)o(ays.)45 +b(Normally)28 b(it)h(is)g(not)g(necessary)h(to)f(e)o(xtract)g(all)0 +2808 y(cells)c(in)f(a)h(layout.)30 b(T)-8 b(o)25 b(e)o(xtract)f(only)g +(those)g(cells)h(that)f(ha)n(v)o(e)h(changed)g(since)f(the)o(y)g(were)i +(e)o(xtracted,)e(use:)900 3014 y Fe(:load)h Fh(r)l(oot)900 +3134 y Fe(:extract)146 3339 y Fg(The)f(e)o(xtractor)f(looks)f(for)i(a)g +Fe(.ext)g Fg(\002le)g(for)f(e)n(v)o(ery)g(cell)h(in)f(the)g(tree)h +(that)f(descends)g(from)g(the)h(cell)f Fh(r)l(oot)p Fg(.)29 +b(The)0 3460 y Fe(.ext)d Fg(\002le)f(is)g(searched)h(for)g(in)f(the)g +(same)g(directory)h(that)e(contains)h(the)g(cell')-5 +b(s)25 b Fe(.mag)g Fg(\002le.)33 b(An)o(y)24 b(cells)h(that)g(ha)n(v)o +(e)0 3580 y(been)e(modi\002ed)e(since)i(the)o(y)e(were)i(last)f(e)o +(xtracted,)h(and)f(all)g(of)g(their)h(parents,)f(are)h(re-e)o +(xtracted.)30 b(Cells)23 b(ha)n(ving)0 3701 y(no)i Fe(.ext)g +Fg(\002les)g(are)g(also)f(re-e)o(xtracted.)146 3821 y(T)-8 +b(o)29 b(try)g(out)f(the)g(e)o(xtractor)h(on)f(an)h(e)o(xample,)g(cop)o +(y)g(all)f(the)h Fe(tut8)p Fh(x)h Fg(cells)e(to)h(your)f(current)h +(directory)g(with)0 3941 y(the)c(follo)n(wing)e(shell)h(commands:)900 +4147 y Fe(cp)i(\230cad/lib/magic/tutorial/tut8*.mag)48 +b(.)146 4352 y Fg(Start)26 b(magic)f(on)g(the)g(cell)g +Fe(tut8a)h Fg(and)f(type)g Fe(:extract)p Fg(.)34 b(Magic)25 +b(will)f(print)h(the)g(name)g(of)g(each)h(cell)g(\()p +Fe(tut8a)p Fg(,)0 4472 y Fe(tut8b)p Fg(,)33 b Fe(tut8c)p +Fg(,)g(and)e Fe(tut8d)p Fg(\))h(as)f(it)f(is)h(e)o(xtracted.)48 +b(No)n(w)30 b(type)h Fe(:extract)h Fg(a)f(second)f(time.)48 +b(This)30 b(time)h(nothing)0 4593 y(gets)25 b(printed,)f(since)h(Magic) +f(didn')n(t)h(ha)n(v)o(e)f(to)h(re-e)o(xtract)g(an)o(y)g(cells.)31 +b(No)n(w)24 b(delete)h(the)g(piece)g(of)g(poly)g(labelled)0 +4713 y(\223)p Fe(delete)32 b(me)p Fg(\224)f(and)f(type)h +Fe(:extract)g Fg(again.)48 b(This)29 b(time,)j(only)d(the)i(cell)f +Fe(tut8a)h Fg(is)f(e)o(xtracted)h(as)f(it)g(is)g(the)h(only)0 +4834 y(one)23 b(that)g(changed.)30 b(If)24 b(you)e(mak)o(e)i(a)f +(change)h(to)e(cell)i Fe(tut8b)g Fg(\(do)f(it\))g(and)g(then)g(e)o +(xtract)g(again,)f(both)h Fe(tut8b)h Fg(and)0 4954 y +Fe(tut8a)h Fg(will)f(be)h(re-e)o(xtracted,)g(since)g +Fe(tut8a)g Fg(is)f(the)h(parent)g(of)g Fe(tut8b)p Fg(.)146 +5074 y(T)-8 b(o)25 b(force)g(all)g(cells)g(in)f(the)h(subtree)f(rooted) +h(at)g(cell)f Fh(r)l(oot)g Fg(to)g(be)h(re-e)o(xtracted,)g(use)g +Fe(:extract)h(all)p Fg(:)900 5280 y Fe(:load)p Fh(r)l(oot)900 +5400 y Fe(:extract)g(all)1875 5649 y Fg(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fg(Magic)24 b(T)l(utorial)g(#8:)30 b(Circuit)25 +b(Extraction)1603 b(September)25 b(26,)g(2001)146 69 +y(T)m(ry)g(this)e(also)i(on)f Fe(tut8a)p Fg(.)146 189 +y(Y)-11 b(ou)25 b(can)g(also)f(use)h(the)g Fe(:extract)h +Fg(command)d(to)i(e)o(xtract)f(a)h(single)f(cell)h(as)g(follo)n(ws:)900 +422 y Fe(:extract)h(cell)f Fh(name)146 653 y Fg(will)33 +b(e)o(xtract)g(just)g(the)g(selected)g(\(current\))h(cell,)i(and)d +(place)h(the)f(output)f(in)i(the)f(\002le)h Fh(name)p +Fg(.)56 b(Select)34 b(the)0 774 y(cell)29 b Fe(tut8b)h +Fg(\()p Fe(tut8b)p 694 774 30 4 v 37 w(0)p Fg(\))f(and)g(type)g +Fe(:extract)h(cell)e(differ)n(entFile)j Fg(to)e(try)f(this)g(out.)43 +b(After)29 b(this)f(command,)h(the)0 894 y(\002le)24 +b Fe(differ)n(entFile.ext)i Fg(will)d(contain)g(the)h(e)o(xtracted)g +(circuit)f(for)i(the)e(cell)h Fe(tut8b)p Fg(.)32 b(The)24 +b(children)f(of)h Fe(tut8b)h Fg(\(in)0 1014 y(this)g(case,)j(the)e +(single)g(cell)g Fe(tut8d)p Fg(\))i(will)d(not)h(be)h(re-e)o(xtracted)f +(by)g(this)g(command.)35 b(If)26 b(more)h(than)f(one)g(cell)h(is)0 +1135 y(selected,)e(the)f(upper)n(-leftmost)g(one)h(is)f(e)o(xtracted.) +146 1256 y(Y)-11 b(ou)19 b(should)g(be)g(careful)h(about)f(using)g +Fe(:extract)h(cell)p Fg(,)h(since)e(e)n(v)o(en)g(though)f(you)h(may)g +(only)g(mak)o(e)g(a)h(change)0 1376 y(to)26 b(a)h(child)e(cell,)i(all)f +(of)h(its)e(parents)i(may)f(ha)n(v)o(e)g(to)g(be)g(re-e)o(xtracted.)36 +b(T)-8 b(o)26 b(re-e)o(xtract)h(all)f(of)g(the)h(parents)f(of)g(the)0 +1496 y(selected)f(cell,)f(you)h(may)f(use)900 1728 y +Fe(:extract)i(par)n(ents)146 1960 y Fg(T)m(ry)e(this)g(out)g(with)g +Fe(tut8b)h Fg(still)e(selected.)31 b(Magic)24 b(will)g(e)o(xtract)g +(only)f(the)i(cell)f Fe(tut8a)p Fg(,)h(since)f(it)g(is)h(the)f(only)0 +2081 y(one)33 b(that)f(uses)h(the)g(cell)g Fe(tut8b)p +Fg(.)56 b(T)-8 b(o)32 b(see)i(what)e(cells)h(w)o(ould)f(be)h(e)o +(xtracted)g(by)f Fe(:extract)i(par)n(ents)h Fg(without)0 +2201 y(actually)24 b(e)o(xtracting)g(them,)g(use)900 +2433 y Fe(:extract)i(sho)o(wpar)n(ents)146 2665 y Fg(T)m(ry)f(this)e +(command)h(as)h(well.)0 3007 y Fi(3)143 b(F)l(eedback:)43 +b(Err)m(ors)34 b(and)h(W)-9 b(ar)n(nings)0 3232 y Fg(When)22 +b(the)g(e)o(xtractor)g(encounters)g(problems,)f(it)h(lea)n(v)o(es)f +(feedback)i(in)f(the)g(form)f(of)i(stippled)d(white)i(rectangu-)0 +3352 y(lar)k(areas)h(on)e(the)h(screen.)34 b(Each)27 +b(area)f(co)o(v)o(ers)f(the)h(portion)f(of)h(the)g(layout)f(that)g +(caused)h(the)g(error)-5 b(.)34 b(Each)26 b(area)0 3472 +y(also)e(has)g(an)g(error)g(message)g(associated)g(with)f(it,)g(which)h +(you)g(can)g(see)g(by)g(using)f(the)h Fe(:feedback)i +Fg(command.)0 3593 y(T)-8 b(ype)25 b Fe(:feedback)i(help)e +Fg(while)g(in)f(Magic)g(for)h(assistance)g(in)f(using)g(the)h +Fe(:feedback)i Fg(command.)146 3714 y(The)i(e)o(xtractor)f(will)g(al)o +(w)o(ays)g(report)g(e)o(xtraction)g Fh(err)l(or)o(s)p +Fg(.)40 b(These)29 b(are)g(problems)e(in)h(the)h(layout)e(that)h(may)0 +3834 y(cause)c(the)g(output)e(of)i(the)f(e)o(xtractor)h(to)f(be)h +(incorrect.)31 b(The)23 b(layout)g(should)g(be)h(\002x)o(ed)f(to)g +(eliminate)g(e)o(xtraction)0 3954 y(errors)32 b(before)g(attempting)e +(to)h(simulate)g(the)g(circuit;)k(otherwise,)d(the)g(results)f(of)g +(the)h(simulation)d(may)j(not)0 4075 y(re\003ect)26 b(reality)-6 +b(.)146 4196 y(Extraction)30 b(errors)i(can)f(come)g(from)g(violations) +e(of)i(transistor)f(rules.)49 b(There)32 b(are)f(tw)o(o)g(rules)g +(about)f(the)0 4316 y(formation)j(of)g(transistors:)47 +b(no)33 b(transistor)g(can)h(be)g(formed,)h(and)f(none)f(can)h(be)g +(destro)o(yed,)h(as)f(a)g(result)f(of)0 4436 y(cell)d(o)o(v)o(erlaps.) +44 b(F)o(or)30 b(e)o(xample,)h(it)e(is)g(ille)o(gal)f(to)i(ha)n(v)o(e)g +(poly)f(in)g(one)h(cell)g(o)o(v)o(erlap)f(dif)n(fusion)f(in)h(another)h +(cell,)0 4557 y(as)36 b(that)f(w)o(ould)f(form)h(a)h(transistor)f(in)g +(the)g(parent)h(where)f(none)h(w)o(as)f(present)h(in)f(either)g(child.) +62 b(It)35 b(is)h(also)0 4677 y(ille)o(gal)23 b(to)h(ha)n(v)o(e)g(a)h +(b)n(uried)f(contact)h(in)f(one)g(cell)h(o)o(v)o(erlap)e(a)i +(transistor)f(in)g(another)l(,)g(as)h(this)f(w)o(ould)f(destro)o(y)h +(the)0 4798 y(transistor)-5 b(.)53 b(V)-6 b(iolating)32 +b(these)h(transistor)e(rules)i(will)f(cause)h(design-rule)g(violations) +e(as)i(well)f(as)h(e)o(xtraction)0 4918 y(errors.)48 +b(These)31 b(errors)g(only)f(relate)h(to)f(circuit)g(e)o(xtraction:)41 +b(the)30 b(f)o(abricated)h(circuit)g(may)f(still)f(w)o(ork;)k(it)d +(just)0 5038 y(w)o(on')n(t)25 b(be)f(e)o(xtracted)h(correctly)-6 +b(.)146 5159 y(In)28 b(general,)h(it)e(is)h(an)g(error)g(for)h +(material)e(of)h(tw)o(o)f(types)h(on)f(the)h(same)g(plane)f(to)h(o)o(v) +o(erlap)f(or)h(ab)n(ut)f(if)h(the)o(y)0 5280 y(don')n(t)f(connect)g(to) +h(each)g(other)-5 b(.)38 b(F)o(or)27 b(e)o(xample,)g(in)g(CMOS)h(it)f +(is)g(ille)o(gal)f(for)h(p-dif)n(fusion)f(and)i(n-dif)n(fusion)d(to)0 +5400 y(o)o(v)o(erlap)f(or)h(ab)n(ut.)1875 5649 y(\2263\226)p +eop +%%Page: 4 4 +4 3 bop 0 -180 a Fg(September)25 b(26,)f(2001)1604 b(Magic)25 +b(T)l(utorial)e(#8:)30 b(Circuit)25 b(Extraction)146 +68 y(In)20 b(addition)e(to)h(errors,)i(the)f(e)o(xtractor)f(can)h(gi)n +(v)o(e)e Fh(warnings)p Fg(.)28 b(If)20 b(only)f(w)o(arnings)f(are)j +(present,)f(the)f(e)o(xtracted)0 188 y(circuit)26 b(can)h(still)e(be)i +(simulated.)35 b(By)27 b(def)o(ault,)f(only)g(some)g(types)g(of)h(w)o +(arnings)f(are)h(reported)g(and)f(displayed)0 309 y(as)f(feedback.)31 +b(T)-8 b(o)25 b(cause)g(all)g(w)o(arnings)f(to)g(be)h(displayed,)f(use) +900 541 y Fe(:extract)i(war)o(n)f(all)146 773 y Fg(The)g(command)900 +1005 y Fe(:extract)h(war)o(n)f Fh(warning)146 1237 y +Fg(may)32 b(be)g(used)g(to)f(enable)h(speci\002c)g(w)o(arnings)g +(selecti)n(v)o(ely;)h(see)f(belo)n(w)-6 b(.)51 b(T)-8 +b(o)31 b(cause)i(no)e(w)o(arnings)g(to)h(be)0 1358 y(displayed,)24 +b(or)h(to)f(disable)g(display)g(of)h(a)g(particular)g +Fh(warning)p Fg(,)f(use)g(respecti)n(v)o(ely)900 1590 +y Fe(:extract)i(war)o(n)f(no)g(all)f Fg(or)900 1710 y +Fe(:extract)i(war)o(n)f(no)g Fh(warning)146 1942 y Fg(Three)j(dif)n +(ferent)f(kinds)f(of)h(w)o(arnings)f(are)i(generated.)38 +b(The)27 b Fe(dup)h Fg(w)o(arning)f(checks)g(to)g(see)g(whether)h(you)0 +2063 y(ha)n(v)o(e)f(tw)o(o)g(electrically)g(unconnected)g(nodes)g(in)g +(the)g(same)g(cell)h(labelled)f(with)f(the)i(same)f(name.)38 +b(If)28 b(so,)g(you)0 2183 y(are)k(w)o(arned)f(because)h(the)f(tw)o(o)g +(unconnected)f(nodes)h(will)f(appear)i(to)f(be)g(connected)g(in)g(the)g +(resulting)f Fe(.ext)0 2304 y Fg(\002le,)k(which)e(means)g(that)f(the)h +(e)o(xtracted)g(circuit)g(w)o(ould)f(not)h(represent)g(the)g(actual)g +(layout.)52 b(This)31 b(is)h(bad)g(if)0 2424 y(you')-5 +b(re)25 b(simulating)d(the)j(circuit)f(to)g(see)h(if)f(it)h(will)e(w)o +(ork)i(correctly:)30 b(the)25 b(simulator)e(will)g(think)h(the)g(tw)o +(o)h(nodes)0 2544 y(are)32 b(connected,)g(b)n(ut)f(since)g(there')-5 +b(s)31 b(no)g(physical)e(wire)j(between)f(them,)h(the)f(electrons)g(w)o +(on')n(t!)49 b(When)32 b(tw)o(o)0 2665 y(unconnected)e(nodes)f(share)h +(the)g(same)g(label)g(\(name\),)h(the)f(e)o(xtractor)f(lea)n(v)o(es)h +(feedback)h(squares)e(o)o(v)o(er)g(each)0 2785 y(instance)24 +b(of)h(the)g(shared)g(name.)146 2906 y(It')-5 b(s)36 +b(an)g(e)o(xcellent)f(idea)h(to)g(a)n(v)n(oid)g(labelling)e(tw)o(o)i +(unconnected)g(nodes)f(with)h(the)g(same)f(name)h(within)0 +3026 y(a)e(cell.)57 b(Instead,)36 b(use)e(the)f(\224correct\224)i(name) +f(for)g(one)g(of)f(the)h(nodes,)h(and)f(some)f(mnemonic)g(b)n(ut)g(te)o +(xtually)0 3147 y(distinct)25 b(name)h(for)h(the)f(other)g(nodes.)35 +b(F)o(or)27 b(e)o(xample,)f(in)g(a)g(cell)h(with)e(multiple)g(po)n(wer) +h(rails,)g(you)g(might)f(use)0 3267 y Fe(Vdd!)62 b Fg(for)35 +b(one)f(of)h(the)g(rails,)i(and)e(names)f(lik)o(e)g Fe(Vdd#1)h +Fg(for)g(the)g(others.)60 b(As)35 b(an)g(e)o(xample,)h(load)f(the)f +(cell)0 3387 y Fe(tut8e)p Fg(.)44 b(If)30 b(the)f(tw)o(o)f(nodes)h(are) +h(connected)f(in)f(a)i(higher)n(-le)n(v)o(el)d(cell)i(the)o(y)g(will)f +(e)n(v)o(entually)f(be)i(mer)n(ged)g(when)0 3508 y(the)j(e)o(xtracted)f +(circuit)h(is)f(\003attened.)52 b(If)33 b(you)e(w)o(ant)h(to)f +(simulate)g(a)h(cell)g(out)f(of)h(conte)o(xt,)h(b)n(ut)e(still)g(w)o +(ant)g(the)0 3628 y(higher)n(-le)n(v)o(el)d(nodes)h(to)g(be)h(hook)o +(ed)f(up,)h(you)f(can)h(al)o(w)o(ays)g(create)g(a)g(dummy)e(parent)i +(cell)f(that)g(hooks)g(them)0 3749 y(together)l(,)d(either)f(with)h +(wire)g(or)g(by)f(using)g(the)h(same)f(name)h(for)g(pieces)g(of)g +(paint)f(that)h(lie)f(o)o(v)o(er)g(the)h(terminals)0 +3869 y(to)e(be)h(connected;)g(see)g(the)g(cell)f Fe(tut8f)i +Fg(for)f(an)g(e)o(xample)f(of)h(this)f(latter)g(technique.)146 +3990 y(Y)-11 b(ou)25 b(can)g(use)g(the)f(command)900 +4222 y Fe(:extract)i(unique)146 4454 y Fg(as)j(an)h(automatic)e(means)g +(of)i(labelling)d(nodes)i(in)g(the)f(manner)h(described)g(abo)o(v)o(e.) +43 b(Run)29 b(this)f(command)0 4575 y(on)g(the)h(cell)f +Fe(tut8g)p Fg(.)43 b(A)28 b(second)h(v)o(ersion)e(of)i(this)f(command)f +(is)h(pro)o(vided)g(for)g(compatibility)f(with)g(pre)n(vious)0 +4695 y(v)o(ersions)c(of)i(Magic.)31 b(Running)900 4927 +y Fe(:extract)26 b(unique)g(#)146 5159 y Fg(will)32 b(only)f(append)h +(a)h(unique)f(numeric)g(suf)n(\002x)f(to)h(labels)g(that)g(end)g(with)g +(a)h(\223)p Fe(#)p Fg(\224.)53 b(An)o(y)32 b(other)g(duplicate)0 +5280 y(nodenames)26 b(that)g(also)g(don')n(t)g(end)h(in)f(a)h(\223)p +Fe(!)p Fg(\224)37 b(\(the)26 b(global)g(nodename)g(suf)n(\002x)g(as)h +(described)f(in)g(Section)h(5\))f(are)0 5400 y(\003agged)f(by)g +(feedback.)1875 5649 y(\2264\226)p eop +%%Page: 5 5 +5 4 bop 0 -180 a Fg(Magic)24 b(T)l(utorial)g(#8:)30 b(Circuit)25 +b(Extraction)1603 b(September)25 b(26,)g(2001)146 69 +y(A)36 b(second)g(type)g(of)g(w)o(arning,)i Fe(fets)p +Fg(,)h(checks)e(to)e(see)h(whether)h(an)o(y)e(transistors)g(ha)n(v)o(e) +g(fe)n(wer)i(dif)n(fusion)0 189 y(terminals)19 b(than)i(the)f(minimum)e +(for)j(their)f(types.)29 b(F)o(or)20 b(e)o(xample,)g(the)h(transistor)e +(type)h(\223)p Fe(dfet)p Fg(\224)i(is)e(de\002ned)h(in)f(the)0 +309 y Fe(nmos)j Fg(technology)e(\002le)i(as)f(requiring)g(tw)o(o)g(dif) +n(fusion)f(terminals:)28 b(a)23 b(source)f(and)h(a)g(drain.)29 +b(If)23 b(a)g(capacitor)g(with)0 430 y(only)d(one)i(dif)n(fusion)d +(terminal)i(is)f(desired)h(in)g(this)g(technology)-6 +b(,)20 b(the)h(type)g Fe(dcap)h Fg(should)e(be)h(used)g(instead.)29 +b(The)0 550 y Fe(fets)20 b Fg(w)o(arning)f(is)g(a)h(consistenc)o(y)e +(check)j(for)e(transistors)g(whose)g(dif)n(fusion)f(terminals)g(ha)n(v) +o(e)i(been)g(accidentally)0 671 y(shorted)k(together)l(,)h(or)f(for)h +(transistors)f(with)g(insuf)n(\002ciently)f(man)o(y)h(dif)n(fusion)f +(terminals.)146 791 y(The)k(third)e(w)o(arning,)h Fe(labels)p +Fg(,)h(is)f(generated)g(if)g(you)g(violate)g(the)g(follo)n(wing)e +(guideline)i(for)g(placement)g(of)0 911 y(labels:)k(Whene)n(v)o(er)24 +b(geometry)h(from)f(tw)o(o)h(subcells)f(ab)n(uts)g(or)h(o)o(v)o +(erlaps,)e(it')-5 b(s)24 b(a)h(good)f(idea)h(to)g(mak)o(e)g(sure)g +(that)0 1032 y(there)f(is)g(a)g(label)f(attached)h(to)g(the)f(geometry) +h(in)f(each)i(subcell)e Fh(in)g(the)h(ar)l(ea)g(of)f(the)h(o)o(verlap)f +(or)h(along)f(the)h(line)0 1152 y(of)h(ab)n(utment)p +Fg(.)31 b(F)o(ollo)n(wing)23 b(this)i(guideline)f(isn')n(t)h(necessary) +h(for)f(the)g(e)o(xtractor)g(to)g(w)o(ork,)h(b)n(ut)e(it)h(will)g +(result)f(in)0 1272 y(noticeably)g(f)o(aster)h(e)o(xtraction.)146 +1393 y(By)g(def)o(ault,)g(the)g Fe(dup)h Fg(and)e Fe(fets)i +Fg(w)o(arnings)e(are)h(enabled,)g(and)g(the)f Fe(labels)h +Fg(w)o(arning)f(is)h(disabled.)146 1513 y(Load)f(the)h(cell)f +Fe(tut8h)p Fg(,)h(e)o(xpand)f(all)g(its)f(children)h(\()p +Fe(tut8i)h Fg(and)f Fe(tut8j)p Fg(\),)h(and)f(enable)h(all)f(e)o +(xtractor)g(w)o(arnings)0 1634 y(with)k Fe(:extract)h(war)o(n)f(all)p +Fg(.)41 b(No)n(w)28 b(e)o(xtract)g Fe(tut8h)i Fg(and)e(all)g(of)h(its)e +(children)h(with)g Fe(:extract)p Fg(,)i(and)f(e)o(xamine)e(the)0 +1754 y(feedback)e(for)h(e)o(xamples)d(of)i(f)o(atal)g(errors)g(and)g(w) +o(arnings.)0 2087 y Fi(4)143 b(Adv)o(anced)33 b(Cir)m(cuit)i +(Extraction)0 2339 y Ff(4.1)119 b(Lengths)0 2527 y Fg(The)33 +b(Magic)g(e)o(xtractor)g(has)g(a)g(rudimentary)f(ability)g(to)h +(compute)f(wire)i(lengths)e(between)h(speci\002c)g(named)0 +2647 y(points)19 b(in)h(a)h(circuit.)29 b(This)20 b(feature)h(is)f +(intended)g(for)h(use)f(with)g(technologies)f(where)i(the)g(wire)f +(length)g(between)0 2768 y(tw)o(o)31 b(points)f(is)h(more)g(important)f +(than)h(the)g(total)g(capacitance)h(on)f(the)g(net;)k(this)30 +b(may)h(occur)l(,)i(for)f(e)o(xample,)0 2888 y(when)e(e)o(xtracting)g +(circuits)g(with)f(v)o(ery)h(long)g(wires)h(being)e(dri)n(v)o(en)h(at)g +(high)g(speeds)g(\()p Fh(e)o(.g)o(.)p Fg(,)h(bipolar)f(circuits\).)0 +3008 y(Currently)-6 b(,)27 b(you)g(must)e(indicate)i(to)g(Magic)f +(which)h(pairs)g(of)g(points)f(are)h(to)g(ha)n(v)o(e)g(distances)f +(computed.)36 b(Y)-11 b(ou)0 3129 y(do)32 b(this)g(by)g(pro)o(viding)f +(tw)o(o)h(lists:)45 b(one)33 b(of)f Fh(driver)o(s)g Fg(and)h(one)f(of)h +Fh(r)l(eceiver)o(s)p Fg(.)55 b(The)32 b(e)o(xtractor)h(computes)e(the)0 +3249 y(distance)24 b(between)h(each)h(dri)n(v)o(er)d(and)i(each)h +(recei)n(v)o(er)e(that)h(it)f(is)g(connected)h(to.)146 +3369 y(Load)h(the)f(cell)h Fe(tut8k)p Fg(.)34 b(There)27 +b(are)f(\002)n(v)o(e)f(labels:)32 b(tw)o(o)25 b(are)i(dri)n(v)o(ers)d +(\()p Fe(dri)o(v)o(er1)j Fg(and)e Fe(dri)o(v)o(er2)p +Fg(\))i(and)e(three)h(are)0 3490 y(recei)n(v)o(ers)e(\()p +Fe(r)n(ecei)o(v)o(erA)p Fg(,)j Fe(r)n(ecei)o(v)o(erB)p +Fg(,)f(and)f Fe(r)n(ecei)o(v)o(erC)p Fg(\).)h(T)-8 b(ype)24 +b(the)h(commands:)900 3666 y Fe(:extract)h(length)f(dri)o(v)o(er)h(dri) +o(v)o(er1)f(dri)o(v)o(er2)900 3787 y(:extract)h(length)f(r)n(ecei)o(v)o +(er)h(r)n(ecei)o(v)o(erA)g(r)n(ecei)o(v)o(erB)h(r)n(ecei)o(v)o(erC)146 +3963 y Fg(No)n(w)g(enable)g(e)o(xtraction)f(of)h(lengths)f(with)h +Fe(:extract)h(do)f(length)h Fg(and)f(then)g(e)o(xtract)g(the)g(cell)g +(\()p Fe(:extract)p Fg(\).)0 4084 y(If)e(you)f(e)o(xamine)g +Fe(tut8k.ext)p Fg(,)i(you)e(will)g(see)h(se)n(v)o(eral)e +Fe(distance)j Fg(lines,)e(corresponding)f(to)i(the)f(dri)n(v)o(er)n +(-recei)n(v)o(er)0 4204 y(distances)e(described)g(abo)o(v)o(e.)29 +b(These)22 b(distances)g(are)h(through)e(the)h(centerlines)g(of)h +(wires)f(connecting)f(the)i(tw)o(o)0 4325 y(labels;)h(where)h(multiple) +e(paths)i(e)o(xist,)e(the)i(shortest)f(is)g(used.)146 +4445 y(Normally)h(the)g(dri)n(v)o(er)g(and)g(recei)n(v)o(er)g(tables)g +(will)g(be)g(b)n(uilt)g(by)g(using)f Fe(:sour)n(ce)j +Fg(to)e(read)h(a)g(\002le)g(of)f Fe(:extract)0 4565 y(length)32 +b(dri)o(v)o(er)f Fg(and)g Fe(:extract)h(length)f(r)n(ecei)o(v)o(er)h +Fg(commands.)48 b(Once)31 b(these)g(tables)f(are)i(created)f(in)g +(Magic,)0 4686 y(the)o(y)24 b(remain)h(until)e(you)h(lea)n(v)o(e)h +(Magic)g(or)f(type)h(the)g(command)900 4862 y Fe(:extract)h(length)f +(clear)146 5039 y Fg(which)g(wipes)f(out)g(both)g(tables.)146 +5159 y(Because)e(e)o(xtraction)e(of)h(wire)h(lengths)d(is)i +Fh(not)f Fg(performed)h(hierarchically)-6 b(,)21 b(it)g(should)f(only)g +(be)h(done)g(in)f(the)0 5280 y(root)26 b(cell)h(of)g(a)g(design.)35 +b(Also,)27 b(because)g(it')-5 b(s)26 b(not)g(hierarchical,)h(it)f(can)h +(tak)o(e)g(a)g(long)f(time)g(for)h(long,)f(comple)o(x)0 +5400 y(wires)f(such)f(as)h(po)n(wer)f(and)h(ground)f(nets.)31 +b(This)24 b(feature)h(is)g(still)e(e)o(xperimental)h(and)g(subject)g +(to)h(change.)1875 5649 y(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Fg(September)25 b(26,)f(2001)1604 b(Magic)25 +b(T)l(utorial)e(#8:)30 b(Circuit)25 b(Extraction)0 82 +y Ff(4.2)119 b(Resistance)0 283 y Fg(Magic)34 b(pro)o(vides)f(for)h +(more)g(accurate)h(resistance)f(e)o(xtraction)f(using)g(the)h +Fe(:extr)n(esis)h Fg(command.)58 b Fe(:extr)n(esis)0 +403 y Fg(pro)o(vides)28 b(a)i(detailed)g(resistance/capacitance)g +(description)e(for)i(nets)g(where)g(parasitic)f(resistance)h(is)f(lik)o +(ely)0 524 y(to)24 b(signi\002cantly)g(af)n(fect)h(circuit)g(timing.)0 +829 y Fe(4.2.1)99 b(T)-9 b(utorial)25 b(Intr)n(oduction)0 +1030 y Fg(T)-8 b(o)30 b(try)g(out)g(the)g(resistance)g(e)o(xtractor)l +(,)h(load)f(in)g(the)g(cell)g Fe(tut8r)p Fg(.)48 b(Extract)30 +b(it)g(using)f Fe(:extract)p Fg(,)j(pause)f(magic,)0 +1150 y(and)25 b(run)f(e)o(xt2sim)f(on)i(the)g(cell)f(with)g(the)h +(command)900 1428 y Fe(ext2sim)f(tut8r)146 1699 y Fg(This)g(should)g +(produce)h Fe(tut8r)-10 b(.sim)p Fg(,)25 b Fe(tut8r)-10 +b(.nodes)p Fg(,)26 b(and)f Fe(tut8r)-10 b(.al)p Fg(.)31 +b(Restart)25 b(magic)f(and)h(type)900 1977 y Fe(:extr)n(esis)g +(tolerance)h(10)900 2098 y(:extr)n(esis)146 2369 y Fg(This)32 +b(will)f(e)o(xtract)h(interconnect)g(resistances)g(for)h(an)o(y)e(net)h +(where)h(the)f(interconnect)g(delay)g(is)g(at)g(least)0 +2489 y(one-tenth)24 b(of)h(the)g(transistor)e(delay)-6 +b(.)31 b(Magic)24 b(should)g(gi)n(v)o(e)f(the)i(messages:)900 +2767 y Fe(:extr)n(esis)g(tolerance)h(10)900 2888 y(:extr)n(esis)900 +3008 y(Adding)g(net2;)f(Tnew)h(=)f(0.428038ns,T)-9 b(old)24 +b(=)g(0.3798ns)900 3128 y(Adding)i(net1;)f(Tnew)h(=)f(0.529005ns,T)-9 +b(old)24 b(=)g(0.4122ns)900 3249 y(T)-9 b(otal)25 b(Nets:)31 +b(7)900 3369 y(Nets)25 b(extracted:)32 b(2)25 b(\(0.285714\))900 +3490 y(Nets)g(output:)32 b(2)25 b(\(0.285714\))146 3761 +y Fg(These)33 b(may)f(v)n(ary)g(slightly)e(depending)i(on)g(your)g +(technology)f(parameters.)54 b(The)32 b Fe(Adding)h([net])h +Fg(lines)0 3881 y(describe)39 b(which)f(netw)o(orks)f(for)i(which)f +(magic)g(produced)g(resistor)g(netw)o(orks.)71 b Fe(Tnew)40 +b Fg(is)e(the)g(estimated)0 4002 y(delay)30 b(on)g(the)g(net)g +(including)f(the)h(resistor)f(parasitics,)i(while)f Fe(T)-9 +b(old)30 b Fg(is)g(the)g(delay)g(without)f(parasitics.)46 +b(The)0 4122 y(ne)o(xt)35 b(line)g(describes)h(where)g(magic)f(thinks)g +(the)g(slo)n(west)g(node)g(in)h(the)f(net)h(is.)63 b(The)36 +b(\002nal)g(3)f(lines)g(gi)n(v)o(e)g(a)0 4243 y(brief)24 +b(summary)f(of)i(the)e(total)h(number)f(of)i(nets,)e(the)h(nets)g +(requiring)f(e)o(xtraction,)h(and)g(the)g(number)f(for)i(which)0 +4363 y(resistors)f(were)h(added)g(to)g(the)f(output.)146 +4490 y(Running)37 b(the)h(resistance)f(e)o(xtractor)h(also)f(produced)g +(the)h(\002le)g Fe(cell.r)n(es.ext)p Fg(.)70 b(T)-8 b(o)37 +b(produce)h(a)g Fe(.sim)f Fg(\002le)0 4610 y(containing)24 +b(resistors,)f(quit)h(magic)h(and)f(type:)900 4888 y +Fe(cat)h(tut8r)-10 b(.ext)26 b(tut8r)-10 b(.r)n(es.ext)26 +b Fd(>)p Fe(tut8r)-10 b(.2.ext)900 5008 y(ext2sim)24 +b(-R)h(-t!)32 b(-t#)25 b(tut8r)-10 b(.2)146 5280 y Fg(Comparing)32 +b(the)g(tw)o(o)g(\002les,)j Fe(tut8r)-10 b(.sim)33 b +Fg(and)f Fe(tut8r)-10 b(.2.sim)p Fg(,)34 b(sho)n(ws)d(that)h(the)h +(latter)f(has)g(the)g(nodes)g(net1)0 5400 y(and)25 b(net2)f(split)g +(into)g(se)n(v)o(eral)g(parts,)g(with)g(resistors)g(added)h(to)f +(connect)h(the)g(ne)n(w)f(nodes)h(together)-5 b(.)1875 +5649 y(\2266\226)p eop +%%Page: 7 7 +7 6 bop 0 -180 a Fg(Magic)24 b(T)l(utorial)g(#8:)30 b(Circuit)25 +b(Extraction)1603 b(September)25 b(26,)g(2001)0 69 y +Fe(4.2.2)99 b(General)25 b(Notes)g(on)g(using)g(the)g(r)n(esistance)h +(extractor)0 260 y Fg(T)-8 b(o)36 b(use)h Fe(:extr)n(esis)p +Fg(,)i(the)e(circuit)f(must)f(\002rst)i(be)f(e)o(xtracted)h(using)e +Fe(:extract)i Fg(and)g(\003attened)g(using)e(e)o(xt2sim.)0 +380 y(When)h(e)o(xt2sim)f(is)h(run,)i(do)e(not)g(use)g(the)g +Fe(-t#)h Fg(and)f Fe(-t!)66 b Fg(\003ags)37 b(\(i.e.)65 +b(don')n(t)36 b(trim)f(the)h(trailing)f(\224#\224)i(and)f(\224!\224)0 +501 y(characters\))30 b(or)f(the)g Fe(-R)h Fg(\003ag)f(because)h +Fe(:extr)n(esis)f Fg(needs)g(the)g Fe(.sim)g Fg(and)g +Fe(.ext)g Fg(names)g(to)g(correspond)f(e)o(xactly)-6 +b(,)0 621 y(and)21 b(it)f(needs)h(the)g(lumped)f(resistance)h(v)n +(alues)f(that)g(the)h(e)o(xtractor)g(produces.)29 b(Also,)21 +b(do)f(not)h(delete)g(or)g(rename)0 741 y(the)g Fe(.nodes)h +Fg(\002le;)g Fe(:extr)n(esis)g Fg(needs)f(this)f(to)h(run.)29 +b(Once)22 b(the)f Fe(.sim)f Fg(and)i Fe(.nodes)f Fg(\002les)h(ha)n(v)o +(e)e(been)i(produced,)f(type)0 862 y(the)30 b(command)g +Fe(:extr)n(esis)h Fg(while)f(running)f(magic)h(on)h(the)f(root)g(cell.) +48 b(As)30 b(the)g(resistance)h(e)o(xtractor)f(runs,)i(it)0 +982 y(will)h(identify)h(which)f(nets)h(\(if)h(an)o(y\))e(for)i(which)f +(it)f(is)h(producing)g(RC)h(netw)o(orks,)h(and)e(will)f(identify)g +(what)0 1102 y(it)e(thinks)e(is)i(the)g(\224slo)n(west\224)f(point)g +(in)g(the)h(netw)o(ork.)49 b(When)31 b(it)g(completes,)h(it)e(will)g +(print)h(a)g(brief)g(summary)0 1223 y(of)37 b(ho)n(w)g(man)o(y)f(nets)h +(it)f(e)o(xtracted)h(and)g(ho)n(w)g(man)o(y)f(required)h(supplemental)f +(netw)o(orks.)67 b(The)37 b(resistance)0 1343 y(netw)o(orks)23 +b(are)i(placed)f(in)g(the)g(\002le)g Fe(r)n(oot.r)n(es.ext)p +Fg(.)31 b(T)-8 b(o)24 b(produce)g(a)h Fe(.sim)e Fg(\002le)i(with)e(the) +h(supplemental)e(resistors,)0 1464 y(type)g Fe(cat)h(r)n(oot.ext)g(r)n +(oot.r)n(es.ext)g Fd(>)p Fe(newname.ext)p Fg(,)h(and)e(then)h(rerun)f +Fe(ext2sim)g Fg(on)h(the)f(ne)n(w)g(\002le.)30 b(During)22 +b(this)0 1584 y(second)j Fe(ext2sim)f Fg(run,)h(the)f +Fe(-t)h Fg(\003ag)h(may)e(be)h(used.)146 1706 y(Lik)o(e)h(e)o +(xtraction)e(of)i(wire)f(lengths,)g(resistance)g(e)o(xtraction)g(is)g +Fh(not)f Fg(performed)i(hierarchically;)f(it)g(should)0 +1826 y(only)f(be)h(done)g(in)f(the)h(root)f(cell)h(of)g(a)g(design)f +(and)h(can)g(tak)o(e)g(a)g(long)f(time)g(for)h(comple)o(x)f(wires.)0 +2103 y Fe(4.2.3)99 b(Options,)24 b(F)n(eatur)n(es,)i(Ca)n(v)o(eats)e +(and)h(Bugs)0 2295 y Fg(The)g(follo)n(wing)e(is)h(a)h(list)f(of)h +(command)f(line)g(options)f(and)i(the)g(ar)n(guments)f(that)g(the)o(y)g +(tak)o(e.)145 2535 y Fc(\017)49 b Fe(tolerance)26 b([v)o(alue])244 +2655 y Fg(This)h(controls)g(ho)n(w)g(lar)n(ge)h(the)g(resistance)f(in)h +(a)g(netw)o(ork)f(must)g(be)h(before)g(it)f(is)h(added)f(to)h(the)f +(output)244 2776 y(description.)52 b Fe(v)o(alue)33 b +Fg(is)f(de\002ned)g(as)h(the)f(minimum)e(ratio)i(of)h(transistor)e +(resistance)i(to)f(interconnect)244 2896 y(resistance)c(that)g +(requires)g(a)h(resistance)f(netw)o(ork.)40 b(The)29 +b(def)o(ault)f(v)n(alue)f(is)h(1;)i(v)n(alues)d(less)h(than)g(1)g(will) +244 3016 y(cause)c(fe)n(wer)g(resistors)e(to)i(be)f(output)g(and)g +(will)g(mak)o(e)g(the)h(program)f(run)h(f)o(aster)l(,)g(while)f(v)n +(alues)f(greater)244 3137 y(than)i(1)h(will)f(produce)h(more)f(a)i(lar) +n(ger)l(,)f(more)g(accurate)g(description)f(b)n(ut)g(will)g(run)h(slo)n +(wer)-5 b(.)145 3349 y Fc(\017)49 b Fe(all)244 3469 y +Fg(Causes)38 b(all)f(nets)g(in)g(the)g(circuit)g(to)g(be)g(e)o +(xtracted;)44 b(no)37 b(comparison)f(between)h(transistor)g(size)g(and) +244 3589 y(lumped)24 b(resistance)g(is)h(performed.)30 +b(This)25 b(option)e(is)h(not)h(recommended)f(for)h(lar)n(ge)g +(designs.)145 3801 y Fc(\017)49 b Fe(simplify)24 b([on/off])244 +3922 y Fg(T)l(urns)30 b(on/of)n(f)g(the)h(resistance)g(netw)o(ork)f +(simpli\002cation)g(routines.)48 b(Magic)31 b(normally)f(simpli\002es)f +(the)244 4042 y(resistance)38 b(netw)o(ork)g(it)g(e)o(xtracts)f(by)h +(remo)o(ving)f(small)g(resistors;)44 b(specifying)37 +b(this)h(\003ag)g(turns)g(this)244 4162 y(feature)25 +b(of)n(f.)145 4374 y Fc(\017)49 b Fe(extout)25 b([on/off])244 +4495 y Fg(T)l(urns)f(on)g(and)h(of)n(f)g(the)f(writing)g(of)h(the)g +Fb(root.res.ext)d Fg(\002le.)31 b(The)25 b(def)o(ault)f(v)n(alue)g(is)h +(on.)145 4707 y Fc(\017)49 b Fe(lumped)26 b([on/off])244 +4827 y Fg(T)l(urns)40 b(on)g(the)h(writing)f(of)h Fb(root.res.lump)p +Fg(.)76 b(This)40 b(\002le)h(contains)f(an)h(updated)f(v)n(alue)g(of)h +(the)244 4947 y(lumped)24 b(resistance)g(for)h(each)h(net)f(that)f +Fe(:extr)n(esis)h Fg(e)o(xtracts.)145 5159 y Fc(\017)49 +b Fe(silent)25 b([on/off])244 5280 y Fg(This)38 b(option)f(suppresses)h +(printing)f(of)h(the)h(name)f(and)h(location)e(of)i(nets)f(for)h(which) +f(resistors)f(are)244 5400 y(produced.)1875 5649 y(\2267\226)p +eop +%%Page: 8 8 +8 7 bop 0 -180 a Fg(September)25 b(26,)f(2001)1604 b(Magic)25 +b(T)l(utorial)e(#8:)30 b(Circuit)25 b(Extraction)145 +69 y Fc(\017)49 b Fe(skip)25 b(mask)244 189 y Fg(Speci\002es)h(a)f +(list)e(of)i(layers)g(that)f(the)h(resistance)g(e)o(xtractor)f(is)h(to) +f(ignore.)145 405 y Fc(\017)49 b Fe(help)244 526 y Fg(Print)25 +b(brief)g(list)e(of)i(options.)146 772 y(Attrib)n(ute)36 +b(labels)g(may)g(also)g(be)g(used)g(to)g(specify)h(certain)f(e)o +(xtractor)g(options.)65 b(F)o(or)36 b(a)h(description)e(of)0 +893 y(attrib)n(utes)24 b(and)g(ho)n(w)g(the)o(y)g(w)o(ork,)h(see)g +(tutorial)f(2.)30 b(F)o(ollo)n(wing)23 b(is)h(a)i(description)d(of)i +Fe(:extr)n(esis)g Fg(attrib)n(utes.)145 1139 y Fc(\017)49 +b Fe(r)n(es:skip@)244 1259 y Fg(Causes)33 b(this)f(net)h(to)f(be)i +(skipped.)54 b(This)32 b(is)g(useful)h(for)g(a)n(v)n(oiding)f(e)o +(xtraction)g(of)h(po)n(wer)f(supplies)g(or)244 1380 y(other)25 +b(DC)g(signals)e(that)i(are)g(not)g(labeled)f(Vdd)h(or)g(GND.)145 +1596 y Fc(\017)49 b Fe(r)n(es:f)n(or)n(ce@)244 1717 y +Fg(F)o(orces)30 b(e)o(xtraction)f(of)h(this)e(net)i(re)o(gardless)f(of) +h(its)f(lumped)g(resistance)g(v)n(alue.)45 b(Nets)30 +b(with)f(both)g(skip)244 1837 y(and)c(force)g(labels)g(attached)f(will) +g(cause)h(the)g(e)o(xtractor)g(to)f(complain.)145 2053 +y Fc(\017)49 b Fe(r)n(es:min=[v)o(alue]@)244 2174 y Fg(Sets)30 +b(the)f(smallest)g(resistor)g(size)h(for)g(this)e(net.)46 +b(The)30 b(def)o(ault)f(v)n(alue)g(is)h(the)f(resistance)h(of)g(the)f +(lar)n(gest)244 2294 y(dri)n(ving)23 b(transistor)h(di)n(vided)f(by)i +(the)f(tolerance)h(described)g(abo)o(v)o(e.)145 2510 +y Fc(\017)49 b Fe(r)n(es:dri)o(v)o(e@)33 b Fg(-)f(Nets)g(with)g(no)g +(dri)n(ving)f(transistors)f(will)i(normally)f(not)h(be)g(e)o(xtracted.) +53 b(This)31 b(option)244 2631 y(allo)n(ws)e(the)h(designer)f(to)h +(specify)g(from)g(where)h(in)e(the)h(net)g(the)g(signal)f(is)h(dri)n(v) +o(en.)45 b(This)30 b(is)f(primarily)244 2751 y(useful)d(when)g(e)o +(xtracting)f(subcells,)g(where)i(the)f(transistors)e(dri)n(ving)h(a)h +(gi)n(v)o(en)f(signal)g(may)h(be)g(located)244 2872 y(in)e(a)h(dif)n +(ferent)g(cell.)0 3154 y Fe(4.2.4)99 b(T)-9 b(echnology)25 +b(File)g(Changes)0 3347 y Fg(Certain)33 b(changes)f(must)f(be)i(made)f +(in)g(the)g(e)o(xtract)g(section)g(of)h(the)f(technology)f(\002le)i(to) +f(support)f(resistance)0 3468 y(e)o(xtraction.)39 b(These)28 +b(include)g(the)g Fe(fetr)n(esist)g Fg(and)g Fe(contact)h +Fg(lines,)f(plus)f(a)i(small)e(change)h(to)g(the)f(fet)i(line.)39 +b(Full)0 3588 y(details)26 b(can)i(be)f(found)g(in)g(Magic)f +(Maintainer')-5 b(s)26 b(Manual)h(#2.)37 b(The)27 b(only)g(thing)f(to)h +(note)f(is)h(that,)g(contrary)g(to)0 3708 y(the)d(documentation,)e(the) +i Fe(gccap)g Fg(and)g Fe(gscap)g Fg(parts)g(of)g(the)g(fet)g(line)f +(MUST)h(be)g(set;)g(the)g(resistance)f(e)o(xtractor)0 +3829 y(uses)h(them)h(to)f(calculate)h(RC)h(time)e(constants)g(for)h +(the)f(circuit.)0 4185 y Fi(5)143 b(Extraction)34 b(Details)g(and)h +(Limitations)0 4414 y Fg(This)28 b(section)g(e)o(xplores)g(in)h +(greater)g(depth)f(what)h(gets)f(e)o(xtracted)h(by)f(Magic,)i(as)f +(well)f(as)h(the)g(limitations)d(of)0 4534 y(the)f(circuit)g(e)o +(xtractor)-5 b(.)30 b(A)25 b(detailed)g(e)o(xplanation)e(of)i(the)g +(format)g(of)g(the)g Fe(.ext)g Fg(\002les)g(output)f(by)h(Magic)f(may)h +(be)0 4655 y(found)20 b(in)g(the)g(manual)g(page)g Fh(e)n(xt)h +Fg(\(5\).)30 b(\223Magic)20 b(Maintainer')-5 b(s)19 b(Manual)h(#2:)28 +b(The)20 b(T)-7 b(echnology)20 b(File\224)g(describes)0 +4775 y(ho)n(w)k(e)o(xtraction)g(parameters)h(are)g(speci\002ed)g(for)g +(the)g(e)o(xtractor)-5 b(.)0 5087 y Ff(5.1)119 b(Nodes)0 +5280 y Fg(Magic)28 b(approximates)g(the)h(pieces)f(of)h(interconnect)g +(between)f(transistors)g(as)h(\223nodes\224.)42 b(A)29 +b(node)f(is)h(lik)o(e)f(an)0 5400 y(equipotential)e(re)o(gion,)h(b)n +(ut)g(also)h(includes)e(a)i(lumped)f(resistance)h(and)f(capacitance)i +(to)e(substrate.)38 b(Figure)28 b(1)1875 5649 y(\2268\226)p +eop +%%Page: 9 9 +9 8 bop 0 -180 a Fg(Magic)24 b(T)l(utorial)g(#8:)30 b(Circuit)25 +b(Extraction)1603 b(September)25 b(26,)g(2001)1306 1294 +y @beginspecial 68 @llx 68 @lly 246 @urx 247 @ury 1544 +@rwi @setspecial +%%BeginDocument: ../psfigures/tut8.1.ps +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + + +% XCircuit output starts here. + +/resistor { +% -14 -64 28 128 bbox +begingate +% fundamental +1 1.00 0 64 0 36 2 polygon +1 1.00 0 -64 0 -36 2 polygon +1 1.00 0 -36 14 -30 -14 -18 14 -6 -14 6 14 18 -14 30 0 36 8 polygon +1.000 0.000 0.000 scb +(r.1) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel +(r.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel +sce +(spice:R%i %pr.1 %pr.2 1.0K) {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel +(sim:r %pr.1 %pr.2) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel +endgate +} def + +/capacitor { +% -32 -64 64 128 bbox +begingate +% fundamental +1 1.00 0 -64 0 -6 2 polygon +1 1.00 0 64 0 6 2 polygon +1 1.00 -32 6 32 6 2 polygon +1 1.00 -32 -6 32 -6 2 polygon +1.000 0.000 0.000 scb +(c.1) {/Times-Roman 1.000 cf} 2 9 0 0 64 pinlabel +(c.2) {/Times-Roman 1.000 cf} 2 13 0 0 -64 pinlabel +sce +(spice:C%i %pc.1 %pc.2 1.0P) {/Times-Roman 1.000 cf} 2 0 0 -208 -160 infolabel +(sim:c %pc.1 %pc.2) {/Times-Roman 1.000 cf} 2 0 0 -208 -208 infolabel +endgate +} def + +/circle { +% -6 -12 28 24 bbox +begingate +1 1.00 16 0 6 0.00 360.00 xcarc +1 1.00 0 0 10 0 2 polygon +1.000 0.000 0.000 scb +(out) {/Times-Roman 1.000 cf} 2 4 0 16 0 pinlabel +(out) {/Times-Roman 1.000 cf} 2 7 0 0 0 pinlabel +sce +endgate +} def + +/gnd { +% -32 -60 64 68 bbox +begingate +1 1.00 0 0 0 -32 2 polygon +1 1.00 -32 -32 32 -32 2 polygon +1 1.00 -18 -46 18 -46 2 polygon +1 1.00 -4 -60 4 -60 2 polygon +1.000 0.000 0.000 scb +(GND) {/Times-Roman 1.000 cf} 2 1 0 0 0 pinglobal +sce +endgate +} def + +/dot { +% -10 -10 20 20 bbox +begingate +248 1.00 0 0 6 0.00 360.00 xcarc +endgate +} def + +/pgsave save def bop +% 430 412 offsets +1.0000 inchscale +2.6000 setlinewidth + +1.00 0 430 508 resistor +1.00 315 504 486 resistor +1.00 270 526 412 resistor +1.00 270 334 412 resistor +1.00 0 430 316 capacitor +1 1.00 430 380 430 444 2 polygon +1 1.00 398 412 462 412 2 polygon +1 1.00 430 412 462 444 2 polygon +1.00 0 590 412 circle +1.00 45 550 532 circle +1.00 90 430 572 circle +1.00 180 270 412 circle +(C) {/Times-Italic 1.000 cf} 2 20 0 478 316 label +(/2) {/Times-Roman 1.000 cf} (R) {/Times-Italic 1.000 cf} 4 29 0 526 388 label +(1) {/Times-Roman 1.000 cf} 2 20 0 630 412 label +(2) {/Times-Roman 1.000 cf} 2 24 0 574 556 label +(3) {/Times-Roman 1.000 cf} 2 25 0 430 620 label +(N) {/Times-Italic 1.000 cf} 2 23 0 222 412 label +(/2) {/Times-Roman 1.000 cf} (R) {/Times-Italic 1.000 cf} 4 29 0 334 388 label +(/2) {/Times-Roman 1.000 cf} (R) {/Times-Italic 1.000 cf} 4 28 0 526 484 label +(/2) {/Times-Roman 1.000 cf} (R) {/Times-Italic 1.000 cf} 4 23 0 398 540 label +1.00 0 430 252 gnd +1.00 0 430 412 dot +(.) {/Times-Bold 1.000 cf} 2 21 0 364 486 label +(.) {/Times-Bold 1.000 cf} 2 21 0 387 506 label +(.) {/Times-Bold 1.000 cf} 2 21 0 350 460 label +pgsave restore showpage + +XCIRCsave restore +%%EndDocument + @endspecial 0 1498 a(Figure)31 b(1:)42 b(Each)31 b(node)f(e)o +(xtracted)h(by)f(Magic)g(has)h(a)g(lumped)f(resistance)g +Fh(R)h Fg(and)f(a)h(lumped)f(capacitance)i Fh(C)0 1618 +y Fg(to)d(the)h(substrate.)45 b(These)30 b(lumped)f(v)n(alues)g(can)h +(be)g(interpreted)g(as)g(in)f(the)h(diagram)f(abo)o(v)o(e,)i(in)e +(which)g(each)0 1738 y(de)n(vice)24 b(connected)h(to)g(the)f(node)h(is) +f(attached)h(to)f(one)h(of)g(the)g(points)e Fh(1)p Fg(,)i +Fh(2)p Fg(,)g(.)15 b(.)g(.)g(,)24 b Fh(N)p Fg(.)0 2108 +y(sho)n(ws)29 b(ho)n(w)h(these)g(lumped)g(v)n(alues)g(are)h(intended)f +(to)g(be)h(interpreted)f(by)g(the)g(analysis)g(programs)g(that)g(use)0 +2229 y(the)25 b(e)o(xtracted)f(circuit.)146 2352 y(Each)k(node)g(in)g +(an)g(e)o(xtracted)f(circuit)h(has)g(a)g(name,)g(which)g(is)f(either)h +(one)g(of)g(the)f(labels)h(attached)g(to)f(the)0 2473 +y(geometry)f(in)g(the)h(node)g(if)f(an)o(y)g(e)o(xist,)g(or)h +(automatically)e(generated)i(by)g(the)f(e)o(xtractor)-5 +b(.)36 b(These)27 b(latter)f(names)0 2593 y(are)h(al)o(w)o(ays)g(of)g +(the)f(form)h Fh(p)p 985 2593 30 4 v 35 w(x)p 1064 2593 +V 36 w(y#)p Fg(,)h(where)f Fh(p)p Fg(,)g Fh(x)p Fg(,)g(and)g +Fh(y)g Fg(are)g(inte)o(gers,)f Fh(e)o(.g)o(.)p Fg(,)g +Fe(3)p 2714 2593 V 36 w(104)p 2900 2593 V 35 w(17#)p +Fg(.)36 b(If)27 b(a)g(label)g(ending)e(in)0 2713 y(the)31 +b(character)g(\223)p Fe(!)p Fg(\224)50 b(is)30 b(attached)h(to)f(a)h +(node,)h(the)f(node)f(is)g(considered)h(to)f(be)h(a)g(\223global\224.) +48 b(Post-processing)0 2834 y(programs)21 b(such)g(as)h +Fh(e)n(xt2sim)f Fg(\(1\))h(will)f(check)h(to)f(ensure)g(that)h(nodes)f +(in)g(dif)n(ferent)g(cells)g(that)g(are)i(labelled)e(with)0 +2954 y(the)k(same)f(global)g(name)h(are)g(electrically)g(connected.)146 +3078 y(Nodes)j(may)f(ha)n(v)o(e)h(attrib)n(utes)f(attached)h(to)g(them) +f(as)h(well)f(as)h(names.)40 b(Node)28 b(attrib)n(utes)f(are)i(labels)e +(end-)0 3198 y(ing)35 b(in)f(the)i(special)e(character)j(\223)p +Fe(@)p Fg(\224,)h(and)d(pro)o(vide)f(a)i(mechanism)e(for)h(passing)f +(information)g(to)h(analysis)0 3319 y(programs)d(such)g(as)g +Fh(crystal)g Fg(\(1\).)53 b(The)33 b(man)f(page)g Fh(e)n(xt)h +Fg(\(5\))g(pro)o(vides)e(additional)g(information)g(about)g(node)0 +3439 y(attrib)n(utes.)0 3755 y Ff(5.2)119 b(Resistance)0 +3949 y Fg(Magic)27 b(e)o(xtracts)g(a)g(lumped)g(resistance)g(for)h +(each)g(node,)f(rather)h(than)f(a)h(point-to-point)d(resistance)i +(between)0 4069 y(each)k(pair)f(of)h(de)n(vices)f(connected)g(to)g +(that)g(node.)47 b(The)31 b(result)e(is)h(that)g(all)g(such)g +(point-to-point)e(resistances)0 4190 y(are)e(approximated)d(by)i(the)f +(w)o(orst-case)h(resistance)g(between)g(an)o(y)f(tw)o(o)h(points)e(in)h +(that)h(node.)146 4313 y(By)j(def)o(ault,)f(node)f(resistances)h(are)g +(approximated)f(rather)h(than)g(computed)f(e)o(xactly)-6 +b(.)36 b(F)o(or)26 b(a)i(node)e(com-)0 4434 y(prised)c(entirely)f(of)h +(a)g(single)f(type)h(of)g(material,)g(Magic)f(will)g(compute)g(the)h +(node')-5 b(s)21 b(total)h(perimeter)f(and)h(area.)0 +4554 y(It)g(then)g(solv)o(es)f(a)i(quadratic)f(equation)g(to)g(\002nd)g +(the)g(width)g(and)g(height)f(of)i(a)g(simple)e(rectangle)h(with)g +(this)f(same)0 4674 y(perimeter)31 b(and)g(area,)j(and)d(approximates)e +(the)i(resistance)g(of)h(the)e(node)h(as)h(the)e(resistance)h(of)h +(this)e(\223equi)n(v-)0 4795 y(alent\224)h(rectangle.)48 +b(The)31 b(resistance)g(is)f(al)o(w)o(ays)g(tak)o(en)h(in)f(the)h +(longer)f(dimension)f(of)i(the)f(rectangle.)49 b(When)0 +4915 y(a)30 b(node)f(contains)f(more)i(than)f(a)h(single)e(type)h(of)h +(material,)g(Magic)f(computes)f(an)i(equi)n(v)n(alent)d(rectangle)j +(for)0 5036 y(each)25 b(type,)g(and)g(then)f(sums)g(the)g(resistances)h +(as)g(though)e(the)i(rectangles)g(were)g(laid)g(end-to-end.)146 +5159 y(This)30 b(approximation)e(for)j(resistance)f(does)f(not)h(tak)o +(e)g(into)g(account)g(an)o(y)f(branching,)i(so)f(it)g(can)g(be)h(sig-)0 +5280 y(ni\002cantly)26 b(in)f(error)i(for)f(nodes)g(that)f(ha)n(v)o(e)h +(side)g(branches.)34 b(Figure)27 b(2)f(gi)n(v)o(es)e(an)i(e)o(xample.) +34 b(F)o(or)26 b(global)f(signal)0 5400 y(trees)33 b(such)f(as)g +(clocks)g(or)h(po)n(wer)l(,)g(Magic')-5 b(s)32 b(estimate)f(of)i +(resistance)f(will)g(lik)o(ely)f(be)h(se)n(v)o(eral)g(times)f(higher) +1875 5649 y(\2269\226)p eop +%%Page: 10 10 +10 9 bop 0 -180 a Fg(September)25 b(26,)f(2001)1604 b(Magic)25 +b(T)l(utorial)e(#8:)30 b(Circuit)25 b(Extraction)0 68 +y(than)f(the)h(actual)g(resistance)g(between)g(tw)o(o)f(points.)390 +1444 y @beginspecial 68 @llx 68 @lly 652 @urx 303 @ury +3744 @rwi @setspecial +%%BeginDocument: ../psfigures/tut8.2.ps +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + + +% XCircuit output starts here. + +/dot { +% -10 -10 20 20 bbox +begingate +248 1.00 0 0 6 0.00 360.00 xcarc +endgate +} def + +/pgsave save def bop +% 992 510 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.800 0.800 0.800 scb +240 1.00 192 254 192 798 1728 798 1728 254 4 polygon +sce +0.490 0.651 0.980 scb +240 1.00 1152 510 1408 510 1408 382 1248 382 1248 350 1568 350 1568 382 1440 +382 1440 510 1568 510 1568 542 1344 542 1344 638 1664 638 1664 766 1632 766 +1632 670 1312 670 1312 542 1152 542 20 polygon +240 1.00 256 510 448 510 448 318 672 318 672 638 800 638 800 510 960 510 960 +542 832 542 832 670 640 670 640 350 480 350 480 542 256 542 16 polygon +sce +0 1.00 256 510 448 510 448 318 672 318 672 638 800 638 800 510 960 510 960 542 +832 542 832 670 640 670 640 350 480 350 480 542 256 542 16 polygon +0 1.00 1152 510 1408 510 1408 382 1248 382 1248 350 1568 350 1568 382 1440 382 +1440 510 1568 510 1568 542 1344 542 1344 638 1664 638 1664 766 1632 766 1632 +670 1312 670 1312 542 1152 542 20 polygon +1.000 1.000 0.000 scb +1 1.00 256 526 464 526 464 334 656 334 656 654 816 654 816 526 960 526 +8 polygon +1 1.00 1152 526 1568 526 2 polygon +1 1.00 1248 366 1568 366 2 polygon +1 1.00 1424 366 1424 526 2 polygon +1 1.00 1328 526 1328 654 1648 654 1648 766 4 polygon +1.00 0 256 526 dot +1.00 0 960 526 dot +1.00 0 1152 526 dot +1.00 0 1568 526 dot +sce +(1) {/Helvetica 1.000 cf} 2 23 0 224 526 label +(2) {/Helvetica 1.000 cf} 2 20 0 976 526 label +(1) {/Helvetica 1.000 cf} 2 23 0 1120 526 label +(2) {/Helvetica 1.000 cf} 2 20 0 1600 526 label +(\(a\)) {/Times-Roman 1.000 cf} 2 21 0 560 206 label +(\(b\)) {/Times-Roman 1.000 cf} 2 21 0 1424 206 label +pgsave restore showpage + +XCIRCsave restore +%%EndDocument + @endspecial 0 1648 a(Figure)29 b(2:)39 b(Magic)29 b(approximates)f +(the)h(resistance)g(of)g(a)h(node)f(by)f(assuming)g(that)h(it)f(is)h(a) +g(simple)f(wire.)44 b(The)0 1768 y(length)39 b(and)h(width)e(of)i(the)g +(wire)g(are)g(estimated)f(from)g(the)h(node')-5 b(s)39 +b(perimeter)g(and)h(area.)76 b(\(a\))41 b(F)o(or)e(non-)0 +1889 y(branching)29 b(nodes,)h(this)f(approximation)f(is)h(a)h(good)f +(one.)46 b(\(b\))29 b(The)h(computed)f(resistance)g(for)h(this)f(node)h +(is)0 2009 y(the)25 b(same)g(as)g(for)g(\(a\))g(because)h(the)e(side)h +(branches)g(are)h(counted,)e(yet)h(the)g(actual)g(resistance)f(between) +h(points)0 2129 y(1)g(and)f(2)h(is)g(signi\002cantly)e(less)h(than)h +(in)f(\(a\).)146 2457 y(The)i(approximated)e(resistance)h(also)g(does)g +(not)g(lend)g(itself)g(well)g(to)g(hierarchical)g(adjustments,)f(as)h +(does)0 2578 y(capacitance.)40 b(T)-8 b(o)28 b(allo)n(w)e(programs)h +(lik)o(e)h Fe(ext2sim)f Fg(to)g(incorporate)h(hierarchical)g +(adjustments)d(into)i(a)h(resis-)0 2698 y(tance)g(approximation,)e +(each)i(node)f(in)g(the)h Fe(.ext)g Fg(\002le)f(also)g(contains)g(a)h +(perimeter)f(and)h(area)g(for)g(each)g(\223resis-)0 2818 +y(tance)23 b(class\224)f(that)g(w)o(as)g(de\002ned)h(in)f(the)h +(technology)e(\002le)i(\(see)f(\223Maintainer')-5 b(s)22 +b(Manual)g(#2:)29 b(The)22 b(T)-7 b(echnology)0 2939 +y(File,)g(\224)23 b(and)g Fh(e)n(xt)g Fg(\(5\)\).)30 +b(When)23 b(\003attening)f(a)h(circuit,)f Fe(ext2sim)g +Fg(uses)g(this)g(information)f(along)h(with)g(adjustments)0 +3059 y(to)i(perimeter)h(and)g(area)h(to)e(produce)h(the)f(v)n(alue)h +(it)f(actually)g(uses)h(for)g(node)f(resistance.)146 +3179 y(If)39 b(you)e(wish)g(to)g(disable)g(the)h(e)o(xtraction)f(of)g +(resistances)h(and)f(node)h(perimeters)f(and)h(areas,)k(use)37 +b(the)0 3300 y(command)900 3495 y Fe(:extract)26 b(no)f(r)n(esistance) +146 3689 y Fg(which)37 b(will)g(cause)h(all)f(node)h(resistances,)i +(perimeters,)g(and)e(areas)g(in)g(the)f Fe(.ext)h Fg(\002le)g(to)f(be)h +(zero.)69 b(T)-8 b(o)0 3810 y(re-enable)26 b(e)o(xtraction)d(of)i +(resistance,)g(use)g(the)f(command)900 4005 y Fe(:extract)i(do)f(r)n +(esistance)p Fg(.)146 4199 y(Sometimes)i(it')-5 b(s)28 +b(important)e(that)i(resistances)g(be)g(computed)f(more)h(accurately)h +(than)f(is)f(possible)g(using)0 4320 y(the)33 b(lumped)f(approximation) +g(abo)o(v)o(e.)55 b(Magic')-5 b(s)32 b Fe(:extr)n(esist)i +Fg(command)e(does)h(this)f(by)h(computing)f(e)o(xplicit)0 +4440 y(tw)o(o-terminal)20 b(resistors)h(and)g(modifying)f(the)h +(circuit)g(netw)o(ork)g(to)g(include)g(them)f(so)h(it)g(re\003ects)i +(more)e(e)o(xactly)0 4561 y(the)28 b(topology)f(of)i(the)f(layout.)40 +b(See)30 b(the)e(section)g(on)g Fe(Adv)o(anced)i(Extraction)f +Fg(for)g(more)f(details)f(on)i(e)o(xplicit)0 4681 y(resistance)c(e)o +(xtraction)f(with)g Fe(:extr)n(esist)p Fg(.)0 4972 y +Ff(5.3)119 b(Capacitance)0 5159 y Fg(Capacitance)22 b(to)e(substrate)g +(comes)g(from)g(tw)o(o)g(dif)n(ferent)h(sources.)29 b(Each)21 +b(type)f(of)h(material)f(has)g(a)h(capacitance)0 5280 +y(to)k(substrate)f(per)i(unit)e(area.)33 b(Each)25 b(type)g(of)g(edge)g +(\(i.e,)h(each)f(pair)h(of)f(types\))g(has)g(a)g(capacitance)h(to)f +(substrate)0 5400 y(per)g(unit)f(length.)30 b(See)c(Figure)f(3.)30 +b(The)25 b(computation)e(of)i(capacitance)h(may)e(be)h(disabled)f(with) +1850 5649 y(\22610\226)p eop +%%Page: 11 11 +11 10 bop 0 -180 a Fg(Magic)24 b(T)l(utorial)g(#8:)30 +b(Circuit)25 b(Extraction)1603 b(September)25 b(26,)g(2001)975 +1288 y @beginspecial 68 @llx 68 @lly 498 @urx 352 @ury +2340 @rwi @setspecial +%%BeginDocument: ../psfigures/tut8.3.ps +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + + +% XCircuit output starts here. + +/mgrid { +% -304 -368 736 736 bbox +begingate +1 1.00 -256 368 -256 -368 2 polygon +1 1.00 -128 368 -128 -368 2 polygon +1 1.00 -304 192 432 192 2 polygon +1 1.00 -304 64 432 64 2 polygon +1 1.00 0 368 0 -368 2 polygon +1 1.00 256 368 256 -368 2 polygon +1 1.00 128 368 128 -368 2 polygon +1 1.00 -304 -192 432 -192 2 polygon +1 1.00 -304 -64 432 -64 2 polygon +1 1.00 -304 -320 432 -320 2 polygon +1 1.00 -304 320 432 320 2 polygon +1 1.00 384 368 384 -368 2 polygon +endgate +} def + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrow { +% -12 -40 24 80 bbox +begingate +1 0.80 0 -40 0 20 2 polygon +1.00 0 0 40 arrowhead +endgate +} def + +/pgsave save def bop +% 720 464 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.133 0.545 0.133 scb +240 1.00 368 624 368 880 752 880 752 624 4 polygon +sce +0.439 1.000 0.314 scb +241 1.00 240 240 880 240 880 496 752 496 752 624 368 624 368 496 240 496 +8 polygon +1 1.00 752 864 752 880 2 polygon +sce +0.800 0.800 0.800 scb +1.00 0 496 560 mgrid +sce +0 1.00 368 624 368 880 752 880 752 624 4 polygon +1.000 1.000 1.000 scb +(buried) {/Times-Roman 1.000 cf} 2 21 0 560 752 label +sce +(diffusion) {/Times-Roman 1.000 cf} 2 21 0 544 400 label +(diff-space perimeter) {/Times-Roman 1.000 cf} 2 28 0 976 224 label +(diff-buried perimeter) {/Times-Roman 1.000 cf} 2 21 0 944 704 label +3 1.00 368 624 368 496 240 496 240 240 880 240 880 496 752 496 752 624 +8 polygon +1.00 60 928 256 arrow +1.000 1.000 1.000 scb +3 1.00 368 624 752 624 2 polygon +1.00 135 720 656 arrow +sce +pgsave restore showpage + +XCIRCsave restore +%%EndDocument + @endspecial 0 1491 a(Figure)g(3:)30 b(Each)25 b(type)f(of)h(edge)g +(has)f(capacitance)i(to)e(substrate)g(per)h(unit)f(length.)30 +b(Here,)25 b(the)f(dif)n(fusion-space)0 1612 y(perimeter)30 +b(of)f(13)h(units)f(has)g(one)h(v)n(alue)f(per)h(unit)f(length,)h(and)g +(the)f(dif)n(fusion-b)n(uried)f(perimeter)i(of)g(3)f(units)0 +1732 y(another)-5 b(.)30 b(In)25 b(addition,)e(each)j(type)e(of)h +(material)g(has)f(capacitance)i(per)f(unit)f(area.)900 +2101 y Fe(:extract)i(no)f(capacitance)146 2307 y Fg(which)k(causes)h +(all)f(substrate)f(capacitance)i(v)n(alues)f(in)g(the)g +Fe(.ext)h Fg(\002le)f(to)g(be)h(zero.)45 b(It)29 b(may)g(be)h +(re-enabled)0 2427 y(with)900 2633 y Fe(:extract)c(do)f(capacitance)p +Fg(.)146 2839 y(Internodal)34 b(capacitance)h(comes)e(from)h(three)g +(sources,)i(as)e(sho)n(wn)f(in)g(Figure)i(4.)58 b(When)34 +b(materials)f(of)0 2960 y(tw)o(o)e(dif)n(ferent)f(types)h(o)o(v)o +(erlap,)g(the)g(capacitance)h(to)f(substrate)f(of)h(the)g(one)g(on)g +(top)g(\(as)g(determined)f(by)h(the)0 3080 y(technology\))h(is)h +(replaced)h(by)e(an)i(internodal)e(capacitance)i(to)f(the)g(one)g(on)g +(the)g(bottom.)54 b(Its)33 b(computation)0 3201 y(may)24 +b(be)h(disabled)f(with)900 3407 y Fe(:extract)i(no)f(coupling)146 +3613 y Fg(which)30 b(will)g(also)f(cause)i(the)f(e)o(xtractor)g(to)g +(run)g(30\045)g(to)g(50\045)g(f)o(aster)-5 b(.)47 b(Extraction)29 +b(of)h(coupling)f(capaci-)0 3733 y(tances)c(can)g(be)g(re-enabled)g +(with)900 3939 y Fe(:extract)h(do)f(coupling)p Fg(.)146 +4145 y(Whene)n(v)o(er)g(material)f(from)g(tw)o(o)h(subcells)f(o)o(v)o +(erlaps)f(or)i(ab)n(uts,)f(the)g(e)o(xtractor)h(computes)f(adjustments) +e(to)0 4266 y(substrate)d(capacitance,)j(coupling)c(capacitance,)k(and) +e(node)f(perimeter)h(and)g(area.)30 b(Often,)20 b(these)g(adjustments)0 +4386 y(mak)o(e)g(little)f(dif)n(ference)i(to)f(the)g(type)g(of)h +(analysis)e(you)h(are)h(performing,)f(as)h(when)f(you)g(wish)f(only)h +(to)g(compare)0 4506 y(netlists.)34 b(Ev)o(en)25 b(when)h(running)g +(Crystal)g(for)g(timing)f(analysis,)h(the)g(adjustments)e(can)j(mak)o +(e)f(less)g(than)g(a)g(5\045)0 4627 y(dif)n(ference)g(in)g(the)g +(timing)e(of)i(critical)g(paths)g(in)f(designs)g(with)h(only)f(a)h +(small)f(amount)g(of)i(inter)n(-cell)e(o)o(v)o(erlap.)0 +4747 y(T)-8 b(o)25 b(disable)f(the)g(computation)f(of)i(these)g +(adjustments,)e(use)900 4953 y Fe(:extract)j(no)f(adjustment)146 +5159 y Fg(which)g(will)g(result)f(in)h(approximately)f(50\045)h(f)o +(aster)h(e)o(xtraction.)31 b(This)25 b(speedup)g(is)f(not)h(entirely)g +(additi)n(v)o(e)0 5280 y(with)i(the)h(speedup)g(resulting)e(from)i +Fe(:extract)h(no)f(coupling)p Fg(.)41 b(T)-8 b(o)28 b(re-enable)h +(computation)d(of)i(adjustments,)0 5400 y(use)d Fe(:extract)g(do)h +(adjustment)p Fg(.)1850 5649 y(\22611\226)p eop +%%Page: 12 12 +12 11 bop 0 -180 a Fg(September)25 b(26,)f(2001)1604 +b(Magic)25 b(T)l(utorial)e(#8:)30 b(Circuit)25 b(Extraction)488 +1238 y @beginspecial 68 @llx 68 @lly 484 @urx 244 @ury +3510 @rwi @setspecial +%%BeginDocument: ../psfigures/tut8.4.ps +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +/pgsave save def bop +% 928 256 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.490 0.651 0.980 scb +192 480 beginpath +544 608 544 480 2 polyc +512 608 32 0.00 90.00 arc +192 640 1 polyc +240 1.00 endpath +1280 480 beginpath +928 608 928 480 2 polyc +960 608 32 180.00 90.00 arcn +1280 640 1 polyc +240 1.00 endpath +sce +1.000 0.000 0.000 scb +192 192 beginpath +1120 320 1120 192 2 polyc +1088 320 32 0.00 90.00 arc +192 352 1 polyc +240 1.00 endpath +sce +192 480 beginpath +544 608 544 480 2 polyc +512 608 32 0.00 90.00 arc +192 640 1 polyc +1 1.00 endpath +1280 480 beginpath +928 608 928 480 2 polyc +960 608 32 180.00 90.00 arcn +1280 640 1 polyc +1 1.00 endpath +192 192 beginpath +1120 320 1120 192 2 polyc +1088 320 32 0.00 90.00 arc +192 352 1 polyc +1 1.00 endpath +(\(metal\)) {/Times-Roman 1.000 cf} 2 21 0 352 560 label +(\(metal\)) {/Times-Roman 1.000 cf} 2 21 0 1120 560 label +(\(poly\)) {/Times-Roman 1.000 cf} 2 21 0 656 272 label +(sidewall overlap) {/Times-Italic 1.000 cf} 2 21 0 688 448 label +(sidewall) {/Times-Italic 1.000 cf} 2 21 0 720 576 label +(overlap) {/Times-Roman 1.000 cf} 2 21 0 352 424 label +(\(oxide\)) {/Times-Roman 1.000 cf} 2 21 0 1024 416 label +1.00 0 560 576 arrowhead90 +1.00 -1 912 576 arrowhead90 +1.00 0 560 512 arrowhead90 +1.00 -91 688 368 arrowhead90 +1 1.00 560 576 640 576 2 polygon +1 1.00 912 576 800 576 2 polygon +1 1.00 560 512 688 512 688 480 3 polygon +1 1.00 688 416 688 368 2 polygon +1.00 -91 352 368 arrowhead90 +1.00 270 352 464 arrowhead90 +1 1.00 352 432 352 464 2 polygon +1 1.00 352 368 352 400 2 polygon +pgsave restore showpage + +XCIRCsave restore +%%EndDocument + @endspecial 0 1441 a(Figure)33 b(4:)47 b(Magic)33 b(e)o(xtracts)f +(three)i(kinds)e(of)h(internodal)f(coupling)g(capacitance.)56 +b(This)32 b(\002gure)i(is)f(a)g(cross-)0 1561 y(section)i(\(side)g(vie) +n(w)-6 b(,)36 b(not)f(a)g(top)g(vie)n(w\))f(of)i(a)f(set)g(of)h(masks)e +(that)h(sho)n(ws)f(all)h(three)g(kinds)f(of)h(capacitance.)0 +1682 y Fh(Overlap)g Fg(capacitance)h(is)f(parallel-plate)g(capacitance) +h(between)g(tw)o(o)e(dif)n(ferent)h(kinds)g(of)g(material)g(when)0 +1802 y(the)o(y)26 b(o)o(v)o(erlap.)37 b Fh(Side)o(wall)26 +b Fg(capacitance)h(is)g(parallel-plate)g(capacitance)h(between)f(the)g +(v)o(ertical)f(edges)h(of)h(tw)o(o)0 1922 y(pieces)f(of)f(the)h(same)f +(kind)g(of)h(material.)36 b Fh(Side)o(wall)25 b(o)o(verlap)h +Fg(capacitance)i(is)e(orthogonal-plate)f(capacitance)0 +2043 y(between)30 b(the)g(v)o(ertical)g(edge)g(of)g(one)g(piece)h(of)f +(material)f(and)h(the)g(horizontal)g(surf)o(ace)g(of)h(another)f(piece) +g(of)0 2163 y(material)24 b(that)h(o)o(v)o(erlaps)e(the)i(\002rst)g +(edge.)0 2539 y Ff(5.4)119 b(T)-9 b(ransistors)0 2726 +y Fg(Lik)o(e)25 b(the)g(resistances)g(of)g(nodes,)f(the)h(lengths)f +(and)h(widths)f(of)h(transistors)f(are)i(approximated.)31 +b(Magic)24 b(com-)0 2847 y(putes)e(the)g(contrib)n(ution)f(to)h(the)h +(total)f(perimeter)g(by)h(each)g(of)f(the)h(terminals)e(of)i(the)g +(transistor)-5 b(.)28 b(See)23 b(Figure)g(5.)0 2967 y(F)o(or)i +(rectangular)f(transistors,)g(this)f(yields)h(an)h(e)o(xact)f($L)g(/)h +(W$.)30 b(F)o(or)25 b(non-branching,)f(non-rectangular)g(tran-)0 +3087 y(sistors,)29 b(it)g(is)h(still)e(possible)g(to)h(approximate)g +($L)g(/)h(W$)f(f)o(airly)h(well,)g(b)n(ut)f(substantial)f(inaccuracies) +i(can)g(be)0 3208 y(introduced)c(if)g(the)h(channel)f(of)h(a)g +(transistor)f(contains)f(branches.)37 b(Since)27 b(most)e(transistors)h +(are)h(rectangular)l(,)0 3328 y(ho)n(we)n(v)o(er)l(,)c(Magic')-5 +b(s)24 b(approximation)f(w)o(orks)i(well)f(in)h(practice.)p +371 3467 3158 4 v 369 3587 4 121 v 465 3551 a(T)-8 b(ype)303 +b(Loc)270 b(A)24 b(P)150 b(Subs)263 b(Gate)296 b(Source)258 +b(Drain)p 3527 3587 V 371 3591 3158 4 v 369 3711 4 121 +v 421 3675 a(fet)25 b(nfet)149 b(59)25 b(1)g(60)f(2)149 +b(8)25 b(12)111 b(GND!)f(Mid2)24 b(4)h Fe(N3)160 b Fg(Out)24 +b(4)h(0)160 b(Vss#0)24 b(4)h(0)p 3527 3711 V 369 3831 +V 421 3795 a(fet)g(nfet)149 b(36)25 b(1)g(37)f(2)149 +b(8)25 b(12)133 b(Float)f(Mid1)24 b(4)h Fe(N2)127 b Fg(Mid2)24 +b(4)g(0)127 b(Vss#0)24 b(4)h(0)p 3527 3831 V 369 3952 +V 421 3916 a(fet)g(nfet)199 b(4)25 b(1)g(5)f(2)199 b(8)25 +b(12)111 b(Vss#0)176 b(In)25 b(4)f Fe(N1)194 b Fg(Mid1)24 +b(4)g(0)127 b(Vss#0)24 b(4)h(0)p 3527 3952 V 369 4072 +V 421 4036 a(fet)g(pfet)100 b(59)24 b(25)h(60)f(26)99 +b(8)25 b(12)133 b(Vdd!)138 b(Mid2)24 b(4)g Fe(P3)105 +b Fg(Vdd#0)24 b(4)h(0)149 b(Out)25 b(4)f(0)p 3527 4072 +V 369 4192 V 421 4156 a(fet)h(pfet)100 b(36)24 b(25)h(37)f(26)99 +b(8)25 b(12)111 b(VBias)116 b(Mid1)24 b(4)g Fe(P2)105 +b Fg(Vdd#0)24 b(4)h(0)116 b(Mid2)24 b(4)h(0)p 3527 4192 +V 369 4313 V 421 4277 a(fet)g(pfet)149 b(4)25 b(25)g(5)f(26)149 +b(8)25 b(12)99 b(Vdd#0)171 b(In)25 b(4)g Fe(P1)171 b +Fg(Vdd#0)24 b(4)h(0)116 b(Mid1)24 b(4)h(0)p 3527 4313 +V 371 4316 3158 4 v 1090 4476 a(T)-8 b(able)25 b(1:)31 +b(The)24 b(transistor)g(section)g(of)h Fe(tut8l.ext)p +Fg(.)146 4798 y(In)30 b(addition)e(to)g(ha)n(ving)h(gate,)h(source,)g +(and)f(drain)h(terminals,)f(MOSFET)g(transistors)f(also)h(ha)n(v)o(e)g +(a)g(sub-)0 4918 y(strate)i(terminal.)48 b(By)31 b(def)o(ault,)h(this)e +(terminal)g(is)g(connected)h(to)f(a)h(global)f(node)h(that)f(depends)h +(on)f(the)h(tran-)0 5039 y(sistor')-5 b(s)30 b(type.)49 +b(F)o(or)31 b(e)o(xample,)h(p-channel)f(transistors)f(might)g(ha)n(v)o +(e)h(a)g(substrate)f(terminal)h(of)g Fe(Vdd!)p Fg(,)j(while)0 +5159 y(n-channel)28 b(transistors)f(w)o(ould)g(ha)n(v)o(e)h(one)g(of)g +Fe(GND!)p Fg(.)40 b(Ho)n(we)n(v)o(er)l(,)28 b(when)g(a)g(transistor)f +(is)h(surrounded)f(by)h(e)o(x-)0 5280 y(plicit)e(\223well\224)h +(material)g(\(as)g(de\002ned)h(in)f(the)g(technology)f(\002le\),)i +(Magic)f(will)f(o)o(v)o(erride)g(the)h(def)o(ault)g(substrate)0 +5400 y(terminal)e(with)f(the)i(node)f(to)g(which)g(the)g(well)g +(material)g(is)g(connected.)33 b(This)25 b(has)g(se)n(v)o(eral)g(adv)n +(antages:)31 b(it)25 b(al-)1850 5649 y(\22612\226)p eop +%%Page: 13 13 +13 12 bop 0 -180 a Fg(Magic)24 b(T)l(utorial)g(#8:)30 +b(Circuit)25 b(Extraction)1603 b(September)25 b(26,)g(2001)488 +2170 y @beginspecial 68 @llx 68 @lly 467 @urx 364 @ury +3510 @rwi @setspecial +%%BeginDocument: ../psfigures/tut8.5.ps +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/arrowhead90 { +% -20 -12 36 24 bbox +begingate +1.00 90 -16 0 arrowhead +endgate +} def + +/pgsave save def bop +% 916 480 offsets +1.0000 inchscale +2.6000 setlinewidth + +1.000 0.000 0.000 scb +240 1.00 260 736 260 800 324 800 324 736 4 polygon +240 1.00 516 736 516 800 580 800 580 736 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 324 800 324 896 516 896 516 800 4 polygon +240 1.00 324 640 324 736 516 736 516 640 4 polygon +sce +0.133 0.545 0.133 scb +240 1.00 324 736 324 800 516 800 516 736 4 polygon +sce +1.000 0.000 0.000 scb +240 1.00 260 320 260 384 324 384 324 320 4 polygon +240 1.00 516 320 516 384 580 384 580 320 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 324 384 324 512 516 512 516 384 4 polygon +240 1.00 324 192 324 320 516 320 516 192 4 polygon +sce +0.133 0.545 0.133 scb +240 1.00 324 320 324 384 516 384 516 320 4 polygon +sce +1.000 0.000 0.000 scb +240 1.00 852 736 852 800 916 800 916 736 4 polygon +240 1.00 1012 544 1012 608 1076 608 1076 544 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 916 800 916 896 1172 896 1172 800 4 polygon +sce +0.133 0.545 0.133 scb +240 1.00 916 736 916 800 1076 800 1076 736 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 916 608 916 736 1012 736 1012 608 4 polygon +sce +0.133 0.545 0.133 scb +240 1.00 1012 608 1012 736 1076 736 1076 608 4 polygon +240 1.00 388 288 388 416 452 416 452 288 4 polygon +sce +0.439 1.000 0.314 scb +240 1.00 1076 608 1076 800 1172 800 1172 608 4 polygon +sce +(6) {/Times-Roman 1.000 cf} 2 21 0 420 928 label +(6) {/Times-Roman 1.000 cf} 2 21 0 420 544 label +(6) {/Times-Roman 1.000 cf} 2 21 0 1204 704 label +(2) {/Times-Roman 1.000 cf} 2 21 0 1044 512 label +(2) {/Times-Roman 1.000 cf} 2 21 0 820 768 label +(2) {/Times-Roman 1.000 cf} 2 21 0 612 768 label +(2) {/Times-Roman 1.000 cf} 2 21 0 612 352 label +(1) {/Times-Roman 1.000 cf} 2 25 0 612 464 label +(4) {/Times-Roman 1.000 cf} 2 21 0 884 672 label +(\(a\)) {/Times-Roman 1.000 cf} 2 21 0 212 768 label +(\(c\)) {/Times-Roman 1.000 cf} 2 21 0 212 352 label +(\(b\)) {/Times-Roman 1.000 cf} 2 21 0 756 768 label +1 1.00 836 800 804 800 2 polygon +1 1.00 836 736 804 736 2 polygon +1.00 0 820 736 arrowhead +1.00 -181 820 800 arrowhead +1 1.00 1012 528 1012 480 2 polygon +1 1.00 1076 528 1076 480 2 polygon +1 1.00 1188 608 1236 608 2 polygon +1 1.00 1188 800 1236 800 2 polygon +1 1.00 852 608 900 608 2 polygon +1 1.00 596 384 644 384 2 polygon +1 1.00 596 320 644 320 2 polygon +1 1.00 532 416 644 416 2 polygon +1 1.00 596 736 644 736 2 polygon +1 1.00 596 800 644 800 2 polygon +1 1.00 324 912 324 960 2 polygon +1 1.00 516 912 516 960 2 polygon +1 1.00 324 528 324 576 2 polygon +1 1.00 516 528 516 576 2 polygon +1 1.00 452 544 500 544 2 polygon +1 1.00 388 544 340 544 2 polygon +1 1.00 388 928 340 928 2 polygon +1 1.00 452 928 500 928 2 polygon +1 1.00 612 816 612 848 2 polygon +1 1.00 612 720 612 688 2 polygon +1 1.00 820 816 820 864 2 polygon +1 1.00 820 720 820 672 2 polygon +1 1.00 612 400 612 448 2 polygon +1 1.00 612 304 612 256 2 polygon +1 1.00 996 512 948 512 2 polygon +1 1.00 1092 512 1140 512 2 polygon +1 1.00 1204 624 1204 672 2 polygon +1 1.00 1204 736 1204 784 2 polygon +1 1.00 884 640 884 624 2 polygon +1 1.00 884 704 884 720 2 polygon +1.00 0 612 736 arrowhead +1.00 0 612 320 arrowhead +1.00 0 1204 800 arrowhead +1.00 0 884 736 arrowhead +1.00 -181 884 608 arrowhead +1.00 -181 1204 608 arrowhead +1.00 -181 612 800 arrowhead +1.00 -181 612 384 arrowhead +1.00 -181 612 416 arrowhead +1.00 0 340 928 arrowhead90 +1.00 0 340 544 arrowhead90 +1.00 0 1092 512 arrowhead90 +1.00 -1 996 512 arrowhead90 +1.00 -1 500 544 arrowhead90 +1.00 -1 500 928 arrowhead90 +pgsave restore showpage + +XCIRCsave restore +%%EndDocument + @endspecial 0 2373 a(Figure)40 b(5:)61 b(\(a\))41 b(When)g +(transistors)d(are)j(rectangular)l(,)j(it)c(is)g(possible)f(to)g +(compute)h Fd(L=W)54 b Fg(e)o(xactly)-6 b(.)75 b(Here)0 +2494 y Fh(gateperim)p Fa(=)37 b(4)p Fg(,)31 b Fh(sr)l(cperim)p +Fa(=)37 b(6)p Fg(,)31 b Fh(dr)o(ainperim)p Fa(=)36 b(6)p +Fg(,)31 b(and)f Fd(L=W)52 b Fa(=)37 b(2)p Fd(=)p Fa(6)p +Fg(.)47 b(\(b\))30 b(The)h Fd(L=W)44 b Fg(of)30 b(non-branching)0 +2614 y(transistors)19 b(can)i(be)g(approximated.)28 b(Here)21 +b Fh(gateperim)p Fa(=)26 b(4)p Fg(,)21 b Fh(sr)l(cperim)p +Fa(=)27 b(6)p Fg(,)22 b Fh(dr)o(ainperim)p Fa(=)j(10)p +Fg(.)k(By)21 b(a)n(v)o(eraging)0 2735 y Fh(sr)l(cperim)29 +b Fg(and)h Fh(dr)o(ainperim)e Fg(we)i(get)g Fd(L=W)51 +b Fa(=)37 b(2)p Fd(=)p Fa(8)p Fg(.)45 b(\(c\))31 b(The)f +Fd(L=W)44 b Fg(of)30 b(branching)f(transistors)g(is)g(not)g(well)0 +2855 y(approximated.)44 b(Here)31 b Fh(gateperim)p Fa(=)k(16)p +Fg(,)30 b Fh(sr)l(cperim)p Fa(=)37 b(2)p Fg(,)30 b Fh(dr)o(ainperim)p +Fa(=)35 b(2)p Fg(.)45 b(Magic')-5 b(s)28 b(estimate)h(of)h +Fd(L=W)44 b Fg(is)0 2975 y Fa(8)p Fd(=)p Fa(2)p Fg(,)25 +b(whereas)h(in)f(f)o(act)h(because)g(of)g(current)g(spreading,)f +Fd(W)40 b Fg(is)25 b(ef)n(fecti)n(v)o(ely)f(lar)n(ger)i(than)f +Fa(2)h Fg(and)f Fd(L)h Fg(ef)n(fecti)n(v)o(ely)0 3096 +y(smaller)e(than)h Fa(8)p Fg(,)f(so)h Fd(L=W)38 b Fg(is)25 +b(o)o(v)o(erestimated.)0 3467 y(lo)n(ws)f(simulation)e(of)j(analog)f +(circuits)h(in)f(which)g(wells)h(are)g(biased)f(to)h(dif)n(ferent)f +(potentials,)f(and)i(it)f(pro)o(vides)0 3587 y(a)31 b(form)f(of)h +(checking)f(to)g(ensure)h(that)f(wells)g(in)g(a)h(CMOS)g(process)f(are) +h(e)o(xplicitly)e(tied)h(to)g(the)g(appropriate)0 3708 +y(DC)25 b(v)n(oltage.)146 3831 y(T)m(ransistor)30 b(substrate)h(nodes)g +(are)h(disco)o(v)o(ered)e(by)h(the)h(e)o(xtractor)f(only)f(if)i(the)f +(transistor)f(and)i(the)f(o)o(v)o(er)n(-)0 3951 y(lapping)e(well)g +(layer)h(are)h(in)e(the)h(same)f(cell.)46 b(If)30 b(the)o(y)f(appear)i +(in)e(dif)n(ferent)g(cells,)i(the)f(transistor')-5 b(s)28 +b(substrate)0 4071 y(terminal)c(will)g(be)h(set)f(to)h(the)f(def)o +(ault)h(for)g(the)g(type)f(of)h(transistor)-5 b(.)146 +4194 y(Load)26 b(the)h(cell)f Fe(tut8l)p Fg(,)h(e)o(xtract)f(it,)g(and) +g(look)g(at)g(the)g(\002le)h Fe(tut8l.ext)p Fg(.)36 b(T)-8 +b(able)26 b(1)g(sho)n(ws)f(the)h(lines)g(for)h(the)f(six)0 +4314 y(transistors)21 b(in)i(the)f(\002le.)31 b(Y)-11 +b(ou')o(ll)22 b(notice)g(that)h(the)f(substrate)g(terminals)g(\(the)h +Fh(Subs)f Fg(column\))g(for)h(all)f(transistors)0 4435 +y(are)i(dif)n(ferent.)30 b(Since)25 b(each)f(transistor)f(in)g(this)g +(design)g(has)g(a)h(dif)n(ferent)g(gate)f(attrib)n(ute)g(attached)h(to) +f(it)g(\(sho)n(wn)0 4555 y(in)h(bold)g(in)h(the)g(table,)f +Fh(e)o(.g)o(.)p Fg(,)g Fe(N1)p Fg(,)g Fe(P2)p Fg(,)h(etc\),)g(we')o(ll) +g(use)f(them)g(in)h(the)f(follo)n(wing)f(discussion.)146 +4678 y(The)j(simplest)e(tw)o(o)i(transistors)f(are)h +Fe(N3)g Fg(and)g Fe(P3)p Fg(,)g(which)f(don')n(t)h(appear)g(in)g(an)o +(y)f(e)o(xplicitly)f(dra)o(wn)i(wells.)0 4798 y(The)20 +b(substrate)f(terminals)g(for)h(these)f(are)i Fe(GND!)e +Fg(and)h Fe(Vdd!)30 b Fg(respecti)n(v)o(ely)-6 b(,)19 +b(since)g(that')-5 b(s)19 b(what)h(the)f(technology)0 +4918 y(\002le)29 b(says)f(is)g(the)h(def)o(ault)f(for)h(the)f(tw)o(o)g +(types)g(of)h(transistors.)40 b Fe(N1)29 b Fg(and)f Fe(P1)h +Fg(are)g(standard)f(transistors)f(that)h(lie)0 5039 y(in)f(wells)f +(tied)g(to)h(the)g(ground)f(and)h(po)n(wer)f(rails,)h(labelled)g(in)f +(this)g(cell)h(as)g Fe(Vss#0)f Fg(and)h Fe(Vdd#0)g Fg(respecti)n(v)o +(ely)-6 b(.)0 5159 y(\(The)o(y')h(re)29 b(not)g(labelled)g +Fe(GND!)g Fg(and)g Fe(Vdd!)45 b Fg(so)29 b(you')o(ll)f(see)i(the)f(dif) +n(ference)g(between)g Fe(N1)g Fg(and)h Fe(N3)p Fg(\).)44 +b Fe(P2)29 b Fg(lies)0 5280 y(in)h(a)h(well)f(that)g(is)f(tied)h(to)g +(a)h(dif)n(ferent)f(bias)g(v)n(oltage,)h Fe(VBias)p Fg(,)g(such)f(as)h +(might)e(occur)h(in)g(an)h(analog)f(design.)0 5400 y(Finally)-6 +b(,)32 b Fe(N2)g Fg(is)f(in)h(a)g(well)f(that)g(isn')n(t)h(tied)f(to)g +(an)o(y)h(wire.)51 b(The)32 b(substrate)f(node)h(appears)g(as)f +Fe(Float)h Fg(because)1850 5649 y(\22613\226)p eop +%%Page: 14 14 +14 13 bop 0 -180 a Fg(September)25 b(26,)f(2001)1604 +b(Magic)25 b(T)l(utorial)e(#8:)30 b(Circuit)25 b(Extraction)0 +69 y(that')-5 b(s)24 b(the)g(label)h(that)f(w)o(as)h(attached)g(to)f +(the)h(well)g(surrounding)e Fe(N2)p Fg(.)146 190 y(The)41 +b(ability)f(to)h(e)o(xtract)f(transistor)g(substrate)h(nodes)f(allo)n +(ws)g(you)h(to)f(perform)h(a)h(simple)d(check)j(for)0 +310 y(whether)34 b(or)h(not)f(transistors)f(are)i(in)f(properly)g +(connected)h(\()p Fh(e)o(.g)o(.)p Fg(,)g(grounded\))f(wells.)59 +b(In)35 b(a)g(p-well)f(CMOS)0 431 y(process,)24 b(for)g(e)o(xample,)f +(you)h(might)e(set)i(the)g(def)o(ault)f(substrate)h(node)f(for)i +(n-channel)e(transistors)g(to)h(be)g(some)0 551 y(distinguished)j +(global)h(node)i(other)f(than)g(ground,)g Fh(e)o(.g)o(.)p +Fg(,)h Fe(NSubstrateNode!)p Fg(.)46 b(Y)-11 b(ou)29 b(could)g(then)g(e) +o(xtract)g(the)0 671 y(circuit,)35 b(\003atten)f(it)f(using)g +Fh(e)n(xt2spice)g Fg(\(1\))h(\(which)f(preserv)o(es)h(substrate)f +(nodes,)i(unlik)o(e)e Fh(e)n(xt2sim)g Fg(\(1\))h(which)0 +792 y(ignores)29 b(them\),)h(and)f(look)g(at)g(the)g(substrate)g(node)g +(\002elds)g(of)h(all)f(the)g(n-channel)g(transistors:)38 +b(if)30 b(there)f(were)0 912 y(an)o(y)21 b(whose)h(substrate)f(nodes)h +(weren')n(t)g(connected)g(to)g Fe(GND!)p Fg(,)g(then)f(these)h +(transistors)f(appear)h(either)g(outside)0 1033 y(of)h(an)o(y)f(e)o +(xplicit)f(well)h(\(their)h(substrate)f(nodes)g(will)g(be)g(the)h(def)o +(ault)f(of)h Fe(NSubstrateNode)p Fg(\),)i(or)e(in)f(a)h(well)g(that)0 +1153 y(isn')n(t)h(tied)h(to)f Fe(GND!)g Fg(with)g(a)i(substrate)e +(contact.)0 1498 y Fi(6)143 b(Extraction)34 b(styles)0 +1723 y Fg(Magic)25 b(usually)f(kno)n(ws)h(se)n(v)o(eral)f(dif)n(ferent) +h(w)o(ays)h(to)f(e)o(xtract)g(a)g(circuit)h(from)f(a)g(gi)n(v)o(en)f +(layout.)32 b(Each)26 b(of)f(these)0 1843 y(w)o(ays)h(is)h(called)f(a)h +Fh(style)p Fg(.)36 b(Dif)n(ferent)26 b(styles)g(can)h(be)g(used)f(to)g +(handle)h(dif)n(ferent)f(f)o(abrication)g(f)o(acilities,)h(which)0 +1964 y(may)36 b(dif)n(fer)g(in)g(the)g(parameters)g(the)o(y)f(ha)n(v)o +(e)h(for)h(parasitic)f(capacitance)h(and)f(resistance.)64 +b(F)o(or)37 b(a)f(scalable)0 2084 y(technology)-6 b(,)41 +b(such)e(as)g(the)g(def)o(ault)g Fe(scmos)p Fg(,)k(there)c(can)h(be)f +(a)h(dif)n(ferent)f(e)o(xtraction)f(style)h(for)g(each)h(scale)0 +2205 y(f)o(actor)-5 b(.)30 b(The)24 b(e)o(xact)g(number)g(and)g(nature) +g(of)g(the)g(e)o(xtraction)f(styles)g(is)h(described)g(in)f(the)h +(technology)f(\002le)i(that)0 2325 y(Magic)f(reads)i(when)e(it)h +(starts.)30 b(At)24 b(an)o(y)g(gi)n(v)o(en)g(time,)g(there)h(is)f(one)h +(current)g(e)o(xtraction)f(style.)146 2446 y(T)-8 b(o)25 +b(print)f(a)h(list)f(of)h(the)f(e)o(xtraction)g(styles)g(a)n(v)n +(ailable,)g(type)h(the)f(command)900 2681 y Fe(:extract)i(style)p +Fg(.)146 2915 y(The)33 b Fe(scmos)g Fg(technology)f(currently)g(has)h +(the)g(styles)f Fe(lambda=1.5)p Fg(,)i Fe(lambda=1.0)p +Fg(,)h(and)e Fe(lambda=0.6)p Fg(,)0 3036 y(though)28 +b(this)g(changes)g(o)o(v)o(er)g(time)g(as)h(technology)f(e)n(v)n(olv)o +(es.)41 b(T)-8 b(o)29 b(change)g(the)f(e)o(xtraction)g(style)g(to)h +Fh(style)p Fg(,)g(use)0 3156 y(the)c(command)900 3391 +y Fe(:extract)h(style)p Fh(style)146 3625 y Fg(Each)31 +b(style)e(has)h(a)h(speci\002c)f(scale)g(f)o(actor)h(between)f(Magic)g +(units)f(and)h(physical)f(units)g(\()p Fh(e)o(.g)o(.)p +Fg(,)h(microns\);)0 3746 y(you)25 b(can')n(t)h(use)f(a)h(particular)f +(style)g(with)f(a)i(dif)n(ferent)f(scale)h(f)o(actor)-5 +b(.)32 b(T)-8 b(o)25 b(change)h(the)f(scalef)o(actor)l(,)h(you')o(ll)e +(ha)n(v)o(e)0 3866 y(to)g(edit)h(the)g(appropriate)f(style)g(in)h(the)g +Fe(extract)g Fg(section)f(of)h(the)g(technology)f(\002le.)31 +b(This)24 b(process)h(is)f(described)0 3986 y(in)g(\223Magic)h +(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 b(The)25 b(T)-7 +b(echnology)24 b(File.)-7 b(\224)0 4331 y Fi(7)143 b(Flattening)34 +b(Extracted)f(Cir)m(cuits)0 4556 y Fg(Unfortunately)-6 +b(,)19 b(v)o(ery)g(fe)n(w)h(tools)f(e)o(xist)f(to)i(tak)o(e)f(adv)n +(antage)h(of)f(the)h Fh(e)n(xt)g Fg(\(5\))g(format)f(\002les)h +(produced)g(by)f(Magic')-5 b(s)0 4677 y(e)o(xtractor)g(.)31 +b(T)-8 b(o)25 b(use)g(these)h(\002les)f(for)g(simulation)f(or)h(timing) +e(analysis,)i(you)g(will)f(most)g(lik)o(ely)g(need)i(to)f(con)l(v)o +(ert)0 4797 y(them)f(to)h(a)g(\003attened)g(format,)f(such)h(as)g +Fh(sim)f Fg(\(5\))h(or)g Fh(spice)f Fg(\(5\).)146 4918 +y(There)c(are)h(se)n(v)o(eral)d(programs)h(for)h(\003attening)f +Fh(e)n(xt)h Fg(\(5\))g(\002les.)29 b Fh(Ext2sim)18 b +Fg(\(1\))i(produces)g Fh(sim)f Fg(\(5\))g(\002les)h(suitable)0 +5039 y(for)i(use)g(with)f Fh(crystal)h Fg(\(1\),)g Fh(esim)g +Fg(\(1\),)h(or)f Fh(r)o(sim)f Fg(\(1\).)30 b Fh(Ext2spice)22 +b Fg(\(1\))g(is)f(used)h(to)g(produce)g Fh(spice)g Fg(\(5\))g(\002les)g +(for)g(use)0 5159 y(with)h(the)h(circuit-le)n(v)o(el)f(simulator)f +Fh(spice)i Fg(\(1\).)30 b(Finally)-6 b(,)23 b Fh(e)n(xtc)o(hec)n(k)i +Fg(\(1\))f(can)h(be)f(used)f(to)h(perform)g(connecti)n(vity)0 +5280 y(checking)29 b(and)g(will)g(summarize)f(the)h(number)g(of)g +(\003attened)h(nodes,)g(transistors,)e(capacitors,)j(and)e(resistors)0 +5400 y(in)22 b(a)g(circuit.)30 b(All)21 b(of)h(these)g(programs)g(mak)o +(e)g(use)g(of)g(a)g(library)g(kno)n(wn)f(as)h Fh(e)n(xt\003at)g +Fg(\(3\),)h(so)f(the)g(con)l(v)o(entions)e(for)1850 5649 +y(\22614\226)p eop +%%Page: 15 15 +15 14 bop 0 -180 a Fg(Magic)24 b(T)l(utorial)g(#8:)30 +b(Circuit)25 b(Extraction)1603 b(September)25 b(26,)g(2001)0 +68 y(each)30 b(and)g(the)g(checks)g(the)o(y)f(perform)h(are)g +(virtually)f(identical.)45 b(The)29 b(documentation)g(for)h +Fh(e)n(xtc)o(hec)n(k)g Fg(co)o(v)o(ers)0 189 y(the)25 +b(options)e(common)h(to)g(all)g(of)h(these)g(programs.)146 +309 y(T)-8 b(o)29 b(see)h(ho)n(w)e Fh(e)n(xt2sim)h Fg(w)o(orks,)h(load) +e(the)h(cell)g Fe(tut8n)i Fg(and)e(e)o(xpand)f(all)h(the)g +Fe(tutm)h Fg(subcells.)43 b(Notice)29 b(ho)n(w)0 429 +y(the)d Fe(GND!)f Fg(b)n(us)g(is)g(completely)g(wired,)h(b)n(ut)f(the)h +Fe(Vdd!)34 b Fg(b)n(us)25 b(is)h(in)f(three)h(disconnected)f(pieces.)33 +b(No)n(w)25 b(e)o(xtract)0 550 y(e)n(v)o(erything)f(with)h +Fe(:extract)p Fg(,)j(then)d(e)o(xit)g(Magic)h(and)g(run)g +Fe(ext2sim)g(tut8n)p Fg(.)35 b(Y)-11 b(ou')o(ll)25 b(see)i(the)e(follo) +n(wing)f(sort)i(of)0 670 y(output:)300 898 y Fb(***)59 +b(Global)g(name)f(Vdd!)119 b(not)59 b(fully)g(connected:)300 +1019 y(One)g(portion)f(contains)g(the)h(names:)600 1139 +y(left/Vdd!)300 1260 y(The)g(other)g(portion)f(contains)g(the)h(names:) +600 1380 y(center/Vdd!)300 1500 y(I'm)g(merging)f(the)h(two)h(pieces)e +(into)h(a)g(single)g(node,)f(but)i(you)300 1621 y(should)e(be)i(sure)f +(eventually)e(to)i(connect)g(them)g(in)g(the)g(layout.)300 +1861 y(***)g(Global)g(name)f(Vdd!)119 b(not)59 b(fully)g(connected:)300 +1982 y(One)g(portion)f(contains)g(the)h(names:)600 2102 +y(left/Vdd!)600 2223 y(center/Vdd!)300 2343 y(The)g(other)g(portion)f +(contains)g(the)h(names:)600 2463 y(right/Vdd!)300 2584 +y(I'm)g(merging)f(the)h(two)h(pieces)e(into)h(a)g(single)g(node,)f(but) +i(you)300 2704 y(should)e(be)i(sure)f(eventually)e(to)i(connect)g(them) +g(in)g(the)g(layout.)300 2945 y(Memory)f(used:)119 b(56k)146 +3173 y Fg(The)25 b(w)o(arning)f(messages)g(are)h(telling)e(you)h(that)g +(the)h(global)e(name)i Fe(Vdd!)31 b Fg(isn')n(t)24 b(completely)g +(wired)g(in)g(the)0 3294 y(layout.)33 b(The)26 b(\003attener)h(w)o +(arns)f(you,)g(b)n(ut)f(goes)h(ahead)g(and)g(connects)g(the)g(pieces)g +(together)f(an)o(yw)o(ay)h(to)f(allo)n(w)0 3414 y(you)i(to)f(simulate)g +(the)h(circuit)g(as)g(though)f(it)h(had)g(been)g(completely)f(wired.)38 +b(The)27 b(output)f(of)h Fh(e)n(xt2sim)g Fg(will)f(be)0 +3534 y(three)h(\002les:)34 b Fe(tut8n.sim)p Fg(,)28 b +Fe(tut8n.al)p Fg(,)f(and)g Fe(tut8n.nodes)p Fg(;)i(see)e +Fh(e)n(xt2sim)f Fg(\(1\))h(or)g Fh(sim)f Fg(\(5\))h(for)g(more)g +(information)0 3655 y(on)h(the)h(contents)e(of)i(these)f(\002les.)42 +b(\223)p Fe(Magic)28 b(T)-9 b(utorial)29 b(#11:)38 b(Using)28 +b(RSIM)h(with)f(Magic)p Fg(\224)h(e)o(xplains)e(ho)n(w)g(to)0 +3775 y(use)e(the)f(output)g(of)h Fh(e)n(xt2sim)f Fg(with)g(the)h +(switch-le)n(v)o(el)e(simulator)l(,)g Fh(r)o(sim)h Fg(\(1\).)1850 +5649 y(\22615\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tut9.ps b/doc/psfiles/tut9.ps new file mode 100644 index 00000000..08b1f693 --- /dev/null +++ b/doc/psfiles/tut9.ps @@ -0,0 +1,869 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tut9.dvi +%%Pages: 6 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tut9.dvi -o tut9.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +%%BeginProcSet: special.pro +TeXDict begin /SDict 200 dict N SDict begin /@SpecialDefaults{/hs 612 N +/vs 792 N /ho 0 N /vo 0 N /hsc 1 N /vsc 1 N /ang 0 N /CLIP 0 N /rwiSeen +false N /rhiSeen false N /letter{}N /note{}N /a4{}N /legal{}N}B +/@scaleunit 100 N /@hscale{@scaleunit div /hsc X}B /@vscale{@scaleunit +div /vsc X}B /@hsize{/hs X /CLIP 1 N}B /@vsize{/vs X /CLIP 1 N}B /@clip{ +/CLIP 2 N}B /@hoffset{/ho X}B /@voffset{/vo X}B /@angle{/ang X}B /@rwi{ +10 div /rwi X /rwiSeen true N}B /@rhi{10 div /rhi X /rhiSeen true N}B +/@llx{/llx X}B /@lly{/lly X}B /@urx{/urx X}B /@ury{/ury X}B /magscale +true def end /@MacSetUp{userdict /md known{userdict /md get type +/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup +length 20 add dict copy def}if end md begin /letter{}N /note{}N /legal{} +N /od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath +clippath mark{transform{itransform moveto}}{transform{itransform lineto} +}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{ +itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{ +closepath}}pathforall newpath counttomark array astore /gc xdf pop ct 39 +0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}N +/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 +scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get +ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip +not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 +TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{noflips{TR +pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 +-1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg +TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg +sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr +0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add +2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N /cp +{pop pop showpage pm restore}N end}if}if}N /normalscale{Resolution 72 +div VResolution 72 div neg scale magscale{DVImag dup scale}if 0 setgray} +N /psfts{S 65781.76 div N}N /startTexFig{/psf$SavedState save N userdict +maxlength dict begin /magscale true def normalscale currentpoint TR +/psf$ury psfts /psf$urx psfts /psf$lly psfts /psf$llx psfts /psf$y psfts +/psf$x psfts currentpoint /psf$cy X /psf$cx X /psf$sx psf$x psf$urx +psf$llx sub div N /psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy +scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR +/showpage{}N /erasepage{}N /copypage{}N /p 3 def @MacSetUp}N /doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N /endTexFig{end psf$SavedState restore}N /@beginspecial{SDict +begin /SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count /ocount X /dcount countdictstack N}N /@setspecial +{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if /showpage{}N /erasepage{}N /copypage{}N newpath +}N /@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{ +end}repeat grestore SpecialSave restore end}N /@defspecial{SDict begin} +N /@fedspecial{end}B /li{lineto}B /rl{rlineto}B /rc{rcurveto}B /np{ +/SaveX currentpoint /SaveY X N 1 setlinecap newpath}N /st{stroke SaveX +SaveY moveto}N /fil{fill SaveX SaveY moveto}N /ellipse{/endangle X +/startangle X /yrad X /xrad X /savematrix matrix currentmatrix N TR xrad +yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tut9.dvi) +@start /Fa 134[50 1[72 50 55 33 39 44 1[55 50 55 83 28 +2[28 1[50 33 44 55 44 55 50 12[66 3[61 12[72 5[57 2[33 +50 4[50 2[50 50 1[25 33 3[33 33 36[55 55 2[{ + TeXBase1Encoding ReEncodeFont }35 100.000003 /Times-Bold +rf /Fb 138[66 40 47 53 2[60 66 100 33 2[33 66 2[53 66 +53 1[60 12[80 6[113 9[86 8[40 55[66 2[{ TeXBase1Encoding ReEncodeFont } +19 119.999948 /Times-Bold rf /Fc 105[50 1[44 44 24[44 +50 50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 +50 33 44 50 44 50 44 7[72 1[94 1[72 61 55 66 1[55 72 +1[89 61 2[33 72 72 55 61 72 66 66 72 5[28 28 50 1[50 +50 50 50 50 50 50 50 28 25 33 25 2[33 33 33 2[50 50 31[55 +55 2[{ TeXBase1Encoding ReEncodeFont }70 100.000003 /Times-Roman +rf /Fd 134[44 44 66 1[50 28 39 39 1[50 50 50 72 28 3[50 +2[44 50 1[50 50 11[72 1[50 3[72 66 3[44 27[25 1[25 2[33 +33 37[50 2[{ TeXBase1Encoding ReEncodeFont }27 100.000003 +/Times-Italic rf /Fe 134[72 1[104 72 80 48 56 64 2[72 +80 120 40 2[40 80 72 48 64 80 64 80 72 9[143 2[96 80 +104 1[88 112 104 135 3[56 1[112 88 2[104 96 7[48 72 3[72 +72 72 72 72 3[48 9[72 35[{ TeXBase1Encoding ReEncodeFont }42 +143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 158 101 a Fe(Magic)36 b(T)-13 b(utorial)34 b(#9:)43 +b(F)l(ormat)35 b(Con)-6 b(v)o(ersion)33 b(f)l(or)i(CIF)g(and)g(Calma) +1618 521 y Fd(J)n(ohn)24 b(Ousterhout)1401 941 y Fc(Computer)g(Science) +i(Di)n(vision)1020 1062 y(Electrical)f(Engineering)f(and)h(Computer)f +(Sciences)1473 1182 y(Uni)n(v)o(ersity)f(of)i(California)1544 +1303 y(Berk)o(ele)o(y)-6 b(,)24 b(CA)h(94720)1448 1573 +y Fd(\(Updated)f(by)h(other)o(s,)f(too.\))1053 1843 y +Fc(This)g(tutorial)g(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.)0 +2336 y Fb(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 +2513 y Fc(Magic)24 b(T)l(utorial)g(#1:)30 b(Getting)24 +b(Started)300 2633 y(Magic)g(T)l(utorial)g(#2:)30 b(Basic)25 +b(P)o(ainting)f(and)h(Selection)300 2754 y(Magic)f(T)l(utorial)g(#4:)30 +b(Cell)25 b(Hierarchies)0 2930 y Fb(Commands)k(intr)n(oduced)j(in)f +(this)f(tutorial:)300 3107 y Fc(:calma,)24 b(:cif)0 3284 +y Fb(Macr)n(os)29 b(intr)n(oduced)i(in)g(this)f(tutorial:)300 +3477 y Fd(\(None\))0 4334 y Fe(1)143 b(Basics)0 4557 +y Fc(CIF)33 b(\(Caltech)f(Intermediate)f(F)o(orm\))g(and)g(Calma)h +(Stream)f(F)o(ormat)g(are)h(standard)f(layout)g(description)f(lan-)0 +4678 y(guages)g(used)g(to)g(transfer)h(mask-le)n(v)o(el)e(layouts)g +(between)i(or)n(ganizations)e(and)h(design)g(tools.)46 +b(This)30 b(tutorial)0 4798 y(describes)22 b(ho)n(w)f(Magic)h(can)h(be) +f(used)g(to)g(read)h(and)f(write)g(\002les)g(in)g(CIF)i(and)e(Stream)g +(formats.)30 b(The)22 b(v)o(ersion)f(of)0 4918 y(CIF)26 +b(that)e(Magic)h(supports)f(is)g(CIF)i(2.0;)f(it)f(is)g(the)h(most)f +(popular)g(layout)g(language)h(in)g(the)f(uni)n(v)o(ersity)f(design)0 +5039 y(community)-6 b(.)40 b(The)29 b(Calma)g(format)g(that)f(Magic)h +(supports)e(is)i(GDS)g(II)g(Stream)h(format,)f(v)o(ersion)f(3.0,)h +(corre-)0 5159 y(sponding)21 b(to)h(GDS)h(II)g(Release)g(5.1.)30 +b(This)22 b(is)g(probably)g(the)g(most)f(popular)h(layout)g +(description)g(language)g(for)0 5280 y(the)j(industrial)e(design)h +(community)-6 b(.)146 5400 y(T)e(o)25 b(write)g(out)f(a)h(CIF)h +(\002le,)f(place)g(the)g(cursor)g(o)o(v)o(er)f(a)h(layout)f(windo)n(w)f +(and)i(type)f(the)h(command)1875 5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fc(September)25 b(26,)f(2001)781 b(Magic)24 +b(T)l(utorial)g(#9:)30 b(F)o(ormat)24 b(Con)l(v)o(ersion)g(for)h(CIF)h +(and)f(Calma)900 84 y Fa(:cif)146 289 y Fc(This)31 b(will)g(generate)i +(a)f(CIF)h(\002le)f(called)g Fd(name)p Fa(.cif)p Fc(,)i(where)e +Fd(name)g Fc(is)f(the)h(name)g(of)g(the)f(root)h(cell)g(in)f(the)0 +409 y(windo)n(w)-6 b(.)32 b(The)26 b(CIF)h(\002le)g(will)e(contain)g(a) +i(description)d(of)i(the)g(entire)g(cell)g(hierarchy)g(in)f(that)h +(windo)n(w)-6 b(.)32 b(If)27 b(you)0 530 y(wish)d(to)h(use)f(a)h(name)g +(dif)n(ferent)f(from)h(the)g(root)f(cell,)h(type)f(the)h(command)900 +735 y Fa(:cif)g(write)g Fd(\002le)146 939 y Fc(This)j(will)g(store)h +(the)g(CIF)h(in)e Fd(\002le)p Fa(.cif)p Fc(.)43 b(Start)29 +b(Magic)g(up)f(to)h(edit)f Fa(tut9a)h Fc(and)g(generate)h(CIF)g(for)f +(that)f(cell.)0 1060 y(The)23 b(CIF)h(\002le)f(will)f(be)h(in)f(ASCII)i +(format,)f(so)f(you)h(can)g(use)f(Unix)h(commands)e(lik)o(e)h +Fa(mor)n(e)i Fc(and)e Fa(vi)h Fc(to)f(see)h(what)0 1180 +y(it)h(contains.)146 1301 y(T)-8 b(o)25 b(read)g(a)g(CIF)h(\002le)g +(into)e(Magic,)g(place)h(the)g(cursor)g(o)o(v)o(er)e(a)j(layout)e +(windo)n(w)f(and)i(type)f(the)h(command)900 1505 y Fa(:cif)g(r)n(ead)h +Fd(\002le)146 1710 y Fc(This)38 b(will)f(read)i(the)f(\002le)g +Fd(\002le)p Fa(.cif)h Fc(\(which)e(must)h(be)g(in)g(CIF)h(format\),)i +(generate)e(Magic)f(cells)g(for)g(the)0 1831 y(hierarchy)d(described)g +(in)g(the)g(\002le,)j(mak)o(e)d(the)g(entire)g(hierarchy)g(a)g(subcell) +g(of)g(the)g(edit)g(cell,)i(and)e(run)g(the)0 1951 y(design-rule)18 +b(check)o(er)i(to)f(v)o(erify)f(e)n(v)o(erything)g(read)h(from)g(the)g +(\002le.)29 b(Information)18 b(in)h(the)g(top-le)n(v)o(el)e(cell)i +(\(usually)0 2071 y(just)25 b(a)i(call)f(on)h(the)f(\223main\224)g +(cell)g(of)h(the)f(layout\))g(will)f(be)i(placed)f(into)f(the)i(edit)f +(cell.)35 b(Start)27 b(Magic)f(up)g(afresh)0 2192 y(and)35 +b(read)g(in)f Fa(tut9a.cif)p Fc(,)k(which)c(you)h(created)g(abo)o(v)o +(e.)60 b(It)34 b(will)g(be)h(easier)g(if)g(you)f(al)o(w)o(ays)h(read)g +(CIF)h(when)0 2312 y(Magic)23 b(has)h(just)f(been)h(started)g(up:)29 +b(if)24 b(some)f(of)h(the)g(cells)g(already)g(e)o(xist,)f(the)g(CIF)i +(reader)g(will)e(not)g(o)o(v)o(erwrite)0 2432 y(them,)h(b)n(ut)g(will)g +(instead)g(use)h(numbers)f(for)h(cell)g(names.)146 2553 +y(T)-8 b(o)34 b(read)h(and)f(write)g(Stream-format)g(\002les,)i(use)e +(the)g(commands)f Fa(:calma)h(r)n(ead)h Fc(and)f Fa(:calma)p +Fc(,)i(respec-)0 2673 y(ti)n(v)o(ely)-6 b(.)43 b(These)30 +b(commands)f(ha)n(v)o(e)g(the)h(same)g(ef)n(fect)g(as)g(the)g(CIF)h +(commands,)e(e)o(xcept)h(that)f(the)o(y)g(operate)h(on)0 +2794 y(\002les)24 b(with)g Fa(.strm)g Fc(e)o(xtensions.)29 +b(Stream)24 b(is)g(a)h(binary)f(format,)g(so)f(you)h(can')n(t)h(e)o +(xamine)e Fa(.strm)i Fc(\002les)f(with)g(a)g(te)o(xt)0 +2914 y(editor)-5 b(.)146 3034 y(Stream)38 b(\002les)g(do)f(not)g +(identify)g(a)g(top-le)n(v)o(el)f(cell,)41 b(so)c(you)g(w)o(on')n(t)g +(see)h(an)o(ything)e(on)h(the)g(screen)h(after)0 3155 +y(you')-5 b(v)o(e)24 b(used)g(the)g Fa(:calma)g(r)n(ead)i +Fc(command.)j(Y)-11 b(ou')o(ll)24 b(ha)n(v)o(e)g(to)g(use)h(the)f +Fa(:load)g Fc(command)g(to)g(look)g(at)g(the)g(cells)0 +3275 y(you)d(read.)30 b(Ho)n(we)n(v)o(er)l(,)21 b(if)h(Magic)f(w)o(as)h +(used)f(to)g(write)h(the)f(Calma)h(\002le)g(being)f(read,)i(the)e +(library)h(name)f(reported)0 3396 y(by)k(the)f Fa(:calma)h(r)n(ead)h +Fc(command)d(is)i(the)f(same)h(as)g(the)g(name)f(of)h(the)g(root)f +(cell)h(for)g(that)f(library)-6 b(.)146 3516 y(Also,)43 +b(Calma)d(format)f(places)h(some)f(limitations)e(on)i(the)h(names)f(of) +h(cells:)60 b(the)o(y)39 b(can)h(only)f(contain)0 3636 +y(alphanumeric)24 b(characters,)h(\223$\224,)g(and)g(\223)p +1427 3636 30 4 v 36 w(\224,)g(and)f(can)h(be)g(at)g(most)e(32)h +(characters)i(long.)k(If)25 b(the)f(name)h(of)f(a)h(cell)0 +3757 y(does)c(not)g(meet)g(these)h(limitations,)d Fa(:calma)j(write)g +Fc(con)l(v)o(erts)e(it)h(to)g(a)h(unique)f(name)g(of)h(the)f(form)p +3410 3757 150 5 v 172 w Fd(n)p Fc(,)h(where)0 3877 y +Fd(n)29 b Fc(is)f(a)h(small)f(inte)o(ger)-5 b(.)41 b(T)-8 +b(o)29 b(a)n(v)n(oid)f(an)o(y)g(possible)f(con\003icts,)j(you)e(should) +g(a)n(v)n(oid)g(using)g(names)g(lik)o(e)g(these)h(for)0 +3997 y(your)c(o)n(wn)e(cells.)146 4118 y(Y)-11 b(ou)27 +b(shouldn')n(t)e(need)i(to)g(kno)n(w)e(much)i(more)f(than)h(what')-5 +b(s)26 b(abo)o(v)o(e)g(in)g(order)h(to)g(read)g(and)g(write)f(CIF)i +(and)0 4238 y(Stream.)i(The)21 b(sections)f(belo)n(w)g(describe)i(the)e +(dif)n(ferent)h(styles)f(of)i(CIF/Calma)g(that)e(Magic)h(can)g +(generate)h(and)0 4359 y(the)31 b(limitations)e(of)j(the)f(CIF/Calma)h +(f)o(acilities)f(\(you)g(may)g(ha)n(v)o(e)h(noticed)e(that)h(when)h +(you)f(wrote)g(and)h(read)0 4479 y(CIF)24 b(abo)o(v)o(e)e(you)h(didn')n +(t)f(quite)h(get)g(back)g(what)g(you)f(started)h(with;)g(Section)g(3)g +(describes)f(the)h(dif)n(ferences)h(that)0 4599 y(can)k(occur\).)40 +b(Although)26 b(the)h(discussion)f(mentions)g(only)h(CIF)-8 +b(,)28 b(the)g(same)f(features)h(and)g(problems)e(apply)h(to)0 +4720 y(Calma.)0 5056 y Fe(2)143 b(Styles)0 5280 y Fc(Magic)28 +b(usually)f(kno)n(ws)g(se)n(v)o(eral)g(dif)n(ferent)h(w)o(ays)g(to)g +(generate)g(CIF/Calma)i(from)e(a)g(gi)n(v)o(en)f(layout.)40 +b(Each)28 b(of)0 5400 y(these)h(w)o(ays)g(is)f(called)h(a)g +Fd(style)p Fc(.)43 b(Dif)n(ferent)29 b(styles)f(can)h(be)g(used)g(to)f +(handle)h(dif)n(ferent)f(f)o(abrication)h(f)o(acilities,)1875 +5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#9:)30 b(F)o(ormat)24 +b(Con)l(v)o(ersion)g(for)h(CIF)h(and)f(Calma)781 b(September)25 +b(26,)g(2001)0 68 y(which)f(may)g(dif)n(fer)g(in)g(the)g(names)g(the)o +(y)g(use)g(for)h(layers)f(or)g(in)g(the)g(e)o(xact)h(mask)e(set)i +(required)f(for)h(f)o(abrication.)0 188 y(Dif)n(ferent)34 +b(styles)f(can)h(be)h(also)e(used)h(to)g(write)g(out)f(CIF/Calma)i +(with)f(slightly)e(dif)n(ferent)h(feature)i(sizes)f(or)0 +309 y(design)24 b(rules.)31 b(CIF/Calma)26 b(styles)e(are)i(described)f +(in)g(the)f(technology)g(\002le)i(that)e(Magic)h(reads)g(when)g(it)g +(starts)0 429 y(up;)d(the)g(e)o(xact)g(number)g(and)g(nature)g(of)g +(the)g(styles)f(is)h(determined)f(by)h(whoe)n(v)o(er)f(wrote)h(your)g +(technology)f(\002le.)0 549 y(There)h(are)h(separate)f(styles)e(for)i +(reading)g(and)g(writing)e(CIF/Calma;)k(at)d(an)o(y)g(gi)n(v)o(en)g +(time,)g(there)h(is)f(one)h(current)0 670 y(input)i(style)g(and)h(one)f +(current)h(output)f(style.)146 790 y(The)f(standard)g(SCMOS)h +(technology)d(\002le)j(pro)o(vides)d(an)i(e)o(xample)f(of)h(ho)n(w)g +(dif)n(ferent)f(styles)g(can)h(be)g(used.)0 911 y(Start)i(up)g(Magic)f +(with)g(the)h(SCMOS)g(technology)f(\()p Fa(magic)h(-Tscmos)p +Fc(\).)31 b(Then)24 b(type)h(the)g(commands)900 1082 +y Fa(:cif)g(ostyle)900 1202 y(:cif)g(istyle)146 1373 +y Fc(The)e(\002rst)g(command)f(will)f(print)i(out)f(a)h(list)e(of)i +(all)g(the)f(styles)g(in)g(which)h(Magic)f(can)h(write)g(CIF/Calma)g +(\(in)0 1493 y(this)18 b(technology\))g(and)i(the)f(second)f(command)h +(prints)f(out)g(the)h(styles)g(in)f(which)h(Magic)g(can)h(read)f +(CIF/Calma.)0 1614 y(Y)-11 b(ou)31 b(use)g(the)h Fa(:cif)f +Fc(command)g(to)g(change)g(the)g(current)h(styles,)g(b)n(ut)f(the)g +(styles)f(are)i(used)f(for)h(both)f(CIF)h(and)0 1734 +y(Calma)h(format)f(con)l(v)o(ersion.)53 b(The)33 b(SCMOS)g(technology)e +(\002le)i(pro)o(vides)f(se)n(v)o(eral)g(output)f(styles.)53 +b(The)33 b(ini-)0 1854 y(tial)d(\(def)o(ault\))h(style)e(for)i(writing) +f(CIF)h(is)f Fa(lambda=1.0\(gen\))p Fc(.)49 b(This)29 +b(style)h(generates)h(mask)f(layers)g(for)h(the)0 1975 +y(MOSIS)h(scalable)g(CMOS)h(process,)g(where)f(each)h(Magic)f(unit)f +(corresponds)g(to)g(1)h(micron)f(and)h(both)f(well)0 +2095 y(polarities)21 b(are)h(generated.)30 b(See)23 b(the)e(technology) +g(manual)g(for)h(more)g(information)e(on)i(the)f(v)n(arious)g(styles)g +(that)0 2216 y(are)26 b(a)n(v)n(ailable.)k(Y)-11 b(ou)24 +b(can)h(change)g(the)g(output)e(style)i(with)f(the)g(command)900 +2386 y Fa(:cif)h(ostyle)g Fd(ne)o(wStyle)146 2557 y Fc(where)30 +b Fd(ne)o(wStyle)f Fc(is)g(the)g(ne)n(w)f(style)h(you')-5 +b(d)28 b(lik)o(e)h(to)g(use)g(for)g(output.)43 b(After)29 +b(this)f(command,)h(an)o(y)g(future)0 2678 y(CIF)g(or)g(Calma)f +(\002les)h(will)e(be)i(generated)f(with)g(the)g(ne)n(w)g(style.)40 +b(The)29 b Fa(:cif)f(istyle)g Fc(command)f(can)i(be)f(used)g(in)0 +2798 y(the)d(same)f(w)o(ay)h(to)g(see)g(the)f(a)n(v)n(ailable)g(styles) +g(for)h(reading)g(CIF)h(and)f(to)f(change)h(the)g(current)g(style.)146 +2919 y(Each)d(style)e(has)h(a)h(speci\002c)g(scalef)o(actor;)g(you)f +(can')n(t)h(use)f(a)h(particular)f(style)f(with)h(a)g(dif)n(ferent)g +(scalef)o(actor)-5 b(.)0 3039 y(T)d(o)35 b(change)h(the)f(scalef)o +(actor)l(,)k(you')o(ll)34 b(ha)n(v)o(e)i(to)f(edit)g(the)g(appropriate) +g(style)g(in)g(the)g Fa(ci\002nput)j Fc(or)d Fa(cif)n(output)0 +3159 y Fc(section)28 b(of)h(the)f(technology)g(\002le.)43 +b(This)28 b(process)h(is)f(described)g(in)h(\223Magic)f(Maintainer')-5 +b(s)28 b(Manual)g(#2:)38 b(The)0 3280 y(T)-7 b(echnology)24 +b(File.)-7 b(\224)0 3612 y Fe(3)143 b(Rounding)0 3835 +y Fc(The)27 b(units)e(used)i(for)g(coordinates)f(in)g(Magic)g(are)i +(generally)e(dif)n(ferent)h(from)f(those)g(in)g(CIF)i(\002les.)37 +b(In)27 b(Magic,)0 3955 y(most)h(technology)h(\002les)h(use)f +(lambda-based)g(units,)g(where)h(one)g(unit)f(is)g(typically)f(half)i +(the)f(minimum)e(fea-)0 4076 y(ture)d(size.)31 b(In)25 +b(CIF)g(\002les,)g(the)f(units)f(are)j(centimicrons)d(\(hundredths)g +(of)i(a)g(micron\).)30 b(When)24 b(reading)h(CIF)g(and)0 +4196 y(Calma)h(\002les,)h(an)f(inte)o(ger)f(scalef)o(actor)i(is)e(used) +h(to)g(con)l(v)o(ert)f(from)h(centimicrons)f(to)h(Magic)f(units.)34 +b(If)26 b(the)g(CIF)0 4317 y(\002le)h(contains)f(coordinates)g(that)h +(don')n(t)f(scale)h(e)o(xactly)f(to)h(inte)o(ger)f(Magic)g(units,)g +(Magic)h(rounds)f(the)g(coordi-)0 4437 y(nates)31 b(up)g(or)g(do)n(wn)g +(to)g(the)g(closest)f(inte)o(ger)h(Magic)g(units.)49 +b(A)31 b(CIF)h(coordinate)f(e)o(xactly)g(halfw)o(ay)g(between)0 +4557 y(tw)o(o)21 b(Magic)g(units)f(is)h(rounded)g(do)n(wn.)29 +b(The)21 b(\002nal)h(authority)e(on)h(rounding)f(is)h(the)g(procedure)h +(CIFScaleCoord)0 4678 y(in)g(the)g(\002le)h(cif/CIFreadutils.c)f(When)g +(rounding)f(occurs,)i(the)f(resulting)f(Magic)h(\002le)h(will)e(not)h +(match)g(the)g(CIF)0 4798 y(\002le)j(e)o(xactly)-6 b(.)146 +4918 y(T)f(echnology)30 b(\002les)h(usually)e(specify)i(geometrical)f +(operations)g(such)g(as)h(bloating,)f(shrinking,)h(and-ing,)0 +5039 y(and)c(or)n(-ing)f(to)h(be)g(performed)g(on)f(CIF)i(geometries)e +(when)h(the)o(y)f(are)i(read)f(into)f(Magic.)37 b(These)27 +b(geometrical)0 5159 y(operations)h(are)h(all)g(performed)f(in)h(the)f +(CIF)i(coordinate)e(system)g(\(centimicrons\))f(so)i(there)g(is)f(no)g +(rounding)0 5280 y(or)c(loss)e(of)i(accurac)o(y)g(in)f(the)g +(operations.)30 b(Rounding)22 b(occurs)i(only)f(AFTER)h(the)f +(geometrical)g(operations,)g(at)0 5400 y(the)i(last)f(possible)f +(instant)h(before)h(entering)g(paint)f(into)g(the)g(Magic)h(database.) +1875 5649 y(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fc(September)25 b(26,)f(2001)781 b(Magic)24 +b(T)l(utorial)g(#9:)30 b(F)o(ormat)24 b(Con)l(v)o(ersion)g(for)h(CIF)h +(and)f(Calma)0 99 y Fe(4)143 b(Non-Manhattan)33 b(Geometries)0 +417 y Fc(Magic)f(only)f(supports)g(Manhattan)g(features.)52 +b(When)32 b(CIF)i(or)e(Calma)g(\002les)g(contain)f(non-Manhattan)g +(fea-)0 537 y(tures,)37 b(the)o(y)e(are)h(approximated)e(with)g +(Manhattan)g(ones.)62 b(The)35 b(approximations)e(occur)j(for)f(wires)g +(\(if)g(the)0 658 y(centerline)22 b(contains)f(non-Manhattan)g(se)o +(gments\))g(and)h(polygons)e(\(if)i(the)g(outline)f(contains)g +(non-Manhattan)0 778 y(se)o(gments\).)39 b(In)28 b(these)g(cases,)h +(the)f(non-Manhattan)e(se)o(gments)h(are)h(replaced)h(with)e(one)h(or)g +(more)g(horizontal)0 899 y(and)j(v)o(ertical)g(se)o(gments)f(before)h +(the)h(\002gure)f(is)g(processed.)50 b(Con)l(v)o(ersion)30 +b(is)h(done)g(by)g(inserting)f(a)i(one-unit)0 1019 y(stairstep)24 +b(on)h(a)g(45-de)o(gree)g(angle)g(until)f(a)i(point)e(is)g(reached)i +(where)g(a)f(horizontal)g(or)g(v)o(ertical)f(line)h(can)g(reach)0 +1139 y(the)f(se)o(gment')-5 b(s)22 b(endpoint.)29 b(Some)24 +b(e)o(xamples)f(are)i(illustrated)e(in)g(the)h(\002gure)h(belo)n(w:)k +(in)23 b(each)i(case,)g(the)f(\002gure)0 1260 y(on)h(the)f(left)h(is)f +(the)h(one)g(speci\002ed)g(in)f(the)h(CIF)h(\002le,)f(and)g(the)f +(\002gure)i(on)e(the)h(right)f(is)g(what)h(results)f(in)g(Magic.)877 +4007 y @beginspecial 68 @llx 68 @lly 403 @urx 447 @ury +2574 @rwi @setspecial +%%BeginDocument: ../psfigures/tut9.1.ps +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + + +% XCircuit output starts here. + +/dot { +% -10 -10 20 20 bbox +begingate +248 1.00 0 0 6 0.00 360.00 xcarc +endgate +} def + +/cifwire { +% -272 -32 400 64 bbox +begingate +0.490 0.651 0.980 scb +96 -32 beginpath +96 0 32 -90.00 90.00 arc +-240 32 1 polyc +-240 0 32 90.00 270.00 arc +96 -32 1 polyc +241 1.00 endpath +sce +1 1.00 -240 0 96 0 2 polygon +1.00 0 96 0 dot +1.00 0 -240 0 dot +96 -32 beginpath +96 0 32 -90.00 90.00 arc +-240 32 1 polyc +-240 0 32 90.00 270.00 arc +96 -32 1 polyc +1 1.00 endpath +endgate +} def + +/pgsave save def bop +% 800 1038 offsets +% 32.00 8.00 gridspace +1.0000 inchscale +2.6000 setlinewidth + +0.800 0.800 0.800 scb +241 1.00 672 302 800 302 1056 430 1056 558 928 686 736 654 672 590 672 302 +8 polygon +sce +0.490 0.651 0.980 scb +241 1.00 192 302 320 302 576 430 576 558 448 686 256 654 192 590 192 302 +8 polygon +sce +0.616 0.624 0.925 scb +241 1.00 672 302 864 302 864 366 928 366 928 430 1056 430 1056 558 992 558 992 +622 928 622 928 686 864 686 864 622 672 622 672 302 15 polygon +sce +0.490 0.651 0.980 scb +240 1.00 688 862 800 862 800 926 864 926 864 990 928 990 928 1054 992 1054 992 +1182 928 1182 928 1118 864 1118 864 1054 800 1054 800 990 736 990 736 926 688 +926 18 polygon +sce +1.00 45 464 1070 cifwire +0 1.00 688 862 800 862 800 926 864 926 864 990 928 990 928 1054 992 1054 992 +1182 928 1182 928 1118 864 1118 864 1054 800 1054 800 990 736 990 736 926 688 +926 18 polygon +1 1.00 720 894 768 894 768 958 832 958 832 1022 896 1022 896 1086 960 1086 960 +1150 9 polygon +1.00 0 960 1150 dot +1.00 0 720 894 dot +1 1.00 192 302 320 302 576 430 576 558 448 686 256 654 192 590 192 302 +8 polygon +0.490 0.651 0.980 scb +241 1.00 800 302 864 302 864 334 800 302 4 polygon +240 1.00 672 590 704 622 672 622 3 polygon +240 1.00 864 678 928 686 864 686 3 polygon +sce +1 1.00 672 302 864 302 864 366 928 366 928 430 1056 430 1056 558 992 558 992 +622 928 622 928 686 864 686 864 622 672 622 672 302 15 polygon +(CIF Wire) {/Helvetica 1.000 cf} 2 21 0 320 782 label +(Resulting Magic Shape) {/Helvetica 1.000 cf} 2 21 0 864 782 label +(CIF Polygon) {/Helvetica 1.000 cf} 2 21 0 352 206 label +(Resulting Magic Shape) {/Helvetica 1.000 cf} 2 21 0 864 206 label +pgsave restore showpage + +XCIRCsave restore +%%EndDocument + @endspecial 146 4512 a(The)29 b(shape)g(of)g(the)f(Magic)h(stairstep)f +(depends)g(on)g(the)h(order)g(in)f(which)h(v)o(ertices)f(appear)h(in)g +(the)f(CIF)i(or)0 4632 y(Calma)36 b(\002le.)62 b(The)36 +b(stairstep)e(is)h(made)h(by)f(\002rst)g(incrementing)f(or)i +(decrementing)f(the)g(x-coordinate,)i(then)0 4753 y(incrementing)d(or)g +(decrementing)h(the)f(y-coordinate,)j(then)d(x,)j(then)e(y)-6 +b(,)36 b(and)f(so)g(on.)60 b(F)o(or)35 b(e)o(xample,)h(in)e(the)0 +4873 y(\002gure)j(abo)o(v)o(e,)i(the)e(polygon)f(w)o(as)h(speci\002ed)g +(in)f(counter)n(-clockwise)h(order;)43 b(if)37 b(it)f(had)h(been)g +(speci\002ed)g(in)0 4993 y(clockwise)24 b(order)h(the)g(result)f(w)o +(ould)g(ha)n(v)o(e)h(been)g(slightly)e(dif)n(ferent.)146 +5159 y(An)31 b(additional)f(approximation)f(occurs)j(for)f(wires.)50 +b(The)31 b(CIF)h(wire)g(\002gure)f(assumes)g(that)f(round)h(caps)0 +5280 y(will)f(be)h(generated)g(at)g(each)g(end)g(of)f(the)h(wire.)48 +b(In)31 b(Magic,)h(square)f(caps)g(are)g(generated)g(instead.)48 +b(The)31 b(top)0 5400 y(e)o(xample)24 b(of)h(the)f(\002gure)i(abo)o(v)o +(e)e(illustrates)f(this)h(approximation.)1875 5649 y(\2264\226)p +eop +%%Page: 5 5 +5 4 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#9:)30 b(F)o(ormat)24 +b(Con)l(v)o(ersion)g(for)h(CIF)h(and)f(Calma)781 b(September)25 +b(26,)g(2001)0 99 y Fe(5)143 b(Other)35 b(Pr)m(oblems)f(with)g(Reading) +g(and)i(Writing)f(CIF)0 322 y Fc(Y)-11 b(ou)38 b(may)h(ha)n(v)o(e)f +(noticed)g(that)h(when)f(you)h(wrote)f(out)g(CIF)i(for)f +Fa(tut9a)h Fc(and)e(read)i(it)e(back)h(in)f(again,)k(you)0 +443 y(didn')n(t)26 b(get)h(back)g(quite)f(what)g(you)g(started)h(with.) +35 b(Although)26 b(the)g(dif)n(ferences)h(shouldn')n(t)e(cause)j(an)o +(y)e(serious)0 563 y(problems,)c(this)f(section)g(describes)h(what)g +(the)o(y)g(are)h(so)f(you')o(ll)f(kno)n(w)g(what)h(to)g(e)o(xpect.)29 +b(There)23 b(are)g(three)f(areas)0 683 y(where)f(there)f(may)h(be)f +(discrepancies:)28 b(labels,)21 b(arrays,)g(and)g(contacts.)29 +b(These)20 b(are)h(illustrated)e(in)h Fa(tut9b)p Fc(.)30 +b(Load)0 804 y(this)25 b(cell,)g(then)h(generate)g(CIF)-8 +b(,)27 b(then)e(read)h(the)g(CIF)g(back)g(in)f(again.)33 +b(When)26 b(the)f(CIF)i(is)e(read)h(in,)g(you')o(ll)e(get)i(a)0 +924 y(couple)c(of)h(w)o(arning)f(messages)g(because)h(Magic)f(w)o(on')n +(t)g(allo)n(w)g(the)g(CIF)i(to)e(o)o(v)o(erwrite)g(e)o(xisting)e +(cells:)29 b(it)22 b(uses)0 1045 y(ne)n(w)h(numbered)h(cells)f(instead) +g(\(this)g(is)g(why)g(you)g(should)g(normally)g(read)h(CIF)h(with)e(a)h +(\223clean)g(slate\224;)g(in)f(this)0 1165 y(case)34 +b(it')-5 b(s)32 b(con)l(v)o(enient)g(to)h(ha)n(v)o(e)g(both)f(the)h +(original)g(and)g(reconstructed)g(infromation)f(present)h(at)g(the)g +(same)0 1285 y(time;)d(just)e(ignore)h(the)g(w)o(arnings\).)43 +b(The)29 b(information)f(from)h(the)g(CIF)h(cell)f(appears)g(as)h(a)f +(subcell)f(named)h Fa(1)0 1406 y Fc(right)e(on)g(top)g(of)g(the)h(old)e +(contents)h(of)g Fa(tut9b)p Fc(;)j(select)d Fa(1)p Fc(,)h(mo)o(v)o(e)e +(it)h(belo)n(w)g Fa(tut9b)p Fc(,)i(and)e(e)o(xpand)g(it)g(so)g(you)g +(can)0 1526 y(compare)e(its)f(contents)g(to)g Fa(tut9b)p +Fc(.)146 1647 y(The)c(\002rst)f(problem)g(area)i(is)e(that)g(CIF)h +(normally)f(allo)n(ws)f(only)g(point)h(labels.)28 b(By)20 +b(def)o(ault,)g(where)g(you)f(ha)n(v)o(e)0 1767 y(line)28 +b(or)h(box)f(labels)g(in)g(Magic,)h(CIF)h(labels)e(are)h(generated)g +(at)g(the)f(center)h(of)g(the)f(Magic)g(labels.)42 b(The)28 +b(label)0 1887 y Fa(in)d Fc(in)f Fa(tut9y)i Fc(is)e(an)h(e)o(xample)f +(of)h(a)g(line)f(label)h(that)f(gets)h(smashed)f(in)g(the)h(CIF)h +(processing.)k(The)24 b(command)900 2103 y Fa(:cif)h(ar)n(ealabels)g(y) +o(es)146 2319 y Fc(sets)36 b(a)g(switch)f(telling)g(Magic)h(to)f(use)h +(an)h(e)o(xtension)d(to)i(cif)g(to)f(output)g(area-labels.)65 +b(This)35 b(is)h(not)f(the)0 2440 y(def)o(ault)25 b(since)f(man)o(y)g +(programs)g(that)h(tak)o(e)f(CIF)i(as)f(input)f(do)g(not)h(understand)f +(this)g(e)o(xtension.)146 2560 y(If)g(you)f(are)h(reading)f(a)g(CIF)i +(\002le)e(created)h(by)f(a)h(tool)e(other)h(than)g(Magic,)g(there)g(is) +g(an)g(additional)f(problems)0 2681 y(with)h(labels.)30 +b(The)23 b(CIF)i(label)f(construct)f(\(\223)p Fa(94)g +Fd(label)h(x)g(y)g(layer)p Fc(\224\))f(has)h(an)g(optional)e +Fd(layer)i Fc(\002eld)g(that)f(indicates)0 2801 y(the)i(layer)f(to)h +(which)f(a)h(label)f(is)h(attached.)30 b(If)25 b(reading)g(a)g(CIF)h +(\002le)f(generated)g(by)f(Magic,)g(this)g(\002eld)h(is)f(al)o(w)o(ays) +0 2921 y(present)j(and)h(so)f(a)h(label')-5 b(s)27 b(layer)g(is)g +(unambiguous.)37 b(Ho)n(we)n(v)o(er)l(,)27 b(if)h(the)f(\002eld)h(is)f +(absent,)g(Magic)h(must)e(decide)0 3042 y(which)g(layer)g(to)g(use.)35 +b(It)27 b(does)f(this)f(by)h(looking)f(to)h(see)h(what)f(Magic)g +(layers)g(lie)g(beneath)g(the)g(label)g(after)h(the)0 +3162 y(CIF)h(has)e(been)h(read)g(in.)35 b(When)27 b(there)g(are)g(se)n +(v)o(eral)f(layers,)g(it)g(chooses)g(the)h(one)f(appearing)h(LA)-11 +b(TEST)26 b(in)g(the)0 3283 y Fa(types)i Fc(section)e(of)h(the)g +(technology)f(\002le.)39 b(Usually)-6 b(,)26 b(it')-5 +b(s)26 b(possible)g(to)h(ensure)g(that)g(the)g(right)f(layer)i(is)e +(used)h(by)0 3403 y(placing)d(signal)f(layers)h(\(such)g(as)g(metal,)g +(dif)n(fusion,)f(and)h(poly\))f(later)i(in)e(the)h(types)g(section)f +(than)h(layers)g(such)0 3523 y(as)k(pwell)f(or)h(nplus.)38 +b(Ho)n(we)n(v)o(er)l(,)27 b(sometimes)f(Magic)i(will)e(still)h(pick)g +(the)h(wrong)f(layer)l(,)i(and)e(it)g(will)g(be)h(up)f(to)0 +3644 y(you)d(to)h(mo)o(v)o(e)e(the)i(label)f(to)h(the)f(right)g(layer)h +(yourself.)146 3764 y(The)20 b(second)f(problem)g(is)g(with)g(arrays.) +30 b(CIF)20 b(has)g(no)f(standard)g(array)i(construct,)f(so)f(when)g +(Magic)h(outputs)0 3884 y(arrays)34 b(it)f(does)h(it)f(as)h(a)g +(collection)f(of)g(cell)h(instances.)57 b(When)34 b(the)f(CIF)i(\002le) +f(is)f(read)i(back)f(in,)h(each)f(array)0 4005 y(element)d(comes)h +(back)g(as)f(a)i(separate)f(subcell.)51 b(The)32 b(array)g(of)g +Fa(tut9y)g Fc(cells)g(is)f(an)h(e)o(xample)f(of)h(this.)50 +b(Most)0 4125 y(designs)26 b(only)h(ha)n(v)o(e)g(a)h(fe)n(w)f(arrays)h +(that)f(are)h(lar)n(ge)g(enough)f(to)g(matter;)g(where)h(this)f(is)g +(the)g(case,)h(you)f(should)0 4246 y(go)d(back)g(after)h(reading)f(the) +g(CIF)i(and)e(replace)h(the)f(multiple)e(instances)i(with)f(a)i(single) +e(array)-6 b(.)31 b(Calma)24 b(format)0 4366 y(does)h(ha)n(v)o(e)f(an)h +(array)h(construct,)e(so)g(it)g(doesn')n(t)h(ha)n(v)o(e)f(this)g +(problem.)146 4486 y(The)i(third)e(discrepanc)o(y)h(is)g(that)g(where)h +(there)f(are)h(lar)n(ge)g(contact)f(areas,)h(when)f(CIF)i(is)e(read)g +(and)h(written)0 4607 y(the)h(area)h(of)f(the)g(contact)g(may)f(be)i +(reduced)f(slightly)-6 b(.)35 b(This)26 b(happened)h(to)g(the)g(lar)n +(ge)g(poly)g(contact)f(in)h Fa(tut9b)p Fc(.)0 4727 y(The)c(shrink)f +(doesn')n(t)h(reduce)g(the)g(ef)n(fecti)n(v)o(e)f(area)i(of)g(the)e +(contact;)i(it)e(just)g(reduces)h(the)g(area)h(dra)o(wn)f(in)g(Magic.)0 +4847 y(T)-8 b(o)25 b(see)g(what')-5 b(s)24 b(happening)g(here,)h(place) +g(the)g(box)f(around)h Fa(tut9b)h Fc(and)e Fa(1)p Fc(,)h(e)o(xpand)f(e) +n(v)o(erything,)f(then)h(type)900 5064 y Fa(:cif)h(see)g(CCP)146 +5280 y Fc(This)d(causes)h(feedback)h(to)e(be)h(displayed)e(sho)n(wing)g +(CIF)j(layer)f(\223CCP\224)i(\(contact)e(cut)f(to)h(poly\).)29 +b(Y)-11 b(ou)22 b(may)0 5400 y(ha)n(v)o(e)j(to)f(zoom)h(in)f(a)i(bit)e +(to)h(distinguish)d(the)j(indi)n(vidual)e(via)i(holes.)30 +b(Magic)25 b(generates)g(lots)f(of)h(small)f(contact)1875 +5649 y(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Fc(September)25 b(26,)f(2001)781 b(Magic)24 +b(T)l(utorial)g(#9:)30 b(F)o(ormat)24 b(Con)l(v)o(ersion)g(for)h(CIF)h +(and)f(Calma)0 68 y(vias)f(o)o(v)o(er)f(the)i(area)g(of)f(the)g +(contact,)h(and)f(if)g(contacts)g(aren')n(t)h(e)o(xact)f(multiples)e +(of)j(the)f(hole)g(size)g(and)h(spacing)0 188 y(then)c(e)o(xtra)h +(space)g(is)f(left)h(around)g(the)f(edges.)30 b(When)22 +b(the)f(CIF)i(is)f(read)g(back)g(in,)g(this)f(e)o(xtra)g(space)h(isn')n +(t)f(turned)0 309 y(back)31 b(into)e(contact.)47 b(The)31 +b(circuit)f(that)g(is)g(read)g(in)g(is)g(functionally)f(identical)h(to) +g(the)g(original)g(circuit,)h(e)n(v)o(en)0 429 y(though)24 +b(the)g(Magic)h(contact)f(appears)i(slightly)c(smaller)-5 +b(.)146 549 y(There)24 b(is)f(an)g(additional)f(problem)g(with)h +(generating)f(CIF)j(ha)n(ving)d(to)h(do)g(with)f(the)h(cell)h +(hierarchy)-6 b(.)29 b(When)0 670 y(Magic)h(generates)h(CIF)-8 +b(,)32 b(it)e(performs)g(geometric)g(operations)g(such)h(as)f(\223gro)n +(w\224)h(and)f(\223shrink\224on)g(the)h(mask)0 790 y(layers.)63 +b(Some)36 b(of)g(these)f(operations)g(are)h(not)f(guaranteed)h(to)g(w)o +(ork)f(perfectly)h(on)f(hierarchical)h(designs.)0 911 +y(Magic)20 b(detects)h(when)g(there)g(are)h(problems)d(and)i(creates)h +(feedback)f(areas)h(to)e(mark)h(the)g(trouble)f(spots.)28 +b(When)0 1031 y(you)h(write)g(CIF)-8 b(,)30 b(Magic)f(will)f(w)o(arn)i +(you)e(that)h(there)h(were)f(troubles.)43 b(These)30 +b(should)e(almost)g(ne)n(v)o(er)g(happen)0 1151 y(if)e(you)f(generate)h +(CIF)h(from)f(designs)f(that)g(don')n(t)g(ha)n(v)o(e)h(an)o(y)f +(design-rule)g(errors.)34 b(If)27 b(the)o(y)e(do)g(occur)l(,)h(you)g +(can)0 1272 y(get)f(around)f(them)g(by)h(writing)f(cif)h(with)f(the)g +(follo)n(wing)f(command)900 1500 y Fa(:cif)i(\003at)g +Fd(\002leName)146 1728 y Fc(This)31 b(command)g(creates)h(an)g +(internal)f(v)o(ersion)f(of)i(the)f(design)g(with)g(hierarchy)g(remo)o +(v)o(ed,)h(before)h(out-)0 1849 y(puting)22 b(CIF)i(as)g(in)f +Fa(cif)g(write)p Fc(.)30 b(An)24 b(alternati)n(v)o(e)d(approach)j(that) +f(does)g(not)f(require)i(\003attening)e(is)h(to)g(modify)f(the)0 +1969 y(technology)28 b(\002le)h(in)g(use.)43 b(Read)30 +b(\223Magic)f(Maintainers)f(Manual)g(#2:)39 b(The)29 +b(T)-7 b(echnology)28 b(File\224,)i(if)f(you)f(w)o(ant)0 +2090 y(to)c(try)h(this)f(approach.)1875 5649 y(\2266\226)p +eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tutscm1.ps b/doc/psfiles/tutscm1.ps new file mode 100644 index 00000000..1395f953 --- /dev/null +++ b/doc/psfiles/tutscm1.ps @@ -0,0 +1,878 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tutscm1.dvi +%%Pages: 9 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tutscm1.dvi -o tutscm1.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +%%BeginProcSet: special.pro +TeXDict begin /SDict 200 dict N SDict begin /@SpecialDefaults{/hs 612 N +/vs 792 N /ho 0 N /vo 0 N /hsc 1 N /vsc 1 N /ang 0 N /CLIP 0 N /rwiSeen +false N /rhiSeen false N /letter{}N /note{}N /a4{}N /legal{}N}B +/@scaleunit 100 N /@hscale{@scaleunit div /hsc X}B /@vscale{@scaleunit +div /vsc X}B /@hsize{/hs X /CLIP 1 N}B /@vsize{/vs X /CLIP 1 N}B /@clip{ +/CLIP 2 N}B /@hoffset{/ho X}B /@voffset{/vo X}B /@angle{/ang X}B /@rwi{ +10 div /rwi X /rwiSeen true N}B /@rhi{10 div /rhi X /rhiSeen true N}B +/@llx{/llx X}B /@lly{/lly X}B /@urx{/urx X}B /@ury{/ury X}B /magscale +true def end /@MacSetUp{userdict /md known{userdict /md get type +/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup +length 20 add dict copy def}if end md begin /letter{}N /note{}N /legal{} +N /od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath +clippath mark{transform{itransform moveto}}{transform{itransform lineto} +}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{ +itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{ +closepath}}pathforall newpath counttomark array astore /gc xdf pop ct 39 +0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}N +/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 +scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get +ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip +not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 +TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{noflips{TR +pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 +-1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg +TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg +sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr +0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add +2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N /cp +{pop pop showpage pm restore}N end}if}if}N /normalscale{Resolution 72 +div VResolution 72 div neg scale magscale{DVImag dup scale}if 0 setgray} +N /psfts{S 65781.76 div N}N /startTexFig{/psf$SavedState save N userdict +maxlength dict begin /magscale true def normalscale currentpoint TR +/psf$ury psfts /psf$urx psfts /psf$lly psfts /psf$llx psfts /psf$y psfts +/psf$x psfts currentpoint /psf$cy X /psf$cx X /psf$sx psf$x psf$urx +psf$llx sub div N /psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy +scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR +/showpage{}N /erasepage{}N /copypage{}N /p 3 def @MacSetUp}N /doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N /endTexFig{end psf$SavedState restore}N /@beginspecial{SDict +begin /SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count /ocount X /dcount countdictstack N}N /@setspecial +{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if /showpage{}N /erasepage{}N /copypage{}N newpath +}N /@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{ +end}repeat grestore SpecialSave restore end}N /@defspecial{SDict begin} +N /@fedspecial{end}B /li{lineto}B /rl{rlineto}B /rc{rcurveto}B /np{ +/SaveX currentpoint /SaveY X N 1 setlinecap newpath}N /st{stroke SaveX +SaveY moveto}N /fil{fill SaveX SaveY moveto}N /ellipse{/endangle X +/startangle X /yrad X /xrad X /savematrix matrix currentmatrix N TR xrad +yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tutscm1.dvi) +@start /Fa 1 1 df<7FFFFFFFFFFFFFE0FFFFFFFFFFFFFFF0FFFFFFFFFFFFFFF07FFFFF +FFFFFFFFE03C04789A4D>0 D E /Fb 1 63 df<7000000000000000FC00000000000000 +FF000000000000007FC00000000000001FF000000000000007FC00000000000001FF0000 +00000000007FC00000000000001FF000000000000007FE00000000000001FF8000000000 +00007FE00000000000001FF800000000000003FE00000000000000FF800000000000003F +E00000000000000FF800000000000003FF00000000000000FFC00000000000003FF00000 +000000000FFC00000000000001FF000000000000007FC00000000000001FF00000000000 +0007FC00000000000001FF000000000000007FC00000000000001FE00000000000001FE0 +0000000000007FC0000000000001FF00000000000007FC0000000000001FF00000000000 +007FC0000000000001FF0000000000000FFC0000000000003FF0000000000000FFC00000 +00000003FF0000000000000FF80000000000003FE0000000000000FF80000000000003FE +0000000000001FF80000000000007FE0000000000001FF80000000000007FE0000000000 +001FF00000000000007FC0000000000001FF00000000000007FC0000000000001FF00000 +000000007FC0000000000000FF00000000000000FC000000000000007000000000000000 +3B3878B44C>62 D E /Fc 1 62 df<7FFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFF80FFFFFF +FFFFFFFFFF807FFFFFFFFFFFFFFF00000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000007FFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFF80FFFFFF +FFFFFFFFFF807FFFFFFFFFFFFFFF0041187BA44C>61 D E /Fd 133[44 +50 50 72 50 55 33 39 44 55 55 50 55 83 28 55 33 28 55 +50 33 44 55 44 55 50 33[50 4[33 1[50 2[50 50 50 1[50 +50 28 25 33 1[57 50 33 33 33 3[50 1[33 30[55 2[{ + TeXBase1Encoding ReEncodeFont }45 100.000003 /Times-Bold +rf /Fe 134[60 1[86 1[66 40 47 53 1[66 60 66 100 33 2[33 +66 60 40 53 66 53 66 60 12[80 66 5[113 80 2[47 5[86 80 +86 6[40 60 60 60 60 60 60 60 60 60 60 1[30 40 42[66 2[{ + TeXBase1Encoding ReEncodeFont }42 119.999948 /Times-Bold +rf /Ff 104[100 50 1[44 44 24[44 50 50 72 50 50 28 39 +33 50 50 50 50 78 28 50 28 28 50 50 33 44 50 44 50 44 +3[33 1[33 1[72 1[94 2[61 55 66 1[55 72 72 89 2[39 33 +72 72 55 61 72 66 1[72 1[44 3[28 28 50 50 50 50 50 50 +50 50 50 50 28 25 33 25 56 50 33 33 33 3[50 1[33 29[55 +55 2[{ TeXBase1Encoding ReEncodeFont }76 100.000003 /Times-Roman +rf /Fg 134[44 44 1[44 50 28 39 39 50 50 50 50 72 28 1[28 +28 50 50 28 44 50 44 50 50 13[50 61 1[61 1[66 83 55 2[33 +5[66 1[61 3[67 6[50 1[50 1[50 50 2[25 33 3[33 33 4[50 +35[{ TeXBase1Encoding ReEncodeFont }42 100.000003 /Times-Italic +rf /Fh 134[72 1[104 1[80 48 56 64 1[80 72 80 120 40 80 +1[40 80 72 48 64 80 64 80 72 12[96 80 104 4[135 3[56 +6[96 7[48 6[72 72 72 3[48 9[72 35[{ TeXBase1Encoding ReEncodeFont }33 +143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 121 101 a Fh(Magic)36 b(T)-13 b(utorial)34 b(#S-1:)43 +b(The)35 b(scheme)f(command-line)e(inter)o(pr)m(eter)1655 +521 y Fg(Rajit)24 b(Manohar)1282 941 y Ff(Department)g(of)h(Computer)f +(Science)1271 1062 y(California)h(Institute)f(of)h(T)-7 +b(echnology)1534 1182 y(P)o(asadena,)25 b(CA)h(91125)1053 +1453 y(This)e(tutorial)g(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.)0 +1976 y Fe(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 +2176 y Ff(Read)c(reference)g([1])0 2376 y Fe(Commands)j(intr)n(oduced)j +(in)f(this)f(tutorial:)300 2576 y Ff(:scm-echo-result,)24 +b(:e)n(v)n(al,)f(lots)h(of)h(scheme)g(functions)0 2776 +y Fe(Macr)n(os)k(intr)n(oduced)i(in)g(this)f(tutorial:)300 +3000 y Fg(\(None\))0 3892 y Fh(1)143 b(Intr)m(oduction)0 +4115 y Ff(Magic')-5 b(s)18 b(original)g(command-line)g(interpreter)h +(has)g(some)f(limitations.)26 b(Some)19 b(of)h(these)e(include)h(the)g +(absence)0 4236 y(of)i(de\002nitions)g(with)f(ar)n(guments,)i(block)f +(structure,)g(the)g(ability)g(to)g(de\002ne)h(comple)o(x)e(functions.) +28 b(W)-8 b(e)22 b(describe)0 4356 y(an)j(e)o(xtension)e(which)h(is)g +(almost)f(completely)h(backw)o(ard)h(compatible)e(with)h(the)g(e)o +(xisting)f(magic)h(command-)0 4476 y(line)g(syntax,)g(b)n(ut)h(permits) +e(the)i(use)g(of)g(Scheme)g(on)f(the)h(command-line.)0 +4815 y Fh(2)143 b(Backward)34 b(compatibility)0 5039 +y Ff(T)-8 b(o)19 b(permit)f(e)o(xisting)f(magic)i(source)g(\002les)g +(to)g(w)o(ork)g(within)e(the)i(scheme)g(interpreter)l(,)h(we)g(ha)n(v)o +(e)e(had)h(to)g(sacri\002ce)0 5159 y(one)29 b(feature)h(of)f(the)g +(magic)g(command-line)f(syntax.)43 b(Single)29 b(quotes)f(can)i(only)e +(be)h(used)g(to)g(quote)g(a)g(single)0 5280 y(character)-5 +b(.)69 b(The)38 b(reason)f(for)h(this)f(limitation)e(is)i(that)g +Fg(unmatc)o(hed)f Ff(quotes)h(are)h(used)f(by)g(scheme)h(to)f(stop)0 +5400 y(e)n(v)n(aluation)23 b(of)i(the)g(ne)o(xt)e(input)h(symbol.)1875 +5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Ff(September)25 b(26,)f(2001)713 b(Magic)25 +b(T)l(utorial)e(#S-1:)31 b(The)25 b(scheme)g(command-line)e +(interpreter)146 68 y(P)o(arentheses)g(are)h(used)f(by)g(the)g(scheme)g +(interpreter)-5 b(.)30 b(If)23 b(you)g(use)g(parentheses)g(outside)f +(single)h(or)g(double)0 188 y(quotes)i(in)g(your)g(magic)g(source)h +(\002les,)g(you)f(might)f(\002nd)i(that)f(the)g(source)h(\002les)g +(don')n(t)f(w)o(ork)g(properly)-6 b(.)32 b(T)-8 b(o)26 +b(cir)n(-)0 309 y(cumv)o(ent)21 b(this)f(problem,)i(simply)e(put)h +(your)h(parentheses)f(in)h(double)f(quotes.)29 b(Y)-11 +b(ou)21 b(can)i(also)e(use)h(backslashes)0 429 y(to)i(quote)h +(parentheses)f(as)h(in:)900 664 y Fd(:macr)n(o)1227 664 +y +/bksp 2 string def bksp 0 92 put bksp show + 1227 664 a 40 w Fd(\()1325 664 y +(") show + 1325 664 a 60 w Fd(echo)h(hello)1809 +664 y +(") show + 1809 664 a 146 898 a Ff(Another)h(thing)f(you)h(may)f(notice)h +(is)g(that)f(\003oating-point)g(numbers)g(are)i(parsed)f(as)g(such,)g +(and)g(therefore)0 1019 y(a)e(command)f(such)g(as)900 +1253 y Fd(:echo)i(5.3)146 1488 y Ff(w)o(ould)e(display)g(the)h(string)f +Fd(5.300000)p Ff(.)29 b(If)c(you)g(really)f(w)o(ant)h(the)f(string)g +Fd(5.3)p Ff(,)h(use:)900 1723 y Fd(:echo)1152 1723 y +(") show + +1152 1723 a 60 w Fd(5.3)1337 1723 y +(") show + 1337 1723 a 146 1957 +a Ff(If)g(this)f(dif)n(ference)h(is)f(undesirable,)g(the)h(scheme)f +(interpreter)h(can)g(be)g(turned)f(of)n(f)h(at)f(compile-time.)29 +b(T)-8 b(alk)0 2077 y(to)23 b(your)h(local)g(magic)f(maintainer)g(if)h +(you)f(w)o(ant)h(this)f(done.)30 b(W)-8 b(e)24 b(feel)g(that)g(the)f +(minor)g(trouble)h(tak)o(en)f(in)h(mod-)0 2197 y(ifying)k(e)o(xisting)f +(magic)i(source)g(\002les)g(will)f(be)h(outweighed)f(by)h(the)g(adv)n +(antage)g(of)g(using)f(a)h(more)g(po)n(werful)0 2318 +y(layout)24 b(language.)0 2663 y Fh(3)143 b(The)35 b(scheme)f(inter)o +(pr)m(eter)0 2888 y Ff(The)25 b(interpreter)f(supports)g(a)h(subset)f +(of)h(the)f(scheme)h(language.)30 b(The)25 b(features)g(of)g(scheme)f +(that)h(are)g(missing)0 3008 y(include)h(character)j(types,)d(v)o +(ector)h(types,)g(\002le)g(input/output,)e(comple)o(x)h(numbers,)g(the) +h(distinction)e(between)0 3129 y(e)o(xact)g(and)f(ine)o(xact)h +(arithmetic,)e(quasi-quotations,)g(and)i(continuations.)0 +3429 y Fe(3.1)119 b(Command-line)31 b(interaction)0 3618 +y Ff(When)e(interacting)e(with)h(the)g(command-line)g(of)g(magic,)h +(the)f(interpreter)h(implicitly)d(parenthesizes)j(its)e(in-)0 +3739 y(put.)j(F)o(or)25 b(e)o(xample,)f(the)g(command)900 +3974 y Fd(:paint)i(poly)146 4208 y Ff(w)o(ould)e(be)h(interpreted)g(as) +g(the)f(scheme)h(e)o(xpression)900 4443 y Fd(\(paint)h(poly\))146 +4677 y Ff(This)18 b(has)h(e)o(xactly)f(the)h(same)g(ef)n(fect)g(as)g +(the)f(original)g(e)o(xpression,)h(because)g(all)g(e)o(xisting)e(magic) +h(command-)0 4797 y(line)29 b(functions)f(are)i(also)e(scheme)h +(functions.)43 b(Since)29 b(the)g(v)n(alid)f(magic)h(commands)f(v)n +(ary)h(from)g(windo)n(w)e(to)0 4918 y(windo)n(w)-6 b(,)20 +b(the)h(return)f(v)n(alue)h(of)g(the)g(function)f(is)g(a)h(boolean)g +(that)f(indicates)h(whether)g(the)f(command)g(w)o(as)h(v)n(alid)0 +5038 y(for)k(the)g(current)g(windo)n(w)-6 b(.)146 5159 +y(The)26 b(boolean)f Fd(scm-echo-r)n(esult)i Ff(controls)e(whether)g +(or)h(not)e(the)i(result)f(of)g(the)h(e)n(v)n(aluation)d(is)i +(displayed.)0 5280 y(If)k(the)f(v)n(ariable)g(does)h(not)f(e)o(xist,)g +(or)g(the)h(v)n(ariable)f(is)g(not)g(boolean-v)n(alued,)g(the)g(result) +g(of)h(e)n(v)n(aluation)e(is)h(not)0 5400 y(echoed.)j(Since)25 +b(the)g(input)f(is)g(implicitly)e(parenthesized,)j(typing)e(in)1875 +5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Ff(Magic)24 b(T)l(utorial)g(#S-1:)31 +b(The)24 b(scheme)h(command-line)f(interpreter)713 b(September)25 +b(26,)g(2001)900 84 y Fd(:scm-echo-r)n(esult)146 379 +y Ff(w)o(ould)f(not)h(display)e(the)i(v)n(alue)f(of)h(the)g(v)n +(ariable,)f(since)g(it)h(w)o(ould)f(be)h(e)n(v)n(aluated)e(as:)900 +684 y Fd(\(scm-echo-r)n(esult\))146 979 y Ff(T)-8 b(o)25 +b(display)f(the)g(v)n(alue)h(of)f(a)i(v)n(ariable,)e(use)g(the)h(b)n +(uilt-in)e(procedure)j Fd(e)o(v)o(al)e Ff(as)h(follo)n(ws:)900 +1284 y Fd(:e)o(v)o(al)f(scm-echo-r)n(esult)146 1579 y +Ff(This)g(w)o(ould)g(result)h(in)f(the)h(e)o(xpression:)900 +1884 y Fd(\(e)o(v)o(al)f(scm-echo-r)n(esult\))146 2179 +y Ff(which)e(w)o(ould)g(ha)n(v)o(e)g(the)g(desired)g(ef)n(fect)h +(\(note)f(that)f(for)i(this)e(to)h(actually)g(display)f(an)o(ything,)g +(the)h(v)n(alue)g(of)0 2299 y Fd(scm-echo-r)n(esult)30 +b Ff(must)d(be)h Fd(#t)p Ff(,)i(and)e(so)g(e)o(xamining)e(its)i(v)n +(alue)f(is)h(really)g(a)h(futile)e(e)o(x)o(ercise\227which)g(is)h(why)0 +2420 y(it)c(is)h(an)g(e)o(xample,)e(of)i(course!\).)0 +2776 y Fe(3.2)119 b(T)-9 b(ypes)30 b(of)f(ar)o(guments)0 +2983 y Ff(Since)e(scheme)g(e)o(xpressions)f(are)i(typed,)f(we)g(may)g +(need)g(to)f(e)o(xamine)h(the)f(type)h(of)g(a)h(particular)e(e)o +(xpression.)0 3104 y(The)f(follo)n(wing)e(functions)g(return)i +(booleans,)f(and)h(can)g(be)g(used)g(to)f(determine)g(the)h(type)f(of)h +(an)g(object.)146 3234 y Fd(#t)e Ff(and)g Fd(#f)g Ff(are)g(constants)f +(representing)g(the)g(booleans)g(true)h(and)g(f)o(alse.)30 +b(A)23 b(standard)f(scheme)h(con)l(v)o(ention)0 3354 +y(is)35 b(to)h(name)g(functions)e(that)i(return)g(booleans)f(with)g(a)h +(name)g(ending)f(with)g(\223?\224.)65 b(The)36 b(b)n(uilt-in)e +(functions)0 3474 y(conform)24 b(to)h(this)f(con)l(v)o(ention.)146 +3604 y(The)h(e)o(xpression)f Fg(e)n(xpr)h Ff(is)f(e)n(v)n(aluated,)g +(and)g(the)h(type)f(of)h(the)g(result)f(of)h(e)n(v)n(aluation)e(is)h +(check)o(ed.)p 996 3822 1908 4 v 994 3942 4 121 v 1046 +3906 a Fd(\(boolean?)31 b Fg(e)n(xpr)p Fd(\))p 1850 3942 +V 201 w(#t)25 b Ff(if)g Fg(e)n(xpr)g Ff(is)f(a)i(boolean)p +2902 3942 V 996 3946 1908 4 v 994 4066 4 121 v 1046 4030 +a Fd(\(symbol?)k Fg(e)n(xpr)p Fd(\))p 1850 4066 V 229 +w(#t)25 b Ff(if)g Fg(e)n(xpr)g Ff(is)f(a)i(symbol)p 2902 +4066 V 996 4069 1908 4 v 994 4190 4 121 v 1046 4154 a +Fd(\(list?)k Fg(e)n(xpr)p Fd(\))p 1850 4190 V 406 w(#t)25 +b Ff(if)g Fg(e)n(xpr)g Ff(is)f(a)i(list)p 2902 4190 V +996 4193 1908 4 v 994 4313 4 121 v 1046 4277 a Fd(\(pair?)31 +b Fg(e)n(xpr)p Fd(\))p 1850 4313 V 356 w(#t)25 b Ff(if)g +Fg(e)n(xpr)g Ff(is)f(a)i(pair)p 2902 4313 V 996 4317 +1908 4 v 994 4437 4 121 v 1046 4401 a Fd(\(number?)33 +b Fg(e)n(xpr)p Fd(\))p 1850 4437 V 195 w(#t)25 b Ff(if)g +Fg(e)n(xpr)g Ff(is)f(a)i(number)p 2902 4437 V 996 4440 +1908 4 v 994 4561 4 121 v 1046 4525 a Fd(\(string?)31 +b Fg(e)n(xpr)p Fd(\))p 1850 4561 V 284 w(#t)25 b Ff(if)g +Fg(e)n(xpr)g Ff(is)f(a)i(string)p 2902 4561 V 996 4564 +1908 4 v 994 4684 4 121 v 1046 4648 a Fd(\(pr)n(ocedur)n(e?)34 +b Fg(e)n(xpr)p Fd(\))p 1850 4684 V 99 w(#t)25 b Ff(if)g +Fg(e)n(xpr)g Ff(is)f(a)i(procedure)p 2902 4684 V 996 +4688 1908 4 v 146 4939 a(F)o(or)f(e)o(xample,)900 5244 +y Fd(\(boolean?)31 b(#t\))p Fc(=)p Fb(>)25 b Fg(#t)900 +5364 y Fd(\(number?)33 b(#t\))p Fc(=)p Fb(>)24 b Fg(#f)1875 +5649 y Ff(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Ff(September)25 b(26,)f(2001)713 b(Magic)25 +b(T)l(utorial)e(#S-1:)31 b(The)25 b(scheme)g(command-line)e +(interpreter)0 82 y Fe(3.3)119 b(Lists)29 b(and)h(pairs)0 +278 y Ff(A)i(pair)g(is)g(a)g(record)h(structure)e(with)h(tw)o(o)f +(\002elds,)j(called)e(the)g(car)g(and)g(cdr)h(\002elds)f(\(for)g +(historical)f(reasons\).)0 399 y(P)o(airs)24 b(are)g(used)g(primarily)f +(to)g(represent)h(lists.)29 b(A)24 b(list)f(can)h(be)g(de\002ned)g +(recursi)n(v)o(ely)f(as)h(either)g(the)f(empty)g(list,)0 +519 y(or)31 b(a)f(pair)h(whose)f(cdr)h(\002eld)f(is)g(a)h(list.)47 +b(The)30 b(follo)n(wing)f(functions)g(are)i(used)f(to)g(e)o(xtract)g +(these)h(\002elds)f(and)g(to)0 640 y(construct)24 b(ne)n(w)h(pairs)f +(and)h(lists.)p 446 813 3009 4 v 444 933 4 121 v 496 +897 a Fd(\(car)g Fg(pair)p Fd(\))p 1203 933 V 362 w Ff(the)g(car)g +(\002eld)g(of)g Fg(pair)p 3452 933 V 446 937 3009 4 v +444 1057 4 121 v 496 1021 a Fd(\(cdr)h Fg(pair)p Fd(\))p +1203 1057 V 356 w Ff(the)f(cdr)g(\002eld)g Fg(pair)p +3452 1057 V 446 1060 3009 4 v 444 1181 4 121 v 496 1144 +a Fd(\(cons)g Fg(obj1)f(obj2)p Fd(\))p 1203 1181 V 99 +w Ff(a)h(ne)n(w)g(pair)f(whose)h(car)g(\002eld)g(is)g +Fg(obj1)f Ff(and)h(cdr)g(\002eld)g(is)f Fg(obj2)p 3452 +1181 V 446 1184 3009 4 v 444 1304 4 121 v 496 1268 a +Fd(\(list)g Fg(ar)l(g1)h(.)15 b(.)g(.)g Fd(\))p 1203 +1304 V 210 w Ff(a)25 b(ne)n(w)g(list)e(consisting)g(of)i(its)f(ar)n +(guments)p 3452 1304 V 446 1308 3009 4 v 444 1428 4 121 +v 496 1392 a Fd(\(null?)31 b Fg(list)p Fd(\))p 1203 1428 +V 322 w(#t)25 b Ff(if)g Fg(list)e Ff(is)i(the)f(empty)g(list)p +3452 1428 V 446 1431 3009 4 v 444 1552 4 121 v 496 1516 +a Fd(\(length)i Fg(list)p Fd(\))p 1203 1552 V 278 w Ff(the)f(number)f +(of)h(elements)f(in)g Fg(list)p 3452 1552 V 446 1555 +3009 4 v 146 1767 a Ff(F)o(or)h(e)o(xample,)900 2028 +y Fd(\(car)g('\(a)g(b)h(c\)\))p Fg(=)p Fb(>)f Fg(a)900 +2148 y Fd(\(cdr)h('\(a)f(b)g(c\)\))p Fg(=)p Fb(>)h Fg(\(b)f(c\))900 +2269 y Fd(\(cons)g('a)g('\(b)h(c\)\))p Fg(=)p Fb(>)f +Fg(\(a)g(b)g(c\))900 2389 y Fd(\(list)f('a)h('b)h('c\))p +Fg(=)p Fb(>)f Fg(\(a)g(b)g(c\))900 2509 y Fd(\(null?)31 +b('\(a)25 b(b\)\))p Fg(=)p Fb(>)h Fg(#f)900 2630 y Fd(\(null?)31 +b(\(\)\))p Fg(=)p Fb(>)26 b Fg(#t)146 2886 y Ff(The)f(car)h(\002eld)f +(and)g(cdr)g(\002eld)g(of)g(a)g(pair)g(can)g(be)g(set)f(using)g(the)h +(follo)n(wing)e(tw)o(o)h(functions.)p 411 3059 3079 4 +v 409 3180 4 121 v 461 3144 a Fd(\(set-car!)32 b Fg(pair)24 +b(obj)p Fd(\))p 1251 3180 V 104 w Ff(sets)h(the)f(car)i(\002eld)f(of)g +Fg(pair)f Ff(to)g Fg(obj)p Ff(.)30 b(It)25 b(returns)g(the)f(ne)n(w)h +(pair)p 3487 3180 V 411 3183 3079 4 v 409 3304 4 121 +v 461 3267 a Fd(\(set-cdr!)32 b Fg(pair)24 b(obj)p Fd(\))p +1251 3304 V 99 w Ff(sets)h(the)f(cdr)h(\002eld)g(of)g +Fg(pair)f Ff(to)h Fg(obj)p Ff(.)30 b(It)25 b(returns)f(the)h(ne)n(w)f +(pair)p 3487 3304 V 411 3307 3079 4 v 146 3519 a(These)e(tw)o(o)e +(functions)h(ha)n(v)o(e)g Fg(side-ef)n(fects)p Ff(,)g(another)g +(feature)h(that)f(distinguishes)e(scheme)i(from)g(pure)g(lisp.)0 +3640 y(Another)j(naming)g(con)l(v)o(ention)f(follo)n(wed)h(is)g(that)h +(functions)e(that)i(ha)n(v)o(e)f(side-ef)n(fects)h(end)g(in)f +(\223!\224.)146 3764 y(T)m(ry)h(the)f(follo)n(wing)f(sequence)i(in)g +(magic:)900 4025 y Fd(\(de\002ne)i(x)d('\(a)i(b\)\))p +Fg(=)p Fb(>)f Fg(\(a)g(b\))900 4145 y Fd(\(set-car!)32 +b(x)25 b('c\))p Fg(=)p Fb(>)g Fg(\(c)g(b\))900 4266 y +Fd(\(set-cdr!)32 b(x)25 b('\(q\)\))p Fg(=)p Fb(>)h Fg(\(c)g(q\))900 +4386 y Fd(\(set-cdr!)32 b(x)25 b('q\))p Fg(=)p Fb(>)h +Fg(\(c)f(.)31 b(q\))146 4763 y Ff(After)25 b(the)g(last)f(statement,)g +(the)h(v)n(alue)f(of)h(x)g(is)f(no)g(longer)h(a)g(list)f(b)n(ut)g(a)h +(pair)-5 b(.)0 5084 y Fe(3.4)119 b(Arithmetic)0 5280 +y Ff(The)26 b(interpreter)f(supports)g(both)g(\003oating-point)f(and)h +(inte)o(ger)g(arithmetic.)32 b(The)26 b(basic)f(arithmetic)g(functions) +0 5400 y(are)h(supported.)1875 5649 y(\2264\226)p eop +%%Page: 5 5 +5 4 bop 0 -180 a Ff(Magic)24 b(T)l(utorial)g(#S-1:)31 +b(The)24 b(scheme)h(command-line)f(interpreter)713 b(September)25 +b(26,)g(2001)p 1015 3 1871 4 v 1013 124 4 121 v 1065 +88 a Fd(\(+)f Fg(num1)h(num2)p Fd(\))p 1735 124 V 106 +w Ff(the)f(sum)g Fg(num1)p Ff(+)p Fg(num2)p 2884 124 +V 1015 127 1871 4 v 1013 247 4 121 v 1065 211 a Fd(\(-)h +Fg(num1)f(num2)p Fd(\))p 1735 247 V 130 w Ff(the)g(dif)n(ference)i +Fg(num1)p Ff(-)p Fg(num2)p 2884 247 V 1015 251 1871 4 +v 1013 371 4 121 v 1065 335 a Fd(\(*)e Fg(num1)h(num2)p +Fd(\))p 1735 371 V 113 w Ff(the)f(product)h Fg(num1)p +Ff(*)p Fg(num2)p 2884 371 V 1015 374 1871 4 v 1013 495 +4 121 v 1065 459 a Fd(\(/)f Fg(num1)h(num2)p Fd(\))p +1735 495 V 135 w Ff(the)f(quotient)g Fg(num1)p Ff(/)p +Fg(num2)p 2884 495 V 1015 498 1871 4 v 1013 619 4 121 +v 1065 582 a Fd(\(truncate)i Fg(num)p Fd(\))p 1735 619 +V 100 w Ff(the)e(inte)o(ger)g(part)h(of)g Fg(num)p 2884 +619 V 1015 622 1871 4 v 146 831 a Ff(The)34 b(di)n(vision)d(operator)i +(checks)h(for)f(di)n(vision)e(by)i(zero,)j(and)e(promotes)e(inte)o +(gers)g(to)h(\003oating-point)f(if)0 951 y(deemed)39 +b(necessary)-6 b(.)73 b(Floating-point)37 b(numbers)i(can)g(be)g(con)l +(v)o(erted)g(into)f(inte)o(gers)g(by)h(truncation.)72 +b(The)0 1072 y(range)25 b(of)g(a)g(number)f(can)i(be)f(check)o(ed)g +(using)f(the)g(follo)n(wing)f(predicates:)p 1108 1241 +1684 4 v 1106 1361 4 121 v 1158 1325 a Fd(\(zer)n(o?)32 +b Fg(num)p Fd(\))p 1877 1361 V 271 w(#t)25 b Ff(if)f +Fg(num)h Ff(is)f(zero)p 2790 1361 V 1108 1365 1684 4 +v 1106 1485 4 121 v 1158 1449 a Fd(\(positi)o(v)o(e?)31 +b Fg(num)p Fd(\))p 1877 1485 V 127 w(#t)25 b Ff(if)f +Fg(num)h Ff(is)f(positi)n(v)o(e)p 2790 1485 V 1108 1488 +1684 4 v 1106 1609 4 121 v 1158 1573 a Fd(\(negati)o(v)o(e?)31 +b Fg(num)p Fd(\))p 1877 1609 V 100 w(#t)25 b Ff(if)f +Fg(num)h Ff(is)f(ne)o(gati)n(v)o(e)p 2790 1609 V 1108 +1612 1684 4 v 0 1871 a Fe(3.5)119 b(Strings)0 2066 y +Ff(The)36 b(interpreter)g(supports)f(string)g(manipulation.)63 +b(String)36 b(manipulation)e(can)i(be)h(useful)e(for)i(interaction)0 +2187 y(with)24 b(the)h(user)g(as)f(well)h(as)g(constructing)e(names)i +(for)g(labels.)p 142 2356 3617 4 v 140 2476 4 121 v 192 +2440 a Fd(\(string-append)h Fg(str1)e(str2)p Fd(\))p +1317 2476 V 152 w Ff(the)h(string)f(formed)h(by)f(concatenating)g +Fg(str1)g Ff(and)h Fg(str2)p 3757 2476 V 142 2480 3617 +4 v 140 2600 4 121 v 192 2564 a Fd(\(string-length)h +Fg(str)p Fd(\))p 1317 2600 V 431 w Ff(the)f(length)f(of)h(string)f +Fg(str)p 3757 2600 V 142 2603 3617 4 v 140 2844 4 241 +v 192 2688 a Fd(\(string-compar)n(e)i Fg(str1)e(str2)p +Fd(\))p 1317 2844 V 98 w Ff(a)j(positi)n(v)o(e,)c(zero,)k(or)f(ne)o +(gati)n(v)o(e)e(number)h(depending)g(on)h(whether)1368 +2808 y Fg(str1)e Ff(is)h(le)o(xicographically)e(greater)l(,)i(equal)g +(to,)f(or)h(less)g(than)f Fg(str2)p 3757 2844 V 142 2847 +3617 4 v 140 3088 4 241 v 192 2932 a Fd(\(string-r)n(ef)i +Fg(str)e(int)p Fd(\))p 1317 3088 V 447 w Ff(the)e(numerical)f(v)n(alue) +g(of)h(the)f(character)i(stored)e(at)h(position)e Fg(int)h +Ff(in)1368 3052 y Fg(str)k Ff(\(The)g(\002rst)g(character)g(is)g(at)g +(position)e(0.\))p 3757 3088 V 142 3092 3617 4 v 140 +3212 4 121 v 192 3176 a Fd(\(string-set!)31 b Fg(str)24 +b(int1)g(int2)p Fd(\))p 1317 3212 V 182 w Ff(sets)h(character)h(in)e +(string)g Fg(str)g Ff(at)h(position)e Fg(int1)h Ff(to)g +Fg(int2)p 3757 3212 V 142 3215 3617 4 v 140 3456 4 241 +v 192 3299 a Fd(\(substring)h Fg(str)f(int1)g(int2)p +Fd(\))p 1317 3456 V 221 w Ff(returns)d(substring)e(of)h +Fg(str)g Ff(from)g(position)f Fg(int1)h Ff(\(inclusi)n(v)o(e\))e(to)i +Fg(int2)1368 3420 y Ff(\(e)o(xclusi)n(v)o(e\))p 3757 +3456 V 142 3459 3617 4 v 146 3668 a(Strings)25 b(can)g(be)g(used)f(to)h +(con)l(v)o(ert)f(to)g(and)h(from)g(v)n(arious)e(types.)p +304 3838 3292 4 v 302 3958 4 121 v 354 3922 a Fd(\(number)l(-)p +Fb(>)p Fd(string)k Fg(num)p Fd(\))p 1383 3958 V 126 w +Ff(the)d(string)g(corresponding)g(to)g(the)h(representation)f(of)h +Fg(num)p 3594 3958 V 304 3961 3292 4 v 302 4082 4 121 +v 354 4046 a Fd(\(string-)p Fb(>)p Fd(number)i Fg(str)p +Fd(\))p 1383 4082 V 188 w Ff(the)d(number)h(corresponding)e(to)i +Fg(str)p 3594 4082 V 304 4085 3292 4 v 302 4205 4 121 +v 354 4169 a Fd(\(string-)p Fb(>)p Fd(symbol)g Fg(str)p +Fd(\))p 1383 4205 V 221 w Ff(a)g(symbol)e(named)i Fg(str)p +3594 4205 V 304 4209 3292 4 v 302 4329 4 121 v 354 4293 +a Fd(\(symbol)p Fa(\000)j Fb(>)p Fd(string)d Fg(sym)p +Fd(\))p 1383 4329 V 100 w Ff(the)f(string)g(corresponding)g(to)g(the)h +(name)g(of)g Fg(sym)p 3594 4329 V 304 4333 3292 4 v 0 +4592 a Fe(3.6)119 b(Bindings)31 b(and)f(functions)0 4787 +y Ff(An)21 b(object)f(\(more)h(accurately)-6 b(,)21 b(the)g +Fg(location)f Ff(where)h(the)g(object)f(is)g(stored\))h(can)g(be)g +(bound)f(to)h(a)g(symbol)e(using)0 4907 y(the)25 b(follo)n(wing)e(tw)o +(o)h(functions:)p 132 5076 3636 4 v 130 5197 4 121 v +182 5161 a Fd(\(de\002ne)j Fg(sym)e(e)n(xpr)p Fd(\))p +931 5197 V 100 w Ff(bind)f Fg(e)n(xpr)h Ff(to)f Fg(sym)p +Ff(,)h(creating)f(a)i(ne)n(w)e(symbol)f(if)i(necessary)g(and)g(return)g +Fg(e)n(xpr)p 3766 5197 V 132 5200 3636 4 v 130 5320 4 +121 v 182 5284 a Fd(\(set!)32 b Fg(sym)24 b(e)n(xpr)p +Fd(\))p 931 5320 V 200 w Ff(bind)g Fg(e)n(xpr)h Ff(to)f(an)h(e)o +(xisting)e(symbol)g Fg(sym)i Ff(and)g(return)g Fg(e)n(xpr)p +3766 5320 V 132 5324 3636 4 v 770 5400 a Ff(\(Note:)31 +b(these)24 b(functions)g(do)h(not)f(e)n(v)n(aluate)g(their)g(\002rst)h +(ar)n(gument.\))1875 5649 y(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Ff(September)25 b(26,)f(2001)713 b(Magic)25 +b(T)l(utorial)e(#S-1:)31 b(The)25 b(scheme)g(command-line)e +(interpreter)146 69 y(The)i(dif)n(ference)g(between)g(the)g(tw)o(o)f +(is)g(that)g Fd(de\002ne)j Ff(introduces)d(a)h(ne)n(w)f(binding,)f +(whereas)j Fd(set!)31 b Ff(modi\002es)0 189 y(an)g(e)o(xisting)e +(binding.)48 b(In)31 b(both)f(cases,)j Fg(e)n(xpr)e Ff(is)f(e)n(v)n +(aluated,)i(and)f(the)f(result)h(is)f(bound)g(to)h(the)g(symbol)e +Fg(sym)p Ff(.)0 309 y(The)c(result)f(of)h(the)g(e)n(v)n(aluation)e(is)h +(also)g(returned.)900 473 y Fd(\(de\002ne)j(x)d(4\))p +Fc(=)p Fb(>)h Fg(4)146 637 y Ff(Functions)c(can)g(be)h(de\002ned)f +(using)f(lambda)h(e)o(xpressions.)28 b(T)-8 b(ypically)20 +b(a)i(function)e(is)h(bound)f(to)h(a)h(v)n(ariable.)0 +757 y(If)j(required,)g(a)g(lambda)f(e)o(xpression)g(or)h(b)n(uilt-in)e +(function)h(can)h(be)g(applied)f(to)h(a)g(list.)p 1212 +836 1476 4 v 1210 956 4 121 v 1262 920 a Fd(\(lambda)g +Fg(list)f(obj)p Fd(\))p 1997 956 V 99 w Ff(a)h(ne)n(w)g(function)p +2686 956 V 1212 960 1476 4 v 963 1042 a(\(Note:)30 b(a)25 +b(lambda)f(does)h(not)f(e)n(v)n(aluate)g(its)g(ar)n(guments.\))146 +1205 y Fg(list)34 b Ff(is)g(a)h(list)e(of)i(symbol)e(names,)j(and)f +Fg(obj)f Ff(is)g(the)g(e)o(xpression)f(that)h(corresponds)g(to)g(the)h +(body)f(of)g(the)0 1326 y(function.)c(F)o(or)25 b(e)o(xample,)900 +1490 y Fd(\(lambda)g(\(x)g(y)g(z\))g(\(+)g(\(+)g(x)g(y\))f(z\)\))p +Fc(=)p Fb(>)i Fg(#pr)l(oc)146 1653 y Ff(is)33 b(a)h(function)f(that)g +(tak)o(es)g(three)h(ar)n(guments)f(and)g(returns)g(their)g(sum.)56 +b(It)34 b(can)f(be)h(bound)f(to)g(a)h(symbol)0 1774 y(using)24 +b Fd(de\002ne)p Ff(.)900 1938 y Fd(\(de\002ne)j(sum3)e(\(lambda)g(\(x)g +(y)f(z\))i(\(+)f(\(+)f(x)h(y\))g(z\)\)\))p Fc(=)p Fb(>)g +Fg(#pr)l(oc)146 2101 y Ff(No)n(w)-6 b(,)24 b(we)h(can)g(use)g +Fd(sum3)g Ff(lik)o(e)f(an)o(y)g(other)h(function.)900 +2265 y Fd(\(sum3)g(5)g(3)f(8\))p Fc(=)p Fb(>)h Fg(16)146 +2429 y Ff(A)g(function)f(can)h(be)g(applied)f(to)h(a)g(list)f(using)g +Fd(apply)p Ff(.)p 1186 2508 1528 4 v 1184 2628 4 121 +v 1236 2592 a Fd(\(apply)h Fg(pr)l(oc)g(list)p Fd(\))p +1939 2628 V 98 w Ff(apply)f Fg(pr)l(oc)g Ff(to)h Fg(list)p +2712 2628 V 1186 2631 1528 4 v 783 2713 a Ff(\(Note:)30 +b(both)24 b Fg(pr)l(oc)g Ff(and)h Fg(list)f Ff(are)h(e)n(v)n(aluated)f +(before)h(application.\))146 2877 y Fg(list)e Ff(is)g(used)h(as)g(the)f +(list)g(of)h(ar)n(guments)f(for)h(the)f(function.)30 +b(F)o(or)24 b(instance,)f(an)h(alternati)n(v)o(e)e(w)o(ay)i(to)f(sum)g +(the)0 2997 y(three)i(numbers)f(in)g(the)h(e)o(xample)f(abo)o(v)o(e)g +(is:)900 3161 y Fd(\(apply)h(sum3)g('\(3)g(5)g(8\)\))p +Fc(=)p Fb(>)g Fg(16)146 3325 y Ff(An)g(alternati)n(v)o(e)e(method)h +(for)h(creating)g(bindings)e(is)i(pro)o(vided)e(by)i(the)f +Fd(let)h Ff(mechanism.)p 301 3402 3298 4 v 299 3522 4 +121 v 351 3486 a Fd(\(let)g Fg(binding-list)e(e)n(xpr)p +Fd(\))p 1386 3522 V 230 w Ff(e)n(v)n(aluate)h Fg(e)n(xpr)h +Ff(after)h(the)e(bindings)f(ha)n(v)o(e)i(been)g(performed)p +3597 3522 V 301 3525 3298 4 v 299 3646 4 121 v 351 3609 +a Fd(\(let*)g Fg(binding-list)d(e)n(xpr)p Fd(\))p 1386 +3646 V 181 w Ff(e)n(v)n(aluate)i Fg(e)n(xpr)h Ff(after)h(the)e +(bindings)f(ha)n(v)o(e)i(been)g(performed)p 3597 3646 +V 301 3649 3298 4 v 299 3769 4 121 v 351 3733 a Fd(\(letr)n(ec)h +Fg(binding-list)d(e)n(xpr)p Fd(\))p 1386 3769 V 99 w +Ff(e)n(v)n(aluate)h Fg(e)n(xpr)h Ff(after)h(the)e(bindings)f(ha)n(v)o +(e)i(been)g(performed)p 3597 3769 V 301 3773 3298 4 v +146 3893 a(The)g Fg(binding-list)e Ff(is)h(a)i(list)d(of)i(bindings.)30 +b(Each)25 b(binding)e(is)i(a)g(list)f(containing)g(a)h(symbol)e(and)i +(an)g(e)o(xpres-)0 4013 y(sion.)39 b(The)28 b(e)o(xpression)f(is)g(e)n +(v)n(aluated)g(and)h(bound)f(to)h(the)f(symbol.)39 b(In)28 +b(the)g(case)g(of)g Fd(let)p Ff(,)h(all)f(the)g(e)o(xpressions)0 +4133 y(are)f(e)n(v)n(aluated)e(before)h(binding)f(them)g(to)h(an)o(y)g +(symbol;)e Fd(let*)p Ff(,)j(on)e(the)h(other)g(hand,)g(e)n(v)n(aluates) +f(an)h(e)o(xpression)0 4254 y(and)i(binds)g(it)g(to)g(the)h(symbol)e +(before)i(e)n(v)n(aluating)d(the)j(ne)o(xt)e(e)o(xpression.)41 +b Fd(letr)n(ec)30 b Ff(permits)d(bindings)g(to)h(refer)0 +4374 y(to)h(each)h(other)l(,)h(permitting)c(mutually)h(recursi)n(v)o(e) +h(function)f(de\002nitions.)44 b(The)29 b(e)n(v)n(aluation)f(order)i +(is)f(de\002ned)0 4494 y(to)d(be)h(from)g(left)g(to)f(right)g(in)h(all) +f(cases.)37 b(After)27 b(performing)g(the)f(bindings,)g +Fg(e)n(xpr)h Ff(is)f(e)n(v)n(aluated)g(with)g(the)h(ne)n(w)0 +4615 y(bindings)c(in)i(ef)n(fect)g(and)f(the)h(result)f(is)h(returned.) +146 4735 y Fd(let)g Ff(bindings)e(can)j(be)f(used)f(in)h(interesting)e +(w)o(ays.)31 b(An)24 b(e)o(xample)g(of)h(their)g(use)f(is)h(pro)o +(vided)e(later)-5 b(.)146 4856 y(Scheme)37 b(is)f(an)g(eager)h +(language,)h(and)e(only)f(a)i(fe)n(w)f(functions)f(do)h(not)f(e)n(v)n +(aluate)g(all)h(their)g(ar)n(guments)0 4976 y(\(de\002nitions)c(and)h +(conditionals\).)53 b(Ev)n(aluation)31 b(can)i(be)g(controlled)f(to)g +(some)h(de)o(gree)g(using)e(the)i(follo)n(wing)0 5096 +y(tw)o(o)24 b(functions:)p 1100 5153 1700 4 v 1098 5273 +4 121 v 1150 5237 a Fd(\(quote)i Fg(obj)p Fd(\))p 1655 +5273 V 99 w Ff(the)f(une)n(v)n(aluated)e(object)i Fg(obj)p +2798 5273 V 1100 5276 1700 4 v 1098 5397 4 121 v 1150 +5361 a Fd(\(e)o(v)o(al)f Fg(obj)p Fd(\))p 1655 5397 V +168 w Ff(e)n(v)n(aluates)g(object)g Fg(obj)p 2798 5397 +V 1100 5400 1700 4 v 1875 5649 a Ff(\2266\226)p eop +%%Page: 7 7 +7 6 bop 0 -180 a Ff(Magic)24 b(T)l(utorial)g(#S-1:)31 +b(The)24 b(scheme)h(command-line)f(interpreter)713 b(September)25 +b(26,)g(2001)0 82 y Fe(3.7)119 b(Contr)n(ol)30 b(structur)n(es)0 +270 y Ff(Since)23 b(scheme)f(is)g(a)h(functional)f(programming)f +(language,)i(functions)e(that)h(are)h(usually)f(written)g(using)f +(loops)0 390 y(are)37 b(written)f(using)f(recursion.)66 +b(Conditional)35 b(constructs)g(are)i(used)g(to)f(terminate)f(the)i +(recursion.)65 b(These)0 511 y(constructs)21 b(are)h(slightly)e(dif)n +(ferent)i(in)f(that)h(the)o(y)f(do)g(not)g(e)n(v)n(aluate)g(all)h +(their)f(ar)n(guments)g(\(otherwise)h(recursi)n(v)o(e)0 +631 y(functions)i(w)o(ould)g(not)g(terminate!\).)p 552 +750 2797 4 v 550 871 4 121 v 602 835 a Fd(\(if)h Fg(e)n(xpr)g(ar)l(g1)f +(ar)l(g2)p Fd(\))p 1396 871 V 99 w Ff(e)n(v)n(aluate)g +Fg(e)n(xpr)h Ff(and)g(e)n(v)n(aluate)f(one)h(of)f Fg(ar)l(g1)h +Ff(or)g Fg(ar)l(g2)p 3346 871 V 552 874 2797 4 v 146 +1040 a Ff(The)j Fd(if)g Ff(construct)f(e)n(v)n(aluates)g(its)g(\002rst) +h(ar)n(gument)g(\(which)f(must)g(result)g(in)h(a)g(boolean\),)g(and)g +(if)g(the)g(result)0 1160 y(is)c Fd(#t)h Ff(e)n(v)n(aluates)f +Fg(ar)l(g1)g Ff(and)h(returns)g(the)f(result;)g(otherwise)g +Fg(ar)l(g2)h Ff(is)f(e)n(v)n(aluated)g(and)h(returned.)146 +1280 y(F)o(or)g(instance,)f(the)h(standard)f(f)o(actorial)h(function)f +(might)g(be)h(written)f(as:)900 1485 y Fd(\(de\002ne)j(fact)e(\(lambda) +g(\(x\))g(\(if)g(\(positi)o(v)o(e?)31 b(x\))25 b(\(*)f(x)h(\(fact)h +(\(-)f(x)g(1\)\)\))g(1\)\)\))146 1689 y Ff(A)g(more)g(complicated)f +(form)g(of)h(conditional)e(beha)n(vior)i(is)f(pro)o(vided)g(by)g +Fd(cond)p Ff(.)p 989 1808 1922 4 v 987 1928 4 121 v 1039 +1892 a Fd(\(cond)i Fg(ar)l(g1)e(ar)l(g2)h(...)p Fd(\))p +1877 1928 V 99 w Ff(generalized)h(conditional)p 2909 +1928 V 989 1932 1922 4 v 146 2097 a(Each)j(ar)n(gument)e(consists)g(of) +h(a)h(list)e(which)h(contains)f(tw)o(o)h(e)o(xpressions.)39 +b(The)28 b(\002rst)g(e)o(xpression)f(is)h(e)n(v)n(al-)0 +2217 y(uated)35 b(\(and)g(must)f(e)n(v)n(aluate)g(to)h(a)g(boolean\),)i +(and)e(if)g(it)g(is)f(true)h(the)g(second)g(e)o(xpression)f(is)g(e)n(v) +n(aluated)g(and)0 2338 y(returned)29 b(as)g(the)f(result)g(of)h(the)g +(entire)g(e)o(xpression.)41 b(If)29 b(the)g(result)f(w)o(as)h(f)o +(alse,)g(the)g(ne)o(xt)f(ar)n(gument)g(is)h(e)o(xam-)0 +2458 y(ined)23 b(and)g(the)g(abo)o(v)o(e)f(procedure)h(is)g(repeated.) +30 b(If)24 b(all)f(ar)n(guments)f(e)n(v)n(aluate)g(to)h(f)o(alse,)g +(the)g(result)g(is)f(unde\002ned.)146 2579 y(F)o(or)j(instance)f(if)h +Fd(x)g Ff(w)o(as)g(a)g(list,)f(the)g(e)o(xpression)900 +2783 y Fd(\(cond)i(\(\(null?)31 b(x\))25 b(x\))g(\(\(list?)30 +b(x\))25 b(\(car)h(x\)\))f(\(#t)g(\(echo)2804 2783 y +(") show + +2804 2783 a 60 w Fd(err)n(or)3088 2783 y +(") show + 3088 2783 a +61 w Fd(\)\)\))146 2987 y Ff(w)o(ould)e(return)h(the)g(empty)f(list)g +(if)h Fd(x)g Ff(w)o(as)g(the)f(empty)h(list)e(and)i(the)g(\002rst)g +(element)f(from)h(the)g(list)f(otherwise.)0 3107 y(When)i +Fd(x)g Ff(is)f(not)g(a)h(list,)f(an)h(error)g(message)g(is)f +(displayed.)30 b(Note)24 b(that)h Fd(echo)g Ff(is)g(a)g(standard)f +(magic)h(command.)146 3228 y(Often)g(one)f(needs)h(to)f(e)n(v)n(aluate) +f(a)i(number)f(of)g(e)o(xpressions)f(in)h(sequence)h(\(since)f(the)h +(language)f(has)g(side-)0 3348 y(ef)n(fects\).)31 b(The)25 +b Fd(begin)g Ff(construct)f(can)i(be)f(used)f(for)h(this)f(purpose.)p +1000 3467 1900 4 v 998 3588 4 121 v 1050 3552 a Fd(\(begin)i +Fg(ar)l(g1)e(ar)l(g2)g(.)15 b(.)g(.)g Fd(\))p 1960 3588 +V 100 w Ff(sequencing)24 b(construct)p 2898 3588 V 1000 +3591 1900 4 v 146 3757 a Fd(begin)29 b Ff(e)n(v)n(aluates)e(each)i(of)f +(its)g(ar)n(guments)f(in)h(sequence,)h(and)g(returns)f(the)g(result)f +(of)i(e)n(v)n(aluating)d(its)i(last)0 3877 y(ar)n(gument.)0 +4169 y Fe(3.8)119 b(Interaction)30 b(with)h(lay)m(out)0 +4356 y Ff(All)25 b(standard)h(magic)f(commands)g(are)i(also)e(scheme)h +(functions.)33 b(This)25 b(permits)g(one)h(to)f(write)h(scheme)g(func-) +0 4477 y(tions)20 b(that)g(interact)g(with)g(the)h(layout)f(directly)-6 +b(.)28 b(Apart)21 b(from)f(the)h(standard)f(magic)g(commands,)h(the)f +(follo)n(wing)0 4597 y(scheme)25 b(functions)e(are)j(pro)o(vided)e(so)g +(as)h(to)f(enable)h(the)g(user)g(to)f(edit)h(layout.)p +408 4714 3085 4 v 406 4835 4 121 v 458 4799 a Fd(\(getbox\))p +1051 4835 V 296 w Ff(a)h(list)d(containing)h(four)h(members)f(\(llx)g +(lly)g(urx)h(ury\))p 3491 4835 V 408 4838 3085 4 v 406 +5079 4 241 v 458 4922 a Fd(\(getpaint)g Fg(str)p Fd(\))p +1051 5079 V 99 w Ff(a)j(list)e(containing)g(the)h(box)o(es)f(from)h +(layer)g Fg(str)f Ff(under)h(the)g(current)1102 5043 +y(box)e(that)f(ha)n(v)o(e)h(paint)f(in)g(them)p 3491 +5079 V 408 5082 3085 4 v 406 5323 4 241 v 458 5166 a +Fd(\(getlabel)h Fg(str)p Fd(\))p 1051 5323 V 115 w Ff(a)e(list)f +(containing)f(the)h(labels)g(under)h(the)f(current)h(box)f(that)g +(match)1102 5287 y Fg(str)p 3491 5323 V 408 5326 3085 +4 v 406 5446 4 121 v 458 5410 a Fd(\(magic)i Fg(sym)p +Fd(\))p 1051 5446 V 144 w Ff(forces)i Fg(sym)e Ff(to)h(be)g +(interpreted)f(as)h(a)g(magic)g(command)p 3491 5446 V +408 5450 3085 4 v 1875 5649 a(\2267\226)p eop +%%Page: 8 8 +8 7 bop 0 -180 a Ff(September)25 b(26,)f(2001)713 b(Magic)25 +b(T)l(utorial)e(#S-1:)31 b(The)25 b(scheme)g(command-line)e +(interpreter)146 68 y(The)30 b(pairs)f(\(llx,lly\))f(and)i(\(urx,ury\)) +f(correspond)g(to)g(magic)h(coordinates)e(for)i(the)f(lo)n(wer)g(left)h +(and)f(upper)0 188 y(right)35 b(corner)i(of)f(the)g(current)h(box.)64 +b Fd(getpaint)37 b Ff(returns)f(a)g(list)f(of)i(box)o(es)e(\(llx)g(lly) +h(urx)g(ury\),)j(and)d Fd(getlabel)0 309 y Ff(returns)29 +b(a)h(list)f(of)h(tagged)f(box)o(es)g(\(label)g(llx)g(lly)g(urx)h +(ury\))f(which)h(contain)f(the)g(label)g(string.)45 b +Fd(magic)29 b Ff(can)h(be)0 429 y(used)h(to)g(force)h(the)f(scheme)g +(interpreter)g(to)g(interpret)g(a)g(symbol)f(as)h(a)h(magic)e +(procedure.)51 b(The)31 b(e)n(v)n(aluation)0 549 y(returns)25 +b(the)f(speci\002ed)h(magic)g(command.)0 867 y Fe(3.9)119 +b(Miscellaneous)0 1062 y Ff(Some)25 b(additional)e(functions)h(are)i +(pro)o(vided)d(to)i(enable)f(the)h(user)g(to)f(deb)n(ug)h(functions.)p +591 1231 2718 4 v 589 1352 4 121 v 641 1316 a Fd(\(sho)o(wframe\))p +1505 1352 V 381 w Ff(display)f(the)g(current)h(list)f(of)h(bindings)p +3307 1352 V 591 1355 2718 4 v 589 1476 4 121 v 641 1439 +a Fd(\(display-object)h Fg(obj)p Fd(\))p 1505 1476 V +99 w Ff(display)e(the)g(type)h(and)g(v)n(alue)f(of)h +Fg(obj)p 3307 1476 V 591 1479 2718 4 v 589 1599 4 121 +v 641 1563 a Fd(\(err)n(or)h Fg(str)p Fd(\))p 1505 1599 +V 494 w Ff(display)e(error)h(message)g(and)f(abort)h(e)n(v)n(aluation)p +3307 1599 V 591 1603 2718 4 v 589 1723 4 121 v 641 1687 +a Fd(\(eqv?)31 b Fg(obj1)24 b(obj2)p Fd(\))p 1505 1723 +V 240 w Ff(checks)h(if)g(tw)o(o)f(objects)g(are)i(equal)p +3307 1723 V 591 1726 2718 4 v 589 1847 4 121 v 641 1810 +a Fd(\(collect-garbage\))p 1505 1847 V 203 w Ff(force)f(garbage)g +(collection)p 3307 1847 V 591 1850 2718 4 v 146 2059 +a(The)g(follo)n(wing)d(is)i(a)h(complete)f(list)g(of)g(the)g(b)n +(uilt-in)f(scheme)i(v)n(ariables)f(that)g(can)g(be)h(used)f(to)g +(control)g(the)0 2179 y(interpreter)-5 b(.)p 163 2348 +3575 4 v 161 2469 4 121 v 213 2433 a Fd(scm-library-path)p +1296 2469 V 410 w Ff(a)25 b(colon-separated)g(path)g(string)p +3735 2469 V 163 2472 3575 4 v 161 2713 4 241 v 213 2556 +a Fd(scm-echo-r)n(esult)p 1296 2713 V 468 w Ff(a)48 b(boolean)e(used)h +(to)g(determine)f(if)i(the)f(result)f(of)h(e)n(v)n(aluation)1347 +2677 y(should)24 b(be)h(displayed)p 3735 2713 V 163 2716 +3575 4 v 161 2837 4 121 v 213 2801 a Fd(scm-trace-magic)p +1296 2837 V 432 w Ff(controls)f(display)g(of)h(actual)g(magic)f +(commands)p 3735 2837 V 163 2840 3575 4 v 161 2960 4 +121 v 213 2924 a Fd(scm-echo-parser)l(-input)p 1296 2960 +V 178 w Ff(controls)g(display)g(of)h(the)f(string)g(sent)h(to)f(the)h +(scheme)f(parser)p 3735 2960 V 163 2964 3575 4 v 161 +3084 4 121 v 213 3048 a Fd(scm-echo-parser)l(-output)p +1296 3084 V 123 w Ff(controls)g(display)g(of)h(the)f(result)h(of)g +(parsing)p 3735 3084 V 163 3087 3575 4 v 161 3328 4 241 +v 213 3172 a Fd(scm-stack-display-depth)p 1296 3328 V +101 w Ff(controls)j(the)h(number)f(of)h(frames)g(displayed)e(in)i(the)f +(stack)h(trace)1347 3292 y(output)24 b(when)h(an)g(error)g(occurs)g +(during)f(e)n(v)n(aluation)p 3735 3328 V 163 3331 3575 +4 v 161 3452 4 121 v 213 3416 a Fd(scm-gc-fr)n(equency)p +1296 3452 V 386 w Ff(controls)g(the)h(frequenc)o(y)g(of)f(garbage)h +(collection)p 3735 3452 V 163 3455 3575 4 v 0 3714 a +Fe(3.10)119 b(Libraries)0 3909 y Ff(The)25 b(follo)n(wing)e(function)h +(loads)g(in)g(a)h(\002le)h(and)e(e)n(v)n(aluates)g(its)g(contents)g(in) +g(order)-5 b(.)p 343 4078 3215 4 v 341 4199 4 121 v 392 +4163 a Fd(\(load-scm)25 b Fg(str)p Fd(\))p 1168 4199 +V 248 w Ff(reads)g(scheme)g(commands)e(in)i(from)f(the)h(named)g +(\002le)p 3556 4199 V 343 4202 3215 4 v 341 4322 4 121 +v 392 4286 a Fd(\(sa)n(v)o(e-scm)g Fg(str)f(obj)p Fd(\))p +1168 4322 V 99 w Ff(appends)g Fg(obj)h Ff(to)f(the)h(\002le)g +Fg(str)p Ff(,)f(creating)h(a)g(ne)n(w)f(\002le)i(if)e(necessary)p +3556 4322 V 343 4326 3215 4 v 146 4535 a(The)d(\002le)f(can)h(be)f(in)g +(the)g(current)h(directory)-6 b(,)20 b(or)g(in)g(an)o(y)g(of)g(the)g +(locations)f(speci\002ed)i(by)f(a)g(string)f(containing)0 +4655 y(a)25 b(colon-separated)g(list)f(of)g(directory)h(names)f(stored) +h(in)f Fd(scm-library-path)p Ff(.)146 4779 y(The)35 b(format)g(of)g +(these)f(\002les)i(dif)n(fers)e(from)h(standard)f(magic)h(source)g +(\002les)g(because)g(the)g(contents)f(of)h(a)0 4899 y(line)e(are)h(not) +f(implicitly)f(parenthesized.)57 b(In)33 b(addition,)i(semicolons)d +(are)i(used)f(as)h(a)g(comment)e(character;)0 5020 y(e)n(v)o(erything) +23 b(follo)n(wing)g(a)i(semicolon)e(to)i(the)g(end)f(of)h(the)g +(current)g(line)f(is)h(treated)g(as)f(a)i(comment.)146 +5144 y(F)o(or)f(instance,)900 5400 y Fd(de\002ne)i(f)e(\(lambda)g +(\(x\))g(x\))1875 5649 y Ff(\2268\226)p eop +%%Page: 9 9 +9 8 bop 0 -180 a Ff(Magic)24 b(T)l(utorial)g(#S-1:)31 +b(The)24 b(scheme)h(command-line)f(interpreter)713 b(September)25 +b(26,)g(2001)146 69 y(w)o(ould)h(de\002ne)i Fd(f)f Ff(to)f(be)i(the)e +(identity)g(function)g(when)g(placed)h(in)g(a)g(magic)g(source)g +(\002le)g(\(so)g(as)g(to)f(pro)o(vide)0 189 y(backw)o(ard)d +(compatibility\).)k(The)c(same)f(de\002nition)g(w)o(ould)g(result)g(in) +g(an)g(error)i(if)e(placed)h(in)f(a)h(scheme)f(source)0 +309 y(\002le.)900 538 y Fd(\(de\002ne)27 b(f)e(\(lambda)g(\(x\))g +(x\)\))146 766 y Ff(The)g(abo)o(v)o(e)f(e)o(xpression)f(should)h(be)h +(used)g(in)f(the)h(scheme)f(\002le)i(to)e(achie)n(v)o(e)g(the)h(same)f +(ef)n(fect.)0 1106 y Fh(Refer)m(ences)0 1329 y Ff([1])49 +b(H.)25 b(Abelson)f(and)g(G.J.)h(Sussman,)35 b Fg(Structur)l(e)24 +b(and)g(Interpr)l(etation)f(of)i(Computer)f(Pr)l(o)o(gr)o(ams)p +Ff(.)0 1532 y([2])49 b(H.)25 b(Abelson)f Fg(et)g(al.)p +Ff(,)36 b Fg(Re)o(vised)24 b(Report)g(on)h(the)f(Algorithmic)f(Langua)o +(g)o(e)i(Sc)o(heme)p Ff(.)1875 5649 y(\2269\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tutscm2.ps b/doc/psfiles/tutscm2.ps new file mode 100644 index 00000000..e567f389 --- /dev/null +++ b/doc/psfiles/tutscm2.ps @@ -0,0 +1,474 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tutscm2.dvi +%%Pages: 4 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tutscm2.dvi -o tutscm2.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +%%BeginProcSet: special.pro +TeXDict begin /SDict 200 dict N SDict begin /@SpecialDefaults{/hs 612 N +/vs 792 N /ho 0 N /vo 0 N /hsc 1 N /vsc 1 N /ang 0 N /CLIP 0 N /rwiSeen +false N /rhiSeen false N /letter{}N /note{}N /a4{}N /legal{}N}B +/@scaleunit 100 N /@hscale{@scaleunit div /hsc X}B /@vscale{@scaleunit +div /vsc X}B /@hsize{/hs X /CLIP 1 N}B /@vsize{/vs X /CLIP 1 N}B /@clip{ +/CLIP 2 N}B /@hoffset{/ho X}B /@voffset{/vo X}B /@angle{/ang X}B /@rwi{ +10 div /rwi X /rwiSeen true N}B /@rhi{10 div /rhi X /rhiSeen true N}B +/@llx{/llx X}B /@lly{/lly X}B /@urx{/urx X}B /@ury{/ury X}B /magscale +true def end /@MacSetUp{userdict /md known{userdict /md get type +/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup +length 20 add dict copy def}if end md begin /letter{}N /note{}N /legal{} +N /od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath +clippath mark{transform{itransform moveto}}{transform{itransform lineto} +}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{ +itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{ +closepath}}pathforall newpath counttomark array astore /gc xdf pop ct 39 +0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}N +/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 +scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get +ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip +not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 +TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{noflips{TR +pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 +-1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg +TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg +sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr +0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add +2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N /cp +{pop pop showpage pm restore}N end}if}if}N /normalscale{Resolution 72 +div VResolution 72 div neg scale magscale{DVImag dup scale}if 0 setgray} +N /psfts{S 65781.76 div N}N /startTexFig{/psf$SavedState save N userdict +maxlength dict begin /magscale true def normalscale currentpoint TR +/psf$ury psfts /psf$urx psfts /psf$lly psfts /psf$llx psfts /psf$y psfts +/psf$x psfts currentpoint /psf$cy X /psf$cx X /psf$sx psf$x psf$urx +psf$llx sub div N /psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy +scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR +/showpage{}N /erasepage{}N /copypage{}N /p 3 def @MacSetUp}N /doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N /endTexFig{end psf$SavedState restore}N /@beginspecial{SDict +begin /SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count /ocount X /dcount countdictstack N}N /@setspecial +{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if /showpage{}N /erasepage{}N /copypage{}N newpath +}N /@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{ +end}repeat grestore SpecialSave restore end}N /@defspecial{SDict begin} +N /@fedspecial{end}B /li{lineto}B /rl{rlineto}B /rc{rcurveto}B /np{ +/SaveX currentpoint /SaveY X N 1 setlinecap newpath}N /st{stroke SaveX +SaveY moveto}N /fil{fill SaveX SaveY moveto}N /ellipse{/endangle X +/startangle X /yrad X /xrad X /savematrix matrix currentmatrix N TR xrad +yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tutscm2.dvi) +@start /Fa 133[44 50 50 1[50 55 33 39 44 1[55 50 55 83 +28 2[28 55 50 33 44 55 44 55 50 30[66 2[50 1[57 2[33 +3[50 50 50 50 50 50 2[25 33 1[57 50 33 33 33 3[50 1[33 +30[55 2[{ TeXBase1Encoding ReEncodeFont }42 100.000003 +/Times-Bold rf /Fb 138[66 40 47 53 2[60 66 100 33 2[33 +66 2[53 66 53 1[60 12[80 6[113 9[86 8[40 55[66 2[{ + TeXBase1Encoding ReEncodeFont }19 119.999948 /Times-Bold +rf /Fc 105[50 1[44 44 24[44 50 50 72 50 50 28 39 33 50 +50 50 50 78 28 50 1[28 50 50 33 44 50 44 50 44 9[94 2[61 +55 66 1[55 1[72 89 3[33 72 1[55 61 72 66 66 72 6[28 50 +1[50 50 50 50 50 50 50 50 1[25 33 25 2[33 33 33 3[50 +32[55 2[{ TeXBase1Encoding ReEncodeFont }61 100.000003 +/Times-Roman rf /Fd 139[28 1[39 2[50 50 3[28 28 50 2[44 +3[50 14[61 3[66 83 35[33 33 40[{ TeXBase1Encoding ReEncodeFont }14 +100.000003 /Times-Italic rf /Fe 133[64 1[72 104 72 80 +48 56 64 2[72 80 120 40 2[40 80 72 48 64 80 64 80 72 +9[143 2[96 80 5[135 96 5[88 3[96 7[48 3[72 72 72 72 72 +72 3[48 9[72 35[{ TeXBase1Encoding ReEncodeFont }37 143.999997 +/Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 787 101 a Fe(Magic)35 b(T)-13 b(utorial)34 b(#S-2:)43 +b(Boxes)35 b(and)g(labels)1655 521 y Fd(Rajit)24 b(Manohar)1282 +941 y Fc(Department)g(of)h(Computer)f(Science)1271 1062 +y(California)h(Institute)f(of)h(T)-7 b(echnology)1534 +1182 y(P)o(asadena,)25 b(CA)h(91125)1053 1453 y(This)e(tutorial)g +(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.)0 1973 y +Fb(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 +2171 y Fc(Magic)24 b(T)l(utorial)g(#S-1:)31 b(The)24 +b(scheme)h(command-line)f(interpreter)0 2368 y Fb(Commands)29 +b(intr)n(oduced)j(in)f(this)f(tutorial:)300 2566 y Fc(:getbox,)24 +b(:box.push,)f(:box.pop,)g(:box.mo)o(v)o(e,)f(:label.v)o(ert,)i +(:label.horiz,)300 2686 y(:label.rename,)g(:label.search,)h +(:label.\002nd-ne)o(xt)0 2884 y Fb(Macr)n(os)k(intr)n(oduced)i(in)g +(this)f(tutorial:)300 3104 y Fd(\(None\))0 3693 y Fe(1)143 +b(The)35 b(curr)m(ent)g(box)0 3916 y Fc(The)28 b(fundamental)e(w)o(ay)i +(scheme)f(programs)g(interact)h(with)e(magic)h(layout)g(is)g(by)h +(using)e(magic')-5 b(s)27 b Fa(box)g Fc(com-)0 4037 y(mand.)j(F)o(or)25 +b(instance,)900 4257 y Fa(\(box)g(1)g(1)g(2)f(2\))146 +4478 y Fc(changes)d(the)g(current)g(box)f(to)g(the)h(rectangle)g +(de\002ned)g(by)g(the)f(coordinates)h(\(1,1\))f(and)h(\(2,2\))g(in)f +(the)h(current)0 4598 y(edit)k(cell.)32 b(This)25 b(is)f(the)i +(standard)e(magic)h Fa(:box)h Fc(command.)31 b(After)26 +b(mo)o(ving)d(the)i(box)g(to)g(a)h(particular)f(position)0 +4718 y(in)f(the)h(layout,)f(the)h(area)g(can)h(be)f(painted,)f(erased,) +h(selected,)g(etc.)146 4839 y(The)g(scheme)g(function)f +Fa(getbox)h Fc(returns)g(the)f(current)h(box)g(as)f(a)i(list)d(of)i +(four)g(inte)o(gers.)30 b(F)o(or)25 b(instance,)900 5059 +y Fa(\(box)g(1)g(1)g(2)f(2\))900 5180 y(\(de\002ne)j(x)d(\(getbox\)\)) +146 5400 y Fc(will)g(bind)g(the)h(list)f Fa(\(1)h(1)f(2)h(2\))g +Fc(to)f(v)n(ariable)h Fa(x)p Fc(.)1875 5649 y(\2261\226)p +eop +%%Page: 2 2 +2 1 bop 0 -180 a Fc(September)25 b(26,)f(2001)1559 b(Magic)24 +b(T)l(utorial)g(#S-2:)30 b(Box)o(es)25 b(and)g(labels)0 +99 y Fe(2)143 b(Sa)l(ving)35 b(and)g(r)m(estoring)f(the)h(box)0 +322 y Fc(If)29 b(a)h(scheme)f(function)f(mo)o(v)o(es)f(the)i(current)g +(box)g(around,)g(it)g(is)f(good)h(practice)g(to)g(restore)g(the)g(box)f +(back)h(to)0 443 y(its)23 b(original)f(position.)28 b(This)23 +b(is)g(especially)g(useful)g(when)g(writing)f(a)i(function)f(that)f +(the)i(user)f(is)g(lik)o(ely)f(to)h(type)0 563 y(on)i(the)f(command)g +(line.)146 683 y Fa(box.push)j Fc(can)f(be)g(used)g(to)f(push)g(a)h +(box)g(onto)f(the)g(current)h(stack)g(of)g(box)o(es.)33 +b Fa(box.pop)26 b Fc(restores)g(the)g(box)0 804 y(to)e(the)h(one)g(on)f +(the)h(top)f(of)h(the)g(box)f(stack.)31 b(The)24 b(sequence)900 +998 y Fa(\(box.push)i(\(getbox\)\))900 1118 y(\(box)f(1)g(1)g(5)f(4\)) +900 1239 y(\(paint)i(poly\))900 1359 y(\(box.pop\))146 +1553 y Fc(will)31 b(paint)g(a)g(rectangle)h(of)g(polysilicon)d(from)i +(\(1,1\))h(to)f(\(5,4\),)i(restoring)d(the)i(original)e(position)g(of)h +(the)0 1674 y(box.)0 2009 y Fe(3)143 b(Mo)o(ving)35 b(the)g(box)0 +2232 y Fc(Magic')-5 b(s)24 b(b)n(uilt-in)f Fa(mo)o(v)o(e)i +Fc(command)f(is)g(not)g(entirely)g(reliable.)31 b(Sometimes)23 +b(mo)o(v)o(e)h(commands)f(are)j(ignored,)0 2353 y(with)j(disastrous)e +(ef)n(fects.)45 b(\(Think)28 b(about)h(what)g(might)f(happen)h(if)h(a)f +(mo)o(v)o(e)f(command)g(w)o(as)i(ignored)e(in)h(the)0 +2473 y(middle)g(of)g(dra)o(wing)g(a)h(stack)g(of)g(twenty)f +(transistors)f(.)46 b(.)g(.\))f(The)30 b(scheme)g(function)f +Fa(box.mo)o(v)o(e)g Fc(mo)o(v)o(es)f(the)0 2593 y(box)c(relati)n(v)o(e) +g(to)g(the)h(current)g(position.)900 2787 y Fa(\(box.mo)o(v)o(e)g(5)g +(3\))146 2982 y Fc(will)f(mo)o(v)o(e)g(the)g(box)h(right)f(5)g(lambda)h +(and)f(up)h(3)g(lambda.)0 3316 y Fe(4)143 b(Labelling)34 +b(v)o(ertical)g(and)h(horizontal)e(wir)m(es)0 3540 y +Fc(Datapaths)21 b(are)i(usually)d(designed)h(by)h(designing)e(cells)i +(for)g(a)g(single)f(bit)g(of)g(the)h(datapath,)g(and)g(then)f(arraying) +0 3660 y(those)27 b(cells)g(to)g(obtain)f(the)i(complete)e(datapath.)39 +b(When)27 b(simulating)e(such)i(designs,)g(it)g(is)g(usually)f +(desirable)0 3781 y(to)e(label)h(wires)g(in)f(the)h(datapath)f(with)g +(names)h(lik)o(e)f(\223name0\224,)h(\223name1\224,)g(up)f(to)h +(\223nameN.)-7 b(\224)146 3901 y(There)21 b(are)h(tw)o(o)e(functions)g +(that)g(can)h(be)g(used)f(to)h(perform)f(such)h(a)g(task.)29 +b(The)20 b(function)g Fa(label.v)o(ert)h Fc(returns)0 +4022 y(a)j(function)e(that)h(can)h(be)f(used)g(as)h(a)g(labeller)f(for) +g(v)o(ertically)g(arrayed)h(nodes.)30 b Fa(label.horiz)23 +b Fc(returns)g(a)h(function)0 4142 y(that)g(can)i(be)e(used)h(as)g(a)g +(labeller)g(for)g(horizontally)e(arrayed)j(nodes.)900 +4336 y Fa(\(de\002ne)h(lbl)d(\(label.v)o(ert)1807 4336 +y +(") show + 1807 4336 a 59 w Fa(name)2098 4336 y +(") show + 2098 4336 a 86 +w Fa(6\))146 4530 y Fc(The)29 b(command)e(abo)o(v)o(e)h(de\002nes)h(a)g +(ne)n(w)f(function)f Fa(lbl)i Fc(that)f(can)h(be)g(used)f(to)g +(generate)h(labels)f(be)o(ginning)0 4651 y(with)213 4651 +y +(") show + 213 4651 a 60 w Fc(name0)539 4651 y +(") show + 539 4651 a 95 w +Fc(for)35 b(nodes)h(that)f(are)h(v)o(ertically)e(spaced)i(by)f(6)h +(lambda.)62 b(The)36 b(simplest)e(w)o(ay)h(to)h(use)f(this)0 +4771 y(function)24 b(is)g(to)h(bind)f(it)g(to)g(a)i(macro)e(as)h(follo) +n(ws:)900 4965 y Fa(\(macr)n(o)g(1)1302 4965 y +(") show + 1302 4965 +a 60 w Fa(lbl)1473 4965 y +(") show + 1473 4965 a 59 w Fa(\))146 +5159 y Fc(Place)32 b(the)f(box)g(o)o(v)o(er)f(the)h(lo)n(west)f(node.) +49 b(Ev)o(ery)31 b(time)f(k)o(e)o(y)h(\2231\224)g(is)g(pressed,)i(a)e +(ne)n(w)g(label)g(\223nameM\224)g(is)0 5280 y(created)j(and)f(the)g +(box)g(is)g(mo)o(v)o(ed)e(up)i(by)g(6)g(lambda.)55 b +Fa(label.horiz)34 b Fc(can)f(be)h(used)f(in)g(a)g(similar)f(f)o(ashion) +h(for)0 5400 y(labelling)24 b(nodes)g(that)g(are)i(horizontally)d +(arrayed.)1875 5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#S-2:)31 +b(Box)o(es)24 b(and)h(labels)1558 b(September)25 b(26,)g(2001)0 +99 y Fe(5)143 b(Finding)34 b(and)i(r)m(enaming)e(existing)g(labels)0 +323 y Fc(The)25 b(label)g(macros)g(pro)o(vide)f(functionality)f(to)i +(search)h(for)f(all)g(labels)g(that)f(match)h(a)h(particular)f(string.) +30 b(Place)0 444 y(the)25 b(box)f(o)o(v)o(er)g(the)h(re)o(gion)f(of)g +(interest.)31 b(T)-8 b(ype:)900 675 y Fa(\(label.sear)n(ch)1463 +675 y +(") show + 1463 675 a 59 w Fa(label)1727 675 y +(") show + 1727 675 a +60 w Fa(\))146 906 y Fc(T)g(o)25 b(place)g(the)g(box)f(o)o(v)o(er)g +(the)h(\002rst)g(occurrence)g(of)g(the)g(label)g(you)f(searched)h(for)l +(,)g(type:)900 1138 y Fa(\(label.\002nd-next\))146 1369 +y Fc(Repeatedly)20 b(e)o(x)o(ecuting)f(this)f(function)h(causes)h(the)g +(box)f(to)g(mo)o(v)o(e)g(to)g(all)g(the)h(labels)f(that)h(match)f(the)h +(search)0 1490 y(pattern.)30 b(T)-8 b(ypically)i(,)24 +b(one)g(w)o(ould)g(bind)g Fa(label.\002nd-next)j Fc(to)d(a)i(macro.)146 +1610 y(The)k(command)e Fa(label.r)n(ename)j Fc(can)f(be)g(used)f(to)g +(rename)h(all)f(labels)g(with)g(a)h(particular)f(name.)45 +b(T)-8 b(o)29 b(use)0 1731 y(this)24 b(command,)g(place)h(the)f(box)h +(o)o(v)o(er)f(the)g(re)o(gion)g(of)h(interest.)30 b(Then)25 +b(type)900 1963 y Fa(\(label.r)n(ename)1507 1963 y +(") show + 1507 +1963 a 60 w Fa(label1)1822 1963 y +(") show + 1822 1963 a 1906 1963 +a +(") show + 1906 1963 a 60 w Fa(label2)2221 1963 y +(") show + 2221 1963 a +59 w Fa(\))146 2194 y Fc(All)g(occurrences)g(of)g(label)g +(\223label1\224)f(in)h(the)g(current)g(box)f(will)g(be)h(renamed)g(to)f +(\223label2\224.)0 2536 y Fe(6)143 b(Writing)35 b(these)g(functions)0 +2760 y Fc(The)h(functions)f(discussed)g(in)g(this)g(tutorial)g(are)i +(not)e(b)n(uilt-in.)63 b(The)o(y)35 b(are)h(user)n(-de\002ned)h +(functions)e(in)g(the)0 2881 y(def)o(ault)25 b(scheme)f(\002le)h +(loaded)g(in)f(when)h(magic)f(starts.)146 3001 y(As)32 +b(you)f(be)o(gin)g(to)h(use)f(magic)h(with)f(the)g(scheme)h +(command-line)e(interpreter)l(,)k(you)d(will)g(observ)o(e)h(that)0 +3122 y(commands)26 b(for)h(dra)o(wing)g(paint)f(on)h(the)g(screen)h +(are)g(e)o(xtremely)e(slo)n(w)-6 b(.)36 b(This)26 b(time)h(interv)n(al) +f(is)h(not)f(normally)0 3242 y(noticeable)e(because)h(editing)f(is)g +(interacti)n(v)o(e.)29 b(Ho)n(we)n(v)o(er)l(,)24 b(when)g(one)h(can)g +(write)f(a)h(scheme)g(program)f(to)g(dra)o(w)0 3363 y(twenty)k +(transistors)g(on)g(the)h(screen,)h(this)e(delay)h(becomes)f +(noticeable.)43 b(It)28 b(is)h(w)o(orthwhile)f(to)g(minimize)f(the)0 +3483 y(number)g(of)g(magic)g(commands)f(e)o(x)o(ecuted,)h(e)n(v)o(en)g +(if)g(this)f(in)l(v)n(olv)o(es)g(writing)g(more)h(scheme)g(code.)39 +b(The)27 b Fa(box-)0 3603 y(pop)g Fc(command)e(has)i(been)f(tuned)g(a)h +(little)e(to)h(not)f(e)o(x)o(ecute)h(the)g Fa(box)h Fc(command)e(if)h +(the)h(box)e(w)o(ould)h(not)g(mo)o(v)o(e)0 3724 y(as)f(a)g(result.)300 +3955 y Fa(\(de\002ne)i(box.list)d(\(\)\))300 4196 y(\(de\002ne)j +(box.mo)o(v)o(e)600 4317 y(\(lambda)e(\(dx)g(dy\))900 +4437 y(\(let*)g(\(\(x)g(\(getbox\)\))1138 4557 y(\(nllx)g(\(+)g(dx)g +(\(car)g(x\)\)\))1138 4678 y(\(nlly)g(\(+)g(dy)g(\(cadr)h(x\)\)\))1138 +4798 y(\(nurx)g(\(+)f(dx)g(\(caddr)h(x\)\)\))1138 4918 +y(\(nury)g(\(+)f(dy)g(\(cadddr)i(x\)\)\)\))900 5039 y(\(box)e(nllx)g +(nlly)f(nurx)i(nury\))900 5159 y(\))600 5280 y(\))300 +5400 y(\))1875 5649 y Fc(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fc(September)25 b(26,)f(2001)1559 b(Magic)24 +b(T)l(utorial)g(#S-2:)30 b(Box)o(es)25 b(and)g(labels)300 +205 y Fa(\(de\002ne)i(box.=?)600 325 y(\(lambda)e(\(b1)g(b2\))900 +445 y(\(and)h(\(and)f(\(=?)31 b(\(car)25 b(b1\))h(\(car)f(b2\)\))g +(\(=?)31 b(\(cadr)26 b(b1\))f(\(cadr)h(b2\)\)\))1138 +566 y(\(and)g(\(=?)k(\(caddr)d(b1\))e(\(caddr)h(b2\)\))f(\(=?)31 +b(\(caddr)26 b(b1\))g(\(caddr)g(b2\)\)\))900 686 y(\))600 +807 y(\))300 927 y(\))300 1168 y(\(de\002ne)h(box.push)600 +1288 y(\(lambda)e(\(pos\))900 1408 y(\(set!)31 b(box.list)25 +b(\(cons)g(pos)g(box.list\)\))600 1529 y(\))300 1649 +y(\))300 1878 y(\(de\002ne)i(box.pop)600 1998 y(\(lambda)e(\(\))900 +2118 y(\(if)g(\(null?)31 b(box.list\))1138 2239 y(\(echo)1390 +2239 y +(") show + 1390 2239 a 60 w Fa(Box)25 b(list)f(is)g(empty)2149 +2239 y +(") show + 2149 2239 a 61 w Fa(\))1138 2359 y(\(let)h(\(\(x)g(\(car)h +(box.list\)\)\))1438 2479 y(\(begin)1438 2600 y(\(set!)32 +b(box.list)24 b(\(cdr)i(box.list\)\))1438 2720 y(\(if)f(\(box.=?)31 +b(x)24 b(\(getbox\)\))i(#t)f(\(e)o(v)o(al)f(\(cons)h('box)g(x\)\)\)) +1438 2841 y(\))1138 2961 y(\))900 3081 y(\))600 3202 +y(\))300 3322 y(\))1875 5649 y Fc(\2264\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tutscm3.ps b/doc/psfiles/tutscm3.ps new file mode 100644 index 00000000..aba808b7 --- /dev/null +++ b/doc/psfiles/tutscm3.ps @@ -0,0 +1,481 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tutscm3.dvi +%%Pages: 2 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tutscm3.dvi -o tutscm3.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +%%BeginProcSet: special.pro +TeXDict begin /SDict 200 dict N SDict begin /@SpecialDefaults{/hs 612 N +/vs 792 N /ho 0 N /vo 0 N /hsc 1 N /vsc 1 N /ang 0 N /CLIP 0 N /rwiSeen +false N /rhiSeen false N /letter{}N /note{}N /a4{}N /legal{}N}B +/@scaleunit 100 N /@hscale{@scaleunit div /hsc X}B /@vscale{@scaleunit +div /vsc X}B /@hsize{/hs X /CLIP 1 N}B /@vsize{/vs X /CLIP 1 N}B /@clip{ +/CLIP 2 N}B /@hoffset{/ho X}B /@voffset{/vo X}B /@angle{/ang X}B /@rwi{ +10 div /rwi X /rwiSeen true N}B /@rhi{10 div /rhi X /rhiSeen true N}B +/@llx{/llx X}B /@lly{/lly X}B /@urx{/urx X}B /@ury{/ury X}B /magscale +true def end /@MacSetUp{userdict /md known{userdict /md get type +/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup +length 20 add dict copy def}if end md begin /letter{}N /note{}N /legal{} +N /od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath +clippath mark{transform{itransform moveto}}{transform{itransform lineto} +}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{ +itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{ +closepath}}pathforall newpath counttomark array astore /gc xdf pop ct 39 +0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}N +/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 +scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get +ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip +not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 +TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{noflips{TR +pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 +-1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg +TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg +sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr +0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add +2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N /cp +{pop pop showpage pm restore}N end}if}if}N /normalscale{Resolution 72 +div VResolution 72 div neg scale magscale{DVImag dup scale}if 0 setgray} +N /psfts{S 65781.76 div N}N /startTexFig{/psf$SavedState save N userdict +maxlength dict begin /magscale true def normalscale currentpoint TR +/psf$ury psfts /psf$urx psfts /psf$lly psfts /psf$llx psfts /psf$y psfts +/psf$x psfts currentpoint /psf$cy X /psf$cx X /psf$sx psf$x psf$urx +psf$llx sub div N /psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy +scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR +/showpage{}N /erasepage{}N /copypage{}N /p 3 def @MacSetUp}N /doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N /endTexFig{end psf$SavedState restore}N /@beginspecial{SDict +begin /SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count /ocount X /dcount countdictstack N}N /@setspecial +{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if /showpage{}N /erasepage{}N /copypage{}N newpath +}N /@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{ +end}repeat grestore SpecialSave restore end}N /@defspecial{SDict begin} +N /@fedspecial{end}B /li{lineto}B /rl{rlineto}B /rc{rcurveto}B /np{ +/SaveX currentpoint /SaveY X N 1 setlinecap newpath}N /st{stroke SaveX +SaveY moveto}N /fil{fill SaveX SaveY moveto}N /ellipse{/endangle X +/startangle X /yrad X /xrad X /savematrix matrix currentmatrix N TR xrad +yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tutscm3.dvi) +@start /Fa 1 63 df<7000000000000000FC00000000000000FF000000000000007FC0 +0000000000001FF000000000000007FC00000000000001FF000000000000007FC0000000 +0000001FF000000000000007FE00000000000001FF800000000000007FE0000000000000 +1FF800000000000003FE00000000000000FF800000000000003FE00000000000000FF800 +000000000003FF00000000000000FFC00000000000003FF00000000000000FFC00000000 +000001FF000000000000007FC00000000000001FF000000000000007FC00000000000001 +FF000000000000007FC00000000000001FE00000000000001FE00000000000007FC00000 +00000001FF00000000000007FC0000000000001FF00000000000007FC0000000000001FF +0000000000000FFC0000000000003FF0000000000000FFC0000000000003FF0000000000 +000FF80000000000003FE0000000000000FF80000000000003FE0000000000001FF80000 +000000007FE0000000000001FF80000000000007FE0000000000001FF00000000000007F +C0000000000001FF00000000000007FC0000000000001FF00000000000007FC000000000 +0000FF00000000000000FC0000000000000070000000000000003B3878B44C>62 +D E /Fb 1 1 df<7FFFFFFFFFFFFFE0FFFFFFFFFFFFFFF0FFFFFFFFFFFFFFF07FFFFFFF +FFFFFFE03C04789A4D>0 D E /Fc 103[33 29[44 50 50 72 50 +55 33 39 44 1[55 50 55 83 28 55 2[55 50 1[44 55 44 55 +50 10[72 12[39 20[50 1[50 1[50 1[25 33 1[57 50 33 33 +33 83 35[55 2[{ TeXBase1Encoding ReEncodeFont }37 100.000003 +/Times-Bold rf /Fd 138[66 40 47 53 2[60 66 100 33 2[33 +66 2[53 66 53 1[60 12[80 6[113 9[86 8[40 55[66 2[{ + TeXBase1Encoding ReEncodeFont }19 119.999948 /Times-Bold +rf /Fe 105[50 1[44 44 24[44 50 50 72 50 50 28 39 33 50 +50 50 50 78 28 50 28 28 50 50 33 44 50 44 50 44 7[72 +2[72 1[61 55 2[55 72 72 89 3[33 1[72 55 61 72 66 66 72 +6[28 50 1[50 50 50 50 50 50 50 50 28 25 33 25 2[33 33 +4[50 32[55 2[{ TeXBase1Encoding ReEncodeFont }63 100.000003 +/Times-Roman rf /Ff 139[28 1[39 2[50 50 3[28 28 50 2[44 +3[50 14[61 3[66 83 35[33 33 40[{ TeXBase1Encoding ReEncodeFont }14 +100.000003 /Times-Italic rf /Fg 138[80 48 56 64 2[72 +80 1[40 80 1[40 1[72 1[64 80 64 1[72 12[96 80 2[88 2[135 +18[48 6[72 72 72 3[48 9[72 35[{ TeXBase1Encoding ReEncodeFont }24 +143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 770 101 a Fg(Magic)35 b(T)-13 b(utorial)34 b(#S-3:)43 +b(T)-11 b(ransistor)34 b(stacks)1655 521 y Ff(Rajit)24 +b(Manohar)1282 941 y Fe(Department)g(of)h(Computer)f(Science)1271 +1062 y(California)h(Institute)f(of)h(T)-7 b(echnology)1534 +1182 y(P)o(asadena,)25 b(CA)h(91125)1053 1453 y(This)e(tutorial)g +(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.)0 1987 y +Fd(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 +2197 y Fe(Magic)24 b(T)l(utorial)g(#S-1:)31 b(The)24 +b(scheme)h(command-line)f(interpreter)0 2406 y Fd(Commands)29 +b(intr)n(oduced)j(in)f(this)f(tutorial:)300 2616 y Fe(:stack.p,)24 +b(:stack.n,)g(:stack.tallp,)f(:stack.talln,)g(:prs.dra)o(w)-6 +b(,)24 b(:prs.mgn,)300 2737 y(:prs.talldra)o(w)-6 b(,)23 +b(:prs.tallmgn)0 2945 y Fd(Macr)n(os)29 b(intr)n(oduced)i(in)g(this)f +(tutorial:)300 3182 y Ff(\(None\))0 4093 y Fg(1)143 b(Stacks)0 +4319 y Fe(The)37 b(\002rst)f(step)g(in)h(laying)e(out)h(a)h +(gate/operator)f(using)g(magic)g(tends)g(to)g(in)l(v)n(olv)o(e)f(dra)o +(wing)h(the)g(transistor)0 4440 y(stacks)h(without)f(an)o(y)h(wiring,)j +(labelling)c(all)h(the)h(important)e(nodes)h(in)g(the)g(circuit.)68 +b(Since)38 b(the)f(e)o(xtractor)0 4560 y(pretends)24 +b(that)f(nodes)h(that)f(ha)n(v)o(e)h(the)g(same)f(label)h(are)h +(electrically)e(connected,)i(the)e(e)o(xtracted)h(circuit)g(can)g(be)0 +4680 y(simulated)f(using)h(SPICE)i(to)f(obtain)f(some)g(indication)f +(of)i(the)g(po)n(wer/speed)f(of)h(the)f(circuit.)146 +4802 y Fc(stack.tallp)f Fe(and)g Fc(stack.talln)g Fe(can)g(be)f(used)h +(to)f(dra)o(w)h(such)f(transistor)g(stacks)g(and)g(place)h(contacts)g +(where)0 4922 y(required.)43 b(These)29 b(tw)o(o)g(functions)f(tak)o(e) +h(a)g(transistor)f(width)g(and)h(a)g(list)f(of)h(strings)f(that)g +(represent)h(the)g(stack)0 5043 y(as)i(their)f(ar)n(guments,)i(and)e +(dra)o(w)h(the)f(stack)h(v)o(ertically)f(\(gates)g(run)g +(horizontally\))g(at)h(the)f(current)h(box.)48 b(F)o(or)0 +5163 y(e)o(xample,)900 5400 y Fc(\(stack.tallp)25 b(40)g('\(\()1622 +5400 y +(") show + 1622 5400 a 60 w Fc(Vdd)1864 5400 y +(") show + 1864 5400 +a 60 w Fc(\))1983 5400 y +(") show + 1983 5400 a 59 w Fc(a)2092 5400 +y +(") show + 2092 5400 a 2177 5400 a +(") show + 2177 5400 a 60 w Fc(b)2292 +5400 y +(") show + 2292 5400 a 85 w Fc(\()2410 5400 y +(") show + 2410 5400 a +60 w Fc(Inode)2713 5400 y +(") show + 2713 5400 a 60 w Fc(\))2831 +5400 y +(") show + 2831 5400 a 60 w Fc(d)2946 5400 y +(") show + 2946 5400 a +85 w Fc(\()3064 5400 y +(") show + 3064 5400 a 60 w Fc(out)3262 5400 +y +(") show + 3262 5400 a 60 w Fc(\)\)\))1875 5649 y Fe(\2261\226)p +eop +%%Page: 2 2 +2 1 bop 0 -180 a Fe(September)25 b(26,)f(2001)1563 b(Magic)25 +b(T)l(utorial)e(#S-3:)31 b(T)m(ransistor)24 b(stacks)146 +68 y(dra)o(ws)37 b(a)g(v)o(ertical)f(stack)h(of)g(p-transistors)e(with) +h(the)h(dif)n(fusion)e(being)h(40)h(lambda)f(wide.)66 +b(The)37 b(stack)0 188 y(be)o(gins)28 b(with)h(a)h(contact)f(labelled)h +(\223Vdd\224,)g(follo)n(wed)f(by)g(tw)o(o)g(gates)g(labelled)g +(\223a\224)i(and)e(\223b\224,)i(follo)n(wed)d(by)i(a)0 +309 y(contact)k(labelled)f(\223Inode\224,)j(follo)n(wed)c(by)i(a)g +(gate)f(labelled)g(\223d\224,)k(follo)n(wed)32 b(by)i(a)g(contact)f +(labelled)g(\223out\224.)0 429 y(Contacts)28 b(are)i(indicated)e(by)g +(placing)g(the)g(string)g(for)h(the)f(label)g(in)g(parenthesis.)42 +b(Note)28 b(the)g(presence)i(of)e(the)0 549 y(quote)c(that)h(pre)n(v)o +(ents)e(the)i(interpreter)g(from)f(attempting)f(to)i(e)n(v)n(aluate)f +(the)g(list.)146 670 y(The)g(contact)g(width)f(and)h(contact-gate)f +(spacing)h(together)f(amount)g(to)h(more)f(than)h(the)g(spacing)f +(between)0 790 y(adjacent)30 b(gates.)47 b(Often)30 b(it)g(is)g +(desired)g(to)g(eliminate)f(this)h(e)o(xtra)g(space)h(by)f(jogging)f +(the)h(poly)f(wires)i(so)f(that)0 911 y(the)25 b(amount)g(of)h +(internal)f(dif)n(fusion)f(capacitance)i(is)f(minimized.)31 +b(The)26 b(functions)e Fc(stack.p)j Fe(and)e Fc(stack.n)i +Fe(can)0 1031 y(be)e(used)f(to)h(do)f(so.)31 b(T)-8 b(yping)900 +1259 y Fc(\(stack.tallp)25 b(40)g('\(\()1622 1259 y +(") show + 1622 +1259 a 60 w Fc(Vdd)1864 1259 y +(") show + 1864 1259 a 60 w Fc(\))1983 +1259 y +(") show + 1983 1259 a 59 w Fc(a)2092 1259 y +(") show + 2092 1259 a +2177 1259 a +(") show + 2177 1259 a 60 w Fc(b)2292 1259 y +(") show + 2292 1259 +a 85 w Fc(\()2410 1259 y +(") show + 2410 1259 a 60 w Fc(Inode)2713 +1259 y +(") show + 2713 1259 a 60 w Fc(\))2831 1259 y +(") show + 2831 1259 a +60 w Fc(d)2946 1259 y +(") show + 2946 1259 a 85 w Fc(\()3064 1259 +y +(") show + 3064 1259 a 60 w Fc(out)3262 1259 y +(") show + 3262 1259 a 60 +w Fc(\)\)\))146 1488 y Fe(will)f(dra)o(w)h(the)f(same)h(stack)g(and)f +(jog)h(the)f(poly)g(wires)h(corresponding)f(to)g(the)h(gate)f(for)h +(\223d\224.)0 1827 y Fg(2)143 b(Pr)m(oduction)34 b(rules)0 +2051 y Fe(The)c(functions)e Fc(prs.draw)j Fe(and)f Fc(prs.mgn)g +Fe(can)g(be)g(used)g(to)f(dra)o(w)h(the)f(transistor)g(stacks)g(that)h +(implement)e(a)0 2171 y(production)c(rule.)30 b(F)o(or)25 +b(instance,)900 2399 y Fc(\(prs.draw)h(40)1467 2399 y +(") show + +1467 2399 a 60 w Fc(x)f(&)g(y)f Fb(\000)29 b Fa(>)24 +b Fc(z-)2067 2399 y +(") show + 2067 2399 a 61 w Fc(\))146 2628 y +Fe(will)33 b(dra)o(w)g(the)g(stack)h(required)f(to)g(implement)f(the)h +(speci\002ed)h(production)e(rule)i(with)e(width)h(20.)56 +b(The)0 2748 y(function)24 b(tak)o(es)g(a)h(gate)g(width)f(and)g(a)h +(single)f(production)g(rule)g(as)h(its)f(ar)n(guments.)30 +b(Note)25 b(that)f(the)g(production)0 2868 y(rules)h(must)e(be)i(in)g +(ne)o(gation)e(normal)h(form,)g(i.e.,)h(all)f(ne)o(gations)f(must)h(be) +h(on)f(v)n(ariables.)146 2989 y(Contacts)32 b(can)h(be)f(shared)h +(between)f(operators)g(by)g(pro)o(viding)e(a)j(list)e(of)h(production)f +(rules)h(as)g(input)f(to)0 3109 y Fc(prs.mgn)p Fe(,)25 +b(as)g(follo)n(ws:)900 3338 y Fc(\(prs.mgn)h(40)e(20)1559 +3338 y +(") show + 1559 3338 a 59 w Fc(x)h(&)g(y)g Fb(\000)j Fa(>)d +Fc(z-)2159 3338 y +(") show + 2159 3338 a 2244 3338 a +(") show + 2244 3338 a +60 w Fc(u)g(&)g(v)f Fb(\000)29 b Fa(>)24 b Fc(w-)2877 +3338 y +(") show + 2877 3338 a 2962 3338 a +(") show + 2962 3338 a 60 w Fc(\230x)h(&)g(\230y)g +Fb(\000)j Fa(>)d Fc(z+)3653 3338 y +(") show + 3653 3338 a 59 w Fc(\))146 +3566 y Fe(The)g(contact)g(to)f(GND)h(will)f(be)h(shared)g(between)g +(the)f(pull-do)n(wn)f(stacks)i(for)g(z)g(and)g(w)-6 b(.)146 +3686 y(Both)37 b(production-rule)e(dra)o(wing)g(function)h(ensure)g +(that)g(the)g(v)n(ariable)g(order)h(in)f(the)g(production)f(rule)0 +3807 y(\(from)g(left)f(to)g(right\))g(corresponds)g(to)h(the)f(gate)g +(order)h(in)f(the)h(transistor)e(stacks)h(\(from)h(po)n(wer)f(supply)f +(to)0 3927 y(output\).)146 4047 y(It)27 b(is)e(not)h(al)o(w)o(ays)g +(possible)f(to)h(directly)f(dra)o(w)h(a)h(production)e(rule)h(in)g(a)h +(single)e(stack)h(with)g(no)f(additional)0 4168 y(internal)f(contacts.) +31 b(In)25 b(this)g(case,)g(the)g(function)f(creates)i(an)f(internal)f +(node)h(name)g(of)g(the)g(form)g(\223)p 3449 4168 30 +4 v 36 w(\224)g(follo)n(wed)0 4288 y(by)j(a)h(number)-5 +b(.)41 b(Y)-11 b(ou)28 b(can)h(search)g(for)g(these)g(using)e +Fc(\(label.sear)n(ch)2396 4288 y +(") show + 2396 4288 a 2461 4288 +30 4 v 95 w Fc(*)2541 4288 y +(") show + 2541 4288 a 60 w Fc(\))p +Fe(,)i(follo)n(wed)f(by)g Fc(\(label.\002nd-next\))p +Fe(.)0 4408 y(T)-8 b(o)25 b(complete)f(the)g(implementation,)f(you)h +(will)g(ha)n(v)o(e)g(to)h(wire)g(up)f(these)h(internal)f(contacts)h(as) +f(well.)146 4529 y(Both)e Fc(prs.mgn)g Fe(and)g Fc(prs.draw)g +Fe(dra)o(w)f(the)h(transistor)e(stacks)h(using)g Fc(stack.p)h +Fe(and)g Fc(stack.n)p Fe(.)30 b(The)22 b(v)n(ariants)0 +4649 y Fc(prs.tallmgn)j Fe(and)g Fc(prs.talldraw)f Fe(use)h +Fc(stack.tallp)g Fe(and)g Fc(stack.talln)g Fe(instead.)1875 +5649 y(\2262\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tutscm4.ps b/doc/psfiles/tutscm4.ps new file mode 100644 index 00000000..6bf4f37e --- /dev/null +++ b/doc/psfiles/tutscm4.ps @@ -0,0 +1,232 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tutscm4.dvi +%%Pages: 1 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tutscm4.dvi -o tutscm4.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tutscm4.dvi) +@start /Fa 138[66 40 47 53 2[60 66 100 33 2[33 66 2[53 +66 53 1[60 12[80 6[113 9[86 8[40 55[66 2[{ + TeXBase1Encoding ReEncodeFont }19 119.999948 /Times-Bold +rf /Fb 105[50 28[50 2[50 50 28 39 33 1[50 50 50 78 28 +2[28 50 50 33 44 50 44 1[44 12[61 55 2[55 2[89 3[33 4[72 +66 1[72 6[28 50 1[50 1[50 2[50 50 2[25 33 25 8[50 35[{ + TeXBase1Encoding ReEncodeFont }38 100.000003 /Times-Roman +rf /Fc 139[28 1[39 2[50 50 3[28 28 50 2[44 3[50 14[61 +3[66 83 35[33 33 40[{ TeXBase1Encoding ReEncodeFont }14 +100.000003 /Times-Italic rf /Fd 138[80 48 56 64 2[72 +80 1[40 2[40 80 72 1[64 80 64 1[72 12[96 80 5[135 3[56 +14[48 5[72 2[72 3[48 9[72 32[80 2[{ TeXBase1Encoding ReEncodeFont }24 +143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 709 101 a Fd(Magic)35 b(T)-13 b(utorial)34 b(#S-4:)43 +b(The)35 b(design)g(rule)g(\002le)1655 521 y Fc(Rajit)24 +b(Manohar)1296 941 y Fb(Deparment)g(of)h(Computer)g(Science)1271 +1062 y(California)g(Institute)f(of)h(T)-7 b(echnology)1534 +1182 y(P)o(asadena,)25 b(CA)h(91125)1053 1453 y(This)e(tutorial)g +(corresponds)g(to)g(Magic)h(v)o(ersion)e(7.)0 1981 y +Fa(T)-11 b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 +2184 y Fb(Magic)24 b(T)l(utorial)g(#S-1:)31 b(The)24 +b(scheme)h(command-line)f(interpreter)0 2388 y Fa(Commands)29 +b(intr)n(oduced)j(in)f(this)f(tutorial:)300 2591 y Fb(:drc.)0 +2795 y Fa(Macr)n(os)f(intr)n(oduced)i(in)g(this)f(tutorial:)300 +3023 y Fc(\(None\))0 3620 y Fd(1)143 b(Intr)m(oduction)1875 +5649 y Fb(\2261\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tuttcl1.ps b/doc/psfiles/tuttcl1.ps new file mode 100644 index 00000000..b2c8ffed --- /dev/null +++ b/doc/psfiles/tuttcl1.ps @@ -0,0 +1,862 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: tuttcl1.dvi +%%Pages: 9 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman Courier +%%+ Times-BoldItalic +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -t letter tuttcl1.dvi -o ../psfiles/tuttcl1.ps +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2006.04.12:1204 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: texps.pro +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type/integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics/Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{ +dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 +roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def +dup[exch{dup CharStrings exch known not{pop/.notdef/Encoding true def} +if}forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def} +def end + +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tuttcl1.dvi) +@start /Fa 135[50 2[55 28 39 39 1[50 50 55 78 28 2[28 +55 50 1[44 50 44 50 50 9[89 1[72 61 55 5[89 3[39 1[72 +1[66 72 66 66 7[33 3[50 50 50 1[50 50 3[33 45[{ +TeXBase1Encoding ReEncodeFont}36 99.6264 /Times-BoldItalic +rf +%DVIPSBitmapFont: Fb cmsy10 12 2 +/Fb 2 104 df102 D<12FEEAFFE0EA07F8EA00FEEB7F806D7E6D7E130F6D7EA26D7EB3AD6D7EA26D7E +806E7E6E7EEC0FE0EC03FC913800FFE0A2913803FC00EC0FE0EC3FC04A5A4AC7FC5C495A +A2495AB3AD495AA2495A131F495A495A01FEC8FCEA07F8EAFFE048C9FC236479CA32>I +E +%EndDVIPSBitmapFont +/Fc 134[50 50 72 50 55 33 39 44 1[55 50 55 83 28 55 1[28 +55 50 33 44 55 44 55 50 3[33 1[33 3[100 2[66 55 2[61 +78 1[94 66 2[39 78 78 61 66 72 72 66 72 6[33 2[50 50 +50 50 1[50 50 50 28 25 33 1[57 50 5[50 33[55 2[{ +TeXBase1Encoding ReEncodeFont}56 99.6264 /Times-Bold +rf /Fd 135[60 60 60 60 60 60 60 1[60 60 60 60 60 60 1[60 +60 60 60 60 60 60 60 60 10[60 1[60 1[60 2[60 60 60 4[60 +60 1[60 60 60 60 60 3[60 1[60 60 3[60 1[60 1[60 60 60 +60 60 60 60 2[60 60 40[{TeXBase1Encoding ReEncodeFont}49 +99.6264 /Courier rf /Fe 105[50 1[44 44 24[44 50 50 72 +50 50 28 39 33 50 50 50 50 78 28 50 28 28 50 50 33 44 +50 44 50 44 33 6[72 72 94 1[72 61 55 66 1[55 72 72 89 +61 72 39 33 72 72 55 61 72 66 66 72 1[44 3[28 28 50 50 +50 50 50 50 50 50 50 50 28 25 33 25 2[33 33 33 1[83 1[50 +1[33 29[55 55 2[{TeXBase1Encoding ReEncodeFont}78 99.6264 +/Times-Roman rf /Ff 134[44 1[66 44 1[28 39 39 1[50 50 +50 72 28 44 1[28 50 50 1[44 50 44 50 50 3[39 8[55 50 +61 12[61 72 66 1[61 14[50 50 2[25 33 3[33 33 2[83 1[50 +35[{TeXBase1Encoding ReEncodeFont}36 99.6264 /Times-Italic +rf /Fg 134[72 72 104 1[80 48 56 64 1[80 72 80 120 40 +80 1[40 80 72 48 64 80 64 80 72 9[143 2[96 80 5[135 3[56 +1[112 88 96 104 104 96 2[72 4[48 3[72 72 72 72 72 72 +3[48 36 8[72 35[{TeXBase1Encoding ReEncodeFont}44 143.462 +/Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%BeginPaperSize: Letter +letter +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 850 101 a Fg(Magic)35 b(Tcl)g(T)-13 b(utorial)34 +b(#1:)44 b(Intr)m(oduction)1546 521 y Ff(R.)25 b(T)-5 +b(imothy)24 b(Edwar)l(ds)1583 941 y Fe(Space)i(Department)1434 +1062 y(Johns)e(Hopkins)g(Uni)n(v)o(ersity)1391 1182 y(Applied)g +(Physics)g(Laboratory)1578 1303 y(Laurel,)h(MD)f(20723)819 +1573 y(This)g(tutorial)g(corresponds)g(to)h(Tcl-based)f(Magic)h(v)o +(ersion)e(7.2)0 2287 y Fg(1)143 b(What)36 b(is)f(Tcl-based)f(Magic,)h +(and)g(Wh)n(y?)0 2511 y Fe(In)30 b(Magic)f(v)o(ersion)f(7.0,)i(Rajit)f +(Manohar)g(incorporated)g(a)h(SCHEME)g(interpreter)f(into)g(the)g +(Magic)g(source,)0 2631 y(noting)h(the)i(limitation)d(of)j(magic)f(to)g +(handle)h(de\002nitions)e(and)i(v)n(ariables,)g(conditionals,)f(and)h +(block)f(struc-)0 2752 y(tures.)56 b(By)33 b(embedding)f(an)h +(interpreter)h(into)e(the)h(code,)i(the)e(interpreter')-5 +b(s)33 b(functions)f(are)i(made)f(a)n(v)n(ailable)0 2872 +y(on)k(the)h(magic)f(command)g(line,)k(making)36 b(magic)i(e)o +(xtensible.)68 b(The)38 b(SCHEME)g(interpreter)f(and)h(v)n(arious)0 +2992 y(e)o(xtensions)29 b(incorporated)i(into)f(loadable)h(scripts)f +(are)i(outlined)e(in)g(the)h(tutorials)f Fd(tutscm1.ps)f +Fe(through)0 3113 y Fd(tutscm4.ps)p Fe(.)146 3233 y(While)19 +b(making)g(Magic)g(considerably)g(more)g(\003e)o(xible,)h(the)f +(embedded)g(SCHEME)h(interpreter)f(had)h(some)0 3354 +y(notable)25 b(dra)o(wbacks.)32 b(The)25 b(primary)g(one)g(is)g(that)g +(the)g(SCHEME)g(language)g(is)g(syntactically)f(dif)n(ferent)h(from)0 +3474 y(Magic')-5 b(s)33 b(command-line)f(syntax.)57 b(Also,)35 +b(the)f(interpreter)g(is)f(lar)n(gely)h(disconnected)f(from)g(the)h +(code,)i(and)0 3594 y(does)25 b(not)f(af)n(fect)h(or)g(e)o(xtend)f(the) +g(graphics)h(or)g(handle)f(results)g(from)h(magic)f(commands.)146 +3715 y(Be)o(ginning)h(in)g(Magic)g(v)o(ersion)f(7.2,)h(Magic)g(has)h +(been)f(recast)h(into)f(a)g(frame)n(w)o(ork)g(called)h +Ff(ScriptED)m(A)p Fe(,)d(in)0 3835 y(which)28 b(e)o(xisting)e +(applications)h(become)h Fc(extensions)h Fe(of)f(an)g(interpreter)h +(rather)f(than)g(ha)n(ving)g(an)g(interpreter)0 3955 +y(embedded)22 b(in)f(the)h(application.)29 b(The)22 b(main)f(adv)n +(antage)h(of)g(e)o(xtending)f(o)o(v)o(er)g(embedding)g(is)h(that)f(the) +h(applica-)0 4076 y(tion)j(becomes)h(a)g(module)f(of)h(the)g +(interpreter)g(language,)g(which)g(does)f(not)h(preclude)g(the)g(use)g +(of)g(additional,)0 4196 y(unrelated)e(modules)f(in)h(the)h(same)f +(interpreti)n(v)o(e)f(en)l(vironment.)29 b(F)o(or)24 +b(e)o(xample,)g(in)g(Tcl-based)g(Magic,)g(graph-)0 4317 +y(ics)31 b(are)h(handled)e(by)h(Tk)g(\(the)g(primary)f(graphics)h +(package)h(for)f(use)g(with)f(Tcl\),)j(and)e(applications)e(such)i(as)0 +4437 y(IRSIM)d(\(the)g(digital)e(simulator\))g(can)i(be)g(run)f(as)h +(if)f(the)o(y)g(were)h(an)f(e)o(xtension)f(of)i(magic)f(itself.)38 +b(Commands)0 4557 y(for)28 b(Tcl,)g(Tk,)g(IRSIM,)g(BL)-9 +b(T)i(,)28 b(and)f(an)o(y)g(other)h(Tcl-based)f(package)h(can)g(be)g +(mix)o(ed)e(on)h(the)h(magic)f(command)0 4678 y(line.)146 +4798 y(While)g Ff(ScriptED)m(A)f Fe(suggests)g(the)h(use)h(of)f(the)h +Fc(SWIG)e Fe(package)i(to)f(gi)n(v)o(e)f(applications)g(the)i(ability)e +(to)h(be)0 4918 y(compiled)33 b(as)h(e)o(xtensions)e(of)i(an)o(y)f +(interpreter)h(\(Tcl,)i(Python,)f(SCHEME,)f(Perl,)j(etc.\),)f(there)e +(are)h(speci\002c)0 5039 y(adv)n(antages)24 b(to)h(tar)n(geting)g(Tcl.) +32 b(F)o(oremost,)24 b(the)h(syntax)f(of)h(Tcl)h(is)e(virtually)g +(100\045)h(compatible)f(with)g(that)h(of)0 5159 y(Magic.)43 +b(This)28 b(is)h(not)f(coincidentally)g(because)h(both)f(Magic)h(and)g +(Tcl)g(were)h(written)e(by)h(John)f(Ousterhout!)0 5280 +y(Man)o(y)23 b(ideas)h(from)g(the)g(de)n(v)o(elopment)e(of)i(Magic)g +(were)h(incorporated)f(into)f(the)h(o)o(v)o(erall)f(concept)h(and)g +(design)0 5400 y(of)h(the)g(Tcl)f(interpreter)h(language.)1875 +5649 y(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fe(April)24 b(12,)h(2006)1886 b(Magic)24 +b(Tcl)h(T)l(utorial)e(#1:)30 b(Introduction)146 68 y(Lar)n(gely)19 +b(due)g(to)g(the)f(syntactical)g(compatibility)-6 b(,)17 +b(Tcl-based)i(magic)f(is)h(completely)e(backw)o(ardly-compatible)0 +188 y(with)30 b(the)h(non-interpreter)f(v)o(ersion)g(of)h(magic.)49 +b(Either)30 b(can)i(be)f(selected)g(at)g(compile-time,)f(in)h(addition) +e(to)0 309 y(compiling)f(with)h(embedded)h(SCHEME,)g(which)f(has)h +(been)g(retained)g(in)f(full)h(as)g(an)g(option.)44 b(A)30 +b(fe)n(w)g(minor)0 429 y(issues,)24 b(such)g(as)g(the)h(appearance)g +(of)g(the)f(cursor)g(when)h(magic)f(is)g(used)g(without)f(a)i(Tk)f +(console)g(windo)n(w)-6 b(,)22 b(are)0 549 y(addressed)j(belo)n(w)-6 +b(.)146 670 y(Magic)28 b(e)o(xtensions)d(under)j(Tcl)f(are)h +(considerable,)g(and)g(e)o(xplanations)d(of)j(the)f(features)h(ha)n(v)o +(e)g(been)f(split)0 790 y(into)d(se)n(v)o(eral)g(tutorial)g(\002les,)h +(as)f(listed)g(in)h(T)-8 b(able)24 b(1.)p 837 916 2227 +4 v 835 1036 4 121 v 887 1000 a(Magic)g(Tcl)h(T)l(utorial)e(#1:)30 +b(Introduction)p 3061 1036 V 835 1156 V 887 1120 a(Magic)24 +b(Tcl)h(T)l(utorial)e(#2:)30 b(The)25 b(GUI)g(Wrapper)p +3061 1156 V 835 1277 V 887 1241 a(Magic)f(Tcl)h(T)l(utorial)e(#3:)30 +b(Extraction)24 b(and)h(Netlisting)p 3061 1277 V 835 +1397 V 887 1361 a(Magic)f(Tcl)h(T)l(utorial)e(#4:)30 +b(Simulation)24 b(with)g(IRSIM)p 3061 1397 V 835 1518 +V 887 1481 a(Magic)g(Tcl)h(T)l(utorial)e(#5:)30 b(Writing)24 +b(Tcl)h(Scripts)g(for)g(Magic)p 3061 1518 V 837 1521 +2227 4 v 782 1788 a(T)-8 b(able)25 b(1:)30 b(The)25 b(Magic)f(Tcl)h +(tutorials)f(and)g(other)h(documentation.)0 2241 y Fg(2)143 +b(F)l(eatur)m(es)35 b(of)g(Tcl-based)f(Magic)0 2465 y +Fe(In)22 b(summary)-6 b(,)21 b(the)h(features)g(of)g(Tcl-based)g(Magic) +g(\(corresponding)f(to)h(Magic)g(v)o(ersion)f(7.2,)h(re)n(vision)e +(31\))i(are)0 2585 y(as)j(follo)n(ws:)120 2797 y(1.)49 +b(The)25 b(command)g(name)g Fc(magic)h Fe(itself)e(is)i(a)f(script,)h +(not)f(a)g(compiled)g(e)o(x)o(ecutable.)32 b(The)25 b(script)g +(launches)244 2917 y(Tcl)32 b(and)h(gi)n(v)o(es)e(it)h(the)h(name)f(of) +h(a)g(Tcl)g(script)f(to)g(e)n(v)n(aluate)g(\()p Fd(magic.tcl)p +Fe(\).)52 b(The)33 b(Tcl)g(script)f(loads)244 3038 y(Magic)k(as)g(an)h +(e)o(xtension)e(of)h(Tcl)h(and)f(performs)g(all)g(other)h(operations)e +(necessary)i(to)f(start)g(up)g(the)244 3158 y(application.)120 +3357 y(2.)49 b(Command-line)31 b(ar)n(guments)g(passed)h(to)f(Magic)h +(ha)n(v)o(e)f(been)i(changed.)52 b(Some)32 b(older)l(,)h(unused)f(ar)n +(gu-)244 3478 y(ments)24 b(ha)n(v)o(e)g(been)h(remo)o(v)o(ed.)30 +b(Se)n(v)o(eral)24 b(ar)n(guments)h(ha)n(v)o(e)f(been)h(added,)g(as)g +(follo)n(ws:)299 3677 y(\(a\))49 b Fd(-noconsole)23 b +Fe(Normally)-6 b(,)22 b(under)j(Tcl/Tk,)e(Magic)h(starts)g(by)g +(launching)f(a)i(Tk-based)f(console)458 3798 y(windo)n(w)i(\()p +Fd(tkcon.tcl)p Fe(\))f(which)i(is)f(the)h(windo)n(w)e(that)i(accepts)g +(magic)f(commands.)36 b(Pre)n(vious)458 3918 y(v)o(ersions)27 +b(of)i(Magic)f(accepted)g(commands)f(from)h(the)g(calling)g(terminal.) +40 b(The)28 b(former)h(style)e(of)458 4038 y(running)20 +b(commands)g(from)g(the)h(calling)f(terminal)g(can)h(be)g(selected)g +(by)f(choosing)g(this)g(ar)n(gument)458 4159 y(at)26 +b(runtime.)32 b(Note,)25 b(ho)n(we)n(v)o(er)l(,)f(that)h(due)g(to)g +(fundamental)g(dif)n(ferences)h(in)f(the)g(underlying)f(input)458 +4279 y(routines)30 b(between)g(Tcl)g(and)h(magic,)g(the)f +(terminal-based)g(command)f(entry)h(does)g(not)g(e)o(xactly)458 +4400 y(match)38 b(the)g(original)f(beha)n(vior)g(of)h(magic.)70 +b(In)38 b(particular)l(,)j(the)d(background)f(DRC)i(function)458 +4520 y(does)27 b(not)g(change)g(the)g(prompt.)36 b(In)27 +b(addition,)f(\223Xterm\224)h(consoles)g(must)e(select)i(option)f(\223) +-8 b(Allo)n(w)458 4640 y(SendEv)o(ents\224)21 b(for)g(k)o(e)o(ystrok)o +(es)f(to)g(be)h(echoed)g(from)g(the)g(layout)f(windo)n(w)g(into)g(the)h +(terminal.)28 b(F)o(or)458 4761 y(security)d(reasons,)f(the)h +(application)f(cannot)g(change)h(this)f(option)g(on)g(the)h(terminal.) +294 4918 y(\(b\))48 b Fd(-wrapper)22 b Fe(T)-8 b(o)23 +b(enforce)h(backw)o(ard-compatibility)-6 b(,)20 b(magic)j(appears)h(as) +f(it)f(w)o(ould)h(without)e(the)458 5039 y(Tcl)29 b(interpreter)f +(\(apart)h(from)f(the)g(te)o(xt)f(entry)h(console\))g(when)g(launched)g +(with)f(the)i(same)f(ar)n(gu-)458 5159 y(ments.)38 b(Ho)n(we)n(v)o(er)l +(,)26 b(most)g(users)i(will)e(w)o(ant)h(to)g(mak)o(e)g(use)g(of)h(the)f +(e)o(xtensions)e(and)j(con)l(v)o(enience)458 5280 y(functions)j(pro)o +(vided)g(by)h(the)g(\223wrapper\224)h(GUI.)f(These)g(functions)f(are)i +(detailed)f(in)f(a)i(separate)458 5400 y(tutorial)24 +b(\(see)i(T)l(utorial)d(#2\).)1875 5649 y(\2262\226)p +eop +%%Page: 3 3 +3 2 bop 0 -180 a Fe(Magic)24 b(Tcl)h(T)l(utorial)f(#1:)30 +b(Introduction)1885 b(April)24 b(12,)h(2006)120 68 y(3.)49 +b(Magic-related)34 b(programs)h(\223e)o(xt2spice\224)f(and)g(\223e)o +(xt2sim\224)g(ha)n(v)o(e)g(been)h(recast)g(as)g(magic)f(commands)244 +188 y(instead)25 b(of)g(standalone)f(e)o(x)o(ecutables.)32 +b(This)24 b(mak)o(es)h(a)h(good)e(deal)i(of)f(sense,)h(as)f(both)f +(programs)h(mak)o(e)244 309 y(hea)n(vy)36 b(use)h(of)f(the)g(magic)g +(internal)g(database.)66 b(Most)35 b(v)n(alues)h(required)g(to)g +(produce)h(netlists)d(were)244 429 y(passed)28 b(through)f(the)h +(intermediary)g(\002le)g(format)g Fd(.ext)p Fe(.)40 b(Ho)n(we)n(v)o(er) +l(,)28 b(not)g(all)g(necessary)g(v)n(alues)f(were)244 +549 y(included)d(in)g(the)g Fd(.ext)g Fe(\002le)h(format)f +(speci\002cation,)h(and)f(some)g(of)h(these)f(missing)f(v)n(alues)h +(were)h(hard-)244 670 y(coded)j(into)e(the)i(programs)f(where)h(the)o +(y)f(ha)n(v)o(e)g(since)g(become)h(mismatched)e(to)h(the)h(magic)f +(database.)244 790 y(This)g(has)h(been)g(corrected)g(so)g(that)f(all)h +(netlist)e(output)h(corresponds)g(to)g(the)h(technology)f(\002le)h +(used)f(by)244 911 y(a)e(layout.)244 1071 y(Both)g(commands)e(\223e)o +(xt2spice\224)h(and)h(\223e)o(xt2sim\224)e(allo)n(w)h(all)h(of)f(the)h +(command-line)e(ar)n(guments)i(pre)n(vi-)244 1192 y(ously)f(accepted)h +(by)g(the)f(standalone)g(programs.)30 b(Some)25 b(of)g(the)g(more)f +(common)g(functions,)g(ho)n(we)n(v)o(er)l(,)244 1312 +y(ha)n(v)o(e)36 b(been)h(duplicated)e(as)i(command)e(options)g(in)h +(the)g(usual)g(format)g(of)h(magic)f(commands.)64 b(F)o(or)244 +1432 y(instance,)24 b(one)h(may)f(use)h(the)g(magic)f(command:)1144 +1668 y Fc(ext2sim)g(help)244 1904 y Fe(to)g(get)h(more)g(information)e +(on)h Fd(ext2sim)g Fe(command-line)f(options.)120 2105 +y(4.)49 b(All)25 b(Tcl)g(interpreter)h(procedures)f(may)g(be)h(freely)g +(mix)o(ed)e(with)g(magic)h(commands)g(on)g(the)g(command)244 +2225 y(line.)53 b(F)o(or)32 b(instance,)i(a)e(user)h(can)g(use)f(Tcl)g +(to)g(compute)g(arithmetic)f(e)o(xpressions)g(on)h(the)g(command)244 +2345 y(line:)1144 2581 y Fc(copy)25 b(e)g([expr)p Fb(f)p +Fc(276)g(*)g(5)g(+)f(4)p Fb(g)p Fc(])120 2817 y Fe(5.)49 +b(A)31 b(number)g(of)h(magic)f(commands)f(pass)h(v)n(alues)f(back)i(to) +f(the)g(interpreter)-5 b(.)50 b(F)o(or)32 b(instance,)g(the)f(com-)244 +2937 y(mand)1144 3173 y Fc(box)25 b(v)o(alues)244 3409 +y Fe(returns)j(the)g(lo)n(wer)f(left-)h(and)g(upper)g(right-hand)f +(coordinates)h(of)g(the)g(cursor)g(box)f(in)h(magic)g(internal)244 +3529 y(units.)h(This)23 b(return)g(v)n(alue)g(can)g(be)h(incorporated)f +(into)f(an)i(e)o(xpression,)e(such)h(as)h(the)f(one)g(belo)n(w)g(which) +244 3649 y(mo)o(v)o(es)g(the)i(box)f(to)g(the)h(left)g(by)f(the)h(v)n +(alue)f(of)h(its)f(o)n(wn)g(width:)1144 3885 y Fc(set)h(b)o(box)g([box) +g(v)o(alues])1144 4005 y(set)g(bwidth)h(expr)f Fb(f)p +Fc([lindex)h($b)o(box)f(2])g(-)g([lindex)g($b)o(box)g(0])p +Fb(g)p Fc(])1144 4126 y(mo)o(v)o(e)g(e)g($bwidth)120 +4362 y Fe(6.)49 b(Magic)34 b(prompts)e(for)j(te)o(xt)e(ha)n(v)o(e)g +(been)i(recast)f(as)g(Tk)g(dialog)f(box)o(es.)57 b(F)o(or)34 +b(instance,)i(the)e(command)244 4482 y Fc(writeall)f +Fe(will)g(pop)g(up)h(a)g(dialog)e(box)i(with)f(\002)n(v)o(e)g(b)n +(uttons,)h(one)g(for)g(each)g(of)g(the)f(a)n(v)n(ailable)g(choices)244 +4602 y(\(write,)25 b(\003ush,)f(skip,)g(abort,)h(and)f(auto\).)120 +4803 y(7.)49 b(IRSIM)33 b(is)e(no)g(longer)h(a)n(v)n(ailable)f(as)h(a)g +(\223mode\224)g(reached)g(by)g(switching)e(tools)h(by)h(command)e(or)i +(the)244 4924 y(space-bar)i(macro.)54 b(Instead,)35 b(IRSIM)f(\(v)o +(ersion)e(9.6\))g(can)i(be)f(compiled)e(as)i(a)h(Tcl)e(e)o(xtension)g +(in)g(the)244 5044 y(same)f(manner)h(as)g(Magic,)h(at)e(compile)g +(time.)51 b(When)32 b(this)e(is)i(done,)h(IRSIM)f(is)f(in)l(v)n(ok)o +(ed)g(simply)f(by)244 5164 y(typing)1144 5400 y Fc(irsim)1875 +5649 y Fe(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fe(April)24 b(12,)h(2006)1886 b(Magic)24 +b(Tcl)h(T)l(utorial)e(#1:)30 b(Introduction)244 68 y(on)36 +b(the)g(Magic)f(command)g(line.)64 b(IRSIM)37 b(is)f(loaded)g(as)g(a)g +(Tcl)g(package,)j(and)e(IRSIM)f(and)g(Magic)244 188 y(commands)23 +b(may)i(be)g(freely)g(mix)o(ed)f(on)g(the)h(Magic)f(command)g(line:) +1144 481 y Fc(assert)h([getnode])244 775 y Fe(IRSIM)33 +b(does)e(not)h(require)g(the)g(name)g(of)g(a)g(\002le)g(to)g(start.)52 +b(W)l(ithout)30 b(ar)n(guments,)j(it)f(will)f(assume)g(the)244 +895 y(currently)36 b(loaded)h(cell)g(is)f(to)h(be)f(simulated,)j(and)e +(it)f(will)g(generate)h(the)g Fd(.sim)f Fe(\002le)h(if)g(it)f(does)h +(not)244 1015 y(already)25 b(e)o(xist.)120 1256 y(8.)49 +b(In)25 b(addition)g(to)g(IRSIM,)h(programs)f Fc(xcir)n(cuit)h +Fe(and)g Fc(netgen)g Fe(can)g(be)g(compiled)e(as)i(Tcl)f(e)o(xtensions) +f(and)244 1376 y(pro)o(vide)g(cabability)f(for)j(schematic)e(capture)h +(and)g(layout-vs.-schematic,)e(respecti)n(v)o(ely)-6 +b(.)120 1617 y(9.)49 b(Tcl-based)34 b(Magic)g(mak)o(es)h(use)f(of)h +(the)f(Tcl)g(v)n(ariable)g(space.)61 b(F)o(or)34 b(instance,)i(it)e(k)o +(eeps)h(track)g(of)f(the)244 1737 y(installation)28 b(directory)h +(through)g(the)h(v)n(ariable)f Fd(CAD)p 2132 1737 30 +4 v 35 w(HOME)p Fe(,)g(which)h(mirrors)f(the)h(v)n(alue)f(of)h(the)g +(shell)244 1858 y(en)l(vironment)35 b(v)n(ariable)i(of)f(the)h(same)g +(name.)66 b(In)37 b(addition,)h(it)e(mak)o(es)h(use)f(of)h(v)n +(ariables)f Fd(VDD)g Fe(and)244 1978 y Fd(GND)23 b Fe(in)g(the)h +(technology)e(\002le)j(to)e(aid)g(in)h(the)f(e)o(xtraction)g(of)h +(substrate-)f(and)h(well-connected)f(nodes)g(on)244 2098 +y(transistors.)71 2339 y(10.)48 b(Magic)30 b(input)g(\002les,)j(such)d +(as)h(the)g Fd(.magic)f Fe(startup)g(\002le,)i(are)g(sourced)f(as)g +(Tcl)g(scripts,)g(and)g(so)f(may)244 2459 y(themselv)o(es)23 +b(contain)h(a)h(mixture)f(of)h(Tcl)g(and)g(magic)f(commands.)0 +2846 y Fg(3)143 b(Compilation)33 b(and)i(Installation)0 +3085 y Fe(Magic)24 b(is)h(selected)g(for)g(compilation)e(as)h(a)i(Tcl)e +(e)o(xtention)g(when)g(running)g(the)900 3333 y Fc(mak)o(e)h(con\002g)0 +3574 y Fe(script.)64 b(The)36 b(\002rst)h(question)e(asks)g(whether)i +(magic)e(should)g(be)i(compiled)e(as)h(a)g(Tcl)g(e)o(xtension,)i(with)d +(the)0 3694 y(SCHEME)k(interpreter)g(embedded,)k(or)c(as)g(the)g +(original)f(v)o(ersion)g(with)h(no)g(interpreter)-5 b(.)73 +b(Subsequent)38 b(to)0 3814 y(choosing)30 b(Tcl)h(as)h(the)f +(interpreter)g(and)g(answering)g(the)g(remaining)f(con\002guration)h +(questions,)g(Tcl)g(should)0 3935 y(be)25 b(compiled)f(and)g(installed) +g(using)g(the)g(commands)900 4183 y Fc(mak)o(e)h(tcl)0 +4423 y Fe(and)900 4671 y Fc(mak)o(e)g(install-tcl)0 4912 +y Fe(Note)g(that)f(if)h(magic)f(is)g(to)h(be)g(compiled)f(under)g(dif)n +(ferent)h(interpreters,)f(it)h(is)f(necessary)h(to)f(perform)900 +5159 y Fc(mak)o(e)h(clean)0 5400 y Fe(between)g(the)g(compilations,)d +(so)j(that)f(all)g(references)j(to)d(the)h(last)f(compiled)g(v)o +(ersion)f(are)j(deleted.)1875 5649 y(\2264\226)p eop +%%Page: 5 5 +5 4 bop 0 -180 a Fe(Magic)24 b(Tcl)h(T)l(utorial)f(#1:)30 +b(Introduction)1885 b(April)24 b(12,)h(2006)0 99 y Fg(4)143 +b(Dual-Sour)m(ce)34 b(Input)g(and)h(Backward)f(Compatibility)0 +494 y Fe(From)24 b(its)e(inception,)h(Magic)g(has)h(used)f(an)h(unsual) +f(b)n(ut)g(v)o(ery)g(ef)n(fecti)n(v)o(e)g(interf)o(ace)h(in)f(which)g +(commands)f(may)0 615 y(be)k(passed)g(to)g(the)g(program)g(from)g(tw)o +(o)g(dif)n(ferent)g(sources,)g(the)g(layout)g(windo)n(w)-6 +b(,)24 b(and)i(the)h(calling)e(terminal.)0 735 y(K)n(e)o(ystrok)o(es)30 +b(in)i(the)g(layout)f(windo)n(w)f(are)j(handled)e(by)h(the)g(graphics)f +(package.)53 b(These)32 b(are)g(interpreted)g(as)0 856 +y Ff(macr)l(os)p Fe(.)d(The)24 b(k)o(e)o(ystrok)o(e)f(v)n(alues)g(are)h +(e)o(xpanded)f(into)g(magic)h(command-line)e(commands)h(and)g(e)o(x)o +(ecuted)g(by)0 976 y(the)f(command-line)e(command)h(dispatcher)g +(routine.)29 b(T)-8 b(w)o(o)22 b(macros,)g(`)p Fd(.)p +Fe(')30 b(and)22 b(`)p Fd(:)p Fe(')29 b(are)23 b(reserv)o(ed:)29 +b(The)21 b(period)0 1096 y(e)o(xpands)k(to)g(the)g(last)g(command)f(e)o +(x)o(ecuted)h(from)g(the)h(command)e(line)h(\()p Ff(not)g +Fe(from)g(a)h(macro)g(e)o(xpansion\),)e(and)0 1217 y(the)33 +b(colon)h(initiates)e(a)i(redirection)f(of)h(k)o(e)o(ystrok)o(es)e +(from)h(the)h(layout)f(windo)n(w)f(into)h(the)g(calling)g(terminal.)0 +1337 y(Magic)c(users)g(quickly)f(get)h(used)g(to)g(the)g(combination)f +(of)h(k)o(e)o(ystrok)o(es,)g(mouse)g(functions,)g(and)g(command-)0 +1458 y(line)24 b(commands.)146 1661 y(In)39 b(the)f(Tcl-based)h(v)o +(ersion)e(of)i(Magic,)i(the)e(command-line)e(dispatching)g(is)h(gi)n(v) +o(en)f(o)o(v)o(er)h(entirely)f(to)0 1781 y(Tcl,)g(and)d(the)h +(dispatching)e(of)i(k)o(e)o(ystrok)o(e)e(e)n(v)o(ents)g(in)i(the)f +(layout)g(windo)n(w)f(is)h(gi)n(v)o(en)f(o)o(v)o(er)h(entirely)g(to)g +(Tk.)0 1901 y(Unfortunately)-6 b(,)38 b(in)f(relinquishing)e(these)i +(duties,)i(Magic)d(loses)g(some)h(of)g(the)f(ef)n(fecti)n(v)o(eness)g +(of)h(its)f(dual-)0 2022 y(source)21 b(input)g(model.)28 +b(One)22 b(aspect)f(of)h(this)e(is)h(that)g(Tcl)g(is)g(a)h(line-based)f +(interpreter)l(,)h(and)f(does)g(not)g(recognize)0 2142 +y(an)o(ything)h(on)i(the)g(command)f(line)h(until)e(the)i(return)g(k)o +(e)o(y)g(has)g(been)g(pressed)g(and)g(the)g(entire)g(line)f(is)h +(passed)f(to)0 2263 y(the)e(command)g(dispatcher)g(routine.)29 +b(W)l(ithout)20 b(an)o(y)h(understanding)f(of)i(character)n(-based)h +(input,)e(it)g(is)g(dif)n(\002cult)0 2383 y(to)k(impossible)e(to)i +(directly)f(edit)h(the)g(command)f(line)h(from)g(outside)f(the)h +(calling)g(terminal,)f(because)i(it)e(is)h(the)0 2503 +y(terminal,)f(and)h(not)f(Tcl,)g(which)h(interprets)f(k)o(e)o(ystrok)o +(es)g(on)g(a)h(character)n(-by-character)i(basis.)146 +2706 y(The)39 b(w)o(ay)g(around)f(this)g(problem)g(is)g(to)h(use)f(a)i +Ff(console)p Fe(,)h(which)d(is)h(an)g(application)e(that)h(runs)h(in)f +(the)0 2827 y(manner)f(usually)g(e)o(xpected)g(by)g(Tk,)j(in)d(that)g +(it)g(is)g(a)g(GUI-dri)n(v)o(en)f(application.)68 b(The)37 +b(interpreter)g(is)g(split)0 2947 y(into)30 b Ff(master)g +Fe(and)h Ff(slave)f Fe(interpreters)h(\(see)g(the)g(Tcl)g +(documentation)e(on)h(the)h Fc(inter)o(p)h Fe(command\),)f(with)f(the)0 +3068 y(master)21 b(interpreter)h(running)e(the)i(console)f(application) +f(and)i(the)f(sla)n(v)o(e)g(interpreter)g(running)g(the)g(application.) +0 3188 y(The)36 b(master)g(interpreter)g(then)f(has)h(character)n +(-based)h(control)f(o)o(v)o(er)f(the)h(command)f(line,)j(and)e(the)f +(Magic)0 3308 y(dual-source)k(input)f(model)h(can)g(be)h(implemented)d +(e)o(xactly)i(as)g(originally)f(designed.)73 b(The)40 +b(background)0 3429 y(DRC)34 b(function)f(can)h(change)f(the)g(command) +g(line)g(cursor)g(from)g(`)p Ff(\045)p Fe(')h(to)f(`)p +Ff(])p Fe(')g(to)g(indicate)g(that)g(the)g(DRC)i(is)0 +3549 y(in)c(progress,)h(and)f(user)g(input)f(can)h(be)g(redirected)g +(from)g(the)g(layout)f(windo)n(w)g(to)g(the)h(console)f(with)h(the)f(`) +p Fc(:)p Fe(')0 3670 y(k)o(e)o(ystrok)o(e.)146 3873 y(In)f(addition)f +(to)h(these)f(functions,)h(the)g(console)f(mak)o(es)h(use)g(of)g(Tcl') +-5 b(s)28 b(ability)g(to)g(rename)i(commands)d(to)0 3993 +y(recast)22 b(the)f(basic)g(Tcl)h(output)e(function)h(`)p +Fc(puts)p Fe(')h(in)f(such)g(a)h(w)o(ay)g(that)f(output)f(to)h +Fd(stdout)f Fe(and)i Fd(stdin)e Fe(can)i(be)0 4113 y(handled)28 +b(dif)n(ferently)-6 b(.)41 b(In)29 b(the)g Fc(TkCon)h +Fe(console,)f(output)e(to)h Fd(stdout)g Fe(is)g(printed)g(in)h(blue,)g +(while)f(output)f(to)0 4234 y Fd(stderr)22 b Fe(is)h(printed)g(in)g +(red.)30 b(Magic)23 b(mak)o(es)g(use)h(of)f(Tcl')-5 b(s)23 +b(output)f(procedures)h(so)g(that)g(returned)h(v)n(alues)e(and)0 +4354 y(information)g(are)i(printed)f(in)g(blue,)g(while)g(w)o(arnings)g +(and)g(error)h(messages)f(are)h(printed)f(in)g(red.)30 +b(The)24 b(console)0 4475 y(also)35 b(implements)e(command-line)h +(history)g(and)h(cut-and-paste)g(methods.)61 b(The)35 +b(console)f(command-line)0 4595 y(history)24 b(replaces)h(the)g +(embedded)f Ff(r)l(eadline)g Fe(implementation)f(in)h(magic.)146 +4798 y(The)30 b Fc(TkCon)h Fe(console)e(is)g(a)h(placeholder)g(for)g +(what)f(is)h(intended)f(to)g(be)h(a)g(\223project)g(manager\224)g +(console,)0 4918 y(with)36 b(functions)g(more)h(appropriate)f(to)h(the) +g(Electronic)f(Design)g(Automation)f(suite)i(of)g(Tcl-based)f(tools.)0 +5039 y(In)f(general,)i(the)d(menu)g(functions)g(which)g(are)h +(displayed)e(on)i(the)f(TkCon)g(console)g(are)i(not)e(of)g(particular)0 +5159 y(interest)26 b(to)h(the)g(Magic)g(user)l(,)h(with)e(the)h(e)o +(xception)f(of)h(the)g Fc(History)f Fe(menu,)h(which)g(can)g(be)h(used) +f(to)f(re-enter)0 5280 y(pre)n(viously)31 b(e)o(x)o(ecuted)h(commands,) +h(and)g(the)g Fc(Pr)n(efs)g Fe(menu,)h(which)f(includes)f(highlighting) +e(options)h(and)i(a)0 5400 y(v)o(ery)24 b(useful)h(calculator)g(mode.) +1875 5649 y(\2265\226)p eop +%%Page: 6 6 +6 5 bop 0 -180 a Fe(April)24 b(12,)h(2006)1886 b(Magic)24 +b(Tcl)h(T)l(utorial)e(#1:)30 b(Introduction)0 99 y Fg(5)143 +b(Tk)36 b(Graphics)d(Methods)0 322 y Fe(Because)28 b(the)f(graphics)g +(under)h(Tcl)f(are)h(managed)f(by)g(the)g(Tk)g(package,)h(the)f(only)g +(graphics)g(options)f(which)0 443 y(can)k(be)g(compiled)e(are)i(the)g +(X11)f(and)g(the)h(OpenGL)f(options.)44 b(There)29 b(are)i(numerous)d +(dif)n(ferences)i(between)0 563 y(these)j(graphics)f(interf)o(aces)i +(as)e(the)o(y)h(e)o(xist)e(under)i(Tcl)g(and)g(under)g(the)f +(non-Tcl-based)h(v)o(ersion.)54 b(The)33 b(tw)o(o)0 683 +y(primary)22 b(dif)n(ferences)h(are)h(the)f(w)o(ay)f(windo)n(ws)g(are)h +(generated)g(and)g(the)g(w)o(ay)g(commands)e(are)j(sent)e(to)h +(speci\002c)0 804 y(windo)n(ws.)28 b(In)20 b(Tcl-based)h(magic,)g(a)g +(layout)f(windo)n(w)f(does)i(not)f(ha)n(v)o(e)g(to)h(be)f(a)i(top-le)n +(v)o(el)d(application)g(windo)n(w)-6 b(.)0 924 y(by)25 +b(using)e(the)i(command)f(syntax)900 1090 y Fc(openwindo)o(w)i +Ff(cellname)e(tk)p 1923 1090 30 4 v 36 w(pathname)146 +1255 y Fe(An)j(unmapped)f(windo)n(w)g(can)h(be)g(generated,)h +(corresponding)e(to)h(the)g(Tk)f(windo)n(w)g(hierarchy)h(speci\002ed)0 +1376 y(by)22 b Ff(tk)p 200 1376 V 35 w(pathname)f Fe(\(see)i(the)f(Tk)f +(documentation)g(for)h(the)g(speci\002cs)g(of)g(Tk)g(windo)n(w)e(path)i +(name)g(syntax\).)29 b(This)0 1496 y(windo)n(w)c(is)h(then)g(mapped)g +(and)g(managed)h(by)f(Tk)g(commands.)34 b(Using)26 b(this)f(method,)h +(a)h(magic)f(windo)n(w)f(can)0 1616 y(be)32 b(embedded)g(inside)f(a)i +(\223wrapper\224)g(application,)f(an)g(e)o(xample)g(of)g(which)g(has)g +(been)g(done)g(with)f(the)h(GUI)0 1737 y(wrapper)24 b(in)l(v)n(ok)o(ed) +e(with)h(the)g(\223)p Fd(-w)p Fe(\224)g(command-line)f(ar)n(gument.)30 +b(Extensions)21 b(of)j(magic)e(windo)n(w)g(commands)0 +1857 y(ha)n(v)o(e)30 b(been)g(added)h(so)e(that)h(the)g(wrapper)h(can)f +(control)g(the)g(windo)n(w)f(frame,)j(including)c(the)i(scrollbars)g +(and)0 1978 y(title.)146 2098 y(Whene)n(v)o(er)f(a)h(windo)n(w)e(is)h +(created,)i(Magic)e(creates)h(a)g(Tcl/Tk)e(command)h(with)f(the)h(same) +h(name)f(as)g(the)0 2218 y(windo)n(w)19 b(\(this)g(is)h(con)l(v)o +(entional)f(practice)h(with)g(Tk)g(widgets\).)28 b(Magic)20 +b(and)g(Tcl)g(commands)f(can)i(be)f(passed)g(as)0 2339 +y(ar)n(guments)j(to)g(the)g(windo)n(w)f(command.)29 b(Such)24 +b(commands)e(are)i(e)o(x)o(ecuted)f(relati)n(v)o(e)f(to)h(the)g +(speci\002c)h(windo)n(w)-6 b(.)0 2459 y(This)20 b(applies)g(to)g(all)g +(of)h(magic')-5 b(s)20 b(windo)n(w-based)f(commands,)h(including)f +(instructions)g(such)h(as)h Fc(mo)o(v)o(e)p Fe(,)g Fc(load)p +Fe(,)0 2580 y(and)31 b(so)g(forth.)49 b(Commands)30 b(which)g(apply)h +(to)f(all)h(windo)n(ws)e(will)h(automatically)g(be)h(sent)g(to)f(all)h +(windo)n(ws.)0 2700 y(These)e(commands)f(are)h(used)g(primarly)f(by)h +(the)g(wrapper)g(GUI,)g(b)n(ut)f(are)i(also)e(called)h(\(transparently) +g(to)f(the)0 2820 y(end)23 b(user\))h(whene)n(v)o(er)f(a)h(command)e +(is)i(e)o(x)o(ecuted)e(from)h(a)h(layout)f(windo)n(w)f(via)h(an)o(y)g +(macro,)h(including)e(the)h(`)p Fc(:)p Fe(')0 2941 y(command-line)i +(entry)-6 b(.)35 b(In)26 b(addition,)f(ho)n(we)n(v)o(er)l(,)g(the)o(y)h +(may)g(be)g(called)h(from)f(the)g(command)f(line)h(to)g(perform)0 +3061 y(an)k(action)g(in)g(a)h(speci\002c)g(windo)n(w)-6 +b(.)45 b(By)31 b(def)o(ault)f(\(in)g(the)g(absence)h(of)f(a)h(wrapper)g +(GUI\),)f(magic')-5 b(s)30 b(windo)n(ws)0 3181 y(are)25 +b(named)f Ff(.ma)o(gic1)p Fe(,)f Ff(.ma)o(gic2)p Fe(,)h(and)g(so)g +(forth,)g(in)f(order)i(of)f(appearance,)h(and)g(these)f(names)f(are)i +(re\003ected)g(in)0 3302 y(the)g(title)f(bar)h(of)g(the)f(windo)n(w)-6 +b(.)29 b(So)c(it)f(is)h(equi)n(v)n(alent)e(to)h(do)900 +3467 y Fc(:mo)o(v)o(e)h(s)g(10)0 3633 y Fe(from)f(layout)f(windo)n(w)g +(`)p Ff(.ma)o(gic2)p Fe(')h(\(where)g(the)g(colon)g(indicates)f(the)h +(k)o(e)o(y)g(macro)g(for)g(command-line)f(entry\),)0 +3753 y(and)900 3919 y Fc(.magic2)h(mo)o(v)o(e)h(s)g(10)0 +4084 y Fe(typed)f(in)h(the)f(console.)0 4417 y Fg(6)143 +b(T)-13 b(utorial)34 b(Examples)0 4641 y Fe(Example)23 +b(sessions)g(of)h(running)e(magic)i(in)f(v)n(arious)g(modes)g(are)i +(presented)e(belo)n(w)-6 b(,)23 b(along)g(with)g(e)o(xamples)g(of)0 +4761 y(methods)18 b(speci\002c)h(to)g(each)h(mode.)28 +b(In)19 b(the)g(e)o(xamples)f(belo)n(w)-6 b(,)19 b(prompts)e(are)j(sho) +n(wn)e(to)h(indicate)f(the)h(conte)o(xt)f(of)0 4881 y(each)26 +b(command.)31 b(The)26 b Ff(#)f Fe(sign)f(indicates)h(the)g(shell)g +(prompt,)f Ff(\(gdb\))h Fe(indicates)g(the)g(GNU)g(deb)n(ugger)g +(prompt,)0 5002 y(and)g Ff(\045)g Fe(indicates)f(the)g(Tcl)h(\(i.e.,)g +(Magic\))f(prompt.)0 5159 y Fa(Example)g(1:)31 b(Standard)24 +b(Magic)h(Ex)o(ecution)146 5400 y Fe(Run)g(Tcl-based)g(magic)f(in)h +(its)f(most)g(basic)g(form)h(by)f(doing)g(the)h(follo)n(wing:)1875 +5649 y(\2266\226)p eop +%%Page: 7 7 +7 6 bop 0 -180 a Fe(Magic)24 b(Tcl)h(T)l(utorial)f(#1:)30 +b(Introduction)1885 b(April)24 b(12,)h(2006)900 84 y +Ff(#)g Fc(magic)f(-noconsole)h(tut2a)146 439 y Fe(Magic)e(looks)g +(generally)g(lik)o(e)f(its)h(traditional)f(form,)h(e)o(xcept)g(that)g +(the)g(command-line)f(prompt)g(is)h(the)g(Tcl)0 559 y(`)p +Ff(\045)p Fe(')28 b(prompt.)39 b(It)28 b(should)f(be)h(possible)f(to)g +(write)h(commands)f(from)g(either)h(the)g(terminal)f(or)h(using)f(the)h +(colon)0 679 y(k)o(e)o(ystrok)o(e,)i(and)g(it)g(is)f(possible)g(to)h +(partially)f(type)h(a)g(command)f(after)i(the)f(colon)g(k)o(e)o(ystrok) +o(e)f(and)h(\002nish)f(the)0 800 y(command)22 b(inside)g(the)h +(terminal,)g(b)n(ut)f(not)h(vice)g(v)o(ersa.)30 b(Enabling)22 +b(the)h(colon)f(k)o(e)o(ystrok)o(e)g(may)h(require)g(setting)0 +920 y(\223)-8 b(Allo)n(w)24 b(SendEv)o(ents\224)g(mode)g(on)h(the)f +(calling)g(terminal.)0 1109 y Fa(Example)g(2:)31 b(Console-based)25 +b(Magic)f(Ex)o(ecution)146 1356 y Fe(Run)h(the)g(TkCon)g(console-based) +f(magic)g(by)h(doing)f(the)g(follo)n(wing:)900 1596 y +Ff(#)h Fc(magic)f(tut2a)146 1950 y Fe(The)g(layout)e(windo)n(w)h(will)f +(still)g(look)h(lik)o(e)g(the)g(usual,)g(basic)h(form.)30 +b(Ho)n(we)n(v)o(er)l(,)22 b(the)i(calling)e(terminal)h(will)0 +2071 y(be)i(suspended)g(\(unless)g(the)g(application)f(is)h +(backgrounded;)g(ho)n(we)n(v)o(er)l(,)f(if)h(backgrounding)f(the)h +(application,)0 2191 y(be)f(a)o(w)o(are)g(that)f(an)o(y)g(output)f +(sent)h(to)h(the)f(terminal)g(will)f(hang)i(the)f(application)g(until)f +(it)h(is)g(fore)o(grounded\))g(and)0 2312 y(the)e(Tcl)g(prompt)f(will)g +(appear)i(in)e(a)i(ne)n(w)e(windo)n(w)-6 b(,)20 b(which)h(is)f(the)h +Fc(console)p Fe(.)30 b(The)21 b(console)f(may)h(ha)n(v)o(e)g(a)g +(slightly)0 2432 y(dif)n(ferent)31 b(appearance)h(depending)e(on)h(the) +g(graphics)g(mode)g(used.)49 b(F)o(or)32 b(instance,)g(magic)f(has)g +(historically)0 2552 y(had)21 b(dif)n(\002culties)f(running)g(in)g +(8-bit)g(\(PseudoColor\))i(graphics)e(mode,)h(because)h(it)e(installs)f +(its)i(o)n(wn)f(colormap.)0 2673 y(Because)i(it)e(does)g(not)g(share)h +(the)f(colormap)g(with)g(the)h(calling)f(terminal,)g(the)g(calling)g +(terminal)g(gets)g(repainted)0 2793 y(in)35 b(random)f(colors)h(from)g +(magic')-5 b(s)34 b(colormap)g(when)h(the)g(cursor)g(is)g(in)g(the)f +(layout)h(windo)n(w)-6 b(.)59 b(In)35 b(unluck)o(y)0 +2914 y(setups,)24 b(te)o(xt)g(and)g(background)h(may)f(be)h +(unreadable.)146 3040 y(In)35 b(the)g(TkCon)g(console)f(setup,)i(the)f +(console)f(is)h(mapped)f(prior)h(to)f(determining)g(the)g(graphics)h +(mode)0 3160 y(required,)i(so)d(it)h(also)f(does)g(not)g(share)h(the)g +(colormap.)60 b(Ho)n(we)n(v)o(er)l(,)36 b(it)e(is)g(possible)f(to)i +(query)f(Magic')-5 b(s)34 b(col-)0 3281 y(ormap)d(to)f(\002nd)i(the)f +(location)f(of)h(speci\002c)h(colors,)g(and)f(repaint)g(the)g(te)o(xt)f +(and)h(background)f(of)i(the)f(console)0 3401 y(accordingly)-6 +b(.)29 b(Thus,)24 b(the)g(Magic)g(console)g(can)h(be)f(used)g(when)h +(the)f(display)f(is)h(in)g(8-bit)g(PseudoColor)g(mode,)0 +3522 y(without)g(e)o(xtreme)h(color)h(remappings)e(in)i(the)f(console)g +(which)h(mak)o(e)f(it)g(potentially)f(impossible)g(to)h(read)h(the)0 +3642 y(console)e(when)h(the)g(cursor)f(is)h(in)f(a)h(layout)f(windo)n +(w)-6 b(.)146 3768 y(If)28 b(compiled)e(with)g(both)h(OpenGL)g(and)g +(X11)f(graphics)h(capability)-6 b(,)26 b(magic)h(will)f(start)h(in)g +(X11)g(mode)f(by)0 3889 y(def)o(ault.)k(The)25 b(OpenGL)g(interf)o(ace) +g(can)g(only)f(be)h(enabled)g(at)g(startup)f(by)h(specifying:)900 +4129 y Ff(#)g Fc(magic)f(-d)i(OGL)e(tut4x)0 4484 y Fe(The)k(OpenGL)g +(interf)o(ace,)h(in)f(addition)f(to)h(ha)n(ving)f(more)h(solid,)g +(vibrant)f(colors,)h(has)g(an)h(additional)d(feature)0 +4604 y(which)e(dra)o(ws)h(three-dimensional)e(vie)n(ws)h(of)h(a)g +(layout.)30 b(This)24 b(is)g(discussed)g(in)g(T)l(utorial)g(#??.)0 +4792 y Fa(Example)g(4:)31 b(The)26 b(Magic)e(Wrapper)f(GUI)146 +5039 y Fe(The)i(magic)g(GUI)f(interf)o(ace)i(is)e(in)l(v)n(ok)o(ed)g +(by)h(starting)e(magic)i(with)f(the)h Fc(-w)g Fe(option:)900 +5280 y Ff(#)g Fc(magic)f(-w)h(tut2b)1875 5649 y Fe(\2267\226)p +eop +%%Page: 8 8 +8 7 bop 0 -180 a Fe(April)24 b(12,)h(2006)1886 b(Magic)24 +b(Tcl)h(T)l(utorial)e(#1:)30 b(Introduction)146 68 y(The)35 +b(immediately)e(noticeable)h(dif)n(ferences)h(are)g(the)g(layer)g +(toolbar)f(on)g(the)g(side,)j(and)e(the)f(menu)g(and)0 +188 y(redesigned)26 b(title)f(bar)i(on)f(the)g(top.)34 +b(Experimenting)25 b(with)g(some)h(mouse)f(clicks,)h(the)g(user)g(will) +g(note)g(that)f(the)0 309 y(magic)f(coordinates)h(of)f(the)h(cursor)g +(box)f(are)i(displayed)e(on)g(the)h(right-hand)f(side)g(of)h(the)g +(titlebar)-5 b(.)146 429 y(The)27 b(toolbar)f(contains)f(one)i(e)o +(xample)f(of)g(each)h(layer)g(de\002ned)g(in)f(the)h(magic)f +(technology)f(\002le.)36 b(Position)0 549 y(a)25 b(box)g(on)g(the)g +(screen,)g(then)g(put)g(the)g(cursor)g(o)o(v)o(er)f(a)h(layer)h(icon)e +(and)h(press)g(the)g(middle)f(mouse)h(b)n(utton.)30 b(This)0 +670 y(paints)d(the)h(layer)h(into)e(the)h(box.)40 b(Y)-11 +b(ou)28 b(will)f(also)g(notice)h(that)g(the)g(name)g(of)g(the)g(layer)g +(is)g(printed)f(in)h(the)g(title)0 790 y(bar)d(while)f(the)h(cursor)g +(is)f(o)o(v)o(er)g(the)h(layer)g(icon.)146 911 y(The)k(icons)e(ha)n(v)o +(e)h(other)h(responses,)f(too.)41 b(The)28 b(\002rst)h(and)f(third)g +(mouse)f(b)n(uttons)g(respecti)n(v)o(ely)g(sho)n(w)g(and)0 +1031 y(hide)k(the)f(layer)h(in)g(the)g(layout.)48 b(This)30 +b(w)o(orks)g(with)g(labels,)i(subcell)f(boundaries,)g(and)g(error)h +(paint)e(\(the)h(top)0 1151 y(three)d(layer)f(icons\))g(as)h(well)f(as) +g(with)g(re)o(gular)g(paintable)f(layers.)39 b(In)27 +b(addition)f(to)h(mouse)g(b)n(utton)f(responses,)0 1272 +y(the)k(b)n(uttons)e(in)l(v)n(ok)o(e)i(v)n(arious)f(commands)g(in)g +(reponse)h(to)g(k)o(e)o(ystrok)o(es.)45 b(K)n(e)o(y)29 +b(`p')h(paints)f(the)h(layer;)j(k)o(e)o(y)c(`e')0 1392 +y(erases)c(it.)30 b(K)n(e)o(y)24 b(`s')h(selects)g(the)g(layer)g(in)f +(the)h(box)f(while)g(k)o(e)o(y)h(`S')g(unselects)f(it.)146 +1513 y(The)f(menubar)f(has)g(three)h(items,)f Fc(File)p +Fe(,)g Fc(Cell)p Fe(,)h(and)f Fc(T)-9 b(ech)p Fe(.)31 +b(Button)22 b Fc(File)g Fe(pops)g(up)g(a)h(menu)f(with)g(options)e(to)0 +1633 y(read)28 b(and)f(write)g(layout,)f(read)i(and)f(write)g(CIF)h(or) +f(GDS)h(output,)e(open)h(a)g(ne)n(w)g(layout)f(windo)n(w)g(or)h(close)g +(the)0 1753 y(e)o(xisting)18 b(one,)k(or)e(\003ush)g(the)h(current)f +(edit)g(cell.)29 b(Buttons)20 b Fc(Cell)g Fe(and)g Fc(T)-9 +b(ech)22 b Fe(re)n(v)o(eal)e(transient)f(windo)n(ws)g(sho)n(wing)0 +1874 y(information)24 b(about)i(the)f(cell)h(hierarchy)g(and)f(the)h +(technology)f(\002le,)h(respecti)n(v)o(ely)-6 b(.)32 +b(The)25 b(cell)h(hierarchy)g(vie)n(w)0 1994 y(is)21 +b(only)g(a)n(v)n(ailable)g(if)g(the)h(Tcl/Tk)f(package)h +Fc(BL)-9 b(T)23 b Fe(has)e(been)h(compiled)f(and)g(installed)f(on)i +(the)f(system.)29 b(If)22 b(so,)g(it)0 2114 y(gi)n(v)o(es)h(a)i(tree)f +(vie)n(w)g(of)h(the)f(cell)g(hierarchy)g(and)h(allo)n(ws)e(speci\002c)i +(cells)f(to)g(be)g(loaded,)g(edited,)g(and)h(e)o(xpanded,)0 +2235 y(or)h(vie)n(wed)g(to)g(\002t)g(the)h(windo)n(w)-6 +b(.)33 b(This)25 b(can)i(be)f(e)o(xpecially)g(useful)g(for)g(querying)g +(the)g(cell)g(hierarchy)g(of)h(GDS)0 2355 y(\002les,)e(which)f(do)h +(not)f(declare)i(top-le)n(v)o(el)d(cells)h(lik)o(e)h(CIF)g(\002les)g +(do.)146 2476 y(The)31 b(technology)e(manager)i(windo)n(w)e(reports)h +(the)g(current)h(technology)e(\002le,)k(its)c(v)o(ersion)h(and)g +(descrip-)0 2596 y(tion,)23 b(and)h(the)g(current)h(CIF)g(input)e(and)h +(output)f(styles,)g(the)h(current)g(e)o(xtraction)f(style,)g(and)h(the) +g(current)h(v)n(alue)0 2716 y(of)f(lambda)g(in)g(microns.)29 +b(The)c(technology)e(\002le)h(and)g(the)h(CIF)g(input)e(and)h(output)f +(styles)g(and)i(e)o(xtraction)e(style)0 2837 y(are)k(also)g(b)n(uttons) +e(which)h(can)h(be)g(used)g(to)f(select)h(a)g(ne)n(w)f(style)g(or)h +(technology)f(from)g(those)g(currently)h(a)n(v)n(ail-)0 +2957 y(able.)40 b(Clicking)28 b(on)f(the)h(current)h(e)o(xtract)e +(style,)h(for)h(instance,)f(gi)n(v)o(es)e(a)j(list)e(of)h(the)g(styles) +f(which)g(ha)n(v)o(e)h(been)0 3077 y(speci\002ed)f(in)g(the)g(current)g +(technology)f(\002le.)37 b(Clicking)26 b(on)h(one)g(of)g(the)g(entries) +f(in)h(the)g(list)f(mak)o(es)g(it)h(the)g(ne)n(w)0 3198 +y(current)e(e)o(xtract)g(style.)146 3318 y(Cell)j(hierarchy)e(and)h +(technology)f(manager)i(windo)n(ws)d(should)h(be)h(closed)g(by)g +(clicking)f(on)h(the)g(\223Close\224)0 3439 y(b)n(utton)f(at)g(the)h +(bottom,)f(not)g(by)g(in)l(v)n(oking)f(an)o(y)i(titlebar)f(functions)f +(\(which)i(will)f(probably)g(cause)h(the)g(whole)0 3559 +y(application)d(to)g(e)o(xit\).)0 3727 y Fa(Example)g(5:)31 +b(Batc)o(h-mode)25 b(Magic)146 3968 y Fe(Unlik)o(e)j(pre)n(vious)f(v)o +(ersions)f(of)j(magic,)f(it)g(is)f(not)h(necessary)g(to)g(ha)n(v)o(e)g +(a)g(layout)g(windo)n(w)f(present)g(to)h(run)0 4088 y(magic.)i(Magic)25 +b(may)f(be)h(in)l(v)n(ok)o(ed)f(in)g(\223batch)h(mode\224)g(by)f(the)h +(follo)n(wing)e(command-line:)900 4285 y Ff(#)i Fc(magic)f(-no)o(windo) +o(w)i(tut2b)146 4602 y Fe(Note)g(ho)n(we)n(v)o(er)l(,)f(that)h(most)f +(magic)g(commands)g(e)o(xpect)h(a)g(windo)n(w)f(to)h(be)g(present)g(to) +f(e)o(x)o(ecute)h(the)g(func-)0 4722 y(tion.)65 b(The)37 +b(main)e(use)i(for)g(batch)f(mode)g(is)g(for)h(wrapper)n(-type)g +(applications)e(to)h(delay)g(opening)g(a)h(layout)0 4842 +y(windo)n(w)23 b(until)h(one)h(is)f(requested.)31 b(F)o(or)24 +b(e)o(xample:)900 5039 y Ff(#)h Fc(magic)f(-no)o(windo)o(w)i(tut2b)900 +5159 y Ff(\045)f Fc(tople)o(v)o(el)f(.myframe)900 5280 +y Ff(\045)h Fc(openwindo)o(w)h(tut2b)g(.myframe.mylay)n(out)900 +5400 y Ff(\045)f Fc(pack)h(.myframe.mylay)n(out)1875 +5649 y Fe(\2268\226)p eop +%%Page: 9 9 +9 8 bop 0 -180 a Fe(Magic)24 b(Tcl)h(T)l(utorial)f(#1:)30 +b(Introduction)1885 b(April)24 b(12,)h(2006)900 84 y +Ff(\045)g Fc(.myframe.mylay)n(out)f(box)h(0)g(0)f(12)h(12)900 +205 y Ff(\045)g Fc(.myframe.mylay)n(out)f(select)h(ar)n(ea)g(poly)900 +325 y Ff(\045)g Fc(wm)g(withdraw)g(.myframe)900 445 y +Ff(\045)g Fc(wm)g(deiconify)g(.myframe)900 566 y Ff(\045)g +Fc(.myframe.mylay)n(out)f(closewindo)o(w)146 867 y Fe(Note)e(that)g +(this)f(is)h(the)g(basic)g(setup)g(of)g(the)g(standard)g(GUI)g(wrapper) +l(,)h(albeit)f(with)f(much)h(greater)h(sophisti-)0 987 +y(cation.)29 b(The)22 b(standard)f(GUI)h(wrapper)h(is)e(generated)h +(entirely)f(by)h(script,)g(which)f(can)h(be)g(found)f(in)h(the)f +(library)0 1108 y(directory)k Fc($)p Fb(f)p Fc(CAD)p +707 1108 30 4 v 35 w(HOME)p Fb(g)p Fc(/lib/magic/tcl/wrapper)-10 +b(.tcl)p Fe(.)0 1270 y Fa(Example)24 b(6:)31 b(Tcl-Magic)24 +b(under)i(the)f(De)o(b)n(ugger)146 1511 y Fe(When)36 +b(running)f(under)g(Tcl,)j(Magic)d(cannot)h(be)f(deb)n(ugged)g(in)h +(the)f(usual)g(manner)h(of)f(e)o(x)o(ecuting,)i(for)0 +1631 y(instance,)22 b(\223)p Fc(gdb)i(magic)p Fe(\224,)e(because)h(the) +f(main)g(e)o(x)o(ecutable)f(is)h(actually)g(the)g(program)g(\223)p +Fc(wish)p Fe(\224.)30 b(T)-8 b(o)22 b(run)g(Magic)0 1752 +y(with)g(deb)n(ugging)g(capability)-6 b(,)21 b(it)h(is)h(necessary)g +(to)f(do)h(the)f(steps)h(belo)n(w)-6 b(.)28 b(In)23 b(the)g(follo)n +(wing,)e(it)h(is)h(assumed)f(that)0 1872 y(Magic)30 b(has)g(been)g +(installed)f(in)h(the)f(def)o(ault)h(location)g Fd(CAD)p +2137 1872 V 35 w(HOME=/usr/local/)p Fe(,)e(and)i(that)f(the)h(GNU)0 +1993 y(deb)n(ugger)25 b Fd(gdb)f Fe(is)g(the)h(deb)n(ugger)f(of)h +(choice.)600 2173 y Ff(#)g Fc(gdb)g(wish)600 2294 y Ff(\(gdb\))g +Fc(run)600 2414 y Ff(\045)g Fc(sour)n(ce)h +(/usr/local/lib/magic/tcl/magic.tcl)900 2534 y Fe(.)900 +2655 y(.)900 2775 y(.)600 2896 y Ff(\045)f(\(type)g(Contr)l(ol-C)f(in)g +(the)h(terminal)f(window\))600 3016 y(\(gdb\))h Fc(br)n(eak)h +(TxTclDispatch)600 3136 y Ff(\(gdb\))f Fc(cont)600 3257 +y Ff(\045)g Fc(paint)g(m1)600 3498 y Fd(Breakpoint)58 +b(1,)h(TxTclDispath)e(\(clientData=0x0,)f(argc=2,)900 +3618 y(argv=0xbffff400\))899 3738 y(at)j(txCommands.c:1146)600 +3859 y(1146)537 b(DRCBreak\(\);)600 3979 y Ff(\(gdb\))146 +4280 y Fe(Command-line)26 b(ar)n(guments)h(can)h(be)f(passed)g(to)g +(magic)f(through)h(the)g(Tcl)g(v)n(ariables)f Fd(argc)h +Fe(and)g Fd(argv)p Fe(.)0 4401 y(The)h(inte)o(ger)f(v)n(alue)g +Fd(argc)g Fe(must)f(match)i(the)f(number)g(of)h(entries)g(passed)f(in)g +(the)h Fd(argv)f Fe(list.)38 b(F)o(or)28 b(e)o(xample,)0 +4521 y(do)d(the)f(follo)n(wing:)900 4702 y Ff(#)h Fc(gdb)g(wish)900 +4822 y Ff(\(gdb\))g Fc(run)900 4942 y Ff(\045)g Fc(set)g(ar)o(gc)g(4) +900 5063 y Ff(\045)g Fc(set)g(ar)o(gv)g Fb(f)p Fc(-w)f(-d)i(OGL)e(tut1) +i Fb(g)900 5183 y Ff(\045)f Fc(sour)n(ce)h +(/usr/local/lib/magic/tcl/magic.tcl)1875 5649 y Fe(\2269\226)p +eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tuttcl2.ps b/doc/psfiles/tuttcl2.ps new file mode 100644 index 00000000..ac6c7728 --- /dev/null +++ b/doc/psfiles/tuttcl2.ps @@ -0,0 +1,241 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: tuttcl2.dvi +%%Pages: 1 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -t letter tuttcl2.dvi -o ../psfiles/tuttcl2.ps +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2006.04.12:1204 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: texps.pro +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type/integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics/Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{ +dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 +roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def +dup[exch{dup CharStrings exch known not{pop/.notdef/Encoding true def} +if}forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def} +def end + +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tuttcl2.dvi) +@start /Fa 105[50 28[50 2[50 50 28 39 33 1[50 50 50 78 +28 50 1[28 50 50 1[44 50 44 50 44 11[72 61 55 2[55 2[89 +61 1[39 1[72 3[72 2[72 9[50 3[50 50 50 50 1[25 33 25 +44[{TeXBase1Encoding ReEncodeFont}39 99.6264 /Times-Roman +rf /Fb 134[44 1[66 2[28 39 39 2[50 1[72 3[28 50 3[50 +2[50 12[55 1[61 12[61 22[25 46[{TeXBase1Encoding ReEncodeFont}15 +99.6264 /Times-Italic rf /Fc 138[80 48 1[64 1[80 72 2[40 +2[40 80 72 1[64 1[64 1[72 9[143 1[104 96 6[135 3[56 1[112 +12[48 7[72 72 13[72 35[{TeXBase1Encoding ReEncodeFont}22 +143.462 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%BeginPaperSize: Letter +letter +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 665 101 a Fc(Magic)35 b(Tcl)h(T)-13 b(utorial)33 +b(#2:)44 b(The)35 b(Wrapper)g(GUI)1546 521 y Fb(R.)25 +b(T)-5 b(imothy)24 b(Edwar)l(ds)1583 941 y Fa(Space)i(Department)1434 +1062 y(Johns)e(Hopkins)g(Uni)n(v)o(ersity)1391 1182 y(Applied)g +(Physics)g(Laboratory)1578 1303 y(Laurel,)h(MD)f(20723)819 +1573 y(This)g(tutorial)g(corresponds)g(to)h(Tcl-based)f(Magic)h(v)o +(ersion)e(7.2)0 2320 y Fc(1)143 b(The)35 b(Wrapper)g(GUI)1875 +5649 y Fa(\2261\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tuttcl3.ps b/doc/psfiles/tuttcl3.ps new file mode 100644 index 00000000..a4e1e3e6 --- /dev/null +++ b/doc/psfiles/tuttcl3.ps @@ -0,0 +1,244 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: tuttcl3.dvi +%%Pages: 1 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -t letter tuttcl3.dvi -o ../psfiles/tuttcl3.ps +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2006.04.12:1204 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: texps.pro +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type/integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics/Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{ +dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 +roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def +dup[exch{dup CharStrings exch known not{pop/.notdef/Encoding true def} +if}forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def} +def end + +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tuttcl3.dvi) +@start /Fa 105[50 28[50 2[50 50 28 39 33 1[50 50 50 78 +28 50 1[28 50 50 1[44 50 44 50 44 11[72 61 55 2[55 2[89 +61 1[39 1[72 3[72 2[72 9[50 3[50 50 50 50 1[25 33 25 +44[{TeXBase1Encoding ReEncodeFont}39 99.6264 /Times-Roman +rf /Fb 134[44 1[66 2[28 39 39 2[50 1[72 3[28 50 3[50 +2[50 12[55 1[61 12[61 22[25 46[{TeXBase1Encoding ReEncodeFont}15 +99.6264 /Times-Italic rf /Fc 135[72 2[80 48 56 64 1[80 +72 80 120 40 2[40 80 72 48 64 80 64 1[72 12[96 5[104 +135 7[96 1[104 8[48 6[72 72 72 13[72 32[80 2[{ +TeXBase1Encoding ReEncodeFont}29 143.462 /Times-Bold +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%BeginPaperSize: Letter +letter +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 466 101 a Fc(Magic)35 b(Tcl)g(T)-13 b(utorial)34 +b(#3:)44 b(Extracting)33 b(and)i(Netlisting)1546 521 +y Fb(R.)25 b(T)-5 b(imothy)24 b(Edwar)l(ds)1583 941 y +Fa(Space)i(Department)1434 1062 y(Johns)e(Hopkins)g(Uni)n(v)o(ersity) +1391 1182 y(Applied)g(Physics)g(Laboratory)1578 1303 +y(Laurel,)h(MD)f(20723)819 1573 y(This)g(tutorial)g(corresponds)g(to)h +(Tcl-based)f(Magic)h(v)o(ersion)e(7.2)0 2320 y Fc(1)143 +b(T)-13 b(ech)35 b(\002le)g(extensions)e(f)l(or)j(extraction)0 +2606 y(2)143 b(Commands)33 b(exttospice)h(and)h(exttosim)1875 +5649 y Fa(\2261\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tuttcl4.ps b/doc/psfiles/tuttcl4.ps new file mode 100644 index 00000000..e5bf91f8 --- /dev/null +++ b/doc/psfiles/tuttcl4.ps @@ -0,0 +1,959 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.95a Copyright 2005 Radical Eye Software +%%Title: tuttcl4.dvi +%%Pages: 8 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman Courier-Bold +%%+ Courier CMSY10 CMR12 CMMI12 +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -t letter tuttcl4.dvi -o ../psfiles/tuttcl4.ps +%DVIPSParameters: dpi=600 +%DVIPSSource: TeX output 2006.04.14:1844 +%%BeginProcSet: tex.pro 0 0 +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S +/BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy +setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask +restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc 0 0 +% File 8r.enc TeX Base 1 Encoding Revision 2.0 2002-10-30 +% +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry, +% W. Schmidt, P. Lehman", +% version = "2.0", +% date = "30 October 2002", +% filename = "8r.enc", +% email = "tex-fonts@@tug.org", +% docstring = "This is the encoding vector for Type1 and TrueType +% fonts to be used with TeX. This file is part of the +% PSNFSS bundle, version 9" +% @} +% +% The idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard encoding, ISO Latin 1, Windows ANSI including the euro symbol, +% MacRoman, and some extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% These are /dotlessj /ff /ffi /ffl. +% +% (4) hyphen appears twice for compatibility with both ASCII and Windows. +% +% (5) /Euro was assigned to 128, as in Windows ANSI +% +% (6) Missing characters from MacRoman encoding incorporated as follows: +% +% PostScript MacRoman TeXBase1 +% -------------- -------------- -------------- +% /notequal 173 0x16 +% /infinity 176 0x17 +% /lessequal 178 0x18 +% /greaterequal 179 0x19 +% /partialdiff 182 0x1A +% /summation 183 0x1B +% /product 184 0x1C +% /pi 185 0x1D +% /integral 186 0x81 +% /Omega 189 0x8D +% /radical 195 0x8E +% /approxequal 197 0x8F +% /Delta 198 0x9D +% /lozenge 215 0x9E +% +/TeXBase1Encoding [ +% 0x00 + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef /breve + /minus /.notdef /Zcaron /zcaron +% 0x10 + /caron /dotlessi /dotlessj /ff + /ffi /ffl /notequal /infinity + /lessequal /greaterequal /partialdiff /summation + /product /pi /grave /quotesingle +% 0x20 + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus + /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three + /four /five /six /seven + /eight /nine /colon /semicolon + /less /equal /greater /question +% 0x40 + /at /A /B /C + /D /E /F /G + /H /I /J /K + /L /M /N /O +% 0x50 + /P /Q /R /S + /T /U /V /W + /X /Y /Z /bracketleft + /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c + /d /e /f /g + /h /i /j /k + /l /m /n /o +% 0x70 + /p /q /r /s + /t /u /v /w + /x /y /z /braceleft + /bar /braceright /asciitilde /.notdef +% 0x80 + /Euro /integral /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /Omega /radical /approxequal +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /Delta /lozenge /Ydieresis +% 0xA0 + /.notdef /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot /hyphen /registered /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde + /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + + +%%EndProcSet +%%BeginProcSet: texps.pro 0 0 +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 +ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ +pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get +div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type +/nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end +definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup +sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll +mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ +exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} +forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def +end + +%%EndProcSet +%%BeginFont: CMMI12 +%!PS-AdobeFont-1.1: CMMI12 1.100 +%%CreationDate: 1996 Jul 27 08:57:55 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.100) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMMI12) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +end readonly def +/FontName /CMMI12 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 58 /period put +dup 110 /n put +readonly def +/FontBBox{-30 -250 1026 750}readonly def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE +3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B +532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 +B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B +986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE +D919C2DDD26BDC0D99398B9F4D03D6A8F05B47AF95EF28A9C561DBDC98C47CF5 +5250011D19E9366EB6FD153D3A100CAA6212E3D5D93990737F8D326D347B7EDC +4391C9DF440285B8FC159D0E98D4258FC57892DCC57F7903449E07914FBE9E67 +3C15C2153C061EB541F66C11E7EE77D5D77C0B11E1AC55101DA976CCACAB6993 +EED1406FBB7FF30EAC9E90B90B2AF4EC7C273CA32F11A5C1426FF641B4A2FB2F +4E68635C93DB835737567FAF8471CBC05078DCD4E40E25A2F4E5AF46C234CF59 +2A1CE8F39E1BA1B2A594355637E474167EAD4D97D51AF0A899B44387E1FD933A +323AFDA6BA740534A510B4705C0A15647AFBF3E53A82BF320DD96753639BE49C +2F79A1988863EF977B800C9DB5B42039C23EB86953713F730E03EA22FF7BB2C1 +D97D33FD77B1BDCC2A60B12CF7805CFC90C5B914C0F30A673DF9587F93E47CEA +5932DD1930560C4F0D97547BCD805D6D854455B13A4D7382A22F562D7C55041F +0FD294BDAA1834820F894265A667E5C97D95FF152531EF97258F56374502865D +A1E7C0C5FB7C6FB7D3C43FEB3431095A59FBF6F61CEC6D6DEE09F4EB0FD70D77 +2A8B0A4984C6120293F6B947944BE23259F6EB64303D627353163B6505FC8A60 +00681F7A3968B6CBB49E0420A691258F5E7B07B417157803FCBE9B9FB1F80FD8 +CA0DA1186446DD565542BCCC7D339A1EB34C7F49246E8D72E987EB477C6DB757 +99AF86CEBCD7605C487A00CD2CD093098182DC57B20D78ECE0BECF3A0BF88EBA +C866DB19F34BBBED6634AFC0F08D2AFB2A92578A6F8B4ADCD6594737FF6EED7D +5B536DA9E3E2CADB40DB7C600EA4D100D33C3B92B1CF857E012C4EB370BA8295 +55B50047CD58E912E67E22C1B92F41D0BEE742201DF1841098B2FDEF9E460667 +C94DA8A259380B5C76A572D8B6B17B2F6CC25937DFC98BBF8BC5699C73122C23 +1D18E692199499119235481C272FAAA88C8F00D17DA078B463489A0F16B98378 +4C3E03B20E1E4DE2E33BE9539AE5452FF616A0D8E3C4043F344213FF08CB0072 +EB840136F4FAFA24A106A14739CB0585B002FDE204C47DE9F2E77E3F64B8C6F0 +84CEB054B5BE8ED33A3E479DCF3FFA00F1F208687F3C3D53BF9F76C9A67E65C6 +B49AF14843F0F3D20D5E7FD32F0616A4ADB9CD24FB46951FB63067C82917282B +1A1A99AAFC38898B5403623DDF7483614A77850F4D223B47827538F3C6FF2E06 +5951E570C6FBDBC926AD9D057DFC75B48767682C539AE1EC576582E09ACAA28A +C7CB884E63EF5BB1C96767316BCA34975AFE146BC2F2AFFD9DF13AC8B7FCC9C2 +55DF310FC646F5BB0C24CD7F96FF126141F42D5B62D65309F76643567C4A6EE0 +BCE68B5EC3C0C3CEF644CE706CBC31CB91F3991B77A1DB2CDF4CF85034EF34E0 +98EEC275802627DD7F1560E30A5E65485E49CE13C88A514569AD848E520AF44B +787133A0E662511B89FA6936E78F7652A3976C9A831C74C4EC704BCD381303A6 +D33217E0C788E05DB861 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMR12 +%!PS-AdobeFont-1.1: CMR12 1.0 +%%CreationDate: 1991 Aug 20 16:38:05 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.0) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMR12) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle 0 def +/isFixedPitch false def +end readonly def +/FontName /CMR12 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 48 /zero put +dup 49 /one put +readonly def +/FontBBox{-34 -251 988 750}readonly def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 +016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 +9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F +D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 +469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 +2BDBF16FBC7512FAA308A093FE5CF4E9D2405B169CD5365D6ECED5D768D66D6C +68618B8C482B341F8CA38E9BB9BAFCFAAD9C2F3FD033B62690986ED43D9C9361 +3645B82392D5CAE11A7CB49D7E2E82DCD485CBA04C77322EB2E6A79D73DC194E +59C120A2DABB9BF72E2CF256DD6EB54EECBA588101ABD933B57CE8A3A0D16B28 +51D7494F73096DF53BDC66BBF896B587DF9643317D5F610CD9088F9849126F23 +DDE030F7B277DD99055C8B119CAE9C99158AC4E150CDFC2C66ED92EBB4CC092A +AA078CE16247A1335AD332DAA950D20395A7384C33FF72EAA31A5B89766E635F +45C4C068AD7EE867398F0381B07CB94D29FF097D59FF9961D195A948E3D87C31 +821E9295A56D21875B41988F7A16A1587050C3C71B4E4355BB37F255D6B237CE +96F25467F70FA19E0F85785FF49068949CCC79F2F8AE57D5F79BB9C5CF5EED5D +9857B9967D9B96CDCF73D5D65FF75AFABB66734018BAE264597220C89FD17379 +26764A9302D078B4EB0E29178C878FD61007EEA2DDB119AE88C57ECFEF4B71E4 +140A34951DDC3568A84CC92371A789021A103A1A347050FDA6ECF7903F67D213 +1D0C7C474A9053866E9C88E65E6932BA87A73686EAB0019389F84D159809C498 +1E7A30ED942EB211B00DBFF5BCC720F4E276C3339B31B6EABBB078430E6A09BB +377D3061A20B1EB98796B8607EECBC699445EAA866C38E02DF59F5EDD378303A +0733B90E7835C0AAF32BA04F1566D8161EA89CD4D14DDB953F8B910BFC8A7F03 +5020F55EF8FC2640ADADA156F6CF8F2EB6610F7EE8874A26CBE7CD154469B9F4 +ED76886B3FB679FFDEB59BB6C55AF7087BA48B75EE2FB374B19BCC421A963E15 +FE05ECAAF9EECDF4B2715010A320102E6F8CCAA342FA11532671CCCC52875960 +84CC1832A068F03077BAA0C4CB6EB8A6ACF53741914AD12120F8BE6F0A9A65BF +0C099B28A58F40BCC782438962B9EF94FFFD64B4825C08E2F64F1C494F2FE514 +0206F432B586845DEE85C5A0D896A89F2EE07B93CB341DE53930F82AEAEBDD18 +5005D096E36BF691DE22DBA7F5D63F1552AE0BC8E675E2FB600691535BC72BFD +8EF2B5B1D9076592E540D76A56C21F61A5E1ECBC18EE7E8C8F0990685A38A4E4 +81C19C4FAD43B6EF537879E828101FE69AD179FB7CC15F0EE9069DB29C6AF70E +E394970A078D99CB082DF51B9C3A31E1526A048FE477F3997E36AD2F35347039 +69A74AB1D2628C6558105E71BB6C72688BE5BEAF2B23C36D3A55888C532A36F6 +092870681F340FBD5D423AFA2397B20555AA1AFBE03502406375C7EE481A5E3C +34613F21902308BF1FDEAD4FDB076109F23871A698CE725652E1D5D77E34221B +A51A11F44332CDC79C72ECBC9619AE171DAFDB333DBD89945282B9FC3B508932 +F371F2420BD6A5D79632D5457202C7DCEADBF8769717290F99487E129A387169 +0D5FA2EF8AA2FA629A0759E0BFDDCD68B8D686661203ECD52508DA082505C743 +B87C5D944C2B40 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMSY10 +%!PS-AdobeFont-1.1: CMSY10 1.0 +%%CreationDate: 1991 Aug 15 07:20:57 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.0) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMSY10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.035 def +/isFixedPitch false def +end readonly def +/FontName /CMSY10 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 0 /minus put +dup 102 /braceleft put +dup 103 /braceright put +readonly def +/FontBBox{-29 -960 1116 775}readonly def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 +7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 +A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 +E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A +221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A +27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF +5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 +0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 +DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A +71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 +4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C +515DB70A8D4F6146FE068DC1E5DE8BC570317AAEA74A842CFD26F9591866F5A0 +9B4EAD7395F5196B36997F1D59E88165C94739E74C2B40820F8C972B175ED79D +87C9E323C3CDD5C2BEE6409017767534E19F45AFCE2C6687733451AD2E75D112 +42040BADFF90F5FCF3F2901FDEA619E64D6D0C6028216A78E7C25112B0D34428 +AE383A46C0FE7D29AE9EE114224EF9BB7DC731072DBE736AB1358F37610C3762 +F266B1016768B04306F3AC083DAF863E78CA401B28090A92C6AFC4FC601C2397 +A24426104896F5D2D2E7651942A70EE036A943E59D3554AE462B9E0911B58F75 +4ACDA535B87CFE5614EFDA21855F6F9C1FC25D2DDF53A49D8DA9188F3D7D1769 +E55F4B40B211D1ACB084C157CE1608A3781D134EC608C6A1A6F1FE1707BDB0CF +B111D95C18D611BFA1535A6CC94EA264FE45347D40DCD5C5390D862AC6291D44 +B007322C02AED356974E5BD9C2C434430E50DBE4020B35220345B9B8C287AF4C +ACCAD84CF351FE3878C61BAE570D9188760BE493FDE2C9C551E4BCE313039C74 +54EBF847327459041B7F6D9D0920034D7FFEF514EC312B6090B07BFFE3E74AE7 +BC3740D3072C9A78B16EBBB3EDE20CB6E506F6B66E8780B5631CBDF7D8B54EF5 +AE5CAD8129B6C75472F6DC7E90C0A5E0CEFC3588635BA402B64852A03C3BEA47 +57D73980B741FF62395F39DAFA78047ECE96DE9715D7ABAC46F9922220A24686 +CDF91735904661E52C5FC67A76609DA9D7843D2415599C53C8F4388F4262BC19 +289DE84C70F67EB0A6329242865E0DBCFBDCCEE1E111F0D9AC3AD5BD4FCA1C39 +2E3317FD91906802B79D7D08E27AEE0440CD9AE58CCCBC4F8630C3089F3B091F + +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +TeXDict begin 40258431 52099146 1000 600 600 (tuttcl4.dvi) +@start /Fa 145[58 51[27 58[{}2 99.6264 /CMMI12 rf /Fb +206[49 49 48[{}2 99.6264 /CMR12 rf /Fc 152[50 50 101[77{}3 +99.6264 /CMSY10 rf /Fd 134[60 60 1[60 60 60 60 60 60 +60 60 60 60 60 2[60 60 60 60 60 60 60 60 60 9[60 60 1[60 +60 60 3[60 60 3[60 1[60 1[60 60 1[60 60 3[60 1[60 60 +60 60 60 60 60 1[60 60 60 60 60 60 60 60 2[60 60 60 3[60 +60 34[{TeXBase1Encoding ReEncodeFont}56 99.6264 /Courier +rf /Fe 133[60 1[60 60 60 60 60 60 60 1[60 60 60 60 60 +60 1[60 60 60 60 60 60 60 60 60 3[60 1[60 6[60 60 60 +2[60 1[60 60 3[60 60 1[60 60 60 60 60 7[60 3[60 60 60 +60 60 60 60 60 60 60 7[60 60 35[{TeXBase1Encoding ReEncodeFont}51 +99.6264 /Courier-Bold rf /Ff 136[72 50 55 33 39 44 2[50 +55 83 28 55 1[28 55 50 1[44 55 44 1[50 12[66 7[66 9[66 +7[33 58[{TeXBase1Encoding ReEncodeFont}22 99.6264 /Times-Bold +rf /Fg 138[66 40 47 53 2[60 66 100 33 2[33 66 2[53 66 +53 1[60 12[80 6[113 9[86 8[40 55[66 2[{TeXBase1Encoding ReEncodeFont}19 +119.552 /Times-Bold rf /Fh 64[44 29[33 10[50 1[44 44 +24[44 50 50 72 50 50 28 39 33 50 50 50 50 78 28 50 28 +28 50 50 33 44 50 44 50 44 33 2[33 1[33 1[72 72 94 72 +72 61 55 66 1[55 72 72 89 61 1[39 33 72 72 55 61 72 66 +66 72 1[44 3[28 28 50 50 50 50 50 50 50 50 50 50 28 25 +33 25 2[33 33 33 2[50 50 1[33 29[55 55 2[{TeXBase1Encoding ReEncodeFont} +82 99.6264 /Times-Roman rf /Fi 134[44 1[66 44 50 28 39 +39 1[50 50 50 72 28 2[28 50 50 28 44 50 44 50 50 5[39 +6[55 50 61 3[66 83 3[33 3[61 22[25 33 25 2[33 33 2[83 +1[50 35[{TeXBase1Encoding ReEncodeFont}36 99.6264 /Times-Italic +rf /Fj 133[64 72 1[104 72 80 48 56 64 80 80 72 80 120 +40 80 1[40 80 72 48 64 80 64 80 72 9[143 104 1[96 80 +104 4[135 3[56 1[112 88 1[104 104 96 104 6[48 72 72 72 +72 72 72 72 72 72 2[36 10[72 35[{TeXBase1Encoding ReEncodeFont}49 +143.462 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%BeginPaperSize: Letter +letter +%%EndPaperSize + end +%%EndSetup +%%Page: 1 1 +TeXDict begin 1 0 bop 518 101 a Fj(Magic)35 b(Tcl)g(T)-13 +b(utorial)34 b(#4:)44 b(Simulation)33 b(with)i(IRSIM)1546 +521 y Fi(R.)25 b(T)-5 b(imothy)24 b(Edwar)l(ds)1583 941 +y Fh(Space)i(Department)1434 1062 y(Johns)e(Hopkins)g(Uni)n(v)o(ersity) +1391 1182 y(Applied)g(Physics)g(Laboratory)1578 1303 +y(Laurel,)h(MD)f(20723)819 1573 y(This)g(tutorial)g(corresponds)g(to)h +(Tcl-based)f(Magic)h(v)o(ersion)e(7.2)0 2070 y Fg(T)-11 +b(utorials)30 b(to)f(r)n(ead)h(\002rst:)300 2251 y Fh(Magic)24 +b(T)l(utorial)g(#1:)30 b(Getting)24 b(Started)300 2371 +y(Magic)g(T)l(utorial)g(#2:)30 b(Basic)25 b(P)o(ainting)f(and)h +(Selection)300 2492 y(Magic)f(T)l(utorial)g(#4:)30 b(Cell)25 +b(Hierarchies)300 2612 y(Magic)f(T)l(utorial)g(#8:)30 +b(Circuit)25 b(Extraction)300 2732 y(Magic)f(T)l(utorial)g(#11:)30 +b(Using)24 b(IRSIM)h(and)g(RSIM)h(with)e(Magic)0 2913 +y Fg(Commands)29 b(intr)n(oduced)j(in)f(this)f(tutorial:)300 +3093 y Fh(irsim)24 b(,)h(getnode,)f(goto)300 3213 y(graphnode,)g(w)o +(atchnode,)h(unw)o(atchnode)300 3334 y(mo)o(v)o(enode,)e(w)o(atchtime,) +h(unw)o(atchtime,)f(mo)o(v)o(etime)300 3454 y Fi(\(plus)h(the)h +(standar)l(d)e(IRSIM)i(command)f(set\))0 3634 y Fg(Macr)n(os)29 +b(intr)n(oduced)i(in)g(this)f(tutorial:)300 3832 y Fi(\(None\))0 +4394 y Fj(1)143 b(IRSIM)35 b(V)-14 b(ersion)34 b(9.6)0 +4618 y Fh(In)28 b(v)o(ersion)e(9.6,)i(IRSIM)h(has)e(been)h(redesigned)f +(to)h(w)o(ork)f(under)h(the)f(Tcl)h(interpreter)l(,)g(in)f(the)h(same)f +(manner)0 4738 y(as)g(Magic)g(v)o(ersion)g(7.2)g(does.)38 +b(Lik)o(e)27 b(Magic)g(v)o(ersion)f(7.2,)i(section)e(of)i(Tcl)f(as)h +(an)f(interpreter)h(is)e(speci\002ed)i(at)0 4859 y(compile-time,)j +(along)g(with)g(v)n(arious)f(use)i(options.)49 b(The)31 +b(\223)p Ff(mak)o(e)p Fh(\224)h(method)f(has)g(been)h(re)n(written)e +(to)i(match)0 4979 y(the)25 b(one)f(which)h(Magic)f(uses,)h(so)f(IRSIM) +i(can)f(be)g(compiled)f(and)g(installed)g(in)g(a)h(similar)f(manner:) +900 5159 y Fe(make)59 b(config)900 5280 y(make)g(tcl)900 +5400 y(make)g(install-tcl)1875 5649 y Fh(\2261\226)p +eop end +%%Page: 2 2 +TeXDict begin 2 1 bop 0 -180 a Fh(April)24 b(14,)h(2006)1437 +b(Magic)25 b(Tcl)f(T)l(utorial)g(#4:)30 b(Simulation)23 +b(with)h(IRSIM)146 68 y(Tcl-based)i(IRSIM,)g(lik)o(e)e(its)h +(non-interpreter)g(v)o(ersion,)f(can)i(be)f(run)g(as)h(a)f(standalone)g +(product,)g(and)g(will)0 188 y(simulate)33 b(a)i(circuit)f(from)g(a)h +Fd(.sim)e Fh(format)h(\002le.)60 b(Ho)n(we)n(v)o(er)l(,)36 +b(it)e(is)g(speci\002cally)g(designed)f(to)h(be)h(operated)0 +309 y(in)27 b(conjunction)f(with)g(magic,)i(with)e(methods)g(for)i(pro) +o(viding)d(feedback)j(directly)f(into)g(the)g(layout)f(from)h(the)0 +429 y(simulation,)k(and)h(vice)g(v)o(ersa.)52 b(There)32 +b(are)g(a)h(number)e(of)h Fi(cr)l(oss-application)d(commands)p +Fh(,)j(detailed)g(belo)n(w)-6 b(,)0 549 y(which)36 b(belong)f(to)h +(neither)g(Magic)f(or)h(IRSIM,)h(b)n(ut)f(are)h(applicable)e(when)h +(both)g(are)g(running)g(in)f(the)h(Tcl)0 670 y(interpreter)25 +b(at)g(the)f(same)h(time.)146 791 y(The)38 b(cross-application)f +(commands)f(highlight)g(the)i(usefulness)e(of)i(the)g(method)f(of)h +(compiling)d(each)0 911 y(application)24 b(as)h(a)g(loadable)f(Tcl)h +(object)f(module.)146 1032 y(In)e(addition)f(to)g(cross-application)g +(commands,)g(Tcl-based)h(IRSIM)h(allo)n(ws)d(the)i(use)g(of)g +(interpreter)f(v)n(ari-)0 1152 y(ables,)31 b(conditionals,)f(and)g +(control)f(structures)h(to)f(set)h(up)g(detailed)g(simulation)e(en)l +(vironments.)45 b(A)30 b(random)0 1272 y(number)37 b(generator)h(has)f +(been)h(added)g(to)f(the)g(Tcl-based)h(v)o(ersion,)h(allo)n(wing)d +(generation)h(of)h(random)f(bit)0 1393 y(v)o(ectors)24 +b(for)h(statistically-based)e(co)o(v)o(erage)h(of)h(input)f(pattern)h +(spaces.)0 1734 y Fj(2)143 b(In)-6 b(v)o(oking)34 b(IRSIM)h(fr)m(om)g +(Magic)0 1959 y Fh(W)l(ithin)e(the)h(Tcl/Tk)f(en)l(vironment,)j(IRSIM)f +(is)e(easier)i(than)f(e)n(v)o(er)f(to)h(in)l(v)n(ok)o(e.)58 +b(F)o(or)34 b(tutorial)f(purposes,)j(we)0 2079 y(will)30 +b(use)i(the)f(same)g(cell)g(used)g(for)h(the)f(original)f(T)l(utorial)g +(#11.)50 b(Unlik)o(e)30 b(the)h(original)g(v)o(ersion,)h(Magic)e(7.2)0 +2199 y(requires)f(no)h(preparation)f(for)h(simulation)d(and)i(can)h +(operate)g(directly)f(of)n(f)g(of)g(the)h(tutorial)e(directory)h +(input.)0 2320 y(Start)c(magic)f(with)h(the)f(command-line)900 +2551 y Fi(#)h Fe(magic)58 b(-w)i(-d)f(OGL)g(tut11a)146 +2781 y Fh(Note)23 b(that)f(the)g(OpenGL)g(interf)o(ace)i(and)e(Wrapper) +h(en)l(vironment)f(speci\002ed)g(abo)o(v)o(e)g(are)h(optional,)f(and)g +(do)0 2902 y(not)i(af)n(fect)h(the)g(descriptions)e(in)i(this)f +(tutorial.)146 3022 y(It)34 b(is)f(not)f(necessary)i(to)f(e)o(xtract!) +56 b(The)34 b(scripts)e(which)h(in)l(v)n(ok)o(e)g(IRSIM)h(are)g +(capable)g(of)f(looking)f(for)i(a)0 3143 y(netlist)26 +b(\002le)i(to)f(simulate)f(for)h(the)g(currently-loaded)g(cell.)38 +b(Because)28 b(these)f(e)o(xist)g(for)g(the)g(tutorial)f(cells,)i(the)o +(y)0 3263 y(will)c(be)h(used.)30 b(IRSIM)c(is)e(therefore)i(simply)d +(in)l(v)n(ok)o(ed)h(by:)900 3494 y Fi(\045)h Fe(irsim)146 +3725 y Fh(Y)-11 b(ou)25 b(will)f(see)h(a)g(sle)n(w)f(of)h(output)e +(that)i(looks)f(lik)o(e)g(the)h(follo)n(wing:)300 3955 +y Fd(Warning:)118 b(irsim)58 b(command)h('time')f(use)h +(fully-qualified)e(name)h('::irsim::time')300 4076 y(Warning:)118 +b(irsim)58 b(command)h('start')f(use)h(fully-qualified)d(name)j +('::irsim::start')300 4196 y(Warning:)118 b(irsim)58 +b(command)h('help')f(use)h(fully-qualified)e(name)h('::irsim::help')300 +4317 y(Warning:)118 b(irsim)58 b(command)h('path')f(use)h +(fully-qualified)e(name)h('::irsim::path')300 4437 y(Warning:)118 +b(irsim)58 b(command)h('clear')f(use)h(fully-qualified)d(name)j +('::irsim::clear')300 4557 y(Warning:)118 b(irsim)58 +b(command)h('alias')f(use)h(fully-qualified)d(name)j('::irsim::alias') +300 4678 y(Warning:)118 b(irsim)58 b(command)h('set')f(use)h +(fully-qualified)e(name)i('::irsim::set')300 4798 y(Warning:)118 +b(irsim)58 b(command)h('exit')f(use)h(fully-qualified)e(name)h +('::irsim::exit')300 4918 y(Starting)g(irsim)h(under)f(Tcl)h +(interpreter)300 5039 y(IRSIM)g(9.6)g(compiled)f(on)h(Thu)g(Mar)g(20)h +(17:19:00)e(EST)h(2003)300 5159 y(Warning:)118 b(Aliasing)58 +b(nodes)g('GND')h(and)g('Gnd')300 5280 y(/usr/local/lib/magic/tutorial) +o(/tut1)o(1a.s)o(im:)113 b(Ignoring)58 b(lumped-resistance)600 +5400 y(\('R')h(construct\))1875 5649 y Fh(\2262\226)p +eop end +%%Page: 3 3 +TeXDict begin 3 2 bop 0 -180 a Fh(Magic)24 b(Tcl)h(T)l(utorial)f(#4:)30 +b(Simulation)23 b(with)h(IRSIM)1439 b(April)24 b(14,)h(2006)300 +205 y Fd(Read)59 b(/usr/local/lib/magic/tutorial)o(/tut)o(11a.s)o(im)54 +b(lambda:1.00u)j(format:MIT)300 325 y(68)i(nodes;)g(transistors:)117 +b(n-channel=56)57 b(p-channel=52)300 445 y(parallel)h(txtors:none)300 +566 y Fi(\045)146 751 y Fh(These)25 b(comments)f(require)i(some)e(e)o +(xplanation.)30 b(The)c(w)o(arning)e(messages)h(all)g(ha)n(v)o(e)g(to)f +(do)h(with)g(the)g(f)o(act)0 872 y(that)i(certain)i(command)d(names)i +(are)h(used)e(both)g(by)h(IRSIM)h(and)f(Magic,)g(or)g(by)g(IRSIM)g(and) +g(Tcl)g(or)g(one)g(of)0 992 y(its)i(loaded)g(packages)g(\(such)g(as)h +(Tk\).)47 b(There)30 b(are)h(se)n(v)o(eral)f(w)o(ays)g(to)g(w)o(ork)g +(around)g(the)g(unfortunate)g(conse-)0 1112 y(quences)i(of)f(multiply)f +(de\002ning)h(command)f(names,)j(b)n(ut)e(the)g(easiest)h(is)f(to)g +(mak)o(e)g(use)h(of)f(the)h(Tcl)f(concept)0 1233 y(of)i +Fi(namespaces)p Fh(.)56 b(A)33 b(complete)g(description)f(of)h(Tcl)g +(namespaces)h(is)e(be)o(yond)h(the)g(scope)g(of)g(this)f(tutorial;)0 +1353 y(ho)n(we)n(v)o(er)l(,)24 b(a)h(simple)f(description)f(suf)n +(\002ces.)32 b(By)25 b(pre\002xing)g(a)g(\223scope\224)h(to)e(the)h +(command,)f(the)h(command)f(can)0 1474 y(only)33 b(be)g(e)o(x)o(ecuted) +g(when)g(the)g(complete)g(name)g(\(scope)g(plus)g(the)g(double)g(colon) +g(`::')47 b(plus)33 b(the)g(command)0 1594 y(name\))25 +b(is)f(entered.)146 1714 y(In)g(general,)g(the)g(ED)l(A)g(tools)e(mak)o +(e)i(an)g(attempt)f(to)g(allo)n(w)g(commands)g(to)g(be)h(entered)g +(without)f(the)g(scope)0 1835 y(pre\002x)g(at)f(the)g(command)g(line.) +29 b(As)22 b(long)g(as)g(command)f(names)h(are)h(unique,)f(this)g(is)f +(done)h(without)f(comment.)0 1955 y(Ho)n(we)n(v)o(er)l(,)29 +b(when)g(commands)e(o)o(v)o(erlap,)i(the)g(easiest)g(solution)e(is)h +(to)h(require)g(the)g(scope)g(pre\002x.)43 b(Therefore,)0 +2076 y(the)27 b(command)g(`)p Ff(set)p Fh(')h(w)o(ould)f(refer)i(to)e +(the)h(Tcl)f Ff(set)h Fh(command)f(\(i.e.,)h(to)f(set)h(a)g(v)n +(ariable\),)g(while)f(`)p Ff(irsim::set)p Fh(')0 2196 +y(w)o(ould)e(refer)h(to)f(the)g(IRSIM)i(command.)k(Some)26 +b(attempt)e(is)h(made)h(to)f(o)o(v)o(erload)f(commands)g(which)h +(con\003ict)0 2316 y(b)n(ut)k(which)g(ha)n(v)o(e)g(unique)g(syntax,)h +(so)f(that)g(it)g(is)g(possible)f(to)i(determine)f(which)g(use)g(is)g +(intended)g(when)g(the)0 2437 y(command)24 b(is)g(dispatched)g(by)h +(the)f(interpreter)-5 b(.)146 2557 y(In)30 b(addition)e(to)h(the)h(w)o +(arnings,)g(there)g(are)g(a)g(fe)n(w)f(standard)h(w)o(arnings)f(about)g +(global)f(name)i(aliases)f(and)0 2677 y(lumped)24 b(resistance,)g(and)h +(some)f(information)g(about)g(the)h Fd(.sim)f Fh(\002le)h(which)f(w)o +(as)h(read.)0 3011 y Fj(3)143 b(IRSIM)35 b(Command)f(Set)0 +3235 y Fh(In)27 b(addition)e(to)h(the)g(e)o(xceptions)f(noted)h(abo)o +(v)o(e)g(for)h(fully-quali\002ed)e(namespace)i(commands,)f(there)g(are) +i(se)n(v-)0 3355 y(eral)i(IRSIM)h(commands)e(which)h(are)g(not)g +(compatible)f(with)g(Tcl)h(syntax,)g(and)g(these)g(ha)n(v)o(e)g(been)g +(renamed.)0 3475 y(The)d(old)e(and)i(ne)n(w)f(commands)f(are)i(as)g +(follo)n(ws)e(\(see)i(the)f(IRSIM)i(documentation)c(for)j(the)f(full)g +(set)h(of)f(com-)0 3596 y(mands\):)p 457 3690 2987 4 +v 455 3811 4 121 v 507 3775 a(\277)122 b(sa)n(v)o(estate)633 +b(sa)n(v)o(e)25 b(netw)o(ork)f(state)p 3441 3811 V 455 +3931 V 507 3895 a(\241)133 b(restorestate)536 b(restore)25 +b(netw)o(ork)g(state)p 3441 3931 V 455 4051 V 507 4015 +a(\241\241)100 b(restoreall)619 b(restore)25 b(netw)o(ork)g(and)f +(input)g(state)p 3441 4051 V 455 4172 V 507 4136 a(?)122 +b(querysource)503 b(get)25 b(info)f(re)o(garding)g(source/drain)g +(connections)p 3441 4172 V 455 4292 V 507 4256 a(!)133 +b(querygate)597 b(get)25 b(info)f(re)o(garding)g(gate)g(connections)p +3441 4292 V 455 4413 V 673 4376 a(source)h Fi(\(Tcl)g(command\))99 +b Fh(source)25 b(a)g(command)f(\002le)p 3441 4413 V 457 +4416 2987 4 v 146 4557 a(Note)k(that)f(the)g(`')h(command)f(is)g +(simply)f(superceded)i(by)f(the)g(Tcl)h(`)p Ff(sour)n(ce)p +Fh(')h(command,)e(which)g(is)g(more)0 4678 y(general)36 +b(in)f(that)h(it)f(allo)n(ws)f(a)i(mixture)f(of)h(Tcl)f(and)h(IRSIM)g +(commands)f(\(and)h(commands)e(for)i(an)o(y)f(other)0 +4798 y(loaded)25 b(package,)g(such)f(as)h(Magic\))g(to)f(be)h(combined) +f(in)g(the)h(command)f(\002le.)146 4918 y(Once)40 b(loaded)f(into)g +(Tcl)h(alongside)e(Magic)h(via)h(the)f Ff(irsim)g Fh(command,)j(the)e +(IRSIM)g(commands)e(are)0 5039 y(typed)24 b(directly)g(into)f(the)i +(Magic)f(command)f(line,)h(and)h(will)e(e)o(x)o(ecute)h(the)g +(appropriate)h(IRSIM)g(function.)30 b(By)0 5159 y(repeating)23 +b(the)h(contents)e(of)i(T)l(utorial)e(#11)h(in)g(the)g(Tcl)h(en)l +(vironment,)e(this)h(method)f(should)g(become)i(clear)l(,)g(as)0 +5280 y(will)g(the)h(bene\002ts)f(of)h(using)f(the)h(interpreter)g(en)l +(vironment)e(for)i(simulation.)146 5400 y(T)-8 b(o)25 +b(setup)f(the)h(simulation,)d(the)j(equi)n(v)n(alent)e(instruction)g +(to)h(that)h(of)g(T)l(utorial)e(#11)h(is)h(the)f(follo)n(wing:)1875 +5649 y(\2263\226)p eop end +%%Page: 4 4 +TeXDict begin 4 3 bop 0 -180 a Fh(April)24 b(14,)h(2006)1437 +b(Magic)25 b(Tcl)f(T)l(utorial)g(#4:)30 b(Simulation)23 +b(with)h(IRSIM)900 84 y Fi(\045)50 b Fe(source)58 b($)p +Fc(f)p Fe(CAD)p 1747 84 30 4 v 35 w(HOME)p Fc(g)p Fe +(/lib/magic/tutorial/tut11)o(a.cm)o(d)146 297 y Fh(Note)24 +b(that)g(because)g(the)g Ff(sour)n(ce)h Fh(command)e(is)g(a)h(Tcl)g +(command,)f(not)h(a)g(Magic)g(or)g(IRSIM)h(command,)e(it)0 +417 y(it)i(necessary)g(to)g(specify)g(the)g(complete)g(path)f(to)h(the) +g(\002le,)h(as)f(Tcl)g(does)g(not)g(understand)f(the)h(search)h(path)f +(for)0 538 y(Magic)f(cells,)h(which)f(includes)g(the)h(tutorial)f +(directory)-6 b(.)146 658 y(As)33 b(most)f(common)g(commands)g(are)i +(not)f(among)f(the)h(set)g(that)g(cause)h(con\003icts)f(with)f(Magic)h +(and)g(Tcl)0 778 y(commands,)23 b(the)i(tutorial)f(command)g(\002le)h +(loads)f(and)h(e)o(x)o(ecutes)f(without)f(comment.)146 +899 y(F)o(ollo)n(wing)32 b(the)i(e)o(xample)f(of)h(T)l(utorial)f(#11,)i +(type)f Ff(c)g Fh(\(IRSIM)h(clock)f(command\))f(on)h(the)g(magic)f +(com-)0 1019 y(mand)28 b(line)h(to)g(clock)g(the)f(circuit.)43 +b(V)-11 b(alues)29 b(for)g(the)g(w)o(atched)g(nodes,)h(which)e(were)i +(declared)g(in)e(the)h(tutorial)0 1139 y(command)24 b(\002le,)h(are)h +(displayed)d(in)i(the)f(console)h(windo)n(w)-6 b(.)28 +b(Lik)o(e)n(wise,)900 1331 y Fe(h)60 b(RESET)p 1326 1331 +V 34 w(B)g(hold)0 1523 y Fh(will)24 b(set)h(the)f(nodes)g +Fe(RESET)p 1025 1523 V 35 w(B)h Fh(and)g Fe(hold)f Fh(to)g(v)n(alue)g +(1.)0 1860 y Fj(4)143 b(F)l(eedback)34 b(to)i(Magic)0 +2084 y Fh(The)31 b(cross-application)f(commands)g(re)n(v)o(eal)h(the)g +(usefulness)f(of)h(ha)n(ving)g(both)f(applications)g(as)h(e)o +(xtensions)0 2204 y(of)25 b(the)g(same)f(Tcl)h(interpreter)-5 +b(.)146 2324 y(While)34 b(Magic)g(and)g(IRSIM)g(are)h(acti)n(v)o(e)e +(and)h(\002le)h Fd(tut11a)d Fh(is)i(loaded,)i(e)o(x)o(ecute)d(the)h +(follo)n(wing)e(com-)0 2445 y(mands)24 b(from)h(the)f(command)g(line:) +900 2636 y Fe(stepsize)58 b(100)900 2757 y(watchnode)g(RESET)p +1804 2757 V 35 w(B)900 2877 y(watchnode)g(hold)0 3069 +y Fh(Note)30 b(that)g(the)g(nodes)g(and)g(v)n(alues)g(are)h +(immediately)e(printed)g(in)h(the)g(magic)g(windo)n(w)-6 +b(,)30 b(making)g(use)g(of)g(the)0 3189 y(magic)c(\223)p +Ff(element)p Fh(\224)h(command.)34 b(These)26 b(v)n(alues)g(are)h +(persisent)e(in)h(the)g(sense)g(that)g(the)o(y)f(will)g(remain)h +(through)0 3309 y(v)n(arious)19 b(transformations,)h(openings,)g(and)g +(closings)f(of)h(the)g(layout)f(windo)n(w)-6 b(,)20 b(b)n(ut)f(the)o(y) +h(are)h(temporary)e(in)h(the)0 3430 y(sense)25 b(that)g(the)o(y)f(will) +h(not)f(be)i(sa)n(v)o(ed)e(along)h(with)f(the)h(layout)g(if)g(the)g +(\002le)h(is)f(written)f(\(ho)n(we)n(v)o(er)l(,)g(this)g(beha)n(vior)0 +3550 y(can)h(be)g(modi\002ed\).)146 3671 y(The)i Ff(watchnode)h +Fh(command)d(requires)i(no)f(special)g(action)g(for)h(placing)f(the)h +(label)f(elements)g(in)g(the)g(lay-)0 3791 y(out)31 b(because)i(magic)e +(uses)h(the)g(labels)f(or)h(other)g(node)g(information)e(to)i(pinpoint) +e(a)i(position)f(in)g(the)h(layout)0 3911 y(belonging)d(to)h(that)g +(node,)i(and)e(places)h(the)f(label)g(element)g(there.)48 +b(It)30 b(is)g(possible)g(to)g(use)g Ff(watchnode)i Fh(with)0 +4032 y(v)o(ectors.)d(Ho)n(we)n(v)o(er)l(,)23 b(as)g(no)g(location)f +(can)h(be)g(pinpointed)f(for)h(a)g(v)o(ector)l(,)g(the)g(magic)g +(cursor)g(box)g(position)e(will)0 4152 y(be)k(used)f(to)h(place)g(the)g +(label)f(element.)146 4273 y(Mo)o(v)o(e)g(the)g(magic)h(cursor)g(box)f +(to)g(a)h(empty)f(space)i(in)e(the)h(layout)f(windo)n(w)-6 +b(,)23 b(and)h(type)900 4464 y Fe(watchnode)58 b(bits)146 +4656 y Fh(No)n(w)24 b(mo)o(v)o(e)g(the)g(cursor)h(box)g(to)f(another)h +(empty)f(space)h(and)g(type)900 4847 y Fe(watchtime)0 +5039 y Fh(No)n(w)f(all)h(of)g(the)f(simulation)f(v)n(alues)h(of)h +(interest)f(are)h(displayed)f(directly)g(on)h(the)g(Magic)f(layout.)146 +5159 y(The)31 b(display)f(of)h(an)o(y)g(node)f(can)i(be)f(remo)o(v)o +(ed)e(with)i(the)f(command)g Fe(unwatchnode)p Fh(,)g(with)g(the)h(same) +0 5280 y(syntax)k(as)h Fe(watchnode)p Fh(,)h(and)f(similarly)-6 +b(,)36 b(the)g(display)f(of)h(simulation)e(time)h(can)h(be)g(remo)o(v)o +(ed)f(with)g(the)0 5400 y(command)24 b Fe(unwatchtime)p +Fh(.)1875 5649 y(\2264\226)p eop end +%%Page: 5 5 +TeXDict begin 5 4 bop 0 -180 a Fh(Magic)24 b(Tcl)h(T)l(utorial)f(#4:)30 +b(Simulation)23 b(with)h(IRSIM)1439 b(April)24 b(14,)h(2006)146 +68 y(If)i(the)f(position)f(of)h(a)h(label)f(is)g(not)g(in)g(a)g(good)g +(position)f(to)h(read,)h(or)f(the)g(relati)n(v)o(e)g(position)e(of)j +(tw)o(o)f(labels)0 188 y(places)31 b(them)e(on)i(top)e(of)i(one)f +(another)l(,)i(making)e(them)f(dif)n(\002cult)h(to)g(read,)j(the)d +(labels)g(can)h(be)f(mo)o(v)o(ed)f(using)0 309 y(the)g +Ff(mo)o(v)o(enode)g Fh(command.)42 b(F)o(or)29 b(instance,)g(the)g +(node)f Fd(RESET)p 2296 309 30 4 v 35 w(B)h Fh(is)f(not)g(e)o(xactly)g +(on)h(the)f(polysilicon)f(pad.)0 429 y(T)-8 b(o)25 b(center)g(it)f(e)o +(xactly)g(on)h(the)g(pad,)f(select)h(the)g(square)g(pad,)f(so)h(that)f +(the)h(box)f(cursor)h(is)f(on)h(it,)f(then)g(do)900 689 +y Fe(movenode)58 b(RESET)p 1744 689 V 35 w(B)0 939 y +Fh(The)36 b(label)g(will)f(be)h(mo)o(v)o(ed)f(so)g(that)h(it)f(is)h +(centered)h(on)e(the)h(center)h(of)f(the)g(cursor)g(box.)64 +b(The)36 b(equi)n(v)n(alent)0 1060 y(method)24 b(can)h(be)g(applied)f +(to)h(the)f(time)g(v)n(alue)g(using)g(the)h Fe(movetime)e +Fh(command.)146 1190 y(It)g(is)g(not)g(necessary)g(to)g(kno)n(w)f(the)h +(name)g(of)g(a)g(node)g(in)g(order)h(to)e(query)h(or)g(display)g(its)f +(simulation)f(v)n(alue.)0 1310 y(F)o(or)28 b(instance,)g(une)o(xpand)e +(the)i(layout)f(of)h Fd(tut11a.mag)p Fh(,)e(select)i(an)f(unlabeled)h +(node,)g(and)f(use)h(a)g(mixture)0 1430 y(of)d(IRSIM)h(and)e(magic)h +(commands)e(to)i(w)o(atch)g(its)f(v)n(alue:)900 1690 +y Fe(box)59 b(93)g(-104)g(94)h(-102)900 1811 y(select)e(area)900 +1931 y(watchnode)g([getnode])0 2302 y Fh(In)39 b(this)f(e)o(xample,)k +(both)c(the)h(node)g(\()p Fd(bit)p 1538 2302 V 35 w(1/tut11d)p +2053 2302 V 35 w(0/a)p 2268 2302 V 35 w(39)p 2423 2302 +V 35 w(n23#)p Fh(\))g(and)g(its)f(v)n(alue)g(are)i(displayed.)0 +2422 y(Lik)o(e)n(wise,)32 b(the)f Ff(getnode)h Fh(command)e(can)i(be)f +(combined)f(with)h(other)g(IRSIM)h(commands)e(to)h(setup)f(clocks)0 +2543 y(and)g(v)o(ectors)f(from)g(unlabeled)g(nodes.)45 +b(This)29 b(can)h(be)g(particularly)f(useful)g(in)g(situations)f(where) +i(it)f(may)h(not)0 2663 y(be)25 b(ob)o(vious)e(which)h(nodes)h(in)f(a)h +(design)f(need)h(to)g(be)g(e)o(xamined)e(prior)i(to)f(running)g(the)h +(simulation.)0 3063 y Fj(5)143 b(Analyzer)34 b(Display)0 +3306 y Fh(Tcl-based)g(IRSIM)h(has)f(a)g(graphical)g(node)g(display)f +(which)g(is)h(deri)n(v)o(ed)f(from)g(functions)g(a)n(v)n(ailable)h(in)f +(the)0 3426 y(\223)p Ff(BL)-9 b(T)p Fh(\224)27 b(graphics)e(package.)32 +b(These)25 b(functions)f(are)i(not)e(particularly)h(well-suited)f(for)h +(display)f(of)h(logic)g(v)n(al-)0 3547 y(ues,)d(and)g(so)f(this)g(will) +f(probably)h(be)h(replaced)g(in)f(the)h(future)g(with)e(a)i(more)g +(appropriate)f(interf)o(ace.)30 b(Ho)n(we)n(v)o(er)l(,)0 +3667 y(it)24 b(accomplishes)g(most)g(of)h(the)f(functions)g(of)h(the)f +(former)h(X11-based)g(analyzer)g(display)-6 b(.)146 3797 +y(In)27 b(the)f(Tcl-based)g(IRSIM,)h(no)f(special)g(command)g(is)g +(needed)g(to)g(initialize)f(the)h(analyzer)h(display)-6 +b(.)34 b(One)0 3917 y(command)24 b(sets)g(up)h(signals)e(to)i(be)g +(displayed)f(in)g(the)h(analyzer)g(windo)n(w)-6 b(.)29 +b(This)24 b(is:)900 4177 y Fe(graphnode)f Fi(name)i Fh([)p +Fi(r)l(ow)p Fh(])f([)p Fi(of)n(fset)p Fh(])0 4428 y(F)o(or)h(display)f +(of)h(multiple)f(signals)g(in)g(the)h(windo)n(w)-6 b(,)23 +b(the)i(optional)f(ar)n(guments)h Fi(r)l(ow)f Fh(and)h +Fi(of)n(fset)g Fh(are)g(pro)o(vided.)0 4548 y(Each)g(signal)f(which)g +(declares)h(a)g(ne)n(w)f Fi(r)l(ow)g Fh(\(def)o(ault)h(zero\))g(will)f +(appear)h(in)f(a)h(separate)g(graph)g(in)f(the)h(display)-6 +b(.)0 4668 y(Signals)33 b(which)f(appear)i(in)f(the)g(same)g(graph,)i +(ho)n(we)n(v)o(er)l(,)f(may)f(declare)h(a)f(non-zero)h +Fi(of)n(fset)e Fh(which)h(will)f(set)0 4789 y(them)23 +b(at)h(a)h(dif)n(ferent)e(v)o(ertical)h(placement)f(on)h(the)g(graph,)g +(for)g(cases)h(in)e(which)h(this)f(pro)o(vides)g(better)g(vie)n(wing)0 +4909 y(than)h(ha)n(ving)h(the)f(signals)g(directly)g(o)o(v)o +(erlapping.)146 5039 y(The)29 b(analyzer)h(display)e(updates)h(at)g +(the)g(end)g(of)g(each)h(simulation)d(c)o(ycle.)43 b(Logic)29 +b(v)n(alues)f(are)i(displayed)0 5159 y(as)38 b(0)g(or)g(1,)j(with)c +(unde\002ned)h(\(v)n(alue)f('X'\))i(v)n(alues)e(displayed)g(as)h(1/2.) +69 b(Note)38 b(that)g(the)f(BL)-9 b(T)g(-based)38 b(inter)n(-)0 +5280 y(f)o(ace)d(prohibits)d(the)h(display)g(of)h(multi-bit)e(v)n +(alues,)j(and)e(only)g(nodes,)j(not)d(v)o(ectors,)i(can)f(be)g(passed)g +(to)f(the)0 5400 y Fe(graphnode)23 b Fh(command.)1875 +5649 y(\2265\226)p eop end +%%Page: 6 6 +TeXDict begin 6 5 bop 0 -180 a Fh(April)24 b(14,)h(2006)1437 +b(Magic)25 b(Tcl)f(T)l(utorial)g(#4:)30 b(Simulation)23 +b(with)h(IRSIM)0 99 y Fj(6)143 b(W)m(ildcards)0 322 y +Fh(The)35 b(original)f(IRSIM)i(used)f(\223wildcard\224)g(characters)g +(in)g(the)g(form)g(of)g(standard)f(UNIX)h(\223re)o(gular)g(e)o(xpres-)0 +443 y(sions\224)d(to)h(perform)h(operations)e(on)h(multiple)f(nodes)h +(with)f(one)i(command.)55 b(Unfortunately)-6 b(,)34 b(there)f(w)o(as)h +(a)0 563 y(syntactical)c(collision)f(between)h(IRSIM)h(and)g(Magic)f(o) +o(v)o(er)g(the)g(use)h(of)f(brack)o(ets)h(\(`)p Fe([)p +Fh(')g(and)f(`)p Fe(])p Fh('\).)48 b(Brack)o(ets)0 683 +y(represent)20 b(groupings)e(in)h(re)o(gular)g(e)o(xpression)f(syntax.) +29 b(Ho)n(we)n(v)o(er)l(,)19 b(Magic)g(uses)g(brack)o(ets)h(to)f +(represent)h(arrays)0 804 y(of)29 b(subcells.)42 b(Because)30 +b(Tcl)f(itself)f(implements)f(re)o(gular)i(e)o(xpressions)e(in)i(the)g +(form)f(of)h(the)g(Tcl)g(\223)p Fe(regexp)p Fh(\224)0 +924 y(command,)34 b(there)f(is)f(a)h(w)o(ay)g(around)f(this)g(problem)g +(in)g(the)g(Tcl)h(v)o(ersion)f(of)g(IRSIM.)i(IRSIM')-5 +b(s)33 b(parsing)f(of)0 1045 y(re)o(gular)27 b(e)o(xpressions)f(has)i +(been)f(disabled.)38 b(In)28 b(place)f(of)h(it,)g(Tcl)f(lists)f(may)h +(be)h(passed)f(as)h(ar)n(guments)f(to)g(an)o(y)0 1165 +y(command)j(which)h(pre)n(viously)e(w)o(ould)h(accept)i(wildcard)e +(characters.)50 b(In)31 b(addition,)h(Tcl-IRSIM)f(de\002nes)h(a)0 +1285 y(command)900 1480 y Fe(listnodes)0 1675 y Fh(which)23 +b(returns)g(a)g(Tcl)g(list)f(of)h(all)g(the)g(nodes)g(de\002ned)g(in)g +(the)g(netlist)f(input)g(\002le.)30 b(This)23 b(list)f(can)h(be)h +(searched)f(by)0 1795 y(Tcl)k(re)o(gular)f(e)o(xpression)g(commands,)f +(and)i(the)g(resulting)e(sub-lists)g(passed)i(as)f(node)h(ar)n(guments) +f(to)g(IRSIM)0 1916 y(commands.)38 b(F)o(or)27 b(e)o(xample,)g(the)h +(follo)n(wing)d(script)i(sets)g(all)g(nodes)g(in)g(the)h(circuit)f(\(e) +o(xcept)g(for)h Fd(Vdd)p Fh(,)g(which)0 2036 y(is)c(\002x)o(ed\))h(to)g +(zero,)g(then)f(releases)i(them:)900 2231 y Fe(set)59 +b(nl)g([listnodes])900 2351 y(l)h($nl)900 2472 y(s)900 +2592 y(x)g($nl)146 2787 y Fh(Brack)o(ets)33 b(in)f(indi)n(vidual)d +(node)j(names)g(are)h(treated)f(as-is)g(by)f(IRSIM,)i(as)f(are)h(other) +f(Magic-generated)0 2907 y(characters)25 b(such)e(as)h(the)g(slash,)f +(underscore,)h(and)g(hash)g(mark.)30 b(Note,)24 b(ho)n(we)n(v)o(er)l(,) +e(that)i(because)g(Tcl)g(itself)f(de-)0 3028 y(\002nes)f(brack)o(ets)g +(as)g(representing)g(command)f(groupings)f(which)i(return)g(an)g +(immediate)e(result,)i(the)g(follo)n(wing)0 3148 y(is)i(ille)o(gal:)900 +3343 y Fi(\045)h Fe(l)59 b(multcell5)p 1673 3343 30 4 +v 34 w(0[1,0]/a)p 2187 3343 V 34 w(13)p 2341 3343 V 36 +w(n21#)900 3463 y Fd(invalid)f(command)g(name)h("1,0")0 +3658 y Fh(Instead,)42 b(node)d(names)g(containing)e(brack)o(ets)i +(should)f(be)h(surrounded)f(by)h(braces)g(\(`)p Fc(f)p +Fh(')h(and)f(`)p Fc(g)p Fh('\),)k(which)0 3778 y(ef)n(fecti)n(v)o(ely) +36 b(turns)h(a)h(node)g(name)f(into)g(a)h(list)f(of)h(node)f(names)g +(which)h(happens)f(to)g(contain)g(e)o(xactly)g(one)0 +3899 y(entry:)900 4093 y Fi(\045)25 b Fe(l)59 b Fc(f)p +Fe(multcell5)p 1723 4093 V 34 w(0[1,0]/a)p 2237 4093 +V 34 w(13)p 2391 4093 V 36 w(n21#)p Fc(g)0 4409 y Fh(The)38 +b(Tcl)g(v)o(ersions)f(of)h(Magic)g(and)g(IRSIM)h(are)g(set)f(up)g(in)g +(such)g(a)g(w)o(ay)h(that)e(when)h(the)o(y)g(return)g(results)0 +4529 y(containing)24 b(node)g(names,)g(these)h(names)g(are)g +(automatically)e(treated)i(as)g(lists.)30 b(Therefore,)25 +b(the)g(command)900 4724 y Fi(\045)g Fe(select)58 b(area)h([goto)g +Fc(f)p Fe(multcell5)p 2680 4724 V 34 w(0[1,0]/a)p 3194 +4724 V 34 w(13)p 3348 4724 V 35 w(n21#)p Fc(g)24 b Fe(])900 +4844 y Fi(\045)h Fe(l)59 b([getnode])0 5039 y Fh(does)32 +b(not)f(produce)h(an)o(y)g(error)g(when)g(the)g(arrayed)h(node)e(name)h +(is)g(passed)g(to)f(the)h(IRSIM)h(\223)p Fe(l)p Fh(\224)f(command,)0 +5159 y(and)g(sets)f(the)h(v)n(alue)f(of)h(the)g(node)f(to)h(zero)g(as)g +(e)o(xpected.)52 b(It)31 b(is)h(only)f(when)h(node)f(names)h(are)g +(entered)g(in)g(a)0 5280 y(script)20 b(or)g(from)g(the)g(command)f +(line)h(that)f(precautions)h(must)f(be)h(tak)o(en)g(to)g(list-enclose)f +(names)h(which)g(contain)0 5400 y(brack)o(ets.)1875 5649 +y(\2266\226)p eop end +%%Page: 7 7 +TeXDict begin 7 6 bop 0 -180 a Fh(Magic)24 b(Tcl)h(T)l(utorial)f(#4:)30 +b(Simulation)23 b(with)h(IRSIM)1439 b(April)24 b(14,)h(2006)0 +99 y Fj(7)143 b(Scripting)34 b(IRSIM)h(Command)f(Sequences)0 +324 y Fh(A)i(consequence)h(of)g(placing)e(IRSIM)j(in)e(an)g +(interpreter)h(en)l(vironment)e(is)h(the)g(ability)g(to)g(use)g +(interpreter)0 444 y(features)25 b(such)g(as)g(v)n(ariables,)f +(conditionals,)e(and)j(loops)f(to)g(set)h(up)g(complicated)e +(simulation)g(en)l(vironments.)0 788 y Fj(8)143 b(Deterministic)33 +b(Bit)i(V)-14 b(ector)34 b(Generation)0 1013 y Fh(A)23 +b(con)l(v)o(enience)g(function)f(has)i(been)f(added)g(to)g(Tcl-IRSIM)h +(to)f(aid)g(in)g(generating)g(deterministic)e(sequences)0 +1134 y(of)k(inputs.)k(This)24 b(is)h(the)f(command)900 +1341 y Fe(bconvert)f Fi(value)i(bits)f Fh([)p Fi(dir)p +Fh(])0 1548 y(where)j Fi(value)f Fh(is)h(an)f(inte)o(ger)g(decimal)g(v) +n(alue,)g Fi(bits)g Fh(is)g(the)g(length)g(of)h(the)f(bit)g(v)o(ector)g +(to)g(hold)g(the)g(con)l(v)o(ersion,)0 1669 y(and)g Fi(dir)g +Fh(is)g(an)h(optional)e(direction)h(\003ag.)36 b(If)27 +b Fi(dir)f Fh(is)g(1,)h(then)f(the)h(bit)e(v)o(ector)h(is)g(de\002ned)h +(with)f(the)g(most)g(signif-)0 1789 y(icant)i(bit)g(\(MSB\))h(on)f(the) +g(right.)41 b(The)28 b Fe(bconvert)f Fh(command)g(returns)h(the)g +(string)g(v)n(alue)f(of)i(the)f(bit)g(v)o(ector)0 1909 +y(containing)c Fd(0)g Fh(and)h Fd(1)g Fh(characters.)31 +b(F)o(or)25 b(e)o(xample:)900 2143 y Fi(\045)g Fe(bconvert)58 +b(20)h(5)900 2264 y Fd(10100)900 2384 y Fi(\045)25 b +Fe(bconvert)58 b(20)h(5)h(1)900 2504 y Fd(00101)0 2849 +y Fj(9)143 b(Random)34 b(Bit)h(V)-14 b(ector)34 b(Generation)0 +3074 y Fh(The)c(tutorial)f(e)o(xamples)g(are)i(small)e(by)h(design,)g +(b)n(ut)f(real)i(systems)e(\(such)g(as)i(a)f(microprocessor\))f(are)i +(often)0 3194 y(so)d(comple)o(x)f(that)h(generating)g(and)g(simulating) +e(an)i(e)o(xhausti)n(v)o(e)e(set)i(of)h(all)f(possible)e(states)i(of)h +(the)f(circuit)g(is)0 3314 y(impossible,)h(and)h(instead)g(simulations) +d(rely)k(on)e(the)h(generation)g(of)g(a)h(set)f(of)g +(randomly-generated)f(inputs)0 3435 y(to)24 b(test)h(a)g(representati)n +(v)o(e)f(set)g(of)h(states.)146 3556 y(Random)19 b(number)g(generation) +g(is)g(not)g(a)g(b)n(uilt-in)f(feature)i(of)f(the)h(Tcl)f(language,)h +(b)n(ut)f(se)n(v)o(eral)f(open-source)0 3676 y(packages)23 +b(e)o(xist,)e(one)i(of)f(which)g(has)h(been)f(incorporated)h(into)e +(the)h(IRSIM)i(9.6)e(source.)30 b(The)22 b(pseudorandom)0 +3797 y(number)h(generator)g(is)g(compiled)f(as)h(a)g(separate)h(Tcl)f +(package,)h(b)n(ut)e(is)h(loaded)g(by)f(the)h(IRSIM)h(startup)f +(script.)0 3917 y(It)i(contains)f(one)h(command,)e Fe(random)p +Fh(,)h(with)g(the)g(follo)n(wing)f(ar)n(guments:)900 +4125 y Fe(random)h Fi(option)0 4331 y Fh(where)h Fi(option)f +Fh(may)g(be)h(one)g(of:)244 4538 y Fe(-reset)e Fh(will)h(cause)i(the)e +(generator)h(to)g(be)g(reseeded)g(using)f(current)h(pid)f(and)h +(current)g(time.)244 4745 y Fe(-seed)f Fi(n)g Fh(will)g(reseed)i(the)e +(generator)h(with)f(the)h(inte)o(ger)f(v)n(alue)g Fi(n)p +Fh(.)244 4952 y Fe(-integer)e Fi(...)30 b Fh(will)23 +b(cause)h(the)g(number)f(returned)h(to)f(be)h(rounded)f(do)n(wn)g(to)g +(the)h(lar)n(gest)g(inte)o(ger)f(less)244 5073 y(than)h(or)h(equal)g +(to)f(the)h(number)f(which)h(w)o(ould)f(otherwise)g(be)h(returned.)244 +5280 y Fe(-normal)e Fi(m)h(s)h Fh(will)e(cause)i(the)f(number)g +(returned)h(to)f(be)g(tak)o(en)h(from)f(a)h(gaussian)e(with)g(mean)i +Fi(m)f Fh(and)244 5400 y(standard)g(de)n(viation)g Fi(s)p +Fh(.)1875 5649 y(\2267\226)p eop end +%%Page: 8 8 +TeXDict begin 8 7 bop 0 -180 a Fh(April)24 b(14,)h(2006)1437 +b(Magic)25 b(Tcl)f(T)l(utorial)g(#4:)30 b(Simulation)23 +b(with)h(IRSIM)244 68 y Fe(-exponential)h Fi(m)i Fh(will)g(cause)g(the) +g(number)g(returned)h(to)f(be)g(tak)o(en)h(from)f(an)g(e)o(xponential)f +(distri-)244 188 y(b)n(ution)d(with)h(mean)h Fi(m)p Fh(.)244 +392 y Fe(-uniform)h Fi(low)i(high)f Fh(will)g(cause)h(the)g(number)g +(returned)g(to)f(be)h(tak)o(en)g(from)g(uniform)f(distrib)n(ution)244 +512 y(on)d Fi([a,b\))p Fh(.)244 716 y Fe(-chi2)18 b Fi(n)i +Fh(will)e(cause)i(the)f(number)g(returned)h(to)f(be)g(tak)o(en)h(from)f +(the)g(chi2)g(distrib)n(ution)e(with)i Fi(n)g Fh(de)o(grees)244 +836 y(of)25 b(freedom.)244 1039 y Fe(-select)32 b Fi(n)h(list)g +Fh(will)f(cause)i Fi(n)f Fh(elements)g(to)g(be)h(selected)f(at)h +(random)e(from)i(the)f(list)f Fi(list)h Fh(with)f(re-)244 +1160 y(placement.)244 1363 y Fe(-choose)h Fi(n)h(list)g +Fh(will)f(cause)i Fi(n)g Fh(elements)e(to)h(be)h(selected)g(at)f +(random)g(from)g(the)h(list)e Fi(list)h Fh(without)244 +1483 y(replacement.)244 1687 y Fe(-permutation)24 b Fi(n)i +Fh(will)f(return)i(a)g(permutation)e(of)h Fb(0)17 b Fa(:)g(:)g(:)f(n)23 +b Fc(\000)h Fb(1)i Fh(if)g Fi(n)h Fh(is)f(a)g(number)g(and)h(will)e +(return)244 1807 y(a)g(permutation)e(of)i(its)f(elements)g(if)h +Fi(n)g Fh(is)f(a)h(list.)146 2011 y(The)39 b(follo)n(wing)e(script)i +(clocks)f(a)i(random)e(serial)h(bit)f(v)o(ector)h(into)f(a)h(state)g +(machine,)j(assuming)c(that)0 2131 y Fe(bit)p 186 2131 +30 4 v 35 w(in)25 b Fh(is)f(the)h(node)f(to)h(set,)f(and)h(that)f(the)h +(proper)g(clock)g(v)o(ectors)f(ha)n(v)o(e)g(already)h(been)g(set)g(up:) +600 2334 y(for)g Fc(f)p Fh(set)f(i)h(0)p Fc(g)g(f)p Fh($i)f(\241)h(100) +p Fc(g)f(f)p Fh(incr)h(i)p Fc(g)f(f)900 2455 y Fh(if)h +Fc(f)p Fh([random])f(\241)h(0.5)p Fc(g)g(f)1421 2575 +y Fh(l)g(bit)p 1586 2575 V 35 w(in)900 2696 y Fc(g)g +Fh(else)g Fc(f)1421 2816 y Fh(h)g(bit)p 1608 2816 V 35 +w(in)900 2936 y Fc(g)900 3057 y Fh(c)600 3177 y Fc(g)1875 +5649 y Fh(\2268\226)p eop end +%%Trailer + +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tuttcl5.ps b/doc/psfiles/tuttcl5.ps new file mode 100644 index 00000000..f4c0b5a8 --- /dev/null +++ b/doc/psfiles/tuttcl5.ps @@ -0,0 +1,242 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: tuttcl5.dvi +%%Pages: 1 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -t letter tuttcl5.dvi -o ../psfiles/tuttcl5.ps +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2006.04.12:1204 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: texps.pro +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type/integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics/Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{ +dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 +roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def +dup[exch{dup CharStrings exch known not{pop/.notdef/Encoding true def} +if}forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def} +def end + +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tuttcl5.dvi) +@start /Fa 105[50 28[50 2[50 50 28 39 33 1[50 50 50 78 +28 50 1[28 50 50 1[44 50 44 50 44 11[72 61 55 2[55 2[89 +61 1[39 1[72 3[72 2[72 9[50 3[50 50 50 50 1[25 33 25 +44[{TeXBase1Encoding ReEncodeFont}39 99.6264 /Times-Roman +rf /Fb 134[44 1[66 2[28 39 39 2[50 1[72 3[28 50 3[50 +2[50 12[55 1[61 12[61 22[25 46[{TeXBase1Encoding ReEncodeFont}15 +99.6264 /Times-Italic rf /Fc 138[80 48 56 64 1[80 72 +80 1[40 2[40 1[72 48 2[64 1[72 9[143 2[96 80 5[135 18[48 +4[72 3[72 13[72 35[{TeXBase1Encoding ReEncodeFont}21 +143.462 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%BeginPaperSize: Letter +letter +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 328 101 a Fc(Magic)36 b(Tcl)f(T)-13 b(utorial)34 +b(#5:)43 b(Writing)35 b(Tcl)g(Scripts)g(f)l(or)g(Magic)1546 +521 y Fb(R.)25 b(T)-5 b(imothy)24 b(Edwar)l(ds)1583 941 +y Fa(Space)i(Department)1434 1062 y(Johns)e(Hopkins)g(Uni)n(v)o(ersity) +1391 1182 y(Applied)g(Physics)g(Laboratory)1578 1303 +y(Laurel,)h(MD)f(20723)819 1573 y(This)g(tutorial)g(corresponds)g(to)h +(Tcl-based)f(Magic)h(v)o(ersion)e(7.2)0 2320 y Fc(1)143 +b(Scripting)34 b(in)i(Magic)1875 5649 y Fa(\2261\226)p +eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/psfiles/tutwrl1.ps b/doc/psfiles/tutwrl1.ps new file mode 100644 index 00000000..9237bc16 --- /dev/null +++ b/doc/psfiles/tutwrl1.ps @@ -0,0 +1,820 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software +%%Title: tutwrl1.dvi +%%Pages: 4 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Italic Times-Roman +%%DocumentPaperSizes: Letter +%%EndComments +%DVIPSCommandLine: dvips tutwrl1.dvi -o tutwrl1.ps +%DVIPSParameters: dpi=600, comments removed +%DVIPSSource: TeX output 2001.09.26:1352 +%%BeginProcSet: tex.pro +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} +if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for +65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 +0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V +{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 +getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} +ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end +%%EndProcSet +%%BeginFont: Times-Bold +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def +%%EndFont +%%BeginProcSet: texps.pro +TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2 +index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont /setfont load]cvx def}def +/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def +/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def +end +%%EndProcSet +%%BeginProcSet: special.pro +TeXDict begin /SDict 200 dict N SDict begin /@SpecialDefaults{/hs 612 N +/vs 792 N /ho 0 N /vo 0 N /hsc 1 N /vsc 1 N /ang 0 N /CLIP 0 N /rwiSeen +false N /rhiSeen false N /letter{}N /note{}N /a4{}N /legal{}N}B +/@scaleunit 100 N /@hscale{@scaleunit div /hsc X}B /@vscale{@scaleunit +div /vsc X}B /@hsize{/hs X /CLIP 1 N}B /@vsize{/vs X /CLIP 1 N}B /@clip{ +/CLIP 2 N}B /@hoffset{/ho X}B /@voffset{/vo X}B /@angle{/ang X}B /@rwi{ +10 div /rwi X /rwiSeen true N}B /@rhi{10 div /rhi X /rhiSeen true N}B +/@llx{/llx X}B /@lly{/lly X}B /@urx{/urx X}B /@ury{/ury X}B /magscale +true def end /@MacSetUp{userdict /md known{userdict /md get type +/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup +length 20 add dict copy def}if end md begin /letter{}N /note{}N /legal{} +N /od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath +clippath mark{transform{itransform moveto}}{transform{itransform lineto} +}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{ +itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{ +closepath}}pathforall newpath counttomark array astore /gc xdf pop ct 39 +0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}N +/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 +scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get +ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip +not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 +TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{noflips{TR +pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 +-1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg +TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg +sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr +0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add +2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N /cp +{pop pop showpage pm restore}N end}if}if}N /normalscale{Resolution 72 +div VResolution 72 div neg scale magscale{DVImag dup scale}if 0 setgray} +N /psfts{S 65781.76 div N}N /startTexFig{/psf$SavedState save N userdict +maxlength dict begin /magscale true def normalscale currentpoint TR +/psf$ury psfts /psf$urx psfts /psf$lly psfts /psf$llx psfts /psf$y psfts +/psf$x psfts currentpoint /psf$cy X /psf$cx X /psf$sx psf$x psf$urx +psf$llx sub div N /psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy +scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR +/showpage{}N /erasepage{}N /copypage{}N /p 3 def @MacSetUp}N /doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N /endTexFig{end psf$SavedState restore}N /@beginspecial{SDict +begin /SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count /ocount X /dcount countdictstack N}N /@setspecial +{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if /showpage{}N /erasepage{}N /copypage{}N newpath +}N /@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{ +end}repeat grestore SpecialSave restore end}N /@defspecial{SDict begin} +N /@fedspecial{end}B /li{lineto}B /rl{rlineto}B /rc{rcurveto}B /np{ +/SaveX currentpoint /SaveY X N 1 setlinecap newpath}N /st{stroke SaveX +SaveY moveto}N /fil{fill SaveX SaveY moveto}N /ellipse{/endangle X +/startangle X /yrad X /xrad X /savematrix matrix currentmatrix N TR xrad +yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (tutwrl1.dvi) +@start /Fa 134[50 50 72 50 55 33 39 44 1[55 50 55 83 +28 55 1[28 55 50 33 44 55 44 55 50 9[100 28[33 3[50 2[50 +50 50 1[28 2[25 2[33 33 40[{ TeXBase1Encoding ReEncodeFont }33 +100.000003 /Times-Bold rf /Fb 134[60 60 86 1[66 40 47 +53 1[66 60 66 100 33 66 1[33 66 60 1[53 66 53 1[60 9[120 +2[80 66 5[113 3[47 2[73 2[86 1[86 6[40 4[60 60 60 60 +60 2[30 43[66 2[{ TeXBase1Encoding ReEncodeFont }36 119.999948 +/Times-Bold rf /Fc 105[50 27[44 50 50 72 50 50 28 39 +33 50 50 50 50 78 28 50 1[28 50 50 33 44 50 44 50 44 +8[72 94 2[61 55 66 1[55 2[89 61 2[33 2[55 61 72 66 1[72 +5[28 28 50 1[50 50 1[50 50 50 50 50 1[25 33 25 2[33 33 +33 3[50 32[55 2[{ TeXBase1Encoding ReEncodeFont }58 100.000003 +/Times-Roman rf /Fd 134[44 1[66 2[28 39 39 1[50 50 50 +72 28 44 28 28 50 50 28 44 50 44 50 50 9[83 2[55 50 4[66 +83 55 7[72 66 61 15[50 50 7[33 33 40[{ TeXBase1Encoding ReEncodeFont } +34 100.000003 /Times-Italic rf /Fe 134[72 72 104 1[80 +48 56 64 2[72 80 1[40 2[40 80 72 1[64 80 64 1[72 9[143 +2[96 1[104 4[135 3[56 2[88 96 104 104 1[104 6[48 5[72 +72 72 72 3[48 9[72 35[{ TeXBase1Encoding ReEncodeFont }34 +143.999997 /Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: Letter + +%%EndSetup +%%Page: 1 1 +1 0 bop 540 101 a Fe(Magic)36 b(T)-13 b(utorial)33 b(#W)-5 +b(-1:)44 b(Design-Rule)33 b(Extensions)1747 521 y Fd(Don)24 +b(Stark)1359 941 y Fc(W)-8 b(estern)25 b(Research)h(Laboratory)1327 +1062 y(Digital)e(Equipment)f(Corporation)1530 1182 y(P)o(alo)i(Alto,)f +(CA)h(94301)1053 1453 y(This)f(tutorial)g(corresponds)g(to)g(Magic)h(v) +o(ersion)e(7.)0 1996 y Fb(T)-11 b(utorials)30 b(to)f(r)n(ead)h +(\002rst:)300 2214 y Fc(Magic)24 b(T)l(utorial)g(#6:)30 +b(Design-Rule)25 b(Checking)300 2334 y(Magic)f(T)l(utorial)g(#9:)30 +b(F)o(ormat)24 b(Con)l(v)o(ersion)g(for)h(CIF)h(and)f(Calma)300 +2454 y(Magic)f(Maintainer')-5 b(s)24 b(Manual)g(#2:)30 +b(The)25 b(T)-7 b(echnology)24 b(File)0 2670 y Fb(Commands)29 +b(intr)n(oduced)j(in)f(this)f(tutorial:)300 2888 y Fd(\(None\))0 +3103 y Fb(Macr)n(os)f(intr)n(oduced)i(in)g(this)f(tutorial:)300 +3351 y Fd(\(None\))0 3979 y Fe(1)143 b(Intr)m(oduction)0 +4207 y Fc(Magic')-5 b(s)33 b(original)g(design)h(rule)g(check)o(er)h +(has)f(pro)o(v)o(ed)e(inadequate)i(to)g(implement)e(all)i(the)g(rules)g +(found)f(in)0 4328 y(adv)n(anced)25 b(technologies.)30 +b(The)25 b(rules)g(described)g(in)f(this)h(section)f(allo)n(w)g(more)h +(complicated)f(con\002gurations)0 4448 y(to)k(be)g(analyzed.)41 +b(T)-8 b(w)o(o)27 b(ne)n(w)h(rules)g(check)g(a)h(re)o(gion')-5 +b(s)26 b(area)j(and)f(its)g(maximum)e(width.)40 b(In)28 +b(addition,)f(width,)0 4569 y(spacing,)d(area,)i(and)f(maxwidth)e +(checks)i(may)f(no)n(w)g(be)h(performed)g(on)g(cif)g(layers.)0 +4924 y Fe(2)143 b(Ar)m(ea)35 b(Rules)0 5152 y Fc(The)25 +b Fa(ar)n(ea)g Fc(rule)g(is)f(used)h(to)f(check)h(the)g(minimum)d(area) +k(of)f(a)g(re)o(gion.)30 b(Its)25 b(syntax)f(is:)900 +5400 y Fa(ar)n(ea)h Fd(types)g(minar)l(ea)f(minedg)o(e)h(why)1875 +5649 y Fc(\2261\226)p eop +%%Page: 2 2 +2 1 bop 0 -180 a Fc(September)25 b(26,)f(2001)1234 b(Magic)25 +b(T)l(utorial)e(#W)-6 b(-1:)30 b(Design-Rule)25 b(Extensions)146 +68 y Fd(T)-7 b(ypes)20 b Fc(is)f(a)g(list)g(of)g(types)g(that)f +(compose)h(the)g(re)o(gion,)h(all)f(of)g(which)g(must)f(be)i(on)f(the)g +(same)g(plane.)29 b Fd(Minar)l(ea)0 188 y Fc(is)24 b(the)h(minimum)d +(area)j(that)f(a)h(re)o(gion)f(must)g(ha)n(v)o(e,)g(while)g +Fd(minedg)o(e)g Fc(is)g(the)h(minimum)d(length)i(of)g(an)h(edge)g(for)0 +309 y(the)d(re)o(gion.)29 b(This)21 b(second)h(dimension)f(is)h +(basically)f(an)h(optimization)f(to)g(mak)o(e)h(the)g(design)g(rule)g +(check)o(er)h(run)0 429 y(f)o(aster;)h(without)d(it,)i(the)g(check)o +(er)h(has)f(to)f(assume)h(that)f(a)i(re)o(gion)e(1)h(lambda)f(wide)h +(and)g Fd(minar)l(ea)g Fc(long)f(is)g(le)o(gal,)0 549 +y(and)29 b(it)f(must)f(e)o(xamine)h(a)h(much)f(lar)n(ger)h(area)g(when) +g(checking)f(the)g(interaction)g(between)h(cells.)41 +b(Specifying)0 670 y Fd(minedg)o(e)24 b Fc(reduces)i(this)d +(interaction)h(distance.)31 b(An)24 b(e)o(xample)g(rule)h(is:)900 +849 y Fa(ar)n(ea)g(\(emitter)-9 b(,em1c\)/npoly)26 b(6)f(2)2164 +849 y +(") show + 2164 849 a 60 w Fa(emitter)h(must)f(be)h(at)f(least)f(2x3)3395 +849 y +(") show + 3395 849 a 683 2415 a @beginspecial 68 @llx 68 +@lly 331 @urx 211 @ury 3042 @rwi @setspecial +%%BeginDocument: ../psfigures/tutw1.2.ps +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/pgsave save def bop +% 576 260 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.439 1.000 0.314 scb +240 1.00 192 196 192 548 704 548 704 196 4 polygon +sce +(minarea) {/Times-Roman 1.000 cf} 2 21 0 448 372 label +0 1.00 192 196 192 548 704 548 704 196 4 polygon +(minedge) {/Times-Roman 1.000 cf} 2 20 0 736 372 label +1 1.00 720 548 800 548 2 polygon +1 1.00 720 196 800 196 2 polygon +1 1.00 768 532 768 404 2 polygon +1 1.00 768 340 768 212 2 polygon +1.00 0 768 548 arrowhead +1.00 -181 768 196 arrowhead +pgsave restore showpage + +XCIRCsave restore +%%EndDocument + @endspecial 1251 2618 a Fc(Figure)h(1:)31 b(Example)24 +b(of)h(the)f(area)i(rule.)0 3136 y Fe(3)143 b(Maxwidth)35 +b(Rules)0 3360 y Fc(Sometimes)28 b(a)h(technology)f(requires)g(that)h +(a)g(re)o(gion)f(not)g(be)h(wider)g(than)g(a)g(certain)g(v)n(alue.)42 +b(The)29 b Fa(maxwidth)0 3480 y Fc(rule)c(can)g(be)g(used)f(to)h(check) +g(this.)900 3660 y Fa(maxwidth)g Fd(layer)o(s)f(mwidth)h(bends)f(why) +146 3839 y(Layer)o(s)p Fc(,)30 b(the)e(types)f(that)h(compose)f(the)h +(re)o(gion,)g(must)g(all)f(be)i(in)f(the)g(same)g(plane.)40 +b(The)29 b(re)o(gion)e(must)g(be)0 3960 y(less)20 b(than)h +Fd(mwidth)f Fc(wide)g(in)h(either)f(the)h(horizontal)f(or)h(v)o +(ertical)f(dimension.)27 b Fd(Bends)21 b Fc(tak)o(es)f(one)h(of)g(tw)o +(o)f(v)n(alues,)0 4080 y Fa(bend)p 215 4080 30 4 v 37 +w(illegal)29 b Fc(and)i Fa(bend)p 921 4080 V 37 w(ok)p +Fc(.)47 b(F)o(or)30 b Fa(bend)p 1511 4080 V 38 w(illegal)f +Fc(rules,)i(the)f(check)o(er)h(forms)f(a)h(bounding)e(box)g(around)h +(all)0 4200 y(contiguous)23 b(tiles)h(of)h(the)g(correct)g(type,)g +(then)f(checks)h(this)f(box')-5 b(s)24 b(width.)29 b(F)o(or)c(e)o +(xample:)900 4380 y Fa(maxwidth)g(\(emitter)-9 b(,em1c\)/npoly)26 +b(2)f(bend)p 2545 4380 V 37 w(illegal)2855 4380 y +/bksp 2 string def bksp 0 92 put bksp show + 2855 +4380 a 1421 4500 a +(") show + 1421 4500 a 60 w Fa(emitter)h(width)f(cannot)h(be)g +(o)o(v)o(er)f(2)2783 4500 y +(") show + 2783 4500 a 146 4680 a Fa(bend)p +361 4680 30 4 v 38 w(ok)19 b Fc(rules)g(are)g(used)g(to)f(check)i +(structures)e(where)i(the)e(re)o(gion)g(must)g(be)h(locally)g(less)f +(than)h(maxwidth,)0 4800 y(b)n(ut)24 b(may)h(contain)f(bends,)g(T')-5 +b(s,)24 b(and)h(X')-5 b(s.)900 4980 y Fa(maxwidth)25 +b(tr)n(ench)i(2)e(bend)p 1941 4980 V 37 w(ok)2102 4980 +y +(") show + 2102 4980 a 60 w Fa(tr)n(ench)i(must)e(be)g(exactly)g(2)g(wide)3419 +4980 y +(") show + 3419 4980 a 146 5159 a Fa(W)-6 b(ar)o(ning:)37 +b Fc(the)28 b(bend)p 941 5159 30 4 v 35 w(ok)g(rule)g(is)g(basically)f +(a)i(kludge,)f(and)g(may)g(f)o(ail)g(for)g(re)o(gions)f(composed)g(of)h +(more)0 5280 y(than)e(one)g(type,)h(or)f(for)h(intersections)e(more)i +(complicated)e(than)h(T')-5 b(s)26 b(or)h(X')-5 b(s.)35 +b(Figure)26 b(3)h(sho)n(ws)e(some)h(e)o(xam-)0 5400 y(ples)e(of)h(both) +f(types)h(of)f(rules.)1875 5649 y(\2262\226)p eop +%%Page: 3 3 +3 2 bop 0 -180 a Fc(Magic)24 b(T)l(utorial)g(#W)-6 b(-1:)30 +b(Design-Rule)24 b(Extensions)1233 b(September)25 b(26,)g(2001)0 +1459 y @beginspecial 68 @llx 68 @lly 862 @urx 365 @ury +4680 @rwi @setspecial +%%BeginDocument: ../psfigures/tutw1.1.ps +% +% PostScript prolog for output from xcircuit +% Version: 2.0 +% +% Electrical circuit (and otherwise general) drawing program +% +% Written by Tim Edwards 8/5/93--2/25/99 (tim@bach.ece.jhu.edu) +% The Johns Hopkins University +% +% supporting definitions --- these are the primary xcircuit types. + +/XCIRCsave save def +/topmat matrix currentmatrix def + +/fontslant { /slant exch def [1 0 slant 1 0 0] + exch findfont exch makefont dup length dict /ndict exch def + { 1 index /FID ne { ndict 3 1 roll put } { pop pop } ifelse } forall + ndict definefont pop} def +/cf { dup type /realtype eq {40 mul /fscale exch def} if dup /xfont exch def + findfont fscale scalefont setfont } def +/Ss { gsave 0.67 dup scale gsave mty neg rmoveto + glevel 1 add /glevel exch def } def +/ss { gsave 0.67 dup scale gsave mty 0.5 mul rmoveto + glevel 1 add /glevel exch def } def +/ns { currentpoint transform % preserve x position! + glevel {grestore} repeat /glevel 0 def + itransform pop currentpoint pop sub 0 rmoveto } def +/ul { showflag 1 eq { gsave + currentpoint topmat setmatrix 0 0 moveto 2 index stringwidth pop (_) + false charpath flattenpath pathbbox grestore exch pop 1 index + sub setlinewidth exch pop currentpoint 3 -1 roll add moveto 0 + rlineto stroke moveto } if } def +/ol { showflag 1 eq { gsave gsave + currentpoint topmat setmatrix 2 index stringwidth pop 3 index + true charpath flattenpath pathbbox grestore exch pop + exch pop topmat setmatrix (_) true charpath pathbbox grestore + exch pop 1 index sub setlinewidth exch pop currentpoint + exch 4 1 roll exch sub add moveto pop 0 rlineto stroke + moveto } if } def +/stW { gsave true charpath flattenpath pathbbox pop exch pop sub + grestore } def +/bs { stW 0 rmoveto } def +/pspc 0 def +/qS { (aa) stW (a a) stW sub 4 div 0 rmoveto } def +/hS { qS qS } def +/textx { dup 1 add copy 0 exch { exch dup type /stringtype eq + {stringwidth pop add}{exec} ifelse } repeat neg ns } def +/mty { 0 topmat setmatrix (A) true charpath flattenpath pathbbox exch + pop exch sub exch pop neg grestore } def +/texty { gsave 2 copy pop exec mty } def +/tcenter { textx grestore 0.5 mul 0 rmoveto } def +/tright { textx grestore fspc sub 0 rmoveto } def +/tmiddle { texty 0.5 mul rmoveto } def +/ttop { texty fspc sub rmoveto } def +/tshow {{ dup type /stringtype eq {show}{exec} ifelse} repeat ns } def + +/label { gsave translate 0 0 moveto rotate /just exch def just 16 and 0 gt + {0 1 dtransform gsave pagemat setmatrix idtransform exch grestore + 1 0 dtransform gsave pagemat setmatrix idtransform exch grestore + dup 0 eq {pop mul 0 gt} {3 1 roll pop pop 0 lt} ifelse + {-1 /just just dup 3 and 1 ne {3 xor} if def} {1} ifelse exch 0 lt + {-1 /just just dup 12 and 4 ne {12 xor} if def} {1} ifelse scale } if + /glevel 0 def /showflag 0 def /fspc pspc def + just 1 and 0 gt {gsave just 2 and 0 gt {tright}{tcenter} ifelse} + {fspc 0 rmoveto} ifelse + just 4 and 0 gt {just 8 and 0 gt {ttop}{tmiddle} ifelse} + {0 fspc rmoveto} ifelse + /showflag 1 def tshow grestore } def +/pinlabel { hlevel 0 eq { /pspc 20 def label /pspc 0 def } + { pop pop pop pop {pop} repeat } ifelse } def +/pinglobal { pinlabel } def +/infolabel { pinlabel } def + +/begingate { /hlevel hlevel 1 add def gsave translate 0 0 moveto dup 0 lt + {neg 1 sub -1 1 scale} if rotate dup scale } bind def +/makeparm {3 string cvs dup length 1 add string /tstr exch def tstr exch + 1 exch putinterval tstr 0 (v) putinterval tstr cvn} bind def +/beginparm { -1 1 {makeparm exch def} for + dup type /arraytype eq { aload length -1 1 {makeparm exch def} + for } if begingate } bind def +/endgate { /hlevel hlevel 1 sub def grestore } bind def + +/hlevel 0 def +/tmpa [1 0 0 1 0 0] def +/gar {8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {<30 70 60 02 03 07 06 20>} imagemask} bind +{8 8 true tmpa {<0c 1e 1e 0c c0 e1 e1 c0>} imagemask} bind +{8 8 true tmpa {<0f 0f 0f 0f f0 f0 f0 f0>} imagemask} bind +{8 8 true tmpa {<3f f3 e1 e1 f3 3f 1e 1e>} imagemask} bind +{8 8 true tmpa {} imagemask} bind +{8 8 true tmpa {} imagemask} bind 7 array astore def +/ppaint { gsave clip tmpa dup setmatrix pathbbox neg exch neg 4 2 roll + neg 4 -1 roll 2 copy gt {exch} if 8 div ceiling 8 mul 4 2 roll neg 2 copy + gt {exch} if 8 div ceiling 8 mul 3 -1 roll -8 5 -1 roll + { 3 index exch 5 exch put dup -8 3 index { 3 index + exch 4 exch put 3 index exec } for } for pop pop pop pop grestore } bind def +/setstyles { + currentlinewidth mul setlinewidth /style exch def + style 1 and 0 gt not {closepath} if + style 2 and 0 gt {currentlinewidth 4 mul dup 2 array astore 0 setdash} if + style 4 and 0 gt {0.5 currentlinewidth 4 mul 2 array astore 0 setdash} if + style dup 256 ge exch 480 lt and { gsave 1 setgray eofill grestore } if + style 16 and 0 gt { gsave style 224 and -5 bitshift dup 7 lt + {gar exch get ppaint} { pop eofill } ifelse grestore } if + style 8 and 0 gt { newpath } { stroke } ifelse grestore } def +/scb { gsave setrgbcolor } bind def /sce { grestore } bind def + +/polygon { gsave /num exch def moveto num 1 sub {lineto} repeat setstyles } def +/xcarc { gsave newpath arc setstyles } def +/elb { matrix currentmatrix 7 -1 roll 7 -1 roll translate 5 1 roll 4 -1 roll + 3 index div 1 scale } def +/ele { 0 4 1 roll 0 4 1 roll } bind def +/ellipse { gsave elb newpath ele arc setmatrix setstyles } def +/pellip { elb ele arc setmatrix } def +/nellip { elb ele arcn setmatrix } def +/spline { gsave moveto curveto setstyles } def +/polyc { {lineto} repeat } bind def +/beginpath { gsave moveto } bind def +/endpath { setstyles } bind def +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/insertion {/PSobj save def /showpage {} def bop translate} def +/end_insert {PSobj restore} def +/setpagemat {/pagemat matrix currentmatrix def} def +/inchscale {setpagemat 0.375 mul dup scale} def +/cmscale {setpagemat 0.35433071 mul dup scale} def + + +% XCircuit output starts here. + +/arrowhead { +% -12 -32 24 36 bbox +begingate +8 -28 beginpath +3 -18 3 -15 0 0 curveto +-3 -15 -3 -18 -8 -28 curveto +-2 -26 2 -26 8 -28 curveto +249 1.00 endpath +endgate +} def + +/pgsave save def bop +% 1200 357 offsets +1.0000 inchscale +2.6000 setlinewidth + +0.800 0.800 0.800 scb +240 1.00 192 261 192 965 1072 965 1072 261 4 polygon +240 1.00 1136 261 1136 965 2288 965 2288 261 4 polygon +sce +0.745 0.600 0.871 scb +240 1.00 720 549 720 645 912 645 912 549 4 polygon +241 1.00 496 581 368 581 368 677 592 677 592 485 496 485 496 581 7 polygon +sce +0 1.00 720 549 720 645 912 645 912 549 4 polygon +0.490 0.651 0.980 scb +241 1.00 1232 389 1616 389 1616 901 1232 901 1232 485 1168 485 1168 421 1232 +421 1232 389 1296 453 1296 805 1552 805 1552 453 1296 453 14 polygon +241 1.00 1840 389 1840 613 1744 613 1744 677 1840 677 1840 901 2192 901 2192 +581 2256 581 2256 517 2192 517 2192 389 1840 389 1904 453 2128 453 2128 517 +2064 517 2064 581 2128 581 2128 837 1904 837 1904 453 22 polygon +sce +0 1.00 1296 453 1296 805 1552 805 1552 453 4 polygon +1 1.00 1904 453 1904 837 2128 837 2128 581 2064 581 2064 517 2128 517 2128 453 +1904 453 9 polygon +1 1.00 2192 389 1840 389 1840 613 1744 613 1744 677 1840 677 1840 901 2192 901 +2192 581 2256 581 2256 517 2192 517 2192 389 13 polygon +1 1.00 1232 485 1232 901 1616 901 1616 389 1232 389 1232 421 1168 421 1168 485 +1232 485 9 polygon +1 1.00 496 581 368 581 368 677 592 677 592 485 496 485 496 581 7 polygon +(mwidth) {/Times-Roman 1.000 cf} 2 23 0 336 629 label +(mwidth) {/Times-Roman 1.000 cf} 2 23 0 416 437 label +(mwidth) {/Times-Roman 1.000 cf} 2 20 0 928 597 label +1 1.00 928 645 1008 645 2 polygon +1 1.00 928 549 1008 549 2 polygon +1 1.00 960 661 960 709 2 polygon +1 1.00 960 533 960 485 2 polygon +1 1.00 352 581 272 581 2 polygon +1 1.00 320 565 320 517 2 polygon +1 1.00 352 677 272 677 2 polygon +1 1.00 320 693 320 741 2 polygon +1 1.00 496 469 496 405 2 polygon +1 1.00 592 469 592 405 2 polygon +1 1.00 576 437 432 437 2 polygon +1.00 0 960 549 arrowhead +1.00 0 320 581 arrowhead +1.00 -181 320 677 arrowhead +1.00 -181 960 645 arrowhead +1.00 -91 592 437 arrowhead +1.00 -91 496 437 arrowhead +(invalid) {/Times-Roman 1.250 cf} 2 21 0 464 325 label +(valid) {/Times-Roman 1.250 cf} 2 21 0 816 325 label +(invalid) {/Times-Roman 1.250 cf} 2 21 0 1424 325 label +(valid) {/Times-Roman 1.250 cf} 2 21 0 2016 325 label +(bend_ok) {/Times-Roman 1.500 cf} 2 21 0 1728 213 label +(bend_illegal) {/Times-Roman 1.500 cf} 2 21 0 608 213 label +pgsave restore showpage + +XCIRCsave restore +%%EndDocument + @endspecial 324 x(Figure)k(2:)38 b(Examples)28 b(of)g(the)h(maxwidth)e +(rule.)42 b(The)29 b(dogle)o(g)e(at)i(the)f(left)h(w)o(ould)f(be)g(ok)h +(in)f(a)h Fa(bend)p 3555 1783 30 4 v 37 w(ok)g Fc(rule,)0 +1903 y(b)n(ut)h(f)o(ails)g(in)g(a)h Fa(bend)p 755 1903 +V 37 w(illegal)f Fc(one,)i(where)f(the)f(re)o(gion')-5 +b(s)29 b(bounding)g(box)h(is)g(check)o(ed.)49 b(F)o(or)30 +b Fa(bend)p 3514 1903 V 38 w(ok)g Fc(rules,)0 2023 y(each)e(tile)e(in)g +(the)h(re)o(gion)f(is)h(check)o(ed.)37 b(The)27 b(left)g(shape)g(f)o +(ails)f(in)h(tw)o(o)f(places:)35 b(the)27 b(top)f(horizontal)g(part)h +(is)g(too)0 2144 y(thick)d(and)h(the)g(stub)f(at)g(the)h(bottom)e +(intersects)h(the)h(re)o(gion)f(in)g(a)i(shape)e(other)h(than)f(a)i(T)e +(or)h(X.)0 2525 y Fe(4)143 b(Rules)35 b(on)g(CIF)g(lay)o(ers)0 +2749 y Fc(F)o(or)21 b(technologies)f(with)h(complicated)f(generated)i +(layers,)f(it)g(is)g(often)g(dif)n(\002cult)f(to)h(check)h(design)e +(rules)h(on)g(the)0 2869 y(abstract)30 b(types)f(that)g(are)h(dra)o(wn) +g(in)f(Magic.)45 b(T)-8 b(o)29 b(ameliorate)h(this)e(problem,)i(the)g +(e)o(xtended)f(check)o(er)h(allo)n(ws)0 2990 y(simple)19 +b(checks)i(to)f(be)h(performed)f(on)g(cif)h(layers.)29 +b(The)21 b(rules)f(that)g(can)h(be)f(check)o(ed)h(are)g(width,)g +(spacing,)f(area,)0 3110 y(and)28 b(maxarea.)40 b(Since)28 +b(checking)g(rules)f(on)h(the)f(cif)h(layers)g(requires)g(that)f(these) +h(layers)g(be)f(generated,)i(these)0 3230 y(checks)k(are)h +(considerably)e(slo)n(wer)g(than)g(the)h(normal)f(ones,)j(and)d(should) +g(only)g(be)h(used)g(when)f(absolutely)0 3351 y(necessary)-6 +b(.)0 3643 y Fb(4.1)119 b(Setting)31 b(the)f(CIF)g(style)0 +3830 y Fc(The)25 b Fa(cifstyle)g Fc(rule)f(is)h(used)f(to)h(select)f +(which)h Fa(cif)n(output)h Fc(style)e(is)g(used.)900 +4033 y Fa(cifstyle)h Fd(cif)p 1330 4033 V 35 w(style)146 +4236 y(Cif)p 274 4236 V 36 w(style)36 b Fc(must)f(be)h(one)h(of)f(the)g +(cif)h(styles)e(included)g(in)h(the)g(cifoutput)f(section.)65 +b(In)36 b(the)g(current)h(im-)0 4357 y(plementation,)c(the)g(cif)g +(check)o(er)h(generates)g(all)e(the)h(layers)g(in)g(the)g(style)f(re)o +(gardless)g(of)h(whether)g(the)o(y)f(are)0 4477 y(actually)27 +b(used)h(in)g(design-rule)f(checks;)i(for)f(speed,)h(de\002ning)e(a)i +(separate)f(cif)g(style)f(for)h(design)g(rule)f(check-)0 +4597 y(ing)h(it)g(may)f(be)i(w)o(orthwhile)e(when)h(only)g(a)g(fe)n(w)h +(layers)f(are)h(check)o(ed.)42 b(An)o(y)27 b(layer)i(in)f(the)g(cif)g +(style,)h(de\002ned)0 4718 y(by)c(either)f(a)h Fd(layer)g +Fc(or)g(a)g Fd(templayer)f Fc(rule,)h(may)g(be)g(check)o(ed.)0 +5009 y Fb(4.2)119 b(W)n(idth)30 b(Checks)0 5197 y Fc(The)25 +b(syntax)f(for)h Fa(cifwidth)h Fc(is)e(analogous)g(to)g(that)h(of)f +(the)h(re)o(gular)g(width)e(rule:)900 5400 y Fa(cifwidth)j +Fd(layer)e(width)h(why)1875 5649 y Fc(\2263\226)p eop +%%Page: 4 4 +4 3 bop 0 -180 a Fc(September)25 b(26,)f(2001)1234 b(Magic)25 +b(T)l(utorial)e(#W)-6 b(-1:)30 b(Design-Rule)25 b(Extensions)146 +68 y Fd(Layer)j Fc(is)g(a)g(single)e(cif)i(layer)-5 b(.)39 +b(\(T)-8 b(o)28 b(do)f(width)g(checks)h(with)f(more)g(than)g(one)h(cif) +g(layer)l(,)g Fa(or)g Fc(all)g(the)f(layers)0 188 y(into)d(a)h(ne)n(w)f +Fd(templayer)p Fc(\).)31 b Fd(W)-5 b(idth)23 b Fc(is)i(the)f(minimum)f +(width)h(of)g(the)h(re)o(gion)f(in)g(centimicrons.)0 +483 y Fb(4.3)119 b(Spacing)31 b(Checks)0 671 y Fc(The)25 +b Fa(cifspacing)g Fc(rule)g(is)f(also)h(v)o(ery)f(similar)g(to)g(the)h +(re)o(gular)f(rule:)900 899 y Fa(cifspacing)h Fd(layer1)g(layer2)f +(separ)o(ation)f(adjacency)h(why)146 1128 y(Layer1)35 +b Fc(and)e Fd(layer2)h Fc(are)h(both)e(cif)h(layers.)58 +b(If)34 b Fd(adjacency)g Fc(is)g Fa(touching)p 2771 1128 +30 4 v 36 w(ok)p Fc(,)j(then)c(layer1)h(must)f(equal)0 +1248 y(layer2.)59 b(F)o(or)34 b Fa(touching)p 880 1248 +V 36 w(illegal)f Fc(rules,)j Fd(layer1)e Fc(and)g Fd(layer2)g +Fc(may)f(be)i(an)o(y)e(tw)o(o)h(cif)g(layers.)59 b Fd(Separ)o(ation)32 +b Fc(is)0 1368 y(gi)n(v)o(en)23 b(in)i(centimicrons.)0 +1664 y Fb(4.4)119 b(Ar)n(ea)30 b(Checks)0 1851 y Fc(The)25 +b(area)h(rule)e(is:)900 2080 y Fa(cifar)n(ea)h Fd(layer)g(minar)l(ea)f +(minedg)o(e)h(why)146 2308 y(Layer)g Fc(is)e(again)g(a)h(single)f(cif)h +(layer)-5 b(.)30 b Fd(minedg)o(e)23 b Fc(is)h(e)o(xpressed)f(in)g +(centimicrons,)g(and)h Fd(minar)l(ea)f Fc(is)g(gi)n(v)o(en)f(in)0 +2428 y(square)j(centimicrons.)0 2723 y Fb(4.5)119 b(Maxwidth)31 +b(Checks)0 2911 y Fc(The)25 b(maxwidth)e(rule)i(is:)900 +3139 y Fa(cifmaxwidth)g Fd(layer)g(mwidth)f(bends)g(why)146 +3368 y Fc(Again,)g Fd(layer)h Fc(is)f(a)h(single)f(cif)h(layer)l(,)g +(and)g Fd(mwidth)f Fc(is)h(gi)n(v)o(en)e(in)h(centimicrons.)1875 +5649 y(\2264\226)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/textfiles/LEF.txt b/doc/textfiles/LEF.txt new file mode 100644 index 00000000..edd99cb5 --- /dev/null +++ b/doc/textfiles/LEF.txt @@ -0,0 +1,123 @@ +LEF extensions to Magic-7.2 +------------------------------------- +1) Ports + + A new method exists for declaring a cell to be a subcircuit. + This involves the creation of ports, which are a special kind + of label. The existence of any port in a cell marks that cell + as a subcircuit, which causes it to be treated differently + during the process of extraction and netlist generation: + + a) Subcircuits are extracted as usual, except for the presence + of the "port" keyword for each port in the .ext file. + + b) Exttosim (ext2sim) operates as usual, because the netlist is + not hierarchical. + + c) Exttospice (ext2spice) will generate an "X" record for each + instance of the subcircuit cell, rather than flattening the + cell. To simulate in SPICE, a ".subckt" record for the cell + must be added to the SPICE deck. This behavior can be + subverted in the Tcl-based magic by using "exttospice subcircuits + off", in which case all subcircuits will be flattened. + + d) The "extresis" command will ignore the contents of subcircuits. + On the other hand, after doing "extresis geometry", subsequent + use of "extresis" will generate a ".fh" file containing the + detailed three-dimensional geometry of the cell in the format + of nodes and segments used by the FastHenry field equation + solver. This is unrelated to the LEF module. + + A new command "port" turns labels into ports. The syntax of + the command is: + + port [option], where [option] is one of: + + class [type] get [set] port class type + use [type] get [set] port use type + index [number] get [set] port number + connections [dir...] get [set] port connection directions + make [index] [dir...] turn a label into a port + remove turn a port back into a label + help print this help information + [] + + To use the port command, a label must first exist, and the cursor box + must overlap the label, and only that label. + + The index indicates the order of the port in the argument list of the + subcircuit definition and calls. The ordering of ports must match + the order of arguments to any .subckt record used in a SPICE simulation + of the cell. + + The directions given to "connections" must be one or more of "n", "s", + "e", and "w" (with no spaces in between; e.g., "port connections nsew"). + They indicate the edge of the port to which connections may be made to + the cell. This is unused by LEF, which uses more detailed information + about metal routing and obstructions inside the cell to determine how + to attach to a pin. In the abbreviated command usage "port ", + a default direction will be determined by the position of the text on + the label. + + Class and use types correspond to LEF classes and uses for pins. + + Valid class types are: + default + input + output + tristate + bidirectional, inout + feedthrough, feedthru + + Valid use types are: + default + analog + signal, digital + power + ground + clock + +2) Properties + + While the "port" command and method specifies information about pins, + LEF also supports information about the cell itself. The "property" + command is a general-purpose interface for attaching key-value pairs + to a cell, which are saved in the output and may be parsed by any + function. Keys relevant to the LEF module begin with the text "LEF". + LEF-related keys are: + + LEFclass corresponding to LEF "CLASS" + LEFsource corresponding to LEF "SOURCE" + LEFsymmetry corresponding to LEF "SYMMETRY" + + The string value attached to each key is written to the LEF output + verbatim, thus any value may be used that is acceptable LEF syntax. + + The property command has the following syntax: + + property [ []] + + With no arguments, "property" returns all the key-value pairs defined + for the current edit cell. Given the key argument only, it returns + the value attached to the indicated key. Given both arguments, it + assigns the string value to the indicated key. A value which is an + empty string ("") will cause the key to become undefined. Values + which consist of more than one word must be enclosed in quotes. + + Example: property LEFsymmetry "X Y" + +3) LEF file generation + + A LEF-definition file with extension ".lef" may be written for each + cell. This file contains detailed information required for placing + and routing the cell, including all information regarding pins, + ports, and obstructions on the metallization layers. The syntax of + the LEF command is: + + lef write [] + + to write a .lef file for a single cell. If is not specified, + then the output will be for the current edit cell. All cells in a + design my be written using the syntax: + + lef writeall diff --git a/doc/textfiles/default_macros.txt b/doc/textfiles/default_macros.txt new file mode 100644 index 00000000..f126121c --- /dev/null +++ b/doc/textfiles/default_macros.txt @@ -0,0 +1,112 @@ +---------------------------------------------------------------- +Explanation of the default keyboard macros +(installed in ${CAD_ROOT}/magic/sys/.magic) +---------------------------------------------------------------- +Note: ellipses (...) indicate an interactive macro + asterisk (*) indicates a macro available only under X11 + +---------------------------------------------------------------- +macro key command +---------------------------------------------------------------- +a select visible +A select more visible +ctrl-A select less visible + +b box + +c copy + +d delete +ctrl-D erase $ + +e edit + +f sideways (flip horizontal) +F upside (flip vertical) + +g grid (toggle) + +i select cell +I select more cell +ctrl-I select less cell * + +l label... +L shell ls +ctrl-L redraw + +m move +M stretch + +o openwindow +O closewindow + +p paint... + +ctrl-shift-Q quit * + +r clockwise [90] +R clockwise 270 +ctrl-R clockwise 180 + +s select +S select more +ctrl-S select less +ctrl-shift-S undo; select * + +u undo +U redo + +v view +V xview + +w writeall +W writeall force + +x expand +X unexpand +ctrl-X expand toggle + +z zoom 0.5 +Z zoom 2 +ctrl-Z findbox zoom +ctrl-shift-Z center * + +? drc why +/ select area; what; select clear +, select clear +! shell... +space tool +shift-space tool box * +ctrl-shft-space tool wiring * + + (below: [dir] may be one of right, left, up, or down) + +[dir]_arrow scroll [dir] .1 * +shift-[dir]_arrow scroll [dir] 1 * +ctrl-[dir]_arrow box +[dir] 1 * +ctrl-shift-[dir]_arrow box -[~dir] 1 * + +keypad_period box w 0; box h 0 * +keypad_0 box w 4; box h 4 * +shift-keypad_0 box w 7; box h 2 * +ctrl-keypad_0 box w 2; box h 7 * + + (below: [num] may be 1 through 9; the resulting direction [dir] + corresponds to the position of the number on the keypad. + Diagonal directions are implemented as two commands) + +keypad_[num] move [dir] 1 * +shift-keypad_[num] stretch [dir] 1 * + +F1 paint ndiff * +F2 paint pdiff * +F3 paint poly * +F4 paint poly2 * +F5 paint m1 * +F6 paint m2 * +F7 paint m3 * +F8 paint m4 * +F9 paint ndc * +F10 paint pdc * +F11 paint pc * +F12 paint via * diff --git a/doc/textfiles/hires-color.txt b/doc/textfiles/hires-color.txt new file mode 100644 index 00000000..92d3f3e8 --- /dev/null +++ b/doc/textfiles/hires-color.txt @@ -0,0 +1,52 @@ + + 3 February 1997 + + A More Colorful Magic + + Michael D. Godfrey + + +This file describes the implementation of color visuals > 8bits. + +The purposes of these changes are: + +1. Try to select the "best" visual on systems which offer choices. + The current Magic just takes the default, and crashes if the + color depth is greater than 8. + +2. Support operation using TrueColor at 16 or 24 bits (and maybe 15 + bits, thanks to Linux over-zealous implementation). + +The changes require X11R5 or above. I do not know what will happen +if older X11's are used, but it is not likely to be useful. All +changes are in the files graphics/grX11su1.c, grX11su2.c, and +grX11su5.c. Most of the changes are in grX11su2.c. + +The changes are: + +1. Call XGetVisualInfo() to find out what visuals the X-server has + to offer. + +2. Look at the optional environment variable MAGIC_COLOR. If it is + present try to use the requested visual. Valid requests are: + setenv MAGIC_COLOR <8bit | 16bit | 24bit>. If the requested + visual is not offered Magic terminates. If there was no + MAGIC_COLOR variable try: 8bit PseudoColor, 24bit TrueColor, 16bit + TrueColor in that order. + +3. If 8bit PseudoColor was selected, the code is unchanged and the + file mos.7bit.dstyle5 is read from CAD_ROOT. If TrueColor is + selected, the generation of pixel values and masks is fundamentally + changed since TrueColor does not allow writable colormaps. The + intent is to produce the same RGB color values, but no "transparent" + colors are possible. Therefore, a new file: mos.24bit.dstlye5 is + read. This file has M1 and M2 stippled, and the selection box made + non-transparent. + +Further change in version 7.1: + +4. Because some X servers, like PC-XWare for Windows, reserve spots + at the bottom of the colormap rather than the top, it is necessary + to let these values be set at runtime. We allow two environment + variables, X_COLORMAP_RESERVED and X_COLORMAP_BASE, for the + purpose of overriding the default values set in graphics/grX11su2.c. diff --git a/doc/textfiles/locking.txt b/doc/textfiles/locking.txt new file mode 100644 index 00000000..3579387e --- /dev/null +++ b/doc/textfiles/locking.txt @@ -0,0 +1,74 @@ + August 1999 +Files modified to implement file locking. + +file comment +------------------------------------------------------------------ + +flock/locking documentation +misc/magic.h added #define FILE_LOCKS +database/database.h define CDNOEDIT cd_flag and flock_list +database/DBio.c definition of locking functions, and I/O calls. + fixed :save command error +database/DBcellname.c diagnostics +dbwind/DBWprocs.c apply CDNOEDIT tests +commands/cmde.c checks on :edit command +commands/cmdlq.c lock on :open command +windows/windclient.c defn: flock_close_wlist() +windows/windcmdam.c call to flock_close_wlist on window close +windows/windcmdnr.c Diagnostic code in windOpenCmd +main/main.c call to flock_close_wlist on Magic exit. +utils/path.c control of fopens + +The logic of the file locking implementation is as follows: + +First, Magic checks if there is a directory named flock in the directory +given by CAD_ROOT. If directory flock is not present Magic turns off +flie locking. If file locking is on: + +1. When a file is opened due to being named on the call line, or used in + a :load or :open command its status is checked. + + If it is not locked, lock is set and file is opened r/w (if permissions + allow). + + If it is locked, the file is opened read-only and NOT editing cell. An + attempt to use :edit to make it the editing cell will be rejected. + +2. A list of locked files is maintained in each magic execution. + Magic does (more or less) + open/close sequences when reading/writing files. In addition, Magic + just exits when it is :quit. The conditions that can cause the locking to + release a lock are :close and :quit. In principle some cell's locks + could be released on :close. However, if a window contains a root + cell which contains references to other cells down the hierarchy, only + the cells which are the root or have been expanded will have been + read from the filesystem and locked. Cells that are unexpanded are + not written back nor unlocked. The same cell may appear in multiple + windows in a locked or unlocked state. This all leads to the choice + that :close does not unlock any files. On :quit all locks are released. + +3. When Magic starts, a lock directory (flock_list) is created in the current + directory. A file is written in this directory for each local *.mag file + read by Magic. The file name is the lock record. This record is removed + on normal (:quit) termination. When Magic starts it checks for any + "leftover" locks and tries to clear any "stale" ones. Files that are read + from other directories (by being found through library paths or directly) + are unconditionally marked as read-only. Normally such files should not + be updated. If they are to be updated Magic must be executed from the + directory containing the file. + + The following may be implemented to reduce problems due to "stale locks" + leftover from cases such as magic crashes: During execution Magic + updates the timestamp of its lock once every 10s. locks older + than 10s are stale. Ideally, a simple thread would do this, but... + + UPDATE HISTORY + ------------------------------------------------------------------- + + 5 January 2000: It was discovered that the use of :addpath and, + generally, reading files from other directories had not been considered + properly. In fact, use of :addpath led to a magic crash since it tried + to create an invalid filename. This has now been corrected as + described above. All non-local files are are marked read-only. + + diff --git a/doc/textfiles/macro_extension.txt b/doc/textfiles/macro_extension.txt new file mode 100644 index 00000000..8312e23d --- /dev/null +++ b/doc/textfiles/macro_extension.txt @@ -0,0 +1,270 @@ +Extend keyboard macros for magic +Provided by Philippe Pouliquen +Johns Hopkins University department of Electrical and Computer Engineering +Added to magic-6.5.2 distribution 3/28/00 + +-------------------------------------------------------------------------- +Use of extended keyboard macros: + +To distinguish between normal key macros and extended keyboard macros, +the extended keyboard macros key names all start with 'XK_'. For instance, +the 'i' key has: + + macro i "select cell" + macro XK_i "select cell" + +Although these two macros are the same, the extended keyboard macros +are only available when the mouse cursor is in the drawing window, and +X11 graphics is being used. If the mouse cursor is in the terminal window, +or if magic is started with "-d NULL" then only the normal macros are +available. Note that with the "-d NULL" option, magic will warn about +'Unrecognized macro name XK_xxx' on startup. + +For the uppercase version of the 'i' key, which you get when the 'shift' +key and the 'i' key are depressed simultaneously, you would use: + + macro I "select more cell" + macro Shift_XK_i "select more cell" + +Note that for some keys, such as the numbers, the shifted version is a +symbol rather than a number. So the the number '3' and american keyboards, +you would see: + + macro 3 "see allSame" + macro XK_3 "see allSame" + macro # "see no allSame" + macro XK_3 "see no allSame" + +Finally, extended macros allow you to use any keyboard key as a distinct +macro, along with its 'Meta', 'Control', 'Capslock', and 'Shift' variants. +For instance, the up-arrow key is heavily loaded: + + macro XK_Up "scroll u .1" + macro Shift_XK_Up "scroll u 1" + macro Control_XK_Up "box +u 1" + macro Control_Shift_XK_Up "box -d 1" + +There is one exception to the usual rule, involving the keypad. Keypads +are usually set up such that Shift + a keypad number produces the ASCII +number. To make it possible to distinguish between the number key and +the keypad equivalent, magic parses the number key as ASCII and the +keypad key as XK_KP_(number). For example: + + "XK_8" and "8" both refer to the "8" key. + "XK_KP_Up" refers to the unshifted keypad "8" key. + "XK_KP_8" refers to the shifted keypad "8" key, or the keypad "8" key + by itself with "Num Lock" ON. + +This exception was introduced in revision 42 of magic 7.2; prior revisions +did not distinguish the keypad from the number. + +Note that control characters should be specified with the carat ("^") +notation. Embedding actual control characters in the macro definition +is not compatible with the Tcl-interpreter-based version of magic, for +which it is a syntax error. However, the printable carat notation is +not backwardly-compatible to magic 6.X. + +-------------------------------------------------------------------------- + +The easiest way to add a macro is to type the key combination you want to +use and see what magic reports (if the key combination is not already in +use). For instance, typing 'a' with all the modifiers results in the +message: + + Unknown macro or short command: 'Meta_Control_Capslock_Shift_XK_a' + +Finally, along with the 'macro' command, there is also an 'imacro' +command. This version is an 'interactive' version of the normal macro. +The assigned string is printed as if you had typed it in, allowing you +to add more to the end of the command. For instance: + + imacro l "label " + imacro XK_l "label " + +Now typing the 'l' key is equivalent to typing ":label ". Another example +is the '!' to enter shell commands: + + imacro ! "shell " + imacor XK_Shift_1 "shell " + +Now typing "!ls" followed by the return key is equivalent to typing +":shell ls" to get a directory listing. + +############################################################################## +# Example .magic macro file +############################################################################## +macro '^L' "redraw" +# A key +macro a "" +macro XK_a "select visible" +macro A "" +macro Shift_XK_a "select more visible" +macro Control_XK_a "select less visible" +# B key +macro b "box" +macro XK_b "box" +macro B "" +# C key +macro c "" +macro XK_c "copy" +macro C "" +# D key +macro d "delete" +macro XK_d "delete" +macro '^D' "erase $" +macro Control_XK_d "erase $" +# E key +macro e "edit" +macro XK_e "edit" +macro E "" +# F key +macro f "sideways" +macro XK_f "sideways" +macro F "upsidedown" +macro Shift_XK_f "upsidedown" +# G key +macro g "grid" +macro XK_g "grid" +macro G "" +# H key +macro h "" +macro H "" +# I key +macro i "select cell" +macro XK_i "select cell" +macro I "select more cell" +macro Shift_XK_i "select more cell" +macro Control_XK_i "select less cell" +# J key +macro j "" +macro J "" +# K key +macro k "" +macro K "" +# L key +imacro l "label " +macro L "shell ls" +# M key +macro XK_m "move" +macro Shift_XK_m "stretch" +# N key +macro n "" +macro N "" +# O key +macro o "openwindow" +macro XK_o "openwindow" +macro O "closewindow" +macro Shift_XK_o "closewindow" +# P key +imacro p "paint " +imacro XK_p "paint " +# Q key +macro q "" +macro Q "" +# R key +macro r "clockwise" +macro XK_r "clockwise" +macro R "clockwise 270" +macro Shift_XK_r "clockwise 270" +macro '^R' "clockwise 180" +macro Control_XK_r "clockwise 180" +# S key +macro s "" +macro XK_s "select" +macro S "" +macro Shift_XK_s "select more" +macro Control_XK_s "select less" +macro Control_Shift_XK_s "undo ; select" +# T key +macro t "" +macro T "" +# U key +macro u "undo" +macro XK_u "undo" +macro U "redo" +macro Shift_XK_u "redo" +# V key +macro v "" +macro XK_v "xview" +macro V "" +macro Shift_XK_v "view" +# W key +macro w "writeall" +macro XK_w "writeall" +macro W "writeall force" +macro Shift_XK_w "writeall force" +# X key +macro x "expand" +macro XK_x "expand" +macro X "unexpand" +macro Shift_XK_x "unexpand" +macro '^X' "expand toggle" +macro Control_XK_x "expand toggle" +# Y key +macro y "" +macro Y "" +# Z key +macro z "" +macro XK_z "zoom .5" +macro Z "" +macro Shift_XK_z "zoom 2" +macro Control_XK_z "center" +# ? key +macro ? "drc why" +macro Shift_XK_question "drc why" +macro / "select area; what ; select clear" +macro XK_slash "select area; what ; select clear" +# , key +macro , "" +macro XK_comma "select clear" +# Quote key +imacro '"' "shell " +imacro XK_quotedbl "shell " +imacro Shift_XK_quotedbl "shell " +imacro "'" "shell " +imacro XK_apostrophe "shell " +imacro Shift_XK_apostrophe "shell " +# Space key +macro ' ' "tool" +macro XK_space "tool" +macro Shift_XK_space "tool box" +macro Control_XK_space "tool wiring" +# Arrow keys +macro XK_Left "scroll l .1" +macro Shift_XK_Left "scroll l 1" +macro Control_XK_Left "box +l 1" +macro Control_Shift_XK_Left "box -r 1" +macro XK_Right "scroll r .1" +macro Shift_XK_Right "scroll r 1" +macro Control_XK_Right "box +r 1" +macro Control_Shift_XK_Right "box -l 1" +macro XK_Up "scroll u .1" +macro Shift_XK_Up "scroll u 1" +macro Control_XK_Up "box +u 1" +macro Control_Shift_XK_Up "box -d 1" +macro XK_Down "scroll d .1" +macro Shift_XK_Down "scroll d 1" +macro Control_XK_Down "box +d 1" +macro Control_Shift_XK_Down "box -u 1" +# Keypad keys +macro XK_KP_0 "box w 4; box h 4" +macro Shift_XK_KP_0 "box w 7; box h 2" +macro Control_XK_KP_0 "box w 2; box h 7" +macro XK_KP_1 "move l 1; move d 1" +macro Shift_XK_KP_1 "stretch l 1; stretch d 1" +macro XK_KP_2 "move d 1" +macro Shift_XK_KP_2 "stretch d 1" +macro XK_KP_3 "move r 1; move d 1" +macro Shift_XK_KP_3 "stretch r 1; stretch d 1" +macro XK_KP_4 "move l 1" +macro Shift_XK_KP_4 "stretch l 1" +macro XK_KP_5 "findbox zoom" +macro Shift_XK_KP_5 "findbox" +macro XK_KP_6 "move r 1" +macro Shift_XK_KP_6 "stretch r 1" +macro XK_KP_7 "move l 1; move u 1" +macro Shift_XK_KP_7 "stretch l 1; stretch u 1" +macro XK_KP_8 "move u 1" +macro Shift_XK_KP_8 "stretch u 1" +macro XK_KP_9 "move r 1; move u 1" +macro Shift_XK_KP_9 "stretch r 1; stretch u 1" diff --git a/doc/textfiles/non-manhattan.txt b/doc/textfiles/non-manhattan.txt new file mode 100644 index 00000000..54dbefb4 --- /dev/null +++ b/doc/textfiles/non-manhattan.txt @@ -0,0 +1,108 @@ +---------------------------------------------- +non-Manhattan extensions in Magic +---------------------------------------------- +written by R. Timothy Edwards +version dated 12/10/01 +updated 2/21/06 +---------------------------------------------- + +1. INTRODUCTION + +With the non-Manhattan extensions compiled in (this is the default +configuration), Magic includes the ability to handle a large subset +of non-Manhattan geometry. The implementation was chosen to fit into +the "corner-stitched" data structures which form the basis of all +operations in Magic, so as to require as little possible overhead. +In fact, when non-Manhattan extensions are compiled in, Magic will not +be measurably slower when acting on standard Manhattan geometry than +it is without the extensions compiled in. + +2. IMPLEMENTATION + +The chosen implementation does not include every possible type of +non-Manhattan geometry (for instance, it does not include any kind of +circular geometry). It implements what I would call "corner-split +geometry". Every rectangular tile in Magic may be split across the +diagonal, with one layer type on one side and another layer type on +the other side, thus: + + +-----+ + |XXXX/| + |XXX/ | + |XX/ | + |X/ | + |/ | + +-----+ + +The corner-split geometry allows angles of any value, as long as the +endpoints of each tile lie on the integer layout grid. + +[For those interested in implementation issues: There are only a +maximum of 256 or so "types", which means TileType could easily be +type short int, or 2 bytes long, with plenty room to spare. Instead, +the TileType is defined as int, 4 bytes long, partly to let the +data structure share the space as a pointer for subcell definitions. +This allows the 32 bits to be sliced up into bit fields. I define +14 bits for the left-side type, 14 bits for the right-side type, one +bit to define the direction ("/" or "\") of the split, and one bit +to declare the tile as being split. Each Magic function requiring +a check for non-Manhattan geometry makes a single test for the +non-Manhattan declaration bit and branches to the non-Manhattan +handling code, thus limiting the overhead on Manhattan geometry to +two machine instructions (AND + BZ).] + +3. COMMANDS + +Two simple commands allow basic generation and manipulation of +non-Manhattan geometry: + + splitpaint [] + + spliterase + +These commands are analogous to the "paint" and "erase" commands. +Instead of filling (or erasing the contents of) the box cursor, the +non-Manhattan command paints (or erases) a triangle inside the cursor +select box, with the corner of the triangle facing the direction +indicated by , which can be one of the list: (nw, sw, ne, se). + names the layer type to paint, and the optional +names a layer to fill the rest of the box not covered by . + +For instance, in the example tile shown above, if the X's represent metal1, +the tile would be generated by the command "split nw m1". + +4. SUPPORTED FEATURES + +Non-Manhattan geometry extensions are complete in magic versio 7.4, apart +from possible minor bug fixes. Supported features are listed below. + +Full support for: + X11 and OpenGL rendering + Painting/erasing (including move, copy, flip, rotate, and subcell geometry) + Loading/saving + Selection + Connectivity searches + CIF read/write (see below)* + GDS read/write + Plotting + Extraction/Extresis (unlikely to extract non-Manhattan transistors) + DRC (see below)** + +---------------------------------------------- +* Non-Manhattan CIF and GDS writes: The "bloat-max" and "bloat-min" + functions are not defined for non-Manhattan geometry. However, I + am not aware of any technology file which uses either function. + "bloat-or" may produce incorrect output in pathological situations, + but is expected to work properly for the usual uses of bloat-or + such as auto-generated wells and selects. The CIF/GDS output "squares" + function will not produce contact cuts inside nonmanhattan tiles. + Technologies allowing/requiring nonmanhattan contact cuts should + define the Magic layer to exactly correspond to the cut, instead of + using the "squares" command. Otherwise, nonmanhattan regions should + not be created from Magic contact layers. + +** Non-Manhattan DRC: Currently, non-Manhattan DRC operates in the following + manner: DRC checks occur for each orthogonal edge of a split tile. So + the tile must obey DRC rules separately for each of the two types which + make up the tile. This covers about 90% of the required DRC rules. + Additional rules are required but have not yet been implemented. diff --git a/doc/textfiles/open_gl.txt b/doc/textfiles/open_gl.txt new file mode 100644 index 00000000..10336033 --- /dev/null +++ b/doc/textfiles/open_gl.txt @@ -0,0 +1,184 @@ + + 16 March 2000 + + Magic Freed From 8 Bit Planes! + + R. Timothy Edwards + + +This file describes the implementation of an OpenGL interface for +magic. + +The purpose of these changes is: + + Avoid the limit of 8 bit planes imposed by the pseudocolor colormap + without compromising the quality of the display by using stipples + in place of solid color fills. + +Details: + + Magic is losing ground to 1) new VLSI fabrication + processes, and 2) new video cards. The first is not + necessarily a problem: magic is well thought out and + surprisingly versatile. However, the second was giving + me fits a while back when I found that magic only runs + in 8-bit colormap (pseudocolor) mode, while many of my + other X11 applications wouldn't run at all and were only + happy in 24-bit (TrueColor) mode. This is particularly + true of Linux and the new breed of window managers and + GUIs such as KDE which normally expect the desktop + visual to be 24-bit TrueColor. I was forced to + close my X session and restart in 8-bit mode to get + magic to work. Then, I would often get the problem + that by installing its own 8-bit colormap, magic would + cause the colors of the xterm which it uses for text + I/O to become unreadable. Later, I bought the Xi + Graphics X11 server which supports 8-bit overlays on + top of a 24-bit color, and that works well, but I + regard it as a temporary solution. + + Magic makes good use of its color bit planes to represent + layers in the VLSI layout. The result is a display that + looks better than any of the multi-thousand-dollar + professional layout tools (Cadence or Mentor Graphics, + which use stipple patterns on a harsh black background, + or Tanner's L-Edit, which is still backwardly-compatible + to the original 4-plane color and uses a harsh white + background). The problem with magic is that the 8-bit + colormap mode is increasingly considered "archaic" and + is less well supported as applications move toward 24-bit + color. Also, fabrication processes have moved toward + multiple metal and poly layers, which exceeds the + capacity of 8 bit planes to represent separate fabrication + layers. + + I have a solution: write a new graphics interface to + magic for OpenGL. Why? OpenGL is supported by many + high-performance video cards. It can do color blending + in hardware, which gives similar results to what magic + does with careful allocation of colors in the colormap. + And: it's not limited to eight bit planes. And: it + works in 24-bit color. And: say goodbye to stipple + patterns. All layers can be represented by solid colors, + and non-edit cell layers can have that "washed out" look + without compromising graphics resolution. The results + are stunning. Ideally, the interface would be based on + "glut", the generic graphics API for OpenGL, which would + avoid making explicit calls to X11 functions and make + magic easier to port to non-UNIX operating systems + (namely, Windows). Unfortunately, this approach got + bogged down in a problem with threads and Xlib. The + final answer on that is: Don't ever multithread an + OpenGL program unless you're sure you have 100% control + over the relative timing of the execution of all X11 and + OpenGL calls. Instead of glut, this implementation is + based on glX, the more specific API detailing the + use of OpenGL within an X11 environment. This method + keeps the original X11Handler as the event manager for + magic, and uses X11 cursors and a few other routines. + Everything else is rendered using OpenGL commands. + +Usage notes: + + Especially for Intel x86 and compatible platforms: + Don't attempt to using magic/OpenGL with the Mesa OpenGL + library unless you have video hardware support (as far as + I know, this is only true for the Voodoo cards). + More specifically, the hardware has to support color + blends (GL_BLEND function); otherwise you will be waiting + all day long for magic to draw your chip layout. There + is one (commercial) driver available as of this writing + (Xi graphics 3D Accelerated X server, see www.xig.com, + works with several dozen video cards), and promises for + the near future from SuSe, RedHat, MetroX, and Precision + Insight. I am assuming that this is the wave of the + future; otherwise, I wouldn't bother with the + implementation. OpenGL rendering under the Xi Graphics + server is a bit slower than with the X11 interface, but + benchmarks are a complex combination of driver, card, + revision numbers of each, processor type and speed, and + magic implementation. + + If magic is compiled only for OpenGL, this will come up + as the default. Otherwise, if it is compiled along with + X11, X11 will be the default and it will require typing + + > magic -d OGL + + on the command line to get the OpenGL graphics. + +Implementation notes: + + OpenGL is normally considered a 3D rendering engine; + here, I make use of 3D hardware acceleration, but all + transformation matrices are aligned perpendicular to + the depth (z) axis. There is no colormap; although + OpenGL can work in color index mode, there is no + point in doing so because the X11 version would be + faster. For reasons of simplicity, the OpenGL + version takes its color input from mos.7bit.std.cmap1, + although instead of plugging them into a colormap, it + sets the color according to their RGB values. The + mos.7bit.std.cmap1 has been extended to include a set + of solid colors which implement the "washed out" look + of magic's non-edit cells without reverting to the + checkerboard stipple pattern. Existence of the gray + background made the color blending tricky, because + anything blended with gray becomes grayer. However, + OpenGL allows color specs to run outside of the + normal color boundaries; it only cares whether the + color values map to real video values after all + transformations (like blending) have been performed + on the color values. So we compute "super-colors" + which can be whiter than white and blacker than + black, but which arithmetically resolve to the + usual magic colors when blended with the background + gray. This achieves the desired effect. The only + real difference between the OpenGL and X11 displays + is the blend colors, which are always "computationally + perfect" blends of multiple solids in OpenGL but have + been tweaked for aesthetic effect in the X11 + colormap version. This effect has been reproduced + in the OpenGL version by tweaking the color, style, + and tech files. In addition, new styles have been + added for poly2 and capacitors. + OpenGL has several emergent features unavailable + in the X11 version: one is an unlimited number of + solid colors (and their mixtures); this made all + the difference on my layouts in 3-metal layer + technologies, where the 3rd metal layer covers large + areas and makes parts of the circuit uninterpretable + when viewed through the nasty cross-hatched magenta + stipple. Under OpenGL, the magenta color is perhaps + still a bit severe, but the whole circuit is easily + viewed underneath. The second emergent benefit is + that layers of the same material which overlap in + separate cells are drawn darker at the overlap (due + to the blending function), so it is much easier to + see where one cell ends and another begins. + +Bugs: + + Bugs of the source and of the glX driver are difficult + to separate. My Xi Graphics 3D Accelerated-X server + previously had problems drawing over X11 windows + overlapping the magic window; this behavior has + disappeared in the current distribution of the X + server (May 2000). A good test of server bugs is + to run magic/OpenGL on an SGI machine, which has a + stable implementation of OpenGL. + +Files changed are: + +1. scripts/configure.in (altered) + +2. graphics/Makefile (altered) + +3. graphics/grOGL*.c (new) + graphics/grTOGL*.c (new) + +4. scmos/mos.7bit.std.cmap (altered) + scmos/mos.OpenGL.dstyle (new) + scmos/mos.7bit.dstyle (altered) + scmos/*.tech (altered) + diff --git a/doc/textfiles/readline.txt b/doc/textfiles/readline.txt new file mode 100644 index 00000000..66658f07 --- /dev/null +++ b/doc/textfiles/readline.txt @@ -0,0 +1,71 @@ + + + 11 January 2001 + + Magic now with GNU Readline + + Jeff Solomon + + +This file describes the implementation of the GNU Readline interface +in to magic. + +1. Introduction + + GNU Readline helps you type. As you may know from using a modern shell, + like bash, tcsh, or zsh, quickly returning to an old command or typing + only an abbreviation of the command desired can save a tremendous amount + of time. Now magic has those same capabilities with the addition of GNU + Readline. + +2. Building + + First, you have to compile the readline interface in. Do this by + selecting "yes" when asked from scripts/config program. The magic + distribution comes with the source for readline and I'd suggest using it + because it will always be a version that works. + +3. Usage + + The short answer is "Press ". In Readline, the TAB key cause + completion to occur. First press ":" to get the command prompt, then + hit TAB twice. You should see a list of all magic commands. Next, hit + the letter "c" and hit TAB again. You should see a list of all the + commands that begin with the letter "c". But wait, there's more! This + implementation of readline has context sensitive completion. Type + ":see " and hit TAB. It gives a list of possible layer names in the + current technology. Pretty cool, huh? Next, try ":getcell " and then + TAB, it will list all possible cell names. Very neat I think. Here are + the possible things that are completed depending on the command and + the placement of the cursor in a command: + + commands + command arguments + macros + interative macros + layer names + file names/usernames + cell names + istyle names + ostyle names + directions (eg. bottom, down, east) + + When in doubt, just hit TAB! + +4. Programming + + Mostly all the code for the readline interface lives in + textio/txInput.c. There is also some in textio/txMain.c, but only in + one place of initialization. See these two files and the docs for + readline itself for instructions on changing the interface. + +5. GNU License vs. Magic License + + The GNU license under with Readline is released is fairly + restrictive. There is some concern that by integrating readline into + magic, the magic code itself will be "infected" with the GNU + license. My belief (which clearly could be wrong) is that as long as + compiling without the code is an option and the code is clearly + #ifdef'ed then it should not be a problem because a clear + deliniation between magic and readline code has been maintained. Any + GNU experts feel free to enlighten the rest of us if we're wrong. diff --git a/doc/tutcells/Makefile b/doc/tutcells/Makefile new file mode 100644 index 00000000..7edc8cb5 --- /dev/null +++ b/doc/tutcells/Makefile @@ -0,0 +1,37 @@ +# +# makefile for Magic documentation +# + +MAGICDIR = ../.. + +include ${MAGICDIR}/defs.mak + +TUTDIR = ${LIBDIR}/magic/tutorial + +TUTFILES= m3a.mag maint2a.mag tut1.mag \ + tut2a.mag tut2b.mag tut2c.mag tut2d.mag \ + tut3a.mag tut3b.mag tut3c.mag tut3d.mag tut3e.mag \ + tut3f.mag tut3g.mag tut3h.mag \ + tut4a.mag tut4x.mag tut4y.mag tut4z.mag \ + tut5a.mag tut5b.mag \ + tut6a.mag tut6b.mag tut6c.mag tut6x.mag tut6y.mag \ + tut7a.mag tut7b.mag tut7b.net tut7c.mag tut7d.mag tut7d.net \ + tut8a.mag tut8b.mag tut8c.mag tut8d.mag tut8e.mag tut8f.mag \ + tut8g.mag tut8h.mag tut8i.mag tut8j.mag tut8k.mag tut8l.mag \ + tut8m.mag tut8n.mag tut8r.mag \ + tut9a.mag tut9b.mag tut9x.mag tut9y.mag \ + tut11a.mag tut11b.mag tut11c.mag tut11d.mag \ + tut11a.al tut11a.cmd tut11a.ext tut11a.nodes tut11a.sim \ + tut11b.ext tut11c.ext tut11d.ext + +INST_TUTFILES= $(TUTFILES:%=$(DESTDIR)${TUTDIR}/%) + +install: $(DESTDIR)${TUTDIR} ${INST_TUTFILES} + +$(DESTDIR)${TUTDIR}: make-tut-dirs + +make-tut-dirs: + ${SCRIPTS}/mkdirs $(DESTDIR)${TUTDIR} + +$(DESTDIR)${TUTDIR}/%: % $(DESTDIR)${TUTDIR} + ${CP} $* $(DESTDIR)${TUTDIR}/$* diff --git a/doc/tutcells/m3a.mag b/doc/tutcells/m3a.mag new file mode 100644 index 00000000..d26288ab --- /dev/null +++ b/doc/tutcells/m3a.mag @@ -0,0 +1,25 @@ +magic +tech nmos +timestamp 478544012 +<< polysilicon >> +rect -10 8 -8 10 +rect -6 8 10 10 +rect -10 1 -8 5 +rect -6 1 -3 5 +<< diffusion >> +rect -8 10 -6 12 +rect -8 5 -6 8 +rect -8 -1 -6 1 +rect -8 -9 -6 -5 +<< metal >> +rect 1 1 10 4 +rect -6 -5 10 -2 +<< poly-metal-contact >> +rect -3 1 1 5 +<< diff-metal-contact >> +rect -10 -5 -6 -1 +<< enhancement-fet >> +rect -8 8 -6 10 +<< depletion-fet >> +rect -8 1 -6 5 +<< end >> diff --git a/doc/tutcells/maint2a.mag b/doc/tutcells/maint2a.mag new file mode 100644 index 00000000..5be636b7 --- /dev/null +++ b/doc/tutcells/maint2a.mag @@ -0,0 +1,24 @@ +magic +tech scmos +timestamp 617322824 +<< polysilicon >> +rect -13 8 -9 10 +rect -6 8 10 10 +rect -13 1 -9 5 +rect -6 1 -3 5 +<< ndiffusion >> +rect -9 10 -6 13 +rect -9 5 -6 8 +rect -9 -1 -6 1 +rect -9 -9 -6 -5 +<< metal1 >> +rect 1 1 10 4 +rect -6 -5 10 -2 +<< polycontact >> +rect -3 1 1 5 +<< ndcontact >> +rect -10 -5 -6 -1 +<< ntransistor >> +rect -9 8 -6 10 +rect -9 1 -6 5 +<< end >> diff --git a/doc/tutcells/tut1.mag b/doc/tutcells/tut1.mag new file mode 100644 index 00000000..6abc7b05 --- /dev/null +++ b/doc/tutcells/tut1.mag @@ -0,0 +1,10 @@ +magic +tech scmos +timestamp 500615676 +<< polysilicon >> +rect -17 -15 -10 -5 +<< ndiffusion >> +rect -12 11 2 14 +<< metal1 >> +rect 7 -3 13 6 +<< end >> diff --git a/doc/tutcells/tut11a.al b/doc/tutcells/tut11a.al new file mode 100644 index 00000000..89a1dd61 --- /dev/null +++ b/doc/tutcells/tut11a.al @@ -0,0 +1,68 @@ += bit_3 bit_3/tut11d_0/B += bit_3 bit_3/5_73_39# += bit_3 bit_3/tut11d_0/Q_out += bit_3/5_69_27# bit_3/tut11d_0/5_23_109# += bit_3/5_69_27# bit_2/5_69_105# += bit_2 bit_2/tut11d_0/B += bit_2 bit_2/5_73_87# += bit_2 bit_2/tut11d_0/Q_out += bit_2/5_69_83# bit_2/tut11d_0/5_23_109# += bit_2/5_69_83# bit_1/5_69_49# += bit_1 bit_1/tut11d_0/B += bit_1 bit_1/5_73_39# += bit_1 bit_1/tut11d_0/Q_out += bit_1/5_69_27# bit_1/tut11d_0/5_23_109# += bit_1/5_69_27# bit_0/5_69_105# += phi2_b bit_3/tut11d_0/phi2_b += phi2_b bit_2/tut11d_0/phi2_b += phi2_b bit_1/tut11d_0/phi2_b += phi2_b bit_0/tut11d_0/phi2_b += phi2_b bit_3/5_41_121# += phi2_b bit_2/5_41_121# += phi2_b bit_1/5_41_121# += phi2_b bit_0/5_41_121# += phi1 bit_3/tut11d_0/phi1 += phi1 bit_2/tut11d_0/phi1 += phi1 bit_1/tut11d_0/phi1 += phi1 bit_0/tut11d_0/phi1 += phi1 bit_3/5_81_121# += phi1 bit_2/5_81_121# += phi1 bit_1/5_81_121# += phi1 bit_0/5_81_121# += phi2 bit_3/tut11d_0/phi2 += phi2 bit_2/tut11d_0/phi2 += phi2 bit_1/tut11d_0/phi2 += phi2 bit_0/tut11d_0/phi2 += RESET_B bit_3/tut11d_0/reset_b += RESET_B bit_2/tut11d_0/reset_b += RESET_B bit_1/tut11d_0/reset_b += RESET_B bit_0/tut11d_0/reset_b += phi1_b bit_3/tut11d_0/phi1_b += phi1_b bit_2/tut11d_0/phi1_b += phi1_b bit_1/tut11d_0/phi1_b += phi1_b bit_0/tut11d_0/phi1_b += hold bit_0/5_69_83# += hold bit_0/tut11d_0/5_23_109# += bit_0 bit_0/tut11d_0/B += bit_0 bit_0/5_73_87# += bit_0 bit_0/tut11d_0/Q_out += Vdd bit_3/tut11d_0/Vdd += Vdd bit_3/5_37_89# += Vdd bit_2/tut11d_0/Vdd += Vdd bit_2/5_37_45# += Vdd bit_1/tut11d_0/Vdd += Vdd bit_1/5_37_89# += Vdd bit_0/tut11d_0/Vdd += Vdd bit_0/5_37_45# += GND bit_3/tut11d_0/GND += GND bit_1/tut11d_0/GND += GND bit_1/7_81_13# += GND bit_1/4_81_57# += GND bit_3/7_81_13# += GND bit_3/4_81_57# += GND bit_2/tut11d_0/GND += GND bit_2/7_81_121# += GND bit_2/4_81_121# += GND bit_0/tut11d_0/GND += GND bit_0/7_81_121# += GND bit_0/4_81_121# diff --git a/doc/tutcells/tut11a.cmd b/doc/tutcells/tut11a.cmd new file mode 100644 index 00000000..583ae1b1 --- /dev/null +++ b/doc/tutcells/tut11a.cmd @@ -0,0 +1,6 @@ +vector clk phi1 phi2 +vector clkb phi1_b phi2_b +clock clk 10 00 01 00 +clock clkb 01 11 10 11 +vector bits bit_3 bit_2 bit_1 bit_0 +w clk hold RESET_B bits diff --git a/doc/tutcells/tut11a.ext b/doc/tutcells/tut11a.ext new file mode 100644 index 00000000..05027b95 --- /dev/null +++ b/doc/tutcells/tut11a.ext @@ -0,0 +1,113 @@ +timestamp 552706284 +version 7.2 +tech scmos +style lambda=1.0(scna20_orb) +scale 1000 1 100 +resistclasses 26670 59550 23860 19690 27260 2000000 49 26 2505830 +use tut11c bit_3 0 1 28 -1 0 -62 +use tut11b bit_2 0 1 82 -1 0 -62 +use tut11c bit_1 0 1 136 -1 0 -62 +use tut11b bit_0 0 1 190 -1 0 -62 +node "GND" 2 68694 -34 -222 m1 0 0 0 0 0 0 0 0 0 0 0 0 1350 462 276 116 0 0 +node "bit_0" 0 4248 158 -197 v 0 0 0 0 0 0 0 0 0 0 0 0 16 16 208 112 0 0 +node "bit_1" 0 4248 104 -197 v 0 0 0 0 0 0 0 0 0 0 0 0 16 16 208 112 0 0 +node "bit_2" 0 4248 50 -197 v 0 0 0 0 0 0 0 0 0 0 0 0 16 16 208 112 0 0 +node "bit_3" 0 4248 -4 -197 v 0 0 0 0 0 0 0 0 0 0 0 0 16 16 208 112 0 0 +node "hold" 0 9306 190 -32 m1 0 0 0 0 0 0 0 0 0 0 0 0 206 90 0 0 0 0 +node "Vdd" 2 65682 -32 -19 v 0 0 0 0 0 0 0 0 0 0 0 0 1332 456 162 90 0 0 +node "a_36_n244#" 596 12852 36 -244 p 0 0 0 0 108 108 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_24_n244#" 322 6746 24 -244 p 0 0 0 0 54 58 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_8_n244#" 643 13804 8 -244 p 0 0 0 0 116 116 0 0 0 0 0 0 0 0 0 0 0 0 +node "phi2" 203 4366 190 -159 p 0 0 0 0 34 38 0 0 0 0 0 0 0 0 0 0 0 0 +node "RESET_B" 97 9316 190 -151 p 0 0 0 0 124 56 0 0 0 0 0 0 0 0 0 0 0 0 +node "phi1_b" 203 4366 190 -129 p 0 0 0 0 34 38 0 0 0 0 0 0 0 0 0 0 0 0 +node "phi2_b" 322 25379 190 -175 p 0 0 0 0 62 62 0 0 0 0 0 0 375 256 0 0 0 0 +node "phi1" 644 24191 190 -113 p 0 0 0 0 116 116 0 0 0 0 0 0 189 132 0 0 0 0 +cap "phi1" "phi2_b" 180 +cap "phi1" "hold" 240 +cap "GND" "bit_3" 1080 +cap "phi1_b" "phi2_b" 180 +cap "GND" "bit_2" 1080 +cap "phi2_b" "RESET_B" 180 +cap "phi2_b" "phi2" 180 +cap "GND" "bit_1" 1080 +cap "bit_0" "GND" 1080 +cap "bit_3/tut11d_0/phi2" "bit_3/tut11d_0/GND" -784 +cap "bit_3/tut11d_0/phi2_b" "bit_3/tut11d_0/GND" -784 +cap "bit_3/tut11d_0/reset_b" "bit_3/tut11d_0/GND" -784 +cap "bit_2/tut11d_0/Vdd" "bit_2/tut11d_0/reset_b" -316 +cap "bit_2/tut11d_0/phi2" "bit_2/tut11d_0/Vdd" -316 +cap "bit_2/tut11d_0/phi2_b" "bit_2/tut11d_0/Vdd" -316 +cap "bit_1/tut11d_0/GND" "bit_2/tut11d_0/reset_b" -784 +cap "bit_1/tut11d_0/GND" "bit_2/tut11d_0/phi2" -784 +cap "bit_1/tut11d_0/GND" "bit_2/tut11d_0/phi2_b" -784 +cap "bit_2/tut11d_0/phi1" "bit_3/tut11d_0/GND" -784 +cap "bit_3/tut11d_0/phi1_b" "bit_3/tut11d_0/GND" -784 +cap "bit_1/tut11d_0/GND" "bit_2/tut11d_0/phi1" -784 +cap "bit_2/tut11d_0/Vdd" "bit_2/tut11d_0/phi1" -316 +cap "bit_1/tut11d_0/GND" "bit_2/tut11d_0/phi1_b" -784 +cap "bit_2/tut11d_0/Vdd" "bit_2/tut11d_0/phi1_b" -316 +cap "bit_3/a_n40_n60#" "bit_2/tut11d_0/GND" -228 +cap "bit_3/w_n40_n28#" "bit_3/a_n34_n13#" -1128 +cap "bit_3/w_n40_n28#" "bit_3/a_n20_n60#" -468 +cap "bit_3/w_n40_n28#" "bit_3/a_n40_n60#" -468 +cap "bit_2/tut11d_0/GND" "bit_3/a_n34_n13#" -1080 +cap "bit_2/tut11d_0/GND" "bit_3/a_n20_n60#" -228 +cap "bit_3/w_n40_n28#" "bit_2/tut11d_0/GND" -1710 +cap "bit_1/w_n40_n28#" "bit_2/a_n20_n60#" -468 +cap "bit_1/w_n40_n28#" "bit_0/tut11d_0/GND" -1710 +cap "bit_2/a_n40_n60#" "bit_2/a_n18_n22#" -228 +cap "bit_2/a_n40_n60#" "bit_0/tut11d_0/GND" -228 +cap "bit_2/a_n18_n22#" "bit_2/a_n34_n41#" -1080 +cap "bit_0/tut11d_0/GND" "bit_1/a_n34_n13#" -1080 +cap "bit_1/w_n40_n28#" "bit_2/a_n40_n60#" -468 +cap "bit_2/a_n18_n22#" "bit_2/a_n20_n60#" -228 +cap "bit_0/tut11d_0/GND" "bit_2/a_n20_n60#" -228 +cap "bit_1/w_n40_n28#" "bit_1/a_n34_n13#" -1128 +merge "bit_0/a_n18_n22#" "bit_1/tut11d_0/Vdd" -1710 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 -138 -88 0 0 +merge "bit_1/tut11d_0/Vdd" "bit_2/tut11d_0/Vdd" -1710 +merge "bit_2/tut11d_0/Vdd" "bit_2/a_n18_n22#" -1710 +merge "bit_2/a_n18_n22#" "bit_3/a_n18_n44#" -1710 +merge "bit_3/a_n18_n44#" "Vdd" -1710 +merge "bit_0/tut11d_0/GND" "bit_1/tut11d_0/GND" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +merge "bit_1/tut11d_0/GND" "bit_2/tut11d_0/GND" 0 +merge "bit_2/tut11d_0/GND" "bit_3/tut11d_0/GND" 0 +merge "bit_3/tut11d_0/GND" "GND" 0 +merge "GND" "bit_3/w_n40_n28#" 0 +merge "bit_3/w_n40_n28#" "bit_1/w_n40_n28#" 0 +merge "bit_0/tut11d_0/phi1_b" "bit_1/tut11d_0/phi1_b" -320 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 0 0 0 0 +merge "bit_1/tut11d_0/phi1_b" "bit_2/tut11d_0/phi1_b" -320 +merge "bit_2/tut11d_0/phi1_b" "bit_3/tut11d_0/phi1_b" -320 +merge "bit_3/tut11d_0/phi1_b" "phi1_b" -320 +merge "bit_2/tut11d_0/Q_out" "bit_2" -752 0 0 0 0 0 0 0 0 0 0 0 0 -16 -16 0 0 0 0 +merge "bit_0/a_n34_n41#" "hold" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -8 0 0 0 0 +merge "bit_0/a_n20_n60#" "bit_1/a_n20_n60#" -640 0 0 0 0 0 -8 0 0 0 0 0 0 0 0 0 0 0 0 +merge "bit_1/a_n20_n60#" "bit_2/a_n20_n60#" -640 +merge "bit_2/a_n20_n60#" "bit_3/a_n20_n60#" -640 +merge "bit_3/a_n20_n60#" "bit_0/tut11d_0/phi2_b" -640 +merge "bit_0/tut11d_0/phi2_b" "bit_1/tut11d_0/phi2_b" -640 +merge "bit_1/tut11d_0/phi2_b" "bit_2/tut11d_0/phi2_b" -640 +merge "bit_2/tut11d_0/phi2_b" "bit_3/tut11d_0/phi2_b" -640 +merge "bit_3/tut11d_0/phi2_b" "phi2_b" -640 +merge "bit_0/tut11d_0/reset_b" "bit_1/tut11d_0/reset_b" -320 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 0 0 0 0 +merge "bit_1/tut11d_0/reset_b" "bit_2/tut11d_0/reset_b" -320 +merge "bit_2/tut11d_0/reset_b" "bit_3/tut11d_0/reset_b" -320 +merge "bit_3/tut11d_0/reset_b" "RESET_B" -320 +merge "bit_0/a_n34_n52#" "bit_1/a_n34_n13#" 0 0 0 0 0 0 0 0 0 0 0 0 0 -24 -20 0 0 0 0 +merge "bit_1/a_n34_n24#" "bit_2/a_n34_n41#" -1128 0 0 0 0 0 0 0 0 0 0 0 0 -24 -20 0 0 0 0 +merge "bit_2/a_n34_n52#" "bit_3/a_n34_n13#" 0 0 0 0 0 0 0 0 0 0 0 0 0 -24 -20 0 0 0 0 +merge "bit_0/tut11d_0/Q_out" "bit_0" -752 0 0 0 0 0 0 0 0 0 0 0 0 -16 -16 0 0 0 0 +merge "bit_0/a_n40_n60#" "bit_1/a_n40_n60#" -640 0 0 0 0 0 -8 0 0 0 0 0 0 0 0 0 0 0 0 +merge "bit_1/a_n40_n60#" "bit_2/a_n40_n60#" -640 +merge "bit_2/a_n40_n60#" "bit_3/a_n40_n60#" -640 +merge "bit_3/a_n40_n60#" "bit_0/tut11d_0/phi1" -640 +merge "bit_0/tut11d_0/phi1" "bit_1/tut11d_0/phi1" -640 +merge "bit_1/tut11d_0/phi1" "bit_2/tut11d_0/phi1" -640 +merge "bit_2/tut11d_0/phi1" "bit_3/tut11d_0/phi1" -640 +merge "bit_3/tut11d_0/phi1" "phi1" -640 +merge "bit_1/tut11d_0/Q_out" "bit_1" -752 0 0 0 0 0 0 0 0 0 0 0 0 -16 -16 0 0 0 0 +merge "bit_0/tut11d_0/phi2" "bit_1/tut11d_0/phi2" -320 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 0 0 0 0 +merge "bit_1/tut11d_0/phi2" "bit_2/tut11d_0/phi2" -320 +merge "bit_2/tut11d_0/phi2" "bit_3/tut11d_0/phi2" -320 +merge "bit_3/tut11d_0/phi2" "phi2" -320 +merge "bit_3/tut11d_0/Q_out" "bit_3" -752 0 0 0 0 0 0 0 0 0 0 0 0 -16 -16 0 0 0 0 diff --git a/doc/tutcells/tut11a.mag b/doc/tutcells/tut11a.mag new file mode 100644 index 00000000..eed5e80f --- /dev/null +++ b/doc/tutcells/tut11a.mag @@ -0,0 +1,100 @@ +magic +tech scmos +timestamp 552706284 +<< polysilicon >> +rect 190 -24 201 -22 +rect 199 -42 201 -24 +rect 190 -44 192 -42 +rect 190 -113 199 -111 +rect 203 -113 207 -111 +rect 190 -129 207 -127 +rect 197 -149 207 -143 +rect 190 -151 207 -149 +rect 197 -154 207 -151 +rect 190 -159 207 -157 +rect 190 -175 193 -173 +rect 197 -175 207 -173 +rect 8 -226 19 -224 +rect 8 -233 10 -226 +rect 17 -233 19 -226 +rect 8 -235 19 -233 +rect 8 -244 10 -235 +rect 15 -237 17 -235 +rect 15 -239 19 -237 +rect 17 -240 19 -239 +rect 17 -242 21 -240 +rect 19 -244 21 -242 +rect 24 -242 26 -224 +rect 36 -226 47 -224 +rect 36 -233 38 -226 +rect 45 -233 47 -226 +rect 36 -235 47 -233 +rect 24 -244 33 -242 +rect 36 -244 38 -235 +rect 45 -244 47 -235 +<< metal1 >> +rect -26 -19 76 -13 +rect 82 -19 184 -13 +rect 214 -28 224 -24 +rect 190 -32 224 -28 +rect 214 -35 224 -32 +rect 193 -171 196 -46 +rect 199 -109 202 -46 +rect -34 -222 22 -216 +rect 28 -222 130 -216 +rect 136 -222 191 -216 +<< metal2 >> +rect -32 -22 -26 -19 +rect 76 -22 82 -19 +rect 184 -22 190 -19 +rect -4 -245 0 -197 +rect 22 -216 28 -199 +rect 50 -245 54 -197 +rect 104 -245 108 -197 +rect 130 -216 136 -199 +rect 158 -245 162 -197 +<< polycontact >> +rect 192 -46 196 -42 +rect 199 -46 203 -42 +rect 199 -113 203 -109 +rect 193 -175 197 -171 +<< m2contact >> +rect -32 -19 -26 -13 +rect 76 -19 82 -13 +rect 184 -19 190 -13 +rect -4 -197 0 -193 +rect 50 -197 54 -193 +rect 104 -197 108 -193 +rect 158 -197 162 -193 +rect 22 -222 28 -216 +rect 130 -222 136 -216 +use tut11c bit_3 +timestamp 552706284 +transform 0 1 28 -1 0 -62 +box -40 -60 137 0 +use tut11b bit_2 +timestamp 552706284 +transform 0 1 82 -1 0 -62 +box -40 -60 137 0 +use tut11c bit_1 +timestamp 552706284 +transform 0 1 136 -1 0 -62 +box -40 -60 137 0 +use tut11b bit_0 +timestamp 552706284 +transform 0 1 190 -1 0 -62 +box -40 -60 137 0 +<< labels >> +rlabel metal1 224 -35 224 -24 7 hold +rlabel polysilicon 207 -113 207 -111 7 phi1 +rlabel metal1 191 -222 191 -216 1 GND +rlabel m2contact 190 -19 190 -13 5 Vdd +rlabel polysilicon 207 -129 207 -127 7 phi1_b +rlabel polysilicon 207 -159 207 -157 7 phi2 +rlabel polysilicon 207 -175 207 -173 7 phi2_b +rlabel metal2 160 -245 160 -245 5 bit_0 +rlabel metal2 106 -245 106 -245 5 bit_1 +rlabel metal2 52 -245 52 -245 5 bit_2 +rlabel metal2 -2 -245 -2 -245 5 bit_3 +rlabel polysilicon 202 -143 202 -143 1 RESET_B +<< end >> diff --git a/doc/tutcells/tut11a.nodes b/doc/tutcells/tut11a.nodes new file mode 100644 index 00000000..41e983a8 --- /dev/null +++ b/doc/tutcells/tut11a.nodes @@ -0,0 +1,72 @@ +94 5_72_489# 5400 -36600 p; +94 5_48_489# 3600 -36600 p; +94 5_16_489# 1200 -36600 p; +94 bit_3/5_69_49# 600 -4350 ndc; +94 bit_3/5_69_35# 1650 -4350 green; +94 bit_3/tut11d_0/5_202_95# 2100 -24600 ndc; +94 bit_3/tut11d_0/5_154_89# 1650 -21000 green; +94 bit_3/tut11d_0/5_154_81# 1050 -21000 green; +94 bit_3/tut11d_0/5_110_95# 2100 -17700 ndc; +94 bit_3/tut11d_0/5_78_79# 900 -15300 green; +94 bit_3/tut11d_0/5_52_79# 900 -13350 green; +94 bit_3/tut11d_0/5_78_47# -1500 -15300 brown; +94 bit_3/tut11d_0/5_62_79# 900 -14100 green; +94 bit_3/tut11d_0/5_52_47# -1500 -13350 brown; +94 bit_3/tut11d_0/A 2850 -9450 green; +94 bit_3/tut11d_0/B_b 900 -11100 ndc; +94 bit_3/tut11d_0/A_b 2850 -7050 ndc; +94 bit_3 -600 -29550 v; +94 bit_2/5_69_91# 5550 -4350 green; +94 bit_3/5_69_27# 3150 -7800 p; +94 bit_2/tut11d_0/5_202_95# 5250 -24600 ndc; +94 bit_2/tut11d_0/5_154_89# 5700 -21000 green; +94 bit_2/tut11d_0/5_154_81# 6300 -21000 green; +94 bit_2/tut11d_0/5_110_95# 5250 -17700 ndc; +94 bit_2/tut11d_0/5_78_79# 6450 -15300 green; +94 bit_2/tut11d_0/5_52_79# 6450 -13350 green; +94 bit_2/tut11d_0/5_78_47# 8850 -15300 brown; +94 bit_2/tut11d_0/5_62_79# 6450 -14100 green; +94 bit_2/tut11d_0/5_52_47# 8850 -13350 brown; +94 bit_2/tut11d_0/A 4500 -9450 green; +94 bit_2/tut11d_0/B_b 6450 -11100 ndc; +94 bit_2/tut11d_0/A_b 4500 -7050 ndc; +94 bit_2 7500 -29550 v; +94 bit_2/5_69_83# 4200 -7800 p; +94 bit_1/5_69_35# 17850 -4350 green; +94 bit_1/tut11d_0/5_202_95# 18300 -24600 ndc; +94 bit_1/tut11d_0/5_154_89# 17850 -21000 green; +94 bit_1/tut11d_0/5_154_81# 17250 -21000 green; +94 bit_1/tut11d_0/5_110_95# 18300 -17700 ndc; +94 bit_1/tut11d_0/5_78_79# 17100 -15300 green; +94 bit_1/tut11d_0/5_52_79# 17100 -13350 green; +94 bit_1/tut11d_0/5_78_47# 14700 -15300 brown; +94 bit_1/tut11d_0/5_62_79# 17100 -14100 green; +94 bit_1/tut11d_0/5_52_47# 14700 -13350 brown; +94 bit_1/tut11d_0/A 19050 -9450 green; +94 bit_1/tut11d_0/B_b 17100 -11100 ndc; +94 bit_1/tut11d_0/A_b 19050 -7050 ndc; +94 bit_1 15600 -29550 v; +94 bit_0/5_69_91# 21750 -4350 green; +94 bit_1/5_69_27# 19350 -7800 p; +94 phi2_b 28500 -26250 p; +94 phi1 28500 -16950 p; +94 bit_0/tut11d_0/5_202_95# 21450 -24600 ndc; +94 phi2 28500 -23850 p; +94 bit_0/tut11d_0/5_154_89# 21900 -21000 green; +94 bit_0/tut11d_0/5_154_81# 22500 -21000 green; +94 RESET_B 28500 -22650 p; +94 phi1_b 28500 -19350 p; +94 bit_0/tut11d_0/5_110_95# 21450 -17700 ndc; +94 bit_0/tut11d_0/5_78_79# 22650 -15300 green; +94 bit_0/tut11d_0/5_52_79# 22650 -13350 green; +94 bit_0/tut11d_0/5_78_47# 25050 -15300 brown; +94 bit_0/tut11d_0/5_62_79# 22650 -14100 green; +94 bit_0/tut11d_0/5_52_47# 25050 -13350 brown; +94 bit_0/tut11d_0/A 20700 -9450 green; +94 bit_0/tut11d_0/B_b 22650 -11100 ndc; +94 bit_0/tut11d_0/A_b 20700 -7050 ndc; +94 hold 20400 -7800 p; +94 bit_0 23700 -29550 v; +94 Vdd -2250 -6900 pdc; +94 GND -5100 -33300 m1; +94 Vdd! 28500 -9450 space; diff --git a/doc/tutcells/tut11a.sim b/doc/tutcells/tut11a.sim new file mode 100644 index 00000000..3f0d1e2e --- /dev/null +++ b/doc/tutcells/tut11a.sim @@ -0,0 +1,280 @@ +| units: 100 tech: scmos format: SU +p hold Vdd bit_0/tut11d_0/A_b 2 6 175 -52 g=S_Vdd! s=A_1108,P_688 d=A_30,P_22 +p bit_0/tut11d_0/A_b bit_0/tut11d_0/A Vdd 2 5 172 -63 g=S_Vdd! s=A_25,P_20 d=A_0,P_0 +p bit_0 bit_0/tut11d_0/B_b Vdd 2 6 167 -79 g=S_Vdd! s=A_30,P_22 d=A_0,P_0 +p bit_0/tut11d_0/A_b Vdd bit_0/tut11d_0/a_26_n23# 2 6 167 -87 g=S_Vdd! s=A_0,P_0 d=A_18,P_18 +p bit_0/tut11d_0/B_b bit_0/tut11d_0/a_26_n23# bit_0/tut11d_0/a_31_n39# 2 6 167 -92 g=S_Vdd! s=A_0,P_0 d=A_66,P_46 +p bit_0 bit_0/tut11d_0/a_31_n39# bit_0/tut11d_0/a_39_n23# 2 6 167 -100 g=S_Vdd! s=A_0,P_0 d=A_12,P_16 +p bit_0/tut11d_0/A bit_0/tut11d_0/a_39_n23# Vdd 2 6 167 -104 g=S_Vdd! s=A_0,P_0 d=A_0,P_0 +n bit_0 bit_0/tut11d_0/B_b GND 2 6 151 -79 g=S_GND s=A_30,P_34 d=A_792,P_896 +n bit_0/tut11d_0/A_b GND bit_0/tut11d_0/a_26_n39# 2 6 151 -87 g=S_GND s=A_0,P_0 d=A_18,P_18 +n bit_0 bit_0/tut11d_0/a_26_n39# bit_0/tut11d_0/a_31_n39# 2 6 151 -92 g=S_GND s=A_0,P_0 d=A_66,P_82 +n bit_0/tut11d_0/B_b bit_0/tut11d_0/a_31_n39# bit_0/tut11d_0/a_39_n39# 2 6 151 -100 g=S_GND s=A_0,P_0 d=A_12,P_16 +n bit_0/tut11d_0/A bit_0/tut11d_0/a_39_n39# GND 2 6 151 -104 g=S_GND s=A_0,P_0 d=A_0,P_0 +n hold bit_0/tut11d_0/A_b GND 2 6 138 -52 g=S_GND s=A_30,P_34 d=A_0,P_0 +n bit_0/tut11d_0/A_b GND bit_0/tut11d_0/A 2 6 138 -61 g=S_GND s=A_0,P_0 d=A_30,P_34 +p phi1_b bit_0/tut11d_0/a_31_n39# bit_0/tut11d_0/a_55_n47# 2 6 172 -118 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +p RESET_B Vdd bit_0/tut11d_0/a_77_n40# 2 5 173 -150 g=S_Vdd! s=A_0,P_0 d=A_117,P_80 +n phi1 bit_0/tut11d_0/a_55_n47# bit_0/tut11d_0/a_31_n39# 2 6 148 -118 g=S_GND s=A_30,P_34 d=A_0,P_0 +p bit_0/tut11d_0/a_55_n47# bit_0/tut11d_0/a_77_n40# Vdd 2 6 170 -140 g=S_Vdd! s=A_0,P_0 d=A_0,P_0 +n bit_0/tut11d_0/a_55_n47# bit_0/tut11d_0/a_77_n44# bit_0/tut11d_0/a_77_n40# 2 6 148 -140 g=S_GND s=A_12,P_16 d=A_60,P_68 +n RESET_B GND bit_0/tut11d_0/a_77_n44# 2 6 144 -140 g=S_GND s=A_0,P_0 d=A_0,P_0 +p phi2_b bit_0/tut11d_0/a_77_n40# bit_0/tut11d_0/a_101_n47# 2 6 170 -164 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +n phi2 bit_0/tut11d_0/a_101_n47# bit_0/tut11d_0/a_77_n40# 2 6 148 -164 g=S_GND s=A_30,P_34 d=A_0,P_0 +p bit_0/tut11d_0/a_101_n47# bit_0 Vdd 2 12 170 -186 g=S_Vdd! s=A_60,P_34 d=A_0,P_0 +n bit_0/tut11d_0/a_101_n47# GND bit_0 2 12 148 -186 g=S_GND s=A_0,P_0 d=A_60,P_58 +p phi2_b bit_1/a_n34_n13# Vdd 2 6 168 -43 g=S_Vdd! s=A_24,P_22 d=A_0,P_0 +n bit_0 bit_0/a_n34_n45# hold 2 6 147 -29 g=S_GND s=A_12,P_16 d=A_24,P_36 +n phi1 bit_1/a_n34_n13# bit_0/a_n34_n45# 2 6 143 -29 g=S_GND s=A_48,P_72 d=A_0,P_0 +p bit_1/a_n34_n13# Vdd bit_1/tut11d_0/A_b 2 6 90 -52 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +p bit_1/tut11d_0/A_b bit_1/tut11d_0/A Vdd 2 5 93 -63 g=S_Vdd! s=A_25,P_20 d=A_0,P_0 +p bit_1 bit_1/tut11d_0/B_b Vdd 2 6 98 -79 g=S_Vdd! s=A_30,P_22 d=A_0,P_0 +p bit_1/tut11d_0/A_b Vdd bit_1/tut11d_0/a_26_n23# 2 6 98 -87 g=S_Vdd! s=A_0,P_0 d=A_18,P_18 +p bit_1/tut11d_0/B_b bit_1/tut11d_0/a_26_n23# bit_1/tut11d_0/a_31_n39# 2 6 98 -92 g=S_Vdd! s=A_0,P_0 d=A_66,P_46 +p bit_1 bit_1/tut11d_0/a_31_n39# bit_1/tut11d_0/a_39_n23# 2 6 98 -100 g=S_Vdd! s=A_0,P_0 d=A_12,P_16 +p bit_1/tut11d_0/A bit_1/tut11d_0/a_39_n23# Vdd 2 6 98 -104 g=S_Vdd! s=A_0,P_0 d=A_0,P_0 +n bit_1 bit_1/tut11d_0/B_b GND 2 6 114 -79 g=S_GND s=A_30,P_34 d=A_0,P_0 +n bit_1/tut11d_0/A_b GND bit_1/tut11d_0/a_26_n39# 2 6 114 -87 g=S_GND s=A_0,P_0 d=A_18,P_18 +n bit_1 bit_1/tut11d_0/a_26_n39# bit_1/tut11d_0/a_31_n39# 2 6 114 -92 g=S_GND s=A_0,P_0 d=A_66,P_82 +n bit_1/tut11d_0/B_b bit_1/tut11d_0/a_31_n39# bit_1/tut11d_0/a_39_n39# 2 6 114 -100 g=S_GND s=A_0,P_0 d=A_12,P_16 +n bit_1/tut11d_0/A bit_1/tut11d_0/a_39_n39# GND 2 6 114 -104 g=S_GND s=A_0,P_0 d=A_0,P_0 +n bit_1/a_n34_n13# bit_1/tut11d_0/A_b GND 2 6 127 -52 g=S_GND s=A_30,P_34 d=A_0,P_0 +n bit_1/tut11d_0/A_b GND bit_1/tut11d_0/A 2 6 127 -61 g=S_GND s=A_0,P_0 d=A_30,P_34 +p phi1_b bit_1/tut11d_0/a_31_n39# bit_1/tut11d_0/a_55_n47# 2 6 93 -118 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +p RESET_B Vdd bit_1/tut11d_0/a_77_n40# 2 5 92 -150 g=S_Vdd! s=A_0,P_0 d=A_117,P_80 +n phi1 bit_1/tut11d_0/a_55_n47# bit_1/tut11d_0/a_31_n39# 2 6 117 -118 g=S_GND s=A_30,P_34 d=A_0,P_0 +p bit_1/tut11d_0/a_55_n47# bit_1/tut11d_0/a_77_n40# Vdd 2 6 95 -140 g=S_Vdd! s=A_0,P_0 d=A_0,P_0 +n bit_1/tut11d_0/a_55_n47# bit_1/tut11d_0/a_77_n44# bit_1/tut11d_0/a_77_n40# 2 6 117 -140 g=S_GND s=A_12,P_16 d=A_60,P_68 +n RESET_B GND bit_1/tut11d_0/a_77_n44# 2 6 121 -140 g=S_GND s=A_0,P_0 d=A_0,P_0 +p phi2_b bit_1/tut11d_0/a_77_n40# bit_1/tut11d_0/a_101_n47# 2 6 95 -164 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +n phi2 bit_1/tut11d_0/a_101_n47# bit_1/tut11d_0/a_77_n40# 2 6 117 -164 g=S_GND s=A_30,P_34 d=A_0,P_0 +p bit_1/tut11d_0/a_101_n47# bit_1 Vdd 2 12 95 -186 g=S_Vdd! s=A_60,P_34 d=A_0,P_0 +n bit_1/tut11d_0/a_101_n47# GND bit_1 2 12 117 -186 g=S_GND s=A_0,P_0 d=A_60,P_58 +n phi1 bit_1/a_n34_n17# bit_1/a_n34_n13# 2 6 121 -29 g=S_GND s=A_12,P_16 d=A_0,P_0 +n bit_1 bit_2/a_n34_n41# bit_1/a_n34_n17# 2 6 117 -29 g=S_GND s=A_48,P_72 d=A_0,P_0 +p phi2_b bit_2/a_n34_n41# Vdd 2 6 92 -43 g=S_Vdd! s=A_24,P_22 d=A_0,P_0 +p bit_2/a_n34_n41# Vdd bit_2/tut11d_0/A_b 2 6 67 -52 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +p bit_2/tut11d_0/A_b bit_2/tut11d_0/A Vdd 2 5 64 -63 g=S_Vdd! s=A_25,P_20 d=A_0,P_0 +p bit_2 bit_2/tut11d_0/B_b Vdd 2 6 59 -79 g=S_Vdd! s=A_30,P_22 d=A_0,P_0 +p bit_2/tut11d_0/A_b Vdd bit_2/tut11d_0/a_26_n23# 2 6 59 -87 g=S_Vdd! s=A_0,P_0 d=A_18,P_18 +p bit_2/tut11d_0/B_b bit_2/tut11d_0/a_26_n23# bit_2/tut11d_0/a_31_n39# 2 6 59 -92 g=S_Vdd! s=A_0,P_0 d=A_66,P_46 +p bit_2 bit_2/tut11d_0/a_31_n39# bit_2/tut11d_0/a_39_n23# 2 6 59 -100 g=S_Vdd! s=A_0,P_0 d=A_12,P_16 +p bit_2/tut11d_0/A bit_2/tut11d_0/a_39_n23# Vdd 2 6 59 -104 g=S_Vdd! s=A_0,P_0 d=A_0,P_0 +n bit_2 bit_2/tut11d_0/B_b GND 2 6 43 -79 g=S_GND s=A_30,P_34 d=A_0,P_0 +n bit_2/tut11d_0/A_b GND bit_2/tut11d_0/a_26_n39# 2 6 43 -87 g=S_GND s=A_0,P_0 d=A_18,P_18 +n bit_2 bit_2/tut11d_0/a_26_n39# bit_2/tut11d_0/a_31_n39# 2 6 43 -92 g=S_GND s=A_0,P_0 d=A_66,P_82 +n bit_2/tut11d_0/B_b bit_2/tut11d_0/a_31_n39# bit_2/tut11d_0/a_39_n39# 2 6 43 -100 g=S_GND s=A_0,P_0 d=A_12,P_16 +n bit_2/tut11d_0/A bit_2/tut11d_0/a_39_n39# GND 2 6 43 -104 g=S_GND s=A_0,P_0 d=A_0,P_0 +n bit_2/a_n34_n41# bit_2/tut11d_0/A_b GND 2 6 30 -52 g=S_GND s=A_30,P_34 d=A_0,P_0 +n bit_2/tut11d_0/A_b GND bit_2/tut11d_0/A 2 6 30 -61 g=S_GND s=A_0,P_0 d=A_30,P_34 +p phi1_b bit_2/tut11d_0/a_31_n39# bit_2/tut11d_0/a_55_n47# 2 6 64 -118 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +p RESET_B Vdd bit_2/tut11d_0/a_77_n40# 2 5 65 -150 g=S_Vdd! s=A_0,P_0 d=A_117,P_80 +n phi1 bit_2/tut11d_0/a_55_n47# bit_2/tut11d_0/a_31_n39# 2 6 40 -118 g=S_GND s=A_30,P_34 d=A_0,P_0 +p bit_2/tut11d_0/a_55_n47# bit_2/tut11d_0/a_77_n40# Vdd 2 6 62 -140 g=S_Vdd! s=A_0,P_0 d=A_0,P_0 +n bit_2/tut11d_0/a_55_n47# bit_2/tut11d_0/a_77_n44# bit_2/tut11d_0/a_77_n40# 2 6 40 -140 g=S_GND s=A_12,P_16 d=A_60,P_68 +n RESET_B GND bit_2/tut11d_0/a_77_n44# 2 6 36 -140 g=S_GND s=A_0,P_0 d=A_0,P_0 +p phi2_b bit_2/tut11d_0/a_77_n40# bit_2/tut11d_0/a_101_n47# 2 6 62 -164 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +n phi2 bit_2/tut11d_0/a_101_n47# bit_2/tut11d_0/a_77_n40# 2 6 40 -164 g=S_GND s=A_30,P_34 d=A_0,P_0 +p bit_2/tut11d_0/a_101_n47# bit_2 Vdd 2 12 62 -186 g=S_Vdd! s=A_60,P_34 d=A_0,P_0 +n bit_2/tut11d_0/a_101_n47# GND bit_2 2 12 40 -186 g=S_GND s=A_0,P_0 d=A_60,P_58 +p phi2_b bit_3/a_n34_n13# Vdd 2 6 60 -43 g=S_Vdd! s=A_24,P_22 d=A_0,P_0 +n bit_2 bit_2/a_n34_n45# bit_2/a_n34_n41# 2 6 39 -29 g=S_GND s=A_12,P_16 d=A_0,P_0 +n phi1 bit_3/a_n34_n13# bit_2/a_n34_n45# 2 6 35 -29 g=S_GND s=A_48,P_72 d=A_0,P_0 +p bit_3/a_n34_n13# Vdd bit_3/tut11d_0/A_b 2 6 -18 -52 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +p bit_3/tut11d_0/A_b bit_3/tut11d_0/A Vdd 2 5 -15 -63 g=S_Vdd! s=A_25,P_20 d=A_0,P_0 +p bit_3 bit_3/tut11d_0/B_b Vdd 2 6 -10 -79 g=S_Vdd! s=A_30,P_22 d=A_0,P_0 +p bit_3/tut11d_0/A_b Vdd bit_3/tut11d_0/a_26_n23# 2 6 -10 -87 g=S_Vdd! s=A_0,P_0 d=A_18,P_18 +p bit_3/tut11d_0/B_b bit_3/tut11d_0/a_26_n23# bit_3/tut11d_0/a_31_n39# 2 6 -10 -92 g=S_Vdd! s=A_0,P_0 d=A_66,P_46 +p bit_3 bit_3/tut11d_0/a_31_n39# bit_3/tut11d_0/a_39_n23# 2 6 -10 -100 g=S_Vdd! s=A_0,P_0 d=A_12,P_16 +p bit_3/tut11d_0/A bit_3/tut11d_0/a_39_n23# Vdd 2 6 -10 -104 g=S_Vdd! s=A_0,P_0 d=A_0,P_0 +n bit_3 bit_3/tut11d_0/B_b GND 2 6 6 -79 g=S_GND s=A_30,P_34 d=A_0,P_0 +n bit_3/tut11d_0/A_b GND bit_3/tut11d_0/a_26_n39# 2 6 6 -87 g=S_GND s=A_0,P_0 d=A_18,P_18 +n bit_3 bit_3/tut11d_0/a_26_n39# bit_3/tut11d_0/a_31_n39# 2 6 6 -92 g=S_GND s=A_0,P_0 d=A_66,P_82 +n bit_3/tut11d_0/B_b bit_3/tut11d_0/a_31_n39# bit_3/tut11d_0/a_39_n39# 2 6 6 -100 g=S_GND s=A_0,P_0 d=A_12,P_16 +n bit_3/tut11d_0/A bit_3/tut11d_0/a_39_n39# GND 2 6 6 -104 g=S_GND s=A_0,P_0 d=A_0,P_0 +n bit_3/a_n34_n13# bit_3/tut11d_0/A_b GND 2 6 19 -52 g=S_GND s=A_30,P_34 d=A_0,P_0 +n bit_3/tut11d_0/A_b GND bit_3/tut11d_0/A 2 6 19 -61 g=S_GND s=A_0,P_0 d=A_30,P_34 +p phi1_b bit_3/tut11d_0/a_31_n39# bit_3/tut11d_0/a_55_n47# 2 6 -15 -118 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +p RESET_B Vdd bit_3/tut11d_0/a_77_n40# 2 5 -16 -150 g=S_Vdd! s=A_0,P_0 d=A_117,P_80 +n phi1 bit_3/tut11d_0/a_55_n47# bit_3/tut11d_0/a_31_n39# 2 6 9 -118 g=S_GND s=A_30,P_34 d=A_0,P_0 +p bit_3/tut11d_0/a_55_n47# bit_3/tut11d_0/a_77_n40# Vdd 2 6 -13 -140 g=S_Vdd! s=A_0,P_0 d=A_0,P_0 +n bit_3/tut11d_0/a_55_n47# bit_3/tut11d_0/a_77_n44# bit_3/tut11d_0/a_77_n40# 2 6 9 -140 g=S_GND s=A_12,P_16 d=A_60,P_68 +n RESET_B GND bit_3/tut11d_0/a_77_n44# 2 6 13 -140 g=S_GND s=A_0,P_0 d=A_0,P_0 +p phi2_b bit_3/tut11d_0/a_77_n40# bit_3/tut11d_0/a_101_n47# 2 6 -13 -164 g=S_Vdd! s=A_0,P_0 d=A_30,P_22 +n phi2 bit_3/tut11d_0/a_101_n47# bit_3/tut11d_0/a_77_n40# 2 6 9 -164 g=S_GND s=A_30,P_34 d=A_0,P_0 +p bit_3/tut11d_0/a_101_n47# bit_3 Vdd 2 12 -13 -186 g=S_Vdd! s=A_60,P_34 d=A_0,P_0 +n bit_3/tut11d_0/a_101_n47# GND bit_3 2 12 9 -186 g=S_GND s=A_0,P_0 d=A_60,P_58 +n phi1 bit_3/a_n34_n17# bit_3/a_n34_n13# 2 6 13 -29 g=S_GND s=A_12,P_16 d=A_0,P_0 +n bit_3 bit_3/a_n34_n24# bit_3/a_n34_n17# 2 6 9 -29 g=S_GND s=A_24,P_36 d=A_0,P_0 +p phi2_b bit_3/a_n34_n24# Vdd 2 6 -16 -43 g=S_Vdd! s=A_24,P_22 d=A_0,P_0 +C bit_3/tut11d_0/B_b GND 5.8 +C bit_3 bit_3/tut11d_0/a_55_n47# 3.2 +C bit_0/tut11d_0/A GND 15.2 +C bit_2 Vdd 2.5 +C bit_1/tut11d_0/a_55_n47# GND 5.9 +C bit_1/tut11d_0/a_55_n47# bit_1 3.2 +C bit_3 Vdd 2.5 +C phi1_b GND 26.4 +C bit_0/tut11d_0/a_55_n47# GND 5.9 +C bit_2/tut11d_0/a_101_n47# GND 6.6 +C bit_0 GND 10.0 +C phi2 GND 33.3 +C bit_3/tut11d_0/a_55_n47# GND 5.9 +C bit_0/tut11d_0/B_b GND 5.8 +C bit_1 Vdd 2.5 +C bit_0/tut11d_0/a_31_n39# bit_0 2.5 +C bit_0/tut11d_0/a_101_n47# GND 6.6 +C bit_2 GND 10.0 +C bit_0/tut11d_0/a_77_n40# bit_0 2.2 +C bit_3 GND 10.5 +C bit_3 bit_3/tut11d_0/a_77_n40# 2.2 +C bit_0/tut11d_0/A_b GND 15.8 +C bit_2/a_n34_n41# GND 7.5 +C bit_2 bit_2/tut11d_0/a_31_n39# 2.5 +C bit_1 bit_1/tut11d_0/a_77_n40# 2.2 +C bit_1 GND 10.5 +C bit_3/tut11d_0/A_b GND 15.8 +C bit_1/tut11d_0/B_b GND 5.8 +C bit_2/tut11d_0/a_55_n47# phi1_b 2.2 +C RESET_B GND 33.3 +C bit_2/tut11d_0/A GND 15.2 +C phi1 GND 58.5 +C bit_2/tut11d_0/B_b GND 5.8 +C bit_1/tut11d_0/a_55_n47# phi1_b 2.2 +C bit_2/tut11d_0/a_55_n47# bit_2 3.2 +C GND bit_1/tut11d_0/a_101_n47# 6.6 +C bit_0/tut11d_0/a_55_n47# phi1_b 2.2 +C bit_3 bit_3/tut11d_0/a_31_n39# 2.5 +C bit_0/tut11d_0/a_55_n47# bit_0 3.2 +C bit_1/tut11d_0/A_b GND 15.8 +C hold GND 6.7 +C bit_3/tut11d_0/a_101_n47# GND 6.6 +C bit_3/tut11d_0/a_55_n47# phi1_b 2.2 +C bit_2/tut11d_0/A_b GND 15.8 +C bit_2/tut11d_0/a_55_n47# GND 5.9 +C Vdd bit_0 2.5 +C phi2_b GND 52.5 +C bit_3/tut11d_0/A GND 15.2 +C bit_1/tut11d_0/a_31_n39# bit_1 2.5 +C bit_1/tut11d_0/A GND 15.2 +C bit_3/a_n34_n13# GND 16.9 +C bit_1/a_n34_n13# GND 16.9 +C bit_2/tut11d_0/a_77_n40# bit_2 2.2 +C a_36_n244# GND 12.9 +R a_36_n244# 596 +C a_24_n244# GND 6.7 +R a_24_n244# 322 +C a_8_n244# GND 13.8 +R a_8_n244# 643 +C bit_3/a_n34_n24# GND 8.1 +R bit_3/a_n34_n24# 464 +R bit_3/a_n34_n17# 80 +C bit_3/tut11d_0/a_101_n47# GND 11.5 +R bit_3/tut11d_0/a_101_n47# 820 +R bit_3/tut11d_0/a_77_n44# 80 +C bit_3/tut11d_0/a_77_n40# GND 11.1 +R bit_3/tut11d_0/a_77_n40# 1150 +C bit_3/tut11d_0/a_55_n47# GND 11.3 +R bit_3/tut11d_0/a_55_n47# 773 +R bit_3/tut11d_0/a_39_n39# 80 +R bit_3/tut11d_0/a_26_n39# 53 +R bit_3/tut11d_0/a_39_n23# 179 +C bit_3/tut11d_0/a_31_n39# GND 9.6 +R bit_3/tut11d_0/a_31_n39# 973 +R bit_3/tut11d_0/a_26_n23# 119 +C bit_3/tut11d_0/A GND 7.0 +R bit_3/tut11d_0/A 1107 +C bit_3/tut11d_0/B_b GND 12.3 +R bit_3/tut11d_0/B_b 713 +C bit_3/tut11d_0/A_b GND 14.6 +R bit_3/tut11d_0/A_b 1537 +C bit_3 GND 46.3 +R bit_3 2324 +R bit_2/a_n34_n45# 80 +C bit_3/a_n34_n13# GND 12.2 +R bit_3/a_n34_n13# 1386 +C bit_2/tut11d_0/a_101_n47# GND 11.5 +R bit_2/tut11d_0/a_101_n47# 820 +R bit_2/tut11d_0/a_77_n44# 80 +C bit_2/tut11d_0/a_77_n40# GND 11.1 +R bit_2/tut11d_0/a_77_n40# 1150 +C bit_2/tut11d_0/a_55_n47# GND 11.3 +R bit_2/tut11d_0/a_55_n47# 773 +R bit_2/tut11d_0/a_39_n39# 80 +R bit_2/tut11d_0/a_26_n39# 53 +R bit_2/tut11d_0/a_39_n23# 179 +C bit_2/tut11d_0/a_31_n39# GND 9.6 +R bit_2/tut11d_0/a_31_n39# 973 +R bit_2/tut11d_0/a_26_n23# 119 +C bit_2/tut11d_0/A GND 7.0 +R bit_2/tut11d_0/A 1107 +C bit_2/tut11d_0/B_b GND 12.3 +R bit_2/tut11d_0/B_b 713 +C bit_2/tut11d_0/A_b GND 14.6 +R bit_2/tut11d_0/A_b 1537 +C bit_2 GND 46.9 +R bit_2 2324 +C bit_2/a_n34_n41# GND 21.0 +R bit_2/a_n34_n41# 1386 +R bit_1/a_n34_n17# 80 +C bit_1/tut11d_0/a_101_n47# GND 11.5 +R bit_1/tut11d_0/a_101_n47# 820 +R bit_1/tut11d_0/a_77_n44# 80 +C bit_1/tut11d_0/a_77_n40# GND 11.1 +R bit_1/tut11d_0/a_77_n40# 1150 +C bit_1/tut11d_0/a_55_n47# GND 11.3 +R bit_1/tut11d_0/a_55_n47# 773 +R bit_1/tut11d_0/a_39_n39# 80 +R bit_1/tut11d_0/a_26_n39# 53 +R bit_1/tut11d_0/a_39_n23# 179 +C bit_1/tut11d_0/a_31_n39# GND 9.6 +R bit_1/tut11d_0/a_31_n39# 973 +R bit_1/tut11d_0/a_26_n23# 119 +C bit_1/tut11d_0/A GND 7.0 +R bit_1/tut11d_0/A 1107 +C bit_1/tut11d_0/B_b GND 12.3 +R bit_1/tut11d_0/B_b 713 +C bit_1/tut11d_0/A_b GND 14.6 +R bit_1/tut11d_0/A_b 1537 +C bit_1 GND 46.3 +R bit_1 2324 +R bit_0/a_n34_n45# 80 +C bit_1/a_n34_n13# GND 12.2 +R bit_1/a_n34_n13# 1386 +C phi2_b GND 86.3 +R phi2_b 6913 +C phi1 GND 90.6 +R phi1 7806 +C bit_0/tut11d_0/a_101_n47# GND 11.5 +R bit_0/tut11d_0/a_101_n47# 820 +C phi2 GND 34.8 +R phi2 3784 +R bit_0/tut11d_0/a_77_n44# 80 +C bit_0/tut11d_0/a_77_n40# GND 11.1 +R bit_0/tut11d_0/a_77_n40# 1150 +C RESET_B GND 36.3 +R RESET_B 3486 +C phi1_b GND 41.8 +R phi1_b 3784 +C bit_0/tut11d_0/a_55_n47# GND 11.3 +R bit_0/tut11d_0/a_55_n47# 773 +R bit_0/tut11d_0/a_39_n39# 80 +R bit_0/tut11d_0/a_26_n39# 53 +R bit_0/tut11d_0/a_39_n23# 179 +C bit_0/tut11d_0/a_31_n39# GND 9.6 +R bit_0/tut11d_0/a_31_n39# 973 +R bit_0/tut11d_0/a_26_n23# 119 +C bit_0/tut11d_0/A GND 7.0 +R bit_0/tut11d_0/A 1107 +C bit_0/tut11d_0/B_b GND 12.3 +R bit_0/tut11d_0/B_b 713 +C bit_0/tut11d_0/A_b GND 14.6 +R bit_0/tut11d_0/A_b 1537 +C hold GND 23.4 +R hold 866 +C bit_0 GND 46.9 +R bit_0 2324 +C Vdd GND 302.9 +R Vdd 9192 +C GND GND 297.9 +R GND 13271 diff --git a/doc/tutcells/tut11b.ext b/doc/tutcells/tut11b.ext new file mode 100644 index 00000000..f01cd241 --- /dev/null +++ b/doc/tutcells/tut11b.ext @@ -0,0 +1,47 @@ +timestamp 552706284 +version 7.2 +tech scmos +style lambda=1.0(scna20_orb) +scale 1000 1 100 +resistclasses 26670 59550 23860 19690 27260 2000000 49 26 2505830 +use tut11d tut11d_0 1 0 0 0 1 0 +node "m2_n40_n60#" 0 0 -40 -60 m2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 162 66 0 0 +node "a_n34_n45#" 80 0 -34 -45 ndiff 12 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_n34_n41#" 329 10522 -34 -41 ndiff 24 36 0 0 16 16 0 0 0 0 0 0 164 98 88 52 0 0 +node "a_n18_n22#" 196 5362 -18 -22 pdiff 0 0 58 36 0 0 0 0 0 0 0 0 32 24 162 66 0 0 +node "a_n34_n52#" 464 3666 -34 -52 ndc 24 36 24 22 0 0 0 0 0 0 0 0 172 102 0 0 0 0 +node "a_n20_n60#" 716 6828 -20 -60 p 0 0 0 0 120 124 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_n36_n43#" 620 10974 -36 -43 p 0 0 0 0 112 112 0 0 0 0 0 0 20 18 72 44 0 0 +node "a_n40_n60#" 859 10176 -40 -60 p 0 0 0 0 144 148 0 0 0 0 0 0 0 0 0 0 0 0 +node "w_n40_n60#" 0 0 -40 -60 pw 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +cap "w_n40_n60#" "a_n34_n52#" 5452 +cap "a_n34_n45#" "a_n34_n52#" 282 +cap "a_n40_n60#" "a_n34_n52#" 120 +cap "w_n40_n60#" "a_n40_n60#" 6172 +cap "m2_n40_n60#" "a_n34_n52#" 1080 +cap "m2_n40_n60#" "w_n40_n60#" 2166 +cap "a_n34_n52#" "a_n34_n41#" 720 +cap "a_n40_n60#" "a_n18_n22#" 228 +cap "w_n40_n60#" "a_n34_n41#" 1658 +cap "m2_n40_n60#" "a_n40_n60#" 228 +cap "a_n36_n43#" "a_n20_n60#" 38 +cap "a_n18_n22#" "a_n34_n41#" 1080 +cap "a_n34_n52#" "a_n36_n43#" 876 +cap "w_n40_n60#" "a_n36_n43#" 3812 +cap "a_n18_n22#" "a_n36_n43#" 66 +cap "w_n40_n60#" "a_n20_n60#" 6664 +cap "a_n34_n41#" "a_n36_n43#" 152 +cap "a_n18_n22#" "a_n20_n60#" 228 +cap "m2_n40_n60#" "a_n20_n60#" 228 +cap "a_n34_n41#" "a_n20_n60#" 152 +device mosfet nfet -34 -47 -33 -46 2 6 "w_n40_n60#" "a_n40_n60#" 4 0 "a_n34_n52#" 6 0 "a_n34_n45#" 6 0 +device mosfet nfet -34 -43 -33 -42 2 6 "w_n40_n60#" "a_n36_n43#" 4 0 "a_n34_n45#" 6 0 "a_n34_n41#" 6 0 +device mosfet pfet -20 -22 -19 -21 2 6 "Vdd!" "a_n20_n60#" 4 0 "a_n34_n52#" 6 0 "a_n18_n22#" 6 0 +cap "m2_n40_n60#" "w_n40_n60#" -456 +cap "w_n40_n60#" "tut11d_0/a_n11_n54#" 395 +cap "a_n36_n43#" "a_n18_n22#" 264 +merge "tut11d_0/Vdd" "a_n18_n22#" -3652 0 0 -36 -26 0 0 0 0 0 0 0 0 -32 -24 -24 -20 0 0 +merge "tut11d_0/GND" "w_n40_n60#" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -72 -48 0 0 +merge "w_n40_n60#" "m2_n40_n60#" 0 +merge "tut11d_0/a_n11_n54#" "a_n34_n41#" -1035 0 0 0 0 0 -8 0 0 0 0 0 0 0 0 0 0 0 0 +merge "tut11d_0/B" "a_n36_n43#" -475 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -32 -32 0 0 diff --git a/doc/tutcells/tut11b.mag b/doc/tutcells/tut11b.mag new file mode 100644 index 00000000..59ed0855 --- /dev/null +++ b/doc/tutcells/tut11b.mag @@ -0,0 +1,70 @@ +magic +tech scmos +timestamp 552706284 +<< polysilicon >> +rect -40 -45 -38 0 +rect -30 -10 -27 -8 +rect -30 -28 -28 -10 +rect -20 -16 -18 0 +rect -30 -30 -25 -28 +rect -27 -41 -25 -30 +rect -36 -43 -34 -41 +rect -28 -43 -25 -41 +rect -40 -47 -34 -45 +rect -28 -47 -26 -45 +rect -40 -60 -38 -47 +rect -20 -60 -18 -22 +<< ndiffusion >> +rect -30 -40 -28 -39 +rect -34 -41 -28 -40 +rect -34 -45 -28 -43 +rect -34 -48 -28 -47 +rect -30 -49 -28 -48 +<< pdiffusion >> +rect -22 -18 -20 -16 +rect -21 -22 -20 -18 +rect -18 -18 -17 -16 +rect -18 -22 -13 -18 +<< metal1 >> +rect -34 -31 -30 0 +rect -27 -11 -23 -10 +rect -17 -9 -13 -5 +rect -34 -36 -30 -35 +rect -25 -44 -21 -22 +rect -16 -31 -12 -30 +rect -34 -48 -21 -44 +rect -34 -60 -30 -52 +<< metal2 >> +rect -40 -1 -13 0 +rect -40 -5 -17 -1 +rect -40 -6 -13 -5 +rect -27 -19 -23 -15 +rect -27 -23 -17 -19 +rect -30 -35 -16 -31 +rect -40 -60 -13 -54 +<< pwell >> +rect -40 -60 -12 -32 +<< polycontact >> +rect -27 -10 -23 -6 +rect -15 -30 -11 -26 +<< ndcontact >> +rect -34 -40 -30 -36 +rect -34 -52 -30 -48 +<< pdcontact >> +rect -25 -22 -21 -18 +rect -17 -18 -13 -9 +<< m2contact >> +rect -17 -5 -13 -1 +rect -27 -15 -23 -11 +rect -34 -35 -30 -31 +rect -16 -35 -12 -31 +<< ntransistor >> +rect -34 -43 -28 -41 +rect -34 -47 -28 -45 +<< ptransistor >> +rect -20 -22 -18 -16 +use tut11d tut11d_0 +timestamp 552706284 +transform 1 0 0 0 1 0 +box -17 -60 137 0 +<< end >> diff --git a/doc/tutcells/tut11c.ext b/doc/tutcells/tut11c.ext new file mode 100644 index 00000000..8cfa1533 --- /dev/null +++ b/doc/tutcells/tut11c.ext @@ -0,0 +1,44 @@ +timestamp 552706284 +version 7.2 +tech scmos +style lambda=1.0(scna20_orb) +scale 1000 1 100 +resistclasses 26670 59550 23860 19690 27260 2000000 49 26 2505830 +use tut11d tut11d_0 1 0 0 0 -1 -60 +node "m2_n40_n6#" 0 0 -40 -6 m2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 162 66 0 0 +node "a_n18_n44#" 196 5362 -18 -44 pdiff 0 0 58 36 0 0 0 0 0 0 0 0 32 24 162 66 0 0 +node "a_n20_n60#" 716 6828 -20 -60 p 0 0 0 0 120 124 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_n34_n24#" 464 8084 -34 -24 ndc 24 36 24 22 0 0 0 0 0 0 0 0 164 90 0 0 0 0 +node "a_n36_n19#" 620 10422 -36 -19 p 0 0 0 0 112 112 0 0 0 0 0 0 20 18 72 44 0 0 +node "a_n34_n17#" 80 0 -34 -17 ndiff 12 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_n34_n13#" 329 5079 -34 -13 ndiff 24 36 0 0 16 16 0 0 0 0 0 0 156 108 56 36 0 0 +node "a_n40_n60#" 859 10176 -40 -60 p 0 0 0 0 144 148 0 0 0 0 0 0 0 0 0 0 0 0 +node "w_n40_n28#" 0 0 -40 -28 pw 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +cap "w_n40_n28#" "a_n40_n60#" 6172 +cap "a_n40_n60#" "m2_n40_n6#" 228 +cap "a_n36_n19#" "a_n34_n13#" 210 +cap "w_n40_n28#" "a_n34_n13#" 6244 +cap "a_n34_n13#" "m2_n40_n6#" 1080 +cap "a_n36_n19#" "a_n18_n44#" 66 +cap "w_n40_n28#" "a_n36_n19#" 4288 +cap "w_n40_n28#" "m2_n40_n6#" 2166 +cap "a_n18_n44#" "a_n34_n24#" 1080 +cap "a_n34_n13#" "a_n20_n60#" 152 +cap "a_n36_n19#" "a_n34_n24#" 1296 +cap "w_n40_n28#" "a_n34_n24#" 752 +cap "a_n18_n44#" "a_n20_n60#" 228 +cap "a_n36_n19#" "a_n20_n60#" 38 +cap "w_n40_n28#" "a_n20_n60#" 6664 +cap "m2_n40_n6#" "a_n20_n60#" 228 +cap "a_n40_n60#" "a_n18_n44#" 228 +device mosfet pfet -20 -44 -19 -43 2 6 "Vdd!" "a_n20_n60#" 4 0 "a_n34_n24#" 6 0 "a_n18_n44#" 6 0 +device mosfet nfet -34 -19 -33 -18 2 6 "w_n40_n28#" "a_n36_n19#" 4 0 "a_n34_n24#" 6 0 "a_n34_n17#" 6 0 +device mosfet nfet -34 -15 -33 -14 2 6 "w_n40_n28#" "a_n40_n60#" 4 0 "a_n34_n17#" 6 0 "a_n34_n13#" 6 0 +cap "a_n18_n44#" "a_n36_n19#" 264 +cap "tut11d_0/a_n11_n54#" "w_n40_n28#" 536 +cap "m2_n40_n6#" "w_n40_n28#" -456 +merge "tut11d_0/Vdd" "a_n18_n44#" -3652 0 0 -36 -26 0 0 0 0 0 0 0 0 -32 -24 -24 -20 0 0 +merge "tut11d_0/B" "a_n36_n19#" -475 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -32 -32 0 0 +merge "tut11d_0/GND" "w_n40_n28#" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -72 -48 0 0 +merge "w_n40_n28#" "m2_n40_n6#" 0 +merge "tut11d_0/a_n11_n54#" "a_n34_n13#" -1176 0 0 0 0 0 -8 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/doc/tutcells/tut11c.mag b/doc/tutcells/tut11c.mag new file mode 100644 index 00000000..fb054741 --- /dev/null +++ b/doc/tutcells/tut11c.mag @@ -0,0 +1,74 @@ +magic +tech scmos +timestamp 552706284 +<< polysilicon >> +rect -40 -13 -38 0 +rect -40 -15 -34 -13 +rect -28 -15 -26 -13 +rect -40 -60 -38 -15 +rect -36 -19 -34 -17 +rect -28 -19 -25 -17 +rect -27 -22 -25 -19 +rect -29 -24 -25 -22 +rect -29 -30 -27 -24 +rect -30 -32 -27 -30 +rect -30 -50 -28 -32 +rect -20 -38 -18 0 +rect -30 -52 -27 -50 +rect -20 -60 -18 -44 +<< ndiffusion >> +rect -30 -12 -28 -11 +rect -34 -13 -28 -12 +rect -34 -17 -28 -15 +rect -34 -20 -28 -19 +rect -30 -21 -28 -20 +<< pdiffusion >> +rect -21 -42 -20 -38 +rect -22 -44 -20 -42 +rect -18 -42 -13 -38 +rect -18 -44 -17 -42 +<< metal1 >> +rect -34 -8 -30 0 +rect -30 -12 -22 -8 +rect -34 -38 -30 -24 +rect -26 -25 -22 -12 +rect -16 -30 -12 -29 +rect -16 -34 -15 -30 +rect -34 -42 -25 -38 +rect -34 -60 -30 -42 +rect -27 -50 -23 -49 +rect -17 -55 -13 -51 +<< metal2 >> +rect -40 -6 -13 0 +rect -22 -29 -16 -25 +rect -27 -41 -17 -37 +rect -27 -45 -23 -41 +rect -40 -55 -13 -54 +rect -40 -59 -17 -55 +rect -40 -60 -13 -59 +<< pwell >> +rect -40 -28 -13 0 +<< polycontact >> +rect -15 -34 -11 -30 +rect -27 -54 -23 -50 +<< ndcontact >> +rect -34 -12 -30 -8 +rect -34 -24 -30 -20 +<< pdcontact >> +rect -25 -42 -21 -38 +rect -17 -51 -13 -42 +<< m2contact >> +rect -26 -29 -22 -25 +rect -16 -29 -12 -25 +rect -27 -49 -23 -45 +rect -17 -59 -13 -55 +<< ntransistor >> +rect -34 -15 -28 -13 +rect -34 -19 -28 -17 +<< ptransistor >> +rect -20 -44 -18 -38 +use tut11d tut11d_0 +timestamp 552706284 +transform 1 0 0 0 -1 -60 +box -17 -60 137 0 +<< end >> diff --git a/doc/tutcells/tut11d.ext b/doc/tutcells/tut11d.ext new file mode 100644 index 00000000..db87c364 --- /dev/null +++ b/doc/tutcells/tut11d.ext @@ -0,0 +1,101 @@ +timestamp 552706284 +version 7.2 +tech scmos +style lambda=1.0(scna20_orb) +scale 1000 1 100 +resistclasses 26670 59550 23860 19690 27260 2000000 49 26 2505830 +node "phi2_b" 859 9684 99 -20 p 0 0 0 0 144 148 0 0 0 0 0 0 0 0 0 0 0 0 +equiv "phi2_b" "phi2_b" +node "a_101_n47#" 820 11470 101 -47 ndc 30 34 30 22 100 100 0 0 0 0 0 0 176 120 0 0 0 0 +node "phi2" 859 7936 95 -60 p 0 0 0 0 144 148 0 0 0 0 0 0 0 0 0 0 0 0 +equiv "phi2" "phi2" +node "a_77_n44#" 80 0 77 -44 ndiff 12 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_77_n40#" 1150 11092 77 -40 ndiff 60 68 117 80 0 0 0 0 0 0 0 0 176 108 0 0 0 0 +node "reset_b" 859 7066 75 -46 p 0 0 0 0 144 148 0 0 0 0 0 0 0 0 0 0 0 0 +equiv "reset_b" "reset_b" +node "phi1_b" 859 9684 53 -18 p 0 0 0 0 144 148 0 0 0 0 0 0 0 0 0 0 0 0 +equiv "phi1_b" "phi1_b" +node "a_55_n47#" 773 11298 55 -47 ndc 30 34 30 22 100 96 0 0 0 0 0 0 176 96 0 0 0 0 +node "phi1" 859 7698 49 -42 p 0 0 0 0 144 148 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_39_n39#" 80 0 39 -39 ndiff 12 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_26_n39#" 53 0 26 -39 ndiff 18 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_39_n23#" 179 0 39 -23 pdiff 0 0 12 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +node "a_31_n39#" 973 9635 31 -39 ndiff 66 82 66 46 0 0 0 0 0 0 0 0 169 96 0 0 0 0 +node "a_26_n23#" 119 0 26 -23 pdiff 0 0 18 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +node "A" 1107 6996 0 -52 ndiff 30 34 25 20 150 150 0 0 0 0 0 0 81 74 0 0 0 0 +node "B_b" 713 12278 11 -39 ndc 30 34 30 22 86 84 0 0 0 0 0 0 186 130 0 0 0 0 +node "A_b" 1537 14566 -16 -52 ndc 30 34 30 22 220 220 0 0 0 0 0 0 116 98 0 0 0 0 +node "a_n11_n54#" 561 4606 -11 -54 p 0 0 0 0 94 98 0 0 0 0 0 0 0 0 0 0 0 0 +node "B" 1655 32895 13 -14 pc 60 58 60 34 212 210 0 0 0 0 0 0 140 62 648 332 0 0 +equiv "B" "Q_out" +node "Vdd" 2107 59727 -17 -18 pdc 120 116 255 162 0 0 0 0 0 0 0 0 650 374 924 320 0 0 +node "GND" 3185 57314 -17 -60 pw 198 224 112 112 0 0 0 0 0 0 0 0 650 396 924 320 0 0 +cap "B_b" "a_26_n23#" 846 +cap "phi2_b" "B" 152 +cap "phi1" "Vdd" 316 +cap "a_55_n47#" "GND" 5868 +cap "A_b" "B_b" 180 +cap "a_31_n39#" "phi1" 180 +cap "a_31_n39#" "B_b" 60 +cap "B" "a_n11_n54#" 152 +cap "phi2_b" "a_101_n47#" 480 +cap "phi2_b" "GND" 6980 +cap "a_26_n39#" "B_b" 846 +cap "phi2" "B" 152 +cap "A" "B" 1080 +cap "reset_b" "B" 152 +cap "phi2_b" "Vdd" 316 +cap "a_101_n47#" "B" 720 +cap "GND" "B" 5114 +cap "a_77_n40#" "B" 2160 +cap "Vdd" "B" 2150 +cap "GND" "a_n11_n54#" 4684 +cap "A_b" "B" 692 +cap "phi1_b" "GND" 6980 +cap "a_31_n39#" "B" 2516 +cap "phi2" "GND" 8728 +cap "GND" "A" 15163 +cap "phi1" "B" 152 +cap "B_b" "B" 1618 +cap "A_b" "a_n11_n54#" 180 +cap "phi2" "a_77_n40#" 240 +cap "phi1_b" "Vdd" 316 +cap "reset_b" "GND" 8728 +cap "a_39_n23#" "B" 176 +cap "phi2" "Vdd" 316 +cap "a_101_n47#" "GND" 6638 +cap "reset_b" "a_77_n40#" 240 +cap "a_55_n47#" "B" 3167 +cap "a_77_n40#" "GND" 1692 +cap "reset_b" "Vdd" 316 +cap "A_b" "A" 180 +cap "a_31_n39#" "A" 180 +cap "A_b" "GND" 15778 +cap "a_31_n39#" "GND" 1316 +cap "a_55_n47#" "phi1_b" 2220 +cap "phi1" "GND" 8966 +cap "B_b" "GND" 5826 +device mosfet nfet 123 -42 124 -41 2 12 "GND" "a_101_n47#" 4 0 "GND" 12 0 "B" 12 0 +device mosfet pfet 123 -20 124 -19 2 12 "Vdd!" "a_101_n47#" 4 0 "B" 12 0 "Vdd" 12 0 +device mosfet nfet 101 -42 102 -41 2 6 "GND" "phi2" 4 0 "a_101_n47#" 6 0 "a_77_n40#" 6 0 +device mosfet pfet 101 -20 102 -19 2 6 "Vdd!" "phi2_b" 4 0 "a_77_n40#" 6 0 "a_101_n47#" 6 0 +device mosfet nfet 77 -46 78 -45 2 6 "GND" "reset_b" 4 0 "GND" 6 0 "a_77_n44#" 6 0 +device mosfet nfet 77 -42 78 -41 2 6 "GND" "a_55_n47#" 4 0 "a_77_n44#" 6 0 "a_77_n40#" 6 0 +device mosfet pfet 77 -20 78 -19 2 6 "Vdd!" "a_55_n47#" 4 0 "a_77_n40#" 6 0 "Vdd" 6 0 +device mosfet nfet 55 -42 56 -41 2 6 "GND" "phi1" 4 0 "a_55_n47#" 6 0 "a_31_n39#" 6 0 +device mosfet pfet 87 -17 88 -16 2 5 "Vdd!" "reset_b" 4 0 "Vdd" 5 0 "a_77_n40#" 5 0 +device mosfet pfet 55 -18 56 -17 2 6 "Vdd!" "phi1_b" 4 0 "a_31_n39#" 6 0 "a_55_n47#" 6 0 +device mosfet nfet -2 -52 -1 -51 2 6 "GND" "A_b" 4 0 "GND" 6 0 "A" 6 0 +device mosfet nfet -11 -52 -10 -51 2 6 "GND" "a_n11_n54#" 4 0 "A_b" 6 0 "GND" 6 0 +device mosfet nfet 41 -39 42 -38 2 6 "GND" "A" 4 0 "a_39_n39#" 6 0 "GND" 6 0 +device mosfet nfet 37 -39 38 -38 2 6 "GND" "B_b" 4 0 "a_31_n39#" 6 0 "a_39_n39#" 6 0 +device mosfet nfet 29 -39 30 -38 2 6 "GND" "B" 4 0 "a_26_n39#" 6 0 "a_31_n39#" 6 0 +device mosfet nfet 24 -39 25 -38 2 6 "GND" "A_b" 4 0 "GND" 6 0 "a_26_n39#" 6 0 +device mosfet nfet 16 -39 17 -38 2 6 "GND" "B" 4 0 "B_b" 6 0 "GND" 6 0 +device mosfet pfet 41 -23 42 -22 2 6 "Vdd!" "A" 4 0 "a_39_n23#" 6 0 "Vdd" 6 0 +device mosfet pfet 37 -23 38 -22 2 6 "Vdd!" "B" 4 0 "a_31_n39#" 6 0 "a_39_n23#" 6 0 +device mosfet pfet 29 -23 30 -22 2 6 "Vdd!" "B_b" 4 0 "a_26_n23#" 6 0 "a_31_n39#" 6 0 +device mosfet pfet 24 -23 25 -22 2 6 "Vdd!" "A_b" 4 0 "Vdd" 6 0 "a_26_n23#" 6 0 +device mosfet pfet 16 -23 17 -22 2 6 "Vdd!" "B" 4 0 "B_b" 6 0 "Vdd" 6 0 +device mosfet pfet 0 -18 1 -17 2 5 "Vdd!" "A_b" 4 0 "A" 5 0 "Vdd" 5 0 +device mosfet pfet -11 -15 -10 -14 2 6 "Vdd!" "a_n11_n54#" 4 0 "Vdd" 6 0 "A_b" 6 0 diff --git a/doc/tutcells/tut11d.mag b/doc/tutcells/tut11d.mag new file mode 100644 index 00000000..bd1f9303 --- /dev/null +++ b/doc/tutcells/tut11d.mag @@ -0,0 +1,327 @@ +magic +tech scmos +timestamp 552706284 +<< polysilicon >> +rect 24 -7 38 -5 +rect -11 -9 -9 -7 +rect 24 -8 26 -7 +rect 16 -10 26 -8 +rect 17 -14 18 -10 +rect -11 -46 -9 -15 +rect -4 -18 0 -16 +rect 5 -18 8 -16 +rect 16 -17 18 -14 +rect 24 -17 26 -13 +rect 36 -13 38 -7 +rect 29 -17 31 -14 +rect 36 -15 39 -13 +rect 37 -17 39 -15 +rect 41 -17 43 -15 +rect -4 -26 -2 -18 +rect -4 -43 -2 -30 +rect 16 -33 18 -23 +rect 24 -33 26 -23 +rect 29 -26 31 -23 +rect 37 -24 39 -23 +rect 33 -26 39 -24 +rect 33 -29 35 -26 +rect 29 -31 35 -29 +rect 29 -33 31 -31 +rect 37 -33 39 -29 +rect 41 -33 43 -23 +rect 16 -41 18 -39 +rect 24 -43 26 -39 +rect 29 -42 31 -39 +rect 37 -42 39 -39 +rect -4 -45 26 -43 +rect -2 -46 0 -45 +rect 38 -46 39 -42 +rect 41 -50 43 -39 +rect 49 -40 51 0 +rect 65 -16 67 0 +rect 87 -12 89 0 +rect 53 -18 55 -16 +rect 61 -18 67 -16 +rect 49 -42 55 -40 +rect 61 -42 63 -40 +rect 11 -52 43 -50 +rect -11 -54 -9 -52 +rect -2 -54 0 -52 +rect 52 -60 54 -42 +rect 65 -60 67 -18 +rect 74 -20 77 -18 +rect 83 -20 85 -18 +rect 74 -40 76 -20 +rect 74 -42 77 -40 +rect 83 -42 85 -40 +rect 87 -44 89 -17 +rect 75 -46 77 -44 +rect 83 -46 89 -44 +rect 87 -60 89 -46 +rect 95 -40 97 0 +rect 111 -18 113 0 +rect 99 -20 101 -18 +rect 107 -20 113 -18 +rect 95 -42 101 -40 +rect 107 -42 109 -40 +rect 95 -60 97 -42 +rect 111 -60 113 -20 +rect 120 -20 123 -18 +rect 135 -20 137 -18 +rect 120 -42 123 -40 +rect 135 -42 137 -40 +<< ndiffusion >> +rect 15 -39 16 -33 +rect 18 -39 19 -33 +rect 23 -39 24 -33 +rect 26 -39 29 -33 +rect 31 -39 32 -33 +rect 36 -39 37 -33 +rect 39 -39 41 -33 +rect 43 -39 44 -33 +rect -12 -52 -11 -46 +rect -9 -52 -8 -46 +rect -4 -52 -2 -46 +rect 0 -52 1 -46 +rect 55 -40 61 -39 +rect 55 -43 61 -42 +rect 77 -40 83 -39 +rect 77 -44 83 -42 +rect 77 -47 83 -46 +rect 101 -40 107 -39 +rect 101 -43 107 -42 +rect 123 -40 135 -39 +rect 123 -43 135 -42 +<< pdiffusion >> +rect -13 -15 -11 -9 +rect -9 -15 -8 -9 +rect 0 -16 5 -15 +rect 0 -19 5 -18 +rect 15 -23 16 -17 +rect 18 -23 19 -17 +rect 23 -23 24 -17 +rect 26 -23 29 -17 +rect 31 -23 32 -17 +rect 36 -23 37 -17 +rect 39 -23 41 -17 +rect 43 -23 44 -17 +rect 55 -16 61 -15 +rect 84 -17 87 -12 +rect 89 -17 94 -12 +rect 77 -18 83 -17 +rect 55 -19 61 -18 +rect 77 -21 83 -20 +rect 90 -21 94 -17 +rect 101 -18 107 -17 +rect 101 -21 107 -20 +rect 123 -18 135 -17 +rect 123 -21 135 -20 +<< metal1 >> +rect -17 -9 -13 -5 +rect 2 -5 3 -1 +rect 7 -5 8 -1 +rect -9 -15 -8 -9 +rect 2 -11 5 -5 +rect 12 -14 13 -10 +rect -8 -26 -5 -15 +rect 20 -17 23 -1 +rect 44 -5 55 -1 +rect 61 -5 72 -1 +rect 76 -5 77 -1 +rect -1 -23 0 -19 +rect -8 -30 -6 -26 +rect -8 -40 -5 -30 +rect -15 -43 -5 -40 +rect -15 -46 -12 -43 +rect 1 -46 4 -23 +rect 12 -26 15 -23 +rect 26 -26 29 -10 +rect 44 -17 48 -5 +rect 83 -5 90 -1 +rect 94 -5 102 -1 +rect 106 -5 114 -1 +rect 118 -5 123 -1 +rect 61 -15 68 -11 +rect 12 -29 29 -26 +rect 12 -33 15 -29 +rect -9 -52 -8 -46 +rect 5 -52 7 -48 +rect -8 -55 -4 -52 +rect 20 -55 23 -39 +rect 26 -43 29 -29 +rect 32 -27 36 -23 +rect 55 -27 61 -23 +rect 32 -30 61 -27 +rect 32 -33 36 -30 +rect 55 -35 61 -30 +rect 64 -28 68 -15 +rect 77 -12 83 -6 +rect 135 -5 137 -1 +rect 123 -13 135 -6 +rect 107 -17 119 -13 +rect 135 -17 137 -13 +rect 115 -21 116 -17 +rect 83 -25 90 -21 +rect 94 -25 101 -21 +rect 64 -32 70 -28 +rect 26 -46 34 -43 +rect 45 -55 48 -39 +rect 64 -43 68 -32 +rect 77 -35 83 -25 +rect 101 -35 107 -25 +rect 115 -39 119 -21 +rect 123 -28 135 -25 +rect 127 -32 135 -28 +rect 123 -35 135 -32 +rect 115 -43 116 -39 +rect 61 -47 68 -43 +rect 107 -47 119 -43 +rect 135 -47 137 -43 +rect 77 -55 83 -51 +rect 123 -54 135 -47 +rect 20 -59 21 -55 +rect 25 -59 27 -55 +rect 38 -59 40 -55 +rect 44 -59 56 -55 +rect 60 -59 78 -55 +rect 82 -59 90 -55 +rect 94 -59 102 -55 +rect 106 -59 114 -55 +rect 118 -59 123 -55 +rect 135 -59 137 -55 +<< metal2 >> +rect -17 -1 77 0 +rect -13 -5 8 -1 +rect 20 -5 77 -1 +rect -17 -6 77 -5 +rect 83 -6 123 0 +rect 135 -6 137 0 +rect 8 -19 12 -14 +rect -17 -23 69 -19 +rect 65 -28 69 -23 +rect 65 -32 123 -28 +rect -17 -55 90 -54 +rect -17 -59 -8 -55 +rect -4 -59 27 -55 +rect 38 -59 90 -55 +rect -17 -60 90 -59 +rect 94 -60 123 -54 +rect 135 -60 137 -54 +<< pwell >> +rect -17 -31 -9 -30 +rect -17 -32 57 -31 +rect -17 -60 137 -32 +<< polycontact >> +rect 13 -14 17 -10 +rect 29 -14 33 -10 +rect -6 -30 -2 -26 +rect 34 -46 38 -42 +rect 7 -52 11 -48 +rect 70 -32 74 -28 +rect 116 -21 120 -17 +rect 116 -43 120 -39 +<< ndcontact >> +rect 11 -39 15 -33 +rect 19 -39 23 -33 +rect 32 -39 36 -33 +rect 44 -39 48 -33 +rect -16 -52 -12 -46 +rect -8 -52 -4 -46 +rect 1 -52 5 -46 +rect 55 -39 61 -35 +rect 55 -47 61 -43 +rect 77 -39 83 -35 +rect 77 -51 83 -47 +rect 101 -39 107 -35 +rect 101 -47 107 -43 +rect 123 -39 135 -35 +rect 123 -47 135 -43 +<< pdcontact >> +rect -17 -18 -13 -9 +rect -8 -15 -4 -9 +rect 0 -15 5 -11 +rect 0 -23 5 -19 +rect 11 -23 15 -17 +rect 19 -23 23 -17 +rect 32 -23 36 -17 +rect 44 -23 48 -17 +rect 55 -15 61 -11 +rect 77 -17 84 -12 +rect 55 -23 61 -19 +rect 77 -25 83 -21 +rect 90 -25 94 -21 +rect 101 -17 107 -13 +rect 123 -17 135 -13 +rect 101 -25 107 -21 +rect 123 -25 135 -21 +<< m2contact >> +rect -17 -5 -13 -1 +rect 8 -5 20 -1 +rect 8 -14 12 -10 +rect 77 -6 83 0 +rect 123 -6 135 0 +rect 123 -32 127 -28 +rect -8 -59 -4 -55 +rect 27 -59 38 -55 +rect 90 -60 94 -54 +rect 123 -60 135 -54 +<< ntransistor >> +rect 16 -39 18 -33 +rect 24 -39 26 -33 +rect 29 -39 31 -33 +rect 37 -39 39 -33 +rect 41 -39 43 -33 +rect -11 -52 -9 -46 +rect -2 -52 0 -46 +rect 55 -42 61 -40 +rect 77 -42 83 -40 +rect 77 -46 83 -44 +rect 101 -42 107 -40 +rect 123 -42 135 -40 +<< ptransistor >> +rect -11 -15 -9 -9 +rect 0 -18 5 -16 +rect 16 -23 18 -17 +rect 24 -23 26 -17 +rect 29 -23 31 -17 +rect 37 -23 39 -17 +rect 41 -23 43 -17 +rect 55 -18 61 -16 +rect 87 -17 89 -12 +rect 77 -20 83 -18 +rect 101 -20 107 -18 +rect 123 -20 135 -18 +<< psubstratepcontact >> +rect 10 -59 14 -55 +rect 21 -59 25 -55 +rect 40 -59 44 -55 +rect 56 -59 60 -55 +rect 78 -59 82 -55 +rect 102 -59 106 -55 +rect 114 -59 118 -55 +<< nsubstratencontact >> +rect 3 -5 7 -1 +rect 40 -5 44 -1 +rect 55 -5 61 -1 +rect 72 -5 76 -1 +rect 90 -5 94 -1 +rect 102 -5 106 -1 +rect 114 -5 118 -1 +<< labels >> +rlabel metal1 129 -30 129 -30 1 Q_out +rlabel polysilicon 112 -53 112 -53 1 phi2_b +rlabel polysilicon 96 -52 96 -52 3 phi2 +rlabel polysilicon 88 -52 88 -52 7 reset_b +rlabel polysilicon 66 -53 66 -53 1 phi1_b +rlabel polysilicon 50 -9 50 -9 1 phi1 +rlabel polysilicon 66 -9 66 -9 1 phi1_b +rlabel polysilicon 88 -10 88 -10 1 reset_b +rlabel polysilicon 96 -10 96 -10 1 phi2 +rlabel polysilicon 112 -10 112 -10 1 phi2_b +rlabel metal2 1 -57 1 -57 3 GND +rlabel metal2 1 -3 1 -3 3 Vdd +rlabel polysilicon 38 -41 38 -41 1 B_b +rlabel polysilicon 42 -41 42 -41 1 A +rlabel polysilicon 30 -41 30 -41 1 B +rlabel polysilicon 25 -41 25 -41 1 A_b +<< end >> diff --git a/doc/tutcells/tut2.f1a.cif b/doc/tutcells/tut2.f1a.cif new file mode 100644 index 00000000..18f3a6b7 --- /dev/null +++ b/doc/tutcells/tut2.f1a.cif @@ -0,0 +1,34 @@ +DS 1 200 4; +9 shiftcell; +L NP; B 40 8 20 24; + B 16 8 76 24; + B 8 100 52 50; + B 24 36 20 62; + B 20 16 150 196; + B 20 16 -82 -84; +L ND; B 16 12 20 6; + B 24 20 20 22; + B 68 8 42 36; + B 8 12 72 26; + B 16 16 20 92; + B 8 44 20 62; +L NM; B 84 16 42 8; + B 84 16 42 92; +L NI; B 16 52 20 62; +L NB; B 16 20 20 46; + B 16 20 72 26; +L NC; B 8 8 20 8; + B 8 8 20 92; +2A "In" T 4 24; +0V 4 24 4 24 4 24 4 24 4 24; +2A "Vdd" T 4 92; +0V 4 92 4 92 4 92 4 92 4 92; +2A "GND" T 4 8; +0V 4 8 4 8 4 8 4 8 4 8; +2A "Phi" T 52 68; +0V 52 68 52 68 52 68 52 68 52 68; +2A "Out" T 80 24; +0V 80 24 80 24 80 24 80 24 80 24; +DF; +C 1; +End diff --git a/doc/tutcells/tut2.f1b.cif b/doc/tutcells/tut2.f1b.cif new file mode 100644 index 00000000..35fb68f8 --- /dev/null +++ b/doc/tutcells/tut2.f1b.cif @@ -0,0 +1,66 @@ +DS 1 200 4; +9 f4b; +L NP; B 40 8 20 24; + B 8 100 52 50; + B 8 12 28 50; + B 8 12 12 50; + B 24 24 20 68; + B 8 8 80 24; + B 8 8 100 98; + B 8 8 100 50; + B 8 8 100 34; +L ND; B 68 8 42 36; + B 4 4 30 14; + B 4 4 10 14; + B 24 16 20 24; + B 8 4 20 42; + B 8 4 72 30; + B 8 28 20 70; + B 8 8 100 66; + B 8 8 100 50; + B 8 8 100 34; +L NM; B 56 16 56 8; + B 12 16 6 8; + B 56 16 56 92; + B 12 16 6 92; + B 8 8 -56 148; + B 8 8 252 -56; + B 8 8 100 82; +L NI; B 8 24 20 68; + B 8 8 100 34; +L NB; B 8 12 20 50; + B 8 8 72 24; + B 8 8 100 18; +0V 12 0 12 16 28 16 28 0 12 0 28 16; +0V 28 0 12 16; +0V 12 84 12 100 28 100 28 84 12 84 28 100; +0V 28 84 12 100; +0V 96 -2 96 6 104 6 104 -2 96 -2 104 6; +0V 96 6 104 -2; +2A "In" T 4 24; +0V 4 24 4 24 4 24 4 24 4 24; +2A "Vdd" T 4 92; +0V 4 92 4 92 4 92 4 92 4 92; +2A "GND" T 4 8; +0V 4 8 4 8 4 8 4 8 4 8; +2A "Phi" T 52 68; +0V 52 68 52 68 52 68 52 68 52 68; +2A "Out" T 80 24; +0V 80 24 80 24 80 24 80 24 80 24; +2L "Depletion-FET" T 108 32; +0V 108 32 108 32 108 32 108 32 108 32; +2L "Enhancement-FET" T 108 48; +0V 108 48 108 48 108 48 108 48 108 48; +2L "Diffusion" T 108 64; +0V 108 64 108 64 108 64 108 64 108 64; +2L "Metal" T 108 80; +0V 108 80 108 80 108 80 108 80 108 80; +2L "Polysilicon" T 108 96; +0V 108 96 108 96 108 96 108 96 108 96; +2L "Diff-Metal-Contact" T 108 0; +0V 108 0 108 0 108 0 108 0 108 0; +2L "Buried-Contact" T 108 16; +0V 108 16 108 16 108 16 108 16 108 16; +DF; +C 1; +End diff --git a/doc/tutcells/tut2a.mag b/doc/tutcells/tut2a.mag new file mode 100644 index 00000000..693c26d1 --- /dev/null +++ b/doc/tutcells/tut2a.mag @@ -0,0 +1,20 @@ +magic +tech scmos +timestamp 500615676 +<< polysilicon >> +rect -33 3 -29 7 +<< ndiffusion >> +rect -40 3 -36 7 +<< pdiffusion >> +rect -12 3 -8 7 +<< metal2 >> +rect -19 3 -15 7 +<< polycontact >> +rect -26 3 -22 7 +<< labels >> +rlabel ndiffusion -38 3 -38 3 5 ndiff +rlabel polysilicon -31 3 -31 3 5 poly +rlabel polycontact -24 3 -24 3 5 pcontact +rlabel metal2 -17 3 -17 3 5 metal2 +rlabel pdiffusion -10 3 -10 3 5 pdiff +<< end >> diff --git a/doc/tutcells/tut2b.mag b/doc/tutcells/tut2b.mag new file mode 100644 index 00000000..cded43fd --- /dev/null +++ b/doc/tutcells/tut2b.mag @@ -0,0 +1,17 @@ +magic +tech scmos +timestamp 500615676 +<< polysilicon >> +rect -7 3 1 5 +rect -1 -5 1 3 +rect 10 -5 12 14 +<< ndiffusion >> +rect -3 -21 -1 -13 +rect -19 -23 -1 -21 +rect -19 -33 -17 -23 +<< metal1 >> +rect -18 7 -15 14 +rect -18 4 -12 7 +<< polycontact >> +rect -12 3 -7 7 +<< end >> diff --git a/doc/tutcells/tut2c.mag b/doc/tutcells/tut2c.mag new file mode 100644 index 00000000..5d2b1f97 --- /dev/null +++ b/doc/tutcells/tut2c.mag @@ -0,0 +1,15 @@ +magic +tech scmos +timestamp 500615676 +<< polysilicon >> +rect -17 7 0 13 +<< pdiffusion >> +rect 5 -15 13 -4 +<< metal1 >> +rect -18 -18 -5 -10 +<< labels >> +rlabel polysilicon -15 10 -15 10 3 Label1 +rlabel metal1 -17 -14 -17 -14 3 Metal1 label +rlabel pdiffusion 13 -13 13 -7 7 Line label +rlabel space 4 2 25 22 1 Rectangular label +<< end >> diff --git a/doc/tutcells/tut2d.mag b/doc/tutcells/tut2d.mag new file mode 100644 index 00000000..d89fb55c --- /dev/null +++ b/doc/tutcells/tut2d.mag @@ -0,0 +1,28 @@ +magic +tech scmos +timestamp 500615676 +<< polysilicon >> +rect 4 2 6 10 +rect 4 -5 6 -1 +rect 4 -15 6 -8 +<< ndiffusion >> +rect -5 -1 4 2 +rect 6 -1 8 2 +rect -5 -8 4 -5 +rect 6 -8 8 -5 +<< metal1 >> +rect -7 11 2 14 +rect 7 11 30 14 +<< polycontact >> +rect 2 10 7 14 +<< ntransistor >> +rect 4 -1 6 2 +rect 4 -8 6 -5 +<< labels >> +rlabel metal1 24 12 24 12 1 Local node name +rlabel ndiffusion -3 -6 -3 -6 1 Global name! +rlabel ndiffusion -3 1 -3 1 1 Node Attribute@ +rlabel ntransistor 6 1 6 1 3 Source/Drain Attribute$ +rlabel ntransistor 5 -6 5 -6 3 Gate Attribute^ +rlabel metal1 -7 11 -7 14 7 Label for routing +<< end >> diff --git a/doc/tutcells/tut3a.mag b/doc/tutcells/tut3a.mag new file mode 100644 index 00000000..3a076695 --- /dev/null +++ b/doc/tutcells/tut3a.mag @@ -0,0 +1,21 @@ +magic +tech scmos +timestamp 500617727 +<< polysilicon >> +rect -12 6 12 8 +<< metal1 >> +rect -12 0 29 3 +<< metal2 >> +rect -12 -6 -2 -3 +<< labels >> +rlabel polysilicon 11 7 11 7 7 1 +rlabel space 11 21 11 21 1 2 +rlabel metal1 28 1 28 1 7 5 +rlabel space 28 -13 28 -13 5 6 +rlabel metal2 -3 -5 -3 -5 7 8 +rlabel space 15 -9 15 -9 5 9 +rlabel space 5 -21 5 -21 5 10 +rlabel space 35 20 35 20 3 3 +rlabel space 34 35 34 35 1 4 +rlabel space 47 -12 47 -12 3 7 +<< end >> diff --git a/doc/tutcells/tut3b.mag b/doc/tutcells/tut3b.mag new file mode 100644 index 00000000..41f48d35 --- /dev/null +++ b/doc/tutcells/tut3b.mag @@ -0,0 +1,15 @@ +magic +tech scmos +timestamp 616379430 +<< polysilicon >> +rect -16 19 16 21 +<< ndiffusion >> +rect -16 28 16 31 +rect -16 22 16 25 +<< metal1 >> +rect -16 32 16 35 +rect -16 13 16 16 +<< labels >> +rlabel space -32 12 -14 36 1 Fill here +rlabel space 14 12 52 36 1 Corner here +<< end >> diff --git a/doc/tutcells/tut3c.mag b/doc/tutcells/tut3c.mag new file mode 100644 index 00000000..b643d72b --- /dev/null +++ b/doc/tutcells/tut3c.mag @@ -0,0 +1,21 @@ +magic +tech scmos +timestamp 500617727 +<< metal1 >> +rect -20 64 18 67 +rect -20 56 18 59 +rect -20 48 18 51 +rect -20 40 18 43 +rect -20 32 18 35 +rect -20 24 18 27 +rect -20 16 18 19 +rect -20 8 18 11 +rect -20 0 18 3 +rect -20 -8 18 -5 +<< metal2 >> +rect 22 -8 24 -5 +<< m2contact >> +rect 18 -8 22 -4 +<< labels >> +rlabel space 18 0 20 8 5 Array +<< end >> diff --git a/doc/tutcells/tut3d.mag b/doc/tutcells/tut3d.mag new file mode 100644 index 00000000..f12d10cc --- /dev/null +++ b/doc/tutcells/tut3d.mag @@ -0,0 +1,410 @@ +magic +tech scmos +timestamp 616380303 +<< polysilicon >> +rect 338 168 340 171 +rect 344 165 346 167 +rect 391 168 393 171 +rect 385 165 387 167 +rect 338 158 340 160 +rect 357 156 359 160 +rect 372 156 374 160 +rect 391 158 393 160 +rect 357 154 374 156 +rect 357 153 359 154 +rect 344 151 354 153 +rect 344 146 346 151 +rect 358 151 359 153 +rect 344 140 346 143 +rect 343 121 346 123 +rect 349 121 351 123 +rect 343 116 345 121 +rect 365 114 367 154 +rect 372 153 374 154 +rect 372 151 373 153 +rect 377 151 387 153 +rect 385 146 387 151 +rect 385 140 387 143 +rect 380 121 382 123 +rect 385 121 388 123 +rect 386 116 388 121 +rect 345 112 386 114 +rect 340 103 342 111 +rect 358 102 360 105 +rect 371 102 373 105 +rect 389 103 391 111 +rect 351 96 353 98 +rect 377 96 379 98 +rect 358 92 360 93 +rect 371 92 373 93 +rect 358 86 360 87 +rect 371 86 373 87 +rect 351 83 353 85 +rect 377 83 379 85 +rect 339 69 341 78 +rect 358 73 360 78 +rect 371 73 373 78 +rect 389 69 391 78 +rect 342 59 344 64 +rect 387 59 389 64 +rect 342 57 346 59 +rect 349 57 351 59 +rect 380 57 382 59 +rect 385 57 389 59 +rect 344 37 346 39 +rect 385 37 387 39 +rect 344 29 346 34 +rect 344 27 354 29 +rect 338 20 340 22 +rect 356 21 358 27 +rect 372 27 373 29 +rect 385 29 387 34 +rect 377 27 387 29 +rect 372 21 374 27 +rect 391 21 393 23 +rect 344 14 346 16 +rect 338 11 340 13 +rect 385 14 387 16 +rect 391 11 393 13 +<< ndiffusion >> +rect 335 165 338 168 +rect 336 161 338 165 +rect 335 160 338 161 +rect 340 164 343 168 +rect 346 167 361 170 +rect 359 165 361 167 +rect 371 167 385 170 +rect 371 165 372 167 +rect 346 164 357 165 +rect 340 160 346 164 +rect 350 160 357 164 +rect 359 160 372 165 +rect 374 164 385 165 +rect 388 164 391 168 +rect 374 160 381 164 +rect 385 160 391 164 +rect 393 160 396 168 +rect 331 96 340 103 +rect 342 99 349 103 +rect 353 99 358 102 +rect 342 98 351 99 +rect 331 92 351 96 +rect 355 93 358 99 +rect 360 98 363 102 +rect 368 98 371 102 +rect 360 93 371 98 +rect 373 99 377 102 +rect 381 99 389 103 +rect 373 93 376 99 +rect 379 98 389 99 +rect 391 99 397 103 +rect 391 96 392 99 +rect 379 95 392 96 +rect 336 87 351 92 +rect 331 85 351 87 +rect 379 86 394 95 +rect 331 78 339 85 +rect 341 82 351 83 +rect 355 82 358 86 +rect 341 78 350 82 +rect 354 78 358 82 +rect 360 82 371 86 +rect 360 78 363 82 +rect 368 78 371 82 +rect 373 82 376 86 +rect 379 85 392 86 +rect 379 82 389 83 +rect 373 78 379 82 +rect 383 78 389 82 +rect 391 82 392 85 +rect 391 78 397 82 +rect 343 20 346 21 +rect 335 13 338 20 +rect 340 17 346 20 +rect 350 17 356 21 +rect 340 13 343 17 +rect 346 16 356 17 +rect 358 16 372 21 +rect 374 17 381 21 +rect 385 17 391 21 +rect 374 16 385 17 +rect 358 14 361 16 +rect 346 12 361 14 +rect 371 14 372 16 +rect 371 12 385 14 +rect 388 13 391 17 +rect 393 13 396 21 +rect 346 11 385 12 +<< pdiffusion >> +rect 339 143 344 146 +rect 346 143 347 146 +rect 339 139 343 143 +rect 339 135 346 139 +rect 339 128 347 135 +rect 339 124 346 128 +rect 346 123 349 124 +rect 346 120 349 121 +rect 346 117 354 120 +rect 384 143 385 146 +rect 387 143 392 146 +rect 388 139 392 143 +rect 385 135 392 139 +rect 384 128 392 135 +rect 385 124 392 128 +rect 382 123 385 124 +rect 382 120 385 121 +rect 377 117 385 120 +rect 346 60 354 63 +rect 346 59 349 60 +rect 377 60 385 63 +rect 382 59 385 60 +rect 346 56 349 57 +rect 382 56 385 57 +rect 339 52 346 56 +rect 385 52 392 56 +rect 339 45 347 52 +rect 384 45 392 52 +rect 339 41 346 45 +rect 385 41 392 45 +rect 339 37 343 41 +rect 388 37 392 41 +rect 339 34 344 37 +rect 346 34 347 37 +rect 384 34 385 37 +rect 387 34 392 37 +<< metal1 >> +rect 339 176 342 178 +rect 341 171 342 176 +rect 331 159 336 161 +rect 339 152 342 171 +rect 334 149 342 152 +rect 334 106 337 149 +rect 347 147 350 160 +rect 354 160 357 178 +rect 366 171 367 176 +rect 366 170 371 171 +rect 374 160 377 178 +rect 389 176 392 178 +rect 389 171 390 176 +rect 354 156 364 160 +rect 340 143 347 146 +rect 340 116 343 143 +rect 346 134 350 135 +rect 346 129 348 134 +rect 346 128 350 129 +rect 355 121 358 148 +rect 350 117 354 120 +rect 334 103 346 106 +rect 350 103 353 117 +rect 361 114 364 156 +rect 343 75 346 103 +rect 357 111 364 114 +rect 367 156 377 160 +rect 367 114 370 156 +rect 373 121 376 148 +rect 381 147 384 160 +rect 389 152 392 171 +rect 389 149 397 152 +rect 384 143 391 146 +rect 381 134 385 135 +rect 383 129 385 134 +rect 381 128 385 129 +rect 367 111 374 114 +rect 357 92 360 111 +rect 363 102 368 104 +rect 371 92 374 111 +rect 377 103 380 120 +rect 388 116 391 143 +rect 394 106 397 149 +rect 386 103 397 106 +rect 357 87 358 92 +rect 373 87 374 92 +rect 333 72 346 75 +rect 333 31 336 72 +rect 339 37 343 64 +rect 351 60 354 78 +rect 357 69 360 87 +rect 363 76 368 78 +rect 371 69 374 87 +rect 357 66 364 69 +rect 346 51 350 52 +rect 346 46 348 51 +rect 346 45 350 46 +rect 339 34 347 37 +rect 333 28 342 31 +rect 331 19 335 21 +rect 339 11 342 28 +rect 347 21 350 33 +rect 355 32 358 59 +rect 361 24 364 66 +rect 354 21 364 24 +rect 367 66 374 69 +rect 367 24 370 66 +rect 379 63 382 78 +rect 386 75 389 103 +rect 392 92 399 95 +rect 392 87 395 92 +rect 392 86 399 87 +rect 386 72 398 75 +rect 377 60 382 63 +rect 373 32 376 59 +rect 381 51 385 52 +rect 383 46 385 51 +rect 381 45 385 46 +rect 388 37 392 64 +rect 384 34 392 37 +rect 367 21 377 24 +rect 341 6 342 11 +rect 339 4 342 6 +rect 354 4 357 21 +rect 361 11 371 12 +rect 365 10 371 11 +rect 365 6 366 10 +rect 374 4 377 21 +rect 381 21 384 33 +rect 395 31 398 72 +rect 389 28 398 31 +rect 389 11 392 28 +rect 389 6 390 11 +rect 389 4 392 6 +<< metal2 >> +rect 331 171 367 176 +rect 371 171 402 176 +rect 331 154 336 155 +rect 331 150 402 154 +rect 331 129 348 134 +rect 352 129 379 134 +rect 383 129 402 134 +rect 331 119 402 123 +rect 331 110 402 114 +rect 363 108 368 110 +rect 331 87 395 92 +rect 399 87 402 92 +rect 363 70 368 72 +rect 331 66 402 70 +rect 331 57 402 61 +rect 331 46 348 51 +rect 352 46 379 51 +rect 383 46 402 51 +rect 331 26 402 30 +rect 331 25 336 26 +rect 331 10 402 11 +rect 331 6 366 10 +rect 371 6 402 10 +<< polycontact >> +rect 336 171 341 176 +rect 390 171 395 176 +rect 354 148 358 153 +rect 340 111 345 116 +rect 373 148 377 153 +rect 386 111 391 116 +rect 358 87 363 92 +rect 368 87 373 92 +rect 339 64 344 69 +rect 387 64 392 69 +rect 354 27 358 32 +rect 373 27 377 32 +rect 336 6 341 11 +rect 390 6 395 11 +<< ndcontact >> +rect 331 161 336 165 +rect 361 165 371 170 +rect 346 160 350 164 +rect 381 160 385 164 +rect 349 99 353 103 +rect 363 98 368 102 +rect 377 99 381 103 +rect 392 95 402 99 +rect 350 78 354 82 +rect 363 78 368 82 +rect 379 78 383 82 +rect 392 82 402 86 +rect 331 15 335 19 +rect 346 17 350 21 +rect 381 17 385 21 +rect 361 12 371 16 +<< pdcontact >> +rect 347 143 351 147 +rect 346 124 350 128 +rect 354 117 358 121 +rect 380 143 384 147 +rect 381 124 385 128 +rect 373 117 377 121 +rect 354 59 358 63 +rect 373 59 377 63 +rect 346 52 350 56 +rect 381 52 385 56 +rect 347 33 351 37 +rect 380 33 384 37 +<< m2contact >> +rect 331 155 336 159 +rect 367 171 371 176 +rect 348 129 352 134 +rect 379 129 383 134 +rect 363 104 368 108 +rect 363 72 368 76 +rect 348 46 352 51 +rect 331 21 335 25 +rect 395 87 399 92 +rect 379 46 383 51 +rect 366 6 371 10 +<< ntransistor >> +rect 338 160 340 168 +rect 346 165 359 167 +rect 372 165 385 167 +rect 357 160 359 165 +rect 372 160 374 165 +rect 391 160 393 168 +rect 340 98 342 103 +rect 340 96 351 98 +rect 358 93 360 102 +rect 371 93 373 102 +rect 389 98 391 103 +rect 379 96 391 98 +rect 339 83 351 85 +rect 339 78 341 83 +rect 358 78 360 86 +rect 371 78 373 86 +rect 379 83 391 85 +rect 389 78 391 83 +rect 338 13 340 20 +rect 356 16 358 21 +rect 372 16 374 21 +rect 346 14 358 16 +rect 372 14 385 16 +rect 391 13 393 21 +<< ptransistor >> +rect 344 143 346 146 +rect 346 121 349 123 +rect 385 143 387 146 +rect 382 121 385 123 +rect 346 57 349 59 +rect 382 57 385 59 +rect 344 34 346 37 +rect 385 34 387 37 +<< psubstratepcontact >> +rect 361 170 366 176 +rect 331 87 336 92 +rect 361 6 365 11 +<< nsubstratencontact >> +rect 346 135 350 139 +rect 381 135 385 139 +rect 346 41 350 45 +rect 381 41 385 45 +<< labels >> +rlabel metal2 402 89 402 89 7 GND! +rlabel metal1 391 178 391 178 5 accA1# +rlabel metal1 355 178 355 178 5 accB0# +rlabel metal1 376 178 376 178 5 accB1# +rlabel metal1 340 178 340 178 5 accA0# +rlabel space 359 125 378 143 5 Plow here +rlabel metal2 402 112 402 112 7 busB1# +rlabel metal2 402 68 402 68 7 busB0# +rlabel metal2 402 49 402 49 7 Vdd! +rlabel metal2 402 28 402 28 7 busA0# +rlabel metal1 391 4 391 4 1 accA1# +rlabel metal1 340 4 340 4 1 accA0# +rlabel metal2 402 9 402 9 8 GND! +rlabel metal1 355 4 355 4 1 accB0# +rlabel metal1 376 4 376 4 1 accB1# +<< end >> diff --git a/doc/tutcells/tut3e.mag b/doc/tutcells/tut3e.mag new file mode 100644 index 00000000..3c118e0e --- /dev/null +++ b/doc/tutcells/tut3e.mag @@ -0,0 +1,54 @@ +magic +tech scmos +timestamp 616380512 +<< polysilicon >> +rect 8 17 10 19 +rect 16 16 18 21 +rect 25 20 27 21 +rect 22 18 27 20 +rect 16 14 20 16 +rect 8 11 10 14 +rect 18 0 20 14 +rect 22 0 24 18 +rect 30 16 32 21 +rect 38 14 40 21 +rect 30 0 32 13 +rect 38 12 42 14 +rect 45 12 47 14 +rect 38 0 40 12 +<< ndiffusion >> +rect 12 17 15 21 +rect 1 14 8 17 +rect 10 14 15 17 +rect 1 0 4 14 +rect 12 11 15 14 +rect 12 7 13 11 +rect 29 13 30 16 +rect 32 13 33 16 +rect 42 14 45 15 +rect 42 11 45 12 +<< metal1 >> +rect 33 17 41 19 +rect 37 16 41 17 +rect 45 16 47 19 +rect 0 7 5 10 +rect 17 7 41 10 +rect 0 0 4 4 +rect 8 0 47 4 +<< polycontact >> +rect 5 7 10 11 +<< ndcontact >> +rect 13 7 17 11 +rect 4 0 8 4 +rect 25 13 29 17 +rect 33 13 37 17 +rect 41 15 45 19 +rect 41 7 45 11 +<< ntransistor >> +rect 8 14 10 17 +rect 30 13 32 16 +rect 42 12 45 14 +<< labels >> +rlabel space 5 6 21 21 0 select me +rlabel space 27 6 27 6 1 point here +<< end >> diff --git a/doc/tutcells/tut3f.mag b/doc/tutcells/tut3f.mag new file mode 100644 index 00000000..0f40b227 --- /dev/null +++ b/doc/tutcells/tut3f.mag @@ -0,0 +1,26 @@ +magic +tech scmos +timestamp 500618087 +<< error_s >> +rect 49 6 50 8 +<< polysilicon >> +rect 19 15 21 46 +rect 28 15 30 46 +rect 33 15 35 46 +rect 21 -37 23 -6 +rect 25 -37 27 -6 +rect 33 -37 35 -6 +<< ndiffusion >> +rect 15 15 17 46 +<< metal1 >> +rect 50 10 64 13 +rect -6 1 3 4 +rect -6 -6 3 -2 +rect 50 -6 65 -2 +use tut3e tut3e_0 +timestamp 500618087 +transform 1 0 3 0 1 -6 +box 0 0 47 21 +<< labels >> +rlabel space 72 4 72 4 7 Point here +<< end >> diff --git a/doc/tutcells/tut3g.mag b/doc/tutcells/tut3g.mag new file mode 100644 index 00000000..cee52d96 --- /dev/null +++ b/doc/tutcells/tut3g.mag @@ -0,0 +1,31 @@ +magic +tech scmos +timestamp 616380642 +<< polysilicon >> +rect -5 23 -3 27 +rect -19 21 -3 23 +rect -19 7 -17 21 +rect -1 19 1 27 +rect -15 17 1 19 +rect -15 11 -13 17 +rect -15 9 -5 11 +rect -19 5 -9 7 +rect -11 2 -9 5 +rect -19 0 -9 2 +rect -19 -17 -17 0 +rect -7 -2 -5 9 +rect -15 -4 -5 -2 +rect -15 -13 -13 -4 +rect -15 -15 1 -13 +rect -19 -19 -3 -17 +rect -5 -20 -3 -19 +rect -1 -20 1 -15 +<< ndiffusion >> +rect 2 16 5 27 +rect -2 13 5 16 +rect -2 -8 1 13 +rect -2 -11 6 -8 +rect 3 -20 6 -11 +<< labels >> +rlabel space -23 -23 10 28 0 put box here +<< end >> diff --git a/doc/tutcells/tut3h.mag b/doc/tutcells/tut3h.mag new file mode 100644 index 00000000..54c57ce6 --- /dev/null +++ b/doc/tutcells/tut3h.mag @@ -0,0 +1,13 @@ +magic +tech scmos +timestamp 500618087 +<< polysilicon >> +rect -6 -16 34 -14 +rect -6 -20 34 -18 +rect -6 -24 34 -22 +rect -6 -28 34 -26 +rect -6 -32 34 -30 +<< labels >> +rlabel space 9 -32 19 -12 0 put plow here +rlabel space -8 -37 36 -9 3 put boundary here +<< end >> diff --git a/doc/tutcells/tut4a.mag b/doc/tutcells/tut4a.mag new file mode 100644 index 00000000..e2204f3e --- /dev/null +++ b/doc/tutcells/tut4a.mag @@ -0,0 +1,29 @@ +magic +tech scmos +timestamp 500618121 +<< metal1 >> +rect 1 36 4 44 +rect 7 36 10 44 +rect 21 36 24 44 +rect 27 36 30 44 +rect 33 36 36 44 +rect 39 36 42 44 +rect 53 36 56 44 +rect 59 36 62 44 +use tut4x tut4x_1 +timestamp 500618087 +transform 1 0 13 0 -1 156 +box -16 72 55 112 +use tut4x tut4x_0 +timestamp 500618087 +transform 1 0 13 0 1 -76 +box -16 72 55 112 +use tut4y tut4y_0 +timestamp 500618087 +transform 1 0 -68 0 1 -59 +box -3 -10 210 37 +use tut4y tut4y_1 +timestamp 500618087 +transform 1 0 -68 0 -1 -79 +box -3 -10 210 37 +<< end >> diff --git a/doc/tutcells/tut4x.mag b/doc/tutcells/tut4x.mag new file mode 100644 index 00000000..3af39841 --- /dev/null +++ b/doc/tutcells/tut4x.mag @@ -0,0 +1,125 @@ +magic +tech scmos +timestamp 616443648 +<< polysilicon >> +rect -3 104 -1 106 +rect 38 104 40 106 +rect -3 96 -1 101 +rect -3 94 7 96 +rect -9 88 -7 90 +rect 9 88 11 94 +rect 25 94 26 96 +rect 38 96 40 101 +rect 30 94 40 96 +rect 25 88 27 94 +rect 44 88 46 90 +rect -3 81 -1 83 +rect -9 79 -7 80 +rect 38 81 40 83 +rect 44 79 46 80 +<< ndiffusion >> +rect -12 86 -9 88 +rect -11 82 -9 86 +rect -12 80 -9 82 +rect -7 84 -1 88 +rect 3 84 9 88 +rect -7 80 -4 84 +rect -1 83 9 84 +rect 11 83 25 88 +rect 27 84 34 88 +rect 38 84 44 88 +rect 27 83 38 84 +rect 11 81 14 83 +rect -1 79 14 81 +rect 24 81 25 83 +rect 24 79 38 81 +rect 41 80 44 84 +rect 46 80 49 88 +rect -1 78 18 79 +rect 23 78 38 79 +<< pdiffusion >> +rect -8 108 1 112 +rect 36 108 45 112 +rect -8 104 -4 108 +rect 41 104 45 108 +rect -8 101 -3 104 +rect -1 101 0 104 +rect 37 101 38 104 +rect 40 101 45 104 +<< metal1 >> +rect -12 99 -9 112 +rect -6 105 -3 112 +rect -6 104 3 105 +rect -6 102 0 104 +rect -12 96 -5 99 +rect -12 89 -11 92 +rect -16 86 -11 89 +rect -8 79 -5 96 +rect 0 88 3 100 +rect 8 99 11 112 +rect 14 91 17 112 +rect 7 88 17 91 +rect 20 91 23 112 +rect 26 99 29 112 +rect 40 104 43 112 +rect 37 101 43 104 +rect 20 88 30 91 +rect -6 74 -5 79 +rect -8 72 -5 74 +rect 7 72 10 88 +rect 14 78 24 79 +rect 18 77 23 78 +rect 18 74 19 77 +rect 27 72 30 88 +rect 34 88 37 100 +rect 46 98 49 112 +rect 42 95 49 98 +rect 42 79 45 95 +rect 42 74 43 79 +rect 42 72 45 74 +<< metal2 >> +rect -16 93 55 97 +rect -12 89 -11 93 +rect -16 86 -11 89 +rect -16 77 55 79 +rect -16 74 19 77 +rect 23 74 55 77 +<< polycontact >> +rect 7 94 11 99 +rect 26 94 30 99 +rect -11 74 -6 79 +rect 43 74 48 79 +<< ndcontact >> +rect -16 82 -11 86 +rect -1 84 3 88 +rect 34 84 38 88 +rect 14 79 24 83 +<< pdcontact >> +rect 0 100 4 104 +rect 33 100 37 104 +<< m2contact >> +rect -16 89 -12 93 +rect 19 73 23 77 +<< ntransistor >> +rect -9 80 -7 88 +rect 9 83 11 88 +rect 25 83 27 88 +rect -1 81 11 83 +rect 25 81 38 83 +rect 44 80 46 88 +<< ptransistor >> +rect -3 101 -1 104 +rect 38 101 40 104 +<< psubstratepcontact >> +rect 13 74 18 78 +<< nsubstratencontact >> +rect 1 108 5 112 +rect 32 108 36 112 +<< labels >> +rlabel metal1 -8 72 -5 72 1 accA0 +rlabel metal1 7 72 10 72 1 accB0 +rlabel metal1 27 72 30 72 1 accB1 +rlabel metal1 42 72 45 72 1 accA1 +rlabel metal2 55 74 55 79 7 GND! +rlabel metal2 55 93 55 97 7 busA0 +<< end >> diff --git a/doc/tutcells/tut4y.mag b/doc/tutcells/tut4y.mag new file mode 100644 index 00000000..f748fcf7 --- /dev/null +++ b/doc/tutcells/tut4y.mag @@ -0,0 +1,22 @@ +magic +tech scmos +timestamp 500618087 +<< metal1 >> +rect 5 -10 8 -3 +rect 20 -10 23 -3 +rect 40 -10 43 -3 +rect 55 -10 58 -3 +rect 76 -10 79 -3 +rect 91 -10 94 -3 +rect 111 -10 114 -3 +rect 126 -10 129 -3 +rect 147 -10 150 -3 +rect 162 -10 165 -3 +rect 182 -10 185 -3 +rect 197 -10 200 -3 +use tut4x tut4x_0 +array 0 2 71 0 0 39 +timestamp 500618087 +transform 1 0 13 0 1 -75 +box -16 72 55 112 +<< end >> diff --git a/doc/tutcells/tut4z.mag b/doc/tutcells/tut4z.mag new file mode 100644 index 00000000..be4fc2d2 --- /dev/null +++ b/doc/tutcells/tut4z.mag @@ -0,0 +1,78 @@ +magic +tech scmos +timestamp 616443771 +<< polysilicon >> +rect 104 107 106 109 +rect 104 99 106 104 +rect 104 97 114 99 +rect 98 91 100 93 +rect 116 91 118 97 +rect 104 84 106 86 +rect 98 82 100 83 +<< ndiffusion >> +rect 95 90 98 91 +rect 96 86 98 90 +rect 95 83 98 86 +rect 100 87 106 91 +rect 110 87 116 91 +rect 100 83 103 87 +rect 106 86 116 87 +rect 118 86 131 91 +rect 118 84 121 86 +rect 106 81 121 84 +<< pdiffusion >> +rect 99 111 108 115 +rect 99 107 103 111 +rect 99 104 104 107 +rect 106 104 107 107 +<< metal1 >> +rect 95 102 98 115 +rect 101 108 104 115 +rect 101 107 110 108 +rect 101 105 107 107 +rect 95 99 102 102 +rect 91 91 95 92 +rect 91 90 96 91 +rect 99 82 102 99 +rect 107 91 110 103 +rect 115 102 118 115 +rect 121 94 124 115 +rect 114 91 124 94 +rect 127 91 131 115 +rect 101 77 102 82 +rect 99 75 102 77 +rect 114 75 117 91 +rect 126 81 131 82 +rect 126 77 127 81 +<< metal2 >> +rect 91 96 131 100 +rect 95 92 96 96 +rect 91 90 96 92 +rect 91 81 131 82 +rect 91 77 127 81 +<< polycontact >> +rect 114 97 118 102 +rect 96 77 101 82 +<< ndcontact >> +rect 91 86 96 90 +rect 106 87 110 91 +rect 121 82 131 86 +<< pdcontact >> +rect 107 103 111 107 +<< m2contact >> +rect 91 92 95 96 +rect 127 77 131 81 +<< ntransistor >> +rect 98 83 100 91 +rect 116 86 118 91 +rect 106 84 118 86 +<< ptransistor >> +rect 104 104 106 107 +<< psubstratepcontact >> +rect 121 77 126 82 +<< nsubstratencontact >> +rect 108 111 112 115 +<< labels >> +rlabel metal1 114 75 117 75 1 accB0 +rlabel metal1 99 75 102 75 1 accA0 +<< end >> diff --git a/doc/tutcells/tut5a.mag b/doc/tutcells/tut5a.mag new file mode 100644 index 00000000..0c37863a --- /dev/null +++ b/doc/tutcells/tut5a.mag @@ -0,0 +1,220 @@ +magic +tech scmos +timestamp 616454097 +<< polysilicon >> +rect 97 -18 98 -16 +rect 106 -18 108 -16 +rect 99 -24 101 -22 +rect 112 -24 119 -22 +rect 122 -24 124 -22 +rect 142 -22 149 -20 +rect 154 -19 163 -17 +rect 142 -24 144 -22 +rect 112 -32 114 -24 +rect 142 -29 144 -27 +rect 106 -36 112 -34 +rect 168 -32 170 -30 +rect 161 -38 163 -36 +rect 171 -38 172 -36 +rect 106 -51 114 -50 +rect 161 -51 163 -49 +rect 171 -51 172 -49 +rect 106 -52 112 -51 +rect 99 -65 101 -63 +rect 112 -63 114 -55 +rect 142 -60 144 -58 +rect 168 -57 170 -55 +rect 112 -65 119 -63 +rect 122 -65 124 -63 +rect 97 -71 98 -69 +rect 106 -71 108 -69 +rect 142 -65 144 -63 +rect 142 -67 149 -65 +rect 154 -70 163 -68 +<< ndiffusion >> +rect 98 -14 101 -13 +rect 105 -14 106 -13 +rect 98 -16 106 -14 +rect 163 -14 172 -9 +rect 163 -17 173 -14 +rect 98 -21 106 -18 +rect 102 -24 106 -21 +rect 96 -36 99 -24 +rect 101 -28 102 -24 +rect 101 -34 106 -28 +rect 163 -28 168 -19 +rect 167 -30 168 -28 +rect 170 -30 173 -17 +rect 163 -33 167 -32 +rect 163 -36 171 -33 +rect 96 -39 106 -36 +rect 96 -49 97 -39 +rect 101 -49 106 -39 +rect 163 -41 171 -38 +rect 163 -49 171 -46 +rect 96 -50 106 -49 +rect 96 -63 99 -50 +rect 101 -59 106 -52 +rect 101 -63 102 -59 +rect 102 -66 106 -63 +rect 163 -54 171 -51 +rect 163 -57 167 -54 +rect 167 -61 168 -57 +rect 98 -69 106 -66 +rect 163 -68 168 -61 +rect 170 -70 173 -57 +rect 98 -74 106 -71 +rect 163 -73 173 -70 +rect 163 -75 167 -73 +<< pdiffusion >> +rect 119 -21 141 -17 +rect 119 -22 122 -21 +rect 126 -24 141 -21 +rect 119 -25 122 -24 +rect 130 -25 137 -24 +rect 141 -27 142 -24 +rect 144 -27 148 -24 +rect 145 -32 148 -27 +rect 119 -63 122 -62 +rect 130 -63 137 -62 +rect 145 -60 148 -55 +rect 141 -63 142 -60 +rect 144 -63 148 -60 +rect 119 -66 122 -65 +rect 126 -66 141 -63 +rect 119 -70 141 -66 +<< metal1 >> +rect 105 -13 107 -9 +rect 114 -14 163 -11 +rect 90 -19 92 -17 +rect 114 -17 117 -14 +rect 97 -19 117 -17 +rect 90 -20 117 -19 +rect 120 -21 149 -17 +rect 120 -25 123 -21 +rect 160 -21 163 -14 +rect 160 -24 177 -21 +rect 106 -28 118 -25 +rect 122 -29 123 -25 +rect 130 -26 137 -24 +rect 130 -28 131 -26 +rect 136 -28 137 -26 +rect 145 -32 163 -29 +rect 90 -35 109 -32 +rect 106 -39 109 -35 +rect 117 -36 144 -33 +rect 151 -36 177 -35 +rect 151 -38 172 -36 +rect 151 -39 154 -38 +rect 96 -43 97 -39 +rect 92 -44 97 -43 +rect 95 -49 97 -44 +rect 106 -42 154 -39 +rect 106 -48 154 -45 +rect 162 -46 165 -41 +rect 106 -52 109 -48 +rect 151 -49 154 -48 +rect 151 -51 172 -49 +rect 90 -55 109 -52 +rect 117 -54 144 -51 +rect 151 -52 177 -51 +rect 145 -57 148 -55 +rect 106 -62 118 -59 +rect 119 -66 122 -62 +rect 130 -61 131 -59 +rect 136 -61 137 -59 +rect 130 -63 137 -61 +rect 145 -60 163 -57 +rect 90 -68 116 -67 +rect 90 -70 92 -68 +rect 97 -70 116 -68 +rect 119 -70 149 -66 +rect 160 -67 177 -64 +rect 113 -73 116 -70 +rect 160 -73 163 -67 +rect 113 -76 163 -73 +rect 171 -74 177 -70 +rect 171 -78 172 -74 +<< metal2 >> +rect 92 -44 97 -9 +rect 111 -13 115 -9 +rect 110 -14 115 -13 +rect 95 -49 97 -44 +rect 92 -80 97 -49 +rect 111 -80 115 -14 +rect 131 -26 136 -9 +rect 131 -57 136 -30 +rect 131 -80 136 -61 +rect 142 -80 146 -9 +rect 151 -41 155 -9 +rect 151 -46 157 -41 +rect 151 -80 155 -46 +rect 172 -74 177 -9 +rect 172 -80 177 -78 +<< polycontact >> +rect 92 -19 97 -14 +rect 149 -22 154 -17 +rect 112 -36 117 -32 +rect 172 -41 177 -36 +rect 172 -51 177 -46 +rect 112 -55 117 -51 +rect 92 -73 97 -68 +rect 149 -70 154 -65 +<< ndcontact >> +rect 101 -14 105 -9 +rect 102 -28 106 -24 +rect 163 -32 167 -28 +rect 97 -49 101 -39 +rect 165 -46 169 -41 +rect 102 -63 106 -59 +rect 163 -61 167 -57 +rect 167 -80 171 -73 +<< pdcontact >> +rect 118 -29 122 -25 +rect 137 -28 141 -24 +rect 144 -36 148 -32 +rect 144 -55 148 -51 +rect 118 -62 122 -58 +rect 137 -63 141 -59 +<< m2contact >> +rect 107 -13 111 -9 +rect 131 -30 136 -26 +rect 91 -49 95 -44 +rect 157 -46 162 -41 +rect 131 -61 136 -57 +rect 172 -78 177 -74 +<< ntransistor >> +rect 98 -18 106 -16 +rect 99 -34 101 -24 +rect 163 -19 170 -17 +rect 99 -36 106 -34 +rect 168 -30 170 -19 +rect 163 -38 171 -36 +rect 99 -52 106 -50 +rect 163 -51 171 -49 +rect 99 -63 101 -52 +rect 98 -71 106 -69 +rect 168 -68 170 -57 +rect 163 -70 170 -68 +<< ptransistor >> +rect 119 -24 122 -22 +rect 142 -27 144 -24 +rect 142 -63 144 -60 +rect 119 -65 122 -63 +<< psubstratepcontact >> +rect 172 -14 177 -9 +rect 92 -43 96 -39 +<< nsubstratencontact >> +rect 126 -28 130 -24 +rect 126 -63 130 -59 +<< labels >> +rlabel metal2 153 -80 153 -80 1 busB0# +rlabel metal2 134 -80 134 -80 1 Vdd! +rlabel metal1 90 -54 90 -54 3 accB1# +rlabel metal1 90 -33 90 -33 3 accB0# +rlabel metal2 113 -80 113 -80 1 busA0# +rlabel metal2 95 -80 95 -80 2 GND! +rlabel metal1 90 -18 90 -18 3 accA0# +rlabel metal1 90 -69 90 -69 3 accA1# +rlabel metal2 174 -80 174 -80 1 GND! +<< end >> diff --git a/doc/tutcells/tut5b.mag b/doc/tutcells/tut5b.mag new file mode 100644 index 00000000..746c6f5e --- /dev/null +++ b/doc/tutcells/tut5b.mag @@ -0,0 +1,78 @@ +magic +tech scmos +timestamp 616454154 +<< polysilicon >> +rect 114 76 116 78 +rect 114 68 116 73 +rect 114 66 124 68 +rect 108 60 110 62 +rect 126 60 128 66 +rect 114 53 116 55 +rect 108 51 110 52 +<< ndiffusion >> +rect 105 59 108 60 +rect 106 55 108 59 +rect 105 52 108 55 +rect 110 56 116 60 +rect 120 56 126 60 +rect 110 52 113 56 +rect 116 55 126 56 +rect 128 55 141 60 +rect 128 53 131 55 +rect 116 50 131 53 +<< pdiffusion >> +rect 109 80 118 84 +rect 109 76 113 80 +rect 109 73 114 76 +rect 116 73 117 76 +<< metal1 >> +rect 105 71 108 84 +rect 111 77 114 84 +rect 111 76 120 77 +rect 111 74 117 76 +rect 105 68 112 71 +rect 101 60 105 61 +rect 101 59 106 60 +rect 109 51 112 68 +rect 117 60 120 72 +rect 125 71 128 84 +rect 131 63 134 84 +rect 124 60 134 63 +rect 137 60 141 84 +rect 111 46 112 51 +rect 109 44 112 46 +rect 124 44 127 60 +rect 136 50 141 51 +rect 136 46 137 50 +<< metal2 >> +rect 101 65 141 69 +rect 105 61 106 65 +rect 101 59 106 61 +rect 101 50 141 51 +rect 101 46 137 50 +<< polycontact >> +rect 124 66 128 71 +rect 106 46 111 51 +<< ndcontact >> +rect 101 55 106 59 +rect 116 56 120 60 +rect 131 51 141 55 +<< pdcontact >> +rect 117 72 121 76 +<< m2contact >> +rect 101 61 105 65 +rect 137 46 141 50 +<< ntransistor >> +rect 108 52 110 60 +rect 126 55 128 60 +rect 116 53 128 55 +<< ptransistor >> +rect 114 73 116 76 +<< psubstratepcontact >> +rect 131 46 136 51 +<< nsubstratencontact >> +rect 118 80 122 84 +<< labels >> +rlabel metal1 124 44 127 44 1 accB0 +rlabel metal1 109 44 112 44 1 accA0 +<< end >> diff --git a/doc/tutcells/tut6a.mag b/doc/tutcells/tut6a.mag new file mode 100644 index 00000000..8203ec18 --- /dev/null +++ b/doc/tutcells/tut6a.mag @@ -0,0 +1,17 @@ +magic +tech scmos +timestamp 500618582 +<< error_p >> +rect -4 15 -2 17 +rect -1 12 1 15 +rect 9 12 12 14 +rect 9 8 15 11 +rect -5 2 8 4 +<< metal1 >> +rect -7 12 -2 17 +rect -1 11 2 15 +rect 9 12 12 16 +rect 9 8 12 11 +rect 12 5 15 8 +rect -5 1 8 2 +<< end >> diff --git a/doc/tutcells/tut6b.mag b/doc/tutcells/tut6b.mag new file mode 100644 index 00000000..e5bedafb --- /dev/null +++ b/doc/tutcells/tut6b.mag @@ -0,0 +1,31 @@ +magic +tech scmos +timestamp 500618582 +<< error_p >> +rect 59 39 60 41 +rect 59 19 60 24 +rect 54 18 61 19 +rect 70 18 71 19 +rect 86 18 90 19 +rect 57 17 61 18 +rect 59 1 60 7 +<< error_s >> +rect -12 18 -9 19 +rect 8 18 11 19 +rect 0 0 1 7 +<< polysilicon >> +rect -12 18 11 22 +use tut6x tut6x_1 +timestamp 500618582 +transform -1 0 -10 0 1 6 +box -9 -6 7 11 +use tut6x tut6x_0 +timestamp 500618582 +transform 1 0 9 0 1 6 +box -9 -6 7 11 +use tut6x tut6x_2 +array 0 2 16 0 2 17 +timestamp 500618582 +transform 1 0 52 0 1 6 +box -9 -6 7 11 +<< end >> diff --git a/doc/tutcells/tut6c.mag b/doc/tutcells/tut6c.mag new file mode 100644 index 00000000..cf322d8e --- /dev/null +++ b/doc/tutcells/tut6c.mag @@ -0,0 +1,30 @@ +magic +tech scmos +timestamp 616458517 +<< error_p >> +rect 55 47 57 51 +rect 10 33 12 37 +rect 10 -4 12 0 +rect 55 -4 57 0 +rect 55 -23 56 -21 +rect 55 -41 57 -37 +<< polysilicon >> +rect 53 28 55 30 +rect 54 -23 56 -21 +<< metal1 >> +rect 52 47 55 51 +rect 9 33 10 37 +rect 52 10 55 14 +rect 9 -4 10 0 +rect 52 -4 55 0 +rect 52 -41 55 -37 +use tut6y tut6y_0 +timestamp 616458517 +transform 1 0 -23 0 1 -33 +box 13 29 32 70 +use tut6y tut6y_1 +array 0 3 20 0 1 51 +timestamp 616458517 +transform 1 0 22 0 1 -70 +box 13 29 32 70 +<< end >> diff --git a/doc/tutcells/tut6x.mag b/doc/tutcells/tut6x.mag new file mode 100644 index 00000000..617e4613 --- /dev/null +++ b/doc/tutcells/tut6x.mag @@ -0,0 +1,9 @@ +magic +tech scmos +timestamp 500618582 +<< polysilicon >> +rect 1 8 7 11 +rect 5 5 7 8 +rect -9 -6 -6 1 +rect 2 -5 6 0 +<< end >> diff --git a/doc/tutcells/tut6y.mag b/doc/tutcells/tut6y.mag new file mode 100644 index 00000000..a57365f8 --- /dev/null +++ b/doc/tutcells/tut6y.mag @@ -0,0 +1,42 @@ +magic +tech scmos +timestamp 616458412 +<< polysilicon >> +rect 20 60 25 62 +rect 29 60 31 62 +rect 20 49 22 60 +rect 13 47 22 49 +rect 29 47 32 49 +rect 20 40 22 47 +rect 20 37 25 40 +rect 29 37 31 40 +<< ndiffusion >> +rect 25 40 29 41 +rect 25 33 29 37 +<< pdiffusion >> +rect 25 62 29 66 +rect 25 59 29 60 +<< metal1 >> +rect 13 66 20 70 +rect 28 66 32 70 +rect 25 52 29 55 +rect 25 45 29 47 +rect 13 29 20 33 +rect 28 29 32 33 +<< polycontact >> +rect 25 47 29 52 +<< ndcontact >> +rect 25 41 29 45 +rect 24 29 28 33 +<< pdcontact >> +rect 24 66 28 70 +rect 25 55 29 59 +<< ntransistor >> +rect 25 37 29 40 +<< ptransistor >> +rect 25 60 29 62 +<< psubstratepcontact >> +rect 20 29 24 33 +<< nsubstratencontact >> +rect 20 66 24 70 +<< end >> diff --git a/doc/tutcells/tut7a.mag b/doc/tutcells/tut7a.mag new file mode 100644 index 00000000..c30ce5f5 --- /dev/null +++ b/doc/tutcells/tut7a.mag @@ -0,0 +1,41 @@ +magic +tech scmos +timestamp 616462131 +<< polysilicon >> +rect -23 -8 -15 -6 +<< ndiffusion >> +rect -27 14 -20 17 +rect -23 2 -20 5 +<< metal1 >> +rect 14 26 17 32 +rect 18 15 21 19 +rect 13 12 21 15 +rect -2 -8 1 -1 +rect 16 -8 19 0 +<< metal2 >> +rect -21 29 -16 32 +rect -21 26 -18 29 +rect -4 26 -1 32 +rect 6 0 15 3 +rect 19 0 21 3 +rect 6 -3 9 0 +<< ndcontact >> +rect -27 1 -23 5 +<< m2contact >> +rect 15 0 19 4 +<< labels >> +rlabel metal1 17 -8 17 -8 1 bad1 +rlabel metal1 17 -8 17 -8 5 (use line label) +rlabel ndcontact -27 1 -27 5 3 good5 +rlabel metal2 -4 32 -3 32 5 bad4 +rlabel metal2 -4 32 -3 32 1 (not wide enough to route to) +rlabel polysilicon -20 -8 -15 -8 1 bad5 +rlabel polysilicon -20 -8 -15 -8 5 (will work, but why not make wider?) +rlabel metal1 21 12 21 19 7 good2 +rlabel metal2 6 -3 9 0 1 (works, but better to place on cell edge) +rlabel metal2 6 -3 9 0 5 bad3 +rlabel metal2 -21 29 -16 32 5 good4 +rlabel metal1 14 32 17 32 5 good3 +rlabel metal1 -2 -8 1 -5 1 good1 +rlabel ndiffusion -27 14 -27 17 3 bad2 (can't route to diff) +<< end >> diff --git a/doc/tutcells/tut7b.mag b/doc/tutcells/tut7b.mag new file mode 100644 index 00000000..8d77356d --- /dev/null +++ b/doc/tutcells/tut7b.mag @@ -0,0 +1,18 @@ +magic +tech scmos +timestamp 500618984 +<< metal1 >> +rect 94 93 100 102 +rect -66 -45 94 -29 +rect -61 -181 -55 -173 +use tut7c tut7c_0 +timestamp 500618984 +transform 1 0 11 0 1 26 +box -14 -29 45 35 +use tut7c tut7c_1 +timestamp 500618984 +transform 1 0 18 0 1 -106 +box -14 -29 45 35 +<< labels >> +rlabel metal1 -66 -45 -66 -29 3 foo +<< end >> diff --git a/doc/tutcells/tut7b.net b/doc/tutcells/tut7b.net new file mode 100644 index 00000000..8f28b99a --- /dev/null +++ b/doc/tutcells/tut7b.net @@ -0,0 +1,17 @@ + Net List File + +tut7c_0/top1 +tut7c_1/top1 + +tut7c_1/left3 +tut7c_0/left3 + +tut7c_1/left4 +tut7c_1/left1 + +tut7c_1/bot1 +tut7c_0/right3 + +tut7c_0/right4 +tut7c_1/top4 +tut7c_1/bot3 diff --git a/doc/tutcells/tut7c.mag b/doc/tutcells/tut7c.mag new file mode 100644 index 00000000..72485912 --- /dev/null +++ b/doc/tutcells/tut7c.mag @@ -0,0 +1,53 @@ +magic +tech scmos +timestamp 616462327 +<< polysilicon >> +rect 9 25 11 30 +<< ndiffusion >> +rect 38 10 41 13 +<< pdiffusion >> +rect -10 -5 -5 -2 +<< metal1 >> +rect 1 30 4 35 +rect 30 32 35 35 +rect 30 30 33 32 +rect 38 -5 45 -2 +rect -14 -18 -7 -15 +rect 6 -29 9 -22 +rect 37 -29 45 -25 +<< metal2 >> +rect -12 22 -9 35 +rect 38 23 41 26 +rect -14 19 -9 22 +rect -14 10 -5 13 +rect 38 -17 45 -14 +rect -6 -26 -3 -19 +rect -12 -29 -3 -26 +rect 25 -29 28 -22 +<< polycontact >> +rect 9 30 13 35 +<< ndcontact >> +rect 41 10 45 14 +<< pdcontact >> +rect -14 -5 -10 -1 +<< m2contact >> +rect 41 23 45 27 +rect -7 -19 -3 -15 +<< labels >> +rlabel metal2 -12 -29 -3 -29 1 bot3 +rlabel metal1 6 -29 9 -29 1 bot2 +rlabel pdcontact -14 -5 -14 -1 3 left2 +rlabel ndcontact 45 10 45 14 7 right2 +rlabel polycontact 9 35 13 35 5 top3 +rlabel m2contact 45 23 45 27 7 right1 +rlabel metal1 30 35 35 35 5 top4 +rlabel metal2 -14 10 -14 13 3 left3 +rlabel metal1 -14 -18 -14 -15 3 left1 +rlabel metal2 25 -29 28 -29 1 bot1 +rlabel metal1 45 -29 45 -25 7 right5 +rlabel metal2 45 -17 45 -14 7 right4 +rlabel metal1 45 -5 45 -2 7 right3 +rlabel metal2 -14 19 -14 22 3 left4 +rlabel metal2 -12 35 -9 35 5 top1 +rlabel metal1 1 35 4 35 5 top2 +<< end >> diff --git a/doc/tutcells/tut7d.mag b/doc/tutcells/tut7d.mag new file mode 100644 index 00000000..c442a234 --- /dev/null +++ b/doc/tutcells/tut7d.mag @@ -0,0 +1,88 @@ +magic +tech scmos +timestamp 616465268 +<< metal1 >> +rect -24 80 3 83 +rect -24 43 -21 80 +rect 0 75 3 80 +rect 84 72 94 81 +rect -32 32 -17 35 +rect -32 -13 -29 32 +rect -40 -16 -29 -13 +rect -40 -53 -37 -16 +rect -24 -45 -21 23 +rect 56 21 67 24 +rect 64 19 67 21 +rect 64 16 71 19 +rect 67 8 83 11 +rect 72 -45 75 -1 +rect 80 -13 83 8 +rect 80 -16 91 -13 +rect -24 -48 -5 -45 +rect 72 -48 79 -45 +rect -8 -53 -5 -48 +rect 88 -53 91 -16 +rect -40 -56 -13 -53 +rect -8 -56 11 -53 +rect -16 -77 -13 -56 +rect 8 -61 11 -56 +rect 48 -56 91 -53 +rect 48 -71 51 -56 +rect -24 -80 -13 -77 +rect -24 -93 -21 -80 +rect -13 -88 -9 -85 +rect -24 -96 -9 -93 +rect -16 -125 -13 -105 +rect -8 -124 4 -121 +rect -8 -125 -5 -124 +rect -16 -128 -5 -125 +rect -41 -160 -31 -151 +rect 8 -157 11 -145 +rect 40 -149 43 -145 +rect 80 -149 83 -65 +rect 40 -152 83 -149 +rect 88 -157 91 -56 +rect 8 -160 91 -157 +<< metal2 >> +rect -1 61 2 71 +rect -24 27 -21 39 +rect -17 36 -3 39 +rect -17 35 -13 36 +rect 56 11 67 12 +rect 56 9 63 11 +rect 72 3 75 15 +rect 80 -61 83 -49 +rect 6 -65 7 -61 +rect 6 -71 9 -65 +rect -9 -85 4 -84 +rect -5 -87 4 -85 +rect -16 -101 -13 -89 +rect -5 -96 4 -93 +rect 8 -141 11 -135 +rect 43 -145 46 -135 +<< m2contact >> +rect -1 71 3 75 +rect -25 39 -21 43 +rect -17 31 -13 35 +rect -25 23 -21 27 +rect 71 15 75 19 +rect 63 7 67 11 +rect 71 -1 75 3 +rect 79 -49 83 -45 +rect 7 -65 11 -61 +rect 79 -65 83 -61 +rect -17 -89 -13 -85 +rect -9 -89 -5 -85 +rect -9 -97 -5 -93 +rect -17 -105 -13 -101 +rect 7 -145 11 -141 +rect 39 -145 43 -141 +use tut7c tut7c_0 +timestamp 616462327 +transform 1 0 11 0 1 26 +box -14 -29 45 35 +use tut7c tut7c_1 +timestamp 616462327 +transform 1 0 18 0 1 -106 +box -14 -29 45 35 +<< end >> diff --git a/doc/tutcells/tut7d.net b/doc/tutcells/tut7d.net new file mode 100644 index 00000000..8f28b99a --- /dev/null +++ b/doc/tutcells/tut7d.net @@ -0,0 +1,17 @@ + Net List File + +tut7c_0/top1 +tut7c_1/top1 + +tut7c_1/left3 +tut7c_0/left3 + +tut7c_1/left4 +tut7c_1/left1 + +tut7c_1/bot1 +tut7c_0/right3 + +tut7c_0/right4 +tut7c_1/top4 +tut7c_1/bot3 diff --git a/doc/tutcells/tut8a.mag b/doc/tutcells/tut8a.mag new file mode 100644 index 00000000..32173751 --- /dev/null +++ b/doc/tutcells/tut8a.mag @@ -0,0 +1,24 @@ +magic +tech scmos +timestamp 539486845 +<< polysilicon >> +rect -3 -14 -1 7 +<< metal1 >> +rect -14 8 -1 12 +rect -18 0 -1 4 +rect -18 -8 -14 0 +<< metal2 >> +rect -18 -18 -14 8 +<< m2contact >> +rect -18 8 -14 12 +use tut8b tut8b_0 +timestamp 500619087 +transform 1 0 5 0 1 0 +box -6 0 18 12 +use tut8c tut8c_0 +timestamp 500619087 +transform 1 0 4 0 1 -14 +box -22 -8 11 6 +<< labels >> +rlabel polysilicon -3 -14 -1 7 3 delete_me +<< end >> diff --git a/doc/tutcells/tut8b.mag b/doc/tutcells/tut8b.mag new file mode 100644 index 00000000..9e3bd467 --- /dev/null +++ b/doc/tutcells/tut8b.mag @@ -0,0 +1,28 @@ +magic +tech scmos +timestamp 500619087 +<< polysilicon >> +rect -6 5 0 7 +rect 3 5 10 7 +<< ndiffusion >> +rect 0 7 3 8 +rect 0 4 3 5 +<< metal1 >> +rect -6 8 0 12 +rect 4 8 10 12 +rect -6 0 0 4 +rect 4 0 10 4 +<< ndcontact >> +rect 0 8 4 12 +rect 0 0 4 4 +<< ntransistor >> +rect 0 5 3 7 +use tut8d tut8d_0 +timestamp 500619087 +transform 1 0 0 0 1 3 +box 10 -3 18 9 +<< labels >> +rlabel metal1 -6 0 -6 4 3 Out +rlabel metal1 -6 8 -6 12 3 In +rlabel polysilicon -6 5 -6 7 3 Gate +<< end >> diff --git a/doc/tutcells/tut8c.mag b/doc/tutcells/tut8c.mag new file mode 100644 index 00000000..5981c00d --- /dev/null +++ b/doc/tutcells/tut8c.mag @@ -0,0 +1,32 @@ +magic +tech scmos +timestamp 500619087 +<< polysilicon >> +rect -7 -2 3 0 +rect 6 -2 8 0 +rect -7 -4 -3 -2 +<< ndiffusion >> +rect 3 0 6 2 +rect 3 -4 6 -2 +<< metal1 >> +rect -22 2 2 6 +rect 7 2 11 6 +rect -10 -8 -9 -4 +rect 7 -8 11 -4 +<< metal2 >> +rect -22 -8 -14 -4 +rect -10 -8 11 -4 +<< polycontact >> +rect -9 -8 -3 -4 +<< ndcontact >> +rect 2 2 7 6 +rect 2 -8 7 -4 +<< m2contact >> +rect -14 -8 -10 -4 +<< ntransistor >> +rect 3 -2 6 0 +<< labels >> +rlabel metal2 -22 -8 -22 -4 3 A +rlabel metal1 -22 2 -22 6 3 B +rlabel metal1 11 -8 11 -4 7 C +<< end >> diff --git a/doc/tutcells/tut8d.mag b/doc/tutcells/tut8d.mag new file mode 100644 index 00000000..b046100e --- /dev/null +++ b/doc/tutcells/tut8d.mag @@ -0,0 +1,9 @@ +magic +tech scmos +timestamp 500619087 +<< polysilicon >> +rect 10 2 18 4 +<< metal1 >> +rect 10 5 18 9 +rect 10 -3 18 1 +<< end >> diff --git a/doc/tutcells/tut8e.mag b/doc/tutcells/tut8e.mag new file mode 100644 index 00000000..dd96e10c --- /dev/null +++ b/doc/tutcells/tut8e.mag @@ -0,0 +1,90 @@ +magic +tech scmos +timestamp 617925319 +<< polysilicon >> +rect -95 26 -92 28 +rect -72 26 -70 28 +rect -95 2 -93 26 +rect -72 15 -54 17 +rect -95 0 -92 2 +rect -72 0 -70 2 +rect -95 -18 -92 -16 +rect -72 -18 -70 -16 +rect -95 -42 -93 -18 +rect -72 -33 -54 -31 +rect -95 -44 -92 -42 +rect -72 -44 -70 -42 +<< ndiffusion >> +rect -92 2 -72 3 +rect -92 -1 -72 0 +rect -92 -16 -72 -15 +rect -92 -19 -72 -18 +<< pdiffusion >> +rect -92 28 -72 29 +rect -92 25 -72 26 +rect -92 -42 -72 -41 +rect -92 -45 -72 -44 +<< metal1 >> +rect -88 34 -87 38 +rect -92 33 -87 34 +rect -76 18 -72 21 +rect -102 14 -99 18 +rect -76 7 -72 14 +rect -92 -6 -87 -5 +rect -88 -10 -87 -6 +rect -92 -11 -87 -10 +rect -76 -30 -72 -23 +rect -103 -34 -99 -30 +rect -76 -37 -72 -34 +rect -92 -50 -87 -49 +rect -88 -54 -87 -50 +<< metal2 >> +rect -103 34 -92 38 +rect -88 34 -54 38 +rect -103 -10 -92 -6 +rect -88 -10 -54 -6 +rect -103 -54 -92 -50 +rect -88 -54 -54 -50 +<< nwell >> +rect -101 16 -70 39 +rect -101 -55 -70 -32 +<< polycontact >> +rect -99 14 -95 18 +rect -76 14 -72 18 +rect -99 -34 -95 -30 +rect -76 -34 -72 -30 +<< ndcontact >> +rect -92 3 -72 7 +rect -92 -5 -72 -1 +rect -92 -15 -72 -11 +rect -92 -23 -72 -19 +<< pdcontact >> +rect -92 29 -72 33 +rect -92 21 -72 25 +rect -92 -41 -72 -37 +rect -92 -49 -72 -45 +<< m2contact >> +rect -92 34 -88 38 +rect -92 -10 -88 -6 +rect -92 -54 -88 -50 +<< ntransistor >> +rect -92 0 -72 2 +rect -92 -18 -72 -16 +<< ptransistor >> +rect -92 26 -72 28 +rect -92 -44 -72 -42 +<< psubstratepcontact >> +rect -87 -11 -83 -5 +<< nsubstratencontact >> +rect -87 33 -82 38 +rect -87 -54 -82 -49 +<< labels >> +rlabel metal1 -101 -32 -101 -32 3 in2 +rlabel metal1 -101 16 -101 16 3 in1 +rlabel polysilicon -57 16 -57 16 1 net1 +rlabel polysilicon -58 -32 -58 -32 1 net2 +rlabel metal2 -64 -8 -64 -8 5 GND! +rlabel metal2 -62 36 -62 36 5 Vdd! +rlabel metal2 -64 -8 -64 -8 1 GND! +rlabel metal2 -62 -52 -62 -52 1 Vdd#1 +<< end >> diff --git a/doc/tutcells/tut8f.mag b/doc/tutcells/tut8f.mag new file mode 100644 index 00000000..e6e7b5db --- /dev/null +++ b/doc/tutcells/tut8f.mag @@ -0,0 +1,14 @@ +magic +tech scmos +timestamp 617925832 +<< metal2 >> +rect 39 89 49 93 +rect 38 1 49 5 +use tut8e tut8e_0 +timestamp 617925319 +transform 1 0 103 0 1 55 +box -103 -55 -54 39 +<< labels >> +rlabel metal2 47 3 47 3 8 Vdd! +rlabel metal2 47 91 47 91 6 Vdd! +<< end >> diff --git a/doc/tutcells/tut8g.mag b/doc/tutcells/tut8g.mag new file mode 100644 index 00000000..2f181218 --- /dev/null +++ b/doc/tutcells/tut8g.mag @@ -0,0 +1,90 @@ +magic +tech scmos +timestamp 617925690 +<< polysilicon >> +rect 8 81 11 83 +rect 31 81 33 83 +rect 8 57 10 81 +rect 31 70 49 72 +rect 8 55 11 57 +rect 31 55 33 57 +rect 8 37 11 39 +rect 31 37 33 39 +rect 8 13 10 37 +rect 31 22 49 24 +rect 8 11 11 13 +rect 31 11 33 13 +<< ndiffusion >> +rect 11 57 31 58 +rect 11 54 31 55 +rect 11 39 31 40 +rect 11 36 31 37 +<< pdiffusion >> +rect 11 83 31 84 +rect 11 80 31 81 +rect 11 13 31 14 +rect 11 10 31 11 +<< metal1 >> +rect 15 89 16 93 +rect 11 88 16 89 +rect 27 73 31 76 +rect 1 69 4 73 +rect 27 62 31 69 +rect 11 49 16 50 +rect 15 45 16 49 +rect 11 44 16 45 +rect 27 25 31 32 +rect 0 21 4 25 +rect 27 18 31 21 +rect 11 5 16 6 +rect 15 1 16 5 +<< metal2 >> +rect 0 89 11 93 +rect 15 89 49 93 +rect 0 45 11 49 +rect 15 45 49 49 +rect 0 1 11 5 +rect 15 1 49 5 +<< nwell >> +rect 2 71 33 94 +rect 2 0 33 23 +<< polycontact >> +rect 4 69 8 73 +rect 27 69 31 73 +rect 4 21 8 25 +rect 27 21 31 25 +<< ndcontact >> +rect 11 58 31 62 +rect 11 50 31 54 +rect 11 40 31 44 +rect 11 32 31 36 +<< pdcontact >> +rect 11 84 31 88 +rect 11 76 31 80 +rect 11 14 31 18 +rect 11 6 31 10 +<< m2contact >> +rect 11 89 15 93 +rect 11 45 15 49 +rect 11 1 15 5 +<< ntransistor >> +rect 11 55 31 57 +rect 11 37 31 39 +<< ptransistor >> +rect 11 81 31 83 +rect 11 11 31 13 +<< psubstratepcontact >> +rect 16 44 20 50 +<< nsubstratencontact >> +rect 16 88 21 93 +rect 16 1 21 6 +<< labels >> +rlabel metal1 2 23 2 23 3 in2 +rlabel metal1 2 71 2 71 3 in1 +rlabel polysilicon 46 71 46 71 1 net1 +rlabel polysilicon 45 23 45 23 1 net2 +rlabel metal2 39 47 39 47 5 GND! +rlabel metal2 41 91 41 91 5 Vdd! +rlabel metal2 39 47 39 47 1 GND! +rlabel metal2 40 3 40 3 1 Vdd! +<< end >> diff --git a/doc/tutcells/tut8h.mag b/doc/tutcells/tut8h.mag new file mode 100644 index 00000000..c383308f --- /dev/null +++ b/doc/tutcells/tut8h.mag @@ -0,0 +1,32 @@ +magic +tech scmos +timestamp 617922660 +<< error_s >> +rect -3 -7 0 -5 +<< polysilicon >> +rect -1 6 5 8 +rect -7 -7 4 -5 +<< ndiffusion >> +rect -9 15 -1 20 +rect -10 8 -1 11 +rect -10 6 -7 8 +rect -10 3 -1 6 +<< ntransistor >> +rect -7 6 -1 8 +use tut8j tut8j +timestamp 617922547 +transform 0 1 -3 -1 0 -1 +box 0 0 10 3 +use tut8i tut8i_0 +timestamp 617922660 +transform 1 0 -13 0 1 -17 +box -15 0 11 2 +use tut8i tut8i_1 +timestamp 617922660 +transform 1 0 13 0 1 -17 +box -15 0 11 2 +<< labels >> +rlabel polysilicon 5 6 5 8 7 Gate +rlabel ndiffusion -9 15 -9 20 3 Drain +rlabel ndiffusion -10 3 -10 11 3 Drain +<< end >> diff --git a/doc/tutcells/tut8i.mag b/doc/tutcells/tut8i.mag new file mode 100644 index 00000000..06a06278 --- /dev/null +++ b/doc/tutcells/tut8i.mag @@ -0,0 +1,8 @@ +magic +tech scmos +timestamp 617922660 +<< polysilicon >> +rect -15 0 11 2 +<< labels >> +rlabel polysilicon -15 0 -15 2 3 A +<< end >> diff --git a/doc/tutcells/tut8j.mag b/doc/tutcells/tut8j.mag new file mode 100644 index 00000000..262a32b3 --- /dev/null +++ b/doc/tutcells/tut8j.mag @@ -0,0 +1,8 @@ +magic +tech scmos +timestamp 617922547 +<< ndiffusion >> +rect 0 0 10 3 +<< labels >> +rlabel ndiffusion 0 0 0 2 3 B +<< end >> diff --git a/doc/tutcells/tut8k.mag b/doc/tutcells/tut8k.mag new file mode 100644 index 00000000..0cdd37e3 --- /dev/null +++ b/doc/tutcells/tut8k.mag @@ -0,0 +1,22 @@ +magic +tech scmos +timestamp 539497029 +<< metal1 >> +rect -6 24 4 28 +rect -40 -3 -36 4 +rect -6 -22 -2 24 +rect 1 -3 5 4 +rect 5 -7 24 -3 +rect -6 -26 4 -22 +<< metal2 >> +rect -36 -7 1 -4 +<< m2contact >> +rect -40 -7 -36 -3 +rect 1 -7 5 -3 +<< labels >> +rlabel metal1 24 -5 24 -5 3 ReceiverC +rlabel metal1 3 4 3 4 1 Driver2 +rlabel metal1 -38 4 -38 4 1 ReceiverB +rlabel metal1 4 -24 4 -24 3 Driver1 +rlabel metal1 4 27 4 27 3 ReceiverA +<< end >> diff --git a/doc/tutcells/tut8l.mag b/doc/tutcells/tut8l.mag new file mode 100644 index 00000000..06380f9b --- /dev/null +++ b/doc/tutcells/tut8l.mag @@ -0,0 +1,107 @@ +magic +tech scmos +timestamp 539905536 +<< polysilicon >> +rect -1 25 4 27 +rect 8 25 10 27 +rect 31 25 36 27 +rect 40 25 42 27 +rect 54 25 59 27 +rect 63 25 65 27 +rect -1 3 1 25 +rect 31 12 33 25 +rect 8 10 33 12 +rect 54 12 56 25 +rect 40 10 56 12 +rect 31 3 33 10 +rect 54 3 56 10 +rect -6 1 4 3 +rect 8 1 10 3 +rect 31 1 36 3 +rect 40 1 42 3 +rect 54 1 59 3 +rect 63 1 65 3 +<< ndiffusion >> +rect 4 3 8 4 +rect 36 3 40 4 +rect 59 3 63 4 +rect 4 -2 8 1 +rect 36 -2 40 1 +rect 59 -2 63 1 +<< pdiffusion >> +rect 4 27 8 35 +rect 36 27 40 35 +rect 59 27 63 35 +rect 4 24 8 25 +rect 36 24 40 25 +rect 59 24 63 25 +<< metal1 >> +rect -5 35 4 39 +rect 12 35 36 39 +rect 40 35 59 39 +rect 63 35 67 39 +rect -5 28 26 32 +rect 30 28 67 32 +rect 4 14 8 20 +rect 4 8 8 10 +rect 36 14 40 20 +rect 36 8 40 10 +rect 59 14 63 20 +rect 59 10 67 14 +rect 59 8 63 10 +rect -6 -6 4 -2 +rect 12 -6 36 -2 +rect 40 -6 59 -2 +rect 63 -6 67 -2 +<< pwell >> +rect -2 -12 15 14 +rect 30 -12 46 14 +<< nwell >> +rect -2 14 15 43 +rect 26 14 46 43 +<< polycontact >> +rect 4 10 8 14 +rect 36 10 40 14 +<< ndcontact >> +rect 4 4 8 8 +rect 36 4 40 8 +rect 59 4 63 8 +rect 4 -6 8 -2 +rect 36 -6 40 -2 +rect 59 -6 63 -2 +<< pdcontact >> +rect 4 35 8 39 +rect 36 35 40 39 +rect 59 35 63 39 +rect 4 20 8 24 +rect 36 20 40 24 +rect 59 20 63 24 +<< ntransistor >> +rect 4 1 8 3 +rect 36 1 40 3 +rect 59 1 63 3 +<< ptransistor >> +rect 4 25 8 27 +rect 36 25 40 27 +rect 59 25 63 27 +<< psubstratepcontact >> +rect 8 -6 12 -2 +<< nsubstratencontact >> +rect 8 35 12 39 +rect 26 28 30 32 +<< labels >> +rlabel polysilicon -6 1 -6 3 7 In +rlabel pwell 38 -10 38 -10 1 Float +rlabel metal1 -5 28 -5 32 7 VBias +rlabel metal1 67 10 67 14 3 Out +rlabel polysilicon 19 11 19 11 1 Mid1 +rlabel polysilicon 50 11 50 11 1 Mid2 +rlabel metal1 -5 35 -5 39 7 Vdd#0 +rlabel metal1 -6 -6 -6 -2 7 Vss#0 +rlabel ntransistor 6 2 6 2 7 N1^ +rlabel ntransistor 38 2 38 2 7 N2^ +rlabel ntransistor 61 2 61 2 7 N3^ +rlabel ptransistor 6 26 6 26 7 P1^ +rlabel ptransistor 38 26 38 26 7 P2^ +rlabel ptransistor 61 26 61 26 7 P3^ +<< end >> diff --git a/doc/tutcells/tut8m.mag b/doc/tutcells/tut8m.mag new file mode 100644 index 00000000..39d16a86 --- /dev/null +++ b/doc/tutcells/tut8m.mag @@ -0,0 +1,41 @@ +magic +tech scmos +timestamp 539557994 +<< polysilicon >> +rect 3 35 8 37 +rect 14 35 16 37 +rect 3 24 5 35 +rect 0 22 5 24 +rect 3 9 5 22 +rect 3 7 8 9 +rect 14 7 16 9 +<< ndiffusion >> +rect 8 9 14 10 +rect 8 6 14 7 +<< pdiffusion >> +rect 8 37 14 38 +rect 8 34 14 35 +<< metal1 >> +rect 0 40 8 44 +rect 14 40 16 44 +rect 8 25 14 28 +rect 8 21 16 25 +rect 8 16 14 21 +rect 0 0 8 4 +rect 14 0 16 4 +<< ndcontact >> +rect 8 10 14 16 +rect 8 0 14 6 +<< pdcontact >> +rect 8 38 14 44 +rect 8 28 14 34 +<< ntransistor >> +rect 8 7 14 9 +<< ptransistor >> +rect 8 35 14 37 +<< labels >> +rlabel metal1 0 40 0 44 7 Vdd! +rlabel metal1 0 0 0 4 7 GND! +rlabel polysilicon 0 22 0 24 7 In +rlabel metal1 16 21 16 25 3 Out +<< end >> diff --git a/doc/tutcells/tut8n.mag b/doc/tutcells/tut8n.mag new file mode 100644 index 00000000..2ee3d0be --- /dev/null +++ b/doc/tutcells/tut8n.mag @@ -0,0 +1,20 @@ +magic +tech scmos +timestamp 539560185 +<< checkpaint >> +rect -28 -19 58 9 +<< metal1 >> +rect -16 -7 46 -3 +use tut8m left +timestamp 539557994 +transform 1 0 -16 0 1 -7 +box 0 0 16 44 +use tut8m center +timestamp 539557994 +transform 1 0 7 0 1 -7 +box 0 0 16 44 +use tut8m right +timestamp 539557994 +transform 1 0 30 0 1 -7 +box 0 0 16 44 +<< end >> diff --git a/doc/tutcells/tut8r.mag b/doc/tutcells/tut8r.mag new file mode 100644 index 00000000..7d4e9a48 --- /dev/null +++ b/doc/tutcells/tut8r.mag @@ -0,0 +1,162 @@ +magic +tech scmos +timestamp 617565736 +<< polysilicon >> +rect -95 26 -92 28 +rect -72 26 -70 28 +rect -3 26 0 28 +rect 4 26 6 28 +rect -95 2 -93 26 +rect -3 17 -1 26 +rect -72 15 -1 17 +rect -3 2 -1 15 +rect -95 0 -92 2 +rect -72 0 -70 2 +rect -3 0 0 2 +rect 4 0 8 2 +rect 6 -16 8 0 +rect -95 -18 -92 -16 +rect -72 -18 -70 -16 +rect -2 -18 0 -16 +rect 4 -18 18 -16 +rect -95 -42 -93 -18 +rect -3 -22 0 -20 +rect 4 -22 6 -20 +rect -3 -31 -1 -22 +rect -72 -33 -1 -31 +rect -3 -42 -1 -33 +rect 16 -42 18 -18 +rect -95 -44 -92 -42 +rect -72 -44 -70 -42 +rect -3 -44 0 -42 +rect 4 -44 6 -42 +rect 8 -44 10 -42 +rect 14 -44 18 -42 +<< ndiffusion >> +rect -92 2 -72 3 +rect 0 2 4 3 +rect -92 -1 -72 0 +rect 0 -1 4 0 +rect -92 -16 -72 -15 +rect 0 -16 4 -15 +rect -92 -19 -72 -18 +rect 0 -20 4 -18 +rect 0 -23 4 -22 +<< pdiffusion >> +rect -92 28 -72 29 +rect 0 28 4 29 +rect -92 25 -72 26 +rect 0 25 4 26 +rect -92 -42 -72 -41 +rect 0 -42 4 -41 +rect 10 -42 14 -41 +rect -92 -45 -72 -44 +rect 0 -45 4 -44 +rect 10 -45 14 -44 +<< metal1 >> +rect -88 34 -87 38 +rect -92 33 -87 34 +rect -1 34 0 38 +rect -5 33 0 34 +rect -76 18 -72 21 +rect -102 14 -99 18 +rect -76 7 -72 14 +rect 0 7 4 21 +rect -92 -6 -87 -5 +rect -88 -10 -87 -6 +rect -92 -11 -87 -10 +rect -5 -6 0 -5 +rect -1 -10 0 -6 +rect -5 -11 0 -10 +rect -76 -30 -72 -23 +rect -103 -34 -99 -30 +rect -76 -37 -72 -34 +rect 0 -37 4 -27 +rect 4 -41 10 -37 +rect 4 -49 10 -45 +rect -92 -50 -87 -49 +rect -88 -54 -87 -50 +rect -5 -50 0 -49 +rect -1 -54 0 -50 +<< metal2 >> +rect -104 34 -92 38 +rect -88 34 -5 38 +rect -1 34 24 38 +rect 20 -6 24 34 +rect -110 -10 -92 -6 +rect -88 -10 -5 -6 +rect -1 -10 13 -6 +rect 20 -10 28 -6 +rect 20 -50 24 -10 +rect -104 -54 -92 -50 +rect -88 -54 -5 -50 +rect -1 -54 24 -50 +<< nwell >> +rect -101 16 -70 39 +rect -14 16 17 39 +rect -101 -55 -70 -32 +rect -14 -55 17 -32 +<< polycontact >> +rect -99 14 -95 18 +rect -76 14 -72 18 +rect -99 -34 -95 -30 +rect -76 -34 -72 -30 +<< ndcontact >> +rect -92 3 -72 7 +rect 0 3 4 7 +rect -92 -5 -72 -1 +rect 0 -5 4 -1 +rect -92 -15 -72 -11 +rect 0 -15 4 -11 +rect -92 -23 -72 -19 +rect 0 -27 4 -23 +<< pdcontact >> +rect -92 29 -72 33 +rect 0 29 4 33 +rect -92 21 -72 25 +rect 0 21 4 25 +rect -92 -41 -72 -37 +rect 0 -41 4 -37 +rect 10 -41 14 -37 +rect -92 -49 -72 -45 +rect 0 -49 4 -45 +rect 10 -49 14 -45 +<< m2contact >> +rect -92 34 -88 38 +rect -5 34 -1 38 +rect -92 -10 -88 -6 +rect -5 -10 -1 -6 +rect -92 -54 -88 -50 +rect -5 -54 -1 -50 +<< ntransistor >> +rect -92 0 -72 2 +rect 0 0 4 2 +rect -92 -18 -72 -16 +rect 0 -18 4 -16 +rect 0 -22 4 -20 +<< ptransistor >> +rect -92 26 -72 28 +rect 0 26 4 28 +rect -92 -44 -72 -42 +rect 0 -44 4 -42 +rect 10 -44 14 -42 +<< psubstratepcontact >> +rect -87 -11 -83 -5 +rect 0 -11 4 -5 +<< nsubstratencontact >> +rect -87 33 -82 38 +rect 0 33 5 38 +rect -87 -54 -82 -49 +rect 0 -54 5 -49 +<< labels >> +rlabel metal2 -43 -8 -43 -8 1 GND! +rlabel metal2 -41 36 -41 36 5 Vdd! +rlabel metal2 -43 -8 -43 -8 5 GND! +rlabel metal2 -41 -52 -41 -52 1 Vdd! +rlabel polysilicon -37 -32 -37 -32 1 net2 +rlabel polysilicon -36 16 -36 16 1 net1 +rlabel metal1 -101 -32 -101 -32 3 in2 +rlabel metal1 -101 16 -101 16 3 in1 +rlabel metal1 2 12 2 12 1 out1 +rlabel metal1 2 -30 2 -30 1 out2 +<< end >> diff --git a/doc/tutcells/tut9a.mag b/doc/tutcells/tut9a.mag new file mode 100644 index 00000000..c264c675 --- /dev/null +++ b/doc/tutcells/tut9a.mag @@ -0,0 +1,49 @@ +magic +tech scmos +timestamp 502161799 +<< polysilicon >> +rect -1 15 1 20 +rect -1 9 1 11 +rect -1 -1 1 1 +rect -1 -10 1 -5 +<< ndiffusion >> +rect -2 -5 -1 -1 +rect 1 -5 2 -1 +<< pdiffusion >> +rect -2 11 -1 15 +rect 1 11 2 15 +<< metal1 >> +rect -5 7 -2 11 +rect -9 4 -2 7 +rect -5 -1 -2 4 +rect 2 7 5 11 +rect 2 4 6 7 +rect 2 -1 5 4 +<< metal2 >> +rect -10 15 6 20 +rect -10 -10 6 -5 +<< ndcontact >> +rect -6 -5 -2 -1 +rect 2 -5 6 -1 +<< pdcontact >> +rect -6 11 -2 15 +rect 2 11 6 15 +<< ntransistor >> +rect -1 -5 1 -1 +<< ptransistor >> +rect -1 11 1 15 +use tut9x tut9x_0 +timestamp 502161799 +transform 1 0 -25 0 1 6 +box -1 -16 16 14 +<< labels >> +rlabel metal2 -9 -7 -9 -7 1 GND! +rlabel metal2 -9 17 -9 17 5 Vdd! +rlabel metal1 -9 5 -9 5 1 in +rlabel metal2 6 -10 6 -5 7 GND! +rlabel metal1 6 4 6 7 7 out +rlabel metal2 6 15 6 20 7 Vdd! +rlabel metal2 6 15 6 20 3 Vdd! +rlabel metal2 -1 20 1 20 5 phibar +rlabel metal2 -1 -10 1 -10 1 phi +<< end >> diff --git a/doc/tutcells/tut9b.mag b/doc/tutcells/tut9b.mag new file mode 100644 index 00000000..8f57d42e --- /dev/null +++ b/doc/tutcells/tut9b.mag @@ -0,0 +1,11 @@ +magic +tech scmos +timestamp 502162889 +<< polycontact >> +rect 24 36 47 51 +use tut9y tut9y_0 +array 0 3 27 0 0 30 +timestamp 502162889 +transform 1 0 -17 0 1 13 +box -1 -16 26 14 +<< end >> diff --git a/doc/tutcells/tut9x.mag b/doc/tutcells/tut9x.mag new file mode 100644 index 00000000..59ed0a1e --- /dev/null +++ b/doc/tutcells/tut9x.mag @@ -0,0 +1,57 @@ +magic +tech scmos +timestamp 502161799 +<< polysilicon >> +rect 8 9 10 14 +rect 8 1 10 5 +rect 8 -7 10 -3 +rect 8 -16 10 -11 +<< ndiffusion >> +rect 7 -11 8 -7 +rect 10 -11 11 -7 +<< pdiffusion >> +rect 7 5 8 9 +rect 10 5 11 9 +<< metal1 >> +rect 2 9 6 10 +rect 15 5 16 8 +rect -1 -2 5 1 +rect 13 -7 16 5 +rect 15 -10 16 -7 +rect 2 -12 6 -11 +<< metal2 >> +rect -1 10 2 14 +rect 6 10 15 14 +rect -1 9 15 10 +rect -1 -12 15 -11 +rect -1 -16 2 -12 +rect 6 -16 15 -12 +<< polycontact >> +rect 5 -3 10 1 +<< ndcontact >> +rect 3 -11 7 -7 +rect 11 -11 15 -7 +<< pdcontact >> +rect 3 5 7 9 +rect 11 5 15 9 +<< m2contact >> +rect 2 10 6 14 +rect 2 -16 6 -12 +<< ntransistor >> +rect 8 -11 10 -7 +<< ptransistor >> +rect 8 5 10 9 +<< psubstratepcontact >> +rect -1 -11 3 -7 +<< nsubstratencontact >> +rect -1 5 3 9 +<< labels >> +rlabel metal1 15 -1 15 -1 7 out +rlabel metal2 15 11 15 11 6 Vdd! +rlabel metal2 15 -13 15 -13 8 GND! +rlabel metal1 -1 -2 -1 1 3 in +rlabel metal2 -1 9 -1 14 3 Vdd! +rlabel metal2 -1 -16 -1 -11 3 GND! +rlabel metal2 8 -16 10 -16 1 in +rlabel metal2 8 14 10 14 5 in +<< end >> diff --git a/doc/tutcells/tut9y.mag b/doc/tutcells/tut9y.mag new file mode 100644 index 00000000..85b39c91 --- /dev/null +++ b/doc/tutcells/tut9y.mag @@ -0,0 +1,59 @@ +magic +tech scmos +timestamp 502162889 +<< polysilicon >> +rect 8 9 10 14 +rect 8 1 10 5 +rect 8 -7 10 -3 +rect 8 -16 10 -11 +<< ndiffusion >> +rect 7 -11 8 -7 +rect 10 -11 11 -7 +<< pdiffusion >> +rect 7 5 8 9 +rect 10 5 11 9 +<< metal1 >> +rect 2 9 6 10 +rect 15 5 16 8 +rect 13 1 16 5 +rect -1 -2 5 1 +rect 13 -2 26 1 +rect 13 -7 16 -2 +rect 15 -10 16 -7 +rect 2 -12 6 -11 +<< metal2 >> +rect -1 10 2 14 +rect 6 10 21 14 +rect -1 9 21 10 +rect -1 -12 21 -11 +rect -1 -16 2 -12 +rect 6 -16 21 -12 +<< polycontact >> +rect 5 -3 10 1 +<< ndcontact >> +rect 3 -11 7 -7 +rect 11 -11 15 -7 +<< pdcontact >> +rect 3 5 7 9 +rect 11 5 15 9 +<< m2contact >> +rect 2 10 6 14 +rect 2 -16 6 -12 +<< ntransistor >> +rect 8 -11 10 -7 +<< ptransistor >> +rect 8 5 10 9 +<< psubstratepcontact >> +rect -1 -11 3 -7 +<< nsubstratencontact >> +rect -1 5 3 9 +<< labels >> +rlabel metal1 15 -1 15 -1 7 out +rlabel metal2 15 11 15 11 6 Vdd! +rlabel metal2 15 -13 15 -13 8 GND! +rlabel metal1 -1 -2 -1 1 3 in +rlabel metal2 -1 -16 -1 -11 3 GND! +rlabel metal2 -1 9 -1 14 3 Vdd! +rlabel metal2 8 14 10 14 5 in +rlabel metal2 8 -16 10 -16 1 in +<< end >> diff --git a/doc/tutcells/tuttcl1.cmd b/doc/tutcells/tuttcl1.cmd new file mode 100644 index 00000000..486b054c --- /dev/null +++ b/doc/tutcells/tuttcl1.cmd @@ -0,0 +1,4 @@ +# Simulation script tuttcl1.cmd +# For use with Tcl-based magic and Tcl-based IRSIM +# This script corresponds to layout tut11a.mag +# diff --git a/drc/DRCarray.c b/drc/DRCarray.c new file mode 100644 index 00000000..75039503 --- /dev/null +++ b/drc/DRCarray.c @@ -0,0 +1,387 @@ +/* + * DRCarray.c -- + * + * This file provides routines that check arrays to be sure + * there are no unpleasant interactions between adjacent + * elements. Note: the routines in this file are NOT generally + * re-entrant. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/drc/DRCarray.c,v 1.2 2009/05/01 18:59:44 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" +#include "windows/windows.h" +#include "commands/commands.h" + +/* Forward references: */ + +extern int drcArrayYankFunc(), drcArrayOverlapFunc(); + +/* Dummy DRC cookie used to pass the error message to DRC error + * routines. + */ + +static DRCCookie drcArrayCookie = { + 0, 0, 0, 0, + { 0 }, { 0 }, + 0, 0, 0, + "This layer can't abut or partially overlap between array elements", + (DRCCookie *) NULL +}; + +/* Static variables used to pass information between DRCArrayCheck + * and drcArrayFunc: + */ + +static int drcArrayCount; /* Count of number of errors found. */ +static void (*drcArrayErrorFunc)(); /* Function to call on violations. */ +static ClientData drcArrayClientData; /* Extra parameter to pass to func. */ + + +/* + * ---------------------------------------------------------------------------- + * + * drcArrayFunc -- + * + * This procedure is invoked by DBCellSrArea once for each cell + * overlapping the area being checked. If the celluse is for + * an array, then it is checked for array correctness. + * + * Results: + * Always returns 2, to skip the remaining instances in the + * current array. + * + * Side effects: + * Design rules are checked for the subcell, if it is an array, + * and the count of errors is added into drcSubCount. + * + * Design: + * To verify that an array is correct, we only have to check + * four interaction areas, shaded as A, B, C, and D in the diagram + * below. The exact size of the interaction areas depends on + * how much overlap there is. In the extreme cases, there may be + * no areas to check at all (instances widely separated), or there + * may even be areas with more than four instances overlapping + * (spacing less than half the size of the instance). + * + * --------------DDDDD------------------------------ + * | DDDDD | | + * | | | | + * | | | | + * | | | | + * ------------------------------------------------- + * | | | | + * | | | | + * | | | | + * AAAAAAAAAAAAAAAAAAA | CCC + * AAAAAAAAAAAAAAAAAAA---------------------------CCC + * AAAAAAAAAAAAAAAAAAA | CCC + * | BBBBB | | + * | BBBBB | | + * | BBBBB | | + * --------------BBBBB------------------------------ + * + * ---------------------------------------------------------------------------- + */ + +int +drcArrayFunc(scx, area) + SearchContext *scx; /* Information about the search. */ + Rect *area; /* Area in which errors are to be + * regenerated. + */ +{ + int xsep, ysep; + int xsize, ysize; + Rect errorArea, yankArea, tmp, tmp2; + CellUse *use = scx->scx_use; + struct drcClientData arg; + + if ((use->cu_xlo == use->cu_xhi) && (use->cu_ylo == use->cu_yhi)) + return 2; + + /* Set up the client data that will be passed down during + * checks for exact overlaps. + */ + + arg.dCD_celldef = DRCdef; + arg.dCD_errors = &drcArrayCount; + arg.dCD_clip = &errorArea; + arg.dCD_cptr = &drcArrayCookie; + arg.dCD_function = drcArrayErrorFunc; + arg.dCD_clientData = drcArrayClientData; + + /* Compute the sizes and separations of elements, in coordinates + * of the parend. If the array is 1-dimensional, we set the + * corresponding spacing to an impossibly large distance. + */ + + tmp.r_xbot = 0; + tmp.r_ybot = 0; + if (use->cu_xlo == use->cu_xhi) + tmp.r_xtop = DRCTechHalo + use->cu_def->cd_bbox.r_xtop + - use->cu_def->cd_bbox.r_xbot; + else tmp.r_xtop = use->cu_xsep; + if (use->cu_ylo == use->cu_yhi) + tmp.r_ytop = DRCTechHalo + use->cu_def->cd_bbox.r_ytop + - use->cu_def->cd_bbox.r_ybot; + else tmp.r_ytop = use->cu_ysep; + GeoTransRect(&use->cu_transform, &tmp, &tmp2); + xsep = tmp2.r_xtop - tmp2.r_xbot; + ysep = tmp2.r_ytop - tmp2.r_ybot; + GeoTransRect(&use->cu_transform, &use->cu_def->cd_bbox, &tmp2); + xsize = tmp2.r_xtop - tmp2.r_xbot; + ysize = tmp2.r_ytop - tmp2.r_ybot; + + /* Check each of the four areas A, B, C, and D. Remember that + * absolutely arbitrary overlaps between cells are allowed. + * Skip some or all of the areas if the cell isn't arrayed in + * that direction or if the instances are widely spaced. + */ + + if (ysep < ysize + DRCTechHalo) + { + /* A */ + + errorArea.r_xbot = use->cu_bbox.r_xbot; + errorArea.r_xtop = use->cu_bbox.r_xbot + xsize + DRCTechHalo; + errorArea.r_ybot = use->cu_bbox.r_ybot + ysep - DRCTechHalo; + errorArea.r_ytop = use->cu_bbox.r_ybot + ysize + DRCTechHalo; + GeoClip(&errorArea, area); + if (!GEO_RECTNULL(&errorArea)) + { + GEO_EXPAND(&errorArea, DRCTechHalo, &yankArea); + DBCellClearDef(DRCdef); + (void) DBArraySr(use, &yankArea, drcArrayYankFunc, + (ClientData) &yankArea); + drcArrayCount += DRCBasicCheck(DRCdef, &yankArea, &errorArea, + drcArrayErrorFunc, drcArrayClientData); + (void) DBArraySr(use, &errorArea, drcArrayOverlapFunc, + (ClientData) &arg); + } + + /* C */ + + errorArea.r_xtop = use->cu_bbox.r_xtop; + errorArea.r_xbot = use->cu_bbox.r_xtop - DRCTechHalo; + GeoClip(&errorArea, area); + if (!GEO_RECTNULL(&errorArea)) + { + GEO_EXPAND(&errorArea, DRCTechHalo, &yankArea); + DBCellClearDef(DRCdef); + (void) DBArraySr(use, &yankArea, drcArrayYankFunc, + (ClientData) &yankArea); + drcArrayCount += DRCBasicCheck(DRCdef, &yankArea, &errorArea, + drcArrayErrorFunc, drcArrayClientData); + (void) DBArraySr(use, &errorArea, drcArrayOverlapFunc, + (ClientData) &arg); + } + } + + if (xsep < xsize + DRCTechHalo) + { + /* B */ + + errorArea.r_xbot = use->cu_bbox.r_xbot + xsep - DRCTechHalo; + errorArea.r_xtop = use->cu_bbox.r_xbot + xsize + DRCTechHalo; + errorArea.r_ybot = use->cu_bbox.r_ybot; + errorArea.r_ytop = errorArea.r_ybot + ysep - DRCTechHalo; + GeoClip(&errorArea, area); + if (!GEO_RECTNULL(&errorArea)) + { + GEO_EXPAND(&errorArea, DRCTechHalo, &yankArea); + DBCellClearDef(DRCdef); + (void) DBArraySr(use, &yankArea, drcArrayYankFunc, + (ClientData) &yankArea); + drcArrayCount += DRCBasicCheck(DRCdef, &yankArea, &errorArea, + drcArrayErrorFunc, drcArrayClientData); + (void) DBArraySr(use, &errorArea, drcArrayOverlapFunc, + (ClientData) &arg); + } + + /* D */ + + errorArea.r_ytop = use->cu_bbox.r_ytop; + errorArea.r_ybot = use->cu_bbox.r_ytop - DRCTechHalo; + GeoClip(&errorArea, area); + if (!GEO_RECTNULL(&errorArea)) + { + GEO_EXPAND(&errorArea, DRCTechHalo, &yankArea); + DBCellClearDef(DRCdef); + (void) DBArraySr(use, &yankArea, drcArrayYankFunc, + (ClientData) &yankArea); + drcArrayCount += DRCBasicCheck(DRCdef, &yankArea, &errorArea, + drcArrayErrorFunc, drcArrayClientData); + (void) DBArraySr(use, &errorArea, drcArrayOverlapFunc, + (ClientData) &arg); + } + } + + return 2; +} + +/* + * ---------------------------------------------------------------------------- + * DRCArrayCheck -- + * + * This procedure finds all DRC errors in a given area of + * a given cell that stem from array formation errors in + * children of that cell. Func is called for each violation + * found. Func should have the same form as in DRCBasicCheck. + * Note: the def passed to func is the dummy DRC definition, + * and the errors are all expressed in coordinates of celluse. + * + * Results: + * The number of errors found. + * + * Side effects: + * Whatever is done by func. + * + * ---------------------------------------------------------------------------- + */ + +int +DRCArrayCheck(def, area, func, cdarg) + CellDef *def; /* Parent cell containing the arrays to + * be rechecked. + */ + Rect *area; /* Area, in def's coordinates, where all + * array violations are to be regenerated. + */ + void (*func)(); /* Function to call for each error. */ + ClientData cdarg; /* Client data to be passed to func. */ + +{ + SearchContext scx; + int oldTiles; + PaintResultType (*savedPaintTable)[NT][NT]; + PaintResultType (*savedEraseTable)[NT][NT]; + void (*savedPaintPlane)(); + + /* Use DRCDummyUse to fake up a celluse for searching purposes. */ + + DRCDummyUse->cu_def = def; + + drcArrayErrorFunc = func; + drcArrayClientData = cdarg; + drcArrayCount = 0; + oldTiles = DRCstatTiles; + + scx.scx_area = *area; + scx.scx_use = DRCDummyUse; + scx.scx_trans = GeoIdentityTransform; + + /* During array processing, switch the paint table to catch + * illegal overlaps. + */ + + savedPaintTable = DBNewPaintTable(DRCCurStyle->DRCPaintTable); + savedPaintPlane = DBNewPaintPlane(DBPaintPlaneMark); + (void) DBCellSrArea(&scx, drcArrayFunc, (ClientData) area); + (void) DBNewPaintTable(savedPaintTable); + (void) DBNewPaintPlane(savedPaintPlane); + + /* Update count of array tiles processed. */ + + DRCstatArrayTiles += DRCstatTiles - oldTiles; + return drcArrayCount; +} + + +/* + * ---------------------------------------------------------------------------- + * + * drcArrayYankFunc -- + * + * Search action function called while yanking pieces of an array. + * + * Results: + * Always returns 0, to keep the search going. + * + * Side effects: + * Yanks from an array element into the DRC yank buffer. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +drcArrayYankFunc(use, transform, x, y, yankArea) + CellUse *use; /* CellUse being array-checked. */ + Transform *transform; /* Transform from instance to parent.*/ + int x, y; /* Element indices (not used). */ + Rect *yankArea; /* Area to yank (in parent coords). */ + +{ + SearchContext scx; + Transform tinv; + + GeoInvertTrans(transform, &tinv); + GeoTransRect(&tinv, yankArea, &scx.scx_area); + scx.scx_use = use; + scx.scx_trans = *transform; + (void) DBCellCopyAllPaint(&scx, &DBAllButSpaceBits, 0, DRCuse); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcArrayOverlapFunc -- + * + * This is a search action function called while checking pieces + * of an array to be sure that there aren't any illegal partial + * overlaps. It just invokes overlap checking facilities in + * DRCsubcell.c + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * The client's error function may be invoked. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +drcArrayOverlapFunc(use, transform, x, y, arg) + CellUse *use; /* CellUse for array element. */ + Transform *transform; /* Transform from use to parent. */ + int x, y; /* Indices of element. */ + struct drcClientData *arg; /* Information used in overlap + * checking. See drcExactOverlapTile. + */ +{ + Transform tinv; + SearchContext scx; + + GeoInvertTrans(transform, &tinv); + GeoTransRect(&tinv, arg->dCD_clip, &scx.scx_area); + scx.scx_use = use; + scx.scx_trans = *transform; + (void) DBTreeSrTiles(&scx, &DRCCurStyle->DRCExactOverlapTypes, 0, + drcExactOverlapTile, (ClientData) arg); + return 0; +} diff --git a/drc/DRCbasic.c b/drc/DRCbasic.c new file mode 100644 index 00000000..97448766 --- /dev/null +++ b/drc/DRCbasic.c @@ -0,0 +1,1108 @@ +/* + * DRCbasic.c -- + * + * This file provides routines that make perform basic design-rule + * checking: given an area of a cell definition, this file will + * find all of the rule violations and call a client procedure for + * each one. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/drc/DRCbasic.c,v 1.7 2010/09/20 21:13:22 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include // for memcpy() +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" +#include "utils/signals.h" +#include "utils/maxrect.h" +#include "utils/malloc.h" + +int dbDRCDebug = 0; + +/* The following DRC cookie is used when there are tiles of type + * TT_ERROR_S found during the basic DRC. These arise during + * hierarchical checking when there are illegal overlaps. + */ + +static DRCCookie drcOverlapCookie = { + 0, 0, 0, 0, + { 0 }, { 0 }, + 0, 0, 0, + "Can't overlap those layers", + (DRCCookie *) NULL +}; + +/* Forward references: */ + +extern int areaCheck(); +extern int drcTile(); +extern MaxRectsData *drcCanonicalMaxwidth(); + +/* + *----------------------------------------------------------------------- + * + * point_to_segment + * + * Euclidean-distance point-to-segment distance (squared) + * calculation (borrowed from XCircuit) + * + * Results: + * Squared Euclidean distance of the closest approach of the + * line segment to the point (long result). + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------- + */ + +long +point_to_segment(px, py, s1x, s1y, s2x, s2y) + int px, py; /* The position of the point */ + int s1x, s1y; /* One endpoint of the line segment */ + int s2x, s2y; /* The other endpoint of the line segment */ +{ + long x, y; + long a, b, c, frac; + float protod; + + x = (long)s2x - (long)s1x; + y = (long)s2y - (long)s1y; + c = (x * x + y * y); + + x = (long)px - (long)s1x; + y = (long)py - (long)s1y; + a = (x * x + y * y); + + x = (long)px - (long)s2x; + y = (long)py - (long)s2y; + b = (x * x + y * y); + + frac = a - b; + if (frac >= c) return b; + else if (-frac >= c) return a; + else + { + protod = (float)(c + a - b); + return (a - (long)((protod * protod) / (float)(c << 2))); + } +} + +/* Define Euclidean distance checks */ + +#define RADIAL_NW 0x1000 +#define RADIAL_NE 0x8000 +#define RADIAL_SW 0x2000 +#define RADIAL_SE 0x4000 + + +/* + * ---------------------------------------------------------------------------- + * + * areaCheck -- + * + * Call the function passed down from DRCBasicCheck() if the current tile + * violates the rule in the given DRCCookie. If the rule's connectivity + * flag is set, then make sure the violating material isn't connected + * to what's on the initial side of the edge before calling the client + * error function. + * + * This function is called from DBSrPaintArea(). + * + * Results: + * Zero (so that the search will continue). + * + * Side effects: + * Applies the function passed as an argument. + * + * ---------------------------------------------------------------------------- + */ + +int +areaCheck(tile, arg) + Tile *tile; + struct drcClientData *arg; +{ + Rect rect; /* Area where error is to be recorded. */ + + TiToRect(tile, &rect); + + /* Only consider the portion of the suspicious tile that overlaps + * the clip area for errors, unless this is a trigger rule. + */ + + if (!(arg->dCD_cptr->drcc_flags & DRC_TRIGGER)) + GeoClip(&rect, arg->dCD_clip); + + GeoClip(&rect, arg->dCD_constraint); + if ((rect.r_xbot >= rect.r_xtop) || (rect.r_ybot >= rect.r_ytop)) + return 0; + + /* + * When Euclidean distance checks are enabled, check for error tiles + * outside of the perimeter of the circle in the corner extension area + * that extends "sdist" from the corner of the edge. + * + * Also check the relatively rare case where the tile is inside the + * circle perimeter, but only the corner of the triangle projects into + * the error check rectangle, and is outside of the circle. + */ + + if (arg->dCD_radial != 0) + { + unsigned int i; + int sqx, sqy; + int sdist = arg->dCD_radial & 0xfff; + long sstest, ssdist = sdist * sdist; + + if ((arg->dCD_radial & RADIAL_NW) != 0) + { + if (((sqx = arg->dCD_constraint->r_xbot + sdist + - rect.r_xtop) >= 0) && ((sqy = rect.r_ybot + - arg->dCD_constraint->r_ytop + sdist) >= 0) + && ((sqx * sqx + sqy * sqy) >= ssdist)) + return 0; + else if (IsSplit(tile) && !SplitDirection(tile) && !SplitSide(tile)) + { + sstest = point_to_segment(arg->dCD_constraint->r_xbot + sdist, + arg->dCD_constraint->r_ytop - sdist, + LEFT(tile), BOTTOM(tile), RIGHT(tile), TOP(tile)); + if (sstest > ssdist) return 0; + } + } + if ((arg->dCD_radial & RADIAL_NE) != 0) + { + if (((sqx = rect.r_xbot - arg->dCD_constraint->r_xtop + + sdist) >= 0) && ((sqy = rect.r_ybot + - arg->dCD_constraint->r_ytop + sdist) >= 0) + && ((sqx * sqx + sqy * sqy) >= ssdist)) + return 0; + else if (IsSplit(tile) && SplitDirection(tile) && SplitSide(tile)) + { + sstest = point_to_segment(arg->dCD_constraint->r_xtop - sdist, + arg->dCD_constraint->r_ytop - sdist, + LEFT(tile), TOP(tile), RIGHT(tile), BOTTOM(tile)); + if (sstest > ssdist) return 0; + } + } + if ((arg->dCD_radial & RADIAL_SW) != 0) + { + if (((sqx = arg->dCD_constraint->r_xbot + sdist + - rect.r_xtop) >= 0) && + ((sqy = arg->dCD_constraint->r_ybot + + sdist - rect.r_ytop) >= 0) + && ((sqx * sqx + sqy * sqy) >= ssdist)) + return 0; + else if (IsSplit(tile) && SplitDirection(tile) && !SplitSide(tile)) + { + sstest = point_to_segment(arg->dCD_constraint->r_xbot + sdist, + arg->dCD_constraint->r_ybot + sdist, + LEFT(tile), TOP(tile), RIGHT(tile), BOTTOM(tile)); + if (sstest > ssdist) return 0; + } + } + if ((arg->dCD_radial & RADIAL_SE) != 0) + { + if (((sqx = rect.r_xbot - arg->dCD_constraint->r_xtop + + sdist) >= 0) && + ((sqy = arg->dCD_constraint->r_ybot + + sdist - rect.r_ytop) >= 0) + && ((sqx * sqx + sqy * sqy) >= ssdist)) + return 0; + else if (IsSplit(tile) && !SplitDirection(tile) && SplitSide(tile)) + { + sstest = point_to_segment(arg->dCD_constraint->r_xtop - sdist, + arg->dCD_constraint->r_ybot + sdist, + LEFT(tile), BOTTOM(tile), RIGHT(tile), TOP(tile)); + if (sstest > ssdist) return 0; + } + } + } + + if (arg->dCD_cptr->drcc_flags & DRC_TRIGGER) + { + Rect *newrlist; + int entries = arg->dCD_entries; + + /* The following code allows the rect list to be expanded by */ + /* multiples of 8, when necessary. */ + + arg->dCD_entries++; + if (arg->dCD_rlist == NULL) + arg->dCD_rlist = (Rect *)mallocMagic(8 * sizeof(Rect)); + else if ((arg->dCD_entries & ~(entries | 7)) == arg->dCD_entries) + { + newrlist = (Rect *)mallocMagic((arg->dCD_entries << 1) * sizeof(Rect)); + memcpy((void *)newrlist, (void *)arg->dCD_rlist, (size_t)entries * + sizeof(Rect)); + freeMagic(arg->dCD_rlist); + arg->dCD_rlist = newrlist; + } + arg->dCD_rlist[arg->dCD_entries - 1] = rect; + } + else + { + (*(arg->dCD_function))(arg->dCD_celldef, &rect, arg->dCD_cptr, + arg->dCD_clientData); + (*(arg->dCD_errors))++; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCBasicCheck -- + * + * This is the top-level routine for basic design-rule checking. + * + * Results: + * Number of errors found. + * + * Side effects: + * Calls function for each design-rule violation in celldef + * that is triggered by an edge in rect and whose violation + * area falls withing clipRect. This routine makes a flat check: + * it considers only information in the paint planes of celldef, + * and does not expand children. Function should have the form: + * void + * function(def, area, rule, cdarg) + * CellDef *def; + * Rect *area; + * DRCCookie *rule; + * ClientData cdarg; + * { + * } + * + * In the call to function, def is the definition containing the + * basic area being checked, area is the actual area where a + * rule is violated, rule is the rule being violated, and cdarg + * is the client data passed through all of our routines. + * + * Note: + * If an interrupt occurs (SigInterruptPending gets set), then + * the basic will be aborted immediately. This means the check + * may be incomplete. + * + * ---------------------------------------------------------------------------- + */ + +int +DRCBasicCheck (celldef, checkRect, clipRect, function, cdata) + CellDef *celldef; /* CellDef being checked */ + Rect *checkRect; /* Check rules in this area -- usually two Haloes + * larger than the area where changes were made. + */ + Rect *clipRect; /* Clip error tiles against this area. */ + void (*function)(); /* Function to apply for each error found. */ + ClientData cdata; /* Passed to function as argument. */ +{ + struct drcClientData arg; + int errors; + int planeNum; + + if (DRCCurStyle == NULL) return 0; /* No DRC, no errors */ + + /* Insist on top quality rectangles. */ + + if ((checkRect->r_xbot >= checkRect->r_xtop) + || (checkRect->r_ybot >= checkRect->r_ytop)) + return (0); + + errors = 0; + + arg.dCD_celldef = celldef; + arg.dCD_rect = checkRect; + arg.dCD_errors = &errors; + arg.dCD_function = function; + arg.dCD_clip = clipRect; + arg.dCD_clientData = cdata; + arg.dCD_rlist = NULL; + arg.dCD_entries = 0; + + for (planeNum = PL_TECHDEPBASE; planeNum < DBNumPlanes; planeNum++) + { + arg.dCD_plane = planeNum; + DBResetTilePlane(celldef->cd_planes[planeNum], DRC_UNPROCESSED); + (void) DBSrPaintArea ((Tile *) NULL, celldef->cd_planes[planeNum], + checkRect, &DBAllTypeBits, drcTile, (ClientData) &arg); + } + drcCifCheck(&arg); + if (arg.dCD_rlist != NULL) freeMagic(arg.dCD_rlist); + return (errors); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcTile -- + * + * This is a search function invoked once for each tile in + * the area to be checked. It checks design rules along the left + * and bottom of the given tile. If the tile extends beyond the + * clipping rectangle in any direction, then the boundary on that + * side of the tile will be skipped. + * + * Results: + * Zero (so that the search will continue), unless an interrupt + * occurs, in which case 1 is returned to stop the check. + * + * Side effects: + * Calls the client's error function if errors are found. + * + * ---------------------------------------------------------------------------- + */ + +int +drcTile (tile, arg) + Tile *tile; /* Tile being examined */ + struct drcClientData *arg; +{ + DRCCookie *cptr; /* Current design rule on list */ + Rect *rect = arg->dCD_rect; /* Area being checked */ + Rect errRect; /* Area checked for an individual rule */ + MaxRectsData *mrd; /* Used by widespacing rule */ + TileTypeBitMask tmpMask, *rMask; + bool trigpending; /* Hack for widespacing rule */ + bool firsttile; + int triggered; + int cdist, dist, ccdist, result; + + arg->dCD_constraint = &errRect; + + /* + * If we were interrupted, we want to + * abort the check as quickly as possible. + */ + if (SigInterruptPending) return 1; + DRCstatTiles++; + + /* If this tile is an error tile, it arose because of an illegal + * overlap between things in adjacent cells. This means that + * there's an automatic violation over the area of the tile. + */ + + if (TiGetType(tile) == TT_ERROR_S) + { + TiToRect(tile, &errRect); + GeoClip(&errRect, rect); + (*(arg->dCD_function)) (arg->dCD_celldef, &errRect, + &drcOverlapCookie, arg->dCD_clientData); + (*(arg->dCD_errors))++; + } + + if (IsSplit(tile)) + { + /* Check rules for DRC_ANGLES rule and process */ + TileType tt = TiGetLeftType(tile); + if (tt != TT_SPACE) + { + for (cptr = DRCCurStyle->DRCRulesTbl[TT_SPACE][tt]; + cptr != (DRCCookie *) NULL; cptr = cptr->drcc_next) + if (cptr->drcc_flags & DRC_ANGLES) + { + drcCheckAngles(tile, arg, cptr); + break; + } + } + tt = TiGetRightType(tile); + if (tt != TT_SPACE) + { + for (cptr = DRCCurStyle->DRCRulesTbl[TT_SPACE][tt]; + cptr != (DRCCookie *) NULL; cptr = cptr->drcc_next) + if (cptr->drcc_flags & DRC_ANGLES) + { + drcCheckAngles(tile, arg, cptr); + break; + } + } + + /* This drc is only for the left edge of the tile */ + if (SplitSide(tile)) goto checkbottom; + } + + /* + * Check design rules along a vertical boundary between two tiles. + * + * 1 | 4 + * T + * | + * tpleft | tile + * | + * B + * 2 | 3 + * + * The labels "T" and "B" indicate pointT and pointB respectively. + * + * If a rule's direction is FORWARD, then check from left to right. + * + * * Check the top right corner if the 1x1 lambda square + * on the top left corner (1) of pointT matches the design + * rule's "corner" mask. + * + * * Check the bottom right corner if the rule says check + * BOTHCORNERS and the 1x1 lambda square on the bottom left + * corner (2) of pointB matches the design rule's "corner" mask. + * + * If a rule's direction is REVERSE, then check from right to left. + * + * * Check the bottom left corner if the 1x1 lambda square + * on the bottom right corner (3) of pointB matches the design + * rule's "corner" mask. + * + * * Check the top left corner if the rule says check BOTHCORNERS + * and the 1x1 lambda square on the top right corner (4) of + * pointT matches the design rule's "corner" mask. + */ + + if (LEFT(tile) >= rect->r_xbot) /* check tile against rect */ + { + Tile *tpleft, *tpl, *tpr; + TileType tt, to; + int edgeTop, edgeBot; + int top = MIN(TOP(tile), rect->r_ytop); + int bottom = MAX(BOTTOM(tile), rect->r_ybot); + int edgeX = LEFT(tile); + + firsttile = TRUE; + for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft)) + { + /* Get the tile types to the left and right of the edge */ + + tt = TiGetLeftType(tile); + to = TiGetRightType(tpleft); + + /* Don't check synthetic edges, i.e. edges with same type on + * both sides. Such "edges" have no physical significance, and + * depend on internal-details of how paint is spit into tiles. + * Thus checking them just leads to confusion. (When edge rules + * involving such edges are encountered during technology read-in + * the user is warned that such edges are not checked). + */ + + if (tt == to) continue; + + /* + * Go through list of design rules triggered by the + * left-to-right edge. + */ + edgeTop = MIN(TOP (tpleft), top); + edgeBot = MAX(BOTTOM(tpleft), bottom); + if (edgeTop <= edgeBot) + continue; + + triggered = 0; + for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL; + cptr = cptr->drcc_next) + { + if (cptr->drcc_flags & DRC_ANGLES) continue; + + /* Find the rule distances according to the scale factor */ + dist = cptr->drcc_dist; + cdist = cptr->drcc_cdist; + trigpending = (cptr->drcc_flags & DRC_TRIGGER) ? TRUE : FALSE; + + /* drcc_edgeplane is used to avoid checks on edges */ + /* in more than one plane */ + + if (arg->dCD_plane != cptr->drcc_edgeplane) + { + if (trigpending) cptr = cptr->drcc_next; + continue; + } + + DRCstatRules++; + + if (cptr->drcc_flags & DRC_AREA) + { + if (firsttile) + drcCheckArea(tile, arg, cptr); + continue; + } + + if ((cptr->drcc_flags & (DRC_MAXWIDTH | DRC_BENDS)) == + (DRC_MAXWIDTH | DRC_BENDS)) + { + /* New algorithm --- Tim 3/6/05 */ + Rect *lr; + int i; + + if (!trigpending) cptr->drcc_dist++; + + if (cptr->drcc_flags & DRC_REVERSE) + mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr); + else if (firsttile) + mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr); + else + mrd = NULL; + if (!trigpending) cptr->drcc_dist--; + if (trigpending) + { + if (mrd) + triggered = mrd->entries; + else + cptr = cptr->drcc_next; + } + else if (mrd) + { + for (i = 0; i < mrd->entries; i++) + { + lr = &mrd->rlist[i]; + GeoClip(lr, arg->dCD_clip); + if (!GEO_RECTNULL(lr)) + { + (*(arg->dCD_function)) (arg->dCD_celldef, + lr, cptr, arg->dCD_clientData); + (*(arg->dCD_errors))++; + } + } + } + continue; + } + else if (cptr->drcc_flags & DRC_MAXWIDTH) + { + /* bends_illegal option only */ + if (firsttile) + drcCheckMaxwidth(tile, arg, cptr); + continue; + } + else if (!triggered) mrd = NULL; + + if (cptr->drcc_flags & DRC_RECTSIZE) + { + /* only checked for bottom-left tile in a rect area */ + if (firsttile && !TTMaskHasType(&cptr->drcc_mask, + TiGetRightType(BL(tile))) && + !TTMaskHasType(&cptr->drcc_mask, + TiGetTopType(LB(tile)))) + drcCheckRectSize(tile, arg, cptr); + continue; + } + + result = 0; + arg->dCD_radial = 0; + do { + if (triggered) + { + /* For triggered rules, we want to look at the */ + /* clipped region found by the triggering rule */ + + if (mrd) + errRect = mrd->rlist[--triggered]; + else + errRect = arg->dCD_rlist[--triggered]; + errRect.r_ytop += cdist; + errRect.r_ybot -= cdist; + if (errRect.r_ytop > edgeTop) errRect.r_ytop = edgeTop; + if (errRect.r_ybot < edgeBot) errRect.r_ybot = edgeBot; + } + else + { + errRect.r_ytop = edgeTop; + errRect.r_ybot = edgeBot; + } + + if (cptr->drcc_flags & DRC_REVERSE) + { + /* + * Determine corner extensions. + */ + + /* Find the point (3) to the bottom right of pointB */ + if (BOTTOM(tile) >= errRect.r_ybot) tpr = LB(tile); + else tpr = tile; + + /* Also find point (2) to check for edge continuation */ + if (BOTTOM(tpleft) >= errRect.r_ybot) + for (tpl = LB(tpleft); RIGHT(tpl) < edgeX; tpl = TR(tpl)); + else tpl = tpleft; + + /* Make sure the edge stops at edgeBot */ + if ((TiGetTopType(tpl) != TiGetBottomType(tpleft)) || + (TiGetTopType(tpr) != TiGetBottomType(tile))) + { + if (TTMaskHasType(&cptr->drcc_corner, TiGetTopType(tpr))) + { + errRect.r_ybot -= cdist; + if (DRCEuclidean) + arg->dCD_radial |= RADIAL_SW; + } + } + + if (cptr->drcc_flags & DRC_BOTHCORNERS) + { + /* + * Check the other corner + */ + + /* Find point (4) to the top right of pointT */ + if (TOP(tile) <= errRect.r_ytop) + for (tpr = RT(tile); LEFT(tpr) > edgeX; tpr = BL(tpr)); + else tpr = tile; + + /* Also find point (1) to check for edge continuation */ + if (TOP(tpleft) <= errRect.r_ytop) tpl = RT(tpleft); + else tpl = tpleft; + + /* Make sure the edge stops at edgeTop */ + if ((TiGetBottomType(tpl) != TiGetTopType(tpleft)) || + (TiGetBottomType(tpr) != TiGetTopType(tile))) + { + if (TTMaskHasType(&cptr->drcc_corner, + TiGetBottomType(tpr))) + { + errRect.r_ytop += cdist; + if (DRCEuclidean) + arg->dCD_radial |= RADIAL_NW; + } + } + } + + /* + * Just for grins, see if we could avoid a messy search + * by looking only at tpleft. + */ + errRect.r_xbot = edgeX - dist; + if (cptr->drcc_flags & DRC_OUTSIDE) errRect.r_xbot--; + if (LEFT(tpleft) <= errRect.r_xbot + && BOTTOM(tpleft) <= errRect.r_ybot + && TOP(tpleft) >= errRect.r_ytop + && arg->dCD_plane == cptr->drcc_plane + && TTMaskHasType(&cptr->drcc_mask, + TiGetRightType(tpleft))) + continue; + + errRect.r_xtop = edgeX; + if (cptr->drcc_flags & DRC_OUTSIDE) errRect.r_xtop -= dist; + arg->dCD_initial = tile; + } + else /* FORWARD */ + { + /* + * Determine corner extensions. + */ + + /* Find the point (1) to the top left of pointT */ + if (TOP(tpleft) <= errRect.r_ytop) tpl = RT(tpleft); + else tpl = tpleft; + + /* Also find point (4) to check for edge continuation */ + if (TOP(tile) <= errRect.r_ytop) + for (tpr = RT(tile); LEFT(tpr) > edgeX; tpr = BL(tpr)); + else tpr = tile; + + /* Make sure the edge stops at edgeTop */ + if ((TiGetBottomType(tpl) != TiGetTopType(tpleft)) || + (TiGetBottomType(tpr) != TiGetTopType(tile))) + { + if (TTMaskHasType(&cptr->drcc_corner, TiGetBottomType(tpl))) + { + errRect.r_ytop += cdist; + if (DRCEuclidean) + arg->dCD_radial |= RADIAL_NE; + } + } + + if (cptr->drcc_flags & DRC_BOTHCORNERS) + { + /* + * Check the other corner + */ + + /* Find point (2) to the bottom left of pointB. */ + if (BOTTOM(tpleft) >= errRect.r_ybot) + for (tpl = LB(tpleft); RIGHT(tpl) < edgeX; tpl = TR(tpl)); + else tpl = tpleft; + + /* Also find point (3) to check for edge continuation */ + if (BOTTOM(tile) >= errRect.r_ybot) tpr = LB(tile); + else tpr = tile; + + /* Make sure the edge stops at edgeBot */ + if ((TiGetTopType(tpl) != TiGetBottomType(tpleft)) || + (TiGetTopType(tpr) != TiGetBottomType(tile))) + { + if (TTMaskHasType(&cptr->drcc_corner, TiGetTopType(tpl))) + { + errRect.r_ybot -= cdist; + if (DRCEuclidean) + arg->dCD_radial |= RADIAL_SE; + } + } + } + + /* + * Just for grins, see if we could avoid a messy search + * by looking only at tile. + */ + errRect.r_xtop = edgeX + dist; + if (cptr->drcc_flags & DRC_OUTSIDE) errRect.r_xtop++; + if (RIGHT(tile) >= errRect.r_xtop + && BOTTOM(tile) <= errRect.r_ybot + && TOP(tile) >= errRect.r_ytop + && arg->dCD_plane == cptr->drcc_plane + && TTMaskHasType(&cptr->drcc_mask, + TiGetLeftType(tile))) + continue; + + errRect.r_xbot = edgeX; + if (cptr->drcc_flags & DRC_OUTSIDE) errRect.r_xbot += dist; + arg->dCD_initial= tpleft; + } + if (arg->dCD_radial) + { + arg->dCD_radial &= 0xf000; + arg->dCD_radial |= (0xfff & cdist); + } + + DRCstatSlow++; + arg->dCD_cptr = cptr; + arg->dCD_entries = 0; + TTMaskCom2(&tmpMask, &cptr->drcc_mask); + TTMaskClearType(&tmpMask, TT_ERROR_S); + DBSrPaintArea((Tile *) NULL, + arg->dCD_celldef->cd_planes[cptr->drcc_plane], + &errRect, &tmpMask, areaCheck, (ClientData) arg); + } while (triggered); + + if (arg->dCD_entries == 0) + { + /* Trigger rule: If rule check found errors, */ + /* do the next rule. Otherwise, skip it. */ + + if (trigpending) + cptr = cptr->drcc_next; + } + else + triggered = arg->dCD_entries; + } + DRCstatEdges++; + firsttile = FALSE; + } + } + + /* This drc is only for the bottom edge of the tile */ + +checkbottom: + if (IsSplit(tile)) + if (SplitSide(tile) == SplitDirection(tile)) return 0; + + /* + * Check design rules along a horizontal boundary between two tiles. + * + * 4 tile 3 + * --L----------------R-- + * 1 tpbot 2 + * + * The labels "L" and "R" indicate pointL and pointR respectively. + * If a rule's direction is FORWARD, then check from bottom to top. + * + * * Check the top left corner if the 1x1 lambda square on the bottom + * left corner (1) of pointL matches the design rule's "corner" mask. + * + * * Check the top right corner if the rule says check BOTHCORNERS and + * the 1x1 lambda square on the bottom right (2) corner of pointR + * matches the design rule's "corner" mask. + * + * If a rule's direction is REVERSE, then check from top to bottom. + * + * * Check the bottom right corner if the 1x1 lambda square on the top + * right corner (3) of pointR matches the design rule's "corner" + * mask. + * + * * Check the bottom left corner if the rule says check BOTHCORNERS + * and the 1x1 lambda square on the top left corner (4) of pointL + * matches the design rule's "corner" mask. + */ + + if (BOTTOM(tile) >= rect->r_ybot) + { + Tile *tpbot, *tpx; + TileType tt, to; + int edgeLeft, edgeRight; + int left = MAX(LEFT(tile), rect->r_xbot); + int right = MIN(RIGHT(tile), rect->r_xtop); + int edgeY = BOTTOM(tile); + + /* Go right across bottom of tile */ + firsttile = TRUE; + for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot)) + { + /* Get the tile types to the top and bottom of the edge */ + + tt = TiGetBottomType(tile); + to = TiGetTopType(tpbot); + + /* Don't check synthetic edges, i.e. edges with same type on + * both sides. Such "edges" have no physical significance, and + * depend on internal-details of how paint is spit into tiles. + * Thus checking them just leads to confusion. (When edge rules + * involving such edges are encountered during technology readin + * the user is warned that such edges are not checked). + */ + + if (tt == to) continue; + + /* + * Check to insure that we are inside the clip area. + * Go through list of design rules triggered by the + * bottom-to-top edge. + */ + edgeLeft = MAX(LEFT(tpbot), left); + edgeRight = MIN(RIGHT(tpbot), right); + if (edgeLeft >= edgeRight) + continue; + + triggered = 0; + for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL; + cptr = cptr->drcc_next) + { + if (cptr->drcc_flags & DRC_ANGLES) continue; + + /* Find the rule distances according to the scale factor */ + dist = cptr->drcc_dist; + cdist = cptr->drcc_cdist; + trigpending = (cptr->drcc_flags & DRC_TRIGGER) ? TRUE : FALSE; + + /* drcc_edgeplane is used to avoid checks on edges */ + /* in more than one plane */ + + if (arg->dCD_plane != cptr->drcc_edgeplane) + { + if (trigpending) cptr = cptr->drcc_next; + continue; + } + + DRCstatRules++; + + /* top to bottom */ + + if ((cptr->drcc_flags & (DRC_MAXWIDTH | DRC_BENDS)) == + (DRC_MAXWIDTH | DRC_BENDS)) + { + /* New algorithm --- Tim 3/6/05 */ + Rect *lr; + int i; + + if (!trigpending) cptr->drcc_dist++; + + if (cptr->drcc_flags & DRC_REVERSE) + mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr); + else if (firsttile) + mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr); + else + mrd = NULL; + if (!trigpending) cptr->drcc_dist--; + if (trigpending) + { + if (mrd) + triggered = mrd->entries; + else + cptr = cptr->drcc_next; + } + else if (mrd) + { + for (i = 0; i < mrd->entries; i++) + { + lr = &mrd->rlist[i]; + GeoClip(lr, arg->dCD_clip); + if (!GEO_RECTNULL(lr)) + { + (*(arg->dCD_function)) (arg->dCD_celldef, + lr, cptr, arg->dCD_clientData); + (*(arg->dCD_errors))++; + } + } + } + continue; + } + else if (cptr->drcc_flags & (DRC_AREA | DRC_RECTSIZE + | DRC_MAXWIDTH)) + { + /* only have to do these checks in one direction */ + if (trigpending) cptr = cptr->drcc_next; + continue; + } + else if (!triggered) mrd = NULL; + + result = 0; + arg->dCD_radial = 0; + do { + if (triggered) + { + /* For triggered rules, we want to look at the */ + /* clipped region found by the triggering rule */ + + if (mrd) + errRect = mrd->rlist[--triggered]; + else + errRect = arg->dCD_rlist[--triggered]; + errRect.r_xtop += cdist; + errRect.r_xbot -= cdist; + if (errRect.r_xtop > edgeRight) errRect.r_xtop = edgeRight; + if (errRect.r_xbot < edgeLeft) errRect.r_xbot = edgeLeft; + } + else + { + errRect.r_xbot = edgeLeft; + errRect.r_xtop = edgeRight; + } + + if (cptr->drcc_flags & DRC_REVERSE) + { + /* + * Determine corner extensions. + * Find the point (3) to the top right of pointR + */ + if (RIGHT(tile) <= errRect.r_xtop) + for (tpx = TR(tile); BOTTOM(tpx) > edgeY; tpx = LB(tpx)); + else tpx = tile; + + if (TTMaskHasType(&cptr->drcc_corner, TiGetLeftType(tpx))) + { + errRect.r_xtop += cdist; + if (DRCEuclidean) + arg->dCD_radial |= RADIAL_SE; + } + + if (cptr->drcc_flags & DRC_BOTHCORNERS) + { + /* + * Check the other corner by finding the + * point (4) to the top left of pointL. + */ + + if (LEFT(tile) >= errRect.r_xbot) tpx = BL(tile); + else tpx = tile; + + if (TTMaskHasType(&cptr->drcc_corner, TiGetRightType(tpx))) + { + errRect.r_xbot -= cdist; + if (DRCEuclidean) + arg->dCD_radial |= RADIAL_SW; + } + } + + /* + * Just for grins, see if we could avoid + * a messy search by looking only at tpbot. + */ + errRect.r_ybot = edgeY - dist; + if (cptr->drcc_flags & DRC_OUTSIDE) errRect.r_ybot--; + if (BOTTOM(tpbot) <= errRect.r_ybot + && LEFT(tpbot) <= errRect.r_xbot + && RIGHT(tpbot) >= errRect.r_xtop + && arg->dCD_plane == cptr->drcc_plane + && TTMaskHasType(&cptr->drcc_mask, + TiGetTopType(tpbot))) + continue; + + errRect.r_ytop = edgeY; + if (cptr->drcc_flags & DRC_OUTSIDE) errRect.r_ytop -= dist; + arg->dCD_initial = tile; + } + else /* FORWARD */ + { + /* + * Determine corner extensions. + * Find the point (1) to the bottom left of pointL + */ + + if (LEFT(tpbot) >= errRect.r_xbot) + for (tpx = BL(tpbot); TOP(tpx) < edgeY; tpx = RT(tpx)); + else tpx = tpbot; + + if (TTMaskHasType(&cptr->drcc_corner, TiGetRightType(tpx))) + { + errRect.r_xbot -= cdist; + if (DRCEuclidean) + arg->dCD_radial |= RADIAL_NW; + } + + if (cptr->drcc_flags & DRC_BOTHCORNERS) + { + /* + * Check the other corner by finding the + * point (2) to the bottom right of pointR. + */ + if (RIGHT(tpbot) <= errRect.r_xtop) tpx = TR(tpbot); + else tpx = tpbot; + + if (TTMaskHasType(&cptr->drcc_corner, TiGetLeftType(tpx))) + { + errRect.r_xtop += cdist; + if (DRCEuclidean) + arg->dCD_radial |= RADIAL_NE; + } + } + + /* + * Just for grins, see if we could avoid + * a messy search by looking only at tile. + */ + errRect.r_ytop = edgeY + dist; + if (cptr->drcc_flags & DRC_OUTSIDE) errRect.r_ytop++; + if (TOP(tile) >= errRect.r_ytop + && LEFT(tile) <= errRect.r_xbot + && RIGHT(tile) >= errRect.r_xtop + && arg->dCD_plane == cptr->drcc_plane + && TTMaskHasType(&cptr->drcc_mask, + TiGetBottomType(tile))) + continue; + + errRect.r_ybot = edgeY; + if (cptr->drcc_flags & DRC_OUTSIDE) errRect.r_ybot += dist; + arg->dCD_initial = tpbot; + } + if (arg->dCD_radial) + { + arg->dCD_radial &= 0xf000; + arg->dCD_radial |= (0xfff & cdist); + } + + DRCstatSlow++; + arg->dCD_cptr = cptr; + arg->dCD_entries = 0; + TTMaskCom2(&tmpMask, &cptr->drcc_mask); + TTMaskClearType(&tmpMask, TT_ERROR_S); + DBSrPaintArea((Tile *) NULL, + arg->dCD_celldef->cd_planes[cptr->drcc_plane], + &errRect, &tmpMask, areaCheck, (ClientData) arg); + } while (triggered); + + if (arg->dCD_entries == 0) + { + /* Trigger rule: If rule check found errors, */ + /* do the next rule. Otherwise, skip it. */ + + if (trigpending) + cptr = cptr->drcc_next; + } + else + triggered = arg->dCD_entries; + } + DRCstatEdges++; + firsttile = FALSE; + } + } + return (0); +} diff --git a/drc/DRCcif.c b/drc/DRCcif.c new file mode 100644 index 00000000..6fe7321b --- /dev/null +++ b/drc/DRCcif.c @@ -0,0 +1,1425 @@ +/* + * DRCcif.c -- + * + ****************************************************************************** + * Copyright (C) 1989 Digital Equipment Corporation + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. Digital Equipment Corporation + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + **************************************************************************** + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/drc/DRCcif.c,v 1.5 2010/10/20 20:34:20 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "dbwind/dbwtech.h" +#include "drc/drc.h" +#include "cif/cif.h" +#include "cif/CIFint.h" +#include "utils/signals.h" +#include "utils/stack.h" +#include "utils/malloc.h" +#include "utils/utils.h" + +extern char *drcWhyDup(); +extern int drcCifTile(); +extern int areaCifCheck(); +extern void drcCheckCifMaxwidth(); +extern void drcCheckCifArea(); + +extern Stack *DRCstack; + +#define PUSHTILE(tp) \ + if ((tp)->ti_client == (ClientData) DRC_UNPROCESSED) { \ + (tp)->ti_client = (ClientData) DRC_PENDING; \ + STACKPUSH((ClientData) (tp), DRCstack); \ + } + +extern CIFStyle *drcCifStyle; +extern bool DRCForceReload; +TileTypeBitMask drcCifGenLayers; + +DRCCookie *drcCifRules[MAXCIFLAYERS][2]; +DRCCookie *drcCifCur=NULL; +int drcCifValid = FALSE; +int beenWarned; + +#define DRC_CIF_SPACE 0 +#define DRC_CIF_SOLID 1 + +/* + * ---------------------------------------------------------------------------- + * + * drcCifSetStyle -- + * + * Process a declaration of the cif style. + * This is of the form: + * + * cifstyle cif_style + * + * e.g, + * + * cifstyle pg + * + * Results: + * Returns 0. + * + * Side effects: + * Updates drcCifStyle. Do NOT attempt to update the CIF style + * in the middle of reading the DRC section. Instead, if the + * reported CIF style is not current, flag a warning. The DRC + * will be re-read with the CIF extensions when the CIF output + * style is changed. + * + * ---------------------------------------------------------------------------- + */ + +int +drcCifSetStyle(argc, argv) + int argc; + char *argv[]; +{ + CIFKeep *new; + + for (new = CIFStyleList; new != NULL; new = new->cs_next) + { + if (!strcmp(new->cs_name, argv[1])) + { + DRCForceReload = TRUE; + if (!strcmp(new->cs_name, CIFCurStyle->cs_name)) + drcCifStyle = CIFCurStyle; + else + { + TechError("DRC cif extensions are not enabled.\n\t" + "Use \"cif ostyle %s\" to enable them.\n", + new->cs_name); + drcCifStyle = NULL; + beenWarned = TRUE; /* post no more error messages */ + } + return 0; + } + } + TechError("Unknown DRC cifstyle %s\n",argv[1]); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * ---------------------------------------------------------------------------- + */ + +int +drcCifWarning() +{ + if (!beenWarned) + { + TechError("Missing cif style for drc\n\t" + "This message will not be repeated.\n"); + beenWarned = TRUE; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcCifWidth -- same this as drcCifWidth, except that it works on + * cif layers + * + * Results: + * Returns distance. + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcCifWidth(argc, argv) + int argc; + char *argv[]; +{ + char *layername = argv[1]; + int scalefactor; + int centidistance = atoi(argv[2]); + char *why = drcWhyDup(argv[3]); + TileTypeBitMask set, setC, tmp1; + int thislayer = -1; + DRCCookie *dpnew,*dpnext; + TileType i; + + if (drcCifStyle == NULL) + return drcCifWarning(); + + for (i = 0; i < drcCifStyle->cs_nLayers;i++) + { + CIFLayer *layer = drcCifStyle->cs_layers[i]; + + if (strcmp(layer->cl_name,layername) == 0) + { + thislayer = i; + break; + } + } + if (thislayer == -1) + { + TechError("Unknown cif layer: %s\n",layername); + return (0); + } + + scalefactor = drcCifStyle->cs_scaleFactor; + centidistance *= drcCifStyle->cs_expander; // BSI + + dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, centidistance, dpnext, &CIFSolidBits, + &CIFSolidBits, why, centidistance, + DRC_FORWARD, thislayer, 0); + drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; + + return ((centidistance+scalefactor-1)/scalefactor); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcCifSpacing -- same this as drcSpacing, except that it works on cif + * layers. + * + * Results: + * Returns distance. + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcCifSpacing(argc, argv) + int argc; + char *argv[]; +{ + char *adjacency = argv[4]; + char *why = drcWhyDup(argv[5]); + DRCCookie *dpnext, *dpnew; + int needReverse = FALSE; + TileType i, j; + int scalefactor; + int centidistance = atoi(argv[3]); + char *layers[2]; + TileType layer[2]; + TileTypeBitMask cmask; + int k; + + layers[0] = argv[1]; + layers[1] = argv[2]; + + if (drcCifStyle == NULL) + return drcCifWarning(); + + for (k=0; k!= 2;k++) + { + for (i = 0; i < drcCifStyle->cs_nLayers;i++) + { + CIFLayer *l = drcCifStyle->cs_layers[i]; + + if (strcmp(l->cl_name,layers[k]) == 0) + { + layer[k]=i; + break; + } + } + if (i == drcCifStyle->cs_nLayers || layer[k] == -1) + { + TechError("Unknown cif layer: %s",layers[k]); + return (0); + } + } + + if (strcmp (adjacency, "touching_ok") == 0) + { + /* If touching is OK, everything must fall in the same plane. */ + if (layer[0] != layer[1]) + { + TechError( + "Spacing check with touching ok must all be in one plane.\n"); + return (0); + } + cmask = DBSpaceBits; + } + else if (strcmp (adjacency, "touching_illegal") == 0) + { + cmask = DBAllTypeBits; + needReverse = TRUE; + /* nothing for now */ + } + else + { + TechError("Badly formed drc spacing line\n"); + return (0); + } + + scalefactor = drcCifStyle->cs_scaleFactor; + centidistance *= drcCifStyle->cs_expander; // BSI + dpnext = drcCifRules[layer[0]][DRC_CIF_SOLID]; + dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie)); + drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, + &cmask, why, centidistance, DRC_FORWARD, layer[1], 0); + drcCifRules[layer[0]][DRC_CIF_SOLID] = dpnew; + if (needReverse) dpnew->drcc_flags |= DRC_BOTHCORNERS; + + // Add rule in reverse direction + dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; + dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie)); + drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, + &cmask, why, centidistance, DRC_REVERSE, layer[1], 0); + drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; + + if (needReverse) + { + // This is not so much "reverse" as it is just the + // rule for b->a spacing that matches the a->b spacing. + + dpnew->drcc_flags |= DRC_BOTHCORNERS; + dpnext = drcCifRules[layer[1]][DRC_CIF_SOLID]; + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, + why, centidistance, DRC_FORWARD|DRC_BOTHCORNERS, layer[0], 0); + drcCifRules[layer[1]][DRC_CIF_SOLID] = dpnew; + + // Add rule in reverse direction + dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; + dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie)); + drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, + why, centidistance, DRC_REVERSE|DRC_BOTHCORNERS, layer[0], 0); + drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; + + if (layer[0] == layer[1]) + { + dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, + &cmask, why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS, + layer[0], 0); + drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; + + dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, + why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS, + layer[1], 0); + drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; + } + } + + if (layer[0] != layer[1]) /* make sure they don't overlap exactly */ + { + dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits, + why, scalefactor, DRC_FORWARD, layer[0], 0); + drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; + + dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits, + why, scalefactor, DRC_FORWARD, layer[1], 0); + drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; + } + + return ((centidistance+scalefactor-1)/scalefactor); +} + +/* + * ---------------------------------------------------------------------------- + * Scale CIF/DRC rules to match grid scaling. Scale by factor (n / d) + * ---------------------------------------------------------------------------- + */ + +void +drcCifScale(int n, int d) +{ + DRCCookie *dp; + int i, j; + + if (DRCCurStyle != NULL) + { + for (i = 0; i != MAXCIFLAYERS; i++) + for (j = 0; j < 2; j++) + for (dp = drcCifRules[i][j]; dp != NULL; dp = dp->drcc_next) + { + if (dp->drcc_dist != 0) + { + dp->drcc_dist *= n; + dp->drcc_dist /= d; + } + if (dp->drcc_cdist != 0) + { + dp->drcc_cdist *= n; + dp->drcc_cdist /= d; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * ---------------------------------------------------------------------------- + */ + +void +drcCifFreeStyle() +{ + DRCCookie *dp; + int i; + char *old; + + if (DRCCurStyle != NULL) + { + for (i = 0; i != MAXCIFLAYERS; i++) + { + dp = drcCifRules[i][DRC_CIF_SPACE]; + while (dp != NULL) + { + old = (char *)dp; + dp = dp->drcc_next; + freeMagic(old); + } + dp = drcCifRules[i][DRC_CIF_SOLID]; + while (dp != NULL) + { + old = (char *)dp; + dp = dp->drcc_next; + freeMagic(old); + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * ---------------------------------------------------------------------------- + */ + +void +drcCifInit() +{ + int i; + + if (drcCifValid == TRUE) + drcCifFreeStyle(); + + for (i = 0; i != MAXCIFLAYERS; i++) + { + drcCifRules[i][DRC_CIF_SPACE] = NULL; + drcCifRules[i][DRC_CIF_SOLID] = NULL; + } + drcCifValid = FALSE; + TTMaskZero(&drcCifGenLayers); + beenWarned = FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * ---------------------------------------------------------------------------- + */ + +void +drcCifFinal() +{ + int i; + + for (i = 0; i != MAXCIFLAYERS; i++) + { + DRCCookie *dp; + + for (dp = drcCifRules[i][DRC_CIF_SPACE]; dp; dp = dp->drcc_next) + { + drcCifValid = TRUE; + TTMaskSetType(&drcCifGenLayers, i); + TTMaskSetType(&drcCifGenLayers, dp->drcc_plane); + } + for (dp = drcCifRules[i][DRC_CIF_SOLID]; dp; dp = dp->drcc_next) + { + drcCifValid = TRUE; + TTMaskSetType(&drcCifGenLayers, i); + TTMaskSetType(&drcCifGenLayers, dp->drcc_plane); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * drcCifCheck--- + * + * This is the primary routine for design-rule checking on CIF layers. + * + * Results: + * None. + * + * Side effects: + * Error paint, CIF layer generation, lots of stuff going on. + * + * ---------------------------------------------------------------------------- + */ + +void +drcCifCheck(arg) + struct drcClientData *arg; +{ + Rect *checkRect = arg->dCD_rect; + Rect cifrect; + int scale; + int i,j; + int oldTiles; + + if (drcCifValid == FALSE) return; + else if (CIFCurStyle != drcCifStyle) return; + + scale = drcCifStyle->cs_scaleFactor; + cifrect = *checkRect; + cifrect.r_xbot *= scale; + cifrect.r_xtop *= scale; + cifrect.r_ybot *= scale; + cifrect.r_ytop *= scale; + arg->dCD_rect = &cifrect; + oldTiles = DRCstatTiles; + + CIFGen(arg->dCD_celldef, checkRect, CIFPlanes, &DBAllTypeBits, TRUE, TRUE); + + for (i = 0; i < drcCifStyle->cs_nLayers; i++) + { + for (j = 0; j != 2; j++) + { + for (drcCifCur = drcCifRules[i][j]; + drcCifCur; drcCifCur = drcCifCur->drcc_next) + { + TileTypeBitMask *mask; + + arg->dCD_plane = i; + DBSrPaintArea((Tile *) NULL, CIFPlanes[i], &cifrect, + (j == DRC_CIF_SOLID) ? &DBSpaceBits : &CIFSolidBits, + drcCifTile, arg); + } + } + } + arg->dCD_rect = checkRect; + DRCstatCifTiles += DRCstatTiles - oldTiles; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcCifTile -- + * + * Results: + * Zero (so that the search will continue), unless an interrupt + * occurs, in which case 1 is returned to stop the check. + * + * Side effects: + * Calls the client's error function if errors are found. + * + * ---------------------------------------------------------------------------- + */ + +int +drcCifTile (tile, arg) + Tile *tile; /* Tile being examined */ + struct drcClientData *arg; +{ + DRCCookie *cptr; /* Current design rule on list */ + Tile *tp; /* Used for corner checks */ + Rect *rect = arg->dCD_rect; /* Area being checked */ + Rect errRect; /* Area checked for an individual rule */ + TileTypeBitMask tmpMask; + + arg->dCD_constraint = &errRect; + arg->dCD_radial = 0; + + /* + * If we were interrupted, we want to + * abort the check as quickly as possible. + */ + if (SigInterruptPending) return 1; + DRCstatTiles++; + + /* + * Check design rules along a vertical boundary between two tiles. + * + * 1 | 4 + * T + * | + * tpleft | tile + * | + * B + * 2 | 3 + * + * The labels "T" and "B" indicate pointT and pointB respectively. + * + * If a rule's direction is FORWARD, then check from left to right. + * + * * Check the top right corner if the 1x1 lambda square + * on the top left corner (1) of pointT matches the design + * rule's "corner" mask. + * + * * Check the bottom right corner if the rule says check + * BOTHCORNERS and the 1x1 lambda square on the bottom left + * corner (2) of pointB matches the design rule's "corner" mask. + * + * If a rule's direction is REVERSE, then check from right to left. + * + * * Check the bottom left corner if the 1x1 lambda square + * on the bottom right corner (3) of pointB matches the design + * rule's "corner" mask. + * + * * Check the top left corner if the rule says check BOTHCORNERS + * and the 1x1 lambda square on the top right corner (4) of + * pointT matches the design rule's "corner" mask. + */ + + if (drcCifCur->drcc_flags & DRC_AREA) + { + drcCheckCifArea(tile, arg, drcCifCur); + return 0; + } + if (drcCifCur->drcc_flags & DRC_MAXWIDTH) + { + drcCheckCifMaxwidth(tile, arg, drcCifCur); + return 0; + } + if (LEFT(tile) >= rect->r_xbot) /* check tile against rect */ + { + Tile *tpleft; + int edgeTop, edgeBot; + int top = MIN(TOP(tile), rect->r_ytop); + int bottom = MAX(BOTTOM(tile), rect->r_ybot); + int edgeX = LEFT(tile); + + for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft)) + { + /* Don't check synthetic edges, i.e. edges with same type on + * both sides. Such "edges" have no physical significance, and + * depend on internal-details of how paint is spit into tiles. + * Thus checking them just leads to confusion. (When edge rules + * involving such edges are encountered during technology readin + * the user is warned that such edges are not checked). + */ + if (TiGetRightType(tpleft) == TiGetLeftType(tile)) + continue; + + /* + * Go through list of design rules triggered by the + * left-to-right edge. + */ + edgeTop = MIN(TOP (tpleft), top); + edgeBot = MAX(BOTTOM(tpleft), bottom); + if (edgeTop <= edgeBot) + continue; + + /* do this more intelligently later XXX */ + cptr = drcCifCur; + { + errRect.r_ytop = edgeTop; + errRect.r_ybot = edgeBot; + + if (cptr->drcc_flags & DRC_REVERSE) + { + /* + * Determine corner extensions. + * Find the point (3) to the bottom right of pointB + */ + for (tp = tile; BOTTOM(tp) >= errRect.r_ybot; tp = LB(tp)) + /* Nothing */; + if (TTMaskHasType(&cptr->drcc_corner, TiGetTopType(tp))) + { + errRect.r_ybot -= cptr->drcc_cdist; + if (DRCEuclidean) + arg->dCD_radial |= 0x1000; + } + + if (cptr->drcc_flags & DRC_BOTHCORNERS) + { + /* + * Check the other corner by finding the + * point (4) to the top right of pointT. + */ + if (TOP(tp = tile) <= errRect.r_ytop) + for (tp = RT(tp); LEFT(tp) > edgeX; tp = BL(tp)) + /* Nothing */; + if (TTMaskHasType(&cptr->drcc_corner, TiGetBottomType(tp))) + { + errRect.r_ytop += cptr->drcc_cdist; + if (DRCEuclidean) + arg->dCD_radial |= 0x2000; + } + } + + /* + * Just for grins, see if we could avoid a messy search + * by looking only at tpleft. + */ + errRect.r_xbot = edgeX - cptr->drcc_dist; + if (LEFT(tpleft) <= errRect.r_xbot + && BOTTOM(tpleft) <= errRect.r_ybot + && TOP(tpleft) >= errRect.r_ytop + && arg->dCD_plane == cptr->drcc_plane + && TTMaskHasType(&cptr->drcc_mask, TiGetType(tpleft))) + continue; + errRect.r_xtop = edgeX; + arg->dCD_initial = tile; + } + else /* FORWARD */ + { + /* + * Determine corner extensions. + * Find the point (1) to the top left of pointT + */ + for (tp = tpleft; TOP(tp) <= errRect.r_ytop; tp = RT(tp)) + /* Nothing */; + if (TTMaskHasType(&cptr->drcc_corner, TiGetBottomType(tp))) + { + errRect.r_ytop += cptr->drcc_cdist; + if (DRCEuclidean) + arg->dCD_radial |= 0x8000; + } + + if (cptr->drcc_flags & DRC_BOTHCORNERS) + { + /* + * Check the other corner by finding the + * point (2) to the bottom left of pointB. + */ + if (BOTTOM(tp = tpleft) >= errRect.r_ybot) + for (tp = LB(tp); RIGHT(tp) < edgeX; tp = TR(tp)) + /* Nothing */; + if (TTMaskHasType(&cptr->drcc_corner, TiGetTopType(tp))) + { + errRect.r_ybot -= cptr->drcc_cdist; + if (DRCEuclidean) + arg->dCD_radial |= 0x4000; + } + } + + /* + * Just for grins, see if we could avoid a messy search + * by looking only at tile. + */ + errRect.r_xtop = edgeX + cptr->drcc_dist; + if (RIGHT(tile) >= errRect.r_xtop + && BOTTOM(tile) <= errRect.r_ybot + && TOP(tile) >= errRect.r_ytop + && arg->dCD_plane == cptr->drcc_plane + && TTMaskHasType(&cptr->drcc_mask, TiGetLeftType(tile))) + continue; + errRect.r_xbot = edgeX; + arg->dCD_initial= tpleft; + } + if (arg->dCD_radial) + { + arg->dCD_radial &= 0xf0000; + arg->dCD_radial |= (0xfff & cptr->drcc_cdist); + } + + DRCstatSlow++; + arg->dCD_cptr = (DRCCookie *)cptr; + TTMaskCom2(&tmpMask, &cptr->drcc_mask); + (void) DBSrPaintArea((Tile *) NULL, + CIFPlanes[cptr->drcc_plane], + &errRect, &tmpMask, areaCifCheck, (ClientData) arg); + } + DRCstatEdges++; + } + } + + + /* + * Check design rules along a horizontal boundary between two tiles. + * + * 4 tile 3 + * --L----------------R-- + * 1 tpbot 2 + * + * The labels "L" and "R" indicate pointL and pointR respectively. + * If a rule's direction is FORWARD, then check from bottom to top. + * + * * Check the top left corner if the 1x1 lambda square on the bottom + * left corner (1) of pointL matches the design rule's "corner" mask. + * + * * Check the top right corner if the rule says check BOTHCORNERS and + * the 1x1 lambda square on the bottom right (2) corner of pointR + * matches the design rule's "corner" mask. + * + * If a rule's direction is REVERSE, then check from top to bottom. + * + * * Check the bottom right corner if the 1x1 lambda square on the top + * right corner (3) of pointR matches the design rule's "corner" + * mask. + * + * * Check the bottom left corner if the rule says check BOTHCORNERS + * and the 1x1 lambda square on the top left corner (4) of pointL + * matches the design rule's "corner" mask. + */ + + if (BOTTOM(tile) >= rect->r_ybot) + { + Tile *tpbot; + int edgeLeft, edgeRight; + int left = MAX(LEFT(tile), rect->r_xbot); + int right = MIN(RIGHT(tile), rect->r_xtop); + int edgeY = BOTTOM(tile); + + /* Go right across bottom of tile */ + for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot)) + { + + /* Don't check synthetic edges, i.e. edges with same type on + * both sides. Such "edges" have no physical significance, and + * depend on internal-details of how paint is spit into tiles. + * Thus checking them just leads to confusion. (When edge rules + * involving such edges are encountered during technology readin + * the user is warned that such edges are not checked). + */ + if(TiGetTopType(tpbot) == TiGetBottomType(tile)) + continue; + + /* + * Check to insure that we are inside the clip area. + * Go through list of design rules triggered by the + * bottom-to-top edge. + */ + edgeLeft = MAX(LEFT(tpbot), left); + edgeRight = MIN(RIGHT(tpbot), right); + if (edgeLeft >= edgeRight) + continue; + + cptr = drcCifCur; + { + DRCstatRules++; + errRect.r_xbot = edgeLeft; + errRect.r_xtop = edgeRight; + + /* top to bottom */ + if (cptr->drcc_flags & DRC_REVERSE) + { + /* + * Determine corner extensions. + * Find the point (3) to the top right of pointR + */ + if (RIGHT(tp = tile) <= errRect.r_xtop) + for (tp = TR(tp); BOTTOM(tp) > edgeY; tp = LB(tp)) + /* Nothing */; + if (TTMaskHasType(&cptr->drcc_corner, TiGetLeftType(tp))) + { + errRect.r_xtop += cptr->drcc_cdist; + if (DRCEuclidean) + arg->dCD_radial |= 0x4000; + } + + if (cptr->drcc_flags & DRC_BOTHCORNERS) + { + /* + * Check the other corner by finding the + * point (4) to the top left of pointL. + */ + for (tp = tile; LEFT(tp) >= errRect.r_xbot; tp = BL(tp)) + /* Nothing */; + if (TTMaskHasType(&cptr->drcc_corner, TiGetRightType(tp))) + { + errRect.r_xbot -= cptr->drcc_cdist; + if (DRCEuclidean) + arg->dCD_radial |= 0x1000; + } + } + + /* + * Just for grins, see if we could avoid + * a messy search by looking only at tpbot. + */ + errRect.r_ybot = edgeY - cptr->drcc_dist; + if (BOTTOM(tpbot) <= errRect.r_ybot + && LEFT(tpbot) <= errRect.r_xbot + && RIGHT(tpbot) >= errRect.r_xtop + && arg->dCD_plane == cptr->drcc_plane + && TTMaskHasType(&cptr->drcc_mask, TiGetTopType(tpbot))) + continue; + errRect.r_ytop = edgeY; + arg->dCD_initial = tile; + } + else /* FORWARD */ + { + /* + * Determine corner extensions. + * Find the point (1) to the bottom left of pointL + */ + if (LEFT(tp = tpbot) >= errRect.r_xbot) + for (tp = BL(tp); TOP(tp) < edgeY; tp = RT(tp)) + /* Nothing */; + + if (TTMaskHasType(&cptr->drcc_corner, TiGetRightType(tp))) + { + errRect.r_xbot -= cptr->drcc_cdist; + if (DRCEuclidean) + arg->dCD_radial |= 0x2000; + } + + if (cptr->drcc_flags & DRC_BOTHCORNERS) + { + /* + * Check the other corner by finding the + * point (2) to the bottom right of pointR. + */ + for (tp=tpbot; RIGHT(tp) <= errRect.r_xtop; tp=TR(tp)) + /* Nothing */; + if (TTMaskHasType(&cptr->drcc_corner, TiGetLeftType(tp))) + { + errRect.r_xtop += cptr->drcc_cdist; + if (DRCEuclidean) + arg->dCD_radial |= 0x8000; + } + } + + /* + * Just for grins, see if we could avoid + * a messy search by looking only at tile. + */ + errRect.r_ytop = edgeY + cptr->drcc_dist; + if (TOP(tile) >= errRect.r_ytop + && LEFT(tile) <= errRect.r_xbot + && RIGHT(tile) >= errRect.r_xtop + && arg->dCD_plane == cptr->drcc_plane + && TTMaskHasType(&cptr->drcc_mask, TiGetType(tile))) + continue; + errRect.r_ybot = edgeY; + arg->dCD_initial = tpbot; + } + if (arg->dCD_radial) + { + arg->dCD_radial &= 0xf000; + arg->dCD_radial |= (0xfff & cptr->drcc_cdist); + } + + DRCstatSlow++; + arg->dCD_cptr = (DRCCookie *)cptr; + TTMaskCom2(&tmpMask, &cptr->drcc_mask); + (void) DBSrPaintArea((Tile *) NULL, + CIFPlanes[cptr->drcc_plane], + &errRect, &tmpMask, areaCifCheck, (ClientData) arg); + } + DRCstatEdges++; + } + } + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * areaCifCheck -- + * + * Call the function passed down from DRCBasicCheck() if the current tile + * violates the rule in the given DRCCookie. If the rule's connectivity + * flag is set, then make sure the violating material isn't connected + * to what's on the initial side of the edge before calling the client + * error function. + * + * This function is called from DBSrPaintArea(). + * + * Results: + * Zero (so that the search will continue). + * + * Side effects: + * Applies the function passed as an argument. + * + * ---------------------------------------------------------------------------- + */ + +int +areaCifCheck(tile, arg) + Tile *tile; + struct drcClientData *arg; +{ + Rect rect; /* Area where error is to be recorded. */ + int scale = drcCifStyle->cs_scaleFactor; + + /* If the tile has a legal type, then return. */ + + if (TTMaskHasType(&arg->dCD_cptr->drcc_mask, TiGetType(tile))) return 0; + + /* Only consider the portion of the suspicious tile that overlaps + * the clip area for errors. + */ + + TiToRect(tile, &rect); + GeoClip(&rect, arg->dCD_constraint); + if ((rect.r_xbot >= rect.r_xtop) || (rect.r_ybot >= rect.r_ytop)) + return 0; + rect.r_xbot /= scale; + rect.r_xtop /= scale; + if (rect.r_xbot == rect.r_xtop) + { + if (rect.r_xbot < 0) rect.r_xbot--; else rect.r_xtop++; + } + rect.r_ybot /= scale; + rect.r_ytop /= scale; + if (rect.r_ybot == rect.r_ytop) + { + if (rect.r_ybot < 0) rect.r_ybot--; else rect.r_ytop++; + } + GeoClip(&rect, arg->dCD_clip); + if ((rect.r_xbot >= rect.r_xtop) || (rect.r_ybot >= rect.r_ytop)) + return 0; + + (*(arg->dCD_function)) (arg->dCD_celldef, &rect, + arg->dCD_cptr, arg->dCD_clientData); + (*(arg->dCD_errors))++; + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcCifArea -- + * + * Process an area rule. + * This is of the form: + * + * cifarea layers distance why + * + * e.g, + * + * cifarea VIA 4 "via area must be at least 4" + * + * Results: + * Returns distance. + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcCifArea(argc, argv) + int argc; + char *argv[]; +{ + char *layers = argv[1]; + int centiarea = atoi(argv[2]); + int centihorizon = atoi(argv[3]); + char *why = drcWhyDup(argv[4]); + TileTypeBitMask set, setC, tmp1; + DRCCookie *dpnext, *dpnew; + TileType i, j; + int plane; + int thislayer; + int scalefactor; + + if (drcCifStyle == NULL) + return drcCifWarning(); + + for (i = 0; i < drcCifStyle->cs_nLayers;i++) + { + CIFLayer *layer = drcCifStyle->cs_layers[i]; + + if (strcmp(layer->cl_name,layers) == 0) + { + thislayer = i; + break; + } + } + if (thislayer == -1) + { + TechError("Unknown cif layer: %s\n",layers); + return (0); + } + + scalefactor = drcCifStyle->cs_scaleFactor; + centiarea *= (drcCifStyle->cs_expander * drcCifStyle->cs_expander); + dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, centihorizon, dpnext, &CIFSolidBits, &CIFSolidBits, + why, centiarea, DRC_AREA | DRC_FORWARD, thislayer, 0); + drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; + + + return ((centihorizon+scalefactor-1)/scalefactor); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcCifMaxwidth -- cif version of drc list. + * + * Results: + * Returns distance. + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcCifMaxwidth(argc, argv) + int argc; + char *argv[]; +{ + char *layers = argv[1]; + int centidistance = atoi(argv[2]); + char *bends = argv[3]; + char *why = drcWhyDup(argv[4]); + TileTypeBitMask set, setC, tmp1; + DRCCookie *dpnext, *dpnew; + TileType i, j; + int plane; + int bend; + int thislayer; + int scalefactor; + + if (drcCifStyle == NULL) + return drcCifWarning(); + + for (i = 0; i < drcCifStyle->cs_nLayers;i++) + { + CIFLayer *layer = drcCifStyle->cs_layers[i]; + + if (strcmp(layer->cl_name,layers) == 0) + { + thislayer = i; + break; + } + } + if (thislayer == -1) + { + TechError("Unknown cif layer: %s\n",layers); + return (0); + } + + if (strcmp(bends,"bend_illegal") == 0) bend =0; + else if (strcmp(bends,"bend_ok") == 0) bend =DRC_BENDS; + else + { + TechError("unknown bend option %s\n",bends); + return (0); + } + + scalefactor = drcCifStyle->cs_scaleFactor; + centidistance *= drcCifStyle->cs_expander; // BSI + dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, centidistance, dpnext, &CIFSolidBits, &CIFSolidBits, + why, centidistance, DRC_MAXWIDTH | bend, thislayer, 0); + drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; + + + return ((centidistance+scalefactor-1)/scalefactor); +} + +/* + *------------------------------------------------------------------------- + * + * drcCifCheckArea-- + * + * checks to see that a collection of cif tiles + * have more than a minimum area. + * + * Results: + * None + * + * Side Effects: + * May cause errors to be painted. + * + *------------------------------------------------------------------------- + */ + +void +drcCheckCifArea(starttile, arg, cptr) + Tile *starttile; + struct drcClientData *arg; + DRCCookie *cptr; +{ + int arealimit = cptr->drcc_cdist; + long area = 0L; + TileTypeBitMask *oktypes = &cptr->drcc_mask; + Tile *tile,*tp; + Rect *cliprect = arg->dCD_rect; + int scale = drcCifStyle->cs_scaleFactor; + + arg->dCD_cptr = (DRCCookie *)cptr; + if (DRCstack == (Stack *) NULL) + DRCstack = StackNew(64); + + /* Mark this tile as pending and push it */ + PUSHTILE(starttile); + + while (!StackEmpty(DRCstack)) + { + tile = (Tile *) STACKPOP(DRCstack); + if (tile->ti_client != (ClientData)DRC_PENDING) continue; + area += (long)(RIGHT(tile)-LEFT(tile))*(TOP(tile)-BOTTOM(tile)); + tile->ti_client = (ClientData)DRC_PROCESSED; + /* are we at the clip boundary? If so, skip to the end */ + if (RIGHT(tile) == cliprect->r_xtop || + LEFT(tile) == cliprect->r_xbot || + BOTTOM(tile) == cliprect->r_ybot || + TOP(tile) == cliprect->r_ytop) goto forgetit; + + if (area >= (long)arealimit) goto forgetit; + + /* Top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); + + /* Left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); + + /* Bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); + + /* Right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); + } + if (area < (long)arealimit) + { + Rect rect; + TiToRect(starttile,&rect); + rect.r_xbot /= scale; + rect.r_xtop /= scale; + rect.r_ybot /= scale; + rect.r_ytop /= scale; + GeoClip(&rect, arg->dCD_clip); + if (!GEO_RECTNULL(&rect)) { + (*(arg->dCD_function)) (arg->dCD_celldef, &rect, + arg->dCD_cptr, arg->dCD_clientData); + (*(arg->dCD_errors))++; + } + + } +forgetit: + /* reset the tiles */ + starttile->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(starttile, DRCstack); + while (!StackEmpty(DRCstack)) + { + tile = (Tile *) STACKPOP(DRCstack); + + /* Top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + } +} + +/* + *------------------------------------------------------------------------- + * + * drcCheckCifMaxwidth -- + * + * Checks to see that at least one dimension of a region + * does not exceed some amount. + * + * Results: + * None. + * + * Side Effects: + * May cause errors to be painted. + * + *------------------------------------------------------------------------- + */ + +void +drcCheckCifMaxwidth(starttile,arg,cptr) + Tile *starttile; + struct drcClientData *arg; + DRCCookie *cptr; + +{ + int edgelimit = cptr->drcc_dist; + Rect boundrect; + TileTypeBitMask *oktypes = &cptr->drcc_mask; + Tile *tile,*tp; + int scale = drcCifStyle->cs_scaleFactor; + + arg->dCD_cptr = (DRCCookie *)cptr; + if (DRCstack == (Stack *) NULL) + DRCstack = StackNew(64); + + /* if bends are allowed, just check on a tile-by-tile basis that + one dimension is the max. This is pretty stupid, but it correctly + calculates the trench width rule. dcs 12.06.89 */ + if (cptr->drcc_flags & DRC_BENDS) + { + Rect rect; + TiToRect(starttile,&rect); + if (rect.r_xtop-rect.r_xbot > edgelimit && + rect.r_ytop-rect.r_ybot > edgelimit) + { + rect.r_xbot /= scale; + rect.r_xtop /= scale; + rect.r_ybot /= scale; + rect.r_ytop /= scale; + GeoClip(&rect, arg->dCD_clip); + if (!GEO_RECTNULL(&rect)) { + (*(arg->dCD_function)) (arg->dCD_celldef, &rect, + arg->dCD_cptr, arg->dCD_clientData); + (*(arg->dCD_errors))++; + } + } + return; + } + /* Mark this tile as pending and push it */ + PUSHTILE(starttile); + TiToRect(starttile,&boundrect); + + while (!StackEmpty(DRCstack)) + { + tile = (Tile *) STACKPOP(DRCstack); + if (tile->ti_client != (ClientData)DRC_PENDING) continue; + + if (boundrect.r_xbot > LEFT(tile)) boundrect.r_xbot = LEFT(tile); + if (boundrect.r_xtop < RIGHT(tile)) boundrect.r_xtop = RIGHT(tile); + if (boundrect.r_ybot > BOTTOM(tile)) boundrect.r_ybot = BOTTOM(tile); + if (boundrect.r_ytop < TOP(tile)) boundrect.r_ytop = TOP(tile); + tile->ti_client = (ClientData)DRC_PROCESSED; + + if (boundrect.r_xtop - boundrect.r_xbot > edgelimit && + boundrect.r_ytop - boundrect.r_ybot > edgelimit) break; + + /* Top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); + + /* Left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); + + /* Bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); + + /* Right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (TTMaskHasType(oktypes, TiGetType(tp))) PUSHTILE(tp); + } + + if (boundrect.r_xtop - boundrect.r_xbot > edgelimit && + boundrect.r_ytop - boundrect.r_ybot > edgelimit) + { + Rect rect; + TiToRect(starttile,&rect); + { + rect.r_xbot /= scale; + rect.r_xtop /= scale; + rect.r_ybot /= scale; + rect.r_ytop /= scale; + GeoClip(&rect, arg->dCD_clip); + if (!GEO_RECTNULL(&rect)) { + (*(arg->dCD_function)) (arg->dCD_celldef, &rect, + arg->dCD_cptr, arg->dCD_clientData); + (*(arg->dCD_errors))++; + } + } + + } + /* reset the tiles */ + starttile->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(starttile, DRCstack); + while (!StackEmpty(DRCstack)) + { + tile = (Tile *) STACKPOP(DRCstack); + + /* Top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + } +} + diff --git a/drc/DRCcontin.c b/drc/DRCcontin.c new file mode 100644 index 00000000..6365db7a --- /dev/null +++ b/drc/DRCcontin.c @@ -0,0 +1,798 @@ +/* + * DRCcontinuous.c -- + * + * This file provides the facilities for continuously keeping + * design-rule violation information up to date in Magic. It + * records areas that need to be rechecked, and provides a + * routine to perform those checks in background. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/drc/DRCcontin.c,v 1.7 2010/03/12 17:19:45 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "dbwind/dbwtech.h" +#include "utils/main.h" +#include "commands/commands.h" +#include "drc/drc.h" +#include "utils/signals.h" +#include "graphics/graphics.h" +#include "utils/undo.h" +#include "utils/malloc.h" + +#ifdef MAGIC_WRAPPER + +/* Global variable which indicates that the background checker is + * still registered as an idle process. + */ + +global unsigned char DRCStatus = DRC_NOT_RUNNING; + +#endif + +/* Global variable, settable by outside world, that enables + * and disables the background checker. If disabled, check + * tiles pile up but nothing is checked. + */ + +global unsigned char DRCBackGround = DRC_NOT_SET; + +/* Global variable, settable by outside world, that enables + * and disables Euclidean DRC checking. If enabled, magic + * computes corner-to-corner distances using a Euclidean metric. + * If disabled, magic computes corner-to-corner distances using + * a Manhattan metric. + * + * Note: should this feature be settable from the technology + * file, rather than from the command line? + */ + +global bool DRCEuclidean = FALSE; + +/* Global variable that defines the size of chunks into which + * to decompose large DRC areas. Also used to guarantee a + * canonical determination of interaction areas. May be + * set either while reading the tech file, or automatically + * when DRCInit() is called. + */ + +/*------- Things used by other DRC modules but not outside world. -------*/ + +/* Base of linked list of CellDefs waiting for background DRC. + * Can be read by outside world to see if there's any work + * to do. */ + +global DRCPendingCookie * DRCPendingRoot = (DRCPendingCookie *) NULL; + +/* Pointers to yank buffer's use and def on the heap */ + +CellDef * DRCdef = (CellDef *) NULL; +CellUse * DRCuse = (CellUse *) NULL; + +/* Boolean indicating whether DRC initialization has been done. */ + +bool DRCInitialized = FALSE; + +/* Boolean indicating whether or not check tiles are being displayed. */ + +bool DRCDisplayCheckTiles = FALSE; + +/* The following use is a dummy, provided because the DBCellCopyAll + * routine requires a cellUse, and we don't generally have one. + * As a kludge, we just keep around this dummy, with identity + * transform and no arraying, and just change the def pointer + * in it before calling DBCellCopyAll. + */ + +CellUse *DRCDummyUse = (CellUse *) NULL; + +/*------- Things used only within this module. -------*/ + +/* Layer mask for the DRC layers. */ + +TileTypeBitMask DRCLayers; + +/* In order to reduce the amount of DRC redisplay, whenever an area + * is rechecked we log all the previous violations in that area, + * XOR them with all of the new violations in the area, and only + * redisplay the bounding box of the changes. The plane and paint + * tables below are used for storing the information and doing the + * XOR. + */ + +static Plane *drcDisplayPlane; + +#define DRC_SOLID 1 + +static PaintResultType drcXorTable[] = {DRC_SOLID, TT_SPACE}; + +/* When computing DRC violations, they don't get painted directly + * into the database. Instead, they get painted first into a + * temporary plane. That way, if DRC is interrupted we can exit + * quickly without leaving error information in a weird state. + * Once everything has been computed, then it's painted into the + * cell in one fell swoop. + */ + +static Plane *drcTempPlane; + +/* Forward declarations and imports from other drc modules: */ + +extern int drcCheckTile(); +extern CellDef *DRCErrorDef; +extern TileType DRCErrorType; + + +/* + * ---------------------------------------------------------------------------- + * DRCCheckThis -- + * + * Mark an area of a CellDef so that it will be checked by continuous + * DRC. Add the CellDef to the list of Defs to be checked. If the + * pointer to the area rectangle is NULL, just add the CellDef to the + * list. + * + * Two types of check tiles (CHECKPAINT and CHECKSUBCELL) are used + * to distinguish areas of new paint in the CellDef from areas where + * subcells of the CellDef have changed. Painted areas will be + * checked for internal consistency and their interactions with + * subcells. Areas where a subcell has changed will be checked + * for interactions with paint, interactions with other subcells, and + * correct array structure (if the subcell is used as an array). + * + * Called by paint, erase and cell operations in the commands module. + * Also calls itself recursively in order to propagate check areas up + * through a hierarchy of CellDefs and CellUses. + * + * Results: + * None. + * + * Side effects: + * Modifies the PL_DRC_CHECK plane of given CellDef. The area + * recorded on the plane is one halo larger than the area modified, + * i.e. the area where errors must be regenerated. Inserts the + * CellDef into the list of Defs waiting to be checked. + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +void +DRCCheckThis (celldef, operation, area) + CellDef * celldef; /* Allows check areas to propagate + * up from EditCell. + */ + TileType operation; /* TT_CHECKPAINT or TT_CHECKSUBCELL */ + Rect * area; /* Area that changed. */ +{ + CellUse * cu; /* Ptr to uses of the given CellDef */ + Rect transRect; /* Area in coords of parent CellDefs, + * expanded if the use is in an array + */ + Rect dummyRect, dummyRect2; + DRCPendingCookie * p, ** pback; /* Used to insert new element in list + * of CellDefs waiting for DRC + */ + + /* Ignore read-only, internal, and vendor GDS cells. None of these */ + /* can contain DRC errors that could be fixed in magic. */ + + if (celldef->cd_flags & (CDVENDORGDS | CDNOEDIT | CDINTERNAL)) return; + + /* Insert celldef into list of Defs waiting to be checked, unless */ + /* it is already there. */ + + pback = &DRCPendingRoot; + p = DRCPendingRoot; + + while (p != (DRCPendingCookie *) NULL) + { + if (p->dpc_def == celldef) + { + *pback = p->dpc_next; + break; + } + pback = &(p->dpc_next); + p = p->dpc_next; + } + if (p == (DRCPendingCookie *) NULL) + { + p = (DRCPendingCookie *) mallocMagic(sizeof (DRCPendingCookie)); + p->dpc_def = celldef; + } + p->dpc_next = DRCPendingRoot; + DRCPendingRoot = p; + + /* Mark the area in this celldef (but don't worry about this stuff + * for undo purposes). Also, it's important to disable interrupts + * in here, or the paint operation could get aborted underneath us. + */ + + if (area != (Rect *) NULL) + { + GEO_EXPAND(area, DRCTechHalo, &dummyRect); + + SigDisableInterrupts(); + DBPaintPlane(celldef->cd_planes[PL_DRC_CHECK], &dummyRect, + DBStdPaintTbl(TT_CHECKPAINT, PL_DRC_CHECK), + (PaintUndoInfo *) NULL); + SigEnableInterrupts(); + + } + else return; + + /* Call recursively for each use of this + * CellDef in a parent. + */ + for (cu = celldef->cd_parents; cu != (CellUse *) NULL; cu = cu->cu_nextuse) + { + if (cu->cu_parent == (CellDef *) NULL) /* use for a Window */ + continue; + /* area in coordinates of the parent Def */ + GeoTransRect (&(cu->cu_transform), area, &transRect); + + if ((cu->cu_xlo != cu->cu_xhi) || (cu->cu_ylo != cu->cu_yhi)) + { + /* transRect needs to include all images + * of "area" in the array, in coordinates + * of the parent Def + */ + DBComputeArrayArea(area, cu, cu->cu_xhi, cu->cu_yhi, &dummyRect); + GeoTransRect(&cu->cu_transform, &dummyRect, &dummyRect2); + (void) GeoInclude (&dummyRect2, &transRect); + } + + DRCCheckThis (cu->cu_parent, TT_CHECKSUBCELL, &transRect); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * DRCRemovePending -- + * + * Remove a cell def from the DRC pending list. + * + * Results: + * None. + * + * Side effects: + * DRCPendingRoot linked list modified + * + * ---------------------------------------------------------------------------- + */ + +void +DRCRemovePending(def) + CellDef *def; +{ + DRCPendingCookie *p, *plast; + + p = DRCPendingRoot; + plast = NULL; + + while (p != NULL) + { + if (p->dpc_def == def) + { + if (plast == NULL) + DRCPendingRoot = p->dpc_next; + else + plast->dpc_next = p->dpc_next; + + freeMagic(p); + return; + } + plast = p; + p = p->dpc_next; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCInit -- + * + * This procedure initializes DRC data. It must be called after + * the technology file has been read. + * + * Results: + * None. + * + * Side effects: + * Owns shared between the DRC modules are initialized. + * + * ---------------------------------------------------------------------------- + */ + +void +DRCInit() +{ + int i; + TileTypeBitMask displayedTypes; + + /* Only do initialization once. */ + + if (DRCInitialized) return; + DRCInitialized = TRUE; + + /* Create a cell use to use for holding yank data in interaction checks. */ + + DRCdef = DBCellLookDef(DRCYANK); + if (DRCdef == (CellDef *) NULL) + { + DRCdef = DBCellNewDef (DRCYANK,(char *) NULL); + ASSERT(DRCdef != (CellDef *) NULL, "DRCInit"); + DBCellSetAvail(DRCdef); + DRCdef->cd_flags |= CDINTERNAL; + } + DRCuse = DBCellNewUse (DRCdef, (char *) NULL); + DBSetTrans (DRCuse, &GeoIdentityTransform); + DRCuse->cu_expandMask = CU_DESCEND_SPECIAL; /* This is always expanded. */ + + /* Create a dummy cell use to use for passing to procedures + * that need a use when all we've got is a def. + */ + + DRCDummyUse = DBCellNewUse(DRCdef, (char *) NULL); + DBSetTrans (DRCDummyUse, &GeoIdentityTransform); + + /* See if check tiles are being displayed. */ + + TTMaskZero(&displayedTypes); + for (i = 0; i < DBWNumStyles; i++) + TTMaskSetMask(&displayedTypes, DBWStyleToTypes(i)); + + DRCDisplayCheckTiles = TTMaskHasType(&displayedTypes, TT_CHECKPAINT) + || TTMaskHasType(&displayedTypes, TT_CHECKSUBCELL); + + /* Initialize mask of DRC layer types. */ + + TTMaskZero(&DRCLayers); + TTMaskSetType(&DRCLayers, TT_ERROR_P); + TTMaskSetType(&DRCLayers, TT_ERROR_S); + TTMaskSetType(&DRCLayers, TT_ERROR_PS); + + /* Create planes to hold error areas to redisplay and to hold + * temporary error information. + */ + + drcDisplayPlane = DBNewPlane((ClientData) TT_SPACE); + drcTempPlane = DBNewPlane((ClientData) TT_SPACE); +} + +#ifdef MAGIC_WRAPPER +/* Needs to be global so the DRCBreak() routine can use the value */ +Rect drc_orig_bbox; + +/* + * ---------------------------------------------------------------------------- + * DRCBreak -- + * + * This is called by "window" or "file" event callbacks from magic + * which would invalidate the current DRC process. This routine + * is just a copy of the exit code for DRCContinuous. Because Tcl + * doesn't have a "peek" routine for examining its event queue, we + * can only execute pending events and break the DRC process from + * the event callback code. + * This is called prior to running commands which do their own + * WindUpdate() call, so it is not necessary to call it here. + * ---------------------------------------------------------------------------- + */ + +void +DRCBreak() +{ + if (DRCHasWork && (DRCStatus == DRC_IN_PROGRESS)) + { + UndoEnable(); + + /* fprintf(stderr, "DRC breaking. . .\n"); fflush(stderr); */ + + /* As a convenience for debugging DRC stuff, we pretend the DRC + * cell is a real one and recompute its bounding box, and redisplay + * both its old area (currently in box) and its current area. + */ + + DBReComputeBbox(DRCdef); + (void) GeoInclude(&DRCdef->cd_bbox, &drc_orig_bbox); + DBWAreaChanged(DRCdef, &drc_orig_bbox, DBW_ALLWINDOWS, &DBAllButSpaceBits); + DRCStatus = DRC_BREAK_PENDING; + } +} + +#endif + +/* + * ---------------------------------------------------------------------------- + * DRCContinuous -- + * + * Called by WindDispatch() before it goes to sleep waiting for user input. + * This routine checks to see if there are any areas of the layout that + * need to be design-rule-checked. If so, it does the appropriate checks. + * This procedure will abort itself at the earliest convenient moment + * after the user types a new command. + * + * Results: + * None. + * + * Side effects: + * Modifies the DRC_CHECK and DRC_ERROR planes + * of the CellDefs on the DRCPending list. + * ---------------------------------------------------------------------------- + */ + +void +DRCContinuous() +{ +#ifndef MAGIC_WRAPPER + Rect drc_orig_bbox; /* Area of DRC def that changed. */ +#endif + + if (DRCHasWork == FALSE) + { +#ifdef MAGIC_WRAPPER + DRCStatus = DRC_NOT_RUNNING; +#endif + return; + } + +#ifdef MAGIC_WRAPPER + if (DRCStatus != DRC_NOT_RUNNING) return; /* Avoid infinitely recursive loop */ + GrFlush(); + DRCStatus = DRC_IN_PROGRESS; + Tcl_EvalEx(magicinterp, "after idle magic::drcstate busy", -1, 0); + if (TxInputRedirect != TX_INPUT_REDIRECTED) TxSetPrompt(']'); + /* fprintf(stderr, "Starting DRC\n"); fflush(stderr); */ +#endif + + UndoDisable(); /* Don't want to undo error info. */ + drc_orig_bbox = DRCdef->cd_bbox; + + while (DRCPendingRoot != (DRCPendingCookie *) NULL) + { + /* DBSrPaintArea() returns 1 if drcCheckTile() + * returns 1, meaning that a CHECK tile + * was found and processed. + */ + while ((DRCPendingRoot != (DRCPendingCookie *)NULL) && + DBSrPaintArea ((Tile *) NULL, + DRCPendingRoot->dpc_def->cd_planes [PL_DRC_CHECK], + &TiPlaneRect, &DBAllButSpaceBits, drcCheckTile, (ClientData) NULL)) + { + /* check for new user command (without blocking) */ + +#ifdef MAGIC_WRAPPER + /* Execute pending Tcl events, so the DRC process doesn't block. */ + /* NOTE: Exclude file events, or else "drc catchup" will not work */ + /* in batch mode. */ + UndoEnable(); + while (Tcl_DoOneEvent(TCL_DONT_WAIT)) + { + if (DRCStatus == DRC_BREAK_PENDING) + { + /* fprintf(stderr, "DRC exiting loop. . .\n"); fflush(stderr); */ + DRCStatus = DRC_NOT_RUNNING; + return; + } + } + UndoDisable(); + /* fprintf(stderr, "DRC continuing internally. . .\n"); fflush(stderr); */ +#else +#ifndef USE_IO_PROBE + if (SigInterruptPending) goto checkDone; +#else + if (TxGetInputEvent (FALSE, FALSE) == TRUE) goto checkDone; +#endif +#endif + } + + /* No check tiles were found, so knock this cell off the list. */ + + if (DRCPendingRoot != (DRCPendingCookie *)NULL) { + DBReComputeBbox(DRCPendingRoot->dpc_def); + freeMagic((char *) DRCPendingRoot); + DRCPendingRoot = DRCPendingRoot->dpc_next; + } + + /* Give the timestamp manager a chance to update any mismatches. */ + + DBFixMismatch(); + } + +#ifdef MAGIC_WRAPPER + DRCStatus = DRC_NOT_RUNNING; + Tcl_EvalEx(magicinterp, "after idle magic::drcstate idle", -1, 0); + /* fprintf(stderr, "DRC is finished\n"); fflush(stderr); */ + if (TxInputRedirect != TX_INPUT_REDIRECTED) TxSetPrompt('%'); +#endif + +checkDone: + + UndoEnable(); + + /* As a convenience for debugging DRC stuff, we pretend the DRC + * cell is a real one and recompute its bounding box, and redisplay + * both its old area (currently in box) and its current area. + */ + + DBReComputeBbox(DRCdef); + (void) GeoInclude(&DRCdef->cd_bbox, &drc_orig_bbox); + DBWAreaChanged(DRCdef, &drc_orig_bbox, DBW_ALLWINDOWS, &DBAllButSpaceBits); + +#ifdef MAGIC_WRAPPER + WindUpdate(); + GrFlush(); +#endif +} + + +/* + * ---------------------------------------------------------------------------- + * drcCheckTile -- + * + * This procedure is called when a check tile is found in + * the DRC_CHECK plane of the CellDef at the front of the + * DRCPending list. This procedure is the heart of Magic's + * continuous checker. + * + * For DRC purposes, each cell is divided up checkerboard-style + * into areas DRCStepSize on each side. All checking is done + * in terms of these squares. When a check tile is found, we + * find the outer area of all check tiles in the square containing + * the original check tile's lower-left corner. Errors within + * this area are regenerated, then all check tiles in that area + * are erased. The checkerboard approach serves three purposes. + * First, it allows nearby small tiles to be combined for checking + * purposes. Second, it limits the maximum amount of work that + * is done at once, so if we're getting interrupted by new commands + * there is still some hope of eventually getting the DRC caught up. + * And third, it provides a canonical form for the checks, particularly + * those involving subcells, so the same results are produced no + * matter what the original check area is. + * + * The three DRC meta-rules are: + * (1) paint in one CellDef must be consistent by itself, + * that is, without regard to subcells + * (2) subtrees must be consistent -- this includes both + * paint interacting with subcells, and subcells + * interacting with each other. + * (3) an arrayed use of a CellDef must be consistent by itself, + * that is, without regard to paint or other subcells + * in the parent. This check happens automatically as + * part of the subtree check. + * + * Two types of error tiles are kept independently in the + * DRC_ERROR plane: (1) paint + * (2) subtree + * + * This function is passed to DBSrPaintArea(). + * + * Results: + * Always returns one. This function is only called on non-space + * (CHECK) tiles, so if it is called a CHECK tile must have been + * processed and we want DBSrPaintArea to abort the search. + * + * Side effects: + * Modifies both DRC planes of the CellDef at the front of the + * DRCPending list. + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +drcCheckTile(tile, arg) + Tile * tile; /* tile in DRC_CHECK plane */ + ClientData arg; /* Not used. */ +{ + Rect square; /* Square area of the checkerboard + * being processed right now. + */ + Rect erasebox; /* erase old ERROR tiles in this + * region and clip new ERRORs to it + */ + CellDef * celldef; /* First CellDef on DRCPending list. */ + Rect redisplayArea; /* Area to be redisplayed. */ + extern int drcXorFunc(); /* Forward declarations. */ + extern int drcPutBackFunc(); + + celldef = DRCPendingRoot->dpc_def; + DRCErrorDef = celldef; + + /* Find the checkerboard square containing the lower-left corner + * of the check tile, then find all check tiles within that square. + */ + + DRCstatSquares += 1; + square.r_xbot = (LEFT(tile)/DRCStepSize) * DRCStepSize; + if (square.r_xbot > LEFT(tile)) square.r_xbot -= DRCStepSize; + square.r_ybot = (BOTTOM(tile)/DRCStepSize) * DRCStepSize; + if (square.r_ybot > BOTTOM(tile)) square.r_ybot -= DRCStepSize; + square.r_xtop = square.r_xbot + DRCStepSize; + square.r_ytop = square.r_ybot + DRCStepSize; + erasebox = GeoNullRect; + (void) DBSrPaintArea((Tile *) NULL, celldef->cd_planes[PL_DRC_CHECK], + &square, &DBAllButSpaceBits, drcIncludeArea, (ClientData) &erasebox); + GeoClip(&erasebox, &square); + + /* TxPrintf("Check area = (%d, %d) (%d, %d)\n", + erasebox.r_xbot, erasebox.r_ybot, + erasebox.r_xtop, erasebox.r_ytop); + */ + + /* Use drcDisplayPlane to save all the current errors in the + * area we're about to recheck. + */ + + DBClearPaintPlane(drcDisplayPlane); + (void) DBSrPaintArea((Tile *) NULL, celldef->cd_planes[PL_DRC_ERROR], + &square, &DBAllButSpaceBits, drcXorFunc, (ClientData) NULL); + + /* Check #1: recheck the paint of the cell, ignoring subcells. */ + + DRCErrorType = TT_ERROR_P; + DBClearPaintPlane(drcTempPlane); + + /* May 4, 2008: Moved DRCBasicCheck into DRCInteractionCheck + * to avoid requiring DRC rules to be satisfied independently + * of subcells (checkbox was [erasebox + DRCTechHalo], now + * computed within DRCInteractionCheck()). + */ + + /* DRCBasicCheck (celldef, &checkbox, &erasebox, drcPaintError, + (ClientData) drcTempPlane); */ + + /* Check #2: check interactions between paint and subcells, and + * also between subcells and other subcells. If any part of a + * square is rechecked for interactions, the whole thing has to + * be rechecked. We use TT_ERROR_S tiles for this so that we + * don't have to recheck paint and array errors over the whole + * square. + */ + + DRCErrorType = TT_ERROR_S; + (void) DRCInteractionCheck(celldef, &square, &erasebox, + drcPaintError, (ClientData) drcTempPlane); + + /* Check #3: check for array formation errors in the area. */ + + DRCErrorType = TT_ERROR_P; + (void) DRCArrayCheck(celldef, &erasebox, drcPaintError, + (ClientData) drcTempPlane); + + /* If there was an interrupt, return without modifying the cell + * at all. + */ + + if (SigInterruptPending) return 1; + + /* Erase the check tile from the check plane, erase the pre-existing + * error tiles, and paint back in the new error tiles. Do this all + * with interrupts disabled to be sure that it won't be aborted. + */ + + SigDisableInterrupts(); + + DBPaintPlane(celldef->cd_planes[PL_DRC_CHECK], &erasebox, + DBStdEraseTbl(TiGetType(tile), PL_DRC_CHECK), + (PaintUndoInfo *) NULL); + DBPaintPlane(celldef->cd_planes[PL_DRC_ERROR], &erasebox, + DBStdEraseTbl(TT_ERROR_P, PL_DRC_ERROR), + (PaintUndoInfo *) NULL); + DBPaintPlane(celldef->cd_planes[PL_DRC_ERROR], &square, + DBStdEraseTbl(TT_ERROR_S, PL_DRC_ERROR), + (PaintUndoInfo *) NULL); + (void) DBSrPaintArea((Tile *) NULL, drcTempPlane, &TiPlaneRect, + &DBAllButSpaceBits, drcPutBackFunc, (ClientData) celldef); + + /* XOR the new errors in the tile with the old errors we + * saved in drcDisplayPlane. Where information has changed, + * clip to square and redisplay. If check tiles are being + * displayed, then always redisplay the entire area. + */ + + (void) DBSrPaintArea((Tile *) NULL, celldef->cd_planes[PL_DRC_ERROR], + &square, &DBAllButSpaceBits, drcXorFunc, (ClientData) NULL); + if (DBBoundPlane(drcDisplayPlane, &redisplayArea)) + { + GeoClip(&redisplayArea, &square); + if (!GEO_RECTNULL(&redisplayArea)) + DBWAreaChanged (celldef, &redisplayArea, DBW_ALLWINDOWS, + &DRCLayers); + } + if (DRCDisplayCheckTiles) + DBWAreaChanged(celldef, &square, DBW_ALLWINDOWS, &DRCLayers); + DBCellSetModified (celldef, TRUE); + SigEnableInterrupts(); + + return (1); /* stop the area search: we modified the database! */ +} + +/* The utility function below gets called for each error tile in a + * region. It just XOR's the area of the tile into drcDisplayPlane. + */ + +int +drcXorFunc(tile) + Tile *tile; +{ + Rect area; + + TiToRect(tile, &area); + DBPaintPlane(drcDisplayPlane, &area, drcXorTable, (PaintUndoInfo *) NULL); + return 0; +} + +/* This procedure is the one that actually paints error tiles into the + * database cells. + */ + +int +drcPutBackFunc(tile, cellDef) + Tile *tile; /* Error tile, from drcTempPlane. */ + CellDef *cellDef; /* Celldef in which to paint error. */ +{ + Rect area; + + TiToRect(tile, &area); + DBPaintPlane(cellDef->cd_planes[PL_DRC_ERROR], &area, + DBStdPaintTbl(TiGetType(tile), PL_DRC_ERROR), + (PaintUndoInfo *) NULL); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcIncludeArea -- + * + * This is a drc utility procedure called by DBSrPaintArea. It + * merely computes the total area of non-space tiles in the + * given area of the plane. It is only called for non-space + * tiles. + * + * Results: + * Always returns 0 so the search continues. + * + * Side effects: + * The client data must be a pointer to a rectangle. The + * rectangle is enlarged to include the area of this tile. + * + * ---------------------------------------------------------------------------- + */ + +int +drcIncludeArea(tile, rect) + Tile *tile; + Rect *rect; /* Rectangle in which to record total area. */ +{ + Rect dum; + + TiToRect(tile, &dum); + (void) GeoInclude(&dum, rect); + return 0; +} diff --git a/drc/DRCextend.c b/drc/DRCextend.c new file mode 100644 index 00000000..5cc87601 --- /dev/null +++ b/drc/DRCextend.c @@ -0,0 +1,527 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/drc/DRCextend.c,v 1.6 2010/09/20 21:13:22 tim Exp $"; +#endif + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "dbwind/dbwtech.h" +#include "drc/drc.h" +#include "utils/signals.h" +#include "utils/stack.h" +#include "utils/maxrect.h" + +Stack *DRCstack = (Stack *)NULL; + +#define PUSHTILE(tp) \ + if ((tp)->ti_client == (ClientData) DRC_UNPROCESSED) { \ + (tp)->ti_client = (ClientData) DRC_PENDING; \ + STACKPUSH((ClientData) (tp), DRCstack); \ + } + +/* + *------------------------------------------------------------------------- + * + * drcCheckAngles --- checks whether a tile conforms to orthogonal-only + * geometry (90 degree angles only) or 45-degree geometry (x must + * be equal to y on all non-Manhattan tiles). + * + * Results: none + * + * Side Effects: may cause errors to be painted. + * + *------------------------------------------------------------------------- + */ + + +void +drcCheckAngles(tile, arg, cptr) + Tile *tile; + struct drcClientData *arg; + DRCCookie *cptr; +{ + Rect rect; + int ortho = (cptr->drcc_flags & 0x01); /* 1 = orthogonal, 0 = 45s */ + + if (IsSplit(tile)) + { + if (ortho || (RIGHT(tile) - LEFT(tile)) != (TOP(tile) - BOTTOM(tile))) + { + TiToRect(tile, &rect); + GeoClip(&rect, arg->dCD_clip); + if (!GEO_RECTNULL(&rect)) + { + arg->dCD_cptr = cptr; + (*(arg->dCD_function)) (arg->dCD_celldef, &rect, + arg->dCD_cptr, arg->dCD_clientData); + (*(arg->dCD_errors))++; + } + } + } +} + +/* + *------------------------------------------------------------------------- + * + * drcCheckArea- checks to see that a collection of tiles of a given + * type have more than a minimum area. + * + * Results: none + * + * Side Effects: may cause errors to be painted. + * + *------------------------------------------------------------------------- + */ + +void +drcCheckArea(starttile,arg,cptr) + Tile *starttile; + struct drcClientData *arg; + DRCCookie *cptr; + +{ + int arealimit; + long area = 0L; + TileTypeBitMask *oktypes = &cptr->drcc_mask; + Tile *tile,*tp; + Rect *cliprect = arg->dCD_rect; + + arealimit = cptr->drcc_cdist; + + arg->dCD_cptr = cptr; + if (DRCstack == (Stack *) NULL) + DRCstack = StackNew(64); + + /* Mark this tile as pending and push it */ + PUSHTILE(starttile); + + while (!StackEmpty(DRCstack)) + { + tile = (Tile *) STACKPOP(DRCstack); + if (tile->ti_client != (ClientData)DRC_PENDING) continue; + area += (long)(RIGHT(tile)-LEFT(tile))*(TOP(tile)-BOTTOM(tile)); + tile->ti_client = (ClientData)DRC_PROCESSED; + /* are we at the clip boundary? If so, skip to the end */ + if (RIGHT(tile) == cliprect->r_xtop || + LEFT(tile) == cliprect->r_xbot || + BOTTOM(tile) == cliprect->r_ybot || + TOP(tile) == cliprect->r_ytop) goto forgetit; + + if (area >= (long)arealimit) goto forgetit; + + /* Top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (TTMaskHasType(oktypes, TiGetBottomType(tp))) PUSHTILE(tp); + + /* Left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (TTMaskHasType(oktypes, TiGetRightType(tp))) PUSHTILE(tp); + + /* Bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (TTMaskHasType(oktypes, TiGetTopType(tp))) PUSHTILE(tp); + + /* Right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (TTMaskHasType(oktypes, TiGetLeftType(tp))) PUSHTILE(tp); + } + + if (area < (long)arealimit) + { + Rect rect; + TiToRect(starttile,&rect); + GeoClip(&rect, arg->dCD_clip); + if (!GEO_RECTNULL(&rect)) { + (*(arg->dCD_function)) (arg->dCD_celldef, &rect, + arg->dCD_cptr, arg->dCD_clientData); + /*** + DBWAreaChanged(arg->dCD_celldef,&rect, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + ***/ + (*(arg->dCD_errors))++; + } + } + +forgetit: + while (!StackEmpty(DRCstack)) tile = (Tile *) STACKPOP(DRCstack); + + /* reset the tiles */ + starttile->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(starttile, DRCstack); + while (!StackEmpty(DRCstack)) + { + tile = (Tile *) STACKPOP(DRCstack); + + /* Top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + } +} + + +/* + *------------------------------------------------------------------------- + * + * drcCheckMaxwidth - checks to see that at least one dimension of a region + * does not exceed some amount (original version---for "bends_illegal" + * option only). + * + * This should really be folded together with drcCheckArea, since the routines + * are nearly identical, but I'm feeling lazy, so I'm just duplicating + * the code for now. + * + * Results: 1 if within max bounds, 0 otherwise. + * + * Side Effects: may cause errors to be painted. + * + *------------------------------------------------------------------------- + */ + +int +drcCheckMaxwidth(starttile,arg,cptr) + Tile *starttile; + struct drcClientData *arg; + DRCCookie *cptr; +{ + int edgelimit; + int retval = 0; + Rect boundrect; + TileTypeBitMask *oktypes; + Tile *tile,*tp; + + oktypes = &cptr->drcc_mask; + edgelimit = cptr->drcc_dist; + arg->dCD_cptr = cptr; + if (DRCstack == (Stack *) NULL) + DRCstack = StackNew(64); + + /* Mark this tile as pending and push it */ + + PUSHTILE(starttile); + TiToRect(starttile,&boundrect); + + while (!StackEmpty(DRCstack)) + { + tile = (Tile *) STACKPOP(DRCstack); + if (tile->ti_client != (ClientData)DRC_PENDING) continue; + tile->ti_client = (ClientData)DRC_PROCESSED; + + if (boundrect.r_xbot > LEFT(tile)) boundrect.r_xbot = LEFT(tile); + if (boundrect.r_xtop < RIGHT(tile)) boundrect.r_xtop = RIGHT(tile); + if (boundrect.r_ybot > BOTTOM(tile)) boundrect.r_ybot = BOTTOM(tile); + if (boundrect.r_ytop < TOP(tile)) boundrect.r_ytop = TOP(tile); + + if (boundrect.r_xtop - boundrect.r_xbot > edgelimit && + boundrect.r_ytop - boundrect.r_ybot > edgelimit) + { + while (!StackEmpty(DRCstack)) tile = (Tile *) STACKPOP(DRCstack); + break; + } + + /* Top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (TTMaskHasType(oktypes, TiGetBottomType(tp))) PUSHTILE(tp); + + /* Left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (TTMaskHasType(oktypes, TiGetRightType(tp))) PUSHTILE(tp); + + /* Bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (TTMaskHasType(oktypes, TiGetTopType(tp))) PUSHTILE(tp); + + /* Right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (TTMaskHasType(oktypes, TiGetLeftType(tp))) PUSHTILE(tp); + } + + if (boundrect.r_xtop - boundrect.r_xbot > edgelimit && + boundrect.r_ytop - boundrect.r_ybot > edgelimit) + { + Rect rect; + TiToRect(starttile,&rect); + GeoClip(&rect, arg->dCD_clip); + if (!GEO_RECTNULL(&rect)) { + (*(arg->dCD_function)) (arg->dCD_celldef, &rect, + arg->dCD_cptr, arg->dCD_clientData); + (*(arg->dCD_errors))++; + retval = 1; + } + + } + + /* reset the tiles */ + starttile->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(starttile, DRCstack); + while (!StackEmpty(DRCstack)) + { + tile = (Tile *) STACKPOP(DRCstack); + + /* Top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + /* Right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (tp->ti_client != (ClientData)DRC_UNPROCESSED) + { + tp->ti_client = (ClientData)DRC_UNPROCESSED; + STACKPUSH(tp,DRCstack); + } + + } + return retval; +} + + +/* + *------------------------------------------------------------------------- + * + * drcCheckRectSize- + * + * Checks to see that a collection of tiles of given + * types have the proper size (max size and also even or odd size). + * + * Results: none + * + * Side Effects: may cause errors to be painted. + * + *------------------------------------------------------------------------- + */ + +void +drcCheckRectSize(starttile, arg, cptr) + Tile *starttile; + struct drcClientData *arg; + DRCCookie *cptr; +{ + int maxsize, even; + TileTypeBitMask *oktypes = &cptr->drcc_mask; + int width; + int height; + int errwidth; + int errheight; + Tile *t; + bool error = FALSE; + + maxsize = cptr->drcc_dist; + even = cptr->drcc_cdist; + + /* This code only has to work for rectangular regions, since we always + * check for rectangular-ness using normal edge rules produced when + * we read in the tech file. + */ + arg->dCD_cptr = cptr; + ASSERT(TTMaskHasType(oktypes, TiGetType(starttile)), "drcCheckRectSize"); + for (t = starttile; TTMaskHasType(oktypes, TiGetType(t)); t = TR(t)) + /* loop has empty body */ ; + errwidth = width = LEFT(t) - LEFT(starttile); + for (t = starttile; TTMaskHasType(oktypes, TiGetType(t)); t = RT(t)) + /* loop has empty body */ ; + errheight = height = BOTTOM(t) - BOTTOM(starttile); + ASSERT(width > 0 && height > 0, "drcCheckRectSize"); + + if (width > maxsize) {error = TRUE; errwidth = (width - maxsize);} + else if (height > maxsize) {error = TRUE; errheight = (height - maxsize);} + else if (even >= 0) { + /* meaning of "even" variable: -1, any; 0, even; 1, odd */ + if (ABS(width - ((width/2)*2)) != even) {error = TRUE; errwidth = 1;} + else if (ABS(height - ((height/2)*2)) != even) {error = TRUE; errheight = 1;} + } + + if (error) { + Rect rect; + TiToRect(starttile, &rect); + rect.r_xtop = rect.r_xbot + errwidth; + rect.r_ytop = rect.r_ybot + errheight; + GeoClip(&rect, arg->dCD_clip); + if (!GEO_RECTNULL(&rect)) { + (*(arg->dCD_function)) (arg->dCD_celldef, &rect, + arg->dCD_cptr, arg->dCD_clientData); + (*(arg->dCD_errors))++; + } + + } +} + +/* + *------------------------------------------------------------------------- + * + * drcCanonicalMaxwidth - checks to see that at least one dimension of a + * rectangular region does not exceed some amount. + * + * This differs from "CheckMaxwidth" in being more rigorous about + * determining where a region of max width might be found. There + * is no "bend" rule here. We check from the edge being observed + * and back, and adjust the bounds on the sides, forking as + * necessary to consider alternative arrangements of the interior + * rectangle. A distance "dist" is passed to the routine. We + * may push the interior rectangle back by up to this amount from + * the observed edge. For "widespacing" rules, we check all + * interior regions that satisfy maxwidth and whose edge is + * within "dist" of the original edge. For slotting requirement + * rules, "dist" is zero (inability to find a rectangle touching + * the original edge ensures that no such rectangle exists that + * can't be found touching a different edge). Also, we only + * need to check one of the four possible edge combinations + * (this part of it is handled in the drcBasic code). + * + * Results: + * LinkedRect list of areas satisfying maxwidth. There may be + * more than one rectangle, and rectangles may overlap. It + * may make more sense to return only one rectangle, the union + * of all rectangles in the list. + * + * Side Effects: + * None. + * + *------------------------------------------------------------------------- + */ + +MaxRectsData * +drcCanonicalMaxwidth(starttile, dir, arg, cptr) + Tile *starttile; + int dir; /* direction of rule */ + struct drcClientData *arg; + DRCCookie *cptr; +{ + int s, edgelimit; + Tile *tile,*tp; + TileTypeBitMask wrongtypes; + static MaxRectsData *mrd = (MaxRectsData *)NULL; + Rect *boundrect, boundorig; + + /* Generate an initial array size of 8 for rlist and swap. */ + if (mrd == (MaxRectsData *)NULL) + { + mrd = (MaxRectsData *)mallocMagic(sizeof(MaxRectsData)); + mrd->rlist = (Rect *)mallocMagic(8 * sizeof(Rect)); + mrd->swap = (Rect *)mallocMagic(8 * sizeof(Rect)); + mrd->listdepth = 8; + } + if (starttile == NULL) return mrd; + + boundrect = &(mrd->rlist[0]); + mrd->match = CLIENTDEFAULT; + + edgelimit = cptr->drcc_dist; + arg->dCD_cptr = cptr; + + TiToRect(starttile, boundrect); + + /* Determine area to be searched */ + + switch (dir) + { + case GEO_NORTH: + boundrect->r_ytop = boundrect->r_ybot; + boundrect->r_xbot -= (edgelimit - 1); + boundrect->r_xtop += (edgelimit - 1); + boundrect->r_ytop += edgelimit; + break; + + case GEO_SOUTH: + boundrect->r_ybot = boundrect->r_ytop; + boundrect->r_xbot -= (edgelimit - 1); + boundrect->r_xtop += (edgelimit - 1); + boundrect->r_ybot -= edgelimit; + break; + + case GEO_EAST: + boundrect->r_xtop = boundrect->r_xbot; + boundrect->r_ybot -= (edgelimit - 1); + boundrect->r_ytop += (edgelimit - 1); + boundrect->r_xtop += edgelimit; + break; + + case GEO_WEST: + boundrect->r_xbot = boundrect->r_xtop; + boundrect->r_ybot -= (edgelimit - 1); + boundrect->r_ytop += (edgelimit - 1); + boundrect->r_xbot -= edgelimit; + break; + + case GEO_CENTER: + boundrect->r_xbot -= edgelimit; + boundrect->r_xtop += edgelimit; + boundrect->r_ybot -= edgelimit; + boundrect->r_ytop += edgelimit; + break; + } + + /* Do an area search on boundrect to find all materials not */ + /* in oktypes. Each such tile clips or subdivides */ + /* boundrect. Any rectangles remaining after the search */ + /* satisfy the maxwidth rule. */ + + mrd->entries = 1; + mrd->maxdist = edgelimit; + TTMaskCom2(&wrongtypes, &cptr->drcc_mask); + boundorig = *boundrect; + DBSrPaintArea(starttile, arg->dCD_celldef->cd_planes[cptr->drcc_plane], + &boundorig, &wrongtypes, FindMaxRects, mrd); + if (mrd->entries == 0) + return NULL; + else + return (MaxRectsData *)mrd; +} + diff --git a/drc/DRCmain.c b/drc/DRCmain.c new file mode 100644 index 00000000..88702e04 --- /dev/null +++ b/drc/DRCmain.c @@ -0,0 +1,921 @@ +/* + * DRCmain.c -- + * + * This file provides global routines that are invoked at + * command-level. They do things like give information about + * errors and print statistics. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/drc/DRCmain.c,v 1.4 2010/06/24 12:37:16 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "drc/drc.h" +#include "utils/undo.h" + +/* The global variables defined below are parameters between + * the DRC error routines (drcPaintError and drcPrintError) + * and the higher-level routines that start up DRC error checks. + * It seemed simpler to do the communication this way rather + * than creating a special new record that is passed down as + * ClientData. Any routine invoking DRCBasicCheck with drcPaintError + * or drcPrintError as action routine should fill in the relevant + * variables. + */ + +/* The following points to a list of all the DRC styles currently + * understood: + */ + +DRCKeep *DRCStyleList = NULL; + +DRCStyle *DRCCurStyle = NULL; + +/* Used by both routines: */ + +int DRCErrorCount; /* Incremented by each call to either routine. + */ + +/* Used by drcPaintError: */ + +CellDef *DRCErrorDef; /* Place to paint error tiles. */ +TileType DRCErrorType; /* Type of error tile to paint. */ + +/* Used by drcPrintError: */ + +HashTable DRCErrorTable; /* Hash table used to eliminate duplicate + * error strings. + */ + +/* Global variables used by all DRC modules to record statistics. + * For each statistic we keep two values, the count since stats + * were last printed (in DRCstatXXX), and the total count (in + * drcTotalXXX). + */ + +int DRCstatSquares = 0; /* Number of DRCStepSize-by-DRCStepSize + * squares processed by continuous checker. + */ +int DRCstatTiles = 0; /* Number of tiles processed by basic + * checker. + */ +int DRCstatEdges = 0; /* Number of "atomic" edges processed + * by basic checker. + */ +int DRCstatRules = 0; /* Number of rules processed by basic checker + * (rule = one constraint for one edge). + */ +int DRCstatSlow = 0; /* Number of places where constraint doesn't + * all fall in a single tile. + */ +int DRCstatInteractions = 0; /* Number of times drcInt is called to check + * an interaction area. + */ +int DRCstatIntTiles = 0; /* Number of tiles processed as part of + * subcell interaction checks. + */ +int DRCstatCifTiles = 0; /* Number of tiles processed as part of + * cif checks. + */ +int DRCstatArrayTiles = 0; /* Number of tiles processed as part of + * array interaction checks. + */ + +#ifdef DRCRULESHISTO +int DRCstatVRulesHisto[DRC_MAXRULESHISTO]; +int DRCstatHRulesHisto[DRC_MAXRULESHISTO]; +#endif /* DRCRULESHISTO */ + +static int drcTotalSquares = 0; +static int drcTotalTiles = 0; +static int drcTotalEdges = 0; +static int drcTotalRules = 0; +static int drcTotalSlow = 0; +static int drcTotalInteractions = 0; +static int drcTotalIntTiles = 0; +static int drcTotalArrayTiles = 0; + +#ifdef DRCRULESHISTO +static int drcTotalVRulesHisto[DRC_MAXRULESHISTO]; +static int drcTotalHRulesHisto[DRC_MAXRULESHISTO]; +#endif /* DRCRULESHISTO */ + + +/* + * ---------------------------------------------------------------------------- + * drcPaintError -- + * + * Action function that paints error tiles for each violation found. + * + * Results: + * None. + * + * Side effects: + * A tile of type DRCErrorType is painted over the area of + * the error, in the plane given by "plane". Also, DRCErrorCount + * is incremented. + * ---------------------------------------------------------------------------- + */ + +void +drcPaintError(celldef, rect, cptr, plane) + CellDef * celldef; /* CellDef being checked */ + Rect * rect; /* Area of error */ + DRCCookie * cptr; /* Design rule violated -- not used */ + Plane * plane; /* Where to paint error tiles. */ +{ + PaintUndoInfo ui; + + ui.pu_def = celldef; + ui.pu_pNum = PL_DRC_ERROR; + DBPaintPlane(plane, rect, DBStdPaintTbl(DRCErrorType, + PL_DRC_ERROR), &ui); + DRCErrorCount += 1; +} + + +/* + * ---------------------------------------------------------------------------- + * drcPrintError -- + * + * Action function that prints the error message associated with each + * violation found. + * + * Results: + * None. + * + * Side effects: + * DRCErrorCount is incremented. The text associated with + * the error is entered into DRCErrorTable, and, if this is + * the first time that entry has been seen, then the error + * text is printed. If the area parameter is non-NULL, then + * only errors intersecting that area are considered. + * ---------------------------------------------------------------------------- + */ + +void +drcPrintError (celldef, rect, cptr, scx) + CellDef * celldef; /* CellDef being checked -- not used here */ + Rect * rect; /* Area of error */ + DRCCookie * cptr; /* Design rule violated */ + SearchContext * scx; /* Only errors in scx->scx_area get reported. */ +{ + HashEntry *h; + int i; + Rect *area, r; + + ASSERT (cptr != (DRCCookie *) NULL, "drcPrintError"); + + area = &scx->scx_area; + if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return; + DRCErrorCount += 1; + h = HashFind(&DRCErrorTable, cptr->drcc_why); + i = (spointertype) HashGetValue(h); + if (i == 0) + TxPrintf("%s\n", cptr->drcc_why); + i += 1; + HashSetValue(h, (spointertype)i); +} + +/* Same routine as above, but output goes to a Tcl list and is appended */ +/* to the interpreter result. */ + +#ifdef MAGIC_WRAPPER + +void +drcListError (celldef, rect, cptr, scx) + CellDef * celldef; /* CellDef being checked -- not used here */ + Rect * rect; /* Area of error */ + DRCCookie * cptr; /* Design rule violated */ + SearchContext * scx; /* Only errors in scx->scx_area get reported */ +{ + HashEntry *h; + int i; + Rect *area; + + ASSERT (cptr != (DRCCookie *) NULL, "drcListError"); + + area = &scx->scx_area; + if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return; + DRCErrorCount += 1; + h = HashFind(&DRCErrorTable, cptr->drcc_why); + i = (spointertype) HashGetValue(h); + if (i == 0) + { + Tcl_Obj *lobj; + lobj = Tcl_GetObjResult(magicinterp); + Tcl_ListObjAppendElement(magicinterp, lobj, + Tcl_NewStringObj(cptr->drcc_why, -1)); + Tcl_SetObjResult(magicinterp, lobj); + } + i += 1; + HashSetValue(h, (spointertype)i); +} + +/* Same routine as above, but output for every single error is recorded */ +/* along with position information. */ + +void +drcListallError (celldef, rect, cptr, scx) + CellDef * celldef; /* CellDef being checked -- not used here */ + Rect * rect; /* Area of error */ + DRCCookie * cptr; /* Design rule violated */ + SearchContext * scx; /* Only errors in scx->scx_area get reported. */ +{ + Tcl_Obj *lobj, *pobj; + HashEntry *h; + Rect *area, r; + + ASSERT (cptr != (DRCCookie *) NULL, "drcListallError"); + + // Report in top-level coordinates + GeoTransRect(&scx->scx_trans, rect, &r); + area = &scx->scx_area; + if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return; + DRCErrorCount += 1; + h = HashFind(&DRCErrorTable, cptr->drcc_why); + lobj = (Tcl_Obj *) HashGetValue(h); + if (lobj == NULL) + lobj = Tcl_NewListObj(0, NULL); + + pobj = Tcl_NewListObj(0, NULL); + + Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xbot)); + Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ybot)); + Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xtop)); + Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ytop)); + Tcl_ListObjAppendElement(magicinterp, lobj, pobj); + + HashSetValue(h, lobj); +} + +#else + +#define drcListError drcPrintError + +#endif + +/* + * ---------------------------------------------------------------------------- + * + * DRCPrintStats -- + * + * Prints out statistics gathered by the DRC checking routines. + * + * Results: + * None. + * + * Side effects: + * Statistics are printed. Two values are printed for each + * statistic: the number since statistics were last printed, + * and the total to date. The own variables used to keep + * track of statistics are updated. + * + * ---------------------------------------------------------------------------- + */ + +void +DRCPrintStats() +{ +#ifdef DRCRULESHISTO + int n; +#endif /* DRCRULESHISTO */ + + TxPrintf("Design-rule checker statistics (recent/total):\n"); + drcTotalSquares += DRCstatSquares; + TxPrintf(" Squares processed: %d/%d\n", DRCstatSquares, + drcTotalSquares); + DRCstatSquares = 0; + drcTotalTiles += DRCstatTiles; + TxPrintf(" Tiles processed: %d/%d\n", DRCstatTiles, drcTotalTiles); + DRCstatTiles = 0; + drcTotalEdges += DRCstatEdges; + TxPrintf(" Edges pieces processed: %d/%d\n", DRCstatEdges, + drcTotalEdges); + DRCstatEdges = 0; + drcTotalRules += DRCstatRules; + TxPrintf(" Constraint areas checked: %d/%d\n", DRCstatRules, + drcTotalRules); + DRCstatRules = 0; + drcTotalSlow += DRCstatSlow; + TxPrintf(" Multi-tile constraints: %d/%d\n", DRCstatSlow, + drcTotalSlow); + DRCstatSlow = 0; + drcTotalInteractions += DRCstatInteractions; + TxPrintf(" Interaction areas processed: %d/%d\n", + DRCstatInteractions, drcTotalInteractions); + DRCstatInteractions = 0; + drcTotalIntTiles += DRCstatIntTiles; + TxPrintf(" Tiles processed for interactions: %d/%d\n", + DRCstatIntTiles, drcTotalIntTiles); + DRCstatIntTiles = 0; + drcTotalArrayTiles += DRCstatArrayTiles; + TxPrintf(" Tiles processed for arrays: %d/%d\n", + DRCstatArrayTiles, drcTotalArrayTiles); + DRCstatArrayTiles = 0; + +#ifdef DRCRULESHISTO + TxPrintf(" Number of rules applied per edge:\n"); + TxPrintf(" # rules Horiz freq Vert freq\n"); + for (n = 0; n < DRC_MAXRULESHISTO; n++) + { + drcTotalHRulesHisto[n] += DRCstatHRulesHisto[n]; + drcTotalVRulesHisto[n] += DRCstatVRulesHisto[n]; + if (drcTotalHRulesHisto[n] == 0 && drcTotalVRulesHisto[n] == 0) + continue; + TxPrintf(" %3d %10d/%10d %10d/%10d\n", + n, + DRCstatHRulesHisto[n], drcTotalHRulesHisto[n], + DRCstatVRulesHisto[n], drcTotalVRulesHisto[n]); + DRCstatHRulesHisto[n] = DRCstatVRulesHisto[n] = 0; + } +#endif /* DRCRULESHISTO */ +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCWhy -- + * + * This procedure finds all errors within an area and prints messages + * about each distinct kind of violation found. + * + * Results: + * None. + * + * Side effects: + * None, except that error messages are printed. The given + * area is DRC'ed for both paint and subcell violations in every + * cell of def's tree that it intersects. + * + * ---------------------------------------------------------------------------- + */ + +void +DRCWhy(dolist, use, area) + bool dolist; /* + * Generate Tcl list for value + */ + CellUse *use; /* Use in whose definition to start + * the hierarchical check. + */ + Rect *area; /* Area, in def's coordinates, that + * is to be checked. + */ +{ + SearchContext scx; + Rect box; + extern int drcWhyFunc(); /* Forward reference. */ + + /* Create a hash table to used for eliminating duplicate messages. */ + + HashInit(&DRCErrorTable, 16, HT_STRINGKEYS); + DRCErrorCount = 0; + box = DRCdef->cd_bbox; + + /* Undo will only slow things down in here, so turn it off. */ + + UndoDisable(); + scx.scx_use = use; + scx.scx_x = use->cu_xlo; + scx.scx_y = use->cu_ylo; + scx.scx_area = *area; + scx.scx_trans = GeoIdentityTransform; + drcWhyFunc(&scx, (pointertype)dolist); + UndoEnable(); + + /* Delete the hash table now that we're finished (otherwise there + * will be a core leak. + */ + + HashKill(&DRCErrorTable); + + /* Redisplay the DRC yank definition in case anyone is looking + * at it. + */ + + DBReComputeBbox(DRCdef); + (void) GeoInclude(&DRCdef->cd_bbox, &box); + DBWAreaChanged(DRCdef, &box, DBW_ALLWINDOWS, &DBAllButSpaceBits); + + if (DRCErrorCount == 0) TxPrintf("No errors found.\n"); +} + +#ifdef MAGIC_WRAPPER + +void +DRCWhyAll(use, area, fout) + CellUse *use; /* Use in whose definition to start + * the hierarchical check. + */ + Rect *area; /* Area, in def's coordinates, that + * is to be checked. + */ + FILE *fout; /* + * Write formatted output to fout + */ +{ + SearchContext scx; + Rect box; + extern int drcWhyAllFunc(); /* Forward reference. */ + HashSearch hs; + HashEntry *he; + Tcl_Obj *lobj, *robj; + + /* Create a hash table to used for eliminating duplicate messages. */ + + HashInit(&DRCErrorTable, 16, HT_STRINGKEYS); + DRCErrorCount = 0; + box = DRCdef->cd_bbox; + + /* Undo will only slow things down in here, so turn it off. */ + + UndoDisable(); + scx.scx_use = use; + scx.scx_x = use->cu_xlo; + scx.scx_y = use->cu_ylo; + scx.scx_area = *area; + scx.scx_trans = GeoIdentityTransform; + drcWhyAllFunc(&scx, NULL); + UndoEnable(); + + /* Generate results */ + + robj = Tcl_NewListObj(0, NULL); + + HashStartSearch(&hs); + while ((he = HashNext(&DRCErrorTable, &hs)) != (HashEntry *)NULL) + { + lobj = (Tcl_Obj *)HashGetValue(he); + if (lobj != NULL) + { + Tcl_ListObjAppendElement(magicinterp, robj, + Tcl_NewStringObj((char *)he->h_key.h_name, -1)); + Tcl_ListObjAppendElement(magicinterp, robj, lobj); + } + } + Tcl_SetObjResult(magicinterp, robj); + + /* Delete the hash table now that we're finished (otherwise there + * will be a core leak. + */ + + HashKill(&DRCErrorTable); + + /* Redisplay the DRC yank definition in case anyone is looking + * at it. + */ + + DBReComputeBbox(DRCdef); + (void) GeoInclude(&DRCdef->cd_bbox, &box); + DBWAreaChanged(DRCdef, &box, DBW_ALLWINDOWS, &DBAllButSpaceBits); + + if (DRCErrorCount == 0) TxPrintf("No errors found.\n"); +} + +#endif /* MAGIC_WRAPPER */ + +/* + * ---------------------------------------------------------------------------- + * + * drcWhyFunc -- + * + * This function is invoked underneath DrcWhy. It's called once + * for each subcell instance of the current cell. If the subcell + * is expanded, then it computes errors in that subcell and + * searches the subcell recursively. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +drcWhyFunc(scx, cdarg) + SearchContext *scx; /* Describes current state of search. */ + ClientData cdarg; /* Used to hold boolean value "dolist" */ +{ + CellDef *def = scx->scx_use->cu_def; + bool dolist = (bool)((pointertype)cdarg); + + /* Check paint and interactions in this subcell. */ + +// (void) DRCBasicCheck(def, &haloArea, &scx->scx_area, +// (dolist) ? drcListError : drcPrintError, +// (ClientData) scx); + (void) DRCInteractionCheck(def, &scx->scx_area, &scx->scx_area, + (dolist) ? drcListError : drcPrintError, + (ClientData) scx); + (void) DRCArrayCheck(def, &scx->scx_area, + (dolist) ? drcListError : drcPrintError, + (ClientData) scx); + + /* Also search children. */ + + (void) DBCellSrArea(scx, drcWhyFunc, (ClientData)cdarg); + + return 0; +} + +#ifdef MAGIC_WRAPPER + +int +drcWhyAllFunc(scx, cdarg) + SearchContext *scx; /* Describes current state of search. */ + ClientData cdarg; /* Unused */ +{ + CellDef *def = scx->scx_use->cu_def; + + /* Check paint and interactions in this subcell. */ + + (void) DRCInteractionCheck(def, &scx->scx_area, &scx->scx_area, + drcListallError, (ClientData)scx); + (void) DRCArrayCheck(def, &scx->scx_area, + drcListallError, (ClientData)scx); + + /* Also search children. */ + + (void) DBCellSrArea(scx, drcWhyAllFunc, (ClientData)cdarg); + + return 0; +} + +#endif /* MAGIC_WRAPPER */ + +/* + * ---------------------------------------------------------------------------- + * + * DRCCheck -- + * + * Marks all areas underneath the cursor, forcing them to be + * rechecked by the DRC. + * + * Results: + * None. + * + * Side effects: + * Check tiles are painted. + * + * ---------------------------------------------------------------------------- + */ + +void +DRCCheck(use, area) + CellUse *use; /* Top-level use of hierarchy. */ + Rect *area; /* This area is rechecked everywhere in the + * hierarchy underneath use. + */ +{ + SearchContext scx; + extern int drcCheckFunc(); /* Forward reference. */ + + DBCellReadArea(use, area); + + scx.scx_use = use; + scx.scx_x = use->cu_xlo; + scx.scx_y = use->cu_ylo; + scx.scx_area = *area; + scx.scx_trans = GeoIdentityTransform; + (void) drcCheckFunc(&scx, (ClientData) NULL); +} + + /* ARGSUSED */ +int +drcCheckFunc(scx, cdarg) + SearchContext *scx; + ClientData cdarg; /* Not used. */ +{ + Rect cellArea; + CellDef *def; + + /* Clip the area to the size of the cell, then recheck that area. + * The recheck is handled by painting the check info directly + * and then calling DRCCheckThis only to add the cell to the + * list of those to be checked. This avoids the hierarchical + * upwards search that would normally be made by DRCCheckThis, + * but which is unwelcome (and slow) here. + */ + + cellArea = scx->scx_area; + def = scx->scx_use->cu_def; + GeoClip(&cellArea, &def->cd_bbox); + GEO_EXPAND(&cellArea, DRCTechHalo, &cellArea); + + DBPaintPlane(def->cd_planes[PL_DRC_CHECK], &cellArea, + DBStdPaintTbl(TT_CHECKPAINT, PL_DRC_CHECK), + (PaintUndoInfo *) NULL); + + DRCCheckThis(def, TT_CHECKPAINT, (Rect *) NULL); + + /* Check child cells also. */ + + (void) DBCellSrArea(scx, drcCheckFunc, (ClientData) NULL); + + /* As a special performance hack, if the complete cell area is + * handled here, don't bother to look at any more array elements. + */ + + if (GEO_SURROUND(&cellArea, &def->cd_bbox)) + return 2; + else return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCCount -- + * + * Searches the entire hierarchy underneath the given area. + * For each cell found, counts design-rule violations in + * that cell and outputs the counts. + * + * Results: + * Return linked list of cell definitions and their error counts. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +DRCCountList * +DRCCount(use, area) + CellUse *use; /* Top-level use of hierarchy. */ + Rect *area; /* Area in which violations are counted. */ +{ + DRCCountList *dcl, *newdcl; + HashTable dupTable; + HashEntry *he; + HashSearch hs; + int count; + SearchContext scx; + extern int drcCountFunc(); /* Forward reference. */ + + /* Use a hash table to make sure that we don't output information + * for any cell more than once. + */ + + HashInit(&dupTable, 16, HT_WORDKEYS); + + scx.scx_use = use; + scx.scx_x = use->cu_xlo; + scx.scx_y = use->cu_ylo; + scx.scx_area = *area; + scx.scx_trans = GeoIdentityTransform; + (void) drcCountFunc(&scx, &dupTable); + + /* Create the list from the hash table */ + + dcl = NULL; + if (dupTable.ht_table != (HashEntry **) NULL) + { + HashStartSearch(&hs); + while ((he = HashNext(&dupTable, &hs)) != (HashEntry *)NULL) + { + count = (spointertype)HashGetValue(he); + if (count > 1) + { + newdcl = (DRCCountList *)mallocMagic(sizeof(DRCCountList)); + newdcl->dcl_count = count - 1; + newdcl->dcl_def = (CellDef *)he->h_key.h_ptr; + newdcl->dcl_next = dcl; + dcl = newdcl; + } + } + } + HashKill(&dupTable); + return dcl; +} + +int +drcCountFunc(scx, dupTable) + SearchContext *scx; + HashTable *dupTable; /* Passed as client data, used to + * avoid searching any cell twice. + */ +{ + int count; + HashEntry *h; + CellDef *def; + extern int drcCountFunc2(); + + /* If we've already seen this cell definition before, then skip it + * now. + */ + + def = scx->scx_use->cu_def; + h = HashFind(dupTable, (char *)def); + if (HashGetValue(h) != 0) goto done; + HashSetValue(h, 1); + + /* Count errors in this cell definition by scanning the error plane. */ + + count = 0; + (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], + &def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData) &count); + HashSetValue(h, (spointertype)count + 1); + + /* Ignore children that have not been loaded---we will only report */ + /* errors that can be seen. This avoids immediately loading and */ + /* drc processing large layouts simply because we asked for an */ + /* error count. When the cell is loaded, drc will be checked */ + /* anyway, and the count can be updated in response to that check. */ + + if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) return 0; + + /* Scan children recursively. */ + + (void) DBCellSrArea(scx, drcCountFunc, (ClientData) dupTable); + + /* As a special performance hack, if the complete cell area is + * handled here, don't bother to look at any more array elements. + */ + + done: if (GEO_SURROUND(&scx->scx_area, &def->cd_bbox)) return 2; + else return 0; +} + +int +drcCountFunc2(tile, pCount) + Tile *tile; /* Tile found in error plane. */ + int *pCount; /* Address of count word. */ +{ + if (TiGetType(tile) != (TileType) TT_SPACE) *pCount += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCCatchUp-- + * + * This procedure just runs the background checker, regardless + * of whether it's enabled or not, and waits for it to complete. + * + * Results: + * None. + * + * Side effects: + * Error and check tiles get painted and erased by the checker. + * + * ---------------------------------------------------------------------------- + */ + +void +DRCCatchUp() +{ + int background; + + background = DRCBackGround; + DRCBackGround = DRC_SET_ON; + DRCContinuous(); + DRCBackGround = background; +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCFind -- + * + * Locates the next violation tile in the cell pointed to by + * "use" and its children. + * Successive calls will located successive violations, in + * circular order. + * + * Results: + * If an error tile was found in def, returns the indx of + * the error tile (> 0). Returns 0 if there were no error + * tiles in def. Returns -1 if indx was out-of-range + * (not that many errors in def). + * + * Side effects: + * Rect is filled with the location of the tile, if one is found. + * + * ---------------------------------------------------------------------------- + */ + +typedef struct { + int current; /* count of current error */ + int target; /* count of target error */ + Rect *rect; /* Return rectangle */ + Transform trans; /* Return transform */ + HashTable *deft; /* Table of cell definitions to avoid duplicates */ +} Sindx; + +int +DRCFind(use, area, rect, indx) + CellUse *use; /* Cell use to check. */ + Rect *area; /* Area of search */ + Rect *rect; /* Rectangle to fill in with tile location. */ + int indx; /* Go to this error. */ +{ + SearchContext scx; + Sindx finddata; + Rect trect; + int result; + int drcFindFunc(); + HashTable defTable; + + scx.scx_use = use; + scx.scx_x = use->cu_xlo; + scx.scx_y = use->cu_ylo; + scx.scx_area = *area; + scx.scx_trans = GeoIdentityTransform; + + HashInit(&defTable, 16, HT_WORDKEYS); + + finddata.current = 0; + finddata.target = indx; + finddata.rect = &trect; + finddata.trans = scx.scx_trans; + finddata.deft = &defTable; + + result = drcFindFunc(&scx, &finddata); + + HashKill(&defTable); + + if (result == 0) + { + if (finddata.current == 0) + return 0; + else + return -1; + } + + /* Translate rectangle back into coordinate system of "use" */ + GeoTransRect(&finddata.trans, &trect, rect); + return indx; +} + +int +drcFindFunc(scx, finddata) + SearchContext *scx; + Sindx *finddata; +{ + CellDef *def; + HashEntry *h; + int drcFindFunc2(); + + def = scx->scx_use->cu_def; + h = HashFind(finddata->deft, (char *)def); + if (HashGetValue(h) != 0) return 0; + HashSetValue(h, 1); + + (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + + if (DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], + &def->cd_bbox, &DBAllButSpaceBits, drcFindFunc2, + (ClientData)finddata) != 0) + { + finddata->trans = scx->scx_trans; + return 1; + } + + /* Recursively search children */ + return DBCellSrArea(scx, drcFindFunc, (ClientData)finddata); +} + +int +drcFindFunc2(tile, finddata) + Tile *tile; /* Tile in error plane. */ + Sindx *finddata; /* Information about error to find */ + +{ + if (TiGetType(tile) == (TileType) TT_SPACE) return 0; + if (++finddata->current == finddata->target) + { + TiToRect(tile, finddata->rect); + return 1; + } + return 0; +} diff --git a/drc/DRCprint.c b/drc/DRCprint.c new file mode 100644 index 00000000..855384ab --- /dev/null +++ b/drc/DRCprint.c @@ -0,0 +1,186 @@ +/* + * DRCPrint.c -- + * + * Edge-based design rule checker + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/drc/DRCprint.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" + +extern char *maskToPrint(); +extern char *DBTypeShortName(); + +/* + * ---------------------------------------------------------------------------- + * + * drcGetName -- + * + * This is a utility procedure that returns a convenient name for + * a mask layer. + * + * Results: + * The result is the first 8 characters of the long name for + * the layer. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +char * +drcGetName(layer, string) + int layer; + char *string; /* Used to hold name. Must have length >= 8 */ +{ + (void) strncpy(string, DBTypeShortName(layer), 8); + string[8] = '\0'; + if (layer == TT_SPACE) return "space"; + return string; +} + + +/* + * ---------------------------------------------------------------------------- + * DRCPrintRulesTable -- + * + * Write compiled DRC rules table and adjacency matrix to the given file. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +DRCPrintRulesTable (fp) + FILE *fp; +{ + int i, j, k; + DRCCookie * dp; + char buf1[20], buf2[20]; + int gotAny; + /* print the rules table */ + for (i = 0; i < DBNumTypes; i++) + { + gotAny = FALSE; + for (j = 0; j < DBNumTypes; j++) + { + if (DRCCurStyle->DRCRulesTbl [i][j] != (DRCCookie *) NULL) + { + k = 1; + for (dp = DRCCurStyle->DRCRulesTbl [i][j]; dp != (DRCCookie *) NULL; + dp = dp->drcc_next) + { + gotAny = TRUE; + if (k == 1) + { + fprintf(fp,"%-8s %-8s ",drcGetName(i, buf1), + drcGetName(j, buf2)); + k++; + } + else fprintf(fp," "); + + fprintf(fp,"%d x %d %s (%s)\n", + dp->drcc_dist, dp->drcc_cdist, + maskToPrint(&dp->drcc_mask), + DBPlaneLongName(dp->drcc_plane)); + fprintf(fp," %s", + maskToPrint(&dp->drcc_corner)); + if (dp->drcc_flags > 0) + fprintf(fp, "\n "); + if (dp->drcc_flags & DRC_REVERSE) + fprintf(fp," reverse"); + if (dp->drcc_flags & DRC_BOTHCORNERS) + fprintf(fp," both-corners"); + if (dp->drcc_flags & DRC_TRIGGER) + fprintf(fp," trigger"); + if (dp->drcc_flags & DRC_AREA) + fprintf(fp," area"); + if (dp->drcc_flags & DRC_MAXWIDTH) + fprintf(fp," maxwidth"); + if (dp->drcc_flags & DRC_BENDS) + fprintf(fp," bends"); + if (dp->drcc_flags & DRC_RECTSIZE) + fprintf(fp," rect-size"); + if (dp->drcc_flags & DRC_ANGLES) + fprintf(fp," angles"); + fprintf(fp,"\n"); + } + } + } + if (gotAny) fprintf(fp,"\n"); + } + + /* Print out overlaps that are illegal between subcells. */ + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if ((i == TT_ERROR_S) || (j == TT_ERROR_S)) continue; + if (DRCCurStyle->DRCPaintTable[0][i][j] == TT_ERROR_S) + fprintf(fp, "Tile type %s can't overlap type %s.\n", + drcGetName(i, buf1), drcGetName(j, buf2)); + } + } + + /* Print out tile types that must have exact overlaps. */ + + if (!TTMaskIsZero(&DRCCurStyle->DRCExactOverlapTypes)) + { + fprintf(fp, "Types that must overlap exactly: %s\n", + maskToPrint(&DRCCurStyle->DRCExactOverlapTypes)); + } +} + +char * +maskToPrint (mask) + TileTypeBitMask *mask; +{ + int i; + int gotSome = FALSE; + static char printchain[400]; + char buffer[20]; + + if (TTMaskIsZero(mask)) + return ""; + + printchain[0] = '\0'; + + for (i = 0; i < DBNumTypes; i++) + if (TTMaskHasType(mask, i)) + { + if (gotSome) strcat(printchain, ","); + else gotSome = TRUE; + strcat(printchain, drcGetName(i, buffer)); + } + + return (printchain); +} diff --git a/drc/DRCsubcell.c b/drc/DRCsubcell.c new file mode 100644 index 00000000..bd2b3953 --- /dev/null +++ b/drc/DRCsubcell.c @@ -0,0 +1,750 @@ +/* + * DRCsubcell.c -- + * + * This file provides the facilities for finding design-rule + * violations that occur as a result of interactions between + * subcells and either paint or other subcells. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/drc/DRCsubcell.c,v 1.4 2009/05/01 18:59:44 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" +#include "windows/windows.h" +#include "commands/commands.h" +#include "utils/undo.h" + +/* The variables below are made owns so that they can be used to + * pass information to the various search functions. + */ + +static Rect drcSubIntArea; /* Accumulates area of interactions. */ +static CellDef *drcSubDef; /* Cell definition we're checking. */ +static int drcSubRadius; /* Interaction radius. */ +static CellUse *drcSubCurUse; /* Holds current use when checking to see + * if more than one use in an area. + */ +static Rect drcSubLookArea; /* Area where we're looking for interactions */ +static void (*drcSubFunc)(); /* Error function. */ +static ClientData drcSubClientData; + /* To be passed to error function. */ + +/* The cookie below is dummied up to provide an error message for + * errors that occur because of inexact overlaps between subcells. + */ + +static DRCCookie drcSubcellCookie = { + 0, 0, 0, 0, + { 0 }, { 0 }, + 0, 0, 0, + "This layer can't abut or partially overlap between subcells", + (DRCCookie *) NULL +}; + +extern int DRCErrorType; + + +/* + * ---------------------------------------------------------------------------- + * + * drcFindOtherCells -- + * + * This is a search function invoked when looking around a given + * cell for interactions. If a cell is found other than drcSubCurUse, + * then it constitutes an interaction, and its area is included + * into the area parameter. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * The area parameter may be modified by including the area + * of the current tile. + * + * ---------------------------------------------------------------------------- + */ + +int +drcFindOtherCells(tile, area) + Tile *tile; /* Tile in subcell plane. */ + Rect *area; /* Area in which to include interactions. */ +{ + Rect r; + CellTileBody *ctbptr = (CellTileBody *) tile->ti_body; + + if (ctbptr == NULL) return 0; + if ((ctbptr->ctb_use != drcSubCurUse) || (ctbptr->ctb_next != NULL)) + { + TiToRect(tile, &r); + (void) GeoInclude(&r, area); + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcSubcellTileFunc -- + * + * Called by TiSrArea when looking for interactions in + * a given area. It sees if this subcell tile participates + * in any interactions in the area we're rechecking. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * The area drcSubIntArea is modified to include interactions + * stemming from this subcell. + * + * ---------------------------------------------------------------------------- + */ + +int +drcSubcellTileFunc(tile) + Tile *tile; /* Subcell tile. */ +{ + Rect area, haloArea, intArea; + int i; + CellTileBody *ctbptr = (CellTileBody *) tile->ti_body; + + if (ctbptr == NULL) return 0; + + /* To determine interactions, find the bounding box of + * all paint and other subcells within one halo of this + * subcell tile (and also within the original area where + * we're recomputing errors). + */ + + TiToRect(tile, &area); + GEO_EXPAND(&area, drcSubRadius, &haloArea); + GeoClip(&haloArea, &drcSubLookArea); + intArea = GeoNullRect; + for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) + { + (void) DBSrPaintArea((Tile *) NULL, drcSubDef->cd_planes[i], + &haloArea, &DBAllButSpaceBits, drcIncludeArea, + (ClientData) &intArea); + } + drcSubCurUse = ctbptr->ctb_use; + (void) TiSrArea((Tile *) NULL, drcSubDef->cd_planes[PL_CELL], + &haloArea, drcFindOtherCells, (ClientData) &intArea); + if (GEO_RECTNULL(&intArea)) return 0; + + GEO_EXPAND(&intArea, drcSubRadius, &intArea); + GeoClip(&intArea, &haloArea); + (void) GeoInclude(&intArea, &drcSubIntArea); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcAlwaysOne -- + * + * This is a utility procedure that always returns 1 when it + * is called. It aborts searches and notifies the invoker that + * an item was found during the search. + * + * Results: + * Always returns 1 to abort searches. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +drcAlwaysOne() +{ + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcSubCheckPaint -- + * + * This procedure is invoked once for each subcell in a + * particular interaction area. It checks to see whether the + * subcell's subtree actually contains some paint in the potential + * interaction area. As soon as the second such subcell is found, + * it aborts the search. + * + * Results: + * Returns 0 to keep the search alive, unless we've found the + * second subcell containing paint in the interaction area. + * When this occurs, the search is aborted by returning 1. + * + * Side effects: + * When the first use with paint is found, curUse is modified + * to contain its address. + * + * ---------------------------------------------------------------------------- + */ + +int +drcSubCheckPaint(scx, curUse) + SearchContext *scx; /* Contains information about the celluse + * that was found. + */ + CellUse **curUse; /* Points to a celluse, or NULL, or -1. -1 + * means paint was found in the root cell, + * and non-NULL means some other celluse had + * paint in it. If we find another celluse + * with paint, when this is non-NULL, it + * means there really are two cells with + * interacting paint, so we abort the + * search to tell the caller to really check + * this area. + */ +{ + if (DBTreeSrTiles(scx, &DBAllButSpaceAndDRCBits, 0, drcAlwaysOne, + (ClientData) NULL) != 0) + { + /* This subtree has stuff under the interaction area. */ + + if (*curUse != NULL) return 1; + *curUse = scx->scx_use; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCFindInteractions -- + * + * This procedure finds the bounding box of all subcell-subcell + * or subcell-paint interactions in a given area of a given cell. + * + * Results: + * Returns TRUE if there were any interactions in the given + * area, FALSE if there were none. + * + * Side effects: + * The parameter interaction is set to contain the bounding box + * of all places in area where one subcell comes within radius + * of another subcell, or where paint in def comes within radius + * of a subcell. Interactions between elements of array are not + * considered here, but interactions between arrays and other + * things are considered. This routine is a bit clever, in that + * it not only checks for bounding boxes interacting, but also + * makes sure the cells really contain material in the interaction + * area. + * ---------------------------------------------------------------------------- + */ + +bool +DRCFindInteractions(def, area, radius, interaction) + CellDef *def; /* Cell to check for interactions. */ + Rect *area; /* Area of def to check for interacting + * material. + */ + int radius; /* How close two pieces of material must be + * to be considered interacting. Two pieces + * radius apart do NOT interact, but if they're + * close than this they do. + */ + Rect *interaction; /* Gets filled in with the bounding box of + * the interaction area, if any. Doesn't + * have a defined value when FALSE is returned. + */ +{ + int i; + CellUse *use; + SearchContext scx; + + drcSubDef = def; + drcSubRadius = radius; + DRCDummyUse->cu_def = def; + + /* Find all the interactions in the area and compute the + * outer bounding box of all those interactions. An interaction + * exists whenever material in one cell approaches within radius + * of material in another cell. As a first approximation, assume + * each cell has material everywhere within its bounding box. + */ + + drcSubIntArea = GeoNullRect; + GEO_EXPAND(area, radius, &drcSubLookArea); + (void) TiSrArea((Tile *) NULL, def->cd_planes[PL_CELL], + &drcSubLookArea, drcSubcellTileFunc, (ClientData) NULL); + + /* If there seems to be an interaction area, make a second pass + * to make sure there's more than one cell with paint in the + * area. This will save us a lot of work where two cells + * have overlapping bounding boxes without overlapping paint. + */ + + if (GEO_RECTNULL(&drcSubIntArea)) return FALSE; + use = NULL; + for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) + { + if (DBSrPaintArea((Tile *) NULL, def->cd_planes[i], + &drcSubIntArea, &DBAllButSpaceBits, drcAlwaysOne, + (ClientData) NULL) != 0) + { + use = (CellUse *) -1; + break; + } + } + scx.scx_use = DRCDummyUse; + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = drcSubIntArea; + if (DBTreeSrCells(&scx, 0, drcSubCheckPaint, (ClientData) &use) == 0) + return FALSE; + + /* OK, no more excuses, there's really an interaction area here. */ + + *interaction = drcSubIntArea; + GeoClip(interaction, area); + if (GEO_RECTNULL(interaction)) return FALSE; + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcExactOverlapCheck -- + * + * This procedure is invoked to check for overlap violations. + * It is invoked by DBSrPaintArea from drcExactOverlapTile. + * Any tiles passed to this procedure must lie within + * arg->dCD_rect, or an error is reported. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * If an error occurs, the client error function is called and + * the error count is incremented. + * + * ---------------------------------------------------------------------------- + */ + +int +drcExactOverlapCheck(tile, arg) + Tile *tile; /* Tile to check. */ + struct drcClientData *arg; /* How to detect and process errors. */ +{ + Rect rect; + + TiToRect(tile, &rect); + GeoClip(&rect, arg->dCD_clip); + if (GEO_RECTNULL(&rect)) return 0; + + (*(arg->dCD_function)) (arg->dCD_celldef, &rect, arg->dCD_cptr, + arg->dCD_clientData); + (*(arg->dCD_errors))++; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcExactOverlapTile -- + * + * This procedure is invoked by DBTreeSrTiles for each tile + * in each constituent cell of a subcell interaction. It + * makes sure that if this tile overlaps other tiles of the + * same type in other cells, then the overlaps are EXACT: + * each cell contains exactly the same information. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * If there are errors, the client error handling routine + * is invoked and the count in the drcClientData record is + * incremented. + * + * ---------------------------------------------------------------------------- + */ + +int +drcExactOverlapTile(tile, cxp) + Tile *tile; /* Tile that must overlap exactly. */ + TreeContext *cxp; /* Tells how to translate out of subcell. + * The client data must be a drcClientData + * record, and the caller must have filled + * in the celldef, clip, errors, function, + * cptr, and clientData fields. + */ +{ + struct drcClientData *arg; + TileTypeBitMask typeMask, invMask, *rmask; + TileType type, t; + Tile *tp; + Rect r1, r2, r3, rex; + int i; + + arg = (struct drcClientData *) cxp->tc_filter->tf_arg; + TiToRect(tile, &r1); + GeoTransRect(&(cxp->tc_scx->scx_trans), &r1, &r2); + + GEO_EXPAND(&r2, 1, &rex); /* Area includes abutting tiles */ + GeoClip(&rex, arg->dCD_clip); /* Except areas outside search area */ + + type = TiGetType(tile); + TTMaskSetOnlyType(&typeMask, type); + for (t = DBNumUserLayers; t < DBNumTypes; t++) + { + rmask = DBResidueMask(t); + if (TTMaskHasType(rmask, type)) + TTMaskSetType(&typeMask, t); + } + TTMaskCom2(&invMask, &typeMask); + + for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) + { + if (DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i], + &rex, &typeMask, drcAlwaysOne, (ClientData) NULL)) + { + /* There is an overlap or abutment of ExactOverlap types. */ + /* 1) Check if any invalid type is under this tile. */ + + arg->dCD_rect = &r2; + DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i], &r2, + &invMask, drcExactOverlapCheck, (ClientData) arg); + + /* 2) Search the neighboring tiles for types that do not */ + /* match the exact overlap type, and flag abutment errors. */ + + /* Search bottom */ + arg->dCD_rect = &r3; + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (TTMaskHasType(&invMask, TiGetType(tp))) + { + TiToRect(tp, &r1); + GeoTransRect(&(cxp->tc_scx->scx_trans), &r1, &r3); + GeoClip(&r3, &rex); + if (!GEO_RECTNULL(&r3)) + DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i], + &r3, &typeMask, drcExactOverlapCheck, + (ClientData) arg); + } + + /* Search right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (TTMaskHasType(&invMask, TiGetType(tp))) + { + TiToRect(tp, &r1); + GeoTransRect(&(cxp->tc_scx->scx_trans), &r1, &r3); + GeoClip(&r3, &rex); + if (!GEO_RECTNULL(&r3)) + DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i], + &r3, &typeMask, drcExactOverlapCheck, + (ClientData) arg); + } + + /* Search top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (TTMaskHasType(&invMask, TiGetType(tp))) + { + TiToRect(tp, &r1); + GeoTransRect(&(cxp->tc_scx->scx_trans), &r1, &r3); + GeoClip(&r3, &rex); + if (!GEO_RECTNULL(&r3)) + DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i], + &r3, &typeMask, drcExactOverlapCheck, + (ClientData) arg); + } + + /* Search left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (TTMaskHasType(&invMask, TiGetType(tp))) + { + TiToRect(tp, &r1); + GeoTransRect(&(cxp->tc_scx->scx_trans), &r1, &r3); + GeoClip(&r3, &rex); + if (!GEO_RECTNULL(&r3)) + DBSrPaintArea((Tile *) NULL, DRCdef->cd_planes[i], + &r3, &typeMask, drcExactOverlapCheck, + (ClientData) arg); + } + } + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCInteractionCheck -- + * + * This is the top-level procedure that performs subcell interaction + * checks. All interaction rule violations in area of def are + * found, and func is called for each one. + * + * Results: + * The number of errors found. + * + * Side effects: + * The procedure func is called for each violation found. See + * the header for DRCBasicCheck for information about how func + * is called. The violations passed to func are expressed in + * the coordinates of def. Only violations stemming from + * interactions in def, as opposed to def's children, are reported. + * + * Design Note: + * This procedure is trickier than you think. The problem is that + * DRC must be guaranteed to produce EXACTLY the same collection + * of errors in an area, no matter how the area is checked. Checking + * it all as one big area should produce the same results as + * checking it in several smaller pieces. Otherwise, "drc why" + * won't work correctly, and the error configuration will depend + * on how the chip was checked, which is intolerable. This problem + * is solved here by dividing the world up into squares along a grid + * of dimension DRCStepSize aligned at the origin. Interaction areas + * are always computed by considering everything inside one grid square + * at a time. We may have to consider several grid squares in order + * to cover the area passed in by the client. + * ---------------------------------------------------------------------------- + */ + +int +DRCInteractionCheck(def, area, erasebox, func, cdarg) + CellDef *def; /* Definition in which to do check. */ + Rect *area; /* Area in which all errors are to be found. */ + Rect *erasebox; /* Smaller area containing DRC check tiles */ + void (*func)(); /* Function to call for each error. */ + ClientData cdarg; /* Extra info to be passed to func. */ +{ + int oldTiles, count, x, y, errorSaveType; + Rect intArea, square, cliparea, subArea; + PaintResultType (*savedPaintTable)[NT][NT]; + void (*savedPaintPlane)(); + struct drcClientData arg; + SearchContext scx; + + drcSubFunc = func; + drcSubClientData = cdarg; + oldTiles = DRCstatTiles; + count = 0; + + /* Divide the area to be checked up into squares. Process each + * square separately. + */ + + x = (area->r_xbot/DRCStepSize) * DRCStepSize; + if (x > area->r_xbot) x -= DRCStepSize; + y = (area->r_ybot/DRCStepSize) * DRCStepSize; + if (y > area->r_ybot) y -= DRCStepSize; + for (square.r_xbot = x; square.r_xbot < area->r_xtop; + square.r_xbot += DRCStepSize) + for (square.r_ybot = y; square.r_ybot < area->r_ytop; + square.r_ybot += DRCStepSize) + { + square.r_xtop = square.r_xbot + DRCStepSize; + square.r_ytop = square.r_ybot + DRCStepSize; + + /* Limit square to area. Otherwise, a huge processing */ + /* penalty is incurred for finding a single error (e.g., */ + /* using "drc find" or "drc why" in a large design with a */ + /* large step size. */ + + cliparea = square; + GeoClip(&cliparea, area); + + /* Find all the interactions in the square, and clip to the error + * area we're interested in. */ + + if (!DRCFindInteractions(def, &cliparea, DRCTechHalo, &intArea)) + { + /* Added May 4, 2008---if there are no subcells, run the + * basic check over the area of the square. + */ + subArea = *erasebox; + GeoClip(&subArea, &cliparea); + GEO_EXPAND(&subArea, DRCTechHalo, &intArea); + + errorSaveType = DRCErrorType; + DRCErrorType = TT_ERROR_P; // Basic check is always ERROR_P + DRCBasicCheck(def, &intArea, &subArea, func, cdarg); + DRCErrorType = errorSaveType; + continue; + } + else + { + /* Added March 6, 2012: Any area(s) outside the + * interaction area are processed with the basic + * check. This avoids unnecessary copying, so it + * speeds up the DRC without requiring that geometry + * passes DRC rules independently of subcell geometry + * around it. + * + * As intArea can be smaller than square, we may have + * to process as many as four independent rectangles. + * NOTE that the area of (intArea + halo) will be checked + * in the subcell interaction check, so we can ignore + * that. + */ + Rect eraseClip, eraseHalo, subArea; + + errorSaveType = DRCErrorType; + DRCErrorType = TT_ERROR_P; // Basic check is always ERROR_P + eraseClip = *erasebox; + GeoClip(&eraseClip, &cliparea); + subArea = eraseClip; + + /* check above */ + if (intArea.r_ytop < eraseClip.r_ytop) + { + subArea.r_ybot = intArea.r_ytop; + GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo); + DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg); + } + /* check below */ + if (intArea.r_ybot > eraseClip.r_ybot) + { + subArea.r_ybot = eraseClip.r_ybot; + subArea.r_ytop = intArea.r_ybot; + GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo); + DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg); + } + subArea.r_ytop = intArea.r_ytop; + subArea.r_ybot = intArea.r_ybot; + + /* check right */ + if (intArea.r_xtop < eraseClip.r_xtop) + { + subArea.r_xbot = intArea.r_xtop; + GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo); + DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg); + } + /* check left */ + if (intArea.r_xbot > eraseClip.r_xbot) + { + subArea.r_xtop = intArea.r_xbot; + subArea.r_xbot = eraseClip.r_xbot; + GEO_EXPAND(&subArea, DRCTechHalo, &eraseHalo); + DRCBasicCheck(def, &eraseHalo, &subArea, func, cdarg); + } + DRCErrorType = errorSaveType; + } + + /* Flatten the interaction area. */ + + DRCstatInteractions += 1; + GEO_EXPAND(&intArea, DRCTechHalo, &scx.scx_area); + DRCDummyUse->cu_def = def; + scx.scx_use = DRCDummyUse; + scx.scx_trans = GeoIdentityTransform; + DBCellClearDef(DRCdef); + + savedPaintTable = DBNewPaintTable(DRCCurStyle->DRCPaintTable); + savedPaintPlane = DBNewPaintPlane(DBPaintPlaneMark); + + (void) DBCellCopyAllPaint(&scx, &DBAllButSpaceBits, 0, DRCuse); + + (void) DBNewPaintTable(savedPaintTable); + (void) DBNewPaintPlane(savedPaintPlane); + + /* Run the basic checker over the interaction area. */ + + count += DRCBasicCheck(DRCdef, &scx.scx_area, &intArea, + func, cdarg); + /* TxPrintf("Interaction area: (%d, %d) (%d %d)\n", + intArea.r_xbot, intArea.r_ybot, + intArea.r_xtop, intArea.r_ytop); + */ + + /* Check for illegal partial overlaps. */ + + scx.scx_use = DRCDummyUse; + scx.scx_area = intArea; + scx.scx_trans = GeoIdentityTransform; + arg.dCD_celldef = DRCdef; + arg.dCD_clip = &intArea; + arg.dCD_errors = &count; + arg.dCD_cptr = &drcSubcellCookie; + arg.dCD_function = func; + arg.dCD_clientData = cdarg; + (void) DBTreeSrUniqueTiles(&scx, &DRCCurStyle->DRCExactOverlapTypes, + 0, drcExactOverlapTile, (ClientData) &arg); + } + + /* Update count of interaction tiles processed. */ + + DRCstatIntTiles += DRCstatTiles - oldTiles; + return count; +} + +void +DRCFlatCheck(use, area) + CellUse *use; + Rect *area; +{ + int x, y; + Rect chunk; + SearchContext scx; + void drcIncCount(); + PaintResultType (*savedPaintTable)[NT][NT]; + void (*savedPaintPlane)(); + int drcFlatCount = 0; + + UndoDisable(); + for (y = area->r_ybot; y < area->r_ytop; y += 300) + { + for (x = area->r_xbot; x < area->r_xtop; x += 300) + { + chunk.r_xbot = x; + chunk.r_ybot = y; + chunk.r_xtop = x+300; + chunk.r_ytop = y+300; + if (chunk.r_xtop > area->r_xtop) chunk.r_xtop = area->r_xtop; + if (chunk.r_ytop > area->r_ytop) chunk.r_ytop = area->r_ytop; + GEO_EXPAND(&chunk, DRCTechHalo, &scx.scx_area); + scx.scx_use = use; + scx.scx_trans = GeoIdentityTransform; + DBCellClearDef(DRCdef); + + savedPaintTable = DBNewPaintTable(DRCCurStyle->DRCPaintTable); + savedPaintPlane = DBNewPaintPlane(DBPaintPlaneMark); + + (void) DBCellCopyAllPaint(&scx, &DBAllButSpaceBits, 0, DRCuse); + + (void) DBNewPaintTable(savedPaintTable); + (void) DBNewPaintPlane(savedPaintPlane); + + (void) DRCBasicCheck(DRCdef, &scx.scx_area, &chunk, + drcIncCount, (ClientData) &drcFlatCount); + } + } + TxPrintf("%d total errors found.\n", drcFlatCount); + UndoEnable(); +} + +void +drcIncCount(def, area, rule, count) + CellDef *def; + Rect *area; + DRCCookie *rule; + int *count; +{ + *count++; +} diff --git a/drc/DRCtech.c b/drc/DRCtech.c new file mode 100644 index 00000000..5802e23a --- /dev/null +++ b/drc/DRCtech.c @@ -0,0 +1,3886 @@ +/* + * DRCtech.c -- + * + * Technology initialization for the DRC module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/drc/DRCtech.c,v 1.12 2010/10/20 12:04:12 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" +#include "utils/tech.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "cif/cif.h" +#include "cif/CIFint.h" + +CIFStyle *drcCifStyle = NULL; +bool DRCForceReload = FALSE; + +/* + * DRC interaction radius being used (not necessarily the same as + * what's defined in the current DRC style). + */ +global int DRCTechHalo; +global int DRCStepSize; + +/* The following variable can be set to zero to turn off + * any optimizations of design rule lists. + */ + +global int DRCRuleOptimization = TRUE; + +/* The following variables count how many rules were specified by + * the technology file and how many edge rules were optimized away. + */ + +static int drcRulesSpecified = 0; +static int drcRulesOptimized = 0; + +/* + * Forward declarations. + */ +int drcWidth(), drcSpacing(), drcEdge(), drcNoOverlap(); +int drcExactOverlap(), drcExtend(); +int drcSurround(), drcRectOnly(), drcOverhang(); +int drcStepSize(); +int drcMaxwidth(), drcArea(), drcRectangle(), drcAngles(); +int drcCifSetStyle(), drcCifWidth(), drcCifSpacing(); +int drcCifMaxwidth(), drcCifArea(); + +void DRCTechStyleInit(); +void drcLoadStyle(); +void DRCTechFinal(); +void drcTechFinalStyle(); + +/* + * ---------------------------------------------------------------------------- + * + * Given a TileType bit mask, return the plane mask of planes that are + * coincident with all types. This is roughly equivalent to the deprecated + * DBTechMinSetPlanes(), but does not attempt to produce a reduced set of + * tile types. Since the collective mask of all possible planes is usually + * found by a call to DBTechNoisyNameMask, we don't attempt to OR all the + * plane masks together, but assume this collective mask is available and + * passed as an argument. + * + * ---------------------------------------------------------------------------- + */ + +PlaneMask +CoincidentPlanes(typeMask, pmask) + TileTypeBitMask *typeMask; /* Mask of types to check coincidence */ + PlaneMask pmask; /* Mask of all possible planes of types */ +{ + PlaneMask planes = pmask; + TileType i; + + /* AND each plane against the collective mask */ + for (i = TT_SELECTBASE; i < DBNumTypes; i++) + if (TTMaskHasType(typeMask, i)) + planes &= DBTypePlaneMaskTbl[i]; + + return planes; +} + + +/* + * ---------------------------------------------------------------------------- + * + * Given a plane mask, return the plane number of the lowest plane in the mask. + * + * ---------------------------------------------------------------------------- + */ + +int +LowestMaskBit(PlaneMask pmask) +{ + PlaneMask pset = pmask; + int plane = 0; + + if (pmask == 0) return DBNumPlanes; + + while ((pset & 0x1) == 0) + { + plane++; + pset >>= 1; + } + return plane; +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCPrintStyle -- + * + * Print the available and/or current extraction styles. + * + * Results: + * None. + * + * Side effects: + * Output. + * + * ---------------------------------------------------------------------------- + */ + +void +DRCPrintStyle(dolist, doforall, docurrent) + bool dolist, doforall, docurrent; +{ + DRCKeep *style; + + if (docurrent) + { + if (DRCCurStyle == NULL) + TxError("Error: No style is set\n"); + else + { + if (!dolist) TxPrintf("The current style is \""); +#ifdef MAGIC_WRAPPER + if (dolist) + Tcl_SetResult(magicinterp, DRCCurStyle->ds_name, NULL); + else +#endif + TxPrintf("%s", DRCCurStyle->ds_name); + if (!dolist) TxPrintf("\".\n"); + } + } + + if (doforall) + { + if (!dolist) TxPrintf("The DRC styles are: "); + + for (style = DRCStyleList; style; style = style->ds_next) + { + if (dolist) + { +#ifdef MAGIC_WRAPPER + Tcl_AppendElement(magicinterp, style->ds_name); +#else + if (style != DRCStyleList) TxPrintf(" "); + TxPrintf("%s", style->ds_name); +#endif + } + else + { + if (style != DRCStyleList) TxPrintf(", "); + TxPrintf("%s", style->ds_name); + } + } + if (!dolist) TxPrintf(".\n"); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCSetStyle -- + * + * Set the current DRC style to 'name'. + * + * Results: + * None. + * + * Side effects: + * Output. + * + * ---------------------------------------------------------------------------- + */ + +void +DRCSetStyle(name) + char *name; +{ + DRCKeep *style, *match; + int length; + + if (name == NULL) return; + + match = NULL; + length = strlen(name); + for (style = DRCStyleList; style; style = style->ds_next) + { + if (strncmp(name, style->ds_name, length) == 0) + { + if (match != NULL) + { + TxError("DRC style \"%s\" is ambiguous.\n", name); + DRCPrintStyle(FALSE, TRUE, TRUE); + return; + } + match = style; + } + } + + if (match != NULL) + { + drcLoadStyle(match->ds_name); + TxPrintf("DRC style is now \"%s\"\n", name); + return; + } + + TxError("\"%s\" is not one of the DRC styles Magic knows.\n", name); + DRCPrintStyle(FALSE, TRUE, TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcTechFreeStyle -- + * + * This procedure frees all memory associated with a DRC style. + * + * Results: + * None. + * + * Side effects: + * Memory free'd. + * + * ---------------------------------------------------------------------------- + */ + +void +drcTechFreeStyle() +{ + int i, j; + char *old; + DRCCookie *dp; + + if (DRCCurStyle != NULL) + { + /* Remove all old rules from the DRC rules table */ + + for (i = 0; i < TT_MAXTYPES; i++) + for (j = 0; j < TT_MAXTYPES; j++) + { + dp = DRCCurStyle->DRCRulesTbl[i][j]; + while (dp != NULL) + { + char *old = (char *) dp; + dp = dp->drcc_next; + freeMagic(old); + } + } + + /* Clear the DRCWhyList */ + + while (DRCCurStyle->DRCWhyList != NULL) + { + old = (char *) DRCCurStyle->DRCWhyList; + StrDup(&(DRCCurStyle->DRCWhyList->dwl_string), (char *) NULL); + DRCCurStyle->DRCWhyList = DRCCurStyle->DRCWhyList->dwl_next; + freeMagic(old); + } + + freeMagic(DRCCurStyle); + DRCCurStyle = NULL; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * drcTechNewStyle -- + * + * This procedure creates a new DRC style at the end of the list + * of styles and initializes it to completely null. + * + * Results: + * None. + * + * Side effects: + * A new element is added to the end of DRCStyleList, and DRCCurStyle + * is set to point to it. + * + * ---------------------------------------------------------------------------- + */ + +void +drcTechNewStyle() +{ + drcTechFreeStyle(); + DRCTechStyleInit(); +} + +/* + * ---------------------------------------------------------------------------- + * drcWhyDup -- + * + * Duplicate a shared "why" string using StrDup() and remember it so we can + * free it sometime later, in drcWhyClear(). + * + * Returns: + * A copy of the given string. + * + * Side effects: + * Adds to the DRCWhyList. Calls StrDup(). + * ---------------------------------------------------------------------------- + */ + +char * +drcWhyDup(why) + char * why; +{ + struct drcwhylist * new; + + new = (struct drcwhylist *) mallocMagic((unsigned) (sizeof *new)); + new->dwl_string = StrDup((char **) NULL, why); + new->dwl_next = DRCCurStyle->DRCWhyList; + DRCCurStyle->DRCWhyList = new; + + return new->dwl_string; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcFindBucket -- + * + * Find the bucket preceding the point where we with to insert a new DRC + * cookie. Don't insert a cookie in the middle of a pair of coupled + * (trigger + check) rules. + * + * Results: + * Returns a pointer to the location where we want to insert a rule + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +DRCCookie * +drcFindBucket(i, j, distance) + int i, j, distance; +{ + DRCCookie *dp; + + if (DRCCurStyle == NULL) return NULL; + + /* find bucket preceding the new one we wish to insert */ + + for (dp = DRCCurStyle->DRCRulesTbl[i][j]; + dp->drcc_next != (DRCCookie *) NULL; + dp = dp->drcc_next) + { + if (dp->drcc_next->drcc_flags & DRC_TRIGGER) + { + if (dp->drcc_next->drcc_next->drcc_dist >= distance) + break; + else + dp = dp->drcc_next; + } + else if (dp->drcc_next->drcc_dist >= distance) break; + } + + return dp; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcLoadStyle -- + * + * Re-read the technology file to load the specified technology DRC style + * into structure DRCCurStyle. It incurs a complete reading of the tech + * file on startup and every time the extraction style is changed, but we + * can assume that this does not happen often. The first style in the + * technology file is assumed to be the default, so that re-reading the + * tech file is not necessary on startup unless the default DRC style is + * changed by a call do "drc style". + * + * ---------------------------------------------------------------------------- + */ + +void +drcLoadStyle(stylename) + char *stylename; +{ + SectionID invdrc; + + if (DRCCurStyle->ds_name == stylename) return; + + drcTechNewStyle(); /* Reinitialize and mark as not loaded */ + DRCCurStyle->ds_name = stylename; + + invdrc = TechSectionGetMask("drc", NULL); + TechLoad(NULL, invdrc); + + DRCTechScale(DBLambda[0], DBLambda[1]); +} + +/* + * ---------------------------------------------------------------------------- + * DRCReloadCurStyle --- + * + * This routine is used by CIFLoadStyle whenever the DRC section makes + * reference to CIF layers. + * + * Results: + * None. + * + * Side Effects: + * DRC rule database is deleted and regenerated. + * + * ---------------------------------------------------------------------------- + */ + +void +DRCReloadCurStyle() +{ + char *stylename; + DRCKeep * style; + + if (DRCCurStyle == NULL) return; + + for (style = DRCStyleList; style != NULL; style = style->ds_next) + { + if (!strcmp(style->ds_name, DRCCurStyle->ds_name)) + { + DRCCurStyle->ds_name = NULL; + drcLoadStyle(style->ds_name); + break; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * DRCTechInit -- + * + * Free and re-initialize the technology-specific variables for the DRC module. + * This routine is *only* called upon a "tech load" command, when all existing + * DRC data must be cleaned up and free'd. + * + * Results: + * None. + * + * Side effects: + * Clears out all the DRC tables. + * ---------------------------------------------------------------------------- + */ + +void +DRCTechInit() +{ + DRCKeep *style; + + /* Clean up any old info */ + + drcTechFreeStyle(); + + for (style = DRCStyleList; style != NULL; style = style->ds_next) + { + freeMagic(style->ds_name); + freeMagic(style); + } + DRCStyleList = NULL; +} + +/* + * ---------------------------------------------------------------------------- + * DRCTechStyleInit -- + * + * Initialize the technology-specific variables for the DRC module. + * + * Results: + * None. + * + * Side effects: + * Clears out all the DRC tables. + * ---------------------------------------------------------------------------- + */ + +void +DRCTechStyleInit() +{ + int i, j, plane; + DRCCookie *dp; + PaintResultType result; + + drcRulesOptimized = 0; + drcRulesSpecified = 0; + + if (DRCCurStyle == NULL) + { + DRCCurStyle = (DRCStyle *) mallocMagic(sizeof(DRCStyle)); + DRCCurStyle->ds_name = NULL; + } + + DRCCurStyle->ds_status = TECH_NOT_LOADED; + + TTMaskZero(&DRCCurStyle->DRCExactOverlapTypes); + DRCCurStyle->DRCWhyList = NULL; + DRCCurStyle->DRCTechHalo = 0; + DRCCurStyle->DRCScaleFactorN = 1; + DRCCurStyle->DRCScaleFactorD = 1; + DRCCurStyle->DRCStepSize = 0; + + DRCTechHalo = 0; + + /* Put a dummy rule at the beginning of the rules table for each entry */ + + for (i = 0; i < TT_MAXTYPES; i++) + { + for (j = 0; j < TT_MAXTYPES; j++) + { + dp = DRCCurStyle->DRCRulesTbl[i][j]; + dp = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + dp->drcc_dist = -1; + dp->drcc_cdist = -1; + dp->drcc_next = (DRCCookie *) NULL; + TTMaskZero(&dp->drcc_mask); + DRCCurStyle->DRCRulesTbl[i][j] = dp; + } + } + + /* Copy the default paint table into the DRC paint table. The DRC + * paint table will be modified as we read the drc section. Also + * make sure that the error layer is super-persistent (once it + * appears, it can't be gotten rid of by painting). Also, make + * some crossings automatically illegal: two layers can't cross + * unless the result of painting one on top of the other is to + * get one of the layers, and it doesn't matter which is painted + * on top of which. + */ + + for (plane = 0; plane < DBNumPlanes; plane++) + for (i = 0; i < DBNumTypes; i++) + for (j = 0; j < DBNumTypes; j++) + { + result = DBPaintResultTbl[plane][i][j]; + if ((i == TT_ERROR_S) || (j == TT_ERROR_S)) + DRCCurStyle->DRCPaintTable[plane][i][j] = TT_ERROR_S; + else if ((i == TT_SPACE) || (j == TT_SPACE) + || !DBTypeOnPlane(j, plane) + || !DBPaintOnTypePlanes(i, j)) + DRCCurStyle->DRCPaintTable[plane][i][j] = result; + + /* Modified for stackable types (Tim, 10/3/03) */ + else if ((i >= DBNumUserLayers) || + ((result >= DBNumUserLayers) + && (DBTechFindStacking(i, j) == result))) + { + DRCCurStyle->DRCPaintTable[plane][i][j] = result; + } + + else if ((!TTMaskHasType(&DBLayerTypeMaskTbl[i], result) + && !TTMaskHasType(&DBLayerTypeMaskTbl[j], result)) + || ((result != DBPaintResultTbl[plane][j][i]) + && DBTypeOnPlane(i, plane) + && DBPaintOnTypePlanes(j, i))) + { + DRCCurStyle->DRCPaintTable[plane][i][j] = TT_ERROR_S; + /* TxError("Error: %s on %s, was %s\n", + DBTypeLongNameTbl[i], DBTypeLongNameTbl[j], + DBTypeLongNameTbl[result]); */ + } + else + DRCCurStyle->DRCPaintTable[plane][i][j] = result; + } + + drcCifInit(); +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCTechLine -- + * + * Parse a line in the DRC section from the technology file. Handle DRC + * styles. The rules themselves are handled by DRCTechAddRule. + * + * Results: + * TRUE if line parsed correctly; FALSE if fatal error condition + * encountered. + * + * Side effects: + * Appends information to the DRC tables. + * + * ---------------------------------------------------------------------------- + */ + +bool +DRCTechLine(sectionName, argc, argv) + char *sectionName; /* The name of this section */ + int argc; /* Number of fields on the line */ + char *argv[]; /* Values of the fields */ +{ + int j, l; + DRCKeep *newStyle, *p; + char *tptr, *cptr; + + if (argc <= 0) return TRUE; + else if (argc >= 2) l = strlen(argv[1]); + + if (strcmp(argv[0], "style") == 0) + { + if (argc != 2) + { + if ((argc != 4) || (strncmp(argv[2], "variant", 7))) + { + wrongNumArgs: + TechError("Wrong number of arguments in %s statement.\n", + argv[0]); + return TRUE; + } + } + for (newStyle = DRCStyleList; newStyle != NULL; + newStyle = newStyle->ds_next) + { + /* Here we're only establishing existence; break on + * the first variant found. + */ + if (!strncmp(newStyle->ds_name, argv[1], l)) + break; + } + if (newStyle == NULL) + { + if (argc == 2) + { + newStyle = (DRCKeep *)mallocMagic(sizeof(DRCKeep)); + newStyle->ds_next = NULL; + newStyle->ds_name = StrDup((char **) NULL, argv[1]); + + /* Append to end of style list */ + if (DRCStyleList == NULL) + DRCStyleList = newStyle; + else + { + for (p = DRCStyleList; p->ds_next; p = p->ds_next); + p->ds_next = newStyle; + } + } + else /* Handle style variants */ + { + DRCKeep *saveStyle = NULL; + + /* 4th argument is a comma-separated list of variants */ + + tptr = argv[3]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) *cptr = '\0'; + newStyle = (DRCKeep *)mallocMagic(sizeof(DRCKeep)); + newStyle->ds_next = NULL; + newStyle->ds_name = (char *)mallocMagic(l + + strlen(tptr) + 1); + sprintf(newStyle->ds_name, "%s%s", argv[1], tptr); + + /* Remember the 1st variant as the default */ + if (saveStyle == NULL) saveStyle = newStyle; + + /* Append to end of style list */ + if (DRCStyleList == NULL) + DRCStyleList = newStyle; + else + { + for (p = DRCStyleList; p->ds_next; p = p->ds_next); + p->ds_next = newStyle; + } + + if (cptr == NULL) + break; + else + tptr = cptr + 1; + } + newStyle = saveStyle; + } + } + + if (DRCCurStyle == NULL) /* Shouldn't happen, but be safe. . .*/ + { + drcTechNewStyle(); + DRCCurStyle->ds_name = newStyle->ds_name; + DRCCurStyle->ds_status = TECH_PENDING; + } + else if ((DRCCurStyle->ds_status == TECH_PENDING) || + (DRCCurStyle->ds_status == TECH_SUSPENDED)) + DRCCurStyle->ds_status = TECH_LOADED; + else if (DRCCurStyle->ds_status == TECH_NOT_LOADED) + { + if (DRCCurStyle->ds_name == NULL) { + DRCCurStyle->ds_name = newStyle->ds_name; + DRCCurStyle->ds_status = TECH_PENDING; + } + else if (argc == 2) + { + if (!strcmp(argv[1], DRCCurStyle->ds_name)) + DRCCurStyle->ds_status = TECH_PENDING; + } + else if (argc == 4) + { + /* Verify that the style matches one variant */ + + if (!strncmp(DRCCurStyle->ds_name, argv[1], l)) + { + tptr = argv[3]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) *cptr = '\0'; + if (!strcmp(DRCCurStyle->ds_name + l, tptr)) + { + DRCCurStyle->ds_status = TECH_PENDING; + return TRUE; + } + if (cptr == NULL) + return TRUE; + else + tptr = cptr + 1; + } + } + } + } + return (TRUE); + } + + if (DRCCurStyle == NULL) + return FALSE; + + /* For backwards compatibility, if we have encountered a line that */ + /* is not "style" prior to setting a style, then we create a style */ + /* called "default". */ + + if (DRCStyleList == NULL) + { + char *locargv[2][10] = {"style", "default"}; + + if (DRCTechLine(sectionName, 2, locargv) == FALSE) + return FALSE; + } + else if (DRCStyleList->ds_next == NULL) + { + /* On reload, if there is only one style, use it. This is */ + /* necessary for the DRC-CIF extensions, since even though */ + /* the one-and-only DRC section may have been loaded, the DRC- */ + /* CIF parts of it become enabled or disabled depending on what */ + /* CIFCurStyle is active. */ + + DRCCurStyle->ds_status = TECH_PENDING; + } + + /* Only continue past this point if we are loading the DRC style */ + + if ((DRCCurStyle->ds_status != TECH_PENDING) && + (DRCCurStyle->ds_status != TECH_SUSPENDED)) + return TRUE; + + /* Process "scalefactor" line next (if any) */ + + if (strcmp(argv[0], "scalefactor") == 0) + { + int scaleN, scaleD; + + if (argc != 2 && argc != 3) goto wrongNumArgs; + + scaleN = atof(argv[1]); + + if (argc == 3) + scaleD = atof(argv[2]); + else + scaleD = 1; + + if (scaleN <= 0 || scaleD <= 0) + { + TechError("Scale factor must be greater than 0.\n"); + TechError("Setting scale factor to default value 1.\n"); + DRCCurStyle->DRCScaleFactorN = 1; + DRCCurStyle->DRCScaleFactorD = 1; + return TRUE; + } + DRCCurStyle->DRCScaleFactorN = scaleN; + DRCCurStyle->DRCScaleFactorD = scaleD; + return TRUE; + } + + /* Process "variant" lines next. */ + + if (strncmp(argv[0], "variant", 7) == 0) + { + /* If our style variant is not one of the ones declared */ + /* on the line, then we ignore all input until we */ + /* either reach the end of the style, the end of the */ + /* section, or another "variant" line. */ + + if (argc != 2) goto wrongNumArgs; + tptr = argv[1]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) + { + *cptr = '\0'; + for (j = 1; isspace(*(cptr - j)); j++) + *(cptr - j) = '\0'; + } + + if (*tptr == '*') + { + DRCCurStyle->ds_status = TECH_PENDING; + return TRUE; + } + else + { + l = strlen(DRCCurStyle->ds_name) - strlen(tptr); + if (!strcmp(tptr, DRCCurStyle->ds_name + l)) + { + DRCCurStyle->ds_status = TECH_PENDING; + return TRUE; + } + } + + if (cptr == NULL) + break; + else + tptr = cptr + 1; + } + DRCCurStyle->ds_status = TECH_SUSPENDED; + } + + /* Anything below this line is not parsed if we're in TECH_SUSPENDED mode */ + if (DRCCurStyle->ds_status != TECH_PENDING) return TRUE; + + return DRCTechAddRule(sectionName, argc, argv); +} + +void +drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefrom) + DRCCookie *cookie, *next; + int dist, cdist; + TileTypeBitMask *mask, *corner; + char *why; + int flags, planeto, planefrom; +{ + /* Diagnostic */ + if (planeto >= DBNumPlanes) { + TxError("Bad plane in DRC assign!\n"); + } + (cookie)->drcc_dist = dist; + (cookie)->drcc_next = next; + (cookie)->drcc_mask = *mask; + (cookie)->drcc_corner = *corner; + (cookie)->drcc_why = why; + (cookie)->drcc_cdist = cdist; + (cookie)->drcc_flags = flags; + (cookie)->drcc_edgeplane = planefrom; + (cookie)->drcc_plane = planeto; + (cookie)->drcc_mod = 0; + (cookie)->drcc_cmod = 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCTechAddRule -- + * + * Add a new entry to the DRC table. + * + * Results: + * Always returns TRUE so that tech file read-in doesn't abort. + * + * Side effects: + * Updates the DRC technology variables. + * + * Organization: + * We select a procedure based on the first keyword (argv[0]) + * and call it to do the work of implementing the rule. Each + * such procedure is of the following form: + * + * int + * proc(argc, argv) + * int argc; + * char *argv[]; + * { + * } + * + * It returns the distance associated with the design rule, + * or -1 in the event of a fatal error that should cause + * DRCTechAddRule() to return FALSE (currently, none of them + * do, so we always return TRUE). If there is no distance + * associated with the design rule, 0 is returned. + * + * ---------------------------------------------------------------------------- + */ + + + /* ARGSUSED */ +bool +DRCTechAddRule(sectionName, argc, argv) + char *sectionName; /* Unused */ + int argc; + char *argv[]; +{ + int which, distance, mdist; + char *fmt; + static struct + { + char *rk_keyword; /* Initial keyword */ + int rk_minargs; /* Min # arguments */ + int rk_maxargs; /* Max # arguments */ + int (*rk_proc)(); /* Procedure implementing this keyword */ + char *rk_err; /* Error message */ + } ruleKeys[] = { + "angles", 4, 4, drcAngles, + "layers 45|90 why", + "edge", 8, 9, drcEdge, + "layers1 layers2 distance okTypes cornerTypes cornerDistance why [plane]", + "edge4way", 8, 9, drcEdge, + "layers1 layers2 distance okTypes cornerTypes cornerDistance why [plane]", + "exact_overlap", 2, 2, drcExactOverlap, + "layers", + "extend", 5, 6, drcExtend, + "layers1 layers2 distance why", + "no_overlap", 3, 3, drcNoOverlap, + "layers1 layers2", + "overhang", 5, 5, drcOverhang, + "layers1 layers2 distance why", + "rect_only", 3, 3, drcRectOnly, + "layers why", + "spacing", 6, 7, drcSpacing, + "layers1 layers2 separation [layers3] adjacency why", + "stepsize", 2, 2, drcStepSize, + "step_size", + "surround", 6, 6, drcSurround, + "layers1 layers2 distance presence why", + "width", 4, 4, drcWidth, + "layers width why", + "widespacing", 7, 7, drcSpacing, + "layers1 width layers2 separation adjacency why", + "area", 5, 5, drcArea, + "layers area horizon why", + "maxwidth", 4, 5, drcMaxwidth, + "layers maxwidth bends why", + "cifstyle", 2, 2, drcCifSetStyle, + "cif_style", + "cifwidth", 4, 4, drcCifWidth, + "layers width why", + "cifspacing", 6, 6, drcCifSpacing, + "layers1 layers2 separation adjacency why", + "cifarea", 5, 5, drcCifArea, + "layers area horizon why", + "cifmaxwidth", 5, 5, drcCifMaxwidth, + "layers maxwidth bends why", + "rectangle", 5, 5, drcRectangle, + "layers maxwidth [even|odd|any] why", + 0 + }, *rp; + + drcRulesSpecified += 1; + + which = LookupStruct(argv[0], (LookupTable *) ruleKeys, sizeof ruleKeys[0]); + if (which < 0) + { + TechError("Bad DRC rule type \"%s\"\n", argv[0]); + TxError("Valid rule types are:\n"); + for (fmt = "%s", rp = ruleKeys; rp->rk_keyword; rp++, fmt = ", %s") + TxError(fmt, rp->rk_keyword); + TxError(".\n"); + return (TRUE); + } + rp = &ruleKeys[which]; + if (argc < rp->rk_minargs || argc > rp->rk_maxargs) + { + TechError("Rule type \"%s\" usage: %s %s\n", + rp->rk_keyword, rp->rk_keyword, rp->rk_err); + return (TRUE); + } + + distance = (*rp->rk_proc)(argc, argv); + if (distance < 0) + return (FALSE); + + /* Update the halo to be the maximum distance (in magic units) of */ + /* any design rule */ + + mdist = distance; + + if (mdist > DRCTechHalo) + DRCTechHalo = mdist; + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcExtend -- + * + * Process an extension rule. + * This is of the form: + * + * extend layers1 layers2 distance [exact_width] why + * + * indicating that if "layers1" extends from "layers2", then it must + * have a width of at least "distance". This is very much like the + * "overhang" rule, except that the extension is optional. Example: + * + * extend nfet ndiff 2 "n-transistor length must be at least 2" + * + * "extend" implements the following general-purpose edge rule: + * + * edge4way layers2 layers1 distance layers1 0 0 why + * + * Option "exact_width" implements an additional rule that checks for + * maximum extension at distance. This is intended for use with, for + * example, a fixed gate length for a specific type of device. + * + * Results: + * Returns distance. + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcExtend(argc, argv) + int argc; + char *argv[]; +{ + char *layers1 = argv[1]; + char *layers2 = argv[2]; + int distance = atoi(argv[3]); + char *why; + TileTypeBitMask set1, setC; + DRCCookie *dp, *dpnew, *dptrig; + TileType i, j; + int plane, plane2; + TileTypeBitMask set2, setZ, setN; + PlaneMask pMask1, pMask2, pset, ptest; + bool exact = FALSE; + + if (!strncmp(argv[4], "exact_", 6)) + { + exact = TRUE; + why = drcWhyDup(argv[5]); + } + else + why = drcWhyDup(argv[4]); + + ptest = DBTechNoisyNameMask(layers1, &set1); + pMask1 = CoincidentPlanes(&set1, ptest); + + if (pMask1 == 0) + { + TechError("All layers in first set for \"extend\" must be on " + "the same plane\n"); + return (0); + } + TTMaskCom2(&setN, &set1); + + ptest = DBTechNoisyNameMask(layers2, &set2); + pMask2 = CoincidentPlanes(&set2, ptest); + + if (pMask2 == 0) + { + TechError("All layers in second set for \"extend\" must be on " + "the same plane\n"); + return (0); + } + TTMaskCom2(&setC, &set2); + + /* Zero mask */ + TTMaskZero(&setZ); + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + if (pset = (DBTypesOnSamePlane(i, j) & pMask2)) + { + /* Edge depends on whether or not the extension is */ + /* on the same plane as the layer from which it is */ + /* measured. */ + + if ((pset & pMask1) != 0) + { + if (TTMaskHasType(&set2, i) && TTMaskHasType(&set1, j)) + { + plane = LowestMaskBit(pset & pMask1); + + /* find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set1, &setZ, why, + 0, DRC_FORWARD, plane, plane); + + dp->drcc_next = dpnew; + + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set1, &setZ, why, + 0, DRC_REVERSE, plane, plane); + + dp->drcc_next = dpnew; + + if (exact) + { + /* find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &setN, &setZ, why, + 0, DRC_FORWARD | DRC_OUTSIDE, plane, plane); + + dp->drcc_next = dpnew; + + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &setN, &setZ, why, + 0, DRC_REVERSE | DRC_OUTSIDE, plane, plane); + + dp->drcc_next = dpnew; + } + } + } + else /* Multi-plane extend rule */ + { + if (TTMaskHasType(&set2, i) && TTMaskHasType(&setC, j)) + { + plane = LowestMaskBit(pset); + plane2 = LowestMaskBit(pMask1); + + /* find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set1, &setZ, why, + 0, DRC_FORWARD, plane2, plane); + dptrig = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dptrig, 1, dpnew, &setN, &setZ, why, + 0, DRC_FORWARD | DRC_TRIGGER, plane2, plane); + dp->drcc_next = dptrig; + + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set1, &setZ, why, + 0, DRC_REVERSE, plane2, plane); + dptrig = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dptrig, 1, dpnew, &setN, &setZ, why, + 0, DRC_REVERSE | DRC_TRIGGER, plane2, plane); + dp->drcc_next = dptrig; + } + } + } + } + } + return (distance); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcWidth -- + * + * Process a width rule. + * This is of the form: + * + * width layers distance why + * + * e.g, + * + * width poly,pmc 2 "poly width must be at least 2" + * + * Optional "from layers2" is useful when defining a device width; + * effectively, it represents an overhang rule where the presence of + * the overhanging material is optional. The equivalent rule is: + * + * edge4way layers2 layers distance layers 0 0 why + * + * + * Results: + * Returns distance. + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcWidth(argc, argv) + int argc; + char *argv[]; +{ + char *layers = argv[1]; + int distance = atoi(argv[2]); + char *why = drcWhyDup(argv[3]); + TileTypeBitMask set, setC; + PlaneMask pmask, pset, ptest; + DRCCookie *dp, *dpnew; + TileType i, j; + int plane; + + ptest = DBTechNoisyNameMask(layers, &set); + pmask = CoincidentPlanes(&set, ptest); + TTMaskCom2(&setC, &set); + + if (pmask == 0) + { + TechError("All layers for \"width\" must be on same plane\n"); + return (0); + } + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + /* + * Must have types in 'set' for at least 'distance' + * to the right of any edge between a type in '~set' + * and a type in 'set'. + */ + + if (pset = (DBTypesOnSamePlane(i, j) & pmask)) + { + if (TTMaskHasType(&setC, i) && TTMaskHasType(&set, j)) + { + plane = LowestMaskBit(pset); + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set, &set, + why, distance, DRC_FORWARD, plane, plane); + dp->drcc_next = dpnew; + } + } + } + } + return (distance); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcArea -- + * + * Process an area rule. + * This is of the form: + * + * area layers area horizon why + * + * e.g, + * + * area pmc 4 2 "poly contact area must be at least 4" + * + * "area" is the total area in lambda^2. + * + * "horizon" is the halo distance for the check. Normally, this would + * be the area (in lambda^2) divided by the minimum width rule (in + * lambda). Anything larger would not be a violation as long as the + * minimum width rule is satisfied. + * + * Results: + * Returns distance. + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcArea(argc, argv) + int argc; + char *argv[]; +{ + char *layers = argv[1]; + int distance = atoi(argv[2]); + int horizon = atoi(argv[3]); + char *why = drcWhyDup(argv[4]); + TileTypeBitMask set, setC; + DRCCookie *dp, *dpnew; + TileType i, j; + PlaneMask pmask, ptest, pset; + int plane; + + ptest = DBTechNoisyNameMask(layers, &set); + pmask = CoincidentPlanes(&set, ptest); + TTMaskCom2(&setC, &set); + + if (pmask == 0) + { + TechError("All layers for \"area\" must be on same plane\n"); + return (0); + } + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + /* + * Must have types in 'set' for at least 'distance' + * to the right of any edge between a type in '~set' + * and a type in 'set'. + */ + if (pset = (DBTypesOnSamePlane(i, j) & pmask)) + { + if (TTMaskHasType(&setC, i) && TTMaskHasType(&set, j)) + { + plane = LowestMaskBit(pset); + + /* find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, horizon); + dpnew = (DRCCookie *) mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew, horizon, dp->drcc_next, &set, &set, why, + distance, DRC_AREA|DRC_FORWARD, plane, plane); + + dp->drcc_next = dpnew; + } + } + } + } + return (horizon); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcMaxwidth -- + * + * Process a maxwidth rule. + * This is of the form: + * + * maxwidth layers distance [bends] why + * + * This routine was updated 3/6/05 to match the "canonical" definition of + * a maxwidth region, which is any rectangle containing that is + * at least in both width and height. If the keyword + * "bend_illegal" is present, then the definition reverts to the original + * (see below) for backwards-compatibility. Otherwise ("bend_ok" or + * nothing), the new routine is used. + * + * maxwidth metal1 389 "metal1 width > 35um must be slotted" + * maxwidth pmc 4 bend_illegal "poly contact area must be no wider than 4" + * maxwidth trench 4 bend_ok "trench width must be exactly 4" + * + * bend_illegal - means that one_dimension must be distance for any + * point in the region. This is used for emitters and contacts + * that are rectangular (so we can't generate them with the + * squares command) and some exact width in one direction. + * bend_ok - Used mainly for wide metal rules where metal greater than + * some given width must be slotted. Also, used for things + * like trench, where the width is some fixed value: + * + * XXXXX XXXXXX + * X X XXXXXX + * X X X X + * XXXXX XXXXXX + * + * OK BAD + * + * Results: + * Returns distance. + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcMaxwidth(argc, argv) + int argc; + char *argv[]; +{ + char *layers = argv[1]; + int distance = atoi(argv[2]); + char *bends = argv[3]; + char *why; + TileTypeBitMask set, setC; + DRCCookie *dp, *dpnew; + TileType i, j; + PlaneMask pmask, ptest, pset; + int plane; + int bend; + + ptest = DBTechNoisyNameMask(layers, &set); + pmask = CoincidentPlanes(&set, ptest); + TTMaskCom2(&setC, &set); + + if (pmask == 0) + { + TechError("All layers for \"maxwidth\" must be on same plane\n"); + return (0); + } + + if (argc == 4) + { + /* "bends" is irrelevent if distance is zero, so choose the */ + /* faster algorithm to process */ + + if (distance == 0) + bend = 0; + else + bend = DRC_BENDS; + why = drcWhyDup(argv[3]); + } + else + { + if (strcmp(bends,"bend_illegal") == 0) bend = 0; + else if (strcmp(bends,"bend_ok") == 0) bend = DRC_BENDS; + else + { + TechError("unknown bend option %s\n",bends); + return (0); + } + why = drcWhyDup(argv[4]); + } + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + /* + * Must have types in 'set' for at least 'distance' + * to the right of any edge between a type in '~set' + * and a type in 'set'. + */ + if (pset = (DBTypesOnSamePlane(i, j) & pmask)) + { + if (TTMaskHasType(&setC, i) && TTMaskHasType(&set, j)) + { + plane = LowestMaskBit(pset); + + /* find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *) mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set, &set, why, + distance, DRC_MAXWIDTH | bend, plane, plane); + + dp->drcc_next = dpnew; + } + } + } + } + return (distance); +} + +/* + * ---------------------------------------------------------------------------- + * drcAngles -- + * + * Process an "angles" rule specifying that geometry for a certain layer + * must be limited to 90 degrees or 45 degrees. If not specified, any + * angle is allowed, although width rules will flag errors on acute angles. + * + * ---------------------------------------------------------------------------- + */ + +int +drcAngles(argc, argv) + int argc; + char *argv[]; +{ + char *layers = argv[1]; + int angles = atoi(argv[2]); + char *why = drcWhyDup(argv[3]); + TileTypeBitMask set; + DRCCookie *dp, *dpnew; + int plane; + TileType i, j; + + DBTechNoisyNameMask(layers, &set); + + angles /= 45; + angles--; /* angles now 0 for 45s and 1 for 90s */ + + if ((angles != 0) && (angles != 1)) + { + TechError("angles must be 45 or 90\n"); + return 0; + } + + for (i = 0; i < DBNumTypes; i++) + { + if (TTMaskHasType(&set, i)) + { + plane = DBPlane(i); + + /* Insert rule at boundary of tile and TT_SPACE. This is */ + /* processed for each tile, separately from other rules, so */ + /* we don't really care what the edge is; TT_SPACE is */ + /* chosen as an arbitrary place to hold the rule. */ + + dp = drcFindBucket(TT_SPACE, i, 1); + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, 1, dp->drcc_next, &set, &set, why, + 1, DRC_ANGLES | angles, plane, plane); + dp->drcc_next = dpnew; + } + } + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcSpacing3 -- + * + * Process a special spacing rule of the form: + * + * spacing layers1 layers2 distance corner_ok layers3 why + * + * This spacing rule is not checked when a type from "layers3" fills the + * corner between "layers1" and "layers2". This is used, e.g., for + * diffusion-to-poly spacing, where diffusion and poly may touch at the + * corner of a FET type. It is equivalent to: + * + * edge4way layers1 ~(layers3,layers1) distance ~(layers2) 0 0 why + * + * ---------------------------------------------------------------------------- + */ + +int +drcSpacing3(argc, argv) + int argc; + char *argv[]; +{ + char *layers1 = argv[1], *layers2 = argv[2]; + char *layers3 = argv[5]; + int distance = atoi(argv[3]); + char *adjacency = argv[4]; + char *why = drcWhyDup(argv[6]); + TileTypeBitMask set1, set2, set3; + int plane; + DRCCookie *dp, *dpnew; + TileType i, j; + PlaneMask pmask, pset, ptest; + + ptest = DBTechNoisyNameMask(layers1, &set1); + pmask = CoincidentPlanes(&set1, ptest); + + ptest = DBTechNoisyNameMask(layers2, &set2); + pmask &= CoincidentPlanes(&set2, ptest); + + ptest = DBTechNoisyNameMask(layers3, &set3); + pmask &= CoincidentPlanes(&set3, ptest); + + if (pmask == 0) + { + TechError("Spacing check with \"corner_ok\" must have" + " all types in one plane.\n"); + return (0); + } + + /* In this usage everything must fall in the same plane. */ + + /* We need masks for (~types2)/plane and for (~(types1,types3))/plane */ + + TTMaskCom(&set2); + TTMaskSetMask(&set3, &set1); + TTMaskCom(&set3); + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + if (pset = (DBTypesOnSamePlane(i, j) & pmask)) + { + if (TTMaskHasType(&set1, i) && TTMaskHasType(&set3, j)) + { + plane = LowestMaskBit(pset); + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set2, &set3, + why, distance, DRC_FORWARD | DRC_BOTHCORNERS, + plane, plane); + dp->drcc_next = dpnew; + + /* find bucket preceding new one we wish to insert */ + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set2, &set3, + why, distance, DRC_REVERSE | DRC_BOTHCORNERS, + plane, plane); + dp->drcc_next = dpnew; + } + } + } + } + return distance; +} + +/* + *------------------------------------------------------------------- + * + * drcMaskSpacing --- + * + * This is the core of the drcSpacing routine. When the spacing + * rule layers independently cover more than one plane, this routine + * is invoked for each independent plane. + * + * Results: + * Returns the rule's maximum distance + * + * Side effects: + * Adds rules to the DRC rule table. + * + *------------------------------------------------------------------- + */ + +int +drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency, + why, widerule, multiplane) + TileTypeBitMask *set1, *set2; + PlaneMask pmask1, pmask2; + int wwidth, distance; + char *adjacency, *why; + bool widerule, multiplane; +{ + TileTypeBitMask tmp1, tmp2, setR, setRreverse; + int plane, plane2; + PlaneMask pset, ptest; + DRCCookie *dp, *dpnew; + int needReverse = (widerule) ? TRUE : FALSE; + TileType i, j, pref; + bool needtrigger = FALSE; + bool touchingok = TRUE; + bool cornerok = FALSE; + + if (!strcmp(adjacency, "surround_ok")) + { + if (multiplane) + { + TechError("\"surround_ok\" requires surrounding types to " + "be in the same plane.\n"); + return (0); + } + else if ((pmask1 & pmask2) == 0) + { + /* New rule implementation (7/8/06): When types */ + /* are on different planes and "surround_ok" is */ + /* declared, implement as a triggered rule (but not */ + /* for widespacing, which already uses the */ + /* triggering rule mechanism). */ + + if (!widerule) + { + needtrigger = TRUE; + touchingok = FALSE; + + } + else + { + TechError("Widespacing checks cannot use \"surround_ok\".\n"); + return (0); + } + } + else + { + TechError("\"surround_ok\" used when spacing rule types are in " + "the same plane. Did you mean \"touching_ok\"?\n"); + touchingok = TRUE; /* Treat like "touching_ok" */ + } + } + else if (!strcmp(adjacency, "touching_ok")) + { + /* If touching is OK, everything must fall in the same plane. */ + if (multiplane || ((pmask1 & pmask2) == 0)) + { + TechError("Spacing check with \"touching_ok\" must have" + " all types in one plane. Possibly you want" + " \"surround_ok\"?\n"); + return (0); + } + else + touchingok = TRUE; + } + else if (!strcmp(adjacency, "touching_illegal")) + { + touchingok = FALSE; + needtrigger = FALSE; + } + else + { + TechError("Badly formed drc spacing line: need \"touching_ok\", " + "\"touching_illegal\", or \"surround_ok\".\n"); + return (0); + } + + if (touchingok) + { + /* In "touching_ok rules, spacing to set2 is be checked in FORWARD + * direction at edges between set1 and (setR = ~set1 AND ~set2). + * + * In addition, spacing to set1 is checked in FORWARD direction + * at edges between set2 and (setRreverse = ~set1 AND ~set2). + * + * If set1 and set2 are different, above are checked in REVERSE as + * well as forward direction. This is important since touching + * material frequently masks violations in one direction. + * + * setR and setRreverse are set appropriately below. + */ + + tmp1 = *set1; + tmp2 = *set2; + + /* Restrict planes to those that are coincident */ + pmask1 &= pmask2; + pmask2 = pmask1; + TTMaskCom(&tmp1); + TTMaskCom(&tmp2); + TTMaskAndMask(&tmp1, &tmp2); + setR = tmp1; + setRreverse = tmp1; + + /* If set1 != set2, set flag to check rules in both directions */ + if (!TTMaskEqual(set1, set2)) + needReverse = TRUE; + } + else + { + /* In "touching_illegal" rules, spacing to set2 will be checked + * in FORWARD direction at edges between set1 and (setR=~set1). + * + * In addition, spacing to set1 will be checked in FORWARD direction + * at edges between set2 and (setRreverse= ~set2). + * + * setR and setRreverse are set appropriately below. + */ + TTMaskCom2(&setR, set1); + TTMaskCom2(&setRreverse, set2); + } + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + if (pset = (DBTypesOnSamePlane(i, j) & pmask1)) + { + plane = LowestMaskBit(pset); + + /* LHS is an element of set1, RHS is an element of setR */ + if (TTMaskHasType(set1, i) && TTMaskHasType(&setR, j)) + { + plane2 = LowestMaskBit(pmask2); + + /* + * Must not have 'set2' for 'distance' to the right of + * an edge between 'set1' and the types not in 'set1' + * (touching_illegal case) or in neither + * 'set1' nor 'set2' (touching_ok case). + */ + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + TTMaskClearMask3(&tmp1, &DBPlaneTypes[plane2], set2); + TTMaskAndMask3(&tmp2, &DBPlaneTypes[plane], &setR); + + if (widerule) + { + DRCCookie *dptrig; + + /* Create two contiguous rules, one for spacing */ + /* and one for width. These are created in */ + /* reverse order due to the stack property of */ + /* the linked list. */ + + drcAssign(dpnew, distance, dp->drcc_next, &tmp1, &tmp2, + why, distance, DRC_FORWARD, plane2, plane); + dptrig = (DRCCookie *) mallocMagic((unsigned) + (sizeof (DRCCookie))); + drcAssign(dptrig, wwidth, dpnew, set1, set1, why, + wwidth, DRC_REVERSE | DRC_MAXWIDTH | + DRC_TRIGGER | DRC_BENDS, plane2, plane); + + dp->drcc_next = dptrig; + } + else if (needtrigger) + { + DRCCookie *dptrig; + + /* Create two contiguous spacing rules */ + + drcAssign(dpnew, distance, dp->drcc_next, &tmp1, &tmp2, + why, wwidth, DRC_FORWARD | DRC_BOTHCORNERS, + plane2, plane); + dptrig = (DRCCookie *) mallocMagic((unsigned) + (sizeof (DRCCookie))); + drcAssign(dptrig, 1, dpnew, set2, &tmp2, why, 1, + DRC_FORWARD | DRC_TRIGGER, + plane2, plane); + + dp->drcc_next = dptrig; + } + else + { + drcAssign(dpnew, distance, dp->drcc_next, &tmp1, + &tmp2, why, wwidth, DRC_FORWARD, plane2, plane); + dp->drcc_next = dpnew; + } + + if (needReverse) + dpnew->drcc_flags |= DRC_BOTHCORNERS; + + if (needReverse) + { + /* Add check in reverse direction, + * NOTE: am assuming single plane rule here (since reverse + * rules only used with touching_ok which must be + * single plane) + */ + + /* find bucket preceding new one we wish to insert */ + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + if (widerule) + { + DRCCookie *dptrig; + + /* Assign two coupled rules (see above) */ + + drcAssign(dpnew, distance, dp->drcc_next, &tmp1, + &tmp2, why, distance, + DRC_REVERSE | DRC_BOTHCORNERS, plane2, plane); + dptrig = (DRCCookie *) mallocMagic((unsigned) + (sizeof (DRCCookie))); + drcAssign(dptrig, wwidth, dpnew, set1, set1, why, + wwidth, DRC_FORWARD | DRC_MAXWIDTH | + DRC_TRIGGER | DRC_BENDS, plane2, plane); + dp->drcc_next = dptrig; + } + else if (needtrigger) + { + DRCCookie *dptrig; + + /* Create two contiguous spacing rules */ + + drcAssign(dpnew, distance, dp->drcc_next, &tmp1, &tmp2, + why, wwidth, DRC_REVERSE | DRC_BOTHCORNERS, + plane2, plane); + dptrig = (DRCCookie *) mallocMagic((unsigned) + (sizeof (DRCCookie))); + drcAssign(dptrig, 1, dpnew, set2, &tmp2, why, 1, + DRC_REVERSE | DRC_TRIGGER, + plane2, plane); + + dp->drcc_next = dptrig; + } + else + { + drcAssign(dpnew,distance,dp->drcc_next, + &tmp1, &tmp2, why, wwidth, + DRC_REVERSE | DRC_BOTHCORNERS, plane2, plane); + dp->drcc_next = dpnew; + } + } + } + } + + if (TTMaskEqual(set1, set2)) continue; + if (widerule) continue; /* Can't determine width of set1 */ + /* when looking at the edge of set2 */ + + /* + * Now, if set1 and set2 are distinct apply the rule for LHS in set1 + * and RHS in set2. + */ + + if (pset = (DBTypesOnSamePlane(i, j) & pmask2)) + { + plane = LowestMaskBit(pset); + + /* LHS is an element of set2, RHS is an element of setRreverse */ + if (TTMaskHasType(set2, i) && TTMaskHasType(&setRreverse, j)) + { + plane2 = LowestMaskBit(pmask1); + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + TTMaskClearMask3(&tmp1, &DBPlaneTypes[plane2], set1); + TTMaskAndMask3(&tmp2, &DBPlaneTypes[plane], &setRreverse); + + if (needtrigger) + { + DRCCookie *dptrig; + + /* Create two contiguous spacing rules */ + + drcAssign(dpnew, distance, dp->drcc_next, &tmp1, &tmp2, + why, distance, DRC_FORWARD | DRC_BOTHCORNERS, + plane2, plane); + dptrig = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dptrig, 1, dpnew, set1, &tmp2, why, 1, + DRC_FORWARD | DRC_TRIGGER, + plane2, plane); + dp->drcc_next = dptrig; + } + else + { + drcAssign(dpnew, distance, dp->drcc_next, &tmp1, &tmp2, + why, distance, DRC_FORWARD, plane2, plane); + dp->drcc_next = dpnew; + } + + if (needReverse) + dpnew->drcc_flags |= DRC_BOTHCORNERS; + + if (needReverse) + { + /* Add check in reverse direction, + * NOTE: am assuming single plane rule here (since reverse + * rules only used with touching_ok which must be + * single plane) + */ + /* find bucket preceding new one we wish to insert */ + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *) mallocMagic(sizeof (DRCCookie)); + + if (needtrigger) + { + DRCCookie *dptrig; + + /* Create two contiguous spacing rules */ + + drcAssign(dpnew, distance, dp->drcc_next, &tmp1, &tmp2, + why, distance, DRC_REVERSE | DRC_BOTHCORNERS, + plane2, plane); + dptrig = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dptrig, 1, dpnew, set1, &tmp2, why, 1, + DRC_REVERSE | DRC_TRIGGER, + plane2, plane); + dp->drcc_next = dptrig; + } + else + { + drcAssign(dpnew, distance, dp->drcc_next, + &tmp1, &tmp2, why, distance, + DRC_REVERSE | DRC_BOTHCORNERS, plane2, plane); + dp->drcc_next = dpnew; + } + } + } + } + + /* Finally, if multiplane rule then check that set2 types + * are not present just to right of edges with setR on LHS + * and set1 on RHS. This check is necessary to make sure + * that a set1 rectangle doesn't coincide exactly with a + * set2 rectangle. + * (This check added by Michael Arnold on 4/10/86.) + */ + + if (needtrigger) continue; + + if (pset = (DBTypesOnSamePlane(i, j) & pmask1)) + { + plane = LowestMaskBit(pset); + + /* LHS is an element of setR, RHS is an element of set1 */ + if (TTMaskHasType(&setR, i) && TTMaskHasType(set1, j)) + { + /* + * Must not have 'set2' for 'distance' to the right of + * an edge between the types not in set1 and set1. + * (is only checked for cross plane rules - these are + * all of type touching_illegal) + */ + + /* Walk list to last check. New checks ("cookies") go + * at end of list since we are checking for distance of + * 1 and the list is sorted in order of decreasing distance. + */ + for (dp = DRCCurStyle->DRCRulesTbl [i][j]; + dp->drcc_next != (DRCCookie *) NULL; + dp = dp->drcc_next); /* null body */ + + /* Insert one check for each plane involved in set2 */ + plane2 = LowestMaskBit(pmask2); + + /* filter out checks that are not cross plane */ + if (i == TT_SPACE) + { + if (DBTypeOnPlane(j, plane2)) + continue; + } + else + { + if (DBTypeOnPlane(i, plane2)) + continue; + } + + /* create new check and add it to list */ + dpnew = (DRCCookie *) mallocMagic(sizeof (DRCCookie)); + TTMaskClearMask3(&tmp1, &DBPlaneTypes[plane2], set2); + TTMaskZero(&tmp2); + + drcAssign(dpnew, 1, dp->drcc_next, &tmp1, &tmp2, why, + distance, DRC_FORWARD, plane2, plane); + dp->drcc_next = dpnew; + } + } + } + } + return (MAX(wwidth, distance)); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcSpacing -- + * + * Process a spacing rule. + * This is of the form: + * + * spacing layers1 layers2 distance adjacency why + * + * e.g, + * + * spacing metal,pmc/m,dmc/m metal,pmc/m,dmc/m 4 touching_ok \ + * "metal spacing must be at least 4" + * + * Adjacency may be either "touching_ok" or "touching_illegal" + * In the first case, no violation occurs when types in layers1 are + * immediately adjacent to types in layers2. In the second case, + * such adjacency causes a violation. + * + * Results: + * Returns distance. + * + * Side effects: + * Updates the DRC technology variables. + * + * Notes: + * Extended to include the rule syntax: + * + * widespacing layers1 width layers2 distance adjacency why + * + * This extension covers rules such as "If m1 width > 10um, then spacing to + * unconnected m1 must be at least 0.6um". This assumes that the instantiated + * edge4way rule is a standard "spacing" rule in which "dist" and "cdist" + * (corner extension) distances are always the same, so we can use the "cdist" + * record to encode the width of "layers1" which triggers the rule. We re-use + * the CheckMaxwidth() code, but with the following differences: 1) it does not + * trigger any error painting functions, 2) it returns a value stating whether + * the maxwidth rule applies or not, 3) it uses the DBLayerTypeMaskTbl[] for + * the tile type in question, not "oktypes", for its search, and 4) it uses + * the max width in the "cdist" record, not the "dist" record, for the max + * width rule. The "dist" record is copied to "cdist" before actually applying + * the spacing rule, so that the rule acts like a proper spacing rule. + * + * Added adjacency rule "surround_ok" to check spacing to a type that + * may also abut or surround the first layer---the portion of the layer + * that is abutting or surrounding is not checked. This allows checks + * of, e.g., diffusion in well to a separate well edge, or distance from + * a poly bottom plate to unconnected poly. + * + * (Added 11/6/06) Adjacency may be "corner_ok", in which case it calls + * routing drcSpacing3() (see above). + * + * ---------------------------------------------------------------------------- + */ + +int +drcSpacing(argc, argv) + int argc; + char *argv[]; +{ + char *layers1 = argv[1], *layers2; + char *adjacency; + char *why; + TileTypeBitMask set1, set2, tmp1, tmp2; + PlaneMask pmask1, pmask2, pmaskA, pmaskB, ptest; + int wwidth, distance, plane, plane2; + bool widerule, multiplane = FALSE; + + if ((argc == 7) && (!strcmp(argv[4], "corner_ok"))) + return drcSpacing3(argc, argv); + + widerule = (strncmp(argv[0], "wide", 4) == 0); + + if (widerule) + { + wwidth = atoi(argv[2]); + layers2 = argv[3]; + distance = atoi(argv[4]); + adjacency = argv[5]; + why = drcWhyDup(argv[6]); + /* TxPrintf("Info: DRCtech: widespacing rule for %s width %d:" + " spacing must be %d\n", layers1, wwidth, distance); */ + } + else + { + layers2 = argv[2]; + distance = atoi(argv[3]); + adjacency = argv[4]; + wwidth = distance; + why = drcWhyDup(argv[5]); + if (argc == 7) + { + TechError("Unknown argument in spacing line.\n"); + return(0); + } + } + + /* Either list of types may contain independent types on different */ + /* planes. However, if so, then we may not use touching_ok, and */ + /* there are other restrictions. */ + + ptest = DBTechNoisyNameMask(layers1, &set1); + pmask1 = CoincidentPlanes(&set1, ptest); + + if ((pmask1 == 0) && (ptest != 0)) + { + pmask1 = ptest; + multiplane = TRUE; + for (plane = 0; plane < DBNumPlanes; plane++) + for (plane2 = 0; plane2 < DBNumPlanes; plane2++) + { + if (plane == plane2) continue; + if (PlaneMaskHasPlane(pmask1, plane) && + PlaneMaskHasPlane(pmask1, plane2)) + { + TTMaskAndMask3(&tmp1, &DBPlaneTypes[plane], + &DBPlaneTypes[plane2]); + TTMaskAndMask(&tmp1, &set1); + if (!TTMaskIsZero(&tmp1)) + { + TechError("Types in first list must either be in" + " one plane or else types must not share" + " planes.\n"); + return (0); + } + } + } + } + + ptest = DBTechNoisyNameMask(layers2, &set2); + pmask2 = CoincidentPlanes(&set2, ptest); + + if ((pmask2 == 0) && (ptest != 0)) + { + pmask2 = ptest; + multiplane = TRUE; + for (plane = 0; plane < DBNumPlanes; plane++) + for (plane2 = 0; plane2 < DBNumPlanes; plane2++) + { + if (plane == plane2) continue; + if (PlaneMaskHasPlane(pmask2, plane) && + PlaneMaskHasPlane(pmask2, plane2)) + { + TTMaskAndMask3(&tmp1, &DBPlaneTypes[plane], + &DBPlaneTypes[plane2]); + TTMaskAndMask(&tmp1, &set2); + if (!TTMaskIsZero(&tmp1)) + { + TechError("Types in second list must either be in" + " one plane or else types must not share" + " planes.\n"); + return (0); + } + } + } + } + + if (multiplane) + { + /* Loop over independent plane/layer combinations */ + + for (plane = 0; plane < DBNumPlanes; plane++) + for (plane2 = 0; plane2 < DBNumPlanes; plane2++) + { + if (PlaneMaskHasPlane(pmask1, plane) && + PlaneMaskHasPlane(pmask2, plane2)) + { + pmaskA = PlaneNumToMaskBit(plane); + pmaskB = PlaneNumToMaskBit(plane2); + + TTMaskAndMask3(&tmp1, &set1, &DBPlaneTypes[plane]); + TTMaskAndMask3(&tmp2, &set2, &DBPlaneTypes[plane2]); + + return drcMaskSpacing(&tmp1, &tmp2, pmaskA, pmaskB, + wwidth, distance, adjacency, why, + widerule, multiplane); + } + } + } + else + return drcMaskSpacing(&set1, &set2, pmask1, pmask2, wwidth, + distance, adjacency, why, widerule, multiplane); + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcEdge -- + * + * Process a primitive edge rule. + * This is of the form: + * + * edge layers1 layers2 dist OKtypes cornerTypes cornerDist why [plane] + * or edge4way layers1 layers2 dist OKtypes cornerTypes cornerDist why [plane] + * + * e.g, + * + * edge poly,pmc s 1 diff poly,pmc "poly-diff separation must be 2" + * + * An "edge" rule is applied only down and to the left. + * An "edge4way" rule is applied in all four directions. + * + * Results: + * Returns greater of dist and cdist. + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcEdge(argc, argv) + int argc; + char *argv[]; +{ + char *layers1 = argv[1], *layers2 = argv[2]; + int distance = atoi(argv[3]); + char *okTypes = argv[4], *cornerTypes = argv[5]; + int cdist = atoi(argv[6]); + char *why = drcWhyDup(argv[7]); + bool fourway = (strcmp(argv[0], "edge4way") == 0); + TileTypeBitMask set1, set2, setC, setM; + DRCCookie *dp, *dpnew; + int plane, checkPlane, tmpPlane; + PlaneMask pMask1, pMaskM, pMaskC, pset, ptest; + TileType i, j; + + /* + * Edge4way rules produce [j][i] entries as well as [i][j] + * ones, and check both corners rather than just one corner. + */ + + ptest = DBTechNoisyNameMask(layers1, &set1); + pMask1 = CoincidentPlanes(&set1, ptest); + + ptest = DBTechNoisyNameMask(layers2, &set2); + pMask1 &= CoincidentPlanes(&set2, ptest); + + if (pMask1 == 0) + { + TechError("All edges in edge rule must lie in shared planes.\n"); + return (0); + } + + /* Give warning if types1 and types2 intersect */ + if (TTMaskIntersect(&set1, &set2)) + TechError("Warning: types1 and types2 have nonempty intersection. " + "DRC does not check edges with the same type on both " + "sides.\n"); + + ptest = DBTechNoisyNameMask(cornerTypes, &setC); + pMaskC = CoincidentPlanes(&setC, ptest); + + if ((pMaskC & pMask1) == 0) + { + TechError("Corner types aren't in same plane as edges.\n"); + return (0); + } + + if (argc == 9) + tmpPlane = DBTechNoisyNamePlane(argv[8]); + + /* + * OKtypes determine the checkPlane. If checkPlane exists, it should + * only be used to check against the plane of OKtypes. + */ + + ptest = DBTechNoisyNameMask(okTypes, &setM); + pMaskM = CoincidentPlanes(&setM, ptest); + + if (pMaskM == 0 || pMaskM == DBTypePlaneMaskTbl[TT_SPACE]) + { + /* Technically it should be illegal to specify simply "space" + * in the types list for a DRC rule, as it is ambiguous. + * However, we will assume that the plane of the edge is + * intended. The "plane" argument may be used to do the + * qualification (for backwards compatibility); any other use + * gets a warning. + */ + + if (TTMaskEqual(&DBSpaceBits, &setM)) + { + if (argc == 9) + pMaskM = PlaneNumToMaskBit(tmpPlane); + else + { + TechError("OK types \"%s\" in more than one plane.\n" + " Assuming same plane (%s) as edge.\n", + okTypes, DBPlaneLongNameTbl[LowestMaskBit(pMask1)]); + pMaskM = pMask1; + } + } + + /* The case okTypes="0" is explicitly allowed according */ + /* to the manual, so we parse it accordingly. */ + + else if (!strcmp(okTypes, "0")) + pMaskM = pMask1; + else + { + TechError("All OK types must lie in one plane.\n"); + return (0); + } + } + + /* "plane" argument deprecated; kept for backward compatibility only */ + + if ((argc == 9) && (PlaneNumToMaskBit(tmpPlane) != pMaskM)) + TechError("Ignoring bad plane argument.\n"); + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + if (pset = (DBTypesOnSamePlane(i, j) & pMask1)) + { + if (TTMaskHasType(&set1, i) && TTMaskHasType(&set2, j)) + { + /* For fastest DRC, checkPlane and plane should be */ + /* the same, if possible. */ + + if (pset & pMaskM != 0) + { + plane = LowestMaskBit(pset & pMaskM); + checkPlane = plane; + } + else + { + plane = LowestMaskBit(pset); + checkPlane = LowestMaskBit(pMaskM); + } + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &setM, &setC, + why, cdist, DRC_FORWARD, checkPlane, plane); + if (fourway) dpnew->drcc_flags |= DRC_BOTHCORNERS; + dp->drcc_next = dpnew; + + if (!fourway) continue; + + /* find bucket preceding new one we wish to insert */ + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew,distance,dp->drcc_next, &setM, &setC, + why, cdist, DRC_REVERSE, checkPlane, plane); + dpnew->drcc_flags |= DRC_BOTHCORNERS; + dp->drcc_next = dpnew; + } + } + } + } + return (MAX(distance, cdist)); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcOverhang -- + * + * Process an overhang rule. + * This is of the form: + * + * overhang layers2 layers1 dist why + * + * indicating that layers2 must overhang layers1 by a distance of at least + * dist. + * + * This rule is equivalent to: + * + * edge4way layers1 space/p2|layers2 dist layers1|layers2 \ + * space/p2|layers2 dist why + * + * ---------------------------------------------------------------------------- + */ + +int +drcOverhang(argc, argv) + int argc; + char *argv[]; +{ + char *layers2 = argv[1], *layers1 = argv[2]; + int distance = atoi(argv[3]); + char *why = drcWhyDup(argv[4]); + TileTypeBitMask set1, set2, setM, setC, setN, set2inv; + DRCCookie *dp, *dpnew, *dptrig; + int plane, plane2; + TileType i, j; + PlaneMask pMask1, pMask2, pset, ptest; + + ptest = DBTechNoisyNameMask(layers1, &set1); + pMask1 = CoincidentPlanes(&set1, ptest); + if (pMask1 == 0) + { + TechError("All layers in first set for \"overhang\" must be on " + "the same plane\n"); + return (0); + } + TTMaskCom2(&setN, &set1); + + ptest = DBTechNoisyNameMask(layers2, &set2); + pMask2 = CoincidentPlanes(&set2, ptest); + if (pMask2 == 0) + { + TechError("All layers in second set for \"overhang\" must be on " + "the same plane\n"); + return (0); + } + TTMaskCom2(&set2inv, &set2); + + /* Warn if types1 and types2 intersect */ + if (TTMaskIntersect(&set1, &set2)) + TechError("Warning: inside and outside types have nonempty intersection. " + "DRC does not check edges with the same type on both sides.\n"); + + /* SetM is the union of set1 and set2 */ + TTMaskZero(&setM); + TTMaskSetMask3(&setM, &set1, &set2); + + /* Add space to set2 */ + TTMaskSetType(&set2, TT_SPACE); + + /* SetC is the empty set */ + TTMaskZero(&setC); + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + if (pset = (DBTypesOnSamePlane(i, j) & pMask2)) + { + if ((pset & pMask1) != 0) + { + if (TTMaskHasType(&set1, i) && TTMaskHasType(&set2, j)) + { + plane = LowestMaskBit(pset); + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic (sizeof (DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &setM, + &setM, why, distance, + DRC_FORWARD | DRC_BOTHCORNERS, + plane, plane); + dp->drcc_next = dpnew; + + /* find bucket preceding new one we wish to insert */ + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, + &setM, &setM, why, distance, + DRC_REVERSE | DRC_BOTHCORNERS, + plane, plane); + dp->drcc_next = dpnew; + } + } + else /* Multi-plane overhang rule */ + { + if (TTMaskHasType(&set2, i) && TTMaskHasType(&set2inv, j)) + { + plane = LowestMaskBit(pset); + plane2 = LowestMaskBit(pMask1); + + /* find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set1, &set1, why, + distance, DRC_FORWARD, plane2, plane); + dptrig = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dptrig, 1, dpnew, &setN, &setC, why, + 0, DRC_FORWARD | DRC_TRIGGER, plane2, plane); + dp->drcc_next = dptrig; + + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set1, &set1, why, + distance, DRC_REVERSE, plane2, plane); + dptrig = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dptrig, 1, dpnew, &setN, &setC, why, + 0, DRC_REVERSE | DRC_TRIGGER, plane2, plane); + dp->drcc_next = dptrig; + } + } + } + } + } + return distance; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcRectOnly -- + * + * Process a rectangle-only rule. This rule prohibits non-rectangular + * geometry, and is used especially for contacts, as the "squares" operator + * in the CIF/GDS output generator can't handle non-rectangular areas. + * The rule is of the form: + * + * rect_only layers why + * + * and is equivalent to: + * + * edge4way layers ~(layers)/plane 1 ~(layers)/plane (all_layers)/plane 1 + * + * The rect_only rule avoids the above contrived construction, especially the + * requirement of specifying "all_layers" as something like (~(x),x)/p, a sure- + * fire obfuscation. + * + * ---------------------------------------------------------------------------- + */ + +int +drcRectOnly(argc, argv) + int argc; + char *argv[]; +{ + char *layers = argv[1]; + char *why = drcWhyDup(argv[2]); + TileTypeBitMask set1, set2, setC; + PlaneMask pmask, pset, ptest; + DRCCookie *dp, *dpnew; + int plane; + TileType i, j; + + ptest = DBTechNoisyNameMask(layers, &set1); + pmask = CoincidentPlanes(&set1, ptest); + + if (pmask == 0) + { + TechError("All types for \"rect_only\" must be on the same plane.\n"); + return (0); + } + + /* set2 is the inverse of set1 */ + TTMaskCom2(&set2, &set1); + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + + if (pset = (DBTypesOnSamePlane(i, j) & pmask)) + { + if (TTMaskHasType(&set1, i) && TTMaskHasType(&set2, j)) + { + plane = LowestMaskBit(pset); + /* setC = all types in plane */ + TTMaskZero(&setC); + TTMaskSetMask(&setC, &DBPlaneTypes[plane]); + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, 1); + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew, 1, dp->drcc_next, &set2, &setC, why, 1, + DRC_FORWARD | DRC_BOTHCORNERS, plane, plane); + dp->drcc_next = dpnew; + + /* find bucket preceding new one we wish to insert */ + dp = drcFindBucket(j, i, 1); + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew,1,dp->drcc_next, &set2, &setC, why, 1, + DRC_REVERSE | DRC_BOTHCORNERS, plane, plane); + dp->drcc_next = dpnew; + } + } + } + } + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcSurround -- + * + * Process a surround rule. + * This is of the form: + * + * surround layers1 layers2 dist presence why + * + * indicating that layers2 must surround layers1 by at least distance + * dist in all directions. + * + * This rule is equivalent to: + * + * edge4way ~(layers2)/plane2 layers2 dist ~(layers1)/plane1 \ + * layers2 dist why + * + * When presence=absence_illegal, the following additional rule is needed: + * + * edge4way layers1 ~(layers2)/plane1 dist NULL ~(layers2)/plane1 \ + * dist why + * + * Extension added July 12, 2014: For via rules where an asymmetric + * surround is allowed, with a smaller surround allowed on two sides if + * the remaining two sides have a larger surround. This can be implemented + * with a trigger rule, and is specified by the syntax above with "presence" + * being "directional". Note that the rule expresses that the overhang rule + * requires the presence of the material on one side of a corner. If the + * other side has a non-zero minimum surround requirement, then it should + * be implemented with an additional (absence_illegal) surround rule. + * Otherwise, any width of material less than "dist" on one side of a + * corner will trigger the rule requiring at least "dist" width of the same + * material on the other side of the corner. + * + * ---------------------------------------------------------------------------- + */ + +int +drcSurround(argc, argv) + int argc; + char *argv[]; +{ + char *layers1 = argv[1], *layers2 = argv[2]; + int distance = atoi(argv[3]); + char *presence = argv[4]; + char *why = drcWhyDup(argv[5]); + TileTypeBitMask set1, set2, setM, invM, setR; + DRCCookie *dp, *dpnew, *dptrig; + int plane1, plane2; + PlaneMask pmask, pmask2, pset, ptest; + TileType i, j; + bool isExact = FALSE; + bool isDirectional = FALSE; + + ptest = DBTechNoisyNameMask(layers1, &setM); + pmask = CoincidentPlanes(&setM, ptest); + if (pmask == 0) + { + TechError("Inside types in \"surround\" must be on the same plane\n"); + return (0); + } + + ptest = DBTechNoisyNameMask(layers2, &set2); + pmask2 = CoincidentPlanes(&set2, ptest); + if (pmask2 == 0) + { + TechError("Outside types in \"surround\" must be on the same plane\n"); + return (0); + } + + /* "exact_width" rule implemented 9/16/10. This enforces an exact */ + /* surround distance. "absence_illegal" is implied. */ + + if (!strncmp(presence, "exact_", 6)) isExact = TRUE; + else if (!strncmp(presence, "directional", 11)) + { + isDirectional = TRUE; + /* Combined mask */ + TTMaskZero(&setR); + TTMaskSetMask(&setR, &setM); + TTMaskSetMask(&setR, &set2); + } + + /* invert setM */ + TTMaskCom2(&invM, &setM); + + /* set1 is the inverse of set2 */ + TTMaskCom2(&set1, &set2); + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; /* Ignore false edges */ + if (pset = (DBTypesOnSamePlane(i, j) & pmask2)) + { + if (isDirectional) + { + /* Directional surround is done entirely differently */ + + if (TTMaskHasType(&setM, i) && TTMaskHasType(&invM, j)) + { + plane1 = LowestMaskBit(pmask); + plane2 = LowestMaskBit(pset); + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + + /* Insert triggered rule */ + drcAssign(dpnew, distance, dp->drcc_next, &setR, + &DBAllTypeBits, + why, distance, + DRC_REVERSE | DRC_BOTHCORNERS, + plane1, plane2); + dptrig = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dptrig, distance, dpnew, &set2, + &DBZeroTypeBits, why, 0, + DRC_FORWARD | DRC_TRIGGER, + plane1, plane2); + dp->drcc_next = dptrig; + + /* And the other direction. . . */ + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + + /* Insert triggered rule */ + drcAssign(dpnew, distance, dp->drcc_next, &setR, + &DBAllTypeBits, + why, distance, + DRC_FORWARD | DRC_BOTHCORNERS, + plane1, plane2); + dptrig = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dptrig, distance, dpnew, &set2, + &DBZeroTypeBits, why, 0, + DRC_REVERSE | DRC_TRIGGER, + plane1, plane2); + dp->drcc_next = dptrig; + } + } + else + { + if (TTMaskHasType(&set1, i) && TTMaskHasType(&set2, j)) + { + plane1 = LowestMaskBit(pmask); + plane2 = LowestMaskBit(pset); + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &invM, &set2, + why, distance, + DRC_FORWARD | DRC_BOTHCORNERS, + plane1, plane2); + dp->drcc_next = dpnew; + + /* find bucket preceding new one we wish to insert */ + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &invM, &set2, + why, distance, + DRC_REVERSE | DRC_BOTHCORNERS, + plane1, plane2); + dp->drcc_next = dpnew; + } + } + } + } + } + + if (isExact) + { + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; /* Ignore false edges */ + if (pset = (DBTypesOnSamePlane(i, j) & pmask)) + { + if (TTMaskHasType(&setM, i) && TTMaskHasType(&set2, j)) + { + plane1 = LowestMaskBit(pset); + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set1, &set2, + why, distance, + DRC_FORWARD | DRC_BOTHCORNERS | DRC_OUTSIDE, + plane1, plane1); + dp->drcc_next = dpnew; + + /* find bucket preceding new one we wish to insert */ + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *)mallocMagic(sizeof(DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, &set1, &set2, + why, distance, + DRC_REVERSE | DRC_BOTHCORNERS | DRC_OUTSIDE, + plane1, plane1); + dp->drcc_next = dpnew; + } + } + } + } + } + + if ((!isExact) && strcmp(presence, "absence_illegal")) return distance; + + /* Add an extra rule when presence of the surrounding */ + /* layer is required. Rule is different if planes match. */ + + if (pset = pmask & pmask2) + { + TTMaskZero(&invM); + TTMaskSetMask(&invM, &setM); + TTMaskSetMask(&invM, &set2); + TTMaskCom(&invM); + TTMaskZero(&set1); + + for (i = 0; i < DBNumTypes; i++) + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + if (pset = (DBTypesOnSamePlane(i, j) & pmask & pmask2)) + { + plane1 = LowestMaskBit(pset); + if (TTMaskHasType(&setM, i) && TTMaskHasType(&invM, j)) + { + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *) mallocMagic((unsigned) + (sizeof (DRCCookie))); + drcAssign(dpnew, distance, dp->drcc_next, + &set1, &invM, why, distance, + DRC_FORWARD | DRC_BOTHCORNERS, + plane1, plane1); + dp->drcc_next = dpnew; + + /* find bucket preceding new one we wish to insert */ + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *) mallocMagic((unsigned) + (sizeof (DRCCookie))); + drcAssign(dpnew,distance,dp->drcc_next, + &set1, &invM, why, distance, + DRC_REVERSE | DRC_BOTHCORNERS, + plane1, plane1); + dp->drcc_next = dpnew; + } + } + } + } + else + { + for (i = 0; i < DBNumTypes; i++) + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + if (pset = (DBTypesOnSamePlane(i, j) & pmask)) + { + if (TTMaskHasType(&setM, i) && TTMaskHasType(&invM, j)) + { + plane1 = LowestMaskBit(pset); + plane2 = LowestMaskBit(pmask2); + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *) mallocMagic((unsigned) + (sizeof (DRCCookie))); + drcAssign(dpnew, distance, dp->drcc_next, + &set2, &invM, why, distance, + DRC_FORWARD | DRC_BOTHCORNERS, + plane2, plane1); + dp->drcc_next = dpnew; + + /* find bucket preceding new one we wish to insert */ + dp = drcFindBucket(j, i, distance); + dpnew = (DRCCookie *) mallocMagic((unsigned) + (sizeof (DRCCookie))); + drcAssign(dpnew,distance,dp->drcc_next, + &set2, &invM, why, distance, + DRC_REVERSE | DRC_BOTHCORNERS, + plane2, plane1); + dp->drcc_next = dpnew; + } + } + } + } + + return distance; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcNoOverlap -- + * + * Process a no-overlap rule. + * This is of the form: + * + * no_overlap layers1 layers2 + * + * e.g, + * + * no_overlap poly m2contact + * + * Results: + * Returns 0. + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcNoOverlap(argc, argv) + int argc; + char *argv[]; +{ + char *layers1 = argv[1], *layers2 = argv[2]; + TileTypeBitMask set1, set2; + TileType i, j; + int plane; + + /* + * Grab up two sets of tile types, and make sure that if + * any type from one set is painted over any type from the + * other, then an error results. + */ + + DBTechNoisyNameMask(layers1, &set1); + DBTechNoisyNameMask(layers2, &set2); + + for (i = 0; i < DBNumTypes; i++) + for (j = 0; j < DBNumTypes; j++) + if (TTMaskHasType(&set1, i) && TTMaskHasType(&set2, j)) + for (plane = 0; plane < DBNumPlanes; plane++) + { + DRCCurStyle->DRCPaintTable[plane][j][i] = TT_ERROR_S; + DRCCurStyle->DRCPaintTable[plane][i][j] = TT_ERROR_S; + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcExactOverlap -- + * + * Process an exact overlap + * This is of the form: + * + * exact_overlap layers + * + * e.g, + * + * exact_overlap pmc,dmc + * + * Results: + * Returns 0. + * + * Side effects: + * Updates DRCExactOverlapTypes. + * + * ---------------------------------------------------------------------------- + */ + +int +drcExactOverlap(argc, argv) + int argc; + char *argv[]; +{ + char *layers = argv[1]; + TileTypeBitMask set; + + /* + * Grab up a bunch of tile types, and remember these: tiles + * of these types cannot overlap themselves in different cells + * unless they overlap exactly. + */ + + DBTechNoisyNameMask(layers, &set); + TTMaskSetMask(&DRCCurStyle->DRCExactOverlapTypes, &set); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * drcRectangle -- + * + * Process a rectangle rule. This is of the form: + * + * rectangle layers maxwidth [even|odd|any] why + * + * The rule checks to make sure that the region is rectangular and that the + * width and length are even or odd, as specified. These two criteria ensure + * that the squares rule of the cifout section can properly produce via + * holes without misaligning them between cells and without putting the via + * holes off grid. The maxwidth is required to make the extent of this rule + * a finite size, so that we can set the DRChalo to something finite. + * + * Results: + * maxwidth + * + * Side effects: + * Updates the DRC technology variables. + * + * ---------------------------------------------------------------------------- + */ + +int +drcRectangle(argc, argv) + int argc; + char *argv[]; +{ + char *layers = argv[1]; + char *why = drcWhyDup(argv[4]); + TileTypeBitMask types, nottypes; + int maxwidth; + static char *drcRectOpt[4] = {"any", "even", "odd", 0}; + int i, j, even, plane; + PlaneMask pMask, pset, ptest; + + /* parse arguments */ + ptest = DBTechNoisyNameMask(layers, &types); + pMask = CoincidentPlanes(&types, ptest); + + if (pMask == 0) { + TechError("Layers in rectangle rule must lie in a single plane."); + return 0; + } + TTMaskCom2(¬types, &types); + + if (sscanf(argv[2], "%d", &maxwidth) != 1) { + TechError("bad maxwidth in rectangle rule"); + return 0; + } + even = Lookup(argv[3], drcRectOpt); + if (even < 0) { + TechError("bad [even|odd|any] selection in rectangle rule"); + return 0; + } + even--; /* -1: any, 0: even, 1: odd */ + + /* Install 2 edge rules: one that checks rectangle-ness, and one that + * checks size + */ + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + if (i == j) continue; + + if (pset = (DBTypesOnSamePlane(i, j) & pMask)) + { + if (TTMaskHasType(&types, i) && TTMaskHasType(¬types, j)) + { + DRCCookie *dp, *dpnew; + + plane = LowestMaskBit(pset); + + /* + * A rule that checks rectangle-ness. + * left: oktypes, right: other types + * This rule needs to be checked in all 4 directions + */ + int distance = 1; + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(i, j, distance); + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, distance, dp->drcc_next, + ¬types, &DBAllTypeBits, why, distance, + DRC_FORWARD, plane, plane); + dp->drcc_next = dpnew; + + /* Find bucket preceding the new one we wish to insert */ + dp = drcFindBucket(j, i, distance); /* note: j, i not i, j */ + dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); + drcAssign(dpnew, distance, dp->drcc_next, + ¬types, &DBAllTypeBits, why, distance, + DRC_REVERSE, plane, plane); + dp->drcc_next = dpnew; + + if (maxwidth > 0) { + /* + * A rule that checks size. + * left: other types, right: oktypes + */ + distance = maxwidth; + + /* note: j, i not i, j */ + for (dp = DRCCurStyle->DRCRulesTbl[j][i]; + dp->drcc_next != (DRCCookie *) NULL && + dp->drcc_next->drcc_dist < distance; + dp = dp->drcc_next); /* null body */ + + dpnew = (DRCCookie *)mallocMagic(sizeof (DRCCookie)); + drcAssign(dpnew, distance, dp->drcc_next, + &types, &DBZeroTypeBits, why, even, + DRC_RECTSIZE, plane, plane); + dp->drcc_next = dpnew; + } + } + } + } + } + return maxwidth; +} + +/* + * ---------------------------------------------------------------------------- + * + * drcStepSize -- + * + * Process a declaration of the step size. + * This is of the form: + * + * stepsize step_size + * + * e.g, + * + * stepsize 1000 + * + * Results: + * Returns 0. + * + * Side effects: + * Updates DRCStepSize. + * + * ---------------------------------------------------------------------------- + */ + +int +drcStepSize(argc, argv) + int argc; + char *argv[]; +{ + if (DRCCurStyle == NULL) return 0; + + DRCCurStyle->DRCStepSize = atoi(argv[1]); + if (DRCCurStyle->DRCStepSize <= 0) + { + TechError("Step size must be a positive integer.\n"); + DRCCurStyle->DRCStepSize = 0; + } + else if (DRCCurStyle->DRCStepSize < 16) + { + TechError("Warning: abnormally small DRC step size (%d)\n", + DRCCurStyle->DRCStepSize); + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCTechFinal -- + * + * Called after all lines of the drc section in the technology file have been + * read. Ensures that a valid style is in effect, and then calls + * drcTechFinalStyle(). + * + * Results: + * None. + * + * Side effects: + * See drcTechFinalStyle(); + * + * ---------------------------------------------------------------------------- + */ + +void +DRCTechFinal() +{ + DRCStyle *ds; + + /* Create a "default" style if there isn't one */ + + if (DRCStyleList == NULL) + { + DRCStyleList = (DRCKeep *)mallocMagic(sizeof(DRCKeep)); + DRCStyleList->ds_next = NULL; + DRCStyleList->ds_name = StrDup((char **)NULL, "default"); + + drcTechNewStyle(); + DRCCurStyle->ds_name = DRCStyleList->ds_name; + DRCCurStyle->ds_status = TECH_LOADED; + } + drcTechFinalStyle(DRCCurStyle); +} + +/* + * ---------------------------------------------------------------------------- + * drcScaleDown --- + * + * DRC distances may be specified with a scale factor so that physically + * based rules can be recorded, but the rules used will be rounded (up) + * to the nearest lambda. The fractional part of the true distance in + * lambda is saved, so that the original value can be recovered when + * the magic grid is rescaled. + * + * Results: + * None. + * + * Side Effects: + * Scales all the DRC distances by dividing by the DRC scale factor. + * ---------------------------------------------------------------------------- + */ + +void +drcScaleDown(style, scalefactor) + DRCStyle *style; + int scalefactor; +{ + TileType i, j; + DRCCookie *dp; + int dist; + + if (scalefactor > 1) + { + for (i = 0; i < TT_MAXTYPES; i++) + for (j = 0; j < TT_MAXTYPES; j++) + for (dp = style->DRCRulesTbl[i][j]; dp != NULL; dp = dp->drcc_next) + { + if (dp->drcc_dist > 0) + { + dist = dp->drcc_dist; + dp->drcc_dist /= scalefactor; + if ((dp->drcc_mod = (unsigned char)(dist % scalefactor)) != 0) + if (!(dp->drcc_flags & DRC_MAXWIDTH)) + dp->drcc_dist++; + } + if (dp->drcc_cdist > 0) + { + int locscale = scalefactor; + if (dp->drcc_flags & DRC_AREA) + locscale *= scalefactor; + + dist = dp->drcc_cdist; + dp->drcc_cdist /= locscale; + if ((dp->drcc_cmod = (unsigned char)(dist % locscale)) != 0) + dp->drcc_cdist++; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * drcScaleUp --- + * + * Recovers the original (pre-scaled) values for drcc_dist and + * drcc_cdist in the DRC cookies. + * + * Results: + * None. + * + * Side Effects: + * Scales all the DRC distances by multiplying by the DRC scale factor. + * ---------------------------------------------------------------------------- + */ + +void +drcScaleUp(style, scalefactor) + DRCStyle *style; + int scalefactor; +{ + TileType i, j; + DRCCookie *dp; + int dist; + + if (style == NULL) return; + + if (scalefactor > 1) + { + for (i = 0; i < TT_MAXTYPES; i++) + for (j = 0; j < TT_MAXTYPES; j++) + for (dp = style->DRCRulesTbl[i][j]; dp != NULL; dp = dp->drcc_next) + { + if (dp->drcc_dist > 0) + { + dist = dp->drcc_dist; + if (dp->drcc_mod != 0) + if (!(dp->drcc_flags & DRC_MAXWIDTH)) + dp->drcc_dist--; + dp->drcc_dist *= scalefactor; + dp->drcc_dist += (short)dp->drcc_mod; + dp->drcc_mod = 0; + } + if (dp->drcc_cdist > 0) + { + dist = dp->drcc_cdist; + if (dp->drcc_cmod != 0) + dp->drcc_cdist--; + dp->drcc_cdist *= scalefactor; + if (dp->drcc_flags & DRC_AREA) + dp->drcc_cdist *= scalefactor; + dp->drcc_cdist += (short)dp->drcc_cmod; + dp->drcc_cmod = 0; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * drcTechFinalStyle -- + * + * Called after all lines of the drc section in the technology file have been + * read. The preliminary DRC Rules Table is pruned by removing rules covered + * by other (longer distance) rules, and by removing the dummy rule at the + * front of each list. Where edges are completely illegal, the rule list is + * pruned to a single rule. + * + * Results: + * None. + * + * Side effects: + * May remove DRCCookies from the linked lists of the DRCRulesTbl. + * + * ---------------------------------------------------------------------------- + */ + +void +drcTechFinalStyle(style) + DRCStyle *style; +{ + TileTypeBitMask tmpMask, nextMask; + DRCCookie *dummy, *dp, *next, *dptrig; + DRCCookie **dpp, **dp2back; + TileType i, j; + + /* If the scale factor is not 1, then divide all distances by */ + /* the scale factor, take the ceiling, and save the (negative) */ + /* remainder. */ + + drcScaleUp(style, style->DRCScaleFactorD); + drcScaleDown(style, style->DRCScaleFactorN); + + /* Set maximum halo */ + style->DRCTechHalo = DRCTechHalo; + + /* A reasonable chunk size for design-rule checking is about + * 16 times the maximum design-rule interaction distance. This + * results in a halo overhead of about 27%. If there's no DRC + * information at all (TechHalo is zero), just pick any size. + * (Update 1/13/09: "any size" needs a bit of modification, + * because 64 will be way too small for a layout with a small + * scalefactor. Assuming that the CIF output style is valid, + * use its scalefactor to adjust the step size). + */ + if (style->DRCStepSize == 0) + { + if (style->DRCTechHalo == 0) + { + if (CIFCurStyle != NULL) + style->DRCStepSize = 6400 / CIFCurStyle->cs_scaleFactor; + else + style->DRCStepSize = 64; + } + else + style->DRCStepSize = 16 * style->DRCTechHalo; + } + DRCStepSize = style->DRCStepSize; + + /* Remove dummy buckets */ + for (i = 0; i < TT_MAXTYPES; i++) + { + for (j = 0; j < TT_MAXTYPES; j++) + { + dpp = &(style->DRCRulesTbl [i][j]); + dummy = *dpp; + *dpp = dummy->drcc_next; + freeMagic((char *) dummy); + } + } + drcCifFinal(); + + if (!DRCRuleOptimization) return; + + /* Check for edges that are completely illegal. Where this is the + * case, eliminate all of the edge's rules except one. + */ + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + DRCCookie *keep = NULL, *dptest, *dptemp, *dpnew; + + for (dp = style->DRCRulesTbl[i][j]; dp != NULL; dp = dp->drcc_next) + { + if (dp->drcc_flags & (DRC_NONSTANDARD || DRC_OUTSIDE)) continue; + if (dp->drcc_flags & DRC_REVERSE) + { + if ((i == TT_SPACE) || TTMaskHasType(&dp->drcc_mask, i)) continue; + } + else + { + if ((j == TT_SPACE) || TTMaskHasType(&dp->drcc_mask, j)) continue; + } + + /* Rules where okTypes are in a different plane don't count, */ + /* unless i or j also appear in the checked plane. */ + + if (dp->drcc_plane != dp->drcc_edgeplane) + { + if (dp->drcc_flags & DRC_REVERSE) + { + if ((i == TT_SPACE) || !DBTypeOnPlane(i, dp->drcc_plane)) + continue; + } + else + { + if ((j == TT_SPACE) || !DBTypeOnPlane(j, dp->drcc_plane)) + continue; + } + } + + // if (DBIsContact(i) || DBIsContact(j) || i == TT_SPACE || + // j == TT_SPACE) continue; + + dpnew = NULL; + keep = dp; + + /* This edge is illegal. Throw away all rules except the one + * needed that is always violated. + */ + + dptest = style->DRCRulesTbl[i][j]; + while (dptest != NULL) + { + dptemp = dptest->drcc_next; + if ((dptest == keep) || (dptest->drcc_edgeplane != + keep->drcc_edgeplane)) + { + dptest->drcc_next = NULL; + if (dpnew == NULL) + style->DRCRulesTbl[i][j] = dptest; + else + dpnew->drcc_next = dptest; + dpnew = dptest; + + /* "keep" can't be a trigger rule! */ + if (dptest == keep) + keep->drcc_flags &= ~DRC_TRIGGER; + } + else + { + /* Don't free the shared drcc_why string here! */ + freeMagic((char *)dptest); + drcRulesOptimized++; + } + dptest = dptemp; + } + } + + /* TxPrintf("Edge %s-%s is illegal.\n", DBTypeShortName(i), + DBTypeShortName(j)); + */ + } + } + + /* + * Remove any rule A "covered" by another rule B, i.e., + * B's distance >= A's distance, + * B's corner distance >= A's corner distance, + * B's RHS type mask is a subset of A's RHS type mask, and + * B's corner mask == A's corner mask + * B's check plane == A's check plane + * either both A and B or neither is a REVERSE direction rule + * if A is BOTHCORNERS then B must be, too + */ + + for (i = 0; i < DBNumTypes; i++) + { + for (j = 0; j < DBNumTypes; j++) + { + for (dp = style->DRCRulesTbl[i][j]; dp != NULL; dp = dp->drcc_next) + { + /* Don't optimize on trigger rules; optimize on the */ + /* rule that gets triggered. */ + if (dp->drcc_flags & DRC_TRIGGER) + { + dptrig = dp; + dp = dp->drcc_next; + } + else + dptrig = NULL; + + /* + * Check following buckets to see if any is a superset. + */ + if (dp->drcc_flags & DRC_NONSTANDARD) continue; + for (next = dp->drcc_next; next != NULL; + next = next->drcc_next) + { + if (next->drcc_flags & DRC_TRIGGER) + { + /* A triggered rule cannot be considered */ + /* a superset of a non-triggered rule or */ + /* a rule with a different trigger, so */ + /* we skip all triggered rules and their */ + /* triggering rule. */ + next = next->drcc_next; + continue; + } + tmpMask = nextMask = next->drcc_mask; + TTMaskAndMask(&tmpMask, &dp->drcc_mask); + if (!TTMaskEqual(&tmpMask, &nextMask)) continue; + if (!TTMaskEqual(&dp->drcc_corner, &next->drcc_corner)) + continue; + if (dp->drcc_dist > next->drcc_dist) continue; + if (dp->drcc_cdist > next->drcc_cdist) continue; + if (dp->drcc_plane != next->drcc_plane) continue; + if (dp->drcc_flags & DRC_REVERSE) + { + if (!(next->drcc_flags & DRC_REVERSE)) continue; + } + else if (next->drcc_flags & DRC_REVERSE) continue; + if ((next->drcc_flags & DRC_BOTHCORNERS) + && (dp->drcc_flags & DRC_BOTHCORNERS) == 0) + continue; + if (next->drcc_flags & DRC_NONSTANDARD) continue; + if (dp->drcc_dist == next->drcc_dist) + { + if ((next->drcc_flags & DRC_OUTSIDE) && + !(dp->drcc_flags & DRC_OUTSIDE)) continue; + if (!(next->drcc_flags & DRC_OUTSIDE) && + (dp->drcc_flags & DRC_OUTSIDE)) continue; + } + break; + } + + if (next == NULL) continue; + + /* "dp" is a subset of "next". Eliminate it. */ + + /* For triggered rules, eliminate both the rule */ + /* and the trigger. */ + if (dptrig != NULL) dp = dptrig; + + /* TxPrintf("For edge %s-%s, \"%s\" covers \"%s\"\n", + DBTypeShortName(i), DBTypeShortName(j), + next->drcc_why, dp->drcc_why); + */ + dp2back = &(style->DRCRulesTbl[i][j]); + while (*dp2back != dp) + dp2back = &(*dp2back)->drcc_next; + + /* Trigger rules */ + if (dptrig != NULL) + { + dptrig = dp->drcc_next; + freeMagic((char *)dp->drcc_next); + *dp2back = dp->drcc_next->drcc_next; + + /* Replace this entry so on the next cycle */ + /* dp will be the next rule. This works */ + /* even though dp is free'd (below), due to */ + /* the one-delayed free mechanism. */ + dp->drcc_next = *dp2back; + } + else + *dp2back = dp->drcc_next; + + /* Don't free the shared drcc_why string here! */ + freeMagic((char *) dp); + drcRulesOptimized += 1; + } + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * DRCTechRuleStats -- + * + * Print out some statistics about the design rule database. + * + * Results: + * None. + * + * Side effects: + * A bunch of stuff gets printed on the terminal. + * + * ---------------------------------------------------------------------------- + */ + +#define MAXBIN 10 + +void +DRCTechRuleStats() +{ + int counts[MAXBIN+1]; + int edgeRules, overflow; + int i, j; + DRCCookie *dp; + + /* Count up the total number of edge rules, and histogram them + * by the number of rules per edge. + */ + + edgeRules = 0; + overflow = 0; + for (i=0; i<=MAXBIN; i++) counts[i] = 0; + + for (i=0; iDRCRulesTbl[i][j]; dp != NULL; dp = dp->drcc_next) + thisCount++; + edgeRules += thisCount; + if (!DBTypesOnSamePlane(i, j)) continue; + if (thisCount <= MAXBIN) counts[thisCount] += 1; + else overflow += 1; + } + + /* Print out the results. */ + + TxPrintf("Total number of rules specifed in tech file: %d\n", + drcRulesSpecified); + TxPrintf("Edge rules optimized away: %d\n", drcRulesOptimized); + TxPrintf("Edge rules left in database: %d\n", edgeRules); + TxPrintf("Histogram of # edges vs. rules per edge:\n"); + for (i=0; i<=MAXBIN; i++) + { + TxPrintf(" %2d rules/edge: %d.\n", i, counts[i]); + } + TxPrintf(" >%2d rules/edge: %d.\n", MAXBIN, overflow); +} + +/* + * ---------------------------------------------------------------------------- + * + * DRCTechScale -- + * + * Multiply all DRC rule widths and spacings by a factor of scaled/scalen. + * (Don't need to use DBScaleValue() because all values must be positive + * and cannot be (M)INFINITY.) + * + * ---------------------------------------------------------------------------- + */ + +void +DRCTechScale(scalen, scaled) + int scalen, scaled; +{ + DRCCookie *dp; + TileType i, j; + int scalegcf; + + if (DRCCurStyle == NULL) return; + else if (scalen == scaled == 1) return; + + /* Revert DRC rules to original (unscaled) values */ + drcScaleUp(DRCCurStyle, DRCCurStyle->DRCScaleFactorN); + drcScaleDown(DRCCurStyle, DRCCurStyle->DRCScaleFactorD); + + DRCCurStyle->DRCScaleFactorD *= scaled; + DRCCurStyle->DRCScaleFactorN *= scalen; + + /* Reduce scalefactor ratio by greatest common factor */ + scalegcf = FindGCF(DRCCurStyle->DRCScaleFactorD, DRCCurStyle->DRCScaleFactorN); + DRCCurStyle->DRCScaleFactorD /= scalegcf; + DRCCurStyle->DRCScaleFactorN /= scalegcf; + + /* Rescale all rules to the new scalefactor */ + drcScaleUp(DRCCurStyle, DRCCurStyle->DRCScaleFactorD); + drcScaleDown(DRCCurStyle, DRCCurStyle->DRCScaleFactorN); + + DRCTechHalo *= scaled; + DRCTechHalo /= scalen; + + DRCStepSize *= scaled; + DRCStepSize /= scalen; + + DRCCurStyle->DRCTechHalo *= scaled; + DRCCurStyle->DRCTechHalo /= scalen; + + DRCCurStyle->DRCStepSize *= scaled; + DRCCurStyle->DRCStepSize /= scalen; +} + +/* The following routines are used by the "tech" command (and in other places, + * such as the LEF file reader) to query the DRC database. + */ + +/* + *----------------------------------------------------------------------------- + * DRCGetDefaultLayerWidth --- + * + * Determine a default layer width from the DRC width rules + * of a layer. Continue processing until we have processed all + * rules, since rules are ordered from shortest to longest distance, + * and the maximum distance rule will mask any rules with a shorter + * distance. + * + * Results: + * The minimum width of the magic layer, in magic internal units + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +int +DRCGetDefaultLayerWidth(ttype) + TileType ttype; +{ + int routeWidth = 0; + DRCCookie *cptr; + TileTypeBitMask *set; + + for (cptr = DRCCurStyle->DRCRulesTbl[TT_SPACE][ttype]; cptr != (DRCCookie *) NULL; + cptr = cptr->drcc_next) + { + /* FORWARD rules only, and no MAXWIDTH */ + if ((cptr->drcc_flags & (DRC_REVERSE | DRC_MAXWIDTH)) == 0) + { + set = &cptr->drcc_mask; + if (TTMaskHasType(set, ttype) && TTMaskEqual(set, &cptr->drcc_corner)) + if ((cptr->drcc_plane == DBPlane(ttype)) && + (cptr->drcc_dist == cptr->drcc_cdist)) + { + routeWidth = cptr->drcc_dist; + /* Diagnostic */ + /* + TxPrintf("DRC: Layer %s has default width %d\n", + DBTypeLongNameTbl[ttype], routeWidth); + */ + } + } + } + return routeWidth; +} + +/* + *----------------------------------------------------------------------------- + * DRCGetDefaultLayerSpacing --- + * + * Determine a default layer-to-layer spacing from the DRC width + * rules of a layer. Continue processing all rules, since rules + * are ordered from shortest to longest distance, and the largest + * distance matching the criteria sets the rule. + * + * Results: + * The minimum spacing between the specified magic layer types, + * in magic internal units + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +int +DRCGetDefaultLayerSpacing(ttype1, ttype2) + TileType ttype1, ttype2; +{ + int routeSpacing = 0; + DRCCookie *cptr; + TileTypeBitMask *set; + + for (cptr = DRCCurStyle->DRCRulesTbl[ttype1][TT_SPACE]; cptr != (DRCCookie *) NULL; + cptr = cptr->drcc_next) + { + if (cptr->drcc_flags & DRC_TRIGGER) { /* Skip widespacing rules */ + cptr = cptr->drcc_next; + continue; + } + if ((cptr->drcc_flags & DRC_REVERSE) == 0) /* FORWARD only */ + { + set = &cptr->drcc_mask; + if (!TTMaskHasType(set, ttype2)) + if (PlaneMaskHasPlane(DBTypePlaneMaskTbl[ttype2], cptr->drcc_plane) && + (cptr->drcc_dist == cptr->drcc_cdist)) + { + routeSpacing = cptr->drcc_dist; + /* Diagnostic */ + /* + TxPrintf("DRC: Layer %s has default spacing %d to layer %s\n", + DBTypeLongNameTbl[ttype1], routeSpacing, + DBTypeLongNameTbl[ttype2]); + */ + } + } + } + return routeSpacing; +} + +/* + *----------------------------------------------------------------------------- + * DRCGetDefaultLayerSurround --- + * + * Determine the default minimum required surround amount + * of layer type 2 around layer type 1. + * Continue processing all rules, since rules are ordered from + * shortest to longest distance, and the largest value of the + * surround material sets the minimum required width. + * + * Results: + * The minimum spacing between the specified magic layer types, + * in magic internal units + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +int +DRCGetDefaultLayerSurround(ttype1, ttype2) + TileType ttype1, ttype2; +{ + int layerSurround = 0; + DRCCookie *cptr; + TileTypeBitMask *set; + + for (cptr = DRCCurStyle->DRCRulesTbl[ttype1][TT_SPACE]; cptr != (DRCCookie *) NULL; + cptr = cptr->drcc_next) + { + if ((cptr->drcc_flags & DRC_REVERSE) == 0) /* FORWARD only */ + { + set = &cptr->drcc_mask; + if (!TTMaskHasType(set, TT_SPACE)) + if (PlaneMaskHasPlane(DBTypePlaneMaskTbl[ttype2], cptr->drcc_plane) && + (cptr->drcc_dist == cptr->drcc_cdist)) + { + layerSurround = cptr->drcc_dist; + /* Diagnostic */ + /* + TxPrintf("DRC: Layer %s has default surround %d over layer %s\n", + DBTypeLongNameTbl[ttype2], layerSurround, + DBTypeLongNameTbl[ttype1]); + */ + } + } + } + return layerSurround; +} diff --git a/drc/Depend b/drc/Depend new file mode 100644 index 00000000..d8c486cb --- /dev/null +++ b/drc/Depend @@ -0,0 +1,36 @@ +DRCarray.o: DRCarray.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h ../drc/drc.h \ + ../windows/windows.h ../commands/commands.h +DRCbasic.o: DRCbasic.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h ../drc/drc.h \ + ../utils/signals.h ../utils/maxrect.h ../utils/malloc.h +DRCcif.o: DRCcif.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../windows/windows.h \ + ../dbwind/dbwind.h ../dbwind/dbwtech.h ../drc/drc.h ../cif/cif.h \ + ../cif/CIFint.h ../utils/signals.h ../utils/stack.h ../utils/malloc.h \ + ../utils/utils.h +DRCcontin.o: DRCcontin.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../textio/textio.h ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../windows/windows.h ../dbwind/dbwind.h \ + ../dbwind/dbwtech.h ../utils/main.h ../commands/commands.h ../drc/drc.h \ + ../utils/signals.h ../graphics/graphics.h ../utils/undo.h \ + ../utils/malloc.h +DRCmain.o: DRCmain.c ../utils/magic.h ../utils/malloc.h \ + ../textio/textio.h ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../windows/windows.h ../dbwind/dbwind.h \ + ../drc/drc.h ../utils/undo.h +DRCsubcell.o: DRCsubcell.c ../utils/magic.h ../textio/textio.h \ + ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../drc/drc.h ../windows/windows.h \ + ../commands/commands.h ../utils/undo.h +DRCtech.o: DRCtech.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/utils.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../drc/drc.h ../utils/tech.h ../textio/textio.h \ + ../utils/malloc.h ../cif/cif.h ../cif/CIFint.h +DRCprint.o: DRCprint.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h ../drc/drc.h +DRCextend.o: DRCextend.c ../utils/magic.h ../utils/malloc.h \ + ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../windows/windows.h ../dbwind/dbwind.h \ + ../dbwind/dbwtech.h ../drc/drc.h ../utils/signals.h ../utils/stack.h \ + ../utils/maxrect.h diff --git a/drc/Makefile b/drc/Makefile new file mode 100644 index 00000000..84a14297 --- /dev/null +++ b/drc/Makefile @@ -0,0 +1,11 @@ +# +# rcsid "$Header: /usr/cvsroot/magic-8.0/drc/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" +# + +MODULE = drc +MAGICDIR = .. +SRCS = DRCarray.c DRCbasic.c DRCcif.c DRCcontin.c DRCmain.c \ + DRCsubcell.c DRCtech.c DRCprint.c DRCextend.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/drc/drc.h b/drc/drc.h new file mode 100644 index 00000000..1ee8b9db --- /dev/null +++ b/drc/drc.h @@ -0,0 +1,273 @@ +/* + * drc.h -- + * + * Definitions for the DRC module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * Needs to include: magic.h database.h + * + * rcsid $Header: /usr/cvsroot/magic-8.0/drc/drc.h,v 1.6 2010/09/20 21:13:22 tim Exp $ + */ + +#ifndef _DRC_H +#define _DRC_H + +#include "database/database.h" + +/* ----------------- component of DRC table ---------------------------- */ + +typedef struct drccookie +{ + int drcc_dist; /* Extent of rule from edge. */ + unsigned char drcc_mod; /* Fractional part of drcc_dist */ + int drcc_cdist; /* Size of corner extension.* */ + unsigned char drcc_cmod; /* Fractional part of drcc_cdist */ + TileTypeBitMask drcc_mask; /* Legal types on RHS */ + TileTypeBitMask drcc_corner; /* Types that trigger corner check */ + unsigned char drcc_flags; /* Miscellaneous flags, see below. */ + int drcc_edgeplane; /* Plane of edge */ + int drcc_plane; /* Index of plane on which to check + * legal types. */ + char *drcc_why; /* Explanation of error found */ + struct drccookie *drcc_next; +} DRCCookie; + +/* *This is size "int" because it holds an area for DRC_AREA rules, */ +/* and therefore may have twice the bit length of a normal rule distance. */ + +/* DRCCookie flags: + * DRC_FORWARD: Rule applies from left to right (or bottom to top). + * DRC_REVERSE: Rule applies from right to left (or top to bottom). + * DRC_BOTHCORNERS: Must make corner extensions in both directions. + * DRC_OUTSIDE: Rule applies only to the outside edge of the rule area. + * DRC_TRIGGER: Violation of rule triggers a secondary rule. + * + * All other flags denote special DRC rules that do not use the standard 4-way + * edge processing. + */ + +#define DRC_FORWARD 0x00 +#define DRC_REVERSE 0x01 +#define DRC_BOTHCORNERS 0x02 +#define DRC_TRIGGER 0x04 +#define DRC_BENDS 0x08 +#define DRC_OUTSIDE 0x08 // Note: Shared with DRC_BENDS +#define DRC_AREA 0x10 +#define DRC_MAXWIDTH 0x20 +#define DRC_RECTSIZE 0x40 +#define DRC_ANGLES 0x80 +#define DRC_NONSTANDARD (DRC_AREA|DRC_MAXWIDTH|DRC_RECTSIZE|DRC_ANGLES) + +#define DRC_PENDING 0 +#define DRC_UNPROCESSED CLIENTDEFAULT +#define DRC_PROCESSED 1 + +/* + * Background DRC (DRC Idle proc) for Tcl-based Magic + */ +#ifdef MAGIC_WRAPPER +enum { DRC_NOT_RUNNING, DRC_IN_PROGRESS, DRC_BREAK_PENDING }; +extern unsigned char DRCStatus; +#endif + +/* + * States of the background checker. This allows us to force an off state + * during initialization while allowing the startup scripts to set the + * state on or off. + */ +enum { DRC_SET_OFF, DRC_SET_ON, DRC_NOT_SET }; + +/* This is client data passed down through the various DRC checking + * routines, and contains information about the area and rule being + * checked. + */ +struct drcClientData +{ + CellDef * dCD_celldef; /* CellDef, plane and area to DRC. */ + int dCD_plane; + Rect * dCD_rect; + Tile * dCD_initial; /* Initial tile for search (left side + * for forward rules, right for reverse + * rules). + */ + Rect * dCD_clip; /* Clip error tiles against this. */ + int * dCD_errors; /* Count of errors found. */ + int dCD_radial; /* Radial check for corner extensions */ + DRCCookie * dCD_cptr; /* Rule being checked. */ + Rect * dCD_constraint; /* Constraint area from rule. */ + Rect * dCD_rlist; /* Multiple constraints for triggered rules */ + int dCD_entries; /* Number of constraints for triggered rules */ + void (* dCD_function)(); /* Function to call for each + * error found. */ + ClientData dCD_clientData; /* Parameter for dCD_function */ +}; + +/* Describes a cell whose contents require design-rule checking of + * some sort. These are linked together for processing by the + * continuous checker. + */ +#define DRCYANK "__DRCYANK__" /* predefined DRC yank buffer */ + +typedef struct drcpendingcookie +{ + CellDef *dpc_def; + struct drcpendingcookie *dpc_next; +} DRCPendingCookie; + +/* Structure used to pass back lists of cell definitions and error tile counts */ + +typedef struct drccountlist +{ + CellDef *dcl_def; + int dcl_count; + struct drccountlist *dcl_next; +} DRCCountList; + +/* Structure used to keep information about the current DRC style */ + +typedef struct drckeep +{ + struct drckeep *ds_next; + char *ds_name; +} DRCKeep; + +/* + * DRC "why" strings are potentially referred to hundreds of times by + * DRC cookies in the rule table. Rather than creating hundreds of + * copies of each string, we create just one copy and let all the cookies + * point to that one copy. + * + * Since we can't free these shared "why" strings when we delete a cookie, + * we keep a list of these strings and free them all when convenient. + */ + +typedef struct drcwhylist +{ + char * dwl_string; + struct drcwhylist * dwl_next; +} drcWhyList; + +/* + * Structure defining a DRC style + */ + +typedef struct drcstyle +{ + char ds_status; /* Status: Loaded, not loaded, or pending */ + char *ds_name; /* Name of this DRC style */ + DRCCookie *DRCRulesTbl[TT_MAXTYPES][TT_MAXTYPES]; + TileTypeBitMask DRCExactOverlapTypes; + int DRCScaleFactorN; /* Divide dist by this to get magic units */ + int DRCScaleFactorD; /* Multiply dist by this to get magic units */ + int DRCTechHalo; /* largest action distance of design rules */ + int DRCStepSize; /* chunk size for decomposing large areas */ + drcWhyList *DRCWhyList; + PaintResultType DRCPaintTable[NP][NT][NT]; +} DRCStyle; + +/* Things shared between DRC functions, but not used by the + * outside world: + */ + +extern int DRCstatEdges; /* counters for statistics gathering */ +extern int DRCstatSlow; +extern int DRCstatRules; +extern int DRCstatTiles; +extern int DRCstatInteractions; +extern int DRCstatIntTiles; +extern int DRCstatCifTiles; +extern int DRCstatSquares; +extern int DRCstatArrayTiles; + +#ifdef DRCRULESHISTO +# define DRC_MAXRULESHISTO 30 /* Max rules per edge for statistics */ +extern int DRCstatHRulesHisto[DRC_MAXRULESHISTO]; +extern int DRCstatVRulesHisto[DRC_MAXRULESHISTO]; +#endif /* DRCRULESHISTO */ + +extern int DRCTechHalo; /* Current halo being used */ +extern int DRCStepSize; /* Current step size being used */ +extern DRCPendingCookie * DRCPendingRoot; + +extern unsigned char DRCBackGround; /* global flag to enable/disable + * continuous DRC + */ +extern bool DRCEuclidean; /* global flag to enable/disable + * Euclidean distance measure + */ +extern int dbDRCDebug; +extern bool DRCForceReload; /* TRUE if we have to reload DRC on a + * change of the CIF output style + */ + +extern DRCKeep *DRCStyleList; /* List of available DRC styles */ +extern DRCStyle *DRCCurStyle; /* Current DRC style in effect */ +extern CellDef *DRCdef; /* Current cell being checked for DRC */ +extern CellUse *DRCuse, *DRCDummyUse; + +/* + * Internal procedures + */ + +extern void drcPaintError(); +extern void drcPrintError(); +extern int drcIncludeArea(); +extern int drcExactOverlapTile(); +extern void drcInitRulesTbl(); + +/* + * Exported procedures + */ + +extern int DRCGetDefaultLayerWidth(); +extern int DRCGetDefaultLayerSpacing(); +extern int DRCGetDefaultLayerSurround(); + +extern void DRCTechInit(); +extern bool DRCTechLine(); +extern bool DRCTechAddRule(); +extern void DRCTechStyleInit(); +extern void DRCTechFinal(); +extern void DRCTechRuleStats(); +extern void DRCTechScale(); +extern void DRCReloadCurStyle(); + +extern void DRCInit(); +extern void DRCContinuous(); +extern void DRCCheckThis(); +extern void DRCRemovePending(); +extern void DRCPrintRulesTable(); +extern void DRCWhy(); +extern void DRCPrintStats(); +extern void DRCCheck(); +extern DRCCountList *DRCCount(); +extern int DRCFind(); +extern void DRCCatchUp(); +extern bool DRCFindInteractions(); + +extern void DRCPrintStyle(); +extern void DRCSetStyle(); +extern void DRCLoadStyle(); + +/* The following macro can be used by the outside world to see if + * the background checker needs to be called. + */ + +#ifdef MAGIC_WRAPPER +#define DRCHasWork ((DRCPendingRoot != NULL) && (DRCBackGround == DRC_SET_ON)) +#else +#define DRCHasWork ((DRCPendingRoot != NULL) && (DRCBackGround != DRC_SET_OFF)) +#endif + +#endif /* _DRC_H */ diff --git a/ext2sim/Depend b/ext2sim/Depend new file mode 100644 index 00000000..91214224 --- /dev/null +++ b/ext2sim/Depend @@ -0,0 +1,6 @@ +ext2sim.o: ext2sim.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/hash.h ../utils/utils.h ../tiles/tile.h \ + ../database/database.h ../windows/windows.h ../textio/textio.h \ + ../dbwind/dbwind.h ../commands/commands.h ../textio/txcommands.h \ + ../extflat/extflat.h ../extract/extract.h ../utils/runstats.h \ + ../utils/malloc.h diff --git a/ext2sim/Makefile b/ext2sim/Makefile new file mode 100644 index 00000000..ff4a218c --- /dev/null +++ b/ext2sim/Makefile @@ -0,0 +1,37 @@ +# +# rcsid "$Header: /usr/cvsroot/magic-8.0/ext2sim/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" +# + +MODULE = ext2sim +MAGICDIR = .. +SRCS = ext2sim.c + +EXTRA_LIBS = ${MAGICDIR}/extflat/libextflat.o ${MAGICDIR}/utils/libutils.a + +include ${MAGICDIR}/defs.mak + +LIBS += -lm ${LD_EXTRA_LIBS} ${SUB_EXTRA_LIBS} +CLEANS += exttosim${SHDLIB_EXT} simwrap.o + +main: ext2sim + +tcl-main: exttosim${SHDLIB_EXT} + +simwrap.o: ext2sim.c + ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ext2sim.c -c -o simwrap.o + +exttosim${SHDLIB_EXT}: simwrap.o ${MAGICDIR}/extflat/libextflat.o + @echo --- making exttosim Tcl library \(exttosim${SHDLIB_EXT}\) + ${RM} exttosim${SHDLIB_EXT} + ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} simwrap.o \ + ${MAGICDIR}/extflat/libextflat.o ${LD_SHARED} -lc ${LIBS} + +install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} + +install-tcl: $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT} + +$(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT}: exttosim${SHDLIB_EXT} + ${RM} $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT} + ${CP} exttosim${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT} + +include ${MAGICDIR}/rules.mak diff --git a/ext2sim/ext2sim.c b/ext2sim/ext2sim.c new file mode 100644 index 00000000..f147616f --- /dev/null +++ b/ext2sim/ext2sim.c @@ -0,0 +1,1707 @@ +/* + * ext2sim.c -- + * + * Program to flatten hierarchical .ext files and produce + * a .sim file, suitable for use as input to simulators + * such as esim and crystal. + * + * Flattens the tree rooted at file.ext, reading in additional .ext + * files as specified by "use" lines in file.ext. The output is left + * in file.sim, unless '-o esSimFile' is specified, in which case the + * output is left in 'esSimFile'. + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ext2sim/ext2sim.c,v 1.2 2008/12/03 14:12:09 tim Exp $"; +#endif /* not lint */ + +#include +#include /* for atof() */ +#include +#include +#include /* for sqrt() in bipolar L,W calculation */ + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#ifdef MAGIC_WRAPPER +#include "database/database.h" +#include "windows/windows.h" +#include "textio/textio.h" +#include "dbwind/dbwind.h" /* for DBWclientID */ +#include "commands/commands.h" /* for module auto-load */ +#include "textio/txcommands.h" +#endif +#include "extflat/extflat.h" +#include "extract/extract.h" /* for extDevTable */ +#include "utils/runstats.h" +#include "utils/malloc.h" + +/* Forward declarations */ +#ifdef MAGIC_WRAPPER +void CmdExtToSim(); +#endif +bool simnAP(); +bool simnAPHier(); +int simmainArgs(); +int simdevVisit(), simresistVisit(), simcapVisit(), simnodeVisit(); +int simmergeVisit(); + +/* Options specific to ext2sim */ +#ifdef EXT2SIM_AUTO +bool esDoExtResis = FALSE; +bool esDevNodesOnly = FALSE; +bool esNoAttrs = FALSE; +bool esHierAP = FALSE; +bool esMergeDevsA = FALSE; /* merge devices of equal length */ +bool esMergeDevsC = FALSE; /* merge devices of equal length & width */ +int esCapAccuracy = 1; + +#else +extern bool esDoExtResis; +extern bool esDevNodesOnly; +extern bool esNoAttrs; +extern bool esHierAP; +extern bool esMergeDevsA; +extern bool esMergeDevsC; +extern int esCapAccuracy; +#endif + +bool esNoAlias = TRUE; +bool esNoLabel = TRUE; +char simesDefaultOut[FNSIZE]; +char *simesOutName = simesDefaultOut; +char esDefaultAlias[FNSIZE], esDefaultLabel[FNSIZE]; +char *esAliasName = esDefaultAlias; +char *esLabelName = esDefaultLabel; +char esCapFormat[FNSIZE]; +FILE *esSimF = NULL; +FILE *esAliasF = NULL; +FILE *esLabF = NULL; + + +#define MIT 0 +#define LBL 1 +#define SU 2 + +static unsigned short esFormat = MIT ; + +struct { + short resClassSD ; /* the resistance class of the src/drn of the dev */ + short resClassSub ; /* the resistance class of the substrate of the dev */ + char *defSubs ; /* the default substrate node */ +} fetInfo[MAXDEVTYPES]; + +typedef struct { + long visitMask:MAXDEVTYPES; +} nodeClient; + +typedef struct { + HierName *lastPrefix; + long visitMask:MAXDEVTYPES; +} nodeClientHier; + +#define NO_RESCLASS -1 + +#define markVisited(client, rclass) \ + { (client)->visitMask |= (1<visitMask = (long)0; } + +#define beenVisited(client, rclass) \ + ( (client)->visitMask & (1<efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \ + (( nodeClient *)(node)->efnode_client)->visitMask = (long) 0; \ +} + + +#define initNodeClientHier(node) \ +{ \ + (node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClientHier))); \ + ((nodeClientHier *) (node)->efnode_client)->visitMask = (long) 0; \ +} + + +/* device merging */ + +#define devIsKilled(n) (esFMult[(n)] <= (float)0.0) +#define DEV_KILLED ((float) -1.0) +#define FMULT_SIZE (1<<10) +static float *esFMult = NULL; +static int esFMIndex = 0; +static int esFMSize = FMULT_SIZE; +int esDevsMerged; + +/* macro to add a dev's multiplier to the table and grow it if necessary */ +#define addDevMult(f) \ +{ \ + if ( esFMult == NULL ) { \ + esFMult = (float *) mallocMagic((unsigned) (esFMSize*sizeof(float))); \ + } else if ( esFMIndex >= esFMSize ) { \ + int i; \ + float *op = esFMult ; \ + esFMult = (float *) mallocMagic((unsigned) ((esFMSize = esFMSize*2)*sizeof(float))); \ + for ( i = 0 ; i < esFMSize/2 ; i++ ) esFMult[i] = op[i]; \ + if (op) freeMagic(op); \ + } \ + esFMult[esFMIndex++] = (float)(f); \ +} + +#define setDevMult(i,f) { esFMult[(i)] = (float)(f); } + +#define getCurDevMult() ((esFMult) ? esFMult[esFMIndex-1] : (float)1.0) + +/* cache list used to find parallel devs */ +typedef struct _devMerge { + int l, w; + EFNode *g, *s, *d, *b; + Dev * dev; + int esFMIndex; + HierName *hierName; + struct _devMerge *next; +} devMerge; + +#ifdef EXT2SIM_AUTO +devMerge *devMergeList = NULL ; +#else +extern devMerge *devMergeList; +#endif + +/* attributes controlling the Area/Perimeter extraction of fet terminals */ +#define ATTR_FLATAP "*[Ee][Xx][Tt]:[Aa][Pp][Ff]*" +#define ATTR_HIERAP "*[Ee][Xx][Tt]:[Aa][Pp][Hh]*" +#define ATTR_SUBSAP "*[Ee][Xx][Tt]:[Aa][Pp][Ss]*" + +#ifdef MAGIC_WRAPPER + +#define atoCap(s) ((EFCapValue)atof(s)) + +/* Forward declaration */ +int _ext2sim_start(); + +#ifdef EXT2SIM_AUTO +/* + * ---------------------------------------------------------------------------- + * + * Tcl package initialization function + * + * ---------------------------------------------------------------------------- + */ + +int +Exttosim_Init(interp) + Tcl_Interp *interp; +{ + /* Sanity checks! */ + if (interp == NULL) return TCL_ERROR; + if (Tcl_PkgRequire(interp, "Tclmagic", MAGIC_VERSION, 0) == NULL) + return TCL_ERROR; + if (Tcl_InitStubs(interp, "8.1", 0) == NULL) return TCL_ERROR; + + TxPrintf("Auto-loading EXTTOSIM module\n"); + TxFlushOut(); + + /* Replace the auto-load function with the one defined in */ + /* this package in the command functions list. */ + + if (WindReplaceCommand(DBWclientID, "exttosim", CmdExtToSim) < 0) + return TCL_ERROR; + + /* ext2sim is an alias for exttosim */ + if (WindReplaceCommand(DBWclientID, "ext2sim", CmdExtToSim) < 0) + return TCL_ERROR; + + Tcl_PkgProvide(interp, "Exttosim", MAGIC_VERSION); + return TCL_OK; +} + +#endif /* EXT2SIM_AUTO */ + + +/* + * ---------------------------------------------------------------------------- + * + * Main Tcl callback for command "magic::exttosim" + * + * ---------------------------------------------------------------------------- + */ + +#define EXTTOSIM_RUN 0 +#define EXTTOSIM_ALIAS 1 +#define EXTTOSIM_LABELS 2 +#define EXTTOSIM_DEFAULT 3 +#define EXTTOSIM_FORMAT 4 +#define EXTTOSIM_RTHRESH 5 +#define EXTTOSIM_CTHRESH 6 +#define EXTTOSIM_MERGE 7 +#define EXTTOSIM_EXTRESIST 8 +#define EXTTOSIM_HELP 9 + +void +CmdExtToSim(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int i,flatFlags; + char *inName; + FILE *f; + + int value; + int option = EXTTOSIM_RUN; + int argc = cmd->tx_argc; + char **argv = cmd->tx_argv; + char **msg; + bool err_result; + + short sd_rclass; + short sub_rclass; + char *devname; + char *subname; + int idx; + + static EFCapValue LocCapThreshold = 2; + static int LocResistThreshold = 10; + + static char *cmdExtToSimOption[] = { + "[run] [options] run exttosim on current cell\n" + " use \"run -help\" to get standard options", + "alias on|off enable/disable alias (.al) file", + "labels on|off enable/disable labels (.nodes) file", + "default reset to default values", + "format MIT|SU|LBL set output format", + "rthresh [value] set resistance threshold value", + "cthresh [value] set capacitance threshold value", + "merge [option] merge parallel transistors", + "extresist on|off incorporate extresist output", + "help print help information", + NULL + }; + + static char *sim_formats[] = { + "MIT", + "LBL", + "SU", + NULL + }; + + static char *yesno[] = { + "yes", + "true", + "on", + "no", + "false", + "off", + NULL + }; + + static char *cmdMergeTypes[] = { + "none don't merge parallel devices", + "conservative merge devices with same L, W", + "aggressive merge devices with same L" + }; + + if (cmd->tx_argc > 1) + { + option = Lookup(cmd->tx_argv[1], cmdExtToSimOption); + if (option < 0) option = EXTTOSIM_RUN; + else argv++; + } + + switch (option) + { + case EXTTOSIM_EXTRESIST: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, (esDoExtResis) ? "on" : "off", NULL); + return; + } + else if (cmd->tx_argc != 3) + goto usage; + idx = Lookup(cmd->tx_argv[2], yesno); + if (idx < 0) goto usage; + else if (idx < 3) esDoExtResis = TRUE; + else esDoExtResis = FALSE; + break; + case EXTTOSIM_ALIAS: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, (esNoAlias) ? "off" : "on", NULL); + return; + } + else if (cmd->tx_argc != 3) + goto usage; + idx = Lookup(cmd->tx_argv[2], yesno); + if (idx < 0) goto usage; + else if (idx < 3) esNoAlias = FALSE; + else esNoAlias = TRUE; + break; + case EXTTOSIM_LABELS: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, (esNoLabel) ? "off" : "on", NULL); + return; + } + else if (cmd->tx_argc != 3) + goto usage; + idx = Lookup(cmd->tx_argv[2], yesno); + if (idx < 0) goto usage; + else if (idx < 3) esNoLabel = FALSE; + else esNoLabel = TRUE; + break; + case EXTTOSIM_CTHRESH: + if (cmd->tx_argc == 2) + { + if (!IS_FINITE_F(LocCapThreshold)) + Tcl_SetResult(magicinterp, "infinite", NULL); + else + Tcl_SetObjResult(magicinterp, + Tcl_NewDoubleObj((double)LocCapThreshold)); + return; + } + else if (cmd->tx_argc < 3) goto usage; + if (!strncmp(cmd->tx_argv[2], "inf", 3)) + LocCapThreshold = INFINITE_THRESHOLD_F; + else if (StrIsNumeric(cmd->tx_argv[2])) + LocCapThreshold = atoCap(cmd->tx_argv[2]); + else + TxError("exttosim: numeric value or \"infinite\" expected.\n"); + break; + case EXTTOSIM_RTHRESH: + if (cmd->tx_argc == 2) + { + if (LocResistThreshold == INFINITE_THRESHOLD) + Tcl_SetResult(magicinterp, "infinite", NULL); + else + Tcl_SetObjResult(magicinterp, + Tcl_NewIntObj(LocResistThreshold)); + return; + } + else if (cmd->tx_argc < 3) goto usage; + if (StrIsInt(cmd->tx_argv[2])) + LocResistThreshold = atoi(cmd->tx_argv[2]); + else if (!strncmp(cmd->tx_argv[2], "inf", 3)) + LocResistThreshold = INFINITE_THRESHOLD; + else + TxError("exttosim: integer value or \"infinite\" expected.\n"); + break; + case EXTTOSIM_FORMAT: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, sim_formats[esFormat], TCL_STATIC); + return; + } + else if (cmd->tx_argc < 3) goto usage; + value = Lookup(cmd->tx_argv[2], sim_formats); + if (value < 0) + TxError("exttosim: output formats are MIT, LBL, or SU\n"); + else + esFormat = value; + break; + case EXTTOSIM_MERGE: + if (cmd->tx_argc == 2) + { + if (esMergeDevsA) + Tcl_SetResult(magicinterp, "aggressive", NULL); + else if (esMergeDevsC) + Tcl_SetResult(magicinterp, "conservative", NULL); + else + Tcl_SetResult(magicinterp, "none", NULL); + return; + } + else if (cmd->tx_argc < 3) goto usage; + value = Lookup(cmd->tx_argv[2], cmdMergeTypes); + if (value < 0) + { + TxError("Merge types are:\n"); + for (msg = &(cmdMergeTypes[0]); *msg != NULL; msg++) + TxPrintf(" %s\n", *msg); + } + else switch (value) { + case 0: + esMergeDevsA = FALSE; + esMergeDevsC = FALSE; + break; + case 1: + esMergeDevsA = FALSE; + esMergeDevsC = TRUE; + break; + case 2: + esMergeDevsA = TRUE; + esMergeDevsC = FALSE; + break; + } + break; + + case EXTTOSIM_DEFAULT: + LocCapThreshold = 2; + LocResistThreshold = 10; + EFTrimFlags = 0; + EFScale = 0.0; + if (EFArgTech) + { + freeMagic(EFArgTech); + EFArgTech = NULL; + } + if (EFSearchPath) + { + freeMagic(EFSearchPath); + EFSearchPath = NULL; + } + break; + case EXTTOSIM_RUN: + goto runexttosim; + break; + case EXTTOSIM_HELP: +usage: + for (msg = &(cmdExtToSimOption[0]); *msg != NULL; msg++) + { + TxPrintf(" %s\n", *msg); + } + break; + } + return; + +runexttosim: + + esDevsMerged = 0; + esFMIndex = 0; + + EFInit(); + + /* Set local values for capacitor and resistor thresholds */ + EFCapThreshold = LocCapThreshold; + EFResistThreshold = LocResistThreshold; + + /* Process command line arguments */ + inName = EFArgs(argc, argv, &err_result, simmainArgs, (ClientData) NULL); + + if (err_result == TRUE) + { + EFDone(); + return /* TCL_ERROR */; + } + + if (inName == NULL) + { + /* Assume that we want to do exttospice on the currently loaded cell */ + + if (w == (MagWindow *) NULL) + windCheckOnlyWindow(&w, DBWclientID); + + if (w == (MagWindow *) NULL) + { + TxError("Point to a window or specify a cell name.\n"); + EFDone(); + return /* TCL_ERROR */; + } + inName = ((CellUse *) w->w_surfaceID)->cu_def->cd_name; + } + + /* + * Initializations specific to this program. + * Make output, alias, and label names be of the form + * inName.suffix if they weren't explicitly specified, + * where suffix is .sim, .al, or .nodes. + */ + + /* Addendum: Because extresis depends on ".sim" output, we */ + /* add ".res" in the output name (the same as used for the */ + /* ".res.ext" output) so that this output won't be grabbed */ + /* the next time "extresist" is run. */ + + if (simesOutName == simesDefaultOut) + (void) sprintf(simesDefaultOut, "%s%s.sim", inName, + ((esDoExtResis) ? ".ext" : "")); + if (esAliasName == esDefaultAlias) + (void) sprintf(esDefaultAlias, "%s%s.al", inName, + ((esDoExtResis) ? ".ext" : "")); + if (esLabelName == esDefaultLabel) + (void) sprintf(esDefaultLabel, "%s%s.nodes", inName, + ((esDoExtResis) ? ".ext" : "")); + if ((esSimF = fopen(simesOutName, "w")) == NULL) + { + char *tclres = Tcl_Alloc(128); + sprintf(tclres, "exttosim: Unable to open file %s for writing\n", + simesOutName); + Tcl_SetResult(magicinterp, tclres, TCL_DYNAMIC); + EFDone(); + return /* TCL_ERROR */; + } + if (!esNoAlias && (esAliasF = fopen(esAliasName, "w")) == NULL) + { + char *tclres = Tcl_Alloc(128); + sprintf(tclres, "exttosim: Unable to open file %s for writing\n", + esAliasName); + Tcl_SetResult(magicinterp, tclres, TCL_DYNAMIC); + EFDone(); + return /* TCL_ERROR */; + } + if (!esNoLabel && (esLabF = fopen(esLabelName, "w")) == NULL) + { + char *tclres = Tcl_Alloc(128); + sprintf(tclres, "exttosim: Unable to open file %s for writing\n", + esLabelName); + Tcl_SetResult(magicinterp, tclres, TCL_DYNAMIC); + return /* TCL_ERROR */; + } + + /* Read the hierarchical description of the input circuit */ + if (EFReadFile(inName, FALSE, esDoExtResis, FALSE) == FALSE) + { + EFDone(); + return /* TCL_ERROR */; + } + + if ((EFStyle == NULL) && (esFormat == SU)) + { + TxError("Warning: Current extraction style does not match .ext file!\n"); + TxError("Area/Perimeter values will be zero.\n"); + } + + /* create default fetinfo entries (MOSIS) which can be overriden by + the command line arguments */ + + for ( i = 0 ; i < MAXDEVTYPES ; i++ ) + { + fetInfo[i].resClassSD = NO_RESCLASS; + fetInfo[i].resClassSub = NO_RESCLASS; + fetInfo[i].defSubs = NULL; + } + + /* Get fetInfo information from the current extraction style */ + /* (this works only for the Tcl version with the embedded exttospice */ + /* command) */ + + idx = 0; + while (ExtGetDevInfo(idx++, &devname, &sd_rclass, &sub_rclass, &subname)) + { + if (idx == MAXDEVTYPES) + { + TxError("Error: Ran out of space for device types!\n"); + break; + } + i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, devname); + + if (EFStyle != NULL) + { + fetInfo[i].resClassSD = sd_rclass; + fetInfo[i].resClassSub = sub_rclass; + fetInfo[i].defSubs = subname; + } + } + + /* Write the output file */ + + fprintf(esSimF, "| units: %g tech: %s format: %s\n", EFScale, EFTech, + (esFormat == MIT) ? "MIT" : + ( (esFormat == LBL) ? "LBL" : "SU" ) ); + + /* Convert the hierarchical description to a flat one */ + flatFlags = EF_FLATNODES; + if (IS_FINITE_F(LocCapThreshold)) flatFlags |= EF_FLATCAPS; + if (LocResistThreshold != INFINITE_THRESHOLD) flatFlags |= EF_FLATRESISTS; + EFFlatBuild(inName, flatFlags); + + if (esMergeDevsA || esMergeDevsC) + { + devMerge *p; + + EFVisitDevs(simmergeVisit, (ClientData) NULL); + TxPrintf("Devices merged: %d\n", esDevsMerged); + esFMIndex = 0; + for (p = devMergeList; p != NULL; p = p->next) + freeMagic(p); + devMergeList = NULL; + } + + EFVisitDevs(simdevVisit, (ClientData)NULL); + if (flatFlags & EF_FLATCAPS) { + (void) sprintf( esCapFormat, " %%.%dlf\n", esCapAccuracy); + EFVisitCaps(simcapVisit, (ClientData) NULL); + } + EFVisitResists(simresistVisit, (ClientData) NULL); + (void) sprintf( esCapFormat, " GND %%.%dlf\n", esCapAccuracy); + EFVisitNodes(simnodeVisit, (ClientData) NULL); + + EFFlatDone(); + EFDone(); + + if (esSimF) fclose(esSimF); + if (esLabF) fclose(esLabF); + if (esAliasF) fclose(esAliasF); + + TxPrintf("exttosim finished.\n"); +} + +#else /* !MAGIC_WRAPPER */ + +/* + * ---------------------------------------------------------------------------- + * + * main -- + * + * Top level of ext2sim (non-Tcl version only) + * + * ---------------------------------------------------------------------------- + */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + + int i,flatFlags; + char *inName; + FILE *f; + + esDevsMerged = 0; + + EFInit(); + /* create default fetinfo entries (MOSIS) which can be overriden by + the command line arguments */ + for ( i = 0 ; i < MAXDEVTYPES ; i++ ) { + fetInfo[i].resClassSD = NO_RESCLASS; + fetInfo[i].resClassSub = NO_RESCLASS; + fetInfo[i].defSubs = NULL; + } + i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "nfet"); + fetInfo[i].resClassSD = 0 ; + fetInfo[i].resClassSub = NO_RESCLASS ; + fetInfo[i].defSubs = "Gnd!"; + i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "pfet"); + fetInfo[i].resClassSD = 1 ; + fetInfo[i].resClassSub = 6 ; + fetInfo[i].defSubs = "Vdd!"; + i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "nmos"); + fetInfo[i].resClassSD = 0 ; + fetInfo[i].resClassSub = NO_RESCLASS ; + fetInfo[i].defSubs = "Gnd!"; + i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "pmos"); + fetInfo[i].resClassSD = 1 ; + fetInfo[i].resClassSub = 6 ; + fetInfo[i].defSubs = "Vdd!"; + /* Process command line arguments */ + inName = EFArgs(argc, argv, NULL, simmainArgs, (ClientData) NULL); + if (inName == NULL) + exit (1); + + /* + * Initializations specific to this program. + * Make output, alias, and label names be of the form + * inName.suffix if they weren't explicitly specified, + * where suffix is .sim, .al, or .nodes. + */ + + if (simesOutName == simesDefaultOut) + (void) sprintf(simesDefaultOut, "%s.sim", inName); + if (esAliasName == esDefaultAlias) + (void) sprintf(esDefaultAlias, "%s.al", inName); + if (esLabelName == esDefaultLabel) + (void) sprintf(esDefaultLabel, "%s.nodes", inName); + if ((esSimF = fopen(simesOutName, "w")) == NULL) + { + perror(simesOutName); + exit (1); + } + if (!esNoAlias && (esAliasF = fopen(esAliasName, "w")) == NULL) + { + perror(esAliasName); + exit (1); + } + if (!esNoLabel && (esLabF = fopen(esLabelName, "w")) == NULL) + { + perror(esLabelName); + exit (1); + } + + /* Read the hierarchical description of the input circuit */ + if (EFReadFile(inName, FALSE, esDoExtResis, FALSE) == FALSE) + { + exit(1); + } + + fprintf(esSimF, "| units: %g tech: %s format: %s\n", EFScale, EFTech, + (esFormat == MIT) ? "MIT" : + ( (esFormat == LBL) ? "LBL" : "SU" ) ); + + /* Convert the hierarchical description to a flat one */ + flatFlags = EF_FLATNODES; + if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS; + if (EFResistThreshold != INFINITE_THRESHOLD) flatFlags |= EF_FLATRESISTS; + EFFlatBuild(inName, flatFlags); + + if (esMergeDevsA || esMergeDevsC) { + devMerge *p; + + EFVisitDevs(simmergeVisit, (ClientData) NULL); + TxPrintf("Devices merged: %d\n", esDevsMerged); + esFMIndex = 0; + for (p = devMergeList; p != NULL; p = p->next) freeMagic(p); + } + + EFVisitDevs(simdevVisit, (ClientData) NULL); + if (flatFlags & EF_FLATCAPS) { + (void) sprintf( esCapFormat, " %%.%dlf\n", esCapAccuracy); + EFVisitCaps(simcapVisit, (ClientData) NULL); + } + EFVisitResists(simresistVisit, (ClientData) NULL); + (void) sprintf( esCapFormat, " GND %%.%dlf\n", esCapAccuracy); + EFVisitNodes(simnodeVisit, (ClientData) NULL); + + EFFlatDone(); + EFDone(); + + if (esSimF) fclose(esSimF); + if (esLabF) fclose(esLabF); + if (esAliasF) fclose(esAliasF); + + TxPrintf("Memory used: %s\n", RunStats(RS_MEM, NULL, NULL)); + exit(0); +} + +#endif /* MAGIC_WRAPPER */ + +/* + * ---------------------------------------------------------------------------- + * + * simmainArgs -- + * + * Process those arguments that are specific to ext2sim. + * Assumes that *pargv[0][0] is '-', indicating a flag + * argument. + * + * Results: + * None. TCL version returns False if an error is encountered + * while parsing arguments, True otherwise. + * + * Side effects: + * After processing an argument, updates *pargc and *pargv + * to point to after the argument. + * + * May initialize various global variables based on the + * arguments given to us. + * + * Exits in the event of an improper argument. + * + * ---------------------------------------------------------------------------- + */ + +int +simmainArgs(pargc, pargv) + int *pargc; + char ***pargv; +{ + char **argv = *pargv, *cp; + int argc = *pargc; + + switch (argv[0][1]) + { + case 'A': + esNoAlias = TRUE; + break; + case 'B': + esNoAttrs = TRUE; + break; + case 'F': + esDevNodesOnly = TRUE; + break; + case 'L': + esNoLabel = TRUE; + break; + case 'M': + esMergeDevsA = TRUE; + break; + case 'm': + esMergeDevsC = TRUE; + break; + case 'a': + if ((esAliasName = ArgStr(&argc, &argv, "filename")) == NULL) + goto usage; + break; + case 'l': + if ((esLabelName = ArgStr(&argc, &argv, "filename")) == NULL) + goto usage; + break; + case 'o': + if ((simesOutName = ArgStr(&argc, &argv, "filename")) == NULL) + goto usage; + break; + case 'f': { + char *ftmp ; + + if ((ftmp = ArgStr(&argc, &argv, "format")) == NULL) + goto usage; + if ( strcasecmp(ftmp,"MIT") == 0 ) + esFormat = MIT ; + else if ( strcasecmp(ftmp,"LBL") == 0 ) + esFormat = LBL ; + else if ( strcasecmp(ftmp,"SU") == 0 ) + esFormat = SU ; + else goto usage; + break; + } + case 'y': { + char *t; + + if (( t = ArgStr(&argc, &argv, "cap-accuracy") ) == NULL) + goto usage; + esCapAccuracy = atoi(t); + break; + } + case 'J': + { + char *ftmp ; + + if ((ftmp = ArgStr(&argc, &argv, "hierAP_SD")) == NULL) + goto usage; + if ( strcasecmp(ftmp, "HIER") == 0 ) + esHierAP = TRUE ; + else if ( strcasecmp(ftmp, "FLAT") == 0 ) + esHierAP = FALSE ; + else goto usage; + + break; + } +#ifndef MAGIC_WRAPPER + case 'j': + { + char *rp, subsNode[80] ; + int ndx, rClass, rClassSub = NO_RESCLASS; + + if ((cp = ArgStr(&argc,&argv,"resistance class")) == NULL) + goto usage; + if ( (rp = strchr(cp,':')) == NULL ) + goto usage; + else *rp++ = '\0'; + if ( sscanf(rp, "%d/%d/%s", &rClass, &rClassSub, subsNode) != 3 ) { + rClassSub = NO_RESCLASS ; + if ( sscanf(rp, "%d/%s", &rClass, subsNode) != 2 ) goto usage; + } + ndx = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, cp); + fetInfo[ndx].resClassSD = rClass; + fetInfo[ndx].resClassSub = rClassSub; + fetInfo[ndx].defSubs = (char *) mallocMagic((unsigned) (strlen(subsNode)+1)); + strcpy(fetInfo[ndx].defSubs,subsNode); + TxError("Info: fet %s(%d) sdRclass=%d subRclass=%d dSub=%s\n", + cp, ndx, fetInfo[ndx].resClassSD, fetInfo[ndx].resClassSub, + fetInfo[ndx].defSubs); + break; + } +#endif /* MAGIC_WRAPPER */ + default: + TxError("Unrecognized flag: %s\n", argv[0]); + goto usage; + } + + *pargv = argv; + *pargc = argc; + return 0; + +usage: + TxError("Usage: ext2sim [-a aliasfile] [-A] [-B] [-l labelfile] [-L]\n" + "[-o simfile] [-J flat|hier] [-y cap_digits]\n" + "[-f mit|lbl|su] " +#ifdef MAGIC_WRAPPER + "[file]\n" +#else + "[-j device:sdRclass[/subRclass]/defaultSubstrate]\n" + "file\n\n or else see options to extcheck(1)\n" +#endif + ); + +#ifdef MAGIC_WRAPPER + return 1; +#else + exit (1); +#endif +} + + +/* + * ---------------------------------------------------------------------------- + * + * SimGetNode -- + * + * function to find a node given its hierarchical prefix and suffix + * + * Results: + * a pointer to the node struct or NULL + * + * ---------------------------------------------------------------------------- + */ +EFNode * +SimGetNode(prefix, suffix) +HierName *prefix; +HierName *suffix; +{ + HashEntry *he; + + he = EFHNConcatLook(prefix, suffix, "output"); + return(((EFNodeName *) HashGetValue(he))->efnn_node); +} + + +/* + * ---------------------------------------------------------------------------- + * + * simdevVisit -- + * + * Procedure to output a single dev to the .sim file. + * Called by EFVisitDevs(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the file esSimF. + * + * Format of a .sim dev line: + * + * type gate source drain l w x y g= s= d= + * + * where + * type is a name identifying this type of transistor + * gate, source, and drain are the nodes to which these three + * terminals connect + * l, w are the length and width of the channel + * x, y are the x, y coordinates of a point within the channel. + * g=, s=, d= are the (optional) attributes; if present, each + * is followed by a comma-separated list of attributes. + * + * ---------------------------------------------------------------------------- + */ + +int +simdevVisit(dev, hierName, scale, trans) + Dev *dev; /* Device being output */ + HierName *hierName; /* Hierarchical path down to this device */ + float scale; /* Scale transform for output */ + Transform *trans; /* Coordinate transform */ +{ + DevTerm *gate, *source, *drain; + EFNode *subnode, *snode, *dnode; + int l, w; + Rect r; + char name[12]; + + sprintf(name, "output"); + + /* If no terminals, can't do much of anything */ + if (dev->dev_nterm < 1) + return 0; + + /* If one terminal, can't do much of anything, either, */ + /* except maybe with a subcircuit device. That's not */ + /* supported by ext2sim, though. . . */ + + if (dev->dev_nterm < 2) + return 0; + + /* Merged devices */ + if ((esMergeDevsA || esMergeDevsC) && devIsKilled(esFMIndex++)) + return 0; + + /* Computation of length and width has been moved from efVisitDevs */ + EFGetLengthAndWidth(dev, &l, &w); + + /* If only two terminals, connect the source to the drain */ + gate = &dev->dev_terms[0]; + if (dev->dev_nterm >= 2) + source = drain = &dev->dev_terms[1]; + if (dev->dev_nterm >= 3) + drain = &dev->dev_terms[2]; + subnode = dev->dev_subsnode; + + /* Kludge for .sim: transistor types can only be one character */ + switch(dev->dev_class) + { + /* "sim" types are fixed according to the device class */ + case DEV_BJT: + fprintf(esSimF, "b"); /* sim format extension */ + break; + case DEV_DIODE: + case DEV_PDIODE: + case DEV_NDIODE: + fprintf(esSimF, "D"); + break; + case DEV_RES: + fprintf(esSimF, "r"); + break; + case DEV_CAP: + case DEV_CAPREV: + fprintf(esSimF, "c"); /* sim format extension */ + break; + default: + fprintf(esSimF, "%c", EFDevTypes[dev->dev_type][0]); + break; + } + + /* Output gate node name. Resistor devices don't generate this node. */ + if (dev->dev_class != DEV_RES) + simdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, name, esSimF); + + /* Output source and drain node names */ + if (dev->dev_nterm > 1) + simdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, name, esSimF); + + /* Hack for BiCMOS---see scmos.tech27 hack: Tim, 7/16/96 */ + /* Second hack, using dev_class 2/20/03 */ + if (EFDevTypes[dev->dev_type][0] == 'b') + dev->dev_class = DEV_BJT; + + if (dev->dev_class == DEV_BJT && subnode) + { + sprintf(name, "fet"); + simdevOutNode(hierName, subnode->efnode_name->efnn_hier, name, esSimF); + } + else if ((dev->dev_class == DEV_DIODE || dev->dev_class == DEV_PDIODE || + dev->dev_class == DEV_NDIODE) && dev->dev_nterm == 1 && subnode) + { + sprintf(name, "fet"); + simdevOutNode(hierName, subnode->efnode_name->efnn_hier, name, esSimF); + } + else if (dev->dev_nterm > 2) + simdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier, name, esSimF); + + /* Support gemini's substrate comparison */ + if (esFormat == LBL && subnode) + { + putc(' ', esSimF); + simdevSubstrate(hierName, subnode->efnode_name->efnn_hier, + dev->dev_type, 0, FALSE, esSimF); + } + + GeoTransRect(trans, &dev->dev_rect, &r); + + if (dev->dev_class == DEV_BJT || EFDevTypes[dev->dev_type][0] == 'b') + { + /* Bipolar sim format: We don't have the length and width + * of the collector well, but we can get it from the area + * and perimeter measurements; hopefully any strict netlist + * comparator will deal with any problem arising from + * swapping L and W. + */ + + int n; + double cl, cw; + double chp = 0.0; + double ca = 0.0; + + for (n = 0; n < efNumResistClasses; n++) { + ca += (double)(subnode->efnode_pa[n].pa_area); + chp += 0.5 * (double)(subnode->efnode_pa[n].pa_perim); + } + + cl = 0.5 * (chp + sqrt(chp * chp - 4 * ca)); + cw = ca / cl; + + fprintf(esSimF, " %d %d %g %g", (int)cl, (int)cw, + r.r_xbot * scale, r.r_ybot * scale); + } + else if (dev->dev_class == DEV_RES) { /* generate a resistor */ + fprintf(esSimF, " %f", (double)(dev->dev_res)); + } + else if (dev->dev_class == DEV_CAP) { /* generate a capacitor */ + fprintf(esSimF, " %f", (double)(dev->dev_cap)); + } + else if (dev->dev_class == DEV_CAPREV) { /* generate a capacitor */ + fprintf(esSimF, " %f", (double)(dev->dev_cap)); + } + else if ((dev->dev_class != DEV_DIODE) && (dev->dev_class != DEV_PDIODE) + && (dev->dev_class != DEV_NDIODE)) { + + /* + * Scale L and W appropriately by the same amount as distance + * values in the transform. The transform will have a scale + * different from 1 only in the case when the scale factors of + * some of the .ext files differed, making it necessary to scale + * all dimensions explicitly instead of having a single scale + * factor at the beginning of the .sim file. + */ + + fprintf(esSimF, " %g %g %g %g", + l * scale, w * scale, r.r_xbot * scale, r.r_ybot * scale); + + /* Attributes, if present */ + if (!esNoAttrs) + { + bool subAP= FALSE, hierS = esHierAP, hierD = esHierAP; + + if (gate->dterm_attrs) + fprintf(esSimF, " g=%s", gate->dterm_attrs); + if ( esFormat == SU ) { + if ( gate->dterm_attrs ) { + subAP = Match(ATTR_SUBSAP, gate->dterm_attrs ) ; + fprintf(esSimF, ","); + } else + fprintf(esSimF, " g="); + simdevSubstrate(hierName, subnode->efnode_name->efnn_hier, + dev->dev_type, scale, subAP, esSimF); + } + if (source->dterm_attrs) { + fprintf(esSimF, " s=%s", source->dterm_attrs); + if ( Match(ATTR_HIERAP, source->dterm_attrs ) != FALSE ) + hierS = TRUE ; + else if ( Match(ATTR_FLATAP, source->dterm_attrs ) != FALSE ) + hierS = FALSE ; + } + if ( esFormat == SU ) { + fprintf(esSimF, "%s", (source->dterm_attrs) ? "," : " s=" ); + if (hierS) + simnAPHier(source, hierName, fetInfo[dev->dev_type].resClassSD, + scale, esSimF); + else { + snode= SimGetNode(hierName, + source->dterm_node->efnode_name->efnn_hier); + simnAP(snode, fetInfo[dev->dev_type].resClassSD, scale, esSimF); + } + } + if (drain->dterm_attrs) { + fprintf(esSimF, " d=%s", drain->dterm_attrs); + if ( Match(ATTR_HIERAP, drain->dterm_attrs ) != FALSE ) + hierD = TRUE ; + else if ( Match(ATTR_FLATAP, drain->dterm_attrs ) != FALSE ) + hierD = FALSE ; + } + if ( esFormat == SU ) { + fprintf(esSimF, "%s", (drain->dterm_attrs) ? "," : " d=" ); + if (hierD) + simnAPHier(drain, hierName, fetInfo[dev->dev_type].resClassSD, + scale, esSimF); + else { + dnode = SimGetNode(hierName, + drain->dterm_node->efnode_name->efnn_hier); + simnAP(dnode, fetInfo[dev->dev_type].resClassSD, + scale, esSimF); + } + } + } + } + fprintf(esSimF, "\n"); + + return 0; +} + +int +simdevSubstrate( prefix, suffix, type, scale, doAP, outf) +HierName *prefix; +HierName *suffix; +int type, scale; +bool doAP; +FILE *outf; +{ + HashEntry *he; + EFNodeName *nn; + char *suf ; + int l ; + EFNode *subnode; + + suf = EFHNToStr(suffix); + if (fetInfo[type].defSubs && strcasecmp(suf,fetInfo[type].defSubs) == 0) { + l = strlen(suf) - 1; + if ( ( EFTrimFlags & EF_TRIMGLOB ) && suf[l] =='!' || + ( EFTrimFlags & EF_TRIMLOCAL ) && suf[l] == '#' ) + suf[l] = '\0' ; + if ( esFormat == SU ) + fprintf(outf, "S_"); + fprintf(outf, "%s", suf); + } + else { + he = EFHNConcatLook(prefix, suffix, "substrate"); + if (he == NULL) + { + fprintf(outf, "errGnd!"); + return 0; + } + /* Canonical name */ + nn = (EFNodeName *) HashGetValue(he); + subnode = nn->efnn_node; + if ( esFormat == SU ) { + if ( doAP ) { + if ( fetInfo[type].resClassSub < 0 ) { + TxError("Error: subap for devtype %d required but not " + "specified on command line\n", type); + fprintf(outf,"A_0,P_0,"); + } + else { + simnAP(subnode, fetInfo[type].resClassSub, scale, outf); + putc(',', outf); + } + } + fprintf(outf, "S_"); + } + EFHNOut(nn->efnn_node->efnode_name->efnn_hier, outf); + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * simnAP, simnAPHier -- + * + * Output the area perimeter of the node with type type if it has not + * been visited. + * The simnAPHier version outputs the area and perimeter only within the + * local subcell with hierarchical name hierName. + * + * Side effects: + * Set the visited flags so that the node A/P will not be output multiple + * times + * + * ---------------------------------------------------------------------------- + */ + +bool simnAP(node, resClass, scale, outf) +EFNode *node; +int resClass, scale; +FILE *outf; +{ + int a, p; + + if ( node->efnode_client == (ClientData) NULL ) + initNodeClient(node); + if ( resClass == NO_RESCLASS || + beenVisited((nodeClient *)node->efnode_client, resClass) ) { + fprintf(outf,"A_0,P_0"); + return FALSE; + } + markVisited((nodeClient *)node->efnode_client, resClass); + a = node->efnode_pa[resClass].pa_area*scale*scale; + p = node->efnode_pa[resClass].pa_perim*scale; + if ( a < 0 ) a = 0; + if ( p < 0 ) p = 0; + fprintf(outf,"A_%d,P_%d", a, p); + return TRUE; +} + +bool simnAPHier(dterm, hierName, resClass, scale, outf) + DevTerm *dterm; + HierName *hierName; + int resClass, scale; + FILE *outf; +{ + EFNode *node = dterm->dterm_node; + nodeClientHier *nc ; + int a, p; + + if ( node->efnode_client == (ClientData) NULL ) + initNodeClientHier(node); + nc = (nodeClientHier *)node->efnode_client; + if ( nc->lastPrefix != hierName ) { + nc->visitMask = 0; + nc->lastPrefix = hierName; + } + if ( resClass == NO_RESCLASS || + beenVisited((nodeClientHier *)node->efnode_client, resClass) ) { + fprintf(outf,"A_0,P_0"); + return FALSE; + } + markVisited((nodeClientHier *)node->efnode_client, resClass); + a = node->efnode_pa[resClass].pa_area*scale*scale; + p = node->efnode_pa[resClass].pa_perim*scale; + if ( a < 0 ) a = 0; + if ( p < 0 ) p = 0; + fprintf(outf,"A_%d,P_%d", a, p); + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * + * simdevOutNode -- + * + * Output the name of the node whose hierarchical prefix down to this + * point is 'prefix' and whose name from the end of suffix down to the + * leaves is 'suffix', just as in the arguments to EFHNConcat(). + * + * + * Results: + * None. + * + * Side effects: + * Writes to the file 'outf'. + * Sets the efnode_client field as described above. + * + * ---------------------------------------------------------------------------- + */ + +int +simdevOutNode(prefix, suffix, name, outf) + HierName *prefix; + HierName *suffix; + char *name; + FILE *outf; +{ + HashEntry *he; + EFNodeName *nn; + + he = EFHNConcatLook(prefix, suffix, name); + if (he == NULL) + { + fprintf(outf, " GND"); + return 0; + } + + /* Canonical name */ + nn = (EFNodeName *) HashGetValue(he); + (void) putc(' ', outf); + EFHNOut(nn->efnn_node->efnode_name->efnn_hier, outf); + if ( nn->efnn_node->efnode_client == (ClientData) NULL ) + initNodeClient(nn->efnn_node); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * simcapVisit -- + * + * Procedure to output a single capacitor to the .sim file. + * Called by EFVisitCaps(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the file esSimF. + * + * Format of a .sim cap line: + * + * C node1 node2 cap + * + * where + * node1, node2 are the terminals of the capacitor + * cap is the capacitance in femtofarads (NOT attofarads). + * + * ---------------------------------------------------------------------------- + */ + +int simcapVisit(hierName1, hierName2, cap) + HierName *hierName1; + HierName *hierName2; + double cap; +{ + cap = cap / 1000; + if (cap <= EFCapThreshold) + return 0; + + fprintf(esSimF, "C "); + EFHNOut(hierName1, esSimF); + fprintf(esSimF, " "); + EFHNOut(hierName2, esSimF); + fprintf(esSimF, esCapFormat, cap); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * simresistVisit -- + * + * Procedure to output a single resistor to the .sim file. + * Called by EFVisitResists(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the file esSimF. + * + * Format of a .sim resistor line: + * + * r node1 node2 res + * + * where + * node1, node2 are the terminals of the resistor + * res is the resistance in ohms (NOT milliohms) + * + * + * ---------------------------------------------------------------------------- + */ + +int +simresistVisit(hierName1, hierName2, res) + HierName *hierName1; + HierName *hierName2; + float res; +{ + fprintf(esSimF, "r "); + EFHNOut(hierName1, esSimF); + fprintf(esSimF, " "); + EFHNOut(hierName2, esSimF); + fprintf(esSimF, " %g\n", res / 1000.); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * simnodeVisit -- + * + * Procedure to output a single node to the .sim file, along with + * its aliases to the .al file and its location to the .nodes file. + * Called by EFVisitNodes(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the files esSimF, esAliasF, and esLabF. + * + * ---------------------------------------------------------------------------- + */ + +int simnodeVisit(node, res, cap) + EFNode *node; + int res; + double cap; +{ + EFNodeName *nn; + HierName *hierName; + bool isGlob; + char *fmt; + EFAttr *ap; + + if (esDevNodesOnly && node->efnode_client == (ClientData) NULL) + return 0; + + hierName = (HierName *) node->efnode_name->efnn_hier; + cap = cap / 1000; + res = (res + 500) / 1000; + if (cap > EFCapThreshold) + { + fprintf(esSimF, "C "); + EFHNOut(hierName, esSimF); + fprintf(esSimF, esCapFormat, cap); + } + if (res > EFResistThreshold) + { + fprintf(esSimF, "R "); + EFHNOut(hierName, esSimF); + fprintf(esSimF, " %d\n", res); + } + if (node->efnode_attrs && !esNoAttrs) + { + fprintf(esSimF, "A "); + EFHNOut(hierName, esSimF); + for (fmt = " %s", ap = node->efnode_attrs; ap; ap = ap->efa_next) + { + fprintf(esSimF, fmt, ap->efa_text); + fmt = ",%s"; + } + putc('\n', esSimF); + } + + if (esAliasF) + { + isGlob = EFHNIsGlob(hierName); + for (nn = node->efnode_name->efnn_next; nn; nn = nn->efnn_next) + { + if (isGlob && EFHNIsGlob(nn->efnn_hier)) + continue; + fprintf(esAliasF, "= "); + EFHNOut(hierName, esAliasF); + fprintf(esAliasF, " "); + EFHNOut(nn->efnn_hier, esAliasF); + fprintf(esAliasF, "\n"); + } + } + + if (esLabF) + { + fprintf(esLabF, "94 "); + EFHNOut(hierName, esLabF); + fprintf(esLabF, " %d %d %s;\n", + node->efnode_loc.r_xbot, node->efnode_loc.r_ybot, + EFLayerNames[node->efnode_type]); + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * simmkDevMerge -- + * Create a new devMerge structure. + * + * Results: + * Obvious + * + * Side effects: + * Allocates memory and sets the fields of the structure. + * + * ---------------------------------------------------------------------------- + */ +devMerge *simmkDevMerge(l, w, g, s, d, b, hn, dev) +int l, w; +EFNode *g, *s, *d, *b; +HierName *hn; +Dev *dev; +{ + devMerge *fp; + + fp = (devMerge *) mallocMagic((unsigned) (sizeof(devMerge))); + fp->l = l; fp->w = w; + fp->g = g; fp->s = s; + fp->d = d; fp->b = b; + fp->dev = dev; + fp->esFMIndex = esFMIndex; + fp->hierName = hn; + fp->next = NULL; + addDevMult(1.0); + + return fp; +} + +/* + * ---------------------------------------------------------------------------- + * + * parallelDevs -- + * Macro to look if two devs are in parallel + * + * Results: + * NOT_PARALLEL if not in parallel + * PARALLEL if s==s d==d and g==g and bulk=bulk + * FLIP_PARALLEL if s==d d==s --->>---------------- + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ +#define NOT_PARALLEL 0 +#define PARALLEL 1 +#define PARALLEL_R 2 + +#define parallelDevs(f1, f2) \ +( \ + ( (f1)->g == (f2)->g && (f1)->b == (f2)->b && (f1)->l == (f2)->l && \ + ( esMergeDevsA || (f1)->w == (f2)->w ) ) ? \ + ( ((f1)->d == (f2)->d && (f1)->s == (f2)->s ) ? \ + PARALLEL : \ + (((f1)->s == (f2)->d && (f1)->d == (f2)->s ) ? PARALLEL_R : NOT_PARALLEL) )\ + : NOT_PARALLEL \ +) + +/* + * ---------------------------------------------------------------------------- + * + * mergeAttr -- + * Macro to merge two attribute strings + * + * Results: + * The merged strings + * + * Side effects: + * Might allocate and free memory. + * + * ---------------------------------------------------------------------------- + */ +#define mergeAttr(a1, a2) { \ + if ( a1 == NULL ) a1 = a2 ; \ + else { \ + char *t; \ + int l1 = strlen(a1); \ + int l2 = strlen(a2); \ + t = (char *) mallocMagic((unsigned) (l1+l2)+1); \ + t = (char *) strcat(a1,a2); \ + freeMagic(a1); \ + a1 = t ; \ + } \ +} + + +/* + * ---------------------------------------------------------------------------- + * + * simmergeVisit -- + * Visits each dev throu EFVisitDevs and finds if it is in parallel with + * any previously visited dev. + * + * Results: + * 0 always to keep the caller going. + * + * Side effects: + * Numerous. + * + * ---------------------------------------------------------------------------- + */ +int +simmergeVisit(dev, hierName, scale, trans) +Dev *dev; /* Dev to examine */ +HierName *hierName; /* Hierarchical path down to this dev */ +float scale; /* Scale transform */ +Transform *trans; /* Coordinate transform (not used) */ +{ + DevTerm *gate, *source, *drain; + Dev *cf; + DevTerm *cg, *cs, *cd; + EFNode *subnode, *snode, *dnode, *gnode; + int pmode, l, w; + float m; + devMerge *fp, *cfp; + + if (dev->dev_nterm < 2) { + TxError("outPremature\n"); + return 0; + } + + gate = &dev->dev_terms[0]; + source = drain = &dev->dev_terms[1]; + if (dev->dev_nterm >= 3) + drain = &dev->dev_terms[2]; + subnode = dev->dev_subsnode; + + gnode = SimGetNode (hierName, gate->dterm_node->efnode_name->efnn_hier); + snode = SimGetNode (hierName, source->dterm_node->efnode_name->efnn_hier); + dnode = SimGetNode (hierName, drain->dterm_node->efnode_name->efnn_hier); + + EFGetLengthAndWidth(dev, &l, &w); + fp = simmkDevMerge((int)(l*scale), (int)(w*scale), gnode, snode, + dnode, subnode, hierName, dev); + + /* + * run the list of devs. compare the current one with + * each one in the list. if they fullfill the matching requirements + * merge them. + */ + + for ( cfp = devMergeList ; cfp != NULL ; cfp = cfp->next ) { + if ((pmode = parallelDevs(fp, cfp)) != NOT_PARALLEL) { + + cf = cfp->dev; + cg = &cfp->dev->dev_terms[0]; + cs = cd = &cfp->dev->dev_terms[1]; + if (cfp->dev->dev_nterm >= 3) { + if ( pmode == PARALLEL ) + cd = &cfp->dev->dev_terms[2]; + else if ( pmode == PARALLEL_R ) + cs = &cfp->dev->dev_terms[2]; + } + + m = esFMult[cfp->esFMIndex] + ((float)fp->w/(float)cfp->w); + setDevMult(fp->esFMIndex, DEV_KILLED); + setDevMult(cfp->esFMIndex, m); + esDevsMerged++; + freeMagic(fp); + return 0; + } + } + /* No parallel devs to it yet */ + fp->next = devMergeList; + devMergeList = fp; + return 0; +} + diff --git a/ext2sim/finds.c b/ext2sim/finds.c new file mode 100644 index 00000000..382ed4a3 --- /dev/null +++ b/ext2sim/finds.c @@ -0,0 +1,97 @@ +#include "utils/magic.h" +#include "utils/hash.h" +#include +#include + +char * +token(pnext) + char **pnext; +{ + char *cp, *ep; + + cp = *pnext; + while (*cp && isspace(*cp)) cp++; + if (*cp == '\0') + return (NULL); + + for (ep = cp; *ep && !isspace(*ep); ep++) /* Nothing */; + if (*ep) + *ep++ = '\0'; + *pnext = ep; + return (cp); +} + +/* + * Match the last len characters of cp against name. + * Returns 1 on success, 0 on failure. + */ +endmatch(name, len, cp) + char *name, *cp; + int len; +{ + char *ep; + + ep = cp; + while (*ep++) /* Nothing */; + ep -= (len + 1); + if (ep < cp) + return (0); + + while (*name++ == *ep) + if (*ep++ == '\0') + return (1); + + return (0); +} + +main(argc, argv) + int argc; + char *argv[]; +{ + char line[1024], *name, *cp, *next; + HashTable ht; + HashSearch hs; + HashEntry *he; + int len; + + if (argc != 2) + { + printf("Usage: %s name\n", argv[0]); + exit (1); + } + + name = argv[1]; + len = strlen(name); + HashInit(&ht, 32, 0); + while (fgets(line, sizeof line, stdin)) + { + for (next = line, cp = token(&next); cp; cp = token(&next)) + if (endmatch(name, len, cp)) + (void) HashFind(&ht, cp); + } + + HashStartSearch(&hs); + while (he = HashNext(&ht, &hs)) + printf("%s\n", he->h_key.h_name); +} + +char * +TxGetLine(line, len) + char *line; + int len; +{ + return (fgets(line, len, stdin)); +} + +TxError(s, a) + char *s; +{ + vfprintf(stdout, s, &a); + fflush(stdout); +} + +MainExit(code) + int code; +{ + exit(code); +} diff --git a/ext2sim/sim2simp.c b/ext2sim/sim2simp.c new file mode 100644 index 00000000..fd11f843 --- /dev/null +++ b/ext2sim/sim2simp.c @@ -0,0 +1,156 @@ +/* no comments are provided - the code is self explanatory :-) */ +#include +#include +#include +#include + +#define STRLEN 1024 +#define NSIZE 100000 + + + +typedef struct { + char typ; + char *g, *s, *d ; + float l, w; + char *ga ; + int x, y, as, ps, ad, pd; +} MOS ; + +MOS mosFets[NSIZE]; +int par = 0, ndx = 0; + + +char *strsave(s) +char *s; +{ + char *p ; + + p = (char *) malloc(strlen(s)+1); + strcpy(p,s); + return p; +} + +int parseAttr(str, a, p) +char *str; +int *a, *p; +{ + int l; + char *s; + + if ( (l=strlen(str)) <= 2 ) { + *a = 0 ; *p = 0; + return; + } + + for ( s = str+l*sizeof(char) ; *s != 'A' && *s != 'a' && s != str ; s-- ) ; + if ( sscanf(s,"A_%d,P_%d", a, p ) != 2) + if ( sscanf(s,"a_%d,p_%d", a, p ) != 2 ) + if ( sscanf(s,"A_%d,p_%d", a, p ) != 2 ) + if ( sscanf(s,"a_%d,P_%d", a, p ) != 2 ) + fprintf(stderr,"Weird attributes output will be incorect\n"); +} + +void addMos( typ, g, s, d, l, w, x, y, ga, sa, da) +char *typ, *g, *s, *d, *l, *w, *x, *y, *ga, *sa, *da; +{ + int i ; + MOS *iptr; + float ln, wn ; + int as, ps, ad, pd; + + ln = (float) atof(l); wn = (float) atof(w); + if ( ga == NULL ) + as = ps = ad = pd = 0 ; + else { + parseAttr(sa, &as, &ps); + parseAttr(da, &ad, &pd); + } + for ( i = 0 ; i < ndx ; i ++ ) { + iptr = mosFets + i ; + if ( iptr->typ == *typ && iptr->l == ln + && ! strcmp(iptr->g, g) + && ( ! strcmp(iptr->s, s) && ! strcmp(iptr->d, d) ) + ) { + iptr->w += wn; + iptr->as += as ; iptr->ps += ps ; + iptr->ad += ad ; iptr->pd += pd ; + par ++; + return; + } + if ( iptr->typ == *typ && iptr->l == ln + && ! strcmp(iptr->g, g) + && ( ! strcmp(iptr->s, d) && ! strcmp(iptr->d, s) )) { + iptr->w += wn; + iptr->as += ad ; iptr->ps += pd ; + iptr->ad += as ; iptr->pd += ps ; + par ++; + return; + } + } + + iptr = mosFets + ndx ; + iptr->typ = *typ; + iptr->g = strsave(g); iptr->s = strsave(s); iptr->d = strsave(d); + iptr->l = ln ; iptr->w = wn; + if ( x != NULL ) { + iptr->x = (int) atoi(x); + iptr->y = (int) atoi(y); + iptr->as = as ; iptr->ps = ps ; + iptr->ad = ad ; iptr->pd = pd ; + if (ga ) iptr->ga = strsave(ga); else iptr->ga = NULL; + } + if ( ++ ndx >= NSIZE ) { + fprintf(stderr, "Mos max cound %d exceeded\n", NSIZE); + exit(1); + } +} + + +main () +{ + int i; + char str[STRLEN]; + char *typ, *g, *s, *d, *l, *w, *x, *y, *ga, *sa, *da; + + + while (fgets (str, STRLEN - 1, stdin)) { + if ( *str == 'p' || *str == 'n' || + *str == 'e' || *str == 'd' ) { + typ = strtok(str, " "); + g = strtok(NULL, " "); + s = strtok(NULL, " "); + d = strtok(NULL, " "); + l = strtok(NULL, " "); + w = strtok(NULL, " "); + x = strtok(NULL, " "); + y = strtok(NULL, " "); + if ( y == NULL ) { + ga = sa = da = NULL ; + } else { + ga = strtok(NULL, " "); + sa = strtok(NULL, " "); + da = strtok(NULL, " "); + } + addMos(typ, g, s, d, l, w, x, y, ga, sa, da); + } + else puts(str); + } + fprintf(stderr,"| %d parallel devices\n", par); + for ( i = 0 ; i < ndx ; i ++ ) + /*if ( mosFets[i].ga )*/ + if (1) + printf("%c %s %s %s %g %g %d %d %s s=A_%d,P_%d d=A_%d,P_%d\n", + mosFets[i].typ, mosFets[i].g, mosFets[i].s, + mosFets[i].d, mosFets[i].l, mosFets[i].w, + mosFets[i].x, mosFets[i].y,mosFets[i].ga, + mosFets[i].as,mosFets[i].ps, + mosFets[i].ad,mosFets[i].pd); + else + printf("%c %s %s %s %g %g %d %d\n", + mosFets[i].typ, mosFets[i].g, mosFets[i].s, + mosFets[i].d, mosFets[i].l, mosFets[i].w, + mosFets[i].x, mosFets[i].y); + exit (0); +} + diff --git a/ext2sim/sim2spi b/ext2sim/sim2spi new file mode 100755 index 00000000..8396f74f --- /dev/null +++ b/ext2sim/sim2spi @@ -0,0 +1,88 @@ +#!/usr/bin/nawk -f +# awk script to replace sim2spice! +# Drew Wingard June, 1988 +# modified by Peter Lim and Stefanos Sidiropoulos +# +# The awk script allows spice simulation of layout from Stanford BiCMOS +# Technology. To use this awk script, +# 1. generate a .ext file from magic using ":ext" +# 2. run ext2sim to generate .sim file +# 3. use sim2spi .sim > .spi to generate a spice deck. +# 4. edit the generate spice deck as needed +# +# In order to recognize bipolars the ext2simBiCMOS program should be used +# (this is no longer true --- Tim 10/10/97 +# (modified by Tim Edwards for bipolar handling w/magic 6.5.1) +# +# Areas and perimeters are calculated if the right ext2sim version is used +BEGIN{ + trimSubs = 1; + cnum = 1 ; bnum = 1 ; num = 1 ; + rnum = 1 ; xnum = 1; lumpResnum = 1 ; + print "* Extracted spice deck" ; + print "* for su-bicmos you should get the .sim file using ext2simBiCMOS" + units = 1.0 ; # in microns +} +$1 == "|" { + if ( $2 == "units:" ) units = $3 / 100 ; + printf "* Units: %f, Technology: %s\n", units, $5; + } +$1 ~ /^\|$/ { scale = 1 } +$1 ~ /^[Cc]$/ { print "C"cnum , $2 , $3 , $4"fF" ; cnum = cnum + 1} +$1 ~ /^p$/ { + subs = "Vdd" + if ( NF > 8 ) { + n = split($9, arr, "[=,]" ); + subs = substr(arr[n],3,length(arr[n])); + if ( trimSubs ) { + l = length(subs); + if ( substr(subs,l,1) == "!" ) + subs = substr(subs,1,l-1); + } + n = split($10, arr, "[=_,]"); + ps = arr[n]; + as = arr[n-2]; + n = split($11, arr, "[=_,]"); + pd = arr[n]; + ad = arr[n-2]; + } + print "M"num , $4 , $2 , $3 , subs, " PMOS W=" $6*units \ + "U L=" $5*units "U " + print "+ AD=" ad*units*units"P PD=" pd*units"U"\ + " AS=" as*units*units"P PS=" ps*units"U" + num = num + 1} +$1 ~ /^w$/ { + printf "Xcap%d %s %s wcap w=%fu l=%fu\n", xnum, $2, $3, \ + $5*units, $6*units; + xnum = xnum + 1; + } +$1 ~ /^n$/ { + subs = "Gnd" + if ( NF > 8 ) { + n = split($9, arr, "[=,]" ); + subs = substr(arr[n],3,length(arr[n])); + if ( trimSubs ) { + l = length(subs); + if ( substr(subs,l,1) == "!" ) + subs = substr(subs,1,l-1); + } + n = split($10, arr, "[=_,]"); + ps = arr[n]; + as = arr[n-2]; + n = split($11, arr, "[=_,]"); + pd = arr[n]; + ad = arr[n-2]; + } + print "M"num , $4 , $2 , $3 , subs, " NMOS W=" $6*units \ + "U L=" $5*units "U " + print "+ AD=" ad*units*units"P PD=" pd*units"U"\ + " AS=" as*units*units"P PS=" ps*units"U" + num = num + 1} + +$1 ~ /^b$/ { print "Q"bnum , $3 , $4 , $2 " npn" + bnum = bnum + 1} +$1 ~ /^q$/ { print "Q"bnum , $4 , $2 , $3 " 0 b1.6 " $6 - 1.6 + bnum = bnum + 1} +$1 ~ /^r$/ { print "r"rnum , $2 , $3 , $4 + rnum = rnum + 1} +$1 ~ /^R$/ { printf "ERROR: %s (lumped resistor not supported)\n", $0; } diff --git a/ext2spice/Depend b/ext2spice/Depend new file mode 100644 index 00000000..d1d5f932 --- /dev/null +++ b/ext2spice/Depend @@ -0,0 +1,14 @@ +ext2spice.o: ext2spice.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/malloc.h ../utils/geometry.h ../utils/hash.h ../utils/dqueue.h \ + ../utils/utils.h ../tiles/tile.h ../database/database.h \ + ../windows/windows.h ../textio/textio.h ../dbwind/dbwind.h \ + ../commands/commands.h ../textio/txcommands.h ../extflat/extflat.h \ + ../extflat/EFint.h ../extract/extract.h ../utils/runstats.h \ + ../ext2spice/ext2spice.h +ext2hier.o: ext2hier.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/malloc.h ../utils/geometry.h ../utils/hash.h ../utils/dqueue.h \ + ../utils/utils.h ../tiles/tile.h ../database/database.h \ + ../windows/windows.h ../textio/textio.h ../dbwind/dbwind.h \ + ../commands/commands.h ../textio/txcommands.h ../extflat/extflat.h \ + ../extflat/EFint.h ../extract/extract.h ../utils/runstats.h \ + ../ext2spice/ext2spice.h diff --git a/ext2spice/Makefile b/ext2spice/Makefile new file mode 100644 index 00000000..3a7b7e96 --- /dev/null +++ b/ext2spice/Makefile @@ -0,0 +1,44 @@ +# +# rcsid "$Header: /usr/cvsroot/magic-8.0/ext2spice/Makefile,v 1.2 2010/08/10 00:18:45 tim Exp $" +# + +MODULE = ext2spice +MAGICDIR = .. +SRCS = ext2spice.c ext2hier.c + +EXTRA_LIBS = ${MAGICDIR}/extflat/libextflat.o ${MAGICDIR}/utils/libutils.a + +include ${MAGICDIR}/defs.mak + +LIBS += -lm ${LD_EXTRA_LIBS} ${SUB_EXTRA_LIBS} +CLEANS += exttospice${SHDLIB_EXT} spicewrap.o spicehier.o + +main: ext2spice + +tcl-main: exttospice${SHDLIB_EXT} + +spicewrap.o: ext2spice.c ext2spice.h + ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ext2spice.c -c -o spicewrap.o + +spicehier.o: ext2hier.c ext2spice.h + ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ext2hier.c -c -o spicehier.o + +exttospice${SHDLIB_EXT}: spicewrap.o spicehier.o ${MAGICDIR}/extflat/libextflat.o + @echo --- making exttospice Tcl library \(exttospice${SHDLIB_EXT}\) + ${RM} exttospice${SHDLIB_EXT} + ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} spicewrap.o spicehier.o \ + ${MAGICDIR}/extflat/libextflat.o ${LD_SHARED} -lc ${LIBS} + +install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${BINDIR}/spice2sim + +install-tcl: $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT} $(DESTDIR)${BINDIR}/spice2sim + +$(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT}: exttospice${SHDLIB_EXT} + ${RM} $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT} + ${CP} exttospice${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT} + +$(DESTDIR)${BINDIR}/spice2sim: spice2sim + ${RM} $(DESTDIR)${BINDIR}/spice2sim + ${CP} spice2sim $(DESTDIR)${BINDIR}/spice2sim + +include ${MAGICDIR}/rules.mak diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c new file mode 100644 index 00000000..cf7a1f48 --- /dev/null +++ b/ext2spice/ext2hier.c @@ -0,0 +1,1830 @@ +/* + * ext2hier.c -- + * + * Program to convert hierarchical .ext files into a single + * hierarchical .spice file, suitable for use as input to a + * hierarchy-capable LVS (layout vs. schematic) tool such as + * netgen. + * + * Generates the tree rooted at file.ext, reading in additional .ext + * files as specified by "use" lines in file.ext. The output is left + * in file.spice, unless '-o esSpiceFile' is specified, in which case the + * output is left in 'esSpiceFile'. + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ext2spice/ext2hier.c,v 1.5 2010/12/16 18:59:03 tim Exp $"; +#endif /* not lint */ + +#include +#include /* for atof() */ +#include +#include +#include /* for fabs() */ + +#ifdef MAGIC_WRAPPER +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/dqueue.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "textio/textio.h" +#include "dbwind/dbwind.h" /* for DBWclientID */ +#include "commands/commands.h" /* for module auto-load */ +#include "textio/txcommands.h" +#include "extflat/extflat.h" +#include "extflat/EFint.h" +#include "extract/extract.h" /* for extDevTable */ +#include "utils/runstats.h" +#include "ext2spice/ext2spice.h" + +// Structure passed to esHierVisit + +typedef struct _defflagsdata { + Def *def; + int flags; +} DefFlagsData; + +/* + * ---------------------------------------------------------------------------- + * + * ESGenerateHierarchy --- + * + * Generate hierarchical SPICE output + * + * ---------------------------------------------------------------------------- + */ + +void +ESGenerateHierarchy(inName, flags) + char *inName; + int flags; +{ + int esHierVisit(), esMakePorts(); /* Forward declaration */ + Use u; + Def *def; + HierContext hc; + DefFlagsData dfd; + + u.use_def = efDefLook(inName); + hc.hc_use = &u; + hc.hc_hierName = NULL; + hc.hc_trans = GeoIdentityTransform; + hc.hc_x = hc.hc_y = 0; + EFHierSrDefs(&hc, esMakePorts, NULL); + EFHierSrDefs(&hc, NULL, NULL); /* Clear processed */ + + dfd.def = u.use_def; + dfd.flags = flags; + EFHierSrDefs(&hc, esHierVisit, (ClientData)(&dfd)); + EFHierSrDefs(&hc, NULL, NULL); /* Clear processed */ + + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * GetHierNode -- + * + * function to find a node structure given its name + * + * Results: + * a pointer to the node struct or NULL + * + * ---------------------------------------------------------------------------- + */ + +EFNode * +GetHierNode(hc, name) + HierContext *hc; + HierName *name; +{ + HashEntry *he; + EFNodeName *nn; + Def *def = hc->hc_use->use_def; + + he = EFHNConcatLook(hc->hc_hierName, name, "node"); + if (he == NULL) return NULL; + nn = (EFNodeName *) HashGetValue(he); + if (nn == NULL) return NULL; + return(nn->efnn_node); +} + + +/* + * ---------------------------------------------------------------------------- + * + * spcHierWriteParams --- + * + * Write parameters to a device line in SPICE output. This is normally + * restricted to subcircuit devices but may include other devices to + * accomodate various extensions to the basic SPICE format. + * ---------------------------------------------------------------------------- + */ + +void +spcHierWriteParams(hc, dev, scale, l, w, sdM) + HierContext *hc; + Dev *dev; /* Dev being output */ + float scale; /* Scale transform for output */ + int l; /* Device length, in internal units */ + int w; /* Device width, in internal units */ + float sdM; /* Device multiplier */ +{ + bool hierD; + DevParam *plist; + int parmval; + EFNode *dnode, *subnodeFlat = NULL; + + /* Write all requested parameters to the subcircuit call. */ + + plist = efGetDeviceParams(EFDevTypes[dev->dev_type]); + while (plist != NULL) + { + switch (plist->parm_type[0]) + { + case 'a': + // Check for area of terminal node vs. device area + if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0') + { + fprintf(esSpiceF, " %s=", plist->parm_name); + parmval = dev->dev_area; + if (esScale < 0) + fprintf(esSpiceF, "%g", parmval * scale * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", parmval * scale * scale + * esScale * esScale * plist->parm_scale + * 1E-12); + else + fprintf(esSpiceF, "%gp", parmval * scale * scale + * esScale * esScale); + } + else + { + int pn; + pn = plist->parm_type[1] - '0'; + if (pn >= dev->dev_nterm) pn = dev->dev_nterm - 1; + + dnode = GetHierNode(hc, + dev->dev_terms[pn].dterm_node->efnode_name->efnn_hier); + + // For parameter an followed by parameter pn, + // process both at the same time + + if (plist->parm_next && plist->parm_next->parm_type[0] == + 'p' && plist->parm_next->parm_type[1] == + plist->parm_type[1]) + { + spcnAP(dnode, esFetInfo[dev->dev_type].resClassSD, + scale, plist->parm_name, + plist->parm_next->parm_name, sdM, + esSpiceF, w); + plist = plist->parm_next; + } + else + { + spcnAP(dnode, esFetInfo[dev->dev_type].resClassSD, + scale, plist->parm_name, NULL, sdM, + esSpiceF, w); + } + } + + break; + case 'p': + // Check for perimeter of terminal node vs. device perimeter + if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0') + { + fprintf(esSpiceF, " %s=", plist->parm_name); + parmval = dev->dev_perim; + + if (esScale < 0) + fprintf(esSpiceF, "%g", parmval * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", parmval * scale + * esScale * plist->parm_scale * 1E-6); + else + fprintf(esSpiceF, "%gu", parmval * scale * esScale); + } + else + { + int pn; + pn = plist->parm_type[1] - '0'; + if (pn >= dev->dev_nterm) pn = dev->dev_nterm - 1; + + dnode = GetHierNode(hc, + dev->dev_terms[pn].dterm_node->efnode_name->efnn_hier); + + // For parameter pn followed by parameter an, + // process both at the same time + + if (plist->parm_next && plist->parm_next->parm_type[0] == + 'a' && plist->parm_next->parm_type[1] == + plist->parm_type[1]) + { + spcnAP(dnode, esFetInfo[dev->dev_type].resClassSD, + scale, plist->parm_next->parm_name, + plist->parm_name, sdM, esSpiceF, w); + plist = plist->parm_next; + } + else + { + spcnAP(dnode, esFetInfo[dev->dev_type].resClassSD, + scale, NULL, plist->parm_name, sdM, + esSpiceF, w); + } + } + + break; + case 'l': + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", l * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", l * scale * esScale + * plist->parm_scale * 1E-6); + else + fprintf(esSpiceF, "%gu", l * scale * esScale); + break; + case 'w': + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", w * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", w * scale * esScale + * plist->parm_scale * 1E-6); + else + fprintf(esSpiceF, "%gu", w * scale * esScale); + break; + case 's': + fprintf(esSpiceF, " %s=", plist->parm_name); + subnodeFlat = spcdevSubstrate(hc->hc_hierName, + dev->dev_subsnode->efnode_name->efnn_hier, + dev->dev_type, esSpiceF); + break; + case 'x': + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", dev->dev_rect.r_xbot * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", dev->dev_rect.r_xbot * scale + * esScale * plist->parm_scale * 1E-6); + else + fprintf(esSpiceF, "%gu", dev->dev_rect.r_xbot * scale + * esScale); + break; + case 'y': + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", dev->dev_rect.r_ybot * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", dev->dev_rect.r_ybot * scale + * esScale * plist->parm_scale * 1E-6); + else + fprintf(esSpiceF, "%gu", dev->dev_rect.r_ybot * scale + * esScale); + break; + case 'r': + fprintf(esSpiceF, " %s=", plist->parm_name); + fprintf(esSpiceF, "%f", (double)(dev->dev_res)); + break; + case 'c': + fprintf(esSpiceF, " %s=", plist->parm_name); + fprintf(esSpiceF, "%ff", (double)(dev->dev_cap)); + break; + } + plist = plist->parm_next; + } + + /* Add parameters that are to be copied verbatim */ + for (plist = dev->dev_params; plist; plist = plist->parm_next) + fprintf(esSpiceF, " %s", plist->parm_name); +} + +/* + * ---------------------------------------------------------------------------- + * + * esOutputHierResistor --- + * + * Routine used by spcdevHierVisit to print a resistor device. This + * is broken out into a separate routine so that each resistor + * device may be represented (if the option is selected) by a + * "tee" network of two resistors on either side of the central + * node, which then has a capacitance to ground. + * + * Results: + * None. + * + * Side effects: + * Output to the SPICE deck. + * + * ---------------------------------------------------------------------------- + */ + +void +esOutputHierResistor(hc, dev, scale, term1, term2, has_model, l, w, dscale) + HierContext *hc; + Dev *dev; /* Dev being output */ + float scale; /* Scale transform for output */ + DevTerm *term1, *term2; /* Terminals of the device */ + bool has_model; /* Is this a modeled resistor? */ + int l, w; /* Device length and width */ + int dscale; /* Device scaling (for split resistors) */ +{ + Rect r; + float sdM ; + char name[12], devchar; + + /* Resistor is "Rnnn term1 term2 value" */ + /* extraction sets two terminals, which are assigned */ + /* term1=gate term2=source by the above code. */ + /* extracted units are Ohms; output is in Ohms */ + + spcdevOutNode(hc->hc_hierName, term1->dterm_node->efnode_name->efnn_hier, + "res_top", esSpiceF); + spcdevOutNode(hc->hc_hierName, term2->dterm_node->efnode_name->efnn_hier, + "res_bot", esSpiceF); + + sdM = getCurDevMult(); + + /* SPICE has two resistor types. If the "name" (EFDevTypes) is */ + /* "None", the simple resistor type is used, and a value given. */ + /* If not, the "semiconductor resistor" is used, and L and W */ + /* and the device name are output. */ + + if (!has_model) + { + fprintf(esSpiceF, " %f", ((double)(dev->dev_res) + / (double)(dscale)) / (double)sdM); + spcHierWriteParams(hc, dev, scale, l, w, sdM); + } + else + { + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + if (esScale < 0) + { + fprintf(esSpiceF, " w=%d l=%d", (int)((float)w * scale), + (int)(((float)l * scale) / (float)dscale)); + } + else + { + fprintf(esSpiceF, " w=%gu l=%gu", + (float)w * scale * esScale, + (float)((l * scale * esScale) / dscale)); + } + spcHierWriteParams(hc, dev, scale, l, w, sdM); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + } +} + +/* + * ---------------------------------------------------------------------------- + * ---------------------------------------------------------------------------- + * + */ + +int +subcktHierVisit(use, hierName, is_top) + Use *use; + HierName *hierName; + bool is_top; /* TRUE if this is the top-level cell */ +{ + Def *def = use->use_def; + EFNode *snode; + bool hasports = FALSE; + + /* Avoid generating records for circuits that have no ports. */ + /* These are already absorbed into the parent. All other */ + /* subcircuits have at least one port marked by the EF_PORT flag. */ + + for (snode = (EFNode *) def->def_firstn.efnode_next; + snode != &def->def_firstn; + snode = (EFNode *) snode->efnode_next) + if (snode->efnode_flags & (EF_PORT | EF_SUBS_PORT)) + { + hasports = TRUE; + break; + } + + if (hasports || is_top) + return subcktVisit(use, hierName, is_top); + else if (def->def_flags & DEF_NODEVICES) + return 0; + else + return subcktVisit(use, hierName, is_top); +} + +/* + * ---------------------------------------------------------------------------- + * + * spcdevHierVisit -- + * + * Procedure to output a single dev to the .spice file. + * Called by EFHierVisitDevs(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the file esSpiceF. + * + * Format of a .spice dev line: + * + * M%d drain gate source substrate type w=w l=l * x y + * + ad= pd= as= ps= * asub= psub= + * **devattr g= s= d= + * + * where + * type is a name identifying this type of transistor + * other types of transistors are extracted with + * an M card but it should be easy to turn them to whatever + * you want. + * gate, source, and drain are the nodes to which these three + * terminals connect + * l, w are the length and width of the channel + * x, y are the x, y coordinates of a point within the channel. + * g=, s=, d= are the (optional) attributes; if present, each + * is followed by a comma-separated list of attributes. + * + * ---------------------------------------------------------------------------- + */ + +int +spcdevHierVisit(hc, dev, scale) + HierContext *hc; + Dev *dev; /* Dev being output */ + float scale; /* Scale transform for output */ +{ + DevParam *plist, *pptr; + DevTerm *gate, *source, *drain; + EFNode *subnode, *snode, *dnode, *subnodeFlat = NULL; + int l, w, i, parmval; + Rect r; + bool subAP= FALSE, hierS, hierD, extHierSDAttr() ; + float sdM; + char devchar; + bool has_model = TRUE; + + /* If no terminals, or only a gate, can't do much of anything */ + if (dev->dev_nterm <= 1 ) + return 0; + + if ( (esMergeDevsA || esMergeDevsC) && devIsKilled(esFMIndex++) ) + return 0; + + /* Get L and W of device */ + EFGetLengthAndWidth(dev, &l, &w); + + /* If only two terminals, connect the source to the drain */ + gate = &dev->dev_terms[0]; + source = drain = (DevTerm *)NULL; + if (dev->dev_nterm >= 2) + source = drain = &dev->dev_terms[1]; + if (dev->dev_nterm >= 3) + { + /* If any terminal is marked with attribute "D" or "S" */ + /* (label "D$" or "S$" at poly-diffusion interface), */ + /* then force order of source and drain accordingly. */ + + if ((dev->dev_terms[1].dterm_attrs && + !strcmp(dev->dev_terms[1].dterm_attrs, "D")) || + (dev->dev_terms[2].dterm_attrs && + !strcmp(dev->dev_terms[2].dterm_attrs, "S"))) + { + drain = &dev->dev_terms[1]; + source = &dev->dev_terms[2]; + } + else + drain = &dev->dev_terms[2]; + } + else if (dev->dev_nterm == 1) // Is a device with one terminal an error? + source = drain = &dev->dev_terms[0]; + subnode = dev->dev_subsnode; + + /* Original hack for BiCMOS, Tim 10/4/97, is deprecated. */ + /* Use of "device bjt" preferred to "fet" with model="npn". */ + + if (!strcmp(EFDevTypes[dev->dev_type], "npn")) dev->dev_class = DEV_BJT; + + /* For resistor and capacitor classes, set a boolean to */ + /* denote whether the device has a model or not, so we */ + /* don't have to keep doing a string compare on EFDevTypes. */ + + switch(dev->dev_class) + { + case DEV_RES: + case DEV_CAP: + case DEV_CAPREV: + if (dev->dev_type == esNoModelType) + has_model = FALSE; + break; + } + + /* Flag shorted devices---this should probably be an option */ + switch(dev->dev_class) + { + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_FET: + if (source == drain) + { + if (esFormat == NGSPICE) fprintf(esSpiceF, "; "); + fprintf(esSpiceF, "** SOURCE/DRAIN TIED\n"); + } + break; + + default: + if (gate == source) + { + if (esFormat == NGSPICE) fprintf(esSpiceF, "; "); + fprintf(esSpiceF, "** SHORTED DEVICE\n"); + } + break; + } + + /* Generate SPICE device name */ + switch(dev->dev_class) + { + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_FET: + devchar = 'M'; + break; + case DEV_BJT: + devchar = 'Q'; + break; + case DEV_DIODE: + case DEV_NDIODE: + case DEV_PDIODE: + devchar = 'D'; + break; + case DEV_RES: + devchar = 'R'; + break; + case DEV_CAP: + case DEV_CAPREV: + devchar = 'C'; + break; + case DEV_SUBCKT: + case DEV_RSUBCKT: + case DEV_MSUBCKT: + devchar = 'X'; + break; + } + fprintf(esSpiceF, "%c", devchar); + + /* Device index is taken from gate attributes if attached; */ + /* otherwise, the device is numbered in sequence. */ + + if (gate->dterm_attrs) + fprintf(esSpiceF, "%s", gate->dterm_attrs); + else + { + switch (dev->dev_class) + { + case DEV_RES: + fprintf(esSpiceF, "%d", esResNum++); + /* For resistor tee networks, use, e.g., */ + /* "R1A" and "R1B", for clarity */ + if (esDoResistorTee) fprintf(esSpiceF, "A"); + break; + case DEV_DIODE: + case DEV_NDIODE: + case DEV_PDIODE: + fprintf(esSpiceF, "%d", esDiodeNum++); + break; + case DEV_CAP: + case DEV_CAPREV: + fprintf(esSpiceF, "%d", esCapNum++); + break; + case DEV_SUBCKT: + case DEV_RSUBCKT: + case DEV_MSUBCKT: + fprintf(esSpiceF, "%d", esSbckNum++); + break; + default: + fprintf(esSpiceF, "%d", esDevNum++); + break; + } + } + /* Order and number of nodes in the output depends on the device class */ + + switch (dev->dev_class) + { + case DEV_BJT: + if (source == NULL) break; + + /* BJT is "Qnnn collector emitter base model" */ + /* extraction sets collector=subnode, emitter=gate, base=drain */ + + spcdevOutNode(hc->hc_hierName, subnode->efnode_name->efnn_hier, + "collector", esSpiceF); + spcdevOutNode(hc->hc_hierName, gate->dterm_node->efnode_name->efnn_hier, + "emitter", esSpiceF); + + /* fix mixed up drain/source for bjts hace 2/2/99 */ + if (gate->dterm_node->efnode_name->efnn_hier == + source->dterm_node->efnode_name->efnn_hier) + spcdevOutNode(hc->hc_hierName, + drain->dterm_node->efnode_name->efnn_hier, + "base", esSpiceF); + else + spcdevOutNode(hc->hc_hierName, + source->dterm_node->efnode_name->efnn_hier, + "base", esSpiceF); + + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + spcHierWriteParams(hc, dev, scale, l, w, sdM); + break; + + case DEV_MSUBCKT: + /* msubcircuit is "Xnnn source gate [drain [sub]]]" */ + /* to more conveniently handle situations where MOSFETs */ + /* are modeled by subcircuits with the same pin ordering. */ + + spcdevOutNode(hc->hc_hierName, + source->dterm_node->efnode_name->efnn_hier, + "subckt", esSpiceF); + + /* Drop through to below (no break statement) */ + + case DEV_SUBCKT: + + /* Subcircuit is "Xnnn gate [source [drain [sub]]]" */ + /* Subcircuit .subckt record must be ordered to match! */ + + spcdevOutNode(hc->hc_hierName, + gate->dterm_node->efnode_name->efnn_hier, + "subckt", esSpiceF); + + /* Drop through to below (no break statement) */ + + case DEV_RSUBCKT: + /* RC-like subcircuits are exactly like other subcircuits */ + /* except that the "gate" node is treated as an identifier */ + /* only and is not output. */ + + if ((dev->dev_nterm > 1) && (dev->dev_class != DEV_MSUBCKT)) + spcdevOutNode(hc->hc_hierName, + source->dterm_node->efnode_name->efnn_hier, + "subckt", esSpiceF); + if (dev->dev_nterm > 2) + spcdevOutNode(hc->hc_hierName, + drain->dterm_node->efnode_name->efnn_hier, + "subckt", esSpiceF); + + /* The following only applies to DEV_SUBCKT*, which may define as */ + /* many terminal types as it wants. */ + + for (i = 4; i < dev->dev_nterm; i++) + { + drain = &dev->dev_terms[i - 1]; + spcdevOutNode(hc->hc_hierName, + drain->dterm_node->efnode_name->efnn_hier, + "subckt", esSpiceF); + } + + /* Get the device parameters now, and check if the substrate is */ + /* passed as a parameter rather than as a node. */ + + plist = efGetDeviceParams(EFDevTypes[dev->dev_type]); + for (pptr = plist; pptr != NULL; pptr = pptr->parm_next) + if (pptr->parm_type[0] == 's') + break; + + if ((pptr == NULL) && subnode) + { + fprintf(esSpiceF, " "); + subnodeFlat = spcdevSubstrate(hc->hc_hierName, + subnode->efnode_name->efnn_hier, + dev->dev_type, esSpiceF); + } + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + /* Write all requested parameters to the subcircuit call. */ + sdM = getCurDevMult(); + spcHierWriteParams(hc, dev, scale, l, w, sdM); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + break; + + case DEV_RES: + if (esDoResistorTee) + { + /* There are three ways of handling capacitance */ + /* on resistor networks. One is to ignore it */ + /* (the default; generates "floating" nodes in */ + /* the SPICE output) which is okay for LVS. */ + /* Another way is the Pi network, in which the */ + /* capacitance is split evenly between the */ + /* terminals. Again, the resistor node is left */ + /* floating. The third is the Tee network, in */ + /* which the resistance is split in two parts, */ + /* connecting to a capacitor to ground in the */ + /* middle. This is the best solution but plays */ + /* havoc with LVS. So, the choice is a command */ + /* line option. */ + + esOutputHierResistor(hc, dev, scale, gate, source, has_model, + l, w, 2); + fprintf(esSpiceF, "\n%c", devchar); + if (gate->dterm_attrs) + fprintf(esSpiceF, "%sB", gate->dterm_attrs); + else + fprintf(esSpiceF, "%dB", esResNum - 1); + esOutputHierResistor(hc, dev, scale, gate, drain, has_model, + l, w, 2); + } + else + { + esOutputHierResistor(hc, dev, scale, source, drain, has_model, + l, w, 1); + } + break; + + case DEV_DIODE: + case DEV_PDIODE: + if (source == NULL) break; + + /* Diode is "Dnnn top bottom model" */ + + spcdevOutNode(hc->hc_hierName, + gate->dterm_node->efnode_name->efnn_hier, + "diode_top", esSpiceF); + if (dev->dev_nterm > 1) + spcdevOutNode(hc->hc_hierName, + source->dterm_node->efnode_name->efnn_hier, + "diode_bot", esSpiceF); + else if (subnode) + spcdevOutNode(hc->hc_hierName, + subnode->efnode_name->efnn_hier, + "diode_bot", esSpiceF); + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + spcHierWriteParams(hc, dev, scale, l, w, sdM); + break; + + case DEV_NDIODE: + if (source == NULL) break; + + /* Diode is "Dnnn bottom top model" */ + + if (dev->dev_nterm > 1) + spcdevOutNode(hc->hc_hierName, + source->dterm_node->efnode_name->efnn_hier, + "diode_bot", esSpiceF); + else if (subnode) + spcdevOutNode(hc->hc_hierName, + subnode->efnode_name->efnn_hier, + "diode_bot", esSpiceF); + spcdevOutNode(hc->hc_hierName, + gate->dterm_node->efnode_name->efnn_hier, + "diode_top", esSpiceF); + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + spcHierWriteParams(hc, dev, scale, l, w, sdM); + break; + + case DEV_CAP: + if (source == NULL) break; + + /* Capacitor is "Cnnn top bottom value" */ + /* extraction sets top=gate bottom=source */ + /* extracted units are fF; output is in fF */ + + spcdevOutNode(hc->hc_hierName, + gate->dterm_node->efnode_name->efnn_hier, + "cap_top", esSpiceF); + spcdevOutNode(hc->hc_hierName, + source->dterm_node->efnode_name->efnn_hier, + "cap_bot", esSpiceF); + + sdM = getCurDevMult(); + + /* SPICE has two capacitor types. If the "name" (EFDevTypes) is */ + /* "None", the simple capacitor type is used, and a value given. */ + /* If not, the "semiconductor capacitor" is used, and L and W */ + /* and the device name are output. */ + + if (!has_model) + { + fprintf(esSpiceF, " %ffF", (double)sdM * + (double)(dev->dev_cap)); + spcHierWriteParams(hc, dev, scale, l, w, sdM); + } + else + { + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + if (esScale < 0) + { + fprintf(esSpiceF, " w=%g l=%g", w*scale, l*scale); + } + else + { + fprintf(esSpiceF, " w=%gu l=%gu", + w * scale * esScale, + l * scale * esScale); + } + spcHierWriteParams(hc, dev, scale, l, w, sdM); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + } + break; + + case DEV_CAPREV: + if (source == NULL) break; + + /* Capacitor is "Cnnn bottom top value" */ + /* extraction sets top=source bottom=gate */ + /* extracted units are fF; output is in fF */ + + spcdevOutNode(hc->hc_hierName, + gate->dterm_node->efnode_name->efnn_hier, + "cap_bot", esSpiceF); + spcdevOutNode(hc->hc_hierName, + source->dterm_node->efnode_name->efnn_hier, + "cap_top", esSpiceF); + + sdM = getCurDevMult(); + + /* SPICE has two capacitor types. If the "name" (EFDevTypes) is */ + /* "None", the simple capacitor type is used, and a value given. */ + /* If not, the "semiconductor capacitor" is used, and L and W */ + /* and the device name are output. */ + + if (!has_model) + { + fprintf(esSpiceF, " %ffF", (double)sdM * + (double)(dev->dev_cap)); + spcHierWriteParams(hc, dev, scale, l, w, sdM); + } + else + { + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + if (esScale < 0) + { + fprintf(esSpiceF, " w=%g l=%g", w*scale, l*scale); + } + else + { + fprintf(esSpiceF, " w=%gu l=%gu", + w * scale * esScale, + l * scale * esScale); + } + spcHierWriteParams(hc, dev, scale, l, w, sdM); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + } + break; + + case DEV_FET: + case DEV_MOSFET: + case DEV_ASYMMETRIC: + if (source == NULL) break; + + /* MOSFET is "Mnnn drain gate source [L=x W=x [attributes]]" */ + + spcdevOutNode(hc->hc_hierName, + drain->dterm_node->efnode_name->efnn_hier, + "drain", esSpiceF); + spcdevOutNode(hc->hc_hierName, + gate->dterm_node->efnode_name->efnn_hier, + "gate", esSpiceF); + spcdevOutNode(hc->hc_hierName, + source->dterm_node->efnode_name->efnn_hier, + "source", esSpiceF); + if (subnode) + { + fprintf(esSpiceF, " "); + subnodeFlat = spcdevSubstrate(hc->hc_hierName, + subnode->efnode_name->efnn_hier, + dev->dev_type, esSpiceF); + } + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + sdM = getCurDevMult(); + + if (esScale < 0) + { + fprintf(esSpiceF, " w=%g l=%g", w*scale, l*scale); + } + else + { + fprintf(esSpiceF, " w=%gu l=%gu", + w * scale * esScale, + l * scale * esScale); + } + spcHierWriteParams(hc, dev, scale, l, w, sdM); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + + /* + * Check controlling attributes and output area and perimeter. + */ + hierS = extHierSDAttr(source); + hierD = extHierSDAttr(drain); + if ( gate->dterm_attrs ) + subAP = Match(ATTR_SUBSAP, gate->dterm_attrs ) ; + + fprintf(esSpiceF, "\n+ "); + dnode = GetHierNode(hc, drain->dterm_node->efnode_name->efnn_hier); + spcnAP(dnode, esFetInfo[dev->dev_type].resClassSD, scale, + "ad", "pd", sdM, esSpiceF, w); + snode= GetHierNode(hc, source->dterm_node->efnode_name->efnn_hier); + spcnAP(snode, esFetInfo[dev->dev_type].resClassSD, scale, + "as", "ps", sdM, esSpiceF, w); + if (subAP) + { + fprintf(esSpiceF, " * "); + if (esFetInfo[dev->dev_type].resClassSub < 0) + { + TxError("error: subap for devtype %d unspecified\n", + dev->dev_type); + fprintf(esSpiceF, "asub=0 psub=0"); + } + else if (subnodeFlat) + spcnAP(subnodeFlat, esFetInfo[dev->dev_type].resClassSub, scale, + "asub", "psub", sdM, esSpiceF, -1); + else + fprintf(esSpiceF, "asub=0 psub=0"); + } + + /* Now output attributes, if present */ + if (!esNoAttrs) + { + if (gate->dterm_attrs || source->dterm_attrs || drain->dterm_attrs) + fprintf(esSpiceF,"\n**devattr"); + if (gate->dterm_attrs) + fprintf(esSpiceF, " g=%s", gate->dterm_attrs); + if (source->dterm_attrs) + fprintf(esSpiceF, " s=%s", source->dterm_attrs); + if (drain->dterm_attrs) + fprintf(esSpiceF, " d=%s", drain->dterm_attrs); + } + break; + } + fprintf(esSpiceF, "\n"); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * spcdevHierMergeVisit -- + * + * First pass visit to devices to determine if they can be merged with + * any previously visited device. + * + * ---------------------------------------------------------------------------- + */ + +int +spcdevHierMergeVisit(hc, dev, scale) + HierContext *hc; + Dev *dev; /* Dev being output */ + float scale; /* Scale of transform (may be non-integer) */ +{ + DevTerm *gate, *source, *drain; + EFNode *subnode, *snode, *dnode, *gnode; + int pmode, l, w; + devMerge *fp, *cfp; + float m; + + /* If no terminals, or only a gate, can't do much of anything */ + if (dev->dev_nterm < 2) return 0; + + gate = &dev->dev_terms[0]; + source = drain = &dev->dev_terms[1]; + if (dev->dev_nterm >= 3) + drain = &dev->dev_terms[2]; + + gnode = GetHierNode(hc, gate->dterm_node->efnode_name->efnn_hier); + snode = GetHierNode(hc, source->dterm_node->efnode_name->efnn_hier); + dnode = GetHierNode(hc, drain->dterm_node->efnode_name->efnn_hier); + subnode = dev->dev_subsnode; + + EFGetLengthAndWidth(dev, &l, &w); + + fp = mkDevMerge((float)((float)l * scale), (float)((float)w * scale), + gnode, snode, dnode, subnode, hc->hc_hierName, dev); + + for (cfp = devMergeList; cfp != NULL; cfp = cfp->next) + { + if ((pmode = parallelDevs(fp, cfp)) != NOT_PARALLEL) + { + /* To-do: add back source, drain attribute check */ + + switch(dev->dev_class) + { + case DEV_MOSFET: + case DEV_MSUBCKT: + case DEV_ASYMMETRIC: + case DEV_FET: + m = esFMult[cfp->esFMIndex] + (fp->w / cfp->w); + break; + case DEV_RSUBCKT: + case DEV_RES: + if (fp->dev->dev_type == esNoModelType) + m = esFMult[cfp->esFMIndex] + (fp->dev->dev_res + / cfp->dev->dev_res); + else + m = esFMult[cfp->esFMIndex] + (fp->l / cfp->l); + break; + case DEV_CAP: + case DEV_CAPREV: + if (fp->dev->dev_type == esNoModelType) + m = esFMult[cfp->esFMIndex] + (fp->dev->dev_cap + / cfp->dev->dev_cap); + else + m = esFMult[cfp->esFMIndex] + + ((fp->l * fp->w) / (cfp->l * cfp->w)); + break; + } + setDevMult(fp->esFMIndex, DEV_KILLED); + setDevMult(cfp->esFMIndex, m); + esSpiceDevsMerged++; + freeMagic(fp); + return 0; + } + } + + /* No devices are parallel to this one (yet) */ + fp->next = devMergeList; + devMergeList = fp; + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * spccapHierVisit -- + * + * Procedure to output a single capacitor to the .spice file. + * Called by EFHierVisitCaps(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the file esSpiceF. Increments esCapNum. + * + * Format of a .spice cap line: + * + * C%d node1 node2 cap + * + * where + * node1, node2 are the terminals of the capacitor + * cap is the capacitance in femtofarads (NOT attofarads). + * + * ---------------------------------------------------------------------------- + */ + +int +spccapHierVisit(hc, hierName1, hierName2, cap) + HierContext *hc; + HierName *hierName1; + HierName *hierName2; + double cap; +{ + cap = cap / 1000; + if (fabs(cap) <= EFCapThreshold) + return 0; + + fprintf(esSpiceF, esSpiceCapFormat, esCapNum++, + nodeSpiceHierName(hc, hierName1), + nodeSpiceHierName(hc, hierName2), cap); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * spcresistHierVisit -- + * + * Procedure to output a single resistor to the .spice file. + * Called by EFHierVisitResists(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the file esSpiceF. Increments esResNum. + * + * Format of a .spice resistor line: + * + * R%d node1 node2 res + * + * where + * node1, node2 are the terminals of the resistor + * res is the resistance in ohms (NOT milliohms) + * + * + * ---------------------------------------------------------------------------- + */ +int +spcresistHierVisit(hc, hierName1, hierName2, res) + HierContext *hc; + HierName *hierName1; + HierName *hierName2; + int res; +{ + res = (res + 500) / 1000; + + fprintf(esSpiceF, "R%d %s %s %d\n", esResNum++, + nodeSpiceHierName(hc, hierName1), + nodeSpiceHierName(hc, hierName2), res); + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * spcsubHierVisit -- + * + * Find the node that connects to the substrate. Copy the string name + * of this node into "resstr" to be returned to the caller. + * + * Results: + * Return 1 if the substrate node has been found, to stop the search. + * Otherwise return 0 to keep the search going. + * + * ---------------------------------------------------------------------------- + */ + +int +spcsubHierVisit(hc, node, res, cap, resstrptr) + HierContext *hc; + EFNode *node; + int res; // Unused + double cap; // Unused + char **resstrptr; +{ + HierName *hierName; + char *nsn; + + if (node->efnode_flags & EF_SUBS_NODE) + { + hierName = (HierName *) node->efnode_name->efnn_hier; + nsn = nodeSpiceHierName(hc, hierName); + *resstrptr = StrDup((char **)NULL, nsn); + return 1; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * spcnodeHierVisit -- + * + * Procedure to output a single node to the .spice file along with its + * attributes and its dictionary (if present). Called by EFHierVisitNodes(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the files esSpiceF + * + * ---------------------------------------------------------------------------- + */ + +int +spcnodeHierVisit(hc, node, res, cap) + HierContext *hc; + EFNode *node; + int res; + double cap; +{ + EFNodeName *nn; + HierName *hierName; + bool isConnected = FALSE; + char *fmt, *nsn; + EFAttr *ap; + + if (node->efnode_client) + { + isConnected = (esDistrJunct) ? + (((nodeClient *)node->efnode_client)->m_w.widths != NULL) : + ((((nodeClient *)node->efnode_client)->m_w.visitMask + & DEV_CONNECT_MASK) != 0); + } + if (!isConnected && esDevNodesOnly) + return 0; + + /* Don't mark known ports as "FLOATING" nodes */ + if (!isConnected && node->efnode_flags & EF_PORT) isConnected = TRUE; + + hierName = (HierName *) node->efnode_name->efnn_hier; + nsn = nodeSpiceHierName(hc, hierName); + + if (esFormat == SPICE2 || esFormat == HSPICE && !strncmp(nsn, "z@", 2)) { + static char ntmp[MAX_STR_SIZE]; + + EFHNSprintf(ntmp, hierName); + if (esFormat == NGSPICE) fprintf(esSpiceF, " ; "); + fprintf(esSpiceF, "** %s == %s\n", ntmp, nsn); + } + cap = cap / 1000; + if (fabs(cap) > EFCapThreshold) + { + fprintf(esSpiceF, esSpiceCapFormat, esCapNum++, nsn, cap, + (isConnected) ? "" : + (esFormat == NGSPICE) ? " ; **FLOATING" : + " **FLOATING"); + } + if (node->efnode_attrs && !esNoAttrs) + { + if (esFormat == NGSPICE) fprintf(esSpiceF, " ; "); + fprintf(esSpiceF, "**nodeattr %s :",nsn ); + for (fmt = " %s", ap = node->efnode_attrs; ap; ap = ap->efa_next) + { + fprintf(esSpiceF, fmt, ap->efa_text); + fmt = ",%s"; + } + putc('\n', esSpiceF); + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * nodeSpiceHierName -- + * Find the real spice name for the node with hierarchical name hname. + * SPICE2 ==> numeric + * SPICE3, NGSPICE ==> full magic path + * HSPICE ==> less than 15 characters long + * + * Results: + * Returns the spice node name. + * + * Side effects: + * Allocates nodeClients for the node. + * + * ---------------------------------------------------------------------------- + */ +static char esTempName[MAX_STR_SIZE]; + +char *nodeSpiceHierName(hc, hname) + HierContext *hc; + HierName *hname; +{ + EFNodeName *nn; + HashEntry *he; + EFNode *node; + Def *def = hc->hc_use->use_def; + + // he = HashLookOnly(&def->def_nodes, EFHNToStr(hname)); + he = HashLookOnly(&efNodeHashTable, (char *)hname); + if (he == NULL) return "error"; + + nn = (EFNodeName *) HashGetValue(he); + if (nn == NULL) + return ""; + node = nn->efnn_node; + + if ((nodeClient *) (node->efnode_client) == NULL) + { + initNodeClient(node); + goto makeName; + } + else if (((nodeClient *) (node->efnode_client))->spiceNodeName == NULL) + goto makeName; + else goto retName; + +makeName: + if (esFormat == SPICE2) + sprintf(esTempName, "%d", esNodeNum++); + else { + EFHNSprintf(esTempName, node->efnode_name->efnn_hier); + if (esFormat == HSPICE) /* more processing */ + nodeHspiceName(esTempName); + } + ((nodeClient *) (node->efnode_client))->spiceNodeName = + StrDup(NULL, esTempName); + +retName: + return ((nodeClient *) (node->efnode_client))->spiceNodeName; +} + +/* + * ---------------------------------------------------------------------------- + * + * devMergeVisit -- + * Visits each dev throu EFHierVisitDevs and finds if it is in parallel with + * any previously visited dev. + * + * Results: + * 0 always to keep the caller going. + * + * Side effects: + * Numerous. + * + * ---------------------------------------------------------------------------- + */ + +int +devMergeHierVisit(hc, dev, scale) + HierContext *hc; + Dev *dev; /* Dev to examine */ + float scale; /* Scale transform of output */ +{ + DevTerm *gate, *source, *drain; + Dev *cf; + DevTerm *cg, *cs, *cd; + EFNode *subnode, *snode, *dnode, *gnode; + int pmode, l, w; + bool hS, hD, chS, chD; + devMerge *fp, *cfp; + float m; + + if (esDistrJunct) + devDistJunctHierVisit(hc, dev, scale); + + if (dev->dev_nterm < 2) + { + TxError("outPremature\n"); + return 0; + } + + gate = &dev->dev_terms[0]; + source = drain = &dev->dev_terms[1]; + if (dev->dev_nterm >= 3) + drain = &dev->dev_terms[2]; + + + gnode = GetHierNode(hc, gate->dterm_node->efnode_name->efnn_hier); + snode = GetHierNode(hc, source->dterm_node->efnode_name->efnn_hier); + dnode = GetHierNode(hc, drain->dterm_node->efnode_name->efnn_hier); + if (dev->dev_subsnode) + subnode = spcdevSubstrate(hc->hc_hierName, + dev->dev_subsnode->efnode_name->efnn_hier, + dev->dev_type, NULL); + else + subnode = NULL; + + /* Get length and width of the device */ + EFGetLengthAndWidth(dev, &l, &w); + + fp = mkDevMerge((float)((float)l * scale), (float)((float)w * scale), + gnode, snode, dnode, subnode, NULL, dev); + hS = extHierSDAttr(source); + hD = extHierSDAttr(drain); + + /* + * run the list of devs. compare the current one with + * each one in the list. if they fullfill the matching requirements + * merge them only if: + * 1) they have both apf S, D attributes + * or + * 2) one of them has aph S, D attributes and they have the same + * hierarchical prefix + * If one of them has apf and the other aph print a warning. + */ + + for (cfp = devMergeList; cfp != NULL; cfp = cfp->next) + { + if ((pmode = parallelDevs(fp, cfp)) != NOT_PARALLEL) + { + cf = cfp->dev; + cg = &cfp->dev->dev_terms[0]; + cs = cd = &cfp->dev->dev_terms[1]; + if (cfp->dev->dev_nterm >= 3) + { + if (pmode == PARALLEL) + cd = &cfp->dev->dev_terms[2]; + else if (pmode == ANTIPARALLEL) + cs = &cfp->dev->dev_terms[2]; + } + + chS = extHierSDAttr(cs); chD = extHierSDAttr(cd); + if (!(chS || chD || hS || hD)) /* all flat S, D */ + goto mergeThem; + + if (hS && !chS) + { + mergeAttr(&cs->dterm_attrs, &source->dterm_attrs); + } + if (hD && !chD) + { + mergeAttr(&cd->dterm_attrs, &drain->dterm_attrs); + } +mergeThem: + switch(dev->dev_class) + { + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_MSUBCKT: + case DEV_FET: + m = esFMult[cfp->esFMIndex] + ((float)fp->w / (float)cfp->w); + break; + case DEV_RSUBCKT: + case DEV_RES: + if (fp->dev->dev_type == esNoModelType) + m = esFMult[cfp->esFMIndex] + (fp->dev->dev_res + / cfp->dev->dev_res); + else + m = esFMult[cfp->esFMIndex] + (fp->l / cfp->l); + break; + case DEV_CAP: + case DEV_CAPREV: + if (fp->dev->dev_type == esNoModelType) + m = esFMult[cfp->esFMIndex] + (fp->dev->dev_cap + / cfp->dev->dev_cap); + else + m = esFMult[cfp->esFMIndex] + + ((fp->l * fp->w) / (cfp->l * cfp->w)); + break; + } + setDevMult(fp->esFMIndex, DEV_KILLED); + setDevMult(cfp->esFMIndex, m); + esSpiceDevsMerged++; + /* Need to do attribute stuff here */ + freeMagic(fp); + return 0; + } + } + + /* No parallel devs to it yet */ + fp->next = devMergeList; + devMergeList = fp; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * devDistJunctVisit -- + * Called for every dev and updates the nodeclients of its terminals + * + * Results: + * 0 to keep the calling procedure going + * + * Side effects: + * calls update_w which might allocate stuff + * + * ---------------------------------------------------------------------------- + */ + +int +devDistJunctHierVisit(hc, dev, scale) + HierContext *hc; + Dev *dev; /* Dev to examine */ + float scale; /* Scale tranform of output */ +{ + EFNode *n; + int i, l, w; + + if (dev->dev_nterm < 2) + { + TxError("outPremature\n"); + return 0; + } + + w = (int)((float)w * scale); + EFGetLengthAndWidth(dev, &l, &w); + + for (i = 1; idev_nterm; i++) + { + n = GetHierNode(hc, dev->dev_terms[i].dterm_node->efnode_name->efnn_hier); + update_w(esFetInfo[dev->dev_type].resClassSD, w, n); + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * esMakePorts --- + * + * Routine called once for each cell definition in the extraction + * hierarchy. Called from EFHierSrDefs(). Looks at all subcircuit + * connections in the cell, and adds a port record to the subcircuit + * for each connection to it. Note that this generates an arbitrary + * port order for each cell. To have a specific port order, it is + * necessary to generate ports for each cell. + * ---------------------------------------------------------------------------- + */ + +int +esMakePorts(hc, cdata) + HierContext *hc; + ClientData cdata; +{ + Connection *conn; + Def *def = hc->hc_use->use_def, *portdef, *updef; + Use *use; + HashEntry *he; + EFNodeName *nn; + char *name, *portname, *tptr, *aptr, *locname; + int j; + + if (def->def_uses == NULL) return 0; /* Bottom of hierarchy */ + + for (conn = (Connection *)def->def_conns; conn; conn = conn->conn_next) + { + for (j = 0; j < 2; j++) + { + name = (j == 0) ? conn->conn_1.cn_name : conn->conn_2.cn_name; + locname = (j == 0) ? conn->conn_2.cn_name : conn->conn_1.cn_name; + if ((tptr = strchr(name, '/')) == NULL) + continue; + + portname = name; + updef = def; + + while (tptr != NULL) + { + /* Ignore array information for the purpose of tracing */ + /* the cell definition hierarchy. */ + + aptr = strchr(portname, '['); + if ((aptr == NULL) || (aptr > tptr)) + *tptr = '\0'; + else + *aptr = '\0'; + + // Find the cell for the instance + portdef = NULL; + for (use = updef->def_uses; use; use = use->use_next) + { + if (!strcmp(use->use_id, portname)) + { + portdef = use->use_def; + break; + } + } + if ((aptr == NULL) || (aptr > tptr)) + *tptr = '/'; + else + *aptr = '['; + portname = tptr + 1; + + // Find the net of portname in the subcell and + // make it a port if it is not already. + + if (portdef) + { + he = HashFind(&portdef->def_nodes, portname); + nn = (EFNodeName *) HashGetValue(he); + if (nn == NULL) + { + efBuildNode(portdef, FALSE, portname, 0.0, + 0, 0, NULL, NULL, 0); + nn = (EFNodeName *) HashGetValue(he); + } + + if (!(nn->efnn_node->efnode_flags & EF_PORT)) + { + nn->efnn_node->efnode_flags |= EF_PORT; + nn->efnn_port = -1; // Will be sorted later + } + } + + if ((tptr = strchr(portname, '/')) == NULL) + break; + if (portdef == NULL) break; // Error condition? + + updef = portdef; + } + // Diagnostic + // TxPrintf("Connection in %s to net %s (%s)\n", def->def_name, + // name, portname); + } + } + + // Now do the same thing for parasitic connections into subcells + // However, restrict the number of ports based on "cthresh". + + for (conn = (Connection *)def->def_caps; conn; conn = conn->conn_next) + { + for (j = 0; j < 2; j++) + { + name = (j == 0) ? conn->conn_1.cn_name : conn->conn_2.cn_name; + locname = (j == 0) ? conn->conn_2.cn_name : conn->conn_1.cn_name; + if ((tptr = strchr(name, '/')) == NULL) + continue; + + // Ignore capacitances that are less than the threshold. + // In particular, this keeps parasitics out of the netlist for + // LVS purposes if "cthresh" is set to "infinite". + + if (fabs((double)conn->conn_cap) < EFCapThreshold) continue; + + portname = name; + updef = def; + + while (tptr != NULL) + { + /* Ignore array information for the purpose of tracing */ + /* the cell definition hierarchy. */ + + aptr = strchr(portname, '['); + if ((aptr == NULL) || (aptr > tptr)) + *tptr = '\0'; + else + *aptr = '\0'; + + // Find the cell for the instance + portdef = NULL; + for (use = updef->def_uses; use; use = use->use_next) + { + if (!strcmp(use->use_id, portname)) + { + portdef = use->use_def; + break; + } + } + if ((aptr == NULL) || (aptr > tptr)) + *tptr = '/'; + else + *aptr = '['; + portname = tptr + 1; + + // Find the net of portname in the subcell and + // make it a port if it is not already. + + if (portdef) + { + he = HashFind(&portdef->def_nodes, portname); + nn = (EFNodeName *) HashGetValue(he); + if (nn == NULL) + { + efBuildNode(portdef, FALSE, portname, 0.0, + 0, 0, NULL, NULL, 0); + nn = (EFNodeName *) HashGetValue(he); + } + + if (!(nn->efnn_node->efnode_flags & EF_PORT)) + { + nn->efnn_node->efnode_flags |= EF_PORT; + nn->efnn_port = -1; // Will be sorted later + } + } + + if ((tptr = strchr(portname, '/')) == NULL) + break; + if (portdef == NULL) break; // Error condition? + + updef = portdef; + } + // Diagnostic + // TxPrintf("Connection in %s to net %s (%s)\n", def->def_name, + // name, portname); + } + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * esHierVisit --- + * + * Routine called once for each cell definition in the extraction + * hierarchy. Called from EFHierSrDefs(). Outputs a single + * subcircuit record for the cell definition. Note that this format + * ignores all information pertaining to flattened cells, and is + * appropriate mainly for LVS purposes. + * ---------------------------------------------------------------------------- + */ + +int +esHierVisit(hc, cdata) + HierContext *hc; + ClientData cdata; +{ + HierContext *hcf; + Def *def = hc->hc_use->use_def; + Def *topdef; + EFNode *snode; + char *resstr = NULL; + DefFlagsData *dfd; + int flags; + int locDoSubckt = esDoSubckt; + + dfd = (DefFlagsData *)cdata; + topdef = dfd->def; + flags = dfd->flags; + + /* Cells without any contents (devices or subcircuits) will */ + /* be absorbed into their parents. Use this opportunity to */ + /* remove all ports. */ + + if (def != topdef) + { + if (def->def_devs == NULL && def->def_uses == NULL) + { + if (locDoSubckt == AUTO) + { + /* Determine if there are ports, and don't */ + /* kill the cell if it has any. */ + locDoSubckt = FALSE; + for (snode = (EFNode *) def->def_firstn.efnode_next; + snode != &def->def_firstn; + snode = (EFNode *) snode->efnode_next) + if (snode->efnode_flags & (EF_PORT | EF_SUBS_PORT)) + { + locDoSubckt = TRUE; + break; + } + } + if (locDoSubckt == FALSE) + { + for (snode = (EFNode *) def->def_firstn.efnode_next; + snode != &def->def_firstn; + snode = (EFNode *) snode->efnode_next) + snode->efnode_flags &= ~(EF_PORT | EF_SUBS_PORT); + if (def != topdef) return 0; + } + } + } + + /* Flatten this definition only */ + hcf = EFFlatBuildOneLevel(hc->hc_use->use_def, flags); + + /* If definition has been marked as having no devices, then this */ + /* def is not to be output unless it is the top level. */ + + if ((def != topdef) && (hc->hc_use->use_def->def_flags & DEF_NODEVICES)) + { + EFFlatDone(); + return 0; + } + + /* Generate subcircuit header */ + if ((def != topdef) || (def->def_flags & DEF_SUBCIRCUIT)) + topVisit(def); + else + fprintf(esSpiceF, "\n* Top level circuit %s\n\n", topdef->def_name); + + /* Output subcircuit calls */ + EFHierVisitSubcircuits(hcf, subcktHierVisit, (ClientData)NULL); + + /* Merge devices */ + if (esMergeDevsA || esMergeDevsC) + { + devMerge *p; + + EFHierVisitDevs(hcf, spcdevHierMergeVisit, (ClientData)NULL); + TxPrintf("Devs merged: %d\n", esSpiceDevsMerged); + esFMIndex = 0; + for (p = devMergeList; p != NULL; p = p->next) + freeMagic(p); + devMergeList = NULL; + } + + /* Output devices */ + EFHierVisitDevs(hcf, spcdevHierVisit, (ClientData)NULL); + + /* Output lumped parasitic resistors */ + EFHierVisitResists(hcf, spcresistHierVisit, (ClientData)NULL); + + /* Output coupling capacitances */ + sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n", esCapAccuracy); + EFHierVisitCaps(hcf, spccapHierVisit, (ClientData)NULL); + + if (EFCompat == FALSE) + { + /* Find the substrate node */ + EFHierVisitNodes(hcf, spcsubHierVisit, (ClientData)&resstr); + if (resstr == NULL) resstr = StrDup((char **)NULL, "0"); + + /* Output lumped capacitance and resistance to substrate */ + sprintf( esSpiceCapFormat, "C%%d %%s %s %%.%dlffF%%s\n", + resstr, esCapAccuracy); + EFHierVisitNodes(hcf, spcnodeHierVisit, (ClientData) NULL); + freeMagic(resstr); + } + + if ((def != topdef) || (def->def_flags & DEF_SUBCIRCUIT)) + fprintf(esSpiceF, ".ends\n\n"); + else + fprintf(esSpiceF, ".end\n\n"); + + /* Reset device/node/subcircuit instance counts */ + + esCapNum = 0; + esDevNum = 1000; + esResNum = 0; + esDiodeNum = 0; + esSbckNum = 0; + esNodeNum = 10; + + EFFlatDone(); + return 0; +} + +#endif /* MAGIC_WRAPPER */ diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c new file mode 100644 index 00000000..cb9edc5c --- /dev/null +++ b/ext2spice/ext2spice.c @@ -0,0 +1,3739 @@ +/* + * ext2spice.c -- + * + * Program to flatten hierarchical .ext files and produce + * a .spice file, suitable for use as input to simulators + * such as spice and hspice. + * + * Flattens the tree rooted at file.ext, reading in additional .ext + * files as specified by "use" lines in file.ext. The output is left + * in file.spice, unless '-o esSpiceFile' is specified, in which case the + * output is left in 'esSpiceFile'. + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ext2spice/ext2spice.c,v 1.8 2010/08/25 17:33:56 tim Exp $"; +#endif /* not lint */ + +#include +#include /* for atof() */ +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/dqueue.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#ifdef MAGIC_WRAPPER +#include "database/database.h" +#include "windows/windows.h" +#include "textio/textio.h" +#include "dbwind/dbwind.h" /* for DBWclientID */ +#include "commands/commands.h" /* for module auto-load */ +#include "textio/txcommands.h" +#endif +#include "extflat/extflat.h" +#include "extflat/EFint.h" +#include "extract/extract.h" /* for extDevTable */ +#include "utils/runstats.h" + +#include "ext2spice/ext2spice.h" + +/* Options specific to ext2spice */ +bool esDoExtResis = FALSE; +bool esDoPorts = TRUE; +bool esDoHierarchy = FALSE; +bool esDoRenumber = FALSE; +bool esDoResistorTee = FALSE; +int esDoSubckt = AUTO; +bool esDevNodesOnly = FALSE; +bool esMergeNames = TRUE; +bool esNoAttrs = FALSE; +bool esHierAP = FALSE; +char spcesDefaultOut[FNSIZE]; +int esCapAccuracy = 2; +char esSpiceCapFormat[FNSIZE]; +char *spcesOutName = spcesDefaultOut; +FILE *esSpiceF = NULL; +float esScale = -1.0 ; /* negative if hspice the EFScale/100 otherwise */ + +unsigned short esFormat = SPICE3 ; + +int esCapNum, esDevNum, esResNum, esDiodeNum; +int esNodeNum; /* just in case we're extracting spice2 */ +int esSbckNum; /* used in hspice node name shortening */ +int esNoModelType; /* index for device type "None" (model-less device) */ + +/* + * The following hash table and associated functions are used only if + * the format is hspice, to keep the translation between the hierarchical + * prefix of a node and the x num that we use to output valid hspice + * which also are meaningful. + */ +HashTable subcktNameTable ; /* the hash table itself */ +DQueue subcktNameQueue ; /* q used to print it sorted at the end*/ + +fetInfoList esFetInfo[MAXDEVTYPES]; + +/* Record for keeping a list of global names */ + +typedef struct GLL *globalListPtr; + +typedef struct GLL { + globalListPtr gll_next; + char *gll_name; +} globalList; + +unsigned long initMask = 0; + +bool esMergeDevsA = FALSE; /* aggressive merging of devs L1=L2 merge them */ +bool esMergeDevsC = FALSE; /* conservative merging of devs L1=L2 and W1=W2 */ + /* used with the hspice multiplier */ +bool esDistrJunct = FALSE; + +/* + *--------------------------------------------------------- + * Variables & macros used for merging parallel devs + * The merging of devs is based on the fact that spcdevVisit + * visits the devs in the same order all the time so the + * value of esFMult[i] keeps the multiplier for the ith dev + *--------------------------------------------------------- + */ + +float *esFMult = NULL; /* the array itself */ +int esFMIndex = 0; /* current index to it */ +int esFMSize = FMULT_SIZE ; /* its current size (growable) */ +int esSpiceDevsMerged; + +devMerge *devMergeList = NULL ; + +/* + * ---------------------------------------------------------------------------- + * + * Apply modifications to a global node name and output to file "outf" + * + * Results: + * None. + * + * Side effects: + * Output to file + * ---------------------------------------------------------------------------- + */ + +void +esFormatSubs(outf, suf) + FILE *outf; + char *suf; +{ + char *specchar; + int l; + + if (outf) + { + l = strlen(suf) - 1; + if ((EFTrimFlags & EF_TRIMGLOB ) && suf[l] == '!' || + (EFTrimFlags & EF_TRIMLOCAL) && suf[l] == '#') + suf[l] = '\0' ; + if (EFTrimFlags & EF_CONVERTCOMMAS) + while ((specchar = strchr(suf, ',')) != NULL) + *specchar = ';'; + if (EFTrimFlags & EF_CONVERTEQUAL) + while ((specchar = strchr(suf, '=')) != NULL) + *specchar = ':'; + fprintf(outf, "%s", suf); + } +} + +#ifdef MAGIC_WRAPPER + +#ifdef EXT2SPICE_AUTO +/* + * ---------------------------------------------------------------------------- + * + * Tcl package initialization function + * + * ---------------------------------------------------------------------------- + */ + +int +Exttospice_Init(interp) + Tcl_Interp *interp; +{ + /* Sanity checks! */ + if (interp == NULL) return TCL_ERROR; + if (Tcl_PkgRequire(interp, "Tclmagic", MAGIC_VERSION, 0) == NULL) + return TCL_ERROR; + if (Tcl_InitStubs(interp, "8.1", 0) == NULL) return TCL_ERROR; + + TxPrintf("Auto-loading EXTTOSPICE module\n"); + TxFlushOut(); + + /* Replace the auto-load function with the one defined in */ + /* this package in the command functions list. */ + + if (WindReplaceCommand(DBWclientID, "exttospice", CmdExtToSpice) < 0) + return TCL_ERROR; + + /* Add "ext2spice" as an alias for "exttospice" */ + if (WindReplaceCommand(DBWclientID, "ext2spice", CmdExtToSpice) < 0) + return TCL_ERROR; + + Tcl_PkgProvide(interp, "Exttospice", MAGIC_VERSION); + return TCL_OK; +} +#endif /* EXT2SPICE_AUTO */ + +/* + * ---------------------------------------------------------------------------- + * + * Main callback for command "magic::exttospice" + * + * ---------------------------------------------------------------------------- + */ + +#define EXTTOSPC_RUN 0 +#define EXTTOSPC_DEFAULT 1 +#define EXTTOSPC_FORMAT 2 +#define EXTTOSPC_RTHRESH 3 +#define EXTTOSPC_CTHRESH 4 +#define EXTTOSPC_MERGE 5 +#define EXTTOSPC_EXTRESIST 6 +#define EXTTOSPC_RESISTORTEE 7 +#define EXTTOSPC_SCALE 8 +#define EXTTOSPC_SUBCIRCUITS 9 +#define EXTTOSPC_HIERARCHY 10 +#define EXTTOSPC_RENUMBER 11 +#define EXTTOSPC_MERGENAMES 12 +#define EXTTOSPC_HELP 13 + +void +CmdExtToSpice(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int i,flatFlags; + char *inName; + FILE *f; + + int value; + int option = EXTTOSPC_RUN; + int argc = cmd->tx_argc; + char **argv = cmd->tx_argv; + char **msg; + char *resstr = NULL; + char *substr = NULL; + bool err_result, locDoSubckt; + + short sd_rclass; + short sub_rclass; + char *devname; + char *subname; + int idx, idx2; + globalList *glist = NULL; + + static EFCapValue LocCapThreshold = 2; + static int LocResistThreshold = INFINITE_THRESHOLD; + + static char *spiceFormats[] = { + "SPICE2", "SPICE3", "HSPICE", "NGSPICE", NULL + }; + + static char *cmdExtToSpcOption[] = { + "[run] [options] run exttospice on current cell\n" + " use \"run -help\" to get standard options", + "default reset to default values", + "format [] set output format", + "rthresh [] set resistance threshold value", + "cthresh [] set capacitance threshold value", + "merge [] merge parallel transistors", + "extresist [on|off] incorporate information from extresist", + "resistor tee [on|off] model resistor capacitance as a T-network", + "scale [on|off] use .option card for scaling", + "subcircuits [on|off] standard cells become subcircuit calls", + "hierarchy [on|off] output hierarchical spice for LVS", + "renumber [on|off] on = number instances X1, X2, etc.\n" + " off = keep instance ID names", + "global [on|off] on = merge unconnected global nets by name", + "help print help information", + NULL + }; + + static char *cmdMergeTypes[] = { + "none don't merge parallel devices", + "conservative merge devices with same L, W", + "aggressive merge devices with same L", + NULL + }; + + static char *cmdExtToSpcFormat[] = { + "spice2", + "spice3", + "hspice", + "ngspice", + NULL + }; + + static char *yesno[] = { + "yes", + "true", + "on", + "no", + "false", + "off", + NULL + }; + + static char *subcktopts[] = { + "yes", + "true", + "on", + "no", + "false", + "off", + "automatic", + "top", + "descend", + NULL + }; + + typedef enum { + IDX_YES, IDX_TRUE, IDX_ON, IDX_NO, IDX_FALSE, IDX_OFF, + IDX_AUTO, IDX_TOP, IDX_DESCEND + } yesnoType; + + esNoModelType = -1; + + if (cmd->tx_argc > 1) + { + option = Lookup(cmd->tx_argv[1], cmdExtToSpcOption); + if (option < 0) option = EXTTOSPC_RUN; + else argv++; + } + + switch (option) + { + case EXTTOSPC_EXTRESIST: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, (esDoExtResis) ? "on" : "off", NULL); + return; + } + else if (cmd->tx_argc != 3) + goto usage; + idx = Lookup(cmd->tx_argv[2], yesno); + if (idx < 0) goto usage; + else if (idx < 3) esDoExtResis = TRUE; + else esDoExtResis = FALSE; + break; + + case EXTTOSPC_RESISTORTEE: + if (cmd->tx_argc == 3) + { + Tcl_SetResult(magicinterp, (esDoResistorTee) ? "on" : "off", NULL); + return; + } + else if (cmd->tx_argc != 4) + goto usage; + idx = Lookup(cmd->tx_argv[3], yesno); + if (idx < 0) goto usage; + else if (idx < 3) esDoResistorTee = TRUE; + else esDoResistorTee = FALSE; + break; + + case EXTTOSPC_SCALE: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, (esScale < 0) ? "on" : "off", NULL); + return; + } + else if (cmd->tx_argc != 3) + goto usage; + idx = Lookup(cmd->tx_argv[2], yesno); + if (idx < 0) goto usage; + else if (idx < 3) esScale = -1.0; + else esScale = 0.0; + break; + + case EXTTOSPC_HIERARCHY: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, (esDoHierarchy) ? "on" : "off", NULL); + return; + } + idx = Lookup(cmd->tx_argv[2], yesno); + if (idx < 0) goto usage; + else if (idx < 3) /* yes */ + esDoHierarchy = TRUE; + else /* no */ + esDoHierarchy = FALSE; + break; + + case EXTTOSPC_RENUMBER: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, (esDoRenumber) ? "on" : "off", NULL); + return; + } + idx = Lookup(cmd->tx_argv[2], yesno); + if (idx < 0) goto usage; + else if (idx < 3) /* yes */ + esDoRenumber = TRUE; + else /* no */ + esDoRenumber = FALSE; + break; + + case EXTTOSPC_MERGENAMES: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, (esMergeNames) ? "on" : "off", NULL); + return; + } + idx = Lookup(cmd->tx_argv[2], yesno); + if (idx < 0) goto usage; + else if (idx < 3) /* yes */ + esMergeNames = TRUE; + else /* no */ + esMergeNames = FALSE; + break; + + case EXTTOSPC_SUBCIRCUITS: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, (esDoPorts) ? "on" : "off", NULL); + return; + } + idx = Lookup(cmd->tx_argv[2], subcktopts); + switch (idx) { + case IDX_YES: case IDX_TRUE: case IDX_ON: + esDoPorts = TRUE; + return; + break; + case IDX_NO: case IDX_FALSE: case IDX_OFF: + esDoPorts = FALSE; + return; + break; + case IDX_DESCEND: + if (cmd->tx_argc == 3) + { + Tcl_SetResult(magicinterp, (esDoPorts) ? "on" : "off", NULL); + return; + } + break; + case IDX_TOP: + if (cmd->tx_argc == 3) + { + Tcl_SetResult(magicinterp, + (esDoSubckt == 2) ? "auto" : + (esDoSubckt == 1) ? "on" : "off", NULL); + return; + } + break; + default: + goto usage; + break; + } + + if (cmd->tx_argc != 4) goto usage; + idx2 = Lookup(cmd->tx_argv[3], subcktopts); + switch (idx2) { + case IDX_YES: case IDX_TRUE: case IDX_ON: + if (idx == IDX_DESCEND) + esDoPorts = TRUE; + else + esDoSubckt = TRUE; + break; + case IDX_NO: case IDX_FALSE: case IDX_OFF: + if (idx == IDX_DESCEND) + esDoPorts = FALSE; + else + esDoSubckt = FALSE; + break; + case IDX_AUTO: + esDoSubckt = AUTO; + break; + default: + goto usage; + } + break; + + case EXTTOSPC_FORMAT: + if (cmd->tx_argc == 2) + { + Tcl_SetResult(magicinterp, cmdExtToSpcFormat[esFormat], NULL); + return; + } + else if (cmd->tx_argc < 3) goto usage; + idx = Lookup(cmd->tx_argv[2], cmdExtToSpcFormat); + if (idx < 0) + { + Tcl_SetResult(magicinterp, "Bad format type. Formats are:" + "spice2, spice3, and hspice.", NULL); + return; + } + else + { + esFormat = idx; + /* By default, use .option to declare scale in HSPICE mode */ + if (esFormat == HSPICE) esScale = -1.0; + } + break; + + case EXTTOSPC_CTHRESH: + if (cmd->tx_argc == 2) + { + if (!IS_FINITE_F(LocCapThreshold)) + Tcl_SetResult(magicinterp, "infinite", NULL); + else + Tcl_SetObjResult(magicinterp, + Tcl_NewDoubleObj((double)LocCapThreshold)); + return; + } + else if (cmd->tx_argc < 3) goto usage; + + /* Note that strtod() (called by StrIsNumeric()) accepts */ + /* "infinite" as a valid numerical value; however, the */ + /* conversion to C type INF is *not* INFINITE_THRESHOLD, so */ + /* we need to check this case first. . . */ + + if (!strncmp(cmd->tx_argv[2], "inf", 3)) + LocCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F; + else if (StrIsNumeric(cmd->tx_argv[2])) + LocCapThreshold = atoCap(cmd->tx_argv[2]); + else + TxError("exttospice: numeric value or \"infinite\" expected.\n"); + break; + + case EXTTOSPC_RTHRESH: + if (cmd->tx_argc == 2) + { + if (LocResistThreshold == INFINITE_THRESHOLD) + Tcl_SetResult(magicinterp, "infinite", NULL); + else + Tcl_SetObjResult(magicinterp, + Tcl_NewIntObj(LocResistThreshold)); + return; + } + else if (cmd->tx_argc < 3) goto usage; + if (StrIsInt(cmd->tx_argv[2])) + LocResistThreshold = atoi(cmd->tx_argv[2]); + else if (!strncmp(cmd->tx_argv[2], "inf", 3)) + LocResistThreshold = INFINITE_THRESHOLD; + else + TxError("exttospice: integer value or \"infinite\" expected.\n"); + break; + + case EXTTOSPC_MERGE: + if (cmd->tx_argc == 2) + { + if (esMergeDevsA) + Tcl_SetResult(magicinterp, "aggressive", NULL); + else if (esMergeDevsC) + Tcl_SetResult(magicinterp, "conservative", NULL); + else + Tcl_SetResult(magicinterp, "none", NULL); + return; + } + else if (cmd->tx_argc < 3) goto usage; + value = Lookup(cmd->tx_argv[2], cmdMergeTypes); + if (value < 0) + { + TxError("Merge types are:\n"); + for (msg = &(cmdMergeTypes[0]); *msg != NULL; msg++) + TxPrintf(" %s\n", *msg); + } + else switch (value) { + case 0: + esMergeDevsA = FALSE; + esMergeDevsC = FALSE; + break; + case 1: + esMergeDevsA = FALSE; + esMergeDevsC = TRUE; + break; + case 2: + esMergeDevsA = TRUE; + esMergeDevsC = FALSE; + break; + } + break; + + case EXTTOSPC_DEFAULT: + LocCapThreshold = 2; + LocResistThreshold = INFINITE_THRESHOLD; + EFTrimFlags = EF_CONVERTCOMMAS | EF_CONVERTEQUAL; + EFScale = 0.0; + if (EFArgTech) + { + freeMagic(EFArgTech); + EFArgTech = NULL; + } + if (EFSearchPath) + { + freeMagic(EFSearchPath); + EFSearchPath = NULL; + } + break; + + case EXTTOSPC_RUN: + goto runexttospice; + break; + + case EXTTOSPC_HELP: +usage: + for (msg = &(cmdExtToSpcOption[0]); *msg != NULL; msg++) + { + TxPrintf(" %s\n", *msg); + } + break; + } + return; + +runexttospice: + + /* Reset the device indices */ + esCapNum = 0; + esDevNum = 1000; + esResNum = 0; + esDiodeNum = 0; + esSbckNum = 0; + esNodeNum = 10; /* just in case we're extracting spice2 */ + esFMIndex = 0; + esSpiceDevsMerged = 0; + esDevNodesOnly = FALSE; /* so using -F doesn't become permanent */ + + EFInit(); + + EFResistThreshold = LocResistThreshold; + EFCapThreshold = LocCapThreshold; + + /* Process command line arguments */ + + inName = EFArgs(argc, argv, &err_result, spcmainArgs, (ClientData) NULL); + if (err_result == TRUE) + { + EFDone(); + return; + } + + if (inName == NULL) + { + /* Assume that we want to do exttospice on the currently loaded cell */ + + if (w == (MagWindow *) NULL) + { + windCheckOnlyWindow(&w, DBWclientID); + } + + if (w == (MagWindow *) NULL) + { + TxError("Point to a window or specify a cell name.\n"); + return; + } + if ((inName = ((CellUse *) w->w_surfaceID)->cu_def->cd_name) == NULL) + { + TxError("No cell present\n"); + return; + } + } + + /* + * Initializations specific to this program. + * Make output name inName.spice if they weren't + * explicitly specified + */ + + if (spcesOutName == spcesDefaultOut) + sprintf(spcesDefaultOut, "%s.spice", inName); + + /* Read the hierarchical description of the input circuit */ + if (EFReadFile(inName, TRUE, esDoExtResis, FALSE) == FALSE) + { + EFDone(); + return; + } + + /* If the .ext file was read without error, then open the output file */ + + if ((esSpiceF = fopen(spcesOutName, "w")) == NULL) + { + char *tclres = Tcl_Alloc(128); + sprintf(tclres, "exttospice: Unable to open file %s for writing\n", + spcesOutName); + Tcl_SetResult(magicinterp, tclres, TCL_DYNAMIC); + EFDone(); + return; + } + + if (EFStyle == NULL) + { + TxError("Warning: Current extraction style does not match .ext file!\n"); + TxError("Area/Perimeter values and parasitic values will be zero.\n"); + } + + /* create default devinfo entries (MOSIS) which can be overridden by + the command line arguments */ + + for ( i = 0 ; i < MAXDEVTYPES ; i++ ) { + esFetInfo[i].resClassSD = NO_RESCLASS; + esFetInfo[i].resClassSub = NO_RESCLASS; + esFetInfo[i].defSubs = NULL; + } + + /* Get esFetInfo information from the current extraction style */ + /* (this works only for the Tcl version with the embedded exttospice */ + /* command) */ + + idx = 0; + while (ExtGetDevInfo(idx++, &devname, &sd_rclass, &sub_rclass, &subname)) + { + if (idx == MAXDEVTYPES) + { + TxError("Error: Ran out of space for device types!\n"); + break; + } + i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, devname); + if (!strcmp(devname, "None")) + esNoModelType = i; + if (EFStyle != NULL) + { + esFetInfo[i].resClassSD = sd_rclass; + esFetInfo[i].resClassSub = sub_rclass; + esFetInfo[i].defSubs = subname; + } + + if (EFCompat == TRUE) + { + /* Tcl variable substitution for substrate node names */ + if (subname && (subname[0] == '$')) + { + resstr = (char *)Tcl_GetVar(magicinterp, &subname[1], + TCL_GLOBAL_ONLY); + if (resstr != NULL) esFetInfo[i].defSubs = resstr; + } + } + + if (esDoHierarchy && (subname != NULL)) + { + globalList *glptr; + char *locsubname, *bangptr; + bool isgood = TRUE; + + locsubname = StrDup(NULL, subname); + + bangptr = locsubname + strlen(locsubname) - 1; + if (*bangptr == '!') *bangptr = '\0'; + + // Ad-hoc check: Global names with "Error", "err", etc. + // should be rejected from the list. Also node name + // "None" is a common entry indicating that extracting + // an implicit substrate is disallowed. + + if (!strncmp(locsubname, "err", 3)) isgood = FALSE; + else if (strstr(locsubname, "error") != NULL) isgood = FALSE; + else if (strstr(locsubname, "Error") != NULL) isgood = FALSE; + else if (strstr(locsubname, "ERROR") != NULL) isgood = FALSE; + else if (!strcasecmp(locsubname, "None")) isgood = FALSE; + + for (glptr = glist; glptr; glptr = glptr->gll_next) + if (!strcmp(glptr->gll_name, locsubname)) + break; + + if (isgood && (glptr == NULL)) + { + glptr = (globalList *)mallocMagic(sizeof(globalList)); + glptr->gll_name = locsubname; + glptr->gll_next = glist; + glist = glptr; + } + else + freeMagic(locsubname); + } + } + + if (EFCompat == TRUE) + { + /* Keep a pointer to the "GND" variable, if it exists. */ + + resstr = (char *)Tcl_GetVar(magicinterp, "GND", TCL_GLOBAL_ONLY); + if (resstr == NULL) resstr = "GND"; /* default value */ + } + + /* Write the output file */ + + fprintf(esSpiceF, "* %s file created from %s.ext - technology: %s\n\n", + spiceFormats[esFormat], inName, EFTech); + if (esScale < 0) + fprintf(esSpiceF, ".option scale=%gu\n\n", EFScale / 100.0); + else + esScale = EFScale / 100.0; + + /* Set output format flags */ + + flatFlags = EF_FLATNODES; + if (esMergeNames == FALSE) flatFlags |= EF_NONAMEMERGE; + + // This forces options TRIMGLOB and CONVERTEQUAL, not sure that's such a + // good idea. . . + EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL; + if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS; + if (esFormat == HSPICE) + EFTrimFlags |= EF_TRIMLOCAL; + + /* Write globals under a ".global" card */ + + if (esDoHierarchy && (glist != NULL)) + { + fprintf(esSpiceF, ".global "); + while (glist != NULL) + { + if (EFCompat == TRUE) + { + /* Handle global names that are TCL variables */ + if (glist->gll_name[0] == '$') + { + resstr = (char *)Tcl_GetVar(magicinterp, + &(glist->gll_name[1]), TCL_GLOBAL_ONLY); + if (resstr != NULL) + esFormatSubs(esSpiceF, resstr); + else + esFormatSubs(esSpiceF, glist->gll_name); + } + else + esFormatSubs(esSpiceF, glist->gll_name); + } + else + esFormatSubs(esSpiceF, glist->gll_name); + + fprintf(esSpiceF, " "); + freeMagic(glist->gll_name); + freeMagic(glist); + glist = glist->gll_next; + } + fprintf(esSpiceF, "\n\n"); + } + + /* Convert the hierarchical description to a flat one */ + + if (esFormat == HSPICE) { + HashInit(&subcktNameTable, 32, HT_STRINGKEYS); +#ifndef UNSORTED_SUBCKT + DQInit(&subcktNameQueue, 64); +#endif + } + locDoSubckt = FALSE; + if (esDoHierarchy) + { + ESGenerateHierarchy(inName, flatFlags); + } + else + { + EFFlatBuild(inName, flatFlags); + + /* Determine if this is a subcircuit */ + if (esDoSubckt == AUTO) { + if (efFlatRootDef->def_flags & DEF_SUBCIRCUIT) + locDoSubckt = TRUE; + } + if ((esDoSubckt == TRUE) || (locDoSubckt == TRUE)) + topVisit(efFlatRootDef); + + /* When generating subcircuits, remove the subcircuit */ + /* flag from the top level cell. Other than being */ + /* used to generate the subcircuit wrapper, it should */ + /* not prevent descending into its own hierarchy. */ + + efFlatRootDef->def_flags &= ~(DEF_SUBCIRCUIT); + + /* If we don't want to write subcircuit calls, remove */ + /* the subcircuit flag from all cells at this time. */ + + if (!esDoPorts) + EFVisitSubcircuits(subcktUndef, (ClientData) NULL); + + initMask = ( esDistrJunct ) ? (unsigned long)0 : DEV_CONNECT_MASK; + + if (esMergeDevsA || esMergeDevsC) + { + devMerge *p; + + EFVisitDevs(devMergeVisit, (ClientData) NULL); + TxPrintf("Devs merged: %d\n", esSpiceDevsMerged); + esFMIndex = 0; + for (p = devMergeList; p != NULL; p = p->next) + freeMagic(p); + devMergeList = NULL; + } + else if (esDistrJunct) + EFVisitDevs(devDistJunctVisit, (ClientData) NULL); + EFVisitDevs(spcdevVisit, (ClientData) NULL); + initMask = (unsigned long) 0; + if (flatFlags & EF_FLATCAPS) + { + (void) sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n", + esCapAccuracy); + EFVisitCaps(spccapVisit, (ClientData) NULL); + } + EFVisitResists(spcresistVisit, (ClientData) NULL); + EFVisitSubcircuits(subcktVisit, (ClientData) NULL); + + /* Visit nodes to find the substrate node */ + EFVisitNodes(spcsubVisit, (ClientData)&substr); + if (substr == NULL) + substr = StrDup((char **)NULL, "0"); + + (void) sprintf( esSpiceCapFormat, "C%%d %%s %s %%.%dlffF%%s", + substr, esCapAccuracy); + EFVisitNodes(spcnodeVisit, (ClientData) NULL); + + if (EFCompat == FALSE) freeMagic(substr); + + if ((esDoSubckt == TRUE) || (locDoSubckt == TRUE)) + fprintf(esSpiceF, ".ends\n"); + + if (esFormat == HSPICE) + printSubcktDict(); + + EFFlatDone(); + } + EFDone(); + + if (esSpiceF) fclose(esSpiceF); + + TxPrintf("exttospice finished.\n"); + return; +} + +#else /* MAGIC_WRAPPER */ + +/* + * ---------------------------------------------------------------------------- + * + * main -- + * + * Top level of ext2spice. + * + * ---------------------------------------------------------------------------- + */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + + int i,flatFlags; + char *inName; + FILE *f; + bool locDoSubckt; + + esSpiceDevsMerged = 0; + + static char *spiceFormats[] = { + "SPICE2", "SPICE3", "HSPICE", "NGSPICE", NULL + }; + + EFInit(); + EFResistThreshold = INFINITE_THRESHOLD ; + /* create default devinfo entries (MOSIS) which can be overriden by + the command line arguments */ + for ( i = 0 ; i < MAXDEVTYPES ; i++ ) { + esFetInfo[i].resClassSD = NO_RESCLASS; + esFetInfo[i].resClassSub = NO_RESCLASS; + esFetInfo[i].defSubs = NULL; + } + i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "ndev"); + esFetInfo[i].resClassSD = 0 ; + esFetInfo[i].resClassSub = NO_RESCLASS ; + esFetInfo[i].defSubs = "Gnd!"; + i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "pdev"); + esFetInfo[i].resClassSD = 1 ; + esFetInfo[i].resClassSub = 8 ; + esFetInfo[i].defSubs = "Vdd!"; + i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "nmos"); + esFetInfo[i].resClassSD = 0 ; + esFetInfo[i].resClassSub = NO_RESCLASS ; + esFetInfo[i].defSubs = "Gnd!"; + i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "pmos"); + esFetInfo[i].resClassSD = 1 ; + esFetInfo[i].resClassSub = 8 ; + esFetInfo[i].defSubs = "Vdd!"; + /* Process command line arguments */ + + inName = EFArgs(argc, argv, NULL, spcmainArgs, (ClientData) NULL); + if (inName == NULL) + exit (1); + + /* + * Initializations specific to this program. + * Make output name inName.spice if they weren't + * explicitly specified + */ + + if (spcesOutName == spcesDefaultOut) + sprintf(spcesDefaultOut, "%s.spice", inName); + + if ((esSpiceF = fopen(spcesOutName, "w")) == NULL) + { + perror(spcesOutName); + exit (1); + } + + /* Read the hierarchical description of the input circuit */ + if (EFReadFile(inName, TRUE, esDoExtResis, FALSE) == FALSE) + { + exit (1); + } + + fprintf(esSpiceF, "* %s file created from %s.ext - technology: %s\n\n", + spiceFormats[esFormat], inName, EFTech); + if (esScale < 0) + fprintf(esSpiceF,".option scale=%gu\n\n", EFScale / 100.0); + else + esScale = EFScale / 100.0; + + /* Convert the hierarchical description to a flat one */ + flatFlags = EF_FLATNODES; + EFTrimFlags |= EF_TRIMGLOB ; + if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS; + if (esFormat == HSPICE) { + EFTrimFlags |= EF_TRIMLOCAL ; + HashInit(&subcktNameTable, 32, HT_STRINGKEYS); +#ifndef UNSORTED_SUBCKT + DQInit(&subcktNameQueue, 64); +#endif + } + EFFlatBuild(inName, flatFlags); + + /* Determine if this is a subcircuit */ + locDoSubckt = FALSE; + if (esDoSubckt == AUTO) { + if (efFlatRootDef->def_flags & DEF_SUBCIRCUIT) + locDoSubckt = TRUE; + } + if ((esDoSubckt == TRUE) || (locDoSubckt == TRUE)) + topVisit(efFlatRootDef); + + /* If we don't want to write subcircuit calls, remove the */ + /* subcircuit flag from all cells at this time. */ + + if (!esDoPorts) + EFVisitSubcircuits(subcktUndef, (ClientData) NULL); + + initMask = ( esDistrJunct ) ? (unsigned long)0 : DEV_CONNECT_MASK ; + + if ( esMergeDevsA || esMergeDevsC ) { + EFVisitDevs(devMergeVisit, (ClientData) NULL); + TxPrintf("Devs merged: %d\n", esSpiceDevsMerged); + esFMIndex = 0 ; + { + devMerge *p; + + for ( p = devMergeList ; p != NULL ; p=p->next ) freeMagic(p); + } + } else if ( esDistrJunct ) + EFVisitDevs(devDistJunctVisit, (ClientData) NULL); + EFVisitDevs(spcdevVisit, (ClientData) NULL); + initMask = (unsigned long) 0; + if (flatFlags & EF_FLATCAPS) { + (void) sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n",esCapAccuracy); + EFVisitCaps(spccapVisit, (ClientData) NULL); + } + EFVisitResists(spcresistVisit, (ClientData) NULL); + EFVisitSubcircuits(subcktVisit, (ClientData) NULL); + (void) sprintf( esSpiceCapFormat, "C%%d %%s GND %%.%dlffF%%s", esCapAccuracy); + EFVisitNodes(spcnodeVisit, (ClientData) NULL); + + if ((esDoSubckt == TRUE) || (locDoSubckt == TRUE)) + fprintf(esSpiceF, ".ends\n"); + + if (esFormat == HSPICE) + printSubcktDict(); + + EFFlatDone(); + EFDone(); + + if (esSpiceF) fclose(esSpiceF); + + TxPrintf("Memory used: %s\n", RunStats(RS_MEM, NULL, NULL)); + exit (0); +} + +#endif /* MAGIC_WRAPPER */ + + +/* + * ---------------------------------------------------------------------------- + * + * spcmainArgs -- + * + * Process those arguments that are specific to ext2spice. + * Assumes that *pargv[0][0] is '-', indicating a flag + * argument. + * + * Results: + * None. + * + * Side effects: + * After processing an argument, updates *pargc and *pargv + * to point to after the argument. + * + * May initialize various global variables based on the + * arguments given to us. + * + * Exits in the event of an improper argument. + * + * ---------------------------------------------------------------------------- + */ + +int +spcmainArgs(pargc, pargv) + int *pargc; + char ***pargv; +{ + char **argv = *pargv, *cp; + int argc = *pargc; + + switch (argv[0][1]) + { + case 'd': + esDistrJunct = TRUE; + break; + case 'M': + esMergeDevsA = TRUE; + break; + case 'm': + esMergeDevsC = TRUE; + break; + case 'B': + esNoAttrs = TRUE; + break; + case 'F': + esDevNodesOnly = TRUE; + break; + case 'o': + if ((spcesOutName = ArgStr(&argc, &argv, "filename")) == NULL) + goto usage; + break; + case 'f': { + char *ftmp ; + + if ((ftmp = ArgStr(&argc, &argv, "format")) == NULL) + goto usage; + if (strcasecmp(ftmp, "SPICE2") == 0) + esFormat = SPICE2; + else if (strcasecmp(ftmp, "SPICE3") == 0) + esFormat = SPICE3; + else if (strcasecmp(ftmp, "HSPICE") == 0) + { + esFormat = HSPICE; + esScale = -1.0; + } + else if (strcasecmp(ftmp, "NGSPICE") == 0) + esFormat = NGSPICE; + else goto usage; + break; + } + case 'J': + { + char *ftmp ; + + if ((ftmp = ArgStr(&argc, &argv, "hierAP_SD")) == NULL) + goto usage; + if ( strcasecmp(ftmp, "HIER") == 0 ) + esHierAP = TRUE ; + else if ( strcasecmp(ftmp, "FLAT") == 0 ) + esHierAP = FALSE ; + else goto usage; + + break; + } + case 'y': { + char *t; + + if (( t = ArgStr(&argc, &argv, "cap-accuracy") ) == NULL) + goto usage; + esCapAccuracy = atoi(t); + break; + } +#ifndef MAGIC_WRAPPER + case 'j': + { + char *rp, subsNode[80] ; + int ndx, rClass, rClassSub = -1; + + if ((cp = ArgStr(&argc,&argv,"resistance class")) == NULL) + goto usage; + if ( (rp = (char *) strchr(cp,':')) == NULL ) + goto usage; + else *rp++ = '\0'; + if ( sscanf(rp, "%d/%d/%s", &rClass, &rClassSub, subsNode) != 3 ) { + rClassSub = -1 ; + if ( sscanf(rp, "%d/%s", &rClass, subsNode) != 2 ) goto usage; + } + ndx = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, cp); + esFetInfo[ndx].resClassSD = rClass; + esFetInfo[ndx].resClassSub = rClassSub; + if ( ((1<efnn_node); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHierSDAttr -- + * Check if the attribute of the argument dev_terminal or the global + * settings are such that we want a hierarchical extraction of its S/D + * + * + * Results: + * TRUE or FALSE + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool extHierSDAttr(term) + DevTerm *term; +{ + bool r = esHierAP; + + if (term->dterm_attrs) + { + if (Match(ATTR_HIERAP, term->dterm_attrs) != FALSE) + r = TRUE; + else if (Match(ATTR_FLATAP, term->dterm_attrs) != FALSE) + r = FALSE; + } + return r; +} + +/* + * ---------------------------------------------------------------------------- + * + * subcktVisit -- + * + * Procedure to output a subcircuit definition to the .spice file. + * Called by EFVisitSubcircuits(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the file esSpiceF. + * + * Format of a .spice subcircuit call: + * + * X%d node1 node2 ... noden name + * + * where + * node1 node2 ... noden are the nodes connecting to the ports of + * the subcircuit. "name" is the name of the subcircuit. It is + * assumed that the definition of "name" (.defs name ... .ends) + * exists elsewhere and will be appended to the SPICE deck prior + * to simulation (as is also assumed for device models). + * + * ---------------------------------------------------------------------------- + */ +int +subcktVisit(use, hierName, is_top) + Use *use; + HierName *hierName; + bool is_top; /* TRUE if this is the top-level cell */ +{ + EFNode *snode; + Def *def = use->use_def; + EFNodeName *nodeName; + int portorder, portmax, imp_max, tchars; + char stmp[MAX_STR_SIZE]; + char *instname, *subcktname; + DevParam *plist, *pptr; + + if (is_top == TRUE) return 0; /* Ignore the top-level cell */ + + /* Retain instance name unless esDoRenumber is set, or format is Spice2 */ + if (use->use_id == NULL || esDoRenumber == TRUE || esFormat == SPICE2) + { + fprintf(esSpiceF, "X%d", esSbckNum++); + tchars = 5; + } + else + { + int savflags = EFTrimFlags; + EFTrimFlags = 0; // Do no substitutions on subcircuit names + + /* Use full hierarchical decomposition for name */ + /* (not just use->use_id. hierName already has use->use_id at end) */ + EFHNSprintf(stmp, hierName); + fprintf(esSpiceF, "X%s", stmp); + EFTrimFlags = savflags; + tchars = 1 + strlen(stmp); + } + + /* This is not a DEV, but "spcdevOutNode" is a general-purpose routine that */ + /* turns a local name in the use's def to a hierarchical name in the */ + /* calling def. */ + + /* Note that the ports of the subcircuit will not necessarily be */ + /* ALL the entries in the hash table, so we have to check. */ + + portmax = EFGetPortMax(def, &imp_max); + + if (portmax < 0) + { + /* No port order declared; print them as we see them. */ + /* This shouldn't happen for proper .ext files written */ + /* by the magic extractor. */ + + for (snode = (EFNode *) def->def_firstn.efnode_next; + snode != &def->def_firstn; + snode = (EFNode *) snode->efnode_next) + { + if (snode->efnode_flags & EF_PORT) + for (nodeName = snode->efnode_name; nodeName != NULL; + nodeName = nodeName->efnn_next) + if (nodeName->efnn_port >= 0) + { + portmax++; + if (tchars > 80) + { + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + tchars += spcdevOutNode(hierName, nodeName->efnn_hier, + "subcircuit", esSpiceF); + } + } + + /* Look for all implicit substrate connections that are */ + /* declared as local node names, and put them last. */ + + for (snode = (EFNode *) def->def_firstn.efnode_next; + snode != &def->def_firstn; + snode = (EFNode *) snode->efnode_next) + { + if (snode->efnode_flags & EF_SUBS_PORT) + { + nodeName = snode->efnode_name; + if (nodeName->efnn_port < 0) + nodeName->efnn_port = ++portmax; + + /* This is not a hierarchical name or node! */ + EFHNSprintf(stmp, nodeName->efnn_hier); + if (tchars > 80) + { + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + fprintf(esSpiceF, " %s", stmp); + tchars += (1 + strlen(stmp)); + } + } + } + else + { + /* Port numbers need not start at zero or be contiguous. */ + /* They will be printed in numerical order. */ + + portorder = 0; + while (portorder <= portmax) + { + for (snode = (EFNode *) def->def_firstn.efnode_next; + snode != &def->def_firstn; + snode = (EFNode *) snode->efnode_next) + { + if (!(snode->efnode_flags & EF_PORT)) continue; + for (nodeName = snode->efnode_name; nodeName != NULL; + nodeName = nodeName->efnn_next) + { + int portidx = nodeName->efnn_port; + if (portidx == portorder) + { + if (tchars > 80) + { + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + tchars += spcdevOutNode(hierName, nodeName->efnn_hier, + "subcircuit", esSpiceF); + break; + } + } + if (nodeName != NULL) break; + } + portorder++; + } + + /* Look for all implicit substrate connections that are */ + /* declared as local node names, and put them last. */ + + portorder = portmax; + while (portorder <= imp_max) + { + for (snode = (EFNode *) def->def_firstn.efnode_next; + snode != &def->def_firstn; + snode = (EFNode *) snode->efnode_next) + { + if (!(snode->efnode_flags & EF_SUBS_PORT)) continue; + nodeName = snode->efnode_name; + if (nodeName->efnn_port == portorder) + { + /* This is not a hierarchical name or node! */ + EFHNSprintf(stmp, nodeName->efnn_hier); + if (tchars > 80) + { + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + fprintf(esSpiceF, " %s", stmp); + tchars += (1 + strlen(stmp)); + } + } + portorder++; + } + } + + // Check for a "device parameter" defined with the name of the cell. + // This contains a list of parameter strings to be passed to the + // cell instance. + + instname = mallocMagic(2 + strlen(def->def_name)); + sprintf(instname, ":%s", def->def_name); + plist = efGetDeviceParams(instname); + for (pptr = plist; pptr; pptr = pptr->parm_next) + { + if (tchars > 80) + { + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + fprintf(esSpiceF, " %s", pptr->parm_name); + tchars += (1 + strlen(pptr->parm_name)); + } + freeMagic(instname); + + /* SPICE subcircuit names must begin with A-Z. This will also be */ + /* enforced when writing X subcircuit calls. */ + subcktname = def->def_name; + while (!isalpha(*subcktname)) subcktname++; + + if (tchars > 80) fprintf(esSpiceF, "\n+"); + fprintf(esSpiceF, " %s\n", subcktname); /* subcircuit model name */ + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * subcktUndef -- + * + * Procedure to remove the DEF_SUBCIRCUIT flag from all subcells. + * Called by EFVisitSubcircuits(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Undefines the DEF_SUBCIRCUIT flag in each encountered Def. + * + * ---------------------------------------------------------------------------- + */ +int +subcktUndef(use, hierName, is_top) + Use *use; + HierName *hierName; + bool is_top; /* TRUE if this is the top-level cell */ +{ + Def *def = use->use_def; + + def->def_flags &= ~(DEF_SUBCIRCUIT); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * topVisit -- + * + * Procedure to output a subcircuit definition to the .spice file. + * + * Results: + * None. + * + * Side effects: + * Writes to the file esSpiceF. + * + * Format of a .spice subcircuit definition: + * + * .subckt name node1 node2 ... noden + * + * where + * node1 node2 ... noden are the nodes connecting to the ports of + * the subcircuit. "name" is the name of the cell def. + * + * ---------------------------------------------------------------------------- + */ + +void +topVisit(def) + Def *def; +{ + EFNode *snode; + EFNodeName *sname, *nodeName; + HashSearch hs; + HashEntry *he; + int portorder, portmax, tchars; + DevParam *plist, *pptr; + char *instname; + char *subcktname; + char *pname; + + /* SPICE subcircuit names must begin with A-Z. This will also be */ + /* enforced when writing X subcircuit calls. */ + subcktname = def->def_name; + while (!isalpha(*subcktname)) subcktname++; + + fprintf(esSpiceF, ".subckt %s", subcktname); + tchars = 8 + strlen(subcktname); + + /* Note that the ports of the subcircuit will not necessarily be */ + /* ALL the entries in the hash table, so we have to check. */ + + HashStartSearch(&hs); + portmax = -1; + + while (he = HashNext(&def->def_nodes, &hs)) + { + sname = (EFNodeName *) HashGetValue(he); + if (sname == NULL) continue; + snode = sname->efnn_node; + if (!(snode->efnode_flags & EF_PORT)) continue; + for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next) + { + portorder = nodeName->efnn_port; + if (portorder > portmax) portmax = portorder; + } + } + + if (portmax < 0) + { + /* No port order declared; print them and number them */ + /* as we encounter them. This normally happens only */ + /* when writing hierarchical decks for LVS. */ + + portorder = 0; + + HashStartSearch(&hs); + while (he = HashNext(&def->def_nodes, &hs)) + { + sname = (EFNodeName *) HashGetValue(he); + if (sname == NULL) continue; + snode = sname->efnn_node; + + if (snode->efnode_flags & EF_PORT) + if (snode->efnode_name->efnn_port < 0) + { + if (tchars > 80) + { + /* Line continuation */ + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + pname = nodeSpiceName(snode->efnode_name->efnn_hier); + fprintf(esSpiceF, " %s", pname); + tchars += strlen(pname) + 1; + snode->efnode_name->efnn_port = portorder++; + } + } + } + else + { + /* Port numbers need not start at zero or be contiguous. */ + /* They will be printed in numerical order. */ + + portorder = 0; + while (portorder <= portmax) + { + HashStartSearch(&hs); + while (he = HashNext(&def->def_nodes, &hs)) + { + int portidx; + EFNodeName *unnumbered; + + sname = (EFNodeName *) HashGetValue(he); + snode = sname->efnn_node; + + if (!(snode->efnode_flags & EF_PORT)) continue; + + for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next) + { + portidx = nodeName->efnn_port; + if (portidx == portorder) + { + if (tchars > 80) + { + /* Line continuation */ + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + pname = nodeSpiceName(snode->efnode_name->efnn_hier); + fprintf(esSpiceF, " %s", pname); + tchars += strlen(pname) + 1; + break; + } + else if (portidx < 0) + unnumbered = nodeName; + } + if (nodeName != NULL) + break; + else if (portidx < 0) + // Node has not been assigned a port number + unnumbered->efnn_port = ++portmax; + } + portorder++; + } + } + + /* Add all implicitly-defined local substrate node names */ + + HashStartSearch(&hs); + while (he = HashNext(&def->def_nodes, &hs)) + { + sname = (EFNodeName *) HashGetValue(he); + if (sname == NULL) continue; + snode = sname->efnn_node; + + if (snode->efnode_flags & EF_SUBS_PORT) + { + if (snode->efnode_name->efnn_port < 0) + { + char stmp[MAX_STR_SIZE]; + + if (tchars > 80) + { + /* Line continuation */ + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + /* This is not a hierarchical name or node! */ + EFHNSprintf(stmp, snode->efnode_name->efnn_hier); + fprintf(esSpiceF, " %s", stmp); + snode->efnode_name->efnn_port = portorder++; + tchars += strlen(stmp) + 1; + } + } + } + + // Add any parameters defined by "property parameter" in the cell + + instname = mallocMagic(2 + strlen(def->def_name)); + sprintf(instname, ":%s", def->def_name); + plist = efGetDeviceParams(instname); + for (pptr = plist; pptr; pptr = pptr->parm_next) + { + if (tchars > 80) + { + /* Line continuation */ + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + pname = pptr->parm_name; + fprintf(esSpiceF, " %s", pname); + tchars += strlen(pname) + 1; + } + freeMagic(instname); + + fprintf(esSpiceF, "\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * spcWriteParams --- + * + * Write parameters to a device line in SPICE output. This is normally + * restricted to subcircuit devices but may include other devices to + * accomodate various extensions to the basic SPICE format. + * + * ---------------------------------------------------------------------------- + */ + +void +spcWriteParams(dev, hierName, scale, l, w, sdM) + Dev *dev; /* Dev being output */ + HierName *hierName; /* Hierarchical path down to this dev */ + float scale; /* Scale transform for output */ + int l; /* Device length, in internal units */ + int w; /* Device width, in internal units */ + float sdM; /* Device multiplier */ +{ + bool hierD; + DevParam *plist; + int parmval; + EFNode *dnode, *subnodeFlat = NULL; + + bool extHierSDAttr(); + + plist = efGetDeviceParams(EFDevTypes[dev->dev_type]); + while (plist != NULL) + { + switch (plist->parm_type[0]) + { + case 'a': + // Check for area of terminal node vs. device area + if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0') + { + fprintf(esSpiceF, " %s=", plist->parm_name); + parmval = dev->dev_area; + if (esScale < 0) + fprintf(esSpiceF, "%g", parmval * scale * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", parmval * scale * scale + * esScale * esScale * plist->parm_scale + * 1E-12); + else + fprintf(esSpiceF, "%gp", parmval * scale * scale + * esScale * esScale); + } + else + { + int pn; + + pn = plist->parm_type[1] - '0'; + if (pn >= dev->dev_nterm) pn = dev->dev_nterm - 1; + + hierD = extHierSDAttr(&dev->dev_terms[pn]); + + // For parameter a followed by parameter p, + // process both at the same time. + + if (plist->parm_next && plist->parm_next->parm_type[0] + == 'p' && plist->parm_next->parm_type[1] + == plist->parm_type[1]) + { + if (hierD) + spcnAPHier(&dev->dev_terms[pn], hierName, + esFetInfo[dev->dev_type].resClassSD, + scale, plist->parm_type, + plist->parm_next->parm_type, + sdM, esSpiceF); + else + { + dnode = SpiceGetNode(hierName, + dev->dev_terms[pn].dterm_node->efnode_name->efnn_hier); + spcnAP(dnode, esFetInfo[dev->dev_type].resClassSD, + scale, plist->parm_name, + plist->parm_next->parm_name, + sdM, esSpiceF, w); + } + plist = plist->parm_next; + } + else + { + if (hierD) + spcnAPHier(&dev->dev_terms[pn], hierName, + esFetInfo[dev->dev_type].resClassSD, + scale, plist->parm_type, NULL, + sdM, esSpiceF); + else + { + dnode = SpiceGetNode(hierName, + dev->dev_terms[pn].dterm_node->efnode_name->efnn_hier); + spcnAP(dnode, esFetInfo[dev->dev_type].resClassSD, + scale, plist->parm_name, NULL, + sdM, esSpiceF, w); + } + } + } + + break; + case 'p': + // Check for area of terminal node vs. device area + if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0') + { + fprintf(esSpiceF, " %s=", plist->parm_name); + parmval = dev->dev_perim; + if (esScale < 0) + fprintf(esSpiceF, "%g", parmval * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", parmval * scale + * esScale * plist->parm_scale * 1E-6); + else + fprintf(esSpiceF, "%gu", parmval * scale * esScale); + } + else + { + int pn; + + pn = plist->parm_type[1] - '0'; + if (pn >= dev->dev_nterm) pn = dev->dev_nterm - 1; + + hierD = extHierSDAttr(&dev->dev_terms[pn]); + + // For parameter p followed by parameter a, + // process both at the same time. + + if (plist->parm_next && plist->parm_next->parm_type[0] + == 'a' && plist->parm_next->parm_type[1] + == plist->parm_type[1]) + { + if (hierD) + spcnAPHier(&dev->dev_terms[pn], hierName, + esFetInfo[dev->dev_type].resClassSD, + scale, plist->parm_next->parm_type, + plist->parm_type, sdM, esSpiceF); + else + { + dnode = SpiceGetNode(hierName, + dev->dev_terms[pn].dterm_node->efnode_name->efnn_hier); + spcnAP(dnode, esFetInfo[dev->dev_type].resClassSD, + scale, plist->parm_next->parm_name, + plist->parm_name, sdM, esSpiceF, w); + } + plist = plist->parm_next; + } + else + { + if (hierD) + spcnAPHier(&dev->dev_terms[pn], hierName, + esFetInfo[dev->dev_type].resClassSD, + scale, NULL, plist->parm_type, + sdM, esSpiceF); + else + { + dnode = SpiceGetNode(hierName, + dev->dev_terms[pn].dterm_node->efnode_name->efnn_hier); + spcnAP(dnode, esFetInfo[dev->dev_type].resClassSD, + scale, NULL, plist->parm_name, + sdM, esSpiceF, w); + } + } + } + break; + + case 'l': + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", l * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", l * scale * esScale + * plist->parm_scale * 1E-6); + else + fprintf(esSpiceF, "%gu", l * scale * esScale); + break; + case 'w': + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", w * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", w * scale * esScale + * plist->parm_scale * 1E-6); + else + fprintf(esSpiceF, "%gu", w * scale * esScale); + break; + case 's': + fprintf(esSpiceF, " %s=", plist->parm_name); + subnodeFlat = spcdevSubstrate(hierName, + dev->dev_subsnode->efnode_name->efnn_hier, + dev->dev_type, esSpiceF); + break; + case 'x': + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", dev->dev_rect.r_xbot * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", dev->dev_rect.r_xbot * scale + * esScale * plist->parm_scale * 1E-6); + else + fprintf(esSpiceF, "%gu", dev->dev_rect.r_xbot * scale + * esScale); + break; + case 'y': + fprintf(esSpiceF, " %s=", plist->parm_name); + if (esScale < 0) + fprintf(esSpiceF, "%g", dev->dev_rect.r_ybot * scale); + else if (plist->parm_scale != 1.0) + fprintf(esSpiceF, "%g", dev->dev_rect.r_ybot * scale + * esScale * plist->parm_scale * 1E-6); + else + fprintf(esSpiceF, "%gu", dev->dev_rect.r_ybot * scale + * esScale); + break; + case 'r': + fprintf(esSpiceF, " %s=", plist->parm_name); + fprintf(esSpiceF, "%f", (double)(dev->dev_res)); + break; + case 'c': + fprintf(esSpiceF, " %s=", plist->parm_name); + fprintf(esSpiceF, "%ff", (double)(dev->dev_cap)); + break; + } + plist = plist->parm_next; + } + + /* Add parameters that are to be copied verbatim */ + for (plist = dev->dev_params; plist; plist = plist->parm_next) + fprintf(esSpiceF, " %s", plist->parm_name); +} + +/* + * ---------------------------------------------------------------------------- + * + * esOutputResistor --- + * + * Routine used by spcdevVisit to print a resistor device. This + * is broken out into a separate routine so that each resistor + * device may be represented (if the option is selected) by a + * "tee" network of two resistors on either side of the central + * node, which then has a capacitance to ground. + * + * Results: + * None. + * + * Side effects: + * Output to the SPICE deck. + * + * ---------------------------------------------------------------------------- + */ + +void +esOutputResistor(dev, hierName, scale, term1, term2, has_model, l, w, dscale) + Dev *dev; /* Dev being output */ + HierName *hierName; /* Hierarchical path down to this dev */ + float scale; /* Scale transform for output */ + DevTerm *term1, *term2; /* Terminals of the device */ + bool has_model; /* Is this a modeled resistor? */ + int l, w; /* Device length and width */ + int dscale; /* Device scaling (for split resistors) */ +{ + float sdM ; + char name[12], devchar; + + /* Resistor is "Rnnn term1 term2 value" */ + /* extraction sets two terminals, which are assigned */ + /* term1=gate term2=source by the above code. */ + /* extracted units are Ohms; output is in Ohms */ + + spcdevOutNode(hierName, term1->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + spcdevOutNode(hierName, term2->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + + sdM = getCurDevMult(); + + /* SPICE has two resistor types. If the "name" (EFDevTypes) is */ + /* "None", the simple resistor type is used, and a value given. */ + /* If not, the "semiconductor resistor" is used, and L and W */ + /* and the device name are output. */ + + if (!has_model) + { + fprintf(esSpiceF, " %f", ((double)(dev->dev_res) + / (double)(dscale)) / (double)sdM); + spcWriteParams(dev, hierName, scale, l, w, sdM); + } + else + { + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + if (esScale < 0) + fprintf(esSpiceF, " w=%g l=%g", w * scale, (l * scale) / dscale); + else + fprintf(esSpiceF, " w=%gu l=%gu", + w * scale * esScale, + ((l * scale * esScale) / dscale)); + + spcWriteParams(dev, hierName, scale, l, w, sdM); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * spcdevVisit -- + * + * Procedure to output a single dev to the .spice file. + * Called by EFVisitDevs(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the file esSpiceF. + * + * Format of a .spice dev line: + * + * M%d drain gate source substrate type w=w l=l * x y + * + ad= pd= as= ps= * asub= psub= + * **devattr g= s= d= + * + * where + * type is a name identifying this type of transistor + * other types of transistors are extracted with + * an M card but it should be easy to turn them to whatever + * you want. + * gate, source, and drain are the nodes to which these three + * terminals connect + * l, w are the length and width of the channel + * x, y are the x, y coordinates of a point within the channel. + * g=, s=, d= are the (optional) attributes; if present, each + * is followed by a comma-separated list of attributes. + * + * ---------------------------------------------------------------------------- + */ + +int +spcdevVisit(dev, hierName, scale, trans) + Dev *dev; /* Dev being output */ + HierName *hierName; /* Hierarchical path down to this dev */ + float scale; /* Scale transform for output */ + Transform *trans; /* (unused) */ +{ + DevParam *plist, *pptr; + DevTerm *gate, *source, *drain; + EFNode *subnode, *snode, *dnode, *subnodeFlat = NULL; + int l, w, i, parmval; + bool subAP= FALSE, hierS, hierD, extHierSDAttr() ; + float sdM; + char name[12], devchar; + bool has_model = TRUE; + + sprintf(name, "output"); + + /* If no terminals, can't do much of anything */ + if (dev->dev_nterm < 1 ) + return 0; + + if ( (esMergeDevsA || esMergeDevsC) && devIsKilled(esFMIndex++) ) + return 0; + + /* Get L and W of device */ + EFGetLengthAndWidth(dev, &l, &w); + + /* If only two terminals, connect the source to the drain */ + gate = &dev->dev_terms[0]; + if (dev->dev_nterm >= 2) + source = drain = &dev->dev_terms[1]; + if (dev->dev_nterm >= 3) + { + /* If any terminal is marked with attribute "D" or "S" */ + /* (label "D$" or "S$" at poly-diffusion interface), */ + /* then force order of source and drain accordingly. */ + + if ((dev->dev_terms[1].dterm_attrs && + !strcmp(dev->dev_terms[1].dterm_attrs, "D")) || + (dev->dev_terms[2].dterm_attrs && + !strcmp(dev->dev_terms[2].dterm_attrs, "S"))) + { + drain = &dev->dev_terms[1]; + source = &dev->dev_terms[2]; + } + else + drain = &dev->dev_terms[2]; + } + subnode = dev->dev_subsnode; + + /* Check for minimum number of terminals. */ + + switch(dev->dev_class) + { + case DEV_SUBCKT: + case DEV_RSUBCKT: + case DEV_MSUBCKT: + break; + case DEV_DIODE: + case DEV_PDIODE: + case DEV_NDIODE: + if ((dev->dev_nterm < 2) && (subnode == NULL)) + { + TxError("Diode has only one terminal\n"); + return 0; + } + break; + default: + if (dev->dev_nterm < 2) + { + TxError("Device other than subcircuit has only " + "one terminal\n"); + return 0; + } + break; + } + + /* Original hack for BiCMOS, Tim 10/4/97, is deprecated. */ + /* Use of "device bjt" preferred to "fet" with model="npn". */ + + if (!strcmp(EFDevTypes[dev->dev_type], "npn")) dev->dev_class = DEV_BJT; + + /* For resistor and capacitor classes, set a boolean to */ + /* denote whether the device has a model or not, so we */ + /* don't have to keep doing a string compare on EFDevTypes. */ + + switch(dev->dev_class) + { + case DEV_RES: + case DEV_CAP: + case DEV_CAPREV: + if (dev->dev_nterm < 1) + return 0; + if (dev->dev_type == esNoModelType) + has_model = FALSE; + break; + } + + /* Flag shorted devices---this should probably be an option */ + switch(dev->dev_class) + { + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_FET: + if (source == drain) + { + if (esFormat == NGSPICE) fprintf(esSpiceF, "; "); + fprintf(esSpiceF, "** SOURCE/DRAIN TIED\n"); + } + break; + + default: + if (gate == source) + { + if (esFormat == NGSPICE) fprintf(esSpiceF, "; "); + fprintf(esSpiceF, "** SHORTED DEVICE\n"); + } + break; + } + + /* Generate SPICE device name */ + switch(dev->dev_class) + { + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_FET: + devchar = 'M'; + break; + case DEV_BJT: + devchar = 'Q'; + break; + case DEV_DIODE: + case DEV_NDIODE: + case DEV_PDIODE: + devchar = 'D'; + break; + case DEV_RES: + devchar = 'R'; + break; + case DEV_CAP: + case DEV_CAPREV: + devchar = 'C'; + break; + case DEV_SUBCKT: + case DEV_RSUBCKT: + case DEV_MSUBCKT: + devchar = 'X'; + break; + } + fprintf(esSpiceF, "%c", devchar); + + /* Device index is taken from gate attributes if attached; */ + /* otherwise, the device is numbered in sequence. */ + + if (gate->dterm_attrs) + { + /* Output the name found in the gate attributes */ + /* prefixed by the hierarchical name. */ + fprintf(esSpiceF, "%s%s", EFHNToStr(hierName), gate->dterm_attrs); + } + else + { + switch (dev->dev_class) + { + case DEV_RES: + fprintf(esSpiceF, "%d", esResNum++); + /* For resistor tee networks, use, e.g., */ + /* "R1A" and "R1B", for clarity */ + if (esDoResistorTee) fprintf(esSpiceF, "A"); + break; + case DEV_DIODE: + case DEV_NDIODE: + case DEV_PDIODE: + fprintf(esSpiceF, "%d", esDiodeNum++); + break; + case DEV_CAP: + case DEV_CAPREV: + fprintf(esSpiceF, "%d", esCapNum++); + break; + case DEV_SUBCKT: + case DEV_RSUBCKT: + case DEV_MSUBCKT: + fprintf(esSpiceF, "%d", esSbckNum++); + break; + default: + fprintf(esSpiceF, "%d", esDevNum++); + break; + } + } + /* Order and number of nodes in the output depends on the device class */ + + switch (dev->dev_class) + { + case DEV_BJT: + + /* BJT is "Qnnn collector emitter base model" */ + /* extraction sets collector=subnode, emitter=gate, base=drain */ + + sprintf(name, "fet"); + spcdevOutNode(hierName, subnode->efnode_name->efnn_hier, name, esSpiceF); + spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + + /* fix mixed up drain/source for bjts hace 2/2/99 */ + if (gate->dterm_node->efnode_name->efnn_hier == + source->dterm_node->efnode_name->efnn_hier) + spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + else + spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + spcWriteParams(dev, hierName, scale, l, w, sdM); + break; + + case DEV_MSUBCKT: + + /* MOS-like subcircuit is "Xnnn source gate [drain [sub]]" */ + /* to more conveniently handle cases where MOS devices are */ + /* modeled by subcircuits with the same pin ordering. */ + + spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + + /* Drop through to below (no break statement) */ + + case DEV_SUBCKT: + + /* Subcircuit is "Xnnn gate [source [drain [sub]]]" */ + /* Subcircuit .subckt record must be ordered to match! */ + + spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + + /* Drop through to below (no break statement) */ + + case DEV_RSUBCKT: + /* RC-like subcircuits are exactly like other subcircuits */ + /* except that the "gate" node is treated as an identifier */ + /* only and is not output. */ + + if ((dev->dev_nterm > 1) && (dev->dev_class != DEV_MSUBCKT)) + spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + if (dev->dev_nterm > 2) + spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + + /* The following only applies to DEV_SUBCKT*, which may define as */ + /* many terminal types as it wants. */ + + for (i = 4; i < dev->dev_nterm; i++) + { + drain = &dev->dev_terms[i - 1]; + spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + } + + /* Get the device parameters now, and check if the substrate is */ + /* passed as a parameter rather than as a node. */ + + plist = efGetDeviceParams(EFDevTypes[dev->dev_type]); + for (pptr = plist; pptr != NULL; pptr = pptr->parm_next) + if (pptr->parm_type[0] == 's') + break; + + if ((pptr == NULL) && subnode) + { + fprintf(esSpiceF, " "); + subnodeFlat = spcdevSubstrate(hierName, + subnode->efnode_name->efnn_hier, + dev->dev_type, esSpiceF); + } + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + /* Write all requested parameters to the subcircuit call. */ + + sdM = getCurDevMult(); + spcWriteParams(dev, hierName, scale, l, w, sdM); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + break; + + case DEV_RES: + if (esDoResistorTee) + { + /* There are three ways of handling capacitance */ + /* on resistor networks. One is to ignore it */ + /* (the default; generates "floating" nodes in */ + /* the SPICE output) which is okay for LVS. */ + /* Another way is the Pi network, in which the */ + /* capacitance is split evenly between the */ + /* terminals. Again, the resistor node is left */ + /* floating. The third is the Tee network, in */ + /* which the resistance is split in two parts, */ + /* connecting to a capacitor to ground in the */ + /* middle. This is the best solution but plays */ + /* havoc with LVS. So, the choice is a command */ + /* line option. */ + + esOutputResistor(dev, hierName, scale, gate, source, has_model, + l, w, 2); + fprintf(esSpiceF, "\n%c", devchar); + if (gate->dterm_attrs) + fprintf(esSpiceF, "%s%sB", EFHNToStr(hierName), gate->dterm_attrs); + else + fprintf(esSpiceF, "%dB", esResNum - 1); + esOutputResistor(dev, hierName, scale, gate, drain, has_model, + l, w, 2); + } + else + { + esOutputResistor(dev, hierName, scale, source, drain, has_model, + l, w, 1); + } + break; + + case DEV_DIODE: + case DEV_PDIODE: + + /* Diode is "Dnnn top bottom model" */ + + spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + if (dev->dev_nterm > 1) + spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + else if (subnode) + spcdevOutNode(hierName, subnode->efnode_name->efnn_hier, + name, esSpiceF); + + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + spcWriteParams(dev, hierName, scale, l, w, sdM); + break; + + case DEV_NDIODE: + + /* Diode is "Dnnn bottom top model" */ + + if (dev->dev_nterm > 1) + spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + else if (subnode) + spcdevOutNode(hierName, subnode->efnode_name->efnn_hier, + name, esSpiceF); + spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + spcWriteParams(dev, hierName, scale, l, w, sdM); + break; + + case DEV_CAP: + + /* Capacitor is "Cnnn top bottom value" */ + /* extraction sets top=gate bottom=source */ + /* extracted units are fF; output is in fF */ + + spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + + sdM = getCurDevMult(); + + /* SPICE has two capacitor types. If the "name" (EFDevTypes) is */ + /* "None", the simple capacitor type is used, and a value given. */ + /* If not, the "semiconductor capacitor" is used, and L and W */ + /* and the device name are output. */ + + if (!has_model) + { + fprintf(esSpiceF, " %ffF", (double)sdM * + (double)(dev->dev_cap)); + spcWriteParams(dev, hierName, scale, l, w, sdM); + } + else + { + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + if (esScale < 0) + fprintf(esSpiceF, " w=%g l=%g", w*scale, l*scale); + else + fprintf(esSpiceF, " w=%gu l=%gu", + w * scale * esScale, + l * scale * esScale); + + spcWriteParams(dev, hierName, scale, l, w, sdM); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + } + break; + + case DEV_CAPREV: + + /* Capacitor is "Cnnn bottom top value" */ + /* extraction sets top=source bottom=gate */ + /* extracted units are fF; output is in fF */ + + spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + + sdM = getCurDevMult(); + + /* SPICE has two capacitor types. If the "name" (EFDevTypes) is */ + /* "None", the simple capacitor type is used, and a value given. */ + /* If not, the "semiconductor capacitor" is used, and L and W */ + /* and the device name are output. */ + + if (!has_model) + { + fprintf(esSpiceF, " %ffF", (double)sdM * + (double)(dev->dev_cap)); + spcWriteParams(dev, hierName, scale, l, w, sdM); + } + else + { + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + if (esScale < 0) + fprintf(esSpiceF, " w=%g l=%g", w*scale, l*scale); + else + fprintf(esSpiceF, " w=%gu l=%gu", + w * scale * esScale, + l * scale * esScale); + + spcWriteParams(dev, hierName, scale, l, w, sdM); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + } + break; + + case DEV_FET: + case DEV_MOSFET: + case DEV_ASYMMETRIC: + + /* MOSFET is "Mnnn drain gate source [L=x W=x [attributes]]" */ + + spcdevOutNode(hierName, drain->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + spcdevOutNode(hierName, gate->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + spcdevOutNode(hierName, source->dterm_node->efnode_name->efnn_hier, + name, esSpiceF); + if (subnode) + { + fprintf(esSpiceF, " "); + subnodeFlat = spcdevSubstrate(hierName, + subnode->efnode_name->efnn_hier, + dev->dev_type, esSpiceF); + } + fprintf(esSpiceF, " %s", EFDevTypes[dev->dev_type]); + + /* + * Scale L and W appropriately by the same amount as distance + * values in the transform. The transform will have a scale + * different from 1 only in the case when the scale factors of + * some of the .ext files differed, making it necessary to scale + * all dimensions explicitly instead of having a single scale + * factor at the beginning of the .spice file. + */ + + sdM = getCurDevMult(); + + if (esScale < 0) + fprintf(esSpiceF, " w=%g l=%g", w*scale, l*scale); + else + fprintf(esSpiceF, " w=%gu l=%gu", + w * scale * esScale, + l * scale * esScale); + + spcWriteParams(dev, hierName, scale, l, w, sdM); + if (sdM != 1.0) + fprintf(esSpiceF, " M=%g", sdM); + + /* + * Check controlling attributes and output area and perimeter. + */ + hierS = extHierSDAttr(source); + hierD = extHierSDAttr(drain); + if ( gate->dterm_attrs ) + subAP = Match(ATTR_SUBSAP, gate->dterm_attrs ) ; + + fprintf(esSpiceF, "\n+ "); + if (hierD) + spcnAPHier(drain, hierName, esFetInfo[dev->dev_type].resClassSD, + scale, "ad", "pd", sdM, esSpiceF); + else + { + dnode = SpiceGetNode(hierName, drain->dterm_node->efnode_name->efnn_hier); + spcnAP(dnode, esFetInfo[dev->dev_type].resClassSD, scale, + "ad", "pd", sdM, esSpiceF, w); + } + if (hierS) + spcnAPHier(source, hierName, esFetInfo[dev->dev_type].resClassSD, + scale, "as", "ps", sdM, esSpiceF); + else { + snode= SpiceGetNode(hierName, source->dterm_node->efnode_name->efnn_hier); + spcnAP(snode, esFetInfo[dev->dev_type].resClassSD, scale, + "as", "ps", sdM, esSpiceF, w); + } + if (subAP) + { + fprintf(esSpiceF, " * "); + if (esFetInfo[dev->dev_type].resClassSub < 0) + { + TxError("error: subap for devtype %d unspecified\n", + dev->dev_type); + fprintf(esSpiceF, "asub=0 psub=0"); + } + else if (subnodeFlat) + spcnAP(subnodeFlat, esFetInfo[dev->dev_type].resClassSub, scale, + "asub", "psub", sdM, esSpiceF, -1); + else + fprintf(esSpiceF, "asub=0 psub=0"); + } + + /* Now output attributes, if present */ + if (!esNoAttrs) + { + if (gate->dterm_attrs || source->dterm_attrs || drain->dterm_attrs) + fprintf(esSpiceF,"\n**devattr"); + if (gate->dterm_attrs) + fprintf(esSpiceF, " g=%s", gate->dterm_attrs); + if (source->dterm_attrs) + fprintf(esSpiceF, " s=%s", source->dterm_attrs); + if (drain->dterm_attrs) + fprintf(esSpiceF, " d=%s", drain->dterm_attrs); + } + break; + } + fprintf(esSpiceF, "\n"); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * spcdevSubstrate - + * + * Output the node name of the substrate of a dev. If the suffix is the + * same as the default dont go looking for it just output the default + * (trimmed appropriately). Otherwise look it up .. + * + * Results: + * NULL if not found or the default substrate or the node pointer + * otherwise (might be reused to output area and perimeter of + * the substrate). + * + * Side effects: + * Might allocate the nodeClient for the node through nodeSpiceName. + * + * ---------------------------------------------------------------------------- + */ +EFNode *spcdevSubstrate( prefix, suffix, type, outf) +HierName *prefix, *suffix; +int type; +FILE *outf; +{ + HashEntry *he; + EFNodeName *nn; + char *suf; + + suf = EFHNToStr(suffix); + if (esFetInfo[type].defSubs && strcasecmp(suf,esFetInfo[type].defSubs) == 0) { + esFormatSubs(outf, suf); + return NULL; + } + else { + he = EFHNConcatLook(prefix, suffix, "substrate"); + if (he == NULL) + { + if (outf) + fprintf(outf, "errGnd!"); + return NULL; + } + /* Canonical name */ + nn = (EFNodeName *) HashGetValue(he); + if (outf) + fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier)); + /* Mark node as visited */ + ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + return nn->efnn_node; + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * spcnAP, spcnAPHier -- + * + * Output the area perimeter of the node with type type if it has not + * been visited. + * The spcnAPHier version outputs the area and perimeter only within the + * local subcell with hierarchical name hierName. + * + * Return: + * 0 on success, 1 on error + * + * Side effects: + * Set the visited flags so that the node A/P will not be output multiple + * times + * + * ---------------------------------------------------------------------------- + */ +int spcnAP(node, resClass, scale, asterm, psterm, m, outf, w) + EFNode *node; + int resClass; + float scale, m; + char *asterm, *psterm; + FILE *outf; + int w; +{ + char afmt[15], pfmt[15]; + float dsc; + + if ((node == NULL) || (node->efnode_client == (ClientData)NULL)) + { + TxError("spcnAP: major internal inconsistency\n"); + return 1; + } + + if (esScale < 0) + { + if (asterm) sprintf(afmt, " %s=%%g", asterm); + if (psterm) sprintf(pfmt, " %s=%%g", psterm); + } + else + { + if (asterm) sprintf(afmt, " %s=%%gp", asterm); + if (psterm) sprintf(pfmt, " %s=%%gu", psterm); + } + + if (!esDistrJunct || w == -1) goto oldFmt; + + dsc = w / ((nodeClient*)node->efnode_client)->m_w.widths[resClass]; + if (esScale < 0) + { + if (asterm) + fprintf(outf, afmt, + node->efnode_pa[resClass].pa_area * scale * scale * dsc); + if (psterm) + fprintf(outf, pfmt, + node->efnode_pa[resClass].pa_perim * scale * dsc); + } + else + { + if (asterm) + fprintf(outf, afmt, + ((float)node->efnode_pa[resClass].pa_area * scale * scale) + * esScale * esScale * dsc); + if (psterm) + fprintf(outf, pfmt, + ((float)node->efnode_pa[resClass].pa_perim * scale) + * esScale * dsc); + } + + return 0; + +oldFmt: + if (resClass == NO_RESCLASS || + beenVisited((nodeClient *)node->efnode_client, resClass)) + scale = 0; + else + markVisited((nodeClient *)node->efnode_client, resClass); + + if (esScale < 0) + { + if (asterm) + fprintf(outf, afmt, + node->efnode_pa[resClass].pa_area * scale * scale / m); + if (psterm) + fprintf(outf, pfmt, + node->efnode_pa[resClass].pa_perim * scale / m); + } + else + { + if (asterm) + fprintf(outf, afmt, + ((float)node->efnode_pa[resClass].pa_area * scale * scale) + * esScale * esScale); + if (psterm) + fprintf(outf, pfmt, + ((float)node->efnode_pa[resClass].pa_perim * scale) + * esScale); + } + return 0; +} + +int spcnAPHier(dterm, hierName, resClass, scale, asterm, psterm, m, outf) + DevTerm *dterm; + HierName *hierName; + int resClass; + float scale, m; + char *asterm, *psterm; + FILE *outf; +{ + EFNode *node = dterm->dterm_node; + nodeClientHier *nc; + char afmt[15], pfmt[15]; + + if (esScale < 0) + { + sprintf(afmt," %s=%%g", asterm); + sprintf(pfmt," %s=%%g", psterm); + } + else + { + sprintf(afmt," %s=%%gp", asterm); + sprintf(pfmt," %s=%%gu", psterm); + } + if (node->efnode_client == (ClientData) NULL) + initNodeClientHier(node); + + nc = (nodeClientHier *)node->efnode_client; + if (nc->lastPrefix != hierName) + { + clearVisited(nc); + nc->lastPrefix = hierName; + } + if (resClass == NO_RESCLASS || + beenVisited((nodeClientHier *)node->efnode_client, resClass) ) + scale = 0.0; + else + markVisited((nodeClientHier *)node->efnode_client, resClass); + + if (esScale < 0) + { + fprintf(outf, afmt, + node->efnode_pa[resClass].pa_area * scale * scale / m); + fprintf(outf, pfmt, + node->efnode_pa[resClass].pa_perim * scale / m); + } + else + { + fprintf(outf, afmt, + ((float)node->efnode_pa[resClass].pa_area * scale) + * esScale * esScale); + fprintf(outf, pfmt, + ((float)node->efnode_pa[resClass].pa_perim * scale) + * esScale); + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * spcdevOutNode -- + * + * Output the name of the node whose hierarchical prefix down to this + * point is 'prefix' and whose name from the end of suffix down to the + * leaves is 'suffix', just as in the arguments to EFHNConcat(). + * + * + * Results: + * Return number of characters printed on success, 0 on error. + * + * Side effects: + * Writes to the file 'outf'. + * Sets the efnode_client field as described above. + * + * ---------------------------------------------------------------------------- + */ + +int +spcdevOutNode(prefix, suffix, name, outf) + HierName *prefix; + HierName *suffix; + char *name; + FILE *outf; +{ + HashEntry *he; + EFNodeName *nn; + char *nname; + + he = EFHNConcatLook(prefix, suffix, name); + if (he == NULL) + { + fprintf(outf, " errGnd!"); + return 0; + } + nn = (EFNodeName *) HashGetValue(he); + nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier); + fprintf(outf, " %s", nname); + /* Mark node as visited */ + ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + return (1 + strlen(nname)); +} + + +/* + * ---------------------------------------------------------------------------- + * + * spccapVisit -- + * + * Procedure to output a single capacitor to the .spice file. + * Called by EFVisitCaps(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the file esSpiceF. Increments esCapNum. + * + * Format of a .spice cap line: + * + * C%d node1 node2 cap + * + * where + * node1, node2 are the terminals of the capacitor + * cap is the capacitance in femtofarads (NOT attofarads). + * + * ---------------------------------------------------------------------------- + */ + +int +spccapVisit(hierName1, hierName2, cap) + HierName *hierName1; + HierName *hierName2; + double cap; +{ + cap = cap / 1000; + if (cap <= EFCapThreshold) + return 0; + + fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1), + nodeSpiceName(hierName2), cap); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * spcresistVisit -- + * + * Procedure to output a single resistor to the .spice file. + * Called by EFVisitResists(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the file esSpiceF. Increments esResNum. + * + * Format of a .spice resistor line: + * + * R%d node1 node2 res + * + * where + * node1, node2 are the terminals of the resistor + * res is the resistance in ohms (NOT milliohms) + * + * + * ---------------------------------------------------------------------------- + */ +int +spcresistVisit(hierName1, hierName2, res) + HierName *hierName1; + HierName *hierName2; + float res; +{ + fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1), + nodeSpiceName(hierName2), res / 1000.); + + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * spcsubVisit -- + * + * Routine to find the node that connects to substrate. Copy the + * string name of this node into "resstr" to be returned to the + * caller. + * + * Results: + * Return 1 if the substrate node has been found, to stop the search. + * Otherwise return 0 to keep the search going. + * + * ---------------------------------------------------------------------------- + */ + +int +spcsubVisit(node, res, cap, resstr) + EFNode *node; + int res; // Unused + double cap; // Unused + char **resstr; +{ + HierName *hierName; + char *nsn; + + if (node->efnode_flags & EF_SUBS_NODE) + { + hierName = (HierName *) node->efnode_name->efnn_hier; + nsn = nodeSpiceName(hierName); + *resstr = StrDup((char **)NULL, nsn); + return 1; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * spcnodeVisit -- + * + * Procedure to output a single node to the .spice file along with its + * attributes and its dictionary (if present). Called by EFVisitNodes(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * Writes to the files esSpiceF + * + * ---------------------------------------------------------------------------- + */ + +int +spcnodeVisit(node, res, cap) + EFNode *node; + int res; + double cap; +{ + EFNodeName *nn; + HierName *hierName; + bool isConnected = FALSE; + char *fmt, *nsn; + EFAttr *ap; + + if (node->efnode_client) + { + isConnected = (esDistrJunct) ? + (((nodeClient *)node->efnode_client)->m_w.widths != NULL) : + ((((nodeClient *)node->efnode_client)->m_w.visitMask + & DEV_CONNECT_MASK) != 0); + } + if (!isConnected && esDevNodesOnly) + return 0; + + /* Don't mark known ports as "FLOATING" nodes */ + if (!isConnected && node->efnode_flags & EF_PORT) isConnected = TRUE; + + hierName = (HierName *) node->efnode_name->efnn_hier; + nsn = nodeSpiceName(hierName); + + if (esFormat == SPICE2 || esFormat == HSPICE && strncmp(nsn, "z@", 2)==0 ) { + static char ntmp[MAX_STR_SIZE]; + + EFHNSprintf(ntmp, hierName); + if (esFormat == NGSPICE) fprintf(esSpiceF, "; "); + fprintf(esSpiceF, "** %s == %s\n", ntmp, nsn); + } + cap = cap / 1000; + if (cap > EFCapThreshold) + { + fprintf(esSpiceF, esSpiceCapFormat, esCapNum++, nsn, cap, + (isConnected) ? "\n" : + (esFormat == NGSPICE) ? " ; **FLOATING\n" : + " **FLOATING\n"); + } + if (node->efnode_attrs && !esNoAttrs) + { + if (esFormat == NGSPICE) fprintf(esSpiceF, " ; "); + fprintf(esSpiceF, "**nodeattr %s :",nsn ); + for (fmt = " %s", ap = node->efnode_attrs; ap; ap = ap->efa_next) + { + fprintf(esSpiceF, fmt, ap->efa_text); + fmt = ",%s"; + } + putc('\n', esSpiceF); + } + + return 0; +} + +/* a debugging procedure */ +int +nodeVisitDebug(node, res, cap) + EFNode *node; + int res; + double cap; +{ + EFNodeName *nn; + HierName *hierName; + char *fmt, *nsn; + EFAttr *ap; + + hierName = (HierName *) node->efnode_name->efnn_hier; + nsn = nodeSpiceName(hierName); + TxError("** %s (%x)\n", nsn, node); + + printf("\t client.name=%s, client.m_w=%p\n", + ((nodeClient *)node->efnode_client)->spiceNodeName, + ((nodeClient *)node->efnode_client)->m_w.widths); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * nodeSpiceName -- + * Find the real spice name for the node with hierarchical name hname. + * SPICE2 ==> numeric + * SPICE3 ==> full magic path + * HSPICE ==> less than 15 characters long + * + * Results: + * Returns the spice node name. + * + * Side effects: + * Allocates nodeClients for the node. + * + * ---------------------------------------------------------------------------- + */ +static char esTempName[MAX_STR_SIZE]; + +char *nodeSpiceName(hname) + HierName *hname; +{ + EFNodeName *nn; + HashEntry *he; + EFNode *node; + + he = EFHNLook(hname, (char *) NULL, "nodeName"); + if ( he == NULL ) + return "errGnd!"; + nn = (EFNodeName *) HashGetValue(he); + node = nn->efnn_node; + + if ( (nodeClient *) (node->efnode_client) == NULL ) { + initNodeClient(node); + goto makeName; + } else if ( ((nodeClient *) (node->efnode_client))->spiceNodeName == NULL) + goto makeName; + else goto retName; + + +makeName: + if ( esFormat == SPICE2 ) + sprintf(esTempName, "%d", esNodeNum++); + else { + EFHNSprintf(esTempName, node->efnode_name->efnn_hier); + if ( esFormat == HSPICE ) /* more processing */ + nodeHspiceName(esTempName); + } + ((nodeClient *) (node->efnode_client))->spiceNodeName = + StrDup(NULL, esTempName); + +retName: + return ((nodeClient *) (node->efnode_client))->spiceNodeName; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHNSprintf -- + * + * Create a hierarchical node name. + * The flags in EFTrimFlags control whether global (!) or local (#) + * suffixes are to be trimmed. Also substitutes \. with \@ if the + * format is hspice. + * + * Results: + * None. + * + * Side effects: + * Changes the area pointed to by str + * + * ---------------------------------------------------------------------------- + */ + +int +EFHNSprintf(str, hierName) + char *str; + HierName *hierName; +{ + bool trimGlob, trimLocal, convertComma, convertEqual; + char *s, *cp, c; + char *efHNSprintfPrefix(HierName *, char *); + + s = str; + if (hierName->hn_parent) str = efHNSprintfPrefix(hierName->hn_parent, str); + if (EFTrimFlags) + { + cp = hierName->hn_name; + trimGlob = (EFTrimFlags & EF_TRIMGLOB); + trimLocal = (EFTrimFlags & EF_TRIMLOCAL); + convertComma = (EFTrimFlags & EF_CONVERTCOMMAS); + convertEqual = (EFTrimFlags & EF_CONVERTEQUAL); + while (c = *cp++) + { + switch (c) + { + case '!': if (!trimGlob) *str++ = c; break; + case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break; + case '=': if (convertEqual) *str++ = ':'; break; + case ',': if (convertComma) *str++ = ';'; break; + case '#': if (trimLocal) break; // else fall through + default: *str++ = c; break; + } + } + *str++ = '\0'; + } + else strcpy(str, hierName->hn_name); + return 0; +} + +char *efHNSprintfPrefix(hierName, str) + HierName *hierName; + char *str; +{ + char *cp, c; + bool convertEqual = (EFTrimFlags & EF_CONVERTEQUAL) ? TRUE : FALSE; + + if (hierName->hn_parent) + str = efHNSprintfPrefix(hierName->hn_parent, str); + + cp = hierName->hn_name; + while (1) { + if (convertEqual && (*cp == '=')) + *str = ':'; + else + *str = *cp; + if (!(*str)) break; + str++; + cp++; + } + *str = '/'; + return ++str; +} + +/* + * ---------------------------------------------------------------------------- + * + * nodeHspiceName -- + * + * Convert the hierarchical node name used in Berkeley spice + * to a name understodd by hspice and hopefully by the user. + * + * Results: + * A somewhat meaningfull node name + * + * Side effects: + * Mucks with the hash table above. + * + * ---------------------------------------------------------------------------- + */ + +int nodeHspiceName(s) + char *s; +{ + char *p, *sf; + int l, snum = -1; + HashEntry *he; + static char map[MAX_STR_SIZE]; + + /* + * find the suffix + */ + l = strlen(s); + for (p = s + l; (p > s) && *p != '/'; p--); + if (p == s) + { + strcpy(map, s); + goto topLevel; + } + + /* + * break it into prefix '/0' suffix + */ + if (*p == '/') + *p = 0; + sf = p + 1; + + /* + * look up prefix in the hash table ad create it if doesnt exist + */ + if ((he = HashLookOnly(&subcktNameTable, s)) == NULL) + { + snum = esSbckNum++; + he = HashFind(&subcktNameTable, s); + HashSetValue(he, (ClientData)(pointertype) snum); +#ifndef UNSORTED_SUBCKT + DQPushRear(&subcktNameQueue, he); +#endif + } + else + snum = (spointertype) HashGetValue(he); + sprintf(map, "x%d/%s", snum, sf); + +topLevel: + strcpy(s, map); + if (strlen(s) > 15) + { + /* still hspice does not get it */ + sprintf(s, "z@%d", esNodeNum++); + if (strlen(s) > 15) + { + /* screw it: hspice will not work */ + TxError("Error: too many nodes in this circuit to be " + "output as names\n"); + TxError(" use spice2 format or call and complain " + "to Meta software about their stupid parser\n"); +#ifdef MAGIC_WRAPPER + return TCL_ERROR; +#else + exit(1); +#endif + } + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * printSubcktDict -- + * + * Print out the hspice subcircuit dictionary. Ideally this should go to a + * pa0 file but uncfortunately hspice crashes if the node names contain + * dots so we just append it at the end of the spice file + * + * Results: + * None. + * + * Side effects: + * Writes to the output file + * + * ---------------------------------------------------------------------------- + */ + +int printSubcktDict() +{ + HashSearch hs; + HashEntry *he; + + fprintf(esSpiceF,"\n** hspice subcircuit dictionary\n"); + +#ifndef UNSORTED_SUBCKT + while ((he = (HashEntry *)DQPopFront(&subcktNameQueue)) != NULL) +#else + HashStartSearch(&hs); + while ((he = HashNext(&subcktNameTable, &hs)) != NULL) +#endif + fprintf(esSpiceF,"* x%"DLONG_PREFIX"d\t%s\n", (dlong) HashGetValue(he), he->h_key.h_name); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * mkDevMerge -- + * Create a new devMerge structure. + * + * Results: + * Obvious + * + * Side effects: + * Allocates memory and sets the fields of the structure. + * + * ---------------------------------------------------------------------------- + */ + +devMerge *mkDevMerge(l, w, g, s, d, b, hn, dev) + float l, w; + EFNode *g, *s, *d, *b; + HierName *hn; + Dev *dev; +{ + devMerge *fp; + + fp = (devMerge *) mallocMagic((unsigned) (sizeof(devMerge))); + fp->l = l; fp->w = w; + fp->g = g; fp->s = s; + fp->d = d; fp->b = b; + fp->dev = dev; + fp->esFMIndex = esFMIndex; + fp->hierName = hn; + fp->next = NULL; + addDevMult(1.0); + + return fp; +} + +/* + * ---------------------------------------------------------------------------- + * + * parallelDevs -- + * + * Determine if two devs are in parallel + * + * Results: + * NOT_PARALLEL if not in parallel + * PARALLEL if parallel and an exact match + * ANTIPARALLEL if parallel but reversed source<->drain nodes + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +parallelDevs(f1, f2) + devMerge *f1, *f2; +{ + /* If the devices are not in the same class, then */ + /* they cannot be parallel. */ + + if (f1->dev->dev_class != f2->dev->dev_class) + return NOT_PARALLEL; + + /* Can't merge devices with different models */ + if (f1->dev->dev_type != f2->dev->dev_type) + return NOT_PARALLEL; + + /* Class-dependent action */ + switch(f1->dev->dev_class) + { + case DEV_MSUBCKT: + case DEV_MOSFET: + case DEV_FET: + + if (f1->b != f2->b) return NOT_PARALLEL; + if ((f1->g == f2->g) && (f1->l == f2->l) + && (esMergeDevsA || (f1->w == f2->w))) + { + if ((f1->d == f2->d) && (f1->s == f2->s)) + return PARALLEL; + else if ((f1->s == f2->d) && (f1->d == f2->s)) + return ANTIPARALLEL; + } + break; + + case DEV_ASYMMETRIC: + + if (f1->b != f2->b) return NOT_PARALLEL; + if ((f1->g == f2->g) && (f1->d == f2->d) && (f1->s == f2->s) + && (f1->l == f2->l) && (esMergeDevsA || (f1->w == f2->w))) + { + return PARALLEL; + } + break; + + /* Capacitors match if top ("gate") and bottom ("source") are */ + /* the same. Do not attempt to swap top and bottom, as we do */ + /* not know when it is safe to do so. */ + + case DEV_CAP: + case DEV_CAPREV: + if ((f1->g != f2->g) || (f1->s != f2->s)) + return NOT_PARALLEL; + + else if (f1->dev->dev_type == esNoModelType) + { + /* Unmodeled capacitor */ + if (esMergeDevsA || (f1->dev->dev_cap == f2->dev->dev_cap)) + return PARALLEL; + } + else if (esMergeDevsA || ((f1->l == f2->l) && (f1->w == f2->w))) + return PARALLEL; + break; + + /* We can't merge resistors because we accumulate capacitance */ + /* on the central ("gate") node. Merging the devices would */ + /* cause nodes to disappear. */ + + case DEV_RES: + break; + + /* For the remaining devices, it might be possible to merge */ + /* if we know that the device model level accepts length and */ + /* width parameters. However, at this time, no such */ + /* information is passed to the SPICE deck, so we don't try to */ + /* merge these devices. */ + + case DEV_BJT: + case DEV_DIODE: + case DEV_NDIODE: + case DEV_PDIODE: + break; + + /* There is no way to merge subcircuit devices */ + + case DEV_SUBCKT: + case DEV_RSUBCKT: + break; + } + return NOT_PARALLEL; +} + +/* + * ---------------------------------------------------------------------------- + * + * mergeAttr -- + * + * merge two attribute strings + * + * Results: + * The merged strings + * + * Side effects: + * Might allocate and free memory. + * + * ---------------------------------------------------------------------------- + */ + +void +mergeAttr(a1, a2) + char **a1, **a2; +{ + if (*a1 == NULL) + *a1 = *a2; + else + { + char *t; + int l1 = strlen(*a1); + int l2 = strlen(*a2); + t = (char *) mallocMagic((unsigned int)((l1 + l2) + 1)); + t = (char *) strcat(*a1, *a2); + freeMagic(*a1); + *a1 = t; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * devMergeVisit -- + * Visits each dev throu EFVisitDevs and finds if it is in parallel with + * any previously visited dev. + * + * Results: + * 0 always to keep the caller going. + * + * Side effects: + * Numerous. + * + * ---------------------------------------------------------------------------- + */ + +int +devMergeVisit(dev, hierName, scale, trans) + Dev *dev; /* Dev to examine */ + HierName *hierName; /* Hierarchical path down to this dev */ + float scale; /* Scale transform */ + Transform *trans; /* (unused) */ +{ + DevTerm *gate, *source, *drain; + Dev *cf; + DevTerm *cg, *cs, *cd; + EFNode *subnode, *snode, *dnode, *gnode; + int pmode, l, w; + bool hS, hD, chS, chD; + devMerge *fp, *cfp; + float m; + + if (esDistrJunct) + devDistJunctVisit(dev, hierName, scale, trans); + + if (dev->dev_nterm < 2) + { + TxError("outPremature\n"); + return 0; + } + + gate = &dev->dev_terms[0]; + if (dev->dev_nterm >= 2) + source = drain = &dev->dev_terms[1]; + if (dev->dev_nterm >= 3) + drain = &dev->dev_terms[2]; + + gnode = SpiceGetNode(hierName, gate->dterm_node->efnode_name->efnn_hier); + if (dev->dev_nterm >= 2) + { + snode = SpiceGetNode(hierName, source->dterm_node->efnode_name->efnn_hier); + dnode = SpiceGetNode(hierName, drain->dterm_node->efnode_name->efnn_hier); + } + if (dev->dev_subsnode) + subnode = spcdevSubstrate(hierName, + dev->dev_subsnode->efnode_name->efnn_hier, + dev->dev_type, NULL); + else + subnode = NULL; + + /* Get length and width of the device */ + EFGetLengthAndWidth(dev, &l, &w); + + fp = mkDevMerge((float)((float)l * scale), (float)((float)w * scale), + gnode, snode, dnode, subnode, hierName, dev); + hS = extHierSDAttr(source); + hD = extHierSDAttr(drain); + + /* + * run the list of devs. compare the current one with + * each one in the list. if they fullfill the matching requirements + * merge them only if: + * 1) they have both apf S, D attributes + * or + * 2) one of them has aph S, D attributes and they have the same + * hierarchical prefix + * If one of them has apf and the other aph print a warning. + */ + + for (cfp = devMergeList; cfp != NULL; cfp = cfp->next) + { + if ((pmode = parallelDevs(fp, cfp)) != NOT_PARALLEL) + { + cf = cfp->dev; + cg = &cfp->dev->dev_terms[0]; + cs = cd = &cfp->dev->dev_terms[1]; + if (cfp->dev->dev_nterm >= 3) + { + if (pmode == PARALLEL) + cd = &cfp->dev->dev_terms[2]; + else if (pmode == ANTIPARALLEL) + cs = &cfp->dev->dev_terms[2]; + } + + chS = extHierSDAttr(cs); chD = extHierSDAttr(cd); + if (!(chS || chD || hS || hD)) /* all flat S, D */ + goto mergeThem; + if (cfp->hierName != hierName && + ((chS && !hS) || (chD && !hD) || + (!chS && hS) || (!chD && hD))) + { + + efHNSprintfPrefix((cfp->hierName)?cfp->hierName:hierName, + esTempName); + TxError("Warning: conflicting SD attributes of parallel" + " devs in cell: %s\n", esTempName); + break; + } + else if (cfp->hierName == hierName) + { + if (hS && !chS) + { + mergeAttr(&cs->dterm_attrs, &source->dterm_attrs); + } + if (hD && !chD) + { + mergeAttr(&cd->dterm_attrs, &drain->dterm_attrs); + } + } + else /* cfp->hierName != hierName */ + break; +mergeThem: + switch(dev->dev_class) + { + case DEV_MSUBCKT: + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_FET: + m = esFMult[cfp->esFMIndex] + (fp->w / cfp->w); + break; + case DEV_RSUBCKT: + case DEV_RES: + if (fp->dev->dev_type == esNoModelType) + m = esFMult[cfp->esFMIndex] + (fp->dev->dev_res + / cfp->dev->dev_res); + else + m = esFMult[cfp->esFMIndex] + (fp->l / cfp->l); + break; + case DEV_CAP: + case DEV_CAPREV: + if (fp->dev->dev_type == esNoModelType) + m = esFMult[cfp->esFMIndex] + (fp->dev->dev_cap + / cfp->dev->dev_cap); + else + m = esFMult[cfp->esFMIndex] + + ((fp->l * fp->w) / (cfp->l * cfp->w)); + break; + } + setDevMult(fp->esFMIndex, DEV_KILLED); + setDevMult(cfp->esFMIndex, m); + esSpiceDevsMerged++; + /* Need to do attribute stuff here */ + freeMagic(fp); + return 0; + } + } + + /* No parallel devs to it yet */ + fp->next = devMergeList; + devMergeList = fp; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * update_w -- + * Updates the width client of node n with the current dev width + * + * Results: + * N/A + * + * Side effects: + * might allocate node client and widths + * + * ---------------------------------------------------------------------------- + */ + +int +update_w(resClass, w, n) + short resClass; + int w; + EFNode *n; +{ + nodeClient *nc; + int i; + + if (n->efnode_client == (ClientData)NULL) + initNodeClient(n); + nc = (nodeClient *) n->efnode_client; + if (nc->m_w.widths == NULL) + { + (nc->m_w.widths) = (float *)mallocMagic((unsigned)sizeof(float) + * efNumResistClasses); + for (i = 0; i < EFDevNumTypes; i++) + nc->m_w.widths[i] = 0.0; + } + nc->m_w.widths[resClass] += (float)w; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * devDistJunctVisit -- + * Called for every dev and updates the nodeclients of its terminals + * + * Results: + * 0 to keep the calling procedure going + * + * Side effects: + * calls update_w which might allocate stuff + * + * ---------------------------------------------------------------------------- + */ + +int +devDistJunctVisit(dev, hierName, scale, trans) + Dev *dev; /* Dev to examine */ + HierName *hierName; /* Hierarchical path down to this dev */ + float scale; /* Scale transform */ + Transform *trans; /* (unused) */ +{ + EFNode *n; + int i; + int l, w; + + if (dev->dev_nterm < 2) + { + TxError("outPremature\n"); + return 0; + } + + w = (int)((float)w * scale); + EFGetLengthAndWidth(dev, &l, &w); + + for (i = 1; idev_nterm; i++) + { + n = SpiceGetNode(hierName, + dev->dev_terms[i].dterm_node->efnode_name->efnn_hier); + update_w(esFetInfo[dev->dev_type].resClassSD, w, n); + } + return 0; +} + diff --git a/ext2spice/ext2spice.h b/ext2spice/ext2spice.h new file mode 100644 index 00000000..66302022 --- /dev/null +++ b/ext2spice/ext2spice.h @@ -0,0 +1,205 @@ +/* + * ext2spice.h -- + * Definitions for ext2spice.c and ext2hier.c + */ + +#ifndef _EXTTOSPICE_H +#define _EXTTOSPICE_H + +/* cache list used to find parallel devs */ +typedef struct _devMerge { + float l, w; + EFNode *g, *s, *d, *b; + Dev * dev; + int esFMIndex; + HierName *hierName; + struct _devMerge *next; +} devMerge; + +/* Forward declarations */ +#ifdef MAGIC_WRAPPER +void CmdExtToSpice(); +#endif +extern int spcmainArgs(); +extern int spccapVisit(), spcdevVisit(), spcnodeVisit(), subcktVisit(); +extern int spcresistVisit(), devMergeVisit(), devDistJunctVisit(); +extern int spcsubVisit(); +extern int subcktUndef(); +extern EFNode *spcdevSubstrate(); +extern char *nodeSpiceName(); +extern int nodeVisitDebug(); +extern void topVisit(); +extern int _ext2spice_start(); + +extern EFNode *spcdevHierSubstrate(); +extern char *nodeSpiceHierName(); +extern devMerge *mkDevMerge(); +extern bool extHierSDAttr(); + +/* Options specific to ext2spice */ +extern bool esDoExtResis; +extern bool esDoPorts; +extern bool esDoHierarchy; +extern bool esDoResistorTee; +extern int esDoSubckt; +extern bool esDevNodesOnly; +extern bool esNoAttrs; +extern bool esHierAP; +extern char spcesDefaultOut[FNSIZE]; +extern int esCapAccuracy; +extern char esSpiceCapFormat[FNSIZE]; +extern char *spcesOutName; +extern FILE *esSpiceF; +extern float esScale; /* negative if hspice the EFScale/100 otherwise */ + +extern unsigned short esFormat; +extern unsigned long initMask; + +extern int esCapNum, esDevNum, esResNum, esDiodeNum; +extern int esNodeNum; /* just in case we're extracting spice2 */ +extern int esSbckNum; /* used in hspice node name shortening */ +extern int esNoModelType; /* index for device type "None" (model-less device) */ + +extern bool esMergeDevsA; /* aggressive merging of devs L1=L2 merge them */ +extern bool esMergeDevsC; /* conservative merging of devs L1=L2 and W1=W2 */ + /* used with the hspice multiplier */ +extern bool esDistrJunct; + +extern float *esFMult; /* the array itself */ +extern int esFMIndex; /* current index to it */ +extern int esFMSize; /* its current size (growable) */ + +extern int esSpiceDevsMerged; +extern devMerge *devMergeList; + +/* + * The following hash table and associated functions are used only if + * the format is hspice, to keep the translation between the hierarchical + * prefix of a node and the x num that we use to output valid hspice + * which also are meaningful. + */ +extern HashTable subcktNameTable ; /* the hash table itself */ +extern DQueue subcktNameQueue ; /* q used to print it sorted at the end*/ + + +typedef struct { + short resClassSD ; /* the resistance class of the src/drn of the dev */ + short resClassSub ; /* the resistance class of the substrate of the dev */ + char *defSubs ; /* the default substrate node */ +} fetInfoList; + +extern fetInfoList esFetInfo[MAXDEVTYPES]; + +#define MAX_STR_SIZE (1<<11) /* 2K should be enough for keeping temp + names even of the most complicated design */ + +/* Node clients for figuring out areas and perimeters of sources and drains */ +typedef struct { + long _duml:MAXDEVTYPES; +} _dum; /* if you get an error here you should change + the data structures and visitMask */ + +typedef union { + long visitMask; /* mask for normal visits */ + float *widths; /* width used for distributing area perim */ +} maskOrWidth ; + +typedef struct { + char *spiceNodeName; + maskOrWidth m_w; +} nodeClient; + +typedef struct { + HierName *lastPrefix; + maskOrWidth m_w; +} nodeClientHier; + +#define NO_RESCLASS -1 + +#define markVisited(client, rclass) \ + { (client)->m_w.visitMask |= (1<m_w.visitMask = (long)0; } + +#define beenVisited(client, rclass) \ + ( (client)->m_w.visitMask & (1<efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \ + (( nodeClient *)(node)->efnode_client)->spiceNodeName = NULL; \ + (( nodeClient *)(node)->efnode_client)->m_w.visitMask = (unsigned long)initMask; \ +} + + +#define initNodeClientHier(node) \ +{ \ + (node)->efnode_client = (ClientData) mallocMagic((unsigned)(sizeof(nodeClientHier))); \ + ((nodeClientHier *) (node)->efnode_client)->m_w.visitMask = (unsigned long) 0; \ +} + + + +/* attributes controlling the Area/Perimeter extraction of dev terminals */ +#define ATTR_FLATAP "*[Ee][Xx][Tt]:[Aa][Pp][Ff]*" +#define ATTR_HIERAP "*[Ee][Xx][Tt]:[Aa][Pp][Hh]*" +#define ATTR_SUBSAP "*[Ee][Xx][Tt]:[Aa][Pp][Ss]*" + +#define SPICE2 0 +#define SPICE3 1 +#define HSPICE 2 +#define NGSPICE 3 + +#define AUTO 2 /* TRUE | FALSE | AUTO for esDoSubckt */ + +#define NOT_PARALLEL 0 +#define PARALLEL 1 +#define ANTIPARALLEL 2 + +/* + *--------------------------------------------------------- + * Variables & macros used for merging parallel devs + * The merging of devs is based on the fact that spcdevVisit + * visits the devs in the same order all the time so the + * value of esFMult[i] keeps the multiplier for the ith dev + *--------------------------------------------------------- + */ +#define DEV_KILLED ((float) -1.0) +#define FMULT_SIZE (1<<10) + +#define devIsKilled(n) ( esFMult[(n)] <=(float)0.0 ) + +#define DEV_KILLED ((float) -1.0) + + +/* macro to add a dev's multiplier to the table and grow it if necessary */ +#define addDevMult(f) \ +{ \ + if ( esFMult == NULL ) { \ + esFMult = (float *) mallocMagic((unsigned) (esFMSize*sizeof(float))); \ + } else if ( esFMIndex >= esFMSize ) { \ + int i; \ + float *op = esFMult ; \ + esFMult = (float *) mallocMagic((unsigned) ((esFMSize = esFMSize*2)*sizeof(float))); \ + for ( i = 0 ; i < esFMSize/2 ; i++ ) esFMult[i] = op[i]; \ + if (op) freeMagic(op); \ + } \ + esFMult[esFMIndex++] = (float)(f); \ +} + +#define setDevMult(i,f) { esFMult[(i)] = (float)(f); } + +#define getCurDevMult() ((esFMult && (esFMIndex > 0)) ? esFMult[esFMIndex-1] : (float)1.0) + +#ifdef MAGIC_WRAPPER +#define atoCap(s) ((EFCapValue)atof(s)) +#endif + +#endif /* _EXTTOSPICE_H */ diff --git a/ext2spice/spice2sim b/ext2spice/spice2sim new file mode 100755 index 00000000..2ea85f7f --- /dev/null +++ b/ext2spice/spice2sim @@ -0,0 +1,81 @@ +#!/bin/awk -f +# convert an ext2spice produced file to a .sim file for debugging +# +BEGIN { + firstLine = 1 ; gotScale = 0; firstFet = 1; + scale = 100; +} + +firstLine == 1 { + if ( firstLine ) { + style = $2 ; firstLine = 0; + if ( style != "HSPICE" && style != "SPICE2" && style != "SPICE3" ) { + print "weird spice style assuming SPICE3" | "cat 1>&2" + } + if ( style == "HSPICE" ) scale = -100; + } +} + +$1 ~ /^\.opt/ && $2 ~ /^scale/ { + if ( style != "HSPICE" ) { + print "ERROR: scale found in a non HSPICE file\n" | "cat 1>&2" + exit; + } + l = length($2)-7; + scale = (substr($2, 7, l))*100; +} + + +$1 ~ /^[m|M]/ { + if ( firstFet ) { + firstFet = 0; + if ( style == "HSPICE" && scale < 0 ) { + print "ERROR: scale not fount in HSPICE file\n"| "cat 1>&2" + exit; + } + printf "| units: %d tech: spice2sim format: MIT\n", scale + scale = scale/100; + } + sl = $8; sw = $7; + ll = length(sl); + lw = length(sw); + if ( style != "HSPICE" ) { + if (substr(sw, lw, 1)!= "u" || substr(sl, ll, 1) != "u") { + print "ERROR: weird units in w/l of fet:\n", $0 | "cat 1>&2" + exit; + } + l = substr(sl, 3, ll-3); + w = substr(sw, 3, lw-3); + } else { # HSPICE + l = substr(sl, 3, ll-2); + w = substr(sw, 3, lw-2); + if ( NF == 9 ) { # get the mult + if ( substr($9, 1, 2) != "M=" ) { + printf "ERROR - weird multiplier : %s\n", $0; + } else w = w * (substr($9, 3, 100)+1.0-1.0); + } + } + printf "%s %s %s %s %.2f %.2f\n", substr($6,1,1), $3, $2, $4, l, w; +} + +$1 ~ /^[c|C]/ { + if ( $4 ~ /[0-9]*fF/ ) + printf "C %s %s %s\n", $2, $3, substr($4, 1, length($4)-2); + else + printf "ERROR - weird capacitor: %s\n", $0; + } +$1 ~ /^[R|R]/ { + if ( $4 ~ /^[0-9]*/ ) + printf "r %s %s %s\n", $2, $3, $4; + else + printf "ERROR - weird resistor: %s\n", $0; + } + +$1 ~ /^[q|Q]/ { + print "ERROR: found a bipolar in spice file" | "cat 1>&2" + } + +$1 ~ /^[v|V]/ { + print "ERROR: found a voltage source in spice file" | "cat 1>&2" + } + diff --git a/extcheck/Depend b/extcheck/Depend new file mode 100644 index 00000000..9cba00af --- /dev/null +++ b/extcheck/Depend @@ -0,0 +1,3 @@ +extcheck.o: extcheck.c ../utils/magic.h ../utils/paths.h \ + ../utils/geometry.h ../utils/hash.h ../utils/utils.h \ + ../utils/pathvisit.h ../extflat/extflat.h ../utils/runstats.h diff --git a/extcheck/Makefile b/extcheck/Makefile new file mode 100644 index 00000000..64d8888d --- /dev/null +++ b/extcheck/Makefile @@ -0,0 +1,22 @@ +# +# rcsid "$Header: /usr/cvsroot/magic-8.0/extcheck/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" +# + +MODULE = extcheck +MAGICDIR = .. +SRCS = extcheck.c + +EXTRA_LIBS = ${MAGICDIR}/extflat/libextflat.o ${MAGICDIR}/utils/libutils.a + +include ${MAGICDIR}/defs.mak + +LIBS += -lm + +main: extcheck + +install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} + +install-tcl: + echo "Nothing to do here" + +include ${MAGICDIR}/rules.mak diff --git a/extcheck/extcheck.c b/extcheck/extcheck.c new file mode 100644 index 00000000..b8aa6241 --- /dev/null +++ b/extcheck/extcheck.c @@ -0,0 +1,173 @@ +/* + * extcheck.c -- + * + * Program to check .ext files for consistency without producing + * any output. Checks for disconnected global nodes as well as + * for version consistency. Counts the number of interesting + * things in the circuit (devices, capacitors, resistors, nodes). + * + * Flattens the tree rooted at file.ext, reading in additional .ext + * files as specified by "use" lines in file.ext. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] = "$Header: /usr/cvsroot/magic-8.0/extcheck/extcheck.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/paths.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/utils.h" +#include "utils/pathvisit.h" +#include "extflat/extflat.h" +#include "utils/runstats.h" + +int ecNumDevs; +int ecNumCaps; +int ecNumResists; +int ecNumThreshCaps; +int ecNumThreshResists; +int ecNumNodes; +int ecNumGlobalNodes; +int ecNumNodeCaps; +int ecNumNodeResists; + +/* Forward declarations */ +int nodeVisit(), devVisit(), capVisit(), resistVisit(); + +/* + * ---------------------------------------------------------------------------- + * + * main -- + * + * Top level of extcheck. + * + * ---------------------------------------------------------------------------- + */ + +main(argc, argv) + char *argv[]; +{ + char *inName; + + /* Process command line arguments */ + EFInit(); + inName = EFArgs(argc, argv, NULL, (int (*)()) NULL, (ClientData) NULL); + if (inName == NULL) + exit (1); + + /* Read the hierarchical description of the input circuit */ + EFReadFile(inName, FALSE, FALSE, FALSE); + if (EFArgTech) EFTech = StrDup((char **) NULL, EFArgTech); + if (EFScale == 0.0) EFScale = 1.0; + + /* Convert the hierarchical description to a flat one */ + EFFlatBuild(inName, EF_FLATNODES|EF_FLATCAPS|EF_FLATRESISTS); + + EFVisitDevs(devVisit, (ClientData) NULL); + if (IS_FINITE_F(EFCapThreshold)) + EFVisitCaps(capVisit, (ClientData) NULL); + if (EFResistThreshold != INFINITE_THRESHOLD) + EFVisitResists(resistVisit, (ClientData) NULL); + EFVisitNodes(nodeVisit, (ClientData) NULL); + +#ifdef free_all_mem + EFFlatDone(); + EFDone(); +#endif /* free_all_mem */ + + printf("Memory used: %s\n", RunStats(RS_MEM, NULL, NULL)); + printf("%d devices\n", ecNumDevs); + printf("%d nodes (%d global, %d local)\n", + ecNumNodes, ecNumGlobalNodes, ecNumNodes - ecNumGlobalNodes); + printf("%d nodes above capacitance threshold\n", ecNumNodeCaps); + printf("%d nodes above resistance threshold\n", ecNumNodeResists); + printf("%d internodal capacitors (%d above threshold)\n", + ecNumCaps, ecNumThreshCaps); + printf("%d explicit resistors (%d above threshold)\n", + ecNumResists, ecNumThreshResists); + exit (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * nodeVisit -- + * devVisit -- + * capVisit -- + * resistVisit -- + * + * Called once for each of the appropriate type of object. + * Each updates various counts. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +nodeVisit(node, res, cap) + EFNode *node; + int res; + double cap; +{ + cap = (cap + 500) / 1000; + res = (res + 500) / 1000; + + ecNumNodes++; + if (EFHNIsGlob(node->efnode_name->efnn_hier)) + ecNumGlobalNodes++; + if (res > EFResistThreshold) ecNumNodeResists++; + if (cap > (double) EFCapThreshold) ecNumNodeCaps++; + return 0; +} + +int +devVisit() +{ + ecNumDevs++; + return 0; +} + + /*ARGSUSED*/ +int +capVisit(hn1, hn2, cap) + HierName *hn1, *hn2; /* UNUSED */ + double cap; +{ + ecNumCaps++; + if ((cap / 1000.) > (double) EFCapThreshold) ecNumThreshCaps++; + return 0; +} + + /*ARGSUSED*/ +int +resistVisit(hn1, hn2, res) + HierName *hn1, *hn2; /* UNUSED */ + float res; +{ + ecNumResists++; + if ((res / 1000.) > EFResistThreshold) ecNumThreshResists++; + return 0; +} diff --git a/extflat/COMPRESS b/extflat/COMPRESS new file mode 100644 index 00000000..ba1b3798 --- /dev/null +++ b/extflat/COMPRESS @@ -0,0 +1,162 @@ +Name compression: + + {prefix}/{suffix} -> {prefix} if {prefix} is unique + {prefix}/{suffix} -> {suffix} if {suffix} is unique + {prefix}/{middle}/{suffix} -> {prefix}/{suffix} if unique + +Consider array subscripts independently from name portions. +Apply name compression only to the most-preferred name for each node. + + +Algorithm (greedy): + + Input is a name of the form: + +Name * +shorten(startName) + Name *startName; /* nk/.../n1/n0 */ +{ + Name *best, *prefix, *suffix; + int bestLength, length, i; + + best = startName; + bestLength = nameLength(startName); + + /* Find small suffixes */ + for (suffix = NULL, i = 0; i <= bestLength + 1; i++) + { + newName = "ni/.../n0"; + if (totallyUnique(newName) && suffixUnique(newName)) + { + suffix = newName; + break; + } + } + if (suffix && nameLength(suffix) < bestLength) + { + best = suffix; + bestLength = nameLength(suffix); + } + + /* Find small prefixes */ + for (prefix = NULL, i = bestLength + 1; i >= 0; i--) + { + newName = "nk/.../ni"; + if (totallyUnique(newName) && prefixUnique(newName)) + { + prefix = newName; + break; + } + } + if (prefix && nameLength(prefix) < bestLength) + { + best = prefix; + bestLength = nameLength(prefix); + } + + /* + * Consider eliding inner parts of the name. + * This loop starts with the smallest length and goes up + * to names of length bestLength. + */ + for (length = 1; length < bestLength; length++) + if (genAllSubNames(startName, length, elideFunc, &best)) + break; + + return best; +} + +/* + * totallyUnique -- + * + * Determine whether 'name' is unique with respect to all the + * names currently in nameTable. + * + * Results: + * TRUE if 'name' is unique, FALSE if not. + * + * Side effects: + * None. + */ + +bool +totallyUnique(name) + Name *name; +{ +} + +/* + * prefixUnique -- + * + * Compare 'name' with all other names in nameTable, looking + * only at the leading components of these names. If 'name' + * isn't unique with respect to the set of names formed by + * the leading components, return FALSE. + * + * Results: + * TRUE if 'name' is unique as described above, FALSE if not. + * + * Side effects: + * None. + */ + +bool +prefixUnique(name) + Name *name; +{ +} + +/* + * suffixUnique -- + * + * Compare 'name' with all other names in nameTable, looking + * only at the trailing components of these names. If 'name' + * isn't unique with respect to the set of names formed by + * the trailing components, return FALSE. + * + * Results: + * TRUE if 'name' is unique as described above, FALSE if not. + * + * Side effects: + * None. + */ + +bool +suffixUnique(name) + Name *name; +{ +} + +/* + * genAllSubNames -- + * + * Generate all subnames of 'name' that are of length 'subLength'. + * Call (*func)() on each name, where (*func)() is of the following + * form: + * + * int + * (*func)(name, cdata) + * Name *name; + * ClientData cdata; + * { + * } + * + * This function should return 0 if genAllSubNames() should continue + * generating names, or 1 if we should stop. + * + * Results: + * Returns 1 if (*func)() aborted the generation; otherwise + * returns 0. + * + * Side effects: + * None other than those caused by (*func)(). + */ + +int +genAllSubNames(name, subLength, func, cdata) + Name *name; + int subLength; + int (*func)(); + ClientData cdata; +{ +} diff --git a/extflat/Depend b/extflat/Depend new file mode 100644 index 00000000..86844587 --- /dev/null +++ b/extflat/Depend @@ -0,0 +1,30 @@ +EFargs.o: EFargs.c ../utils/magic.h ../utils/paths.h ../utils/geometry.h \ + ../utils/hash.h ../utils/utils.h ../utils/malloc.h ../utils/pathvisit.h \ + ../extflat/extflat.h ../extflat/EFint.h +EFbuild.o: EFbuild.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/utils.h ../utils/malloc.h ../extflat/extflat.h \ + ../extflat/EFint.h ../extract/extract.h +EFdef.o: EFdef.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/utils.h ../utils/malloc.h ../extflat/extflat.h \ + ../extflat/EFint.h +EFerr.o: EFerr.c ../utils/magic.h ../utils/geometry.h ../textio/textio.h +EFflat.o: EFflat.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \ + ../extflat/extflat.h ../extflat/EFint.h +EFhier.o: EFhier.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \ + ../extflat/extflat.h ../extflat/EFint.h +EFname.o: EFname.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/geofast.h ../utils/hash.h ../utils/malloc.h \ + ../utils/utils.h ../extflat/extflat.h ../extflat/EFint.h +EFread.o: EFread.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/malloc.h \ + ../utils/geometry.h ../utils/hash.h ../utils/utils.h ../tiles/tile.h \ + ../commands/commands.h ../windows/windows.h ../database/database.h \ + ../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h \ + ../utils/paths.h +EFsym.o: EFsym.c ../utils/magic.h ../utils/geometry.h ../utils/geofast.h \ + ../utils/hash.h ../utils/malloc.h ../utils/utils.h ../extflat/extflat.h \ + ../extflat/EFint.h +EFvisit.o: EFvisit.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \ + ../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h diff --git a/extflat/EFargs.c b/extflat/EFargs.c new file mode 100644 index 00000000..40b57278 --- /dev/null +++ b/extflat/EFargs.c @@ -0,0 +1,397 @@ +/* + * EFargs.c - + * + * General command-line argument processing and overall initialization + * for the .ext file flattener. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFargs.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/paths.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/utils.h" +#include "utils/malloc.h" +#include "utils/pathvisit.h" +#include "extflat/extflat.h" +#include "extflat/EFint.h" + +#define atoCap(s) ((EFCapValue)atof(s)) + +/* --------------------- Visible outside extflat ---------------------- */ + + /* Command-line flags */ +EFCapValue EFCapThreshold = 2; /* -c/-C: (fF) smallest interesting C */ +int EFResistThreshold = 10; /* -r/-R: (Ohms) smallest interesting R */ +int EFTrimFlags = 0; /* -t: output of nodename trailing #!'s */ +char *EFSearchPath = NULL; /* -p: Search path for .ext files */ +char *EFArgTech = NULL; /* -T: Tech specified on command line */ + + /* Misc globals */ +float EFScale = 0.0; /* Uninitialized scale factor */ +char *EFVersion = MAGIC_VERSION;/* Version number of .ext format we read */ +char *EFLibPath = NULL; /* Library search path for .ext files */ +char *EFTech = NULL; +char *EFStyle = NULL; /* Start with no extraction style */ +bool EFCompat = TRUE; /* Start with backwards compatibility enabled */ + +#ifdef MAGIC_WRAPPER +extern char *Path; /* magic's search path---note this should */ + /* be done with #include "utils/main.h" but */ + /* this is easier. */ +#endif + + +/* -------------------- Visible only inside extflat ------------------- */ + + /* Command-line flags */ +bool efWarn = FALSE; /* -v: Warn about duplicate node names */ +bool efHNStats = FALSE; /* -z: TRUE if we gather mem usage stats */ +bool efWatchNodes = FALSE; /* -n: TRUE if watching nodes in table below */ +HashTable efWatchTable; /* -n: Names to watch, keyed by HierName */ + + /* Misc globals */ +int efResists[128]; /* Sheet resistivity for each resist class */ +int efNumResistClasses = 0; /* Number of resist classes */ +bool efResistChanged = FALSE; /* TRUE if .ext resist classes mismatch */ +bool efScaleChanged = FALSE; /* TRUE if .ext scales mismatch */ + + /* Forward declarations */ +#ifndef MAGIC_WRAPPER +extern int efLoadPathFunc(); +extern void efLoadSearchPath(); +#endif + +/* + * ---------------------------------------------------------------------------- + * + * EFArgs -- + * + * Process command-line arguments that are relevant to the extractor + * flattener. Arguments that are specific to the calling function + * are processed by the procedure (*argsProc)(), which should + * have the following form: + * + * (*argsProc)(pargc, pargv, cdata) + * int *pargc; + * char ***pargv; + * ClientData cdata; + * { + * } + * + * If we don't recognize an argument, we call (*argsProc)() with + * *pargc and *pargv pointing to the position in the argument + * vector that we didn't recognize. If (*argsProc)() also doesn't + * recognize the argument, it exits; otherwise, it updates *pargc + * and *pargv to point past the argument it gobbled off and returns. + * If argsProc is NULL, then any arguments we don't recognize are + * considered errors. + * + * Arguments processed are: + * + * -T techname Specify the name of the technology, leaving + * EFArgTech pointing to the technology name. + * -p path Use the colon-separated search path 'path' + * for finding .ext files. Overrides any paths + * found in .magicrc files. + * -s sym=value Set the name 'sym' in the symbol hash table to + * have value 'value', where 'value' is an integer. + * Certain attributes interpreted during circuit + * flattening may have symbolic values; the -s flag + * provides a means of associating a numeric value + * with a symbol. + * -S symfile Read the file 'symfile', which should consist of + * lines of the form sym=value, processing each line + * as though it were an argument to -s. + * + * The following flags are for debugging purposes only: + * -n nodename For debugging: print all merges involving + * the node named 'nodename'. + * -N nodefile For debugging: print all merges involving + * any of the nodes whose names appear in the + * file 'nodefile' (one node name per line). + * -v Warn about unusual occurrences while flattening + * the circuit; mainly for debugging. + * -z Print memory utilized for names. + * + * Results: + * Returns a pointer to a string containing the base name + * of the input .ext file. + * + * Side effects: + * Can set global variables based on the values of command-line + * arguments. + * err_result, if non-null, is set to TRUE if an error occurred. + * err_result is only used by the Tcl version of Magic. + * + * ---------------------------------------------------------------------------- + */ + +char * +EFArgs(argc, argv, err_result, argsProc, cdata) + int argc; /* Number of command-line args */ + char *argv[]; /* Vector of command-line args */ + bool *err_result; /* Set to TRUE if error occurs */ + bool (*argsProc)(); /* Called for args we don't recognize */ + ClientData cdata; /* Passed to (*argsProc)() */ +{ + static char libpath[FNSIZE]; + char *realIn, line[1024], *inname = NULL, *name, *cp; + HierName *hierName; + FILE *f; + + if (err_result != NULL) *err_result = FALSE; + + /* Hash table of nodes we're going to watch if -N given */ + HashInitClient(&efWatchTable, 32, HT_CLIENTKEYS, + efHNCompare, (char *(*)()) NULL, + efHNHash, (int (*)()) NULL); + + /* Process command line options */ + for (argc--, argv++; argc-- > 0; argv++) + { + if (argv[0][0] != '-') + { + if (inname) + { + TxError("Warning: multiple input files specified; "); + TxError("ignoring \"%s\"\n", inname); + } + inname = argv[0]; + continue; + } + + switch (argv[0][1]) + { + /*** NORMAL OPTIONS ***/ + case 'c': + if ((cp = ArgStr(&argc, &argv, "cap threshold")) == NULL) + goto usage; + EFCapThreshold = atoCap(cp); /* Femtofarads */ + break; + case 'p': + EFSearchPath = ArgStr(&argc, &argv, "search path"); + if (EFSearchPath == NULL) + goto usage; + break; + case 'r': + if ((cp = ArgStr(&argc, &argv, "resist threshold")) == NULL) + goto usage; + EFResistThreshold = atoi(cp); /* Ohms */ + break; + case 's': + if ((cp = ArgStr(&argc, &argv, "symbolic name")) == NULL) + goto usage; + efSymAdd(cp); + break; + case 't': + if ((cp = ArgStr(&argc, &argv, "trim characters")) == NULL) + goto usage; + if (strchr(cp, '!')) EFTrimFlags |= EF_TRIMGLOB; + if (strchr(cp, '#')) EFTrimFlags |= EF_TRIMLOCAL; + if (strchr(cp, ',')) EFTrimFlags |= EF_CONVERTCOMMAS; + if (strchr(cp, '=')) EFTrimFlags |= EF_CONVERTEQUAL; + break; + case 'C': + EFCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F; + break; + case 'R': + EFResistThreshold = INFINITE_THRESHOLD; + break; + case 'S': + if ((cp = ArgStr(&argc, &argv, "symbol file")) == NULL) + goto usage; + efSymAddFile(cp); + break; + +#ifndef MAGIC_WRAPPER + case 'T': + if ((EFArgTech = ArgStr(&argc, &argv, "tech name")) == NULL) + goto usage; + break; +#endif + + /*** OPTIONS FOR DEBUGGING ***/ + case 'n': + if ((name = ArgStr(&argc, &argv, "nodename")) == NULL) + goto usage; + printf("Watching node '%s'\n", name); + hierName = EFStrToHN((HierName *) NULL, name); + (void) HashFind(&efWatchTable, (char *) hierName); + efWatchNodes = TRUE; + break; + case 'N': + if ((name = ArgStr(&argc, &argv, "filename")) == NULL) + goto usage; + + /* Add everything in the file to the hash table */ + f = fopen(name, "r"); + if (f == NULL) + { + perror(name); + break; + } + while (fgets(line, sizeof line, f)) + { + cp = strchr(line, '\n'); + if (cp) *cp = '\0'; + printf("Watching node '%s'\n", line); + hierName = EFStrToHN((HierName *) NULL, line); + (void) HashFind(&efWatchTable, (char *) hierName); + } + (void) fclose(f); + efWatchNodes = TRUE; + break; + case 'v': + efWarn = TRUE; + break; + case 'z': + efHNStats = TRUE; + break; + + /*** Try a caller-supplied argument processing function ***/ + default: + if (argsProc == NULL) + goto usage; + if ((*argsProc)(&argc, &argv, cdata)) + { + TxError("\n"); + goto usage; + } + break; + } + } + + /* Find the search path if one was not specified */ + if (EFSearchPath == NULL) +#ifdef MAGIC_WRAPPER + /* Set the search path to be the same as magic's search path */ + EFSearchPath = StrDup(NULL, Path); +#else + efLoadSearchPath(&EFSearchPath); +#endif + + EFLibPath = libpath; + *EFLibPath = 0; /* start with no path */ + if (EFArgTech) (void) sprintf(EFLibPath, EXT_PATH, EFArgTech); + + if (inname == NULL) +#ifdef MAGIC_WRAPPER + return NULL; +#else + goto usage; +#endif + + /* Eliminate trailing .ext from input name */ + if ((cp = strrchr(inname, '.')) && strcmp(cp, ".ext") == 0) + { + realIn = (char *) mallocMagic((unsigned)(cp - inname + 1)); + (void) strncpy(realIn, inname, cp - inname); + realIn[cp - inname] = '\0'; + inname = realIn; + } + + return inname; + +usage: + TxError("Standard arguments: [-R] [-C] [-r rthresh] [-c cthresh] [-v]\n" + "[-p searchpath] [-s sym=value] [-S symfile] [-t trimchars]\n" + +#ifdef MAGIC_WRAPPER + "[rootfile]\n"); + if (err_result != NULL) *err_result = TRUE; + return NULL; +#else + "[-T techname] rootfile\n"); + exit (1); + /*NOTREACHED*/ +#endif +} + +#ifndef MAGIC_WRAPPER + +/* + * ---------------------------------------------------------------------------- + * + * efLoadSearchPath -- + * + * Load the search path string pointed to by 'path' + * with whatever is specified in the .magicrc files + * in $CAD_ROOT/magic/sys, ~, and ., searched in that + * order with the last path taking precedence. See paths.h. + * + * Results: + * None. + * + * Side effects: + * Leaves *path pointing to the correct search path, + * which may either be static or allocated via StrDup(). + * + * ---------------------------------------------------------------------------- + */ + +void +efLoadSearchPath(path) + char **path; +{ + PaVisit *pv; + + *path = NULL; + pv = PaVisitInit(); + PaVisitAddClient(pv, "path", efLoadPathFunc, (ClientData) path); + PaVisitFiles(DOT_MAGIC_PATH, ".magicrc", pv); + PaVisitFree(pv); + if (*path == NULL) + *path = "."; +} + +int +efLoadPathFunc(line, ppath) + char *line; + char **ppath; +{ + char *cp, *dp, c; + char path[BUFSIZ]; + + /* Skip leading blanks */ + for (cp = &line[4]; *cp && isspace(*cp); cp++) + /* Nothing */; + + /* Copy the path into 'path' */ + for (dp = path; (c = *cp++) && !isspace(c) && c != '\n'; ) + { + if (c == '"') + { + while ((c = *cp++) && c != '"') + *dp++ = c; + if (c == '\0') + break; + } + else *dp++ = c; + } + *dp = '\0'; + (void) StrDup(ppath, path); + return 0; /* continue search */ +} + +#endif diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c new file mode 100644 index 00000000..65b25586 --- /dev/null +++ b/extflat/EFbuild.c @@ -0,0 +1,1729 @@ +/* + * EFbuild.c - + * + * Procedures for building up the hierarchical representation + * of a circuit. These are all called from efReadDef() in EFread.c. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFbuild.c,v 1.6 2010/06/24 12:37:17 tim Exp $"; +#endif /* not lint */ + +#include +#include /* for atof() */ +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/utils.h" +#include "utils/malloc.h" +#include "extflat/extflat.h" +#include "extflat/EFint.h" +#include "extract/extract.h" /* for device class list */ + +/* + * To avoid allocating ridiculously large amounts of memory to hold + * transistor types and the names of node types, we maintain the following + * string tables. Each string (transistor type or Magic layername) appears + * exactly once in its respective table; each Dev structure's dev_type field + * is an index into EFDevTypes[], and each node layer name an index into + * EFLayerNames[]. + */ + +/* The following are ridiculously high */ +#define MAXTYPES 100 + +/* Table of transistor types */ +char *EFDevTypes[MAXDEVTYPES]; +int EFDevNumTypes; + +/* Table of Magic layers */ +char *EFLayerNames[MAXTYPES] = { "space" }; +int EFLayerNumNames; + +/* Forward declarations */ +Connection *efAllocConn(); +EFNode *efBuildDevNode(); +void efNodeAddName(); +void efNodeMerge(); + +bool efConnBuildName(); +bool efConnInitSubs(); + + +/* + * ---------------------------------------------------------------------------- + * + * efBuildNode -- + * + * Process a "node" line from a .ext file. + * Creates a new node with an initial name of 'nodeName' + * and capacitance to substrate 'nodeCap'. If there is + * already a node by the name of 'nodeName', adds 'nodeCap' + * to its existing capacitance. + * + * In addition, the arguments 'av' and 'ac' are an (argv, argc) + * vector of pairs of perimeters and areas for each of the + * resist classes; these are either stored in the newly created + * node, or added to the values already stored in an existing one. + * + * Results: + * None. + * + * Side effects: + * Updates the HashTable and node list of 'def'. + * + * EFNode tables: + * Each hash table of nodes is organized in the following way. + * This organization is true both for the node tables for each + * Def, and for the global table of flattened nodes maintained + * in EFflatten.c (although the flattened nodes use the HierName + * struct for representing hierarchical names efficiently). + * + * Each HashEntry points to a EFNodeName struct. The EFNodeName + * is a link back to the hash key (a HierName), as well as + * a link to the actual EFNode for that name. The EFNode points + * to the first EFNodeName in the NULL-terminated list of all + * EFNodeNames pointing to that EFNode; the intent is that this + * first EFNodeName is the "official" or highest-precedence + * name for the node. + * + * The nodes themselves are linked into a circular, doubly + * linked list, for ease in merging two nodes into a single + * one as a result of a "connect" statement. + * + * HashEntries EFNodeNames EFNodes + * + * +---------------+ + * | | + * V | to from + * +-------+ +-------+ | prev prev + * | | ----> | |-+ | ^ | + * +-------+ +-------+ | | | | + * | | | | V + * V | +---------------+ + * +-------+ +-------+ +---> | | + * | | ----> | | ----> | | + * +-------+ +-------+ +---> | | + * | | +---------------+ + * V | ^ | + * +-------+ +-------+ | | | + * | | ----> | |-+ | V + * +-------+ +-------+ from to + * | next next + * V + * NIL + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildNode(def, isSubsnode, nodeName, nodeCap, x, y, layerName, av, ac) + Def *def; /* Def to which this connection is to be added */ + bool isSubsnode; /* TRUE if the node is the substrate */ + char *nodeName; /* One of the names for this node */ + double nodeCap; /* Capacitance of this node to ground */ + int x; int y; /* Location of a point inside this node */ + char *layerName; /* Name of tile type */ + char **av; /* Pairs of area, perimeter strings */ + int ac; /* Number of strings in av */ +{ + EFNodeName *newname; + EFNode *newnode; + HashEntry *he; + unsigned size; + int n; + + he = HashFind(&def->def_nodes, nodeName); + if (newname = (EFNodeName *) HashGetValue(he)) + { + if (efWarn) + efReadError("Warning: duplicate node name %s\n", nodeName); + + /* Just add to C, perim, area of existing node */ + newnode = newname->efnn_node; + newnode->efnode_cap += (EFCapValue) nodeCap; + for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2) + { + newnode->efnode_pa[n].pa_area += atoi(*av++); + newnode->efnode_pa[n].pa_perim += atoi(*av++); + } + return; + } + + /* Allocate a new node with 'nodeName' as its single name */ + newname = (EFNodeName *) mallocMagic((unsigned)(sizeof (EFNodeName))); + newname->efnn_hier = EFStrToHN((HierName *) NULL, nodeName); + newname->efnn_port = -1; /* No port assignment */ + newname->efnn_next = NULL; + HashSetValue(he, (char *) newname); + + /* New node itself */ + size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (PerimArea); + newnode = (EFNode *) mallocMagic((unsigned)(size)); + newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0; + newnode->efnode_cap = nodeCap; + newnode->efnode_attrs = (EFAttr *) NULL; + newnode->efnode_loc.r_xbot = x; + newnode->efnode_loc.r_ybot = y; + newnode->efnode_loc.r_xtop = x + 1; + newnode->efnode_loc.r_ytop = y + 1; + newnode->efnode_client = (ClientData) NULL; + if (layerName) newnode->efnode_type = + efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName); + else newnode->efnode_type = 0; + + for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2) + { + newnode->efnode_pa[n].pa_area = atoi(*av++); + newnode->efnode_pa[n].pa_perim = atoi(*av++); + } + for ( ; n < efNumResistClasses; n++) + newnode->efnode_pa[n].pa_area = newnode->efnode_pa[n].pa_perim = 0; + + /* Update back pointers */ + newnode->efnode_name = newname; + newname->efnn_node = newnode; + + /* Link the node into the list for this def */ + newnode->efnode_next = def->def_firstn.efnode_next; + newnode->efnode_prev = (EFNodeHdr *) &def->def_firstn; + def->def_firstn.efnode_next->efnhdr_prev = (EFNodeHdr *) newnode; + def->def_firstn.efnode_next = (EFNodeHdr *) newnode; + + /* If isSubsnode was TRUE, then turn off backwards compatibility mode */ + if (isSubsnode == TRUE) EFCompat = FALSE; +} + +/* + * Process a "subcap" line by adding the specified adjustment + * value to the indicated node's substrate capacitance. + */ + +void +efAdjustSubCap(def, nodeName, nodeCapAdjust) + Def *def; /* Def to which this connection is to be added */ + char *nodeName; /* One of the names for this node */ + double nodeCapAdjust; /* Substrate capacitance adjustment */ +{ + EFNodeName *nodename; + EFNode *node; + HashEntry *he; + + he = HashFind(&def->def_nodes, nodeName); + if (nodename = (EFNodeName *) HashGetValue(he)) + { + node = nodename->efnn_node; + node->efnode_cap += (EFCapValue) nodeCapAdjust; + return; + } + else + { + if (efWarn) + efReadError("Error: subcap has unknown node %s\n", nodeName); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildAttr -- + * + * Prepend another node attribute to the list for node 'nodeName'. + * The attribute is located at the coordinates given by 'r' and + * is on the layer 'layerName'. The text of the attribute is 'text'. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildAttr(def, nodeName, r, layerName, text) + Def *def; + char *nodeName; + Rect *r; + char *layerName; + char *text; +{ + HashEntry *he; + EFNodeName *nn; + EFAttr *ap; + int size; + + he = HashLookOnly(&def->def_nodes, nodeName); + if (he == NULL || HashGetValue(he) == NULL) + { + efReadError("Attribute for nonexistent node %s ignored\n", nodeName); + return; + } + nn = (EFNodeName *) HashGetValue(he); + + size = ATTRSIZE(strlen(text)); + ap = (EFAttr *) mallocMagic((unsigned)(size)); + (void) strcpy(ap->efa_text, text); + ap->efa_type = + efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName); + ap->efa_loc = *r; + ap->efa_next = nn->efnn_node->efnode_attrs; + nn->efnn_node->efnode_attrs = ap; +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildDist -- + * + * Process a "dist" line from a .ext file. + * Both of the names driver and receiver are pathnames with slashes. + * Add a new Distance record to the hash table for Def, or update + * an existing Distance record. + * + * This strategy allows the .ext file to contain several distance + * lines for the same pair of points; we do the compression here + * rather than requiring it be done during extraction. It's necessary + * to do compression at some point before flattening; see the description + * in efFlatDists(). + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildDist(def, driver, receiver, min, max) + Def *def; /* Def for which we're adding a new Distance */ + char *driver; /* Source terminal */ + char *receiver; /* Destination terminal */ + int min, max; /* Minimum and maximum acyclic distance from source + * to destination. + */ +{ + Distance *dist, distKey; + HierName *hn1, *hn2; + HashEntry *he; + + hn1 = EFStrToHN((HierName *) NULL, driver); + hn2 = EFStrToHN((HierName *) NULL, receiver); + distKey.dist_min = min; + distKey.dist_max = max; + if (EFHNBest(hn1, hn2)) + { + distKey.dist_1 = hn1; + distKey.dist_2 = hn2; + } + else + { + distKey.dist_1 = hn2; + distKey.dist_2 = hn1; + } +#ifdef notdef + TxError("ADD %s ", EFHNToStr(distKey.dist_1)); + TxError("%s ", EFHNToStr(distKey.dist_2)); + TxError("%d %d\n", min, max); +#endif /* notdef */ + + he = HashFind(&def->def_dists, (char *) &distKey); + if (dist = (Distance *) HashGetValue(he)) + { + /* + * There was already an entry in the table; update it + * to reflect new minimum and maximum distances. We + * can free the keys since they were already in the + * table. + */ + dist->dist_min = MIN(dist->dist_min, min); + dist->dist_max = MAX(dist->dist_max, max); + EFHNFree(hn1, (HierName *) NULL, HN_ALLOC); + EFHNFree(hn2, (HierName *) NULL, HN_ALLOC); + } + else + { + /* + * When the key was installed in the hash table, it was + * a copy of the Distance 'distKey'. Leave this as the + * value of the HashEntry. + */ + HashSetValue(he, (ClientData) he->h_key.h_ptr); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildKill -- + * + * Process a "killnode" line from a .ext file. + * Prepends a Kill to the list for def. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildKill(def, name) + Def *def; /* Def for which we're adding a new Kill */ + char *name; /* Name of node to die */ +{ + Kill *kill; + + kill = (Kill *) mallocMagic((unsigned)(sizeof (Kill))); + kill->kill_name = EFStrToHN((HierName *) NULL, name); + kill->kill_next = def->def_kills; + def->def_kills = kill; +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildEquiv -- + * + * Process an "equiv" line from a .ext file. + * One of the names 'nodeName1' or 'nodeName2' should be a name for + * an existing node in the def 'def'. We simply prepend this name to + * the list of names for that node. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildEquiv(def, nodeName1, nodeName2) + Def *def; /* Def for which we're adding a new node name */ + char *nodeName1; /* One of node names to be made equivalent */ + char *nodeName2; /* Other name to be made equivalent. One of nodeName1 + * or nodeName2 must already be known. + */ +{ + EFNodeName *nn1, *nn2; + HashEntry *he1, *he2; + + /* Look up both names in the hash table for this def */ + he1 = HashFind(&def->def_nodes, nodeName1); + he2 = HashFind(&def->def_nodes, nodeName2); + + nn1 = (EFNodeName *) HashGetValue(he1); + nn2 = (EFNodeName *) HashGetValue(he2); + + if (nn2 == (EFNodeName *) NULL) + { + /* Create nodeName1 if it doesn't exist */ + if (nn1 == (EFNodeName *) NULL) + { + if (efWarn) + efReadError("Creating new node %s\n", nodeName1); + efBuildNode(def, FALSE, + nodeName1, (double)0, 0, 0, + (char *) NULL, (char **) NULL, 0); + nn1 = (EFNodeName *) HashGetValue(he1); + } + + /* Make nodeName2 be another alias for node1 */ + efNodeAddName(nn1->efnn_node, he2, + EFStrToHN((HierName *) NULL, nodeName2)); + return; + } + + /* If both names exist and are for different nodes, merge them */ + if (nn1) + { + if (nn1->efnn_node != nn2->efnn_node) + { + if (efWarn) + efReadError("Merged nodes %s and %s\n", nodeName1, nodeName2); + efNodeMerge(nn1->efnn_node, nn2->efnn_node); + } + return; + } + + /* Make nodeName1 be another alias for node2 */ + efNodeAddName(nn2->efnn_node, he1, + EFStrToHN((HierName *) NULL, nodeName1)); +} + + +/* + * ---------------------------------------------------------------------------- + * + * + * ---------------------------------------------------------------------------- + */ + +DevParam * +efGetDeviceParams(name) + char *name; +{ + HashEntry *he; + DevParam *plist = NULL; + + he = HashLookOnly(&efDevParamTable, (char *)name); + if (he != NULL) + plist = (DevParam *)HashGetValue(he); + return plist; +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildDeviceParams -- + * + * Fill in a device parameter hash table entry from a "parameters" line in + * the .ext file. + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildDeviceParams(name, argc, argv) + char *name; + int argc; + char *argv[]; +{ + HashEntry *he; + DevParam *plist = NULL, *newparm; + char *pptr; + int n; + + he = HashFind(&efDevParamTable, name); + plist = (DevParam *)HashGetValue(he); + if (plist != NULL) return; /* Already got one! */ + + /* Parse arguments for each parameter */ + for (n = 0; n < argc; n++) + { + char *mult; + + pptr = strchr(argv[n], '='); + if (pptr == NULL) + { + efReadError("Bad parameter assignment \"%s\" for device \"%s\"\n", + argv[n], name); + continue; + } + newparm = (DevParam *)mallocMagic(sizeof(DevParam)); + newparm->parm_type[0] = *argv[n]; + if ((pptr - argv[n]) == 1) + newparm->parm_type[1] = '\0'; + else + newparm->parm_type[1] = *(argv[n] + 1); + + if ((mult = strchr(pptr + 1, '*')) != NULL) + { + *mult = '\0'; + newparm->parm_scale = atof(mult + 1); + } + else + newparm->parm_scale = 1.0; + + // For parameters defined for cell defs, copy the whole + // expression verbatim into parm_name. parm_type is + // reassigned to be a numerical order. + + if (name[0] == ':') + { + newparm->parm_name = StrDup((char **)NULL, argv[n]); + newparm->parm_type[1] = '0' + n / 10; + newparm->parm_type[0] = '0' + n % 10; + } + else + newparm->parm_name = StrDup((char **)NULL, pptr + 1); + newparm->parm_next = plist; + plist = newparm; + } + HashSetValue(he, (char *)plist); +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildDevice -- + * + * Process a device line from a .ext file. + * The number of terminals in the dev is argc/3 (which must be integral). + * Each block of 3 strings in argv describes a single terminal; see the + * comments below for their interpretation. + * + * Results: + * Returns 0 on success, 1 on failure to parse any terminal's values + * + * Side effects: + * Prepends this dev to the list for the def 'def'. + * + * ---------------------------------------------------------------------------- + */ + +int +efBuildDevice(def, class, type, r, argc, argv) + Def *def; /* Def to which this connection is to be added */ + char class; /* Class (dev, bjt, etc.) of this device */ + char *type; /* Type (name) of this device */ + Rect *r; /* Coordinates of 1x1 rectangle entirely inside device */ + int argc; /* Size of argv */ + char *argv[]; /* Tokens for the rest of the dev line. + * The first depend on the type of device. The rest + * are taken in groups of 3, one for each terminal. + * Each group of 3 consists of the node name to which + * the terminal connects, the length of the terminal, + * and an attribute list (or the token 0). + */ +{ + int n, nterminals, pn; + DevTerm *term; + Dev *newdev, devtmp; + DevParam *newparm, *devp, *sparm; + char ptype, *pptr, **av; + int argstart = 1; /* start of terminal list in argv[] */ + bool hasModel = strcmp(type, "None") ? TRUE : FALSE; + + int area, perim; /* Total area, perimeter of primary type (i.e., channel) */ + + devtmp.dev_subsnode = NULL; + devtmp.dev_cap = 0.0; + devtmp.dev_res = 0.0; + devtmp.dev_area = 0; + devtmp.dev_perim = 0; + devtmp.dev_length = 0; + devtmp.dev_width = 0; + devtmp.dev_params = NULL; + + switch (class) + { + case DEV_FET: + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_BJT: + argstart = 3; + break; + case DEV_DIODE: + case DEV_NDIODE: + case DEV_PDIODE: + argstart = 0; + break; + case DEV_RES: + case DEV_CAP: + case DEV_CAPREV: + if (hasModel) + argstart = 2; + break; + case DEV_SUBCKT: + case DEV_MSUBCKT: + case DEV_RSUBCKT: + argstart = 0; + } + + devp = efGetDeviceParams(type); + + /* Parse initial arguments for parameters */ + while ((pptr = strchr(argv[argstart], '=')) != NULL) + { + // Check if this parameter is in the table. + // If so, handle appropriately. Otherwise, the + // parameter gets saved verbatim locally. The + // "parameters" line comes before any "device" line + // in the .ext file, so the table should be complete. + + *pptr = '\0'; + for (sparm = devp; sparm; sparm = sparm->parm_next) + if (!strcasecmp(sparm->parm_type, argv[argstart])) + break; + *pptr = '='; + if (sparm == NULL) + { + /* Copy the parameter into dev_params */ + /* (parm_type and parm_scale records are not used) */ + newparm = (DevParam *)mallocMagic(sizeof(DevParam)); + newparm->parm_name = StrDup((char **)NULL, argv[argstart]); + newparm->parm_next = devtmp.dev_params; + devtmp.dev_params = newparm; + argstart++; + continue; + } + + pptr++; + switch(*argv[argstart]) + { + case 'a': + if ((pptr - argv[argstart]) == 2) + devtmp.dev_area = atoi(pptr); + else + { + pn = *(argv[argstart] + 1) - '0'; + if (pn == 0) + devtmp.dev_area = atoi(pptr); + /* Otherwise, punt */ + } + break; + case 'p': + if ((pptr - argv[argstart]) == 2) + devtmp.dev_perim = atoi(pptr); + else + { + pn = *(argv[argstart] + 1) - '0'; + if (pn == 0) + devtmp.dev_perim = atoi(pptr); + /* Otherwise, use verbatim */ + } + break; + case 'l': + devtmp.dev_length = atoi(pptr); + break; + case 'w': + devtmp.dev_width = atoi(pptr); + break; + case 'c': + devtmp.dev_cap = (float)atof(pptr); + break; + case 'r': + devtmp.dev_res = (float)atof(pptr); + break; + } + argstart++; + } + + /* Check for optional substrate node */ + + switch (class) + { + case DEV_RES: + case DEV_CAP: + case DEV_CAPREV: + case DEV_RSUBCKT: + case DEV_MSUBCKT: + case DEV_SUBCKT: + case DEV_DIODE: + case DEV_NDIODE: + case DEV_PDIODE: + n = argc - argstart; + if ((n % 3) == 1) + { + if (strncmp(argv[argstart], "None", 4) != 0) + devtmp.dev_subsnode = efBuildDevNode(def, argv[argstart], TRUE); + + argstart++; + } + break; + } + + /* Between argstart and argc, we should only have terminal triples */ + if (((argc - argstart) % 3) != 0) + return 1; + + nterminals = (argc - argstart) / 3; + + newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals)); + newdev->dev_subsnode = devtmp.dev_subsnode; + newdev->dev_cap = devtmp.dev_cap; + newdev->dev_res = devtmp.dev_res; + newdev->dev_area = devtmp.dev_area; + newdev->dev_perim = devtmp.dev_perim; + newdev->dev_length = devtmp.dev_length; + newdev->dev_width = devtmp.dev_width; + newdev->dev_params = devtmp.dev_params; + + newdev->dev_nterm = nterminals; + newdev->dev_rect = *r; + newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type); + newdev->dev_class = class; + + switch (class) + { + case DEV_FET: /* old-style "fet" record */ + newdev->dev_area = atoi(argv[0]); + newdev->dev_perim = atoi(argv[1]); + newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); + break; + case DEV_MOSFET: /* new-style "device mosfet" record */ + case DEV_ASYMMETRIC: + case DEV_BJT: + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + + /* "None" in the place of the substrate name means substrate is ignored */ + if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) + newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); + break; + case DEV_RES: + if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) + { + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + } + else if (StrIsNumeric(argv[0])) + { + newdev->dev_res = (float)atof(argv[0]); + } + else + { + if (hasModel) + { + efReadError("Error: expected L and W, got %s %s\n", argv[0], + argv[1]); + newdev->dev_length = 0; + newdev->dev_width = 0; + } + else + { + efReadError("Error: expected resistance value, got %s\n", argv[0]); + newdev->dev_res = 0.0; + } + } + if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) + newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); + + break; + case DEV_CAP: + case DEV_CAPREV: + if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) + { + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + } + else if (StrIsNumeric(argv[0])) + { + newdev->dev_cap = (float)atof(argv[0]); + } + else + { + if (hasModel) + { + efReadError("Error: expected L and W, got %s %s\n", argv[0], + argv[1]); + newdev->dev_length = 0; + newdev->dev_width = 0; + } + else + { + efReadError("Error: expected capacitance value, got %s\n", argv[0]); + newdev->dev_cap = 0.0; + } + } + if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) + newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); + + break; + } + +#define TERM_NAME 0 +#define TERM_PERIM 1 +#define TERM_ATTRS 2 + + for (av = &argv[argstart], n = 0; n < nterminals; n++, av += 3) + { + term = &newdev->dev_terms[n]; + term->dterm_node = efBuildDevNode(def, av[TERM_NAME], FALSE); + term->dterm_length = atoi(av[TERM_PERIM]); + term->dterm_area = 0; + term->dterm_perim = 0; + + /* If the attr list is '0', this signifies no attributes */ + if (av[TERM_ATTRS][0] == '0' && av[TERM_ATTRS][1] == '\0') + term->dterm_attrs = (char *) NULL; + else + term->dterm_attrs = StrDup((char **) NULL, av[TERM_ATTRS]); + } + +#undef TERM_NAME +#undef TERM_PERIM +#undef TERM_ATTRS + + /* Add this dev to the list for def */ + newdev->dev_next = def->def_devs; + def->def_devs = newdev; + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildPortNode -- + * + * Look for the node named 'name' in the local table for 'def', or in + * the global node name table. If it doesn't already exist, create a + * EFNode for it, and set capacitance and area/perimeter to zero. + * Set the efnode_flags value to EF_PORT, with the port number encoded + * in the efNodeName structure. + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildPortNode(def, name, idx, x, y, layername) + Def *def; /* Def to which this connection is to be added */ + char *name; /* One of the names for this node */ + int idx; /* Port number (order) */ + int x; int y; /* Location of a point inside this node */ + char *layername; /* Name of tile type */ +{ + HashEntry *he; + EFNodeName *nn; + + he = HashFind(&def->def_nodes, name); + nn = (EFNodeName *) HashGetValue(he); + if (nn == (EFNodeName *) NULL) + { + /* Create node if it doesn't already exist */ + efBuildNode(def, FALSE, name, (double)0, x, y, + layername, (char **) NULL, 0); + + nn = (EFNodeName *) HashGetValue(he); + } + if (nn != (EFNodeName *) NULL) + { + nn->efnn_node->efnode_flags |= EF_PORT; + nn->efnn_port = idx; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * EFGetPortMax -- + * + * Find the highest port number in the cell def and return the value. + * + * Results: + * Value of highest port number in the cell def's node list + * + * Side effects: + * Larger value including the implicit ports is placed in the + * location of the pointer imp_max. + * + * ---------------------------------------------------------------------------- + */ + +int +EFGetPortMax(def, imp_max) + Def *def; + int *imp_max; +{ + EFNode *snode; + EFNodeName *nodeName; + int portmax, portorder; + + portmax = -1; + if (imp_max) *imp_max = -1; + + for (snode = (EFNode *) def->def_firstn.efnode_next; + snode != &def->def_firstn; + snode = (EFNode *) snode->efnode_next) + { + if (imp_max && (snode->efnode_flags & EF_SUBS_PORT)) + { + nodeName = snode->efnode_name; + portorder = nodeName->efnn_port; + if (portorder > (*imp_max)) (*imp_max) = portorder; + } + else if (snode->efnode_flags & EF_PORT) + { + for (nodeName = snode->efnode_name; nodeName != NULL; nodeName = + nodeName->efnn_next) + { + portorder = nodeName->efnn_port; + if (portorder > portmax) portmax = portorder; + } + } + } + return portmax; +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildDevNode -- + * + * Look for the node named 'name' in the local table for 'def', or + * in the global node name table. If it doesn't already exist, + * create a EFNode for it. If 'isSubsNode' is TRUE, this is node + * is a substrate node and may not exist yet; otherwise, the node + * must already exist. + * + * Results: + * Returns a pointer to the EFNode for 'name'. + * + * Side effects: + * May create a new node, as per above. + * + * ---------------------------------------------------------------------------- + */ + +EFNode * +efBuildDevNode(def, name, isSubsNode) + Def *def; + char *name; + bool isSubsNode; +{ + HashEntry *he; + EFNodeName *nn; + + he = HashFind(&def->def_nodes, name); + nn = (EFNodeName *) HashGetValue(he); + if (nn == (EFNodeName *) NULL) + { + /* Create node if it doesn't already exist */ + if (efWarn && !isSubsNode) + efReadError("Node %s doesn't exist so creating it\n", name); + efBuildNode(def, isSubsNode, name, (double)0, 0, 0, + (char *) NULL, (char **) NULL, 0); + + nn = (EFNodeName *) HashGetValue(he); + if (isSubsNode) + { + if (!EFHNIsGlob(nn->efnn_hier)) + { + /* This node is declared to be an implicit port */ + nn->efnn_node->efnode_flags |= EF_SUBS_PORT; + nn->efnn_port = -1; + def->def_flags |= DEF_SUBSNODES; + } + nn->efnn_node->efnode_flags |= (EF_DEVTERM | EF_SUBS_NODE); + } + } + return nn->efnn_node; +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildAddStr -- + * + * Return the index of 'str' in 'table'. + * Add the string 'str' to the table 'table' if it's not already there. + * + * Results: + * See above. + * + * Side effects: + * Increments *pMax if we add an entry to the table. + * + * ---------------------------------------------------------------------------- + */ + +int +efBuildAddStr(table, pMax, size, str) + char *table[]; /* Table to search */ + int *pMax; /* Increment this if we add an entry */ + int size; /* Maximum size of table */ + char *str; /* String to add */ +{ + int n, max; + + max = *pMax; + for (n = 0; n < max; n++) + if (strcmp(table[n], str) == 0) + return n; + + if (max >= size) + { + printf("Too many entries in table (max is %d) to add %s\n", size, str); + printf("Recompile libextflat.a with a bigger table size\n"); + exit (1); + } + + table[n++] = StrDup((char **) NULL, str); + *pMax = n; + + return max; +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildUse -- + * + * Process a "use" line from a .ext file. + * Creates a new use by the name 'subUseId' of the def named 'subDefName'. + * If 'subDefName' doesn't exist, it is created, but left marked as + * unavailable so that readfile() will read it in after it is done + * with this file. If 'subUseId' ends in an array subscript, e.g, + * useid[xlo:xhi:xsep][ylo:yhi:ysep] + * its ArrayInfo is filled in from this information; otherwise, its + * ArrayInfo is marked as not being needed (xlo == xhi, ylo == yhi). + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf) + Def *def; /* Def to which this connection is to be added */ + char *subDefName; /* Def of which this a use */ + char *subUseId; /* Use identifier for the def 'subDefName' */ + int ta, tb, tc, + td, te, tf; /* Elements of a transform from coordinates of + * subDefName up to def. + */ +{ + Use *newuse; + Def *newdef; + char *cp; + + newdef = efDefLook(subDefName); + if (newdef == NULL) + newdef = efDefNew(subDefName); + + newuse = (Use *) mallocMagic((unsigned)(sizeof (Use))); + newuse->use_def = newdef; + newuse->use_trans.t_a = ta; + newuse->use_trans.t_b = tb; + newuse->use_trans.t_c = tc; + newuse->use_trans.t_d = td; + newuse->use_trans.t_e = te; + newuse->use_trans.t_f = tf; + newuse->use_next = def->def_uses; + def->def_uses = newuse; + + /* Set the use identifier and array information */ + if ((cp = strchr(subUseId, '[')) == NULL) + { + newuse->use_id = StrDup((char **) NULL, subUseId); + newuse->use_xlo = newuse->use_xhi = 0; + newuse->use_ylo = newuse->use_yhi = 0; + newuse->use_xsep = newuse->use_ysep = 0; + return; + } + + *cp = '\0'; + newuse->use_id = StrDup((char **) NULL, subUseId); + *cp = '['; + (void) sscanf(cp, "[%d:%d:%d][%d:%d:%d]", + &newuse->use_xlo, &newuse->use_xhi, &newuse->use_xsep, + &newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep); +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildConnect -- + * + * Process a "connect" line from a .ext file. + * Creates a connection record for the names 'nodeName1' and + * 'nodeName2'. + * + * Results: + * None. + * + * Side effects: + * Allocates a new connection record, and prepends it to the + * list for def. + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac) + Def *def; /* Def to which this connection is to be added */ + char *nodeName1; /* Name of first node in connection */ + char *nodeName2; /* Name of other node in connection */ + double deltaC; /* Adjustment in capacitance */ + char **av; /* Strings for area, perimeter adjustment */ + int ac; /* Number of strings in av */ +{ + int n; + Connection *conn; + unsigned size = sizeof (Connection) + + (efNumResistClasses - 1) * sizeof (PerimArea); + + conn = (Connection *) mallocMagic((unsigned)(size)); + + if (efConnInitSubs(conn, nodeName1, nodeName2)) + { + conn->conn_cap = (EFCapValue) deltaC; + conn->conn_next = def->def_conns; + for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2) + { + conn->conn_pa[n].pa_area = atoi(*av++); + conn->conn_pa[n].pa_perim = atoi(*av++); + } + for ( ; n < efNumResistClasses; n++) + conn->conn_pa[n].pa_area = conn->conn_pa[n].pa_perim = 0; + def->def_conns = conn; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildResistor -- + * + * Process a "resistor" line from a .ext file. + * Creates a resistor record for the names 'nodeName1' and + * 'nodeName2'. Both 'nodeName1' and 'nodeName2' must be non-NULL. + * + * Results: + * None. + * + * Side effects: + * Allocates a new connection record, and prepends it to the + * def_resistors list for def. + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildResistor(def, nodeName1, nodeName2, resistance) + Def *def; /* Def to which this connection is to be added */ + char *nodeName1; /* Name of first node in resistor */ + char *nodeName2; /* Name of second node in resistor */ + float resistance; /* Resistor value */ +{ + Connection *conn; + + conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection))); + if (efConnInitSubs(conn, nodeName1, nodeName2)) + { + conn->conn_res = resistance; + conn->conn_next = def->def_resistors; + def->def_resistors = conn; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * efBuildCap -- + * + * Process a "cap" line from a .ext file. + * Creates a capacitor record for the names 'nodeName1' and + * 'nodeName2'. Both 'nodeName1' and 'nodeName2' must be non-NULL. + * + * Results: + * None. + * + * Side effects: + * Allocates a new connection record, and prepends it to the + * def_caps list for def. + * + * ---------------------------------------------------------------------------- + */ + +void +efBuildCap(def, nodeName1, nodeName2, cap) + Def *def; /* Def to which this connection is to be added */ + char *nodeName1; /* Name of first node in capacitor */ + char *nodeName2; /* Name of second node in capacitor */ + double cap; /* Capacitor value */ +{ + Connection *conn; + + conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection))); + if (efConnInitSubs(conn, nodeName1, nodeName2)) + { + conn->conn_cap = (EFCapValue) cap; + conn->conn_next = def->def_caps; + def->def_caps = conn; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * efConnInitSubs -- + * + * Fill in and check the subscript information for the newly allocated + * Connection 'conn'. + * + * Results: + * Returns TRUE if successful, FALSE on error. + * + * Side effects: + * Fills in the two ConnNames conn->conn_1 and conn->conn_2. + * Frees 'conn' in the event of an error. + * + * ---------------------------------------------------------------------------- + */ + +bool +efConnInitSubs(conn, nodeName1, nodeName2) + Connection *conn; + char *nodeName1, *nodeName2; +{ + ConnName *c1, *c2; + int n; + + c1 = &conn->conn_1; + c2 = &conn->conn_2; + if (!efConnBuildName(c1, nodeName1) || !efConnBuildName(c2, nodeName2)) + goto bad; + + if (c1->cn_nsubs != c2->cn_nsubs) + { + efReadError("Number of subscripts doesn't match\n"); + goto bad; + } + + for (n = 0; n < c1->cn_nsubs; n++) + { + if (c1->cn_subs[n].r_hi - c1->cn_subs[n].r_lo + != c2->cn_subs[n].r_hi - c2->cn_subs[n].r_lo) + { + efReadError("Subscript %d range mismatch\n", n); + goto bad; + } + } + return TRUE; + +bad: + if (c1->cn_name) freeMagic((char *) c1->cn_name); + if (c2->cn_name) freeMagic((char *) c2->cn_name); + freeMagic((char *) conn); + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * efConnBuildName -- + * + * Fill in the fields of 'cnp' from the string 'name'. + * If 'name' contains no trailing subscript ranges (which are + * of the form [lo1:hi1] or [lo1:hi1,lo2:hi2], or [lo1:hi1][lo2:hi2] for + * compatibility with older versions of Magic), we set cnp->cn_nsubs + * to zero and cnp->cn_name to a copy of 'name'. Otherwise, we decode + * the subscripts and fill in cnp->cn_subs and cnp->cn_nsubs appropriately. + * + * Results: + * Returns TRUE if successful, FALSE on error. + * + * Side effects: + * Fills in the fields of the ConnName 'cnp'. + * + * ---------------------------------------------------------------------------- + */ + +bool +efConnBuildName(cnp, name) + ConnName *cnp; + char *name; +{ + char *srcp, *dstp, *cp, *dp; + int nsubs; + Range *rp; + char newname[1024]; + char c; + + cnp->cn_nsubs = 0; + if (name == NULL) + { + cnp->cn_name = NULL; + return TRUE; + } + + cp = name; + /* Make sure it's an array subscript range before treating it specially */ +again: + if ((cp = strchr(cp, '[')) == NULL) + { + cnp->cn_name = StrDup((char **) NULL, name); + return TRUE; + } + for (dp = cp + 1; *dp && *dp != ':'; dp++) + { + if (*dp == ']') + { + cp = dp+1; + goto again; + } + } + + /* Copy the initial part of the name */ + for (srcp = name, dstp = newname; srcp < cp; *dstp++ = *srcp++) + /* Nothing */; + + /* Replace each subscript range with %d */ + for (nsubs = 0, rp = cnp->cn_subs; (c = *cp) == '[' || c == ','; nsubs++) + { + if (nsubs >= MAXSUBS) + { + efReadError("Too many array subscripts (maximum=2)\n"); + return FALSE; + } + if (sscanf(++cp, "%d:%d", &rp[nsubs].r_lo, &rp[nsubs].r_hi) != 2) + { + efReadError("Subscript syntax error\n"); + return FALSE; + } + if (rp[nsubs].r_lo > rp[nsubs].r_hi) + { + efReadError("Backwards subscript range [%d:%d]\n", + rp[nsubs].r_lo, rp[nsubs].r_hi); + return FALSE; + } + + while (*cp && *cp != ']' && *cp != ',') + cp++; + if (*cp == ']') cp++; + } + + /* Generate format for sprintf */ + *dstp++ = '['; + *dstp++ = '%'; + *dstp++ = 'd'; + if (nsubs == 2) + { + *dstp++ = ','; + *dstp++ = '%'; + *dstp++ = 'd'; + } + *dstp++ = ']'; + + /* Copy remainder of path */ + while (*dstp++ = *cp++) + /* Nothing */; + + cnp->cn_name = StrDup((char **) NULL, newname); + cnp->cn_nsubs = nsubs; + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * efNodeAddName -- + * + * Add a name to the list for 'node'. + * We already have a HashEntry for the new name. + * The new name is added to the front of the list + * for 'node' only if it is higher in precedence + * than the name already at the front of the list. + * Sets the value of 'he' to be the newly allocated + * EFNodeName. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efNodeAddName(node, he, hn) + EFNode *node; + HashEntry *he; + HierName *hn; +{ + EFNodeName *newnn; + EFNodeName *oldnn; + + newnn = (EFNodeName *) mallocMagic((unsigned)(sizeof (EFNodeName))); + newnn->efnn_node = node; + newnn->efnn_hier = hn; + newnn->efnn_port = -1; + HashSetValue(he, (char *) newnn); + + /* Link in the new name */ + oldnn = node->efnode_name; + if (oldnn == NULL || EFHNBest(newnn->efnn_hier, oldnn->efnn_hier)) + { + /* New head of list */ + newnn->efnn_next = oldnn; + node->efnode_name = newnn; + } + else + { + /* Link it in behind the head of the list */ + newnn->efnn_next = oldnn->efnn_next; + oldnn->efnn_next = newnn; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * efNodeMerge -- + * + * Combine two nodes. The resistances and capacitances are summed. + * The attribute lists are appended. The location chosen is the + * lower-leftmost, with lowest being considered before leftmost. + * The canonical name of the new node is taken to be the highest + * precedence among the names for all nodes. + * + * One of the nodes will no longer be referenced, so we arbitrarily + * make this node2 and free its memory. + * + * Results: + * Return 0 if node1 has precedence, 1 if node2 has precedence + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efNodeMerge(node1, node2) + EFNode *node1, *node2; /* Hierarchical nodes */ +{ + EFNodeName *nn, *nnlast; + EFAttr *ap; + int n; + + /* Sanity check: ignore if same node */ + if (node1 == node2) + return; + + if (efWatchNodes) + { + if (HashLookOnly(&efWatchTable, (char *) node1->efnode_name->efnn_hier) + || (node2->efnode_name + && HashLookOnly(&efWatchTable, + (char *) node2->efnode_name->efnn_hier))) + { + printf("\ncombine: %s\n", + EFHNToStr(node1->efnode_name->efnn_hier)); + printf(" with %s\n\n", + node2->efnode_name + ? EFHNToStr(node2->efnode_name->efnn_hier) + : "(unnamed)"); + } + } + + /* Sum capacitances, perimeters, areas */ + node1->efnode_cap += node2->efnode_cap; + for (n = 0; n < efNumResistClasses; n++) + { + node1->efnode_pa[n].pa_area += node2->efnode_pa[n].pa_area; + node1->efnode_pa[n].pa_perim += node2->efnode_pa[n].pa_perim; + } + + /* Make all EFNodeNames point to node1 */ + if (node2->efnode_name) + { + for (nn = node2->efnode_name; nn; nn = nn->efnn_next) + { + nnlast = nn; + nn->efnn_node = node1; + } + + /* Concatenate list of EFNodeNames, taking into account precedence */ + if (EFHNBest(node2->efnode_name->efnn_hier, + node1->efnode_name->efnn_hier)) + { + /* + * New official name is that of node2. + * The new list of names is: + * node2-names, node1-names + */ + nnlast->efnn_next = node1->efnode_name; + node1->efnode_name = node2->efnode_name; + + /* + * Choose the new location only if node2's location is a valid one, + * i.e, node2 wasn't created before it was mentioned. This is mainly + * to deal with new fets, resistors, and capacitors created by resistance + * extraction, which appear with their full hierarchical names in the + * .ext file for the root cell. + * + * This code has been moved up from below so that the original + * location and type will be prefered when the original name + * is preferred. + * + * I am purposefully subverting the original specification that + * the node refer to the bottom corner of the network. Does + * this have any effect on exttosim or exttospice? + * + * Tim, 6/14/04 + */ + if (node2->efnode_type > 0) + { + node1->efnode_loc = node2->efnode_loc; + node1->efnode_type = node2->efnode_type; + + if (node2->efnode_loc.r_ybot < node1->efnode_loc.r_ybot + || (node2->efnode_loc.r_ybot == node1->efnode_loc.r_ybot + && node2->efnode_loc.r_xbot < node1->efnode_loc.r_xbot)) + { +// node1->efnode_loc = node2->efnode_loc; +// node1->efnode_type = node2->efnode_type; + } + } + } + else + { + /* + * Keep old official name. + * The new list of names is: + * node1-names[0], node2-names, node1-names[1-] + */ + nnlast->efnn_next = node1->efnode_name->efnn_next; + node1->efnode_name->efnn_next = node2->efnode_name; + } + } + + /* Merge attribute lists */ + if (ap = node2->efnode_attrs) + { + while (ap->efa_next) + ap = ap->efa_next; + ap->efa_next = node1->efnode_attrs; + node1->efnode_attrs = ap; + node2->efnode_attrs = (EFAttr *) NULL; /* Sanity */ + } + + /* Unlink node2 from list for def */ + node2->efnode_prev->efnhdr_next = node2->efnode_next; + node2->efnode_next->efnhdr_prev = node2->efnode_prev; + + /* + * Only if both nodes were EF_DEVTERM do we keep EF_DEVTERM set + * in the resultant node. + */ + if ((node2->efnode_flags & EF_DEVTERM) == 0) + node1->efnode_flags &= ~EF_DEVTERM; + + /* + * If node2 has the EF_PORT flag set, then copy the port + * record in the flags to node1. + */ + if (node2->efnode_flags & EF_PORT) + node1->efnode_flags |= EF_PORT; + + /* + * If node2 has the EF_SUBS_NODE flag set, then copy the port + * record in the flags to node1. + */ + if (node2->efnode_flags & EF_SUBS_NODE) + node1->efnode_flags |= EF_SUBS_NODE; + + /* Get rid of node2 */ + freeMagic((char *) node2); +} + +/* + * ---------------------------------------------------------------------------- + * + * efFreeNodeTable -- + * + * Free the EFNodeNames (and the HierNames they point to) pointed to by + * the entries in the HashTable 'table'. Each EFNodeName is assumed to + * be pointed to by exactly one HashEntry, but each HierName can be + * pointed to by many entries (some of which may be in other HashTables). + * As a result, the HierNames aren't freed here; instead, an entry is + * added to efFreeHashTable for each HierName encountered. Everything + * is then freed at the end by EFDone(). + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * Adds an entry to hnTable for each HierName. + * + * ---------------------------------------------------------------------------- + */ + +void +efFreeNodeTable(table) + HashTable *table; +{ + HashSearch hs; + HashEntry *he; + HierName *hn; + EFNodeName *nn; + + HashStartSearch(&hs); + while (he = HashNext(table, &hs)) + if (nn = (EFNodeName *) HashGetValue(he)) + { + for (hn = nn->efnn_hier; hn; hn = hn->hn_parent) + (void) HashFind(&efFreeHashTable, (char *) hn); + freeMagic((char *) nn); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * efFreeNodeList -- + * + * Free the circular list of nodes of which 'head' is the head. + * Don't free 'head' itself, since it's statically allocated. + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * + * ---------------------------------------------------------------------------- + */ + +void +efFreeNodeList(head) + EFNode *head; +{ + EFNode *node; + EFAttr *ap; + + for (node = (EFNode *) head->efnode_next; + node != head; + node = (EFNode *) node->efnode_next) + { + for (ap = node->efnode_attrs; ap; ap = ap->efa_next) + freeMagic((char *) ap); + freeMagic((char *) node); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * efFreeConn -- + * + * Free the Connection *conn. + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * + * ---------------------------------------------------------------------------- + */ + +void +efFreeConn(conn) + Connection *conn; +{ + if (conn->conn_name1) freeMagic(conn->conn_name1); + if (conn->conn_name2) freeMagic(conn->conn_name2); + freeMagic((char *) conn); +} diff --git a/extflat/EFdef.c b/extflat/EFdef.c new file mode 100644 index 00000000..13df4a61 --- /dev/null +++ b/extflat/EFdef.c @@ -0,0 +1,266 @@ +/* + * EFdef.c - + * + * Procedures for managing the database of Defs. + * There is a single Def for each .ext file in a hierarchically + * extracted circuit. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFdef.c,v 1.2 2008/12/03 14:12:09 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/utils.h" +#include "utils/malloc.h" +#include "extflat/extflat.h" +#include "extflat/EFint.h" + +/* Initial size of def hash table */ +#define INITDEFSIZE 128 + +/* Initial size of node hash table in each def */ +#define INITNODESIZE 32 + +/* Def hash table itself; maps from def names into pointers to Defs */ +HashTable efDefHashTable; + +/* Hash table used for checking for malloc leaks */ +HashTable efFreeHashTable; + +/* Hash table used for keeping subcircuit parameter names for a device */ +HashTable efDevParamTable; + +/* + * ---------------------------------------------------------------------------- + * + * EFInit -- + * + * Initialize the hash table of def names and global signal names. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +EFInit() +{ + EFLayerNumNames = 1; + EFDevNumTypes = 0; + EFCompat = TRUE; + + HashInit(&efFreeHashTable, 32, HT_WORDKEYS); + HashInit(&efDefHashTable, INITDEFSIZE, 0); + HashInit(&efDevParamTable, 8, HT_STRINGKEYS); + efSymInit(); +} + +/* + * ---------------------------------------------------------------------------- + * + * EFDone -- + * + * Overall cleanup. + * + * Results: + * None. + * + * Side effects: + * Eliminates the def and global name hash tables. + * If malloc tracing is enabled, also frees everything else we + * allocated with malloc. + * + * ---------------------------------------------------------------------------- + */ + +void +EFDone() +{ + Connection *conn; + HashSearch hs; + HashEntry *he; + Kill *kill; + Def *def; + Use *use; + Dev *dev; + int n; + + HashStartSearch(&hs); + while (he = HashNext(&efDefHashTable, &hs)) + { + def = (Def *) HashGetValue(he); + freeMagic(def->def_name); + efFreeNodeTable(&def->def_nodes); + efFreeNodeList(&def->def_firstn); + HashKill(&def->def_nodes); + HashKill(&def->def_dists); + for (use = def->def_uses; use; use = use->use_next) + { + freeMagic(use->use_id); + freeMagic((char *) use); + } + for (conn = def->def_conns; conn; conn = conn->conn_next) + efFreeConn(conn); + for (conn = def->def_caps; conn; conn = conn->conn_next) + efFreeConn(conn); + for (conn = def->def_resistors; conn; conn = conn->conn_next) + efFreeConn(conn); + for (dev = def->def_devs; dev; dev = dev->dev_next) + { + for (n = 0; n < (int)dev->dev_nterm; n++) + if (dev->dev_terms[n].dterm_attrs) + freeMagic((char *) dev->dev_terms[n].dterm_attrs); + freeMagic((char *) dev); + } + for (kill = def->def_kills; kill; kill = kill->kill_next) + { + freeMagic(kill->kill_name); + freeMagic((char *) kill); + } + freeMagic((char *) def); + } + + /* Misc cleanup */ + for (n = 0; n < EFDevNumTypes; n++) freeMagic(EFDevTypes[n]); + + /* Changed from n = 0 to n = 1; First entry "space" is predefined, */ + /* not malloc'd. ---Tim 9/3/02 */ + for (n = 1; n < EFLayerNumNames; n++) freeMagic(EFLayerNames[n]); + + if (EFTech) + { + freeMagic(EFTech); + EFTech = (char *)NULL; + } + + /* Free up all HierNames that were stored in efFreeHashTable */ +/* + HashStartSearch(&hs); + while (he = HashNext(&efFreeHashTable, &hs)) + freeMagic(he->h_key.h_ptr); +*/ + + /* Free up the parameter name tables for each device */ + + HashStartSearch(&hs); + while (he = HashNext(&efDevParamTable, &hs)) + { + DevParam *plist = (DevParam *)HashGetValue(he); + while (plist != NULL) + { + freeMagic(plist->parm_name); + freeMagic(plist); + plist = plist->parm_next; + } + } + HashKill(&efDevParamTable); + + HashKill(&efFreeHashTable); + + /* Final cleanup */ + HashKill(&efDefHashTable); +} + +/* + * ---------------------------------------------------------------------------- + * + * efDefLook -- + * + * Look for a def by the given name in the hash table. + * If the def doesn't exist, return NULL; otherwise, return + * a pointer to the def. + * + * Results: + * Returns a pointer to a def, or NULL if none by that + * name exists. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +Def * +efDefLook(name) + char *name; +{ + HashEntry *he; + + he = HashLookOnly(&efDefHashTable, name); + if (he == (HashEntry*) NULL) + return ((Def *) NULL); + + return ((Def *) HashGetValue(he)); +} + +/* + * ---------------------------------------------------------------------------- + * + * efDefNew -- + * + * Allocate a new def by the given name. + * + * Results: + * Returns a pointer to a def. + * + * Side effects: + * Allocates a new def and initializes it. + * + * ---------------------------------------------------------------------------- + */ + +Def * +efDefNew(name) + char *name; +{ + HashEntry *he; + Def *newdef; + + he = HashFind(&efDefHashTable, name); + newdef = (Def *) mallocMagic((unsigned) (sizeof (Def))); + HashSetValue(he, (char *) newdef); + + newdef->def_name = StrDup((char **) NULL, name); + newdef->def_flags = 0; + newdef->def_scale = 1.0; + newdef->def_conns = (Connection *) NULL; + newdef->def_caps = (Connection *) NULL; + newdef->def_resistors = (Connection *) NULL; + newdef->def_devs = (Dev *) NULL; + newdef->def_uses = (Use *) NULL; + newdef->def_kills = (Kill *) NULL; + + /* Initialize circular list of nodes */ + newdef->def_firstn.efnode_next = (EFNodeHdr *) &newdef->def_firstn; + newdef->def_firstn.efnode_prev = (EFNodeHdr *) &newdef->def_firstn; + + /* Initialize hash table of node names */ + HashInit(&newdef->def_nodes, INITNODESIZE, HT_STRINGKEYS); + + /* Initialize hash table of distances */ + HashInitClient(&newdef->def_dists, INITNODESIZE, HT_CLIENTKEYS, + efHNDistCompare, efHNDistCopy, efHNDistHash, efHNDistKill); + + return (newdef); +} diff --git a/extflat/EFerr.c b/extflat/EFerr.c new file mode 100644 index 00000000..ec80c266 --- /dev/null +++ b/extflat/EFerr.c @@ -0,0 +1,80 @@ +/* + * EFerr.c - + * + * Contains only the routine efReadError(). This used to be in EFread.c, + * but including Tcl/Tk stuff caused definition conflicts. So now it + * gets its own file. Note that *printf routines have been changed to + * the Tx* print routines for compatibility with the Tcl-based version. + * Note also that the standalone executables ext2sim and ext2spice get + * the Tx* functions from utils/LIBtextio.c, whereas the built-in + * "extract" function gets them from textio/txOutput.c. In the Tcl + * version, all these functions are built in, so utils/LIBtextio.c is + * not compiled or linked. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFerr.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "textio/textio.h" + +extern char *efReadFileName; +extern int efReadLineNum; + +#ifdef MAGIC_WRAPPER +extern int Tcl_printf(); +#endif + + +/* + * ---------------------------------------------------------------------------- + * + * efReadError -- + * + * Complain about an error encountered while reading an .ext file. + * Called with a variable number of arguments. + * + * Results: + * None. + * + * Side effects: + * Prints an error message to stderr, complete with offending + * filename and line number. + * + * ---------------------------------------------------------------------------- + */ + +void +efReadError(char *fmt, ...) +{ + va_list args; + + TxError("%s, line %d: ", efReadFileName, efReadLineNum); + va_start(args, fmt); +#ifdef MAGIC_WRAPPER + Tcl_printf(stderr, fmt, args); +#else + vfprintf(stderr, fmt, args); +#endif + va_end(args); + TxFlushErr(); +} diff --git a/extflat/EFflat.c b/extflat/EFflat.c new file mode 100644 index 00000000..62266d0a --- /dev/null +++ b/extflat/EFflat.c @@ -0,0 +1,1155 @@ +/* + * EFflat.c - + * + * Procedures to flatten the hierarchical description built + * by efReadDef(). + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFflat.c,v 1.5 2010/12/16 18:59:03 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "utils/utils.h" +#include "extflat/extflat.h" +#include "extflat/EFint.h" + +/* Initial size of the hash table of all flattened node names */ +#define INITFLATSIZE 1024 + +/* Hash table containing all flattened capacitors */ +HashTable efCapHashTable; + +/* Hash table containing all flattened distances */ +HashTable efDistHashTable; + +/* Head of circular list of all flattened nodes */ +EFNode efNodeList; + +/* Root of the tree being flattened */ +Def *efFlatRootDef; +Use efFlatRootUse; +HierContext efFlatContext; + +/* Forward declarations */ +int efFlatSingleCap(); +void efFlatGlob(); +int efFlatGlobHash(HierName *); +bool efFlatGlobCmp(HierName *, HierName *); +char *efFlatGlobCopy(HierName *); +void efFlatGlobError(EFNodeName *, EFNodeName *); +int efAddNodes(HierContext *, bool); +int efAddOneConn(HierContext *, char *, char *, Connection *); + + +/* + * ---------------------------------------------------------------------------- + * + * EFFlatBuild -- + * + * First pass of flattening a circuit. + * Builds up the flattened tables of nodes, capacitors, etc, depending + * on the bits contained in flags: EF_FLATNODES causes the node table + * to be built, EF_FLATCAPS the internodal capacitor table (implies + * EF_FLATNODES), and EF_FLATDISTS the distance table. + * + * Callers who want various pieces of information should call + * the relevant EFVisit procedures (e.g., EFVisitDevs(), EFVisitCaps(), + * EFVisitNodes(), etc). + * + * Results: + * None. + * + * Side effects: + * Allocates lots of memory. + * Be certain to call EFFlatDone() when this memory is + * no longer needed. + * + * ---------------------------------------------------------------------------- + */ + +void +EFFlatBuild(name, flags) + char *name; /* Name of root def being flattened */ + int flags; /* Say what to flatten; see above */ +{ + efFlatRootDef = efDefLook(name); + if (efHNStats) efHNPrintSizes("before building flattened table"); + + /* Keyed by a full HierName */ + HashInitClient(&efNodeHashTable, INITFLATSIZE, HT_CLIENTKEYS, + efHNCompare, (char *(*)()) NULL, efHNHash, (int (*)()) NULL); + + /* Keyed by a pair of HierNames */ + HashInitClient(&efDistHashTable, INITFLATSIZE, HT_CLIENTKEYS, + efHNDistCompare, efHNDistCopy, efHNDistHash, efHNDistKill); + + /* Keyed by pairs of EFNode pointers (i.e., EFCoupleKeys) */ + HashInit(&efCapHashTable, INITFLATSIZE, HashSize(sizeof (EFCoupleKey))); + + /* Keyed by a string and a HierName */ + HashInitClient(&efHNUseHashTable, INITFLATSIZE, HT_CLIENTKEYS, + efHNUseCompare, (char *(*)()) NULL, efHNUseHash, (int (*)()) NULL); + + /* Circular list of all nodes contains no elements initially */ + efNodeList.efnode_next = (EFNodeHdr *) &efNodeList; + efNodeList.efnode_prev = (EFNodeHdr *) &efNodeList; + + efFlatContext.hc_hierName = (HierName *) NULL; + efFlatContext.hc_use = &efFlatRootUse; + efFlatContext.hc_trans = GeoIdentityTransform; + efFlatContext.hc_x = efFlatContext.hc_y = 0; + efFlatRootUse.use_def = efFlatRootDef; + + if (flags & EF_FLATNODES) + { + if (flags & EF_NOFLATSUBCKT) + efFlatNodesStdCell(&efFlatContext); + else + efFlatNodes(&efFlatContext); + efFlatKills(&efFlatContext); + if (!(flags & EF_NONAMEMERGE)) + efFlatGlob(); + } + + /* Must happen after kill processing */ + if (flags & EF_FLATCAPS) + efFlatCaps(&efFlatContext); + + /* Distances are independent of kill processing */ + if (flags & EF_FLATDISTS) + efFlatDists(&efFlatContext); + + if (efHNStats) efHNPrintSizes("after building flattened table"); + + return; +} + +/*----------------------------------------------------------------------*/ +/* EFFlatBuildOneLevel -- */ +/* */ +/* EFFlatBuild for a single hierarchical level. Note, however that */ +/* where subcircuits have no extracted components, the hierarchy of */ +/* the subcircuit will be traversed and the subcircuit merged into */ +/* the root being flattened. */ +/* */ +/* This routine used for hierarchical extraction. */ +/*----------------------------------------------------------------------*/ + +HierContext * +EFFlatBuildOneLevel(def, flags) + Def *def; /* root def being flattened */ + int flags; +{ + int usecount, savecount; + Use *use; + int efFlatNodesDeviceless(); /* Forward declaration */ + int efFlatCapsDeviceless(); /* Forward declaration */ + + efFlatRootDef = def; + + /* Keyed by a full HierName */ + HashInitClient(&efNodeHashTable, INITFLATSIZE, HT_CLIENTKEYS, + efHNCompare, (char *(*)()) NULL, efHNHash, (int (*)()) NULL); + + /* Keyed by a pair of HierNames */ + HashInitClient(&efDistHashTable, INITFLATSIZE, HT_CLIENTKEYS, + efHNDistCompare, efHNDistCopy, efHNDistHash, efHNDistKill); + + /* Keyed by pairs of EFNode pointers (i.e., EFCoupleKeys) */ + HashInit(&efCapHashTable, INITFLATSIZE, HashSize(sizeof (EFCoupleKey))); + + /* Keyed by a string and a HierName */ + HashInitClient(&efHNUseHashTable, INITFLATSIZE, HT_CLIENTKEYS, + efHNUseCompare, (char *(*)()) NULL, efHNUseHash, (int (*)()) NULL); + + /* Circular list of all nodes contains no elements initially */ + efNodeList.efnode_next = (EFNodeHdr *) &efNodeList; + efNodeList.efnode_prev = (EFNodeHdr *) &efNodeList; + + efFlatContext.hc_hierName = (HierName *) NULL; + efFlatContext.hc_use = &efFlatRootUse; + efFlatContext.hc_trans = GeoIdentityTransform; + efFlatContext.hc_x = efFlatContext.hc_y = 0; + efFlatRootUse.use_def = efFlatRootDef; + + usecount = 0; + + /* Record all nodes of the next level in the hierarchy */ + efHierSrUses(&efFlatContext, efAddNodes, (ClientData)TRUE); + + /* Expand all subcells that contain connectivity information but */ + /* no active devices (including those in subcells). */ + + for (use = efFlatRootUse.use_def->def_uses; use; use = use->use_next) + usecount++; + + /* Recursively flatten uses that have no active devices */ + if (usecount > 0) + efHierSrUses(&efFlatContext, efFlatNodesDeviceless, (ClientData)&usecount); + + if ((usecount == 0) && (efFlatRootUse.use_def->def_devs == NULL)) + efFlatRootUse.use_def->def_flags |= DEF_NODEVICES; + + /* Record all local nodes */ + efAddNodes(&efFlatContext, FALSE); + efAddConns(&efFlatContext); + + efFlatKills(&efFlatContext); + if (!(flags & EF_NONAMEMERGE)) + efFlatGlob(); + if (flags & EF_FLATCAPS) + efFlatCapsDeviceless(&efFlatContext); + if (flags & EF_FLATDISTS) + efFlatDists(&efFlatContext); + + return &efFlatContext; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFFlatDone -- + * + * Cleanup by removing all memory used by the flattened circuit + * representation. + * + * Results: + * None. + * + * Side effects: + * Frees lots of memory. + * + * ---------------------------------------------------------------------------- + */ + +void +EFFlatDone() +{ +#ifdef MALLOCTRACE + /* Hash table statistics */ + TxPrintf("\n\nStatistics for node hash table:\n"); + HashStats(&efNodeHashTable); +#endif /* MALLOCTRACE */ + + /* Free temporary storage */ + efFreeNodeTable(&efNodeHashTable); + efFreeNodeList(&efNodeList); + HashFreeKill(&efCapHashTable); + HashKill(&efNodeHashTable); + HashKill(&efHNUseHashTable); + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * efFlatNodes -- + * + * Recursive procedure to flatten the nodes in hc->hc_use->use_def, + * using a depth-first post-order traversal of the hierarchy. + * + * Algorithm: + * We first recursivly call efFlatNodes for all of our children uses. + * This adds their node names to the global node table. Next we add + * our own nodes to the table. Some nodes will have to be merged + * by connections made in this def, or at least will require adjustments + * to their resistance or capacitance. We walk down the connection + * list hc->hc_use->use_def->def_conns to do this merging. Whenever + * two nodes merge, the EFNodeName list for the resulting node is + * rearranged to begin with the highest precedence name from the lists + * for the two nodes being combined. See efNodeMerge for a discussion + * of precedence. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * Adds node names to the table of flattened node names efNodeHashTable. + * May merge nodes from the list efNodeList as per the connection + * list hc->hc_use->use_def->def_conns. + * + * ---------------------------------------------------------------------------- + */ + +int +efFlatNodes(hc) + HierContext *hc; +{ + (void) efHierSrUses(hc, efFlatNodes); + + /* Add all our own nodes to the table */ + efAddNodes(hc, FALSE); + + /* Process our own connections and adjustments */ + (void) efAddConns(hc); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * efFlatNodesStdCell -- + * + * Recursive procedure to flatten the nodes in hc->hc_use->use_def, + * using a depth-first post-order traversal of the hierarchy. We stop + * whenever we reach a subcircuit definition, only enumerating its ports. + * + * Algorithm: + * We first recursivly call efFlatNodes for all of our children uses. + * This adds their node names to the global node table. Next we add + * our own nodes to the table. Some nodes will have to be merged + * by connections made in this def, or at least will require adjustments + * to their resistance or capacitance. We walk down the connection + * list hc->hc_use->use_def->def_conns to do this merging. Whenever + * two nodes merge, the EFNodeName list for the resulting node is + * rearranged to begin with the highest precedence name from the lists + * for the two nodes being combined. See efNodeMerge for a discussion + * of precedence. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * Adds node names to the table of flattened node names efNodeHashTable. + * May merge nodes from the list efNodeList as per the connection + * list hc->hc_use->use_def->def_conns. + * + * ---------------------------------------------------------------------------- + */ + +int +efFlatNodesStdCell(hc) + HierContext *hc; +{ + if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT)) + { + /* Recursively flatten each use, except in defined subcircuits */ + (void) efHierSrUses(hc, efFlatNodesStdCell, (ClientData) NULL); + } + + /* Add all our own nodes to the table */ + efAddNodes(hc, TRUE); + + /* Process our own connections and adjustments */ + if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT)) + (void) efAddConns(hc); + + return (0); +} + +int +efFlatNodesDeviceless(hc, cdata) + HierContext *hc; + ClientData cdata; +{ + int *usecount = (int *)cdata; + int newcount = 0; + Use *use; + + for (use = hc->hc_use->use_def->def_uses; use; use = use->use_next) + newcount++; + + /* Recursively flatten uses that have no active devices */ + if (newcount > 0) + efHierSrUses(hc, efFlatNodesDeviceless, (ClientData)&newcount); + + if ((hc->hc_use->use_def->def_devs == NULL) && (newcount == 0)) + { + /* Add all our own nodes to the table */ + efAddNodes(hc, TRUE); + + /* Process our own connections and adjustments */ + efAddConns(hc); + + /* Mark this definition as having no devices, so it will not be visited */ + hc->hc_use->use_def->def_flags |= DEF_NODEVICES; + + (*usecount)--; + } + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * efAddNodes -- + * + * Add all the nodes defined by the def 'hc->hc_use->use_def' to the + * global symbol table. Each global name is prefixed by the hierarchical + * name component hc->hc_hierName. If "stdcell" is TRUE, we ONLY add nodes + * that are defined ports. Otherwise, we add all nodes. + * + * Results: + * None. + * + * Side effects: + * Adds node names to the table of flattened node names efNodeHashTable. + * + * ---------------------------------------------------------------------------- + */ + +int +efAddNodes(hc, stdcell) + HierContext *hc; + bool stdcell; +{ + Def *def = hc->hc_use->use_def; + EFNodeName *nn, *newname, *oldname; + EFNode *node, *newnode; + EFAttr *ap, *newap; + HierName *hierName; + float scale; + int size, asize; + HashEntry *he; + bool is_subcircuit = (def->def_flags & DEF_SUBCIRCUIT) ? TRUE : FALSE; + + scale = def->def_scale; + size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (PerimArea); + + for (node = (EFNode *) def->def_firstn.efnode_next; + node != &def->def_firstn; + node = (EFNode *) node->efnode_next) + { + /* In subcircuits, only enumerate the ports */ + if (stdcell && is_subcircuit && !(node->efnode_flags & EF_PORT)) + continue; + + newnode = (EFNode *) mallocMagic((unsigned)(size)); + newnode->efnode_attrs = (EFAttr *) NULL; + for (ap = node->efnode_attrs; ap; ap = ap->efa_next) + { + asize = ATTRSIZE(strlen(ap->efa_text)); + newap = (EFAttr *) mallocMagic((unsigned)(asize)); + (void) strcpy(newap->efa_text, ap->efa_text); + GeoTransRect(&hc->hc_trans, &ap->efa_loc, &newap->efa_loc); + newap->efa_loc.r_xbot = (int)((float)(newap->efa_loc.r_xbot) * scale); + newap->efa_loc.r_xtop = (int)((float)(newap->efa_loc.r_xtop) * scale); + newap->efa_loc.r_ybot = (int)((float)(newap->efa_loc.r_ybot) * scale); + newap->efa_loc.r_ytop = (int)((float)(newap->efa_loc.r_ytop) * scale); + + newap->efa_type = ap->efa_type; + newap->efa_next = newnode->efnode_attrs; + newnode->efnode_attrs = newap; + } + + // If called with "hierarchy on", all local node caps and adjustments + // have been output and should be ignored. + + newnode->efnode_cap = (!stdcell) ? node->efnode_cap : (EFCapValue)0.0; + newnode->efnode_client = (ClientData) NULL; + newnode->efnode_flags = node->efnode_flags; + newnode->efnode_type = node->efnode_type; + if (!stdcell) + bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa, + efNumResistClasses * sizeof (PerimArea)); + else + bzero((char *) newnode->efnode_pa, + efNumResistClasses * sizeof (PerimArea)); + GeoTransRect(&hc->hc_trans, &node->efnode_loc, &newnode->efnode_loc); + + /* Scale the result by "scale" --- hopefully we end up with an integer */ + /* We don't scale the transform because the scale may be non-integer */ + /* and the Transform type has integers only. */ + newnode->efnode_loc.r_xbot = (int)((float)(newnode->efnode_loc.r_xbot) * scale); + newnode->efnode_loc.r_xtop = (int)((float)(newnode->efnode_loc.r_xtop) * scale); + newnode->efnode_loc.r_ybot = (int)((float)(newnode->efnode_loc.r_ybot) * scale); + newnode->efnode_loc.r_ytop = (int)((float)(newnode->efnode_loc.r_ytop) * scale); + + /* Prepend to global node list */ + newnode->efnode_next = efNodeList.efnode_next; + newnode->efnode_prev = (EFNodeHdr *) &efNodeList; + efNodeList.efnode_next->efnhdr_prev = (EFNodeHdr *) newnode; + efNodeList.efnode_next = (EFNodeHdr *) newnode; + + /* Add each name for this node to the hash table */ + newnode->efnode_name = (EFNodeName *) NULL; + + for (nn = node->efnode_name; nn; nn = nn->efnn_next) + { + /* + * Construct the full hierarchical name of this node. + * The path down to this point is given by hc->hc_hierName, + * to which nn->efnn_hier is "appended". Exception: nodes + * marked with EF_DEVTERM (fet substrate nodes used before + * declared, so intended to refer to default global names) + * are added as global nodes. + */ + if (node->efnode_flags & EF_DEVTERM) hierName = nn->efnn_hier; + else hierName = EFHNConcat(hc->hc_hierName, nn->efnn_hier); + he = HashFind(&efNodeHashTable, (char *) hierName); + + /* + * The name should only have been in the hash table already + * if the node was marked with EF_DEVTERM as described above. + */ + if (oldname = (EFNodeName *) HashGetValue(he)) + { + if (hierName != nn->efnn_hier) + EFHNFree(hierName, hc->hc_hierName, HN_CONCAT); + if (oldname->efnn_node != newnode) + efNodeMerge(oldname->efnn_node, newnode); + newnode = oldname->efnn_node; + continue; + } + + /* + * We only guarantee that the first name for the node remains + * first (since the first name is the "canonical" name for the + * node). The order of the remaining names will be reversed. + */ + newname = (EFNodeName *) mallocMagic((unsigned)(sizeof (EFNodeName))); + HashSetValue(he, (char *) newname); + newname->efnn_node = newnode; + newname->efnn_hier = hierName; + if (newnode->efnode_name) + { + newname->efnn_next = newnode->efnode_name->efnn_next; + newnode->efnode_name->efnn_next = newname; + } + else + { + newname->efnn_next = (EFNodeName *) NULL; + newnode->efnode_name = newname; + } + } + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * efAddConns -- + * + * Make all the connections for a given def. This may cause previously + * distinct nodes in the flat table to merge. + * + * Results: + * Returns 0 + * + * Side effects: + * May merge nodes from the list efNodeList as per the connection + * list hc->hc_use->use_def->def_conns. + * + * ---------------------------------------------------------------------------- + */ + +int +efAddConns(hc) + HierContext *hc; +{ + Connection *conn; + + if (efWatchNodes) + TxPrintf("Processing %s (%s)\n", + EFHNToStr(hc->hc_hierName), + hc->hc_use->use_def->def_name); + + for (conn = hc->hc_use->use_def->def_conns; conn; conn = conn->conn_next) + { + /* Special case for speed when no array info is present */ + if (conn->conn_1.cn_nsubs == 0) + efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn); + else + efHierSrArray(hc, conn, efAddOneConn, (ClientData) NULL); + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * efAddOneConn -- + * + * Do the work of adding a single connection. The names of the nodes + * to be connected are 'name1' and 'name2' (note that these are regular + * strings, not HierNames). The resistance of the merged node is to be + * adjusted by 'deltaR' and its capacitance by 'deltaC'. If 'name2' is + * NULL, we just adjust the R and C of the node 'name1'. + * + * Results: + * Returns 0 + * + * Side effects: + * May merge nodes from the list efNodeList. + * + * ---------------------------------------------------------------------------- + */ + +int +efAddOneConn(hc, name1, name2, conn) + HierContext *hc; + char *name1, *name2; /* These are strings, not HierNames */ + Connection *conn; +{ + HashEntry *he1, *he2; + EFNode *node, *newnode; + int n; + + he1 = EFHNLook(hc->hc_hierName, name1, "connect(1)"); + if (he1 == NULL) + return 0; + + /* Adjust the resistance and capacitance of its corresponding node */ + node = ((EFNodeName *) HashGetValue(he1))->efnn_node; + node->efnode_cap += conn->conn_cap; + for (n = 0; n < efNumResistClasses; n++) + { + node->efnode_pa[n].pa_area += conn->conn_pa[n].pa_area; + node->efnode_pa[n].pa_perim += conn->conn_pa[n].pa_perim; + } + + /* Merge this node with conn_name2 if one was specified */ + if (name2) + { + he2 = EFHNLook(hc->hc_hierName, name2, "connect(2)"); + if (he2 == NULL) + return 0; + newnode = ((EFNodeName *) HashGetValue(he2))->efnn_node; + if (node != newnode) + efNodeMerge(node, newnode); + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * efFlatGlob -- + * + * This procedure checks to ensure that all occurrences of the same global + * name are connected. It also adds the reduced form of the global name + * (i.e., the global name with no pathname prefix) to the hash table + * efNodeHashTable, making this the preferred name of the global node. + * + * Algorithm: + * Scan through the node table looking for globals. Add each + * global to a global name table keyed by just the first component + * of the HierName. The value of the entry in this table is set + * initially to the EFNodeName for the first occurrence of the + * global node. If another occurrence of the global name is + * found whose EFNode differs from this one's, it's an error. + * However, we still merge all the pieces of a global node + * into a single one at the end. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efFlatGlob() +{ + EFNodeName *nameFlat, *nameGlob; + EFNode *nodeFlat, *nodeGlob; + HashEntry *heFlat, *heGlob; + HierName *hnFlat, *hnGlob; + HashTable globalTable; + HashSearch hs; + + HashInitClient(&globalTable, INITFLATSIZE, HT_CLIENTKEYS, + efFlatGlobCmp, efFlatGlobCopy, efFlatGlobHash, (int (*)()) NULL); + + /* + * The following loop examines each global name (the last component of + * each flat HierName that ends in the global symbol '!'), using the + * hash table globalTable to keep track of how many times each global + * name has been seen. Each global name should be seen exactly once. + * The only exceptions are fet substrate nodes (nodes marked with the + * flag EF_DEVTERM), which automatically merge with other global nodes + * with the same name, since they're only implicitly connected anyway. + */ + for (nodeFlat = (EFNode *) efNodeList.efnode_next; + nodeFlat != &efNodeList; + nodeFlat = (EFNode *) nodeFlat->efnode_next) + { + /* + * Ignore nodes whose names aren't global. NOTE: we rely on + * the fact that EFHNBest() prefers global names to all others, + * so if the first name in a node's list isn't global, none of + * the rest are either. + */ + nameFlat = nodeFlat->efnode_name; + hnFlat = nameFlat->efnn_hier; + if (!EFHNIsGlob(hnFlat)) + continue; + + /* + * Look for an entry corresponding to the global part of hnFlat + * (only the leaf component) in the global name table. If one + * isn't found, an entry gets created. + */ + heGlob = HashFind(&globalTable, (char *) hnFlat); + nameGlob = (EFNodeName *) HashGetValue(heGlob); + if (nameGlob == NULL) + { + /* + * Create a new EFNodeName that points to nodeFlat, but + * don't link it in to nodeFlat->efnode_name yet. + */ + nameGlob = (EFNodeName *) mallocMagic((unsigned)(sizeof (EFNodeName))); + HashSetValue(heGlob, (ClientData) nameGlob); + nameGlob->efnn_node = nodeFlat; + nameGlob->efnn_hier = (HierName *) heGlob->h_key.h_ptr; + } + else if (nameGlob->efnn_node != nodeFlat) + { + /* + * If either node is a fet substrate node (marked with EF_DEVTERM) + * it's OK to merge them; otherwise, it's an error, but we still + * merge the nodes. When merging, we blow away nodeGlob and + * absorb it into nodeFlat for simplicity in control of the main + * loop. Note that since nameGlob isn't on the efnode_name list + * for nodeGlob, we have to update its node backpointer explicitly. + */ + nodeGlob = nameGlob->efnn_node; + if ((nodeGlob->efnode_flags & EF_DEVTERM) == 0 + && (nodeFlat->efnode_flags & EF_DEVTERM) == 0) + { + efFlatGlobError(nameGlob, nameFlat); + } + efNodeMerge(nodeFlat, nodeGlob); + nameGlob->efnn_node = nodeFlat; + } + } + + /* + * Now make another pass through the global name table, + * prepending the global name (the HierName consisting of + * the trailing component only that was allocated when the + * name was added to globalTable above) to its node, and + * also adding it to the global hash table efNodeHashTable. + */ + HashStartSearch(&hs); + while (heGlob = HashNext(&globalTable, &hs)) + { + /* + * Add the name to the flat node name hash table, and + * prepend the EFNodeName to the node's list, but only + * if the node didn't already exist in efNodeHashTable. + * Otherwise, free nameGlob. + */ + nameGlob = (EFNodeName *) HashGetValue(heGlob); + hnGlob = nameGlob->efnn_hier; + heFlat = HashFind(&efNodeHashTable, (char *) hnGlob); + if (HashGetValue(heFlat) == NULL) + { + nodeFlat = nameGlob->efnn_node; + HashSetValue(heFlat, (ClientData) nameGlob); + nameGlob->efnn_next = nodeFlat->efnode_name; + nodeFlat->efnode_name = nameGlob; + } + else + { + freeMagic((char *) nameGlob); + EFHNFree(hnGlob, (HierName *) NULL, HN_GLOBAL); + } + } + + HashKill(&globalTable); + return; +} + +void +efFlatGlobError(nameGlob, nameFlat) + EFNodeName *nameGlob, *nameFlat; +{ + EFNode *nodeGlob = nameGlob->efnn_node, *nodeFlat = nameFlat->efnn_node; + EFNodeName *nn; + int count; + + TxPrintf("*** Global name %s not fully connected:\n", + nameGlob->efnn_hier->hn_name); + TxPrintf("One portion contains the names:\n"); + for (count = 0, nn = nodeGlob->efnode_name; + count < 10 && nn; + count++, nn = nn->efnn_next) + { + TxPrintf(" %s\n", EFHNToStr(nn->efnn_hier)); + } + if (nn) TxPrintf(" .... (no more names will be printed)\n"); + TxPrintf("The other portion contains the names:\n"); + for (count = 0, nn = nodeFlat->efnode_name; + count < 10 && nn; + count++, nn = nn->efnn_next) + { + TxPrintf(" %s\n", EFHNToStr(nn->efnn_hier)); + } + if (nn) TxPrintf(" .... (no more names will be printed)\n"); + TxPrintf("I'm merging the two pieces into a single node, but you\n"); + TxPrintf("should be sure eventually to connect them in the layout.\n\n"); + return; +} + +bool +efFlatGlobCmp(hierName1, hierName2) + HierName *hierName1, *hierName2; +{ + if (hierName1 == hierName2) + return FALSE; + + return ((bool)(hierName1 == NULL || hierName2 == NULL + || hierName1->hn_hash != hierName2->hn_hash + || strcmp(hierName1->hn_name, hierName2->hn_name) != 0 + )); +} + +char * +efFlatGlobCopy(hierName) + HierName *hierName; +{ + HierName *hNew; + int size; + + size = HIERNAMESIZE(strlen(hierName->hn_name)); + hNew = (HierName *) mallocMagic((unsigned)(size)); + (void) strcpy(hNew->hn_name, hierName->hn_name); + hNew->hn_parent = (HierName *) NULL; + hNew->hn_hash = hierName->hn_hash; + if (efHNStats) + efHNRecord(size, HN_GLOBAL); + + return (char *) hNew; +} + +int +efFlatGlobHash(hierName) + HierName *hierName; +{ + return hierName->hn_hash; +} + +/* + * ---------------------------------------------------------------------------- + * + * efFlatKills -- + * + * Recursively mark all killed nodes, using a depth-first post-order + * traversal of the hierarchy. The algorithm is the same as for + * efFlatNodes above. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * May mark node entries in the global name table as killed + * by setting EF_KILLED in the efnode_flags field. + * + * ---------------------------------------------------------------------------- + */ + +int +efFlatKills(hc) + HierContext *hc; +{ + Def *def = hc->hc_use->use_def; + HashEntry *he; + EFNodeName *nn; + Kill *k; + + /* Recursively visit each use */ + (void) efHierSrUses(hc, efFlatKills, (ClientData) NULL); + + /* Process all of our kill information */ + for (k = def->def_kills; k; k = k->kill_next) + { + if (he = EFHNConcatLook(hc->hc_hierName, k->kill_name, "kill")) + { + nn = (EFNodeName *) HashGetValue(he); + nn->efnn_node->efnode_flags |= EF_KILLED; + } + } + + return (0); +} + + +/*---- + * WIP + *---- + */ + +int +efFlatCapsDeviceless(hc) + HierContext *hc; +{ + Connection *conn; + int newcount = 0; + Use *use; + + for (use = hc->hc_use->use_def->def_uses; use; use = use->use_next) + newcount++; + + /* Recursively flatten uses that have no active devices */ + if (newcount > 0) + efHierSrUses(hc, efFlatCapsDeviceless, (ClientData)NULL); + + if (!(hc->hc_use->use_def->def_flags & DEF_NODEVICES)) + if (hc->hc_use->use_def->def_flags & DEF_PROCESSED) + return 0; + + /* Output our own capacitors */ + for (conn = hc->hc_use->use_def->def_caps; conn; conn = conn->conn_next) + { + /* Special case for speed if no arraying info */ + if (conn->conn_1.cn_nsubs == 0) + efFlatSingleCap(hc, conn->conn_name1, conn->conn_name2, conn); + else + efHierSrArray(hc, conn, efFlatSingleCap, (ClientData) NULL); + } + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * efFlatCaps -- + * + * Recursive procedure to flatten all capacitors in the circuit. + * Produces a single, global hash table (efCapHashTable) indexed + * by pairs of EFNode pointers, where the value of each entry is the + * capacitance between the two nodes. + * + * Algorithm: + * Before this procedure is called, efFlatNodes() should have been + * called to create a global table of all node names. We do a recursive + * traversal of the design rooted at 'hc->hc_use->use_def', and construct + * full hierarchical names from the terminals of each capacitor + * encountered. + * + * These full names are used to find via a lookup in efNodeHashTable the + * canonical name of the node for which this full name is an alias. The + * canonical name is output as the node to which this terminal connects. + * + * Capacitance where one of the nodes is substrate is treated specially; + * instead of adding an entry to the global hash table, we update + * the substrate capacitance of the other node appropriately. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +efFlatCaps(hc) + HierContext *hc; +{ + Connection *conn; + + /* Recursively flatten capacitors */ + (void) efHierSrUses(hc, efFlatCaps, (ClientData) 0); + + /* Output our own capacitors */ + for (conn = hc->hc_use->use_def->def_caps; conn; conn = conn->conn_next) + { + /* Special case for speed if no arraying info */ + if (conn->conn_1.cn_nsubs == 0) + efFlatSingleCap(hc, conn->conn_name1, conn->conn_name2, conn); + else + efHierSrArray(hc, conn, efFlatSingleCap, (ClientData) NULL); + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * efFlatSingleCap -- + * + * Add a capacitor with value 'conn->conn_cap' between the nodes + * 'name1' and 'name2' (text names, not hierarchical names). Don't + * add the capacitor if either terminal is a killed node. + * + * Results: + * Returns 0 + * + * Side effects: + * Adds an entry to efCapHashTable indexed by the nodes of 'name1' + * and 'name2' respectively. If the two nodes are the same, though, + * nothing happens. If either node is ground (GND!), the capacitance + * is added to the substrate capacitance of the other node instead of + * creating a hash table entry. + * + * ---------------------------------------------------------------------------- + */ + +int +efFlatSingleCap(hc, name1, name2, conn) + HierContext *hc; /* Contains hierarchical pathname to cell */ + char *name1, *name2; /* Names of nodes connecting to capacitor */ + Connection *conn; /* Contains capacitance to add */ +{ + EFNode *n1, *n2; + HashEntry *he; + EFCoupleKey ck; + + if ((he = EFHNLook(hc->hc_hierName, name1, "cap(1)")) == NULL) + return 0; + n1 = ((EFNodeName *) HashGetValue(he))->efnn_node; + if (n1->efnode_flags & EF_KILLED) + return 0; + + if ((he = EFHNLook(hc->hc_hierName, name2, "cap(2)")) == NULL) + return 0; + n2 = ((EFNodeName *) HashGetValue(he))->efnn_node; + if (n2->efnode_flags & EF_KILLED) + return 0; + + /* Do nothing if the nodes aren't different */ + if (n1 == n2) + return 0; + + if (n1->efnode_flags & EF_SUBS_NODE) + n2->efnode_cap += conn->conn_cap; /* node 2 to substrate */ + else if (n2->efnode_flags & EF_SUBS_NODE) + n1->efnode_cap += conn->conn_cap; /* node 1 to substrate */ + else + { + /* node1 to node2 */ + if (n1 < n2) ck.ck_1 = n1, ck.ck_2 = n2; + else ck.ck_1 = n2, ck.ck_2 = n1; + he = HashFind(&efCapHashTable, (char *) &ck); + CapHashSetValue(he, (double) (conn->conn_cap + CapHashGetValue(he))); + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * efFlatDists -- + * + * Recursive procedure to flatten all distance information in the circuit. + * Produces a single, global hash table (efDistHashTable) indexed + * by Distance structures, where the value of each entry is the same + * as the key and gives the min and maximum distances between the two + * points. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +efFlatDists(hc) + HierContext *hc; +{ + Distance *dist, *distFlat, distKey; + HashEntry *he, *heFlat; + HashSearch hs; + + /* Recursively flatten distances */ + (void) efHierSrUses(hc, efFlatDists, (ClientData) 0); + + /* Process our own distances */ + HashStartSearch(&hs); + while (he = HashNext(&hc->hc_use->use_def->def_dists, &hs)) + { + dist = (Distance *) HashGetValue(he); + efHNBuildDistKey(hc->hc_hierName, dist, &distKey); + heFlat = HashFind(&efDistHashTable, (char *) &distKey); + if (distFlat = (Distance *) HashGetValue(heFlat)) + { + /* + * This code differs from that in efBuildDist(), in that + * we replace the min/max information in distFlat from + * that in dist, rather than computing a new min/max. + * The reason is that the information in dist (in the + * parent) is assumed to override that already computed + * in the child. + */ + distFlat->dist_min = dist->dist_min; + distFlat->dist_max = dist->dist_max; + EFHNFree(distKey.dist_1, hc->hc_hierName, HN_CONCAT); + EFHNFree(distKey.dist_2, hc->hc_hierName, HN_CONCAT); + } + else + { + /* + * If there was no entry in the table already with this + * key, make the HashEntry point to its key (which is + * the newly malloc'd Distance structure). + */ + HashSetValue(heFlat, (ClientData) he->h_key.h_ptr); + } + } + + return 0; +} + +/* + * CapHashGetValue() + * do a HashGetValue, and if the pointer is null, return (EFCapValue)0.0 + */ + +EFCapValue CapHashGetValue(he) +HashEntry *he; +{ + EFCapValue *capp = (EFCapValue *)HashGetValue(he); + if(capp == NULL) + return (EFCapValue)0; + else + return *capp; +} + +/* + * CapHashSetValue() + * if the pointer is null, allocate a EFCapValue and point to it. + * Then copy in the new value. + * + * need to pass doubles regardless of what CapValue is because of + * argument promotion in ANSI C + * + */ +void +CapHashSetValue(he, c) +HashEntry *he; +double c; +{ + EFCapValue *capp = (EFCapValue *)HashGetValue(he); + if(capp == NULL) { + capp = (EFCapValue *) mallocMagic((unsigned)(sizeof(EFCapValue))); + HashSetValue(he, capp); + } + *capp = (EFCapValue) c; + return; +} diff --git a/extflat/EFhier.c b/extflat/EFhier.c new file mode 100644 index 00000000..599557c3 --- /dev/null +++ b/extflat/EFhier.c @@ -0,0 +1,741 @@ +/* + * EFhier.c - + * + * Procedures for traversing the hierarchical representation + * of a circuit. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFhier.c,v 1.5 2010/12/16 18:59:03 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "utils/utils.h" +#include "extflat/extflat.h" +#include "extflat/EFint.h" + +/* + * ---------------------------------------------------------------------------- + * + * efHierSrUses -- + * + * Visit all the children of hc->hc_use->use_def, keeping the transform + * to flat coordinates and the hierarchical path from the root up to date. + * For each child, calls the function 'func', which should be of the + * following form: + * + * int + * (*func)(hc, cdata) + * HierContext *hc; + * ClientData cdata; + * { + * } + * + * This procedure should return 0 normally, or 1 to abort the search. + * + * Hierarchical names: + * The current hierarchical prefix down to this point is given by the + * the HierName pointed to by hc->hc_hierName. To construct a full + * hierarchical name from a name local to this def, we prepend a + * newly allocated HierName component to hc->hc_hierName. + * + * Results: + * Returns 0 if completed successfully, 1 if aborted. + * + * Side effects: + * Whatever (*func)() does. + * + * ---------------------------------------------------------------------------- + */ + +int +efHierSrUses(hc, func, cdata) + HierContext *hc; + int (*func)(); + ClientData cdata; +{ + int xlo, xhi, ylo, yhi, xbase, ybase, xsep, ysep; + HierContext newhc; + Transform t; + Use *u; + + for (u = hc->hc_use->use_def->def_uses; u; u = u->use_next) + { + newhc.hc_use = u; + if (!IsArray(u)) + { + newhc.hc_hierName = efHNFromUse(&newhc, hc->hc_hierName); + GeoTransTrans(&u->use_trans, &hc->hc_trans, &newhc.hc_trans); + if ((*func)(&newhc, cdata)) + return (1); + continue; + } + + /* Set up for iterating over all array elements */ + if (u->use_xlo <= u->use_xhi) + xlo = u->use_xlo, xhi = u->use_xhi, xsep = u->use_xsep; + else + xlo = u->use_xhi, xhi = u->use_xlo, xsep = -u->use_xsep; + if (u->use_ylo <= u->use_yhi) + ylo = u->use_ylo, yhi = u->use_yhi, ysep = u->use_ysep; + else + ylo = u->use_yhi, yhi = u->use_ylo, ysep = -u->use_ysep; + + GeoTransTrans(&u->use_trans, &hc->hc_trans, &t); + for (newhc.hc_x = xlo; newhc.hc_x <= xhi; newhc.hc_x++) + for (newhc.hc_y = ylo; newhc.hc_y <= yhi; newhc.hc_y++) + { + xbase = xsep * (newhc.hc_x - u->use_xlo); + ybase = ysep * (newhc.hc_y - u->use_ylo); + GeoTransTranslate(xbase, ybase, &t, &newhc.hc_trans); + newhc.hc_hierName = efHNFromUse(&newhc, hc->hc_hierName); + if ((*func)(&newhc, cdata)) + return (1); + } + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * efHierSrArray -- + * + * Iterate over the subscripts in the Connection 'conn', deriving the + * names conn_name1 and conn_name2 for each such subscript, calling + * the supplied procedure for each. + * + * This procedure should be of the following form: + * + * (*proc)(hc, name1, name2, conn, cdata) + * HierContext *hc; + * char *name1; /# Fully-expanded first name #/ + * char *name2; /# Fully-expanded 2nd name, or NULL #/ + * Connection *conn; + * ClientData cdata; + * { + * } + * + * The procedure should return 0 normally, or 1 if it wants us to abort. + * + * Results: + * 0 normally, or 1 if we were aborted. + * + * Side effects: + * Whatever those of 'proc' are. + * + * ---------------------------------------------------------------------------- + */ + +int +efHierSrArray(hc, conn, proc, cdata) + HierContext *hc; + Connection *conn; + int (*proc)(); + ClientData cdata; +{ + char name1[1024], name2[1024]; + int i, j, i1lo, i2lo, j1lo, j2lo; + ConnName *c1, *c2; + + /* + * Only handle three cases: + * 0 subscripts + * 1 subscript + * 2 subscripts + */ + c1 = &conn->conn_1; + c2 = &conn->conn_2; + switch (c1->cn_nsubs) + { + case 0: + return (*proc)(hc, c1->cn_name, c2->cn_name, conn, cdata); + break; + case 1: + i1lo = c1->cn_subs[0].r_lo, i2lo = c2->cn_subs[0].r_lo; + for (i = i1lo; i <= c1->cn_subs[0].r_hi; i++) + { + (void) sprintf(name1, c1->cn_name, i); + if (c2->cn_name) + (void) sprintf(name2, c2->cn_name, i - i1lo + i2lo); + if ((*proc)(hc, name1, c2->cn_name ? name2 : (char *) NULL, + conn, cdata)) + return 1; + } + break; + case 2: + i1lo = c1->cn_subs[0].r_lo, i2lo = c2->cn_subs[0].r_lo; + j1lo = c1->cn_subs[1].r_lo, j2lo = c2->cn_subs[1].r_lo; +#ifdef notdef + (void) printf("[%d:%d,%d:%d] [%d:%d,%d:%d]\n", + i1lo, c1->cn_subs[0].r_hi, + j1lo, c1->cn_subs[1].r_hi, + i2lo, c2->cn_subs[0].r_hi, + j2lo, c2->cn_subs[1].r_hi); +#endif /* notdef */ + for (i = i1lo; i <= c1->cn_subs[0].r_hi; i++) + { + for (j = j1lo; j <= c1->cn_subs[1].r_hi; j++) + { + (void) sprintf(name1, c1->cn_name, i, j); + if (c2->cn_name) + (void) sprintf(name2, c2->cn_name, + i - i1lo + i2lo, j - j1lo + j2lo); + if ((*proc)(hc,name1,c2->cn_name ? name2 : (char *) NULL, + conn, cdata)) + return 1; + } + } + break; + default: + printf("Can't handle > 2 array subscripts\n"); + break; + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHierSrDefs --- + * + * Traverse the cell definition hierarchy, processing each cell once. + * For each definition, call func() with client data argument cdata. + * If func() is NULL, then traverse the hierarchy and mark all cell + * definitions as unprocessed. + * + * ---------------------------------------------------------------------------- + */ + +int +EFHierSrDefs(hc, func, cdata) + HierContext *hc; + int (*func)(); + ClientData cdata; +{ + HierContext newhc; + Use *u; + int retval; + + if (func == NULL) + { + if (!(hc->hc_use->use_def->def_flags & DEF_PROCESSED)) + return 0; + hc->hc_use->use_def->def_flags &= ~DEF_PROCESSED; + } + else + { + if (hc->hc_use->use_def->def_flags & DEF_PROCESSED) + return 0; + hc->hc_use->use_def->def_flags |= DEF_PROCESSED; + } + + for (u = hc->hc_use->use_def->def_uses; u; u = u->use_next) + { + newhc.hc_use = u; + newhc.hc_hierName = NULL; + GeoTransTrans(&u->use_trans, &hc->hc_trans, &newhc.hc_trans); + if (EFHierSrDefs(&newhc, func, cdata)) + return 1; + } + if (func == NULL) + return 0; + else + { + /* Clear DEF_PROCESSED for the duration of running the function */ + + hc->hc_use->use_def->def_flags &= ~DEF_PROCESSED; + retval = (*func)(hc, cdata); + hc->hc_use->use_def->def_flags |= DEF_PROCESSED; + return retval; + } +} + +/*----------------------------------------------------------------------*/ +/* All the routines below have been copied and modified from EFvisit.c. */ +/* They are used for hierarchical output, such as a netlist for LVS. */ +/*----------------------------------------------------------------------*/ + +/* + * ---------------------------------------------------------------------------- + * + * EFHierVisitSubcircuits -- + * + * Visit all of the "defined" subcircuits in the circuit. + * This is meant to provide a generic functionality similar to + * the transistor/resistor/capacitor extraction. It assumes that the + * end-user has an existing description of the extracted subcircuit, + * such as a characterized standard cell, and that magic is not to + * attempt an extraction itself, but only to call the predefined + * subcircuit, matching nodes to the subcircuit's port list. + * + * For each def encountered, call the user-supplied procedure + * (*subProc)(), which should be of the following form: + * + * (*subProc)(hc, use, hierName) + * HierContext *hc; + * bool is_top; + * { + * } + * + * The procedure should return 0 normally, or 1 to abort the search. + * + * Results: + * Returns 0 if terminated normally, or 1 if the search + * was aborted. + * + * Side effects: + * Whatever (*subProc)() does. + * + * ---------------------------------------------------------------------------- + */ + +int +EFHierVisitSubcircuits(hc, subProc, cdata) + HierContext *hc; + int (*subProc)(); + ClientData cdata; /* unused */ +{ + CallArg ca; + int efHierVisitSubcircuits(); /* Forward declaration */ + + /* For each subcell of the top-level def that is defined as */ + /* a subcircuit, call subProc. */ + + ca.ca_proc = subProc; + ca.ca_cdata = (ClientData)hc->hc_use->use_def; /* Save top-level def */ + + if (efHierSrUses(hc, efHierVisitSubcircuits, (ClientData) &ca)) + return 1; + + return 0; +} + +/* + * Procedure to visit recursively all subcircuits in the design. + * Does all the work of EFHierVisitSubcircuits() above. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * Calls the client procedure (*ca->ca_proc)(). + */ + +int +efHierVisitSubcircuits(hc, ca) + HierContext *hc; + CallArg *ca; +{ + /* Visit all children of this def */ + Def *def = (Def *)ca->ca_cdata; + bool is_top = (def == hc->hc_use->use_def) ? TRUE : FALSE; + + if ((*ca->ca_proc)(hc->hc_use, hc->hc_hierName, is_top)) + return 1; + else + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * efHierDevKilled -- + * + * Check all of the nodes to which the dev 'dev' is connected. + * If any of these nodes have been killed, then the dev is also killed. + * + * Results: + * TRUE if the dev is connected to a killed node, FALSE if it's ok. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +efHierDevKilled(hc, dev, prefix) + HierContext *hc; + Dev *dev; + HierName *prefix; +{ + HierName *suffix; + HashEntry *he; + EFNodeName *nn; + int n; + Def *def = hc->hc_use->use_def; + + for (n = 0; n < dev->dev_nterm; n++) + { + suffix = dev->dev_terms[n].dterm_node->efnode_name->efnn_hier; + he = HashLookOnly(&efNodeHashTable, (char *)suffix); + if (he && (nn = (EFNodeName *) HashGetValue(he)) + && (nn->efnn_node->efnode_flags & EF_KILLED)) + return TRUE; + } + + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHierVisitDevs -- + * + * Visit all the devs in the circuit. + * For each dev in the circuit, call the user-supplied procedure + * (*devProc)(), which should be of the following form: + * + * (*devProc)(hc, dev, scale, cdata) + * HierContext *hc; + * Dev *dev; + * float scale; + * ClientData cdata; + * { + * } + * + * The procedure should return 0 normally, or 1 to abort the + * search. + * + * We ensure that no devs connected to killed nodes are passed + * to this procedure. + * + * Results: + * Returns 0 if terminated normally, or 1 if the search + * was aborted. + * + * Side effects: + * Whatever (*devProc)() does. + * + * ---------------------------------------------------------------------------- + */ + +int +EFHierVisitDevs(hc, devProc, cdata) + HierContext *hc; + int (*devProc)(); + ClientData cdata; +{ + CallArg ca; + + ca.ca_proc = devProc; + ca.ca_cdata = cdata; + return efHierVisitDevs(hc, (ClientData) &ca); +} + +/* + * Procedure to visit recursively all devs in the design. + * Does all the work of EFHierVisitDevs() above. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * Calls the client procedure (*ca->ca_proc)(). + */ + +int +efHierVisitDevs(hc, ca) + HierContext *hc; + CallArg *ca; +{ + Def *def = hc->hc_use->use_def; + Dev *dev; + float scale; + + /* + * Note that the transform passed does not transform + * the scale; where def->def_scale != 1.0, the visited + * procedure will have to multiply values by def->def_scale. + */ + + scale = (efScaleChanged && def->def_scale != 1.0) ? def->def_scale : 1.0; + + /* Visit all devices */ + for (dev = def->def_devs; dev; dev = dev->dev_next) + { + if (efHierDevKilled(hc, dev, hc->hc_hierName)) + continue; + + if ((*ca->ca_proc)(hc, dev, scale, ca->ca_cdata)) + return 1; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * efHierVisitSingleResist -- + * + * Visit a resistor of res->conn_res milliohms between the nodes + * 'name1' and 'name2' (text names, not hierarchical names). Don't + * process the resistor if either terminal is a killed node. + * + * Results: + * Whatever the user-supplied procedure (*ca->ca_proc)() returns + * (type int). + * + * Side effects: + * Calls the user-supplied procedure. + * + * ---------------------------------------------------------------------------- + */ + +int +efHierVisitSingleResist(hc, name1, name2, res, ca) + HierContext *hc; /* Contains hierarchical pathname to cell */ + char *name1, *name2; /* Names of nodes connecting to resistor */ + Connection *res; /* Contains resistance to add */ + CallArg *ca; +{ + EFNode *n1, *n2; + HashEntry *he; + Def *def = hc->hc_use->use_def; + + if ((he = HashLookOnly(&def->def_nodes, name1)) == NULL) + return 0; + n1 = ((EFNodeName *) HashGetValue(he))->efnn_node; + if (n1->efnode_flags & EF_KILLED) + return 0; + + if ((he = HashLookOnly(&def->def_nodes, name2)) == NULL) + return 0; + n2 = ((EFNodeName *) HashGetValue(he))->efnn_node; + if (n2->efnode_flags & EF_KILLED) + return 0; + + /* Do nothing if the nodes aren't different */ + if (n1 == n2) + return 0; + + return (*ca->ca_proc)(hc, n1->efnode_name->efnn_hier, + n2->efnode_name->efnn_hier, + res->conn_res, ca->ca_cdata); +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHierVisitResists -- + * + * Visit all the resistors in the circuit. + * For each resistor in the circuit, call the user-supplied procedure + * (*resProc)(), which should be of the following form, where hn1 and + * hn2 are the HierNames of the two nodes connected by the resistor. + * + * (*resProc)(hc, hn1, hn2, resistance, cdata) + * HierContext *hc; + * HierName *hn1, *hn2; + * int resistance; + * ClientData cdata; + * { + * } + * + * The procedure should return 0 normally, or 1 to abort the + * search. + * + * We ensure that no resistors connected to killed nodes are passed + * to this procedure. + * + * Results: + * Returns 0 if terminated normally, or 1 if the search + * was aborted. + * + * Side effects: + * Whatever (*resProc)() does. + * + * ---------------------------------------------------------------------------- + */ + +int +EFHierVisitResists(hc, resProc, cdata) + HierContext *hc; + int (*resProc)(); + ClientData cdata; +{ + CallArg ca; + int efHierVisitResists(); /* Forward reference */ + + ca.ca_proc = resProc; + ca.ca_cdata = cdata; + return efHierVisitResists(hc, (ClientData) &ca); +} + +/* + * Procedure to visit recursively all resistors in the design. + * Does all the work of EFHierVisitResists() above. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * Calls the client procedure (*ca->ca_proc)(). + */ + +int +efHierVisitResists(hc, ca) + HierContext *hc; + CallArg *ca; +{ + Def *def = hc->hc_use->use_def; + Connection *res; + Transform t; + int scale; + + /* Visit all resistors */ + for (res = def->def_resistors; res; res = res->conn_next) + { + /* Special case for speed if no arraying info */ + if (res->conn_1.cn_nsubs == 0) + { + if (efHierVisitSingleResist(hc, res->conn_name1, res->conn_name2, + res, ca)) + return 1; + } + else if (efHierSrArray(hc, res, efHierVisitSingleResist, (ClientData) ca)) + return 1; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHierVisitCaps -- + * + * Visit all the local capacitance records + * Calls the user-provided procedure (*capProc)() + * which should be of the following format: + * + * (*capProc)(hc, hierName1, hierName2, cap, cdata) + * HierContext *hc; + * HierName *hierName1, *hierName2; + * EFCapValue cap; + * ClientData cdata; + * { + * } + * + * Here cap is the capacitance in attofarads. + * + * Results: + * Returns 1 if the client procedure returned 1; + * otherwise returns 0. + * + * Side effects: + * Calls the user-provided procedure (*capProc)(). + * + * ---------------------------------------------------------------------------- + */ + +int +EFHierVisitCaps(hc, capProc, cdata) + HierContext *hc; + int (*capProc)(); + ClientData cdata; +{ + HashSearch hs; + HashEntry *he; + EFCoupleKey *ck; + EFCapValue ccap; + + /* Visit capacitors flattened from a lower level, as well */ + /* as our own. These have been created and saved in */ + /* efCapHashTable using efFlatCaps(). */ + + HashStartSearch(&hs); + while (he = HashNext(&efCapHashTable, &hs)) + { + ccap = CapHashGetValue(he); + ck = (EFCoupleKey *) he->h_key.h_words; + if ((*capProc)(hc, ck->ck_1->efnode_name->efnn_hier, + ck->ck_2->efnode_name->efnn_hier, + (double) ccap, cdata)) + return 1; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHierVisitNodes -- + * + * Visit all the flat nodes in the circuit. + * Calls the user-provided procedure (*nodeProc)() + * which should be of the following format: + * + * (*nodeProc)(hc, hierName1, hierName2, res, cap, cdata) + * HierContext *hc; + * HierName *hierName1, *hierName2; + * int res; + * EFCapValue cap; + * ClientData cdata; + * { + * } + * + * Here cap is the lumped capacitance to substrate in attofarads, + * and res is the lumped resistance to substrate in milliohms. + * + * Results: + * Returns 1 if the client procedure returned 1; + * otherwise returns 0. + * + * Side effects: + * Calls the user-provided procedure (*nodeProc)(). + * + * ---------------------------------------------------------------------------- + */ + +int +EFHierVisitNodes(hc, nodeProc, cdata) + HierContext *hc; + int (*nodeProc)(); + ClientData cdata; +{ + Def *def = hc->hc_use->use_def; + EFCapValue cap; + int res; + EFNode *snode; + HierName *hierName; + + for (snode = (EFNode *) efNodeList.efnode_next; + snode != &efNodeList; + snode = (EFNode *) snode->efnode_next) + { + res = EFNodeResist(snode); + cap = snode->efnode_cap; + hierName = (HierName *) snode->efnode_name->efnn_hier; + if (snode->efnode_flags & EF_SUBS_NODE) + cap = 0; + + if (snode->efnode_flags & EF_KILLED) continue; + + if ((*nodeProc)(hc, snode, res, (double)cap, cdata)) + return 1; + } + return 0; +} + diff --git a/extflat/EFint.h b/extflat/EFint.h new file mode 100644 index 00000000..01a3b49d --- /dev/null +++ b/extflat/EFint.h @@ -0,0 +1,321 @@ +/* + * EFint.h -- + * + * Internal definitions for the procedures to flatten hierarchical + * (.ext) circuit extraction files. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/extflat/EFint.h,v 1.6 2010/12/16 18:59:03 tim Exp $ + */ + +#ifndef _EFINT_H +#define _EFINT_H + +#include "utils/magic.h" + +/* + * Add in the next character value to a hash sum. + * This function uses a 4-bit rotate to ensure that "ab" and "ba" + * hash to different values; the 4 bits of rotation are provided + * to allow even short strings to produce large hash values. + * (Small hash values don't get randomized very well). + * + *************************************************************** + * BE VERY CAREFUL ABOUT CHANGING THIS! IT CAN MAKE AN ENORMOUS + * DIFFERENCE TO THE PERFORMANCE OF THE HASHING ALGORITHM! + *************************************************************** + */ +#define HASHADDVAL(sum, val) \ + (((((unsigned) (sum)) >> 28) | (((unsigned) (sum)) << 4)) + (val)) + +/* ------------------------ Distance information ---------------------- */ + +/* + * The .ext file also allows explicit distance information to be + * represented. This information is stored in a hash table in each + * Def, keyed by this same structure. Distances are between named + * signals, rather than nodes, so we use HierNames instead of EFNodes + * for the two points between which distance is measured. + */ +typedef struct dist +{ + int dist_min, dist_max; /* Min and max distance (lambda) */ + HierName *dist_1, *dist_2; /* Two points */ +} Distance; + +/* ------------------------- Kill information ------------------------- */ + +/* + * In order for resistance and distance extraction to work correctly, + * it's sometimes necessary to override the structure of the graph + * extracted at a lower level of the hierarchy. The "killnode" line + * in a .ext file specifies that a given node, and everything that + * connects to it, have been re-extracted and are represented in + * flat format later in the .ext file. + * + * The kill list bisects the .ext file. Fets, resistors, distance + * info, etc that appear before the first killnode in a .ext file + * are processed by the flattener before processing the kill list + * for a given cell, followed by processing those fets, resistors, + * etc that appear after the first killnode line. + * + * To allow the distinction to be made between before-kill and after-kill + * processing, node structures have a flag field that can have the + * EF_AFTERKILL bit set, indicating that the node appeared after + * the killnode lines. This information isn't necessary for capacitors, + * resistors, or fets, since they are implicitly killed whenever any + * of their terminals is connected to a killed node. + */ +typedef struct kill +{ + struct kill *kill_next; /* Next kill in def */ + HierName *kill_name; /* Node to kill */ +} Kill; + +/* --------------------------- Connections ---------------------------- */ + +/* + * Connections are used for a multitude of purposes. They all + * boil down to a need to represent hierarchical names with some + * array range information present. + * + * Connections are used to represent that two nodes must be merged, + * and the resultant node's resistance and capacitance adjusted + * (conn_name2 non-NULL), or that the resistance and capacitance + * of a single node be adjusted (conn_name2 NULL). + * + * They are also used to represent internodal capacitors when + * they appear on the def_caps list of a Def, or explicit resistors + * when appearing on the def_resistors list. In these latter cases, + * both conn_name1 and conn_name2 are non-NULL. + */ + + /* Max number of dimensions in an array */ +#define MAXSUBS 2 + + /* Subscripts range from r_lo to r_hi inclusive; r_lo <= r_hi */ +typedef struct +{ + int r_lo, r_hi; +} Range; + + /* + * Each node in the connection may be accompanied by subscripts. + * The range of values of the subscripts are stored here. + * When cn_nsubs is 2, cn_subs[0] is x, cn_subs[1] is y. + */ +typedef struct +{ + char *cn_name; + int cn_nsubs; + Range cn_subs[MAXSUBS]; +} ConnName; + + /* Connection itself */ +typedef struct conn +{ + ConnName conn_1; /* First node in connection */ + ConnName conn_2; /* Second (optional) node in connection */ + union { + float conn_val_res; /* Value of capacitance (attofarads) or */ + EFCapValue conn_val_cap; /* resistance (milliohms). */ + } conn_value; + + struct conn *conn_next; /* Next connection in list */ + PerimArea conn_pa[1]; /* Dummy; each connection actually has + * efNumResistClasses array elements + * allocated to it. + */ +} Connection; + + /* Abbreviations */ +#define conn_name1 conn_1.cn_name +#define conn_name2 conn_2.cn_name +#define conn_res conn_value.conn_val_res +#define conn_cap conn_value.conn_val_cap + +/* -------------------------- Defs and uses --------------------------- */ + +/* A Def exists for each .ext file */ +typedef struct def +{ + char *def_name; /* Name of this def */ + float def_scale; /* Multiply all dimensions by this */ + int def_flags; /* Flags -- see below */ + HashTable def_nodes; /* Map names into EFNodeNames */ + HashTable def_dists; /* Map pairs of names into Distances */ + EFNode def_firstn; /* Head of circular list of nodes */ + + /* The following are all NULL-terminated lists */ + + struct use *def_uses; /* Children of this def */ + Connection *def_conns; /* Hierarchical connections/adjustments */ + Connection *def_caps; /* Two-terminal capacitors */ + Connection *def_resistors; /* Two-terminal resistors */ + Dev *def_devs; /* Devices */ + Kill *def_kills; /* Used to modify hierarchical structure + * using information present only in the + * parent, e.g, to kill an old node and + * all its attached fets prior to replacing + * the node with several smaller ones, + * connected by explicit resistors. + */ +} Def; + +#define DEF_AVAILABLE 0x01 /* This def has been read in */ +#define DEF_SUBCIRCUIT 0x02 /* This def defines subcircuit ports */ +#define DEF_PROCESSED 0x04 /* This def processed in hierarchical output */ +#define DEF_NODEVICES 0x08 /* This def contains no devices */ +#define DEF_SUBSNODES 0x10 /* This def contains implicit substrate nodes */ + +/* + * Every Def has a NULL-terminated list of uses that correspond + * to the subcells of that Def. If the use is an array, the ArrayInfo + * structure describes the indices and the separation between elements + * (for computing transforms). + */ +#ifndef _DATABASE_H +typedef struct +{ + int ar_xlo, ar_xhi; + int ar_ylo, ar_yhi; + int ar_xsep, ar_ysep; +} ArrayInfo; +#endif /* _DATABASE_H */ + +typedef struct use +{ + char *use_id; /* Use identifier (appears in hier paths) */ + Def *use_def; /* Sub def being used */ + // EFNodeName *use_ports; /* Port connections, for hierarchical output */ + struct use *use_next; /* Next use in list (NULL-terminated) */ + Transform use_trans; /* Transform up to parent coords (for fets) */ + ArrayInfo use_array; /* Arraying information */ +} Use; + +#define use_xlo use_array.ar_xlo +#define use_xhi use_array.ar_xhi +#define use_ylo use_array.ar_ylo +#define use_yhi use_array.ar_yhi +#define use_xsep use_array.ar_xsep +#define use_ysep use_array.ar_ysep + +#define IsArray(u) ((u)->use_xlo!=(u)->use_xhi || (u)->use_ylo!=(u)->use_yhi) + +/* -------------------------------------------------------------------- */ + +/* Structure passed down during hierarchical searching */ +typedef struct +{ + Use *hc_use; /* Use being visited */ + int hc_x, hc_y; /* X and Y indices if array */ + Transform hc_trans; /* Transform to flat coordinates (for fets) */ + HierName *hc_hierName; /* Ptr to trailing component of HierName list */ +} HierContext; + +/* ------------------------------ Debugging --------------------------- */ + +extern bool efHNStats; /* TRUE if we keep statistics on HierNames */ + +/* -------------------------------------------------------------------- */ + +/* Structure for passing procedures and cdata to client functions */ +typedef struct +{ + int (*ca_proc)(); + ClientData ca_cdata; +} CallArg; + +/* -------------------------------------------------------------------- */ + +/* + * Structure used as key in hash table of internodal capacitors. + * Keys are EFNodes, since capacitors exist between a pair of electrical + * nodes. The keys are ordered so that the lowest-address EFNode is + * first. + */ +typedef struct +{ + EFNode *ck_1, *ck_2; +} EFCoupleKey; + +/* -------------------------------------------------------------------- */ + +/* Max filename length */ +#define FNSIZE 1024 + + /* Resistance is in milliohms, capacitance in attofarads */ +extern bool efWarn; /* If TRUE, warn about unusual occurrences */ +extern bool efScaleChanged; /* If TRUE, multiply all dimensions by scale + * factor on output; otherwise, leave them + * alone and output a global scale factor + * of efScale in the .sim file. + */ + +extern int efResists[]; /* Resistance per square for each class */ +extern bool efResistChanged; /* TRUE if some cells' resistclasses unequal */ + +extern HashTable efFreeHashTable; +extern HashTable efNodeHashTable; +extern HashTable efDevParamTable; +extern HashTable efHNUseHashTable; +extern HashTable efCapHashTable; +extern HashTable efDistHashTable; +extern HashTable efWatchTable; +extern bool efWatchNodes; +extern EFNode efNodeList; +extern Def *efFlatRootDef; + +/* --------------------- Internally used procedures ------------------- */ + + /* Def table management */ +extern Def *efDefLook(); +extern Def *efDefNew(); +extern Def *EFRootDef(); + + /* HierName manipulation */ +extern HierName *efHNFromUse(); +extern char *efHNToStrFunc(); + + /* Functions for hashing of HierNames */ +extern int efHNCompare(); +extern int efHNHash(HierName *); + + /* Functions for hashing of Distances */ +extern bool efHNDistCompare(); +extern char *efHNDistCopy(); +extern int efHNDistHash(); +extern void efHNDistKill(); + + /* Functions for hashing of use id HierNames */ +extern bool efHNUseCompare(); +extern int efHNUseHash(); + +extern EFCapValue CapHashGetValue(); +extern void CapHashSetValue(); + + /* efBuild procedures */ +/* Warning: The capacitance argument to these should be always double + regardless of whether you set EFCapValue to float or double + This should be done to avoid trouble with argument promotion + that some ANSI C compilers introduce */ + +extern DevParam *efGetDeviceParams(); +extern void efBuildNode(); +extern void efBuildConnect(); +extern void efBuildResistor(); +extern void efBuildCap(); +extern HierContext *EFFlatBuildOneLevel(); + +#endif /* _EFINT_H */ diff --git a/extflat/EFname.c b/extflat/EFname.c new file mode 100644 index 00000000..527d18a2 --- /dev/null +++ b/extflat/EFname.c @@ -0,0 +1,1000 @@ +/* + * EFhier.c - + * + * Procedures for manipulating HierNames. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFname.c,v 1.2 2010/08/10 00:18:45 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "utils/utils.h" +#include "extflat/extflat.h" +#include "extflat/EFint.h" + +#ifdef MAGIC_WRAPPER +#define PrintErr TxError +#else +#define PrintErr printf +#endif + +/* + * Hash table containing all flattened node names. + * The keys in this table are HierNames, processed by the + * procedures efHNCompare(), efHNHash(), efHierCopy(), + * and efHierKill(). + */ +HashTable efNodeHashTable; + +/* + * Hash table used by efHNFromUse to ensure that it always returns + * a pointer to the SAME HierName structure each time it is called + * with the same fields. + */ +HashTable efHNUseHashTable; + +extern void EFHNFree(); +extern void efHNInit(); +extern void efHNRecord(); + + +/* + * ---------------------------------------------------------------------------- + * + * EFHNIsGlob -- + * + * Determine whether a HierName is of the format of a global name, + * i.e, it ends in a '!'. + * + * The Tcl version of magic further refines this to include names + * which are defined in the global Tcl variable space. (7.3.94): + * also check if the array variable "globals" contains the name as + * a key entry. + * + * Results: + * TRUE if the name is a global. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +EFHNIsGlob(hierName) + HierName *hierName; +{ +#ifdef MAGIC_WRAPPER + char *retstr; + retstr = (char *)Tcl_GetVar2(magicinterp, "globals", hierName->hn_name, + TCL_GLOBAL_ONLY); + if (retstr != NULL) return TRUE; + + retstr = (char *)Tcl_GetVar(magicinterp, hierName->hn_name, TCL_GLOBAL_ONLY); + if (retstr != NULL) return TRUE; +#endif + return hierName->hn_name[strlen(hierName->hn_name) - 1] == '!'; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHNIsGND -- + * + * Determine whether a HierName is the same as the global signal GND. + * + * The Tcl version of magic expands this to include names which are + * equal to the global Tcl variable $GND, if it is set. + * + * This is only used in substrate backwards-compatibility mode, when the + * substrate is not specified in the technology file. + * + * Results: + * TRUE if the name is GND, false if not. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +EFHNIsGND(hierName) + HierName *hierName; +{ +#ifdef MAGIC_WRAPPER + char *retstr; +#endif + + if (hierName->hn_parent != (HierName *)NULL) return FALSE; + +#ifdef MAGIC_WRAPPER + retstr = (char *)Tcl_GetVar(magicinterp, "GND", TCL_GLOBAL_ONLY); + if (retstr != NULL) + if (!strcmp(hierName->hn_name, retstr)) return TRUE; +#endif + + return (strcmp(hierName->hn_name, "GND!") == 0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * EFHNConcat -- + * + * Given a HierName prefix and a HierName suffix, make a newly allocated + * copy of the suffix that points to the prefix. + * + * Results: + * Pointer to the new HierName as described above. + * + * Side effects: + * May allocate memory. + * + * ---------------------------------------------------------------------------- + */ + +HierName * +EFHNConcat(prefix, suffix) + HierName *prefix; /* Components of name on root side */ + HierName *suffix; /* Components of name on leaf side */ +{ + HierName *new, *prev; + HierName *firstNew; + unsigned size; + + for (firstNew = prev = (HierName *) NULL; + suffix; + prev = new, suffix = suffix->hn_parent) + { + size = HIERNAMESIZE(strlen(suffix->hn_name)); + new = (HierName *) mallocMagic((unsigned)(size)); + if (efHNStats) efHNRecord(size, HN_CONCAT); + new->hn_hash = suffix->hn_hash; + (void) strcpy(new->hn_name, suffix->hn_name); + if (prev) + prev->hn_parent = new; + else + firstNew = new; + } + prev->hn_parent = prefix; + + return firstNew; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFStrToHN -- + * + * Given a hierarchical prefix (the HierName pointed to by prefix) + * and a name relative to that prefix (the string 'suffixStr'), return a + * pointer to the HierName we should use. Normally, this is just a newly + * built HierName containing the path components of 'suffixStr' appended to + * prefix. + * + * Results: + * Pointer to a name determined as described above. + * + * Side effects: + * May allocate new HierNames. + * + * ---------------------------------------------------------------------------- + */ + +HierName * +EFStrToHN(prefix, suffixStr) + HierName *prefix; /* Components of name on side of root */ + char *suffixStr; /* Leaf part of name (may have /'s) */ +{ + char *cp; + HashEntry *he; + char *slashPtr; + HierName *hierName; + unsigned size; + int len; + + /* Skip to the end of the relative name */ + slashPtr = NULL; + for (cp = suffixStr; *cp; cp++) + if (*cp == '/') + slashPtr = cp; + + /* + * Convert the relative name into a HierName path, with one HierName + * created for each slash-separated segment of suffixStr. + */ + cp = slashPtr = suffixStr; + for (;;) + { + if (*cp == '/' || *cp == '\0') + { + size = HIERNAMESIZE(cp - slashPtr); + hierName = (HierName *) mallocMagic((unsigned)(size)); + if (efHNStats) efHNRecord(size, HN_ALLOC); + efHNInit(hierName, slashPtr, cp); + hierName->hn_parent = prefix; + if (*cp++ == '\0') + break; + slashPtr = cp; + prefix = hierName; + } + else cp++; + } + + return hierName; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHNToStr -- + * + * Convert a HierName chain into a printable name. + * Stores the result in a static buffer. + * + * Results: + * Returns a pointer to the static buffer containing the + * printable name. + * + * Side effects: + * Overwrites the previous contents of the static buffer. + * + * ---------------------------------------------------------------------------- + */ + +char * +EFHNToStr(hierName) + HierName *hierName; /* Name to be converted */ +{ + static char namebuf[2048]; + + (void) efHNToStrFunc(hierName, namebuf); + return namebuf; +} + +/* + * efHNToStrFunc -- + * + * Recursive part of name conversion. + * Calls itself recursively on hierName->hn_parent and dstp, + * adding the prefix of the pathname to the string pointed to + * by dstp. Then stores hierName->hn_name at the end of the + * just-stored prefix, and returns a pointer to the end. + * + * Results: + * Returns a pointer to the null byte at the end of + * all the pathname components stored so far in dstp. + * + * Side effects: + * Stores characters in dstp. + */ + +char * +efHNToStrFunc(hierName, dstp) + HierName *hierName; /* Name to be converted */ + char *dstp; /* Store name here */ +{ + char *srcp; + + if (hierName == NULL) + { + *dstp = '\0'; + return dstp; + } + + if (hierName->hn_parent) + { + dstp = efHNToStrFunc(hierName->hn_parent, dstp); + *dstp++ = '/'; + } + + srcp = hierName->hn_name; + while (*dstp++ = *srcp++) + /* Nothing */; + + return --dstp; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHNLook -- + * + * Look for the entry in the efNodeHashTable whose name is formed + * by concatenating suffixStr to prefix. If there's not an + * entry in efNodeHashTable, or the entry has a NULL value, complain + * and return NULL; otherwise return the HashEntry. + * + * The string errorStr should say what we were processing, e.g, + * "fet", "connect(1)", "connect(2)", etc., for use in printing + * error messages. If errorStr is NULL, we don't print any error + * messages. + * + * Results: + * See above. + * + * Side effects: + * Allocates memory temporarily to build the key for HashLookOnly(), + * but then frees it before returning. + * + * ---------------------------------------------------------------------------- + */ + +HashEntry * +EFHNLook(prefix, suffixStr, errorStr) + HierName *prefix; /* Components of name on root side */ + char *suffixStr; /* Part of name on leaf side */ + char *errorStr; /* Explanatory string for errors */ +{ + HierName *hierName, *hn; + bool dontFree = FALSE; + HashEntry *he; + + if (suffixStr == NULL) + { + hierName = prefix; + dontFree = TRUE; + } + else hierName = EFStrToHN(prefix, suffixStr); + + he = HashLookOnly(&efNodeHashTable, (char *) hierName); + if (he == NULL || HashGetValue(he) == NULL) + { + if (errorStr) + PrintErr("%s: no such node %s\n", errorStr, EFHNToStr(hierName)); + he = NULL; + } + + /* + * Free the portion of the HierName we just allocated for + * looking in the table, if we allocated one. + */ + if (!dontFree) + EFHNFree(hierName, prefix, HN_ALLOC); + + return he; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHNConcatLook -- + * + * Like EFHNLook above, but the argument suffix is itself a HierName. + * We construct the full name by concatenating the hierarchical prefix + * and the node name 'suffix', then looking it up in the flat node + * table for its real name. + * + * Results: + * See EFHNLook()'s comments. + * + * Side effects: + * See EFHNLook()'s comments. + * + * ---------------------------------------------------------------------------- + */ + +HashEntry * +EFHNConcatLook(prefix, suffix, errorStr) + HierName *prefix; /* Components of name on root side */ + HierName *suffix; /* Part of name on leaf side */ + char *errorStr; /* Explanatory string for errors */ +{ + HashEntry *he; + HierName *hn; + + /* + * Find the last component of the suffix, then temporarily + * link the HierNames for use as a hash key. This is safe + * because HashLookOnly() doesn't ever store anything in the + * hash table, so we don't have to worry about this temporarily + * built key somehow being saved without our knowledge. + */ + hn = suffix; + while (hn->hn_parent) + hn = hn->hn_parent; + hn->hn_parent = prefix; + + he = HashLookOnly(&efNodeHashTable, (char *) suffix); + if (he == NULL || HashGetValue(he) == NULL) + { + PrintErr("%s: no such node %s\n", errorStr, EFHNToStr(suffix)); + he = (HashEntry *) NULL; + } + + /* Undo the temp link */ + hn->hn_parent = (HierName *) NULL; + return he; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHNFree -- + * + * Free a list of HierNames, up to but not including the element pointed + * to by 'prefix' (or the NULL indicating the end of the HierName list). + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * + * ---------------------------------------------------------------------------- + */ + +void +EFHNFree(hierName, prefix, type) + HierName *hierName, *prefix; + int type; /* HN_ALLOC, HN_CONCAT, etc */ +{ + HierName *hn; + + for (hn = hierName; hn; hn = hn->hn_parent) + { + if (hn == prefix) + break; + + freeMagic((char *) hn); + if (efHNStats) + { + int len = strlen(hn->hn_name); + efHNRecord(-HIERNAMESIZE(len), type); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHNBest -- + * + * Determine which of two names is more preferred. The most preferred + * name is a global name. Given two non-global names, the one with the + * fewest pathname components is the most preferred. If the two names + * have equally many pathname components, we choose the shortest. + * If they both are of the same length, we choose the one that comes + * later in the alphabet. + * + * Results: + * TRUE if the first name is preferable to the second, FALSE if not. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +EFHNBest(hierName1, hierName2) + HierName *hierName1, *hierName2; +{ + int ncomponents1, ncomponents2, len1, len2; + HierName *np1, *np2; + char last1, last2; + + for (ncomponents1 = 0, np1 = hierName1; np1; np1 = np1->hn_parent) + ncomponents1++; + for (ncomponents2 = 0, np2 = hierName2; np2; np2 = np2->hn_parent) + ncomponents2++; + + last1 = hierName1->hn_name[strlen(hierName1->hn_name) - 1]; + last2 = hierName2->hn_name[strlen(hierName2->hn_name) - 1]; + if (last1 != '!' || last2 != '!') + { + /* Prefer global over local names */ + if (last1 == '!') return TRUE; + if (last2 == '!') return FALSE; + + /* Neither name is global, so chose label over generated name */ + if (last1 != '#' && last2 == '#') return TRUE; + if (last1 == '#' && last2 != '#') return FALSE; + } + + /* + * Compare two names the hard way. Both are of the same class, + * either both global or both non-global, so compare in order: + * number of pathname components, length, and lexicographic + * ordering. + */ + if (ncomponents1 < ncomponents2) return TRUE; + if (ncomponents1 > ncomponents2) return FALSE; + + /* Non-default substrate node name is preferred over "0" */ + if (ncomponents1 == 1 && !strcmp(hierName1->hn_name, "0")) return FALSE; + if (ncomponents2 == 1 && !strcmp(hierName2->hn_name, "0")) return TRUE; + + /* Same # of pathname components; check length */ + for (len1 = 0, np1 = hierName1; np1; np1 = np1->hn_parent) + len1 += strlen(np1->hn_name); + for (len2 = 0, np2 = hierName2; np2; np2 = np2->hn_parent) + len2 += strlen(np2->hn_name); + if (len1 < len2) return TRUE; + if (len1 > len2) return FALSE; + + return (efHNLexOrder(hierName1, hierName2) > 0); +} + +/* + * ---------------------------------------------------------------------------- + * + * efHNLexOrder -- + * + * Procedure to ensure that the canonical ordering used in determining + * preferred names is the same as would have been used if we were comparing + * the string version of two HierNames, instead of comparing them as pathnames + * with the last component first. + * + * Results: + * Same as strcmp(), i.e, + * -1 if hierName1 should precede hierName2 lexicographically, + * +1 if hierName1 should follow hierName2, and + * 0 is they are identical. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +efHNLexOrder(hierName1, hierName2) + HierName *hierName1, *hierName2; +{ + int i; + + if (hierName1 == hierName2) + return 0; + + if (hierName1->hn_parent) + if (i = efHNLexOrder(hierName1->hn_parent, hierName2->hn_parent)) + return i; + + return strcmp(hierName1->hn_name, hierName2->hn_name); +} + +/* + * ---------------------------------------------------------------------------- + * + * efHNFromUse -- + * + * Construct a HierName for a cell use (for the array element identified + * by (hc_x, hc_y) if the use is an array). The parent pointer of this + * newly allocated HierName will be set to prefix. + * + * Results: + * Returns a pointer to a newly allocated HierName. + * + * Side effects: + * See above. + * Note: we use a hash table to ensure that we always return + * the SAME HierName whenever prefix, the (x, y) use + * coordinates, and the use id are the same. + * + * ---------------------------------------------------------------------------- + */ + +HierName * +efHNFromUse(hc, prefix) + HierContext *hc; /* Contains use and array information */ + HierName *prefix; /* Root part of name */ +{ + char *srcp, *dstp; + char name[2048], *namePtr; + Use *u = hc->hc_use; + HierName *hierName; + bool hasX, hasY; + HashEntry *he; + unsigned size; + + hasX = u->use_xlo != u->use_xhi; + hasY = u->use_ylo != u->use_yhi; + namePtr = u->use_id; + if (hasX || hasY) + { + namePtr = name; + srcp = u->use_id; + dstp = name; + while (*dstp++ = *srcp++) + /* Nothing */; + + /* Array subscript */ + dstp[-1] = '['; + + /* Y comes before X */ + if (hasY) + { + (void) sprintf(dstp, "%d", hc->hc_y); + while (*dstp++) + /* Nothing */; + dstp--; /* Leave pointing to NULL byte */ + } + + if (hasX) + { + if (hasY) *dstp++ = ','; + (void) sprintf(dstp, "%d", hc->hc_x); + while (*dstp++) + /* Nothing */; + dstp--; /* Leave pointing to NULL byte */ + } + + *dstp++ = ']'; + *dstp = '\0'; + } + + size = HIERNAMESIZE(strlen(namePtr)); + hierName = (HierName *) mallocMagic ((unsigned)(size)); + if (efHNStats) efHNRecord(size, HN_FROMUSE); + efHNInit(hierName, namePtr, (char *) NULL); + hierName->hn_parent = prefix; + + /* See if we already have an entry for this one */ + he = HashFind(&efHNUseHashTable, (char *) hierName); + if (HashGetValue(he)) + { + freeMagic((char *) hierName); + return (HierName *) HashGetValue(he); + } + HashSetValue(he, (ClientData) hierName); + + (void) HashFind(&efFreeHashTable, (char *) hierName); + + return hierName; +} + +/* + * ---------------------------------------------------------------------------- + * + * efHNUseCompare -- + * + * Compare two HierNames for equality, but using a different sense + * of comparison than efHNCompare: two names are considered equal + * only if their hn_parent fields are equal and their hn_name strings + * are identical. + * + * Results: Returns 0 if they are equal, 1 if not. + * + * efHNUseHash -- + * + * Convert a HierName to a single 32-bit value suitable for being + * turned into a hash bucket by the hash module. Hashes based on + * hierName->hn_hash and hierName->hn_parent, rather than summing + * the hn_hash values. + * + * Results: Returns the 32-bit hash value. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +efHNUseCompare(hierName1, hierName2) + HierName *hierName1, *hierName2; +{ + return ((bool)(hierName1->hn_parent != hierName2->hn_parent + || strcmp(hierName1->hn_name, hierName2->hn_name) + )); +} + +int +efHNUseHash(hierName) + HierName *hierName; +{ + return hierName->hn_hash + (spointertype) hierName->hn_parent; +} + +/* + * ---------------------------------------------------------------------------- + * + * efHNInit -- + * + * Copy the string 'cp' into hierName->hn_name, also initializing + * the hn_hash fields of hierName. If 'endp' is NULL, copy all + * characters in 'cp' up to a trailing NULL byte; otherwise, copy + * up to 'endp'. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efHNInit(hierName, cp, endp) + HierName *hierName; /* Fill in fields of this HierName */ + char *cp; /* Start of name to be stored in hn_name */ + char *endp; /* End of name if non-NULL; else, see above */ +{ + unsigned hashsum; + char *dstp; + + hashsum = 0; + dstp = hierName->hn_name; + if (endp) + { + while (cp < endp) + { + hashsum = HASHADDVAL(hashsum, *cp); + *dstp++ = *cp++; + } + *dstp = '\0'; + } + else + { + while (*dstp++ = *cp) + hashsum = HASHADDVAL(hashsum, *cp++); + } + + hierName->hn_hash = hashsum; +} + +/* + * ---------------------------------------------------------------------------- + * + * efHNCompare -- + * + * Compare two HierNames for equality. Passed as a client procedure + * to the hash module. The most likely place for a difference in the + * two names is in the lowest-level component, which fortunately is + * the first in a HierName list. + * + * Results: + * Returns 0 if they are equal, 1 if not. + * + * efHNHash -- + * + * Convert a HierName to a single 32-bit value suitable for being + * turned into a hash bucket by the hash module. Passed as a client + * procedure to the hash module. + * + * Results: + * Returns the 32-bit hash value. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +efHNCompare(hierName1, hierName2) + HierName *hierName1, *hierName2; +{ + while (hierName1) + { + if (hierName1 == hierName2) + return 0; + + if (hierName2 == NULL + || hierName1->hn_hash != hierName2->hn_hash + || strcmp(hierName1->hn_name, hierName2->hn_name) != 0) + return 1; + hierName1 = hierName1->hn_parent; + hierName2 = hierName2->hn_parent; + } + + return (hierName2 ? 1 : 0); +} + +int +efHNHash(hierName) + HierName *hierName; +{ + int n; + + for (n = 0; hierName; hierName = hierName->hn_parent) + n += hierName->hn_hash; + + return n; +} + +/* + * ---------------------------------------------------------------------------- + * + * efHNDistCompare -- + * efHNDistCopy -- + * efHNDistHash -- + * efHNDistKill -- + * + * Procedures for managing a HashTable whose keys are pointers + * to malloc'd Distance structures. Distances point to a pair of + * HierNames; the comparison and hashing functions rely directly + * on those for processing HierNames (efHNCompare() and efHNHash()). + * + * Results: + * efHNDistCompare returns 0 if the two keys are equal, 1 if not. + * efHNDistCopy returns a pointer to a malloc'd copy of its Distance + * argument. + * efHNDistHash returns a single 32-bit hash value based on a Distance's + * two HierNames. + * efHNDistKill has no return value. + * + * Side effects: + * efHNDistKill frees its Distance argument, and adds the HierNames + * pointed to by it to the table of HierNames to free. + * + * ---------------------------------------------------------------------------- + */ + +bool +efHNDistCompare(dist1, dist2) + Distance *dist1, *dist2; +{ + return ((bool)(efHNCompare(dist1->dist_1, dist2->dist_1) + || efHNCompare(dist1->dist_2, dist2->dist_2) + )); +} + +char * +efHNDistCopy(dist) + Distance *dist; +{ + Distance *distNew; + + distNew = (Distance *) mallocMagic ((unsigned)(sizeof (Distance))); + *distNew = *dist; + return (char *) distNew; +} + +int +efHNDistHash(dist) + Distance *dist; +{ + return efHNHash(dist->dist_1) + efHNHash(dist->dist_2); +} + + +void +efHNDistKill(dist) + Distance *dist; +{ + HierName *hn; + + for (hn = dist->dist_1; hn; hn = hn->hn_parent) + (void) HashFind(&efFreeHashTable, (char *) hn); + for (hn = dist->dist_2; hn; hn = hn->hn_parent) + (void) HashFind(&efFreeHashTable, (char *) hn); + + freeMagic((char *) dist); +} + +/* + * ---------------------------------------------------------------------------- + * + * efHNBuildDistKey -- + * + * Build the key for looking in the Distance hash table for efFlatDists() + * above. + * + * Results: + * None. + * + * Side effects: + * Sets up *distKey. + * + * ---------------------------------------------------------------------------- + */ + +void +efHNBuildDistKey(prefix, dist, distKey) + HierName *prefix; + Distance *dist; + Distance *distKey; +{ + HierName *hn1, *hn2; + + hn1 = EFHNConcat(prefix, dist->dist_1); + hn2 = EFHNConcat(prefix, dist->dist_2); + if (EFHNBest(hn1, hn2)) + { + distKey->dist_1 = hn1; + distKey->dist_2 = hn2; + } + else + { + distKey->dist_1 = hn2; + distKey->dist_2 = hn1; + } + + distKey->dist_min = dist->dist_min; + distKey->dist_max = dist->dist_max; +} + +/* + * ---------------------------------------------------------------------------- + * + * efHNDump -- + * + * Print all the names in the node hash table efNodeHashTable. + * Used for debugging. + * + * Results: + * None. + * + * Side effects: + * Creates a file "hash.dump" and writes the node names to + * it, one per line. + * + * ---------------------------------------------------------------------------- + */ + +void +efHNDump() +{ + HashSearch hs; + HashEntry *he; + FILE *f; + + f = fopen("hash.dump", "w"); + if (f == NULL) + { + perror("hash.dump"); + return; + } + + HashStartSearch(&hs); + while (he = HashNext(&efNodeHashTable, &hs)) + fprintf(f, "%s\n", EFHNToStr((HierName *) he->h_key.h_ptr)); + + (void) fclose(f); +} + +int efHNSizes[4]; + +void +efHNRecord(size, type) + int size; + int type; +{ + efHNSizes[type] += size; +} + +void +efHNPrintSizes(when) + char *when; +{ + int total, i; + + total = 0; + for (i = 0; i < 4; i++) + total += efHNSizes[i]; + + printf("Memory used in HierNames %s:\n", when ? when : ""); + printf("%8d bytes for global names\n", efHNSizes[HN_GLOBAL]); + printf("%8d bytes for concatenated HierNames\n", efHNSizes[HN_CONCAT]); + printf("%8d bytes for names from cell uses\n", efHNSizes[HN_FROMUSE]); + printf("%8d bytes for names from strings\n", efHNSizes[HN_ALLOC]); + printf("--------\n"); + printf("%8d bytes total\n", total); +} diff --git a/extflat/EFread.c b/extflat/EFread.c new file mode 100644 index 00000000..9eed3752 --- /dev/null +++ b/extflat/EFread.c @@ -0,0 +1,715 @@ +/* + * EFread.c - + * + * Procedures to read a .ext file and call the procedures + * in EFbuild.c to build up a description of each def. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFread.c,v 1.4 2009/01/30 03:51:02 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#include "commands/commands.h" +#include "database/database.h" +#include "extflat/extflat.h" +#include "extflat/EFint.h" +#include "extract/extract.h" +#include "utils/paths.h" + +#ifndef MAGIC_WRAPPER +/* This must match the definition for extDevTable in extract/ExtBasic.c */ +char *extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres", + "devcap", "devcaprev", "diode", "pdiode", "ndiode", + "subckt", "rsubckt", "msubckt", NULL}; +#endif + +/* + * The following table describes the kinds of lines + * that may be read in a .ext file. + */ +typedef enum +{ + ADJUST, ATTR, CAP, DEVICE, DIST, EQUIV, FET, KILLNODE, MERGE, NODE, + PARAMETERS, PORT, RESISTOR, RESISTCLASS, RNODE, SCALE, SUBCAP, + SUBSTRATE, TECH, TIMESTAMP, USE, VERSION, EXT_STYLE +} Key; + +static struct +{ + char *k_name; /* Name of first token on line */ + Key k_key; /* Internal name for token of this type */ + int k_mintokens; /* Min total # of tokens on line of this type */ +} +keyTable[] = +{ + "adjust", ADJUST, 4, + "attr", ATTR, 8, + "cap", CAP, 4, + "device", DEVICE, 11, /* effectively replaces "fet" */ + "distance", DIST, 4, + "equiv", EQUIV, 3, + "fet", FET, 12, /* for backwards compatibility */ + "killnode", KILLNODE, 2, + "merge", MERGE, 3, + "node", NODE, 7, + "parameters", PARAMETERS, 3, + "port", PORT, 8, + "resist", RESISTOR, 4, + "resistclasses", RESISTCLASS, 1, + "rnode", RNODE, 5, + "scale", SCALE, 4, + "subcap", SUBCAP, 3, + "substrate", SUBSTRATE, 3, + "tech", TECH, 2, + "timestamp", TIMESTAMP, 2, + "use", USE, 9, + "version", VERSION, 2, + "style", EXT_STYLE, 2, + 0 +}; + +/* Data shared with EFerror.c */ +char *efReadFileName; /* Name of file currently being read */ +int efReadLineNum; /* Current line number in above file */ + +/* Data local to this file */ +static bool efReadDef(); + +/* atoCap - convert a string to a EFCapValue */ +#define atoCap(s) ((EFCapValue)atof(s)) + + +/* + * ---------------------------------------------------------------------------- + * + * EFReadFile -- + * + * Main procedure to read a .ext file. If there is no Def by the + * name of 'name', allocates a new one. Calls efReadDef to do the + * work of reading the def itself. If 'dosubckt' is true, then port + * mappings are kept. If 'resist' is true, read in the .res.ext file + * (from extresist) if it exists, after reading the .ext file. + * + * Results: + * Passes on the return value of efReadDef (see below) + * + * Side effects: + * See above. + * Leaves EFTech set to the technology specified with the -T flag + * if there was one. Leaves EFScale set to 1 if it changed while + * reading the .ext files. + * + * ---------------------------------------------------------------------------- + */ + +bool +EFReadFile(name, dosubckt, resist, noscale) + char *name; /* Name of def to be read in */ + bool dosubckt, resist; +{ + Def *def; + bool rc; + + def = efDefLook(name); + if (def == NULL) + def = efDefNew(name); + + rc = efReadDef(def, dosubckt, resist, noscale, TRUE); + if (EFArgTech) EFTech = StrDup((char **) NULL, EFArgTech); + if (EFScale == 0.0) EFScale = 1.0; + + return rc; +} + +/* + * ---------------------------------------------------------------------------- + * + * efReadDef -- + * + * Procedure to read in a Def. Actually does the work of reading + * the file 'def->def_name'.ext to build up the fields of the new + * def, then recursively reads all uses of this def that haven't + * yet been read. + * + * Results: + * Returns TRUE if successful, FALSE if the file for 'name' + * could not be found or we encountered errors. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +bool +efReadDef(def, dosubckt, resist, noscale, toplevel) + Def *def; + bool dosubckt, resist, noscale, toplevel; +{ + int argc, ac, n; + EFCapValue cap; + char line[1024], *argv[64], *name, *attrs; + int rscale = 1; /* Multiply resistances by this */ + int cscale = 1; /* Multiply capacitances by this */ + float lscale = 1.0; /* Multiply lambda by this */ + FILE *inf; + Use *use; + Rect r; + bool rc = TRUE; + bool DoResist = resist; + bool DoSubCircuit = dosubckt; + + /* Mark def as available */ + def->def_flags |= DEF_AVAILABLE; + name = def->def_name; + inf = PaOpen(name, "r", ".ext", EFSearchPath, EFLibPath, &efReadFileName); + if (inf == NULL) + { + /* Complementary to .ext file write: If file is in a read-only */ + /* directory, then .ext file is written to CWD. */ + char *proot; + proot = strrchr(name, '/'); + if (proot != NULL) + inf = PaOpen(proot + 1, "r", ".ext", ".", ".", &efReadFileName); + } + if (inf == NULL) + { +#ifdef MAGIC_WRAPPER + char *tclres = Tcl_Alloc(128); + sprintf(tclres, "Cannot read extract file %s.ext\n", name); + Tcl_SetResult(magicinterp, tclres, TCL_DYNAMIC); +#else + perror(name); +#endif + return FALSE; + } + +readfile: + efReadLineNum = 0; + while ((argc = efReadLine(line, sizeof line, inf, argv)) >= 0) + { + n = LookupStruct(argv[0], (LookupTable *) keyTable, sizeof keyTable[0]); + if (n < 0) + { + efReadError("Unrecognized token \"%s\" (ignored)\n", argv[0]); + continue; + } + if (argc < keyTable[n].k_mintokens) + { + efReadError("Not enough tokens for %s line\n", argv[0]); + continue; + } + + switch (keyTable[n].k_key) + { + /* scale rscale cscale lscale */ + case SCALE: + rscale = atoi(argv[1]); + if (rscale == 0) + { + efReadError("Bad resistance scaling = 0; reset to 1.\n"); + rscale = 1; + } + cscale = atoi(argv[2]); + if (cscale == 0) + { + efReadError("Bad capacitance scaling = 0; reset to 1.\n"); + cscale = 1; + } + lscale = (float)atof(argv[3]); + if (lscale == 0.0) + { + efReadError("Bad linear scaling = 0; reset to 1.\n"); + lscale = 1.0; + } + if (noscale == FALSE) + { + def->def_scale = lscale; + if (EFScale != lscale) + { + if (EFScale != 0) efScaleChanged = TRUE, EFScale = 1.0; + else EFScale = lscale; + } + } + break; + + /* attr node xlo ylo xhi yhi type text */ + case ATTR: + r.r_xbot = atoi(argv[2]); + r.r_ybot = atoi(argv[3]); + r.r_xtop = atoi(argv[4]); + r.r_ytop = atoi(argv[5]), + efBuildAttr(def, argv[1], &r, argv[6], argv[7]); + break; + + /* cap node1 node2 capacitance */ + case CAP: + cap = cscale*atoCap(argv[3]); + efBuildCap(def, argv[1], argv[2], (double) cap); + break; + + /* subcap node capacitance */ + case SUBCAP: + cap = cscale*atoCap(argv[2]); + efAdjustSubCap(def, argv[1], cap); + break; + + /* equiv node1 node2 */ + case EQUIV: + efBuildEquiv(def, argv[1], argv[2]); + break; + + /* replaces "fet" (below) */ + /* device mosfet|bjt|subckt type xlo ylo xhi yhi */ + /* area perim [substrate] GATE T1 T2 ... */ + /* device res|cap|rsubckt type xlo ylo xhi yhi value */ + /* GATE T1 T2 ... */ + case DEVICE: + /* Parse device class */ + for (n = 0; extDevTable[n] != NULL; n++) + if (!strcmp(argv[1], extDevTable[n])) + break; + + if (extDevTable[n] == NULL) + { + efReadError("Unknown device class\n"); + continue; + } + switch (n) + { + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_BJT: + ac = 10; + break; + case DEV_DIODE: + case DEV_NDIODE: + case DEV_PDIODE: + ac = 7; + break; + case DEV_CAP: + case DEV_CAPREV: + case DEV_RES: + if (!strcmp(argv[2], "None")) /* Has device value */ + ac = 8; + else + ac = 9; /* Has device L and W */ + break; + case DEV_SUBCKT: + case DEV_MSUBCKT: + case DEV_RSUBCKT: + ac = 7; /* Actually can have many arguments, which */ + break; /* we will deal with in efBuildDevice(). */ + } + + r.r_xbot = atoi(argv[3]); + r.r_ybot = atoi(argv[4]); + r.r_xtop = atoi(argv[5]); + r.r_ytop = atoi(argv[6]); + + if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, + &argv[7]) != 0) + { + efReadError("Incomplete terminal description for device\n"); + continue; + } + break; + + /* for backwards compatibility */ + /* fet type xlo ylo xhi yhi area perim substrate GATE T1 T2 ... */ + case FET: + r.r_xbot = atoi(argv[2]); + r.r_ybot = atoi(argv[3]); + r.r_xtop = atoi(argv[4]); + r.r_ytop = atoi(argv[5]); + if (efBuildDevice(def, DEV_FET, argv[1], &r, argc - 6, &argv[6]) != 0) + { + efReadError("Incomplete terminal description for fet\n"); + continue; + } + break; + + /* merge node1 node2 C a1 p1 a2 p2 ... */ + case MERGE: + /* Redundant merge lines are purposely generated with */ + /* no area and perimeter values; these should not be */ + /* flagged as errors. */ + + /* + if (argc > 4) && (argc - 4 < 2 * efNumResistClasses)) + { + efReadError("Too few area/perim values: " + "assuming remainder are zero\n"); + } + */ + + /* cap = (argc > 3) ? atoCap(argv[3]) * cscale : 0; */ + /* 3/1/2017: Cap adjustments now handled under SUBCAP. */ + efBuildConnect(def, argv[1], argv[2], (double)0.0, &argv[4], argc - 4); + break; + + /* node name R C x y layer a1 p1 a2 p2 ... [ attrs ] */ + case NODE: + case SUBSTRATE: + attrs = NULL; + ac = argc - 7; + if (ac & 01) + attrs = argv[argc-1], ac--; + if (ac < 2*efNumResistClasses) + { + efReadError( + "Too few area/perim values: assuming remainder are zero\n"); + } + /* Note: resistance is ignored; we use perim/area instead */ + cap = atoCap(argv[3])*cscale; + efBuildNode(def, + (keyTable[n].k_key == SUBSTRATE) ? TRUE : FALSE, + argv[1], (double) cap, + atoi(argv[4]), atoi(argv[5]), argv[6], + &argv[7], ac); + break; + + /* parameters name */ + case PARAMETERS: + efBuildDeviceParams(argv[1], argc - 2, &argv[2]); + break; + + /* port name num xl yl xh yh type */ + case PORT: + if (DoSubCircuit) + { + DoResist = FALSE; + def->def_flags |= DEF_SUBCIRCUIT; + efBuildPortNode(def, argv[1], atoi(argv[2]), atoi(argv[3]), + atoi(argv[4]), argv[7]); + } + break; + + /* + * rnode name R C x y layer + * These are nodes resulting from resistance extraction and + * so have no "intrinsic" resistance per se. + */ + case RNODE: + cap = atoCap(argv[3])*cscale; + efBuildNode(def, FALSE, argv[1], (double) cap, + atoi(argv[4]), atoi(argv[5]), argv[6], + (char **) NULL, 0); + break; + + /* resist r1 r2 ... */ + case RESISTCLASS: + if (efNumResistClasses == 0) + { + efNumResistClasses = argc-1; + for (n = 0; n < efNumResistClasses; n++) + efResists[n] = atoi(argv[n + 1]); + } + else if (efNumResistClasses != argc-1) + { + efReadError("Number of resistance classes doesn't match:\n"); +resistChanged: + efReadError("Re-extract the entire tree with " + "the same technology file\n"); + efResistChanged = TRUE; + break; + } + for (n = 0; n < efNumResistClasses; n++) + if (efResists[n] != atoi(argv[n + 1])) + { + efReadError("Resistance class values don't match:\n"); + goto resistChanged; + } + break; + + /* use def use-id T0 .. T5 */ + case USE: + efBuildUse(def, argv[1], argv[2], + atoi(argv[3]), atoi(argv[4]), atoi(argv[5]), + atoi(argv[6]), atoi(argv[7]), atoi(argv[8])); + break; + + /* tech techname */ + case TECH: +#ifdef MAGIC_WRAPPER + if (strcmp(argv[1], DBTechName)) + { + /* If we are running in batch mode and no layout is */ + /* present, then load the new technology. */ + + if (CmdCheckForPaintFunc()) + { + TxError("Error: .ext file has different technology %s\n", + argv[1]); + TxError("Load this technology and repeat.\n"); + rc = FALSE; + break; + } + else + { + TxError("Loading technology %s\n", argv[1]); + if (!TechLoad(argv[1], 0)) + { + TxError("Error in loading technology file\n"); + rc = FALSE; + break; + } + else + EFTech = StrDup((char **) NULL, argv[1]); + } + } +#else + if (EFTech && EFTech[0]) + { + if (strcmp(EFTech, argv[1]) != 0) + { + efReadError("Technology %s doesn't match initial " + "technology %s\n", EFTech, argv[1]); + rc = FALSE; + break; + } + } +#endif + else EFTech = StrDup((char **) NULL, argv[1]); + + if (!EFLibPath[0]) /* Put in a path if there wasn't one */ + (void) sprintf(EFLibPath, EXT_PATH, EFTech); + break; + + /* ext_style stylename */ + case EXT_STYLE: +#ifdef MAGIC_WRAPPER + if (ExtCompareStyle(argv[1]) == FALSE) + { + TxError("Warning: .ext file style %s is not known " + "in this technology!\n", argv[1]); + if (EFStyle) + { + freeMagic(EFStyle); + EFStyle = NULL; + } + } +#else + if (EFStyle) + { + if (strcmp(EFStyle, argv[1]) != 0) + { + efReadError("Extraction style doesn't match: %s\n", argv[1]); + rc = FALSE; + break; + } + } +#endif + else + EFStyle = StrDup(&EFStyle, argv[1]); + break; + + /* version version-number */ + case VERSION: + if (strcmp(argv[1], EFVersion) != 0) + { + efReadError( + "Cell was extracted using version %s of the extractor.\n", argv[1]); + efReadError(" It should be re-extracted.\n"); + } + break; + + /* distance driver receiver min max */ + case DIST: + efBuildDist(def, argv[1], argv[2], + (int)(lscale*atoi(argv[3])), + (int)(lscale*atoi(argv[4]))); + break; + + /* killnode nodename */ + case KILLNODE: + efBuildKill(def, argv[1]); + break; + + /* resistor node1 node2 resistance */ + case RESISTOR: + efBuildResistor(def, argv[1], argv[2], rscale*atoi(argv[3])); + break; + + /* To-do: compare timestamp against the cell */ + case TIMESTAMP: + break; + + /* Ignore the rest for now */ + case ADJUST: /* Unused */ + default: + break; + } + } + (void) fclose(inf); + + /* Is there an "extresist" extract file? */ + if (DoResist) + { + DoResist = FALSE; /* do this only once */ + inf = PaOpen(name, "r", ".res.ext", EFSearchPath, EFLibPath, &efReadFileName); + if (inf != NULL) + goto readfile; + } + + /* If we are considering standard cells, only the first level of */ + /* subcircuits is meaningful. */ + + if ((def->def_flags & DEF_SUBCIRCUIT) && (toplevel != TRUE)) + DoSubCircuit = FALSE; + + /* Read in each def that has not yet been read in */ + for (use = def->def_uses; use; use = use->use_next) + if ((use->use_def->def_flags & DEF_AVAILABLE) == 0) + if (efReadDef(use->use_def, DoSubCircuit, resist, noscale, FALSE) + != TRUE) + rc = FALSE; + + return rc; +} + +/* + * ---------------------------------------------------------------------------- + * + * efReadLine -- + * + * Read a line from a .ext file and split it up into tokens. + * Blank lines are ignored. Lines ending in backslash are joined + * to their successor lines. Lines beginning with '#' are considered + * to be comments and are ignored. + * + * Results: + * Returns the number of tokens into which the line was split, or + * -1 on end of file. Never returns 0. + * + * Side effects: + * Copies the line just read into 'line'. The trailing newline + * is turned into a '\0'. The line is broken into tokens which + * are then placed into argv. Updates *plinenum to point to the + * current line number in 'file'. + * + * ---------------------------------------------------------------------------- + */ + +int +efReadLine(line, size, file, argv) + char *line; /* Character array into which line is read */ + int size; /* Size of character array */ + FILE *file; /* Open .ext file */ + char *argv[]; /* Vector of tokens built by efReadLine() */ +{ + char *get, *put; + bool inquote; + int argc = 0; + + /* Read one line into the buffer, joining lines when they end in '\' */ +start: + get = line; + while (size > 0) + { + efReadLineNum += 1; + if (fgets(get, size, file) == NULL) return (-1); + for (put = get; *put != '\n'; put++) size -= 1; + if ((put != get) && (*(put-1) == '\\')) + { + get = put-1; + continue; + } + *put= '\0'; + break; + } + if (size == 0) efReadError("long line truncated\n"); + + get = put = line; + + if (*line == '#') goto start; /* Ignore comments */ + + while (*get != '\0') + { + /* Skip leading blanks */ + while (isspace(*get)) get++; + + /* Beginning of the token is here */ + argv[argc] = put = get; + inquote = FALSE; + + /* + * Grab up characters to the end of the token. Any character + * preceded by a backslash is taken literally. + */ + while (*get != '\0') + { + if (inquote) + { + if (*get == '"') + { + get++; + inquote = FALSE; + continue; + } + } + else + { + if (isspace(*get)) + break; + if (*get == '"') + { + get++; + inquote = TRUE; + continue; + } + } + + if (*get == '\\') /* Process quoted characters literally */ + { + get++; + if (*get == '\0') break; + } + + /* Copy into token receiving area */ + *put++ = *get++; + } + + /* + * If we got no characters in the token, we must have been at + * the end of the line. + */ + if (get == argv[argc]) + break; + + /* Terminate the token and advance over the terminating character. */ + + if (*get != '\0') get++; /* Careful! could be at end of line! */ + *put++ = '\0'; + argc++; + } + + if (argc == 0) + goto start; + + return (argc); +} diff --git a/extflat/EFsym.c b/extflat/EFsym.c new file mode 100644 index 00000000..d3d1fcd2 --- /dev/null +++ b/extflat/EFsym.c @@ -0,0 +1,203 @@ +/* + * EFsym.c - + * + * Procedures for managing symbolic names. + * Such names are used to assign values to things like transistor dimensions. + * When an attribute of the form "ext:what=value" is attached to a fet, the + * corresponding quantity 'what' for that fet is set to 'value'. The 'value' + * can be symbolic, allowing us to change it during flattening without having + * to re-extract. The binding between symbolic names and numeric values is + * set up by calls to efSymAdd(). Recognized values of 'what' are: + * + * w, l + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFsym.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "utils/utils.h" +#include "extflat/extflat.h" +#include "extflat/EFint.h" + +/* Forward declarations */ +bool efSymAdd(); + +HashTable efSymHash; + +/* + * ---------------------------------------------------------------------------- + * + * efSymInit -- + * + * Initialize the hash table 'efSymHash' used for symbolic name assignments. + * Called by EFInit(). + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efSymInit() +{ + HashInit(&efSymHash, 16, HT_STRINGKEYS); +} + +/* + * ---------------------------------------------------------------------------- + * + * efSymAddFile -- + * + * Read the file 'name' for symbol assignments. Each line of the file + * should be of the form name=value. We add each symbol 'name' to efSymHash + * with value 'value'. + * + * Results: + * TRUE on success, FALSE on an error in opening 'name'. + * + * Side effects: + * Adds symbols to the hash table. + * Complains if we can't open the file or if errors are encountered + * while reading it. + * + * ---------------------------------------------------------------------------- + */ + +bool +efSymAddFile(name) + char *name; +{ + char line[1024], *cp; + int lineNum; + FILE *f; + + f = fopen(name, "r"); + if (f == NULL) + { + perror(name); + return FALSE; + } + + for (lineNum = 1; fgets(line, sizeof line, f); lineNum++) + { + if (cp = strchr(line, '\n')) + *cp = '\0'; + if (!efSymAdd(line)) + TxError("Error at line %d of %s\n", lineNum, name); + } + fclose(f); + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * + * efSymAdd -- + * + * Given a string of the form name=value, add the symbol 'name' to efSymHash + * with value 'value'. + * + * Results: + * TRUE normally, FALSE if the input was malformed or resulted in + * assigning a new value to an existing name. + * + * Side effects: + * Adds a symbol to the hash table. + * Complains if we have to return FALSE. + * + * ---------------------------------------------------------------------------- + */ + +bool +efSymAdd(str) + char *str; +{ + HashEntry *he; + char *value; + + value = strchr(str, '='); + if (value == NULL) + { + TxError("Missing '=' in symbol assignment\n"); + return FALSE; + } + + value++; + if (!StrIsInt(value)) + { + TxError("Symbol value must be numeric; ignoring \"%s\"\n", str); + return FALSE; + } + + value[-1] = '\0'; + if (he = HashLookOnly(&efSymHash, str)) + { + TxError("Symbol \"%s\" already defined\n", str); + value[-1] = '='; + return FALSE; + } + + he = HashFind(&efSymHash, str); + value[-1] = '='; + HashSetValue(he, (spointertype)atoi(value)); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * efSymLook -- + * + * Look up the value of a symbol and store the value in *pValue. + * + * Results: + * TRUE if the symbol was defined, FALSE if not. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +bool +efSymLook(name, pValue) + char *name; + int *pValue; +{ + HashEntry *he; + + he = HashLookOnly(&efSymHash, name); + if (he == NULL) + return FALSE; + + *pValue = (spointertype) HashGetValue(he); + return TRUE; +} diff --git a/extflat/EFvisit.c b/extflat/EFvisit.c new file mode 100644 index 00000000..4e0f991e --- /dev/null +++ b/extflat/EFvisit.c @@ -0,0 +1,905 @@ +/* + * EFvisit.c - + * + * Procedures to traverse and output flattened nodes, capacitors, + * transistors, resistors, and Distances. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFvisit.c,v 1.5 2010/08/10 00:18:45 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "utils/utils.h" +#include "extflat/extflat.h" +#include "extflat/EFint.h" +#include "extract/extract.h" + +/* Root of the tree being flattened */ +extern Def *efFlatRootDef; +extern Use efFlatRootUse; +extern HierContext efFlatContext; + +extern void efDevFixLW(); +extern void efHNOutPrefix(); + +bool efDevKilled(); + +/* + * ---------------------------------------------------------------------------- + * + * EFVisitSubcircuits -- + * + * Visit all of the "defined" subcircuits in the circuit. + * This is meant to provide a generic functionality similar to + * the transistor/resistor/capacitor extraction. It assumes that the + * end-user has an existing description of the extracted subcircuit, + * such as a characterized standard cell, and that magic is not to + * attempt an extraction itself, but only to call the predefined + * subcircuit, matching nodes to the subcircuit's port list. + * + * For each def encountered which has the DEF_SUBCIRCUIT flag set, + * call the user-supplied procedure (*subProc)(), which should be of + * the following form: + * + * (*subProc)(use, hierName, is_top) + * Use *use; + * HierName *hierName; + * Boolean is_top; + * { + * } + * + * is_top will be TRUE for the top-level cell, and FALSE for all + * other cells. The procedure should return 0 normally, or 1 to abort + * the search. + * + * Results: + * Returns 0 if terminated normally, or 1 if the search + * was aborted. + * + * Side effects: + * Whatever (*subProc)() does. + * + * ---------------------------------------------------------------------------- + */ + +int +EFVisitSubcircuits(subProc, cdata) + int (*subProc)(); + ClientData cdata; +{ + CallArg ca; + HierContext *hc; + int efVisitSubcircuits(); /* Forward declaration */ + + /* If the top-level def is defined as a subcircuit, call topProc */ + + hc = &efFlatContext; + if (hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT) + if ((*subProc)(hc->hc_use, hc->hc_hierName, TRUE)) + return 1; + + /* For each subcell of the top-level def that is defined as */ + /* a subcircuit, call subProc. */ + + ca.ca_proc = subProc; + ca.ca_cdata = cdata; + + if (efHierSrUses(hc, efVisitSubcircuits, (ClientData) &ca)) + return 1; + + return 0; +} + +/* + * Procedure to visit recursively all subcircuits in the design. + * Does all the work of EFVisitSubcircuits() above. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * Calls the client procedure (*ca->ca_proc)(). + */ + +int +efVisitSubcircuits(hc, ca) + HierContext *hc; + CallArg *ca; +{ + /* Look for children of this def which are defined */ + /* as subcircuits via the DEF_SUBCIRCUIT flag. */ + + if (hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT) + { + if ((*ca->ca_proc)(hc->hc_use, hc->hc_hierName, NULL)) + return 1; + else + return 0; + } + + /* Recursively visit subcircuits in our children last. */ + + if (efHierSrUses(hc, efVisitSubcircuits, (ClientData) ca)) + return 1; + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFGetLengthAndWidth -- + * + * Estimate length and width for a device from area and perimeter values. + * Mostly this routine is meant to handle the older "fet" record. + * Newer "device" types should have length and width properly determined + * already, and we just return those values from the device structure. + * + * Results: + * None + * + * Side Effects: + * Values substituted for length and width. + * + * ---------------------------------------------------------------------------- + */ + +void +EFGetLengthAndWidth(dev, lptr, wptr) + Dev *dev; + int *lptr; + int *wptr; +{ + DevTerm *gate, *source, *drain; + int area, perim, l, w; + + switch (dev->dev_class) + { + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_BJT: + case DEV_SUBCKT: + case DEV_MSUBCKT: + case DEV_RSUBCKT: + case DEV_DIODE: + case DEV_PDIODE: + case DEV_NDIODE: + case DEV_CAP: + case DEV_CAPREV: + case DEV_RES: + l = dev->dev_length; + w = dev->dev_width; + break; + + case DEV_FET: + area = dev->dev_area; + perim = dev->dev_perim; + + gate = &dev->dev_terms[0]; + + /* + * L, W, and flat coordinates of a point inside the channel. + * Handle FETs with two terminals (capacitors) separately. + */ + + if (dev->dev_nterm == 2) + { + /* Convert area to type double to avoid overflow in */ + /* extreme cases. */ + l = perim - (int)sqrt((double)(perim * perim) - 16 * (double)area); + l >>= 2; + w = area / l; + } + else + { + source = drain = &dev->dev_terms[1]; + if (dev->dev_nterm >= 3) + drain = &dev->dev_terms[2]; + l = gate->dterm_length / 2; + w = (source->dterm_length + drain->dterm_length) / 2; + } + if (gate->dterm_attrs) efDevFixLW(gate->dterm_attrs, &l, &w); + break; + + default: + l = w = 0; + break; + } + + *lptr = l; + *wptr = w; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFVisitDevs -- + * + * Visit all the devs in the circuit. + * Must be called after EFFlatBuild(). + * For each dev in the circuit, call the user-supplied procedure + * (*devProc)(), which should be of the following form: + * + * (*devProc)(dev, hierName, scale, cdata) + * Dev *dev; + * HierName *hierName; + * float scale; + * Transform *trans; + * ClientData cdata; + * { + * } + * + * The procedure should return 0 normally, or 1 to abort the + * search. + * + * We ensure that no devs connected to killed nodes are passed + * to this procedure. + * + * Results: + * Returns 0 if terminated normally, or 1 if the search + * was aborted. + * + * Side effects: + * Whatever (*devProc)() does. + * + * ---------------------------------------------------------------------------- + */ + +int +EFVisitDevs(devProc, cdata) + int (*devProc)(); + ClientData cdata; +{ + CallArg ca; + + ca.ca_proc = devProc; + ca.ca_cdata = cdata; + return efVisitDevs(&efFlatContext, (ClientData) &ca); +} + +/* + * Procedure to visit recursively all devs in the design. + * Does all the work of EFVisitDevs() above. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * Calls the client procedure (*ca->ca_proc)(). + */ + +int +efVisitDevs(hc, ca) + HierContext *hc; + CallArg *ca; +{ + Def *def = hc->hc_use->use_def; + Dev *dev; + float scale; + Transform t; + + if (def->def_flags & DEF_SUBCIRCUIT) return 0; + + /* Recursively visit devs in our children first */ + if (efHierSrUses(hc, efVisitDevs, (ClientData) ca)) + return 1; + + scale = (efScaleChanged && def->def_scale != 1.0) ? def->def_scale : 1.0; + t = hc->hc_trans; + + /* Visit our own devices */ + for (dev = def->def_devs; dev; dev = dev->dev_next) + { + if (efDevKilled(dev, hc->hc_hierName)) + continue; + + if ((*ca->ca_proc)(dev, hc->hc_hierName, scale, &t, ca->ca_cdata)) + return 1; + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * efDevKilled -- + * + * Check all of the nodes to which the dev 'dev' is connected (its + * hierarchical prefix is hc->hc_hierName). If any of these nodes + * have been killed, then the dev is also killed. + * + * Results: + * TRUE if the dev is connected to a killed node, FALSE if it's ok. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +efDevKilled(dev, prefix) + Dev *dev; + HierName *prefix; +{ + HierName *suffix; + HashEntry *he; + EFNodeName *nn; + int n; + + for (n = 0; n < dev->dev_nterm; n++) + { + suffix = dev->dev_terms[n].dterm_node->efnode_name->efnn_hier; + he = EFHNConcatLook(prefix, suffix, "kill"); + if (he && (nn = (EFNodeName *) HashGetValue(he)) + && (nn->efnn_node->efnode_flags & EF_KILLED)) + return TRUE; + } + + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * efDevFixLW -- + * + * Called for any devs that have gate attributes; these attributes may + * specify the L and W of the dev explicitly. The attributes will be + * of the form ext:l=value or ext:w=value, where value is either numerical + * or symbolic; if symbolic the symbol must have been defined via efSymAdd(). + * If the value is symbolic but wasn't defined by efSymAdd(), it's ignored. + * The variables *pL and *pW are changed to reflect the new L and W as + * appropriate. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +efDevFixLW(attrs, pL, pW) + char *attrs; + int *pL, *pW; +{ + char *cp, *ep; + char attrName, savec; + int value; + + cp = attrs; + while (cp && *cp) + { + if (*cp != 'e' || strncmp(cp, "ext:", 4) != 0) + goto skip; + + cp += 4; + if (*cp && cp[1] == '=') + { + switch (*cp) + { + case 'w': case 'W': + attrName = 'w'; + goto both; + case 'l': case 'L': + attrName = 'l'; + both: + cp += 2; + for (ep = cp; *ep && *ep != ','; ep++) + /* Nothing */; + savec = *ep; + *ep = '\0'; + if (StrIsInt(cp)) value = atoi(cp); + else if (!efSymLook(cp, &value)) goto done; + + if (attrName == 'w') + *pW = value; + else if (attrName == 'l') + *pL = value; + + done: + *ep = savec; + } + } + +skip: + /* Skip to next attribute */ + while (*cp && *cp++ != ',') + /* Nothing */; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * EFVisitResists -- + * + * Visit all the resistors in the circuit. + * Must be called after EFFlatBuild(). + * For each resistor in the circuit, call the user-supplied procedure + * (*resProc)(), which should be of the following form, where hn1 and + * hn2 are the HierNames of the two nodes connected by the resistor. + * + * (*resProc)(hn1, hn2, resistance, cdata) + * HierName *hn1, *hn2; + * int resistance; + * ClientData cdata; + * { + * } + * + * The procedure should return 0 normally, or 1 to abort the + * search. + * + * We ensure that no resistors connected to killed nodes are passed + * to this procedure. + * + * Results: + * Returns 0 if terminated normally, or 1 if the search + * was aborted. + * + * Side effects: + * Whatever (*resProc)() does. + * + * ---------------------------------------------------------------------------- + */ + +int +EFVisitResists(resProc, cdata) + int (*resProc)(); + ClientData cdata; +{ + CallArg ca; + + ca.ca_proc = resProc; + ca.ca_cdata = cdata; + return efVisitResists(&efFlatContext, (ClientData) &ca); +} + +/* + * Procedure to visit recursively all resistors in the design. + * Does all the work of EFVisitResists() above. + * + * Results: + * Returns 0 to keep efHierSrUses going. + * + * Side effects: + * Calls the client procedure (*ca->ca_proc)(). + */ + +extern int efVisitSingleResist(); + +int +efVisitResists(hc, ca) + HierContext *hc; + CallArg *ca; +{ + Def *def = hc->hc_use->use_def; + Connection *res; + + /* Ignore subcircuits */ + if (def->def_flags & DEF_SUBCIRCUIT) return 0; + + /* Recursively visit resistors in our children first */ + if (efHierSrUses(hc, efVisitResists, (ClientData) ca)) + return 1; + + /* Visit our own resistors */ + for (res = def->def_resistors; res; res = res->conn_next) + { + /* Special case for speed if no arraying info */ + if (res->conn_1.cn_nsubs == 0) + { + if (efVisitSingleResist(hc, res->conn_name1, res->conn_name2, + res, ca)) + return 1; + } + else if (efHierSrArray(hc, res, efVisitSingleResist, (ClientData) ca)) + return 1; + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * efVisitSingleResist -- + * + * Visit a resistor of res->conn_res milliohms between the nodes + * 'name1' and 'name2' (text names, not hierarchical names). Don't + * process the resistor if either terminal is a killed node. + * + * Results: + * Whatever the user-supplied procedure (*ca->ca_proc)() returns + * (type int). + * + * Side effects: + * Calls the user-supplied procedure. + * + * ---------------------------------------------------------------------------- + */ + +int +efVisitSingleResist(hc, name1, name2, res, ca) + HierContext *hc; /* Contains hierarchical pathname to cell */ + char *name1, *name2; /* Names of nodes connecting to resistor */ + Connection *res; /* Contains resistance to add */ + CallArg *ca; +{ + EFNode *n1, *n2; + HashEntry *he; + + if ((he = EFHNLook(hc->hc_hierName, name1, "resist(1)")) == NULL) + return 0; + n1 = ((EFNodeName *) HashGetValue(he))->efnn_node; + if (n1->efnode_flags & EF_KILLED) + return 0; + + if ((he = EFHNLook(hc->hc_hierName, name2, "resist(2)")) == NULL) + return 0; + n2 = ((EFNodeName *) HashGetValue(he))->efnn_node; + if (n2->efnode_flags & EF_KILLED) + return 0; + + /* Do nothing if the nodes aren't different */ + if (n1 == n2) + return 0; + + return (*ca->ca_proc)(n1->efnode_name->efnn_hier, + n2->efnode_name->efnn_hier, + res->conn_res, ca->ca_cdata); +} + +/* + * ---------------------------------------------------------------------------- + * + * EFVisitCaps -- + * + * Visit all the capacitors built up by efFlatCaps. + * Calls the user-provided procedure (*capProc)() + * which should be of the following format: + * + * (*capProc)(hierName1, hierName2, cap, cdata) + * HierName *hierName1, *hierName2; + * EFCapValue cap; + * ClientData cdata; + * { + * } + * + * Here cap is the capacitance in attofarads. + * + * Results: + * Returns 1 if the client procedure returned 1; + * otherwise returns 0. + * + * Side effects: + * Calls the user-provided procedure (*capProc)(). + * + * ---------------------------------------------------------------------------- + */ + +int +EFVisitCaps(capProc, cdata) + int (*capProc)(); + ClientData cdata; +{ + HashSearch hs; + HashEntry *he; + EFCoupleKey *ck; + EFCapValue cap; + + HashStartSearch(&hs); + while (he = HashNext(&efCapHashTable, &hs)) + { + cap = CapHashGetValue(he); + ck = (EFCoupleKey *) he->h_key.h_words; + if ((*capProc)(ck->ck_1->efnode_name->efnn_hier, + ck->ck_2->efnode_name->efnn_hier, + (double) cap, cdata)) + return 1; + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFVisitNodes -- + * + * Procedure to visit all flat nodes in the circuit. + * For each node, calls the procedure (*nodeProc)(), + * which should be of the following form: + * + * (*nodeProc)(node, r, c, cdata) + * EFNode *node; + * int r; + * EFCapValue c; + * ClientData cdata; + * { + * } + * + * Where 'r' and 'c' are the lumped resistance estimate + * and capacitance to ground, in milliohms and attofarads + * respectively. When either falls below the threshold + * for output, they are passed as 0. + * + * Results: + * Returns 1 if (*nodeProc)() returned 1 to abort the + * search; otherwise, returns 0. + * + * Side effects: + * Calls (*nodeProc)(). + * + * ---------------------------------------------------------------------------- + */ + +int +EFVisitNodes(nodeProc, cdata) + int (*nodeProc)(); + ClientData cdata; +{ + EFNode *node; + EFNodeName *nn; + HierName *hierName; + EFCapValue cap; + int res; + + for (node = (EFNode *) efNodeList.efnode_next; + node != &efNodeList; + node = (EFNode *) node->efnode_next) + { + res = EFNodeResist(node); + cap = node->efnode_cap; + hierName = (HierName *) node->efnode_name->efnn_hier; + if (EFCompat) + { + if (EFHNIsGND(hierName)) + cap = 0; + } + else + { + if (node->efnode_flags & EF_SUBS_NODE) + cap = 0; + } + if (efWatchNodes) + { + for (nn = node->efnode_name; nn; nn = nn->efnn_next) + if (HashLookOnly(&efWatchTable, (char *) nn->efnn_hier)) + { + TxPrintf("Equivalent nodes:\n"); + for (nn = node->efnode_name; nn; nn = nn->efnn_next) + TxPrintf("\t%s\n", EFHNToStr(nn->efnn_hier)); + break; + } + } + + if (node->efnode_flags & EF_KILLED) + continue; + + if ((*nodeProc)(node, res, (double) cap, cdata)) + return 1; + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFNodeResist -- + * + * The input to this procedure is a pointer to a EFNode. + * Its resistance is computed from the area and perimeter stored + * in the array efnode_pa. + * + * We approximate the resistive region as a collection of rectangles + * of width W and length L, one for each set of layers having a different + * sheet resistivity. We do so by noting that for a rectangle, + * + * Area = L * W + * Perimeter = 2 * (L + W) + * + * Solving the two simultaneous equations for L yields the following + * quadratic: + * + * 2 * (L**2) - Perimeter * L + 2 * Area = 0 + * + * Solving this quadratic for L, the longer dimension, we get + * + * L = (Perimeter + S) / 4 + * + * where + * + * S = sqrt( (Perimeter**2) - 16 * Area ) + * + * The smaller dimension is W, ie, + * + * W = (Perimeter - S) / 4 + * + * The resistance is L / W squares: + * + * Perimeter + S + * R = ------------- + * Perimeter - S + * + * Results: + * Returns the resistance. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +EFNodeResist(node) + EFNode *node; +{ + int n, perim, area; + float s, fperim; + double v, dresist; + int resist; + + resist = 0; + for (n = 0; n < efNumResistClasses; n++) + { + area = node->efnode_pa[n].pa_area; + perim = node->efnode_pa[n].pa_perim; + if (area > 0 && perim > 0) + { + v = (double) perim * (double) perim - 16.0 * area; + + /* Approximate by one square if v < 0; shouldn't happen! */ + if (v < 0.0) s = 0.0; else s = sqrt(v); + + fperim = (float) perim; + dresist = (fperim + s)/(fperim - s) * efResists[n]; + if (dresist + (double) resist > (double) INT_MAX) + resist = INT_MAX; + else + resist += dresist; + } + } + return (resist); +} + +/* + * ---------------------------------------------------------------------------- + * + * EFLookDist -- + * + * Look for the Distance between two points given by their HierNames. + * + * Results: + * TRUE if a distance was found, FALSE if not. + * + * Side effects: + * Sets *pMinDist and *pMaxDist to the min and max distances + * if found. + * + * ---------------------------------------------------------------------------- + */ + +bool +EFLookDist(hn1, hn2, pMinDist, pMaxDist) + HierName *hn1, *hn2; + int *pMinDist, *pMaxDist; +{ + Distance distKey, *dist; + HashEntry *he; + + if (EFHNBest(hn1, hn2)) + { + distKey.dist_1 = hn1; + distKey.dist_2 = hn2; + } + else + { + distKey.dist_1 = hn2; + distKey.dist_2 = hn1; + } + he = HashLookOnly(&efDistHashTable, (char *) &distKey); + if (he == NULL) + return FALSE; + + dist = (Distance *) HashGetValue(he); + *pMinDist = dist->dist_min; + *pMaxDist = dist->dist_max; + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * EFHNOut -- + * + * Output a hierarchical node name. + * The flags in EFTrimFlags control whether global (!) or local (#) + * suffixes are to be trimmed. + * + * Results: + * None. + * + * Side effects: + * Writes to the files 'outf'. + * + * ---------------------------------------------------------------------------- + */ + +void +EFHNOut(hierName, outf) + HierName *hierName; + FILE *outf; +{ + bool trimGlob, trimLocal, trimComma; + char *cp, c; + + if (hierName->hn_parent) efHNOutPrefix(hierName->hn_parent, outf); + if (EFTrimFlags) + { + cp = hierName->hn_name; + trimGlob = (EFTrimFlags & EF_TRIMGLOB); + trimLocal = (EFTrimFlags & EF_TRIMLOCAL); + trimComma = (EFTrimFlags & EF_CONVERTCOMMAS); + while (c = *cp++) + { + if (*cp) + { + if (trimComma && (c == ',')) + putc(';', outf); + else + putc(c, outf); + } + else switch (c) + { + case '!': if (!trimGlob) (void) putc(c, outf); break; + case '#': if (trimLocal) break; + default: (void) putc(c, outf); break; + } + } + } + else (void) fputs(hierName->hn_name, outf); +} + +void +efHNOutPrefix(hierName, outf) + HierName *hierName; + FILE *outf; +{ + char *cp, c; + + if (hierName->hn_parent) + efHNOutPrefix(hierName->hn_parent, outf); + + cp = hierName->hn_name; + while (c = *cp++) + putc(c, outf); + putc('/', outf); +} diff --git a/extflat/Makefile b/extflat/Makefile new file mode 100644 index 00000000..4ec0e281 --- /dev/null +++ b/extflat/Makefile @@ -0,0 +1,11 @@ +# +# rcsid "$Header: /usr/cvsroot/magic-8.0/extflat/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" +# + +MODULE = extflat +MAGICDIR = .. +SRCS = EFargs.c EFbuild.c EFdef.c EFerr.c EFflat.c EFhier.c EFname.c \ + EFread.c EFsym.c EFvisit.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/extflat/READ_ME b/extflat/READ_ME new file mode 100644 index 00000000..889d6cad --- /dev/null +++ b/extflat/READ_ME @@ -0,0 +1,5 @@ +This directory contains a library for reading hierarchical .ext files +and flattening them. See ../ext2sim, ../ext2spice, or ../ext2dlys for +examples of programs that use this library. + + Walter Scott diff --git a/extflat/extflat.h b/extflat/extflat.h new file mode 100644 index 00000000..996b8c5f --- /dev/null +++ b/extflat/extflat.h @@ -0,0 +1,360 @@ +/* + * extflat.h -- + * + * Internal definitions for the procedures to flatten hierarchical + * (.ext) circuit extraction files. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/extflat/extflat.h,v 1.2 2008/12/03 14:12:09 tim Exp $ + */ + +#ifndef _EXTFLAT_H +#define _EXTFLAT_H + +#include "utils/magic.h" + +typedef unsigned char U_char; + +/* + * Arguments to EFFlatBuild(). + */ +#define EF_FLATNODES 0x01 /* Flatten nodes */ +#define EF_FLATCAPS 0x02 /* Flatten capacitors */ +#define EF_FLATRESISTS 0x04 /* Flatten resistors */ +#define EF_FLATDISTS 0x08 /* Flatten distances */ +#define EF_NOFLATSUBCKT 0x10 /* Don't flatten standard cells */ +#define EF_NONAMEMERGE 0x20 /* Don't merge unconnected nets */ + /* with the same name. */ + +/* Flags to control output of node names. Stored in EFTrimFlags */ +#define EF_TRIMGLOB 0x01 /* Delete trailing '!' from names */ +#define EF_TRIMLOCAL 0x02 /* Delete trailing '#' from names */ +#define EF_CONVERTCOMMAS 0x04 /* Change ',' to ';' in names */ +#define EF_CONVERTEQUAL 0x08 /* Change '=' to ':' in names */ + +/* + * capacitance type now set to float + */ +typedef float EFCapValue; + +/* ------------------------ Hierarchical names ------------------------ */ + +/* + * One of the biggest consumers of memory space when flattening a circuit + * are the full hierarchical names of all nodes. Most of this space is + * wasted since it's redundant. Also, a lot of time is spent comparing + * long names whose initial components are identical. + * + * The following structure allows hierarchical names to be represented + * with sharing. Names are represented as a sequence of components, + * from the lowest level of the hierarchy pointing back toward the root. + * Hence, comparisons are likely to detect differences between names + * early on. Second, many children can share the same parent, so + * storage space should be comparable to that needed for an unflattened + * hierarchy (with arrays flattened, however). + */ +typedef struct hiername +{ + struct hiername *hn_parent; /* Back-pointer toward root */ + int hn_hash; /* For speed in hashing */ + char hn_name[4]; /* String is allocated here */ +} HierName; + +/* + * Size of a HierName big enough to hold a string containing + * n bytes (not including the NULL byte). + */ +#define HIERNAMESIZE(n) ((n) + sizeof (HierName) - 3) + +/* Indicates where the HierName was allocated: passed to EFHNFree() */ +#define HN_ALLOC 0 /* Normal name (FromStr) */ +#define HN_CONCAT 1 /* Concatenation of two HierNames */ +#define HN_GLOBAL 2 /* Global name */ +#define HN_FROMUSE 3 /* From a cell use */ + +/* ----------------------- Node attribute lists ----------------------- */ + +typedef struct efattr +{ + struct efattr *efa_next; /* Next in list */ + Rect efa_loc; /* Location of attr label */ + int efa_type; /* Tile type attr attached to */ + char efa_text[4]; /* String is allocated here */ +} EFAttr; + +/* + * Size of an EFAttr big enough to hold a string containing + * n bytes (not including the NULL byte). + */ +#define ATTRSIZE(n) ((n) + sizeof (EFAttr) - 3) + +/* ------------------- Hierarchical and flat nodes -------------------- */ + +/* + * Each entry in the a nodename hash table points to a EFNodeName. + * Several EFNodeNames may point to the same EFNode. Such EFNodeNames + * are linked into a NULL-terminated list by the name_next pointers. + * The first name in this list, pointed to by the efnode_name field of + * the EFNode they all point to, is the canonical name for this node. + * + * The name_hier field points to the HierName for this node, which + * will have only a single component for EFNodes within a Def, but + * multiple components for hierarchical node names. + */ +typedef struct efnn +{ + struct efnode *efnn_node; /* Corresponding node */ + struct efnn *efnn_next; /* Next name for this node */ + HierName *efnn_hier; /* HierName for this node */ + int efnn_port; /* Port number for this node */ +} EFNodeName; + +/* + * Both hierarchical and flat nodes use the same structure. Hierarchical + * nodes appear along with each cell def. Flat nodes are pointed to by + * the global hash table. + * + * Hierarchical nodes are linked in a doubly-linked list with all + * other nodes in the same cell, and flat nodes are similarly linked + * with all other flat nodes in the circuit. The list is doubly + * linked to allow nodes to be deleted easily when it is necessary + * to merge two nodes into a single node. + * + * There is a third way in which a node can exist if only its name is + * of interest, namely as an EFNodeHdr. The first part of an EFNode + * is an EFNodeHdr. + */ + + /* Represents perimeter and area for a resistance class */ +typedef struct +{ + int pa_area; + int pa_perim; +} PerimArea; + +typedef struct efnhdr +{ + int efnhdr_flags; /* See below */ + EFNodeName *efnhdr_name; /* Canonical name for this node, this is a ptr + * to the first element in a null-terminated + * list of all the EFNodeNames for this node. + */ + struct efnhdr *efnhdr_next; /* Next node in list */ + struct efnhdr *efnhdr_prev; /* Previous node in list */ +} EFNodeHdr; + +/* Node flags */ + /* + * If set, this node was killed and neither it nor anything connected + * to it should be output. There should have been a new, identical + * structure in the input that was connected to the new node. + */ +#define EF_KILLED 0x01 + + /* + * If set, this node was allocated as a substrate terminal for a + * dev, and so should be automatically merged with nodes of the + * same name after all nodes have been flattened, rather than + * complaining about it being unconnected. + */ +#define EF_DEVTERM 0x02 + + /* + * This can be used as a general-purpose flag. It is used by + * the LEF module to indicate that a node is a "special" net. + */ +#define EF_SPECIAL 0x04 + /* + * If set, this node is a subcircuit port and should be treated + * accordingly when writing netlist output. The port number is + * encoded in the efNodeName structure, since there may be + * multiple ports per node (for example, a thru route). + */ +#define EF_PORT 0x08 + /* + * This is used when a node is a substrate node with a local + * node name, making it an implicitly-defined port. It differs + * from EF_DEVTERM in that EF_DEVTERM includes global substrate + * nodes, which are not declared ports. + */ +#define EF_SUBS_PORT 0x10 + /* + * EF_SUBS_NODE is defined for substrate nodes defined in the + * .ext file. + */ +#define EF_SUBS_NODE 0x20 + +extern int efNumResistClasses; /* Number of resistance classes in efResists */ + +typedef struct efnode +{ + EFNodeHdr efnode_hdr; /* See above */ +#define efnode_name efnode_hdr.efnhdr_name +#define efnode_next efnode_hdr.efnhdr_next +#define efnode_prev efnode_hdr.efnhdr_prev +#define efnode_flags efnode_hdr.efnhdr_flags + + EFCapValue efnode_cap; /* Total capacitance to ground for this node */ + int efnode_type; /* Index into type table for node */ + Rect efnode_loc; /* Location of a 1x1 rect contained in this + * node. This information is provided in the + * .ext file so it will be easy to map between + * node names and locations. + */ + EFAttr *efnode_attrs; /* Node attribute list */ + ClientData efnode_client; /* For hire */ + PerimArea efnode_pa[1]; /* Dummy; each node actually has + * efNumResistClasses array elements + * allocated to it. + */ +} EFNode; + +/* -------------------------- Devices ----------------------------- */ + +/* + * Each device can contain several terminals. + * Each terminal is described by the following structure. + * We use a EFNode pointer for the terminal to which a device connects; + * this assumes that devices appear after all the nodes for a cell. + */ +typedef struct devterm +{ + EFNode *dterm_node; /* Node to which we're connected */ + char *dterm_attrs; /* Attribute list */ + int dterm_length; /* Length of terminal connection to gate */ + int dterm_perim; /* Terminal perimeter if passed as a param */ + int dterm_area; /* Terminal area if passed as a param */ +} DevTerm; + +/* + * Device itself. + * The dev_substrate and dev_type pointers are actually pointer into shared + * tables of names, rather than being individually allocated for each + * transistor. + */ + +typedef struct parm +{ + char parm_type[2]; + char *parm_name; + double parm_scale; + struct parm *parm_next; +} DevParam; + +typedef struct dev +{ + struct dev *dev_next; /* Next device in def */ + U_char dev_class; /* Device class (see extract/extract.h) */ + U_char dev_type; /* Index into device type table */ + U_char dev_nterm; /* Number of terminals in device */ + EFNode *dev_subsnode; /* Substrate node */ + Rect dev_rect; /* 1x1 rectangle inside device */ + + /* Most device types use only one or two of these, but subcircuits */ + /* may keep all values to pass along as parameters. */ + float dev_cap; /* Capacitance for class "cap" or subckt */ + float dev_res; /* Resistance for class "res" or subckt */ + int dev_area; + int dev_perim; + int dev_length; + int dev_width; + DevParam *dev_params; /* List of subcircuit parameters to output */ + DevTerm dev_terms[1]; /* Terminals. The actual number will depend + * on dev_nterm above, so the size of this + * structure will vary. + */ +} Dev; + +/* Size of a Dev structure for 'n' terminals (including the "gate") */ +#define DevSize(n) (sizeof (Dev) + ((n)-1)*sizeof (DevTerm)) + +/* -------------------------------------------------------------------- */ + +/* + * A big number, used for thresholds for capacitance and resistance + * when no processing is desired (NOTE: Probably should be using + * C99 "INFINITY" here instead). + */ +#define INFINITE_THRESHOLD (((unsigned int) (~0)) >> 1) +#define INFINITE_THRESHOLD_F ((EFCapValue)(1.0E38)) +#define IS_FINITE_F(a) (((EFCapValue)(a)) != INFINITE_THRESHOLD_F) + +/* Max filename length */ +#define FNSIZE 1024 + + +extern float EFScale; /* Scale factor to multiply all coords by */ +extern char *EFTech; /* Technology of extracted circuit */ +extern char *EFStyle; /* Extraction style of extracted circuit */ +extern char *EFSearchPath; /* Path to search for .ext files */ +extern char *EFLibPath; /* Library search path */ +extern char *EFVersion; /* Version of extractor we work with */ +extern char *EFArgTech; /* Tech file given as command line argument */ +extern bool EFCompat; /* Subtrate backwards-compatibility mode */ + + /* + * Thresholds used by various extflat clients to filter out + * unwanted resistors and capacitors. Resistance is in milliohms, + * capacitance in attofarads. + */ +extern int EFResistThreshold; +extern EFCapValue EFCapThreshold; + + /* Table of transistor types */ +extern char *EFDevTypes[]; +extern int EFDevNumTypes; + + /* Table of Magic layers */ +extern char *EFLayerNames[]; +extern int EFLayerNumNames; + + /* Output control flags */ +extern int EFTrimFlags; + +/* -------------------------- Exported procedures --------------------- */ + +extern char *EFArgs(); + + /* HierName manipulation */ +extern HashEntry *EFHNLook(); +extern HashEntry *EFHNConcatLook(); +extern HierName *EFHNConcat(); +extern HierName *EFStrToHN(); +extern char *EFHNToStr(); +extern int EFGetPortMax(); + +/* ------------------------- constants used by clients -------------- */ +/* This gives us a 32 or 64 dev types which should be ok */ +#define BITSPERCHAR 8 +#define MAXDEVTYPES (sizeof(long)*BITSPERCHAR) + +/* + * ANSI C definitions of arguments to EFvisit procedures + */ + +/* - left for documentation purposes + +typedef int (*capproc)(HierName *, HierName *, double, ClientData ); + +extern int EFVisitCaps(capproc, ClientData ); + +typedef int (*nodeproc)(EFNode *, int , double, ClientData ); + +extern int EFVisitNodes(nodeproc , ClientData ); + +extern int EFReadFile(char *); + +*/ + +#endif /* _EXTFLAT_H */ diff --git a/extract/Depend b/extract/Depend new file mode 100644 index 00000000..7171cc1a --- /dev/null +++ b/extract/Depend @@ -0,0 +1,97 @@ +ExtArray.o: ExtArray.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../debug/debug.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../utils/signals.h ../utils/styles.h \ + ../windows/windows.h ../dbwind/dbwind.h +ExtBasic.o: ExtBasic.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../debug/debug.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../utils/signals.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../utils/stack.h +ExtCell.o: ExtCell.c ../utils/magic.h ../utils/geometry.h \ + ../utils/styles.h ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../utils/malloc.h ../textio/textio.h ../debug/debug.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../utils/signals.h ../utils/stack.h ../utils/utils.h \ + ../windows/windows.h ../utils/main.h ../utils/undo.h +ExtCouple.o: ExtCouple.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h +ExtHard.o: ExtHard.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../utils/malloc.h \ + ../textio/textio.h ../utils/styles.h ../debug/debug.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../utils/geofast.h +ExtHier.o: ExtHier.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../utils/styles.h ../windows/windows.h ../dbwind/dbwind.h \ + ../debug/debug.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h +ExtLength.o: ExtLength.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../debug/debug.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../utils/signals.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../utils/stack.h ../utils/main.h \ + ../utils/utils.h +ExtMain.o: ExtMain.c ../utils/magic.h ../utils/geometry.h \ + ../utils/styles.h ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../utils/malloc.h ../textio/textio.h ../debug/debug.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../utils/signals.h ../utils/stack.h ../utils/utils.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/main.h ../utils/undo.h +ExtNghbors.o: ExtNghbors.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../debug/debug.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../utils/signals.h ../utils/stack.h +ExtPerim.o: ExtPerim.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h ../utils/malloc.h \ + ../utils/stack.h ../debug/debug.h ../extract/extract.h \ + ../extract/extractInt.h ../extract/extDebugInt.h +ExtRegion.o: ExtRegion.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h ../utils/malloc.h \ + ../textio/textio.h ../debug/debug.h ../extract/extract.h \ + ../extract/extractInt.h ../extract/extDebugInt.h ../utils/signals.h +ExtSubtree.o: ExtSubtree.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../debug/debug.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../utils/signals.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h +ExtTech.o: ExtTech.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/utils.h ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../database/databaseInt.h ../utils/malloc.h \ + ../textio/textio.h ../utils/tech.h ../debug/debug.h ../extract/extract.h \ + ../extract/extractInt.h ../extract/extDebugInt.h ../cif/CIFint.h +ExtTest.o: ExtTest.c ../utils/magic.h ../utils/utils.h \ + ../utils/geometry.h ../utils/styles.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../windows/windows.h \ + ../graphics/graphics.h ../dbwind/dbwind.h ../utils/main.h \ + ../commands/commands.h ../textio/textio.h ../textio/txcommands.h \ + ../debug/debug.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h +ExtTimes.o: ExtTimes.c ../utils/magic.h ../utils/utils.h \ + ../utils/geometry.h ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h +ExtYank.o: ExtYank.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../debug/debug.h ../utils/styles.h ../extract/extract.h \ + ../extract/extractInt.h ../extract/extDebugInt.h +ExtInter.o: ExtInter.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../utils/undo.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../debug/debug.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../utils/signals.h ../utils/styles.h +ExtUnique.o: ExtUnique.c ../utils/magic.h ../utils/geometry.h \ + ../utils/styles.h ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../utils/malloc.h ../textio/textio.h ../debug/debug.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../utils/signals.h ../utils/stack.h ../utils/utils.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/main.h ../utils/undo.h diff --git a/extract/ExtArray.c b/extract/ExtArray.c new file mode 100644 index 00000000..b4106c6d --- /dev/null +++ b/extract/ExtArray.c @@ -0,0 +1,1021 @@ +/* + * ExtArray.c -- + * + * Circuit extraction. + * Extract interactions between elements of an array. + * The routines in this file are not re-entrant. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtArray.c,v 1.2 2009/05/30 03:14:00 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "utils/styles.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" + +/* Canonical interaction areas */ +#define AREA_A 0 +#define AREA_B 1 +#define AREA_C 2 + +/* Imports from elsewhere in this module */ +extern int extHardProc(); + +/* Local data passed to extArrayTileToNode() and its children */ +Point extArrayPrimXY; /* X, Y indices of primary array element */ +Point extArrayInterXY; /* X, Y indices of intersecting array element */ +Transform extArrayPTrans; /* Transform from primary element to root */ +Transform extArrayITrans; /* Transform from intersecting element ... */ +int extArrayWhich; /* Which interaction area is being processed */ +ExtTree *extArrayPrimary; /* Primary array element */ + +/* Forward declarations */ +int extArrayFunc(); +int extArrayPrimaryFunc(), extArrayInterFunc(); +char *extArrayRange(); +char *extArrayTileToNode(); +LabRegion *extArrayHardNode(); +char *extArrayNodeName(); + +void extArrayProcess(); +void extArrayAdjust(); +void extArrayHardSearch(); + +#if 0 + +/* + * ---------------------------------------------------------------------------- + * extOutputGeneratedLabels --- + * + * Write to the .ext file output "node" lines for labels generated in + * the parent cell where paint in the subcell is not otherwise + * represented by a node in the parent. These nodes have no material + * in the parent, and therefore have no capacitance or resistance + * associated with them. + * + * ---------------------------------------------------------------------------- + */ + +void +extOutputGeneratedLabels(parentUse, f) + CellUse *parentUse; + FILE *f; +{ + CellDef *parentDef; + Label *lab; + int n; + + parentDef = parentUse->cu_def; + + while ((lab = parentDef->cd_labels) != NULL) + { + if ((lab->lab_flags & LABEL_GENERATE) == 0) return; + + fprintf(f, "node \"%s\" 0 0 %d %d %s", + lab->lab_text, lab->lab_rect.r_xbot, + lab->lab_rect.r_ybot, + DBTypeShortName(lab->lab_type)); + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + fprintf(f, " 0 0"); + putc('\n', f); + freeMagic(lab); + parentDef->cd_labels = lab->lab_next; + } +} + +#endif + +/* + * ---------------------------------------------------------------------------- + * + * extArray -- + * + * Extract all connections resulting from interactions within each + * array of subcells in the cell parentUse->cu_def. + * + * This procedure only finds arrays, and then calls extArrayFunc() to + * do the real work. See the comments there for more details. + * + * Results: + * None. + * + * Side effects: + * Outputs connections and adjustments to the file 'f'. + * There are two kinds of records; see extSubtree for a description. + * However, when we output nodenames, they may contain implicit + * subscripting information, e.g, + * + * cap a[1:3]/In a[2:4]/Phi1 deltaC + * + * which is like 3 separate "cap" records: + * + * cap a[1]/In a[2]/Phi1 deltaC + * cap a[2]/In a[3]/Phi1 deltaC + * cap a[3]/In a[4]/Phi1 deltaC + * + * ---------------------------------------------------------------------------- + */ + +void +extArray(parentUse, f) + CellUse *parentUse; + FILE *f; +{ + SearchContext scx; + HierExtractArg ha; + + /* + * The connection hash table is initialized here but doesn't get + * cleared until the end. It is responsible for changes to the + * node structure over the entire cell 'parentUse->cu_def'. + */ + ha.ha_outf = f; + ha.ha_parentUse = parentUse; + ha.ha_nodename = extArrayTileToNode; + ha.ha_cumFlat.et_use = extYuseCum; + HashInit(&ha.ha_connHash, 32, 0); + + /* The real work of processing each array is done by extArrayFunc() */ + scx.scx_use = parentUse; + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = TiPlaneRect; + (void) DBCellSrArea(&scx, extArrayFunc, (ClientData) &ha); + +#if 0 + /* Output generated labels and remove them from the parent */ + extOutputGeneratedLabels(parentUse, f); +#endif + + /* Output connections and node adjustments */ + extOutputConns(&ha.ha_connHash, f); + HashKill(&ha.ha_connHash); +} + +/* + * ---------------------------------------------------------------------------- + * + * extArrayFunc -- + * + * Given a CellUse as argument, extract and output all the connections that + * result from interactions between neighboring elements of the array. + * + * Results: + * Returns 2 always so we stop after the first CellUse in the array. + * + * Side effects: + * Writes to the file 'ha->ha_outf' + * + * Design: + * To extract all the connections made between members of an array, we + * only have to look for interactions in three canonical areas, shaded as + * A, B, and C in the diagram below. Each interaction area consists only + * of the portion of overlap between the canonical cell (1 for A, B, and + * 2 for C) and its neighbors. Hence the exact size of the interaction + * areas depends on how much overlap there is. In the extreme cases, + * there may be no areas to check at all (instances widely separated), + * or there may even be areas with more than four instances overlapping + * (spacing less than half the size of the instance). + * + * ------------------------------------------------- + * | | | | + * | 2 | | | + * | | | | + * | CCC | | + * --------------CCC-------------------------------- + * | | | | + * | | | | + * | | | | + * | | | | + * AAAAAAAAAAAAAAaba-------------------------------| + * AAAAAAAAAAAAAAbab | | + * | BBB | | + * | 1 BBB | | + * | BBB | | + * --------------BBB-------------------------------- + * + * In area A, we check for interactions with 1 and the elements directly + * above, or above and to the right. In area B, we check for interactions + * only with elements at the same level but to the right. In area C, we + * check for interactions only with elements below and to the right. + * + * ---------------------------------------------------------------------------- + */ + +int +extArrayFunc(scx, ha) + SearchContext *scx; /* Describes first element of array */ + HierExtractArg *ha; /* Extraction context */ +{ + int xsep, ysep; /* X, Y separation in parent coordinates */ + int xsize, ysize; /* X, Y sizes in parent coordinates */ + int halo = ExtCurStyle->exts_sideCoupleHalo + 1; + CellUse *use = scx->scx_use; + CellDef *def = use->cu_def; + Rect tmp, tmp2, primary; + + /* Skip uses that aren't arrays */ + if ((use->cu_xlo == use->cu_xhi) && (use->cu_ylo == use->cu_yhi)) + return (2); + + if ((ExtOptions & (EXT_DOCOUPLING|EXT_DOADJUST)) + != (EXT_DOCOUPLING|EXT_DOADJUST)) + halo = 1; + + /* + * Compute the sizes and separations of elements, in coordinates + * of the parent. If the array is 1-dimensional, we set the + * corresponding spacing to an impossibly large distance. + */ + tmp.r_xbot = tmp.r_ybot = 0; + if (use->cu_xlo == use->cu_xhi) + tmp.r_xtop = def->cd_bbox.r_xtop - def->cd_bbox.r_xbot + 2; + else tmp.r_xtop = use->cu_xsep; + if (use->cu_ylo == use->cu_yhi) + tmp.r_ytop = def->cd_bbox.r_ytop - def->cd_bbox.r_ybot + 2; + else tmp.r_ytop = use->cu_ysep; + GeoTransRect(&use->cu_transform, &tmp, &tmp2); + xsep = tmp2.r_xtop - tmp2.r_xbot; + ysep = tmp2.r_ytop - tmp2.r_ybot; + GeoTransRect(&use->cu_transform, &def->cd_bbox, &tmp2); + xsize = tmp2.r_xtop - tmp2.r_xbot; + ysize = tmp2.r_ytop - tmp2.r_ybot; + + /* + * For areas A and B, we will be looking at the interactions + * between the element in the lower-left corner of the array + * (in parent coordinates) and its neighbors to the top, right, + * and top-right. + */ + primary.r_xbot = use->cu_bbox.r_xbot; + primary.r_xtop = use->cu_bbox.r_xbot + 1; + primary.r_ybot = use->cu_bbox.r_ybot; + primary.r_ytop = use->cu_bbox.r_ybot + 1; + ha->ha_subUse = use; + + /* Area A */ + if (ysep <= ysize) + { + ha->ha_clipArea.r_xbot = use->cu_bbox.r_xbot; + ha->ha_clipArea.r_xtop = use->cu_bbox.r_xbot + xsize + halo; + ha->ha_clipArea.r_ybot = use->cu_bbox.r_ybot + ysep - halo; + ha->ha_clipArea.r_ytop = use->cu_bbox.r_ybot + ysize + halo; + ha->ha_interArea = ha->ha_clipArea; + extArrayWhich = AREA_A; + extArrayProcess(ha, &primary); + if (SigInterruptPending) + return (1); + } + + /* Area B */ + if (xsep <= xsize) + { + ha->ha_clipArea.r_xbot = use->cu_bbox.r_xbot + xsep - halo; + ha->ha_clipArea.r_xtop = use->cu_bbox.r_xbot + xsize + halo; + ha->ha_clipArea.r_ybot = use->cu_bbox.r_ybot; + ha->ha_clipArea.r_ytop = use->cu_bbox.r_ybot + ysize + halo; + ha->ha_interArea = ha->ha_clipArea; + extArrayWhich = AREA_B; + extArrayProcess(ha, &primary); + if (SigInterruptPending) + return (1); + } + + /* Area C */ + if (ysep <= ysize && xsep <= xsize) + { + /* + * For area C, we will be looking at the interactions between + * the element in the upper-left corner of the array (in parent + * coordinates) and its neighbors to the bottom-right only. + */ + primary.r_ybot = use->cu_bbox.r_ytop - 1; + primary.r_ytop = use->cu_bbox.r_ytop; + ha->ha_clipArea.r_xbot = use->cu_bbox.r_xbot + xsep - halo; + ha->ha_clipArea.r_xtop = use->cu_bbox.r_xbot + xsize + halo; + ha->ha_clipArea.r_ybot = use->cu_bbox.r_ytop - ysize - halo; + ha->ha_clipArea.r_ytop = use->cu_bbox.r_ytop - ysep + halo; + ha->ha_interArea = ha->ha_clipArea; + extArrayWhich = AREA_C; + extArrayProcess(ha, &primary); + } + + return (2); +} + +/* + * ---------------------------------------------------------------------------- + * + * extArrayProcess -- + * + * Process a single canonical interaction area for the arrayed CellUse + * 'ha->ha_subUse'. The area 'primary', in parent coordinates, should + * be contained in only one element of the array. For each other element + * in the array that appears in the area 'ha->ha_interArea', we determine + * all connections and R/C adjustments and output them in the form of an + * implicitly iterated "merge" or "adjust" line for the rest of the array. + * + * Expects extArrayWhich to be one of AREA_A, AREA_B, or AREA_C; this + * is the interaction area being searched. + * + * Results: + * None. + * + * Side effects: + * See extArrayPrimaryFunc and extArrayInterFunc for details. + * Trashes ha->ha_cumFlat.et_use. + * + * ---------------------------------------------------------------------------- + */ + +void +extArrayProcess(ha, primary) + HierExtractArg *ha; + Rect *primary; /* Area guaranteed to contain only the primary + * element of the array, against which we will + * extract all other elements that overlap the + * area 'ha->ha_interArea'. + */ +{ + CellUse *use = ha->ha_subUse; + + + /* + * Yank the primary array element into a new yank buffer + * that we leave extArrayPrimary pointing to. + */ + extArrayPrimary = (ExtTree *) NULL; + if (DBArraySr(use, primary, extArrayPrimaryFunc, (ClientData) ha) == 0) + { + DBWFeedbackAdd(primary, + "System error: expected array element but none found", + ha->ha_parentUse->cu_def, 1, STYLE_MEDIUMHIGHLIGHTS); + extNumFatal++; + return; + } + if (SigInterruptPending) goto done; + + /* + * Find and process all other elements that intersect ha->ha_interArea, + * extracting connections against extArrayPrimary. + */ + (void) DBArraySr(use, &ha->ha_interArea, extArrayInterFunc, (ClientData)ha); + +done: + if (extArrayPrimary) extHierFreeOne(extArrayPrimary); + extArrayPrimary = (ExtTree *) NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * extArrayPrimaryFunc -- + * + * Called by DBArraySr, which should only find a single array element. + * We record which element was found by setting extArrayPrimXY.p_x + * and extArrayPrimXY.p_y, and also the transform in extArrayPTrans + * for use by extArrayHardNode(). + * + * We yank the paint and labels of this array element into a new ExtTree, + * which we leave extArrayPrimary pointing to. The area, perimeter, + * capacitance, and coupling capacitance for this element are extracted. + * + * Results: + * Returns 1 to cause DBArraySr to abort and return 1 itself. + * This is so the caller of DBArraySr can tell whether or not + * any elements were found (a sanity check). + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +extArrayPrimaryFunc(use, trans, x, y, ha) + CellUse *use; /* Use of which this is an array element */ + Transform *trans; /* Transform from coordinates of use->cu_def to those + * in use->cu_parent, for the array element (x, y). + */ + int x, y; /* X, Y indices of this array element */ + HierExtractArg *ha; +{ + CellDef *primDef; + HierYank hy; + + /* + * Remember the indices of this array element. + * When we are looking for all other array elements intersecting + * this area, we will ignore this element. We also remember the + * transform in case we need to use it in extArrayHardNode(). + */ + extArrayPrimXY.p_x = x, extArrayPrimXY.p_y = y; + extArrayPTrans = *trans; + + /* Restrict searching to interaction area for this element of array */ + GeoTransRect(trans, &use->cu_def->cd_bbox, &ha->ha_subArea); + GeoClip(&ha->ha_subArea, &ha->ha_interArea); + + /* Yank this element into the primary buffer */ + extArrayPrimary = extHierNewOne(); + hy.hy_area = &ha->ha_subArea; + hy.hy_target = extArrayPrimary->et_use; + hy.hy_prefix = FALSE; + (void) extHierYankFunc(use, trans, x, y, &hy); + + /* + * Extract extArrayPrimary, getting node capacitance, perimeter, + * and area, and coupling capacitances between nodes. Assign + * labels from primDef's label list. + */ + primDef = extArrayPrimary->et_use->cu_def; + extArrayPrimary->et_nodes = extFindNodes(primDef, &ha->ha_clipArea, FALSE); + ExtLabelRegions(primDef, ExtCurStyle->exts_nodeConn, + &extArrayPrimary->et_nodes, &ha->ha_clipArea); + if ((ExtOptions & (EXT_DOADJUST|EXT_DOCOUPLING)) + == (EXT_DOADJUST|EXT_DOCOUPLING)) + extFindCoupling(primDef, &extArrayPrimary->et_coupleHash, + &ha->ha_clipArea); + + return (1); +} + +/* + * ---------------------------------------------------------------------------- + * + * extArrayInterFunc -- + * + * Called by DBArraySr, which should find all array elements inside + * 'ha->ha_interArea' (in parent coordinates). If the array element + * (x, y) is the same as the primary element found by extArrayPrimaryFunc, + * i.e, the element (extArrayPrimXY.p_x, extArrayPrimXY.p_y), we + * skip it. Otherwise, we yank the overlap of this array element with + * 'ha->ha_interArea' into its own subtree and extract the interactions + * between it and extArrayPrimary. + * + * Results: + * Returns 0 to cause DBArraySr to continue. + * + * Side effects: + * Sets extArrayInterXY.p_x, extArrayInterXY.p_y to the element + * (x, y) so that lower-level functions have access to this information. + * + * ---------------------------------------------------------------------------- + */ + +int +extArrayInterFunc(use, trans, x, y, ha) + CellUse *use; /* Use of which this is an array element */ + Transform *trans; /* Transform from use->cu_def to use->cu_parent + * coordinates, for the array element (x, y). + */ + int x, y; /* X, Y of this array element in use->cu_def coords */ + HierExtractArg *ha; +{ + CellUse *cumUse = ha->ha_cumFlat.et_use; + CellDef *cumDef = cumUse->cu_def; + SearchContext scx; + CellDef *oneDef; + ExtTree *oneFlat; + HierYank hy; + + /* Skip this element if it is the primary one */ + if (x == extArrayPrimXY.p_x && y == extArrayPrimXY.p_y) + return (0); + + switch (extArrayWhich) + { + /* + * Area A is above, or above and to the right. + * Given where we search, there are no elements below and + * to the right of area A. + */ + case AREA_A: + if (x == extArrayPrimXY.p_x || y == extArrayPrimXY.p_y) + { + /* + * Exactly one of X or Y is the same as for + * the primary element. + */ + if (trans->t_a) + { + /* + * X, Y are still X, Y in parent. + * If X is different, this element is only to the + * right and so belongs to area B. + */ + if (x != extArrayPrimXY.p_x) return (0); + } + else + { + /* + * X, Y are interchanged in parent. + * If Y is different, this element is only to the + * right and so belongs to area B. + */ + if (y != extArrayPrimXY.p_y) return (0); + } + } + break; + /* + * Area B is only interactions to the right (not + * above, or diagonally above or below), in parent + * coordinates. + */ + case AREA_B: + if (trans->t_a) + { + /* x, y are still x, y in parent */ + if (y != extArrayPrimXY.p_y) return (0); + } + else + { + /* x, y are interchanged in parent */ + if (x != extArrayPrimXY.p_x) return (0); + } + break; + /* + * Area C checks only diagonal interactions. + * Given where we search, there are no interactions + * above and to the right of area C; the only diagonal + * interactions are below and to the right. + */ + case AREA_C: + if (x == extArrayPrimXY.p_x || y == extArrayPrimXY.p_y) + return (0); + break; + } + + /* Indicate which element this is to connection output routines */ + extArrayInterXY.p_x = x, extArrayInterXY.p_y = y; + extArrayITrans = *trans; + + /* Restrict searching to interaction area for this element of array */ + GeoTransRect(trans, &use->cu_def->cd_bbox, &ha->ha_subArea); + GeoClip(&ha->ha_subArea, &ha->ha_interArea); + + /* Yank this array element into a new ExtTree */ + oneFlat = extHierNewOne(); + hy.hy_area = &ha->ha_subArea; + hy.hy_target = oneFlat->et_use; + hy.hy_prefix = FALSE; + (void) extHierYankFunc(use, trans, x, y, &hy); + + /* + * Extract node capacitance, perimeter, area, and coupling capacitance + * for this subtree. Labels come from the hierarchical labels yanked + * above, but may have additional labels added when we find names the + * hard way. + */ + oneDef = oneFlat->et_use->cu_def; + oneFlat->et_nodes = extFindNodes(oneDef, &ha->ha_clipArea, FALSE); + ExtLabelRegions(oneDef, ExtCurStyle->exts_nodeConn, &oneFlat->et_nodes, + &ha->ha_clipArea); + if ((ExtOptions & (EXT_DOADJUST|EXT_DOCOUPLING)) + == (EXT_DOADJUST|EXT_DOCOUPLING)) + extFindCoupling(oneDef, &oneFlat->et_coupleHash, &ha->ha_clipArea); + + /* Process connections */ + extHierConnections(ha, extArrayPrimary, oneFlat); + + /* Process substrate connection */ + extHierSubstrate(ha, use, x, y); + + ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL; + if (ExtOptions & EXT_DOADJUST) + { + /* Build cumulative buffer from both extArrayPrimary and oneFlat */ + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = TiPlaneRect; + scx.scx_use = oneFlat->et_use; + DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, cumUse); + scx.scx_use = extArrayPrimary->et_use; + DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, cumUse); + + /* + * Extract everything in the cumulative buffer. + * Don't bother labelling the nodes, though, since we will never look + * at the node labels (we only search extArrayPrimary or oneFlat for + * the name of a node). Finally, compute and output adjustments for + * nodes and coupling capacitance. + */ + HashInit(&ha->ha_cumFlat.et_coupleHash, 32, + HashSize(sizeof (CoupleKey))); + ha->ha_cumFlat.et_nodes = extFindNodes(cumDef, &ha->ha_clipArea, FALSE); + if (ExtOptions & EXT_DOCOUPLING) + extFindCoupling(cumDef, &ha->ha_cumFlat.et_coupleHash, + &ha->ha_clipArea); + extArrayAdjust(ha, oneFlat, extArrayPrimary); + if (ExtOptions & EXT_DOCOUPLING) + extCapHashKill(&ha->ha_cumFlat.et_coupleHash); + } + + /* Clean up */ + if (oneFlat) extHierFreeOne(oneFlat); + if (ha->ha_cumFlat.et_nodes) + ExtFreeLabRegions((LabRegion *) ha->ha_cumFlat.et_nodes); + ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL; + DBCellClearDef(cumDef); + return (0); +} + +void +extArrayAdjust(ha, et1, et2) + HierExtractArg *ha; + ExtTree *et1, *et2; +{ + CapValue cap; /* value of capacitance WAS: int */ + NodeRegion *np; + CoupleKey *ck; + HashEntry *he; + NodeName *nn; + HashSearch hs; + char *name; + + /* + * Initialize the capacitance, perimeter, and area values + * in the Nodes in the hash table ha->ha_connHash, taking + * their values from the NodeRegions in ha->ha_cumFlat. + */ + for (np = ha->ha_cumFlat.et_nodes; np; np = np->nreg_next) + { + if ((name = extArrayNodeName(np, ha, et1, et2)) + && (he = HashLookOnly(&ha->ha_connHash, name)) + && (nn = (NodeName *) HashGetValue(he))) + { + nn->nn_node->node_cap = np->nreg_cap; + bcopy((char *) np->nreg_pa, (char *) nn->nn_node->node_pa, + ExtCurStyle->exts_numResistClasses * sizeof (PerimArea)); + } + } + + /* + * Coupling capacitance from et1 and et2 gets subtracted from that + * stored in ha->ha_cumFlat. Also, subtract the node capacitance, + * perimeter, and area of each subtree from ha->ha_cumFlat's nodes. + */ + extHierAdjustments(ha, &ha->ha_cumFlat, et1, et1); + extHierAdjustments(ha, &ha->ha_cumFlat, et2, et2); + + HashStartSearch(&hs); + while (he = HashNext(&ha->ha_cumFlat.et_coupleHash, &hs)) + { + cap = extGetCapValue(he) / ExtCurStyle->exts_capScale; + if (cap == 0) + continue; + + ck = (CoupleKey *) he->h_key.h_words; + name = extArrayNodeName(ck->ck_1, ha, et1, et2); + fprintf(ha->ha_outf, "cap \"%s\" ", name); + name = extArrayNodeName(ck->ck_2, ha, et1, et2); + fprintf(ha->ha_outf, "\"%s\" %lg\n", name, cap); + } +} + +char * +extArrayNodeName(np, ha, et1, et2) + NodeRegion *np; + HierExtractArg *ha; + ExtTree *et1, *et2; +{ + Tile *tp; + + tp = extNodeToTile(np, et1); + if (tp && TiGetType(tp) != TT_SPACE && extHasRegion(tp, extUnInit)) + return (extArrayTileToNode(tp, np->nreg_pnum, et1, ha, TRUE)); + + tp = extNodeToTile(np, et2); + if (tp && TiGetType(tp) != TT_SPACE && extHasRegion(tp, extUnInit)) + return (extArrayTileToNode(tp, np->nreg_pnum, et2, ha, TRUE)); + + return ("(none)"); +} + +/* + * ---------------------------------------------------------------------------- + * + * extArrayTileToNode -- + * + * Map from a Tile in a given ExtTree to the name of the node + * containing that tile. + * + * The node associated with a tile can be determined in one of the + * following ways: + * + * (1) Look for a label on the list of the Region pointed to by the + * tile planes of 'et->et_use->cu_def'. If no label was found, + * then try (2). + * + * (2) Call extArrayHardNode() to do a painful extraction of a label. + * See the comments in extArrayHardNode() for a description of + * the algorithm used. Only do this if doHard is TRUE. + * + * The actual name we use will be prefixed by the array use identifier + * (from ha->ha_subUse), followed by the range of subscripts for that array + * for which this is valid. The ExtTree 'et' tells us whether we are looking + * at the primary element of an array (when it is extArrayPrimary), or at + * one of the elements against which the primary is being extracted. + * + * Results: + * Returns a pointer to the name of the node containing + * the tile. If no node name was found, and doHard was + * TRUE, return the string "(none)"; if doHard was FALSE, + * return NULL. + * + * Side effects: + * The string returned is allocated from a static buffer, so + * subsequent calls to extArrayTileToNode() will overwrite + * the results returned in previous calls. + * + * Records an error with the feedback package if no node name + * could be found, and doHard was TRUE. + * + * ---------------------------------------------------------------------------- + */ + +char * +extArrayTileToNode(tp, pNum, et, ha, doHard) + Tile *tp; + int pNum; + ExtTree *et; + HierExtractArg *ha; + bool doHard; /* If TRUE, we look up this node's name the hard way + * if we can't find it any other way; otherwise, we + * return NULL if we can't find the node's name. + */ +{ + static char name[2048]; + static char errorStr[] = + "Cannot find the name of this node (probable extractor error)"; + CellDef *def = et->et_use->cu_def; + CellUse *use = ha->ha_subUse; + char *srcp, *dstp, *endp; + bool hasX = (use->cu_xlo != use->cu_xhi); + bool hasY = (use->cu_ylo != use->cu_yhi); + int xdiff = extArrayInterXY.p_x - extArrayPrimXY.p_x; + int ydiff = extArrayInterXY.p_y - extArrayPrimXY.p_y; + LabRegion *reg; + Rect r; + + if (extHasRegion(tp, extUnInit)) + { + reg = (LabRegion *) extGetRegion(tp); + if (reg->lreg_labels) + goto found; + } + + if (!DebugIsSet(extDebugID, extDebNoHard)) + if (reg = (LabRegion *) extArrayHardNode(tp, pNum, def, ha)) + goto found; + + /* Blew it */ + if (!doHard) return ((char *) NULL); + extNumFatal++; + TiToRect(tp, &r); + if (!DebugIsSet(extDebugID, extDebNoFeedback)) + DBWFeedbackAdd(&r, errorStr, ha->ha_parentUse->cu_def, 1, + STYLE_MEDIUMHIGHLIGHTS); + return ("(none)"); + +found: + /* Copy in the use id, leaving room for [%d:%d,%d:%d] at the end */ + srcp = use->cu_id; + dstp = name; + endp = &name[sizeof name - 40]; + while (dstp < endp && (*dstp++ = *srcp++)) + /* Nothing */; + if (dstp >= endp) goto done; + dstp--; + +#define Far(v, lo, hi) ((v) == (lo) ? (hi) : (lo)) +#define FarX(u) Far(extArrayPrimXY.p_x, (u)->cu_xlo, (u)->cu_xhi) +#define FarY(u) Far(extArrayPrimXY.p_y, (u)->cu_ylo, (u)->cu_yhi) + + /* + * Append the array subscripts. + * Remember that 2-d arrays are subscripted [y,x] and not [x,y]. + */ + if (def == extArrayPrimary->et_use->cu_def) + { + if (hasY) + dstp = extArrayRange(dstp, extArrayPrimXY.p_y, + FarY(use) - ydiff, FALSE, hasX); + if (hasX) + dstp = extArrayRange(dstp, extArrayPrimXY.p_x, + FarX(use) - xdiff, hasY, FALSE); + } + else + { + if (hasY) + dstp = extArrayRange(dstp, extArrayInterXY.p_y, + FarY(use), FALSE, hasX); + if (hasX) + dstp = extArrayRange(dstp, extArrayInterXY.p_x, + FarX(use), hasY, FALSE); + } + +#undef Far +#undef FarX +#undef FarY + +done: + *dstp++ = '/'; + endp = &name[sizeof name - 1]; + srcp = extNodeName(reg); + while (dstp < endp && (*dstp++ = *srcp++)) + /* Nothing */; + + *dstp = '\0'; + return (name); +} + +/* + * ---------------------------------------------------------------------------- + * + * extArrayRange -- + * + * Called by extArrayTileToNode above, we print a range of the form [lo:hi] + * into the string pointed to by 'dstp'. Guarantees that lo <= hi. + * + * Results: + * Returns a pointer to the NULL byte at the end of the string + * we print into (dstp). + * + * Side effects: + * Writes characters into 'dstp', which should be large enough + * to hold any possible string of the form [int:int]. + * + * ---------------------------------------------------------------------------- + */ + +char * +extArrayRange(dstp, lo, hi, prevRange, followRange) + char *dstp; + int lo, hi; + bool prevRange; /* TRUE if preceded by a range */ + bool followRange; /* TRUE if followed by a range */ +{ + if (!prevRange) *dstp++ = '['; + if (hi < lo) + (void) sprintf(dstp, "%d:%d", hi, lo); + else + (void) sprintf(dstp, "%d:%d", lo, hi); + while (*dstp++) /* Nothing */; + dstp[-1] = followRange ? ',' : ']'; + *dstp = '\0'; + return (dstp); +} + +/* + * ---------------------------------------------------------------------------- + * + * extArrayHardNode -- + * + * Find a node name for the electrical node containing the tile 'tp' + * the hard way. We assume tp->ti_client points to a LabRegion that + * had no labels associated with it; if we succeed, we leave this + * LabRegion pointing to a newly allocated LabelList and Label. + * + * Results: + * Returns a pointer to LabRegion for the node to which the tile + * 'tp' belongs. Returns NULL if no region could be found. + * + * Side effects: + * None. + * + * Algorithm: + * Search in the appropriate array element to the yank buffer + * in question: if 'def' is the primary buffer, search the + * element (extArrayPrimXY.p_x, extArrayPrimXY.p_y); otherwise, + * search (extArrayInterXY.p_x, extArrayInterXY.p_y). + * + * For each cell we find in the course of a hierarchical search + * of this array element in the area of the tile 'tp', trace out + * the nodes lying in the area of the overlap, and then do a label + * assignment for those nodes. As soon as we find a label, we're + * done. Otherwise, we reset this def back the way we found it + * and continue on to the next cell in our search. + * + * ---------------------------------------------------------------------------- + */ + +LabRegion * +extArrayHardNode(tp, pNum, def, ha) + Tile *tp; + int pNum; + CellDef *def; + HierExtractArg *ha; +{ + TileType type = TiGetType(tp); + char labelBuf[4096]; + SearchContext scx; + HardWay arg; + + arg.hw_ha = ha; + arg.hw_label = (Label *) NULL; + arg.hw_mask = DBPlaneTypes[pNum]; + TTMaskAndMask(&arg.hw_mask, &DBConnectTbl[type]); + arg.hw_tpath.tp_last = &labelBuf[sizeof labelBuf - 3]; + arg.hw_tpath.tp_first = arg.hw_tpath.tp_next = labelBuf; + arg.hw_prefix = FALSE; + arg.hw_autogen = FALSE; + TiToRect(tp, &arg.hw_area); + scx.scx_use = ha->ha_subUse; + + /* Find a label in the interaction area */ + labelBuf[0] = '\0'; + extArrayHardSearch(def, &arg, &scx, extHardProc); + if (arg.hw_label == NULL) + { + labelBuf[0] = '\0'; + arg.hw_autogen = TRUE; + extArrayHardSearch(def, &arg, &scx, extHardProc); + } + + if (arg.hw_label) + { + LabRegion *lreg; + LabelList *ll; + + lreg = (LabRegion *) extGetRegion(tp); + ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList))); + lreg->lreg_labels = ll; + ll->ll_next = (LabelList *) NULL; + ll->ll_label = arg.hw_label; + arg.hw_label->lab_next = def->cd_labels; + def->cd_labels = arg.hw_label; + return (lreg); + } + + return ((LabRegion *) NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * extArrayHardSearch -- + * + * Do the actual work of calling (*proc)() either to find a label the hard + * way, or to create a new label. Called from extArrayHardNode above. + * + * Results: + * None. + * + * Side effects: + * Those of (*proc)(). + * + * ---------------------------------------------------------------------------- + */ + +void +extArrayHardSearch(def, arg, scx, proc) + CellDef *def; + HardWay *arg; + SearchContext *scx; + int (*proc)(); +{ + Transform tinv; + + if (def == extArrayPrimary->et_use->cu_def) + { + scx->scx_trans = extArrayPTrans; + scx->scx_x = extArrayPrimXY.p_x; + scx->scx_y = extArrayPrimXY.p_y; + } + else + { + scx->scx_trans = extArrayITrans; + scx->scx_x = extArrayInterXY.p_x; + scx->scx_y = extArrayInterXY.p_y; + } + GeoInvertTrans(&scx->scx_trans, &tinv); + GeoTransRect(&tinv, &arg->hw_area, &scx->scx_area); + (void) (*proc)(scx, arg); +} diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c new file mode 100644 index 00000000..c0088992 --- /dev/null +++ b/extract/ExtBasic.c @@ -0,0 +1,3639 @@ +/* + * ExtBasic.c -- + * + * Circuit extraction. + * Flat extraction of a single CellDef. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char sccsid[] = "@(#)ExtBasic.c 4.13 MAGIC (Berkeley) 12/5/85"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "utils/stack.h" +#include "utils/utils.h" + +/* These must be in the order of "known devices" in extract.h. */ + +/* Note: "fet" refers to the original fet type; "mosfet" refers to the */ +/* new type. The main difference is that "fet" records area/perimeter */ +/* while "mosfet" records length/width. */ +/* Also: Note that this table is repeated in extflat/EFread.c when */ +/* ext2spice/ext2sim are compiled as separate programs (i.e., non-Tcl) */ + +#ifdef MAGIC_WRAPPER +char *extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres", + "devcap", "devcaprev", "diode", "pdiode", "ndiode", "subckt", + "rsubckt", "msubckt", NULL}; +#endif + +/* --------------------- Data local to this file ---------------------- */ + + /* + * The following are used to accumulate perimeter and area + * on each layer when building up the node list. They are + * used to compute the resistance of each node. Each is + * indexed by sheet resistivity class. + */ +int extResistPerim[NT], extResistArea[NT]; + + /* + * The following structure is used in extracting transistors. + * + * A "terminal" below refers to any port on the transistor that + * is not the gate. In most cases, these are the "diffusion" + * ports of the transistor. + */ +#define MAXSD 10 /* Maximum # of terminals per transistor */ + + +typedef struct /* Position of each terminal (below) tile position */ +{ + int pnum; + Point pt; +} TermTilePos; + +struct transRec +{ + int tr_nterm; /* Number of terminals */ + int tr_gatelen; /* Perimeter of connection to gate */ + NodeRegion *tr_gatenode; /* Node region for gate terminal */ + NodeRegion *tr_termnode[MAXSD]; /* Node region for each diff terminal */ + NodeRegion *tr_subsnode; /* Substrate node */ + int tr_termlen[MAXSD]; /* Length of each diff terminal edge, + * used for computing L/W for the fet. + */ + Point tr_termvector[MAXSD]; /* Perimeter traversal vector, used to + * find and calculate correct parameters + * for annular (ring) devices and other + * non-rectangular geometries. + */ + int tr_perim; /* Total perimeter */ + TermTilePos tr_termpos[MAXSD]; /* lowest tile connecting to term */ +} extTransRec; + +typedef struct LB1 +{ + Rect r; /* Boundary segment */ + int dir; /* Direction of travel */ + struct LB1 *b_next; +} LinkedBoundary; + +LinkedBoundary **extSpecialBounds; /* Linked Boundary List */ +NodeRegion *glob_subsnode = NULL; /* Global substrate node */ +NodeRegion *temp_subsnode = NULL; /* Last subsnode found */ + +/* Structure used for finding substrate connections on implicitly-defined + * substrates + */ + +typedef struct TSD1 +{ + bool found; /* Set to 1 if a substrate connection was found */ + Rect rtrans; /* Rectangle of device */ + Rect rhalo; /* Search halo around device */ + NodeRegion *nreg; /* Closest substrate region within halo */ +} TransSubsData; + +#define EDGENULL(r) ((r)->r_xbot > (r)->r_xtop || (r)->r_ybot > (r)->r_ytop) + +/* Forward declarations */ +void extOutputNodes(); +int extTransTileFunc(); +int extTransPerimFunc(); +int extTransFindSubs(); + +int extAnnularTileFunc(); +int extResistorTileFunc(); +int extSpecialPerimFunc(); + +void extFindDuplicateLabels(); +void extOutputDevices(); +void extOutputParameters(); +void extTransOutTerminal(); +void extTransBad(); + +bool extLabType(); + +/* + * ---------------------------------------------------------------------------- + * + * extBasic -- + * + * Extract a single CellDef, and output the result to the + * file 'outFile'. + * + * Results: + * Returns a list of Region structs that comprise all + * the nodes in 'def'. It is the caller's responsibility + * to call ExtResetTile() and ExtFreeLabRegions() to restore + * the CellDef to its original state and to free the list + * of regions we build up. + * + * Side effects: + * Writes the result of extracting just the paint of + * the CellDef 'def' to the output file 'outFile'. + * The following kinds of records are output: + * + * node + * substrate + * equiv + * fet + * device + * + * Interruptible in a limited sense. We will still return a + * Region list, but labels may not have been assigned, and + * nodes and fets may not have been output. + * + * ---------------------------------------------------------------------------- + */ + +NodeRegion * +extBasic(def, outFile) + CellDef *def; /* Cell being extracted */ + FILE *outFile; /* Output file */ +{ + NodeRegion *nodeList, *extFindNodes(); + bool coupleInitialized = FALSE; + TransRegion *transList; + HashTable extCoupleHash; + char *propptr; + bool propfound = FALSE; + + glob_subsnode = (NodeRegion *)NULL; + + /* + * Build up a list of the device regions for extOutputDevices() + * below. We're only interested in pointers from each region to + * a tile in that region, not the back pointers from the tiles to + * the regions. + */ + transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect, + &ExtCurStyle->exts_transMask, + ExtCurStyle->exts_transConn, + extUnInit, extTransFirst, extTransEach); + ExtResetTiles(def, extUnInit); + + /* + * Build up a list of the electrical nodes (equipotentials) + * for extOutputNodes() below. For this, we definitely want + * to leave each tile pointing to its associated Region struct. + * Compute resistance and capacitance on the fly. + * Use a special-purpose version of ExtFindRegions for speed. + */ + if (!SigInterruptPending) + nodeList = extFindNodes(def, (Rect *) NULL, FALSE); + + glob_subsnode = temp_subsnode; // Keep a record of the def's substrate + + /* Assign the labels to their associated regions */ + if (!SigInterruptPending) + ExtLabelRegions(def, ExtCurStyle->exts_nodeConn, &nodeList, &TiPlaneRect); + + /* + * Make sure all geometry with the same label is part of the + * same electrical node. + */ + if (!SigInterruptPending && (ExtDoWarn & EXTWARN_DUP)) + extFindDuplicateLabels(def, nodeList); + + /* + * Build up table of coupling capacitances (overlap, sidewall). + * This comes before extOutputNodes because we may have to adjust + * node capacitances in this step. + */ + if (!SigInterruptPending && (ExtOptions&EXT_DOCOUPLING)) + { + coupleInitialized = TRUE; + HashInit(&extCoupleHash, 256, HashSize(sizeof (CoupleKey))); + extFindCoupling(def, &extCoupleHash, (Rect *) NULL); + + /* Convert coupling capacitance to the substrate node to + * substrate capacitance on each node in nreg_cap + */ + + if (ExtCurStyle->exts_globSubstratePlane != -1) + if (!SigInterruptPending && (ExtOptions&EXT_DOCOUPLING)) + extRelocateSubstrateCoupling(&extCoupleHash, glob_subsnode); + } + + /* Output device parameters for any subcircuit devices */ + if (!SigInterruptPending) + extOutputParameters(def, transList, outFile); + + /* Check for "device", as it modifies handling of parasitics */ + propptr = (char *)DBPropGet(def, "device", &propfound); + if (propfound) + { + /* Remove parasitics from local nodes */ + NodeRegion *tnode; + for (tnode = nodeList; tnode; tnode = tnode->nreg_next) + { + tnode->nreg_cap = (CapValue)0.0; + tnode->nreg_resist = (ResValue)0; + } + } + + /* Output each node, along with its resistance and capacitance to substrate */ + if (!SigInterruptPending) + extOutputNodes(nodeList, outFile); + + /* Output coupling capacitances */ + if (!SigInterruptPending && (ExtOptions&EXT_DOCOUPLING) && (!propfound)) + extOutputCoupling(&extCoupleHash, outFile); + + /* Output devices and connectivity between nodes */ + if (!SigInterruptPending) + { + int llx, lly, urx, ury, devidx, l, w; + char *token, *modelname, *subsnode; + char *propvalue; + + modelname = NULL; + subsnode = NULL; + propvalue = NULL; + + if (propfound) + { + /* Sanity checking on syntax of property line, plus */ + /* conversion of values to internal units. */ + propvalue = StrDup((char **)NULL, propptr); + token = strtok(propvalue, " "); + devidx = Lookup(token, extDevTable); + if (devidx < 0) + { + TxError("Extract error: \"device\" property has unknown " + "device type.\n", token); + propfound = FALSE; + } + if (propfound) + { + token = strtok(NULL, " "); + if (token == NULL) + propfound = FALSE; + else + modelname = StrDup((char **)NULL, token); + } + if (propfound) + { + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &llx)) + propfound = FALSE; + else + llx *= ExtCurStyle->exts_unitsPerLambda; + } + if (propfound) + { + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &lly)) + propfound = FALSE; + else + lly *= ExtCurStyle->exts_unitsPerLambda; + } + if (propfound) + { + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &urx)) + propfound = FALSE; + else + urx *= ExtCurStyle->exts_unitsPerLambda; + if (urx <= llx) urx++; + } + if (propfound) + { + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &ury)) + propfound = FALSE; + else + ury *= ExtCurStyle->exts_unitsPerLambda; + if (ury <= lly) ury++; + } + if (propfound) + { + switch (devidx) + { + case DEV_FET: + /* Read area */ + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &w)) + propfound = FALSE; + else + w *= ExtCurStyle->exts_unitsPerLambda * + ExtCurStyle->exts_unitsPerLambda; + /* Read perimeter */ + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &l)) + propfound = FALSE; + else + l *= ExtCurStyle->exts_unitsPerLambda; + break; + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_BJT: + /* Read width */ + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &w)) + propfound = FALSE; + else + w *= ExtCurStyle->exts_unitsPerLambda; + /* Read length */ + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &l)) + propfound = FALSE; + else + l *= ExtCurStyle->exts_unitsPerLambda; + break; + case DEV_RES: + if (strcmp(modelname, "None")) + { + /* Read width */ + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &w)) + propfound = FALSE; + else + w *= ExtCurStyle->exts_unitsPerLambda; + /* Read length */ + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &l)) + propfound = FALSE; + else + l *= ExtCurStyle->exts_unitsPerLambda; + break; + } + break; + case DEV_CAP: + case DEV_CAPREV: + if (strcmp(modelname, "None")) + { + /* Read area */ + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &w)) + propfound = FALSE; + else + w *= ExtCurStyle->exts_unitsPerLambda * + ExtCurStyle->exts_unitsPerLambda; + /* Read perimeter */ + token = strtok(NULL, " "); + if ((token == NULL) || !sscanf(token, "%d", &l)) + propfound = FALSE; + else + l *= ExtCurStyle->exts_unitsPerLambda; + break; + } + break; + } + } + + if (propfound) + { + if (devidx == DEV_FET) + fprintf(outFile, "fet"); + else + fprintf(outFile, "device %s", extDevTable[devidx]); + fprintf(outFile, " %s %d %d %d %d", modelname, + llx, lly, urx, ury); + switch (devidx) { + case DEV_FET: + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_BJT: + fprintf(outFile, " %d %d", w, l); + break; + case DEV_RES: + case DEV_CAP: + case DEV_CAPREV: + if (strcmp(modelname, "None")) + fprintf(outFile, " %d %d", w, l); + break; + } + /* Print remainder of arguments verbatim. */ + /* Note: There should be additional checks on */ + /* node triplets including area and perim. conversions */ + while (1) { + token = strtok(NULL, " "); + if (token == NULL) + break; + else + fprintf(outFile, " %s", token); + } + } + else if (devidx >= 0) + { + TxError("Extract error: \"device %s\" property syntax" + " error\n", extDevTable[devidx]); + } + if (modelname) freeMagic(modelname); + if (propvalue) freeMagic(propvalue); + } + + if (!propfound) + extOutputDevices(def, transList, outFile); + } + + /* Clean up */ + if (coupleInitialized) + extCapHashKill(&extCoupleHash); + ExtFreeLabRegions((LabRegion *) transList); + return (nodeList); +} + +/* + * ---------------------------------------------------------------------------- + * + * extSetResist -- + * + * The input to this procedure is a pointer to a NodeRegion. + * Its resistance is computed from the area and perimeter stored + * in the arrays extResistPerim[] and extResistArea[]. These arrays + * are then reset to zero. + * + * We approximate the resistive region as a collection of rectangles + * of width W and length L, one for each set of layers having a different + * sheet resistivity. We do so by noting that for a rectangle, + * + * Area = L * W + * Perimeter = 2 * (L + W) + * + * Solving the two simultaneous equations for L yields the following + * quadratic: + * + * 2 * (L**2) - Perimeter * L + 2 * Area = 0 + * + * Solving this quadratic for L, the longer dimension, we get + * + * L = (Perimeter + S) / 4 + * + * where + * + * S = sqrt( (Perimeter**2) - 16 * Area ) + * + * The smaller dimension is W, ie, + * + * W = (Perimeter - S) / 4 + * + * The resistance is L / W squares: + * + * Perimeter + S + * R = ------------- + * Perimeter - S + * + * Results: + * None. + * + * Side effects: + * See the comments above. + * + * ---------------------------------------------------------------------------- + */ + +void +extSetResist(reg) + NodeRegion *reg; +{ + int n, perim, area; + float s, fperim, v; + + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + { + reg->nreg_pa[n].pa_area = area = extResistArea[n]; + reg->nreg_pa[n].pa_perim = perim = extResistPerim[n]; + if (area > 0 && perim > 0) + { + v = (double) (perim*perim - 16*area); + + /* Approximate by one square if v < 0 */ + if (v < 0) s = 0; else s = sqrt(v); + + fperim = (float) perim; + reg->nreg_resist += (fperim + s) / (fperim - s) + * ExtCurStyle->exts_resistByResistClass[n]; + } + + /* Reset for the next pass */ + extResistArea[n] = extResistPerim[n] = 0; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extOutputNodes -- + * + * The resistance and capacitance of each node have already been + * computed, so all we need do is output them. + * + * Results: + * None. + * + * Side effects: + * Writes a number of 'node' and 'equiv' records to the file 'outFile'. + * + * Interruptible. If SigInterruptPending is detected, we stop outputting + * nodes and return. + * + * ---------------------------------------------------------------------------- + */ + +void +extOutputNodes(nodeList, outFile) + NodeRegion *nodeList; /* Nodes */ + FILE *outFile; /* Output file */ +{ + ResValue rround = ExtCurStyle->exts_resistScale / 2; + CapValue finC; + int intR; + NodeRegion *reg; + LabelList *ll; + char *cp; + int n; + Label *lab; + char *text; + + /* If this node is a subcircuit port, it gets special treatment. */ + /* There may be multiple ports per node. */ + + for (reg = nodeList; reg && !SigInterruptPending; reg = reg->nreg_next) + for (ll = reg->nreg_labels; ll; ll = ll->ll_next) + if (ll->ll_attr == LL_PORTATTR) + { + fprintf(outFile, "port \"%s\" %d %d %d %d %d %s\n", + ll->ll_label->lab_text, + ll->ll_label->lab_flags & PORT_NUM_MASK, + ll->ll_label->lab_rect.r_xbot, + ll->ll_label->lab_rect.r_ybot, + ll->ll_label->lab_rect.r_xtop, + ll->ll_label->lab_rect.r_ytop, + DBTypeShortName(ll->ll_label->lab_type)); + + /* If the port name matches the node name to be written */ + /* to the node record, then reassign the node position */ + /* and type to be that of the port, so we don't have a */ + /* conflict. */ + + if (!strcmp(extNodeName((LabRegion *) reg), + ll->ll_label->lab_text)) + { + reg->nreg_ll.p_x = ll->ll_label->lab_rect.r_xbot; + reg->nreg_ll.p_y = ll->ll_label->lab_rect.r_ybot; + reg->nreg_type = ll->ll_label->lab_type; + reg->nreg_pnum = DBPlane(reg->nreg_type); + } + } + + for (reg = nodeList; reg && !SigInterruptPending; reg = reg->nreg_next) + { + /* Output the node */ + text = extNodeName((LabRegion *) reg); + + /* Check if this node is the substrate */ + if (reg == glob_subsnode) + { + fprintf(outFile, "substrate \"%s\" 0 0", text); + } + else + { + intR = (reg->nreg_resist + rround) / ExtCurStyle->exts_resistScale; + finC = reg->nreg_cap/ExtCurStyle->exts_capScale; + fprintf(outFile, "node \"%s\" %d %lg", text, intR, finC); + } + + /* Output its location (lower-leftmost point and type name) */ + + if (reg->nreg_type & TT_DIAGONAL) { + /* Node may be recorded as a diagonal tile if no other */ + /* non-diagonal tiles are adjoining it. */ + + TileType loctype = (reg->nreg_type & TT_SIDE) ? ((reg->nreg_type & + TT_RIGHTMASK) >> 14) : (reg->nreg_type & TT_LEFTMASK); + + fprintf(outFile, " %d %d %s", + reg->nreg_ll.p_x, reg->nreg_ll.p_y, + DBTypeShortName(loctype)); + } + else + { + fprintf(outFile, " %d %d %s", + reg->nreg_ll.p_x, reg->nreg_ll.p_y, + DBTypeShortName(reg->nreg_type)); + } + + /* Output its area and perimeter for each resistivity class */ + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + fprintf(outFile, " %d %d", reg->nreg_pa[n].pa_area, + reg->nreg_pa[n].pa_perim); + (void) putc('\n', outFile); + + /* Output its attribute list */ + for (ll = reg->nreg_labels; ll; ll = ll->ll_next) + if (extLabType(ll->ll_label->lab_text, LABTYPE_NODEATTR)) + { + /* Don't output the trailing character for node attributes */ + lab = ll->ll_label; + fprintf(outFile, "attr %s %d %d %d %d %s \"", + text, lab->lab_rect.r_xbot, lab->lab_rect.r_ybot, + lab->lab_rect.r_xtop, lab->lab_rect.r_ytop, + DBTypeShortName(lab->lab_type)); + cp = lab->lab_text; + n = strlen(cp) - 1; + while (n-- > 0) + putc(*cp++, outFile); + fprintf(outFile, "\"\n"); + } + + /* Output the alternate names for the node */ + for (ll = reg->nreg_labels; ll; ll = ll->ll_next) + if (ll->ll_label->lab_text == text) + { + for (ll = ll->ll_next; ll; ll = ll->ll_next) + if (extLabType(ll->ll_label->lab_text, LABTYPE_NAME)) + fprintf(outFile, "equiv \"%s\" \"%s\"\n", + text, ll->ll_label->lab_text); + break; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extFindDuplicateLabels -- + * + * Verify that no node in the list 'nreg' has a label that appears in + * any other node in the list. Leave a warning turd if one is. + * + * Results: + * None. + * + * Side effects: + * Leaves feedback attached to each node that contains a label + * duplicated in another node. + * + * ---------------------------------------------------------------------------- + */ + +void +extFindDuplicateLabels(def, nreg) + CellDef *def; + NodeRegion *nreg; +{ + static char *badmesg = + "Label \"%s\" attached to more than one unconnected node: %s"; + bool hashInitialized = FALSE; + char message[512], name[512], *text; + NodeRegion *np, *np2; + LabelList *ll, *ll2; + HashEntry *he; + NodeRegion *lastreg; + NodeRegion badLabel; + HashTable labelHash; + Rect r; + + for (np = nreg; np; np = np->nreg_next) + { + for (ll = np->nreg_labels; ll; ll = ll->ll_next) + { + text = ll->ll_label->lab_text; + if (!extLabType(text, LABTYPE_NAME)) + continue; + + if (!hashInitialized) + HashInit(&labelHash, 32, 0), hashInitialized = TRUE; + he = HashFind(&labelHash, text); + lastreg = (NodeRegion *) HashGetValue(he); + if (lastreg == (NodeRegion *) NULL) + HashSetValue(he, (ClientData) np); + else if (lastreg != np && lastreg != &badLabel) + { + /* + * Make a pass through all labels for all nodes. + * Leave a feedback turd over each instance of the + * offending label. + */ + for (np2 = nreg; np2; np2 = np2->nreg_next) + { + for (ll2 = np2->nreg_labels; ll2; ll2 = ll2->ll_next) + { + if (strcmp(ll2->ll_label->lab_text, text) == 0) + { + extNumWarnings++; + if (!DebugIsSet(extDebugID, extDebNoFeedback)) + { + r.r_ll = r.r_ur = ll2->ll_label->lab_rect.r_ll; + r.r_xbot--, r.r_ybot--, r.r_xtop++, r.r_ytop++; + extMakeNodeNumPrint(name, + np2->nreg_pnum, np2->nreg_ll); + (void) sprintf(message, badmesg, text, name); + DBWFeedbackAdd(&r, message, def, + 1, STYLE_PALEHIGHLIGHTS); + } + } + } + } + + /* Mark this label as already having generated an error */ + HashSetValue(he, (ClientData) &badLabel); + } + } + } + + if (hashInitialized) + HashKill(&labelHash); +} + +/* + * ---------------------------------------------------------------------------- + * + * extNodeName -- + * + * Given a pointer to a LabRegion, return a pointer to a string + * that can be printed as the name of the node. If the LabRegion + * has a list of attached labels, use one of the labels; otherwise, + * use its node number. + * + * Results: + * Returns a pointer to a string. If the node had a label, this + * is a pointer to the lab_text field of the first label on the + * label list for the node; otherwise, it is a pointer to a static + * buffer into which we have printed the node number. + * + * Side effects: + * May overwrite the static buffer used to hold the printable + * version of a node number. + * + * ---------------------------------------------------------------------------- + */ + +char * +extNodeName(node) + LabRegion *node; +{ + static char namebuf[256]; /* Big enough to hold a generated nodename */ + LabelList *ll; + + if (node == (LabRegion *) NULL || SigInterruptPending) + return ("(none)"); + + for (ll = node->lreg_labels; ll; ll = ll->ll_next) + if (extLabType(ll->ll_label->lab_text, LABTYPE_NAME)) + return (ll->ll_label->lab_text); + + extMakeNodeNumPrint(namebuf, node->lreg_pnum, node->lreg_ll); + return (namebuf); +} + +/* + * --------------------------------------------------------------------- + * + * ExtSortTerminals -- + * + * Sort the terminals of a transistor so that the terminal with the + * lowest leftmost coordinate on the plane with the lowest number is + * output first. + * + * Results: + * None + * + * Side effects: + * The tr_termnode, tr_termlen, and tr_termpos entries may change. + * + * --------------------------------------------------------------------- + */ + +void +ExtSortTerminals(tran, ll) + struct transRec *tran; + LabelList *ll; +{ + int nsd, changed; + TermTilePos *p1, *p2; + NodeRegion *tmp_node; + TermTilePos tmp_pos; + int tmp_len; + LabelList *lp; + + do + { + changed = 0; + for( nsd = 0; nsd < tran->tr_nterm-1; nsd++ ) + { + p1 = &(tran->tr_termpos[nsd]); + p2 = &(tran->tr_termpos[nsd+1]); + if( p2->pnum > p1->pnum ) + continue; + else if( p2->pnum == p1->pnum ) + { + if( p2->pt.p_x > p1->pt.p_x ) + continue; + else if( p2->pt.p_x == p1->pt.p_x && p2->pt.p_y > p1->pt.p_y ) + continue; + else if( p2->pt.p_x == p1->pt.p_x && p2->pt.p_y == p1->pt.p_y ) + { + TxPrintf("Extract error: Duplicate tile position, ignoring\n"); + continue; + } + } + changed = 1; + tmp_node = tran->tr_termnode[nsd]; + tmp_pos = tran->tr_termpos[nsd]; + tmp_len = tran->tr_termlen[nsd]; + + tran->tr_termnode[nsd] = tran->tr_termnode[nsd+1]; + tran->tr_termpos[nsd] = tran->tr_termpos[nsd+1]; + tran->tr_termlen[nsd] = tran->tr_termlen[nsd+1]; + + tran->tr_termnode[nsd+1] = tmp_node; + tran->tr_termpos[nsd+1] = tmp_pos; + tran->tr_termlen[nsd+1] = tmp_len; + /* Need to SWAP the indices in the labRegion too. + * These for loops within the bubblesort in here are kinda slow + * but S,D attributes are not that common so it should not matter + * that much -- Stefanos 5/96 */ + for ( lp = ll ; lp ; lp = lp->ll_next ) + if ( lp->ll_attr == nsd ) lp->ll_attr = LL_SORTATTR ; + else if ( lp->ll_attr == nsd+1 ) lp->ll_attr = nsd ; + for ( lp = ll ; lp ; lp = lp->ll_next ) + if ( lp->ll_attr == LL_SORTATTR ) lp->ll_attr = nsd+1; + } + } + while( changed ); +} + +/* + *---------------------------------------------------------------------- + * + * extComputeCapLW -- + * + * Determine effective length and width of a rectangular capacitor, + * based on the boundary vectors stored in extSpecialBounds. This + * routine should only be called for capacitors that have exactly + * one terminal. + * + * Results: + * None + * + * Side Effects: + * Puts effective length and width into the pointers + * passed as arguments. + *---------------------------------------------------------------------- + */ + +void +extComputeCapLW(rlengthptr, rwidthptr) + int *rlengthptr, *rwidthptr; +{ + LinkedBoundary *lb; + Rect bbox; + + /* Quick algorithm---ignore tabs, compute max extents of */ + /* the special bounds vector. */ + + lb = extSpecialBounds[0]; + if (lb == NULL) + { + TxError("extract: Can't get capacitor L and W\n"); + return; /* error condition */ + } + bbox = lb->r; + for (lb = extSpecialBounds[0]; lb != NULL; lb = lb->b_next) + GeoIncludeAll(&lb->r, &bbox); + + *rwidthptr = bbox.r_xtop - bbox.r_xbot; + *rlengthptr = bbox.r_ytop - bbox.r_ybot; +} + +/* + *---------------------------------------------------------------------- + * + * extComputeEffectiveLW -- + * + * Determine effective length and width of an annular (or otherwise + * non-rectangular) transistor structure, based on the boundary vectors + * stored in extSpecialBounds. + * + * Note that "L" and "W" are reversed when this routine is called + * to compute L and W for a resistor. The sense of "length" and + * "width" as used in the routine are appropriate for a transistor. + * + * Also note that this algorithm will tend to over-estimate the width + * of transistors with angled bends. This problem would be eliminated + * if non-Manhattan geometry were evaluated directly rather than being + * first converted to Manhattan geometry. + * + * Results: + * None. + * + * Side Effects: + * Puts effective length and width into the pointers + * passed as arguments. + *---------------------------------------------------------------------- + */ + +void +extComputeEffectiveLW(rlengthptr, rwidthptr, numregions, chop) + int *rlengthptr, *rwidthptr; + int numregions; + float chop; +{ + int i, j, p, jmax; + LinkedBoundary *lb, *lb2; + int oppdir, length, loclength, testlen, width; + int locwidth, testwid, cornerw; + int segp, segn, segc, sege; + bool isComplex = FALSE; + + /* First, check for MOScap-connected transistors. In such + * cases, one or more extSpecialBounds[] is NULL. Try to + * separate the existing extSpecialBounds[] vectors into + * independent (non-connecting) vectors. + */ + + /* For each segment in the primary list, find the closest + * segment in the other list which lies on the opposite + * side of the gate area. Calculate the length, and check + * for overlap, treating the length as a corner extension. + * + * The primary list is chosen as the one with the largest + * number of elements. This helps prevent the algorithm from + * producing a different result for devices at different + * orientations. + */ + + p = 0; + jmax = 0; + for (i = 0; i < numregions; i++) + { + j = 0; + for (lb = extSpecialBounds[i]; lb != NULL; lb = lb->b_next) j++; + if (j > jmax) + { + jmax = j; + p = i; + } + } + + /* fprintf(stderr, "Annular transistor detailed L,W computation:\n"); */ + + width = 0; + length = 0; + for (lb = extSpecialBounds[p]; lb != NULL; lb = lb->b_next) + { + loclength = INFINITY; + switch (lb->dir) + { + case BD_LEFT: oppdir = BD_RIGHT; break; + case BD_RIGHT: oppdir = BD_LEFT; break; + case BD_TOP: oppdir = BD_BOTTOM; break; + case BD_BOTTOM: oppdir = BD_TOP; break; + } + + /* First pass: Find the distance of the closest segment within */ + /* the range of its corner extension. We do two passes because */ + /* there may be more than one segment at this distance. */ + + for (i = 0; i < numregions; i++) + { + if ((i == p) && (numregions > 1)) continue; + for (lb2 = extSpecialBounds[i]; lb2 != NULL; lb2 = lb2->b_next) + { + if (lb2->dir == oppdir) + { + switch (lb->dir) + { + case BD_LEFT: + if (lb2->r.r_xbot > lb->r.r_xbot) + { + testlen = lb2->r.r_xbot - lb->r.r_xbot; + if (lb2->r.r_ybot < lb->r.r_ytop + testlen && + lb2->r.r_ytop > lb->r.r_ybot - testlen) + { + /* Adjustments for offset segments */ + if (lb2->r.r_ybot > lb->r.r_ytop) + testlen += lb2->r.r_ybot - lb->r.r_ytop; + else if (lb2->r.r_ytop < lb->r.r_ybot) + testlen += lb->r.r_ybot - lb2->r.r_ytop; + + if (testlen < loclength) loclength = testlen; + } + } + break; + case BD_RIGHT: + if (lb2->r.r_xtop < lb->r.r_xtop) + { + testlen = lb->r.r_xtop - lb2->r.r_xtop; + if (lb2->r.r_ybot < lb->r.r_ytop + testlen && + lb2->r.r_ytop > lb->r.r_ybot - testlen) + { + /* Adjustments for offset segments */ + if (lb2->r.r_ybot > lb->r.r_ytop) + testlen += lb2->r.r_ybot - lb->r.r_ytop; + else if (lb2->r.r_ytop < lb->r.r_ybot) + testlen += lb->r.r_ybot - lb2->r.r_ytop; + + if (testlen < loclength) loclength = testlen; + } + } + break; + case BD_TOP: + if (lb2->r.r_ytop < lb->r.r_ytop) + { + testlen = lb->r.r_ytop - lb2->r.r_ytop; + if (lb2->r.r_xbot < lb->r.r_xtop + testlen && + lb2->r.r_xtop > lb->r.r_xbot - testlen) + { + /* Adjustments for offset segments */ + if (lb2->r.r_xbot > lb->r.r_xtop) + testlen += lb2->r.r_xbot - lb->r.r_xtop; + else if (lb2->r.r_xtop < lb->r.r_xbot) + testlen += lb->r.r_xbot - lb2->r.r_xtop; + + if (testlen < loclength) loclength = testlen; + } + } + break; + case BD_BOTTOM: + if (lb2->r.r_ybot > lb->r.r_ybot) + { + testlen = lb2->r.r_ybot - lb->r.r_ybot; + if (lb2->r.r_xbot < lb->r.r_xtop + testlen && + lb2->r.r_xtop > lb->r.r_xbot - testlen) + { + /* Adjustments for offset segments */ + if (lb2->r.r_xbot > lb->r.r_xtop) + testlen += lb2->r.r_xbot - lb->r.r_xtop; + else if (lb2->r.r_xtop < lb->r.r_xbot) + testlen += lb->r.r_xbot - lb2->r.r_xtop; + + if (testlen < loclength) loclength = testlen; + } + } + break; + } + } + } + } + + /* This segment should not be considered current-carrying; it */ + /* only adds to the gate capacitance. Should we output the */ + /* extra capacitance somewhere? */ + + if (loclength == INFINITY) continue; + + /* Note that the L/W calculation ignores the possibility that a */ + /* transistor may have multiple lengths. Such cases should */ + /* either 1) scale the width to one of the lengths, or 2) out- */ + /* put a separate transistor record for each length. */ + + if (length == 0) + length = loclength; /* Default length */ + + else if ((length != 0) && (length != loclength)) + { + /* If the newly computed length is less than the */ + /* original, scale the original. Otherwise, scale */ + /* the new length. */ + + if (loclength < length) + { + width *= loclength; + width /= length; + length = loclength; + } + isComplex = TRUE; + } + + /* fprintf(stderr, " segment length = %d\n", loclength); */ + + /* Second pass: All segments at "length" distance add to the */ + /* length and width calculation. Sides opposite and corner */ + /* extensions are treated separately. Areas outside the corner */ + /* extension are ignored. */ + + locwidth = 0; + cornerw = 0; + for (i = 0; i < numregions; i++) + { + if ((i == p) && (numregions > 1)) continue; + for (lb2 = extSpecialBounds[i]; lb2 != NULL; lb2 = lb2->b_next) + { + if (lb2->dir == oppdir) + { + if (((lb->dir == BD_LEFT) && + (lb2->r.r_xbot - lb->r.r_xbot == loclength)) || + ((lb->dir == BD_RIGHT) && + (lb->r.r_xtop - lb2->r.r_xtop == loclength))) + { + /* opposite */ + segp = MIN(lb2->r.r_ytop, lb->r.r_ytop); + segn = MAX(lb2->r.r_ybot, lb->r.r_ybot); + testwid = segp - segn; + if (testwid > 0) locwidth += testwid * 2; + if (testwid <= -loclength) continue; + + /* corner extend top */ + segc = MAX(lb2->r.r_ytop, lb->r.r_ytop); + sege = MAX(segp, segn); + testwid = segc - sege; + if (testwid > loclength) testwid = loclength; + if (testwid > 0) cornerw += testwid; + + /* corner extend bottom */ + segc = MIN(lb2->r.r_ybot, lb->r.r_ybot); + sege = MIN(segp, segn); + testwid = sege - segc; + if (testwid > loclength) testwid = loclength; + if (testwid > 0) cornerw += testwid; + } + else if (((lb->dir == BD_TOP) && + (lb->r.r_ytop - lb2->r.r_ytop == loclength)) || + ((lb->dir == BD_BOTTOM) && + (lb2->r.r_ybot - lb->r.r_ybot == loclength))) + { + /* opposite */ + segp = MIN(lb2->r.r_xtop, lb->r.r_xtop); + segn = MAX(lb2->r.r_xbot, lb->r.r_xbot); + testwid = segp - segn; + if (testwid > 0) locwidth += testwid * 2; + if (testwid <= -loclength) continue; + + /* corner extend right */ + segc = MAX(lb2->r.r_xtop, lb->r.r_xtop); + sege = MAX(segp, segn); + testwid = segc - sege; + if (testwid > loclength) testwid = loclength; + if (testwid > 0) cornerw += testwid; + + /* corner extend left */ + segc = MIN(lb2->r.r_xbot, lb->r.r_xbot); + sege = MIN(segp, segn); + testwid = sege - segc; + if (testwid > loclength) testwid = loclength; + if (testwid > 0) cornerw += testwid; + } + } + } + } + /* if (width > 0) + fprintf(stderr, " segment width = %d\n", width); */ + + /* Width scaling for transistor sections with different lengths */ + locwidth += (int)(0.5 + ((float)cornerw * chop)); + if (loclength != length) + { + locwidth *= length; + locwidth /= loclength; + } + width += locwidth; + } + if ((length > 0) && (width > 0)) + { + *rlengthptr = length; + + // If numregions == 1 then everything was put in one record, + // and we have double-counted the width. + + if (numregions == 1) + *rwidthptr = (width >> 2); + else + *rwidthptr = (width >> 1); + + /* fprintf(stderr, "total L = %d, W = %d\n", length, width); */ + /* fflush(stderr); */ + + if (isComplex) + TxError("Device has multiple lengths: scaling" + " all widths to length %d\n", length); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extSeparateBounds -- + * + * Because the non-source/drain perimeter is not a node, all the + * boundary vectors end up in one record. So we have to pry them + * apart. + * + * Results: + * None. + * + * Side effects: + * Messes with the extSpecialBounds[] linked lists. + * + * ---------------------------------------------------------------------------- + */ + +void +extSeparateBounds(nterm) + int nterm; /* last terminal (# terminals - 1) */ +{ + Rect lbrect; + LinkedBoundary *lb, *lbstart, *lbend, *lblast, *lbnext; + bool found; + + /* Avoid crash condition on a badly-defined extract definition */ + if ((nterm < 0) || (extSpecialBounds[0] == NULL)) return; + + if (extSpecialBounds[nterm] == NULL) + { + /* Put first record into the unused terminal entry */ + extSpecialBounds[nterm] = extSpecialBounds[0]; + extSpecialBounds[0] = extSpecialBounds[nterm]->b_next; + extSpecialBounds[nterm]->b_next = NULL; + + /* Add connected segments until no more are found */ + lbstart = lbend = extSpecialBounds[nterm]; + lbrect = lbstart->r; + found = TRUE; + while (found == TRUE) + { + lblast = NULL; + found = FALSE; + for (lb = extSpecialBounds[0]; lb != NULL; lb = lbnext) + { + /* perhaps we should cut down on these cases by */ + /* checking the direction of the segment. . . */ + + lbnext = lb->b_next; + if (((lb->r.r_xbot == lbrect.r_xbot) && + (lb->r.r_ybot == lbrect.r_ybot))) + { + if (lblast == NULL) + extSpecialBounds[0] = lb->b_next; + else + lblast->b_next = lb->b_next; + // Insert lb after lbstart + lb->b_next = lbstart->b_next; + lbstart->b_next = lb; + lbstart = lb; + lbrect.r_xbot = lb->r.r_xtop; + lbrect.r_ybot = lb->r.r_ytop; + found = TRUE; + } + else if (((lb->r.r_xtop == lbrect.r_xbot) && + (lb->r.r_ytop == lbrect.r_ybot))) + { + if (lblast == NULL) + extSpecialBounds[0] = lb->b_next; + else + lblast->b_next = lb->b_next; + lb->b_next = lbstart->b_next; + lbstart->b_next = lb; + lbstart = lb; + lbrect.r_xbot = lb->r.r_xbot; + lbrect.r_ybot = lb->r.r_ybot; + found = TRUE; + } + else if (((lb->r.r_xtop == lbrect.r_xtop) && + (lb->r.r_ytop == lbrect.r_ytop))) + { + if (lblast == NULL) + extSpecialBounds[0] = lb->b_next; + else + lblast->b_next = lb->b_next; + lb->b_next = lbend->b_next; + lbend->b_next = lb; + lbend = lb; + lbrect.r_xtop = lb->r.r_xbot; + lbrect.r_ytop = lb->r.r_ybot; + found = TRUE; + } + else if (((lb->r.r_xbot == lbrect.r_xtop) && + (lb->r.r_ybot == lbrect.r_ytop))) + { + if (lblast == NULL) + extSpecialBounds[0] = lb->b_next; + else + lblast->b_next = lb->b_next; + lb->b_next = lbend->b_next; + lbend->b_next = lb; + lbend = lb; + lbrect.r_xtop = lb->r.r_xtop; + lbrect.r_ytop = lb->r.r_ytop; + found = TRUE; + } + else + lblast = lb; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extOutputParameters -- + * + * Scan through the TransRegion in the supplied list, and collect a mask of + * all transistor types used in the layout. Then for each transistor type, + * find if it belongs to a "subcircuit" (including "rsubcircuit" and + * "msubcircuit") definition. If it does, output a record containing the + * list of parameter names used by that subcircuit. + * + * Results: + * None. + * + * Side effects: + * Possibly writes to outFile. The purpose of this scan is not to have + * to write out shared parameter information for every individual device. + * ---------------------------------------------------------------------------- + */ + +void +extOutputParameters(def, transList, outFile) + CellDef *def; /* Cell being extracted */ + TransRegion *transList; /* Transistor regions built up in first pass */ + FILE *outFile; /* Output file */ +{ + ParamList *plist; + TransRegion *reg; + TileType t; + TileTypeBitMask tmask; + + TTMaskZero(&tmask); + + for (reg = transList; reg && !SigInterruptPending; reg = reg->treg_next) + { + TileType loctype = reg->treg_type; + + /* Watch for rare split reg->treg_type */ + if (loctype & TT_DIAGONAL) + loctype = (reg->treg_type & TT_SIDE) ? ((reg->treg_type & + TT_RIGHTMASK) >> 14) : (reg->treg_type & TT_LEFTMASK); + + TTMaskSetType(&tmask, loctype); + } + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + if (TTMaskHasType(&tmask, t)) + { + plist = ExtCurStyle->exts_deviceParams[t]; + if (plist != (ParamList *)NULL) + { + fprintf(outFile, "parameters %s", ExtCurStyle->exts_transName[t]); + for (; plist != NULL; plist = plist->pl_next) + { + if (plist->pl_param[1] != '\0') + { + if (plist->pl_scale != 1.0) + fprintf(outFile, " %c%c=%s*%g", + plist->pl_param[0], plist->pl_param[1], + plist->pl_name, plist->pl_scale); + else + fprintf(outFile, " %c%c=%s", plist->pl_param[0], + plist->pl_param[1], plist->pl_name); + } + else + { + if (plist->pl_scale != 1.0) + fprintf(outFile, " %c=%s*%g", + plist->pl_param[0], + plist->pl_name, plist->pl_scale); + else + fprintf(outFile, " %c=%s", plist->pl_param[0], + plist->pl_name); + } + } + fprintf(outFile, "\n"); + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extGetNativeResistClass() -- + * + * For the purpose of generating a node area and perimeter value to output + * to a subcircuit call as a passed parameter. The value output is assumed + * to refer only to the part of the whole eletrical node that is the + * actual device node, not to include connected metal, contacts, etc. + * Since area and perimeter information about a node is separated into + * resist classes, we need to figure out which resist class belongs to + * the device terminal type. + * + * "type" is the type identifier for the device (e.g., gate). "term" is + * the index of the terminal for the device. Devices with symmetrical + * terminals (e.g., MOSFETs), may have fewer type masks than terminals. + * + * ---------------------------------------------------------------------------- + */ + +int +extGetNativeResistClass(type, term) + TileType type; + int term; +{ + TileTypeBitMask *tmask, *rmask; + int i, n; + + tmask = NULL; + for (i = 0;; i++) + { + rmask = &ExtCurStyle->exts_transSDTypes[type][i]; + if (TTMaskIsZero(rmask)) break; + tmask = rmask; + if (i == term) break; + } + if (tmask == NULL) return -1; /* Error */ + + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + { + rmask = &ExtCurStyle->exts_typesByResistClass[n]; + if (TTMaskIntersect(rmask, tmask)) + return n; + } + return -1; /* Error */ +} + +/* + * ---------------------------------------------------------------------------- + * + * extOutputDevParams --- + * + * Write information to the output in the form of parameters + * representing pre-defined aspects of the device geometry + * that may be specified for any device. + * + * Results: + * None. + * + * Side effects: + * Writes non-terminated output to the file 'outFile'. + * + * ---------------------------------------------------------------------------- + */ + +void +extOutputDevParams(reg, t, outFile, length, width) + TransRegion *reg; + TileType t; + FILE *outFile; + int length; + int width; +{ + ParamList *chkParam; + + for (chkParam = ExtCurStyle->exts_deviceParams[t]; chkParam + != NULL; chkParam = chkParam->pl_next) + { + switch(tolower(chkParam->pl_param[0])) + { + case 'a': + if (chkParam->pl_param[1] == '\0' || + chkParam->pl_param[1] == '0') + fprintf(outFile, " %c=%d", chkParam->pl_param[0], + reg->treg_area); + break; + case 'p': + if (chkParam->pl_param[1] == '\0' || + chkParam->pl_param[1] == '0') + fprintf(outFile, " %c=%d", chkParam->pl_param[0], + extTransRec.tr_perim); + break; + case 'l': + fprintf(outFile, " %c=%d", chkParam->pl_param[0], + length); + break; + case 'w': + fprintf(outFile, " %c=%d", chkParam->pl_param[0], + width); + break; + case 'c': + fprintf(outFile, " %c=%g", chkParam->pl_param[0], + (ExtCurStyle->exts_transGateCap[t] + * reg->treg_area) + + (ExtCurStyle->exts_transSDCap[t] + * extTransRec.tr_perim)); + break; + case 's': + case 'x': + case 'y': + /* Do nothing; these values are standard output */ + break; + default: + fprintf(outFile, " %c=", chkParam->pl_param[0]); + break; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extOutputDevices -- + * + * For each TransRegion in the supplied list, corresponding to a single + * transistor in the layout, compute and output: + * - Its type + * - Its area and perimeter OR length and width OR capacitance OR resistance + * - Its substrate node + * - For each of the gate, and the various diff terminals (eg, + * source, drain): + * Node to which the terminal connects + * Length of the terminal + * Attributes (comma-separated), or 0 if none. + * + * The tiles in 'def' don't point back to the TransRegions in this list, + * but rather to the NodeRegions corresponding to their electrical nodes. + * + * Results: + * None. + * + * Side effects: + * Writes a number of 'fet' records to the file 'outFile'. + * + * Interruptible. If SigInterruptPending is detected, we stop traversing + * the transistor list and return. + * + * ---------------------------------------------------------------------------- + */ + +void +extOutputDevices(def, transList, outFile) + CellDef *def; /* Cell being extracted */ + TransRegion *transList; /* Transistor regions built up in first pass */ + FILE *outFile; /* Output file */ +{ + NodeRegion *node, *subsNode; + TransRegion *reg; + char *subsName; + FindRegion arg; + LabelList *ll; + TileType t; + int nsd, length, width, n, i, ntiles, corners, tn, rc; + double dres, dcap; + char mesg[256]; + bool isAnnular, hasModel; + + for (reg = transList; reg && !SigInterruptPending; reg = reg->treg_next) + { + /* + * Visit all of the tiles in the transistor region, updating + * extTransRec.tr_termnode[] and extTransRec.tr_termlen[], + * and the attribute lists for this transistor. + * + * Algorithm: first visit all tiles in the transistor, marking + * them with 'reg', then visit them again re-marking them with + * the gate node (extGetRegion(reg->treg_tile)). + */ + extTransRec.tr_nterm = 0; + extTransRec.tr_gatelen = 0; + extTransRec.tr_perim = 0; + extTransRec.tr_subsnode = (NodeRegion *)NULL; + + arg.fra_def = def; + arg.fra_connectsTo = ExtCurStyle->exts_transConn; + + extTransRec.tr_gatenode = (NodeRegion *) extGetRegion(reg->treg_tile); + t = reg->treg_type; + + /* Watch for rare split reg->treg_type */ + if (t & TT_DIAGONAL) + t = (reg->treg_type & TT_SIDE) ? ((reg->treg_type & + TT_RIGHTMASK) >> 14) : (reg->treg_type & TT_LEFTMASK); + + arg.fra_pNum = DBPlane(t); + + /* Set all terminals to NULL to guard against */ + /* asymmetric devices missing a terminal. */ + /* 5/30/09---but, reinitialize the array out to MAXSD, */ + /* or devices declaring minterms < maxterms screw up! */ + + nsd = ExtCurStyle->exts_transSDCount[t]; + for (i = 0; i < MAXSD; i++) extTransRec.tr_termnode[i] = NULL; + + /* Mark with reg and process each perimeter segment */ + arg.fra_uninit = (ClientData) extTransRec.tr_gatenode; + arg.fra_region = (Region *) reg; + arg.fra_each = extTransTileFunc; + ntiles = ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + + /* Re-mark with extTransRec.tr_gatenode */ + arg.fra_uninit = (ClientData) reg; + arg.fra_region = (Region *) extTransRec.tr_gatenode; + arg.fra_each = (int (*)()) NULL; + (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + + /* Are the terminal types on a compeletely different */ + /* plane than the top type? If so, do an area search */ + /* on that plane in the area under the device node. */ + + /* Devices may define one terminal per plane, but this */ + /* method cannot handle several different layer types */ + /* on one plane under the device identifier layer */ + /* acting as separate device nodes. If any terminal */ + /* search fails, give up and proceed with the reduced */ + /* number of terminals. */ + + while (extTransRec.tr_nterm < nsd) + { + TileTypeBitMask *tmask; + + tmask = &ExtCurStyle->exts_transSDTypes[t][extTransRec.tr_nterm]; + if (TTMaskIsZero(tmask)) break; + if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum])) + { + node = NULL; + extTransFindSubs(reg->treg_tile, t, tmask, def, &node); + if (node == NULL) break; + extTransRec.tr_termnode[extTransRec.tr_nterm++] = node; + } + else if (TTMaskHasType(tmask, TT_SPACE)) { + /* Device node is specified as being the substrate */ + if (glob_subsnode == NULL) break; + extTransRec.tr_termnode[extTransRec.tr_nterm++] = glob_subsnode; + } + else break; + } + + /* + * For types that require a minimum number of terminals, + * check to make sure that they all exist. If they don't, + * issue a warning message and make believe the missing + * terminals are the same as the last terminal we do have. + */ + if (extTransRec.tr_nterm < nsd) + { + int missing = nsd - extTransRec.tr_nterm; + + (void) sprintf(mesg, "device missing %d terminal%s", missing, + missing == 1 ? "" : "s"); + if (extTransRec.tr_nterm > 0) + { + node = extTransRec.tr_termnode[extTransRec.tr_nterm - 1]; + (void) strcat(mesg, ";\n connecting remainder to node "); + (void) strcat(mesg, extNodeName((LabRegion *) node)); + while (extTransRec.tr_nterm < nsd) + { + extTransRec.tr_termlen[extTransRec.tr_nterm] = 0; + extTransRec.tr_termnode[extTransRec.tr_nterm++] = node; + } + } + if (ExtDoWarn & EXTWARN_FETS) + extTransBad(def, reg->treg_tile, mesg); + } + else if (extTransRec.tr_nterm > nsd) + { + /* It is not an error condition to have more terminals */ + /* than the minimum. */ + } + + /* + * Output the transistor record. + * The type is ExtCurStyle->exts_transName[t], which should have + * some meaning to the simulator we are producing this file for. + * Use the default substrate node unless the transistor overlaps + * material whose type is in exts_transSubstrateTypes, in which + * case we use the node of the overlapped material. + * + * Technology files using the "substrate" keyword (magic-8.1 or + * newer) should have the text "error" in the substrate node + * name. + */ + subsName = ExtCurStyle->exts_transSubstrateName[t]; + if (!TTMaskIsZero(&ExtCurStyle->exts_transSubstrateTypes[t]) + && (subsNode = extTransRec.tr_subsnode)) + { + subsName = extNodeName(subsNode); + } + +#ifdef MAGIC_WRAPPER + + // Substrate variable substitution when in backwards-compatibility + // substrate mode. + + else if ((ExtCurStyle->exts_globSubstratePlane == -1) && + (subsName && subsName[0] == '$' && subsName[1] != '$')) + { + // If subsName is a Tcl variable (begins with "$"), make the + // variable substitution, if one exists. Ignore double-$. + + char *varsub = (char *)Tcl_GetVar(magicinterp, &subsName[1], + TCL_GLOBAL_ONLY); + if (varsub != NULL) subsName = varsub; + } +#endif + + /* Original-style FET record backward compatibility */ + if (ExtCurStyle->exts_deviceClass[t] != DEV_FET) + fprintf(outFile, "device "); + + fprintf(outFile, "%s %s", + extDevTable[ExtCurStyle->exts_deviceClass[t]], + ExtCurStyle->exts_transName[t]); + + fprintf(outFile, " %d %d %d %d", + reg->treg_ll.p_x, reg->treg_ll.p_y, + reg->treg_ll.p_x + 1, reg->treg_ll.p_y + 1); + + /* NOTE: The following code makes unreasonable simplifying */ + /* assumptions about how to calculate device length and width. */ + /* However, it is the same as was always used by ext2sim and */ + /* ext2spice. By putting it here, where all the tile */ + /* information exists, it is at least theoretically possible to */ + /* write better routines that can deal with bends in resistors */ + /* and transistors, annular devices, multiple-drain devices, */ + /* etc., etc. */ + /* Tim, 2/20/03 */ + + switch (ExtCurStyle->exts_deviceClass[t]) + { + case DEV_FET: /* old style, perimeter & area */ + fprintf(outFile, " %d %d \"%s\"", + reg->treg_area, extTransRec.tr_perim, + (subsName == NULL) ? "None" : subsName); + break; + + /* "device " types, calculation of length & width */ + + case DEV_MOSFET: + case DEV_BJT: + case DEV_SUBCKT: + case DEV_MSUBCKT: + case DEV_ASYMMETRIC: + length = extTransRec.tr_gatelen / 2; /* (default) */ + width = 0; + isAnnular = FALSE; + + /* Note that width is accumulated on one tr_termlen */ + /* record when nodes are merged, so proper behavior */ + /* for transistors w/connected S-D is to count over */ + /* non-NULL termnodes, not non-zero termlens. */ + + for (n = 0; n < extTransRec.tr_nterm; n++) + { + if (extTransRec.tr_termnode[n] == NULL) continue; + + width += extTransRec.tr_termlen[n]; + + /* Mark annular transistors as requiring extra processing */ + if (extTransRec.tr_termvector[n].p_x == 0 && + extTransRec.tr_termvector[n].p_y == 0) + isAnnular = TRUE; + } + if (n) width /= n; + + /*------------------------------------------------------*/ + /* Note that the tr_termvector says a lot about the */ + /* device geometry. If the sum of x and y for any */ + /* vector is 0, then the terminal is enclosed (annular */ + /* device). If the sum of x and y for all vectors is */ + /* zero, then we have a normal rectangular device. But */ + /* if the sum of all x and y is nonzero, then the */ + /* device length changes along the device (including */ + /* bends). This is a trigger to do a more extensive */ + /* boundary search to find the exact dimensions of the */ + /* device. */ + /*------------------------------------------------------*/ + + if (n == 0) + { + /* Don't issue a warning on devices such as a */ + /* vertical diode that may declare zero terminals */ + /* because the substrate node (i.e., well) is the */ + /* other terminal. */ + + if (ExtDoWarn && (ExtCurStyle->exts_transSDCount[t] > 0)) + extTransBad(def, reg->treg_tile, + "Could not determine device boundary"); + length = width = 0; + } + else + { + LinkedBoundary *lb; + + extSpecialBounds = (LinkedBoundary **)mallocMagic(n * + sizeof(LinkedBoundary *)); + + for (i = 0; i < n; i++) extSpecialBounds[i] = NULL; + + /* Mark with reg and process each perimeter segment */ + + arg.fra_uninit = (ClientData) extTransRec.tr_gatenode; + arg.fra_region = (Region *) reg; + arg.fra_each = extAnnularTileFunc; + (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + + extSeparateBounds(n - 1); /* Handle MOScaps (if necessary) */ + extComputeEffectiveLW(&length, &width, n, + ExtCurStyle->exts_cornerChop[t]); + + /* Free the lists */ + + for (i = 0; i < n; i++) + for (lb = extSpecialBounds[i]; lb != NULL; lb = lb->b_next) + freeMagic((char *)lb); + freeMagic((char *)extSpecialBounds); + + /* Put the region list back the way we found it: */ + /* Re-mark with extTransRec.tr_gatenode */ + + arg.fra_uninit = (ClientData) reg; + arg.fra_region = (Region *) extTransRec.tr_gatenode; + arg.fra_each = (int (*)()) NULL; + (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + + } + + if (ExtCurStyle->exts_deviceClass[t] == DEV_MOSFET || + ExtCurStyle->exts_deviceClass[t] == DEV_ASYMMETRIC || + ExtCurStyle->exts_deviceClass[t] == DEV_BJT) + { + fprintf(outFile, " %d %d", length, width); + } + + extOutputDevParams(reg, t, outFile, length, width); + + fprintf(outFile, " \"%s\"", (subsName == NULL) ? + "None" : subsName); + break; + + case DEV_DIODE: /* Only handle the optional substrate node */ + case DEV_NDIODE: + case DEV_PDIODE: + extOutputDevParams(reg, t, outFile, length, width); + if (subsName != NULL) + fprintf(outFile, " \"%s\"", subsName); + break; + + case DEV_RES: + case DEV_RSUBCKT: + hasModel = strcmp(ExtCurStyle->exts_transName[t], "None"); + length = extTransRec.tr_perim; + isAnnular = FALSE; + + /* Boundary perimeter scan for resistors with more than */ + /* one tile. */ + + for (n = 0; n < extTransRec.tr_nterm; n++) + { + if (extTransRec.tr_termnode[n] == NULL) continue; + + /* Mark annular resistors as requiring extra processing */ + if (extTransRec.tr_termvector[n].p_x == 0 && + extTransRec.tr_termvector[n].p_y == 0) + isAnnular = TRUE; + } + + if (n == 0) + width = length = 0; + else if (ntiles > 1) + { + LinkedBoundary *lb; + + extSpecialBounds = (LinkedBoundary **)mallocMagic(n * + sizeof(LinkedBoundary *)); + + for (i = 0; i < n; i++) extSpecialBounds[i] = NULL; + + /* Mark with reg and process each perimeter segment */ + + arg.fra_uninit = (ClientData) extTransRec.tr_gatenode; + arg.fra_region = (Region *) reg; + if (isAnnular) + arg.fra_each = extAnnularTileFunc; + else + arg.fra_each = extResistorTileFunc; + (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + + if (extSpecialBounds[0] != NULL) + { + extSeparateBounds(n - 1); + if (isAnnular) + extComputeEffectiveLW(&length, &width, n, + ExtCurStyle->exts_cornerChop[t]); + else + extComputeEffectiveLW(&width, &length, n, + ExtCurStyle->exts_cornerChop[t]); + } + else + { + if (ExtDoWarn) + extTransBad(def, reg->treg_tile, + "Could not determine resistor boundary"); + length = width = 0; + } + + /* Free the lists */ + + for (i = 0; i < n; i++) + for (lb = extSpecialBounds[i]; lb != NULL; lb = lb->b_next) + freeMagic((char *)lb); + freeMagic((char *)extSpecialBounds); + + /* Put the region list back the way we found it: */ + /* Re-mark with extTransRec.tr_gatenode */ + + arg.fra_uninit = (ClientData) reg; + arg.fra_region = (Region *) extTransRec.tr_gatenode; + arg.fra_each = (int (*)()) NULL; + (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + } + else + { + /* Single tile resistor means a simple L,W */ + /* calculation from perimeter & area. */ + + width = 0; + for (n = 0; extTransRec.tr_termlen[n] != 0; n++) + { + width += extTransRec.tr_termlen[n]; + length -= extTransRec.tr_termlen[n]; + } + width >>= 1; + length >>= 1; + } + if (width) + { + dres = ExtCurStyle->exts_sheetResist[t] * (double)length / + (double)width; + if (ExtDoWarn && (n > 2)) + { + if (hasModel) + sprintf(mesg, "Resistor has %d terminals: " + "extracted L/W will be wrong", n); + else + sprintf(mesg, "Resistor has %d terminals: " + "extracted value will be wrong", n); + extTransBad(def, reg->treg_tile, mesg); + } + } + else { + dres = 0.0; + if (ExtDoWarn) + extTransBad(def, reg->treg_tile, + "Resistor has zero width"); + } + + extOutputDevParams(reg, t, outFile, length, width); + + if (ExtCurStyle->exts_deviceClass[t] == DEV_RSUBCKT) + { + fprintf(outFile, " \"%s\"", (subsName == NULL) ? + "None" : subsName); + } + else if (hasModel) /* SPICE semiconductor resistor */ + { + fprintf(outFile, " %d %d", length, width); + if (subsName != NULL) + fprintf(outFile, " \"%s\"", subsName); + } + else /* regular resistor */ + fprintf(outFile, " %g", dres / 1000.0); /* mOhms -> Ohms */ + break; + + case DEV_CAP: + case DEV_CAPREV: + hasModel = strcmp(ExtCurStyle->exts_transName[t], "None"); + if (hasModel) + { + for (n = 0; n < extTransRec.tr_nterm && + extTransRec.tr_termnode[n] != NULL; n++); + + /* Don't know what to do (yet) with capacitors */ + /* multiple terminals (see below); treat them in */ + /* the original naive manner. */ + + if (n == 0) + { + width = 0; + extTransBad(def, reg->treg_tile, + "Capacitor has zero size"); + fprintf(outFile, " 0 0"); + } + else + { + /* Special handling of multiple-tile areas. */ + /* This algorithm assumes that the capacitor */ + /* has one terminal and that the area is a */ + /* rectangle. It should be extended to output */ + /* multiple capacitors for multiple rectangular */ + /* areas, combining to form any arbitrary shape */ + + LinkedBoundary *lb; + + extSpecialBounds = (LinkedBoundary **)mallocMagic(n * + sizeof(LinkedBoundary *)); + + for (i = 0; i < n; i++) extSpecialBounds[i] = NULL; + + /* Mark with reg and process each perimeter segment */ + + arg.fra_uninit = (ClientData) extTransRec.tr_gatenode; + arg.fra_region = (Region *) reg; + arg.fra_each = extAnnularTileFunc; + (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + + extComputeCapLW(&length, &width); + if ((length * width) > reg->treg_area) + { + if (ExtDoWarn) + extTransBad(def, reg->treg_tile, "L,W estimated " + "for non-rectangular capacitor."); + fprintf(outFile, " %d %d", width, + reg->treg_area / width); + } + else + fprintf(outFile, " %d %d", length, width); + + /* Free the lists */ + + for (i = 0; i < n; i++) + for (lb = extSpecialBounds[i]; lb != NULL; lb = lb->b_next) + freeMagic((char *)lb); + freeMagic((char *)extSpecialBounds); + + /* Put the region list back the way we found it: */ + /* Re-mark with extTransRec.tr_gatenode */ + + arg.fra_uninit = (ClientData) reg; + arg.fra_region = (Region *) extTransRec.tr_gatenode; + arg.fra_each = (int (*)()) NULL; + (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + } + extOutputDevParams(reg, t, outFile, length, width); + if (subsName != NULL) + fprintf(outFile, " \"%s\"", subsName); + } + else + { + dcap = (ExtCurStyle->exts_transGateCap[t] * reg->treg_area) + + (ExtCurStyle->exts_transSDCap[t] * extTransRec.tr_perim); + + fprintf(outFile, " %g", dcap / 1000.0); /* aF -> fF */ + } + break; + } + + /* gate */ + node = (NodeRegion *) extGetRegion(reg->treg_tile); + ll = node->nreg_labels; + extTransOutTerminal((LabRegion *) node, ll, LL_GATEATTR, + extTransRec.tr_gatelen, outFile); + + /* Sort source and drain terminals by position, unless the */ + /* device is asymmetric, in which case source and drain do not */ + /* permute, and the terminal order is fixed. */ + + if (TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[t][1])) + ExtSortTerminals(&extTransRec, ll); + + /* each non-gate terminal */ + for (nsd = 0; nsd < extTransRec.tr_nterm; nsd++) + extTransOutTerminal((LabRegion *) extTransRec.tr_termnode[nsd], ll, + nsd, extTransRec.tr_termlen[nsd], outFile); + + (void) fputs("\n", outFile); + } +} + +int +extTransFindSubs(tile, t, mask, def, sn) + Tile *tile; + TileType t; + TileTypeBitMask *mask; + CellDef *def; + NodeRegion **sn; +{ + Rect tileArea; + int pNum; + int extTransFindSubsFunc1(); /* Forward declaration */ + + TiToRect(tile, &tileArea); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + if (TTMaskIntersect(&DBPlaneTypes[pNum], mask)) + { + if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &tileArea, + mask, extTransFindSubsFunc1, (ClientData)sn)) + return 1; + } + } + return 0; +} + +int +extTransFindSubsFunc1(tile, sn) + Tile *tile; + NodeRegion **sn; +{ + /* Report split substrate region errors (two different substrate + * regions under the same device) + */ + + if (tile->ti_client != (ClientData) extUnInit) + { + if ((*sn != (NodeRegion *)NULL) && (*sn != tile->ti_client)) + TxError("Warning: Split substrate under device at (%d %d)\n", + tile->ti_ll.p_x, tile->ti_ll.p_y); + + *sn = (NodeRegion *) tile->ti_client; + return 1; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * extTransTileFunc -- + * + * Filter function called by ExtFindNeighbors for each tile in a + * transistor. Responsible for collecting the nodes, lengths, + * and attributes of all the terminals on this transistor. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Fills in the transRec structure extTransRec. + * + * ---------------------------------------------------------------------------- + */ + +int +extTransTileFunc(tile, pNum, arg) + Tile *tile; + int pNum; + FindRegion *arg; +{ + TileTypeBitMask mask; + TileType loctype; + int perim; + bool allow_globsubsnode; + + LabelList *ll; + Label *lab; + Rect r; + + for (ll = extTransRec.tr_gatenode->nreg_labels; ll; ll = ll->ll_next) + { + /* Skip if already marked */ + if (ll->ll_attr != LL_NOATTR) continue; + lab = ll->ll_label; + TITORECT(tile, &r); + if (GEO_TOUCH(&r, &lab->lab_rect) && + extLabType(lab->lab_text, LABTYPE_GATEATTR)) + { + ll->ll_attr = LL_GATEATTR; + } + } + /* + * Visit each segment of the perimeter of this tile that + * that borders on something of a different type. + */ + if (IsSplit(tile)) + { + loctype = (SplitSide(tile)) ? SplitRightType(tile): SplitLeftType(tile); + // return (0); /* Hack alert! We must properly handle diagonals! */ + } + else + loctype = TiGetTypeExact(tile); + + mask = ExtCurStyle->exts_transConn[loctype]; + TTMaskCom(&mask); + + /* NOTE: DO NOT USE extTransRec.tr_perim += extEnumTilePerim(...) */ + /* The AMD target gcc compile works and the Intel target gcc */ + /* compile doesn't! The following code works the same on both. */ + + perim = extEnumTilePerim(tile, mask, pNum, + extTransPerimFunc, (ClientData)NULL); + extTransRec.tr_perim += perim; + + allow_globsubsnode = FALSE; + if (extTransRec.tr_subsnode == (NodeRegion *)NULL) + { + TileTypeBitMask *smask; + + smask = &ExtCurStyle->exts_transSubstrateTypes[loctype]; + if (TTMaskHasType(smask, TT_SPACE)) + { + allow_globsubsnode = TRUE; + TTMaskClearType(smask, TT_SPACE); + } + extTransFindSubs(tile, loctype, smask, arg->fra_def, &extTransRec.tr_subsnode); + if (allow_globsubsnode) + TTMaskSetType(smask, TT_SPACE); + } + + /* If the transistor does not connect to a defined node, and + * the substrate types include "space", then it is assumed to + * connect to the global substrate. + */ + + if (extTransRec.tr_subsnode == (NodeRegion *)NULL) + if (allow_globsubsnode) + extTransRec.tr_subsnode = glob_subsnode; + + return (0); +} + +int +extTransPerimFunc(bp) + Boundary *bp; +{ + TileType tinside, toutside; + Tile *tile; + NodeRegion *diffNode = (NodeRegion *) extGetRegion(bp->b_outside); + int i, len = BoundaryLength(bp); + int thisterm; + LabelList *ll; + Label *lab; + Rect r; + bool SDterm = FALSE; + + tile = bp->b_inside; + if (IsSplit(tile)) + tinside = (SplitSide(tile)) ? SplitRightType(tile): SplitLeftType(tile); + else + tinside = TiGetTypeExact(bp->b_inside); + tile = bp->b_outside; + if (IsSplit(tile)) + toutside = (SplitSide(tile)) ? SplitRightType(tile): SplitLeftType(tile); + else + toutside = TiGetTypeExact(bp->b_outside); + + for (i = 0; !TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[tinside][i]); i++) + { + /* TT_SPACE is allowed, for declaring that a device terminal is */ + /* the substrate. However, it should not be in the plane of */ + /* the device identifier layer, so space tiles should never be */ + /* flagged during a device perimeter search. */ + + if (toutside == TT_SPACE) break; + + if (TTMaskHasType(&ExtCurStyle->exts_transSDTypes[tinside][i], toutside)) + { + /* + * It's a diffusion terminal (source or drain). See if the node is + * already in our table; add it if it wasn't already there. + * Asymmetric devices must have terminals in order. + */ + if (TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[tinside][1])) + { + for (thisterm = 0; thisterm < extTransRec.tr_nterm; thisterm++) + if (extTransRec.tr_termnode[thisterm] == diffNode) + break; + } + else + thisterm = i; + + if (extTransRec.tr_termnode[thisterm] == NULL) + { + extTransRec.tr_nterm++; + extTransRec.tr_termnode[thisterm] = diffNode; + extTransRec.tr_termlen[thisterm] = 0; + extTransRec.tr_termvector[thisterm].p_x = 0; + extTransRec.tr_termvector[thisterm].p_y = 0; + extTransRec.tr_termpos[thisterm].pnum = DBPlane(toutside); + extTransRec.tr_termpos[thisterm].pt = bp->b_outside->ti_ll; + + /* Find the total area of this terminal */ + } + else if (extTransRec.tr_termnode[thisterm] == diffNode) + { + TermTilePos *pos = &(extTransRec.tr_termpos[thisterm]); + Tile *otile = bp->b_outside; + + /* update the region tile position */ + + if( DBPlane(TiGetType(otile)) < pos->pnum ) + { + pos->pnum = DBPlane(TiGetType(otile)); + pos->pt = otile->ti_ll; + } + else if( DBPlane(TiGetType(otile)) == pos->pnum ) + { + if( LEFT(otile) < pos->pt.p_x ) + pos->pt = otile->ti_ll; + else if( LEFT(otile) == pos->pt.p_x && + BOTTOM(otile) < pos->pt.p_y ) + pos->pt.p_y = BOTTOM(otile); + } + } + else + { + TxError("Error: Asymmetric device with multiple terminals!\n"); + } + + /* Add the length to this terminal's perimeter */ + extTransRec.tr_termlen[thisterm] += len; + + /* Update the boundary traversal vector */ + switch(bp->b_direction) { + case BD_LEFT: + extTransRec.tr_termvector[thisterm].p_y += len; + break; + case BD_TOP: + extTransRec.tr_termvector[thisterm].p_x += len; + break; + case BD_RIGHT: + extTransRec.tr_termvector[thisterm].p_y -= len; + break; + case BD_BOTTOM: + extTransRec.tr_termvector[thisterm].p_x -= len; + break; + } + + /* + * Mark this attribute as belonging to this transistor + * if it is either: + * (1) a terminal attribute whose LL corner touches bp->b_segment, + * or (2) a gate attribute that lies inside bp->b_inside. + */ + for (ll = extTransRec.tr_gatenode->nreg_labels; ll; ll = ll->ll_next) + { + /* Skip if already marked */ + if (ll->ll_attr != LL_NOATTR) + continue; + lab = ll->ll_label; + if (GEO_ENCLOSE(&lab->lab_rect.r_ll, &bp->b_segment) + && extLabType(lab->lab_text, LABTYPE_TERMATTR)) + { + ll->ll_attr = thisterm; + } + } + SDterm = TRUE; + break; + } + } + + if (!SDterm && extConnectsTo(tinside, toutside, ExtCurStyle->exts_nodeConn)) + { + /* Not in a terminal, but are in something that connects to gate */ + extTransRec.tr_gatelen += len; + } + + /* + * Total perimeter (separate from terminals, for dcaps + * that might not be surrounded by terminals on all sides). + */ + + /* Don't double-count contact perimeters (added by Tim 1/9/07) */ + if ((!DBIsContact(toutside) && !DBIsContact(tinside)) || + (bp->b_plane == extTransRec.tr_gatenode->nreg_pnum)) + extTransRec.tr_perim += len; + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extAnnularTileFunc -- + * + * Filter function called by ExtFindNeighbors for each tile in a + * transistor. Responsible for doing an extensive boundary + * survey to determine the length of the transistor. + * This is basically a subset of the code in extTransTileFunc() + * but passes a different function to extEnumTilePerim(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * + * ---------------------------------------------------------------------------- + */ + +int +extAnnularTileFunc(tile, pNum) + Tile *tile; + int pNum; +{ + TileTypeBitMask mask; + TileType loctype; + + /* + * Visit each segment of the perimeter of this tile that + * that borders on something of a different type. + */ + if (IsSplit(tile)) + { + loctype = (SplitSide(tile)) ? SplitRightType(tile): SplitLeftType(tile); + } + else + loctype = TiGetTypeExact(tile); + + mask = ExtCurStyle->exts_transConn[loctype]; + TTMaskCom(&mask); + extEnumTilePerim(tile, mask, pNum, extSpecialPerimFunc, (ClientData) TRUE); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extResistorTileFunc -- + * + * Filter function called by ExtFindNeighbors for each tile in a + * resistor. This is very similar to the extAnnularTileFunc + * above, but it looks a boundaries with non-source/drain types + * rather than the source/drain boundaries themselves. This is + * correct for tracing the detailed perimeter of a device where + * L > W. + * + * Ideally, one wants to call both of these functions to check + * both the case of L > W and the case W > L, assuming that both + * are legal resistor layouts. + * + * Results: + * Returns 0 always. + * + * Side effects: + * + * ---------------------------------------------------------------------------- + */ + +int +extResistorTileFunc(tile, pNum) + Tile *tile; + int pNum; +{ + TileTypeBitMask mask; + TileType loctype; + + /* + * Visit each segment of the perimeter of this tile that + * that borders on something of a different type. + */ + if (IsSplit(tile)) + { + loctype = (SplitSide(tile)) ? SplitRightType(tile): SplitLeftType(tile); + } + else + loctype = TiGetTypeExact(tile); + + mask = ExtCurStyle->exts_transConn[loctype]; + TTMaskSetMask(&mask, &ExtCurStyle->exts_transSDTypes[loctype][0]); + TTMaskCom(&mask); + + extEnumTilePerim(tile, mask, pNum, extSpecialPerimFunc, (ClientData)FALSE); + + return (0); +} + +/*----------------------------------------------------------------------*/ +/* Detailed boundary survey for unusual transistor geometries (esp. */ +/* annular). If "sense" is TRUE, look at boundaries with source/drain */ +/* types. If "sense" is FALSE, looks at non-source/drain boundaries. */ +/*----------------------------------------------------------------------*/ + +int +extSpecialPerimFunc(bp, sense) + Boundary *bp; + bool sense; +{ + TileType tinside, toutside; + NodeRegion *diffNode = (NodeRegion *) extGetRegion(bp->b_outside); + int thisterm, extended, i; + LinkedBoundary *newBound, *lb, *lastlb; + bool needSurvey; + + /* Note that extEnumTilePerim() assumes for the non-Manhattan case */ + /* that non-Manhattan tiles should be incorporated into the device */ + /* gate for purposes of computing effective length and width. In */ + /* most cases this will be only a slight deviation from the true */ + /* result. */ + + switch (bp->b_direction) + { + case BD_TOP: + tinside = TiGetTopType(bp->b_inside); + toutside = TiGetBottomType(bp->b_outside); + break; + case BD_BOTTOM: + tinside = TiGetBottomType(bp->b_inside); + toutside = TiGetTopType(bp->b_outside); + break; + case BD_RIGHT: + tinside = TiGetRightType(bp->b_inside); + toutside = TiGetLeftType(bp->b_outside); + break; + case BD_LEFT: + tinside = TiGetLeftType(bp->b_inside); + toutside = TiGetRightType(bp->b_outside); + break; + } + + /* Check all terminal classes for a matching type */ + needSurvey = FALSE; + for (i = 0; !TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[tinside][i]); i++) + { + if (TTMaskHasType(&ExtCurStyle->exts_transSDTypes[tinside][i], toutside)) + { + needSurvey = TRUE; + break; + } + } + + if (!sense || needSurvey) + { + if (toutside == TT_SPACE) + if (glob_subsnode != NULL) + diffNode = glob_subsnode; + + /* + * Since we're repeating the search, all terminals should be there. + */ + if (!sense) + thisterm = 0; + else + { + for (thisterm = 0; thisterm < extTransRec.tr_nterm; thisterm++) + if (extTransRec.tr_termnode[thisterm] == diffNode) + break; + if (thisterm >= extTransRec.tr_nterm) + { + if (toutside == TT_SPACE) + TxError("Internal Error in Transistor Perimeter Boundary Search!\n"); + return 1; + } + } + + /* + * Check the existing segment list to see if this segment + * extends an existing segment. + */ + + extended = 0; + for (lb = extSpecialBounds[thisterm]; lb != NULL; lb = lb->b_next) + { + if (bp->b_direction == lb->dir) + { + switch(lb->dir) + { + case BD_LEFT: + case BD_RIGHT: + if (bp->b_segment.r_xbot == lb->r.r_xbot) + { + if (bp->b_segment.r_ybot == lb->r.r_ytop) + { + if (extended) + lastlb->r.r_ybot = lb->r.r_ybot; + else + lb->r.r_ytop = bp->b_segment.r_ytop; + extended++; + lastlb = lb; + } + else if (bp->b_segment.r_ytop == lb->r.r_ybot) + { + if (extended) + lastlb->r.r_ytop = lb->r.r_ytop; + else + lb->r.r_ybot = bp->b_segment.r_ybot; + extended++; + lastlb = lb; + } + } + break; + case BD_TOP: + case BD_BOTTOM: + if (bp->b_segment.r_ybot == lb->r.r_ybot) + { + if (bp->b_segment.r_xbot == lb->r.r_xtop) + { + if (extended) + lastlb->r.r_xbot = lb->r.r_xbot; + else + lb->r.r_xtop = bp->b_segment.r_xtop; + extended++; + lastlb = lb; + } + else if (bp->b_segment.r_xtop == lb->r.r_xbot) + { + if (extended) + lastlb->r.r_xtop = lb->r.r_xtop; + else + lb->r.r_xbot = bp->b_segment.r_xbot; + extended++; + lastlb = lb; + } + } + break; + } + } + if (extended == 2) + { + /* Connected two existing entries---need to remove lastlb, */ + /* which is now a redundant segment. */ + + if (lastlb == extSpecialBounds[thisterm]) + extSpecialBounds[thisterm] = lastlb->b_next; + else + { + for (lb = extSpecialBounds[thisterm]; lb != NULL; + lb = lb->b_next) + { + if (lastlb == lb->b_next) + { + lb->b_next = lastlb->b_next; + break; + } + } + } + freeMagic((char *)lastlb); + + /* New segment cannot extend more than two existing segments */ + break; + } + } + + if (!extended) + { + newBound = (LinkedBoundary *)mallocMagic(sizeof(LinkedBoundary)); + newBound->r = bp->b_segment; + newBound->dir = bp->b_direction; + newBound->b_next = extSpecialBounds[thisterm]; + extSpecialBounds[thisterm] = newBound; + } + } + return (0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * extTransOutTerminal -- + * + * Output the information associated with one terminal of a + * transistor. This consists of three things: + * - the name of the node to which the terminal is connected + * - the length of the terminal along the perimeter of the transistor + * - a list of attributes pertinent to this terminal. + * + * If 'whichTerm' is LL_GATEATTR, this is the gate; otherwise, it is one + * of the diffusion terminals. + * + * Results: + * None. + * + * Side effects: + * Writes the above information to 'outFile'. + * Resets ll_attr for each attribute we output to LL_NOATTR. + * + * ---------------------------------------------------------------------------- + */ + +void +extTransOutTerminal(lreg, ll, whichTerm, len, outFile) + LabRegion *lreg; /* Node connected to terminal */ + LabelList *ll; /* Gate's label list */ + int whichTerm; /* Which terminal we are processing. The gate + * is indicated by LL_GATEATTR. + */ + int len; /* Length of perimeter along terminal */ + FILE *outFile; /* Output file */ +{ + char *cp; + int n; + char fmt; + + + fprintf(outFile, " \"%s\" %d", extNodeName(lreg), len); + for (fmt = ' '; ll; ll = ll->ll_next) + if (ll->ll_attr == whichTerm) + { + fprintf(outFile, "%c\"", fmt); + cp = ll->ll_label->lab_text; + n = strlen(cp) - 1; + while (n-- > 0) + putc(*cp++, outFile); + ll->ll_attr = LL_NOATTR; + fprintf(outFile, "\""); + fmt = ','; + } + + if (fmt == ' ') + fprintf(outFile, " 0"); +} + +/* + * ---------------------------------------------------------------------------- + * + * extTransBad -- + * + * For a transistor where an error was encountered, give feedback + * as to the location of the error. + * + * Results: + * None. + * + * Side effects: + * Complains to the user. + * + * ---------------------------------------------------------------------------- + */ + +void +extTransBad(def, tp, mesg) + CellDef *def; + Tile *tp; + char *mesg; +{ + Rect r; + + if (!DebugIsSet(extDebugID, extDebNoFeedback)) + { + TiToRect(tp, &r); + DBWFeedbackAdd(&r, mesg, def, 1, STYLE_PALEHIGHLIGHTS); + } + extNumWarnings++; +} + +/* + * ---------------------------------------------------------------------------- + * + * extLabType -- + * + * Check to see whether the text passed as an argument satisfies + * any of the label types in 'typeMask'. + * + * Results: + * TRUE if the text is of one of the label types in 'typeMask', + * FALSE if not. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +extLabType(text, typeMask) + char *text; + int typeMask; +{ + if (*text == '\0') + return (FALSE); + + while (*text) text++; + switch (*--text) + { + case '@': /* Node attribute */ + return ((bool)(typeMask & LABTYPE_NODEATTR)); + case '$': /* Terminal (source/drain) attribute */ + return ((bool)(typeMask & LABTYPE_TERMATTR)); + case '^': /* Gate attribute */ + return ((bool)(typeMask & LABTYPE_GATEATTR)); + default: + return ((bool)(typeMask & LABTYPE_NAME)); + } + /*NOTREACHED*/ +} + + +/* + * ---------------------------------------------------------------------------- + * extNodeToTile -- + * + * Sets tp to be the tile containing the lower-leftmost point of the + * NodeRegion *np, but in the tile planes of the ExtTree *et instead + * of the tile planes originally containing *np. This routine used + * to be defined as the macro NODETOTILE(). + * + * Results: + * Returns a pointer to the tile + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +Tile *extNodeToTile(np, et) + NodeRegion *np; + ExtTree *et; +{ + Tile *tp; + Plane *myplane; + + myplane = et->et_use->cu_def->cd_planes[np->nreg_pnum]; + + tp = myplane->pl_hint; + GOTOPOINT(tp, &np->nreg_ll); + myplane->pl_hint = tp; + + if (IsSplit(tp)) + { + TileType tpt = TiGetTypeExact(tp); + if ((tpt & TT_LEFTMASK) == (np->nreg_type & TT_LEFTMASK)) + TiSetBody(tp, tpt & ~TT_SIDE); + else + TiSetBody(tp, tpt | TT_SIDE); + } + + return tp; +} + +/* + * ---------------------------------------------------------------------------- + * + * extSetNodeNum -- + * + * Update reg->lreg_ll and reg->lreg_pnum so that they are always the + * lowest leftmost coordinate in a cell, on the plane with the lowest + * number (formerly a macro in extractInt.h). + * + * (10/1/05: Changed from a macro to a subroutine and modified for + * handling non-Manhattan geometry) + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +extSetNodeNum(reg, plane, tile) + LabRegion *reg; + int plane; + Tile *tile; +{ + TileType type; + + if (IsSplit(tile)) + { + /* Only consider split tiles if the lower-left-hand corner */ + /* is only the type under consideration. */ + + if (!SplitSide(tile) && SplitDirection(tile)) + type = SplitSide(tile) ? SplitRightType(tile) : SplitLeftType(tile); + else if (reg->lreg_pnum == DBNumPlanes) + type = TiGetTypeExact(tile); + else + return; + } + else + type = TiGetType(tile); + + if ((plane < reg->lreg_pnum) || (reg->lreg_type & TT_DIAGONAL)) + { + reg->lreg_type = type; + reg->lreg_pnum = plane; + reg->lreg_ll = tile->ti_ll; + } + else if (plane == reg->lreg_pnum) + { + if (LEFT(tile) < reg->lreg_ll.p_x) + { + reg->lreg_ll = tile->ti_ll; + reg->lreg_type = type; + } + else if (LEFT(tile) == reg->lreg_ll.p_x + && BOTTOM(tile) < reg->lreg_ll.p_y) + { + reg->lreg_ll.p_y = BOTTOM(tile); + reg->lreg_type = type; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extTransFirst -- + * extTransEach -- + * + * Filter functions passed to ExtFindRegions when tracing out transistor + * regions as part of flat circuit extraction. + * + * Results: + * extTransFirst returns a pointer to a new TransRegion. + * extTransEach returns NULL. + * + * Side effects: + * Memory is allocated by extTransFirst. + * We cons the newly allocated region onto the front of the existing + * region list. + * + * The area of each transistor is updated by extTransEach. + * + * ---------------------------------------------------------------------------- + */ + +Region * +extTransFirst(tile, arg) + Tile *tile; + FindRegion *arg; +{ + TransRegion *reg; + + reg = (TransRegion *) mallocMagic((unsigned) (sizeof (TransRegion))); + reg->treg_next = (TransRegion *) NULL; + reg->treg_labels = (LabelList *) NULL; + reg->treg_area = 0; + reg->treg_tile = tile; + reg->treg_pnum = DBNumPlanes; + + if (IsSplit(tile)) + reg->treg_type = SplitSide(tile) ? SplitRightType(tile) : SplitLeftType(tile); + else + reg->treg_type = TiGetTypeExact(tile); + + /* Prepend it to the region list */ + reg->treg_next = (TransRegion *) arg->fra_region; + arg->fra_region = (Region *) reg; + return ((Region *) reg); +} + + /*ARGSUSED*/ +int +extTransEach(tile, pNum, arg) + Tile *tile; + int pNum; + FindRegion *arg; +{ + TransRegion *reg = (TransRegion *) arg->fra_region; + int area = TILEAREA(tile); + + if (IsSplit(tile)) area /= 2; /* Split tiles are 1/2 area! */ + else if (IsSplit(reg->treg_tile)) + { + /* Avoid setting the region's tile pointer to a split tile */ + reg->treg_tile = tile; + reg->treg_type = TiGetTypeExact(tile); + } + + /* The following is non-ideal. It assumes that the lowest plane of */ + /* types connected to a device is the plane of the device itself. */ + /* Otherwise, the area of the device will be miscalculated. */ + + if (pNum < reg->treg_pnum) reg->treg_area = 0; + + extSetNodeNum((LabRegion *) reg, pNum, tile); + + if (pNum == reg->treg_pnum) reg->treg_area += area; + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extFindNodes -- + * + * Build up, in the manner of ExtFindRegions, a list of all the + * node regions in the CellDef 'def'. This procedure is heavily + * optimized for speed. + * + * Results: + * Returns a pointer to a NULL-terminated list of NodeRegions + * that correspond to the nodes in the circuit. The label lists + * for each node region have not yet been filled in. + * + * Side effects: + * Memory is allocated. + * + * ---------------------------------------------------------------------------- + */ + +Stack *extNodeStack = NULL; +Rect *extNodeClipArea = NULL; + +NodeRegion * +extFindNodes(def, clipArea, subonly) + CellDef *def; /* Def whose nodes are being found */ + Rect *clipArea; /* If non-NULL, ignore perimeter and area that extend + * outside this rectangle. + */ + bool subonly; /* If true, only find the substrate node, and return */ +{ + int extNodeAreaFunc(); + int extSubsFunc(); + FindRegion arg; + int pNum, n; + TileTypeBitMask subsTypesNonSpace; + + /* Reset perimeter and area prior to node extraction */ + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + extResistArea[n] = extResistPerim[n] = 0; + + extNodeClipArea = clipArea; + if (extNodeStack == (Stack *) NULL) + extNodeStack = StackNew(64); + + arg.fra_def = def; + arg.fra_region = (Region *) NULL; + + SigDisableInterrupts(); + + /* First pass: Find substrate. Collect all tiles belonging */ + /* to the substrate and push them onto the stack. Then */ + /* call extNodeAreaFunc() on the first of these to generate */ + /* a single substrate node. */ + + temp_subsnode = (NodeRegion *)NULL; // Reset for new search + + TTMaskZero(&subsTypesNonSpace); + TTMaskSetMask(&subsTypesNonSpace, &ExtCurStyle->exts_globSubstrateTypes); + TTMaskClearType(&subsTypesNonSpace, TT_SPACE); + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + /* Does the type set of this plane intersect the substrate types? */ + if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace)) + { + arg.fra_pNum = pNum; + DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], + &TiPlaneRect, &subsTypesNonSpace, extUnInit, + extSubsFunc, (ClientData) &arg); + } + } + + /* If there was a substrate connection, process it and everything */ + /* that was connected to it. If not, then create a new node */ + /* to represent the substrate. */ + + if (!StackEmpty(extNodeStack)) + { + Tile *tile; + int tilePlaneNum; + + POPTILE(tile, tilePlaneNum); + arg.fra_pNum = tilePlaneNum; + extNodeAreaFunc(tile, &arg); + temp_subsnode = (NodeRegion *)arg.fra_region; + } + else if (ExtCurStyle->exts_globSubstratePlane != -1) + { + NodeRegion *loc_subsnode; + + extNodeAreaFunc((Tile *)NULL, (FindRegion *)&arg); + loc_subsnode = (NodeRegion *)arg.fra_region; + loc_subsnode->nreg_pnum = ExtCurStyle->exts_globSubstratePlane; + loc_subsnode->nreg_type = TT_SPACE; + loc_subsnode->nreg_ll.p_x = MINFINITY + 3; + loc_subsnode->nreg_ll.p_y = MINFINITY + 3; + loc_subsnode->nreg_labels = NULL; + temp_subsnode = loc_subsnode; + } + if (subonly == TRUE) return ((NodeRegion *) arg.fra_region); + + /* Second pass: Find all other nodes */ + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + arg.fra_pNum = pNum; + (void) DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], + &TiPlaneRect, &ExtCurStyle->exts_activeTypes, + extUnInit, extNodeAreaFunc, (ClientData) &arg); + } + SigEnableInterrupts(); + + /* Compute resistance for last node */ + if (arg.fra_region && (ExtOptions & EXT_DORESISTANCE)) + extSetResist((NodeRegion *) arg.fra_region); + + return ((NodeRegion *) arg.fra_region); +} + +int +extSubsFunc(tile, arg) + Tile *tile; + FindRegion *arg; +{ + TileType type; + + if (IsSplit(tile)) + { + type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); + if (type == TT_SPACE) return 0; /* Should not happen */ + } + + /* Mark this tile as pending and push it */ + PUSHTILE(tile, arg->fra_pNum); + + /* That's all we do */ + return (0); +} + + +int +extNodeAreaFunc(tile, arg) + Tile *tile; + FindRegion *arg; +{ + int tilePlaneNum, pNum, len, area, resistClass, n, nclasses; + PlaneMask pMask; + CapValue capval; + TileTypeBitMask *mask, *resMask; + NodeRegion *reg; + Tile *tp; + TileType type, t, residue, tres; + NodeRegion *old; + Rect r; + PlaneAndArea pla; + + if (tile && IsSplit(tile)) + { + type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); + if (type == TT_SPACE) return 0; /* Should not happen */ + } + + /* Compute the resistance for the previous region */ + if (old = (NodeRegion *) arg->fra_region) + if (ExtOptions & EXT_DORESISTANCE) + extSetResist(old); + + /* Allocate a new node */ + nclasses = ExtCurStyle->exts_numResistClasses; + n = sizeof (NodeRegion) + (sizeof (PerimArea) * (nclasses - 1)); + reg = (NodeRegion *) mallocMagic((unsigned) n); + reg->nreg_labels = (LabelList *) NULL; + reg->nreg_cap = (CapValue) 0; + reg->nreg_resist = 0; + reg->nreg_pnum = DBNumPlanes; + reg->nreg_next = (NodeRegion *) NULL; + for (n = 0; n < nclasses; n++) + reg->nreg_pa[n].pa_perim = reg->nreg_pa[n].pa_area = 0; + + /* Prepend the new node to the region list */ + reg->nreg_next = (NodeRegion *) arg->fra_region; + arg->fra_region = (Region *) reg; + + /* Used by substrate generating routine */ + if (tile == NULL) return 1; + + /* Mark this tile as pending and push it */ + PUSHTILE(tile, arg->fra_pNum); + + /* Continue processing tiles until there are none left */ + while (!StackEmpty(extNodeStack)) + { + POPTILE(tile, tilePlaneNum); + + /* + * Since tile was pushed on the stack, we know that it + * belongs to this region. Check to see that it hasn't + * been visited in the meantime. If it's still unvisited, + * visit it and process its neighbors. + */ + if (tile->ti_client == (ClientData) reg) + continue; + tile->ti_client = (ClientData) reg; + if (DebugIsSet(extDebugID, extDebNeighbor)) + extShowTile(tile, "neighbor", 1); + + if (IsSplit(tile)) + { + type = (SplitSide(tile)) ? SplitRightType(tile): + SplitLeftType(tile); + } + else + type = TiGetTypeExact(tile); + + /* Contacts are replaced by their residues when calculating */ + /* area/perimeter capacitance and resistance. */ + + residue = (DBIsContact(type)) ? + DBPlaneToResidue(type, tilePlaneNum) : type; + + mask = &ExtCurStyle->exts_nodeConn[type]; + resMask = &ExtCurStyle->exts_typesResistChanged[residue]; + resistClass = ExtCurStyle->exts_typeToResistClass[residue]; + + /* + * Make sure the lower-leftmost point in the node is + * kept up to date, so we can generate an internal + * node name that does not depend on any other nodes + * in this cell. + */ + extSetNodeNum((LabRegion *) reg, tilePlaneNum, tile); + + /* + * Keep track of the total area of this node, and the + * contribution to parasitic ground capacitance resulting + * from area. + */ + if (extNodeClipArea) + { + TITORECT(tile, &r); + GEOCLIP(&r, extNodeClipArea); + area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot); + } + else area = TILEAREA(tile); + + if (IsSplit(tile)) area /= 2; /* Split tiles are 1/2 area! */ + + if (resistClass != -1) + extResistArea[resistClass] += area; + reg->nreg_cap += area * ExtCurStyle->exts_areaCap[residue]; + + /* Compute perimeter of nonManhattan edges */ + if (IsSplit(tile)) + { + len = ((RIGHT(tile) - LEFT(tile)) * (RIGHT(tile) - LEFT(tile))) + + ((TOP(tile) - BOTTOM(tile)) * (TOP(tile) - BOTTOM(tile))); + len = (int)sqrt((double)len); + + if (extNodeClipArea) + { + /* To-do: Find perimeter length of clipped edge */ + } + + /* Find the type on the other side of the tile */ + t = (SplitSide(tile)) ? SplitLeftType(tile): + SplitRightType(tile); + tres = (DBIsContact(t)) ? DBPlaneToResidue(t, tilePlaneNum) : t; + if ((capval = ExtCurStyle->exts_perimCap[residue][tres]) != (CapValue) 0) + reg->nreg_cap += capval * len; + if (TTMaskHasType(resMask, tres) && resistClass != -1) + extResistPerim[resistClass] += len; + } + + /* + * Walk along all four sides of tile. + * Sum perimeter capacitance as we go. + * Keep track of the contribution to the total perimeter + * of this node, for computing resistance. + */ + + /* Top */ +topside: + + if (IsSplit(tile) && (SplitSide(tile) ^ SplitDirection(tile))) goto leftside; + + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + { + if (extNodeClipArea) + { + r.r_ybot = r.r_ytop = TOP(tile); + r.r_xtop = MIN(RIGHT(tile), RIGHT(tp)); + r.r_xbot = MAX(LEFT(tile), LEFT(tp)); + GEOCLIP(&r, extNodeClipArea); + len = EDGENULL(&r) ? 0 : r.r_xtop - r.r_xbot; + } + else len = MIN(RIGHT(tile), RIGHT(tp)) - MAX(LEFT(tile), LEFT(tp)); + if (IsSplit(tp)) + { + t = SplitBottomType(tp); + if (tp->ti_client == extUnInit && TTMaskHasType(mask, t)) + { + PUSHTILEBOTTOM(tp, tilePlaneNum); + } + else if (tp->ti_client != (ClientData)reg && TTMaskHasType(mask, t)) + { + /* Count split tile twice, once for each node it belongs to. */ + tp->ti_client = extUnInit; + PUSHTILEBOTTOM(tp, tilePlaneNum); + } + } + else + { + t = TiGetTypeExact(tp); + if (tp->ti_client == extUnInit && TTMaskHasType(mask, t)) + { + PUSHTILE(tp, tilePlaneNum); + } + } + tres = (DBIsContact(t)) ? DBPlaneToResidue(t, tilePlaneNum) : t; + if ((capval = ExtCurStyle->exts_perimCap[residue][tres]) != (CapValue) 0) + reg->nreg_cap += capval * len; + if (TTMaskHasType(resMask, tres) && resistClass != -1) + extResistPerim[resistClass] += len; + } + + /* Left */ +leftside: + + if (IsSplit(tile) && SplitSide(tile)) goto bottomside; + + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + { + if (extNodeClipArea) + { + r.r_xbot = r.r_xtop = LEFT(tile); + r.r_ytop = MIN(TOP(tile), TOP(tp)); + r.r_ybot = MAX(BOTTOM(tile), BOTTOM(tp)); + GEOCLIP(&r, extNodeClipArea); + len = EDGENULL(&r) ? 0 : r.r_ytop - r.r_ybot; + } + else len = MIN(TOP(tile), TOP(tp)) - MAX(BOTTOM(tile), BOTTOM(tp)); + if (IsSplit(tp)) + { + t = SplitRightType(tp); + if (tp->ti_client == extUnInit && TTMaskHasType(mask, t)) + { + PUSHTILERIGHT(tp, tilePlaneNum); + } + else if (tp->ti_client != (ClientData)reg && TTMaskHasType(mask, t)) + { + /* Count split tile twice, once for each node it belongs to. */ + tp->ti_client = extUnInit; + PUSHTILERIGHT(tp, tilePlaneNum); + } + } + else + { + t = TiGetTypeExact(tp); + if (tp->ti_client == extUnInit && TTMaskHasType(mask, t)) + { + PUSHTILE(tp, tilePlaneNum); + } + } + tres = (DBIsContact(t)) ? DBPlaneToResidue(t, tilePlaneNum) : t; + if ((capval = ExtCurStyle->exts_perimCap[residue][tres]) != (CapValue) 0) + reg->nreg_cap += capval * len; + if (TTMaskHasType(resMask, tres) && resistClass != -1) + extResistPerim[resistClass] += len; + } + + /* Bottom */ +bottomside: + + if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile)))) + goto rightside; + + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + { + if (extNodeClipArea) + { + r.r_ybot = r.r_ytop = BOTTOM(tile); + r.r_xtop = MIN(RIGHT(tile), RIGHT(tp)); + r.r_xbot = MAX(LEFT(tile), LEFT(tp)); + GEOCLIP(&r, extNodeClipArea); + len = EDGENULL(&r) ? 0 : r.r_xtop - r.r_xbot; + } + else len = MIN(RIGHT(tile), RIGHT(tp)) - MAX(LEFT(tile), LEFT(tp)); + if (IsSplit(tp)) + { + t = SplitTopType(tp); + if (tp->ti_client == extUnInit && TTMaskHasType(mask, t)) + { + PUSHTILETOP(tp, tilePlaneNum); + } + else if (tp->ti_client != (ClientData)reg && TTMaskHasType(mask, t)) + { + /* Count split tile twice, once for each node it belongs to. */ + tp->ti_client = extUnInit; + PUSHTILETOP(tp, tilePlaneNum); + } + } + else + { + t = TiGetTypeExact(tp); + if (tp->ti_client == extUnInit && TTMaskHasType(mask, t)) + { + PUSHTILE(tp, tilePlaneNum); + } + } + tres = (DBIsContact(t)) ? DBPlaneToResidue(t, tilePlaneNum) : t; + if ((capval = ExtCurStyle->exts_perimCap[residue][tres]) != (CapValue) 0) + reg->nreg_cap += capval * len; + if (TTMaskHasType(resMask, tres) && resistClass != -1) + extResistPerim[resistClass] += len; + } + + /* Right */ +rightside: + + if (IsSplit(tile) && !SplitSide(tile)) goto donesides; + + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + { + if (extNodeClipArea) + { + r.r_xbot = r.r_xtop = RIGHT(tile); + r.r_ytop = MIN(TOP(tile), TOP(tp)); + r.r_ybot = MAX(BOTTOM(tile), BOTTOM(tp)); + GEOCLIP(&r, extNodeClipArea); + len = EDGENULL(&r) ? 0 : r.r_ytop - r.r_ybot; + } + else len = MIN(TOP(tile), TOP(tp)) - MAX(BOTTOM(tile), BOTTOM(tp)); + if (IsSplit(tp)) + { + t = SplitLeftType(tp); + if (tp->ti_client == extUnInit && TTMaskHasType(mask, t)) + { + PUSHTILELEFT(tp, tilePlaneNum); + } + else if (tp->ti_client != (ClientData)reg && TTMaskHasType(mask, t)) + { + /* Count split tile twice, once for each node it belongs to */ + tp->ti_client = extUnInit; + PUSHTILELEFT(tp, tilePlaneNum); + } + } + else + { + t = TiGetTypeExact(tp); + if (tp->ti_client == extUnInit && TTMaskHasType(mask, t)) + { + PUSHTILE(tp, tilePlaneNum); + } + } + tres = (DBIsContact(t)) ? DBPlaneToResidue(t, tilePlaneNum) : t; + if ((capval = ExtCurStyle->exts_perimCap[residue][tres]) != (CapValue) 0) + reg->nreg_cap += capval * len; + if (TTMaskHasType(resMask, tres) && resistClass != -1) + extResistPerim[resistClass] += len; + } + +donesides: + /* No capacitance */ + if ((ExtOptions & EXT_DOCAPACITANCE) == 0) + reg->nreg_cap = (CapValue) 0; + + /* If this is a contact, visit all the other planes */ + if (DBIsContact(type)) + { + pMask = DBConnPlanes[type]; + pMask &= ~(PlaneNumToMaskBit(tilePlaneNum)); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (PlaneMaskHasPlane(pMask, pNum)) + { + Plane *plane = arg->fra_def->cd_planes[pNum]; + + tp = plane->pl_hint; + GOTOPOINT(tp, &tile->ti_ll); + plane->pl_hint = tp; + + if (tp->ti_client != extUnInit) continue; + + /* tp and tile should have the same geometry for a contact */ + if (IsSplit(tile) && IsSplit(tp)) + { + if (SplitSide(tile)) + { + t = SplitRightType(tp); + if (TTMaskHasType(mask, t)) + { + PUSHTILERIGHT(tp, pNum); + } + } + else + { + t = SplitLeftType(tp); + if (TTMaskHasType(mask, t)) + { + PUSHTILELEFT(tp, pNum); + } + } + } + else if (IsSplit(tp)) + { + /* Need to test both sides of the tile */ + t = SplitRightType(tp); + if (TTMaskHasType(mask, t)) + { + PUSHTILERIGHT(tp, pNum); + } + t = SplitLeftType(tp); + if (TTMaskHasType(mask, t)) + { + PUSHTILELEFT(tp, pNum); + } + } + else + { + t = TiGetTypeExact(tp); + if (TTMaskHasType(mask, t)) + { + PUSHTILE(tp, pNum); + } + } + } + } + + /* + * The hairiest case is when this type connects to stuff on + * other planes, but isn't itself connected as a contact. + * For example, a CMOS pwell connects to diffusion of the + * same doping (p substrate diff). In a case like this, + * we need to search the entire AREA of the tile plus a + * 1-lambda halo to find everything it overlaps or touches + * on the other plane. + */ + if (pMask = DBAllConnPlanes[type]) + { + Rect biggerArea; + bool is_split = IsSplit(tile); + + extNbrUn = extUnInit; + TITORECT(tile, &pla.area); + GEO_EXPAND(&pla.area, 1, &biggerArea); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if ((pNum != tilePlaneNum) && PlaneMaskHasPlane(pMask, pNum)) + { + pla.plane = pNum; + if (is_split) + DBSrPaintNMArea((Tile *) NULL, + arg->fra_def->cd_planes[pNum], + TiGetTypeExact(tile) & + (TT_DIAGONAL | TT_SIDE | TT_DIRECTION), + &biggerArea, mask, extNbrPushFunc, + (ClientData) &pla); + else + DBSrPaintArea((Tile *) NULL, + arg->fra_def->cd_planes[pNum], &biggerArea, + mask, extNbrPushFunc, (ClientData) &pla); + } + } + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extGetCapValue -- + * extSetCapValue -- + * + * Procedures to get/set a value from our capacitance tables. + * + * ---------------------------------------------------------------------------- + */ + +void +extSetCapValue(he, value) + HashEntry *he; + CapValue value; +{ + if (HashGetValue(he) == NULL) + HashSetValue(he, (CapValue *) mallocMagic(sizeof(CapValue))); + *( (CapValue *) HashGetValue(he)) = value; +} + +CapValue +extGetCapValue(he) + HashEntry *he; +{ + if (HashGetValue(he) == NULL) + extSetCapValue(he, (CapValue) 0); + return *( (CapValue *) HashGetValue(he)); +} + +/* + * ---------------------------------------------------------------------------- + * + * extCapHashKill -- + * + * Kill off a coupling capacitance hash table. + * + * Results: + * None. + * + * Side effects: + * Frees up storage in the table. + * ---------------------------------------------------------------------------- + */ + +void +extCapHashKill(ht) + HashTable *ht; +{ + HashSearch hs; + HashEntry *he; + + HashStartSearch(&hs); + while (he = HashNext(ht, &hs)) + { + if (HashGetValue(he) != NULL) + { + freeMagic(HashGetValue(he)); /* Free a malloc'ed CapValue */ + HashSetValue(he, (ClientData) NULL); + } + } + HashKill(ht); +} diff --git a/extract/ExtCell.c b/extract/ExtCell.c new file mode 100644 index 00000000..a34f27e1 --- /dev/null +++ b/extract/ExtCell.c @@ -0,0 +1,406 @@ +/* + * ExtCell.c -- + * + * Circuit extraction. + * Extract a single cell. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtCell.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/styles.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "utils/stack.h" +#include "utils/utils.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "utils/undo.h" + +/* --------------------------- Global data ---------------------------- */ + +/* + * Value normally present in ti_client to indicate tiles that have not + * been marked with their associated region. + */ +ClientData extUnInit = (ClientData) CLIENTDEFAULT; + + +/* ------------------------ Data local to this file ------------------- */ + +/* Forward declarations */ +int extOutputUsesFunc(); +FILE *extFileOpen(); + +void extCellFile(); +void extHeader(); + + +/* + * ---------------------------------------------------------------------------- + * + * ExtCell -- + * + * Extract the cell 'def', plus all its interactions with its subcells. + * Place the result in the file named 'outName'. + * + * Results: + * None. + * + * Side effects: + * Creates the file 'outName'.ext and writes to it. + * May leave feedback information where errors were encountered. + * Upon return, extNumFatal contains the number of fatal errors + * encountered while extracting 'def', and extNumWarnings contains + * the number of warnings. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtCell(def, outName, doLength) + CellDef *def; /* Cell being extracted */ + char *outName; /* Name of output file; if NULL, derive from def name */ + bool doLength; /* If TRUE, extract pathlengths from drivers to + * receivers (the names are stored in ExtLength.c). + * Should only be TRUE for the root cell in a + * hierarchy. + */ +{ + char *filename; + FILE *f; + + f = extFileOpen(def, outName, "w", &filename); + + TxPrintf("Extracting %s into %s:\n", def->cd_name, filename); + + if (f == NULL) + { +#ifdef MAGIC_WRAPPER + TxError("Cannot open output file.\n"); +#else + TxError("Cannot open output file: "); + perror(filename); +#endif + return; + } + + extNumFatal = extNumWarnings = 0; + extCellFile(def, f, doLength); + (void) fclose(f); + + if (extNumFatal > 0 || extNumWarnings > 0) + { + TxPrintf("%s:", def->cd_name); + if (extNumFatal > 0) + TxPrintf(" %d fatal error%s", + extNumFatal, extNumFatal != 1 ? "s" : ""); + if (extNumWarnings > 0) + TxPrintf(" %d warning%s", + extNumWarnings, extNumWarnings != 1 ? "s" : ""); + TxPrintf("\n"); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extFileOpen -- + * + * Open the .ext file corresponding to a .mag file. + * If def->cd_file is non-NULL, the .ext file is just def->cd_file with + * the trailing .mag replaced by .ext. Otherwise, the .ext file is just + * def->cd_name followed by .ext. + * + * Results: + * Return a pointer to an open FILE, or NULL if the .ext + * file could not be opened in the specified mode. + * + * Side effects: + * Opens a file. + * + * ---------------------------------------------------------------------------- + */ + +FILE * +extFileOpen(def, file, mode, prealfile) + CellDef *def; /* Cell whose .ext file is to be written */ + char *file; /* If non-NULL, open 'name'.ext; otherwise, + * derive filename from 'def' as described + * above. + */ + char *mode; /* Either "r" or "w", the mode in which the .ext + * file is to be opened. + */ + char **prealfile; /* If this is non-NULL, it gets set to point to + * a string holding the name of the .ext file. + */ +{ + char namebuf[512], *name, *endp, *ends; + int len; + FILE *rfile, *testf; + + if (file) name = file; + else if (def->cd_file) + { + name = def->cd_file; + ends = strrchr(def->cd_file, '/'); + if (ends == NULL) ends = def->cd_file; + if (endp = strrchr(ends + 1, '.')) + { + name = namebuf; + len = endp - def->cd_file; + if (len > sizeof namebuf - 1) len = sizeof namebuf - 1; + (void) strncpy(namebuf, def->cd_file, len); + namebuf[len] = '\0'; + } + } + else name = def->cd_name; + + /* Try once as-is, and if this fails, try stripping any leading */ + /* path information in case cell is in a read-only directory. */ + + if ((rfile = PaOpen(name, mode, ".ext", Path, CellLibPath, prealfile)) != NULL) + return rfile; + + if (!strcmp(mode, "r")) return NULL; /* Not even readable */ + + /* Try writing to the cwd IF there is no .mag file by the */ + /* same name in the cwd that would conflict. */ + + name = strrchr(def->cd_name, '/'); + if (name != NULL) + name++; + else + name = def->cd_name; + + ends = strrchr(def->cd_file, '/'); + if (ends != NULL) + { + testf = PaOpen(ends + 1, "r", ".mag", ".", ".", NULL); + if (testf) + { + fclose(testf); + return NULL; + } + } + return (PaOpen(name, mode, ".ext", ".", ".", prealfile)); +} + +/* + * ---------------------------------------------------------------------------- + * + * extCellFile -- + * + * Internal interface for extracting a single cell. + * Extracts it to the open FILE 'f'. Doesn't print + * any messages. + * + * Results: + * None. + * + * Side effects: + * May leave feedback information where errors were encountered. + * Upon return, extNumFatal has been incremented by the number of + * fatal errors encountered while extracting 'def', and extNumWarnings + * by the number of warnings. + * + * ---------------------------------------------------------------------------- + */ + +void +extCellFile(def, f, doLength) + CellDef *def; /* Def to be extracted */ + FILE *f; /* Output to this file */ + bool doLength; /* TRUE if we should extract driver-receiver path + * length information for this cell (see ExtCell + * for more details). + */ +{ + NodeRegion *reg; + + UndoDisable(); + + /* Output the header: timestamp, technology, calls on cell uses */ + if (!SigInterruptPending) extHeader(def, f); + + /* Extract the mask information in this cell */ + reg = (NodeRegion *) NULL; + if (!SigInterruptPending) reg = extBasic(def, f); + + /* Do hierarchical extraction */ + extParentUse->cu_def = def; + if (!SigInterruptPending) extSubtree(extParentUse, reg, f); + if (!SigInterruptPending) extArray(extParentUse, f); + + /* Clean up from basic extraction */ + if (reg) ExtFreeLabRegions((LabRegion *) reg); + ExtResetTiles(def, extUnInit); + + /* Final pass: extract length information if desired */ + if (!SigInterruptPending && doLength && (ExtOptions & EXT_DOLENGTH)) + extLength(extParentUse, f); + + UndoEnable(); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHeader -- + * + * Output header information to the .ext file for a cell. + * This information consists of: + * + * timestamp + * extractor version number + * technology + * scale factors for resistance, capacitance, and lambda + * calls on all subcells used by this cell (see extOutputUsesFunc) + * + * Results: + * None. + * + * Side effects: + * Writes to (FILE *) 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +extHeader(def, f) + CellDef *def; /* Cell being extracted */ + FILE *f; /* Write to this file */ +{ + int n; + bool propfound; + char *propvalue; + + /* Output a timestamp (should be first) */ + fprintf(f, "timestamp %d\n", def->cd_timestamp); + + /* Output our version number */ + fprintf(f, "version %s\n", MagicVersion); + + /* Output the technology */ + fprintf(f, "tech %s\n", DBTechName); + + /* Output the extract style name */ + fprintf(f, "style %s\n", ExtCurStyle->exts_name); + + /* + * Output scaling factors: R C D + * R = amount to multiply all resistances in the file by + * C = amount to multiply all capacitances by + * D = amount to multiply all linear distances by (areas + * should be multiplied by D**2). + */ + fprintf(f, "scale %d %d %g\n", + ExtCurStyle->exts_resistScale, + ExtCurStyle->exts_capScale, + ExtCurStyle->exts_unitsPerLambda); + + /* Output the sheet resistivity classes */ + fprintf(f, "resistclasses"); + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + fprintf(f, " %d", ExtCurStyle->exts_resistByResistClass[n]); + fprintf(f, "\n"); + + /* Output any parameters defined for this cell that */ + /* are to be passed to instances of the cell */ + /* (created by defining property "parameter") */ + + propvalue = (char *)DBPropGet(def, "parameter", &propfound); + if (propfound) + { + // Use device parameter table to store the cell def parameters, + // but preface name with ":" to avoid any conflict with device + // names. + fprintf(f, "parameters :%s %s\n", def->cd_name, propvalue); + } + + /* Output all calls on subcells */ + (void) DBCellEnum(def, extOutputUsesFunc, (ClientData) f); +} + +/* + * ---------------------------------------------------------------------------- + * + * extOutputUsesFunc -- + * + * Filter function, called via DBCellEnum, that outputs all the + * cell uses contained in the parent's cell tile planes. + * + * Results: + * Always returns 0, for DBCellEnum to keep going. + * + * Side effects: + * Writes a line for each use encountered to 'outf'. + * The line is of the following form: + * + * use defname useid Ta ... Tf + * + * where 'defname' is the name of the cell def referenced (cd_name), + * 'useid' is its use identifier (cu_id), and Ta ... Tf are the six + * components of the transform from coordinates of this use up to + * its parent. If the cell is an array, the use id may be followed by: + * + * [xlo,xhi,xsep][ylo,yhi,ysep] + * + * The indices are xlo through xhi inclusive, or ylo through yhi + * inclusive. The separation between adjacent elements is xsep + * or ysep; this is used in computing the transform for a particular + * array element. If arraying is not present in a given direction, + * the low and high indices are equal and the separation is ignored. + * + * ---------------------------------------------------------------------------- + */ + +int +extOutputUsesFunc(cu, outf) + CellUse *cu; + FILE *outf; +{ + Transform *t = &cu->cu_transform; + + fprintf(outf, "use %s %s", cu->cu_def->cd_name, cu->cu_id); + if (cu->cu_xlo != cu->cu_xhi || cu->cu_ylo != cu->cu_yhi) + { + fprintf(outf, "[%d:%d:%d]", + cu->cu_xlo, cu->cu_xhi, cu->cu_xsep); + fprintf(outf, "[%d:%d:%d]", + cu->cu_ylo, cu->cu_yhi, cu->cu_ysep); + } + + /* Output transform to parent */ + fprintf(outf, " %d %d %d %d %d %d\n", + t->t_a, t->t_b, t->t_c, t->t_d, t->t_e, t->t_f); + + return (0); +} diff --git a/extract/ExtCouple.c b/extract/ExtCouple.c new file mode 100644 index 00000000..5223577b --- /dev/null +++ b/extract/ExtCouple.c @@ -0,0 +1,1169 @@ +/* + * ExtCouple.c -- + * + * Circuit extraction. + * Extraction of coupling capacitance. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtCouple.c,v 1.2 2010/06/24 12:37:17 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "extract/extract.h" +#include "extract/extractInt.h" + +/* --------------------- Data local to this file ---------------------- */ + +/* Pointer to hash table currently being updated with coupling capacitance */ +HashTable *extCoupleHashPtr; + +/* Clipping area for coupling searches */ +Rect *extCoupleSearchArea; + +/* Current list of sidewall capacitance rules */ +EdgeCap *extCoupleList; +EdgeCap *extOverlapList; + +/* Def being processed */ +CellDef *extOverlapDef; + +/* Forward procedure declarations */ +int extBasicOverlap(), extBasicCouple(); +int extAddOverlap(), extAddCouple(); +int extSideLeft(), extSideRight(), extSideBottom(), extSideTop(); +int extSideOverlap(); +void extSideCommon(); + +/* Structure to pass on to the coupling and sidewall capacitance */ +/* routines to include the current cell definition and the current */ +/* plane being searched. */ + +typedef struct _ecs { + CellDef *def; + int plane; +} extCapStruct; + +/* Structure to pass on two planes to check for coupling and the tile */ +/* which is doing the coupling. */ + +typedef struct _ecpls { + Tile *tile; + int plane_of_tile; + int plane_checked; +} extCoupleStruct; + +/* Structure to pass on two planes to check for coupling and the */ +/* boundary which initiated the check. */ + +typedef struct _esws { + Boundary *bp; + int plane_of_boundary; + int plane_checked; +} extSidewallStruct; + + +/* --------------------- Debugging stuff ---------------------- */ +#define CAP_DEBUG FALSE + +void extNregAdjustCap(nr, c, str) + NodeRegion *nr; + CapValue c; + char *str; +{ + char *name; + name = extNodeName((LabRegion *) nr); + fprintf(stderr, "CapDebug: %s += %f (%s)\n", name, c, str); +} + +void extAdjustCouple(he, c, str) + HashEntry *he; + CapValue c; + char *str; +{ + char *name1; + char *name2; + CoupleKey *ck; + ck = (CoupleKey *) he->h_key.h_words; + name1 = extNodeName((LabRegion *) ck->ck_1); + name2 = extNodeName((LabRegion *) ck->ck_2); + fprintf(stderr, "CapDebug: %s-%s += %f (%s)\n", name1, name2, c, str); +} + + +/* + * ---------------------------------------------------------------------------- + * + * extFindCoupling -- + * + * Find the coupling capacitances in the cell def. Such capacitances + * arise from three causes: + * + * Overlap. When two tiles on different planes overlap, they + * may have a coupling capacitance proportional to + * their areas. If this is so, we subtract the substrate + * capacitance of the overlapped type, and add the overlap + * capacitance to the coupling hash table. + * + * Sidewall. When tiles on the same plane are adjacent, they may + * have a coupling capacitance proportional to the + * length of their edges, divided by the distance between + * them. In this case, we just add the sidewall coupling + * capacitance to the hash table. + * + * Sidewall + * overlap. When the edge of a tile on one plane overlaps a tile + * on a different plane, the two tiles may have a coupling + * capacitance proportional to the length of the overlapping + * edge. In this case we add the coupling capacitance to the + * hash table. (We may want to deduct the perimeter capacitance + * to substrate?). + * + * Requires that ExtFindRegions has been run on 'def' to label all its + * tiles with NodeRegions. Also requires that the HashTable 'table' + * has been initialized by the caller. + * + * If 'clipArea' is non-NULL, search for overlap capacitance only inside + * the area *clipArea. Search for sidewall capacitance only from tiles + * inside *clipArea, although this capacitance may be to tiles outside + * *clipArea. + * + * Results: + * None. + * + * Side effects: + * When done, the HashTable 'table' will have been filled + * in with an entry for each pair of nodes having coupling + * capacitance. Each entry will have a two-word key organized + * as an CoupleKey struct, with ck_1 and ck_2 pointing to the + * coupled nodes. The value of the hash entry will be the + * coupling capacitance between that pair of nodes. + * + * ---------------------------------------------------------------------------- + */ + +void +extFindCoupling(def, table, clipArea) + CellDef *def; + HashTable *table; + Rect *clipArea; +{ + Rect *searchArea; + int pNum; + extCapStruct ecs; + + ecs.def = def; + + extCoupleHashPtr = table; + extCoupleSearchArea = clipArea; + searchArea = clipArea ? clipArea : &TiPlaneRect; + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + ecs.plane = pNum; + + if (PlaneMaskHasPlane(ExtCurStyle->exts_overlapPlanes, pNum)) + (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], + searchArea, &ExtCurStyle->exts_overlapTypes[pNum], + extBasicOverlap, (ClientData) &ecs); + if (PlaneMaskHasPlane(ExtCurStyle->exts_sidePlanes, pNum)) + (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], + searchArea, &ExtCurStyle->exts_sideTypes[pNum], + extBasicCouple, (ClientData) &ecs); + } + +} + +/* + * ---------------------------------------------------------------------------- + * + * extRelocateSubstrateCoupling --- + * + * Move coupling capacitance to the substrate node from the coupling + * cap table onto the source node's cap-to-substrate record. + * + * ---------------------------------------------------------------------------- + */ + +void +extRelocateSubstrateCoupling(table, subsnode) + HashTable *table; /* Coupling capacitance hash table */ + NodeRegion *subsnode; /* Node record for substrate */ +{ + HashEntry *he; + CoupleKey *ck; + HashSearch hs; + CapValue cap; + NodeRegion *rtp; + NodeRegion *rbp; + + HashStartSearch(&hs); + while (he = HashNext(table, &hs)) + { + cap = extGetCapValue(he); + if (cap == 0) continue; + + ck = (CoupleKey *) he->h_key.h_words; + rtp = (NodeRegion *) ck->ck_1; + rbp = (NodeRegion *) ck->ck_2; + + if (rtp == subsnode) + { + rbp->nreg_cap += cap; + extSetCapValue(he, (CapValue)0); + } + else if (rbp == subsnode) + { + rtp->nreg_cap += cap; + extSetCapValue(he, (CapValue)0); + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * extOutputCoupling -- + * + * Output the coupling capacitance table built up by extFindCoupling(). + * Each entry in the hash table is a capacitance between the pair of + * nodes identified by he->h_key, an CoupleKey struct. + * + * ExtFindRegions and ExtLabelRegions should have been called prior + * to this procedure. + * + * Results: + * None. + * + * Side effects: + * See the comments above. + * + * ---------------------------------------------------------------------------- + */ + +void +extOutputCoupling(table, outFile) + HashTable *table; /* Coupling capacitance hash table */ + FILE *outFile; /* Output file */ +{ + HashEntry *he; + CoupleKey *ck; + HashSearch hs; + char *text; + CapValue cap; /* value of capacitance. */ + + HashStartSearch(&hs); + while (he = HashNext(table, &hs)) + { + cap = extGetCapValue(he) / ExtCurStyle->exts_capScale; + if (cap == 0) + continue; + + ck = (CoupleKey *) he->h_key.h_words; + text = extNodeName((LabRegion *) ck->ck_1); + fprintf(outFile, "cap \"%s\" ", text); + text = extNodeName((LabRegion *) ck->ck_2); + fprintf(outFile, "\"%s\" %lg\n", text, cap); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extBasicOverlap -- + * + * Filter function for overlap capacitance. + * Called for each tile that might have coupling capacitance + * to another node because it overlaps a tile or tiles in that + * node. Causes an area search over the area of 'tile' in all + * planes to which 'tile' has overlap capacitance, for any tiles + * to which 'tile' has overlap capacitance. + * + * Results: + * Returns 0 to keep DBSrPaintArea() going. + * + * Side effects: + * See extAddOverlap(). + * + * ---------------------------------------------------------------------------- + */ + +int +extBasicOverlap(tile, ecs) + Tile *tile; + extCapStruct *ecs; +{ + int thisType; + int pNum; + PlaneMask pMask; + TileTypeBitMask *tMask; + Rect r; + CellDef *def = ecs->def; + int thisPlane = ecs->plane; + extCoupleStruct ecpls; + + if (IsSplit(tile)) + thisType = (SplitSide(tile)) ? SplitRightType(tile) : + SplitLeftType(tile); + else + thisType = TiGetTypeExact(tile); + + if (DBIsContact(thisType)) + thisType = DBPlaneToResidue(thisType, thisPlane); + + pMask = ExtCurStyle->exts_overlapOtherPlanes[thisType]; + tMask = &ExtCurStyle->exts_overlapOtherTypes[thisType]; + + TITORECT(tile, &r); + extOverlapDef = def; + if (extCoupleSearchArea) + { + GEOCLIP(&r, extCoupleSearchArea); + } + + ecpls.tile = tile; + ecpls.plane_of_tile = thisPlane; + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + /* Skip if nothing interesting on the other plane */ + if (pNum == thisPlane || !PlaneMaskHasPlane(pMask, pNum)) + continue; + + ecpls.plane_checked = pNum; + (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &r, tMask, + extAddOverlap, (ClientData) &ecpls); + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extAddOverlap -- + * + * We are called for each tile that is overlapped by the tile passed to + * extBasicOverlap() above (our argument 'tabove'). The intent is that + * 'tbelow' actually shields 'tabove' from the substrate, so we should + * replace node(tabove)'s capacitance to substrate with a capacitance + * to node(tbelow) whose size is proportional to the area of the overlap. + * + * We check to insure that tabove is not shielded from tbelow by any + * intervening material; if it is, we deduct the capacitance between + * node(tabove) and node(tbelow) for the area of the overlap. + * + * Results: + * Returns 0 to keep DBSrPaintArea() going. + * + * Side effects: + * Updates the HashEntry with key node(tbelow), node(tabove) + * by adding the capacitance of the overlap if node(tbelow) + * and node(tabove) are different, and if they are not totally + * shielded by intervening material. Also subtracts the capacitance + * to substrate from node(tabove) for the area of the overlap. + * If node(tbelow) and node(tabove) are the same, we do nothing. + * + * ---------------------------------------------------------------------------- + */ + +struct overlap +{ + Rect o_clip; + int o_area; + PlaneMask o_pmask; + TileTypeBitMask o_tmask; +}; + +int +extAddOverlap(tbelow, ecpls) + Tile *tbelow; + extCoupleStruct *ecpls; +{ + int extSubtractOverlap(), extSubtractOverlap2(); + NodeRegion *rabove, *rbelow; + HashEntry *he; + struct overlap ov; + TileType ta, tb; + CoupleKey ck; + int pNum; + CapValue c; + Tile *tabove = ecpls->tile; + + /* Check if both tiles are connected. If they are, we don't need */ + /* to check for shielding material, and we don't want to add any */ + /* coupling capacitance between them. However, we *do* want to */ + /* subtract off any substrate (area) capacitance previously added */ + /* (Correction made 4/29/04 by Tim from a tip by Jeff Sondeen). */ + + rabove = (NodeRegion *) extGetRegion(tabove); + rbelow = (NodeRegion *) extGetRegion(tbelow); + + /* Quick check on validity of tile's ti_client record */ + if (rbelow == (NodeRegion *)CLIENTDEFAULT) return 0; + + /* Compute the area of overlap */ + ov.o_clip.r_xbot = MAX(LEFT(tbelow), LEFT(tabove)); + ov.o_clip.r_xtop = MIN(RIGHT(tbelow), RIGHT(tabove)); + ov.o_clip.r_ybot = MAX(BOTTOM(tbelow), BOTTOM(tabove)); + ov.o_clip.r_ytop = MIN(TOP(tbelow), TOP(tabove)); + if (extCoupleSearchArea) + { + GEOCLIP(&ov.o_clip, extCoupleSearchArea); + } + ov.o_area = (ov.o_clip.r_ytop - ov.o_clip.r_ybot) + * (ov.o_clip.r_xtop - ov.o_clip.r_xbot); + ta = TiGetType(tabove); + tb = TiGetType(tbelow); + + /* Revert any contacts to their residues */ + + if (DBIsContact(ta)) + ta = DBPlaneToResidue(ta, ecpls->plane_of_tile); + + if (DBIsContact(tb)) + tb = DBPlaneToResidue(tb, ecpls->plane_checked); + + /* + * Find whether rabove and rbelow are shielded by intervening material. + * Deduct the area shielded from the area of the overlap, so we adjust + * the overlap capacitance correspondingly. + */ + if (ov.o_pmask = ExtCurStyle->exts_overlapShieldPlanes[ta][tb]) + { + ov.o_tmask = ExtCurStyle->exts_overlapShieldTypes[ta][tb]; + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + if (!PlaneMaskHasPlane(ov.o_pmask, pNum)) continue; + ov.o_pmask &= ~(PlaneNumToMaskBit(pNum)); + if (ov.o_pmask == 0) + { + (void) DBSrPaintArea((Tile *) NULL, + extOverlapDef->cd_planes[pNum], &ov.o_clip, &ov.o_tmask, + extSubtractOverlap, (ClientData) &ov); + } + else + { + (void) DBSrPaintArea((Tile *) NULL, + extOverlapDef->cd_planes[pNum], &ov.o_clip, &DBAllTypeBits, + extSubtractOverlap2, (ClientData) &ov); + } + break; + } + } + + /* If any capacitance remains, add this record to the table */ + if (ov.o_area > 0) + { + int oa = ExtCurStyle->exts_planeOrder[ecpls->plane_of_tile]; + int ob = ExtCurStyle->exts_planeOrder[ecpls->plane_checked]; + if (oa > ob) + { + Tile *tp; + TileType t, tres; + TileTypeBitMask *mask; + int len; + CapValue cp; + /* + * Subtract the substrate capacitance from tabove's region due to + * the area of the overlap, minus any shielded area. The shielded + * areas get handled later, when processing coupling between tabove + * and the shielding tile. (Tabove was the overlapping tile, so it + * is shielded from the substrate by tbelow if the Tabove plane is + * above the Tbelow plane). + */ + rabove->nreg_cap -= ExtCurStyle->exts_areaCap[ta] * ov.o_area; + if (CAP_DEBUG) + extNregAdjustCap(rabove, + -(ExtCurStyle->exts_areaCap[ta] * ov.o_area), + "obsolete_overlap"); + + } else if (CAP_DEBUG) + extNregAdjustCap(rabove, 0.0, + "obsolete_overlap (skipped, wrong direction)"); + + /* If the regions are the same, skip this part */ + if (rabove == rbelow) return (0); + + /* Find the coupling hash record */ + if (rabove < rbelow) ck.ck_1 = rabove, ck.ck_2 = rbelow; + else ck.ck_1 = rbelow, ck.ck_2 = rabove; + he = HashFind(extCoupleHashPtr, (char *) &ck); + + /* Add the overlap capacitance to the table */ + c = extGetCapValue(he); + c += ExtCurStyle->exts_overlapCap[ta][tb] * ov.o_area; + if (CAP_DEBUG) + extAdjustCouple(he, ExtCurStyle->exts_overlapCap[ta][tb] * + ov.o_area, "overlap"); + extSetCapValue(he, c); + } + return (0); +} + +int +extSubtractOverlap(tile, ov) + Tile *tile; + struct overlap *ov; +{ + Rect r; + int area; + + TITORECT(tile, &r); + GEOCLIP(&r, &ov->o_clip); + area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot); + if (area > 0) + ov->o_area -= area; + + return (0); +} + +int +extSubtractOverlap2(tile, ov) + Tile *tile; + struct overlap *ov; +{ + struct overlap ovnew; + int area, pNum; + Rect r; + + TITORECT(tile, &r); + GEOCLIP(&r, &ov->o_clip); + area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot); + if (area <= 0) + return (0); + + /* This tile shields everything below */ + if (TTMaskHasType(&ov->o_tmask, TiGetType(tile))) + { + ov->o_area -= area; + return (0); + } + + /* Tile doesn't shield, so search next plane */ + ovnew = *ov; + ovnew.o_clip = r; + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + if (!PlaneMaskHasPlane(ovnew.o_pmask, pNum)) continue; + ovnew.o_pmask &= ~(PlaneNumToMaskBit(pNum)); + if (ovnew.o_pmask == 0) + { + (void) DBSrPaintArea((Tile *) NULL, + extOverlapDef->cd_planes[pNum], &ovnew.o_clip, &ovnew.o_tmask, + extSubtractOverlap, (ClientData) &ovnew); + } + else + { + (void) DBSrPaintArea((Tile *) NULL, + extOverlapDef->cd_planes[pNum], &ovnew.o_clip, &DBAllTypeBits, + extSubtractOverlap2, (ClientData) &ovnew); + } + break; + } + ov->o_area = ovnew.o_area; + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extBasicCouple -- + * + * Filter function for sidewall coupling capacitance. + * Called for each tile that might have coupling capacitance + * to another node because it is near tiles on the same plane, + * or because its edge overlaps tiles on a different plane. + * + * Causes an area search over a halo surrounding each edge of + * 'tile' for edges to which each edge has coupling capacitance + * on this plane, and a search for tiles on different planes that + * this edge overlaps. + * + * Results: + * Returns 0 to keep DBSrPaintArea() going. + * + * Side effects: + * See extAddCouple(). + * + * ---------------------------------------------------------------------------- + */ + +int +extBasicCouple(tile, ecs) + Tile *tile; + extCapStruct *ecs; +{ + (void) extEnumTilePerim(tile, ExtCurStyle->exts_sideEdges[TiGetType(tile)], + ecs->plane, extAddCouple, (ClientData) ecs); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extAddCouple -- + * + * Called for each segment along the boundary of the tile bp->b_inside + * that might have coupling capacitance with its neighbors. + * Causes an area search over a halo surrounding the boundary bp->b_segment + * on the side outside bp->b_inside for edges to which this one has coupling + * capacitance on this plane, and for tiles overlapping this edge on different + * planes. + * + * Results: + * Returns 0 to keep DBSrPaintArea() going. + * + * Side effects: + * For each edge (tnear, tfar) we find that has coupling capacitance + * to us, update the HashEntry with key node(bp->b_inside), node(tfar) + * by adding the sidewall capacitance if node(bp->b_inside) and node(tfar) + * are different. If node(bp->b_inside) and node(tfar) are the same, we + * do nothing. + * + * For each tile tp we find on a different plane that overlaps this + * edge, update the HashEntry with key node(bp->b_inside), node(tp) + * by adding the sidewall overlap capacitance. If node(bp->b_inside) + * and node(tp) are the same, do nothing. + * + * ---------------------------------------------------------------------------- + */ + +Rect extSideOverlapSearchArea; + +int +extAddCouple(bp, ecs) + Boundary *bp; /* Boundary being considered */ + extCapStruct *ecs; +{ + TileType tin = TiGetType(bp->b_inside), tout = TiGetType(bp->b_outside); + int pNum; + PlaneMask pMask; + int (*proc)(); + Boundary bpCopy; + Rect r, ovr; + CellDef *def = ecs->def; + extSidewallStruct esws; + + /* Revert any edge contacts to their residues */ + if (DBIsContact(tin)) + tin = DBPlaneToResidue(tin, ecs->plane); + if (DBIsContact(tout)) + tout = DBPlaneToResidue(tout, ecs->plane); + + extCoupleList = ExtCurStyle->exts_sideCoupleCap[tin][tout]; + extOverlapList = ExtCurStyle->exts_sideOverlapCap[tin][tout]; + if (extCoupleList == NULL && extOverlapList == NULL) + return (0); + + /* + * Clip the edge of interest to the area where we're searching + * for coupling capacitance, if such an area has been specified. + */ + if (extCoupleSearchArea) + { + bpCopy = *bp; + bp = &bpCopy; + + GEOCLIP(&bp->b_segment, extCoupleSearchArea); + + /* Fixed 2/27/2017 by Tim + * GEO_RECTNULL should not be applied to boundaries, which are + * segments and therefore have no area. This causes the function + * to always return. + */ + /* if (GEO_RECTNULL(&bp->b_segment)) return (0); */ + + if ((bp->b_segment.r_ytop <= bp->b_segment.r_ybot) && + (bp->b_segment.r_xtop <= bp->b_segment.r_xbot)) + return 0; + } + r = ovr = bp->b_segment; + + switch (bp->b_direction) + { + case BD_LEFT: /* Along left */ + r.r_xbot -= ExtCurStyle->exts_sideCoupleHalo ; + ovr.r_xbot -= 1; + proc = extSideLeft; + break; + case BD_RIGHT: /* Along right */ + r.r_xtop += ExtCurStyle->exts_sideCoupleHalo ; + ovr.r_xtop += 1; + proc = extSideRight; + break; + case BD_TOP: /* Along top */ + r.r_ytop += ExtCurStyle->exts_sideCoupleHalo ; + ovr.r_ytop += 1; + proc = extSideTop; + break; + case BD_BOTTOM: /* Along bottom */ + r.r_ybot -= ExtCurStyle->exts_sideCoupleHalo ; + ovr.r_ybot -= 1; + proc = extSideBottom; + break; + } + + if (extCoupleList) + (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[ecs->plane], + &r, &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], + proc, (ClientData) bp); + + if (extOverlapList) + { + pMask = ExtCurStyle->exts_sideOverlapOtherPlanes[tin][tout]; + extSideOverlapSearchArea = ovr; + extOverlapDef = def; + + esws.bp = bp; + esws.plane_of_boundary = ecs->plane; + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (PlaneMaskHasPlane(pMask, pNum)) + { + esws.plane_checked = pNum; + (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], + &ovr, &ExtCurStyle->exts_sideOverlapOtherTypes[tin][tout], + extSideOverlap, (ClientData) &esws); + } + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extSideOverlap -- + * + * The boundary 'bp' has been found to overlap the tile 'tp', which it + * has coupling capacitance to. + * + * Results: + * Returns 0 to keep DBSrPaintArea() going. + * + * Side effects: + * Update the coupling capacitance between node(bp->t_inside) and + * node(tp) if the two nodes are different. Does so by updating + * the value stored in the HashEntry keyed by the two nodes. + * + * ---------------------------------------------------------------------------- + */ + +int +extSideOverlap(tp, esws) + Tile *tp; /* Overlapped tile */ + extSidewallStruct *esws; /* Overlapping edge and plane information */ +{ + Boundary *bp = esws->bp; /* Overlapping edge */ + NodeRegion *rtp = (NodeRegion *) extGetRegion(tp); + NodeRegion *rbp = (NodeRegion *) extGetRegion(bp->b_inside); + TileType ta, tb; + Rect tpr; + struct overlap ov; + HashEntry *he; + EdgeCap *e; + int length, areaAccountedFor; + CapValue cap; + CoupleKey ck; + + if (bp->b_segment.r_xtop == bp->b_segment.r_xbot) + { + length = MIN(bp->b_segment.r_ytop, TOP(tp)) + - MAX(bp->b_segment.r_ybot, BOTTOM(tp)); + } + else + { + length = MIN(bp->b_segment.r_xtop, RIGHT(tp)) + - MAX(bp->b_segment.r_xbot, LEFT(tp)); + } + + TITORECT(tp, &ov.o_clip); + GEOCLIP(&ov.o_clip, &extSideOverlapSearchArea); + ov.o_area = length; + areaAccountedFor = 0; + ASSERT(length == GEO_WIDTH(&ov.o_clip) * GEO_HEIGHT(&ov.o_clip), + "extSideOverlap"); + ta = TiGetType(bp->b_inside); + tb = TiGetType(tp); + + /* Avoid doing the code below if we're just going to return without */ + /* changing anything. */ + if ((tb == TT_SPACE) && (rtp == rbp)) return (0); + + /* Revert any contacts to their residues */ + if (DBIsContact(ta)) + ta = DBPlaneToResidue(ta, esws->plane_of_boundary); + if (DBIsContact(tb)) + tb = DBPlaneToResidue(tb, esws->plane_checked); + + /* Apply each rule, incorporating shielding into the edge length. */ + cap = (CapValue) 0; + for (e = extOverlapList; e; e = e->ec_next) + { + /* Only apply rules for the plane in which they are declared */ + if (!PlaneMaskHasPlane(e->ec_pmask, esws->plane_checked)) continue; + + /* Does this rule "e" include the tile we found? */ + if (TTMaskHasType(&e->ec_near, TiGetType(tp))) + { + /* We have a possible capacitor, but are the tiles shielded from + * each other part of the way? + */ + int pNum; + ov.o_area = length; + ov.o_pmask = ExtCurStyle->exts_sideOverlapShieldPlanes[ta][tb]; + if (ov.o_pmask) + { + ov.o_tmask = e->ec_far; /* Actually shieldtypes. */ + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + /* Each call to DBSrPaintArea has an opportunity to + * subtract from the area (really length 'cause width=1. + */ + if (!PlaneMaskHasPlane(ov.o_pmask, pNum)) continue; + ov.o_pmask &= ~(PlaneNumToMaskBit(pNum)); + if (ov.o_pmask == 0) + { + (void) DBSrPaintArea((Tile *) NULL, + extOverlapDef->cd_planes[pNum], &ov.o_clip, + &ov.o_tmask, extSubtractOverlap, (ClientData) &ov); + } + else + { + (void) DBSrPaintArea((Tile *) NULL, + extOverlapDef->cd_planes[pNum], &ov.o_clip, + &DBAllTypeBits, + extSubtractOverlap2, (ClientData) &ov); + } + break; + } + } + if (rtp != rbp) + cap += e->ec_cap * ov.o_area; + areaAccountedFor += ov.o_area; + } + } + + /* Add in the new capacitance. */ + if (tb == TT_SPACE) + { + /* Is tp a space tile? If so, extGetRegion points to garbage; + * make terminal 2 point to ground. + */ + rbp->nreg_cap += cap; + if (CAP_DEBUG) extNregAdjustCap(rbp, cap, "sideoverlap_to_subs"); + } + else + { + int oa = ExtCurStyle->exts_planeOrder[esws->plane_of_boundary]; + int ob = ExtCurStyle->exts_planeOrder[esws->plane_checked]; + if (oa > ob) + { + /* If the overlapped tile is between the substrate and the boundary + * tile, then we subtract the fringe substrate capacitance + * from rbp's region due to the area of the sideoverlap, since + * we now know it is shielded from the substrate. + */ + CapValue subcap; + TileType outtype = TiGetType(bp->b_outside); + + /* Decompose contacts into their residues */ + if (DBIsContact(ta)) + ta = DBPlaneToResidue(ta, esws->plane_of_boundary); + if (DBIsContact(outtype)) + outtype = DBPlaneToResidue(outtype, esws->plane_of_boundary); + + subcap = (ExtCurStyle->exts_perimCap[ta][outtype] * + MIN(areaAccountedFor, length)); + rbp->nreg_cap -= subcap; + if (CAP_DEBUG) + extNregAdjustCap(rbp, -subcap, "obsolete_perimcap"); + } else if (CAP_DEBUG) + extNregAdjustCap(rbp, 0.0, + "obsolete_perimcap (skipped, wrong direction)"); + + /* If the nodes are electrically connected, then we don't add */ + /* any side overlap capacitance to the node. */ + if (rtp == rbp) return (0); + + if (rtp < rbp) ck.ck_1 = rtp, ck.ck_2 = rbp; + else ck.ck_1 = rbp, ck.ck_2 = rtp; + he = HashFind(extCoupleHashPtr, (char *) &ck); + if (CAP_DEBUG) extAdjustCouple(he, cap, "sideoverlap"); + extSetCapValue(he, cap + extGetCapValue(he)); + } + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extSideLeft -- + * + * Searching to the left of the boundary 'bp', we found the tile + * 'tpfar' which may lie on the far side of an edge to which the + * edge bp->b_inside | bp->b_outside has sidewall coupling capacitance. + * + * Walk along the right-hand side of 'tpfar' searching for such + * edges, and recording their capacitance in the hash table + * *extCoupleHashPtr. + * + * Results: + * Returns 0 always. + * + * Side effects: + * If node(tpfar) exists, and node(bp->b_inside) != node(tpfar), + * search along the inside edge of tpfar (the one closest to + * the boundary bp) for edges having capacitance with bp. For + * each such edge found, update the entry in *extCoupleHashPtr + * identified by node(bp->b_inside) and node(tpfar) by adding + * the capacitance due to the adjacency of the pair of edges. + * + * ---------------------------------------------------------------------------- + */ + +int +extSideLeft(tpfar, bp) + Tile *tpfar; + Boundary *bp; +{ + NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); + NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); + Tile *tpnear; + + if (rfar != (NodeRegion *) extUnInit && rfar != rinside) + { + int sep = bp->b_segment.r_xbot - RIGHT(tpfar); + int limit = MAX(bp->b_segment.r_ybot, BOTTOM(tpfar)); + int start = MIN(bp->b_segment.r_ytop, TOP(tpfar)); + + for (tpnear = TR(tpfar); TOP(tpnear) > limit; tpnear = LB(tpnear)) + { + int overlap = MIN(TOP(tpnear), start) - MAX(BOTTOM(tpnear), limit); + + if (overlap > 0) + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); + } + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extSideRight -- + * + * Searching to the right of the boundary 'bp', we found the tile + * 'tpfar' which may lie on the far side of an edge to which the + * edge bp->b_inside | bp->b_outside has sidewall coupling capacitance. + * + * Walk along the left-hand side of 'tpfar' searching for such + * edges, and recording their capacitance in the hash table + * *extCoupleHashPtr. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See extSideLeft. + * + * ---------------------------------------------------------------------------- + */ + +int +extSideRight(tpfar, bp) + Tile *tpfar; + Boundary *bp; +{ + NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); + NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); + Tile *tpnear; + + if (rfar != (NodeRegion *) extUnInit && rfar != rinside) + { + int sep = LEFT(tpfar) - bp->b_segment.r_xtop; + int limit = MIN(bp->b_segment.r_ytop, TOP(tpfar)); + int start = MAX(bp->b_segment.r_ybot, BOTTOM(tpfar)); + + for (tpnear = BL(tpfar); BOTTOM(tpnear) < limit; tpnear = RT(tpnear)) + { + int overlap = MIN(TOP(tpnear), limit) - MAX(BOTTOM(tpnear), start); + + if (overlap > 0) + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); + } + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extSideTop -- + * + * Searching to the top of the boundary 'bp', we found the tile + * 'tpfar' which may lie on the far side of an edge to which the + * edge bp->b_inside | bp->b_outside has sidewall coupling capacitance. + * + * Walk along the bottom side of 'tpfar' searching for such + * edges, and recording their capacitance in the hash table + * *extCoupleHashPtr. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See extSideLeft. + * + * ---------------------------------------------------------------------------- + */ + +int +extSideTop(tpfar, bp) + Tile *tpfar; + Boundary *bp; +{ + NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); + NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); + Tile *tpnear; + + if (rfar != (NodeRegion *) extUnInit && rfar != rinside) + { + int sep = BOTTOM(tpfar) - bp->b_segment.r_ytop; + int limit = MIN(bp->b_segment.r_xtop, RIGHT(tpfar)); + int start = MAX(bp->b_segment.r_xbot, LEFT(tpfar)); + + for (tpnear = LB(tpfar); LEFT(tpnear) < limit; tpnear = TR(tpnear)) + { + int overlap = MIN(RIGHT(tpnear), limit) - MAX(LEFT(tpnear), start); + + if (overlap > 0) + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); + } + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extSideBottom -- + * + * Searching to the bottom of the boundary 'bp', we found the tile + * 'tpfar' which may lie on the far side of an edge to which the + * edge bp->b_inside | bp->b_outside has sidewall coupling capacitance. + * + * Walk along the top side of 'tpfar' searching for such + * edges, and recording their capacitance in the hash table + * *extCoupleHashPtr. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See extSideLeft. + * + * ---------------------------------------------------------------------------- + */ + +int +extSideBottom(tpfar, bp) + Tile *tpfar; + Boundary *bp; +{ + NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); + NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); + Tile *tpnear; + + if (rfar != (NodeRegion *) extUnInit && rfar != rinside) + { + int sep = bp->b_segment.r_ybot - TOP(tpfar); + int limit = MAX(bp->b_segment.r_xbot, LEFT(tpfar)); + int start = MIN(bp->b_segment.r_xtop, RIGHT(tpfar)); + + for (tpnear = RT(tpfar); RIGHT(tpnear) > limit; tpnear = BL(tpnear)) + { + int overlap = MIN(RIGHT(tpnear), start) - MAX(LEFT(tpnear), limit); + + if (overlap > 0) + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); + } + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extSideCommon -- + * + * Perform the actual update to the hash table entry for + * the regions 'rinside' and 'rfar'. We assume that neither + * 'rinside' nor 'rfar' are extUnInit, and further that they + * are not equal. + * + * Walk along the rules in extCoupleList, applying the appropriate + * amount of capacitance for an edge with tpnear on the close side + * and tpfar on the remote side. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See extSideLeft. + * + * ---------------------------------------------------------------------------- + */ + +void +extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep) + NodeRegion *rinside, *rfar; /* Both must be valid */ + Tile *tpnear, *tpfar; /* Tiles on near and far side of edge */ + int overlap, sep; /* Overlap of this edge with original one, + * and distance between the two. + */ +{ + TileType near = TiGetType(tpnear), far = TiGetType(tpfar); + HashEntry *he; + EdgeCap *e; + CoupleKey ck; + CapValue cap; + + if (rinside < rfar) ck.ck_1 = rinside, ck.ck_2 = rfar; + else ck.ck_1 = rfar, ck.ck_2 = rinside; + he = HashFind(extCoupleHashPtr, (char *) &ck); + + cap = extGetCapValue(he); + for (e = extCoupleList; e; e = e->ec_next) + if (TTMaskHasType(&e->ec_near, near) && TTMaskHasType(&e->ec_far, far)) { + cap += (e->ec_cap * overlap) / sep; + if (CAP_DEBUG) + extAdjustCouple(he, (e->ec_cap * overlap) / sep, "sidewall"); + } + extSetCapValue(he, cap); +} diff --git a/extract/ExtHard.c b/extract/ExtHard.c new file mode 100644 index 00000000..5e92aaa6 --- /dev/null +++ b/extract/ExtHard.c @@ -0,0 +1,504 @@ +/* + * ExtHard.c -- + * + * Circuit extraction. + * Procedures for finding the name of a node during hierarchical + * extraction, when no label for that node could be found in the + * interaction area. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtHard.c,v 1.2 2010/06/24 12:37:17 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "utils/styles.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/geofast.h" + +/* Forward declarations */ + +void extHardFreeAll(); +bool extHardGenerateLabel(); +bool extHardSetLabel(); + +/* + * ---------------------------------------------------------------------------- + * + * extLabFirst -- + * extLabEach -- + * + * Filter functions passed to ExtFindRegions when tracing out extended + * label regions as part of hierarchical circuit extraction. We use the + * TransRegion record because it allows us to save a pointer to a tile + * along with the usual LabRegion data. Since treg_area is not needed, + * we use it to store the plane of the tile. + * + * Results: + * extLabFirst returns a pointer to a new TransRegion. + * extLabEach returns NULL. + * + * Side effects: + * Memory is allocated by extLabFirst. + * We cons the newly allocated region onto the front of the existing + * region list. + * + * ---------------------------------------------------------------------------- + */ + +Region * +extLabFirst(tile, arg) + Tile *tile; + FindRegion *arg; +{ + TransRegion *reg; + reg = (TransRegion *) mallocMagic((unsigned) (sizeof (TransRegion))); + reg->treg_next = (TransRegion *) NULL; + reg->treg_labels = (LabelList *) NULL; + reg->treg_pnum = DBNumPlanes; + reg->treg_area = DBNumPlanes; + reg->treg_tile = tile; + + /* Prepend it to the region list */ + reg->treg_next = (TransRegion *) arg->fra_region; + arg->fra_region = (Region *) reg; + return ((Region *) reg); +} + + /*ARGSUSED*/ +int +extLabEach(tile, pNum, arg) + Tile *tile; + int pNum; + FindRegion *arg; +{ + TransRegion *reg = (TransRegion *) arg->fra_region; + + /* Avoid setting the region's tile pointer to a split tile if we can */ + if (IsSplit(reg->treg_tile) && !IsSplit(tile)) + { + reg->treg_tile = tile; + reg->treg_area = pNum; + } + + if (reg->treg_area == DBNumPlanes) reg->treg_area = pNum; + extSetNodeNum((LabRegion *)reg, pNum, tile); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHardProc -- + * + * Called for each cell use in a tree. We determine if there is any + * geometry in this cell whose type is in the mask arg->hw_mask and + * whose node name we can determine. + * + * If so, we set arg->hw_label to point to a newly allocated Label whose + * name is the full hierarchical path of the node name we just found, and + * whose location (lab_rect) lies within the geometry of the node, but has + * been transformed to root coordinates by scx->scx_trans. + * + * Several fields in the HardWay struct pointed to by 'arg' control + * the details of how we assign a label: + * + * arg->hw_prefix If this is FALSE, we are responsible for constructing + * the full hierarchical pathname for the generated label + * starting from the immediate children of the root cell + * ha->ha_parentUse->cu_def. We do this by appending + * the use-id of scx->scx_use to arg->hw_tpath before + * appending the final component of the label name to + * arg->hw_tpath. + * + * If TRUE, we are responsible only for appending segments + * to arg->hw_tpath for grandchildren of the root cell and + * their descendants; the caller is responsible for the + * initial part of the pathname. + * + * arg->hw_autogen If FALSE, attempt to find an existing label for the + * geometry in the node. + * + * If TRUE, generate a label from the canonical nodename + * for the first piece of geometry we find. + * + * Results: + * Returns 0 if the caller (DBCellSrArea) should keep going, + * or 1 if we've succeeded and the caller may return. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +extHardProc(scx, arg) + SearchContext *scx; /* Context of the search to this cell */ + HardWay *arg; /* See above; this structure provides both + * options to govern how we generate labels + * and a place to store the label we return. + */ +{ + HierExtractArg *ha = arg->hw_ha; + bool isTopLevel = (scx->scx_use->cu_parent == ha->ha_parentUse->cu_def); + CellDef *def = scx->scx_use->cu_def; + TransRegion *reg; + TransRegion *labRegList; + char *savenext; + int ret = 0; + + /* + * Build up next component of label path. + * If the caller has already taken care of generating a prefix + * for immediate children of the root cell, arg->hw_prefix will + * have been set to FALSE. + */ + savenext = arg->hw_tpath.tp_next; /* Will be restored before we return */ + if (arg->hw_prefix || !isTopLevel) + { + arg->hw_tpath.tp_next = + DBPrintUseId(scx, savenext, arg->hw_tpath.tp_last - savenext, + FALSE); + *arg->hw_tpath.tp_next++ = '/'; + *arg->hw_tpath.tp_next = '\0'; + } + + /* + * We use a TransRegion because it holds both a LabelList + * and a tile pointer, and call extLabEach to make sure + * that treg_pnum and treg_ll are kept up-to-date (so we + * can generate a node label if none is found). + * + * The call below may return several TransRegions, as when + * geometry in a parent overlaps two different nodes in a + * single child. + */ + labRegList = (TransRegion *) ExtFindRegions(def, &scx->scx_area, + &arg->hw_mask, ExtCurStyle->exts_nodeConn, extUnInit, + extLabFirst, extLabEach); + if (labRegList) + { + /* + * If labels are being generated automatically on this pass, + * we don't bother to assign labels to geometry. Instead, we + * construct a new label based on the lower-leftmost tile in + * the Region labRegList. + */ + if (arg->hw_autogen) + { + (void) extHardGenerateLabel(scx, labRegList, arg); + goto success; + } + + /* + * Assign labels to LabRegions. + * Tiles in 'def' that belong to nodes other than those in labRegList + * will have uninitialized region pointers, and so will not have labels + * assigned to them. + */ + // ExtLabelRegions(def, ExtCurStyle->exts_nodeConn, &labRegList, + // &scx->scx_area); + ExtLabelRegions(def, ExtCurStyle->exts_nodeConn, NULL, NULL); + + /* Now try to find a region with a node label */ + for (reg = labRegList; reg; reg = reg->treg_next) + if (reg->treg_labels && extHardSetLabel(scx, reg, arg)) + goto success; + + /* No luck; it's as though there was no geometry at all */ + extHardFreeAll(def, labRegList); + } + + /* No luck; check our subcells recursively */ + ret = DBCellSrArea(scx, extHardProc, (ClientData) arg); + arg->hw_tpath.tp_next = savenext; + goto done; + +success: + extHardFreeAll(def, labRegList); + ret = 1; + +done: + return (ret); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHardSetLabel -- + * + * We found a LabRegion, 'reg', that has a label list. + * Walk down its label list looking for a node label. + * If we find one, append it to the TerminalPath we've + * been constructing from the root, make a new label + * whose text is this full pathname, and assign it to + * arg->hw_label. + * + * The coordinates of the result label are those of + * the node label we find, transformed by scx->scx_trans + * to lie in the root. + * + * Results: + * Returns TRUE if we found a node label, FALSE if not. + * + * Side effects: + * If successful, allocates a new Label struct as described + * above, and assigns it to arg->hw_label. + * + * ---------------------------------------------------------------------------- + */ + +bool +extHardSetLabel(scx, reg, arg) + SearchContext *scx; /* We use scx->scx_trans to transform label + * coordinates in the def scx->scx_use->cu_def + * up to root coordinates. + */ + TransRegion *reg; /* Region with a label list */ + HardWay *arg; /* We will set arg->hw_label if a node + * label is found on the label list of 'reg'. + */ +{ + TerminalPath *tpath = &arg->hw_tpath; + Label *oldlab, *newlab; + char *srcp, *dstp; + LabelList *ll; + int prefixlen; + char *text; + int len; + Rect r; + int pNum; + Tile *tp; + + for (ll = reg->treg_labels; ll; ll = ll->ll_next) + if (extLabType(ll->ll_label->lab_text, LABTYPE_NAME)) break; + + if (ll == (LabelList *) NULL) + return (FALSE); + oldlab = ll->ll_label; + + /* Compute length of new label */ + prefixlen = tpath->tp_next - tpath->tp_first; + len = strlen(oldlab->lab_text) + prefixlen; + + /* Allocate a Label big enough to hold the complete path */ + newlab = (Label *) mallocMagic((unsigned) (sizeof (Label) + len - 3)); + r=oldlab->lab_rect; + if (!GEO_SURROUND(&scx->scx_area,&r)) + { + GEOCLIP(&r,&scx->scx_area); + + pNum = DBPlane(oldlab->lab_type); + tp = scx->scx_use->cu_def->cd_planes[pNum]->pl_hint; + GOTOPOINT(tp, &r.r_ll); + scx->scx_use->cu_def->cd_planes[pNum]->pl_hint = tp; + if ((TransRegion *)extGetRegion(tp) == reg) + { + /* found an OK point */ + r.r_ur.p_x =r.r_ll.p_x+1; + r.r_ur.p_y =r.r_ll.p_y+1; + } + else + { + GOTOPOINT(tp, &r.r_ur); + if ((TransRegion *)extGetRegion(tp) == reg) + { + r.r_ll = r.r_ur; + } + else + { + /* forget it; we're never going to find the damn thing */ + r=oldlab->lab_rect; + } + + } + } + GeoTransRect(&scx->scx_trans, &r, &newlab->lab_rect); + newlab->lab_type = oldlab->lab_type; + text = oldlab->lab_text; + + /* Don't care, really, which orientation the label has */ + newlab->lab_just = GEO_NORTH; + + /* Construct the text of the new label */ + dstp = newlab->lab_text; + if (prefixlen) + { + srcp = tpath->tp_first; + do { *dstp++ = *srcp++; } while (--prefixlen > 0); + } + srcp = text; + while (*dstp++ = *srcp++) /* Nothing */; + + arg->hw_label = newlab; + if (DebugIsSet(extDebugID, extDebHardWay)) + TxPrintf("Hard way: found label = \"%s\"\n", newlab->lab_text); + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHardGenerateLabel -- + * + * Generate a label automatically from reg->treg_pnum and + * reg->treg_ll according to the conventions used for node + * labels in ExtBasic.c. The label is prefixed with the + * TerminalPath we've been constructing from the root in + * arg->hw_tpath. + * + * The coordinates of the result label are those of reg->treg_tile->ti_ll, + * transformed by scx->scx_trans to lie in the root. + * + * Results: + * Always TRUE. + * + * Side effects: + * Allocates a new Label struct as described above, + * and assigns it to arg->hw_label. + * + * ---------------------------------------------------------------------------- + */ + +bool +extHardGenerateLabel(scx, reg, arg) + SearchContext *scx; /* We use scx->scx_trans to transform the + * generated label's coordinates up to + * root coordinates. + */ + TransRegion *reg; /* Region whose treg_ll and treg_pnum we use + * to generate a new label name. + */ + HardWay *arg; /* We set arg->hw_label to the new label */ +{ + TerminalPath *tpath = &arg->hw_tpath; + char *srcp, *dstp; + Label *newlab; + int prefixlen; + char gen[100]; + int len; + Rect r; + Point p; + + // Modification 9/9/2014 by Tim: + // Convert the treg_ll value up to top-level coordinates. + // Otherwise you end up with a node that is apparently in + // "canonical coordinates", but if you try to find the + // location of the node using the name, you'll end up in + // a random place. It also allows the low-probability + // but possible conflict between this node and another with + // the same name in the parent cell. + // + // Reverted 10/30/2014: Apparently this causes worse + // problems. + // + // GeoTransPoint(&scx->scx_trans, ®->treg_ll, &r.r_ll); + // extMakeNodeNumPrint(gen, reg->treg_pnum, r.r_ll); + + extMakeNodeNumPrint(gen, reg->treg_pnum, reg->treg_ll); + + prefixlen = tpath->tp_next - tpath->tp_first; + len = strlen(gen) + prefixlen; + newlab = (Label *) mallocMagic((unsigned) (sizeof (Label) + len - 3)); + r.r_ll = reg->treg_tile->ti_ll; + GEOCLIP(&r,&scx->scx_area); + r.r_ur.p_x = r.r_ll.p_x+1; + r.r_ur.p_y = r.r_ll.p_y+1; + GeoTransRect(&scx->scx_trans, &r, &newlab->lab_rect); + newlab->lab_type = TiGetType(reg->treg_tile); + + /* Don't care, really, which orientation the label has */ + newlab->lab_just = GEO_NORTH; + + /* Mark this as a generated label; may or may not be useful */ + newlab->lab_flags = LABEL_GENERATE; + + /* Construct the text of the new label */ + dstp = newlab->lab_text; + if (prefixlen) + { + srcp = tpath->tp_first; + do { *dstp++ = *srcp++; } while (--prefixlen > 0); + } + srcp = gen; + while (*dstp++ = *srcp++) /* Nothing */; + arg->hw_label = newlab; + if (DebugIsSet(extDebugID, extDebHardWay)) + TxPrintf("Hard way: generated label = \"%s\"\n", newlab->lab_text); + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHardFreeAll -- + * + * Reset all the ti_client fields that we set in 'def' that + * were set to point to regions in the list 'tReg' of TransRegions. + * Then free all the regions in 'tReg'. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extHardFreeAll(def, tReg) + CellDef *def; + TransRegion *tReg; +{ + TransRegion *reg; + LabelList *ll; + FindRegion arg; + + /* Don't need to initialize arg.fra_first below */ + arg.fra_connectsTo = ExtCurStyle->exts_nodeConn; + arg.fra_def = def; + arg.fra_each = (int (*)()) NULL; + arg.fra_region = (Region *) extUnInit; + + for (reg = tReg; reg; reg = reg->treg_next) + { + /* Reset all ti_client fields to extUnInit */ + arg.fra_uninit = (ClientData) reg; + if (reg->treg_tile) + { + arg.fra_pNum = reg->treg_area; + ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); + } + + /* Free all LabelLists and then the region */ + for (ll = reg->treg_labels; ll; ll = ll->ll_next) + freeMagic((char *) ll); + freeMagic((char *) reg); + } +} diff --git a/extract/ExtHier.c b/extract/ExtHier.c new file mode 100644 index 00000000..f08a6e18 --- /dev/null +++ b/extract/ExtHier.c @@ -0,0 +1,909 @@ +/* + * ExtHier.c -- + * + * Circuit extraction. + * Lower-level procedures common both to ordinary subtree extraction, + * and to array extraction. + * The procedures in this file are not re-entrant. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtHier.c,v 1.3 2010/06/24 12:37:17 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "utils/styles.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" + +/* Local data */ + + /* Passed to search functions by extHierConnections */ +ExtTree *extHierCumFlat; /* Cum buffer */ +ExtTree *extHierOneFlat; /* Subtree being compared with extHierCumFlat */ + + /* List of free cells around for use in yanking subtrees */ +ExtTree *extHierFreeOneList = (ExtTree *) NULL; + + /* Appended to the name of each new CellDef created by extHierNewOne() */ +int extHierOneNameSuffix = 0; + +/* Forward declarations */ +int extHierConnectFunc1(); +int extHierConnectFunc2(); +int extHierConnectFunc3(); +Node *extHierNewNode(); + + +/*----------------------------------------------*/ +/* extHierSubstrate */ +/* */ +/* Find the substrate node of a child cell and */ +/* make a connection between parent and child */ +/* substrates. If either of the substrate */ +/* nodes is already in the hash table, then the */ +/* table will be updated as necessary. */ +/*----------------------------------------------*/ + +void +extHierSubstrate(ha, use, x, y) + HierExtractArg *ha; // Contains parent def and hash table + CellUse *use; // Child use + int x, y; // Array subscripts, or -1 if not an array +{ + NodeRegion *nodeList; + HashTable *table = &ha->ha_connHash; + HashEntry *he; + NodeName *nn; + Node *node1, *node2; + char *name1, *name2, *childname; + CellDef *def; + + NodeRegion *extFindNodes(); + + /* Backwards compatibility with tech files that don't */ + /* define a substrate plane or substrate connections. */ + if (glob_subsnode == NULL) return; + + def = (CellDef *)ha->ha_parentUse->cu_def; + + /* Register the name of the parent's substrate */ + /* The parent def's substrate node is in glob_subsnode */ + + name1 = extNodeName(glob_subsnode); + he = HashFind(table, name1); + nn = (NodeName *) HashGetValue(he); + node1 = nn ? nn->nn_node : extHierNewNode(he); + + /* Find the child's substrate node */ + nodeList = extFindNodes(use->cu_def, (Rect *) NULL, TRUE); + + /* Make sure substrate labels are represented */ + ExtLabelRegions(use->cu_def, ExtCurStyle->exts_nodeConn, &nodeList, + &TiPlaneRect); + + ExtResetTiles(use->cu_def, extUnInit); + + name2 = extNodeName(temp_subsnode); + + if (x >= 0 && y >= 0) + { + /* Process array information */ + childname = mallocMagic(strlen(name2) + strlen(use->cu_id) + 14); + sprintf(childname, "%s[%d,%d]/%s", use->cu_id, y, x, name2); + } + else if (x >= 0 || y >= 0) + { + childname = mallocMagic(strlen(name2) + strlen(use->cu_id) + 9); + sprintf(childname, "%s[%d]/%s", use->cu_id, ((x >= 0) ? x : y), + name2); + } + else + { + childname = mallocMagic(strlen(name2) + strlen(use->cu_id) + 2); + sprintf(childname, "%s/%s", use->cu_id, name2); + } + he = HashFind(table, childname); + nn = (NodeName *) HashGetValue(he); + node2 = nn ? nn->nn_node : extHierNewNode(he); + + freeMagic(childname); + + if (node1 != node2) + { + /* + * Both sets of names will now point to node1. + */ + for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next) + nn->nn_node = node1; + nn->nn_node = node1; + nn->nn_next = node1->node_names; + node1->node_names = node2->node_names; + freeMagic((char *) node2); + } + freeMagic(nodeList); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHierConnections -- + * + * Process connections between the two ExtTrees 'oneFlat' and 'cumFlat'. + * This consists of detecting overlaps or abutments between connecting + * tiles (maybe on different planes), and recording the connection in the hash + * table ha->ha_connHash. + * + * Results: + * None. + * + * Side effects: + * Adds connections to ha->ha_connHash. + * Doesn't change resistance or capacitance of the connected + * nodes; that is the job of extHierAdjustments(). + * + * ---------------------------------------------------------------------------- + */ + +void +extHierConnections(ha, cumFlat, oneFlat) + HierExtractArg *ha; + ExtTree *cumFlat, *oneFlat; +{ + int pNum; + CellDef *sourceDef = oneFlat->et_use->cu_def; + Label *lab; + + extHierCumFlat = cumFlat; + extHierOneFlat = oneFlat; + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + ha->hierPNum = pNum; + (void) DBSrPaintArea((Tile *) NULL, + sourceDef->cd_planes[pNum], &ha->ha_subArea, + &DBAllButSpaceBits, extHierConnectFunc1, (ClientData) ha); + } + + /* Look for sticky labels in the child cell that are not */ + /* connected to any geometry. */ + + for (lab = sourceDef->cd_labels; lab; lab = lab->lab_next) + { + CellDef *cumDef = cumFlat->et_use->cu_def; + Rect r = lab->lab_rect; + TileTypeBitMask *connected = &DBConnectTbl[lab->lab_type]; + int i = DBPlane(lab->lab_type); + + ha->hierOneTile = (Tile *)lab; /* Blatant hack recasting */ + ha->hierType = lab->lab_type; + ha->hierPNumBelow = i; + + GEOCLIP(&r, &ha->ha_subArea); + if (lab->lab_flags & LABEL_STICKY) + DBSrPaintArea((Tile *) NULL, + cumFlat->et_use->cu_def->cd_planes[i], &r, + connected, extHierConnectFunc3, (ClientData) ha); + } +} + +/* + * extHierConnectFunc1 -- + * + * Called for each tile 'oneTile' in the ExtTree 'oneFlat' above + * that lies in the area ha->ha_subArea. + * + * Results: + * Returns 0 always. + * + * Side effects: + * None here, but see extHierConnectFunc2(). + */ + +int +extHierConnectFunc1(oneTile, ha) + Tile *oneTile; /* Comes from 'oneFlat' in extHierConnections */ + HierExtractArg *ha; /* Extraction context */ +{ + CellDef *cumDef = extHierCumFlat->et_use->cu_def; + Rect r; + TileTypeBitMask mask, *connected; + TileType rtype; + Label *lab, *newlab; + int i; + unsigned n; + + /* + * Find all tiles that connect to 'srcTile', but in the + * yank buffer cumDef. Adjust connectivity for each tile found. + * Widen the rectangle to detect connectivity by abutment. + */ + ha->hierOneTile = oneTile; + ha->hierType = TiGetTypeExact(oneTile); + + if (IsSplit(oneTile)) + { + rtype = ha->hierType; + ha->hierType = (rtype & TT_SIDE) ? SplitRightType(oneTile) : + SplitLeftType(oneTile); + } + + connected = &(ExtCurStyle->exts_nodeConn[ha->hierType]); + TITORECT(oneTile, &r); + GEOCLIP(&r, &ha->ha_subArea); + r.r_xbot--, r.r_ybot--, r.r_xtop++, r.r_ytop++; + for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) + { + ha->hierPNumBelow = i; + TTMaskAndMask3(&mask, connected, &DBPlaneTypes[i]); + if (!TTMaskIsZero(&mask)) + { + if (IsSplit(oneTile)) + DBSrPaintNMArea((Tile *) NULL, cumDef->cd_planes[i], + rtype, &r, + ((i == ha->hierPNum) ? &ExtCurStyle->exts_activeTypes + : connected), extHierConnectFunc2, (ClientData) ha); + else + DBSrPaintArea((Tile *) NULL, cumDef->cd_planes[i], &r, + ((i == ha->hierPNum) ? &ExtCurStyle->exts_activeTypes + : connected), extHierConnectFunc2, (ClientData) ha); + } + } + + /* Where labels have been saved from the parent cell, look for any */ + /* that are inside the cell boundary and would connect to the tile. */ + /* This allows the extractor to catch "sticky" labels that are not */ + /* attached to a physical layer in the parent cell. */ + + // NOTE by Tim, 9/10/2014: This generates phantom nodes when the + // labels are created by the "hard" node search; I think this code + // should be restricted to sticky labels only. But not certain. + // Definitely this causes problems in arrays, because the array node + // name may refer to a range of array elements, and the generated + // node only describes a single point. + + for (lab = cumDef->cd_labels; lab; lab = lab->lab_next) + if (GEO_TOUCH(&r, &lab->lab_rect) && (lab->lab_flags & LABEL_STICKY)) + if (TTMaskHasType(connected, lab->lab_type)) + { + HashTable *table = &ha->ha_connHash; + HashEntry *he; + NodeName *nn; + Node *node1, *node2; + char *name; + + /* Register the name, like is done in extHierConnectFunc2 */ + he = HashFind(table, lab->lab_text); + nn = (NodeName *) HashGetValue(he); + node1 = nn ? nn->nn_node : extHierNewNode(he); + + name = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum, + extHierOneFlat, ha, TRUE); + he = HashFind(table, name); + nn = (NodeName *) HashGetValue(he); + node2 = nn ? nn->nn_node : extHierNewNode(he); + + if (node1 != node2) + { + /* + * Both sets of names will now point to node1. + * We don't need to update node_cap since it + * hasn't been computed yet. + */ + for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next) + nn->nn_node = node1; + nn->nn_node = node1; + nn->nn_next = node1->node_names; + node1->node_names = node2->node_names; + freeMagic((char *) node2); + } + +#if 0 + /* Copy this label to the parent def with a */ + /* special flag, so we can output it as a node */ + /* and then delete it. Don't duplicate labels */ + /* that are already in the parent. */ + + for (newlab = ha->ha_parentUse->cu_def->cd_labels; + newlab; newlab = newlab->lab_next) + if (!strcmp(newlab->lab_text, lab->lab_text)) + break; + + if (newlab == NULL) + { + n = sizeof(Label) + strlen(lab->lab_text) + - sizeof lab->lab_text + 1; + newlab = (Label *)mallocMagic((unsigned)n); + bcopy((char *)lab, (char *)newlab, (int)n); + + newlab->lab_next = ha->ha_parentUse->cu_def->cd_labels; + ha->ha_parentUse->cu_def->cd_labels = newlab; + } +#endif + } + + return (0); +} + +/* + * extHierConnectFunc2 -- + * + * Called once for each tile 'cum' in extHierCumFlat->et_use->cu_def + * on the same plane as ha->hierOneTile that also overlaps or abuts + * the intersection of ha->hierOneTile with ha->ha_subArea, and for tiles + * in other planes that may connect. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Makes a connection between the nodes of the two tiles + * if the types of ha->hierOneTile and 'cum' connect. + * Otherwise, if the tiles actually overlap (as opposed + * to merely abut), mark it with feedback as an error. + */ + +int +extHierConnectFunc2(cum, ha) + Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */ + HierExtractArg *ha; /* Extraction context */ +{ + HashTable *table = &ha->ha_connHash; + Node *node1, *node2; + TileType ttype; + HashEntry *he; + NodeName *nn; + char *name; + Rect r; + + /* Compute the overlap area */ + r.r_xbot = MAX(LEFT(ha->hierOneTile), LEFT(cum)); + r.r_xtop = MIN(RIGHT(ha->hierOneTile), RIGHT(cum)); + r.r_ybot = MAX(BOTTOM(ha->hierOneTile), BOTTOM(cum)); + r.r_ytop = MIN(TOP(ha->hierOneTile), TOP(cum)); + + /* If the tiles don't even touch, they don't connect */ + if (r.r_xtop < r.r_xbot || r.r_ytop < r.r_ybot + || (r.r_xtop == r.r_xbot && r.r_ytop == r.r_ybot)) + return (0); + + /* + * Only make a connection if the types of 'ha->hierOneTile' and 'cum' + * connect. If they overlap and don't connect, it is an error. + * If they do connect, mark their nodes as connected. + */ + + ttype = TiGetTypeExact(cum); + + if (IsSplit(cum)) + ttype = (ttype & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum); + + if (extConnectsTo(ha->hierType, ttype, ExtCurStyle->exts_nodeConn)) + { + name = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE); + he = HashFind(table, name); + nn = (NodeName *) HashGetValue(he); + node1 = nn ? nn->nn_node : extHierNewNode(he); + + name = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum, extHierOneFlat, + ha, TRUE); + he = HashFind(table, name); + nn = (NodeName *) HashGetValue(he); + node2 = nn ? nn->nn_node : extHierNewNode(he); + + if (node1 != node2) + { + /* + * Both sets of names will now point to node1. + * We don't need to update node_cap since it + * hasn't been computed yet. + */ + for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next) + nn->nn_node = node1; + nn->nn_node = node1; + nn->nn_next = node1->node_names; + node1->node_names = node2->node_names; + freeMagic((char *) node2); + } + } + else if (r.r_xtop > r.r_xbot && r.r_ytop > r.r_ybot) + { + extNumFatal++; + if (!DebugIsSet(extDebugID, extDebNoFeedback)) + DBWFeedbackAdd(&r, "Illegal overlap (types do not connect)", + ha->ha_parentUse->cu_def, 1, STYLE_MEDIUMHIGHLIGHTS); + } + + return (0); +} + +/* + * extHierConnectFunc3 -- + * + * Called once for each tile 'cum' in extHierCumFlat->et_use->cu_def + * Similar to extHierConnectFunc2, but is called for a label in the + * parent cell that does not necessarily have associated geometry. + * Value passed in ha_oneTile is the label (recast for convenience; + * need to use a union type in HierExtractArg). + */ + +int +extHierConnectFunc3(cum, ha) + Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */ + HierExtractArg *ha; /* Extraction context */ +{ + HashTable *table = &ha->ha_connHash; + Node *node1, *node2; + TileType ttype; + HashEntry *he; + NodeName *nn; + char *name; + Rect r; + Label *lab = (Label *)(ha->hierOneTile); /* Lazy recasting */ + + /* Compute the overlap area */ + r.r_xbot = MAX(lab->lab_rect.r_xbot, LEFT(cum)); + r.r_xtop = MIN(lab->lab_rect.r_xtop, RIGHT(cum)); + r.r_ybot = MAX(lab->lab_rect.r_ybot, BOTTOM(cum)); + r.r_ytop = MIN(lab->lab_rect.r_ytop, TOP(cum)); + + /* If the tiles don't even touch, they don't connect */ + if (r.r_xtop < r.r_xbot || r.r_ytop < r.r_ybot) + return (0); + + /* + * Only make a connection if the types of 'ha->hierOneTile' and 'cum' + * connect. If they overlap and don't connect, it is an error. + * If they do connect, mark their nodes as connected. + */ + + ttype = TiGetTypeExact(cum); + + if (IsSplit(cum)) + ttype = (ttype & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum); + + if (extConnectsTo(ha->hierType, ttype, ExtCurStyle->exts_nodeConn)) + { + name = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE); + he = HashFind(table, name); + nn = (NodeName *) HashGetValue(he); + node1 = nn ? nn->nn_node : extHierNewNode(he); + + name = lab->lab_text; + he = HashFind(table, name); + nn = (NodeName *) HashGetValue(he); + node2 = nn ? nn->nn_node : extHierNewNode(he); + + if (node1 != node2) + { + /* + * Both sets of names will now point to node1. + * We don't need to update node_cap since it + * hasn't been computed yet. + */ + for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next) + nn->nn_node = node1; + nn->nn_node = node1; + nn->nn_next = node1->node_names; + node1->node_names = node2->node_names; + freeMagic((char *) node2); + } + } + else if (r.r_xtop > r.r_xbot && r.r_ytop > r.r_ybot) + { + extNumFatal++; + if (!DebugIsSet(extDebugID, extDebNoFeedback)) + DBWFeedbackAdd(&r, "Illegal overlap (types do not connect)", + ha->ha_parentUse->cu_def, 1, STYLE_MEDIUMHIGHLIGHTS); + } + + return (0); +} +/* + * ---------------------------------------------------------------------------- + * + * extHierAdjustments -- + * + * Process adjustments to substrate capacitance, coupling capacitance, + * node perimeter, and node area between the subtree 'oneFlat' and the + * cumulative yank buffer 'cumFlat'. The subtree 'lookFlat' is used + * for looking up node names when handling capacitance/perimeter/area + * adjustment. + * + * Results: + * None. + * + * Side effects: + * Updates capacitance in the table cumFlat->et_coupleHash. + * Updates capacitance, perimeter, and area recorded in the + * nodes of 'cumFlat'. + * + * Algorithm: + * For each capacitor recorded in oneFlat->et_coupleHash, find + * the corresponding nodes in 'cumFlat' and subtract the + * capacitance from the entry indexed by these nodes in the + * table cumFlat->et_coupleHash. + * + * For each node in oneFlat->et_nodes, find the corresponding + * node in 'lookFlat'. Look for the Node with this name in + * the table ha->ha_connHash, and subtract the oneFlat node's + * capacitance, perimeter, and area from it. If no Node is + * found in this table, don't do anything since the oneFlat + * node must not participate in any connections. + * + * The node in 'cumFlat' corresponding to one in 'oneFlat' + * is the one containing some point in 'oneFlat', since 'oneFlat' + * is a strict subset of 'cumFlat'. + * + * ---------------------------------------------------------------------------- + */ + +void +extHierAdjustments(ha, cumFlat, oneFlat, lookFlat) + HierExtractArg *ha; + ExtTree *cumFlat, *oneFlat, *lookFlat; +{ + HashEntry *he, *heCum; + int n; + CoupleKey *ckpOne, ckCum; + NodeRegion *np; + HashSearch hs; + NodeName *nn; + Tile *tp; + char *name; + + /* Update all coupling capacitors */ + if (ExtOptions & EXT_DOCOUPLING) + { + HashStartSearch(&hs); + while (he = HashNext(&oneFlat->et_coupleHash, &hs)) + { + ckpOne = ((CoupleKey *) he->h_key.h_words); + + /* Find nodes in cumFlat->et_coupleHash */ + NODETONODE(ckpOne->ck_1, cumFlat, ckCum.ck_1); + NODETONODE(ckpOne->ck_2, cumFlat, ckCum.ck_2); + if (ckCum.ck_1 == NULL || ckCum.ck_2 == NULL) continue; + + /* Skip if the same; reverse to make smaller node pointer first */ + if (ckCum.ck_1 == ckCum.ck_2) continue; + if (ckCum.ck_2 < ckCum.ck_1) + np = ckCum.ck_1, ckCum.ck_1 = ckCum.ck_2, ckCum.ck_2 = np; + + /* Update the capacitor record in cumFlat->et_coupleHash */ + heCum = HashFind(&cumFlat->et_coupleHash, (char *) &ckCum); + extSetCapValue(heCum, extGetCapValue(heCum) - extGetCapValue(he)); + } + } + + /* + * Update all node values. + * Find the corresponding tile in the ExtTree lookFlat, then look + * for its name. If this name appear in the connection hash table, + * update the capacitance, perimeter, and area stored there; otherwise + * ignore it. + * + * The FALSE argument to (*ha->ha_nodename)() means that we don't bother + * looking for node names the hard way; if we didn't already have a valid + * node name then it couldn't appear in the table ha->ha_connHash in the + * first place. + */ + for (np = oneFlat->et_nodes; np; np = np->nreg_next) + { + /* Ignore orphaned nodes (non-Manhattan shards outside the clip box) */ + if (np->nreg_pnum == DBNumPlanes) continue; + + tp = extNodeToTile(np, lookFlat); + + /* Ignore regions that do not participate in extraction */ + if (!extHasRegion(tp, extUnInit)) continue; + + /* Ignore substrate nodes (failsafe: should not happen) */ + if (TiGetTypeExact(tp) == TT_SPACE) continue; + + if (tp && (name = (*ha->ha_nodename)(tp, np->nreg_pnum, lookFlat, ha, FALSE)) + && (he = HashLookOnly(&ha->ha_connHash, name)) + && (nn = (NodeName *) HashGetValue(he))) + { + /* Adjust the capacitance and resistance */ + nn->nn_node->node_cap -= np->nreg_cap; + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + { + nn->nn_node->node_pa[n].pa_perim -= np->nreg_pa[n].pa_perim; + nn->nn_node->node_pa[n].pa_area -= np->nreg_pa[n].pa_area; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extOutputConns -- + * + * Dump the contents of the hash table 'table' of connectivity and + * node R, C adjustments to the output file outf. + * + * Results: + * None. + * + * Side effects: + * Outputs a number of "merge" records to the file 'outf'. + * + * ---------------------------------------------------------------------------- + */ + +void +extOutputConns(table, outf) + HashTable *table; + FILE *outf; +{ + CapValue c; /* cap value */ + NodeName *nn, *nnext; + Node *node; + int n; + NodeName *nfirst; + HashSearch hs; + HashEntry *he; + + HashStartSearch(&hs); + while (he = HashNext(table, &hs)) + { + nfirst = (NodeName *) HashGetValue(he); + + /* + * If nfirst->nn_node == NULL, the name for this hash entry + * had been output previously as a member of the merge list + * for a node appearing earlier in the table. If so, we need + * only free the NodeName without any further processing. + */ + if (node = nfirst->nn_node) + { + /* + * If there are N names for this node, output N-1 merge lines. + * Only the first merge line will contain the C, perimeter, + * and area updates. + */ + /* Note 3/1/2017: Cap value no longer used */ + c = (node->node_cap) / ExtCurStyle->exts_capScale; + nn = node->node_names; + if (nnext = nn->nn_next) + { + /* First merge */ + fprintf(outf, "merge \"%s\" \"%s\" %lg", + nn->nn_name, nnext->nn_name, c); + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + fprintf(outf, " %d %d", + node->node_pa[n].pa_area, + node->node_pa[n].pa_perim); + fprintf(outf, "\n"); + + nn->nn_node = (Node *) NULL; /* Processed */ + + /* Subsequent merges */ + for (nn = nnext; nnext = nn->nn_next; nn = nnext) + { + fprintf(outf, "merge \"%s\" \"%s\"\n", + nn->nn_name, nnext->nn_name); + nn->nn_node = (Node *) NULL; /* Processed */ + } + } + nn->nn_node = (Node *) NULL; + freeMagic((char *) node); + } + freeMagic((char *) nfirst); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extHierNewNode -- + * + * Create a new NodeName and Node to go with the HashEntry supplied. + * The NodeName will point to the new Node, which will point back to the + * NodeName. + * + * Results: + * Returns a pointer to the newly created Node. + * + * Side effects: + * Allocates memory. + * Sets (via HashSetValue) the value of HashEntry 'he' to the + * newly created NodeName. + * + * ---------------------------------------------------------------------------- + */ + +Node * +extHierNewNode(he) + HashEntry *he; +{ + int n, nclasses; + NodeName *nn; + Node *node; + + nclasses = ExtCurStyle->exts_numResistClasses; + n = (nclasses - 1) * sizeof (PerimArea) + sizeof (Node); + nn = (NodeName *) mallocMagic((unsigned) (sizeof (NodeName))); + node = (Node *) mallocMagic((unsigned) n); + + nn->nn_node = node; + nn->nn_next = (NodeName *) NULL; + nn->nn_name = he->h_key.h_name; + node->node_names = nn; + node->node_cap = (CapValue) 0; + for (n = 0; n < nclasses; n++) + node->node_pa[n].pa_perim = node->node_pa[n].pa_area = 0; + HashSetValue(he, (char *) nn); + + return (node); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHierLabFirst -- + * extHierLabEach -- + * + * Filter functions passed to ExtFindRegions when tracing out labelled + * regions as part of a hierarchical circuit extraction. + * + * Results: + * extHierLabFirst returns a pointer to a new LabRegion. + * extHierLabEach returns 0 always. + * + * Side effects: + * Memory is allocated by extHierLabFirst(); it conses the newly + * allocated region onto the front of the existing region list. + * The node-naming info (reg_ll, reg_pnum) is updated by + * extHierLabEach(). + * + * ---------------------------------------------------------------------------- + */ + + /*ARGSUSED*/ +Region * +extHierLabFirst(tile, arg) + Tile *tile; + FindRegion *arg; +{ + LabRegion *new; + + new = (LabRegion *) mallocMagic((unsigned) (sizeof (LabRegion))); + new->lreg_next = (LabRegion *) NULL; + new->lreg_labels = (LabelList *) NULL; + new->lreg_pnum = DBNumPlanes; + + /* Prepend it to the region list */ + new->lreg_next = (LabRegion *) arg->fra_region; + arg->fra_region = (Region *) new; + + return ((Region *) new); +} + + /*ARGSUSED*/ +int +extHierLabEach(tile, pNum, arg) + Tile *tile; + int pNum; + FindRegion *arg; +{ + LabRegion *reg; + + reg = (LabRegion *) arg->fra_region; + extSetNodeNum(reg, pNum, tile); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHierNewOne -- + * + * Allocate a new ExtTree for use in hierarchical extraction. + * This ExtTree will be used to hold an entire flattened subtree. + * We try to return one from our free list if one exists; if none + * are left, we create a new CellDef and CellUse and allocate a + * new ExtTree. The new CellDef has a name of the form __EXTTREEn__, + * where 'n' is a small integer. + * + * The HashTable et_coupleHash will be initialized but empty. + * The node list et_nodes, the next pointer et_next, and the CellDef + * pointer et_lookNames will all be set to NULL. + * + * Results: + * Returns a pointer to a new ExtTree. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +ExtTree * +extHierNewOne() +{ + char defname[128]; + CellDef *dummy; + ExtTree *et; + + if (extHierFreeOneList) + { + et = extHierFreeOneList; + extHierFreeOneList = et->et_next; + } + else + { + et = (ExtTree *) mallocMagic((unsigned)(sizeof (ExtTree))); + (void) sprintf(defname, "__EXTTREE%d__", extHierOneNameSuffix++); + DBNewYank(defname, &et->et_use, &dummy); + } + + et->et_next = (ExtTree *) NULL; + et->et_lookNames = (CellDef *) NULL; + et->et_nodes = (NodeRegion *) NULL; + if (ExtOptions & EXT_DOCOUPLING) + HashInit(&et->et_coupleHash, 32, HashSize(sizeof (CoupleKey))); + return (et); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHierFreeOne -- + * + * Return an ExtTree allocated via extHierNewOne() above to the + * free list. Frees the HashTable et->et_coupleHash, any NodeRegions + * on the list et->et_nodes, any labels on the label list and any + * paint in the cell et->et_use->cu_def. + * + * Results: + * None. + * + * Side effects: + * See above. + * The caller should NOT use et->et_next after this procedure + * has returned. + * + * ---------------------------------------------------------------------------- + */ + +void +extHierFreeOne(et) + ExtTree *et; +{ + if (ExtOptions & EXT_DOCOUPLING) + extCapHashKill(&et->et_coupleHash); + if (et->et_nodes) ExtFreeLabRegions((LabRegion *) et->et_nodes); + extHierFreeLabels(et->et_use->cu_def); + DBCellClearDef(et->et_use->cu_def); + + et->et_next = extHierFreeOneList; + extHierFreeOneList = et; +} diff --git a/extract/ExtInter.c b/extract/ExtInter.c new file mode 100644 index 00000000..e0626faa --- /dev/null +++ b/extract/ExtInter.c @@ -0,0 +1,691 @@ +/* + * ExtInteraction.c -- + * + * Circuit extraction. + * Finds interaction areas. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtInter.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/undo.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "utils/styles.h" + + /* Local data */ +CellUse *extInterUse = (CellUse *) NULL; /* Subtree being processed */ +Plane *extInterPlane; /* Paint into this plane */ +int extInterHalo; /* Elements closer than this + * constitute an interaction. + */ +int extInterBloat; /* Bloat by this much when + * painting into result plane. + */ + + /* Forward declarations */ +int extInterOverlapSubtree(); +int extInterOverlapTile(); +int extInterSubtree(); +int extInterSubtreeClip(); +int extInterSubtreeElement(); +int extInterSubtreeTile(); +int extInterSubtreePaint(); + +#define BLOATBY(r, h) ( (r)->r_xbot -= (h), (r)->r_ybot -= (h), \ + (r)->r_xtop += (h), (r)->r_ytop += (h) ) + +/* + * ---------------------------------------------------------------------------- + * + * ExtFindInteractions -- + * + * Paint into the supplied tile plane 'resultPlane' TT_ERROR_P tiles + * for each area in the CellDef 'def' that must be processed for + * interactions. + * + * Each interaction arises from paint in two different subtrees + * being less than (but not equal to) 'halo' units away from + * each other. In this definition, a subtree refers to a single + * CellUse, which may be either a single cell or an entire array. + * + * If 'bloat' is non-zero, each interaction area is bloated by + * this amount when being painted into the result plane. + * + * Results: + * None. + * + * Side effects: + * Paints into the plane 'resultPlane'. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtFindInteractions(def, halo, bloatby, resultPlane) + CellDef *def; /* Find interactions among children of def */ + int halo; /* Interaction is elements closer than halo */ + int bloatby; /* Bloat each interaction area by this amount when + * painting into resultPlane. + */ + Plane *resultPlane; /* Paint interaction areas into this plane */ +{ + SearchContext scx; + + UndoDisable(); + extInterPlane = resultPlane; + extInterHalo = halo; + extInterBloat = bloatby; + extParentUse->cu_def = def; + scx.scx_use = extParentUse; + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = def->cd_bbox; + + /* + * Process each child subtree. + * This involves comparing all the paint in the subtree + * with all the paint in all other subtrees up to, but + * not including, the subtree under consideration. + */ + extInterUse = (CellUse *) NULL; + (void) extCellSrArea(&scx, extInterSubtree, (ClientData) NULL); + + /* + * Process parent paint if there were any subcells. + * We compare each paint rectangle with all the paint in + * all the subtrees, to see if there is an overlap. + */ + if (extInterUse) + { + extInterUse = (CellUse *) NULL; + (void) extCellSrArea(&scx, extInterSubtreePaint, (ClientData) def); + } + UndoEnable(); +} + +int +extInterSubtreePaint(scx, def) + SearchContext *scx; + CellDef *def; +{ + Rect r; + int pNum; + + r = scx->scx_use->cu_bbox; + BLOATBY(&r, extInterHalo); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &r, + &DBAllButSpaceAndDRCBits, extInterSubtreeTile, (ClientData) NULL); + + return (2); +} + +/* + * ---------------------------------------------------------------------------- + * + * extInterSubtree -- + * + * Called for each immediate child use of the cell being processed + * for interactions. Our job is to process all the paint in this + * use against all other subtrees overlapping this one. + * + * Results: + * Returns 2 to abort after the first array element. + * + * Side effects: + * Sets extInterUse to scx->scx_use. + * Children may paint into extInterPlane. + * + * ---------------------------------------------------------------------------- + */ + +int +extInterSubtree(scx) + SearchContext *scx; +{ + CellUse *oldUse = extInterUse; + SearchContext parentScx; + + extInterUse = scx->scx_use; + if (oldUse) + { + /* Find all other subtrees overlapping this cell */ + parentScx.scx_area = scx->scx_use->cu_bbox; + BLOATBY(&parentScx.scx_area, extInterHalo); + parentScx.scx_trans = GeoIdentityTransform; + parentScx.scx_use = extParentUse; + (void) extCellSrArea(&parentScx, extInterSubtreeClip, (ClientData) scx); + } + return (2); +} + +int +extInterSubtreeClip(overlapScx, scx) + SearchContext *overlapScx, *scx; +{ + Rect r, r2; + + /* Only search as far as extInterUse */ + if (overlapScx->scx_use == extInterUse) + return (2); + + /* + * Only process the overlap between overlapScx and scx, + * bloating both by extInterHalo. + */ + r = overlapScx->scx_use->cu_bbox; + BLOATBY(&r, extInterHalo); + r2 = scx->scx_use->cu_bbox; + BLOATBY(&r2, extInterHalo); + GEOCLIP(&r, &r2); + + (void) DBArraySr(scx->scx_use, &r, extInterSubtreeElement, + (ClientData) &r); + return (2); +} + +/* + * ---------------------------------------------------------------------------- + * + * extInterSubtreeElement -- + * + * Called for each element in the array forming the use passed to + * extInterSubtree(). See extInterSubtree() for comments. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See ExtFindInteractions. + * + * ---------------------------------------------------------------------------- + */ + +int +extInterSubtreeElement(use, trans, x, y, r) + CellUse *use; + Transform *trans; + int x, y; + Rect *r; +{ + SearchContext scx; + Transform tinv; + + scx.scx_use = use; + scx.scx_trans = *trans; + scx.scx_x = x; + scx.scx_y = y; + GEOINVERTTRANS(trans, &tinv); + GEOTRANSRECT(&tinv, r, &scx.scx_area); + (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, + extInterSubtreeTile, (ClientData) NULL); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extInterSubtreeTile -- + * + * Called for each tile in the subtree being processed by + * extInterSubtree(). Transform this tile to root coordinates, + * bloating by extInterHalo, and then call extInterOverlapSubtree + * to process all the other subtrees for paint overlapping + * this bloated area. If the argument 'cxp' is non-NULL, we + * use cxp->tc_scx->scx_trans to transform the area of tile to + * root coordinates; otherwise, we don't transform it at all. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See extInterOverlapTile. + * + * ---------------------------------------------------------------------------- + */ + +int +extInterSubtreeTile(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + SearchContext newscx; + Rect r; + + TITORECT(tile, &r); + BLOATBY(&r, extInterHalo); + if (cxp) + { + GEOTRANSRECT(&cxp->tc_scx->scx_trans, &r, &newscx.scx_area); + } + else newscx.scx_area = r; + newscx.scx_trans = GeoIdentityTransform; + newscx.scx_use = extParentUse; + (void) extCellSrArea(&newscx, extInterOverlapSubtree, (ClientData) NULL); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extInterOverlapSubtree -- + * + * Called for each subcell of the root that overlaps the piece + * of paint found by extInterSubtreeTile() above. We stop + * as soon as we see extInterUse; otherwise, search all the + * cells in the subtree rooted at scx->scx_use for paint + * overlapping scx->scx_area. + * + * Results: + * Returns 2 if we see extInterUse; otherwise, returns 0. + * + * Side effects: + * Paints into the plane 'resultPlane'; see extInterOverlapTile. + * + * ---------------------------------------------------------------------------- + */ + +int +extInterOverlapSubtree(scx) + SearchContext *scx; +{ + if (extInterUse == scx->scx_use) + return (2); + + (void) extTreeSrPaintArea(scx, extInterOverlapTile, (ClientData) NULL); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extInterOverlapTile -- + * + * Called for each piece of paint overlapping the piece found + * by extInterSubtreeTile(). Bloat the found piece by extInterHalo, + * then clip to the area of the overlapping piece of paint in root + * coordinates. If the result is non-empty, paint it into the + * plane extInterPlane. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into the plane 'resultPlane'. + * + * ---------------------------------------------------------------------------- + */ + +int +extInterOverlapTile(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + SearchContext *scx = cxp->tc_scx; + Rect r, rootr; + + TITORECT(tile, &r); + BLOATBY(&r, extInterHalo); + GEOCLIP(&r, &scx->scx_area); + if (GEO_RECTNULL(&r)) + return (0); + + GEOTRANSRECT(&scx->scx_trans, &r, &rootr); + BLOATBY(&rootr, extInterBloat); + DBPaintPlane(extInterPlane, &rootr, DBStdWriteTbl(TT_ERROR_P), + (PaintUndoInfo *) NULL); + + return (0); +} + +/* + *----------------------------------------------------------------------------- + * + * extTreeSrPaintArea -- + * + * Recursively search downward from the supplied CellUse for + * all paint tiles. + * + * The procedure should be of the following form: + * + * int + * func(tile, scx, cdata) + * Tile *tile; + * SearchContext *scx; + * ClientData cdata; + * { + * } + * + * The SearchContext is stored in cxp->tc_scx, and the user's arg is stored + * in cxp->tc_filter->tf_arg. + * + * In the above, the scx transform is the net transform from the coordinates + * of tile to "world" coordinates (or whatever coordinates the initial + * transform supplied to extTreeSrTiles was a transform to). Func returns + * 0 under normal conditions. If 1 is returned, it is a request to + * abort the search. + * + * *** WARNING *** + * + * The client procedure should not modify any of the paint planes in + * the cells visited by extTreeSrTiles, because we use DBSrPaintArea + * instead of TiSrArea as our paint-tile enumeration function. + * + * Results: + * 0 is returned if the search finished normally. 1 is returned + * if the search was aborted. + * + * Side effects: + * Whatever side effects are brought about by applying the + * procedure supplied. + * + *----------------------------------------------------------------------------- + */ + +int +extTreeSrPaintArea(scx, func, cdarg) + SearchContext *scx; /* Pointer to search context specifying + * a cell use to search, an area in the + * coordinates of the cell's def, and a + * transform back to "root" coordinates. + */ + int (*func)(); /* Function to apply at each qualifying tile */ + ClientData cdarg; /* Client data for above function */ +{ + int extTreeSrFunc(); + CellDef *def = scx->scx_use->cu_def; + TreeContext context; + TreeFilter filter; + int pNum; + + if ((def->cd_flags & CDAVAILABLE) == 0) + if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + + filter.tf_func = func; + filter.tf_arg = cdarg; + context.tc_scx = scx; + context.tc_filter = &filter; + + /* + * Apply the function first to any of the tiles in the planes + * for this CellUse's CellDef that match the mask. + */ + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], + &scx->scx_area, &DBAllButSpaceAndDRCBits, func, + (ClientData) &context)) + return (1); + + /* Visit our children recursively */ + return (extCellSrArea(scx, extTreeSrFunc, (ClientData) &filter)); +} + +/* + * extTreeSrFunc -- + * + * Filter procedure applied to subcells by extTreeSrPaintArea(). + */ + +int +extTreeSrFunc(scx, fp) + SearchContext *scx; + TreeFilter *fp; +{ + CellDef *def = scx->scx_use->cu_def; + TreeContext context; + int pNum; + + if ((def->cd_flags & CDAVAILABLE) == 0) + if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return (0); + + context.tc_scx = scx; + context.tc_filter = fp; + + /* + * Apply the function first to any of the tiles in the planes + * for this CellUse's CellDef that match the mask. + */ + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], + &scx->scx_area, &DBAllButSpaceAndDRCBits, + fp->tf_func, (ClientData) &context)) + return (1); + + /* Visit our children recursively */ + return (extCellSrArea(scx, extTreeSrFunc, (ClientData) fp)); +} + +/* + *----------------------------------------------------------------------------- + * + * extCellSrArea -- + * + * Apply the supplied procedure to each of the cellUses found in the + * given area in the subcell plane of the child def of the supplied + * search context. + * + * The procedure is applied to each array element in each cell use that + * overlaps the clipping rectangle. The scx_x and scx_y parts of + * the SearchContext passed to the filter function correspond to the + * array element being visited. The same CellUse is, of course, passed + * as scx_use for all elements of the array. + * + * The array elements are visited by varying the X coordinate fastest. + * + * The procedure should be of the following form: + * int + * func(scx, cdarg) + * SearchContext *scx; + * ClientData cdarg; + * { + * } + * + * Func normally returns 0. If it returns 1 then the search is + * aborted. If it returns 2, then any remaining elements in the + * current array are skipped. + * + * Results: + * 0 is returned if the search terminated normally. 1 is + * returned if it was aborted. + * + * Side effects: + * Whatever side effects are brought about by applying the + * procedure supplied. + * + *----------------------------------------------------------------------------- + */ + +int +extCellSrArea(scx, func, cdarg) + SearchContext *scx; + /* Pointer to search context specifying a cell use to + * search, an area in the coordinates of the cell's + * def, and a transform back to "root" coordinates. + * The area may have zero size. + */ + int (*func)(); /* Function to apply at every tile found */ + ClientData cdarg; /* Argument to pass to function */ +{ + int xlo, xhi, ylo, yhi, xbase, ybase, xsep, ysep, clientResult; + int srchBot, srchRight; + Plane *plane = scx->scx_use->cu_def->cd_planes[PL_CELL]; + Tile *tp, *tpnew; + Rect *rect, *bbox; + CellUse *use; + SearchContext newScx; + CellTileBody *body; + Transform t, tinv; + TreeFilter filter; + Rect expanded; + Point start; + + filter.tf_func = func; + filter.tf_arg = cdarg; + + if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) + if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, NULL)) + return 0; + + /* + * In order to make this work with zero-size areas, we first expand + * the area by before searching the tile plane. extCellSrFunc will + * check carefully to throw out things that don't overlap the original + * area. The expansion is tricky because we mustn't expand infinities. + */ + + expanded = scx->scx_area; + if (expanded.r_xbot > TiPlaneRect.r_xbot) expanded.r_xbot -= 1; + if (expanded.r_ybot > TiPlaneRect.r_ybot) expanded.r_ybot -= 1; + if (expanded.r_xtop < TiPlaneRect.r_xtop) expanded.r_xtop += 1; + if (expanded.r_ytop < TiPlaneRect.r_ytop) expanded.r_ytop += 1; + rect = &expanded; + + /* Start along the top of the LHS of the search area */ + start.p_x = rect->r_xbot; + start.p_y = rect->r_ytop - 1; + tp = plane->pl_hint; + GOTOPOINT(tp, &start); + + /* Each iteration visits another tile on the LHS of the search area */ + while (TOP(tp) > rect->r_ybot) + { + /* Each iteration enumerates another tile */ +enumerate: + plane->pl_hint = tp; + if (SigInterruptPending) + return (1); + + /* + * Since subcells are allowed to overlap, a single tile body may + * refer to many subcells and a single subcell may be referred to + * by many tile bodies. To insure that each CellUse is enumerated + * exactly once, the procedure given to DBCellSrArea is only applied + * to a CellUse when its lower right corner is contained in the + * tile to dbCellSrFunc (or otherwise at the last tile encountered + * in the event the lower right corner of the CellUse is outside the + * search rectangle). + */ + srchBot = scx->scx_area.r_ybot; + srchRight = scx->scx_area.r_xtop; + for (body = (CellTileBody *) TiGetBody(tp); + body != NULL; + body = body->ctb_next) + { + use = newScx.scx_use = body->ctb_use; + ASSERT(use != (CellUse *) NULL, "dbCellSrFunc"); + + /* + * The check below is to ensure that we only enumerate each + * cell once, even though it appears in many different tiles + * in the subcell plane. + */ + bbox = &use->cu_bbox; + if ( (BOTTOM(tp) <= bbox->r_ybot || + (BOTTOM(tp) <= srchBot && bbox->r_ybot < srchBot)) + && (RIGHT(tp) >= bbox->r_xtop || + (RIGHT(tp) >= srchRight && bbox->r_xtop >= srchRight))) + { + /* + * Make sure that this cell really does overlap the + * search area (it could be just touching because of + * the expand-by-one in DBCellSrArea). + */ + if (!GEO_OVERLAP(&scx->scx_area, bbox)) continue; + + /* If not an array element, it's much simpler */ + if (use->cu_xlo == use->cu_xhi && use->cu_ylo == use->cu_yhi) + { + newScx.scx_x = use->cu_xlo, newScx.scx_y = use->cu_yhi; + if (SigInterruptPending) return 1; + GEOINVERTTRANS(&use->cu_transform, &tinv); + GEOTRANSTRANS(&use->cu_transform, &scx->scx_trans, + &newScx.scx_trans); + GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area); + if ((*func)(&newScx, filter.tf_arg) == 1) + return 1; + continue; + } + + /* + * More than a single array element; + * check to see which ones overlap our search area. + */ + DBArrayOverlap(use, &scx->scx_area, &xlo, &xhi, &ylo, &yhi); + xsep = (use->cu_xlo > use->cu_xhi) + ? -use->cu_xsep : use->cu_xsep; + ysep = (use->cu_ylo > use->cu_yhi) + ? -use->cu_ysep : use->cu_ysep; + for (newScx.scx_y = ylo; newScx.scx_y<=yhi; newScx.scx_y++) + for (newScx.scx_x = xlo; newScx.scx_x<=xhi; newScx.scx_x++) + { + if (SigInterruptPending) return 1; + xbase = xsep * (newScx.scx_x - use->cu_xlo); + ybase = ysep * (newScx.scx_y - use->cu_ylo); + GEOTRANSTRANSLATE(xbase, ybase, &use->cu_transform, &t); + GEOINVERTTRANS(&t, &tinv); + GEOTRANSTRANS(&t, &scx->scx_trans, &newScx.scx_trans); + GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area); + clientResult = (*func)(&newScx, filter.tf_arg); + if (clientResult == 2) goto skipArray; + else if (clientResult == 1) return 1; + } + } + skipArray: continue; + } + + tpnew = TR(tp); + if (LEFT(tpnew) < rect->r_xtop) + { + while (BOTTOM(tpnew) >= rect->r_ytop) tpnew = LB(tpnew); + if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot) + { + tp = tpnew; + goto enumerate; + } + } + + /* Each iteration returns one tile further to the left */ + while (LEFT(tp) > rect->r_xbot) + { + if (BOTTOM(tp) <= rect->r_ybot) + return (0); + tpnew = LB(tp); + tp = BL(tp); + if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot) + { + tp = tpnew; + goto enumerate; + } + } + + /* At left edge -- walk down to next tile along the left edge */ + for (tp = LB(tp); RIGHT(tp) <= rect->r_xbot; tp = TR(tp)) + /* Nothing */; + } + return (0); +} diff --git a/extract/ExtLength.c b/extract/ExtLength.c new file mode 100644 index 00000000..a0661a35 --- /dev/null +++ b/extract/ExtLength.c @@ -0,0 +1,1033 @@ +/* + * ExtLength.c -- + * + * Circuit extraction. + * Computation of the length of the shortest path from a driver + * to a receiver. This information is intended to be used in + * computing delays of signals propagating in a transmission + * line mode, where delay is proportional to the driver-to-receiver + * distance. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * Lawrence Livermore National Laboratory + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtLength.c,v 1.3 2009/09/10 20:32:52 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "utils/stack.h" +#include "utils/main.h" +#include "utils/utils.h" + +/* Temporary cell for holding an entire flattened net */ +CellDef *extPathDef = NULL; +CellUse *extPathUse = NULL; + +/* + * Tables that hold information describing each driver and receiver + * in the circuit. + * + * Each entry in the driver table will be initially 0, and later + * will be made to point to a list of hierarchical labels (i.e., + * specially constructed labels whose text field contains a full + * hierarchical pathname) where the driver label appears in the + * design. + * + * Each entry in the receiver table is initially 0, and is set to 1 + * when that receiver is processed as being connected to some driver. + */ +HashTable extDriverHash; +HashTable extReceiverHash; + +/* Initial size of the hash tables used in this file */ +#define INITHASHSIZE 32 + +/* Max length of a hierarchical name */ +#define MAXNAMESIZE 2048 + +/* + * List of labels being built up hierarchically by extLengthYank(). + * This is used within this file to pass data down to filter + * procedures of search functions. + */ +static Label *extLengthLabelList; + +/* + * Used to hold information while tracing out paths. + * Passed directly down to filter procedures of search functions. + */ +struct extPathArg +{ + int epa_min, epa_max; + int epa_pNum; + Label *epa_lab1, *epa_lab2; +}; + +/* + * Additional information passed down to extPathFloodFunc() + */ +struct extPathFloodArg +{ + int epfa_distance; + Point *epfa_srcPoint; + Tile *epfa_srcTile; + Rect epfa_srcArea; + struct extPathArg *epfa_epa; +}; + +/* Used to mark tiles during path tracing */ +#define MARKED ((ClientData) 1) + +/* Forward declarations */ +Label *extPathLabel(); +Label *extLengthYank(); +int extLengthLabels(); +int extLengthLabelsFunc(); +int extPathPairFunc(); +int extPathResetClient(); +int extPathFloodFunc(); + +void extLengthInit(); +void extPathPairDistance(); +void extPathFlood(); +void extPathFloodTile(); + + +/* + * ---------------------------------------------------------------------------- + * + * ExtSetDriver -- + * ExtSetReceiver -- + * + * Add a terminal name to either the driver or the receiver table. + * + * Results: + * None. + * + * Side effects: + * Adds an entry to the hash tables extDriverHash or extReceiverHash + * respectively. The initial value of the hash entry is 0. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtSetDriver(name) + char *name; +{ + HashEntry *he; + + he = HashFind(&extDriverHash, name); + HashSetValue(he, 0); +} + +void +ExtSetReceiver(name) + char *name; +{ + HashEntry *he; + + he = HashFind(&extReceiverHash, name); + HashSetValue(he, 0); +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtLengthClear -- + * + * Kill extDriverHash and extReceiverHash, and re-initialize them. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtLengthClear() +{ + HashKill(&extDriverHash); + HashKill(&extReceiverHash); + extLengthInit(); +} + +/* + * ---------------------------------------------------------------------------- + * + * extLengthInit -- + * + * Allocates and initializes the hash tables extDriverHash + * and extReceiverHash. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extLengthInit() +{ + HashInit(&extDriverHash, INITHASHSIZE, 0); + HashInit(&extReceiverHash, INITHASHSIZE, 0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extLength -- + * + * Using the driver and receiver tables, compute the distances from + * each driver to each receiver on its (flattened) net. Output to + * the file 'f' lines of the following format: + * + * distance drivername receivername min max + * + * e.g, + * + * distance a/b/cOUT d/e/fIN 1234 2345 + * + * The units of distance are lambda. + * + * Results: + * None. + * + * Side effects: + * Outputs to the FILE 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +extLength(rootUse, f) + CellUse *rootUse; /* The names stored in the driver and receiver tables + * should all be relative to this root cell. It is + * the responsibility of the caller to ensure this. + */ + FILE *f; /* Open output file */ +{ + Label *dList, *rList, *dLab, *rLab; + int min, max; + HashSearch hs; + HashEntry *he; + + /* Create the yank cell if it doesn't already exist */ + if (extPathDef == (CellDef *) NULL) + DBNewYank("__PATHYANK__", &extPathUse, &extPathDef); + + /* + * Initialize the entries in the driver table to point to + * a list of hierarchical labels describing the locations + * where that driver appears. These labels should all + * be from a single cell. + */ + HashStartSearch(&hs); + while (he = HashNext(&extDriverHash, &hs)) + { + dList = extPathLabel(rootUse, he->h_key.h_name); + HashSetValue(he, (ClientData) dList); + } + + /* + * Main loop. + * For each driver, find all the receivers connected to it, and + * then compute and output the distance to each. + */ + HashStartSearch(&hs); + while (he = HashNext(&extDriverHash, &hs)) + { + /* Ignore drivers whose labels couldn't be found */ + dList = (Label *) HashGetValue(he); + if (dList == (Label *) NULL) + continue; + + /* + * Flatten this net into extPathDef. + * Find all the labels that overlap material we yanked and + * whose names appear in the receiver table. Build a hierarchical + * list of these labels. + */ + rList = extLengthYank(rootUse, dList); + + /* + * Now compute the distance from the driver label to + * each of the receivers. Free each driver label + * as it is processed. + */ + for (dLab = dList; dLab; dLab = dLab->lab_next) + { + for (rLab = rList; rLab; rLab = rLab->lab_next) + { + extPathPairDistance(dLab, rLab, &min, &max); + fprintf(f, "distance %s %s %d %d\n", + dLab->lab_text, rLab->lab_text, min, max); + } + + /* Free the driver label */ + freeMagic((char *) dLab); + } + + /* Free all the receiver labels built up during this iteration */ + for (rLab = rList; rLab; rLab = rLab->lab_next) + freeMagic((char *) rLab); + + /* For sanity since we've freed the driver label list */ + HashSetValue(he, (ClientData) NULL); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * extLengthYank -- + * + * Trace out all material connected to each location on the label + * list 'labList', both in the root cell use->cu_def and hierarchically + * in all of its children. Flatten this material into the cell + * 'extPathDef'. + * + * Results: + * Returns a list of the hierarchical labels whose names appear + * in the receiver table (extReceiverHash) that are overlapped + * by material we yanked. + * + * Side effects: + * Adds material to extPathDef after erasing its previous contents. + * + * ---------------------------------------------------------------------------- + */ + +Label * +extLengthYank(use, labList) + CellUse *use; /* Cell whose material is to be traced */ + Label *labList; /* List of labels whose attached net is to be traced */ +{ + SearchContext scx; + char mesg[512]; + Label *lab; + int pNum; + + /* Eliminate previous contents of yank cell */ + if (DebugIsSet(extDebugID, extDebLength)) + { + DBReComputeBbox(extPathDef); + DBWAreaChanged(extPathDef, &extPathDef->cd_bbox, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + } + DBCellClearDef(extPathDef); + + /* + * Search out all material connected to each label. + * Bloat the label's rectangle to consider even material + * that only touches the label. + */ + for (lab = labList; lab; lab = lab->lab_next) + { + if (lab->lab_type == TT_SPACE) + continue; + scx.scx_use = use; + scx.scx_trans = GeoIdentityTransform; + GEO_EXPAND(&lab->lab_rect, 1, &scx.scx_area); + DBTreeCopyConnect(&scx, &DBConnectTbl[lab->lab_type], 0, + DBConnectTbl, &TiPlaneRect, extPathUse); + } + + if (DebugIsSet(extDebugID, extDebLength)) + { + DBReComputeBbox(extPathDef); + DBWAreaChanged(extPathDef, &extPathDef->cd_bbox, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + WindUpdate(); + (void) sprintf(mesg, "Yanked %s", + labList ? labList->lab_text : "(NONE)"); + TxMore(mesg); + } + + /* + * Now find all the labels appearing in the receiver table that are + * overlapped by any of the material we just yanked. This may not + * be the most efficient way to do things: we're searching the label + * list of at least the root cell every time we process a tile in + * the yanked net. The hope is that this is still fast enough. + * Possibly a better way would be to identify the CELLS that are + * overlapped by tiles in the net, and then to process each label + * list just once. + */ + extLengthLabelList = (Label *) NULL; + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + (void) DBSrPaintArea((Tile *) NULL, extPathDef->cd_planes[pNum], + &TiPlaneRect, &DBAllButSpaceBits, extLengthLabels, + (ClientData) use); + } + + return (extLengthLabelList); +} + +/* + * ---------------------------------------------------------------------------- + * + * extLengthLabels -- + * + * Called for each paint tile in extPathDef to find all the labels + * in the original search tree that overlap the tile. We bloat each + * tile to the top and right by one unit to be certain to catch + * labels appearing on these edges. + * + * Results: + * Always returns 0. + * + * Side effects: + * May cons hierarchical labels (newly created labels whose text + * is the full hierarchical path of a label in a subcell) to the + * list extLengthLabelList. + * + * ---------------------------------------------------------------------------- + */ + +int +extLengthLabels(tile, rootUse) + Tile *tile; /* Some tile in extPathDef */ + CellUse *rootUse; /* The original root cell */ +{ + char name[MAXNAMESIZE]; + TileTypeBitMask mask; + TerminalPath tpath; + SearchContext scx; + + /* Grow the search area to include labels on the top and right */ + TITORECT(tile, &scx.scx_area); + scx.scx_area.r_xtop++; + scx.scx_area.r_ytop++; + scx.scx_use = rootUse; + scx.scx_trans = GeoIdentityTransform; + tpath.tp_first = tpath.tp_next = name; + tpath.tp_last = &name[sizeof name - 2]; + + TTMaskSetOnlyType(&mask, TiGetType(tile)); + (void) DBTreeSrLabels(&scx, &mask, 0, &tpath, TF_LABEL_ATTACH, + extLengthLabelsFunc, (ClientData) NULL); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extLengthLabelsFunc -- + * + * Called for each label found while searching hierarchically the area + * beneath one of the tiles in extPathDef. If the hierarchical label + * name matches a name appearing in the receiver table (extReceiverHash) + * we cons a newly created hierarchical label onto the front of + * extLengthLabelList. + * + * Results: + * Always returns 0. + * + * Side effects: + * May cons hierarchical labels (newly created labels whose text + * is the full hierarchical path of a label in a subcell) to the + * list extLengthLabelList. Also, for each receiver label we + * did find, leaves a value of 1 (via HashSetValue()) in the + * receiver hash table, so we can know at the end which receiver + * labels weren't driven by any driver. + * + * ---------------------------------------------------------------------------- + */ + +int +extLengthLabelsFunc(scx, label, tpath) + SearchContext *scx; /* Where in the search tree we are */ + Label *label; /* The label itself */ + TerminalPath *tpath; /* Identifies hierarchical prefix for label. + * The full hierarchical pathname will be the + * concatenation of the string tpath->tp_first + * and the string label->lab_text. + */ +{ + Label *newLab; + HashEntry *he; + int len; + + /* Concatenate the prefix and label to get the full hierarchical name */ + (void) strcpy(tpath->tp_next, label->lab_text); + + /* Only bother with labels in the receiver table */ + he = HashLookOnly(&extReceiverHash, tpath->tp_first); + if (he == NULL) + return (0); + + /* Mark this receiver as being seen */ + HashSetValue(he, (ClientData) 1); + + /* Allocate and fill in a new hierarchical label */ + len = strlen(tpath->tp_first) + sizeof (Label) + - sizeof newLab->lab_text + 1; + newLab = (Label *) mallocMagic((unsigned) len); + newLab->lab_type = label->lab_type; + newLab->lab_just = GeoTransPos(&scx->scx_trans, label->lab_just); + GeoTransRect(&scx->scx_trans, &label->lab_rect, &newLab->lab_rect); + newLab->lab_next = extLengthLabelList; + extLengthLabelList = newLab; + (void) strcpy(newLab->lab_text, tpath->tp_first); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extPathLabel -- + * + * Find all the locations of labels matching the hierarchical + * name 'text' and return a linked list of newly allocated + * labels with the full hierarchical name. + * + * Results: + * Returns a pointer to the newly allocated Label list + * + * Side effects: + * Allocates memory. + * Complains if the label couldn't be found. + * + * ---------------------------------------------------------------------------- + */ + +Label * +extPathLabel(use, text) + CellUse *use; + char *text; +{ + int extPathLabelFunc(); + Label *lab; + + lab = (Label *) NULL; + (void) DBSrLabelLoc(use, text, extPathLabelFunc, (ClientData) &lab); + if (lab == NULL) + TxError("Can't find terminal \"%s\"\n", text); + return (lab); +} + +/* + * ---------------------------------------------------------------------------- + * + * extPathLabelFunc -- + * + * Called via DBSrLabelLoc() on behalf of extPathLabel() above. + * Creates a Label whose text is the string pointed to by text, + * whose lab_rect is *rect, and whose type is childLab->lab_type. + * Cons it onto the front of the list *pLabList. + * + * Results: + * Always returns 0. + * + * Side effects: + * Allocates memory. + * + * ---------------------------------------------------------------------------- + */ + +int +extPathLabelFunc(rect, text, childLab, pLabList) + Rect *rect; /* Transformed location of the label */ + char *text; /* Full hierarchical name of the label */ + Label *childLab; /* The label itself */ + Label **pLabList; /* Cons the newly allocated label onto the front of + * this list. + */ +{ + Label *lab; + int len; + + len = strlen(text) + sizeof (Label) - sizeof lab->lab_text + 1; + lab = (Label *) mallocMagic((unsigned) len); + lab->lab_type = childLab->lab_type; + lab->lab_rect = *rect; + lab->lab_just = GEO_CENTER; /* Irrelevant */ + lab->lab_next = *pLabList; + + /* Cons to front of list */ + *pLabList = lab; + (void) strcpy(lab->lab_text, text); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extPathPairDistance -- + * + * Compute the actual delay between two locations 'lab1' and 'lab2'. + * The delay is computed using optimistic and pessimistic assumptions + * to get a min and max delay respectively. + * + * Algorithm: + * The algorithm we use here is simplistic, assuming that all + * wires are of essentially uniform width. We use a tile-based + * depth-first flooding algorithm that computes a delay on the + * forward pass based on the wire's length. + * + * Results: + * None. + * + * Side effects: + * Stores the min and max delay in *pMin and *pMax respectively. + * Uses the ti_client fields of the tiles in extPathDef, since + * these are used while tracing out paths. + * + * ---------------------------------------------------------------------------- + */ + +void +extPathPairDistance(lab1, lab2, pMin, pMax) + Label *lab1, *lab2; + int *pMin, *pMax; +{ + struct extPathArg epa; + TileTypeBitMask mask; + PlaneMask pMask; + int pNum; + Rect r; + + /* Skip if either type is space (sanity check) */ + if (lab1->lab_type == TT_SPACE || lab2->lab_type == TT_SPACE) + return; + + /* Include all tiles touching lab1 that are connected to it */ + GEO_EXPAND(&lab1->lab_rect, 1, &r); + mask = DBConnectTbl[lab1->lab_type]; + + /* + * Find min and max delays, considering each plane that + * lab1 is connected to. Don't reset the ti_client fields + * until after we've found all paths. + */ + epa.epa_min = INFINITY; + epa.epa_max = MINFINITY; + epa.epa_lab1 = lab1; + epa.epa_lab2 = lab2; + pMask = DBTechTypesToPlanes(&mask); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (PlaneMaskHasPlane(pMask, pNum)) + { + epa.epa_pNum = pNum; + (void) DBSrPaintClient((Tile *) NULL, extPathDef->cd_planes[pNum], + &r, &mask, (ClientData) CLIENTDEFAULT, + extPathPairFunc, (ClientData) &epa); + } + + /* Pass the min and max delay back to our caller */ + *pMin = epa.epa_min; + *pMax = epa.epa_max; + + /* Reset ti_client fields in tiles */ + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + (void) DBSrPaintClient((Tile *) NULL, extPathDef->cd_planes[pNum], + &TiPlaneRect, &DBAllButSpaceBits, MARKED, + extPathResetClient, (ClientData) NULL); +} + +/* + * ---------------------------------------------------------------------------- + * extPathResetClient -- + * + * Called by DBSrPaintClient() on behalf of extPathPairDistance() + * above to reset each tile's ti_client field to CLIENTDEFAULT. + * + * Results: + * Always returns 0. + * + * Side effects: + * Sets tile->ti_client to CLIENTDEFAULT. + * ---------------------------------------------------------------------------- + */ + +int +extPathResetClient(tile) + Tile *tile; +{ + tile->ti_client = (ClientData) CLIENTDEFAULT; + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extPathPairFunc -- + * + * Called by DBSrPaintClient() on behalf of extPathPairDistance() + * above for each unprocessed tile (ti_client == CLIENTDEFAULT) + * overlapped by epa->epa_lab1 that is connected to it. + * Floods outward in depth-first search toward the destination + * epa->epa_lab2. Remembers the min and max delay to the + * destination in epa->epa_min and epa->epa_max. + * + * We use depth-first search instead of breadth-first because + * it's easier, we need to consider both the longest and shortest + * path, and we expect there to be only a few paths. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See above. + * Marks the ti_client fields of the tiles we visit as MARKED. + * + * ---------------------------------------------------------------------------- + */ + +int +extPathPairFunc(tile, epa) + Tile *tile; + struct extPathArg *epa; +{ + Point startPoint; + Rect r; + + /* + * Visit all this tile's neighbors. + * Our initial delay is zero, and our initial starting point + * is in the center of the overlap of epa->epa_lab1 and tile. + */ + TITORECT(tile, &r); + GEOCLIP(&r, &epa->epa_lab1->lab_rect); + startPoint.p_x = (r.r_xtop + r.r_xbot) / 2; + startPoint.p_y = (r.r_ytop + r.r_ybot) / 2; + extPathFlood(tile, &startPoint, 0, epa); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extPathFlood -- + * + * Flood from a tile to all its connected and unprocessed neighbors. + * As we flood to each neighbor, we estimate a delay for the increment + * from the point 'p' (usually on the center of 'tile', and at distance + * 'distance' from the starting point) to the central point of the new + * tile. Contacts are processed in a similar way, except the point 'p' + * doesn't change. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extPathFlood(tile, p, distance, epa) + Tile *tile; /* Tile whose neighbors we are to visit */ + Point *p; /* Usually at center of 'tile' */ + int distance; /* Distance to 'p' */ + struct extPathArg *epa; /* Update epa_min and epa_max when we reach + * the destination epa_lab2. + */ +{ + TileType type = TiGetType(tile); + Label *lab2 = epa->epa_lab2; + int pNum, newdistance; + PlaneMask pMask; + Tile *tp; + char mesg[512]; + Point p2; + Rect r; + + /* Mark the tile as being visited */ + tile->ti_client = MARKED; + + /* + * Are we at the destination yet? + * If so, compute final delay and just return. + * Update the min and max delay if necessary. + * Don't propagate to neighboring tiles since doing so + * can only lengthen the path. + */ + TITORECT(tile, &r); + if (DebugIsSet(extDebugID, extDebLength)) + { + ShowRect(extPathDef, &r, STYLE_SOLIDHIGHLIGHTS); + TxMore("Visit tile"); + ShowRect(extPathDef, &r, STYLE_ERASEHIGHLIGHTS); + } + + if (GEO_TOUCH(&r, &lab2->lab_rect) && DBConnectsTo(type, lab2->lab_type)) + { + /* Find distance to closest point in 'lab2->lab_rect' to 'p' */ + p2 = *p; + GeoClipPoint(&p2, &lab2->lab_rect); + newdistance = extPathTileDist(p, &p2, tile, distance); + + if (DebugIsSet(extDebugID, extDebLength)) + { + (void) sprintf(mesg, "Reached destination, dist = %d", newdistance); + TxMore(mesg); + } + + /* Update min and max distance */ + if (newdistance < epa->epa_min) epa->epa_min = newdistance; + if (newdistance > epa->epa_max) epa->epa_max = newdistance; + return; + } + + /* Walk around the perimeter to connected tiles */ + + /* TOP */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (tp->ti_client != MARKED && DBConnectsTo(TiGetType(tp), type)) + extPathFloodTile(tile, p, distance, tp, epa); + + /* RIGHT */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (tp->ti_client != MARKED && DBConnectsTo(TiGetType(tp), type)) + extPathFloodTile(tile, p, distance, tp, epa); + + /* BOTTOM */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (tp->ti_client != MARKED && DBConnectsTo(TiGetType(tp), type)) + extPathFloodTile(tile, p, distance, tp, epa); + + /* LEFT */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (tp->ti_client != MARKED && DBConnectsTo(TiGetType(tp), type)) + extPathFloodTile(tile, p, distance, tp, epa); + + /* Try connections to other planes */ + if (DBIsContact(type)) + { + int saveplane = epa->epa_pNum; + PlaneMask pMask = DBConnPlanes[type]; + pMask &= ~(PlaneNumToMaskBit(epa->epa_pNum)); + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (PlaneMaskHasPlane(pMask, pNum)) + { + Plane *plane = extPathDef->cd_planes[pNum]; + + /* Find the point on the new plane */ + tp = plane->pl_hint; + GOTOPOINT(tp, &tile->ti_ll); + plane->pl_hint = tp; + + /* If not yet visited, process tp */ + if (tp->ti_client == (ClientData) CLIENTDEFAULT + && DBConnectsTo(type, TiGetType(tp))) + { + epa->epa_pNum = pNum; + extPathFlood(tp, p, distance, epa); + } + } + epa->epa_pNum = saveplane; + } + + /* + * The hairiest case is when this type connects to stuff on + * other planes, but isn't itself connected as a contact. + * For example, a CMOS pwell connects to diffusion of the + * same doping (p substrate diff). In a case like this, + * we need to search the entire AREA of the tile plus a + * 1-lambda halo to find everything it overlaps or touches + * on the other plane. + */ + if (pMask = DBAllConnPlanes[type]) + { + int saveplane = epa->epa_pNum; + struct extPathFloodArg epfa; + Rect biggerArea; + + TITORECT(tile, &epfa.epfa_srcArea); + GEO_EXPAND(&epfa.epfa_srcArea, 1, &biggerArea); + epfa.epfa_distance = distance; + epfa.epfa_epa = epa; + epfa.epfa_srcPoint = p; + epfa.epfa_srcTile = tile; + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (pNum != epa->epa_pNum && PlaneMaskHasPlane(pMask, pNum)) + { + epa->epa_pNum = pNum; + (void) DBSrPaintClient((Tile *) NULL, + extPathDef->cd_planes[pNum], &biggerArea, + &DBConnectTbl[type], (ClientData) CLIENTDEFAULT, + extPathFloodFunc, (ClientData) &epfa); + } + epa->epa_pNum = saveplane; + } +} + +int +extPathFloodFunc(dstTile, epfa) + Tile *dstTile; + struct extPathFloodArg *epfa; +{ + Rect srcRect, dstRect; + Point dstPoint, *p; + int dstDist; + + /* + * If dstTile overlaps epfa->epfa_srcArea, use epfa->epfa_srcPoint; + * otherwise, pick a point along the boundary of epfa->epfa_srcArea + * that's in common with dstTile. + */ + dstDist = epfa->epfa_distance; + srcRect = epfa->epfa_srcArea; + TITORECT(dstTile, &dstRect); + if (GEO_OVERLAP(&srcRect, &dstRect)) + p = epfa->epfa_srcPoint; + else + { + /* Pick a point along the boundary */ + GEOCLIP(&srcRect, &dstRect); + dstPoint.p_x = (srcRect.r_xbot + srcRect.r_xtop) / 2; + dstPoint.p_y = (srcRect.r_ybot + srcRect.r_ytop) / 2; + + /* Compute the incremental delay */ + dstDist = extPathTileDist(epfa->epfa_srcPoint, &dstPoint, + epfa->epfa_srcTile, dstDist); + p = &dstPoint; + } + + /* Recurse */ + extPathFlood(dstTile, p, dstDist, epfa->epfa_epa); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * extPathFloodTile -- + * + * Propagate from a tile 'srcTile' to one of its neighbors 'dstTile'. + * The delay 'srcDelay' has been computed to 'srcPoint' (which is + * contained within 'srcTile' or is on its border). We pick the + * midpoint of the overlap between 'srcTile' and 'dstTile' as the + * point to which the next cost is computed, and then recursively + * call extPathFlood() with dstTile and the new point. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extPathFloodTile(srcTile, srcPoint, srcDist, dstTile, epa) + Tile *srcTile; /* Tile through which we're propagating */ + Point *srcPoint; /* Point inside or on srcTile */ + int srcDist; /* Distance to srcPoint so far */ + Tile *dstTile; /* Tile on border of srcTile */ + struct extPathArg *epa; +{ + Rect srcRect, dstRect; + Point dstPoint; + int dstDist; + + /* + * Pick the central point along the boundary of srcTile and dstTile + * for purposes of computing costs. + */ + TITORECT(srcTile, &srcRect); + TITORECT(dstTile, &dstRect); + GEOCLIP(&srcRect, &dstRect); + dstPoint.p_x = (srcRect.r_xbot + srcRect.r_xtop) / 2; + dstPoint.p_y = (srcRect.r_ybot + srcRect.r_ytop) / 2; + + /* Compute the incremental delay */ + dstDist = extPathTileDist(srcPoint, &dstPoint, srcTile, srcDist); + + /* Recurse */ + extPathFlood(dstTile, &dstPoint, dstDist, epa); +} + +/* + * ---------------------------------------------------------------------------- + * + * extPathTileDist -- + * + * Update delay information to include the costs of passing through + * 'tile' from p1 to p2. The old distance is 'oldDist'. We account + * for the distance from p1 to p2 through the tile 'tile'. + * + * Results: + * Returns the distance described above. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +extPathTileDist(p1, p2, tile, oldDist) + Point *p1, *p2; + Tile *tile; + int oldDist; +{ + int newDist; + + newDist = oldDist + ABSDIFF(p1->p_x, p2->p_x) + ABSDIFF(p1->p_y, p2->p_y); + + /* + * If both points were on the same side, include a little extra + * for passing through the middle of the tile (which wasn't counted). + */ + if (p1->p_x == p2->p_x) + { + if (p1->p_x == LEFT(tile) || p1->p_x == RIGHT(tile)) + newDist += RIGHT(tile) - LEFT(tile); + } + if (p1->p_y == p2->p_y) + { + if (p1->p_y == BOTTOM(tile) || p1->p_y == TOP(tile)) + newDist += TOP(tile) - BOTTOM(tile); + } + + return (newDist); +} diff --git a/extract/ExtMain.c b/extract/ExtMain.c new file mode 100644 index 00000000..2eba659f --- /dev/null +++ b/extract/ExtMain.c @@ -0,0 +1,676 @@ +/* + * ExtMain.c -- + * + * Circuit extraction. + * Command interface. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtMain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/styles.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "utils/stack.h" +#include "utils/utils.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" +#include "utils/undo.h" + +/* Imports from elsewhere in this module */ +extern FILE *extFileOpen(); + +/* ------------------------ Exported variables ------------------------ */ + + /* + * See extract.h for the bit flags that may be set in the following. + * If any are set, the corresponding warnings get generated, leaving + * feedback messages. If this word is zero, only fatal errors are + * reported. + */ +int ExtDoWarn = EXTWARN_DUP|EXTWARN_FETS; +int ExtOptions = EXT_DOALL; + +/* --------------------------- Global data ---------------------------- */ + + /* Cumulative yank buffer for hierarchical circuit extraction */ +CellUse *extYuseCum = NULL; +CellDef *extYdefCum = NULL; + + /* Identifier returned by the debug module for circuit extraction */ +ClientData extDebugID; + + /* Number of errors encountered during extraction */ +int extNumFatal; +int extNumWarnings; + + /* Dummy use pointing to def being extracted */ +CellUse *extParentUse; + +/* ------------------------ Data local to this file ------------------- */ + + /* Stack of defs pending extraction */ +Stack *extDefStack; + + /* Forward declarations */ +int extDefInitFunc(), extDefPushFunc(); +void extParents(); +void extDefParentFunc(); +void extDefParentAreaFunc(); +void extExtractStack(); + +bool extContainsGeometry(); +bool extContainsCellFunc(); +bool extTimestampMisMatch(); + +/* + * ---------------------------------------------------------------------------- + * + * ExtInit -- + * + * Initialize the technology-independent part of the extraction module. + * This procedure should be called once, after the database module has + * been initialized. + * + * Results: + * None. + * + * Side effects: + * Initializes the local variables of the extraction module. + * Registers the extractor with the debugging module. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtInit() +{ + int n; + static struct + { + char *di_name; + int *di_id; + } debugFlags[] = { + "areaenum", &extDebAreaEnum, + "array", &extDebArray, + "hardway", &extDebHardWay, + "hiercap", &extDebHierCap, + "hierareacap", &extDebHierAreaCap, + "label", &extDebLabel, + "length", &extDebLength, + "neighbor", &extDebNeighbor, + "noarray", &extDebNoArray, + "nofeedback", &extDebNoFeedback, + "nohard", &extDebNoHard, + "nosubcell", &extDebNoSubcell, + "perimeter", &extDebPerim, + "resist", &extDebResist, + "visonly", &extDebVisOnly, + "yank", &extDebYank, + 0 + }; + + /* Register ourselves with the debugging module */ + extDebugID = + DebugAddClient("extract", sizeof debugFlags/sizeof debugFlags[0]); + for (n = 0; debugFlags[n].di_name; n++) + *(debugFlags[n].di_id) = + DebugAddFlag(extDebugID, debugFlags[n].di_name); + + /* Create the yank buffer used for hierarchical extraction */ + DBNewYank("__ext_cumulative", &extYuseCum, &extYdefCum); + + /* Create the dummy use also used in hierarchical extraction */ + extParentUse = DBCellNewUse(extYdefCum, (char *) NULL); + DBSetTrans(extParentUse, &GeoIdentityTransform); + + /* Initialize the hash tables used in ExtLength.c */ + extLengthInit(); +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtAll -- + * + * Extract the subtree rooted at the CellDef 'rootUse->cu_def'. + * Each cell is extracted to a file in the current directory + * whose name consists of the last part of the cell's path, + * with a .ext suffix. + * + * Results: + * None. + * + * Side effects: + * Creates a number of .ext files and writes to them. + * Adds feedback information where errors have occurred. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtAll(rootUse) + CellUse *rootUse; +{ + /* Make sure the entire subtree is read in */ + DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox); + + /* Fix up bounding boxes if they've changed */ + DBFixMismatch(); + + /* Mark all defs as being unvisited */ + (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); + + /* Recursively visit all defs in the tree and push on stack */ + extDefStack = StackNew(100); + (void) extDefPushFunc(rootUse); + + /* Now extract all the cells we just found */ + extExtractStack(extDefStack, TRUE, rootUse->cu_def); + StackFree(extDefStack); +} + +/* + * Function to initialize the client data field of all + * cell defs, in preparation for extracting a subtree + * rooted at a particular def. + */ +int +extDefInitFunc(def) + CellDef *def; +{ + def->cd_client = (ClientData) 0; + return (0); +} + +/* + * Function to push each cell def on extDefStack + * if it hasn't already been pushed, and then recurse + * on all that def's children. + */ +int +extDefPushFunc(use) + CellUse *use; +{ + CellDef *def = use->cu_def; + + if (def->cd_client || (def->cd_flags&CDINTERNAL)) + return (0); + + def->cd_client = (ClientData) 1; + StackPush((ClientData) def, extDefStack); + (void) DBCellEnum(def, extDefPushFunc, (ClientData) 0); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtUnique -- + * + * For each cell in the subtree rooted at rootUse->cu_def, make + * sure that there are not two different nodes with the same label. + * If there are, we generate unique names by appending a numeric + * suffix to all but one of the offending labels. + * If "option" is 1 (tagged mode), then only labels ending in the + * character "#" are forced to be unique. If "option" is 2 (noports + * mode), then port labels are not forced to be unique. Finally, + * if the label has been changed and doesn't end in a '!', we leave + * feedback. + * + * Results: + * None. + * + * Side effects: + * May modify the label lists of some of the cells rooted + * at rootUse->cu_def, and mark the cells as CDMODIFIED. + * May also leave feedback. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtUnique(rootUse, option) + CellUse *rootUse; + int option; +{ + CellDef *def; + int nwarn; + + /* Make sure the entire subtree is read in */ + DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox); + + /* Fix up bounding boxes if they've changed */ + DBFixMismatch(); + + /* Mark all defs as being unvisited */ + (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); + + /* Recursively visit all defs in the tree and push on stack */ + extDefStack = StackNew(100); + (void) extDefPushFunc(rootUse); + + /* Now process all the cells we just found */ + nwarn = 0; + while (def = (CellDef *) StackPop(extDefStack)) + { + def->cd_client = (ClientData) 0; + if (!SigInterruptPending) + nwarn += extUniqueCell(def, option); + } + StackFree(extDefStack); + if (nwarn) + TxError("%d uncorrected errors (see the feedback info)\n", nwarn); +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtParents -- + * ExtShowParents -- + * + * ExtParents extracts the cell use->cu_def and all its parents. + * ExtShowParents merely finds and prints all the parents without + * extracting them. + * + * As in ExtAll, each cell is extracted to a file in the current + * directory whose name consists of the last part of the cell's path, + * with a .ext suffix. + * + * Results: + * None. + * + * Side effects: + * Creates a number of .ext files and writes to them. + * Adds feedback information where errors have occurred. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtParents(use) + CellUse *use; +{ + extParents(use, TRUE); +} + +void +ExtShowParents(use) + CellUse *use; +{ + extParents(use, FALSE); +} + +void +extParents(use, doExtract) + CellUse *use; + bool doExtract; /* If TRUE, we extract; if FALSE, we print */ +{ + /* Mark all defs as being unvisited */ + (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); + + /* Recursively visit all defs in the tree and push on stack */ + extDefStack = StackNew(100); + extDefParentFunc(use->cu_def); + + /* Now extract all the cells we just found */ + extExtractStack(extDefStack, doExtract, (CellDef *) NULL); + StackFree(extDefStack); +} + +/* + * Function to visit all the parents of 'def' and push them on + * extDefStack. We only push a def if it is unmarked, ie, its + * cd_client field is 0. After pushing a def, we mark it by + * setting its cd_client field to 1. + */ + +void +extDefParentFunc(def) + CellDef *def; +{ + CellUse *parent; + + if (def->cd_client || (def->cd_flags&CDINTERNAL)) + return; + + def->cd_client = (ClientData) 1; + StackPush((ClientData) def, extDefStack); + for (parent = def->cd_parents; parent; parent = parent->cu_nextuse) + if (parent->cu_parent) + extDefParentFunc(parent->cu_parent); +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtParentArea -- + * + * ExtParentArea extracts the cell use->cu_def and each of its + * parents that contain geometry touching or overlapping the area + * of use->cu_def. + * + * Results: + * None. + * + * Side effects: + * Creates one or more .ext files and writes to them. + * Adds feedback information where errors have occurred. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtParentArea(use, changedArea, doExtract) + CellUse *use; /* Use->cu_def changed; extract its affected parents */ + Rect *changedArea; /* Area changed in use->cu_def coordinates */ + bool doExtract; /* If TRUE, we extract; if FALSE, we just print names + * of the cells we would extract. + */ +{ + Rect area; + + /* Mark all defs as being unvisited */ + (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); + + /* + * Recursively visit all defs in the tree + * and push on stack if they contain any geometry + * overlapping or touching the area 'changedArea'. + */ + area = *changedArea; + area.r_xbot--, area.r_ybot--; + area.r_xtop++, area.r_ytop++; + extDefStack = StackNew(100); + extDefParentAreaFunc(use->cu_def, use->cu_def, (CellUse *) NULL, &area); + + /* Now extract all the cells we just found */ + extExtractStack(extDefStack, doExtract, (CellDef *) NULL); + StackFree(extDefStack); +} + +/* + * Function to visit all the parents of 'def' and push them on + * extDefStack. We only push a def if it is unmarked, ie, its + * cd_client field is 0, and if it is either 'baseDef' or it + * contains geometry or other subcells in the area 'area'. + * We mark each def visited by setting cd_client to 1. + */ + +void +extDefParentAreaFunc(def, baseDef, allButUse, area) + CellDef *def; + CellDef *baseDef; + CellUse *allButUse; + Rect *area; +{ + int x, y, xoff, yoff; + CellUse *parent; + Transform t, t2; + Rect parArea; + + if (def->cd_client || (def->cd_flags&CDINTERNAL)) + return; + + if (def == baseDef || extContainsGeometry(def, allButUse, area)) + { + def->cd_client = (ClientData) 1; + StackPush((ClientData) def, extDefStack); + } + + for (parent = def->cd_parents; parent; parent = parent->cu_nextuse) + { + if (parent->cu_parent) + { + for (x = parent->cu_xlo; x <= parent->cu_xhi; x++) + { + for (y = parent->cu_ylo; y <= parent->cu_yhi; y++) + { + xoff = (x - parent->cu_xlo) * parent->cu_xsep; + yoff = (y - parent->cu_ylo) * parent->cu_ysep; + GeoTranslateTrans(&GeoIdentityTransform, xoff, yoff, &t); + GeoTransTrans(&t, &parent->cu_transform, &t2); + GeoTransRect(&t2, area, &parArea); + extDefParentAreaFunc(parent->cu_parent, baseDef, + parent, &parArea); + } + } + } + } +} + +bool +extContainsGeometry(def, allButUse, area) + CellDef *def; + CellUse *allButUse; + Rect *area; +{ + int extContainsPaintFunc(); + bool extContainsCellFunc(); + int pNum; + + if (TiSrArea((Tile *) NULL, def->cd_planes[PL_CELL], area, + extContainsCellFunc, (ClientData) allButUse)) + return (TRUE); + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], + area, &DBAllButSpaceBits, + extContainsPaintFunc, (ClientData) NULL)) + return (TRUE); + + return (FALSE); +} + +bool +extContainsCellFunc(tile, allButUse) + Tile *tile; + CellUse *allButUse; +{ + CellTileBody *ctb; + + for (ctb = (CellTileBody *) TiGetBody(tile); ctb; ctb = ctb->ctb_next) + if (ctb->ctb_use != allButUse) + return (TRUE); + + return (FALSE); +} + +int +extContainsPaintFunc() +{ + return (1); +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtIncremental -- + * + * Starting at 'rootUse', extract all cell defs that have changed. + * Right now, we forcibly read in the entire tree before doing the + * extraction. + * + * Results: + * None. + * + * Side effects: + * Creates a number of .ext files and writes to them. + * Adds feedback information where errors have occurred. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtIncremental(rootUse) + CellUse *rootUse; +{ + /* Make sure the entire subtree is read in */ + DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox); + + /* Fix up bounding boxes if they've changed */ + DBFixMismatch(); + + /* Update all timestamps */ + DBUpdateStamps(); + + /* Mark all defs as being unvisited */ + (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); + + /* + * Recursively visit all defs in the tree + * and push on stack if they need extraction. + */ + extDefStack = StackNew(100); + (void) extDefIncrementalFunc(rootUse); + + /* Now extract all the cells we just found */ + extExtractStack(extDefStack, TRUE, rootUse->cu_def); + StackFree(extDefStack); +} + +/* + * Function to push each cell def on extDefStack if it hasn't + * already been pushed and if it needs re-extraction, and then + * recurse on all that def's children. + */ + +int +extDefIncrementalFunc(use) + CellUse *use; +{ + CellDef *def = use->cu_def; + + if (def->cd_client || (def->cd_flags&CDINTERNAL)) + return (0); + + def->cd_client = (ClientData) 1; + if (extTimestampMisMatch(def)) + StackPush((ClientData) def, extDefStack); + (void) DBCellEnum(def, extDefIncrementalFunc, (ClientData) 0); + return (0); +} + +/* + * Function returning TRUE if 'def' needs re-extraction. + * This will be the case if either the .ext file for 'def' + * does not exist, or if its timestamp fails to match that + * recorded in 'def'. + */ + +bool +extTimestampMisMatch(def) + CellDef *def; +{ + char line[256]; + FILE *extFile; + bool ret = TRUE; + int stamp; + + extFile = extFileOpen(def, (char *) NULL, "r", (char **) NULL); + if (extFile == NULL) + return (TRUE); + + if (fgets(line, sizeof line, extFile) == NULL) goto closeit; + if (sscanf(line, "timestamp %d", &stamp) != 1) goto closeit; + if (def->cd_timestamp != stamp) goto closeit; + ret = FALSE; + +closeit: + (void) fclose(extFile); + return (ret); +} + +/* + * ---------------------------------------------------------------------------- + * + * extExtractStack -- + * + * If 'doExtract' is TRUE, call ExtCell for each def on the stack 'stack'; + * otherwise, print the name of each def on the stack 'stack'. + * The root cell of the tree being processed is 'rootDef'; we only + * extract pathlength information for this cell. + * + * Results: + * None. + * + * Side effects: + * Leaves 'stack' empty. + * Calls ExtCell on each def on the stack if 'doExtract' is TRUE. + * Resets cd_client to 0 for each def on the stack. + * Prints the total number of errors and warnings. + * + * ---------------------------------------------------------------------------- + */ + +void +extExtractStack(stack, doExtract, rootDef) + Stack *stack; + bool doExtract; + CellDef *rootDef; +{ + int fatal = 0, warnings = 0; + bool first = TRUE; + CellDef *def; + + while (def = (CellDef *) StackPop(stack)) + { + def->cd_client = (ClientData) 0; + if (!SigInterruptPending) + { + if (doExtract) + { + ExtCell(def, (char *) NULL, (def == rootDef)); + fatal += extNumFatal; + warnings += extNumWarnings; + } + else + { + if (!first) TxPrintf(", "); + TxPrintf("%s", def->cd_name); + TxFlush(); + first = FALSE; + } + } + } + + if (!doExtract) + { + TxPrintf("\n"); + } + else + { + if (fatal > 0) + TxError("Total of %d fatal error%s.\n", + fatal, fatal != 1 ? "s" : ""); + if (warnings > 0) + TxError("Total of %d warning%s.\n", + warnings, warnings != 1 ? "s" : ""); + } +} diff --git a/extract/ExtNghbors.c b/extract/ExtNghbors.c new file mode 100644 index 00000000..b9ee25a0 --- /dev/null +++ b/extract/ExtNghbors.c @@ -0,0 +1,375 @@ +/* + * ExtNeighbors.c -- + * + * Circuit extraction. + * This file contains the primitive function ExtFindNeighbors() + * for visiting all neighbors of a tile that connect to it, and + * applying a filter function at each tile. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtNghbors.c,v 1.3 2010/09/12 20:32:33 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "utils/stack.h" + +/* + * The algorithm used by ExtFindNeighbors is non-recursive. + * It uses a stack (extNodeStack) to hold a list of tiles yet to + * be processed. To mark a tile as being on the stack, we store + * the value VISITPENDING in its ti_client field. + */ + +/* Used for communicating with extNbrPushFunc */ +ClientData extNbrUn; + +/* + * ---------------------------------------------------------------------------- + * + * ExtFindNeighbors -- + * + * For each tile adjacent to 'tile' that connects to it (according to + * arg->fra_connectsTo), and (if it is a contact) for tiles on other + * planes that connect to it, we recursively visit the tile, call the + * client's filter procedure (*arg->fra_each)(), if it is non-NULL. + * The tile is marked as being visited by setting it's ti_client field + * to arg->fra_region. + * + * Results: + * Returns the number of tiles that are found to be connected. + * This is used to find, for example, transistor gates made of + * only one tile, for which a simple calculation suffices for + * computing length and width. If an error occurred, returns + * the value -1. + * + * Side effects: + * See comments above. + * + * ---------------------------------------------------------------------------- + */ + +int +ExtFindNeighbors(tile, tilePlaneNum, arg) + Tile *tile; + int tilePlaneNum; + FindRegion *arg; +{ + TileTypeBitMask *connTo = arg->fra_connectsTo; + Tile *tp; + TileType type, t; + TileTypeBitMask *mask; + Rect biggerArea; + int pNum, tilesfound; + PlaneMask pMask; + PlaneAndArea pla; + + tilesfound = 0; + + extNbrUn = arg->fra_uninit; + if (extNodeStack == (Stack *) NULL) + extNodeStack = StackNew(64); + + /* Mark this tile as pending and push it */ + PUSHTILE(tile, tilePlaneNum); + + while (!StackEmpty(extNodeStack)) + { + POPTILE(tile, tilePlaneNum); + + if (IsSplit(tile)) + { + type = (SplitSide(tile)) ? SplitRightType(tile): + SplitLeftType(tile); + } + else + type = TiGetTypeExact(tile); + + mask = &connTo[type]; + + /* + * Since tile was pushed on the stack, we know that it + * belongs to this region. Check to see that it hasn't + * been visited in the meantime. If it's still unvisited, + * visit it and process its neighbors. + */ + if (tile->ti_client == (ClientData) arg->fra_region) + continue; + tile->ti_client = (ClientData) arg->fra_region; + tilesfound++; + if (DebugIsSet(extDebugID, extDebNeighbor)) + extShowTile(tile, "neighbor", 1); + + /* Top */ +topside: + if (IsSplit(tile) && (SplitSide(tile) ^ SplitDirection(tile))) goto leftside; + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + { + if (IsSplit(tp)) + { + t = SplitBottomType(tp); + // if (tp->ti_client == extNbrUn && TTMaskHasType(mask, t)) + if (tp->ti_client != (ClientData)arg->fra_region && TTMaskHasType(mask, t)) + { + PUSHTILEBOTTOM(tp, tilePlaneNum); + } + } + else + { + t = TiGetTypeExact(tp); + if (tp->ti_client == extNbrUn && TTMaskHasType(mask, t)) + { + PUSHTILE(tp, tilePlaneNum); + } + } + } + + /* Left */ +leftside: + if (IsSplit(tile) && SplitSide(tile)) goto bottomside; + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + { + if (IsSplit(tp)) + { + t = SplitRightType(tp); + // if (tp->ti_client == extNbrUn && TTMaskHasType(mask, t)) + if (tp->ti_client != (ClientData)arg->fra_region && TTMaskHasType(mask, t)) + { + PUSHTILERIGHT(tp, tilePlaneNum); + } + } + else + { + t = TiGetTypeExact(tp); + if (tp->ti_client == extNbrUn && TTMaskHasType(mask, t)) + { + PUSHTILE(tp, tilePlaneNum); + } + } + } + + /* Bottom */ +bottomside: + if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile)))) + goto rightside; + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + { + if (IsSplit(tp)) + { + t = SplitTopType(tp); + // if (tp->ti_client == extNbrUn && TTMaskHasType(mask, t)) + if (tp->ti_client != (ClientData)arg->fra_region && TTMaskHasType(mask, t)) + { + PUSHTILETOP(tp, tilePlaneNum); + } + } + else + { + t = TiGetTypeExact(tp); + if (tp->ti_client == extNbrUn && TTMaskHasType(mask, t)) + { + PUSHTILE(tp, tilePlaneNum); + } + } + } + + /* Right */ +rightside: + if (IsSplit(tile) && !SplitSide(tile)) goto donesides; + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + { + if (IsSplit(tp)) + { + t = SplitLeftType(tp); + // if (tp->ti_client == extNbrUn && TTMaskHasType(mask, t)) + if (tp->ti_client != (ClientData)arg->fra_region && TTMaskHasType(mask, t)) + { + PUSHTILELEFT(tp, tilePlaneNum); + } + } + else + { + t = TiGetTypeExact(tp); + if (tp->ti_client == extNbrUn && TTMaskHasType(mask, t)) + { + PUSHTILE(tp, tilePlaneNum); + } + } + } + +donesides: + /* Apply the client's filter procedure if one exists */ + if (arg->fra_each) + if ((*arg->fra_each)(tile, tilePlaneNum, arg)) + goto fail; + + /* If this is a contact, visit all the other planes */ + if (DBIsContact(type)) + { + pMask = DBConnPlanes[type]; + pMask &= ~(PlaneNumToMaskBit(tilePlaneNum)); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (PlaneMaskHasPlane(pMask, pNum)) + { + Plane *plane = arg->fra_def->cd_planes[pNum]; + + tp = plane->pl_hint; + GOTOPOINT(tp, &tile->ti_ll); + plane->pl_hint = tp; + if (tp->ti_client != extNbrUn) continue; + + /* tp and tile should have the same geometry for a contact */ + if (IsSplit(tile) && IsSplit(tp)) + { + if (SplitSide(tile)) + { + t = SplitRightType(tp); + if (TTMaskHasType(mask, t)) + { + PUSHTILERIGHT(tp, pNum); + } + } + else + { + t = SplitLeftType(tp); + if (TTMaskHasType(mask, t)) + { + PUSHTILELEFT(tp, pNum); + } + } + } + else if (IsSplit(tp)) + { + t = SplitRightType(tp); + if (TTMaskHasType(mask, t)) + { + PUSHTILERIGHT(tp, pNum); + } + t = SplitLeftType(tp); + if (TTMaskHasType(mask, t)) + { + PUSHTILELEFT(tp, pNum); + } + } + else + { + t = TiGetTypeExact(tp); + if (TTMaskHasType(mask, t)) + { + PUSHTILE(tp, pNum); + } + } + } + } + + /* + * The hairiest case is when this type connects to stuff on + * other planes, but isn't itself connected as a contact. + * For example, a CMOS pwell connects to diffusion of the + * same doping (p substrate diff). In a case like this, + * we need to search the entire AREA of the tile plus a + * 1-lambda halo to find everything it overlaps or touches + * on the other plane. + */ + if (pMask = DBAllConnPlanes[type]) + { + TITORECT(tile, &pla.area); + GEO_EXPAND(&pla.area, 1, &biggerArea); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if ((pNum != tilePlaneNum) && PlaneMaskHasPlane(pMask, pNum)) + { + pla.plane = pNum; + (void) DBSrPaintArea((Tile *) NULL, + arg->fra_def->cd_planes[pNum], &biggerArea, + mask, extNbrPushFunc, (ClientData) &pla); + } + } + } + + return tilesfound; + +fail: + /* Flush the stack */ + while (!StackEmpty(extNodeStack)) + { + POPTILE(tile, tilePlaneNum); + tile->ti_client = (ClientData) arg->fra_region; + } + return -1; +} + +/* + * ---------------------------------------------------------------------------- + * + * extNbrPushFunc -- + * + * Called for each tile overlapped by a 1-unit wide halo around the area + * tileArea. If the tile overlaps or shares a non-null segment of border + * with tileArea, and it hasn't already been visited, push it on the stack + * extNodeStack. + * + * Uses the global parameter extNbrUn to determine whether or not a tile + * has been visited; if the tile's client field is equal to extNbrUn, then + * this is the first time the tile has been seen. + * + * Results: + * Always returns 0. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +extNbrPushFunc(tile, pla) + Tile *tile; + PlaneAndArea *pla; +{ + Rect *tileArea; + Rect r; + + tileArea = &pla->area; + + /* Ignore tile if it's already been visited */ + if (tile->ti_client != extNbrUn) + return 0; + + /* Only consider tile if it overlaps tileArea or shares part of a side */ + TITORECT(tile, &r); + if (!GEO_OVERLAP(&r, tileArea)) + { + GEOCLIP(&r, tileArea); + if (r.r_xbot >= r.r_xtop && r.r_ybot >= r.r_ytop) + return 0; + } + + /* Push tile on the stack and mark as being visited */ + PUSHTILE(tile, pla->plane); + + return 0; +} diff --git a/extract/ExtPerim.c b/extract/ExtPerim.c new file mode 100644 index 00000000..31847a9c --- /dev/null +++ b/extract/ExtPerim.c @@ -0,0 +1,183 @@ +/* + * ExtPerim.c -- + * + * Circuit extraction. + * Functions for tracing the perimeter of a tile or of a + * connected region. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtPerim.c,v 1.5 2010/09/12 20:32:33 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "utils/stack.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" + +#define POINTEQUAL(p, q) ((p)->p_x == (q)->p_x && (p)->p_y == (q)->p_y) + +/* + * ---------------------------------------------------------------------------- + * + * extEnumTilePerim -- + * + * Visit all the tiles along the perimeter of 'tpIn' whose types are in + * the mask 'mask'. For each such tile, call the supplied function 'func' + * if it is non-null: + * + * (*func)(bp, cdata) + * Boundary *bp; /# bp->b_inside is tpIn, bp->b_outside + * # is the tile along the boundary of tpIn, + * # and bp->b_segment is the segment of the + * # boundary in common. + * #/ + * ClientData cdata; /# Supplied in call to extEnumTilePerim #/ + * { + * } + * + * The value returned by this function is ignored. + * + * Results: + * Returns the total length of the portion of the perimeter of + * 'tpIn' that borders tiles whose types are in 'mask'. + * + * Side effects: + * None directly, but applies the client's filter function + * to each qualifying segment of the boundary. + * + * Note: + * The width/length calculation method is manhattan-only. So this + * routine is pseudo-manhattan. It computes the true non-manhattan + * perimeter, but calls the function on the perimeter tiles as if + * the whole tile is the transistor type. + * + * Non-interruptible. + * + * ---------------------------------------------------------------------------- + */ + +int +extEnumTilePerim(tpIn, mask, pNum, func, cdata) + Tile *tpIn; + TileTypeBitMask mask; /* Note: this is not a pointer */ + int pNum; /* Plane of perimeter */ + int (*func)(); + ClientData cdata; +{ + TileType origType; + Tile *tpOut; + int perimCorrect; + Boundary b; + unsigned char sides = 0; + + b.b_inside = tpIn; + b.b_plane = pNum; + perimCorrect = 0; + + /* Diagonal */ + if (IsSplit(tpIn)) + { + TileType otype = (SplitSide(tpIn)) ? SplitLeftType(tpIn): SplitRightType(tpIn); + TileType itype = (SplitSide(tpIn)) ? SplitRightType(tpIn): SplitLeftType(tpIn); + origType = TiGetTypeExact(tpIn); + if (TTMaskHasType(&mask, otype)) + { + int width = RIGHT(tpIn) - LEFT(tpIn); + int height = TOP(tpIn) - BOTTOM(tpIn); + perimCorrect = width * width + height * height; + perimCorrect = (int)sqrt((double)perimCorrect); + } + sides = (SplitSide(tpIn)) ? BD_LEFT : BD_RIGHT; + sides |= (SplitSide(tpIn) == SplitDirection(tpIn)) ? BD_BOTTOM : BD_TOP; + TiSetBody(tpIn, itype); + } + else + sides = 0; + + /* Top */ + b.b_segment.r_ybot = b.b_segment.r_ytop = TOP(tpIn); + b.b_direction = BD_TOP; + for (tpOut = RT(tpIn); RIGHT(tpOut) > LEFT(tpIn); tpOut = BL(tpOut)) + { + if (TTMaskHasType(&mask, TiGetBottomType(tpOut))) + { + b.b_segment.r_xbot = MAX(LEFT(tpIn), LEFT(tpOut)); + b.b_segment.r_xtop = MIN(RIGHT(tpIn), RIGHT(tpOut)); + b.b_outside = tpOut; + if (sides & BD_TOP) perimCorrect -= BoundaryLength(&b); + if (func) (*func)(&b, cdata); + } + } + + /* Bottom */ + b.b_segment.r_ybot = b.b_segment.r_ytop = BOTTOM(tpIn); + b.b_direction = BD_BOTTOM; + for (tpOut = LB(tpIn); LEFT(tpOut) < RIGHT(tpIn); tpOut = TR(tpOut)) + { + if (TTMaskHasType(&mask, TiGetTopType(tpOut))) + { + b.b_segment.r_xbot = MAX(LEFT(tpIn), LEFT(tpOut)); + b.b_segment.r_xtop = MIN(RIGHT(tpIn), RIGHT(tpOut)); + b.b_outside = tpOut; + if (sides & BD_BOTTOM) perimCorrect -= BoundaryLength(&b); + if (func) (*func)(&b, cdata); + } + } + + /* Left */ + b.b_segment.r_xbot = b.b_segment.r_xtop = LEFT(tpIn); + b.b_direction = BD_LEFT; + for (tpOut = BL(tpIn); BOTTOM(tpOut) < TOP(tpIn); tpOut = RT(tpOut)) + { + if (TTMaskHasType(&mask, TiGetRightType(tpOut))) + { + b.b_segment.r_ybot = MAX(BOTTOM(tpIn), BOTTOM(tpOut)); + b.b_segment.r_ytop = MIN(TOP(tpIn), TOP(tpOut)); + b.b_outside = tpOut; + if (sides & BD_LEFT) perimCorrect -= BoundaryLength(&b); + if (func) (*func)(&b, cdata); + } + } + + /* Right */ + b.b_segment.r_xbot = b.b_segment.r_xtop = RIGHT(tpIn); + b.b_direction = BD_RIGHT; + for (tpOut = TR(tpIn); TOP(tpOut) > BOTTOM(tpIn); tpOut = LB(tpOut)) + { + if (TTMaskHasType(&mask, TiGetLeftType(tpOut))) + { + b.b_segment.r_ybot = MAX(BOTTOM(tpIn), BOTTOM(tpOut)); + b.b_segment.r_ytop = MIN(TOP(tpIn), TOP(tpOut)); + b.b_outside = tpOut; + if (sides & BD_RIGHT) perimCorrect -= BoundaryLength(&b); + if (func) (*func)(&b, cdata); + } + } + + if (sides != 0) + TiSetBody(tpIn, origType); + + return (perimCorrect); +} diff --git a/extract/ExtRegion.c b/extract/ExtRegion.c new file mode 100644 index 00000000..c392462b --- /dev/null +++ b/extract/ExtRegion.c @@ -0,0 +1,454 @@ +/* + * ExtRegion.c -- + * + * Circuit extraction. + * This file contains the code to trace out connected Regions + * in a layout, and to build up or tear down lists of Regions. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtRegion.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" + +/* + * ---------------------------------------------------------------------------- + * + * ExtFindRegions -- + * + * Find all the connected geometrical regions in a given area of a CellDef + * that will correspond to nodes or devices in the extracted circuit. + * Two procedures are supplied by the caller, 'first' and 'each'. + * + * The function 'first' must be non-NULL. It is called for each tile + * tile found in the region. It must return a pointer to a Region + * struct (or one of the client forms of a Region struct; see the + * comments in extractInt.h). + * + * Region * + * (*first)(tile, arg) + * Tile *tile; /# Tile is on plane arg->fra_pNum #/ + * FindRegion *arg; + * { + * } + * + * If the function 'each' is non-NULL, it is applied once to each tile found + * in the region: + * + * (*each)(tile, planeNum, arg) + * Tile *tile; + * int planeNum; /# May be different than arg->fra_pNum #/ + * FindRegion *arg; + * { + * } + * + * Results: + * Returns a pointer to the first element in the linked list + * of Region structures for this CellDef. The Region structs + * may in fact contain more than the basic Region struct; this + * will depend on what the function 'first' allocates. + * + * Side effects: + * Each non-space tile has its ti_client field left pointing + * to a Region structure that describes the region that tile + * belongs to. + * + * Non-interruptible. It is the caller's responsibility to check + * for interrupts. + * + * ---------------------------------------------------------------------------- + */ + +Region * +ExtFindRegions(def, area, mask, connectsTo, uninit, first, each) + CellDef *def; /* Cell definition being searched */ + Rect *area; /* Area to search initially for tiles */ + TileTypeBitMask *mask; /* In the initial area search, only visit + * tiles whose types are in this mask. + */ + TileTypeBitMask *connectsTo;/* Connectivity table for determining regions. + * If t1 and t2 are the types of adjacent + * tiles, then t1 and t2 belong to the same + * region iff: + * TTMaskHasType(&connectsTo[t1], t2) + * + * We assume that connectsTo[] is symmetric, + * so this is the same as: + * TTMaskHasType(&connectsTo[t2], t1) + */ + ClientData uninit; /* Contents of a ti_client field indicating + * that the tile has not yet been visited. + */ + Region * (*first)(); /* Applied to first tile in region */ + int (*each)(); /* Applied to each tile in region */ +{ + FindRegion arg; + int extRegionAreaFunc(); + + ASSERT(first != NULL, "ExtFindRegions"); + arg.fra_connectsTo = connectsTo; + arg.fra_def = def; + arg.fra_uninit = uninit; + arg.fra_first = first; + arg.fra_each = each; + arg.fra_region = (Region *) NULL; + + SigDisableInterrupts(); + for (arg.fra_pNum=PL_TECHDEPBASE; arg.fra_pNumcd_planes[arg.fra_pNum], + area, mask, uninit, extRegionAreaFunc, (ClientData) &arg); + SigEnableInterrupts(); + + return (arg.fra_region); +} + +/* + * ---------------------------------------------------------------------------- + * + * extRegionAreaFunc -- + * + * Filter function called for each tile found during the area enumeration + * in ExtFindRegions above. Only tiles whose ti_client is not already + * equal to arg->fra_uninit are visited. + * + * We call 'fra_first' to allocate a new region struct for it, and then + * prepend it to the Region list (Region *) arg->fra_clientData. We + * then call ExtFindNeighbors to trace out recursively all the remaining + * tiles in the region. + * + * Results: + * Always returns 0, to cause DBSrPaintClient to continue its search. + * + * Side effects: + * Allocates a new Region struct if the tile has not yet been visited. + * See also the comments for ExtFindNeighbors. + * + * ---------------------------------------------------------------------------- + */ + +int +extRegionAreaFunc(tile, arg) + Tile *tile; + FindRegion *arg; +{ + /* Allocate a new region */ + if (arg->fra_first) + (void) (*arg->fra_first)(tile, arg); + + if (DebugIsSet(extDebugID, extDebAreaEnum)) + extShowTile(tile, "area enum", 0); + + /* Recursively visit all tiles surrounding this one that we connect to */ + (void) ExtFindNeighbors(tile, arg->fra_pNum, arg); + return (0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * ExtLabelRegions -- + * + * Given a CellDef whose tiles have been set to point to LabRegions + * by ExtFindRegions, walk down the label list and assign labels + * to regions. If the tile over which a label lies is still uninitialized + * ie, points to extUnInit, we skip the label. + * + * A label is attached to the LabRegion for a tile if the label's + * type and the tile's type are connected according to the table + * 'connTo'. This disambiguates the case where a label lies + * on the boundary between two tiles of different types. + * + * Results: + * None. + * + * Side effects: + * Each LabRegion has labels added to its label list. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtLabelRegions(def, connTo, nodeList, clipArea) + CellDef *def; /* Cell definition being labelled */ + TileTypeBitMask *connTo; /* Connectivity table (see above) */ + NodeRegion **nodeList; /* Node list to add to (or NULL) */ + Rect *clipArea; /* Area to search for sticky labels */ +{ + static Point offsets[] = { { 0, 0 }, { 0, -1 }, { -1, -1 }, { -1, 0 } }; + LabelList *ll; + Label *lab; + Tile *tp; + LabRegion *reg; + int quad, pNum; + Point p; + bool found; + + for (lab = def->cd_labels; lab; lab = lab->lab_next) + { + found = FALSE; + pNum = DBPlane(lab->lab_type); + if (lab->lab_type == TT_SPACE || pNum < PL_TECHDEPBASE) + continue; + for (quad = 0; quad < 4; quad++) + { + /* + * Visit each of the four quadrants surrounding + * the lower-left corner of the label, searching + * for a tile whose type matches that of the label + * or connects to it. + */ + p.p_x = lab->lab_rect.r_xbot + offsets[quad].p_x; + p.p_y = lab->lab_rect.r_ybot + offsets[quad].p_y; + tp = def->cd_planes[pNum]->pl_hint; + GOTOPOINT(tp, &p); + def->cd_planes[pNum]->pl_hint = tp; + if (extConnectsTo(TiGetType(tp), lab->lab_type, connTo) + && extHasRegion(tp, extUnInit)) + { + found = TRUE; + reg = (LabRegion *) extGetRegion(tp); + ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList))); + ll->ll_label = lab; + ll->ll_next = reg->lreg_labels; + reg->lreg_labels = ll; + if (lab->lab_flags & PORT_DIR_MASK) + ll->ll_attr = LL_PORTATTR; + else + ll->ll_attr = LL_NOATTR; + break; + } + } + if ((found == FALSE) && (nodeList != NULL)) + { + // Unconnected node label. This may be a "sticky label". + // If it is not connected to TT_SPACE, then create a new + // node region for it. + // (3/24/2015---changed from GEO_LABEL_IN_AREA to GEO_SURROUND) + + if ((GEO_SURROUND(&lab->lab_rect, clipArea) || + GEO_TOUCH(&lab->lab_rect, clipArea)) + && (lab->lab_type != TT_SPACE)) + { + NodeRegion *newNode; + int n; + int nclasses = ExtCurStyle->exts_numResistClasses; + + n = sizeof (NodeRegion) + (sizeof (PerimArea) * (nclasses - 1)); + newNode = (NodeRegion *)mallocMagic((unsigned) n); + + ll = (LabelList *)mallocMagic(sizeof(LabelList)); + ll->ll_label = lab; + ll->ll_next = NULL; + if (lab->lab_flags & PORT_DIR_MASK) + ll->ll_attr = LL_PORTATTR; + else + ll->ll_attr = LL_NOATTR; + + newNode->nreg_next = *nodeList; + newNode->nreg_pnum = pNum; + newNode->nreg_type = lab->lab_type; + newNode->nreg_ll = lab->lab_rect.r_ll; + newNode->nreg_cap = (CapValue)0; + newNode->nreg_resist = 0; + for (n = 0; n < nclasses; n++) + newNode->nreg_pa[n].pa_perim = newNode->nreg_pa[n].pa_area = 0; + newNode->nreg_labels = ll; + + *nodeList = newNode; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtLabelOneRegion -- + * + * Same as ExtLabelRegion, but it only assigns labels to one particular + * region. + * + * Results: + * None. + * + * Side effects: + * The region has labels added to its label list. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtLabelOneRegion(def, connTo, reg) + CellDef *def; /* Cell definition being labelled */ + TileTypeBitMask *connTo; /* Connectivity table (see above) */ + NodeRegion *reg; /* The region whose labels we want */ +{ + static Point offsets[] = { { 0, 0 }, { 0, -1 }, { -1, -1 }, { -1, 0 } }; + LabelList *ll; + Label *lab; + Tile *tp; + int quad, pNum; + Point p; + + /* Generate segment list for subcircuit boundary, if any */ + + for (lab = def->cd_labels; lab; lab = lab->lab_next) + { + pNum = DBPlane(lab->lab_type); + if (lab->lab_type == TT_SPACE || pNum < PL_TECHDEPBASE) + continue; + for (quad = 0; quad < 4; quad++) + { + /* + * Visit each of the four quadrants surrounding + * the lower-left corner of the label, searching + * for a tile whose type matches that of the label + * or connects to it. + */ + p.p_x = lab->lab_rect.r_xbot + offsets[quad].p_x; + p.p_y = lab->lab_rect.r_ybot + offsets[quad].p_y; + tp = def->cd_planes[pNum]->pl_hint; + GOTOPOINT(tp, &p); + def->cd_planes[pNum]->pl_hint = tp; + if (extConnectsTo(TiGetType(tp), lab->lab_type, connTo) + && (NodeRegion *) extGetRegion(tp) == reg) + { + ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList))); + ll->ll_label = lab; + ll->ll_next = reg->nreg_labels; + reg->nreg_labels = ll; + if (lab->lab_flags & PORT_DIR_MASK) + ll->ll_attr = LL_PORTATTR; + else + ll->ll_attr = LL_NOATTR; + break; + } + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * ExtResetTiles -- + * + * Given a CellDef whose tiles have been set to point to Regions + * by ExtFindRegions, reset all the tiles to uninitialized. + * + * Results: + * None. + * + * Side effects: + * All the non-space tiles in the CellDef have their ti_client + * fields set back to uninitialized. Does not free the Region + * structs that these tiles point to; that must be done by + * ExtFreeRegions, ExtFreeLabRegions, or ExtFreeHierLabRegions. + * + * Non-interruptible. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtResetTiles(def, resetTo) + CellDef *def; + ClientData resetTo; /* New value for ti_client */ +{ + int pNum; + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + DBResetTilePlane(def->cd_planes[pNum], resetTo); +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtFreeRegions -- + * ExtFreeLabRegions -- + * ExtFreeHierLabRegions -- + * + * Free a list of Regions. + * ExtFreeLabRegions also frees the LabelLists pointed to by lreg_labels. + * ExtFreeHierLabRegions, in addition to freeing the LabelLists, frees + * the labels they point to. + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * + * Non-interruptible. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtFreeRegions(regList) + Region *regList; /* List of regions to be freed */ +{ + Region *reg; + + for (reg = regList; reg; reg = reg->reg_next) + freeMagic((char *) reg); +} + +void +ExtFreeLabRegions(regList) + LabRegion *regList; /* List of regions to be freed */ +{ + LabRegion *lreg; + LabelList *ll; + + for (lreg = regList; lreg; lreg = lreg->lreg_next) + { + for (ll = lreg->lreg_labels; ll; ll = ll->ll_next) + freeMagic((char *) ll); + freeMagic((char *) lreg); + } +} + +void +ExtFreeHierLabRegions(regList) + Region *regList; /* List of regions to be freed */ +{ + Region *reg; + LabelList *ll; + + for (reg = regList; reg; reg = reg->reg_next) + { + for (ll = ((LabRegion *)reg)->lreg_labels; ll; ll = ll->ll_next) + { + freeMagic((char *) ll->ll_label); + freeMagic((char *) ll); + } + freeMagic((char *) reg); + } +} diff --git a/extract/ExtSubtree.c b/extract/ExtSubtree.c new file mode 100644 index 00000000..d484d73e --- /dev/null +++ b/extract/ExtSubtree.c @@ -0,0 +1,1141 @@ +/* + * ExtSubtree.c -- + * + * Circuit extraction. + * Extracts interactions between subtrees of a parent and the + * parent itself. Does not handle extraction of interactions + * arising between elements of the same array; those are handled + * by the procedures in ExtArray.c + * + * The procedures in this file are not re-entrant. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtSubtree.c,v 1.3 2010/06/24 12:37:17 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" + +#ifdef exactinteractions +/* + * If "exactinteractions" is defined, we use an experimental algorithm + * for finding exact interaction areas. Currently it doesn't work too + * well, so we leave it turned off. + */ +int ExtInterBloat = 10; +#endif /* exactinteractions */ + +/* Imports from elsewhere in this module */ +extern int extHierYankFunc(); +extern LabRegion *extSubtreeHardNode(); +extern Node *extHierNewNode(); +extern ExtTree *extHierNewOne(); + +/* Global data incremented by extSubtree() */ +int extSubtreeTotalArea; /* Total area of cell */ +int extSubtreeInteractionArea; /* Total area of all interactions, counting the + * entire area of the interaction each time. + */ +int extSubtreeClippedArea; /* Total area of all interactions, counting only + * the area that lies inside each chunk, so no + * area is counted more than once. + */ + +/* Local data */ + + /* TRUE if processing the first subtree in an interaction area */ +bool extFirstPass; + + /* Points to list of subtrees in an interaction area */ +ExtTree *extSubList = (ExtTree *) NULL; + +/* Forward declarations of filter functions */ +char *extSubtreeTileToNode(); +int extSubtreeFunc(); +int extConnFindFunc(); +int extSubtreeHardUseFunc(); +int extHardProc(); +int extSubtreeCopyPlane(); +int extSubtreeShrinkPlane(); +void extSubtreeInteraction(); +void extSubtreeAdjustInit(); +void extSubtreeOutputCoupling(); +void extSubtreeHardSearch(); + + +/* + * ---------------------------------------------------------------------------- + * + * extSubtree -- + * + * Do the hierarchical part of extracting the cell 'parentUse->cu_def'. + * This consists of finding all connections either between geometry in the + * parent and geometry in a subcell, or between geometry in two overlapping + * or adjacent subcells. + * + * This procedure only finds interaction areas, where subcells are close + * to each other or to mask information, and then calls extSubtreeInteraction() + * to do the real work. See the comments there for more details. + * + * Results: + * None. + * + * Side effects: + * Outputs connections and adjustments to the file 'f'. + * There are two kinds of records: + * + * merge node1 node2 deltaC deltaP1 deltaA1 deltaP2 deltaA2 ... + * cap node1 node2 deltaC + * + * The first merges node1 and node2, adjusts the substrate capacitance + * by adding deltaC (usually negative), and the node perimeter and area + * for each resistive layer n by deltaPn deltaAn. + * + * The second adjusts the coupling capacitance between node1 and node2 + * by deltaC, which may be positive or negative. + * + * ---------------------------------------------------------------------------- + */ + +#define RECTAREA(r) (((r)->r_xtop-(r)->r_xbot) * ((r)->r_ytop-(r)->r_ybot)) + +void +extSubtree(parentUse, reg, f) + CellUse *parentUse; + NodeRegion *reg; /* Node regions of the parent cell */ + FILE *f; +{ + int extSubtreeInterFunc(); + CellDef *def = parentUse->cu_def; + int halo = ExtCurStyle->exts_sideCoupleHalo + 1; + HierExtractArg ha; + Rect r, rlab, rbloat, *b; + Label *lab; + bool result; + + if ((ExtOptions & (EXT_DOCOUPLING|EXT_DOADJUST)) + != (EXT_DOCOUPLING|EXT_DOADJUST)) + halo = 1; + + /* + * The cumulative buffer is initially empty. It will be built up + * for each interaction area, and then cleared before processing + * the next one. + * + * The connection hash table is initialized here but doesn't get + * cleared until the end. It is responsible for changes to the + * node structure over the entire cell 'def'. + */ + extSubtreeTotalArea += RECTAREA(&def->cd_bbox); + ha.ha_outf = f; + ha.ha_parentUse = parentUse; + ha.ha_parentReg = reg; + ha.ha_nodename = extSubtreeTileToNode; + ha.ha_cumFlat.et_use = extYuseCum; + HashInit(&ha.ha_connHash, 32, 0); + +#ifndef exactinteractions + /* + * Cookie-cutter up def into pieces ExtCurStyle->exts_stepSize by + * ExtCurStyle->exts_stepSize. + * Find all interaction areas (within halo units distance, where + * halo has been set above to reflect the maximum distance for + * sidewall coupling capacitance). + */ + b = &def->cd_bbox; + for (r.r_ybot = b->r_ybot; r.r_ybot < b->r_ytop; r.r_ybot = r.r_ytop) + { + r.r_ytop = r.r_ybot + ExtCurStyle->exts_stepSize; + for (r.r_xbot = b->r_xbot; r.r_xbot < b->r_xtop; r.r_xbot = r.r_xtop) + { + r.r_xtop = r.r_xbot + ExtCurStyle->exts_stepSize; + if (SigInterruptPending) + goto done; + rbloat = r; + rbloat.r_xbot -= halo, rbloat.r_ybot -= halo; + rbloat.r_xtop += halo, rbloat.r_ytop += halo; + result = DRCFindInteractions(def, &rbloat, halo, &ha.ha_interArea); + + // Check area for labels. Expand interaction area to include + // the labels. This catches labels that are not attached to + // any geometry in the cell and therefore do not get flagged by + // DRCFindInteractions(). + + for (lab = def->cd_labels; lab; lab = lab->lab_next) + if (GEO_OVERLAP(&lab->lab_rect, &r) || GEO_TOUCH(&lab->lab_rect, &r)) { + // Clip the label area to the area of rbloat + rlab = lab->lab_rect; + GEOCLIP(&rlab, &rbloat); + if (!result) { + // If result == FALSE then ha.ha_interArea is invalid. + ha.ha_interArea = rlab; + result = TRUE; + } + else + result |= GeoIncludeAll(&rlab, &ha.ha_interArea); + } + + if (result) + { + ha.ha_clipArea = ha.ha_interArea; + GEOCLIP(&ha.ha_clipArea, &r); + extSubtreeInteractionArea += RECTAREA(&ha.ha_interArea); + extSubtreeClippedArea += RECTAREA(&ha.ha_clipArea); + extSubtreeInteraction(&ha); + } + } + } +#else /* exactinteractions */ + { + static Plane *interPlane = NULL, *bloatPlane = NULL; + + /* + * Experimental code to find exact interaction areas. + * Currently, this both takes longer to find interactions + * and longer to process them than the cookie-cutter + * approach above, but maybe it can be turned into a + * scheme that is faster. + */ + if (interPlane == (Plane *) NULL) + interPlane = DBNewPlane((ClientData) TT_SPACE); + if (bloatPlane == (Plane *) NULL) + bloatPlane = DBNewPlane((ClientData) TT_SPACE); + ExtFindInteractions(def, halo, ExtInterBloat, interPlane); + if (ExtInterBloat) + { + /* Shrink back down */ + (void) DBSrPaintArea((Tile *) NULL, interPlane, + &TiPlaneRect, &DBAllButSpaceBits, + extSubtreeCopyPlane, (ClientData) bloatPlane); + (void) DBSrPaintArea((Tile *) NULL, bloatPlane, + &TiPlaneRect, &DBSpaceBits, + extSubtreeShrinkPlane, (ClientData) interPlane); + DBClearPaintPlane(bloatPlane); + } + (void) DBSrPaintArea((Tile *) NULL, interPlane, + &TiPlaneRect, &DBAllButSpaceBits, + extSubtreeInterFunc, (ClientData) &ha); + DBClearPaintPlane(interPlane); + } +#endif /* exactinteractions */ + +done: + /* Output connections and node adjustments */ + extOutputConns(&ha.ha_connHash, f); + HashKill(&ha.ha_connHash); +} + +#ifdef exactinteractions +int +extSubtreeCopyPlane(tile, plane) + Tile *tile; + Plane *plane; +{ + Rect r; + + TITORECT(tile, &r); + (void) DBPaintPlane(plane, &r, DBStdWriteTbl(TT_ERROR_P), + (PaintUndoInfo *) NULL); + return (0); +} + +int +extSubtreeShrinkPlane(tile, plane) + Tile *tile; + Plane *plane; +{ + Rect r; + + TITORECT(tile, &r); + r.r_xbot -= ExtInterBloat; r.r_ybot -= ExtInterBloat; + r.r_xtop += ExtInterBloat; r.r_ytop += ExtInterBloat; + GEOCLIP(&r, &TiPlaneRect); + (void) DBPaintPlane(plane, &r, DBStdWriteTbl(TT_SPACE), + (PaintUndoInfo *) NULL); + return (0); +} + +int +extSubtreeInterFunc(tile, ha) + Tile *tile; + HierExtractArg *ha; +{ + TITORECT(tile, &ha->ha_interArea); + ha->ha_clipArea = ha->ha_interArea; + extSubtreeInteractionArea += RECTAREA(&ha->ha_interArea); + extSubtreeClippedArea += RECTAREA(&ha->ha_clipArea); + extSubtreeInteraction(ha); + return (0); +} +#endif /* exactinteractions */ + +/* + * ---------------------------------------------------------------------------- + * + * extSubtreeInteraction -- + * + * Having found an interaction area, we process it. + * The def being extracted is ha->ha_parentUse->cu_def. + * + * Clipping: + * The cookie-cutter piece we were looking at for the interaction is + * ha->ha_clipArea, and the interaction area actually found is + * ha->ha_interArea. It is possible that ha->ha_interArea extends + * outside of ha->ha_clipArea; if this is the case, all area and + * perimeter outside of ha->ha_clipArea are ignored when making + * adjustments. When computing sidewall coupling capacitance, + * we search for an initial tile only inside ha->ha_clipArea. + * + * Algorithm: + * Extracting an interaction area consists of two passes. + * + * The first pass will build the connection table ha->ha_connHash, + * but leave the adjustment for each connection as zero. At the + * end of the first pass, extSubList is a list of ExtTrees containing + * each flattened subtree in the area of the interaction (including + * the parent geometry), and ha->ha_cumFlat contains everything + * flattened. + * + * The second pass will make the adjustments in ha->ha_connHash, and + * will build the table et_coupleHash in ha->ha_cumFlat. All of + * the table ha->ha_connHash will be output, but only those entries + * in et_coupleHash with non-zero capacitance adjustment (either + * positive or negative) will get output. + * + * Results: + * None. + * + * Side effects: + * Adds more information to ha->ha_connHash and + * ha->ha_cumFlat.et_coupleHash. + * + * ---------------------------------------------------------------------------- + */ + +void +extSubtreeInteraction(ha) + HierExtractArg *ha; /* Context for hierarchical extraction */ +{ + CellDef *oneDef, *cumDef = ha->ha_cumFlat.et_use->cu_def; + ExtTree *oneFlat, *nextFlat; + NodeRegion *reg; + SearchContext scx; + + /* Copy parent paint into ha->ha_cumFlat (which was initially empty) */ + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = ha->ha_interArea; + scx.scx_use = ha->ha_parentUse; + DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, ha->ha_cumFlat.et_use); +#ifdef notdef + extCopyPaint(ha->ha_parentUse->cu_def, &ha->ha_interArea, cumDef); +#endif /* notdef */ + + /* + * First element on the subtree list will be parent mask info. + * Extract nodes and capacitors. Node names come from parent. + */ + oneFlat = extHierNewOne(); + oneDef = oneFlat->et_use->cu_def; + DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, oneFlat->et_use); + +#ifdef notdef + extCopyPaint(ha->ha_parentUse->cu_def, &ha->ha_interArea, oneDef); +#endif /* notdef */ + oneFlat->et_nodes = extFindNodes(oneDef, &ha->ha_clipArea, FALSE); + if ((ExtOptions & (EXT_DOCOUPLING|EXT_DOADJUST)) + == (EXT_DOCOUPLING|EXT_DOADJUST)) + { + HashInit(&oneFlat->et_coupleHash, 32, HashSize(sizeof (CoupleKey))); + extFindCoupling(oneDef, &oneFlat->et_coupleHash, &ha->ha_clipArea); + } + oneFlat->et_lookNames = ha->ha_parentUse->cu_def; + oneFlat->et_realuse = (CellUse *) NULL; + extSubList = oneFlat; + + /* + * Cumulative yank buffer names also come from parent. + * Since we only mark nodes for use in naming on the first + * pass, there's no need to extract nodes in ha_cumFlat + * until we process the first subcell in extSubtreeFunc. + */ + ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL; + ha->ha_cumFlat.et_lookNames = ha->ha_parentUse->cu_def; + extFirstPass = TRUE; + + /* + * Process each subcell in the interaction area exactly once. + * After processing each subcell, we reset ha->ha_cumFlat.et_nodes + * to NULL. + */ + (void) DBCellSrArea(&scx, extSubtreeFunc, (ClientData) ha); + + if (ExtOptions & EXT_DOADJUST) + { + /* + * Re-extract ha->ha_cumFlat, this time getting node capacitance, + * perimeter, and area, and coupling capacitances between nodes. + * Assign labels from cumDef's label list. + * Don't reset ha_lookNames, since we still need to be able to + * refer to nodes in the parent. + */ + ha->ha_cumFlat.et_nodes = extFindNodes(cumDef, &ha->ha_clipArea, FALSE); + ExtLabelRegions(cumDef, ExtCurStyle->exts_nodeConn, + &(ha->ha_cumFlat.et_nodes), &ha->ha_clipArea); + if (ExtOptions & EXT_DOCOUPLING) + { + HashInit(&ha->ha_cumFlat.et_coupleHash, 32, + HashSize(sizeof(CoupleKey))); + extFindCoupling(cumDef, &ha->ha_cumFlat.et_coupleHash, + &ha->ha_clipArea); + } + + /* Process all adjustments */ + ha->ha_subUse = (CellUse *) NULL; + extSubtreeAdjustInit(ha); + for (oneFlat = extSubList; oneFlat; oneFlat = oneFlat->et_next) + extHierAdjustments(ha, &ha->ha_cumFlat, oneFlat, &ha->ha_cumFlat); + + /* + * Output adjustments to substrate capacitance that are not + * output anywhere else. Nodes that connect down into the + * hierarchy are part of ha_connHash and have adjustments + * that are printed in the "merge" statement. Nodes not in + * the current cell are not considered. Anything left over + * has its adjusted value output. + */ + for (reg = ha->ha_parentReg; reg; reg = reg->nreg_next) + { + Rect r; + NodeRegion *treg; + CapValue finC; + char *text; + + r.r_ll = reg->nreg_ll; + r.r_xtop = r.r_xbot + 1; + r.r_ytop = r.r_ybot + 1; + + /* Use the tile position of the parent region to find the + * equivalent region in cumDef. Then compare the substrate + * cap and output the difference. + */ + + if (DBSrPaintArea((Tile *)NULL, cumDef->cd_planes[reg->nreg_pnum], + &r, &DBAllButSpaceBits, extConnFindFunc, + (ClientData) &treg)) + { + text = extNodeName(reg); + // Output the adjustment made to the substrate cap + // (should be negative). Ignore adjustments of zero + finC = (treg->nreg_cap - reg->nreg_cap) / + ExtCurStyle->exts_capScale; + if (finC < -1.0E-6) + fprintf(ha->ha_outf, "subcap \"%s\" %lg\n", text, finC); + } + } + + /* + * Output adjustments to coupling capacitance. + * The names output for coupling capacitors are those on the + * label list for each node in the cumulative buffer. + */ + if (ExtOptions & EXT_DOCOUPLING) + { + extSubtreeOutputCoupling(ha); + extCapHashKill(&ha->ha_cumFlat.et_coupleHash); + } + } + + /* Free the subtrees (this must happen after all adjustments are made) */ + for (oneFlat = extSubList; oneFlat; oneFlat = nextFlat) + nextFlat = oneFlat->et_next, extHierFreeOne(oneFlat); + extSubList = (ExtTree *) NULL; + + /* + * Done with the cumulative yank buffer for this interaction. + * Free the list of nodes, the list of hierarchical labels + * built when we yanked this def, and then erase all the paint + * in the buffer. + */ + if (ha->ha_cumFlat.et_nodes) + ExtFreeLabRegions((LabRegion *) ha->ha_cumFlat.et_nodes); + ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL; + extHierFreeLabels(cumDef); + DBCellClearDef(cumDef); +} + +/* + * ---------------------------------------------------------------------------- + * + * extSubtreeAdjustInit -- + * + * Initialize the node capacitance, perimeter, and area values in + * all the Nodes in the HashTable ha->ha_connHash. The initial + * values come from the NodeRegions in ha->ha_cumFlat.et_nodes, + * which correspond to extracting the entire flattened interaction + * area. We add these values to any already existing from a previous + * interaction area in case there were any nodes that span the boundary + * between two interaction areas. We will then call extHierAdjustments + * to subtract away the extracted values in each of the individually + * flattened subtrees. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * Design notes: + * We only need to update perimeter, area, or substrate capacitance + * when nodes from different subtrees abut or overlap, i.e., connect. + * These nodes have already been recorded in the table ha->ha_connHash + * by extHierConnections(), so all we have to do is find the appropriate + * entries in this table. + * + * Each NodeRegion in ha->ha_cumFlat contains a list of labels with + * it. The first label in each list is guaranteed to correspond to + * an entry in the table ha->ha_connHash if this node is a participant + * in a connection, so we pass this label to HashFind to obtain the + * appropriate Node. + * + * ---------------------------------------------------------------------------- + */ + +void +extSubtreeAdjustInit(ha) + HierExtractArg *ha; +{ + NodeRegion *np; + NodeName *nn; + int n; + HashEntry *he; + char *name; + + /* + * Initialize the capacitance, perimeter, and area values + * in the Nodes in the hash table ha->ha_connHash. + */ + for (np = ha->ha_cumFlat.et_nodes; np; np = np->nreg_next) + { + if ((name = extNodeName((LabRegion *) np)) + && (he = HashLookOnly(&ha->ha_connHash, name)) + && (nn = (NodeName *) HashGetValue(he))) + { + nn->nn_node->node_cap += np->nreg_cap; + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + { + nn->nn_node->node_pa[n].pa_perim += np->nreg_pa[n].pa_perim; + nn->nn_node->node_pa[n].pa_area += np->nreg_pa[n].pa_area; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extSubtreeOutputCoupling -- + * + * Output the coupling capacitance table built up by extFindCoupling(). + * Each entry in the hash table is a capacitance between the pair of + * nodes identified by he->h_key, an CoupleKey struct. Writes to the + * FILE ha->ha_outf. + * + * Because it is possible that the coupled nodes aren't already named, + * we have to call extSubtreeTileToNode() to find their actual names. + * + * Results: + * None. + * + * Side effects: + * See the comments above. + * + * ---------------------------------------------------------------------------- + */ + +void +extSubtreeOutputCoupling(ha) + HierExtractArg *ha; +{ + CapValue cap; + CoupleKey *ck; + HashEntry *he; + Tile *tp; + HashSearch hs; + char *name; + + HashStartSearch(&hs); + while (he = HashNext(&ha->ha_cumFlat.et_coupleHash, &hs)) + { + cap = extGetCapValue(he) / ExtCurStyle->exts_capScale; + if (cap == 0) + continue; + + ck = (CoupleKey *) he->h_key.h_words; + + tp = extNodeToTile(ck->ck_1, &ha->ha_cumFlat); + name = extSubtreeTileToNode(tp, ck->ck_1->nreg_pnum, &ha->ha_cumFlat, ha, TRUE); + fprintf(ha->ha_outf, "cap \"%s\" ", name); + + tp = extNodeToTile(ck->ck_2, &ha->ha_cumFlat); + name = extSubtreeTileToNode(tp, ck->ck_2->nreg_pnum, &ha->ha_cumFlat, ha, TRUE); + fprintf(ha->ha_outf, "\"%s\" %lg\n", name, cap); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extSubtreeFunc -- + * + * Called once for each cell use that is a child of the parent def + * being extracted. Yanks the subtree into a new ExtTree. Extract + * connections between this subtree and ha->ha_cumFlat, then paint + * the subtree into the cumulative buffer ha->ha_cumFlat and prepend + * the subtree to extSubList. + * + * Results: + * Always returns 2, to avoid further elements in arrays. + * + * Side effects: + * Leaves ha->ha_cumFlat unextracted (all LabRegions free, + * and ha->ha_cumFlat.et_nodes set to NULL). + * See extHierConnections(). + * + * ---------------------------------------------------------------------------- + */ + +int +extSubtreeFunc(scx, ha) + SearchContext *scx; + HierExtractArg *ha; +{ + CellUse *cumUse = ha->ha_cumFlat.et_use; + CellUse *use = scx->scx_use; + CellDef *oneDef; + SearchContext newscx; + ExtTree *oneFlat; + HierYank hy; + int x, y; + + /* Allocate a new ExtTree to hold the flattened, extracted subtree */ + oneFlat = extHierNewOne(); + oneFlat->et_realuse = use; + + /* Record information for finding node names the hard way later */ + ha->ha_subUse = use; + + /* + * Yank all array elements of this subcell that lie in the interaction + * area. Transform to parent coordinates. Prefix is true, meaning that + * we should prefix each hierarchical name with the subcell use it + * belongs to. + */ + ha->ha_subArea = use->cu_bbox; + GEOCLIP(&ha->ha_subArea, &ha->ha_interArea); + hy.hy_area = &ha->ha_subArea; + hy.hy_target = oneFlat->et_use; + hy.hy_prefix = TRUE; + (void) DBArraySr(use, &ha->ha_subArea, extHierYankFunc, (ClientData) &hy); + + /* + * Extract node capacitance, perimeter, area, and coupling capacitance + * for this subtree. Labels come from the hierarchical labels yanked + * above, but may have additional labels added when we find names the + * hard way. + */ + oneDef = oneFlat->et_use->cu_def; + oneFlat->et_nodes = extFindNodes(oneDef, &ha->ha_clipArea, FALSE); + ExtLabelRegions(oneDef, ExtCurStyle->exts_nodeConn, + &(oneFlat->et_nodes), &ha->ha_clipArea); + if ((ExtOptions & (EXT_DOCOUPLING|EXT_DOADJUST)) + == (EXT_DOCOUPLING|EXT_DOADJUST)) + extFindCoupling(oneDef, &oneFlat->et_coupleHash, &ha->ha_clipArea); + + /* + * If this is not the first subcell we're processing, mark ha_cumFlat's + * tiles with LabRegions. We don't mark it the first time through, + * since then ha_cumFlat contains only the parent mask geometry and + * node names will be found by looking in ha_lookNames. + */ + if (extFirstPass) + { + // On the first pass, run through et_lookName's label list. + // Copy any sticky labels to cumUse->cu_def, so that the labels + // can be found even when there is no geometry underneath in + // the parent cell. + + CellDef *cumDef = ha->ha_cumFlat.et_lookNames; + + if (cumDef != NULL) + { + Label *lab, *newlab; + unsigned int n; + + for (lab = cumDef->cd_labels; lab ; lab = lab->lab_next) + { + n = sizeof (Label) + strlen(lab->lab_text) + - sizeof lab->lab_text + 1; + + newlab = (Label *)mallocMagic(n); + newlab->lab_type = lab->lab_type; + newlab->lab_rect = lab->lab_rect; + newlab->lab_flags = lab->lab_flags; + strcpy(newlab->lab_text, lab->lab_text); + + newlab->lab_next = cumUse->cu_def->cd_labels; + cumUse->cu_def->cd_labels = newlab; + } + } + extFirstPass = FALSE; + } + else + { + /* + * We don't care about the lreg_ll or lreg_pNum for these + * nodes (we're only interested in the label list associated + * with each node), so we don't pass extHierLabEach() to + * ExtFindRegions(). + */ + ha->ha_cumFlat.et_nodes = + (NodeRegion *) ExtFindRegions(cumUse->cu_def, &TiPlaneRect, + &ExtCurStyle->exts_activeTypes, + ExtCurStyle->exts_nodeConn, + extUnInit, extHierLabFirst, (int (*)()) NULL); + ExtLabelRegions(cumUse->cu_def, ExtCurStyle->exts_nodeConn, + &(ha->ha_cumFlat.et_nodes), &TiPlaneRect); + } + + /* Process connections; this updates ha->ha_connHash */ + extHierConnections(ha, &ha->ha_cumFlat, oneFlat); + + /* Process substrate connection. All substrates should be */ + /* connected together in the cell def, so in the case of an */ + /* array, just make sure that the first array entry is */ + /* connected. */ + + if (use->cu_xhi == use->cu_xlo && use->cu_yhi == use->cu_ylo) + extHierSubstrate(ha, use, -1, -1); + else if (use->cu_xhi == use->cu_xlo && use->cu_yhi > use->cu_ylo) + { + for (y = use->cu_ylo; y <= use->cu_yhi; y++) + extHierSubstrate(ha, use, -1, y); + } + else if (use->cu_xhi > use->cu_xlo && use->cu_yhi == use->cu_ylo) + { + for (x = use->cu_xlo; x <= use->cu_xhi; x++) + extHierSubstrate(ha, use, x, -1); + } + else + { + for (x = use->cu_xlo; x <= use->cu_xhi; x++) + for (y = use->cu_ylo; y <= use->cu_yhi; y++) + extHierSubstrate(ha, use, x, y); + } + + /* Free the cumulative node list we extracted above */ + if (ha->ha_cumFlat.et_nodes) + { + ExtResetTiles(cumUse->cu_def, extUnInit); + ExtFreeLabRegions((LabRegion *) ha->ha_cumFlat.et_nodes); + ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL; + } + + /* + * Paint the subtree buffer on top of the cumulative buffer. + * Copy the labels that were yanked along with the subtree into + * the cumulative buffer as well. + */ + newscx.scx_use = oneFlat->et_use; + newscx.scx_area = ha->ha_subArea; + newscx.scx_trans = GeoIdentityTransform; + DBCellCopyPaint(&newscx, &DBAllButSpaceBits, 0, cumUse); +#ifdef notdef + extCopyPaint(oneFlat->et_use->cu_def, &ha->ha_subArea, cumUse->cu_def); +#endif /* notdef */ + extHierCopyLabels(oneFlat->et_use->cu_def, cumUse->cu_def); + + /* Prepend this tree to the list of trees we've processed so far */ + oneFlat->et_next = extSubList; + extSubList = oneFlat; + + return (2); +} + +/* + * ---------------------------------------------------------------------------- + * + * extSubtreeTileToNode -- + * + * Map from a Tile in a given yank buffer 'et' to the name of the node + * containing that tile. + * + * The node associated with a tile can be determined in one of the + * following ways: + * + * (1) Look for a label on the list of the Region pointed to by the + * tile planes of the yank buffer. If no label was found, then + * try (2). + * + * (2) If et->et_lookNames is non-NULL, see if the tile overlaps a + * connected tile on the same plane of the def et->et_lookNames. + * + * (3) Call extSubtreeHardNode() to do a painful extraction of a label. + * See the comments in extSubtreeHardNode() for a description of + * the algorithm used. Only do this if doHard is TRUE. + * + * Results: + * Returns a pointer to the name of the node containing + * the tile. If no node name was found, and doHard was + * TRUE, return the string "(none)"; if doHard was FALSE, + * return NULL. + * + * Side effects: + * The string returned is allocated from a static buffer, so + * subsequent calls to extSubtreeTileToNode() will overwrite + * the results returned in previous calls. + * + * Records an error with the feedback package if no node name + * could be found and doHard was TRUE. + * + * ---------------------------------------------------------------------------- + */ + +char * +extSubtreeTileToNode(tp, pNum, et, ha, doHard) + Tile *tp; /* Tile whose node name is to be found */ + int pNum; /* Plane of the tile */ + ExtTree *et; /* Yank buffer to search */ + HierExtractArg *ha; /* Extraction context */ + bool doHard; /* If TRUE, we look up this node's name the hard way + * if we can't find it any other way; otherwise, we + * return NULL if we can't find the node's name. + */ +{ + static char warningStr[] = + "Warning: node labels should be inside overlap area"; + static char errorStr[] = + "Cannot find the name of this node (probable extractor error)"; + CellDef *parentDef = ha->ha_parentUse->cu_def; + LabRegion *reg; + Label *lab; + Rect r; + TileType ttype; + + /* If there is a label list, use it */ + if (extHasRegion(tp, extUnInit)) + { + reg = (LabRegion *) extGetRegion(tp); + if (reg->lreg_labels) + return (extNodeName(reg)); + } + + /* + * If there is any node at all in the cell et->et_lookNames, + * use it. The node doesn't have to have a label list. + */ + TITORECT(tp, &r); + if (et->et_lookNames) + { + /* + * Make sure we've got a valid tile -- interactions with interrupts + * can cause problems. + */ + if (IsSplit(tp)) + { + if (SplitSide(tp)) + ttype = SplitRightType(tp); + else + ttype = SplitLeftType(tp); + } + else + ttype = TiGetTypeExact(tp); + + if (pNum >= PL_PAINTBASE) + { + if (IsSplit(tp)) + { + if (DBSrPaintNMArea((Tile *) NULL, + et->et_lookNames->cd_planes[pNum], + TiGetTypeExact(tp), &r, &DBAllButSpaceBits, + extConnFindFunc, (ClientData) ®)) + { + if (SigInterruptPending) + return ("(none)"); + return (extNodeName(reg)); + } + } + else + { + if (DBSrPaintArea((Tile *) NULL, + et->et_lookNames->cd_planes[pNum], &r, + &DBAllButSpaceBits, extConnFindFunc, (ClientData) ®)) + { + if (SigInterruptPending) + return ("(none)"); + return (extNodeName(reg)); + } + } + } + } + + /* We have to do it the hard way */ + if (!doHard) return ((char *) NULL); + if (extHasRegion(tp, extUnInit) + && (reg = extSubtreeHardNode(tp, pNum, et, ha))) + { + if (ExtDoWarn & EXTWARN_LABELS) + { + DBWFeedbackAdd(&r, warningStr, parentDef, 1, STYLE_PALEHIGHLIGHTS); + extNumWarnings++; + } + return (extNodeName(reg)); + } + + extNumFatal++; + if (!DebugIsSet(extDebugID, extDebNoFeedback)) + DBWFeedbackAdd(&r, errorStr, parentDef, 1, STYLE_MEDIUMHIGHLIGHTS); + return ("(none)"); +} + +/* + * ---------------------------------------------------------------------------- + * extConnFindFunc -- + * + * Called when searching the area of a tile in the def et->et_lookNames + * by extSubtreeTileToNode() above. + * + * Results: + * If we find a tile that has been marked with a node, + * return 1; otherwise, return 0. + * + * Side effects: + * Sets *preg to the node found if we returned 1; otherwise, + * leaves *preg alone. + * ---------------------------------------------------------------------------- + */ + +int +extConnFindFunc(tp, preg) + Tile *tp; + LabRegion **preg; +{ + if (extHasRegion(tp, extUnInit)) + { + *preg = (LabRegion *) extGetRegion(tp); + return (1); + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extSubtreeHardNode -- + * + * Find a node name for the electrical node containing the tile 'tp' + * the hard way. We assume tp->ti_client points to a LabRegion that + * had no labels associated with it; if we succeed, we leave this + * LabRegion pointing to a newly allocated LabelList and Label. + * + * Results: + * Returns a pointer to LabRegion for the node to which the tile + * 'tp' belongs. Returns NULL if no region could be found. + * + * Side effects: + * See above. + * + * Algorithm: + * For each subcell of the parent that could have contributed + * to the yank buffer in question, search the original tree + * for geometry in the area of the tile 'tp'. For each cell + * we find, we trace out just those nodes lying in the area + * of the overlap, and then do a label assignment for those + * nodes. As soon as we find a label, we're done. Otherwise, + * we reset this def back the way we found it and continue on + * to the next cell in our search. + * + * ---------------------------------------------------------------------------- + */ + +LabRegion * +extSubtreeHardNode(tp, pNum, et, ha) + Tile *tp; + int pNum; + ExtTree *et; + HierExtractArg *ha; +{ + LabRegion *lreg = (LabRegion *) extGetRegion(tp); + CellDef *def = et->et_use->cu_def; + TileType ttype; + char labelBuf[4096]; + LabelList *ll; + HardWay arg; + + ASSERT(lreg->lreg_labels == NULL, "extSubtreeHardNode"); + + if (IsSplit(tp)) + { + if (SplitSide(tp)) + ttype = SplitRightType(tp); + else + ttype = SplitLeftType(tp); + } + else + ttype = TiGetTypeExact(tp); + + arg.hw_ha = ha; + arg.hw_label = (Label *) NULL; + arg.hw_mask = DBPlaneTypes[pNum]; + TTMaskAndMask(&arg.hw_mask, &DBConnectTbl[ttype]); + arg.hw_tpath.tp_last = &labelBuf[sizeof labelBuf - 3]; + arg.hw_tpath.tp_first = arg.hw_tpath.tp_next = labelBuf; + arg.hw_prefix = TRUE; + TITORECT(tp, &arg.hw_area); + + /* + * Try to find a label in the area. + * If we can't find a label, we make one up based on the + * automatically generated node name in a child cell that + * contains paint in this node. + */ + labelBuf[0] = '\0'; + arg.hw_autogen = FALSE; + extSubtreeHardSearch(et, &arg); + if (arg.hw_label == NULL) + { + labelBuf[0] = '\0'; + arg.hw_autogen = TRUE; + extSubtreeHardSearch(et, &arg); + } + + /* + * If we succeeded (we always should), we now have a label. + * Make the single LabelList for the region 'lreg' point to + * this label, and prepend it to the list for 'def'. + */ + if (arg.hw_label) + { + ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList))); + lreg->lreg_labels = ll; + ll->ll_next = (LabelList *) NULL; + ll->ll_label = arg.hw_label; + arg.hw_label->lab_next = def->cd_labels; + def->cd_labels = arg.hw_label; + return (lreg); + } + + return ((LabRegion *) NULL); +} + +/* + * ---------------------------------------------------------------------------- + * extSubtreeHardSearch -- + * + * Do the actual work of deciding which subtrees to search + * for extSubtreeHardNode above. We apply the procedure + * extHardProc() at each subcell. + * ---------------------------------------------------------------------------- + */ + +void +extSubtreeHardSearch(et, arg) + ExtTree *et; + HardWay *arg; +{ + HierExtractArg *ha = arg->hw_ha; + ExtTree *oneFlat; + + + arg->hw_proc = extHardProc; + if (et == &ha->ha_cumFlat) + { + /* + * Recursively search all children of parent up to, but not + * including, ha->ha_subUse. Don't search parent paint. + */ + for (oneFlat = extSubList; oneFlat; oneFlat = oneFlat->et_next) + { + if (oneFlat->et_realuse) + { + if (DBArraySr(oneFlat->et_realuse, &arg->hw_area, + extSubtreeHardUseFunc, (ClientData) arg)) + { + break; + } + } + } + } + else + { + /* Recursively search only the elements of ha->ha_subUse */ + (void) DBArraySr(ha->ha_subUse, &arg->hw_area, + extSubtreeHardUseFunc, (ClientData) arg); + } +} + +/* + * ---------------------------------------------------------------------------- + * extSubtreeHardUseFunc -- + * + * When searching a subtree, this is called once for each element + * in the array that is the root of the subtree. + * + * Results: + * Returns 1 if we have successfully found a label, 0 if not + * (return value of arg->hw_proc). + * + * Side effects: + * Calls (*arg->hw_proc)(). + * ---------------------------------------------------------------------------- + */ + +int +extSubtreeHardUseFunc(use, trans, x, y, arg) + CellUse *use; /* Use that is the root of the subtree being searched */ + Transform *trans; /* Transform from coordinates of use->cu_def to those + * in use->cu_parent, for the array element (x, y). + */ + int x, y; /* Indices of this array element */ + HardWay *arg; /* Context passed down to filter functions */ +{ + SearchContext scx; + Transform tinv; + + scx.scx_use = use; + scx.scx_trans = *trans; + scx.scx_x = x; + scx.scx_y = y; + GEOINVERTTRANS(trans, &tinv); + GEOTRANSRECT(&tinv, &arg->hw_area, &scx.scx_area); + return ((*arg->hw_proc)(&scx, arg)); +} diff --git a/extract/ExtTech.c b/extract/ExtTech.c new file mode 100644 index 00000000..ab560823 --- /dev/null +++ b/extract/ExtTech.c @@ -0,0 +1,2968 @@ +/* + * ExtTech.c -- + * + * Circuit extraction. + * Code to read and process the sections of a technology file + * that are specific to circuit extraction. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char sccsid[] = "@(#)ExtTech.c 4.8 MAGIC (Berkeley) 10/26/85"; +#endif /* not lint */ + +#include +#include /* for strtod() */ +#include +#include +#include /* for isspace() */ + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/utils.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "database/databaseInt.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "utils/tech.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "cif/CIFint.h" + +/* Whether we are converting units from microns to lambda */ +bool doConvert; + +/* Current extraction style */ +ExtStyle *ExtCurStyle = NULL; + +/* List of all styles */ +ExtKeep *ExtAllStyles = NULL; + +/* Forward declarations */ +void extTechFinalStyle(); +void ExtLoadStyle(); +void ExtTechScale(int, int); + +/* + * Table used for parsing the extract section of a .tech file + * Each line in the extract section is of a type determined by + * its first keyword. There is one entry in the following table + * for each such keyword. + */ + +typedef enum +{ + AREAC, CONTACT, CSCALE, + DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP, + DEFAULTSIDEWALL, + DEVICE, FET, FETRESIST, HEIGHT, LAMBDA, OVERC, + PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP, + SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT +} Key; + +typedef struct +{ + char *k_name; + int k_key; + int k_minargs; + int k_maxargs; + char *k_usage; +} keydesc; + +static keydesc keyTable[] = { + "areacap", AREAC, 3, 3, +"types capacitance", + + "contact", CONTACT, 3, 6, +"type resistance", + + "cscale", CSCALE, 2, 2, +"capacitance-scalefactor", + + "defaultareacap", DEFAULTAREACAP, 4, 6, +"types plane capacitance", + + "defaultoverlap", DEFAULTOVERLAP, 6, 6, +"types plane otertypes otherplane capacitance", + + "defaultperimeter", DEFAULTPERIMETER, 4, 6, +"types plane capacitance", + + "defaultsideoverlap", DEFAULTSIDEOVERLAP, 6, 6, +"types plane othertypes otherplane capacitance", + + "defaultsidewall", DEFAULTSIDEWALL, 4, 4, +"types plane capacitance", + + "device", DEVICE, 4, 10, +"device dev-type types options...", + + "fet", FET, 8, 9, +"types terminal-types min-#-terminals name [subs-types] subs-node gscap gate-chan-cap", + + "fetresist", FETRESIST, 4, 4, +"type region ohms-per-square", + + "height", HEIGHT, 4, 4, +"type height-above-subtrate thickness", + + "lambda", LAMBDA, 2, 2, +"units-per-lambda", + + "overlap", OVERC, 4, 5, +"toptypes bottomtypes capacitance [shieldtypes]", + + "perimc", PERIMC, 4, 4, +"intypes outtypes capacitance", + + "planeorder", PLANEORDER, 3, 3, +"plane index", + "noplaneordering", NOPLANEORDER, 1, 1, +"(no arguments needed)", + + "resist", RESIST, 3, 4, +"types resistance", + + "rscale", RSCALE, 2, 2, +"resistance-scalefactor", + + "sidehalo", SIDEHALO, 2, 2, +"halo", + + "sideoverlap", SIDEOVERLAP, 5, 6, +"intypes outtypes ovtypes capacitance [shieldtypes]", + + "sidewall", SIDEWALL, 6, 6, +"intypes outtypes neartypes fartypes capacitance", + + "step", STEP, 2, 2, +"size", + + "style", STYLE, 2, 4, +"stylename", + + "substrate", SUBSTRATE, 3, 3, +"types plane", + + "units", UNITS, 2, 2, +"lambda|microns", + + "variants", VARIANT, 2, 2, +"style,...", + + 0 +}; + + +/* + * Table used for parsing the "device" keyword types + * + * (Note: "10" for max types in subcircuit is arbitrary---the parser + * ignores max types for DEV_SUBCKT and DEV_MSUBCKT). + */ + +/* types are enumerated in extract.h */ + +static keydesc devTable[] = { + "mosfet", DEV_MOSFET, 5, 10, +"name gate-types src-types [drn-types] sub-types|None sub-node [gscap gccap]", + + "bjt", DEV_BJT, 5, 5, +"name base-types emitter-types collector-types", + + "capacitor", DEV_CAP, 4, 8, +"name top-types bottom-types [sub-types|None sub-node] [[perimcap] areacap]", + + "capreverse", DEV_CAPREV, 4, 8, +"name bottom-types top-types [sub-types|None sub-node] [[perimcap] areacap]", + + "resistor", DEV_RES, 4, 6, +"name|None res-types terminal-types [sub-types|None sub-node]", + + "diode", DEV_DIODE, 4, 6, +"name pos-types neg-types [sub-types|None sub-node]", + + "pdiode", DEV_PDIODE, 4, 6, +"name pos-types neg-types [sub-types|None sub-node]", + + "ndiode", DEV_NDIODE, 4, 6, +"name neg-types pos-types [sub-types|None sub-node]", + + "subcircuit", DEV_SUBCKT, 3, 11, +"name dev-types [N] [term1-types ... termN-types [sub-types|None sub-node]] [options]", + + "rsubcircuit", DEV_RSUBCKT, 4, 7, +"name dev-types terminal-types [sub-types|None sub-node] [options]", + + "msubcircuit", DEV_MSUBCKT, 4, 11, +"name dev-types [N] [term1-types ... termN-types [sub-types|None sub-node]] [options]", + + 0 +}; + +#ifdef MAGIC_WRAPPER + +/* + * ---------------------------------------------------------------------------- + * + * ExtCompareStyle -- + * + * This routine is designed to work with embedded exttosim and + * exttospice. It determines whether the current extract style + * matches the string (picked up from the .ext file). If so, it + * returns TRUE. If not, it checks whether the style exists in + * the list of known files for this technology. If so, it loads + * the correct style and returns TRUE. If not, it returns FALSE. + * + * ---------------------------------------------------------------------------- + */ + +bool +ExtCompareStyle(stylename) + char *stylename; +{ + ExtKeep *style; + + if (!strcmp(stylename, ExtCurStyle->exts_name)) + return TRUE; + else + { + for (style = ExtAllStyles; style != NULL; style = style->exts_next) + { + if (!strcmp(stylename, style->exts_name)) + { + ExtLoadStyle(stylename); + return TRUE; + } + } + } + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtGetDevInfo -- + * + * This routine is designed to work with the embedded exttosim and + * exttospice commands under the Tcl-based magic, such that all + * device information needed by these commands can be picked up + * from the current extraction style (as it should!). This + * really should be set up when the extract file is read, which is + * why the routine is here, although this is not a very efficient + * way to do it (but it needs to be this way to keep backward + * compatibility with the non-Tcl, standalone programs ext2sim and + * ext2spice). + * + * Note that finding the device by index ("idx") is horribly + * inefficient, but keeps the netlist generator separated from + * the extractor. Some of this code is seriously schizophrenic, + * and should not be investigated too closely. + * + * Results: + * Return FALSE if no device corresponds to index "idx". TRUE + * otherwise. + * + * Side Effects: + * Fills values in the argument list. + * ---------------------------------------------------------------------------- + */ + +bool +ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) + int idx; + char **devnameptr; + short *sd_rclassptr; /* First SD type only---needs to be updated! */ + short *sub_rclassptr; + char **subnameptr; +{ + TileType t; + TileTypeBitMask *rmask, *tmask; + int n, i = 0, j; + bool repeat; + char *locdname; + char **uniquenamelist = (char **)mallocMagic(DBNumTypes * sizeof(char *)); + + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + locdname = ExtCurStyle->exts_transName[t]; + if (locdname != NULL) + { + repeat = FALSE; + for (j = 0; j < i; j++) + if (!strcmp(uniquenamelist[j], locdname)) + { + repeat = TRUE; + break; + } + if (repeat == FALSE) + { + if (i == idx) break; + uniquenamelist[i] = locdname; + i++; + } + } + } + if (t == DBNumTypes) return FALSE; + + *devnameptr = locdname; + *subnameptr = ExtCurStyle->exts_transSubstrateName[t]; + + tmask = &ExtCurStyle->exts_transSDTypes[t][0]; + *sd_rclassptr = (short)(-1); /* NO_RESCLASS */ + + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + { + rmask = &ExtCurStyle->exts_typesByResistClass[n]; + if (TTMaskIntersect(rmask, tmask)) + { + *sd_rclassptr = (short)n; + break; + } + } + + tmask = &ExtCurStyle->exts_transSubstrateTypes[t]; + *sub_rclassptr = (short)(-1); /* NO_RESCLASS */ + + for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) + { + rmask = &ExtCurStyle->exts_typesByResistClass[n]; + if (TTMaskIntersect(rmask, tmask)) + { + *sub_rclassptr = (short)(n); + break; + } + } + + freeMagic(uniquenamelist); + return TRUE; +} + +#endif /* MAGIC_WRAPPER */ + + +#ifdef THREE_D +/* + * ---------------------------------------------------------------------------- + * + * ExtGetZAxis -- + * + * Get the height and thickness parameters for a layer (used by the + * graphics module which does not have access to internal variables + * in the extract section). + * + * Results: + * None + * + * Side Effects: + * Fills values "height" and "thick" in argument list. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtGetZAxis(tile, height, thick) + Tile *tile; + float *height, *thick; +{ + TileType ttype; + + if (ExtCurStyle == NULL) return; + + ttype = TiGetLeftType(tile); /* Ignore non-Manhattan for now */ + + /* Note that w_scale is multiplied by SUBPIXEL to get fixed-point accuracy. */ + /* However, we downshift by only 9 (divide by 512) so that heights are */ + /* exaggerated in the layout by a factor of 8 (height exaggeration is */ + /* standard practice for VLSI cross-sections). */ + + *height = ExtCurStyle->exts_height[ttype]; + *thick = ExtCurStyle->exts_thick[ttype]; +} +#endif /* THREE_D */ + + +/* + * ---------------------------------------------------------------------------- + * + * ExtPrintStyle -- + * + * Print the available and/or current extraction styles. + * + * Results: + * None. + * + * Side effects: + * Output. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtPrintStyle(dolist, doforall, docurrent) + bool dolist; + bool doforall; + bool docurrent; +{ + ExtKeep *style; + + if (docurrent) + { + if (ExtCurStyle == NULL) + TxError("Error: No style is set\n"); + else + { + if (!dolist) TxPrintf("The current style is \""); +#ifdef MAGIC_WRAPPER + if (dolist) + Tcl_SetResult(magicinterp, ExtCurStyle->exts_name, NULL); + else +#endif + TxPrintf("%s", ExtCurStyle->exts_name); + if (!dolist) TxPrintf("\".\n"); + } + } + + if (doforall) + { + if (!dolist) TxPrintf("The extraction styles are: "); + + for (style = ExtAllStyles; style; style = style->exts_next) + { + if (dolist) + { +#ifdef MAGIC_WRAPPER + Tcl_AppendElement(magicinterp, style->exts_name); +#else + if (style != ExtAllStyles) TxPrintf(" "); + TxPrintf("%s", style->exts_name); +#endif + } + else + { + if (style != ExtAllStyles) TxPrintf(", "); + TxPrintf("%s", style->exts_name); + } + } + if (!dolist) TxPrintf(".\n"); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtSetStyle -- + * + * Set the current extraction style to 'name', or print + * the available and current styles if 'name' is NULL. + * + * Results: + * None. + * + * Side effects: + * Just told you. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtSetStyle(name) + char *name; +{ + ExtKeep *style, *match; + int length; + + if (name == NULL) return; + + match = NULL; + length = strlen(name); + for (style = ExtAllStyles; style; style = style->exts_next) + { + if (strncmp(name, style->exts_name, length) == 0) + { + if (match != NULL) + { + TxError("Extraction style \"%s\" is ambiguous.\n", name); + ExtPrintStyle(FALSE, TRUE, TRUE); + return; + } + match = style; + } + } + + if (match != NULL) + { + ExtLoadStyle(match->exts_name); + TxPrintf("Extraction style is now \"%s\"\n", name); + return; + } + + TxError("\"%s\" is not one of the extraction styles Magic knows.\n", name); + ExtPrintStyle(FALSE, TRUE, TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * extTechStyleAlloc -- + * + * Allocate memory for a new extract style structure. + * + * ---------------------------------------------------------------------------- + */ + +ExtStyle * +extTechStyleAlloc() +{ + ExtStyle *style; + TileType r; + + style = (ExtStyle *) mallocMagic(sizeof (ExtStyle)); + + /* Make sure that the memory for character strings is NULL, */ + /* because we want the Init section to free memory if it */ + /* has been previously allocated. */ + + for (r = 0; r < NT; r++) + { + style->exts_transSubstrateName[r] = (char *) NULL; + style->exts_transName[r] = (char *) NULL; + style->exts_transSDTypes[r] = (TileTypeBitMask *) NULL; + style->exts_deviceParams[r] = (ParamList *) NULL; + style->exts_deviceClass[r] = (char) 0; + style->exts_transResist[r].ht_table = (HashEntry **) NULL; + } + return style; +} + +/* + * ---------------------------------------------------------------------------- + * + * extTechStyleInit -- + * + * Fill in the extract style structure with initial values. + * + * ---------------------------------------------------------------------------- + */ + +void +extTechStyleInit(style) + ExtStyle *style; +{ + TileType r, s; + + style->exts_name = NULL; + style->exts_status = TECH_NOT_LOADED; + + style->exts_sidePlanes = style->exts_overlapPlanes = 0; + TTMaskZero(&style->exts_transMask); + style->exts_activeTypes = DBAllButSpaceAndDRCBits; + + for (r = 0; r < NP; r++) + { + TTMaskZero(&style->exts_sideTypes[r]); + TTMaskZero(&style->exts_overlapTypes[r]); + style->exts_planeOrder[r] = -1; + } + + for (r = 0; r < NT; r++) + { + TTMaskZero(&style->exts_nodeConn[r]); + TTMaskZero(&style->exts_resistConn[r]); + TTMaskZero(&style->exts_transConn[r]); + style->exts_allConn[r] = DBAllTypeBits; + + style->exts_sheetResist[r] = 0; + style->exts_cornerChop[r] = 1.0; + style->exts_viaResist[r] = 0; + style->exts_height[r] = 0.0; + style->exts_thick[r] = 0.0; + style->exts_areaCap[r] = (CapValue) 0; + style->exts_overlapOtherPlanes[r] = 0; + TTMaskZero(&style->exts_overlapOtherTypes[r]); + TTMaskZero(&style->exts_sideEdges[r]); + for (s = 0; s < NT; s++) + { + TTMaskZero(&style->exts_sideCoupleOtherEdges[r][s]); + TTMaskZero(&style->exts_sideOverlapOtherTypes[r][s]); + style->exts_sideOverlapOtherPlanes[r][s] = 0; + style->exts_sideCoupleCap[r][s] = (EdgeCap *) NULL; + style->exts_sideOverlapCap[r][s] = (EdgeCap *) NULL; + style->exts_perimCap[r][s] = (CapValue) 0; + style->exts_overlapCap[r][s] = (CapValue) 0; + + TTMaskZero(&style->exts_overlapShieldTypes[r][s]); + style->exts_overlapShieldPlanes[r][s] = 0; + style->exts_sideOverlapShieldPlanes[r][s] = 0; + } + + TTMaskZero(&style->exts_perimCapMask[r]); +#ifdef ARIEL + TTMaskZero(&style->exts_subsTransistorTypes[r]); +#endif + if (style->exts_transSDTypes[r] != NULL) + freeMagic(style->exts_transSDTypes[r]); + style->exts_transSDTypes[r] = NULL; + style->exts_transSDCount[r] = 0; + style->exts_transGateCap[r] = (CapValue) 0; + style->exts_transSDCap[r] = (CapValue) 0; + if (style->exts_transSubstrateName[r] != (char *) NULL) + { + freeMagic(style->exts_transSubstrateName[r]); + style->exts_transSubstrateName[r] = (char *) NULL; + } + if (style->exts_transName[r] != (char *) NULL) + { + freeMagic(style->exts_transName[r]); + style->exts_transName[r] = (char *) NULL; + } + while (style->exts_deviceParams[r] != (ParamList *) NULL) + { + /* Parameter lists are shared. Only free the last one! */ + + if (style->exts_deviceParams[r]->pl_count > 1) + { + style->exts_deviceParams[r]->pl_count--; + style->exts_deviceParams[r] = (ParamList *)NULL; + } + else + { + freeMagic(style->exts_deviceParams[r]->pl_name); + freeMagic(style->exts_deviceParams[r]); + style->exts_deviceParams[r] = style->exts_deviceParams[r]->pl_next; + } + } + style->exts_deviceClass[r] = (char)0; + if (style->exts_transResist[r].ht_table != (HashEntry **) NULL) + HashKill(&style->exts_transResist[r]); + HashInit(&style->exts_transResist[r], 8, HT_STRINGKEYS); + style->exts_linearResist[r] = 0; + } + + style->exts_sideCoupleHalo = 0; + style->exts_stepSize = 100; + style->exts_unitsPerLambda = 100.0; + style->exts_resistScale = 1000; + style->exts_capScale = 1000; + style->exts_numResistClasses = 0; + + style->exts_planeOrderStatus = needPlaneOrder ; + + for (r = 0; r < DBNumTypes; r++) + { + style->exts_resistByResistClass[r] = 0; + TTMaskZero(&style->exts_typesByResistClass[r]); + style->exts_typesResistChanged[r] = DBAllButSpaceAndDRCBits; + TTMaskSetType(&style->exts_typesResistChanged[r], TT_SPACE); + style->exts_typeToResistClass[r] = -1; + } + doConvert = FALSE; + + // The exts_globSubstratePlane setting of -1 will be used to set a + // backwards-compatibility mode matching previous behavior with + // respect to the substrate when there is no "substrate" line in + // the techfile. + + style->exts_globSubstratePlane = -1; + TTMaskZero(&style->exts_globSubstrateTypes); +} + + +/* + * ---------------------------------------------------------------------------- + * + * extTechStyleNew -- + * + * Allocate a new style with zeroed technology variables. + * + * Results: + * Allocates a new ExtStyle, initializes it, and returns it. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +ExtStyle * +extTechStyleNew() +{ + ExtStyle *style; + + style = extTechStyleAlloc(); + extTechStyleInit(style); + return style; +} + +/* + * ---------------------------------------------------------------------------- + * + * aToCap -- + * + * Utility procedure for reading capacitance values. + * + * Returns: + * A value of type CapValue. + * + * Side effects: + * none. + * ---------------------------------------------------------------------------- + */ + +CapValue +aToCap(str) + char *str; +{ + CapValue capVal; + if (sscanf(str, "%lf", &capVal) != 1) { + capVal = (CapValue) 0; + TechError("Capacitance value %s must be a number\n", str); + } + return capVal; +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtLoadStyle -- + * + * Re-read the technology file to load the specified technology extraction + * style into structure ExtCurStyle. This is much more memory-efficient than + * keeping a separate (and huge!) ExtStyle structure for each extraction style. + * It incurs a complete reading of the tech file on startup and every time the + * extraction style is changed, but we can assume that this does not happen + * often. The first style in the technology file is assumed to be default, so + * that re-reading the tech file is not necessary on startup unless the default + * extraction style is changed by a call to "extract style". + * + * ---------------------------------------------------------------------------- + */ +void +ExtLoadStyle(stylename) + char *stylename; +{ + SectionID invext; + + extTechStyleInit(ExtCurStyle); /* Reinitialize and mark as not */ + ExtCurStyle->exts_name = stylename; /* loaded. */ + + /* Invalidate the extract section, and reload it. */ + /* The second parameter to TechSectionGetMask is NULL because */ + /* no other tech client sections depend on the extract section. */ + + invext = TechSectionGetMask("extract", NULL); + TechLoad(NULL, invext); + + /* extTechFinalStyle(ExtCurStyle); */ /* Taken care of by TechLoad() */ + ExtTechScale(DBLambda[0], DBLambda[1]); +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtTechInit -- + * + * Ensure that all memory allocated to the extract database has + * been freed up. Called before loading a new technology. + * + * ---------------------------------------------------------------------------- + */ +void +ExtTechInit() +{ + ExtKeep *style; + int r; + + /* Delete everything in ExtCurStyle */ + + if (ExtCurStyle != NULL) + { + extTechStyleInit(ExtCurStyle); + + /* Everything has been freed except the hash tables, which */ + /* were just reinitialized by extTechStyleInit(). */ + for (r = 0; r < NT; r++) + { + if (ExtCurStyle->exts_transResist[r].ht_table != (HashEntry **) NULL) + HashKill(&ExtCurStyle->exts_transResist[r]); + } + ExtCurStyle = NULL; + } + + /* Forget all the extract style names */ + + for (style = ExtAllStyles; style != NULL; style = style->exts_next) + { + freeMagic(style->exts_name); + freeMagic(style); + } + ExtAllStyles = NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtTechSimpleAreaCap -- + * + * Parse the techfile line for the "defaultareacap" keyword. + * This is equivalent to the "areacap" line but also applies + * to "overlap" of types on the second plane (if specified) and + * all planes below it, with appropriate intervening types. + * + * Usage: + * defaultareacap types plane [[subtypes] subplane] value + * + * where "types" are the types for which to compute area cap, + * "plane" is the plane of "types", "subplane" is a plane + * containing wells or any types that have the same coupling + * as the substrate. If absent, it is assumed that nothing + * shields "types" from the subtrate. Additional optional + * "subtypes" is a list of types in "subplane" that shield. + * If absent, then all types in "subplane" are shields to the + * substrate. "value" is the area capacitance in aF/um^2. + * + * Results: + * None. + * + * Side Effects: + * Adds information into the ExtCurStyle records. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtTechSimpleAreaCap(argc, argv) + int argc; + char *argv[]; +{ + TileType s, t; + TileTypeBitMask types, subtypes, shields; + CapValue capVal; + int plane1, plane2, plane3, pnum1, pnum2, pnum3; + PlaneMask pshield; + + if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder) + { + TechError("Cannot parse area cap line without plane ordering!\n"); + return; + } + + DBTechNoisyNameMask(argv[1], &types); + plane1 = DBTechNoisyNamePlane(argv[2]); + TTMaskAndMask(&types, &DBPlaneTypes[plane1]); + + capVal = aToCap(argv[argc - 1]); + + if (argc == 4) + plane2 = -1; + else + plane2 = DBTechNoisyNamePlane(argv[argc - 2]); + + if (argc > 5) + DBTechNoisyNameMask(argv[argc - 3], &subtypes); + else + subtypes = DBAllButSpaceAndDRCBits; + + /* Part 1: Area cap */ + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types, t)) + ExtCurStyle->exts_areaCap[t] = capVal; + + if (plane2 == -1) return; /* No "virtual" overlaps */ + else if (plane1 == plane2) return; /* shouldn't happen */ + + pnum1 = ExtCurStyle->exts_planeOrder[plane1]; + pnum2 = ExtCurStyle->exts_planeOrder[plane2]; + + /* Part 2: Overlap cap on types equivalent to substrate */ + /* Find all types in or below plane2 (i.e., ~(space)/plane2) */ + /* Shield types are everything in the planes between plane1 and plane2 */ + + TTMaskZero(&shields); + + pshield = 0; + for (plane3 = PL_TECHDEPBASE; plane3 < DBNumPlanes; plane3++) + { + pnum3 = ExtCurStyle->exts_planeOrder[plane3]; + if (pnum3 > pnum2 && pnum3 < pnum1) + { + TTMaskSetMask(&shields, &DBPlaneTypes[plane3]); + pshield |= PlaneNumToMaskBit(plane3); + } + else if (pnum3 <= pnum2) + { + TTMaskAndMask(&subtypes, &DBPlaneTypes[plane3]); + TTMaskClearType(&subtypes, TT_SPACE); + } + TTMaskClearType(&shields, TT_SPACE); + } + + /* Now record all of the overlap capacitances */ + + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + if (TTMaskHasType(&types, s)) + { + /* Contact overlap caps are determined from residues */ + if (DBIsContact(s)) continue; + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + if (!TTMaskHasType(&subtypes, t)) continue; + + if (s == t) continue; /* shouldn't happen */ + if (ExtCurStyle->exts_overlapCap[s][t] > (CapValue) 0) + continue; /* redundant overlap */ + + ExtCurStyle->exts_overlapCap[s][t] = capVal; + ExtCurStyle->exts_overlapPlanes |= PlaneNumToMaskBit(plane1); + ExtCurStyle->exts_overlapOtherPlanes[s] |= PlaneNumToMaskBit(plane2); + TTMaskSetType(&ExtCurStyle->exts_overlapTypes[plane1], s); + TTMaskSetType(&ExtCurStyle->exts_overlapOtherTypes[s], t); + + ExtCurStyle->exts_overlapShieldPlanes[s][t] = pshield; + ExtCurStyle->exts_overlapShieldTypes[s][t] = shields; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtTechSimplePerimCap -- + * + * Parse the techfile line for the "defaultperimeter" keyword. + * This comprises both the "perimc" statement and the "sideoverlap" + * statement for overlaps to types that are effectively substrate + * (e.g., well, implant, marker layers, etc.) + * + * Usage: + * defaultperimeter types plane [[subtypes] subplane] value + * + * where "types" are the types for which to compute fringing cap, + * "plane" is the plane of the types, "subplane" is an optional + * plane that shields "types" from substrate, and "value" is the + * fringing cap in aF/micron. If "subplane" is omitted, then + * nothing shields "types" from the substrate. Optional "subtypes" + * lists the types in "subplane" that shield. Otherwise, it is + * assumed that all types in "subplane" shield "types" from the + * substrate. + * + * Results: + * None. + * + * Side Effects: + * Adds information into the ExtCurStyle records. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtTechSimplePerimCap(argc, argv) + int argc; + char *argv[]; +{ + TileType r, s, t; + TileTypeBitMask types, nottypes, subtypes, shields; + CapValue capVal; + int plane1, plane2, plane3, pnum1, pnum2, pnum3; + PlaneMask pshield; + EdgeCap *cnew; + + if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder) + { + TechError("Cannot parse area cap line without plane ordering!\n"); + return; + } + + DBTechNoisyNameMask(argv[1], &types); + // TTMaskCom2(¬types, &types); + // For general use, only consider space and space-like types. + // For device fringing fields, like poly to diffusion on a FET, + // use perimc commands to augment the defaults. + TTMaskZero(¬types); + TTMaskSetType(¬types, TT_SPACE); + plane1 = DBTechNoisyNamePlane(argv[2]); + TTMaskAndMask(&types, &DBPlaneTypes[plane1]); + TTMaskAndMask(¬types, &DBPlaneTypes[plane1]); + + capVal = aToCap(argv[argc - 1]); + + if (argc >= 4) + plane2 = DBTechNoisyNamePlane(argv[argc - 2]); + else + plane2 = -1; + + if (argc > 5) + DBTechNoisyNameMask(argv[argc - 3], &subtypes); + else + subtypes = DBAllButSpaceAndDRCBits; + + /* Part 1: Perimeter cap */ + + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + for (t = 0; t < DBNumTypes; t++) + if (TTMaskHasType(&types, s) && TTMaskHasType(¬types, t)) + { + ExtCurStyle->exts_perimCap[s][t] = capVal; + TTMaskSetType(&ExtCurStyle->exts_perimCapMask[s], t); + } + + if (plane2 == -1) return; /* No "virtual" overlaps */ + else if (plane1 == plane2) return; /* shouldn't happen */ + + pnum1 = ExtCurStyle->exts_planeOrder[plane1]; + pnum2 = ExtCurStyle->exts_planeOrder[plane2]; + + /* Part 2: Sidewall overlap cap on types equivalent to substrate */ + /* Find all types in or below plane2 (i.e., ~(space)/plane2) */ + /* Shield types are everything in the planes between plane1 and plane2 */ + + TTMaskZero(&shields); + + pshield = 0; + for (plane3 = PL_TECHDEPBASE; plane3 < DBNumPlanes; plane3++) + { + pnum3 = ExtCurStyle->exts_planeOrder[plane3]; + if (pnum3 > pnum2 && pnum3 < pnum1) + { + TTMaskSetMask(&shields, &DBPlaneTypes[plane3]); + pshield |= PlaneNumToMaskBit(plane3); + } + else if (pnum3 <= pnum2) + { + TTMaskAndMask(&subtypes, &DBPlaneTypes[plane3]); + } + } + TTMaskClearType(&shields, TT_SPACE); + TTMaskClearType(&subtypes, TT_SPACE); + + /* Record all of the sideoverlap capacitances */ + + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + /* Side overlap computed from residues */ + if (DBIsContact(s)) continue; + + if (TTMaskHasType(&types, s)) // Corrected, 2/21/2017 + { + ExtCurStyle->exts_sidePlanes |= PlaneNumToMaskBit(plane1); + TTMaskSetType(&ExtCurStyle->exts_sideTypes[plane1], s); + TTMaskSetMask(&ExtCurStyle->exts_sideEdges[s], ¬types); + for (t = 0; t < DBNumTypes; t++) + { + if (!TTMaskHasType(¬types, t)) continue; + if (DBIsContact(t)) continue; + + TTMaskSetMask(&ExtCurStyle->exts_sideOverlapOtherTypes[s][t], &subtypes); + ExtCurStyle->exts_sideOverlapOtherPlanes[s][t] |= + PlaneNumToMaskBit(plane2); + cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); + cnew->ec_cap = capVal; + cnew->ec_far = shields; /* Types that shield */ + cnew->ec_near = subtypes; /* Types we create cap with */ + cnew->ec_pmask = PlaneNumToMaskBit(plane2); + cnew->ec_next = ExtCurStyle->exts_sideOverlapCap[s][t]; + ExtCurStyle->exts_sideOverlapCap[s][t] = cnew; + + for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) + if (TTMaskHasType(&subtypes, r)) + ExtCurStyle->exts_sideOverlapShieldPlanes[s][r] |= pshield; + } + } + + /* Reverse case (swap "types" and "subtypes") */ + + if (TTMaskHasType(&subtypes, s)) + { + ExtCurStyle->exts_sidePlanes |= PlaneNumToMaskBit(plane2); + TTMaskSetType(&ExtCurStyle->exts_sideTypes[plane2], s); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + if (DBIsContact(t)) continue; + + TTMaskSetMask(&ExtCurStyle->exts_sideOverlapOtherTypes[s][t], &types); + ExtCurStyle->exts_sideOverlapOtherPlanes[s][t] |= + PlaneNumToMaskBit(plane1); + cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); + cnew->ec_cap = capVal; + cnew->ec_far = shields; /* Types that shield */ + cnew->ec_near = types; /* Types we create cap with */ + cnew->ec_pmask = PlaneNumToMaskBit(plane1); + cnew->ec_next = ExtCurStyle->exts_sideOverlapCap[s][t]; + ExtCurStyle->exts_sideOverlapCap[s][t] = cnew; + + for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) + if (TTMaskHasType(&types, r)) + ExtCurStyle->exts_sideOverlapShieldPlanes[s][r] |= pshield; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtTechSimpleSidewallCap -- + * + * Parse the techfile line for the "defaultsidewall" keyword. + * + * Results: + * None. + * + * Side Effects: + * Adds information into the ExtCurStyle records. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtTechSimpleSidewallCap(argv) + char *argv[]; +{ + /* Like ExtTechLine, but with near = types2 and far = types1 */ + + TileType s, t; + TileTypeBitMask types1, types2; + CapValue capVal; + EdgeCap *cnew; + int plane; + + DBTechNoisyNameMask(argv[1], &types1); + plane = DBTechNoisyNamePlane(argv[2]); + capVal = aToCap(argv[3]); + + // Like perimeter cap, treat only space and space-like types + // TTMaskCom2(&types2, &types1); + TTMaskZero(&types2); + TTMaskSetType(&types2, TT_SPACE); + + TTMaskAndMask(&types1, &DBPlaneTypes[plane]); + TTMaskAndMask(&types2, &DBPlaneTypes[plane]); + + if (TTMaskHasType(&types1, TT_SPACE)) + TechError("Can't have space on inside of edge [ignored]\n"); + + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + if (TTMaskHasType(&types1, s)) + { + ExtCurStyle->exts_sidePlanes |= PlaneNumToMaskBit(DBPlane(s)); + TTMaskSetType(&ExtCurStyle->exts_sideTypes[DBPlane(s)], s); + TTMaskSetMask(&ExtCurStyle->exts_sideEdges[s], &types2); + for (t = 0; t < DBNumTypes; t++) + { + if (!TTMaskHasType(&types2, t)) + continue; + TTMaskSetMask(&ExtCurStyle->exts_sideCoupleOtherEdges[s][t], &types1); + cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); + cnew->ec_cap = capVal; + cnew->ec_near = types2; + cnew->ec_far = types1; + cnew->ec_next = ExtCurStyle->exts_sideCoupleCap[s][t]; + cnew->ec_pmask = 0; + ExtCurStyle->exts_sideCoupleCap[s][t] = cnew; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtTechSimpleOverlapCap -- + * + * Parse the techfile line for the "defaultoverlap" keyword. + * This is the same as the "overlap" statement excet that shield + * types are determined automatically from the planeorder. + * + * Results: + * None. + * + * Side Effects: + * Adds information into the ExtCurStyle records. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtTechSimpleOverlapCap(argv) + char *argv[]; +{ + TileType s, t; + TileTypeBitMask types1, types2, shields; + CapValue capVal; + int plane1, plane2, plane3, pnum1, pnum2, pnum3; + PlaneMask pshield; + + if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder) + { + TechError("Cannot parse area cap line without plane ordering!\n"); + return; + } + + DBTechNoisyNameMask(argv[1], &types1); + plane1 = DBTechNoisyNamePlane(argv[2]); + TTMaskAndMask(&types1, &DBPlaneTypes[plane1]); + + DBTechNoisyNameMask(argv[3], &types2); + plane2 = DBTechNoisyNamePlane(argv[4]); + TTMaskAndMask(&types2, &DBPlaneTypes[plane2]); + + capVal = aToCap(argv[5]); + + pnum1 = ExtCurStyle->exts_planeOrder[plane1]; + pnum2 = ExtCurStyle->exts_planeOrder[plane2]; + + /* Find all types in or below plane2 (i.e., ~(space)/plane2) */ + /* Shield types are everything in the planes between plane1 and plane2 */ + + TTMaskZero(&shields); + + pshield = 0; + for (plane3 = PL_TECHDEPBASE; plane3 < DBNumPlanes; plane3++) + { + pnum3 = ExtCurStyle->exts_planeOrder[plane3]; + if (pnum3 > pnum2 && pnum3 < pnum1) + { + TTMaskSetMask(&shields, &DBPlaneTypes[plane3]); + pshield |= PlaneNumToMaskBit(plane3); + } + } + TTMaskClearType(&shields, TT_SPACE); + + /* Now record all of the overlap capacitances */ + + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + if (TTMaskHasType(&types1, s)) + { + /* Contact overlap caps are determined from residues */ + if (DBIsContact(s)) continue; + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + if (!TTMaskHasType(&types2, t)) continue; + if (DBIsContact(t)) continue; + + if (s == t) continue; /* shouldn't happen */ + if (plane1 == plane2) continue; /* shouldn't happen */ + if (ExtCurStyle->exts_overlapCap[s][t] > (CapValue) 0) + continue; /* redundant overlap */ + + ExtCurStyle->exts_overlapCap[s][t] = capVal; + ExtCurStyle->exts_overlapPlanes |= PlaneNumToMaskBit(plane1); + ExtCurStyle->exts_overlapOtherPlanes[s] |= PlaneNumToMaskBit(plane2); + TTMaskSetType(&ExtCurStyle->exts_overlapTypes[plane1], s); + TTMaskSetType(&ExtCurStyle->exts_overlapOtherTypes[s], t); + + ExtCurStyle->exts_overlapShieldPlanes[s][t] = pshield; + ExtCurStyle->exts_overlapShieldTypes[s][t] = shields; + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtTechSimpleSideOverlapCap -- + * + * Parse the techfile line for the "defaultsideoverlap" keyword. + * + * Results: + * None. + * + * Side Effects: + * Adds information into the ExtCurStyle records. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtTechSimpleSideOverlapCap(argv) + char *argv[]; +{ + TileType r, s, t; + TileTypeBitMask types, nottypes, ov, notov, shields; + CapValue capVal; + int plane1, plane2, plane3, pnum1, pnum2, pnum3; + PlaneMask pshield; + EdgeCap *cnew; + + if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder) + { + TechError("Cannot parse area cap line without plane ordering!\n"); + return; + } + + DBTechNoisyNameMask(argv[1], &types); + plane1 = DBTechNoisyNamePlane(argv[2]); + + // TTMaskCom2(¬types, &types); + TTMaskZero(¬types); + TTMaskSetType(¬types, TT_SPACE); + + TTMaskAndMask(&types, &DBPlaneTypes[plane1]); + TTMaskAndMask(¬types, &DBPlaneTypes[plane1]); + + DBTechNoisyNameMask(argv[3], &ov); + plane2 = DBTechNoisyNamePlane(argv[4]); + + // TTMaskCom2(¬ov, &ov); + TTMaskZero(¬ov); + TTMaskSetType(¬ov, TT_SPACE); + + TTMaskAndMask(&ov, &DBPlaneTypes[plane2]); + TTMaskAndMask(¬ov, &DBPlaneTypes[plane2]); + + capVal = aToCap(argv[5]); + + pnum1 = ExtCurStyle->exts_planeOrder[plane1]; + pnum2 = ExtCurStyle->exts_planeOrder[plane2]; + + /* Find all types in or below plane2 (i.e., ~(space)/plane2) */ + /* Shield planes are the ones between plane1 and plane2 */ + + TTMaskZero(&shields); + pshield = 0; + for (plane3 = PL_TECHDEPBASE; plane3 < DBNumPlanes; plane3++) + { + pnum3 = ExtCurStyle->exts_planeOrder[plane3]; + if (pnum3 > pnum2 && pnum3 < pnum1) + { + TTMaskSetMask(&shields, &DBPlaneTypes[plane3]); + pshield |= PlaneNumToMaskBit(plane3); + } + } + TTMaskClearType(&shields, TT_SPACE); + + /* Now record all of the sideoverlap capacitances */ + + if (TTMaskHasType(&types, TT_SPACE) || TTMaskHasType(&ov, TT_SPACE)) + { + TechError("Overlap types can't contain space [ignored]\n"); + return; + } + + /* Record all of the sideoverlap capacitances */ + + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + /* Side overlap computed from residues */ + if (DBIsContact(s)) continue; + + if (TTMaskHasType(&types, s)) + { + ExtCurStyle->exts_sidePlanes |= PlaneNumToMaskBit(plane1); + TTMaskSetType(&ExtCurStyle->exts_sideTypes[plane1], s); + TTMaskSetMask(&ExtCurStyle->exts_sideEdges[s], ¬types); + for (t = TT_SPACE; t < DBNumTypes; t++) + { + if (!TTMaskHasType(¬types, t)) continue; + if (DBIsContact(t)) continue; + + TTMaskSetMask(&ExtCurStyle->exts_sideOverlapOtherTypes[s][t], &ov); + ExtCurStyle->exts_sideOverlapOtherPlanes[s][t] |= + PlaneNumToMaskBit(plane2); + cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); + cnew->ec_cap = capVal; + cnew->ec_far = shields; /* Types that shield */ + cnew->ec_near = ov; /* Types we create cap with */ + cnew->ec_pmask = PlaneNumToMaskBit(plane2); + cnew->ec_next = ExtCurStyle->exts_sideOverlapCap[s][t]; + ExtCurStyle->exts_sideOverlapCap[s][t] = cnew; + + for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) + if (TTMaskHasType(&ov, r)) + ExtCurStyle->exts_sideOverlapShieldPlanes[s][r] |= pshield; + } + } + + /* Reverse case (swap "types" and "ov") */ + +#if 0 + if (TTMaskHasType(&ov, s)) + { + ExtCurStyle->exts_sidePlanes |= PlaneNumToMaskBit(plane2); + TTMaskSetType(&ExtCurStyle->exts_sideTypes[plane2], s); + TTMaskSetMask(&ExtCurStyle->exts_sideEdges[s], ¬ov); + for (t = TT_SPACE; t < DBNumTypes; t++) + { + if (!TTMaskHasType(¬ov, t)) continue; + if (DBIsContact(t)) continue; + + TTMaskSetMask(&ExtCurStyle->exts_sideOverlapOtherTypes[s][t], &types); + ExtCurStyle->exts_sideOverlapOtherPlanes[s][t] |= + PlaneNumToMaskBit(plane1); + cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); + cnew->ec_cap = capVal; + cnew->ec_far = shields; /* Types that shield */ + cnew->ec_near = types; /* Types we create cap with */ + cnew->ec_pmask = PlaneNumToMaskBit(plane1); + cnew->ec_next = ExtCurStyle->exts_sideOverlapCap[s][t]; + ExtCurStyle->exts_sideOverlapCap[s][t] = cnew; + + for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) + if (TTMaskHasType(&types, r)) + ExtCurStyle->exts_sideOverlapShieldPlanes[s][r] |= pshield; + } + } +#endif /* 0 */ + } +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtTechLine -- + * + * Process a line from the "extract" section of a technology file. + * + * Each line in the extract section of a technology begins + * with a keyword that identifies the format of the rest of + * the line. + * + * The following three kinds of lines are used to define the resistance + * and parasitic capacitance to substrate of each tile type: + * + * resist types resistance + * areacap types capacitance + * perimcap inside outside capacitance + * + * where 'types', 'inside', and 'outside' are comma-separated lists + * of tile types, 'resistance' is an integer giving the resistance + * per square in milli-ohms, and 'capacitance' is an integer giving + * capacitance (per square lambda for areacap, or per lambda perimeter + * for perimcap) in attofarads. + * + * The perimeter (sidewall) capacitance depends both on the types + * inside and outside the perimeter. For a given 'perimcap' line, + * any segment of perimeter with a type in 'inside' inside the + * perimeter and a type in 'outside' ontside the perimeter will + * have the indicated capacitance. + * + * Both area and perimeter capacitance computed from the information + * above apply between a given node and the substrate beneath it, as + * determined by extSubstrate[]. + * + * Contact resistances are specified by: + * + * contact type minsize resistance + * + * where type is the type of contact tile, minsize is chosen so that contacts + * that are integer multiples of minsize get an additional contact cut for each + * increment of minsize, and resistance is in milliohms. + * + * Overlap coupling capacitance is specified by: + * + * overlap toptypes bottomtypes capacitance [shieldtypes] + * + * where 'toptypes' and 'bottomtypes' are comma-separated lists of tile types, + * and 'capacitance' is an integer giving capacitance in attofarads per + * square lambda of overlap. The sets 'toptypes' and 'bottomtypes' should + * be disjoint. Also, the union of the planes of 'toptypes' should be disjoint + * from the union of the planes of 'bottomtypes'. If 'shieldtypes' are + * present, they should also be a comma-separated list of types, on + * planes disjoint from those of either 'toptypes' or 'bottomtypes'. + * + * Whenever a tile of a type in 'toptypes' overlaps one of a type in + * 'bottomtypes', we deduct the capacitance to substrate of the 'toptypes' + * tile for the area of the overlap, and create an overlap capacitance + * between the two nodes based on 'capacitance'. When material in + * 'shieldtypes' appears over any of this overlap area, however, we + * only deduct the substrate capacitance; we don't create an overlap + * capacitor. + * + * Sidewall coupling capacitance is specified by: + * + * sidewall intypes outtypes neartypes fartypes capacitance + * + * where 'intypes', 'outtypes', 'neartypes', and 'fartypes' are all comma- + * separated lists of types, and 'capacitance' is an integer giving capacitance + * in attofarads. All of the tiles in all four lists should be on the same + * plane. + * + * Whenever an edge of the form i|j is seen, where 'i' is in intypes and + * 'j' is in outtypes, we search on the 'j' side for a distance of + * ExtCurStyle->exts_sideCoupleHalo for edges with 'neartypes' on the + * close side and 'fartypes' on the far side. We create a capacitance + * equal to the length of overlap, times capacitance, divided by the + * separation between the edges (poor approximation, but better than + * none). + * + * Sidewall overlap coupling capacitance is specified by: + * + * sideoverlap intypes outtypes ovtypes capacitance + * + * where 'intypes', 'outtypes', and 'ovtypes' are comma-separated lists + * of types, and 'capacitance' is an integer giving capacitance in attofarads + * per lambda. Both intypes and outtypes should be in the same plane, and + * ovtypes should be in a different plane from intypes and outtypes. + * + * The next kind of line describes transistors: + * + * fet types terminals min-#terminals names substrate gscap gccap + * + * where 'types' and 'terminals' are comma-separated lists of tile types. + * The meaning is that each type listed in 'types' is a transistor, whose + * source and drain connect to any of the types listed in 'terminals'. + * These transistors must have exactly min-#terminals terminals, in addition + * to the gate (whose connectivity is specified in the system-wide connectivity + * table in the "connect" section of the .tech file). Currently gscap and + * gccap are unused, but refer to the gate-source (or gate-drain) capacitance + * and the gate-channel capacitance in units of attofarads per lambda and + * attofarads per square lambda respectively. + * + * The resistances of transistors is specified by: + * + * fetresist type region ohms + * + * where type is a type of tile that is a fet, region is a string ("linear" + * is treated specially), and ohms is the resistance per square of the fet + * type while operating in "region". The values of fets in the "linear" + * region are stored in a separate table. + * + * Results: + * Returns TRUE normally, or FALSE if the line from the + * technology file is so malformed that Magic should abort. + * Currently, we always return TRUE. + * + * Side effects: + * Initializes the per-technology variables that appear at the + * beginning of this file. + * + * ---------------------------------------------------------------------------- + */ + +#define MAXSD 6 + + /*ARGSUSED*/ +bool +ExtTechLine(sectionName, argc, argv) + char *sectionName; + int argc; + char *argv[]; +{ + int n, l, i, j, size, val, p1, p2, p3, nterm, iterm, class; + PlaneMask pshield, pov; + CapValue capVal, gscap, gccap; + TileTypeBitMask types1, types2, termtypes[MAXSD]; + TileTypeBitMask near, far, ov, shield, subsTypes; + char *subsName, *transName, *cp, *endptr, *paramName; + TileType s, t, r, o; + keydesc *kp, *dv; + bool isLinear; + HashEntry *he; + EdgeCap *cnew; + ExtKeep *es, *newStyle; + ParamList *subcktParams, *newParam; + int refcnt; + double dhalo; + bool bad; + + if (argc < 1) + { + TechError("Each line must begin with a keyword\n"); + return (TRUE); + } + + n = LookupStruct(argv[0], (LookupTable *) keyTable, sizeof keyTable[0]); + if (n < 0) + { + TechError("Illegal keyword. Legal keywords are:\n\t"); + for (n = 0; keyTable[n].k_name; n++) + TxError(" %s", keyTable[n].k_name); + TxError("\n"); + return (TRUE); + } + + kp = &keyTable[n]; + if (argc < kp->k_minargs) + goto usage; + + /* Handle maxargs for DEVICE type separately */ + if ((argc > kp->k_maxargs) && (kp->k_key != DEVICE)) + goto usage; + + else if (argc >= 2) l = strlen(argv[1]); + + /* If ExtCurStyle is NULL, this is a first pass, and we should */ + /* immediately load this style as default. Otherwise, check if */ + /* the style name is in the table of styles, and add it if it is */ + /* not. */ + + if (kp->k_key == STYLE) + { + if (argc != 2) + if ((argc != 4) || (strncmp(argv[2], "variant", 7))) + goto usage; + + for (newStyle = ExtAllStyles; newStyle != NULL; + newStyle = newStyle->exts_next) + { + if (!strncmp(newStyle->exts_name, argv[1], l)) + break; + } + if (newStyle == NULL) + { + if (argc == 2) + { + newStyle = (ExtKeep *)mallocMagic(sizeof(ExtKeep)); + newStyle->exts_next = NULL; + newStyle->exts_name = StrDup((char **) NULL, argv[1]); + + if (ExtAllStyles == NULL) + ExtAllStyles = newStyle; + else + { + /* Append to end of style list */ + for (es = ExtAllStyles; es->exts_next; es = es->exts_next); + es->exts_next = newStyle; + } + } + else /* Handle style variants */ + { + ExtKeep *saveStyle = NULL; + char *tptr, *cptr; + + /* 4th argument is a comma-separated list of variants. */ + /* In addition to the default name recorded above, */ + /* record each of the variants. */ + + tptr = argv[3]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) *cptr = '\0'; + newStyle = (ExtKeep *)mallocMagic(sizeof(ExtKeep)); + newStyle->exts_next = NULL; + newStyle->exts_name = (char *)mallocMagic(l + + strlen(tptr) + 1); + sprintf(newStyle->exts_name, "%s%s", argv[1], tptr); + + /* Remember the first variant as the default */ + if (saveStyle == NULL) saveStyle= newStyle; + + /* Append to end of style list */ + if (ExtAllStyles == NULL) + ExtAllStyles = newStyle; + else + { + for (es = ExtAllStyles; es->exts_next; es = es->exts_next); + es->exts_next = newStyle; + } + + if (cptr == NULL) + break; + else + tptr = cptr + 1; + } + newStyle = saveStyle; + } + } + + /* Load style as default extraction style if this is the first */ + /* style encountered. Otherwise, if we are changing styles, */ + /* load this style only if the name matches that in ExtCurStyle.*/ + + if (ExtCurStyle == NULL) + { + ExtCurStyle = extTechStyleNew(); + ExtCurStyle->exts_name = newStyle->exts_name; + ExtCurStyle->exts_status = TECH_PENDING; + } + else if ((ExtCurStyle->exts_status == TECH_PENDING) || + (ExtCurStyle->exts_status == TECH_SUSPENDED)) + /* Finished loading; stop */ + ExtCurStyle->exts_status = TECH_LOADED; + else if (ExtCurStyle->exts_status == TECH_NOT_LOADED) + { + if (ExtCurStyle->exts_name == NULL) + return (FALSE); /* Don't know what to load! */ + else if (argc == 2) + { + if (!strcmp(argv[1], ExtCurStyle->exts_name)) + ExtCurStyle->exts_status = TECH_PENDING; /* load pending */ + } + else if (argc == 4) + { + /* Verify that the style matches one variant */ + char *tptr, *cptr; + if (!strncmp(ExtCurStyle->exts_name, argv[1], l)) + { + tptr = argv[3]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) *cptr = '\0'; + if (!strcmp(ExtCurStyle->exts_name + l, tptr)) + { + ExtCurStyle->exts_status = TECH_PENDING; + return TRUE; + } + if (cptr == NULL) + return TRUE; + else + tptr = cptr + 1; + } + } + } + } + return (TRUE); + } + + /* Only continue past this point if we are loading the extraction style */ + if (ExtCurStyle == NULL) return FALSE; + if ((ExtCurStyle->exts_status != TECH_PENDING) && + (ExtCurStyle->exts_status != TECH_SUSPENDED)) + return TRUE; + + /* Process "variant" lines next */ + + if (kp->k_key == VARIANT) + { + int l; + char *cptr, *tptr; + + /* If our style variant is not one of the ones declared */ + /* on the line, then we ignore all input until we */ + /* either reach the end of the style, the end of the */ + /* section, or another "variant" line. */ + + if (argc != 2) goto usage; + tptr = argv[1]; + while (*tptr != '\0') + { + cptr = strchr(tptr, ','); + if (cptr != NULL) + { + *cptr = '\0'; + for (j = 1; isspace(*(cptr - j)); j++) + *(cptr - j) = '\0'; + } + + if (*tptr == '*') /* Wildcard for "all variants" */ + { + ExtCurStyle->exts_status = TECH_PENDING; + return TRUE; + } + else + { + l = strlen(ExtCurStyle->exts_name) - strlen(tptr); + if (!strcmp(tptr, ExtCurStyle->exts_name + l)) + { + ExtCurStyle->exts_status = TECH_PENDING; + return TRUE; + } + } + + if (cptr == NULL) + break; + else + tptr = cptr + 1; + } + ExtCurStyle->exts_status = TECH_SUSPENDED; + } + + /* Anything below this line is not parsed if we're in TECH_SUSPENDED mode */ + if (ExtCurStyle->exts_status != TECH_PENDING) return TRUE; + + switch (kp->k_key) + { + case AREAC: + case CONTACT: + case FET: + case FETRESIST: + case HEIGHT: + case OVERC: + case PERIMC: + case RESIST: + case SIDEWALL: + case SIDEOVERLAP: + case SUBSTRATE: + DBTechNoisyNameMask(argv[1], &types1); + break; + case DEVICE: + DBTechNoisyNameMask(argv[3], &types1); + break; + case PLANEORDER: + case NOPLANEORDER: + default: + break; + } + + switch (kp->k_key) + { + case AREAC: + capVal = aToCap(argv[2]); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + ExtCurStyle->exts_areaCap[t] = capVal; + break; + case CONTACT: + /* Contact size, border, spacing deprecated (now taken from */ + /* cifoutput "squares" generation parameters). */ + if (argc != 3) + { + if (argc == 4) + TxPrintf("Contact size value ignored " + "(using GDS generation rules).\n"); + else + TxPrintf("Contact size, spacing, and border values ignored " + "(using GDS generation rules).\n"); + } + + if (!StrIsInt(argv[argc - 1])) + { + TechError("Contact resistivity %s must be an integer value " + "(in milliohms/square).\n", argv[argc - 1]); + break; + } + val = atoi(argv[argc - 1]); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + ExtCurStyle->exts_viaResist[t] = val; + break; + case CSCALE: + ExtCurStyle->exts_capScale = strtol(argv[1], &endptr, 10); + if (endptr == argv[1]) + { + TechError("Cannot parse cap scale value \"%s\"\n", argv[1]); + ExtCurStyle->exts_capScale = 1; + } + break; + case FET: + + /* Original FET format, kept for backwards compatibility */ + + DBTechNoisyNameMask(argv[2], &termtypes[0]); + nterm = atoi(argv[3]); + transName = argv[4]; + subsName = argv[5]; + + // From magic version 8.1, subs name can be a nonfunctional + // throwaway (e.g., "error"), so don't throw a warning. + + cp = strchr(subsName, '!'); + if (cp == NULL || cp[1] != '\0') + { + if (strcasecmp(subsName, "error")) + { + TechError("Fet substrate node %s is not a global name\n", + subsName); + } + } + + subsTypes = DBZeroTypeBits; + if (sscanf(argv[6], "%lf", &capVal) != 1) + { + DBTechNoisyNameMask(argv[6], &subsTypes); + gscap = aToCap(argv[7]); + gccap = (argc > 8) ? aToCap(argv[8]) : (CapValue) 0; + } + else + { + gscap = aToCap(argv[6]); + gccap = (argc > 7) ? aToCap(argv[7]) : (CapValue) 0; + } + + TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + { + TTMaskSetMask(ExtCurStyle->exts_transConn+t,&types1); + ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *) + mallocMagic(2 * sizeof(TileTypeBitMask)); + ExtCurStyle->exts_transSDTypes[t][0] = termtypes[0]; + ExtCurStyle->exts_transSDTypes[t][1] = DBZeroTypeBits; + ExtCurStyle->exts_transSDCount[t] = nterm; + ExtCurStyle->exts_transSDCap[t] = gscap; + ExtCurStyle->exts_transGateCap[t] = gccap; + ExtCurStyle->exts_deviceClass[t] = DEV_FET; + ExtCurStyle->exts_transName[t] = + StrDup((char **) NULL, transName); + ExtCurStyle->exts_transSubstrateName[t] = + StrDup((char **) NULL, subsName); + ExtCurStyle->exts_transSubstrateTypes[t] = subsTypes; +#ifdef ARIEL + { + int z; + + for (z = TT_TECHDEPBASE; z < DBNumTypes; z++) + { + if (TTMaskHasType(&subsTypes, z)) + TTMaskSetType(&ExtCurStyle->exts_subsTransistorTypes[z], + t); + } + } +#endif + } + break; + + case DEFAULTAREACAP: + ExtTechSimpleAreaCap(argc, argv); + break; + case DEFAULTOVERLAP: + ExtTechSimpleOverlapCap(argv); + break; + case DEFAULTPERIMETER: + ExtTechSimplePerimCap(argc, argv); + break; + case DEFAULTSIDEOVERLAP: + ExtTechSimpleSideOverlapCap(argv); + break; + case DEFAULTSIDEWALL: + ExtTechSimpleSidewallCap(argv); + break; + + case DEVICE: + + /* Parse second argument for device type */ + + n = LookupStruct(argv[1], (LookupTable *) devTable, sizeof devTable[0]); + if (n < 0) + { + TechError("Illegal device. Legal devices are:\n\t"); + for (n = 0; devTable[n].k_name; n++) + TxError(" %s", devTable[n].k_name); + TxError("\n"); + return (TRUE); + } + + dv = &devTable[n]; + if ((argc - 1) < dv->k_minargs) + goto usage; + + /* Parse parameters from the end of the argument list. */ + /* Parameters may be provided for any device. */ + + /* Check final arguments for "x=y" statements showing what */ + /* parameter names the device uses. */ + + subcktParams = NULL; + while ((paramName = strchr(argv[argc - 1], '=')) != NULL) + { + char *mult; + + paramName++; + newParam = (ParamList *)mallocMagic(sizeof(ParamList)); + newParam->pl_count = 0; + newParam->pl_param[0] = *argv[argc - 1]; + newParam->pl_param[1] = '\0'; + + if (paramName - argv[argc - 1] == 3) + newParam->pl_param[1] = *(argv[argc - 1] + 1); + + else if (paramName - argv[argc - 1] > 3) + TechError("Parameter name %s can be no more than" + "two characters.\n", argv[argc - 1]); + + // Parameter syntax "=*" indicates + // that the subcircuit has internal scaling, and the + // extractor should multiply the parameter by this value + // before passing it to the subcircuit. + + if ((mult = strchr(paramName, '*')) != NULL) + { + *mult = '\0'; + mult++; + newParam->pl_scale = atof(mult); + } + else + newParam->pl_scale = 1.0; + + newParam->pl_name = StrDup((char **)NULL, paramName); + newParam->pl_next = subcktParams; + subcktParams = newParam; + argc--; + } + + /* Check the number of arguments after splitting out */ + /* parameter entries. There is no limit on arguments in */ + /* DEV_SUBCKT and DEV_MSUBCKT. */ + + class = dv->k_key; + switch (class) + { + case DEV_SUBCKT: + case DEV_MSUBCKT: + break; + default: + /* If parameters were saved but the */ + /* argument list indicates a bad */ + /* device entry, then free up the */ + /* parameters. */ + + if ((argc - 1) > dv->k_maxargs) + { + while (subcktParams != NULL) + { + freeMagic(subcktParams->pl_name); + freeMagic(subcktParams); + subcktParams = subcktParams->pl_next; + } + goto usage; + } + break; + } + + gscap = (CapValue) 0; + gccap = (CapValue) 0; + subsName = NULL; + subsTypes = DBZeroTypeBits; + transName = argv[2]; + + switch (dv->k_key) + { + case DEV_BJT: + DBTechNoisyNameMask(argv[4], &termtypes[0]); /* emitter */ + termtypes[1] = DBZeroTypeBits; + DBTechNoisyNameMask(argv[5], &subsTypes); /* collector */ + nterm = 1; /* emitter is the only "terminal type" expected */ + break; + case DEV_MOSFET: + if ((argc > 7) && (!StrIsNumeric(argv[7]))) + { + /* Asymmetric device with different source and drain types */ + + DBTechNoisyNameMask(argv[4], &termtypes[0]); /* source */ + DBTechNoisyNameMask(argv[5], &termtypes[1]); /* drain */ + TTMaskAndMask3(&termtypes[2], &termtypes[0], &termtypes[1]); + + if (TTMaskEqual(&termtypes[0], &termtypes[1])) + termtypes[1] = DBZeroTypeBits; /* Make it symmetric */ + else if (!TTMaskIsZero(&termtypes[2])) + { + TechError("Device mosfet %s has overlapping drain" + " and source types!\n", transName); + /* Should this device be disabled? */ + } + termtypes[2] = DBZeroTypeBits; + if (strcmp(argv[6], "None")) + DBTechNoisyNameMask(argv[6], &subsTypes); /* substrate */ + subsName = argv[7]; + if (argc > 8) gscap = aToCap(argv[8]); + if (argc > 9) gccap = aToCap(argv[9]); + nterm = 2; + class = DEV_ASYMMETRIC; + } + else + { + /* Normal symmetric device with swappable source/drain */ + + DBTechNoisyNameMask(argv[4], &termtypes[0]); /* source/drain */ + termtypes[1] = DBZeroTypeBits; + if (strcmp(argv[5], "None")) + DBTechNoisyNameMask(argv[5], &subsTypes); /* substrate */ + if (argc > 6) subsName = argv[6]; + if (argc > 7) gscap = aToCap(argv[7]); + if (argc > 8) gccap = aToCap(argv[8]); + /* nterm = 1; */ /* Symmetric devices can be MOScaps */ + nterm = 2; + } + break; + + case DEV_DIODE: + case DEV_PDIODE: + case DEV_NDIODE: + DBTechNoisyNameMask(argv[4], &termtypes[0]); /* negative types */ + termtypes[1] = DBZeroTypeBits; + nterm = 1; + if ((argc > 4) && strcmp(argv[4], "None")) + DBTechNoisyNameMask(argv[4], &subsTypes); /* substrate */ + else + subsTypes = DBZeroTypeBits; + if (argc > 5) subsName = argv[5]; + break; + + case DEV_RES: + DBTechNoisyNameMask(argv[4], &termtypes[0]); /* terminals */ + termtypes[1] = DBZeroTypeBits; + nterm = 2; + if ((argc > 5) && strcmp(argv[5], "None")) + DBTechNoisyNameMask(argv[5], &subsTypes); /* substrate */ + else + subsTypes = DBZeroTypeBits; + if (argc > 6) subsName = argv[6]; + break; + + case DEV_CAP: + case DEV_CAPREV: + DBTechNoisyNameMask(argv[4], &termtypes[0]); /* bottom */ + termtypes[1] = DBZeroTypeBits; + + if (argc > 5) + gccap = aToCap(argv[argc - 1]); /* area cap */ + if ((argc > 6) && StrIsNumeric(argv[argc - 2])) + { + gscap = aToCap(argv[argc - 2]); /* perimeter cap */ + argc--; + } + nterm = 1; + + if ((argc > 6) && strcmp(argv[5], "None")) + DBTechNoisyNameMask(argv[5], &subsTypes); /* substrate */ + else + subsTypes = DBZeroTypeBits; + if (argc > 7) subsName = argv[6]; + break; + + case DEV_SUBCKT: + case DEV_MSUBCKT: + if (StrIsInt(argv[4])) + { + nterm = atoi(argv[4]); + iterm = 4 + nterm; + } + else + { + nterm = 1; + iterm = 4; + } + + /* terminals */ + for (i = iterm; i < iterm + nterm; i++) + DBTechNoisyNameMask(argv[iterm], &termtypes[i - iterm]); + termtypes[nterm] = DBZeroTypeBits; + + if (nterm == 0) i++; + + // Type MSUBCKT: Source and drain are symmetric. The + // number of unique terminals in the definition is 1, + // but nterm needs to be set to 2 for proper extraction. + + if ((dv->k_key == DEV_MSUBCKT) && (nterm == 1)) nterm = 2; + + if (argc > i) + DBTechNoisyNameMask(argv[i], &subsTypes); /* substrate */ + if (argc > (i + 1)) subsName = argv[i + 1]; + break; + + case DEV_RSUBCKT: + nterm = 2; + DBTechNoisyNameMask(argv[4], &termtypes[0]); /* terminals */ + termtypes[1] = DBZeroTypeBits; + + if ((argc > 5) && strcmp(argv[5], "None")) + DBTechNoisyNameMask(argv[5], &subsTypes); /* substrate */ + else + subsTypes = DBZeroTypeBits; + if (argc > 6) subsName = argv[6]; + break; + } + + TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + if (TTMaskHasType(&types1, t)) + { + TTMaskSetMask(ExtCurStyle->exts_transConn + t, &types1); + + for (i = 0; !TTMaskIsZero(&termtypes[i]); i++); + ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *) + mallocMagic((i + 1) * sizeof(TileTypeBitMask)); + + for (i = 0; !TTMaskIsZero(&termtypes[i]); i++) + ExtCurStyle->exts_transSDTypes[t][i] = termtypes[i]; + ExtCurStyle->exts_transSDTypes[t][i] = DBZeroTypeBits; + + ExtCurStyle->exts_transSDCount[t] = nterm; + ExtCurStyle->exts_transSDCap[t] = gscap; + ExtCurStyle->exts_transGateCap[t] = gccap; + ExtCurStyle->exts_deviceClass[t] = class; + ExtCurStyle->exts_transName[t] = + StrDup((char **) NULL, transName); + if (subsName != NULL) + ExtCurStyle->exts_transSubstrateName[t] = + StrDup((char **) NULL, subsName); + ExtCurStyle->exts_transSubstrateTypes[t] = subsTypes; +#ifdef ARIEL + { + int z; + + for (z = TT_TECHDEPBASE; z < DBNumTypes; z++) + { + if (TTMaskHasType(&subsTypes, z)) + TTMaskSetType(&ExtCurStyle-> + exts_subsTransistorTypes[z], t); + } + } +#endif + if (subcktParams != NULL) + { + ExtCurStyle->exts_deviceParams[t] = subcktParams; + subcktParams->pl_count++; + } + } + } + break; + + case FETRESIST: + if (!StrIsInt(argv[3])) + { + TechError("Fet resistivity %s must be numeric\n", argv[3]); + break; + } + val = atoi(argv[3]); + isLinear = (strcmp(argv[2], "linear") == 0); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + { + he = HashFind(&ExtCurStyle->exts_transResist[t], argv[2]); + HashSetValue(he, (spointertype)val); + if (isLinear) + ExtCurStyle->exts_linearResist[t] = val; + } + break; + case HEIGHT: { + float height, thick; + + if (!StrIsNumeric(argv[2])) + { + TechError("Layer height %s must be numeric\n", argv[2]); + break; + } + if (!StrIsNumeric(argv[3])) + { + TechError("Layer thickness %s must be numeric\n", argv[3]); + break; + } + height = (float)strtod(argv[2], NULL); + thick = (float)strtod(argv[3], NULL); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + { + ExtCurStyle->exts_height[t] = height; + ExtCurStyle->exts_thick[t] = thick; + } + } + break; + case UNITS: + if (!strcmp(argv[1], "microns")) + doConvert = TRUE; + else if (!strcmp(argv[1], "um")) + doConvert = TRUE; + else if (strcmp(argv[1], "lambda")) + TechError("Units must be microns or lambda. Using the " + "default value (lambda).\n"); + break; + case LAMBDA: + ExtCurStyle->exts_unitsPerLambda = (float)atof(argv[1]); + break; + case OVERC: + DBTechNoisyNameMask(argv[2], &types2); + capVal = aToCap(argv[3]); + bad = FALSE; + shield = DBZeroTypeBits; + if (argc > 4) + DBTechNoisyNameMask(argv[4], &shield); + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + if (!TTMaskHasType(&types1, s)) continue; + + /* Contact overlap caps are determined from residues */ + if (DBIsContact(s)) continue; + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + if (!TTMaskHasType(&types2, t)) continue; + + /* Contact overlap caps are determined from residues */ + if (DBIsContact(t)) continue; + + if (s == t) + { + TechError("Can't have overlap capacitance between" + " tiles of the same type (%s)\n", + DBTypeLongName(s)); + bad = TRUE; + continue; + } + p1 = DBPlane(s), p2 = DBPlane(t); + if (p1 == p2) + { + TechError("Can't have overlap capacitance between" + " tiles on the same plane (%s, %s)\n", + DBTypeLongName(s), DBTypeLongName(t)); + bad = TRUE; + continue; + } + if (ExtCurStyle->exts_overlapCap[s][t] > (CapValue) 0) + { + TechError("Only one of \"overlap %s %s\" or" + " \"overlap %s %s\" allowed\n", + DBTypeLongName(s), DBTypeLongName(t), + DBTypeLongName(t), DBTypeLongName(s)); + bad = TRUE; + continue; + } + ExtCurStyle->exts_overlapCap[s][t] = capVal; + ExtCurStyle->exts_overlapPlanes |= PlaneNumToMaskBit(p1); + ExtCurStyle->exts_overlapOtherPlanes[s] + |= PlaneNumToMaskBit(p2); + TTMaskSetType(&ExtCurStyle->exts_overlapTypes[p1], s); + TTMaskSetType(&ExtCurStyle->exts_overlapOtherTypes[s], t); + if (argc == 4) continue; + + /* Shielding */ + pshield = 0; + for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) + { + if (TTMaskHasType(&shield, r)) + { + /* Shielding types are determined from residues */ + if (DBIsContact(r)) continue; + + p3 = DBPlane(r); + if (p3 == p1 || p3 == p2) + { + TechError("Shielding type (%s) must be on a" + " different plane from shielded types.\n", + DBTypeLongName(r)); + bad = TRUE; + continue; + } + pshield |= PlaneNumToMaskBit(p3); + } + } + ExtCurStyle->exts_overlapShieldPlanes[s][t] = pshield; + ExtCurStyle->exts_overlapShieldTypes[s][t] = shield; + } + } + if (bad) + return (TRUE); + break; + case SIDEOVERLAP: + bad = FALSE; + DBTechNoisyNameMask(argv[2], &types2); + pov = DBTechNoisyNameMask(argv[3], &ov); + capVal = aToCap(argv[4]); + shield = DBZeroTypeBits; + if (argc == 6) DBTechNoisyNameMask(argv[5], &shield); + if (TTMaskHasType(&types1, TT_SPACE)) + TechError("Can't have space on inside of edge [ignored]\n"); + /* It's ok to have the overlap be to space as long as a plane is */ + /* specified. */ + if (TTMaskHasType(&ov, TT_SPACE)) + { + if ((cp = strchr(argv[3],'/')) == NULL) + { + TechError("Must specify plane for sideoverlap to space\n"); + } + cp++; + p3 = (spointertype) dbTechNameLookup(cp, &dbPlaneNameLists); + if (p3 < 0) + TechError("Unknown overlap plane %s\n",argv[3]); + else + pov = PlaneNumToMaskBit(p3); + } + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + if (!TTMaskHasType(&types1, s)) + continue; + + /* Side overlap computed from residues */ + if (DBIsContact(s)) continue; + + p1 = DBPlane(s); + if (PlaneMaskHasPlane(pov, p1)) + goto diffplane; + ExtCurStyle->exts_sidePlanes |= PlaneNumToMaskBit(p1); + TTMaskSetType(&ExtCurStyle->exts_sideTypes[p1], s); + TTMaskSetMask(&ExtCurStyle->exts_sideEdges[s], &types2); + for (t = 0; t < DBNumTypes; t++) + { + if (!TTMaskHasType(&types2, t)) + continue; + + /* Side overlap computed from residues */ + if (DBIsContact(t)) continue; + + p2 = DBPlane(t); + if (t != TT_SPACE && PlaneMaskHasPlane(pov, p2)) + goto diffplane; + TTMaskSetMask(&ExtCurStyle->exts_sideOverlapOtherTypes[s][t], &ov); + ExtCurStyle->exts_sideOverlapOtherPlanes[s][t] |= pov; + cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); + cnew->ec_cap = capVal; + cnew->ec_far = shield; /* Really types that shield */ + cnew->ec_near = ov; /* Really types we create cap with */ + cnew->ec_pmask = pov; + cnew->ec_next = ExtCurStyle->exts_sideOverlapCap[s][t]; + ExtCurStyle->exts_sideOverlapCap[s][t] = cnew; + + /* Shielding */ + pshield = 0; + for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) + { + if (TTMaskHasType(&shield, r)) + { + /* Side overlap shielding computed from residues */ + if (DBIsContact(r)) continue; + + p3 = DBPlane(r); + if (p3 == p1 || p3 == p2) + { + TechError("Shielding type (%s) must be on" + " a different plane from shielded types.\n", + DBTypeLongName(r)); + bad = TRUE; + continue; + } + pshield |= PlaneNumToMaskBit(p3); + } + } + for (o = TT_TECHDEPBASE; o < DBNumTypes; o++) + { + if (TTMaskHasType(&ov, o)) + { + ExtCurStyle->exts_sideOverlapShieldPlanes[s][o] |= pshield; + } + } + } + } + if (bad) + return (TRUE); + break; + case SIDEWALL: + DBTechNoisyNameMask(argv[2], &types2); + DBTechNoisyNameMask(argv[3], &near); + DBTechNoisyNameMask(argv[4], &far); + if (TTMaskHasType(&types1, TT_SPACE)) + TechError("Can't have space on inside of edge [ignored]\n"); + capVal = aToCap(argv[5]); + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + if (!TTMaskHasType(&types1, s)) + continue; + ExtCurStyle->exts_sidePlanes |= PlaneNumToMaskBit(DBPlane(s)); + TTMaskSetType(&ExtCurStyle->exts_sideTypes[DBPlane(s)], s); + TTMaskSetMask(&ExtCurStyle->exts_sideEdges[s], &types2); + for (t = 0; t < DBNumTypes; t++) + { + if (!TTMaskHasType(&types2, t)) + continue; + TTMaskSetMask(&ExtCurStyle->exts_sideCoupleOtherEdges[s][t], &far); + cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); + cnew->ec_cap = capVal; + cnew->ec_near = near; + cnew->ec_far = far; + cnew->ec_next = ExtCurStyle->exts_sideCoupleCap[s][t]; + cnew->ec_pmask = 0; + ExtCurStyle->exts_sideCoupleCap[s][t] = cnew; + } + } + break; + case SIDEHALO: + /* Allow floating-point and increase by factor of 1000 */ + /* to accommodate "units microns". */ + + /* Warning: Due to some gcc bug with an i686 FPU, using a */ + /* result from atof() with a static value like 1000 */ + /* produces a NaN result! sscanf() seems to be safe. . . */ + + sscanf(argv[1], "%lg", &dhalo); + dhalo *= (double)1000.0; + ExtCurStyle->exts_sideCoupleHalo = (int)dhalo; + break; + case PERIMC: + DBTechNoisyNameMask(argv[2], &types2); + capVal = aToCap(argv[3]); + if (capVal == (CapValue) 0) + break; + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + for (t = 0; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, s) && TTMaskHasType(&types2, t)) + { + ExtCurStyle->exts_perimCap[s][t] = capVal; + TTMaskSetType(&ExtCurStyle->exts_perimCapMask[s], t); + } + break; + case RESIST: { + float chop = 1.0; + + if (!StrIsInt(argv[2])) + { + if (!strcmp(argv[2], "None")) + { + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + TTMaskClearType(&ExtCurStyle->exts_activeTypes, t); + break; + } + else + { + TxError("Resist argument must be integer or \"None\".\n"); + break; + } + } + else + val = atoi(argv[2]); + + if (argc == 4) + chop = atof(argv[3]); + class = ExtCurStyle->exts_numResistClasses++; + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + { + ExtCurStyle->exts_sheetResist[t] = val; + ExtCurStyle->exts_cornerChop[t] = chop; + ExtCurStyle->exts_typeToResistClass[t] = class; + } + ExtCurStyle->exts_resistByResistClass[class] = val; + ExtCurStyle->exts_typesByResistClass[class] = types1; + } + break; + case RSCALE: + ExtCurStyle->exts_resistScale = atoi(argv[1]); + break; + case STEP: + val = (int)atof(argv[1]); + if (val <= 0) + { + TechError("Hierarchical interaction step size must be > 0\n"); + return (FALSE); + } + ExtCurStyle->exts_stepSize = val; + break; + case SUBSTRATE: + TTMaskZero(&ExtCurStyle->exts_globSubstrateTypes); + TTMaskSetMask(&ExtCurStyle->exts_globSubstrateTypes, &types1); + ExtCurStyle->exts_globSubstratePlane = DBTechNoisyNamePlane(argv[2]); + break; + case NOPLANEORDER: { + if ( ExtCurStyle->exts_planeOrderStatus == seenPlaneOrder ) + TechError("\"noplaneordering\" specified after \"planeorder\".\n"); + else + ExtCurStyle->exts_planeOrderStatus = noPlaneOrder ; + } + break ; + case PLANEORDER: { + int pnum = (spointertype) dbTechNameLookup(argv[1], &dbPlaneNameLists); + int pos = atoi(argv[2]); + + if ( ExtCurStyle->exts_planeOrderStatus == noPlaneOrder ) { + TechError("\"planeorder\" specified after \"noplaneordering\".\n"); + } + ExtCurStyle->exts_planeOrderStatus = seenPlaneOrder ; + if (pnum < 0) + TechError("Unknown planeorder plane %s\n", argv[1]); + else if (pos < 0 || pos >= DBNumPlanes-PL_TECHDEPBASE) + TechError("Planeorder index must be [0..%d]\n", + DBNumPlanes-PL_TECHDEPBASE-1); + else + ExtCurStyle->exts_planeOrder[pnum] = pos; + } + break; + } + return (TRUE); + +usage: + TechError("Malformed line for keyword %s. Correct usage:\n\t%s %s\n", + kp->k_name, kp->k_name, kp->k_usage); + return (TRUE); + +diffplane: + TechError("Overlapped types in \"sideoverlap\" rule must be on a\n" + "\tdifferent plane from intypes and outtypes.\n"); + return (TRUE); +} + + +/* + * ---------------------------------------------------------------------------- + * + * ExtTechFinal -- + * + * Postprocess the technology specific information for extraction. + * Builds the connectivity tables exts_nodeConn[], exts_resistConn[], + * and exts_transConn[]. + * + * Results: + * None. + * + * Side effects: + * Initializes the tables mentioned above. + * Leaves ExtCurStyle pointing to the first style in the list + * ExtAllStyles. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtTechFinal() +{ + ExtStyle *es; + + /* Create a "default" style if there isn't one */ + if (ExtAllStyles == NULL) + { + ExtAllStyles = (ExtKeep *)mallocMagic(sizeof(ExtKeep)); + ExtAllStyles->exts_next = NULL; + ExtAllStyles->exts_name = StrDup((char **) NULL, "default"); + + ExtCurStyle = extTechStyleNew(); + ExtCurStyle->exts_name = ExtAllStyles->exts_name; + ExtCurStyle->exts_status = TECH_LOADED; + } + extTechFinalStyle(ExtCurStyle); +} + + +void +extTechFinalStyle(style) + ExtStyle *style; +{ + TileTypeBitMask maskBits; + TileType r, s, t; + int p, p1, missing, conflict; + int indicis[NP]; + + for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) + { + maskBits = style->exts_nodeConn[r] = DBConnectTbl[r]; + if (!TTMaskHasType(&style->exts_transMask, r)) + { + TTMaskZero(&style->exts_transConn[r]); + } + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + if (TTMaskHasType(&maskBits, s)) + if (style->exts_typeToResistClass[s] + != style->exts_typeToResistClass[r]) + TTMaskClearType(&maskBits, s); + } + style->exts_resistConn[r] = maskBits; + } + + /* r ranges over types, s over resistance entries */ + for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) + { + s = style->exts_typeToResistClass[r]; + if (s >= 0) + TTMaskClearMask(&style->exts_typesResistChanged[r], + &style->exts_typesByResistClass[s]); + } + + /* + * Residue check: + * We have ignored all contact types when parsing parasitic + * capacitances. Now we need to add them. For each contact + * type, add the contact type to the types lists accordingly. + * Note that we don't have to record any cap values, since the + * extraction routine dissolves contacts into their residue + * types when computing the parasitics. But, the type must be + * in the type lists or contact tiles will be passed over during + * searches. + */ + + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + TileTypeBitMask rmask; + PlaneMask pMask; + TileType q; + + if (!DBIsContact(s)) continue; + + pMask = DBTypePlaneMaskTbl[s]; + for (p = 0; p < DBNumPlanes; p++) + { + if (PlaneMaskHasPlane(pMask, p)) + { + TTMaskSetType(&style->exts_overlapTypes[p], s); + TTMaskSetType(&style->exts_sideTypes[p], s); + } + } + DBFullResidueMask(s, &rmask); + for (r = TT_TECHDEPBASE; r < DBNumUserLayers; r++) + { + if (!TTMaskHasType(&rmask, r)) continue; + + TTMaskSetMask(&style->exts_sideEdges[s], &style->exts_sideEdges[r]); + + for (q = TT_TECHDEPBASE; q < DBNumUserLayers; q++) + { + if (TTMaskHasType(&style->exts_overlapOtherTypes[q], r)) + TTMaskSetType(&style->exts_overlapOtherTypes[q], s); + + for (t = TT_TECHDEPBASE; t < DBNumUserLayers; t++) + if (TTMaskHasType(&style->exts_overlapShieldTypes[q][t], r) + && !TTMaskHasType(&rmask, q) + && !TTMaskHasType(&rmask, t)) + TTMaskSetType(&style->exts_overlapShieldTypes[q][t], s); + + /* For sideOverlap, t is "outtypes" and includes space, so we */ + /* must count from TT_SPACE, not TT_TECHDEPBASE. */ + + for (t = TT_SPACE; t < DBNumUserLayers; t++) + if (TTMaskHasType(&style->exts_sideOverlapOtherTypes[q][t], r)) + TTMaskSetType(&style->exts_sideOverlapOtherTypes[q][t], s); + } + } + } + + /* + * Consistency check: + * If a type R shields S from T, make sure that R is listed as + * being in the list of overlapped types for S, even if there + * was no overlap capacitance explicitly specified for this + * pair of types in an "overlap" line. This guarantees that + * R will shield S from substrate even if there is no capacitance + * associated with the overlap. + */ + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + if (style->exts_overlapShieldPlanes[s][t] == 0) + continue; + for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) + { + if (!TTMaskHasType(&style->exts_overlapShieldTypes[s][t], r)) + continue; + p1 = DBPlane(s); + style->exts_overlapPlanes |= PlaneNumToMaskBit(p1); + style->exts_overlapOtherPlanes[s] + |= PlaneNumToMaskBit(DBPlane(r)); + TTMaskSetType(&style->exts_overlapTypes[p1], s); + TTMaskSetType(&style->exts_overlapOtherTypes[s], r); + } + } + + /* Finally, for all coupling type masks, remove those types */ + /* that have been declared not to participate in extraction. */ + + for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) + { + TTMaskAndMask(&style->exts_overlapOtherTypes[s], &style->exts_activeTypes); + TTMaskAndMask(&style->exts_perimCapMask[s], &style->exts_activeTypes); + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + TTMaskAndMask(&style->exts_overlapShieldTypes[s][t], + &style->exts_activeTypes); + TTMaskAndMask(&style->exts_sideOverlapOtherTypes[s][t], + &style->exts_activeTypes); + TTMaskAndMask(&style->exts_sideCoupleOtherEdges[s][t], + &style->exts_activeTypes); + } + } + + for (p = 0; p < DBNumPlanes; p++) + { + TTMaskAndMask(&style->exts_overlapTypes[p], &style->exts_activeTypes); + TTMaskAndMask(&style->exts_sideTypes[p], &style->exts_activeTypes); + } + + if ( style->exts_planeOrderStatus == noPlaneOrder ) + return /* no need to check */ ; + /* Else Check to make sure the plane order is a permutation of the + numbers 0..DBNumPlanes-DBNumPlanes-1 */ + for (p1 = PL_TECHDEPBASE; p1 < DBNumPlanes; p1++) { + indicis[p1] = 0; + } + for (p1 = PL_TECHDEPBASE; p1 < DBNumPlanes; p1++) { + int pn = style->exts_planeOrder[p1]+PL_TECHDEPBASE; + if (pn >= PL_TECHDEPBASE && pn < DBNumPlanes) + indicis[pn]++; + } + conflict = FALSE; + missing = FALSE; + for (p1 = PL_TECHDEPBASE; p1 < DBNumPlanes; p1++) { + if (indicis[p1] > 1) conflict = TRUE ; + if (indicis[p1] < 1) missing = TRUE ; + } + if (!conflict && !missing) /* Everything was ok */ + goto zinit; + + TxError ("\nWarning: Extraction Style %s\n", style -> exts_name); + if (conflict) { + TxError (" Conflicting planeorder for plane(s):\n "); + for (p1 = PL_TECHDEPBASE; p1 < DBNumPlanes; p1++) { + if (indicis[p1] > 1) + TxError (" %s,", DBPlaneLongNameTbl[p1]); + } + TxError("\n"); + } + if (missing) { + TxError (" Missing planeorder for plane(s):\n "); + for (p1 = PL_TECHDEPBASE; p1 < DBNumPlanes; p1++) { + if (indicis[p1] < 1) + TxError (" %s,", DBPlaneLongNameTbl[p1]); + } + TxError("\n"); + } + TxError(" Magic will use the default planeorder for this style:\n "); + for (p1 = PL_TECHDEPBASE; p1 < DBNumPlanes; p1++) { + style->exts_planeOrder[p1] = p1 - PL_TECHDEPBASE ; + TxError(" %s=%d,",DBPlaneLongNameTbl[p1], style->exts_planeOrder[p1]); + } + TxError("\n"); + + /* Now that we have a plane ordering, we can apply default height */ + /* and thickness values for those layers. */ + +zinit: + for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) + { + if (style->exts_thick[r] == 0) + style->exts_thick[r] = 0.05; + if (style->exts_height[r] == 0) + style->exts_height[r] = 0.1 * style->exts_planeOrder[DBPlane(r)]; + } + + /* If global variable "doConvert" is TRUE, then we convert from */ + /* microns to lambda and microns^2 to lambda^2. */ + + if (doConvert) + { + /* exts_unitsPerLambda is in centimicrons, so divide by */ + /* 100 to get microns. */ + + CapValue scalefac = (CapValue)style->exts_unitsPerLambda / 100.0; + CapValue sqfac = scalefac * scalefac; + + for (r = 0; r < DBNumTypes; r++) + { + style->exts_areaCap[r] *= sqfac; + style->exts_transSDCap[r] *= sqfac; + style->exts_transGateCap[r] *= sqfac; + + for (s = 0; s < DBNumTypes; s++) + { + EdgeCap *ec; + + style->exts_perimCap[r][s] *= scalefac; + style->exts_overlapCap[r][s] *= sqfac; + for (ec = style->exts_sideOverlapCap[r][s]; ec != NULL; + ec = ec->ec_next) + ec->ec_cap *= scalefac; + + // Note that because sidewall caps are referred to + // a specific distance, the value (run / separation) + // is unscaled, so the capacitance does not get + // modified by the scalefactor. However, the lambda + // reference for sidewall cap is 2 lambda, so if + // the reference is to be interpreted as 1 micron, + // the value needs to be divided by 2 (the factor of + // 2 is made up by the fact that the sidewall is + // independently accumulated on each plate of the + // capacitor) + + for (ec = style->exts_sideCoupleCap[r][s]; ec != NULL; + ec = ec->ec_next) + ec->ec_cap *= 0.5; + } + } + + /* side halo and step size are also in microns */ + + style->exts_sideCoupleHalo = (int)(((CapValue)style->exts_sideCoupleHalo + / scalefac) + 0.5); + style->exts_stepSize = (int)(((CapValue)style->exts_stepSize + / scalefac) + 0.5); + } + + /* Avoid setting stepSize to zero, or extraction will hang! */ + if (style->exts_stepSize <= 0) + { + TxError("Warning: zero step size! Resetting to default.\n"); + style->exts_stepSize = 100; /* Revert to default */ + } + + /* We had multiplied sideCoupleHalo by 1000 to accommodate a */ + /* floating-point value in microns, whether or not doConvert was */ + /* needed, so normalize it back to lambda units. */ + + style->exts_sideCoupleHalo /= 1000; +} + +/* + * ---------------------------------------------------------------------------- + * ExtTechScale -- + * + * Scale all extraction values appropriately when rescaling the grid. + * ---------------------------------------------------------------------------- + */ + +void +ExtTechScale(scalen, scaled) + int scalen; /* Scale numerator */ + int scaled; /* Scale denominator */ +{ + ExtStyle *style = ExtCurStyle; + EdgeCap *ec; + int i, j; + float sqn, sqd; + + if (style == NULL) return; + + sqn = (float)(scalen * scalen); + sqd = (float)(scaled * scaled); + + style->exts_unitsPerLambda = style->exts_unitsPerLambda * (float)scalen + / (float)scaled; + DBScaleValue(&style->exts_sideCoupleHalo, scaled, scalen); + DBScaleValue(&style->exts_stepSize, scaled, scalen); + + for (i = 0; i < DBNumTypes; i++) + { + style->exts_areaCap[i] *= sqn; + style->exts_areaCap[i] /= sqd; + + style->exts_transSDCap[i] *= sqn; + style->exts_transSDCap[i] /= sqd; + style->exts_transGateCap[i] *= sqn; + style->exts_transGateCap[i] /= sqd; + + style->exts_height[i] *= scaled; + style->exts_height[i] /= scalen; + style->exts_thick[i] *= scaled; + style->exts_thick[i] /= scalen; + + for (j = 0; j < DBNumTypes; j++) + { + style->exts_perimCap[i][j] *= scalen; + style->exts_perimCap[i][j] /= scaled; + style->exts_overlapCap[i][j] *= sqn; + style->exts_overlapCap[i][j] /= sqd; /* Typo fixed in 7.2.57 */ + + // Do not scale sidewall cap, for while the value is + // per distance, the distance is referred to a separation + // distance in the same units, so the cap never scales. + + // for (ec = style->exts_sideCoupleCap[i][j]; ec != NULL; + // ec = ec->ec_next) + // { + // ec->ec_cap *= scalen; + // ec->ec_cap /= scaled; + // } + for (ec = style->exts_sideOverlapCap[i][j]; ec != NULL; + ec = ec->ec_next) + { + ec->ec_cap *= scalen; + ec->ec_cap /= scaled; + } + } + } + + return; +} + diff --git a/extract/ExtTest.c b/extract/ExtTest.c new file mode 100644 index 00000000..98f61b06 --- /dev/null +++ b/extract/ExtTest.c @@ -0,0 +1,1431 @@ +/* + * ExtTest.c -- + * + * Circuit extraction. + * Interface for testing. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtTest.c,v 1.3 2009/05/13 15:03:16 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/utils.h" +#include "utils/geometry.h" +#include "utils/styles.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" +#include "commands/commands.h" +#include "textio/textio.h" +#include "textio/txcommands.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" + +int extDebAreaEnum; +int extDebArray; +int extDebHardWay; +int extDebHierCap; +int extDebHierAreaCap; +int extDebLabel; +int extDebNeighbor; +int extDebNoArray; +int extDebNoFeedback; +int extDebNoHard; +int extDebNoSubcell; +int extDebLength; +int extDebPerim; +int extDebResist; +int extDebVisOnly; +int extDebYank; + +/* + * The following are used for selective redisplay while debugging + * the circuit extractor. + */ +Rect extScreenClip; +CellDef *extCellDef; +MagWindow *extDebugWindow; + +/* The width of an edge in pixels when it is displayed */ +int extEdgePixels = 4; + +/* Forward declarations */ +int extShowInter(); +void extShowTech(); +void extDispInit(); +bool extShowRect(); +void extMore(); + +void extShowTrans(char *, TileTypeBitMask *, FILE *); +void extShowMask(TileTypeBitMask *, FILE *); +void extShowPlanes(PlaneMask, FILE *); +void extShowConnect(char *, TileTypeBitMask *, FILE *); + + +/* + * ---------------------------------------------------------------------------- + * + * ExtractTest -- + * + * Command interface for testing circuit extraction. + * Usage: + * *extract + * + * Results: + * None. + * + * Side effects: + * Extracts the current cell, writing a file named + * currentcellname.ext. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtractTest(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + extern long extSubtreeTotalArea; + extern long extSubtreeInteractionArea; + extern long extSubtreeClippedArea; + static Plane *interPlane = (Plane *) NULL; + static long areaTotal = 0, areaInteraction = 0, areaClipped = 0; + long a1, a2; + int n, halo, bloat; + CellUse *selectedCell; + Rect editArea; + char *addr, *name; + FILE *f; + typedef enum { CLRDEBUG, CLRLENGTH, DRIVER, DUMP, INTERACTIONS, + INTERCOUNT, EXTPARENTS, RECEIVER, SETDEBUG, SHOWDEBUG, + SHOWPARENTS, SHOWTECH, STATS, STEP, TIME } cmdType; + static struct + { + char *cmd_name; + cmdType cmd_val; + } cmds[] = { + "clrdebug", CLRDEBUG, + "clrlength", CLRLENGTH, + "driver", DRIVER, + "dump", DUMP, + "interactions", INTERACTIONS, + "intercount", INTERCOUNT, + "parents", EXTPARENTS, + "receiver", RECEIVER, + "setdebug", SETDEBUG, + "showdebug", SHOWDEBUG, + "showparents", SHOWPARENTS, + "showtech", SHOWTECH, + "stats", STATS, + "step", STEP, + "times", TIME, + 0 + }; + + if (cmd->tx_argc == 1) + { + selectedCell = CmdGetSelectedCell((Transform *) NULL); + if (selectedCell == NULL) + { + TxError("No cell selected\n"); + return; + } + + extDispInit(selectedCell->cu_def, w); + ExtCell(selectedCell->cu_def, selectedCell->cu_def->cd_name, FALSE); + return; + } + + n = LookupStruct(cmd->tx_argv[1], (LookupTable *) cmds, sizeof cmds[0]); + if (n < 0) + { + TxError("Unrecognized subcommand: %s\n", cmd->tx_argv[1]); + TxError("Valid subcommands:"); + for (n = 0; cmds[n].cmd_name; n++) + TxError(" %s", cmds[n].cmd_name); + TxError("\n"); + return; + } + + switch (cmds[n].cmd_val) + { + case STATS: + areaTotal += extSubtreeTotalArea; + areaInteraction += extSubtreeInteractionArea; + areaClipped += extSubtreeClippedArea; + TxPrintf("Extraction statistics (recent/total):\n"); + TxPrintf("Total area of all cells = %ld / %ld\n", + extSubtreeTotalArea, areaTotal); + a1 = extSubtreeTotalArea; + a2 = areaTotal; + if (a1 == 0) a1 = 1; + if (a2 == 0) a2 = 1; + TxPrintf( + "Total interaction area processed = %ld (%.2f%%) / %ld (%.2f%%)\n", + extSubtreeInteractionArea, + ((double) extSubtreeInteractionArea) / ((double) a1) * 100.0, + ((double) areaInteraction) / ((double) a2) * 100.0); + TxPrintf( + "Clipped interaction area= %ld (%.2f%%) / %ld (%.2f%%)\n", + extSubtreeClippedArea, + ((double) extSubtreeClippedArea) / ((double) a1) * 100.0, + ((double) areaClipped) / ((double) a2) * 100.0); + extSubtreeTotalArea = 0; + extSubtreeInteractionArea = 0; + extSubtreeClippedArea = 0; + break; + case INTERACTIONS: + if (interPlane == NULL) + interPlane = DBNewPlane((ClientData) TT_SPACE); + halo = 1, bloat = 0; + if (cmd->tx_argc > 2) halo = atoi(cmd->tx_argv[2]) + 1; + if (cmd->tx_argc > 3) bloat = atoi(cmd->tx_argv[3]); + ExtFindInteractions(EditCellUse->cu_def, halo, bloat, interPlane); + (void) DBSrPaintArea((Tile *) NULL, interPlane, &TiPlaneRect, + &DBAllButSpaceBits, extShowInter, (ClientData) NULL); + DBClearPaintPlane(interPlane); + break; + case INTERCOUNT: + f = stdout; + halo = 1; + if (cmd->tx_argc > 2) + halo = atoi(cmd->tx_argv[2]); + if (cmd->tx_argc > 3) + { + f = fopen(cmd->tx_argv[3], "w"); + if (f == NULL) + { + perror(cmd->tx_argv[3]); + break; + } + } + ExtInterCount((CellUse *) w->w_surfaceID, halo, f); + if (f != stdout) + (void) fclose(f); + break; + case TIME: + f = stdout; + if (cmd->tx_argc > 2) + { + f = fopen(cmd->tx_argv[2], "w"); + if (f == NULL) + { + perror(cmd->tx_argv[2]); + break; + } + } + ExtTimes((CellUse *) w->w_surfaceID, f); + if (f != stdout) + (void) fclose(f); + break; + case EXTPARENTS: + if (ToolGetEditBox(&editArea)) + ExtParentArea(EditCellUse, &editArea, TRUE); + break; + + case DUMP: + if (cmd->tx_argc != 2 && cmd->tx_argc != 3) + { + TxError("Usage: *extract dump filename|-\n"); + break; + } + ExtDumpCaps(cmd->tx_argc > 2 ? cmd->tx_argv[2] : "-"); + break; + + case DRIVER: + if (cmd->tx_argc != 3) + { + TxError("Usage: *extract driver terminalname\n"); + break; + } + ExtSetDriver(cmd->tx_argv[2]); + break; + case RECEIVER: + if (cmd->tx_argc != 3) + { + TxError("Usage: *extract receiver terminalname\n"); + break; + } + ExtSetReceiver(cmd->tx_argv[2]); + break; + case CLRLENGTH: + TxPrintf("Clearing driver/receiver length list\n"); + ExtLengthClear(); + break; + + case SHOWPARENTS: + if (ToolGetEditBox(&editArea)) + ExtParentArea(EditCellUse, &editArea, FALSE); + break; + case SETDEBUG: + DebugSet(extDebugID, cmd->tx_argc - 2, &cmd->tx_argv[2], TRUE); + break; + case CLRDEBUG: + DebugSet(extDebugID, cmd->tx_argc - 2, &cmd->tx_argv[2], FALSE); + break; + + case SHOWDEBUG: + DebugShow(extDebugID); + break; + case SHOWTECH: + extShowTech(cmd->tx_argc > 2 ? cmd->tx_argv[2] : "-"); + break; + case STEP: + TxPrintf("Current interaction step size is %d\n", + ExtCurStyle->exts_stepSize); + if (cmd->tx_argc > 2) + { + ExtCurStyle->exts_stepSize = atoi(cmd->tx_argv[2]); + TxPrintf("New interaction step size is %d\n", + ExtCurStyle->exts_stepSize); + } + break; + } +} + +int +extShowInter(tile) + Tile *tile; +{ + Rect r; + + TiToRect(tile, &r); + DBWFeedbackAdd(&r, "interaction", EditCellUse->cu_def, + 1, STYLE_MEDIUMHIGHLIGHTS); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extShowTech -- + * + * Display the technology-specific tables maintained for circuit + * extraction in a human-readable format. Intended mainly for + * debugging technology files. If the argument 'name' is "-", + * the output is to the standard output; otherwise, it is to + * the file whose name is 'name'. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +extShowTech(name) + char *name; +{ + FILE *out; + TileType t, s; + int p; + EdgeCap *e; + + if (strcmp(name, "-") == 0) + out = stdout; + else + { + out = fopen(name, "w"); + if (out == NULL) + { + perror(name); + return; + } + } + + extShowTrans("Transistor", &ExtCurStyle->exts_transMask, out); + + fprintf(out, "\nNode resistance and capacitance:\n"); + fprintf(out, "type R-ohm/sq AreaC-ff/l**2\n"); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + fprintf(out, "%-8.8s %8d %9lf\n", + DBTypeShortName(t), + ExtCurStyle->exts_resistByResistClass[ + ExtCurStyle->exts_typeToResistClass[t]], + ExtCurStyle->exts_areaCap[t]); + + fprintf(out, "\nTypes contributing to resistive perimeter:\n"); + fprintf(out, "type R-type boundary types\n"); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + fprintf(out, "%-8.8s ", DBTypeShortName(t)); + fprintf(out, "%7d ", ExtCurStyle->exts_typeToResistClass[t]); + extShowMask(&ExtCurStyle->exts_typesResistChanged[t], out); + fprintf(out, "\n"); + } + + fprintf(out, "\nSidewall capacitance:\n"); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + for (s = 0; s < DBNumTypes; s++) + if (ExtCurStyle->exts_perimCap[t][s] != (CapValue) 0) + fprintf(out, " %-8.8s %-8.8s %8lf\n", + DBTypeShortName(t), DBTypeShortName(s), + ExtCurStyle->exts_perimCap[t][s]); + + fprintf(out, "\nInternodal overlap capacitance:\n"); + fprintf(out, "\n (by plane)\n"); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + { + if (PlaneMaskHasPlane(ExtCurStyle->exts_overlapPlanes , p)) + { + fprintf(out, " %-10.10s: types=", DBPlaneShortName(p)); + extShowMask(&ExtCurStyle->exts_overlapTypes [p], out); + fprintf(out, "\n"); + } + } + fprintf(out, "\n (by type)\n"); + for (t = 0; t < DBNumTypes; t++) + if (!TTMaskIsZero(&ExtCurStyle->exts_overlapOtherTypes[t])) + { + fprintf(out, " %-10.10s: planes=", DBTypeShortName(t)); + extShowPlanes(ExtCurStyle->exts_overlapOtherPlanes[t], out); + fprintf(out, "\n overlapped types="); + extShowMask(&ExtCurStyle->exts_overlapOtherTypes[t], out); + fprintf(out, "\n"); + for (s = 0; s < DBNumTypes; s++) + if (ExtCurStyle->exts_overlapCap[t][s] != (CapValue) 0) + fprintf(out, " %-10.10s: %8lf\n", + DBTypeShortName(s), ExtCurStyle->exts_overlapCap[t][s]); + } + + fprintf(out, "\nSidewall-coupling/sidewall-overlap capacitance:\n"); + fprintf(out, "\n (by plane)\n"); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + { + if (PlaneMaskHasPlane(ExtCurStyle->exts_sidePlanes, p)) + { + fprintf(out, " %-10.10s: ", DBPlaneShortName(p)); + extShowMask(&ExtCurStyle->exts_sideTypes[p], out); + fprintf(out, "\n"); + } + } + fprintf(out, "\n (by type)\n"); + for (s = 0; s < DBNumTypes; s++) + if (!TTMaskIsZero(&ExtCurStyle->exts_sideEdges[s])) + { + fprintf(out, " %-10.10s: ", DBTypeShortName(s)); + extShowMask(&ExtCurStyle->exts_sideEdges[s], out); + fprintf(out, "\n"); + for (t = 0; t < DBNumTypes; t++) + { + if (!TTMaskIsZero(&ExtCurStyle->exts_sideCoupleOtherEdges[s][t])) + { + fprintf(out, " edge mask="); + extShowMask(&ExtCurStyle->exts_sideCoupleOtherEdges[s][t], out); + fprintf(out, "\n"); + } + if (!TTMaskIsZero(&ExtCurStyle->exts_sideOverlapOtherTypes[s][t])) + { + fprintf(out, " overlap mask="); + extShowMask(&ExtCurStyle->exts_sideOverlapOtherTypes[s][t], + out); + fprintf(out, "\n"); + } + if (e = ExtCurStyle->exts_sideCoupleCap[s][t]) + for ( ; e; e = e->ec_next) + { + fprintf(out, " COUPLE: "); + extShowMask(&e->ec_near, out); + fprintf(out, " || "); + extShowMask(&e->ec_far, out); + fprintf(out, ": %lf\n", e->ec_cap); + } + if (e = ExtCurStyle->exts_sideOverlapCap[s][t]) + for ( ; e; e = e->ec_next) + { + fprintf(out, " OVERLAP: "); + extShowMask(&e->ec_near, out); + fprintf(out, ": %lf\n", e->ec_cap); + } + } + } + + fprintf(out, "\n\nSidewall coupling halo = %d\n", ExtCurStyle->exts_sideCoupleHalo ); + + extShowConnect("\nNode connectivity", ExtCurStyle->exts_nodeConn, out); + extShowConnect("\nResistive region connectivity", ExtCurStyle->exts_resistConn, out); + extShowConnect("\nTransistor connectivity", ExtCurStyle->exts_transConn, out); + + if (out != stdout) + (void) fclose(out); +} + +void +extShowTrans(name, mask, out) + char *name; + TileTypeBitMask *mask; + FILE *out; +{ + TileType t; + + fprintf(out, "%s types: ", name); + extShowMask(mask, out); + fprintf(out, "\n"); + + for (t = 0; t < DBNumTypes; t++) + if (TTMaskHasType(mask, t)) + { + fprintf(out, " %-8.8s %d terminals: ", + DBTypeShortName(t), ExtCurStyle->exts_transSDCount[t]); + extShowMask(&ExtCurStyle->exts_transSDTypes[t][0], out); + fprintf(out, "\n\tcap (gate-sd/gate-ch) = %lf/%lf\n", + ExtCurStyle->exts_transSDCap[t], + ExtCurStyle->exts_transGateCap[t]); + } +} + +void +extShowConnect(hdr, connectsTo, out) + char *hdr; + TileTypeBitMask *connectsTo; + FILE *out; +{ + TileType t; + + fprintf(out, "%s\n", hdr); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (!TTMaskEqual(&connectsTo[t], &DBZeroTypeBits)) + { + fprintf(out, " %-8.8s: ", DBTypeShortName(t)); + extShowMask(&connectsTo[t], out); + fprintf(out, "\n"); + } +} + +void +extShowMask(m, out) + TileTypeBitMask *m; + FILE *out; +{ + TileType t; + bool first = TRUE; + + for (t = 0; t < DBNumTypes; t++) + if (TTMaskHasType(m, t)) + { + if (!first) + fprintf(out, ","); + first = FALSE; + fprintf(out, "%s", DBTypeShortName(t)); + } +} + +void +extShowPlanes(m, out) + PlaneMask m; + FILE *out; +{ + int pNum; + bool first = TRUE; + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (PlaneMaskHasPlane(m, pNum)) + { + if (!first) + fprintf(out, ","); + first = FALSE; + fprintf(out, "%s", DBPlaneShortName(pNum)); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extDispInit -- + * + * Initialize the screen information to be used during + * extraction debugging. + * + * Results: + * None. + * + * Side effects: + * Initializes extDebugWindow, extScreenClip, and extCellDef. + * + * ---------------------------------------------------------------------------- + */ + +void +extDispInit(def, w) + CellDef *def; + MagWindow *w; +{ + extDebugWindow = w; + extCellDef = def; + extScreenClip = w->w_screenArea; + GeoClip(&extScreenClip, &GrScreenRect); +} + +/* + * ---------------------------------------------------------------------------- + * + * extShowEdge -- + * + * Display the edge described by the Boundary 'bp' on the display, + * with text string 's' on the text terminal. Prompt with '--next--' + * to allow a primitive sort of 'more' processing. + * + * Results: + * None. + * + * Side effects: + * Updates the display. + * + * ---------------------------------------------------------------------------- + */ + +void +extShowEdge(s, bp) + char *s; + Boundary *bp; +{ + Rect extScreenRect, edgeRect; + int style = STYLE_PURPLE1; + + edgeRect = bp->b_segment; + WindSurfaceToScreen(extDebugWindow, &edgeRect, &extScreenRect); + if (extScreenRect.r_ybot == extScreenRect.r_ytop) + { + extScreenRect.r_ybot -= extEdgePixels/2; + extScreenRect.r_ytop += extEdgePixels - extEdgePixels/2; + } + else /* extScreenRect.r_xtop == extScreenRect.r_xbot */ + { + extScreenRect.r_xbot -= extEdgePixels/2; + extScreenRect.r_xtop += extEdgePixels - extEdgePixels/2; + } + + if (DebugIsSet(extDebugID, extDebVisOnly)) + { + Rect r; + + r = extScreenRect; + GeoClip(&r, &extScreenClip); + if (r.r_xtop <= r.r_xbot || r.r_ytop <= r.r_ybot) + return; + } + + TxPrintf("%s: ", s); + GrLock(extDebugWindow, TRUE); + GrClipBox(&extScreenRect, style); + GrUnlock(extDebugWindow); + (void) GrFlush(); + extMore(); + GrLock(extDebugWindow, TRUE); + GrClipBox(&extScreenRect, STYLE_ORANGE1); + GrUnlock(extDebugWindow); + (void) GrFlush(); +} + +/* + * ---------------------------------------------------------------------------- + * + * extShowTile -- + * + * Display the tile 'tp' on the display by highlighting it. Also show + * the text string 's' on the terminal. Prompt with '--next--' to allow + * a primitive sort of more processing. + * + * Results: + * None. + * + * Side effects: + * Updates the display. + * + * ---------------------------------------------------------------------------- + */ + +void +extShowTile(tile, s, style_index) + Tile *tile; + char *s; + int style_index; +{ + Rect tileRect; + static int styles[] = { STYLE_PALEHIGHLIGHTS, STYLE_DOTTEDHIGHLIGHTS }; + + TiToRect(tile, &tileRect); + if (!extShowRect(&tileRect, styles[style_index])) + return; + + TxPrintf("%s: ", s); + extMore(); + (void) extShowRect(&tileRect, STYLE_ERASEHIGHLIGHTS); +} + +bool +extShowRect(r, style) + Rect *r; + int style; +{ + Rect extScreenRect; + + WindSurfaceToScreen(extDebugWindow, r, &extScreenRect); + if (DebugIsSet(extDebugID, extDebVisOnly)) + { + Rect rclip; + + rclip = extScreenRect; + GeoClip(&rclip, &extScreenClip); + if (rclip.r_xtop <= rclip.r_xbot || rclip.r_ytop <= rclip.r_ybot) + return (FALSE); + } + + GrLock(extDebugWindow, TRUE); + GrClipBox(&extScreenRect, style); + GrUnlock(extDebugWindow); + (void) GrFlush(); + return (TRUE); +} + +void +extMore() +{ + char line[100]; + + TxPrintf("--next--"); (void) fflush(stdout); + (void) TxGetLine(line, sizeof line); +} + +void +extNewYank(name, puse, pdef) + char *name; + CellUse **puse; + CellDef **pdef; +{ + DBNewYank(name, puse, pdef); +} + +/* + * ---------------------------------------------------------------------------- + * Dump parasitic capacitance extraction information to a file + * ---------------------------------------------------------------------------- + */ + +void +ExtDumpCapsToFile(f) + FILE *f; +{ + TileType t, s, r; + EdgeCap *e; + int p, found; + + fprintf(f, "Parasitic extraction capacitance values\n"); + + fprintf(f, "\n1) Area caps\n"); + for (t = 0; t < DBNumTypes; t++) + { + if (ExtCurStyle->exts_areaCap[t] > 0.0) + fprintf(f, "%s %3.3f\n", + DBTypeLongNameTbl[t], + ExtCurStyle->exts_areaCap[t]); + } + + fprintf(f, "\n2) Perimeter caps\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + if (ExtCurStyle->exts_perimCap[t][s] > 0.0) + fprintf(f, "%s | %s %3.3f\n", + DBTypeLongNameTbl[t], + DBTypeLongNameTbl[s], + ExtCurStyle->exts_perimCap[t][s]); + } + } + + fprintf(f, "\n3) Overlap caps\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + if (ExtCurStyle->exts_overlapCap[t][s] > 0.0) + fprintf(f, "%s | %s %3.3f\n", + DBTypeLongNameTbl[t], + DBTypeLongNameTbl[s], + ExtCurStyle->exts_overlapCap[t][s]); + } + } + + fprintf(f, "\n4) Side coupling caps\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + for (e = ExtCurStyle->exts_sideCoupleCap[t][s]; e; e = e->ec_next) { + fprintf(f, "%s | %s: %3.3f\n", + DBTypeLongNameTbl[t], + DBTypeLongNameTbl[s], + e->ec_cap); + fprintf(f, " near: "); + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&e->ec_near, r)) + fprintf(f, " %s", DBTypeLongNameTbl[r]); + fprintf(f, "\n far: "); + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&e->ec_far, r)) + fprintf(f, " %s", DBTypeLongNameTbl[r]); + fprintf(f, "\n planes: "); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(e->ec_pmask, p)) + fprintf(f, " %s", DBPlaneLongNameTbl[p]); + fprintf(f, "\n"); + } + } + } + + fprintf(f, "\n5) Side overlap caps\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + for (e = ExtCurStyle->exts_sideOverlapCap[t][s]; e; e = e->ec_next) { + fprintf(f, "%s | %s: %3.3f\n", + DBTypeLongNameTbl[t], + DBTypeLongNameTbl[s], + e->ec_cap); + fprintf(f, " near: "); + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&e->ec_near, r)) + fprintf(f, " %s", DBTypeLongNameTbl[r]); + fprintf(f, "\n far: "); + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&e->ec_far, r)) + fprintf(f, " %s", DBTypeLongNameTbl[r]); + fprintf(f, "\n planes: "); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(e->ec_pmask, p)) + fprintf(f, " %s", DBPlaneLongNameTbl[p]); + fprintf(f, "\n"); + } + } + } + + fprintf(f, "\n6) (Check) Perimeter cap mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + found = 0; + for (s = 0; s < DBNumTypes; s++) + if (TTMaskHasType(&ExtCurStyle->exts_perimCapMask[t], s)) + { + if (found == 0) + { + fprintf(f, " %s: ", DBTypeLongNameTbl[t]); + found = 1; + } + fprintf(f, " %s", DBTypeLongNameTbl[s]); + } + if (found != 0) fprintf(f, "\n"); + } + + fprintf(f, "\n7) (Check) Overlap plane mask\n"); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_overlapPlanes, p)) + fprintf(f, " %s", DBPlaneLongNameTbl[p]); + fprintf(f, "\n"); + + fprintf(f, "\n8) (Check) Overlap types mask\n"); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + { + found = 0; + for (s = 0; s < DBNumTypes; s++) + if (TTMaskHasType(&ExtCurStyle->exts_overlapTypes[p], s)) + { + if (found == 0) + { + found = 1; + fprintf(f, " %s: ", DBPlaneLongNameTbl[p]); + } + fprintf(f, " %s", DBTypeLongNameTbl[s]); + } + if (found != 0) fprintf(f, "\n"); + } + + fprintf(f, "\n9) (Check) Overlap other types mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + found = 0; + for (s = 0; s < DBNumTypes; s++) + if (TTMaskHasType(&ExtCurStyle->exts_overlapOtherTypes[t], s)) + { + if (found == 0) + { + fprintf(f, " %s: ", DBTypeLongNameTbl[t]); + found = 1; + } + fprintf(f, " %s", DBTypeLongNameTbl[s]); + } + if (found != 0) fprintf(f, "\n"); + } + + fprintf(f, "\n10) (Check) Overlap other planes mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + found = 0; + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_overlapOtherPlanes[t], p)) + { + if (found == 0) + { + fprintf(f, " %s: ", DBTypeLongNameTbl[t]); + found = 1; + } + fprintf(f, " %s", DBPlaneLongNameTbl[p]); + } + if (found != 0) fprintf(f, "\n"); + } + + fprintf(f, "\n11) (Check) Overlap shield types mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&ExtCurStyle->exts_overlapShieldTypes[t][s], r)) + { + if (found == 0) + { + fprintf(f, " %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + fprintf(f, " %s", DBTypeLongNameTbl[r]); + } + if (found != 0) fprintf(f, "\n"); + } + } + + fprintf(f, "\n12) (Check) Overlap shield planes mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_overlapShieldPlanes[t][s], p)) + { + if (found == 0) + { + fprintf(f, " %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + fprintf(f, " %s", DBPlaneLongNameTbl[p]); + } + if (found != 0) fprintf(f, "\n"); + } + } + + fprintf(f, "\n13) (Check) Side couple other edges mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&ExtCurStyle->exts_sideCoupleOtherEdges[t][s], r)) + { + if (found == 0) + { + fprintf(f, " %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + fprintf(f, " %s", DBTypeLongNameTbl[r]); + } + if (found != 0) fprintf(f, "\n"); + } + } + + fprintf(f, "\n14) (Check) Side overlap other planes mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_sideOverlapOtherPlanes[t][s], p)) + { + if (found == 0) + { + fprintf(f, " %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + fprintf(f, " %s", DBPlaneLongNameTbl[p]); + } + if (found != 0) fprintf(f, "\n"); + } + } + + fprintf(f, "\n15) (Check) Side overlap other types mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&ExtCurStyle->exts_sideOverlapOtherTypes[t][s], r)) + { + if (found == 0) + { + fprintf(f, " %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + fprintf(f, " %s", DBTypeLongNameTbl[r]); + } + if (found != 0) fprintf(f, "\n"); + } + } + + fprintf(f, "\n16) (Check) Side overlap shield planes mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_sideOverlapShieldPlanes[t][s], p)) + { + if (found == 0) + { + fprintf(f, " %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + fprintf(f, " %s", DBPlaneLongNameTbl[p]); + } + if (found != 0) fprintf(f, "\n"); + } + } + + fprintf(f, "\n17) (Check) Side planes mask\n"); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_sidePlanes, p)) + fprintf(f, " %s", DBPlaneLongNameTbl[p]); + fprintf(f, "\n"); + + fprintf(f, "\n18) (Check) Side types mask\n"); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + { + found = 0; + for (s = 0; s < DBNumTypes; s++) + if (TTMaskHasType(&ExtCurStyle->exts_sideTypes[p], s)) + { + if (found == 0) + { + fprintf(f, " %s: ", DBPlaneLongNameTbl[p]); + found = 1; + } + fprintf(f, " %s", DBTypeLongNameTbl[s]); + } + if (found != 0) fprintf(f, "\n"); + } + + fprintf(f, "\n19) (Check) Side edges mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + found = 0; + for (s = 0; s < DBNumTypes; s++) + if (TTMaskHasType(&ExtCurStyle->exts_sideTypes[t], s)) + { + if (found == 0) + { + fprintf(f, " %s: ", DBTypeLongNameTbl[t]); + found = 1; + } + fprintf(f, " %s", DBTypeLongNameTbl[s]); + } + if (found != 0) fprintf(f, "\n"); + } +} + +/* + * ---------------------------------------------------------------------------- + * ExtDumpCaps --- + * Debugging tool. Dump information about all parasitics + * ---------------------------------------------------------------------------- + */ + +void +ExtDumpCaps(filename) + char *filename; +{ + TileType t, s, r; + EdgeCap *e; + int p, found; + + if (strcmp(filename, "-")) + { + FILE *f; + f = fopen(filename, "w"); + if (f == NULL) + { + TxError("Cannot open file %s for writing\n", filename); + return; + } + ExtDumpCapsToFile(f); + return; + } + + TxPrintf("Parasitic extraction capacitance values\n"); + + TxPrintf("\n1) Area caps\n"); + for (t = 0; t < DBNumTypes; t++) + { + if (ExtCurStyle->exts_areaCap[t] > 0.0) + TxPrintf("%s %3.3f\n", + DBTypeLongNameTbl[t], + ExtCurStyle->exts_areaCap[t]); + } + + TxPrintf("\n2) Perimeter caps\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + if (ExtCurStyle->exts_perimCap[t][s] > 0.0) + TxPrintf("%s | %s %3.3f\n", + DBTypeLongNameTbl[t], + DBTypeLongNameTbl[s], + ExtCurStyle->exts_perimCap[t][s]); + } + } + + TxPrintf("\n3) Overlap caps\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + if (ExtCurStyle->exts_overlapCap[t][s] > 0.0) + TxPrintf("%s | %s %3.3f\n", + DBTypeLongNameTbl[t], + DBTypeLongNameTbl[s], + ExtCurStyle->exts_overlapCap[t][s]); + } + } + + TxPrintf("\n4) Side coupling caps\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + for (e = ExtCurStyle->exts_sideCoupleCap[t][s]; e; e = e->ec_next) { + TxPrintf("%s | %s: %3.3f\n", + DBTypeLongNameTbl[t], + DBTypeLongNameTbl[s], + e->ec_cap); + TxPrintf(" near: "); + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&e->ec_near, r)) + TxPrintf(" %s", DBTypeLongNameTbl[r]); + TxPrintf("\n far: "); + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&e->ec_far, r)) + TxPrintf(" %s", DBTypeLongNameTbl[r]); + TxPrintf("\n planes: "); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(e->ec_pmask, p)) + TxPrintf(" %s", DBPlaneLongNameTbl[p]); + TxPrintf("\n"); + } + } + } + + TxPrintf("\n5) Side overlap caps\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + for (e = ExtCurStyle->exts_sideOverlapCap[t][s]; e; e = e->ec_next) { + TxPrintf("%s | %s: %3.3f\n", + DBTypeLongNameTbl[t], + DBTypeLongNameTbl[s], + e->ec_cap); + TxPrintf(" near: "); + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&e->ec_near, r)) + TxPrintf(" %s", DBTypeLongNameTbl[r]); + TxPrintf("\n far: "); + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&e->ec_far, r)) + TxPrintf(" %s", DBTypeLongNameTbl[r]); + TxPrintf("\n planes: "); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(e->ec_pmask, p)) + TxPrintf(" %s", DBPlaneLongNameTbl[p]); + TxPrintf("\n"); + } + } + } + + TxPrintf("\n6) (Check) Perimeter cap mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + found = 0; + for (s = 0; s < DBNumTypes; s++) + if (TTMaskHasType(&ExtCurStyle->exts_perimCapMask[t], s)) + { + if (found == 0) + { + TxPrintf(" %s: ", DBTypeLongNameTbl[t]); + found = 1; + } + TxPrintf(" %s", DBTypeLongNameTbl[s]); + } + if (found != 0) TxPrintf("\n"); + } + + TxPrintf("\n7) (Check) Overlap plane mask\n"); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_overlapPlanes, p)) + TxPrintf(" %s", DBPlaneLongNameTbl[p]); + TxPrintf("\n"); + + TxPrintf("\n8) (Check) Overlap types mask\n"); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + { + found = 0; + for (s = 0; s < DBNumTypes; s++) + if (TTMaskHasType(&ExtCurStyle->exts_overlapTypes[p], s)) + { + if (found == 0) + { + found = 1; + TxPrintf(" %s: ", DBPlaneLongNameTbl[p]); + } + TxPrintf(" %s", DBTypeLongNameTbl[s]); + } + if (found != 0) TxPrintf("\n"); + } + + TxPrintf("\n9) (Check) Overlap other types mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + found = 0; + for (s = 0; s < DBNumTypes; s++) + if (TTMaskHasType(&ExtCurStyle->exts_overlapOtherTypes[t], s)) + { + if (found == 0) + { + TxPrintf(" %s: ", DBTypeLongNameTbl[t]); + found = 1; + } + TxPrintf(" %s", DBTypeLongNameTbl[s]); + } + if (found != 0) TxPrintf("\n"); + } + + TxPrintf("\n10) (Check) Overlap other planes mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + found = 0; + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_overlapOtherPlanes[t], p)) + { + if (found == 0) + { + TxPrintf(" %s: ", DBTypeLongNameTbl[t]); + found = 1; + } + TxPrintf(" %s", DBPlaneLongNameTbl[p]); + } + if (found != 0) TxPrintf("\n"); + } + + TxPrintf("\n11) (Check) Overlap shield types mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&ExtCurStyle->exts_overlapShieldTypes[t][s], r)) + { + if (found == 0) + { + TxPrintf(" %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + TxPrintf(" %s", DBTypeLongNameTbl[r]); + } + if (found != 0) TxPrintf("\n"); + } + } + + TxPrintf("\n12) (Check) Overlap shield planes mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_overlapShieldPlanes[t][s], p)) + { + if (found == 0) + { + TxPrintf(" %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + TxPrintf(" %s", DBPlaneLongNameTbl[p]); + } + if (found != 0) TxPrintf("\n"); + } + } + + TxPrintf("\n13) (Check) Side couple other edges mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&ExtCurStyle->exts_sideCoupleOtherEdges[t][s], r)) + { + if (found == 0) + { + TxPrintf(" %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + TxPrintf(" %s", DBTypeLongNameTbl[r]); + } + if (found != 0) TxPrintf("\n"); + } + } + + TxPrintf("\n14) (Check) Side overlap other planes mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_sideOverlapOtherPlanes[t][s], p)) + { + if (found == 0) + { + TxPrintf(" %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + TxPrintf(" %s", DBPlaneLongNameTbl[p]); + } + if (found != 0) TxPrintf("\n"); + } + } + + TxPrintf("\n15) (Check) Side overlap other types mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (r = 0; r < DBNumTypes; r++) + if (TTMaskHasType(&ExtCurStyle->exts_sideOverlapOtherTypes[t][s], r)) + { + if (found == 0) + { + TxPrintf(" %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + TxPrintf(" %s", DBTypeLongNameTbl[r]); + } + if (found != 0) TxPrintf("\n"); + } + } + + TxPrintf("\n16) (Check) Side overlap shield planes mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + for (s = 0; s < DBNumTypes; s++) + { + found = 0; + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_sideOverlapShieldPlanes[t][s], p)) + { + if (found == 0) + { + TxPrintf(" %s | %s: ", + DBTypeLongNameTbl[t], DBTypeLongNameTbl[s]); + found = 1; + } + TxPrintf(" %s", DBPlaneLongNameTbl[p]); + } + if (found != 0) TxPrintf("\n"); + } + } + + TxPrintf("\n17) (Check) Side planes mask\n"); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (PlaneMaskHasPlane(ExtCurStyle->exts_sidePlanes, p)) + TxPrintf(" %s", DBPlaneLongNameTbl[p]); + TxPrintf("\n"); + + TxPrintf("\n18) (Check) Side types mask\n"); + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + { + found = 0; + for (s = 0; s < DBNumTypes; s++) + if (TTMaskHasType(&ExtCurStyle->exts_sideTypes[p], s)) + { + if (found == 0) + { + TxPrintf(" %s: ", DBPlaneLongNameTbl[p]); + found = 1; + } + TxPrintf(" %s", DBTypeLongNameTbl[s]); + } + if (found != 0) TxPrintf("\n"); + } + + TxPrintf("\n19) (Check) Side edges mask\n"); + for (t = 0; t < DBNumTypes; t++) + { + found = 0; + for (s = 0; s < DBNumTypes; s++) + if (TTMaskHasType(&ExtCurStyle->exts_sideTypes[t], s)) + { + if (found == 0) + { + TxPrintf(" %s: ", DBTypeLongNameTbl[t]); + found = 1; + } + TxPrintf(" %s", DBTypeLongNameTbl[s]); + } + if (found != 0) TxPrintf("\n"); + } +} diff --git a/extract/ExtTimes.c b/extract/ExtTimes.c new file mode 100644 index 00000000..3e2e0cbc --- /dev/null +++ b/extract/ExtTimes.c @@ -0,0 +1,1112 @@ +/* + * ExtTimes.c -- + * + * Circuit extraction timing. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtTimes.c,v 1.2 2009/05/13 15:03:16 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#ifdef SYSV +#include +#include +#endif +#include /* for sqrt() function */ + +#include "utils/magic.h" +#include "utils/utils.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" + +/* + * One of the following structures gets allocated for each cell. + * It holds the statistics we accumulate while extracting that cell. + */ +struct cellStats +{ + CellDef *cs_def; /* Which cell */ + struct timeval cs_tpaint; /* Paint-only extraction time */ + struct timeval cs_tcell; /* Extract just this cell */ + struct timeval cs_thier; /* Extract complete tree */ + struct timeval cs_tincr; /* Incremental extraction time */ + int cs_fets; /* Transistor count in this cell */ + int cs_rects; /* Non-space tile count in this cell */ + int cs_hfets; /* Hierarchical transistor count */ + int cs_hrects; /* Hierarchical tile count */ + int cs_ffets; /* Total flat transistor count */ + int cs_frects; /* Total flat tile count */ + long cs_area; /* Total area of cell */ + long cs_interarea; /* Interaction areas sum */ + long cs_cliparea; /* Interaction area, counting each + * overlap of interaction areas only + * once instead of once for each + * interaction area. + */ +}; + +/* Hash table of all the above structs, keyed by CellDef */ +HashTable cellStatsTable; + +/* + * Cumulative statistics + */ +struct cumStats +{ + double cums_min; /* Smallest value */ + double cums_max; /* Largest value */ + double cums_sum; /* Sum of values */ + double cums_sos; /* Sum of squares */ + int cums_n; /* Number values */ +}; + +struct cumStats cumFetsPerSecPaint; +struct cumStats cumRectsPerSecPaint; +struct cumStats cumFetsPerSecFlat; +struct cumStats cumRectsPerSecFlat; +struct cumStats cumFetsPerSecHier; +struct cumStats cumRectsPerSecHier; +struct cumStats cumIncrTime; +struct cumStats cumPercentClipped; +struct cumStats cumPercentInteraction; +struct cumStats cumTotalArea, cumInteractArea, cumClippedArea; + +FILE *extDevNull = NULL; + +/* Forward declarations */ + +struct cellStats *extGetStats(); +void extTimesCellFunc(); +void extTimesIncrFunc(); +void extTimesSummaryFunc(); +void extTimesParentFunc(); +void extTimeProc(); +void extCumInit(); +void extCumOutput(); +void extCumAdd(); +void extPaintOnly(CellDef *); +void extHierCell(CellDef *); +int extCountTiles(); + +extern int extDefInitFunc(); + + +/* + * ---------------------------------------------------------------------------- + * + * ExtTimes -- + * + * Time the extractor. + * All cells in the tree rooted at 'rootUse' are extracted. + * We report the following times for each cell (seconds of CPU + * time, accurate to 10 milliseconds). + * + * Time to extract just its paint. + * Time to extract it completely. + * Time to perform incremental re-extraction if just this cell changed. + * + * In addition, we report: + * + * Fets/second paint extraction speed + * Fets/second cell extraction speed + * Fets/second hierarchical extraction speed + * Rects/second paint extraction speed + * Rects/second cell extraction speed + * Rects/second hierarchical extraction speed + * + * Also for each cell, we report the number of transistors, number + * of rectangles, and rectangles per transistor. + * + * In addition, we report the following cumulative information, as + * means, standard deviation, min, and max: + * + * Fets/second flat extraction speed + * Fets/second complete extraction speed + * Rects/second flat extraction speed + * Rects/second complete extraction speed + * Incremental extraction time after changing one cell. + * + * Results: + * None. + * + * Side effects: + * Writes to the file 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +ExtTimes(rootUse, f) + CellUse *rootUse; + FILE *f; +{ + double clip, inter; + HashSearch hs; + HashEntry *he; + + /* Make sure this cell is read in */ + DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox); + + /* Initialize cumulative statistics */ + extCumInit(&cumFetsPerSecPaint); + extCumInit(&cumRectsPerSecPaint); + extCumInit(&cumFetsPerSecFlat); + extCumInit(&cumRectsPerSecFlat); + extCumInit(&cumFetsPerSecHier); + extCumInit(&cumRectsPerSecHier); + extCumInit(&cumIncrTime); + extCumInit(&cumPercentClipped); + extCumInit(&cumPercentInteraction); + extCumInit(&cumTotalArea); + extCumInit(&cumInteractArea); + extCumInit(&cumClippedArea); + + /* Open to /dev/null */ + extDevNull = fopen("/dev/null", "w"); + if (extDevNull == NULL) + { + perror("/dev/null"); + return; + } + + /* Mark all defs as unvisited */ + (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); + + /* Recursively visit all defs in the tree and store in hash table */ + HashInit(&cellStatsTable, 128, 1); + (void) extTimesInitFunc(rootUse); + + /* + * Now visit every cell in the hash table and compute + * its individual statistics. + */ + TxPrintf("Computing individual cell statistics:\n"); TxFlush(); + HashStartSearch(&hs); + while (he = HashNext(&cellStatsTable, &hs)) + extTimesCellFunc((struct cellStats *) HashGetValue(he)); + + /* + * Now visit every cell in the hash table and compute + * its incremental time (ancestors) and hierarchical + * time (children). + */ + TxPrintf("Computing hierarchical and incremental statistics:\n"); TxFlush(); + HashStartSearch(&hs); + while (he = HashNext(&cellStatsTable, &hs)) + extTimesIncrFunc((struct cellStats *) HashGetValue(he)); + + /* + * Compute the summary statistics and output everything. + * Free each entry in the table as we go. + */ + TxPrintf("Computing summary statistics:\n"); TxFlush(); + HashStartSearch(&hs); + while (he = HashNext(&cellStatsTable, &hs)) + { + extTimesSummaryFunc((struct cellStats *) HashGetValue(he), f); + freeMagic((char *) HashGetValue(he)); + } + + /* Output the summary statistics */ + fprintf(f, "\n\nSummary statistics:\n\n"); + fprintf(f, "%s %8s %8s %8s %8s\n", + " ", "min", "max", "mean", "std.dev"); + extCumOutput("fets/sec paint ", &cumFetsPerSecPaint, f); + extCumOutput("fets/sec hier ", &cumFetsPerSecHier, f); + extCumOutput("fets/sec flat ", &cumFetsPerSecFlat, f); + extCumOutput("rects/sec paint", &cumRectsPerSecPaint, f); + extCumOutput("rects/sec hier ", &cumRectsPerSecHier, f); + extCumOutput("rects/sec flat ", &cumRectsPerSecFlat, f); + extCumOutput("tot incr time ", &cumIncrTime, f); + extCumOutput("% cell clipped ", &cumPercentClipped, f); + extCumOutput("% cell interact", &cumPercentInteraction, f); + + /* Fix up average value to be weighted */ + clip = inter = 0.0; + if (cumTotalArea.cums_sum > 0) + { + clip = 100.0 * cumClippedArea.cums_sum / cumTotalArea.cums_sum; + inter = 100.0 * cumInteractArea.cums_sum / cumTotalArea.cums_sum; + } + fprintf(f, "Mean %% clipped area = %.2f\n", clip); + fprintf(f, "Mean %% interaction area = %.2f\n", inter); + + /* Free the hash table */ + HashKill(&cellStatsTable); + + (void) fclose(extDevNull); +} + +/* + * ---------------------------------------------------------------------------- + * + * extTimesInitFunc -- + * + * Called to add the cellStats struct for use->cu_def to the hash table + * cellStatsTable if it is not already present, and to initialize this + * structure. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +extTimesInitFunc(use) + CellUse *use; +{ + CellDef *def = use->cu_def; + struct cellStats *cs; + HashEntry *he; + + he = HashFind(&cellStatsTable, (char *) def); + if (HashGetValue(he)) + return (0); + + /* Not yet visited: add it to the hash table */ + cs = (struct cellStats *) mallocMagic(sizeof (struct cellStats)); + cs->cs_def = def; + cs->cs_tpaint.tv_sec = cs->cs_tpaint.tv_usec = 0; + cs->cs_tcell.tv_sec = cs->cs_tcell.tv_usec = 0; + cs->cs_thier.tv_sec = cs->cs_thier.tv_usec = 0; + cs->cs_tincr.tv_sec = cs->cs_tincr.tv_usec = 0; + cs->cs_fets = cs->cs_rects = 0; + cs->cs_ffets = cs->cs_frects = 0; + cs->cs_hfets = cs->cs_hrects = 0; + cs->cs_area = cs->cs_interarea = cs->cs_cliparea = 0; + HashSetValue(he, (ClientData) cs); + + /* Visit our children */ + (void) DBCellEnum(def, extTimesInitFunc, (ClientData) 0); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extTimesCellFunc -- + * + * Called for each cellStats structure in the hash table, we extract + * the paint of cs->cs_def and then both the paint and subcells, timing + * both. Also count the number of fets in this cell and the total number + * of tiles. Store this information in: + * + * cs->cs_tpaint Time to extract paint only + * cs->cs_tcell Time to extract paint and subcells + * cs->cs_fets Number of fets + * cs->cs_rects Number of non-space tiles + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extTimesCellFunc(cs) + struct cellStats *cs; +{ + extern long extSubtreeTotalArea; + extern long extSubtreeInteractionArea; + extern long extSubtreeClippedArea; + TransRegion *transList, *tl; + CellDef *def = cs->cs_def; + int pNum; + + TxPrintf("Processing %s\n", def->cd_name); TxFlush(); + + /* Count the number of transistors */ + transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect, + &ExtCurStyle->exts_transMask, ExtCurStyle->exts_transConn, + extUnInit, extTransFirst, extTransEach); + ExtResetTiles(def, extUnInit); + for (tl = transList; tl; tl = tl->treg_next) + cs->cs_fets++; + ExtFreeLabRegions((LabRegion *) transList); + + /* Count the number of tiles */ + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &TiPlaneRect, + &DBAllButSpaceBits, extCountTiles, (ClientData) cs); + + /* Measure the flat extraction time */ + extTimeProc(extPaintOnly, def, &cs->cs_tpaint); + + /* Measure the total extraction time */ + extSubtreeTotalArea = 0; + extSubtreeInteractionArea = 0; + extSubtreeClippedArea = 0; + extTimeProc(extHierCell, def, &cs->cs_tcell); + cs->cs_area = extSubtreeTotalArea; + cs->cs_interarea = extSubtreeInteractionArea; + cs->cs_cliparea = extSubtreeClippedArea; +} + +/* + * extCountTiles -- + * + * Count the number of tiles in a cell. + * Called via DBSrPaintArea by extTimesCellFunc() above. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Increments cs->cs_rects. + */ + +int +extCountTiles(tile, cs) + Tile *tile; /* UNUSED */ + struct cellStats *cs; +{ + cs->cs_rects++; + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extTimesIncrFunc -- + * + * All cells have been visited by extTimesCellFunc above. This procedure + * accumulates the hierarchical information from both above and below + * in the tree. The cs_tcell times for all ancestors, plus this cell, + * are summed into cs->cs_tincr. The cs_tcell times for all children, + * counting each child once, are summed into cs->cs_thier. The cs_fets + * and cs_rects for all children, also counting each child once, are + * summed into cs_hfets and cs_hrects. Finally, the cs_fets and cs_rects + * for all children, counting each child as many times as it appears, + * are summed into cs_ffets and cs_frects. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extTimesIncrFunc(cs) + struct cellStats *cs; +{ + /* + * Visit all of our parents recursively. + * This sums the incremental times. + */ + extTimesParentFunc(cs->cs_def, cs); + + /* Reset all defs */ + (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); + + /* + * Visit all of our children recursively, visiting + * each child only once. This sums the number of fets + * and rectangles for cs_hfets and cs_hrects. + */ + (void) extTimesHierFunc(cs->cs_def, cs); + + /* Reset all defs */ + (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); + + /* + * Visit all of our children recursively, visiting each + * child as many times as it appears. This sums the + * number of fets and rectangles as cs_ffets and cs_frects. + */ + (void) extTimesFlatFunc(cs->cs_def, cs); +} + +/* + * ---------------------------------------------------------------------------- + * + * extTimesSummaryFunc -- + * + * Write the statistics contained in the cellStats structure 'cs' + * out to the FILE 'f'. Add them to the summary structures being + * maintained (cumFetsPerSecPaint, etc). + * + * Results: + * None. + * + * Side effects: + * Writes to the FILE f. + * + * ---------------------------------------------------------------------------- + */ + +void +extTimesSummaryFunc(cs, f) + struct cellStats *cs; + FILE *f; +{ + double tpaint, tcell, thier, tincr; + double fetspaint, rectspaint; + double fetshier, rectshier; + double fetsflat, rectsflat; + double pctinter, pctclip; + + pctinter = pctclip = 0.0; + if (cs->cs_area > 0) + { + pctinter = ((double)cs->cs_interarea) / ((double)cs->cs_area) * 100.0; + pctclip = ((double)cs->cs_cliparea) / ((double)cs->cs_area) * 100.0; + } + + tpaint = cs->cs_tpaint.tv_usec; + tpaint = (tpaint / 1000000.) + cs->cs_tpaint.tv_sec; + + tcell = cs->cs_tcell.tv_usec; + tcell = (tcell / 1000000.) + cs->cs_tcell.tv_sec; + + thier = cs->cs_thier.tv_usec; + thier = (thier / 1000000.) + cs->cs_thier.tv_sec; + + tincr = cs->cs_tincr.tv_usec; + tincr = (tincr / 1000000.) + cs->cs_tincr.tv_sec; + + fetspaint = fetsflat = fetshier = 0.0; + rectspaint = rectsflat = rectshier = 0.0; + + if (tpaint > 0.01) + { + fetspaint = cs->cs_fets / tpaint; + rectspaint = cs->cs_rects / tpaint; + } + + if (thier > 0.01) + { + fetshier = cs->cs_hfets / thier; + rectshier = cs->cs_hrects / thier; + fetsflat = cs->cs_ffets / thier; + rectsflat = cs->cs_frects / thier; + } + + /* Cell name */ + fprintf(f, "\n%8s %8s %s\n", "", "", cs->cs_def->cd_name); + + /* Sizes */ + fprintf(f, "%8d %8d (paint) fets rects\n", + cs->cs_fets, cs->cs_rects); + fprintf(f, "%8d %8d (hier) fets rects\n", + cs->cs_hfets, cs->cs_hrects); + fprintf(f, "%8d %8d (flat) fets rects\n", + cs->cs_ffets, cs->cs_frects); + + /* Times */ + fprintf(f, "%8.2f %8.2f Tpaint, Tcell\n", tpaint, tcell); + fprintf(f, "%8.2f %8.2f Thier, Tincr\n", thier, tincr); + + /* Speeds */ + fprintf(f, "%8.2f %8.2f (paint) fets/sec rects/sec\n", + fetspaint, rectspaint); + fprintf(f, "%8.2f %8.2f (hier) fets/sec rects/sec\n", + fetshier, rectshier); + fprintf(f, "%8.2f %8.2f (flat) fets/sec rects/sec\n", + fetsflat, rectsflat); + + /* Fraction of area in subtree processing */ + fprintf(f, "%8.2f %8.2f clip %% inter %%\n", + pctclip, pctinter); + + /* Accumulate statistics */ + if (cs->cs_fets > 0) extCumAdd(&cumFetsPerSecPaint, fetspaint); + if (cs->cs_rects > 0) extCumAdd(&cumRectsPerSecPaint, rectspaint); + if (cs->cs_hfets > 0) extCumAdd(&cumFetsPerSecHier, fetshier); + if (cs->cs_hrects > 0) extCumAdd(&cumRectsPerSecHier, rectshier); + if (cs->cs_ffets > 0) extCumAdd(&cumFetsPerSecFlat, fetsflat); + if (cs->cs_frects > 0) extCumAdd(&cumRectsPerSecFlat, rectsflat); + if (pctclip > 0.0) extCumAdd(&cumPercentClipped, pctclip); + if (pctinter > 0.0) extCumAdd(&cumPercentInteraction, pctinter); + extCumAdd(&cumTotalArea, (double) cs->cs_area); + extCumAdd(&cumInteractArea, (double) cs->cs_interarea); + extCumAdd(&cumClippedArea, (double) cs->cs_cliparea); + extCumAdd(&cumIncrTime, tincr); +} + +/* + * ---------------------------------------------------------------------------- + * + * extTimesParentFunc -- + * + * Function to visit all the parents of 'def' and add their + * times to that of 'cs'. We only add the times if the def + * being visited is unmarked, ie, its cd_client field is 0. + * After adding the times for a def, we mark it by setting + * its cd_client field to 1. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extTimesParentFunc(def, cs) + CellDef *def; + struct cellStats *cs; +{ + struct cellStats *csForDef; + CellUse *parent; + + if (def->cd_client) + return; + + /* Mark this def as visited */ + def->cd_client = (ClientData) 1; + + /* Find its statistics in the table */ + if ((csForDef = extGetStats(def)) == NULL) + return; + + /* Add the time */ + cs->cs_tincr.tv_sec += csForDef->cs_tcell.tv_sec; + cs->cs_tincr.tv_usec += csForDef->cs_tcell.tv_usec; + if (cs->cs_tincr.tv_usec > 1000000) + { + cs->cs_tincr.tv_usec -= 1000000; + cs->cs_tincr.tv_sec += 1; + } + + /* Visit all our parents */ + for (parent = def->cd_parents; parent; parent = parent->cu_nextuse) + if (parent->cu_parent) + extTimesParentFunc(parent->cu_parent, cs); +} + +/* + * ---------------------------------------------------------------------------- + * + * extTimesHierFunc -- + * + * Function to visit all the children of 'def' and add their + * times to that of 'cs'. We only add the times if the def + * being visited is unmarked, ie, its cd_client field is 0. + * After adding the times for a def, we mark it by setting + * its cd_client field to 1. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +extTimesHierFunc(def, cs) + CellDef *def; + struct cellStats *cs; +{ + int extTimesHierUse(); + struct cellStats *csForDef; + + if (def->cd_client) + return (0); + + /* Mark this def as visited */ + def->cd_client = (ClientData) 1; + + /* Find its statistics in the table */ + if ((csForDef = extGetStats(def)) == NULL) + return (0); + + /* Add the time */ + cs->cs_thier.tv_sec += csForDef->cs_tcell.tv_sec; + cs->cs_thier.tv_usec += csForDef->cs_tcell.tv_usec; + if (cs->cs_thier.tv_usec > 1000000) + { + cs->cs_thier.tv_usec -= 1000000; + cs->cs_thier.tv_sec += 1; + } + + /* Add the fets and rectangles */ + cs->cs_hfets += csForDef->cs_fets; + cs->cs_hrects += csForDef->cs_rects; + + /* Visit our children */ + (void) DBCellEnum(def, extTimesHierUse, (ClientData) cs); + return (0); +} + +int +extTimesHierUse(use, cs) + CellUse *use; + struct cellStats *cs; +{ + return (extTimesHierFunc(use->cu_def, cs)); +} + +/* + * ---------------------------------------------------------------------------- + * + * extTimesFlatFunc -- + * + * Function to visit all the children of 'def' and add their + * fet and rect counts to those of 'cs'. This is a fully + * instantiated count, rather than a drawn count, so we count + * each cell as many times as it appears in an array or as + * a subcell. + * + * Results: + * Returns 0 always. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +extTimesFlatFunc(def, cs) + CellDef *def; + struct cellStats *cs; +{ + struct cellStats *csForDef; + int extTimesFlatUse(); + + /* Find this cell's statistics in the table */ + if ((csForDef = extGetStats(def)) == NULL) + return (0); + + /* Add the fets and rectangles */ + cs->cs_ffets += csForDef->cs_fets; + cs->cs_frects += csForDef->cs_rects; + + /* Visit our children */ + (void) DBCellEnum(def, extTimesFlatUse, (ClientData) cs); + return (0); +} + +int +extTimesFlatUse(use, cs) + CellUse *use; + struct cellStats *cs; +{ + struct cellStats dummyCS; + int nx, ny, nel; + + /* Compute statistics for this cell and its children */ + bzero((char *) &dummyCS, sizeof dummyCS); + (void) extTimesFlatFunc(use->cu_def, &dummyCS); + + /* Scale by number of elements in this array */ + if (use->cu_xlo < use->cu_xhi) nx = use->cu_xhi - use->cu_xlo + 1; + else nx = use->cu_xlo - use->cu_xhi + 1; + if (use->cu_ylo < use->cu_yhi) ny = use->cu_yhi - use->cu_ylo + 1; + else ny = use->cu_ylo - use->cu_yhi + 1; + + nel = nx * ny; + + /* Fets and rects */ + cs->cs_ffets += dummyCS.cs_ffets * nel; + cs->cs_frects += dummyCS.cs_frects * nel; + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extTimeProc -- + * + * Time a procedure applied to the CellDef 'def', storing the time + * in the timeval pointed to by 'tv'. The procedure should be of + * the form: + * + * (*proc)(def) + * CellDef *def; + * { + * } + * + * Results: + * None. + * + * Side effects: + * See above. + * + * Algorithm: + * If (*proc)() takes less than a second to run, we run it ten + * times to get a better time estimate, then divide by ten. + * + * ---------------------------------------------------------------------------- + */ + +void +extTimeProc(proc, def, tv) + int (*proc)(); + CellDef *def; + struct timeval *tv; +{ + int secs, usecs, i; + +#ifdef SYSV + tv->tv_sec = 0; + tv->tv_usec = 0; +#else + extern int getrusage(); + struct rusage r1, r2; + + (void) getrusage(RUSAGE_SELF, &r1); + (*proc)(def); + (void) getrusage(RUSAGE_SELF, &r2); + + tv->tv_sec = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec; + tv->tv_usec = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec; + if (tv->tv_usec < 0) + { + tv->tv_usec += 1000000; + tv->tv_sec -= 1; + } + + if (tv->tv_sec < 1) + { + (void) getrusage(RUSAGE_SELF, &r1); + for (i = 0; i < 10; i++) + (*proc)(def); + (void) getrusage(RUSAGE_SELF, &r2); + secs = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec; + usecs = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec; + usecs = (usecs + (secs * 1000000)) / 10; + tv->tv_sec = usecs / 1000000; + tv->tv_usec = usecs % 1000000; + } +#endif +} + +/* + * ---------------------------------------------------------------------------- + * + * extPaintOnly -- + * + * Called via extTimeProc() above. Extract just the paint in a cell. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +extPaintOnly(def) + CellDef *def; +{ + NodeRegion *reg; + + reg = extBasic(def, extDevNull); + if (reg) ExtFreeLabRegions((LabRegion *) reg); + ExtResetTiles(def, extUnInit); +} + +/* + * ---------------------------------------------------------------------------- + * + * extHierCell -- + * + * Called via extTimeProc() above. Extract a cell normally, but + * send the extracted output to /dev/null. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +extHierCell(def) + CellDef *def; +{ + extCellFile(def, extDevNull, FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * extCumInit -- + * + * Initialize a cumulative statistics structure. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extCumInit(cum) + struct cumStats *cum; +{ + cum->cums_min = (double) INFINITY; + cum->cums_max = (double) MINFINITY; + cum->cums_sum = 0.0; + cum->cums_sos = 0.0; + cum->cums_n = 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * extCumOutput -- + * + * Output a cumulative statistics structure. + * + * Results: + * None. + * + * Side effects: + * Writes to the FILE 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +extCumOutput(str, cum, f) + char *str; /* Prefix string */ + struct cumStats *cum; + FILE *f; +{ + double mean, var; + + mean = var = 0.0; + if (cum->cums_n != 0) + { + mean = cum->cums_sum / (double) cum->cums_n; + var = (cum->cums_sos / (double) cum->cums_n) - (mean * mean); + } + + fprintf(f, "%s", str); + if (cum->cums_min < INFINITY) + fprintf(f, " %8.2f", cum->cums_min); + else + fprintf(f, " "); + if (cum->cums_max > MINFINITY) + fprintf(f, " %8.2f", cum->cums_max); + else + fprintf(f, " "); + fprintf(f, " %8.2f %8.2f\n", mean, sqrt(var)); +} + +/* + * ---------------------------------------------------------------------------- + * + * extCumAdd -- + * + * Add the value v to the cumulative statistics structure, + * updating the statistics. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extCumAdd(cum, v) + struct cumStats *cum; + double v; +{ + if (v < cum->cums_min) cum->cums_min = v; + if (v > cum->cums_max) cum->cums_max = v; + cum->cums_sum += v; + cum->cums_sos += v*v; + cum->cums_n++; +} + +/* + * ---------------------------------------------------------------------------- + * + * extGetStats -- + * + * Return the cellStats record for the CellDef 'def'. + * + * Results: + * See above. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +struct cellStats * +extGetStats(def) + CellDef *def; +{ + HashEntry *he; + + he = HashLookOnly(&cellStatsTable, (char *) def); + if (he == (HashEntry *) NULL) + return ((struct cellStats *) NULL); + + return ((struct cellStats *) HashGetValue(he)); +} + +/* + * ---------------------------------------------------------------------------- + * + * ExtInterCount -- + * + * Find all interaction areas in an entire design, and count + * the fraction of the total area that is really an interaction + * area. Report this for each cell in the design, and as a + * fraction of the total area. + * + * Results: + * None. + * + * Side effects: + * Writes to the FILE 'f'. + * + * ---------------------------------------------------------------------------- + */ + +int extInterCountHalo; +CellDef *extInterCountDef; + +void +ExtInterCount(rootUse, halo, f) + CellUse *rootUse; + int halo; + FILE *f; +{ + double inter; + + /* Make sure this cell is read in */ + DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox); + + /* Initialize cumulative statistics */ + extCumInit(&cumPercentInteraction); + extCumInit(&cumTotalArea); + extCumInit(&cumInteractArea); + + /* Mark all defs as unvisited */ + (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); + + /* + * Recursively visit all defs in the tree and compute + * their interaction area. + */ + extInterCountHalo = halo; + (void) extInterAreaFunc(rootUse, f); + + /* Mark all defs as unvisited */ + (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0); + + /* Output the summary statistics */ + fprintf(f, "\n\nSummary statistics:\n\n"); + fprintf(f, "%s %8s %8s %8s %8s\n", + " ", "min", "max", "mean", "std.dev"); + extCumOutput("% cell interact", &cumPercentInteraction, f); + + /* Fix up average value to be weighted */ + inter = 0.0; + if (cumTotalArea.cums_sum > 0) + inter = 100.0 * cumInteractArea.cums_sum / cumTotalArea.cums_sum; + fprintf(f, "Mean %% interaction area = %.2f\n", inter); +} + +int +extInterAreaFunc(use, f) + CellUse *use; + FILE *f; +{ + static Plane *interPlane = (Plane *) NULL; + CellDef *def = use->cu_def; + int extInterCountFunc(); + int area, interarea; + double pctinter; + + if (interPlane == NULL) + interPlane = DBNewPlane((ClientData) TT_SPACE); + + /* Skip if already visited */ + if (def->cd_client) + return (0); + + /* Mark as visited */ + def->cd_client = (ClientData) 1; + + /* Compute interaction area */ + extInterCountDef = def; + ExtFindInteractions(def, extInterCountHalo, 0, interPlane); + interarea = 0; + (void) DBSrPaintArea((Tile *) NULL, interPlane, &TiPlaneRect, + &DBAllButSpaceBits, extInterCountFunc, (ClientData) &interarea); + DBClearPaintPlane(interPlane); + area = (def->cd_bbox.r_xtop - def->cd_bbox.r_xbot) + * (def->cd_bbox.r_ytop - def->cd_bbox.r_ybot); + + pctinter = 0.0; + if (area > 0) + pctinter = ((double) interarea) / ((double) area) * 100.0; + if (pctinter > 0.0) extCumAdd(&cumPercentInteraction, pctinter); + extCumAdd(&cumTotalArea, (double) area); + extCumAdd(&cumInteractArea, (double) interarea); + + fprintf(f, "%7.2f%% %s\n", pctinter, def->cd_name); + + /* Visit our children */ + (void) DBCellEnum(def, extInterAreaFunc, (ClientData) f); + return (0); +} + +int +extInterCountFunc(tile, pArea) + Tile *tile; + int *pArea; +{ + Rect r; + + TITORECT(tile, &r); + GEOCLIP(&r, &extInterCountDef->cd_bbox); + *pArea += (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot); + return (0); +} diff --git a/extract/ExtUnique.c b/extract/ExtUnique.c new file mode 100644 index 00000000..150306ea --- /dev/null +++ b/extract/ExtUnique.c @@ -0,0 +1,270 @@ +/* + * ExtUnique.c -- + * + * Circuit extraction. + * Generation of unique names. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtUnique.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/styles.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "utils/stack.h" +#include "utils/utils.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" +#include "utils/undo.h" + +/* + * ---------------------------------------------------------------------------- + * + * extUniqueCell -- + * + * For the cell 'def', look for the same label appearing in two or more + * distinct nodes. For each such label found: + * + * If option is 0, then generate unique names for all + * but one of the nodes by appending a unique numeric + * suffix to the offending labels. + * If option is 1, then generate unique names only if + * the label ends in '#'. Leave feedback for all other + * names that don't end in '!'. + * If option is 2, then generate unique names as for + * option 0 only if the label is not a port. + * + * Results: + * Returns the number of warnings generated. + * + * Side effects: + * May modify the label list of def, and mark def as CDMODIFIED. + * May also leave feedback. + * + * ---------------------------------------------------------------------------- + */ + +int +extUniqueCell(def, option) + CellDef *def; + int option; +{ + LabRegion *lregList, *lastreg, processedLabel; + LabRegion *lp; + LabelList *ll; + HashEntry *he; + HashTable labelHash; + Label *lab; + char *text; + int nwarn; + + nwarn = 0; + HashInit(&labelHash, 32, HT_STRINGKEYS); + TxPrintf("Processing %s\n", def->cd_name); + TxFlush(); + + /* Build up a list of nodes and assign them to tiles */ + lregList = (LabRegion *) ExtFindRegions(def, &TiPlaneRect, + &ExtCurStyle->exts_activeTypes, + ExtCurStyle->exts_nodeConn, + extUnInit, extHierLabFirst, (int (*)()) NULL); + + /* Assign the labels to their associated regions */ + ExtLabelRegions(def, ExtCurStyle->exts_nodeConn, &lregList, &TiPlaneRect); + + /* + * First pass: + * Place all node labels in the cell in the hash table. + */ + for (lab = def->cd_labels; lab; lab = lab->lab_next) + if (extLabType(lab->lab_text, LABTYPE_NAME)) + (void) HashFind(&labelHash, lab->lab_text); + + /* Fix up labels as necessary */ + for (lp = lregList; lp; lp = lp->lreg_next) + { + for (ll = lp->lreg_labels; ll; ll = ll->ll_next) + { + /* + * We might have set ll->ll_label to NULL if we changed it + * to make it unique. Also ignore if the label is not a + * node label type (e.g, it is an attribute). + */ + if (ll->ll_label == (Label *) NULL) + continue; + text = ll->ll_label->lab_text; + if (!extLabType(text, LABTYPE_NAME)) + continue; + + /* + * See if this label has been seen before in this cell. + * If not, remember the current LabRegion as the first + * one seen with this label. If it has been seen, but + * with this same region, or it has already been made + * unique (lastreg == &processedLabel), skip it. + */ + he = HashFind(&labelHash, text); + lastreg = (LabRegion *) HashGetValue(he); + if (lastreg == (LabRegion *) NULL) + { + HashSetValue(he, (ClientData) lp); + continue; + } + if (lastreg != lp && lastreg != &processedLabel) + { + nwarn += extMakeUnique(def, ll, lp, lregList, + &labelHash, option); + HashSetValue(he, (ClientData) &processedLabel); + } + } + } + + HashKill(&labelHash); + ExtFreeLabRegions((LabRegion *) lregList); + ExtResetTiles(def, extUnInit); + if (nwarn) + TxError("%s: %d warnings\n", def->cd_name, nwarn); + return (nwarn); +} + +int +extMakeUnique(def, ll, lreg, lregList, labelHash, option) + CellDef *def; + LabelList *ll; + LabRegion *lreg, *lregList; + HashTable *labelHash; + int option; +{ + static char *badmesg = + "Non-global label \"%s\" attached to more than one unconnected node: %s"; + char *cpend, *text, name[1024], name2[1024], message[1024]; + LabRegion *lp2; + LabelList *ll2; + int nsuffix, nwarn; + Label saveLab, *lab; + Rect r; + + /* + * Make a pass through all labels for all nodes. + * Replace labels as appropriate. This loop + * sets ll_label pointers to NULL whenever it + * changes a label to make it unique. + */ + text = ll->ll_label->lab_text; + if (option == 0) + goto makeUnique; + else if ((option == 2) && !(ll->ll_label->lab_flags & PORT_DIR_MASK)) + goto makeUnique; + + cpend = strchr(text, '\0'); + if (cpend > text) cpend--; + if (*cpend == '#') goto makeUnique; + if (*cpend == '!') return 0; + if ((option == 2) && (ll->ll_label->lab_flags & PORT_DIR_MASK)) return 0; + + /* Generate a warning for each occurrence of this label */ + nwarn = 0; + for (lp2 = lregList; lp2; lp2 = lp2->lreg_next) + { + for (ll2 = lp2->lreg_labels; ll2; ll2 = ll2->ll_next) + { + if (ll2->ll_label && strcmp(ll2->ll_label->lab_text, text) == 0) + { + nwarn++; + r.r_ll = r.r_ur = ll2->ll_label->lab_rect.r_ll; + GEO_EXPAND(&r, 1, &r); + extMakeNodeNumPrint(name, lp2->lreg_pnum, lp2->lreg_ll); + (void) sprintf(message, badmesg, text, name); + DBWFeedbackAdd(&r, message, def, 1, STYLE_MEDIUMHIGHLIGHTS); + } + } + } + return nwarn; + + /* + * For each occurrence of this label in all nodes but lreg, + * replace the label by one with a unique suffix. If the + * label is replaced, we mark it in the label list of the + * node by NULLing-out the ll_label field of the LabelList + * pointing to it. + */ +makeUnique: + nsuffix = 0; + (void) strcpy(name, text); + for (lp2 = lregList; lp2; lp2 = lp2->lreg_next) + { + /* Skip lreg -- its labels will be unchanged */ + if (lp2 == lreg) + continue; + + lab = (Label *) NULL; + for (ll2 = lp2->lreg_labels; ll2; ll2 = ll2->ll_next) + { + if (ll2->ll_label == (Label *) NULL) + continue; + if (strcmp(ll2->ll_label->lab_text, name) != 0) + continue; + + /* + * Keep looking for a name not already in this cell. + * This is a bit conservative, since names that might not have + * been attached to nodes were also added to the table in + * extUniqueCell() above, but we ensure that we don't generate + * a name that might conflict with an existing one (e.g, turning + * Phi into Phi1 when there's already a Phi1 in the cell). + * It's not necessary to add the final name to labelHash + * because nsuffix increases monotonically -- we can never + * generate a label identical to one previously generated. + */ + for (;;) + { + (void) sprintf(name2, "%s_uq%d", name, nsuffix); + if (HashLookOnly(labelHash, name2) == NULL) + break; + nsuffix++; + } + + lab = ll2->ll_label; + saveLab = *lab; + DBEraseLabelsByContent(def, &lab->lab_rect, lab->lab_type, lab->lab_text); + (void) DBPutFontLabel(def, &saveLab.lab_rect, + saveLab.lab_font, saveLab.lab_size, saveLab.lab_rotate, + &saveLab.lab_offset, saveLab.lab_just, name2, + saveLab.lab_type, saveLab.lab_flags); + ll2->ll_label = (Label *) NULL; + } + + /* Bump the suffix if we replaced any labels */ + if (lab) nsuffix++; + } + + return 0; +} diff --git a/extract/ExtYank.c b/extract/ExtYank.c new file mode 100644 index 00000000..b7c3fbdb --- /dev/null +++ b/extract/ExtYank.c @@ -0,0 +1,264 @@ +/* + * ExtYank.c -- + * + * Circuit extraction. + * Hierarchical yanking of paint and labels. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtYank.c,v 1.2 2008/06/01 18:37:42 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "utils/styles.h" +#include "extract/extract.h" +#include "extract/extractInt.h" + +Rect extSubcellArea; /* Area of currently processed subcell, clipped + * to area of interaction, in parent coords. + */ + +/* Forward declarations of filter functions */ +int extHierYankFunc(); +int extHierLabelFunc(); + +/* + * ---------------------------------------------------------------------------- + * + * extHierCopyLabels -- + * + * Copy the label list from sourceDef to targetDef, prepending + * it to any labels already in targetDef. Does not change + * sourceDef's label list. + * + * Labels are copied in order, so the first label on sourceDef's + * list becomes the first label on targetDef's list. THIS IS + * CRITICAL TO INSURE THAT HIERARCHICAL ADJUSTMENTS CAN BE MADE + * PROPERLY; SEE extSubtreeAdjustInit() FOR AN EXPLANATION. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extHierCopyLabels(sourceDef, targetDef) + CellDef *sourceDef, *targetDef; +{ + Label *lab, *newlab, *firstLab, *lastLab; + unsigned n; + + firstLab = lastLab = (Label *) NULL; + for (lab = sourceDef->cd_labels; lab; lab = lab->lab_next) + { + n = sizeof (Label) + strlen(lab->lab_text) - sizeof lab->lab_text + 1; + newlab = (Label *) mallocMagic((unsigned) n); + bcopy((char *) lab, (char *) newlab, (int) n); + + if (lastLab == NULL) lastLab = firstLab = newlab; + else lastLab->lab_next = newlab, lastLab = newlab; + } + + if (lastLab) + { + lastLab->lab_next = targetDef->cd_labels; + targetDef->cd_labels = firstLab; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * extHierFreeLabels -- + * + * Free all the labels from 'def'. + * Leaves the label lis of 'def' pointing to NULL. + * + * This procedure exists mainly so we can trace the freeing + * of labels for debugging. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +extHierFreeLabels(def) + CellDef *def; +{ + Label *lab; + + for (lab = def->cd_labels; lab; lab = lab->lab_next) + freeMagic((char *) lab); + def->cd_labels = (Label *) NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * extHierYankFunc -- + * + * Filter function normally called by DBArraySr to yank hierarchically the + * paint and labels from 'use'. Called for each array element. Also called + * during array extraction. + * + * Expects hy->hy_area to be the area, in use->cu_parent coordinates, + * to be yanked. What we yank will be transformed to parent coordinates + * and placed in the cell hy->hy_target. If hy->hy_prefix is TRUE, we + * will prepend all the labels we yank with the use id of this array + * element; otherwise, the labels have no prefix. + * + * WARNING: + * Only node-name labels are yanked; attributes are not. + * The hierarchical extraction code depends on this fact. + * + * Results: + * Returns 0 to cause DBArraySr to keep going. + * + * Side effects: + * Adds paint and new labels to 'hy->hy_target'. + * + * ---------------------------------------------------------------------------- + */ + +int +extHierYankFunc(use, trans, x, y, hy) + CellUse *use; /* Use that is the root of the subtree being yanked */ + Transform *trans; /* Transform from coordinates of use->cu_def to those + * in use->cu_parent, for the array element (x, y). + */ + int x, y; /* Indices of this array element */ + HierYank *hy; /* See comments in procedure header */ +{ + char labelBuf[4096]; + TerminalPath tpath; + SearchContext scx; + Transform tinv; + + /* + * Want scx.scx_area to be the area in coordinates of use->cu_def + * but hy->hy_area is in coordinates of use->cu_parent. + */ + GEOINVERTTRANS(trans, &tinv); + GEOTRANSRECT(&tinv, hy->hy_area, &scx.scx_area); + GEOCLIP(&scx.scx_area, &use->cu_def->cd_bbox); + + scx.scx_use = use; + scx.scx_trans = *trans; + scx.scx_x = x; + scx.scx_y = y; + + /* Yank the paint */ +// if (!DBIsSubcircuit(use->cu_def)) + DBCellCopyAllPaint(&scx, &DBAllButSpaceBits, 0, hy->hy_target); + + /* Yank the labels */ + tpath.tp_next = tpath.tp_first = labelBuf; + tpath.tp_last = &labelBuf[sizeof labelBuf - 2]; + if (hy->hy_prefix) + { + tpath.tp_next = DBPrintUseId(&scx, labelBuf, sizeof labelBuf - 3, FALSE); + *tpath.tp_next++ = '/'; + } + *tpath.tp_next = '\0'; + (void) DBTreeSrLabels(&scx, &DBAllButSpaceBits, 0, &tpath, TF_LABEL_ATTACH, + extHierLabelFunc, (ClientData) hy->hy_target->cu_def); + + return (0); +} + +int +extHierLabelFunc(scx, label, tpath, targetDef) + SearchContext *scx; + Label *label; + TerminalPath *tpath; + CellDef *targetDef; +{ + char *srcp, *dstp; + Label *newlab; + int len; + + /* Reject if the label falls over space */ + if (label->lab_type == TT_SPACE) + return (0); + + /* Reject if not a node label */ + if (!extLabType(label->lab_text, LABTYPE_NAME)) + return (0); + + /* Determine size of new label with hierarchical name */ + for (srcp = label->lab_text; *srcp++; ) + /* Nothing */; + len = srcp - label->lab_text; + for (srcp = tpath->tp_first; *srcp++; ) + /* Nothing */; + len += srcp - tpath->tp_first + 1; + + /* Allocate new label at correct location */ + newlab = (Label *) mallocMagic((unsigned) (sizeof (Label) + len - 4)); + GeoTransRect(&scx->scx_trans, &label->lab_rect, &newlab->lab_rect); + newlab->lab_just = GeoTransPos(&scx->scx_trans, label->lab_just); + newlab->lab_type = label->lab_type; + newlab->lab_flags = label->lab_flags; + dstp = newlab->lab_text; + for (srcp = tpath->tp_first; *dstp++ = *srcp++; ) + /* Nothing */; + for (--dstp, srcp = label->lab_text; *dstp++ = *srcp++; ) + /* Nothing */; + + newlab->lab_next = targetDef->cd_labels; + targetDef->cd_labels = newlab; + + /* Add paint inside label if this is a subcircuit */ + /* Caveat: If label has zero area, it will be extended by 1 unit */ + +// if (label->lab_flags & PORT_DIR_MASK) +// { +// int pNum; +// +// /* Is extending the label area valid in all cases? */ +// if (newlab->lab_rect.r_xbot == newlab->lab_rect.r_xtop) +// newlab->lab_rect.r_xtop++; +// if (newlab->lab_rect.r_ybot == newlab->lab_rect.r_ytop) +// newlab->lab_rect.r_ytop++; +// +// pNum = DBPlane(newlab->lab_type); +// DBPaintPlane(targetDef->cd_planes[pNum], &newlab->lab_rect, +// DBStdPaintTbl(newlab->lab_type, pNum), +// (PaintUndoInfo *) NULL); +// } + + return (0); +} diff --git a/extract/Makefile b/extract/Makefile new file mode 100644 index 00000000..d9348e3e --- /dev/null +++ b/extract/Makefile @@ -0,0 +1,13 @@ +# +# rcsid "$Header: /usr/cvsroot/magic-8.0/extract/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" +# + +MODULE = extract +MAGICDIR = .. +SRCS = ExtArray.c ExtBasic.c ExtCell.c ExtCouple.c ExtHard.c \ + ExtHier.c ExtLength.c ExtMain.c ExtNghbors.c ExtPerim.c \ + ExtRegion.c ExtSubtree.c ExtTech.c ExtTest.c ExtTimes.c ExtYank.c \ + ExtInter.c ExtUnique.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/extract/extDebugInt.h b/extract/extDebugInt.h new file mode 100644 index 00000000..f7e415ff --- /dev/null +++ b/extract/extDebugInt.h @@ -0,0 +1,40 @@ +/* + * extDebugInt.h -- + * + * Definitions of debugging flags for extraction. + * This is a separate include file so that new debugging flags + * can be added to it without forcing recompilation of the + * entire extract module. + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/extract/extDebugInt.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + */ + +extern int extDebAreaEnum; +extern int extDebArray; +extern int extDebHardWay; +extern int extDebHierCap; +extern int extDebHierAreaCap; +extern int extDebLabel; +extern int extDebNeighbor; +extern int extDebNoArray; +extern int extDebNoFeedback; +extern int extDebNoHard; +extern int extDebNoSubcell; +extern int extDebLength; +extern int extDebPerim; +extern int extDebResist; +extern int extDebVisOnly; +extern int extDebYank; diff --git a/extract/extract.h b/extract/extract.h new file mode 100644 index 00000000..4877491a --- /dev/null +++ b/extract/extract.h @@ -0,0 +1,89 @@ +/* + * extract.h -- + * + * Defines the exported interface to the circuit extractor. + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/extract/extract.h,v 1.3 2009/01/30 03:51:02 tim Exp $" + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + */ + +#ifndef _EXTRACT_H +#define _EXTRACT_H + +#include "utils/magic.h" + +/* Extractor warnings */ +#define EXTWARN_DUP 0x01 /* Warn if two nodes have the same name */ +#define EXTWARN_LABELS 0x02 /* Warn if connecting to unlabelled subcell + * node. + */ +#define EXTWARN_FETS 0x04 /* Warn about badly constructed fets */ + +#define EXTWARN_ALL (EXTWARN_DUP|EXTWARN_LABELS|EXTWARN_FETS) + +extern int ExtDoWarn; /* Bitmask of above */ + +/* Known devices (see ExtTech.c and ExtBasic.c) */ +/* Make sure these match extDevTable in extract/ExtBasic.c and */ +/* also extflat/EFread.c */ + +#define DEV_FET 0 /* FET w/area, perimeter declared */ +#define DEV_MOSFET 1 /* FET w/length, width declared */ +#define DEV_ASYMMETRIC 2 /* Like MOSFET but D,S not swappable */ +#define DEV_BJT 3 /* Bipolar Junction Transistor */ +#define DEV_RES 4 /* Resistor */ +#define DEV_CAP 5 /* Capacitor */ +#define DEV_CAPREV 6 /* Capacitor, terminals reversed */ +#define DEV_DIODE 7 /* Diode */ +#define DEV_PDIODE 8 /* pDiode, same as Diode */ +#define DEV_NDIODE 9 /* nDiode, terminals reversed */ +#define DEV_SUBCKT 10 /* general-purpose subcircuit */ +#define DEV_RSUBCKT 11 /* Resistor-like subcircuit. */ +#define DEV_MSUBCKT 12 /* MOSFET-like subcircuit. */ + +/* Device names for .ext file output (new in version 7.2) */ +/* (defined in extract/ExtBasic.c *and* extflat/EFread.c) */ + +extern char *extDevTable[]; + +/* Extractor options */ +#define EXT_DOADJUST 0x01 /* Extract hierarchical adjustments */ +#define EXT_DOCAPACITANCE 0x02 /* Extract capacitance */ +#define EXT_DOCOUPLING 0x04 /* Extract coupling capacitance */ +#define EXT_DORESISTANCE 0x08 /* Extract resistance */ +#define EXT_DOLENGTH 0x10 /* Extract pathlengths */ +#define EXT_DOALL 0x1f /* ALL OF THE ABOVE */ + +extern int ExtOptions; /* Bitmask of above */ + +extern bool ExtTechLine(); +extern void ExtTechInit(); +extern void ExtTechFinal(); +extern void ExtSetStyle(); +extern void ExtPrintStyle(); +extern void ExtCell(); + +#ifdef MAGIC_WRAPPER +extern bool ExtGetDevInfo(); +extern bool ExtCompareStyle(); +#endif + +#ifdef THREE_D +extern void ExtGetZAxis(); +#endif + +extern void ExtDumpCaps(); + +#endif /* _EXTRACT_H */ diff --git a/extract/extractInt.h b/extract/extractInt.h new file mode 100644 index 00000000..ee264862 --- /dev/null +++ b/extract/extractInt.h @@ -0,0 +1,1057 @@ +/* + * extractInt.h -- + * + * Defines things shared internally by the extract module of Magic, + * but not generally needed outside the extract module. + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/extract/extractInt.h,v 1.7 2010/08/10 00:18:46 tim Exp $" + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This module has been modified at DEC/WRL and Stanford University. + * The above disclaimers apply. + * + */ + +#ifndef _EXTRACTINT_H +#define _EXTRACTINT_H + +#include "database/database.h" + +#undef NT +#define NT TT_MAXTYPES +#undef NP +#define NP PL_MAXTYPES + +/* ------------------------ Capacitance Values ------------------------- */ + +typedef double CapValue; /* No longer allowed to define back to integer, + * as this touches too many parts of the code. + */ + +/* Procs to manipulate capacitance hash tables. */ +extern CapValue extGetCapValue(); +extern void extSetCapValue(); +extern void extCapHashKill(); + +typedef int ResValue; /* Warning: in some places resistances are stored + * as ints. This is here for documentation only. + */ + +/* ------------------------ Parameter lists --------------------------- */ + +/* These lists keep track of what parameter names subcircuit definitions + * use for parameters that magic knows how to generate. Valid pl_param + * values are a (area), p (perimeter), w (width), l (length), s (substrate), + * x (position), and y (position). Values "a" and "p" may be followed by + * an additional integer indicating the terminal from which the value is + * used (e.g., source area, drain perimeter, etc.). An integer "0" + * indicates the device identifier region (e.g., gate) and is equivalent + * to having no integer at all. Integers "1" and up indicate terminals, + * in order. + */ + +typedef struct pl +{ + int pl_count; /* Share this list. . . */ + char pl_param[2]; /* Default character for parameter */ + char *pl_name; /* Full name for parameter */ + double pl_scale; /* Scaling of parameter, if specified */ + struct pl *pl_next; /* Next parameter in list */ +} ParamList; + +/* -------------------------- Label lists ----------------------------- */ + +/* + * List of labels for a node. + * We keep around pointers to the entire labels for + * later figuring out which are attached to the gates, + * sources, or drains of transistors. + */ +typedef struct ll +{ + Label *ll_label; /* Actual Label in the source CellDef */ + struct ll *ll_next; /* Next LabelList in this region */ + int ll_attr; /* Which terminal of a transistor this is + * an attribute of. + */ +} LabelList; + +#define LL_NOATTR -1 /* Value for ll_attr above if the label is + * not a transistor attribute. + */ +#define LL_GATEATTR -2 /* Value for ll_attr if the label is a gate + * attribute, rather than one of the diffusion + * terminals' attributes. + */ +#define LL_SORTATTR -3 /* value for ll_attr used in + * ExtBasic.c/ExtSortTerminals() to swap + * the attributes as well as the regions + * -- Stefanos 5/96 + */ +#define LL_PORTATTR -4 /* value for ll_attr used to declare + * the label to be a subcircuit port + * -- Tim 5/02 + */ +/* + * Types of labels. + * These can be or'd into a mask and passed to extLabType(). + */ +#define LABTYPE_NAME 0x01 /* Normal node name */ +#define LABTYPE_NODEATTR 0x02 /* Node attribute */ +#define LABTYPE_GATEATTR 0x04 /* Transistor gate attribute */ +#define LABTYPE_TERMATTR 0x08 /* Transistor terminal (source/drain) + * attribute. + */ +#define LABTYPE_PORTATTR 0x10 /* Subcircuit port */ + +/* ----------------------------- Regions ------------------------------ */ + +/* + * The following are the structures built up by the various + * clients of ExtFindRegions. The general rule for these + * structures is that their initial fields must be identical + * to those in a Region, but subsequent fields are up to + * the individual client. + * + * Regions marked as GENERIC are the types accepted by + * procedures in ExtRegion.c. + */ + + /* + * GENERIC Region struct. + * All this provides is a pointer to the next Region. + * This is the type passed to functions like ExtFreeRegions, + * and is the type returned by ExtFindRegions. Clients should + * cast pointers of this type to their own, client type. + */ +typedef struct reg +{ + struct reg *reg_next; /* Next region in list */ +} Region; + + /* + * GENERIC region with labels. + * Any other structure that wants to reference node names + * must include the same fields as this one as its first part. + */ +typedef struct lreg +{ + struct lreg *lreg_next; /* Next region in list */ + int lreg_pnum; /* Lowest numbered plane in this region */ + int lreg_type; /* Type of tile that contains lreg_ll */ + Point lreg_ll; /* Lower-leftmost point in this region on + * plane lreg_pnum. We take the min first + * in X, then in Y. + */ + LabelList *lreg_labels; /* List of labels for this region. These are + * any labels connected to the geometry making + * up this region. If the list is empty, make + * up a name from lreg_pnum and lreg_ll. + */ +} LabRegion; + + /* + * Node region: labelled region with resistance and capacitance. + * Used for each node in the flat extraction of a cell. + */ + +typedef struct +{ + int pa_perim; + int pa_area; +} PerimArea; + +typedef struct nreg +{ + struct nreg *nreg_next; /* Next region in list */ + int nreg_pnum; /* Lowest numbered plane in this region */ + int nreg_type; /* Type of tile that contains nreg_ll */ + Point nreg_ll; /* Lower-leftmost point in this region on + * plane nreg_pnum. We take the min first + * in X, then in Y. + */ + LabelList *nreg_labels; /* See LabRegion for description */ + CapValue nreg_cap; /* Capacitance to ground */ + ResValue nreg_resist; /* Resistance estimate */ + PerimArea nreg_pa[1]; /* Dummy; each node actually has + * ExtCurStyle->exts_numResistClasses + * array elements allocated to it. + */ +} NodeRegion; + + /* + * Transistor region: labelled region with perimeter and area. + * Used for each transistor in the flat extraction of a cell. + */ +typedef struct treg +{ + struct treg *treg_next; /* Next region in list */ + int treg_pnum; /* UNUSED */ + int treg_type; /* Type of tile that contains treg_ll */ + Point treg_ll; /* UNUSED */ + LabelList *treg_labels; /* Attribute list */ + Tile *treg_tile; /* Some tile in the channel */ + int treg_area; /* Area of channel */ +} TransRegion; + +typedef struct { /* Maintain plane information when pushing */ + Rect area; /* tiles on the node stack. For use with */ + int plane; /* function extNbrPushFunc(). */ +} PlaneAndArea; + +/* Structure to be kept in a hash table of node regions for the current */ +/* extract cell. It tracks the original substrate cap calculated for */ +/* each region used in the "node" line output, the final substrate cap */ +/* calculated after taking all subcircuits into account, and a running */ +/* total of all corrections to the node's substrate cap generated in */ +/* "merge" lines by extSubtree() and extArray(). After both routines */ +/* have run, any unaccounted capacitance is output to the .ext file as */ +/* a "subcap" line. */ + +typedef struct { + NodeRegion *subcap_reg; + CapValue subcap_orig; + CapValue subcap_final; + CapValue subcap_adjust; +} SubCapAdjust; + +/* + * The following constructs a node name from the plane number 'n' + * and lower left Point l, and places it in the string 's' (which must + * be large enough). + */ +#define extMakeNodeNumPrint(buf, plane, coord) \ + (void) sprintf((buf), "%s_%s%d_%s%d#", DBPlaneShortName(plane), \ + ((coord).p_x < 0) ? "n": "", abs((coord).p_x), \ + ((coord).p_y < 0) ? "n": "", abs((coord).p_y)) + +/* Old way: cryptic numbers, but a bit shorter + * + * #define extMakeNodeNumPrint(s, n, l) \ + * (void) sprintf((s), "%d_%d_%d#", (n), extCoord((l).p_x), extCoord((l).p_y)) + * + * The following is used to map the full coordinate space into + * the positive integers, for constructing internally generated + * node names. + * + * #define extCoord(x) (((x) < 0) ? (1 - ((x) << 1)) : ((x) << 1)) + */ + +/* + * Argument passed to filter functions for finding regions. + */ +typedef struct +{ + TileTypeBitMask *fra_connectsTo; /* Array of TileTypeBitMasks. The + * element fra_connectsTo[t] has a + * bit set for each type that + * connects to 't'. + */ + CellDef *fra_def; /* Def being searched */ + int fra_pNum; /* Plane currently searching */ + ClientData fra_uninit; /* This value appears in the ti_client + * field of a tile if it's not yet + * been visited. + */ + Region *(*fra_first)(); /* Function to init new region */ + int (*fra_each)(); /* Function for each tile in region */ + Region *fra_region; /* Ptr to Region struct for current + * region. May be set by fra_first + * and used by fra_each. + */ +} FindRegion; + +#define TILEAREA(tp) ((TOP(tp) - BOTTOM(tp)) * (RIGHT(tp) - LEFT(tp))) + +/* -------------------- Perimeter of a region ------------------------- */ + +/* + * Segment of the boundary of a region whose perimeter + * is being traced by ExtTracePerimeter() and extEnumTilePerim(). + */ +typedef struct +{ + Tile *b_inside; /* Pointer to tile just inside segment */ + Tile *b_outside; /* Pointer to tile just outside segment */ + Rect b_segment; /* Actual coordinates of segment */ + unsigned char b_direction; /* Direction following segment (see below) */ + int b_plane; /* extract argument for extSideOverlap */ +} Boundary; + +#define BoundaryLength(bp) \ + ((bp)->b_segment.r_xtop - (bp)->b_segment.r_xbot \ + + (bp)->b_segment.r_ytop - (bp)->b_segment.r_ybot) + +/* Directions in which we can be following the boundary of a perimeter */ + +#define BD_LEFT 1 /* Inside is to right */ +#define BD_TOP 2 /* Inside is below */ +#define BD_RIGHT 4 /* Inside is to left */ +#define BD_BOTTOM 8 /* Inside is above */ + +/* -------- Yank buffers for hierarchical and array extraction -------- */ + +extern CellUse *extYuseCum; +extern CellDef *extYdefCum; + +/* --------------- Argument passed to extHierYankFunc ----------------- */ + +typedef struct +{ + Rect *hy_area; /* Area (in parent coordinates) to be yanked */ + CellUse *hy_target; /* Yank into this use */ + bool hy_prefix; /* If TRUE, prefix labels with use id */ +} HierYank; + +/* ----- Arguments to filter functions in hierarchical extraction ---- */ + + /* + * The following defines an extracted subtree. + * The CellUse et_use will be either a cell we are extracting, + * or a flattened subtree. If et_lookNames is non-NULL, it + * points to a CellDef that we should look in for node names. + */ +typedef struct extTree +{ + CellUse *et_use; /* Extracted cell, usually flattened */ + CellUse *et_realuse; /* If et_use is flattened, et_realuse + * points to the unflattened subtree's + * root use; otherwise it is NULL. + */ + CellDef *et_lookNames; /* See above */ + NodeRegion *et_nodes; /* List of nodes */ + HashTable et_coupleHash; /* Table for coupling capacitance. + * key is type CoupleKey + * value is pointer to type CapValue + */ + struct extTree *et_next; /* Next one in list */ +} ExtTree; + + /* + * The following structure contains information passed down + * through several levels of filter functions during hierarchical + * extraction. + * + * The procedure ha_nodename is used to map from a tile into the + * name of the node to which that tile belongs. It should be of + * the following format: + * + * char * + * proc(tp, et, ha) + * Tile *tp; + * ExtTree *et; + * HierExtractArg *ha; + * { + * } + * + * It should always return a non-NULL string; if the name of a + * node can't be determined, the string can be "(none)". + */ +typedef struct +{ + FILE *ha_outf; /* The .ext file being written */ + CellUse *ha_parentUse; /* Use pointing to the def being extracted */ + char *(*ha_nodename)(); /* Map (tp, et, ha) into nodename; see above */ + ExtTree ha_cumFlat; /* Cumulative yank buffer */ + NodeRegion *ha_parentReg; /* Node region list from parent def */ + HashTable ha_connHash; /* Connections made during hier processing */ + +/* All areas are in parent coordinates */ + + Rect ha_interArea; /* Area of whole interaction being considered */ + Rect ha_clipArea; /* Only consider capacitance, perimeter, and + * area that come from inside this area. This + * rectangle is contained within ha_interArea. + */ + CellUse *ha_subUse; /* Root of the subtree being processed now */ + Rect ha_subArea; /* Area of ha_subUse inside the interaction + * area, i.e, contained within ha_interArea. + */ + Tile *hierOneTile; /* Used in ExtHier.c, tile from extHierOneFlat */ + int hierPNum; /* Used in ExtHier.c, plane of tile above */ + TileType hierType; /* Used in ExtHier.c, type of tile above */ + int hierPNumBelow; /* Used in ExtHier.c, plane of tile below */ +} HierExtractArg; + +/* + * Normally, nodes in overlapping subcells are expected to have labels + * in the area of overlap. When this is not the case, we have to use + * a much more expensive algorithm for finding the labels attached to + * the subcells' geometry in the overlap area. The following structure + * is used to hold information about the search in progress for such + * labels. + */ +typedef struct +{ + HierExtractArg *hw_ha; /* Describes context of search */ + Label *hw_label; /* We update hw_label with a ptr to a + * newly allocated label if successful. + */ + Rect hw_area; /* Area in parent coordinates of the + * area where we're searching. + */ + bool hw_autogen; /* If TRUE, we trace out all geometry + * in the first node in the first cell + * found to overlap the search area, + * and use the internal name for that + * node. + */ + TerminalPath hw_tpath; /* Hierarchical path down to label + * we are searching for, rooted at + * the parent being extracted. + */ + TileTypeBitMask hw_mask; /* Mask of tile types that connect to + * the tile whose node is to be found, + * and which are on the same plane. + * Used when calling ExtFindRegions. + */ + bool hw_prefix; /* If FALSE, we skip the initial + * use identifier when building + * hierarchical labels (as when + * extracting arrays; see hy_prefix + * in the HierYank struct). + */ + int (*hw_proc)(); +} HardWay; + +/* --------------------- Coupling capacitance ------------------------- */ + +/* + * The following structure is the hash key used for computing + * internodal coupling capacitance. Each word is a pointer to + * one of the nodes being coupled. By convention, the first + * word is the lesser of the two NodeRegion pointers. + */ +typedef struct +{ + NodeRegion *ck_1, *ck_2; +} CoupleKey; + +extern void extCoupleHashZero(); /* Clears out all pointers to data in table */ + +/* ------------------ Interface to debugging module ------------------- */ + +extern ClientData extDebugID; /* Identifier returned by the debug module */ + +/* ----------------- Technology-specific information ------------------ */ + +/* + * Structure used to define sidewall coupling capacitances. + */ +typedef struct edgecap +{ + struct edgecap *ec_next; /* Next edge capacitance rule in list */ + CapValue ec_cap; /* Capacitance (attofarads) */ + TileTypeBitMask ec_near; /* Types closest to causing edge, or in + * the case of sideOverlaps, the + * types we are overlapping. + */ + TileTypeBitMask ec_far; /* Types farthest from causing edge, or + * in the case of sideOverlaps, the + * types that shield the edge from + * the overlaped tile. + */ + int ec_pmask; /* specifies which planes are to be */ + /* used. */ +} EdgeCap; + + +/* A type used to determine if current style needs planeorder or not */ +typedef enum { noPlaneOrder, needPlaneOrder, seenPlaneOrder } planeOrderStatus ; + +/* + * Because a large TT_MAXTYPES value quickly generates huge extract section + * structures, we want to keep around only the style names, and dynamically + * load and destroy the extract section values as needed, when doing an + * extraction command. + */ + +typedef struct extkeep +{ + struct extkeep *exts_next; + char *exts_name; +} ExtKeep; + +/* + * Parameters for the process being extracted. + * We try to use use integers here, rather than floats, to be nice to + * machines like Sun workstations that don't have hardware + * floating point. + * + * In the case of capacitances, though, we may have to use floats, depending + * upon the type CapValue. In some newer processes the capacitance per + * lambda^2 is less than 1 attofarad. + */ + +typedef struct extstyle +{ + char exts_status; /* Loaded, not loaded, or pending */ + char *exts_name; /* Name of this style */ + + /* + * Connectivity tables. + * Each table is an array of TileTypeBitMasks indexed by TileType. + * The i-th element of each array is a mask of those TileTypes + * to which type 'i' connects. + */ + + /* Everything is connected to everything else in this table */ + TileTypeBitMask exts_allConn[NT]; + + /* + * Connectivity for determining electrical nodes. + * This should be essentially the same as DBConnectTbl[]. + */ + TileTypeBitMask exts_nodeConn[NT]; + + /* + * Connectivity for determining resistive regions. + * Two types should be marked as connected here if + * they are both connected in exts_nodeConnect[], and + * if they both have the same resistance per square. + */ + TileTypeBitMask exts_resistConn[NT]; + + /* + * Connectivity for determining transistors. + * Each transistor type should connect only to itself. + * Nothing else should connect to anything else. + */ + TileTypeBitMask exts_transConn[NT]; + + /* + * Set of types to be considered for extraction. Types not in + * this list cannot be nodes (e.g., implant layers) + */ + TileTypeBitMask exts_activeTypes; + + /* + * Sheet resistivity for each tile type, in milli-ohms per square. + * For types that are transistors or capacitors, this corresponds + * to the sheet resistivity of the gate. + */ + + /* Maps from a tile type to the index of its sheet resistance entry */ + int exts_typeToResistClass[NT]; + + /* Gives a mask of neighbors of a type with different resistivity */ + TileTypeBitMask exts_typesResistChanged[NT]; + + /* + * Resistance information is also provided by the following tables: + * exts_typesByResistClass[] is an array of masks of those types + * having the same sheet resistivity, for each different value + * of sheet resistivity; exts_resistByResistClass[] is a parallel array + * giving the actual value of sheet resistivity. Both are indexed + * from 0 up to (but not including) exts_numResistClasses. + */ + TileTypeBitMask exts_typesByResistClass[NT]; + ResValue exts_resistByResistClass[NT]; + int exts_numResistClasses; + + /* Resistance per type */ + ResValue exts_sheetResist[NT]; + + /* + * Resistances for via holes, given in milliohms. Number of + * cuts is determined by the "cifoutput" style "squares" + * parameters. + */ + ResValue exts_viaResist[NT]; + + /* + * Amount to scale resistance of a material on a corner. + * Defauts to 1.0. Often set to 0.5. + */ + float exts_cornerChop[NT]; + + /* Layer height and thickness used by the geometry extractor */ + float exts_height[NT]; + float exts_thick[NT]; + + /* + * Capacitance to substrate for each tile type, in units of + * attofarads per square lambda. + */ + + /* + * Capacitance per unit area. This is zero for explicit capacitor + * types, which handle gate-channel capacitance specially. For + * transistor types, this is at best an approximation that is + * truly valid only when the transistor is switched off. + */ + CapValue exts_areaCap[NT]; + + /* + * Capacitance per unit perimeter. Sidewall capacitance depends both + * on the type inside the perimeter as well as the type outside it, + * so the table is doubly indexed by TileType. + * + * The mask exts_perimCapMask[t] contains bits for all those TileTypes + * 's' such that exts_perimCap[t][s] is nonzero. + */ + CapValue exts_perimCap[NT][NT]; + TileTypeBitMask exts_perimCapMask[NT]; + + /* + * Overlap coupling capacitance for each pair of tile types, in units + * of attofarads per square lambda of overlap. + * Internodal capacitance due to overlap only occurs between tile + * types on different tile planes that are not shielded by intervening + * tiles. + */ + + /* + * The mask exts_overlapPlanes is a mask of those planes that must + * be searched for tiles having overlap capacitance, and the mask + * exts_overlapTypes[p] is those types having overlap capacitance + * on each plane p. The intent is that exts_overlapTypes[p] lists + * only those types t for which some entry of exts_overlapCap[t][s] + * is non-zero. + */ + PlaneMask exts_overlapPlanes; + TileTypeBitMask exts_overlapTypes[NP]; + + /* + * The mask exts_overlapOtherPlanes[t] is a mask of the planes that + * must be searched for tiles having overlap capacitance with tiles + * of type 't', and exts_overlapOtherTypes[t] is a mask of the types + * with which our overlap capacitance is non-zero. + */ + TileTypeBitMask exts_overlapOtherTypes[NT]; + PlaneMask exts_overlapOtherPlanes[NT]; + + /* + * Both exts_overlapShieldTypes[][] and exts_overlapShieldPlanes[][] + * are indexed by the same pair of types used to index the table + * exts_overlapCap[][]; they identify the types and planes that + * shield capacitance between their index types. + */ + TileTypeBitMask exts_overlapShieldTypes[NT][NT]; + PlaneMask exts_overlapShieldPlanes[NT][NT]; + + /* + * The table extOverlapCap[][] is indexed by two types to give the + * overlap coupling capacitance between them, per unit area. Only + * one of extOverlapCap[i][j] and extOverlapCap[j][i] should be + * nonzero. The capacitance to substrate of the tile of type 'i' + * is deducted when an overlap between i and j is detected, if + * extOverlapCap[i][j] is nonzero. This is only done, however, if + * tile i is below tile j in exts_planeOrder; + */ + CapValue exts_overlapCap[NT][NT]; + + /* Specifies an ordering of the planes, so we can determine which + * tile is above another one. This is used only when determining + * if we should subtract capacitance to substrate for overlap and + * sideoverlap rules. If no planeorder is specified and the style + * does not contain a noplaneordering command a warning is issued + * and the default planeorder is used for the style. + */ + int exts_planeOrder[NP]; + /* set/reset with planeorder commands to determine whether + * we will warn if no planeorder is specified. This is done + * because at Stanford we use a lot of diagnostic extraction + * styles (for floating wells etc.) and we don't want to specify + * the planeorder for each and every one of them. + */ + planeOrderStatus exts_planeOrderStatus; + + + /* + * Sidewall coupling capacitance. This capacitance is between edges + * on the same plane, and is in units of attofarads. It is multiplied + * by the value interpolated from a fringing-field table indexed by the + * common length of the pair of edges divided by their separation: + * + * | | + * E1 +----------------------------+ + * ^ + * +--- distance between edges + * v + * +-----------------------------------+ E2 + * | | + * + * <-----------------------> length in common + */ + + /* + * The entry exts_sideCoupleCap[i][j] is a list of the coupling + * capacitance info between edges with type 'i' on the inside + * and 'j' on the outside, and other kinds of edges. + */ + EdgeCap *exts_sideCoupleCap[NT][NT]; + + /* + * exts_sideCoupleOtherEdges[i][j] is a mask of those types on the + * far sides of edges to which an edge with 'i' on the inside and + * 'j' on the outside has coupling capacitance. + */ + TileTypeBitMask exts_sideCoupleOtherEdges[NT][NT]; + + /* + * We search out a distance exts_sideCoupleHalo from each edge + * for other types with which we have coupling capacitance. + * This value determines how much extra gets yanked when + * computing hierarchical adjustments, so should be kept + * small to insure reasonable performance. + */ + int exts_sideCoupleHalo; + + /* + * Sidewall-overlap coupling capacitance. + * This is between an edge on one plane and a type on another plane + * that overlaps the edge (from the outside of the edge), and is in + * units of attofarads per lambda. + * + * When an edge with sidewall capacitance to substrate is found to + * overlap a type to which it has sidewall overlap capacitance, the + * original capacitance to substrate is replaced with the overlap + * capacitance to the tile overlapped, if the edge is above the tile + * being overlapped (according to ext_planeOrder). If the tiles are + * the other way around, then this replacement is not done. + */ + + /* + * The entry exts_sideOverlapCap[i][j] is a list of the coupling + * capacitance info between edges with type 'i' on the inside + * and 'j' on the outside, and other kinds of tiles on other + * planes. The ec_near mask in the EdgeCap record identifies the + * types to which we have sidewall overlap capacitance, and the + * ec_far mask identifies the types that shield the tiles preventing + * a capacitance. + */ + EdgeCap *exts_sideOverlapCap[NT][NT]; + + /* + * extSideOverlapOtherTypes[i][j] is a mask of those types to which + * an edge with 'i' on the inside and 'j' on the outside has coupling + * capacitance. extSideOverlapOtherPlanes[i][j] is a mask of those + * planes to which edge [i][j] has overlap coupling capacitance. + * exts_sideOverlapShieldPlanes[s][t] is a list of the planes that + * need to be examined for shielding material when we are considering + * a sidewall overlap capacitor between types s and t. This may + * be the "or" of the planes needed by several sideoverlap rules, + * since there can be several types of edges in which type s is + * the "intype" member and the "outtype" member varies. Note that + * sideOverlapShieldPlanes is indexed like overlapShieldPlanes, not + * like sideOverlapOtherPlanes. + */ + PlaneMask exts_sideOverlapOtherPlanes[NT][NT]; + TileTypeBitMask exts_sideOverlapOtherTypes[NT][NT]; + PlaneMask exts_sideOverlapShieldPlanes[NT][NT]; + + /* + * Both exts_overlapShieldTypes[][] and exts_overlapShieldPlanes[][] + * are indexed by the same pair of types used to index the table + * exts_overlapCap[][]; they identify the types and planes that + * shield capacitance between their index types. + */ + + + /* Common to both sidewall coupling and sidewall overlap */ + + /* + * exts_sideTypes[p] is a mask of those types 't' having sidewall + * coupling or sidewall overlap capacitance on plane p (i.e, for + * which a bin in exts_sideCoupleCap[t][] or exts_sideOverlapCap[t][] + * is non-empty), and exts_sidePlanes a mask of those planes containing + * tiles in exts_sideTypes[]. + */ + PlaneMask exts_sidePlanes; + TileTypeBitMask exts_sideTypes[NP]; + + /* + * The mask exts_sideEdges[i] is just a mask of those types j for + * which either exts_sideCoupleCap[i][j] or exts_sideOverlapCap[i][j] + * is non-empty. + */ + TileTypeBitMask exts_sideEdges[NT]; + + /* Transistors */ + + /* Name of each transistor type as output in .ext file */ + char *exts_transName[NT]; + + /* List of parameter names for each subcircuit type */ + ParamList *exts_deviceParams[NT]; + + /* Device class for each layer type */ + char exts_deviceClass[NT]; + + /* Contains one for each type of fet, zero for all other types */ + TileTypeBitMask exts_transMask; + + /* + * Per-square resistances for each possible transistor type, + * in the various regions that such a type might operate. + * The only operating region currently used is "linear", + * which the resistance extractor uses in its thresholding + * operation. NOTE: resistances in this table are in OHMS + * per square, not MILLIOHMS! + */ + HashTable exts_transResist[NT]; + ResValue exts_linearResist[NT]; + + /* + * Mask of the types of tiles that connect to the channel terminals + * of a transistor type. The intent is that these will be the + * diffusion terminals of a transistor, ie, its source and drain. + * UPDATED May, 2008: Record is a list of type masks, allowing + * multiple terminal types in the case of, e.g., high-voltage + * or other asymmetric devices. The last entry in the list should + * be equal to DBSpaceBits. + */ + TileTypeBitMask *exts_transSDTypes[NT]; + + /* + * Maximum number of terminals (source/drains) per transistor type. + * This table exists to allow the possibility of transistors with + * more than two diffusion terminals at some point in the future. + */ + int exts_transSDCount[NT]; + + /* Currently unused: gate-source capacitance per unit perimeter */ + CapValue exts_transSDCap[NT]; + + /* Currently unused: gate-channel capacitance per unit area */ + CapValue exts_transGateCap[NT]; + + /* + * Each type of transistor has a substrate node. By default, + * it is the one given by exts_transSubstrateName[t]. However, + * if the mask exts_transSubstrateTypes[t] is non-zero, and if + * the transistor overlaps material of one of the types in the + * mask, then the transistor substrate node is the node of the + * material it overlaps. If exts_transSub + */ + char *exts_transSubstrateName[NT]; + TileTypeBitMask exts_transSubstrateTypes[NT]; +#ifdef ARIEL + TileTypeBitMask exts_subsTransistorTypes[NT]; +#endif /* ARIEL */ + + /* + * There is a single name for global substrate, and a list of + * types that connect to the substrate. Since for non-SOI + * processes, this generally is used to specify that space on + * the well plane is the substrate, the plane number for the + * well plane is given, too. + */ + char *exts_globSubstrateName; + TileTypeBitMask exts_globSubstrateTypes; + int exts_globSubstratePlane; + + /* Scaling */ + /* + * Step size used when breaking up a large cell for interaction + * checks during hierarchical extraction. We check exts_stepSize + * by exts_stepSize chunks for interactions one at a time. + */ + int exts_stepSize; + + /* + * Number of linear units per lambda. All perimeter dimensions + * that we output to the .ext file should be multiplied by + * exts_unitsPerLambda; we produce a "scale" line in the .ext file + * indicating this. All area dimensions should be multiplied + * by exts_unitsPerLambda**2. + * (changed to type float May 11, 2006 to accommodate, e.g., 90 + * and 130 nm technologies) + */ + float exts_unitsPerLambda; + + /* + * Scaling for resistance and capacitance. + * All resistances in the .ext file should be multiplied by + * exts_resistScale to get milliohms, and all capacitances by + * exts_capScale to get attofarads. These numbers appear in + * the "scale" line in the .ext file. + */ + int exts_capScale; + int exts_resistScale; +} ExtStyle; + +#define EXT_PLUG_GND 1 +#define EXT_PLUG_VDD 2 + +extern ExtStyle *ExtCurStyle; + +/* ------------------- Hierarchical node merging ---------------------- */ + +/* + * Table used to hold all merged nodes during hierarchical extraction. + * Used for duplicate suppression. + */ +extern HashTable extHierMergeTable; + +/* + * Each hash entry in the above table points to a NodeName struct. + * Each NodeName points to the Node corresponding to that name. + * Each Node points back to a list of NodeNames that point to that + * Node, and which are linked together along their nn_next fields. + */ +typedef struct nn +{ + struct node *nn_node; /* Node for which this is a name */ + char *nn_name; /* Text of name */ + struct nn *nn_next; /* Other names of nn_node */ +} NodeName; + +typedef struct node +{ + NodeName *node_names; /* List of names for this node. The first name + * in the list is the "official" node name. + */ + CapValue node_cap; /* Capacitance to substrate */ + PerimArea node_pa[1]; /* Dummy; each node actually has + * ExtCurStyle->exts_numResistClasses + * array elements allocated to it. + */ +} Node; + +/* -------------------------------------------------------------------- */ + +/* + * Value normally resident in the ti_client field of a tile, + * indicating that the tile has not yet been visited in a + * region search. + */ +extern ClientData extUnInit; + +#define extGetRegion(tp) ( (tp)->ti_client ) +#define extHasRegion(tp,und) ( (tp)->ti_client != (und) ) + + +/* For non-recursive flooding algorithm */ +#define VISITPENDING ((ClientData) NULL) /* Marks tiles on stack */ + +/* Note that this macro depends on MAXPLANES being small */ +/* compared to the bit position of TT_SIDE. Since tens of */ +/* thousands of planes is inconceivable, this should not be a */ +/* problem. It is necessary to push the tile's TT_SIDE bit */ +/* because the search algorithm can overwrite it between the */ +/* time the tile is pushed and the time that it is popped. */ + +#define PUSHTILE(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)(pointertype)(pl | \ + ((TileType)(spointertype)(tp)->ti_body & TT_SIDE)), extNodeStack); \ + STACKPUSH((ClientData)(pointertype)tp, extNodeStack) + +#define POPTILE(tp, pl) \ + tp = (Tile *) STACKPOP(extNodeStack); \ + pl = (spointertype) STACKPOP(extNodeStack); \ + if (pl & TT_SIDE) { \ + TiSetBody((tp), TiGetTypeExact(tp) | TT_SIDE); \ + pl &= (~TT_SIDE); \ + } \ + else \ + TiSetBody((tp), TiGetTypeExact(tp) & (~TT_SIDE)) + +/* Variations of "pushtile" to force a specific value on TT_SIDE */ + +#define PUSHTILEBOTTOM(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)(pointertype)(pl | \ + ((SplitDirection(tp)) ? 0 : TT_SIDE)), extNodeStack) ;\ + STACKPUSH((ClientData)(pointertype)tp, extNodeStack) + +#define PUSHTILETOP(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)(pointertype)(pl | \ + ((SplitDirection(tp)) ? TT_SIDE : 0)), extNodeStack) ;\ + STACKPUSH((ClientData)(pointertype)tp, extNodeStack) + +#define PUSHTILELEFT(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)(pointertype)(pl), extNodeStack); \ + STACKPUSH((ClientData)(pointertype)tp, extNodeStack) + +#define PUSHTILERIGHT(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)(pointertype)(pl | TT_SIDE), extNodeStack); \ + STACKPUSH((ClientData)(pointertype)tp, extNodeStack) + +/* ------------------------- Region finding --------------------------- */ + +extern Region *ExtFindRegions(); + +/* Filter functions for ExtFindRegions() */ +extern Region *extTransFirst(); extern int extTransEach(); +extern Region *extResFirst(); extern int extResEach(); +extern Region *extNodeFirst(); extern int extNodeEach(); +extern Region *extHierLabFirst(); extern int extHierLabEach(); + +extern Tile *extNodeToTile(); + +/* -------- Search for matching node in another ExtTree ---------- */ + +/* + * NODETONODE(nold, et, nnew) + * NodeRegion *nold; + * ExtTree *et; + * NodeRegion *nnew; + * + * Like extNodeToTile(), but leaves nnew pointing to the node associated + * with the tile we find. + */ +#define NODETONODE(nold, et, nnew) \ + if (1) { \ + Tile *tp; \ + \ + (nnew) = (NodeRegion *) NULL; \ + tp = extNodeToTile((nold), (et)); \ + if (tp && extHasRegion(tp, extUnInit)) \ + (nnew) = (NodeRegion *) extGetRegion(tp); \ + } + +/* -------------------- Miscellaneous procedures ---------------------- */ + +extern char *extNodeName(); +extern NodeRegion *extBasic(); +extern NodeRegion *extFindNodes(); +extern ExtTree *extHierNewOne(); +extern int extNbrPushFunc(); + +/* --------------------- Miscellaneous globals ------------------------ */ + +extern int extNumFatal; /* Number fatal errors encountered so far */ +extern int extNumWarnings; /* Number warning messages so far */ +extern CellUse *extParentUse; /* Dummy use for def being extracted */ +extern ClientData extNbrUn; /* Ditto */ + +extern NodeRegion *glob_subsnode; /* Substrate node for cell def */ +extern NodeRegion *temp_subsnode; /* Substrate connection to subcell */ + + /* + * This is really a (Stack *), but we use the struct tag to avoid + * having to include stack.h in every .c file. Used in the non-recursive + * flooding algorithm. + */ +extern struct stack *extNodeStack; + +/* ------------------ Connectivity table management ------------------- */ + +/* + * The following is true if tile types 'r' and 's' are connected + * according to the connectivity table 'tbl' + */ +#define extConnectsTo(r, s, tbl) ( TTMaskHasType(&(tbl)[(r)], (s)) ) + +/* -------------------------------------------------------------------- */ + +#include "extDebugInt.h" + +#endif /* _EXTRACTINT_H */ diff --git a/extract/extractInt.h.new b/extract/extractInt.h.new new file mode 100644 index 00000000..39335c89 --- /dev/null +++ b/extract/extractInt.h.new @@ -0,0 +1,1053 @@ +/* + * extractInt.h -- + * + * Defines things shared internally by the extract module of Magic, + * but not generally needed outside the extract module. + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/extract/extractInt.h.new,v 1.2 2008/06/01 18:37:42 tim Exp $" + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This module has been modified at DEC/WRL and Stanford University. + * The above disclaimers apply. + * + */ + +#ifndef _EXTRACTINT_H +#define _EXTRACTINT_H + +#include "database/database.h" + +#undef NT +#define NT TT_MAXTYPES +#undef NP +#define NP PL_MAXTYPES + +/* ------------------------ Capacitance Values ------------------------- */ + +typedef double CapValue; /* No longer allowed to define back to integer, + * as this touches too many parts of the code. + */ + +/* Procs to manipulate capacitance hash tables. */ +extern CapValue extGetCapValue(); +extern void extSetCapValue(); +extern void extCapHashKill(); + +typedef int ResValue; /* Warning: in some places resistances are stored + * as ints. This is here for documentation only. + */ + +/* -------------------------- Label lists ----------------------------- */ + +/* + * List of labels for a node. + * We keep around pointers to the entire labels for + * later figuring out which are attached to the gates, + * sources, or drains of transistors. + */ +typedef struct ll +{ + Label *ll_label; /* Actual Label in the source CellDef */ + struct ll *ll_next; /* Next LabelList in this region */ + int ll_attr; /* Which terminal of a transistor this is + * an attribute of. + */ +} LabelList; + +#define LL_NOATTR -1 /* Value for ll_attr above if the label is + * not a transistor attribute. + */ +#define LL_GATEATTR -2 /* Value for ll_attr if the label is a gate + * attribute, rather than one of the diffusion + * terminals' attributes. + */ +#define LL_SORTATTR -3 /* value for ll_attr used in + * ExtBasic.c/ExtSortTerminals() to swap + * the attributes as well as the regions + * -- Stefanos 5/96 + */ +#define LL_PORTATTR -4 /* value for ll_attr used to declare + * the label to be a subcircuit port + * -- Tim 5/02 + */ +/* + * Types of labels. + * These can be or'd into a mask and passed to extLabType(). + */ +#define LABTYPE_NAME 0x01 /* Normal node name */ +#define LABTYPE_NODEATTR 0x02 /* Node attribute */ +#define LABTYPE_GATEATTR 0x04 /* Transistor gate attribute */ +#define LABTYPE_TERMATTR 0x08 /* Transistor terminal (source/drain) + * attribute. + */ +#define LABTYPE_PORTATTR 0x10 /* Subcircuit port */ + +/* ----------------------------- Regions ------------------------------ */ + +/* + * The following are the structures built up by the various + * clients of ExtFindRegions. The general rule for these + * structures is that their initial fields must be identical + * to those in a Region, but subsequent fields are up to + * the individual client. + * + * Regions marked as GENERIC are the types accepted by + * procedures in ExtRegion.c. + */ + + /* + * GENERIC Region struct. + * All this provides is a pointer to the next Region. + * This is the type passed to functions like ExtFreeRegions, + * and is the type returned by ExtFindRegions. Clients should + * cast pointers of this type to their own, client type. + */ +typedef struct reg +{ + struct reg *reg_next; /* Next region in list */ +} Region; + + /* + * GENERIC region with labels. + * Any other structure that wants to reference node names + * must include the same fields as this one as its first part. + */ +typedef struct lreg +{ + struct lreg *lreg_next; /* Next region in list */ + int lreg_pnum; /* Lowest numbered plane in this region */ + int lreg_type; /* Type of tile that contains lreg_ll */ + Point lreg_ll; /* Lower-leftmost point in this region on + * plane lreg_pnum. We take the min first + * in X, then in Y. + */ + LabelList *lreg_labels; /* List of labels for this region. These are + * any labels connected to the geometry making + * up this region. If the list is empty, make + * up a name from lreg_pnum and lreg_ll. + */ +} LabRegion; + + /* + * Node region: labelled region with resistance and capacitance. + * Used for each node in the flat extraction of a cell. + */ + +typedef struct +{ + int pa_perim; + int pa_area; +} PerimArea; + +typedef struct nreg +{ + struct nreg *nreg_next; /* Next region in list */ + int nreg_pnum; /* Lowest numbered plane in this region */ + int nreg_type; /* Type of tile that contains nreg_ll */ + Point nreg_ll; /* Lower-leftmost point in this region on + * plane nreg_pnum. We take the min first + * in X, then in Y. + */ + LabelList *nreg_labels; /* See LabRegion for description */ + CapValue nreg_cap; /* Capacitance to ground */ + ResValue nreg_resist; /* Resistance estimate */ + PerimArea nreg_pa[1]; /* Dummy; each node actually has + * ExtCurStyle->exts_numResistClasses + * array elements allocated to it. + */ +} NodeRegion; + + /* + * Transistor region: labelled region with perimeter and area. + * Used for each transistor in the flat extraction of a cell. + */ +typedef struct treg +{ + struct treg *treg_next; /* Next region in list */ + int treg_pnum; /* UNUSED */ + int treg_type; /* Type of tile that contains treg_ll */ + Point treg_ll; /* UNUSED */ + LabelList *treg_labels; /* Attribute list */ + Tile *treg_tile; /* Some tile in the channel */ + int treg_area; /* Area of channel */ +} TransRegion; + +typedef struct { /* Maintain plane information when pushing */ + Rect area; /* tiles on the node stack. For use with */ + int plane; /* function extNbrPushFunc(). */ +} PlaneAndArea; + +/* + * The following constructs a node name from the plane number 'n' + * and lower left Point l, and places it in the string 's' (which must + * be large enough). + */ +#define extMakeNodeNumPrint(buf, plane, coord) \ + (void) sprintf((buf), "%s_%s%d_%s%d#", DBPlaneShortName(plane), \ + ((coord).p_x < 0) ? "n": "", abs((coord).p_x), \ + ((coord).p_y < 0) ? "n": "", abs((coord).p_y)) + +/* Old way: cryptic numbers, but a bit shorter + * + * #define extMakeNodeNumPrint(s, n, l) \ + * (void) sprintf((s), "%d_%d_%d#", (n), extCoord((l).p_x), extCoord((l).p_y)) + * + * The following is used to map the full coordinate space into + * the positive integers, for constructing internally generated + * node names. + * + * #define extCoord(x) (((x) < 0) ? (1 - ((x) << 1)) : ((x) << 1)) + */ + +/* + * Argument passed to filter functions for finding regions. + */ +typedef struct +{ + TileTypeBitMask *fra_connectsTo; /* Array of TileTypeBitMasks. The + * element fra_connectsTo[t] has a + * bit set for each type that + * connects to 't'. + */ + CellDef *fra_def; /* Def being searched */ + int fra_pNum; /* Plane currently searching */ + ClientData fra_uninit; /* This value appears in the ti_client + * field of a tile if it's not yet + * been visited. + */ + Region *(*fra_first)(); /* Function to init new region */ + int (*fra_each)(); /* Function for each tile in region */ + Region *fra_region; /* Ptr to Region struct for current + * region. May be set by fra_first + * and used by fra_each. + */ +} FindRegion; + +#define TILEAREA(tp) ((TOP(tp) - BOTTOM(tp)) * (RIGHT(tp) - LEFT(tp))) + +/* -------------------- Perimeter of a region ------------------------- */ + +/* + * Segment of the boundary of a region whose perimeter + * is being traced by ExtTracePerimeter() and extEnumTilePerim(). + */ +typedef struct +{ + Tile *b_inside; /* Pointer to tile just inside segment */ + Tile *b_outside; /* Pointer to tile just outside segment */ + Rect b_segment; /* Actual coordinates of segment */ + unsigned char b_direction; /* Direction following segment (see below) */ + int b_plane; /* extract argument for extSideOverlap */ +} Boundary; + +#define BoundaryLength(bp) \ + ((bp)->b_segment.r_xtop - (bp)->b_segment.r_xbot \ + + (bp)->b_segment.r_ytop - (bp)->b_segment.r_ybot) + +/* Directions in which we can be following the boundary of a perimeter */ + +#define BD_LEFT 0 /* Inside is to right */ +#define BD_TOP 1 /* Inside is below */ +#define BD_RIGHT 2 /* Inside is to left */ +#define BD_BOTTOM 3 /* Inside is above */ + +/* -------- Yank buffers for hierarchical and array extraction -------- */ + +extern CellUse *extYuseCum; +extern CellDef *extYdefCum; + +/* --------------- Argument passed to extHierYankFunc ----------------- */ + +typedef struct +{ + Rect *hy_area; /* Area (in parent coordinates) to be yanked */ + CellUse *hy_target; /* Yank into this use */ + bool hy_prefix; /* If TRUE, prefix labels with use id */ +} HierYank; + +/* ----- Arguments to filter functions in hierarchical extraction ---- */ + + /* + * The following defines an extracted subtree. + * The CellUse et_use will be either a cell we are extracting, + * or a flattened subtree. If et_lookNames is non-NULL, it + * points to a CellDef that we should look in for node names. + */ +typedef struct extTree +{ + CellUse *et_use; /* Extracted cell, usually flattened */ + CellUse *et_realuse; /* If et_use is flattened, et_realuse + * points to the unflattened subtree's + * root use; otherwise it is NULL. + */ + CellDef *et_lookNames; /* See above */ + NodeRegion *et_nodes; /* List of nodes */ + HashTable et_coupleHash; /* Table for coupling capacitance. + * key is type CoupleKey + * value is pointer to type CapValue + */ + struct extTree *et_next; /* Next one in list */ +} ExtTree; + + /* + * The following structure contains information passed down + * through several levels of filter functions during hierarchical + * extraction. + * + * The procedure ha_nodename is used to map from a tile into the + * name of the node to which that tile belongs. It should be of + * the following format: + * + * char * + * proc(tp, et, ha) + * Tile *tp; + * ExtTree *et; + * HierExtractArg *ha; + * { + * } + * + * It should always return a non-NULL string; if the name of a + * node can't be determined, the string can be "(none)". + */ +typedef struct +{ + FILE *ha_outf; /* The .ext file being written */ + CellUse *ha_parentUse; /* Use pointing to the def being extracted */ + char *(*ha_nodename)();/* Map (tp, et, ha) into nodename; see above */ + ExtTree ha_cumFlat; /* Cumulative yank buffer */ + HashTable ha_connHash; /* Connections made during hier processing */ + +/* All areas are in parent coordinates */ + + Rect ha_interArea; /* Area of whole interaction being considered */ + Rect ha_clipArea; /* Only consider capacitance, perimeter, and + * area that come from inside this area. This + * rectangle is contained within ha_interArea. + */ + CellUse *ha_subUse; /* Root of the subtree being processed now */ + Rect ha_subArea; /* Area of ha_subUse inside the interaction + * area, i.e, contained within ha_interArea. + */ + Tile *hierOneTile; /* Used in ExtHier.c, tile from extHierOneFlat */ + int hierPNum; /* Used in ExtHier.c, plane of tile above */ + TileType hierType; /* Used in ExtHier.c, type of tile above */ + int hierPNumBelow; /* Used in ExtHier.c, plane of tile below */ +} HierExtractArg; + +/* + * Normally, nodes in overlapping subcells are expected to have labels + * in the area of overlap. When this is not the case, we have to use + * a much more expensive algorithm for finding the labels attached to + * the subcells' geometry in the overlap area. The following structure + * is used to hold information about the search in progress for such + * labels. + */ +typedef struct +{ + HierExtractArg *hw_ha; /* Describes context of search */ + Label *hw_label; /* We update hw_label with a ptr to a + * newly allocated label if successful. + */ + Rect hw_area; /* Area in parent coordinates of the + * area where we're searching. + */ + bool hw_autogen; /* If TRUE, we trace out all geometry + * in the first node in the first cell + * found to overlap the search area, + * and use the internal name for that + * node. + */ + TerminalPath hw_tpath; /* Hierarchical path down to label + * we are searching for, rooted at + * the parent being extracted. + */ + TileTypeBitMask hw_mask; /* Mask of tile types that connect to + * the tile whose node is to be found, + * and which are on the same plane. + * Used when calling ExtFindRegions. + */ + bool hw_prefix; /* If FALSE, we skip the initial + * use identifier when building + * hierarchical labels (as when + * extracting arrays; see hy_prefix + * in the HierYank struct). + */ + int (*hw_proc)(); +} HardWay; + +/* --------------------- Coupling capacitance ------------------------- */ + +/* + * The following structure is the hash key used for computing + * internodal coupling capacitance. Each word is a pointer to + * one of the nodes being coupled. By convention, the first + * word is the lesser of the two NodeRegion pointers. + */ +typedef struct +{ + NodeRegion *ck_1, *ck_2; +} CoupleKey; + +extern void extCoupleHashZero(); /* Clears out all pointers to data in table */ + +/* ------------------ Interface to debugging module ------------------- */ + +extern ClientData extDebugID; /* Identifier returned by the debug module */ + +/* ----------------- Technology-specific information ------------------ */ + +/* + * Structure used to define sidewall coupling capacitances. + */ +typedef struct edgecap +{ + struct edgecap *ec_next; /* Next edge capacitance rule in list */ + CapValue ec_cap; /* Capacitance (attofarads) */ + TileTypeBitMask ec_near; /* Types closest to causing edge, or in + * the case of sideOverlaps, the + * types we are overlapping. + */ + TileTypeBitMask ec_far; /* Types farthest from causing edge, or + * in the case of sideOverlaps, the + * types that shield the edge from + * the overlaped tile. + */ + int ec_plane; /* if ec_near is TT_SPACE, ec_plane */ + /* specifies which plane is to be */ + /* used. -1 if ec_near isn't space */ +} EdgeCap; + + +/* A type used to determine if current style needs planeorder or not */ +typedef enum { noPlaneOrder, needPlaneOrder, seenPlaneOrder } planeOrderStatus ; + +/* + * Because a large TT_MAXTYPES value quickly generates huge extract section + * structures, we want to keep around only the style names, and dynamically + * load and destroy the extract section values as needed, when doing an + * extraction command. + */ + +typedef struct extkeep +{ + struct extkeep *exts_next; + char *exts_name; +} ExtKeep; + +/* + * Parameters for the process being extracted. + * We try to use use integers here, rather than floats, to be nice to + * machines like Sun workstations that don't have hardware + * floating point. + * + * In the case of capacitances, though, we may have to use floats, depending + * upon the type CapValue. In some newer processes the capacitance per + * lambda^2 is less than 1 attofarad. + */ + +/*---------------------------------------------------------------*/ +/* Structure containing inter-layer information (NT x NT matrix) */ +/*---------------------------------------------------------------*/ + +typedef struct extinterlayerstyle +{ + /* + * Capacitance per unit perimeter. Sidewall capacitance depends both + * on the type inside the perimeter as well as the type outside it, + * so the table is doubly indexed by TileType. + * + * The mask exts_perimCapMask[t] contains bits for all those TileTypes + * 's' such that exts_perimCap[t][s] is nonzero. + */ + CapValue exts_perimCap; + + /* + * Both exts_overlapShieldTypes[][] and exts_overlapShieldPlanes[][] + * are indexed by the same pair of types used to index the table + * exts_overlapCap[][]; they identify the types and planes that + * shield capacitance between their index types. + */ + TileTypeBitMask exts_overlapShieldTypes; + int exts_overlapShieldPlanes; + + /* + * The table extOverlapCap[][] is indexed by two types to give the + * overlap coupling capacitance between them, per unit area. Only + * one of extOverlapCap[i][j] and extOverlapCap[j][i] should be + * nonzero. The capacitance to substrate of the tile of type 'i' + * is deducted when an overlap between i and j is detected, if + * extOverlapCap[i][j] is nonzero. This is only done, however, if + * tile i is below tile j in exts_planeOrder; + */ + CapValue exts_overlapCap; + + /* + * Sidewall coupling capacitance. This capacitance is between edges + * on the same plane, and is in units of attofarads. It is multiplied + * by the value interpolated from a fringing-field table indexed by the + * common length of the pair of edges divided by their separation: + * + * | | + * E1 +----------------------------+ + * ^ + * +--- distance between edges + * v + * +-----------------------------------+ E2 + * | | + * + * <-----------------------> length in common + */ + + /* + * The entry exts_sideCoupleCap[i][j] is a list of the coupling + * capacitance info between edges with type 'i' on the inside + * and 'j' on the outside, and other kinds of edges. + */ + EdgeCap *exts_sideCoupleCap; + + /* + * exts_sideCoupleOtherEdges[i][j] is a mask of those types on the + * far sides of edges to which an edge with 'i' on the inside and + * 'j' on the outside has coupling capacitance. + */ + TileTypeBitMask exts_sideCoupleOtherEdges; + /* + * The entry exts_sideOverlapCap[i][j] is a list of the coupling + * capacitance info between edges with type 'i' on the inside + * and 'j' on the outside, and other kinds of tiles on other + * planes. The ec_near mask in the EdgeCap record identifies the + * types to which we have sidewall overlap capacitance, and the + * ec_far mask identifies the types that shield the tiles preventing + * a capacitance. + */ + EdgeCap *exts_sideOverlapCap; + + /* + * extSideOverlapOtherTypes[i][j] is a mask of those types to which + * an edge with 'i' on the inside and 'j' on the outside has coupling + * capacitance. extSideOverlapOtherPlanes[i][j] is a mask of those + * planes to which edge [i][j] has overlap coupling capacitance. + * exts_sideOverlapShieldPlanes[s][t] is a list of the planes that + * need to be examined for shielding material when we are considering + * a sidewall overlap capacitor between types s and t. This may + * be the "or" of the planes needed by several sideoverlap rules, + * since there can be several types of edges in which type s is + * the "intype" member and the "outtype" member varies. Note that + * sideOverlapShieldPlanes is indexed like overlapShieldPlanes, not + * like sideOverlapOtherPlanes. + */ + int exts_sideOverlapOtherPlanes; + int exts_sideOverlapShieldPlanes; + TileTypeBitMask exts_sideOverlapOtherTypes; + +} ExtInterLayerStyle; + +/*-----------------------------------------------------------*/ +/* Structure containing per-layer information (1 x NT array) */ +/*-----------------------------------------------------------*/ + +typedef struct extlayerstyle +{ + /* + * Connectivity tables. + * Each table is an array of TileTypeBitMasks indexed by TileType. + * The i-th element of each array is a mask of those TileTypes + * to which type 'i' connects. + */ + + /* Everything is connected to everything else in this table */ + TileTypeBitMask exts_allConn; + + /* + * Connectivity for determining electrical nodes. + * This should be essentially the same as DBConnectTbl[]. + */ + TileTypeBitMask exts_nodeConn; + + /* + * Connectivity for determining resistive regions. + * Two types should be marked as connected here if + * they are both connected in exts_nodeConnect[], and + * if they both have the same resistance per square. + */ + TileTypeBitMask exts_resistConn; + + /* + * Connectivity for determining transistors. + * Each transistor type should connect only to itself. + * Nothing else should connect to anything else. + */ + TileTypeBitMask exts_transConn; + + /* + * Sheet resistivity for each tile type, in milli-ohms per square. + * For types that are transistors or capacitors, this corresponds + * to the sheet resistivity of the gate. + */ + + /* Maps from a tile type to the index of its sheet resistance entry */ + int exts_typeToResistClass; + + /* Gives a mask of neighbors of a type with different resistivity */ + TileTypeBitMask exts_typesResistChanged; + + /* + * Resistance information is also provided by the following tables: + * exts_typesByResistClass[] is an array of masks of those types + * having the same sheet resistivity, for each different value + * of sheet resistivity; exts_resistByResistClass[] is a parallel array + * giving the actual value of sheet resistivity. Both are indexed + * from 0 up to (but not including) exts_numResistClasses. + */ + TileTypeBitMask exts_typesByResistClass; + ResValue exts_resistByResistClass; + + /* Resistance per type */ + ResValue exts_sheetResist; + + /* + * Resistances for via holes. + * These have four parts: the size, border, and spacing + * of a minimum-size contact (it's assumed to be square), + * and the resistance of its via hole. The resistance is + * given in milliohms. + */ + int exts_viaSize; + int exts_viaSpacing; + int exts_viaBorder; + ResValue exts_viaResist; + + /* Layer height and thickness used by the geometry extractor */ + float exts_height; + float exts_thick; + + /* + * Capacitance to substrate for each tile type, in units of + * attofarads per square lambda. + */ + + /* + * Capacitance per unit area. This is zero for explicit capacitor + * types, which handle gate-channel capacitance specially. For + * transistor types, this is at best an approximation that is + * truly valid only when the transistor is switched off. + */ + CapValue exts_areaCap; + + TileTypeBitMask exts_perimCapMask; + + /* + * Overlap coupling capacitance for each pair of tile types, in units + * of attofarads per square lambda of overlap. + * Internodal capacitance due to overlap only occurs between tile + * types on different tile planes that are not shielded by intervening + * tiles. + */ + + /* + * The mask exts_overlapOtherPlanes[t] is a mask of the planes that + * must be searched for tiles having overlap capacitance with tiles + * of type 't', and exts_overlapOtherTypes[t] is a mask of the types + * with which our overlap capacitance is non-zero. + */ + TileTypeBitMask exts_overlapOtherTypes; + int exts_overlapOtherPlanes; + + /* + * Sidewall-overlap coupling capacitance. + * This is between an edge on one plane and a type on another plane + * that overlaps the edge (from the outside of the edge), and is in + * units of attofarads per lambda. + * + * When an edge with sidewall capacitance to substrate is found to + * overlap a type to which it has sidewall overlap capacitance, the + * original capacitance to substrate is replaced with the overlap + * capacitance to the tile overlapped, if the edge is above the tile + * being overlapped (according to ext_planeOrder). If the tiles are + * the other way around, then this replacement is not done. + */ + + /* + * The mask exts_sideEdges[i] is just a mask of those types j for + * which either exts_sideCoupleCap[i][j] or exts_sideOverlapCap[i][j] + * is non-empty. + */ + TileTypeBitMask exts_sideEdges; + + /* Transistors */ + + /* Name of each transistor type as output in .ext file */ + char *exts_transName; + + /* Device class */ + char exts_deviceClass; + + /* + * Per-square resistances for each possible transistor type, + * in the various regions that such a type might operate. + * The only operating region currently used is "linear", + * which the resistance extractor uses in its thresholding + * operation. NOTE: resistances in this table are in OHMS + * per square, not MILLIOHMS! + */ + HashTable exts_transResist; + ResValue exts_linearResist; + + /* + * Mask of the types of tiles that connect to the channel terminals + * of a transistor type. The intent is that these will be the + * diffusion terminals of a transistor, ie, its source and drain. + * UPDATED May, 2008: Record is a list of type masks, allowing + * multiple terminal types in the case of, e.g., high-voltage + * or other asymmetric devices. The last entry in the list should + * be equal to DBSpaceBits. + */ + TileTypeBitMask *exts_transSDTypes; + + /* + * Maximum number of terminals (source/drains) per transistor type. + * This table exists to allow the possibility of transistors with + * more than two diffusion terminals at some point in the future. + */ + int exts_transSDCount; + + /* Currently unused: gate-source capacitance per unit perimeter */ + CapValue exts_transSDCap; + + /* Currently unused: gate-channel capacitance per unit area */ + CapValue exts_transGateCap; + + /* + * Each type of transistor has a substrate node. By default, + * it is the one given by exts_transSubstrateName[t]. However, + * if the mask exts_transSubstrateTypes[t] is non-zero, and if + * the transistor overlaps material of one of the types in the + * mask, then the transistor substrate node is the node of the + * material it overlaps. + */ + char *exts_transSubstrateName; + TileTypeBitMask exts_transSubstrateTypes; + TileTypeBitMask exts_subsTransistorTypes; + + ExtInterLayerStyle *eils[NT]; /* inter-layer information */ + /* (dynamically allocated) */ +} ExtLayerStyle; + +/*-----------------------------------------------------------*/ +/* Structure containing per-plane information (1 x NP array) */ +/*-----------------------------------------------------------*/ + +typedef struct extplanestyle +{ + /* Specifies an ordering of the planes, so we can determine which + * tile is above another one. This is used only when determining + * if we should subtract capacitance to substrate for overlap and + * sideoverlap rules. If no planeorder is specified and the style + * does not contain a noplaneordering command a warning is issued + * and the default planeorder is used for the style. + */ + int exts_planeOrder; + /* + * The mask exts_overlapPlanes is a mask of those planes that must + * be searched for tiles having overlap capacitance, and the mask + * exts_overlapTypes[p] is those types having overlap capacitance + * on each plane p. The intent is that exts_overlapTypes[p] lists + * only those types t for which some entry of exts_overlapCap[t][s] + * is non-zero. + */ + TileTypeBitMask exts_overlapTypes; + + /* Common to both sidewall coupling and sidewall overlap */ + + /* + * exts_sideTypes[p] is a mask of those types 't' having sidewall + * coupling or sidewall overlap capacitance on plane p (i.e, for + * which a bin in exts_sideCoupleCap[t][] or exts_sideOverlapCap[t][] + * is non-empty), and exts_sidePlanes a mask of those planes containing + * tiles in exts_sideTypes[]. + */ + TileTypeBitMask exts_sideTypes; + +} ExtPlaneStyle; + +/*--------------------------------------------------------------*/ +/* Main extraction style information */ +/*--------------------------------------------------------------*/ + +typedef struct extstyle +{ + char exts_status; /* Loaded, not loaded, or pending */ + char *exts_name; /* Name of this style */ + + int exts_sidePlanes; + int exts_overlapPlanes; + + /* set/reset with planeorder commands to determine whether + * we will warn if no planeorder is specified. This is done + * because at Stanford we use a lot of diagnostic extraction + * styles (for floating wells etc.) and we don't want to specify + * the planeorder for each and every one of them. + */ + + planeOrderStatus exts_planeOrderStatus; + + /* + * We search out a distance exts_sideCoupleHalo from each edge + * for other types with which we have coupling capacitance. + * This value determines how much extra gets yanked when + * computing hierarchical adjustments, so should be kept + * small to insure reasonable performance. + */ + int exts_sideCoupleHalo; + + int exts_numResistClasses; + + /* Scaling */ + /* + * Step size used when breaking up a large cell for interaction + * checks during hierarchical extraction. We check exts_stepSize + * by exts_stepSize chunks for interactions one at a time. + */ + int exts_stepSize; + + /* + * Number of linear units per lambda. All perimeter dimensions + * that we output to the .ext file should be multiplied by + * exts_unitsPerLambda; we produce a "scale" line in the .ext file + * indicating this. All area dimensions should be multiplied + * by exts_unitsPerLambda**2. + * (changed to type float May 11, 2006 to accommodate, e.g., 90 + * and 130 nm technologies) + */ + float exts_unitsPerLambda; + + /* + * Scaling for resistance and capacitance. + * All resistances in the .ext file should be multiplied by + * exts_resistScale to get milliohms, and all capacitances by + * exts_capScale to get attofarads. These numbers appear in + * the "scale" line in the .ext file. + */ + int exts_capScale; + int exts_resistScale; + + /* Contains one for each type of fet, zero for all other types */ + TileTypeBitMask exts_transMask; + + ExtLayerStyle *els[NT]; /* Per-layer information (allocated) */ + ExtPlaneStyle *eps[NP]; /* Per-plane information (allocated) */ + +} ExtStyle; + +#define EXT_PLUG_GND 1 +#define EXT_PLUG_VDD 2 + +extern ExtStyle *ExtCurStyle; + +/* ------------------- Hierarchical node merging ---------------------- */ + +/* + * Table used to hold all merged nodes during hierarchical extraction. + * Used for duplicate suppression. + */ +extern HashTable extHierMergeTable; + +/* + * Each hash entry in the above table points to a NodeName struct. + * Each NodeName points to the Node corresponding to that name. + * Each Node points back to a list of NodeNames that point to that + * Node, and which are linked together along their nn_next fields. + */ +typedef struct nn +{ + struct node *nn_node; /* Node for which this is a name */ + char *nn_name; /* Text of name */ + struct nn *nn_next; /* Other names of nn_node */ +} NodeName; + +typedef struct node +{ + NodeName *node_names; /* List of names for this node. The first name + * in the list is the "official" node name. + */ + CapValue node_cap; /* Capacitance to substrate */ + PerimArea node_pa[1]; /* Dummy; each node actually has + * ExtCurStyle->exts_numResistClasses + * array elements allocated to it. + */ +} Node; + +/* -------------------------------------------------------------------- */ + +/* + * Value normally resident in the ti_client field of a tile, + * indicating that the tile has not yet been visited in a + * region search. + */ +extern ClientData extUnInit; + +#define extGetRegion(tp) ( (tp)->ti_client ) +#define extHasRegion(tp,und) ( (tp)->ti_client != (und) ) + + +/* For non-recursive flooding algorithm */ +#define VISITPENDING ((ClientData) NULL) /* Marks tiles on stack */ + +#ifdef NONMANHATTAN + +/* Note that this macro depends on MAXPLANES being small */ +/* compared to the bit position of TT_SIDE. Since tens of */ +/* thousands of planes is inconceivable, this should not be a */ +/* problem. It is necessary to push the tile's TT_SIDE bit */ +/* because the search algorithm can overwrite it between the */ +/* time the tile is pushed and the time that it is popped. */ + +#define PUSHTILE(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)(pointertype)(pl | \ + ((TileType)(spointertype)(tp)->ti_body & TT_SIDE)), extNodeStack); \ + STACKPUSH((ClientData)(pointertype)tp, extNodeStack) + +#define POPTILE(tp, pl) \ + tp = (Tile *) STACKPOP(extNodeStack); \ + pl = (spointertype) STACKPOP(extNodeStack); \ + if (pl & TT_SIDE) { \ + TiSetBody((tp), TiGetTypeExact(tp) | TT_SIDE); \ + pl &= (~TT_SIDE); \ + } \ + else \ + TiSetBody((tp), TiGetTypeExact(tp) & (~TT_SIDE)) + +/* Variations of "pushtile" to force a specific value on TT_SIDE */ + +#define PUSHTILEBOTTOM(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)(pointertype)(pl | \ + ((SplitDirection(tp)) ? 0 : TT_SIDE)), extNodeStack) ;\ + STACKPUSH((ClientData)(pointertype)tp, extNodeStack) + +#define PUSHTILETOP(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)(pointertype)(pl | \ + ((SplitDirection(tp)) ? TT_SIDE : 0)), extNodeStack) ;\ + STACKPUSH((ClientData)(pointertype)tp, extNodeStack) + +#define PUSHTILELEFT(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)(pointertype)(pl), extNodeStack); \ + STACKPUSH((ClientData)(pointertype)tp, extNodeStack) + +#define PUSHTILERIGHT(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)(pointertype)(pl | TT_SIDE), extNodeStack); \ + STACKPUSH((ClientData)(pointertype)tp, extNodeStack) + +#else + +#define PUSHTILE(tp, pl) \ + (tp)->ti_client = VISITPENDING; \ + STACKPUSH((ClientData)pl, extNodeStack); \ + STACKPUSH((ClientData)tp, extNodeStack) + +#define POPTILE(tp, pl) \ + tp = (Tile *) STACKPOP(extNodeStack); \ + pl = (int) STACKPOP(extNodeStack) + +#endif + +/* ------------------------- Region finding --------------------------- */ + +extern Region *ExtFindRegions(); + +/* Filter functions for ExtFindRegions() */ +extern Region *extTransFirst(); extern int extTransEach(); +extern Region *extResFirst(); extern int extResEach(); +extern Region *extNodeFirst(); extern int extNodeEach(); +extern Region *extHierLabFirst(); extern int extHierLabEach(); + +/* -------- Search for matching tile/node in another ExtTree ---------- */ + +/* + * NODETOTILE(np, et, tp) + * NodeRegion *np; + * ExtTree *et; + * Tile *tp; + * + * Sets tp to be the tile containing the lower-leftmost point of the + * NodeRegion *np, but in the tile planes of the ExtTree *et instead + * of the tile planes originally containing *np. + */ +#define NODETOTILE(np, et, tp) \ + if (1) { \ + Plane *myplane = (et)->et_use->cu_def->cd_planes[(np)->nreg_pnum]; \ +\ + (tp) = myplane->pl_hint; \ + GOTOPOINT(tp, &(np)->nreg_ll); \ + myplane->pl_hint = (tp); \ + } + +/* + * NODETONODE(nold, et, nnew) + * NodeRegion *nold; + * ExtTree *et; + * NodeRegion *nnew; + * + * Like NODETOTILE above, but leaves nnew pointing to the node associated + * with the tile we find. + */ +#define NODETONODE(nold, et, nnew) \ + if (1) { \ + Tile *tp; \ + \ + (nnew) = (NodeRegion *) NULL; \ + NODETOTILE((nold), (et), tp); \ + if (tp && extHasRegion(tp, extUnInit)) \ + (nnew) = (NodeRegion *) extGetRegion(tp); \ + } + +/* -------------------- Miscellaneous procedures ---------------------- */ + +extern char *extNodeName(); +extern NodeRegion *extBasic(); +extern NodeRegion *extFindNodes(); +extern ExtTree *extHierNewOne(); +extern int extNbrPushFunc(); + +/* --------------------- Miscellaneous globals ------------------------ */ + +extern int extNumFatal; /* Number fatal errors encountered so far */ +extern int extNumWarnings; /* Number warning messages so far */ +extern CellUse *extParentUse; /* Dummy use for def being extracted */ +extern ClientData extNbrUn; /* Ditto */ + + /* + * This is really a (Stack *), but we use the struct tag to avoid + * having to include stack.h in every .c file. Used in the non-recursive + * flooding algorithm. + */ +extern struct stack *extNodeStack; + +/* ------------------ Connectivity table management ------------------- */ + +/* + * The following is true if tile types 'r' and 's' are connected + * according to the connectivity table 'tbl' + */ +#define extConnectsTo(r, s, tbl) ( TTMaskHasType(&(tbl)[(r)], (s)) ) + +/* -------------------------------------------------------------------- */ + +#include "extDebugInt.h" + +#endif /* _EXTRACTINT_H */ diff --git a/garouter/Depend b/garouter/Depend new file mode 100644 index 00000000..db36861d --- /dev/null +++ b/garouter/Depend @@ -0,0 +1,46 @@ +gaChannel.o: gaChannel.c ../utils/magic.h ../utils/geometry.h \ + ../utils/hash.h ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../windows/windows.h ../utils/main.h ../dbwind/dbwind.h \ + ../utils/signals.h ../netmenu/netmenu.h ../gcr/gcr.h ../router/router.h \ + ../grouter/grouter.h ../grouter/grouteDebug.h ../garouter/garouter.h \ + ../garouter/gaDebug.h ../utils/netlist.h ../textio/textio.h \ + ../utils/styles.h ../debug/debug.h +gaMain.o: gaMain.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../windows/windows.h ../utils/main.h ../dbwind/dbwind.h \ + ../utils/signals.h ../netmenu/netmenu.h ../gcr/gcr.h ../router/router.h \ + ../grouter/grouter.h ../grouter/grouteDebug.h ../garouter/garouter.h \ + ../garouter/gaDebug.h ../utils/netlist.h ../textio/textio.h \ + ../debug/debug.h ../drc/drc.h +gaMaze.o: gaMaze.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/heap.h ../utils/undo.h ../tiles/tile.h ../database/database.h \ + ../windows/windows.h ../utils/main.h ../dbwind/dbwind.h \ + ../utils/signals.h ../netmenu/netmenu.h ../gcr/gcr.h ../router/router.h \ + ../grouter/grouter.h ../grouter/grouteDebug.h ../garouter/garouter.h \ + ../garouter/gaDebug.h gaInternal.h ../utils/netlist.h ../textio/textio.h \ + ../utils/styles.h ../utils/malloc.h ../drc/drc.h ../debug/debug.h \ + ../utils/list.h ../mzrouter/mzrouter.h +gaSimple.o: gaSimple.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../utils/hash.h ../utils/heap.h ../tiles/tile.h \ + ../database/database.h ../windows/windows.h ../utils/main.h \ + ../dbwind/dbwind.h ../utils/signals.h ../netmenu/netmenu.h ../gcr/gcr.h \ + ../router/router.h ../grouter/grouter.h ../grouter/grouteDebug.h \ + ../garouter/garouter.h ../garouter/gaDebug.h ../utils/netlist.h \ + ../textio/textio.h ../utils/styles.h ../utils/malloc.h ../drc/drc.h \ + ../debug/debug.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h +gaStem.o: gaStem.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../windows/windows.h ../utils/main.h ../dbwind/dbwind.h \ + ../utils/signals.h ../netmenu/netmenu.h ../gcr/gcr.h ../router/router.h \ + ../grouter/grouter.h ../grouter/grouteDebug.h ../garouter/garouter.h \ + ../garouter/gaDebug.h gaInternal.h ../utils/netlist.h ../textio/textio.h \ + ../utils/styles.h ../utils/malloc.h ../drc/drc.h ../debug/debug.h +gaTest.o: gaTest.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../utils/signals.h ../textio/textio.h ../debug/debug.h ../gcr/gcr.h \ + ../router/router.h ../grouter/grouter.h ../grouter/grouteDebug.h \ + ../graphics/graphics.h ../garouter/garouter.h ../garouter/gaDebug.h \ + ../windows/windows.h ../dbwind/dbwind.h ../textio/txcommands.h \ + ../utils/main.h ../utils/utils.h ../commands/commands.h \ + ../utils/styles.h diff --git a/garouter/Makefile b/garouter/Makefile new file mode 100644 index 00000000..5eaa8ede --- /dev/null +++ b/garouter/Makefile @@ -0,0 +1,11 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/garouter/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +MODULE = garouter +MAGICDIR = .. +SRCS = gaChannel.c gaMain.c gaMaze.c gaSimple.c gaStem.c \ + gaTest.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/garouter/OUTLINE b/garouter/OUTLINE new file mode 100644 index 00000000..16738763 --- /dev/null +++ b/garouter/OUTLINE @@ -0,0 +1,36 @@ +Gate-array router. +This is an initial version tuned specifically for the AMCC 3500 +gate-array, intended mainly to develop experience in gate-array +routing. It is intended that this form the foundation for a +more general-purpose routing system integrated with the other +Magic routing tools. + +Overall structure: +----------------- + - Build netlist (just like in router module) + - Channel generation: + Differences from Magic router: + - Channels are provided by the user rather than being + generated automatically. There are commands of the + several forms: + + garoute channel xlo ylo xhi yhi + Define a general-purpose routing channel + + garoute channel xlo ylo xhi yhi [horizontal | vertical] + Define either a horizontal or a vertical + river-routing region + + - Channels are cleared by + garoute clear + + - Terminals can appear inside river-routing channels. + + - Terminal pin assignment: + Simply assign each pin to both sides of the channel, making + certain that there isn't already a pin in the way. Assign + edge pins to the channel side that is nearest. If pins are + not already aligned, we will do stem generation; it's up to + the user to leave enough room in the channels. + + - Global routing: diff --git a/garouter/TODO b/garouter/TODO new file mode 100644 index 00000000..4fb13c85 --- /dev/null +++ b/garouter/TODO @@ -0,0 +1,18 @@ +TO DO: +----- +Eliminate unnecessary stuff from router module, particularly user channel + definition using labels. +Via minimization. + +TEST: +---- +Temporary hack: mechanism to use pre-routed stems provided by AMCC + (possibly an "alias" command to the router that sets up a table + mapping terminal names in the netlist to new names). +Check for blockages in the channel; eliminate blocked layers from the + list of layers we try to connect to during stem generation. +Stem generation: be generous in allowing stems to use above grid + lines as well as below. + + + diff --git a/garouter/gaChannel.c b/garouter/gaChannel.c new file mode 100644 index 00000000..828f8364 --- /dev/null +++ b/garouter/gaChannel.c @@ -0,0 +1,629 @@ +/* + * gaChannel.c - + * + * Channel management for the gate-array router. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/garouter/gaChannel.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "netmenu/netmenu.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "garouter/garouter.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "utils/styles.h" +#include "debug/debug.h" + +/* List of all active channels */ +GCRChannel *gaChannelList = NULL; + +/* Def used to hold channel plane */ +CellDef *gaChannelDef = NULL; + +/* Forward declarations */ +int gaSplitTile(); +int gaSetClient(); +void gaChannelStats(); +void gaPinStats(); +void gaPropagateBlockages(); +void gaInitRiverBlockages(); + +#define CNULL ((ClientData) NULL) + +int gaTotNormCross, gaTotRiverCross, gaClearNormCross, gaClearRiverCross; + + +/* + * ---------------------------------------------------------------------------- + * + * GAChannelInitOnce -- + * + * Once-only channel initialization for the gate-array router. + * + * Results: + * None. + * + * Side effects: + * Allocates the tile plane used to hold channel information, + * RtrChannelPlane. + * + * ---------------------------------------------------------------------------- + */ + +void +GAChannelInitOnce() +{ + if (gaChannelDef == NULL) + gaChannelDef = RtrFindChannelDef(); + RtrChannelPlane = gaChannelDef->cd_planes[PL_DRC_ERROR]; + GAClearChannels(); +} + +/* + * ---------------------------------------------------------------------------- + * + * GAClearChannels -- + * + * Clear any pre-existing channels in preparation for definition of + * new ones. + * + * Results: + * None. + * + * Side effects: + * Paints TileType 1 (blocked) over the tile plane that records all + * available channel area, and frees all channel structures. + * + * ---------------------------------------------------------------------------- + */ + +void +GAClearChannels() +{ + GCRChannel *ch; + Rect r; + + r.r_xbot = TiPlaneRect.r_xbot / 2; + r.r_ybot = TiPlaneRect.r_ybot / 2; + r.r_xtop = TiPlaneRect.r_xtop / 2; + r.r_ytop = TiPlaneRect.r_ytop / 2; + SigDisableInterrupts(); + (void) DBPaintPlane(RtrChannelPlane, &r, DBStdWriteTbl(1), + (PaintUndoInfo *) NULL); + for (ch = gaChannelList; ch; ch = ch->gcr_next) + GCRFreeChannel(ch); + gaChannelList = (GCRChannel *) NULL; + SigEnableInterrupts(); +} + +/* + * ---------------------------------------------------------------------------- + * + * GADefineChannel -- + * + * Add a new channel definition to the list of channels we know + * about. First ensure that the channel boundaries are correctly + * aligned (round down if they aren't) and also that the area of + * this channel has not already been assigned to another channel. + * + * The parameter chanType is one of 0 (for an ordinary channel), + * CHAN_HRIVER (for a horizontal river-routing channel), or CHAN_VRIVER + * (for a vertical river-routing channel). + * + * The rectangle 'r' gives the area of the channel. + * + * Results: + * TRUE on success, FALSE on failure. + * + * Side effects: + * Paints the area of this channel into RtrChannelPlane (as space) + * to mark that this area is used. + * + * ---------------------------------------------------------------------------- + */ + +bool +GADefineChannel(chanType, r) + int chanType; + Rect *r; +{ + int length, width, halfGrid = RtrGridSpacing / 2; + GCRChannel *ch; + Point origin; + Rect r2; + + /* + * Make the channel boundaries lie halfway between grid lines. + * To ensure consistent results when RtrGridSpacing is odd, + * we always subtract halfGrid from a grid line. + */ + r2 = *r; + r->r_xbot = RTR_GRIDUP(r->r_xbot, RtrOrigin.p_x) - halfGrid; + r->r_ybot = RTR_GRIDUP(r->r_ybot, RtrOrigin.p_y) - halfGrid; + r->r_xtop = RTR_GRIDDOWN(r->r_xtop, RtrOrigin.p_x) + RtrGridSpacing + - halfGrid; + r->r_ytop = RTR_GRIDDOWN(r->r_ytop, RtrOrigin.p_y) + RtrGridSpacing + - halfGrid; + + if (r2.r_xbot != r->r_xbot || r2.r_ybot != r->r_ybot + || r2.r_xtop != r->r_xtop || r2.r_ytop != r->r_ytop) + { + TxPrintf("Rounding channel to center-grid alignment: "); + TxPrintf("ll=(%d,%d) ur=(%d,%d)\n", + r->r_xbot, r->r_ybot, r->r_xtop, r->r_ytop); + } + + /* Ensure no overlap */ + if (DBSrPaintArea((Tile *) NULL, RtrChannelPlane, r, &DBSpaceBits, + gaAlwaysOne, (ClientData) NULL)) + { + TxError("Channel ll=(%d,%d) ur=(%d,%d) overlaps existing channels\n", + r->r_xbot, r->r_ybot, r->r_xtop, r->r_ytop); + return (FALSE); + } + + if (DebugIsSet(gaDebugID, gaDebShowChans)) + DBWFeedbackAdd(r, "Channel area", EditCellUse->cu_def, + 1, STYLE_OUTLINEHIGHLIGHTS); + + /* Paint it into the channel plane */ + SigDisableInterrupts(); + (void) DBPaintPlane(RtrChannelPlane, r, DBStdWriteTbl(TT_SPACE), + (PaintUndoInfo *) NULL); + + /* Allocate the new channel */ + RtrChannelBounds(r, &length, &width, &origin); + ch = GCRNewChannel(length, width); + ch->gcr_area = *r; + ch->gcr_origin = origin; + ch->gcr_type = chanType; + + /* Link it in with the pre-existing list */ + ch->gcr_next = gaChannelList; + gaChannelList = ch; + SigEnableInterrupts(); + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaChannelInit -- + * + * Called immediately prior to routing to set up lots of useful + * information in channels: + * + * Tile plane initialization: + * - Carve up the tile plane so each channel corresponds to a + * single space tile, and unavailable areas correspond to + * tiles of type 1. + * - Make the ti_client fields of tiles in the channel plane + * point to their corresponding channels. + * + * Obstacle initialization: + * - Initialize the obstacle and hazard maps for each channel. + * Identify pins too close to two-layer blockages and mark + * them as already taken (by net GCR_BLOCKEDNETID). + * - For river-routing channels, ensure that pairs of pins + * can be river-routed to each other; if not, mark both + * as unavailable. + * + * Pin initialization (including stem assignment): + * - Fill in the global-routing information in the channel + * structure. Specifically, set gcr_ch, gcr_side, gcr_linked, + * and gcr_point for each GCRPin. Link available pins for + * each side of the channel into a doubly-linked list so + * they can be visited easily during global routing. + * + * Results: + * None. + * + * Side effects: + * Fills in a lot of information in the channel structures. + * + * ---------------------------------------------------------------------------- + */ + +void +gaChannelInit(list, routeUse, netList) + GCRChannel *list; /* List of channels to process */ + CellUse *routeUse; /* Cell being routed (searched for obstacles) */ + NLNetList *netList; /* Netlist being routed */ +{ + GCRChannel *ch; + + RtrMilestoneStart("Obstacle map initialization"); + for (ch = list; ch && !SigInterruptPending; ch = ch->gcr_next) + { + /* Ensure that no channel tiles cross channel boundaries */ + while (DBSrPaintArea((Tile *) NULL, RtrChannelPlane, &ch->gcr_area, + &DBAllTypeBits, gaSplitTile, (ClientData) &ch->gcr_area)) + /* Nothing */; + + /* Obstacle initialization */ + RtrMilestonePrint(); + RtrChannelObstacles(routeUse, ch); + if (ch->gcr_type == CHAN_NORMAL) + RtrChannelDensity(ch); + RtrChannelCleanObstacles(ch); + } + RtrMilestoneDone(); + + /* + * Set all ti_client fields in the channel plane to NULL, and then + * for each channel set the ti_client fields of the tiles it overlaps + * to point back to that channel. + */ + (void) DBSrPaintArea((Tile *) NULL, RtrChannelPlane, &TiPlaneRect, + &DBAllTypeBits, gaSetClient, (ClientData) NULL); + for (ch = list; ch && !SigInterruptPending; ch = ch->gcr_next) + (void) DBSrPaintArea((Tile *) NULL, RtrChannelPlane, &ch->gcr_area, + &DBAllTypeBits, gaSetClient, (ClientData) ch); + if (SigInterruptPending) + return; + + /* + * Pin initialization. + * This fills in a bunch of information needed for global + * routing in each pin along each channel boundary. + */ + for (ch = list; ch && !SigInterruptPending; ch = ch->gcr_next) + RtrPinsInit(ch); + + /* + * Pick the actual pin locations for terminals. + * This comes here because it needs the blockage and gcr_linked + * information set above. However, it must precede marking + * pairs of river-routing crossings as unavailable, since + * these pairs are only marked unavailable for routes across + * the channel. They may still be usable as stem tips, so + * we can't block them until after stems have been assigned. + */ + gaStemAssignAll(routeUse, netList); + if (SigInterruptPending) + return; + + /* + * Now mark pairs of river-routing crossings as unavailable. + * A crossing is unavailable if a straight-across from one side + * of the channel to the other on a single layer is impossible. + * Propagate these blockages.. + */ + for (ch = list; ch && !SigInterruptPending; ch = ch->gcr_next) + if (ch->gcr_type != CHAN_NORMAL) + gaInitRiverBlockages(routeUse, ch); + gaPropagateBlockages(list); + if (SigInterruptPending) + return; + + /* + * Hazard initialization. + * This has to happen after blockages have been propagated. + */ + RtrMilestoneStart("Hazard initialization"); + for (ch = list; ch && !SigInterruptPending; ch = ch->gcr_next) + if (ch->gcr_type == CHAN_NORMAL) + { + RtrHazards(ch); + RtrMilestonePrint(); + } + RtrMilestoneDone(); + + /* + * Link all the available pins along each side of each + * channel into a linked list. Only unblocked pins with + * non-NULL gcr_linked pins are linked into this list. + * Since pins taken as stem tips by gaAssignPins above + * were marked, these lists don't include any pins that + * are stem tips. + */ + for (ch = list; ch && !SigInterruptPending; ch = ch->gcr_next) + RtrPinsLink(ch); + if (DebugIsSet(gaDebugID, gaDebChanStats)) + gaChannelStats(list); +} + +void +gaChannelStats(list) + GCRChannel *list; +{ + GCRChannel *ch; + int *tot, *clear, numTot, numClear; + double fNorm, fRiver, fTot; + + gaTotNormCross = 0; + gaTotRiverCross = 0; + gaClearNormCross = 0; + gaClearRiverCross = 0; + + for (ch = list; ch; ch = ch->gcr_next) + { + switch (ch->gcr_type) + { + case CHAN_NORMAL: + tot = &gaTotNormCross; + clear = &gaClearNormCross; + break; + case CHAN_HRIVER: + case CHAN_VRIVER: + tot = &gaTotRiverCross; + clear = &gaClearRiverCross; + break; + } + gaPinStats(ch->gcr_tPins, ch->gcr_length, tot, clear); + gaPinStats(ch->gcr_bPins, ch->gcr_length, tot, clear); + gaPinStats(ch->gcr_lPins, ch->gcr_width, tot, clear); + gaPinStats(ch->gcr_rPins, ch->gcr_width, tot, clear); + } + + numTot = gaTotRiverCross + gaTotNormCross; + numClear = gaClearRiverCross + gaClearNormCross; + fRiver = ((double) gaClearRiverCross / (double) gaTotRiverCross) * 100.0; + fNorm = ((double) gaClearNormCross / (double) gaTotNormCross) * 100.0; + fTot = ((double) numClear / (double) numTot) * 100.0; + TxPrintf("Total pins: %d, clear: %d (%.1f%%)\n", numTot, numClear, fTot); + TxPrintf("Norm chan pins: %d, clear: %d (%.1f%%)\n", gaTotNormCross, + gaClearNormCross, fNorm); + TxPrintf("River chan pins: %d, clear: %d (%.1f%%)\n", gaTotRiverCross, + gaClearRiverCross, fRiver); +} + +void +gaPinStats(pins, nPins, pTot, pClear) + GCRPin *pins; + int nPins; + int *pTot, *pClear; +{ + GCRPin *pin, *pend; + + pin = &pins[1]; + pend = &pins[nPins]; + for ( ; pin <= pend; pin++) + { + *pTot += 1; + if (pin->gcr_linked && pin->gcr_pId == (GCRNet *) NULL + && pin->gcr_linked->gcr_pId == (GCRNet *) NULL) + { + *pClear += 1; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * gaPropagateBlockages -- + * + * If a pin is blocked on one side of a channel BOUNDARY, + * it is blocked on the other side as well. If a pin on + * one side of a river-routing CHANNEL is blocked, the pin + * on the other side gets blocked too. Several iterations + * may be necessary to propagate blockages across all + * channel boundaries and river-routing channels. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +gaPropagateBlockages(list) + GCRChannel *list; +{ + GCRChannel *ch; + bool changed; + + do + { + changed = FALSE; + for (ch = list; ch; ch = ch->gcr_next) + if (RtrPinsBlock(ch)) + changed = TRUE; + } while (changed); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaSetClient -- + * + * Called for each tile overlapping ch->gcr_area to set the + * client pointer for that tile to 'cdata'. + * + * Results: + * Always returns 0. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +gaSetClient(tile, cdata) + Tile *tile; + ClientData cdata; +{ + tile->ti_client = (ClientData) cdata; + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaSplitTile -- + * + * Called for each tile overlapping the area of a channel (the Rect 'r'), + * we ensure that no tiles cross the channel boundary. If one does, we + * split it at the boundary and return 1. + * + * Results: + * Returns 1 if tile was split, or 0 if no split occurred. + * We return 1 to ensure that DBSrPaintArea doesn't get + * confused from our having modified the tile plane. + * + * Side effects: + * May split 'tile'; if it does, we return 1. + * + * ---------------------------------------------------------------------------- + */ + +int +gaSplitTile(tile, r) + Tile *tile; + Rect *r; +{ + Tile *tp; + ASSERT(TiGetType(tile) == TT_SPACE, "gaSplitTile"); + + if (TOP(tile) > r->r_ytop) + { + tp = TiSplitY(tile, r->r_ytop); + TiSetBody(tp, TT_SPACE); + return (1); + } + if (BOTTOM(tile) < r->r_ybot) + { + tp = TiSplitY(tile, r->r_ybot); + TiSetBody(tp, TT_SPACE); + return (1); + } + if (LEFT(tile) < r->r_xbot) + { + tp = TiSplitX(tile, r->r_xbot); + TiSetBody(tp, TT_SPACE); + return (1); + } + if (RIGHT(tile) > r->r_xtop) + { + tp = TiSplitX(tile, r->r_xtop); + TiSetBody(tp, TT_SPACE); + return (1); + } + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaInitRiverBlockages -- + * + * The channel 'ch' is a river-routing channel (ch->gcr_type is either + * CHAN_HRIVER or CHAN_VRIVER). These channels can only be routed + * across in a single direction (horizontally for CHAN_HRIVER, or + * vertically for CHAN_VRIVER). + * + * If pins have already been taken by terminals (as stem tips), we + * don't mark them as blocked. + * + * Results: + * None. + * + * Side effects: + * Marks pairs of pins on the channel boundary as blocked if + * a river-route across the channel is not possible along + * the track that runs between the pin pair. Blocked pins + * have a special gcr_pId of GCR_BLOCKEDNETID to mark them as + * "in use". + * + * ---------------------------------------------------------------------------- + */ + +void +gaInitRiverBlockages(routeUse, ch) + CellUse *routeUse; + GCRChannel *ch; +{ + GCRPin *p1, *p2; + int n, nPins, coord; + SearchContext scx; + + switch (ch->gcr_type) + { + case CHAN_HRIVER: + p1 = &ch->gcr_lPins[1]; + p2 = &ch->gcr_rPins[1]; + nPins = ch->gcr_width; + scx.scx_area.r_xbot = ch->gcr_area.r_xbot; + scx.scx_area.r_xtop = ch->gcr_area.r_xtop; + coord = ch->gcr_origin.p_y + RtrGridSpacing; + break; + case CHAN_VRIVER: + p1 = &ch->gcr_tPins[1]; + p2 = &ch->gcr_bPins[1]; + nPins = ch->gcr_length; + scx.scx_area.r_ybot = ch->gcr_area.r_ybot; + scx.scx_area.r_ytop = ch->gcr_area.r_ytop; + coord = ch->gcr_origin.p_x + RtrGridSpacing; + break; + } + + scx.scx_use = routeUse; + scx.scx_trans = GeoIdentityTransform; + for (n = 1; n <= nPins; n++, p1++, p2++, coord += RtrGridSpacing) + { + switch (ch->gcr_type) + { + case CHAN_HRIVER: + scx.scx_area.r_ybot = coord - RtrSubcellSepUp; + scx.scx_area.r_ytop = coord + RtrSubcellSepDown; + break; + case CHAN_VRIVER: + scx.scx_area.r_xbot = coord - RtrSubcellSepUp; + scx.scx_area.r_xtop = coord + RtrSubcellSepDown; + break; + } + + /* + * If obstacles to both routing layers are found, + * then block this pair of crossing points if they + * aren't already taken. + */ + if (DBTreeSrTiles(&scx, &RtrMetalObstacles, 0, gaAlwaysOne, CNULL) + && DBTreeSrTiles(&scx, &RtrPolyObstacles, 0, gaAlwaysOne, CNULL)) + { + if (p1->gcr_pId == (GCRNet *) NULL) p1->gcr_pId = GCR_BLOCKEDNETID; + if (p2->gcr_pId == (GCRNet *) NULL) p2->gcr_pId = GCR_BLOCKEDNETID; + } + } + +} + +int +gaAlwaysOne() +{ + return (1); +} diff --git a/garouter/gaDebug.h b/garouter/gaDebug.h new file mode 100644 index 00000000..e19af70c --- /dev/null +++ b/garouter/gaDebug.h @@ -0,0 +1,34 @@ +/* + * gaDebug.h -- + * + * Definitions of debugging flags for the gate-array router. + * This is a separate include file so that new debugging flags + * can be added to it without forcing recompilation of the + * entire module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/garouter/gaDebug.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + + /* Flags */ +extern int gaDebChanOnly; +extern int gaDebChanStats; +extern int gaDebMaze; +extern int gaDebNoSimple; +extern int gaDebPaintStems; +extern int gaDebShowChans; +extern int gaDebShowMaze; +extern int gaDebStems; +extern int gaDebVerbose; +extern int gaDebNoClean; diff --git a/garouter/gaInternal.h b/garouter/gaInternal.h new file mode 100644 index 00000000..5b969991 --- /dev/null +++ b/garouter/gaInternal.h @@ -0,0 +1,99 @@ +/* + * gaInternal.h -- + * + * This file defines data structures and constantds and declares + * variables INTERNAL TO THE GAROUTER. + * but shard by two or more soruce files. + * * + * Structures etc. that are exported by the irouter are defined in + * irouter.h. + * + * Structures etc. that are local to a given source + * file are declared at the top of that source file. + * + * Structures, etc., specific to a given function are usually defined at + * the head of that function. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/garouter/gaInternal.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _GAINTERNAL_H +#define _GAINTERNAL_H + +#include "database/database.h" + +/* Sets limit on amount of searching before mzrouter gives up during + * stem generation. The idea is not to waste time on routes that + * fail. The number is the maximum number of "blooms" permit during + * searching. See mzrouter documentation for details. + */ +#define MAZE_TIMEOUT 100; +/* + * Netlist structure. + * This is similar to the netlist structures defined in the netmenu + * package, but contains enough additional information that we + * maintain our own here. + * + * Each netlist consists of a set of Net structures. These + * point to a list of Terms that belong to the net. + */ + + /* + * A Term is a point from which routing proceeds. + * It is possible for the same label to appear at several different + * places in a cell. We assume that these points are connected + * internally, and so only route to one. The one we choose for + * routing appears on the net_terms list; all other Terms appear + * on the term_others list. + */ +typedef struct term +{ + Rect term_loc; /* Connect to anywhere in this area */ + TileType term_layer; /* What type of material */ + char *term_name; /* Pointer to HashEntry key, or NULL */ + struct net *term_net; /* Back-pointer to net */ + struct term *term_next; /* Next term in net */ + int term_flags; /* See below */ + struct term *term_others; /* Other valid starting points */ +} Term; + + /* Flags for above */ +#define TERM_FRINGE 0x01 /* Candidate for fringe routing */ +#define TERM_FEEDTHROUGH 0x02 /* Member of feedthrough list */ +#define TERM_ROUTED 0x04 /* Routed to rest of net */ + + /* Everything in a Net is electrically identical */ +typedef struct net +{ + struct net *net_next; /* Next net in nnl_netList */ + struct term *net_terms; /* List of Terms in this net */ + int net_prio; /* If > 0 then user-specified priority + * with 1 meaning highest; if 0 then + * no priority specified. + * +++ NOT CURRENTLY USED +++ + */ +} Net; + + /* A NetList specifies a set of connections to be made */ +typedef struct nnl +{ + HashTable nnl_termHash; /* Map from names to Terms */ + struct net *nnl_netList; /* List of all Nets */ +} NewNetList; + +/* procedure declarations */ +extern bool gaMazeInit(); + +#endif /* _GAINTERNAL_H */ diff --git a/garouter/gaMain.c b/garouter/gaMain.c new file mode 100644 index 00000000..539fb1ce --- /dev/null +++ b/garouter/gaMain.c @@ -0,0 +1,463 @@ +/* + * gaMain.c - + * + * Top-level of the gate-array router. + * + * For an overview of how routing systems work in general, see + * the papers: + * + * "Magic's Obstacle-Avoiding Global Router", G.T. Hamachi and + * J.K. Ousterhout, Proceedings of the 1985 Chapel Hill Conference + * on VLSI, May 1985, pp. 393-418 + * + * "A Switchbox Router with Obstacle Avoidance", G.T. Hamachi + * and J.K. Ousterhout, Proc 21st Design Automation Conference, + * June 1984, pp. 173-179. + * + * "The PI (Placement and Interconnect) System", R.L. Rivest, + * Proc 19th Design Automation Conference, June 1982, pp. 475-481. + * + * This router shares much code with the standard router in the "router" + * module, and also makes use of the "grouter" (global-router) "gcr" + * (channel-router), and "mzrouter" (maze-router) modules. + * + * The primary differences between this module and the "router" module + * are that "garouter" allows the user to define channels explicitly + * (rather than having them be generated automatically as they are in + * the "router" module). These channels can overlap subcells arbitrarily, + * unlike automatically generated channels which only appear in areas + * where there are no subcells. + * + * User-specified channels can be specially identified as "river-routing" + * channels. Unlike ordinary channels, these may contain routing terminals. + * However, the routing across a river-routing channel is simpler than + * that in an ordinary channel: tracks run either straight across horizontally, + * for horizontal river routing channels, or vertically, for vertical + * river routing channels, but never both. (See gcr.h for a description + * of normal channels and the two kinds of river routing channels). + * + * Router organization: + * ------------------- + * + * Routing is composed of a number of steps. First, the channels are + * defined (by the user in this module) by calls to GADefineChannel(). + * The remainder of the work is done in GARoute(), which: + * + * - reads the list of intended connections into a NLNetList + * structure, + * - generates "stems" for all terminals, + * - sets up the channels for global routing, + * - calls the global router to determine the sequence of channel + * boundary points through which the route for each net will pass, + * - calls the channel router to fill in the detailed routes for + * each net in each channel structure, and then paint this + * information back into the edit cell, + * - generates paint for each stem generated at the start of routing + * + * The following sections briefly describe each of the above tasks in + * a bit more detail: + * + * Nets and terminals: + * ------------------ + * + * The connections that the router must make are described to it in + * the form of a netlist, which comes from a text file that is either + * generated outside of Magic or created using the netlist editor in + * the "netmenu" module of Magic. Each "net" is a collection of named + * terminals that must be connected. These terminals are described by + * the hierarchical names of labels. Each terminal appears in exactly + * one net. A given label may appear in several places in the same cell, + * so a terminal may have several locations. The router assumes that all + * of these locations are already electrically connected. + * + * + * Channels and pins: + * ----------------- + * + * This router is grid-based, meaning that wires are generated so that + * their left-hand side and bottom align with evenly-spaced grid lines + * in x and y. Two key structures, defined in gcr.h, represent the + * routing problem in this grid-based world: the channel (GCRChannel) + * and pin (GCRPin). Channels are rectangular areas with pins along + * their boundaries: + * + * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + * . . . . . . . + * . +---X---------X---------X---------X---------X-----+ . + * . | . . . . . | . + * . | . . . . . | . + * . . . X . P---------P---------P---------P---------P . . X . . + * . | | . . . | | . + * . | | . . . | | . + * . | | . . . | | . + * . . . X . P . . . . . . . . . . . . . . . . . . . P . . X . . + * . | | . . . | | . + * . | | . . . | | . + * . | | . . . | | . + * . . . X . P . . . . . . . . . . . . . . . . . . . P . . X . . + * . | | . . . | | . + * . | | . . . | | . + * . | | . . . | | . + * . . . X . P---------P---------P---------P---------P . . X . . + * . | . . . . . | . + * . +---X---------X---------X---------X---------X-----+ . + * . . . . . . . + * . . . . . . . + * O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + * + * The dots indicate the grid lines. The set of grid points enclosed + * by the channel is the inner dashed line. The actual channel boundary + * lies between these grid lines and the next grid lines out. (To handle + * the case where the grid spacing is odd, the boundary actually lies + * at a location that is half the grid spacing (rounded down to the nearest + * integer) DOWN and to the LEFT of a grid line, hence the asymmetry in + * the diagram above. + * + * "Crossing points" lie along the channel boundary and are marked by X's. + * Each crossing point has a pin associated with it; these pins are marked + * by P's. (Note that the pins in the corners occupy the same grid + * points but different crossing points; this reflects the fact that + * the routing for a column and a track can overlap). + * Each channel structure has four arrays of pins: one along each of its + * LHS, RHS, and top and bottom (indexed as 1, 2, ... in order of + * increasing x or y as appropriate; the 0th element of the pin + * arrays is not used). + * + * When two channels share a common boundary, a single crossing + * point may be associated with two pins: one in each channel. + * During channel initialization (below), those pairs of pins + * that share a crossing point are made to point to each other. + * + * + * Stem generation: + * --------------- + * + * Although the router is grid based, terminals in cells need not be + * aligned to the routing grid. Stem generation is the process of + * finding one (or two) channel pin(s) that are reachable from each + * terminal in the routing problem, and marking these pins with the + * net to which the terminal belongs. If a terminal lies in the middle + * of a river-routing channel, up to two pins will be assigned to it + * (on opposite sides of the channel). Otherwise, (e.g., if the terminal + * is inside a cell but not in any channel) only one pin will be assigned, + * in the channel closest to the terminal. + * + * Stem generation actually has two parts. The first only determines + * if a stem CAN be run from a terminal to a pin, but doesn't generate + * any paint, since not all terminals will necessarily be used by + * the global router. (For example, if a terminal appears in more + * than one place in a cell, it may be that only one of these places + * is actually connected by the router). The second part of stem + * generation, invoked after channel routing is complete, actually + * paints the stems into the edit cell. + * + * Since the stem generator has no way of knowing which layer the + * channel router will use for a signal it routes to a pin, it must + * be possible for the final stems to connect to either routing + * layer. The stem generator checks to ensure that it can connect + * to either layer during the first part, and rejects pins it can't + * reach on either layer (unless the area of the pin itself is covered + * by one layer, in which case the stem only has to be able to connect + * to the free layer). + * + * The code for stem generation is split between this module (for + * stems inside river-routing channels), the "router" module (for + * stems for terminals outside of any channel), and the "mzrouter" + * module (used to determine when stems can be routed, if it isn't + * obvious). + * + * Global routing: + * -------------- + * + * Initially, all the pins in each channel are marked as not belonging + * to any net, except for the pins that were assigned to terminals by + * stem generation. The job of the global router is to find paths + * (as sequences of pins) for all nets, and to mark the pins on a + * given net's path with that net's identifier. These channels + * and marked pins will be used as the input to the channel router. + * + * Channel routing: + * --------------- + * + * Each channel structure contains a two-dimensional array with one + * element for each internal grid point in the channel. The channel + * router accepts a channel whose pins have been marked with net + * identifiers, and fills in this internal array with flags indicating + * the type of material/contact to place at that grid location. After + * all channels have been routed, we use the information in these + * internal arrays to generate actual paint for the edit cell. Since + * channels are routed independently of what material is in adjacent + * channels, sometimes it is necessary during this paintback to add + * contacts at channel boundaries to switch routing layers. + * + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/garouter/gaMain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "netmenu/netmenu.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "garouter/garouter.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "drc/drc.h" + + +/* + * ---------------------------------------------------------------------------- + * + * GARouteCmd -- + * + * Top-level procedure for the gate-array router. + * Routes the cell 'routeUse->cu_def' using the netlist 'netListName'. + * + * Results: + * Returns the number of routing errors left as feedback. + * Returning -1 means that routing was unable to commence + * because of other errors (e.g, the netlist couldn't be + * read) which were already reported to the user. + * + * Side effects: + * Leaves paint in routeUse->cu_def. Leaves feedback where routing + * errors occurred. Frees all the memory associated with channel + * structures when done. + * + * ---------------------------------------------------------------------------- + */ + +int +GARouteCmd(routeUse, netListName) + CellUse *routeUse; + char *netListName; +{ + int errs; + NLNetList netList; + GCRChannel *ch; + NLNet *net; + + /* Initialize ga maze routing */ + if(gaMazeInit(routeUse)==FALSE) + { + TxError("Could not initialize maze router.\n"); + return(-1); + } + + /* Ensure that there are channels defined */ + if (gaChannelList == (GCRChannel *) NULL) + { + TxError("Must define channels before routing.\n"); + return (-1); + } + + /* Read the netlist */ + if (gaBuildNetList(netListName, routeUse, &netList) < 0) + return (-1); + if (SigInterruptPending) + goto done; + + /* Figure out the size of the routing area */ + RouteArea.r_xbot = RouteArea.r_ybot = INFINITY; + RouteArea.r_xtop = RouteArea.r_ytop = MINFINITY; + for (ch = gaChannelList; ch && !SigInterruptPending; ch = ch->gcr_next) + (void) GeoIncludeAll(&ch->gcr_area, &RouteArea); + for (net = netList.nnl_nets; net; net = net->nnet_next) + (void) GeoIncludeAll(&net->nnet_area, &RouteArea); + + errs = GARoute(gaChannelList, routeUse, &netList); + +done: + /* Cleanup */ + NLFree(&netList); + GAClearChannels(); + + return (errs); +} + +/* + * ---------------------------------------------------------------------------- + * + * GARoute -- + * + * Routes the cell 'routeUse->cu_def' using the netlist 'netList'. + * The list of channels is 'list'. These channels are fresh from + * being allocated by GCRNewChannel(). + * + * Results: + * Returns the number of routing errors left as feedback. + * Returning -1 means that routing was unable to commence + * because of other errors (e.g, the netlist couldn't be + * read) which were already reported to the user. + * + * Side effects: + * Leaves paint in routeUse->cu_def. Leaves feedback where routing + * errors occurred. Frees all the memory associated with channel + * structures when done. + * + * ---------------------------------------------------------------------------- + */ + +int +GARoute(list, routeUse, netList) + GCRChannel *list; /* List of channels */ + CellUse *routeUse; /* Cell being routed */ + NLNetList *netList; /* List of nets to route */ +{ + int feedCount = DBWFeedbackCount, errs; + GCRChannel *ch; + + /* + * Initialize all the pointers in the channel structure (stem assignment), + * and also determine which tracks are available for river-routing + * in channels so marked (CHAN_HRIVER or CHAN_VRIVER). + */ + gaChannelInit(list, routeUse, netList); + if (SigInterruptPending + || DebugIsSet(gaDebugID, gaDebChanOnly) + || DebugIsSet(glDebugID, glDebStemsOnly)) + goto done; + + /* Perform global routing */ + RtrMilestoneStart("Global routing"); + GlGlobalRoute(list, netList); + RtrMilestoneDone(); + if (SigInterruptPending || DebugIsSet(glDebugID, glDebGreedy)) + goto done; + + /* Channel routing */ + errs = 0; + RtrMilestoneStart("Channel routing"); + for (ch = list; ch && !SigInterruptPending; ch = ch->gcr_next) + RtrChannelRoute(ch, &errs); + RtrMilestoneDone(); + if (errs > 0) + TxError("%d bad connection%s.\n", errs, errs != 1 ? "s" : ""); + if (SigInterruptPending) + goto done; + + /* Paint results in a separate pass */ + RtrMilestoneStart("Painting results"); + for (ch = list; ch && !SigInterruptPending; ch = ch->gcr_next) + { + RtrMilestonePrint(); + RtrPaintBack(ch, routeUse->cu_def); + /* update bounding box NOW so searches during stem gen. + * work correctly. + */ + DBReComputeBbox(routeUse->cu_def); + } + RtrMilestoneDone(); + if (SigInterruptPending) + goto done; + + if (DebugIsSet(gaDebugID, gaDebPaintStems)) + { + DRCCheckThis(routeUse->cu_def, TT_CHECKPAINT, &RouteArea); + DBWAreaChanged(routeUse->cu_def, &RouteArea, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + WindUpdate(); + TxMore("After channel paintback"); + } + + gaStemPaintAll(routeUse, netList); + + /* + * Mark the areas modified. + * Only areas inside the routing channels are actually affected. + */ + SigDisableInterrupts(); + /* recomp bbox again just in case stem gen changed it (unlikely) */ + DBReComputeBbox(routeUse->cu_def); + DRCCheckThis(routeUse->cu_def, TT_CHECKPAINT, &RouteArea); + DBWAreaChanged(routeUse->cu_def, &RouteArea, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + SigEnableInterrupts(); + +done: + /* Return number of errors */ + return (DBWFeedbackCount - feedCount); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaBuildNetList -- + * + * Construct the netlist that will be used for routing. + * Use netListName if supplied; otherwise use the name of + * the current netlist; if neither are set, use the name + * of the cell 'routeUse->cu_def'. + * + * Leaves the constructed netlist in 'netList'. + * + * Results: + * Returns the number of nets in netList. If there were + * no nets, returns 0. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +gaBuildNetList(netListName, routeUse, netList) + char *netListName; + CellUse *routeUse; + NLNetList *netList; +{ + CellDef *routeDef = routeUse->cu_def; + int numNets; + + /* Select the netlist */ + if (netListName == NULL) + { + if (!NMHasList()) + { + netListName = routeDef->cd_name; + TxPrintf("No netlist selected yet; using \"%s\".\n", netListName); + NMNewNetlist(netListName); + } + else netListName = NMNetlistName(); + } + else NMNewNetlist(netListName); + + if (DebugIsSet(gaDebugID, gaDebVerbose)) + TxPrintf("Reading netlist %s.\n", netListName); + RtrMilestoneStart("Building netlist"); + numNets = NLBuild(routeUse, netList); + RtrMilestoneDone(); + if (numNets == 0) + TxError("No nets to route.\n"); + if (DebugIsSet(gaDebugID, gaDebVerbose)) + TxPrintf("Read %d nets.\n", numNets); + + return (numNets); +} diff --git a/garouter/gaMaze.c b/garouter/gaMaze.c new file mode 100644 index 00000000..240d3ffb --- /dev/null +++ b/garouter/gaMaze.c @@ -0,0 +1,403 @@ +/* + * gaMaze.c - + * + * Code to interface to mzrouter for harder stems. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/garouter/gaMaze.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "utils/undo.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "netmenu/netmenu.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "garouter/garouter.h" +#include "gaInternal.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "utils/styles.h" +#include "utils/malloc.h" +#include "drc/drc.h" +#include "debug/debug.h" +#include "utils/list.h" +#include "../mzrouter/mzrouter.h" + +/*-------------- Global data only referenced within this file ---------------*/ +/* Parameter settings passed to mzrouter (initialized when first needed.) */ + +MazeParameters *gaMazeParms = NULL; + +/* Top Level Cell used by mzrouter during stem generation. + * Contains a fence, to limit the scope of the search, + * and the edit cell as a subcell */ + +CellUse *gaMazeTopUse; +CellDef *gaMazeTopDef; +CellUse *gaMazeTopSub; + +/* Forward declarations */ + +void gaMazeBounds(); + + +/* + * ---------------------------------------------------------------------------- + * + * gaMazeInit -- + * + * Initialize ga maze routing code. + + * Results: + * TRUE if successful, FALSE if unsuccessful. + * + * Side effects: + * sets up gaMazeTop cell. + * + * ---------------------------------------------------------------------------- + */ + +bool +gaMazeInit(routeUse) + CellUse *routeUse; /* Cell routing will be done in - made subcell + * of gaMazeTop + */ +{ + UndoDisable(); + + /* setup maze parms */ + + if (GAMazeInitParms() == FALSE) + return FALSE; + + /* allocate gaMazeTop - if necessary */ + if(!gaMazeTopUse) + { + DBNewYank("__GAMAZETOP", &gaMazeTopUse, &gaMazeTopDef); + } + + /* unlink old subcell - if any */ + if(gaMazeTopSub) + { + DBUnLinkCell(gaMazeTopSub, gaMazeTopDef); + DBDeleteCell(gaMazeTopSub); + DBCellDeleteUse(gaMazeTopSub); + } + + /* make routeUse a subcell of gaMazeTop (using identity transform) */ + { + gaMazeTopSub = DBCellNewUse(routeUse->cu_def, "__MAZE_TOP_SUB"); + DBPlaceCell(gaMazeTopSub, gaMazeTopDef); + } + + UndoEnable(); + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * + * GAMazeInitParms -- Initialize ga maze routing parameters. + * + * Called by gaMazeInit the first time it is invoked. + + * Results: + * TRUE if successful, FALSE if unsuccessful + * + * Side effects: + * gaMazeParms setup. + * + * ---------------------------------------------------------------------------- + */ +bool +GAMazeInitParms() +{ + if (gaMazeParms != NULL) + { + MZFreeParameters(gaMazeParms); + gaMazeParms = NULL; + } + + /* Initialize to copy of default garouter parameters */ + gaMazeParms = MZCopyParms(MZFindStyle("garouter")); + + if(gaMazeParms == NULL) + return FALSE; + + /* optimize for this application */ + gaMazeParms->mp_expandEndpoints = TRUE; + gaMazeParms->mp_topHintsOnly = TRUE; + gaMazeParms->mp_bloomLimit = MAZE_TIMEOUT; + + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * + * gaMazeRoute -- + * + * Try to maze route from pinPoint to terminalLoc + * ending up on a layer in `pinLayerMask' while constraining + * all wiring to stay within boundingRect. + * + * Uses the Magic maze router (mzrouter module). + * + * Results: + * Returns TRUE if a route is possible, FALSE if not. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +gaMazeRoute(routeUse, terminalLoc, pinPoint, pinLayerMask, side, writeFlag) + CellUse *routeUse; /* Cell to route in - top level cell visible + * to router and also cell route is painted + * into. All subcells are treated as expanded + * by the router, i.e. their contents are + * examined. And routing across the tops of + * subcells is permitted. + */ + NLTermLoc *terminalLoc; /* Terminal to connect to - somewhere in + * interior of cell */ + Point *pinPoint; /* Point to connect from (on edge of cell) */ + TileTypeBitMask pinLayerMask; /* layer at pin (no more than one + * bit should correspond to a known + * routing layer) + */ + int side; /* side of cell destPoint lies on */ + bool writeFlag; /* If non-null, paint back result (into + * routeUse), otherwise just check if + * route is possible. + */ +{ + Rect routeBounds; + bool done = FALSE; + + /* setup bounding box */ + { + /* compute route bounds */ + gaMazeBounds(terminalLoc, pinPoint, &routeBounds); + + /* Enforce route bounds with fence */ + + UndoDisable(); + DBPaint(gaMazeTopDef, &routeBounds, TT_FENCE); + DBReComputeBbox(gaMazeTopDef); + UndoEnable(); + + /* Set bounds hint to fence - improves mzrouter performance */ + gaMazeParms->mp_boundsHint = &routeBounds; + } + + /* Initialize Maze Route */ + { + MZInitRoute(gaMazeParms, gaMazeTopUse, /* all subcells visible */ 0); + } + + /* set maze router start point to pinPoint */ + { + TileType type; + + /* determine starting type from mask */ + { + RouteLayer *rL; + + /* find route layer corresponding to mask */ + for(rL = gaMazeParms->mp_rLayers; rL!=NULL; rL=rL->rl_next) + { + if(TTMaskHasType(&pinLayerMask,rL->rl_routeType.rt_tileType)) + { + break; + } + } + + /* make sure we found a routelayer */ + if (rL == NULL) + { + TxError("gaMaze.c: no routetypes in destLayerMask\n"); + goto abort; + } + + /* set type to tiletype of routelayer */ + type = rL->rl_routeType.rt_tileType; + } + + /* give the mzrouter the start point and type */ + MZAddStart(pinPoint, type); + } + + /* set maze router dest area to terminal loc and layer*/ + { + MZAddDest(&(terminalLoc->nloc_rect), + terminalLoc->nloc_label->lab_type); + } + + /* Do the Route */ + { + RoutePath *path; + + /* search for path */ + path = MZRoute(NULL); /* Note: we could make use of the result code... */ + if(SigInterruptPending) goto abort; + + /* If no path found, abort */ + if(path == NULL) + { + goto abort; + } + + /* if write flag set, paint back route path */ + if (writeFlag) + { + CellUse *resultUse; + + /* Have MazeRouter paint the path into a cell*/ + resultUse = MZPaintPath(path); + if(SigInterruptPending) goto abort; + + /* Copy path to route cell */ + { + SearchContext scx; + + scx.scx_use = resultUse; + scx.scx_area = resultUse->cu_def->cd_bbox; + scx.scx_trans = GeoIdentityTransform; + (void) DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, routeUse); + DBReComputeBbox(routeUse->cu_def); + } + + /* Notify dbwind module (for redisplay), and DRC module + * of changed area */ + { + Rect changedArea; + changedArea= routeUse->cu_def->cd_bbox; + + DBWAreaChanged(routeUse->cu_def, &changedArea, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + DRCCheckThis(routeUse->cu_def, TT_CHECKPAINT, &changedArea); + } + } + } + + /* Make sure we got here without interruption */ + if(SigInterruptPending) goto abort; + + /* We are done */ + done = TRUE; + +abort: + /* cleanup and return */ + UndoDisable(); + DBErase(gaMazeTopDef, &routeBounds, TT_FENCE); + UndoEnable(); + + /* cleanup after the mzrouter */ + if(!DebugIsSet(gaDebugID, gaDebNoClean)) + { + MZClean(); + } + + return done; +} + + +/* + * ---------------------------------------------------------------------------- + * + * gaMazeBounds -- + * + * Pick a rectangular area for mazerouting containing terminalLoc and + * enough extra slop to make sure connection and contacts are possible + * at the end points. + * + * Results: + * None. + * + * Side effects: + * Sets *r to the area described above. + * + * ---------------------------------------------------------------------------- + */ + +void +gaMazeBounds(terminalLoc, pinPoint, r) + NLTermLoc *terminalLoc; /* Terminal */ + Point *pinPoint; /* Grid point */ + Rect *r; /* Set to bounding area for maze route */ +{ + + /* set containing rectangle */ + r->r_xbot = MIN(terminalLoc->nloc_rect.r_xbot, pinPoint->p_x); + r->r_ybot = MIN(terminalLoc->nloc_rect.r_ybot, pinPoint->p_y); + r->r_xtop = MAX(terminalLoc->nloc_rect.r_xtop, pinPoint->p_x); + r->r_ytop = MAX(terminalLoc->nloc_rect.r_ytop, pinPoint->p_y); + + /* Adjust for width of routes */ + { + int width = 0; + + /* compute max active width */ + { + RouteType *rT; + + for(rT=gaMazeParms->mp_rTypes; rT!=NULL; rT=rT->rt_next) + { + if(rT->rt_active) + { + width = MAX(width, rT->rt_width); + } + } + } + + /* Grow to top and right by max active width */ + + /* NOTE: Changed by Tim, 7/30/06. 1x max active width is WAY */ + /* too constraining, and causes MANY routes to fail. We only */ + /* want to avoid hapless searching far outside the local space */ + /* that might cause routes to be placed in the way of other */ + /* routes. */ + + { + /* r->r_xtop += width; */ + /* r->r_ytop += width; */ + + r->r_xtop += (2 * width); + r->r_ytop += (2 * width); + r->r_xbot -= (2 * width); + r->r_ybot -= (2 * width); + } + } + + return; +} diff --git a/garouter/gaSimple.c b/garouter/gaSimple.c new file mode 100644 index 00000000..8506138e --- /dev/null +++ b/garouter/gaSimple.c @@ -0,0 +1,705 @@ +/* + * gaSimple.c - + * + * Code to try very simple stems + * (straight line connection from pin to terminal + * with a possible contact at or near each end) + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/garouter/gaSimple.c,v 1.2 2009/05/13 15:03:16 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "netmenu/netmenu.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "garouter/garouter.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "utils/styles.h" +#include "utils/malloc.h" +#include "drc/drc.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" + +bool gaIsClear(); + +/*--- Externals referenced in this file and not declared in include files ---*/ +extern int gaMetalClear; +extern int gaPolyClear; +extern int gaContactClear; + + +/* + * ---------------------------------------------------------------------------- + * + * gaStemSimpleInit -- + * + * Initialize the SimpleStem struct to contain information on what + * simple routes are possible. + * + * Simple routes are grid aligned straight routes from the terminal + * to the pin, with a possible contact at the terminal and another near + * the pin on the grid line just before the channel edge. + * + * If this routine returns TRUE, gaStemSimpleRoute() must still be called + * to determine if a simple route is possible (and optionally to paint the + * route into a cell). + * + * Results: + * TRUE if successful, FALSE if it was not possible to make a + * grid-aligned route. + * + * Side effects: + * Fills in the fields of *simple. + * + * ---------------------------------------------------------------------------- + */ + +bool +gaStemSimpleInit(routeUse, term, pinPoint, pinSide, simple) + CellUse *routeUse; /* Search this cell for obstacles */ + NLTermLoc *term; /* Route from term->nloc_rect */ + Point *pinPoint; /* Crossing point to reach */ + int pinSide; /* Direction of pin from term. */ + SimpleStem *simple; /* Fill this in */ +{ + + SimpleWire *sMetal = &simple->ss_metalWire; + SimpleWire *sPoly = &simple->ss_polyWire; + Rect *cTerm = &simple->ss_cTerm; + Rect *cPin = &simple->ss_cPin; + Rect *termLoc = &term->nloc_rect; + + /* + * Check that the start terminal is big enough for the route to be + * grid-aligned. The start terminal has to be big enough + * to hold a grid-aligned wire on each of the routing types. + */ + { + int bot, top; + + switch (pinSide) + { + case GEO_NORTH: + case GEO_SOUTH: + { + bot = pinPoint->p_x; + top = termLoc->r_xtop; + if (bot < termLoc->r_xbot) + return (FALSE); + break; + } + + case GEO_EAST: + case GEO_WEST: + { + bot = pinPoint->p_y; + top = termLoc->r_ytop; + if (bot < termLoc->r_ybot) + return (FALSE); + break; + } + } + if (bot + RtrMetalWidth > top || bot + RtrPolyWidth > top) + return (FALSE); + } + + /* Misc initialization */ + { + simple->ss_dir = pinSide; + simple->ss_pinPoint = *pinPoint; + simple->ss_termArea = term->nloc_rect; + simple->ss_termType = term->nloc_label->lab_type; + + sMetal->sw_type = RtrMetalType; + sPoly->sw_type = RtrPolyType; + } + + /* Determine which types connect to terminal directly + * (without adding a contact) + */ + if (simple->ss_termType == RtrContactType) + { + TTMaskSetOnlyType(&(simple->ss_termMask), RtrMetalType); + TTMaskSetType(&(simple->ss_termMask), RtrPolyType); + } + else + { + TTMaskSetOnlyType(&(simple->ss_termMask), simple->ss_termType); + } + + /* + * Compute contact and wire areas. + * Defn of areas: + * - long wires run from terminal to pin, + * - short wires run from terminal to contact near pin, + * - pinStubs run from pinContact to pin. + */ + { + switch (pinSide) + { + case GEO_NORTH: + /* pin is directly above terminal */ + { + /* compute terminal contact location */ + cTerm->r_xbot = pinPoint->p_x + RtrContactOffset; + cTerm->r_ybot = termLoc->r_ytop - RtrContactWidth; + cTerm->r_xtop = cTerm->r_xbot + RtrContactWidth; + cTerm->r_ytop = cTerm->r_ybot + RtrContactWidth; + + /* compute pin contact location */ + cPin->r_xbot = pinPoint->p_x + RtrContactOffset; + cPin->r_ybot = (RTR_GRIDDOWN(pinPoint->p_y, RtrOrigin.p_y) + + RtrContactOffset); + cPin->r_xtop = cPin->r_xbot + RtrContactWidth; + cPin->r_ytop = cPin->r_ybot + RtrContactWidth; + + /* compute poly pin stub location */ + sPoly->sw_pinStub.r_xbot = pinPoint->p_x; + sPoly->sw_pinStub.r_ybot = cPin->r_ytop; + sPoly->sw_pinStub.r_xtop = pinPoint->p_x + RtrPolyWidth; + sPoly->sw_pinStub.r_ytop = pinPoint->p_y; + + /* compute metal pin stub location */ + sMetal->sw_pinStub.r_xbot = pinPoint->p_x; + sMetal->sw_pinStub.r_ybot = cPin->r_ytop; + sMetal->sw_pinStub.r_xtop = pinPoint->p_x + RtrMetalWidth; + sMetal->sw_pinStub.r_ytop = pinPoint->p_y; + + /* compute short metal wire */ + sMetal->sw_short.r_xbot = pinPoint->p_x; + sMetal->sw_short.r_ybot = termLoc->r_ytop; + sMetal->sw_short.r_xtop = pinPoint->p_x + RtrMetalWidth; + sMetal->sw_short.r_ytop = cPin->r_ybot; + + /* compute short poly wire */ + sPoly->sw_short.r_xbot = pinPoint->p_x; + sPoly->sw_short.r_xtop = pinPoint->p_x + RtrPolyWidth; + sPoly->sw_short.r_ybot = termLoc->r_ytop; + sPoly->sw_short.r_ytop = cPin->r_ybot; + + /* compute long metal wire */ + sMetal->sw_long = sMetal->sw_short; + sMetal->sw_long.r_ytop = pinPoint->p_y; + + /* compute long poly wire */ + sPoly->sw_long = sPoly->sw_short; + sPoly->sw_long.r_ytop = pinPoint->p_y; + break; + } + + case GEO_SOUTH: + /* pin is directly below terminal */ + { + /* compute terminal contact location */ + cTerm->r_xbot = pinPoint->p_x + RtrContactOffset; + cTerm->r_ybot = termLoc->r_ybot; + cTerm->r_xtop = cTerm->r_xbot + RtrContactWidth; + cTerm->r_ytop = cTerm->r_ybot + RtrContactWidth; + + /* compute pin contact location */ + cPin->r_xbot = pinPoint->p_x + RtrContactOffset; + cPin->r_ybot = (RTR_GRIDUP(pinPoint->p_y, RtrOrigin.p_y) + + RtrContactOffset); + cPin->r_xtop = cPin->r_xbot + RtrContactWidth; + cPin->r_ytop = cPin->r_ybot + RtrContactWidth; + + /* compute poly pin stub location */ + sPoly->sw_pinStub.r_xbot = pinPoint->p_x; + sPoly->sw_pinStub.r_ybot = pinPoint->p_y; + sPoly->sw_pinStub.r_xtop = pinPoint->p_x + RtrPolyWidth; + sPoly->sw_pinStub.r_ytop = cPin->r_ybot; + + /* compute metal pin stub location */ + sMetal->sw_pinStub.r_xbot = pinPoint->p_x; + sMetal->sw_pinStub.r_ybot = pinPoint->p_y; + sMetal->sw_pinStub.r_xtop = pinPoint->p_x + RtrMetalWidth; + sMetal->sw_pinStub.r_ytop = cPin->r_ybot; + + /* compute short metal wire */ + sMetal->sw_short.r_xbot = pinPoint->p_x; + sMetal->sw_short.r_ybot = cPin->r_ytop; + sMetal->sw_short.r_xtop = pinPoint->p_x + RtrMetalWidth; + sMetal->sw_short.r_ytop = termLoc->r_ybot; + + /* compute short poly wire */ + sPoly->sw_short.r_xbot = pinPoint->p_x; + sPoly->sw_short.r_ybot = cPin->r_ytop; + sPoly->sw_short.r_xtop = pinPoint->p_x + RtrPolyWidth; + sPoly->sw_short.r_ytop = termLoc->r_ybot; + + /* long metal wire */ + sMetal->sw_long = sMetal->sw_short; + sMetal->sw_long.r_ybot = pinPoint->p_y; + + /* long poly wire */ + sPoly->sw_long = sPoly->sw_short; + sPoly->sw_long.r_ybot = pinPoint->p_y; + + break; + } + + case GEO_EAST: + /* pin is directly to right of terminal */ + { + /* compute terminal contact location */ + cTerm->r_xbot = termLoc->r_xtop - RtrContactWidth; + cTerm->r_ybot = pinPoint->p_y + RtrContactOffset; + cTerm->r_xtop = cTerm->r_xbot + RtrContactWidth; + cTerm->r_ytop = cTerm->r_ybot + RtrContactWidth; + + /* compute pin contact location */ + cPin->r_xbot = (RTR_GRIDDOWN(pinPoint->p_x, RtrOrigin.p_x) + + RtrContactOffset); + cPin->r_ybot = pinPoint->p_y + RtrContactOffset; + cPin->r_xtop = cPin->r_xbot + RtrContactWidth; + cPin->r_ytop = cPin->r_ybot + RtrContactWidth; + + /* compute poly pin stub location */ + sPoly->sw_pinStub.r_xbot = cPin->r_xtop; + sPoly->sw_pinStub.r_ybot = pinPoint->p_y; + sPoly->sw_pinStub.r_xtop = pinPoint->p_x; + sPoly->sw_pinStub.r_ytop = pinPoint->p_y + RtrPolyWidth; + + /* compute metal pin stub location */ + sMetal->sw_pinStub.r_xbot = cPin->r_xtop; + sMetal->sw_pinStub.r_ybot = pinPoint->p_y; + sMetal->sw_pinStub.r_xtop = pinPoint->p_x; + sMetal->sw_pinStub.r_ytop = pinPoint->p_y + RtrMetalWidth; + + /* compute short metal wire */ + sMetal->sw_short.r_xbot = termLoc->r_xtop; + sMetal->sw_short.r_ybot = pinPoint->p_y; + sMetal->sw_short.r_xtop = cPin->r_xbot; + sMetal->sw_short.r_ytop = pinPoint->p_y + RtrMetalWidth; + + /* compute short poly wire */ + sPoly->sw_short.r_xbot = termLoc->r_xtop; + sPoly->sw_short.r_ybot = pinPoint->p_y; + sPoly->sw_short.r_xtop = cPin->r_xbot; + sPoly->sw_short.r_ytop = pinPoint->p_y + RtrPolyWidth; + + /* compute long metal wire */ + sMetal->sw_long = sMetal->sw_short; + sMetal->sw_long.r_xtop = pinPoint->p_x; + + /* compute long poly wire */ + sPoly->sw_long = sPoly->sw_short; + sPoly->sw_long.r_xtop = pinPoint->p_x; + break; + } + + case GEO_WEST: + /* pin is directly to left of terminal */ + { + /* compute terminal contact location */ + cTerm->r_xbot = termLoc->r_xbot; + cTerm->r_ybot = pinPoint->p_y + RtrContactOffset; + cTerm->r_xtop = cTerm->r_xbot + RtrContactWidth; + cTerm->r_ytop = cTerm->r_ybot + RtrContactWidth; + + /* compute pin contact location */ + cPin->r_xbot = (RTR_GRIDUP(pinPoint->p_x, RtrOrigin.p_x) + + RtrContactOffset); + cPin->r_ybot = pinPoint->p_y + RtrContactOffset; + cPin->r_xtop = cPin->r_xbot + RtrContactWidth; + cPin->r_ytop = cPin->r_ybot + RtrContactWidth; + + /* compute poly pin stub location */ + sPoly->sw_pinStub.r_xbot = pinPoint->p_x; + sPoly->sw_pinStub.r_ybot = pinPoint->p_y; + sPoly->sw_pinStub.r_xtop = cPin->r_xbot; + sPoly->sw_pinStub.r_ytop = pinPoint->p_y + RtrPolyWidth; + + /* compute metal pin stub location */ + sMetal->sw_pinStub.r_xbot = pinPoint->p_x; + sMetal->sw_pinStub.r_ybot = pinPoint->p_y; + sMetal->sw_pinStub.r_xtop = cPin->r_xbot; + sMetal->sw_pinStub.r_ytop = pinPoint->p_y + RtrMetalWidth; + + /* compute short metal wire */ + sMetal->sw_short.r_xbot = cPin->r_xtop; + sMetal->sw_short.r_ybot = pinPoint->p_y; + sMetal->sw_short.r_xtop = termLoc->r_xbot; + sMetal->sw_short.r_ytop = pinPoint->p_y + RtrMetalWidth; + + /* compute short poly wire */ + sPoly->sw_short.r_xbot = cPin->r_xtop; + sPoly->sw_short.r_ybot = pinPoint->p_y; + sPoly->sw_short.r_xtop = termLoc->r_xbot; + sPoly->sw_short.r_ytop = pinPoint->p_y + RtrPolyWidth; + + /* long metal wire */ + sMetal->sw_long = sMetal->sw_short; + sMetal->sw_long.r_xbot = pinPoint->p_x; + + /* long poly wire */ + sPoly->sw_long = sPoly->sw_short; + sPoly->sw_long.r_xbot = pinPoint->p_x; + + break; + } + + } /* end switch */ + } + + /* check which wires and contacts are blocked */ + { + Rect rTerm, rPin, rShortMetal, rShortPoly, rLongMetal, rLongPoly; + Rect rStubMetal, rStubPoly; + + /* + * bloat wire and contact areas to produce the areas that must + * be clear of obstacles in order for a route to be possible. + */ + { + GEO_EXPAND(cTerm, gaContactClear, &rTerm); + GEO_EXPAND(cPin, gaContactClear, &rPin); + GEO_EXPAND(&sMetal->sw_short, gaMetalClear, &rShortMetal); + GEO_EXPAND(&sMetal->sw_long, gaMetalClear, &rLongMetal); + GEO_EXPAND(&sMetal->sw_pinStub, gaMetalClear, &rStubMetal); + GEO_EXPAND(&sPoly->sw_short, gaPolyClear, &rShortPoly); + GEO_EXPAND(&sPoly->sw_long, gaPolyClear, &rLongPoly); + GEO_EXPAND(&sPoly->sw_pinStub, gaPolyClear, &rStubPoly); + } + + /* + * Prune check areas at terminal and pin to allow prexisting + * material at the connection points. + * + * (NOTE the terminal contact area is not trimmed, but will + * only be checked on the layer (if any) that is not part + * of the terminal) + */ + { + Rect pruneR; + + /* compute prune area */ + { + pruneR = routeUse->cu_bbox; + switch (pinSide) + { + case GEO_NORTH: + { + pruneR.r_ybot = termLoc->r_ytop; + pruneR.r_ytop = pinPoint->p_y; + break; + } + + case GEO_SOUTH: + { + pruneR.r_ybot = pinPoint->p_y; + pruneR.r_ytop = termLoc->r_ybot; + break; + } + + case GEO_EAST: + { + pruneR.r_xbot = termLoc->r_xtop; + pruneR.r_xtop = pinPoint->p_x; + break; + } + + case GEO_WEST: + { + pruneR.r_xbot = pinPoint->p_x; + pruneR.r_xtop = termLoc->r_xbot; + } + } + } + + /* prune the areas (accept for rTerm) */ + { + GEOCLIP(&rPin, &pruneR); + GEOCLIP(&rShortMetal, &pruneR); + GEOCLIP(&rLongMetal, &pruneR); + GEOCLIP(&rStubMetal, &pruneR); + GEOCLIP(&rShortPoly, &pruneR); + GEOCLIP(&rLongPoly, &pruneR); + GEOCLIP(&rStubPoly, &pruneR); + } + } + + /* check areas for obstacles */ + { + /* terminal contact */ + { + if(!TTMaskHasType(&simple->ss_termMask, RtrMetalType)) + { + simple->ss_cTermOK = gaIsClear(routeUse, + &rTerm, + &RtrMetalObstacles); + } + if(!TTMaskHasType(&simple->ss_termMask, RtrPolyType)) + { + simple->ss_cTermOK = gaIsClear(routeUse, + &rTerm, + &RtrPolyObstacles); + } + } + + /* pin contact */ + { + TileTypeBitMask allObs; + + TTMaskSetMask3(&allObs, &RtrPolyObstacles, &RtrMetalObstacles); + simple->ss_cPinOK = gaIsClear(routeUse, &rPin, &allObs); + } + + /* short metal wire + * (a short wire is only ok if both the short wire itself and + * the complementary stub are clear) + */ + sMetal->sw_shortOK = (gaIsClear(routeUse, + &rShortMetal, + &RtrMetalObstacles) + && + gaIsClear(routeUse, + &rStubPoly, + &RtrPolyObstacles)); + + + /* long metal wire */ + sMetal->sw_longOK = gaIsClear(routeUse, + &rLongMetal, + &RtrMetalObstacles); + + /* short poly wire */ + sPoly->sw_shortOK = (gaIsClear(routeUse, + &rShortPoly, + &RtrPolyObstacles) + && + gaIsClear(routeUse, + &rStubMetal, + &RtrMetalObstacles)); + + /* long poly wire */ + sPoly->sw_longOK = gaIsClear(routeUse, + &rLongPoly, + &RtrPolyObstacles); + } + } + + return (TRUE); +} + + +/* + * ---------------------------------------------------------------------------- + * + * gaIsClear -- + * + * + * Check that r is clear of all material of types in mask. + * + * Results: + * TRUE if the area is clear, FALSE if not. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +gaIsClear(use, r, mask) + CellUse *use; + Rect *r; + TileTypeBitMask *mask; +{ + int gaIsClearFunc(); + SearchContext scx; + + scx.scx_use = use; + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = *r; + if (DebugIsSet(gaDebugID, gaDebStems)) + { + ShowRect(use->cu_def, r, STYLE_OUTLINEHIGHLIGHTS); + TxMore("Checking clear area"); + ShowRect(use->cu_def, r, STYLE_ERASEHIGHLIGHTS); + } + if (DBTreeSrTiles(&scx, mask, 0, gaIsClearFunc, (ClientData) NULL)) + return (FALSE); + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaIsClearFunc -- + * + * Called for tiles whose type matches 'mask' underneath the area + * 'r' in gaIsClear() above. + * + * Results: + * Always returns 1 since we only need a single obstacle to not have + * a clear area. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +gaIsClearFunc(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + return 1; +} + + +/* + * ---------------------------------------------------------------------------- + * + * gaStemSimpleRoute -- + * + * See if a simple type of route is possible given the pinLayer. + * All other information describing the simple route is + * present in *simple. + * + * Results: + * TRUE if a route was possible, FALSE if not. + * + * Side effects: + * Paints the path into 'def' if 'def' is non-NULL. + * + * ---------------------------------------------------------------------------- + */ + +bool +gaStemSimpleRoute(simple, pinLayer, def) + SimpleStem *simple; /* Describes the route */ + TileType pinLayer; /* Connect to pin on this layer */ + CellDef *def; /* If non-NULL, paint to this def */ +{ + SimpleWire *wPin, *wOther; + + /* + * Determine which wire corresponds to pin + * and which corresponds to the other route layer. + */ + if (pinLayer == RtrPolyType) + { + wPin = &simple->ss_polyWire; + wOther = &simple->ss_metalWire; + } + else if (pinLayer == RtrMetalType) + { + wPin = &simple->ss_metalWire; + wOther = &simple->ss_polyWire; + } + else + { + ASSERT(FALSE, "gaStemSimpleRoute: bad destType"); + } + + if(TTMaskHasType(&simple->ss_termMask, pinLayer)) + /* layer of pin also OK for final connection at terminal */ + { + if(wPin->sw_longOK) + /* No contact connection */ + { + if(def) + { + DBPaint(def, &wPin->sw_long, wPin->sw_type); + } + return TRUE; + } + /* contact at pin only */ + else if (TTMaskHasType(&simple->ss_termMask, wOther->sw_type) && + wOther->sw_shortOK && + simple->ss_cPinOK) + { + if(def) + { + DBPaint(def, &wOther->sw_short, wOther->sw_type); + RtrPaintContact(def, &simple->ss_cPin); + DBPaint(def, &wPin->sw_pinStub, wPin->sw_type); + } + return TRUE; + } + else if (simple->ss_cTermOK && + wOther->sw_shortOK && + simple->ss_cPinOK) + /* two contact route */ + { + if(def) + { + RtrPaintContact(def, &simple->ss_cTerm); + DBPaint(def, &wOther->sw_short, wOther->sw_type); + RtrPaintContact(def, &simple->ss_cPin); + DBPaint(def, &wPin->sw_pinStub, wPin->sw_type); + } + return TRUE; + } + else + /* No simple route */ + { + return FALSE; + } + } + else + /* pin and terminal connections on opposite layers */ + { + if(simple->ss_cTermOK && + wPin->sw_longOK) + /* contact at terminal only */ + { + if(def) + { + RtrPaintContact(def, &simple->ss_cTerm); + DBPaint(def, &wPin->sw_long, wPin->sw_type); + } + return TRUE; + } + else if(wOther->sw_shortOK && + simple->ss_cPinOK) + /* contact at pin only */ + { + if(def) + { + DBPaint(def, &wOther->sw_short, wOther->sw_type); + RtrPaintContact(def, &simple->ss_cPin); + DBPaint(def, &wPin->sw_pinStub, wPin->sw_type); + } + return TRUE; + } + else + /* No simple route */ + { + return FALSE; + } + } +} diff --git a/garouter/gaStem.c b/garouter/gaStem.c new file mode 100644 index 00000000..8789f7c9 --- /dev/null +++ b/garouter/gaStem.c @@ -0,0 +1,1174 @@ +/* + * gaStem.c - + * + * Assignment of routing-grid pin locations to terminals. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/garouter/gaStem.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "netmenu/netmenu.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "garouter/garouter.h" +#include "gaInternal.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "utils/styles.h" +#include "utils/malloc.h" +#include "drc/drc.h" +#include "debug/debug.h" + +/* + * If TRUE, leave feedback for each location for a terminal that + * is unusable. If FALSE, only leave feedback if ALL locations + * for a particular terminal are unusable. + */ +bool GAStemWarn = FALSE; + +/* Used locally */ +int gaMaxAbove; /* The maximum distance any routing material extends + * above (or to the right of) a routing grid line. + */ +int gaMaxBelow; /* Same as above, but for material below or to the + * left of routing grid lines. + */ +int gaMinAbove; /* Minimum distance any routing material extends + * above (or to the right of) a routing grid line. + */ + +/* + * The following are conservative distances around each of + * metal, poly, and contact types that must be clear of material. + */ +int gaMetalClear, gaPolyClear, gaContactClear; + +/* Statistics */ +int gaNumDegenerate; +int gaNumLocs; +int gaNumPairs; +int gaNumInt, gaNumExt, gaNumNoChan; +int gaNumInNorm; +int gaNumOverlap; +int gaNumNetBlock; +int gaNumPinBlock; +int gaNumMazeStem, gaNumSimpleStem; +int gaNumSimplePaint, gaNumMazePaint, gaNumExtPaint; + +/* Forward declarations */ +int gaStemContainingChannelFunc(); +bool gaStemAssign(); +void gaStemGridRange(); +void gaStemPaint(); +bool gaStemNetClear(); +bool gaStemInternalFunc(); +bool gaStemInternal(); +bool gaStemGrow(); + + +/* + * ---------------------------------------------------------------------------- + * + * gaStemAssignAll -- + * + * Assign one or two crossing points to each terminal location. + * Terminal locations must lie inside river-routing channels; + * they are assigned crossings on either side of the channel + * as long as those crossings are reachable by river-routing. + * + * If terminal locations aren't grid-aligned, this code takes + * care of figuring out which grid-aligned crossing point to + * use and ensuring that this point is reachable from the terminal. + * + * Results: + * None. + * + * Side effects: + * Adds one additional NLTermLoc to the netlist for each + * terminal location that is given two crossing points. + * When it isn't possible to assign any crossing points + * to a NLTermLoc, it is deleted from the list and we + * leave feedback. + * + * ---------------------------------------------------------------------------- + */ + +void +gaStemAssignAll(routeUse, netList) + CellUse *routeUse; + NLNetList *netList; +{ + TileType t; + + /* Statistics */ + gaNumDegenerate = 0; + gaNumLocs = 0; + gaNumInt = 0; + gaNumExt = 0; + gaNumNoChan = 0; + gaNumPairs = 0; + gaNumInNorm = 0; + gaNumOverlap = 0; + gaNumNetBlock = 0; + gaNumPinBlock = 0; + gaNumMazeStem = 0; + gaNumSimpleStem = 0; + + /* + * Compute the distance around metal, poly, and contact that + * must be clear of material. + */ + gaMetalClear = gaPolyClear = 0; + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + if (RtrMetalSeps[t] > gaMetalClear) gaMetalClear = RtrMetalSeps[t]; + if (RtrPolySeps[t] > gaPolyClear) gaPolyClear = RtrPolySeps[t]; + } + gaContactClear = MAX(gaMetalClear + RtrMetalSurround, + gaPolyClear + RtrPolySurround); + + /* Max distance any routing material extends above a grid line */ + gaMaxAbove = MAX(RtrMetalWidth, RtrPolyWidth); + gaMaxAbove = MAX(gaMaxAbove, RtrContactWidth - RtrContactOffset); + + /* Min distance any routing material extends above a grid line */ + gaMinAbove = MIN(RtrMetalWidth, RtrPolyWidth); + gaMinAbove = MIN(gaMinAbove, RtrContactWidth - RtrContactOffset); + + /* Max distance any routing material extends below a grid line */ + gaMaxBelow = RtrContactOffset; + + /* Assign the stems (gaStemAssign() does the real work) */ + RtrStemProcessAll(routeUse, netList, GAStemWarn, gaStemAssign); + + if (DebugIsSet(gaDebugID, gaDebVerbose)) + { + TxPrintf("%d terminals processed.\n", gaNumLocs); + TxPrintf("%d internal, %d external, %d no channel.\n", + gaNumInt, gaNumExt, gaNumNoChan); + TxPrintf("%d paired internal stems.\n", gaNumPairs); + TxPrintf("%d degenerate.\n", gaNumDegenerate); + TxPrintf("%d discarded because inside normal channels.\n", gaNumInNorm); + TxPrintf("%d discarded because overlapped channel boundaries.\n", + gaNumOverlap); + TxPrintf("%d possible stems blocked by other terminals.\n", + gaNumNetBlock); + TxPrintf("%d possible stems to blocked pins.\n", gaNumPinBlock); + TxPrintf("%d simple paths, %d maze paths.\n", + gaNumSimpleStem, gaNumMazeStem); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * gaStemAssign -- + * + * Do the real work of gaStemAssignAll() above -- assign one or two + * crossing points to the terminal location 'loc'. + * + * Results: + * TRUE if successful, FALSE if no locations could be assigned. + * + * Side effects: + * May add one additional NLTermLoc to the list for 'loc', + * in the position immediately following loc, if this location + * is given two crossing points. The caller should be aware + * of this in traversing a linked list of NLTermLocs. + * + * ---------------------------------------------------------------------------- + */ + +bool +gaStemAssign(routeUse, doWarn, loc, term, net, netList) + CellUse *routeUse; /* Cell being routed */ + bool doWarn; /* If TRUE, leave feedback for each error */ + NLTermLoc *loc; /* Location considered */ + NLTerm *term; /* Terminal of which loc is a location */ + NLNet *net; /* Net to which it belongs */ + NLNetList *netList; /* Netlist (searched for blocking terminals) */ +{ + GCRChannel *ch; + + gaNumLocs++; + + /* + * See if this location lies inside a river-routing channel. + * If it does, return the channel containing it. + */ + if (ch = gaStemContainingChannel(routeUse, doWarn, loc)) + { + if (ch->gcr_type != CHAN_HRIVER && ch->gcr_type != CHAN_VRIVER) + goto fail; + gaNumInt++; + return (gaStemInternal(routeUse, doWarn, loc, net, ch, netList)); + } + + /* Not inside a river-routing channel. Try for a nearby normal channel */ + if (RtrStemAssignExt(routeUse, doWarn, loc, term, net)) + { + gaNumExt++; + return (TRUE); + } + + if (doWarn) + { + DBWFeedbackAdd(&loc->nloc_rect, + "No crossing reachable from terminal", + routeUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); + } + +fail: + gaNumNoChan++; + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaStemContainingChannel -- + * + * Find the channel containing 'loc' if there is one. This channel, + * if it exists, should be a river-routing channel. If it isn't, + * we leave feedback if 'doWarn' is TRUE. + * + * If loc is degenerate, it can't lie on the border of a channel + * (this restriction may be lifted later; it's just a pain to + * deal with now). + * + * It is illegal for loc to straddle a channel boundary. + * + * Results: + * Returns the channel as described above, or NULL if loc + * didn't lie in a channel or it violated one of the above + * conditions. + * + * Side effects: + * Leaves feedback in the event of errors, if 'doWarn' is TRUE. + * + * ---------------------------------------------------------------------------- + */ + +GCRChannel * +gaStemContainingChannel(routeUse, doWarn, loc) + CellUse *routeUse; /* For errors */ + bool doWarn; /* If TRUE, leave feedback if error */ + NLTermLoc *loc; /* Find a channel for this terminal */ +{ + GCRChannel *ch; + Rect area; + + /* Special handling is required for degenerate locs */ + area = loc->nloc_rect; + if (GEO_RECTNULL(&area)) + if (!gaStemGrow(&area)) + goto overlap; + + /* Ensure that only one channel is overlapped */ + ch = (GCRChannel *) NULL; + if (DBSrPaintArea((Tile *) NULL, RtrChannelPlane, &area, + &DBAllTypeBits, gaStemContainingChannelFunc, (ClientData) &ch)) + goto overlap; + + /* Illegal to be inside a normal channel */ + if (ch && ch->gcr_type == CHAN_NORMAL) + { + gaNumInNorm++; + if (doWarn) + { + DBWFeedbackAdd(&area, + "Terminal is inside a normal routing channel", + routeUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); + } + } + + return (ch); + +overlap: + gaNumOverlap++; + if (doWarn) + { + DBWFeedbackAdd(&area, + "Terminal overlaps a channel boundary", + routeUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); + } + return ((GCRChannel *) NULL); +} + +/* + * gaStemContainingChannelFunc -- + * + * Called via DBSrPaintArea on behalf of gaStemContainingChannel above + * for each tile overlapping the area of a terminal, to determine + * whether more than one channel is overlapped by that terminal. + * + * Results: + * Returns 0 normally, or 1 if *pCh was non-zero and + * the channel associated with tile was different from + * *pCh. + * + * Side effects: + * Sets *pCh to the channel associated with tile if there + * was one. + * + * ---------------------------------------------------------------------------- + */ + +int +gaStemContainingChannelFunc(tile, pCh) + Tile *tile; + GCRChannel **pCh; +{ + GCRChannel *ch; + + if (ch = (GCRChannel *) tile->ti_client) + { + if (*pCh) + { + if (ch != *pCh) + return (1); + } + else *pCh = ch; + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaStemGrow -- + * + * The terminal being processed (described by the initial value of *area) + * is degenerate, so figure out which side is of interest and grow *area + * in that direction. + * + * If *area is entirely contained by a channel or empty space, + * we don't have to do anything. If it lies on the border + * of a channel, then currently we reject it. + * + * Results: + * TRUE if area is entirely contained in either channel or empty + * space; FALSE otherwise. + * + * Side effects: + * Modifies *area as described above. + * + * ---------------------------------------------------------------------------- + */ + +bool +gaStemGrow(area) + Rect *area; +{ + Rect r; + GCRChannel *ch; + + r = *area; + if (r.r_xbot == r.r_xtop) r.r_xbot--, r.r_xtop++; + if (r.r_ybot == r.r_ytop) r.r_ybot--, r.r_ytop++; + gaNumDegenerate++; + + /* OK if either zero or one channel is overlapped */ + ch = (GCRChannel *) NULL; + if (DBSrPaintArea((Tile *) NULL, RtrChannelPlane, &r, + &DBAllTypeBits, gaStemContainingChannelFunc, (ClientData) &ch) == 0) + return (TRUE); + + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaStemInternal -- + * + * Having determined that 'loc' lies entirely within a river-routing + * channel, try to bring it out to both sides of the channel. + * + * If the terminal permits a grid aligned route, "simple" routes are + * tried first. A simple route is a grid aligned straight line from + * terminal to pin with a possible layer change at the terminal and + * another at the grid point just prior to the pin. If simple routes + * are not possible, the mzrouter() is called. + * + * Marks the pins in the channel OUTSIDE the river-routing channel with + * net (the ones INSIDE the river-routing channel are left blank, + * so the channel router won't try connecting them). Also sets gcr_pSeg + * for the outside pins to GCR_STEMSEGID to tell the global router that + * they are stem tips; the global router will reassign a real segment + * number to the crossing point when the stem tip is used. + * + * Each NLTermLoc has nloc_chan set to the channels on the outside + * of 'ch', rather than 'ch' itself, in order to be consistent with + * gaStemExternal. + * + * Results: + * TRUE if we succeeded in assigning one (or two) crossing points; + * FALSE if none could be assigned. + * + * Side effects: + * See above. + * May add one additional NLTermLoc to the list for 'loc', + * in the position immediately following loc, if this location + * is given two crossing points. + * + * ---------------------------------------------------------------------------- + */ + +bool +gaStemInternal(routeUse, doWarn, loc, net, ch, netList) + CellUse *routeUse; /* Cell being routed */ + bool doWarn; /* If TRUE, leave feedback on all errors */ + NLTermLoc *loc; /* Terminal being processed */ + NLNet *net; /* Used for marking pins */ + GCRChannel *ch; /* Channel containing loc */ + NLNetList *netList; /* Netlist (searched for blocking terminals) */ +{ + int min, max, start, lo, hi; + + /* Compute the grid lines that can be used for this terminal */ + gaStemGridRange(ch->gcr_type, &loc->nloc_rect, &min, &max, &start); + + /* + * Try each possibility until we find a grid line that is usable, + * or until we've run out of possibilities. Work outward from + * the starting point. We don't make any attempt to pick the + * best grid line, so if we see one early that can only be routed + * to one side, and one later that can be routed to both, we still + * pick the earlier. The greedy strategy is simpler, and also we + * expect that usually there will only be a single grid line per + * terminal. + */ + if (gaStemInternalFunc(routeUse, loc, net, ch, start, netList)) + return (TRUE); + for (lo = start - RtrGridSpacing, hi = start + RtrGridSpacing; + lo >= min || hi <= max; + lo -= RtrGridSpacing, hi += RtrGridSpacing) + { + if (lo >= min) + if (gaStemInternalFunc(routeUse, loc, net, ch, lo, netList)) + return (TRUE); + if (hi <= max) + if (gaStemInternalFunc(routeUse, loc, net, ch, hi, netList)) + return (TRUE); + } + + if (doWarn) + { + DBWFeedbackAdd(&loc->nloc_rect, + "Terminal can't be brought out to either channel boundary", + routeUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); + } + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaStemInternalFunc -- + * + * Try "simple" (straight line) routes and failing that mzroutes from + * terminal to pins on both sides of the channel. + * If it is possible to connect to one or both sides of the channel + * mark loc->nloc_stem, + * loc->nloc_chan, and loc->nloc_dir with the location of the + * crossing chosen (add a new loc to the list if two crossings were + * chosen), and mark the pins in the channels OUTSIDE of the crossings + * as described in the comments to gaStemInternal() above. The pin + * used for the crossing is stored in loc->nloc_pin. + * + * NOTE: loc->nloc_chan is the channel on the OUTSIDE of 'ch', + * rather than 'ch' itself. + * + * Results: + * TRUE on success, FALSE on failure. + * + * Side effects: + * See above, and also the comments to gaStemInternal(). + * + * ---------------------------------------------------------------------------- + */ + +bool +gaStemInternalFunc(routeUse, loc, net, ch, gridLine, netList) + CellUse *routeUse; + NLTermLoc *loc; + NLNet *net; + GCRChannel *ch; + int gridLine; + NLNetList *netList; +{ + GCRPin *pin1, *pin2; + NLTermLoc *loc2; + Point p1, p2; + int dir1, dir2; + + /* + * Compute the areas that must be searched to ensure that + * river-routes to the outside of the channel are possible. + */ + switch (ch->gcr_type) + { + case CHAN_HRIVER: + p1.p_x = ch->gcr_area.r_xbot; + p1.p_y = gridLine; + p2.p_x = ch->gcr_area.r_xtop; + p2.p_y = gridLine; + dir1 = GEO_WEST; + dir2 = GEO_EAST; + break; + case CHAN_VRIVER: + p1.p_x = gridLine; + p1.p_y = ch->gcr_area.r_ybot; + p2.p_x = gridLine; + p2.p_y = ch->gcr_area.r_ytop; + dir1 = GEO_SOUTH; + dir2 = GEO_NORTH; + break; + } + + if (DebugIsSet(gaDebugID, gaDebStems)) + { + TxPrintf("Loc: ll=(%d,%d) ur=(%d,%d)\n", + loc->nloc_rect.r_xbot, loc->nloc_rect.r_ybot, + loc->nloc_rect.r_xtop, loc->nloc_rect.r_ytop); + TxPrintf("Try crossings: L=(%d,%d) and R=(%d,%d)\n", + p1.p_x, p1.p_y, p2.p_x, p2.p_y); + } + + pin1 = gaStemCheckPin(routeUse, loc, ch, dir1, &p1, netList); + pin2 = gaStemCheckPin(routeUse, loc, ch, dir2, &p2, netList); + + if (DebugIsSet(gaDebugID, gaDebStems)) + { + if (pin1) TxPrintf("Success L=(%d,%d)\n", p1.p_x, p1.p_y); + if (pin2) TxPrintf("Success R=(%d,%d)\n", p2.p_x, p2.p_y); + if (pin1 == NULL && pin2 == NULL) + TxPrintf("FAILURE ON BOTH CROSSINGS\n"); + TxMore("--------"); + } + + if (pin1 == (GCRPin *) NULL && pin2 == (GCRPin *) NULL) + return (FALSE); + + if (pin1) + { + loc->nloc_dir = dir1; + loc->nloc_stem = p1; + loc->nloc_chan = pin1->gcr_linked->gcr_ch; + loc->nloc_pin = pin1->gcr_linked; + + /* Mark the crossing OUTSIDE ch */ + pin1->gcr_linked->gcr_pId = (GCRNet *) net; + pin1->gcr_linked->gcr_pSeg = GCR_STEMSEGID; + } + if (pin2) + { + if (pin1) + { + /* Allocate a new NLTermLoc to hold the second crossing */ + loc2 = (NLTermLoc *) mallocMagic(sizeof (NLTermLoc)); + *loc2 = *loc; + loc->nloc_next = loc2; + loc = loc2; + gaNumPairs++; + } + loc->nloc_dir = dir2; + loc->nloc_stem = p2; + loc->nloc_chan = pin2->gcr_linked->gcr_ch; + loc->nloc_pin = pin2->gcr_linked; + + /* Mark the crossing OUTSIDE ch */ + pin2->gcr_linked->gcr_pId = (GCRNet *) net; + pin2->gcr_linked->gcr_pSeg = GCR_STEMSEGID; + } + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaStemCheckPin -- + * + * Determine if the crossing point at 'point' is reachable from 'loc'. + * Simple connections are tried first. If these fail, the mzrouter module + * is called. + * + * It must normally be possible to connect to either layer in the + * adjacent channel (channel routing isn't guaranteed to leave a + * signal on a particular layer since the layer used depends on the + * channel orientation). However, if one layer is blocked in the + * channel, then we only need to connect to the other layer. + * + * Results: + * Returns the pin belonging to 'ch' and using the crossing + * point at 'point' if a river-route is possible, or NULL + * if no river-route is possible. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +GCRPin * +gaStemCheckPin(routeUse, terminalLoc, ch, side, gridPoint, netList) + CellUse *routeUse; /* Cell being routed */ + NLTermLoc *terminalLoc; /* Terminal */ + GCRChannel *ch; /* Channel whose pin we are to use */ + int side; /* Direction 'gridPoint' lies relative to 'loc' */ + Point *gridPoint; /* Crossing point to use */ + NLNetList *netList; /* Searched for obstructing terminals */ +{ + TileTypeBitMask destMask; + GCRPin *pin; + SimpleStem simple; + short code; + + /* + * Discard this pin immediately if any of the following are true: + * - it is already occupied by a net + * - it isn't adjacent to a usable channel (i.e, it has no gcr_linked + * pin or its gcr_linked pin is blocked) + * - there's another terminal from this netlist in the way + */ + pin = RtrPointToPin(ch, side, gridPoint); + if (pin->gcr_pId != (GCRNet *) NULL + || pin->gcr_linked == (GCRPin *) NULL + || pin->gcr_linked->gcr_pId != (GCRNet *) NULL) + { + gaNumPinBlock++; + return ((GCRPin *) NULL); + } + + if (!gaStemNetClear(&terminalLoc->nloc_rect, gridPoint, side, netList)) + { + gaNumNetBlock++; + return ((GCRPin *) NULL); + } + + /* + * What types are present at the pin location? + * Only worry about connecting to layers that aren't + * present in the channel. The code above assumes + * that two-layer blockages at channel boundaries + * will cause their corresponding pins to be marked + * as blocked. + */ + code = pin->gcr_ch->gcr_result[pin->gcr_x][pin->gcr_y]; + destMask = DBZeroTypeBits; + if ((code & GCRBLKM) == 0) TTMaskSetType(&destMask, RtrMetalType); + if ((code & GCRBLKP) == 0) TTMaskSetType(&destMask, RtrPolyType); + + ASSERT(!TTMaskEqual(&destMask, &DBZeroTypeBits), "gaStemCheckPin"); + + /* + * Try to do things the simple way first, considering routes + * of a very stylized nature: straight across with at most one + * layer change over the terminal, and another on the grid line + * just before the channel boundary. This avoids having to + * call the maze router if we don't need to. + */ + if (DebugIsSet(gaDebugID, gaDebNoSimple)) + goto hardway; + if (!gaStemSimpleInit(routeUse, terminalLoc, gridPoint, side, &simple)) + goto hardway; + if (TTMaskHasType(&destMask, RtrMetalType) + && !gaStemSimpleRoute(&simple, RtrMetalType, (CellDef *) NULL)) + { + goto hardway; + } + if (TTMaskHasType(&destMask, RtrPolyType) + && !gaStemSimpleRoute(&simple, RtrPolyType, (CellDef *) NULL)) + { + goto hardway; + } + + /* Win */ + gaNumSimpleStem++; + return pin; + +hardway: + /* Simple connections have failed, so try using mzrouter. A connection + * must be possible from EITHER ROUTING LAYER, so we know we can connect + * no matter how the channel is routed. + * + * NULL writeUse is used so no paint is generated, we just check + * if the connections are possible, deferring the actual stem generation + * until after channel routing, so we know what layers to connect to. + */ + { + bool writeFlag = FALSE; + TileTypeBitMask polyMask, metalMask; + TTMaskSetOnlyType(&polyMask, RtrPolyType); + TTMaskSetOnlyType(&metalMask, RtrMetalType); + + if(gaMazeRoute(routeUse, terminalLoc, gridPoint, polyMask, side, + writeFlag) && + gaMazeRoute(routeUse, terminalLoc, gridPoint, metalMask, side, + writeFlag)) + { + gaNumMazeStem++; + return pin; + } + else + { + return ((GCRPin *) NULL); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * gaStemNetClear -- + * + * Determine whether the area between termArea and the crossing point + * 'point' is clear of other terminals that might want to share the + * same grid line. The purpose of this procedure is primarily to avoid + * doing something silly in the following situation (both terminals share + * the same horizontal grid line in a CHAN_HRIVER river-routing channel): + * + * +---------------------------+ + * | | + * | +---+ +---+ | + * | | A | | B | | + * | +---+ +---+ | + * | | + * +---------------------------+ + * + * Here, terminal "A" should only be brought out to the left, and "B" + * only to the right of the channel, since to do otherwise would block + * a terminal completely. + * + * +++ Currently, we consider a path from termArea to point blocked + * +++ by another terminal T only if T can use a single grid line, + * +++ and this grid line is the same as that of point. + * + * Results: + * TRUE if no terminals share the same grid line, FALSE otherwise. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +gaStemNetClear(termArea, point, side, netList) + Rect *termArea; /* Area of the starting terminal */ + Point *point; /* Crossing point where we want to end up */ + int side; /* Direction of point relative to termArea */ + NLNetList *netList; /* Netlist to check for terminals to avoid */ +{ + int min, max, start, type, grid; + NLTermLoc *loc; + NLTerm *term; + NLNet *net; + Rect r; + + /* + * First cut: determine a search area large enough so that any + * terminals lying entirely outside of it can't possibly conflict + * with this one. + */ + switch (side) + { + case GEO_NORTH: + r.r_xbot = point->p_x - RtrSubcellSepUp; + r.r_xtop = point->p_x + RtrSubcellSepDown; + r.r_ybot = termArea->r_ytop; + r.r_ytop = point->p_y + RtrSubcellSepDown; + type = CHAN_VRIVER; + break; + case GEO_SOUTH: + r.r_xbot = point->p_x - RtrSubcellSepUp; + r.r_xtop = point->p_x + RtrSubcellSepDown; + r.r_ybot = point->p_y - RtrSubcellSepUp; + r.r_ytop = termArea->r_ybot; + type = CHAN_VRIVER; + break; + case GEO_WEST: + r.r_ybot = point->p_y - RtrSubcellSepUp; + r.r_ytop = point->p_y + RtrSubcellSepDown; + r.r_xbot = point->p_x - RtrSubcellSepUp; + r.r_xtop = termArea->r_xbot; + type = CHAN_HRIVER; + break; + case GEO_EAST: + r.r_ybot = point->p_y - RtrSubcellSepUp; + r.r_ytop = point->p_y + RtrSubcellSepDown; + r.r_xbot = termArea->r_xtop; + r.r_xtop = point->p_x + RtrSubcellSepDown; + type = CHAN_HRIVER; + break; + } + grid = (type == CHAN_HRIVER) ? point->p_y : point->p_x; + + /* Only need to do work if a terminal lies inside this search area */ + for (net = netList->nnl_nets; net; net = net->nnet_next) + { + if (!GEO_OVERLAP(&net->nnet_area, &r)) + continue; + for (term = net->nnet_terms; term; term = term->nterm_next) + { + for (loc = term->nterm_locs; loc; loc = loc->nloc_next) + if (GEO_OVERLAP(&loc->nloc_rect, &r)) + { + /* Only reject if both prefer same grid location */ + gaStemGridRange(type, &loc->nloc_rect, &min,&max,&start); + if (start == grid) + return (FALSE); + } + } + } + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaStemGridRange -- + * + * Determine the range of grid lines usable by the terminal whose + * area is 'r', for a river-routing channel whose type is 'type' + * (one of CHAN_HRIVER or CHAN_VRIVER). Usable grid lines are at + * most one grid line away from the relevant boundary of 'r'. + * Pick a starting grid line that is as close to the center of the + * range of usable grid points and that is also between the top + * and bottom (for CHAN_HRIVER) or left and right (for CHAN_VRIVER) + * of 'r'. + * + * Results: + * None. + * + * Side effects: + * Sets *pMinGrid, *pMaxGrid, and *pStart. + * + * ---------------------------------------------------------------------------- + */ + +void +gaStemGridRange(type, r, pMinGrid, pMaxGrid, pStart) + int type; + Rect *r; + int *pMinGrid, *pMaxGrid, *pStart; +{ + int min, max, start; + + switch (type) + { + case CHAN_HRIVER: + { + min = RTR_GRIDDOWN(r->r_ybot, RtrOrigin.p_y); + max = RTR_GRIDDOWN(r->r_ytop - gaMaxAbove, RtrOrigin.p_y); + start = (max + min)/2; + start = RTR_GRIDDOWN(start, RtrOrigin.p_y); + if (start < r->r_ybot && (start + RtrGridSpacing) < r->r_ytop) + { + start += RtrGridSpacing; + } + break; + } + case CHAN_VRIVER: + { + min = RTR_GRIDDOWN(r->r_xbot, RtrOrigin.p_x); + max = RTR_GRIDDOWN(r->r_xtop - gaMaxAbove, RtrOrigin.p_x); + start = (max + min)/2; + start = RTR_GRIDDOWN(start, RtrOrigin.p_x); + if (start < r->r_xbot && (start + RtrGridSpacing) < r->r_xtop) + { + start += RtrGridSpacing; + } + break; + } + default: + { + ASSERT(FALSE, "Bad channel type in gaStemGridRange"); + break; + } + } + max = MAX(max, start); + min= MIN(min, start); + *pMaxGrid = max; + *pMinGrid = min; + *pStart = start; +} + +/* + * ---------------------------------------------------------------------------- + * + * gaStemPaintAll -- + * + * Paint each stem that turned out to be connected. + * See gaStemPaint() for details. + * + * Results: + * None. + * + * Side effects: + * Adds paint to 'routeUse->cu_def'. + * + * ---------------------------------------------------------------------------- + */ + +void +gaStemPaintAll(routeUse, netList) + CellUse *routeUse; + NLNetList *netList; +{ + NLTermLoc *loc; + NLTerm *term; + int numInt; + NLNet *net; + + gaNumSimplePaint = 0; + gaNumMazePaint = 0; + gaNumExtPaint = 0; + RtrMilestoneStart("Painting stems"); + for (net = netList->nnl_nets; net; net = net->nnet_next) + { + for (term = net->nnet_terms; term; term = term->nterm_next) + for (loc = term->nterm_locs; loc; loc = loc->nloc_next) + { + if (SigInterruptPending) + goto out; + if (loc->nloc_dir > 0) + gaStemPaint(routeUse, loc); + } + RtrMilestonePrint(); + } + +out: + RtrMilestoneDone(); + if (DebugIsSet(gaDebugID, gaDebVerbose)) + { + numInt = gaNumSimplePaint + gaNumMazePaint; + TxPrintf("%d simple, %d maze, %d total internal stems.\n", + gaNumSimplePaint, gaNumMazePaint, numInt); + TxPrintf("%d external stems painted.\n", gaNumExtPaint); + TxPrintf("%d total stems painted.\n", numInt + gaNumExtPaint); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * gaStemPaint -- + * + * Paint a single stem. + * Terminals that don't lie inside a river-routing channel are "external" + * and are handled by the standard router stem-generator. Terminals that + * lie inside a river-routing channel are "internal"; they are connected + * to their stem tips on the channel boundary using simple routes if + * possible, and failing that using the Magic maze-router (mzrouter). + * + * Results: + * None. + * + * Side effects: + * Adds paint to 'routeUse->cu_def'. + * + * ---------------------------------------------------------------------------- + */ + +void +gaStemPaint(routeUse, terminalLoc) + CellUse *routeUse; + NLTermLoc *terminalLoc; +{ + TileTypeBitMask terminalLayerMask; /* Possible layers for stem at + terminal */ + TileTypeBitMask pinLayerMask; /* Possible layers for stem at pin */ + Rect errArea; + char *errReason; + GCRPin *pin; + short flags; + + /* + * Find the pin used for this stem. If this pin wasn't actually + * used by the global router, there's no point in routing a stem + * to it so we return. + */ + pin = terminalLoc->nloc_pin; + if (pin->gcr_pId == (GCRNet *) NULL) + return; + + /* + * Figure out which layers are OK to start routing and which + * layers are OK to finish up on. Perform a sanity check: + * if the destination layer isn't one of the legal routing + * layers, just return. (This will catch pins that were + * supposed to be routed by the channel router, but which + * it was unable to connect to). + */ + flags = pin->gcr_ch->gcr_result[pin->gcr_x][pin->gcr_y]; + if (!rtrStemMask(routeUse, terminalLoc, flags, + &terminalLayerMask, &pinLayerMask)) + { + errReason = "Terminal is not on a legal routing layer"; + GEO_EXPAND(&terminalLoc->nloc_rect, 1, &errArea); + goto failure; + } + + if (!TTMaskHasType(&pinLayerMask, RtrMetalType) + && !TTMaskHasType(&pinLayerMask, RtrPolyType)) + { + /* To do: connect down to pin layer with contacts. */ + /* Or, just let the maze router handle this. */ + } + + /* + * The terminal could be internal (terminalLoc->nloc_rect lies + * inside a river-routing channel) or external (terminalLoc->nloc_rect + * lies outside of a channel but the stem tip borders on a normal + * routing channel). In the latter case, use the old stem + * generation code (temporary measure until we get our own + * code working). + */ + + if (!RtrMazeStems && (pin->gcr_linked == (GCRPin *) NULL)) + { + /* Terminal didn't lie in a river-routing channel */ + (void) RtrStemPaintExt(routeUse, terminalLoc); + gaNumExtPaint++; + return; + } + + ASSERT(pin->gcr_linked->gcr_ch->gcr_type != CHAN_NORMAL, "gaStemPaint"); + + /* + * Try a simple stem. + */ + + if (!RtrMazeStems) + { + SimpleStem simple; + Point *gridPoint = &(terminalLoc->nloc_stem); + int side = terminalLoc->nloc_dir; + + if (gaStemSimpleInit(routeUse, terminalLoc, gridPoint, side, &simple)) + { + /* try ending on "metal" */ + if (TTMaskHasType(&pinLayerMask, RtrMetalType)) + { + if(gaStemSimpleRoute(&simple,RtrMetalType,routeUse->cu_def)) + { + gaNumSimplePaint++; + return; + } + } + /* didn't work, so try ending on "poly" */ + if (TTMaskHasType(&pinLayerMask, RtrPolyType)) + { + if(gaStemSimpleRoute(&simple,RtrPolyType,routeUse->cu_def)) + { + gaNumSimplePaint++; + return; + } + } + } + } + + /* + * Try the maze router. + */ + if (RtrMazeStems) + { + Point *pinPoint = &(terminalLoc->nloc_stem); + int side = terminalLoc->nloc_dir; + bool writeResult = TRUE; + + extern CellDef *gaMazeTopDef; /* Forward declaration quick hack. */ + + + /* Note that by not running the gate array router, we may not */ + /* have initialized the maze router at this point. */ + + if ((gaMazeTopDef == NULL) && (EditCellUse != NULL)) + if (gaMazeInit(EditCellUse) == FALSE) + goto totalLoss; + + + if(gaMazeRoute(routeUse, terminalLoc, pinPoint, pinLayerMask, side, + writeResult)) + { + gaNumMazePaint++; + + if(DebugIsSet(gaDebugID,gaDebShowMaze)) + /* Feedback all maze routes so we can check them + * (this will cause all maze routes to be reported as + * routing errors) + */ + { + Rect area; + + area = terminalLoc->nloc_rect; + GeoIncludePoint(&terminalLoc->nloc_stem, &area); + if (GEO_RECTNULL(&area)) + { + GEO_EXPAND(&area, 1, &area); + } + + DBWFeedbackAdd(&area, + "MAZE ROUTE", + routeUse->cu_def, + 1, + STYLE_PALEHIGHLIGHTS); + } + + return; + } + + } + + /* + * Total loss. + * This should never happen! But there are a few cases when it can, + * such as if we have given a difficult path to route from the channel, + * over obstructions, to the pin, requiring the maze router, and the + * maze router is not set up in the technology file. + */ + +totalLoss: + errReason = "Couldn't maze route final connection"; + errArea = terminalLoc->nloc_rect; + GeoIncludePoint(&terminalLoc->nloc_stem, &errArea); + if (GEO_RECTNULL(&errArea)) + { + GEO_EXPAND(&errArea, 1, &errArea); + } + +failure: + DBWFeedbackAdd(&errArea, errReason, routeUse->cu_def, 1, + STYLE_PALEHIGHLIGHTS); +} diff --git a/garouter/gaTest.c b/garouter/gaTest.c new file mode 100644 index 00000000..590be2cf --- /dev/null +++ b/garouter/gaTest.c @@ -0,0 +1,416 @@ +/* + * gaTest.c -- + * + * Testing code for the gate-array router. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/garouter/gaTest.c,v 1.2 2009/05/01 18:59:44 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "graphics/graphics.h" +#include "garouter/garouter.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "textio/txcommands.h" +#include "utils/main.h" +#include "utils/utils.h" +#include "commands/commands.h" +#include "utils/styles.h" + +bool gaInitialized = FALSE; + +ClientData gaDebugID = 0; + +int gaDebChanOnly = 0; +int gaDebChanStats = 0; +int gaDebMaze = 0; +int gaDebNoSimple = 0; +int gaDebPaintStems = 0; +int gaDebShowChans = 0; +int gaDebShowMaze = 0; +int gaDebStems = 0; +int gaDebVerbose = 0; +int gaDebNoClean = 0; + +/* Used in the "*garoute split" command */ +PlaneMask gaSplitPlaneMask; +void (*gaSplitPaintPlane)(); +Rect gaSplitArea; +int gaSplitType; + +/* Forward declarations */ + +void GAInit(); + + +/* + * ---------------------------------------------------------------------------- + * + * GATest -- + * + * Command interface for testing the gate-array router. + * + * Results: + * None. + * + * Side effects: + * Depends on the command; see below. + * + * ---------------------------------------------------------------------------- + */ + +void +GATest(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int n; + typedef enum { CLRDEBUG, SETDEBUG, SHOWDEBUG} cmdType; + static struct + { + char *cmd_name; + cmdType cmd_val; + } cmds[] = { + "clrdebug", CLRDEBUG, + "setdebug", SETDEBUG, + "showdebug", SHOWDEBUG, + 0 + }; + + GAInit(); + if (cmd->tx_argc == 1) + { + TxError("Must give subcommand\n"); + goto badCmd; + } + + n = LookupStruct(cmd->tx_argv[1], (LookupTable *) cmds, sizeof cmds[0]); + if (n < 0) + { + TxError("Unrecognized subcommand: %s\n", cmd->tx_argv[1]); +badCmd: + TxError("Valid subcommands:"); + for (n = 0; cmds[n].cmd_name; n++) + TxError(" %s", cmds[n].cmd_name); + TxError("\n"); + return; + } + + switch (cmds[n].cmd_val) + { + case SETDEBUG: + DebugSet(gaDebugID, cmd->tx_argc - 2, &cmd->tx_argv[2], TRUE); + break; + case CLRDEBUG: + DebugSet(gaDebugID, cmd->tx_argc - 2, &cmd->tx_argv[2], FALSE); + break; + case SHOWDEBUG: + DebugShow(gaDebugID); + break; + } + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * GAGenChans -- + * + * Generate gate-array channels over the area 'area'. These channels + * will be one of two types: CHAN_NORMAL, for channels over empty space, + * or chanType (either CHAN_HRIVER or CHAN_VRIVER) for channels over + * existing subcells. The output is a collection of "garoute channel" + * commands on the file 'f'. + * + * Results: + * None. + * + * Side effects: + * Writes to 'f'. + * + * ---------------------------------------------------------------------------- + */ + +void +GAGenChans(chanType, area, f) + int chanType; + Rect *area; + FILE *f; +{ + extern void DBPaintPlane0(), DBPaintPlaneVert(); + int gaSplitFunc(), gaSplitOut(); + static CellDef *genDef = (CellDef *) NULL; + static CellUse *genUse = (CellUse *) NULL; + TileTypeBitMask obstacleMask; + int halfUp, halfDown; + SearchContext scx; + Plane *plane; + + if (genDef == NULL) + DBNewYank("__GENCHANNEL__", &genUse, &genDef); + + /* + * Round the appropriate side of area down to the nearest + * center-grid line. + */ + halfDown = RtrGridSpacing / 2; + halfUp = RtrGridSpacing - halfDown; + switch (chanType) + { + case CHAN_HRIVER: + gaSplitPaintPlane = DBPaintPlane0; + area->r_ytop = RTR_GRIDDOWN(area->r_ytop - halfUp, RtrOrigin.p_y) + + halfUp; + area->r_ybot = RTR_GRIDUP(area->r_ybot + halfDown, RtrOrigin.p_y) + - halfDown; + break; + case CHAN_VRIVER: + gaSplitPaintPlane = DBPaintPlaneVert; + area->r_xtop = RTR_GRIDDOWN(area->r_xtop - halfUp, RtrOrigin.p_x) + + halfUp; + area->r_xbot = RTR_GRIDUP(area->r_xbot + halfDown, RtrOrigin.p_x) + - halfDown; + break; + } + + /* Make sure everything in 'area' is read */ + (void) DBCellReadArea(EditCellUse, area); + DBFixMismatch(); + + /* Start with a clean slate */ + DBCellClearDef(genDef); + + /* + * Basic algorithm: + * Find all cells in 'area'. Compute the bounding rectangle for + * each plane that can affect routing. Bloat by RtrSubcellSepUp or + * RtrSubcellSepDown (appropriate direction). Extend this to the top + * and bottom of 'area' for CHAN_HRIVER channels, or to the left and + * right of 'area' for CHAN_VRIVER ones, and paint into the DRC error + * plane of genDef. + */ + TTMaskSetMask3(&obstacleMask, &RtrPolyObstacles, &RtrMetalObstacles); + TTMaskSetType(&obstacleMask, RtrMetalType); + TTMaskSetType(&obstacleMask, RtrPolyType); + TTMaskSetType(&obstacleMask, RtrContactType); + gaSplitPlaneMask = DBTechTypesToPlanes(&obstacleMask); + gaSplitArea = *area; + gaSplitType = chanType; + scx.scx_use = EditCellUse; + scx.scx_area = gaSplitArea; + scx.scx_trans = GeoIdentityTransform; + plane = genDef->cd_planes[PL_DRC_ERROR]; + (void) DBCellSrArea(&scx, gaSplitFunc, (ClientData) plane); + + /* Output all the tiles that lie inside 'area' in 'plane */ + (void) DBSrPaintArea((Tile *) NULL, plane, &gaSplitArea, &DBAllTypeBits, + gaSplitOut, (ClientData) f); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaSplitOut -- + * + * Called for each tile inside the area that was processed by GAGenChans() + * above. Outputs each tile as the appropriate type of channel (space + * tiles are CHAN_NORMAL, non-space are either CHAN_HRIVER or CHAN_VRIVER) + * after first clipping to the area gaSplitArea. + * + * Results: + * Always returns 0. + * + * Side effects: + * Writes to 'f'. + * + * ---------------------------------------------------------------------------- + */ + +int +gaSplitOut(tile, f) + Tile *tile; + FILE *f; +{ + Rect r; + + TITORECT(tile, &r); + GeoClip(&r, &gaSplitArea); + if (GEO_RECTNULL(&r)) + return (0); + + fprintf(f, "garoute channel %d %d %d %d", + r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop); + if (TiGetType(tile) != TT_SPACE) + fprintf(f, " %s", gaSplitType == CHAN_HRIVER ? "h" : "v"); + fprintf(f, "\n"); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * gaSplitFunc -- + * + * Called for each cell in the area being processed by GAGenChans() + * above. Computes a "true" bounding box for the cell (only looking + * at the layers that are obstacles to routing), and then extends the + * box as follows: + * + * If producing CHAN_HRIVER channels, we extend the box to the + * top and bottom of gaSplitArea, and bloat it to the right and + * left to the next farthest-out line between two grid lines. + * + * If producing CHAN_VRIVER channels, we extend the box to the + * left and right of gaSplitArea, and bloat it to the top and + * bottom to the next farthest-out line between two grid lines. + * + * Results: + * Always returns 0. + * + * Side effects: + * Paints the bloated area into the DRC error plane of 'plane' + * with a TileType of 1. + * + * ---------------------------------------------------------------------------- + */ + +int +gaSplitFunc(scx, plane) + SearchContext *scx; + Plane *plane; +{ + int halfUp, halfDown; + CellDef *def = scx->scx_use->cu_def; + Rect r, rAll, rTrans; + int pNum; + + /* Compute the bounding rect for the interesting planes */ + rAll = GeoNullRect; + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (PlaneMaskHasPlane(gaSplitPlaneMask, pNum)) + { + if (DBBoundPlane(def->cd_planes[pNum], &r)) + (void) GeoInclude(&r, &rAll); + } + + GeoTransRect(&scx->scx_trans, &rAll, &rTrans); + GeoClip(&rTrans, &gaSplitArea); + + /* Skip if no area */ + if (GEO_RECTNULL(&rTrans)) + return (0); + + /* Extend in the appropriate direction and bloat in the other one */ + halfDown = RtrGridSpacing / 2; + halfUp = RtrGridSpacing - halfDown; + + switch (gaSplitType) + { + case CHAN_HRIVER: + rTrans.r_ytop = gaSplitArea.r_ytop; + rTrans.r_ybot = gaSplitArea.r_ybot; + rTrans.r_xtop += RtrSubcellSepUp; + rTrans.r_xbot -= RtrSubcellSepDown; + rTrans.r_xtop = RTR_GRIDUP(rTrans.r_xtop + halfDown, RtrOrigin.p_x) + - halfUp; + rTrans.r_xbot = RTR_GRIDDOWN(rTrans.r_xbot - halfUp, RtrOrigin.p_x) + + halfDown; + break; + case CHAN_VRIVER: + rTrans.r_xtop = gaSplitArea.r_xtop; + rTrans.r_xbot = gaSplitArea.r_xbot; + rTrans.r_ytop += RtrSubcellSepUp; + rTrans.r_ybot -= RtrSubcellSepDown; + rTrans.r_ytop = RTR_GRIDUP(rTrans.r_ytop + halfDown, RtrOrigin.p_y) + - halfUp; + rTrans.r_ybot = RTR_GRIDDOWN(rTrans.r_ybot - halfUp, RtrOrigin.p_y) + + halfDown; + break; + } + + /* Paint into DRC error plane */ + (*gaSplitPaintPlane)(plane, &rTrans, DBStdWriteTbl(1), + (PaintUndoInfo *) NULL, PAINT_NORMAL); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * GAInit -- + * + * One-time-only initialization for the gate-array router. + * Called after technology initialization. + * + * Results: + * None. + * + * Side effects: + * Register ourself with the debug module and list all + * debugging flags. Also initialize channel information. + * + * ---------------------------------------------------------------------------- + */ + +void +GAInit() +{ + int n; + static struct + { + char *di_name; + int *di_id; + } dflags[] = { + "chanonly", &gaDebChanOnly, + "chanstats", &gaDebChanStats, + "maze", &gaDebMaze, + "nosimple", &gaDebNoSimple, + "paintstems", &gaDebPaintStems, + "showchans", &gaDebShowChans, + "showmaze", &gaDebShowMaze, + "stems", &gaDebStems, + "verbose", &gaDebVerbose, + "noclean", &gaDebNoClean, + 0 + }; + + if (gaInitialized) + return; + + gaInitialized = TRUE; + + /* Register ourselves with the debugging module */ + gaDebugID = DebugAddClient("garouter", sizeof dflags/sizeof dflags[0]); + for (n = 0; dflags[n].di_name; n++) + *(dflags[n].di_id) = DebugAddFlag(gaDebugID, dflags[n].di_name); + + /* Initialize channel information */ + GAChannelInitOnce(); +} diff --git a/garouter/garouter.h b/garouter/garouter.h new file mode 100644 index 00000000..f00f4cbe --- /dev/null +++ b/garouter/garouter.h @@ -0,0 +1,103 @@ +/* + * garouter.h -- + * + * Header file for the gate-array router. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/garouter/garouter.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _GAROUTER_H +#define _GAROUTER_H + +#include "grouter/grouter.h" + +/* + * The following structure describes "simple stems" -- routes + * from a terminal to a grid point that are of a very simple + * style, involving a straight-across wire and at most one + * contact at either end. + */ + +typedef struct +{ + TileType sw_type; /* Type of wire */ + Rect sw_long; /* Wire all the way to dest */ + Rect sw_short; /* Wire only to pin contact */ + Rect sw_pinStub; /* Wire from pin contact to pin */ + bool sw_longOK; /* Space exists for long wire */ + bool sw_shortOK; /* Space exists for short wire (implied + * if sw_longOK is TRUE). + */ +} SimpleWire; + +typedef struct +{ + /* Terminal */ + TileType ss_termType; + Rect ss_termArea; + + TileTypeBitMask ss_termMask; /* If ss_termType is a contact type, + * this mask contains both metal and + * poly; otherwise, it contains just + * ss_termType. + */ + + /* Pin */ + int ss_dir; + Point ss_pinPoint; + + /* Information describing the wires to paint */ + SimpleWire ss_metalWire; /* Metal wire */ + SimpleWire ss_polyWire; /* Poly wire */ + + /* Contacts */ + Rect ss_cTerm; /* Contact over terminal */ + bool ss_cTermOK; /* Contact over terminal is OK */ + Rect ss_cPin; /* Contact near pin */ + bool ss_cPinOK; /* Contact near pin is OK */ +} SimpleStem; + +/* List of all active channels */ +extern GCRChannel *gaChannelList; + +/* Def used to hold channel plane */ +extern CellDef *gaChannelDef; + +/* Used during stem generation */ +extern int gaMinAbove; +extern int gaMaxAbove, gaMaxBelow; + + /* Debugging information */ +extern bool gaInitialized; /* TRUE if registered with debug module */ +extern ClientData gaDebugID; /* Our identity with the debugging module */ +#include "gaDebug.h" /* Can add flags without total recompile */ + +/* Internal procedures */ +extern GCRChannel *gaStemContainingChannel(); +extern GCRPin *gaStemCheckPin(); +extern int gaAlwaysOne(); +extern bool gaMazeRoute(); + +/* Exported procedures */ +extern int GARoute(); +extern void GAChannelInitOnce(); +extern void GAClearChannels(); +extern bool GADefineChannel(); +extern bool GAMazeInitParms(); + +/* Exported variables */ +extern bool GAStemWarn; + +#endif /* _GAROUTER_H */ diff --git a/gcr/Depend b/gcr/Depend new file mode 100644 index 00000000..20826ffd --- /dev/null +++ b/gcr/Depend @@ -0,0 +1,29 @@ +gcrChannel.o: gcrChannel.c ../utils/magic.h ../utils/geometry.h \ + ../gcr/gcr.h ../utils/malloc.h +gcrColl.o: gcrColl.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../gcr/gcr.h ../utils/malloc.h +gcrDebug.o: gcrDebug.c ../utils/magic.h ../utils/geometry.h \ + ../textio/textio.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../gcr/gcr.h ../utils/heap.h ../router/router.h \ + ../utils/malloc.h +gcrEdge.o: gcrEdge.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../gcr/gcr.h +gcrFeas.o: gcrFeas.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../gcr/gcr.h ../utils/hash.h ../database/database.h ../router/router.h +gcrFlags.o: gcrFlags.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../gcr/gcr.h +gcrInit.o: gcrInit.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../router/router.h ../gcr/gcr.h ../utils/malloc.h +gcrLib.o: gcrLib.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../gcr/gcr.h ../utils/malloc.h +gcrRiver.o: gcrRiver.c ../utils/magic.h ../utils/geometry.h ../gcr/gcr.h \ + ../textio/textio.h ../utils/malloc.h +gcrRoute.o: gcrRoute.c ../utils/magic.h ../utils/geometry.h ../gcr/gcr.h \ + ../utils/signals.h ../utils/malloc.h ../utils/styles.h +gcrShwFlgs.o: gcrShwFlgs.c ../utils/magic.h ../utils/geometry.h \ + ../utils/hash.h ../tiles/tile.h ../database/database.h \ + ../windows/windows.h ../dbwind/dbwind.h ../gcr/gcr.h ../utils/heap.h \ + ../router/router.h ../utils/main.h ../utils/styles.h ../textio/textio.h +gcrUnsplit.o: gcrUnsplit.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../gcr/gcr.h ../utils/malloc.h diff --git a/gcr/Makefile b/gcr/Makefile new file mode 100644 index 00000000..91d7b7ef --- /dev/null +++ b/gcr/Makefile @@ -0,0 +1,12 @@ +# +# rscid $Header: +# + +MODULE = gcr +MAGICDIR = .. +SRCS = gcrChannel.c gcrColl.c gcrDebug.c gcrEdge.c gcrFeas.c \ + gcrFlags.c gcrInit.c gcrLib.c gcrRiver.c gcrRoute.c gcrShwFlgs.c \ + gcrUnsplit.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/gcr/gcr.h b/gcr/gcr.h new file mode 100644 index 00000000..733609ac --- /dev/null +++ b/gcr/gcr.h @@ -0,0 +1,346 @@ +/* + * gcr.h -- + * + * Routines to implement a modified version of Rivest's Greedy Router. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/gcr/gcr.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + */ + +#ifndef _GCR_H +#define _GCR_H + +#include "utils/magic.h" + +/* GCRPin: One of these for each pin location along each edge of a channel. + * All of the pins for a given net are stored on a doubly-linked list + * for the net, sorted from left to right and bottom to top. Stored + * with the pin are its track and column coordinates (not the actual + * locations of terminals). + * + * A pin also stores crossing information for use by the global router, + * namely gcr_cost (the best cost known so far to reach this pin), + * gcr_side (GEO_NORTH, GEO_SOUTH, GEO_EAST, or GEO_WEST, giving the + * side of the channel that the pin lies on), and gcr_linked, pointing + * to the pin (in the neighboring channel) that shares the same crossing + * point as this one. + * + * x= 0 means the pin is at the left edge of the channel. + * x= length+1 means the pin is at the right edge of the channel. + * y= 0 means the pin is at the bottom edge of the channel. + * y= width+1 means the pin is at the top edge of the channel. + * + * A net id is in two parts, a net id (gcr_pId) and a segment + * id (gcr_pSeg). During global routing the net id is an integer + * net id, not a pointer to a struct (it doesn't turn into a + * pointer until just before channel routing). The segment id + * distinguishes parts of a net which are not connected within a + * channel because they are connected elsewhere (this prevents + * the router from generating loops in the routing). + */ +typedef struct pin +{ + int gcr_x, gcr_y; /* Column and track coordinates */ + + /* Information on nearest obstacle */ + int gcr_pFlags; /* 0=clear,1=Obstacle,2=Hazard */ + short gcr_pSize; /* Size of nearest obstacle */ + short gcr_pDist; /* Distance to nearest obstacle */ + + /* + * Net id and segment id assigned to this pin. + * Special semantics: + * gcr_pId == GCR_BLOCKEDNETID means this pin is blocked. + * gcr_pSeg == GCR_STEMSEGID means this pin is a stem tip; + * gcr_pId gives the net to which the stem tip belongs. + */ + int gcr_pSeg; /* Id naming part of a net id */ + struct gcrnet *gcr_pId; /* Net structure for pin's net */ + + /* + * These fields link available pins along the side of a channel + * during global routing, and link pins in a net during channel + * routing. + */ + struct pin *gcr_pNext; /* Next pin to the right or up */ + struct pin *gcr_pPrev; /* Next pin left or down */ + + /* + * Stuff for the global router. + * This is NOT valid in transformed channels, so should + * not be used by the channel router. + */ + int gcr_cost; /* Used during global routing */ + struct chan *gcr_ch; /* Channel to which this pin belongs */ + int gcr_side; /* Side of channel this pin lies on */ + struct pin *gcr_linked; /* Pin (in channel abutting this one) + * sharing same crossing point. + */ + Point gcr_point; /* Point along channel boundary + * in edit cell coords. + */ +} GCRPin; + +#define GCR_BLOCKEDNETID ((GCRNet *) -1) +#define GCR_STEMSEGID (-1) + +/* GCRNet: One structure for each net to be routed. Nets have pointers, + * to their leftmost and rightmost pins. The dist field stores the + * distance from an unsplit rising or falling active net's current + * track to its next connection. Nets are linked so they may be + * freed when the routing is complete. + * + * Each net_id/seg_id pair generates a unique gcrnet struct. + */ +typedef struct gcrnet +{ + int gcr_Id; /* Integer identifying the net */ + int gcr_dist; /* Distance to target track +/- */ + int gcr_sortKey; /* Use to prioritize nets */ + int gcr_track; /* Track index, used for working + * storage in colInit. + */ + GCRPin *gcr_lPin; /* Leftmost pin of net */ + GCRPin *gcr_rPin; /* Rightmost pin of net */ + struct gcrnet *gcr_next; /* Next on a linked list of nets */ +} GCRNet; + + +/* GRColEl: Used in array form, this struct stores horizontal and vertical + * wiring for the current column as it is routed. Locations 1..width are + * valid tracks, while 0 and width+1 are wiring to channel top and bottom. + * + * gcr_hi and gcr_lo are used to maintain ordered doubly linked lists of + * all tracks occupied by the same net. + * + * gcr_hOk and gcr_lOk are tricky. They are needed because we + * artificially split nets near the end of a channel if there + * are multiple end connections. The net must stay split, but + * what's tricky is that several groups of tracks may exist that + * are connected within the groups, but the groups haven't been + * connected together yet. These flags keep track of this information. + * For example, if gcr_hOk is TRUE but gcr_lOk is false, it + * means we don't need to collapse this track with the next one + * up, but we do need to join this track with the next one down. + * These flags are only used near the ends of channels, and are + * normally FALSE. + */ +typedef struct gcrColEl +{ + GCRNet * gcr_h; /* Net for horizontal wiring */ + GCRNet * gcr_v; /* Net for vertical wiring */ + int gcr_hi; /* Next higher track for net gcr_h */ + int gcr_lo; /* Next lower track for net gcr_h */ + bool gcr_hOk; /* TRUE if don't need to collapse up */ + bool gcr_lOk; /* TRUE if don't need to collapse dn */ + int gcr_flags; /* Flags from the "result" array */ + GCRNet * gcr_wanted; /* Net that wants this track for end pin*/ +} GCRColEl; + + +/* GCRChannel: + * + * Represents all information concerning a channel to be routed. + * In order to handle boundary conditions more easily, the grid + * arrays, such as gcr_lCol and gcr_result hold an extra grid + * point's worth on each side: the grids run from 0 through + * length+1 in x, and from 0 through width+1 in y. The actual + * channel is from 1..length and 1..width + */ + +#define CHAN_NORMAL 0 +#define CHAN_HRIVER 1 +#define CHAN_VRIVER 2 + +typedef struct chan +{ +/* Description of the channel */ + int gcr_type; /* CHAN_NORMAL (0) if a normal channel, + * CHAN_HRIVER if only horizontal river routes + * are allowed, CHAN_VRIVER if only vertical + * river routes are allowed. + */ + int gcr_length; /* Number of columns in the channel */ + int gcr_width; /* Number of tracks in the channel */ + Point gcr_origin; /* Grid 0 point */ + Rect gcr_area; /* Area of channel in edit cell coords */ + Transform gcr_transform; /* Transform used when cell has been flipped + * or rotated. Apply this transfrom to grid + * coords, scale by grid size, then displace + * by gcr_origin to get edit cell coords. + */ + +/* For use by the global router */ + short *gcr_dRowsByCol;/* Horizontal density during global routing */ + short *gcr_dColsByRow;/* Vertical density during global routing */ + short gcr_dMaxByCol; /* Max horizontal density */ + short gcr_dMaxByRow; /* Max vertical density */ +#define IDENSITY +#ifdef IDENSITY + short *gcr_iRowsByCol;/* FOR DEBUGGING */ + short *gcr_iColsByRow;/* FOR DEBUGGING */ +#endif /* IDENSITY */ + struct chan *gcr_next; /* For linked lists of channels */ + +/* Description of the connections */ + GCRPin *gcr_tPins; /* Pins at the top of the channel */ + GCRPin *gcr_bPins; /* Pins at the bottom of the channel */ + GCRPin *gcr_lPins; /* Pins at the left edge of the channel */ + GCRPin *gcr_rPins; /* Pins at the right edge of the channel */ + GCRNet *gcr_nets; /* Data for each net */ + +/* Working storage */ + GCRColEl *gcr_lCol; /* Column for vertical wiring */ + int *gcr_density; /* Density for each column */ + short **gcr_result; /* Array of columns, storing the result */ + +/* For hanging additional information in channels */ + ClientData gcr_client; /* For hire */ + int gcr_orient; /* Channel orientation */ +} GCRChannel; + +/* Macros that look like procedures */ + +/************************************************************************ + * Is1stPin(pin) + * GCRPin * pin; + * + * Return TRUE if the indexed pin is the first pin on its list. + */ +#define Is1stPin(pin) ((pin)==(pin)->gcr_pId->gcr_lPin) + +/************************************************************************ + * IsLstPin(pin) + * GCRPin * pin; + * + * Return TRUE if the indexed pin is the last pin on its list. + */ +#define IsLstPin(pin) ((pin)==(pin)->gcr_pId->gcr_rPin) + +/************************************************************************ + * GCRNearEnd(channel, column) + * GCRChannel * channel; + * int column; + * + * Return TRUE if the column is within GCREndDist of the end of the channel. + */ +#define GCRNearEnd(ch,col) (((ch)->gcr_length+1-(col)) <= GCREndDist) + +/************************************************************************ + * GCRPin1st(net) + * GCRNet * net; + * + * Return a pointer to the net's first pin. + */ +#define GCRPin1st(n) ((n)->gcr_lPin) + +/************************************************************************ + * GCRPinNext(pin) + * GCRPin * pin; + * + * Return a pointer to a net's next pin. + */ +#define GCRPinNext(p) ((p)->gcr_pNext) + +#define BLOCK(i) (((i)&GCRBLKM) && ((i)&GCRBLKP)) +#define CLEAR(i) (!((i)&(GCRBLKM|GCRBLKP))) +#define HAS_M(i) (((i)&GCRBLKM) && (!((i)&GCRBLKP))) +#define HAS_P(i) (((i)&GCRBLKP) && (!((i)&GCRBLKM))) +#define IS_EMPTY(c,x,y) ((x)<0 ? TRUE : ((x)>(c)->gcr_length ? TRUE : \ + CLEAR((c)->gcr_result[x][y]))) + + +/* + * Constants for the result array bits. Metal and poly here refer to + * the preferred materials for the long and short dimension of the + * channel. + */ + + /* + * The input routine sets these to show where the obstacles are. + * These entries need to be present in these positions. + */ +#define GCRBLKM 0x0001 /* 1 if the location is blocked with metal */ +#define GCRBLKP 0x0002 /* 1 if the location is blocked with poly */ + + /* The router sets these bits to show the wiring it produces */ +#define GCRU 0x0004 /* 1 if connect from track upwards */ +#define GCRR 0x0008 /* 1 if connect to the right */ +#define GCRX 0x0010 /* 1 if metal/poly contact */ + + /* + * These bits are used to indicate whether obstacles block tracks + * or columns for the density computation; they are reset to zero + * after density initialization so they don't interfere with the + * wiring bits above (which occupy the same bit positions and mean + * something entirely different). + */ +#define GCRBLKT 0x0004 /* Blocks a track */ +#define GCRBLKC 0x0008 /* Blocks a column */ + + /* The obstacle identifier sets these to say how to avoid obstacles */ +#define GCRVL 0x0020 /* 1 if the track should be vacated here */ +#define GCRV2 0x0040 /* 1 if vacate here due to 2-layer obstacle */ +#define GCRTC 0x0080 /* 1 if track contact needed */ +#define GCRCC 0x0100 /* 1 if column contact needed */ +#define GCRTE 0x0200 /* 1 if track can't be use in next column to rt */ +#define GCRCE 0x0400 /* 1 if column ends beyond this point */ + + /* The metal maximizer sets these bits */ +#define GCRVM 0x0800 /* 1 if vertical poly changed to metal */ +#define GCRXX 0x1000 /* 1 if via not deleted */ + + /* The hazard generation code uses these bits */ +#define GCRVR 0x2000 /* 1 if hazard to nets entering from the right */ +#define GCRVU 0x4000 /* 1 if hazard to nets entering from the top */ +#define GCRVD 0x8000 /* 1 if hazard to nets entering from the bottom */ +#define EMPTY -1 + +/* Flag bits used to indicate obstacles or hazards over pins */ +#define GCRCLR 0 /* No hazard or obstacle over crossing */ +#define GCRHAZRD 1 /* Hazard over crossing */ +#define GCROBST 2 /* Obstacle over crossing */ +#define GCRBLK 4 /* Blocked area over crossing */ +#define GCRTCC 8 /* Track or column contact near crossing */ + +/* Clip a value (e.g, column or track number) to lie within a range */ +#define INRANGE(x, min, max) \ + ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))) + +/* These are parameters the user sets to control the router. */ +extern int GCRMinJog; +extern int GCREndDist; +extern int GCRSteadyNet; +extern float GCRObstDist; +extern int GCRMinChannelSize; +extern bool GcrShowMap; +extern bool GcrShowEnd; +extern bool GcrShowResult; +extern bool GcrNoCheck; +extern bool GcrDebug; + + +/* Procedures exported by the greedy router to the rest of the world: */ + +extern GCRChannel *GCRNewChannel(); +extern void GCRFreeChannel(); +extern GCRChannel *GCRRouteFromFile(); +extern int GCRroute(); +extern void GCRFlipLeftRight(); +extern void GCRFlipXY(); +extern void GCRNoFlip(); +extern void GCRShow(); + +#endif /* _GCR_H */ diff --git a/gcr/gcrChannel.c b/gcr/gcrChannel.c new file mode 100644 index 00000000..0da9651b --- /dev/null +++ b/gcr/gcrChannel.c @@ -0,0 +1,494 @@ +/* + * gcrChannel.c - + * + * Channel manipulation: allocation, freeing, and transforming + * (e.g, flipping them left-to-right or rotating). Transforming + * is done so that the channel can be routed in the easiest + * direction. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrChannel.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "gcr/gcr.h" +#include "utils/malloc.h" + + +/* + * ---------------------------------------------------------------------------- + * + * GCRNewChannel -- + * + * This procedure allocates storage for a new channel structure, + * and initializes most of the structure. + * + * Results: + * The return value is a pointer to the new channel. + * + * Side effects: + * Storage is allocated. The initial state of the channel is + * completely empty, although all pin and result arrays are + * allocated. This procedure does not initialize the fields + * gcr_area, gcr_origin, or gcr_lCol, although it allocates + * storage for gcr_lCol. Also, it doesn't initialize the + * value of gcr_point for each pin. + * + * ---------------------------------------------------------------------------- + */ + +GCRChannel * +GCRNewChannel(length, width) + int length; /* Length of the channel (# of columns) */ + int width; /* Width of the channel (# rows) */ +{ + unsigned lenWds, widWds, nBytes; + GCRChannel *ch; + int i; + + lenWds = length + 2; + widWds = width + 2; + + ch = (GCRChannel *) mallocMagic((unsigned) (sizeof (GCRChannel))); + ch->gcr_type = CHAN_NORMAL; + ch->gcr_length = length; + ch->gcr_width = width; + ch->gcr_transform = GeoIdentityTransform; + ch->gcr_nets = (GCRNet *) NULL; + + /* Malloc storage for pin arrays and zero each */ + nBytes = lenWds * sizeof (GCRPin); + ch->gcr_tPins = (GCRPin *) mallocMagic((unsigned) nBytes); + ch->gcr_bPins = (GCRPin *) mallocMagic((unsigned) nBytes); + bzero((char *) ch->gcr_tPins, (int) nBytes); + bzero((char *) ch->gcr_bPins, (int) nBytes); + + nBytes = widWds * sizeof (GCRPin); + ch->gcr_lPins = (GCRPin *) mallocMagic((unsigned) nBytes); + ch->gcr_rPins = (GCRPin *) mallocMagic((unsigned) nBytes); + bzero((char *) ch->gcr_lPins, (int) nBytes); + bzero((char *) ch->gcr_rPins, (int) nBytes); + + ch->gcr_lCol = (GCRColEl *) mallocMagic((unsigned) (widWds * sizeof (GCRColEl))); + ch->gcr_density = (int *) mallocMagic((unsigned) (lenWds * sizeof (int))); + + /* Global router-specific initialization */ + ch->gcr_dRowsByCol = (short *) mallocMagic((unsigned) (lenWds * sizeof (short))); + bzero((char *) ch->gcr_dRowsByCol, (int) lenWds * sizeof (short)); + ch->gcr_dColsByRow = (short *) mallocMagic ((unsigned) (widWds * sizeof (short))); + bzero((char *) ch->gcr_dColsByRow, (int) widWds * sizeof (short)); + ch->gcr_dMaxByRow = ch->gcr_dMaxByCol = 0; + +#ifdef IDENSITY + /* For debugging */ + ch->gcr_iRowsByCol = (short *) mallocMagic((unsigned) (lenWds * sizeof (short))); + bzero((char *) ch->gcr_iRowsByCol, (int) lenWds * sizeof (short)); + ch->gcr_iColsByRow = (short *) mallocMagic((unsigned) (widWds * sizeof (short))); + bzero((char *) ch->gcr_iColsByRow, (int) widWds * sizeof (short)); +#endif /* IDENSITY */ + + ch->gcr_client = (ClientData) NULL; + + /* Allocate the result array */ + ch->gcr_result = (short **) mallocMagic ((unsigned) (lenWds * sizeof (short *))); + + /* + * Fill in fields of pins that aren't zero; also allocate + * and clear each row of the result array. + */ + nBytes = widWds * sizeof (short); + for (i = 0; i < lenWds; i++) + { + ch->gcr_result[i] = (short *) mallocMagic((unsigned) nBytes); + bzero((char *) ch->gcr_result[i], (int) nBytes); + + /* BOTTOM */ + ch->gcr_bPins[i].gcr_pDist = -1; + ch->gcr_bPins[i].gcr_x = i; + ch->gcr_bPins[i].gcr_y = 0; + + /* TOP */ + ch->gcr_tPins[i].gcr_pDist = -1; + ch->gcr_tPins[i].gcr_x = i; + ch->gcr_tPins[i].gcr_y = widWds - 1; + } + + for (i = 0; i < widWds; i++) + { + /* LEFT */ + ch->gcr_lPins[i].gcr_pDist = -1; + ch->gcr_lPins[i].gcr_x = 0; + ch->gcr_lPins[i].gcr_y = i; + + /* RIGHT */ + ch->gcr_rPins[i].gcr_pDist = -1; + ch->gcr_rPins[i].gcr_x = lenWds - 1; + ch->gcr_rPins[i].gcr_y = i; + } + + return (ch); +} + +/* + * ---------------------------------------------------------------------------- + * + * GCRFreeChannel -- + * + * This procedure frees up all the storage associated with + * a channel + * + * Results: + * None. + * + * Side effects: + * The storage of ch is completely freed. The caller should + * refrain from any use of the pointer after this procedure + * returns. + * + * ---------------------------------------------------------------------------- + */ + +void +GCRFreeChannel(ch) + GCRChannel *ch; /* Pointer to channel structure to be freed. */ +{ + GCRNet *net; + int i; + + freeMagic((char *) ch->gcr_tPins); + freeMagic((char *) ch->gcr_bPins); + freeMagic((char *) ch->gcr_lPins); + freeMagic((char *) ch->gcr_rPins); + for (net = ch->gcr_nets; net; net = net->gcr_next) + freeMagic((char *) net); + freeMagic((char *) ch->gcr_lCol); + + freeMagic((char *) ch->gcr_dRowsByCol); + freeMagic((char *) ch->gcr_dColsByRow); + +#ifdef IDENSITY + /* For debugging */ + freeMagic((char *) ch->gcr_iRowsByCol); + freeMagic((char *) ch->gcr_iColsByRow); +#endif /* IDENSITY */ + + freeMagic((char *) ch->gcr_density); + for (i = 0; i <= ch->gcr_length + 1; i++) + freeMagic((char *) ch->gcr_result[i]); + freeMagic((char *) ch->gcr_result); + freeMagic((char *) ch); +} + +/* + * ---------------------------------------------------------------------------- + * + * GCRFlipLeftRight -- + * + * This procedure will flip the contents of a channel left-to-right. + * + * Results: + * None. + * + * Side effects: + * The contents of channel dst are modified so that they are + * a left-to-right flip of src. Only the four pin arrays, the + * transform, the origin, the area, and the result array are + * modified. The other fields of dst are untouched. This means, + * in particular, that this procedure should be called BEFORE + * the linked lists for nets get set up, or else AFTER all the + * channel routing has been done and the nets have been freed up. + * Also, this procedure does not transform the flag bits GCRTE or + * GCRCE, so this procedure shouldn't be called when those flags + * are significant. + * + * ---------------------------------------------------------------------------- + */ + +void +GCRFlipLeftRight(src, dst) + GCRChannel *src; /* Original channel. */ + GCRChannel *dst; /* Channel to be modified to contain + * transformed info from src. The two + * channels must have the same dimensions, + * but must not be the same channel. + */ +{ + int y, lenWds, widWds; + short old, new; + int i, j; + Transform t; + + ASSERT(src->gcr_length == dst->gcr_length, "GCRFlipLeftRight: mismatch"); + ASSERT(src->gcr_width == dst->gcr_width, "GCRFlipLeftRight: mismatch"); + + lenWds = src->gcr_length + 1; + widWds = src->gcr_width + 1; + + for (i = 0; i <= lenWds; i++) + { + j = lenWds - i; + + /* Exchange pairs of pins in the top and bottom arrays */ + dst->gcr_tPins[j] = src->gcr_tPins[i]; + dst->gcr_tPins[j].gcr_x = j; + dst->gcr_bPins[j] = src->gcr_bPins[i]; + dst->gcr_bPins[j].gcr_x = j; + + /* + * Go through the result array, exchanging flag values. Also, + * be careful to switch the left-right hazard bits now that the + * sense of the channel is reversed. Also switch the GCRR bit + * in case there's been routing done. + */ + for (y = 0; y <= widWds; y++) + { + old = src->gcr_result[i][y]; + new = old & ~(GCRVR|GCRVL|GCRR); + if (old & GCRVR) new |= GCRVL; + if (old & GCRVL) new |= GCRVR; + if (i != 0 && (src->gcr_result[i-1][y] & GCRR)) + new |= GCRR; + dst->gcr_result[j][y] = new; + } + } + + /* Switch the left and right end pins */ + for (i = 0; i <= widWds; i++) + { + dst->gcr_lPins[i] = src->gcr_rPins[i]; + dst->gcr_lPins[i].gcr_x = 0; + dst->gcr_rPins[i] = src->gcr_lPins[i]; + dst->gcr_rPins[i].gcr_x = widWds; + } + + /* Copy the horizontal and vertical density information */ + dst->gcr_dMaxByCol = src->gcr_dMaxByCol; + dst->gcr_dMaxByRow = src->gcr_dMaxByRow; + bcopy((char *) src->gcr_dColsByRow, (char *) dst->gcr_dColsByRow, + sizeof (short) * widWds); +#ifdef IDENSITY + bcopy((char *) src->gcr_iColsByRow, (char *) dst->gcr_iColsByRow, + sizeof (short) * widWds); +#endif /* IDENSITY */ + for (i = 0; i <= lenWds; i++) + { + /* Flip left-to-right */ + j = lenWds - i; + dst->gcr_dRowsByCol[j] = src->gcr_dRowsByCol[i]; +#ifdef IDENSITY + dst->gcr_iRowsByCol[j] = src->gcr_iRowsByCol[i]; +#endif /* IDENSITY */ + } + + /* Now fix up the transform of the new channel */ + GeoTranslateTrans(&GeoSidewaysTransform, src->gcr_length+1, 0, &t); + GeoTransTrans(&t, &src->gcr_transform, &dst->gcr_transform); + dst->gcr_origin = src->gcr_origin; + dst->gcr_area = src->gcr_area; + dst->gcr_type = src->gcr_type; +} + +/* + * ---------------------------------------------------------------------------- + * + * GCRFlipXY -- + * + * This procedure rotates and flips a channel to interchange + * x and y coordinates. + * + * Results: + * None. + * + * Side effects: + * The contents of channel dst are modified so that they are + * a x-y flip of src. See comments for GCRFlipLeftRight for + * warnings about when it is and isn't safe to call this + * procedure. + * + * ---------------------------------------------------------------------------- + */ + +void +GCRFlipXY(src, dst) + GCRChannel *src; /* Original channel. */ + GCRChannel *dst; /* Channel to be modified to contain + * transformed info from src. + */ +{ + static Transform flipxy = {0, 1, 0, 1, 0, 0}; + int tmp, lenWds, widWds; + short old, new; + int i, j; + + ASSERT(src->gcr_width == dst->gcr_length, "gcrFlipXY: channel mismatch"); + ASSERT(src->gcr_length == dst->gcr_width, "gcrFlipXY: channel mismatch"); + + lenWds = src->gcr_length + 1; + widWds = src->gcr_width + 1; + + /* First, flip the side pins to top and bottom */ + for (i = 0; i <= widWds; i++) + { + dst->gcr_tPins[i] = src->gcr_rPins[i]; + tmp = dst->gcr_tPins[i].gcr_x; + dst->gcr_tPins[i].gcr_x = dst->gcr_tPins[i].gcr_y; + dst->gcr_tPins[i].gcr_y = tmp; + dst->gcr_bPins[i] = src->gcr_lPins[i]; + tmp = dst->gcr_bPins[i].gcr_x; + dst->gcr_bPins[i].gcr_x = dst->gcr_bPins[i].gcr_y; + dst->gcr_bPins[i].gcr_y = tmp; + } + + /* Same thing except flip top and bottom pins to sides */ + for (i = 0; i <= lenWds; i++) + { + dst->gcr_rPins[i] = src->gcr_tPins[i]; + tmp = dst->gcr_rPins[i].gcr_x; + dst->gcr_rPins[i].gcr_x = dst->gcr_rPins[i].gcr_y; + dst->gcr_rPins[i].gcr_y = tmp; + dst->gcr_lPins[i] = src->gcr_bPins[i]; + tmp = dst->gcr_lPins[i].gcr_x; + dst->gcr_lPins[i].gcr_x = dst->gcr_lPins[i].gcr_y; + dst->gcr_lPins[i].gcr_y = tmp; + } + + /* + * Now flip the result array. EXTRA SPECIAL TRICKINESS: the + * GCRBLKM and GCRBLKP flags must get switched, because what + * blocked a column in the old channel blocks a row in the + * new one. + */ + for (i = 0; i <= lenWds; i++) + for (j = 0; j <= widWds; j++) + { + old = src->gcr_result[i][j]; + new = old & ~(GCRVR|GCRVL|GCRVU|GCRVD|GCRR|GCRU|GCRBLKM|GCRBLKP); + if (old & GCRVR) new |= GCRVU; + if (old & GCRVU) new |= GCRVR; + if (old & GCRVL) new |= GCRVD; + if (old & GCRVD) new |= GCRVL; + if (old & GCRR) new |= GCRU; + if (old & GCRU) new |= GCRR; + if (old & GCRBLKM) new |= GCRBLKP; + if (old & GCRBLKP) new |= GCRBLKM; + dst->gcr_result[j][i] = new; + } + + /* Copy the horizontal and vertical density information */ + dst->gcr_dMaxByRow = src->gcr_dMaxByCol; + dst->gcr_dMaxByCol = src->gcr_dMaxByRow; + bcopy((char *) src->gcr_dRowsByCol, (char *) dst->gcr_dColsByRow, + sizeof (short) * lenWds); + bcopy((char *) src->gcr_dColsByRow, (char *) dst->gcr_dRowsByCol, + sizeof (short) * widWds); +#ifdef IDENSITY + bcopy((char *) src->gcr_iRowsByCol, (char *) dst->gcr_iColsByRow, + sizeof (short) * lenWds); + bcopy((char *) src->gcr_iColsByRow, (char *) dst->gcr_iRowsByCol, + sizeof (short) * widWds); +#endif /* IDENSITY */ + + /* Lastly, make a new transform */ + GeoTransTrans(&flipxy, &src->gcr_transform, &dst->gcr_transform); + dst->gcr_origin = src->gcr_origin; + dst->gcr_area = src->gcr_area; + switch (src->gcr_type) + { + case CHAN_HRIVER: dst->gcr_type = CHAN_VRIVER; break; + case CHAN_VRIVER: dst->gcr_type = CHAN_HRIVER; break; + default: dst->gcr_type = CHAN_NORMAL; break; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * GCRNoFlip -- + * + * This procedure performs the identity transform. It makes a copy. + * + * Results: + * None. + * + * Side effects: + * The contents of channel dst are modified so that they are + * a copy of src. Only the four pin arrays, the transform, the + * the area, and the result array are modified. The other fields + * of dst are untouched. This means, + * in particular, that this procedure should be called BEFORE + * the linked lists for nets get set up, or else AFTER all the + * channel routing has been done and the nets have been freed up. + * + * ---------------------------------------------------------------------------- + */ + +void +GCRNoFlip(src, dst) + GCRChannel *src; /* Original channel. */ + GCRChannel *dst; /* Channel to be modified to contain + * transformed info from src. The two + * channels must have the same dimensions, + * but must not be the same channel. + */ +{ + int lenWds, widWds, pinBytes, resBytes; + int i; + + ASSERT(src->gcr_length == dst->gcr_length, "GCRFlipLeftRight: mismatch"); + ASSERT(src->gcr_width == dst->gcr_width, "GCRFlipLeftRight: mismatch"); + + lenWds = src->gcr_length + 1; + widWds = src->gcr_width + 1; + + /* Copy pairs of pins in the top and bottom arrays */ + pinBytes = lenWds * sizeof (GCRPin); + bcopy((char *) src->gcr_tPins, (char *) dst->gcr_tPins, pinBytes); + bcopy((char *) src->gcr_bPins, (char *) dst->gcr_bPins, pinBytes); + + /* Copy flag values from the result array */ + resBytes = widWds * sizeof (short); + for (i = 0; i <= lenWds; i++) + bcopy((char *)src->gcr_result[i], (char *)dst->gcr_result[i], resBytes); + + /* Copy the left and right end pins */ + pinBytes = widWds * sizeof (GCRPin); + bcopy((char *) src->gcr_lPins, (char *) dst->gcr_lPins, pinBytes); + bcopy((char *) src->gcr_rPins, (char *) dst->gcr_rPins, pinBytes); + + /* Copy the horizontal and vertical density information */ + dst->gcr_dMaxByCol = src->gcr_dMaxByCol; + dst->gcr_dMaxByRow = src->gcr_dMaxByRow; + bcopy((char *) src->gcr_dRowsByCol, (char *) dst->gcr_dRowsByCol, + sizeof (short) * lenWds); + bcopy((char *) src->gcr_dColsByRow, (char *) dst->gcr_dColsByRow, + sizeof (short) * widWds); +#ifdef IDENSITY + bcopy((char *) src->gcr_iRowsByCol, (char *) dst->gcr_iRowsByCol, + sizeof (short) * lenWds); + bcopy((char *) src->gcr_iColsByRow, (char *) dst->gcr_iColsByRow, + sizeof (short) * widWds); +#endif /* IDENSITY */ + + /* Now fix up the transform of the new channel */ + dst->gcr_origin = src->gcr_origin; + dst->gcr_transform = src->gcr_transform; + dst->gcr_area = src->gcr_area; + dst->gcr_type = src->gcr_type; +} diff --git a/gcr/gcrColl.c b/gcr/gcrColl.c new file mode 100644 index 00000000..003de9a9 --- /dev/null +++ b/gcr/gcrColl.c @@ -0,0 +1,397 @@ +/* gcrColl.c - + * + * The greedy router: Collapsing split nets. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrColl.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "gcr/gcr.h" +#include "utils/malloc.h" + +/* Variables to save the best pattern of collapsing jogs. They get their + * initialized values from an initial call to gcrEvalPat. + * + * gcrBestCol: The best column of collapsing jogs seen so far. + * gcrBestFreed: The number of tracks freed by the pattern in gcrBestCol + */ +GCRColEl * gcrBestCol=(GCRColEl *) NULL; +int gcrBestFreed; +int gcrSplitNets; +int * gcrNthSplit=(int *) NULL; + +/* Forward declarations */ +void gcrEvalPat(); + + +/* + * ---------------------------------------------------------------------------- + * gcrCollapse -- + * + * Add vertical segments to this column to collapse split nets in a + * pattern that will create the most empty tracks. Generate all legal + * combinations and pick the best. + * + * Results: + * None. + * + * Side effects: + * If the evaluated column is the best seen, then gcrEvalPat saves it + * away. In any event, gcrEvalPat sets its col argument to NULL. + * ---------------------------------------------------------------------------- + */ + +void +gcrCollapse(col, width, bot, top, freed) + GCRColEl ** col; + int width; + int bot; + int top; + int freed; +{ + int i, to; + GCRNet * net; + GCRColEl * newCol, *gcrCopyCol(); + + ASSERT(freed<=width, "gcrCollapse."); + for(i=bot; i<=top; i++) + { + /* If net at i is split with a higher track, and there is no + * interfering vertical wiring placed in a previous step... + */ + to= (*col)[i].gcr_hi; + if((to==EMPTY) || (*col)[i].gcr_hOk) + continue; + + /* ...except that the collapse should be skipped if both tracks involved + * are where they are supposed to be to make connections at the end of the + * channel. + */ + /* comment out for a test + if(((*col)[i].gcr_h==(*col)[i].gcr_wanted) && + ((*col)[to].gcr_h==(*col)[to].gcr_wanted)) + continue; + */ + + if( gcrVertClear( *col, i, to) ) + { + /* There is one freed track for each collapsing jog, plus + * one additional track for every net finished. + */ + net=(*col)[i].gcr_h; + newCol=gcrCopyCol( *col, width); + if( ((*col)[to].gcr_wanted!=net) && + ((*col)[ i].gcr_wanted==net) ) + gcrMoveTrack(newCol, net, to, i); + else + gcrMoveTrack(newCol, net, i, to); + if(newCol[to].gcr_h!=(GCRNet *) NULL) + { + if((newCol[to].gcr_hi== EMPTY) && (newCol[to].gcr_lo== EMPTY) && + (GCRPin1st(newCol[to].gcr_h)==(GCRPin *) NULL)) + gcrCollapse(&newCol, width, to, top, freed+2); + else + gcrCollapse(&newCol, width, to, top, freed+1); + } + if(top>to) + top=to-1; + } + } + gcrEvalPat( col, freed, width); + *col=(GCRColEl *) NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrInitCollapse -- + * + * This procedure sets up the data structure used in determining + * optimal split-net collapses. It must be called before the + * first call to gcrEvalPat to make sure that there's a large + * enough internal structure. + * + * Results: + * None. + * + * Side effects: + * The gcrNthSplit array is allocated. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrInitCollapse(size) + int size; /* Number of tracks in column. */ +{ + gcrBestFreed = 0; + gcrSplitNets = -1; + if(gcrNthSplit) + freeMagic((char *) gcrNthSplit); + + gcrNthSplit =(int *) mallocMagic((unsigned) size*sizeof(int)); + ASSERT(gcrNthSplit, "gcrEvalPat: mallocMagic failed"); + if (gcrBestCol) + { + freeMagic((char *) gcrBestCol); + gcrBestCol = (GCRColEl *) NULL; + } +} + +/* + * ---------------------------------------------------------------------------- + * gcrEvalPat -- + * + * Evaluate a pattern of jogs to determine whether it is better than + * a previous pattern. Evaluation criteria in order of importance: + * 1. Highest number of tracks freed. + * 2. Outermost uncollapsed split nets furthest from channel edge. + * 3. Largest sum of jog lengths. + * Results: + * None. + * + * Side effects: + * If col better than previously best, then free previous best, save col + * in gcrBestCol, save tracks freed in gcrBestFreed, and set *col to NULL. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrEvalPat(col, freed, size) + GCRColEl ** col; /* Describes column in which to collapse. */ + int freed; /* We've already found a set of collapsing + * jogs that frees at least this many tracks. + */ + int size; /* Number of tracks in column. */ +{ + int i, n, newDist, oldWiring, newWiring; + + if(gcrBestCol==(GCRColEl *) NULL) + { + gcrBestCol= *col; + gcrBestFreed=freed; + return; + } + + if(freed>gcrBestFreed) goto newBetter; + if(freedgcrSplitNets) /* Don't recompute previously found values */ + gcrNthSplit[++gcrSplitNets]=gcrNextSplit(gcrBestCol, size, i); + + if (gcrNthSplit[n]>size) /* No more uncollapsed split nets */ + goto oldBetter; + + newDist=gcrNextSplit(*col, size, i); + if(newDistnewWiring) goto oldBetter; + else goto newBetter; + + /* We get here when we find out that the new pattern is better than + * the old pattern. + */ + + newBetter: + if (gcrBestCol != NULL) freeMagic((char *) gcrBestCol); + gcrBestCol = *col; + gcrBestFreed = freed; + return; + + /* We get here when we find out that the old pattern is still best. */ + + oldBetter: + freeMagic((char *) *col); + return; +} + +/* + * ---------------------------------------------------------------------------- + * gcrNextSplit -- + * + * Given a distance i from the channel edge, search inward from the top + * and bottom of the channel for the next uncollapsed split net. + * If there aren't any, return size+1. + * + * Results: + * Return the distance from the channel edge to the next split net. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +int +gcrNextSplit(col, size, i) + GCRColEl * col; + int size; + int i; +{ + for(i++; igcr_lCol==(GCRColEl *) NULL, "gcrPickBest"); + ch->gcr_lCol=gcrBestCol; + gcrBestCol=(GCRColEl *) NULL; +} + +/* + * ---------------------------------------------------------------------------- + * gcrReduceRange -- + * + * Scan from the outside in, trying to move the outermost top track + * of each uncollapsed split net downward, and trying to move the + * outermost bottom track of each uncollapsed split net upwards. + * Make no jogs which are shorter than minimum jog length. + * + * Results: + * None. + * + * Side effects: + * Adjust the list of occupied tracks for the net. + * ---------------------------------------------------------------------------- + */ + +void +gcrReduceRange(col, width) + GCRColEl * col; + int width; +{ + int i, j; + int farthest; + GCRNet * net; + bool clear; + + for(i=1; i=GCRMinJog) + gcrMoveTrack(col, net, i, farthest); + } + + /* Find the highest track assigned to an uncollapsed split net */ + farthest=width+1-i; + if((col[farthest].gcr_hi== EMPTY)&&(col[farthest].gcr_lo!= EMPTY) + &&(col[farthest].gcr_h!=col[farthest].gcr_wanted) + && !col[farthest].gcr_lOk) + { + clear=!(col[i].gcr_flags & (GCRBLKM | GCRBLKP)); + net=col[farthest].gcr_h; + for(j=farthest-1; j>0; j--) + { + if((net==col[j].gcr_h) && col[j].gcr_lOk) + break; + if(gcrBlocked(col, j, net, 0)) + break; + + /* If the original track was clear, don't move into a blocked + * track. + */ + if(clear && (col[j].gcr_flags & (GCRBLKM | GCRBLKP))) + break; + + if( (col[j].gcr_h==(GCRNet *) NULL) && + !(col[j].gcr_flags & GCRCC) ) + { + farthest=j; + if(col[j].gcr_lo== EMPTY) + break; + } + } + if((width+1-i-farthest)>=GCRMinJog) + gcrMoveTrack(col, net, width+1-i, farthest); + } + } +} diff --git a/gcr/gcrDebug.c b/gcr/gcrDebug.c new file mode 100644 index 00000000..efb5c052 --- /dev/null +++ b/gcr/gcrDebug.c @@ -0,0 +1,1024 @@ +/* gcrDebug.c - + * + * The greedy router, debug routines. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrDebug.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "textio/textio.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "utils/heap.h" +#include "router/router.h" +#include "utils/malloc.h" + +int gcrViaCount; +bool GcrShowEnd = FALSE; +bool GcrShowMap = FALSE; +int gcrStandalone=FALSE; /*Flag to control standalone/integrated operation*/ + +/* Forward declarations */ +void gcrDumpResult(); +void gcrStats(); +void gcrShowMap(); +bool gcrMakeChannel(); + +void gcrPrintCol(GCRChannel *, int, int); + + + +/* + * ---------------------------------------------------------------------------- + * + * GCRRouteFromFile -- + * + * Reads a routing problem from the named file and performs the routing. + * + * Results: + * Returns a pointer to the routed channel. + * + * Side effects: + * Allocates memory. + * + * ---------------------------------------------------------------------------- + */ + +GCRChannel * +GCRRouteFromFile(fname) + char *fname; +{ + static Point initOrigin = { 0, 0 }; + struct tms tbuf1, tbuf2; + GCRChannel *ch; + Transform trans; + FILE *fp; + Rect box; + + fp = fopen(fname, "r"); + if (fp == NULL) + { + perror(fname); + return ((GCRChannel *) NULL); + } + + ch = (GCRChannel *) mallocMagic((unsigned) (sizeof (GCRChannel))); + ch->gcr_type = CHAN_NORMAL; +/* ch->gcr_area = box; */ + ch->gcr_transform = GeoIdentityTransform; + ch->gcr_lCol = (GCRColEl *) NULL; + ch->gcr_nets = (GCRNet *) NULL; + ch->gcr_result = (short **) NULL; + ch->gcr_origin = initOrigin; + + if (!gcrMakeChannel(ch, fp)) + { + TxError("Couldn't initialize channel routing problem\n"); + (void) fclose(fp); + freeMagic((char *) ch); + return ((GCRChannel *) NULL); + } + + (void) fclose(fp); + ch->gcr_lCol = (GCRColEl *) mallocMagic((unsigned) ((ch->gcr_width+2) * sizeof (GCRColEl))); + times(&tbuf1); + (void) GCRroute(ch); + times(&tbuf2); + TxPrintf("Time : %5.2fu %5.2fs\n", (tbuf2.tms_utime - + tbuf1.tms_utime)/60.0, (tbuf2.tms_stime-tbuf1.tms_stime)*60); + + gcrDumpResult(ch, GcrShowEnd); + gcrShowMap(ch); + return (ch); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrMakeChannel -- + * + * Read a channel in the new file format. + * + * Results: + * TRUE if successful, FALSE if not. + * + * Side effects: + * Sets values in *channel. + * + * ---------------------------------------------------------------------------- + */ + +bool +gcrMakeChannel(ch, fp) + GCRChannel *ch; + FILE *fp; +{ + GCRPin *gcrMakePinLR(); + unsigned lenWds, widWds; + int i, j, c, pid; + char s[25]; + + c = getc(fp); + if (c != '*') + { + TxError("Old-style channel format no longer supported.\n"); + return (FALSE); + } + + if (fscanf(fp, "%d %d", &ch->gcr_width, &ch->gcr_length) != 2) + { + TxError("Format error in input file width or length.\n"); + return (FALSE); + } + + lenWds = ch->gcr_length + 2; + widWds = ch->gcr_width + 2; + ch->gcr_density = (int *) mallocMagic((unsigned) (lenWds * sizeof (int))); + ch->gcr_lPins = gcrMakePinLR(fp, 0, ch->gcr_width); + ch->gcr_tPins = (GCRPin *) mallocMagic((unsigned) (lenWds * sizeof (GCRPin))); + ch->gcr_bPins = (GCRPin *) mallocMagic((unsigned) (lenWds * sizeof (GCRPin))); + ch->gcr_result = (short **) mallocMagic((unsigned) (lenWds * sizeof (short *))); + + /* Initialize end columns */ + ch->gcr_result[0] = (short *) mallocMagic((unsigned) (widWds * sizeof (short))); + ch->gcr_result[ch->gcr_length+1] = (short *) mallocMagic((unsigned) (widWds * sizeof (short))); + for (i = 0; i < widWds; i++) + { + ch->gcr_result[0][i] = 0; + ch->gcr_result[ch->gcr_length + 1][i] = 0; + } + + /* Initialize internal columns */ + for (i = 1; i <= ch->gcr_length; i++) + { + /* Allocate the column */ + ch->gcr_result[i] = (short *) mallocMagic((unsigned) (widWds * sizeof (short))); + + /* Initialize the bottom pin */ + if (fscanf(fp, "%d", &pid) != 1) + { + TxError("Format error in pin-id in channel file\n"); + return (FALSE); + } + ch->gcr_bPins[i].gcr_pId = (GCRNet *)(spointertype) pid; + ch->gcr_bPins[i].gcr_x = i; + ch->gcr_bPins[i].gcr_y = 0; + + ch->gcr_result[i][0] = 0; + ch->gcr_result[i][ch->gcr_width+1] = 0; + for (j = 1; j <= ch->gcr_width; j++) + { + /* + * Read a column of obstacles. m and M mean metal is blocked, + * p and P mean poly is blocked. Upper case means vacate the + * column, lower case means vacate the track. + */ + if (fscanf(fp, "%s", s) != 1) + { + TxError("Format error in router input file\n"); + return (FALSE); + } + switch (s[0]) + { + case 'M': case 'm': + ch->gcr_result[i][j] = GCRBLKM; + break; + case 'P': case 'p': + ch->gcr_result[i][j] = GCRBLKP; + break; + case '.': + ch->gcr_result[i][j] = 0; + break; + default: + ch->gcr_result[i][j] = GCRBLKP | GCRBLKM; + break; + } + } + + /* Read bottom pin id */ + if (fscanf(fp, "%d", &pid) != 1) + { + TxError("Format error in router input file\n"); + return (FALSE); + } + ch->gcr_tPins[i].gcr_pId = (GCRNet *)(spointertype) pid; + ch->gcr_tPins[i].gcr_x = i; + ch->gcr_tPins[i].gcr_y = ch->gcr_width + 1; + } + + ch->gcr_rPins = gcrMakePinLR(fp, ch->gcr_length + 1, ch->gcr_width); + ch->gcr_area.r_xbot = 0; + ch->gcr_area.r_ybot = 0; + ch->gcr_area.r_xtop = (ch->gcr_length + 1) * RtrGridSpacing; + ch->gcr_area.r_ytop = (ch->gcr_width + 1) * RtrGridSpacing; + + return (TRUE); +} + +GCRPin * +gcrMakePinLR(fp, x, size) + FILE *fp; + int x, size; +{ + GCRPin *result; + int i; + + result = (GCRPin *) mallocMagic((unsigned) ((size+2) * sizeof (GCRPin))); + result[0].gcr_x = result[0].gcr_y = 0; + result[0].gcr_pId = (GCRNet *) NULL; + result[size + 1].gcr_x = result[size + 1].gcr_y = 0; + result[size + 1].gcr_pId = (GCRNet *) NULL; + for (i = 1; i <= size; i++) + { + /* FIXME: Reading a pointer from file is almost guaranteed to break. */ + dlong pointer_bits; + (void) fscanf(fp, "%"DLONG_PREFIX"d", &pointer_bits); + result[i].gcr_pId = (struct gcrnet *) pointer_bits; + result[i].gcr_x = x; + result[i].gcr_y = i; + } + + return (result); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrSaveChannel -- + * + * Write a channel file for subsequent use in debugging. + * + * Results: + * None. + * + * Side effects: + * Creates a disk file named by the channel address, + * e.g, chan.1efb0 + * + * ---------------------------------------------------------------------------- + */ + +void +gcrSaveChannel(ch) + GCRChannel *ch; +{ + FILE *fp; + char name[128]; + int flags, i, j; + + (void) sprintf(name, "chan.%p", ch); + fp = fopen(name, "w"); + if (fp == NULL) + { + TxPrintf("Can't dump channel to file; "); TxFlush(); + perror(name); + return; + } + + /* Output the prologue */ + fprintf(fp, "* %d %d\n", ch->gcr_width, ch->gcr_length); + +#define NETID(pin) ((pin).gcr_pId ? (pin).gcr_pId->gcr_Id : 0) + + /* Output the left pin array */ + for (j = 1; j <= ch->gcr_width; j++) + fprintf(fp, "%d ", NETID(ch->gcr_lPins[j])); + fprintf(fp, "\n"); + + /* Process main body of channel */ + for (i = 1; i <= ch->gcr_length; i++) + { + /* Bottom pin */ + fprintf(fp, "%d ", NETID(ch->gcr_bPins[i])); + + /* + * Interior points (for obstacle map). + * Codes are as follows: + * + * m metal blocked vacate track + * M metal blocked vacate column + * p poly blocked vacate track + * P poly blocked vacate column + */ + for (j = 1; j <= ch->gcr_width; j++) + { + flags = ch->gcr_result[i][j]; + switch (flags & (GCRBLKM|GCRBLKP)) + { + case 0: fprintf(fp, ". "); break; + case GCRBLKM: fprintf(fp, "m "); break; + case GCRBLKP: fprintf(fp, "p "); break; + case GCRBLKM|GCRBLKP: fprintf(fp, "x "); break; + } + } + + /* Top pin */ + fprintf(fp, "%d\n", NETID(ch->gcr_tPins[i])); + } + + /* Output the right pin array */ + for (j = 1; j <= ch->gcr_width; j++) + fprintf(fp, "%d ", NETID(ch->gcr_rPins[j])); + fprintf(fp, "\n"); + (void) fclose(fp); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrPrDensity -- + * + * Create a file of the form "dens.xbot.ybot.xtop.ytop", where + * xbot, ybot are the lower-left coordinates of ch->gcr_area + * and xtop, ytop are the upper right coordinates. This file + * contains a comparison of the density computed by the global + * router with that computed by the channel router; it is used + * for debugging only. + * + * Results: + * None. + * + * Side effects: + * Creates a file named as described above. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrPrDensity(ch, chanDensity) + GCRChannel *ch; + int chanDensity; +{ + int i, diff; + char name[256]; + FILE *fp; + + (void) sprintf(name, "dens.%d.%d.%d.%d", + ch->gcr_area.r_xbot, ch->gcr_area.r_ybot, + ch->gcr_area.r_xtop, ch->gcr_area.r_ytop); + fp = fopen(name, "w"); + if (fp == NULL) + fp = stdout; + + fprintf(fp, "Chan width: %d\n", ch->gcr_width); + fprintf(fp, "Chan length: %d\n", ch->gcr_length); + fprintf(fp, "Chan area: ll=(%d,%d) ur=(%d,%d)\n", + ch->gcr_area.r_xbot, ch->gcr_area.r_ybot, + ch->gcr_area.r_xtop, ch->gcr_area.r_ytop); + fprintf(fp, "Max column density (global): %d\n", ch->gcr_dMaxByCol); + fprintf(fp, "Max column density (channel): %d\n", chanDensity); + fprintf(fp, "Column density by column:\n"); + fprintf(fp, "%3s %5s", "COL", "GLOB"); +#ifdef IDENSITY + fprintf(fp, " %5s %5s", "INIT", "DIFF"); +#endif /* IDENSITY */ + fprintf(fp, " %5s\n", "CHAN"); + for (i = 1; i <= ch->gcr_length; i++) + { + fprintf(fp, "%3d %5d", i, ch->gcr_dRowsByCol[i]); + diff = ch->gcr_dRowsByCol[i]; +#ifdef IDENSITY + diff -= ch->gcr_iRowsByCol[i]; + fprintf(fp, " %5d %5d", ch->gcr_iRowsByCol[i], diff); +#endif /* IDENSITY */ + fprintf(fp, "%5d%s\n", ch->gcr_density[i], + (diff != ch->gcr_density[i]) ? " *****" : ""); + } + fprintf(fp, "------\n"); + fprintf(fp, "Row density by column (global only):\n"); + fprintf(fp, "%3s %5s", "ROW", "GLOB"); +#ifdef IDENSITY + fprintf(fp, " %5s %5s", "INIT", "DIFF"); +#endif /* IDENSITY */ + fprintf(fp, "\n"); + for (i = 1; i <= ch->gcr_width; i++) + { + fprintf(fp, "%3d %5d", i, ch->gcr_dColsByRow[i]); +#ifdef IDENSITY + fprintf(fp, " %5d %5d", ch->gcr_iColsByRow[i], + ch->gcr_dColsByRow[i] - ch->gcr_iColsByRow[i]); +#endif /* IDENSITY */ + fprintf(fp, "\n"); + } + + (void) fflush(fp); + if (fp != stdout) + (void) fclose(fp); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrDumpPins -- + * + * Prints a pin array. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrDumpPins(ch) + GCRChannel *ch; +{ + int i; + GCRPin * pinArray; + + pinArray=ch->gcr_lPins; + TxPrintf("LEFT PINS\n"); + for(i=0; i<=ch->gcr_width; i++) + { + TxPrintf("Location [%d]=%d: x=%d, y=%d, pNext=%d, pPrev=%d, id=%d\n", + i, &pinArray[i], pinArray[i].gcr_x, pinArray[i].gcr_y, + pinArray[i].gcr_pNext, pinArray[i].gcr_pPrev, pinArray[i].gcr_pId); + } + pinArray=ch->gcr_rPins; + TxPrintf("RIGHT PINS\n"); + for(i=0; i<=ch->gcr_width; i++) + { + TxPrintf("Location [%d]=%d: x=%d, y=%d, pNext=%d, pPrev=%d, id=%d\n", + i, &pinArray[i], pinArray[i].gcr_x, pinArray[i].gcr_y, + pinArray[i].gcr_pNext, pinArray[i].gcr_pPrev, pinArray[i].gcr_pId); + } + pinArray=ch->gcr_bPins; + TxPrintf("BOTTOM PINS\n"); + for(i=0; i<=ch->gcr_length; i++) + { + TxPrintf("Location [%d]=%d: x=%d, y=%d, pNext=%d, pPrev=%d, id=%d\n", + i, &pinArray[i], pinArray[i].gcr_x, pinArray[i].gcr_y, + pinArray[i].gcr_pNext, pinArray[i].gcr_pPrev, pinArray[i].gcr_pId); + } + pinArray=ch->gcr_tPins; + TxPrintf("TOP PINS\n"); + for(i=0; i<=ch->gcr_length; i++) + { + TxPrintf("Location [%d]=%d: x=%d, y=%d, pNext=%d, pPrev=%d, id=%d\n", + i, &pinArray[i], pinArray[i].gcr_x, pinArray[i].gcr_y, + pinArray[i].gcr_pNext, pinArray[i].gcr_pPrev, pinArray[i].gcr_pId); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrDumpPinList -- + * + * Prints a list of pins for a net. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrDumpPinList(pin, dir) + GCRPin *pin; + bool dir; +{ + if (pin) + { + TxPrintf("Location (%d, %d)=%x: pNext=%d, pPrev=%d, id=%d\n", + pin->gcr_x, pin->gcr_y, pin, + pin->gcr_pNext, pin->gcr_pPrev, pin->gcr_pId); + if (dir) gcrDumpPinList(pin->gcr_pNext, dir); + else gcrDumpPinList(pin->gcr_pPrev, dir); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrDumpCol -- + * + * Print the left column contents. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrDumpCol(col, size) + GCRColEl *col; + int size; +{ + int i; + + if (!gcrStandalone) + return; + + for (i = size; i >= 0; i--) + TxPrintf("[%2d] hi=%6d(%c) lo=%6d(%c) h=%6d v=%6d w=%6d f=%4d\n", i, + col[i].gcr_hi, col[i].gcr_hOk ? 'T' : 'F', + col[i].gcr_lo, col[i].gcr_lOk ? 'T' : 'F', + col[i].gcr_h, col[i].gcr_v, + col[i].gcr_wanted, col[i].gcr_flags); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrDumpResult -- + * + * Print the results of the routing, up to the current column + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrDumpResult(ch, showResult) + GCRChannel *ch; + bool showResult; +{ + int j; + + if(!showResult) + return; + + gcrStats(ch); + TxPrintf(" "); + for (j = 1; j <= ch->gcr_width; j++) + if (ch->gcr_lPins[j].gcr_pId) + TxPrintf("%2d", ch->gcr_lPins[j].gcr_pId->gcr_Id); + else + TxPrintf(" "); + TxPrintf("\n"); + + for (j = 0; j <= ch->gcr_length; j++) + gcrPrintCol(ch, j, showResult); + + TxPrintf(" "); + for (j = 1; j <= ch->gcr_width; j++) + if (ch->gcr_rPins[j].gcr_pId) + TxPrintf("%2d", ch->gcr_rPins[j].gcr_pId->gcr_Id); + else + TxPrintf(" "); + TxPrintf("\n"); +} + +void gcrPrintCol(ch, i, showResult) + GCRChannel *ch; + int i, showResult; +{ + short **res = ch->gcr_result; + int j; + + if (!showResult) + return; + + if (i>0) + { + if(ch->gcr_bPins[i].gcr_pId) + TxPrintf("[%3d] %2d:", i, (int) ch->gcr_bPins[i].gcr_pId->gcr_Id); + else TxPrintf("[%3d] :", i); + for (j = 0; j <= ch->gcr_width; j++) + { + if (j != 0) + { + if ((res[i][j] & GCRX) && (!(res[i][j] & (GCRBLKM|GCRBLKP)))) + { + TxPrintf("X"); + gcrViaCount++; + } + else if ((res[i][j] & GCRR) || (i > 0 && (res[i-1][j] & GCRR))) + { + if (res[i][j] & GCRBLKM) TxPrintf("|"); + else if ((res[i][j] & GCRU) + || (j != 0 && (res[i][j-1] & GCRU))) + { + if ((res[i][j]&GCRBLKM) && !(res[i][j]&GCRR)) + TxPrintf("+"); + else if (res[i][j]&GCRBLKP) + TxPrintf("#"); + else + TxPrintf(")"); + } + else TxPrintf("#"); + } + else if ((res[i][j] & GCRU) || j != 0 && (res[i][j-1] & GCRU)) + { + if((res[i][j]&GCRCC) && (!(res[i][j]&(GCRBLKM|GCRBLKP)))) + { + gcrViaCount++; + TxPrintf("X"); + } + else + if(res[i][j] & GCRBLKP) + TxPrintf("#"); + else + if(res[i][j+1] & GCRBLKP) + TxPrintf("#"); + else + if(res[i][j] & GCRVM) + TxPrintf("#"); + else + TxPrintf("-"); + } + else + if((res[i][j] & GCRBLKM) && (res[i][j] & GCRBLKP)) + TxPrintf("~"); + else + if(res[i][j] & GCRBLKM) + TxPrintf("'"); + else + if(res[i][j] & GCRBLKP) + TxPrintf("`"); + else + TxPrintf(" "); + } + + if(res[i][j] & GCRU) + if(res[i][j] & GCRBLKP) + TxPrintf("#"); + else + if(res[i][j+1] & GCRBLKP) + TxPrintf("#"); + else + if(res[i][j] & GCRVM) + TxPrintf("#"); + else + TxPrintf("-"); + else + if((res[i][j] & GCRBLKM) && (res[i][j] & GCRBLKP)) + TxPrintf("~"); + else + if( ((res[i][j] & GCRBLKM) && (res[i][j+1] & GCRBLKP)) || + ((res[i][j] & GCRBLKP) && (res[i][j+1] & GCRBLKM)) ) + TxPrintf("~"); + else + if((res[i][j+1] & GCRBLKM) && (res[i][j+1] & GCRBLKP)) + TxPrintf("~"); + else + if((res[i][j] & GCRBLKM) || (res[i][j+1] & GCRBLKM)) + TxPrintf("'"); + else + if((res[i][j] & GCRBLKP) || (res[i][j+1] & GCRBLKP)) + TxPrintf("`"); + else + TxPrintf(" "); + } + if(ch->gcr_tPins[i].gcr_pId!=(GCRNet *) 0) + TxPrintf(":%2d {%2d}", (int) ch->gcr_tPins[i].gcr_pId->gcr_Id, + ch->gcr_density[i]); + else + TxPrintf(": {%2d}", ch->gcr_density[i]); + } + + TxPrintf("\n :"); + for(j=0; j<=ch->gcr_width; j++) + { + if(j!=0) + { + if(res[i][j] & GCRR) + if(res[i][j] & GCRBLKM) + TxPrintf("|"); + else + if((i<=ch->gcr_length) && (res[i+1][j] & GCRBLKM)) + TxPrintf("|"); + else + TxPrintf("#"); + else + if(((res[i][j] & GCRBLKM)&&(res[i][j] & GCRBLKP)) || + ((res[i+1][j] & GCRBLKM)&&(res[i+1][j] & GCRBLKP))) + TxPrintf("~"); + else + if((res[i][j] & GCRBLKM) || (res[i+1][j] & GCRBLKM)) + TxPrintf("'"); + else + if((res[i][j] & GCRBLKP) || (res[i+1][j] & GCRBLKP)) + TxPrintf("`"); + else + TxPrintf(" "); + } + else + if((j!=0) && (i!=0)) + { + if(res[i-1][j] & GCRR) + if(res[i-1][j] & GCRBLKM) + TxPrintf("|"); + else + if((igcr_length) && (res[i][j] & GCRBLKM)) + TxPrintf("|"); + else + TxPrintf("#"); + else + if(((res[i-1][j] & GCRBLKM)&&(res[i-1][j] & GCRBLKP)) || + ((res[i ][j] & GCRBLKM)&&(res[i ][j] & GCRBLKP))) + TxPrintf("~"); + else + if((res[i-1][j] & GCRBLKM) || (res[i][j] & GCRBLKM)) + TxPrintf("'"); + else + if((res[i-1][j] & GCRBLKP) || (res[i][j] & GCRBLKP)) + TxPrintf("`"); + else + TxPrintf(" "); + } + + if((((res[i][j] & GCRBLKM) && (res[i][j] & GCRBLKP)) || + ((res[i][j+1] & GCRBLKM) && (res[i][j+1] & GCRBLKP))) || + (((res[i+1][j] & GCRBLKM) && (res[i+1][j] & GCRBLKP)) || + ((res[i+1][j+1] & GCRBLKM) && (res[i+1][j+1] & GCRBLKP)))) + TxPrintf("~"); + else + if(((res[i][j] & GCRBLKM) || (res[i][j+1] & GCRBLKM))|| + ((res[i+1][j] & GCRBLKM) || (res[i+1][j+1] & GCRBLKM))) + TxPrintf("'"); + else + if(((res[i][j] & GCRBLKP) || (res[i][j+1] & GCRBLKP))|| + ((res[i+1][j] & GCRBLKP) || (res[i+1][j+1] & GCRBLKP))) + TxPrintf("`"); + else + TxPrintf(" "); + } + TxPrintf(":\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrStats -- + * + * Print routing statistics. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrStats(ch) + GCRChannel * ch; +{ + int wireLength=0, viaCount=0, row, col; + short **res, mask, code, code2; + int hWire=0, vWire=0; + + viaCount=0; + res=ch->gcr_result; + for(col=0; col<=ch->gcr_length; col++) + for(row=0; row<=ch->gcr_width; row++) + { + code=res[col][row]; + if(code & GCRR) + { + wireLength++; + hWire++; + } + if(code & GCRU) + { + wireLength++; + vWire++; + } + if(code & GCRX) + { + /* There is a connection at the crossing. Count a contact if metal + * and poly come together here. + */ + mask=0; + code2=ch->gcr_result[col][row+1]; + if(code&GCRU) + { + if(code&GCRVM) mask|=GCRBLKM; /*What type is up*/ + else mask|=GCRBLKP; + } + code2=ch->gcr_result[col+1][row]; + if(code&GCRR) + { + if(code2&GCRBLKM) mask|=GCRBLKP; /*What type is right*/ + else mask|=GCRBLKM; + } + code2=ch->gcr_result[col][row-1]; + if(code2&GCRU) + { + if(code2&GCRVM) mask|=GCRBLKM; /*What type is down*/ + else mask|=GCRBLKP; + } + code2=ch->gcr_result[col-1][row]; + if(code2&GCRR) + { + if(code2&GCRBLKM) mask|=GCRBLKP; /*What type is left*/ + else mask|=GCRBLKM; + } + if((mask!=GCRBLKM)&&(mask!=GCRBLKP)) + viaCount++; + } + } + TxPrintf("Length : %d\n", wireLength); + TxPrintf("Vias : %d\n", viaCount); + TxPrintf("Hwire : %d\n", hWire); + TxPrintf("Vwire : %d\n", vWire); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrCheckCol -- + * + * Check the accuracy of the column's hi and lo pointers. Abort if there + * is a mistake. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrCheckCol(ch, c, where) + GCRChannel *ch; + int c; + char *where; +{ + int i, j; + GCRColEl * col; + + if(GcrNoCheck) + return; + col=ch->gcr_lCol; + for(i=0; i<=ch->gcr_width; i++) + { + if( (col[i].gcr_hOk || col[i].gcr_lOk) && (col[i].gcr_h==(GCRNet *) 0)) + { + if(gcrStandalone) + { + TxError("Botch at column %d, %s (bad hOk/lOk at %d)\n", + c, where, i); + gcrDumpCol(col, ch->gcr_width); + } + if(GcrDebug) + niceabort(); + } + if(((col[i].gcr_hi==i)||(col[i].gcr_lo==i))&&(i!=0)) + { + if(gcrStandalone) + { + TxError("Botch at column %d, %s(pointer loop at %d)\n", + c, where, i); + gcrDumpCol(col, ch->gcr_width); + } + if(GcrDebug) + niceabort(); + } + if(col[i].gcr_h!=(GCRNet *) NULL) + + /* Look upward from the track for the next higher track assigned to + * the net, if any. Just take the first one, breaking afterwards. + */ + for(j=i+1; j<=ch->gcr_width; j++) + { + if(col[j].gcr_h==col[i].gcr_h) + { + /* Check to see if the lower track at i points to the higher + * track at j, and vice versa. If an error, abort. + */ + if( ((col[j].gcr_lo!=i) && !col[j].gcr_lOk && + !col[i].gcr_hOk) || + ((col[i].gcr_hi!=j) && !col[i].gcr_hOk && + !col[j].gcr_lOk) ) + { + if(gcrStandalone) + { + TxError("Botch at column %d, %s", c, where); + TxError(" (link error from %d to %d)\n", i, j); + gcrDumpCol(col, ch->gcr_width); + } + if(GcrDebug) niceabort(); + } + else break; + } + } + if((col[i].gcr_hi>ch->gcr_width)||(col[i].gcr_hi< EMPTY)|| + (col[i].gcr_lo>ch->gcr_width)||(col[i].gcr_lo< EMPTY)) + { + if(gcrStandalone) + { + TxError("Botch at column %d, %s (bounds)\n", c, where); + gcrDumpCol(col, ch->gcr_width); + } + if(GcrDebug) niceabort(); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrShowMap -- + * + * Print the bit map in the result array for the selected field. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrShowMap(ch) + GCRChannel * ch; +{ + int i, j, field; + short ** res; + char buff[512]; + + if (!GcrShowMap) + return; + + while (1) + { + TxPrintf("Field selector (0 terminates): "); + if(!scanf("%d", &field)) /*typed something funny*/ + { + TxPrintf("Bad input. Legal responses are\n"); + TxPrintf(" GCRBLKM 1\n"); + TxPrintf(" GCRBLKP 2\n"); + TxPrintf(" GCRU 4\n"); + TxPrintf(" GCRR 8\n"); + TxPrintf(" GCRX 16\n"); + TxPrintf(" GCRVL 32\n"); + TxPrintf(" GCRV2 64\n"); + TxPrintf(" GCRTC 128\n"); + TxPrintf(" GCRCC 256\n"); + TxPrintf(" GCRTE 512\n"); + TxPrintf(" GCRCE 1024\n"); + TxPrintf(" GCRVM 2048\n"); + TxPrintf(" GCRXX 4096\n"); + TxPrintf(" GCRVR 8192\n"); + TxPrintf(" GCRVU 16384\n"); + TxPrintf(" GCRVD 32768\n"); + (void) fgets(buff, 512, stdin); + } + TxPrintf("\n%d\n", field); + if(field==0) + return; + + TxPrintf("\n "); + for(j=0; j<=ch->gcr_width+1; j++) + TxPrintf("%2d", j); + + for(i=0; i<=ch->gcr_length+1; i++) + { + res=ch->gcr_result; + TxPrintf("\n[%3d] ", i); + for(j=0; j<=ch->gcr_width+1; j++) + { + if(res[i][j] & field) + TxPrintf("1 "); + else + TxPrintf(". "); + } + } + TxPrintf("\n"); + } +} diff --git a/gcr/gcrEdge.c b/gcr/gcrEdge.c new file mode 100644 index 00000000..1ebfd185 --- /dev/null +++ b/gcr/gcrEdge.c @@ -0,0 +1,275 @@ + +/* gcrEdge.c - + * + * The greedy router: + * Functions to make connections at the far end of the channel. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrEdge.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "gcr/gcr.h" + +/* + * ---------------------------------------------------------------------------- + * + * gcrWanted -- + * + * Reserve tracks needed to make connections at the end of the channel + * for net occupying track. Net must be unsplit. If very close then + * reserve all tracks needed by net; otherwise just 1. + * + * Results: + * None. + * + * Side effects: + * Mark the desired tracks for such nets as "wanted" by that net. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrWanted(ch, track, column) + GCRChannel *ch; + int track, column; +{ + GCRColEl *col = ch->gcr_lCol; + GCRPin *pin, *next; + GCRNet *net; + + net = col[track].gcr_h; + if (net == (GCRNet *) NULL) + return; + + /* Done if the net is split */ + if (col[track].gcr_hi != EMPTY || col[track].gcr_lo != EMPTY) + return; + + /* Done if no pins */ + pin = GCRPin1st(net); + if (pin == (GCRPin *) NULL) + return; + + /* Done if interior pin */ + if (pin->gcr_x != ch->gcr_length + 1) + return; + + next = GCRPinNext(pin); + if (next == (GCRPin *) NULL) col[pin->gcr_y].gcr_wanted = net; + else if (GCRNearEnd(ch, column)) + { + for (col[pin->gcr_y].gcr_wanted = net; next; next = GCRPinNext(next)) + col[next->gcr_y].gcr_wanted = net; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrMarkWanted -- + * + * Mark tracks near the end of the channel that are wanted to make some + * connection at the end of the channel. + * + * Results: + * None. + * + * Side effects: + * Changes the wanted field in column elements. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrMarkWanted(ch) + GCRChannel *ch; +{ + GCRColEl *col = ch->gcr_lCol; + GCRPin *pin = ch->gcr_rPins; + int track; + + for (track = 1; track <= ch->gcr_width; track++) + if (pin[track].gcr_pId) + col[track].gcr_wanted = pin[track].gcr_pId; +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrUncollapse -- + * + * Add vertical segments to this column to split nets making more than + * one connection at the end of the channel. Pick a pattern that will + * create the most split. Generate all legal combinations and pick the + * best. This differs from gcrCollapse in that there are no links + * between tracks to be followed. + * + * Results: + * None. + * + * Side effects: + * If the evaluated column is the best seen, then gcrEvalPat saves it + * away. In any event, gcrEvalPat sets its col argument to NULL. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrUncollapse(ch, col, width, bot, top, split) + GCRChannel *ch; /* Channel being processed */ + GCRColEl **col; + int width; /* Size of array pointed to by *col */ + int bot, top; /* Consider tracks between bot .. top inclusive */ + int split; /* Somewhere between 0 and width inclusive */ +{ + int i, to, type, extra, flags; + GCRColEl *newCol, *gcrCopyCol(); + GCRNet *net, *hnet; + + ASSERT(split <= width, "gcrUncollapse."); + for (i = bot; i <= top; i++) + { + /* + * If the track is free but needs to get assigned a net for + * a right edge connection... + */ + net = (*col)[i].gcr_h; + if (net == (GCRNet *) NULL + && (*col)[i].gcr_wanted + && ((*col)[i].gcr_v == (GCRNet *) NULL + || (*col)[i].gcr_v == net)) + { + /* + * Look upwards for the next track that is either assigned to + * the net or wants to get assigned the net. If blocked + * vertically then give up. If found, weight the worth of + * the potential connection. + */ + for (to = i + 1; to <= width; to++) + { + flags = (*col)[to].gcr_flags; + hnet = (*col)[to].gcr_h; + + /* + * Abort if blocked. The last argument indicates that it is + * okay to stop at this location only if this location holds + * the net to which (*col)[i] wants to connect. + */ + if (gcrBlocked(*col, to, net, hnet != (*col)[i].gcr_wanted)) + { + to = width + 1; + break; + } + else if (hnet == (*col)[i].gcr_wanted) + { + /* Connect to a track already assigned to the net. */ + type = 1; + extra = 2; + break; + } + else if ((*col)[to].gcr_wanted == (*col)[i].gcr_wanted + && hnet == (GCRNet *) NULL) + { + /* Connect to another track not yet part of the net. */ + extra = 1; + type = 2; + break; + } + else if (flags & GCRCE) + { + to = width + 1; + break; + } + } + } + else if (net) + { + /* + * If the track is assigned to a net and this net has more + * connections to make at the end, look upward for the next + * track that is empty and wants to connect to this net. + * No collapses of split tracks should occur here, since + * this function comes after collapsing split nets. + */ + for (to = i + 1; to <= width; to++) + { + /* + * Skip if the track ends in the next column. The last + * argument indicates that it is okay to stop here if + * this location wants to get hooked up to "net". + */ + flags = (*col)[to].gcr_flags; + if (gcrBlocked(*col, to, net, net == (*col)[to].gcr_wanted)) + { + to = width + 1; + break; + } + else if( (*col)[to].gcr_wanted == net + && (*col)[to].gcr_h == (GCRNet *) NULL) + { + /* + * Link track "i" (already assigned to the net) to + * track "to" (track being uncollapsed). + */ + extra = 2; + type = 3; + break; + } + else if (flags & GCRCE) + { + to = width + 1; + break; + } + } + } + else continue; + + if (to <= width) + { + /* Found something to connect */ + newCol = gcrCopyCol( *col, width); + switch (type) + { + case 1: + gcrMoveTrack(newCol, net, to, i); + break; + case 2: + net = newCol[to].gcr_wanted; + gcrLinkTrack(newCol, net, to, width); + gcrMoveTrack(newCol, net, to, i); + break; + case 3: + gcrMoveTrack(newCol, net, i, to); + break; + } + + ASSERT(i < to, "gcrEdge.c, gcrUncollapse"); + gcrUncollapse(ch, &newCol, width, to, top, split+extra); + + /* Don't bother to recheck stuff above the last jog */ + if (top > to) top = to-1; + } + + } + + gcrEvalPat(col, split, width); + *col = (GCRColEl *) NULL; +} diff --git a/gcr/gcrFeas.c b/gcr/gcrFeas.c new file mode 100644 index 00000000..35b1fafc --- /dev/null +++ b/gcr/gcrFeas.c @@ -0,0 +1,248 @@ +/* gcrFeas.c - + * + * The greed router: Making feasible top and bottom connections. + * This includes the initial attempt and widening if a + * connection could not be made. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrFeas.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "gcr/gcr.h" +#include "utils/hash.h" +#include "database/database.h" +#include "router/router.h" + +extern int gcrStandalone; +extern int gcrRouterErrors; + +/* Forward declarations */ +void gcrMakeFeasible(); + +/* + * ---------------------------------------------------------------------------- + * gcrFeasible -- + * + * Make feasible top and bottom connections in a minimal manner, running + * to the first track that is either empty or already assigned to the net. + * + * Results: + * None. + * + * Side effects: + * *failedTop and *failedBot get set true or false, depending on whether + * the connections from the top and bottom are successful or not. + * Updates the structs for the nets to delete the pins. + * Updates the column data structure to reflect the track assignment. + * column[0].gcr_hi=column[width+1].gcr_lo=EMPTY at conclusion. + * ---------------------------------------------------------------------------- + */ + +void +gcrFeasible(ch, col) + GCRChannel * ch; + int col; /* Column for feasible connections */ +{ + GCRColEl * column; + GCRNet * topNet, *botNet; + int i, topTarget, botTarget; + int failedTop; + int failedBot; + + topNet=ch->gcr_tPins[col].gcr_pId; + botNet=ch->gcr_bPins[col].gcr_pId; + column=ch->gcr_lCol; + +/* The order in which pins are unlinked is important. This is because + * the unlinker checks to see that pins are unlinked in order of their + * position on the list. + */ + gcrUnlinkPin(&ch->gcr_bPins[col]); + gcrUnlinkPin(&ch->gcr_tPins[col]); + + if (topNet) + { + /* There is a top pin at this column */ + failedTop=TRUE; + + /* Look for the first track to which this net can run. It must either + * be empty or else already assigned to the topNet. + */ + for(i=ch->gcr_width; i>0; i--) + if(gcrBlocked(column, i, topNet, 0)) + break; + else + if((column[i].gcr_h==(GCRNet *) NULL) || (column[i].gcr_h==topNet)) + { + topTarget=i; + failedTop=FALSE; + break; + } + } + else + failedTop=FALSE; + + if(botNet!=(GCRNet *) NULL) + { + failedBot=TRUE; + column[0].gcr_lo=column[0].gcr_hi= EMPTY; + for(i=1; i<=ch->gcr_width; i++) + if(gcrBlocked(column, i, botNet, ch->gcr_width)) + break; + else + if((column[i].gcr_h==(GCRNet *) NULL) || (column[i].gcr_h==botNet)) + { + botTarget= i; + failedBot=FALSE; + break; + } + } + else + failedBot=FALSE; + +/* If there are no empty tracks and net topNet==botNet!=0 is a net which + * has connections in this column only, then run a vertical wire from top + * to bottom of this column. + */ + if( failedTop && failedBot && + (topNet==botNet) && (topNet!=(GCRNet *) NULL) && + (topNet->gcr_lPin==(GCRPin *) NULL) ) + { + /* ... but only do this if there isn't some block */ + for(i = 1; i <= ch->gcr_width; i++) + if(gcrBlocked(column, i, botNet, ch->gcr_width)) return; + gcrMoveTrack(column, topNet, ch->gcr_width+1, 0); + failedBot= failedTop=FALSE; + } + else + +/* If there is a conflict in the wiring, then just wire the one with the + * shortest connection. + */ + if( !(failedBot) && (topNet!=(GCRNet *) NULL) && + !(failedTop) && (botNet!=(GCRNet *) NULL) && (botTarget>=topTarget) ) + if(topNet==botNet) + { + gcrMakeFeasible(column, topNet, ch->gcr_width+1, topTarget, + ch->gcr_width); + gcrMakeFeasible(column, botNet, 0, botTarget, ch->gcr_width); + gcrWanted(ch, topTarget, col); + } + else + if( botTarget > (ch->gcr_width-topTarget-1) ) + { + gcrMakeFeasible(column, topNet, ch->gcr_width+1, topTarget, + ch->gcr_width); + failedBot=TRUE; + gcrWanted(ch, topTarget, col); + } + else + { + gcrMakeFeasible(column, botNet, 0, botTarget, ch->gcr_width); + failedTop=TRUE; + gcrWanted(ch, botTarget, col); + } + else + +/* Make successful connections. Leave unsuccessful connections for later. */ + { + if( (! failedTop) && (topNet!=(GCRNet *) NULL) ) + { + gcrMakeFeasible(column, topNet, ch->gcr_width+1, topTarget, + ch->gcr_width); + gcrWanted(ch, topTarget, col); + } + if( (! failedBot) && (botNet!=(GCRNet *) NULL) ) + { + gcrMakeFeasible(column, botNet, 0, botTarget, ch->gcr_width); + gcrWanted(ch, botTarget, col); + } + } + if(failedTop) + { + RtrChannelError(ch, col, ch->gcr_width, + "Can't make top connection", + ch->gcr_tPins[col].gcr_pId->gcr_Id); + gcrRouterErrors++; + } + if(failedBot) + { + RtrChannelError(ch, col, 1, "Can't make bottom connection", + ch->gcr_bPins[col].gcr_pId->gcr_Id); + gcrRouterErrors++; + } +} + +/* + * ---------------------------------------------------------------------------- + * gcrMakeFeasible -- + * + * Run a feasible connection from the bottom or top to the given target + * track. + * + * Results: + * None. + * + * Side effects: + * Have to fiddle around with column[0] and column[width+1]. + * ---------------------------------------------------------------------------- + */ + +void +gcrMakeFeasible(col, net, from, target, width) + GCRColEl * col; /* Describes current column structure. */ + GCRNet * net; /* Net being brought into column. */ + int from; /* Pin location for net (0 or width+1). */ + int target; /* Target track for net. */ + int width; /* Width of column. */ +{ + int i; + +/* Find the index of the first track occupied by net. Pass it to + * gcrMoveTrack through column[from].gcr_lo or gcr_hi. + */ + col[from].gcr_lo=col[from].gcr_hi= EMPTY; + if(col[target].gcr_h==net) /*run to occupied track*/ + { + col[from].gcr_lo= col[target].gcr_lo; + col[from].gcr_hi= col[target].gcr_hi; + } + else + if(from!=0) /*Run to empty track. Connect from the top*/ + for(i=target-1; i>0; i--) + if(col[i].gcr_h==net) + { + col[from].gcr_lo=i; + col[i].gcr_hi=target; + break; + } + else /*nothing*/; + else /*Run to empty track. Connect from bottom.*/ + for(i=target+1; i<=width; i++) + if(col[i].gcr_h==net) + { + col[0].gcr_hi=i; + col[i].gcr_lo=target; + break; + } + gcrMoveTrack(col, net, from, target); + col[from].gcr_lo=col[from].gcr_hi= EMPTY; +} diff --git a/gcr/gcrFlags.c b/gcr/gcrFlags.c new file mode 100644 index 00000000..b3ccbe1f --- /dev/null +++ b/gcr/gcrFlags.c @@ -0,0 +1,144 @@ +/* gcrFlags.c - + * + * Code to set contact and end flags at each grid point in a channel. + * This code assumes the channel has already been transformed into left + * to right routing form. These flags are used during channel routing. + * + * Hazard flags are set in the router module, as they are needed by the + * global router. The contact and end flags can not be set at that + * time, since we don't yet know in which direction the channel will be + * routed. + * + * CONTACT FLAGS mark clear locations bordering single layer obstacles. + * Extending a track horizontally across an obstacle requires a track + * contact and a layer switch. Extending a column vertically across an + * obstacle requires a column contact and a layer switch. + * + * END FLAGS mark locations beyond which tracks or columns cannot be + * extended due to two-layer obstacles. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrFlags.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "gcr/gcr.h" + +/* + * ---------------------------------------------------------------------------- + * + * gcrSetFlags -- + * + * Scan the channel obstacle map. Set flags for track and column + * contacts, and track and column termination. + * + * Use a top to bottom, left to right point by point scan. Wherever + * a vertical boundary between space and a track material obstacle + * occurs, make a track contact flag. Wherever a horizontal boundary + * between space and a column material obstacle occurs, make a column + * contact flag. + * + * Results: + * None. + * + * Side effects: + * + * ---------------------------------------------------------------------------- + */ + +void +gcrSetFlags(ch) + GCRChannel *ch; /* The channel to be flagged */ +{ + short *curPtr, *nextPtr; + short **map, *curCol, *curEnd, *nextCol; + int col; + + /* + * Scan the channel bottom to top, left to right. + * For each location scanned, look up and right to + * figure out what flags to set. + */ + map = ch->gcr_result; + nextCol = map[1]; + for (col = 1; col <= ch->gcr_length; col++) + { + curCol = nextCol; + curEnd = &curCol[ch->gcr_width]; + nextCol = map[col+1]; + for (curPtr = &curCol[1], nextPtr = &nextCol[1]; + curPtr <= curEnd; + curPtr++, nextPtr++) + { + /* + * Set column contact bits at the border between space and poly. + * Set column end bits at the border of blocked areas. + */ + if (CLEAR(*curPtr)) + { + if (HAS_M(*nextPtr)) /* Look right for track obstacle */ + *curPtr |= GCRTC; + else if (BLOCK(*nextPtr)) /* Look right for blocked area */ + *curPtr |= GCRTE; + + if (HAS_P(*(curPtr+1))) /* Look up for column obstacle */ + *curPtr |= GCRCC; + else if (BLOCK(*(curPtr+1)))/* Look up for blocked area */ + *curPtr |= GCRCE; + } + else if (HAS_P(*curPtr)) + { + if (HAS_M(*nextPtr)) + *curPtr |= GCRTE; + else if (BLOCK(*nextPtr)) + *curPtr |= GCRTE; + + if (CLEAR(*(curPtr+1))) /* Look up for column obstacle end */ + *(curPtr+1) |= GCRCC; + else if (HAS_M(*(curPtr+1)) || BLOCK(*(curPtr+1))) + *curPtr |= GCRCE; /* Look up for column blocked */ + } + else if (HAS_M(*curPtr)) + { + if (CLEAR(*nextPtr)) /* Look right for track obstacle end */ + *nextPtr |= GCRTC; + else if (HAS_P(*nextPtr) || BLOCK(*nextPtr)) + *curPtr |= GCRTE; /* Look right for blocked area */ + + if (HAS_P(*(curPtr+1)) || BLOCK(*(curPtr+1))) + { + *curPtr |= GCRCE; /* Look up for column blocked */ + *(curPtr+1) |= GCRCE; + } + } + else + { + /* + * When a contact is encountered, mark self and up. + * Don't need to mark GCRTE to the right, since this + * flag simply means that the track is blocked to the right. + */ + ASSERT(BLOCK(*curPtr), "Bizarre case"); + *curPtr |= (GCRTE | GCRCE); + *(curPtr+1) |= GCRCE; + } + } + } +} diff --git a/gcr/gcrInit.c b/gcr/gcrInit.c new file mode 100644 index 00000000..340ea275 --- /dev/null +++ b/gcr/gcrInit.c @@ -0,0 +1,398 @@ +/* gcrInit.c - + * + * Initialization for the greedy router. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrInit.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "router/router.h" +#include "gcr/gcr.h" +#include "utils/malloc.h" + +int GCRSteadyNet =1; /*Values get imported from main*/ +int GCREndDist =1; +int GCRMinJog =1; +int GCRsplitAt =0; +bool GcrShowResult =FALSE; +bool GcrNoCheck =TRUE; +bool GcrDebug =FALSE; +#ifndef lint +float GCRObstDist = 0.7; +#else +float GCRObstDist; /* Sun lint brain death */ +#endif /* lint */ + +/* Forward declarations */ +void gcrLinkPin(); + + +/* + * ---------------------------------------------------------------------------- + * + * gcrSetEndDist -- + * + * Set the global variable specifying how soon the router starts to get + * nets into tracks for end connections. + * + * Get the number of end connections as a percentage of the width of + * the channel. Add extra for multipin end connections. + * + * Results: + * None. + * + * Side effects: + * Changes GCREndDist. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrSetEndDist(ch) + GCRChannel *ch; /* The channel to be routed */ +{ + int rightTotal, multiTotal; + GCRNet *net; + GCRPin *pin; + int count; + + /* + * Do this the easy way. + * Enumerate each net and look at its pins, starting + * from the rightmost. + */ + rightTotal = 0; + multiTotal = 0; + for (net = ch->gcr_nets; net; net = net->gcr_next) + { + count = 0; + for (pin = net->gcr_rPin; pin; pin = pin->gcr_pPrev, count++) + if (pin->gcr_x <= ch->gcr_length) + break; + rightTotal += count; + if (count > 1) + multiTotal++; + } + + GCREndDist = (multiTotal/2 + rightTotal/4) * RtrEndConst; + if (GCREndDist < 1) GCREndDist = 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrBuildNets -- + * + * Scan the top, bot, left, and right pin arrays, setting pointers to + * the left and right pins for each net. Sets pointers within the + * pin arrays to point to next and previous pins. + * + * Results: + * None. + * + * Side effects: + * Allocates and initializes storage for nets. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrBuildNets(ch) + GCRChannel * ch; +{ + HashTable ht; + int i; + + /* + * Initialize the hash table that maps net ids to GCRNet structs. + * The table is keyed by 2 words: seg/net. + */ + HashInit(&ht, 256, 2); + + for (i = 1; i <= ch->gcr_width; i++) + gcrLinkPin(&ch->gcr_lPins[i], &ht, ch); + + for (i = 1; i <= ch->gcr_length; i++) + { + gcrLinkPin(&ch->gcr_bPins[i], &ht, ch); + gcrLinkPin(&ch->gcr_tPins[i], &ht, ch); + } + + for (i = 1; i <= ch->gcr_width; i++) + gcrLinkPin(&ch->gcr_rPins[i], &ht, ch); + + HashKill(&ht); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrLinkPin -- + * + * Establish the forward and backward links for a pin on the edge of + * a channel. + * + * Results: + * None. + * + * Side effects: + * The pin is added to the end of the list for its net. A + * new net structure is created if one doesn't already + * exist. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrLinkPin(pin, ht, ch) + GCRPin *pin; + HashTable *ht; + GCRChannel *ch; +{ + GCRNet *net; + GCRNet *gcrNewNet(); + HashEntry *hEntry; + + /* + * GCR_BLOCKEDNETID means that the crossing was blocked. + * Restore these crossings to "empty". + */ + if (pin->gcr_pId == GCR_BLOCKEDNETID) pin->gcr_pId = (GCRNet *) NULL; + + /* Skip empty pins */ + if (pin->gcr_pId == (GCRNet *) NULL) + return; + + /* Find the 2-word seg/net key */ + hEntry = HashFind(ht, (char *) &(pin->gcr_pSeg)); + net = (GCRNet *) HashGetValue(hEntry); + if (net == (GCRNet *) NULL) + { + /* New net */ + net = (GCRNet *) mallocMagic((unsigned) (sizeof (GCRNet))); + HashSetValue(hEntry, (char *) net); + net->gcr_Id = (spointertype) pin->gcr_pId; + + /* Link net onto channel net list */ + net->gcr_next = ch->gcr_nets; + ch->gcr_nets = net; + + /* Link pin onto net pin list */ + net->gcr_lPin = net->gcr_rPin= pin; + pin->gcr_pPrev = (GCRPin *) NULL; + } + else + { + /* Old net. Add to end of net's list. */ + net->gcr_rPin->gcr_pNext = pin; + pin->gcr_pPrev = net->gcr_rPin; + net->gcr_rPin = pin; + } + pin->gcr_pId = net; + pin->gcr_pNext = (GCRPin *) NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrUnlinkPin -- + * + * Remove a pin from the pin list for a net. The pin had better + * be the first pin of its net. + * + * Results: + * None. + * + * Side effects: + * The pin is removed from the list associated with its net. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrUnlinkPin(pin) + GCRPin *pin; +{ + GCRNet *net; + + if (net = pin->gcr_pId) + { + ASSERT(pin == net->gcr_lPin, "gcrUnlinkPin"); + net->gcr_lPin = pin->gcr_pNext; + if (pin->gcr_pNext) + pin->gcr_pNext->gcr_pPrev = pin->gcr_pPrev; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrDensity -- + * + * Determine the channel density at every column. Starting at the left + * end of the channel with density=0, the density of the next column is + * the current density plus the number of nets with first pin in the + * current column minus the number of nets with last pin in the previous + * column. + * + * Must be called AFTER gcrBuildNets. + * + * Results: + * Returns the maximum column density. + * + * Side effects: + * Allocates storage for the density array GCRDensity and stores densities. + * + * ---------------------------------------------------------------------------- + */ + +int +gcrDensity(ch) + GCRChannel *ch; +{ + int density, i, last, maxVal; + unsigned lenWds; + + last = 0; + density = 0; + + for (i = 1; i <= ch->gcr_width; i++) + if (ch->gcr_lPins[i].gcr_pId) + { + if (Is1stPin(&ch->gcr_lPins[i])) density++; + if (IsLstPin(&ch->gcr_lPins[i])) last++; + } + + lenWds = ch->gcr_length + 2; + if (ch->gcr_density == (int *) NULL) + { + ch->gcr_density = (int *) mallocMagic((unsigned) (lenWds * sizeof (int))); + } + ch->gcr_density[0] = maxVal = density; + + for (i = 1; i <= ch->gcr_length; i++) + { + density = density - last; + last = 0; + + if (ch->gcr_tPins[i].gcr_pId) + { + if (Is1stPin(&ch->gcr_tPins[i])) density++; + else if (IsLstPin(&ch->gcr_tPins[i])) last++; + } + + if (ch->gcr_bPins[i].gcr_pId) + { + if (Is1stPin(&ch->gcr_bPins[i])) density++; + else if (IsLstPin(&ch->gcr_bPins[i])) + { + if (ch->gcr_tPins[i].gcr_pId == ch->gcr_bPins[i].gcr_pId) + density--; + else last++; + } + } + + ch->gcr_density[i] = density; + if (density > maxVal) + maxVal = density; + } + + return (maxVal); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrInitCol -- + * + * Initialize the column structure to hold the configuration at + * the left side of the channel. + * + * Results: + * None. + * + * Side effects: + * Pointers are updated in the column data structure. + * Changes the track field of each net struct. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrInitCol(ch, edgeArray) + GCRChannel *ch; + GCRPin *edgeArray; /* Nets at left edge of channel if non-NULL */ +{ + GCRNet *net; + GCRColEl *col; + int i, widWds; + + col = ch->gcr_lCol; + + /* Assign column tracks using an optionally provided pin array */ + if (edgeArray) + { + col[0].gcr_h = (GCRNet *) NULL; + for (i = 1; i <= ch->gcr_width; i++) + { + col[i].gcr_h = edgeArray[i].gcr_pId; + + /* Delete pin from net's pin list */ + gcrUnlinkPin(&edgeArray[i]); + } + col[ch->gcr_width+1].gcr_h = (GCRNet *) NULL; + } + + /* Initialize the hi and lo pointers for the column data structure */ + for (net = ch->gcr_nets; net; net = net->gcr_next) + net->gcr_track = EMPTY; + + widWds = ch->gcr_width + 1; + for (i = 0; i <= widWds; i++) + { + col[i].gcr_v = (GCRNet *) NULL; + col[i].gcr_hi = EMPTY; + col[i].gcr_lo = EMPTY; + col[i].gcr_hOk =FALSE; + col[i].gcr_lOk =FALSE; + col[i].gcr_wanted = (GCRNet *) NULL; + col[i].gcr_flags = 0; + net = col[i].gcr_h; + if (net) + { + if (net->gcr_track == EMPTY) /* 1st track */ + col[i].gcr_h->gcr_track = i; + else + { + col[i].gcr_lo = net->gcr_track; + col[net->gcr_track].gcr_hi = i; + net->gcr_track = i; + } + } + } + + /* Mark tracks needed to make some end connection */ + for (i = 1; i <= ch->gcr_width; i++) + gcrWanted(ch, i, 0); +} diff --git a/gcr/gcrLib.c b/gcr/gcrLib.c new file mode 100644 index 00000000..81cba281 --- /dev/null +++ b/gcr/gcrLib.c @@ -0,0 +1,456 @@ + +/* gcrLib.c - + * + * Miscellaneous stuff for the greedy router. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrLib.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "gcr/gcr.h" +#include "utils/malloc.h" + +/* Forward declarations */ +void gcrUnlinkTrack(); + + +/* + * ---------------------------------------------------------------------------- + * + * gcrBlocked -- + * + * See if a given location is blocked for a vertical run. + * + * Results: + * TRUE if the location is blocked. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +gcrBlocked(col, i, net, last) + GCRColEl *col; /* Current column information */ + int i; /* Which element */ + GCRNet *net; /* Net we're interested in processing: locations + * that already contain this net aren't considered + * to be blocked; all others are. + */ + int last; +{ + GCRColEl *colptr = &col[i]; + + /* True if already wired vertically */ + if (colptr->gcr_v != net && colptr->gcr_v) + return (TRUE); + + /* True if column ended */ + if ((colptr->gcr_flags & GCRCE) && i != last && colptr->gcr_h != net) + return (TRUE); + + /* True if poly and metal blocked and not this net */ + if ((colptr->gcr_flags & (GCRBLKP|GCRBLKM|GCRCC)) + && colptr->gcr_h && colptr->gcr_h != net) + return (TRUE); + + /* Blocked if there's a contact there */ + if (colptr->gcr_flags & GCRX) + return (TRUE); + + /* All clear */ + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrMoveTrack -- + * + * Move a net to a new track. Add it to the occupied net list for the + * given net. If the destination track belongs to the same net, then + * just remove the duplicate. + * + * Results: + * None. + * + * Side effects: + * Adds vertical paint for the track. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrMoveTrack(column, net, from, to) + GCRColEl * column; + GCRNet * net; /* Net to be assigned to a track */ + int from; + int to; +{ + int i, last; + +/* Paint vertical segments. Delete tracks already assigned to this net */ + + if(from==to) + return; + + if(net==(GCRNet *) NULL) + if(column[from].gcr_wanted!=(GCRNet *) NULL) + net=column[from].gcr_wanted; + + last=from; + if(fromto; i--) /*Paint a descending vertica jog*/ + { + column[i].gcr_v=net; + if(column[i].gcr_h==net) + { + if(column[i].gcr_wanted!=net) + gcrUnlinkTrack(column, i); + else + { + column[last].gcr_lOk=TRUE; + column[ i].gcr_hOk=TRUE; + last=i; + } + } + if(column[i].gcr_flags&GCRCC) + column[i].gcr_flags|=(GCRX|GCRBLKM|GCRBLKP); + } + + /* Added to fix the track extension bug */ + if((column[to].gcr_wanted==net) || + (!column[to].gcr_hOk && !column[to].gcr_lOk)) + column[ to].gcr_h=net; + else + { + column[to].gcr_h=(GCRNet *) NULL; + column[to].gcr_hOk=FALSE; + column[to].gcr_lOk=FALSE; + column[to].gcr_hi=column[to].gcr_lo= EMPTY; + } + + if(column[from].gcr_wanted!=net) + { + column[to].gcr_hi=column[from].gcr_hi; + if(column[from].gcr_hi!= EMPTY) + column[column[from].gcr_hi].gcr_lo=to; + if(column[from].gcr_logcr_hi != EMPTY) + col[colPtr->gcr_hi].gcr_lo = colPtr->gcr_lo; + if (colPtr->gcr_lo != EMPTY) + col[colPtr->gcr_lo].gcr_hi = colPtr->gcr_hi; + colPtr->gcr_lo = colPtr->gcr_hi = EMPTY; + colPtr->gcr_h = (GCRNet *) NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrShellSort -- + * + * The shell sort from page 116 of Kernighan and Ritchie. Sorts in + * increasing or decreasing order, depending on whether the flag is set. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrShellSort(v, n, isUp) + GCRNet **v; + int n; + bool isUp; +{ + int gap, i, j, a1, a2; + GCRNet * net; + + for(gap=n/2; gap>0; gap/=2) + for(i=gap; i=0; j-=gap) + { + a1=v[ j]->gcr_sortKey; + a2=v[j+gap]->gcr_sortKey; + if(isUp) + if(a1>a2) + { + net=v[j+gap]; + v[j+gap]=v[j]; + v[j]=net; + } + else ; + else + if(a1to) + { + i=from; + from=to; + to=i; + } + + for(i=from; i<=to; i++) + { + flags=col[i].gcr_flags; + if((col[i].gcr_v!=net)&&(col[i].gcr_v!=(GCRNet *) NULL)) + return(FALSE); /* Already wired vertically */ + else + if((flags & GCRCE) && (i!=to)) + return(FALSE); /* Column ended */ + else + if( (flags & (GCRBLKP|GCRBLKM|GCRX|GCRCC)) && + (col[i].gcr_h!=net) && (col[i].gcr_h!=(GCRNet *) NULL) ) + return(FALSE); /* Poly and metal blocked */ + } + + return(TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrCopyCol -- + * + * Make a copy of the given column array. + * + * Results: + * A pointer to a newly malloc'ed column array of the given size. + * + * Side effects: + * Allocates memory. + * + * ---------------------------------------------------------------------------- + */ + +GCRColEl * +gcrCopyCol(col, size) + GCRColEl *col; + int size; +{ + GCRColEl * result; + int i, limit; + + result = (GCRColEl *) mallocMagic((unsigned) ((size+2) * sizeof (GCRColEl))); + limit = size + 2; + for (i = 0; i < limit; i++) + result[i] = col[i]; + return (result); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrLinkTrack -- + * + * Establishes hi and lo links when a net gets assigned to a track + * the hard way. + * + * Results: + * None. + * + * Side effects: + * Changes links in the column. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrLinkTrack(col, net, track, width) + GCRColEl *col; + GCRNet *net; + int track, width; +{ + int i; + + ASSERT(col[track].gcr_hi == EMPTY, "LinkTrack"); + ASSERT(col[track].gcr_lo == EMPTY, "LinkTrack"); + + col[track].gcr_h = net; + col[track].gcr_hi = EMPTY; + for (i = track + 1; i <= width; i++) + if (col[i].gcr_h == net) + { + col[track].gcr_hi = i; + col[i].gcr_lo = track; + break; + } + + col[track].gcr_lo = EMPTY; + for (i = track - 1; i > 0; i--) + if (col[i].gcr_h == net) + { + col[track].gcr_lo = i; + col[i].gcr_hi = track; + break; + } +} diff --git a/gcr/gcrRiver.c b/gcr/gcrRiver.c new file mode 100644 index 00000000..dcf21f02 --- /dev/null +++ b/gcr/gcrRiver.c @@ -0,0 +1,179 @@ +/* + * gcrRiver.c - + * + * The greedy router: river-routing across the tops of channels. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrRiver.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "gcr/gcr.h" +#include "textio/textio.h" +#include "utils/malloc.h" + +/* Forward declarations */ +bool gcrOverCellVert(); +bool gcrOverCellHoriz(); + + +/* + * ---------------------------------------------------------------------------- + * + * gcrRiverRoute -- + * + * Determine if a channel should be routed by a simple river-router; + * if so, then route it. Currently, river-routing channels are identified + * during channel decomposition. + * + * Results: + * Returns TRUE on success, FALSE on failure (in which case + * the caller should try to route the channel by other means. + * + * Side effects: + * If successful, sets flags in the channel structure to show + * where routing is to be placed. + * + * ---------------------------------------------------------------------------- + */ + +bool +gcrRiverRoute(ch) + GCRChannel *ch; +{ + switch (ch->gcr_type) + { + case CHAN_HRIVER: + if (gcrOverCellHoriz(ch)) + return (TRUE); + break; + case CHAN_VRIVER: + if (gcrOverCellVert(ch)) + return (TRUE); + break; + } + + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrOverCellHoriz -- + * gcrOverCellVert -- + * + * Route an over-cell channel if possible. These channels should be + * river-routable. We perform a few quick checks to ensure that there + * are terminals only on opposite sides in pairs. Channels routed + * horizontally are processed by gcrOverCellHoriz(); those routed + * vertically are processed by gcrOverCellVert(). + * + * Results: + * TRUE if the channel met our requirements and we routed it + * successfully; FALSE if we couldn't route it. + * + * Side effects: + * Sets flags in the channel structure to show where routing + * is to be placed. + * + * ---------------------------------------------------------------------------- + */ + +#define USED(pin) \ + ((pin)->gcr_pId != (GCRNet *) 0 && (pin)->gcr_pId != (GCRNet *) -1) + +bool +gcrOverCellHoriz(ch) + GCRChannel *ch; +{ + short **result = ch->gcr_result; + int col, row; + + /* Ensure top and bottom pins aren't used */ + for (col = 1; col <= ch->gcr_length; col++) + if (USED(&ch->gcr_tPins[col]) || USED(&ch->gcr_bPins[col])) + { + TxPrintf("Failing because top or bottom pins are used\n"); + return (FALSE); + } + + /* Ensure left and right pins match */ + for (row = 1; row <= ch->gcr_width; row++) + if (USED(&ch->gcr_lPins[row]) && USED(&ch->gcr_rPins[row])) + { + if (ch->gcr_lPins[row].gcr_pId != ch->gcr_rPins[row].gcr_pId + || ch->gcr_lPins[row].gcr_pSeg != ch->gcr_rPins[row].gcr_pSeg) + { + TxPrintf("Failing because left and right pins don't match\n"); + return (FALSE); + } + } + + /* + * Channel is routable by a simple river-router: + * zoom across for each row that is to be connected + * across the channel. + */ + for (row = 1; row <= ch->gcr_width; row++) + if (USED(&ch->gcr_lPins[row])) + for (col = 0; col <= ch->gcr_length; col++) + result[col][row] |= GCRR; + + return (TRUE); +} + +bool +gcrOverCellVert(ch) + GCRChannel *ch; +{ + short **result = ch->gcr_result; + int col, row; + + /* Ensure left and right pins aren't used */ + for (row = 1; row <= ch->gcr_width; row++) + if (USED(&ch->gcr_lPins[row]) || USED(&ch->gcr_rPins[row])) + { + TxPrintf("Failing because left or right pins are used\n"); + return (FALSE); + } + + /* Ensure top and bottom pins match */ + for (col = 1; col <= ch->gcr_length; col++) + if (USED(&ch->gcr_tPins[col]) && USED(&ch->gcr_bPins[col])) + { + if (ch->gcr_tPins[col].gcr_pId != ch->gcr_bPins[col].gcr_pId + || ch->gcr_tPins[col].gcr_pSeg != ch->gcr_bPins[col].gcr_pSeg) + { + TxPrintf("Failing because top and bottom pins don't match\n"); + return (FALSE); + } + } + + /* + * Channel is routable by a simple river-router: + * zoom across for each column that is to be connected + * across the channel. + */ + for (col = 1; col <= ch->gcr_length; col++) + if (USED(&ch->gcr_tPins[col])) + for (row = 0; row <= ch->gcr_width; row++) + result[col][row] |= GCRU; + + return (TRUE); +} diff --git a/gcr/gcrRoute.c b/gcr/gcrRoute.c new file mode 100644 index 00000000..aeb91ebc --- /dev/null +++ b/gcr/gcrRoute.c @@ -0,0 +1,319 @@ +/* gcrRoute.c - + * + * The greedy router: Top level procedures. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrRoute.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "gcr/gcr.h" +#include "utils/signals.h" +#include "utils/malloc.h" +#include "utils/styles.h" + +int gcrRouterErrors; +extern int gcrStandalone; + +/* Forward declarations */ +void gcrRouteCol(); +void gcrExtend(); + + +/* + * ---------------------------------------------------------------------------- + * + * GCRroute -- + * + * Top level for the greedy channel router. + * Routes are already set up channel routing problem. + * + * Results: + * The return value is the number of errors found while routing + * this channel. + * + * Side effects: + * Modifies flag bits in the channel to show the presence of routing. + * Calls RtrChannelError when there are errors. + * + * ---------------------------------------------------------------------------- + */ + +int +GCRroute(ch) + GCRChannel *ch; +{ + int i, density, netId; + char mesg[256]; + GCRColEl *col; + GCRPin *pin; + GCRNet *net; + + /* Try river-routing across the channel if possible */ + gcrRouterErrors = 0; + if (gcrRiverRoute(ch)) + return (gcrRouterErrors); + + gcrBuildNets(ch); + if (ch->gcr_nets == (GCRNet *) NULL) + return (gcrRouterErrors); + + gcrSetEndDist(ch); + density = gcrDensity(ch); +/* gcrPrDensity(ch, density); /* Debugging */ + if (density > ch->gcr_width) + { + (void) sprintf(mesg, "Density (%d) > channel size (%d)", + density, ch->gcr_width); + RtrChannelError(ch, ch->gcr_width, ch->gcr_length, mesg, NULL); + } + + gcrInitCollapse(ch->gcr_width + 2); + gcrSetFlags(ch); + + /* Process the first column */ + gcrInitCol(ch, ch->gcr_lPins); + gcrExtend(ch, 0); + gcrPrintCol(ch, 0, GcrShowResult); + + /* Process subsequent columns */ + for (i = 1; i <= ch->gcr_length; i++) + { + if (SigInterruptPending) + goto bottom; + gcrRouteCol(ch, i); + } + + /* Process errors at the end */ + col = ch->gcr_lCol; + pin = ch->gcr_rPins; + for (i = 1; i <= ch->gcr_width; i++, col++, pin++) + if (col->gcr_h != pin->gcr_pId) + { + netId = col->gcr_h ? col->gcr_h->gcr_Id : pin->gcr_pId->gcr_Id; + RtrChannelError(ch, ch->gcr_length, i, + "Can't make end connection", netId); + gcrRouterErrors++; + } + +bottom: + /* For debugging: print channel on screen */ + gcrDumpResult(ch, GcrShowEnd); + + /* + * We have to free up the nets here, since callers may re-arrange + * the channel and cause the net structure to become invalid + * anyway. + */ + for (net = ch->gcr_nets; net; net = net->gcr_next) + freeMagic((char *) net); + ch->gcr_nets = NULL; + + return (gcrRouterErrors); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrRouteCol -- + * + * Route the given column in the channel. + * + * Results: + * None. + * + * Side effects: + * Sets flags in the channel structure to show where routing + * is to be placed. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrRouteCol(ch, indx) + GCRChannel *ch; + int indx; /* Index of column being routed. */ +{ + GCRNet **gcrClassify(), **list; + GCRColEl *col; + int count; + + /* Make feasible top and bottom connections */ + gcrCheckCol(ch, indx, "Start of gcrRouteCol"); + gcrFeasible(ch, indx); + gcrCheckCol(ch, indx, "After feasible connections"); + + /* Here I should vacate terminating tracks */ + if (GCRNearEnd(ch, indx) && + (GCREndDist < ch->gcr_length || !GCRNearEnd(ch, indx - 1))) + gcrMarkWanted(ch); + + /* Collapse split nets in the pattern that frees the most tracks */ + gcrCollapse(&ch->gcr_lCol, ch->gcr_width, 1, ch->gcr_width, 0); + gcrPickBest(ch); + gcrCheckCol(ch, indx, "After collapse"); + + col = ch->gcr_lCol; + + /* Reduce the range of split nets */ + gcrReduceRange(col, ch->gcr_width); + gcrCheckCol(ch, indx, "After reducing range of split nets"); + + /* Vacate obstructed tracks. Split to make multiple end connections */ + gcrVacate(ch, indx); + + /* Raise rising and lower falling nets */ + list = gcrClassify(ch, &count); + gcrCheckCol(ch, indx, "After classifying nets"); + gcrMakeRuns(ch, indx, list, count, TRUE); + gcrCheckCol(ch, indx, "After making rising/falling runs"); + + gcrCheckCol(ch, indx, "After vacating"); + if (GCRNearEnd(ch, indx)) + { + gcrUncollapse(ch, &ch->gcr_lCol, ch->gcr_width, 1, ch->gcr_width, 0); + gcrPickBest(ch); + } + gcrCheckCol(ch, indx, "After uncollapse"); + + /* Extend active tracks to the next column. Place contacts */ + gcrExtend(ch, indx); + gcrCheckCol(ch, indx, "After widen and extend"); + gcrPrintCol(ch, indx, GcrShowResult); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrExtend -- + * + * Extend dangling wires to the next column. + * Don't extend off the end of the channel if the wrong connection + * would be made. + * + * Results: + * None. + * + * Side effects: + * Sets bits in the result array for the channel. Where there + * are blockages in the next column, adds contacts to blocked + * tracks for a layer switch. Clears the vertical wiring for + * the new column. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrExtend(ch, currentCol) + GCRChannel *ch; /* Channel being routed */ + int currentCol; /* Column that has just been completed */ +{ + short *res = ch->gcr_result[currentCol]; + GCRColEl *col = ch->gcr_lCol; + short *prev = (short *) NULL, *next = (short *) NULL; + bool hasNext, hasPrev; + int i; + + ASSERT(ch->gcr_result, "gcrExtend: "); + if (currentCol > 0) prev = ch->gcr_result[currentCol - 1]; + if (currentCol <= ch->gcr_length) next = ch->gcr_result[currentCol + 1]; + + /* + * Consider each track, including the pseudo-track at the + * bottom (0) of the channel, but not the one at the top + * (ch->gcr_width). + */ + for (i = 0; i <= ch->gcr_width; i++) + { + if (col[1].gcr_v == col->gcr_v && col->gcr_v) + { + /* Track extends upwards */ + res[0] |= GCRU; + if (i == ch->gcr_width) res[1] |= GCRU; + if (col->gcr_flags & GCRCC) res[0] |= GCRX; + if (col[1].gcr_flags & GCRCC) res[1] |= GCRX; + } + + /* Don't process track if not occupied by a real net */ + hasPrev = prev && (*prev & GCRR); + if (col->gcr_h == (GCRNet *) NULL) + { + if (currentCol == 0) res[0] &= ~GCRR; + if (hasPrev) res[0] |= GCRX; + col->gcr_v = 0; + } + else + { + /* Extend net if split or another pin exists in this channel */ + hasNext = col->gcr_hi != EMPTY + || col->gcr_lo != EMPTY + || GCRPin1st(col->gcr_h); + + if (col->gcr_v == col->gcr_h && (hasPrev || hasNext)) + res[0] |= GCRX; + + /* Clear vertical wiring */ + col->gcr_v = 0; + + /* Terminate unsplit nets with no pins after the current column */ + if (!hasNext) col->gcr_h = (GCRNet *) NULL; + else if (col->gcr_flags & GCRTE) + { + /* + * If the track should be extended but can't due to a + * hard obstacle, then print a message and terminate it. + */ + RtrChannelError(ch, currentCol, i, + "Can't extend track through obstacle", col->gcr_h->gcr_Id); + gcrRouterErrors++; + col->gcr_h = (GCRNet *) NULL; + } + else if (currentCol == ch->gcr_length && i + && ch->gcr_rPins[i].gcr_pId == (GCRNet *) NULL) + { + /* If track about to make a bad connection, don't extend */ + RtrChannelError(ch, currentCol, i, + "Can't extend track to bad connection", col->gcr_h->gcr_Id); + col->gcr_h = (GCRNet *) NULL; + gcrRouterErrors++; + } + else + { + /* Extend the net into the next column */ + res[0] |= GCRR; + if (currentCol == ch->gcr_length) *next |= GCRR; + } + + /* Contact in next col if GCRTC */ + if (*next & GCRTC) col->gcr_v = col->gcr_h; + } + + if (prev) prev++; + if (next) col->gcr_flags = *next++; + else col->gcr_flags= 0; + res++; + col++; + } + + col->gcr_v = 0; + col->gcr_flags = 0; +} diff --git a/gcr/gcrShwFlgs.c b/gcr/gcrShwFlgs.c new file mode 100644 index 00000000..fc18e6ed --- /dev/null +++ b/gcr/gcrShwFlgs.c @@ -0,0 +1,269 @@ +/* gcrShowFlags.c - + * + * Code to highlight areas flagged by the router. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrShwFlgs.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "gcr/gcr.h" +#include "utils/heap.h" +#include "router/router.h" +#include "utils/main.h" +#include "utils/styles.h" +#include "textio/textio.h" + +#define MAXFLAGS 17 + +char * GCRFlagNames[]= + {"blkb", "blkm", "blkp", "cc", "ce", "r", "tc", "te", "u", + "v2", "vl", "vd", "vm", "vr", "vu", "x", "z", 0}; + +int GCRFlagValue[]= + { 3, 1, 2, 256, 1024, 8, 128, 512, 4, + 64, 32, 32768, 2048, 8192, 16384, 16, 4096}; + +char * GCRFlagDescr[]={ + "3 Both layers are blocked", + "1 Location is blocked with metal", + "2 Location is blocked with poly", + "256 Column contact needed", + "1024 Column ends beyond this point", + "8 Connect to the right", + "128 Track contact needed", + "512 Track ends right of this point", + "4 Connect from track upwards", + "64 Vacate track due to 2-layer obstacle", + "32 Vacate track from left", + "32768 Vacate track from down", + "2048 Vertical poly changed to metal", + "8192 Vacate track from right", + "16384 Vacate track from up", + "16 Metal/poly contact", + "4096 Via not deleted" + }; + +CellDef * gcrShowCell = (CellDef *) NULL; + +/* + * ---------------------------------------------------------------------------- + * + * gcrShow -- + * + * Fields commands of the form :*seeflags to display the router + * flags in the channel under the point. If no arguments, then turn + * off highlighting. + * + * Results: + * None. + * + * Side effects: + * Displays various router flags as feedback. Existing feedback + * is cleared. + * + * ---------------------------------------------------------------------------- + */ + +void +GCRShow(point, arg) + Point * point; + char * arg; +{ + GCRChannel * ch; + HashEntry * he; + Rect box; + int dx, dy, track, col, mask; + short * colBits; + char msg[100]; + Tile * tile; + void gcrDumpChannel(); + +/* Figure out which channel is selected */ + + if(RtrChannelPlane == NULL) + { + TxError("Sorry. You must route before looking at flags!\n"); + return; + } + tile = TiSrPoint((Tile *) NULL, RtrChannelPlane, point); + if(TiGetType(tile) != 0) + { + TxError("Point to the channel you want to highlight.\n"); + return; + } + he = HashLookOnly(&RtrTileToChannel, (char *) tile); + if(he == (HashEntry *) NULL) + { + TxError("No channel under point. Have you already routed?\n"); + return; + } + ch = (GCRChannel *) HashGetValue(he); + +/* Translate the command argument to the bit mask for the flag */ + mask = Lookup(arg, GCRFlagNames); + if ( mask < 0 ) + { + if(strcmp(arg, "dump") == 0) + { + gcrDumpChannel(ch); + return; + } + if(strcmp(arg, "help") == 0) + TxError("Legal values are:\n"); + else + if (mask == -1) + TxError("%s: ambiguous. Legal values are:\n", arg); + else + TxError("%s: not found. Legal values are:\n", arg); + for(col=0; colgcr_result == (short **) NULL) + { + TxError("Oops. Somebody deleted the results array.\n"); + return; + } + +/* Scan the routing grid, create feedback areas for each grid location + * where the mask bit is set. + */ + + dx = ch->gcr_origin.p_x - 2; + for(col = 0; col <= ch->gcr_length; col++) + { + if((colBits = ch->gcr_result[col]) == (short *) NULL) + { + TxError("Oops. Result array column %d is missing.\n", col); + return; + } + dy = ch->gcr_origin.p_y - 2; + for(track = 0; track <= ch->gcr_width; track++) + { + if((colBits[track] & mask) == mask) + { + box.r_xbot = dx; + box.r_ybot = dy; + box.r_xtop = dx + RtrGridSpacing; + box.r_ytop = dy + RtrGridSpacing; + DBWFeedbackAdd(&box, msg, EditCellUse->cu_def, 1, + STYLE_PALEHIGHLIGHTS); + } + dy += RtrGridSpacing; + } + dx += RtrGridSpacing; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrDumpChannel -- + * + * Create a file called "channel.XXXX" where XXXX is the hex address + * of the channel. The file contains the routing problem for the + * channel, complete with obstacles. + * + * Results: + * None. + * + * Side effects: + * Creates a file. + * + * ---------------------------------------------------------------------------- + */ + +void +gcrDumpChannel(ch) + GCRChannel * ch; +{ + char name[20]; + int track, col, netCount = 0, gcrNetName(); + short res; + GCRNet * net, * netNames[500]; + FILE * fp, * fopen(); + + netNames[0]=(GCRNet *) 0; + (void) sprintf(name, "channel.%p", ch); + if((fp = fopen(name, "w")) == NULL) + { + TxError("Can't open file %s to dump channel.\n", name); + return; + } + fprintf(fp, "* %d %d\n", ch->gcr_width, ch->gcr_length); + for(track=1; track<=ch->gcr_width; track++) + { + net = ch->gcr_lPins[track].gcr_pId; + fprintf(fp, "%4d", gcrNetName(netNames, &netCount, net)); + } + fprintf(fp, "\n"); + for(col=1; col<=ch->gcr_length; col++) + { + net = ch->gcr_bPins[col].gcr_pId; + fprintf(fp, "%4d", gcrNetName(netNames, &netCount, net)); + for(track=1; track<=ch->gcr_width; track++) + { + res = ch->gcr_result[col][track]; + if((res & GCRBLKM) && (res & GCRBLKP)) + fprintf(fp, " X"); + else + if(res & GCRBLKM) + fprintf(fp, " M"); + else + if(res & GCRBLKP) + fprintf(fp, " P"); + else + fprintf(fp, " ."); + } + net = ch->gcr_tPins[col].gcr_pId; + fprintf(fp, "%4d", gcrNetName(netNames, &netCount, net)); + fprintf(fp, "\n"); + } + for(track=1; track<=ch->gcr_width; track++) + { + net = ch->gcr_rPins[track].gcr_pId; + fprintf(fp, "%4d", gcrNetName(netNames, &netCount, net)); + } + fprintf(fp, "\n"); + fclose(fp); +} + +int +gcrNetName(netNames, netCount, net) + GCRNet * netNames[]; + int * netCount; + GCRNet * net; +{ + int i; + for(i=0; i<= *netCount; i++) + if(netNames[i]==net) return(i); + *netCount = *netCount + 1; + netNames[*netCount]=net; + return(*netCount); +} diff --git a/gcr/gcrUnsplit.c b/gcr/gcrUnsplit.c new file mode 100644 index 00000000..1e64be9f --- /dev/null +++ b/gcr/gcrUnsplit.c @@ -0,0 +1,610 @@ +/* gcrUnsplit.c - + * + * The greed router: Procedures for jogging unsplit nets. + * * Raising rising nets and lowering falling nets. + * * Vacating tracks needed at the end of the channel. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/gcr/gcrUnsplit.c,v 1.2 2009/12/30 13:42:34 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "gcr/gcr.h" +#include "utils/malloc.h" + +/* Forward declarations */ + +void gcrMakeRuns(); + + +/* + * ---------------------------------------------------------------------------- + * gcrVacate -- + * + * Try to vacate tracks that are needed to make right-edge connections. + * Only consider moving nets that are unsplit. Vacate the nets in + * asccending order of jog length. + * + * If the jogged net is rising or falling, make the jog in the direction + * of motion, except that when near the end of the channel jog any way + * necessary to vacate a needed track. + * + * Results: + * None. + * + * Side effects: + * Changes the wiring in the current column. + * ---------------------------------------------------------------------------- + */ + +void +gcrVacate(ch, column) + GCRChannel * ch; + int column; +{ + int i; + int to, count, gcrIsGreater(); + GCRColEl * col; + GCRNet * net, ** list; + bool nearEnd; + + list=(GCRNet **) mallocMagic((unsigned) (ch->gcr_width+1) * sizeof(GCRNet *)); + ASSERT(list!=(GCRNet **) NULL,"gcrVacate: malloc failed."); + col=ch->gcr_lCol; + count=0; + nearEnd=(ch->gcr_length-column<=GCREndDist); + + for(i=1; i<=ch->gcr_width; i++) + { + net=col[i].gcr_h; + + /* Don't need to vacate an empty track. */ + if(net==(GCRNet *) NULL) + continue; + + /* Skip nets if they are done: unsplit with no more pins */ + if( (col[i].gcr_hi== EMPTY) && (col[i].gcr_lo== EMPTY) && + (GCRPin1st(net)==(GCRPin *) NULL) ) + continue; + + /* Select nets that must vacate their tracks. */ + if( ((col[i].gcr_wanted!=net) && (col[i].gcr_wanted!=(GCRNet *) NULL))|| + ((col[i].gcr_flags & GCRVL) && !nearEnd) ) + { + /* Skip split nets */ + if((col[i].gcr_hi!= EMPTY) || (col[i].gcr_lo!= EMPTY)) + continue; + + /* If the track ends here, then take an empty track, even if it is + * covered; otherwise only vacate to a track that is completely + * free of obstacles. + */ + if( (col[i].gcr_flags & GCRTE) || (i==1) || (i==ch->gcr_width) ) + to=gcrLook(ch, i, TRUE); + else + to=gcrLook(ch, i, FALSE); + + if(to!= EMPTY) /*found a vacating jog*/ + { + /* Skip it if it is to a track needed for an end connection*/ + if(ch->gcr_rPins[to].gcr_pId!=(GCRNet *) 0) + continue; + list[count++]=net; + net->gcr_track=i; + net->gcr_dist=to-i; + net->gcr_sortKey=abs(to-i); + } + } + } + if(count>0) + { + gcrShellSort(list, count, TRUE); + gcrMakeRuns(ch, column, list, count, FALSE); + } +} + +/* + * ---------------------------------------------------------------------------- + * gcrLook -- + * + * Look for an empty track. + * + * Results: + * Return the track index of the nearest empty track which is accessible + * and is not blocked or wanted by some other net. If the currently + * occupying net is rising or falling, the new track should go that way + * if possible. + * + * Want to choose the empty track to minimize the wire length from + * "track" to "empty" to "target". + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +int +gcrLook(ch, track, canCover) + GCRChannel * ch; + int track; + bool canCover; +{ + int up, dn, dir, bestUp= EMPTY, bestDn= EMPTY, uplim, dnlim; + int target, upLength, dnLength; + short flag; + GCRNet * net; + GCRColEl * col; + bool uBlock, dBlock; + + col=ch->gcr_lCol; + net=col[track].gcr_h; + + /* Conflicting vertical wiring blocks any run. + */ + if((col[track].gcr_v!=(GCRNet *) NULL)&&(col[track].gcr_v!=net)) + return(EMPTY); + + /* Find the upper and lower limits on searching: either the edge of + * the channel or else the next track occupied by the net. + */ + if(col[track].gcr_hi!= EMPTY) + uplim=col[track].gcr_hi; + else uplim=ch->gcr_width; + if(col[track].gcr_lo!= EMPTY) + dnlim=col[track].gcr_lo; + else dnlim=1; + + /* Look both upwards and downwards for an available track. + */ + dir=gcrClass(net, track); + target=track+dir; + uBlock=dBlock=FALSE; + for(up=track+1, dn=track-1; ((up<=uplim) || (dn>=dnlim)); up++, dn--) + { + if((up<=uplim) && (!uBlock) && (bestUp== EMPTY)) + { + flag = col[up].gcr_flags; + if(BLOCK(flag)) + uBlock=TRUE; + else + if((col[up].gcr_v!=net) && (col[up].gcr_v!=(GCRNet *) NULL)) + uBlock=TRUE; + else + if((col[up].gcr_h != (GCRNet *) NULL) && (col[up].gcr_h != net) && + (flag & (GCRBLKM | GCRBLKP))) + uBlock=TRUE; + else + if(((col[up].gcr_wanted==(GCRNet *) NULL) || + (col[up].gcr_wanted==net)) && !(flag & GCRVL) && + + /* A track with a single layer of obstacle is disallowed unless + * canCover is set TRUE. + */ + (((!(flag & GCRBLKM)) && (!(flag & GCRBLKP)) ) || canCover)) + { + if(dir>=0) + return(up); + else + { + /* Figure out the wiring length to this track. Set this + * as the length to beat in the other direction. + */ + bestUp=up; + upLength=(bestUp-track)+bestUp-target; + if((track-upLength+1)>dnlim) + dnlim=track-upLength+1; + } + } + } + + if((dn>=dnlim) && (!dBlock) && (bestDn== EMPTY)) + { + flag = col[dn].gcr_flags; + if(BLOCK(flag)) + dBlock=TRUE; + else + if((col[dn].gcr_v!=net) && (col[dn].gcr_v!=(GCRNet *) NULL)) + dBlock=TRUE; + else + if((col[dn].gcr_h != (GCRNet *) NULL) && (col[dn].gcr_h != net) && + (flag & (GCRBLKM | GCRBLKP))) + dBlock=TRUE; + else + if( (col[dn].gcr_h==(GCRNet *) NULL) && + ((col[dn].gcr_wanted==(GCRNet *) NULL) || + (col[dn].gcr_wanted==net)) && !(flag & GCRVL) && + + /* A track with a single layer of obstacle is disallowed unless + * canCover is set TRUE. + */ + ((!(flag & GCRBLKM) && !(flag & GCRBLKP) ) || canCover)) + { + if(dir<=0) + return(dn); + else + { + bestDn=dn; + dnLength=(track-bestDn)+(target-bestDn); + if((track+dnLength-1)0) + return(bestDn); + else + return(bestUp); +} + +/* + * ---------------------------------------------------------------------------- + * gcrClassify -- + * + * Determine whether each net is rising or falling. + * GRclassify is called at startup, when the channel is split, + * and whenever the routing direction changes. + * + * Results: + * Return a pointer to an array of pointers to rising or falling nets, + * sorted in order of decreasing distance to target edge. + * + * Side effects: + * Sets the rising/falling status for all nets. + * ---------------------------------------------------------------------------- + */ + +GCRNet ** +gcrClassify(ch, count) + GCRChannel * ch; + int * count; +{ + GCRColEl * col; + GCRPin * pin, * next; + int i, dist; + GCRNet ** result; + + col=ch->gcr_lCol; + result=(GCRNet **) mallocMagic((unsigned) (ch->gcr_width+1) * sizeof(GCRNet *)); + ASSERT(result!=(GCRNet **) NULL, "gcrClassify: malloc failed."); + *count=0; + +/* Scan up the column, classifying nets. Since each net need only be + * classified once, skip over those nets with some lower track. + */ + for(i=1; i<=ch->gcr_width; i++) + { + /* Process non-empty tracks with no lower track for the net */ + + if( (col[i].gcr_h!=(GCRNet *) NULL) && (col[i].gcr_lo== EMPTY) ) + { + if(col[i].gcr_hi!= EMPTY) + continue; + + pin=GCRPin1st(col[i].gcr_h); + if(pin==NULL) + continue; + + dist=pin->gcr_y-i; + if(dist==0) + continue; + + for(next=GCRPinNext(pin); next!=(GCRPin *) NULL; + next=GCRPinNext(next)) + { + if(next->gcr_x>pin->gcr_x+GCRSteadyNet) + break; /*Too far => doesn't count*/ + + if( ((next->gcr_y-i)>0)!=(dist>0) ) + { + dist=0; /*Pin in the opposite direction*/ + break; + } + } + if(dist!=0) + { + col[i].gcr_h->gcr_dist=dist; + col[i].gcr_h->gcr_sortKey=gcrRealDist(col, i, dist); + col[i].gcr_h->gcr_track=i; + result[(*count)++]=col[i].gcr_h; + } + } + } + result[(*count)]=(GCRNet *) NULL; + if(*count >0) + gcrShellSort(result, *count, FALSE); + return(result); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrRealDist -- + * + * Convert a distance from a track to a pin into a sort key for ranking + * rising and falling nets. Ranking numbers for sorting are non-negative + * integers reflecting the distance a net must move to reach a given track. + * The ranking can be less than the actual distance if the net has vertical + * wiring occupying a range of tracks. + * + * Results: + * Distance value (integer). + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +gcrRealDist(col, i, dist) + GCRColEl * col; + int i, dist; +{ + int j, last; + GCRNet * net=col[i].gcr_h; + last=0; + for(j=i; j!=(i+dist); j=j+ ((dist>0) ? 1 : -1)) + { + if(col[j].gcr_v!=net) + break; + if((col[j].gcr_h==net) || (col[j].gcr_h==(GCRNet *) NULL)) + last=j-i; + } + return(abs(dist-last)); +} + +/* + * ---------------------------------------------------------------------------- + * gcrClass -- + * + * Classify a single net as rising, falling, or steady. Assume that it + * is not split. + * + * Results: + * The distance, or 0 if steady. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +int +gcrClass(net, track) + GCRNet * net; + int track; +{ + GCRPin * pin, * next; + int dist; + + pin=GCRPin1st(net); + if(pin==NULL) + return(0); + + dist=pin->gcr_y-track; + if(dist==0) + return(0); + + for(next=GCRPinNext(pin); next!=(GCRPin *) NULL; + next=GCRPinNext(next)) + { + if(next->gcr_x>pin->gcr_x+GCRSteadyNet) + return(dist); /*Too far => doesn't count*/ + + if( ((next->gcr_y-track)>0)!=(dist>0) ) + return(0); /*Pin in the opposite direction*/ + } + return(dist); +} + +/* + * ---------------------------------------------------------------------------- + * gcrMakeRuns -- + * + * Add jogs to try to move nets from track to track. + * + * Make no jogs that are shorter than minimum jog length, except when + * -within GCREndDist of the end of the channel, + * -the jog brings an unsplit net to its destination track, + * -doing a vacating jog. + * + * Don't jog a net to a free track if it is reserved by another net. + * + * If riseFall (rising and falling jogs) make full or partial runs, + * but only if they do not cause transitions from blocked to clear + * or clear to blocked (blocked to blocked and clear to clear are okay). + * Furthermore, don't overshoot the target track unless it gets + * the track closer to its destination. + * + * If not "riseFall" (vacating jogs) then only make the run if can + * only wire the entire jog. + * + * Results: + * None. + * + * Side effects: + * Changes the wiring in the current column. + * ---------------------------------------------------------------------------- + */ + +void +gcrMakeRuns(ch, column, list, count, riseFall) + GCRChannel * ch; + int column; + GCRNet ** list; + int count; + bool riseFall; +{ + int j, from, to, runTo; + int distToTarget; + GCRNet * net, * gcrEmptySpan(), *save; + GCRColEl * col; + + col=ch->gcr_lCol; + + for(j=0; jgcr_track; + to = from+net->gcr_dist; + distToTarget=abs(from-to); + if(to<=0) + to=1; + else + if(to==ch->gcr_width+1) + to=ch->gcr_width; + + runTo=gcrTryRun(ch, net, from, to, column); + + /* Make no jogs shorter than minimum jog length, except when close + * to the end of the channel, or if the jog would put the net into + * its final track. + */ + if(runTo== EMPTY) + continue; + + if((!riseFall)&&(runTo!=to)) + continue; + + if( (!riseFall) || + (abs(from-runTo)>=GCRMinJog) || + (GCRNearEnd(ch, column) && + (ch->gcr_rPins[runTo].gcr_pId==net)) ) + { + if(!riseFall) + { + save=col[from].gcr_wanted; + col[from].gcr_wanted=(GCRNet *) NULL; + gcrMoveTrack(col, net, from, runTo); + col[from].gcr_wanted=save; + } + else + /* Don't make a rising or falling jog unless it moves the + * net closer to its target track. + */ + if(distToTarget>abs(runTo-to)) + gcrMoveTrack(col, net, from, runTo); + } + gcrCheckCol(ch, column, "gcrMakeRuns"); + } + freeMagic((char *) list); +} + +/* + * ---------------------------------------------------------------------------- + * + * gcrTryRun -- + * + * Try to make a vertical run from one track to another + * + * Results: + * Return the index of the track as close as possible to the desired + * track. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +gcrTryRun(ch, net, from, to, column) + GCRChannel * ch; + GCRNet * net; + int from, to, column; +{ + GCRColEl * col; + GCRNet * vnet, * hnet; + int firstFlag, flag, runTo, i; + bool sourceEnds, covered, up; + + if(from==to) return(EMPTY); + up = (fromgcr_lCol; + runTo = EMPTY; + firstFlag = col[from].gcr_flags; + covered = (firstFlag & (GCRBLKM | GCRBLKP)) ? TRUE : FALSE; + sourceEnds = (firstFlag & GCRTE) ? TRUE : FALSE; + for(i=from; (up && (i<=to)) || (!up && (i>=to)); i=i + ((from>to) ? -1 : 1)) + { + flag=col[i].gcr_flags; + vnet=col[i].gcr_v; + hnet=col[i].gcr_h; + + /* If the column ends here, might as well give up */ + if(flag & GCRCE) break; + + /* Give up if there is previously placed vertical wiring here */ + if( (vnet!=(GCRNet *) NULL) && (vnet!=net) ) + break; + + /* Give up if blocked on both layers by obstacles */ + if(BLOCK(flag)) + break; + + /* Check to see if blocked due to single layer only allowed here */ + if( (flag & (GCRBLKM | GCRBLKP | GCRCC)) && + (hnet!=(GCRNet *) NULL) && (hnet!=net)) + break; + + /* Don't make a run into a track that is blocked beyond this column */ + if(flag & GCRTE) + continue; + + /* Don't run to a track needed for a column contact, unless near the + * end and an end connection is needed, or source ends and no other track + * was found. + */ + if( (flag & GCRCC) && + (!(GCRNearEnd(ch, column) && (net==col[i].gcr_wanted)) || + (sourceEnds && (runTo== EMPTY)) )) + continue; + + /* Don't use a VACATE track unless source track ends or is also VACATE */ + if((flag & GCRVL) && !(firstFlag & GCRVL) + && !(sourceEnds && (runTo== EMPTY)) + && !((net==col[i].gcr_wanted) && GCRNearEnd(ch, column)) ) + continue; + + /* If current track is occupied, then skip it */ + if( (hnet!=(GCRNet *) NULL) && (hnet!=net) ) + continue; + + /* Take a location with conflicting end connection only if the source is + * similar and no other place has yet been found. + */ + if((col[i].gcr_wanted!=(GCRNet *) NULL) && (col[i].gcr_wanted!=net) + && ((runTo!= EMPTY) || ((col[from].gcr_wanted==net) || + (col[from].gcr_wanted==(GCRNet *) NULL)))) + continue; + + /* Don't move from an uncovered track to a covered track, unless + * near the end and a connection is needed. + */ + if( !covered && (flag & (GCRBLKM | GCRBLKP)) && + !((net==col[i].gcr_wanted) && (GCRNearEnd(ch, column))) ) + continue; + + if(i!=from) + runTo=i; + } + return(runTo); +} diff --git a/graphics/DEFAULT.glyphs b/graphics/DEFAULT.glyphs new file mode 100644 index 00000000..50d96618 --- /dev/null +++ b/graphics/DEFAULT.glyphs @@ -0,0 +1,349 @@ +# +# Cursors for the SUN display (just like AED but black & white only). +# +# rcsid "$Header: /usr/cvsroot/magic-8.0/graphics/DEFAULT.glyphs,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" +# +# + +# syntax of first line: size +size 20 16 16 + +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . . K . . . . . . . . +. . . . . . . K . . . . . . . . +K K K K . . . . . . . K K K K . +K K K K K K . .*. K K K K K K . +K K K K . . . . . . . K K K K . +. . . . . . . K . . . . . . . . +. . . . . . . K . . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . . . . . . . . . . . + +K . . . . . . K . . . . . . K . +. K . . . . . K . . . . . K . . +. . K . . . . K . . . . K . . . +. . . K . . . K . . . K . . . . +. . . . K . . K . . K . . . . . +. . . . . K . K . K . . . . . . +. . . . . . K K K . . . . . . . +K K K K K K K .*K K K K K K K . +. . . . . . K K K . . . . . . . +. . . . . K . K . K . . . . . . +. . . . K . . K . . K . . . . . +. . . K . . . K . . . K . . . . +. . K . . . . K . . . . K . . . +. K . . . . . K . . . . . K . . +K . . . . . . K . . . . . . K . +. . . . . . . . . . . . . . . . + +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K K K K K K K K K K K K K K K +K*K K K K K K K K K K K K K K K + +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K* + +K*K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . + +K K K K K K K K K K K K K K K K* +K K K K K K K K K K K K K K K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K + +K K . K . K . K . K . K . K . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K K K K K K K K K K K K K K K +K*K K K K K K K K K K K K K K K + +K . K . K . K . K . K . K . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K* + +K*K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . K . K . K . K . K . K . K + +K K K K K K K K K K K K K K K K* +K K K K K K K K K K K K K K K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . K . K . K . K . K . K . K K + +K K K K K K K K K K K K K K K K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K K K K K K K K K K K K K K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K*K K K K K K K K K K K K K K K + +K K K K K K K K K K K K K K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K K K K K K K K K K K K K K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K* + +K*K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K K K K K K K K K K K K K K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K K K K K K K K K K K K K K + +K K K K K K K K K K K K K K K K* +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K K K K K K K K K K K K K K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K K K K K K K K K K K K K K K K + +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K K . K . K . K . K . K . K +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K*K K K K K K K K K K K K K K K + +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +K . K . K . K . K . K . K K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K* + +K*K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K K . K . K . K . K . K . K +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . + +K K K K K K K K K K K K K K K K* +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +K . K . K . K . K . K . K K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K + +K K K K K K K K K K K K K K K . +K K K K K K K K K K K K K K K . +K K K K K K K K K K K K K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . K*. . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K K K K K K K K K K K K K . +K K K K K K K K K K K K K K K . +K K K K K K K K K K K K K K K . +. . . . . . . . . . . . . . . . + +K*. . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K K . . . . . . . . . . . . . +K K K K . . . . . . . . . . . . +K K K K K . . . . . . . . . . . +K K K K K K . . . . . . . . . . +K K K K K K K . . . . . . . . . +K K K K . . . . . . . . . . . . +K K . K K . . . . . . . . . . . +K . . K K . . . . . . . . . . . +. . . . K K . . . . . . . . . . +. . . . K K . . . . . . . . . . +. . . . . K K . . . . . . . . . +. . . . . K K . . . . . . . . . +. . . . . . K K . . . . . . . . +. . . . . . K K . . . . . . . . diff --git a/graphics/Depend b/graphics/Depend new file mode 100644 index 00000000..6546e387 --- /dev/null +++ b/graphics/Depend @@ -0,0 +1,138 @@ +grMain.o: grMain.c ../utils/magic.h ../utils/magsgtty.h \ + ../textio/textio.h ../utils/geometry.h ../utils/hash.h \ + ../windows/windows.h ../graphics/graphics.h ../graphics/graphicsInt.h +grLock.o: grLock.c ../utils/magic.h ../utils/geometry.h \ + ../windows/windows.h ../graphics/graphics.h ../textio/textio.h +grDStyle.o: grDStyle.c ../utils/magic.h ../utils/malloc.h \ + ../utils/styles.h ../utils/utils.h ../textio/textio.h \ + ../utils/geometry.h ../graphics/glyphs.h ../windows/windows.h \ + ../graphics/graphics.h ../graphics/graphicsInt.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../dbwind/dbwind.h +grText.o: grText.c ../utils/magic.h ../textio/textio.h \ + ../utils/geometry.h ../database/database.h ../tiles/tile.h \ + ../utils/hash.h ../windows/windows.h ../graphics/graphics.h \ + ../graphics/graphicsInt.h ../utils/utils.h +grCMap.o: grCMap.c ../utils/magic.h ../utils/malloc.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../windows/windows.h ../graphics/graphics.h ../graphics/graphicsInt.h \ + ../utils/utils.h ../textio/textio.h +grClip.o: grClip.c ../utils/magic.h ../textio/textio.h \ + ../utils/geometry.h ../tiles/tile.h ../utils/hash.h ../utils/styles.h \ + ../database/database.h ../windows/windows.h ../graphics/graphics.h \ + ../graphics/graphicsInt.h ../utils/malloc.h +grGlyphs.o: grGlyphs.c ../utils/magic.h ../utils/geometry.h \ + ../utils/utils.h ../windows/windows.h ../graphics/graphics.h \ + ../graphics/graphicsInt.h ../graphics/glyphs.h ../textio/textio.h \ + ../utils/malloc.h +grNull.o: grNull.c ../utils/magsgtty.h ../utils/magic.h \ + ../utils/geometry.h ../windows/windows.h ../graphics/graphics.h \ + ../graphics/graphicsInt.h ../textio/textio.h ../textio/txcommands.h \ + ../utils/signals.h +W3Dmain.o: W3Dmain.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../windows/windows.h ../tiles/tile.h ../utils/hash.h \ + ../utils/undo.h ../database/database.h ../utils/main.h \ + ../commands/commands.h ../graphics/wind3d.h ../graphics/graphicsInt.h \ + ../graphics/graphics.h grTOGLInt.h ../textio/textio.h \ + ../textio/txcommands.h ../utils/utils.h ../utils/styles.h \ + ../dbwind/dbwtech.h ../dbwind/dbwind.h ../extract/extract.h \ + ../graphics/glyphs.h ../utils/malloc.h ../windows/windInt.h ../cif/cif.h \ + ../cif/CIFint.h +grX11su1.o: grX11su1.c ../utils/magic.h ../utils/magsgtty.h \ + ../textio/textio.h ../utils/geometry.h ../textio/txcommands.h \ + ../utils/signals.h ../graphics/glyphs.h ../graphics/graphics.h \ + ../windows/windows.h ../graphics/graphicsInt.h ../utils/utils.h \ + ../utils/hash.h grX11Int.h ../utils/paths.h +grX11su2.o: grX11su2.c ../utils/magic.h ../textio/textio.h \ + ../utils/geometry.h ../graphics/graphics.h ../windows/windows.h \ + ../graphics/graphicsInt.h grX11Int.h +grX11su3.o: grX11su3.c ../utils/magic.h ../utils/geometry.h \ + ../graphics/graphics.h ../windows/windows.h ../graphics/graphicsInt.h \ + ../textio/textio.h ../utils/signals.h ../utils/utils.h ../utils/hash.h \ + ../dbwind/dbwind.h ../database/database.h ../tiles/tile.h \ + ../database/fonts.h grX11Int.h +grX11su4.o: grX11su4.c ../utils/magic.h ../utils/magsgtty.h \ + ../textio/textio.h ../utils/geometry.h ../graphics/graphics.h \ + ../windows/windows.h ../graphics/graphicsInt.h ../textio/txcommands.h \ + grX11Int.h +grX11su5.o: grX11su5.c ../utils/magic.h ../utils/styles.h ../utils/hash.h \ + ../textio/textio.h ../utils/geometry.h ../graphics/graphics.h \ + ../graphics/glyphs.h ../windows/windows.h ../graphics/graphicsInt.h \ + grX11Int.h +grTk1.o: grTk1.c ../tcltk/tclmagic.h ../utils/main.h ../windows/windows.h \ + ../utils/magic.h ../utils/geometry.h ../database/database.h \ + ../tiles/tile.h ../utils/hash.h ../utils/malloc.h ../utils/magsgtty.h \ + ../graphics/graphics.h ../graphics/graphicsInt.h ../textio/textio.h \ + ../textio/txcommands.h ../utils/signals.h ../utils/utils.h ../drc/drc.h \ + ../utils/macros.h grTkInt.h ../utils/paths.h ../graphics/grTkCommon.h +grTk2.o: grTk2.c ../tcltk/tclmagic.h ../utils/magic.h ../textio/textio.h \ + ../utils/geometry.h ../graphics/glyphs.h ../windows/windows.h \ + ../graphics/graphics.h ../graphics/graphicsInt.h grTkInt.h +grTk3.o: grTk3.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/geometry.h \ + ../windows/windows.h ../graphics/graphics.h ../graphics/graphicsInt.h \ + ../textio/textio.h ../utils/signals.h ../utils/utils.h ../utils/hash.h \ + ../utils/malloc.h ../graphics/grTkInt.h ../graphics/grTkCommon.h \ + ../database/fonts.h ../tiles/tile.h +grTk4.o: grTk4.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/magsgtty.h \ + ../textio/textio.h ../utils/geometry.h ../windows/windows.h \ + ../graphics/graphics.h ../graphics/graphicsInt.h ../textio/txcommands.h \ + grTkInt.h grTkCommon.h +grTk5.o: grTk5.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/styles.h \ + ../utils/hash.h ../textio/textio.h ../utils/geometry.h \ + ../graphics/glyphs.h ../windows/windows.h ../graphics/graphics.h \ + ../graphics/graphicsInt.h grTkCommon.h grTkInt.h +grTOGL1.o: grTOGL1.c ../tcltk/tclmagic.h ../utils/main.h \ + ../windows/windows.h ../utils/magic.h ../utils/geometry.h \ + ../database/database.h ../tiles/tile.h ../utils/hash.h ../utils/malloc.h \ + ../utils/magsgtty.h ../graphics/graphics.h ../graphics/graphicsInt.h \ + ../textio/textio.h ../textio/txcommands.h ../utils/signals.h \ + ../utils/utils.h ../drc/drc.h ../utils/macros.h ../graphics/grTOGLInt.h \ + ../utils/paths.h ../graphics/grTkCommon.h +grTOGL2.o: grTOGL2.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../textio/textio.h ../utils/geometry.h ../graphics/glyphs.h \ + ../windows/windows.h ../graphics/graphics.h ../graphics/graphicsInt.h \ + grTOGLInt.h +grTOGL3.o: grTOGL3.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/malloc.h ../windows/windows.h \ + ../graphics/graphics.h ../graphics/graphicsInt.h ../textio/textio.h \ + ../utils/signals.h ../utils/utils.h ../utils/hash.h \ + ../graphics/grTOGLInt.h ../graphics/grTkCommon.h ../database/fonts.h \ + ../tiles/tile.h +grTOGL4.o: grTOGL4.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/magsgtty.h ../textio/textio.h ../utils/geometry.h \ + ../windows/windows.h ../graphics/graphics.h ../graphics/graphicsInt.h \ + ../graphics/grTkCommon.h ../textio/txcommands.h grTOGLInt.h +grTOGL5.o: grTOGL5.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/styles.h ../utils/hash.h ../textio/textio.h ../utils/geometry.h \ + ../graphics/glyphs.h ../windows/windows.h ../graphics/graphics.h \ + ../graphics/graphicsInt.h grTkCommon.h grTOGLInt.h +grTkCommon.o: grTkCommon.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/styles.h ../utils/geometry.h ../utils/hash.h ../utils/malloc.h \ + ../utils/utils.h ../tiles/tile.h ../database/database.h \ + ../windows/windows.h ../dbwind/dbwtech.h ../graphics/graphics.h \ + ../graphics/graphicsInt.h ../dbwind/dbwind.h ../graphics/grTkCommon.h \ + ../graphics/glyphs.h +grOGL1.o: grOGL1.c ../utils/magic.h ../utils/magsgtty.h \ + ../utils/geometry.h ../graphics/graphics.h ../windows/windows.h \ + ../graphics/graphicsInt.h ../textio/textio.h ../textio/txcommands.h \ + ../utils/signals.h ../utils/utils.h ../utils/hash.h grOGLInt.h \ + ../utils/paths.h +grOGL2.o: grOGL2.c ../utils/magic.h ../textio/textio.h \ + ../utils/geometry.h ../graphics/glyphs.h ../graphics/graphics.h \ + ../windows/windows.h ../graphics/graphicsInt.h grOGLInt.h +grOGL3.o: grOGL3.c ../utils/magic.h ../utils/geometry.h \ + ../graphics/graphics.h ../windows/windows.h ../graphics/graphicsInt.h \ + ../textio/textio.h ../utils/signals.h ../utils/utils.h ../utils/hash.h \ + ../dbwind/dbwind.h ../database/database.h ../tiles/tile.h \ + ../database/fonts.h grOGLInt.h +grOGL4.o: grOGL4.c ../utils/magic.h ../utils/magsgtty.h \ + ../textio/textio.h ../utils/geometry.h ../graphics/graphics.h \ + ../windows/windows.h ../graphics/graphicsInt.h ../textio/txcommands.h \ + grOGLInt.h +grOGL5.o: grOGL5.c ../utils/magic.h ../utils/styles.h ../utils/hash.h \ + ../textio/textio.h ../utils/geometry.h ../graphics/graphics.h \ + ../graphics/glyphs.h ../windows/windows.h ../graphics/graphicsInt.h \ + grOGLInt.h +X11Helper.o: X11Helper.c +grX11thread.o: grX11thread.c ../utils/magic.h ../utils/geometry.h \ + ../graphics/graphics.h ../windows/windows.h ../graphics/graphicsInt.h \ + grX11Int.h diff --git a/graphics/FreeMono.pt3 b/graphics/FreeMono.pt3 new file mode 100644 index 00000000..63bf20e3 --- /dev/null +++ b/graphics/FreeMono.pt3 @@ -0,0 +1,2837 @@ +%!PS-AdobeFont-1.0: FreeMono $Revision: 1.1.1.1 $ +%%Title: FreeMono +%Version: $Revision: 1.1.1.1 $ +%%CreationDate: Fri Feb 1 11:57:08 2008 +%%Creator: R. Timothy Edwards +%Copyright: Copyleft 2002, 2003, 2005 Free Software Foundation. +% Generated by FontForge 20080109 (http://fontforge.sf.net/) +%%EndComments + +13 dict begin +/FontType 3 def +/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def +/FontName /FreeMono def +/FontBBox {-557 -320 699 1074 }readonly def +/UniqueID 4131621 def +/XUID [1021 202 645001535 11031634] def +/PaintType 0 def +/FontInfo 10 dict dup begin + /version ($Revision: 1.1.1.1 $) readonly def + /Notice (Copyleft 2002, 2003, 2005 Free Software Foundation.) readonly def + /FullName (Free Monospaced) readonly def + /FamilyName (FreeMono) readonly def + /Weight (Book) readonly def + /FSType 0 def + /ItalicAngle 0 def + /isFixedPitch false def + /UnderlinePosition -124.512 def + /UnderlineThickness 49.8047 def +end readonly def +/Encoding StandardEncoding def +/BuildChar { 1 index /Encoding get exch get 1 index /BuildGlyph get exec } bind def +% I call all my CharProcs with two arguments, the top of the stack will be +% 0 and then next thing is the fontdict. If the tos is zero the char will +% do a setcachedevice, otherwise (for referenced chars) it will not. The +% fontdict argument is so a char can invoke a referenced char. BuildGlyph +% itself will remove the arguments from the stack, the CharProc will leave 'em +/BuildGlyph { 2 copy exch /CharProcs get exch 2 copy known not { pop /.notdef} if get exch pop 0 exch exec pop pop fill} bind def +/CharProcs 127 dict def +CharProcs begin + /.notdef { 432 0 33 0 366 667 setcachedevice } bind def + /space { 599 0 0 0 0 0 setcachedevice + } bind def + /exclam { 599 0 240 -15 360 618 setcachedevice + 338 563 moveto + 320 237 lineto + 318.667 220.333 313.333 211 304 209 curveto + 299 209 lineto + 286.333 209 279.667 218.333 279 237 curveto + 261 563 lineto + 260.333 567.667 260 573 260 579 curveto + 260 595 266.667 606.333 280 613 curveto + 286 616.333 292.667 618 300 618 curveto + 315.333 618 326.667 611.333 334 598 curveto + 337.333 592 339 585.667 339 579 curveto + 338 563 lineto + closepath + 293 85 moveto + 306 85 lineto + 326 85 341.333 77.3333 352 62 curveto + 357.333 54 360 45 360 35 curveto + 360 16.3333 351.667 2.33333 335 -7 curveto + 326.333 -12.3333 316.667 -15 306 -15 curveto + 293 -15 lineto + 273 -15 258 -7.33333 248 8 curveto + 242.667 16.6667 240 25.6667 240 35 curveto + 240 53 248 67 264 77 curveto + 272.667 82.3333 282.333 85 293 85 curveto + closepath + } bind def + /quotedbl { 599 0 146 315 454 604 setcachedevice + 146 604 moveto + 274 604 lineto + 240 351 lineto + 237.333 329 229 317 215 315 curveto + 210 315 lineto + 194.667 315 185 324.333 181 343 curveto + 181 345.667 180.667 348.333 180 351 curveto + 146 604 lineto + closepath + 326 604 moveto + 454 604 lineto + 420 351 lineto + 414.667 328.333 404.667 316.333 390 315 curveto + 374 315 364 325.333 360 346 curveto + 360 351 lineto + 326 604 lineto + closepath + } bind def + /numbersign { 599 0 92 -62 508 647 setcachedevice + 321 -42 moveto + 337 189 lineto + 246 189 lineto + 231 -36 lineto + 227.667 -52.6667 220.667 -61.3333 210 -62 curveto + 200.667 -62 194.333 -57.6667 191 -49 curveto + 190.333 -46.3333 190 -43.6667 190 -41 curveto + 190 -33 lineto + 206 189 lineto + 119 189 lineto + 101 189 92 196 92 210 curveto + 92 223.333 101 230 119 230 curveto + 208 230 lineto + 217 356 lineto + 139 356 lineto + 121 356 112 363 112 377 curveto + 112 390.333 121 397 139 397 curveto + 220 397 lineto + 236 622 lineto + 236.667 638.667 243.667 647 257 647 curveto + 269.667 647 276 638.667 276 622 curveto + 276 619 lineto + 261 397 lineto + 352 397 lineto + 368 622 lineto + 369.333 638 376 646.333 388 647 curveto + 399.333 647 406 640.667 408 628 curveto + 408 622 lineto + 408 619 lineto + 392 397 lineto + 481 397 lineto + 499 397 508 390.333 508 377 curveto + 508 363 499 356 481 356 curveto + 390 356 lineto + 381 230 lineto + 461 230 lineto + 479 230 488 223.333 488 210 curveto + 488 196 479 189 461 189 curveto + 378 189 lineto + 362 -36 lineto + 360.667 -53.3333 353.667 -62 341 -62 curveto + 333.667 -62 327.667 -58 323 -50 curveto + 321.667 -47.3333 321 -44.6667 321 -42 curveto + closepath + 349 356 moveto + 258 356 lineto + 249 230 lineto + 340 230 lineto + 349 356 lineto + closepath + } bind def + /dollar { 599 0 113 -92 487 655 setcachedevice + 446 201 moveto + 446 237 427.667 263.333 391 280 curveto + 374.333 287.333 342.333 295.667 295 305 curveto + 245.667 315 210.333 326 189 338 curveto + 153.667 359.333 136 391.667 136 435 curveto + 136 475 152 508.667 184 536 curveto + 210 558 242 571.333 280 576 curveto + 280 628 lineto + 280 646 287 655 301 655 curveto + 314.333 655 321 646 321 628 curveto + 321 576 lineto + 352.333 573.333 378.333 565.333 399 552 curveto + 407 547.333 415.667 541.333 425 534 curveto + 425.667 553.333 432.667 563 446 563 curveto + 459.333 563 466 554 466 536 curveto + 466 476 lineto + 466 458 459.333 449 446 449 curveto + 434.667 449 427.667 455 425 467 curveto + 425 471 lineto + 422.333 489.667 408 506 382 520 curveto + 358 532 331.333 538 302 538 curveto + 264 538 232.667 526 208 502 curveto + 187.333 482.667 177 460 177 434 curveto + 177 401.333 194.333 377.667 229 363 curveto + 244.333 356.333 275.333 348.667 322 340 curveto + 372.667 330 409 318.667 431 306 curveto + 468.333 283.333 487 248.333 487 201 curveto + 487 155 467 118 427 90 curveto + 399 70.6667 363.667 58.6667 321 54 curveto + 321 -65 lineto + 321 -83 314.333 -92 301 -92 curveto + 287 -92 280 -83 280 -65 curveto + 280 54 lineto + 246 55.3333 213.333 65.6667 182 85 curveto + 170.667 92.3333 161.333 100 154 108 curveto + 154 92 lineto + 154 74 147.333 65 134 65 curveto + 120 65 113 74 113 92 curveto + 113 171 lineto + 113 189 120 198 134 198 curveto + 143.333 198 149.333 192.667 152 182 curveto + 152.667 179.333 153.333 176.333 154 173 curveto + 156 151.667 171.667 133 201 117 curveto + 229.667 101 262.333 93 299 93 curveto + 347.667 93 386 106 414 132 curveto + 435.333 151.333 446 174.333 446 201 curveto + closepath + } bind def + /percent { 599 0 87 -12 513 611 setcachedevice + 361 236 moveto + 398.333 236 429 222.333 453 195 curveto + 473.667 171 484 142.667 484 110 curveto + 484 76 471.333 46.6667 446 22 curveto + 422 -0.666667 394 -12 362 -12 curveto + 326.667 -12 296.667 1.33333 272 28 curveto + 250 51.3333 239 79.3333 239 112 curveto + 239 148 252 178.333 278 203 curveto + 301.333 225 329 236 361 236 curveto + closepath + 361 198 moveto + 334.333 198 312.667 187.667 296 167 curveto + 283.333 151 277 132.667 277 112 curveto + 277 84.6667 287.667 62.3333 309 45 curveto + 324.333 32.3333 342 26 362 26 curveto + 388 26 409.667 36.3333 427 57 curveto + 439.667 73 446 91 446 111 curveto + 446 140.333 435 163.667 413 181 curveto + 398.333 192.333 381 198 361 198 curveto + closepath + 237 611 moveto + 274.333 611 305 597.333 329 570 curveto + 349.667 546.667 360 518.667 360 486 curveto + 360 451.333 347 421.333 321 396 curveto + 297.667 374 270 363 238 363 curveto + 202.667 363 172.667 376.333 148 403 curveto + 126 426.333 115 454.333 115 487 curveto + 115 523 128 553.333 154 578 curveto + 177.333 600 205 611 237 611 curveto + closepath + 237 573 moveto + 210.333 573 188.667 562.667 172 542 curveto + 159.333 526 153 507.667 153 487 curveto + 153 459.667 163.667 437.333 185 420 curveto + 200.333 407.333 218 401 238 401 curveto + 263.333 401 284.667 411.333 302 432 curveto + 315.333 448 322 466 322 486 curveto + 322 515.333 311 538.667 289 556 curveto + 274.333 567.333 257 573 237 573 curveto + closepath + 495 344 moveto + 116 222 lineto + 110.667 220 106.667 219 104 219 curveto + 98 219 93 222.667 89 230 curveto + 87.6667 232.667 87 235.333 87 238 curveto + 87 247.333 93 254 105 258 curveto + 484 380 lineto + 489.333 381.333 493.333 382 496 382 curveto + 503.333 382 508.667 378 512 370 curveto + 512.667 368 513 365.667 513 363 curveto + 513 354.333 507 348 495 344 curveto + closepath + } bind def + /ampersand { 599 0 105 -16 478 519 setcachedevice + 393 0 moveto + 362 48 lineto + 332 5.33333 294.667 -16 250 -16 curveto + 212 -16 178.667 -1 150 29 curveto + 121.333 59 106.333 95 105 137 curveto + 105 142 lineto + 105 188.667 122 226.333 156 255 curveto + 173.333 269.667 193.333 280.333 216 287 curveto + 188.667 331 173 359.667 169 373 curveto + 167 380.333 166 389.333 166 400 curveto + 166 434 179 462.667 205 486 curveto + 229 508 257 519 289 519 curveto + 311.667 519 333.667 512.333 355 499 curveto + 367.667 506.333 376.333 510 381 510 curveto + 389 510 394.667 505.667 398 497 curveto + 399.333 494.333 400 491.667 400 489 curveto + 400 481.667 395.667 475.333 387 470 curveto + 386.333 469.333 385.333 468.667 384 468 curveto + 352 452 lineto + 332 469.333 311 478 289 478 curveto + 265 478 244.333 468.333 227 449 curveto + 213.667 433.667 207 416.667 207 398 curveto + 207 380 217 354 237 320 curveto + 241 313.333 245.667 306 251 298 curveto + 362 121 lineto + 382.667 159.667 398 202.333 408 249 curveto + 451 249 lineto + 469 249 478 242.333 478 229 curveto + 478 215 469 208 451 208 curveto + 439 208 lineto + 424.333 152.667 406.667 110.667 386 82 curveto + 413 41 lineto + 451 41 lineto + 469 41 478 34.3333 478 21 curveto + 478 7 469 0 451 0 curveto + 393 0 lineto + closepath + 338 86 moveto + 233 251 lineto + 197.667 243 172.667 224 158 194 curveto + 150 178 146 160.667 146 142 curveto + 146 108 157.667 79.3333 181 56 curveto + 200.333 35.3333 223 25 249 25 curveto + 282.333 25 310.333 42.3333 333 77 curveto + 334.333 80.3333 336 83.3333 338 86 curveto + closepath + } bind def + /quotesingle { 599 0 236 315 364 604 setcachedevice + 236 604 moveto + 364 604 lineto + 330 351 lineto + 326 327.667 316 315.667 300 315 curveto + 282.667 315 272.667 327 270 351 curveto + 236 604 lineto + closepath + } bind def + /parenleft { 599 0 294 -124 458 604 setcachedevice + 294 243 moveto + 294 313.667 314 392.333 354 479 curveto + 378 533 400.667 571 422 593 curveto + 428.667 600.333 434 604 438 604 curveto + 447.333 604 453.667 599.667 457 591 curveto + 457.667 588.333 458 586 458 584 curveto + 458 576 451 559.667 437 535 curveto + 409.667 487 390.333 445 379 409 curveto + 363 356.333 355 300 355 240 curveto + 355 152.667 378.333 60.6667 425 -36 curveto + 433.667 -54 443.667 -73 455 -93 curveto + 457 -98.3333 458 -102 458 -104 curveto + 458 -112.667 453.667 -119 445 -123 curveto + 442.333 -123.667 439.667 -124 437 -124 curveto + 427.667 -124 413 -108.333 393 -77 curveto + 360.333 -24.3333 334.333 36 315 104 curveto + 301 154 294 200.333 294 243 curveto + closepath + } bind def + /parenright { 599 0 147 -124 311 604 setcachedevice + 147 -104 moveto + 147 -96 154 -79.6667 168 -55 curveto + 194.667 -7.66667 214 34.3333 226 71 curveto + 242 123.667 250 180 250 240 curveto + 250 324.667 229 411.667 187 501 curveto + 176.333 524.333 164 548.333 150 573 curveto + 148 578.333 147 582 147 584 curveto + 147 592.667 151.333 599 160 603 curveto + 162.667 603.667 165.333 604 168 604 curveto + 177.333 604 191.667 588.333 211 557 curveto + 244.333 505 270.667 445 290 377 curveto + 304 327 311 280.333 311 237 curveto + 311 166.333 291 87.3333 251 0 curveto + 227 -53.3333 204.333 -91 183 -113 curveto + 176.333 -120.333 171 -124 167 -124 curveto + 157.667 -124 151.333 -119.667 148 -111 curveto + 147.333 -108.333 147 -106 147 -104 curveto + closepath + } bind def + /asterisk { 599 0 113 250 487 604 setcachedevice + 279 438 moveto + 279 577 lineto + 279 595 286 604 300 604 curveto + 313.333 604 320 595 320 577 curveto + 320 438 lineto + 453 481 lineto + 457.667 483 462.667 484 468 484 curveto + 475.333 484 481 480 485 472 curveto + 486.333 469.333 487 466.667 487 464 curveto + 487 454 480 446.667 466 442 curveto + 333 400 lineto + 414 288 lineto + 418.667 279.333 421 273.333 421 270 curveto + 421 260.667 416.667 254.333 408 251 curveto + 405.333 250.333 403 250 401 250 curveto + 395 250 389.333 253.333 384 260 curveto + 382.667 261.333 381.667 262.667 381 264 curveto + 299 376 lineto + 218 264 lineto + 211.333 254.667 204.333 250 197 250 curveto + 187.667 250 181.333 254.333 178 263 curveto + 177.333 265.667 177 268.333 177 271 curveto + 177 273.667 179.667 279.333 185 288 curveto + 266 400 lineto + 133 442 lineto + 119.667 445.333 113 452.333 113 463 curveto + 113 471.667 117 477.667 125 481 curveto + 127.667 482.333 130.333 483 133 483 curveto + 135 483 139.333 482 146 480 curveto + 279 438 lineto + closepath + } bind def + /plus { 599 0 72 32 528 530 setcachedevice + 320 261 moveto + 320 59 lineto + 320 41 313.333 32 300 32 curveto + 286 32 279 41 279 59 curveto + 279 261 lineto + 99 261 lineto + 81 261 72 268 72 282 curveto + 72 295.333 81 302 99 302 curveto + 279 302 lineto + 279 503 lineto + 279 521 286 530 300 530 curveto + 313.333 530 320 521 320 503 curveto + 320 302 lineto + 500 302 lineto + 518.667 302 528 295.333 528 282 curveto + 528 268 518.667 261 500 261 curveto + 320 261 lineto + closepath + } bind def + /comma { 599 0 135 -145 340 145 setcachedevice + 207 145 moveto + 340 145 lineto + 195 -120 lineto + 184.333 -135.333 174 -143.667 164 -145 curveto + 152 -145 143.333 -139.667 138 -129 curveto + 136 -125 135 -120.667 135 -116 curveto + 135 -115.333 135.667 -111.667 137 -105 curveto + 207 145 lineto + closepath + } bind def + /hyphen { 599 0 72 258 528 299 setcachedevice + 501 258 moveto + 99 258 lineto + 81 258 72 265 72 279 curveto + 72 292.333 81 299 99 299 curveto + 501 299 lineto + 519 299 528 292.333 528 279 curveto + 528 265 519 258 501 258 curveto + closepath + } bind def + /period { 599 0 226 -15 374 116 setcachedevice + 295 116 moveto + 305 116 lineto + 329.667 116 348.667 106.667 362 88 curveto + 370 77.3333 374 65 374 51 curveto + 374 27 364.333 8.66667 345 -4 curveto + 333 -11.3333 319.667 -15 305 -15 curveto + 295 -15 lineto + 271 -15 252 -5.66667 238 13 curveto + 230 23.6667 226 36.3333 226 51 curveto + 226 73.6667 235.667 91.3333 255 104 curveto + 266.333 112 279.667 116 295 116 curveto + closepath + } bind def + /slash { 599 0 113 -81 487 668 setcachedevice + 482 633 moveto + 155 -63 lineto + 149.667 -73.6667 144 -79.6667 138 -81 curveto + 133 -81 lineto + 125 -81 119 -77.3333 115 -70 curveto + 113.667 -67.3333 113 -64.6667 113 -62 curveto + 113 -60.6667 114.667 -55.3333 118 -46 curveto + 445 650 lineto + 450.333 660.667 456 666.333 462 667 curveto + 463.333 667.667 465 668 467 668 curveto + 475 668 481 664.333 485 657 curveto + 486.333 654.333 487 651.667 487 649 curveto + 487 645 485.333 639.667 482 633 curveto + closepath + } bind def + /zero { 599 0 113 -15 487 618 setcachedevice + 487 351 moveto + 487 251 lineto + 487 167.667 468 101.333 430 52 curveto + 396 7.33333 352.667 -15 300 -15 curveto + 246.667 -15 202.667 8 168 54 curveto + 131.333 103.333 113 169 113 251 curveto + 113 351 lineto + 113 434.333 131.667 500.667 169 550 curveto + 203.667 595.333 247.333 618 300 618 curveto + 353.333 618 397.333 594.667 432 548 curveto + 468.667 498.667 487 433 487 351 curveto + closepath + 300 577 moveto + 254 577 217.333 552.667 190 504 curveto + 166 460.667 154 408 154 346 curveto + 154 257 lineto + 154 187 168.667 130 198 86 curveto + 224.667 46 258.667 26 300 26 curveto + 346 26 382.667 50.3333 410 99 curveto + 434 143 446 195.667 446 257 curveto + 446 346 lineto + 446 416 431 473 401 517 curveto + 374.333 557 340.667 577 300 577 curveto + closepath + } bind def + /one { 599 0 113 0 487 612 setcachedevice + 321 612 moveto + 321 41 lineto + 460 41 lineto + 478 41 487 34.3333 487 21 curveto + 487 7 478 0 460 0 curveto + 141 0 lineto + 122.333 0 113 7 113 21 curveto + 113 34.3333 122.333 41 141 41 curveto + 280 41 lineto + 280 557 lineto + 148 515 lineto + 140 513 135.333 512 134 512 curveto + 127.333 512 122 515.667 118 523 curveto + 116 526.333 115 529.333 115 532 curveto + 115 540.667 120 547.333 130 552 curveto + 136 554 lineto + 321 612 lineto + closepath + } bind def + /two { 599 0 84 0 478 618 setcachedevice + 104 470 moveto + 104 492.667 115 517.333 137 544 curveto + 167 580 204 603 248 613 curveto + 262 616.333 276 618 290 618 curveto + 336 618 377 602.333 413 571 curveto + 447 541.667 467 506.333 473 465 curveto + 473.667 459 474 452.667 474 446 curveto + 474 419.333 467.667 395.333 455 374 curveto + 439.667 349.333 404 309.667 348 255 curveto + 330 237 lineto + 244 151.667 175 87.3333 123 44 curveto + 123 41 lineto + 437 41 lineto + 437 77 lineto + 437 95 444 104 458 104 curveto + 471.333 104 478 95 478 77 curveto + 478 0 lineto + 84 0 lineto + 84 60 lineto + 320 282 lineto + 372 332.667 404.333 369 417 391 curveto + 427.667 408.333 433 427 433 447 curveto + 433 481 419.333 511 392 537 curveto + 363.333 563.667 329.333 577 290 577 curveto + 250 577 215.333 564 186 538 curveto + 164.667 519.333 150.667 497.333 144 472 curveto + 140.667 458.667 133.667 452 123 452 curveto + 115 452 109 455.667 105 463 curveto + 104.333 465.667 104 468 104 470 curveto + closepath + } bind def + /three { 599 0 96 -15 499 618 setcachedevice + 125 528 moveto + 125 536 133 547.333 149 562 curveto + 181 592 221 610 269 616 curveto + 279.667 617.333 290.333 618 301 618 curveto + 352.333 618 395 602.333 429 571 curveto + 461 541.667 477 506 477 464 curveto + 477 425.333 461.667 391.667 431 363 curveto + 416.333 349 399 338 379 330 curveto + 378.333 330 376.667 329.333 374 328 curveto + 426.667 306.667 463 275 483 233 curveto + 493.667 212.333 499 190.667 499 168 curveto + 499 121.333 481 80.6667 445 46 curveto + 409 10.6667 364.667 -9.33333 312 -14 curveto + 304.667 -14.6667 297.333 -15 290 -15 curveto + 250.667 -15 208.667 -5.33333 164 14 curveto + 126 30.6667 104 46.6667 98 62 curveto + 96.6667 64 96 66.3333 96 69 curveto + 96 77.6667 100 83.3333 108 86 curveto + 110.667 87.3333 113 88 115 88 curveto + 119.667 88 130 82.6667 146 72 curveto + 178.667 49.3333 211.667 35.3333 245 30 curveto + 259.667 27.3333 275 26 291 26 curveto + 336.333 26 375.667 40 409 68 curveto + 441 97.3333 457.333 130.667 458 168 curveto + 458 205.333 441.667 238 409 266 curveto + 375.667 294.667 335 310 287 312 curveto + 279 312 lineto + 261 312 252 319 252 333 curveto + 252 346.333 261 353 279 353 curveto + 316.333 353 341.333 355 354 359 curveto + 358 360.333 362 362 366 364 curveto + 395.333 376 415.667 395.667 427 423 curveto + 433 435.667 436 449 436 463 curveto + 436 497 421.667 525 393 547 curveto + 367 567 336 577 300 577 curveto + 248.667 577 209 563.667 181 537 curveto + 159 515 lineto + 154.333 511 149.667 509 145 509 curveto + 136.333 509 130 513 126 521 curveto + 125.333 523 125 525.333 125 528 curveto + closepath + } bind def + /four { 599 0 105 0 478 604 setcachedevice + 376 169 moveto + 105 169 lineto + 105 216 lineto + 333 604 lineto + 417 604 lineto + 417 210 lineto + 451 210 lineto + 469 210 478 203 478 189 curveto + 478 175.667 469 169 451 169 curveto + 417 169 lineto + 417 41 lineto + 451 41 lineto + 469 41 478 34.3333 478 21 curveto + 478 7 469 0 451 0 curveto + 300 0 lineto + 282 0 273 7 273 21 curveto + 273 34.3333 282 41 300 41 curveto + 376 41 lineto + 376 169 lineto + closepath + 376 210 moveto + 376 563 lineto + 352 563 lineto + 144 210 lineto + 376 210 lineto + closepath + } bind def + /five { 599 0 96 -15 499 604 setcachedevice + 316 354 moveto + 278 354 241.333 345 206 327 curveto + 187.333 317.667 174.667 313 168 313 curveto + 158.667 313 152.667 318 150 328 curveto + 149.333 330 149 332.333 149 335 curveto + 149 604 lineto + 431 604 lineto + 449.667 604 459 597.333 459 584 curveto + 459 570 449.667 563 431 563 curveto + 190 563 lineto + 190 365 lineto + 236.667 384.333 278.667 394.333 316 395 curveto + 322 395 lineto + 372.667 395 414.667 377 448 341 curveto + 482 304.333 499 257.667 499 201 curveto + 499 138.333 480 86.6667 442 46 curveto + 402 6 353 -14.3333 295 -15 curveto + 242.333 -15 192.333 0.666667 145 32 curveto + 119.667 48 104 62.6667 98 76 curveto + 96.6667 78.6667 96 80.6667 96 82 curveto + 96 90.6667 100 97 108 101 curveto + 110.667 101.667 113.333 102 116 102 curveto + 120.667 102 130 96 144 84 curveto + 172 60.6667 198.333 45 223 37 curveto + 245 29.6667 268.333 26 293 26 curveto + 345 26 386.333 44.3333 417 81 curveto + 444.333 113 458 153.667 458 203 curveto + 458 252.333 442.333 291 411 319 curveto + 385 342.333 353.333 354 316 354 curveto + closepath + } bind def + /six { 599 0 136 -15 510 618 setcachedevice + 488 563 moveto + 484.667 563 479 565 471 569 curveto + 459.667 574.333 444 577 424 577 curveto + 374 577 326.333 558.667 281 522 curveto + 257.667 503.333 237.333 481 220 455 curveto + 192.667 412.333 177.667 360.667 175 300 curveto + 175 285 lineto + 175 281.667 175.667 267.333 177 242 curveto + 217 323.333 272.333 364 343 364 curveto + 386.333 364 424 347.333 456 314 curveto + 488.667 280 506.333 239 509 191 curveto + 509.667 187 510 182.667 510 178 curveto + 510 124.667 493.667 79.3333 461 42 curveto + 429.667 6 390.667 -13 344 -15 curveto + 337 -15 lineto + 282.333 -15 237 9 201 57 curveto + 161 109 139.667 178.333 137 265 curveto + 136.333 270.333 136 276 136 282 curveto + 136 373.333 160.667 450 210 512 curveto + 252.667 566 306.667 599.667 372 613 curveto + 390.667 616.333 409.333 618 428 618 curveto + 458.667 618 481.667 612 497 600 curveto + 503.667 594.667 507 589 507 583 curveto + 507 573 502.667 566.667 494 564 curveto + 492 563.333 490 563 488 563 curveto + closepath + 183 188 moveto + 204.333 104.667 239 53.6667 287 35 curveto + 302.333 29 319.333 26 338 26 curveto + 376 26 407.667 41.3333 433 72 curveto + 457 100.667 469 136 469 178 curveto + 469 218.667 456 253.667 430 283 curveto + 405.333 309.667 376 323 342 323 curveto + 285.333 323 235.333 283.333 192 204 curveto + 192 205.333 189 200 183 188 curveto + closepath + } bind def + /seven { 599 0 105 -1 478 604 setcachedevice + 437 545 moveto + 437 563 lineto + 146 563 lineto + 146 528 lineto + 146 509.333 139.333 500 126 500 curveto + 112 500 105 509.333 105 528 curveto + 105 604 lineto + 478 604 lineto + 478 539 lineto + 315 20 lineto + 311 7.33333 305.667 0.666667 299 -0 curveto + 297.667 -0.666667 296.333 -1 295 -1 curveto + 286.333 -1 280 3 276 11 curveto + 275.333 13.6667 275 16.3333 275 19 curveto + 275 21.6667 275.667 26 277 32 curveto + 437 545 lineto + closepath + } bind def + /eight { 599 0 113 -15 487 618 setcachedevice + 375 313 moveto + 441 283 477.667 239.667 485 183 curveto + 486.333 175.667 487 168.333 487 161 curveto + 487 115 470.167 75 436.5 41 curveto + 402.833 7 361.667 -11.6667 313 -15 curveto + 300 -15 lineto + 250 -15 207 1 171 33 curveto + 136.333 65 117 103.333 113 148 curveto + 113 161 lineto + 113 226.333 149.333 276.667 222 312 curveto + 223.333 312 224.333 312.333 225 313 curveto + 171.667 340.333 139.333 374 128 414 curveto + 124.667 426 123 439 123 453 curveto + 123 495.667 139.167 533 171.5 565 curveto + 203.833 597 242.667 614.667 288 618 curveto + 300 618 lineto + 346.667 618 387 602.667 421 572 curveto + 455 542 473.667 506 477 464 curveto + 477 453 lineto + 477 405.667 456.333 367 415 337 curveto + 403 329 389.667 321 375 313 curveto + closepath + 300 577 moveto + 260 577 226.667 563.667 200 537 curveto + 176 513 164 484.333 164 451 curveto + 164 416.333 178.333 387.333 207 364 curveto + 233 343.333 264 333 300 333 curveto + 340 333 373.667 346 401 372 curveto + 424.333 394 436 420 436 450 curveto + 436 486.667 422 517.667 394 543 curveto + 367.333 565.667 336 577 300 577 curveto + closepath + 300 293 moveto + 256.667 293 220.667 279 192 251 curveto + 166.667 225.667 154 195.667 154 161 curveto + 154 123 168.667 90.6667 198 64 curveto + 226 38.6667 260 26 300 26 curveto + 341.333 26 376.333 39.6667 405 67 curveto + 432.333 93 446 124 446 160 curveto + 446 200 430.667 232.667 400 258 curveto + 372.667 281.333 339.333 293 300 293 curveto + closepath + } bind def + /nine { 599 0 136 -15 510 618 setcachedevice + 158 40 moveto + 161.333 40 167 38 175 34 curveto + 186.333 28.6667 202 26 222 26 curveto + 272 26 319.667 44.3333 365 81 curveto + 388.333 99.6667 408.667 122 426 148 curveto + 453.333 190.667 468.333 242.333 471 303 curveto + 471 318 lineto + 471 321.333 470.333 335.667 469 361 curveto + 428.333 279.667 373 239 303 239 curveto + 259.667 239 222 255.667 190 289 curveto + 157.333 322.333 139.667 363.333 137 412 curveto + 136.333 416 136 420.333 136 425 curveto + 136 478.333 152.333 523.667 185 561 curveto + 216.333 597 255.333 616 302 618 curveto + 309 618 lineto + 363.667 618 409 594 445 546 curveto + 485 494 506.333 424.667 509 338 curveto + 509.667 332.667 510 327 510 321 curveto + 510 229.667 485.333 153 436 91 curveto + 393.333 37 339.333 3.33333 274 -10 curveto + 255.333 -13.3333 236.667 -15 218 -15 curveto + 187.333 -15 164.333 -9 149 3 curveto + 142.333 8.33333 139 14 139 20 curveto + 139 29.3333 143 35.6667 151 39 curveto + 153.667 39.6667 156 40 158 40 curveto + closepath + 463 415 moveto + 441.667 498.333 407 549.333 359 568 curveto + 343.667 574 326.667 577 308 577 curveto + 270 577 238.333 561.667 213 531 curveto + 189 502.333 177 467 177 425 curveto + 177 384.333 190 349.333 216 320 curveto + 240.667 293.333 270 280 304 280 curveto + 360.667 280 410.667 319.667 454 399 curveto + 454 397.667 457 403 463 415 curveto + closepath + } bind def + /colon { 599 0 226 -15 374 417 setcachedevice + 295 116 moveto + 305 116 lineto + 329.667 116 348.667 106.667 362 88 curveto + 370 77.3333 374 65 374 51 curveto + 374 27 364.333 8.66667 345 -4 curveto + 333 -11.3333 319.667 -15 305 -15 curveto + 295 -15 lineto + 271 -15 252 -5.66667 238 13 curveto + 230 23.6667 226 36.3333 226 51 curveto + 226 73.6667 235.667 91.3333 255 104 curveto + 266.333 112 279.667 116 295 116 curveto + closepath + 295 417 moveto + 305 417 lineto + 329.667 417 348.667 407.667 362 389 curveto + 370 377.667 374 365 374 351 curveto + 374 327.667 364.333 309.667 345 297 curveto + 333.667 289 320.333 285 305 285 curveto + 295 285 lineto + 270.333 285 251.333 294.333 238 313 curveto + 230 324.333 226 337 226 351 curveto + 226 374.333 235.667 392.333 255 405 curveto + 266.333 413 279.667 417 295 417 curveto + closepath + } bind def + /semicolon { 599 0 139 -145 350 417 setcachedevice + 211 145 moveto + 344 145 lineto + 199 -120 lineto + 191.667 -134.667 183.333 -143 174 -145 curveto + 168 -145 lineto + 156 -145 147.333 -139.667 142 -129 curveto + 140 -125 139 -120.667 139 -116 curveto + 139 -114 139.667 -110.333 141 -105 curveto + 211 145 lineto + closepath + 271 417 moveto + 281 417 lineto + 305 417 324 407.667 338 389 curveto + 346 378.333 350 365.667 350 351 curveto + 350 328.333 340.667 310.333 322 297 curveto + 310 289 296.333 285 281 285 curveto + 271 285 lineto + 246.333 285 227.333 294.333 214 313 curveto + 206 324.333 202 337 202 351 curveto + 202 374.333 211.667 392.333 231 405 curveto + 243 413 256.333 417 271 417 curveto + closepath + } bind def + /less { 599 0 72 44 522 518 setcachedevice + 522 67 moveto + 522 59.6667 518.667 53.3333 512 48 curveto + 508.667 45.3333 505.333 44 502 44 curveto + 499.333 44 495 45.6667 489 49 curveto + 72 281 lineto + 490 513 lineto + 496 516.333 500 518 502 518 curveto + 509.333 518 515.333 513.667 520 505 curveto + 521.333 501.667 522 498.667 522 496 curveto + 522 488.667 517.667 482.667 509 478 curveto + 154 281 lineto + 509 84 lineto + 517.667 79.3333 522 73.6667 522 67 curveto + closepath + } bind def + /equal { 599 0 51 190 549 375 setcachedevice + 522 334 moveto + 78 334 lineto + 60 334 51 341 51 355 curveto + 51 368.333 60 375 78 375 curveto + 522 375 lineto + 540 375 549 368.333 549 355 curveto + 549 341 540 334 522 334 curveto + closepath + 522 190 moveto + 78 190 lineto + 60 190 51 197 51 211 curveto + 51 224.333 60 231 78 231 curveto + 522 231 lineto + 540 231 549 224.333 549 211 curveto + 549 197 540 190 522 190 curveto + closepath + } bind def + /greater { 599 0 78 44 528 518 setcachedevice + 78 496 moveto + 78 502 80.6667 507.667 86 513 curveto + 90 516.333 94 518 98 518 curveto + 101.333 518 105.667 516.333 111 513 curveto + 528 281 lineto + 110 49 lineto + 104.667 45.6667 100.667 44 98 44 curveto + 90 44 84 48.6667 80 58 curveto + 78.6667 60.6667 78 63.6667 78 67 curveto + 78 73.6667 82.3333 79.3333 91 84 curveto + 446 281 lineto + 91 478 lineto + 82.3333 482.667 78 488.667 78 496 curveto + closepath + } bind def + /question { 599 0 134 -15 487 577 setcachedevice + 134 529 moveto + 137.333 529.667 154.333 537 185 551 curveto + 226.333 568.333 267.667 577 309 577 curveto + 367.667 577 413.667 560 447 526 curveto + 473.667 498 487 463.667 487 423 curveto + 487 385 474 352.667 448 326 curveto + 424 302 382 275.667 322 247 curveto + 322 206 lineto + 322 188 315.333 179 302 179 curveto + 288 179 281 188 281 206 curveto + 281 274 lineto + 359.667 307.333 409.667 340.333 431 373 curveto + 441 388.333 446 405 446 423 curveto + 446 459 430.667 487.667 400 509 curveto + 374 527 342 536 304 536 curveto + 269.333 536 235.667 529 203 515 curveto + 194.333 511.667 185 507.333 175 502 curveto + 175 461 lineto + 175 443 168.333 434 155 434 curveto + 141 434 134 443 134 461 curveto + 134 529 lineto + closepath + 287 85 moveto + 314 85 lineto + 338.667 85 355.667 76.3333 365 59 curveto + 369 51.6667 371 43.6667 371 35 curveto + 371 15 362 0.333333 344 -9 curveto + 335.333 -13 325.333 -15 314 -15 curveto + 287 -15 lineto + 262.333 -15 245 -6 235 12 curveto + 231.667 18.6667 230 26.3333 230 35 curveto + 230 55.6667 239.333 70.3333 258 79 curveto + 266.667 83 276.333 85 287 85 curveto + closepath + } bind def + /at { 599 0 105 -62 478 624 setcachedevice + 299 -62 moveto + 243.667 -62 198.333 -38.6667 163 8 curveto + 127 54 107.667 113 105 185 curveto + 105 198 lineto + 105 361 lineto + 105 437 123.333 499.667 160 549 curveto + 193.333 594.333 235.333 619.333 286 624 curveto + 300 624 lineto + 347.333 624 386 607.667 416 575 curveto + 444.667 545 459 507.667 459 463 curveto + 459 186 lineto + 471.667 184 478 177.333 478 166 curveto + 478 152 469 145 451 145 curveto + 418 145 lineto + 418 150 lineto + 398 148 384.667 147 378 147 curveto + 335.333 147 301 161 275 189 curveto + 253 212.333 242 240 242 272 curveto + 242 314.667 259 349.667 293 377 curveto + 325.667 403 366.667 416 416 416 curveto + 418 416 lineto + 418 463 lineto + 418 503 404 534.333 376 557 curveto + 355.333 574.333 330.333 583 301 583 curveto + 256.333 583 219.333 562.667 190 522 curveto + 160.667 479.333 146 424.667 146 358 curveto + 146 198 lineto + 146 132.667 161.333 79.3333 192 38 curveto + 221.333 -1.33333 259 -21 305 -21 curveto + 348.333 -21 382.333 -11.6667 407 7 curveto + 417 15 423.333 19.3333 426 20 curveto + 429 20 lineto + 437.667 20 444 16 448 8 curveto + 448.667 6 449 3.66667 449 1 curveto + 449 -13 436 -26.3333 410 -39 curveto + 376.667 -54.3333 339.667 -62 299 -62 curveto + closepath + 418 192 moveto + 418 376 lineto + 372 376 336.333 363.333 311 338 curveto + 292.333 320 283 298.333 283 273 curveto + 283 243 295.667 220 321 204 curveto + 337.667 193.333 357.667 188 381 188 curveto + 395 188 407.333 189.333 418 192 curveto + closepath + } bind def + /A { 599 0 9 0 591 563 setcachedevice + 428 188 moveto + 162 188 lineto + 108 41 lineto + 187 41 lineto + 205 41 214 34.3333 214 21 curveto + 214 7 205 0 187 0 curveto + 36 0 lineto + 18 0 9 7 9 21 curveto + 9 34.3333 18 41 36 41 curveto + 67 41 lineto + 246 522 lineto + 126 522 lineto + 108 522 99 529 99 543 curveto + 99 556.333 108 563 126 563 curveto + 330 563 lineto + 527 41 lineto + 564 41 lineto + 582 41 591 34.3333 591 21 curveto + 591 7 582 0 564 0 curveto + 408 0 lineto + 390 0 381 7 381 21 curveto + 381 34.3333 390 41 408 41 curveto + 484 41 lineto + 428 188 lineto + closepath + 413 229 moveto + 301 522 lineto + 286 522 lineto + 178 229 lineto + 413 229 lineto + closepath + } bind def + /B { 599 0 43 0 541 563 setcachedevice + 124 41 moveto + 124 522 lineto + 70 522 lineto + 52 522 43 529 43 543 curveto + 43 556.333 52 563 70 563 curveto + 328 563 lineto + 378.667 563 420.667 548 454 518 curveto + 484 490.667 499 457.333 499 418 curveto + 499 376 479 341 439 313 curveto + 431.667 308.333 423.333 303.333 414 298 curveto + 498.667 268 541 219.667 541 153 curveto + 541 111.667 525.333 76 494 46 curveto + 460.667 16 421.333 0.666667 376 0 curveto + 70 0 lineto + 52 0 43 7 43 21 curveto + 43 34.3333 52 41 70 41 curveto + 124 41 lineto + closepath + 165 313 moveto + 312 313 lineto + 362 313 400.667 326 428 352 curveto + 448 370.667 458 393 458 419 curveto + 458 449.667 444.333 475.333 417 496 curveto + 392.333 513.333 363 522 329 522 curveto + 165 522 lineto + 165 313 lineto + closepath + 500 153 moveto + 500 189 484.667 217.667 454 239 curveto + 421.333 261 374.667 272 314 272 curveto + 165 272 lineto + 165 41 lineto + 373 41 lineto + 411.667 41 443.667 53.6667 469 79 curveto + 489.667 99.6667 500 124.333 500 153 curveto + closepath + } bind def + /C { 599 0 63 -16 534 576 setcachedevice + 63 325 moveto + 63 354.333 70.3333 387.333 85 424 curveto + 112.333 491.333 155.333 536.667 214 560 curveto + 241.333 570.667 271.667 576 305 576 curveto + 372.333 576 430 553 478 507 curveto + 478 536 lineto + 478 554 485 563 499 563 curveto + 512.333 563 519 554 519 536 curveto + 519 424 lineto + 519 406 512 397 498 397 curveto + 485.333 397 478.667 405 478 421 curveto + 476 450.333 459 476.333 427 499 curveto + 392.333 523 351.667 535 305 535 curveto + 254.333 535 209.667 516.667 171 480 curveto + 133.667 444 111.667 399.333 105 346 curveto + 104.333 337.333 104 328.333 104 319 curveto + 104 248 lineto + 104 194 122 146 158 104 curveto + 192 62.6667 234 37.3333 284 28 curveto + 296.667 26 309.333 25 322 25 curveto + 372 25 416 40.6667 454 72 curveto + 468 84 482 98.3333 496 115 curveto + 502 121.667 508 125 514 125 curveto + 524.667 125 531.333 120.333 534 111 curveto + 534 106 lineto + 534 97.3333 525.333 84 508 66 curveto + 474.667 30.6667 434.667 6.33333 388 -7 curveto + 366 -13 344 -16 322 -16 curveto + 264.667 -16 212 3.33333 164 42 curveto + 118.667 78.6667 88.3333 123.667 73 177 curveto + 66.3333 198.333 63 220 63 242 curveto + 63 325 lineto + closepath + } bind def + /D { 599 0 43 0 520 563 setcachedevice + 104 41 moveto + 104 522 lineto + 70 522 lineto + 52 522 43 529 43 543 curveto + 43 556.333 52 563 70 563 curveto + 290 563 lineto + 348 563 398.333 542.333 441 501 curveto + 483 461 508.333 410.667 517 350 curveto + 519 336.667 520 323.333 520 310 curveto + 520 254 lineto + 520 188.667 500.667 132 462 84 curveto + 426 39.3333 380.667 12.3333 326 3 curveto + 314.667 1 302.667 0 290 0 curveto + 70 0 lineto + 52 0 43 7 43 21 curveto + 43 34.3333 52 41 70 41 curveto + 104 41 lineto + closepath + 479 318 moveto + 479 342 472.333 369.667 459 401 curveto + 434.333 458.333 397.333 495.333 348 512 curveto + 329.333 518.667 309.333 522 288 522 curveto + 145 522 lineto + 145 41 lineto + 295 41 lineto + 337.667 41 377 58 413 92 curveto + 447 126 468 166 476 212 curveto + 478 223.333 479 234.333 479 245 curveto + 479 318 lineto + closepath + } bind def + /E { 599 0 43 0 520 563 setcachedevice + 165 272 moveto + 165 41 lineto + 479 41 lineto + 479 160 lineto + 479 178 486 187 500 187 curveto + 513.333 187 520 178 520 160 curveto + 520 0 lineto + 70 0 lineto + 52 0 43 7 43 21 curveto + 43 34.3333 52 41 70 41 curveto + 124 41 lineto + 124 522 lineto + 70 522 lineto + 52 522 43 529 43 543 curveto + 43 556.333 52 563 70 563 curveto + 499 563 lineto + 499 424 lineto + 499 406 492 397 478 397 curveto + 464.667 397 458 406 458 424 curveto + 458 522 lineto + 165 522 lineto + 165 313 lineto + 310 313 lineto + 310 358 lineto + 310 376 317 385 331 385 curveto + 344.333 385 351 376 351 358 curveto + 351 227 lineto + 351 209 344.333 200 331 200 curveto + 317 200 310 209 310 227 curveto + 310 272 lineto + 165 272 lineto + closepath + } bind def + /F { 599 0 43 0 520 563 setcachedevice + 165 272 moveto + 165 41 lineto + 303 41 lineto + 321.667 41 331 34.3333 331 21 curveto + 331 7 321.667 0 303 0 curveto + 70 0 lineto + 52 0 43 7 43 21 curveto + 43 34.3333 52 41 70 41 curveto + 124 41 lineto + 124 522 lineto + 70 522 lineto + 52 522 43 529 43 543 curveto + 43 556.333 52 563 70 563 curveto + 520 563 lineto + 520 424 lineto + 520 406 513 397 499 397 curveto + 485.667 397 479 406 479 424 curveto + 479 522 lineto + 165 522 lineto + 165 313 lineto + 310 313 lineto + 310 358 lineto + 310 376 316.667 385 330 385 curveto + 344 385 351 376 351 358 curveto + 351 227 lineto + 351 209 344 200 330 200 curveto + 316.667 200 310 209 310 227 curveto + 310 272 lineto + 165 272 lineto + closepath + } bind def + /G { 599 0 63 -16 562 576 setcachedevice + 315 535 moveto + 235.667 535 177 502 139 436 curveto + 119 400.667 107.333 364 104 326 curveto + 104 317 lineto + 104 244 lineto + 104 168.667 128.667 111.667 178 73 curveto + 218.667 41 271.333 25 336 25 curveto + 375.333 25 412.333 31.6667 447 45 curveto + 479 59 lineto + 479 209 lineto + 340 209 lineto + 322 209 313 216 313 230 curveto + 313 243.333 322 250 340 250 curveto + 534 250 lineto + 552.667 250 562 243.333 562 230 curveto + 562 216 552.667 209 534 209 curveto + 520 209 lineto + 520 36 lineto + 460 1.33333 397.667 -16 333 -16 curveto + 249.667 -16 183.333 8.33333 134 57 curveto + 86.6667 103.667 63 166 63 244 curveto + 63 318 lineto + 63 380 81.3333 434.667 118 482 curveto + 156 530.667 205.333 560.667 266 572 curveto + 281.333 574.667 297 576 313 576 curveto + 379 576 434.333 558 479 522 curveto + 479 536 lineto + 479 554 486 563 500 563 curveto + 512 563 518.667 556.667 520 544 curveto + 520 536 lineto + 520 445 lineto + 520 427 513.333 418 500 418 curveto + 488 418 481.333 426.333 480 443 curveto + 478 468.333 461 490 429 508 curveto + 397 526 359 535 315 535 curveto + closepath + } bind def + /H { 599 0 53 0 551 563 setcachedevice + 437 272 moveto + 167 272 lineto + 167 41 lineto + 221 41 lineto + 239 41 248 34.3333 248 21 curveto + 248 7 239 0 221 0 curveto + 81 0 lineto + 62.3333 0 53 7 53 21 curveto + 53 34.3333 62.3333 41 81 41 curveto + 126 41 lineto + 126 522 lineto + 101 522 lineto + 83 522 74 529 74 543 curveto + 74 556.333 83 563 101 563 curveto + 221 563 lineto + 239 563 248 556.333 248 543 curveto + 248 529 239 522 221 522 curveto + 167 522 lineto + 167 313 lineto + 437 313 lineto + 437 522 lineto + 383 522 lineto + 365 522 356 529 356 543 curveto + 356 556.333 365 563 383 563 curveto + 503 563 lineto + 521 563 530 556.333 530 543 curveto + 530 529 521 522 503 522 curveto + 478 522 lineto + 478 41 lineto + 524 41 lineto + 542 41 551 34.3333 551 21 curveto + 551 7 542 0 524 0 curveto + 383 0 lineto + 365 0 356 7 356 21 curveto + 356 34.3333 365 41 383 41 curveto + 437 41 lineto + 437 272 lineto + closepath + } bind def + /I { 599 0 113 0 487 563 setcachedevice + 320 522 moveto + 320 41 lineto + 459 41 lineto + 477.667 41 487 34.3333 487 21 curveto + 487 7 477.667 0 459 0 curveto + 140 0 lineto + 122 0 113 7 113 21 curveto + 113 34.3333 122 41 140 41 curveto + 279 41 lineto + 279 522 lineto + 140 522 lineto + 122 522 113 529 113 543 curveto + 113 556.333 122 563 140 563 curveto + 459 563 lineto + 477.667 563 487 556.333 487 543 curveto + 487 529 477.667 522 459 522 curveto + 320 522 lineto + closepath + } bind def + /J { 599 0 84 -16 583 563 setcachedevice + 460 522 moveto + 460 165 lineto + 460 118.333 443.333 77.3333 410 42 curveto + 376.667 8 336 -11.3333 288 -16 curveto + 272 -16 lineto + 228 -16 185 -1.66667 143 27 curveto + 125 39 105.333 54.6667 84 74 curveto + 84 223 lineto + 84 241 91 250 105 250 curveto + 118.333 250 125 241 125 223 curveto + 125 93 lineto + 175 47.6667 224.333 25 273 25 curveto + 315 25 350.333 39.3333 379 68 curveto + 405.667 94.6667 419 127 419 165 curveto + 419 522 lineto + 260 522 lineto + 242 522 233 529 233 543 curveto + 233 556.333 242 563 260 563 curveto + 556 563 lineto + 574 563 583 556.333 583 543 curveto + 583 529 574 522 556 522 curveto + 460 522 lineto + closepath + } bind def + /K { 599 0 43 0 572 563 setcachedevice + 165 221 moveto + 165 41 lineto + 240 41 lineto + 258 41 267 34.3333 267 21 curveto + 267 7 258 0 240 0 curveto + 70 0 lineto + 52 0 43 7 43 21 curveto + 43 34.3333 52 41 70 41 curveto + 124 41 lineto + 124 522 lineto + 70 522 lineto + 52 522 43 529 43 543 curveto + 43 556.333 52 563 70 563 curveto + 240 563 lineto + 258 563 267 556.333 267 543 curveto + 267 529 258 522 240 522 curveto + 165 522 lineto + 165 273 lineto + 445 522 lineto + 400 522 lineto + 381.333 522 372 529 372 543 curveto + 372 556.333 381.333 563 400 563 curveto + 518 563 lineto + 536.667 563 546 556.333 546 543 curveto + 546 529 536.667 522 518 522 curveto + 502 522 lineto + 280 324 lineto + 321.333 306.667 354 284.667 378 258 curveto + 405.333 226.667 434.667 173 466 97 curveto + 473.333 80.3333 481 61.6667 489 41 curveto + 545 41 lineto + 563 41 572 34.3333 572 21 curveto + 572 7 563 0 545 0 curveto + 458 0 lineto + 420.667 102.667 387.667 173.667 359 213 curveto + 333.667 247.667 301.667 272.667 263 288 curveto + 257.667 290 252 292 246 294 curveto + 165 221 lineto + closepath + } bind def + /L { 599 0 63 0 541 563 setcachedevice + 227 522 moveto + 227 41 lineto + 500 41 lineto + 500 201 lineto + 500 219 507 228 521 228 curveto + 534.333 228 541 219 541 201 curveto + 541 0 lineto + 90 0 lineto + 72 0 63 7 63 21 curveto + 63 34.3333 72 41 90 41 curveto + 186 41 lineto + 186 522 lineto + 90 522 lineto + 72 522 63 529 63 543 curveto + 63 556.333 72 563 90 563 curveto + 323 563 lineto + 341 563 350 556.333 350 543 curveto + 350 529 341 522 323 522 curveto + 227 522 lineto + closepath + } bind def + /M { 599 0 11 0 593 563 setcachedevice + 326 169 moveto + 280 169 lineto + 121 522 lineto + 113 522 lineto + 113 41 lineto + 187 41 lineto + 205.667 41 215 34.3333 215 21 curveto + 215 7 205.667 0 187 0 curveto + 38 0 lineto + 20 0 11 7 11 21 curveto + 11 34.3333 20 41 38 41 curveto + 72 41 lineto + 72 522 lineto + 47 522 lineto + 29 522 20 529 20 543 curveto + 20 556.333 29 563 47 563 curveto + 146 563 lineto + 303 215 lineto + 457 563 lineto + 557 563 lineto + 575 563 584 556.333 584 543 curveto + 584 529 575 522 557 522 curveto + 532 522 lineto + 532 41 lineto + 566 41 lineto + 584 41 593 34.3333 593 21 curveto + 593 7 584 0 566 0 curveto + 417 0 lineto + 399 0 390 7 390 21 curveto + 390 34.3333 399 41 417 41 curveto + 491 41 lineto + 491 522 lineto + 483 522 lineto + 326 169 lineto + closepath + } bind def + /N { 599 0 22 0 562 563 setcachedevice + 501 0 moveto + 449 0 lineto + 144 504 lineto + 144 41 lineto + 219 41 lineto + 237 41 246 34.3333 246 21 curveto + 246 7 237 0 219 0 curveto + 69 0 lineto + 51 0 42 7 42 21 curveto + 42 34.3333 51 41 69 41 curveto + 103 41 lineto + 103 522 lineto + 49 522 lineto + 31 522 22 529 22 543 curveto + 22 556.333 31 563 49 563 curveto + 155 563 lineto + 460 59 lineto + 460 522 lineto + 386 522 lineto + 367.333 522 358 529 358 543 curveto + 358 556.333 367.333 563 386 563 curveto + 535 563 lineto + 553 563 562 556.333 562 543 curveto + 562 529 553 522 535 522 curveto + 501 522 lineto + 501 0 lineto + closepath + } bind def + /O { 599 0 51 -16 549 576 setcachedevice + 300 576 moveto + 362 576 415.667 553.333 461 508 curveto + 506.333 462.667 534.333 404.333 545 333 curveto + 547.667 314.333 549 295.333 549 276 curveto + 549 204.667 529.333 141.667 490 87 curveto + 454 37.6667 409 5.66667 355 -9 curveto + 337 -13.6667 318.667 -16 300 -16 curveto + 240 -16 187.333 6 142 50 curveto + 96.6667 94 68 150 56 218 curveto + 52.6667 238 51 258.667 51 280 curveto + 51 354 71 418.667 111 474 curveto + 147 524 192.333 556 247 570 curveto + 264.333 574 282 576 300 576 curveto + closepath + 300 535 moveto + 249.333 535 204.667 515 166 475 curveto + 126.667 434.333 103 383.333 95 322 curveto + 93 308 92 294 92 280 curveto + 92 215.333 109.667 158.667 145 110 curveto + 177.667 66 217.333 39 264 29 curveto + 276 26.3333 288 25 300 25 curveto + 349.333 25 393.5 44.8333 432.5 84.5 curveto + 471.5 124.167 495.333 173.333 504 232 curveto + 506.667 246.667 508 261.667 508 277 curveto + 508 344.333 490 402.667 454 452 curveto + 420.667 497.333 379.333 524.333 330 533 curveto + 320 534.333 310 535 300 535 curveto + closepath + } bind def + /P { 599 0 43 0 499 563 setcachedevice + 165 231 moveto + 165 41 lineto + 303 41 lineto + 321.667 41 331 34.3333 331 21 curveto + 331 7 321.667 0 303 0 curveto + 70 0 lineto + 52 0 43 7 43 21 curveto + 43 34.3333 52 41 70 41 curveto + 124 41 lineto + 124 522 lineto + 70 522 lineto + 52 522 43 529 43 543 curveto + 43 556.333 52 563 70 563 curveto + 310 563 lineto + 363.333 563 408 547 444 515 curveto + 480 481.667 498.333 442.667 499 398 curveto + 499 354 481.333 316.333 446 285 curveto + 409.333 251.667 363 233.667 307 231 curveto + 296 231 lineto + 165 231 lineto + closepath + 165 272 moveto + 299 272 lineto + 344.333 272 383 285.333 415 312 curveto + 443.667 336 458 364.667 458 398 curveto + 458 432 443.667 461.333 415 486 curveto + 387 510 353.333 522 314 522 curveto + 165 522 lineto + 165 272 lineto + closepath + } bind def + /Q { 599 0 51 -115 549 576 setcachedevice + 318 -89 moveto + 283.333 -89 245 -94.6667 203 -106 curveto + 186.333 -111.333 174.667 -114 168 -114 curveto + 158.667 -114 152.333 -109.667 149 -101 curveto + 148.333 -98.3333 148 -95.6667 148 -93 curveto + 148 -86.3333 151.667 -80.3333 159 -75 curveto + 249 -10 lineto + 195.667 2 150.667 32.6667 114 82 curveto + 75.3333 134.667 54.3333 195.667 51 265 curveto + 51 280 lineto + 51 354 71 418.667 111 474 curveto + 147 524 192.333 556 247 570 curveto + 264.333 574 282 576 300 576 curveto + 360 576 412.667 554 458 510 curveto + 503.333 466 531.667 409.667 543 341 curveto + 547 321 549 300.667 549 280 curveto + 549 204.667 528.667 139.333 488 84 curveto + 450.667 33.3333 403.667 1.66667 347 -11 curveto + 333.667 -14.3333 319.667 -16 305 -16 curveto + 251 -56 lineto + 277 -50.6667 299.333 -48 318 -48 curveto + 347.333 -48 375.333 -53.3333 402 -64 curveto + 420 -70.6667 434.333 -74 445 -74 curveto + 462.333 -74 482 -67 504 -53 curveto + 515.333 -46.3333 522.667 -43 526 -43 curveto + 536 -43 542.333 -47.6667 545 -57 curveto + 545.667 -59 546 -61.3333 546 -64 curveto + 546 -73.3333 535.333 -83.6667 514 -95 curveto + 488.667 -108.333 464.667 -115 442 -115 curveto + 428 -115 410.333 -111 389 -103 curveto + 364.333 -93.6667 340.667 -89 318 -89 curveto + closepath + 300 535 moveto + 249.333 535 204.667 515 166 475 curveto + 126.667 434.333 103 383.333 95 322 curveto + 93 308 92 294 92 280 curveto + 92 215.333 109.667 158.667 145 110 curveto + 177.667 66 217.333 39 264 29 curveto + 276 26.3333 288 25 300 25 curveto + 349.333 25 393.5 44.8333 432.5 84.5 curveto + 471.5 124.167 495.333 173.333 504 232 curveto + 506.667 246.667 508 261.667 508 277 curveto + 508 344.333 490 402.667 454 452 curveto + 420.667 497.333 379.333 524.333 330 533 curveto + 320 534.333 310 535 300 535 curveto + closepath + } bind def + /R { 599 0 43 0 589 563 setcachedevice + 165 251 moveto + 165 41 lineto + 240 41 lineto + 258 41 267 34.3333 267 21 curveto + 267 7 258 0 240 0 curveto + 70 0 lineto + 52 0 43 7 43 21 curveto + 43 34.3333 52 41 70 41 curveto + 124 41 lineto + 124 522 lineto + 70 522 lineto + 52 522 43 529 43 543 curveto + 43 556.333 52 563 70 563 curveto + 318 563 lineto + 365.333 563 406.667 548.333 442 519 curveto + 475.333 491 494 457.333 498 418 curveto + 498 407 lineto + 498 342.333 451.667 294 359 262 curveto + 390.333 240.667 416.667 216 438 188 curveto + 459.333 160.667 490.333 111.667 531 41 curveto + 562 41 lineto + 580 41 589 34.3333 589 21 curveto + 589 7 580 0 562 0 curveto + 505 0 lineto + 456.333 90 416.333 152 385 186 curveto + 360.333 214 331 235.667 297 251 curveto + 165 251 lineto + closepath + 165 292 moveto + 279 292 lineto + 331 292 375 304.667 411 330 curveto + 441.667 352 457 378 457 408 curveto + 457 437.333 443.333 463.333 416 486 curveto + 387.333 510 354.667 522 318 522 curveto + 165 522 lineto + 165 292 lineto + closepath + } bind def + /S { 599 0 92 -16 508 576 setcachedevice + 464 153 moveto + 464 195 443.667 225.333 403 244 curveto + 384.333 253.333 349.333 263 298 273 curveto + 245.333 283.667 208 294.333 186 305 curveto + 139.333 328.333 115.667 367 115 421 curveto + 115 464.333 132.333 501 167 531 curveto + 201.667 561 245.667 576 299 576 curveto + 351.667 576 397 559.333 435 526 curveto + 438.333 523.333 441.667 520.333 445 517 curveto + 445 536 lineto + 445 554 452 563 466 563 curveto + 479.333 563 486 554 486 536 curveto + 486 433 lineto + 486 415 479.333 406 466 406 curveto + 452.667 406 445.667 414 445 430 curveto + 443 462.667 426.667 489 396 509 curveto + 369.333 526.333 338 535 302 535 curveto + 256 535 219.333 521.667 192 495 curveto + 170 474.333 159 449.333 159 420 curveto + 159 381.333 178.333 353.333 217 336 curveto + 235.667 327.333 270.333 317.667 321 307 curveto + 374.333 296.333 412.667 284.667 436 272 curveto + 484 247.333 508 207 508 151 curveto + 508 103 489 63.3333 451 32 curveto + 412.333 0 362.667 -16 302 -16 curveto + 232.667 -16 177 7 135 53 curveto + 134.333 54.3333 133.667 55.3333 133 56 curveto + 133 27 lineto + 133 9 126 0 112 0 curveto + 98.6667 0 92 9 92 27 curveto + 92 139 lineto + 92 157 99 166 113 166 curveto + 125 166 131.667 158 133 142 curveto + 134.333 108.667 151.667 81 185 59 curveto + 217 36.3333 255.667 25 301 25 curveto + 351.667 25 392.667 39 424 67 curveto + 450.667 91 464 119.667 464 153 curveto + closepath + } bind def + /T { 599 0 72 0 528 563 setcachedevice + 321 41 moveto + 426 41 lineto + 444 41 453 34.3333 453 21 curveto + 453 7 444 0 426 0 curveto + 175 0 lineto + 157 0 148 7 148 21 curveto + 148 34.3333 157 41 175 41 curveto + 280 41 lineto + 280 522 lineto + 113 522 lineto + 113 449 lineto + 113 431 106 422 92 422 curveto + 78.6667 422 72 431 72 449 curveto + 72 563 lineto + 528 563 lineto + 528 449 lineto + 526 431.667 519.333 422.667 508 422 curveto + 498.667 422 492 427.333 488 438 curveto + 487.333 441.333 487 445 487 449 curveto + 487 522 lineto + 321 522 lineto + 321 41 lineto + closepath + } bind def + /U { 599 0 40 -16 560 563 setcachedevice + 499 522 moveto + 499 185 lineto + 499 130.333 481 83.6667 445 45 curveto + 409.667 7.66667 365.667 -12.6667 313 -16 curveto + 300 -16 lineto + 245.333 -16 199.333 2 162 38 curveto + 124.667 74 104.667 119 102 173 curveto + 101.333 177 101 181 101 185 curveto + 101 522 lineto + 67 522 lineto + 49 522 40 529 40 543 curveto + 40 556.333 49 563 67 563 curveto + 216 563 lineto + 234 563 243 556.333 243 543 curveto + 243 529 234 522 216 522 curveto + 142 522 lineto + 142 185 lineto + 142 139.667 157.333 101.333 188 70 curveto + 218.667 40 256 25 300 25 curveto + 344.667 25 382.333 40.6667 413 72 curveto + 443 102.667 458 140.333 458 185 curveto + 458 522 lineto + 384 522 lineto + 366 522 357 529 357 543 curveto + 359.667 555.667 368.667 562.333 384 563 curveto + 533 563 lineto + 550.333 563 559.333 556.333 560 543 curveto + 560 529 551 522 533 522 curveto + 499 522 lineto + closepath + } bind def + /V { 599 0 9 0 591 563 setcachedevice + 267 0 moveto + 67 522 lineto + 36 522 lineto + 18 522 9 529 9 543 curveto + 9 556.333 18 563 36 563 curveto + 187 563 lineto + 205 563 214 556.333 214 543 curveto + 214 529 205 522 187 522 curveto + 110 522 lineto + 296 41 lineto + 299 41 lineto + 492 522 lineto + 414 522 lineto + 396 522 387 529 387 543 curveto + 387 556.333 396 563 414 563 curveto + 564 563 lineto + 582 563 591 556.333 591 543 curveto + 591 529 582 522 564 522 curveto + 533 522 lineto + 324 0 lineto + 267 0 lineto + closepath + } bind def + /W { 599 0 20 0 580 563 setcachedevice + 122 0 moveto + 62 522 lineto + 47 522 lineto + 29 522 20 529 20 543 curveto + 20 556.333 29 563 47 563 curveto + 196 563 lineto + 214.667 563 224 556.333 224 543 curveto + 224 529 214.667 522 196 522 curveto + 103 522 lineto + 159 46 lineto + 271 438 lineto + 333 438 lineto + 442 46 lineto + 499 522 lineto + 403 522 lineto + 385 522 376 529 376 543 curveto + 376 556.333 385 563 403 563 curveto + 553 563 lineto + 571 563 580 556.333 580 543 curveto + 580 529 571 522 553 522 curveto + 538 522 lineto + 476 0 lineto + 412 0 lineto + 300 400 lineto + 185 0 lineto + 122 0 lineto + closepath + } bind def + /X { 599 0 40 0 560 563 setcachedevice + 325 288 moveto + 516 41 lineto + 533 41 lineto + 551 41 560 34.3333 560 21 curveto + 560 7 551 0 533 0 curveto + 401 0 lineto + 383 0 374 7 374 21 curveto + 374 34.3333 383 41 401 41 curveto + 463 41 lineto + 298 255 lineto + 134 41 lineto + 198 41 lineto + 216 41 225 34.3333 225 21 curveto + 225 7 216 0 198 0 curveto + 67 0 lineto + 49 0 40 7 40 21 curveto + 40 34.3333 49 41 67 41 curveto + 84 41 lineto + 272 288 lineto + 93 522 lineto + 78 522 lineto + 60 522 51 529 51 543 curveto + 51 556.333 60 563 78 563 curveto + 188 563 lineto + 206 563 215 556.333 215 543 curveto + 215 529 206 522 188 522 curveto + 145 522 lineto + 300 321 lineto + 453 522 lineto + 408 522 lineto + 390 522 381 529 381 543 curveto + 381 556.333 390 563 408 563 curveto + 519 563 lineto + 537 563 546 556.333 546 543 curveto + 546 529 537 522 519 522 curveto + 504 522 lineto + 325 288 lineto + closepath + } bind def + /Y { 599 0 51 0 549 563 setcachedevice + 322 254 moveto + 322 41 lineto + 427 41 lineto + 445 41 454 34.3333 454 21 curveto + 454 7 445 0 427 0 curveto + 176 0 lineto + 158 0 149 7 149 21 curveto + 149 34.3333 158 41 176 41 curveto + 281 41 lineto + 281 254 lineto + 102 522 lineto + 78 522 lineto + 60 522 51 529 51 543 curveto + 51 556.333 60 563 78 563 curveto + 189 563 lineto + 207 563 216 556.333 216 543 curveto + 216 529 207 522 189 522 curveto + 151 522 lineto + 303 295 lineto + 452 522 lineto + 412 522 lineto + 393.333 522 384 529 384 543 curveto + 384 556.333 393.333 563 412 563 curveto + 522 563 lineto + 538 561 547 554.333 549 543 curveto + 549 531.667 542.333 524.667 529 522 curveto + 522 522 lineto + 498 522 lineto + 322 254 lineto + closepath + } bind def + /Z { 599 0 103 0 497 563 setcachedevice + 497 0 moveto + 103 0 lineto + 103 59 lineto + 431 519 lineto + 431 522 lineto + 162 522 lineto + 162 404 lineto + 162 385.333 155.333 376 142 376 curveto + 128 376 121 385.333 121 404 curveto + 121 563 lineto + 470 563 lineto + 470 505 lineto + 142 45 lineto + 142 41 lineto + 456 41 lineto + 456 182 lineto + 456 200 462.667 209 476 209 curveto + 490 209 497 200 497 182 curveto + 497 0 lineto + closepath + } bind def + /bracketleft { 599 0 280 -124 445 604 setcachedevice + 321 563 moveto + 321 -83 lineto + 418 -83 lineto + 436 -83 445 -89.6667 445 -103 curveto + 445 -117 436 -124 418 -124 curveto + 280 -124 lineto + 280 604 lineto + 418 604 lineto + 436 604 445 597.333 445 584 curveto + 445 570 436 563 418 563 curveto + 321 563 lineto + closepath + } bind def + /backslash { 599 0 113 -81 487 668 setcachedevice + 155 650 moveto + 482 -46 lineto + 485.333 -52 487 -57.3333 487 -62 curveto + 487 -70 483 -75.6667 475 -79 curveto + 472.333 -80.3333 469.667 -81 467 -81 curveto + 459.667 -81 453.333 -77 448 -69 curveto + 447.333 -67 446.333 -65 445 -63 curveto + 118 633 lineto + 114.667 639.667 113 645 113 649 curveto + 113 657 117.333 663 126 667 curveto + 128.667 667.667 131.333 668 134 668 curveto + 141.333 668 147.333 663.667 152 655 curveto + 152.667 653.667 153.667 652 155 650 curveto + closepath + } bind def + /bracketright { 599 0 155 -124 320 604 setcachedevice + 279 -83 moveto + 279 563 lineto + 182 563 lineto + 164 563 155 569.667 155 583 curveto + 155 597 164 604 182 604 curveto + 320 604 lineto + 320 -124 lineto + 182 -124 lineto + 164 -124 155 -117.333 155 -104 curveto + 155 -90 164 -83 182 -83 curveto + 279 -83 lineto + closepath + } bind def + /asciicircum { 599 0 113 354 487 615 setcachedevice + 300 615 moveto + 478 392 lineto + 484 384.667 487 378.667 487 374 curveto + 487 364.667 482.667 358.333 474 355 curveto + 471.333 354.333 469 354 467 354 curveto + 461 354 455 357.333 449 364 curveto + 448.333 365.333 447.667 366.333 447 367 curveto + 300 552 lineto + 153 367 lineto + 147 358.333 140.333 354 133 354 curveto + 124.333 354 118 358 114 366 curveto + 113.333 368.667 113 371.333 113 374 curveto + 113 378.667 116 384.667 122 392 curveto + 300 615 lineto + closepath + } bind def + /underscore { 599 0 -12 -125 612 -75 setcachedevice + 612 -75 moveto + 612 -125 lineto + -12 -125 lineto + -12 -75 lineto + 612 -75 lineto + closepath + } bind def + /grave { 599 0 155 490 320 639 setcachedevice + 194 630 moveto + 308 530 lineto + 315 522 lineto + 318.333 517.333 320 513.667 320 511 curveto + 320 501 315.333 494.333 306 491 curveto + 304 490.333 301.667 490 299 490 curveto + 294.333 490 288.333 493 281 499 curveto + 167 599 lineto + 159 605.667 155 612.333 155 619 curveto + 155 627.667 159 634 167 638 curveto + 169.667 638.667 172.333 639 175 639 curveto + 180.333 639 186.667 636 194 630 curveto + closepath + } bind def + /a { 599 0 72 -16 541 431 setcachedevice + 125 378 moveto + 125 394.667 156.333 409 219 421 curveto + 253.667 427.667 280.333 431 299 431 curveto + 350.333 431 391.667 417 423 389 curveto + 447.667 366.333 460 339.333 460 308 curveto + 460 41 lineto + 514 41 lineto + 532 41 541 34.3333 541 21 curveto + 541 7 532 0 514 0 curveto + 419 0 lineto + 419 67 lineto + 363.667 15 304.667 -12.6667 242 -16 curveto + 228 -16 lineto + 174 -16 132.667 -0.666667 104 30 curveto + 82.6667 52 72 79.3333 72 112 curveto + 72 156.667 92.3333 192.667 133 220 curveto + 172.333 245.333 222.333 258 283 258 curveto + 319.667 258 358.667 252.667 400 242 curveto + 406 240.667 412.333 239 419 237 curveto + 419 308 lineto + 419 336.667 404.333 358.667 375 374 curveto + 353 384.667 326.667 390 296 390 curveto + 262.667 390 226 383 186 369 curveto + 165.333 361.667 151.333 358 144 358 curveto + 135.333 358 129.333 362.333 126 371 curveto + 125.333 373 125 375.333 125 378 curveto + closepath + 419 112 moveto + 419 202 lineto + 379 212 336.333 217 291 217 curveto + 227 217 178.667 203.333 146 176 curveto + 124 158 113 136.333 113 111 curveto + 113 79.6667 127.667 56.3333 157 41 curveto + 176.333 30.3333 199.667 25 227 25 curveto + 277 25 323 39 365 67 curveto + 382.333 79 400.333 94 419 112 curveto + closepath + } bind def + /b { 599 0 22 -16 541 604 setcachedevice + 144 604 moveto + 144 328 lineto + 184.667 385.333 232.333 418.667 287 428 curveto + 299 430 311.333 431 324 431 curveto + 380.667 431 429.667 412.333 471 375 curveto + 510.333 337.667 533.333 291.333 540 236 curveto + 540.667 227.333 541 218.667 541 210 curveto + 541 152.667 522.667 102.667 486 60 curveto + 451.333 18.6667 408 -6 356 -14 curveto + 345.333 -15.3333 334.667 -16 324 -16 curveto + 250.667 -16 190.667 18.6667 144 88 curveto + 144 0 lineto + 49 0 lineto + 31 0 22 7 22 21 curveto + 22 34.3333 31 41 49 41 curveto + 103 41 lineto + 103 563 lineto + 49 563 lineto + 31 563 22 570 22 584 curveto + 22 597.333 31 604 49 604 curveto + 144 604 lineto + closepath + 322 390 moveto + 274 390 233 373.333 199 340 curveto + 165 307.333 147 267 145 219 curveto + 144.333 215 144 211.333 144 208 curveto + 144 158.667 160.333 116.667 193 82 curveto + 225 47.3333 264.333 28.3333 311 25 curveto + 322 25 lineto + 368 25 408.333 41.3333 443 74 curveto + 477 106 496 144.667 500 190 curveto + 500 205 lineto + 500 256.333 483.333 299.667 450 335 curveto + 417.333 369.667 377 388 329 390 curveto + 322 390 lineto + closepath + } bind def + /c { 599 0 84 -16 535 431 setcachedevice + 535 88 moveto + 535 79.3333 525.333 67 506 51 curveto + 469.333 20.3333 424.333 0 371 -10 curveto + 350.333 -14 329.667 -16 309 -16 curveto + 245 -16 192 3.66667 150 43 curveto + 108.667 82.3333 86.6667 132.333 84 193 curveto + 84 204 lineto + 84 268 104.333 321 145 363 curveto + 185 405 236.667 427.667 300 431 curveto + 314 431 lineto + 376.667 431 428.667 412.667 470 376 curveto + 470 389 lineto + 470 407.667 477 417 491 417 curveto + 504.333 417 511 407.667 511 389 curveto + 511 298 lineto + 511 280 504.333 271 491 271 curveto + 480.333 271 473.667 277 471 289 curveto + 471 291 470.667 293 470 295 curveto + 468 321.667 451 344.333 419 363 curveto + 389 381 353 390 311 390 curveto + 253.667 390 207.333 371.333 172 334 curveto + 140.667 300.667 125 257.667 125 205 curveto + 125 151.667 143 108 179 74 curveto + 213.667 41.3333 257.667 25 311 25 curveto + 383.667 25 446 49 498 97 curveto + 504 103 510 106.333 516 107 curveto + 524 107 530 103 534 95 curveto + 534.667 93 535 90.6667 535 88 curveto + closepath + } bind def + /d { 599 0 63 -16 583 604 setcachedevice + 502 604 moveto + 502 41 lineto + 556 41 lineto + 574 41 583 34.3333 583 21 curveto + 583 7 574 0 556 0 curveto + 461 0 lineto + 461 89 lineto + 414.333 19 353.667 -16 279 -16 curveto + 225 -16 177.667 2.66667 137 40 curveto + 97 76 73 120.667 65 174 curveto + 63.6667 185.333 63 196.667 63 208 curveto + 63 264 81.3333 313.333 118 356 curveto + 152.667 396.667 195.667 421 247 429 curveto + 257.667 430.333 268.333 431 279 431 curveto + 347 431 403.667 401.667 449 343 curveto + 461 327 lineto + 461 563 lineto + 407 563 lineto + 389 563 380 570 380 584 curveto + 380 597.333 389 604 407 604 curveto + 502 604 lineto + closepath + 282 390 moveto + 234 390 193 373.333 159 340 curveto + 125 306.667 106.667 266 104 218 curveto + 104 208 lineto + 104 158 120.667 115.667 154 81 curveto + 186.667 45.6667 226.667 27 274 25 curveto + 283 25 lineto + 330.333 25 371 41.3333 405 74 curveto + 439 106.667 457.333 146.333 460 193 curveto + 460.667 197.667 461 202 461 206 curveto + 461 257.333 444.333 300.667 411 336 curveto + 377.667 370.667 336.667 388.667 288 390 curveto + 282 390 lineto + closepath + } bind def + /e { 599 0 63 -16 520 431 setcachedevice + 520 199 moveto + 104 199 lineto + 112 141.667 137 97 179 65 curveto + 214.333 38.3333 256.667 25 306 25 curveto + 353.333 25 398.333 35 441 55 curveto + 457 62.3333 470.333 70.3333 481 79 curveto + 487.667 83.6667 493 86 497 86 curveto + 505 86 511 82 515 74 curveto + 515.667 71.3333 516 68.6667 516 66 curveto + 516 52 499.333 37 466 21 curveto + 424 1 378.667 -11 330 -15 curveto + 321.333 -15.6667 313 -16 305 -16 curveto + 243 -16 189.333 3.33333 144 42 curveto + 100.667 78.6667 74.6667 124.667 66 180 curveto + 64 192 63 204.333 63 217 curveto + 63 273 82.3333 321 121 361 curveto + 159 401 207 424 265 430 curveto + 273.667 430.667 282.333 431 291 431 curveto + 357.667 431 412 410.333 454 369 curveto + 498 326.333 520 269.667 520 199 curveto + closepath + 104 240 moveto + 478 240 lineto + 468.667 291.333 443.333 330.667 402 358 curveto + 370 379.333 333 390 291 390 curveto + 232.333 390 185 370.667 149 332 curveto + 126.333 306.667 111.333 276 104 240 curveto + closepath + } bind def + /f { 599 0 105 0 541 604 setcachedevice + 520 551 moveto + 428 561 lineto + 410.667 562.333 395.333 563 382 563 curveto + 340.667 563 310 551.333 290 528 curveto + 277.333 513.333 271 496.667 271 478 curveto + 271 417 lineto + 460 417 lineto + 478 417 487 410.333 487 397 curveto + 487 383 478 376 460 376 curveto + 271 376 lineto + 271 41 lineto + 449 41 lineto + 467 41 476 34.3333 476 21 curveto + 476 7 467 0 449 0 curveto + 132 0 lineto + 114 0 105 7 105 21 curveto + 105 34.3333 114 41 132 41 curveto + 230 41 lineto + 230 376 lineto + 142 376 lineto + 124 376 115 383 115 397 curveto + 115 410.333 124 417 142 417 curveto + 230 417 lineto + 230 478 lineto + 230 516.667 246 548 278 572 curveto + 306 593.333 341.333 604 384 604 curveto + 423.333 604 465.667 600.333 511 593 curveto + 515.667 592.333 519.667 591.667 523 591 curveto + 535 587.667 541 581 541 571 curveto + 541 561 536 554.667 526 552 curveto + 524 551.333 522 551 520 551 curveto + closepath + } bind def + /g { 599 0 63 -186 562 431 setcachedevice + 440 334 moveto + 440 417 lineto + 535 417 lineto + 553 417 562 410.333 562 397 curveto + 562 383 553 376 535 376 curveto + 481 376 lineto + 481 -28 lineto + 481 -64.6667 468 -97.6667 442 -127 curveto + 440.667 -128.333 439.333 -130 438 -132 curveto + 407.333 -164.667 372 -182.667 332 -186 curveto + 316 -186 lineto + 202 -186 lineto + 184 -186 175 -179 175 -165 curveto + 175 -151.667 184 -145 202 -145 curveto + 318 -145 lineto + 354 -145 384 -131.667 408 -105 curveto + 429.333 -81.6667 440 -54 440 -22 curveto + 440 107 lineto + 399.333 47.6667 348.667 15.6667 288 11 curveto + 282 10.3333 275.667 10 269 10 curveto + 216.333 10 170.667 28 132 64 curveto + 94 99.3333 71.6667 142.667 65 194 curveto + 63.6667 203.333 63 212.333 63 221 curveto + 63 275 80.6667 322 116 362 curveto + 150.667 400.667 193 423.333 243 430 curveto + 251.667 430.667 260.333 431 269 431 curveto + 329 431 378.667 408.333 418 363 curveto + 425.333 354.333 432.667 344.667 440 334 curveto + closepath + 272 390 moveto + 226 390 186.667 374 154 342 curveto + 121.333 307.333 104.667 267 104 221 curveto + 104 174.333 120 134.667 152 102 curveto + 183.333 69.3333 221.667 52.3333 267 51 curveto + 272 51 lineto + 318 51 357.333 67 390 99 curveto + 422 133.667 438.667 173.667 440 219 curveto + 440 267.667 423.667 308.333 391 341 curveto + 359 373.667 319.333 390 272 390 curveto + closepath + } bind def + /h { 599 0 43 0 551 604 setcachedevice + 437 288 moveto + 437 323.333 422.333 350.333 393 369 curveto + 371.667 383 345.333 390 314 390 curveto + 283.333 390 257.333 382.667 236 368 curveto + 220 357.333 200 337.667 176 309 curveto + 165 296 lineto + 165 41 lineto + 210 41 lineto + 228.667 41 238 34.3333 238 21 curveto + 238 7 228.667 0 210 0 curveto + 78 0 lineto + 60 0 51 7 51 21 curveto + 51 34.3333 60 41 78 41 curveto + 124 41 lineto + 124 563 lineto + 70 563 lineto + 52 563 43 570 43 584 curveto + 43 597.333 52 604 70 604 curveto + 165 604 lineto + 165 347 lineto + 199 387.667 232.333 413 265 423 curveto + 281 428.333 299 431 319 431 curveto + 369.667 431 410 415.667 440 385 curveto + 465.333 359.667 478 328.333 478 291 curveto + 478 41 lineto + 523 41 lineto + 541.667 41 551 34.3333 551 21 curveto + 551 7 541.667 0 523 0 curveto + 392 0 lineto + 374 0 365 7 365 21 curveto + 365 34.3333 374 41 392 41 curveto + 437 41 lineto + 437 288 lineto + closepath + } bind def + /i { 599 0 92 0 508 624 setcachedevice + 320 417 moveto + 320 41 lineto + 480 41 lineto + 498.667 41 508 34.3333 508 21 curveto + 508 7 498.667 0 480 0 curveto + 119 0 lineto + 101 0 92 7 92 21 curveto + 92 34.3333 101 41 119 41 curveto + 279 41 lineto + 279 376 lineto + 161 376 lineto + 143 376 134 383 134 397 curveto + 134 410.333 143 417 161 417 curveto + 320 417 lineto + closepath + 318 624 moveto + 318 520 lineto + 259 520 lineto + 259 624 lineto + 318 624 lineto + closepath + } bind def + /j { 599 0 147 -186 458 624 setcachedevice + 417 376 moveto + 176 376 lineto + 158 376 149 383 149 397 curveto + 149 410.333 158 417 176 417 curveto + 458 417 lineto + 458 -28 lineto + 458 -78 441.333 -118 408 -148 curveto + 380 -173.333 345 -186 303 -186 curveto + 174 -186 lineto + 156 -186 147 -179 147 -165 curveto + 147 -151.667 156 -145 174 -145 curveto + 302 -145 lineto + 339.333 -145 369 -131.333 391 -104 curveto + 408.333 -83.3333 417 -58 417 -28 curveto + 417 376 lineto + closepath + 414 624 moveto + 414 520 lineto + 355 520 lineto + 355 624 lineto + 414 624 lineto + closepath + } bind def + /k { 599 0 63 0 541 604 setcachedevice + 185 180 moveto + 185 0 lineto + 90 0 lineto + 72 0 63 7 63 21 curveto + 63 34.3333 72 41 90 41 curveto + 144 41 lineto + 144 563 lineto + 90 563 lineto + 72 563 63 570 63 584 curveto + 63 597.333 72 604 90 604 curveto + 185 604 lineto + 185 229 lineto + 358 376 lineto + 336 376 lineto + 318 376 309 383 309 397 curveto + 309 410.333 318 417 336 417 curveto + 466 417 lineto + 484 417 493 410.333 493 397 curveto + 493 383 484 376 466 376 curveto + 419 376 lineto + 262 245 lineto + 469 41 lineto + 514 41 lineto + 532 41 541 34.3333 541 21 curveto + 541 7 532 0 514 0 curveto + 383 0 lineto + 365 0 356 7 356 21 curveto + 356 34.3333 365 41 383 41 curveto + 411 41 lineto + 231 219 lineto + 185 180 lineto + closepath + } bind def + /l { 599 0 92 0 508 604 setcachedevice + 320 604 moveto + 320 41 lineto + 480 41 lineto + 498.667 41 508 34.3333 508 21 curveto + 508 7 498.667 0 480 0 curveto + 119 0 lineto + 101 0 92 7 92 21 curveto + 92 34.3333 101 41 119 41 curveto + 279 41 lineto + 279 563 lineto + 162 563 lineto + 144 563 135 570 135 584 curveto + 135 597.333 144 604 162 604 curveto + 320 604 lineto + closepath + } bind def + /m { 599 0 11 0 593 431 setcachedevice + 112 417 moveto + 112 365 lineto + 136 399 160.333 419.667 185 427 curveto + 194.333 429.667 205 431 217 431 curveto + 260.333 431 292.667 407.333 314 360 curveto + 344.667 399.333 375 422.333 405 429 curveto + 412.333 430.333 419.667 431 427 431 curveto + 458.333 431 484.333 419 505 395 curveto + 523 374.333 532 350.333 532 323 curveto + 532 41 lineto + 566 41 lineto + 584 41 593 34.3333 593 21 curveto + 593 7 584 0 566 0 curveto + 492 0 lineto + 492 319 lineto + 492 341.667 483.333 360.333 466 375 curveto + 454 385 440.667 390 426 390 curveto + 398.667 390 372 374 346 342 curveto + 338 332.667 330 321.333 322 308 curveto + 322 41 lineto + 356 41 lineto + 374 41 383 34.3333 383 21 curveto + 383 7 374 0 356 0 curveto + 282 0 lineto + 282 316 lineto + 282 339.333 273.333 358.667 256 374 curveto + 244 384.667 231 390 217 390 curveto + 187 390 156.333 369 125 327 curveto + 112 308 lineto + 112 41 lineto + 146 41 lineto + 164 41 173 34.3333 173 21 curveto + 173 7 164 0 146 0 curveto + 37 0 lineto + 19.6667 0 11 7 11 21 curveto + 11 34.3333 20 41 38 41 curveto + 72 41 lineto + 72 376 lineto + 38 376 lineto + 20 376 11 383 11 397 curveto + 11 410.333 20 417 38 417 curveto + 112 417 lineto + closepath + } bind def + /n { 599 0 53 0 541 431 setcachedevice + 319 390 moveto + 269 390 225.333 367 188 321 curveto + 167 294 lineto + 167 41 lineto + 212 41 lineto + 230 41 239 34.3333 239 21 curveto + 239 7 230 0 212 0 curveto + 81 0 lineto + 62.3333 0 53 7 53 21 curveto + 53 34.3333 62.3333 41 81 41 curveto + 126 41 lineto + 126 376 lineto + 92 376 lineto + 74 376 65 383 65 397 curveto + 65 410.333 74 417 92 417 curveto + 167 417 lineto + 167 348 lineto + 201 385.333 231.333 409.333 258 420 curveto + 276 427.333 297.667 431 323 431 curveto + 370.333 431 409 416.667 439 388 curveto + 466.333 362.667 480 331.667 480 295 curveto + 480 41 lineto + 514 41 lineto + 532 41 541 34.3333 541 21 curveto + 541 7 532 0 514 0 curveto + 405 0 lineto + 387 0 378 7 378 21 curveto + 378 34.3333 387 41 405 41 curveto + 439 41 lineto + 439 288 lineto + 439 320.667 425.667 347 399 367 curveto + 377.667 382.333 351 390 319 390 curveto + closepath + } bind def + /o { 599 0 72 -16 528 431 setcachedevice + 300 431 moveto + 359.333 431 410.667 412 454 374 curveto + 495.333 336.667 519.333 290 526 234 curveto + 527.333 224.667 528 215 528 205 curveto + 528 149.667 509 101 471 59 curveto + 434.333 19 388.667 -5.33333 334 -14 curveto + 322.667 -15.3333 311.333 -16 300 -16 curveto + 241.333 -16 190.333 2.66667 147 40 curveto + 105.667 76.6667 81.3333 122 74 176 curveto + 72.6667 186.667 72 197.333 72 208 curveto + 72 264 90.6667 313 128 355 curveto + 164.667 396.333 210.667 421 266 429 curveto + 277.333 430.333 288.667 431 300 431 curveto + closepath + 300 390 moveto + 250 390 207 373.333 171 340 curveto + 135.667 308 116.333 268 113 220 curveto + 113 208 lineto + 113 158.667 130 116.667 164 82 curveto + 197.333 46.6667 238.667 27.6667 288 25 curveto + 300 25 lineto + 349.333 25 392 41.3333 428 74 curveto + 462.667 106 482 145 486 191 curveto + 486.667 195.667 487 200.333 487 205 curveto + 487 256.333 469.667 299.667 435 335 curveto + 400.333 369.667 357.667 388 307 390 curveto + 300 390 lineto + closepath + } bind def + /p { 599 0 22 -186 541 431 setcachedevice + 144 417 moveto + 144 335 lineto + 178.667 379.667 215.333 408.333 254 421 curveto + 274 427.667 297 431 323 431 curveto + 382.333 431 432.333 412.333 473 375 curveto + 513 339.667 535.333 295 540 241 curveto + 540.667 234.333 541 227.667 541 221 curveto + 541 165 522.333 117.333 485 78 curveto + 447.667 38.6667 401.333 16.3333 346 11 curveto + 338 10.3333 330.333 10 323 10 curveto + 257.667 10 204.667 33.6667 164 81 curveto + 156.667 88.3333 150 96.6667 144 106 curveto + 144 -145 lineto + 242 -145 lineto + 260 -145 269 -151.667 269 -165 curveto + 269 -179 260 -186 242 -186 curveto + 49 -186 lineto + 31 -186 22 -179 22 -165 curveto + 22 -151.667 31 -145 49 -145 curveto + 103 -145 lineto + 103 376 lineto + 49 376 lineto + 31 376 22 383 22 397 curveto + 22 410.333 31 417 49 417 curveto + 144 417 lineto + closepath + 322 390 moveto + 273.333 390 232 374 198 342 curveto + 164 310.667 146 272.667 144 228 curveto + 144 221 lineto + 144 174.333 160.667 135 194 103 curveto + 227.333 69.6667 267.667 52.3333 315 51 curveto + 322 51 lineto + 370 51 411.333 66.6667 446 98 curveto + 480 129.333 498 167 500 211 curveto + 500 219 lineto + 500 267 483.333 307.333 450 340 curveto + 415.333 373.333 372.667 390 322 390 curveto + closepath + } bind def + /q { 599 0 63 -186 583 431 setcachedevice + 461 335 moveto + 461 417 lineto + 556 417 lineto + 574 417 583 410.333 583 397 curveto + 583 383 574 376 556 376 curveto + 502 376 lineto + 502 -145 lineto + 556 -145 lineto + 574 -145 583 -151.667 583 -165 curveto + 583 -179 574 -186 556 -186 curveto + 363 -186 lineto + 345 -186 336 -179 336 -165 curveto + 336 -151.667 345 -145 363 -145 curveto + 461 -145 lineto + 461 106 lineto + 423.667 52 376.333 20.6667 319 12 curveto + 307 10.6667 294.333 10 281 10 curveto + 223 10 173.333 28.3333 132 65 curveto + 92 101 69.3333 146 64 200 curveto + 63.3333 206.667 63 213.667 63 221 curveto + 63 277 82 324.667 120 364 curveto + 157.333 403.333 204.333 425.333 261 430 curveto + 267.667 430.667 274.667 431 282 431 curveto + 344 431 395.667 409 437 365 curveto + 445 356.333 453 346.333 461 335 curveto + closepath + 282 390 moveto + 232.667 390 190.667 373.667 156 341 curveto + 122 307.667 104.667 267.667 104 221 curveto + 104 174.333 120.667 134.667 154 102 curveto + 190 69.3333 232.667 52.3333 282 51 curveto + 330 51 371.333 66.6667 406 98 curveto + 440 128.667 458.333 166 461 210 curveto + 461 219 lineto + 461 267 444 307.333 410 340 curveto + 374.667 372.667 332 389.333 282 390 curveto + closepath + } bind def + /r { 599 0 84 0 541 427 setcachedevice + 520 344 moveto + 516 344 508 349 496 359 curveto + 477.333 375 460.333 384 445 386 curveto + 438 386 lineto + 414.667 386 390 377 364 359 curveto + 340 343 301.333 310.667 248 262 curveto + 248 41 lineto + 427 41 lineto + 443.667 39 452.667 32 454 20 curveto + 454 9.33333 447.667 2.66667 435 0 curveto + 427 0 lineto + 111 0 lineto + 95 0 86 6 84 18 curveto + 84 21 lineto + 84 31.6667 90.3333 38.3333 103 41 curveto + 111 41 lineto + 207 41 lineto + 207 376 lineto + 132 376 lineto + 116 376 107 382 105 394 curveto + 105 397 lineto + 105 407.667 111.333 414.333 124 417 curveto + 132 417 lineto + 248 417 lineto + 248 315 lineto + 309.333 370.333 357.333 404.333 392 417 curveto + 408.667 423.667 425 427 441 427 curveto + 472.333 427 500 415.333 524 392 curveto + 535.333 380.667 541 371.667 541 365 curveto + 541 355 536.333 348.333 527 345 curveto + 525 344.333 522.667 344 520 344 curveto + closepath + } bind def + /s { 599 0 103 -16 497 431 setcachedevice + 452 117 moveto + 452 149 432.667 172 394 186 curveto + 376.667 192 341.667 199.333 289 208 curveto + 234.333 216.667 195.667 227 173 239 curveto + 140.333 256.333 124 282.667 124 318 curveto + 124 351.333 140.667 378.667 174 400 curveto + 206.667 420.667 247 431 295 431 curveto + 351.667 431 397.333 415.667 432 385 curveto + 432 389 lineto + 432 405 437.667 414.333 449 417 curveto + 453 417 lineto + 466.333 417 473 407.667 473 389 curveto + 473 320 lineto + 473 302 466.333 293 453 293 curveto + 441 293 434 300.667 432 316 curveto + 428.667 343.333 410.333 363.667 377 377 curveto + 355 385.667 329 390 299 390 curveto + 253 390 217.667 379.667 193 359 curveto + 177 346.333 169 331.667 169 315 curveto + 169 290.333 184.667 273 216 263 curveto + 230.667 258.333 262.333 252.667 311 246 curveto + 368.333 238 410 227 436 213 curveto + 439.333 210.333 443 208 447 206 curveto + 473 188.667 489 165.333 495 136 curveto + 496.333 129.333 497 122.667 497 116 curveto + 497 78.6667 478.667 47.3333 442 22 curveto + 405.333 -3.33333 358.333 -16 301 -16 curveto + 237.667 -16 185.333 2 144 38 curveto + 144 27 lineto + 144 9 137.333 0 124 0 curveto + 110 0 103 9 103 27 curveto + 103 110 lineto + 103 128 110 137 124 137 curveto + 134.667 137 141.333 132 144 122 curveto + 144 115 lineto + 144 108 lineto + 144 84.6667 159 65 189 49 curveto + 219 33 255.333 25 298 25 curveto + 350 25 391 36.6667 421 60 curveto + 441.667 76 452 95 452 117 curveto + closepath + } bind def + /t { 599 0 43 -16 499 563 setcachedevice + 186 417 moveto + 406 417 lineto + 424 417 433 410.333 433 397 curveto + 433 383 424 376 406 376 curveto + 186 376 lineto + 186 109 lineto + 186 77 201 53.6667 231 39 curveto + 249.667 29.6667 272 25 298 25 curveto + 343.333 25 387.667 33.3333 431 50 curveto + 443.667 54.6667 454.667 59.6667 464 65 curveto + 470.667 69 476 71 480 71 curveto + 488 71 493.667 67 497 59 curveto + 498.333 56.3333 499 53.6667 499 51 curveto + 499 38.3333 481.333 25.3333 446 12 curveto + 401.333 -5.33333 355.333 -14.6667 308 -16 curveto + 300 -16 lineto + 243.333 -16 201 -0.333333 173 31 curveto + 154.333 51.6667 145 77 145 107 curveto + 145 376 lineto + 71 376 lineto + 52.3333 376 43 383 43 397 curveto + 43 410.333 52.3333 417 71 417 curveto + 145 417 lineto + 145 536 lineto + 145 554 152 563 166 563 curveto + 178 563 184.667 556.667 186 544 curveto + 186 536 lineto + 186 417 lineto + closepath + } bind def + /u { 599 0 43 -16 541 417 setcachedevice + 439 0 moveto + 439 66 lineto + 382.333 11.3333 321.667 -16 257 -16 curveto + 210.333 -16 174.667 0 150 32 curveto + 132.667 54.6667 124 82.3333 124 115 curveto + 124 376 lineto + 70 376 lineto + 52 376 43 383 43 397 curveto + 43 410.333 52 417 70 417 curveto + 165 417 lineto + 165 115 lineto + 165 86.3333 176 63 198 45 curveto + 214.667 31.6667 234 25 256 25 curveto + 322.667 25 383.667 55 439 115 curveto + 439 376 lineto + 365 376 lineto + 346.333 376 337 383 337 397 curveto + 337 410.333 346.333 417 365 417 curveto + 480 417 lineto + 480 41 lineto + 514 41 lineto + 532 41 541 34.3333 541 21 curveto + 541 7 532 0 514 0 curveto + 439 0 lineto + closepath + } bind def + /v { 599 0 30 0 570 417 setcachedevice + 336 0 moveto + 266 0 lineto + 98 376 lineto + 57 376 lineto + 39 376 30 383 30 397 curveto + 30 410.333 39 417 57 417 curveto + 208 417 lineto + 226.667 417 236 410.333 236 397 curveto + 236 383 226.667 376 208 376 curveto + 143 376 lineto + 293 41 lineto + 312 41 lineto + 459 376 lineto + 391 376 lineto + 373 376 364 383 364 397 curveto + 364 410.333 373 417 391 417 curveto + 543 417 lineto + 561 417 570 410.333 570 397 curveto + 570 383 561 376 543 376 curveto + 502 376 lineto + 336 0 lineto + closepath + } bind def + /w { 599 0 30 0 570 417 setcachedevice + 441 0 moveto + 391 0 lineto + 300 259 lineto + 211 0 lineto + 160 0 lineto + 76 376 lineto + 57 376 lineto + 39 376 30 383 30 397 curveto + 30 410.333 39 417 57 417 curveto + 168 417 lineto + 186 417 195 410.333 195 397 curveto + 195 383 186 376 168 376 curveto + 115 376 lineto + 187 56 lineto + 273 311 lineto + 324 311 lineto + 413 56 lineto + 482 376 lineto + 432 376 lineto + 414 376 405 383 405 397 curveto + 405 410.333 414 417 432 417 curveto + 543 417 lineto + 561 417 570 410.333 570 397 curveto + 570 383 561 376 543 376 curveto + 524 376 lineto + 441 0 lineto + closepath + } bind def + /x { 599 0 51 0 549 417 setcachedevice + 329 219 moveto + 513 41 lineto + 522 41 lineto + 540 41 549 34.3333 549 21 curveto + 549 7 540 0 522 0 curveto + 390 0 lineto + 372 0 363 7 363 21 curveto + 363 34.3333 372 41 390 41 curveto + 455 41 lineto + 300 190 lineto + 143 41 lineto + 211 41 lineto + 229 41 238 34.3333 238 21 curveto + 238 7 229 0 211 0 curveto + 78 0 lineto + 60 0 51 7 51 21 curveto + 51 34.3333 60 41 78 41 curveto + 87 41 lineto + 271 219 lineto + 108 376 lineto + 101 376 lineto + 83 376 74 383 74 397 curveto + 74 410.333 83 417 101 417 curveto + 212 417 lineto + 230 417 239 410.333 239 397 curveto + 239 383 230 376 212 376 curveto + 166 376 lineto + 300 246 lineto + 437 376 lineto + 389 376 lineto + 371 376 362 383 362 397 curveto + 362 410.333 371 417 389 417 curveto + 499 417 lineto + 517 417 526 410.333 526 397 curveto + 526 383 517 376 499 376 curveto + 492 376 lineto + 329 219 lineto + closepath + } bind def + /y { 599 0 51 -186 549 417 setcachedevice + 282 0 moveto + 94 376 lineto + 78 376 lineto + 60 376 51 383 51 397 curveto + 51 410.333 60 417 78 417 curveto + 193 417 lineto + 211 417 220 410.333 220 397 curveto + 220 383 211 376 193 376 curveto + 141 376 lineto + 305 45 lineto + 466 376 lineto + 412 376 lineto + 394 376 385 383 385 397 curveto + 385 410.333 394 417 412 417 curveto + 522 417 lineto + 540 417 549 410.333 549 397 curveto + 549 383 540 376 522 376 curveto + 508 376 lineto + 252 -145 lineto + 317 -145 lineto + 335 -145 344 -151.667 344 -165 curveto + 344 -179 335 -186 317 -186 curveto + 84 -186 lineto + 66 -186 57 -179 57 -165 curveto + 57 -151.667 66 -145 84 -145 curveto + 211 -145 lineto + 282 0 lineto + closepath + } bind def + /z { 599 0 115 0 489 417 setcachedevice + 474 417 moveto + 474 381 lineto + 171 41 lineto + 448 41 lineto + 448 97 lineto + 448 115 455 124 469 124 curveto + 482.333 124 489 115 489 97 curveto + 489 0 lineto + 115 0 lineto + 115 36 lineto + 416 376 lineto + 165 376 lineto + 165 321 lineto + 165 303 158.333 294 145 294 curveto + 131 294 124 303 124 321 curveto + 124 417 lineto + 474 417 lineto + closepath + } bind def + /braceleft { 599 0 197 -124 403 604 setcachedevice + 403 584 moveto + 403 576 397 569.667 385 565 curveto + 355 556 lineto + 333 546.667 322 527.667 322 499 curveto + 322 326 lineto + 322 298 315 276.333 301 261 curveto + 295 254.333 287.333 247.333 278 240 curveto + 300 224 313.333 206.667 318 188 curveto + 320.667 178.667 322 167.333 322 154 curveto + 322 -19 lineto + 322 -47.6667 333.333 -67 356 -77 curveto + 392 -88 lineto + 399.333 -91.3333 403 -96.6667 403 -104 curveto + 403 -115.333 396.667 -122 384 -124 curveto + 379 -124 lineto + 348.333 -124 323.333 -112 304 -88 curveto + 288.667 -68.6667 281 -45.6667 281 -19 curveto + 281 154 lineto + 281 182.667 269.333 201.667 246 211 curveto + 209 224 lineto + 201 227.333 197 232.667 197 240 curveto + 197 248.667 203 255 215 259 curveto + 246 269 lineto + 269.333 278.333 281 297.333 281 326 curveto + 281 499 lineto + 281 532.333 292.667 559.333 316 580 curveto + 334 596 355 604 379 604 curveto + 393 604 400.667 598.333 402 587 curveto + 402.667 586.333 403 585.333 403 584 curveto + closepath + } bind def + /bar { 599 0 280 -124 320 604 setcachedevice + 320 577 moveto + 320 -97 lineto + 320 -115 313.333 -124 300 -124 curveto + 286.667 -124 280 -115 280 -97 curveto + 280 577 lineto + 280 595 286.667 604 300 604 curveto + 313.333 604 320 595 320 577 curveto + closepath + } bind def + /braceright { 599 0 197 -124 403 604 setcachedevice + 197 -104 moveto + 197 -96 203 -89.6667 215 -85 curveto + 245 -76 lineto + 267 -66.6667 278 -47.6667 278 -19 curveto + 278 154 lineto + 278 182 285 204 299 220 curveto + 305 226 312.667 232.667 322 240 curveto + 300 256 286.667 273.333 282 292 curveto + 279.333 301.333 278 312.667 278 326 curveto + 278 499 lineto + 278 527.667 266.667 547 244 557 curveto + 208 568 lineto + 200.667 571.333 197 576.667 197 584 curveto + 197 595.333 203 602 215 604 curveto + 221 604 lineto + 251.667 604 276.667 591.667 296 567 curveto + 311.333 547.667 319 525 319 499 curveto + 319 326 lineto + 319 297.333 330.667 278.333 354 269 curveto + 391 256 lineto + 399 252.667 403 247.333 403 240 curveto + 403 232 396.667 225.667 384 221 curveto + 353 211 lineto + 330.333 201.667 319 182.667 319 154 curveto + 319 -19 lineto + 319 -52.3333 307.333 -79.6667 284 -101 curveto + 266 -116.333 245 -124 221 -124 curveto + 207 -124 199 -118.667 197 -108 curveto + 197 -104 lineto + closepath + } bind def + /asciitilde { 599 0 92 212 508 348 setcachedevice + 386 253 moveto + 406 253 427 266 449 292 curveto + 473 321 lineto + 478.333 327 483.333 330 488 330 curveto + 496.667 330 502.667 326 506 318 curveto + 507.333 315.333 508 313 508 311 curveto + 508 302.333 499 288 481 268 curveto + 455 237.333 429 219 403 213 curveto + 398.333 212.333 393.667 212 389 212 curveto + 365.667 212 338 224.667 306 250 curveto + 261 287 lineto + 241.667 300.333 225.333 307 212 307 curveto + 192 307 173.333 295.667 156 273 curveto + 133 243 lineto + 125.667 234.333 118.333 230 111 230 curveto + 103 230 97 234 93 242 curveto + 92.3333 244 92 246.333 92 249 curveto + 92 255.667 98.6667 268 112 286 curveto + 138 320.667 166 341 196 347 curveto + 201.333 347.667 206.667 348 212 348 curveto + 237.333 348 267.667 334 303 306 curveto + 350 269 lineto + 365.333 258.333 377.333 253 386 253 curveto + closepath + } bind def +end +currentdict end +/FreeMono exch definefont diff --git a/graphics/FreeSans.pt3 b/graphics/FreeSans.pt3 new file mode 100644 index 00000000..a48127f7 --- /dev/null +++ b/graphics/FreeSans.pt3 @@ -0,0 +1,2014 @@ +%!PS-AdobeFont-1.0: FreeSans $Revision: 1.1.1.1 $ +%%Title: FreeSans +%Version: $Revision: 1.1.1.1 $ +%%CreationDate: Fri Feb 1 11:56:16 2008 +%%Creator: R. Timothy Edwards +%Copyright: Copyleft 2002, 2003, 2005 Free Software Foundation. +% Generated by FontForge 20080109 (http://fontforge.sf.net/) +%%EndComments + +13 dict begin +/FontType 3 def +/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def +/FontName /FreeSans def +/FontBBox {-631 -462 1632 1231 }readonly def +/UniqueID 4253034 def +/XUID [1021 202 645001535 9000585] def +/PaintType 0 def +/FontInfo 10 dict dup begin + /version ($Revision: 1.1.1.1 $) readonly def + /Notice (Copyleft 2002, 2003, 2005 Free Software Foundation.) readonly def + /FullName (Free Sans) readonly def + /FamilyName (FreeSans) readonly def + /Weight (Book) readonly def + /FSType 0 def + /ItalicAngle 0 def + /isFixedPitch false def + /UnderlinePosition -175.781 def + /UnderlineThickness 49.8047 def +end readonly def +/Encoding StandardEncoding def +/BuildChar { 1 index /Encoding get exch get 1 index /BuildGlyph get exec } bind def +% I call all my CharProcs with two arguments, the top of the stack will be +% 0 and then next thing is the fontdict. If the tos is zero the char will +% do a setcachedevice, otherwise (for referenced chars) it will not. The +% fontdict argument is so a char can invoke a referenced char. BuildGlyph +% itself will remove the arguments from the stack, the CharProc will leave 'em +/BuildGlyph { 2 copy exch /CharProcs get exch 2 copy known not { pop /.notdef} if get exch pop 0 exch exec pop pop fill} bind def +/CharProcs 128 dict def +CharProcs begin + /.notdef { 500 0 67 0 468 977 setcachedevice } bind def + /space { 277 0 0 0 0 0 setcachedevice + } bind def + /exclam { 277 0 124 0 208 729 setcachedevice + 208 729 moveto + 208 391 lineto + 186 168 lineto + 147 168 lineto + 125 391 lineto + 125 729 lineto + 208 729 lineto + closepath + 208 104 moveto + 208 0 lineto + 124 0 lineto + 124 104 lineto + 208 104 lineto + closepath + } bind def + /quotedbl { 354 0 52 464 305 709 setcachedevice + 52 709 moveto + 145 709 lineto + 145 598 lineto + 118 464 lineto + 79 464 lineto + 52 598 lineto + 52 709 lineto + closepath + 212 709 moveto + 305 709 lineto + 305 598 lineto + 278 464 lineto + 239 464 lineto + 212 598 lineto + 212 709 lineto + closepath + } bind def + /numbersign { 555 0 14 -20 542 697 setcachedevice + 485 697 moveto + 449 501 lineto + 542 501 lineto + 542 433 lineto + 436 433 lineto + 405 259 lineto + 510 259 lineto + 510 191 lineto + 393 191 lineto + 354 -20 lineto + 278 -20 lineto + 316 191 lineto + 192 191 lineto + 153 -20 lineto + 77 -20 lineto + 115 191 lineto + 14 191 lineto + 14 259 lineto + 128 259 lineto + 159 433 lineto + 51 433 lineto + 51 501 lineto + 172 501 lineto + 208 697 lineto + 284 697 lineto + 248 501 lineto + 373 501 lineto + 408 697 lineto + 485 697 lineto + closepath + 360 433 moveto + 236 433 lineto + 204 259 lineto + 329 259 lineto + 360 433 lineto + closepath + } bind def + /dollar { 555 0 33 -126 518 770 setcachedevice + 518 195 moveto + 518 113.667 489.333 54.3333 432 17 curveto + 397.333 -6.33333 354 -19.6667 302 -23 curveto + 302 -126 lineto + 243 -126 lineto + 243 -23 lineto + 153 -17 91.6667 16.6667 59 78 curveto + 41.6667 109.333 33 147 33 191 curveto + 33 208 lineto + 112 208 lineto + 115.333 169.333 120 142 126 126 curveto + 140.667 85.3333 173.333 59.6667 224 49 curveto + 230 47.6667 236.333 46.6667 243 46 curveto + 243 318 lineto + 187.667 334.667 149.667 349.333 129 362 curveto + 125.667 364.667 121.667 367.333 117 370 curveto + 69.6667 404 46 452.667 46 516 curveto + 46 596.667 79.3333 654 146 688 curveto + 173.333 702 205.667 711.333 243 716 curveto + 243 770 lineto + 302 770 lineto + 302 716 lineto + 373.333 710.667 426 684.667 460 638 curveto + 484 605.333 496 565.667 496 519 curveto + 417 519 lineto + 416.333 562.333 401.667 596 373 620 curveto + 353 636 329.333 644.667 302 646 curveto + 302 397 lineto + 369 378 lineto + 441.667 354 487.667 316 507 264 curveto + 514.333 243.333 518 220.333 518 195 curveto + closepath + 243 405 moveto + 243 645 lineto + 188.333 637.667 152.667 614 136 574 curveto + 130 559.333 127 543.333 127 526 curveto + 127 472 158 434 220 412 curveto + 226.667 409.333 234.333 407 243 405 curveto + closepath + 302 46 moveto + 363.333 53.3333 404 79.3333 424 124 curveto + 432 141.333 436 161 436 183 curveto + 436 217 425.333 243.333 404 262 curveto + 384.667 278.667 350.667 294.333 302 309 curveto + 302 46 lineto + closepath + } bind def + /percent { 888 0 29 -20 859 709 setcachedevice + 199 685 moveto + 246.333 685 286.333 668.667 319 636 curveto + 352.333 600.667 369.333 559.333 370 512 curveto + 370 467.333 354.333 428.667 323 396 curveto + 291.667 363.333 254 345.667 210 343 curveto + 200 343 lineto + 154 343 114.667 359 82 391 curveto + 48.6667 422.333 31 460.333 29 505 curveto + 29 514 lineto + 29 559.333 45 598.667 77 632 curveto + 108.333 664.667 146 682.333 190 685 curveto + 199 685 lineto + closepath + 199 615 moveto + 168.333 615 143 603.667 123 581 curveto + 106.333 561.667 98 539.333 98 514 curveto + 98 484 109.667 458.667 133 438 curveto + 152.333 421.333 174.667 413 200 413 curveto + 230 413 255.333 424.333 276 447 curveto + 292.667 466.333 301 488.333 301 513 curveto + 301 545 289.333 571 266 591 curveto + 246.667 607 224.333 615 199 615 curveto + closepath + 609 709 moveto + 675 709 lineto + 280 -20 lineto + 214 -20 lineto + 609 709 lineto + closepath + 688 322 moveto + 736 322 776.333 305.333 809 272 curveto + 841.667 238 858.333 197.333 859 150 curveto + 859 105.333 843.333 66.6667 812 34 curveto + 780.667 2 743.333 -15.6667 700 -19 curveto + 689 -19 lineto + 643.667 -19 604.333 -3 571 29 curveto + 538.333 60.3333 520.667 98.3333 518 143 curveto + 518 152 lineto + 518 197.333 533.667 236.333 565 269 curveto + 596.333 301.667 634.333 319 679 321 curveto + 682.333 321.667 685.333 322 688 322 curveto + closepath + 688 252 moveto + 657.333 252 632 240.333 612 217 curveto + 595.333 198.333 587 176.667 587 152 curveto + 587 121.333 598.667 96 622 76 curveto + 641.333 59.3333 663.667 51 689 51 curveto + 719 51 744.333 62.3333 765 85 curveto + 781.667 103.667 790 125.333 790 150 curveto + 790 182 778 208 754 228 curveto + 735.333 244 713.333 252 688 252 curveto + closepath + } bind def + /ampersand { 666 0 52 -23 637 709 setcachedevice + 466 78 moveto + 442 54 423.667 37.3333 411 28 curveto + 364.333 -6 313 -23 257 -23 curveto + 191.667 -23 140.333 -3 103 37 curveto + 69 73 52 119.333 52 176 curveto + 52 222 63.6667 260.333 87 291 curveto + 110.333 320.333 152.667 353 214 389 curveto + 173.333 439.667 148.667 479 140 507 curveto + 135.333 521 133 536 133 552 curveto + 133 595.333 149.333 632.333 182 663 curveto + 215.333 693.667 256 709 304 709 curveto + 354.667 709 395.333 692.667 426 660 curveto + 453.333 630.667 467 594.667 467 552 curveto + 467 512.667 454.667 479.333 430 452 curveto + 409.333 429.333 375.667 404.667 329 378 curveto + 462 215 lineto + 480.667 249 491 284.667 493 322 curveto + 493 330 lineto + 493 334 lineto + 573 334 lineto + 573 275.333 555.333 217 520 159 curveto + 518.667 156.333 517 153.667 515 151 curveto + 637 0 lineto + 528 0 lineto + 466 78 lineto + closepath + 285 431 moveto + 331.667 460.333 361.667 485.333 375 506 curveto + 383.667 520 388 536 388 554 curveto + 388 583.333 376.667 606.333 354 623 curveto + 338.667 633.667 321 639 301 639 curveto + 267 639 242.667 626.667 228 602 curveto + 219.333 588 215 571.667 215 553 curveto + 215 534.333 220 516.667 230 500 curveto + 238.667 486 257 463 285 431 curveto + closepath + 418 137 moveto + 258 337 lineto + 202.667 301.667 167 270 151 242 curveto + 141 224 136 204.333 136 183 curveto + 136 146.333 149.667 115.667 177 91 curveto + 202.333 67 232.333 55 267 55 curveto + 305 55 342 70 378 100 curveto + 390.667 110 404 122.333 418 137 curveto + closepath + } bind def + /quotesingle { 190 0 48 464 142 709 setcachedevice + 48 709 moveto + 142 709 lineto + 142 598 lineto + 115 464 lineto + 75 464 lineto + 48 598 lineto + 48 709 lineto + closepath + } bind def + /parenleft { 332 0 73 -212 291 729 setcachedevice + 236 729 moveto + 291 729 lineto + 222.333 617.667 179.333 498.333 162 371 curveto + 156.667 333 154 295.667 154 259 curveto + 154 130.333 183 4 241 -120 curveto + 256.333 -151.333 273 -182 291 -212 curveto + 236 -212 lineto + 174 -130.667 128.667 -36.6667 100 70 curveto + 82 135.333 73 198.333 73 259 curveto + 73 358.333 95.3333 459.667 140 563 curveto + 166.667 625 198.667 680.333 236 729 curveto + closepath + } bind def + /parenright { 332 0 38 -212 256 729 setcachedevice + 93 -212 moveto + 38 -212 lineto + 106.667 -101.333 149.667 18 167 146 curveto + 172.333 184 175 221.333 175 258 curveto + 175 387.333 145.667 514.333 87 639 curveto + 72.3333 670.333 56 700.333 38 729 curveto + 93 729 lineto + 155 647.667 200.333 553.667 229 447 curveto + 247 381.667 256 318.667 256 258 curveto + 256 159.333 233.667 58.3333 189 -45 curveto + 162.333 -107 130.333 -162.667 93 -212 curveto + closepath + } bind def + /asterisk { 388 0 40 441 343 729 setcachedevice + 160 729 moveto + 223 729 lineto + 218 617 lineto + 324 655 lineto + 343 596 lineto + 235 566 lineto + 305 477 lineto + 254 441 lineto + 192 534 lineto + 129 441 lineto + 79 477 lineto + 148 566 lineto + 40 596 lineto + 59 655 lineto + 165 617 lineto + 160 729 lineto + closepath + } bind def + /plus { 583 0 50 -10 534 474 setcachedevice + 534 267 moveto + 534 197 lineto + 327 197 lineto + 327 -10 lineto + 257 -10 lineto + 257 197 lineto + 50 197 lineto + 50 267 lineto + 257 267 lineto + 257 474 lineto + 327 474 lineto + 327 267 lineto + 534 267 lineto + closepath + } bind def + /comma { 277 0 87 -147 192 104 setcachedevice + 87 104 moveto + 192 104 lineto + 192 -16 lineto + 192 -103.333 157 -147 87 -147 curveto + 87 -109 lineto + 111.667 -107.667 128 -100 136 -86 curveto + 143.333 -73.3333 147 -50.6667 147 -18 curveto + 147 0 lineto + 87 0 lineto + 87 104 lineto + closepath + } bind def + /hyphen { 332 0 46 240 284 312 setcachedevice + 284 312 moveto + 284 240 lineto + 46 240 lineto + 46 312 lineto + 284 312 lineto + closepath + } bind def + /period { 277 0 87 0 191 104 setcachedevice + 191 104 moveto + 191 0 lineto + 87 0 lineto + 87 104 lineto + 191 104 lineto + closepath + } bind def + /slash { 277 0 -8 -20 284 729 setcachedevice + 229 729 moveto + 284 729 lineto + 47 -20 lineto + -8 -20 lineto + 229 729 lineto + closepath + } bind def + /zero { 555 0 43 -23 507 709 setcachedevice + 43 343 moveto + 43 531 90.6667 647 186 691 curveto + 212.667 703 242.333 709 275 709 curveto + 399 709 473.333 628.333 498 467 curveto + 504 428.333 507 385 507 337 curveto + 507 183 473 77.6667 405 21 curveto + 369.667 -8.33333 326.333 -23 275 -23 curveto + 175.667 -23 108 29.6667 72 135 curveto + 52.6667 191 43 260.333 43 343 curveto + closepath + 275 631 moveto + 180.333 631 133 534.667 133 342 curveto + 133 147.333 179.667 50 273 50 curveto + 337.667 50 380.333 92.6667 401 178 curveto + 411.667 221.333 417 277 417 345 curveto + 417 535.667 369.667 631 275 631 curveto + closepath + } bind def + /one { 555 0 102 0 347 709 setcachedevice + 259 505 moveto + 102 505 lineto + 102 568 lineto + 160 575.333 199.333 584.333 220 595 curveto + 240.667 605.667 257 624 269 650 curveto + 275 663.333 281.667 683 289 709 curveto + 347 709 lineto + 347 0 lineto + 259 0 lineto + 259 505 lineto + closepath + } bind def + /two { 555 0 34 0 511 709 setcachedevice + 50 463 moveto + 54.6667 627 132.667 709 284 709 curveto + 352 709 407 689.333 449 650 curveto + 490.333 611.333 511 561.667 511 501 curveto + 511 417.667 466 349.333 376 296 curveto + 361 287 lineto + 261 233 lineto + 206.333 203.667 170 173.667 152 143 curveto + 142.667 127 136.333 108.333 133 87 curveto + 506 87 lineto + 506 0 lineto + 34 0 lineto + 38 72.6667 51.6667 129.333 75 170 curveto + 97 209.333 135.333 246.333 190 281 curveto + 202.667 289.667 217 298.333 233 307 curveto + 325 359 lineto + 389 395.667 421 442.333 421 499 curveto + 421 539.667 406 572.667 376 598 curveto + 350 620.667 318.333 632 281 632 curveto + 197 632 150 582 140 482 curveto + 139.333 476 138.667 469.667 138 463 curveto + 50 463 lineto + closepath + } bind def + /three { 555 0 32 -23 506 709 setcachedevice + 270 632 moveto + 201.333 632 159 602.667 143 544 curveto + 138.333 526.667 135.667 505.333 135 480 curveto + 47 480 lineto + 49 600 96 673 188 699 curveto + 212 705.667 239 709 269 709 curveto + 348.333 709 407 685.667 445 639 curveto + 471.667 606.333 485 564.667 485 514 curveto + 485 442 452 393 386 367 curveto + 439.333 349 474.333 320.667 491 282 curveto + 501 259.333 506 231.333 506 198 curveto + 506 128.667 483 73.6667 437 33 curveto + 393.667 -4.33333 336.667 -23 266 -23 curveto + 152.667 -23 80.3333 22.6667 49 114 curveto + 40.3333 140.667 34.6667 171.333 32 206 curveto + 120 206 lineto + 124 130 152.333 82.6667 205 64 curveto + 223 58 244.333 55 269 55 curveto + 327 55 368.667 74.3333 394 113 curveto + 408.667 135.667 416 163.667 416 197 curveto + 416 275.667 374.667 318.333 292 325 curveto + 284.667 325.667 277 326 269 326 curveto + 232 325 lineto + 221 325 lineto + 221 400 lineto + 285 400.667 329.333 408 354 422 curveto + 381.333 438.667 395 468.333 395 511 curveto + 395 559 377.667 593.333 343 614 curveto + 322.333 626 298 632 270 632 curveto + closepath + } bind def + /four { 555 0 28 0 520 709 setcachedevice + 327 170 moveto + 28 170 lineto + 28 263 lineto + 350 709 lineto + 415 709 lineto + 415 249 lineto + 520 249 lineto + 520 170 lineto + 415 170 lineto + 415 0 lineto + 327 0 lineto + 327 170 lineto + closepath + 327 249 moveto + 327 559 lineto + 105 249 lineto + 327 249 lineto + closepath + } bind def + /five { 555 0 35 -23 513 709 setcachedevice + 476 709 moveto + 476 622 lineto + 181 622 lineto + 153 424 lineto + 193 452 236.667 466.333 284 467 curveto + 351.333 467 406.333 445.333 449 402 curveto + 491.667 358.667 513 301.667 513 231 curveto + 513 158.333 491.333 98.3333 448 51 curveto + 406 5 351.333 -19.3333 284 -22 curveto + 279.333 -22.6667 274.667 -23 270 -23 curveto + 140 -23 62.6667 38.6667 38 162 curveto + 37.3333 164 36.3333 168 35 174 curveto + 123 174 lineto + 143 98.6667 187.667 59.3333 257 56 curveto + 260.333 55.3333 264 55 268 55 curveto + 325.333 55 367.667 75.3333 395 116 curveto + 413.667 143.333 423 177.667 423 219 curveto + 423 281 404 327 366 357 curveto + 340 378.333 307.333 389 268 389 curveto + 231.333 389 200.333 379.333 175 360 curveto + 163.667 350.667 151.333 338.333 138 323 curveto + 57 323 lineto + 110 709 lineto + 476 709 lineto + closepath + } bind def + /six { 555 0 43 -23 513 709 setcachedevice + 43 323 moveto + 43 506.333 88.3333 625 179 679 curveto + 213 699 252.333 709 297 709 curveto + 362.333 709 413.333 686 450 640 curveto + 475.333 609.333 491.333 570.667 498 524 curveto + 410 524 lineto + 400 574.667 375.667 607.667 337 623 curveto + 323 628.333 307.667 631 291 631 curveto + 227.667 631 183 595.333 157 524 curveto + 141 480.667 133 426.667 133 362 curveto + 171 414.667 225.333 441 296 441 curveto + 358 441 409.333 420.667 450 380 curveto + 490.667 339.333 511.667 286.667 513 222 curveto + 513 216 lineto + 513 149.333 492.667 93.6667 452 49 curveto + 412 5 360.667 -18.6667 298 -22 curveto + 292.667 -22.6667 287 -23 281 -23 curveto + 135.667 -23 56.6667 74.3333 44 269 curveto + 43.3333 286.333 43 304.333 43 323 curveto + closepath + 285 363 moveto + 237 363 199.333 346.333 172 313 curveto + 149.333 286.333 138 253.333 138 214 curveto + 138 166 153.333 126.667 184 96 curveto + 210.667 68.6667 243.333 55 282 55 curveto + 324 55 358.667 70.6667 386 102 curveto + 410.667 131.333 423 167 423 209 curveto + 423 267.667 405 310.333 369 337 curveto + 345.667 354.333 317.667 363 285 363 curveto + closepath + } bind def + /seven { 555 0 46 0 520 709 setcachedevice + 520 709 moveto + 520 635 lineto + 407.333 485 326.667 336.333 278 189 curveto + 258.667 128.333 243.333 65.3333 232 0 curveto + 138 0 lineto + 166 123.333 202.667 231.667 248 325 curveto + 289.333 409.667 349.667 508.667 429 622 curveto + 46 622 lineto + 46 709 lineto + 520 709 lineto + closepath + } bind def + /eight { 555 0 37 -23 513 709 setcachedevice + 391 373 moveto + 472.333 334.333 513 275.333 513 196 curveto + 513 132.667 491.667 81 449 41 curveto + 405.667 -0.333333 349.333 -21.6667 280 -23 curveto + 275 -23 lineto + 205 -23 148 -2.66667 104 38 curveto + 60.6667 80.6667 38.3333 133.667 37 197 curveto + 37 275 77.3333 333.667 158 373 curveto + 117.333 399 90.3333 424.333 77 449 curveto + 67 468.333 62 492 62 520 curveto + 62 575.333 81.8333 620.667 121.5 656 curveto + 161.167 691.333 212.333 709 275 709 curveto + 340.333 709 392.667 690.333 432 653 curveto + 469.333 618.333 488 574 488 520 curveto + 488 480.667 478 449.333 458 426 curveto + 443.333 408.667 421 391 391 373 curveto + closepath + 275 631 moveto + 229.667 631 196 616.333 174 587 curveto + 159.333 568.333 152 545.667 152 519 curveto + 152 479 167.333 449 198 429 curveto + 218.667 415 244.333 408 275 408 curveto + 320.333 408 354 422.333 376 451 curveto + 390.667 469.667 398 492 398 518 curveto + 398 560.667 382 592 350 612 curveto + 329.333 624.667 304.333 631 275 631 curveto + closepath + 275 334 moveto + 225 334 186.333 318 159 286 curveto + 137.667 261.333 127 231 127 195 curveto + 127 149 143 113 175 87 curveto + 201.667 65.6667 234.333 55 273 55 curveto + 325 55 364.667 71.3333 392 104 curveto + 412.667 128.667 423 159 423 195 curveto + 423 241 406.333 277 373 303 curveto + 346.333 323.667 313.667 334 275 334 curveto + closepath + } bind def + /nine { 555 0 38 -23 509 709 setcachedevice + 509 363 moveto + 509 180.333 463.667 62 373 8 curveto + 338.333 -12.6667 298.667 -23 254 -23 curveto + 189.333 -23 138.333 -0.333333 101 45 curveto + 75.6667 76.3333 59.6667 115.333 53 162 curveto + 141 162 lineto + 151 112.667 174.333 80 211 64 curveto + 225.667 58 242 55 260 55 curveto + 322.667 55 367.333 90.6667 394 162 curveto + 409.333 205.333 417.333 259.333 418 324 curveto + 382 281.333 341 256 295 248 curveto + 283 246 270 245 256 245 curveto + 192.667 245 140.667 265.667 100 307 curveto + 59.3333 350.333 38.6667 404.667 38 470 curveto + 38 536.667 58.3333 592.333 99 637 curveto + 139 681 190.333 704.667 253 708 curveto + 258.333 708.667 264 709 270 709 curveto + 404.667 709 482.333 625.667 503 459 curveto + 507 429.667 509 397.667 509 363 curveto + closepath + 269 632 moveto + 226.333 632 191.667 616 165 584 curveto + 140.333 555.333 128 519.667 128 477 curveto + 128 419 146 376.333 182 349 curveto + 204.667 331.667 232.667 323 266 323 curveto + 312.667 323 349.667 339 377 371 curveto + 401 398.333 413 432 413 472 curveto + 413 520.667 398 560.333 368 591 curveto + 340.667 618.333 307.667 632 269 632 curveto + closepath + } bind def + /colon { 277 0 110 0 214 524 setcachedevice + 214 104 moveto + 214 0 lineto + 110 0 lineto + 110 104 lineto + 214 104 lineto + closepath + 214 524 moveto + 214 420 lineto + 110 420 lineto + 110 524 lineto + 214 524 lineto + closepath + } bind def + /semicolon { 277 0 110 -147 215 524 setcachedevice + 215 524 moveto + 215 420 lineto + 111 420 lineto + 111 524 lineto + 215 524 lineto + closepath + 110 104 moveto + 215 104 lineto + 215 -16 lineto + 215 -103.333 180 -147 110 -147 curveto + 110 -109 lineto + 134.667 -107.667 151 -100 159 -86 curveto + 166.333 -73.3333 170 -50.6667 170 -18 curveto + 170 0 lineto + 110 0 lineto + 110 104 lineto + closepath + } bind def + /less { 583 0 45 -9 534 474 setcachedevice + 45 198 moveto + 45 267 lineto + 534 474 lineto + 534 395 lineto + 140 234 lineto + 534 70 lineto + 534 -9 lineto + 45 198 lineto + closepath + } bind def + /equal { 583 0 50 111 534 353 setcachedevice + 534 353 moveto + 534 283 lineto + 50 283 lineto + 50 353 lineto + 534 353 lineto + closepath + 534 181 moveto + 534 111 lineto + 50 111 lineto + 50 181 lineto + 534 181 lineto + closepath + } bind def + /greater { 583 0 50 -9 539 474 setcachedevice + 539 267 moveto + 539 198 lineto + 50 -9 lineto + 50 70 lineto + 444 231 lineto + 50 395 lineto + 50 474 lineto + 539 267 lineto + closepath + } bind def + /question { 555 0 77 0 509 741 setcachedevice + 509 549 moveto + 509 499 491 454.333 455 415 curveto + 446.333 405.667 427.333 387.667 398 361 curveto + 369.333 335 350.333 312.667 341 294 curveto + 333.667 278.667 330 262.667 330 246 curveto + 330 199 lineto + 240 199 lineto + 240 254 lineto + 240 292.667 256.667 330.333 290 367 curveto + 345 420 lineto + 377 449.333 398 475 408 497 curveto + 415.333 513 419 530.333 419 549 curveto + 419 589 403.667 619.667 373 641 curveto + 350.333 655.667 323 663 291 663 curveto + 227 663 187 636.667 171 584 curveto + 165 563.333 162 537.667 162 507 curveto + 77 507 lineto + 77 630.333 123.667 705 217 731 curveto + 240.333 737.667 266.667 741 296 741 curveto + 367.333 741 422.333 720.333 461 679 curveto + 493 645 509 601.667 509 549 curveto + closepath + 330 104 moveto + 330 0 lineto + 240 0 lineto + 240 104 lineto + 330 104 lineto + closepath + } bind def + /at { 1014 0 34 -142 951 741 setcachedevice + 665 501 moveto + 748 501 lineto + 658 221 lineto + 650 199 646 182.333 646 171 curveto + 646 155.667 653.333 143.333 668 134 curveto + 676.667 129.333 686 127 696 127 curveto + 732 127 766 145 798 181 curveto + 830.667 217.667 851.333 262 860 314 curveto + 862.667 328 864 342.333 864 357 curveto + 864 424.333 840 485.667 792 541 curveto + 746.667 593 688.667 629 618 649 curveto + 583.333 659 548 664 512 664 curveto + 430 664 354.333 639 285 589 curveto + 222.333 543 176.333 485 147 415 curveto + 128.333 369 119 321.667 119 273 curveto + 119 193.667 144.667 124 196 64 curveto + 245.333 6.66667 309.333 -32 388 -52 curveto + 422 -60.6667 457.333 -65 494 -65 curveto + 547.333 -65 611.667 -54.3333 687 -33 curveto + 715 -100 lineto + 640.333 -128 565 -142 489 -142 curveto + 387.667 -142 297 -115.667 217 -63 curveto + 146.333 -17 95.3333 42.3333 64 115 curveto + 44 160.333 34 208 34 258 curveto + 34 343.333 57 424.667 103 502 curveto + 127.667 544 157.333 580.667 192 612 curveto + 251.333 666 322 703.667 404 725 curveto + 444.667 735.667 485 741 525 741 curveto + 618.333 741 702.667 716.333 778 667 curveto + 844.667 623 893 567.333 923 500 curveto + 941.667 458 951 414.333 951 369 curveto + 951 303 931 240 891 180 curveto + 883 168 874.333 156.667 865 146 curveto + 815 86.6667 753 57 679 57 curveto + 615 57 578.333 82.6667 569 134 curveto + 531 92.6667 491.333 69 450 63 curveto + 442 62.3333 434.333 62 427 62 curveto + 381 62 342.667 79.3333 312 114 curveto + 280 149.333 264 193 264 245 curveto + 264 306.333 283.667 363 323 415 curveto + 358.333 461.667 401.667 493.667 453 511 curveto + 475.667 518.333 498.333 522 521 522 curveto + 577 522 617.667 493 643 435 curveto + 665 501 lineto + closepath + 453 126 moveto + 492.333 126 527.667 151 559 201 curveto + 584.333 241.667 600 286.667 606 336 curveto + 608 348 609 358.667 609 368 curveto + 609 398 597.333 421.667 574 439 curveto + 557.333 451.667 537.667 458 515 458 curveto + 477.667 458 443.667 440.333 413 405 curveto + 381.667 369 362.667 325.667 356 275 curveto + 354.667 264.333 354 254 354 244 curveto + 354 206.667 365.667 176.333 389 153 curveto + 407.667 135 429 126 453 126 curveto + closepath + } bind def + /A { 666 0 17 0 653 729 setcachedevice + 474 219 moveto + 193 219 lineto + 116 0 lineto + 17 0 lineto + 277 729 lineto + 397 729 lineto + 653 0 lineto + 549 0 lineto + 474 219 lineto + closepath + 448 297 moveto + 336 629 lineto + 216 297 lineto + 448 297 lineto + closepath + } bind def + /B { 666 0 79 0 623 729 setcachedevice + 623 208 moveto + 623 143.333 602 91.6667 560 53 curveto + 520.667 17.6667 470 1.73472e-18 408 0 curveto + 79 0 lineto + 79 729 lineto + 375 729 lineto + 465.667 729 528.667 699.667 564 641 curveto + 582 612.333 591 580 591 544 curveto + 591 470 557.333 417 490 385 curveto + 552 361.667 591.667 328.333 609 285 curveto + 618.333 263 623 237.333 623 208 curveto + closepath + 498 531 moveto + 498 596.333 464 634 396 644 curveto + 382.667 646 368 647 352 647 curveto + 172 647 lineto + 172 415 lineto + 352 415 lineto + 432.667 415 480 441 494 493 curveto + 496.667 504.333 498 517 498 531 curveto + closepath + 399 82 moveto + 459 82 499 104.667 519 150 curveto + 526.333 167.333 530 186.333 530 207 curveto + 530 254.333 513 289.333 479 312 curveto + 457.667 326 431 333 399 333 curveto + 172 333 lineto + 172 82 lineto + 399 82 lineto + closepath + } bind def + /C { 721 0 48 -23 677 741 setcachedevice + 48 356 moveto + 48 438 64.3333 511 97 575 curveto + 144.333 667.667 219.333 721.667 322 737 curveto + 340.667 739.667 360.333 741 381 741 curveto + 517 741 605.333 683 646 567 curveto + 652.667 547.667 658 526.333 662 503 curveto + 567 503 lineto + 551.667 577.667 515 625.333 457 646 curveto + 432.333 654.667 403.333 659 370 659 curveto + 298 659 241.333 631 200 575 curveto + 160.667 521 141 448.333 141 357 curveto + 141 261 164.667 186 212 132 curveto + 254 83.3333 309.333 59 378 59 curveto + 454.667 59 509.667 88 543 146 curveto + 560.333 176.667 573 216.667 581 266 curveto + 677 266 lineto + 655 73.3333 555 -23 377 -23 curveto + 257 -23 168 23.3333 110 116 curveto + 72 177.333 51.3333 251 48 337 curveto + 48 356 lineto + closepath + } bind def + /D { 721 0 89 0 667 729 setcachedevice + 89 0 moveto + 89 729 lineto + 370 729 lineto + 462 729 534.5 696.667 587.5 632 curveto + 640.5 567.333 667 478.333 667 365 curveto + 667 247 638.667 155.333 582 90 curveto + 528.667 30 458 0 370 0 curveto + 89 0 lineto + closepath + 182 82 moveto + 354 82 lineto + 452.667 82 518.333 126.333 551 215 curveto + 566.333 255.667 574 305.333 574 364 curveto + 574 504 532.333 592.333 449 629 curveto + 421.667 641 390 647 354 647 curveto + 182 647 lineto + 182 82 lineto + closepath + } bind def + /E { 666 0 90 0 613 729 setcachedevice + 183 332 moveto + 183 82 lineto + 613 82 lineto + 613 0 lineto + 90 0 lineto + 90 729 lineto + 595 729 lineto + 595 647 lineto + 183 647 lineto + 183 414 lineto + 580 414 lineto + 580 332 lineto + 183 332 lineto + closepath + } bind def + /F { 610 0 90 0 579 729 setcachedevice + 183 332 moveto + 183 0 lineto + 90 0 lineto + 90 729 lineto + 579 729 lineto + 579 647 lineto + 183 647 lineto + 183 414 lineto + 531 414 lineto + 531 332 lineto + 183 332 lineto + closepath + } bind def + /G { 777 0 44 -23 709 741 setcachedevice + 137 362 moveto + 137 294 151.333 234 180 182 curveto + 224.667 102 295 61 391 59 curveto + 398 59 lineto + 462.667 59 516.333 79 559 119 curveto + 601 158.333 623.333 208.667 626 270 curveto + 626.667 274.667 627 279 627 283 curveto + 627 303 lineto + 405 303 lineto + 405 385 lineto + 709 385 lineto + 709 -4 lineto + 650 -4 lineto + 627 93 lineto + 565 24.3333 493.333 -13.6667 412 -21 curveto + 400.667 -22.3333 389.333 -23 378 -23 curveto + 292 -23 219 5 159 61 curveto + 100.333 115 64 187.333 50 278 curveto + 46 303.333 44 329.667 44 357 curveto + 44 433 59.6667 502.333 91 565 curveto + 137 656.333 209.667 712.333 309 733 curveto + 335.667 738.333 364 741 394 741 curveto + 494.667 741 572.667 712 628 654 curveto + 665.333 616 689 567.333 699 508 curveto + 604 508 lineto + 592 563.333 562 604.333 514 631 curveto + 479.333 649.667 439 659 393 659 curveto + 318.333 659 257.667 633.667 211 583 curveto + 163.667 529.667 139 458.667 137 370 curveto + 137 362 lineto + closepath + } bind def + /H { 721 0 83 0 644 729 setcachedevice + 551 332 moveto + 176 332 lineto + 176 0 lineto + 83 0 lineto + 83 729 lineto + 176 729 lineto + 176 414 lineto + 551 414 lineto + 551 729 lineto + 644 729 lineto + 644 0 lineto + 551 0 lineto + 551 332 lineto + closepath + } bind def + /I { 277 0 100 0 194 729 setcachedevice + 194 729 moveto + 194 0 lineto + 100 0 lineto + 100 729 lineto + 194 729 lineto + closepath + } bind def + /J { 500 0 17 -23 426 729 setcachedevice + 221 55 moveto + 275.667 55 310 81 324 133 curveto + 330 155 333 182.667 333 216 curveto + 333 729 lineto + 426 729 lineto + 426 182 lineto + 426 112.667 403.667 59.3333 359 22 curveto + 323 -8 276.667 -23 220 -23 curveto + 150.667 -23 97.6667 -1.66667 61 41 curveto + 31.6667 74.3333 17 117.333 17 170 curveto + 17 234 lineto + 112 234 lineto + 112 187 lineto + 112 122.333 132.667 81.3333 174 64 curveto + 188 58 203.667 55 221 55 curveto + closepath + } bind def + /K { 666 0 79 0 658 729 setcachedevice + 172 255 moveto + 172 0 lineto + 79 0 lineto + 79 729 lineto + 172 729 lineto + 172 360 lineto + 535 729 lineto + 655 729 lineto + 358 432 lineto + 658 0 lineto + 548 0 lineto + 291 374 lineto + 172 255 lineto + closepath + } bind def + /L { 555 0 80 0 533 729 setcachedevice + 173 729 moveto + 173 82 lineto + 533 82 lineto + 533 0 lineto + 80 0 lineto + 80 729 lineto + 173 729 lineto + closepath + } bind def + /M { 832 0 75 0 761 729 setcachedevice + 468 0 moveto + 370 0 lineto + 163 611 lineto + 163 0 lineto + 75 0 lineto + 75 729 lineto + 204 729 lineto + 420 94 lineto + 632 729 lineto + 761 729 lineto + 761 0 lineto + 673 0 lineto + 673 611 lineto + 468 0 lineto + closepath + } bind def + /N { 721 0 76 0 646 729 setcachedevice + 646 729 moveto + 646 0 lineto + 541 0 lineto + 164 591 lineto + 164 0 lineto + 76 0 lineto + 76 729 lineto + 177 729 lineto + 558 133 lineto + 558 729 lineto + 646 729 lineto + closepath + } bind def + /O { 777 0 38 -23 742 741 setcachedevice + 742 353 moveto + 742 259 717.667 178.667 669 112 curveto + 620.333 45.3333 555 3.33333 473 -14 curveto + 446.333 -20 418.667 -23 390 -23 curveto + 296.667 -23 218.333 5.66667 155 63 curveto + 93.6667 119 56.3333 194 43 288 curveto + 39.6667 310.667 38 334.333 38 359 curveto + 38 463 65.3333 549.333 120 618 curveto + 171.333 682 239 721.333 323 736 curveto + 344.333 739.333 366.333 741 389 741 curveto + 487 741 567.667 711 631 651 curveto + 693 591 729.333 510 740 408 curveto + 741.333 390 742 371.667 742 353 curveto + closepath + 389 659 moveto + 315.667 659 255.333 634 208 584 curveto + 160 532 134.333 463 131 377 curveto + 131 359 lineto + 131 270.333 154.333 198.667 201 144 curveto + 245 91.3333 303 63.3333 375 60 curveto + 379.667 59.3333 384.667 59 390 59 curveto + 462.667 59 522.333 83.6667 569 133 curveto + 617 182.333 643.333 248 648 330 curveto + 648.667 338 649 346.333 649 355 curveto + 649 448.333 625 522.667 577 578 curveto + 527.667 631.333 465 658.333 389 659 curveto + closepath + } bind def + /P { 666 0 91 0 617 729 setcachedevice + 617 515 moveto + 617 450.333 596.667 399 556 361 curveto + 518.667 326.333 471 309 413 309 curveto + 184 309 lineto + 184 0 lineto + 91 0 lineto + 91 729 lineto + 392 729 lineto + 482.667 729 546.667 700.333 584 643 curveto + 606 608.333 617 565.667 617 515 curveto + closepath + 184 391 moveto + 378 391 lineto + 435.333 391 476 409.333 500 446 curveto + 513.333 466.667 520 491 520 519 curveto + 520 569.667 500.667 605.667 462 627 curveto + 439.333 640.333 411.333 647 378 647 curveto + 184 647 lineto + 184 391 lineto + closepath + } bind def + /Q { 777 0 38 -59 742 741 setcachedevice + 733 -1 moveto + 686 -59 lineto + 581 28 lineto + 523.667 -6 460 -23 390 -23 curveto + 296.667 -23 218.333 5.66667 155 63 curveto + 93.6667 119 56.3333 194 43 288 curveto + 39.6667 310.667 38 334.333 38 359 curveto + 38 463 65.3333 549.333 120 618 curveto + 171.333 682 239.333 721.333 324 736 curveto + 345.333 739.333 367.333 741 390 741 curveto + 483.333 741 561.667 712.667 625 656 curveto + 685.667 600.667 723 526.667 737 434 curveto + 740.333 410 742 385.667 742 361 curveto + 742 246.333 707.667 151.333 639 76 curveto + 733 -1 lineto + closepath + 481 205 moveto + 570 132 lineto + 622.667 191.333 649 267.333 649 360 curveto + 649 448 626 519.333 580 574 curveto + 536 626.667 478 655 406 659 curveto + 390 659 lineto + 316 659 255.333 633.667 208 583 curveto + 160 531.667 134.333 462.667 131 376 curveto + 131 359 lineto + 131 269.667 154.333 197.667 201 143 curveto + 245.667 90.3333 304 62.6667 376 60 curveto + 380.667 59.3333 385 59 389 59 curveto + 427 59 464 67 500 83 curveto + 502.667 84.3333 505.667 85.6667 509 87 curveto + 435 149 lineto + 481 205 lineto + closepath + } bind def + /R { 721 0 93 0 679 729 setcachedevice + 536 360 moveto + 587.333 338 618.667 303.333 630 256 curveto + 634.667 236 636.667 203.667 636 159 curveto + 635.333 117 638.333 86.6667 645 68 curveto + 651.667 49.3333 663 34.3333 679 23 curveto + 679 0 lineto + 566 0 lineto + 552.667 31.3333 546 71 546 119 curveto + 546 184 lineto + 546 247.333 526 287.333 486 304 curveto + 469.333 310.667 449.333 314 426 314 curveto + 186 314 lineto + 186 0 lineto + 93 0 lineto + 93 729 lineto + 429 729 lineto + 525.667 729 591 699.333 625 640 curveto + 642.333 610.667 651 575.333 651 534 curveto + 651 478.667 634.333 435 601 403 curveto + 584.333 387 562.667 372.667 536 360 curveto + closepath + 554 521 moveto + 554 586.333 527 626 473 640 curveto + 455.667 644.667 435 647 411 647 curveto + 186 647 lineto + 186 396 lineto + 411 396 lineto + 482.333 396 526.667 417.667 544 461 curveto + 550.667 477.667 554 497.667 554 521 curveto + closepath + } bind def + /S { 666 0 48 -23 621 741 setcachedevice + 342 59 moveto + 436 59 494.667 86.3333 518 141 curveto + 524.667 156.333 528 173 528 191 curveto + 528 235 501 268.667 447 292 curveto + 431.667 298 414 303.667 394 309 curveto + 213 357 lineto + 117.667 381.667 70 438.333 70 527 curveto + 70 597 95.6667 651 147 689 curveto + 193 723.667 253.667 741 329 741 curveto + 428.333 741 501 714 547 660 curveto + 579.667 622 596 573.667 596 515 curveto + 508 515 lineto + 507.333 577.667 480 621 426 645 curveto + 398.667 657 365.333 663 326 663 curveto + 268 663 224 647.667 194 617 curveto + 173.333 595.667 163 570 163 540 curveto + 163 508 175.333 483.333 200 466 curveto + 218 453.333 245.667 442 283 432 curveto + 466 383 lineto + 534 364.333 580 329.333 604 278 curveto + 615.333 254.667 621 228.667 621 200 curveto + 621 148.667 605 103.667 573 65 curveto + 524.333 6.33333 445.333 -23 336 -23 curveto + 243.333 -23 171.667 0 121 46 curveto + 73 89.3333 48.6667 151.333 48 232 curveto + 136 232 lineto + 136 227 lineto + 136 173 155 131 193 101 curveto + 228.333 73 278 59 342 59 curveto + closepath + } bind def + /T { 610 0 21 0 593 729 setcachedevice + 354 647 moveto + 354 0 lineto + 261 0 lineto + 261 647 lineto + 21 647 lineto + 21 729 lineto + 593 729 lineto + 593 647 lineto + 354 647 lineto + closepath + } bind def + /U { 721 0 85 -23 645 729 setcachedevice + 552 729 moveto + 645 729 lineto + 645 217 lineto + 645 143.667 619.333 85.3333 568 42 curveto + 517.333 -1.33333 449.333 -23 364 -23 curveto + 270 -23 198 2 148 52 curveto + 106 94 85 149 85 217 curveto + 85 729 lineto + 178 729 lineto + 178 217 lineto + 178 149 206.333 102.667 263 78 curveto + 291 65.3333 324.667 59 364 59 curveto + 434.667 59 486.667 79 520 119 curveto + 541.333 145 552 177.667 552 217 curveto + 552 729 lineto + closepath + } bind def + /V { 666 0 30 0 645 729 setcachedevice + 392 0 moveto + 292 0 lineto + 30 729 lineto + 130 729 lineto + 344 112 lineto + 546 729 lineto + 645 729 lineto + 392 0 lineto + closepath + } bind def + /W { 943 0 22 0 929 729 setcachedevice + 744 0 moveto + 642 0 lineto + 474 599 lineto + 311 0 lineto + 209 0 lineto + 22 729 lineto + 126 729 lineto + 263 137 lineto + 425 729 lineto + 525 729 lineto + 691 137 lineto + 825 729 lineto + 929 729 lineto + 744 0 lineto + closepath + } bind def + /X { 666 0 22 0 649 729 setcachedevice + 391 374 moveto + 649 0 lineto + 534 0 lineto + 335 304 lineto + 135 0 lineto + 22 0 lineto + 280 374 lineto + 38 729 lineto + 151 729 lineto + 338 443 lineto + 526 729 lineto + 637 729 lineto + 391 374 lineto + closepath + } bind def + /Y { 666 0 13 0 661 729 setcachedevice + 387 286 moveto + 387 0 lineto + 294 0 lineto + 294 286 lineto + 13 729 lineto + 128 729 lineto + 342 374 lineto + 550 729 lineto + 661 729 lineto + 387 286 lineto + closepath + } bind def + /Z { 610 0 28 0 583 729 setcachedevice + 581 729 moveto + 581 645 lineto + 145 82 lineto + 583 82 lineto + 583 0 lineto + 28 0 lineto + 28 82 lineto + 466 647 lineto + 56 647 lineto + 56 729 lineto + 581 729 lineto + closepath + } bind def + /bracketleft { 277 0 64 -212 250 729 setcachedevice + 250 729 moveto + 250 657 lineto + 147 657 lineto + 147 -140 lineto + 250 -140 lineto + 250 -212 lineto + 64 -212 lineto + 64 729 lineto + 250 729 lineto + closepath + } bind def + /backslash { 277 0 -8 -20 284 729 setcachedevice + 47 729 moveto + 284 -20 lineto + 229 -20 lineto + -8 729 lineto + 47 729 lineto + closepath + } bind def + /bracketright { 277 0 23 -212 209 729 setcachedevice + 23 -212 moveto + 23 -140 lineto + 126 -140 lineto + 126 657 lineto + 23 657 lineto + 23 729 lineto + 209 729 lineto + 209 -212 lineto + 23 -212 lineto + closepath + } bind def + /asciicircum { 468 0 44 329 425 709 setcachedevice + 197 709 moveto + 270 709 lineto + 425 329 lineto + 356 329 lineto + 234 629 lineto + 113 329 lineto + 44 329 lineto + 197 709 lineto + closepath + } bind def + /underscore { 555 0 -22 -176 578 -126 setcachedevice + 578 -126 moveto + 578 -176 lineto + -22 -176 lineto + -22 -126 lineto + 578 -126 lineto + closepath + } bind def + /grave { 332 0 22 592 231 740 setcachedevice + 135 740 moveto + 231 592 lineto + 171 592 lineto + 22 740 lineto + 135 740 lineto + closepath + } bind def + /a { 555 0 42 -23 535 539 setcachedevice + 65 369 moveto + 68.3333 468.333 122.667 524.333 228 537 curveto + 242.667 538.333 258.333 539 275 539 curveto + 374.333 539 436.333 510.667 461 454 curveto + 468.333 437.333 472 418 472 396 curveto + 472 88 lineto + 472 64.6667 483.333 51.3333 506 48 curveto + 509.333 47.3333 513 47 517 47 curveto + 523 47 529 47.6667 535 49 curveto + 535 -14 lineto + 511.667 -20 492.667 -23 478 -23 curveto + 436.667 -23 410.333 -7.66667 399 23 curveto + 395.667 32.3333 393.333 42.6667 392 54 curveto + 345.333 11.3333 298 -13.6667 250 -21 curveto + 238 -22.3333 226 -23 214 -23 curveto + 151.333 -23 104.667 -4 74 34 curveto + 52.6667 60 42 92.6667 42 132 curveto + 42 189.333 61.3333 230.333 100 255 curveto + 127.333 272.333 173.333 285.667 238 295 curveto + 250 297 271.333 300 302 304 curveto + 344.667 309.333 371.333 319.333 382 334 curveto + 386.667 341.333 389 350.667 389 362 curveto + 389 384 lineto + 389 420.667 368 444.667 326 456 curveto + 310 460 292 462 272 462 curveto + 212.667 462 175 443.667 159 407 curveto + 153.667 396.333 150.333 383.667 149 369 curveto + 65 369 lineto + closepath + 232 50 moveto + 282.667 50 323.667 65 355 95 curveto + 377.667 117 389 140.333 389 165 curveto + 389 259 lineto + 371 251 337.333 243 288 235 curveto + 236.667 227.667 201.333 219.667 182 211 curveto + 146.667 195 129 169.333 129 134 curveto + 129 97.3333 145.667 72.3333 179 59 curveto + 193.667 53 211.333 50 232 50 curveto + closepath + } bind def + /b { 555 0 54 -23 523 729 setcachedevice + 54 729 moveto + 137 729 lineto + 137 453 lineto + 171 505 217.667 533.333 277 538 curveto + 284.333 538.667 291.667 539 299 539 curveto + 371 539 427 512.333 467 459 curveto + 504.333 410.333 523 345.333 523 264 curveto + 523 172.667 500.667 101 456 49 curveto + 414.667 1 361 -23 295 -23 curveto + 225.667 -23 171.667 5 133 61 curveto + 129 67 lineto + 129 0 lineto + 54 0 lineto + 54 729 lineto + closepath + 283 461 moveto + 235.667 461 198.667 440 172 398 curveto + 148.667 362 137 315.333 137 258 curveto + 137 186.667 154.333 132.333 189 95 curveto + 214.333 68.3333 245.667 55 283 55 curveto + 330.333 55 368 74.6667 396 114 curveto + 422.667 150.667 436 197.667 436 255 curveto + 436 327 418 381.667 382 419 curveto + 356 447 323 461 283 461 curveto + closepath + } bind def + /c { 500 0 31 -23 477 539 setcachedevice + 471 348 moveto + 387 348 lineto + 379 403.333 354 438.667 312 454 curveto + 297.333 459.333 281 462 263 462 curveto + 209.667 462 170.333 437 145 387 curveto + 127 351.667 118 307 118 253 curveto + 118 175 138 118.667 178 84 curveto + 201.333 64 230.333 54 265 54 curveto + 336.333 54 379 96 393 180 curveto + 477 180 lineto + 471 102 441.333 45.6667 388 11 curveto + 354 -11.6667 312.333 -23 263 -23 curveto + 191 -23 134 2.66667 92 54 curveto + 51.3333 103.333 31 169.667 31 253 curveto + 31 343 53.6667 414 99 466 curveto + 141 514.667 196 539 264 539 curveto + 343.333 539 400.667 512 436 458 curveto + 456 428.667 467.667 392 471 348 curveto + closepath + } bind def + /d { 555 0 26 -23 495 729 setcachedevice + 495 729 moveto + 495 0 lineto + 421 0 lineto + 421 69 lineto + 389 23 351.333 -5.66667 308 -17 curveto + 292 -21 274 -23 254 -23 curveto + 180.667 -23 123.333 4.66667 82 60 curveto + 44.6667 110.667 26 178.333 26 263 curveto + 26 349.667 48 418.333 92 469 curveto + 132.667 515.667 185.667 539 251 539 curveto + 319.667 539 372 514 408 464 curveto + 412 458 lineto + 412 729 lineto + 495 729 lineto + closepath + 265 461 moveto + 217 461 179 440.667 151 400 curveto + 125.667 363.333 113 316 113 258 curveto + 113 189.333 130.333 136.333 165 99 curveto + 192.333 69.6667 226 55 266 55 curveto + 312.667 55 349.333 75.3333 376 116 curveto + 400 152 412 198.667 412 256 curveto + 412 329.333 394 384.667 358 422 curveto + 333.333 448 302.333 461 265 461 curveto + closepath + } bind def + /e { 555 0 40 -23 513 539 setcachedevice + 513 234 moveto + 127 234 lineto + 127.667 190.667 134.333 157.333 147 134 curveto + 155 122 lineto + 180.333 82 216.667 59.6667 264 55 curveto + 269.333 54.3333 275 54 281 54 curveto + 349 54 394.667 89 418 159 curveto + 502 159 lineto + 489.333 90.3333 456.333 40.3333 403 9 curveto + 367.667 -12.3333 326 -23 278 -23 curveto + 201.333 -23 141.667 4 99 58 curveto + 59.6667 107.333 40 173 40 255 curveto + 40 343.667 63 414 109 466 curveto + 152.333 514.667 209.333 539 280 539 curveto + 344 539 397.333 519 440 479 curveto + 462.667 457 480 431 492 401 curveto + 506 363.667 513 308 513 234 curveto + closepath + 129 302 moveto + 423 302 lineto + 423.667 303.333 424 305.333 424 308 curveto + 424 352.667 409.333 389.667 380 419 curveto + 352 447.667 318.333 462 279 462 curveto + 230.333 462 192 443 164 405 curveto + 144 377.667 132.333 343.333 129 302 curveto + closepath + } bind def + /f { 277 0 18 0 258 732 setcachedevice + 258 524 moveto + 258 456 lineto + 171 456 lineto + 171 0 lineto + 88 0 lineto + 88 456 lineto + 18 456 lineto + 18 524 lineto + 88 524 lineto + 88 613 lineto + 88 663 106.667 697.667 144 717 curveto + 162.667 727 185 732 211 732 curveto + 226.333 732 242 730.333 258 727 curveto + 258 658 lineto + 245.333 658.667 235.667 659 229 659 curveto + 190.333 659 171 641.333 171 606 curveto + 171 524 lineto + 258 524 lineto + closepath + } bind def + /g { 555 0 29 -218 489 539 setcachedevice + 245 -23 moveto + 189 -23 141.333 -2 102 40 curveto + 57.3333 87.3333 33 151.333 29 232 curveto + 29 253 lineto + 29 338.333 49.6667 407.667 91 461 curveto + 130.333 510.333 181 536.333 243 539 curveto + 252 539 lineto + 316 539 368.333 510.333 409 453 curveto + 410.333 451.667 411.333 450 412 448 curveto + 412 524 lineto + 489 524 lineto + 489 86 lineto + 489 -6.66667 477.667 -75 455 -119 curveto + 425.667 -176.333 372 -208.667 294 -216 curveto + 281.333 -217.333 268.333 -218 255 -218 curveto + 175.667 -218 118 -195.667 82 -151 curveto + 61.3333 -126.333 49.3333 -96 46 -60 curveto + 131 -60 lineto + 139 -107.333 169.333 -135.667 222 -145 curveto + 232.667 -147 244.667 -148 258 -148 curveto + 320 -148 361.333 -126.667 382 -84 curveto + 396.667 -56 404 -13.3333 404 44 curveto + 404 71 lineto + 371.333 25 336.333 -4 299 -16 curveto + 282.333 -20.6667 264.333 -23 245 -23 curveto + closepath + 261 462 moveto + 211.667 462 173.667 439.667 147 395 curveto + 126.333 359.667 116 314 116 258 curveto + 116 178.667 135.667 121.333 175 86 curveto + 198.333 64.6667 227.333 54 262 54 curveto + 312.667 54 350.333 77 375 123 curveto + 394.333 157 404 201 404 255 curveto + 404 341 383 401 341 435 curveto + 319 453 292.333 462 261 462 curveto + closepath + } bind def + /h { 555 0 70 0 486 729 setcachedevice + 403 363 moveto + 403 409.667 383.333 441 344 457 curveto + 328.667 463 312.333 466 295 466 curveto + 247.667 466 211 447 185 409 curveto + 163.667 377 153 337 153 289 curveto + 153 0 lineto + 70 0 lineto + 70 729 lineto + 153 729 lineto + 153 452 lineto + 183.667 492 215.667 517.667 249 529 curveto + 269 535.667 293 539 321 539 curveto + 383 539 428.333 520.667 457 484 curveto + 476.333 460 486 430.667 486 396 curveto + 486 0 lineto + 403 0 lineto + 403 363 lineto + closepath + } bind def + /i { 221 0 66 0 150 729 setcachedevice + 150 729 moveto + 150 624 lineto + 66 624 lineto + 66 729 lineto + 150 729 lineto + closepath + 150 524 moveto + 150 0 lineto + 67 0 lineto + 67 524 lineto + 150 524 lineto + closepath + } bind def + /j { 221 0 -18 -218 153 729 setcachedevice + 153 729 moveto + 153 624 lineto + 70 624 lineto + 70 729 lineto + 153 729 lineto + closepath + 70 524 moveto + 153 524 lineto + 153 -109 lineto + 153 -169 119.333 -204.333 52 -215 curveto + 39.3333 -217 25.3333 -218 10 -218 curveto + 1.33333 -218 -8 -217 -18 -215 curveto + -18 -144 lineto + -6.66667 -144.667 -4.33681e-19 -145 2 -145 curveto + 32 -145 51.6667 -137.667 61 -123 curveto + 67 -112.333 70 -96.6667 70 -76 curveto + 70 524 lineto + closepath + } bind def + /k { 500 0 58 0 502 729 setcachedevice + 141 729 moveto + 141 302 lineto + 363 524 lineto + 470 524 lineto + 288 343 lineto + 502 0 lineto + 399 0 lineto + 222 284 lineto + 141 204 lineto + 141 0 lineto + 58 0 lineto + 58 729 lineto + 141 729 lineto + closepath + } bind def + /l { 221 0 68 0 152 729 setcachedevice + 152 729 moveto + 152 0 lineto + 68 0 lineto + 68 729 lineto + 152 729 lineto + closepath + } bind def + /m { 832 0 70 0 762 539 setcachedevice + 70 524 moveto + 147 524 lineto + 147 450 lineto + 177 492.667 210.667 519.667 248 531 curveto + 265.333 536.333 285.333 539 308 539 curveto + 359.333 539 398.667 523.667 426 493 curveto + 434 483.667 441.667 472.333 449 459 curveto + 479.667 495.667 511 519.333 543 530 curveto + 561.667 536 584 539 610 539 curveto + 678.667 539 724.667 514.667 748 466 curveto + 757.333 445.333 762 421 762 393 curveto + 762 0 lineto + 678 0 lineto + 678 361 lineto + 678 407 662 438.333 630 455 curveto + 616 462.333 599.667 466 581 466 curveto + 545.667 466 516 452 492 424 curveto + 469.333 397.333 458 365.667 458 329 curveto + 458 0 lineto + 374 0 lineto + 374 361 lineto + 374 411.667 355.667 444 319 458 curveto + 307 463.333 293 466 277 466 curveto + 241.667 466 212 452 188 424 curveto + 165.333 397.333 154 365.667 154 329 curveto + 154 0 lineto + 70 0 lineto + 70 524 lineto + closepath + } bind def + /n { 555 0 70 0 487 539 setcachedevice + 70 524 moveto + 147 524 lineto + 147 436 lineto + 177 484 212 515 252 529 curveto + 272 535.667 295 539 321 539 curveto + 380.333 539 425 521.667 455 487 curveto + 476.333 462.333 487 432 487 396 curveto + 487 0 lineto + 404 0 lineto + 404 363 lineto + 404 402.333 389 431.333 359 450 curveto + 341.667 460.667 320.667 466 296 466 curveto + 248.667 466 212 447 186 409 curveto + 164.667 377 154 337 154 289 curveto + 154 0 lineto + 70 0 lineto + 70 524 lineto + closepath + } bind def + /o { 555 0 36 -23 510 539 setcachedevice + 272 539 moveto + 358 539 421.667 507.333 463 444 curveto + 494.333 395.333 510 332 510 254 curveto + 510 159.333 485 87.3333 435 38 curveto + 393.667 -2.66667 339.667 -23 273 -23 curveto + 191.667 -23 130 6.33333 88 65 curveto + 53.3333 113.667 36 178 36 258 curveto + 36 356.667 62 430.667 114 480 curveto + 154.667 519.333 207.333 539 272 539 curveto + closepath + 273 462 moveto + 221 462 181.667 439.667 155 395 curveto + 133.667 359 123 313.333 123 258 curveto + 123 180.667 142.333 124 181 88 curveto + 205.667 65.3333 236.333 54 273 54 curveto + 324.333 54 363.333 76 390 120 curveto + 412 154.667 423 199.667 423 255 curveto + 423 337 402.333 395.667 361 431 curveto + 337 451.667 307.667 462 273 462 curveto + closepath + } bind def + /p { 555 0 54 -218 523 539 setcachedevice + 54 -218 moveto + 54 524 lineto + 131 524 lineto + 131 445 lineto + 170.333 507.667 225.833 539 297.5 539 curveto + 369.167 539 425.333 512 466 458 curveto + 504 406.667 523 338.333 523 253 curveto + 523 166.333 501 97.3333 457 46 curveto + 416.333 0 363.667 -23 299 -23 curveto + 243.667 -23 197.667 -5.33333 161 30 curveto + 153 38 145.333 46.3333 138 55 curveto + 138 -218 lineto + 54 -218 lineto + closepath + 284 461 moveto + 236.667 461 199.667 440 173 398 curveto + 149.667 362 138 315.333 138 258 curveto + 138 186.667 155.333 132.333 190 95 curveto + 215.333 68.3333 246.667 55 284 55 curveto + 331.333 55 369 75 397 115 curveto + 423 151 436 197.667 436 255 curveto + 436 326.333 418.333 380.667 383 418 curveto + 356.333 446.667 323.333 461 284 461 curveto + closepath + } bind def + /q { 555 0 26 -218 495 539 setcachedevice + 495 -218 moveto + 412 -218 lineto + 412 60 lineto + 380.667 14 339.667 -12.6667 289 -20 curveto + 277 -22 264 -23 250 -23 curveto + 178 -23 122 3.66667 82 57 curveto + 44.6667 105.667 26 170.667 26 252 curveto + 26 342 48.3333 413.333 93 466 curveto + 134.333 514.667 188 539 254 539 curveto + 317.333 539 369 516 409 470 curveto + 421 454 lineto + 421 524 lineto + 495 524 lineto + 495 -218 lineto + closepath + 266 461 moveto + 218 461 179.667 440.667 151 400 curveto + 125.667 363.333 113 316 113 258 curveto + 113 189.333 130.333 136.333 165 99 curveto + 192.333 69.6667 226 55 266 55 curveto + 312.667 55 349.333 75.3333 376 116 curveto + 400 152 412 198.333 412 255 curveto + 412 329 394.333 384.667 359 422 curveto + 333.667 448 302.667 461 266 461 curveto + closepath + } bind def + /r { 332 0 69 0 321 539 setcachedevice + 321 451 moveto + 263.667 450.333 222.333 438 197 414 curveto + 167.667 386.667 153 339.333 153 272 curveto + 153 0 lineto + 69 0 lineto + 69 524 lineto + 146 524 lineto + 146 429 lineto + 178.667 481.667 210.333 515 241 529 curveto + 255.667 535.667 271.667 539 289 539 curveto + 296.333 539 307 538 321 536 curveto + 321 451 lineto + closepath + } bind def + /s { 500 0 34 -23 459 539 setcachedevice + 122 156 moveto + 126.667 118.667 139.333 92.3333 160 77 curveto + 180.667 61.6667 210.667 54 250 54 curveto + 298 54 332.667 66 354 90 curveto + 366 103.333 372 118.667 372 136 curveto + 372 162 359 181.333 333 194 curveto + 322.333 200 308.333 205 291 209 curveto + 213 228 lineto + 143.667 244.667 97.3333 266.333 74 293 curveto + 56 314.333 47 343 47 379 curveto + 47 431.667 67.6667 472.333 109 501 curveto + 145.667 526.333 192 539 248 539 curveto + 330 539 386 514 416 464 curveto + 430.667 440 438 411.333 438 378 curveto + 350 378 lineto + 348.667 426.667 321.333 454 268 460 curveto + 260.667 461.333 253 462 245 462 curveto + 198.333 462 165.667 449.333 147 424 curveto + 138.333 412 134 398.333 134 383 curveto + 134 357 150.333 337 183 323 curveto + 196.333 317.667 212.333 312.667 231 308 curveto + 311 289 lineto + 379 273 423 247 443 211 curveto + 453.667 192.333 459 169.667 459 143 curveto + 459 89 437 47 393 17 curveto + 354.333 -9.66667 304.333 -23 243 -23 curveto + 129.667 -23 62.6667 18 42 100 curveto + 37.3333 116.667 34.6667 135.333 34 156 curveto + 122 156 lineto + closepath + } bind def + /t { 277 0 14 -23 254 668 setcachedevice + 254 524 moveto + 254 456 lineto + 168 456 lineto + 168 97 lineto + 168 74.3333 173 60.3333 183 55 curveto + 189.667 51.6667 200 50 214 50 curveto + 231.333 50 244.667 51.3333 254 54 curveto + 254 -16 lineto + 228 -20.6667 205.333 -23 186 -23 curveto + 134.667 -23 102.667 -6 90 28 curveto + 86.6667 37.3333 85 48 85 60 curveto + 85 456 lineto + 14 456 lineto + 14 524 lineto + 85 524 lineto + 85 668 lineto + 168 668 lineto + 168 524 lineto + 254 524 lineto + closepath + } bind def + /u { 555 0 65 -23 482 524 setcachedevice + 482 0 moveto + 407 0 lineto + 407 73 lineto + 375.667 29 341.667 0.666667 305 -12 curveto + 283.667 -19.3333 259.333 -23 232 -23 curveto + 172 -23 127 -5.33333 97 30 curveto + 75.6667 54 65 84 65 120 curveto + 65 524 lineto + 148 524 lineto + 148 153 lineto + 148 113 163 84 193 66 curveto + 210.333 55.3333 231.333 50 256 50 curveto + 304 50 341 69 367 107 curveto + 388.333 139 399 179 399 227 curveto + 399 524 lineto + 482 524 lineto + 482 0 lineto + closepath + } bind def + /v { 500 0 10 0 486 524 setcachedevice + 285 0 moveto + 194 0 lineto + 10 524 lineto + 104 524 lineto + 244 99 lineto + 392 524 lineto + 486 524 lineto + 285 0 lineto + closepath + } bind def + /w { 721 0 6 0 708 524 setcachedevice + 554 0 moveto + 459 0 lineto + 353 411 lineto + 252 0 lineto + 158 0 lineto + 6 524 lineto + 98 524 lineto + 205 116 lineto + 305 524 lineto + 407 524 lineto + 510 116 lineto + 614 524 lineto + 708 524 lineto + 554 0 lineto + closepath + } bind def + /x { 500 0 17 0 473 524 setcachedevice + 292 271 moveto + 473 0 lineto + 376 0 lineto + 245 201 lineto + 112 0 lineto + 17 0 lineto + 202 267 lineto + 27 524 lineto + 122 524 lineto + 248 334 lineto + 374 524 lineto + 468 524 lineto + 292 271 lineto + closepath + } bind def + /y { 500 0 20 -218 478 524 setcachedevice + 388 524 moveto + 478 524 lineto + 245 -110 lineto + 217.667 -182 172.667 -218 110 -218 curveto + 88.6667 -218 70 -213.667 54 -205 curveto + 54 -130 lineto + 73.3333 -134 88 -136 98 -136 curveto + 122.667 -136 141 -127.333 153 -110 curveto + 157 -103.333 161 -95 165 -85 curveto + 197 -2 lineto + 20 524 lineto + 109 524 lineto + 243 116 lineto + 388 524 lineto + closepath + } bind def + /z { 500 0 31 0 457 524 setcachedevice + 443 524 moveto + 443 450 lineto + 132 73 lineto + 457 73 lineto + 457 0 lineto + 31 0 lineto + 31 75 lineto + 344 451 lineto + 52 451 lineto + 52 524 lineto + 443 524 lineto + closepath + } bind def + /braceleft { 333 0 43 -212 276 729 setcachedevice + 276 729 moveto + 276 664 lineto + 261 664 lineto + 233.667 664 216 658 208 646 curveto + 201.333 636 198 619.667 198 597 curveto + 198 416 lineto + 198 359.333 188 319 168 295 curveto + 156 279.667 138.667 267.667 116 259 curveto + 161.333 237.667 188 199 196 143 curveto + 197.333 130.333 198 116.333 198 101 curveto + 198 -80 lineto + 198 -110 204 -129 216 -137 curveto + 224.667 -143.667 239.667 -147 261 -147 curveto + 276 -147 lineto + 276 -212 lineto + 230 -212 lineto + 184 -212 152 -192 134 -152 curveto + 125.333 -132.667 121 -109 121 -81 curveto + 121 86 lineto + 121 140 113 176.667 97 196 curveto + 85.6667 210 67.6667 219.333 43 224 curveto + 43 293 lineto + 73.6667 299 94.3333 312.667 105 334 curveto + 115.667 354 121 386.333 121 431 curveto + 121 598 lineto + 121 656.667 139 696 175 716 curveto + 191 724.667 209.333 729 230 729 curveto + 276 729 lineto + closepath + } bind def + /bar { 259 0 100 -212 160 729 setcachedevice + 100 729 moveto + 160 729 lineto + 160 -212 lineto + 100 -212 lineto + 100 729 lineto + closepath + } bind def + /braceright { 333 0 29 -212 262 729 setcachedevice + 29 -212 moveto + 29 -147 lineto + 45 -147 lineto + 73 -147 91.3333 -140.667 100 -128 curveto + 106 -118.667 109 -102.667 109 -80 curveto + 109 101 lineto + 109 170.333 128.667 218.333 168 245 curveto + 174.667 249.667 182.333 254 191 258 curveto + 144.333 280 117.667 320.667 111 380 curveto + 109.667 390.667 109 402.667 109 416 curveto + 109 597 lineto + 109 627 103 646 91 654 curveto + 81.6667 660.667 66.3333 664 45 664 curveto + 29 664 lineto + 29 729 lineto + 76 729 lineto + 123.333 729 155.667 708.667 173 668 curveto + 181.667 648.667 186 625.333 186 598 curveto + 186 431 lineto + 186 377 194.333 340 211 320 curveto + 222.333 306.667 239.333 297.667 262 293 curveto + 262 224 lineto + 232 217.333 211.667 203 201 181 curveto + 191 161 186 129.333 186 86 curveto + 186 -81 lineto + 186 -139.667 167.667 -179 131 -199 curveto + 115 -207.667 96.6667 -212 76 -212 curveto + 29 -212 lineto + closepath + } bind def + /asciitilde { 583 0 75 268 508 438 setcachedevice + 181 371 moveto + 150.333 371 132.667 346.667 128 298 curveto + 128 293 lineto + 75 293 lineto + 79 369 103 415.333 147 432 curveto + 158.333 436 170.333 438 183 438 curveto + 201.667 438 219.667 432.667 237 422 curveto + 354 353 lineto + 372.667 341.667 389.333 336 404 336 curveto + 430 336 446 348.667 452 374 curveto + 454 382.667 455 393.333 455 406 curveto + 455 411 lineto + 508 411 lineto + 508 395 lineto + 508 346.333 493.333 310.667 464 288 curveto + 446.667 274.667 426.333 268 403 268 curveto + 377 268 350 276.667 322 294 curveto + 224 357 lineto + 211.333 364.333 198.333 369 185 371 curveto + 181 371 lineto + closepath + } bind def +end +currentdict end +/FreeSans exch definefont diff --git a/graphics/FreeSerif.pt3 b/graphics/FreeSerif.pt3 new file mode 100644 index 00000000..88ade673 --- /dev/null +++ b/graphics/FreeSerif.pt3 @@ -0,0 +1,2915 @@ +%!PS-AdobeFont-1.0: FreeSerif $Revision: 1.1.1.1 $ +%%Title: FreeSerif +%Version: $Revision: 1.1.1.1 $ +%%CreationDate: Fri Feb 1 11:02:05 2008 +%%Creator: R. Timothy Edwards +%Copyright: Copyleft 2002, 2003, 2005 Free Software Foundation. +% Generated by FontForge 20080109 (http://fontforge.sf.net/) +%%EndComments + +13 dict begin +/FontType 3 def +/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def +/FontName /FreeSerif def +/FontBBox {-797 -545 2010 1166 }readonly def +/UniqueID 4051158 def +/XUID [1021 202 645001535 13246026] def +/PaintType 0 def +/FontInfo 10 dict dup begin + /version ($Revision: 1.1.1.1 $) readonly def + /Notice (Copyleft 2002, 2003, 2005 Free Software Foundation.) readonly def + /FullName (Free Serif) readonly def + /FamilyName (FreeSerif) readonly def + /Weight (Book) readonly def + /FSType 0 def + /ItalicAngle 0 def + /isFixedPitch false def + /UnderlinePosition -124.512 def + /UnderlineThickness 49.8047 def +end readonly def +/Encoding StandardEncoding def +/BuildChar { 1 index /Encoding get exch get 1 index /BuildGlyph get exec } bind def +% I call all my CharProcs with two arguments, the top of the stack will be +% 0 and then next thing is the fontdict. If the tos is zero the char will +% do a setcachedevice, otherwise (for referenced chars) it will not. The +% fontdict argument is so a char can invoke a referenced char. BuildGlyph +% itself will remove the arguments from the stack, the CharProc will leave 'em +/BuildGlyph { 2 copy exch /CharProcs get exch 2 copy known not { pop /.notdef} if get exch pop 0 exch exec pop pop fill} bind def +/CharProcs 128 dict def +CharProcs begin + /.notdef { 432 0 33 0 366 667 setcachedevice } bind def + /space { 250 0 0 0 0 0 setcachedevice + } bind def + /exclam { 332 0 130 -9 237 676 setcachedevice + 189 176 moveto + 176 176 lineto + 167 284 lineto + 165.667 300.667 157.667 364.667 143 476 curveto + 134.333 538.667 130 579.667 130 599 curveto + 130 635 140.333 658.667 161 670 curveto + 167 674 174.333 676 183 676 curveto + 210.333 676 227 659.333 233 626 curveto + 235 617.333 236 607.333 236 596 curveto + 236 587.333 235.333 575 234 559 curveto + 189 176 lineto + closepath + 183 98 moveto + 202.333 98 217.333 90 228 74 curveto + 234 64.6667 237 54.3333 237 43 curveto + 237 23 228.333 8.33333 211 -1 curveto + 202.333 -6.33333 192.667 -9 182 -9 curveto + 161.333 -9 146.333 -0.666667 137 16 curveto + 132.333 24 130 33 130 43 curveto + 130 63.6667 138 79.3333 154 90 curveto + 162.667 95.3333 172.333 98 183 98 curveto + closepath + } bind def + /quotedbl { 407 0 77 431 331 676 setcachedevice + 299 431 moveto + 278 431 lineto + 258.667 538.333 248 606.333 246 635 curveto + 246 651 253.333 662.667 268 670 curveto + 274 674 281 676 289 676 curveto + 305 676 317 669.333 325 656 curveto + 329 650 331 643.333 331 636 curveto + 331 606.667 322.667 551.667 306 471 curveto + 299 431 lineto + closepath + 130 431 moveto + 109 431 lineto + 91 524.333 80.6667 590.333 78 629 curveto + 77.3333 631.667 77 633.667 77 635 curveto + 77 651 84.3333 662.667 99 670 curveto + 105 674 112 676 120 676 curveto + 136 676 148 669.333 156 656 curveto + 160 650 162 643.333 162 636 curveto + 162 606.667 153.667 551.667 137 471 curveto + 130 431 lineto + closepath + } bind def + /numbersign { 500 0 5 0 496 662 setcachedevice + 471 271 moveto + 471 216 lineto + 362 216 lineto + 331 0 lineto + 273 0 lineto + 304 216 lineto + 170 216 lineto + 137 0 lineto + 79 0 lineto + 112 216 lineto + 5 216 lineto + 5 271 lineto + 121 271 lineto + 142 405 lineto + 32 405 lineto + 32 460 lineto + 150 460 lineto + 181 662 lineto + 239 662 lineto + 208 460 lineto + 341 460 lineto + 371 662 lineto + 429 662 lineto + 399 460 lineto + 496 460 lineto + 496 405 lineto + 391 405 lineto + 371 271 lineto + 471 271 lineto + closepath + 333 405 moveto + 200 405 lineto + 179 271 lineto + 313 271 lineto + 333 405 lineto + closepath + } bind def + /dollar { 500 0 44 -87 457 727 setcachedevice + 52 512 moveto + 52 577.333 85.6667 622.333 153 647 curveto + 175.667 655 201.333 660.667 230 664 curveto + 230 727 lineto + 264 727 lineto + 264 664 lineto + 328.667 656 375.667 643 405 625 curveto + 412.333 621 419 616.333 425 611 curveto + 425 500 lineto + 410 500 lineto + 398 560 370 600.333 326 621 curveto + 308.667 629 288 634.333 264 637 curveto + 264 391 lineto + 349 342 lineto + 390.333 316 418.667 289.667 434 263 curveto + 449.333 237.667 457 206.667 457 170 curveto + 457 104 426.333 56.6667 365 28 curveto + 338.333 16 304.667 6.66667 264 0 curveto + 264 -87 lineto + 230 -87 lineto + 230 0 lineto + 174.667 2 130.667 9.66667 98 23 curveto + 81.3333 29.6667 63.3333 39 44 51 curveto + 44 181 lineto + 59 181 lineto + 75.6667 107.667 108.667 61 158 41 curveto + 178.667 32.3333 202.667 28 230 28 curveto + 230 310 lineto + 160 348.667 112.667 383 88 413 curveto + 64 441 52 474 52 512 curveto + closepath + 229 407 moveto + 229 637 lineto + 160.333 623 126 588.667 126 534 curveto + 126 510 133.667 489 149 471 curveto + 163 455 189.667 433.667 229 407 curveto + closepath + 264 293 moveto + 264 28 lineto + 325.333 40 362 67.3333 374 110 curveto + 376.667 120.667 378 132.667 378 146 curveto + 378 176.667 370.667 201.333 356 220 curveto + 341.333 239.333 310.667 263.667 264 293 curveto + closepath + } bind def + /percent { 832 0 61 -13 772 676 setcachedevice + 669 371 moveto + 714.333 371 745 353.667 761 319 curveto + 768.333 303 772 284.667 772 264 curveto + 772 205.333 755.667 150 723 98 curveto + 712.333 80.6667 700 65 686 51 curveto + 652 17 613 0 569 0 curveto + 526.333 0 494 15.6667 472 47 curveto + 456.667 69.6667 449 97 449 129 curveto + 449 183 466.667 233 502 279 curveto + 534.667 321.667 573.667 349.667 619 363 curveto + 635.667 368.333 652.333 371 669 371 curveto + closepath + 586 30 moveto + 623.333 30 657.667 51.6667 689 95 curveto + 717 133 735 175.667 743 223 curveto + 745 235.667 746 247.667 746 259 curveto + 746 285.667 736.667 307 718 323 curveto + 705.333 333.667 691.333 339 676 339 curveto + 634 339 597.667 307.667 567 245 curveto + 546.333 202.333 532.667 159 526 115 curveto + 525.333 107 525 100 525 94 curveto + 525 68 534.667 49.3333 554 38 curveto + 563.333 32.6667 574 30 586 30 curveto + closepath + 282 662 moveto + 304.667 662 324.333 656 341 644 curveto + 357.667 631.333 367 624.667 369 624 curveto + 387 613.333 410.333 608 439 608 curveto + 480.333 608 516 617.667 546 637 curveto + 561.333 646.333 577.667 659.333 595 676 curveto + 634 676 lineto + 249 -13 lineto + 201 -13 lineto + 552 613 lineto + 522.667 595.667 494.333 586 467 584 curveto + 459.667 583.333 451.333 583 442 583 curveto + 416 583 394.333 586.333 377 593 curveto + 381.667 576.333 384 561.667 384 549 curveto + 384 498.333 370 448.667 342 400 curveto + 313.333 350 277.333 316.667 234 300 curveto + 216.667 292.667 198.333 289 179 289 curveto + 145 289 116.333 302.667 93 330 curveto + 71.6667 354 61 382.667 61 416 curveto + 61 471.333 78.6667 522.333 114 569 curveto + 146.667 612.333 185.667 640.667 231 654 curveto + 248.333 659.333 265.333 662 282 662 curveto + closepath + 282 632 moveto + 256 632 228.667 611 200 569 curveto + 172.667 527.667 153.667 482.333 143 433 curveto + 139 415 137 398.667 137 384 curveto + 137 359.333 146.667 341.667 166 331 curveto + 174.667 325.667 184.667 323 196 323 curveto + 230 323 262.667 341 294 377 curveto + 326 413.667 346.333 457.333 355 508 curveto + 357.667 522.667 359 537 359 551 curveto + 359 563.667 356 580 350 600 curveto + 325.333 606.667 306.333 615.667 293 627 curveto + 289 630.333 285.333 632 282 632 curveto + closepath + } bind def + /ampersand { 777 0 42 -13 750 676 setcachedevice + 491 555 moveto + 491 514.333 474.667 479 442 449 curveto + 418.667 427.667 383.333 406 336 384 curveto + 370.667 316.667 405.667 259.333 441 212 curveto + 449 201.333 458 190 468 178 curveto + 522 249.333 552 304.333 558 343 curveto + 558.667 349 559 354.667 559 360 curveto + 559 377.333 553 389 541 395 curveto + 531.667 399.667 516.333 403 495 405 curveto + 495 426 lineto + 711 426 lineto + 711 405 lineto + 680.333 401 658 393 644 381 curveto + 635.333 373.667 626.333 362 617 346 curveto + 591 300 lineto + 564.333 253.333 531 203.333 491 150 curveto + 537 88.6667 588.333 58 645 58 curveto + 669.667 58 690.667 66 708 82 curveto + 716 88.6667 725 98.3333 735 111 curveto + 750 100 lineto + 730 52 700 18.6667 660 0 curveto + 640.667 -8.66667 620.333 -13 599 -13 curveto + 557 -13 515.667 3.33333 475 36 curveto + 461 47.3333 445.667 61.3333 429 78 curveto + 378.333 33.3333 329.667 5.66667 283 -5 curveto + 261.667 -10.3333 238.333 -13 213 -13 curveto + 148.333 -13 101 6.33333 71 45 curveto + 51.6667 70.3333 42 101.667 42 139 curveto + 42 223 94.3333 295 199 355 curveto + 237 377 lineto + 216.333 434.333 205 476 203 502 curveto + 202.333 508.667 202 515.333 202 522 curveto + 202 565.333 217.333 602 248 632 curveto + 277.333 661.333 313.333 676 356 676 curveto + 400.667 676 436 661.667 462 633 curveto + 481.333 611.667 491 585.667 491 555 curveto + closepath + 321 416 moveto + 379.667 447.333 416 480.667 430 516 curveto + 435.333 529.333 438 543.667 438 559 curveto + 438 589 427.333 612 406 628 curveto + 392 638.667 376 644 358 644 curveto + 329.333 644 307.667 632.333 293 609 curveto + 285 595.667 281 580 281 562 curveto + 281 526 290 486.667 308 444 curveto + 311.333 435.333 315.667 426 321 416 curveto + closepath + 252 343 moveto + 200 309.667 166 278 150 248 curveto + 139.333 228 134 205.333 134 180 curveto + 134 140.667 147.333 106.667 174 78 curveto + 199.333 52 229 39 263 39 curveto + 296.333 39 333.667 53.3333 375 82 curveto + 383.667 88 393.333 95.3333 404 104 curveto + 363.333 154.667 325.667 210.333 291 271 curveto + 279 291.667 266 315.667 252 343 curveto + closepath + } bind def + /quotesingle { 179 0 48 431 133 676 setcachedevice + 101 431 moveto + 80 431 lineto + 61.3333 532.333 50.6667 600.333 48 635 curveto + 48 651 55 662.667 69 670 curveto + 75.6667 674 83 676 91 676 curveto + 107 676 119 669.333 127 656 curveto + 131 650 133 643.333 133 636 curveto + 133 604 124.667 549 108 471 curveto + 101 431 lineto + closepath + } bind def + /parenleft { 332 0 48 -177 304 676 setcachedevice + 292 -177 moveto + 244.667 -148.333 201.333 -109.667 162 -61 curveto + 86 31.6667 48 136 48 252 curveto + 48 421.333 121.667 556.667 269 658 curveto + 276.333 664 285 670 295 676 curveto + 304 660 lineto + 259.333 624 226.333 590.667 205 560 curveto + 166.333 504.667 143.667 430 137 336 curveto + 135 310.667 134 283.667 134 255 curveto + 134 129.667 152 34 188 -32 curveto + 208.667 -71.3333 241.333 -109.333 286 -146 curveto + 304 -161 lineto + 292 -177 lineto + closepath + } bind def + /parenright { 332 0 29 -177 285 676 setcachedevice + 41 676 moveto + 88.3333 647.333 131.667 608.667 171 560 curveto + 247 467.333 285 363 285 247 curveto + 285 77.6667 211.333 -57.6667 64 -159 curveto + 56.6667 -164.333 48 -170.333 38 -177 curveto + 29 -161 lineto + 74.3333 -124.333 108 -90 130 -58 curveto + 168.667 -1.33333 191 75.6667 197 173 curveto + 198.333 195.667 199 219.333 199 244 curveto + 199 367.333 182 461.667 148 527 curveto + 126.667 567.667 93.3333 607 48 645 curveto + 29 660 lineto + 41 676 lineto + closepath + } bind def + /asterisk { 500 0 69 265 432 676 setcachedevice + 214 302 moveto + 214 311.333 218.667 329.333 228 356 curveto + 237.333 383.333 242 406 242 424 curveto + 242 432 lineto + 241 449 lineto + 241 456 lineto + 201 430.667 170.333 404.333 149 377 curveto + 140.333 365.667 133.667 358.667 129 356 curveto + 123.667 352.667 115.667 351 105 351 curveto + 85.6667 351 74 359 70 375 curveto + 69.3333 378.333 69 382 69 386 curveto + 69 402 76 413 90 419 curveto + 94 420.333 110 424.667 138 432 curveto + 174 440.667 206 453.667 234 471 curveto + 223 478 lineto + 207.667 488.667 181.333 498 144 506 curveto + 113.333 513.333 93.3333 520 84 526 curveto + 74 533.333 69 543 69 555 curveto + 69 569.667 75 580.333 87 587 curveto + 92.3333 589.667 97.6667 591 103 591 curveto + 117 591 129 585.667 139 575 curveto + 167 541 lineto + 186.333 521 211 502.667 241 486 curveto + 241 499 lineto + 241 523 235.667 555.333 225 596 curveto + 219 617.333 216 632.333 216 641 curveto + 216 655.667 222.333 666 235 672 curveto + 239.667 674.667 245 676 251 676 curveto + 265.667 676 276.333 669.667 283 657 curveto + 285.667 651 287 645 287 639 curveto + 287 630.333 282.667 612 274 584 curveto + 264.667 554.667 260 530 260 510 curveto + 260 484 lineto + 282 496.667 307.667 518.333 337 549 curveto + 357.667 570.333 371.667 583.333 379 588 curveto + 385 591.333 390.333 593 395 593 curveto + 411 593 422 585.667 428 571 curveto + 430 565.667 431 560 431 554 curveto + 431 538.667 424.667 528 412 522 curveto + 408 520.667 392 516.333 364 509 curveto + 329.333 500.333 297.333 487.333 268 470 curveto + 296 452.667 330.667 439.667 372 431 curveto + 397.333 425.667 413 421 419 417 curveto + 427.667 410.333 432 400.333 432 387 curveto + 432 369.667 425 358.333 411 353 curveto + 407 351 402.333 350 397 350 curveto + 382.333 350 367 359 351 377 curveto + 316 416 lineto + 298.667 434.667 280 448 260 456 curveto + 260 449 lineto + 260 412.333 266.333 375.333 279 338 curveto + 285 322 288 311 288 305 curveto + 288 291 282 279.667 270 271 curveto + 263.333 267 256.333 265 249 265 curveto + 235.667 265 225.667 271.333 219 284 curveto + 215.667 289.333 214 295.333 214 302 curveto + closepath + } bind def + /plus { 563 0 30 0 534 506 setcachedevice + 249 286 moveto + 249 506 lineto + 315 506 lineto + 315 286 lineto + 534 286 lineto + 534 220 lineto + 315 220 lineto + 315 0 lineto + 249 0 lineto + 249 220 lineto + 30 220 lineto + 30 286 lineto + 249 286 lineto + closepath + } bind def + /comma { 250 0 56 -141 195 102 setcachedevice + 142 -2 moveto + 122 -6 lineto + 115 -6 lineto + 87 -6 68.6667 4 60 24 curveto + 57.3333 30 56 37 56 45 curveto + 56 69 65.6667 85.6667 85 95 curveto + 94.3333 99.6667 104.333 102 115 102 curveto + 141.667 102 162.667 90.6667 178 68 curveto + 189.333 52 195 33.6667 195 13 curveto + 195 -25.6667 178.667 -62 146 -96 curveto + 128 -114.667 107 -129.667 83 -141 curveto + 74 -122 lineto + 128 -84.6667 155.333 -49.3333 156 -16 curveto + 156 -8 152.333 -3.33333 145 -2 curveto + 142 -2 lineto + closepath + } bind def + /hyphen { 332 0 39 194 285 257 setcachedevice + 39 257 moveto + 285 257 lineto + 285 194 lineto + 39 194 lineto + 39 257 lineto + closepath + } bind def + /period { 250 0 70 -11 181 100 setcachedevice + 125 100 moveto + 143.667 100 158.667 92 170 76 curveto + 177.333 66 181 55 181 43 curveto + 181 25 173 10.3333 157 -1 curveto + 147 -7.66667 136 -11 124 -11 curveto + 106 -11 91.3333 -3.33333 80 12 curveto + 73.3333 21.3333 70 31.6667 70 43 curveto + 70 62.3333 78 78 94 90 curveto + 103.333 96.6667 113.667 100 125 100 curveto + closepath + } bind def + /slash { 277 0 -9 -14 287 676 setcachedevice + 287 676 moveto + 59 -14 lineto + -9 -14 lineto + 220 676 lineto + 287 676 lineto + closepath + } bind def + /zero { 500 0 24 -14 476 676 setcachedevice + 250 -14 moveto + 168 -14 107 29.3333 67 116 curveto + 39 176.667 24.6667 247.667 24 329 curveto + 24 336 lineto + 24 414.667 38.6667 485 68 547 curveto + 82.6667 579 100 604.667 120 624 curveto + 156.667 658.667 201.333 676 254 676 curveto + 312.667 676 362 649.667 402 597 curveto + 446 539 470.333 461 475 363 curveto + 475.667 352.333 476 341.333 476 330 curveto + 476 228 455.667 145.333 415 82 curveto + 376.333 23.3333 326.667 -8.66667 266 -14 curveto + 250 -14 lineto + closepath + 251 650 moveto + 185.667 650 144.667 588.667 128 466 curveto + 122.667 426 120 379.667 120 327 curveto + 120 127.667 159.333 23 238 13 curveto + 242 12.3333 246 12 250 12 curveto + 331.333 12 374.333 105.333 379 292 curveto + 379.667 304 380 316 380 328 curveto + 380 492.667 353.667 594.333 301 633 curveto + 286.333 644.333 269.667 650 251 650 curveto + closepath + } bind def + /one { 500 0 111 0 394 676 setcachedevice + 183 593 moveto + 170.333 593 146.333 585.667 111 571 curveto + 111 585 lineto + 291 676 lineto + 299 674 lineto + 299 74 lineto + 299 51.3333 304.333 36 315 28 curveto + 327 20 353.333 15.6667 394 15 curveto + 394 0 lineto + 118 0 lineto + 118 15 lineto + 156 16.3333 181 21.6667 193 31 curveto + 206.333 41.6667 213 62.3333 213 93 curveto + 213 546 lineto + 213 574.667 204.667 590 188 592 curveto + 186.667 592.667 185 593 183 593 curveto + closepath + } bind def + /two { 500 0 30 0 475 676 setcachedevice + 31 477 moveto + 46.3333 540.333 69.3333 588 100 620 curveto + 136 657.333 182.333 676 239 676 curveto + 290.333 676 333.667 659.333 369 626 curveto + 404.333 593.333 422.667 552.667 424 504 curveto + 424 499 lineto + 424 438.333 397.667 374.667 345 308 curveto + 331 290 314.667 271.333 296 252 curveto + 128 76 lineto + 367 76 lineto + 390.333 76 407.667 80 419 88 curveto + 429.667 96.6667 444 114.667 462 142 curveto + 475 137 lineto + 420 0 lineto + 30 0 lineto + 30 12 lineto + 208 201 lineto + 278 275 319.667 347.333 333 418 curveto + 336.333 432.667 338 447 338 461 curveto + 338 508.333 322 545 290 571 curveto + 264.667 591.667 233.667 602 197 602 curveto + 159 602 128.667 590.333 106 567 curveto + 88 547.667 70 516 52 472 curveto + 31 477 lineto + closepath + } bind def + /three { 500 0 43 -14 432 676 setcachedevice + 81 78 moveto + 96.3333 78 115.667 70.6667 139 56 curveto + 164.333 40.6667 183.333 31 196 27 curveto + 206.667 23.6667 217.667 22 229 22 curveto + 267 22 298.667 37 324 67 curveto + 348 95.6667 360 130.333 360 171 curveto + 360 218.333 344 257 312 287 curveto + 296.667 301 279 311.667 259 319 curveto + 241 325.667 213.667 329.333 177 330 curveto + 153 330 lineto + 153 343 lineto + 211.667 363.667 253.667 386.333 279 411 curveto + 305.667 438.333 319 471 319 509 curveto + 319 545.667 305.667 574 279 594 curveto + 259.667 608.667 236.333 616 209 616 curveto + 162.333 616 122.333 595.667 89 555 curveto + 79.6667 542.333 70 527.333 60 510 curveto + 45 514 lineto + 69.6667 582 103.333 628 146 652 curveto + 174 668 206 676 242 676 curveto + 294 676 334.667 660.333 364 629 curveto + 386.667 604.333 398 574.333 398 539 curveto + 398 504.333 385.667 474 361 448 curveto + 347.667 433.333 328.667 417.667 304 401 curveto + 353.333 379.667 388 352.667 408 320 curveto + 424 292.667 432 259 432 219 curveto + 432 151 407 95.6667 357 53 curveto + 309.667 11.6667 248 -10.6667 172 -14 curveto + 156 -14 lineto + 103.333 -14 68.6667 -3.33333 52 18 curveto + 46 25.3333 43 33.6667 43 43 curveto + 43 59 50.3333 70 65 76 curveto + 69.6667 77.3333 75 78 81 78 curveto + closepath + } bind def + /four { 500 0 12 0 472 676 setcachedevice + 472 231 moveto + 472 167 lineto + 370 167 lineto + 370 0 lineto + 293 0 lineto + 293 167 lineto + 12 167 lineto + 12 231 lineto + 326 676 lineto + 370 676 lineto + 370 231 lineto + 472 231 lineto + closepath + 292 231 moveto + 292 574 lineto + 52 231 lineto + 292 231 lineto + closepath + } bind def + /five { 500 0 32 -14 438 688 setcachedevice + 357 194 moveto + 357 274.667 317.333 334.667 238 374 curveto + 192.667 396 143.333 408.667 90 412 curveto + 76 412 lineto + 68 412 64 414.667 64 420 curveto + 64 422 64.3333 423.667 65 425 curveto + 174 662 lineto + 383 662 lineto + 398.333 662 410.333 666.333 419 675 curveto + 422.333 678.333 425.667 682.667 429 688 curveto + 438 681 lineto + 400 592 lineto + 397.333 586.667 392.333 583.667 385 583 curveto + 377 583 lineto + 181 583 lineto + 139 498 lineto + 249 478.667 326 446 370 400 curveto + 408 360.667 427 308 427 242 curveto + 427 143.333 389.667 71.6667 315 27 curveto + 268.333 -0.333333 214.667 -14 154 -14 curveto + 99.3333 -14 62.3333 -3 43 19 curveto + 35.6667 27 32 36.6667 32 48 curveto + 34.6667 71.3333 49 83.6667 75 85 curveto + 93.6667 85 115.333 76.6667 140 60 curveto + 162.667 44 177.667 34.3333 185 31 curveto + 196.333 25.6667 207.333 23 218 23 curveto + 256.667 23 289.333 39.3333 316 72 curveto + 343.333 105.333 357 146 357 194 curveto + closepath + } bind def + /six { 500 0 34 -14 468 684 setcachedevice + 258 -14 moveto + 194 -14 141.667 11 101 61 curveto + 57.6667 113.667 35.3333 184.333 34 273 curveto + 34 279 lineto + 34 385.667 69.3333 476.333 140 551 curveto + 158 570.333 178.333 588 201 604 curveto + 245.667 635.333 291.333 656.667 338 668 curveto + 366.667 674.667 402.667 680 446 684 curveto + 448 668 lineto + 359.333 653.333 288 615.333 234 554 curveto + 191.333 506 164 449 152 383 curveto + 190.667 406.333 220 420.333 240 425 curveto + 250.667 427 264 428 280 428 curveto + 342.667 428 391 406 425 362 curveto + 453.667 325.333 468 277.667 468 219 curveto + 468 149 448 92.3333 408 49 curveto + 369.333 7 319.333 -14 258 -14 curveto + closepath + 242 382 moveto + 188 382 153.333 365.667 138 333 curveto + 130.667 317 127 293.667 127 263 curveto + 127 167 146 97.3333 184 54 curveto + 206.667 27.3333 235 14 269 14 curveto + 316.333 14 348.667 40.3333 366 93 curveto + 374 118.333 378 149 378 185 curveto + 378 269 357.333 326.667 316 358 curveto + 295.333 374 270.667 382 242 382 curveto + closepath + } bind def + /seven { 500 0 20 -8 449 662 setcachedevice + 449 662 moveto + 449 646 lineto + 237 -8 lineto + 172 -8 lineto + 370 588 lineto + 153 588 lineto + 125 588 104 583 90 573 curveto + 76 563 58.3333 541 37 507 curveto + 20 515 lineto + 79 662 lineto + 449 662 lineto + closepath + } bind def + /eight { 500 0 56 -14 445 676 setcachedevice + 290 371 moveto + 353.333 323.667 395.667 284 417 252 curveto + 435.667 224 445 191.667 445 155 curveto + 445 98.3333 424 54.6667 382 24 curveto + 347.333 -1.33333 302.667 -14 248 -14 curveto + 188 -14 140 3.33333 104 38 curveto + 72 68 56 105.667 56 151 curveto + 56 183 63 209.667 77 231 curveto + 92.3333 253.667 124.333 284 173 322 curveto + 177 325.333 181.333 328.667 186 332 curveto + 134 377.333 100.333 411.667 85 435 curveto + 70.3333 457 62.6667 482.667 62 512 curveto + 62 518 lineto + 62 563.333 80 601 116 631 curveto + 152 661 197.333 676 252 676 curveto + 306 676 349.333 660.333 382 629 curveto + 410 603.667 424 572 424 534 curveto + 424 495.333 410.667 462.667 384 436 curveto + 364 415.333 332.667 393.667 290 371 curveto + closepath + 272 268 moveto + 212 312 lineto + 173.333 281.333 149 249 139 215 curveto + 134.333 198.333 132 179.667 132 159 curveto + 132 108.333 147.333 69.3333 178 42 curveto + 200 23.3333 227 14 259 14 curveto + 297.667 14 327.333 27.6667 348 55 curveto + 362 74.3333 369 97.3333 369 124 curveto + 369 157.333 358.333 186.667 337 212 curveto + 322.333 228.667 300.667 247.333 272 268 curveto + closepath + 261 389 moveto + 295 415 lineto + 335 447.667 355 487.667 355 535 curveto + 355 578.333 340 610 310 630 curveto + 292 642 270 648 244 648 curveto + 206.667 648 177.667 635.333 157 610 curveto + 143 592.667 136 572.333 136 549 curveto + 136 511 155 474.667 193 440 curveto + 211 424 233.667 407 261 389 curveto + closepath + } bind def + /nine { 500 0 30 -22 459 676 setcachedevice + 59 -22 moveto + 56 -2 lineto + 149.333 14 224.667 58 282 130 curveto + 318 176 344 230.667 360 294 curveto + 319.333 262.667 280.333 244.333 243 239 curveto + 232.333 237.667 221.333 237 210 237 curveto + 153.333 237 108.333 257.333 75 298 curveto + 45 334.667 30 382 30 440 curveto + 30 505.333 48.6667 560 86 604 curveto + 121.333 646.667 166 670.333 220 675 curveto + 226 675.667 232 676 238 676 curveto + 298 676 348.333 652.667 389 606 curveto + 431 558 454 495 458 417 curveto + 458.667 409.667 459 402 459 394 curveto + 459 303.333 434 222.333 384 151 curveto + 359.333 115.667 329.333 85 294 59 curveto + 252.667 29 209.667 8.33333 165 -3 curveto + 137 -11 101.667 -17.3333 59 -22 curveto + closepath + 246 280 moveto + 270 280 293.333 285 316 295 curveto + 346.667 309 362 329 362 355 curveto + 362 394 lineto + 362 551.333 324 635.333 248 646 curveto + 242 647.333 236 648 230 648 curveto + 183.333 648 151.333 619.333 134 562 curveto + 126 536 122 506.667 122 474 curveto + 122 400 138.333 346 171 312 curveto + 191.667 290.667 216.667 280 246 280 curveto + closepath + } bind def + /colon { 277 0 81 -11 192 459 setcachedevice + 136 459 moveto + 154.667 459 169.667 451 181 435 curveto + 188.333 425 192 414 192 402 curveto + 192 384 184 369.333 168 358 curveto + 158 351.333 147 348 135 348 curveto + 117 348 102.333 355.667 91 371 curveto + 84.3333 380.333 81 390.667 81 402 curveto + 81 422 89 437.667 105 449 curveto + 115 455.667 125.333 459 136 459 curveto + closepath + 136 100 moveto + 154.667 100 169.667 92 181 76 curveto + 188.333 66 192 55 192 43 curveto + 192 25 184 10.3333 168 -1 curveto + 158 -7.66667 147 -11 135 -11 curveto + 116.333 -11 101.667 -3.33333 91 12 curveto + 84.3333 21.3333 81 31.6667 81 43 curveto + 81 63 89 78.6667 105 90 curveto + 115 96.6667 125.333 100 136 100 curveto + closepath + } bind def + /semicolon { 277 0 80 -141 219 459 setcachedevice + 166 -2 moveto + 146 -6 lineto + 139 -6 lineto + 109 -6 90.3333 5 83 27 curveto + 81 33 80 39.3333 80 46 curveto + 80 70 90 86.6667 110 96 curveto + 118.667 100 128.333 102 139 102 curveto + 165 102 186 91 202 69 curveto + 213.333 53 219 34.3333 219 13 curveto + 219 -27 202 -64 168 -98 curveto + 150.667 -115.333 130.333 -129.667 107 -141 curveto + 98 -122 lineto + 152.667 -84.6667 180 -49.3333 180 -16 curveto + 180 -8.66667 176.667 -4 170 -2 curveto + 166 -2 lineto + closepath + 136 459 moveto + 154.667 459 169.667 451 181 435 curveto + 188.333 425 192 414 192 402 curveto + 192 384 184 369.333 168 358 curveto + 158 351.333 147 348 135 348 curveto + 117 348 102.333 355.667 91 371 curveto + 84.3333 380.333 81 390.667 81 402 curveto + 81 422 89 437.667 105 449 curveto + 115 455.667 125.333 459 136 459 curveto + closepath + } bind def + /less { 563 0 28 -10 536 516 setcachedevice + 536 -10 moveto + 28 220 lineto + 28 286 lineto + 536 516 lineto + 536 444 lineto + 116 253 lineto + 536 62 lineto + 536 -10 lineto + closepath + } bind def + /equal { 563 0 30 120 534 386 setcachedevice + 534 386 moveto + 534 320 lineto + 30 320 lineto + 30 386 lineto + 534 386 lineto + closepath + 534 186 moveto + 534 120 lineto + 30 120 lineto + 30 186 lineto + 534 186 lineto + closepath + } bind def + /greater { 563 0 28 -10 536 516 setcachedevice + 28 -10 moveto + 28 62 lineto + 448 253 lineto + 28 444 lineto + 28 516 lineto + 536 286 lineto + 536 220 lineto + 28 -10 lineto + closepath + } bind def + /question { 443 0 68 -8 414 676 setcachedevice + 230 676 moveto + 282 676 325.667 661.667 361 633 curveto + 396.333 603.667 414 566.333 414 521 curveto + 414 479.667 397.667 435.667 365 389 curveto + 354.333 373.667 335.667 350 309 318 curveto + 281.667 283.333 263 246.667 253 208 curveto + 249.667 194.667 246.667 180 244 164 curveto + 227 164 lineto + 228.333 216 238.333 263.333 257 306 curveto + 285 370 lineto + 309.667 426 322 478 322 526 curveto + 322 562.667 309.667 593 285 617 curveto + 264.333 636.333 240.667 646 214 646 curveto + 184.667 646 160 637.667 140 621 curveto + 126 609.667 119 597.333 119 584 curveto + 119 578 124.667 568 136 554 curveto + 149.333 536.667 156.333 522 157 510 curveto + 157 492 149.667 479.667 135 473 curveto + 129 470.333 122.667 469 116 469 curveto + 89.3333 469 73.6667 483.667 69 513 curveto + 68.3333 518.333 68 524.333 68 531 curveto + 68 573 84.3333 608 117 636 curveto + 147.667 662.667 185.333 676 230 676 curveto + closepath + 237 99 moveto + 255.667 99 270.333 91 281 75 curveto + 287.667 65.6667 291 55.3333 291 44 curveto + 291 24 282.333 9.33333 265 -0 curveto + 256.333 -5.33333 246.667 -8 236 -8 curveto + 216 -8 201 0.333333 191 17 curveto + 186.333 24.3333 184 33 184 43 curveto + 184 64.3333 192.333 80.3333 209 91 curveto + 217.667 96.3333 227 99 237 99 curveto + closepath + } bind def + /at { 920 0 116 -14 809 676 setcachedevice + 482 645 moveto + 406.667 645 343 618.333 291 565 curveto + 243.667 517 214.667 455.333 204 380 curveto + 201.333 361.333 200 342.333 200 323 curveto + 200 243 223.667 175.667 271 121 curveto + 315.667 69 374.333 38 447 28 curveto + 461.667 26 476.667 25 492 25 curveto + 540.667 25 590 34.3333 640 53 curveto + 654.667 58.3333 670.667 65 688 73 curveto + 700 43 lineto + 634.667 13.6667 582 -4 542 -10 curveto + 524 -12.6667 504.333 -14 483 -14 curveto + 395 -14 318 10.3333 252 59 curveto + 192 103 151.333 160 130 230 curveto + 120.667 261.333 116 293.333 116 326 curveto + 116 406 141 477.333 191 540 curveto + 237.667 598 298 638 372 660 curveto + 406.667 670.667 443 676 481 676 curveto + 562.333 676 633 653.667 693 609 curveto + 747.667 567.667 783.333 515.667 800 453 curveto + 806 429.667 809 406.333 809 383 curveto + 809 322.333 792.667 269 760 223 curveto + 730.667 181 695.333 155.333 654 146 curveto + 644.667 144 635 143 625 143 curveto + 593 143 568 154 550 176 curveto + 541.333 187.333 536 200.667 534 216 curveto + 506.667 179.333 474.333 156.333 437 147 curveto + 427.667 145 418.333 144 409 144 curveto + 381.667 144 359.333 156.667 342 182 curveto + 328 202.667 321 227.333 321 256 curveto + 321 306.667 334.333 355.333 361 402 curveto + 389.667 452 425.333 484.333 468 499 curveto + 484 505 500.333 508 517 508 curveto + 538.333 508 554.667 502 566 490 curveto + 572.667 482.667 580.333 471.333 589 456 curveto + 599 494 lineto + 668 494 lineto + 603 240 lineto + 601.667 232 601 226 601 222 curveto + 601 191.333 614 176 640 176 curveto + 669.333 176 696.333 192.333 721 225 curveto + 748.333 261 764 303.333 768 352 curveto + 768.667 358.667 769 365.667 769 373 curveto + 769 436.333 747.667 493 705 543 curveto + 664.333 591 613 622.333 551 637 curveto + 528.333 642.333 505.333 645 482 645 curveto + closepath + 572 406 moveto + 572 438 561 456.667 539 462 curveto + 535.667 463.333 532 464 528 464 curveto + 508 464 485.667 453.333 461 432 curveto + 426.333 400.667 404.667 361 396 313 curveto + 393.333 299.667 392 286 392 272 curveto + 392 234 402.667 208.333 424 195 curveto + 432.667 189.667 442 187 452 187 curveto + 481.333 187 508 209.333 532 254 curveto + 553.333 293.333 566.333 336.333 571 383 curveto + 571.667 391 572 398.667 572 406 curveto + closepath + } bind def + /A { 721 0 15 0 706 674 setcachedevice + 706 19 moveto + 706 0 lineto + 451 0 lineto + 451 19 lineto + 486.333 19.6667 508 25 516 35 curveto + 519.333 39.6667 521 45.6667 521 53 curveto + 521 69.6667 514.667 92 502 120 curveto + 461 216 lineto + 199 216 lineto + 153 99 lineto + 147.667 85 145 72 145 60 curveto + 145 38 159 25 187 21 curveto + 194.333 19.6667 203 19 213 19 curveto + 213 0 lineto + 15 0 lineto + 15 19 lineto + 35 20.3333 50.3333 25.6667 61 35 curveto + 75.6667 48.3333 95 81.6667 119 135 curveto + 139 183 lineto + 347 674 lineto + 367 674 lineto + 616 106 lineto + 634 68 648.333 44.3333 659 35 curveto + 668.333 25.6667 684 20.3333 706 19 curveto + closepath + 216 257 moveto + 447 257 lineto + 331 532 lineto + 216 257 lineto + closepath + } bind def + /B { 666 0 17 0 593 662 setcachedevice + 593 180 moveto + 593 135.333 577.667 97.3333 547 66 curveto + 505 22 439.667 0 351 0 curveto + 17 0 lineto + 17 19 lineto + 55.6667 20.3333 81 25.6667 93 35 curveto + 104.333 43.6667 110.667 61.6667 112 89 curveto + 112.667 95 113 101.667 113 109 curveto + 113 553 lineto + 113 587 109 609 101 619 curveto + 91.6667 630.333 72.6667 637.667 44 641 curveto + 36.6667 641.667 27.6667 642.333 17 643 curveto + 17 662 lineto + 297 662 lineto + 447.667 662 533.333 619.333 554 534 curveto + 557.333 521.333 559 507.333 559 492 curveto + 559 420.667 520 374.333 442 353 curveto + 440 353 433.333 351.333 422 348 curveto + 460.667 338 490.333 327.333 511 316 curveto + 565.667 285.333 593 240 593 180 curveto + closepath + 278 37 moveto + 358.667 37 414 52.3333 444 83 curveto + 466.667 105.667 478 137.667 478 179 curveto + 478 234.333 455.333 274 410 298 curveto + 405.333 301.333 400 304 394 306 curveto + 365.333 318 319 324.667 255 326 curveto + 215 326 lineto + 215 78 lineto + 215 60 221 48.3333 233 43 curveto + 241.667 39 256.667 37 278 37 curveto + closepath + 215 366 moveto + 310 366 lineto + 376 366 420.333 386.333 443 427 curveto + 452.333 444.333 457 464.667 457 488 curveto + 457 555.333 423.667 598 357 616 curveto + 335 622 309.667 625 281 625 curveto + 237 625 lineto + 222.333 625 215 615 215 595 curveto + 215 366 lineto + closepath + } bind def + /C { 666 0 28 -14 633 676 setcachedevice + 28 325 moveto + 28 417.667 54.3333 496 107 560 curveto + 155 617.333 216.333 653.333 291 668 curveto + 314.333 673.333 338.333 676 363 676 curveto + 409 676 454.667 668.667 500 654 curveto + 523.333 646.667 539.333 643 548 643 curveto + 567.333 643 580.667 651.667 588 669 curveto + 588.667 671 589.333 673.333 590 676 curveto + 611 676 lineto + 620 450 lineto + 597 450 lineto + 560.333 574 488.667 636 382 636 curveto + 310 636 252.667 609.667 210 557 curveto + 166 503 144 430 144 338 curveto + 144 206.667 181.667 116.333 257 67 curveto + 295.667 42.3333 340.667 30 392 30 curveto + 452.667 30 509 48.3333 561 85 curveto + 578.333 97.6667 596.333 113 615 131 curveto + 633 113 lineto + 589 54.3333 529.333 15.6667 454 -3 curveto + 424 -10.3333 392.667 -14 360 -14 curveto + 270 -14 195 12.3333 135 65 curveto + 75.6667 117 41 186.667 31 274 curveto + 29 290.667 28 307.667 28 325 curveto + closepath + } bind def + /D { 721 0 16 0 685 662 setcachedevice + 685 334 moveto + 685 259.333 665.333 194 626 138 curveto + 564 50.6667 462.333 4.66667 321 0 curveto + 300 0 lineto + 16 0 lineto + 16 19 lineto + 52 21 75.5 26.8333 86.5 36.5 curveto + 97.5 46.1667 103.333 65.3333 104 94 curveto + 104 109 lineto + 104 553 lineto + 104 586.333 100.667 608.333 94 619 curveto + 86.6667 629.667 70 636.667 44 640 curveto + 36.6667 641.333 27.3333 642.333 16 643 curveto + 16 662 lineto + 286 662 lineto + 445.333 662 558.333 617 625 527 curveto + 665 473.667 685 409.333 685 334 curveto + closepath + 576 327 moveto + 576 413 552.667 482 506 534 curveto + 451.333 594.667 368.667 625 258 625 curveto + 233.333 625 218 620.667 212 612 curveto + 208 606.667 206 598 206 586 curveto + 206 78 lineto + 206 59.3333 211.667 47.3333 223 42 curveto + 229.667 38.6667 241.333 37 258 37 curveto + 426.667 37 528 97.3333 562 218 curveto + 571.333 250 576 286.333 576 327 curveto + closepath + } bind def + /E { 610 0 12 0 597 662 setcachedevice + 201 80 moveto + 201 64 204 53.3333 210 48 curveto + 218.667 41.3333 242 37.6667 280 37 curveto + 306 37 lineto + 333 37 lineto + 399.667 37 447.667 44 477 58 curveto + 505 71.3333 529 95 549 129 curveto + 555.667 140.333 562.333 153.667 569 169 curveto + 597 169 lineto + 552 0 lineto + 12 0 lineto + 12 19 lineto + 47.3333 21 70.6667 27.6667 82 39 curveto + 93.3333 49.6667 99 71 99 103 curveto + 99 109 lineto + 99 553 lineto + 99 587 94.3333 609.667 85 621 curveto + 75 631.667 54 638.667 22 642 curveto + 19.3333 642.667 16 643 12 643 curveto + 12 662 lineto + 543 662 lineto + 546 519 lineto + 521 519 lineto + 513.667 558.333 503.333 584.667 490 598 curveto + 476 612 450.333 620.333 413 623 curveto + 401 623.667 386.333 624 369 624 curveto + 234 624 lineto + 218 624 208.333 620.667 205 614 curveto + 202.333 609.333 201 601.333 201 590 curveto + 201 368 lineto + 355 368 lineto + 398.333 368 427 375.667 441 391 curveto + 450.333 401 457.333 420.333 462 449 curveto + 462.667 452.333 463.667 457 465 463 curveto + 488 463 lineto + 488 231 lineto + 465 231 lineto + 459 269 450.667 294 440 306 curveto + 428.667 318.667 408 325.667 378 327 curveto + 355 327 lineto + 201 327 lineto + 201 80 lineto + closepath + } bind def + /F { 555 0 12 0 546 662 setcachedevice + 479 231 moveto + 456 231 lineto + 450 269 441.333 294.333 430 307 curveto + 418 319 395.333 325.667 362 327 curveto + 346 327 lineto + 201 327 lineto + 201 109 lineto + 201 75 205.667 52.3333 215 41 curveto + 225 29.6667 246 22.6667 278 20 curveto + 282 20 286.667 19.6667 292 19 curveto + 292 0 lineto + 12 0 lineto + 12 19 lineto + 46.6667 21 69.3333 26.6667 80 36 curveto + 91.3333 46 97.6667 66 99 96 curveto + 99 120 lineto + 99 553 lineto + 99 587 94.3333 609.667 85 621 curveto + 75 631.667 54 638.667 22 642 curveto + 19.3333 642.667 16 643 12 643 curveto + 12 662 lineto + 543 662 lineto + 546 519 lineto + 521 519 lineto + 513.667 558.333 503.333 584.667 490 598 curveto + 476 612 450.333 620.333 413 623 curveto + 401 623.667 386.333 624 369 624 curveto + 233 624 lineto + 217 624 207.667 620.667 205 614 curveto + 202.333 609.333 201 601.333 201 590 curveto + 201 368 lineto + 346 368 lineto + 384 368 409.667 373 423 383 curveto + 437 393 447.333 414.333 454 447 curveto + 456 463 lineto + 479 463 lineto + 479 231 lineto + closepath + } bind def + /G { 721 0 32 -14 709 676 setcachedevice + 392 636 moveto + 298 636 230 595 188 513 curveto + 160 460.333 146 398 146 326 curveto + 146 226.667 172.333 150.333 225 97 curveto + 271.667 49.6667 333 26 409 26 curveto + 453.667 26 489.667 34.3333 517 51 curveto + 533.667 61 542 72.3333 542 85 curveto + 542 247 lineto + 542 281.667 537.333 304.667 528 316 curveto + 520 325.333 502.333 331.333 475 334 curveto + 469 334.667 462 335.333 454 336 curveto + 454 354 lineto + 709 354 lineto + 709 336 lineto + 679.667 333.333 660.333 327 651 317 curveto + 643 307 639 287.667 639 259 curveto + 639 56 lineto + 616.333 36 575.333 18.6667 516 4 curveto + 468.667 -8 426 -14 388 -14 curveto + 316.667 -14 251.667 1.66667 193 33 curveto + 105.667 80.3333 54 154.333 38 255 curveto + 34 277.667 32 301 32 325 curveto + 32 415 57.6667 491.667 109 555 curveto + 157 614.333 220 652 298 668 curveto + 322.667 673.333 348.333 676 375 676 curveto + 417 676 460.667 668.667 506 654 curveto + 530 646.667 546.333 643 555 643 curveto + 572.333 643 585.667 650.333 595 665 curveto + 597 668.333 598.667 672 600 676 curveto + 622 676 lineto + 630 465 lineto + 607 465 lineto + 583 523.667 555.333 566 524 592 curveto + 488.667 621.333 444.667 636 392 636 curveto + closepath + } bind def + /H { 721 0 19 0 702 662 setcachedevice + 209 359 moveto + 512 359 lineto + 512 553 lineto + 512 586.333 508 608.333 500 619 curveto + 491.333 629.667 472.667 637 444 641 curveto + 438.667 641.667 432 642.333 424 643 curveto + 424 662 lineto + 702 662 lineto + 702 643 lineto + 666 639.667 642.667 633.667 632 625 curveto + 621.333 616.333 615.333 598.667 614 572 curveto + 614 553 lineto + 614 109 lineto + 614 75 618.667 52.6667 628 42 curveto + 637.333 30.6667 657.667 23.3333 689 20 curveto + 693 20 697.333 19.6667 702 19 curveto + 702 0 lineto + 424 0 lineto + 424 19 lineto + 459.333 21 482 26.3333 492 35 curveto + 503.333 44.3333 510 63 512 91 curveto + 512 120 lineto + 512 315 lineto + 209 315 lineto + 209 109 lineto + 209 75 213.667 52.6667 223 42 curveto + 232.333 30.6667 252.667 23.3333 284 20 curveto + 288 20 292.333 19.6667 297 19 curveto + 297 0 lineto + 19 0 lineto + 19 19 lineto + 53.6667 21 76.3333 26.3333 87 35 curveto + 98.3333 44.3333 104.667 62.6667 106 90 curveto + 106.667 98.6667 107 108.667 107 120 curveto + 107 553 lineto + 107 586.333 103 608.333 95 619 curveto + 87 629.667 69.3333 637 42 641 curveto + 35.3333 641.667 27.6667 642.333 19 643 curveto + 19 662 lineto + 297 662 lineto + 297 643 lineto + 261 639.667 237.667 633.667 227 625 curveto + 216.333 616.333 210.333 598.667 209 572 curveto + 209 553 lineto + 209 359 lineto + closepath + } bind def + /I { 332 0 18 0 315 662 setcachedevice + 115 109 moveto + 115 553 lineto + 115 586.333 111 608.333 103 619 curveto + 94.3333 630.333 75 637.667 45 641 curveto + 37.6667 641.667 28.6667 642.333 18 643 curveto + 18 662 lineto + 315 662 lineto + 315 643 lineto + 275 641 249 635.333 237 626 curveto + 225 616.667 218.333 598 217 570 curveto + 217 553 lineto + 217 109 lineto + 217 75 222 52.3333 232 41 curveto + 243.333 29 266 22 300 20 curveto + 304.667 20 309.667 19.6667 315 19 curveto + 315 0 lineto + 18 0 lineto + 18 19 lineto + 57.3333 20.3333 83 25.3333 95 34 curveto + 107 42.6667 113.667 60.6667 115 88 curveto + 115 109 lineto + closepath + } bind def + /J { 388 0 10 -14 370 662 setcachedevice + 59 108 moveto + 79.6667 108 94.6667 97.3333 104 76 curveto + 119 38 lineto + 123.667 28.6667 130 24 138 24 curveto + 161.333 24 174 42.3333 176 79 curveto + 176 90 lineto + 176 553 lineto + 176 586.333 172 608.333 164 619 curveto + 156 629.667 138 637 110 641 curveto + 102.667 641.667 93.6667 642.333 83 643 curveto + 83 662 lineto + 370 662 lineto + 370 643 lineto + 332 640.333 307.5 634.667 296.5 626 curveto + 285.5 617.333 279.333 600 278 574 curveto + 278 553 lineto + 278 183 lineto + 278 102.333 254.333 45.6667 207 13 curveto + 180.333 -5 147.667 -14 109 -14 curveto + 71.6667 -14 43.6667 -3.66667 25 17 curveto + 15 29 10 42.6667 10 58 curveto + 10 75.3333 17.3333 89 32 99 curveto + 40 105 49 108 59 108 curveto + closepath + } bind def + /K { 721 0 34 0 723 662 setcachedevice + 413 643 moveto + 413 662 lineto + 675 662 lineto + 675 643 lineto + 641 640.333 616 635 600 627 curveto + 582 618.333 556.333 597.667 523 565 curveto + 333 377 lineto + 566 127 lineto + 610.667 79 641.333 49.3333 658 38 curveto + 674 26.6667 692.333 20.6667 713 20 curveto + 715.667 19.3333 719 19 723 19 curveto + 723 0 lineto + 418 0 lineto + 418 19 lineto + 426 19.6667 435.333 20 446 20 curveto + 474 20.6667 488 28 488 42 curveto + 488 58.6667 467 91.3333 425 140 curveto + 405.667 163.333 383.333 187.333 358 212 curveto + 252 317 lineto + 226 296 lineto + 226 109 lineto + 226 75 230.333 52.6667 239 42 curveto + 247.667 30.6667 266.667 23.6667 296 21 curveto + 302 20.3333 308.667 19.6667 316 19 curveto + 316 0 lineto + 34 0 lineto + 34 19 lineto + 69.3333 21 92.6667 26.6667 104 36 curveto + 115.333 45.3333 122 64.3333 124 93 curveto + 124 120 lineto + 124 553 lineto + 124 586.333 119.667 608.667 111 620 curveto + 101.667 631.333 81.6667 638.667 51 642 curveto + 45.6667 642.667 40 643 34 643 curveto + 34 662 lineto + 318 662 lineto + 318 643 lineto + 280.667 640.333 256.333 634.667 245 626 curveto + 234.333 617.333 228.333 600.333 227 575 curveto + 226.333 569 226 561.667 226 553 curveto + 226 348 lineto + 403 509 lineto + 449.667 552.333 475.333 584 480 604 curveto + 480.667 606.667 481 609.333 481 612 curveto + 481 626.667 473.333 636 458 640 curveto + 452.667 641.333 446.333 642 439 642 curveto + 429.667 642 421 642.333 413 643 curveto + closepath + } bind def + /L { 610 0 12 0 598 662 setcachedevice + 354 39 moveto + 448 39 512.333 65.6667 547 119 curveto + 553 128.333 561.667 146.667 573 174 curveto + 598 174 lineto + 550 0 lineto + 12 0 lineto + 12 19 lineto + 47.3333 21 70.6667 27.6667 82 39 curveto + 93.3333 49.6667 99 71 99 103 curveto + 99 109 lineto + 99 553 lineto + 99 587 94.3333 609.667 85 621 curveto + 75 631.667 54 638.667 22 642 curveto + 19.3333 642.667 16 643 12 643 curveto + 12 662 lineto + 294 662 lineto + 294 643 lineto + 256 641 231.333 635 220 625 curveto + 208.667 615 202.333 595 201 565 curveto + 201 553 lineto + 201 80 lineto + 201 63.3333 205.667 52.3333 215 47 curveto + 224.333 41.6667 248.333 39 287 39 curveto + 354 39 lineto + closepath + } bind def + /M { 888 0 12 0 863 662 setcachedevice + 674 573 moveto + 418 0 lineto + 404 0 lineto + 153 550 lineto + 153 147 lineto + 153 97.6667 158.667 64.6667 170 48 curveto + 181.333 32 202.333 22.6667 233 20 curveto + 237 20 241.667 19.6667 247 19 curveto + 247 0 lineto + 12 0 lineto + 12 19 lineto + 48.6667 21.6667 73.3333 28.6667 86 40 curveto + 98.6667 52 106 76 108 112 curveto + 108.667 121.333 109 133 109 147 curveto + 109 553 lineto + 109 587 104.667 609.333 96 620 curveto + 86.6667 631.333 66.6667 638.667 36 642 curveto + 30 642 22.6667 642.333 14 643 curveto + 14 662 lineto + 212 662 lineto + 443 157 lineto + 664 662 lineto + 863 662 lineto + 863 643 lineto + 827.667 640.333 804.667 634.333 794 625 curveto + 782.667 615 776.667 595 776 565 curveto + 776 553 lineto + 776 109 lineto + 776 74.3333 781 51.5 791 40.5 curveto + 801 29.5 822 22.6667 854 20 curveto + 856.667 20 859.667 19.6667 863 19 curveto + 863 0 lineto + 583 0 lineto + 583 19 lineto + 619 21 642.667 26.6667 654 36 curveto + 665.333 46 671.667 65.6667 673 95 curveto + 673.667 101.667 674 110 674 120 curveto + 674 573 lineto + closepath + } bind def + /N { 721 0 12 -11 707 662 setcachedevice + 707 643 moveto + 677.667 640.333 657.667 635.667 647 629 curveto + 627.667 617 616.333 590.667 613 550 curveto + 612.333 539.333 612 527.667 612 515 curveto + 612 -11 lineto + 595 -11 lineto + 153 539 lineto + 153 147 lineto + 153 97.6667 158.667 64.6667 170 48 curveto + 181.333 32 202.333 22.6667 233 20 curveto + 237 20 241.667 19.6667 247 19 curveto + 247 0 lineto + 12 0 lineto + 12 19 lineto + 48.6667 21.6667 73.3333 28.6667 86 40 curveto + 98.6667 52 106 76 108 112 curveto + 108.667 121.333 109 133 109 147 curveto + 109 588 lineto + 87.6667 613.333 70.6667 629 58 635 curveto + 47.3333 640.333 32 643 12 643 curveto + 12 662 lineto + 183 662 lineto + 568 178 lineto + 568 515 lineto + 568 564.333 562 597.333 550 614 curveto + 540 628.667 520 637.667 490 641 curveto + 484.667 641.667 478.667 642.333 472 643 curveto + 472 662 lineto + 707 662 lineto + 707 643 lineto + closepath + } bind def + /O { 721 0 34 -14 688 676 setcachedevice + 355 -14 moveto + 279 -14 212.667 9 156 55 curveto + 97.3333 102.333 59.6667 165.667 43 245 curveto + 37 273 34 301.667 34 331 curveto + 34 421 59 497.333 109 560 curveto + 156.333 618 217.667 654.333 293 669 curveto + 315 673.667 337.667 676 361 676 curveto + 445.667 676 517.333 650.333 576 599 curveto + 634.667 547 670.333 478.333 683 393 curveto + 686.333 371.667 688 349.667 688 327 curveto + 688 235.667 662 159.333 610 98 curveto + 561.333 39.3333 496.667 3.66667 416 -9 curveto + 396 -12.3333 375.667 -14 355 -14 curveto + closepath + 574 328 moveto + 574 458 541.667 548.667 477 600 curveto + 443 626.667 404.333 640 361 640 curveto + 277.667 640 218 598 182 514 curveto + 159.333 462 148 400.333 148 329 curveto + 148 251.667 161.667 186 189 132 curveto + 226.333 58.6667 283 22 359 22 curveto + 440.333 22 499.667 62 537 142 curveto + 561.667 195.333 574 257.333 574 328 curveto + closepath + } bind def + /P { 555 0 16 0 542 662 setcachedevice + 542 481 moveto + 542 418.333 517.667 370 469 336 curveto + 423 304 357 288 271 288 curveto + 251 288 228 289 202 291 curveto + 202 109 lineto + 202 74.3333 207 51.6667 217 41 curveto + 227 29 248.667 22 282 20 curveto + 286 20 290.667 19.6667 296 19 curveto + 296 0 lineto + 16 0 lineto + 16 19 lineto + 49.3333 21.6667 71 27 81 35 curveto + 91.6667 43.6667 97.6667 61 99 87 curveto + 99.6667 95.6667 100 106.667 100 120 curveto + 100 553 lineto + 100 586.333 96 608.333 88 619 curveto + 80.6667 629 63.6667 636.333 37 641 curveto + 31 641.667 24 642.333 16 643 curveto + 16 662 lineto + 280 662 lineto + 355.333 662 416.667 647.667 464 619 curveto + 516 587.667 542 541.667 542 481 curveto + closepath + 202 591 moveto + 202 331 lineto + 224.667 329 243.667 328 259 328 curveto + 366.333 328 424 370.667 432 456 curveto + 432.667 462 433 468.333 433 475 curveto + 433 544.333 403.667 589.333 345 610 curveto + 316.333 620 280 625 236 625 curveto + 219.333 625 209.333 621 206 613 curveto + 203.333 608.333 202 601 202 591 curveto + closepath + } bind def + /Q { 721 0 34 -178 701 676 setcachedevice + 688 331 moveto + 688 207 646 114 562 52 curveto + 520.667 21.3333 475.333 1.66667 426 -7 curveto + 476 -72.3333 529.667 -116 587 -138 curveto + 621 -150.667 659 -157.667 701 -159 curveto + 701 -177 lineto + 695 -177 lineto + 687.667 -177.667 676 -178 660 -178 curveto + 526 -178 422.667 -149.333 350 -92 curveto + 336 -81.3333 323.333 -69.3333 312 -56 curveto + 265 -1 lineto + 172.333 30.3333 107 85 69 163 curveto + 45.6667 210.333 34 265.667 34 329 curveto + 34 420.333 59 497.333 109 560 curveto + 157 618.667 219 655.333 295 670 curveto + 316.333 674 338.333 676 361 676 curveto + 445 676 516.333 650.333 575 599 curveto + 632.333 549 668 483.667 682 403 curveto + 686 379.667 688 355.667 688 331 curveto + closepath + 574 333 moveto + 574 431.667 552.667 509.333 510 566 curveto + 472 615.333 423.333 640 364 640 curveto + 281.333 640 221.333 599.667 184 519 curveto + 160 466.333 148 405 148 335 curveto + 148 204.333 180.333 113.333 245 62 curveto + 278.333 35.3333 317 22 361 22 curveto + 442.333 22 501.333 62.6667 538 144 curveto + 562 197.333 574 260.333 574 333 curveto + closepath + } bind def + /R { 666 0 17 0 659 662 setcachedevice + 293 662 moveto + 383.667 662 451 643 495 605 curveto + 529.667 576.333 547 536.667 547 486 curveto + 547 398.667 491.333 344 380 322 curveto + 392.667 324.667 388 323.667 366 319 curveto + 572 66 lineto + 591.333 44 610 30 628 24 curveto + 636.667 22 647 20.3333 659 19 curveto + 659 0 lineto + 498 0 lineto + 260 308 lineto + 204 306 lineto + 204 109 lineto + 204 75.6667 208.333 53.3333 217 42 curveto + 226.333 30.6667 246.333 23.6667 277 21 curveto + 282.333 20.3333 288 19.6667 294 19 curveto + 294 0 lineto + 17 0 lineto + 17 19 lineto + 51 21.6667 73 27.3333 83 36 curveto + 94.3333 45.3333 100.667 64.6667 102 94 curveto + 102 120 lineto + 102 553 lineto + 102 586.333 98 608 90 618 curveto + 82.6667 628.667 65 636.333 37 641 curveto + 31.6667 641.667 25 642.333 17 643 curveto + 17 662 lineto + 293 662 lineto + closepath + 204 343 moveto + 287.333 345 346 355.667 380 375 curveto + 418.667 397 438 434.667 438 488 curveto + 438 553.333 408.333 595 349 613 curveto + 323.667 621 292.333 625 255 625 curveto + 230.333 625 215 620.667 209 612 curveto + 205.667 606.667 204 599 204 589 curveto + 204 343 lineto + closepath + } bind def + /S { 555 0 42 -14 491 676 setcachedevice + 390 135 moveto + 390 177 369.333 214.333 328 247 curveto + 311.333 259.667 279.333 279.333 232 306 curveto + 182.667 334.667 147.333 359 126 379 curveto + 89.3333 415 71 457 71 505 curveto + 71 557.667 89.6667 600.333 127 633 curveto + 159.667 661.667 198.667 676 244 676 curveto + 274 676 308.667 668.667 348 654 curveto + 370.667 646 386 642 394 642 curveto + 411.333 642 422 653.333 426 676 curveto + 447 676 lineto + 469 463 lineto + 444 463 lineto + 422.667 540.333 385.667 592 333 618 curveto + 310.333 629.333 286.333 635 261 635 curveto + 222.333 635 193.667 622.333 175 597 curveto + 163 581.667 157 563.333 157 542 curveto + 157 508 176 475.667 214 445 curveto + 236 427 266 407.333 304 386 curveto + 390.667 339.333 446.667 292.667 472 246 curveto + 484.667 222 491 196 491 168 curveto + 491 118.667 473 76.6667 437 42 curveto + 400.333 7.33333 354.333 -11.3333 299 -14 curveto + 287 -14 lineto + 252.333 -14 214.667 -7 174 7 curveto + 149.333 15.6667 132 20 122 20 curveto + 110 20 101.667 13.6667 97 1 curveto + 95.6667 -3.66667 94.6667 -8.33333 94 -13 curveto + 72 -13 lineto + 42 199 lineto + 65 199 lineto + 101 111.667 145.667 57 199 35 curveto + 219.667 26.3333 242.333 22 267 22 curveto + 310.333 22 343.333 36 366 64 curveto + 382 83.3333 390 107 390 135 curveto + closepath + } bind def + /T { 610 0 17 0 593 662 setcachedevice + 254 620 moveto + 200 620 lineto + 150.667 620 116.333 614.667 97 604 curveto + 78.3333 592.667 64 571.333 54 540 curveto + 49.3333 527.333 45 511.333 41 492 curveto + 17 492 lineto + 23 662 lineto + 587 662 lineto + 593 492 lineto + 569 492 lineto + 559 539.333 547.333 571 534 587 curveto + 519.333 604.333 495.333 614.667 462 618 curveto + 448 619.333 430.667 620 410 620 curveto + 356 620 lineto + 356 109 lineto + 356 75.6667 360.667 53.3333 370 42 curveto + 380 30 401 22.6667 433 20 curveto + 438.333 20 444.667 19.6667 452 19 curveto + 452 0 lineto + 160 0 lineto + 160 19 lineto + 197.333 21 221.333 26.3333 232 35 curveto + 244 43 251 60.3333 253 87 curveto + 253.667 95.6667 254 106.667 254 120 curveto + 254 620 lineto + closepath + } bind def + /U { 721 0 14 -14 705 662 setcachedevice + 206 233 moveto + 206 155.667 221.667 101.667 253 71 curveto + 280.333 43.6667 322 30 378 30 curveto + 431.333 30 475.667 43.6667 511 71 curveto + 525 82.3333 536 95 544 109 curveto + 558 135.667 565.667 176.333 567 231 curveto + 567 245 lineto + 567 515 lineto + 567 563.667 561.667 596 551 612 curveto + 540.333 628 520 638 490 642 curveto + 484.667 642.667 479 643 473 643 curveto + 473 662 lineto + 705 662 lineto + 705 643 lineto + 669 638.333 645.333 631 634 621 curveto + 621.333 609.667 614 587.667 612 555 curveto + 611.333 545 611 531.667 611 515 curveto + 611 254 lineto + 611 161.333 591 94 551 52 curveto + 509 8 443.667 -14 355 -14 curveto + 232.333 -14 155 30 123 118 curveto + 110.333 152 104 193 104 241 curveto + 104 553 lineto + 104 587 100 609 92 619 curveto + 84 630.333 65.6667 637.667 37 641 curveto + 30.3333 641.667 22.6667 642.333 14 643 curveto + 14 662 lineto + 297 662 lineto + 297 643 lineto + 259.667 639.667 235.667 633.667 225 625 curveto + 213.667 617 207.667 600 207 574 curveto + 206.333 568 206 561 206 553 curveto + 206 233 lineto + closepath + } bind def + /V { 721 0 16 -11 697 662 setcachedevice + 697 662 moveto + 697 643 lineto + 674.333 641.667 658 636.667 648 628 curveto + 636.667 618 623.333 594.333 608 557 curveto + 606.667 555 605.667 552.667 605 550 curveto + 383 -11 lineto + 368 -11 lineto + 122 538 lineto + 101.333 584 84 613.333 70 626 curveto + 58 636.667 40 642.333 16 643 curveto + 16 662 lineto + 282 662 lineto + 282 643 lineto + 263.333 641.667 253.667 641 253 641 curveto + 222.333 639 207 628.667 207 610 curveto + 207 596.667 219 563 243 509 curveto + 245 505.667 246.667 502.333 248 499 curveto + 399 161 lineto + 546 528 lineto + 558.667 559.333 565 583.667 565 601 curveto + 565 618.333 556.667 630 540 636 curveto + 528.667 640 512.667 642.333 492 643 curveto + 492 662 lineto + 697 662 lineto + closepath + } bind def + /W { 943 0 5 -11 932 662 setcachedevice + 932 662 moveto + 932 643 lineto + 904.667 637.667 886 630.667 876 622 curveto + 867.333 614 858.333 597.333 849 572 curveto + 779 382 730.333 246 703 164 curveto + 645 -11 lineto + 630 -11 lineto + 470 412 lineto + 316 -11 lineto + 301 -11 lineto + 108 526 lineto + 90.6667 576 74.6667 608 60 622 curveto + 48 634 29.6667 641 5 643 curveto + 5 662 lineto + 250 662 lineto + 250 643 lineto + 216.667 641 196.667 635.667 190 627 curveto + 186.667 623 185 617.667 185 611 curveto + 185 599 188.667 583.667 196 565 curveto + 340 189 lineto + 447 471 lineto + 414 553 lineto + 398.667 591.667 385.667 616.333 375 627 curveto + 364.333 636.333 347.333 641.667 324 643 curveto + 313 643 lineto + 313 662 lineto + 580 662 lineto + 580 643 lineto + 536 642.333 511 634 505 618 curveto + 503.667 615.333 503 612 503 608 curveto + 503 599.333 509 580.333 521 551 curveto + 524.333 541.667 527.333 533.667 530 527 curveto + 662 186 lineto + 787 525 lineto + 797.667 556.333 803 581.333 803 600 curveto + 803 616.667 794.333 628.333 777 635 curveto + 767 639 752.667 641.667 734 643 curveto + 734 662 lineto + 932 662 lineto + closepath + } bind def + /X { 721 0 10 0 704 662 setcachedevice + 696 662 moveto + 696 643 lineto + 664 641 640 635 624 625 curveto + 605.333 614.333 581 590.667 551 554 curveto + 549.667 552.667 548.333 551 547 549 curveto + 401 367 lineto + 593 93 lineto + 614.333 63 632 43.6667 646 35 curveto + 658.667 27 678 21.6667 704 19 curveto + 704 0 lineto + 407 0 lineto + 407 19 lineto + 423 20.3333 432 21 434 21 curveto + 467.333 21.6667 484 31.3333 484 50 curveto + 484 64.6667 467 97.3333 433 148 curveto + 338 288 lineto + 219 140 lineto + 184.333 97.3333 167 68.6667 167 54 curveto + 167 40.6667 174.333 31.6667 189 27 curveto + 200.333 23 218.333 20.3333 243 19 curveto + 243 0 lineto + 10 0 lineto + 10 19 lineto + 32 20.3333 48.3333 24 59 30 curveto + 73 38 94 59 122 93 curveto + 155 133 lineto + 312 326 lineto + 203 486 lineto + 157.667 552 124.667 594.333 104 613 curveto + 86.6667 629 66 638.667 42 642 curveto + 36.6667 642.667 30 643 22 643 curveto + 22 662 lineto + 324 662 lineto + 324 643 lineto + 296 642 lineto + 266.667 641.333 251 633.667 249 619 curveto + 248.333 617 248 615 248 613 curveto + 248 593 273.667 546.667 325 474 curveto + 327.667 470.667 330.333 467 333 463 curveto + 375 404 lineto + 488 542 lineto + 513.333 575.333 526.667 598.333 528 611 curveto + 528 623.667 521.333 632.333 508 637 curveto + 498 640.333 481.333 642.333 458 643 curveto + 458 662 lineto + 696 662 lineto + closepath + } bind def + /Y { 721 0 22 0 703 662 setcachedevice + 703 662 moveto + 703 643 lineto + 675.667 641 652.667 632 634 616 curveto + 615.333 600 592.333 571 565 529 curveto + 417 303 lineto + 417 109 lineto + 417 75 421.667 52.3333 431 41 curveto + 440.333 29 461.333 22 494 20 curveto + 501.333 20 510 19.6667 520 19 curveto + 520 0 lineto + 214 0 lineto + 214 19 lineto + 254 20.3333 280 25 292 33 curveto + 304 40.3333 311 56.3333 313 81 curveto + 314.333 90.3333 315 103.333 315 120 curveto + 315 294 lineto + 184 486 lineto + 136 556.667 102.333 601 83 619 curveto + 67.6667 633 50.6667 641 32 643 curveto + 22 643 lineto + 22 662 lineto + 302 662 lineto + 302 643 lineto + 294.667 642.333 286.333 642 277 642 curveto + 246.333 640 231 630.333 231 613 curveto + 231 599.667 236.667 585 248 569 curveto + 396 347 lineto + 539 573 lineto + 548.333 589 553 601.333 553 610 curveto + 553 624 545.333 633.333 530 638 curveto + 520 641.333 504.667 643 484 643 curveto + 484 662 lineto + 703 662 lineto + closepath + } bind def + /Z { 610 0 9 0 597 662 setcachedevice + 402 38 moveto + 468 38 514.333 56.6667 541 94 curveto + 551 109.333 561.333 134.667 572 170 curveto + 573.333 172.667 574 174.667 574 176 curveto + 597 176 lineto + 573 0 lineto + 9 0 lineto + 9 15 lineto + 446 624 lineto + 225 624 lineto + 153.667 624 106.333 606.333 83 571 curveto + 72.3333 555 63.6667 528.333 57 491 curveto + 31 491 lineto + 51 662 lineto + 577 662 lineto + 577 647 lineto + 145 38 lineto + 402 38 lineto + closepath + } bind def + /bracketleft { 332 0 88 -156 299 662 setcachedevice + 299 -131 moveto + 299 -156 lineto + 88 -156 lineto + 88 662 lineto + 299 662 lineto + 299 637 lineto + 209 637 lineto + 185 637 170.667 628.333 166 611 curveto + 164.667 606.333 164 600.333 164 593 curveto + 164 -79 lineto + 164 -113.667 180.333 -131 213 -131 curveto + 299 -131 lineto + closepath + } bind def + /backslash { 277 0 -9 -14 287 676 setcachedevice + -9 676 moveto + 58 676 lineto + 287 -14 lineto + 219 -14 lineto + -9 676 lineto + closepath + } bind def + /bracketright { 332 0 34 -156 245 662 setcachedevice + 34 -131 moveto + 124 -131 lineto + 149.333 -131 164 -121 168 -101 curveto + 168.667 -97 169 -92.3333 169 -87 curveto + 169 585 lineto + 169 619.667 152.667 637 120 637 curveto + 34 637 lineto + 34 662 lineto + 245 662 lineto + 245 -156 lineto + 34 -156 lineto + 34 -131 lineto + closepath + } bind def + /asciicircum { 468 0 24 297 446 662 setcachedevice + 92 297 moveto + 24 297 lineto + 205 662 lineto + 265 662 lineto + 446 297 lineto + 378 297 lineto + 235 586 lineto + 92 297 lineto + closepath + } bind def + /underscore { 500 0 0 -125 500 -75 setcachedevice + 500 -125 moveto + 0 -125 lineto + 0 -75 lineto + 500 -75 lineto + 500 -125 lineto + closepath + } bind def + /grave { 332 0 19 507 242 678 setcachedevice + 242 507 moveto + 202 507 lineto + 48 604 lineto + 28.6667 617.333 19 631.667 19 647 curveto + 19 662.333 26.3333 672.333 41 677 curveto + 44.3333 677.667 48.3333 678 53 678 curveto + 64.3333 678 75.6667 673 87 663 curveto + 95 655 lineto + 242 507 lineto + closepath + } bind def + /a { 443 0 37 -10 442 460 setcachedevice + 37 97 moveto + 37 143 61.3333 181.667 110 213 curveto + 135.333 229.667 180.333 250.333 245 275 curveto + 287 292 lineto + 287 353 lineto + 287 398.333 269.333 425.333 234 434 curveto + 227.333 435.333 219.667 436 211 436 curveto + 184.333 436 164 428.333 150 413 curveto + 142.667 405 139 396.333 139 387 curveto + 139 385 140.667 374 144 354 curveto + 144 347 lineto + 144 333 137.333 321.333 124 312 curveto + 116 307.333 107.667 305 99 305 curveto + 84.3333 305 72.3333 311.667 63 325 curveto + 58.3333 332.333 56 340 56 348 curveto + 56 380 72.1667 406.667 104.5 428 curveto + 136.833 449.333 176.667 460 224 460 curveto + 288 460 330 440.333 350 401 curveto + 362 377.667 368 344 368 300 curveto + 368 105 lineto + 368 75 372.667 57 382 51 curveto + 386 48.3333 391.333 47 398 47 curveto + 412 47 426.667 53.3333 442 66 curveto + 442 40 lineto + 418.667 14.6667 398 -0.666667 380 -6 curveto + 372 -8.66667 362.667 -10 352 -10 curveto + 324 -10 305.333 1.33333 296 24 curveto + 292.667 34 290 47 288 63 curveto + 240.667 23 201 -0.333333 169 -7 curveto + 160.333 -9 151.333 -10 142 -10 curveto + 106 -10 78.3333 3.33333 59 30 curveto + 44.3333 48.6667 37 71 37 97 curveto + closepath + 287 123 moveto + 287 268 lineto + 215 242 168 215.667 146 189 curveto + 132 172.333 125 152.333 125 129 curveto + 125 125 lineto + 125 97.6667 134 76.6667 152 62 curveto + 162.667 52.6667 174.667 48 188 48 curveto + 209.333 48 233.667 55.6667 261 71 curveto + 273.667 78.3333 281.333 86.3333 284 95 curveto + 286 101 287 110.333 287 123 curveto + closepath + } bind def + /b { 500 0 3 -10 468 683 setcachedevice + 153 681 moveto + 153 375 lineto + 164.333 403.667 186.333 426 219 442 curveto + 241.667 454 266 460 292 460 curveto + 339.333 460 379.667 441 413 403 curveto + 447.667 363 466 312.667 468 252 curveto + 468 243 lineto + 468 177 448.333 120.333 409 73 curveto + 371.667 27.6667 324.667 1 268 -7 curveto + 256.667 -9 245.333 -10 234 -10 curveto + 188 -10 146.667 -1.66667 110 15 curveto + 82.6667 27.6667 69 40.6667 69 54 curveto + 69 573 lineto + 69 596.333 64.6667 611 56 617 curveto + 49.3333 621.667 37.3333 624 20 624 curveto + 12.6667 624 7 623.667 3 623 curveto + 3 639 lineto + 32 647 lineto + 79.3333 660.333 118 672.333 148 683 curveto + 153 681 lineto + closepath + 153 322 moveto + 153 70 lineto + 153 56.6667 164 45 186 35 curveto + 204.667 26.3333 226 22 250 22 curveto + 301.333 22 338 45.3333 360 92 curveto + 373.333 120 380 155 380 197 curveto + 380 271 363.667 326 331 362 curveto + 309 385.333 282.667 397 252 397 curveto + 222.667 397 197.667 387.667 177 369 curveto + 161 354.333 153 338.667 153 322 curveto + closepath + } bind def + /c { 443 0 25 -10 412 460 setcachedevice + 25 213 moveto + 25 285.667 46.6667 345.333 90 392 curveto + 126.667 430.667 170.667 452.667 222 458 curveto + 229.333 459.333 236.667 460 244 460 curveto + 290 460 328.333 448 359 424 curveto + 385 404.667 398 382.333 398 357 curveto + 398 341.667 390.667 330 376 322 curveto + 368 317.333 359.333 315 350 315 curveto + 332.667 315 319.333 325 310 345 curveto + 307.333 349.667 305 355 303 361 curveto + 297 383 lineto + 291 405.667 282 420 270 426 curveto + 262 429.333 251.333 431 238 431 curveto + 195.333 431 161.333 413 136 377 curveto + 113.333 345.667 102 305.667 102 257 curveto + 102 195 118.667 145.667 152 109 curveto + 180 77.6667 215 62 257 62 curveto + 292.333 62 322.667 73.3333 348 96 curveto + 363.333 109.333 380 129.333 398 156 curveto + 412 147 lineto + 388 99.6667 363 64.3333 337 41 curveto + 301 7 260.333 -10 215 -10 curveto + 161 -10 116.333 10 81 50 curveto + 43.6667 92 25 146.333 25 213 curveto + closepath + } bind def + /d { 500 0 27 -10 491 683 setcachedevice + 344 -10 moveto + 340 -7 lineto + 340 57 lineto + 314 21 282.667 -0.333333 246 -7 curveto + 235.333 -9 224 -10 212 -10 curveto + 156 -10 111 10.6667 77 52 curveto + 43.6667 91.3333 27 142.333 27 205 curveto + 27 271.667 45 329 81 377 curveto + 113.667 421 154.333 447.667 203 457 curveto + 213.667 459 224.333 460 235 460 curveto + 264.333 460 291 452 315 436 curveto + 340 417 lineto + 340 573 lineto + 340 596.333 335.667 611 327 617 curveto + 320.333 621.667 309.333 624 294 624 curveto + 284.667 624 277.333 623.667 272 623 curveto + 272 639 lineto + 330 654.333 379 669 419 683 curveto + 424 681 lineto + 424 114 lineto + 424 87.3333 428 70.6667 436 64 curveto + 442 59.3333 452.667 57 468 57 curveto + 471.333 57 479 57.3333 491 58 curveto + 491 42 lineto + 344 -10 lineto + closepath + 251 42 moveto + 281.667 42 306.667 53 326 75 curveto + 335.333 85 340 94 340 102 curveto + 340 332 lineto + 340 360 328.667 384.333 306 405 curveto + 285.333 423 262.667 432 238 432 curveto + 196.667 432 164.667 412.333 142 373 curveto + 122.667 339.667 113 297 113 245 curveto + 113 173.667 129.667 119.333 163 82 curveto + 187 55.3333 216.333 42 251 42 curveto + closepath + } bind def + /e { 443 0 25 -10 424 460 setcachedevice + 97 277 moveto + 101 170.333 132.333 102.333 191 73 curveto + 209.667 63.6667 230.333 59 253 59 curveto + 294.333 59 329.667 73.3333 359 102 curveto + 375 117.333 391.333 138 408 164 curveto + 424 157 lineto + 392.667 77 346 25.3333 284 2 curveto + 261.333 -6 237.333 -10 212 -10 curveto + 150 -10 102 13.3333 68 60 curveto + 39.3333 99.3333 25 150.667 25 214 curveto + 25 289.333 45.3333 350 86 396 curveto + 124.667 438.667 174 460 234 460 curveto + 315.333 460 368 419.667 392 339 curveto + 397.333 321 401.667 300.333 405 277 curveto + 97 277 lineto + closepath + 99 309 moveto + 303 309 lineto + 295.667 358.333 283 391 265 407 curveto + 251 418.333 231 424 205 424 curveto + 152.333 424 118.667 395.333 104 338 curveto + 102 329.333 100.333 319.667 99 309 curveto + closepath + } bind def + /f { 332 0 20 0 383 683 setcachedevice + 341 580 moveto + 326.333 580 314 588 304 604 curveto + 285 633 lineto + 273.667 647.667 259.667 655 243 655 curveto + 205 655 186 625.333 186 566 curveto + 186 450 lineto + 309 450 lineto + 309 418 lineto + 187 418 lineto + 187 104 lineto + 187 70 191 47.6667 199 37 curveto + 207 25.6667 225.333 19 254 17 curveto + 261.333 16.3333 270 15.6667 280 15 curveto + 280 0 lineto + 20 0 lineto + 20 15 lineto + 53.3333 17 75 22.3333 85 31 curveto + 95.6667 39.6667 101.667 58.3333 103 87 curveto + 103 104 lineto + 103 418 lineto + 21 418 lineto + 21 450 lineto + 103 450 lineto + 104.333 559.333 132.667 630 188 662 curveto + 212.667 676 243 683 279 683 curveto + 318.333 683 347.667 673.667 367 655 curveto + 377.667 645 383 633.667 383 621 curveto + 383 605.667 376 594 362 586 curveto + 355.333 582 348.333 580 341 580 curveto + closepath + } bind def + /g { 500 0 28 -218 470 460 setcachedevice + 73 54 moveto + 73 66 77.3333 77.3333 86 88 curveto + 94 98 119.333 123 162 163 curveto + 118.667 184.333 91 210.333 79 241 curveto + 72.3333 257 69 275.667 69 297 curveto + 69 342.333 85 380.667 117 412 curveto + 149 443.333 188.667 459.333 236 460 curveto + 262.667 460 289.333 455 316 445 curveto + 338 437 lineto + 358 430.333 376.333 427 393 427 curveto + 470 427 lineto + 470 388 lineto + 387 388 lineto + 399.667 358.667 406 330.667 406 304 curveto + 406 255.333 388.333 216.333 353 187 curveto + 323.667 161.667 289.333 149 250 149 curveto + 243.333 149 230.667 150 212 152 curveto + 211.333 152 205 152.667 193 154 curveto + 176.333 148.667 161 137.333 147 120 curveto + 137.667 108.667 133 99 133 91 curveto + 133 75 159 66 211 64 curveto + 340 58 lineto + 387.333 56 421.333 40.3333 442 11 curveto + 454.667 -6.33333 461 -26.3333 461 -49 curveto + 461 -86.3333 442.667 -120 406 -150 curveto + 365.333 -182.667 315 -203.667 255 -213 curveto + 237 -216.333 219 -218 201 -218 curveto + 148.333 -218 104.333 -206.667 69 -184 curveto + 41.6667 -165.333 28 -144.333 28 -121 curveto + 28 -96.3333 42.6667 -70.3333 72 -43 curveto + 85.3333 -29.6667 103.333 -15 126 1 curveto + 98 14.3333 81.6667 26.6667 77 38 curveto + 74.3333 42.6667 73 48 73 54 curveto + closepath + 147 -2 moveto + 120.333 -33.3333 105 -55.3333 101 -68 curveto + 99 -74 98 -80.6667 98 -88 curveto + 98 -113.333 115 -132.667 149 -146 curveto + 175 -156 206.667 -161 244 -161 curveto + 314 -161 366.333 -148 401 -122 curveto + 422.333 -106 433 -86.6667 433 -64 curveto + 433 -44 421.333 -30.3333 398 -23 curveto + 379.333 -17.6667 349.667 -15 309 -15 curveto + 257.667 -15 208.667 -11.3333 162 -4 curveto + 156 -3.33333 151 -2.66667 147 -2 curveto + closepath + 329 265 moveto + 329 295 323.333 325 312 355 curveto + 294 406.333 265.333 432 226 432 curveto + 194.667 432 173 417.333 161 388 curveto + 155 374 152 357.333 152 338 curveto + 152 335 lineto + 152 277 165.333 233 192 203 curveto + 209.333 183.667 230 174 254 174 curveto + 284.667 174 306.333 187.667 319 215 curveto + 325.667 229 329 245.667 329 265 curveto + closepath + } bind def + /h { 500 0 9 0 487 683 setcachedevice + 157 343 moveto + 157 102 lineto + 157 68 161 45.6667 169 35 curveto + 177 25.6667 193.667 19.3333 219 16 curveto + 221 16 223 15.6667 225 15 curveto + 225 0 lineto + 9 0 lineto + 9 15 lineto + 35.6667 19 52.6667 24.6667 60 32 curveto + 68 40.6667 72.3333 58.6667 73 86 curveto + 73 102 lineto + 73 573 lineto + 73 595.667 69.3333 610.333 62 617 curveto + 55.3333 621.667 42 624 22 624 curveto + 16.6667 624 12.6667 623.667 10 623 curveto + 10 639 lineto + 37 647 lineto + 87 661 125.333 673 152 683 curveto + 157 680 lineto + 157 376 lineto + 189 418 222.333 444 257 454 curveto + 271.667 458 287.333 460 304 460 curveto + 373.333 460 413.333 421.333 424 344 curveto + 426 330.667 427 316.333 427 301 curveto + 427 102 lineto + 427 68.6667 430 47.3333 436 38 curveto + 441.333 28.6667 454.667 21.6667 476 17 curveto + 478.667 16.3333 482.333 15.6667 487 15 curveto + 487 0 lineto + 275 0 lineto + 275 15 lineto + 303 18.3333 321 24.6667 329 34 curveto + 337.667 44 342.333 65 343 97 curveto + 343 102 lineto + 343 300 lineto + 343 370.667 318 406 268 406 curveto + 240 406 213.333 395 188 373 curveto + 178.667 365 168.333 355 157 343 curveto + closepath + } bind def + /i { 277 0 16 0 253 683 setcachedevice + 62 394 moveto + 54 394 40 392.667 20 390 curveto + 20 405 lineto + 175 460 lineto + 179 457 lineto + 179 102 lineto + 179 68 182.333 46 189 36 curveto + 195.667 26 210.667 19.6667 234 17 curveto + 239.333 16.3333 245.667 15.6667 253 15 curveto + 253 0 lineto + 16 0 lineto + 16 15 lineto + 48 17 69 22 79 30 curveto + 89 38.6667 94.3333 57 95 85 curveto + 95 102 lineto + 95 334 lineto + 95 366.667 88.6667 386 76 392 curveto + 72 393.333 67.3333 394 62 394 curveto + closepath + 128 683 moveto + 147.333 683 162 675.333 172 660 curveto + 177.333 651.333 180 642 180 632 curveto + 180 613.333 172 599 156 589 curveto + 148 583.667 138.667 581 128 581 curveto + 110 581 96 588.667 86 604 curveto + 80.6667 612.667 78 622 78 632 curveto + 78 650.667 85.6667 665 101 675 curveto + 109.667 680.333 118.667 683 128 683 curveto + closepath + } bind def + /j { 277 0 -70 -218 194 683 setcachedevice + 77 394 moveto + 61 394 46 392.667 32 390 curveto + 32 406 lineto + 84.6667 422 136.667 440 188 460 curveto + 193 457 lineto + 193 0 lineto + 193 -106 161.667 -173.667 99 -203 curveto + 77 -213 52 -218 24 -218 curveto + -12.6667 -218 -39.6667 -209.333 -57 -192 curveto + -65.6667 -183.333 -70 -173.667 -70 -163 curveto + -70 -147.667 -63 -136.333 -49 -129 curveto + -43 -125.667 -36.3333 -124 -29 -124 curveto + -15.6667 -124 -2 -132 12 -148 curveto + 24.6667 -162.667 32.6667 -171.333 36 -174 curveto + 44 -180.667 52.3333 -184 61 -184 curveto + 81 -184 94.3333 -172.333 101 -149 curveto + 106.333 -130.333 109 -95.6667 109 -45 curveto + 109 334 lineto + 109 367.333 102.333 386.667 89 392 curveto + 85.6667 393.333 81.6667 394 77 394 curveto + closepath + 142 683 moveto + 160.667 683 175.333 675 186 659 curveto + 191.333 651 194 642 194 632 curveto + 194 613.333 186 599 170 589 curveto + 161.333 583.667 152 581 142 581 curveto + 123.333 581 109.333 589 100 605 curveto + 94.6667 613 92 622 92 632 curveto + 92 650 99.6667 664 115 674 curveto + 123 680 132 683 142 683 curveto + closepath + } bind def + /k { 500 0 7 0 505 683 setcachedevice + 7 623 moveto + 7 639 lineto + 37 647 lineto + 97.6667 663.667 139.333 675.667 162 683 curveto + 166 681 lineto + 166 261 lineto + 303 383 lineto + 317.667 395.667 325.333 407 326 417 curveto + 326 425 321 430.333 311 433 curveto + 303.667 435 292 436 276 436 curveto + 276 450 lineto + 480 450 lineto + 480 435 lineto + 472 435 lineto + 448.667 435 428 430.667 410 422 curveto + 376.667 406 328 368.333 264 309 curveto + 235 282 lineto + 388 88 lineto + 417.333 53.3333 444.667 31.3333 470 22 curveto + 480 18.6667 491.667 16.3333 505 15 curveto + 505 0 lineto + 287 0 lineto + 287 15 lineto + 306 15 lineto + 317.333 15 324.333 18.6667 327 26 curveto + 327 30 lineto + 327 34.6667 322.333 42.6667 313 54 curveto + 310.333 58 308 61.3333 306 64 curveto + 166 251 lineto + 166 67 lineto + 166 43 174.667 27.6667 192 21 curveto + 200 18.3333 209.667 16.6667 221 16 curveto + 241 15 lineto + 241 0 lineto + 7 0 lineto + 7 15 lineto + 41 20.3333 61.6667 25.6667 69 31 curveto + 77 37 81.3333 48 82 64 curveto + 82 82 lineto + 82 564 lineto + 82 593.333 76.6667 611.667 66 619 curveto + 60 623 51 625 39 625 curveto + 35 625 24.3333 624.333 7 623 curveto + closepath + } bind def + /l { 277 0 19 0 257 683 setcachedevice + 19 623 moveto + 19 639 lineto + 82.3333 654.333 135.333 669 178 683 curveto + 182 681 lineto + 182 84 lineto + 182 56.6667 186.333 39 195 31 curveto + 203.667 22.3333 224.333 17 257 15 curveto + 257 0 lineto + 21 0 lineto + 21 15 lineto + 54.3333 17.6667 75.6667 24.3333 85 35 curveto + 93.6667 44.3333 98 61.6667 98 87 curveto + 98 564 lineto + 98 594 92.3333 612.667 81 620 curveto + 75 623.333 66.6667 625 56 625 curveto + 50 625 39.6667 624.333 25 623 curveto + 19 623 lineto + closepath + } bind def + /m { 777 0 16 0 775 460 setcachedevice + 19 398 moveto + 19 415 lineto + 67.6667 428.333 114.333 443.333 159 460 curveto + 166 458 lineto + 166 383 lineto + 216 420.333 251.667 443.333 273 452 curveto + 287.667 457.333 303.667 460 321 460 curveto + 372.333 460 407 434 425 382 curveto + 427 376 lineto + 475.667 428.667 526.333 456.333 579 459 curveto + 582.333 459.667 586 460 590 460 curveto + 667.333 460 706 400.667 706 282 curveto + 706 76 lineto + 706 42.6667 717 23.6667 739 19 curveto + 749 17 lineto + 775 15 lineto + 775 0 lineto + 556 0 lineto + 556 15 lineto + 584.667 18.3333 602.667 23.6667 610 31 curveto + 618 38.3333 622 55 622 81 curveto + 622 87 lineto + 622 298 lineto + 622 346 614.333 377.667 599 393 curveto + 588.333 403 571 408 547 408 curveto + 507.667 408 475.333 393 450 363 curveto + 438 347 lineto + 438 95 lineto + 438 61 444 39 456 29 curveto + 466 20.3333 484 15.6667 510 15 curveto + 510 0 lineto + 286 0 lineto + 286 15 lineto + 315.333 17 334 22.6667 342 32 curveto + 350 40.6667 354 58.6667 354 86 curveto + 354 303 lineto + 354 373 332 408 288 408 curveto + 259.333 408 231.333 399.333 204 382 curveto + 196.667 378 190.333 373.333 185 368 curveto + 175 357.333 170 351 170 349 curveto + 170 67 lineto + 170 45 176 30.6667 188 24 curveto + 198 19.3333 214.667 16.3333 238 15 curveto + 238 0 lineto + 16 0 lineto + 16 15 lineto + 46.6667 15.6667 66.3333 22 75 34 curveto + 82.3333 43.3333 86 60.3333 86 85 curveto + 86 338 lineto + 86 370.667 80.6667 390.333 70 397 curveto + 65.3333 400.333 59 402 51 402 curveto + 41.6667 402 31 400.667 19 398 curveto + closepath + } bind def + /n { 500 0 16 0 485 460 setcachedevice + 16 398 moveto + 16 415 lineto + 69.3333 430.333 115.333 445.333 154 460 curveto + 161 458 lineto + 161 379 lineto + 202.333 417.667 234.333 441.667 257 451 curveto + 271.667 457 288 460 306 460 curveto + 352 460 385 440 405 400 curveto + 417.667 375.333 424 345.333 424 310 curveto + 424 81 lineto + 424 54.3333 429 36.6667 439 28 curveto + 447.667 22 463 17.6667 485 15 curveto + 485 0 lineto + 277 0 lineto + 277 15 lineto + 303 17 320.333 24.3333 329 37 curveto + 336.333 48.3333 340 69 340 99 curveto + 340 308 lineto + 340 369.333 318 401.667 274 405 curveto + 267 405 lineto + 245.667 405 225.333 398 206 384 curveto + 194.667 376 180.667 364 164 348 curveto + 164 67 lineto + 164 46.3333 170.667 32.3333 184 25 curveto + 193.333 20.3333 208.667 17 230 15 curveto + 230 0 lineto + 18 0 lineto + 18 15 lineto + 44.6667 17 62 23.6667 70 35 curveto + 76.6667 44.3333 80 62.6667 80 90 curveto + 80 338 lineto + 80 370 74.6667 389.333 64 396 curveto + 59.3333 400 52.3333 402 43 402 curveto + 30.3333 402 21.3333 400.667 16 398 curveto + closepath + } bind def + /o { 500 0 29 -10 470 460 setcachedevice + 250 460 moveto + 312 460 363.667 439.667 405 399 curveto + 445.667 359 467.333 308 470 246 curveto + 470 234 lineto + 470 169.333 451 114 413 68 curveto + 377 24.6667 331.333 -0.666667 276 -8 curveto + 266.667 -9.33333 257.333 -10 248 -10 curveto + 188.667 -10 138.333 10.3333 97 51 curveto + 56.3333 91 33.6667 142.667 29 206 curveto + 29 226 lineto + 29 294.667 49.3333 350.667 90 394 curveto + 130 436.667 181.333 458.667 244 460 curveto + 250 460 lineto + closepath + 119 275 moveto + 119 199.667 133 137.333 161 88 curveto + 187 41.3333 220 18 260 18 curveto + 304.667 18 337.333 40.3333 358 85 curveto + 372.667 115 380 153 380 199 curveto + 380 274.333 364.333 333.667 333 377 curveto + 307 413.667 275 432 237 432 curveto + 197 432 166.333 414.333 145 379 curveto + 127.667 351 119 316.333 119 275 curveto + closepath + } bind def + /p { 500 0 5 -217 470 460 setcachedevice + 9 393 moveto + 9 409 lineto + 49.6667 421.667 97.6667 438.667 153 460 curveto + 159 458 lineto + 159 381 lineto + 195.667 426.333 235.333 452 278 458 curveto + 286.667 459.333 295 460 303 460 curveto + 351 460 390.333 440.667 421 402 curveto + 453.667 362 470 310.333 470 247 curveto + 470 178.333 451.667 119.667 415 71 curveto + 381 26.3333 338.667 -1.73472e-18 288 -8 curveto + 278.667 -9.33333 269.333 -10 260 -10 curveto + 230.667 -10 206.333 -3.33333 187 10 curveto + 178.333 16 169 23.6667 159 33 curveto + 159 -124 lineto + 159 -153.333 163.333 -173 172 -183 curveto + 182 -192.333 203.333 -197.667 236 -199 curveto + 247 -199 lineto + 247 -217 lineto + 5 -217 lineto + 5 -200 lineto + 35 -196.667 54.3333 -190.667 63 -182 curveto + 71 -173.333 75 -156.333 75 -131 curveto + 75 337 lineto + 75 363.667 71 380.333 63 387 curveto + 57.6667 391.667 48 394 34 394 curveto + 23.3333 394 15 393.667 9 393 curveto + closepath + 159 334 moveto + 159 88 lineto + 159 73.3333 170 58.6667 192 44 curveto + 215.333 29.3333 239 22 263 22 curveto + 301 22 331.333 41 354 79 curveto + 374 113 384 156 384 208 curveto + 384 277.333 368.333 329.667 337 365 curveto + 316.333 388.333 291 400 261 400 curveto + 235.667 400 211.333 391.667 188 375 curveto + 168.667 361 159 347.333 159 334 curveto + closepath + } bind def + /q { 500 0 24 -217 488 461 setcachedevice + 360 425 moveto + 414 457 lineto + 425 457 lineto + 425 -141 lineto + 425 -162.333 428.667 -176.667 436 -184 curveto + 443.333 -190.667 460.667 -197 488 -203 curveto + 488 -217 lineto + 252 -217 lineto + 252 -200 lineto + 290 -197.333 314.667 -190 326 -178 curveto + 336 -168 341 -150 341 -124 curveto + 341 64 lineto + 295.667 15.3333 243.333 -9.33333 184 -10 curveto + 136.667 -10 98.1667 10 68.5 50 curveto + 38.8333 90 24 141.667 24 205 curveto + 24 272.333 43 330 81 378 curveto + 115.667 423.333 159.667 450 213 458 curveto + 223.667 460 234.333 461 245 461 curveto + 276.333 461 307.333 453 338 437 curveto + 344.667 433.667 352 429.667 360 425 curveto + closepath + 110 241 moveto + 110 186.333 121 141.333 143 106 curveto + 166.333 69.3333 199 51 241 51 curveto + 271 51 297.667 59.6667 321 77 curveto + 323 79 325 80.6667 327 82 curveto + 336.333 89.3333 341 104.333 341 127 curveto + 341 333 lineto + 341 399.667 310 433 248 433 curveto + 200.667 433 164.333 411.667 139 369 curveto + 119.667 335.667 110 293 110 241 curveto + closepath + } bind def + /r { 332 0 5 0 335 460 setcachedevice + 296 362 moveto + 286 362 272.333 368.667 255 382 curveto + 243 392 234.667 397 230 397 curveto + 216.667 397 201.667 387.333 185 368 curveto + 168.333 348.667 160 331 160 315 curveto + 160 90 lineto + 160 60.6667 166 41 178 31 curveto + 190 21.6667 212.333 16.3333 245 15 curveto + 245 0 lineto + 5 0 lineto + 5 15 lineto + 36.3333 21 56 27.6667 64 35 curveto + 72 42.3333 76 56.6667 76 78 curveto + 76 84 lineto + 76 334 lineto + 76 366 70 385 58 391 curveto + 53.3333 393 48 394 42 394 curveto + 31.3333 394 19.6667 392.667 7 390 curveto + 7 406 lineto + 59.6667 422.667 109 440.667 155 460 curveto + 160 458 lineto + 160 366 lineto + 190 409.333 215.333 437 236 449 curveto + 249.333 456.333 264 460 280 460 curveto + 306 460 323 449.667 331 429 curveto + 333.667 422.333 335 415 335 407 curveto + 335 384.333 326.667 370 310 364 curveto + 305.333 362.667 300.667 362 296 362 curveto + closepath + } bind def + /s { 388 0 51 -10 348 459 setcachedevice + 284 440 moveto + 286.667 440 291 442.667 297 448 curveto + 297.667 448.667 298.667 449.333 300 450 curveto + 311 450 lineto + 315 314 lineto + 300 314 lineto + 285.333 370 266 406.333 242 423 curveto + 228 432.333 210.667 437 190 437 curveto + 159.333 437 137.333 426.667 124 406 curveto + 116.667 395.333 113 383 113 369 curveto + 113 341.667 126 319.667 152 303 curveto + 156 301 lineto + 264 237 lineto + 304 213 329.333 188 340 162 curveto + 345.333 148.667 348 134 348 118 curveto + 348 82.6667 334 52.3333 306 27 curveto + 278 2.33333 245 -10 207 -10 curveto + 191 -10 162.667 -5.66667 122 3 curveto + 106 6.33333 94.6667 8 88 8 curveto + 78.6667 8 72 5.33333 68 0 curveto + 66.6667 -0.666667 65.6667 -2 65 -4 curveto + 52 -4 lineto + 52 152 lineto + 68 152 lineto + 75.3333 120 81.6667 97.3333 87 84 curveto + 109 36 145 12 195 12 curveto + 231 12 255.667 24 269 48 curveto + 275 58.6667 278 70.6667 278 84 curveto + 278 114.667 260.667 139.667 226 159 curveto + 168 192 lineto + 114 222.667 79 252.667 63 282 curveto + 55 298 51 316 51 336 curveto + 51 376 66.3333 407.667 97 431 curveto + 121.667 449.667 151.667 459 187 459 curveto + 211 459 235.333 454.667 260 446 curveto + 270.667 442 278.667 440 284 440 curveto + closepath + } bind def + /t { 277 0 13 -10 279 579 setcachedevice + 255 450 moveto + 255 418 lineto + 154 418 lineto + 154 132 lineto + 154 84.6667 164 56 184 46 curveto + 190 43.3333 197.333 42 206 42 curveto + 225.333 42 243.667 51.6667 261 71 curveto + 263 73 264.667 75 266 77 curveto + 279 66 lineto + 245.667 16.6667 205.667 -8.66667 159 -10 curveto + 99.6667 -10 70 32.3333 70 117 curveto + 70 418 lineto + 17 418 lineto + 14.3333 419.333 13 421.667 13 425 curveto + 13 429.667 15.6667 433.667 21 437 curveto + 38.3333 448.333 54 461.333 68 476 curveto + 86 494.667 105.667 519.667 127 551 curveto + 132.333 559 139 568.333 147 579 curveto + 151 579 153 576.667 153 572 curveto + 153.667 570.667 154 568.667 154 566 curveto + 154 450 lineto + 255 450 lineto + closepath + } bind def + /u { 500 0 9 -10 479 450 setcachedevice + 479 50 moveto + 479 36 lineto + 424.333 21.3333 378.667 6.33333 342 -9 curveto + 338 -7 lineto + 338 76 lineto + 295 33 lineto + 271 8.33333 241.333 -5.66667 206 -9 curveto + 201.333 -9.66667 196.667 -10 192 -10 curveto + 148.667 -10 116 6 94 38 curveto + 78.6667 60 71 87.3333 71 120 curveto + 71 372 lineto + 71 399.333 64.6667 417 52 425 curveto + 43.3333 431 29 434.667 9 436 curveto + 9 450 lineto + 155 450 lineto + 155 124 lineto + 155 98.6667 164.333 78.3333 183 63 curveto + 195.667 53 210 48 226 48 curveto + 256.667 48 286 59.3333 314 82 curveto + 325.333 90.6667 331.667 105 333 125 curveto + 333 135 lineto + 333 370 lineto + 333 394.667 328.333 411 319 419 curveto + 309.667 427 289.667 431.667 259 433 curveto + 259 450 lineto + 417 450 lineto + 417 107 lineto + 417 81.6667 422 65.3333 432 58 curveto + 440 52.6667 454 50 474 50 curveto + 479 50 lineto + closepath + } bind def + /v { 500 0 19 -14 477 450 setcachedevice + 477 450 moveto + 477 435 lineto + 462.333 433.667 451.667 429.333 445 422 curveto + 437 413.333 426 391.667 412 357 curveto + 284 36 lineto + 271.333 4.66667 262 -12 256 -14 curveto + 249.333 -14 240.667 1.66667 230 33 curveto + 110 320 lineto + 86 372.667 69.6667 405 61 417 curveto + 52.3333 427.667 40.6667 433.667 26 435 curveto + 19 435 lineto + 19 450 lineto + 215 450 lineto + 215 435 lineto + 189.667 433 175 427 171 417 curveto + 169.667 414.333 169 411 169 407 curveto + 169 395.667 172 383.333 178 370 curveto + 280 114 lineto + 379 373 lineto + 383 383 385 393 385 403 curveto + 385 421.667 369.333 432.333 338 435 curveto + 338 450 lineto + 477 450 lineto + closepath + } bind def + /w { 721 0 21 -14 694 450 setcachedevice + 351 310 moveto + 333 365.333 318.667 400 308 414 curveto + 299.333 424.667 286.667 431.333 270 434 curveto + 268 434.667 265.333 435 262 435 curveto + 262 450 lineto + 465 450 lineto + 465 435 lineto + 435.667 431 418 425 412 417 curveto + 408.667 413 407 407 407 399 curveto + 407 391 409.333 380.333 414 367 curveto + 416 362.333 419.333 353.333 424 340 curveto + 508 116 lineto + 598 338 lineto + 609.333 366.667 615 388.667 615 404 curveto + 615 414.667 609 422.667 597 428 curveto + 591 430.667 582.333 433 571 435 curveto + 571 450 lineto + 694 450 lineto + 694 435 lineto + 683.333 431.667 675.333 426 670 418 curveto + 666.667 412.667 661 400.333 653 381 curveto + 515 35 lineto + 503.667 5.66667 495.667 -10.3333 491 -13 curveto + 489.667 -13.6667 488.333 -14 487 -14 curveto + 483 -14 478.667 -9 474 1 curveto + 471.333 7 467.667 16.3333 463 29 curveto + 372 265 lineto + 260 25 lineto + 248 -1 239.667 -14 235 -14 curveto + 229.667 -14 221 0.666667 209 30 curveto + 74 372 lineto + 60.6667 402.667 50 421.333 42 428 curveto + 36.6667 432 29.6667 434.333 21 435 curveto + 21 450 lineto + 201 450 lineto + 201 435 lineto + 176.333 432.333 161.667 425.667 157 415 curveto + 155.667 411.667 155 407.333 155 402 curveto + 155 392.667 157 382.667 161 372 curveto + 260 111 lineto + 351 310 lineto + closepath + } bind def + /x { 500 0 17 0 479 450 setcachedevice + 248 304 moveto + 304 385 lineto + 311.333 396.333 315 405.667 315 413 curveto + 315 423 308.667 429.333 296 432 curveto + 290.667 433.333 283.667 434.333 275 435 curveto + 275 450 lineto + 433 450 lineto + 433 435 lineto + 401.667 434.333 376 421.667 356 397 curveto + 352 391 lineto + 269 271 lineto + 397 75 lineto + 417.667 45 436.333 26.6667 453 20 curveto + 460.333 16.6667 469 15 479 15 curveto + 479 0 lineto + 278 0 lineto + 278 15 lineto + 299.333 16.3333 311.667 19.6667 315 25 curveto + 317 28.3333 318 33 318 39 curveto + 318 45 316 51 312 57 curveto + 221 197 lineto + 142 74 lineto + 128.667 54 122 40.3333 122 33 curveto + 122 23 130.667 17.3333 148 16 curveto + 152 15.3333 156.667 15 162 15 curveto + 162 0 lineto + 17 0 lineto + 17 15 lineto + 35.6667 17 50 21.6667 60 29 curveto + 68 36.3333 78 48.6667 90 66 curveto + 204 231 lineto + 110 375 lineto + 90.6667 403.667 74.6667 421.667 62 429 curveto + 54 433 44.3333 435 33 435 curveto + 24 435 lineto + 24 450 lineto + 231 450 lineto + 231 435 lineto + 202.333 434.333 188 427 188 413 curveto + 188 400.333 203.333 370.667 234 324 curveto + 248 304 lineto + closepath + } bind def + /y { 500 0 14 -218 475 450 setcachedevice + 151 -134 moveto + 168.333 -134 187.667 -114 209 -74 curveto + 226.333 -40.6667 236.667 -12.3333 240 11 curveto + 240.667 14.3333 241 17 241 19 curveto + 241 33.6667 226.333 67.3333 197 120 curveto + 182 150 lineto + 65 404 lineto + 57 421.333 40 432 14 436 curveto + 14 450 lineto + 220 450 lineto + 220 435 lineto + 187.333 433.667 168.667 427.667 164 417 curveto + 162.667 415 162 412 162 408 curveto + 162 398 165.333 385.333 172 370 curveto + 287 117 lineto + 384 393 lineto + 386.667 399 388 404.667 388 410 curveto + 388 426.667 372 435 340 435 curveto + 340 450 lineto + 475 450 lineto + 475 435 lineto + 458.333 433 446 425.333 438 412 curveto + 434 406.667 430.333 399.333 427 390 curveto + 273 -18 lineto + 239 -110 204 -169.333 168 -196 curveto + 149.333 -210.667 128 -218 104 -218 curveto + 76 -218 55.3333 -209.333 42 -192 curveto + 34 -182.667 30 -172 30 -160 curveto + 30 -144 36.6667 -131.667 50 -123 curveto + 57.3333 -118.333 65 -116 73 -116 curveto + 87.6667 -116 106.667 -120.333 130 -129 curveto + 139.333 -132.333 146.333 -134 151 -134 curveto + closepath + } bind def + /z { 443 0 27 0 418 450 setcachedevice + 272 30 moveto + 319.333 30 351.667 38 369 54 curveto + 379.667 65.3333 388.667 86.3333 396 117 curveto + 396.667 121.667 398 129 400 139 curveto + 418 135 lineto + 404 0 lineto + 27 0 lineto + 27 15 lineto + 293 420 lineto + 155 420 lineto + 125 420 104.667 414.667 94 404 curveto + 83.3333 392.667 75.6667 368.667 71 332 curveto + 53 332 lineto + 56 450 lineto + 403 450 lineto + 403 435 lineto + 134 30 lineto + 272 30 lineto + closepath + } bind def + /braceleft { 479 0 100 -181 350 680 setcachedevice + 350 -181 moveto + 294.667 -180.333 255.333 -172.667 232 -158 curveto + 202 -139.333 186.333 -103 185 -49 curveto + 185 -41 lineto + 185 136 lineto + 185 172.667 178.333 199 165 215 curveto + 152.333 228.333 130.667 240 100 250 curveto + 134.667 260.667 157.667 274 169 290 curveto + 179.667 304.667 185 329 185 363 curveto + 185 541 lineto + 185 597.667 200 636 230 656 curveto + 252 670.667 290.333 678.667 345 680 curveto + 350 680 lineto + 350 669 lineto + 312 659 286.667 643.667 274 623 curveto + 264 605.667 259 580 259 546 curveto + 259 378 lineto + 259 335.333 252.333 305.333 239 288 curveto + 226.333 272 201.667 259 165 249 curveto + 202.333 239.667 227.333 226.333 240 209 curveto + 252.667 192.333 259 163 259 121 curveto + 259 -47 lineto + 259 -89.6667 267.667 -120 285 -138 curveto + 298.333 -151.333 320 -162 350 -170 curveto + 350 -181 lineto + closepath + } bind def + /bar { 199 0 67 -14 133 676 setcachedevice + 67 -14 moveto + 67 676 lineto + 133 676 lineto + 133 -14 lineto + 67 -14 lineto + closepath + } bind def + /braceright { 479 0 130 -181 380 680 setcachedevice + 130 680 moveto + 180.667 679.333 217 673.667 239 663 curveto + 274.333 645 293 606.667 295 548 curveto + 295 540 lineto + 295 363 lineto + 295 325.667 301.667 299.333 315 284 curveto + 327 270.667 348.667 259.333 380 250 curveto + 345.333 238.667 322.333 225 311 209 curveto + 300.333 194.333 295 170 295 136 curveto + 295 -42 lineto + 295 -98.6667 280 -137 250 -157 curveto + 228 -171.667 189.667 -179.667 135 -181 curveto + 130 -181 lineto + 130 -170 lineto + 168 -160 193.333 -144.667 206 -124 curveto + 216 -106.667 221 -81 221 -47 curveto + 221 121 lineto + 221 163.667 227.667 193.667 241 211 curveto + 253.667 227 278.333 240 315 250 curveto + 278.333 259.333 253.667 272 241 288 curveto + 227.667 305.333 221 335.333 221 378 curveto + 221 546 lineto + 221 588.667 212.333 619 195 637 curveto + 181.667 650.333 160 661 130 669 curveto + 130 680 lineto + closepath + } bind def + /asciitilde { 540 0 40 186 502 320 setcachedevice + 163 320 moveto + 195 320 229.333 310.667 266 292 curveto + 297.333 275.333 314.667 266 318 264 curveto + 338 256 356.667 252 374 252 curveto + 394 252 411 259 425 273 curveto + 431.667 280.333 439.333 290.333 448 303 curveto + 502 271 lineto + 472.667 231 446.333 205.667 423 195 curveto + 410.333 189 395.667 186 379 186 curveto + 347 186 312.667 195.333 276 214 curveto + 244.667 230.667 227.333 240 224 242 curveto + 204 250 185.333 254 168 254 curveto + 148 254 131 247 117 233 curveto + 110.333 226.333 102.667 216.333 94 203 curveto + 40 235 lineto + 68.6667 275 95 300.333 119 311 curveto + 131.667 317 146.333 320 163 320 curveto + closepath + } bind def +end +currentdict end +/FreeSerif exch definefont diff --git a/graphics/Makefile b/graphics/Makefile new file mode 100644 index 00000000..b1bb4852 --- /dev/null +++ b/graphics/Makefile @@ -0,0 +1,60 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/graphics/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +MODULE = graphics +MAGICDIR = .. +BASE_SRCS = grMain.c grLock.c grDStyle.c grText.c grCMap.c grClip.c \ + grGlyphs.c grNull.c W3Dmain.c +X11_SRCS = grX11su1.c grX11su2.c grX11su3.c grX11su4.c grX11su5.c +TK_SRCS = grTk1.c grTk2.c grTk3.c grTk4.c grTk5.c +TOGL_SRCS = grTOGL1.c grTOGL2.c grTOGL3.c grTOGL4.c grTOGL5.c +OGL_SRCS = grOGL1.c grOGL2.c grOGL3.c grOGL4.c grOGL5.c + +GLYPHS = bw.glyphs color.glyphs +OUTLINE_FONTS = FreeSerif.pt3 FreeSans.pt3 FreeMono.pt3 + +TKCOMMON_SRCS = grTkCommon.c +X11THREAD_SRCS = grX11thread.c +X11HELPER_SRCS = X11Helper.c +X11HELP_PROG = XHelper7 + +# Sets ${GR_SRCS} to one or more of the above +include ${MAGICDIR}/defs.mak + +SRCS = ${BASE_SRCS} ${GR_SRCS} +DEPSRCS = ${BASE_SRCS} ${X11_SRCS} ${TK_SRCS} ${TOGL_SRCS} ${TKCOMMON_SRCS} \ + ${OGL_SRCS} ${X11HELPER_SRCS} ${X11THREAD_SRCS} +OBJS = ${BASE_SRCS:.c=.o} ${GR_SRCS:.c=.o} +CFLAGS += ${GR_CFLAGS} +DFLAGS += ${GR_DFLAGS} +CLEANS += ${GR_HELPER_PROG} *.o +LIBS += ${GR_LIBS} + +main: ${GR_HELPER_PROG} + +${GR_HELPER_PROG}: ${GR_HELPER_SRCS} + @echo --- building main ${GR_HELPER_PROG} + ${RM} ${GR_HELPER_PROG} + ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${GR_HELPER_SRCS} \ + -o ${GR_HELPER_PROG} ${LIBS} + +install: $(DESTDIR)${BINDIR}/${GR_HELPER_PROG} glyphs fonts + +install-tcl: glyphs fonts + +$(DESTDIR)${BINDIR}/${GR_HELPER_PROG}: ${GR_HELPER_PROG} + ${RM} $(DESTDIR)${BINDIR}/${GR_HELPER_PROG} + ${CP} ${GR_HELPER_PROG} $(DESTDIR)${BINDIR} + +glyphs: ${GLYPHS} + for i in ${GLYPHS}; do \ + ${RM} $(DESTDIR)${SYSDIR}/$$i; \ + ${CP} $$i $(DESTDIR)${SYSDIR}; done + +fonts: ${OUTLINE_FONTS} + for i in ${OUTLINE_FONTS}; do \ + ${RM} $(DESTDIR)${SYSDIR}/$$i; \ + ${CP} $$i $(DESTDIR)${SYSDIR}; done + +include ${MAGICDIR}/rules.mak diff --git a/graphics/README.X10a b/graphics/README.X10a new file mode 100644 index 00000000..abe768f9 --- /dev/null +++ b/graphics/README.X10a @@ -0,0 +1,2 @@ +This driver is a modification of the Stanford X10 driver. The modifications +were done by Walter Scott and Eric Lunow at Lawrence Livermore National Labs. diff --git a/graphics/READ_ME b/graphics/READ_ME new file mode 100644 index 00000000..c7cf7cea --- /dev/null +++ b/graphics/READ_ME @@ -0,0 +1,21 @@ +rcsid = "$Header: /usr/cvsroot/magic-8.0/graphics/READ_ME,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + + + Overall organization of Magic's graphics directory + +In this directory are files to allow Magic to write to a display, going +directly to the frame buffer or instead to a window package such as X. + +For each display supported, there is a driver contained in the files +grXXX1.c through grXXX5.c, and grXXXInt.h. The .c files contain +the code for the driver, and basically just include implementations of +routines listed in graphics.h. The grXXXInt.h file contains internal +(thus the "Int") definitions used by the driver. + +Each driver is given a unique prefix. "Aed" is used for Aed displays, +"SunW" is used for the Sun window system driver, and "X11" is given +for the X11 window system. Multiple drivers can be created, for instance +you could have "X11a" and "X11b" drivers. A table near the start of +grMain.c shows which drivers are available, and how they map to the +"-d" option on Magic's command line. The Makefile must be updated, of +course, to include the .o files for whatever drivers you wish to include. diff --git a/graphics/W3Dmain.c b/graphics/W3Dmain.c new file mode 100644 index 00000000..55c561df --- /dev/null +++ b/graphics/W3Dmain.c @@ -0,0 +1,1874 @@ +/* + * W3Dmain.c -- + * + * Procedures to interface the 3D rendering window with the window package + * for the purposes of window creation, deletion, and modification. + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + */ + +#include +#include +#include + +/* This file is only applicable for OpenGL-enabled graphics; THREE_D is */ +/* defined by the "make config" process and includes all preconditions. */ +#ifdef THREE_D + +#include +#include +#include + +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/undo.h" +#include "database/database.h" +#include "utils/main.h" +#include "commands/commands.h" +#include "graphics/wind3d.h" +#include "graphics/graphicsInt.h" +#include "graphics/graphics.h" +#include "grTOGLInt.h" +#include "textio/textio.h" +#include "textio/txcommands.h" +#include "utils/utils.h" +#include "utils/styles.h" +#include "dbwind/dbwtech.h" +#include "dbwind/dbwind.h" +#include "extract/extract.h" +#include "graphics/glyphs.h" +#include "utils/malloc.h" +#include "windows/windInt.h" /* for access to redisplay pointer */ +#include "cif/cif.h" +#include "cif/CIFint.h" /* access to CIFPlanes, CIFCurStyle, etc. */ + +extern Display *grXdpy; /* X11 display */ +extern GLXContext grXcontext; /* OpenGL/X11 interface def. */ +extern XVisualInfo *grVisualInfo; /* OpenGL preferred visual */ +extern char *MainDisplayType; /* make sure we're using OpenGL */ +extern HashTable grTOGLWindowTable; +extern int grXscrn; +extern int grCurFill; + +static bool w3dNeedStyle; +static bool w3dIsLocked; +static int w3dStyle; +static MagWindow *w3dWindow; +extern bool grDriverInformed; + +extern void grInformDriver(); + +global WindClient W3DclientID; + +#define glTransYs(n) (DisplayHeight(grXdpy, grXscrn)-(n)) + +/* forward declarations */ + +void W3DCIFredisplay(); +void W3Dredisplay(); +void Set3DDefaults(); +void w3drefreshFunc(); +bool W3Ddelete(); + +/* ------------------------Low-Level Routines--------------------------------- */ + +void +w3dLock(w) + MagWindow *w; +{ + grSimpleLock(w, TRUE); + w3dSetProjection(w); +} + +void +w3dUnlock(w) + MagWindow *w; +{ + glFlush(); + glFinish(); + + glDisable(GL_CULL_FACE); + + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDisable(GL_POLYGON_SMOOTH); + + grSimpleUnlock(w); +} + +/* -------------------Low-Level Drawing Routines------------------------------ */ + +void +w3dFillEdge(bbox, r, ztop, zbot) + Rect *bbox; /* tile bounding box */ + Rect *r; + float ztop; + float zbot; +{ + float ztmp; + float xbot = (float)r->r_xbot; + float ybot = (float)r->r_ybot; + float xtop = (float)r->r_xtop; + float ytop = (float)r->r_ytop; + + if (ytop == bbox->r_ybot || xbot == bbox->r_xtop) + { + /* reverse z top and bottom so rectangle is drawn */ + /* counterclockwise as seen from the outside. */ + + ztmp = zbot; + zbot = ztop; + ztop = ztmp; + } + + glBegin(GL_POLYGON); + glVertex3f(xbot, ybot, zbot); + glVertex3f(xbot, ybot, ztop); + glVertex3f(xtop, ytop, ztop); + glVertex3f(xtop, ytop, zbot); + glEnd(); +} + +void +w3dFillPolygon(p, np, zval, istop) + Point *p; + int np; + float zval; + bool istop; +{ + int i; + + glBegin(GL_POLYGON); + if (istop) /* counterclockwise */ + for (i = 0; i < np; i++) + glVertex3f((float)(p[i].p_x), (float)(p[i].p_y), zval); + else /* clockwise */ + for (i = np - 1; i >= 0; i--) + glVertex3f((float)(p[i].p_x), (float)(p[i].p_y), zval); + + glEnd(); +} + +void +w3dFillTile(r, zval, istop) + Rect *r; + float zval; + bool istop; +{ + float xbot, ybot, xtop, ytop; + + ybot = (float)r->r_ybot; + ytop = (float)r->r_ytop; + + if (istop) + { + xbot = (float)r->r_xbot; + xtop = (float)r->r_xtop; + } + else /* makes path counterclockwise as seen from the bottom */ + { + xbot = (float)r->r_xtop; + xtop = (float)r->r_xbot; + } + + glBegin(GL_POLYGON); + glVertex3f(xbot, ybot, zval); + glVertex3f(xtop, ybot, zval); + glVertex3f(xtop, ytop, zval); + glVertex3f(xbot, ytop, zval); + glEnd(); +} + +void +w3dFillXSide(xstart, xend, yval, ztop, zbot) + float xstart, xend, yval, ztop, zbot; +{ + glBegin(GL_POLYGON); + glVertex3f(xstart, yval, zbot); + glVertex3f(xstart, yval, ztop); + glVertex3f(xend, yval, ztop); + glVertex3f(xend, yval, zbot); + glEnd(); +} + +void +w3dFillYSide(xval, ystart, yend, ztop, zbot) + float xval, ystart, yend, ztop, zbot; +{ + glBegin(GL_POLYGON); + glVertex3f(xval, ystart, zbot); + glVertex3f(xval, ystart, ztop); + glVertex3f(xval, yend, ztop); + glVertex3f(xval, yend, zbot); + glEnd(); +} + +/* This routine assumes that vector (x1,y1)->(x2,y2) is in the */ +/* counterclockwise direction with respect to the tile interior. */ + +void +w3dFillDiagonal(x1, y1, x2, y2, ztop, zbot) + float x1, y1, x2, y2, ztop, zbot; +{ + glBegin(GL_POLYGON); + glVertex3f(x1, y1, zbot); + glVertex3f(x2, y2, zbot); + glVertex3f(x2, y2, ztop); + glVertex3f(x1, y1, ztop); + glEnd(); +} + +void +w3dFillOps(trans, tile, cliprect, ztop, zbot) + Transform *trans; + Tile *tile; + Rect *cliprect; + float ztop; + float zbot; +{ + LinkedRect *tilesegs, *segptr; + Rect r, r2; + float xbot, ybot, xtop, ytop; + Point p[5]; + int np; + + r2.r_xbot = LEFT(tile); + r2.r_ybot = BOTTOM(tile); + r2.r_xtop = RIGHT(tile); + r2.r_ytop = TOP(tile); + + GeoTransRect(trans, &r2, &r); + + if (IsSplit(tile)) + { + Rect fullr; + TileType dinfo; + + dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans); + + fullr = r; + if (cliprect != NULL) + GeoClip(&r, cliprect); + + GrClipTriangle(&fullr, &r, cliprect != NULL, dinfo, p, &np); + + if (np > 0) + { + w3dFillPolygon(p, np, ztop, TRUE); + w3dFillPolygon(p, np, zbot, FALSE); + } + } + else + { + /* Clip the tile area to the clipping area */ + if (cliprect != NULL) + GeoClip(&r, cliprect); + + /* draw tile top and bottom */ + if (!GEO_RECTNULL(&r)) + { + w3dFillTile(&r, ztop, TRUE); + w3dFillTile(&r, zbot, FALSE); + } + } + + /* If height is zero, don't bother to draw sides */ + if (ztop == zbot) return; + + /* Find tile outline and render sides */ + + if (GrBoxOutline(tile, &tilesegs)) + { + xbot = (float)r.r_xbot; + ybot = (float)r.r_ybot; + xtop = (float)r.r_xtop; + ytop = (float)r.r_ytop; + + if (r.r_xtop != r.r_xbot) + { + w3dFillXSide(xtop, xbot, ybot, ztop, zbot); + w3dFillXSide(xbot, xtop, ytop, ztop, zbot); + } + if (r.r_ytop != r.r_ybot) + { + w3dFillYSide(xbot, ybot, ytop, ztop, zbot); + w3dFillYSide(xtop, ytop, ybot, ztop, zbot); + } + } + else + { + for (segptr = tilesegs; segptr != NULL; segptr = segptr->r_next) + { + GeoTransRect(trans, &segptr->r_r, &r2); + if (cliprect != NULL) + { + if (GEO_OVERLAP(cliprect, &r2)) + { + GeoClip(&r2, cliprect); + w3dFillEdge(&r, &r2, ztop, zbot); + } + } + else + w3dFillEdge(&r, &r2, ztop, zbot); + freeMagic(segptr); + } + + /* For non-manhattan tiles, GrBoxOutline only returns */ + /* the manhattan edges. This leaves the (possibly */ + /* clipped) diagonal edge to render. */ + + if (IsSplit(tile)) + { + int cp; + for (cp = 0; cp < np - 1; cp++) + { + if ((p[cp].p_x != p[cp + 1].p_x) && (p[cp].p_y != p[cp + 1].p_y)) + { + w3dFillDiagonal((float)p[cp].p_x, (float)p[cp].p_y, + (float)p[cp + 1].p_x, (float)p[cp + 1].p_y, + ztop, zbot); + break; + } + } + if (cp == (np - 1)) + if ((p[cp].p_x != p[0].p_x) && (p[cp].p_y != p[0].p_y)) + w3dFillDiagonal((float)p[cp].p_x, (float)p[cp].p_y, + (float)p[0].p_x, (float)p[0].p_y, + ztop, zbot); + } + + /* Render edges cut by the clipping area, if they're */ + /* inside the tile, so the tile doesn't look "hollow". */ + + if (cliprect != NULL) + { + xbot = (float)r.r_xbot; + ybot = (float)r.r_ybot; + xtop = (float)r.r_xtop; + ytop = (float)r.r_ytop; + + if (r.r_ytop > r.r_ybot) + { + if (r.r_xtop == cliprect->r_xtop) + w3dFillYSide(xtop, ytop, ybot, ztop, zbot); + if (r.r_xbot == cliprect->r_xbot) + w3dFillYSide(xbot, ybot, ytop, ztop, zbot); + } + if (r.r_xtop > r.r_xbot) + { + if (r.r_ytop == cliprect->r_ytop) + w3dFillXSide(xbot, xtop, ytop, ztop, zbot); + if (r.r_ybot == cliprect->r_ybot) + w3dFillXSide(xtop, xbot, ybot, ztop, zbot); + } + } + } +} + +void +w3dRenderVolume(tile, trans, cliprect) + Tile *tile; + Transform *trans; + Rect *cliprect; +{ + float zbot, ztop; + float ftop = 0.0, fthk = 0.0; + W3DclientRec *crec; + + crec = (W3DclientRec *)(w3dWindow->w_clientData); + + ExtGetZAxis(tile, &ftop, &fthk); + + /* Negate z-axis values for OpenGL display */ + ztop = -ftop * crec->scale_z; + zbot = ztop - (fthk * crec->scale_z); + + GR_CHECK_LOCK(); + if (!grDriverInformed) + grInformDriver(); + + if ((grCurFill == GR_STSOLID) || (grCurFill == GR_STSTIPPLE)) + { + w3dFillOps(trans, tile, cliprect, ztop, zbot); + } + + /* To do: Outlines and contact crosses */ + /* To do: Labels */ +} + +void +w3dRenderCIF(tile, layer, trans) + Tile *tile; + CIFLayer *layer; + Transform *trans; +{ + float zbot, ztop; + float ftop, fthk; + W3DclientRec *crec; + + crec = (W3DclientRec *)(w3dWindow->w_clientData); + + ftop = layer->cl_height; + fthk = layer->cl_thick; + + /* Negate z-axis values for OpenGL display */ + ztop = -ftop * crec->scale_z; + zbot = ztop - (fthk * crec->scale_z); + + GR_CHECK_LOCK(); + if (!grDriverInformed) + grInformDriver(); + + if ((grCurFill == GR_STSOLID) || (grCurFill == GR_STSTIPPLE)) + { + w3dFillOps(trans, tile, NULL, ztop, zbot); + } + + /* To do: Outlines */ + /* To do: Labels */ +} + +void +w3dClear() +{ + float fr, fg, fb; + int cidx, lr, lb, lg; + + /* STYLE_TRANSPARENT uses the background color definition, */ + /* so we get RGB values from there. */ + + cidx = GrStyleTable[STYLE_TRANSPARENT].color; + GrGetColor(cidx, &lr, &lg, &lb); + + fr = ((GLfloat)lr / 255); + fg = ((GLfloat)lg / 255); + fb = ((GLfloat)lb / 255); + + glClearColor(fr, fg, fb, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +/* -------------------High-Level Drawing Routines------------------------------ */ + +void +w3dSetProjection(w) + MagWindow *w; +{ + W3DclientRec *crec; + Window wind; + GLfloat light0_pos[] = { 0.0, 0.0, 0.0, 0.0 }; /* light #0 position */ + GLfloat light0_amb[] = { 0.4, 0.4, 0.4, 1.0 }; /* light #0 ambient int. */ + GLfloat light0_dif[] = { 0.0, 0.0, 0.0, 1.0 }; /* light #0 diffuse int. */ + + GLfloat light1_pos[] = { 50.0, 50.0, 50.0, 1.0 }; /* light #1 position */ + GLfloat light1_amb[] = { 0.0, 0.0, 0.0, 1.0 }; /* light #1 ambient int. */ + GLfloat light1_dif[] = { 1.0, 1.0, 1.0, 1.0 }; /* light #1 diffuse int. */ + + crec = (W3DclientRec *) w->w_clientData; + wind = Tk_WindowId((Tk_Window)w->w_grdata); + if (wind == 0) return; /* window was closed by window manager? */ + + /* Should not mess with surfaceArea---we want the area to be displayed */ + /* in crec, in magic internal coordinates, set by the edit box (else- */ + /* where). Set the viewport to maintain 1:1 x:y aspect ratio on the */ + /* rendered volume. */ + + glXMakeCurrent(grXdpy, (GLXDrawable)wind, grXcontext); + + if (crec->level > 0) + { + glEnable(GL_LINE_SMOOTH); + glEnable(GL_POLYGON_SMOOTH); + } + + /* Need to look into dealing properly with double-buffered graphics */ + glDrawBuffer(GL_FRONT); + /* glDrawBuffer(GL_BACK); */ + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + /* Lighting */ + + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); + + glLightfv(GL_LIGHT0, GL_POSITION, light0_pos); /* positional */ + glLightfv(GL_LIGHT0, GL_AMBIENT, light0_amb); /* ambient */ + glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_dif); /* diffuse */ + + glLightfv(GL_LIGHT1, GL_POSITION, light1_pos); /* directional */ + glLightfv(GL_LIGHT1, GL_AMBIENT, light1_amb); /* ambient */ + glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_dif); /* diffuse */ + + /* Fill front-facing polygons only */ + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + /* Preserve aspect ratio of 1:1 for internal units on the display */ + + glScalef((GLfloat)crec->height / (GLfloat)crec->width, 1.0, 1.0); + glViewport((GLsizei)0, (GLsizei)0, (GLsizei)crec->width, (GLsizei)crec->height); + + /* Projection matrix manipulations */ + + glScalef(crec->scale_xy, crec->scale_xy, crec->prescale_z); + + glRotatef(crec->view_x, 1.0, 0.0, 0.0); + glRotatef(crec->view_y, 0.0, 1.0, 0.0); + glRotatef(crec->view_z, 0.0, 0.0, 1.0); + + glTranslatef(crec->trans_x, crec->trans_y, crec->trans_z); +} + +/* Magic layer tile painting function */ + +int +w3dPaintFunc(tile, cxp) + Tile *tile; /* Tile to be displayed */ + TreeContext *cxp; /* From DBTreeSrTiles */ +{ + SearchContext *scx = cxp->tc_scx; + + /* Allow display interrupt a la dbwPaintFunc(). */ + /* HOWEVER, note that GrEventPendingPtr looks at */ + /* events in the window defined by toglCurrent, */ + /* which is not the 3D window. So rendering in the */ + /* 3D window can only be interrupted by events in */ + /* the layout window. */ + + /* Honor display suspend status */ + if (GrDisplayStatus == DISPLAY_SUSPEND) return 0; + + if (GrDisplayStatus == DISPLAY_BREAK_PENDING) + { + GrDisplayStatus = DISPLAY_IN_PROGRESS; + if (GrEventPendingPtr) + { + if ((*GrEventPendingPtr)()) + sigOnInterrupt(0); + else + SigSetTimer(0); + } + } + + if (!w3dIsLocked) + { + w3dLock(w3dWindow); + w3dIsLocked = TRUE; + } + if (w3dNeedStyle) + { + GrSetStuff(w3dStyle); + w3dNeedStyle = FALSE; + } + + w3dRenderVolume(tile, &scx->scx_trans, &scx->scx_area); + return 0; /* keep the search going! */ +} + +/* CIF layer tile painting function */ + +int +w3dCIFPaintFunc(tile, arg) + Tile *tile; /* Tile to be displayed */ + ClientData *arg; /* is NULL */ +{ + CIFLayer *layer = (CIFLayer *)arg; + + /* Honor display suspend status */ + if (GrDisplayStatus == DISPLAY_SUSPEND) return 0; + + /* Allow display interrupt a la dbwPaintFunc() */ + if (GrDisplayStatus == DISPLAY_BREAK_PENDING) + { + GrDisplayStatus = DISPLAY_IN_PROGRESS; + if (GrEventPendingPtr) + { + if ((*GrEventPendingPtr)()) + sigOnInterrupt(0); + else + SigSetTimer(0); + } + } + + if (!w3dIsLocked) + { + w3dLock(w3dWindow); + w3dIsLocked = TRUE; + } + if (w3dNeedStyle) + { + /* TxError("CIF layer 0x%x (%s) render style %d\n", + layer, + layer->cl_name, + layer->cl_renderStyle); */ + GrSetStuff(layer->cl_renderStyle + TECHBEGINSTYLES); + w3dNeedStyle = FALSE; + } + + w3dRenderCIF(tile, layer, &GeoIdentityTransform); + return 0; /* keep the search going! */ +} + +/* -----------------------Command Procedures------------------------------ */ + +/* + * ---------------------------------------------------------------------------- + * + * w3dHelp -- + * + * Print the list of commands available in this window. + * + * ---------------------------------------------------------------------------- + */ + +void +w3dHelp(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + char **msg; + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (cmd->tx_argc == 1) + { + TxPrintf("\nWind3D command summary:\n"); + for (msg = WindGetCommandTable(W3DclientID); *msg != NULL; msg++) + { + TxPrintf(" %s\n", *msg); + } + TxPrintf("\nType '?' in the window to get a key macro summary.\n"); + } + else + TxError("Usage: help\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dCutBox -- + * + * Set a clipping box for the 3D view + * + * ---------------------------------------------------------------------------- + */ + +void +w3dCutBox(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + bool hide = FALSE; + int lidx = 1, num_layers; + TileTypeBitMask mask; + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (cmd->tx_argc == 1 || cmd->tx_argc == 2 || cmd->tx_argc == 5) + { + if (cmd->tx_argc == 1) + { + if (crec->clipped) + { + Tcl_Obj *rlist = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(magicinterp, rlist, + Tcl_NewIntObj((int)(crec->cutbox.r_xbot))); + Tcl_ListObjAppendElement(magicinterp, rlist, + Tcl_NewIntObj((int)(crec->cutbox.r_ybot))); + Tcl_ListObjAppendElement(magicinterp, rlist, + Tcl_NewIntObj((int)(crec->cutbox.r_xtop))); + Tcl_ListObjAppendElement(magicinterp, rlist, + Tcl_NewIntObj((int)(crec->cutbox.r_ytop))); + + Tcl_SetObjResult(magicinterp, rlist); + } + else + Tcl_SetResult(magicinterp, "none", NULL); + } + else if (cmd->tx_argc == 2) + { + if (!strcmp(cmd->tx_argv[1], "none")) + crec->clipped = FALSE; + if (!strcmp(cmd->tx_argv[1], "box")) + { + Rect rootBox; + CellDef *rootBoxDef; + CellDef *cellDef = ((CellUse *)w->w_surfaceID)->cu_def; + + if (ToolGetBox(&rootBoxDef, &rootBox)) + { + if (rootBoxDef == cellDef) + { + crec->clipped = TRUE; + crec->cutbox = rootBox; + } + } + } + w3drefreshFunc(w); + } + else + { + if (StrIsInt(cmd->tx_argv[1]) && + StrIsInt(cmd->tx_argv[2]) && + StrIsInt(cmd->tx_argv[3]) && + StrIsInt(cmd->tx_argv[4])) + { + crec->clipped = TRUE; + crec->cutbox.r_xbot = atoi(cmd->tx_argv[1]); + crec->cutbox.r_ybot = atoi(cmd->tx_argv[2]); + crec->cutbox.r_xtop = atoi(cmd->tx_argv[3]); + crec->cutbox.r_ytop = atoi(cmd->tx_argv[4]); + w3drefreshFunc(w); + } + } + } + else + TxError("Usage: cutbox [none|box|llx lly urx ur]\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dSeeLayers -- + * + * See or hide layers from the 3D view + * + * ---------------------------------------------------------------------------- + */ + +void +w3dSeeLayers(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + bool hide = FALSE; + int lidx = 1, num_layers; + TileTypeBitMask mask; + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (cmd->tx_argc == 2 || cmd->tx_argc == 3) + { + if (cmd->tx_argc == 3) + { + lidx = 2; + if (!strcmp(cmd->tx_argv[1], "no")) hide = TRUE; + } + + if (crec->cif) + { + /* If CIF layers, match the layer name (1 only) */ + if (!CIFNameToMask(cmd->tx_argv[lidx], &mask)) + return; + } + else + { + /* If normal layers, pick up the name with TechType */ + if (!CmdParseLayers(cmd->tx_argv[lidx], &mask)) + return; + } + if (hide) + TTMaskClearMask(&crec->visible, &mask); + else + TTMaskSetMask(&crec->visible, &mask); + + w3drefreshFunc(w); + } + else + TxError("Usage: see [no] layer\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dClose -- + * + * Close the 3D display. This corresponds to the command-line command + * "closewindow" and overrides the default window client command of the + * same name. + * + * ---------------------------------------------------------------------------- + */ + +void +w3dClose(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (cmd->tx_argc == 1) + (void) WindDelete(w); + else + TxError("Usage: closewindow\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dRescale -- + * + * Change scale and translation by indicated scalefactor. + * + * ---------------------------------------------------------------------------- + */ + +void +w3dRescale(crec, scalefactor) + W3DclientRec *crec; + float scalefactor; +{ + crec->scale_xy /= scalefactor; + crec->prescale_z /= scalefactor; + + crec->scale_z *= scalefactor; + crec->trans_y *= scalefactor; + crec->trans_x *= scalefactor; +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dToggleCIF -- + * + * Change between CIF and magic layer views + * + * ---------------------------------------------------------------------------- + */ + +void +w3dToggleCIF(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (cmd->tx_argc == 1) + { + + if ((crec->cif == FALSE) && (CIFCurStyle != NULL)) + { + ((clientRec *)(W3DclientID))->w_redisplay = W3DCIFredisplay; + crec->cif = TRUE; + w3dRescale(crec, (float)CIFCurStyle->cs_scaleFactor); + } + else if (crec->cif == TRUE) + { + ((clientRec *)(W3DclientID))->w_redisplay = W3Dredisplay; + crec->cif = FALSE; + w3dRescale(crec, 1.0 / (float)CIFCurStyle->cs_scaleFactor); + } + + w3drefreshFunc(w); + } + else + TxError("Usage: cif\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dLevel -- + * + * Change rendering level + * + * ---------------------------------------------------------------------------- + */ + +void +w3dLevel(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (cmd->tx_argc == 2) + { + if (StrIsInt(cmd->tx_argv[1])) + crec->level = atoi(cmd->tx_argv[1]); + else if (!strcmp(cmd->tx_argv[1], "up")) + crec->level++; + else if (!strcmp(cmd->tx_argv[1], "down")) + crec->level--; + else + { + TxError("Usage: level [|up|down]\n"); + return; + } + + if (crec->level < 0) crec->level = 0; + w3drefreshFunc(w); + } + else if (cmd->tx_argc == 1) + { + Tcl_SetObjResult(magicinterp, Tcl_NewIntObj((int)crec->level)); + } + else + TxError("Usage: level [n]\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * Function to perform refresh on the entire 3D window + * + * ---------------------------------------------------------------------------- + */ + +void +w3drefreshFunc(mw) + MagWindow *mw; +{ + W3DclientRec *crec = (W3DclientRec *) mw->w_clientData; + Rect screenRect; + + screenRect.r_xbot = 0; + screenRect.r_ybot = 0; + screenRect.r_xtop = crec->width; + screenRect.r_ytop = crec->height; + + WindAreaChanged(mw, &screenRect); + WindUpdate(); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dDefaults -- + * + * Revert to display defaults + * + * ---------------------------------------------------------------------------- + */ + +void +w3dDefaults(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (cmd->tx_argc == 1) + { + Set3DDefaults(w, crec); + w3drefreshFunc(w); + } + else + TxError("Usage: defaults\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dRefresh -- + * + * Refresh the display + * + * ---------------------------------------------------------------------------- + */ + +void +w3dRefresh(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (cmd->tx_argc == 1) + w3drefreshFunc(w); + else + TxError("Usage: refresh\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dView -- + * + * Set the viewing angle into the 3D display. Overrides the window + * client command of the same name. + * + * ---------------------------------------------------------------------------- + */ + +void +w3dView(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + bool relative = FALSE; + int argc = cmd->tx_argc; + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (argc == 5) + { + argc--; + if (!strncmp(cmd->tx_argv[argc], "rel", 3)) + relative = TRUE; + else if (strncmp(cmd->tx_argv[argc], "abs", 3)) + { + TxError("Usage: view angle_x angle_y angle_z absolute|relative\n"); + return; + } + } + + if (argc == 4) + { + /* Pick up x, y, z angles */ + + if (StrIsNumeric(cmd->tx_argv[1]) && + StrIsNumeric(cmd->tx_argv[2]) && + StrIsNumeric(cmd->tx_argv[3])) + { + if (relative) + { + crec->view_x += (float)atof(cmd->tx_argv[1]); + crec->view_y += (float)atof(cmd->tx_argv[2]); + crec->view_z += (float)atof(cmd->tx_argv[3]); + } + else + { + crec->view_x = (float)atof(cmd->tx_argv[1]); + crec->view_y = (float)atof(cmd->tx_argv[2]); + crec->view_z = (float)atof(cmd->tx_argv[3]); + } + + /* Call redisplay function */ + w3drefreshFunc(w); + } + } + else if (argc == 1) + { + Tcl_Obj *vlist = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(magicinterp, vlist, + Tcl_NewDoubleObj((double)(crec->view_x))); + Tcl_ListObjAppendElement(magicinterp, vlist, + Tcl_NewDoubleObj((double)(crec->view_y))); + Tcl_ListObjAppendElement(magicinterp, vlist, + Tcl_NewDoubleObj((double)(crec->view_z))); + + Tcl_SetObjResult(magicinterp, vlist); + } + else + TxError("Usage: view [angle_x angle_y angle_z [relative|absolute]]\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dScroll -- + * + * Set the viewing position into the 3D display. + * + * ---------------------------------------------------------------------------- + */ + +void +w3dScroll(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + bool relative = FALSE; + int argc = cmd->tx_argc; + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (argc == 5) + { + argc--; + if (!strncmp(cmd->tx_argv[argc], "rel", 3)) + relative = TRUE; + else if (strncmp(cmd->tx_argv[argc], "abs", 3)) + { + TxError("Usage: scroll pos_x pos_y pos_z absolute|relative\n"); + return; + } + } + + if (argc == 4) + { + /* Pick up x, y, z translations */ + + if (StrIsNumeric(cmd->tx_argv[1]) && + StrIsNumeric(cmd->tx_argv[2]) && + StrIsNumeric(cmd->tx_argv[3])) + { + if (relative) + { + crec->trans_x += (float)atof(cmd->tx_argv[1]) / crec->scale_xy; + crec->trans_y += (float)atof(cmd->tx_argv[2]) / crec->scale_xy; + crec->trans_z += (float)atof(cmd->tx_argv[3]) / crec->scale_xy; + } + else + { + crec->trans_x = (float)atof(cmd->tx_argv[1]); + crec->trans_y = (float)atof(cmd->tx_argv[2]); + crec->trans_z = (float)atof(cmd->tx_argv[3]); + } + + /* Call redisplay function */ + w3drefreshFunc(w); + } + } + else if (argc == 1) + { + Tcl_Obj *vlist = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(magicinterp, vlist, + Tcl_NewDoubleObj((double)(crec->trans_x))); + Tcl_ListObjAppendElement(magicinterp, vlist, + Tcl_NewDoubleObj((double)(crec->trans_y))); + Tcl_ListObjAppendElement(magicinterp, vlist, + Tcl_NewDoubleObj((double)(crec->trans_z))); + + Tcl_SetObjResult(magicinterp, vlist); + } + else + TxError("Usage: scroll [pos_x pos_y pos_z [absolute|relative]]\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dZoom -- + * + * Set the viewing scale of the 3D display. Overrides the window + * client command of the same name. + * + * ---------------------------------------------------------------------------- + */ + +void +w3dZoom(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + bool relative = FALSE; + int argc = cmd->tx_argc; + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (argc == 4) + { + argc--; + if (!strncmp(cmd->tx_argv[argc], "rel", 3)) + relative = TRUE; + else if (strncmp(cmd->tx_argv[argc], "abs", 3)) + { + TxError("Usage: zoom scale_xy scale_z relative|absolute\n"); + return; + } + } + + if (argc == 3) + { + /* Pick up xy and z scales */ + + if (StrIsNumeric(cmd->tx_argv[1]) && + StrIsNumeric(cmd->tx_argv[2])) + { + float xy, z; + xy = (float)atof(cmd->tx_argv[1]); + z = (float)atof(cmd->tx_argv[2]); + if ((xy <= 0) || (z <= 0)) + { + TxError("Error: zoom values/factors must be positive and nonzero\n"); + return; + } + if (relative) + { + crec->scale_xy *= xy; + crec->scale_z *= z; + } + else + { + crec->scale_xy = xy; + crec->scale_z = z; + } + + /* Call redisplay function */ + w3drefreshFunc(w); + } + } + else if (cmd->tx_argc == 1) + { + Tcl_Obj *vlist = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(magicinterp, vlist, + Tcl_NewDoubleObj((double)(crec->scale_xy))); + Tcl_ListObjAppendElement(magicinterp, vlist, + Tcl_NewDoubleObj((double)(crec->scale_z))); + + Tcl_SetObjResult(magicinterp, vlist); + } + else + TxError("Usage: zoom [scale_xy scale_z [relative|absolute]]\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * w3dRenderValues -- + * + * Set values for 3D rendering. These are independent of any + * extraction or other physical meaning, so we allow them to + * be independently controlled here. + * + * ---------------------------------------------------------------------------- + */ + +void +w3dRenderValues(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int lidx; + CIFLayer *layer; + W3DclientRec *crec = (W3DclientRec *) w->w_clientData; + + if (cmd->tx_argc > 1) + { + for (lidx = 0; lidx < CIFCurStyle->cs_nLayers; lidx++) + { + layer = CIFCurStyle->cs_layers[lidx]; + if (!strcmp(layer->cl_name, cmd->tx_argv[1])) + break; + } + + if (lidx == CIFCurStyle->cs_nLayers) + { + TxError("Unknown CIF layer \"%s\"\n", cmd->tx_argv[1]); + return; + } + } + + if (cmd->tx_argc == 2) + { + Tcl_Obj *llist; + llist = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(magicinterp, llist, + Tcl_NewDoubleObj((double)(layer->cl_height))); + Tcl_ListObjAppendElement(magicinterp, llist, + Tcl_NewDoubleObj((double)(layer->cl_thick))); + Tcl_ListObjAppendElement(magicinterp, llist, + Tcl_NewIntObj((int)(layer->cl_renderStyle))); + Tcl_SetObjResult(magicinterp, llist); + } + else if (cmd->tx_argc == 4 || cmd->tx_argc == 5) + { + int style; + float height, thick; + + style = -1; + if (cmd->tx_argc == 5 && StrIsInt(cmd->tx_argv[4])) + style = atoi(cmd->tx_argv[4]); + if (!StrIsNumeric(cmd->tx_argv[3]) || !StrIsNumeric(cmd->tx_argv[2])) + goto badusage; + height = (float)atof(cmd->tx_argv[2]); + thick = (float)atof(cmd->tx_argv[3]); + + /* It is necessary to update ALL layers of the same name */ + for (lidx = 0; lidx < CIFCurStyle->cs_nLayers; lidx++) + { + layer = CIFCurStyle->cs_layers[lidx]; + if (!strcmp(layer->cl_name, cmd->tx_argv[1])) + { + if (style >= 0) layer->cl_renderStyle = style; + layer->cl_height = height; + layer->cl_thick = thick; + } + } + + /* Call redisplay function */ + w3drefreshFunc(w); + } + else + +badusage: + TxError("Usage: render name [height thick [style]]\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * Set3DDefaults -- + * + * Set default values for the viewing parameters (scale, angle, + * and translation in 3 dimensions) + * + * Default view is top-down (layout) view scaled to fit the celldef's + * bounding box in the 3D window. + * + * ---------------------------------------------------------------------------- + */ + +void +Set3DDefaults(mw, crec) + MagWindow *mw; + W3DclientRec *crec; +{ + int height, width; + int centerx, centery; + float scalex, scaley; + + /* Get translation and scale from the cell bounding box */ + /* (= window's bounding box, set in loadWindow proc) */ + + height = mw->w_bbox->r_ytop - mw->w_bbox->r_ybot; + width = mw->w_bbox->r_xtop - mw->w_bbox->r_xbot; + centerx = -(mw->w_bbox->r_xbot + (width >> 1)); + centery = -(mw->w_bbox->r_ybot + (height >> 1)); + + scalex = 2.0 / ((float)width * 1.1); /* Add 10% margins in x and y */ + scaley = 2.0 / ((float)height * 1.1); + + crec->trans_x = (float)centerx; + crec->trans_y = (float)centery; + crec->trans_z = 0.0; + + crec->scale_xy = (scalex > scaley) ? scaley : scalex; + crec->scale_z = 25.0; /* Height exaggerated by 25x */ + + /* The small z-scale value is necessary to keep large layout distances */ + /* from exceeding the OpenGL (-1,1) limits of the z-axis. Distances in Z, */ + /* like layer thickness, simply scale up to compensate. */ + + crec->prescale_z = 0.0001; + + /* layout view (top down) */ + + crec->view_x = 0.0; + crec->view_y = 0.0; + crec->view_z = 0.0; + + TTMaskZero(&crec->visible); + TTMaskSetMask(&crec->visible, &DBAllTypeBits); + + /* Scale all factors appropriately for CIF display */ + + if (crec->cif == TRUE) + w3dRescale(crec, (float)CIFCurStyle->cs_scaleFactor); + + /* Default is no clipping */ + crec->clipped = FALSE; /* no clipping by default */ +} + +/* -----------------------Client Procedures------------------------------ */ + +/* + * ---------------------------------------------------------------------------- + * + * W3DloadWindow -- + * + * Replace the root cell of a window by the specified cell. + * + * Results: + * TRUE if successful, FALSE if not. The 3D rendering window is + * not allowed to create new cells, only to render existing ones. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +W3DloadWindow(window, name) + MagWindow *window; + char *name; +{ + CellDef *newEditDef; + CellUse *newEditUse; + Rect loadBox; + + newEditDef = DBCellLookDef(name); + if (newEditDef == (CellDef *)NULL) + return FALSE; + + if (!DBCellRead(newEditDef, (char *)NULL, TRUE, NULL)) + return FALSE; + + DBReComputeBbox(newEditDef); + loadBox = newEditDef->cd_bbox; + + /* Attach cell to window */ + + newEditUse = DBCellNewUse(newEditDef, (char *) NULL); + (void) StrDup(&(newEditUse->cu_id), "3D rendered cell"); + + window->w_bbox = &(newEditUse->cu_def->cd_bbox); + return WindLoad(window, W3DclientID, (ClientData)newEditUse, &loadBox); +} + +/* + * ---------------------------------------------------------------------------- + * + * W3Dcreate -- + * + * A new window has been created. Create and initialize the needed + * structures. + * + * Results: + * FALSE if we have too many windows, TRUE otherwise. + * + * Side effects: + * Initialize the window to be editing the background color. + * + * ---------------------------------------------------------------------------- + */ + +bool +W3Dcreate(window, argc, argv) + MagWindow *window; + int argc; + char *argv[]; +{ + W3DclientRec *crec; + Tk_Window tkwind, tktop; + Window wind; + Colormap colormap; + HashEntry *entry; + CellDef *boxDef; + Rect box; + bool result; + char *name = NULL; + + /* At least for now, there's only one 3D window allowed. */ + + if (w3dWindow != NULL) + { + TxError("Only one 3D window allowed.\n"); + return FALSE; + } + + /* The 3D rendering, of course, *only* works with OpenGL, so in an */ + /* executable compiled for multiple graphics interfaces, we need */ + /* to make sure that our display type is OpenGL. */ + + if (!GrIsDisplay(MainDisplayType, "OGL")) + { + TxError("Display type is \"%s\". OpenGL is required for the 3D display.\n", + MainDisplayType); + TxError("Please restart magic with option \"-d OGL\".\n"); + return FALSE; + } + + crec = (W3DclientRec *) mallocMagic(sizeof(W3DclientRec)); + + /* The MagWindow structure and frameArea indicates the cross-sectional */ + /* area of the layout to be rendered in the 3D display window. */ + + /* Need to parse the argument list here. . . At least one argument */ + /* should allow the Tk path name to be passed to the routine, as */ + /* it is for the standard layout window in the Tk interface. */ + + /* Set surface area, etc. of the MagWindow. . . ? */ + + /* Initial window height and width (should be passed as optional */ + /* arguments to the specialopen command) */ + + crec->width = 500; + crec->height = 500; + + /* Rendering level (0 = coarse & fast, 1 = finer but slower, etc. */ + /* Render cif by default. */ + + crec->level = 1; + crec->cif = TRUE; + + window->w_clientData = (ClientData) crec; + window->w_flags &= ~(WIND_SCROLLABLE | WIND_SCROLLBARS | WIND_CAPTION | + WIND_BORDER | WIND_COMMANDS); + + /* Load the current cellDef into the window */ + + if ((argc > 0) && (strlen(argv[0]) > 0)) + result = W3DloadWindow(window, argv[0]); + else if (ToolGetBox(&boxDef, &box)) + result = W3DloadWindow(window, boxDef->cd_name); + else + { + MagWindow *mw = NULL; + + windCheckOnlyWindow(&mw, DBWclientID); + if (mw != NULL) + { + boxDef = ((CellUse *)mw->w_surfaceID)->cu_def; + result = W3DloadWindow(window, boxDef->cd_name); + } + else + { + TxError("Ambiguous directive: Put cursor box in one of the windows.\n"); + return FALSE; + } + } + + if (result == FALSE) + { + TxError("Cells cannot be created in the 3D window.\n"); + return result; + } + + /* Generate the window. */ + + colormap = XCreateColormap(grXdpy, RootWindow(grXdpy, DefaultScreen(grXdpy)), + grVisualInfo->visual, AllocNone); + + if (!(tktop = Tk_MainWindow(magicinterp))) return FALSE; + + /* Check for a Tk pathname for the window; allows window to be */ + /* by a Tk GUI script. */ + if (argc > 1) name = argv[1]; + + if (name == NULL) + tkwind = Tk_CreateWindowFromPath(magicinterp, tktop, ".magic3d", ""); + else + tkwind = Tk_CreateWindowFromPath(magicinterp, tktop, name, NULL); + + if (tkwind != 0) + { + window->w_grdata = (ClientData) tkwind; + entry = HashFind(&grTOGLWindowTable, (char *)tkwind); + HashSetValue(entry, window); + + if (name != NULL) + { + /* Visual type must match what we chose in the graphics init proc */ + Tk_SetWindowVisual(tkwind, grVisualInfo->visual, toglCurrent.depth, + colormap); + Tk_MapWindow(tkwind); + Tk_GeometryRequest(tkwind, crec->width, crec->height); + + wind = Tk_WindowId(tkwind); + if (wind == 0) + glXMakeCurrent(grXdpy, (GLXDrawable)wind, grXcontext); + } + + /* execute any pending Tk events */ + + while (Tcl_DoOneEvent(TCL_DONT_WAIT) != 0); + + /* use the OpenGL Tk event handler (see grTOGL1.c) for the 3d window */ + + Tk_CreateEventHandler(tkwind, ExposureMask | StructureNotifyMask | + ButtonPressMask | KeyPressMask, + (Tk_EventProc *)TOGLEventProc, (ClientData)tkwind); + + w3dWindow = window; + + /* Use Tcl to pass commands to the window */ + MakeWindowCommand((name == NULL) ? ".magic3d" : name, window); + + /* Now that a cell is loaded, set default values for the */ + /* client record based on the cell bounding box. */ + + Set3DDefaults(window, crec); + + return TRUE; + } + + TxError("Could not create a new Tk window\n"); + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * W3Ddelete -- + * + * Clean up the data structures before deleting a window. + * + * Results: + * TRUE if we really want to delete the window, FALSE otherwise. + * + * Side effects: + * A W3DclientRec is freed. + * + * ---------------------------------------------------------------------------- + */ + +bool +W3Ddelete(window) + MagWindow *window; +{ + W3DclientRec *cr; + Tk_Window xw; + + cr = (W3DclientRec *) window->w_clientData; + xw = (Tk_Window)window->w_grdata; + w3dWindow = NULL; + + freeMagic((char *)cr); + window->w_clientData = (ClientData)NULL; + xw = (Tk_Window)window->w_grdata; + /* Tk_DestroyWindow(xw); */ + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * W3Dredisplay -- + * + * Redisplay a portion of the 3D rendered layout view + * + * Results: + * None. + * + * Side effects: + * Redisplay is done. + * ---------------------------------------------------------------------------- + */ + +void +W3Dredisplay(w, rootArea, clipArea) + MagWindow *w; /* The window containing the area. */ + Rect *rootArea; /* Ignore this---area defined by window with box */ + Rect *clipArea; /* Ignore this, too */ +{ + W3DclientRec *crec; + CellDef *cellDef; + SearchContext scontext; + Rect largerArea, *clipRect = &largerArea; + int i; + TileTypeBitMask *mask, layers; + + w3dLock(w); + + crec = (W3DclientRec *) w->w_clientData; + cellDef = ((CellUse *)w->w_surfaceID)->cu_def; + + if (crec->clipped) + clipRect = &crec->cutbox; + + if (rootArea != NULL) + largerArea = *rootArea; + else + largerArea = w->w_surfaceArea; + + largerArea.r_xbot--; + largerArea.r_ybot--; + largerArea.r_xtop++; + largerArea.r_ytop++; + + scontext.scx_area = *clipRect; + scontext.scx_use = ((CellUse *)w->w_surfaceID); + scontext.scx_x = scontext.scx_y = -1; + scontext.scx_trans = GeoIdentityTransform; + + w3dClear(); + + /* follow the same locking procedure as DBWredisplay() */ + w3dUnlock(w); + w3dIsLocked = FALSE; + for (i = 0; i < DBWNumStyles; i++) + { + /* This should probably be redesigned. . . */ + mask = DBWStyleToTypes(i); + TTMaskAndMask3(&layers, mask, &crec->visible); + if (!TTMaskIsZero(&layers)) + { + w3dStyle = i + TECHBEGINSTYLES; + w3dNeedStyle = TRUE; + (void) DBTreeSrTiles(&scontext, &layers, 0, + w3dPaintFunc, (ClientData) NULL); + if (w3dIsLocked) + { + w3dUnlock(w); + w3dIsLocked = FALSE; + } + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * W3DCIFredisplay -- + * + * Redisplay a portion of the 3D rendered layout, in CIF layers. + * + * Results: + * None. + * + * Side effects: + * Redisplay is done. + * ---------------------------------------------------------------------------- + */ + +void +W3DCIFredisplay(w, rootArea, clipArea) + MagWindow *w; /* The window containing the area. */ + Rect *rootArea; /* Ignore this---area defined by window with box */ + Rect *clipArea; /* Ignore this, too */ +{ + W3DclientRec *crec; + SearchContext scx; + CellDef *cellDef; + Rect clipRect; + int i; + TileTypeBitMask *mask; + + w3dLock(w); + + crec = (W3DclientRec *) w->w_clientData; + cellDef = ((CellUse *)w->w_surfaceID)->cu_def; + + clipRect = (crec->clipped) ? crec->cutbox : cellDef->cd_bbox; + GEO_EXPAND(&clipRect, CIFCurStyle->cs_radius, &scx.scx_area); + + /* The following is basically a copy of CIFSeeLayer() */ + + CIFErrorDef = cellDef; + CIFInitCells(); + UndoDisable(); + CIFDummyUse->cu_def = cellDef; + scx.scx_use = CIFDummyUse; + scx.scx_trans = GeoIdentityTransform; + (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, + cifHierCopyFunc, (ClientData) CIFComponentDef); + CIFGen(CIFComponentDef, &clipRect, CIFPlanes, &DBAllTypeBits, TRUE, TRUE); + DBCellClearDef(CIFComponentDef); + + w3dClear(); + + /* follow the same locking procedure as DBWredisplay() */ + w3dUnlock(w); + w3dIsLocked = FALSE; + + for (i = 0; i < CIFCurStyle->cs_nLayers; i++) + { + if (TTMaskHasType(&crec->visible, i)) + { + w3dNeedStyle = TRUE; + DBSrPaintArea((Tile *) NULL, CIFPlanes[i], &TiPlaneRect, + &CIFSolidBits, w3dCIFPaintFunc, + (ClientData)(CIFCurStyle->cs_layers[i])); + + if (w3dIsLocked) + { + w3dUnlock(w); + w3dIsLocked = FALSE; + } + } + } + UndoEnable(); +} + +/* + * ---------------------------------------------------------------------------- + * + * W3Dcommand -- + * + * This procedure is invoked by the window package whenever a + * command is typed while the cursor is over a 3D window. + * + * Results: + * None. + * + * Side effects: + * TBD + * + * ---------------------------------------------------------------------------- + */ + +void +W3Dcommand(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int cmdNum; + + switch (cmd->tx_button) + { + case TX_NO_BUTTON: + WindExecute(w, W3DclientID, cmd); + break; + case TX_LEFT_BUTTON: + case TX_RIGHT_BUTTON: + case TX_MIDDLE_BUTTON: + /* No action---we shouldn't be here anyway. */ + break; + default: + ASSERT(FALSE, "W3Dcommand"); + } + UndoNext(); +} + +/* + * ---------------------------------------------------------------------------- + * + * W3Dinit -- + * + * Add the 3D rendering window client to the window module. + * + * Results: + * None. + * + * Side effects: + * Add ourselves as a client to the window package. + * + * ---------------------------------------------------------------------------- + */ + +void +W3Dinit() +{ + W3DclientID = WindAddClient("wind3d", W3Dcreate, W3Ddelete, + W3DCIFredisplay, W3Dcommand, + (void(*)())NULL, (bool(*)())NULL, + (void(*)())NULL, (GrGlyph *)NULL); + + /* Register commands with the client */ + + WindAddCommand(W3DclientID, + "view [x y z] specify viewpoint angle", + w3dView, FALSE); + WindAddCommand(W3DclientID, + "scroll [x y z] specify viewpoint position", + w3dScroll, FALSE); + WindAddCommand(W3DclientID, + "zoom [xy z] specify render volume scale", + w3dZoom, FALSE); + WindAddCommand(W3DclientID, + "refresh refresh 3D display", + w3dRefresh, FALSE); + WindAddCommand(W3DclientID, + "cif switch to/from CIF layers display", + w3dToggleCIF, FALSE); + WindAddCommand(W3DclientID, + "level [|up|down] set rendering level", + w3dLevel, FALSE); + WindAddCommand(W3DclientID, + "defaults revert to defaults", + w3dDefaults, FALSE); + WindAddCommand(W3DclientID, + "closewindow close the 3D display", + w3dClose, FALSE); + WindAddCommand(W3DclientID, + "render name [height thick [style]]\n" + " properties of CIF layer rendering", + w3dRenderValues, FALSE); + WindAddCommand(W3DclientID, + "see [no] layer view or hide layers from the 3D view", + w3dSeeLayers, FALSE); + WindAddCommand(W3DclientID, + "cutbox [none|box|llx lly urx ury]\n" + " set clipping rectangle for 3D view", + w3dCutBox, FALSE); + WindAddCommand(W3DclientID, + "help print this command list", + w3dHelp, FALSE); +} + +#endif /* THREE_D */ diff --git a/graphics/X11Helper.c b/graphics/X11Helper.c new file mode 100644 index 00000000..9d47e102 --- /dev/null +++ b/graphics/X11Helper.c @@ -0,0 +1,333 @@ +/* X11Helper.c -- This "helper" process, forked off by the magic process, + * looks like a kludge (and is), but is the only way to ensure that X11 + * is able to run its event-driven protocol (through calls to XNextEvent) + * while magic runs its interrupt-driven protocol (through calls to + * select()). Both are infinite (blocking) loops and must execute in + * parallel. Xlib is not thread-safe, so running this as a thread + * instead of a forked process is a bad idea (confuses X11 and locks up). + * + * In magic version 7.1, the executable name for X11Helper has been + * changed to XHelper7 to avoid compatibility conflicts with earlier + * versions of magic. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Portability stuff + */ + +#if (defined(MIPSEB) && defined(SYSTYPE_BSD43)) || ibm032 +# define SIG_RETURNS_INT +#endif + +/* Some machines have signal handlers returning an int, while other machines + * have it returning a void. If you have a machine that requires ints put + * it in the list of machines in utils/magic.h. + */ +#ifdef SIG_RETURNS_INT +#define sigRetVal int +#else +#define sigRetVal void +#endif + +void sigSetAction(int, sigRetVal (*)(int)); +sigRetVal TimeOut(int); +void SetTimeOut(); +void ParseEvent(XEvent *); + +/* + * Declaration of global variables and procedure prototypes + */ + +int readPipe,writePipe; /* pipe file descriptor to magic process */ +int parentID; /* process id of parent */ +Display *grXdpy; /* X11 display */ + +sigRetVal MapWindow(); + +/* + * Main program: + * This infinite loop is a rewrite of XtMainLoop() which includes both + * the ability to handle interrupts and communicate with magic's main + * process via the I/O pipe. The program exits when killed by the + * GrClose() routine in magic. + * + * This process will look every TIMEOUT minutes to see if its parent process + * (magic) still exists. This keeps the helper processes from becoming + * an orphan process if magic crashes or otherwise fails to execute + * GrClose() before exiting. + */ + +#define TIMEOUT 10 /* timeout period (minutes) */ + +int +main (argc, argv) + int argc; + char **argv; +{ + XEvent xevent; + + if (argc <= 1) { + fprintf(stderr, "%s: expecting two file-descriptor numbers.\n\ + \t(This program should be run only by magic itself.)\n", argv[0]); + exit(1); + } + + sscanf(argv[1], "%d %d", &readPipe,&writePipe); + grXdpy = XOpenDisplay(0); + if (grXdpy == (Display *) 0) { + fprintf(stderr,"%s: XOpenDisplay failed.\n", argv[0]); + exit(1); + } + + parentID = getppid(); + +/* sigSetAction(SIGINT, SIG_IGN); */ +/* sigSetAction(SIGQUIT, SIG_IGN); */ + sigSetAction(SIGTERM, MapWindow); +#ifdef SIGTSTP + sigSetAction(SIGTSTP, SIG_IGN); +#endif +#ifdef SIGCONT + sigSetAction(SIGCONT, SIG_IGN); +#endif + + SetTimeOut(); /* set timer for TIMEOUT minutes */ + + while (1) + { + XNextEvent(grXdpy, &xevent); + ParseEvent(&xevent); + } +} + +/* + * ParseEvent(XEvent *event): + * Pass XEvents on to the magic main process by writing into the + * connecting pipe. Keystrokes must be handled such that magic + * can treat untranslated keyboard input from stdin the same way + * that it treats translated keyboard input through X11. + * Use XLookupString() to get an ASCII character out of the + * keycode, but also pass back the event structure so we can + * pull out key modifier information in grX11Stdin(). + * + * Pass the event and key value back through the I/O pipe so that + * the keypress triggers the select() mechanism in magic's textio + * routine. + */ + +void +ParseEvent (event) + XEvent *event; +{ + if (event->type == KeyPress) + { + XKeyPressedEvent *KeyPressedEvent = (XKeyPressedEvent *) event; + char inChar[10], c, *p; + KeySym keysym; + int keywstate; /* KeySym with prepended state information */ + int keymod; + int nbytes; + + nbytes = XLookupString(KeyPressedEvent, inChar, sizeof(inChar), &keysym, NULL); + + if (IsModifierKey(keysym)) return; /* Don't send modifiers as events */ + + keymod = (LockMask | ControlMask | ShiftMask) + & KeyPressedEvent->state; + +#ifdef __APPLE__ + if (KeyPressedEvent->state & (Mod1Mask | Mod2Mask | Mod3Mask + | Mod4Mask | Mod5Mask)) + keymod |= Mod1Mask; +#else + keymod |= (Mod1Mask & KeyPressedEvent->state); +#endif + + if (nbytes == 0) /* No ASCII equivalent to string */ + { + keywstate = (keymod << 16) | (keysym & 0xffff); + + write(writePipe, event, sizeof(XEvent)); + write(writePipe, &keywstate, sizeof(int)); +#ifndef USE_IO_PROBE + kill(parentID, SIGIO); +#endif + } + else if (!strncmp(XKeysymToString(keysym), "KP_", 3)) + { + /* keypad key (special case---would like to */ + /* differentiate between shift-KP-# and # itself) */ + keymod &= ~ShiftMask; + keywstate = (keymod << 16) | (keysym & 0xffff); + write(writePipe, event, sizeof(XEvent)); + write(writePipe, &keywstate, sizeof(int)); +#ifndef USE_IO_PROBE + kill(parentID, SIGIO); +#endif + } + else /* For keys with ASCII equivalent */ + { + /* If Control or Shift is used alone, it should be removed from */ + /* the modifier list, since the ASCII value subsumes the Control */ + /* and Shift functions. However, Control + Shift + key should */ + /* be retained, as it cannot be expressed in ASCII. */ + + if (!(keymod & (LockMask | Mod1Mask))) { + if (!(keymod & ControlMask)) + keymod &= ~ShiftMask; + else if (!(keymod & ShiftMask)) + keymod &= ~ControlMask; + } + + p = inChar; + while (nbytes--) + { + if ((c = *p++) == 3) /* Ctrl-C interrupt */ + { + kill(parentID, SIGINT); + } + else + { + /* When Control modifier is present, use the capital */ + /* letter value instead of the control value. */ + + if ((keymod & ControlMask) && (c < 32)) + c += 'A' - 1; + + keywstate = (keymod << 16) | ((int)c & 0xff); + + write(writePipe, event, sizeof(XEvent)); + write(writePipe, &keywstate, sizeof(int)); +#ifndef USE_IO_PROBE + kill(parentID, SIGIO); +#endif + } + } + } + } + else if (event->type == DestroyNotify) + { + /* If this is the last window to go, it will be too late to catch */ + /* (i.e., read on pipe will never happen). */ + /* Reset timer for 1 second and check presence of parent */ + + struct itimerval checktimer; + + getitimer(ITIMER_REAL, &checktimer); + + if (checktimer.it_value.tv_sec == 0 && checktimer.it_value.tv_usec == 0) + TimeOut(0); + else /* Set timer to 1 second */ + { + checktimer.it_value.tv_sec = 1; + checktimer.it_value.tv_usec = 0; + } + setitimer(ITIMER_REAL, &checktimer, NULL); + } + else /* All event types other than KeyPress */ + { + write(writePipe, event, sizeof(XEvent)); +#ifndef USE_IO_PROBE + kill(parentID, SIGIO); +#endif + } +} + +/* + * SetTimeOut(): + * Initiate an interval timer for an interval of TIMEOUT minutes. + */ + +void +SetTimeOut() +{ + struct itimerval checktimer; + + checktimer.it_value.tv_sec = 60 * TIMEOUT; + checktimer.it_value.tv_usec = 0; + + setitimer(ITIMER_REAL, &checktimer, NULL); + + sigSetAction(SIGALRM, TimeOut); /* Timeout signal handler */ +} + +/* + * TimeOut(): + * Check parent process to see if it still exists. Commit suicide if + * orphaned (it's a harsh, harsh world). Reset the timer for another + * TIMEOUT minutes, otherwise. + */ + +sigRetVal +TimeOut(int signo) +{ + int tmpid; + + if ((tmpid = getppid()) != parentID) + { + fprintf(stderr, X11HELP_PROG ": parent (ID %d) not found. Exiting.\n", + parentID); + exit(1); + } + SetTimeOut(); /* Renew the timer and signal handler */ +} + +/* + * MapWindow(): + * On startup of any new magic window, magic writes the X11 window ID + * into the communication pipe and manually generates a SIGTERM signal. + * The interrupt handler calls MapWindow() on receiving SIGTERM, and + * the window ID is read from the I/O pipe. MapWindow() then activates + * the window by declaring what events it will interpret for that + * window (keystrokes, mouse button, and expose and resize events) + */ + +sigRetVal +MapWindow(int signo) +{ + Window window; + + if (read(readPipe, (char *)&window, sizeof(Window)) == sizeof(Window)) + { + XSelectInput(grXdpy, window, + KeyPressMask|ButtonPressMask|ButtonReleaseMask| + ExposureMask|StructureNotifyMask| + VisibilityChangeMask|OwnerGrabButtonMask); + XSync(grXdpy,1); + } + else + fprintf(stderr, X11HELP_PROG ": read on pipe failed\n"); +} + +/* + * This code duplicated from signals/signals.c so that this program is + * independent of the rest of the magic code. + */ + +void +sigSetAction(int signo, sigRetVal (*handler)(int)) +{ +#if defined(SYSV) || defined(CYGWIN) + struct sigaction sa; + + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(signo, &sa, (struct sigaction *)NULL); +#else + struct sigvec sv; + + sv.sv_handler = handler; + sv.sv_mask = 0; + sv.sv_flags = 0; + sigvec(signo, &sv, (struct sigvec *)NULL); +#endif +} diff --git a/graphics/bw.glyphs b/graphics/bw.glyphs new file mode 100644 index 00000000..2562e16e --- /dev/null +++ b/graphics/bw.glyphs @@ -0,0 +1,417 @@ +# +# Cursors for the SUN display (just like AED but black & white only). +# +# rcsid: $Header: /usr/cvsroot/magic-8.0/graphics/bw.glyphs,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# +# + +# syntax of first line: size +size 24 16 16 + +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . . K . . . . . . . . +. . . . . . . K . . . . . . . . +K K K K . . . . . . . K K K K . +K K K K K K . .*. K K K K K K . +K K K K . . . . . . . K K K K . +. . . . . . . K . . . . . . . . +. . . . . . . K . . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . . . . . . . . . . . + +K . . . . . . K . . . . . . K . +. K . . . . . K . . . . . K . . +. . K . . . . K . . . . K . . . +. . . K . . . K . . . K . . . . +. . . . K . . K . . K . . . . . +. . . . . K . K . K . . . . . . +. . . . . . K K K . . . . . . . +K K K K K K K .*K K K K K K K . +. . . . . . K K K . . . . . . . +. . . . . K . K . K . . . . . . +. . . . K . . K . . K . . . . . +. . . K . . . K . . . K . . . . +. . K . . . . K . . . . K . . . +. K . . . . . K . . . . . K . . +K . . . . . . K . . . . . . K . +. . . . . . . . . . . . . . . . + +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K K K K K K K K K K K K K K K +K*K K K K K K K K K K K K K K K + +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K* + +K*K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . + +K K K K K K K K K K K K K K K K* +K K K K K K K K K K K K K K K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K + +K K . K . K . K . K . K . K . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K K K K K K K K K K K K K K K +K*K K K K K K K K K K K K K K K + +K . K . K . K . K . K . K . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K* + +K*K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . K . K . K . K . K . K . K + +K K K K K K K K K K K K K K K K* +K K K K K K K K K K K K K K K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . K . K . K . K . K . K . K K + +K K K K K K K K K K K K K K K K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K K K K K K K K K K K K K K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K*K K K K K K K K K K K K K K K + +K K K K K K K K K K K K K K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K K K K K K K K K K K K K K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K* + +K*K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K K K K K K K K K K K K K K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K . . . . . K . . . . . . K +K K K K K K K K K K K K K K K K + +K K K K K K K K K K K K K K K K* +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K K K K K K K K K K K K K K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K . . . . . . K . . . . . K K K +K K K K K K K K K K K K K K K K + +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K K . K . K . K . K . K . K +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K*K K K K K K K K K K K K K K K + +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +K . K . K . K . K . K . K K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K* + +K*K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K K . K . K . K . K . K . K +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . +K K K . . . . . . . . . . . . . +K K K . . . . . K . . . . . . . + +K K K K K K K K K K K K K K K K* +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +K . K . K . K . K . K . K K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K +. . . . . . . . . . . . . K K K +. . . . . . . K . . . . . K K K + +K K K K K K K K K K K K K K K . +K K K K K K K K K K K K K K K . +K K K K K K K K K K K K K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . K*. . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K . . . . . . . . . K K K . +K K K K K K K K K K K K K K K . +K K K K K K K K K K K K K K K . +K K K K K K K K K K K K K K K . +. . . . . . . . . . . . . . . . + +K*. . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K K . . . . . . . . . . . . . +K K K K . . . . . . . . . . . . +K K K K K . . . . . . . . . . . +K K K K K K . . . . . . . . . . +K K K K K K K . . . . . . . . . +K K K K . . . . . . . . . . . . +K K . K K . . . . . . . . . . . +K . . K K . . . . . . . . . . . +. . . . K K . . . . . . . . . . +. . . . K K . . . . . . . . . . +. . . . . K K . . . . . . . . . +. . . . . K K . . . . . . . . . +. . . . . . K K . . . . . . . . +. . . . . . K K . . . . . . . . + +K*. . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K K . . . . . . . . . . . . . +K K K K . . . . . . . . K K . . +K K K K K . . . . . K K K K K . +K K K . . . . . K K K . . . K . +K . K K . . K K K . . . . . K K +. . . K K K K . . . . . K K K . +. . . K K . . . . . K K K . . . +. . . . . . . . K K K . . . . . +. . . . . . K K K . . . . . . . +. . . . . K K . . . . . K K . . +. . . . . . K . . . K K K K . . +. . . . . . K K K K K . . K K . +. . . . . . . K K . . . . . K . +. . . . . . . . . . . . . . K K + +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . K K K . . . . +. . . . . . . . . K . . K K . . +. . . . . . . . . . K . . K . . +. . . . . . . . . . K . . . K . +. K K K K K K K K K K . . . K K +K*. . . . . . . . . K K . . . K +. K K K K K K K K K K . K . . K +. . . . K . . . . . K . . K K K +. . . . . K K K K K K . . . . K +. . . . . K . . . . K . . . . K +. . . . . . K K K K K . . . K K +. . . . . . . K K K K K K K K . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . + +. . . . . K K . K K . . . . . . +. . . K K K K . K K K K . . . . +. . K K K . . . . . K K K . . . +. K K . . . . . . . . . K K . . +. K K . . . K . K . . . K K . . +K K . . . K K . K K . . . K K . +K K . . K K . . . K K . . K K . +. . . . . . . .*. . . . . . . . +K K . . K K . . . K K . . K K . +K K . . . K K . K K . . . K K . +. K K . . . K . K . . . K K . . +. K K . . . . . . . . . K K . . +. . K K K . . . . . K K K . . . +. . . K K K K . K K K K . . . . +. . . . . K K . K K . . . . . . +. . . . . . . . . . . . . . . . + +. . . . . . K K K . . . . . . . +. . . . K K K . K K K . . . . . +. . . . K . . . . . K . . . . . +. . . K K . . . . . K K . . . . +. . . K . . . . . . . K . . . . +. . . K . . . . . . . K . . . . +. . . K . . . . . . . K . . . . +. K K K K K K K*K K K K K K . . +. K K K K K . . . K K K K K . . +. K K K K K . . . K K K K K . . +. K K K K K . . . K K K K K . . +. K K K K K K . K K K K K K . . +. K K K K K K . K K K K K K . . +. K K K K K K . K K K K K K . . +. K K K K K K K K K K K K K . . +. . . . . . . . . . . . . . . . diff --git a/graphics/color.glyphs b/graphics/color.glyphs new file mode 100644 index 00000000..383d07ab --- /dev/null +++ b/graphics/color.glyphs @@ -0,0 +1,417 @@ +# +# Cursors for the AED display (and maybe others) +# +# rcsid: $Header: /usr/cvsroot/magic-8.0/graphics/color.glyphs,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# +# + +# syntax of first line: size +size 24 16 16 + +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . . K . . . . . . . . +. . . . . . . K . . . . . . . . +K K K K . . . . . . . K K K K . +K K K K K K . .*. K K K K K K . +K K K K . . . . . . . K K K K . +. . . . . . . K . . . . . . . . +. . . . . . . K . . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . K K K . . . . . . . +. . . . . . . . . . . . . . . . + +K . . . . . . K . . . . . . K . +. K . . . . . K . . . . . K . . +. . K . . . . K . . . . K . . . +. . . K . . . K . . . K . . . . +. . . . K . . K . . K . . . . . +. . . . . K . K . K . . . . . . +. . . . . . K K K . . . . . . . +K K K K K K K .*K K K K K K K . +. . . . . . K K K . . . . . . . +. . . . . K . K . K . . . . . . +. . . . K . . K . . K . . . . . +. . . K . . . K . . . K . . . . +. . K . . . . K . . . . K . . . +. K . . . . . K . . . . . K . . +K . . . . . . K . . . . . . K . +. . . . . . . . . . . . . . . . + +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K K K K K K K K K K K K K K K +K*K K K K K K K K K K K K K K K + +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K* + +K*K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . + +K K K K K K K K K K K K K K K K* +K K K K K K K K K K K K K K K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K + +K K . K . K . K . K . K . K . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K K K K K K K K K K K K K K K +K*K K K K K K K K K K K K K K K + +K . K . K . K . K . K . K . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K* + +K*K K K K K K K K K K K K K K K +K K K K K K K K K K K K K K K K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . K +K K . . . . . . . . . . . . . . +K K . K . K . K . K . K . K . K + +K K K K K K K K K K K K K K K K* +K K K K K K K K K K K K K K K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . . . . . . . . . . . . . K K +. . . . . . . . . . . . . . K K +K . K . K . K . K . K . K . K K + +W W W W W W W W W W W W W W W w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W W W W W W W W W W W W W w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w +w*W W W W W W W W W W W W W W w + +W W W W W W W W W W W W W W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W W W W W W W W W W W W W W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w* + +w*W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W W W W W W W W W W W W W w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W b b b b b W b b b b b b w +W W W W W W W W W W W W W W W w + +W W W W W W W W W W W W W W W w* +W W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W W W W W W W W W W W W W W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W b b b b b b W b b b b b W W w +W W W W W W W W W W W W W W W w + +W W W b b b b b W b b b b b b b +W W W b b b b b b b b b b b b b +W W W b b b b b W b b b b b b b +W W W b b b b b b b b b b b b b +W W W b b b b b W b b b b b b b +W W W b b b b b b b b b b b b b +W W W b b b b b W b b b b b b b +W W W W b W b W b W b W b W b w +W W W b b b b b W b b b b b b b +W W W b b b b b b b b b b b b b +W W W b b b b b W b b b b b b b +W W W b b b b b b b b b b b b b +W W W b b b b b W b b b b b b b +W W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w +w*W W W W W W W W W W W W W W w + +b b b b b b b W b b b b b W W w +b b b b b b b b b b b b b W W w +b b b b b b b W b b b b b W W w +b b b b b b b b b b b b b W W w +b b b b b b b W b b b b b W W w +b b b b b b b b b b b b b W W w +b b b b b b b W b b b b b W W w +W b W b W b W b W b W b W W W w +b b b b b b b W b b b b b W W w +b b b b b b b b b b b b b W W w +b b b b b b b W b b b b b W W w +b b b b b b b b b b b b b W W w +b b b b b b b W b b b b b W W w +W W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w* + +w*W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w +W W W b b b b b W b b b b b b b +W W W b b b b b b b b b b b b b +W W W b b b b b W b b b b b b b +W W W b b b b b b b b b b b b b +W W W b b b b b W b b b b b b b +W W W W b W b W b W b W b W b w +W W W b b b b b W b b b b b b b +W W W b b b b b b b b b b b b b +W W W b b b b b W b b b b b b b +W W W b b b b b b b b b b b b b +W W W b b b b b W b b b b b b b +W W W b b b b b b b b b b b b b +W W W b b b b b W b b b b b b b + +W W W W W W W W W W W W W W W w* +W W W W W W W W W W W W W W W w +W W W W W W W W W W W W W W W w +b b b b b b b W b b b b b W W w +b b b b b b b b b b b b b W W w +b b b b b b b W b b b b b W W w +b b b b b b b b b b b b b W W w +b b b b b b b W b b b b b W W w +W b W b W b W b W b W b W W W w +b b b b b b b W b b b b b W W w +b b b b b b b b b b b b b W W w +b b b b b b b W b b b b b W W w +b b b b b b b b b b b b b W W w +b b b b b b b W b b b b b W W w +b b b b b b b b b b b b b W W w +b b b b b b b W b b b b b W W w + +. . K K K K . . . K K K K . . . +. K K . . K K K K K . . K K . . +K K . . . . . K . . . . . K K . +K . . . . . . K . . . . . . K . +K . . . . . . . . . . . . . K . +K K . . . . . . . . . . . K K . +. K . . . . . K . . . . . K . . +. K K K . . K K*K . . K K K . . +. K . . . . . K . . . . . K . . +K K . . . . . . . . . . . K K . +K . . . . . . . . . . . . . K . +K . . . . . . K . . . . . . K . +K K . . . . . K . . . . . K K . +. K K . . K K K K K . . K K . . +. . K K K K . . . K K K K . . . +. . . . . . . . . . . . . . . . + +K*. . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K K . . . . . . . . . . . . . +K K K K . . . . . . . . . . . . +K K K K K . . . . . . . . . . . +K K K K K K . . . . . . . . . . +K K K K K K K . . . . . . . . . +K K K K . . . . . . . . . . . . +K K . K K . . . . . . . . . . . +K . . K K . . . . . . . . . . . +. . . . K K . . . . . . . . . . +. . . . K K . . . . . . . . . . +. . . . . K K . . . . . . . . . +. . . . . K K . . . . . . . . . +. . . . . . K K . . . . . . . . +. . . . . . K K . . . . . . . . + +K*. . . . . . . . . . . . . . . +K K . . . . . . . . . . . . . . +K K K . . . . . . . . . . . . . +K K K K . . . . . . . . K K . . +K K K K K . . . . . K K K K K . +K K K . . . . . K K K . . . K . +K . K K . . K K K . . . . . K K +. . . K K K K . . . . . K K K . +. . . K K . . . . . K K K . . . +. . . . . . . . K K K . . . . . +. . . . . . K K K . . . . . . . +. . . . . K K . . . . . K K . . +. . . . . . K . . . K K K K . . +. . . . . . K K K K K . . K K . +. . . . . . . K K . . . . . K . +. . . . . . . . . . . . . . K K + +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . K K K . . . . +. . . . . . . . . K . . K K . . +. . . . . . . . . . K . . K . . +. . . . . . . . . . K . . . K . +. K K K K K K K K K K . . . K K +K*. . . . . . . . . K K . . . K +. K K K K K K K K K K . K . . K +. . . . K . . . . . K . . K K K +. . . . . K K K K K K . . . . K +. . . . . K . . . . K . . . . K +. . . . . . K K K K K . . . K K +. . . . . . . K K K K K K K K . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . + +. . . . . K K . K K . . . . . . +. . . K K K K . K K K K . . . . +. . K K K . . . . . K K K . . . +. K K . . . . . . . . . K K . . +. K K . . . K . K . . . K K . . +K K . . . K K . K K . . . K K . +K K . . K K . . . K K . . K K . +. . . . . . . .*. . . . . . . . +K K . . K K . . . K K . . K K . +K K . . . K K . K K . . . K K . +. K K . . . K . K . . . K K . . +. K K . . . . . . . . . K K . . +. . K K K . . . . . K K K . . . +. . . K K K K . K K K K . . . . +. . . . . K K . K K . . . . . . +. . . . . . . . . . . . . . . . + +. . . W W W K K K W W W . . . . +. . . W K K K W K K K W . . . . +. . W W K W W W W W K W W . . . +. . W K K W . . . W K K W . . . +. . W K W W . . . W W K W . . . +. . W K W . . . . . W K W . . . +. W W K W W W W W W W K W W . . +. W K K K K K K*K K K K K W . . +. W K K K K . . . K K K K W . . +. W K K K K . . . K K K K W . . +. W K K K K . . . K K K K W . . +. W K K K K K . K K K K K W . . +. W K K K K K . K K K K K W . . +. W K K K K K . K K K K K W . . +. W K K K K K K K K K K K W . . +. W W W W W W W W W W W W W . . diff --git a/graphics/glyphs.h b/graphics/glyphs.h new file mode 100644 index 00000000..9b045921 --- /dev/null +++ b/graphics/glyphs.h @@ -0,0 +1,57 @@ + +/* + * grGlyphs.h -- + * + * Data structures to hold glyphs. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/graphics/glyphs.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + */ + +#ifndef _GLYPHS_H +#define _GLYPHS_H + +#include "utils/geometry.h" + +/* data structures */ + +typedef struct GR_GLY2 { + Point gr_origin; /* The location of the origin of the glyph. */ + int gr_xsize; /* The width of the glyph. */ + int gr_ysize; /* The height of the glyph. */ + ClientData gr_cache;/* Glyph cached source data. Used by Tk/Tcl; */ + /* without it, Tk will re-use the cursor memory */ + /* and cursors will get rearranged. */ + void (*gr_free)(); /* Routine to call to free the cached data. */ + int gr_pixels[1]; /* Will actually be as large an array as needed. */ +} GrGlyph; + +typedef struct GR_GLY3 +{ + int gr_num; /* The number of glyphs in this record. */ + GrGlyph *gr_glyph[1]; /* Will be big enough to hold as many glyphs as + * we have. + */ +} GrGlyphs; + +/* procedures */ + +extern void GrFreeGlyphs(); + +/* global pointer to the set of window glyphs */ + +extern GrGlyphs *windGlyphs; + +#endif /* _GLYPHS_H */ diff --git a/graphics/grCMap.c b/graphics/grCMap.c new file mode 100644 index 00000000..905175d0 --- /dev/null +++ b/graphics/grCMap.c @@ -0,0 +1,448 @@ +/* grCmap.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file provides routines that manipulate the color map on behalf + * of the magic design system. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grCMap.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "utils/utils.h" +#include "textio/textio.h" + +static colorEntry *colorMap = NULL; /* Storage for the color map. */ +int GrNumColors = 0; /* Number of colors */ + + +/*----------------------------------------------------------------------------- + * + * GrResetCMap -- + * + * Free memory associated with the colormap in preparation for + * rereading the colormap file or reading a different colormap file. + * + * Results: + * None. + * + * Side Effects: + * Currently does nothing; size of colormap structures are fixed. + * + *----------------------------------------------------------------------------- + */ + +void +GrResetCMap() +{ + int i; + colorEntry *ce; + + if (colorMap == NULL || GrNumColors == 0) return; + + for (i = 0; i < GrNumColors; i++) + { + ce = colorMap + i; + if (ce->name != NULL) + freeMagic(ce->name); + } + freeMagic(colorMap); + colorMap = NULL; + GrNumColors = 0; +} + + +/*----------------------------------------------------------------------------- + * GrReadCmap: + * + * This routine initializes the color map values from the data + * given in a file. + * + * Results: + * The return value is TRUE if the color map was successfully + * loaded, and FALSE otherwise. + * + * Side Effects: + * The color map is read from the file and loaded into the graphics + * display. The name of the color map file is x.y.z.cmap, where + * x is techStyle, y is dispType, and z is monType. + * + * Design: + * The format of the file is one or more lines of the form + * . When the first line + * is read in, the given red, green, and blue values are used + * to fill locations 0 - in the color map. Then + * the next line is used to fill from there to the next max location, + * which must be larger than the first, and so on. The last + * is expected to be 255. + *----------------------------------------------------------------------------- + */ + +bool +GrReadCMap(techStyle, dispType, monType, path, libPath) +char *techStyle; /* The type of dstyle file requested by + * the current technology. + */ +char *dispType; /* A class of color map files for one or + * more display types. Usually this + * is defaulted to NULL, in which case the + * type required by the current driver is + * used. If the current driver lists a + * NULL type, it means no color map is + * needed at all (it's a black-and-white + * display), so nothing is loaded. + */ +char *monType; /* The class of monitors being used. Usually + * given as "std". + */ +char *path; /* a search path */ +char *libPath; /* a library search path */ + +{ + FILE *f; + int max, red, green, blue, newmax, argc, i; + colorEntry *ce; + char fullName[256], inputLine[128], colorName[100]; + + if (dispType == NULL) + { + if (grCMapType == NULL) return TRUE; + dispType = grCMapType; + } + (void) sprintf(fullName, "%.80s.%.80s.%.80s", techStyle, + dispType, monType); + + f = PaOpen(fullName, "r", ".cmap", path, libPath, (char **) NULL); + if (f == NULL) + { + /* Check for original ".cmap1" file (prior to magic v. 7.2.27) */ + f = PaOpen(fullName, "r", ".cmap1", path, libPath, (char **) NULL); + if (f == NULL) + { + TxError("Couldn't open color map file \"%s.cmap\"\n", fullName); + return FALSE; + } + } + + /* Reset original colormap if necessary */ + GrResetCMap(); + + /* Get maximum color entry from file (1st pass) */ + + max = 0; + while (fgets(inputLine, 128, f) != NULL) + { + argc = sscanf(inputLine, "%*d %*d %*d %d", &newmax); + if (argc == 0) + { + /* Allow comment lines */ + if (*inputLine == '#') continue; + + TxError("Syntax error in color map file \"%s.cmap\"\n", fullName); + TxError("Last color read was index %d\n", max); + return FALSE; + } + else + { + if (newmax > max) + max = newmax; + } + } + rewind(f); + colorMap = (colorEntry *)mallocMagic((max + 1) * sizeof(colorEntry)); + GrNumColors = max + 1; + + /* Read data into colorMap (2nd pass) */ + + for (i = 0; i < GrNumColors; ) + { + if (fgets(inputLine, 128, f) == NULL) + { + TxError("Premature end-of-file in color map file \"%s.cmap\"\n", + fullName); + break; + } + if ((argc = sscanf(inputLine, "%d %d %d %d %99[^\n]", + &red, &green, &blue, &newmax, colorName)) < 4) + { + /* Allow comment lines */ + if (*inputLine == '#') continue; + + TxError("Syntax error in color map file \"%s.cmap\"\n", fullName); + TxError("Expecting to read color index %d\n", i); + break; + } + else if (newmax < i) + { + TxError("Colors in map are out of order!\n"); + break; + } + + for (; i <= newmax; i++) + { + ce = colorMap + i; + ce->red = (unsigned char)(red & 0xff); + ce->green = (unsigned char)(green & 0xff); + ce->blue = (unsigned char)(blue & 0xff); + if (argc == 5) + ce->name = StrDup(NULL, colorName); + else + ce->name = NULL; + } + } + + fclose(f); + if (i < GrNumColors) return FALSE; + + GrSetCMap(); + return TRUE; +} + + +/*----------------------------------------------------------------------------- + * GrSaveCMap + * + * CMSave will save the current contents of the color map in a file + * so that it can be read back in later with GrLoadCMap. + * + * Results: + * TRUE is returned if the color map was successfully saved. Otherwise + * FALSE is returned. The file that's actually modified is x.y.z.cmap, + * where x is techStyle, y is dispType, and z is monType. + * + * Side Effects: + * The file is overwritten with the color map values in the form + * described above under GrLoadCMap. + *----------------------------------------------------------------------------- + */ + +bool +GrSaveCMap(techStyle, dispType, monType, path, libPath) +char *techStyle; /* The type of dstyle file requested by + * the current technology. + */ +char *dispType; /* A class of color map files for one or + * more display types. Usually this + * is defaulted to NULL, in which case the + * type required by the current driver is + * used. + */ +char *monType; /* The class of monitors being used. Usually + * given as "std". + */ +char *path; /* a search path */ +char *libPath; /* a library search path */ + +{ + FILE *f; + colorEntry *ce, *ce2; + int red, green, blue; + int i; + char fullName[256]; + + if (dispType == NULL) dispType = grCMapType; + (void) sprintf(fullName, "%.80s.%.80s.%.80s", techStyle, + dispType, monType); + f = PaOpen(fullName, "w", ".cmap", path, libPath, (char **) NULL); + if (f == NULL) + { + TxError("Couldn't write color map file \"%s.cmap\"\n", fullName); + return FALSE; + } + + for (i = 0; i < GrNumColors; i++) + { + ce = colorMap + i; + red = (int)ce->red; + green = (int)ce->green; + blue = (int)ce->blue; + + while (i < (GrNumColors - 1)) + { + ce2 = colorMap + i + 1; + if ((red != (int)ce2->red) || (green != (int)ce2->green) + || (blue != (int)ce2->blue)) + break; + i++; + } + + fprintf(f, "%d %d %d %d", red, green, blue, i); + if (ce->name != NULL) + fprintf(f, " %s", ce->name); + fprintf(f, "\n"); + } + (void) fclose(f); + return TRUE; +} + +/* + *----------------------------------------------------------------------------- + * GrNameToColor -- + * + * Get the index of a specific named color, as named in the + * colormap file. + * + * Results: + * The index of the named color, or -1 if there is no match. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +int +GrNameToColor(colorname) + char *colorname; +{ + int i; + colorEntry *ce; + + for (i = 0; i < GrNumColors; i++) + { + ce = colorMap + i; + if (ce->name == NULL) continue; + else if (!strcmp(colorname, ce->name)) + return i; + } + return -1; +} + +/* + *----------------------------------------------------------------------------- + * GrGetColor -- + * reads a color value out of the map. + * + * Results: + * TRUE on success, FALSE on passing an illegal color index. + * + * Side Effects: + * The values of red, green, and blue are overwritten with the + * red, green, and blue intensities for the color indicated by + * layer. + *----------------------------------------------------------------------------- + */ + +bool +GrGetColor(color, red, green, blue) + int color; /* Color to be read. */ + int *red, *green, *blue; /* Pointers to values of color elements. */ +{ + colorEntry *ce; + + if (color >= GrNumColors) return FALSE; + + ce = colorMap + color; + *red = (int)ce->red; + *green = (int)ce->green; + *blue = (int)ce->blue; + return TRUE; +} + + +/*----------------------------------------------------------------------------- + * GrPutColor -- + * modifies the color map values for a single layer spec. + * + * Results: + * TRUE on success, FALSE on passing an illegal color index. + * + * Side Effects: + * The indicated color is modified to have the given red, green, and + * blue intensities. + *----------------------------------------------------------------------------- + */ + +bool +GrPutColor(color, red, green, blue) + int color; /* Color to be changed. */ + int red, green, blue; /* New intensities for color. */ +{ + colorEntry *ce; + + if (color >= GrNumColors) return FALSE; + + ce = colorMap + color; + ce->red = (unsigned char)(red & 0xff); + ce->green = (unsigned char)(green & 0xff); + ce->blue = (unsigned char)(blue & 0xff); + if (ce->name != NULL) + { + freeMagic(ce->name); + ce->name = NULL; + } + GrSetCMap(); + return TRUE; +} + + +/*----------------------------------------------------------------------------- + * GrPutManyColors -- + * + * Stores a new set of intensities in all portions of the map + * which contain a given set of color bits. + * + * Results: + * None. + * + * Side Effects: + * The color map entries for all layer combinations containing at + * least the bits in layers are reset to have the values given by + * red, green, and blue. For example, if layers is 1 then all odd + * map entries are changed. If layers is 3, every fourth map entry + * is changed, and if layers is 0 then all entries are changed. This + * routine is a little tricky because if an opaque layer is present, + * then the six mask color bits must match exactly, since the opaque + * layer obscures ones beneath it. + *----------------------------------------------------------------------------- + */ + +void +GrPutManyColors(color, red, green, blue, opaqueBit) + int color; /* A specification of colors to be modified. */ + int red, green, blue; /* New intensity values. */ + int opaqueBit; /* The opaque/transparent bit. It is assumed + * that the opaque layer colors or + * transparent layer bits lie to the right + * of the opaque/transparent bit. + */ + +{ + int i; + int mask = color; + + /* if a transparent layer */ + if (color & (opaqueBit + opaqueBit - 1)) mask |= opaqueBit; + + /* if a opaque layer */ + if (color & opaqueBit) mask |= (opaqueBit - 1); + + for (i = 0; i < GrNumColors; i++) + if ((i & mask) == color) + (void) GrPutColor(i, red, green, blue); + + GrSetCMap(); +} diff --git a/graphics/grClip.c b/graphics/grClip.c new file mode 100644 index 00000000..fa3204eb --- /dev/null +++ b/graphics/grClip.c @@ -0,0 +1,1676 @@ +/* grClip.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains additional functions to manipulate a + * color display. Included here are rectangle clipping and + * drawing routines. + */ + + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grClip.c,v 1.4 2010/06/24 12:37:18 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/styles.h" +#include "database/database.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "utils/malloc.h" + +/* Forward declaration: */ + +extern bool GrDisjoint(); +extern void GrClipTriangle(); + +/* The following rectangle defines the size of the cross drawn for + * zero-size rectangles. This must be all on one line to keep + * lintpick happy! + */ + +global Rect GrCrossRect = {-GR_CROSSSIZE, -GR_CROSSSIZE, GR_CROSSSIZE, GR_CROSSSIZE}; +global int GrNumClipBoxes = 0; /* for benchmarking */ +global int grCurDStyle; +global unsigned char GrGridMultiple = 1; + +/* A rectangle that is one square of the grid */ +static Rect *grGridRect; + +/* + * ---------------------------------------------------------------------------- + * GrSetStuff -- + * + * Set up current drawing style. + * + * Results: + * None. + * + * Side effects: + * Variables are changed. If anything is drawn, it will appear in the + * specified style. + * ---------------------------------------------------------------------------- + */ + +/* Current state for rectangle and text drawing */ +static int grCurWMask, grCurStipple; +#ifndef MAGIC_WRAPPER +static /* Used in grTkCommon.c, so don't make static */ +#endif +int grCurOutline, grCurFill, grCurColor; + +/* Has the device driver been informed of the above? We only inform it + * when we actually need to draw something -- this makes it harmless (in terms + * of graphics bandwidth) to call GrSetStuff extra times. + */ +bool grDriverInformed = TRUE; + +void +GrSetStuff(style) + int style; +{ + grCurDStyle = style; + grCurWMask = GrStyleTable[style].mask; + grCurColor = GrStyleTable[style].color; + grCurOutline = GrStyleTable[style].outline; + grCurStipple = GrStyleTable[style].stipple; + grCurFill = GrStyleTable[style].fill; + grDriverInformed = FALSE; +} + +/*--------------------------------------------------------------------------- + * grInformDriver: + * + * Inform the driver about the last GrSetStuff call. + * + * Results: + * None. + * + * Side Effects: + * None. + * + *---------------------------------------------------------------------------- + */ + +void +grInformDriver() +{ + /* Now let the device drivers know */ + (*grSetWMandCPtr)(grCurWMask, grCurColor); + (*grSetLineStylePtr)(grCurOutline); + (*grSetStipplePtr)(grCurStipple); + grDriverInformed = TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * grClipAgainst -- + * + * Clip a linked list of rectangles against a single rectangle. This + * may result in the list getting longer or shorter. + * + * Results: + * None. + * + * Side effects: + * The original list may change. + * ---------------------------------------------------------------------------- + */ + +void +grClipAgainst(startllr, clip) + LinkedRect **startllr; /* A pointer to the pointer that heads + * the list . + */ + Rect *clip; /* The rectangle to clip against */ +{ + extern bool grClipAddFunc(); /* forward declaration */ + LinkedRect **llr, *lr; + + for (llr = startllr; *llr != (LinkedRect *) NULL; /*nop*/ ) + { + if ( GEO_TOUCH(&(*llr)->r_r, clip) ) + { + lr = *llr; + *llr = lr->r_next; + /* this will modify the list that we are traversing! */ + (void) GrDisjoint(&lr->r_r, clip, grClipAddFunc, + (ClientData) &llr); + freeMagic( (char *) lr); + } + else + llr = &((*llr)->r_next); + } +} + + +/* Add a box to our linked list, and advance + * our pointer into the list + */ + +bool grClipAddFunc(box, cd) + Rect *box; + ClientData cd; +{ + LinkedRect ***lllr, *lr; + + lllr = (LinkedRect ***) cd; + + lr = (LinkedRect *) mallocMagic((unsigned) (sizeof (LinkedRect))); + lr->r_r = *box; + lr->r_next = **lllr; + **lllr = lr; + *lllr = &lr->r_next; + + return TRUE; +} + + +void +grObsBox(r) + Rect *r; +{ + LinkedRect *ob; + LinkedRect *ar; + LinkedRect **areas; + + ar = (LinkedRect *) mallocMagic((unsigned) (sizeof (LinkedRect))); + ar->r_r = *r; + ar->r_next = NULL; + areas = &ar; + + /* clip against obscuring areas */ + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) + { + if ( GEO_TOUCH(r, &(ob->r_r)) ) + grClipAgainst(areas, &(ob->r_r)); + } + + while (*areas != NULL) + { + LinkedRect *oldarea; + if (grCurFill == GR_STGRID) + (*grDrawGridPtr)(grGridRect, grCurOutline, &((*areas)->r_r)); + else + (*grFillRectPtr)(&((*areas)->r_r)); + oldarea = *areas; + *areas = (*areas)->r_next; + freeMagic( (char *) oldarea ); + } +} + + +/*--------------------------------------------------------- + * grClipPoints: + * This routine computes the 0, 1, or 2 intersection points + * between a line and a box. + * + * Results: + * FALSE if the line is completely outside of the box. + * + * Side Effects: + *--------------------------------------------------------- + */ + +bool +grClipPoints(line, box, p1, p1OK, p2, p2OK) + Rect *line; /* Actually a line from line->r_ll to + * line->r_ur. It is assumed that r_ll is to + * the left of r_ur, but we don't assume that + * r_ll is below r_ur. + */ + Rect *box; /* A box to check intersections with */ + Point *p1, *p2; /* To be filled in with 0, 1, or 2 points + * that are on the border of the box as well as + * on the line. + */ + bool *p1OK, *p2OK; /* Says if the point was filled in */ +{ + int tmp, delx, dely; + bool delyneg; + int x1, x2, y1, y2; + bool ok1, ok2; + + if (p1OK != NULL) *p1OK = FALSE; + ok1 = FALSE; + if (p2OK != NULL) *p2OK = FALSE; + ok2 = FALSE; + + x1 = line->r_xbot; + x2 = line->r_xtop; + y1 = line->r_ybot; + y2 = line->r_ytop; + + delx = x2-x1; + dely = y2-y1; + + /* We have to be careful because of machine-dependent problems + * with rounding during division by negative numbers. + */ + + if (dely<0) + { + dely = -dely; + delyneg = TRUE; + } + else + delyneg = FALSE; + /* we know that delx is nonnegative if this is a real (non-empty) line */ + if (delx < 0) return FALSE; + + if (x1 < box->r_xbot) + { + if (delx == 0) return FALSE; + tmp = (((box->r_xbot-x1)*dely) + (delx>>1))/delx; + if (delyneg) y1 -= tmp; + else y1 += tmp; + x1 = box->r_xbot; + } + else + if (x1 > box->r_xtop) return FALSE; + + if (x2 > box->r_xtop) + { + if (delx == 0) return FALSE; + tmp = ((x2-box->r_xtop)*dely + (delx>>1))/delx; + if (delyneg) y2 += tmp; + else y2 -= tmp; + x2 = box->r_xtop; + } + else + if (x2 < box->r_xbot) return FALSE; + + if (y2 > y1) + { + if (y1 < box->r_ybot) + { + x1 += (((box->r_ybot-y1)*delx) + (dely>>1))/dely; + y1 = box->r_ybot; + } + else if (y1 > box->r_ytop) return FALSE; + if (y2 > box->r_ytop) + { + x2 -= (((y2 - box->r_ytop)*delx) + (dely>>1))/dely; + y2 = box->r_ytop; + } + else if (y2 < box->r_ybot) return FALSE; + } + else + { + if (y1 > box->r_ytop) + { + if (dely == 0) return FALSE; + x1 += (((y1-box->r_ytop)*delx) + (dely>>1))/dely; + y1 = box->r_ytop; + } + else if (y1 < box->r_ybot) return FALSE; + if (y2 < box->r_ybot) + { + if (dely == 0) return FALSE; + x2 -= (((box->r_ybot-y2)*delx) + (dely>>1))/dely; + y2 = box->r_ybot; + } + else if (y2 > box->r_ytop) return FALSE; + } + + if ( (x1 == box->r_xbot) || (y1 == box->r_ybot) || (y1 == box->r_ytop) ) + { + if (p1 != NULL) + { + p1->p_x = x1; + p1->p_y = y1; + } + if (p1OK != NULL) *p1OK = TRUE; + ok1 = TRUE; + } + if ( (x2 == box->r_xtop) || (y2 == box->r_ybot) || (y2 == box->r_ytop) ) + { + if (p2 != NULL) + { + p2->p_x = x2; + p2->p_y = y2; + } + if (p2OK != NULL) *p2OK = TRUE; + ok2 = TRUE; + } + /* is part of the line in the box? */ + return ok1 || ok2 || + ((x1 >= box->r_xbot) && (x1 <= box->r_xtop) && (y1 >= box->r_ybot) + && (y1 <= box->r_ytop)); +} + + +#define NEWAREA(lr,x1,y1,x2,y2) {LinkedRect *tmp; \ + tmp = (LinkedRect *) mallocMagic((unsigned) (sizeof (LinkedRect))); \ + tmp->r_r.r_xbot = x1; tmp->r_r.r_xtop = x2; \ + tmp->r_r.r_ybot = y1; tmp->r_r.r_ytop = y2; tmp->r_next = lr; lr = tmp;} + +/*--------------------------------------------------------- + * GrClipLine: + * GrClipLine will draw a line on the screen in the current + * style and clip stuff. + * + * Results: None. + * + * Side Effects: + * The line is drawn in the current style. + *--------------------------------------------------------- + */ + +void +GrClipLine(x1, y1, x2, y2) + int x1, y1, x2, y2; +{ + LinkedRect **ar; + LinkedRect *ob; + LinkedRect *areas; + + GR_CHECK_LOCK(); + if (!grDriverInformed) grInformDriver(); + + /* we will pretend the the ll corner of a rectangle is the + * left endpoint of a line, and the ur corner the right endpoint + * of the line. + */ + areas = (LinkedRect *) mallocMagic((unsigned) (sizeof (LinkedRect))); + areas->r_next = NULL; + if (x1 < x2) + { + areas->r_r.r_xbot = x1; + areas->r_r.r_ybot = y1; + areas->r_r.r_xtop = x2; + areas->r_r.r_ytop = y2; + } + else + { + areas->r_r.r_xtop = x1; + areas->r_r.r_ytop = y1; + areas->r_r.r_xbot = x2; + areas->r_r.r_ybot = y2; + } + + /* clip against the clip box */ + for (ar = &areas; *ar != NULL; ) + { + Rect *l; + Rect canonRect; + l = &((*ar)->r_r); + GeoCanonicalRect(l, &canonRect); + if (!GEO_TOUCH(&canonRect, &grCurClip)) + { + /* line is totally outside of clip area */ + goto deleteit; + } + else + { + /* is there some intersection with clip area? */ + if (!grClipPoints(l, &grCurClip, &(l->r_ll), (bool *) NULL, + &(l->r_ur), (bool*) NULL)) + { + /* no intersection */ + goto deleteit; + } + + /* clip against obscuring areas */ + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) + { + Point p1, p2; + Rect c; + bool ok1, ok2; + c = ob->r_r; + c.r_xbot--; c.r_ybot--; + c.r_xtop++; c.r_ytop++; + if (grClipPoints(l, &c, &p1, &ok1, &p2, &ok2) && + !ok1 && !ok2) + { + /* Line is not completely outside of the box, + * nor does it intersect it. + * Therefore, line is completely obscured. + */ + goto deleteit; + } + + if (ok1 && + ( ((l->r_xbot == p1.p_x) && (l->r_ybot == p1.p_y)) || + ((l->r_xtop == p1.p_x) && (l->r_ytop == p1.p_y)) ) ) + { + ok1 = FALSE; /* do not split or clip at an endpoint */ + } + if (ok2 && + ( ((l->r_xbot == p2.p_x) && (l->r_ybot == p2.p_y)) || + ((l->r_xtop == p2.p_x) && (l->r_ytop == p2.p_y)) ) ) + { + ok2 = FALSE; /* do not split or clip at an endpoint */ + } + + if (ok1 ^ ok2) + { + /* one segment to deal with */ + if (ok1) + l->r_ur = p1; + else + l->r_ll = p2; + } + else if (ok1 && ok2) + { + /* clip both sides */ + LinkedRect *new; + new = (LinkedRect *) mallocMagic((unsigned) (sizeof (LinkedRect))); + new->r_r.r_ur = l->r_ur; + new->r_r.r_ll = p2; + new->r_next = (*ar); + l->r_ur = p1; + (*ar) = new; + } + } + + } + + ar = &((*ar)->r_next); + continue; + +deleteit: { + LinkedRect *reclaim; + reclaim = (*ar); + *ar = reclaim->r_next; + freeMagic( (char *) reclaim); + } + + } /* for ar */ + + + /* draw the lines */ + while (areas != NULL) + { + LinkedRect *oldarea; + (*grDrawLinePtr)(areas->r_r.r_xbot, areas->r_r.r_ybot, + areas->r_r.r_xtop, areas->r_r.r_ytop); + oldarea = areas; + areas = areas->r_next; + freeMagic( (char *) oldarea ); + } +} + +/* + *--------------------------------------------------------- + * grAddSegment: + * Add a segment to a linked list of rectangles + * + * Results: + * None. + * + * Side effects: + * Allocates memory; appends LinkedRect structure to + * list "segments". + * + * Notes: + * INLINE this for speedup? + *--------------------------------------------------------- + */ + +void +grAddSegment(llx, lly, urx, ury, segments) + int llx, lly, urx, ury; + LinkedRect **segments; +{ + LinkedRect *curseg; + + curseg = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); + curseg->r_r.r_xbot = llx; + curseg->r_r.r_ybot = lly; + curseg->r_r.r_xtop = urx; + curseg->r_r.r_ytop = ury; + curseg->r_next = *segments; + *segments = curseg; +} + +/*--------------------------------------------------------- + * GrBoxOutline: + * For box outlines, works around the boundary of + * the box according to the associated tile structure, + * and returns a linked rect list defining all the + * segments which need to be drawn. + * + * Results: + * TRUE if tile is isolated (GrFastBox can be used). + * Otherwise, result is FALSE. + * + * Side Effects: + * May allocate memory for a linked rect structure, + * with pointer returned in tilesegs. If non-NULL, + * the calling function needs to free memory for the + * linked rect structure. + * + * Implementation notes: + * Standard tech files define most bordered styles as + * contact types, and most if not all contacts are + * required to be square. So we want the case of an + * isolated tile to go fast, avoiding any calls to + * allocate memory. This complicates the routine but + * keeps the routine from slowing down the layout + * rendering. + *--------------------------------------------------------- + */ + +bool +GrBoxOutline(tile, tilesegs) + Tile *tile; + LinkedRect **tilesegs; +{ + Rect rect; + TileType ttype; + LinkedRect *curseg; + Tile *tpleft, *tpright, *tptop, *tpbot; + int edgeTop, edgeBot, edgeRight, edgeLeft; + int isolate = 0; + bool sense; + + *tilesegs = NULL; + TiToRect(tile, &rect); + + if (IsSplit(tile) && SplitSide(tile)) + isolate |= 0x1; + else + { + ttype = TiGetLeftType(tile); + edgeBot = rect.r_ybot; + sense = TRUE; + for (tpleft = BL(tile); BOTTOM(tpleft) < rect.r_ytop; tpleft = RT(tpleft)) + { + if (TiGetRightType(tpleft) != ttype) + { + if (!sense) + { + edgeBot = BOTTOM(tpleft); + if (TOP(tpleft) >= rect.r_ytop) + grAddSegment(rect.r_xbot, edgeBot, rect.r_xbot, rect.r_ytop, + tilesegs); + sense = TRUE; + } + } + else + { + if (sense) + { + edgeTop = BOTTOM(tpleft); + if (edgeTop > edgeBot) + grAddSegment(rect.r_xbot, edgeBot, rect.r_xbot, edgeTop, + tilesegs); + isolate |= 0x1; + sense = FALSE; + } + } + } + } + if (IsSplit(tile) && !SplitSide(tile)) + isolate |= 0x2; + else + { + ttype = TiGetRightType(tile); + edgeTop = rect.r_ytop; + sense = TRUE; + for (tpright = TR(tile); TOP(tpright) > rect.r_ybot; tpright = LB(tpright)) + { + if (TiGetLeftType(tpright) != ttype) + { + if (!sense) + { + edgeTop = TOP(tpright); + if (BOTTOM(tpright) <= rect.r_ybot) + grAddSegment(rect.r_xtop, rect.r_ybot, rect.r_xtop, edgeTop, + tilesegs); + sense = TRUE; + } + } + else + { + if (sense) + { + edgeBot = TOP(tpright); + if (edgeBot < edgeTop) + grAddSegment(rect.r_xtop, edgeBot, rect.r_xtop, edgeTop, + tilesegs); + isolate |= 0x2; + sense = FALSE; + } + } + } + } + + if (IsSplit(tile) && + (SplitSide(tile) == SplitDirection(tile))) + isolate |= 0x4; + else + { + ttype = TiGetBottomType(tile); + edgeLeft = rect.r_xbot; + sense = TRUE; + for (tpbot = LB(tile); LEFT(tpbot) < rect.r_xtop; tpbot = TR(tpbot)) + { + if (TiGetTopType(tpbot) != ttype) + { + if (!sense) + { + edgeLeft = LEFT(tpbot); + if (RIGHT(tpbot) >= rect.r_xtop) + grAddSegment(edgeLeft, rect.r_ybot, rect.r_xtop, rect.r_ybot, + tilesegs); + sense = TRUE; + } + } + else + { + if (sense) + { + edgeRight = LEFT(tpbot); + if (edgeRight > edgeLeft) + grAddSegment(edgeLeft, rect.r_ybot, edgeRight, rect.r_ybot, + tilesegs); + isolate |= 0x4; + sense = FALSE; + } + } + } + } + + if (IsSplit(tile) && + (SplitSide(tile) != SplitDirection(tile))) + isolate |= 0x8; + else + { + ttype = TiGetTopType(tile); + edgeRight = rect.r_xtop; + sense = TRUE; + for (tptop = RT(tile); RIGHT(tptop) > rect.r_xbot; tptop = BL(tptop)) + { + if (TiGetBottomType(tptop) != ttype) + { + if (!sense) + { + edgeRight = RIGHT(tptop); + if (LEFT(tptop) <= rect.r_xbot) + grAddSegment(rect.r_xbot, rect.r_ytop, edgeRight, rect.r_ytop, + tilesegs); + sense = TRUE; + } + } + else + { + if (sense) + { + edgeLeft = RIGHT(tptop); + if (edgeLeft < edgeRight) + grAddSegment(edgeLeft, rect.r_ytop, edgeRight, rect.r_ytop, + tilesegs); + isolate |= 0x8; + sense = FALSE; + } + } + } + } + + if (isolate == 0) /* Common case */ + return TRUE; + else + { + /* Need to malloc segments for isolated sides */ + if (!(isolate & 0x1)) /* Left */ + grAddSegment(rect.r_xbot, rect.r_ybot, rect.r_xbot, rect.r_ytop, + tilesegs); + if (!(isolate & 0x2)) /* Right */ + grAddSegment(rect.r_xtop, rect.r_ybot, rect.r_xtop, rect.r_ytop, + tilesegs); + if (!(isolate & 0x4)) /* Bottom */ + grAddSegment(rect.r_xbot, rect.r_ybot, rect.r_xtop, rect.r_ybot, + tilesegs); + if (!(isolate & 0x8)) /* Top */ + grAddSegment(rect.r_xbot, rect.r_ytop, rect.r_xtop, rect.r_ytop, + tilesegs); + return FALSE; + } +} + +/* Threshold for determining if outlines are too small to draw */ +#define GR_THRESH 4 + +/*--------------------------------------------------------- + * GrBox -- + * + * GrBox draws a rectangle on the screen in the style + * set by the previous call to GrSetStuff. It will + * be clipped against the rectangles passed to GrSetStuff. + * + * Unlike GrFastBox (see below), GrBox makes no assumptions + * about how the outline will be drawn. If there is no + * outline, GrFastBox is called. The tile border is checked, + * and if the tile outline is simple, GrFastBox is called. + * Otherwise, we do a fast fill a la GrFastBox but draw the + * outline segment by segment. + * + * Results: None. + * + * Side Effects: + * The rectangle is drawn in the style specified. + * The rectangle may be clipped before being drawn. + *--------------------------------------------------------- + */ +void +GrBox(MagWindow *mw, Transform *trans, Tile *tile) +{ + Rect r, r2, clipr; + bool needClip, needObscure, simpleBox; + LinkedRect *ob, *tilesegs, *segptr; + Point polyp[5]; + int np; + + r.r_xbot = LEFT(tile); + r.r_ybot = BOTTOM(tile); + r.r_xtop = RIGHT(tile); + r.r_ytop = TOP(tile); + + GeoTransRect(trans, &r, &r2); + if (IsSplit(tile)) + WindSurfaceToScreenNoClip(mw, &r2, &r); + else + WindSurfaceToScreen(mw, &r2, &r); + + GR_CHECK_LOCK(); + if (!grDriverInformed) grInformDriver(); + GrNumClipBoxes++; + + if (!GEO_TOUCH(&r, &grCurClip)) return; + + /* Do a quick check to make the (very common) special case of + * no clipping go fast. + */ + needClip = !GEO_SURROUND(&grCurClip, &r); + needObscure = FALSE; + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) + needObscure |= GEO_TOUCH(&r, &(ob->r_r)); + + /* Nonmanhattan tiles: */ + /* Expects one of the two tile types to be masked out before */ + /* this procedure is called. */ + + if (IsSplit(tile)) + { + /* Perform matrix transformations on split tiles */ + TileType dinfo; + Rect fullr; + + dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans); + clipr = fullr = r; + + if (needClip) + GeoClip(&clipr, &grCurClip); + + GrClipTriangle(&fullr, &clipr, needClip, dinfo, polyp, &np); + + if ((grCurFill == GR_STSOLID) || + (grCurFill == GR_STSTIPPLE) || (grCurFill == GR_STGRID) ) + { + if (needObscure) + grObsBox(&clipr); + else if (grFillPolygonPtr) + (void) (*grFillPolygonPtr)(polyp, np); + } + } + else + { + + /* do solid areas (same as GrFastBox) */ + + if ((grCurFill == GR_STSOLID) || (grCurFill == GR_STSTIPPLE)) + { + /* We have a filled area to deal with */ + clipr = r; + if (needClip) + GeoClip(&clipr, &grCurClip); + if (needObscure) + grObsBox(&clipr); + else + (void) (*grFillRectPtr)(&clipr); + } + } + + /* return if outline is too small to be worth drawing */ + + if ((r.r_xtop - r.r_xbot < GR_THRESH) + && (r.r_ytop - r.r_ybot < GR_THRESH) + && (grCurFill != GR_STOUTLINE)) + return; + + /* do diagonal lines for contacts */ + + if (grCurFill == GR_STCROSS) + { + Rect rnc; + /* don't clip contact diagonals */ + if (needClip || needObscure) + { + WindSurfaceToScreenNoClip(mw, &r2, &rnc); +/* + (*grDrawLinePtr)(rnc.r_xbot, rnc.r_ybot, rnc.r_xtop, rnc.r_ytop); + (*grDrawLinePtr)(rnc.r_xbot, rnc.r_ytop, rnc.r_xtop, rnc.r_ybot); +*/ + if (!IsSplit(tile)) + { + GrClipLine(rnc.r_xbot, rnc.r_ybot, rnc.r_xtop, rnc.r_ytop); + GrClipLine(rnc.r_xbot, rnc.r_ytop, rnc.r_xtop, rnc.r_ybot); + } + } + else + { + if (!IsSplit(tile)) + { + (*grDrawLinePtr)(r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop); + (*grDrawLinePtr)(r.r_xbot, r.r_ytop, r.r_xtop, r.r_ybot); + } + } + } + + /* draw outlines */ + + if (grCurOutline != 0) + { + if (GrBoxOutline(tile, &tilesegs)) + { + /* simple box (from GrFastBox)*/ + + if (needClip || needObscure) + { + GrClipLine(r.r_xbot, r.r_ytop, r.r_xtop, r.r_ytop); + GrClipLine(r.r_xbot, r.r_ybot, r.r_xtop, r.r_ybot); + GrClipLine(r.r_xbot, r.r_ybot, r.r_xbot, r.r_ytop); + GrClipLine(r.r_xtop, r.r_ybot, r.r_xtop, r.r_ytop); + } + else + { + (*grDrawLinePtr)(r.r_xbot, r.r_ytop, r.r_xtop, r.r_ytop); + (*grDrawLinePtr)(r.r_xbot, r.r_ybot, r.r_xtop, r.r_ybot); + (*grDrawLinePtr)(r.r_xbot, r.r_ybot, r.r_xbot, r.r_ytop); + (*grDrawLinePtr)(r.r_xtop, r.r_ybot, r.r_xtop, r.r_ytop); + } + } + else + { + /* non-rectangular box; requires drawing segments */ + for (segptr = tilesegs; segptr != NULL; segptr = segptr->r_next) + { + GeoTransRect(trans, &segptr->r_r, &r2); + WindSurfaceToScreen(mw, &r2, &r); + + if (needClip || needObscure) + GrClipLine(r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop); + else + (*grDrawLinePtr)(r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop); + + /* Free memory, if it was allocated for outline segments */ + freeMagic(segptr); + } + + /* For non-manhattan tiles, the manhattan parts of the */ + /* boundary have already been drawn. The diagonal boundary */ + /* is guaranteed to be continuous by definition, and it has */ + /* already undergone clipping with GrClipTriangle. So just */ + /* draw it, now. */ + + if (IsSplit(tile)) + { + int cp; + for (cp = 0; cp < np - 1; cp++) + { + if ((polyp[cp].p_x != polyp[cp + 1].p_x) && + (polyp[cp].p_y != polyp[cp + 1].p_y)) + { + (*grDrawLinePtr)(polyp[cp].p_x, polyp[cp].p_y, + polyp[cp + 1].p_x, polyp[cp + 1].p_y); + break; /* only 1 diagonal line to draw */ + } + } + if (cp == (np - 1)) + { + if ((polyp[cp].p_x != polyp[0].p_x) && + (polyp[cp].p_y != polyp[0].p_y)) + (*grDrawLinePtr)(polyp[cp].p_x, polyp[cp].p_y, + polyp[0].p_x, polyp[0].p_y); + } + } + } + } +} + +/*--------------------------------------------------------- + * GrDrawFastBox: + * GrDrawFastBox will draw a rectangle on the screen in the + * style set by the previous call to GrSetStuff. It will also + * be clipped against the rectangles passed to GrSetStuff. + * + * If GrClipBox is called between GrDrawFastBox calls then GrSetStuff + * must be called to set the parameters back. + * + * Usually this is called as GrFastBox, defined as GrDrawFastBox(p, 0). + * The "scale" is only used to reduce the size of crosses drawn at + * point positions, to prevent point labels from dominating a layout + * in top-level views. + * + * Results: None. + * + * Side Effects: + * The rectangle is drawn in the style specified. + * The rectangle is clipped before being drawn. + *--------------------------------------------------------- + */ + +void +GrDrawFastBox(prect, scale) + Rect *prect; /* The rectangle to be drawn, given in + * screen coordinates. + */ + int scale; /* If < 0, we reduce the cross size for + * points according to the (negative) scale, + * so point labels don't dominate a top-level + * layout. + */ +{ + Rect *r; + bool needClip, needObscure; + LinkedRect *ob; + + GR_CHECK_LOCK(); + if (!grDriverInformed) grInformDriver(); + GrNumClipBoxes++; + if (grCurFill == GR_STGRID) + { + r = &grCurClip; + grGridRect = prect; + } + else + { + r = prect; + if (!GEO_TOUCH(r, &grCurClip)) return; + } + + /* Do a quick check to make the (very common) special case of + * no clipping go fast. + */ + needClip = !GEO_SURROUND(&grCurClip, r); + needObscure = FALSE; + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) + needObscure |= GEO_TOUCH(r, &(ob->r_r)); + + /* do solid areas */ + if ( (grCurFill == GR_STSOLID) || + (grCurFill == GR_STSTIPPLE) || (grCurFill == GR_STGRID) ) + { + Rect clipr; + /* We have a filled area to deal with */ + clipr = *r; + if (needClip) + GeoClip(&clipr, &grCurClip); + if (needObscure) + grObsBox(&clipr); + else + { + if (grCurFill == GR_STGRID) + (*grDrawGridPtr)(grGridRect, grCurOutline, &clipr); + else + (void) (*grFillRectPtr)(&clipr); + } + } + + /* return if rectangle is too small to see */ + if ((r->r_xtop - r->r_xbot < GR_THRESH) + && (r->r_ytop - r->r_ybot < GR_THRESH) + && (grCurFill != GR_STOUTLINE)) + return; + + /* draw outlines */ + + if ( (grCurOutline != 0) && (grCurFill != GR_STGRID) ) + { + if ( (grCurFill == GR_STOUTLINE) && (r->r_xbot == r->r_xtop) && + (r->r_ybot == r->r_ytop) ) + { + int crossSize = GR_CROSSSIZE; + + if (scale < 0) + { + crossSize += scale; + if (crossSize < 0) + goto endit; + } + + /* turn the outline into a cross */ + if (needClip || needObscure) + goto clipit; + else + { + bool crossClip, crossObscure; + Rect crossBox; + + /* check the larger cross area for clipping */ + crossBox.r_xbot = r->r_xbot - crossSize; + crossBox.r_ybot = r->r_ybot - crossSize; + crossBox.r_xtop = r->r_xtop + crossSize; + crossBox.r_ytop = r->r_ytop + crossSize; + + crossClip = !GEO_SURROUND(&grCurClip, &crossBox); + crossObscure = FALSE; + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) + crossObscure |= GEO_TOUCH(&crossBox, &(ob->r_r)); + + if (crossClip || crossObscure) + goto clipit; + else + goto noclipit; + } + + clipit: + GrClipLine(r->r_xbot, r->r_ybot - crossSize, + r->r_xtop, r->r_ytop + crossSize - 1 + GrPixelCorrect); + GrClipLine(r->r_xbot - crossSize, r->r_ybot, + r->r_xtop + crossSize - 1 + GrPixelCorrect, r->r_ytop); + goto endit; + + noclipit: + (*grDrawLinePtr)(r->r_xbot, r->r_ybot - crossSize, + r->r_xtop, r->r_ytop + crossSize - 1 + GrPixelCorrect); + (*grDrawLinePtr)(r->r_xbot - crossSize, r->r_ybot, + r->r_xtop + crossSize - 1 + GrPixelCorrect, r->r_ytop); + + endit: ; + } + else + { + if (needClip || needObscure) + { + GrClipLine(r->r_xbot, r->r_ytop, r->r_xtop, r->r_ytop); + GrClipLine(r->r_xbot, r->r_ybot, r->r_xtop, r->r_ybot); + GrClipLine(r->r_xbot, r->r_ybot, r->r_xbot, r->r_ytop); + GrClipLine(r->r_xtop, r->r_ybot, r->r_xtop, r->r_ytop); + } + else + { + (*grDrawLinePtr)(r->r_xbot, r->r_ytop, r->r_xtop, r->r_ytop); + (*grDrawLinePtr)(r->r_xbot, r->r_ybot, r->r_xtop, r->r_ybot); + (*grDrawLinePtr)(r->r_xbot, r->r_ybot, r->r_xbot, r->r_ytop); + (*grDrawLinePtr)(r->r_xtop, r->r_ybot, r->r_xtop, r->r_ytop); + } + } + } + + /* do diagonal lines for contacts */ + if (grCurFill == GR_STCROSS) + { + if (needClip || needObscure) + { + GrClipLine(r->r_xbot, r->r_ybot, r->r_xtop, r->r_ytop); + GrClipLine(r->r_xbot, r->r_ytop, r->r_xtop, r->r_ybot); + } + else + { + (*grDrawLinePtr)(r->r_xbot, r->r_ybot, r->r_xtop, r->r_ytop); + (*grDrawLinePtr)(r->r_xbot, r->r_ytop, r->r_xtop, r->r_ybot); + } + } +} + +/*--------------------------------------------------------- + * GrClipTriangle: + * Returns an array of points representing a clipped + * triangle. These are always arranged in counter- + * clockwise order. + * + * Results: + * None. + * + * Side effects: + * Returns array of points and modifies int * np + * to hold the number of points in the array. + *--------------------------------------------------------- + */ + +#define xround(d) (int)(((((d % height) << 1) >= height) ? 1 : 0) + (d / height)) +#define yround(d) (int)(((((d % width) << 1) >= width) ? 1 : 0) + (d / width)) + +void +GrClipTriangle(r, c, clipped, dinfo, points, np) + Rect *r; /* Bounding box of triangle, in screen coords */ + Rect *c; /* Clipping rectangle */ + bool clipped; /* Boolean, if bounding box is clipped */ + TileType dinfo; /* Split side and direction information */ + Point *points; /* Point array (up to 5 points) to fill */ + int *np; /* Number of points in the clipped polygon */ +{ + if (!(dinfo & TT_SIDE)) + { + points[1].p_x = r->r_xbot; + points[0].p_y = r->r_ytop; + points[2].p_y = r->r_ybot; + points[0].p_x = points[2].p_x = r->r_xtop; + } + else + { + points[1].p_x = r->r_xtop; + points[0].p_y = r->r_ybot; + points[2].p_y = r->r_ytop; + points[0].p_x = points[2].p_x = r->r_xbot; + } + + if (!(dinfo & TT_DIRECTION)) + { + points[1].p_y = points[0].p_y; + points[2].p_x = points[1].p_x; + } + else + { + points[0].p_x = points[1].p_x; + points[1].p_y = points[2].p_y; + } + + *np = 3; + + /* Clip the triangle to the clipping rectangle. Result is */ + /* a 3- to 5-sided polygon, or empty. */ + + if (clipped) + { + dlong delx, dely; + dlong width = (dlong)(r->r_xtop - r->r_xbot); + dlong height = (dlong)(r->r_ytop - r->r_ybot); + + switch(dinfo & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)) + { + case TT_DIAGONAL: /* nw */ + if (c->r_ytop < r->r_ytop) /* clip top */ + { + delx = (dlong)(points[1].p_y - c->r_ytop) * width; + points[1].p_y = c->r_ytop; + points[0].p_y = c->r_ytop; + points[0].p_x -= xround(delx); + } + if (c->r_xbot > r->r_xbot) /* clip left */ + { + dely = (dlong)(c->r_xbot - points[2].p_x) * height; + points[1].p_x = c->r_xbot; + points[2].p_x = c->r_xbot; + points[2].p_y += yround(dely); + } + if (c->r_ybot > points[2].p_y) /* clip bottom */ + { + delx = (dlong)(c->r_ybot - points[2].p_y) * width; + points[2].p_y = c->r_ybot; + points[3].p_y = c->r_ybot; + points[3].p_x = points[2].p_x + xround(delx); + *np = 4; + + if (c->r_xtop < points[3].p_x) /* clip right, rectangle */ + { + points[3].p_x = c->r_xtop; + points[0].p_x = c->r_xtop; + } + else if (c->r_xtop < points[0].p_x) /* clip right, pentagon */ + { + dely = (dlong)(points[0].p_x - c->r_xtop) * height; + points[0].p_x = c->r_xtop; + points[4].p_x = c->r_xtop; + points[4].p_y = points[0].p_y - yround(dely); + *np = 5; + } + } + else if (c->r_xtop < points[0].p_x) /* clip right, quadrangle */ + { + dely = (dlong)(points[0].p_x - c->r_xtop) * height; + points[0].p_x = c->r_xtop; + points[3].p_x = c->r_xtop; + points[3].p_y = points[0].p_y - yround(dely); + *np = 4; + } + if (points[1].p_x > points[0].p_x || points[2].p_y > points[1].p_y) + *np = 0; /* clipped out of existence */ + break; + + case TT_DIAGONAL | TT_DIRECTION: /* sw */ + if (c->r_xbot > r->r_xbot) /* clip LEFT */ + { + dely = (dlong)(c->r_xbot - points[1].p_x) * height; + points[1].p_x = c->r_xbot; + points[0].p_x = c->r_xbot; + points[0].p_y -= yround(dely); + } + if (c->r_ybot > r->r_ybot) /* clip BOTTOM */ + { + delx = (dlong)(c->r_ybot - points[2].p_y) * width; + points[1].p_y = c->r_ybot; + points[2].p_y = c->r_ybot; + points[2].p_x -= xround(delx); + } + if (c->r_xtop < points[2].p_x) /* clip RIGHT */ + { + dely = (dlong)(points[2].p_x - c->r_xtop) * height; + points[2].p_x = c->r_xtop; + points[3].p_x = c->r_xtop; + points[3].p_y = points[1].p_y + yround(dely); + *np = 4; + + if (c->r_ytop < points[3].p_y) /* clip TOP, rectangle */ + { + points[3].p_y = c->r_ytop; + points[0].p_y = c->r_ytop; + } + else if (c->r_ytop < points[0].p_y) /* clip TOP, pentagon */ + { + delx = (dlong)(points[0].p_y - c->r_ytop) * width; + points[0].p_y = c->r_ytop; + points[4].p_y = c->r_ytop; + points[4].p_x = points[0].p_x + xround(delx); + *np = 5; + } + } + else if (c->r_ytop < points[0].p_y) /* clip TOP, quadrangle */ + { + delx = (dlong)(points[0].p_y - c->r_ytop) * width; + points[0].p_y = c->r_ytop; + points[3].p_y = c->r_ytop; + points[3].p_x = points[0].p_x + xround(delx); + *np = 4; + } + if (points[1].p_y > points[0].p_y || points[2].p_x < points[1].p_x) + *np = 0; /* clipped out of existence */ + break; + + case TT_DIAGONAL | TT_SIDE: /* se */ + /* order: (bottom, right), (top, left) */ + if (c->r_ybot > r->r_ybot) /* clip BOTTOM */ + { + delx = (dlong)(c->r_ybot - points[1].p_y) * width; + points[1].p_y = c->r_ybot; + points[0].p_y = c->r_ybot; + points[0].p_x += xround(delx); + } + if (c->r_xtop < r->r_xtop) /* clip RIGHT */ + { + dely = (dlong)(points[2].p_x - c->r_xtop) * height; + points[1].p_x = c->r_xtop; + points[2].p_x = c->r_xtop; + points[2].p_y -= yround(dely); + } + if (c->r_ytop < points[2].p_y) /* clip TOP */ + { + delx = (dlong)(points[2].p_y - c->r_ytop) * width; + points[2].p_y = c->r_ytop; + points[3].p_y = c->r_ytop; + points[3].p_x = points[2].p_x - xround(delx); + *np = 4; + + if (c->r_xbot > points[3].p_x) /* clip LEFT, rectangle */ + { + points[3].p_x = c->r_xbot; + points[0].p_x = c->r_xbot; + } + else if (c->r_xbot > points[0].p_x) /* clip LEFT, pentagon */ + { + dely = (dlong)(c->r_xbot - points[0].p_x) * height; + points[0].p_x = c->r_xbot; + points[4].p_x = c->r_xbot; + points[4].p_y = points[0].p_y + yround(dely); + *np = 5; + } + } + else if (c->r_xbot > points[0].p_x) /* clip LEFT, triangle */ + { + dely = (dlong)(c->r_xbot - points[0].p_x) * height; + points[0].p_x = c->r_xbot; + points[3].p_x = c->r_xbot; + points[3].p_y = points[0].p_y + yround(dely); + *np = 4; + } + if (points[0].p_x > points[1].p_x || points[1].p_y > points[2].p_y) + *np = 0; /* clipped out of existence */ + break; + + case TT_DIAGONAL | TT_SIDE | TT_DIRECTION: /* ne */ + /* order: (top, right), (bottom, left) */ + if (c->r_xtop < r->r_xtop) /* clip RIGHT */ + { + dely = (dlong)(points[1].p_x - c->r_xtop) * height; + points[1].p_x = c->r_xtop; + points[0].p_x = c->r_xtop; + points[0].p_y += yround(dely); + } + if (c->r_ytop < r->r_ytop) /* clip TOP */ + { + delx = (dlong)(points[2].p_y - c->r_ytop) * width; + points[1].p_y = c->r_ytop; + points[2].p_y = c->r_ytop; + points[2].p_x += xround(delx); + } + if (c->r_xbot > points[2].p_x) /* clip LEFT */ + { + dely = (dlong)(c->r_xbot - points[2].p_x) * height; + points[2].p_x = c->r_xbot; + points[3].p_x = c->r_xbot; + points[3].p_y = points[2].p_y - yround(dely); + *np = 4; + + if (c->r_ybot >= points[3].p_y) /* clip BOTTOM, rectangle */ + { + points[3].p_y = c->r_ybot; + points[0].p_y = c->r_ybot; + } + else if (c->r_ybot > points[0].p_y) /* clip BOTTOM, pentagon */ + { + delx = (dlong)(c->r_ybot - points[0].p_y) * width; + points[0].p_y = c->r_ybot; + points[4].p_y = c->r_ybot; + points[4].p_x = points[0].p_x - xround(delx); + *np = 5; + } + } + else if (c->r_ybot > points[0].p_y) /* clip BOTTOM, quadrangle */ + { + delx = (dlong)(c->r_ybot - points[0].p_y) * width; + points[0].p_y = c->r_ybot; + points[3].p_y = c->r_ybot; + points[3].p_x = points[0].p_x - xround(delx); + *np = 4; + } + if (points[1].p_y < points[0].p_y || points[2].p_x > points[1].p_x) + *np = 0; /* clipped out of existence */ + break; + } + } +} + +/*--------------------------------------------------------- + * GrDrawTriangleEdge -- + * Draws the diagonal line in a triangle clipped by + * grCurClip. + * + * Results: + * None. + * + * Side effects: + * Draws nonmanhattan layout geometry. + * + *--------------------------------------------------------- + */ + +void +GrDrawTriangleEdge(r, dinfo) + Rect *r; /* Bounding box of triangle, in screen coords */ + TileType dinfo; +{ + Point tpoints[5]; + int tnum, i, j; + + GrClipTriangle(r, &grCurClip, TRUE, dinfo, tpoints, &tnum); + + for (i = 0; i < tnum; i++) + { + j = (i + 1) % tnum; + if (tpoints[i].p_x != tpoints[j].p_x && + tpoints[i].p_y != tpoints[j].p_y) + { + GrClipLine(tpoints[i].p_x, tpoints[i].p_y, + tpoints[j].p_x, tpoints[j].p_y); + break; + } + } +} + +/*--------------------------------------------------------- + * GrDiagonal: + * GrDiagonal will draw a triangle on the screen in the + * style set by the previous call to GrSetStuff. It will also + * be clipped against the rectangles passed to GrSetStuff. + * + * If GrDiagonal is called between GrFastBox calls then GrSetStuff + * must be called to set the parameters back. + * + * Results: + * None. + * + * Side Effects: + * The rectangle is drawn in the style specified. + * The rectangle is clipped before being drawn. + *--------------------------------------------------------- + */ + +void +GrDiagonal(prect, dinfo) + Rect *prect; /* The rectangle to be drawn, given in + * screen coordinates. + */ + TileType dinfo; /* split and direction information */ +{ + Rect *r; + bool needClip, needObscure; + LinkedRect *ob; + int cp, np; + Rect clipr, fullr; + Point polyp[5]; + + GR_CHECK_LOCK(); + if (!grDriverInformed) grInformDriver(); + GrNumClipBoxes++; + if (grCurFill == GR_STGRID) + { + r = &grCurClip; + grGridRect = prect; + } + else + { + r = prect; + if (!GEO_TOUCH(r, &grCurClip)) return; + } + + /* Do a quick check to make the (very common) special case of + * no clipping go fast. + */ + needClip = !GEO_SURROUND(&grCurClip, r); + needObscure = FALSE; + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) + needObscure |= GEO_TOUCH(r, &(ob->r_r)); + + /* Generate points for the triangle and do clipping if necessary */ + + clipr = fullr = *r; + if (needClip) + GeoClip(&clipr, &grCurClip); + + GrClipTriangle(&fullr, &clipr, needClip, dinfo, polyp, &np); + + /* do solid areas */ + if ( (grCurFill == GR_STSOLID) || + (grCurFill == GR_STSTIPPLE) || (grCurFill == GR_STGRID) ) + { + if (needObscure) + grObsBox(&clipr); + else if (grFillPolygonPtr) + (void) (*grFillPolygonPtr)(polyp, np); + } + + /* return if rectangle is too small to see */ + + if ((r->r_xtop - r->r_xbot < GR_THRESH) && + (r->r_ytop - r->r_ybot < GR_THRESH) && (grCurFill != GR_STOUTLINE)) + return; + + /* draw outlines */ + if ( (grCurOutline != 0) && (grCurFill != GR_STGRID) ) + { + /* TO DO: Check for boundary with shared tile type */ + for (cp = 0; cp < np - 1; cp++) + (*grDrawLinePtr)(polyp[cp].p_x, polyp[cp].p_y, + polyp[cp + 1].p_x, polyp[cp + 1].p_y); + + (*grDrawLinePtr)(polyp[cp].p_x, polyp[cp].p_y, + polyp[0].p_x, polyp[0].p_y); + } +} + +/*--------------------------------------------------------- + * GrFillPolygon -- + * This routine is simply a call to the locally-defined + * grFillPolygonPtr routine. + * + *--------------------------------------------------------- + */ + +void +GrFillPolygon(polyp, np) + Point *polyp; /* Array of points defining polygon */ + int np; /* number of points in array polyp */ +{ + if (grFillPolygonPtr != NULL) + { + (*grFillPolygonPtr)(polyp, np); + } +} + + +/*--------------------------------------------------------- + * GrClipBox: + * GrClipBox will draw a rectangle on the screen in one + * of several possible styles, except that the rectangle will + * be clipped against a list of obscuring rectangles. + * + * Results: None. + * + * Side Effects: + * The rectangle is drawn in the style specified. + * The rectangle is clipped before being drawn. + *--------------------------------------------------------- + */ + +void +GrClipBox(prect, style) + Rect *prect; /* The rectangle to be drawn, given in + * screen coordinates. + */ + int style; /* The style to be used in drawing it. */ +{ + GrSetStuff(style); + GrFastBox(prect); +} + + +/* + * ---------------------------------------------------------------------------- + * GrDisjoint -- + * + * Clip a rectanglular area against a clipping box, applying the + * supplied procedure to each rectangular region in "area" which + * falls outside "clipbox". This works in pixel space, where a + * rectangle is contains its lower x- and y-coordinates AND ALSO + * its upper coordinates. This means that if the clipping box + * occupies a given pixel, the things being clipped must not occupy + * that pixel. This procedure will NOT work in tile space. + * + * The procedure should be of the form: + * bool func(box, cdarg) + * Rect * box; + * ClientData cdarg; + * + * Results: + * Return TRUE unless the supplied function returns FALSE. + * + * Side effects: + * The side effects of the invoked procedure. + * ---------------------------------------------------------------------------- + */ +bool +GrDisjoint(area, clipBox, func, cdarg) + Rect * area; + Rect * clipBox; + bool (*func) (); + ClientData cdarg; +{ + Rect ok, rArea; + bool result; + +#define NULLBOX(R) ((R.r_xbot>R.r_xtop)||(R.r_ybot>R.r_ytop)) + + ASSERT((area!=(Rect *) NULL), "GrDisjoint"); + if((clipBox==(Rect *) NULL)||(!GEO_TOUCH(area, clipBox))) + { + /* Since there is no overlap, all of "area" may be processed. */ + + result= (*func)(area, cdarg); + return(result); + } + + /* Do the disjoint operation in four steps, one for each side + * of clipBox. In each step, divide the area being clipped + * into one piece that is DEFINITELY outside clipBox, and one + * piece left to check some more. + */ + + /* Top edge of clipBox: */ + + rArea = *area; + result = TRUE; + if (clipBox->r_ytop < rArea.r_ytop) + { + ok = rArea; + ok.r_ybot = clipBox->r_ytop + 1; + rArea.r_ytop = clipBox->r_ytop; + if (!(*func)(&ok, cdarg)) result = FALSE; + } + + /* Bottom edge of clipBox: */ + + if (clipBox->r_ybot > rArea.r_ybot) + { + ok = rArea; + ok.r_ytop = clipBox->r_ybot - 1; + rArea.r_ybot = clipBox->r_ybot; + if (!(*func)(&ok, cdarg)) result = FALSE; + } + + /* Right edge of clipBox: */ + + if (clipBox->r_xtop < rArea.r_xtop) + { + ok = rArea; + ok.r_xbot = clipBox->r_xtop + 1; + rArea.r_xtop = clipBox->r_xtop; + if (!(*func)(&ok, cdarg)) result = FALSE; + } + + /* Left edge of clipBox: */ + + if (clipBox->r_xbot > rArea.r_xbot) + { + ok = rArea; + ok.r_xtop = clipBox->r_xbot - 1; + rArea.r_xbot = clipBox->r_xbot; + if (!(*func)(&ok, cdarg)) result = FALSE; + } + + /* Just throw away what's left of the area being clipped, since + * it overlaps the clipBox. + */ + + return result; +} /*GrDisjoint*/ diff --git a/graphics/grDStyle.c b/graphics/grDStyle.c new file mode 100644 index 00000000..04b5da1d --- /dev/null +++ b/graphics/grDStyle.c @@ -0,0 +1,633 @@ +/* grDStyle.c - + * + * Parse and read in the display style file. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * Portions of this code are Copyright (C) 2003 Open Circuit Design, Inc., + * for MultiGiG Ltd. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grDStyle.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/styles.h" +#include "utils/utils.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/glyphs.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "dbwind/dbwind.h" + +/* imports from other graphics files */ +extern void (*grSetSPatternPtr)(); +extern void (*grDefineCursorPtr)(); + +/* data structures local to this file only */ + +/* Define a linked-list record to keep track of styles prior */ +/* to allocating the fixed array GrStyleTable. */ + +typedef struct _dstylelink { + GR_STYLE_LINE style; + char shortname; + struct _dstylelink *next; +} dstylelink; + +/* data structures local to the graphics module */ + +extern int grBitPlaneMask; /* Mask of the valid bit-plane bits. */ + +static GrGlyphs *grCursorGlyphs = NULL; +static dstylelink *dstylehead = NULL; + +global int **GrStippleTable = NULL; +global int grNumStipples = 0; + +/* MUST be the same indices as the constants in graphicsInt.h */ +char *fillStyles[] = { + "solid", + "cross", + "outline", + "stipple", + "grid", + NULL }; + + + +/* Internal constants for each section of the style file. */ +/* These are bitmask-mapped so the display style reader */ +/* can check that the section are read in proper order. */ + +#define IGNORE -1 +#define DISP_STYLES 1 +#define LAYOUT_STYLES 2 +#define PALE_STYLES 4 +#define STIPPLES 8 +#define DISP_VERSION 16 + +#define STRLEN 200 + +/* Global variables to export to other modules */ + +int GrStyleNames[128]; /* short names for styles */ +GR_STYLE_LINE *GrStyleTable; + + + +bool +GrDrawGlyphNum(num, xoff, yoff) + int num; + int xoff; + int yoff; +{ + Point p; + + p.p_x = xoff; + p.p_y = yoff; + if (num >= grCursorGlyphs->gr_num) return FALSE; + GrDrawGlyph(grCursorGlyphs->gr_glyph[num], &p); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * GrGetStyleFromName -- + * + * Return an integer style number given a "long name". + * + * Results: + * Integer style number, or -1 if no style matches the name. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +GrGetStyleFromName(stylename) + char *stylename; +{ + int style; + int maxstyles = TECHBEGINSTYLES + (DBWNumStyles * 2); + + for (style = 0; style < maxstyles; style++) + if (GrStyleTable[style].longname != NULL) + if (!strcmp(stylename, GrStyleTable[style].longname)) + break; + + return (style == maxstyles) ? -1 : style; +} + +/* + * ---------------------------------------------------------------------------- + * + * GrResetStyles -- + * + * Free memory associated with the display styles in preparation for + * re-reading the styles file. + * + * Results: + * None. + * + * Side effects: + * Allocated memory free'd. + * + * ---------------------------------------------------------------------------- + */ + +void +GrResetStyles() +{ + int i; + + if (DBWNumStyles == 0) return; /* Nothing has been allocated yet */ + + for (i = 0; i < TECHBEGINSTYLES + (DBWNumStyles * 2); i++) + if (GrStyleTable[i].longname != NULL) + freeMagic(GrStyleTable[i].longname); + + freeMagic((char *)GrStyleTable); + GrStyleTable = NULL; + DBWNumStyles = 0; +} + + +/* + * ---------------------------------------------------------------------------- + * styleBuildDisplayStyle: + * + * Take one line of the display_styles section and process it. + * + * Results: + * True if things worked, false otherwise. + * + * Side effects: + * none + * ---------------------------------------------------------------------------- + */ + +bool +styleBuildDisplayStyle(line, version) + char *line; + int version; +{ + bool res; + int argsread; + int ord = 1, mask, color, outline, nfill, stipple; + char shortName, longName[52]; + char fill[42], ordstr[12], colorName[30]; + dstylelink *newstyle, *sstyle; + + char v6scanline[] = "%10s %o %29s %o %40s %d %c %50s"; + char v7scanline[] = "%10s %i %29s %i %40s %d %c %50s"; + + char *scanline = (version > 6) ? v7scanline : v6scanline; + + res = TRUE; + + if ((argsread = sscanf(line, scanline, + ordstr, &mask, colorName, &outline, fill, &stipple, + &shortName, &longName)) < 7) + { + res = FALSE; + } + else + { + newstyle = (dstylelink *)mallocMagic(sizeof(dstylelink)); + newstyle->next = dstylehead; + dstylehead = newstyle; /* note that dstylehead has styles + * in reverse order. + */ + + /* Allow colors to be specified by index or by name */ + if (sscanf(colorName, ((version > 6) ? "%i" : "%o"), &color) == 0) + color = GrNameToColor(colorName); + + newstyle->style.mask = (mask & grBitPlaneMask); + newstyle->style.color = (color & grBitPlaneMask); + newstyle->style.outline = outline; + if (StrIsInt(ordstr)) + { + newstyle->style.idx = atoi(ordstr); + if (newstyle->style.idx > ord) + ord = newstyle->style.idx + 1; + } + else + newstyle->style.idx = ord++; + nfill = LookupFull(fill, fillStyles); + if (nfill < 0) + res = FALSE; + newstyle->style.fill = nfill; + newstyle->style.stipple = stipple; + + /* Add short style name reverse lookup table entry */ + newstyle->shortname = shortName & 0x7f; + + if (argsread == 8) + newstyle->style.longname = StrDup(NULL, longName); + else + newstyle->style.longname = NULL; + } + return(res); +} + + +/* + * ---------------------------------------------------------------------------- + * styleBuildStippleStyle: + * + * Take one line of the stipples section and process it. + * + * Results: + * True if things worked, false otherwise. + * + * Side effects: + * none + * ---------------------------------------------------------------------------- + */ + +bool +styleBuildStipplesStyle(line, version) + char *line; + int version; +{ + bool res; + int ord; + int row[8]; + + char v6scanline[] = "%d %o %o %o %o %o %o %o %o"; + char v7scanline[] = "%d %x %x %x %x %x %x %x %x"; + + char *scanline = (version > 6) ? v7scanline : v6scanline; + + res = TRUE; + + if (sscanf(line, scanline, + &ord, &(row[0]), &(row[1]), &(row[2]), &(row[3]), + &(row[4]), &(row[5]), &(row[6]), &(row[7]) ) != 9) + { + res = FALSE; + } + else + { + if (ord < 0) + res = FALSE; + else + { + int i, j, ns, **sttable; + + ns = MAX(grNumStipples, ord + 1); + if (ns > grNumStipples) + { + /* Grab in blocks of 8 to avoid over-use of malloc. . . */ + if (ns < (grNumStipples + 8)) ns = grNumStipples + 8; + + sttable = (int **)mallocMagic(ns * sizeof(int *)); + for (i = 0; i < grNumStipples; i++) + sttable[i] = GrStippleTable[i]; + for (; i < ns; i++) + { + sttable[i] = (int *)mallocMagic(8 * sizeof(int)); + for (j = 0; j < 8; j++) + sttable[i][j] = 0; + } + if (GrStippleTable) freeMagic((char *)GrStippleTable); + GrStippleTable = sttable; + grNumStipples = ns; + } + for (i = 0; i < 8; i++) + GrStippleTable[ord][i] = row[i]; + } + } + return(res); +} + + +/* + * ---------------------------------------------------------------------------- + * GrLoadCursors -- + * + * Loads the graphics cursors from a given file. There must not be + * any window locks set, as this routine may need to write to the + * display. + * + * Results: + * True if things worked, false otherwise. + * + * Side effects: + * Cursor patterns are loaded, which may involve writing to the + * display. The file from which the cursors are read is determined + * by combining grCursorType (a driver-dependent string) with a + * ".glyphs" extension. + * ---------------------------------------------------------------------------- + */ + +bool +GrLoadCursors(path, libPath) +char *path; +char *libPath; +{ + if (grCursorGlyphs != (GrGlyphs *) NULL) + { + GrFreeGlyphs(grCursorGlyphs); + grCursorGlyphs = (GrGlyphs *) NULL; + } + + if (!GrReadGlyphs(grCursorType, path, libPath, &grCursorGlyphs)) + { + return FALSE; + } + + if (grDefineCursorPtr == NULL) + TxError("Display does not have a programmable cursor.\n"); + else + (*grDefineCursorPtr)(grCursorGlyphs); + + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * GrLoadStyles: + * + * Reads in a display style file. This has the effect of setting the + * box styles and stipple patterns. + * + * Results: + * -1 if the file contained a format error. + * -2 if the file was not found. + * 0 if everything went OK. + * + * Side effects: + * global variables are changed. + * ---------------------------------------------------------------------------- + */ + +int +GrLoadStyles(techType, path, libPath) +char *techType; /* Type of styles wanted by the technology + * file (usually "std"). We tack two things + * onto this name: the type of styles + * wanted by the display, and a version + * suffix. This three-part name is used + * to look up the actual display styles + * file. + */ +char *path; +char *libPath; +{ + FILE *inp; + int res = 0; + int i, scount, processed = DISP_VERSION; + char fullName[256]; + dstylelink *sstyle; + int MaxTechStyles = 0, MaxTileStyles = 0; + + /* The dstyle file format version number was buried in the filename */ + /* prior to version 6. Therefore versions which do not have a */ + /* "version" keyword in the file should default to version 5. */ + int version = 5; + + /* Reset number of styles to zero */ + GrResetStyles(); + + for (i = 0; i < 128; i++) GrStyleNames[i] = 0; + + (void) sprintf(fullName, "%.100s.%.100s.dstyle", techType, grDStyleType); + + inp = PaOpen(fullName, "r", (char *) NULL, path, libPath, (char **) NULL); + if (inp == NULL) + { + /* Try old format ".dstyle5"? */ + (void) sprintf(fullName, "%.100s.%.100s.dstyle5", techType, grDStyleType); + inp = PaOpen(fullName, "r", (char *) NULL, path, libPath, (char **) NULL); + if (inp == NULL) + { + TxError("Couldn't open display styles file \"%s\"\n", fullName); + return(-2); + } + } + else + { + char line[STRLEN], sectionName[STRLEN]; + char *sres; + bool newSection = FALSE; + int section; + + while (TRUE) + { + sres = fgets(line, STRLEN, inp); + if (sres == NULL) break; + if (StrIsWhite(line, FALSE)) + newSection = TRUE; + else if (line[0] == '#') + { + /* comment line */ + } + else if (newSection) + { + if (sscanf(line, "%s", sectionName) != 1) + { + TxError("File contained format error: " + "unable to read section name.\n"); + res = -1; + } + if (strcmp(sectionName, "version") == 0) + { + if (sscanf(line, "%*s %d", &version) != 1) + { + TxError("DStyle format version could not be " + "read: assuming version 6\n"); + version = 6; + } + section = DISP_VERSION; + } + else if (strcmp(sectionName, "display_styles") == 0) + { + int locbitplanes; + + if ((processed & (LAYOUT_STYLES | PALE_STYLES)) != 0) + { + TxError("DStyle sections out of order: display_styles must " + "come before layout_styles and pale_styles\n"); + res = -1; + } + section = DISP_STYLES; + scount = 0; + } + else if (strcmp(sectionName, "layout_styles") == 0) + { + if ((processed & PALE_STYLES) != 0) + { + TxError("DStyle sections out of order: layout_styles must " + "come before pale_styles\n"); + MainExit(1); + } + section = LAYOUT_STYLES; + if (scount < TECHBEGINSTYLES) + { + TxError("Error: Display style file defines only %d of " + "%d required internal styles.\n", scount, + TECHBEGINSTYLES); + } + else if (scount > TECHBEGINSTYLES) + { + TxError("Error: Display style file defines too many (%d) " + "internal styles; should be %d.\n", scount, + TECHBEGINSTYLES); + } + scount = 0; + } + else if (strcmp(sectionName, "pale_styles") == 0) + { + section = PALE_STYLES; + MaxTechStyles = scount + TECHBEGINSTYLES; + scount = 0; + } + else if (strcmp(sectionName, "stipples") == 0) + { + section = STIPPLES; + if (grNumStipples > 0) + { + while (grNumStipples > 0) + freeMagic((char *)GrStippleTable[--grNumStipples]); + freeMagic((char *)GrStippleTable); + GrStippleTable = NULL; + } + } + else + { + if (StrIsInt(sectionName)) + { + TxError("Unexpected empty line in .dstyle file.\n"); + newSection = FALSE; + goto recovery; + } + TxError("Bad section name \"%s\" in .dstyle file.\n", + sectionName); + section = IGNORE; + } + newSection = FALSE; + processed |= section; + } + else + { + int newres = TRUE; + +recovery: + switch (section) + { + case LAYOUT_STYLES: + case PALE_STYLES: + case DISP_STYLES: + newres = styleBuildDisplayStyle(line, version); + scount++; + break; + case STIPPLES: + newres = styleBuildStipplesStyle(line, version); + break; + case DISP_VERSION: + case IGNORE: + break; + default: + TxError("Internal error in GrStyle\n"); + break; + } + if (!newres) + { + TxError("Style line contained format error: %s", line); + res = -1; + } + } + } + } + if (fclose(inp) == EOF) + TxError("Could not close styles file.\n"); + + if ((processed | STIPPLES) != (LAYOUT_STYLES | DISP_STYLES + | PALE_STYLES | STIPPLES | DISP_VERSION)) + { + TxError("Not all required style sections were read. Missing" + " sections are:"); + if (!(processed & DISP_STYLES)) + TxError(" display_styles"); + if (!(processed & LAYOUT_STYLES)) + TxError(" layout_styles"); + if (!(processed & PALE_STYLES)) + TxError(" pale_styles"); + if (!(processed & DISP_VERSION)) + TxError(" version"); + TxError("\n"); + res = -1; + } + else + { + if (grSetSPatternPtr) + (*grSetSPatternPtr)(GrStippleTable, grNumStipples); + + if ((MaxTechStyles - TECHBEGINSTYLES) != scount) + { + TxError("Error: Number of pale styles (%d) is different from " + "the number of layout styles (%d)\n", + scount, MaxTechStyles - TECHBEGINSTYLES); + res = -1; + } + else + { + DBWNumStyles = scount; + MaxTileStyles = MaxTechStyles + scount; + + GrStyleTable = (GR_STYLE_LINE *)mallocMagic(MaxTileStyles * + sizeof(GR_STYLE_LINE)); + + /* Fill in table backwards, since linked list is a stack */ + sstyle = dstylehead; + for (i = MaxTileStyles - 1; i >= 0; i--) + { + if (sstyle == NULL) + { + GrStyleTable[i].longname = NULL; + break; + } + else + { + GrStyleTable[i] = sstyle->style; + /* Add short style name reverse lookup table entry */ + GrStyleNames[(int)(sstyle->shortname)] = i; + freeMagic(sstyle); + sstyle = sstyle->next; + } + } + dstylehead = NULL; + } + } + if (res != 0) GrResetStyles(); + return(res); +} diff --git a/graphics/grGlyphs.c b/graphics/grGlyphs.c new file mode 100644 index 00000000..034f32f5 --- /dev/null +++ b/graphics/grGlyphs.c @@ -0,0 +1,242 @@ + +/* grGlyphs.c - + * + * Handle glyphs -- reading and display. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grGlyphs.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/utils.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "graphics/glyphs.h" +#include "textio/textio.h" +#include "utils/malloc.h" + +#define STRLEN 500 + +extern void (*grFreeCursorPtr)(); + + +/* + * ---------------------------------------------------------------------------- + * GrFreeGlyphs -- + * + * Free a malloc'ed glyph structure. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +GrFreeGlyphs(g) + GrGlyphs *g; +{ + int i; + ASSERT(g != NULL, "GrFreeGlyphs"); + + if (grFreeCursorPtr != NULL) + (*grFreeCursorPtr)(g); + + + for (i = 0; i < g->gr_num; i++) + { + if ((g->gr_glyph[i]->gr_cache != (ClientData) NULL) && + (g->gr_glyph[i]->gr_free != NULL)) + { + (*(g->gr_glyph[i]->gr_free))(g->gr_glyph[i]->gr_cache); + } + freeMagic( (char *) g->gr_glyph[i]); + } + freeMagic( (char *) g); +} + + +/* + * ---------------------------------------------------------------------------- + * GrReadGlyphs -- + * + * Read a set of glyphs from the specified file. + * + * Results: + * TRUE if it worked. + * + * Side effects: + * A structure is malloc'ed and the last argument pointed to it. + * Error messages are printed if there is any problem reading + * the glyphs file. + * ---------------------------------------------------------------------------- + */ + +bool +GrReadGlyphs(filename, path, libPath, gl) + char *filename; + char *path, *libPath; /* paths to search in for the file */ + GrGlyphs **gl; /* To be filled in with a malloc'ed structure + * This structure must be freed by the caller + * if it is not to live forever. + */ +{ + FILE *file; + bool result = TRUE; + GrGlyphs *ourgl = NULL; + int x, y, glyphnum; + int xmax, ymax, glyphnummax; + char line[STRLEN], *fullname; + bool sizeline = FALSE; + + file = PaOpen(filename, "r", ".glyphs", path, libPath, &fullname); + if (file == NULL) + { + TxError("Couldn't read glyphs file \"%s.glyphs\"\n", filename); + result = FALSE; + goto endit; + } + y = glyphnum = glyphnummax = xmax = ymax = -1; + + while (TRUE) + { + char *sres; + sres = fgets(line, STRLEN, file); + if (sres == NULL) /* end of file */ + { + if ((y == 0) && (glyphnum == glyphnummax)) + result = TRUE; + else + { + TxError("Unexpected end of file in file '%s'\n", fullname); + result = FALSE; + } + goto endit; + } + else if (!StrIsWhite(line, TRUE)) + { + char *cp; + /* an interesting line */ + if (sizeline) + { + if (y > 0) + y--; /* scan from top down */ + else + { + y = ymax; + glyphnum++; + if (glyphnum > glyphnummax) + { + TxError("Extra lines at end of glyph file '%s'\n", + fullname); + result = TRUE; + goto endit; + } + } + cp = line; + + for (x = 0; x <= xmax; x++) + { + char trailingChar; + + if (isspace(*cp)) + { + TxError("Error in glyph file '%s', %s\n ", fullname, + "white space is not a valid glyph character"); + TxError("Line in error is '%s'\n", line); + result = FALSE; + goto endit; + } + ourgl->gr_glyph[glyphnum]->gr_pixels[x + (xmax+1) * y] = + GrStyleNames[ (*cp) & 127 ]; + + cp++; + trailingChar = *cp; + if (trailingChar == '*') + { + ourgl->gr_glyph[glyphnum]->gr_origin.p_x = x; + ourgl->gr_glyph[glyphnum]->gr_origin.p_y = y; + } + + if (x != xmax) + { + cp++; + if ((trailingChar == '\0') || (*cp == '\0')) + { + TxError("Error in glyph file '%s', %s\n ", + fullname, "line is too short."); + TxError("Line in error is '%s'\n", line); + result = FALSE; + goto endit; + } + } + } + } + else + { + int i; + if (sscanf(line, "size %d %d %d\n", + &glyphnummax, &xmax, &ymax) != 3) + { + TxError("Format error in file '%s'\n", fullname); + result = FALSE; + goto endit; + } + sizeline = TRUE; + glyphnummax--; + xmax--; + ymax--; + glyphnum = 0; + x = 0; + y = ymax + 1; + ourgl = (GrGlyphs *) mallocMagic((unsigned) (sizeof(GrGlyphs) + + ((glyphnummax + 1) * sizeof(GrGlyph *))) ); + ourgl->gr_num = glyphnummax + 1; + for (i = 0; i <= glyphnummax; i++) + { + size_t size = sizeof(GrGlyph) + sizeof(int) * (xmax + 1) + * (ymax + 1); + ourgl->gr_glyph[i] = (GrGlyph *) mallocMagic(size); + + /* Null all the fields initially. */ + memset(ourgl->gr_glyph[i], 0, size); + + ourgl->gr_glyph[i]->gr_origin.p_x = 0; + ourgl->gr_glyph[i]->gr_origin.p_y = 0; + ourgl->gr_glyph[i]->gr_xsize = xmax + 1; + ourgl->gr_glyph[i]->gr_ysize = ymax + 1; + } + } + } + } + +endit: + if (file != NULL) + (void) fclose(file); + if (result) + *gl = ourgl; + else if (ourgl != NULL) + GrFreeGlyphs(ourgl); + return result; +} diff --git a/graphics/grLock.c b/graphics/grLock.c new file mode 100644 index 00000000..747d8efb --- /dev/null +++ b/graphics/grLock.c @@ -0,0 +1,216 @@ +/* grLock.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains information related to the locking of windows. + * Windows are locked before any redisplay is done in them, and then + * unlocked afterwards. The procedures grSimpleLock and grSimpleUnlock + * are provided for device drivers that want to ingore the locking stuff -- + * they can just point GrLockPtr and GrUnlockPtr to them. More sophisticated + * drivers (such as for the Sun 160) will want to do some of their own + * locking themselves. + * + * Locking sets up a clipping region (grCurClip and grCurObscure) that is + * used by the graphics drawing routines to clip things being displayed. + * It is an error to draw stuff without locking a window first, and device + * drivers should check for this case by using the macro GR_CHECK_LOCK(). + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grLock.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "textio/textio.h" + +MagWindow *grLockedWindow = NULL; /* The window that we are redisplaying */ +bool grLockScreen = FALSE; /* Full screen access? */ +bool grTraceLocks = FALSE; /* For debugging */ +bool grLockBorder; /* Redrawing the border of the window too? */ + +Rect grCurClip; /* Clip all output to this rectangle */ +LinkedRect * grCurObscure; /* A list of obscuring areas */ + +/* + * ---------------------------------------------------------------------------- + * grWindName -- + * + * Return a string describing the window, either the window caption, + * or "NULL" for a null MagWindow pointer, or "FULL_SCREEN" when + * w is set to GR_LOCK_SCREEN. + * + * Results: + * A string representing the window or window caption + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +static char * +grWindName(w) + MagWindow *w; +{ + if (w == NULL) return ""; + if (w == GR_LOCK_SCREEN) return ""; + return w->w_caption; +} + +/* + * ---------------------------------------------------------------------------- + * grSimpleLock & grSimpleUnlock -- + * + * Handy procedures for device drivers. + * + * Lock a window so that we may safely write to it. Locking is + * required before any operation that may modify the window's pixels. + * Locking is slow and should be done around large blocks of code. + * + * Only one window may be locked at a time. + * + * Results: + * None. + * + * Side effects: + * Stores away the window and clipping info. + * ---------------------------------------------------------------------------- + */ + +void +grSimpleLock(w, inside) + MagWindow *w; /* The window to lock, or GR_LOCK_SCREEN if the + * whole screen. + */ + bool inside; /* If TRUE, clip to inside of window, otherwise clip + * to outside of window. + */ +{ + ASSERT(w != NULL, "grSimpleLock"); + grLockScreen = (w == GR_LOCK_SCREEN); + if (grTraceLocks) TxError("--- Lock %s\n", grWindName(w)); + if (grLockScreen) { + grCurClip = GrScreenRect; + grCurObscure = NULL; + } else { + if (grLockedWindow != NULL) { + TxError("Magic error: Attempt to lock more than one window!\n"); + TxError("Currently locked window is: '%s'\n", + grWindName(grLockedWindow)); + TxError("Window to be locked is: '%s'\n", grWindName(w)); + /* dump core here */ + ASSERT(grLockedWindow == NULL, "grSimpleUnlock"); + } + if (inside) + grCurClip = w->w_screenArea; + else + grCurClip = w->w_allArea; + grCurObscure = w->w_clipAgainst; + } + grLockBorder = !inside; + grLockedWindow = w; + GeoClip(&grCurClip, &GrScreenRect); +} + + +void +grSimpleUnlock(w) + MagWindow *w; +{ + ASSERT(w != NULL, "grSimpleUnlock"); + if (grTraceLocks) TxError("--- Unlock %s\n", grWindName(w)); + if (w != grLockedWindow) { + TxError("Magic error: Attempt to unlock a window that wasn't locked\n"); + TxError("Currently locked window is: '%s'\n", + grWindName(grLockedWindow)); + TxError("Window to be unlocked is: '%s'\n", grWindName(w)); + /* dump core here */ + ASSERT(w == grLockedWindow, "grSimpleUnlock"); + } + grLockedWindow = NULL; + grLockScreen = FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * GrClipTo + * + * Further restrict the clipping area to a portion of a window. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +GrClipTo(r) + Rect *r; +{ + if (grLockedWindow == NULL) return; + if (grLockScreen) + grCurClip = GrScreenRect; + else if (grLockBorder) + grCurClip = grLockedWindow->w_allArea; + else + grCurClip = grLockedWindow->w_screenArea; + GeoClip(&grCurClip, r); + GeoClip(&grCurClip, &GrScreenRect); +} + +/* + * ---------------------------------------------------------------------------- + * grNoLock + * + * We have encountered a bad lock. + * + * Results: + * None. + * + * Side effects: + * Complains or aborts. + * ---------------------------------------------------------------------------- + */ + +void +grNoLock() +{ + TxError("Magic error: Attempt to draw graphics without a window lock.\n"); + /*** ASSERT(FALSE, "grNoLock"); ***/ +} + +/* + * ---------------------------------------------------------------------------- + * GrHaveLock() + * + * Do we have a window lock? + * + * Results: + * boolean. + * + * Side effects: + * none. + * ---------------------------------------------------------------------------- + */ + +bool +GrHaveLock() +{ + return (grLockedWindow != NULL); +} diff --git a/graphics/grMain.c b/graphics/grMain.c new file mode 100644 index 00000000..dd458ac4 --- /dev/null +++ b/graphics/grMain.c @@ -0,0 +1,533 @@ +/* grMain.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains a few core variables and routines for + * manipulating color graphics displays. Its main function is + * to provide a central dispatch point to various routines for + * different display types. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grMain.c,v 1.4 2010/06/24 12:37:18 tim Exp $"; +#endif /* not lint */ + +/* + * The following display types are currently suported by Magic: + * + * NULL A null device for running Magic without using + * a graphics display. This device does nothing + * when its routines are called. + * + * X11 A port to the X11 window system, based on the Stanford + * XWIND X10 driver, mods done at Brown University, an X11 port + * done at the University of Washington, and the X10a + * driver from Lawrence Livermore Labs. This driver was + * developed by Don Stark (Stanford & decwrl). + * 8BIT X11 driver, force 8-bit graphics mode. + * 16BIT X11 driver, force 16-bit graphics mode. + * 24BIT X11 driver, force 24-bit graphics mode. + * + * OpenGL A port to OpenGL or Mesa. Developed by Tim Edwards + * (Johns Hopkins University Applied Physics Lab) + * + * To port Magic to another type of display, you need to add its name to + * the table 'grDisplayTypes' and then add a pointer to an initialization + * routine to 'grInitProcs'. The initialization routine will fill in all + * of the graphics routine pointers so that they point to procedures that + * can handle the new display type. All calls to device-specific + * procedures are made by indirecting through these pointers. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/magsgtty.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" + +#define FAVORITE_DISPLAY "NULL" /* Default display type */ + +/* Correction between real-valued coordinate systems and pixel-based + * coordinate systems, which can disagree by a pixel on the width of + * polygons and position of lines. + */ +global int GrPixelCorrect = 1; + +/* The following rectangle is describes the display area and is available + * to the user of this module. + */ +global Rect GrScreenRect = {0, 0, 0, 0}; + +/* + * Interrupt status for the timer. In TCL, this is used for graphics + * interrupts to periodically check the X11 queue for pending events. + * In both TCL and non-TCL versions, it can be used for a general- + * purpose interrupt timer. + */ +global unsigned char GrDisplayStatus = DISPLAY_IDLE; + +/* The first of the following tables defines the legal + * display types and the second table defines an + * initialization routine for each type. + * + * These entries MUST be all upper case, since what the user types will + * be converted to upper case before comparison. + */ + +static char *grDisplayTypes[] = { +#ifdef X11 + "XWIND", + "X11", + "8BIT", + "16BIT", + "24BIT", +#endif +#ifdef OGL + "OPEN_GL", + "OGL", + "OPENGL", +#endif + "NULL", + NULL}; + +extern bool x11SetDisplay(); +extern bool oglSetDisplay(); +extern bool nullSetDisplay(); + +static bool (*(grInitProcs[]))() = { +#ifdef X11 + x11SetDisplay, + x11SetDisplay, + x11SetDisplay, + x11SetDisplay, + x11SetDisplay, +#endif /* X11 */ +#ifdef OGL + oglSetDisplay, + oglSetDisplay, + oglSetDisplay, +#endif + nullSetDisplay, + NULL}; + +/* The following variables are pointers to the various graphics + * procedures. The macros in graphics.h cause these pointers + * to be indirected through when calls occur to graphics procedures. + * This indirection allows for several display types to be supported + * by a single version of Magic. The pointers are initially NULL, + * but are rewritten by the various graphics initializers. + */ + +void (*GrLockPtr)() = NULL; +void (*GrUnlockPtr)() = NULL; +bool (*GrInitPtr)() = NULL; +void (*GrClosePtr)() = NULL; +void (*GrSetCMapPtr)() = NULL; + +void (*GrSetCursorPtr)() = NULL; +void (*GrTextSizePtr)() = NULL; +void (*GrDrawGlyphPtr)() = NULL; +void (*GrBitBltPtr)() = NULL; +int (*GrReadPixelPtr)() = NULL; +void (*GrFlushPtr)() = NULL; +bool (*GrCreateWindowPtr)() = NULL; +void (*GrDeleteWindowPtr)() = NULL; +void (*GrConfigureWindowPtr)() = NULL; +void (*GrOverWindowPtr)() = NULL; +void (*GrUnderWindowPtr)() = NULL; +void (*GrDamagedPtr)() = NULL; +void (*GrUpdateIconPtr)() = NULL; +bool (*GrEventPendingPtr)() = NULL; +int (*GrWindowIdPtr)() = NULL; +char *(*GrWindowNamePtr)() = NULL; +bool (*GrGetCursorPosPtr)() = NULL; +bool (*GrGetCursorRootPosPtr)() = NULL; + +void (*GrEnableTabletPtr)() = NULL; +void (*GrDisableTabletPtr)() = NULL; + +bool (*GrGetBackingStorePtr)() = NULL; +bool (*GrScrollBackingStorePtr)() = NULL; +void (*GrPutBackingStorePtr)() = NULL; +void (*GrFreeBackingStorePtr)() = NULL; +void (*GrCreateBackingStorePtr)() = NULL; + +/* variables similar to the above, except that they are only used + * internal to the graphics package + */ +void (*grPutTextPtr)() = NULL; +void (*grFontTextPtr)() = NULL; +void (*grGetCharSizePtr)() = NULL; +void (*grSetSPatternPtr)() = NULL; +void (*grDefineCursorPtr)() = NULL; +void (*grFreeCursorPtr)() = NULL; +bool (*grDrawGridPtr)() = NULL; +void (*grDrawLinePtr)() = NULL; +void (*grSetWMandCPtr)() = NULL; +void (*grFillRectPtr)() = NULL; +void (*grSetStipplePtr)() = NULL; +void (*grSetLineStylePtr)() = NULL; +void (*grSetCharSizePtr)() = NULL; +void (*grFillPolygonPtr)() = NULL; + +/* The following variables are set by initialization routines for the + * various displays. They are strings that indicate what kind of + * dstyle, cmap and cursor files should be used for this display. Almost + * all of the displays are happy with the default values given below. + * Note: a NULL grCMapType means that this display doesn't need a + * color map (it's black-and-white). + */ + +char *grDStyleType = "7bit"; +char *grCMapType = "7bit"; +char *grCursorType = "bw"; + +int grNumBitPlanes = 0; /* Number of bit-planes we are using. */ +int grBitPlaneMask = 0; /* Mask of the valid bit-plane bits. */ + +/* Procedures called just before and after Magic is suspended (via ^Z). */ +extern void grNullProc(); +void (*GrStopPtr)() = grNullProc; +void (*GrResumePtr)() = grNullProc; + + +/*--------------------------------------------------------- + * GrSetDisplay -- + * This routine sets a display type, opens files, and initializes the + * display. + * + * Results: + * TRUE is returned if the display was found and initialized + * successfully. If the type didn't register, or the file is + * NULL, then FALSE is returned. + * + * Side Effects: + * Tables are set up to control which display routines are + * used when communcating with the display. The display + * is initialized and made ready for action. + *--------------------------------------------------------- + */ + +bool +GrSetDisplay(type, outName, mouseName) +char *type; /* Name of the display type. */ +char *outName; /* Filename used for communciation with + * display. */ +char *mouseName; /* Filename used for communciation + * with tablet. */ + +{ + char **ptr; + char *cp; + int i; + bool res; + + if (outName == NULL) + { + TxError("No graphics device specified.\n"); + return FALSE; + } + if (mouseName == NULL) + { + TxError("No mouse specified.\n"); + return FALSE; + } + + /* Skip any white space */ + while (isspace(*type)) type++; + + /* Convert display type to upper case. */ + for (cp = type; *cp; cp++) { if (islower(*cp)) *cp = toupper(*cp); } + + /* See if the display type is in our table. */ + ptr = grDisplayTypes; + for (i = 0; *ptr; i++) + { + if (strncmp(*ptr, type, strlen(*ptr)) == 0) break; + ptr++; + } + + /* Did we find it? */ + if (*ptr == NULL) + { + TxError("Unknown display type: %s\n", type); + TxError("These display types are available in this version of Magic:\n"); + ptr = grDisplayTypes; + for (i = 0; *ptr; i++) + { + TxError(" %s\n", *ptr); + ptr++; + } + TxError("Use '-d NULL' if you don't need graphics.\n"); + return FALSE; + } + + /* Call the initialization procedure. */ + res = (*(grInitProcs[i]))(type, outName, mouseName); + if (!res) + { + TxError("The graphics display couldn't be correctly initialized.\n"); + TxError("Use '-d NULL' if you don't need graphics.\n"); + } + return res; +} + +/* + * ---------------------------------------------------------------------------- + * + * GrIsDisplay -- + * + * Check if the first argument is the same type of display as the + * second argument. + * + * Results: + * TRUE if both strings represent the same display type, FALSE + * otherwise. "same display type" is defined as both display + * strings in the grDisplayTypes list corresponding to the same + * initialization procedure in grInitProcs. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ +bool +GrIsDisplay(disp1, disp2) + char *disp1, *disp2; +{ + char **ptr1, **ptr2; + int i, j; + + /* See if the display type is in our table. */ + ptr1 = grDisplayTypes; + for (i = 0; *ptr1; i++) + { + if (strncmp(*ptr1, disp1, strlen(*ptr1)) == 0) break; + ptr1++; + } + if (*ptr1 == NULL) + { + TxError("Unknown display type: %s\n", disp1); + return FALSE; + } + + ptr2 = grDisplayTypes; + for (j = 0; *ptr2; j++) + { + if (strncmp(*ptr2, disp2, strlen(*ptr2)) == 0) break; + ptr2++; + } + if (*ptr2 == NULL) + { + TxError("Unknown display type: %s\n", disp2); + return FALSE; + } + + if (grInitProcs[i] == grInitProcs[j]) return TRUE; + return FALSE; +} + + +/* + * ---------------------------------------------------------------------------- + * GrGuessDisplayType -- + * + * Try to guess what sort of machine we are on, and set the display + * ports and type appropriately. This info is overridden by + * $CAD_ROOT/magic/displays and by command line switches. + * + * Results: + * None. + * + * Side effects: + * Modifies the strings passed in. + * ---------------------------------------------------------------------------- + */ + +void +GrGuessDisplayType(graphics, mouse, display, monitor) + char **graphics; /* default device for sending out graphics */ + char **mouse; /* default device for reading mouse (tablet) */ + char **display; /* default type of device (OGL, etc...) */ + char **monitor; /* default type of monitor (pale, std) */ +{ + bool onSun; /* Are we on a Sun? */ + bool haveX; /* are we running under X? */ + char **ptr; + + *graphics = NULL; + *mouse = NULL; + *display = NULL; + *monitor = "std"; + + /* Check for signs of suntools. */ + onSun = (access("/dev/win0", 0) == 0); + haveX = (getenv("DISPLAY") != NULL); + + if (haveX) + { + *mouse = *graphics = NULL; + *display = "XWIND"; + } + else if (onSun) { + TxError("You are on a Sun but not running X.\n"); + *mouse = *graphics = NULL; + *display = "NULL"; + } + else { + /* GUESS: who knows, maybe a VAX? */ + *mouse = *graphics = NULL; + *display = FAVORITE_DISPLAY; + } + + /* If the guessed value is NOT in the known list of display types, then */ + /* choose the first display type in the list. ---Tim 3/13/00 */ + + ptr = grDisplayTypes; + while ((*ptr != *display) && (*ptr != NULL)) ptr++; + if ((*ptr == NULL) && (ptr != grDisplayTypes)) { + ptr = grDisplayTypes; + *display = *ptr; + } +} + + +/* + * ---------------------------------------------------------------------------- + * grFgets -- + * + * Just like fgets, except that it times out after 20 seconds, and prints + * a warning message. After one second a warning message is also + * printed. + * + * Results: + * Pointer to the string returned by fgets (equal to the 1st argument) + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +char * +grFgets(str, n, stream, name) + char *str; + int n; + FILE *stream; + char *name; /* The user name of the stream, for the error msg */ +{ + fd_set fn; + char *newstr; + struct timeval threeSec, twentySecs; + + threeSec.tv_sec = 3; + threeSec.tv_usec = 0; + twentySecs.tv_sec = 20; + twentySecs.tv_usec = 0; + + FD_ZERO(&fn); + FD_SET(fileno(stream), &fn); + newstr = str; + n--; + if (n < 0) return (char *) NULL; + + while (n > 0) + { + fd_set f; + char ch; + int sel; + + f = fn; + sel = select(TX_MAX_OPEN_FILES, &f, (fd_set *) NULL, (fd_set *) NULL, &threeSec); + if (sel == 0) + { + TxError("The %s is responding slowly, or not at all.\n", name); + TxError("I'll wait for 20 seconds and then give up.\n"); + f = fn; + sel = select(TX_MAX_OPEN_FILES, &f, (fd_set *) NULL, + (fd_set *) NULL, &twentySecs); + if (sel == 0) + { + TxError("The %s did not respond.\n", name); + return (char *) NULL; + } + else if (sel < 0) + { + if (errno == EINTR) { + TxError("Timeout aborted.\n"); + } + else + { + perror("magic"); + TxError("Error in reading the %s\n", name); + } + return (char *) NULL; + } + else + TxError("The %s finally responded.\n", name); + } + else if (sel < 0) + { + if (errno != EINTR) + { + perror("magic"); + TxError("Error in reading the %s\n", name); + return (char *) NULL; + } + /* else try again, back to top of the loop */ + continue; + } + + ch = getc(stream); + *newstr = ch; + n--; + newstr++; + if (ch == '\n') + break; + } + + *newstr = '\0'; + return str; +} + + +/*--------------------------------------------------------------------------- + * grNullProc -- + * + * A procedure of the type 'void' that does absolutely nothing. + * Used when we need to point a procedure pointer to something, but + * don't want it to do anything. + * + * Results: + * None. + * + * Side Effects: + * None. + * + *---------------------------------------------------------------------------- + */ + +void +grNullProc() +{ +} diff --git a/graphics/grNull.c b/graphics/grNull.c new file mode 100644 index 00000000..d9bfe8f3 --- /dev/null +++ b/graphics/grNull.c @@ -0,0 +1,285 @@ +/* + * grNull.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains dummy functions for use when there is no + * graphics display. + */ + +#include +#include + +#include "utils/magsgtty.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "textio/textio.h" +#include "textio/txcommands.h" +#include "utils/signals.h" + + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grNull.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + + +/* Forward declarations */ +extern bool nullReturnFalse(); +extern void nullDoNothing(); +extern int nullReturnZero(); + +/* + *--------------------------------------------------------- + * + * nullDoNothing -- + * + * This procedure does nothing. + * + * Results: + * None. + * + * Side Effects: + * None. + * + *--------------------------------------------------------- + */ + +void +nullDoNothing() +{ +} + +/* + *--------------------------------------------------------- + * + * nullReturnFalse -- + * + * This procedure does nothing, and returns FALSE. + * + * Results: + * Returns FALSE always. + * + * Side Effects: + * None. + * + *--------------------------------------------------------- + */ + +bool +nullReturnFalse() +{ + return (FALSE); +} + +/* + *--------------------------------------------------------- + * + * nullReturnZero -- + * + * This procedure does nothing, and returns 0. + * + * Results: + * Returns 0 always. + * + * Side Effects: + * None. + * + *--------------------------------------------------------- + */ + +int +nullReturnZero() +{ + return (0); +} + +/* + *--------------------------------------------------------- + * + * NullInit -- + * + * NullInit doesn't do much of anything. + * + * Results: + * TRUE always. + * + * Side Effects: + * None. + * + *--------------------------------------------------------- + */ + +bool +NullInit() +{ + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * NullTextSize -- + * + * Determine the size of a text string. + * + * Results: + * None. + * + * Side effects: + * A rectangle is filled in that is the size of the text in pixels. + * The origin (0, 0) of this rectangle is located on the baseline + * at the far left side of the string. + * + * ---------------------------------------------------------------------------- + */ + +void +NullTextSize(text, size, r) + char *text; + int size; + Rect *r; +{ + ASSERT(r != NULL, "nullTextSize"); + r->r_xbot = 0; + r->r_xtop = strlen(text); + r->r_ybot = 0; + r->r_ytop = 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * nullStdin -- + * + * Handle the stdin device for the NULL driver. + * + * Results: + * None. + * + * Side Effects: + * Adds events to the event queue. + * + * ---------------------------------------------------------------------------- + */ + +void +nullStdin(fd, cdata) + int fd; + ClientData cdata; +{ + int ch; + TxInputEvent *event; + + ch = getc(stdin); + event = TxNewEvent(); + if (ch == EOF) + event->txe_button = TX_EOF; + else + event->txe_button = TX_NO_BUTTON; + event->txe_buttonAction = 0; + event->txe_ch = ch; + event->txe_wid = WIND_UNKNOWN_WINDOW; + event->txe_p.p_x = GR_CURSOR_X; + event->txe_p.p_y = GR_CURSOR_Y; + TxAddEvent(event); +} + +/* + * ---------------------------------------------------------------------------- + * + * NullBitBlt -- + * + * A no-op BitBlt operation for devices that don't have one (such as + * the NULL device). + * + * Results: + * None. + * + * Side Effects: + * None, for sure, for sure. + * + * ---------------------------------------------------------------------------- + */ + +void +NullBitBlt() +{ +} + + +/* + *--------------------------------------------------------- + * + * nullSetDisplay -- + * + * This routine sets the appropriate parameters so that + * Magic will work with the particular display type. + * + * Results: + * Returns TRUE. + * + * Side Effects: + * Depends on the display type. + * + *--------------------------------------------------------- + */ + +bool +nullSetDisplay(dispType, outFileName, mouseFileName) + char *dispType; + char *outFileName; + char *mouseFileName; +{ + TxPrintf("Using NULL graphics device.\n"); + + TxAdd1InputDevice(fileno(stdin), nullStdin, (ClientData) NULL); + if (TxStdinIsatty) SigWatchFile(fileno(stdin), "stdin"); + + /* Set up the procedure values in the indirection table. */ + + GrLockPtr = grSimpleLock; + GrUnlockPtr = grSimpleUnlock; + GrInitPtr = NullInit; + GrClosePtr = nullDoNothing; + GrSetCMapPtr = nullDoNothing; + + GrEnableTabletPtr = nullDoNothing; + GrDisableTabletPtr = nullDoNothing; + GrSetCursorPtr = nullDoNothing; + GrTextSizePtr = NullTextSize; + GrDrawGlyphPtr = nullDoNothing; + GrBitBltPtr = NullBitBlt; + GrReadPixelPtr = nullReturnZero; + GrFlushPtr = nullDoNothing; + + /* local indirections */ + grSetSPatternPtr = nullDoNothing; + grPutTextPtr = nullDoNothing; + grFontTextPtr = nullDoNothing; + grDefineCursorPtr = nullDoNothing; + grDrawGridPtr = nullReturnFalse; + grDrawLinePtr = nullDoNothing; + grSetWMandCPtr = nullDoNothing; + grFillRectPtr = nullDoNothing; + grSetStipplePtr = nullDoNothing; + grSetLineStylePtr = nullDoNothing; + grSetCharSizePtr = nullDoNothing; + + GrScreenRect.r_xtop = 511; + GrScreenRect.r_ytop = 483; + + return TRUE; +} diff --git a/graphics/grOGL1.c b/graphics/grOGL1.c new file mode 100644 index 00000000..7488372b --- /dev/null +++ b/graphics/grOGL1.c @@ -0,0 +1,1078 @@ +/* grOGL1.c - + * + * This file contains primitive functions for OpenGL running under + * an X window system (using GLUT). + * Included here are initialization and closing + * functions, and several utility routines used by the other X + * modules. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/magsgtty.h" +#include "utils/geometry.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "textio/textio.h" +#include "textio/txcommands.h" +#include "utils/signals.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "grOGLInt.h" +#include "utils/paths.h" + +GLubyte **grOGLStipples; +HashTable grOGLWindowTable; +Display *grXdpy; +GLXContext grXcontext; +int grXscrn; +int pipeRead, pipeWrite; +int Xhelper; +Visual *grVisual; + +#ifdef HAVE_PTHREADS +extern int writePipe; +extern int readPipe; /* As seen from child */ +#endif + +OGL_CURRENT oglCurrent= {(XFontStruct *)NULL, 0,0,0,0, (Window)0, (MagWindow *)NULL}; + +/* This is kind of a long story, and very kludgy, but the following + * things need to be defined as externals because of the way lint + * libraries are made by taking this module and changing all procedures + * names "Xxxx" to "Grxxx". The change is only done at the declaration + * of the procedure, so we need these declarations to handle uses + * of those names, which don't get modified. Check out the Makefile + * for details on this. + */ + +extern void GrOGLClose(), GrOGLFlush(); +extern void GrOGLDelete(), GrOGLConfigure(), GrOGLRaise(), GrOGLLower(); +extern void GrOGLLock(), GrOGLUnlock(), GrOGLIconUpdate(); +extern bool GrOGLInit(), GrOGLCreate(); +extern void grOGLWStdin(); + + +/*--------------------------------------------------------- + * groglSetWMandC: + * This is a local routine that resets the value of the current + * write mask and color, if necessary. + * + * Results: None. + * + * Side Effects: None. + * + * Errors: None. + *--------------------------------------------------------- + */ + +void +groglSetWMandC (mask, c) + int mask; /* New value for write mask */ + int c; /* New value for current color */ +{ + static int oldMask = -1; + static int oldColor = -1; + + int lr, lb, lg; + GLfloat fr, fb, fg; + GLfloat aval = 0.75; /* Alpha value */ + + if (mask == -65) mask = 127; /* All planes */ + if (mask == oldMask && c == oldColor) return; + + GR_X_FLUSH_BATCH(); + + GrGetColor(c, &lr, &lb, &lg); + + fr = ((GLfloat)lr / 255); + fg = ((GLfloat)lg / 255); + fb = ((GLfloat)lb / 255); + + if (mask == 127) + glDisable(GL_BLEND); + else { + /* Calculate a "supercolor", out of normal color range, but which */ + /* results in the desired color after a blend with the background. */ + + fr = fr * 2 - 0.8; + fg = fg * 2 - 0.8; + fb = fb * 2 - 0.8; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + glColor4f(fr, fb, fg, aval); + + oldMask = mask; + oldColor = c; +} + + +/*--------------------------------------------------------- + * groglSetLineStyle: + * This local routine sets the current line style. + * + * Results: None. + * + * Side Effects: + * A new line style is output to the display. + * + *--------------------------------------------------------- + */ + +void +groglSetLineStyle (style) + int style; /* New stipple pattern for lines. */ +{ + static int oldStyle = -1; + GLushort glstyle; + + style &= 0xFF; + if (style == oldStyle) return; + oldStyle = style; + GR_X_FLUSH_BATCH(); + + switch (style) { + case 0xFF: + case 0x00: + glDisable(GL_LINE_STIPPLE); + break; + default: + glstyle = style | (style << 8); + glEnable(GL_LINE_STIPPLE); + glLineStipple(1, glstyle); + } +} + + +/*--------------------------------------------------------- + * groglSetSPattern: + * xSetSPattern associates stipple patterns with + * OpenGL stipples. This is a local routine + * called from grStyle.c. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +groglSetSPattern (sttable, numstipples) + int **sttable; /* The table of patterns */ + int numstipples; /* Number of stipples */ +{ + int i, j, k, n; + GLubyte *pdata; + + grOGLStipples = (GLubyte **)mallocMagic(numstipples * sizeof(GLubyte *)); + for (k = 0; k < numstipples; k++) + { + pdata = (GLubyte *)mallocMagic(128 * sizeof(GLubyte)); + n = 0; + + /* expand magic's default 8x8 stipple to OpenGL's 32x32 */ + + for (i = 0; i < 32; i++) + for (j = 0; j < 4; j++) + pdata[n++] = (GLubyte)sttable[k][i % 8]; + + grOGLStipples[k] = pdata; + } +} + + +/*--------------------------------------------------------- + * groglSetStipple: + * This routine sets the Xs current stipple number. + * + * Results: None. + * + * Side Effects: + * The current clipmask in the X is set to stipple, + * if it wasn't that already. + *--------------------------------------------------------- + */ + +void +groglSetStipple (stipple) + int stipple; /* The stipple number to be used. */ +{ + static int oldStip = -1; + if (stipple == oldStip) return; + oldStip = stipple; + GR_X_FLUSH_BATCH(); + if (stipple == 0 || stipple > grNumStipples) { + glDisable(GL_POLYGON_STIPPLE); + } else { + if (grOGLStipples[stipple] == (GLubyte *)NULL) MainExit(1); + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(grOGLStipples[stipple]); + } +} + + +/*--------------------------------------------------------- + * GrOGLInit: + * GrOGLInit initializes the graphics display and clears its screen. + * Files must have been previously opened with GrSetDisplay(); + * + * Results: TRUE if successful. + *--------------------------------------------------------- + */ + +bool +GrOGLInit() +{ + XVisualInfo *grVisualInfo; + static int attributeList[] = { GLX_RGBA, None, None }; + static char *OGLCMapType = "OpenGL"; + + grCMapType = OGLCMapType; + grDStyleType = OGLCMapType; + +#ifdef HAVE_PTHREADS + XInitThreads(); +#endif + + grXdpy = XOpenDisplay(NULL); + if (grXdpy == NULL) + { + TxError("Couldn't open display; check DISPLAY variable\n"); + return FALSE; + } + grXscrn = DefaultScreen(grXdpy); + grVisualInfo = glXChooseVisual(grXdpy, grXscrn, attributeList); + if (!grVisualInfo) + { + /* Try for a double-buffered configuration (added by Holger Vogt) */ + attributeList[1] = GLX_DOUBLEBUFFER; + grVisualInfo = glXChooseVisual(grXdpy, grXscrn, attributeList); + if (!grVisualInfo) + { + TxError("No suitable visual!\n"); + MainExit(1); + } + } + grXscrn = grVisualInfo->screen; + grVisual = grVisualInfo->visual; + oglCurrent.depth = grVisualInfo->depth; + + /* Note: The last parameter is GL_TRUE for direct rendering. */ + /* Direct rendering has a speedup advantange for raw rendering, but */ + /* disallows X11 operations such as XCopyArea, which prevents the */ + /* implementation of backing store and fast screen refreshes. So */ + /* we force an indirect rendering context through the X server. */ + + grXcontext = glXCreateContext(grXdpy, grVisualInfo, NULL, GL_FALSE); + + /* Basic GL parameters */ + + glLineWidth(1.0); + glShadeModel (GL_FLAT); + glPixelStorei(GL_PACK_LSB_FIRST, TRUE); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + HashInit(&grOGLWindowTable,8,HT_WORDKEYS); + + /* Globally-accessed variables */ + grNumBitPlanes = oglCurrent.depth; + grBitPlaneMask = (1 << oglCurrent.depth) - 1; + + if (grVisualInfo != NULL) XFree(grVisualInfo); + return groglPreLoadFont(); +} + +/*--------------------------------------------------------- + * GrOGLClose: + * + * Results: + * None. + * + * Side Effects: + * Helper process/thread killed. + *--------------------------------------------------------- + */ + +void +GrOGLClose() +{ + if (grXdpy == NULL) return; + TxDelete1InputDevice(pipeRead); + close(pipeRead); +#ifndef HAVE_PTHREADS + kill(Xhelper, SIGKILL); + do {} while (wait(0) != Xhelper); +#endif + XCloseDisplay(grXdpy); +#ifdef HAVE_PTHREADS + xloop_end(); +#endif +} + + +/*--------------------------------------------------------- + * GrOGLFlush: + * Flush output to display. + * + * Flushing is done automatically the next time input is read, + * so this procedure should not be used very often. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +GrOGLFlush() +{ + GR_X_FLUSH_BATCH(); + glFlush(); + glFinish(); +} + +/*------------------------------------------------------*/ +/* Translate event coordinate to window coordinate */ +/* (y is flipped relative to the window top) */ +/*------------------------------------------------------*/ + +#define glTransYs(n) (DisplayHeight(grXdpy, grXscrn)-(n)) + +/* +int +glTransYs(int wy) +{ + int my; + GLint vparms[4]; + + glGetIntegerv(GL_VIEWPORT, vparms); + my = vparms[3] - wy; + + return my; +} +*/ + +/* + *---------------------------------------------------------------------- + * Set the OpenGL viewport (projection matrix) for the current window + *---------------------------------------------------------------------- + */ +int +oglSetProjection(llx, lly, width, height) + int llx, lly, width, height; +{ + glXMakeCurrent(grXdpy, (GLXDrawable)oglCurrent.window, grXcontext); + +#ifndef OGL_SERVER_SIDE_ONLY + /* For batch-processing lines and rectangles */ + glEnableClientState(GL_VERTEX_ARRAY); +#endif + + /* Force draw to front buffer (in case of double-buffered config) */ + glDrawBuffer(GL_FRONT); /* added by Holger Vogt */ + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glViewport((GLsizei)llx, (GLsizei)lly, (GLsizei) width, (GLsizei) height); + + /* scale to fit window */ + +#ifdef OGL_INVERT_Y + glScalef(1.0 / (float)(width >> 1), -1.0 / (float)(height >> 1), 1.0); +#else + glScalef(1.0 / (float)(width >> 1), 1.0 / (float)(height >> 1), 1.0); +#endif + + /* magic origin maps to window center; move to window origin */ + + glTranslated(-(GLsizei)(width >> 1), -(GLsizei)(height >> 1), 0); +} + +/*----------------------------------------------------------------------*/ +/* pipehandler() is the callback set up by TxAdd1Input. The purpose is */ +/* to comply with magic's interrupt-driven protocol; magic blocks on */ +/* select() until an input arrives at a registered file descriptor, */ +/* then executes the callback associated with the fd, then checks to */ +/* see if the Tx event queue size grew. X11Handler passes info along */ +/* to X11Stdin() in the X11 version; that's because the X11 XtMainLoop */ +/* is a macro and can be re-implemented using XNextEvent() calls. */ +/*----------------------------------------------------------------------*/ + +void +pipehandler() +{ + TxInputEvent *event; + XEvent xevent; + HashEntry *entry; + MagWindow *mw; + + read(pipeRead, &xevent, sizeof(XEvent)); + + switch(xevent.type) { + case KeyPress: { /* Keyboard Callback Function */ + + int wx, wy, ky; + int key; + XKeyPressedEvent *KeyPressedEvent = (XKeyPressedEvent *) &xevent; + + entry = HashLookOnly(&grOGLWindowTable, KeyPressedEvent->window); + mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0; + + event = TxNewEvent(); + + read(pipeRead, &key, sizeof(int)); + + if (key == (int)'\015') key = (int)'\n'; /* Linefeed to Return */ + + event->txe_button = TX_CHARACTER; + event->txe_ch = key; + event->txe_buttonAction = TX_KEY_DOWN; + event->txe_p.p_x = KeyPressedEvent->x; + event->txe_p.p_y = glTransY(mw, KeyPressedEvent->y); + event->txe_wid = mw ? mw->w_wid : WIND_UNKNOWN_WINDOW; + TxAddEvent(event); + } break; + + case ButtonPress: + case ButtonRelease: { /* Mouse Callback Function */ + + XButtonEvent *ButtonEvent = (XButtonEvent *) &xevent; + + entry = HashLookOnly(&grOGLWindowTable, ButtonEvent->window); + mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0; + + event = TxNewEvent(); + switch (ButtonEvent->button) { + case Button1: + event->txe_button = TX_LEFT_BUTTON; + break; + case Button2: + event->txe_button = TX_MIDDLE_BUTTON; + break; + case Button3: + event->txe_button = TX_RIGHT_BUTTON; + break; + case Button4: + event->txe_button = TX_BUTTON_4; + break; + case Button5: + event->txe_button = TX_BUTTON_5; + break; + } + switch(ButtonEvent->type) { + case ButtonRelease: + event->txe_buttonAction = TX_BUTTON_UP; + break; + case ButtonPress: + event->txe_buttonAction = TX_BUTTON_DOWN; + break; + } + + event->txe_p.p_x = ButtonEvent->x; + event->txe_p.p_y = glTransY(mw, ButtonEvent->y); + event->txe_wid = mw ? mw->w_wid : WIND_UNKNOWN_WINDOW; + + TxAddEvent(event); + } break; + + case ConfigureNotify: { /* Reshape/Resize Callback Function */ + + XConfigureEvent *ConfigureEvent = (XConfigureEvent *) &xevent; + XEvent discard; + Rect screenRect; + int width, height; + + width = ConfigureEvent->width; + height = ConfigureEvent->height; + + entry = HashLookOnly(&grOGLWindowTable, ConfigureEvent->window); + mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0; + + screenRect.r_xbot = ConfigureEvent->x; + screenRect.r_xtop = ConfigureEvent->x + width; + screenRect.r_ybot = glTransYs(ConfigureEvent->y); + screenRect.r_ytop = glTransYs(ConfigureEvent->y + height); + + SigDisableInterrupts(); + + /* Redraw the window */ + + WindReframe(mw, &screenRect, FALSE, FALSE); + WindRedisplay(mw); + SigEnableInterrupts(); + + } break; + + case VisibilityNotify: { + XVisibilityEvent *VisEvent = (XVisibilityEvent*) &xevent; + + entry = HashLookOnly(&grOGLWindowTable, VisEvent->window); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + + switch(VisEvent->state) + { + case VisibilityUnobscured: + mw->w_flags &= ~WIND_OBSCURED; + if (mw->w_backingStore == (ClientData)NULL) + { + groglCreateBackingStore(mw); + if (mw->w_backingStore != (ClientData)NULL) + { + WindAreaChanged(mw, &mw->w_allArea); + WindUpdate(); + } + } + break; + case VisibilityPartiallyObscured: + case VisibilityFullyObscured: + mw->w_flags |= WIND_OBSCURED; + break; + } + } break; + + case Expose: { /* (Re)Display Callback Function */ + + Rect screenRect; + XEvent discard; + XExposeEvent *ExposeEvent = (XExposeEvent*) &xevent; + + entry = HashLookOnly(&grOGLWindowTable, ExposeEvent->window); + mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0; + + screenRect.r_xbot = ExposeEvent->x; + screenRect.r_xtop = ExposeEvent->x + ExposeEvent->width; + screenRect.r_ytop = mw->w_allArea.r_ytop - ExposeEvent->y; + screenRect.r_ybot = mw->w_allArea.r_ytop - + (ExposeEvent->y + ExposeEvent->height); + + if (mw->w_backingStore != (ClientData)NULL) + { + Rect surface; + (*GrGetBackingStorePtr)(mw, &screenRect); + WindScreenToSurface(mw, &screenRect, &surface); + DBWHLRedrawPrepWindow(mw, &surface); + WindDrawBorder(mw, &screenRect); + } + else + WindAreaChanged(mw, &screenRect); + WindUpdate(mw); + + } break; + + case CreateNotify: { + + XAnyEvent *AnyEvent = (XAnyEvent *) &xevent; + + entry = HashLookOnly(&grOGLWindowTable, AnyEvent->window); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + + SigDisableInterrupts(); + WindView(mw); + SigEnableInterrupts(); + } break; + } +} + +/*--------------------------------------------------------- + * oglSetDisplay: + * This routine sets the appropriate parameters so that + * Magic will work with glX. + * + * Results: success / fail + * + *--------------------------------------------------------- + */ + +bool +oglSetDisplay (dispType, outFileName, mouseFileName) + char *dispType; /* arguments not used by X */ + char *outFileName; + char *mouseFileName; +{ + int fildes[2], fildes2[2]; + char *planecount; + char *fullname; + FILE* f; + bool execFailed = FALSE; + + WindPackageType = WIND_X_WINDOWS; /* This works okay. */ + + grCursorType = "bw"; + + WindScrollBarWidth = 14; + + pipe(fildes); + pipe(fildes2); + pipeRead = fildes[0]; + pipeWrite = fildes2[1]; + + TxAdd1InputDevice(pipeRead, pipehandler, (ClientData) NULL); + +#ifdef HAVE_PTHREADS + writePipe = fildes[1]; + readPipe = fildes2[0]; +#else +#ifdef CYGWIN + f = PaOpen(X11HELP_PROG, "r", ".exe", + HELPER_PATH, (char *) NULL, &fullname); +#else + f = PaOpen(X11HELP_PROG, "r", (char *) NULL, + HELPER_PATH, (char *) NULL, &fullname); +#endif + if (f == NULL) { + int error; + TxError("Couldn't find helper process %s in search path \"%s\"\n", + X11HELP_PROG, HELPER_PATH); + error = 0; + write(fildes[1], &error, 4); + return FALSE; + } + else { + fclose(f); + } + + FORK(Xhelper); + if (Xhelper == 0) { /* Child process */ + char argv[2][100]; + + sprintf(argv[0], "%s", fullname); + sprintf(argv[1], "%d %d", fildes2[0],fildes[1]); + if (execl(argv[0], argv[0], argv[1], 0) != 0) + { + execFailed = TRUE; + TxError("Couldn't execute helper process \"%s\".\n", fullname); + TxFlush(); + /* we're the child process -- don't muck things up by returning */ + _exit(656); /* see vfork man page for reason for _exit() */ + } + }; + sleep(1); +#endif + + /* Set up the procedure values in the indirection table. */ + + GrPixelCorrect = 0; + + GrLockPtr = GrOGLLock; + GrUnlockPtr = GrOGLUnlock; + GrInitPtr = GrOGLInit; + GrClosePtr = GrOGLClose; + GrSetCMapPtr = GrOGLSetCMap; + + GrEnableTabletPtr = GrOGLEnableTablet; + GrDisableTabletPtr = GrOGLDisableTablet; + GrSetCursorPtr = GrOGLSetCursor; + GrTextSizePtr = GrOGLTextSize; + GrDrawGlyphPtr = GrOGLDrawGlyph; + GrReadPixelPtr = GrOGLReadPixel; + GrFlushPtr = GrOGLFlush; + + GrCreateWindowPtr = GrOGLCreate; + GrDeleteWindowPtr = GrOGLDelete; + GrConfigureWindowPtr = GrOGLConfigure; + GrOverWindowPtr = GrOGLRaise; + GrUnderWindowPtr = GrOGLLower; + GrUpdateIconPtr = GrOGLIconUpdate; + GrBitBltPtr = GrOGLBitBlt; + + GrFreeBackingStorePtr = groglFreeBackingStore; + GrCreateBackingStorePtr = groglCreateBackingStore; + GrGetBackingStorePtr = groglGetBackingStore; + GrPutBackingStorePtr = groglPutBackingStore; + GrScrollBackingStorePtr = groglScrollBackingStore; + + /* local indirections */ + grSetSPatternPtr = groglSetSPattern; + grPutTextPtr = groglPutText; +#ifdef VECTOR_FONTS + grFontTextPtr = groglFontText; +#endif + grDefineCursorPtr = groglDefineCursor; + grDrawGridPtr = groglDrawGrid; + grDrawLinePtr = groglDrawLine; + grSetWMandCPtr = groglSetWMandC; + grFillRectPtr = groglFillRect; + grSetStipplePtr = groglSetStipple; + grSetLineStylePtr = groglSetLineStyle; + grSetCharSizePtr = groglSetCharSize; + grFillPolygonPtr = groglFillPolygon; + + if (execFailed) { + TxError("Execution failed!\n"); + return FALSE; + } + + TxAdd1InputDevice(fileno(stdin), grOGLWStdin, (ClientData) NULL); + + if(!GrOGLInit()){ + return FALSE; + } + GrScreenRect.r_xbot = 0; + GrScreenRect.r_ybot = 0; + GrScreenRect.r_xtop = DisplayWidth(grXdpy,grXscrn); + GrScreenRect.r_ytop = DisplayHeight(grXdpy,grXscrn); + + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * grOGLWStdin -- + * Handle the stdin device for X window interface. + * + * Results: + * None. + * + * Side Effects: + * Adds events to the event queue. + * + * ---------------------------------------------------------------------------- + */ + /*ARGSUSED*/ + +void +grOGLWStdin(fd, cdata) + int fd; + ClientData cdata; +{ + int ch; + TxInputEvent *event; + + event = TxNewEvent(); + ch = getc(stdin); + if (ch == EOF) + event->txe_button = TX_EOF; + else + event->txe_button = TX_CHARACTER; + event->txe_ch = ch; + event->txe_buttonAction = 0; + event->txe_wid = WIND_NO_WINDOW; + event->txe_p.p_x = GR_CURSOR_X; + event->txe_p.p_y = GR_CURSOR_Y; + TxAddEvent(event); +} + + +/* + * ---------------------------------------------------------------------------- + * + * GrOGLCreate -- + * Create a new window under OpenGL + * Bind OpenGL window to Magic Window w. + * + * Results: + * Success/Fail + * + * Side Effects: + * Window created, window ID send to OGLhelper. + * + * ---------------------------------------------------------------------------- + */ + +bool +GrOGLCreate(w, name) + MagWindow *w; + char *name; +{ + Window wind; + HashEntry *entry; + static int firstWindow = 1; + XSizeHints *xsh; + char *windowplace; + char *option = (firstWindow)?"window":"newwindow"; + bool result = TRUE; + int x = w->w_frameArea.r_xbot; + int y = glTransYs(w->w_frameArea.r_ytop); + unsigned int width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; + unsigned int height = w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; + unsigned long attribmask = CWBackPixel | CWBorderPixel | CWColormap; + XSetWindowAttributes grAttributes; + XConfigureEvent xevent; + + WindSeparateRedisplay(w); + xsh = XAllocSizeHints(); + if (windowplace=XGetDefault(grXdpy,"magic",option)) { + XParseGeometry(windowplace,&x,&y,&width,&height); + w->w_frameArea.r_xbot = x; + w->w_frameArea.r_xtop = x+width; + w->w_frameArea.r_ytop = glTransYs(y); + w->w_frameArea.r_ybot = glTransYs(y+height); + WindReframe(w,&(w->w_frameArea),FALSE,FALSE); + xsh->flags = USPosition | USSize; + } + else { + xsh->flags = PPosition|PSize; + } + + grAttributes.colormap = XCreateColormap(grXdpy, RootWindow(grXdpy, grXscrn), + grVisual, AllocNone); + grAttributes.background_pixel = WhitePixel(grXdpy, grXscrn); + grAttributes.border_pixel = BlackPixel(grXdpy,grXscrn); + + if (wind = XCreateWindow(grXdpy, RootWindow(grXdpy, grXscrn), + x, y, width, height, 0, oglCurrent.depth, InputOutput, + grVisual, attribmask, &grAttributes)) { + xsh->x = w->w_frameArea.r_xbot; + xsh->y = glTransYs(w->w_frameArea.r_ytop); + xsh->width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; + xsh->height= w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; + XSetStandardProperties(grXdpy, wind, (name == NULL) ? "magic" : name, + "magic", None, 0, 0, xsh); + + XMapWindow(grXdpy, wind); + + oglCurrent.window = wind; + oglCurrent.mw = w; + glXMakeCurrent(grXdpy, (GLXDrawable)wind, grXcontext); + + w->w_grdata = (ClientData) wind; + entry = HashFind(&grOGLWindowTable, wind); + HashSetValue(entry,w); + XDefineCursor(grXdpy, wind, oglCurrent.cursor); + GrOGLIconUpdate(w, w->w_caption); + +#ifdef HAVE_PTHREADS + xloop_create(wind); +#else + XSync(grXdpy,0); + + write(pipeWrite, (char *) &wind, sizeof(Window)); + kill( Xhelper, SIGTERM); +#endif + + if (firstWindow) + { + firstWindow = 0; + result = groglLoadFont(); + } + + /* Force a StructureNotify event to get X11Helper to paint the window */ + usleep(600); + xevent.type = ConfigureNotify; + xevent.width = width; + xevent.height = height; + xevent.x = xsh->x; + xevent.y = xsh->y; + xevent.window = wind; + XSendEvent(grXdpy, wind, FALSE, StructureNotifyMask, (XEvent *)&xevent); + XFree(xsh); + return result; + } + else { + TxError("Could not open new X window\n"); + result = FALSE; + } + return result; +} + +/* + * ---------------------------------------------------------------------------- + * + * GrOGLDelete -- + * Destroy an X window. + * + * Results: + * None. + * + * Side effects: + * Window destroyed. + * + * ---------------------------------------------------------------------------- + */ + +void +GrOGLDelete(w) + MagWindow *w; +{ + int xw; + HashEntry *entry; + + xw = (Window) w->w_grdata; + entry = HashLookOnly(&grOGLWindowTable,xw); + HashSetValue(entry,NULL); + + XDestroyWindow(grXdpy, xw); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrOGLConfigure -- + * Full Screen function + * + * Results: + * None. + * + * Side Effects: + * Window reconfigured to w->w_frameArea. + * + * ---------------------------------------------------------------------------- + */ + +void +GrOGLConfigure(w) + MagWindow *w; +{ + XMoveResizeWindow(grXdpy,(Window) w->w_grdata, + w->w_frameArea.r_xbot, glTransYs(w->w_frameArea.r_ytop), + w->w_frameArea.r_xtop - w->w_frameArea.r_xbot, + w->w_frameArea.r_ytop - w->w_frameArea.r_ybot); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrOGLRaise -- + * Raise a window to the top of the screen such that nothing + * obscures it. + * + * Results: + * None. + * + * Side Effects: + * Window raised. + * + * ---------------------------------------------------------------------------- + */ + +void +GrOGLRaise(w) + MagWindow *w; +{ + XRaiseWindow(grXdpy, (Window) w->w_grdata ); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrOGLLower -- + * Lower a window below all other X windows. + * obscures it. + * + * Results: + * None. + * + * Side Effects: + * Window lowered. + * + * ---------------------------------------------------------------------------- + */ + +void +GrOGLLower(w) + MagWindow *w; +{ + XLowerWindow(grXdpy, (Window) w->w_grdata ); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrOGLLock -- + * Lock a window and set global variables "oglCurrent.window" + * and "oglCurrent.mw" to reference the locked window. + * + * Results: + * None. + * + * Side Effects: + * Window locked. + * + * ---------------------------------------------------------------------------- + */ + +void +GrOGLLock(w, flag) + MagWindow *w; + bool flag; +{ + grSimpleLock(w, flag); + if ( w != GR_LOCK_SCREEN ) + { + oglCurrent.mw = w; + oglCurrent.window = (Window) w->w_grdata; + + oglSetProjection(w->w_allArea.r_xbot, w->w_allArea.r_ybot, + w->w_allArea.r_xtop - w->w_allArea.r_xbot, + w->w_allArea.r_ytop - w->w_allArea.r_ybot); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * GrOGLUnlock -- + * Unlock a window, flushing stuff out to the display. + * + * Results: + * Display update. + * + * Side Effects: + * Window unlocked. + * + * ---------------------------------------------------------------------------- + */ + +void +GrOGLUnlock(w) + MagWindow *w; +{ + GrOGLFlush(); + grSimpleUnlock(w); +} + + +/* + *------------------------------------------------------------------------- + * + * GrOGLIconUpdate -- updates the icon text with the window script + * + * Results: none + * + * Side Effects: changes the icon text + * + *------------------------------------------------------------------------- + */ + +void +GrOGLIconUpdate(w,text) + MagWindow *w; + char *text; +{ + Window wind = (Window) w->w_grdata; + XClassHint class; + char *brack; + + if (w->w_grdata == (ClientData)NULL) return; + class.res_name = "magic"; + class.res_class = "magic"; + XSetClassHint( grXdpy, wind, &class); + + if (brack = strchr(text,'[')) + { + brack--; + *brack = 0; + XSetIconName(grXdpy,wind,text); + XStoreName(grXdpy,wind,text); + *brack = ' '; + return; + } + if (brack = strrchr(text,' ')) text = brack+1; + XSetIconName(grXdpy,wind,text); + XStoreName(grXdpy,wind,text); +} diff --git a/graphics/grOGL2.c b/graphics/grOGL2.c new file mode 100644 index 00000000..f94c938c --- /dev/null +++ b/graphics/grOGL2.c @@ -0,0 +1,217 @@ +/* grOGL2.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains additional functions to manipulate an X + * color display. Included here are rectangle drawing and color map + * loading. + */ + +#include +char *getenv(); + +#include +#include + +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/glyphs.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "grOGLInt.h" + +extern char *DBWStyleType; + + +/* GROGLSetCMap (pmap) + * + * OpenGL uses R,G,B values explicitly, so there is no + * need to install or record colors in a colormap. + * + * Results: None. + * + * Side Effects: None. + * + * Errors: None. + * + *--------------------------------------------------------- + */ + +void +GrOGLSetCMap () +{ +} + +Rect groglLines[OGL_BATCH_SIZE]; +int groglNbLines=0; +OGLRect groglRects[OGL_BATCH_SIZE]; +int groglNbRects=0; + +/*--------------------------------------------------------- + * groglDrawLines: + * This routine draws a batch of lines. + * + * Results: None. + * + * Side Effects: + * Draw a bunch of lines. + *--------------------------------------------------------- + */ + +void +groglDrawLines(lines, nb) + Rect lines[]; + int nb; +{ + int i; + +#ifdef OGL_SERVER_SIDE_ONLY + + glBegin(GL_LINES); + for (i = 0; i < nb; i++){ + glVertex2i(lines[i].r_ll.p_x, lines[i].r_ll.p_y); + glVertex2i(lines[i].r_ur.p_x, lines[i].r_ur.p_y); + } + glEnd(); + +#else + + glVertexPointer(2, GL_INT, 0, (GLvoid *)lines); + /* use (nb << 1) because there are 2 vertices per line */ + glDrawArrays(GL_LINES, 0, nb << 1); + +#endif +} + +/*--------------------------------------------------------- + * groglDrawLine: + * This routine queues a line for batch drawing. + * The batch drawing is much faster than repeated calls + * to glBegin() and glEnd(). + * + * Results: None. + * + * Side Effects: + * Draw a line for (x1, y1) to (x2, y2) inclusive. + *--------------------------------------------------------- + */ + +void +groglDrawLine (x1, y1, x2, y2) + int x1, y1; /* Screen coordinates of first point. */ + int x2, y2; /* Screen coordinates of second point. */ +{ + if (groglNbLines == OGL_BATCH_SIZE) GR_X_FLUSH_LINES(); + groglLines[groglNbLines].r_ll.p_x = x1; + groglLines[groglNbLines].r_ll.p_y = y1; + groglLines[groglNbLines].r_ur.p_x = x2; + groglLines[groglNbLines].r_ur.p_y = y2; + groglNbLines++; +} + + +/*--------------------------------------------------------- + * groglFillRects: + * This routine draws a bunch of solid rectangles. + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +groglFillRects(rects, nb) + OGLRect rects[]; + int nb; +{ + int i; + +#ifdef OGL_SERVER_SIDE_ONLY + + for (i = 0; i < nb; i++) + glRecti(rects[i].r_ll.p_x, rects[i].r_ll.p_y, + rects[i].r_ur.p_x, rects[i].r_ur.p_y); + +#else + + glVertexPointer(2, GL_INT, 0, (GLvoid *)rects); + /* Use (nb << 2) because there are 4 vertices per rect */ + glDrawArrays(GL_QUADS, 0, nb << 2); + +#endif +} + +/*--------------------------------------------------------- + * groglFillRect: + * This routine queues a solid rectangle for batch drawing. + * + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +groglFillRect(r) + Rect *r; /* Address of a rectangle in screen + * coordinates. + */ +{ + if (groglNbRects == OGL_BATCH_SIZE) GR_X_FLUSH_RECTS(); + groglRects[groglNbRects].r_ll.p_x = r->r_ll.p_x; + groglRects[groglNbRects].r_ll.p_y = r->r_ll.p_y; + + groglRects[groglNbRects].r_ur.p_x = r->r_ur.p_x; + groglRects[groglNbRects].r_ur.p_y = r->r_ur.p_y; + +#ifndef OGL_SERVER_SIDE_ONLY + groglRects[groglNbRects].r_ul.p_x = r->r_ll.p_x; + groglRects[groglNbRects].r_ul.p_y = r->r_ur.p_y; + + groglRects[groglNbRects].r_lr.p_x = r->r_ur.p_x; + groglRects[groglNbRects].r_lr.p_y = r->r_ll.p_y; +#endif + + groglNbRects++; +} + +/*--------------------------------------------------------- + * groglFillPolygon: + * This routine draws a solid polygon + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +groglFillPolygon(tp, np) + Point *tp; + int np; +{ + int i; + + glBegin(GL_POLYGON); + for (i = 0; i < np; i++) + glVertex2i(tp[i].p_x, tp[i].p_y); + glEnd(); +} + diff --git a/graphics/grOGL3.c b/graphics/grOGL3.c new file mode 100644 index 00000000..0fa0af08 --- /dev/null +++ b/graphics/grOGL3.c @@ -0,0 +1,843 @@ +/* grOGL3.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains additional functions to manipulate an X window system + * color display. Included here are device-dependent routines to draw and + * erase text and draw a grid. + * + */ + +#include +#include + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "textio/textio.h" +#include "utils/signals.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "dbwind/dbwind.h" +#include "database/fonts.h" +#include "grOGLInt.h" + +extern Display *grXdpy; + +static XFontStruct *grXFonts[4]; +#define grSmallFont grXFonts[0] +#define grMediumFont grXFonts[1] +#define grLargeFont grXFonts[2] +#define grXLargeFont grXFonts[3] +GLuint grXBases[4]; + + + +/*--------------------------------------------------------- + * groglDrawGrid: + * groglDrawGrid adds a grid to the grid layer, using the current + * write mask and color. + * + * Results: + * TRUE is returned normally. However, if the grid gets too small + * to be useful, then nothing is drawn and FALSE is returned. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +bool +groglDrawGrid (prect, outline, clip) + Rect *prect; /* A rectangle that forms the template + * for the grid. Note: in order to maintain + * precision for the grid, the rectangle + * coordinates are specified in units of + * screen coordinates multiplied by SUBPIXEL. + */ + int outline; /* the outline style */ + Rect *clip; /* a clipping rectangle */ +{ + int xsize, ysize; + int x, y; + int xstart, ystart; + int snum, low, hi, shifted; + + xsize = prect->r_xtop - prect->r_xbot; + ysize = prect->r_ytop - prect->r_ybot; + if (!xsize || !ysize) + return FALSE; + if (GRID_TOO_SMALL(xsize, ysize)) + return FALSE; + + xstart = prect->r_xbot % xsize; + while (xstart < clip->r_xbot << SUBPIXELBITS) xstart += xsize; + ystart = prect->r_ybot % ysize; + while (ystart < clip->r_ybot << SUBPIXELBITS) ystart += ysize; + + groglSetLineStyle(outline); + + glBegin(GL_LINES); + + snum = 0; + low = clip->r_ybot; + hi = clip->r_ytop; + for (x = xstart; x < (clip->r_xtop + 1) << SUBPIXELBITS; x += xsize) + { + shifted = x >> SUBPIXELBITS; + glVertex2i(shifted, low); + glVertex2i(shifted, hi); + snum++; + } + + snum = 0; + low = clip->r_xbot; + hi = clip->r_xtop; + for (y = ystart; y < (clip->r_ytop + 1) << SUBPIXELBITS; y += ysize) + { + shifted = y >> SUBPIXELBITS; + glVertex2i(low, shifted); + glVertex2i(hi, shifted); + snum++; + } + + glEnd(); + return TRUE; +} + + +/*--------------------------------------------------------- + * groglPreLoadFont + * This local routine loads the X fonts used by Magic. + * At this time, we need the font information to size + * the window (making room for the title at the top), + * but with no rendering context set (no window to + * draw to) we defer transferring the font bitmaps to + * OpenGL display lists until later. + * + * Results: Success/Fail + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +bool +groglPreLoadFont() +{ + XFontStruct *fontInfo; + int i; + char *s; + char *unable = "Unable to load font"; + + static char *fontnames[4] = { + X_FONT_SMALL, + X_FONT_MEDIUM, + X_FONT_LARGE, + X_FONT_XLARGE }; + static char *optionnames[4] = { + "small", + "medium", + "large", + "xlarge"}; + + for (i = 0; i < 4; i++) { + s = XGetDefault(grXdpy,"magic",optionnames[i]); + if (s) fontnames[i] = s; + if ((fontInfo = XLoadQueryFont(grXdpy, fontnames[i])) == NULL) { + TxError("%s %s\n",unable,fontnames[i]); + if ((grXFonts[i]= XLoadQueryFont(grXdpy,GR_DEFAULT_FONT))==NULL) { + TxError("%s %s\n",unable,GR_DEFAULT_FONT); + return FALSE; + } + } + grXFonts[i] = fontInfo; + } + return TRUE; +} + + +/*--------------------------------------------------------- + * groglLoadFont + * This local routine transfers the X font bitmaps + * into OpenGL display lists for simple text + * rendering. + * + * Results: Success/Fail. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +bool +groglLoadFont() +{ + XFontStruct *fontInfo; + Font id; + unsigned int first, last, i; + + for (i = 0; i < 4; i++) { + fontInfo = grXFonts[i]; + id = fontInfo->fid; + first = fontInfo->min_char_or_byte2; + last = fontInfo->max_char_or_byte2; + + grXBases[i] = glGenLists(last+1); + if (grXBases[i] == 0) { + TxError("Out of display lists!\n"); + return FALSE; + } + glXUseXFont(id, first, last-first+1, grXBases[i]+first); + } + return TRUE; +} + + +/*--------------------------------------------------------- + * groglSetCharSize: + * This local routine sets the character size in the display, + * if necessary. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +groglSetCharSize (size) + int size; /* Width of characters */ +{ + oglCurrent.fontSize = size; + + switch (size) { + case GR_TEXT_DEFAULT: + case GR_TEXT_SMALL: + oglCurrent.font = grSmallFont; + break; + case GR_TEXT_MEDIUM: + oglCurrent.font = grMediumFont; + break; + case GR_TEXT_LARGE: + oglCurrent.font = grLargeFont; + break; + case GR_TEXT_XLARGE: + oglCurrent.font = grXLargeFont; + break; + default: + TxError("%s%d\n", "groglSetCharSize: Unknown character size ", + size ); + break; + break; + } +} + + +/* + * ---------------------------------------------------------------------------- + * GrOGLTextSize -- + * + * Determine the size of a text string. + * + * Results: + * None. + * + * Side effects: + * A rectangle is filled in that is the size of the text in pixels. + * The origin (0, 0) of this rectangle is located on the baseline + * at the far left side of the string. + * ---------------------------------------------------------------------------- + */ + +void +GrOGLTextSize(text, size, r) + char *text; + int size; + Rect *r; +{ + XCharStruct overall; + XFontStruct *font; + int dir,fa,fd; + + switch (size) { + case GR_TEXT_DEFAULT: + case GR_TEXT_SMALL: + font = grSmallFont; + break; + case GR_TEXT_MEDIUM: + font = grMediumFont; + break; + case GR_TEXT_LARGE: + font = grLargeFont; + break; + case GR_TEXT_XLARGE: + font = grXLargeFont; + break; + default: + TxError("%s%d\n", "GrOGLTextSize: Unknown character size ", + size ); + break; + } + if (font == NULL) return; + XTextExtents(font, text, strlen(text), &dir, &fa, &fd, &overall); + + r->r_ytop = overall.ascent; + r->r_ybot = -overall.descent; + r->r_xtop = overall.width - overall.lbearing; + r->r_xbot = -overall.lbearing - 1; +} + + +/* + * ---------------------------------------------------------------------------- + * GrOGLReadPixel -- + * + * Read one pixel from the screen. + * + * Results: + * An integer containing the pixel's color. + * (Except OpenGL has no such function, so we just return 0) + * + * Side effects: + * none. + * + * ---------------------------------------------------------------------------- + */ + +int +GrOGLReadPixel (w, x, y) + MagWindow *w; + int x,y; /* the location of a pixel in screen coords */ +{ + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * GrOGLBitBlt -- + * + * Copy information from one part of the screen to the other. + * + * Results: + * None. + * + * Side effects: + * changes the screen. + * ---------------------------------------------------------------------------- + */ + +void +GrOGLBitBlt(r, p) + Rect *r; + Point *p; +{ + glCopyPixels(r->r_xbot, r->r_ybot, r->r_xtop - r->r_xbot + 1, + r->r_ytop - r->r_ybot + 1, GL_COLOR); +} + +#ifdef VECTOR_FONTS + +/* + *---------------------------------------------------------------------- + * + * Technically, there should be no self-intersecting polygons in outline + * fonts. However, decomposition of bezier curves into line segments + * may occasionally produce one, so it needs to be handled. + *---------------------------------------------------------------------- + */ + +void +myCombine(GLdouble coords[3], GLdouble *vertex_data[4], + GLfloat weight[4], GLdouble **outData, void *dataptr) +{ + /* This needs to be free'd at the end of gluTessEndPolygon()! */ + GLdouble *new = (GLdouble *)mallocMagic(2 * sizeof(GLdouble)); + new[0] = coords[0]; + new[1] = coords[1]; + *outData = new; + /* Diagnostic */ + TxError("Intersecting polygon in char \"%c\" at %g %g!\n", + *((char *)dataptr), coords[0], coords[1]); +} + +/* + *---------------------------------------------------------------------- + * Draw a text character + * This routine differs from grtoglFillPolygon() in that it uses the + * glu library to handle non-convex polygons as may appear in font + * outlines. + *---------------------------------------------------------------------- + */ + +void +groglDrawCharacter(clist, tc, pixsize) + FontChar *clist; + unsigned char tc; + int pixsize; +{ + Point *tp; + int np, nptotal; + int i, j; + static GLUtesselator *tess = NULL; + static GLdouble *v = NULL; + static int maxnp = 0; + FontChar *ccur; + + if (pixsize < 5) return; /* Label too small to be useful */ + + if (tess == NULL) + { + tess = gluNewTess(); + gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin); + gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv); + gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)glEnd); + gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)myCombine); + } + // Boundary-only does not look particularly good. . . + gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE); + + nptotal = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + nptotal += ccur->fc_numpoints; + + if (nptotal > maxnp) + { + if (v != NULL) freeMagic((char *)v); + maxnp = nptotal; + v = (GLdouble *)mallocMagic(nptotal * 3 * sizeof(GLdouble)); + } + + j = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + { + tp = ccur->fc_points; + np = ccur->fc_numpoints; + + for (i = 0; i < np; i++, j += 3) { + v[j] = tp[i].p_x; + v[j + 1] = tp[i].p_y; + v[j + 2] = 0; + } + } + + gluTessBeginPolygon(tess, (GLvoid *)(&tc)); + j = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + { + np = ccur->fc_numpoints; + gluTessBeginContour(tess); + for (i = 0; i < np; i++, j += 3) { + gluTessVertex(tess, &v[j], &v[j]); + } + gluTessEndContour(tess); + } + gluTessEndPolygon(tess); +} + +/*--------------------------------------------------------- + * groglFontText: + * + * This routine draws text from font vectors using the + * font vector routines in DBlabel.c. Text is clipped + * to the clipping rectangle. + * + * For speed, we should be transferring the font + * vectors into OpenGL display lists! + * + *--------------------------------------------------------- + */ + +void +groglFontText(text, font, size, rotate, pos, clip, obscure) + char *text; /* The text to be drawn */ + int font; /* Font to use from fontList */ + int size; /* Pixel size of the font */ + int rotate; /* Text rotation */ + Point *pos; /* Text base position */ + Rect *clip; /* Clipping area */ + LinkedRect *obscure; /* List of obscuring areas */ +{ + char *tptr; + Point *coffset; /* vector to next character */ + Rect *cbbox; + GLfloat fsize, matvals[16]; + FontChar *clist; + int cheight, baseline; + float tmp; + + /* Keep it simple for now---ignore clip and obscure */ + + glDisable(GL_BLEND); + glPushMatrix(); + glTranslated(pos->p_x, pos->p_y, 0); + glRotated(rotate, 0, 0, 1); + + /* Get label size */ + cbbox = &DBFontList[font]->mf_extents; + + fsize = (GLfloat)size / (GLfloat)cbbox->r_ytop; + glScalef(fsize, fsize, 1.0); + + /* Adjust to baseline */ + baseline = 0; + for (tptr = text; *tptr != '\0'; tptr++) + { + DBFontChar(font, *tptr, NULL, NULL, &cbbox); + if (cbbox->r_ybot < baseline) + baseline = cbbox->r_ybot; + } + glTranslated(0, -baseline, 0); + + for (tptr = text; *tptr != '\0'; tptr++) + { + DBFontChar(font, *tptr, &clist, &coffset, NULL); + groglDrawCharacter(clist, *tptr, size); + glTranslated(coffset->p_x, coffset->p_y, 0); + } + glPopMatrix(); +} + +#endif /* VECTOR_FONTS */ + +static GC grXcopyGC = (GC)NULL; + +/* + * ---------------------------------------------------------------------------- + * groglFreeBackingStore -- + * Free up Pixmap memory for a backing store cell. + * + * Results: + * None. + * + * Side effects: + * memory Free'd + * ---------------------------------------------------------------------------- + */ + +void +groglFreeBackingStore(MagWindow *window) +{ + Pixmap pmap = (Pixmap)window->w_backingStore; + if (pmap == (Pixmap)NULL) return; + XFreePixmap(grXdpy, pmap); + window->w_backingStore = (ClientData)NULL; + /* XFreeGC(grXdpy, grXcopyGC); */ + /* TxPrintf("groglFreeBackingStore called\n"); */ +} + +/* + * ---------------------------------------------------------------------------- + * groglCreateBackingStore -- + * Create Pixmap memory for a backing store cell and copy data + * from the window into it. + * + * Results: + * None. + * + * Side effects: + * memory Allocated. + * + * ---------------------------------------------------------------------------- + */ + +void +groglCreateBackingStore(MagWindow *w) +{ + Pixmap pmap; + Window wind = (Window)w->w_grdata; + unsigned int width, height; + GC gc; + XGCValues gcValues; + + /* ignore for all windows except layout */ + if (w->w_client != DBWclientID) return; + + /* deferred */ + if (w->w_grdata == (Window)NULL) return; + + width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + + if (w->w_backingStore != (ClientData)NULL) groglFreeBackingStore(w); + + if (grXcopyGC == (GC)NULL) + { + gcValues.graphics_exposures = FALSE; + grXcopyGC = XCreateGC(grXdpy, wind, GCGraphicsExposures, &gcValues); + } + + pmap = XCreatePixmap(grXdpy, wind, width, height, oglCurrent.depth); + w->w_backingStore = (ClientData)pmap; + + /* TxPrintf("groglCreateBackingStore area %d %d %d %d\n", + w->w_screenArea.r_xbot, w->w_screenArea.r_ybot, + w->w_screenArea.r_xtop, w->w_screenArea.r_ytop); */ +} + +/* + * ---------------------------------------------------------------------------- + * groglGetBackingStore -- + * Copy data from a backing store Pixmap into the indicated window. + * + * Results: + * TRUE if backing store was copied successfully, FALSE if not. + * + * Side effects: + * Data copied into Pixmap memory. + * + * ---------------------------------------------------------------------------- + */ + +bool +groglGetBackingStore(MagWindow *w, Rect *area) +{ + Pixmap pmap; + Window wind = (Window)w->w_grdata; + unsigned int width, height; + int ybot; + int xoff, yoff; + Rect r; + + pmap = (Pixmap)w->w_backingStore; + if (pmap == (Pixmap)NULL) + return FALSE; + + /* Make a local copy of area so we don't disturb the original */ + r = *area; + GeoClip(&r, &(w->w_screenArea)); + + width = r.r_xtop - r.r_xbot; + height = r.r_ytop - r.r_ybot; + ybot = glTransY(w, r.r_ytop); + + xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot; + yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop; + + XCopyArea(grXdpy, pmap, wind, grXcopyGC, r.r_xbot - xoff, ybot - yoff, + width, height, r.r_xbot, ybot); + + /* TxPrintf("groglGetBackingStore %d %d %d %d\n", + r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop); */ + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * groglScrollBackingStore -- + * Enable fast scrolling by shifting part of the backing store + * from one position to another, with the amount of shift indicated + * by the X and/or Y value of the indicated point. + * + * Results: + * TRUE on success, FALSE on failure. + * + * Side effects: + * Data shifted in Pixmap memory. + * + * ---------------------------------------------------------------------------- + */ + +bool +groglScrollBackingStore(MagWindow *w, Point *shift) +{ + Pixmap pmap; + unsigned int width, height; + int xorigin, yorigin, xshift, yshift; + + pmap = (Pixmap)w->w_backingStore; + if (pmap == (Pixmap)NULL) + { + TxPrintf("groglScrollBackingStore %d %d failure\n", + shift->p_x, shift->p_y); + return FALSE; + } + + width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + xorigin = 0; + yorigin = 0; + xshift = shift->p_x; + yshift = -shift->p_y; + + if (xshift > 0) + width -= xshift; + else if (xshift < 0) + { + width += xshift; + xorigin = -xshift; + xshift = 0; + } + if (yshift > 0) + height -= yshift; + else if (yshift < 0) + { + height += yshift; + yorigin = -yshift; + yshift = 0; + } + + XCopyArea(grXdpy, pmap, pmap, grXcopyGC, xorigin, yorigin, width, height, + xshift, yshift); + + /* TxPrintf("groglScrollBackingStore %d %d\n", shift->p_x, shift->p_y); */ + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * groglPutBackingStore -- + * Copy data from the window into backing store. + * + * Results: + * None. + * + * Side effects: + * Graphics drawing into the window. + * ---------------------------------------------------------------------------- + */ + +void +groglPutBackingStore(MagWindow *w, Rect *area) +{ + Pixmap pmap = (Pixmap)w->w_backingStore; + Window wind = (Window)w->w_grdata; + unsigned int width, height; + int ybot, xoff, yoff; + + if (pmap == (Pixmap)NULL) return; + + /* Attempting to write backing store into an obscured */ + /* window (which we keep track of with Visibility events) */ + /* causes backing store to be invalid. */ + + if (w->w_flags & WIND_OBSCURED) + { + groglFreeBackingStore(w); + w->w_backingStore = (ClientData)NULL; + return; + } + + width = area->r_xtop - area->r_xbot; + height = area->r_ytop - area->r_ybot; + ybot = glTransY(w, area->r_ytop); + + xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot; + yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop; + + XCopyArea(grXdpy, wind, pmap, grXcopyGC, area->r_xbot, ybot, + width, height, area->r_xbot - xoff, ybot - yoff); + + /* TxPrintf("groglPutBackingStore %d %d %d %d\n", + area->r_xbot, area->r_ybot, area->r_xtop, area->r_ytop); */ +} + + +/*--------------------------------------------------------- + * groglPutText: + * (modified on SunPutText) + * + * This routine puts a chunk of text on the screen in the current + * color, size, etc. The caller must ensure that it fits on + * the screen -- no clipping is done except to the obscuring rectangle + * list and the clip rectangle. + * + * Results: + * none. + * + * Side Effects: + * The text is drawn on the screen. + * + *--------------------------------------------------------- + */ + +void +groglPutText (text, pos, clip, obscure) + char *text; /* The text to be drawn. */ + Point *pos; /* A point located at the leftmost point of + * the baseline for this string. + */ + Rect *clip; /* A rectangle to clip against */ + LinkedRect *obscure; /* A list of obscuring rectangles */ + +{ + Rect location; + Rect overlap; + Rect textrect; + LinkedRect *ob; + void grOGLGeoSub(); + int i; + float tscale; + + GrOGLTextSize(text, oglCurrent.fontSize, &textrect); + + location.r_xbot = pos->p_x + textrect.r_xbot; + location.r_xtop = pos->p_x + textrect.r_xtop; + location.r_ybot = pos->p_y + textrect.r_ybot; + location.r_ytop = pos->p_y + textrect.r_ytop; + + /* erase parts of the bitmap that are obscured */ + for (ob = obscure; ob != NULL; ob = ob->r_next) + { + if (GEO_TOUCH(&ob->r_r, &location)) + { + overlap = location; + GeoClip(&overlap, &ob->r_r); + grOGLGeoSub(&location, &overlap); + } + } + + overlap = location; + GeoClip(&overlap, clip); + + /* copy the text to the color screen */ + if ((overlap.r_xbot < overlap.r_xtop)&&(overlap.r_ybot <= overlap.r_ytop)) + { + glScissor(overlap.r_xbot, overlap.r_ybot, overlap.r_xtop - overlap.r_xbot, + overlap.r_ytop - overlap.r_ybot); + glEnable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + glRasterPos2i(pos->p_x, pos->p_y); + glListBase(grXBases[(oglCurrent.fontSize == GR_TEXT_DEFAULT) ? + GR_TEXT_SMALL : oglCurrent.fontSize]); + glCallLists(strlen(text), GL_UNSIGNED_BYTE, (unsigned char *)text); + glDisable(GL_SCISSOR_TEST); + } +} + + +/* grOGLGeoSub: + * return the tallest sub-rectangle of r not obscured by area + * area must be within r. + */ + +void +grOGLGeoSub(r, area) +Rect *r; /* Rectangle to be subtracted from. */ +Rect *area; /* Area to be subtracted. */ + +{ + if (r->r_xbot == area->r_xbot) r->r_xbot = area->r_xtop; + else + if (r->r_xtop == area->r_xtop) r->r_xtop = area->r_xbot; + else + if (r->r_ybot <= area->r_ybot) r->r_ybot = area->r_ytop; + else + if (r->r_ytop == area->r_ytop) r->r_ytop = area->r_ybot; + else + r->r_xtop = area->r_xbot; +} diff --git a/graphics/grOGL4.c b/graphics/grOGL4.c new file mode 100644 index 00000000..c50c729b --- /dev/null +++ b/graphics/grOGL4.c @@ -0,0 +1,138 @@ +/* grOGL4.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains functions to manage the graphics tablet associated + * with the X display. + * + */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/magsgtty.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "textio/txcommands.h" +#include "grOGLInt.h" + +extern Display *grXdpy; +extern int *grXscrn; + + +/*--------------------------------------------------------- + * GrOGLDisableTablet: + * Turns off the cursor. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +GrOGLDisableTablet() +{ +} + + +/*--------------------------------------------------------- + * GrOGLEnableTablet: + * This routine enables the graphics tablet. + * + * Results: + * None. + * + * Side Effects: + * Simply turn on the crosshair. + *--------------------------------------------------------- + */ + +void +GrOGLEnableTablet() +{ +} + + +/* + * ---------------------------------------------------------------------------- + * groglGetCursorPos: + * Read the cursor position in magic coordinates. + * + * Results: + * TRUE is returned if the coordinates were succesfully read, FALSE + * otherwise. + * + * Side effects: + * The parameter is filled in with the cursor position, in the form of + * a point in screen coordinates. + * ---------------------------------------------------------------------------- + */ + +bool +groglGetCursorPos (mw, p) + MagWindow *mw; + Point *p; /* point to be filled in with screen coordinates */ +{ + int x, y, x1, y1; + unsigned int buttons; + Window win1, win2; + + if (mw == (MagWindow *)NULL) mw = oglCurrent.mw; + + XQueryPointer(grXdpy, (Window)mw->w_grdata, + &win1, &win2, &x1, &y1, + &x, &y, &buttons); + p->p_x = x; + p->p_y = glTransY(oglCurrent.mw, y); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * groglGetCursorRootPos: + * Read the cursor position in screen root coordinates + * + * Results: + * TRUE is returned if the coordinates were succesfully read, FALSE + * otherwise. + * + * Side effects: + * The parameter is filled in with the cursor position, in the form of + * a point in screen coordinates. + * ---------------------------------------------------------------------------- + */ + +bool +groglGetCursorRootPos (mw, p) + MagWindow *mw; + Point *p; /* point to be filled in with root coordinates */ +{ + int x, y, x1, y1; + unsigned int buttons; + Window win1, win2; + + if (mw == (MagWindow *)NULL) mw = oglCurrent.mw; + + XQueryPointer(grXdpy, (Window)mw->w_grdata, + &win1, &win2, &x1, &y1, + &x, &y, &buttons); + p->p_x = x1; + p->p_y = y1; + return TRUE; +} diff --git a/graphics/grOGL5.c b/graphics/grOGL5.c new file mode 100644 index 00000000..71d315c8 --- /dev/null +++ b/graphics/grOGL5.c @@ -0,0 +1,324 @@ +/* grOGL5.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * Manipulate the programable cursor on the graphics display. + * + */ + +#include + +#include +#include + +#include "utils/magic.h" +#include "utils/styles.h" +#include "utils/hash.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/graphics.h" +#include "graphics/glyphs.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "grOGLInt.h" + +extern HashTable grOGLWindowTable; +extern Display *grXdpy; +extern int grXscrn; + +Cursor grCursors[MAX_CURSORS]; + + +/* + * ---------------------------------------------------------------------------- + * GrOGLDrawGlyph -- + * + * Draw one glyph on the display. + * + * Results: + * None. + * + * Side effects: + * Draws pixels. + * ---------------------------------------------------------------------------- + */ + +void +GrOGLDrawGlyph (gl, p) + GrGlyph *gl; /* A single glyph */ + Point *p; /* screen pos of lower left corner */ +{ + Rect bBox; + bool anyObscure; + LinkedRect *ob; + + GR_CHECK_LOCK(); + + /* We're going to change the graphics state without affecting */ + /* the standard color and mask saved values, so we had better */ + /* flush all rects & lines first. */ + GR_X_FLUSH_BATCH(); + + bBox.r_ll = *p; + bBox.r_xtop = p->p_x + gl->gr_xsize - 1; + bBox.r_ytop = p->p_y + gl->gr_ysize - 1; + + anyObscure = FALSE; + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) { + if (GEO_TOUCH( &(ob->r_r), &bBox)) { + anyObscure = TRUE; + break; + } + } + + if ((!anyObscure) && (GEO_SURROUND(&grCurClip, &bBox)) ) { + int *pixelp, x, y; + + /* no clipping, try to go quickly */ + pixelp = gl->gr_pixels; + for (y = 0; y < gl->gr_ysize; y++) { + int x1, y1; + + y1 = bBox.r_ybot + y; + for (x = 0; x < gl->gr_xsize; x++) { + int color, red, green, blue, mask; + if (*pixelp != 0) { + mask = GrStyleTable[*pixelp].color << 1; + color = GrStyleTable[*pixelp].color; + x1 = bBox.r_xbot + x; + GrGetColor(color, &red, &green, &blue); + glColor4ub((GLubyte)red, (GLubyte)green, (GLubyte)blue, + (GLubyte)mask); + glBegin(GL_POINTS); + glVertex2i((GLint)x1, (GLint)y1); + glEnd(); + } + pixelp++; + } + } + } else { + /* do pixel by pixel clipping */ + int y, yloc; + + yloc = bBox.r_ybot; + for (y = 0; y < gl->gr_ysize; y++) { + int startx, endx; + if ( (yloc <= grCurClip.r_ytop) && (yloc >= grCurClip.r_ybot) ) { + int laststartx; + laststartx = bBox.r_xbot - 1; + for (startx = bBox.r_xbot; startx <= bBox.r_xtop; + startx = endx + 1) { + int *pixelp; + + startx = MAX(startx, grCurClip.r_xbot); + endx = MIN(bBox.r_xtop, grCurClip.r_xtop); + + if (anyObscure) { + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) { + if ( (ob->r_r.r_ybot <= yloc) && + (ob->r_r.r_ytop >= yloc) ) { + if (ob->r_r.r_xbot <= startx) + startx = MAX(startx, ob->r_r.r_xtop + 1); + else if (ob->r_r.r_xbot <= endx) + endx = MIN(endx, ob->r_r.r_xbot - 1); + } + } + } + + /* stop if we aren't advancing */ + if (startx == laststartx) break; + laststartx = startx; + if (startx > endx) continue; + + /* draw a section of this scan line */ + pixelp = &( gl->gr_pixels[y*gl->gr_xsize + + (startx - bBox.r_xbot)]); + for ( ; startx <= endx; startx++) { + int color, red, green, blue, mask; + if (*pixelp != 0) { + mask = GrStyleTable[*pixelp].mask << 1; + color = GrStyleTable[*pixelp].color; + GrGetColor(color, &red, &green, &blue); + glColor4ub((GLubyte)red, (GLubyte)green, + (GLubyte)blue, (GLubyte)mask); + glBegin(GL_POINTS); + glVertex2i((GLint)startx, (GLint)yloc); + glEnd(); + } + pixelp++; + } + startx = endx + 1; + } + } + yloc++; + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * groglDefineCursor: + * + * Use X cursors on top of the OpenGL window + * + * Results: + * None. + * + * Side effects: + * The given matrix is stored in the graphics display, and it can be + * used as the cursor by calling GrSetCursor. + * ---------------------------------------------------------------------------- + */ + +void +groglDefineCursor(glyphs) + GrGlyphs *glyphs; +{ + int glyphnum; + Rect oldClip; + int red, green, blue; + Pixmap source,mask; + XColor curcolor; + + + if (glyphs->gr_num <= 0) return; + + if (glyphs->gr_num > MAX_CURSORS) + { + TxError("X only has room for %d cursors\n", MAX_CURSORS); + return; + } + + /* expand clipping amount for off-screen access on the X */ + GrLock(GR_LOCK_SCREEN, FALSE); + oldClip = grCurClip; + grCurClip = GrScreenRect; + grCurClip.r_ytop += 16; + + /* what color should the cursor be? The following makes it the + opposite of what the background "mostly" is. + */ + GrGetColor(GrStyleTable[STYLE_TRANSPARENT].color, &red, &green, &blue); + + if (red + green + blue > 0x180) /* (0x180 = 128 * 3) */ + { + curcolor.pixel = BlackPixel(grXdpy,grXscrn); + curcolor.red = 0; + curcolor.green = 0; + curcolor.blue = 0; + curcolor.flags |= DoRed|DoGreen|DoBlue; + } + else + { + curcolor.pixel = WhitePixel(grXdpy,grXscrn); + curcolor.red = 65535; + curcolor.green = 65535; + curcolor.blue = 65535; + curcolor.flags |= DoRed|DoGreen|DoBlue; + } + + /* enter the glyphs */ + for (glyphnum = 0; glyphnum < glyphs->gr_num; glyphnum++) { + int *p; + GrGlyph *g; + int x, y; + unsigned char curs[32]; + + g = glyphs->gr_glyph[glyphnum]; + if ((g->gr_xsize != 16) || (g->gr_ysize != 16)) { + TxError("Cursors for the X must be 16 X 16 pixels.\n"); + return; + } + + /* Perform transposition on the glyph matrix since X displays + * the least significant bit on the left hand side. + */ + p = &(g->gr_pixels[0]); + for (y = 0; y < 32; y += 2) { + int i; + + curs[i = 31 - y - 1] = 0; + for (x = 0; x < 8; x++) + { + if (GrStyleTable[*p].color != 0) + { + curs[i] |= 1 << x; + } + p++; + } + curs[i += 1] = 0; + for (x = 0; x < 8; x++) + { + if (GrStyleTable[*p].color != 0) + { + curs[i] |= 1 << x; + } + p++; + } + } + source = XCreateBitmapFromData(grXdpy, XDefaultRootWindow(grXdpy), + (char *)curs, 16, 16); + mask = XCreateBitmapFromData(grXdpy, XDefaultRootWindow(grXdpy), + (char *)curs, 16, 16); + grCursors[glyphnum] = XCreatePixmapCursor(grXdpy, source, mask, + &curcolor, &curcolor, + g->gr_origin.p_x, + (15 - g->gr_origin.p_y)); + } + + /* Restore clipping */ + grCurClip = oldClip; + GrUnlock(GR_LOCK_SCREEN); +} + + +/* + * ---------------------------------------------------------------------------- + * GrOGLSetCursor: + * + * Make the cursor be a new pattern, as defined in the display styles file. + * + * Results: + * None. + * + * Side effects: + * When the cursor is turned back on it will take on the new pattern. + * ---------------------------------------------------------------------------- + */ + +void +GrOGLSetCursor(cursorNum) +int cursorNum; /* The cursor number as defined in the display + * styles file. + */ +{ + HashEntry *entry; + HashSearch hs; + + if (cursorNum >= MAX_CURSORS) + { + TxError("No such cursor!\n"); + return; + } + + oglCurrent.cursor = grCursors[cursorNum]; + + HashStartSearch(&hs); + while (entry = HashNext(&grOGLWindowTable, &hs)) + if (HashGetValue(entry)) + XDefineCursor(grXdpy, (Window)entry->h_key.h_ptr, oglCurrent.cursor); + + /* The following is necessary to make sure the cursor is changed NOW */ + glXWaitX(); +} diff --git a/graphics/grOGLInt.h b/graphics/grOGLInt.h new file mode 100644 index 00000000..ff290aaf --- /dev/null +++ b/graphics/grOGLInt.h @@ -0,0 +1,95 @@ +/* + * grOGLInt.h -- + * + * Internal definitions for grOGL[1..].c. + * + * NOTE: In order for the these defs to work correctly, this file + * (grXInt.h) must be included after all the Magic .h files and before + * the X .h files. + */ + +#include "utils/magic.h" + +/* Constants + */ +#define M_WIDTH 1023 +#define M_HEIGHT 750 + +#define MAX_CURSORS 32 /* Maximum number of cursors */ + +#define GR_DEFAULT_FONT "9x15" +#define OGL_BATCH_SIZE 10000 + +# define X_FONT_SMALL "-*-helvetica-medium-r-normal--10-*-75-75-p-*-iso8859-*" +# define X_FONT_MEDIUM "-*-helvetica-medium-r-normal--14-*-75-75-p-*-iso8859-*" +# define X_FONT_LARGE "-*-helvetica-medium-r-normal--18-*-75-75-p-*-iso8859-*" +# define X_FONT_XLARGE "-*-helvetica-medium-r-normal--24-*-75-75-p-*-iso8859-*" + +/* Current settings for X function parameters */ +typedef struct { + XFontStruct *font; + int cursor; + int fontSize; + int depth; + int maskmod; + Window window; + MagWindow *mw; +} OGL_CURRENT; + +#ifdef OGL_SERVER_SIDE_ONLY +typedef Rect OGLRect; +#else + +/* Used for vertex arrays */ +typedef struct { + Point r_ll, r_ul, r_ur, r_lr; +} OGLRect; + +#endif + +/*------------------------------------------------------*/ + +extern OGL_CURRENT oglCurrent; + +extern bool groglGetCursorPos(); +extern bool groglGetCursorRootPos(); +extern bool groglDrawGrid(); +extern void GrOGLEnableTablet(); +extern void GrOGLDisableTablet(); +extern void GrOGLSetCMap(); +extern void GrOGLInitWithArgs(); +extern void groglPutText(); +extern void groglFontText(); +extern void groglDefineCursor(); +extern void GrOGLSetCursor(); +extern void GrOGLSetWindow(); +extern void GrOGLTextSize(); +extern void GrOGLDrawGlyph(); +extern void GrOGLBitBlt(); +extern void NullBitBlt(); +extern int GrOGLReadPixel(); +extern void groglDrawLine(); +extern void groglSetLineStyle(); +extern void groglSetCharSize(); +extern void groglSetWMandC(); +extern void groglFillRect(); +extern void groglFillPolygon(); + +extern void groglFreeBackingStore(); +extern void groglCreateBackingStore(); +extern bool groglGetBackingStore(); +extern bool groglScrollBackingStore(); +extern void groglPutBackingStore(); + +extern Rect groglLines[]; +extern OGLRect groglRects[]; +extern void groglDrawLines(); +extern int groglNbLines; +extern void groglFillRects(); +extern int groglNbRects; + +#define glTransY(mw, n) ( mw->w_allArea.r_ytop - (n)) + +#define GR_X_FLUSH_LINES() {if (groglNbLines>0) {groglDrawLines(groglLines, groglNbLines); groglNbLines=0;}} +#define GR_X_FLUSH_RECTS() {if (groglNbRects>0) {groglFillRects(groglRects, groglNbRects); groglNbRects=0;}} +#define GR_X_FLUSH_BATCH() {GR_X_FLUSH_LINES(); GR_X_FLUSH_RECTS();} diff --git a/graphics/grTOGL1.c b/graphics/grTOGL1.c new file mode 100644 index 00000000..085ac305 --- /dev/null +++ b/graphics/grTOGL1.c @@ -0,0 +1,1451 @@ +/* grTOGL1.c + * + * Copyright (C) 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * This file contains primitive functions for OpenGL running under + * an X window system in a Tcl/Tk interpreter environment + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/main.h" +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/magsgtty.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "textio/textio.h" +#include "textio/txcommands.h" +#include "utils/signals.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" +#include "utils/macros.h" +#include "graphics/grTOGLInt.h" +#include "utils/paths.h" +#include "graphics/grTkCommon.h" + +GLubyte **grTOGLStipples; +HashTable grTOGLWindowTable; +GLXContext grXcontext; +XVisualInfo *grVisualInfo; + +TOGL_CURRENT toglCurrent= {(Tk_Font)0, 0, 0, 0, 0, + (Tk_Window)0, (Window)0, (MagWindow *)NULL}; + +/* This is kind of a long story, and very kludgy, but the following + * things need to be defined as externals because of the way lint + * libraries are made by taking this module and changing all procedures + * names "Xxxx" to "Grxxx". The change is only done at the declaration + * of the procedure, so we need these declarations to handle uses + * of those names, which don't get modified. Check out the Makefile + * for details on this. + */ +extern void GrTOGLClose(), GrTOGLFlush(); +extern void GrTOGLDelete(), GrTOGLConfigure(), GrTOGLRaise(), GrTOGLLower(); +extern void GrTOGLLock(), GrTOGLUnlock(), GrTOGLIconUpdate(); +extern bool GrTOGLInit(); +extern bool GrTOGLEventPending(), GrTOGLCreate(), grtoglGetCursorPos(); +extern int GrTOGLWindowId(); +extern char *GrTkWindowName(); + +extern void toglSetProjection(); + + +/*--------------------------------------------------------- + * grtoglSetWMandC: + * This is a local routine that resets the value of the current + * write alpha (mask) and color, if necessary. + * + * Results: None. + * + * Side Effects: None. + * + * Errors: None. + *--------------------------------------------------------- + */ + +void +grtoglSetWMandC (mask, c) + int mask; /* New value for write mask */ + int c; /* New value for current color */ +{ + static int oldColor = -1; + static int oldMask = -1; + + int lr, lb, lg; + GLfloat fr, fb, fg; + GLfloat aval; /* Alpha default value was 0.75 */ + + if (mask == -65) mask = 127; /* All planes */ + if (mask == oldMask && c == oldColor) return; + + GR_TOGL_FLUSH_BATCH(); + + GrGetColor(c, &lr, &lb, &lg); + + fr = ((GLfloat)lr / 255); + fg = ((GLfloat)lg / 255); + fb = ((GLfloat)lb / 255); + + if (mask == 127) + { + glDisable(GL_BLEND); + aval = 1.0; + } + else + { + /* Calculate a "supercolor", outside of the normal color range, */ + /* but which results in the desired color after a blend with */ + /* the background color. */ + + fr = fr * 2 - 0.8; + fg = fg * 2 - 0.8; + fb = fb * 2 - 0.8; + + aval = (GLfloat)mask / 127.0; /* mask translates to alpha in */ + /* the OpenGL version. */ + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + glColor4f(fr, fb, fg, aval); + + oldColor = c; + oldMask = mask; +} + + +/*--------------------------------------------------------- + * grtoglSetLineStyle: + * This local routine sets the current line style. + * + * Results: None. + * + * Side Effects: + * A new line style is output to the display. + * + *--------------------------------------------------------- + */ + +void +grtoglSetLineStyle (style) + int style; /* New stipple pattern for lines. */ +{ + static int oldStyle = -1; + GLushort glstyle; + + style &= 0xFF; + if (style == oldStyle) return; + oldStyle = style; + GR_TOGL_FLUSH_BATCH(); + + switch (style) { + case 0xFF: + case 0x00: + glDisable(GL_LINE_STIPPLE); + break; + default: + glstyle = style | (style << 8); + glEnable(GL_LINE_STIPPLE); + glLineStipple(1, glstyle); + break; + } +} + + +/*--------------------------------------------------------- + * grtoglSetSPattern: + * toglSetSPattern associates a stipple pattern with a given + * stipple number. This is a local routine called from + * grStyle.c . + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +grtoglSetSPattern (sttable, numstipples) + int **sttable; /* The table of patterns */ + int numstipples; /* Number of stipples */ +{ + int i, j, k, n; + GLubyte *pdata; + + grTOGLStipples = (GLubyte **)mallocMagic(numstipples * sizeof(GLubyte *)); + for (k = 0; k < numstipples; k++) + { + pdata = (GLubyte *)mallocMagic(128 * sizeof(GLubyte)); + n = 0; + + /* expand magic's default 8x8 stipple to OpenGL's 32x32 */ + + for (i = 0; i < 32; i++) + for (j = 0; j < 4; j++) + pdata[n++] = (GLubyte)sttable[k][i % 8]; + + grTOGLStipples[k] = pdata; + } +} + + +/*--------------------------------------------------------- + * grtoglSetStipple: + * This routine sets the Xs current stipple number. + * + * Results: None. + * + * Side Effects: + * The current clipmask in the X is set to stipple, + * if it wasn't that already. + *--------------------------------------------------------- + */ + +void +grtoglSetStipple (stipple) + int stipple; /* The stipple number to be used. */ +{ + static int oldStip = -1; + if (stipple == oldStip) return; + oldStip = stipple; + GR_TOGL_FLUSH_BATCH(); + if (stipple == 0 || stipple > grNumStipples) { + glDisable(GL_POLYGON_STIPPLE); + } else { + if (grTOGLStipples[stipple] == (GLubyte *)NULL) MainExit(1); + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(grTOGLStipples[stipple]); + } +} + + +/*------------------------------------------------------------------------ + * GrTOGLInit: + * GrTOGLInit initializes the graphics display and clears its screen. + * Files must have been previously opened with GrSetDisplay(); + * + * Results: TRUE if successful. + * + * Notes: When 3D rendering is compiled in, we search for a double-buffered + * configuration first, because it generates the smoothest graphics, + * and fall back on a single-buffered configuration if necessary. + * For normal, 2D-only rendering, we look for a single-buffered + * configuration first because we don't use the back buffer, so a + * double-buffered configuration just wastes space. + *------------------------------------------------------------------------ + */ + +bool +GrTOGLInit () +{ + bool rstatus; +#ifdef THREE_D + static int attributeList[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None }; +#else + static int attributeList[] = { GLX_RGBA, None, None }; +#endif + + toglCurrent.window = Tk_MainWindow(magicinterp); + if (toglCurrent.window == NULL) + { + TxError("No Top-Level Tk window available. . . is Tk running?\n"); + return FALSE; + } + + toglCurrent.windowid = Tk_WindowId(toglCurrent.window); + grXdpy = Tk_Display(toglCurrent.window); + toglCurrent.depth = Tk_Depth(toglCurrent.window); + + grXscrn = DefaultScreen(grXdpy); + + grVisualInfo = glXChooseVisual(grXdpy, grXscrn, attributeList); + + if (!grVisualInfo) + { + /* Try for a double-buffered configuration */ +#ifdef THREE_D + attributeList[1] = None; +#else + attributeList[1] = GLX_DOUBLEBUFFER; +#endif + grVisualInfo = glXChooseVisual(grXdpy, grXscrn, attributeList); + if (!grVisualInfo) + { + TxError("No suitable visual!\n"); + return FALSE; + } + } + grXscrn = grVisualInfo->screen; + toglCurrent.depth = grVisualInfo->depth; + + /* TRUE = Direct rendering, FALSE = Indirect rendering */ + /* (note that direct rendering may not be able to deal with pixmaps) */ + grXcontext = glXCreateContext(grXdpy, grVisualInfo, NULL, GL_FALSE); + + /* Basic GL parameters */ + + glLineWidth(1.0); + glShadeModel (GL_FLAT); + glPixelStorei(GL_PACK_LSB_FIRST, TRUE); + + /* OpenGL sets its own names for colormap and dstyle file types */ + grCMapType = "OpenGL"; + grDStyleType = "OpenGL"; + + /* Globally-accessed variables */ + grNumBitPlanes = toglCurrent.depth; + grBitPlaneMask = (1 << toglCurrent.depth) - 1; + + HashInit(&grTOGLWindowTable,8,HT_WORDKEYS); + + return grTkLoadFont(); +} + +/*--------------------------------------------------------- + * GrTOGLClose: + * + * Results: None. + * + * Side Effects: + *--------------------------------------------------------- + */ + +void +GrTOGLClose () +{ + if (grXdpy == NULL) return; + if (grVisualInfo != NULL) XFree(grVisualInfo); + + grTkFreeFonts(); + + /* Pop down Tk window but let Tcl/Tk */ + /* do XCloseDisplay() */ +} + + +/*--------------------------------------------------------- + * GrTOGLFlush: + * Flush output to display. + * + * Flushing is done automatically the next time input is read, + * so this procedure should not be used very often. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +GrTOGLFlush () +{ + GR_TOGL_FLUSH_BATCH(); + glFlush(); + glFinish(); +} + +/* + *--------------------------------------------------------- + */ + +static GLXPixmap glpmap = None; + +#define glTransYs(n) (DisplayHeight(grXdpy, grXscrn)-(n)) + +/* + *--------------------------------------------------------- + * Set the OpenGL viewport (projection matrix) for a window + *--------------------------------------------------------- + */ + +void +toglSetProjection(llx, lly, width, height) + int llx, lly, width, height; +{ + if (toglCurrent.mw->w_flags & WIND_OFFSCREEN) + { + if (glpmap != None) glXDestroyGLXPixmap(grXdpy, glpmap); + glpmap = glXCreateGLXPixmap(grXdpy, grVisualInfo, + (Pixmap)toglCurrent.windowid); + glXMakeCurrent(grXdpy, (GLXDrawable)glpmap, grXcontext); + } + else + glXMakeCurrent(grXdpy, (GLXDrawable)toglCurrent.windowid, grXcontext); + +#ifndef OGL_SERVER_SIDE_ONLY + /* For batch-processing lines and rectangles */ + glEnableClientState(GL_VERTEX_ARRAY); +#endif + + /* Because this tends to result in thick lines, it has been moved */ + /* the line drawing routine so it can be enabled for individual */ + /* lines. */ + /* glEnable(GL_LINE_SMOOTH); */ + + /* Force draw to front buffer (in case of double-buffered config) */ + glDrawBuffer(GL_FRONT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glViewport((GLsizei)llx, (GLsizei)lly, (GLsizei) width, (GLsizei) height); + + /* scale to fit window */ + +#ifdef OGL_INVERT_Y + glScalef(1.0 / (float)(width >> 1), -1.0 / (float)(height >> 1), 1.0); +#else + glScalef(1.0 / (float)(width >> 1), 1.0 / (float)(height >> 1), 1.0); +#endif + + /* magic origin maps to window center; move to window origin */ + + glTranslated(-(GLsizei)(width >> 1), -(GLsizei)(height >> 1), 0); + + /* Remaining transformations are done on the modelview matrix */ + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + + +/* + * --------------------------------------------------------------------------- + * + * TOGLEventProc --- + * + * Tk Event Handler + * + * Results: + * None. + * + * Side Effects: + * Calls functions in response to X11 events. + * + * --------------------------------------------------------------------------- + */ + +void +TOGLEventProc(clientData, xevent) + ClientData clientData; + XEvent *xevent; +{ + TxInputEvent *event; + HashEntry *entry; + Tk_Window tkwind = (Tk_Window)clientData; + Window wind; + MagWindow *mw; + unsigned char LocRedirect = TxInputRedirect; + + XKeyPressedEvent *KeyPressedEvent = (XKeyPressedEvent *) xevent; + KeySym keysym; + int nbytes; + + /* Keys and Buttons: Determine expansion of macros or redirect + * keys to the terminal or console. + */ + + switch (xevent->type) + { + case ButtonPress: + { + XButtonEvent *ButtonEvent = (XButtonEvent *) xevent; + int txbutton; + + switch (ButtonEvent->button) { + case Button1: + txbutton = TX_LEFT_BUTTON; + keysym = XK_Pointer_Button1; + break; + case Button2: + txbutton = TX_MIDDLE_BUTTON; + keysym = XK_Pointer_Button2; + break; + case Button3: + txbutton = TX_RIGHT_BUTTON; + keysym = XK_Pointer_Button3; + break; + case Button4: + txbutton = TX_BUTTON_4; + keysym = XK_Pointer_Button4; + break; + case Button5: + txbutton = TX_BUTTON_5; + keysym = XK_Pointer_Button5; + break; + } + nbytes = 0; + + entry = HashLookOnly(&grTOGLWindowTable, (char *)tkwind); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + + if (mw && (mw->w_flags & WIND_SCROLLBARS)) + if (WindButtonInFrame(mw, ButtonEvent->x, + grXtransY(mw, ButtonEvent->y), + txbutton)) + break; + + goto keys_and_buttons; + } + break; + case KeyPress: + { + int keywstate, keymod, idx, idxmax; + char inChar[10]; + Tcl_Channel outChannel = Tcl_GetStdChannel(TCL_STDOUT); + + nbytes = XLookupString(KeyPressedEvent, inChar, sizeof(inChar), + &keysym, NULL); + + if (IsModifierKey(keysym)) break; /* Don't handle modifiers */ + + entry = HashLookOnly(&grTOGLWindowTable, (char *)tkwind); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + +keys_and_buttons: + + keymod = (LockMask | ControlMask | ShiftMask) + & KeyPressedEvent->state; +#ifdef __APPLE__ + if (KeyPressedEvent->state & (Mod1Mask | Mod2Mask | + Mod3Mask | Mod4Mask | Mod5Mask)) + keymod |= Mod1Mask; +#else + keymod |= (Mod1Mask & KeyPressedEvent->state); +#endif + + if (nbytes == 0) /* No ASCII equivalent */ + { + keywstate = (keymod << 16) | (keysym & 0xffff); + } + else if (!strncmp(XKeysymToString(keysym), "KP_", 3)) + { + /* keypad key (special case---would like to */ + /* differentiate between shift-KP-# and # itself) */ + keymod &= ~ShiftMask; + keywstate = (keymod << 16) | (keysym & 0xffff); + nbytes = 0; + } + else /* ASCII-valued character */ + { + if (!(keymod & (LockMask | Mod1Mask))) { + if (!(keymod & ControlMask)) + keymod &= ~ShiftMask; + else if (!(keymod & ShiftMask)) + keymod &= ~ControlMask; + } + } + + idxmax = (nbytes == 0) ? 1 : nbytes; + for (idx = 0; idx < idxmax; idx++) + { + if (inChar[idx] == 3) /* Ctrl-C interrupt */ + { + if (SigInterruptPending) + MainExit(0); /* double Ctrl-C */ + else + sigOnInterrupt(0); /* Set InterruptPending */ + break; + } + else if (nbytes > 0) + { + if ((keymod & ControlMask) && (inChar[idx] < 32)) + inChar[idx] += 'A' - 1; + + keywstate = (keymod << 16) | ((int)inChar[idx] & 0xff); + } + + /* Allow buttons to bypass the console and be */ + /* treated as macros. */ + + if (LocRedirect == TX_INPUT_REDIRECTED) + { + switch (keysym) + { + case XK_Pointer_Button1: + case XK_Pointer_Button2: + case XK_Pointer_Button3: + case XK_Pointer_Button4: + case XK_Pointer_Button5: + LocRedirect = TX_INPUT_NORMAL;; + break; + } + } + + if ((LocRedirect == TX_INPUT_REDIRECTED) && TxTkConsole) + { + Tcl_SavedResult state; + static char outstr[] = "::tkcon::Insert .text \"x\" "; + + switch (keysym) + { + case XK_Return: + TxSetPoint(KeyPressedEvent->x, + grXtransY(mw, KeyPressedEvent->y), + mw->w_wid); + TxInputRedirect = TX_INPUT_PROCESSING; + Tcl_EvalEx(consoleinterp, "::tkcon::Eval .text", + 19, 0); + TxInputRedirect = TX_INPUT_NORMAL; + TxSetPrompt('%'); + + Tcl_SaveResult(magicinterp, &state); + Tcl_EvalEx(magicinterp, "history event 0", 15, 0); + MacroDefine(mw->w_client, (int)'.', + Tcl_GetStringResult(magicinterp), NULL, + FALSE); + Tcl_RestoreResult(magicinterp, &state); + break; + case XK_Up: + Tcl_EvalEx(consoleinterp, "::tkcon::Event -1", + 17, 0); + break; + case XK_Down: + Tcl_EvalEx(consoleinterp, "::tkcon::Event 1", + 16, 0); + break; + case XK_Left: + Tcl_EvalEx(consoleinterp, ".text mark set insert " + "insert-1c ; .text see insert", 50, 0); + break; + case XK_Right: + Tcl_EvalEx(consoleinterp, ".text mark set insert " + "insert+1c ; .text see insert", 50, 0); + break; + case XK_BackSpace: case XK_Delete: + Tcl_EvalEx(consoleinterp, ".text delete insert-1c ;" + ".text see insert", 40, 0); + break; + case XK_quotedbl: case XK_backslash: case XK_bracketleft: + outstr[23] = '\\'; + outstr[24] = inChar[idx]; + outstr[25] = '\"'; + Tcl_EvalEx(consoleinterp, outstr, 26, 0); + outstr[24] = '\"'; + outstr[25] = '\0'; + default: + outstr[23] = inChar[idx]; + Tcl_EvalEx(consoleinterp, outstr, 25, 0); + break; + } + } + else if (LocRedirect == TX_INPUT_REDIRECTED) { + int tl; + if (TxBuffer == NULL) + { + TxBuffer = Tcl_Alloc(2); + *TxBuffer = '\0'; + tl = 0; + } + else + { + tl = strlen(TxBuffer); + TxBuffer = Tcl_Realloc(TxBuffer, tl + 2); + } + if (keysym == XK_BackSpace || keysym == XK_Delete) + { + if (tl >= 0) + { + if (tl > 0) + { + *(TxBuffer + tl - 1) = '\0'; + TxPrintf("\b"); + } + TxPrintf(" \b"); + TxFlushOut(); + } + } + else if (keysym == XK_Return) + { + *(TxBuffer + tl) = '\n'; + *(TxBuffer + tl + 1) = '\0'; + if (tl != 0) MacroDefine(mw->w_client, + XK_period, TxBuffer, NULL, FALSE); + TxInputRedirect = TX_INPUT_NORMAL; + TxSetPoint(KeyPressedEvent->x, + grXtransY(mw, KeyPressedEvent->y), + mw->w_wid); + TxPrintf("\n"); + TxFlushOut(); + Tcl_NotifyChannel(Tcl_GetStdChannel(TCL_STDIN), + TCL_READABLE); + } + else + { + *(TxBuffer + tl) = *(inChar + idx); + *(TxBuffer + tl + 1) = '\0'; + TxPrintf("%c", *(inChar + idx)); + TxFlushOut(); + } + } + else + { + bool iMacro; + char *macroDef; + + macroDef = MacroRetrieve(mw->w_client, keywstate, &iMacro); + + /* Special handling: An imacro beginning with ':' */ + /* sets the prompt to ':' and moves to the next char. */ + + if (macroDef != NULL && *macroDef == ':' && iMacro) + { + if (TxTkConsole) + TxSetPrompt(':'); + else + { + TxPrintf("\b\b: "); + TxFlushOut(); + } + memmove(macroDef, macroDef + 1, strlen(macroDef + 1) + 1); + } + + macroDef = MacroSubstitute(macroDef, "%W", Tk_PathName(tkwind)); + + if (macroDef == NULL) + { + if (keysym != XK_Return) + { + char *vis = MacroName(keywstate); + TxError("Unknown macro or short command: '%s'\n", vis); + + freeMagic(vis); + } + /* Print Carriage Return & Put back Tcl/Tk prompt */ + TxParseString("", NULL, NULL); + } + else + { + int sl = strlen(macroDef); + + if (iMacro) + { + /* Echo macro to interpreter, then redirect keys */ + + if (TxTkConsole) + { + char *outstring = Tcl_Alloc(sl + 20); + sprintf(outstring, ".text insert end \"%s\"", + macroDef); + Tcl_EvalEx(consoleinterp, outstring, -1, 0); + Tcl_Free(outstring); + } + else + { + TxBuffer = Tcl_Alloc(sl + 1); + strcpy(TxBuffer, macroDef); + TxPrintf("%s", macroDef); + TxFlushOut(); + } + TxInputRedirect = TX_INPUT_REDIRECTED; + } + else + { + /* TxParseString is defined by tcltk/tclmagic.c + * and calls Tcl_Eval() + */ + + TxSetPoint(KeyPressedEvent->x, + grXtransY(mw, KeyPressedEvent->y), + mw->w_wid); + TxParseString(macroDef, NULL, NULL); + } + freeMagic(macroDef); + } + } + } + } + break; + case ConfigureNotify: + { + XConfigureEvent *ConfigureEvent = (XConfigureEvent*) xevent; + Rect screenRect; + int width, height; + bool result, need_resize; + + width = ConfigureEvent->width; + height = ConfigureEvent->height; + + entry = HashLookOnly(&grTOGLWindowTable, (char *)tkwind); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + + screenRect.r_xbot = ConfigureEvent->x; + screenRect.r_xtop = ConfigureEvent->x + width; + screenRect.r_ytop = glTransYs(ConfigureEvent->y); + screenRect.r_ybot = glTransYs(ConfigureEvent->y + height); + + need_resize = (screenRect.r_xbot != mw->w_screenArea.r_xbot || + screenRect.r_xtop != mw->w_screenArea.r_xtop || + screenRect.r_ybot != mw->w_screenArea.r_ybot || + screenRect.r_ytop != mw->w_screenArea.r_ytop); + + /* Redraw the window */ + + WindReframe(mw, &screenRect, FALSE, FALSE); + WindRedisplay(mw); + if (need_resize) (*GrCreateBackingStorePtr)(mw); + } + break; + case VisibilityNotify: + { + XVisibilityEvent *VisEvent = (XVisibilityEvent*) xevent; + + entry = HashLookOnly(&grTOGLWindowTable, (char *)tkwind); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + + switch(VisEvent->state) + { + case VisibilityUnobscured: + mw->w_flags &= ~WIND_OBSCURED; + if (mw->w_backingStore == (ClientData)NULL) + { + (*GrCreateBackingStorePtr)(mw); + if (mw->w_backingStore != (ClientData)NULL) + { + WindAreaChanged(mw, &mw->w_allArea); + WindUpdate(); + } + } + break; + case VisibilityPartiallyObscured: + case VisibilityFullyObscured: + mw->w_flags |= WIND_OBSCURED; + break; + } + } + break; + case Expose: + { + XExposeEvent *ExposeEvent = (XExposeEvent*) xevent; + Rect screenRect; + + entry = HashLookOnly(&grTOGLWindowTable, (char *)tkwind); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + + screenRect.r_xbot = ExposeEvent->x; + screenRect.r_xtop = ExposeEvent->x+ExposeEvent->width; + screenRect.r_ytop = mw->w_allArea.r_ytop-ExposeEvent->y; + screenRect.r_ybot = mw->w_allArea.r_ytop - + (ExposeEvent->y + ExposeEvent->height); + + if (mw->w_backingStore != (ClientData)NULL) + { + Rect surface; + (*GrGetBackingStorePtr)(mw, &screenRect); + WindScreenToSurface(mw, &screenRect, &surface); + DBWHLRedrawPrepWindow(mw, &surface); + WindDrawBorder(mw, &screenRect); + } + else + WindAreaChanged(mw, &screenRect); + WindUpdate(); + } + break; + + case MapNotify: + case UnmapNotify: + case DestroyNotify: /* Do nothing */ + break; + + default: + TxError("Tk Event: Unknown (%d)\n", xevent->type); + TxFlush(); + break; + } +} + + + +/*--------------------------------------------------------- + * oglSetDisplay: + * This routine sets the appropriate parameters so that + * Magic will work with the X display. + * + * Under Xlib, all input events (mouse and keyboard) are + * sent to one queue which has to be polled to discover + * whether there is any input or not. To fit the Magic + * interrupt-driven input model, a helper process is + * spawned which reads and blocks on the event queue, + * sending SIGIO's to Magic when it detects input. The + * input read in the helper process is then sent to Magic + * via a communication pipe. + * + * Results: success / fail + * + * Side Effects: Sets up the pipe. + *--------------------------------------------------------- + */ + +bool +oglSetDisplay (dispType, outFileName, mouseFileName) + char *dispType; + char *outFileName; + char *mouseFileName; +{ + char *planecount; + char *fullname; + FILE* f; + bool execFailed = FALSE; + int x, y, width, height; + + WindPackageType = WIND_X_WINDOWS; /* to be changed? */ + TxInputRedirect = TX_INPUT_NORMAL; + + grCursorType = "color"; + WindScrollBarWidth = 14; + + /* Set up the procedure values in the indirection table. */ + + GrPixelCorrect = 0; + + GrLockPtr = GrTOGLLock; + GrUnlockPtr = GrTOGLUnlock; + GrInitPtr = GrTOGLInit; + GrClosePtr = GrTOGLClose; + GrSetCMapPtr = GrTOGLSetCMap; + + GrEnableTabletPtr = GrTOGLEnableTablet; + GrDisableTabletPtr = GrTOGLDisableTablet; + GrSetCursorPtr = GrTOGLSetCursor; + GrTextSizePtr = GrTOGLTextSize; + GrDrawGlyphPtr = GrTOGLDrawGlyph; + GrReadPixelPtr = GrTOGLReadPixel; + GrFlushPtr = GrTOGLFlush; + + GrCreateWindowPtr = GrTOGLCreate; + GrDeleteWindowPtr = GrTOGLDelete; + GrConfigureWindowPtr = GrTOGLConfigure; + GrOverWindowPtr = GrTOGLRaise; + GrUnderWindowPtr = GrTOGLLower; + GrUpdateIconPtr = GrTOGLIconUpdate; + GrEventPendingPtr = GrTOGLEventPending; + GrWindowIdPtr = GrTOGLWindowId; + GrWindowNamePtr = GrTkWindowName; /* from grTkCommon.c */ + GrGetCursorPosPtr = grtoglGetCursorPos; + GrGetCursorRootPosPtr = grtoglGetCursorRootPos; + + /* local indirections */ + grSetSPatternPtr = grtoglSetSPattern; + grPutTextPtr = grtoglPutText; +#ifdef VECTOR_FONTS + grFontTextPtr = grtoglFontText; +#endif + grDefineCursorPtr = grTkDefineCursor; + grFreeCursorPtr = grTkFreeCursors; + GrBitBltPtr = GrTOGLBitBlt; + grDrawGridPtr = grtoglDrawGrid; + grDrawLinePtr = grtoglDrawLine; + grSetWMandCPtr = grtoglSetWMandC; + grFillRectPtr = grtoglFillRect; + grSetStipplePtr = grtoglSetStipple; + grSetLineStylePtr = grtoglSetLineStyle; + grSetCharSizePtr = grtoglSetCharSize; + grFillPolygonPtr = grtoglFillPolygon; + +#ifdef X11_BACKING_STORE + GrFreeBackingStorePtr = grtkFreeBackingStore; + GrCreateBackingStorePtr = grtkCreateBackingStore; + GrGetBackingStorePtr = grtkGetBackingStore; + GrPutBackingStorePtr = grtkPutBackingStore; + GrScrollBackingStorePtr = grtkScrollBackingStore; +#else + GrFreeBackingStorePtr = grtoglFreeBackingStore; + GrCreateBackingStorePtr = grtoglCreateBackingStore; + GrGetBackingStorePtr = grtoglGetBackingStore; + GrPutBackingStorePtr = grtoglPutBackingStore; + GrScrollBackingStorePtr = grtoglScrollBackingStore; +#endif + + if (execFailed) { + TxError("Execution failed!\n"); + return FALSE; + } + + if(!GrTOGLInit()){ + return FALSE; + }; + + Tk_GetVRootGeometry(Tk_MainWindow(magicinterp), &x, &y, &width, &height); + GrScreenRect.r_xbot = x; + GrScreenRect.r_ybot = y; + GrScreenRect.r_xtop = width + x; + GrScreenRect.r_ytop = height + y; + + return Tk_MainWindow(magicinterp) ? TRUE : FALSE; +} + +extern void MakeWindowCommand(); + +/* + * ---------------------------------------------------------------------------- + * + * GrTOGLCreate -- + * Create a new window under the X window system. + * Bind X window to Magic Window w. + * + * Results: + * Success/Fail + * + * Side Effects: + * Window created, window ID send to Xhelper. + * + * ---------------------------------------------------------------------------- + */ + +bool +GrTOGLCreate(w, name) + MagWindow *w; + char *name; +{ + Tk_Window tkwind, tktop; + Window wind; + static int WindowNumber = 0; + HashEntry *entry; + char *windowplace; + char windowname[10]; + int x = w->w_frameArea.r_xbot; + int y = glTransYs(w->w_frameArea.r_ytop); + int width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; + int height = w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; + unsigned long attribmask = CWBackPixel | CWBorderPixel | CWColormap; + XSetWindowAttributes grAttributes; + + WindSeparateRedisplay(w); + + sprintf(windowname, ".magic%d", WindowNumber + 1); + if (windowplace = XGetDefault(grXdpy, "magic", windowname)) + { + XParseGeometry(windowplace,&x,&y, + (unsigned int *)&width,(unsigned int *)&height); + w->w_frameArea.r_xbot = x; + w->w_frameArea.r_xtop = x+width; + w->w_frameArea.r_ytop = glTransYs(y); + w->w_frameArea.r_ybot = glTransYs(y+height); + WindReframe(w,&(w->w_frameArea),FALSE,FALSE); + } + + grAttributes.colormap = XCreateColormap(grXdpy, RootWindow(grXdpy, grXscrn), + grVisualInfo->visual, AllocNone); + grAttributes.background_pixel = WhitePixel(grXdpy,grXscrn); + grAttributes.border_pixel = BlackPixel(grXdpy,grXscrn); + + if (tktop = Tk_MainWindow(magicinterp)) + { + if (!WindowNumber) + { + /* To do: deal with grVisualInfo---destroy and recreate top */ + /* frame if necessary */ + + if (Tk_WindowId(tktop) == 0) + { + Tk_SetWindowVisual(tktop, grVisualInfo->visual, + toglCurrent.depth, grAttributes.colormap); + } + else + { + /* The Top-level window has already been mapped. We can't mess */ + /* with it's visual. If the title is "wish", we'll assume that */ + /* nobody else is claiming it, and unmap it. */ + + if (!strcmp(Tk_Name(tktop), "wish")) Tk_UnmapWindow(tktop); + } + } + } + else + return 0; /* failure */ + + /* Last parameter "" indicates a top-level window in the space of */ + /* the parent. */ + + if (name == NULL) + tkwind = Tk_CreateWindowFromPath(magicinterp, tktop, windowname, ""); + else + tkwind = Tk_CreateWindowFromPath(magicinterp, tktop, name, NULL); + + /* TxError("Creating window named \"%s\", tkwind = 0x%x\n", + windowname, tkwind); TxFlush(); */ + + if (tkwind != 0) + { + bool result; + + GrTOGLFlush(); + + toglCurrent.window = tkwind; + toglCurrent.mw = w; + + w->w_grdata = (ClientData) tkwind; + + entry = HashFind(&grTOGLWindowTable, (char *)tkwind); + HashSetValue(entry,w); + + /* ensure that the visual is what we wanted, if possible to change */ + + Tk_SetWindowVisual(tkwind, grVisualInfo->visual, toglCurrent.depth, + grAttributes.colormap); + + /* map the window, if necessary */ + + Tk_MapWindow(tkwind); + + /* use x, y, width, height to size and position the window */ + + Tk_GeometryRequest(tkwind, width, height); + /* Tk_MoveResizeWindow(tkwind, x, y, width, height); */ + + wind = Tk_WindowId(tkwind); + toglCurrent.windowid = wind; + glXMakeCurrent(grXdpy, (GLXDrawable)wind, grXcontext); + + Tk_DefineCursor(tkwind, toglCurrent.cursor); + GrTOGLIconUpdate(w, w->w_caption); + + WindowNumber++; + + /* execute all Tk events up to current */ + + while (Tcl_DoOneEvent(TCL_DONT_WAIT) != 0); + + /* set up Tk event handler to start processing */ + + Tk_CreateEventHandler(tkwind, ExposureMask | StructureNotifyMask + | ButtonPressMask | KeyPressMask | VisibilityChangeMask, + (Tk_EventProc *)TOGLEventProc, (ClientData) tkwind); + + /* set up commands to be passed expressly to this window */ + + MakeWindowCommand((name == NULL) ? windowname : name, w); + + return (WindowNumber == 1) ? grtoglLoadFont() : 1; + } + else + { + TxError("Could not open new Tk window\n"); + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTOGLDelete -- + * Destroy a Tk/OpenGL window. + * + * Results: + * None. + * + * Side Effects: + * Window destroyed. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLDelete(w) + MagWindow *w; +{ + Tk_Window xw; + HashEntry *entry; + + xw = (Tk_Window) w->w_grdata; + entry = HashLookOnly(&grTOGLWindowTable, (char *)xw); + HashSetValue(entry,NULL); + + Tcl_DeleteCommand(magicinterp, Tk_PathName(xw)); + Tk_DestroyWindow(xw); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTOGLConfigure -- + * Resize/ Move an existing X window. + * + * Results: + * None. + * + * Side Effects: + * Window reconfigured to w->w_frameArea. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLConfigure(w) + MagWindow *w; +{ + if (w->w_flags & WIND_OFFSCREEN) return; + + Tk_MoveResizeWindow((Tk_Window)w->w_grdata, + w->w_frameArea.r_xbot, glTransYs(w->w_frameArea.r_ytop), + w->w_frameArea.r_xtop - w->w_frameArea.r_xbot, + w->w_frameArea.r_ytop - w->w_frameArea.r_ybot); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTOGLRaise -- + * Raise a window to the top of the screen such that nothing + * obscures it. + * + * Results: + * None. + * + * Side Effects: + * Window raised. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLRaise(w) + MagWindow *w; +{ + Tk_Window tkwind; + + if (w->w_flags & WIND_OFFSCREEN) return; + + tkwind = (Tk_Window)w->w_grdata; + Tk_RestackWindow(tkwind, Above, NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTOGLLower -- + * Lower a window below all other Tk windows. + * obscures it. + * + * Results: + * None. + * + * Side Effects: + * Window lowered. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLLower(w) + MagWindow *w; +{ + Tk_Window tkwind; + + if (w->w_flags & WIND_OFFSCREEN) return; + + tkwind = (Tk_Window)w->w_grdata; + Tk_RestackWindow(tkwind, Below, NULL); +} + + +/* + * ---------------------------------------------------------------------------- + * + * GrTOGLLock -- + * Lock a window and set global variables "toglCurrent.window" + * and "toglCurrent.mw" to reference the locked window. + * + * Results: + * None. + * + * Side Effects: + * Window locked. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLLock(w, flag) + MagWindow *w; + bool flag; +{ + Window wind; + + grSimpleLock(w, flag); + if ( w != GR_LOCK_SCREEN ) + { + toglCurrent.mw = w; + + if (w->w_flags & WIND_OFFSCREEN) + { + toglCurrent.window = (Tk_Window) NULL; + toglCurrent.windowid = (Pixmap) w->w_grdata; + } + else + { + toglCurrent.window = (Tk_Window) w->w_grdata; + toglCurrent.windowid = Tk_WindowId(toglCurrent.window); + } + + toglSetProjection(w->w_allArea.r_xbot, w->w_allArea.r_ybot, + w->w_allArea.r_xtop - w->w_allArea.r_xbot, + w->w_allArea.r_ytop - w->w_allArea.r_ybot); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTOGLUnlock -- + * Unlock a window, flushing stuff out to the display. + * + * Results: + * None. + * + * Side Effects: + * Window unlocked. + * Display update. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLUnlock(w) + MagWindow *w; +{ + /* GR_TOGL_FLUSH_BATCH(); */ + GrTOGLFlush(); /* (?) Adds glFlush and glFinish to the above. */ + grSimpleUnlock(w); +} + + +/* + *------------------------------------------------------------------------- + * GrTOGLEventPending -- + * check for pending graphics events. + * Here we use the X11 check for window events, because Tcl/Tk doesn't + * allows peeking into its event queue without executing whatever is + * in the queue. + * + * Results: + * TRUE if an event is waiting in the event queue. + * + * Side effects: + * None, hopefully (put back the event!) + * + *------------------------------------------------------------------------- + */ + +bool +GrTOGLEventPending() +{ + Window wind = toglCurrent.windowid; + XEvent genEvent; + bool retval; + + XSync(grXdpy, FALSE); /* Necessary, or it won't catch mouse/key events */ + retval = XCheckWindowEvent(grXdpy, wind, ExposureMask + | StructureNotifyMask | ButtonPressMask + | KeyPressMask, &genEvent); + if (retval) XPutBackEvent(grXdpy, &genEvent); + return retval; +} + +/* + *------------------------------------------------------------------------- + * + * GrTOGLIconUpdate -- updates the icon text with the window script + * + * Results: none + * + * Side Effects: changes the icon text + * + *------------------------------------------------------------------------- + */ + +void +GrTOGLIconUpdate(w,text) /* See Blt code */ + MagWindow *w; + char *text; +{ + Tk_Window tkwind; + Window wind; + XClassHint class; + char *brack; + + if (w->w_flags & WIND_OFFSCREEN) return; + + tkwind = (Tk_Window)(w->w_grdata); + if (tkwind == NULL) { + tkwind = Tk_MainWindow(magicinterp); + if (tkwind == NULL) return; + } + wind = Tk_WindowId(tkwind); + if (wind == 0) return; + + class.res_name = "magic"; + class.res_class = "magic"; + + XSetClassHint( grXdpy, wind, &class); + if (text) + { + if (brack = strchr(text,'[')) + { + brack--; + *brack = 0; + XSetIconName(grXdpy,wind,text); + XStoreName(grXdpy,wind,text); + *brack = ' '; + return; + } + if (brack = strrchr(text,' ')) text = brack+1; + XSetIconName(grXdpy,wind,text); + XStoreName(grXdpy,wind,text); + } +} + +/* + *------------------------------------------------------------------------- + * GrTOGLWindowId -- + * Get magic's ID number from the indicated MagWindow structure + * + * Results: + * The window ID number. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +int +GrTOGLWindowId(tkname) + char *tkname; +{ + Tk_Window tkwind; + MagWindow *mw; + HashEntry *entry; + int id = 0; + + tkwind = Tk_NameToWindow(magicinterp, tkname, Tk_MainWindow(magicinterp)); + if (tkwind != NULL) + { + entry = HashLookOnly(&grTOGLWindowTable, (char *)tkwind); + mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0; + if (mw) id = mw->w_wid; + } + return id; +} diff --git a/graphics/grTOGL2.c b/graphics/grTOGL2.c new file mode 100644 index 00000000..49b9c081 --- /dev/null +++ b/graphics/grTOGL2.c @@ -0,0 +1,229 @@ +/* grTOGL2.c - + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * This file contains additional functions to manipulate an X + * color display. Included here are rectangle drawing and color map + * loading. + */ + +#include +char *getenv(); + +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/glyphs.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "grTOGLInt.h" + +extern char *DBWStyleType; +extern GLXContext grXcontext; +extern Display *grXdpy; + + +/*--------------------------------------------------------- + * GrOGLSetCMap -- + * + * OpenGL uses RGB values as read from the colormap file, + * directly, so there is no need to install colors into a + * colormap. Therefore, this is a null routine. + * + * Results: None. + * + * Side Effects: None. + * + *--------------------------------------------------------- + */ + +void +GrTOGLSetCMap () +{ +} + +Rect grtoglLines[TOGL_BATCH_SIZE]; +int grtoglNbLines = 0; +TOGLRect grtoglRects[TOGL_BATCH_SIZE]; +int grtoglNbRects = 0; +Rect grtoglDiagonal[TOGL_BATCH_SIZE]; +int grtoglNbDiagonal = 0; + +/*--------------------------------------------------------- + * grtoglDrawLines: + * This routine draws a batch of lines. + * + * Results: None. + * + * Side Effects: + * Draw a bunch of lines. + *--------------------------------------------------------- + */ + +void +grtoglDrawLines(lines, nb) + Rect lines[]; + int nb; +{ + +#ifdef OGL_SERVER_SIDE_ONLY + + int i; + + glBegin(GL_LINES); + for (i = 0; i < nb; i++) + { + glVertex2i(lines[i].r_ll.p_x, lines[i].r_ll.p_y); + glVertex2i(lines[i].r_ur.p_x, lines[i].r_ur.p_y); + } + glEnd(); + +#else + + glVertexPointer(2, GL_INT, 0, (GLvoid *)lines); + glDrawArrays(GL_LINES, 0, nb << 1); + +#endif +} + +/*--------------------------------------------------------- + * grtoglDrawLine: + * This routine draws a line. + * + * Results: None. + * + * Side Effects: + * Draw a line for (x1, y1) to (x2, y2) inclusive. + *--------------------------------------------------------- + */ + +void +grtoglDrawLine (x1, y1, x2, y2) + int x1, y1; /* Screen coordinates of first point. */ + int x2, y2; /* Screen coordinates of second point. */ +{ + /* Treat straight and diagonal lines separately. Some */ + /* implementations of OpenGL make straight lines twice as thick */ + /* when smoothing is enabled. */ + + if ((x1 == x2) || (y1 == y2)) + { + if (grtoglNbLines == TOGL_BATCH_SIZE) GR_TOGL_FLUSH_LINES(); + grtoglLines[grtoglNbLines].r_ll.p_x = x1; + grtoglLines[grtoglNbLines].r_ll.p_y = y1; + grtoglLines[grtoglNbLines].r_ur.p_x = x2; + grtoglLines[grtoglNbLines].r_ur.p_y = y2; + grtoglNbLines++; + } + else + { + if (grtoglNbDiagonal == TOGL_BATCH_SIZE) GR_TOGL_FLUSH_DIAGONAL(); + grtoglDiagonal[grtoglNbDiagonal].r_ll.p_x = x1; + grtoglDiagonal[grtoglNbDiagonal].r_ll.p_y = y1; + grtoglDiagonal[grtoglNbDiagonal].r_ur.p_x = x2; + grtoglDiagonal[grtoglNbDiagonal].r_ur.p_y = y2; + grtoglNbDiagonal++; + } +} + +/*--------------------------------------------------------- + * grtoglFillRects: + * This routine draws a bunch of solid rectangles. + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +grtoglFillRects(rects, nb) + TOGLRect rects[]; + int nb; +{ + +#ifdef OGL_SERVER_SIDE_ONLY + + int i; + + for (i = 0; i < nb; i++) + { + glRecti(rects[i].r_ll.p_x, rects[i].r_ll.p_y, + rects[i].r_ur.p_x, rects[i].r_ur.p_y); + } + +#else + + glVertexPointer(2, GL_INT, 0, (GLvoid *)rects); + glDrawArrays(GL_QUADS, 0, nb << 2); + +#endif +} + +/*--------------------------------------------------------- + * grtoglFillRect: + * This routine draws a solid rectangle. + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +grtoglFillRect(r) + Rect *r; /* Address of a rectangle in screen + * coordinates. + */ +{ + if (grtoglNbRects == TOGL_BATCH_SIZE) GR_TOGL_FLUSH_RECTS(); + grtoglRects[grtoglNbRects].r_ll.p_x = r->r_ll.p_x; + grtoglRects[grtoglNbRects].r_ll.p_y = r->r_ll.p_y; + + grtoglRects[grtoglNbRects].r_ur.p_x = r->r_ur.p_x; + grtoglRects[grtoglNbRects].r_ur.p_y = r->r_ur.p_y; + +#ifndef OGL_SERVER_SIDE_ONLY + grtoglRects[grtoglNbRects].r_ul.p_x = r->r_ll.p_x; + grtoglRects[grtoglNbRects].r_ul.p_y = r->r_ur.p_y; + + grtoglRects[grtoglNbRects].r_lr.p_x = r->r_ur.p_x; + grtoglRects[grtoglNbRects].r_lr.p_y = r->r_ll.p_y; +#endif + + grtoglNbRects++; +} + +/*--------------------------------------------------------- + * grtoglFillPolygon: + * This routine draws a solid (convex) polygon + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +grtoglFillPolygon(tp, np) + Point *tp; + int np; +{ + int i; + + glEnable(GL_POLYGON_SMOOTH); + glBegin(GL_POLYGON); + for (i = 0; i < np; i++) + glVertex2i(tp[i].p_x, tp[i].p_y); + glEnd(); + glDisable(GL_POLYGON_SMOOTH); +} + diff --git a/graphics/grTOGL3.c b/graphics/grTOGL3.c new file mode 100644 index 00000000..8cc8dde6 --- /dev/null +++ b/graphics/grTOGL3.c @@ -0,0 +1,705 @@ +/* grTOGL3.c - + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * This file contains additional functions to manipulate an X window system + * color display. Included here are device-dependent routines to draw and + * erase text and draw a grid. + * + */ + +#include +#include + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/malloc.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "dbwind/dbwind.h" +#include "textio/textio.h" +#include "utils/signals.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "graphics/grTOGLInt.h" +#include "graphics/grTkCommon.h" +#include "database/fonts.h" + +extern Display *grXdpy; + +/* locals */ + +GLuint grXBases[4]; + + +/*--------------------------------------------------------- + * grtoglDrawGrid: + * grxDrawGrid adds a grid to the grid layer, using the current + * write mask and color. + * + * Results: + * TRUE is returned normally. However, if the grid gets too small + * to be useful, then nothing is drawn and FALSE is returned. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +bool +grtoglDrawGrid (prect, outline, clip) + Rect *prect; /* A rectangle that forms the template + * for the grid. Note: in order to maintain + * precision for the grid, the rectangle + * coordinates are specified in units of + * screen coordinates multiplied by SUBPIXEL. + */ + int outline; /* the outline style */ + Rect *clip; /* a clipping rectangle */ +{ + int xsize, ysize; + int x, y; + int xstart, ystart; + int snum, low, hi, shifted; + + xsize = prect->r_xtop - prect->r_xbot; + ysize = prect->r_ytop - prect->r_ybot; + if (!xsize || !ysize || GRID_TOO_SMALL(xsize, ysize)) + return FALSE; + + xstart = prect->r_xbot % xsize; + while (xstart < clip->r_xbot << SUBPIXELBITS) xstart += xsize; + ystart = prect->r_ybot % ysize; + while (ystart < clip->r_ybot << SUBPIXELBITS) ystart += ysize; + + grtoglSetLineStyle(outline); + + glBegin(GL_LINES); + + snum = 0; + low = clip->r_ybot; + hi = clip->r_ytop; + for (x = xstart; x < (clip->r_xtop+1) << SUBPIXELBITS; x += xsize) + { + shifted = x >> SUBPIXELBITS; + glVertex2i(shifted, low); + glVertex2i(shifted, hi); + snum++; + } + + snum = 0; + low = clip->r_xbot; + hi = clip->r_xtop; + for (y = ystart; y < (clip->r_ytop+1) << SUBPIXELBITS; y += ysize) + { + shifted = y >> SUBPIXELBITS; + glVertex2i(low, shifted); + glVertex2i(hi, shifted); + snum++; + } + glEnd(); + return TRUE; +} + + +/*--------------------------------------------------------- + * grtoglLoadFont + * This local routine transfers the X font bitmaps + * into OpenGL display lists for simple text + * rendering. + * + * Results: Success/Failure + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +bool +grtoglLoadFont() +{ + Font id; + unsigned int i; + + for (i = 0; i < 4; i++) { + id = Tk_FontId(grTkFonts[i]); + + grXBases[i] = glGenLists(256); + if (grXBases[i] == 0) { + TxError("Out of display lists!\n"); + return FALSE; + } + glXUseXFont(id, 0, 256, grXBases[i]); + } + return TRUE; +} + + +/*--------------------------------------------------------- + * grtoglSetCharSize: + * This local routine sets the character size in the display, + * if necessary. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +grtoglSetCharSize (size) + int size; /* Width of characters, in pixels (6 or 8). */ +{ + toglCurrent.fontSize = size; + switch (size) + { + case GR_TEXT_DEFAULT: + case GR_TEXT_SMALL: + toglCurrent.font = grSmallFont; + break; + case GR_TEXT_MEDIUM: + toglCurrent.font = grMediumFont; + break; + case GR_TEXT_LARGE: + toglCurrent.font = grLargeFont; + break; + case GR_TEXT_XLARGE: + toglCurrent.font = grXLargeFont; + break; + default: + TxError("%s%d\n", "grtoglSetCharSize: Unknown character size ", + size ); + break; + } +} + + +/* + * ---------------------------------------------------------------------------- + * GrTOGLTextSize -- + * + * Determine the size of a text string. + * + * Results: + * None. + * + * Side effects: + * A rectangle is filled in that is the size of the text in pixels. + * The origin (0, 0) of this rectangle is located on the baseline + * at the far left side of the string. + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLTextSize(text, size, r) + char *text; + int size; + Rect *r; +{ + Tk_FontMetrics overall; + Tk_Font font; + int width; + + switch (size) { + case GR_TEXT_DEFAULT: + case GR_TEXT_SMALL: + font = grSmallFont; + break; + case GR_TEXT_MEDIUM: + font = grMediumFont; + break; + case GR_TEXT_LARGE: + font = grLargeFont; + break; + case GR_TEXT_XLARGE: + font = grXLargeFont; + break; + default: + TxError("%s%d\n", "GrTOGLTextSize: Unknown character size ", + size ); + break; + } + if (font == NULL) return; + Tk_GetFontMetrics(font, &overall); + width = Tk_TextWidth(font, text, strlen(text)); + /* Hack alert! Tk_TextWidth returns values too small! */ + width = width + (width >> 4); + r->r_ytop = overall.ascent; + r->r_ybot = -overall.descent; + r->r_xtop = width; + r->r_xbot = 0; +} + +/* OpenGL backing store functions (now removed from the X11-based ones) */ +/* Since we always paint into the front buffer, the back buffer is */ +/* always available for backing store. We need not create or destroy */ +/* it. We just use the w_backingStore location to store whether the */ +/* backing store contains valid data or not. */ + +void +grtoglFreeBackingStore(MagWindow *window) +{ + window->w_backingStore = (ClientData)0; +} + +void +grtoglCreateBackingStore(MagWindow *w) +{ + Tk_Window tkwind = (Tk_Window)w->w_grdata; + + /* ignore all windows other than layout */ + if (w->w_client != DBWclientID) return; + + /* Deferred */ + if (tkwind == NULL) return; + + w->w_backingStore = (ClientData)1; +} + +bool +grtoglGetBackingStore(MagWindow *w, Rect *area) +{ + unsigned int width, height; + int xbot, ybot; + Rect r; + + // GLboolean result; + // GLint rasterpos[4]; + + if (w->w_backingStore == (ClientData)0) return FALSE; + + GEO_EXPAND(area, 1, &r); + GeoClip(&r, &(w->w_screenArea)); + + width = r.r_xtop - r.r_xbot; + height = r.r_ytop - r.r_ybot; + + xbot = r.r_xbot; + ybot = r.r_ybot; + + glDrawBuffer(GL_FRONT); + glReadBuffer(GL_BACK); + glRasterPos2i((GLint)xbot, (GLint)ybot); + + /* Check for valid raster position */ + // glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, (GLboolean *)(&result)); + // glGetIntegerv(GL_CURRENT_RASTER_POSITION, (GLint *)(&rasterpos[0])); + + // TxPrintf("Raster valid = %d, position = %d %d %d %d\n", + // (int)result, (int)rasterpos[0], (int)rasterpos[1], + // (int)rasterpos[2], (int)rasterpos[3]); + // if (result == 0) + // TxPrintf("Intended position = %d %d\n", xbot, ybot); + + glDisable(GL_BLEND); + glCopyPixels(xbot, ybot, width, height, GL_COLOR); + + return TRUE; +} + + +bool +grtoglScrollBackingStore(MagWindow *w, Point *shift) +{ + unsigned int width, height; + int xorigin, yorigin, xshift, yshift; + + if (w->w_backingStore == (ClientData)0) + { + TxPrintf("grtoglScrollBackingStore %d %d failure\n", + shift->p_x, shift->p_y); + return FALSE; + } + + width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + xorigin = 0; + yorigin = 0; + xshift = shift->p_x; + yshift = shift->p_y; + + if (xshift > 0) + width -= xshift; + else if (xshift < 0) + { + width += xshift; + xorigin = -xshift; + xshift = 0; + } + if (yshift > 0) + height -= yshift; + else if (yshift < 0) + { + height += yshift; + yorigin = -yshift; + yshift = 0; + } + + glDrawBuffer(GL_BACK); + glReadBuffer(GL_BACK); + glRasterPos2i((GLint)xshift, (GLint)yshift); + glDisable(GL_BLEND); + glCopyPixels(xorigin, yorigin, width, height, GL_COLOR); + + glDrawBuffer(GL_FRONT); + + return TRUE; +} + +void +grtoglPutBackingStore(MagWindow *w, Rect *area) +{ + unsigned int width, height; + int ybot, xbot; + + // GLboolean result; + // GLint rasterpos[4]; + + if (w->w_backingStore == (ClientData)0) return; + + width = area->r_xtop - area->r_xbot; + height = area->r_ytop - area->r_ybot; + + ybot = area->r_ybot; + xbot = area->r_xbot; + + if (xbot < 0) { + width -= xbot; + xbot = 0; + } + + if (ybot < 0) { + height -= ybot; + ybot = 0; + } + + glReadBuffer(GL_FRONT); + glDrawBuffer(GL_BACK); + glRasterPos2i((GLint)xbot, (GLint)ybot); + + /* Check for valid raster position */ + // glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, (GLboolean *)(&result)); + // glGetIntegerv(GL_CURRENT_RASTER_POSITION, (GLint *)(&rasterpos[0])); + + // TxPrintf("Raster valid = %d, position = %d %d %d %d\n", + // (int)result, (int)rasterpos[0], (int)rasterpos[1], + // (int)rasterpos[2], (int)rasterpos[3]); + // if (result == 0) + // TxPrintf("Intended position = %d %d\n", xbot, ybot); + + glDisable(GL_BLEND); + glCopyPixels(xbot, ybot, width, height, GL_COLOR); + + glDrawBuffer(GL_FRONT); /* Return to normal front rendering */ +} + + +/* + * ---------------------------------------------------------------------------- + * GrTOGLReadPixel -- + * + * Read one pixel from the screen. + * + * Results: + * An integer containing the pixel's color. + * + * Side effects: + * none. + * + * ---------------------------------------------------------------------------- + */ + +int +GrTOGLReadPixel (w, x, y) + MagWindow *w; + int x,y; /* the location of a pixel in screen coords */ +{ + return 0; /* OpenGL has no such function, so return 0 */ +} + + +/* + * ---------------------------------------------------------------------------- + * GrTOGLBitBlt -- + * + * Copy information in bit block transfers. + * + * Results: + * None. + * + * Side effects: + * changes the screen. + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLBitBlt(r, p) + Rect *r; + Point *p; +{ + glCopyPixels(r->r_xbot, r->r_ybot, r->r_xtop - r->r_xbot + 1, + r->r_ytop - r->r_ybot + 1, GL_COLOR); +} + +#ifdef VECTOR_FONTS + +/* + *---------------------------------------------------------------------- + * + * Technically, there should be no self-intersecting polygons in outline + * fonts. However, decomposition of bezier curves into line segments + * may occasionally produce one, so it needs to be handled. + *---------------------------------------------------------------------- + */ + +void +myCombine(GLdouble coords[3], GLdouble *vertex_data[4], + GLfloat weight[4], GLdouble **outData, void *dataptr) +{ + /* This needs to be free'd at the end of gluTessEndPolygon()! */ + GLdouble *new = (GLdouble *)mallocMagic(2 * sizeof(GLdouble)); + new[0] = coords[0]; + new[1] = coords[1]; + *outData = new; + /* Diagnostic */ + TxError("Intersecting polygon in char \"%c\" at %g %g!\n", + *((char *)dataptr), coords[0], coords[1]); +} + +/* + *---------------------------------------------------------------------- + * Draw a text character + * This routine differs from grtoglFillPolygon() in that it uses the + * glu library to handle non-convex polygons as may appear in font + * outlines. + *---------------------------------------------------------------------- + */ + +void +grtoglDrawCharacter(clist, tc, pixsize) + FontChar *clist; + unsigned char tc; + int pixsize; +{ + Point *tp; + int np, nptotal; + int i, j; + static GLUtesselator *tess = NULL; + static GLdouble *v = NULL; + static int maxnp = 0; + FontChar *ccur; + + if (pixsize < 5) return; /* Label too small to be useful */ + + if (tess == NULL) + { + tess = gluNewTess(); + gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin); + gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv); + gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)glEnd); + gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)myCombine); + } + // Boundary-only does not look particularly good. . . + gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE); + + nptotal = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + nptotal += ccur->fc_numpoints; + + if (nptotal > maxnp) + { + if (v != NULL) freeMagic((char *)v); + maxnp = nptotal; + v = (GLdouble *)mallocMagic(nptotal * 3 * sizeof(GLdouble)); + } + + j = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + { + tp = ccur->fc_points; + np = ccur->fc_numpoints; + + for (i = 0; i < np; i++, j += 3) { + v[j] = tp[i].p_x; + v[j + 1] = tp[i].p_y; + v[j + 2] = 0; + } + } + + gluTessBeginPolygon(tess, (GLvoid *)(&tc)); + j = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + { + np = ccur->fc_numpoints; + gluTessBeginContour(tess); + for (i = 0; i < np; i++, j += 3) { + gluTessVertex(tess, &v[j], &v[j]); + } + gluTessEndContour(tess); + } + gluTessEndPolygon(tess); +} + +/*--------------------------------------------------------- + * grtoglFontText: + * + * This routine draws text from font vectors using the + * font vector routines in DBlabel.c. Text is clipped + * to the clipping rectangle. + * + * For speed, we should be transferring the font + * vectors into OpenGL display lists! + * + *--------------------------------------------------------- + */ + +void +grtoglFontText(text, font, size, rotate, pos, clip, obscure) + char *text; /* The text to be drawn */ + int font; /* Font to use from fontList */ + int size; /* Pixel size of the font */ + int rotate; /* Text rotation */ + Point *pos; /* Text base position */ + Rect *clip; /* Clipping area */ + LinkedRect *obscure; /* List of obscuring areas */ +{ + char *tptr; + Point *coffset; /* vector to next character */ + Rect *cbbox; + GLfloat fsize, matvals[16]; + FontChar *clist; + int cheight, baseline; + float tmp; + + /* Keep it simple for now---ignore clip and obscure */ + + glDisable(GL_BLEND); + glPushMatrix(); + glTranslated(pos->p_x, pos->p_y, 0); + glRotated(rotate, 0, 0, 1); + + /* Get label size */ + cbbox = &DBFontList[font]->mf_extents; + + fsize = (GLfloat)size / (GLfloat)cbbox->r_ytop; + glScalef(fsize, fsize, 1.0); + + /* Adjust to baseline */ + baseline = 0; + for (tptr = text; *tptr != '\0'; tptr++) + { + DBFontChar(font, *tptr, NULL, NULL, &cbbox); + if (cbbox->r_ybot < baseline) + baseline = cbbox->r_ybot; + } + glTranslated(0, -baseline, 0); + + for (tptr = text; *tptr != '\0'; tptr++) + { + DBFontChar(font, *tptr, &clist, &coffset, NULL); + grtoglDrawCharacter(clist, *tptr, size); + glTranslated(coffset->p_x, coffset->p_y, 0); + } + glPopMatrix(); +} + +#endif /* VECTOR_FONTS */ + +/*--------------------------------------------------------- + * grtoglPutText: + * (modified on SunPutText) + * + * This routine puts a chunk of text on the screen in the current + * color, size, etc. The caller must ensure that it fits on + * the screen -- no clipping is done except to the obscuring rectangle + * list and the clip rectangle. + * + * Results: + * none. + * + * Side Effects: + * The text is drawn on the screen. + * + *--------------------------------------------------------- + */ + +void +grtoglPutText (text, pos, clip, obscure) + char *text; /* The text to be drawn. */ + Point *pos; /* A point located at the leftmost point of + * the baseline for this string. + */ + Rect *clip; /* A rectangle to clip against */ + LinkedRect *obscure; /* A list of obscuring rectangles */ + +{ + Rect location; + Rect overlap; + Rect textrect; + LinkedRect *ob; + void grTOGLGeoSub(); + int i; + float tscale; + + GrTOGLTextSize(text, toglCurrent.fontSize, &textrect); + + location.r_xbot = pos->p_x + textrect.r_xbot; + location.r_xtop = pos->p_x + textrect.r_xtop; + location.r_ybot = pos->p_y + textrect.r_ybot; + location.r_ytop = pos->p_y + textrect.r_ytop; + + /* erase parts of the bitmap that are obscured */ + for (ob = obscure; ob != NULL; ob = ob->r_next) + { + if (GEO_TOUCH(&ob->r_r, &location)) + { + overlap = location; + GeoClip(&overlap, &ob->r_r); + grTOGLGeoSub(&location, &overlap); + } + } + + overlap = location; + GeoClip(&overlap, clip); + + /* copy the text to the color screen */ + if ((overlap.r_xbot < overlap.r_xtop)&&(overlap.r_ybot <= overlap.r_ytop)) + { + glScissor(overlap.r_xbot, overlap.r_ybot, overlap.r_xtop - overlap.r_xbot, + overlap.r_ytop - overlap.r_ybot); + glEnable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + glRasterPos2i(pos->p_x, pos->p_y); + glListBase(grXBases[(toglCurrent.fontSize == GR_TEXT_DEFAULT) ? + GR_TEXT_SMALL : toglCurrent.fontSize]); + glCallLists(strlen(text), GL_UNSIGNED_BYTE, (unsigned char *)text); + glDisable(GL_SCISSOR_TEST); + } +} + + +/* grTOGLGeoSub: + * return the tallest sub-rectangle of r not obscured by area + * area must be within r. + */ + +void +grTOGLGeoSub(r, area) +Rect *r; /* Rectangle to be subtracted from. */ +Rect *area; /* Area to be subtracted. */ + +{ + if (r->r_xbot == area->r_xbot) r->r_xbot = area->r_xtop; + else + if (r->r_xtop == area->r_xtop) r->r_xtop = area->r_xbot; + else + if (r->r_ybot <= area->r_ybot) r->r_ybot = area->r_ytop; + else + if (r->r_ytop == area->r_ytop) r->r_ytop = area->r_ybot; + else + r->r_xtop = area->r_xbot; +} diff --git a/graphics/grTOGL3.c.test b/graphics/grTOGL3.c.test new file mode 100644 index 00000000..7358147b --- /dev/null +++ b/graphics/grTOGL3.c.test @@ -0,0 +1,812 @@ +/* grTOGL3.c - + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * This file contains additional functions to manipulate an X window system + * color display. Included here are device-dependent routines to draw and + * erase text and draw a grid. + * + */ + +#include +#include + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/malloc.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "dbwind/dbwind.h" +#include "textio/textio.h" +#include "utils/signals.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "graphics/grTOGLInt.h" +#include "graphics/grTkCommon.h" +#include "database/fonts.h" + +extern Display *grXdpy; + +/* locals */ + +GLuint grXBases[4]; + + +/*--------------------------------------------------------- + * grtoglDrawGrid: + * grxDrawGrid adds a grid to the grid layer, using the current + * write mask and color. + * + * Results: + * TRUE is returned normally. However, if the grid gets too small + * to be useful, then nothing is drawn and FALSE is returned. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +bool +grtoglDrawGrid (prect, outline, clip) + Rect *prect; /* A rectangle that forms the template + * for the grid. Note: in order to maintain + * precision for the grid, the rectangle + * coordinates are specified in units of + * screen coordinates multiplied by SUBPIXEL. + */ + int outline; /* the outline style */ + Rect *clip; /* a clipping rectangle */ +{ + int xsize, ysize; + int x, y; + int xstart, ystart; + int snum, low, hi, shifted; + + xsize = prect->r_xtop - prect->r_xbot; + ysize = prect->r_ytop - prect->r_ybot; + if (!xsize || !ysize || GRID_TOO_SMALL(xsize, ysize)) + return FALSE; + + xstart = prect->r_xbot % xsize; + while (xstart < clip->r_xbot << SUBPIXELBITS) xstart += xsize; + ystart = prect->r_ybot % ysize; + while (ystart < clip->r_ybot << SUBPIXELBITS) ystart += ysize; + + grtoglSetLineStyle(outline); + + glBegin(GL_LINES); + + snum = 0; + low = clip->r_ybot; + hi = clip->r_ytop; + for (x = xstart; x < (clip->r_xtop+1) << SUBPIXELBITS; x += xsize) + { + shifted = x >> SUBPIXELBITS; + glVertex2i(shifted, low); + glVertex2i(shifted, hi); + snum++; + } + + snum = 0; + low = clip->r_xbot; + hi = clip->r_xtop; + for (y = ystart; y < (clip->r_ytop+1) << SUBPIXELBITS; y += ysize) + { + shifted = y >> SUBPIXELBITS; + glVertex2i(low, shifted); + glVertex2i(hi, shifted); + snum++; + } + glEnd(); + return TRUE; +} + + +/*--------------------------------------------------------- + * grtoglLoadFont + * This local routine transfers the X font bitmaps + * into OpenGL display lists for simple text + * rendering. + * + * Results: Success/Failure + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +bool +grtoglLoadFont() +{ + Font id; + unsigned int i; + + for (i = 0; i < 4; i++) { + id = Tk_FontId(grTkFonts[i]); + + grXBases[i] = glGenLists(256); + if (grXBases[i] == 0) { + TxError("Out of display lists!\n"); + return FALSE; + } + glXUseXFont(id, 0, 256, grXBases[i]); + } + return TRUE; +} + + +/*--------------------------------------------------------- + * grtoglSetCharSize: + * This local routine sets the character size in the display, + * if necessary. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +grtoglSetCharSize (size) + int size; /* Width of characters, in pixels (6 or 8). */ +{ + toglCurrent.fontSize = size; + switch (size) + { + case GR_TEXT_DEFAULT: + case GR_TEXT_SMALL: + toglCurrent.font = grSmallFont; + break; + case GR_TEXT_MEDIUM: + toglCurrent.font = grMediumFont; + break; + case GR_TEXT_LARGE: + toglCurrent.font = grLargeFont; + break; + case GR_TEXT_XLARGE: + toglCurrent.font = grXLargeFont; + break; + default: + TxError("%s%d\n", "grtoglSetCharSize: Unknown character size ", + size ); + break; + } +} + + +/* + * ---------------------------------------------------------------------------- + * GrTOGLTextSize -- + * + * Determine the size of a text string. + * + * Results: + * None. + * + * Side effects: + * A rectangle is filled in that is the size of the text in pixels. + * The origin (0, 0) of this rectangle is located on the baseline + * at the far left side of the string. + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLTextSize(text, size, r) + char *text; + int size; + Rect *r; +{ + Tk_FontMetrics overall; + Tk_Font font; + int width; + + switch (size) { + case GR_TEXT_DEFAULT: + case GR_TEXT_SMALL: + font = grSmallFont; + break; + case GR_TEXT_MEDIUM: + font = grMediumFont; + break; + case GR_TEXT_LARGE: + font = grLargeFont; + break; + case GR_TEXT_XLARGE: + font = grXLargeFont; + break; + default: + TxError("%s%d\n", "GrTOGLTextSize: Unknown character size ", + size ); + break; + } + if (font == NULL) return; + Tk_GetFontMetrics(font, &overall); + width = Tk_TextWidth(font, text, strlen(text)); + /* Hack alert! Tk_TextWidth returns values too small! */ + width = width + (width >> 4); + r->r_ytop = overall.ascent; + r->r_ybot = -overall.descent; + r->r_xtop = width; + r->r_xbot = 0; +} + +/* OpenGL backing store functions (now removed from the X11-based ones) */ + +void +grtoglFreeBackingStore(MagWindow *window) +{ + if (window->w_backingStore == (ClientData)NULL) return; + freeMagic(window->w_backingStore); + window->w_backingStore = (ClientData)NULL; +} + +void +grtoglCreateBackingStore(MagWindow *w) +{ + unsigned int width, height; + + /* ignore all windows other than layout */ + if (w->w_client != DBWclientID) return; + + /* deferred */ + if (w->w_grdata == NULL) return; + + width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + + if (w->w_backingStore != (ClientData)NULL) freeMagic(w->w_backingStore); + + w->w_backingStore = (ClientData)mallocMagic(width * height * 3); +} + +bool +grtoglGetBackingStore(MagWindow *w, Rect *area) +{ + unsigned int width, height; + int xbot, ybot; + int xoff, yoff; + Rect r; + + GEO_EXPAND(area, 1, &r); + GeoClip(&r, &(w->w_screenArea)); + + width = r.r_xtop - r.r_xbot; + height = r.r_ytop - r.r_ybot; + + xbot = r.r_xbot; + ybot = r.r_ybot; + + xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot; + yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop; + + glDrawBuffer(GL_FRONT); + glReadBuffer(GL_BACK); + glRasterPos2i((GLint)(xbot - xoff), (GLint)(ybot - yoff)); + glCopyPixels(xbot, ybot, width, height, GL_COLOR); + + return TRUE; +} + + +bool +grtoglxGetBackingStore(MagWindow *w, Rect *area) +{ + unsigned int width, height; + int ybot, y; + int xoff, yoff; + int swidth, sheight, srow; + int bpos; + Rect r; + + if ((GLvoid *)w->w_backingStore == NULL) + return FALSE; + + // Get width and height of the backing store + sheight = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + swidth = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + srow = swidth * 3; + + GEO_EXPAND(area, 1, &r); + GeoClip(&r, &(w->w_screenArea)); + + width = r.r_xtop - r.r_xbot; + height = r.r_ytop - r.r_ybot; + // ybot = grXtransY(w, r.r_ytop); + ybot = r.r_ybot; + + xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot; + yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop; + + bpos = ybot * srow + (3 * r.r_xbot); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glDrawBuffer(GL_FRONT); + for (y = ybot; y < ybot + height; y++) + { + // Remove next line once all math is correct. . . + if ((bpos + srow) > (srow * sheight)) break; + + glRasterPos2i((GLint)(r.r_xbot - xoff), (GLint)(y - yoff)); + glDrawPixels(width, 1, GL_RGB, GL_UNSIGNED_BYTE, + (const GLvoid *)(w->w_backingStore + bpos)); + bpos += srow; + } + + return TRUE; +} + +bool +grtoglScrollBackingStore(MagWindow *w, Point *shift) +{ + return TRUE; +} + +bool +grtoglxScrollBackingStore(MagWindow *w, Point *shift) +{ + unsigned int width, height; + int xorigin, yorigin, xshift, yshift, y, bpos, tpos, srow; + int swidth, sheight; + int memmax; + + if (w->w_backingStore == (ClientData)NULL) + return FALSE; + + swidth = width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + sheight = height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + srow = swidth * 3; + xorigin = 0; + yorigin = 0; + xshift = shift->p_x; + // yshift = -shift->p_y; + yshift = shift->p_y; + + if (xshift > 0) + width -= xshift; + else if (xshift < 0) + { + width += xshift; + xorigin = -xshift; + xshift = 0; + } + if (yshift > 0) + height -= yshift; + else if (yshift < 0) + { + height += yshift; + yorigin = -yshift; + yshift = 0; + } + + /* To do: shift data within the stream itself. . . */ + + /* Source stream position */ + bpos = yorigin * srow + 3 * xorigin; + /* Target stream position */ + tpos = yshift * srow + 3 * xshift; + + /* It's easier to do the whole memmove as a single block. */ + memmax = (width * height * 3) - ((tpos > bpos) ? tpos : bpos); + + + memmove((void *)(w->w_backingStore + tpos), + (void *)(w->w_backingStore + bpos), + memmax); + +// for (y = yorigin; y < yorigin + height; y++) +// { + // Remove next lines once all math is correct. . . +// if ((bpos + srow) > (srow * height)) break; +// if ((tpos + srow) > (srow * height)) break; + +// memmove((void *)(w->w_backingStore + tpos), +// (void *)(w->w_backingStore + bpos), width * 3); + +// if (y >= height) break; +// bpos += srow; +// tpos += srow; +// } + return TRUE; +} + +void +grtoglPutBackingStore(MagWindow *w, Rect *area) +{ + unsigned int width, height; + int ybot, xbot, xoff, yoff; + + width = area->r_xtop - area->r_xbot; + height = area->r_ytop - area->r_ybot; + + ybot = area->r_ybot; + xbot = area->r_xbot; + + xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot; + yoff = w->w_screenArea.r_ytop - w->w_allArea.r_ytop; + + glDrawBuffer(GL_BACK); + glReadBuffer(GL_FRONT); + glRasterPos2i((GLint)(xbot - xoff), (GLint)(ybot - yoff)); + glCopyPixels(xbot, ybot, width, height, GL_COLOR); +} + +void +grtoglxPutBackingStore(MagWindow *w, Rect *area) +{ + unsigned int width, height; + int y, ybot, xbot, xoff, yoff; + int swidth, sheight, srow; + int bpos; + + if ((GLvoid *)w->w_backingStore == NULL) return; + + if (w->w_flags & WIND_OBSCURED) + { + grtoglFreeBackingStore(w); + w->w_backingStore = (ClientData)NULL; + return; + } + + // Get width and height of the backing store area + + swidth = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + sheight = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + srow = swidth * 3; + + width = area->r_xtop - area->r_xbot; + height = area->r_ytop - area->r_ybot; + // ybot = grXtransY(w, area->r_ytop); + ybot = area->r_ybot; + xbot = area->r_xbot; + xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot; + yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop; + + if (GrPixelCorrect == 0) + { + height--; + width--; + xbot++; + } + + // OpenGL has no concept of a 2-dimensional arrangement to the + // data returned, or boundaries, so we have to enforce them. + + if (xbot < 0) + { + width += xbot; + xbot = 0; + } + if (ybot < 0) + { + height += ybot; + ybot = 0; + } + if (width > swidth) width = swidth; + + bpos = (ybot - yoff) * srow + 3 * (xbot - xoff); + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadBuffer(GL_FRONT); + for (y = ybot; y < ybot + height; y++) + { + // Remove next line once all math is correct. . . + if ((bpos + srow) > (srow * sheight)) break; + + glReadPixels(xbot, y, width, 1, + GL_RGB, GL_UNSIGNED_BYTE, + (GLvoid *)(w->w_backingStore + bpos)); + if (y >= sheight) break; + bpos += srow; + } +} + + +/* + * ---------------------------------------------------------------------------- + * GrTOGLReadPixel -- + * + * Read one pixel from the screen. + * + * Results: + * An integer containing the pixel's color. + * + * Side effects: + * none. + * + * ---------------------------------------------------------------------------- + */ + +int +GrTOGLReadPixel (w, x, y) + MagWindow *w; + int x,y; /* the location of a pixel in screen coords */ +{ + return 0; /* OpenGL has no such function, so return 0 */ +} + + +/* + * ---------------------------------------------------------------------------- + * GrTOGLBitBlt -- + * + * Copy information in bit block transfers. + * + * Results: + * None. + * + * Side effects: + * changes the screen. + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLBitBlt(r, p) + Rect *r; + Point *p; +{ + glCopyPixels(r->r_xbot, r->r_ybot, r->r_xtop - r->r_xbot + 1, + r->r_ytop - r->r_ybot + 1, GL_COLOR); +} + +#ifdef VECTOR_FONTS + +/* + *---------------------------------------------------------------------- + * + * Technically, there should be no self-intersecting polygons in outline + * fonts. However, decomposition of bezier curves into line segments + * may occasionally produce one, so it needs to be handled. + *---------------------------------------------------------------------- + */ + +void +myCombine(GLdouble coords[3], GLdouble *vertex_data[4], + GLfloat weight[4], GLdouble **outData, void *dataptr) +{ + /* This needs to be free'd at the end of gluTessEndPolygon()! */ + GLdouble *new = (GLdouble *)mallocMagic(2 * sizeof(GLdouble)); + new[0] = coords[0]; + new[1] = coords[1]; + *outData = new; + /* Diagnostic */ + TxError("Intersecting polygon in char \"%c\" at %g %g!\n", + *((char *)dataptr), coords[0], coords[1]); +} + +/* + *---------------------------------------------------------------------- + * Draw a text character + * This routine differs from grtoglFillPolygon() in that it uses the + * glu library to handle non-convex polygons as may appear in font + * outlines. + *---------------------------------------------------------------------- + */ + +void +grtoglDrawCharacter(clist, tc, pixsize) + FontChar *clist; + unsigned char tc; + int pixsize; +{ + Point *tp; + int np, nptotal; + int i, j; + static GLUtesselator *tess = NULL; + static GLdouble *v = NULL; + static int maxnp = 0; + FontChar *ccur; + + if (pixsize < 5) return; /* Label too small to be useful */ + + if (tess == NULL) + { + tess = gluNewTess(); + gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin); + gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv); + gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)glEnd); + gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)myCombine); + } + // Boundary-only does not look particularly good. . . + gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE); + + nptotal = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + nptotal += ccur->fc_numpoints; + + if (nptotal > maxnp) + { + if (v != NULL) freeMagic((char *)v); + maxnp = nptotal; + v = (GLdouble *)mallocMagic(nptotal * 3 * sizeof(GLdouble)); + } + + j = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + { + tp = ccur->fc_points; + np = ccur->fc_numpoints; + + for (i = 0; i < np; i++, j += 3) { + v[j] = tp[i].p_x; + v[j + 1] = tp[i].p_y; + v[j + 2] = 0; + } + } + + gluTessBeginPolygon(tess, (GLvoid *)(&tc)); + j = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + { + np = ccur->fc_numpoints; + gluTessBeginContour(tess); + for (i = 0; i < np; i++, j += 3) { + gluTessVertex(tess, &v[j], &v[j]); + } + gluTessEndContour(tess); + } + gluTessEndPolygon(tess); +} + +/*--------------------------------------------------------- + * grtoglFontText: + * + * This routine draws text from font vectors using the + * font vector routines in DBlabel.c. Text is clipped + * to the clipping rectangle. + * + * For speed, we should be transferring the font + * vectors into OpenGL display lists! + * + *--------------------------------------------------------- + */ + +void +grtoglFontText(text, font, size, rotate, pos, clip, obscure) + char *text; /* The text to be drawn */ + int font; /* Font to use from fontList */ + int size; /* Pixel size of the font */ + int rotate; /* Text rotation */ + Point *pos; /* Text base position */ + Rect *clip; /* Clipping area */ + LinkedRect *obscure; /* List of obscuring areas */ +{ + char *tptr; + Point *coffset; /* vector to next character */ + Rect *cbbox; + GLfloat fsize, matvals[16]; + FontChar *clist; + int cheight, baseline; + float tmp; + + /* Keep it simple for now---ignore clip and obscure */ + + glDisable(GL_BLEND); + glPushMatrix(); + glTranslated(pos->p_x, pos->p_y, 0); + glRotated(rotate, 0, 0, 1); + + /* Get label size */ + cbbox = &DBFontList[font]->mf_extents; + + fsize = (GLfloat)size / (GLfloat)cbbox->r_ytop; + glScalef(fsize, fsize, 1.0); + + /* Adjust to baseline */ + baseline = 0; + for (tptr = text; *tptr != '\0'; tptr++) + { + DBFontChar(font, *tptr, NULL, NULL, &cbbox); + if (cbbox->r_ybot < baseline) + baseline = cbbox->r_ybot; + } + glTranslated(0, -baseline, 0); + + for (tptr = text; *tptr != '\0'; tptr++) + { + DBFontChar(font, *tptr, &clist, &coffset, NULL); + grtoglDrawCharacter(clist, *tptr, size); + glTranslated(coffset->p_x, coffset->p_y, 0); + } + glPopMatrix(); +} + +#endif /* VECTOR_FONTS */ + +/*--------------------------------------------------------- + * grtoglPutText: + * (modified on SunPutText) + * + * This routine puts a chunk of text on the screen in the current + * color, size, etc. The caller must ensure that it fits on + * the screen -- no clipping is done except to the obscuring rectangle + * list and the clip rectangle. + * + * Results: + * none. + * + * Side Effects: + * The text is drawn on the screen. + * + *--------------------------------------------------------- + */ + +void +grtoglPutText (text, pos, clip, obscure) + char *text; /* The text to be drawn. */ + Point *pos; /* A point located at the leftmost point of + * the baseline for this string. + */ + Rect *clip; /* A rectangle to clip against */ + LinkedRect *obscure; /* A list of obscuring rectangles */ + +{ + Rect location; + Rect overlap; + Rect textrect; + LinkedRect *ob; + void grTOGLGeoSub(); + int i; + float tscale; + + GrTOGLTextSize(text, toglCurrent.fontSize, &textrect); + + location.r_xbot = pos->p_x + textrect.r_xbot; + location.r_xtop = pos->p_x + textrect.r_xtop; + location.r_ybot = pos->p_y + textrect.r_ybot; + location.r_ytop = pos->p_y + textrect.r_ytop; + + /* erase parts of the bitmap that are obscured */ + for (ob = obscure; ob != NULL; ob = ob->r_next) + { + if (GEO_TOUCH(&ob->r_r, &location)) + { + overlap = location; + GeoClip(&overlap, &ob->r_r); + grTOGLGeoSub(&location, &overlap); + } + } + + overlap = location; + GeoClip(&overlap, clip); + + /* copy the text to the color screen */ + if ((overlap.r_xbot < overlap.r_xtop)&&(overlap.r_ybot <= overlap.r_ytop)) + { + glScissor(overlap.r_xbot, overlap.r_ybot, overlap.r_xtop - overlap.r_xbot, + overlap.r_ytop - overlap.r_ybot); + glEnable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + glRasterPos2i(pos->p_x, pos->p_y); + glListBase(grXBases[(toglCurrent.fontSize == GR_TEXT_DEFAULT) ? + GR_TEXT_SMALL : toglCurrent.fontSize]); + glCallLists(strlen(text), GL_UNSIGNED_BYTE, (unsigned char *)text); + glDisable(GL_SCISSOR_TEST); + } +} + + +/* grTOGLGeoSub: + * return the tallest sub-rectangle of r not obscured by area + * area must be within r. + */ + +void +grTOGLGeoSub(r, area) +Rect *r; /* Rectangle to be subtracted from. */ +Rect *area; /* Area to be subtracted. */ + +{ + if (r->r_xbot == area->r_xbot) r->r_xbot = area->r_xtop; + else + if (r->r_xtop == area->r_xtop) r->r_xtop = area->r_xbot; + else + if (r->r_ybot <= area->r_ybot) r->r_ybot = area->r_ytop; + else + if (r->r_ytop == area->r_ytop) r->r_ytop = area->r_ybot; + else + r->r_xtop = area->r_xbot; +} diff --git a/graphics/grTOGL4.c b/graphics/grTOGL4.c new file mode 100644 index 00000000..327cc8cd --- /dev/null +++ b/graphics/grTOGL4.c @@ -0,0 +1,133 @@ +/* grTOGL4.c - + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * This file contains functions to manage the graphics tablet associated + * with the X display. + * + */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/magsgtty.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "graphics/grTkCommon.h" +#include "textio/txcommands.h" +#include "grTOGLInt.h" + +extern Display *grXdpy; + + +/*--------------------------------------------------------- + * GrTOGLDisableTablet: + * Turns off the cursor. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +GrTOGLDisableTablet () +{ +} + + +/*--------------------------------------------------------- + * GrTOGLEnableTablet: + * This routine enables the graphics tablet. + * + * Results: + * None. + * + * Side Effects: + * Simply turn on the crosshair. + *--------------------------------------------------------- + */ + +void +GrTOGLEnableTablet () +{ +} + + +/* + * ---------------------------------------------------------------------------- + * grtoglGetCursorPos: + * Read the cursor position in magic coordinates. + * + * Results: + * TRUE is returned if the coordinates were succesfully read, FALSE + * otherwise. + * + * Side effects: + * The parameter is filled in with the cursor position, in the form of + * a point in screen coordinates. + * ---------------------------------------------------------------------------- + */ + +bool +grtoglGetCursorPos (mw, p) + MagWindow *mw; /* window for which result is given */ + Point *p; /* point to be filled in with screen coordinates */ +{ + int x, y, x1, y1; + unsigned int buttons; + Window win1, win2; + + if (mw == (MagWindow *)NULL) mw = toglCurrent.mw; + + XQueryPointer(grXdpy, Tk_WindowId((Tk_Window)(mw->w_grdata)), + &win1, &win2, &x1, &y1, + &x, &y, &buttons); + + p->p_x = x; + p->p_y = grXtransY(mw, y); + + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * grtoglGetCursorRootPos: + * Read the cursor position in sreen root coordinates. + * + * Results: + * TRUE is returned if the coordinates were succesfully read, FALSE + * otherwise. + * + * Side effects: + * The parameter is filled in with the cursor position, in the form of + * a point in screen coordinates. + * ---------------------------------------------------------------------------- + */ + +bool +grtoglGetCursorRootPos (mw, p) + MagWindow *mw; /* window for which result is given */ + Point *p; /* point to be filled in with screen coordinates */ +{ + int x, y, x1, y1; + unsigned int buttons; + Window win1, win2; + + if (mw == (MagWindow *)NULL) mw = toglCurrent.mw; + + XQueryPointer(grXdpy, Tk_WindowId((Tk_Window)(mw->w_grdata)), + &win1, &win2, &x1, &y1, + &x, &y, &buttons); + + p->p_x = x1; + p->p_y = y1; + + return TRUE; +} diff --git a/graphics/grTOGL5.c b/graphics/grTOGL5.c new file mode 100644 index 00000000..edd9a9bf --- /dev/null +++ b/graphics/grTOGL5.c @@ -0,0 +1,209 @@ +/* grTOGL5.c - + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * Manipulate the programable cursor on the graphics display. + * + */ + +#include +#include + +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/styles.h" +#include "utils/hash.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/glyphs.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "grTkCommon.h" +#include "grTOGLInt.h" + +extern Display *grXdpy; +extern int grXscrn; +extern HashTable grTOGLWindowTable; + + +/* + * ---------------------------------------------------------------------------- + * GrTOGLDrawGlyph -- + * + * Draw one glyph on the display. + * + * Results: + * None. + * + * Side effects: + * Draws pixels. + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLDrawGlyph (gl, p) + GrGlyph *gl; /* A single glyph */ + Point *p; /* screen pos of lower left corner */ +{ + Rect bBox; + bool anyObscure; + LinkedRect *ob; + + GR_CHECK_LOCK(); + + /* We're going to change the graphics state without affecting */ + /* the standard color and mask saved values, so we had better */ + /* flush all rects & lines first. */ + GR_TOGL_FLUSH_BATCH(); + + bBox.r_ll = *p; + bBox.r_xtop = p->p_x + gl->gr_xsize - 1; + bBox.r_ytop = p->p_y + gl->gr_ysize - 1; + + anyObscure = FALSE; + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) { + if (GEO_TOUCH( &(ob->r_r), &bBox)) { + anyObscure = TRUE; + break; + } + } + if ((!anyObscure) && (GEO_SURROUND(&grCurClip, &bBox)) ) { + int *pixelp, x, y, thisp, lastp; + int color, red, green, blue, mask; + + /* no clipping, try to go quickly */ + pixelp = gl->gr_pixels; + thisp = -1; + for (y = 0; y < gl->gr_ysize; y++) { + int x1, y1; + + y1 = bBox.r_ybot + y; + for (x = 0; x < gl->gr_xsize; x++) { + lastp = thisp; + thisp = *pixelp++; + if (thisp != 0) + { + /* Note: mask has traditionally been 0-127 */ + if (thisp != lastp) { + if (lastp != -1) glEnd(); + + mask = GrStyleTable[thisp].mask << 1; + color = GrStyleTable[thisp].color; + GrGetColor(color, &red, &green, &blue); + glColor4ub((GLubyte)red, (GLubyte)green, (GLubyte)blue, + (GLubyte)mask); + glBegin(GL_POINTS); + } + x1 = bBox.r_xbot + x; + glVertex2i((GLint)x1, (GLint)y1); + } + } + } + if (lastp != -1) glEnd(); + } else { + /* do pixel by pixel clipping */ + int y, yloc; + + yloc = bBox.r_ybot; + for (y = 0; y < gl->gr_ysize; y++) { + int startx, endx; + if ( (yloc <= grCurClip.r_ytop) && (yloc >= grCurClip.r_ybot) ) { + int laststartx; + laststartx = bBox.r_xbot - 1; + for (startx = bBox.r_xbot; startx <= bBox.r_xtop; + startx = endx + 1) { + int *pixelp; + + startx = MAX(startx, grCurClip.r_xbot); + endx = MIN(bBox.r_xtop, grCurClip.r_xtop); + + if (anyObscure) { + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) { + if ( (ob->r_r.r_ybot <= yloc) && + (ob->r_r.r_ytop >= yloc) ) { + if (ob->r_r.r_xbot <= startx) + startx = MAX(startx, ob->r_r.r_xtop + 1); + else if (ob->r_r.r_xbot <= endx) + endx = MIN(endx, ob->r_r.r_xbot - 1); + } + } + } + + /* stop if we aren't advancing */ + if (startx == laststartx) break; + laststartx = startx; + if (startx > endx) continue; + + /* draw a section of this scan line */ + pixelp = &( gl->gr_pixels[y*gl->gr_xsize + + (startx - bBox.r_xbot)]); + for ( ; startx <= endx; startx++) { + int color, red, green, blue, mask; + if (*pixelp != 0) + { + mask = GrStyleTable[*pixelp].mask << 1; + color = GrStyleTable[*pixelp].color; + GrGetColor(color, &red, &green, &blue); + glColor4ub((GLubyte)red, (GLubyte)green, + (GLubyte)blue, (GLubyte)mask); + glBegin(GL_POINTS); + glVertex2i((GLint)startx, (GLint)yloc); + glEnd(); + } + pixelp++; + } + startx = endx + 1; + } + } + yloc++; + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * GrTOGLSetCursor: + * + * Make the cursor be a new pattern, as defined in the display styles file. + * + * Results: + * None. + * + * Side effects: + * When the cursor is turned back on it will take on the new pattern. + * ---------------------------------------------------------------------------- + */ + +void +GrTOGLSetCursor(cursorNum) + int cursorNum; /* The cursor number as defined in the display + * styles file. + */ +{ + HashEntry *entry; + HashSearch hs; + Tk_Window tkwind; + + if (cursorNum >= MAX_CURSORS) + { + TxError("No such cursor!\n"); + return; + } + + toglCurrent.cursor = grCursors[cursorNum]; + + HashStartSearch(&hs); + while (entry = HashNext(&grTOGLWindowTable,&hs)) + { + if (HashGetValue(entry)) + { + tkwind = (Tk_Window)entry->h_key.h_ptr; + Tk_DefineCursor(tkwind, toglCurrent.cursor); + } + } +} diff --git a/graphics/grTOGLInt.h b/graphics/grTOGLInt.h new file mode 100644 index 00000000..b9c66ede --- /dev/null +++ b/graphics/grTOGLInt.h @@ -0,0 +1,116 @@ +/* + * grTOGLInt.h -- + * + * Internal definitions for grTOGL[1..5].c. + * + * NOTE: In order for the these defs to work correctly, this file + * (grTOGLInt.h) must be included after all the Magic .h files and before + * the X11, OpenGL, and Tk/Tcl .h files. + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + */ + +#include "utils/magic.h" + +/* Constants + */ +#define M_WIDTH 1023 +#define M_HEIGHT 750 + +#define TOGL_BATCH_SIZE 10000 + +/* Current settings for X function parameters */ +typedef struct { + Tk_Font font; + Tk_Cursor cursor; + int fontSize; + int depth; + int maskmod; + Tk_Window window; + Window windowid; + MagWindow *mw; +} TOGL_CURRENT; + +#ifdef OGL_SERVER_SIDE_ONLY +typedef Rect TOGLRect; +#else + +/* Used for vertex arrays */ +typedef struct { + Point r_ll, r_ul, r_ur, r_lr; +} TOGLRect; + +#endif + +extern TOGL_CURRENT toglCurrent; + +extern bool grtoglGetCursorPos(); +extern bool grtoglGetCursorRootPos(); +extern bool grtoglDrawGrid(); +extern void GrTOGLEnableTablet(); +extern void GrTOGLDisableTablet(); +extern void GrTOGLSetCMap(); +extern void grtoglPutText(); +#ifdef VECTOR_FONTS +extern void grtoglFontText(); +#endif +extern void GrTOGLSetCursor(); +extern void GrTOGLTextSize(); +extern void GrTOGLDrawGlyph(); +extern void GrTOGLBitBlt(); +extern void NullBitBlt(); +extern int GrTOGLReadPixel(); +extern void grtoglSetLineStyle(); +extern void grtoglSetCharSize(); +extern void grtoglSetWMandC(); +extern void grtoglRectConvert(); +extern void grtoglFillPolygon(); + +extern void grtoglFreeBackingStore(); +extern void grtoglCreateBackingStore(); +extern bool grtoglGetBackingStore(); +extern bool grtoglScrollBackingStore(); +extern void grtoglPutBackingStore(); + +extern void grtoglDrawLine(); +extern void grtoglDrawLines(); +extern void grtoglFillRect(); +extern void grtoglFillRects(); + +extern int grtoglNbLines; +extern int grtoglNbDiagonal; +extern int grtoglNbRects; + +extern Rect grtoglLines[]; +extern Rect grtoglDiagonal[]; +extern TOGLRect grtoglRects[]; + +#define GR_TOGL_FLUSH_LINES() { \ + if (grtoglNbLines>0) { \ + grtoglDrawLines(grtoglLines, grtoglNbLines); \ + grtoglNbLines=0; \ + } \ +} + +#define GR_TOGL_FLUSH_DIAGONAL() { \ + if (grtoglNbDiagonal>0) { \ + glEnable(GL_LINE_SMOOTH); \ + grtoglDrawLines(grtoglDiagonal, grtoglNbDiagonal); \ + glDisable(GL_LINE_SMOOTH); \ + grtoglNbDiagonal=0; \ + } \ +} + +#define GR_TOGL_FLUSH_RECTS() { \ + if (grtoglNbRects>0) { \ + grtoglFillRects(grtoglRects, grtoglNbRects); \ + grtoglNbRects=0; \ + } \ +} + +#define GR_TOGL_FLUSH_BATCH() {GR_TOGL_FLUSH_LINES(); \ + GR_TOGL_FLUSH_DIAGONAL(); \ + GR_TOGL_FLUSH_RECTS();} + +/* Used by the wind3d window */ +extern void TOGLEventProc(); diff --git a/graphics/grText.c b/graphics/grText.c new file mode 100644 index 00000000..32076732 --- /dev/null +++ b/graphics/grText.c @@ -0,0 +1,375 @@ +/* grText.c - + * + * Contains functions for manipulating text that are not dependent + * upon the display type. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grText.c,v 1.3 2008/12/11 04:20:06 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "database/database.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "utils/utils.h" + +/*--------------------------------------------------------- + * + * GrFontText --- + * + * This routine is a glorified version of GrPutText + * that draws vector outline fonts according to + * information loaded and stored into the font lists + * (see DBLoadFont() in DBlabel.c). In addition to + * the properties used by GrPutText(), GrFontText() + * uses label scale, rotation, offset, and font. + * + *--------------------------------------------------------- + */ + +bool +GrFontText(str, style, p, font, size, rotate, clip) + char *str; /* The text to be drawn. */ + int style; /* Display style to use for the text */ + Point *p; /* Point of origin */ + int font; /* Font to use */ + int size; /* Scale */ + int rotate; /* Rotation (in degrees) */ + Rect *clip; /* Clipping area */ +{ + Rect nClip; + Point pstart; + + /* Fall back on X11 text if vectored text unavailable */ + if (!grFontTextPtr) + { + GrPutText(str, style, p, GEO_CENTER, GR_TEXT_MEDIUM, FALSE, clip, NULL); + return TRUE; + } + + nClip = *clip; + GeoClip(&nClip, &grCurClip); + + GR_CHECK_LOCK(); + if (!grDriverInformed) grInformDriver(); + + if (style >= 0) + (*grSetWMandCPtr)(GrStyleTable[style].mask, GrStyleTable[style].color); + + (*grFontTextPtr)(str, font, size, rotate, p, &nClip, grCurObscure); + + return TRUE; +} + +/* The following definition defines how much text is offset from + * its positioning point when it isn't centered. + */ + +#define TEXTOFFSET 5 + + +/*--------------------------------------------------------- + * GrPutText: + * This routine puts a chunk of text on the screen in the given + * color, size, and position. It is clipped to a rectangle. + * + * Results: + * True if the text was able to be displayed. + * + * Side Effects: + * The text is drawn on the screen at pos relative to p, using + * style (text can also be erased by passing a suitable style). + * The rectangle 'actual' is filled in with the actual location of + * the text on the screen (if actual is a non-null pointer). The + * text will be shrunk to a smaller font, if that will help it to + * fit into the clipping rectangle. + *--------------------------------------------------------- + */ + +bool +GrPutText(str, style, p, pos, size, adjust, clip, actual) + char *str; /* The text to be drawn. */ + int style; /* The style for drawing text; if -1 then + * the caller has already set the style + * and we don't have to. + */ + + Point *p; /* The point to align with */ + int pos; /* The alignment desired (GR_NORTH, + * GR_NORTHEAST, etc.) + */ + int size; /* The desired size of the text + * (such as GR_TEXT_MEDIUM). + */ + bool adjust; /* TRUE means adjust the text (either by + * sliding it around or using a smaller font) + * if that is necessary to make it fit into + * the clipping rectangle. FALSE means + * display the text exactly as instructed, + * clipping it if it doesn't fit. + */ + Rect *clip; /* A clipping rectangle for the text */ + Rect *actual; /* To be filled in with the location of the + * text. + */ +{ + Rect posR; + Point drawPoint; + int xpos, ypos, hangBelow; + Rect nClip; + + nClip = *clip; + GeoClip(&nClip, &grCurClip); + + GR_CHECK_LOCK(); + if (!grDriverInformed) grInformDriver(); + + if (actual != (Rect *) NULL) + { + actual->r_xbot = actual->r_ybot = 0; + actual->r_xtop = actual->r_ytop = 0; + } + + /* The following loop sees if the text will fit in the clipping + * area. If not, and shrinking is allowed, we try again and + * again with smaller sizes. + */ + + while (TRUE) + { + /* what portion of the screen is taken up by the text? */ + GrTextSize(str, size, &posR); + hangBelow = -posR.r_ybot; + + /* figure out where the text will go, including a border on 1 side */ + + switch (pos) /* horizontal centering */ + { + case GEO_NORTHWEST: + case GEO_WEST: + case GEO_SOUTHWEST: + xpos = p->p_x - TEXTOFFSET - posR.r_xtop; + break; + case GEO_NORTH: + case GEO_CENTER: + case GEO_SOUTH: + xpos = p->p_x - posR.r_xtop/2; + break; + case GEO_NORTHEAST: + case GEO_EAST: + case GEO_SOUTHEAST: + xpos = p->p_x + TEXTOFFSET; + break; + default: + TxError("Illegal position (%d) for text (internal error)\n", + pos); + return FALSE; + break; + } + switch (pos) /* vertical centering */ + { + case GEO_NORTH: + case GEO_NORTHEAST: + case GEO_NORTHWEST: + ypos = p->p_y + TEXTOFFSET; + break; + case GEO_CENTER: + case GEO_WEST: + case GEO_EAST: + ypos = p->p_y - (posR.r_ytop / 2); + break; + case GEO_SOUTH: + case GEO_SOUTHEAST: + case GEO_SOUTHWEST: + ypos = p->p_y - posR.r_ytop - TEXTOFFSET; + break; + } + + /* move area to screen coordinates */ + posR.r_xbot += xpos; + posR.r_xtop += xpos; + posR.r_ybot += ypos; + posR.r_ytop += ypos; + + /* will that area fit within the clipping rectangle? */ + if ( (posR.r_xtop <= nClip.r_xtop) && (posR.r_xbot >= nClip.r_xbot) && + (posR.r_ytop <= nClip.r_ytop) && (posR.r_ybot >= nClip.r_ybot) ) + { + /* it fits! */ + break; + } + + /* it doesn't fit, will sliding it be enough? */ + if (adjust) + { + if ( ((nClip.r_xtop-nClip.r_xbot) >= (posR.r_xtop - posR.r_xbot)) && + ((nClip.r_ytop - nClip.r_ybot) >= (posR.r_ytop - posR.r_ybot)) ) + { + /* it will fit */ + break; + } + + } + + /* Won't fit even with sliding, so shrink if possible. */ + if (adjust && (size > 0) ) + { + /* maybe shrinking it will help */ + size -= 1; + } + else break; + + } /* while */ + + + /* ASSERTION: We've shrunk things to the proper size at this point. */ + + /* Slide the text, if that is allowable and needed. We'll only + * slide the text if there's available space on one side and + * insufficient space on the other. + */ + + if (adjust) + { + int top, bottom, left, right; /* Space needed on each side. */ + int slide; + + right = posR.r_xtop - nClip.r_xtop; + left = nClip.r_xbot - posR.r_xbot; + top = posR.r_ytop - nClip.r_ytop; + bottom = nClip.r_ybot - posR.r_ybot; + + slide = 0; + if (right > 0) + { + if (left < 0) slide = MAX(-right, left); + } + else if (left > 0) slide = MIN(left, -right); + posR.r_xbot += slide; + posR.r_xtop += slide; + + slide = 0; + if (top > 0) + { + if (bottom < 0) slide = MAX(-top, bottom); + } + else if (bottom > 0) slide = MIN(bottom, -top); + posR.r_ybot += slide; + posR.r_ytop += slide; + } + + /* ASSERTION: By now the text is positioned properly. */ + + /* do all clipping within the grPutTextPtr routine */ + + (*grSetCharSizePtr)(size); + if (style >= 0) + (*grSetWMandCPtr)(GrStyleTable[style].mask, GrStyleTable[style].color); + + drawPoint.p_x = posR.r_xbot; + drawPoint.p_y = posR.r_ybot + hangBelow; + (*grPutTextPtr)(str, &drawPoint, &nClip, grCurObscure); + + if (actual != (Rect *) NULL) + *actual = posR; + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * GrLabelSize -- + * + * Determines the total size, in pixels, of a label. + * Used to compute how much to redisplay when a label changes. + * + * Results: + * None. + * + * Side effects: + * The parameter "area" is modified to contain the size, in pixels, + * of the given label, relative to its positioning point. This + * size includes just the text, and not any marker (e.g. cross + * displayed at the label position). + * + * ---------------------------------------------------------------------------- + */ + +void +GrLabelSize(text, pos, size, area) + char *text; /* Text of the label. */ + int pos; /* Position of the label relative + * to its positioning point. + */ + int size; /* Text size. */ + Rect *area; /* To be filled in with label size. */ +{ + int xoffset, yoffset; /* Offsets due to label position. */ + + GrTextSize(text, size, area); + + /* Now we now the text's size... but if it's positioned to one + * side of the point, we have to offset it. + */ + + switch (pos) /* Get x offset first. */ + { + case GEO_NORTHWEST: + case GEO_WEST: + case GEO_SOUTHWEST: + xoffset = - TEXTOFFSET - area->r_xtop; + break; + case GEO_NORTH: + case GEO_CENTER: + case GEO_SOUTH: + xoffset = - area->r_xtop/2; + break; + case GEO_NORTHEAST: + case GEO_EAST: + case GEO_SOUTHEAST: + xoffset = TEXTOFFSET; + break; + } + switch (pos) /* Now get y offset. */ + { + case GEO_NORTH: + case GEO_NORTHEAST: + case GEO_NORTHWEST: + yoffset = TEXTOFFSET; + break; + case GEO_CENTER: + case GEO_WEST: + case GEO_EAST: + yoffset = - area->r_ytop/2; + break; + case GEO_SOUTH: + case GEO_SOUTHEAST: + case GEO_SOUTHWEST: + yoffset = - area->r_ytop - TEXTOFFSET; + break; + } + + area->r_xbot += xoffset; + area->r_xtop += xoffset; + area->r_ybot += yoffset; + area->r_ytop += yoffset; +} diff --git a/graphics/grTk1.c b/graphics/grTk1.c new file mode 100644 index 00000000..76a595f3 --- /dev/null +++ b/graphics/grTk1.c @@ -0,0 +1,1794 @@ +/* grTk1.c + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * This file contains primitive functions to manipulate an X window system + * Included here are initialization and closing + * functions, and several utility routines used by the other X + * modules. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/main.h" +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/magsgtty.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "textio/textio.h" +#include "textio/txcommands.h" +#include "utils/signals.h" +#include "tiles/tile.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" +#include "utils/macros.h" +#include "grTkInt.h" +#include "utils/paths.h" +#include "graphics/grTkCommon.h" + +GR_CURRENT grCurrent = { + (Tk_Font)0, 0, 0, 0, 0, 0, + (MagWindow *)NULL +}; + +GR_DISPLAY grDisplay; + +GC grGCFill, grGCText, grGCDraw, grGCCopy, grGCGlyph, grGCStipple; +Visual *grVisual; +int grClass; +Colormap grXcmap; + +extern char *DBWStyleType; +unsigned long grPixels[256]; +unsigned long grPlanes[256]; +XColor colors[256*3]; /* Unique colors used by Magic */ + +Pixmap *grTkStipples; +HashTable grTkWindowTable; +/* locals */ + +typedef struct { + char dashlist[8]; + int dlen; +} LineStyle; + +static LineStyle LineStyleTab[256]; + +#define grMagicToXs(n) (DisplayHeight(grXdpy,grXscrn)-(n)) +#define grXsToMagic(n) (DisplayHeight(grXdpy,grXscrn)-(n)) + +extern bool GrTkInstalledCMap; + +/* machine-dependent constants - see below */ +#ifdef __APPLE__ +#define X_COLORMAP_BASE 128 +#define X_COLORMAP_RESERVED 4 +#else +#if defined(CYGWIN) +#define X_COLORMAP_BASE 128 +#define X_COLORMAP_RESERVED 0 +#else +#define X_COLORMAP_BASE 0 +#define X_COLORMAP_RESERVED 2 +#endif +#endif + +/* This is kind of a long story, and very kludgy, but the following + * things need to be defined as externals because of the way lint + * libraries are made by taking this module and changing all procedures + * names "Xxxx" to "Grxxx". The change is only done at the declaration + * of the procedure, so we need these declarations to handle uses + * of those names, which don't get modified. Check out the Makefile + * for details on this. + */ +extern void GrTkClose(), GrTkFlush(); +extern void GrTkDelete(),GrTkConfigure(),GrTkRaise(),GrTkLower(); +extern void GrTkLock(),GrTkUnlock(),GrTkIconUpdate(); +extern bool GrTkInit(); +extern bool GrTkEventPending(), GrTkCreate(), grtkGetCursorPos(); +extern int GrTkWindowId(); +extern char *GrTkWindowName(); + + +/*--------------------------------------------------------- + * grtkSetWMandC: + * This is a local routine that resets the value of the current + * write mask and color, if necessary. + * + * Results: None. + * + * Side Effects: None. + * + * Errors: None. + *--------------------------------------------------------- + */ + +void +grtkSetWMandC (mask, c) + long mask; /* New value for write mask */ + int c; /* New value for current color */ +{ + static int oldC = -1; + static int oldM = -1; + + c = grPixels[c]; + if(grDisplay.depth <= 8) { + mask = grPlanes[mask]; + if (mask == -65) mask = AllPlanes; + } + else { + mask = AllPlanes; + } + if (oldC == c && oldM == mask) return; + + GR_TK_FLUSH_BATCH(); + XSetPlaneMask(grXdpy,grGCFill,mask); + XSetPlaneMask(grXdpy,grGCDraw,mask); + XSetPlaneMask(grXdpy,grGCText,mask); + XSetForeground(grXdpy,grGCFill,c); + XSetForeground(grXdpy,grGCDraw,c); + XSetForeground(grXdpy,grGCText,c); + oldC = c; + oldM = mask; +} + + +/*--------------------------------------------------------- + * grtkSetLineStyle: + * This local routine sets the current line style. + * + * Results: None. + * + * Side Effects: + * A new line style is output to the display. + * + *--------------------------------------------------------- + */ + +void +grtkSetLineStyle (style) + int style; /* New stipple pattern for lines. */ +{ + static int oldStyle = -1; + LineStyle *linestyle; + int xstyle; + + style &= 0xFF; + if (style == oldStyle) return; + oldStyle = style; + GR_TK_FLUSH_BATCH(); + + switch (style) { + case 0xFF: + case 0x00: + xstyle = LineSolid; + break; + default: + xstyle = LineOnOffDash; + linestyle = &LineStyleTab[style]; + if (linestyle->dlen == 0) { + + /* translate style to an X11 dashlist */ + + char *e; + int cnt,offset,cur,new,curnew,i,match; + + e = linestyle->dashlist; + cnt = 0; + offset = 1; + cur = 0; + for (i = 7; i >= 0; i--) { + new = (style >> i) & 1; + curnew = (cur << 1) | new; + switch (curnew) { + case 0: + case 3: + cnt++; + break; + case 1: + if (cnt > 0) *e++ = cnt; else offset = 0; + cnt = 1; + break; + case 2: + *e++ = cnt; + cnt = 1; + break; + } + cur = new; + } + *e++ = cnt; + cnt = e - linestyle->dashlist; + if (offset) { + cur = e[0]; + for (i = 0; i < cnt-1; i++) e[i] = e[i+1]; + e[cnt-1] = cur; + } + match = 1; + do { + if (cnt % 2) break; + for (i = 0; i < cnt/2; i++) { + if (e[i] != e[cnt/2 + i]) match = 0; + } + if (match == 0) break; + cnt = cnt/2; + } while (match); + linestyle->dlen = cnt; + } + XSetDashes(grXdpy, grGCDraw, 0, + linestyle->dashlist, linestyle->dlen); + } +#ifdef OLD_XFREE + /* Bypass bug in XFree-2.x server */ + XSetLineAttributes(grXdpy, grGCDraw, 1, + xstyle, CapNotLast, JoinMiter); +#else + XSetLineAttributes(grXdpy, grGCDraw, 0, + xstyle, CapNotLast, JoinMiter); +#endif +} + + +/*--------------------------------------------------------- + * grtkSetSPattern: + * xSetSPattern associates a stipple pattern with a given + * stipple number. This is a local routine called from + * grStyle.c . + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +grtkSetSPattern (sttable, numstipples) + int **sttable; /* The table of patterns */ + int numstipples; /* Number of stipples */ +{ + Tk_Window tkwind; + Window xwid; + Pixmap p; + int i, x, y, pat; + + tkwind = Tk_MainWindow(magicinterp); + + /* This routine may be executed before Tk tells X11 to create the */ + /* main window. So if no X11 window ID is registered, force the */ + /* window creation and update. */ + + if (tkwind == 0 || Tk_WindowId(tkwind) == 0) + Tk_MakeWindowExist(tkwind); + xwid = Tk_WindowId(tkwind); + + grTkStipples = (Pixmap *)mallocMagic(numstipples * sizeof(Pixmap)); + for (i = 0; i < numstipples; i++) + { + p = Tk_GetPixmap(grXdpy, xwid, 8, 8, 1); + if (grGCStipple == NULL) { + /* grGCStipple = Tk_GetGC(tkwind, 0, 0); */ + grGCStipple = XCreateGC(grXdpy, p, 0, 0); + } + for (y = 0; y < 8; y++) { + pat = sttable[i][y]; + for (x = 0; x < 8; x++) { + XSetForeground(grXdpy, grGCStipple, pat & 1); + XDrawPoint(grXdpy, p, grGCStipple, x, y); + pat >>= 1; + } + } + grTkStipples[i] = p; + } +} + + +/*--------------------------------------------------------- + * grtkSetStipple: + * This routine sets the Xs current stipple number. + * + * Results: None. + * + * Side Effects: + * The current clipmask in the X is set to stipple, + * if it wasn't that already. + *--------------------------------------------------------- + */ + +void +grtkSetStipple (stipple) + int stipple; /* The stipple number to be used. */ +{ + static int oldStip = -1; + if (stipple == oldStip) return; + oldStip = stipple; + GR_TK_FLUSH_BATCH(); + if (stipple == 0 || stipple > grNumStipples) { + XSetFillStyle(grXdpy, grGCFill, FillSolid); + } else { + if (grTkStipples[stipple] == 0) MainExit(1); + XSetStipple(grXdpy, grGCFill, grTkStipples[stipple]); + XSetFillStyle(grXdpy, grGCFill, FillStippled); + } +} + + +/*--------------------------------------------------------- + * GrTkInit: + * + * GrTkInit initializes the graphics display. The depth + * of the display is queried from the server, and the + * "best" visual selected. The environment variable + * "MAGIC_COLOR" can override this choice. A colormap + * is selected based on the visual type, but will be + * filled in later. + * + * Results: TRUE if successful. + *--------------------------------------------------------- + */ + +#define visual_table_len 7 + +bool +GrTkInit(dispType) + char *dispType; +{ + int i,j; + XVisualInfo grvisual_info, *grvisual_get, grtemplate; + VisualID defpsvid; + int defpsindex = -1; + int gritems, gritems_list, grcolorCount; + bool rstatus; + Window xwind; + + const char *visual_type[] = { + "StaticGrey", + "GreyScale", + "StaticColor", + "PseudoColor", + "TrueColor", + "DirectColor", + "UNKNOWN" + }; + + int visual_table[visual_table_len]; + char *log_color, *env_str; + int color_base, color_reserved; + int status; + + grCurrent.window = Tk_MainWindow(magicinterp); + + if (grCurrent.window == NULL) + { + TxError("No Top-Level Tk window available. . . is Tk running?\n"); + return FALSE; + } + + grXdpy = Tk_Display(grCurrent.window); + grDisplay.depth = Tk_Depth(grCurrent.window); + grCurrent.windowid = Tk_WindowId(grCurrent.window); + grXscrn = Tk_ScreenNumber(grCurrent.window); + + /* The idea here is to first try allocating the required + * planes out of the default colormap. This is the kindest, + * gentlest thing to do because it doesn't cause all the other + * windows to go technicolor when the cursor is in a magic window. + * If this fails, we go ahead and allocate a colormap specifically + * for magic. The problem now is using this colormap in such + * a way that the other windows' colors get mangled the least. + * Unfortunately, doing this is X-server dependent. This is where + * the constants above come in. X_COLORMAP_BASE indicates + * which part of the colormap (assuming the number of planes + * required is less than the number of planes in the display) + * to fill in the colors magic requires. X_COLORMAP_RESERVED + * tells how many high-end colors the server won't let us touch; + * if we even try to query these colors, we get an X error. + * If, starting at X_COLORMAP_BASE, the number of colors required + * would push us into the top X_COLORMAP_RESERVED colors, then + * we won't be able to set all the colors the user wanted us + * to set. The top colors will remain identical to those + * in the default colormap. + */ + + grXcmap = XDefaultColormap(grXdpy,grXscrn); + + /* Discover properties of Server. */ + + grVisual = XDefaultVisual(grXdpy, grXscrn); + defpsvid = XVisualIDFromVisual(grVisual); + grtemplate.screen = grXscrn; + grtemplate.depth = 0; + grvisual_get = XGetVisualInfo(grXdpy, VisualScreenMask, &grtemplate, &gritems); + if (grvisual_get == NULL) + { + TxPrintf("Could not obtain Visual Info from Server %s. Will attempt default.\n", + getenv("DISPLAY")); + grDisplay.depth = 8; + grDisplay.colorCount = 1 << grDisplay.depth; + } + else + { + gritems_list = gritems; + for (gritems = 0; gritems < gritems_list; gritems++) + { + j = grvisual_get[gritems].class; + if ( j < 0 || j > 5) + { + TxPrintf("Unknown visual class index: %d\n", j); + j = 6; + } + if ((grvisual_get[gritems].class == 3) && + (grvisual_get[gritems].visualid == defpsvid)) + defpsindex = gritems; + } + + /* Unfortunately, the list returned by Xservers has classes in + * random order. Therefore, a search is needed to find a good + * choice. The only currently supported classes are PseudoColor + * at depth 8 and TrueColor at depth 15, 16, and 24. It is likely + * that TrueColor depths 8 through 32 will work, but these have + * not been tested. In addition, it has been discovered that some + * SUN systems "offer" more than one Pseudocolor at depth 8, but + * with differing colormap sizes. There is nothing about how to + * handle this in the X11 documentation, so the search below chooses + * the "first" class. The class with 256 colors seems preferable and + * works at present. The second Pseudocolor in the list gives a + * BatMatch reject from the server, so it is useless. Basing the + * selection on 256 colors might be effective, but might conflict in + * other cases... As usual X11 is just guesswork. At present the + * preferred order is: PseudoColor at 8, then TrueColor at 24, + * then TrueColor at 16, ... Unless this is overridden by the + * MAGIC_COLOR environment variable, which can be: bw, 8, 16, 24 + */ + + for (j = 0; j < visual_table_len; j++) + visual_table[j] = -1; + for (j = 0; j < gritems_list; j++) + { + if ((grvisual_get[j].class == 0) && (grvisual_get[j].depth == 8) + && (visual_table[1] == -1)) + visual_table[1] = j; /* StaticGrey */ + if ((grvisual_get[j].class == 1) && (grvisual_get[j].depth == 8) + && (visual_table[2] == -1)) + visual_table[2] = j; /* GreyScale */ + if ((grvisual_get[j].class == 3) && (grvisual_get[j].depth == 8) + && (visual_table[3] == -1)) + visual_table[3] = j; /* Pseudocolor */ + if ((grvisual_get[j].class == 4) && (grvisual_get[j].depth == 15) + && (visual_table[4] == -1)) + visual_table[4] = j; /* TrueColor */ + if ((grvisual_get[j].class == 4) && (grvisual_get[j].depth == 16) + && (visual_table[5] == -1)) + visual_table[5] = j; /* TrueColor */ + if ((grvisual_get[j].class == 4) && (grvisual_get[j].depth == 24) + && (visual_table[6] == -1)) + visual_table[6] = j; /* TrueColor */ + } + if (defpsindex != -1) + visual_table[3] = defpsindex; + log_color = getenv("MAGIC_COLOR"); + + if ((log_color == NULL) && (dispType != NULL) && (dispType[0] != 'X')) + log_color = dispType; + + /* Allow environment variables to override the colormap base and */ + /* number of reserved colors, as these depend on the terminal X */ + /* server, NOT on the machine running magic. */ + /* Note: ought to use strtod() in place of atoi(). */ + + env_str = getenv("X_COLORMAP_BASE"); + if (env_str != NULL) + color_base = (int)atoi(env_str); + else + color_base = X_COLORMAP_BASE; + env_str = getenv("X_COLORMAP_RESERVED"); + if (env_str != NULL) + color_reserved = (int)atoi(env_str); + else + color_reserved = X_COLORMAP_RESERVED; + + gritems = -1; + if (log_color != NULL) + { + if (strncmp(log_color, "8", 1) == 0) gritems = visual_table[3]; + if (strncmp(log_color, "15", 2) == 0) gritems = visual_table[4]; + if (strncmp(log_color, "16", 2) == 0) gritems = visual_table[5]; + if (strncmp(log_color, "24", 2) == 0) gritems = visual_table[6]; + if (gritems == -1) + { + printf("The visual mode %s is not available. Sorry.\n", log_color); + XFree(grvisual_get); + MainExit(1); + } + } + else + { + if (visual_table[3] != -1) gritems = visual_table[3]; + else if (visual_table[6] != -1) gritems = visual_table[6]; + else if (visual_table[5] != -1) gritems = visual_table[5]; + else if (visual_table[4] != -1) gritems = visual_table[4]; + } + if (gritems == -1) { + TxPrintf("None of TrueColor 15, 16 or 24, or PseudoColor 8 found. " + "Cannot initialize DISPLAY %s\n", getenv("DISPLAY")); + XFree(grvisual_get); + MainExit(1); + } + else + { + TxPrintf("Using %s, VisualID 0x%x depth %d\n", + visual_type[grvisual_get[gritems].class], + grvisual_get[gritems].visualid, + grvisual_get[gritems].depth); + } + grClass = grvisual_get[gritems].class; + grVisual = grvisual_get[gritems].visual; + grcolorCount = grvisual_get[gritems].colormap_size; + grDisplay.depth = grvisual_get[gritems].depth; + grDisplay.red_mask = grvisual_get[gritems].red_mask; + grDisplay.green_mask = grvisual_get[gritems].green_mask; + grDisplay.blue_mask = grvisual_get[gritems].blue_mask; + grDisplay.colorCount = grcolorCount; + } + XFree(grvisual_get); + grDisplay.planeCount = grDisplay.depth; + grDisplay.realColors = grDisplay.colorCount; + + if (grDisplay.planeCount == 8) + { + grDisplay.depth = 7; + grDisplay.planeCount = 7; /* This resets to old 7-plane mode */ + grDisplay.colorCount = 1 << (grDisplay.planeCount); + grDisplay.realColors = grDisplay.colorCount; + } + if (grDisplay.depth) + { + status = 0; + if (grClass != 4) + status= XAllocColorCells(grXdpy, grXcmap, TRUE, grDisplay.planes, + grDisplay.planeCount, &grDisplay.basepixel, 1); + if (status == 0) + { + /* + * Ok, we tried to be nice; now lets whack the default colormap + * and put in one of our own. + */ + + int actualColors = grcolorCount; + int usableColors = actualColors - color_reserved; + + /* Need the window ID. If grCurrent.window is not a valid window, */ + /* Use the default Tk main window. */ + + xwind = grCurrent.windowid; + if (xwind == 0) + { + xwind = Tk_WindowId(Tk_MainWindow(magicinterp)); + if (xwind == 0) + xwind = DefaultRootWindow(grXdpy); + } + + if (usableColors > 256) usableColors = 256; + if (grClass != 4) + TxPrintf("Unable to allocate %d planes in default colormap; " + "making a new one.\n", grDisplay.planeCount); +#ifdef MAGIC_WRAPPER + if (grClass == 3) GrTkInstalledCMap = TRUE; +#endif + if (grDisplay.planeCount <= 8) + { + grDisplay.basepixel = color_base; + grXcmap = XCreateColormap(grXdpy, xwind, grVisual, AllocAll); + } + else { + grDisplay.basepixel = 0; + grXcmap = XCreateColormap(grXdpy, xwind, grVisual, AllocNone); + } + + for (j = 0; j < grDisplay.planeCount; j++) grDisplay.planes[j] = 1 << j; + status = 1; + for (i = 0; i < usableColors; i++) colors[i].pixel = i; + XQueryColors(grXdpy, XDefaultColormap(grXdpy, grXscrn), + colors, usableColors); + if (grDisplay.planeCount <= 8) + XStoreColors(grXdpy, grXcmap, colors, usableColors); + grDisplay.realColors = (grDisplay.basepixel + + grDisplay.colorCount > usableColors) ? + usableColors - grDisplay.basepixel: grDisplay.colorCount; + if ((grDisplay.realColors != grDisplay.colorCount) + && (grDisplay.planeCount <= 8)) + { + TxPrintf("Only %d contiguous colors were available.\n", + grDisplay.realColors); + grDisplay.colorCount = grDisplay.realColors; + } + } + + if (grXcmap == 0 || status ==0) + { + TxError( "Tk/X11 setup: Unable to allocate %d planes\n", + grDisplay.planeCount); + MainExit(1); + } + } + + /* There is a non-obvious mapping between plane depth and the names */ + /* of the corresponding style and cmap filenames to load for each */ + /* display type. */ + + switch(grDisplay.depth) { + case 0: case 1: + grDStyleType = "bw"; + grCMapType = NULL; + /* This must be called here; because in B/W the colormap */ + /* is useless, it will not be called by the style file */ + /* load procedure. */ + GrTkSetCMap(); + break; + case 7: case 8: + grDStyleType = "7bit"; + grCMapType = "7bit"; + break; + default: + grDStyleType = "24bit"; + grCMapType = "24bit"; + break; + } + + /* Globally-accessed variables */ + grNumBitPlanes = grDisplay.depth; + grBitPlaneMask = (1 << grDisplay.depth) - 1; + + HashInit(&grTkWindowTable,8,HT_WORDKEYS); + rstatus = grTkLoadFont(); + return rstatus; +} + +/*--------------------------------------------------------- + * GrTkClose: + * + * Results: + * None. + * + * Side Effects: + * Frees fonts from the Tk font cache. + *--------------------------------------------------------- + */ + +void +GrTkClose () +{ + int i; + + if (grXdpy == NULL) return; + + XFreeGC(grXdpy, grGCStipple); + grGCStipple = NULL; + + /* Free Tk fonts from the font cache */ + grTkFreeFonts(); + + /* XCloseDisplay(grXdpy); */ /* Pop down Tk window but let Tcl/Tk */ + /* do XCloseDisplay() */ +} + + +/*--------------------------------------------------------- + * GrTkFlush: + * Flush output to display. + * + * Flushing is done automatically the next time input is read, + * so this procedure should not be used very often. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +GrTkFlush () +{ + GR_TK_FLUSH_BATCH(); +} + + +/* + * --------------------------------------------------------------------------- + * + * MagicEventProc --- + * + * Tk Event Handler + * + * Results: + * None. + * + * Side Effects: + * Calls functions in response to Tk events. + * + * --------------------------------------------------------------------------- + */ + +void +MagicEventProc(clientData, xevent) + ClientData clientData; + XEvent *xevent; +{ + HashEntry *entry; + Tk_Window wind = (Tk_Window)clientData; + MagWindow *mw; + unsigned char LocRedirect = TxInputRedirect; + + XKeyPressedEvent *KeyPressedEvent = (XKeyPressedEvent *) xevent; + KeySym keysym; + int nbytes; + + /* Keys and Buttons: Determine expansion of macros or redirect + * keys to the terminal/console. + */ + + switch (xevent->type) + { + case ButtonPress: + { + XButtonEvent *ButtonEvent = (XButtonEvent *) xevent; + int txbutton; + + switch (ButtonEvent->button) { + case Button1: + txbutton = TX_LEFT_BUTTON; + keysym = XK_Pointer_Button1; + break; + case Button2: + txbutton = TX_MIDDLE_BUTTON; + keysym = XK_Pointer_Button2; + break; + case Button3: + txbutton = TX_RIGHT_BUTTON; + keysym = XK_Pointer_Button3; + break; + case Button4: + txbutton = TX_BUTTON_4; + keysym = XK_Pointer_Button4; + break; + case Button5: + txbutton = TX_BUTTON_5; + keysym = XK_Pointer_Button5; + break; + } + nbytes = 0; + + entry = HashLookOnly(&grTkWindowTable, (char *)wind); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + + /* Hack---non-wrapper versions of magic have */ + /* fixed handlers for the frame. */ + if (mw && (mw->w_flags & WIND_SCROLLBARS)) + if (WindButtonInFrame(mw, ButtonEvent->x, + grXToMagic(ButtonEvent->y), + txbutton)) + break; + + goto keys_and_buttons; + } + break; + case KeyPress: + { + int keywstate, keymod, idx, idxmax; + char inChar[10]; + Tcl_Channel outChannel = Tcl_GetStdChannel(TCL_STDOUT); + + nbytes = XLookupString(KeyPressedEvent, inChar, sizeof(inChar), + &keysym, NULL); + + if (IsModifierKey(keysym)) break; /* Don't handle modifiers */ + + entry = HashLookOnly(&grTkWindowTable, (char *)wind); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + +keys_and_buttons: + grCurrent.window = wind; + grCurrent.windowid = Tk_WindowId(wind); + grCurrent.mw = mw; + + keymod = (LockMask | ControlMask | ShiftMask) + & KeyPressedEvent->state; + +#ifdef __APPLE__ + if (KeyPressedEvent->state & (Mod1Mask | Mod2Mask | + Mod3Mask | Mod4Mask | Mod5Mask)) + keymod |= Mod1Mask; +#else + keymod |= (Mod1Mask & KeyPressedEvent->state); +#endif + + if (nbytes == 0) + { + /* No ASCII equivalent */ + keywstate = (keymod << 16) | (keysym & 0xffff); + } + else if (!strncmp(XKeysymToString(keysym), "KP_", 3)) + { + /* keypad key (special case---would like to */ + /* differentiate between shift-KP-# and # itself) */ + keymod &= ~ShiftMask; + keywstate = (keymod << 16) | (keysym & 0xffff); + nbytes = 0; + } + else /* ASCII-valued character */ + { + if (!(keymod & (LockMask | Mod1Mask))) { + if (!(keymod & ControlMask)) + keymod &= ~ShiftMask; + else if (!(keymod & ShiftMask)) + keymod &= ~ControlMask; + } + } + + idxmax = (nbytes == 0) ? 1 : nbytes; + for (idx = 0; idx < idxmax; idx++) + { + if (xevent->type == KeyPress && inChar[idx] == 3) + { + /* Ctrl-C interrupt */ + if (SigInterruptPending) + MainExit(0); /* double Ctrl-C */ + else + sigOnInterrupt(0); /* Set InterruptPending */ + TxError("Tk Caught Ctrl-C Interrupt\n"); + TxFlush(); + /* MainExit(0); */ + break; + } + else if (nbytes > 0) + { + if ((keymod & ControlMask) && (inChar[idx] < 32)) + inChar[idx] += 'A' - 1; + + keywstate = (keymod << 16) | ((int)inChar[idx] & 0xff); + } + + /* Allow buttons to bypass the console and be */ + /* treated as macros. */ + + if (LocRedirect == TX_INPUT_REDIRECTED) + { + switch (keysym) + { + case XK_Pointer_Button1: + case XK_Pointer_Button2: + case XK_Pointer_Button3: + case XK_Pointer_Button4: + case XK_Pointer_Button5: + LocRedirect = TX_INPUT_NORMAL;; + break; + } + } + + if ((LocRedirect == TX_INPUT_REDIRECTED) && TxTkConsole) + { + Tcl_SavedResult state; + static char outstr[] = "::tkcon::Insert .text \"x\" "; + /* Translate Control-H to BackSpace */ + if ((keymod & ControlMask) && (keysym == XK_h)) + keysym = XK_BackSpace; + + switch (keysym) + { + case XK_Return: + TxSetPoint(KeyPressedEvent->x, + grXToMagic(KeyPressedEvent->y), + grCurrent.mw->w_wid); + TxInputRedirect = TX_INPUT_PROCESSING; + Tcl_EvalEx(consoleinterp, "::tkcon::Eval .text", + 19, 0); + TxInputRedirect = TX_INPUT_NORMAL; + TxSetPrompt('%'); + + Tcl_SaveResult(magicinterp, &state); + Tcl_EvalEx(magicinterp, "history event 0", 15, + 0); + MacroDefine(mw->w_client, (int)'.', + Tcl_GetStringResult(magicinterp), NULL, + FALSE); + Tcl_RestoreResult(magicinterp, &state); + break; + case XK_Up: + Tcl_EvalEx(consoleinterp, "::tckon::Event -1", + 17, 0); + break; + case XK_Down: + Tcl_EvalEx(consoleinterp, "::tckon::Event 1", + 16, 0); + break; + case XK_Left: + Tcl_EvalEx(consoleinterp, ".text mark set insert " + "insert-1c ; .text see insert", 50, 0); + break; + case XK_Right: + Tcl_EvalEx(consoleinterp, ".text mark set insert " + "insert+1c ; .text see insert", 50, 0); + break; + case XK_BackSpace: case XK_Delete: + Tcl_EvalEx(consoleinterp, ".text delete insert-1c ; " + ".text see insert", 41, 0); + break; + case XK_quotedbl: case XK_backslash: case XK_bracketleft: + outstr[23] = '\\'; + outstr[24] = inChar[idx]; + outstr[25] = '\"'; + Tcl_EvalEx(consoleinterp, outstr, 26, 0); + outstr[24] = '\"'; + outstr[25] = '\0'; + default: + outstr[23] = inChar[idx]; + Tcl_EvalEx(consoleinterp, outstr, 25, 0); + break; + } + } + else if (LocRedirect == TX_INPUT_REDIRECTED) + { + int tl; + if (TxBuffer == NULL) + { + TxBuffer = Tcl_Alloc(2); + *TxBuffer = '\0'; + tl = 0; + } + else + { + tl = strlen(TxBuffer); + TxBuffer = Tcl_Realloc(TxBuffer, tl + 2); + } + if (keysym == XK_BackSpace || keysym == XK_Delete) + { + if (tl >= 0) + { + if (tl > 0) + { + *(TxBuffer + tl - 1) = '\0'; + TxPrintf("\b"); + } + TxPrintf(" \b"); + TxFlushOut(); + } + } + else if (keysym == XK_Return) + { + *(TxBuffer + tl) = '\n'; + *(TxBuffer + tl + 1) = '\0'; + if (tl != 0) MacroDefine(mw->w_client, (int)'.', + TxBuffer, NULL, FALSE); + TxInputRedirect = TX_INPUT_NORMAL; + TxSetPoint(KeyPressedEvent->x, + grXToMagic(KeyPressedEvent->y), + grCurrent.mw->w_wid); + TxPrintf("\n"); + TxFlushOut(); + Tcl_NotifyChannel(Tcl_GetStdChannel(TCL_STDIN), + TCL_READABLE); + } + else + { + *(TxBuffer + tl) = *(inChar + idx); + *(TxBuffer + tl + 1) = '\0'; + TxPrintf("%c", *(inChar + idx)); + TxFlushOut(); + } + } + else + { + bool iMacro; + char *macroDef; + + macroDef = MacroRetrieve(mw->w_client, keywstate, &iMacro); + + /* Special handling: An imacro beginning with ':' */ + /* sets the prompt to ':' and moves to the next char. */ + + if (macroDef != NULL && *macroDef == ':' && iMacro) + { + if (TxTkConsole) + TxSetPrompt(':'); + else + { + TxPrintf("\b\b: "); + TxFlushOut(); + } + memmove(macroDef, macroDef + 1, strlen(macroDef + 1) + 1); + } + + macroDef = MacroSubstitute(macroDef, "%W", Tk_PathName(wind)); + + if (macroDef == NULL) + { + if (keysym != XK_Return) + { + char *vis = MacroName(keywstate); + TxError("Unknown macro or short command: '%s'\n", vis); + + freeMagic(vis); + } + /* Print Carriage Return & Put back Tcl/Tk prompt */ + TxParseString("", NULL, NULL); + } + else + { + int sl = strlen(macroDef); + if (iMacro) + { + /* Echo macro to interpreter, then redirect keys */ + + if (TxTkConsole) + { + char *outstring = Tcl_Alloc(sl + 20); + sprintf(outstring, ".text insert end \"%s\"", + macroDef); + Tcl_EvalEx(consoleinterp, outstring, -1, 0); + Tcl_Free(outstring); + } + else + { + TxBuffer = Tcl_Alloc(sl + 1); + strcpy(TxBuffer, macroDef); + TxPrintf("%s", macroDef); + TxFlushOut(); + } + TxInputRedirect = TX_INPUT_REDIRECTED; + } + else + { + /* TxParseString is defined by tcltk/tclmagic.c + * and calls Tcl_Eval(). + */ + + TxSetPoint(KeyPressedEvent->x, + grXToMagic(KeyPressedEvent->y), + grCurrent.mw->w_wid); + TxParseString(macroDef, NULL, NULL); + } + freeMagic(macroDef); + } + } + } + } + break; + case VisibilityNotify: + { + XVisibilityEvent *VisEvent = (XVisibilityEvent*) xevent; + + entry = HashLookOnly(&grTkWindowTable, (char *)wind); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + + switch(VisEvent->state) + { + case VisibilityUnobscured: + mw->w_flags &= ~WIND_OBSCURED; + if (mw->w_backingStore == (ClientData)NULL) + { + grtkCreateBackingStore(mw); + if (mw->w_backingStore != (ClientData)NULL) + { + WindAreaChanged(mw, &mw->w_allArea); + WindUpdate(); + } + } + break; + case VisibilityPartiallyObscured: + case VisibilityFullyObscured: + mw->w_flags |= WIND_OBSCURED; + break; + } + } + break; + case Expose: + { + XExposeEvent *ExposeEvent = (XExposeEvent*) xevent; + Rect screenRect; + + entry = HashLookOnly(&grTkWindowTable, (char *)wind); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + grCurrent.window = wind; + grCurrent.windowid = Tk_WindowId(wind); + grCurrent.mw = mw; + + screenRect.r_xbot = ExposeEvent->x; + screenRect.r_xtop = ExposeEvent->x+ExposeEvent->width; + screenRect.r_ytop = mw->w_allArea.r_ytop-ExposeEvent->y; + screenRect.r_ybot = mw->w_allArea.r_ytop - + (ExposeEvent->y + ExposeEvent->height); + + if (mw->w_backingStore != (ClientData)NULL) + { + Rect surface; + (*GrGetBackingStorePtr)(mw, &screenRect); + WindScreenToSurface(mw, &screenRect, &surface); + DBWHLRedrawPrepWindow(mw, &surface); + WindDrawBorder(mw, &screenRect); + } + else + WindAreaChanged(mw, &screenRect); + WindUpdate(); + } + break; + case ConfigureNotify: + { + XConfigureEvent *ConfigureEvent = (XConfigureEvent*) xevent; + Rect screenRect; + bool need_resize; + + entry = HashLookOnly(&grTkWindowTable, (char *)wind); + mw = (entry)?(MagWindow *)HashGetValue(entry):0; + grCurrent.window = wind; + grCurrent.windowid = Tk_WindowId(wind); + grCurrent.mw = mw; + + screenRect.r_xbot = ConfigureEvent->x; + screenRect.r_xtop = ConfigureEvent->x + ConfigureEvent->width; + screenRect.r_ytop = grXsToMagic(ConfigureEvent->y); + screenRect.r_ybot = grXsToMagic(ConfigureEvent->y+ + ConfigureEvent->height); + + need_resize = (screenRect.r_xbot != mw->w_screenArea.r_xbot || + screenRect.r_xtop != mw->w_screenArea.r_xtop || + screenRect.r_ybot != mw->w_screenArea.r_ybot || + screenRect.r_ytop != mw->w_screenArea.r_ytop); + + WindReframe(mw, &screenRect, FALSE, FALSE); + WindRedisplay(mw); + if (need_resize) grtkCreateBackingStore(mw); + } + break; + + case MapNotify: + case UnmapNotify: + case DestroyNotify: /* Do nothing */ + break; + + default: + TxError("Tk Event: Unknown (%d)\n", xevent->type); + TxFlush(); + break; + } +} + + +/*--------------------------------------------------------- + * x11SetDisplay: + * This routine sets the appropriate parameters so that + * Magic will work with the X display under Tcl/Tk. + * + * Under Xlib, all input events (mouse and keyboard) are + * sent to one queue which has to be polled to discover + * whether there is any input or not. To fit the Magic + * interrupt-driven input model, a helper process is + * spawned which reads and blocks on the event queue, + * sending SIGIO's to Magic when it detects input. The + * input read in the helper process is then sent to Magic + * via a communication pipe. + * + * Results: success / fail + * + * Side Effects: + *--------------------------------------------------------- + */ + +bool +x11SetDisplay (dispType, outFileName, mouseFileName) + char *dispType; + char *outFileName; + char *mouseFileName; +{ + char *planecount; + char *fullname; + FILE* f; + bool execFailed = FALSE; + int x, y, width, height; + + WindPackageType = WIND_X_WINDOWS; + TxInputRedirect = TX_INPUT_NORMAL; + grCursorType = "color"; + WindScrollBarWidth = 14; + + /* Set up the procedure values in the indirection table. */ + + GrLockPtr = GrTkLock; + GrUnlockPtr = GrTkUnlock; + GrInitPtr = GrTkInit; + GrClosePtr = GrTkClose; + GrSetCMapPtr = GrTkSetCMap; + + GrEnableTabletPtr = GrTkEnableTablet; + GrDisableTabletPtr = GrTkDisableTablet; + GrSetCursorPtr = GrTkSetCursor; + GrTextSizePtr = GrTkTextSize; + GrDrawGlyphPtr = GrTkDrawGlyph; + GrReadPixelPtr = GrTkReadPixel; + GrFlushPtr = GrTkFlush; + + GrCreateWindowPtr = GrTkCreate; + GrDeleteWindowPtr = GrTkDelete; + GrConfigureWindowPtr = GrTkConfigure; + GrOverWindowPtr = GrTkRaise; + GrUnderWindowPtr = GrTkLower; + GrUpdateIconPtr = GrTkIconUpdate; + GrEventPendingPtr = GrTkEventPending; + GrWindowIdPtr = GrTkWindowId; + GrWindowNamePtr = GrTkWindowName; + GrGetCursorPosPtr = grtkGetCursorPos; + GrGetCursorRootPosPtr = grtkGetCursorRootPos; + + /* local indirections */ + grSetSPatternPtr = grtkSetSPattern; + grPutTextPtr = grtkPutText; + grFontTextPtr = grtkFontText; + grDefineCursorPtr = grTkDefineCursor; + grFreeCursorPtr = grTkFreeCursors; + GrBitBltPtr = GrTkBitBlt; + grDrawGridPtr = grtkDrawGrid; + grDrawLinePtr = grtkDrawLine; + grSetWMandCPtr = grtkSetWMandC; + grFillRectPtr = grtkFillRect; + grSetStipplePtr = grtkSetStipple; + grSetLineStylePtr = grtkSetLineStyle; + grSetCharSizePtr = grtkSetCharSize; + grFillPolygonPtr = grtkFillPolygon; + + GrFreeBackingStorePtr = grtkFreeBackingStore; + GrCreateBackingStorePtr = grtkCreateBackingStore; + GrGetBackingStorePtr = grtkGetBackingStore; + GrPutBackingStorePtr = grtkPutBackingStore; + GrScrollBackingStorePtr = grtkScrollBackingStore; + + if (execFailed) { + TxError("Execution failed!\n"); + return FALSE; + } + + if (!GrTkInit(dispType)) { + return FALSE; + }; + + Tk_GetVRootGeometry(Tk_MainWindow(magicinterp), &x, &y, &width, &height); + GrScreenRect.r_xbot = x; + GrScreenRect.r_ybot = y; + GrScreenRect.r_xtop = x + width; + GrScreenRect.r_ytop = y + height; + + return Tk_MainWindow(magicinterp) ? TRUE : FALSE; +} + +extern void MakeWindowCommand(); + + +/* + * ---------------------------------------------------------------------------- + * + * GrTkCreate -- + * Create a new window under Tk. + * Bind Tk window to Magic Window w. + * + * Results: + * Success/Failure + * + * Side Effects: + * Window created and mapped. + * + * ---------------------------------------------------------------------------- + */ + +bool +GrTkCreate(w, name) + MagWindow *w; + char *name; +{ + Tk_Window tkwind, tktop; + Window wind; + static int WindowNumber = 0; + HashEntry *entry; + char *windowplace; + char windowname[10]; + int x = w->w_frameArea.r_xbot; + int y = grMagicToXs(w->w_frameArea.r_ytop); + int width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; + int height = w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; + unsigned long attribmask = CWBackPixel | CWBorderPixel; + XSetWindowAttributes grAttributes; + int grDepth; + + GrTkFlush(); + + WindSeparateRedisplay(w); + + sprintf(windowname, ".magic%d", WindowNumber + 1); + if (windowplace = XGetDefault(grXdpy, "magic", windowname)) + { + XParseGeometry(windowplace,&x,&y, + (unsigned int *)&width,(unsigned int *)&height); + w->w_frameArea.r_xbot = x; + w->w_frameArea.r_xtop = x+width; + w->w_frameArea.r_ytop = grXsToMagic(y); + w->w_frameArea.r_ybot = grXsToMagic(y+height); + WindReframe(w,&(w->w_frameArea),FALSE,FALSE); + } + grAttributes.background_pixel = WhitePixel(grXdpy,grXscrn); + grAttributes.border_pixel = BlackPixel(grXdpy,grXscrn); + + grDepth = grDisplay.depth; + if(grClass == 3) grDepth = 8; /* Needed since grDisplay.depth is reset + to 7 if Pseudocolor */ + + if (tktop = Tk_MainWindow(magicinterp)) + { + if (!WindowNumber) + { + /* To do: deal with grVisual---destroy and recreate */ + /* top frame if necessary */ + + if (Tk_WindowId(tktop) == 0) + { + Tk_SetWindowVisual(tktop, grVisual, grDepth, grXcmap); + } + else + { + /* The Top-level window has already been mapped. We can't mess */ + /* with it's visual. If the title is "wish", we'll assume that */ + /* nobody else is claiming it, and unmap it. */ + + if (!strcmp(Tk_Name(tktop), "wish")) Tk_UnmapWindow(tktop); + } + } + } + else + return 0; /* Failure condition */ + + /* Last parameter "" indicates a top-level window in the space of */ + /* the parent. */ + + if (name == NULL) + tkwind = Tk_CreateWindowFromPath(magicinterp, tktop, windowname, ""); + else + tkwind = Tk_CreateWindowFromPath(magicinterp, tktop, name, NULL); + + /* TxError("Created window named \"%s\", tkwind = 0x%x\n", + windowname, tkwind); */ + + if (tkwind != 0) + { + grCurrent.window = tkwind; + grCurrent.mw = w; + w->w_grdata = (ClientData) tkwind; + + entry = HashFind(&grTkWindowTable, (char *)tkwind); + HashSetValue(entry,w); + + /* set the window attributes, since Tk doesn't do this in the */ + /* Tk_CreateWindowFromPath() function. */ + + Tk_ChangeWindowAttributes(tkwind, attribmask, &grAttributes); + + /* ensure that the visual is what we wanted, if possible to change */ + + Tk_SetWindowVisual(tkwind, grVisual, grDepth, grXcmap); + + /* map the window, if necessary */ + + Tk_MapWindow(tkwind); + + /* use x, y, width, height to size and position the window */ + + Tk_GeometryRequest(tkwind, width, height); + /* Tk_MoveResizeWindow(tkwind, x, y, width, height); */ + + wind = Tk_WindowId(tkwind); + grCurrent.windowid = wind; + + if (!WindowNumber) + { + grGCFill = XCreateGC(grXdpy, wind, 0, 0); + grGCDraw = XCreateGC(grXdpy, wind, 0, 0); + grGCText = XCreateGC(grXdpy, wind, 0, 0); + grGCCopy = XCreateGC(grXdpy, wind, 0, 0); + grGCGlyph = XCreateGC(grXdpy, wind, 0, 0); + } + + XSetPlaneMask(grXdpy, grGCGlyph, AllPlanes); + Tk_DefineCursor(tkwind, grCurrent.cursor); + GrTkIconUpdate(w, w->w_caption); + + /*----------------------------------------------------------------------*/ + /* If we're using TkCon in a PseudoColor visual, we need to set the */ + /* console's colormap to match the magic window. TkCon need know */ + /* nothing about this action (i.e., don't call Tk_SetWindowColormap()). */ + /* Make a call to a routine to reassign colors to match magic's solid */ + /* colors. */ + /*----------------------------------------------------------------------*/ + + if (TxTkConsole && !WindowNumber) + { + Window parent, rret, *clist; + unsigned int iret; + + if (Tk_Visual(tktop) == Tk_Visual(tkwind)) + { + XQueryTree(grXdpy, Tk_WindowId(tktop), &rret, &parent, &clist, &iret); + + /* Overlay plane windows won't have the same visual in both the */ + /* console and the layout windows; in such case, there should */ + /* be no need to set the colormap. */ + + XSetWindowColormap(grXdpy, parent, grXcmap); + + if (clist != NULL) XFree(clist); + } + else + GrTkInstalledCMap = FALSE; + + Tcl_EvalEx(consoleinterp, "catch repaintconsole", 20, 0); + } + WindowNumber++; + + /* set up Tk event handler to start processing */ + + Tk_CreateEventHandler(tkwind, ExposureMask | StructureNotifyMask + | ButtonPressMask | KeyPressMask | VisibilityChangeMask, + (Tk_EventProc *)MagicEventProc, (ClientData) tkwind); + + /* set up commands to be passed expressly to this window */ + + MakeWindowCommand((name == NULL) ? windowname : name, w); + + /*--------------------------------------------------------------*/ + /* In a PseudoColor visual + GUI wrapper environment, we need */ + /* to make sure that the GUI window (layout's parent) has the */ + /* same colormap as the layout. Tk need know nothing about */ + /* this sleight-of-hand. */ + /*--------------------------------------------------------------*/ + + if ((grClass == 3) && !Tk_IsTopLevel(tkwind)) + { + Tk_Window tklayout = tkwind; + Window parent, rret, *clist; + unsigned int iret; + + while (!Tk_IsTopLevel(tklayout)) tklayout = Tk_Parent(tklayout); + XQueryTree(grXdpy, Tk_WindowId(tklayout), &rret, &parent, &clist, &iret); + + /* Avoid trying to set the colormap of a window with an */ + /* incompatible visual (see above). */ + + if (Tk_Visual(tklayout) == Tk_Visual(tkwind)) + { + XSetWindowColormap(grXdpy, parent, grXcmap); + Tk_SetWindowColormap(tklayout, grXcmap); + } + else + { + GrTkInstalledCMap = FALSE; + TxError("Warning: Cannot match colormap of wrapper to layout.\n"); + } + + if (clist != NULL) XFree(clist); + } + + /* Install the colormap in all associated windows, for pseudocolor */ + /* visuals, if required */ + + if (grClass == 3) XInstallColormap(grXdpy, grXcmap); + + return 1; + } + else + { + TxError("Could not open new Tk window\n"); + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTkDelete -- + * Destroy an X window. + * + * Results: + * None. + * + * Side effects: + * Window destroyed. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTkDelete(w) + MagWindow *w; +{ + Tk_Window xw; + HashEntry *entry; + + xw = (Tk_Window) w->w_grdata; + entry = HashLookOnly(&grTkWindowTable, (char *)xw); + HashSetValue(entry,NULL); + + Tcl_DeleteCommand(magicinterp, Tk_PathName(xw)); + + Tk_DestroyWindow(xw); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTkConfigure -- + * Resize/ Move an existing X window. + * + * Results: + * None. + * + * Side Effects: + * Window reconfigured to w->w_frameArea. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTkConfigure(w) + MagWindow *w; +{ + if (w->w_flags & WIND_OFFSCREEN) return; + + Tk_MoveResizeWindow((Tk_Window)w->w_grdata, + w->w_frameArea.r_xbot, grMagicToXs(w->w_frameArea.r_ytop), + w->w_frameArea.r_xtop - w->w_frameArea.r_xbot, + w->w_frameArea.r_ytop - w->w_frameArea.r_ybot); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTkRaise -- + * Raise a window to the top of the screen such that nothing + * obscures it. + * + * Results: + * None. + * + * Side Effects: + * Window raised. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTkRaise(w) + MagWindow *w; +{ + Tk_Window tkwind; + + if (w->w_flags & WIND_OFFSCREEN) return; + + tkwind = (Tk_Window)w->w_grdata; + Tk_RestackWindow(tkwind, Above, NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTkLower -- + * Lower a window below all other X windows. + * obscures it. + * + * Results: + * None. + * + * Side Effects: + * Window lowered. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTkLower(w) + MagWindow *w; +{ + Tk_Window tkwind; + + if (w->w_flags & WIND_OFFSCREEN) return; + + tkwind = (Tk_Window)w->w_grdata; + Tk_RestackWindow(tkwind, Below, NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTkLock -- + * Lock a window and set global variables "grCurrent.window" + * and "grCurrent.mw" to reference the locked window. + * + * Results: + * None. + * + * Side Effects: + * Window locked. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTkLock(w, flag) + MagWindow *w; + bool flag; +{ + + grSimpleLock(w, flag); + if ( w != GR_LOCK_SCREEN ) + { + grCurrent.mw = w; + if (w->w_flags & WIND_OFFSCREEN) + { + grCurrent.window = NULL; + grCurrent.windowid = (Pixmap) w->w_grdata; + } + else + { + grCurrent.window = (Tk_Window) w->w_grdata; + grCurrent.windowid = Tk_WindowId(grCurrent.window); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * GrTkUnlock -- + * Unlock a window, flushing stuff out to the display. + * + * Results: + * None. + * + * Side Effects: + * Window unlocked. + * Display update. + * + * ---------------------------------------------------------------------------- + */ + +void +GrTkUnlock(w) + MagWindow *w; +{ + GR_TK_FLUSH_BATCH(); + grSimpleUnlock(w); +} + + +/* + *------------------------------------------------------------------------- + * GrTkEventPending -- check for pending graphics events. + * Here we use the X11 check for window events, because Tcl/Tk doesn't + * allows peeking into its event queue without executing whatever is + * in the queue. + * + * Results: + * TRUE if an event is in the event queue. + * + * Side effects: + * Hopefully none (put back the event!) + * + *------------------------------------------------------------------------- + */ + +bool +GrTkEventPending() +{ + Tk_Window tkwind = grCurrent.window; + Window wind = grCurrent.windowid; + XEvent genEvent; + bool retval; + + if (wind == 0) return FALSE; + + retval = XCheckWindowEvent(grXdpy, wind, ExposureMask + | StructureNotifyMask | ButtonPressMask + | KeyPressMask, &genEvent); + if (retval) XPutBackEvent(grXdpy, &genEvent); + return retval; +} + +/* + *------------------------------------------------------------------------- + * + * GrTkIconUpdate -- updates the icon text with the window script + * + * Results: none + * + * Side Effects: changes the icon text + * + *------------------------------------------------------------------------- + */ + +void +GrTkIconUpdate(w, text) /* See Blt code */ + MagWindow *w; + char *text; +{ + Tk_Window tkwind; + Window wind; + XClassHint class; + char *brack; + + if (w->w_flags & WIND_OFFSCREEN) return; + + tkwind = (Tk_Window)(w->w_grdata); + if (tkwind == NULL) { + tkwind = Tk_MainWindow(magicinterp); + if (tkwind == NULL) return; + } + wind = Tk_WindowId(tkwind); + if (wind == 0) return; + + class.res_name = "magic"; + class.res_class = "magic"; + + XSetClassHint( grXdpy, wind, &class); + if (brack = strchr(text,'[')) + { + brack--; + *brack = 0; + XSetIconName(grXdpy,wind,text); + XStoreName(grXdpy,wind,text); + *brack = ' '; + return; + } + if (brack = strrchr(text,' ')) text = brack+1; + XSetIconName(grXdpy,wind,text); + XStoreName(grXdpy,wind,text); +} + +/* + *------------------------------------------------------------------------- + * GrTkWindowId -- + * Get magic's ID number from the indicated MagWindow structure + * + * Results: + * The window ID number + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ + +int +GrTkWindowId(tkname) + char *tkname; +{ + Tk_Window tkwind; + MagWindow *mw; + HashEntry *entry; + int id = 0; + + tkwind = Tk_NameToWindow(magicinterp, tkname, Tk_MainWindow(magicinterp)); + if (tkwind != NULL) + { + entry = HashLookOnly(&grTkWindowTable, (char *)tkwind); + mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0; + if (mw) id = mw->w_wid; + } + return id; +} + diff --git a/graphics/grTk2.c b/graphics/grTk2.c new file mode 100644 index 00000000..6574be95 --- /dev/null +++ b/graphics/grTk2.c @@ -0,0 +1,307 @@ +/* grTk2.c - + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * This file contains additional functions to manipulate an X + * color display. Included here are rectangle drawing and color map + * loading. + */ + +#include +#include +char *getenv(); +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/glyphs.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "grTkInt.h" + +extern unsigned long grPixels[256]; +extern unsigned long grPlanes[256]; +extern XColor colors[256 * 3]; +extern Colormap grXcmap; + + +/*--------------------------------------------------------------------- + * GrXSetCMap: + * + * Results: None. + * + * Side Effects: + * The values in the color map are set from the default colormap + * table (see grCMap.c). X color cells are allocated if this + * display has more than 1 plane. + * + *--------------------------------------------------------------------- + */ + +void +GrTkSetCMap() +{ + int i,j; + int red, green, blue; + int red_size, green_size, blue_size; + int red_shift, green_shift, blue_shift; + unsigned long grCompleteMask; + + /* grCompleteMask is a mask of all the planes not used by this + * technology. It is OR'd in with the mask that magic supplies + * to ensure that unused bits of the pixel are cleared. + */ + + if (grDisplay.planeCount > 8) { + grCompleteMask = 0; + if (grDisplay.planeCount == 16) + { + red_size = 5; + green_size = 6; + blue_size = 5; + } + else if (grDisplay.planeCount == 15) + { + red_size = 5; + green_size = 5; + blue_size = 5; + } + else { + red_size = 8; + green_size = 8; + blue_size = 8; + } + red_shift = green_size + blue_size; + green_shift = blue_size; + if ((grDisplay.planeCount == 24) && (grDisplay.red_mask == 0xff)) + { + /* this is SUN Solaris doing it backwards: BGR */ + red_shift = 0; + green_shift = red_size; + blue_shift = green_size + red_size; + } + + /* DANGER! Modify the code below with care: gcc 2.7.2 generates bad */ + /* code if the masks are not used as below. */ + + for (i = 0; i < grDisplay.colorCount; i++) + { + if (!(GrGetColor(i, &red, &green, &blue))) break; + + if ((grDisplay.planeCount == 16) || (grDisplay.planeCount ==15)) + { + grPixels[i] = (long)((red >> (8 - red_size)) + << (green_size + blue_size)) & grDisplay.red_mask; /* red */ + grPixels[i] |= (long)((green >> (8 - green_size)) + << blue_size) & grDisplay.green_mask; /* green */ + grPixels[i] |= (long)(blue >> (8 - blue_size)) + & grDisplay.blue_mask; /* blue */ + } + else if ((grDisplay.planeCount == 24) && (grDisplay.red_mask == 0xff)) + { + /* this is SUN Solaris doing it backwards: BGR */ + grPixels[i] = (long)(red & grDisplay.red_mask); + /* here is where gcc really goes wrong (sign extends) */ + grPixels[i] |= (long)((green << green_shift) & grDisplay.green_mask); + grPixels[i] |= (long)((blue << blue_shift) & grDisplay.blue_mask); + } + else { + grPixels[i] = (long)((red << red_shift) & grDisplay.red_mask); + grPixels[i] |= (long)((green << green_shift) & grDisplay.green_mask); + grPixels[i] |= (long)(blue & grDisplay.blue_mask); + } + } + + for (i = 0; i < grDisplay.planeCount; i++) + { + grDisplay.planes[i] = 1 << i; + grPlanes[i] = 0; + for (j = 0; j != grDisplay.planeCount; j++) + if (i & (1 << j)) + { + grPlanes[i] |= grDisplay.planes[j]; + } + } + } + else /* grDisplay.planeCount <= 8 */ + { + grCompleteMask = 0; + for (i=0; i < grDisplay.planeCount; i++) + { + grCompleteMask |= grDisplay.planes[i]; + } + grCompleteMask = AllPlanes & ~grCompleteMask; + + for (i = 0; i < grDisplay.colorCount; i++) + { + grPixels[i] = grDisplay.basepixel; + grPlanes[i] = grCompleteMask; + for (j = 0; j != grDisplay.planeCount; j++) + if (i & (1 << j)) + { + grPixels[i] |= grDisplay.planes[j]; + grPlanes[i] |= grDisplay.planes[j]; + } + } + } + + if (grDisplay.depth) + { + for (i = 0; i < grDisplay.realColors; i++) + { + if (!(GrGetColor(i, &red, &green, &blue))) break; + colors[i].pixel = grPixels[i]; + colors[i].red = (unsigned short)(red << 8); + colors[i].green = (unsigned short)(green << 8); + colors[i].blue = (unsigned short)(blue << 8); + colors[i].flags = DoRed | DoGreen | DoBlue; + } + if (grDisplay.planeCount <= 8) + { + XStoreColors(grXdpy, grXcmap, colors, grDisplay.realColors); + } + } + else + { + grPixels[0] = WhitePixel(grXdpy,grXscrn); + grPixels[1] = BlackPixel(grXdpy,grXscrn); + grPlanes[0] = 0; + grPlanes[1] = AllPlanes; + } +} + +XSegment grtkLines[TK_BATCH_SIZE]; +int grtkNbLines=0; +XRectangle grtkRects[TK_BATCH_SIZE]; +int grtkNbRects=0; + + +/*--------------------------------------------------------- + * grtkDrawLines: + * This routine draws a batch of lines. + * + * Results: None. + * + * Side Effects: + * Draw a bunch of lines. + *--------------------------------------------------------- + */ + +void +grtkDrawLines(lines, nb) + XSegment lines[]; + int nb; +{ + XDrawSegments(grXdpy, grCurrent.windowid, grGCDraw, + lines, nb); +} + + +/*--------------------------------------------------------- + * grtkDrawLine: + * This routine draws a line. + * + * Results: None. + * + * Side Effects: + * Draw a line for (x1, y1) to (x2, y2) inclusive. + *--------------------------------------------------------- + */ + +void +grtkDrawLine (x1, y1, x2, y2) + int x1, y1; /* Screen coordinates of first point. */ + int x2, y2; /* Screen coordinates of second point. */ +{ + if (grtkNbLines == TK_BATCH_SIZE) GR_TK_FLUSH_LINES(); + grtkLines[grtkNbLines].x1 = x1; + grtkLines[grtkNbLines].y1 = grMagicToX(y1); + grtkLines[grtkNbLines].x2 = x2; + grtkLines[grtkNbLines].y2 = grMagicToX(y2); + + grtkNbLines++; +} + + +/*--------------------------------------------------------- + * grtkFillRects: + * This routine draws a bunch of solid rectangles. + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +grtkFillRects(rects, nb) + XRectangle rects[]; + int nb; +{ + XFillRectangles(grXdpy, grCurrent.windowid, grGCFill, rects, nb); +} + + +/*--------------------------------------------------------- + * grtkFillRect: + * This routine draws a solid rectangle. + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +grtkFillRect(r) + Rect *r; /* Address of a rectangle in screen + * coordinates. + */ +{ + if (grtkNbRects == TK_BATCH_SIZE) GR_TK_FLUSH_RECTS(); + grtkRects[grtkNbRects].x = r->r_xbot; + grtkRects[grtkNbRects].y = grMagicToX(r->r_ytop); + grtkRects[grtkNbRects].width = r->r_xtop - r->r_xbot + 1; + grtkRects[grtkNbRects].height = r->r_ytop - r->r_ybot + 1; + + grtkNbRects++; + +} + +/* + *--------------------------------------------------------- + * + * grtkFillPolygon: + * This routine draws a solid polygon + * + * Results: None. + * + * Side Effects: + * Drawing. + * + *--------------------------------------------------------- + */ + +void +grtkFillPolygon(tp, np) + Point *tp; + int np; +{ + XPoint xp[5]; + int i; + + for (i = 0; i < np; i++) + { + xp[i].x = tp[i].p_x; + xp[i].y = grMagicToX(tp[i].p_y); + } + XFillPolygon(grXdpy, grCurrent.windowid, grGCFill, xp, np, + Convex, CoordModeOrigin); +} + diff --git a/graphics/grTk3.c b/graphics/grTk3.c new file mode 100644 index 00000000..5bfba54c --- /dev/null +++ b/graphics/grTk3.c @@ -0,0 +1,556 @@ +/* grTk3.c - + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * This file contains additional functions to manipulate an X window system + * color display. Included here are device-dependent routines to draw and + * erase text and draw a grid. + * + */ + +#include +#include +#include + +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "textio/textio.h" +#include "utils/signals.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "graphics/grTkInt.h" +#include "graphics/grTkCommon.h" +#include "database/fonts.h" + + +/*--------------------------------------------------------- + * grtkDrawGrid: + * grxDrawGrid adds a grid to the grid layer, using the current + * write mask and color. + * + * Results: + * TRUE is returned normally. However, if the grid gets too small + * to be useful, then nothing is drawn and FALSE is returned. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +#define GR_NUM_GRIDS 64 + +bool +grtkDrawGrid (prect, outline, clip) + Rect *prect; /* A rectangle that forms the template + * for the grid. Note: in order to maintain + * precision for the grid, the rectangle + * coordinates are specified in units of + * screen coordinates multiplied by SUBPIXEL. + */ + int outline; /* the outline style */ + Rect *clip; /* a clipping rectangle */ +{ + int xsize, ysize; + int x, y; + int xstart, ystart; + XSegment seg[GR_NUM_GRIDS]; + int snum, low, hi, shifted; + + xsize = prect->r_xtop - prect->r_xbot; + ysize = prect->r_ytop - prect->r_ybot; + if (!xsize || !ysize || GRID_TOO_SMALL(xsize, ysize)) + return FALSE; + + xstart = prect->r_xbot % xsize; + while (xstart < clip->r_xbot << SUBPIXELBITS) xstart += xsize; + ystart = prect->r_ybot % ysize; + while (ystart < clip->r_ybot << SUBPIXELBITS) ystart += ysize; + + grtkSetLineStyle(outline); + + snum = 0; + low = grMagicToX(clip->r_ybot); + hi = grMagicToX(clip->r_ytop); + for (x = xstart; x < (clip->r_xtop + 1) << SUBPIXELBITS; x += xsize) + { + if (snum == GR_NUM_GRIDS) + { + XDrawSegments(grXdpy, grCurrent.windowid, grGCDraw, seg, snum); + snum = 0; + } + shifted = x >> SUBPIXELBITS; + seg[snum].x1 = shifted; + seg[snum].y1 = low; + seg[snum].x2 = shifted; + seg[snum].y2 = hi; + snum++; + } + XDrawSegments(grXdpy, grCurrent.windowid, grGCDraw, seg, snum); + + snum = 0; + low = clip->r_xbot; + hi = clip->r_xtop; + for (y = ystart; y < (clip->r_ytop + 1) << SUBPIXELBITS; y += ysize) + { + if (snum == GR_NUM_GRIDS) + { + XDrawSegments(grXdpy, grCurrent.windowid, grGCDraw, seg, snum); + snum = 0; + } + shifted = grMagicToX(y >> SUBPIXELBITS); + seg[snum].x1 = low; + seg[snum].y1 = shifted; + seg[snum].x2 = hi; + seg[snum].y2 = shifted; + snum++; + } + XDrawSegments(grXdpy, grCurrent.windowid, grGCDraw, seg, snum); + return TRUE; +} + + +/*--------------------------------------------------------- + * grtkSetCharSize: + * This local routine sets the character size in the display, + * if necessary. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +grtkSetCharSize (size) + int size; /* Width of characters, in pixels (6 or 8). */ +{ + grCurrent.fontSize = size; + switch (size) + { + case GR_TEXT_DEFAULT: + case GR_TEXT_SMALL: + grCurrent.font = grSmallFont; + break; + case GR_TEXT_MEDIUM: + grCurrent.font = grMediumFont; + break; + case GR_TEXT_LARGE: + grCurrent.font = grLargeFont; + break; + case GR_TEXT_XLARGE: + grCurrent.font = grXLargeFont; + break; + default: + TxError("%s%d\n", "grtkSetCharSize: Unknown character size ", + size ); + break; + } +} + + +/* + * ---------------------------------------------------------------------------- + * GrTkTextSize -- + * + * Determine the size of a text string. + * + * Results: + * None. + * + * Side effects: + * A rectangle is filled in that is the size of the text in pixels. + * The origin (0, 0) of this rectangle is located on the baseline + * at the far left side of the string. + * ---------------------------------------------------------------------------- + */ + +void +GrTkTextSize(text, size, r) + char *text; + int size; + Rect *r; +{ + Tk_FontMetrics overall; + Tk_Font font; + int width; + + switch (size) { + case GR_TEXT_DEFAULT: + case GR_TEXT_SMALL: + font = grSmallFont; + break; + case GR_TEXT_MEDIUM: + font = grMediumFont; + break; + case GR_TEXT_LARGE: + font = grLargeFont; + break; + case GR_TEXT_XLARGE: + font = grXLargeFont; + break; + default: + TxError("%s%d\n", "GrTkTextSize: Unknown character size ", + size ); + break; + } + if (font == NULL) return; + Tk_GetFontMetrics(font, &overall); + width = Tk_TextWidth(font, text, strlen(text)); + r->r_ytop = overall.ascent; + r->r_ybot = -overall.descent; + r->r_xtop = width; + r->r_xbot = 0; +} + + +/* + * ---------------------------------------------------------------------------- + * GrTkReadPixel -- + * + * Read one pixel from the screen. + * + * Results: + * An integer containing the pixel's color. + * + * Side effects: + * none. + * + * ---------------------------------------------------------------------------- + */ + +int +GrTkReadPixel (w, x, y) + MagWindow *w; + int x,y; /* the location of a pixel in screen coords */ +{ + XImage *image; + unsigned long value; + XWindowAttributes att; + + XGetWindowAttributes(grXdpy, grCurrent.windowid, &att); + if ( x < 0 || x >= att.width || grMagicToX(y) < 0 || grMagicToX(y) >= att.height) return(0); + image = XGetImage(grXdpy, grCurrent.windowid, x, grMagicToX(y), 1, 1, + ~0, ZPixmap); + value = XGetPixel(image, 0, 0); + return (value & (1 << grDisplay.depth) - 1); +} + + +/* + * ---------------------------------------------------------------------------- + * GrTkBitBlt -- + * + * Copy information from one part of the screen to the other. + * + * Results: + * None. + * + * Side effects: + * changes the screen. + * ---------------------------------------------------------------------------- + */ + +void +GrTkBitBlt(r, p) + Rect *r; + Point *p; +{ + Window wind = grCurrent.windowid; + + XCopyArea(grXdpy, wind, wind, grGCCopy, + r->r_xbot, grMagicToX(r->r_ytop), + r->r_xtop - r->r_xbot + 1, r->r_ytop - r->r_ybot + 1, + p->p_x, grMagicToX(p->p_y)); +} + + + +/* + * ---------------------------------------------------------------------------- + * grtkRectConvert -- + * Convert a magic rectangle into an X11 rectangle + * (Both passed as pointers). + * + * Results: + * None. + * + * Side effects: + * Coordinate-converted rectangle values placed in XRectangle pointer + * xr. + * ---------------------------------------------------------------------------- + */ + +void +grtkRectConvert(mr, xr) + Rect *mr; /* source rectangle pointer */ + XRectangle *xr; /* destination rectangle pointer */ +{ + xr->x = mr->r_xbot; + xr->y = grMagicToX(mr->r_ytop); + xr->width = mr->r_xtop - mr->r_xbot + 1; + xr->height = mr->r_ytop - mr->r_ybot + 1; +} + +/* + *--------------------------------------------------------- + * grtkFontText: + * + * This routine is a fancier version of grtkPutText used for + * drawing vector outline fonts from the fontList records. + * + *--------------------------------------------------------- + */ + +void +grtkFontText(text, font, size, rotate, pos, clip, obscure) + char *text; + int font; + int size; /* pixel size of the text */ + int rotate; /* text rotation */ + Point *pos; /* text base position */ + Rect *clip; + LinkedRect *obscure; +{ + char *tptr; + FontChar *ccur, *clist; + Point *coffset, *tp, loffset, locoffset, corners[4], lpos; + Rect *cbbox, charbbox, *frect; + int np, i, j, w, h, llx, lly, baseline; + XPoint *xp; + Pixmap pxm; + double fscale, scx, scy, tmpx, tmpy, rrad, cr, sr; + static GC fontgc = (GC)NULL; + + frect = &DBFontList[font]->mf_extents; + fscale = (double)size / (double)frect->r_ytop; + rrad = (double)rotate * 0.0174532925; + cr = cos(rrad); + sr = sin(rrad); + lpos = GeoOrigin; + + /* 1st pass: find the descent of the string */ + + baseline = 0; + for (tptr = text; *tptr != '\0'; tptr++) + { + DBFontChar(font, *tptr, NULL, NULL, &cbbox); + if (cbbox->r_ybot < -baseline) + baseline = -cbbox->r_ybot; + } + baseline = (int)((double)baseline * fscale); + + for (tptr = text; *tptr != '\0'; tptr++) + { + scx = (double)lpos.p_x * fscale; + scy = (double)lpos.p_y * fscale; + + tmpx = scx * cr + scy * sr; + tmpy = scy * cr - scx * sr; + + loffset.p_x = pos->p_x + (int)round(tmpx); + loffset.p_y = grMagicToX(pos->p_y + baseline) + (int)round(tmpy); + + DBFontChar(font, *tptr, &clist, &coffset, &cbbox); + np = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + np += ccur->fc_numpoints; + + xp = (XPoint *)mallocMagic(np * sizeof(XPoint)); + + j = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + { + tp = ccur->fc_points; + for (i = 0; i < ccur->fc_numpoints; i++, j++) + { + scx = (double)tp[i].p_x * fscale; + scy = (double)tp[i].p_y * fscale; + + tmpx = scx * cr - scy * sr; + tmpy = scx * sr + scy * cr; + + xp[j].x = (int)round(tmpx); + xp[j].y = (int)round(tmpy); + + /* Initialize bounding box */ + if (j == 0) + { + charbbox.r_xbot = charbbox.r_xtop = xp[j].x; + charbbox.r_ybot = charbbox.r_ytop = xp[j].y; + } + else + { + if (xp[j].x < charbbox.r_xbot) + charbbox.r_xbot = xp[j].x; + else if (xp[j].x > charbbox.r_xtop) + charbbox.r_xtop = xp[j].x; + if (xp[j].y < charbbox.r_ybot) + charbbox.r_ybot = xp[j].y; + else if (xp[j].y > charbbox.r_ytop) + charbbox.r_ytop = xp[j].y; + } + } + } + + /* Create a bitmap */ + + w = charbbox.r_xtop - charbbox.r_xbot + 1; + h = charbbox.r_ytop - charbbox.r_ybot + 1; + + /* Adjust all points to the bounding box origin, and invert Y */ + for (j = 0; j < np; j++) + { + xp[j].x -= charbbox.r_xbot; + xp[j].y = charbbox.r_ytop - xp[j].y; + } + + pxm = XCreatePixmap(grXdpy, grCurrent.windowid, w, h, 1); + + if (fontgc == (GC)NULL) + { + XGCValues values; + values.foreground = 0; + values.background = 0; + fontgc = XCreateGC(grXdpy, pxm, GCForeground | GCBackground, &values); + } + + locoffset.p_x = loffset.p_x + charbbox.r_xbot; + locoffset.p_y = loffset.p_y - charbbox.r_ytop; + + XSetForeground(grXdpy, fontgc, 0); + XSetFunction(grXdpy, fontgc, GXcopy); + XFillRectangle(grXdpy, pxm, fontgc, 0, 0, w, h); + XSetFunction(grXdpy, fontgc, GXxor); + XSetForeground(grXdpy, fontgc, 1); + + j = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + { + np = ccur->fc_numpoints; + XFillPolygon(grXdpy, pxm, fontgc, &xp[j], np, Complex, CoordModeOrigin); + j += np; + } + freeMagic((char *)xp); + + XSetClipMask(grXdpy, grGCText, pxm); + XSetClipOrigin(grXdpy, grGCText, locoffset.p_x, locoffset.p_y); + XFillRectangle(grXdpy, grCurrent.windowid, grGCText, locoffset.p_x, + locoffset.p_y, w, h); + + lpos.p_x += coffset->p_x; + lpos.p_y += coffset->p_y; + + XFreePixmap(grXdpy, pxm); + } +} + +/* + *--------------------------------------------------------- + * grtkPutText: + * + * This routine puts a chunk of text on the screen in the current + * color, size, etc. The caller must ensure that it fits on + * the screen -- no clipping is done except to the obscuring rectangle + * list and the clip rectangle. + * + * Results: + * none. + * + * Side Effects: + * The text is drawn on the screen. + * + *--------------------------------------------------------- + */ + +void +grtkPutText (text, pos, clip, obscure) + char *text; /* The text to be drawn. */ + Point *pos; /* A point located at the leftmost point of + * the baseline for this string. + */ + Rect *clip; /* A rectangle to clip against */ + LinkedRect *obscure; /* A list of obscuring rectangles */ + +{ + Rect location; + Rect overlap; + Rect textrect; + LinkedRect *ob; + void grtkGeoSub(); + + if (grCurrent.font == NULL) return; + + GrTkTextSize(text, grCurrent.fontSize, &textrect); + + location.r_xbot = pos->p_x + textrect.r_xbot; + location.r_xtop = pos->p_x + textrect.r_xtop; + location.r_ybot = pos->p_y + textrect.r_ybot; + location.r_ytop = pos->p_y + textrect.r_ytop; + + /* erase parts of the bitmap that are obscured */ + for (ob = obscure; ob != NULL; ob = ob->r_next) + { + if (GEO_TOUCH(&ob->r_r, &location)) + { + overlap = location; + GeoClip(&overlap, &ob->r_r); + grtkGeoSub(&location, &overlap); + } + } + + overlap = location; + GeoClip(&overlap, clip); + + /* copy the text to the color screen */ + if ((overlap.r_xbot < overlap.r_xtop)&&(overlap.r_ybot <= overlap.r_ytop)) + { + XRectangle xr; + + grtkRectConvert(&overlap, &xr); + XSetClipRectangles(grXdpy, grGCText, 0, 0, &xr, 1, Unsorted); + + XSetFont(grXdpy, grGCText, Tk_FontId(grCurrent.font)); + Tk_DrawChars(grXdpy, grCurrent.windowid, grGCText, + grCurrent.font, text, strlen(text), + pos->p_x, grMagicToX(pos->p_y)); + } +} + + +/* + *--------------------------------------------------------- + * grtkGeoSub: + * Return the tallest sub-rectangle of r not obscured + * by area "area" must be within r. + * + * Results: + * None. + * + * Side effects: + * Source rectangle "r" is modified. + * + *--------------------------------------------------------- + */ + +void +grtkGeoSub(r, area) + Rect *r; /* Rectangle to be subtracted from. */ + Rect *area; /* Area to be subtracted. */ + +{ + if (r->r_xbot == area->r_xbot) r->r_xbot = area->r_xtop; + else + if (r->r_xtop == area->r_xtop) r->r_xtop = area->r_xbot; + else + if (r->r_ybot <= area->r_ybot) r->r_ybot = area->r_ytop; + else + if (r->r_ytop == area->r_ytop) r->r_ytop = area->r_ybot; + else + r->r_xtop = area->r_xbot; +} diff --git a/graphics/grTk4.c b/graphics/grTk4.c new file mode 100644 index 00000000..6056cb80 --- /dev/null +++ b/graphics/grTk4.c @@ -0,0 +1,129 @@ +/* grTk4.c - + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * This file contains functions to manage the graphics tablet associated + * with the X display. + * + */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/magsgtty.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "textio/txcommands.h" +#include "grTkInt.h" +#include "grTkCommon.h" + + +/*--------------------------------------------------------- + * GrTkDisableTablet: + * Turns off the cursor. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +GrTkDisableTablet () +{ +} + + +/*--------------------------------------------------------- + * GrTkEnableTablet: + * This routine enables the graphics tablet. + * + * Results: + * None. + * + * Side Effects: + * Simply turn on the crosshair. + *--------------------------------------------------------- + */ + +void +GrTkEnableTablet () +{ +} + + +/* + * ---------------------------------------------------------------------------- + * grtkGetCursorPos: + * Read the cursor position in magic coordinates. + * + * Results: + * TRUE is returned if the coordinates were succesfully read, FALSE + * otherwise. + * + * Side effects: + * The parameter is filled in with the cursor position, in the form of + * a point in screen coordinates. + * ---------------------------------------------------------------------------- + */ + +bool +grtkGetCursorPos (mw, p) + MagWindow *mw; + Point *p; /* point to be filled in with screen coordinates */ +{ + int x, y, x1, y1; + unsigned int buttons; + Window win1, win2; + + if (mw == NULL) mw = grCurrent.mw; + + XQueryPointer(grXdpy, Tk_WindowId((Tk_Window)mw->w_grdata), + &win1, &win2, &x1, &y1, + &x, &y, &buttons); + p->p_x = x; + p->p_y = grXtransY(mw, y); + + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * grtkGetCursorRootPos: + * Read the cursor position in screen root coordinates. + * + * Results: + * TRUE is returned if the coordinates were succesfully read, FALSE + * otherwise. + * + * Side effects: + * The parameter is filled in with the cursor position, in the form of + * a point in screen coordinates. + * ---------------------------------------------------------------------------- + */ + +bool +grtkGetCursorRootPos (mw, p) + MagWindow *mw; + Point *p; /* point to be filled in with root coordinates */ +{ + int x, y, x1, y1; + unsigned int buttons; + Window win1, win2; + + if (mw == NULL) mw = grCurrent.mw; + + XQueryPointer(grXdpy, Tk_WindowId((Tk_Window)mw->w_grdata), + &win1, &win2, &x1, &y1, + &x, &y, &buttons); + p->p_x = x1; + p->p_y = y1; + + return TRUE; +} diff --git a/graphics/grTk5.c b/graphics/grTk5.c new file mode 100644 index 00000000..6eef9b50 --- /dev/null +++ b/graphics/grTk5.c @@ -0,0 +1,185 @@ +/* grTk5.c - + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * Manipulate the programable cursor on the graphics display. + * + */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/styles.h" +#include "utils/hash.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/glyphs.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "grTkCommon.h" +#include "grTkInt.h" + +extern HashTable grTkWindowTable; +extern XColor colors[]; + + +/* + * ---------------------------------------------------------------------------- + * GrTkDrawGlyph -- + * + * Draw one glyph on the display. + * + * Results: + * None. + * + * Side effects: + * Draws pixels. + * ---------------------------------------------------------------------------- + */ + +void +GrTkDrawGlyph (gl, p) + GrGlyph *gl; /* A single glyph */ + Point *p; /* screen pos of lower left corner */ +{ + Rect bBox; + bool anyObscure; + LinkedRect *ob; + + GR_CHECK_LOCK(); + bBox.r_ll = *p; + bBox.r_xtop = p->p_x + gl->gr_xsize - 1; + bBox.r_ytop = p->p_y + gl->gr_ysize - 1; + + anyObscure = FALSE; + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) { + if (GEO_TOUCH( &(ob->r_r), &bBox)) { + anyObscure = TRUE; + break; + } + } + if(grDisplay.depth <= 8) { + XSetPlaneMask(grXdpy, grGCGlyph, grPlanes[127]); } + + XSetFillStyle(grXdpy, grGCGlyph, FillSolid); + if ((!anyObscure) && (GEO_SURROUND(&grCurClip, &bBox)) ) { + int *pixelp, x, y; + + /* no clipping, try to go quickly */ + pixelp = gl->gr_pixels; + for (y = 0; y < gl->gr_ysize; y++) { + int x1, y1; + + y1 = grMagicToX(bBox.r_ybot + y); + for (x = 0; x < gl->gr_xsize; x++) { + int color; + if (*pixelp != 0) { + color = GrStyleTable[*pixelp].color; + x1 = bBox.r_xbot + x; + XSetForeground(grXdpy, grGCGlyph, grPixels[color]); + XDrawPoint(grXdpy, grCurrent.windowid, grGCGlyph, x1, y1); + } + pixelp++; + } + } + } else { + /* do pixel by pixel clipping */ + int y, yloc; + + yloc = bBox.r_ybot; + for (y = 0; y < gl->gr_ysize; y++) { + int startx, endx; + if ( (yloc <= grCurClip.r_ytop) && (yloc >= grCurClip.r_ybot) ) { + int laststartx; + laststartx = bBox.r_xbot - 1; + for (startx = bBox.r_xbot; startx <= bBox.r_xtop; + startx = endx + 1) { + int *pixelp; + + startx = MAX(startx, grCurClip.r_xbot); + endx = MIN(bBox.r_xtop, grCurClip.r_xtop); + + if (anyObscure) { + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) { + if ( (ob->r_r.r_ybot <= yloc) && + (ob->r_r.r_ytop >= yloc) ) { + if (ob->r_r.r_xbot <= startx) + startx = MAX(startx, ob->r_r.r_xtop + 1); + else if (ob->r_r.r_xbot <= endx) + endx = MIN(endx, ob->r_r.r_xbot - 1); + } + } + } + + /* stop if we aren't advancing */ + if (startx == laststartx) break; + laststartx = startx; + if (startx > endx) continue; + + /* draw a section of this scan line */ + pixelp = &( gl->gr_pixels[y*gl->gr_xsize + + (startx - bBox.r_xbot)]); + for ( ; startx <= endx; startx++) { + int color; + if (*pixelp != 0) { + color = GrStyleTable[*pixelp].color; + XSetForeground(grXdpy, grGCGlyph, grPixels[color]); + XDrawPoint(grXdpy, grCurrent.windowid, grGCGlyph, + startx, grMagicToX(yloc)); + } + pixelp++; + } + startx = endx + 1; + } + } + yloc++; + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * GrTkSetCursor: + * + * Make the cursor be a new pattern, as defined in the display styles file. + * + * Results: + * None. + * + * Side effects: + * When the cursor is turned back on it will take on the new pattern. + * ---------------------------------------------------------------------------- + */ + +void +GrTkSetCursor(cursorNum) + int cursorNum; /* The cursor number as defined in the display + * styles file. + */ +{ + HashEntry *entry; + HashSearch hs; + Tk_Window tkwind; + + if (cursorNum >= MAX_CURSORS) + { + TxError("No such cursor!\n"); + return; + } + grCurrent.cursor = grCursors[cursorNum]; + + HashStartSearch(&hs); + while (entry = HashNext(&grTkWindowTable,&hs)) + { + if (HashGetValue(entry)) + { + tkwind = (Tk_Window)entry->h_key.h_ptr; + Tk_DefineCursor(tkwind, grCurrent.cursor); + } + } +} diff --git a/graphics/grTkCommon.c b/graphics/grTkCommon.c new file mode 100644 index 00000000..f8ef1787 --- /dev/null +++ b/graphics/grTkCommon.c @@ -0,0 +1,1508 @@ +/* grTkCommon.c + * + * Functions common to all graphics routines running under Tcl/Tk + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + */ + +/* We should be here if this is not set! */ +#ifdef MAGIC_WRAPPER + +#include +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/styles.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwtech.h" +#include "utils/styles.h" +#include "graphics/graphics.h" +#include "graphics/graphicsInt.h" +#include "dbwind/dbwind.h" +#include "graphics/grTkCommon.h" +#include "graphics/glyphs.h" + +/* Variables declared by grClip.c */ + +extern int grCurFill, grCurOutline, grCurColor; +extern void grInformDriver(); + +/* Global variables used by both the Tk and TOGL interfaces */ +/* should be defined here. */ + +Display *grXdpy; +int grXscrn; +Tk_Cursor grCursors[MAX_CURSORS]; +Tk_Font grTkFonts[4]; + +/* Used by Tk interface. Defined for both Tk and TOGL, but */ +/* unused by the TOGL interface. */ + +bool GrTkInstalledCMap = FALSE; + +/*--------------------------------------------------------- + * grTkLoadFont + * This local routine loads the Tk fonts used by Magic. + * + * Results: + * Success/Failure. + * + * Side Effects: + * Font information saved in grTkFonts array. + *--------------------------------------------------------- + */ + +bool +grTkLoadFont() +{ + Tk_Window tkwind; + int i; + char *s; + char *unable = "Unable to load font"; + + static char *fontnames[4] = { + TK_FONT_SMALL, + TK_FONT_MEDIUM, + TK_FONT_LARGE, + TK_FONT_XLARGE }; + static char *optionnames[4] = { + "small", + "medium", + "large", + "xlarge"}; + + tkwind = Tk_MainWindow(magicinterp); + for (i = 0; i < 4; i++) + { + s = XGetDefault(grXdpy, "magic", optionnames[i]); + if (s) fontnames[i] = s; + if ((grTkFonts[i] = Tk_GetFont(magicinterp, + tkwind, fontnames[i])) == NULL) + { + TxError("%s %s\n", unable, fontnames[i]); + if ((grTkFonts[i] = Tk_GetFont(magicinterp, + tkwind, TK_DEFAULT_FONT)) == NULL) + { + TxError("%s %s\n", unable, TK_DEFAULT_FONT); + return FALSE; + } + } + } + return TRUE; +} + +/*--------------------------------------------------------- + * grTkFreeFonts + * This local routine frees the Tk font cache. + * + * Results: + * None. + * + * Side Effects: + * Memory deallocation. + *--------------------------------------------------------- + */ + +void +grTkFreeFonts() +{ + int i; + + for (i = 0; i < 4; i++) + Tk_FreeFont(grTkFonts[i]); +} + +/* + * ---------------------------------------------------------------------------- + * grTkFreeCursors: + * + * Remove cursors from the Tk cursor cache. + * + * Results: + * None. + * + * Side effects: + * Tk forgets about the glyph cursors. + * ---------------------------------------------------------------------------- + */ + +void +grTkFreeCursors(glyphs) + GrGlyphs *glyphs; +{ + int i; + for (i = 0; i < glyphs->gr_num; i++) + Tk_FreeCursor(grXdpy, grCursors[i]); +} + +/* + * ---------------------------------------------------------------------------- + * grTkDefineCursor: + * + * Define a new set of cursors. Use Tk-style cursors (portable) + * + * Results: + * None. + * + * Side effects: + * The given matrix is stored in the graphics display, and it can be + * used as the cursor by calling GrSetCursor. + * ---------------------------------------------------------------------------- + */ + +typedef struct { + unsigned char source[32]; + unsigned char mask[32]; +} CursorCache; + +void +grTkDefineCursor(glyphs) + GrGlyphs *glyphs; +{ + char *fgname, *bgname; + int glyphnum; + Rect oldClip; + int red, green, blue; + Tk_Window tkwin; + bool fg_needs_free; + + if (glyphs->gr_num <= 0) return; + + if (glyphs->gr_num > MAX_CURSORS) + { + TxError("magic/Tk only has room for %d cursors\n", MAX_CURSORS); + return; + } + + tkwin = Tk_MainWindow(magicinterp); + + /* expand clipping amount for off-screen access on the X */ + GrLock(GR_LOCK_SCREEN, FALSE); + oldClip = grCurClip; + grCurClip = GrScreenRect; + grCurClip.r_ytop += 16; + + /* enter the glyphs */ + for (glyphnum = 0; glyphnum < glyphs->gr_num; glyphnum++) { + int i, *p, fgstyle; + XColor curcolor; + GrGlyph *g; + int x, y; + CursorCache *glyphcache; + + g = glyphs->gr_glyph[glyphnum]; + if ((g->gr_xsize != 16) || (g->gr_ysize != 16)) { + TxError("Tk/OpenGL Cursors must be 16 X 16 pixels.\n"); + return; + } + + glyphcache = (CursorCache *)mallocMagic(sizeof(CursorCache)); + g->gr_cache = (ClientData)glyphcache; + g->gr_free = freeMagic; + + /* Find the foreground and background colors of the glyph */ + + p = &(g->gr_pixels[0]); + fgstyle = STYLE_TRANSPARENT; + fg_needs_free = FALSE; + for (x = 0; x < 256; x++) + { + if (*p != STYLE_TRANSPARENT) + { + fgstyle = *p; + GrGetColor(GrStyleTable[*p].color, &red, &green, &blue); + curcolor.red = (unsigned short)(red << 8); + curcolor.green = (unsigned short)(green << 8); + curcolor.blue = (unsigned short)(blue << 8); + curcolor.flags = DoRed | DoGreen | DoBlue; + fgname = (char *)Tk_NameOfColor(Tk_GetColorByValue(tkwin, &curcolor)); + break; + } + p++; + } + if (x == 256) + fgname = "black"; + + for (; x < 256; x++) + { + if ((*p != STYLE_TRANSPARENT) && (*p != fgstyle)) + { + GrGetColor(GrStyleTable[*p].color, &red, &green, &blue); + curcolor.red = (unsigned short)(red << 8); + curcolor.green = (unsigned short)(green << 8); + curcolor.blue = (unsigned short)(blue << 8); + curcolor.flags = DoRed | DoGreen | DoBlue; + bgname = StrDup((char **)NULL, fgname); + fgname = bgname; + fg_needs_free = TRUE; + bgname = (char *)Tk_NameOfColor(Tk_GetColorByValue(tkwin, &curcolor)); + break; + } + p++; + } + if (x >= 256) + bgname = "white"; + + /* Perform transposition on the glyph matrix since X displays + * the least significant bit on the left hand side. + */ + p = &(g->gr_pixels[0]); + for (y = 0; y < 32; y++) { + i = (y & 1) ? (32 - y) : (30 - y); + glyphcache->source[i] = glyphcache->mask[i] = 0; + for (x = 0; x < 8; x++) + { + if (*p == fgstyle) + glyphcache->source[i] |= (1 << x); + if (*p != STYLE_TRANSPARENT) + glyphcache->mask[i] |= (1 << x); + p++; + } + } + grCursors[glyphnum] = Tk_GetCursorFromData(magicinterp, + Tk_MainWindow(magicinterp), + (char *)glyphcache->source, (char *)glyphcache->mask, + 16, 16, g->gr_origin.p_x, (15 - g->gr_origin.p_y), + Tk_GetUid(fgname), Tk_GetUid(bgname)); + + if (fg_needs_free) freeMagic(fgname); + } + + /* Restore clipping */ + grCurClip = oldClip; + GrUnlock(GR_LOCK_SCREEN); +} + +/* + *------------------------------------------------------------------------- + * GrTkWindowName -- + * Get the window name from the indicated MagWindow structure + * + * Results: + * The Tk path name of the window "mw" (char * string). + * + * Side Effects: + * None. + *------------------------------------------------------------------------- + */ + +char * +GrTkWindowName(mw) + MagWindow *mw; +{ + Tk_Window tkwind; + char *tkname; + + tkwind = (Tk_Window) mw->w_grdata; + return Tk_PathName(tkwind); +} + +/* + * ---------------------------------------------------------------------------- + * grtkFreeBackingStore -- + * Free up Pixmap memory for a backing store cell. + * + * Results: + * None. + * + * Side effects: + * memory Free'd + * ---------------------------------------------------------------------------- + */ + +void +grtkFreeBackingStore(MagWindow *window) +{ + Pixmap pmap = (Pixmap)window->w_backingStore; + if (pmap == (Pixmap)NULL) return; + XFreePixmap(grXdpy, pmap); + window->w_backingStore = (ClientData)NULL; + /* TxPrintf("grtkFreeBackingStore called\n"); */ +} + +/* + * ---------------------------------------------------------------------------- + * grtkCreateBackingStore -- + * Create Pixmap memory for a backing store cell and copy data + * from the window into it. + * + * Results: + * None. + * + * Side effects: + * memory Allocated. + * + * ---------------------------------------------------------------------------- + */ + +void +grtkCreateBackingStore(MagWindow *w) +{ + Pixmap pmap; + Tk_Window tkwind = (Tk_Window)w->w_grdata; + Window wind; + unsigned int width, height; + + /* ignore all windows other than layout */ + if (w->w_client != DBWclientID) return; + + /* deferred */ + if (tkwind == NULL) return; + + wind = Tk_WindowId(tkwind); + width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + + if (w->w_backingStore != (ClientData)NULL) grtkFreeBackingStore(w); + + pmap = XCreatePixmap(grXdpy, wind, width, height, Tk_Depth(tkwind)); + w->w_backingStore = (ClientData)pmap; + + /* TxPrintf("grtkCreateBackingStore area %d %d %d %d\n", + w->w_screenArea.r_xbot, w->w_screenArea.r_ybot, + w->w_screenArea.r_xtop, w->w_screenArea.r_ytop); */ +} + +/* + * ---------------------------------------------------------------------------- + * grtkGetBackingStore -- + * Copy data from a backing store Pixmap into the indicated window. + * + * Results: + * TRUE if backing store was copied successfully, FALSE if not. + * + * Side effects: + * Data copied into Pixmap memory. + * + * ---------------------------------------------------------------------------- + */ + +bool +grtkGetBackingStore(MagWindow *w, Rect *area) +{ + Pixmap pmap; + Tk_Window tkwind = (Tk_Window)w->w_grdata; + Window wind = Tk_WindowId(tkwind); + unsigned int width, height; + int ybot; + int xoff, yoff; + GC gc; + XGCValues gcValues; + Rect r; + + pmap = (Pixmap)w->w_backingStore; + if (pmap == (Pixmap)NULL) + return FALSE; + + gcValues.graphics_exposures = FALSE; + gc = Tk_GetGC(tkwind, GCGraphicsExposures, &gcValues); + + /* Make a local copy of area so we don't disturb the */ + /* original. Expand by one pixel to deal with different */ + /* boundary conditions between X11 and OpenGL. The redraw */ + /* mechanism allows for at least this much slop. */ + + GEO_EXPAND(area, 1, &r); + GeoClip(&r, &(w->w_screenArea)); + + width = r.r_xtop - r.r_xbot; + height = r.r_ytop - r.r_ybot; + ybot = grXtransY(w, r.r_ytop); + + xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot; + yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop; + + XCopyArea(grXdpy, pmap, wind, gc, r.r_xbot - xoff, + ybot - yoff, width, height, r.r_xbot, ybot); + + /* This is really only necessary for OpenGL, to avoid event */ + /* timing conflicts between OpenGL calls and XCopyArea. */ + /* It does not make sense for this to come AFTER the */ + /* XCopyArea() command. Yet that is what works. So I'm */ + /* sure that I do not entirely understand the situation. */ + + (*GrFlushPtr)(); + + /* TxPrintf("grtkGetBackingStore %d %d %d %d\n", + r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop); */ + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * grtkScrollBackingStore -- + * Enable fast scrolling by shifting part of the backing store + * from one position to another, with the amount of shift indicated + * by the X and/or Y value of the indicated point. + * + * Results: + * TRUE on success, FALSE on failure. + * + * Side effects: + * Data shifted in Pixmap memory. + * + * ---------------------------------------------------------------------------- + */ + +bool +grtkScrollBackingStore(MagWindow *w, Point *shift) +{ + Pixmap pmap; + Tk_Window tkwind = (Tk_Window)w->w_grdata; + unsigned int width, height; + int xorigin, yorigin, xshift, yshift; + GC gc; + XGCValues gcValues; + + pmap = (Pixmap)w->w_backingStore; + if (pmap == (Pixmap)NULL) + { + TxPrintf("grtkScrollBackingStore %d %d failure\n", + shift->p_x, shift->p_y); + return FALSE; + } + + gcValues.graphics_exposures = FALSE; + gc = Tk_GetGC(tkwind, GCGraphicsExposures, &gcValues); + + width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + xorigin = 0; + yorigin = 0; + xshift = shift->p_x; + yshift = -shift->p_y; + + if (xshift > 0) + width -= xshift; + else if (xshift < 0) + { + width += xshift; + xorigin = -xshift; + xshift = 0; + } + if (yshift > 0) + height -= yshift; + else if (yshift < 0) + { + height += yshift; + yorigin = -yshift; + yshift = 0; + } + + XCopyArea(grXdpy, pmap, pmap, gc, xorigin, yorigin, width, height, + xshift, yshift); + + /* TxPrintf("grtkScrollBackingStore %d %d\n", shift->p_x, shift->p_y); */ + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * grtkPutBackingStore -- + * Copy data from the window into backing store. + * + * Results: + * None. + * + * Side effects: + * Graphics drawing into the window. + * ---------------------------------------------------------------------------- + */ + +void +grtkPutBackingStore(MagWindow *w, Rect *area) +{ + Pixmap pmap = (Pixmap)w->w_backingStore; + Tk_Window tkwind = (Tk_Window)w->w_grdata; + Window wind = Tk_WindowId(tkwind); + unsigned int width, height; + int ybot, xbot, xoff, yoff; + GC gc; + XGCValues gcValues; + + if (pmap == (Pixmap)NULL) return; + + /* Attempting to write backing store into an obscured */ + /* window immediately invalidates everything in backing */ + /* store. This is extreme, but is much simpler and under */ + /* normal conditions faster than tracking all obscured */ + /* areas separately. */ + + if (w->w_flags & WIND_OBSCURED) + { + grtkFreeBackingStore(w); + w->w_backingStore = (ClientData)NULL; + return; + } + + width = area->r_xtop - area->r_xbot; + height = area->r_ytop - area->r_ybot; + ybot = grXtransY(w, area->r_ytop); + xbot = area->r_xbot; + + gcValues.graphics_exposures = FALSE; + gc = Tk_GetGC(tkwind, GCGraphicsExposures, &gcValues); + + xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot; + yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop; + + /* This area may need to be expanded by a pixel and/or */ + /* expanded by GrPixelCorrect to compensate for the OpenGL */ + /* coordinate system. */ + + if (GrPixelCorrect == 0) + { + height--; + width--; + xbot++; + } + + XCopyArea(grXdpy, wind, pmap, gc, xbot, ybot, width, height, + xbot - xoff, ybot - yoff); + + /* TxPrintf("grtkPutBackingStore %d %d %d %d\n", + xbot, area->r_ybot, area->r_xtop, area->r_ytop); */ +} + +/* + *--------------------------------------------------------- + * GrTkGetColorByName -- + * + * Returns a string appropriate for setting a color + * value in a Tk window (referenced to the Tk colormap) + * for the given color of the magic style referenced + * by the short name or long name (as given in the dstyle5 + * file). + * + * Note that the colormaps grXcmap and Tk_Colormap(tkwind) + * are the same unless we are in 8-bit PseudoColor mode, + * in which case this function maps between the two. + * + * Note that when given an invalid short name, GrStyleNames[] + * always returns 0, which is the index for style + * "no_color_at_all". On the other hand, long names are not + * uniquely defined between "normal" and "pale" styles. + * + * Results: + * A string allocated by Tcl_Alloc() which will need to + * be free'd by the calling function using Tcl_Free(). + * + * Side Effects: + * None. + * + *--------------------------------------------------------- + */ + +char * +GrTkGetColorByName(name) + char *name; +{ + Tk_Window tkwind = Tk_MainWindow(magicinterp); + int style, red, green, blue; + XColor falsecolor; + char *colstring; + + if (strlen(name) == 1) + style = GrStyleNames[name[0] & 0x7f]; + else if (DBWNumStyles == 0) + { + TxError("No style table exists.\n"); + return NULL; + } + else + { + for (style = 0; style < TECHBEGINSTYLES + DBWNumStyles; style++) + if (GrStyleTable[style].longname != NULL) + if (!strcmp(name, GrStyleTable[style].longname)) + break; + } + + if (style >= TECHBEGINSTYLES + DBWNumStyles) + { + TxError("Style does not exist or style is not accessible\n"); + return NULL; + } + + falsecolor.pixel = GrStyleTable[style].color; + if (GrTkInstalledCMap) + { + XQueryColor(grXdpy, Tk_Colormap(tkwind), &falsecolor); + colstring = Tcl_Alloc(14); + sprintf(colstring, "#%04x%04x%04x", falsecolor.red, + falsecolor.green, falsecolor.blue); + } + else + { + /* Note that XColor colors are unsigned short, but GrGetColor */ + /* expects an int *. */ + + GrGetColor(falsecolor.pixel, &red, &green, &blue); + falsecolor.red = red; + falsecolor.green = green; + falsecolor.blue = blue; + colstring = Tcl_Alloc(8); + sprintf(colstring, "#%02x%02x%02x", falsecolor.red, + falsecolor.green, falsecolor.blue); + } + return colstring; +} + +/* + *--------------------------------------------------------- + * _magic_magiccolor -- + * Tcl command callback for GrTkGetColorByName + * + * Results: + * TCL result type + * + * Side effects: + * None. + *--------------------------------------------------------- + */ + +static int +_magic_magiccolor(ClientData clientData, + Tcl_Interp *interp, int argc, char *argv[]) +{ + char *result; + char *name; + + if (argc != 2) + { + TxError("Usage: magiccolor name\n"); + return TCL_ERROR; + } + name = argv[1]; + + result = GrTkGetColorByName(name); + if (result) + { + Tcl_SetResult(interp, result, TCL_DYNAMIC); + return TCL_OK; + } + else { + TxError("No such color name \"%s\" in style file.\n", name); + return TCL_ERROR; + } +} + +/* + * The following data structure represents the master for a layer + * image: + */ + +typedef struct LayerMaster { + Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means + * the image is being deleted. */ + Tcl_Interp *interp; /* Interpreter for application that is + * using image. */ + Tcl_Command imageCmd; /* Token for image command (used to delete + * it when the image goes away). NULL means + * the image command has already been + * deleted. */ + int width, height; /* Dimensions of image. */ + int layerOff; /* If TRUE layer is displayed in non-edit style */ + int layerLock; /* Layer is displayed with a cursor icon */ + char *layerString; /* Value of -layer option (malloc'ed). */ + struct LayerInstance *instancePtr; + /* First in list of all instances associated + * with this master. */ +} LayerMaster; + +/* + * The following data structure represents all of the instances of an + * image that lie within a particular window: + */ + +typedef struct LayerInstance { + int refCount; /* Number of instances that share this + * data structure. */ + LayerMaster *masterPtr; /* Pointer to master for image. */ + Tk_Window tkwin; /* Window in which the instances will be + * displayed. */ + Pixmap pixmap; /* The bitmap to display. */ + GC gc; /* Graphics context for displaying pixmap */ + struct LayerInstance *nextPtr; + /* Next in list of all instance structures + * associated with masterPtr (NULL means + * end of list). */ +} LayerInstance; + +/* + * The type record for bitmap images: + */ + +static int ImgLayerCreate _ANSI_ARGS_((Tcl_Interp *interp, + const char *name, int argc, Tcl_Obj *CONST objv[], + const Tk_ImageType *typePtr, Tk_ImageMaster master, + ClientData *clientDataPtr)); +static ClientData ImgLayerGet _ANSI_ARGS_((Tk_Window tkwin, + ClientData clientData)); +static void ImgLayerDisplay _ANSI_ARGS_((ClientData clientData, + Display *display, Drawable drawable, + int imageX, int imageY, int width, int height, + int drawableX, int drawableY)); +static void ImgLayerFree _ANSI_ARGS_((ClientData clientData, + Display *display)); +static void ImgLayerDelete _ANSI_ARGS_((ClientData clientData)); + +Tk_ImageType tkLayerImageType = { + "layer", /* name */ + ImgLayerCreate, /* createProc */ + ImgLayerGet, /* getProc */ + ImgLayerDisplay, /* displayProc */ + ImgLayerFree, /* freeProc */ + ImgLayerDelete, /* deleteProc */ + NULL, /* postscriptProc */ + (Tk_ImageType *) NULL /* nextPtr */ +}; + +/* + * Information used for parsing configuration specs: + * Size defaults to a 16x16 area. + */ + +static Tk_ConfigSpec configSpecs[] = { + {TK_CONFIG_STRING, "-name", (char *) NULL, (char *) NULL, + (char *) NULL, Tk_Offset(LayerMaster, layerString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BOOLEAN, "-disabled", (char *) NULL, (char *) NULL, + (char *) "0", Tk_Offset(LayerMaster, layerOff), 0}, + {TK_CONFIG_INT, "-icon", (char *) NULL, (char *) NULL, + (char *) "-1", Tk_Offset(LayerMaster, layerLock), 0}, + {TK_CONFIG_INT, "-width", (char *) NULL, (char *) NULL, + (char *) "16", Tk_Offset(LayerMaster, width), 0}, + {TK_CONFIG_INT, "-height", (char *) NULL, (char *) NULL, + (char *) "16", Tk_Offset(LayerMaster, height), 0}, + {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, + (char *) NULL, 0, 0} +}; + +/* + * Prototypes for procedures used only locally in this file: + */ + +static int ImgLayerCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[])); +static void ImgLayerCmdDeletedProc _ANSI_ARGS_(( + ClientData clientData)); +static void ImgLayerConfigureInstance _ANSI_ARGS_(( + LayerInstance *instancePtr)); +static int ImgLayerConfigureMaster _ANSI_ARGS_(( + LayerMaster *masterPtr, int argc, Tcl_Obj *CONST objv[], + int flags)); + +/* + *---------------------------------------------------------------------- + * + * ImgLayerCreate -- + * + * This procedure is called by the Tk image code to create "test" + * images. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * The data structure for a new image is allocated. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static int +ImgLayerCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) + Tcl_Interp *interp; /* Interpreter for application containing + * image. */ + const char *name; /* Name to use for image. */ + int argc; /* Number of arguments. */ + Tcl_Obj *CONST argv[]; /* Argument objects for options (doesn't + * include image name or type). */ + const Tk_ImageType *typePtr;/* Pointer to our type record (not used). */ + Tk_ImageMaster master; /* Token for image, to be used by us in + * later callbacks. */ + ClientData *clientDataPtr; /* Store manager's token for image here; + * it will be returned in later callbacks. */ +{ + LayerMaster *masterPtr; + + masterPtr = (LayerMaster *) Tcl_Alloc(sizeof(LayerMaster)); + masterPtr->tkMaster = master; + masterPtr->interp = interp; + masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgLayerCmd, + (ClientData) masterPtr, ImgLayerCmdDeletedProc); + masterPtr->width = masterPtr->height = 0; + masterPtr->layerOff = 0; + masterPtr->layerLock = -1; + masterPtr->layerString = NULL; + masterPtr->instancePtr = NULL; + if (ImgLayerConfigureMaster(masterPtr, argc, argv, 0) != TCL_OK) { + ImgLayerDelete((ClientData) masterPtr); + return TCL_ERROR; + } + *clientDataPtr = (ClientData) masterPtr; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ImgLayerConfigureMaster -- + * + * This procedure is called when a bitmap image is created or + * reconfigured. It process configuration options and resets + * any instances of the image. + * + * Results: + * A standard Tcl return value. If TCL_ERROR is returned then + * an error message is left in the masterPtr->interp's result. + * + * Side effects: + * Existing instances of the image will be redisplayed to match + * the new configuration options. + * + *---------------------------------------------------------------------- + */ + +static int +ImgLayerConfigureMaster(masterPtr, objc, objv, flags) + LayerMaster *masterPtr; /* Pointer to data structure describing + * overall pixmap image to (reconfigure). */ + int objc; /* Number of entries in objv. */ + Tcl_Obj *CONST objv[]; /* Pairs of configuration options for image. */ + int flags; /* Flags to pass to Tk_ConfigureWidget, + * such as TK_CONFIG_ARGV_ONLY. */ +{ + LayerInstance *instancePtr; + int dummy1; + + char **argv = (char **) Tcl_Alloc((objc+1) * sizeof(char *)); + for (dummy1 = 0; dummy1 < objc; dummy1++) { + argv[dummy1]=Tcl_GetString(objv[dummy1]); + } + argv[objc] = NULL; + + if (Tk_ConfigureWidget(masterPtr->interp, Tk_MainWindow(masterPtr->interp), + configSpecs, objc, (CONST84 char **)argv, (char *) masterPtr, flags) + != TCL_OK) { + Tcl_Free((char *) argv); + return TCL_ERROR; + } + Tcl_Free((char *) argv); + + /* + * Cycle through all of the instances of this image, regenerating + * the information for each instance. Then force the image to be + * redisplayed everywhere that it is used. + */ + + for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; + instancePtr = instancePtr->nextPtr) { + ImgLayerConfigureInstance(instancePtr); + } + Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width, + masterPtr->height, masterPtr->width, masterPtr->height); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * grDrawOffScreenBox -- + * Draw a box on an off-screen drawable (convenience function for + * the following procedure ImgLayerConfigureInstance() + * + * Results: + * None. + * + * Side effects: + * Draws into an off-screen drawable destination. + * + *---------------------------------------------------------------------- + */ + +void +grDrawOffScreenBox(rect) + Rect *rect; +{ + (*grDrawLinePtr)(rect->r_xbot, rect->r_ytop - 1, rect->r_xtop - 1, + rect->r_ytop - 1); + (*grDrawLinePtr)(rect->r_xbot, rect->r_ybot, rect->r_xtop - 1, + rect->r_ybot); + (*grDrawLinePtr)(rect->r_xbot, rect->r_ybot, rect->r_xbot, + rect->r_ytop - 1); + (*grDrawLinePtr)(rect->r_xtop - 1, rect->r_ybot, rect->r_xtop - 1, + rect->r_ytop - 1); +} + + +/* + *---------------------------------------------------------------------- + * + * ImgLayerConfigureInstance -- + * + * This procedure is called to create displaying information for + * a layer image instance based on the configuration information + * in the master. It is invoked both when new instances are + * created and when the master is reconfigured. + * + * Results: + * None. + * + * Side effects: + * Generates errors via Tcl_BackgroundError if there are problems + * in setting up the instance. + * + *---------------------------------------------------------------------- + */ + +#define LAYER_NORMAL 0 +#define LAYER_LABELS 1 +#define LAYER_SUBCELL 2 +#define LAYER_LAYOUT 3 + +static void +ImgLayerConfigureInstance(instancePtr) + LayerInstance *instancePtr; /* Instance to reconfigure. */ +{ + LayerMaster *masterPtr = instancePtr->masterPtr; + XGCValues gcValues; + GC gc; + unsigned int gcmask; + TileType layer; + TileTypeBitMask *mask; + int i, special = LAYER_NORMAL; + Rect r; + Tk_Window tkwind = instancePtr->tkwin; + MagWindow *mw, tmpmw; + + if (Tk_WindowId(tkwind) == 0) + Tk_MakeWindowExist(tkwind); + + if (Tk_WindowId(tkwind) == 0) + { + Tcl_AddErrorInfo(masterPtr->interp, "No ID exists for window"); + goto error; + } + + /* + * For each of the options in masterPtr, translate the string + * form into an internal form appropriate for instancePtr. + */ + + if (masterPtr->width <= 0 || masterPtr->height <= 0) + { + Tcl_AddErrorInfo(masterPtr->interp, "Image width or height is negative"); + goto error; + } + + if (instancePtr->pixmap != None) { + mw = WindSearchData((ClientData)instancePtr->pixmap); + if (mw != NULL) + { + windUnlink(mw); + windReClip(); + windFree(mw); + } + Tk_FreePixmap(grXdpy, instancePtr->pixmap); + instancePtr->pixmap = None; + } + + if (masterPtr->layerString != NULL) { + if (!strcmp(masterPtr->layerString, "none")) + layer = TT_SPACE; + else if (!strcmp(masterPtr->layerString, "errors")) + layer = TT_ERROR_P; + else if (!strcmp(masterPtr->layerString, "labels")) + { + layer = TT_SPACE; + special = LAYER_LABELS; + } + else if (!strcmp(masterPtr->layerString, "subcell")) + { + layer = TT_SPACE; + special = LAYER_SUBCELL; + } + else + layer = DBTechNameType(masterPtr->layerString); + + if (layer < 0) + { + layer = (*GrWindowIdPtr)(masterPtr->layerString); + + if (layer >= 0) + special = LAYER_LAYOUT; + else + { + Tcl_AddErrorInfo(masterPtr->interp, "Unknown layer type"); + goto error; + } + } + + r.r_xbot = r.r_ybot = 0; + r.r_xtop = masterPtr->width; + r.r_ytop = masterPtr->height; + + gcValues.graphics_exposures = FALSE; + gcmask = GCGraphicsExposures; + gc = Tk_GetGC(tkwind, gcmask, &gcValues); + + if (instancePtr->gc != None) + Tk_FreeGC(grXdpy, instancePtr->gc); + instancePtr->gc = gc; + + if (special == LAYER_LAYOUT) /* Off-Screen Rendering */ + { + Rect screenRect; + Tk_Window pixwind; + + mw = WindSearchWid(layer); + if (mw == NULL) + { + Tcl_AddErrorInfo(masterPtr->interp, "Unknown window ID\n"); + goto error; + } + + pixwind = (Tk_Window)mw->w_grdata; + + instancePtr->pixmap = Tk_GetPixmap(grXdpy, + Tk_WindowId(pixwind), + masterPtr->width, masterPtr->height, + Tk_Depth(pixwind)); + + (*GrDeleteWindowPtr)(mw); + mw->w_flags |= WIND_OFFSCREEN; + mw->w_grdata = (ClientData)instancePtr->pixmap; + + screenRect.r_xbot = 0; + screenRect.r_ybot = 0; + screenRect.r_xtop = masterPtr->width; + screenRect.r_ytop = masterPtr->height; + + WindReframe(mw, &screenRect, FALSE, FALSE); + WindRedisplay(mw); + + return; + } + + instancePtr->pixmap = Tk_GetPixmap(grXdpy, + Tk_WindowId(tkwind), + masterPtr->width, masterPtr->height, + Tk_Depth(tkwind)); + + tmpmw.w_flags = WIND_OFFSCREEN; + tmpmw.w_grdata = (ClientData)instancePtr->pixmap; + tmpmw.w_allArea = r; + tmpmw.w_clipAgainst = NULL; + + GrLock(&tmpmw, FALSE); + + /* First fill with background style */ + GrSetStuff(STYLE_ERASEALL); + grInformDriver(); + (*grFillRectPtr)(&r); + + for (i = 0; i < DBWNumStyles; i++) + { + mask = DBWStyleToTypes(i); + if (TTMaskHasType(mask, layer)) + { + GrSetStuff(i + TECHBEGINSTYLES + + ((masterPtr->layerOff == 0) ? 0 : DBWNumStyles)); + grInformDriver(); + + /* Solid areas */ + if ((grCurFill == GR_STSOLID) || (grCurFill == GR_STSTIPPLE)) + (*grFillRectPtr)(&r); + + /* Outlines */ + if (grCurOutline != 0) + grDrawOffScreenBox(&r); + + /* Contact crosses */ + if (grCurFill == GR_STCROSS) + { + (*grDrawLinePtr)(r.r_xbot, r.r_ybot, r.r_xtop - 1, + r.r_ytop - 1); + (*grDrawLinePtr)(r.r_xbot, r.r_ytop - 1, r.r_xtop - 1, + r.r_ybot); + } + } + } + + switch(special) { + case LAYER_LABELS: + GrSetStuff(STYLE_LABEL); + grInformDriver(); + grDrawOffScreenBox(&r); + break; + case LAYER_SUBCELL: + GrSetStuff(STYLE_BBOX); + grInformDriver(); + grDrawOffScreenBox(&r); + break; + } + if (masterPtr->layerLock >= 0) { + GrSetStuff(STYLE_BLACK); + grInformDriver(); + GrDrawGlyphNum(masterPtr->layerLock, 0, 0); + } + GrUnlock(&tmpmw); + } + + return; + +error: + + /* + * An error occurred: clear the graphics context in the instance to + * make it clear that this instance cannot be displayed. Then report + * the error. + */ + + if (instancePtr->gc != None) + Tk_FreeGC(grXdpy, instancePtr->gc); + instancePtr->gc = None; + + Tcl_AddErrorInfo(masterPtr->interp, "\n (while configuring image \""); + Tcl_AddErrorInfo(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster)); + Tcl_AddErrorInfo(masterPtr->interp, "\")"); + Tcl_BackgroundError(masterPtr->interp); +} + + +/* + *-------------------------------------------------------------- + * + * ImgLayerCmd -- + * + * This procedure is invoked to process the Tcl command + * that corresponds to an image managed by this module. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *-------------------------------------------------------------- + */ + +static int +ImgLayerCmd(clientData, interp, objc, objv) + ClientData clientData; /* Information about the image master. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + static char *layerOptions[] = {"cget", "configure", (char *) NULL}; + LayerMaster *masterPtr = (LayerMaster *) clientData; + int code, index; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } + if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)layerOptions, + "option", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + switch (index) { + case 0: { + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + return TCL_ERROR; + } + return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs, + (char *) masterPtr, Tcl_GetString(objv[2]), 0); + } + case 1: { + if (objc == 2) { + code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp), + configSpecs, (char *) masterPtr, (char *) NULL, 0); + } else if (objc == 3) { + code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp), + configSpecs, (char *) masterPtr, + Tcl_GetString(objv[2]), 0); + } else { + code = ImgLayerConfigureMaster(masterPtr, objc-2, objv+2, + TK_CONFIG_ARGV_ONLY); + } + return code; + } + default: { + panic("bad const entries to layerOptions in ImgLayerCmd"); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ImgLayerGet -- + * + * This procedure is called for each use of a layer image in a + * widget. + * + * Results: + * The return value is a token for the instance, which is passed + * back to us in calls to ImgLayerDisplay and ImgLayerFree. + * + * Side effects: + * A data structure is set up for the instance (or, an existing + * instance is re-used for the new one). + * + *---------------------------------------------------------------------- + */ + +static ClientData +ImgLayerGet(tkwin, masterData) + Tk_Window tkwin; /* Window in which the instance will be + * used. */ + ClientData masterData; /* Pointer to our master structure for the + * image. */ +{ + LayerMaster *masterPtr = (LayerMaster *) masterData; + LayerInstance *instancePtr; + + /* + * See if there is already an instance for this window. If so + * then just re-use it. + */ + + for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; + instancePtr = instancePtr->nextPtr) { + if (instancePtr->tkwin == tkwin) { + instancePtr->refCount++; + return (ClientData) instancePtr; + } + } + + /* + * The image isn't already in use in this window. Make a new + * instance of the image. + */ + + instancePtr = (LayerInstance *) Tcl_Alloc(sizeof(LayerInstance)); + instancePtr->refCount = 1; + instancePtr->masterPtr = masterPtr; + instancePtr->tkwin = tkwin; + instancePtr->pixmap = None; + instancePtr->gc = None; + instancePtr->nextPtr = masterPtr->instancePtr; + masterPtr->instancePtr = instancePtr; + ImgLayerConfigureInstance(instancePtr); + + /* + * If this is the first instance, must set the size of the image. + */ + + if (instancePtr->nextPtr == NULL) { + Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width, + masterPtr->height); + } + + return (ClientData) instancePtr; +} + +/* + *---------------------------------------------------------------------- + * + * ImgLayerDisplay -- + * + * This procedure is invoked to draw a layer image. + * + * Results: + * None. + * + * Side effects: + * A portion of the image gets rendered in a pixmap or window. + * + *---------------------------------------------------------------------- + */ + +static void +ImgLayerDisplay(clientData, display, drawable, imageX, imageY, width, + height, drawableX, drawableY) + ClientData clientData; /* Pointer to LayerInstance structure for + * for instance to be displayed. */ + Display *display; /* Display on which to draw image. */ + Drawable drawable; /* Pixmap or window in which to draw image. */ + int imageX, imageY; /* Upper-left corner of region within image + * to draw. */ + int width, height; /* Dimensions of region within image to draw. */ + int drawableX, drawableY; /* Coordinates within drawable that + * correspond to imageX and imageY. */ +{ + LayerInstance *instancePtr = (LayerInstance *) clientData; + + /* + * If there's no GC, then an error occurred during image creation + * and it should not be displayed. + */ + + if (instancePtr->gc == None) return; + + XCopyArea(display, instancePtr->pixmap, drawable, instancePtr->gc, + imageX, imageY, (unsigned) width, (unsigned) height, + drawableX, drawableY); +} + +/* + *---------------------------------------------------------------------- + * + * ImgLayerFree -- + * + * This procedure is called when a widget ceases to use a + * particular instance of an image. + * + * Results: + * None. + * + * Side effects: + * Internal data structures get cleaned up. + * + *---------------------------------------------------------------------- + */ + +static void +ImgLayerFree(clientData, display) + ClientData clientData; /* Pointer to LayerInstance structure for + * for instance to be displayed. */ + Display *display; /* Display containing window that used image. */ +{ + LayerInstance *instancePtr = (LayerInstance *) clientData; + LayerInstance *prevPtr; + + instancePtr->refCount--; + if (instancePtr->refCount > 0) { + return; + } + + /* + * There are no more uses of the image within this widget. Free + * the instance structure. + */ + + if (instancePtr->pixmap != None) { + MagWindow *mw; + mw = WindSearchData((ClientData)instancePtr->pixmap); + if (mw != NULL) + { + windUnlink(mw); + windReClip(); + windFree(mw); + } + Tk_FreePixmap(display, instancePtr->pixmap); + } + if (instancePtr->masterPtr->instancePtr == instancePtr) { + instancePtr->masterPtr->instancePtr = instancePtr->nextPtr; + } else { + for (prevPtr = instancePtr->masterPtr->instancePtr; + prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) { + /* Empty loop body */ + } + prevPtr->nextPtr = instancePtr->nextPtr; + } + Tcl_Free((char *) instancePtr); +} + +/* + *---------------------------------------------------------------------- + * + * ImgLayerDelete -- + * + * This procedure is called by the image code to delete the + * master structure for an image. + * + * Results: + * None. + * + * Side effects: + * Resources associated with the image get freed. + * + *---------------------------------------------------------------------- + */ + +static void +ImgLayerDelete(masterData) + ClientData masterData; /* Pointer to BitmapMaster structure for + * image. Must not have any more instances. */ +{ + LayerMaster *masterPtr = (LayerMaster *) masterData; + + if (masterPtr->instancePtr != NULL) { + panic("tried to delete layer image when instances still exist"); + } + masterPtr->tkMaster = NULL; + if (masterPtr->imageCmd != NULL) { + Tcl_DeleteCommandFromToken(masterPtr->interp, masterPtr->imageCmd); + } + Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0); + Tcl_Free((char *) masterPtr); +} + +/* + *---------------------------------------------------------------------- + * + * ImgLayerCmdDeletedProc -- + * + * This procedure is invoked when the image command for an image + * is deleted. It deletes the image. + * + * Results: + * None. + * + * Side effects: + * The image is deleted. + * + *---------------------------------------------------------------------- + */ + +static void +ImgLayerCmdDeletedProc(clientData) + ClientData clientData; /* Pointer to BitmapMaster structure for + * image. */ +{ + LayerMaster *masterPtr = (LayerMaster *) clientData; + + masterPtr->imageCmd = NULL; + if (masterPtr->tkMaster != NULL) { + Tk_DeleteImage(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster)); + } +} + +/* + *--------------------------------------------------------- + * RegisterTkCommands -- + * Register the "magiccolor" command with Tcl. + * Register the layer type with the Tk "image" command + * + * Results: + * None. + * + * Side Effects: + * Command registration with the TCL interpreter. + *--------------------------------------------------------- + */ + +void +RegisterTkCommands(Tcl_Interp *interp) +{ + Tcl_CreateCommand(interp, "magic::magiccolor", + (Tcl_CmdProc *)_magic_magiccolor, (ClientData)NULL, + (Tcl_CmdDeleteProc *)NULL); + Tk_CreateImageType(&tkLayerImageType); +} + +#endif /* MAGIC_WRAPPER */ diff --git a/graphics/grTkCommon.h b/graphics/grTkCommon.h new file mode 100644 index 00000000..be6ebe92 --- /dev/null +++ b/graphics/grTkCommon.h @@ -0,0 +1,46 @@ +/* + * grTkCommon.h --- + * + * Header information common to the Tk and TOGL interfaces + * + */ + +#define MAX_CURSORS 32 + +#define grSmallFont grTkFonts[0] +#define grMediumFont grTkFonts[1] +#define grLargeFont grTkFonts[2] +#define grXLargeFont grTkFonts[3] + +/* Macro for conversion between X and Magic coordinates + * (X11/OpenGL independent) + */ + +#define grXtransY(w, y) (w->w_allArea.r_ytop - (y)) + +/* + * Our default fonts for Tk (X11-style naming conventions). + */ + +#define TK_DEFAULT_FONT "9x15" + +#define TK_FONT_SMALL "-*-helvetica-medium-r-normal--10-*-75-75-p-*-iso8859-*" +#define TK_FONT_MEDIUM "-*-helvetica-medium-r-normal--14-*-75-75-p-*-iso8859-*" +#define TK_FONT_LARGE "-*-helvetica-medium-r-normal--18-*-75-75-p-*-iso8859-*" +#define TK_FONT_XLARGE "-*-helvetica-medium-r-normal--24-*-75-75-p-*-iso8859-*" + +extern void grTkDefineCursor(); +extern void grTkFreeCursors(); + +extern void grtkFreeBackingStore(); +extern void grtkCreateBackingStore(); +extern bool grtkGetBackingStore(); +extern bool grtkScrollBackingStore(); +extern void grtkPutBackingStore(); + +extern Tk_Font grTkFonts[4]; +extern Tk_Cursor grCursors[MAX_CURSORS]; + +extern Display *grXdpy; +extern int grXscrn; + diff --git a/graphics/grTkInt.h b/graphics/grTkInt.h new file mode 100644 index 00000000..3bee9f8a --- /dev/null +++ b/graphics/grTkInt.h @@ -0,0 +1,92 @@ +/* + * grTkInt.h -- + * + * Internal definitions for grTk[1..5].c. + * + * NOTE: In order for the these defs to work correctly, this file + * (grXInt.h) must be included after all the Magic .h files and before + * the X .h files. + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + */ + +#include "utils/magic.h" + +/* Constants + */ +#define M_WIDTH 1023 +#define M_HEIGHT 750 + +#define TK_BATCH_SIZE 10000 + +/* + * Macros for conversion between X and Magic coordinates + */ +#define grMagicToX(y) ( grCurrent.mw->w_allArea.r_ytop - (y)) +#define grXToMagic(y) ( grCurrent.mw->w_allArea.r_ytop - (y)) + +/* Current settings for X function parameters */ +typedef struct { + Tk_Font font; + Tk_Cursor cursor; + int fontSize; + int maskmod; + Tk_Window window; + Window windowid; + MagWindow *mw; +} GR_CURRENT; + +typedef struct { + unsigned long basepixel; + unsigned long planes[32]; + int depth; + int planeCount; + int colorCount; + int realColors; + int red_mask; + int green_mask; + int blue_mask; +} GR_DISPLAY; + +extern Display *grXdpy; +extern Colormap grXcmap; +extern int grXscrn; +extern unsigned long grPixels[]; +extern unsigned long grPlanes[]; +extern GR_CURRENT grCurrent; +extern GR_DISPLAY grDisplay; +extern GC grGCFill, grGCText, grGCDraw, grGCCopy, grGCGlyph; + +extern bool grtkGetCursorPos(); +extern bool grtkGetCursorRootPos(); +extern bool grtkDrawGrid(); +extern void GrTkEnableTablet(); +extern void GrTkDisableTablet(); +extern void GrTkSetCMap(); +extern void grtkPutText(); +extern void grtkFontText(); +extern void GrTkSetCursor(); +extern void GrTkTextSize(); +extern void GrTkDrawGlyph(); +extern void GrTkBitBlt(); +extern void NullBitBlt(); +extern int GrTkReadPixel(); +extern void grtkDrawLine(); +extern void grtkSetLineStyle(); +extern void grtkSetCharSize(); +extern void grtkSetWMandC(); +extern void grtkFillRect(); +extern void grtkRectConvert(); +extern void grtkFillPolygon(); + +extern void grtkDrawLines(); +extern XSegment grtkLines[]; +extern int grtkNbLines; +extern void grtkFillRects(); +extern XRectangle grtkRects[]; +extern int grtkNbRects; + +#define GR_TK_FLUSH_LINES() {if (grtkNbLines>0) {grtkDrawLines(grtkLines, grtkNbLines); grtkNbLines=0;}} +#define GR_TK_FLUSH_RECTS() {if (grtkNbRects>0) {grtkFillRects(grtkRects, grtkNbRects); grtkNbRects=0;}} +#define GR_TK_FLUSH_BATCH() {GR_TK_FLUSH_LINES(); GR_TK_FLUSH_RECTS();} + diff --git a/graphics/grX11Int.h b/graphics/grX11Int.h new file mode 100644 index 00000000..51094c93 --- /dev/null +++ b/graphics/grX11Int.h @@ -0,0 +1,118 @@ +/* + * grX11Int.h -- + * + * Internal definitions for grX11su[1..5].c. + * + * NOTE: In order for the these defs to work correctly, this file + * (grXInt.h) must be included after all the Magic .h files and before + * the X .h files. + */ + +#include "utils/magic.h" + +/* Constants + */ +#define M_WIDTH 1023 +#define M_HEIGHT 750 + +#define MAX_CURSORS 32 /* Maximum number of programmable cursors */ + +#define GR_DEFAULT_FONT "9x15" +#define X11_BATCH_SIZE 10000 + +#define grMagicToX(y) ( grCurrent.mw->w_allArea.r_ytop - (y)) +#define grXToMagic(y) ( grCurrent.mw->w_allArea.r_ytop - (y)) + +#ifdef OLD_R2_FONTS +/* + * Some machines still run release 2 of X. + */ +# define X_FONT_SMALL "vg-13" +# define X_FONT_MEDIUM "fg-18" +# define X_FONT_LARGE "vrb-25" +# define X_FONT_XLARGE "vrb-37" +#else +/* + * Our default fonts for X11. (Release 3 fonts.) + */ + +# define X_FONT_SMALL "-*-helvetica-medium-r-normal--10-*-75-75-p-*-iso8859-*" +# define X_FONT_MEDIUM "-*-helvetica-medium-r-normal--14-*-75-75-p-*-iso8859-*" +# define X_FONT_LARGE "-*-helvetica-medium-r-normal--18-*-75-75-p-*-iso8859-*" +# define X_FONT_XLARGE "-*-helvetica-medium-r-normal--24-*-75-75-p-*-iso8859-*" +#endif + +/* Macro for conversion between X and Magic coordinates + */ + +/* Current settings for X function parameters */ +typedef struct { + XFontStruct *font; + Cursor cursor; + int fontSize; + int maskmod; + Window window; + MagWindow *mw; +} GR_CURRENT; + +/* X11 Display settings determined by the visual */ +typedef struct { + unsigned long basepixel; + unsigned long planes[32]; + int depth; + int planeCount; + int colorCount; + int realColors; + int red_mask; + int green_mask; + int blue_mask; +} GR_DISPLAY; + +extern Display *grXdpy; +extern Colormap grXcmap; +extern int grXscrn; +extern unsigned int grClass; +extern unsigned long grPixels[]; +extern unsigned long grPlanes[]; +extern GR_CURRENT grCurrent; +extern GR_DISPLAY grDisplay; +extern GC grGCFill, grGCText, grGCDraw, grGCCopy, grGCGlyph; + +extern bool grx11GetCursorRootPos(); +extern bool grx11DrawGrid(); +extern void GrX11EnableTablet(); +extern void GrX11DisableTablet(); +extern void GrX11SetCMap(); +extern void grx11PutText(); +extern void grx11FontText(); +extern void grx11DefineCursor(); +extern void GrX11SetCursor(); +extern void GrX11TextSize(); +extern void GrX11DrawGlyph(); +extern void GrX11BitBlt(); +extern void NullBitBlt(); +extern int GrX11ReadPixel(); +extern void grx11DrawLine(); +extern void grx11SetLineStyle(); +extern void grx11SetCharSize(); +extern void grx11SetWMandC(); +extern void grx11FillRect(); +extern void grx11RectConvert(); +extern void grx11FillPolygon(); + +extern void grx11FreeBackingStore(); +extern void grx11CreateBackingStore(); +extern bool grx11GetBackingStore(); +extern bool grx11ScrollBackingStore(); +extern void grx11PutBackingStore(); + +extern void grx11DrawLines(); +extern XSegment grx11Lines[]; +extern int grx11NbLines; +extern void grx11FillRects(); +extern XRectangle grx11Rects[]; +extern int grx11NbRects; + +#define GR_X_FLUSH_LINES() {if (grx11NbLines>0) {grx11DrawLines(grx11Lines, grx11NbLines); grx11NbLines=0;}} +#define GR_X_FLUSH_RECTS() {if (grx11NbRects>0) {grx11FillRects(grx11Rects, grx11NbRects); grx11NbRects=0;}} +#define GR_X_FLUSH_BATCH() {GR_X_FLUSH_LINES(); GR_X_FLUSH_RECTS();} diff --git a/graphics/grX11su1.c b/graphics/grX11su1.c new file mode 100644 index 00000000..17319799 --- /dev/null +++ b/graphics/grX11su1.c @@ -0,0 +1,1445 @@ +/* grX11su1.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains primitive functions to manipulate an X window system + * Included here are initialization and closing + * functions, and several utility routines used by the other X + * modules. + */ + +/* #define HIRESDB */ /* debugging only */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "utils/magic.h" +#include "utils/magsgtty.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "textio/txcommands.h" +#include "utils/signals.h" +#include "graphics/glyphs.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "grX11Int.h" +#include "utils/paths.h" + +extern char *DBWStyleType; + +Display *grXdpy; +int grXscrn; +Colormap grXcmap; +Visual *grVisual; +unsigned int grClass; +GR_CURRENT grCurrent= {0,0,0,0,0,0}; +GR_DISPLAY grDisplay; +GC grGCFill, grGCText,grGCDraw; +GC grGCCopy, grGCGlyph, grGCStipple; + +unsigned long grPixels[256]; +unsigned long grPlanes[256]; +XColor colors[256*3]; /* Unique colors used by Magic */ +Pixmap *grX11Stipples; +HashTable grX11WindowTable; + +/* machine-dependent constants - see below */ + +#ifdef __APPLE__ +#define X_COLORMAP_BASE 128 +#define X_COLORMAP_RESERVED 4 +#else +#if defined(CYGWIN) +#define X_COLORMAP_BASE 128 +#define X_COLORMAP_RESERVED 0 +#else +#define X_COLORMAP_BASE 0 +#define X_COLORMAP_RESERVED 2 +#endif /* CYGWIN */ +#endif + +/* locals */ + +int pipeRead, pipeWrite; /* As seen from parent */ +#ifdef HAVE_PTHREADS +extern int writePipe; +extern int readPipe; /* As seen from child */ +#endif + +typedef struct { + char dashlist[8]; + int dlen; +} LineStyle; + +static LineStyle LineStyleTab[256]; + +int Xhelper; + +#define visual_table_len 7 + +#define grMagicToXs(n) (DisplayHeight(grXdpy,grXscrn)-(n)) +#define grXsToMagic(n) (DisplayHeight(grXdpy,grXscrn)-(n)) + +/* This is kind of a long story, and very kludgy, but the following + * things need to be defined as externals because of the way lint + * libraries are made by taking this module and changing all procedures + * names "Xxxx" to "Grxxx". The change is only done at the declaration + * of the procedure, so we need these declarations to handle uses + * of those names, which don't get modified. Check out the Makefile + * for details on this. + */ + +extern void GrX11Close(), GrX11Flush(); +extern bool GrX11Init(), GrX11Create(); +extern void GrX11Delete(), GrX11Configure(), GrX11Raise(), GrX11Lower(); +extern void GrX11Lock(), GrX11Unlock(), GrX11IconUpdate(); +extern void grXWStdin(); +extern bool grx11GetCursorPos(); + + + +/*--------------------------------------------------------- + * grxSetWMandC: + * This is a local routine that resets the value of the current + * write mask and color, if necessary. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +grx11SetWMandC (mask, c) + int mask; /* New value for write mask */ + int c; /* New value for current color */ +{ + static int oldC = -1; + static int oldM = -1; + + c = grPixels[c]; + if(grDisplay.depth <= 8) { + mask = grPlanes[mask]; + if (mask == -65) mask = AllPlanes; + } + else { + mask = AllPlanes; + } + if (oldC == c && oldM == mask) return; + + GR_X_FLUSH_BATCH(); + XSetPlaneMask(grXdpy,grGCFill,mask); + XSetPlaneMask(grXdpy,grGCDraw,mask); + XSetPlaneMask(grXdpy,grGCText,mask); + XSetForeground(grXdpy,grGCFill,c); + XSetForeground(grXdpy,grGCDraw,c); + XSetForeground(grXdpy,grGCText,c); + oldC = c; + oldM = mask; +} + + +/*--------------------------------------------------------- + * grxSetLineStyle: + * This local routine sets the current line style. + * + * Results: None. + * + * Side Effects: + * A new line style is output to the display. + * + *--------------------------------------------------------- + */ + +void +grx11SetLineStyle (style) + int style; /* New stipple pattern for lines. */ +{ + static int oldStyle = -1; + LineStyle *linestyle; + int xstyle; + + style &= 0xFF; + if (style == oldStyle) return; + oldStyle = style; + GR_X_FLUSH_BATCH(); + + switch (style) { + case 0xFF: + case 0x00: + xstyle = LineSolid; + break; + default: + xstyle = LineOnOffDash; + linestyle = &LineStyleTab[style]; + if (linestyle->dlen == 0) { + + /* translate style to an X11 dashlist */ + + char *e; + int cnt,offset,cur,new,curnew,i,match; + + e = linestyle->dashlist; + cnt = 0; + offset = 1; + cur = 0; + for (i = 7; i >= 0; i--) { + new = (style >> i) & 1; + curnew = (cur << 1) | new; + switch (curnew) { + case 0: + case 3: + cnt++; + break; + case 1: + if (cnt > 0) *e++ = cnt; else offset = 0; + cnt = 1; + break; + case 2: + *e++ = cnt; + cnt = 1; + break; + } + cur = new; + } + *e++ = cnt; + cnt = e - linestyle->dashlist; + if (offset) { + cur = e[0]; + for (i = 0; i < cnt-1; i++) e[i] = e[i+1]; + e[cnt-1] = cur; + } + match = 1; + do { + if (cnt % 2) break; + for (i = 0; i < cnt/2; i++) { + if (e[i] != e[cnt/2 + i]) match = 0; + } + if (match == 0) break; + cnt = cnt/2; + } while (match); + linestyle->dlen = cnt; + } + XSetDashes(grXdpy, grGCDraw, 0, + linestyle->dashlist, linestyle->dlen); + } +#ifdef OLD_XFREE + /* Bypass bug in XFree-2.x server */ + XSetLineAttributes(grXdpy, grGCDraw, 1, + xstyle, CapNotLast, JoinMiter); +#else + XSetLineAttributes(grXdpy, grGCDraw, 0, + xstyle, CapNotLast, JoinMiter); +#endif +} + + +/*--------------------------------------------------------- + * grxSetSPattern: + * xSetSPattern associates a stipple pattern with a given + * stipple number. This is a local routine called from + * grStyle.c . + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +grx11SetSPattern (sttable, numstipples) + int **sttable; /* Table of patterns */ + int numstipples; /* Number of stipples */ +{ + Pixmap p; + int i, x, y, pat; + + grX11Stipples = (Pixmap *)mallocMagic(numstipples * sizeof(Pixmap)); + for (i = 0; i < numstipples; i++) + { + p = XCreatePixmap(grXdpy, XDefaultRootWindow(grXdpy), 8, 8, 1); + if (grGCStipple == NULL) { + grGCStipple = XCreateGC(grXdpy, p, 0, 0); + } + for (y = 0; y < 8; y++) { + pat = sttable[i][y]; + for (x = 0; x < 8; x++) { + XSetForeground(grXdpy, grGCStipple, pat & 1); + XDrawPoint(grXdpy, p, grGCStipple, x, y); + pat >>= 1; + } + } + grX11Stipples[i] = p; + } +} + + +/*--------------------------------------------------------- + * grxSetStipple: + * This routine sets the Xs current stipple number. + * + * Results: None. + * + * Side Effects: + * The current clipmask in the X is set to stipple, + * if it wasn't that already. + *--------------------------------------------------------- + */ + +void +grx11SetStipple (stipple) + int stipple; /* The stipple number to be used. */ +{ + static int oldStip = -1; + if (stipple == oldStip) return; + oldStip = stipple; + GR_X_FLUSH_BATCH(); + if (stipple == 0 || stipple > grNumStipples) { + XSetFillStyle(grXdpy, grGCFill, FillSolid); + } else { + if (grX11Stipples[stipple] == 0) MainExit(1); + XSetStipple(grXdpy, grGCFill, grX11Stipples[stipple]); + XSetFillStyle(grXdpy, grGCFill, FillStippled); + } +} + + +/*--------------------------------------------------------- + * GrX11Init: + * + * GrXInit initializes the graphics display. The depth + * of the display is queried from the server, and the + * "best" visual selected. The environment variable + * "MAGIC_COLOR" can override this choice. A colormap + * is selected based on the visual type, but will be + * filled in later. + * + * Results: TRUE if successful. + *--------------------------------------------------------- + */ + +bool +GrX11Init(dispType) + char *dispType; +{ + int i,j; + XVisualInfo grvisual_info, *grvisual_get, grtemplate; + VisualID defpsvid; + int defpsindex = -1; + int gritems, gritems_list, grcolorCount; + + const char *visual_type[] = { + "StaticGrey", + "GreyScale", + "StaticColor", + "PseudoColor", + "TrueColor", + "DirectColor", + "UNKNOWN" + }; + + int visual_table[visual_table_len]; + char *log_color, *env_str; + int color_base, color_reserved; + int status; + +#ifdef HAVE_PTHREADS + XInitThreads(); +#endif + + grXdpy = XOpenDisplay(NULL); + if (grXdpy == NULL) + { + TxError("Couldn't open display; check DISPLAY variable\n"); + return FALSE; + } + grXscrn = XDefaultScreen(grXdpy); + + grCurrent.window = XDefaultRootWindow(grXdpy); + + /* + * The idea here is to first try allocating the required + * planes out of the default colormap. This is the kindest, + * gentlest thing to do because it doesn't cause all the other + * windows to go technicolor when the cursor is in a magic window. + * If this fails, we go ahead and allocate a colormap specifically + * for magic. The problem now is using this colormap in such + * a way that the other windows' colors get mangled the least. + * Unfortunately, doing this is X-server dependent. This is where + * the constants above come in. X_COLORMAP_BASE indicates + * which part of the colormap (assuming the number of planes + * required is less than the number of planes in the display) + * to fill in the colors magic requires. X_COLORMAP_RESERVED + * tells how many high-end colors the server won't let us touch; + * if we even try to query these colors, we get an X error. + * If, starting at X_COLORMAP_BASE, the number of colors required + * would push us into the top X_COLORMAP_RESERVED colors, then + * we won't be able to set all the colors the user wanted us + * to set. The top colors will remain identical to those + * in the default colormap. + */ + + grXcmap = XDefaultColormap(grXdpy, grXscrn); + + /* Discover properties of the X11 Server. */ + + grVisual = XDefaultVisual(grXdpy, grXscrn); + defpsvid = XVisualIDFromVisual(grVisual); + grtemplate.screen = grXscrn; + grtemplate.depth = 0; + grvisual_get = XGetVisualInfo(grXdpy, VisualScreenMask, &grtemplate, &gritems); + if(grvisual_get == NULL) + { + TxPrintf("Could not obtain Visual Info from Server %s. " + "Will attempt default.\n", getenv("DISPLAY")); + + /* Try to default to 8-bit pseudocolor. May not be a great idea. */ + /* grDisplay.red/green/blue_mask not used. */ + + grDisplay.depth = 8; + grDisplay.colorCount = 1 << grDisplay.depth; + } + else + { +#ifdef HIRESDB + TxPrintf("Server Vendor: %s\n", ServerVendor(grXdpy)); + TxPrintf("Vendor Release: %d\n", VendorRelease(grXdpy)); + TxPrintf("Protocol Version: %d\n", ProtocolVersion(grXdpy)); + TxPrintf("Protocol Revision: %d\n", ProtocolRevision(grXdpy)); + TxPrintf("HOSTTYPE: %s\n", getenv("HOSTTYPE")); + TxPrintf("XGetVisualInfo returned visuals list of length %d:\n", gritems); + TxPrintf("Default VisualID 0x%x\n", defpsvid); +#endif /* HIRESDB */ + + gritems_list = gritems; + for (gritems = 0; gritems < gritems_list; gritems++) + { + j = grvisual_get[gritems].class; + if (j < 0 || j > 5) { + TxPrintf("Unknown visual class index: %d\n", j); + j = 6; + } +#ifdef HIRESDB + TxPrintf("Found Visual Class %s, ID 0x%x with:\n " + "depth %d, colormap_size %d, bits_per_rgb %d.\n", + visual_type[j], grvisual_get[gritems].visualid, + grvisual_get[gritems].depth, + grvisual_get[gritems].colormap_size, + grvisual_get[gritems].bits_per_rgb); + + if (grvisual_get[gritems].class == 4) + TxPrintf(" TrueColor masks: red %06x, green %06x, blue %06x\n", + grvisual_get[gritems].red_mask, + grvisual_get[gritems].green_mask, + grvisual_get[gritems].blue_mask); + +#endif /* HIRESDB */ + + if ((grvisual_get[gritems].class == 3) && + (grvisual_get[gritems].visualid == defpsvid)) + defpsindex = gritems; + } + + /* Unfortunately, the list returned by Xservers has classes in + * random order. Therefore, a search is needed to find a good + * choice. The only currently supported classes are PseudoColor + * at depth 8 and TrueColor at depth 15, 16, and 24. It is likely + * that TrueColor depths 8 through 32 will work, but these have + * not been tested. In addition, it has been discovered that some + * SUN systems "offer" more than one Pseudocolor at depth 8, but + * with differing colormap sizes. There is nothing about how to + * handle this in the X11 documentation, so the search below chooses + * the "first" class. The class with 256 colors seems preferable and + * works at present. The second Pseudocolor in the list gives a + * BatMatch reject from the server, so it is useless. Basing the + * selection on 256 colors might be effective, but might conflict in + * other cases... As usual X11 is just guesswork. At present the + * preferred order is: PseudoColor at 8, then TrueColor at 24, + * then TrueColor at 16, ... Unless this is overridden by the + * MAGIC_COLOR environment variable, which can be: bw, 8, 16, 24 + */ + + for (j = 0; j < visual_table_len; j++) + visual_table[j] = -1; + + for (j = 0; j < gritems_list; j++) + { + if ((grvisual_get[j].class == 0) && (grvisual_get[j].depth == 8) + && (visual_table[1] == -1)) + visual_table[1] = j; /* StaticGrey */ + if ((grvisual_get[j].class == 1) && (grvisual_get[j].depth == 8) + && (visual_table[2] == -1)) + visual_table[2] = j; /* GreyScale */ + if ((grvisual_get[j].class == 3) && (grvisual_get[j].depth == 8) + && (visual_table[3] == -1)) + visual_table[3] = j; /* Pseudocolor */ + if ((grvisual_get[j].class == 4) && (grvisual_get[j].depth == 15) + && (visual_table[4] == -1)) + visual_table[4] = j; /* TrueColor */ + if ((grvisual_get[j].class == 4) && (grvisual_get[j].depth == 16) + && (visual_table[5] == -1)) + visual_table[5] = j; /* TrueColor */ + if ((grvisual_get[j].class == 4) && (grvisual_get[j].depth == 24) + && (visual_table[6] == -1)) + visual_table[6] = j; /* TrueColor */ + } + if (defpsindex != -1) + visual_table[3] = defpsindex; + log_color = getenv("MAGIC_COLOR"); + + if ((log_color == NULL) && (dispType != NULL) && (dispType[0] != 'X')) + log_color = dispType; + + /* Allow environment variables to override the colormap base and */ + /* number of reserved colors, as these depend on the terminal X */ + /* server, NOT on the machine running magic. */ + /* Note: ought to use strtod() in place of atoi()... */ + + env_str = getenv("X_COLORMAP_BASE"); + if (env_str != NULL) + color_base = (int)atoi(env_str); + else + color_base = X_COLORMAP_BASE; + env_str = getenv("X_COLORMAP_RESERVED"); + if (env_str != NULL) + color_reserved = (int)atoi(env_str); + else + color_reserved = X_COLORMAP_RESERVED; + + gritems = -1; + if (log_color != NULL) + { + if (strncmp(log_color, "8", 1) == 0) gritems = visual_table[3]; + if (strncmp(log_color, "15", 2) == 0) gritems = visual_table[4]; + if (strncmp(log_color, "16", 2) == 0) gritems = visual_table[5]; + if (strncmp(log_color, "24", 2) == 0) gritems = visual_table[6]; + if (gritems == -1) { + printf("The visual mode %s is not available. Sorry.\n", log_color); + XFree(grvisual_get); + MainExit(1); + } + } + else + { + if (visual_table[3] != -1) gritems = visual_table[3]; + else if (visual_table[6] != -1) gritems = visual_table[6]; + else if (visual_table[5] != -1) gritems = visual_table[5]; + else if (visual_table[4] != -1) gritems = visual_table[4]; + } + if (gritems == -1) + { + TxPrintf("None of TrueColor 15, 16, or 24, or PseudoColor 8 found. " + "Cannot initialize DISPLAY %s\n", getenv("DISPLAY")); + XFree(grvisual_get); + MainExit(1); + } + else + { + TxPrintf("Using %s, VisualID 0x%x depth %d\n", + visual_type[grvisual_get[gritems].class], + grvisual_get[gritems].visualid, + grvisual_get[gritems].depth); + } + grClass = grvisual_get[gritems].class; + grVisual = grvisual_get[gritems].visual; + grcolorCount = grvisual_get[gritems].colormap_size; + grDisplay.depth = grvisual_get[gritems].depth; + grDisplay.colorCount = grcolorCount; + grDisplay.red_mask = grvisual_get[gritems].red_mask; + grDisplay.green_mask = grvisual_get[gritems].green_mask; + grDisplay.blue_mask = grvisual_get[gritems].blue_mask; + } + XFree(grvisual_get); + grDisplay.planeCount = grDisplay.depth; + grDisplay.realColors = grDisplay.colorCount; + + /* "planeCount" is the number of display planes. "depth" is the */ + /* number of planes magic uses, which may be different. In */ + /* particular, magic uses 7 planes in an 8-plane visual. */ + + if (grDisplay.planeCount == 8) + { + grDisplay.depth = 7; + grDisplay.planeCount = 7; /* This resets to old 7-plane mode */ + grDisplay.colorCount = 1 << (grDisplay.planeCount); + grDisplay.realColors = grDisplay.colorCount; + } + if (grDisplay.depth) + { + status = 0; + if (grClass != 4) + status= XAllocColorCells(grXdpy, grXcmap, TRUE, grDisplay.planes, + grDisplay.planeCount, &grDisplay.basepixel, 1); + if (status == 0) + /* + * Ok, we tried to be nice; now lets whack the default colormap + * and put in one of our own. + */ + { + int actualColors = grcolorCount; + int usableColors = actualColors - color_reserved; + + if (usableColors > 256) usableColors = 256; + if (grClass != 4) + TxPrintf("Unable to allocate %d planes in default colormap; " + "making a new one.\n", grDisplay.planeCount); + if (grDisplay.planeCount <= 8) + { + grDisplay.basepixel = color_base; + grXcmap = XCreateColormap(grXdpy,grCurrent.window, + grVisual, AllocAll); + + } + else + { + grDisplay.basepixel = 0; + grXcmap = XCreateColormap(grXdpy,grCurrent.window, + grVisual, AllocNone); + } + + for (j = 0; j < grDisplay.planeCount; j++) + grDisplay.planes[j] = 1 << j; + status = 1; + for (i = 0; i < usableColors; i++) colors[i].pixel = i; + XQueryColors(grXdpy, XDefaultColormap(grXdpy, + grXscrn), colors, usableColors); + if (grDisplay.planeCount <= 8) + XStoreColors(grXdpy, grXcmap, colors, usableColors); + grDisplay.realColors = (grDisplay.basepixel + + grDisplay.colorCount > usableColors)? usableColors + - grDisplay.basepixel: grDisplay.colorCount; + if ((grDisplay.realColors != grDisplay.colorCount) + && (grDisplay.planeCount <= 8)) + { + TxPrintf("Only %d contiguous colors were available.\n", + grDisplay.realColors); + grDisplay.colorCount = grDisplay.realColors; + } + } + + if (grXcmap == 0 || status == 0) + { + TxError( "X11 setup: Unable to allocate %d planes\n", + grDisplay.planeCount); + MainExit(1); + } + } + + /* There is a non-obvious mapping between plane depth and the names */ + /* of the corresponding style and cmap filenames to load for each */ + /* display type. */ + + switch(grDisplay.depth) { + case 0: case 1: + grDStyleType = "bw"; + grCMapType = NULL; + /* This must be called here; because in B/W the colormap */ + /* is useless, it will not be called by the style file */ + /* load procedure. */ + GrX11SetCMap(); + break; + case 7: case 8: + grDStyleType = "7bit"; + grCMapType = "7bit"; + break; + default: + grDStyleType = "24bit"; + grCMapType = "24bit"; + break; + } + + /* Globally-accessed variables */ + grNumBitPlanes = grDisplay.depth; + grBitPlaneMask = (1 << grDisplay.depth) - 1; + + HashInit(&grX11WindowTable,8,HT_WORDKEYS); + return grx11LoadFont(); +} + + +/*--------------------------------------------------------- + * GrXClose -- + * + * Results: + * None. + * + * Side Effects: + * In the non-pthreads version, kills the helper + * process. In the pthreads version, detaches the + * X11 helper thread. + *--------------------------------------------------------- + */ + +void +GrX11Close () +{ + if (grXdpy == NULL) return; + TxDelete1InputDevice(pipeRead); + close(pipeRead); +#ifndef HAVE_PTHREADS + kill(Xhelper, SIGKILL); + WaitPid (Xhelper, 0); +#endif + if (grGCStipple != NULL) { + XFreeGC(grXdpy, grGCStipple); + grGCStipple = NULL; + } + XCloseDisplay(grXdpy); +#ifdef HAVE_PTHREADS + xloop_end(); +#endif +} + + +/*--------------------------------------------------------- + * GrXFlush: + * Flush output to display. + * + * Flushing is done automatically the next time input is read, + * so this procedure should not be used very often. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +GrX11Flush () +{ + XFlush(grXdpy); +} + + +/* + * --------------------------------------------------------------------------- + * + * grXStdin -- + * + * Handle the stdin device for the X driver. + * + * Results: + * None. + * + * Side Effects: + * Adds events to the data queue. + * + * --------------------------------------------------------------------------- + */ + +void +grX11Stdin() +{ + TxInputEvent *event; + XEvent xevent; + HashEntry *entry; + read(pipeRead, &xevent, sizeof(XEvent)); + switch (xevent.type) + { + case ButtonPress: + case ButtonRelease: + { + XButtonEvent *ButtonEvent = (XButtonEvent *) &xevent; + + event = TxNewEvent(); + switch (ButtonEvent->button) { + case Button1: + event->txe_button = TX_LEFT_BUTTON; + break; + case Button2: + event->txe_button = TX_MIDDLE_BUTTON; + break; + case Button3: + event->txe_button = TX_RIGHT_BUTTON; + break; + case Button4: + event->txe_button = TX_BUTTON_4; + break; + case Button5: + event->txe_button = TX_BUTTON_5; + break; + } + switch(xevent.type) { + case ButtonRelease: + event->txe_buttonAction = TX_BUTTON_UP; + break; + case ButtonPress: + event->txe_buttonAction = TX_BUTTON_DOWN; + break; + } + + grCurrent.window = ButtonEvent->window; + entry = HashLookOnly(&grX11WindowTable,grCurrent.window); + grCurrent.mw= (entry)?(MagWindow *)HashGetValue(entry):0; + + event->txe_p.p_x = ButtonEvent->x; + event->txe_p.p_y = grXToMagic(ButtonEvent->y); + event->txe_wid = grCurrent.mw->w_wid; + TxAddEvent(event); + } + break; + case KeyPress: + { + XKeyPressedEvent *KeyPressedEvent = (XKeyPressedEvent *) &xevent; + int c; + + event = TxNewEvent(); + + grCurrent.window = KeyPressedEvent->window; + entry = HashLookOnly(&grX11WindowTable,grCurrent.window); + grCurrent.mw= (entry)?(MagWindow *)HashGetValue(entry):0; + + read(pipeRead, &c, sizeof(int)); + if (c == (int)'\r') c = (int)'\n'; + event->txe_button = TX_CHARACTER; + event->txe_ch = c; + event->txe_buttonAction = TX_KEY_DOWN; + event->txe_p.p_x = KeyPressedEvent->x; + event->txe_p.p_y = grXToMagic(KeyPressedEvent->y); + event->txe_wid = grCurrent.mw->w_wid; + TxAddEvent(event); + } + break; + case Expose: + { + XExposeEvent *ExposeEvent = (XExposeEvent*) &xevent; + Rect screenRect; + MagWindow *w; + + grCurrent.window = ExposeEvent->window; + entry = HashLookOnly(&grX11WindowTable,grCurrent.window); + w = (entry)?(MagWindow *)HashGetValue(entry):0; + grCurrent.mw=w; + + screenRect.r_xbot = ExposeEvent->x; + screenRect.r_xtop = ExposeEvent->x+ExposeEvent->width; + screenRect.r_ytop = + w->w_allArea.r_ytop-ExposeEvent->y; + screenRect.r_ybot = w->w_allArea.r_ytop - + (ExposeEvent->y + ExposeEvent->height); + + if (w->w_backingStore != (ClientData)NULL) + { + Rect surface; + (*GrGetBackingStorePtr)(w, &screenRect); + WindScreenToSurface(w, &screenRect, &surface); + DBWHLRedrawPrepWindow(w, &surface); + WindDrawBorder(w, &screenRect); + } + else + WindAreaChanged(w, &screenRect); + WindUpdate(); + } + break; + case ConfigureNotify: + { + XConfigureEvent *ConfigureEvent = (XConfigureEvent*) &xevent; + Rect screenRect; + MagWindow *w; + + grCurrent.window = ConfigureEvent->window; + entry = HashLookOnly(&grX11WindowTable,grCurrent.window); + w = (entry)?(MagWindow *)HashGetValue(entry):0; + grCurrent.mw=w; + + screenRect.r_xbot = ConfigureEvent->x; + screenRect.r_xtop = ConfigureEvent->x+ + ConfigureEvent->width; + screenRect.r_ytop = grXsToMagic(ConfigureEvent->y); + screenRect.r_ybot = + grXsToMagic(ConfigureEvent->y+ + ConfigureEvent->height); + + WindReframe(w,&screenRect,FALSE,FALSE); + WindRedisplay(w); + } + break; + case VisibilityNotify: + { + XVisibilityEvent *VisEvent = (XVisibilityEvent*) &xevent; + MagWindow *w; + + entry = HashLookOnly(&grX11WindowTable, VisEvent->window); + w = (entry)?(MagWindow *)HashGetValue(entry):0; + + switch(VisEvent->state) + { + case VisibilityUnobscured: + w->w_flags &= ~WIND_OBSCURED; + if (w->w_backingStore == (ClientData)NULL) + { + grx11CreateBackingStore(w); + if (w->w_backingStore != (ClientData)NULL) + { + WindAreaChanged(w, &w->w_allArea); + WindUpdate(); + } + } + break; + case VisibilityPartiallyObscured: + case VisibilityFullyObscured: + w->w_flags |= WIND_OBSCURED; + break; + } + } + break; + case CreateNotify: + { + XAnyEvent *anyEvent = (XAnyEvent*) &xevent; + MagWindow *w; + + grCurrent.window = anyEvent->window; + entry = HashLookOnly(&grX11WindowTable, grCurrent.window); + w = (entry)?(MagWindow *)HashGetValue(entry):0; + +/* The line above is defintely NOT a good idea. w == 0 causes address + exception. Why X11 is generating an event for a non-existent + window is another question... ***mdg*** */ + + if(w == 0) {printf("CreateNotify: w = %d.\n", w); break;} + SigDisableInterrupts(); + WindView(w); + SigEnableInterrupts(); + } + break; + + default: + break; + + } +} + + +/*--------------------------------------------------------- + * x11SetDisplay: + * This routine sets the appropriate parameters so that + * Magic will work with the X display. + * + * Under Xlib, all input events (mouse and keyboard) are + * sent to one queue which has to be polled to discover + * whether there is any input or not. To fit the Magic + * interrupt-driven input model, a helper process is + * spawned which reads and blocks on the event queue, + * sending SIGIO's to Magic when it detects input. The + * input read in the helper process is then sent to Magic + * via a communication pipe. + * + * Results: success / fail + * + * Side Effects: Sets up the pipe. + *--------------------------------------------------------- + */ + +bool +x11SetDisplay (dispType, outFileName, mouseFileName) + char *dispType; /* arguments not used by X */ + char *outFileName; + char *mouseFileName; +{ + int fildes[2],fildes2[2]; + char *fullname; + FILE* f; + bool execFailed = FALSE; + + WindPackageType = WIND_X_WINDOWS; + WindScrollBarWidth = 14; + grCursorType = "color"; + + /* Set up helper process */ + pipe(fildes); + pipe(fildes2); + pipeRead = fildes[0]; + pipeWrite = fildes2[1]; + + TxAdd1InputDevice(pipeRead, grX11Stdin, (ClientData) NULL); + +#ifdef HAVE_PTHREADS + writePipe = fildes[1]; + readPipe = fildes2[0]; +#else +#ifdef CYGWIN + f = PaOpen(X11HELP_PROG, "r", ".exe", + HELPER_PATH, (char *) NULL, &fullname); +#else + f = PaOpen(X11HELP_PROG, "r", (char *) NULL, + HELPER_PATH, (char *) NULL, &fullname); +#endif + if (f == NULL) { + int error; + TxError("Couldn't find helper process %s in search path \"%s\"\n", + X11HELP_PROG, HELPER_PATH); + error = 0; + write(fildes[1], &error, 4); + return FALSE; + } else { + fclose(f); + } + + FORK(Xhelper); + if (Xhelper == 0) { /* Child process */ + char argv[2][100]; + + sprintf(argv[0], "%s", fullname); + sprintf(argv[1], "%d %d", fildes2[0],fildes[1]); + if (execl(argv[0], argv[0], argv[1], 0) != 0) + { + execFailed = TRUE; + TxError("Couldn't execute helper process \"%s\".\n", fullname); + TxFlush(); + /* we're the child process -- don't muck things up by returning */ + _exit(656); /* see vfork man page for reason for _exit() */ + } + }; + sleep(1); +#endif + + /* Set up the procedure values in the indirection table. */ + + GrLockPtr = GrX11Lock; + GrUnlockPtr = GrX11Unlock; + GrInitPtr = GrX11Init; + GrClosePtr = GrX11Close; + GrSetCMapPtr = GrX11SetCMap; + + GrEnableTabletPtr = GrX11EnableTablet; + GrDisableTabletPtr = GrX11DisableTablet; + GrSetCursorPtr = GrX11SetCursor; + GrTextSizePtr = GrX11TextSize; + GrDrawGlyphPtr = GrX11DrawGlyph; + GrReadPixelPtr = GrX11ReadPixel; + GrFlushPtr = GrX11Flush; + + GrCreateWindowPtr = GrX11Create; + GrDeleteWindowPtr = GrX11Delete; + GrConfigureWindowPtr = GrX11Configure; + GrOverWindowPtr = GrX11Raise; + GrUnderWindowPtr = GrX11Lower; + GrUpdateIconPtr = GrX11IconUpdate; + GrGetCursorPosPtr = grx11GetCursorPos; + GrGetCursorRootPosPtr = grx11GetCursorRootPos; + + /* local indirections */ + grSetSPatternPtr = grx11SetSPattern; + grPutTextPtr = grx11PutText; + grFontTextPtr = grx11FontText; + grDefineCursorPtr = grx11DefineCursor; + GrBitBltPtr = GrX11BitBlt; + + GrFreeBackingStorePtr = grx11FreeBackingStore; + GrCreateBackingStorePtr = grx11CreateBackingStore; + GrGetBackingStorePtr = grx11GetBackingStore; + GrPutBackingStorePtr = grx11PutBackingStore; + GrScrollBackingStorePtr = grx11ScrollBackingStore; + + grDrawGridPtr = grx11DrawGrid; + grDrawLinePtr = grx11DrawLine; + grSetWMandCPtr = grx11SetWMandC; + grFillRectPtr = grx11FillRect; + grSetStipplePtr = grx11SetStipple; + grSetLineStylePtr = grx11SetLineStyle; + grSetCharSizePtr = grx11SetCharSize; + grFillPolygonPtr = grx11FillPolygon; + + if (execFailed) + { + TxError("Execution failed!\n"); + return FALSE; + } + + TxAdd1InputDevice(fileno(stdin), grXWStdin, (ClientData) NULL); + + if (!GrX11Init(dispType)) + { + return FALSE; + } + GrScreenRect.r_xtop = DisplayWidth(grXdpy,grXscrn); + GrScreenRect.r_ytop = DisplayHeight(grXdpy,grXscrn); + + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * grXWStdin -- + * Handle the stdin device for X window interface. + * + * Results: + * None. + * + * Side Effects: + * Adds events to the event queue. + * + * ---------------------------------------------------------------------------- + */ + +void +grXWStdin(fd, cdata) + int fd; + ClientData cdata; +{ + int ch; + TxInputEvent *event; + + event = TxNewEvent(); + ch = getc(stdin); + if (ch == EOF) + event->txe_button = TX_EOF; + else + event->txe_button = TX_CHARACTER; + event->txe_ch = ch; + event->txe_buttonAction = 0; + event->txe_wid = WIND_NO_WINDOW; + event->txe_p.p_x = GR_CURSOR_X; + event->txe_p.p_y = GR_CURSOR_Y; + TxAddEvent(event); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrX11Create -- + * Create a new window under the X window system. + * Bind X window to Magic Window w. + * + * Results: + * Success/Failure + * + * Side Effects: + * Window created, window ID send to Xhelper. + * + * ---------------------------------------------------------------------------- + */ + +bool +GrX11Create(w, name) + MagWindow *w; + char *name; +{ + Window wind; + static int firstWindow = 1; + XSizeHints *xsh; + HashEntry *entry; + char *windowplace; + char *option = (firstWindow)?"window":"newwindow"; + int x = w->w_frameArea.r_xbot; + int y = grMagicToXs(w->w_frameArea.r_ytop); + int width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; + int height = w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; + unsigned long attribmask = CWBackPixel | CWBorderPixel | CWColormap; + XSetWindowAttributes grAttributes; + int grDepth; + + WindSeparateRedisplay(w); + xsh = XAllocSizeHints(); + /* ASSERT(xsh!=0, "failed XAllocSizeHints"); */ + if (windowplace=XGetDefault(grXdpy,"magic",option)) + { + XParseGeometry(windowplace,&x,&y, + (unsigned int *)&width,(unsigned int *)&height); + w->w_frameArea.r_xbot = x; + w->w_frameArea.r_xtop = x+width; + w->w_frameArea.r_ytop = grXsToMagic(y); + w->w_frameArea.r_ybot = grXsToMagic(y+height); + WindReframe(w,&(w->w_frameArea),FALSE,FALSE); + xsh->flags = USPosition | USSize; + } + else + { + xsh->flags = PPosition|PSize; + } + grAttributes.background_pixel = WhitePixel(grXdpy,grXscrn); + grAttributes.border_pixel = BlackPixel(grXdpy,grXscrn); + grAttributes.colormap = grXcmap; + grDepth = grDisplay.depth; + if(grClass == 3) grDepth = 8; /* Needed since grDisplay.depth is reset + to 7 if Pseudocolor */ +#ifdef HIRESDB + TxPrintf("x %d y %d width %d height %d depth %d class %d mask %d\n", + x,y,width,height, grDepth, grClass, attribmask); +#endif /* HIRESDB */ + if ( wind = XCreateWindow(grXdpy, XDefaultRootWindow(grXdpy), + x, y, width, height, 0, grDepth, InputOutput, grVisual, + attribmask, &grAttributes)) + { +#ifdef sun + /* Hint's for Sun's implementation of X11 (News/X11) */ + { + XWMHints wmhints; + wmhints.flags = InputHint; + wmhints.input = TRUE; + XSetWMHints(grXdpy, wind, &wmhints); + } +#endif /* sun */ + + /* + * Signal xhelper to poll window. + */ + grCurrent.window = wind; + /* + * Define window cursor and complete initialization. + */ + xsh->x = w->w_frameArea.r_xbot; + xsh->y = grMagicToXs(w->w_frameArea.r_ytop); + xsh->width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; + xsh->height= w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; + XSetStandardProperties(grXdpy, wind, (name == NULL) ? "magic" + : name, "magic", None, 0, 0, xsh); + XMapWindow(grXdpy, grCurrent.window); + XSync(grXdpy,0); + XFree(xsh); + if (firstWindow) + { + firstWindow = 0; + grGCFill = XCreateGC(grXdpy, grCurrent.window, 0, 0); + grGCDraw = XCreateGC(grXdpy, grCurrent.window, 0, 0); + grGCText = XCreateGC(grXdpy, grCurrent.window, 0, 0); + grGCCopy = XCreateGC(grXdpy, grCurrent.window, 0, 0); + grGCGlyph = XCreateGC(grXdpy, grCurrent.window, 0, 0); + } + XSetPlaneMask(grXdpy,grGCGlyph,AllPlanes); + grCurrent.window = wind; + grCurrent.mw = w; + w->w_grdata = (ClientData) wind; + + entry = HashFind(&grX11WindowTable,grCurrent.window); + HashSetValue(entry,w); + + XDefineCursor(grXdpy, grCurrent.window,grCurrent.cursor); + GrX11IconUpdate(w,w->w_caption); + +#ifdef HAVE_PTHREADS + xloop_create(wind); +#else + XSync(grXdpy,0); + + write( pipeWrite, (char *) &wind, sizeof(Window)); + kill( Xhelper, SIGTERM); +#endif + sleep(1); /* wait for Xhelper to for Expose Events; */ + /* the window new doesn't get painted initially */ + /* otherwise. */ +/* printf("Create call completed.\n"); */ + return 1; + } + else + TxError("Could not open new X window\n"); + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * GrXDelete -- + * Destroy an X window. + * + * Results: + * None. + * + * Side Effects: + * Window destroyed. + * + * ---------------------------------------------------------------------------- + */ + +void +GrX11Delete(w) + MagWindow *w; +{ + Window xw; + HashEntry *entry; + + xw = (Window) w->w_grdata; + entry = HashLookOnly(&grX11WindowTable,xw); + HashSetValue(entry,NULL); + + XDestroyWindow(grXdpy,xw); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrXConfigure -- + * Resize/ Move an existing X window. + * + * Results: + * None. + * + * Side Effects: + * Window reconfigured to w->w_frameArea. + * + * ---------------------------------------------------------------------------- + */ + +void +GrX11Configure(w) + MagWindow *w; +{ + XMoveResizeWindow(grXdpy,(Window) w->w_grdata, + w->w_frameArea.r_xbot, grMagicToXs(w->w_frameArea.r_ytop), + w->w_frameArea.r_xtop - w->w_frameArea.r_xbot, + w->w_frameArea.r_ytop - w->w_frameArea.r_ybot); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrXRaise -- + * Raise a window to the top of the screen such that nothing + * obscures it. + * + * Results: + * None. + * + * Side Effects: + * Window raised. + * + * ---------------------------------------------------------------------------- + */ + +void +GrX11Raise(w) + MagWindow *w; +{ + XRaiseWindow(grXdpy, (Window) w->w_grdata ); +} + +/* + * ---------------------------------------------------------------------------- + * + * GrXLower -- + * Lower a window below all other X windows. + * obscures it. + * + * Results: + * None. + * + * Side Effects: + * Window lowered. + * + * ---------------------------------------------------------------------------- + */ + +void +GrX11Lower(w) + MagWindow *w; +{ + XLowerWindow(grXdpy, (Window) w->w_grdata ); +} + + +/* + * ---------------------------------------------------------------------------- + * + * GrX11Lock -- + * Lock a window and set global variables "grCurrent.window" + * and "grCurrent.mw" to reference the locked window. + * + * Results: + * None. + * + * Side Effects: + * Window locked. + * + * ---------------------------------------------------------------------------- + */ + +void +GrX11Lock(w, flag) + MagWindow *w; + bool flag; +{ + grSimpleLock(w, flag); + if ( w != GR_LOCK_SCREEN ) + { + grCurrent.mw = w; + grCurrent.window = (Window) w->w_grdata; + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * GrX11Unlock -- + * Unlock a window, flushing stuff out to the display. + * + * Results: + * None. + * + * Side Effects: + * Window unlocked. + * Display update. + * + * ---------------------------------------------------------------------------- + */ + +void +GrX11Unlock(w) + MagWindow *w; +{ + GR_X_FLUSH_BATCH(); + grSimpleUnlock(w); +} + + +/* + *------------------------------------------------------------------------- + * + * GrX11IconUpdate -- updates the icon text with the window script + * + * Results: none + * + * Side Effects: changes the icon text + * + *------------------------------------------------------------------------- + */ + +void +GrX11IconUpdate(w,text) + MagWindow *w; + char *text; + +{ + Window wind = (Window)(w->w_grdata); + XClassHint class; + char *brack; + + if (w->w_grdata == (ClientData)NULL) return; + class.res_name = "magic"; + class.res_class = "magic"; + XSetClassHint( grXdpy, wind, &class); + if (brack = strchr(text,'[')) + { + brack--; + *brack = 0; + XSetIconName(grXdpy,wind,text); + XStoreName(grXdpy,wind,text); + *brack = ' '; + return; + } + if (brack = strrchr(text,' ')) text = brack+1; + XSetIconName(grXdpy,wind,text); + XStoreName(grXdpy,wind,text); +} diff --git a/graphics/grX11su2.c b/graphics/grX11su2.c new file mode 100644 index 00000000..10db0ce3 --- /dev/null +++ b/graphics/grX11su2.c @@ -0,0 +1,330 @@ +/* grX11su2.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains additional functions to manipulate an X + * color display. Included here are rectangle drawing and color map + * loading. + */ + +/* #define HIRESDB */ /* debugging only */ + +#include +#include + +#include +#include + +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "grX11Int.h" + +extern char *DBWStyleType; +extern unsigned long grPlanes[256]; +extern unsigned long grPixels[256]; +extern XColor colors[256*3]; /* Unique colors used by Magic */ +extern Colormap grXcmap; + + +/*--------------------------------------------------------- + * GrXSetCMap: + * + * Results: + * None. + * + * Side Effects: + * The values in the color map are set from the system + * colormap (see grCMap.c). X color cells are allocated + * if this display has more than 1 plane. + * + *--------------------------------------------------------- + */ + +void +GrX11SetCMap () +{ + int i, j; + int red, green, blue; + int red_size, green_size, blue_size; + int red_shift, green_shift, blue_shift; + unsigned long grCompleteMask; + + /* grCompleteMask is a mask of all the planes not used by this + * technology. It is OR'd in with the mask that magic supplies + * to ensure that unused bits of the pixel are cleared. + */ + +#ifdef HIRESDB + TxPrintf("planeCount %d, realColors %d\n", grDisplay.planeCount, + grDisplay.realColors); +#endif /* HIRESDB */ + + if (grDisplay.planeCount > 8) { + grCompleteMask = 0; + if (grDisplay.planeCount == 16) + { + red_size = 5; + green_size = 6; + blue_size = 5; + } + else if (grDisplay.planeCount == 15) + { + red_size = 5; + green_size = 5; + blue_size = 5; + } else { + red_size = 8; + green_size = 8; + blue_size = 8; + } + red_shift = green_size + blue_size; + green_shift = blue_size; + if ((grDisplay.planeCount == 24) && (grDisplay.red_mask == 0xff)) + { + /* this is SUN Solaris doing it backwards: BGR */ + red_shift = 0; green_shift = red_size; + blue_shift = green_size + red_size; + } + + /* DANGER! Modify the code below with care: gcc 2.7.2 generates bad */ + /* code if the masks are not used as below. */ + + for (i = 0; i != grDisplay.colorCount; i++) + { + if (!GrGetColor(i, &red, &green, &blue)) break; + + if ((grDisplay.planeCount == 16) || (grDisplay.planeCount ==15)) + { + grPixels[i] = (long)((red >> (8 - red_size)) + << (green_size + blue_size)) & grDisplay.red_mask; /* red */ + grPixels[i] |= (long)((green >> (8 - green_size)) + << blue_size) & grDisplay.green_mask; /* green */ + grPixels[i] |= (long)(blue >> (8 - blue_size)) + & grDisplay.blue_mask; /* blue */ + } + else if ((grDisplay.planeCount == 24) && (grDisplay.red_mask == 0xff)) + { + /* this is SUN Solaris doing it backwards: BGR */ + grPixels[i] = (long)(red & grDisplay.red_mask); + /* here is where gcc really goes wrong (sign extends) */ + grPixels[i] |= (long)((green << green_shift) & grDisplay.green_mask); + grPixels[i] |= (long)((blue << blue_shift) & grDisplay.blue_mask); + } + else { + grPixels[i] = (long)((red << red_shift) & grDisplay.red_mask); + grPixels[i] |= (long)((green << green_shift) & grDisplay.green_mask); + grPixels[i] |= (long)(blue & grDisplay.blue_mask); + } + } + +#ifdef HIRESDB + TxPrintf("grPixels: %6x %6x %6x %6x\n", grPixels[0], grPixels[1], + grPixels[2], grPixels[3]); +#endif /* HIRESDB */ + + for (i = 0; i < grDisplay.planeCount; i++) + { + grDisplay.planes[i] = 1 << i; + grPlanes[i] = 0; + for (j = 0; j != grDisplay.planeCount; j++) + if (i & (1 << j)) + { + grPlanes[i] |= grDisplay.planes[j]; + } + } + } + else { /* grDisplay.planeCount <= 8 */ + + if (grDisplay.planeCount < 0) + { + TxError("number of bit planes must be 0 to 8 in this display."); + GrX11Close(); + MainExit(1); + } + + grCompleteMask = 0; + for (i = 0; i < grDisplay.planeCount; i++) + grCompleteMask |= grDisplay.planes[i]; + + grCompleteMask = AllPlanes & ~grCompleteMask; + + for (i = 0; i != grDisplay.colorCount; i++) + { + grPixels[i] = grDisplay.basepixel; + grPlanes[i] = grCompleteMask; + for (j = 0; j < grDisplay.planeCount; j++) + if (i & (1 << j)) + { + grPixels[i] |= grDisplay.planes[j]; + grPlanes[i] |= grDisplay.planes[j]; + } + } + } + + if (grDisplay.depth) + { + for (i = 0; i < grDisplay.realColors; i++) + { + if (!GrGetColor(i, &red, &green, &blue)) break; + colors[i].pixel = grPixels[i]; + colors[i].red = (unsigned short)(red << 8); + colors[i].green = (unsigned short)(green << 8); + colors[i].blue = (unsigned short)(blue << 8); + colors[i].flags = DoRed | DoGreen | DoBlue; + } + if (grDisplay.planeCount <= 8) + { +#ifdef HIRESDB + TxPrintf("XStoreColors: planeCount %d, realColors %d\n", + grDisplay.planeCount, grDisplay.realColors); +#endif /* HIRESDB */ + XStoreColors(grXdpy, grXcmap, colors, grDisplay.realColors); + } + } + else + { + grPixels[0] = WhitePixel(grXdpy,grXscrn); + grPixels[1] = BlackPixel(grXdpy,grXscrn); + grPlanes[0] = 0; + grPlanes[1] = AllPlanes; + } +} + +XSegment grx11Lines[X11_BATCH_SIZE]; +int grx11NbLines=0; +XRectangle grx11Rects[X11_BATCH_SIZE]; +int grx11NbRects=0; + + +/*--------------------------------------------------------- + * grxDrawLines: + * This routine draws a batch of lines. + * + * Results: None. + * + * Side Effects: + * Draw a bunch of lines. + *--------------------------------------------------------- + */ + +void +grx11DrawLines(lines, nb) + XSegment lines[]; + int nb; +{ + XDrawSegments(grXdpy, grCurrent.window, grGCDraw, + lines, nb); +} + +/*--------------------------------------------------------- + * grxDrawLine: + * This routine draws a line. + * + * Results: None. + * + * Side Effects: + * Draw a line for (x1, y1) to (x2, y2) inclusive. + *--------------------------------------------------------- + */ + +void +grx11DrawLine (x1, y1, x2, y2) + int x1, y1; /* Screen coordinates of first point. */ + int x2, y2; /* Screen coordinates of second point. */ +{ + if (grx11NbLines == X11_BATCH_SIZE) GR_X_FLUSH_LINES(); + grx11Lines[grx11NbLines].x1 = x1; + grx11Lines[grx11NbLines].y1 = grMagicToX(y1); + grx11Lines[grx11NbLines].x2 = x2; + grx11Lines[grx11NbLines].y2 = grMagicToX(y2); + grx11NbLines++; +} + + +/*--------------------------------------------------------- + * grxFillRects: + * This routine draws a bunch of solid rectangles. + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +grx11FillRects(rects, nb) + XRectangle rects[]; + int nb; +{ + XFillRectangles(grXdpy, grCurrent.window, grGCFill, rects, nb); +} + + +/*--------------------------------------------------------- + * grxFillRect: + * This routine draws a solid rectangle. + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +grx11FillRect(r) + Rect *r; /* Address of a rectangle in screen + * coordinates. + */ +{ + if (grx11NbRects == X11_BATCH_SIZE) GR_X_FLUSH_RECTS(); + grx11Rects[grx11NbRects].x = r->r_xbot; + grx11Rects[grx11NbRects].y = grMagicToX(r->r_ytop); + grx11Rects[grx11NbRects].width = r->r_xtop - r->r_xbot + 1; + grx11Rects[grx11NbRects].height = r->r_ytop - r->r_ybot + 1; + grx11NbRects++; +} + +/*--------------------------------------------------------- + * grx11FillPolygon: + * This routine draws a solid polygon + * + * Results: None. + * + * Side Effects: + * Drawing. + *--------------------------------------------------------- + */ + +void +grx11FillPolygon(tp, np) + Point *tp; + int np; +{ + XPoint xp[5]; + int i; + + for (i = 0; i < np; i++) + { + xp[i].x = tp[i].p_x; + xp[i].y = grMagicToX(tp[i].p_y); + } + XFillPolygon(grXdpy, grCurrent.window, grGCFill, xp, np, + Convex, CoordModeOrigin); +} + diff --git a/graphics/grX11su3.c b/graphics/grX11su3.c new file mode 100644 index 00000000..0e9f0212 --- /dev/null +++ b/graphics/grX11su3.c @@ -0,0 +1,851 @@ +/* grX11su3.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains additional functions to manipulate an X window system + * color display. Included here are device-dependent routines to draw and + * erase text and draw a grid. + * + */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "textio/textio.h" +#include "utils/signals.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "dbwind/dbwind.h" +#include "database/fonts.h" +#include "grX11Int.h" + +/* locals */ + +static XFontStruct *grXFonts[4]; +#define grSmallFont grXFonts[0] +#define grMediumFont grXFonts[1] +#define grLargeFont grXFonts[2] +#define grXLargeFont grXFonts[3] + + + +/*--------------------------------------------------------- + * grxDrawGrid: + * grxDrawGrid adds a grid to the grid layer, using the current + * write mask and color. + * + * Results: + * TRUE is returned normally. However, if the grid gets too small + * to be useful, then nothing is drawn and FALSE is returned. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +#define GR_NUM_GRIDS 64 + +bool +grx11DrawGrid (prect, outline, clip) + Rect *prect; /* A rectangle that forms the template + * for the grid. Note: in order to maintain + * precision for the grid, the rectangle + * coordinates are specified in units of + * screen coordinates multiplied by SUBPIXEL. + */ + int outline; /* the outline style */ + Rect *clip; /* a clipping rectangle */ +{ + int xsize, ysize; + int x, y; + int xstart, ystart; + XSegment seg[GR_NUM_GRIDS]; + int snum, low, hi, shifted; + + xsize = prect->r_xtop - prect->r_xbot; + ysize = prect->r_ytop - prect->r_ybot; + if (!xsize || !ysize || GRID_TOO_SMALL(xsize, ysize)) + return FALSE; + + xstart = prect->r_xbot % xsize; + while (xstart < clip->r_xbot << SUBPIXELBITS) xstart += xsize; + ystart = prect->r_ybot % ysize; + while (ystart < clip->r_ybot << SUBPIXELBITS) ystart += ysize; + + grx11SetLineStyle(outline); + + snum = 0; + low = grMagicToX(clip->r_ybot); + hi = grMagicToX(clip->r_ytop); + for (x = xstart; x < (clip->r_xtop + 1) << SUBPIXELBITS; x += xsize) + { + if (snum == GR_NUM_GRIDS) + { + XDrawSegments(grXdpy, grCurrent.window, grGCDraw, seg, snum); + snum = 0; + } + shifted = x >> SUBPIXELBITS; + seg[snum].x1 = shifted; + seg[snum].y1 = low; + seg[snum].x2 = shifted; + seg[snum].y2 = hi; + snum++; + } + XDrawSegments(grXdpy, grCurrent.window, grGCDraw, seg, snum); + + snum = 0; + low = clip->r_xbot; + hi = clip->r_xtop; + for (y = ystart; y < (clip->r_ytop + 1) << SUBPIXELBITS; y += ysize) + { + if (snum == GR_NUM_GRIDS) + { + XDrawSegments(grXdpy, grCurrent.window, grGCDraw, seg, snum); + snum = 0; + } + shifted = grMagicToX(y >> SUBPIXELBITS); + seg[snum].x1 = low; + seg[snum].y1 = shifted; + seg[snum].x2 = hi; + seg[snum].y2 = shifted; + snum++; + } + XDrawSegments(grXdpy, grCurrent.window, grGCDraw, seg, snum); + return TRUE; +} + + +/*--------------------------------------------------------- + * grxLoadFont + * This local routine loads the X fonts used by Magic. + * + * Results: Success/failure + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +bool +grx11LoadFont() +{ + static char *fontnames[4] = { + X_FONT_SMALL, + X_FONT_MEDIUM, + X_FONT_LARGE, + X_FONT_XLARGE }; + static char *optionnames[4] = { + "small", + "medium", + "large", + "xlarge"}; + + int i; + char *unable = "Unable to load font"; + + for (i=0; i!= 4; i++) + { + char *s = XGetDefault(grXdpy,"magic",optionnames[i]); + if (s) fontnames[i] = s; + if ((grXFonts[i] = XLoadQueryFont(grXdpy, fontnames[i])) == NULL) + { + TxError("%s %s\n",unable,fontnames[i]); + if ((grXFonts[i]= XLoadQueryFont(grXdpy,GR_DEFAULT_FONT))==NULL) + { + TxError("%s %s\n",unable,GR_DEFAULT_FONT); + return FALSE; + } + } + } + return TRUE; +} + + +/*--------------------------------------------------------- + * grxSetCharSize: + * This local routine sets the character size in the display, + * if necessary. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +grx11SetCharSize (size) + int size; /* Width of characters, in pixels (6 or 8). */ +{ + grCurrent.fontSize = size; + switch (size) + { + case GR_TEXT_DEFAULT: + case GR_TEXT_SMALL: + grCurrent.font = grSmallFont; + break; + case GR_TEXT_MEDIUM: + grCurrent.font = grMediumFont; + break; + case GR_TEXT_LARGE: + grCurrent.font = grLargeFont; + break; + case GR_TEXT_XLARGE: + grCurrent.font = grXLargeFont; + break; + default: + TxError("%s%d\n", "grx11SetCharSize: Unknown character size ", + size ); + break; + } +} + + +/* + * ---------------------------------------------------------------------------- + * GrXTextSize -- + * + * Determine the size of a text string. + * + * Results: + * None. + * + * Side effects: + * A rectangle is filled in that is the size of the text in pixels. + * The origin (0, 0) of this rectangle is located on the baseline + * at the far left side of the string. + * ---------------------------------------------------------------------------- + */ + +void +GrX11TextSize(text, size, r) + char *text; + int size; + Rect *r; +{ + XCharStruct overall; + XFontStruct *font; + int dir,fa,fd; + + switch (size) { + case GR_TEXT_DEFAULT: + case GR_TEXT_SMALL: + font = grSmallFont; + break; + case GR_TEXT_MEDIUM: + font = grMediumFont; + break; + case GR_TEXT_LARGE: + font = grLargeFont; + break; + case GR_TEXT_XLARGE: + font = grXLargeFont; + break; + default: + TxError("%s%d\n", "GrX11TextSize: Unknown character size ", + size ); + break; + } + if (font == NULL) return; + XTextExtents(font, text, strlen(text), &dir, &fa, &fd, &overall); + r->r_ytop = overall.ascent; + r->r_ybot = -overall.descent; + r->r_xtop = overall.width - overall.lbearing; + r->r_xbot = -overall.lbearing - 1; +} + + +/* + * ---------------------------------------------------------------------------- + * GrXReadPixel -- + * + * Read one pixel from the screen. + * + * Results: + * An integer containing the pixel's color. + * + * Side effects: + * none. + * + * ---------------------------------------------------------------------------- + */ + +int +GrX11ReadPixel (w, x, y) + MagWindow *w; + int x,y; /* the location of a pixel in screen coords */ +{ + XImage *image; + unsigned long value; + XWindowAttributes att; + + XGetWindowAttributes(grXdpy,grCurrent.window, &att); + if ( x < 0 || x >= att.width || grMagicToX(y) < 0 + || grMagicToX(y) >= att.height) + return(0); + image = XGetImage(grXdpy, grCurrent.window, x, grMagicToX(y), 1, 1, + ~0, ZPixmap); + value = XGetPixel(image, 0, 0); + return (value & (1 << grDisplay.depth) - 1); +} + + +/* + * ---------------------------------------------------------------------------- + * GrXBitBlt -- + * + * Copy information in bit block transfers. + * + * Results: + * None. + * + * Side effects: + * changes the screen. + * ---------------------------------------------------------------------------- + */ + +void +GrX11BitBlt(r, p) + Rect *r; + Point *p; +{ + Drawable wind = (Drawable)grCurrent.window; + + XCopyArea(grXdpy, wind, wind, grGCCopy, + r->r_xbot, grMagicToX(r->r_ytop), + r->r_xtop - r->r_xbot + 1, r->r_ytop - r->r_ybot + 1, + p->p_x, grMagicToX(p->p_y)); +} + +static GC grXcopyGC = (GC)NULL; + +/* + * ---------------------------------------------------------------------------- + * grx11FreeBackingStore -- + * Free up Pixmap memory for a backing store cell. + * + * Results: + * None. + * + * Side effects: + * memory Free'd + * ---------------------------------------------------------------------------- + */ + +void +grx11FreeBackingStore(MagWindow *window) +{ + Pixmap pmap = (Pixmap)window->w_backingStore; + if (pmap == (Pixmap)NULL) return; + XFreePixmap(grXdpy, pmap); + window->w_backingStore = (ClientData)NULL; + /* XFreeGC(grXdpy, grXcopyGC); */ + /* TxPrintf("grx11FreeBackingStore called\n"); */ +} + +/* + * ---------------------------------------------------------------------------- + * grx11CreateBackingStore -- + * Create Pixmap memory for a backing store cell and copy data + * from the window into it. + * + * Results: + * None. + * + * Side effects: + * memory Allocated. + * + * ---------------------------------------------------------------------------- + */ + +void +grx11CreateBackingStore(MagWindow *w) +{ + Pixmap pmap; + Window wind = (Window)w->w_grdata; + unsigned int width, height; + GC gc; + XGCValues gcValues; + int grDepth; + + /* ignore for all windows except layout */ + if (w->w_client != DBWclientID) return; + + /* deferred */ + if (w->w_grdata == (Window)NULL) return; + + width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + + if (w->w_backingStore != (ClientData)NULL) grx11FreeBackingStore(w); + + if (grXcopyGC == (GC)NULL) + { + gcValues.graphics_exposures = FALSE; + grXcopyGC = XCreateGC(grXdpy, wind, GCGraphicsExposures, &gcValues); + } + + grDepth = grDisplay.depth; + if(grClass == 3) grDepth = 8; /* Needed since grDisplay.depth is reset + to 7 if Pseudocolor */ + + pmap = XCreatePixmap(grXdpy, wind, width, height, grDepth); + w->w_backingStore = (ClientData)pmap; + + /* TxPrintf("grx11CreateBackingStore area %d %d %d %d\n", + w->w_screenArea.r_xbot, w->w_screenArea.r_ybot, + w->w_screenArea.r_xtop, w->w_screenArea.r_ytop); */ +} + +/* + * ---------------------------------------------------------------------------- + * grx11GetBackingStore -- + * Copy data from a backing store Pixmap into the indicated window. + * + * Results: + * TRUE if backing store was copied successfully, FALSE if not. + * + * Side effects: + * Data copied into Pixmap memory. + * + * ---------------------------------------------------------------------------- + */ + +bool +grx11GetBackingStore(MagWindow *w, Rect *area) +{ + Pixmap pmap; + Window wind = (Window)w->w_grdata; + unsigned int width, height; + int ybot; + int xoff, yoff; + Rect r; + + pmap = (Pixmap)w->w_backingStore; + if (pmap == (Pixmap)NULL) + return FALSE; + + /* Make a local copy of area so we don't disturb the original */ + r = *area; + GeoClip(&r, &(w->w_screenArea)); + + width = r.r_xtop - r.r_xbot; + height = r.r_ytop - r.r_ybot; + ybot = grMagicToX(r.r_ytop); + + xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot; + yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop; + + XCopyArea(grXdpy, pmap, wind, grXcopyGC, r.r_xbot - xoff, ybot - yoff, + width, height, r.r_xbot, ybot); + + /* TxPrintf("grx11GetBackingStore %d %d %d %d\n", + r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop); */ + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * grx11ScrollBackingStore -- + * Enable fast scrolling by shifting part of the backing store + * from one position to another, with the amount of shift indicated + * by the X and/or Y value of the indicated point. + * + * Results: + * TRUE on success, FALSE on failure. + * + * Side effects: + * Data shifted in Pixmap memory. + * + * ---------------------------------------------------------------------------- + */ + +bool +grx11ScrollBackingStore(MagWindow *w, Point *shift) +{ + Pixmap pmap; + unsigned int width, height; + int xorigin, yorigin, xshift, yshift; + + pmap = (Pixmap)w->w_backingStore; + if (pmap == (Pixmap)NULL) + { + TxPrintf("grx11ScrollBackingStore %d %d failure\n", + shift->p_x, shift->p_y); + return FALSE; + } + + width = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + height = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + xorigin = 0; + yorigin = 0; + xshift = shift->p_x; + yshift = -shift->p_y; + + if (xshift > 0) + width -= xshift; + else if (xshift < 0) + { + width += xshift; + xorigin = -xshift; + xshift = 0; + } + if (yshift > 0) + height -= yshift; + else if (yshift < 0) + { + height += yshift; + yorigin = -yshift; + yshift = 0; + } + + XCopyArea(grXdpy, pmap, pmap, grXcopyGC, xorigin, yorigin, width, height, + xshift, yshift); + + /* TxPrintf("grx11ScrollBackingStore %d %d\n", shift->p_x, shift->p_y); */ + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * grx11PutBackingStore -- + * Copy data from the window into backing store. + * + * Results: + * None. + * + * Side effects: + * Graphics drawing into the window. + * ---------------------------------------------------------------------------- + */ + +void +grx11PutBackingStore(MagWindow *w, Rect *area) +{ + Pixmap pmap = (Pixmap)w->w_backingStore; + Window wind = (Window)w->w_grdata; + unsigned int width, height; + int ybot, xoff, yoff; + + if (pmap == (Pixmap)NULL) return; + + /* Attempting to write backing store into an obscured */ + /* window immediately invalidates everything in backing */ + /* store. This is extreme, but is much simpler and under */ + /* normal conditions faster than tracking all obscured */ + /* areas separately. */ + + if (w->w_flags & WIND_OBSCURED) + { + grx11FreeBackingStore(w); + w->w_backingStore = (ClientData)NULL; + return; + } + + width = area->r_xtop - area->r_xbot; + height = area->r_ytop - area->r_ybot; + ybot = grMagicToX(area->r_ytop); + + xoff = w->w_screenArea.r_xbot - w->w_allArea.r_xbot; + yoff = w->w_allArea.r_ytop - w->w_screenArea.r_ytop; + + XCopyArea(grXdpy, wind, pmap, grXcopyGC, area->r_xbot, ybot, + width, height, area->r_xbot - xoff, ybot - yoff); + + /* TxPrintf("grx11PutBackingStore %d %d %d %d\n", + area->r_xbot, area->r_ybot, area->r_xtop, area->r_ytop); */ +} + +/* + * ---------------------------------------------------------------------------- + * GrX11RectConvert -- + * Convert a magic rectangle into an X11 rectangle + * (Both passed as pointers) + * + * Results: + * None. + * + * Side effects: + * Converted value returned in xr. + * ---------------------------------------------------------------------------- + */ + +void +grx11RectConvert(mr, xr) + Rect *mr; + XRectangle *xr; +{ + xr->x = mr->r_xbot; + xr->y = grMagicToX(mr->r_ytop); + xr->width = mr->r_xtop - mr->r_xbot + 1; + xr->height = mr->r_ytop - mr->r_ybot + 1; +} + +/* + *--------------------------------------------------------- + * grx11FontText: + * + * This routine is a fancier version of grx11PutText used for + * drawing vector outline fonts from the fontList records. + * + *--------------------------------------------------------- + */ + +void +grx11FontText(text, font, size, rotate, pos, clip, obscure) + char *text; + int font; + int size; /* pixel size of the text */ + int rotate; /* text rotation */ + Point *pos; /* text base position */ + Rect *clip; + LinkedRect *obscure; +{ + char *tptr; + FontChar *ccur, *clist; + Point *coffset, *tp, loffset, locoffset, corners[4], lpos; + Rect *cbbox, charbbox, *frect; + int np, i, j, w, h, llx, lly, baseline; + XPoint *xp; + Pixmap pxm; + double fscale, scx, scy, tmpx, tmpy, rrad, cr, sr; + static GC fontgc = (GC)NULL; + + frect = &DBFontList[font]->mf_extents; + fscale = (double)size / (double)frect->r_ytop; + rrad = (double)rotate * 0.0174532925; + cr = cos(rrad); + sr = sin(rrad); + lpos = GeoOrigin; + + /* 1st pass: find the descent of the string */ + + baseline = 0; + for (tptr = text; *tptr != '\0'; tptr++) + { + DBFontChar(font, *tptr, NULL, NULL, &cbbox); + if (cbbox->r_ybot < -baseline) + baseline = -cbbox->r_ybot; + } + baseline = (int)((double)baseline * fscale); + + for (tptr = text; *tptr != '\0'; tptr++) + { + scx = (double)lpos.p_x * fscale; + scy = (double)lpos.p_y * fscale; + + tmpx = scx * cr + scy * sr; + tmpy = scy * cr - scx * sr; + + loffset.p_x = pos->p_x + (int)round(tmpx); + loffset.p_y = grMagicToX(pos->p_y + baseline) + (int)round(tmpy); + + DBFontChar(font, *tptr, &clist, &coffset, &cbbox); + np = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + np += ccur->fc_numpoints; + + xp = (XPoint *)mallocMagic(np * sizeof(XPoint)); + + j = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + { + tp = ccur->fc_points; + for (i = 0; i < ccur->fc_numpoints; i++, j++) + { + scx = (double)tp[i].p_x * fscale; + scy = (double)tp[i].p_y * fscale; + + tmpx = scx * cr - scy * sr; + tmpy = scx * sr + scy * cr; + + xp[j].x = (int)round(tmpx); + xp[j].y = (int)round(tmpy); + + /* Initialize bounding box */ + if (j == 0) + { + charbbox.r_xbot = charbbox.r_xtop = xp[j].x; + charbbox.r_ybot = charbbox.r_ytop = xp[j].y; + } + else + { + if (xp[j].x < charbbox.r_xbot) + charbbox.r_xbot = xp[j].x; + else if (xp[j].x > charbbox.r_xtop) + charbbox.r_xtop = xp[j].x; + if (xp[j].y < charbbox.r_ybot) + charbbox.r_ybot = xp[j].y; + else if (xp[j].y > charbbox.r_ytop) + charbbox.r_ytop = xp[j].y; + } + } + } + + /* Create a bitmap */ + + w = charbbox.r_xtop - charbbox.r_xbot + 1; + h = charbbox.r_ytop - charbbox.r_ybot + 1; + + /* Adjust all points to the bounding box origin, and invert Y */ + for (j = 0; j < np; j++) + { + xp[j].x -= charbbox.r_xbot; + xp[j].y = charbbox.r_ytop - xp[j].y; + } + + pxm = XCreatePixmap(grXdpy, grCurrent.window, w, h, 1); + + if (fontgc == (GC)NULL) + { + XGCValues values; + values.foreground = 0; + values.background = 0; + fontgc = XCreateGC(grXdpy, pxm, GCForeground | GCBackground, &values); + } + + locoffset.p_x = loffset.p_x + charbbox.r_xbot; + locoffset.p_y = loffset.p_y - charbbox.r_ytop; + + XSetForeground(grXdpy, fontgc, 0); + XSetFunction(grXdpy, fontgc, GXcopy); + XFillRectangle(grXdpy, pxm, fontgc, 0, 0, w, h); + XSetFunction(grXdpy, fontgc, GXxor); + XSetForeground(grXdpy, fontgc, 1); + + j = 0; + for (ccur = clist; ccur != NULL; ccur = ccur->fc_next) + { + np = ccur->fc_numpoints; + XFillPolygon(grXdpy, pxm, fontgc, &xp[j], np, Complex, CoordModeOrigin); + j += np; + } + freeMagic((char *)xp); + + XSetClipMask(grXdpy, grGCText, pxm); + XSetClipOrigin(grXdpy, grGCText, locoffset.p_x, locoffset.p_y); + XFillRectangle(grXdpy, grCurrent.window, grGCText, locoffset.p_x, + locoffset.p_y, w, h); + + lpos.p_x += coffset->p_x; + lpos.p_y += coffset->p_y; + + XFreePixmap(grXdpy, pxm); + } +} + +/*--------------------------------------------------------- + * grxPutText: + * (modified on SunPutText) + * + * This routine puts a chunk of text on the screen in the current + * color, size, etc. The caller must ensure that it fits on + * the screen -- no clipping is done except to the obscuring rectangle + * list and the clip rectangle. + * + * Results: + * none. + * + * Side Effects: + * The text is drawn on the screen. + * + *--------------------------------------------------------- + */ + +void +grx11PutText (text, pos, clip, obscure) + char *text; /* The text to be drawn. */ + Point *pos; /* A point located at the leftmost point of + * the baseline for this string. + */ + Rect *clip; /* A rectangle to clip against */ + LinkedRect *obscure; /* A list of obscuring rectangles */ + +{ + Rect location; + Rect overlap; + Rect textrect; + LinkedRect *ob; + void grX11suGeoSub(); + + if (grCurrent.font == NULL) return; + + GrX11TextSize(text, grCurrent.fontSize, &textrect); + + location.r_xbot = pos->p_x + textrect.r_xbot; + location.r_xtop = pos->p_x + textrect.r_xtop; + location.r_ybot = pos->p_y + textrect.r_ybot; + location.r_ytop = pos->p_y + textrect.r_ytop; + + /* erase parts of the bitmap that are obscured */ + for (ob = obscure; ob != NULL; ob = ob->r_next) + { + if (GEO_TOUCH(&ob->r_r, &location)) + { + overlap = location; + GeoClip(&overlap, &ob->r_r); + grX11suGeoSub(&location, &overlap); + } + } + + overlap = location; + GeoClip(&overlap, clip); + + /* copy the text to the color screen */ + if ((overlap.r_xbot < overlap.r_xtop)&&(overlap.r_ybot <= overlap.r_ytop)) + { + XRectangle xr; + + XSetFont(grXdpy, grGCText, grCurrent.font->fid); + grx11RectConvert(&overlap, &xr); + XSetClipRectangles(grXdpy, grGCText, 0, 0, &xr, 1, Unsorted); + XDrawString(grXdpy, grCurrent.window, grGCText, + pos->p_x, grMagicToX(pos->p_y), + text, strlen(text)); + } +} + + +/* + *--------------------------------------------------------- + * grX11suGeoSub -- + * return the tallest sub-rectangle of r not obscured by area + * area must be within r. + * + * Results: + * None. + * + * Side effects: + * Source rectangle "r" is modified. + *--------------------------------------------------------- + */ + +void +grX11suGeoSub(r, area) + Rect *r; /* Rectangle to be subtracted from. */ + Rect *area; /* Area to be subtracted. */ +{ + if (r->r_xbot == area->r_xbot) r->r_xbot = area->r_xtop; + else + if (r->r_xtop == area->r_xtop) r->r_xtop = area->r_xbot; + else + if (r->r_ybot <= area->r_ybot) r->r_ybot = area->r_ytop; + else + if (r->r_ytop == area->r_ytop) r->r_ytop = area->r_ybot; + else + r->r_xtop = area->r_xbot; +} diff --git a/graphics/grX11su4.c b/graphics/grX11su4.c new file mode 100644 index 00000000..a2f4b725 --- /dev/null +++ b/graphics/grX11su4.c @@ -0,0 +1,137 @@ +/* grX11su4.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains functions to manage the graphics tablet associated + * with the X display. + * + */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/magsgtty.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "textio/txcommands.h" +#include "grX11Int.h" + + +/*--------------------------------------------------------- + * GrXDisableTablet: + * Turns off the cursor. + * + * Results: None. + * + * Side Effects: None. + *--------------------------------------------------------- + */ + +void +GrX11DisableTablet() +{ +} + + +/*--------------------------------------------------------- + * GrXEnableTablet: + * This routine enables the graphics tablet. + * + * Results: + * None. + * + * Side Effects: + * Simply turn on the crosshair. + *--------------------------------------------------------- + */ + +void +GrX11EnableTablet() +{ +} + + +/* + * ---------------------------------------------------------------------------- + * grx11GetCursorPos: + * Read the cursor position in magic coordinates. + * + * Results: + * TRUE is returned if the coordinates were succesfully read, FALSE + * otherwise. + * + * Side effects: + * The parameter is filled in with the cursor position, in the form of + * a point in screen coordinates. + * ---------------------------------------------------------------------------- + */ + +bool +grx11GetCursorPos (mw, p) + MagWindow *mw; + Point *p; /* point to be filled in with screen coordinates */ +{ + int x, y, x1, y1; + unsigned int buttons; + Window win1, win2; + + if (mw == (MagWindow *)NULL) mw = grCurrent.mw; + + XQueryPointer(grXdpy, (Window)mw->w_grdata, + &win1, &win2, &x1, &y1, + &x, &y, &buttons); + p->p_x = x; + p->p_y = grMagicToX(y); + + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * grx11GetCursorRootPos: + * Read the cursor position in screen root coordinates. + * + * Results: + * TRUE is returned if the coordinates were succesfully read, FALSE + * otherwise. + * + * Side effects: + * The parameter is filled in with the cursor position, in the form of + * a point in screen coordinates. + * ---------------------------------------------------------------------------- + */ + +bool +grx11GetCursorRootPos (mw, p) + MagWindow *mw; + Point *p; /* point to be filled in with root coordinates */ +{ + int x, y, x1, y1; + unsigned int buttons; + Window win1, win2; + + if (mw == (MagWindow *)NULL) mw = grCurrent.mw; + + XQueryPointer(grXdpy, (Window)mw->w_grdata, + &win1, &win2, &x1, &y1, + &x, &y, &buttons); + p->p_x = x1; + p->p_y = y1; + + return TRUE; +} diff --git a/graphics/grX11su5.c b/graphics/grX11su5.c new file mode 100644 index 00000000..38b70b7b --- /dev/null +++ b/graphics/grX11su5.c @@ -0,0 +1,326 @@ +/* grX11su5.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * Manipulate the programable cursor on the graphics display. + * + */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/styles.h" +#include "utils/hash.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/graphics.h" +#include "graphics/glyphs.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "grX11Int.h" + +extern HashTable grX11WindowTable; +extern XColor colors[]; +/* locals */ + +Cursor grCursors[MAX_CURSORS]; + + +/* + * ---------------------------------------------------------------------------- + * GrXDrawGlyph -- + * + * Draw one glyph on the display. + * + * Results: + * None. + * + * Side effects: + * Draws pixels. + * ---------------------------------------------------------------------------- + */ + +void +GrX11DrawGlyph (gl, p) + GrGlyph *gl; /* A single glyph */ + Point *p; /* screen pos of lower left corner */ +{ + Rect bBox; + bool anyObscure; + LinkedRect *ob; + + GR_CHECK_LOCK(); + bBox.r_ll = *p; + bBox.r_xtop = p->p_x + gl->gr_xsize - 1; + bBox.r_ytop = p->p_y + gl->gr_ysize - 1; + + anyObscure = FALSE; + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) { + if (GEO_TOUCH( &(ob->r_r), &bBox)) { + anyObscure = TRUE; + break; + } + } + if(grDisplay.depth <= 8) { + XSetPlaneMask(grXdpy, grGCGlyph, grPlanes[127]); } + XSetFillStyle(grXdpy, grGCGlyph, FillSolid); + if ((!anyObscure) && (GEO_SURROUND(&grCurClip, &bBox)) ) { + int *pixelp, x, y; + + /* no clipping, try to go quickly */ + pixelp = gl->gr_pixels; + for (y = 0; y < gl->gr_ysize; y++) { + int x1, y1; + + y1 = grMagicToX(bBox.r_ybot + y); + for (x = 0; x < gl->gr_xsize; x++) { + int color; + if (*pixelp != 0) { + color = GrStyleTable[*pixelp].color; + x1 = bBox.r_xbot + x; + XSetForeground(grXdpy, grGCGlyph, grPixels[color]); + XDrawPoint(grXdpy, grCurrent.window, grGCGlyph, x1, y1); + } + pixelp++; + } + } + } else { + /* do pixel by pixel clipping */ + int y, yloc; + + yloc = bBox.r_ybot; + for (y = 0; y < gl->gr_ysize; y++) { + int startx, endx; + if ( (yloc <= grCurClip.r_ytop) && (yloc >= grCurClip.r_ybot) ) { + int laststartx; + laststartx = bBox.r_xbot - 1; + for (startx = bBox.r_xbot; startx <= bBox.r_xtop; + startx = endx + 1) { + int *pixelp; + + startx = MAX(startx, grCurClip.r_xbot); + endx = MIN(bBox.r_xtop, grCurClip.r_xtop); + + if (anyObscure) { + for (ob = grCurObscure; ob != NULL; ob = ob->r_next) { + if ( (ob->r_r.r_ybot <= yloc) && + (ob->r_r.r_ytop >= yloc) ) { + if (ob->r_r.r_xbot <= startx) + startx = MAX(startx, ob->r_r.r_xtop + 1); + else if (ob->r_r.r_xbot <= endx) + endx = MIN(endx, ob->r_r.r_xbot - 1); + } + } + } + + /* stop if we aren't advancing */ + if (startx == laststartx) break; + laststartx = startx; + if (startx > endx) continue; + + /* draw a section of this scan line */ + pixelp = &( gl->gr_pixels[y*gl->gr_xsize + + (startx - bBox.r_xbot)]); + for ( ; startx <= endx; startx++) { + int color; + if (*pixelp != 0) { + color = GrStyleTable[*pixelp].color; + XSetForeground(grXdpy, grGCGlyph, grPixels[color]); + XDrawPoint(grXdpy, grCurrent.window, grGCGlyph, + startx, grMagicToX(yloc)); + } + pixelp++; + } + startx = endx + 1; + } + } + yloc++; + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * grxDefineCursor: + * + * Define a new set of cursors. + * + * Results: + * None. + * + * Side effects: + * The given matrix is stored in the graphics display, and it can be + * used as the cursor by calling GrSetCursor. + * ---------------------------------------------------------------------------- + */ + +void +grx11DefineCursor(glyphs) + GrGlyphs *glyphs; +{ + int glyphnum; + Rect oldClip; + XColor fgcolor, bgcolor; + Pixmap source, mask; + + if (glyphs->gr_num <= 0) return; + + if (glyphs->gr_num > MAX_CURSORS) + { + TxError("X only has room for %d cursors\n", MAX_CURSORS); + return; + } + + /* expand clipping amount for off-screen access on the X */ + GrLock(GR_LOCK_SCREEN, FALSE); + oldClip = grCurClip; + grCurClip = GrScreenRect; + grCurClip.r_ytop += 16; + + /* enter the glyphs */ + for (glyphnum = 0; glyphnum < glyphs->gr_num; glyphnum++) { + + int i, *p, fgstyle; + GrGlyph *g; + int x, y; + unsigned char curs[32]; + unsigned char mbits[32]; + + g = glyphs->gr_glyph[glyphnum]; + if ((g->gr_xsize != 16) || (g->gr_ysize != 16)) { + TxError("Cursors for the X must be 16 X 16 pixels.\n"); + return; + } + + /* Pick off the non-transparent color and find the */ + /* corresponding display color. If there are two */ + /* colors other than background, we treat them as */ + /* foreground and background, without regard to order. */ + + p = &(g->gr_pixels[0]); + fgstyle = STYLE_TRANSPARENT; + for (x = 0; x < 256; x++) + { + if (*p != STYLE_TRANSPARENT) + { + fgstyle = *p; + fgcolor.pixel = grPixels[GrStyleTable[*p].color]; + XQueryColor(grXdpy, grXcmap, &fgcolor); + break; + } + p++; + } + + if (x == 256) + { + fgcolor.pixel = BlackPixel(grXdpy, grXscrn); + fgcolor.red=0; + fgcolor.green=0; + fgcolor.blue=0; + fgcolor.flags=DoRed|DoGreen|DoBlue; + } + + for (; x < 256; x++) + { + if ((*p != STYLE_TRANSPARENT) && (*p != fgstyle)) + { + bgcolor.pixel = grPixels[GrStyleTable[*p].color]; + XQueryColor(grXdpy, grXcmap, &bgcolor); + break; + } + p++; + } + + if (x == 256) + { + bgcolor.pixel = WhitePixel(grXdpy, grXscrn); + bgcolor.red=65535; + bgcolor.green=65535; + bgcolor.blue=65535; + bgcolor.flags=DoRed|DoGreen|DoBlue; + } + + /* Perform transposition on the glyph matrix since X displays + * the least significant bit on the left hand side. + */ + p = &(g->gr_pixels[0]); + for (y = 0; y < 32; y++) { + i = (y & 1) ? (32 - y) : (30 - y); + + curs[i] = mbits[i] = 0; + for (x = 0; x < 8; x++) + { + if (*p == fgstyle) + curs[i] |= (1 << x); + if (*p != STYLE_TRANSPARENT) + mbits[i] |= (1 << x); + p++; + } + } + source = XCreateBitmapFromData(grXdpy, XDefaultRootWindow(grXdpy), + (const char *)curs, 16, 16); + mask = XCreateBitmapFromData(grXdpy, XDefaultRootWindow(grXdpy), + (const char *)mbits, 16, 16); + grCursors[glyphnum] = XCreatePixmapCursor(grXdpy, source, mask, + &fgcolor, &bgcolor, + g->gr_origin.p_x, + (15 - g->gr_origin.p_y)); + } + + /* Restore clipping */ + grCurClip = oldClip; + GrUnlock(GR_LOCK_SCREEN); +} + + +/* + * ---------------------------------------------------------------------------- + * GrXSetCursor: + * + * Make the cursor be a new pattern, as defined in the display styles file. + * + * Results: + * None. + * + * Side effects: + * When the cursor is turned back on it will take on the new pattern. + * ---------------------------------------------------------------------------- + */ + +void +GrX11SetCursor(cursorNum) + int cursorNum; /* The cursor number as defined in the display + * styles file. + */ +{ + HashEntry *entry; + HashSearch hs; + + if (cursorNum >= MAX_CURSORS) + { + TxError("No such cursor!\n"); + return; + } + + grCurrent.cursor = grCursors[cursorNum]; + + HashStartSearch(&hs); + while (entry = HashNext(&grX11WindowTable,&hs)) + { + if (HashGetValue(entry)) + XDefineCursor(grXdpy,(Window)entry->h_key.h_ptr,grCurrent.cursor); + } +} diff --git a/graphics/grX11thread.c b/graphics/grX11thread.c new file mode 100644 index 00000000..0e817b43 --- /dev/null +++ b/graphics/grX11thread.c @@ -0,0 +1,243 @@ +/* grX11thread.c - + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + * This file contains functions to run the X11 event loop as a separate + * thread. Used by X11 and OpenGL running under X11. Compiled only if + * option "THREADS" is set in "make config". + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "graphics/graphicsInt.h" +#include "grX11Int.h" + +Display *grXdpy; + +int writePipe; /* As seen from child */ +int readPipe; + +pthread_t xloop_thread = 0; + +/*------------------------------------------------------*/ +/* ParseEvent is copied from X11Helper.c */ +/*------------------------------------------------------*/ + +/* + *-------------------------------------------------------------- + * ParseEvent(XEvent *event) -- + * + * Pass XEvents on to the magic main process by writing into the + * connecting pipe. Keystrokes must be handled such that magic + * can treat untranslated keyboard input from stdin the same way + * that it treats translated keyboard input through X11. + * Use XLookupString() to get an ASCII character out of the + * keycode, but also pass back the event structure so we can + * pull out key modifier information in grX11Stdin(). + * + * Pass the event and key value back through the I/O pipe so that + * the keypress triggers the select() mechanism in magic's textio + * routine. + * + * Results: + * None. + * + * Side effects: + * pipe I/O + * + *-------------------------------------------------------------- + */ + +void +ParseEvent (event, parentID) + XEvent *event; + int parentID; +{ + if (event->type == KeyPress) + { + XKeyPressedEvent *KeyPressedEvent = (XKeyPressedEvent *) event; + char inChar[10], c, *p; + KeySym keysym; + int keywstate; /* KeySym with prepended state information */ + int keymod; + int nbytes; + + nbytes = XLookupString(KeyPressedEvent, inChar, sizeof(inChar), &keysym, NULL); + + if (IsModifierKey(keysym)) return; /* Don't send modifiers as events */ + + keymod = (LockMask | ControlMask | ShiftMask) + & KeyPressedEvent->state; + +#ifdef __APPLE__ + if (KeyPressedEvent->state & (Mod1Mask | Mod2Mask | Mod3Mask + | Mod4Mask | Mod5Mask)) + keymod |= Mod1Mask; +#else + keymod |= (Mod1Mask & KeyPressedEvent->state); +#endif + + if (nbytes == 0) /* No ASCII equivalent to string */ + { + keywstate = (keymod << 16) | (keysym & 0xffff); + + write(writePipe, event, sizeof(XEvent)); + write(writePipe, &keywstate, sizeof(int)); + } + else if (!strncmp(XKeysymToString(keysym), "KP_", 3)) + { + /* keypad key (special case---would like to */ + /* differentiate between shift-KP-# and # itself) */ + keymod &= ~ShiftMask; + keywstate = (keymod << 16) | (keysym & 0xffff); + write(writePipe, event, sizeof(XEvent)); + write(writePipe, &keywstate, sizeof(int)); + } + else /* For keys with ASCII equivalent */ + { + /* If Control or Shift is used alone, it should be removed from */ + /* the modifier list, since the ASCII value subsumes the Control */ + /* and Shift functions. However, Control + Shift + key should */ + /* be retained, as it cannot be expressed in ASCII. */ + + if (!(keymod & (LockMask | Mod1Mask))) { + if (!(keymod & ControlMask)) + keymod &= ~ShiftMask; + else if (!(keymod & ShiftMask)) + keymod &= ~ControlMask; + } + + p = inChar; + while (nbytes--) + { + if ((c = *p++) == 3) /* Ctrl-C interrupt */ + { + kill(parentID, SIGINT); + } + else + { + /* When Control modifier is present, use the capital */ + /* letter value instead of the control value. */ + + if ((keymod & ControlMask) && (c < 32)) + c += 'A' - 1; + + keywstate = (keymod << 16) | ((int)c & 0xff); + + write(writePipe, event, sizeof(XEvent)); + write(writePipe, &keywstate, sizeof(int)); + } + } + } + } + else if (event->type == DestroyNotify) + { + /* do nothing? */ + } + else /* All event types other than KeyPress */ + { + write(writePipe, event, sizeof(XEvent)); + } +} + +/*--------------------------------------------------------- + * xloop_begin: Threaded version of XHelper7 (X11Helper.c) + * + *--------------------------------------------------------- + */ + +void +xloop_begin(window) + Window window; +{ + XEvent xevent; + int parentID; + + parentID = (int)getppid(); + + /* Set this thread to cancel immediately when requested */ + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + XLockDisplay(grXdpy); + XSelectInput(grXdpy, window, + KeyPressMask|ButtonPressMask|ButtonReleaseMask| + ExposureMask|StructureNotifyMask| + VisibilityChangeMask|OwnerGrabButtonMask); + XSync(grXdpy,1); + XUnlockDisplay(grXdpy); + + while (1) { + XNextEvent(grXdpy, &xevent); + XLockDisplay(grXdpy); + ParseEvent(&xevent, parentID); + XUnlockDisplay(grXdpy); + } +} + +/*---------------------------------------------------------------------- + * xloop_create -- + * Function creates a thread for the X event loop. + * + * Results: + * Returns 0 on success of pthread_create, non-zero on failure. + * + * Side Effects: + * Thread crated + *---------------------------------------------------------------------- + */ + +int +xloop_create(window) + Window window; +{ + int status = 0; + + XLockDisplay(grXdpy); + XSelectInput(grXdpy, window, + KeyPressMask|ButtonPressMask|ButtonReleaseMask|ExposureMask| + StructureNotifyMask|OwnerGrabButtonMask); + XSync(grXdpy,1); + XUnlockDisplay(grXdpy); + + if (xloop_thread == (pthread_t)0) + status = pthread_create(&xloop_thread, NULL, (void *)xloop_begin, + (void *)window); + + return status; +} + +/* + *---------------------------------------------------------------------- + * xloop_end -- + * Kill the X event loop thread. + * + * Results: + * None. + * + * Side effects: + * Thread destroyed. + *---------------------------------------------------------------------- + */ + +void +xloop_end() +{ + if (xloop_thread != (pthread_t)0) + pthread_cancel(xloop_thread); + + /* For whatever reason, calling this used to work, now just */ + /* causes magic to hang. . . */ + /* pthread_join(xloop_thread, NULL); */ +} + +/*----------------------------------------------------------------------*/ diff --git a/graphics/graphics.h b/graphics/graphics.h new file mode 100644 index 00000000..1d4762ec --- /dev/null +++ b/graphics/graphics.h @@ -0,0 +1,225 @@ +/* graphics.h - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains a bunch of macros that look like + * normal procedure calls but really indirect through procedure + * pointers in order to achieve graphics display independence. + */ + +/* rcsid "$Header: /usr/cvsroot/magic-8.0/graphics/graphics.h,v 1.3 2010/06/24 12:37:18 tim Exp $" */ + +#ifndef _GRAPHICS_H +#define _GRAPHICS_H + +#include "utils/magic.h" +#include "utils/geometry.h" + +/* data structures */ +typedef struct { + int idx, mask, color, outline, fill, stipple; + char shortname; + char *longname; +} GR_STYLE_LINE; + +typedef struct { /* Colormap table entry */ + char *name; + unsigned char red; + unsigned char green; + unsigned char blue; +} colorEntry; + +/* Housekeeping and initialization routines */ +extern bool (*GrInitPtr)(); +extern void (*GrClosePtr)(); +extern void (*GrTextSizePtr)(); + +/* + * Display painting and text routines + * + * You must call GrLock() before using these, and + * call GrUnlock() afterwards. + */ +extern void (*GrLockPtr)(); +extern void (*GrUnlockPtr)(); +extern bool GrHaveLock(); +extern void GrClipTo(); +extern void GrClipBox(); +extern void GrClipLine(); +extern bool GrPutText(); +extern void GrFillPolygon(); +extern void (*GrDrawGlyphPtr)(); +extern void (*GrBitBltPtr)(); +extern int (*GrReadPixelPtr)(); +extern void (*GrFlushPtr)(); + +/* Tablet routines */ +extern void (*GrEnableTabletPtr)(); +extern void (*GrDisableTabletPtr)(); +extern void (*GrSetCursorPtr)(); + +/* graphics routines that are called in the same way for all displays */ +extern int GrLoadStyles(); +extern bool GrLoadCursors(); +extern bool GrSetDisplay(); +extern bool GrIsDisplay(); +extern void GrLabelSize(); +extern void GrSetStuff(); +extern void GrDrawFastBox(); +extern void GrGuessDisplayType(); +extern int GrGetStyleFromName(); +extern bool GrDrawGlyphNum(); + +#define GrFastBox(x) GrDrawFastBox(x, 0) + +/* external color map routines */ +extern bool GrReadCMap(), GrSaveCMap(); +extern bool GrGetColor(), GrPutColor(); +extern int GrNameToColor(); +extern void GrPutManyColors(); +extern void (*GrSetCMapPtr)(); +extern void GrResetCMap(); + +/* Routines for windows, called only if non-null. See SUN160 driver for + * details. + */ +extern bool (*GrCreateWindowPtr)(); /* Passed a window just after it is + * created. + */ +extern void (*GrDeleteWindowPtr)(); /* Passed a window just before it + * is destroyed. + */ +extern void (*GrDamagedPtr)(); /* Called at a conventient time after + * receiving a SIG_WINCH signal. + */ +extern void (*GrUpdateIconPtr)(); /* Adjust text on icon. + */ +extern bool (*GrEventPendingPtr)(); /* Check for pending graphics events. + */ +extern void (*GrConfigureWindowPtr)(); /* Called to reconfigure size/location + * of an existing window. + */ +extern void (*GrOverWindowPtr)(); /* Raise window to top of stack. + */ +extern void (*GrUnderWindowPtr)(); /* Lower window to bottom of stack. + */ +extern int (*GrWindowIdPtr)(); /* Get the window ID from a window name + */ +extern char *(*GrWindowNamePtr)(); /* Get the window name from a MagWin ptr. + */ +extern bool (*GrGetCursorPosPtr)(); /* Get the current cursor position + */ +extern bool (*GrGetCursorRootPosPtr)(); /* Get the current cursor position + * in root (screen) coordinates + */ + +/* Backing store mechanism (added 4/2/05) */ +extern bool (*GrGetBackingStorePtr)(); +extern bool (*GrScrollBackingStorePtr)(); +extern void (*GrPutBackingStorePtr)(); +extern void (*GrCreateBackingStorePtr)(); +extern void (*GrFreeBackingStorePtr)(); + +/* Routines called by the signals module just before Magic is stopped + * (such as via ^Z) and just after it is resumed. + */ +extern void (*GrStopPtr)(); +extern void (*GrResumePtr)(); +#define GrStop (*GrStopPtr) +#define GrResume (*GrResumePtr) + +/* Number of colors defined in the colormap */ +extern int GrNumColors; + +/* Different graphics (OpenGL vs. X11, for instance) have different + * definitions of line and rectangle/polygon coordinates. Usually + * this boils down to a single pixel difference on rectangle edges. + * GrPixelCorrect should be set to 0 for OpenGL and other real-valued + * coordinate systems, 1 for X11 and other pixel-based systems. + */ +extern int GrPixelCorrect; + +/* The size of the screen in screen coordinates */ +extern Rect GrScreenRect; + +/* The size of crosses (drawn for zero-size boxes), in pixels. */ +extern Rect GrCrossRect; + +/* Multiples of the grid spacing which we draw lighter, for a fading effect */ +extern unsigned char GrGridMultiple; + +/* Style tables */ +extern GR_STYLE_LINE *GrStyleTable; +extern int **GrStippleTable; +extern int GrStyleNames[]; + +#ifndef lint + +/* Constants for easy access */ + +#define GrLock (*GrLockPtr) +#define GrUnlock (*GrUnlockPtr) +#define GrInit (*GrInitPtr) +#define GrClose (*GrClosePtr) +#define GrSetCMap (*GrSetCMapPtr) +#define GrTextSize (*GrTextSizePtr) +#define GrDrawGlyph (*GrDrawGlyphPtr) +#define GrBitBlt (*GrBitBltPtr) +#define GrReadPixel (*GrReadPixelPtr) +#define GrFlush (*GrFlushPtr) + +#define GrEnableTablet (*GrEnableTabletPtr) +#define GrDisableTablet (*GrDisableTabletPtr) +#define GrGetCursorPos (*GrGetCursorPosPtr) +#define GrGetCursorRootPos (*GrGetCursorRootPosPtr) +#define GrGetButtons (*GrGetButtonsPtr) +#define GrSetCursor (*GrSetCursorPtr) + +#endif + +enum { DISPLAY_IDLE, DISPLAY_IN_PROGRESS, DISPLAY_BREAK_PENDING, DISPLAY_SUSPEND }; +extern unsigned char GrDisplayStatus; + +/* constants */ + +/* Rectangle filling styles. + * (note: this must match the array in grDStyle.c) + */ + +#define GR_STSOLID 0 +#define GR_STCROSS 1 +#define GR_STOUTLINE 2 +#define GR_STSTIPPLE 3 +#define GR_STGRID 4 + +/* 4 text sizes that are specified by the graphics driver, plus a 5th one. + * This last one is for systems that allow the user to specify a default font + * (such as a sun) -- on other systems it's size is decided by the driver. + * + * Note: + * These must be in sequential, ascending order. + */ +#define GR_TEXT_SMALL 0 +#define GR_TEXT_MEDIUM 1 +#define GR_TEXT_LARGE 2 +#define GR_TEXT_XLARGE 3 +#define GR_TEXT_DEFAULT 4 + +/* Default cursor position -- used on startup and if we can't read the cursor */ +#define GR_CURSOR_X 100 +#define GR_CURSOR_Y 100 + +/* Special full-screen access for window manager only */ +#define GR_LOCK_SCREEN (MagWindow *)(-1) + +#endif /* _GRAPHICS_H */ diff --git a/graphics/graphicsInt.h b/graphics/graphicsInt.h new file mode 100644 index 00000000..a2b75cfe --- /dev/null +++ b/graphics/graphicsInt.h @@ -0,0 +1,92 @@ +/* + * graphicsInt.h -- + * + * Internal definitions for the graphics module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/graphics/graphicsInt.h,v 1.3 2010/06/24 12:37:18 tim Exp $" + */ + +#ifndef _GRAPHICSINT_H +#define _GRAPHICSINT_H + +#include "windows/windows.h" +#include "utils/magic.h" + + +extern int grNumBitPlanes; +extern int grBitPlaneMask; + + +/* procedures */ +extern void (*grPutTextPtr)(); +extern void (*grFontTextPtr)(); /* Vector-drawn text */ +extern void (*grSetSPatternPtr)(); +extern void (*grDefineCursorPtr)(); +extern void (*grFreeCursorPtr)(); +extern bool (*grDrawGridPtr)(); +extern void (*grDrawLinePtr)(); +extern void (*grSetWMandCPtr)(); +extern void (*grFillRectPtr)(); +extern void (*grSetStipplePtr)(); +extern void (*grSetLineStylePtr)(); +extern void (*grSetCharSizePtr)(); +extern void (*grFillPolygonPtr)(); + +extern char *grFgets(); +extern void grSimpleLock(), grSimpleUnlock(); +extern void grNoLock(); +#define GR_CHECK_LOCK() {if (grLockedWindow == NULL) grNoLock();} + +/* The size of the crosses drawn for degenerate box outlines: */ +#define GR_CROSSSIZE 5 + +/* This becomes TRUE if we should quit drawing things and return */ +extern bool SigInterruptPending; + +/* clipping stuff from GrLock() */ +extern MagWindow *grLockedWindow; +extern Rect grCurClip; +extern LinkedRect *grCurObscure; + +/* Strings used to generate file names for glyphs, colormaps, and + * display styles. + */ + +extern char *grDStyleType; +extern char *grCMapType; +extern char *grCursorType; + +/* + * Used to pass display-style information to lower levels + * of a graphics driver. + */ +extern int grCurDStyle; + +/* Number of stipples in the style file */ +extern int grNumStipples; + +/* Used to setup current color, etc. */ +extern bool grDriverInformed; +extern void grInformDriver(); + +/* Macro to check for a bogusly small grid. + * Turn off grid if gridlines are less than 4 pixels apart. + */ +#define GRID_TOO_SMALL(x,y) ( \ + (((x) >> SUBPIXELBITS) < 4) || (((y) >> SUBPIXELBITS) < 4) \ +) + +#endif /* _GRAPHICSINT_H */ diff --git a/graphics/prcolors.c b/graphics/prcolors.c new file mode 100644 index 00000000..57c89f71 --- /dev/null +++ b/graphics/prcolors.c @@ -0,0 +1,22 @@ +#include +#include + + +#ifndef lint +static char rcsid[]="$Header: /usr/cvsroot/magic-8.0/graphics/prcolors.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +main() +{ + Color color; + int i; + + XOpenDisplay(NULL); + for (i = 0; i < 256; i++) + { + color.pixel = i; + if (XQueryColor(&color)) + printf("#%x\t%5d%5d%5d\n", i, + color.red / 256, color.green / 256, color.blue / 256); + } +} diff --git a/graphics/wind3d.h b/graphics/wind3d.h new file mode 100644 index 00000000..9a9362e0 --- /dev/null +++ b/graphics/wind3d.h @@ -0,0 +1,70 @@ +/* + * wind3d.h -- + * + * Interface definitions for the 'glue' between the window + * manager and the 3D rendering window + * + * Copyright 2003 Open Circuit Design, Inc., for MultiGiG Ltd. + * + */ + +#ifndef _WIND3D_H +#define _WIND3D_H + +#include "windows/windows.h" + +/* Data structures */ + +typedef struct +{ + float view_x; /* View angle around x axis */ + float view_y; /* View angle around y axis */ + float view_z; /* View angle around z axis */ + + float trans_x; /* Translation in x */ + float trans_y; /* Translation in y */ + float trans_z; /* Translation in z */ + + float scale_xy; /* Size scaling */ + float prescale_z; /* Depth scaling */ + float scale_z; /* Depth scaling */ + + int width; /* Window width */ + int height; /* Window height */ + + int level; /* rendering level (0 = coarse) */ + + bool cif; /* If TRUE, draw CIF layers */ + + bool clipped; /* If TRUE, set clipping */ + Rect cutbox; /* Clip to this box, if clipping is set */ + + TileTypeBitMask visible; /* Layers to see */ + + MagWindow *boxWin; /* Render what's in this window */ +} W3DclientRec; + +/* Exported procedures */ + +extern void w3dSetProjection(); +extern void W3Dcommand(); +extern void W3Dinit(); + +/* Command procedures */ + +extern void w3dView(); +extern void w3dScroll(); +extern void w3dZoom(); +extern void w3dRefresh(); +extern void w3dToggleCIF(); +extern void w3dDefaults(); +extern void w3dLevel(); +extern void w3dClose(); +extern void w3dRenderValues(); +extern void w3dSeeLayers(); +extern void w3dHelp(); +extern void w3dCutBox(); + +extern WindClient W3DclientID; + +#endif /* _WIND3D_H */ diff --git a/grouter/Depend b/grouter/Depend new file mode 100644 index 00000000..639c83c6 --- /dev/null +++ b/grouter/Depend @@ -0,0 +1,58 @@ +grouteChan.o: grouteChan.c ../utils/magic.h ../utils/geometry.h \ + ../utils/styles.h ../utils/hash.h ../utils/heap.h ../utils/utils.h \ + ../tiles/tile.h ../database/database.h ../debug/debug.h ../gcr/gcr.h \ + ../windows/windows.h ../utils/main.h ../dbwind/dbwind.h \ + ../utils/signals.h ../router/router.h ../grouter/grouter.h \ + ../grouter/grouteDebug.h ../utils/netlist.h ../textio/textio.h \ + ../utils/malloc.h +grouteCrss.o: grouteCrss.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../utils/hash.h ../utils/heap.h ../utils/malloc.h \ + ../debug/debug.h ../tiles/tile.h ../database/database.h ../gcr/gcr.h \ + ../windows/windows.h ../utils/main.h ../dbwind/dbwind.h \ + ../utils/signals.h ../router/router.h ../grouter/grouter.h \ + ../grouter/grouteDebug.h ../utils/netlist.h ../textio/textio.h \ + ../utils/styles.h +grouteDens.o: grouteDens.c ../utils/magic.h ../utils/geometry.h \ + ../utils/hash.h ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../utils/netlist.h ../gcr/gcr.h ../router/router.h ../grouter/grouter.h \ + ../grouter/grouteDebug.h ../utils/signals.h ../textio/textio.h \ + ../utils/malloc.h ../utils/styles.h ../debug/debug.h +grouteMain.o: grouteMain.c ../utils/magic.h ../utils/geometry.h \ + ../utils/styles.h ../utils/hash.h ../utils/heap.h ../utils/utils.h \ + ../tiles/tile.h ../database/database.h ../debug/debug.h ../gcr/gcr.h \ + ../windows/windows.h ../utils/main.h ../dbwind/dbwind.h \ + ../utils/signals.h ../router/router.h ../grouter/grouter.h \ + ../grouter/grouteDebug.h ../utils/netlist.h ../textio/textio.h \ + ../utils/malloc.h +grouteMult.o: grouteMult.c ../utils/magic.h ../utils/geometry.h \ + ../utils/hash.h ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../router/router.h ../gcr/gcr.h ../grouter/grouter.h \ + ../grouter/grouteDebug.h ../utils/netlist.h ../utils/signals.h \ + ../textio/textio.h ../utils/malloc.h ../utils/styles.h \ + ../windows/windows.h ../dbwind/dbwind.h +grouteMaze.o: grouteMaze.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../utils/hash.h ../utils/heap.h ../utils/malloc.h \ + ../debug/debug.h ../tiles/tile.h ../database/database.h ../gcr/gcr.h \ + ../windows/windows.h ../utils/main.h ../dbwind/dbwind.h \ + ../utils/signals.h ../router/router.h ../grouter/grouter.h \ + ../grouter/grouteDebug.h ../utils/netlist.h ../textio/textio.h \ + ../utils/styles.h +groutePath.o: groutePath.c ../utils/magic.h ../utils/geometry.h \ + ../utils/hash.h ../utils/heap.h ../tiles/tile.h ../debug/debug.h \ + ../database/database.h ../gcr/gcr.h ../windows/windows.h ../utils/main.h \ + ../dbwind/dbwind.h ../utils/signals.h ../router/router.h \ + ../grouter/grouter.h ../grouter/grouteDebug.h ../textio/textio.h \ + ../utils/malloc.h +groutePen.o: groutePen.c ../utils/magic.h ../utils/geometry.h \ + ../utils/hash.h ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../utils/netlist.h ../gcr/gcr.h ../router/router.h ../grouter/grouter.h \ + ../grouter/grouteDebug.h ../utils/signals.h ../textio/textio.h \ + ../utils/malloc.h ../utils/styles.h ../utils/list.h +grouteTest.o: grouteTest.c ../utils/magic.h ../utils/geometry.h \ + ../utils/hash.h ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../utils/signals.h ../textio/textio.h ../debug/debug.h ../gcr/gcr.h \ + ../router/router.h ../grouter/grouter.h ../grouter/grouteDebug.h \ + ../graphics/graphics.h ../windows/windows.h ../dbwind/dbwind.h \ + ../textio/txcommands.h ../utils/main.h ../utils/utils.h \ + ../commands/commands.h ../utils/malloc.h ../utils/styles.h \ + ../utils/netlist.h diff --git a/grouter/Makefile b/grouter/Makefile new file mode 100644 index 00000000..d42ed237 --- /dev/null +++ b/grouter/Makefile @@ -0,0 +1,11 @@ +# +# rscid $Header: +# + +MODULE = grouter +MAGICDIR = .. +SRCS = grouteChan.c grouteCrss.c grouteDens.c grouteMain.c \ + grouteMult.c grouteMaze.c groutePath.c groutePen.c grouteTest.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/grouter/TODO b/grouter/TODO new file mode 100644 index 00000000..6cbc5112 --- /dev/null +++ b/grouter/TODO @@ -0,0 +1,6 @@ +When adjusting crossings involving river-routing tiles, be certain + to handle case where we go through several river-routing tiles + in a row (can happen even if river-routing channels aren't adjacent, + such as when density reaches its maximum in a normal channel that + is next to a river-routing channel). +Look at expansion from destination at same time as from starting points. diff --git a/grouter/grouteChan.c b/grouter/grouteChan.c new file mode 100644 index 00000000..cdf9a84d --- /dev/null +++ b/grouter/grouteChan.c @@ -0,0 +1,1098 @@ +/* + * grouteChan.c -- + * + * Code to maintain a map of usable channel areas, using a + * tile plane. One tile is used for each "unobstructed" + * channel area, namely one that contains no embedded regions + * where the channel's density has been exceeded. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/styles.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "debug/debug.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "utils/styles.h" +#include "textio/textio.h" +#include "utils/malloc.h" + +/* Plane to hold channel information */ +Plane *glChanPlane; + +/* Dummy celldef whose PL_DRC_CHECK plane is identical to glChanPlane above */ +CellDef *glChanDef; +CellUse *glChanUse; + +TileTypeBitMask glMaskRiver; /* Mask of river channel types */ +TileTypeBitMask glMaskNormal; /* Mask of normal channel type */ +TileTypeBitMask glMaskChannel; /* Mask of all channel types */ + +int glChanSplitRiver(); +int glChanRiverBlock(); +int glChanFloodVFunc(), glChanFloodHFunc(); +bool glChanClip(); +int glChanClipFunc(); +int glChanMergeFunc(); +int glChanFeedFunc(); +int glChanPaintFunc(); +int glChanSetClient(); +void glChanFreeMap(); +void glChanCheckCover(); +void glChanBlockDens(); +void glChanFlood(); +void glChanShowTiles(); +int glChanShowFunc(); + +typedef struct pa +{ + Rect pa_area; + TileType pa_type; + struct pa *pa_next; +} PaintArea; + +PaintArea *glChanPaintList; + +/* + * ---------------------------------------------------------------------------- + * + * glChanBuildMap -- + * + * Build a tile plane that represents all the channels in the routing + * problem. This tile plane will contain tiles of four types: CT_BLOCKED, + * CT_NORMAL, CT_HRIVER, and CT_VRIVER, corresponding to unusable routing + * area and the three types of channels respectively. + * + * Each channel tile's client field points back to the channel it covers. + * A single channel can be covered by several tiles, however. Initially, + * each normal channel is covered by a single tile, but each river tile + * is covered by several tiles. For example, the tiles covering a HRIVER + * channel are chosen such that there is never a vertical tile boundary + * on either their RHS or LHS except at the top or bottom of the CT_HRIVER + * tile. Situations such as the following: + * + * +-------+ + * | | + * | | normal + * | | + * |HRIVER +------ + * | | + * | | normal + * | | + * +-------+ + * + * aren't allowed to exist; the HRIVER tile gets split: + * + * +-------+ + * | | + * |HRIVER | normal + * | | + * +-------+------ + * | | + * |HRIVER | normal + * | | + * +-------+ + * + * The reason for splitting CT_HRIVER tiles in this way (and CT_VRIVER tiles + * vertically using similar criteria) is to ensure that there is a different + * river tile for each channel on its opposite side. This fact is crucial + * to the working of the inner loop of the global router; see the code in + * groutePair.c for details of the algorithm used. + * + * Results: + * None. + * + * Side effects: + * Builds the tile plane glChanPlane as described above. + * + * ---------------------------------------------------------------------------- + */ + +void +glChanBuildMap(chanList) + GCRChannel *chanList; /* List of all channels in routing problem */ +{ + GCRChannel *ch; + bool workDone; + + if (glChanPlane == NULL) + { + DBNewYank("__CHANMAP__", &glChanUse, &glChanDef); + glChanPlane = glChanDef->cd_planes[PL_DRC_CHECK]; + glChanFreeMap(); + TTMaskSetOnlyType(&glMaskRiver, CHAN_HRIVER); + TTMaskSetType(&glMaskRiver, CHAN_VRIVER); + TTMaskSetOnlyType(&glMaskNormal, CHAN_NORMAL); + TTMaskSetMask3(&glMaskChannel, &glMaskNormal, &glMaskRiver); + } + + /* + * First pass: use painting to cover the areas of all channels + * with the appropriate type of tile. + */ + for (ch = chanList; ch; ch = ch->gcr_next) + DBPaintPlane(glChanPlane, &ch->gcr_area, DBStdWriteTbl(ch->gcr_type), + (PaintUndoInfo *) NULL); + + if (DebugIsSet(glDebugID, glDebTiles)) + glChanShowTiles("After painting all channels"); + + /* + * Second pass: use splits and merges to ensure that each channel + * covers exactly one tile. Leave this tile's ti_client field + * pointing to 'ch'. + */ + do + { + workDone = FALSE; + for (ch = chanList; ch; ch = ch->gcr_next) + if (glChanClip(ch)) + workDone = TRUE; + } + while (workDone); + if (DebugIsSet(glDebugID, glDebTiles)) + glChanShowTiles("After splits and merges"); + if (DebugIsSet(glDebugID, glDebChan)) + glChanCheckCover(chanList, &glMaskChannel); + + /* + * Third pass: find regions of maximum density and "paint" them into + * the tile map. Regions where the density is exceeded in only one + * of the two possible directions through a normal channel result in + * painting a CHAN_HRIVER or CHAN_VRIVER tile as appropriate, while + * regions that are totally blocked result in CHAN_BLOCKED tiles. + * The client fields of the remaining nonblocked tiles are left + * pointing to the channels those tiles overlap. + */ + for (ch = chanList; ch; ch = ch->gcr_next) + glChanBlockDens(ch); + if (DebugIsSet(glDebugID, glDebTiles)) + glChanShowTiles("After density blockages"); + + /* + * Fourth pass: split river tiles as necessary to ensure + * that no river tile has a perpendicular tile boundary + * on either of the sides from which signals can enter. + */ + while (DBSrPaintArea((Tile *) NULL, glChanPlane, &TiPlaneRect, &glMaskRiver, + glChanSplitRiver, (ClientData) NULL)) + /* Nothing */; + if (DebugIsSet(glDebugID, glDebTiles)) + glChanShowTiles("After splitting river tiles"); + + /* + * Final pass: turn any river tiles whose pins are completely + * blocked on one side into blocked tiles. This just involves + * changing the type of the tile. + */ + (void) DBSrPaintArea((Tile *) NULL, glChanPlane, &TiPlaneRect, + &glMaskRiver, glChanRiverBlock, (ClientData) NULL); + if (DebugIsSet(glDebugID, glDebTiles)) + glChanShowTiles("After blocking river tiles"); + if (DebugIsSet(glDebugID, glDebChan)) + { + glChanCheckCover(chanList, &glMaskNormal); + (void) DBSrPaintArea((Tile *) NULL, glChanPlane, &TiPlaneRect, + &glMaskChannel, glChanFeedFunc, (ClientData) NULL); + } +} + +/* + * glChanFeedFunc -- + * + * Used for leaving feedback for each channel tile above. + * + * Results: + * Always returns 0. + * + * Side effects: + * Leaves feedback for each tile found. + */ + +int +glChanFeedFunc(tile) + Tile *tile; +{ + char *mesg; + Rect r; + + switch (TiGetType(tile)) + { + case CHAN_NORMAL: mesg = "normal channel"; break; + case CHAN_HRIVER: mesg = "horizontal river channel"; break; + case CHAN_VRIVER: mesg = "vertical river channel"; break; + } + TITORECT(tile, &r); + DBWFeedbackAdd(&r, mesg, EditCellUse->cu_def, 1, STYLE_OUTLINEHIGHLIGHTS); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glChanFreeMap -- + * + * Free the tile plane built by glChanBuildMap(). + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * + * ---------------------------------------------------------------------------- + */ + +void +glChanFreeMap() +{ + Tile *newCenterTile; + + /* Eliminate all the tiles from this plane */ + DBFreePaintPlane(glChanPlane); + + /* Allocate a new central space tile */ + newCenterTile = TiAlloc(); + glChanPlane->pl_hint = newCenterTile; + TiSetBody(newCenterTile, CHAN_BLOCKED); + dbSetPlaneTile(glChanPlane, newCenterTile); +} + +/* + * ---------------------------------------------------------------------------- + * + * glChanCheckCover -- + * + * Debugging procedure used to check that each channel whose type is + * contained in 'mask' is covered by exactly one tile. Also check + * all channels to make sure that the tiles they cover are the same + * as the channel type (except for blockages). + * + * Results: + * None. + * + * Side effects: + * Leaves feedback where errors occur. + * + * ---------------------------------------------------------------------------- + */ + +int glChanCheckCount; + +void +glChanCheckCover(chanList, mask) + GCRChannel *chanList; + TileTypeBitMask *mask; +{ + int glChanCheckFunc(); + GCRChannel *ch; + char mesg[1024]; + + for (ch = chanList; ch; ch = ch->gcr_next) + { + glChanCheckCount = 0; + (void) DBSrPaintArea((Tile *) NULL, glChanPlane, &ch->gcr_area, + &DBAllTypeBits, glChanCheckFunc, + (ClientData) ch); + if (TTMaskHasType(mask, ch->gcr_type) && glChanCheckCount != 1) + { + (void) sprintf(mesg, "%d tiles over channel", glChanCheckCount); + DBWFeedbackAdd(&ch->gcr_area, mesg, EditCellUse->cu_def, 1, + STYLE_PALEHIGHLIGHTS); + } + } +} + +/* + * glChanCheckFunc -- + * + * Called by above for each tile overlapping a channel. + * + * Results: + * Always returns 0. + * + * Side effects: + * May leave feedback if a channel is overlapped by the + * wrong type of tile. + */ + +int +glChanCheckFunc(tile, ch) + Tile *tile; + GCRChannel *ch; +{ + char mesg[1024]; + Rect r; + + glChanCheckCount++; + if (NOTBLOCKED(tile)) + { + if (TiGetType(tile) != ch->gcr_type) + { + TITORECT(tile, &r); + (void) sprintf(mesg, "Different tile type %d for chan %d", + TiGetType(tile), ch->gcr_type); + DBWFeedbackAdd(&r, mesg, EditCellUse->cu_def, + 1, STYLE_MEDIUMHIGHLIGHTS); + } + if (tile->ti_client != (ClientData) ch) + { + TITORECT(tile, &r); + (void) sprintf(mesg, "Tile client 0x%"DLONG_PREFIX"x doesn't match chan %p", + (dlong) tile->ti_client, ch); + DBWFeedbackAdd(&r, mesg, EditCellUse->cu_def, + 1, STYLE_MEDIUMHIGHLIGHTS); + } + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glChanClip -- + * + * Leave a single tile overlapping the area of channel 'ch'. + * Leave this tile pointing to 'ch'. + * + * Results: + * Returns TRUE if we had to do any splits or merges, + * FALSE if everything was as it should be. + * + * Side effects: + * May split or merge tiles. + * + * ---------------------------------------------------------------------------- + */ + +bool +glChanClip(ch) + GCRChannel *ch; +{ + bool ret; + + ret = FALSE; + + /* First part: clip every tile overlapping this channel to its boundary */ + while (DBSrPaintArea((Tile *) NULL, glChanPlane, &ch->gcr_area, + &DBAllTypeBits, glChanClipFunc, (ClientData) &ch->gcr_area)) + ret = TRUE; + + /* Second part: set the client field of every tile to 'ch' */ + (void) DBSrPaintArea((Tile *) NULL, glChanPlane, &ch->gcr_area, + &DBAllTypeBits, glChanSetClient, (ClientData) ch); + + /* + * Third part: merge every tile overlapping this channel into a + * single one. The procedure called for each tile extracts the + * channel boundaries from the client field of the tile, and + * then generates merges within the channel boundary. + */ + while (DBSrPaintArea((Tile *) NULL, glChanPlane, &ch->gcr_area, + &DBAllTypeBits, glChanMergeFunc, (ClientData) NULL)) + ret = TRUE; + + if (DebugIsSet(glDebugID, glDebTiles)) + { + char mesg[256]; + + (void) sprintf(mesg, "After clipping chan %p", ch); + glChanShowTiles(mesg); + } + + return ret; +} + +int +glChanSetClient(tile, cdata) + Tile *tile; + ClientData cdata; +{ + tile->ti_client = cdata; + return 0; +} + +void +glChanShowTiles(mesg) + char *mesg; +{ + char answer[100], m[1024]; + + DBWAreaChanged(glChanDef, &TiPlaneRect, DBW_ALLWINDOWS, 0); + WindUpdate(); + (void) sprintf(m, "%s: --more-- (t for tiles): ", mesg); + if (TxGetLinePrompt(answer, sizeof answer, m) == NULL || answer[0] != 't') + return; + + (void) DBSrPaintArea((Tile *) NULL, glChanPlane, &TiPlaneRect, + &DBAllTypeBits, glChanShowFunc, (ClientData) NULL); +} + +int +glChanShowFunc(tile) + Tile *tile; +{ + GCRChannel *ch; + char mesg[1024]; + Rect r; + + TITORECT(tile, &r); + ShowRect(EditCellUse->cu_def, &r, STYLE_PALEHIGHLIGHTS); + (void) sprintf(mesg, "tile ch=%"DLONG_PREFIX"x type=%d", + (dlong) tile->ti_client, TiGetType(tile)); + TxMore(mesg); + ShowRect(EditCellUse->cu_def, &r, STYLE_ERASEHIGHLIGHTS); + if (tile->ti_client == (ClientData) CLIENTDEFAULT) + return 0; + ch = (GCRChannel *) tile->ti_client; + ShowRect(EditCellUse->cu_def, &ch->gcr_area, STYLE_MEDIUMHIGHLIGHTS); + (void) sprintf(mesg, "chan %p type=%d", ch, ch->gcr_type); + TxMore(mesg); + ShowRect(EditCellUse->cu_def, &ch->gcr_area, STYLE_ERASEHIGHLIGHTS); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glChanClipFunc -- + * + * Called by DBSrPaintArea() on behalf of glChanClip() above for each + * tile overlapping 'area': splits 'tile' as necessary to ensure that + * it is completely contained within area. + * + * Results: + * Returns 1 if we did any splitting, 0 otherwise. + * + * Side effects: + * May split tiles. + * When a tile is split, the new tile's body and ti_client + * field are set to copies of the original tile's. + * + * ---------------------------------------------------------------------------- + */ + +int +glChanClipFunc(tile, area) + Tile *tile; + Rect *area; +{ + ClientData tileClient = tile->ti_client; + TileType type = TiGetType(tile); + Tile *newTile; + int ret; + + ret = 0; + if (LEFT(tile) < area->r_xbot) + { + tile = TiSplitX(tile, area->r_xbot); + TiSetBody(tile, type); + tile->ti_client = tileClient; + ret = 1; + } + if (BOTTOM(tile) < area->r_ybot) + { + tile = TiSplitY(tile, area->r_ybot); + TiSetBody(tile, type); + tile->ti_client = tileClient; + ret = 1; + } + if (RIGHT(tile) > area->r_xtop) + { + newTile = TiSplitX(tile, area->r_xtop); + TiSetBody(newTile, type); + newTile->ti_client = tileClient; + ret = 1; + } + if (TOP(tile) > area->r_ytop) + { + newTile = TiSplitY(tile, area->r_ytop); + TiSetBody(newTile, type); + newTile->ti_client = tileClient; + ret = 1; + } + + return ret; +} + +/* + * ---------------------------------------------------------------------------- + * + * glChanMergeFunc -- + * + * Called by DBSrPaintArea() on behalf of glChanClip() above for each + * tile contained within some area. Merges this tile with any of + * its neighbors within its channel's area, where the channel is + * pointed to by the ti_client field. We leave the resulting tile's + * ti_client field pointing to this channel ('ch'). + * + * IMPORTANT ASSUMPTION: no tile actually overlaps the boundary of + * ch->gcr_area. This is ensured by the caller's having called + * glChanClipFunc() enough times to have split all the tiles + * that originally might have crossed the channel's boundary. + * + * Results: + * Returns 1 if we did any merging, 0 otherwise. + * + * Side effects: + * May merge tiles. + * Leaves tile->ti_client set to 'ch'. + * + * ---------------------------------------------------------------------------- + */ + +int +glChanMergeFunc(tile) + Tile *tile; +{ + GCRChannel *ch = (GCRChannel *) tile->ti_client; + Tile *tp; + int ret; + + ret = 0; + if (TOP(tile) < ch->gcr_area.r_ytop) + { + tp = RT(tile); + if (TiGetType(tp) == TiGetType(tile) + && LEFT(tp) == LEFT(tile) + && RIGHT(tp) == RIGHT(tile)) + { + TiJoinY(tile, tp, glChanPlane); + ret = 1; + } + } + if (LEFT(tile) > ch->gcr_area.r_xbot) + { + tp = BL(tile); + if (TiGetType(tp) == TiGetType(tile) + && TOP(tp) == TOP(tile) + && BOTTOM(tp) == BOTTOM(tile)) + { + TiJoinX(tile, tp, glChanPlane); + ret = 1; + } + } + if (BOTTOM(tile) > ch->gcr_area.r_ybot) + { + tp = LB(tile); + if (TiGetType(tp) == TiGetType(tile) + && LEFT(tp) == LEFT(tile) + && RIGHT(tp) == RIGHT(tile)) + { + TiJoinY(tile, tp, glChanPlane); + ret = 1; + } + } + if (RIGHT(tile) < ch->gcr_area.r_xtop) + { + tp = TR(tile); + if (TiGetType(tp) == TiGetType(tile) + && TOP(tp) == TOP(tile) + && BOTTOM(tp) == BOTTOM(tile)) + { + TiJoinX(tile, tp, glChanPlane); + ret = 1; + } + } + + return ret; +} + +/* + * ---------------------------------------------------------------------------- + * + * glChanBlockDens -- + * + * Find regions of maximum density in 'ch' (if 'ch' is a normal channel) and + * "paint" them into the tile map. Blockages of a single direction result + * in CHAN_HRIVER or CHAN_VRIVER tiles being painted as appropriate; if + * blockages exist in both directions, then we produce a CHAN_BLOCKED tile. + * + * We rely on the fact that regions of maximum density extend completely + * across a channel, and hence completely across any tile (since tiles are + * never bigger than channels). The client fields of the any tiles in the + * area of the channel that aren't totally blocked are left pointing to + * the overlapping channel. + * + * If columns i through j inclusive have maximum density, then the blockage + * we paint extends from midway between columns i-1 and i to midway between + * column j and j+1, guaranteeing that tile boundaries will always fall + * on half-grid lines. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +glChanBlockDens(ch) + GCRChannel *ch; +{ + GlobChan *gc = (GlobChan *) ch->gcr_client; + int halfGrid, shiftedOrigin; + DensMap *dRow, *dCol; + PaintArea *pa; + short *dens; + int lo, hi; + Rect area; + + if (ch->gcr_type != CHAN_NORMAL) + return; + + dCol = &gc->gc_postDens[CZ_COL]; + dRow = &gc->gc_postDens[CZ_ROW]; + halfGrid = RtrGridSpacing / 2; + glChanPaintList = (PaintArea *) NULL; + if (dCol->dm_max >= dCol->dm_cap) + { + dens = dCol->dm_value; + area.r_ybot = ch->gcr_area.r_ybot; + area.r_ytop = ch->gcr_area.r_ytop; + shiftedOrigin = ch->gcr_origin.p_x - halfGrid; + for (lo = 1; lo < dCol->dm_size; lo++) + { + if (dens[lo] >= dCol->dm_cap) + { + hi = lo+1; + while (dens[hi] >= dCol->dm_cap && hi < dCol->dm_size) + hi++; + + /* Remember area of blocked tile to paint */ + area.r_xbot = shiftedOrigin + lo * RtrGridSpacing; + area.r_xtop = shiftedOrigin + hi * RtrGridSpacing; + pa = (PaintArea *) mallocMagic((unsigned)(sizeof (PaintArea))); + pa->pa_area = area; + pa->pa_next = glChanPaintList; + pa->pa_type = CHAN_VRIVER; + glChanPaintList = pa; + + /* Will get incremented in loop header */ + lo = hi-1; + } + } + } + + if (dRow->dm_max >= dRow->dm_cap) + { + dens = dRow->dm_value; + area.r_xbot = ch->gcr_area.r_xbot; + area.r_xtop = ch->gcr_area.r_xtop; + shiftedOrigin = ch->gcr_origin.p_y - halfGrid; + for (lo = 1; lo < dRow->dm_size; lo++) + { + if (dens[lo] >= dRow->dm_cap) + { + hi = lo+1; + while (dens[hi] >= dRow->dm_cap && hi < dRow->dm_size) + hi++; + + /* Remember area of blocked tile to paint */ + area.r_ybot = shiftedOrigin + lo * RtrGridSpacing; + area.r_ytop = shiftedOrigin + hi * RtrGridSpacing; + pa = (PaintArea *) mallocMagic((unsigned)(sizeof (PaintArea))); + pa->pa_area = area; + pa->pa_next = glChanPaintList; + pa->pa_type = CHAN_HRIVER; + glChanPaintList = pa; + + /* Will get incremented in loop header */ + lo = hi-1; + } + } + } + + /* + * Now do all the work. + * First paint all the blocked areas on glChanPaintList. + * Then make a second pass through this list, searching the + * area around each blocked area tile we painted for river + * tiles of the appropriate type, and propagating this blockage + * to those river tiles as well. Do this until the wavefront + * stops, which will happen as soon as we reach a normal channel. + */ + do + { + for (pa = glChanPaintList; pa; pa = pa->pa_next) + { + /* Clip tiles overlapped by pa->pa_area */ + while (DBSrPaintArea((Tile *) NULL, glChanPlane, &pa->pa_area, + &DBAllTypeBits, glChanClipFunc, (ClientData) &pa->pa_area)) + /* Nothing */; + + /* Change the type of all tiles within the area */ + (void) DBSrPaintArea((Tile *) NULL, glChanPlane, &pa->pa_area, + &DBAllTypeBits, glChanPaintFunc, (ClientData) pa->pa_type); + + /* + * Allow merging, as long as no tiles get merged across + * channel boundaries. + */ + while (DBSrPaintArea((Tile *) NULL, glChanPlane, &pa->pa_area, + &DBAllTypeBits, glChanMergeFunc, (ClientData) NULL)); + } + + /* Second pass to propagate blockages to nearby areas */ + for (pa = glChanPaintList, glChanPaintList = NULL; pa; pa = pa->pa_next) + { + glChanFlood(&pa->pa_area, pa->pa_type); + freeMagic((char *) pa); + } + } while (glChanPaintList != NULL); +} + +int +glChanPaintFunc(tile, type) + Tile *tile; + TileType type; +{ + static TileType changeTable[4][4] = { + /* Paint atop CHAN_NORMAL */ + { CHAN_NORMAL, CHAN_HRIVER, CHAN_VRIVER, CHAN_BLOCKED }, + + /* Paint atop CHAN_HRIVER */ + { CHAN_HRIVER, CHAN_HRIVER, CHAN_BLOCKED, CHAN_BLOCKED }, + + /* Paint atop CHAN_VRIVER */ + { CHAN_VRIVER, CHAN_BLOCKED, CHAN_VRIVER, CHAN_BLOCKED }, + + /* Paint atop CHAN_BLOCKED */ + { CHAN_BLOCKED, CHAN_BLOCKED, CHAN_BLOCKED, CHAN_BLOCKED }, + }; + + TiSetBody(tile, changeTable[TiGetType(tile)][type]); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glChanFlood -- + * + * Search all four sides of 'area' (an area that has just been painted + * as type) for river tiles of the appropriate type (where appropriate + * means tiles that are completely blocked by a tile of type type to + * the side to which it lies). + * + * Each time an appropriate river tiles is found, record a CHAN_BLOCKED + * rectangle on the list glChanPaintList that extends from 'area' through to + * the other side of the river channel. + * + * The purpose of this procedure is so that the presence of the blockage + * on one side of a river tile will be visible from its other side. + * + * Results: + * None. + * + * Side effects: + * May prepend stuff to glChanPaintList. + * + * ---------------------------------------------------------------------------- + */ + +void +glChanFlood(area, type) + Rect *area; + TileType type; +{ + TileTypeBitMask hMask, vMask; + Rect outside; + + TTMaskSetOnlyType(&hMask, CHAN_HRIVER); + TTMaskSetOnlyType(&vMask, CHAN_VRIVER); + + if (type != CHAN_VRIVER) + { + /* TOP */ + outside = *area; + outside.r_ybot = area->r_ytop; + outside.r_ytop = area->r_ytop + 1; + (void) DBSrPaintArea((Tile *) NULL, glChanPlane, &outside, &vMask, + glChanFloodVFunc, (ClientData) area); + + /* BOTTOM */ + outside = *area; + outside.r_ybot = area->r_ybot - 1; + outside.r_ytop = area->r_ybot; + (void) DBSrPaintArea((Tile *) NULL, glChanPlane, &outside, &vMask, + glChanFloodVFunc, (ClientData) area); + } + + if (type != CHAN_HRIVER) + { + /* LEFT */ + outside = *area; + outside.r_xbot = area->r_xbot - 1; + outside.r_xtop = area->r_xbot; + (void) DBSrPaintArea((Tile *) NULL, glChanPlane, &outside, &hMask, + glChanFloodHFunc, (ClientData) area); + + /* RIGHT */ + outside = *area; + outside.r_xbot = area->r_xtop; + outside.r_xtop = area->r_xtop + 1; + (void) DBSrPaintArea((Tile *) NULL, glChanPlane, &outside, &hMask, + glChanFloodHFunc, (ClientData) area); + } +} + +int +glChanFloodVFunc(tile, area) + Tile *tile; + Rect *area; +{ + PaintArea *pa; + + pa = (PaintArea *) mallocMagic((unsigned) (sizeof (PaintArea))); + pa->pa_area.r_xbot = MAX(area->r_xbot, LEFT(tile)); + pa->pa_area.r_xtop = MIN(area->r_xtop, RIGHT(tile)); + pa->pa_area.r_ybot = BOTTOM(tile); + pa->pa_area.r_ytop = TOP(tile); + pa->pa_next = glChanPaintList; + pa->pa_type = CHAN_BLOCKED; + glChanPaintList = pa; + + return 0; +} + +int +glChanFloodHFunc(tile, area) + Tile *tile; + Rect *area; +{ + PaintArea *pa; + + pa = (PaintArea *) mallocMagic((unsigned)(sizeof (PaintArea))); + pa->pa_area.r_ybot = MAX(area->r_ybot, BOTTOM(tile)); + pa->pa_area.r_ytop = MIN(area->r_ytop, TOP(tile)); + pa->pa_area.r_xbot = LEFT(tile); + pa->pa_area.r_xtop = RIGHT(tile); + pa->pa_next = glChanPaintList; + pa->pa_type = CHAN_BLOCKED; + glChanPaintList = pa; + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glChanSplitRiver -- + * + * Called for each river tile (CHAN_HRIVER or CHAN_VRIVER) in glChanPlane. + * Search along the two sides of this tile from which signals can enter + * (the LHS and RHS for CHAN_HRIVER, or the top and bottom for CHAN_VRIVER), + * and make sure that there are no tile boundaries involving some type of + * tile other than CHAN_BLOCKED along that side. If there is a boundary, + * split tile at the boundary. + * + * Results: + * Returns 1 if we did any splitting, 0 if not. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +glChanSplitRiver(tile) + Tile *tile; +{ + ClientData tileClient = tile->ti_client; + Tile *tp, *newTile; + int ret; + + ret = 0; + if (TiGetType(tile) == CHAN_HRIVER) + { + for (tp = BL(tile); TOP(tp) < TOP(tile); tp = RT(tp)) + { + if (NOTBLOCKED(tp) || NOTBLOCKED(RT(tp))) + { + tile = TiSplitY(tile, TOP(tp)); + TiSetBody(tile, CHAN_HRIVER); + tile->ti_client = tileClient; + ret = 1; + } + } + for (tp = TR(tile); BOTTOM(tp) > BOTTOM(tile); tp = LB(tp)) + { + if (NOTBLOCKED(tp) || NOTBLOCKED(LB(tp))) + { + newTile = TiSplitY(tile, BOTTOM(tp)); + TiSetBody(newTile, CHAN_HRIVER); + newTile->ti_client = tileClient; + ret = 1; + } + } + } + else + { + for (tp = RT(tile); LEFT(tp) > LEFT(tile); tp = BL(tp)) + { + if (NOTBLOCKED(tp) || NOTBLOCKED(BL(tp))) + { + newTile = TiSplitX(tile, LEFT(tp)); + TiSetBody(newTile, CHAN_VRIVER); + newTile->ti_client = tileClient; + ret = 1; + } + } + for (tp = LB(tile); RIGHT(tp) < RIGHT(tile); tp = TR(tp)) + { + if (NOTBLOCKED(tp) || NOTBLOCKED(TR(tp))) + { + tile = TiSplitX(tile, RIGHT(tp)); + TiSetBody(tile, CHAN_VRIVER); + tile->ti_client = tileClient; + ret = 1; + } + } + } + + return ret; +} + +/* + * ---------------------------------------------------------------------------- + * + * glChanRiverBlock -- + * + * Called for each river routing tile. Checks to make sure that at least + * some of the pins along the usable sides of this channel are still free; + * if they're not, we change this tile's type to CHAN_BLOCKED. + * + * Note: river routing tiles can overlay portions of a normal channel + * in which the density of the channel equals its capacity in either + * the horizontal or vertical direction. + * + * Results: + * Always returns 0. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +glChanRiverBlock(tile) + Tile *tile; +{ + GCRPin *pin, *pinLast; + GCRChannel *ch; + int lo, hi; + + ch = (GCRChannel *) tile->ti_client; + if (TiGetType(tile) == CHAN_HRIVER) + { + lo = (BOTTOM(tile) - ch->gcr_origin.p_y) / RtrGridSpacing; + hi = (TOP(tile) - ch->gcr_origin.p_y) / RtrGridSpacing; + if (lo < 1) lo = 1; + if (hi > ch->gcr_width) hi = ch->gcr_width; + pinLast = &ch->gcr_lPins[hi]; + for (pin = &ch->gcr_lPins[lo]; pin <= pinLast; pin++) + if (pin->gcr_pId == NULL && pin->gcr_linked) + return 0; + pinLast = &ch->gcr_rPins[hi]; + for (pin = &ch->gcr_rPins[lo]; pin <= pinLast; pin++) + if (pin->gcr_pId == NULL && pin->gcr_linked) + return 0; + } + else + { + /* CHAN_VRIVER */ + lo = (LEFT(tile) - ch->gcr_origin.p_x) / RtrGridSpacing; + hi = (RIGHT(tile) - ch->gcr_origin.p_x) / RtrGridSpacing; + if (lo < 1) lo = 1; + if (hi > ch->gcr_length) hi = ch->gcr_length; + pinLast = &ch->gcr_bPins[hi]; + for (pin = &ch->gcr_bPins[lo]; pin <= pinLast; pin++) + if (pin->gcr_pId == NULL && pin->gcr_linked) + return 0; + pinLast = &ch->gcr_tPins[hi]; + for (pin = &ch->gcr_tPins[lo]; pin <= pinLast; pin++) + if (pin->gcr_pId == NULL && pin->gcr_linked) + return 0; + } + + TiSetBody(tile, CHAN_BLOCKED); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glChanPinToTile -- + * + * Find the tile corresponding to the pin 'pin'. + * The pin mustn't be in one of the corners of a channel. + * + * Results: + * Returns a pointer to the tile found. + * Returns NULL if the tile found was of type CHAN_BLOCKED. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +Tile * +glChanPinToTile(hintTile, pin) + Tile *hintTile; /* Hint for starting the tile search */ + GCRPin *pin; /* Find tile containing this pin */ +{ + GCRChannel *ch; + Tile *tp; + Point p; + Rect r; + + /* Figure out which channel tile the output point lies in */ + p = pin->gcr_point; + switch (pin->gcr_side) + { + case GEO_NORTH: p.p_y--; break; + case GEO_EAST: p.p_x--; break; + } + + tp = TiSrPoint(hintTile, glChanPlane, &p); + if (TiGetType(tp) == CHAN_BLOCKED) + return (Tile *) NULL; + + ASSERT(tp->ti_client != (ClientData) CLIENTDEFAULT, "glChanPinToTile"); + ch = (GCRChannel *) tp->ti_client; + TITORECT(tp, &r); + ASSERT(GEO_SURROUND(&ch->gcr_area, &r), "glChanPinToTile"); + + return tp; +} diff --git a/grouter/grouteCrss.c b/grouter/grouteCrss.c new file mode 100644 index 00000000..ff98ebb3 --- /dev/null +++ b/grouter/grouteCrss.c @@ -0,0 +1,795 @@ +/* + * grouteCross.c - + * + * Global signal router. Code to do crossing placement. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * Lawrence Livermore National Laboratory + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/grouter/grouteCrss.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "utils/malloc.h" +#include "debug/debug.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "utils/styles.h" + +/* Passed to glCrossChoose() */ +GlPoint *glCrossLookAhead; + +/* The following penalties get scaled by RtrGridSpacing */ +int glJogPenalty = 5; +int glObsPenalty1 = 5, glObsPenalty2 = 3; +int glNbrPenalty1 = 2, glNbrPenalty2 = 5; +int glOrphanPenalty = 3; +int glChanPenalty = 1; +bool glPenaltiesScaled = FALSE; + +/* Forward declarations */ +GlPoint *glCrossAdjust(); +int glCrossChoose(); +void glCrossTakePin(); + + +/* + * ---------------------------------------------------------------------------- + * + * glCrossMark -- + * + * Mark all the pins crossed by the linked list of GlPoints pointed to + * by 'path' as taken. This list is linked along the gl_path pointers. + * The starting entry 'path' indicates a pin reserved for a NLTermLoc; + * the last entry is one of the pins on the previous starting-point list. + * + * Results: + * None. + * + * Side effects: + * Marks the pins along the path as taken by 'net'. + * Assigns a segment identifier to each pin that is different + * for each pair of GlPoints in the path. + * Increments pNetId->netid_seg once for each new segment identifier + * created. + * Updates the density information in each channel as the pins are + * marked as taken. + * + * ---------------------------------------------------------------------------- + */ + +void +glCrossMark(rootUse, path, pNetId) + CellUse *rootUse; /* For error feedback if non-NULL */ + GlPoint *path; /* Path linked via gl_path pointers */ + NetId *pNetId; /* Net and segment identifier; netid_seg is updated */ +{ + GCRPin *srcPin, *dstPin; + GlPoint *rp; + bool srcTaken; + NetId markNetId; + + /* + * Walk from path back along gl_path pointers down the list. + * At each step, process the segment between srcPin and + * dstPin in the channel srcPin->gcr_ch. + */ + for (rp = path; rp->gl_path; rp = rp->gl_path) + { + /* + * Increment the segment id once for each channel the net passes + * through. The intent is to make this net appear different to + * the channel router for each global segment processed. + */ + pNetId->netid_seg++; + glCrossingsUsed++; + + /* + * Figure out which segment number to use: + * If srcPin has already been assigned a net, use its segment id + * to mark dstPin and don't do anything to srcPin; otherwise, + * use pNetId->netid_seg as the segment identifier and mark + * both pins as taken. + */ + markNetId = *pNetId; + srcPin = rp->gl_path->gl_pin; + srcTaken = srcPin->gcr_pId && srcPin->gcr_pSeg != GCR_STEMSEGID; + if (srcTaken) + markNetId.netid_seg = srcPin->gcr_pSeg; + + /* Pick the dest pin in the same channel as srcPin */ + dstPin = rp->gl_pin; + if (dstPin->gcr_ch != srcPin->gcr_ch) dstPin = dstPin->gcr_linked; + ASSERT(dstPin&&dstPin->gcr_ch == srcPin->gcr_ch, "glCrossMark"); + + /* Adjust the density -- must happen before pins are marked! */ + if (glDensAdjust(((GlobChan *) srcPin->gcr_ch->gcr_client)->gc_postDens, + srcPin, dstPin, markNetId)) + glChanBlockDens(srcPin->gcr_ch); + + /* Mark pins as taken */ + if (!srcTaken) + glCrossTakePin(rootUse, srcPin, markNetId); + glCrossTakePin(rootUse, dstPin, markNetId); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * glCrossTakePin -- + * + * Reserve a channel's pin for the given net. + * Make a number of sanity checks. + * + * Results: + * None. + * + * Side effects: + * Marks the pin as being taken by the net, by setting + * gcr_pId and gcr_pSeg. + * + * ---------------------------------------------------------------------------- + */ + +void +glCrossTakePin(rootUse, pin, netid) + CellUse *rootUse; /* For error feedback if non-NULL */ + GCRPin *pin; /* Pin to take */ + NetId netid; /* Identifier to assign */ +{ + char c[256], name1[1024], name2[1024]; + Rect r; + + if (DebugIsSet(glDebugID, glDebGreedy)) + return; + + if (DebugIsSet(glDebugID, glDebCross)) + { + glShowCross(pin, netid, CROSS_PERM); + TxMore("-- crossing --"); + } + + r.r_ll = r.r_ur = pin->gcr_point; r.r_xtop++; r.r_ytop++; + ASSERT(netid.netid_net != (NLNet *) NULL, "glCrossTakePin"); + + if (pin->gcr_pId == (GCRNet *) NULL + || (pin->gcr_pId == (GCRNet *) netid.netid_net + && pin->gcr_pSeg == GCR_STEMSEGID)) + { + pin->gcr_pId = (GCRNet *) netid.netid_net; + pin->gcr_pSeg = netid.netid_seg; + + /* Unlink from list along channel side */ + if (pin->gcr_pPrev && (pin->gcr_pPrev->gcr_pNext = pin->gcr_pNext)) + pin->gcr_pNext->gcr_pPrev = pin->gcr_pPrev; + } + else if (pin->gcr_pId == (GCRNet *) netid.netid_net + && pin->gcr_pSeg == netid.netid_seg) + { + (void) sprintf(c, "Warning: crossing reassigned to same net/seg"); + if (rootUse) + DBWFeedbackAdd(&r, c, rootUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); + else TxError("%s\n", c); + } + else + { + /* Shouldn't happen: indicates a bug elsewhere */ + (void) strcpy(name1, NLNetName(pin->gcr_pId)); + (void) strcpy(name2, NLNetName(netid.netid_net)); + (void) sprintf(c, "Crossing multiply used, nets %s/%d, %s/%d", + name1, pin->gcr_pSeg, name2, netid.netid_seg); + if (rootUse) + DBWFeedbackAdd(&r, c, rootUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); + else TxError("%s\n", c); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * glCrossUnreserve -- + * + * Visit all of the pins used by the stems of the NLNet 'net' and reset + * the gcr_pId and gcr_pSeg fields to show a NULL net and no segment id. + * This procedure is called only just prior to the global routing for each + * net; it keeps the crossings that might be used by this net reserved up + * until the last possible minute, but makes sure that they don't stay + * reserved once we actually know the routing for this net (since otherwise + * the channel router would try to connect them up!). + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +glCrossUnreserve(net) + NLNet *net; +{ + NLTermLoc *loc; + NLTerm *term; + GCRPin *pin; + + /* De-reserve the pins taken by each terminal location in this net */ + for (term = net->nnet_terms; term; term = term->nterm_next) + for (loc = term->nterm_locs; loc; loc = loc->nloc_next) + { + pin = loc->nloc_pin; + ASSERT(pin->gcr_pSeg == GCR_STEMSEGID, "glCrossUnreserve"); + pin->gcr_pId = (GCRNet *) NULL; + pin->gcr_pSeg = 0; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * glCrossEnum -- + * + * Enumerate the crossing points between the tile inPt->gl_tile + * and 'tp'. The two tiles should overlap different channels. + * + * For each available crossing (i.e., a pin that is yet unassigned + * and has a linked pin), call the procedure (*func)(), which should + * be of the following form: + * + * int + * (*func)(inPt, tp, pin, cdata) + * GlPoint *inPt; /# Same as inPt passed to glCrossEnum #/ + * Tile *tp; /# Same as tp passed to glCrossEnum #/ + * GCRPin *pin; /# A free pin in 'tp' #/ + * ClientData cdata; /# Same as cdata passed to glCrossEnum #/ + * { + * } + * + * If (*func)() returns 1, glCrossEnum() immediately stops visiting + * further crossing points and returns 1 itself; otherwise, we keep + * going until we run out of crossing points to visit. + * + * Results: + * Returns 1 if (*func)() returned 1; otherwise, returns 0. + * + * Side effects: + * Whatever (*func)() does. + * + * ---------------------------------------------------------------------------- + */ + +int +glCrossEnum(inPt, tp, func, cdata) + GlPoint *inPt; /* Top of heap point being expanded */ + Tile *tp; /* Tile adjacent to inPt->gl_tile */ + int (*func)(); /* Called for each crossing */ + ClientData cdata; /* Passed to (*func)() */ +{ + int outSide, origin, lo, hi, max, start, n, nhi; + GCRChannel *ch = inPt->gl_pin->gcr_ch; + Tile *inTile = inPt->gl_tile; + GCRPin *pins, *pin; + + /* Sanity checks: callers should ensure that these are true */ + ASSERT(tp->ti_client != (ClientData) CLIENTDEFAULT, "glCrossEnum"); + ASSERT((GCRChannel *) tp->ti_client != ch, "glCrossEnum"); + + /* + * Find out the direction from inTile to tp. + * We assume that the two tiles share a side, so this + * is pretty straightforward. + */ + if (LEFT(inTile) == RIGHT(tp)) outSide = GEO_WEST; + else if (RIGHT(inTile) == LEFT(tp)) outSide = GEO_EAST; + else if (TOP(inTile) == BOTTOM(tp)) outSide = GEO_NORTH; + else if (BOTTOM(inTile) == TOP(tp)) outSide = GEO_SOUTH; + + /* + * Find the range of points shared between the two tiles. + * Note that we look at the TILES, not the CHANNELS, since + * there can be many tiles for a single channel. + */ + if (outSide == GEO_NORTH || outSide == GEO_SOUTH) + { + lo = MAX(LEFT(inTile), LEFT(tp)); + hi = MIN(RIGHT(inTile), RIGHT(tp)); + origin = ch->gcr_origin.p_x; + max = ch->gcr_length; + } + else + { + lo = MAX(BOTTOM(inTile), BOTTOM(tp)); + hi = MIN(TOP(inTile), TOP(tp)); + origin = ch->gcr_origin.p_y; + max = ch->gcr_width; + } + + /* + * Now find the range of pins shared between the two tiles. + * We're careful about which pins are actually shared: we + * round the lower coordinate up unless it's grid-aligned, + * but round the higher coordinate down even if it is + * grid-aligned. I.e., + * + * lo' = pin with least coordinate >= lo + * hi' = pin with greatest coordinate < hi + * + * The range of pins shared should be non-NULL; if it's not, + * something is wrong (most likely the channel is too small). + * The pins range from lo to hi, inclusive, and should not + * include pin[0] or pin[length+1] or pin[width+1] (the latter + * respectively for vertical or horizontal edges between tiles). + */ + lo = (lo + RtrGridSpacing - 1 - origin) / RtrGridSpacing; + hi = (hi - origin - 1) / RtrGridSpacing; + ASSERT(lo >= 1 && lo <= max, "glCrossEnum"); + if (lo > hi) + return 0; + + switch (outSide) + { + case GEO_NORTH: pins = ch->gcr_tPins; break; + case GEO_SOUTH: pins = ch->gcr_bPins; break; + case GEO_EAST: pins = ch->gcr_rPins; break; + case GEO_WEST: pins = ch->gcr_lPins; break; + } + + /* + * Now comes the fun part: enumerating pins in the range + * from lo .. hi inclusive in such a way that we visit + * the CLOSEST pin to inPt FIRST. Choose start so that + * it's the index of the closest pin on the exit side to + * inPt, and then worry about whether or not it's in the + * range of pins shared with the next tile. + */ + start = (outSide == GEO_NORTH || outSide == GEO_SOUTH) + ? inPt->gl_pin->gcr_x + : inPt->gl_pin->gcr_y; + + /* CASE 1: visit from bottom to top (or left to right) */ + if (start <= lo) + { + for (n = lo; n <= hi; n++, glCrossingsSeen++) + { + pin = &pins[n]; + if (PINOK(pin) && PINOK(pin->gcr_linked) + && (*func)(inPt, tp, pin->gcr_linked, cdata)) + return 1; + } + return 0; + } + + /* CASE 1: visit from top to bottom (or right to left) */ + if (start >= hi) + { + for (n = hi; n >= lo; n--, glCrossingsSeen++) + { + pin = &pins[n]; + if (PINOK(pin) && PINOK(pin->gcr_linked) + && (*func)(inPt, tp, pin->gcr_linked, cdata)) + return 1; + } + return 0; + } + + /* + * CASE 3: + * Have to consider candidates alternating from + * left to right (or top to bottom) to find the + * closest available pin. Start at the center. + */ + for (n = start, nhi = start+1; n >= lo || nhi <= hi; n--, nhi++) + { + if (n >= lo) + { + glCrossingsSeen++; + pin = &pins[n]; + if (PINOK(pin) && PINOK(pin->gcr_linked) + && (*func)(inPt, tp, pin->gcr_linked, cdata)) + return 1; + } + if (nhi <= hi) + { + glCrossingsSeen++; + pin = &pins[nhi]; + if (PINOK(pin) && PINOK(pin->gcr_linked) + && (*func)(inPt, tp, pin->gcr_linked, cdata)) + return 1; + } + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glCrossAdjust -- + * + * Given a path of crossing points, wiggle them around in each channel + * to try to reduce the total penalty on the path. Construct a new + * path of crossing points that uses the points we select in this way, + * and whose cost fields (gl_cost) include both distance and the + * penalties. Be careful when wiggling crossings through a river + * routing channel: they all have to wiggle at the same time. + * + * Algorithm: + * Two crossing points in the input path are already fixed: + * path itself, and the crossing point at the very end (the + * one for which gl_path is NULL). Starting from the crossing + * point at the end and working back toward 'path', assign + * crossings to all points in the middle. The procedure to + * do this is recursive, considering at each stage three + * crossing points: one that has already been assigned + * (which is either the last point in the path, or the result + * of the previous recursive call), one that is to be assigned + * (the current point along the path), and a "lookahead" point + * (the one that will be next assigned, so we can consider + * it as well when positining the current point. + * + * Results: + * Returns a pointer to the final point in a new path of crossings, + * linked via their gl_path pointers. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +GlPoint * +glCrossAdjust(lookAhead, path) + GlPoint *lookAhead; /* Normally, lookAhead->gl_path == path, except on the + * initial call, in which case lookAhead == NULL. + */ + GlPoint *path; /* Adjust crossings along this path */ +{ + GlPoint *newPath, *newRest; + GCRPin *linkedPin, *pin; + GCRChannel *ch; + + /* + * The location of the last crossing along the path is fixed, + * since it's the "starting point". Simply return when we + * reach this point, since there's no penalty to be computed + * yet. + */ + ASSERT(path != (GlPoint *) NULL, "glCrossAdjust"); + if (path->gl_path == (GlPoint *) NULL) + return path; + + /* + * Basic recursive step: assign crossings to everything + * in the remainder of the path, then cons a new GlPoint + * to the front of the path and adjust its position + * below. The initial cost of newPath will be that + * to the pin it initially occupies, before being + * wiggled by glCrossChoose() later. This gives + * us an upper bound on an acceptable cost. + */ + newRest = glCrossAdjust(path, path->gl_path); + newPath = glPathNew(path->gl_pin, 0, newRest); + newPath->gl_cost = newRest->gl_cost + glCrossCost(lookAhead, path, newRest); + newPath->gl_tile = path->gl_tile; + + /* + * If this was the first crossing in the path, it's also + * immutable and so we just cons it to the path and return. + * We still use a new GlPoint, though, since the cost of + * this point has to include the penalties along the path. + */ + if (lookAhead == (GlPoint *) NULL) + return newPath; + + if (TiGetType(newRest->gl_tile) != CHAN_NORMAL) + { + /* + * If newRest was through a river-routing channel, it fixes + * the pin on the exit side. + */ + pin = newRest->gl_pin; + ch = pin->gcr_ch; + switch (pin->gcr_side) + { + case GEO_NORTH: linkedPin = &ch->gcr_bPins[pin->gcr_x]; break; + case GEO_EAST: linkedPin = &ch->gcr_lPins[pin->gcr_y]; break; + case GEO_SOUTH: linkedPin = &ch->gcr_tPins[pin->gcr_x]; break; + case GEO_WEST: linkedPin = &ch->gcr_rPins[pin->gcr_y]; break; + } + ASSERT(PINOK(linkedPin), "glCrossAdjust"); + newPath->gl_pin = linkedPin->gcr_linked; + newPath->gl_cost = newRest->gl_cost; + newPath->gl_cost += glCrossCost(lookAhead, newPath, newRest); + } + else + { + /* + * Time to choose a crossing for 'path'. + * It has to lie somewhere along the boundary between path->gl_tile + * and newRest->gl_tile. (These two tiles will be different unless + * path is the destination point, but we checked for that above when + * we looked for lookAhead being NULL). Enumerate the crossings + * along this boundary looking for the best one. + */ + glCrossLookAhead = lookAhead; + (void) glCrossEnum(newRest, path->gl_tile, glCrossChoose, + (ClientData) newPath); + } + + return newPath; +} + +/* + * ---------------------------------------------------------------------------- + * + * glCrossChoose -- + * + * Called by glCrossEnum() on behalf of glCrossAdjust() above. + * Evaluate 'pin' as a possible crossing by computing the penalty of + * a segment from newRest through newPath (setting newPath->gl_pin to + * pin), and on through to glCrossLookAhead (if it's non-NULL). + * + * Results: + * Returns 0 normally, or 1 to tell glCrossEnum() that it + * can stop looking at further crossings. + * + * Side effects: + * May modify newPath->gl_cost and newPath->gl_pin. + * + * ---------------------------------------------------------------------------- + */ + + /*ARGSUSED*/ +int +glCrossChoose(newRest, tp, pin, newPath) + GlPoint *newRest; /* Portion of path already assigned */ + Tile *tp; /* UNUSED */ + GCRPin *pin; /* Pin on boundary of tp being considered */ + GlPoint *newPath; /* Update newPath->gl_pin, newPath->gl_cost */ +{ + GCRPin *savePin; + int cost; + + /* + * We've been visiting crossings in order of increasing distance + * from newRest. If the distance to 'pin' plus newRest->gl_cost + * already exceeds the best cost we've been able to find for + * newPath, then we can't gain any more improvement by considering + * any more crossing point, so we stop. + */ + cost = ABSDIFF(pin->gcr_point.p_x, newRest->gl_pin->gcr_point.p_x) + + ABSDIFF(pin->gcr_point.p_y, newRest->gl_pin->gcr_point.p_y) + + newRest->gl_cost; + if (cost >= newPath->gl_cost) + return 1; + + /* + * Evaluate the cost of using 'pin' as the crossing point. + * If it's a better choice than what's currently stored in newPath, + * then use it and update the cost in newPath. + */ + savePin = newPath->gl_pin; + newPath->gl_pin = pin; + cost = newRest->gl_cost + glCrossCost(glCrossLookAhead, newPath, newRest); + if (cost < newPath->gl_cost) + newPath->gl_cost = cost; + else + newPath->gl_pin = savePin; + + /* Keep looking at more crossing points */ + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glCrossCost -- + * + * Evaluate the cost of the segment from 'entryPt' to 'exitPt' (and on through + * 'lookAhead' if it is non-NULL). + * + * Results: + * Returns the sum of the distance from rest to path and the + * penalties associated with this segment. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +glCrossCost(lookAhead, exitPt, entryPt) + GlPoint *lookAhead; + GlPoint *exitPt; + GlPoint *entryPt; +{ + GCRPin *entryPin, *exitPin, *otherPin; + GCRPin *opposite; + int count, cost; + + /* + * Make sure that both entryPin and exitPin are in the same + * channel, and otherPin is in the next channel. + */ + entryPin = entryPt->gl_pin; + exitPin = exitPt->gl_pin; + if (exitPin->gcr_ch != entryPin->gcr_ch) + exitPin = exitPin->gcr_linked; + otherPin = exitPin->gcr_linked; + ASSERT(exitPin != NULL, "glCrossCost"); + + /* Distance cost */ + cost = ABSDIFF(entryPin->gcr_point.p_x, exitPin->gcr_point.p_x) + + ABSDIFF(entryPin->gcr_point.p_y, exitPin->gcr_point.p_y); + + /* + * If exitPt is in a river-routing tile, and we have to continue + * across the channel (lookAhead is non-NULL), then make sure the pin + * on the opposite side is free; otherwise, exitPt has "infinite" + * penalty since it's unusable. + */ + if (lookAhead && TiGetType(exitPt->gl_tile) != CHAN_NORMAL) + { + switch (otherPin->gcr_side) + { + case GEO_NORTH: + opposite = &otherPin->gcr_ch->gcr_bPins[otherPin->gcr_x]; + break; + case GEO_SOUTH: + opposite = &otherPin->gcr_ch->gcr_tPins[otherPin->gcr_x]; + break; + case GEO_EAST: + opposite = &otherPin->gcr_ch->gcr_lPins[otherPin->gcr_y]; + break; + case GEO_WEST: + opposite = &otherPin->gcr_ch->gcr_rPins[otherPin->gcr_y]; + break; + } + if (!PINOK(opposite)) + return INFINITY; + } + + /* Penalty for using lots of channels */ + cost += glChanPenalty; + + /* Penalize if the net doesn't run straight across the channel */ + if (entryPin->gcr_x != exitPin->gcr_x && entryPin->gcr_y != exitPin->gcr_y) + cost += glJogPenalty; + + /* + * If there is an obstacle or hazard over a crossing, or an + * obstacle somewhere along the track or column of the pin, + * then assess a penalty. Look on both sides of the crossing + * to get this penalty. + */ +#define BADCROSSFLAGS (GCROBST|GCRHAZRD|GCRTCC) + if (otherPin && otherPin->gcr_ch->gcr_type == CHAN_NORMAL) + { + if ((otherPin->gcr_pFlags & BADCROSSFLAGS) || otherPin->gcr_pSize != 0) + { + ASSERT(otherPin->gcr_pSize >= 0, "glCrossPenalty"); + cost += glObsPenalty1; + if (otherPin->gcr_pFlags & GCROBST) + cost += glObsPenalty2 * otherPin->gcr_pSize; + else if (otherPin->gcr_pFlags & GCRHAZRD) + cost += MAX(glObsPenalty2*otherPin->gcr_pSize + - otherPin->gcr_pDist, 0); + } + } + + /* + * Done if this channel is used for river-routing (in which + * case the subsequent penalty computation is not needed). + */ + if (entryPin->gcr_ch->gcr_type != CHAN_NORMAL) + return cost; + + if ((exitPin->gcr_pFlags & BADCROSSFLAGS) || exitPin->gcr_pSize != 0) + { + ASSERT(exitPin->gcr_pSize >= 0, "glCrossPenalty"); + cost += glObsPenalty1; + if (exitPin->gcr_pFlags & GCROBST) + cost += glObsPenalty2 * exitPin->gcr_pSize; + else if (exitPin->gcr_pFlags & GCRHAZRD) + cost += MAX(glObsPenalty2 * exitPin->gcr_pSize + - exitPin->gcr_pDist, 0); + } + + /* Penalty for "congestion" (neighboring pins in use) */ + count = 0; + if ((exitPin + 1)->gcr_pId) count++; + if ((exitPin - 1)->gcr_pId) count++; + if (count == 2) cost += glNbrPenalty2; + else if (count == 1) cost += glNbrPenalty1; + + /* + * If the path turns in the channel and the exit crossing + * isn't a paired orphan, assess a penalty. + */ + if (exitPin->gcr_side != GeoOppositePos[entryPin->gcr_side]) + { + switch (exitPin->gcr_side) + { + case GEO_NORTH: + otherPin = &entryPin->gcr_ch->gcr_bPins[exitPin->gcr_x]; + break; + case GEO_SOUTH: + otherPin = &entryPin->gcr_ch->gcr_tPins[exitPin->gcr_x]; + break; + case GEO_EAST: + otherPin = &entryPin->gcr_ch->gcr_lPins[exitPin->gcr_y]; + break; + case GEO_WEST: + otherPin = &entryPin->gcr_ch->gcr_rPins[exitPin->gcr_y]; + break; + } + if (otherPin->gcr_pId == (GCRNet *) NULL) + cost += glOrphanPenalty; + } + + return cost; +} + +/* + * ---------------------------------------------------------------------------- + * + * glCrossScalePenalties -- + * + * Scale the penalties used in the global router cost function so they + * reflect the actual grid size used during routing. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +glCrossScalePenalties() +{ + if (glPenaltiesScaled) + return; + + glPenaltiesScaled = TRUE; + glJogPenalty *= RtrGridSpacing; + glObsPenalty1 *= RtrGridSpacing; + glObsPenalty2 *= RtrGridSpacing; + glNbrPenalty1 *= RtrGridSpacing; + glNbrPenalty2 *= RtrGridSpacing; + glOrphanPenalty *= RtrGridSpacing; + glChanPenalty *= RtrGridSpacing; +} diff --git a/grouter/grouteDebug.h b/grouter/grouteDebug.h new file mode 100644 index 00000000..153873d8 --- /dev/null +++ b/grouter/grouteDebug.h @@ -0,0 +1,60 @@ +/* + * grouteDebug.h -- + * + * Definitions of debugging flags for the global router. + * This is a separate include file so that new debugging flags + * can be added to it without forcing recompilation of the + * entire module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * and the Regents of the University of California + * + * rcsid $Header: /usr/cvsroot/magic-8.0/grouter/grouteDebug.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + + /* Flags */ +extern int glDebAllPoints; +extern int glDebChan; +extern int glDebCross; +extern int glDebFast; +extern int glDebGreedy; +extern int glDebHeap; +extern int glDebHisto; +extern int glDebLog; +extern int glDebMaze; +extern int glDebNet; +extern int glDebNewHeaps; +extern int glDebPen; +extern int glDebShowPins; +extern int glDebStemsOnly; +extern int glDebStraight; +extern int glDebTiles; +extern int glDebVerbose; + + /* Arguments to glShowCross */ +#define CROSS_TEMP 0 /* Crossing point considered but not granted */ +#define CROSS_PERM 1 /* Crossing point permanently taken */ +#define CROSS_ERASE 2 /* Crossing point to be erased */ + +typedef struct glNetHisto +{ + int glh_frontier; /* Total frontier points visited */ + int glh_heap; /* Points removed from top of heap */ + int glh_start; /* Starting points */ + struct glNetHisto *glh_next; /* Next entry in list */ +} GlNetHisto; + +extern char *glOnlyNet; +extern GlNetHisto *glNetHistoList; +extern FILE *glLogFile; +extern int glNumTries; diff --git a/grouter/grouteDens.c b/grouter/grouteDens.c new file mode 100644 index 00000000..b172f3a3 --- /dev/null +++ b/grouter/grouteDens.c @@ -0,0 +1,327 @@ +/* + * grouteDens.c + * + * Procedures for manipulating DensMap structures. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/grouter/grouteDens.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/netlist.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "utils/styles.h" +#include "debug/debug.h" + +/* + * ---------------------------------------------------------------------------- + * + * glDensAdjust -- + * + * Increment the density in the channel as a result of routing the segment + * from p1 to p2 through the channel common to both. The segment is + * identified by the NetId 'netid'. The density map 'dens' is incremented + * for each column/row of the channel through which the segment must run, + * where the segment doesn't already exist. + * + * Results: + * Returns TRUE if any more of srcPin->gcr_ch became filled + * up to maximum density. + * + * Side effects: + * Modifies the local and possibly the maximum densities in *dens. + * + * ---------------------------------------------------------------------------- + */ + +bool +glDensAdjust(dens, srcPin, dstPin, netid) + DensMap dens[2]; + GCRPin *srcPin, *dstPin; + NetId netid; +{ + int minprow, maxprow, minpcol, maxpcol, mincol, maxcol, minrow, maxrow; + int maxvd, maxhd, col, row, nrow, ncol; + GCRChannel *ch = srcPin->gcr_ch; + GCRPin *p1, *p2; + short *dvec; + bool densChanged; + + /* Sanity checking */ + ASSERT(srcPin && dstPin, "glDensAdjust"); + ASSERT(srcPin->gcr_ch == dstPin->gcr_ch, "glDensAdjust"); + + if (DebugIsSet(glDebugID, glDebGreedy)) + return FALSE; + + /* + * Find the first and last column where this net (netId) + * is previously present in the channel, and also the first + * and last row. + */ + nrow = dens[CZ_ROW].dm_size - 1; + ncol = dens[CZ_COL].dm_size - 1; + maxprow = 0, minprow = dens[CZ_ROW].dm_size; + maxpcol = 0, minpcol = dens[CZ_COL].dm_size; + + /* Rows */ + p1 = &ch->gcr_lPins[1], p2 = &ch->gcr_rPins[1]; + for (row = 1; row < dens[CZ_ROW].dm_size; row++, p1++, p2++) + { + if (SAMENET(p1, netid.netid_net, netid.netid_seg)) + { + minpcol = 1; + minprow = MIN(row, minprow); + maxprow = MAX(row, maxprow); + } + if (SAMENET(p2, netid.netid_net, netid.netid_seg)) + { + maxpcol = ncol; + minprow = MIN(row, minprow); + maxprow = MAX(row, maxprow); + } + } + + /* Columns */ + p1 = &ch->gcr_bPins[1], p2 = &ch->gcr_tPins[1]; + for (col = 1; col < dens[CZ_COL].dm_size; col++, p1++, p2++) + { + if (SAMENET(p1, netid.netid_net, netid.netid_seg)) + { + minprow = 1; + minpcol = MIN(col, minpcol); + maxpcol = MAX(col, maxpcol); + } + if (SAMENET(p2, netid.netid_net, netid.netid_seg)) + { + maxprow = nrow; + minpcol = MIN(col, minpcol); + maxpcol = MAX(col, maxpcol); + } + } + + /* + * Increment the density over any range where + * this net was not already present but is now. + */ + p1 = srcPin; + p2 = dstPin; + +#define CLIPTORANGE(x, min, max) \ + ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))) + + densChanged = FALSE; + minrow = MIN(p1->gcr_y, p2->gcr_y); + minrow = CLIPTORANGE(minrow, 1, nrow); + maxrow = MAX(p1->gcr_y, p2->gcr_y); + maxrow = CLIPTORANGE(maxrow, 1, nrow); + maxvd = dens[CZ_ROW].dm_max; + dvec = dens[CZ_ROW].dm_value; + for (row = minrow; row <= maxrow; row++) + if (row < minprow || row > maxprow) + if (++dvec[row] >= maxvd) + { + densChanged = TRUE; + maxvd = dvec[row]; + } + dens[CZ_ROW].dm_max = maxvd; + + mincol = MIN(p1->gcr_x, p2->gcr_x); + mincol = CLIPTORANGE(mincol, 1, ncol); + maxcol = MAX(p1->gcr_x, p2->gcr_x); + maxcol = CLIPTORANGE(maxcol, 1, ncol); + maxhd = dens[CZ_COL].dm_max; + dvec = dens[CZ_COL].dm_value; + for (col = mincol; col <= maxcol; col++) + if (col < minpcol || col > maxpcol) + if (++dvec[col] >= maxhd) + { + maxhd = dvec[col]; + densChanged = TRUE; + } + dens[CZ_COL].dm_max = maxhd; + return densChanged; +} + +/* + * ---------------------------------------------------------------------------- + * + * glDMAlloc -- + * + * Allocate and zero the dm_value array for the DensMap structure 'dm'. + * This array will have size 'top+1'. The maximum capacity is 'cap'. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +glDMAlloc(dm, top, cap) + DensMap *dm; + int top, cap; +{ + dm->dm_max = 0; + dm->dm_size = top + 1; + dm->dm_cap = cap; + dm->dm_value = (short *) callocMagic((unsigned) (sizeof (short) * dm->dm_size)); +} + +/* + * ---------------------------------------------------------------------------- + * + * glDMCopy -- + * + * Copy the DensMap structure *dm1 to *dm2, copying the dm_value array + * as well. (The two DensMap structures better have the same size; + * also, dm2->dm_value must already be allocated). + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +glDMCopy(dm1, dm2) + DensMap *dm1, *dm2; +{ + dm2->dm_max = dm1->dm_max; + ASSERT(dm2->dm_size == dm1->dm_size, "glDMCopy"); + ASSERT(dm2->dm_cap == dm1->dm_cap, "glDMCopy"); + bcopy((char *) dm1->dm_value, (char *) dm2->dm_value, + sizeof (short) * dm1->dm_size); +} + +/* + * ---------------------------------------------------------------------------- + * + * glDMFree -- + * + * Free the memory allocated to dm->dm_value. + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * + * ---------------------------------------------------------------------------- + */ + +void +glDMFree(dm) + DensMap *dm; +{ + freeMagic((char *) dm->dm_value); +} + +/* + * ---------------------------------------------------------------------------- + * + * glDMMaxInRange -- + * + * Return the maximum value of the DensMap in the inclusive range lo .. hi. + * + * Results: + * See above. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +glDMMaxInRange(dm, lo, hi) + DensMap *dm; + int lo, hi; +{ + short *dval = dm->dm_value; + int n, max; + + /* Sanity checks */ + ASSERT(lo > 0, "glDMMaxInRange"); + ASSERT(hi < dm->dm_size, "glDMMaxInRange"); + + max = 0; + for (n = lo; n <= hi; n++) + if (dval[n] > max) + max = dval[n]; + + return (max); +} + +/* + * ---------------------------------------------------------------------------- + * + * glDensInit -- + * + * Initialize the DensMap pair dmap[] from the already-initialized + * density map in the GCRChannel *ch. (The use of two separate kinds + * of density maps is a temporary measure that will go away when the + * integration of the new routing code is complete). + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +glDensInit(dmap, ch) + DensMap dmap[2]; + GCRChannel *ch; +{ + short *dSrc, *dDst, *dEnd; + + dmap[CZ_COL].dm_max = ch->gcr_dMaxByCol; + dmap[CZ_ROW].dm_max = ch->gcr_dMaxByRow; + dSrc = ch->gcr_dRowsByCol; + dDst = dmap[CZ_COL].dm_value; + dEnd = &dmap[CZ_COL].dm_value[dmap[CZ_COL].dm_size]; + while (dDst < dEnd) + *dDst++ = *dSrc++; + + dSrc = ch->gcr_dColsByRow; + dDst = dmap[CZ_ROW].dm_value; + dEnd = &dmap[CZ_ROW].dm_value[dmap[CZ_ROW].dm_size]; + while (dDst < dEnd) + *dDst++ = *dSrc++; +} diff --git a/grouter/grouteMain.c b/grouter/grouteMain.c new file mode 100644 index 00000000..52b730f1 --- /dev/null +++ b/grouter/grouteMain.c @@ -0,0 +1,393 @@ +/* + * grouteMain.c -- + * + * Top level code for the global signal router. + * + * The global router's job is to find the sequence of channel pins + * through which each signal must pass, and mark these pins so the + * channel router can connect them within each channel. + * + * Our overall approach is greedy: we compute the area of the bounding + * box of all terminals in a net for each net, and perform global routing + * of each net in order of increasing area of this bounding box. This + * has the effect of routing more constrained nets first, and less + * constrained ones later. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#include +#include +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/styles.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "debug/debug.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "utils/styles.h" +#include "textio/textio.h" +#include "utils/malloc.h" + +/* Global data */ +Heap glMazeHeap; /* Heap of search points for global routing */ +FILE *glLogFile; /* Used for debugging to remember crossings processed */ +int glNumTries; /* Debugging too -- # calls to glProcessLoc() */ + +/* Forward declarations */ +void glClientInit(); +void glClientFree(); + + +/* + * ---------------------------------------------------------------------------- + * + * GlGlobalRoute -- + * + * Build a heap of nets, ordered with smallest area first. + * Globally route nets on the heap, decomposing multi-pin nets using + * Steiner-like trees. Leave routing problems in channel structures. + * + * Results: + * None. + * + * Side effects: + * On completion crossing points for nets have been set. Channel + * structures are ready to be routed by the channel structure. + * + * ---------------------------------------------------------------------------- + */ + +void +GlGlobalRoute(chanList, netList) + GCRChannel *chanList; /* List of all channels in routing problem */ + NLNetList *netList; /* Netlist built by caller */ +{ + HeapEntry entry; + Heap netHeap; + bool doFast; + int numTerms; + NLNet *net; + + GlInit(); + glStatsInit(); + doFast = DebugIsSet(glDebugID, glDebFast); + + /* + * Initialize the client-specific portion of each channel and + * of each net. These fields point to structures holding + * (respectively) density information and blocked regions + * during global routing. + */ + glClientInit(chanList, netList); + + /* + * Build a tile plane that represents all the channels in the + * routing problem. This tile plane will be used to search + * for nearby channels during global routing. + */ + glChanBuildMap(chanList); + if (DebugIsSet(glDebugID, glDebChan)) + { + SigInterruptPending = TRUE; + return; + } + + /* Compute penalties for passing through congested zones */ + if (DebugIsSet(glDebugID, glDebPen)) + glPenCompute(chanList, netList); + + /* + * Build a heap of nets sorted in order of increasing size, then + * successively remove the topmost entry of the heap and route its + * net. Make almost-Steiner tree global routes for multi-pin nets. + */ + numTerms = 0; + NLSort(netList, &netHeap); + while (HeapRemoveTop(&netHeap, &entry) && !SigInterruptPending) + { + net = (NLNet *) entry.he_id; + if (DebugIsSet(glDebugID, glDebPen)) + { + glCrossUnreserve(net); + glPenSetPerChan(net); + } + numTerms += glMultiSteiner(EditCellUse, net, glProcessLoc, + glCrossMark, (ClientData) doFast, (ClientData) 0); + if (DebugIsSet(glDebugID, glDebPen)) + glPenClearPerChan(net); + RtrMilestonePrint(); + } + HeapKill(&netHeap, (void (*)()) NULL); + + glClientFree(chanList, netList); + glChanFreeMap(); + glStatsDone(netList->nnl_numNets, numTerms); +} + +/* + * ---------------------------------------------------------------------------- + * + * glClientInit -- + * + * Allocate and initialize the structures that go in the gcr_client and + * nnet_cdata fields of all the channels and nets respectively in chanList + * and netList, and leave these fields pointing to the newly allocated and + * initialized structures. + * + * Results: + * None. + * + * Side effects: + * Allocates memory; see above. + * + * ---------------------------------------------------------------------------- + */ + +void +glClientInit(chanList, netList) + GCRChannel *chanList; + NLNetList *netList; +{ + GCRChannel *ch; + GlobChan *gc; + NLNet *net; + int nrow, ncol; + + for (ch = chanList; ch; ch = ch->gcr_next) + { + gc = (GlobChan *) mallocMagic((unsigned) (sizeof (GlobChan))); + gc->gc_penList = (CZone *) NULL; + nrow = ch->gcr_width; + ncol = ch->gcr_length; + glDMAlloc(&gc->gc_prevDens[CZ_COL], ncol, nrow); + glDMAlloc(&gc->gc_prevDens[CZ_ROW], nrow, ncol); + glDMAlloc(&gc->gc_postDens[CZ_COL], ncol, nrow); + glDMAlloc(&gc->gc_postDens[CZ_ROW], nrow, ncol); + glDensInit(gc->gc_prevDens, ch); + glDMCopy(&gc->gc_prevDens[CZ_COL], &gc->gc_postDens[CZ_COL]); + glDMCopy(&gc->gc_prevDens[CZ_ROW], &gc->gc_postDens[CZ_ROW]); + ch->gcr_client = (ClientData) gc; + } + + for (net = netList->nnl_nets; net; net = net->nnet_next) + net->nnet_cdata = (ClientData) callocMagic((unsigned) (sizeof (NetClient))); +} + +/* + * ---------------------------------------------------------------------------- + * + * glClientFree -- + * + * Free the memory allocated by glClientInit() above (as well as any + * memory allocated to CZone lists pointed to by the NetClient structs + * in the NLNetList netList). + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * + * ---------------------------------------------------------------------------- + */ + +void +glClientFree(chanList, netList) + GCRChannel *chanList; + NLNetList *netList; +{ + GlobChan *gc; + CZone *cz; + NetClient *nclient; + GCRChannel *ch; + NLNet *net; + + for (ch = chanList; ch; ch = ch->gcr_next) + { + gc = (GlobChan *) ch->gcr_client; + glDMFree(&gc->gc_prevDens[CZ_COL]); + glDMFree(&gc->gc_prevDens[CZ_ROW]); + glDMFree(&gc->gc_postDens[CZ_COL]); + glDMFree(&gc->gc_postDens[CZ_ROW]); + freeMagic((char *) gc); + ch->gcr_client = (ClientData) NULL; + } + + for (net = netList->nnl_nets; net; net = net->nnet_next) + { + nclient = (NetClient *) net->nnet_cdata; + for (cz = nclient->nc_pens; cz; cz = cz->cz_next) + freeMagic((char *) cz); + net->nnet_cdata = (ClientData) NULL; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * glProcessLoc -- + * + * Function called for all but the first NLTermLoc in a net: finds and + * returns the best-cost path from any of the points in the starting + * point list to loc->nloc_stem. + * + * Algorithm: + * We use two passes. The first attempts to find the shortest + * distance path between the source and the destination, if + * such a path exists. It uses a mechanism for storing the + * best cost so far to each crossing point considered, so + * we avoid looping. If no path can be found, we simply + * give up; otherwise, we perform a second pass where we + * try to generate not only the shortest path, but the + * next shortest, etc, until we find one whose distance + * plus crossing penalty is minimized. + * + * Results: + * Returns the best path. The first element on the list + * (linked by gl_path pointers) is the destination point. + * If no path could be found with cost less than bestCost, + * returns NULL. + * + * Side effects: + * Allocates memory from the temporary GlPoint arena. + * + * ---------------------------------------------------------------------------- + */ + +GlPoint * +glProcessLoc(startList, loc, bestCost, doFast) + GlPoint *startList; /* List of starting points */ + NLTermLoc *loc; /* Location of terminal being routed to */ + int bestCost; /* Best cost so far; if we can't find a path in + * less than this cost, give up. + */ + bool doFast; /* If TRUE, only wiggle crossings around within the + * channels on the shortest path; don't bother + * considering other sequences of channels. If FALSE, + * we keep generating longer and longer paths until + * the sheer length of a path exceeds our best + * adjusted cost to date. + */ +{ + extern bool glMazeShortest; + extern Tile *glMazeDestTile; + extern Point glMazeDestPoint; + extern GlPoint *glMazeFindPath(); + extern GlPoint *glCrossAdjust(); + int headFree, shortLength, bestLength; + GlPoint *lastPt, *bestPt, *adjustedPt; + GlPage *headPage; + + glNumTries++; + glCrossScalePenalties(); + + /* Sanity checks */ + ASSERT(GEO_SAMEPOINT(loc->nloc_pin->gcr_point, loc->nloc_stem), + "glProcessLoc"); + + /* + * Passed to glMazeFindPath() for use in estimating the remaining + * distance to the destination point. Also figure out which + * channel tile contains the destination, so we can handle + * points in it specially. If the destination point is inside + * a blocked area, give up immediately. + */ + glMazeDestPoint = loc->nloc_stem; + glMazeDestTile = glChanPinToTile((Tile *) NULL, loc->nloc_pin); + + /* Abort immediately if destination is obviously unreachable */ + if (glMazeDestTile == NULL) + return (GlPoint *) NULL; + + /* + * First try finding the shortest path. + * This goes very quickly, because we are able to chop + * off unpromising paths at an early stage. + */ + glMazeShortest = TRUE; + HeapInit(&glMazeHeap, 128, FALSE, FALSE); + glListToHeap(startList, &loc->nloc_stem); + headPage = glPathCurPage; + headFree = glPathCurPage->glp_free; + bestPt = glMazeFindPath(loc, bestCost); + glMazeResetCost(headPage, headFree); + HeapKill(&glMazeHeap, (void (*)()) NULL); + if (bestPt == (GlPoint *) NULL) + { + glBadRoutes++; + return bestPt; + } + shortLength = bestPt->gl_cost; + + /* + * Now try finding a path that minimizes the crossing penalty. + * We do this by continuing to generate paths in order of + * increasing length, then adjusting the crossing points + * along the path to minimize (locally) the penalty for + * the path, until we find a path whose unadjusted length + * exceeds the best cost we've been able to achieve so far. + * The gl_cost fields in the paths generated by glCrossAdjust + * incorporate the penalties as well as distance. + */ + HeapInit(&glMazeHeap, 128, FALSE, FALSE); + glListToHeap(startList, &loc->nloc_stem); + if (doFast) + { + headPage = glPathCurPage; + headFree = glPathCurPage->glp_free; + } + else glMazeShortest = FALSE; + bestPt = (GlPoint *) NULL; + while (lastPt = glMazeFindPath(loc, bestCost)) + { + adjustedPt = glCrossAdjust((GlPoint *) NULL, lastPt); + if (adjustedPt->gl_cost < bestCost) + { + bestCost = adjustedPt->gl_cost; + bestLength = lastPt->gl_cost; + bestPt = adjustedPt; + } + } + if (doFast) + glMazeResetCost(headPage, headFree); + HeapKill(&glMazeHeap, (void (*)()) NULL); + if (bestPt) + { + if (glLogFile) + { + fprintf(glLogFile, "%d\t%d (%.2f)\t%d (%.2f)\n", + shortLength, bestLength, + (float) bestLength / (float) shortLength * 100.0, + bestPt->gl_cost, + (float) bestPt->gl_cost / (float) shortLength * 100.0); + } + glGoodRoutes++; + return bestPt; + } + + glBadRoutes++; + glNoRoutes++; + return (GlPoint *) NULL; +} diff --git a/grouter/grouteMaze.c b/grouter/grouteMaze.c new file mode 100644 index 00000000..1419dd5a --- /dev/null +++ b/grouter/grouteMaze.c @@ -0,0 +1,609 @@ +/* + * grouteMaze.c - + * + * Global signal router. Code to route one segment of a + * net, from a set of possible starting points to a single + * destination point. Uses a Lee-like wavefront maze router + * approach, with several performance heuristics to focus + * the search strongly toward the destination rather than + * propagating isotropically from the starting points. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/grouter/grouteMaze.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "utils/malloc.h" +#include "debug/debug.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "utils/styles.h" + +/* Information about the target point */ +Point glMazeDestPoint; /* Point we're routing to */ +Tile *glMazeDestTile; /* Tile in glChanPlane containing destination */ + +/* + * TRUE if we're only finding the shortest path, + * FALSE if we consider all paths. + */ +bool glMazeShortest; + +/* Forward declarations */ +GlPoint *glMazeFindPath(); +int glMazeTileFunc(); +void glMazePropFinal(); +void glMazePropRiver(); +void glMazePropNormal(); +void glMazeTile(); +bool glMazeCheckLoop(); + + +/* + * ---------------------------------------------------------------------------- + * + * glMazeFindPath -- + * + * This is the inner loop of the global router. It assumes that a collection + * of starting points has already been added to the heap, and returns the + * best cost path to the destination from those paths on the heap. + * + * Results: + * Pointer to the crossing point for the destination. Follow + * the gl_path pointers to get the remaining points in the route + * all the way back to one of the starting points that were + * initially added to the heap. Returns NULL if no path was + * found with less cost than bestCost. + * + * Side effects: + * The search point heap (glMazeHeap) changes. If a successful global + * routing was found, all points along the path are removed from + * the heap, leaving other partial path points still on the heap. + * + * ---------------------------------------------------------------------------- + */ + +GlPoint * +glMazeFindPath(loc, bestCost) + NLTermLoc *loc; /* Destination point */ + int bestCost; /* Beat this cost or give up */ +{ + int heapPts, startPts, frontierPts; + GlPoint *inPt; + GCRPin *inPin; + HeapEntry hEntry; + GlPoint *lastPt; + + /* Remember for debugging */ + heapPts = glCrossingsExpanded; + frontierPts = glCrossingsAdded; + startPts = glMazeHeap.he_used; + + /* + * The modified shortest path algorithm extends the partial path for + * which the sum of the current path cost plus the Manhattan distance + * to the destination point is the smallest. + */ + lastPt = (GlPoint *) NULL; + while (!SigInterruptPending && HeapRemoveTop(&glMazeHeap, &hEntry)) + { + glCrossingsExpanded++; + inPt = (GlPoint *) hEntry.he_id; + inPin = inPt->gl_pin; + + /* Done if we reach the destination point */ + if (GEO_SAMEPOINT(inPin->gcr_point, glMazeDestPoint)) + { + lastPt = inPt; + break; + } + + /* + * Give up if the best candidate for expansion is already + * more expensive than the previous best-cost path. + */ + if (inPt->gl_cost >= bestCost) + break; + + /* + * Reject if this pin already has another path to it + * that's cheaper (only reject if we're looking for + * the shortest path). + */ + if (glMazeShortest && inPt->gl_cost > inPt->gl_pin->gcr_cost) + continue; + + /* + * Expand this point. + * Use the type of tile to determine whether we process this + * point as being in a river-routing channel, instead of the + * type of channel overlapping the tile, since it's possible + * for a normal channel to become covered with CHAN_HRIVER or + * CHAN_VRIVER tiles if it contains a point of maximum density. + */ + if (inPt->gl_tile == glMazeDestTile) + glMazePropFinal(inPt, loc); + else if (TiGetType(inPt->gl_tile) == CHAN_NORMAL) + glMazePropNormal(inPt); + else + glMazePropRiver(inPt); + } + + /* Record number of points processed if debugging */ + if (DebugIsSet(glDebugID, glDebHisto)) + glHistoAdd(heapPts, frontierPts, startPts); + + return lastPt; +} + +/* + * ---------------------------------------------------------------------------- + * + * glMazePropFinal -- + * + * Process a point that lies in the destination channel. + * These points are treated specially since we don't need + * to find any more crossings to other channels. + * + * Results: + * None. + * + * Side effects: + * Adds a point to the heap. + * + * ---------------------------------------------------------------------------- + */ + +void +glMazePropFinal(inPt, loc) + GlPoint *inPt; /* Point being processed */ + NLTermLoc *loc; /* Destination point */ +{ + GCRPin *destPin = loc->nloc_pin; + Point *destPoint = &loc->nloc_stem; + GlPoint *outPt; + int cost; + + cost = inPt->gl_cost; + cost += ABSDIFF(inPt->gl_pin->gcr_point.p_x, destPoint->p_x); + cost += ABSDIFF(inPt->gl_pin->gcr_point.p_y, destPoint->p_y); + cost += glChanPenalty; + + if (glMazeShortest) + { + if (cost >= destPin->gcr_cost) + return; + destPin->gcr_cost = cost; + } + + outPt = glPathNew(destPin, cost, inPt); + outPt->gl_tile = glMazeDestTile; + HeapAddInt(&glMazeHeap, cost, (char *) outPt); + glCrossingsAdded++; +} + +/* + * ---------------------------------------------------------------------------- + * + * glMazePropRiver -- + * + * Process a point belonging to a river-routing channel. Since these + * channels can only be used for routing straight across to their + * other side, we only need to consider a single crossing point. + * + * Results: + * None. + * + * Side effects: + * May add a point to the heap. + * + * ---------------------------------------------------------------------------- + */ + +void +glMazePropRiver(inPt) + GlPoint *inPt; +{ + GCRPin *inPin = inPt->gl_pin, *outPin, *linkedPin; + GCRChannel *inCh = inPin->gcr_ch; + int cost; + Tile *outTile; + GlPoint *outPt; + + /* Find the opposing pin */ + switch (inPin->gcr_side) + { + case GEO_NORTH: outPin = &inCh->gcr_bPins[inPin->gcr_x]; break; + case GEO_SOUTH: outPin = &inCh->gcr_tPins[inPin->gcr_x]; break; + case GEO_EAST: outPin = &inCh->gcr_lPins[inPin->gcr_y]; break; + case GEO_WEST: outPin = &inCh->gcr_rPins[inPin->gcr_y]; break; + } + + /* Ignore if opposing pin is occupied */ + if (!PINOK(outPin) || !PINOK(outPin->gcr_linked)) + return; + linkedPin = outPin->gcr_linked; + outTile = glChanPinToTile(inPt->gl_tile, linkedPin); + ASSERT(outTile != (Tile *) NULL, "glMazePropRiver"); + + /* Cost to cross the channel */ + cost = inPt->gl_cost + + ABSDIFF(inPin->gcr_point.p_x, linkedPin->gcr_point.p_x) + + ABSDIFF(inPin->gcr_point.p_y, linkedPin->gcr_point.p_y) + + glChanPenalty; + + /* Avoid looping or revisiting points unnecessarily */ + if (glMazeShortest) + { + if (cost >= linkedPin->gcr_cost) + return; + linkedPin->gcr_cost = outPin->gcr_cost = cost; + } + else if (glMazeCheckLoop(inPt, outTile)) + return; + + outPt = glPathNew(linkedPin, cost, inPt); + outPt->gl_tile = outTile; + + /* Add in estimate of distance remaining to goal */ + cost += ABSDIFF(glMazeDestPoint.p_x, linkedPin->gcr_point.p_x) + + ABSDIFF(glMazeDestPoint.p_y, linkedPin->gcr_point.p_y); + { + HeapAddInt(&glMazeHeap, cost, (char *) outPt); + } + glCrossingsAdded++; + +} + +/* + * ---------------------------------------------------------------------------- + * + * glMazePropNormal -- + * + * Process a normal top-of-heap point contained in a normal routing channel + * segment that is NOT the same one as the destination. + * + * Algorithm: + * Visit all the channel tiles around inPt->gl_tile. + * Each tile corresponds to a segment of a channel in which + * there are regions of maximum density. For each tile, pick + * the closest crossing point to inPt and add this point to the + * heap. + * + * Results: + * None. + * + * Side effects: + * May add points to the heap. + * + * ---------------------------------------------------------------------------- + */ + +#define NOTBLOCKEDH(tp) (NOTBLOCKED(tp) && TiGetType(tp) != CHAN_VRIVER) +#define NOTBLOCKEDV(tp) (NOTBLOCKED(tp) && TiGetType(tp) != CHAN_HRIVER) + +void +glMazePropNormal(inPt) + GlPoint *inPt; +{ + Tile *tile = inPt->gl_tile, *tp; + + /* TOP */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (NOTBLOCKEDV(tp)) + glMazeTile(inPt, tp, GEO_NORTH); + + /* LEFT */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (NOTBLOCKEDH(tp)) + glMazeTile(inPt, tp, GEO_WEST); + + /* BOTTOM */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (NOTBLOCKEDV(tp)) + glMazeTile(inPt, tp, GEO_SOUTH); + + /* RIGHT */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (NOTBLOCKEDH(tp)) + glMazeTile(inPt, tp, GEO_EAST); +} + +/* + * ---------------------------------------------------------------------------- + * + * glMazeTile -- + * + * Propagate from inPt to some tile 'tile' that borders it. The + * caller should make sure it's possible to propagate in that direction + * (it may not be if the channel covered by 'tile' is a river-routing + * channel and we're entering it from the wrong side). + * + * Special handling: it's possible that tile covers the same channel + * as inPt->gl_tile, in which case we just want to skip to the + * opposite side of tile and consider all the tiles that abut it, + * calling glMazeTile on each. + * + * Results: + * None. + * + * Side effects: + * May add points to the heap. + * + * ---------------------------------------------------------------------------- + */ + +void +glMazeTile(inPt, tile, dir) + GlPoint *inPt; /* Top of heap point being expanded */ + Tile *tile; /* Tile adjacent to inPt->gl_tile */ + int dir; /* Direction from inPt->gl_tile to tile */ +{ + GCRChannel *ch = (GCRChannel *) tile->ti_client; + TileType type = TiGetType(tile); + Tile *tp; + + ASSERT((int) ch != MINFINITY, "glMazeTile"); + + /* + * If this is a "real" channel boundary, pick a crossing point, + * add it to the heap, and return. + */ + if (inPt->gl_pin->gcr_ch != ch) + { + (void) glCrossEnum(inPt, tile, glMazeTileFunc, (ClientData) NULL); + return; + } + + /* + * This isn't a real channel boundary, but only the border between + * two tiles overlapping the same channel. Visit the neighbors of + * tile on the side opposite GeoOppositePos[dir] if tile is a river + * routing tile, or the neighbors of tile on all sides except for + * GeoOppositePos[dir] if tile is a normal tile. + */ + switch (type) + { + case CHAN_HRIVER: + if (dir == GEO_EAST) + { + /* RIGHT */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (NOTBLOCKEDH(tp)) + glMazeTile(inPt, tp, GEO_EAST); + } + else + { + /* LEFT */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (NOTBLOCKEDH(tp)) + glMazeTile(inPt, tp, GEO_WEST); + } + break; + case CHAN_VRIVER: + if (dir == GEO_NORTH) + { + /* TOP */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (NOTBLOCKEDV(tp)) + glMazeTile(inPt, tp, GEO_NORTH); + } + else + { + /* BOTTOM */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (NOTBLOCKEDV(tp)) + glMazeTile(inPt, tp, GEO_SOUTH); + } + break; + case CHAN_NORMAL: + if (dir != GEO_SOUTH) + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (NOTBLOCKEDV(tp)) + glMazeTile(inPt, tp, GEO_NORTH); + + if (dir != GEO_EAST) + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (NOTBLOCKEDH(tp)) + glMazeTile(inPt, tp, GEO_WEST); + + if (dir != GEO_NORTH) + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (NOTBLOCKEDV(tp)) + glMazeTile(inPt, tp, GEO_SOUTH); + + if (dir != GEO_WEST) + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (NOTBLOCKEDH(tp)) + glMazeTile(inPt, tp, GEO_EAST); + break; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * glMazeTileFunc -- + * + * Called by glCrossEnum() on behalf of glMazeTile() above. + * Add a new point to the heap for the path from 'inPt' to 'pin'. + * The cost of the new point is inPt->gl_cost plus the distance + * from inPt to pin. + * + * The caller should ensure on the call to glCrossEnum() that + * tp overlaps a different channel than inPt. + * + * Results: + * Always returns 1. + * + * Side effects: + * Adds a new point to the heap. + * + * ---------------------------------------------------------------------------- + */ + +int +glMazeTileFunc(inPt, tp, pin) + GlPoint *inPt; /* Top of heap point being expanded */ + Tile *tp; /* Tile adjacent to inPt->gl_tile */ + GCRPin *pin; /* Available pin on boundary of tp */ +{ + GlPoint *outPt; + int cost; + + /* Sanity check */ + ASSERT(pin->gcr_ch != inPt->gl_pin->gcr_ch, "glMazeTileFunc"); + + cost = inPt->gl_cost; + cost += ABSDIFF(inPt->gl_pin->gcr_point.p_x, pin->gcr_point.p_x); + cost += ABSDIFF(inPt->gl_pin->gcr_point.p_y, pin->gcr_point.p_y); + cost += glChanPenalty; + + /* Avoid looping or revisiting points unnecessarily */ + if (glMazeShortest) + { + if (cost >= pin->gcr_cost) + return 1; + pin->gcr_cost = cost; + if (pin->gcr_linked) + pin->gcr_linked->gcr_cost = cost; + } + else if (glMazeCheckLoop(inPt, tp)) + return 1; + + outPt = glPathNew(pin, cost, inPt); + outPt->gl_tile = tp; + + /* Add in estimate of distance to destination */ + cost += ABSDIFF(glMazeDestPoint.p_x, pin->gcr_point.p_x); + cost += ABSDIFF(glMazeDestPoint.p_y, pin->gcr_point.p_y); + + /* Put this point on the heap */ + HeapAddInt(&glMazeHeap, cost, (char *) outPt); + glCrossingsAdded++; + + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * glMazeCheckLoop -- + * + * Determine if a path loops, i.e., if it already contains the the tile 'tp'. + * + * Results: + * TRUE if the path loops, FALSE if not. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +glMazeCheckLoop(path, tp) + GlPoint *path; + Tile *tp; +{ + for ( ; path; path = path->gl_path) + if (path->gl_tile == tp) + return TRUE; + + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * glMazeResetCost -- + * + * Reset the costs stored with each GlPin after we've completed + * the global routing for a single net. + * + * Results: + * None. + * + * Side effects: + * Sets each pin's cost to INFINITY. + * + * ---------------------------------------------------------------------------- + */ + +void +glMazeResetCost(headPage, headFree) + GlPage *headPage; + int headFree; +{ + GlPage *gpage; + GCRPin *pin; + int n; + + for (gpage = headPage; gpage; gpage = gpage->glp_next) + { + for (n = headFree; n < gpage->glp_free; n++) + if (pin = gpage->glp_array[n].gl_pin) + { + pin->gcr_cost = INFINITY; + if (pin->gcr_linked) + pin->gcr_linked->gcr_cost = INFINITY; + } + if (gpage == glPathCurPage) + break; + headFree = 0; + } +} + +void +glPathPrint(path) + GlPoint *path; +{ + GlPoint *rp; + GCRPin *pin; + GCRChannel *ch; + Tile *tp; + + for (rp = path; rp; rp = rp->gl_path) + { + pin = rp->gl_pin; + ch = pin->gcr_ch; + tp = rp->gl_tile; + TxPrintf("(%d,%d) cost=%d pcost=%d pId=%d/%d\n", + pin->gcr_point.p_x, pin->gcr_point.p_y, + rp->gl_cost, pin->gcr_cost, + pin->gcr_pId, pin->gcr_pSeg); + TxPrintf("\tchan=(%d,%d,%d,%d)/%d\n", + ch->gcr_area.r_xbot, ch->gcr_area.r_ybot, + ch->gcr_area.r_xtop, ch->gcr_area.r_ytop, + ch->gcr_type); + TxPrintf("\ttile=(%d,%d,%d,%d)/%d\n", + LEFT(tp), BOTTOM(tp), RIGHT(tp), TOP(tp), TiGetType(tp)); + } +} diff --git a/grouter/grouteMult.c b/grouter/grouteMult.c new file mode 100644 index 00000000..587b106a --- /dev/null +++ b/grouter/grouteMult.c @@ -0,0 +1,308 @@ +/* + * grouteMulti.c + * + * Route a multi-terminal net. + * Currently includes just a single algorithm, for routing a net + * where arbitrary branching is allowed. This algorithm produces + * something like a steiner-tree, with intermediate points introduced + * at channel boundaries. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/grouter/grouteMult.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* lint */ + +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "router/router.h" +#include "gcr/gcr.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "utils/styles.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" + +/* Forward declarations */ + +void glMultiAddStart(); + + +/* + * ---------------------------------------------------------------------------- + * + * glMultiSteiner -- + * + * Perform global routing for all segments of a net. + * The caller supplies two procedures: one to produce a list of + * GlPoints from any of a set of possible starting points to the + * single destination, and the other to accept a list of GlPoints + * and remember it permanently, e.g, in the form of crossing assignments. + * + * The two procedures are of the following form: + * + * GlPoint * + * (*routeProc)(startList, loc, bestCost, cdRoute) + * GlPoint *startList; --- list of GlPoints that are possible + * --- starting points for the route; the + * --- points in the list are linked via gl_path + * --- fields as though they were a path. + * NLTermLoc *loc; --- loc->nloc_pin is the destination + * int bestCost; --- return NULL if we can't beat this cost + * ClientData cdRoute; --- same as cdRoute passed to us + * { + * } + * + * int + * (*markProc)(rootUse, path, pNetId, cdMark) + * CellUse *rootUse; --- leave feedback here if necessary and if + * --- rootUse is non-NULL + * GlPoint *path; --- path to be marked + * NetId *pNetId; --- netid_net is the argument 'net' to + * --- glMultiSteiner; netid_seg will be + * --- incremented for each new segment id + * --- assigned. + * ClientData cdMark; --- same as 'cdMark' passed to us + * { + * } + * + * + * Assumptions: + * The net has at least two terminals, each of which has at least + * one valid location. + * + * Algorithm: + * Multiterminal nets are routed using an algorithm that finds + * pseudo-Steiner tree routes. The idea is to process the + * terminals of the net in the order they appear in the netlist. + * Processing consists of finding the shortest path from the + * terminal being considered to all of the terminals processed + * before it, or to any of the crossing points used by the routes + * used to connect these previously-processed terminals. + * + * Results: + * Returns the number of terminals processed. + * + * Side effects: + * Whatever (*routeProc)() and (*markProc)() do. + * + * ---------------------------------------------------------------------------- + */ + +int +glMultiSteiner(rootUse, net, routeProc, markProc, cdRoute, cdMark) + CellUse *rootUse; /* If non-NULL, feedback for errors left here */ + NLNet *net; /* Net to process */ + GlPoint *(*routeProc)(); /* Procedure to route a segment */ + int (*markProc)(); /* Procedure to remember the route */ + ClientData cdRoute; /* Passed to (*routeProc)() */ + ClientData cdMark; /* Passed to (*markProc)() */ +{ + GlPoint *startList, *bestDest, *dest; + char mesg[128], *lastTermName; + int bestCost, nterms; + NLTermLoc *loc; + NLTerm *term; + Rect errorArea; + NetId netid; + + /* Skip to the first term that has a location */ + ASSERT(net != (NLNet *) NULL, "glMultiSteiner"); + for (term = net->nnet_terms; term; term = term->nterm_next) + if (term->nterm_locs) + break; + ASSERT(term != (NLTerm *) NULL, "glMultiSteiner"); + + /* + * For the first terminal in the net, mark the point where the terminal + * enters its adjacent channel. If there are several electrically + * equivalent terminals, then mark them all. + */ + nterms = 0; + startList = (GlPoint *) NULL; + lastTermName = term->nterm_name; + for (loc = term->nterm_locs; loc; loc = loc->nloc_next) + glListAdd(&startList, loc->nloc_pin, glMultiStemCost(loc)); + + /* Process all other terminals in net */ + netid.netid_net = net; + netid.netid_seg = 1; + for (term = term->nterm_next; term; term = term->nterm_next) + { + /* + * Skip if no valid locations exist for this terminal; + * the error has already been reported (either in the + * stem generator or the netlist reader). + */ + if (term->nterm_locs == (NLTermLoc *) NULL) + continue; + + /* + * Consider routing to each of the possible locations for + * this terminal, and use the best path. (The comparison of + * route cost includes the final channel in each path). + * After each call to rgRoutePath, 'dest' will be a GlPoint + * for one of the zero-cost points to 'loc' (or NULL if no + * path could be found). + */ + bestCost = INFINITY; + bestDest = (GlPoint *) NULL; + for (loc = term->nterm_locs; loc; loc = loc->nloc_next) + { + nterms++; + + /* Try to find a path from a zero-cost point to loc */ + dest = (*routeProc)(startList, loc, bestCost, cdRoute); + + /* Remember it if it was better than the previous best */ + if (dest && dest->gl_cost < bestCost) + { + if (bestDest) glPathFreePerm(bestDest); + bestDest = glPathCopyPerm(dest); + bestCost = dest->gl_cost; + } + + /* Free all temporary storage used for GlPoints */ + glPathFreeTemp(); + } + + /* + * If we were successful in finding a path, add the crossing points + * to the zero-cost list, mark all the crossings it used as allocated, + * and update the segment-id. + */ + if (bestDest) + { + glMultiAddStart(bestDest, &startList); + (*markProc)(rootUse, bestDest, &netid, cdMark); + glPathFreePerm(bestDest); + + /* + * Finally, move all of the locations for the terminal just + * processed to the zero-cost list, since any of them can + * be used as a new starting point. + */ + for (loc = term->nterm_locs; loc; loc = loc->nloc_next) + glListAdd(&startList, loc->nloc_pin, glMultiStemCost(loc)); + lastTermName = term->nterm_name; + } + else + { + GEO_EXPAND(&term->nterm_locs->nloc_rect, 1, &errorArea); + sprintf(mesg, "Can't find a path from \"%s\" to \"%s\"", + term->nterm_name, lastTermName); + if (rootUse) + DBWFeedbackAdd(&errorArea, mesg, rootUse->cu_def, + 1, STYLE_PALEHIGHLIGHTS); + else TxError("%s\n", mesg); + } + } + + /* Free the list of starting points */ + glPathFreePerm(startList); + return nterms; +} + +/* + * ---------------------------------------------------------------------------- + * + * glMultiStemCost -- + * + * Compute the initial cost of a terminal. This is the cost from the + * terminal loc->nloc_rect to its initial crossing point loc->nloc_stem. + * + * Results: + * Returns the Manhattan distance just described. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +glMultiStemCost(loc) + NLTermLoc *loc; +{ + int n1, n2, cost; + + n1 = ABSDIFF(loc->nloc_stem.p_x, loc->nloc_rect.r_xbot); + n2 = ABSDIFF(loc->nloc_stem.p_x, loc->nloc_rect.r_xtop); + cost = MIN(n1, n2); + n1 = ABSDIFF(loc->nloc_stem.p_y, loc->nloc_rect.r_ybot); + n2 = ABSDIFF(loc->nloc_stem.p_y, loc->nloc_rect.r_ytop); + cost += MIN(n1, n2); + + return cost; +} + +/* + * ---------------------------------------------------------------------------- + * + * glMultiAddStart -- + * + * Add all the pins along the GlPoint 'path' to the list of + * starting points '*pStartList'. For each crossing we add + * up to two pins: one on each side of the crossing. + * If a pin has already been marked as belonging to + * a net, we don't add it, since it was already added + * in an earlier iteration. + * + * Results: + * None. + * + * Side effects: + * Prepends the GlPoints on the list 'path' to the list of + * starting points *pStart. + * + * ---------------------------------------------------------------------------- + */ + +void +glMultiAddStart(path, pStartList) + GlPoint *path; /* Path linked via gl_path pointers */ + GlPoint **pStartList; /* List of starting points */ +{ + GlPoint *srcEntry, *dstEntry; + GCRPin *srcPin, *dstPin; + + /* + * Walk from path back along gl_path pointers down the list. + * At each step, process the segment between srcEntry and + * dstEntry in the channel srcEntry->gl_pin->gcr_ch. + */ + for (srcEntry = path->gl_path, dstEntry = path; + srcEntry; + dstEntry = srcEntry, srcEntry = srcEntry->gl_path) + { + /* Use srcPin's channel for both srcPin and dstPin */ + srcPin = srcEntry->gl_pin; + dstPin = dstEntry->gl_pin; + if (dstPin->gcr_ch != srcPin->gcr_ch) dstPin = dstPin->gcr_linked; + ASSERT(dstPin && dstPin->gcr_ch == srcPin->gcr_ch, "glMultiAddStart"); + + /* Add to list of starting points */ + if (srcPin->gcr_pId == NULL || srcPin->gcr_pSeg == GCR_STEMSEGID) + glListAdd(pStartList, srcPin, 0); + glListAdd(pStartList, dstPin, 0); + } +} diff --git a/grouter/grouteName.c b/grouter/grouteName.c new file mode 100644 index 00000000..13b8a417 --- /dev/null +++ b/grouter/grouteName.c @@ -0,0 +1,131 @@ +/* grouteName.c - + * + * Maintain a translation from net number to net name. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char sccsid[] = "@(#)grouteName.c 4.1 MAGIC (Berkeley) 7/4/85"; +#endif /* not lint */ + +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "debug/debug.h" +#include "utils/hash.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "utils/heap.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "utils/utils.h" + +char **glNameTable; +int glNameTableSize = 0, glNameTableUsed = 0; + +static bool glNameDidInit = FALSE; + +/* + * ---------------------------------------------------------------------------- + * + * glNetNameInit -- + * + * Allocate storage for a net id to net name translation table. + * Free any previously allocated table. + * + * Results: + * None. + * + * Side effects: + * Allocates and frees memory. Sets static variables. + * + * ---------------------------------------------------------------------------- + */ + +void +glNetNameInit(netList, numNets) + NLNetList *netList; + int numNets; +{ + NLNet *net; + int i; + + if (glNameDidInit) /* Free the old table */ + { + for (i = 0; i <= glNameTableSize; i++) + if (glNameTable[i]) + freeMagic(glNameTable[i]); + freeMagic((char *) glNameTable); + } + + if (netList == (NLNetList *) NULL) + { + glNameDidInit = FALSE; + return; + } + + glNameTable = (char **) mallocMagic((unsigned) (numNets+1) * sizeof (char *)); + glNameTableSize = numNets; + glNameTableUsed = 0; + glNameTable[0] = NULL; + glNameDidInit = TRUE; + + /* Create the table mapping back from net ids to net names */ + for (i = 0, net = netList->nnl_nets; net; net = net->nnet_next, i++) + { + ASSERT(i <= numNets, "glNetNameInit"); /* Sanity check */ + glNameTable[(int) net->nnet_cdata] = + StrDup((char **) NULL, net->nnet_terms->nterm_name); + if ((int) net->nnet_cdata > glNameTableUsed) + glNameTableUsed = (int) net->nnet_cdata; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * GlNetIdName -- + * + * Given a net id number, return the name of a terminal associated with + * the net. + * + * Results: + * Pointer to the name of the net. + * + * Side effects: + * If glNameDidInit is FALSE, the string we return is + * generated in a static area and is overwritten by + * the next call to GlNetIdName(). + * + * ---------------------------------------------------------------------------- + */ + +char * +GlNetIdName(id) + int id; +{ + static char tempId[100]; + + if (!glNameDidInit || glNameTableUsed < id) + { + (void) sprintf(tempId, "Net %d (with no name)", id); + return (tempId); + } + + return (glNameTable[id]); +} diff --git a/grouter/grouteNet.c b/grouter/grouteNet.c new file mode 100644 index 00000000..3c631dcf --- /dev/null +++ b/grouter/grouteNet.c @@ -0,0 +1,1794 @@ +/* + * grouteNet.c - + * + * Global signal router. Code to route one segment of a + * net, from a set of possible starting points to a single + * destination point. Uses a Lee-like wavefront maze router + * approach, with several performance heuristics to focus + * the search strongly toward the destination rather than + * propagating isotropically from the starting points. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char sccsid[] = "@(#)grouteNet.c 4.3 MAGIC (Berkeley) 12/6/85"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "utils/malloc.h" +#include "debug/debug.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "utils/styles.h" + +Point glDestPoint; /* Point we're routing to */ + +/* The following penalties get scaled by RtrGridSpacing */ +bool glPenaltiesScaled = FALSE; +int glJogPenalty = 5; +int glObsPenalty1 = 5, glObsPenalty2 = 3; +int glNbrPenalty1 = 2, glNbrPenalty2 = 5; +int glOrphanPenalty = 3; +int glChanPenalty = 1; + +/* Used in glNormalPropagate() */ +typedef struct +{ + int pr_tmin, pr_tmax; /* Range of top pin indices */ + int pr_bmin, pr_bmax; /* Range of bottom pin indices */ + int pr_lmin, pr_lmax; /* Range of left pin indices */ + int pr_rmin, pr_rmax; /* Range of right pin indices */ +} PinRanges; + +PinRanges glInitRange = +{ + INFINITY, MINFINITY, + INFINITY, MINFINITY, + INFINITY, MINFINITY, + INFINITY, MINFINITY +}; + +/* + * Auxiliary information used by the new maze routing algorithm. + * + * Whenever the maze router is ready to select the next frontier + * point to expand, it first moves some points to these two heaps: + * glProximityHeap, which is sorted by distance to the destination + * glDestPoint, and glBestHeap, which is sorted by the same cost + * as glHeap, namely total estimated cost: gl_length plus distance + * to glDestPoint. + * + * In addition, glBestCost is used to remember the total estimated + * cost of the best total estimated cost point in any of the heaps. + */ +Heap glProximityHeap; +Heap glBestHeap; +int glBestCost; +GlPoint *glBestPt; + +/* + * Points are transferred from glHeap to the two heaps above + * only when their cost is less than (fudgeNumer/fudgeDenom) + * times the best total cost of any point still in any of the + * heaps, i.e, (fudgeNumer * glBestCost) / fudgeDenom. + */ +int fudgeNumer = 13; +int fudgeDenom = 10; + +/* Marker to indicate an already-processed GlPoint */ +#define PROCESSED_MARK ((GlPoint *) 1) + +/* + * ---------------------------------------------------------------------------- + * + * glRouteToPoint -- + * + * Perform the global routing for the given pin. The heap starts off + * with one or more starting points. This routine finds the least + * cost path from any starting point to the destination point, + * where cost includes both distance and crossing penalties. + * + * Results: + * Pointer to the ending point in the global routing. Chasing parent + * pointers to the root yields the global routing result. Returns + * NULL if no path was found. + * + * Side effects: + * The search point heap (glHeap) changes. If a successful global + * routing was found, all points along the path are removed from + * the heap, leaving other partial path points still on the heap. + * If no routing was found, the heap is empty. + * + * ---------------------------------------------------------------------------- + */ + +GlPoint * +glRouteToPoint(loc, bestCost) + NLTermLoc *loc; /* Route from points on heap to this point */ + int bestCost; /* If we haven't found a path with less than + * this cost, return NULL. + */ +{ + int heapPts, frontierPts, startPts, headFree; + GCRChannel *inCh; + GlPoint *inPt; + bool newBest, newPaths; + HeapEntry hEntry; + GlPage *headPage; + GlPoint *lastPt; + + /* Initialize auxiliary heaps */ + HeapInit(&glBestHeap, 64, FALSE, FALSE); + HeapInit(&glProximityHeap, 64, FALSE, FALSE); + + glNumTries++; + if (glLogFile) + fprintf(glLogFile, "---\t%d\t0,0\t0\t0\n", glNumTries); + + /* Initialization */ + if (!glPenaltiesScaled) + glScalePenalties(); + + /* Remember for resetting GCRPins later */ + headPage = glCurPage; + headFree = glCurPage->glp_free; + + /* Remember for debugging */ + heapPts = glCrossingsExpanded; + frontierPts = glCrossingsConsidered; + startPts = glHeap.he_used; + + /* + * Passed to glPropagateFn() for use in estimating the remaining + * distance to the destination point. Invert sense of loc->nloc_dir + * (the direction of loc->nloc_ch relative to the cell) to give the + * side of the channel on which loc->nloc_stem lies. + */ + glDestPoint = loc->nloc_stem; + ASSERT(GEO_SAMEPOINT(loc->nloc_pin->gcr_point, loc->nloc_stem), + "glRouteToPoint"); + + /* + * The modified shortest path algorithm extends the partial path for + * which the sum of the current path cost plus the Manhattan distance + * to the destination point is the smallest. + */ + glBestCost = 0; + glBestPt = (GlPoint *) NULL; + newPaths = newBest = TRUE; + lastPt = (GlPoint *) NULL; + while (!SigInterruptPending && glPopFromHeap(&newBest, newPaths, &hEntry)) + { + newPaths = FALSE; + glCrossingsExpanded++; + inPt = (GlPoint *) hEntry.he_id; + + /* Done if we reach the destination crossing point */ + if (GEO_SAMEPOINT(inPt->gl_point, glDestPoint)) + { + lastPt = inPt; + break; + } + + /* Done if the best path is already more expensive than best cost */ + if (inPt->gl_length >= bestCost && !DebugIsSet(glDebugID,glDebNewHeaps)) + break; + + /* Reject if its pin has already been visited more cheaply */ + if (inPt->gl_length > inPt->gl_pin->gcr_cost) + { + glCrossingsObsolete++; + continue; + } + + if (glLogFile) + glLogPath(inPt, hEntry.he_int); + + /* + * There are three possibilities: + * - inPt is in the destination channel, or + * - it is in a river-routing channel, or + * - it is in a normal channel. + * In the latter case, we use a trick to avoid having to process + * all the crossings in the channel at once. + */ + inCh = inPt->gl_ch; + if (inCh != loc->nloc_chan || !glFinalPropagate(inPt, loc)) + { + if (inCh->gcr_type != CHAN_NORMAL) + (void) glRiverPropagate(inPt); + else + glNormalPropagate(inPt, inCh, hEntry.he_int); + } + + /* Remember that points may have been added to glHeap */ + newPaths = TRUE; + } + + /* Reset the cost stored with each GCRPin */ + glResetCost(headPage, headFree); + + /* Record number of points processed if debugging */ + if (DebugIsSet(glDebugID, glDebHisto)) + glHistoAdd(heapPts, frontierPts, startPts); + + /* Free the auxiliary heaps */ + HeapKill(&glBestHeap, (void (*)()) NULL); + HeapKill(&glProximityHeap, (void (*)()) NULL); + + return (lastPt); +} + +/* + * ---------------------------------------------------------------------------- + * + * glScalePenalties -- + * + * Scale the penalties used in the global router cost function so they + * reflect the actual grid size used during routing. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +glScalePenalties() +{ + glJogPenalty *= RtrGridSpacing; + glObsPenalty1 *= RtrGridSpacing; + glObsPenalty2 *= RtrGridSpacing; + glNbrPenalty1 *= RtrGridSpacing; + glNbrPenalty2 *= RtrGridSpacing; + glOrphanPenalty *= RtrGridSpacing; + glChanPenalty *= RtrGridSpacing; + glPenaltiesScaled = TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPopFromHeap -- + * + * Obtain the next frontier point for consideration from the + * heap glHeap. The variable newPaths should be TRUE if + * points were added to glHeap since the last call to this + * procedure. + * + * Algorithm: + * We maintain three heaps. + * The first, glHeap, is the one to which points are added, + * and is referred to as the Reserve heap. + * + * The two remaining heaps are auxiliary: glProximityHeap is sorted + * in order of increasing distance to the goal, and glBestHeap is + * sorted using the same key as glHeap (cost so far plus an estimate + * of the cost remaining to the destination). + * + * The idea is to remove all points from glHeap that are + * within a certain percentage (fudgeNumer/fudgeDenom) of + * the best estimated cost so far (glBestCost), and add these + * to glProximityHeap. The actual points we return are then + * selected from glProximityHeap, which causes points closest + * to the destination to be preferred over points farther away. + * + * Results: + * Returns TRUE if a new entry was stored in hEntry, or + * FALSE if no more points were available. + * + * Side effects: + * May pop points from glHeap and store points in or pop + * points from glBestHeap or glProximityHeap. May change + * *pNewBest (it should be initially TRUE on the very first + * call to glPopFromHeap). Also, may modify glBestCost + * (which should be zero on the first call). Stores the + * entry popped from the top of glProximityHeap in the + * HeapEntry pointed to by hEntry. + * + * ---------------------------------------------------------------------------- + */ + +bool +glPopFromHeap(pNewBest, newPaths, hEntry) + bool *pNewBest; /* Should be TRUE on initial call; afterwards, + * we set it to TRUE when glBestCost is updated. + */ + bool newPaths; /* TRUE if points added to glHeap since the last + * call to glPopFromHeap(). + */ + HeapEntry *hEntry; /* See above */ +{ + HeapEntry *bestCostTop, *glHeapTop; + int minAcceptableCost, newBestCost; + GlPoint *topPt; + + if (!DebugIsSet(glDebugID, glDebNewHeaps)) + return (HeapRemoveTop(&glHeap, hEntry) != NULL); + + /* + * If the top element on glBestHeap changed (this occurs + * when it is popped from glProximityHeap in the previous + * call), we have to move more points from glHeap to + * glProximityHeap. + */ + if (*pNewBest) + { + /* + * Pop bestcost heap until path that hasn't already been + * processed is reached. (Already processed paths are marked + * by setting their gl_next field to PROCESSED_MARK). This + * point will be the one with the best possible cost plus + * estimate to the destination, and will be used to compute + * the minimum acceptable cost for transfer to glProximityHeap. + */ + while ((bestCostTop = HeapLookAtTop(&glBestHeap)) + && ((GlPoint *) bestCostTop->he_id)->gl_next == PROCESSED_MARK) + { + if (DebugIsSet(glDebugID, glDebHeap)) + { + TxPrintf("Discarding point (cost=%d): ", bestCostTop->he_int); + glPrintPoint((GlPoint *) bestCostTop->he_id); + TxPrintf("\n"); + } + HeapRemoveTop(&glBestHeap, hEntry); + } + + /* + * The "new" best cost is min of cost of top of the best-cost + * heap and the reserve heap. If both heaps are empty, we've + * failed and should return FALSE. + */ + if (glHeapTop = HeapLookAtTop(&glHeap)) + { + if (bestCostTop == NULL || glHeapTop->he_int < bestCostTop->he_int) + { + if (DebugIsSet(glDebugID, glDebHeap)) + TxPrintf("Best cost really comes from glHeap\n"); + bestCostTop = glHeapTop; + } + } + else if (bestCostTop == NULL) + return FALSE; + + newBestCost = bestCostTop->he_int; + glBestPt = (GlPoint *) bestCostTop->he_id; + if (newBestCost == glBestCost) + *pNewBest = FALSE; + glBestCost = newBestCost; + + if (DebugIsSet(glDebugID, glDebHeap)) + { + TxPrintf("New best (cost=%d): ", newBestCost); + glPrintPoint(glBestPt); + TxPrintf("\nCost %s\n", *pNewBest ? "changed" : "didn't change"); + } + } + + /* + * Move acceptably cheap paths from reserve to best heaps. + * This has to happen if either the cutoff point changed in + * the code above (*pNewBest == TRUE), or if points had been + * added to glHeap since the last time we were called + * (newPaths == TRUE). + */ + if (*pNewBest || newPaths) + { + /* + * The minimum acceptable cost for transfer from the + * Reserve heap (glHeap) to the proximity and best heaps + * will be glBestCost * (fudgeNumer / fudgeDenom). + */ + minAcceptableCost = (glBestCost * fudgeNumer) / fudgeDenom; + if (DebugIsSet(glDebugID, glDebHeap)) + TxPrintf("Min acceptable cost = %d\n", minAcceptableCost); + + while ((glHeapTop = HeapRemoveTop(&glHeap, hEntry)) + && glHeapTop->he_int <= minAcceptableCost) + { + Point *p = &(((GlPoint *)(glHeapTop->he_id))->gl_point); + int dist = ABSDIFF(p->p_x, glDestPoint.p_x) + + ABSDIFF(p->p_y, glDestPoint.p_y); + + if (DebugIsSet(glDebugID, glDebHeap)) + { + TxPrintf("Move to prox (pcost=%d,cost=%d): ", + dist, glHeapTop->he_int); + glPrintPoint((GlPoint *) glHeapTop->he_id); + TxPrintf("\n"); + } + HeapAddInt(&glBestHeap, glHeapTop->he_int, glHeapTop->he_id); + HeapAddInt(&glProximityHeap, dist, glHeapTop->he_id); + } + + if (glHeapTop) + HeapAddInt(&glHeap, glHeapTop->he_int, glHeapTop->he_id); + } + + /* + * The next point to be processed is the one at the top of + * the proximity heap, i.e., the one closest to the destination. + * If we popped the current best, set newBest flag, so we know + * to compute a new "best cost" the next time we're called. + * Mark the point as "processed", so it will be discarded if + * it ever comes to the top of glBestHeap above. + */ + if (HeapRemoveTop(&glProximityHeap, hEntry) == NULL) + return FALSE; + + topPt = (GlPoint *) hEntry->he_id; + *pNewBest = (topPt == glBestPt); + topPt->gl_next = PROCESSED_MARK; + + /* + * Fix up the cost field of hEntry (remember, it was popped + * from the proximity heap, which is keyed only on the estimated + * distance remaining, while we want the cost plus the estimate + * to the destination). + */ + hEntry->he_int = topPt->gl_length + + ABSDIFF(topPt->gl_point.p_x, glDestPoint.p_x) + + ABSDIFF(topPt->gl_point.p_y, glDestPoint.p_y); + + if (DebugIsSet(glDebugID, glDebHeap)) + { + TxPrintf("Returning point (%s, cost=%d): ", + *pNewBest ? "best" : "not best", hEntry->he_int); + glPrintPoint(topPt); + TxPrintf("\n"); + } + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * glFinalPropagate -- + * + * Process a point that lies in the destination channel. + * These points are treated specially since we don't need + * to find any more crossings to other channels. + * + * Note that we do perform a density computation here, so + * we should avoid attempts to route through a portion of + * a channel where its capacity has been exceeded. + * + * Results: + * FALSE if the path to the destination was blocked because + * it was unreachable; TRUE otherwise. + * + * Side effects: + * May add a point to the heap. + * + * ---------------------------------------------------------------------------- + */ + +bool +glFinalPropagate(inPt, loc) + GlPoint *inPt; /* Point being processed */ + NLTermLoc *loc; /* Destination point */ +{ + GCRChannel *destCh = loc->nloc_chan; + GCRPin *destPin = loc->nloc_pin; + Point *destPoint = &loc->nloc_stem; + GlPoint *outPt; + int cost; + + cost = inPt->gl_length; + cost += ABSDIFF(inPt->gl_point.p_x, destPoint->p_x); + cost += ABSDIFF(inPt->gl_point.p_y, destPoint->p_y); + + /* Disallow the path if it exceeds the channel density */ + if (destCh->gcr_dMaxByRow >= destCh->gcr_length + || destCh->gcr_dMaxByCol >= destCh->gcr_width) + { + if (glDensityExceeded(destCh, inPt->gl_pin, destPin)) + return (FALSE); + } + +#ifdef notdef /* Don't make it too difficult in the final channel */ + if (DebugIsSet(glDebugID, glDebStraight)) + { + /* If the net runs across the channel, it must not jog */ + if (!glJogsAcrossChannel(inPt->gl_pin, destPin)) + return (FALSE); + } +#endif /* notdef */ + + cost = glCrossPenalty(cost, destCh, (GCRChannel *) NULL, + inPt->gl_pin, destPin); + if (cost >= destPin->gcr_cost) + return (TRUE); + + glCrossingsComplete++; + outPt = glNewPoint(destPoint, destCh, destPin, cost, inPt); + HeapAddInt(&glHeap, cost, (char *) outPt); + if (glLogFile) + { + fprintf(glLogFile, "FIN\t%d\t%d,%d\t%d\n", + glNumTries, + outPt->gl_point.p_x, outPt->gl_point.p_y, + outPt->gl_length); + } + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * glRiverPropagate -- + * + * Process a point belonging to a river-routing channel. Since these + * channels can only be used for routing straight across to their + * other side, we only need to consider a single crossing point. + * + * Results: + * Returns the cost with which the point was added to the heap, + * or -1 if the point wasn't added. + * + * Side effects: + * May add a point to the heap. + * + * ---------------------------------------------------------------------------- + */ + +int +glRiverPropagate(inPt) + GlPoint *inPt; +{ + GCRPin *inPin = inPt->gl_pin, *outPin, *linkedPin; + GCRChannel *inCh = inPt->gl_ch; + int cost; + GlPoint *outPt; + + /* Find the opposing pin */ + switch (inPin->gcr_side) + { + case GEO_NORTH: outPin = &inCh->gcr_bPins[inPin->gcr_x]; break; + case GEO_SOUTH: outPin = &inCh->gcr_tPins[inPin->gcr_x]; break; + case GEO_EAST: outPin = &inCh->gcr_lPins[inPin->gcr_y]; break; + case GEO_WEST: outPin = &inCh->gcr_rPins[inPin->gcr_y]; break; + } + + /* Propagate to this pin if it is free */ + if ((linkedPin = outPin->gcr_linked) + && linkedPin->gcr_pId == (GCRNet *) NULL) + { + /* Only add to heap if this path is cheapest so far */ + cost = inPt->gl_length + + ABSDIFF(inPt->gl_point.p_x, linkedPin->gcr_point.p_x) + + ABSDIFF(inPt->gl_point.p_y, linkedPin->gcr_point.p_y); + if (cost < linkedPin->gcr_cost) + { + linkedPin->gcr_cost = outPin->gcr_cost = cost; + outPt = glNewPoint(&outPin->gcr_point, linkedPin->gcr_ch, linkedPin, + cost, inPt); + cost += ABSDIFF(glDestPoint.p_x, linkedPin->gcr_point.p_x) + + ABSDIFF(glDestPoint.p_y, linkedPin->gcr_point.p_y); + HeapAddInt(&glHeap, cost, (char *) outPt); + if (glLogFile) + { + fprintf(glLogFile, "RIV\t%d\t%d,%d\t%d\t%d\n", + glNumTries, + outPt->gl_point.p_x, outPt->gl_point.p_y, + outPt->gl_length, cost); + } + return (cost); + } + } + + return (-1); +} + +/* + * ---------------------------------------------------------------------------- + * + * glNormalPropagate -- + * + * Process a point (inPt) that lies in a normal routing channel (inCh) + * that is not the destination channel. Use a trick to minimize the + * number of crossing points in inCh that must be processed, speeding + * up global routing by a factor of 3 - 5, particularly in the case + * of large channels with lots of crossing points per channel. + * + * Motivation: + * Most channels contain lots of pins. Usually, most of them + * aren't even close to being on the least-cost path, as in + * the case below: + * + * D + * + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * | | + * + + + * | C | + * + + + * | | + * +---+---+---+---+---+---+---S---+---+---+---+---+---+---+ + * + * (Here, "S" is a point on the boundary of channel "C", and "D" + * is the destination point, which happens to lie in the adjacent + * channel. "D" is a very short distance from "S" compared with + * the width of the channel). + * + * It's usually a waste of time to process the points of "C" that + * aren't on the direct path to the destination. However, we + * can't just throw them away, because it may turn out that the + * direct path is blocked, and we need to use one of the points + * to the side, e.g: + * + * D + * BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * | | + * + + + * | C | + * + + + * | | + * +---+---+---+---+---+---+---S---+---+---+---+---+---+---+ + * + * (Here "B" is a blockage in the channel containing "D", forcing + * points to the side of the channel to be used.) + * + * Algorithm: + * The trick is to ensure that the points to the side are added + * to the heap before they are needed, but not necessarily all + * at once. + * + * We compute a rectangle around the starting point "S" that + * will contain the crossing points most likely to be of interest. + * This rectangle "R" is a bloated version of the bounding rectangle + * containing "S" and the destination point, clipped against the + * reachable portion of the channel (reachable in the sense of + * passing through no regions of maximum density): + * + * ................D.... + * : : + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * | : : | + * + : R : + + * | : : | + * + : : + + * | : : | + * +---+---+---+---+---+---+---S---+---+---+---+---+---+---+ + * + * Only crossings inside of "R" are added to the heap. However, + * we put the point "S" BACK on the heap, remembering the area + * "R" already processed. The trick is the cost with which "S" + * is added to the heap: sufficiently high so that points on the + * direct path to the destination are processed before "S" is + * reprocessed, but sufficiently low so that "S" is processed + * BEFORE the points outside of "R" would have been removed + * from the heap, had they been added at the same time "S" + * was originally processed. + * + * When a point is removed from the heap, then, it may either + * be "virgin", or it may have been partially expanded. The + * state of its expansion is described in inPt->gl_visited, + * which gives grid coordinates of a rectangle (including its + * top and right coordinates) covering all pins visited so far. + * + * We determine a new set of pins to visit (based on heapCost, + * as described in the comments for glSetPinClip()), visit them, + * and then if all feasible points haven't yet been reached, we + * add a new point to the heap with a new gl_visited showing the + * points we processed on this iteration. The cost for this new + * heap point is chosen to be less than the cost of any of the + * remaining points, so we have a chance to process them and put + * them on the heap before they are needed. + * + * Results: + * None. + * + * Side effects: + * May add many points to the heap. + * + * ---------------------------------------------------------------------------- + */ + +void +glNormalPropagate(inPt, inCh, heapCost) + GlPoint *inPt; /* Point on the boundary of inCh */ + GCRChannel *inCh; /* Channel through which we're passing */ + int heapCost; /* Cost with which inPt was added to heap */ +{ + PinRanges pinRange, prevRange; + int x, y, baseCost, min, max; + GCRPin *inPin = inPt->gl_pin; + Rect pinRect, densRect; + GCRPin *outPin; + int i, cost; + bool noCheckJogs; + + /* + * Starting at inPt, figure out how high, low, left, and right + * we can go based on density limits. If we're completely + * hemmed in and can't go anywhere, mark the pin as now being + * blocked and return. + */ + if (!glSetDensityClip(inPt, inCh, &densRect)) + { +#ifdef notdef + inPin->gcr_pId = GCR_BLOCKEDNETID; + if (inPin->gcr_linked) + inPin->gcr_linked->gcr_pId = GCR_BLOCKEDNETID; +#endif /* notdef */ + return; + } + + /* + * Next, figure out the range of pins we're interested in + * visiting on this pass. This range will generally cover + * less than the entire channel, and will depend on the + * relative positions of inPt and glDestPoint. The range + * is clipped against densRect. + */ + glSetPinClip(inPt, inCh, heapCost, &densRect, &pinRect); + glRectToRange(inCh, &pinRect, &pinRange); + + /* + * We've already visited the pins identified in pinRect. + * Visit all the pins that lie in pinClip but not in pinRect. + * At the end, if pinRect is not equal to densRect, create + * a new GlPoint like inPt but with gl_range equal to pinRect, + * and add this point back to the heap with a carefully-chosen + * new cost (see below). + */ + glRectToRange(inCh, &inPt->gl_range, &prevRange); + baseCost = inPt->gl_length + glChanPenalty; + x = inPt->gl_point.p_x; + y = inPt->gl_point.p_y; + +#define OKPIN(p) \ + ((p)->gcr_pId == NULL \ + && (p)->gcr_linked && (p)->gcr_linked->gcr_pId == NULL) +#define XCOST(x, pin) ABSDIFF((x), (pin)->gcr_point.p_x) +#define YCOST(y, pin) ABSDIFF((y), (pin)->gcr_point.p_y) + + /* Top */ + min = pinRange.pr_tmin, max = pinRange.pr_tmax; + if (inCh->gcr_tPins->gcr_pNext && min <= max) + { + cost = baseCost + inCh->gcr_area.r_ytop - y; + noCheckJogs = TRUE; + if (inPin->gcr_side != GEO_SOUTH) cost += glJogPenalty; + else if (DebugIsSet(glDebugID, glDebStraight)) noCheckJogs = FALSE; + for (i = min, outPin = &inCh->gcr_tPins[i]; i <= max; i++, outPin++) + { + if (i == prevRange.pr_tmin) + { + i = prevRange.pr_tmax; + outPin += prevRange.pr_tmax - prevRange.pr_tmin; + continue; + } + if (OKPIN(outPin) && cost + XCOST(x, outPin) < outPin->gcr_cost) + if (noCheckJogs || !glJogsAcrossChannel(inPin, outPin)) + (void) glPropagateFn(outPin->gcr_linked->gcr_ch, + outPin, inPt); + } + } + + /* Bottom */ + min = pinRange.pr_bmin, max = pinRange.pr_bmax; + if (inCh->gcr_bPins->gcr_pNext && min <= max) + { + cost = baseCost + y - inCh->gcr_area.r_ybot; + noCheckJogs = TRUE; + if (inPin->gcr_side != GEO_NORTH) cost += glJogPenalty; + else if (DebugIsSet(glDebugID, glDebStraight)) noCheckJogs = FALSE; + for (i = min, outPin = &inCh->gcr_bPins[i]; i <= max; i++, outPin++) + { + if (i == prevRange.pr_bmin) + { + i = prevRange.pr_bmax; + outPin += prevRange.pr_bmax - prevRange.pr_bmin; + continue; + } + if (OKPIN(outPin) && cost + XCOST(x, outPin) < outPin->gcr_cost) + if (noCheckJogs || !glJogsAcrossChannel(inPin, outPin)) + (void) glPropagateFn(outPin->gcr_linked->gcr_ch, + outPin, inPt); + } + } + + /* Left */ + min = pinRange.pr_lmin, max = pinRange.pr_lmax; + if (inCh->gcr_lPins->gcr_pNext && min <= max) + { + cost = baseCost + x - inCh->gcr_area.r_xbot; + noCheckJogs = TRUE; + if (inPin->gcr_side != GEO_EAST) cost += glJogPenalty; + else if (DebugIsSet(glDebugID, glDebStraight)) noCheckJogs = FALSE; + for (i = min, outPin = &inCh->gcr_lPins[i]; i <= max; i++, outPin++) + { + if (i == prevRange.pr_lmin) + { + i = prevRange.pr_lmax; + outPin += prevRange.pr_lmax - prevRange.pr_lmin; + continue; + } + if (OKPIN(outPin) && cost + YCOST(y, outPin) < outPin->gcr_cost) + if (noCheckJogs || !glJogsAcrossChannel(inPin, outPin)) + (void) glPropagateFn(outPin->gcr_linked->gcr_ch, + outPin, inPt); + } + } + + /* Right */ + min = pinRange.pr_rmin, max = pinRange.pr_rmax; + if (inCh->gcr_rPins->gcr_pNext && min <= max) + { + cost = baseCost + inCh->gcr_area.r_xtop - x; + noCheckJogs = TRUE; + if (inPin->gcr_side != GEO_WEST) cost += glJogPenalty; + else if (DebugIsSet(glDebugID, glDebStraight)) noCheckJogs = FALSE; + for (i = min, outPin = &inCh->gcr_rPins[i]; i <= max; i++, outPin++) + { + if (i == prevRange.pr_rmin) + { + i = prevRange.pr_rmax; + outPin += prevRange.pr_rmax - prevRange.pr_rmin; + continue; + } + if (OKPIN(outPin) && cost + YCOST(y, outPin) < outPin->gcr_cost) + if (noCheckJogs || !glJogsAcrossChannel(inPin, outPin)) + (void) glPropagateFn(outPin->gcr_linked->gcr_ch, + outPin, inPt); + } + } + + /* + * If we haven't visited all the points in this channel that + * are reachable because of density, create a copy of inPt and + * add it to the heap, marking its gl_range as the Rect equivalent + * of pinRange. The cost we use in adding this copy to the heap + * is chosen to ensure that we get a chance to add the least cost + * of the remaining points to the heap before anything else of that + * cost gets removed from the heap. + */ + cost = glMinRemainingCost(inPt, inCh, &pinRect, &densRect); + if (cost < INFINITY) + { + inPt = glNewPoint(&inPt->gl_point, inCh, inPin, inPt->gl_length, + inPt->gl_parent); + inPt->gl_range = pinRect; + HeapAddInt(&glHeap, cost - 1, (char *) inPt); + glCrossingsPartial++; + } + else glCrossingsComplete++; +} + +/* + * ---------------------------------------------------------------------------- + * + * glMinRemainingCost -- + * + * Choose the cost with which glNormalPropagate will add a point to the + * heap. This cost is INFINITY if all the points inside of dRect have + * been processed (*pRect == *dRect); otherwise, it is the cost of a + * route from inPt to the closest pin in the set contained in *dRect + * but not in *pRect, plus an estimate of the cost from this pin to + * the destination point, plus the cost of inPt. + * + * Results: + * Returns the cost above. + * + * Side effects: + * May add many points to the heap. + * + * ---------------------------------------------------------------------------- + */ + + +int +glMinRemainingCost(inPt, inCh, pRect, dRect) + GlPoint *inPt; + GCRChannel *inCh; + Rect *pRect, *dRect; +{ + int cost, n; + GCRPin *pins; + + /* + * In the code below, 'cost' represents the sum of the cost + * from inPt to a point in densRect but not in pinRect, plus + * the estimated cost from that point to the destination. + */ + cost = INFINITY; + + /* + * Pins on top and bottom. + * Figure out which x-coordinate on the top or bottom will + * give minimum cost to the destination. + */ + n = (glDestPoint.p_x - inCh->gcr_origin.p_x) / RtrGridSpacing; + n = INRANGE(n, pRect->r_xbot - 1, pRect->r_xtop + 1); + n = INRANGE(n, dRect->r_xbot, dRect->r_xtop); + + /* Top pins */ + if (dRect->r_ytop == inCh->gcr_width + 1) + { + pins = inCh->gcr_tPins; + if (pRect->r_ytop < dRect->r_ytop) + { + /* Haven't reached top yet */ + cost = glPinCost(inPt, &pins[n], cost); + } + else + { + /* Have processed part of the top already */ + if (pRect->r_xbot > dRect->r_xbot) + cost = glPinCost(inPt, &pins[pRect->r_xbot - 1], cost); + if (pRect->r_xtop < dRect->r_xtop) + cost = glPinCost(inPt, &pins[pRect->r_xtop + 1], cost); + } + } + + /* Bottom pins */ + if (dRect->r_ybot == 0) + { + pins = inCh->gcr_bPins; + if (pRect->r_ybot > dRect->r_ybot) + { + /* Haven't reached bottom yet */ + cost = glPinCost(inPt, &pins[n], cost); + } + else + { + /* Have processed part of the bottom already */ + if (pRect->r_xbot > dRect->r_xbot) + cost = glPinCost(inPt, &pins[pRect->r_xbot - 1], cost); + if (pRect->r_xtop < dRect->r_xtop) + cost = glPinCost(inPt, &pins[pRect->r_xtop + 1], cost); + } + } + + /* Pins on right and left */ + n = (glDestPoint.p_y - inCh->gcr_origin.p_y) / RtrGridSpacing; + n = INRANGE(n, pRect->r_ybot - 1, pRect->r_ytop + 1); + n = INRANGE(n, dRect->r_ybot, dRect->r_ytop); + + /* Right pins */ + if (dRect->r_xtop == inCh->gcr_length + 1) + { + pins = inCh->gcr_rPins; + if (pRect->r_xtop < dRect->r_xtop) + { + /* Haven't reached RHS yet */ + cost = glPinCost(inPt, &pins[n], cost); + } + else + { + /* Have processed part of the RHS already */ + if (pRect->r_ybot > dRect->r_ybot) + cost = glPinCost(inPt, &pins[pRect->r_ybot - 1], cost); + if (pRect->r_ytop < dRect->r_ytop) + cost = glPinCost(inPt, &pins[pRect->r_ytop + 1], cost); + } + } + + /* Left pins */ + if (dRect->r_xbot == 0) + { + pins = inCh->gcr_lPins; + if (pRect->r_xbot > dRect->r_xbot) + { + /* Haven't reached LHS yet */ + cost = glPinCost(inPt, &pins[n], cost); + } + else + { + /* Have processed part of the LHS already */ + if (pRect->r_ybot > dRect->r_ybot) + cost = glPinCost(inPt, &pins[pRect->r_ybot - 1], cost); + if (pRect->r_ytop < dRect->r_ytop) + cost = glPinCost(inPt, &pins[pRect->r_ytop + 1], cost); + } + } + + + if (cost == INFINITY) + return (cost); + + return (cost + inPt->gl_length); +} + +/* + * glPinCost -- + * + * Used by above to give the distance from inPt->gl_point to pin->gcr_point, + * plus the distance from pin->gcr_point to the destination, plus any + * penalties that are guaranteed to apply (the channel penalty and + * possibly a jog penalty are all we consider now). + * + * Results: + * Returns the minimum of the above cost and 'oldCost'. + * + * Side effects: + * None. + */ + + +int +glPinCost(inPt, pin, oldCost) + GlPoint *inPt; + GCRPin *pin; + int oldCost; +{ + int cost; + + /* Length from inPt to pin */ + cost = ABSDIFF(inPt->gl_point.p_x, pin->gcr_point.p_x) + + ABSDIFF(inPt->gl_point.p_y, pin->gcr_point.p_y); + + /* Estimate of length from pin to destination */ + cost += ABSDIFF(glDestPoint.p_x, pin->gcr_point.p_x) + + ABSDIFF(glDestPoint.p_y, pin->gcr_point.p_y); + + /* Penalties */ + cost += glChanPenalty; + if (inPt->gl_point.p_x != pin->gcr_point.p_x + && inPt->gl_point.p_y != pin->gcr_point.p_y) + cost += glJogPenalty; + + return (MIN(cost, oldCost)); +} + +/* + * ---------------------------------------------------------------------------- + * + * glSetDensityClip -- + * + * Determine which pins in inCh are reachable from inPt->gl_pin, + * given density restrictions. Leaves *dRect set to the Rect + * (in grid coordinates for 'ch') describing visitable pins + * on each side. If a whole side of pins is not reachable + * (e.g, the top), then that coordinate of *dRect (e.g, r_ytop) + * won't reach all the way to the corresponding extreme value + * for the pin indices for 'ch' (e.g, ch->gcr_width+1). + * + * Results: + * Returns the cost above. + * + * Side effects: + * May add many points to the heap. + * + * ---------------------------------------------------------------------------- + */ + +bool +glSetDensityClip(inPt, ch, dRect) + GlPoint *inPt; + GCRChannel *ch; + Rect *dRect; +{ + GCRPin *inPin = inPt->gl_pin; + short *den, maxdensity; + int n; + + /* + * Default: in the absence of density violations, we can + * visit all the pins on each side of the channel. + */ + dRect->r_xbot = dRect->r_ybot = 0; + dRect->r_xtop = ch->gcr_length + 1; + dRect->r_ytop = ch->gcr_width + 1; + + if (ch->gcr_dMaxByRow >= ch->gcr_length) + { + den = ch->gcr_dColsByRow; + maxdensity = ch->gcr_length; + glVDensityChecks++; + + /* Walk up */ + for (n = MAX(inPin->gcr_y, 1); n <= ch->gcr_width; n++) + { + if (den[n] >= maxdensity) + { + /* Can't reach top */ + glVDensityFailures++; + dRect->r_ytop = n-1; + break; + } + } + + /* Walk down */ + for (n = MIN(inPin->gcr_y, ch->gcr_width); n >= 1; n--) + if (den[n] >= maxdensity) + { + /* Can't reach bottom */ + glVDensityFailures++; + dRect->r_ybot = n+1; + break; + } + } + + if (ch->gcr_dMaxByCol >= ch->gcr_width) + { + den = ch->gcr_dRowsByCol; + maxdensity = ch->gcr_width; + glHDensityChecks++; + + /* Walk right */ + for (n = MAX(inPin->gcr_x, 1); n <= ch->gcr_length; n++) + if (den[n] >= maxdensity) + { + /* Can't reach right hand side */ + glHDensityFailures++; + dRect->r_xtop = n-1; + break; + } + + /* Walk left */ + for (n = MIN(inPin->gcr_x, ch->gcr_length); n >= 1; n--) + if (den[n] >= maxdensity) + { + /* Can't reach left hand side */ + glHDensityFailures++; + dRect->r_xbot = n+1; + break; + } + } + + if (dRect->r_xtop < dRect->r_xbot) dRect->r_ytop = dRect->r_ybot - 1; + else if (dRect->r_ytop < dRect->r_ybot) dRect->r_xtop = dRect->r_xbot - 1; + + return (dRect->r_xtop >= dRect->r_xbot && dRect->r_ytop >= dRect->r_ybot); +} + +/* + * ---------------------------------------------------------------------------- + * + * glSetPinClip -- + * + * Figure out the range of pins we're interested in visiting on this pass. + * The Rect for these pins will generally cover less than the entire channel, + * and will depend on the relative positions of inPt and glDestPoint. The + * Rect is clipped against dRect. + * + * Algorithm: + * Construct an imaginary rectangle ('R') with inPt at one corner and + * glDestPoint at the other. Bloat R on all sides by the amount + * described below and then determine all pins that lie both within + * this rectangle and dRange. + * + * The amount that R is bloated depends on heapCost, which is the + * value currently at the top of the heap. The simple case is when + * heapCost is just inPt->gl_length plus the Manhattan distance from + * inPt to glDestPoint (which we'll call estCost). This case should + * correspond to the first time inPt is processed. If we weren't to + * bloat R at all, all pins lying inside it could end up with the same + * total cost (gl_length plus estimated cost to glDestPoint) as inPt, + * so we at least have to add them. + * + * Things are more complex if heapCost is greater than inPt->gl_length + * plus estCost. Let diff be the difference. We will bloat the rect + * by diff/2. The reason is that points in the bloated rectangle could + * end up with a total cost equal to heapCost, since they involve a + * detour of diff/2 units out and then diff/2 units back to align + * with the destination point. + * + * The actual amount of the bloat is diff/2 + RtrGridSpacing*4 to + * give a little extra slop. + * + * Results: + * None. + * + * Side effects: + * Fills in *pRect. + * + * ---------------------------------------------------------------------------- + */ + +void +glSetPinClip(inPt, inCh, heapCost, dRect, pRect) + GlPoint *inPt; + GCRChannel *inCh; + int heapCost; + Rect *dRect, *pRect; +{ + int bloat, estCost, t; + Rect r; + + if (DebugIsSet(glDebugID, glDebAllPoints)) + { + *pRect = *dRect; + return; + } + + /* + * First construct the rectangle in lambda coordinates. + * Make it canonical: ll <= ur. + */ + r.r_ll = inPt->gl_point; + r.r_ur = glDestPoint; + if (r.r_xbot > r.r_xtop) t = r.r_xbot, r.r_xbot = r.r_xtop, r.r_xtop = t; + if (r.r_ybot > r.r_ytop) t = r.r_ybot, r.r_ybot = r.r_ytop, r.r_ytop = t; + + /* Bloat it */ + estCost = ABSDIFF(inPt->gl_point.p_x, glDestPoint.p_x) + + ABSDIFF(inPt->gl_point.p_y, glDestPoint.p_y); + bloat = (heapCost - (estCost + inPt->gl_length)) / 2; + bloat += RtrGridSpacing * 4; + GEO_EXPAND(&r, bloat, &r); + + /* Convert to grid coordinates */ + pRect->r_xbot = (r.r_xbot - inCh->gcr_origin.p_x) / RtrGridSpacing; + pRect->r_ybot = (r.r_ybot - inCh->gcr_origin.p_y) / RtrGridSpacing; + pRect->r_xtop = (r.r_xtop - inCh->gcr_origin.p_x) / RtrGridSpacing; + pRect->r_ytop = (r.r_ytop - inCh->gcr_origin.p_y) / RtrGridSpacing; + + /* Clip against dRect */ + GEOCLIP(pRect, dRect); +} + +/* + * ---------------------------------------------------------------------------- + * + * glResetCost -- + * + * Reset the costs stored with each GlPin after we've completed + * the global routing for a single net. + * + * Results: + * None. + * + * Side effects: + * Sets each pin's cost to INFINITY. + * + * ---------------------------------------------------------------------------- + */ + +void +glResetCost(headPage, headFree) + GlPage *headPage; + int headFree; +{ + GlPage *gpage; + GCRPin *pin; + int n; + + for (gpage = headPage; gpage; gpage = gpage->glp_next) + { + for (n = headFree; n < gpage->glp_free; n++) + if (pin = gpage->glp_array[n].gl_pin) + { + pin->gcr_cost = INFINITY; + if (pin->gcr_linked) + pin->gcr_linked->gcr_cost = INFINITY; + } + if (gpage == glCurPage) + break; + headFree = 0; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * glPropagateFn -- + * + * Search function called by glRouteToPoint for each unused crossing + * point exiting the channel whose entry point is being processed. + * + * Results: + * Returns the cost with which the point was added to the heap, + * if it was added, or -1 if not. + * + * Side effects: + * If the crossing point is usable and the path through inPin + * is the cheapest, add the new crossing point to the heap. + * + * ---------------------------------------------------------------------------- + */ + +int +glPropagateFn(outCh, outPin, inPt) + GCRChannel *outCh; /* Channel entered from outPin */ + GCRPin *outPin; /* Exit pin, also in inCh */ + GlPoint *inPt; /* Point being considered */ +{ + int cost, n; + int finalCost; + GlPoint *outPt; + + glCrossingsConsidered++; + + /* Add the distance to the exit point to the cost */ + cost = inPt->gl_length; + n = inPt->gl_point.p_x - outPin->gcr_point.p_x; + if (n < 0) cost -= n; else cost += n; + n = inPt->gl_point.p_y - outPin->gcr_point.p_y; + if (n < 0) cost -= n; else cost += n; + + /* Adjust by penalty and see if we can throw out this path */ + cost = glCrossPenalty(cost, inPt->gl_ch, outCh, inPt->gl_pin, outPin); + if (cost >= outPin->gcr_cost) + return (-1); + + if (DebugIsSet(glDebugID, glDebMaze)) + glPropagateDebug(inPt, inPt->gl_pin, outCh, outPin, + outPin->gcr_cost, cost); + + /* Remember the new cheapest cost path and add point to the heap */ +#ifdef notdef + if (outPin->gcr_point.p_x == iPt.p_x && outPin->gcr_point.p_y == iPt.p_y) + TxPrintf("Bingo! cost=%d\n", cost); +#endif /* notdef */ + outPin->gcr_cost = cost; + if (outPin->gcr_linked) + outPin->gcr_linked->gcr_cost = cost; + outPt = glNewPoint(&outPin->gcr_point, outCh, + outPin->gcr_linked, cost, inPt); + + /* + * Special handling if outPt is in a river-routing channel. + * There's no point in adding it to the heap, since we know + * the only point that is reachable from it. Just propagate + * depth-first from here. + */ + if (outCh->gcr_type != CHAN_NORMAL) + return (glRiverPropagate(outPt)); + + /* + * Estimate the least possible cost to reach the destination + * using this path. + */ + finalCost = cost + ABSDIFF(glDestPoint.p_x, outPin->gcr_point.p_x) + + ABSDIFF(glDestPoint.p_y, outPin->gcr_point.p_y); + HeapAddInt(&glHeap, finalCost, (char *) outPt); + if (glLogFile) + { + fprintf(glLogFile, "ADD\t%d\t%d,%d\t%d\t%d\n", + glNumTries, + outPt->gl_point.p_x, outPt->gl_point.p_y, + outPt->gl_length, finalCost); + } + return (finalCost); +} + +/* + * ---------------------------------------------------------------------------- + * + * glCrossPenalty -- + * + * Evaluate a set of crossing points through a channel to determine the + * total cost of bad crossing penalties. These penalties are added to + * 'cost' to give the total cost. (The argument 'cost' should be the + * sum of the cost to get to 'inPin' plus the Manhattan distance from + * 'inPin' to 'outPin'). + * + * Density considerations are ignored here; they are the responsibilty + * of the caller. + * + * Results: + * The total cost plus penalty, in lambda units. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +glCrossPenalty(cost, inCh, outCh, inPin, outPin) + int cost; /* Distance cost */ + GCRChannel *inCh; /* Both inPin and outPin are in this channel */ + GCRChannel *outCh; /* Channel to which outPin exits, or NULL + * if outPin is the destination. + */ + GCRPin *inPin; /* Pin used to enter inCh */ + GCRPin *outPin; /* Pin used to exit inCh into outCh */ +{ + GCRPin *otherPin; + int count; + + /* Penalty for using lots of channels */ + cost += glChanPenalty; + + /* Penalize if the net doesn't run straight across the channel */ + if (inPin->gcr_x != outPin->gcr_x && inPin->gcr_y != outPin->gcr_y) + cost += glJogPenalty; + + /* + * If there is an obstacle or hazard over a crossing, or an + * obstacle somewhere along the track or column of the pin, + * then assess a penalty. Look on both sides of the crossing + * to get this penalty. + */ +#define BADCROSSFLAGS (GCROBST|GCRHAZRD|GCRTCC) + otherPin = outPin->gcr_linked; + if (outCh && outCh->gcr_type == CHAN_NORMAL) + { + if ((otherPin->gcr_pFlags & BADCROSSFLAGS) + || otherPin->gcr_pSize != 0) + { + ASSERT(otherPin->gcr_pSize >= 0, "glCrossPenalty"); + cost += glObsPenalty1; + if (otherPin->gcr_pFlags & GCROBST) + cost += glObsPenalty2 * otherPin->gcr_pSize; + else if (otherPin->gcr_pFlags & GCRHAZRD) + cost += MAX(glObsPenalty2*otherPin->gcr_pSize + - otherPin->gcr_pDist, 0); + } + } + + /* + * Done if this is not a cheaper way of reaching outPin, + * or if this channel is used for river-routing (in which + * case the subsequent penalty computation is not needed). + */ + if (cost >= outPin->gcr_cost || inCh->gcr_type != CHAN_NORMAL) + return (cost); + + if ((outPin->gcr_pFlags & BADCROSSFLAGS) + || outPin->gcr_pSize != 0) + { + ASSERT(outPin->gcr_pSize >= 0, "glCrossPenalty"); + cost += glObsPenalty1; + if (outPin->gcr_pFlags & GCROBST) + cost += glObsPenalty2 * outPin->gcr_pSize; + else if (outPin->gcr_pFlags & GCRHAZRD) + cost += MAX(glObsPenalty2 * outPin->gcr_pSize + - outPin->gcr_pDist, 0); + } + + /* Done if this is not a cheaper way of reaching outPin */ + if (cost >= outPin->gcr_cost) + return (cost); + + /* + * If both neighboring pins are used, the penalty is 5. + * If only one of the neighboring pins is used, the penalty is only 2. + */ + count = 0; + if ((outPin + 1)->gcr_pId) count++; + if ((outPin - 1)->gcr_pId) count++; + if (count == 2) cost += glNbrPenalty2; + else if (count == 1) cost += glNbrPenalty1; + + /* + * If the path turns in the channel and the exit crossing + * isn't a paired orphan, the penalty is 3. + */ + if (outPin->gcr_side != GeoOppositePos[inPin->gcr_side]) + { + switch (outPin->gcr_side) + { + case GEO_NORTH: otherPin = &inCh->gcr_bPins[outPin->gcr_x]; break; + case GEO_SOUTH: otherPin = &inCh->gcr_tPins[outPin->gcr_x]; break; + case GEO_EAST: otherPin = &inCh->gcr_lPins[outPin->gcr_y]; break; + case GEO_WEST: otherPin = &inCh->gcr_rPins[outPin->gcr_y]; break; + } + if (otherPin->gcr_pId == (GCRNet *) NULL) + cost += glOrphanPenalty; + } + + return (cost); +} + +/* + * ---------------------------------------------------------------------------- + * + * glDensityExceeded -- + * + * Determine if the path from inPin to outPin through inCh passes + * through any region of maximum density. + * + * Results: + * Returns TRUE if the path passes through a maximum-density + * region, FALSE if not. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +glDensityExceeded(inCh, inPin, outPin) + GCRChannel *inCh; + GCRPin *inPin, *outPin; +{ + int min, max, maxdensity; + short *den; + short *dlast; + + if (inCh->gcr_dMaxByRow >= inCh->gcr_length) + { + glVDensityChecks++; + maxdensity = inCh->gcr_length; + min = MIN(inPin->gcr_y, outPin->gcr_y); + min = INRANGE(min, 1, inCh->gcr_width); + max = MAX(inPin->gcr_y, outPin->gcr_y); + max = INRANGE(max, 1, inCh->gcr_width); + den = &inCh->gcr_dColsByRow[min]; + dlast = &inCh->gcr_dColsByRow[max]; + while (den <= dlast) + if (*den++ >= maxdensity) + { + glVDensityFailures++; + return (TRUE); + } + } + if (inCh->gcr_dMaxByCol >= inCh->gcr_width) + { + glHDensityChecks++; + maxdensity = inCh->gcr_width; + min = MIN(inPin->gcr_x, outPin->gcr_x); + min = INRANGE(min, 1, inCh->gcr_length); + max = MAX(inPin->gcr_x, outPin->gcr_x); + max = INRANGE(max, 1, inCh->gcr_length); + den = &inCh->gcr_dRowsByCol[min]; + dlast = &inCh->gcr_dRowsByCol[max]; + while (den <= dlast) + if (*den++ >= maxdensity) + { + glHDensityFailures++; + return (TRUE); + } + } + + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * glRectToRange -- + * + * Convert from a Rect to a PinRanges representation of a range of pin + * values. Both representations contain the same information, but the + * latter is more convenient to work with in glNormalPropagate(), while + * the former requires half the storage. + * + * The dimensions of 'ch' are used to determine whether the pins on a + * given side of a channel are to be excluded or not: if the Rect 'r' + * doesn't extend all the way to 0 on the left or bottom, or to + * ch->gcr_width + 1 on the top or ch->gcr_length + 1 on the right, + * then the pins on that side are excluded. + * + * Results: + * None. + * + * Side effects: + * Sets *pr to the PinRanges structure implied by 'r'. + * + * ---------------------------------------------------------------------------- + */ + +void +glRectToRange(ch, r, pr) + GCRChannel *ch; + Rect *r; + PinRanges *pr; +{ + Rect clipR; + + /* Initialize to empty */ + *pr = glInitRange; + + /* Actual ranges will be from 1 to height or width of channel */ + clipR.r_xbot = MAX(r->r_xbot, 1); + clipR.r_ybot = MAX(r->r_ybot, 1); + clipR.r_xtop = MIN(r->r_xtop, ch->gcr_length); + clipR.r_ytop = MIN(r->r_ytop, ch->gcr_width); + + /* Top */ + if (r->r_ytop == ch->gcr_width + 1) + pr->pr_tmin = clipR.r_xbot, pr->pr_tmax = clipR.r_xtop; + + /* Bottom */ + if (r->r_ybot == 0) + pr->pr_bmin = clipR.r_xbot, pr->pr_bmax = clipR.r_xtop; + + /* Left */ + if (r->r_xbot == 0) + pr->pr_lmin = clipR.r_ybot, pr->pr_lmax = clipR.r_ytop; + + /* Right */ + if (r->r_xtop == ch->gcr_length + 1) + pr->pr_rmin = clipR.r_ybot, pr->pr_rmax = clipR.r_ytop; +} + +/* + * ---------------------------------------------------------------------------- + * + * glJogsAcrossChannel -- + * + * Determine whether a signal crosses from one side of a channel + * to the other with a jog. + * + * Results: + * TRUE if inPin and outPin are on opposite sides of the channel + * but are not directly opposite each other. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +glJogsAcrossChannel(inPin, outPin) + GCRPin *inPin, *outPin; +{ + switch (inPin->gcr_side) + { + case GEO_NORTH: + if (outPin->gcr_side == GEO_SOUTH + && outPin->gcr_point.p_x != inPin->gcr_point.p_x) + return (TRUE); + break; + case GEO_SOUTH: + if (outPin->gcr_side == GEO_NORTH + && outPin->gcr_point.p_x != inPin->gcr_point.p_x) + return (TRUE); + break; + case GEO_EAST: + if (outPin->gcr_side == GEO_WEST + && outPin->gcr_point.p_y != inPin->gcr_point.p_y) + return (TRUE); + break; + case GEO_WEST: + if (outPin->gcr_side == GEO_EAST + && outPin->gcr_point.p_y != inPin->gcr_point.p_y) + return (TRUE); + break; + } + + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * glPropagateDebug -- + * + * Used for debugging; print lots of information about the pair of + * crossing points inPin and outPin (propagating through inPt->gl_ch). + * + * Results: + * None. + * + * Side effects: + * Prints stuff on the terminal; also displays the areas of + * the two crossing points on the screen. + * + * ---------------------------------------------------------------------------- + */ + +void +glPropagateDebug(inPt, inPin, outCh, outPin, prevCost, distCost) + GlPoint *inPt; + GCRPin *inPin, *outPin; + GCRChannel *outCh; + int prevCost, distCost; +{ + char mesg[256]; + Point linkedPt; + Rect r; + + r.r_ll = r.r_ur = inPt->gl_point; + r.r_xtop++, r.r_ytop++; + nrShowRect(EditCellUse->cu_def, &r, STYLE_SOLIDHIGHLIGHTS); + if (inPin->gcr_linked) linkedPt = inPin->gcr_linked->gcr_point; + else linkedPt = TiPlaneRect.r_ll; + (void) sprintf(mesg, + "ENTRY ch=%x (%d,%d) (%d,%d) pin=%x (%d,%d) linked=%x (%d,%d)", + outCh, + outCh->gcr_area.r_xbot, outCh->gcr_area.r_ybot, + outCh->gcr_area.r_xtop, outCh->gcr_area.r_ytop, + inPin, inPin->gcr_point.p_x, inPin->gcr_point.p_y, + inPin->gcr_linked, linkedPt.p_x, linkedPt.p_y); + nrMore(mesg); + nrShowRect(EditCellUse->cu_def, &r, STYLE_ERASEHIGHLIGHTS); + + if (outPin->gcr_linked) linkedPt = outPin->gcr_linked->gcr_point; + else linkedPt = TiPlaneRect.r_ll; + (void) sprintf(mesg, + "EXIT ch=%x (%d,%d) (%d,%d) %d/%d pin=%x (%d,%d) linked=%x (%d,%d)", + outCh, + outCh->gcr_area.r_xbot, outCh->gcr_area.r_ybot, + outCh->gcr_area.r_xtop, outCh->gcr_area.r_ytop, + prevCost, distCost, + outPin, outPin->gcr_point.p_x, outPin->gcr_point.p_y, + outPin->gcr_linked, linkedPt.p_x, linkedPt.p_y); + r.r_ll = r.r_ur = outPin->gcr_point; + r.r_xtop++, r.r_ytop++; + nrShowRect(EditCellUse->cu_def, &r, STYLE_SOLIDHIGHLIGHTS); + nrMore(mesg); + nrShowRect(EditCellUse->cu_def, &r, STYLE_ERASEHIGHLIGHTS); +} + +/* + * ---------------------------------------------------------------------------- + * + * glLogPath -- + * + * Print information about the point 'inPt' to the file glLogFile, + * but only if this is the first time the point was removed from + * the heap (indicated by inPt->gl_range being the same as glInitRect.) + * + * Results: + * None. + * + * Side effects: + * May print to glLogFile. + * + * ---------------------------------------------------------------------------- + */ + +void +glLogPath(inPt, cost) + GlPoint *inPt; + int cost; +{ + extern Rect glInitRect; + + if (bcmp((char *)&inPt->gl_range, (char *)&glInitRect, sizeof (Rect)) == 0) + { + fprintf(glLogFile, "TOP\t%d\t%d,%d\t%d\t%d\n", + glNumTries, + inPt->gl_point.p_x, inPt->gl_point.p_y, + inPt->gl_length, cost); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * glPrintPoint -- + * + * Print information about the GlPoint 'inPt'. + * + * Results: + * None. + * + * Side effects: + * Prints to the terminal. + * + * ---------------------------------------------------------------------------- + */ + +void +glPrintPoint(inPt) + GlPoint *inPt; +{ + TxPrintf("(%d,%d) l=%d p=0x%x c=0x%x", + inPt->gl_point.p_x, inPt->gl_point.p_y, + inPt->gl_length, inPt->gl_pin, inPt->gl_ch); +} + diff --git a/grouter/groutePath.c b/grouter/groutePath.c new file mode 100644 index 00000000..d9f34e70 --- /dev/null +++ b/grouter/groutePath.c @@ -0,0 +1,289 @@ +/* + * groutePath.c - + * + * Global signal router code for low-level manipulation of GlPoints. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char sccsid[] = "@(#)groutePoint.c 4.9 MAGIC (Berkeley) 12/6/85"; +#endif /* not lint */ + +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "debug/debug.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "textio/textio.h" +#include "utils/malloc.h" + +/* First, last, and current GlPages on list for allocating GlPoints */ +GlPage *glPathFirstPage = NULL; +GlPage *glPathLastPage = NULL; +GlPage *glPathCurPage = NULL; + +/* + * ---------------------------------------------------------------------------- + * + * glListAdd -- + * + * Add a point to the head of the given linked list of points, + * with a given cost. To free the list when done, pass it to + * glPathFreePerm() below. Lists are linked using the gl_path + * field of a GlPoint, just like paths, but the order of the + * points is unimportant and the cost reflects the cost of + * using a GlPoint as a starting point, rather than the cost + * of reaching it via a particular path. + * + * Results: + * None. + * + * Side effects: + * Memory is allocated for the new point using mallocMagic(), + * rather than using the mechanism of glPathNew(). Hence the + * list built with glListAdd() persists through calls to + * glPathFreeTemp() and must be freed explicitly using glPathFreePerm(). + * + * ---------------------------------------------------------------------------- + */ + +void +glListAdd(list, pin, cost) + GlPoint **list; /* Linked via gl_path pointers */ + GCRPin *pin; + int cost; +{ + GlPoint *newPt; + + newPt = (GlPoint *) mallocMagic((unsigned) (sizeof (GlPoint))); + newPt->gl_tile = (Tile *) NULL; + newPt->gl_pin = pin; + newPt->gl_cost = cost; + newPt->gl_path = *list; + *list = newPt; +} + +/* + * ---------------------------------------------------------------------------- + * + * glListToHeap -- + * + * Copy crossing points from the list of starting points for a net + * into the global heap. The heap cost of the copied point includes + * the Manhattan distance from the point to the destination. We + * recompute the hint tiles for points when we copy them, since + * the tile structure of glChanPlane may have changed since list + * was built. + * + * Results: + * None. + * + * Side effects: + * Memory is allocated. Structs are added to the global heap. + * + * ---------------------------------------------------------------------------- + */ + +void +glListToHeap(list, destPt) + GlPoint *list; /* List of points linked via gl_path pointers */ + Point *destPt; +{ + GlPoint *temp, *new; + GCRPin *pin; + Tile *tp; + int dist; + + for (temp = list; temp; temp = temp->gl_path) + { + /* + * Only copy to heap if this pin doesn't lie within a blocked + * region (a pin can lie in a blocked region when the density + * for a portion of a channel is reached, and the pin happens + * to lie along that channel portion). + */ + pin = temp->gl_pin; + if (tp = glChanPinToTile((Tile *) NULL, pin)) + { + new = glPathNew(pin, temp->gl_cost, (GlPoint *) NULL); + new->gl_tile = tp; + dist = ABSDIFF(pin->gcr_point.p_x, destPt->p_x) + + ABSDIFF(pin->gcr_point.p_y, destPt->p_y) + + temp->gl_cost; + HeapAddInt(&glMazeHeap, dist, (char *) new); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * glPathCopyPerm -- + * glPathFreePerm -- + * + * The first procedure copies a path into a mallocMagic()'d list. + * All points from 'list' are copied; the copy of the point whose + * gl_path field pointed to root has its gl_path field pointing + * to NULL. + * + * The second procedure frees a list allocated in this fashion. + * + * Results: + * glPathCopyPerm returns a pointer to the new GlPoint path; + * glPathFreePerm returns nothing. + * + * Side effects: + * Memory is allocated for the new point for real, + * using mallocMagic(), rather than using the mechanism + * of glPathNew(). Hence the list built with glPathCopyPerm + * persists through calls to glPathFreeTemp() and must be + * freed explicitly using glPathFreePerm(). + * + * ---------------------------------------------------------------------------- + */ + +GlPoint * +glPathCopyPerm(list) + GlPoint *list; +{ + GlPoint *new, *prev, *first; + + for (first = prev = NULL; list; prev = new, list = list->gl_path) + { + new = (GlPoint *) mallocMagic((unsigned) (sizeof (GlPoint))); + *new = *list; + if (first == NULL) first = new; + if (prev) prev->gl_path = new; + } + + if (prev) prev->gl_path = (GlPoint *) NULL; + + return first; +} + +int +glPathFreePerm(list) + GlPoint *list; +{ + GlPoint *p; + + for (p = list; p; p = p->gl_path) + freeMagic((char *) p); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPathNew -- + * + * Create a new GlPoint and link it to the GlPoint from which + * it was visited. + * + * Results: + * Pointer to the newly allocated struct. + * + * Side effects: + * Memory is allocated. + * + * ---------------------------------------------------------------------------- + */ + +GlPoint * +glPathNew(pin, cost, prev) + GCRPin *pin; /* Pin at the crossing point (mustn't be NULL) */ + int cost; /* The cost to get here from source */ + GlPoint *prev; /* Point from which the new one was visited */ +{ + GlPoint *result; + + ASSERT(pin != NULL, "glPathNew"); + if (glPathCurPage == NULL || glPathCurPage->glp_free >= POINTSPERSEG) + { + /* Skip to next page if this one is full */ + if (glPathCurPage && glPathCurPage->glp_free >= POINTSPERSEG) + glPathCurPage = glPathCurPage->glp_next; + + /* If out of pages, allocate a new one */ + if (glPathCurPage == NULL) + { + glPathCurPage = (GlPage *) mallocMagic((unsigned) (sizeof (GlPage))); + glPathCurPage->glp_next = (GlPage *) NULL; + glPathCurPage->glp_free = 0; + if (glPathLastPage == NULL) + { + glPathFirstPage = glPathCurPage; + glPathLastPage = glPathCurPage; + } + else + { + glPathLastPage->glp_next = glPathCurPage; + glPathLastPage = glPathCurPage; + } + } + } + + result = &glPathCurPage->glp_array[glPathCurPage->glp_free++]; + result->gl_path = prev; + result->gl_cost = cost; + result->gl_pin = pin; + result->gl_tile = (Tile *) NULL; + + return result; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPathFreeTemp -- + * + * Reset the temporary arena used for allocating GlPoints. + * + * Results: + * None. + * + * Side effects: + * Memory is freed. + * + * ---------------------------------------------------------------------------- + */ + +void +glPathFreeTemp() +{ + GlPage *gpage; + + for (gpage = glPathFirstPage; gpage; gpage = gpage->glp_next) + { + /* Mark page of RoutePaths as being free */ + gpage->glp_free = 0; + + /* Can stop after processing the last page used in this cycle */ + if (gpage == glPathCurPage) + break; + } + + /* Start allocating again from the first page on the list */ + glPathCurPage = glPathFirstPage; +} diff --git a/grouter/groutePen.c b/grouter/groutePen.c new file mode 100644 index 00000000..87e1fd46 --- /dev/null +++ b/grouter/groutePen.c @@ -0,0 +1,909 @@ +/* + * groutePen.c + * + * Computation of the penalties to be assigned for each net using + * certain congested regions. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/grouter/groutePen.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* lint */ + +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/netlist.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "utils/styles.h" +#include "utils/list.h" + +/* Forward declarations */ +void glPenSavePath(); +int glPenSortNetSet(); +int glPenFindCrossingFunc(); +int glPenDeleteFunc(); +int glPenRouteCost(); +int glPenRerouteNetCost(); +NetSet *glPenFindCrossingNets(); +CZone *glPenScanDens(); +CZone *glPenFindCZones(); + + +/* + * ---------------------------------------------------------------------------- + * + * glPenSetPerChan -- + * glPenClearPerChan -- + * + * Visit all of the channels on the CZone list for 'net' + * (this list is ((NetClient *) net->nnet_cdata)->nc_pens); + * glPenSetPerChan will prepend a copy of each CZone + * to the penalty list for the appropriate channel, while + * glPenClearPerChan will free the list for each channel. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +glPenSetPerChan(net) + NLNet *net; +{ + CZone *czNet, *czChan; + GlobChan *gc; + + for (czNet = ((NetClient *) net->nnet_cdata)->nc_pens; + czNet; + czNet = czNet->cz_next) + { + gc = (GlobChan *) czNet->cz_chan->gcr_client; + czChan = (CZone *) mallocMagic((unsigned) (sizeof (CZone))); + *czChan = *czNet; + czChan->cz_next = gc->gc_penList; + gc->gc_penList = czChan; + } +} + +int +glPenClearPerChan(net) + NLNet *net; +{ + CZone *czNet, *czChan; + GlobChan *gc; + + for (czNet = ((NetClient *) net->nnet_cdata)->nc_pens; + czNet; + czNet = czNet->cz_next) + { + gc = (GlobChan *) czNet->cz_chan->gcr_client; + for (czChan = gc->gc_penList; czChan; czChan = czChan->cz_next) + freeMagic((char *) czChan); + gc->gc_penList = (CZone *) NULL; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenCompute -- + * + * Some routing regions will have many nets passing through them. + * It may be, however, that some of these nets need a given region + * much more than others: the cost to them of going around the + * region is very high. This procedure attempts to identify + * congested regions (CZones), and furthermore to determine the + * nets that should be penalized for using those regions and the + * amount of the penalty. + * + * On input, the gc_prevDens and gc_postDens fields of each channel's + * associated GlobChan structure should be set up to reflect the + * presence of blocking information. + * + * Algorithm: + * Route each net as though it were the first net to be routed. + * Avoid routing through any portion of a channel that is already + * at density (from pre-existing wiring), but otherwise don't + * bother computing penalties. Choose crossing points to give + * locally (i.e, per-channel) optimal lengths. This enables + * us to avoid looking at most crossing points so we can route + * very quickly. + * + * Remember each of the paths that comprised each net by storing + * a permanent copy of each in the list nc_paths in the NetClient + * structure for each net. + * + * After all nets have been processed, update density in the + * gc_postDens density map of all channels to reflect the routes + * assigned to all nets. For each region of a channel where density + * has been exceeded, we look at all the nets that pass through the + * region and see how expensive it would be to route each one if it + * had to avoid that region entirely. (It is infinitely expensive + * if the region contains either the starting or ending point of the + * route!) + * + * While the costs computed above are just an estimate (since they + * consider each net independently), the hope is that they will + * identify fairly well those nets that can easily avoid congested + * areas with only slight detours, as well as those nets for which + * certain regions of channels are critical. + * + * We pick those nets whose cost increases the least by having to + * avoid the congested region as those that will be penalized; the + * penalty for each net is the additional cost of avoiding the region + * for the net for which this cost is highest. (In effect, this gives + * us a balanced tradeoff: the net with low cost for not using the + * channel won't use it unless it has otherwise to make at least as + * big a detour as our estimate for the most expensive one). + * + * Results: + * None. + * + * Side effects: + * Stores a pointer to a list of CZone structures in + * the nnet_cdata->nc_pens field of each net in netList. + * (The list may be NULL). Each element in the list identifies + * a channel and a penalty; the interpretation is that this + * net should be penalized by the indicated penalty if it + * has to go through this channel. + * Also uses nnet_cdata->nc_paths as temporary working storage. + * + * ---------------------------------------------------------------------------- + */ + +void +glPenCompute(chanList, netList) + GCRChannel *chanList; /* All the channels in the routing problem */ + NLNetList *netList; /* Netlist being routed */ +{ +#ifdef notdef + CZone *czones, *cz; + GlobChan *gc; + GCRChannel *ch; + NLNet *net; + + /* + * Process nets in the order they appear, since this routing + * is order-independent. After all done, we have remembered + * the GlPoints for all a net's segments in the NetClient nc_paths + * list for that net. Also, the density map gc_postDens in each + * channel's GlobChan has been set. + */ + for (net = netList->nnl_nets; net; net = net->nnet_next) + glMultiSteiner((CellUse *) NULL, net, glProcessLoc, glPenSavePath, + (ClientData) TRUE, (ClientData) NULL); + + /* + * Set the density map gc_postDens in all channels. + * The initial contents of gc_postDens should have been set + * to the same as gc_prevDens by the caller; we just add + * all the nets routed in the step above. + */ + for (net = netList->nnl_nets; net; net = net->nnet_next) + glPenDensitySet(net); + + /* + * Find all the congested zones in the circuit and store them in + * a list of CZone structures. + */ + czones = glPenFindCZones(chanList); + + /* + * Process each CZone to determine which nets should be assigned + * penalties for crossing that zone. The penalties assigned to + * a net for a CZone in an earlier iteration apply to attempts + * to route that net around other CZones in later iterations. + * The final result of this step is to build the nc_pens list + * for each net's NetClient structure. + */ + for (cz = czones; cz; cz = cz->cz_next) + glPenAssignCosts(cz, netList); + + /* + * Final cleanup: free the GlPoints in each net's nc_paths list, + * since they're no longer needed. Also reset gc_postDens in + * each channel to its initial value, gc_prevDens. + */ + for (net = netList->nnl_nets; net; net = net->nnet_next) + glPenCleanNet(net); + for (ch = chanList; ch; ch = ch->gcr_next) + { + gc = (GlobChan *) ch->gcr_client; + glDMCopy(&gc->gc_prevDens[CZ_COL], &gc->gc_postDens[CZ_COL]); + glDMCopy(&gc->gc_prevDens[CZ_ROW], &gc->gc_postDens[CZ_ROW]); + } +#endif /* notdef */ +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenFindCZones -- + * + * Build up a list of all congested zones in all channels. + * See grouter.h for a definition of a congested zone. + * The density map we search is gc_postDens. + * + * Results: + * Returns a pointer to the list. + * + * Side effects: + * Allocates memory. + * + * ---------------------------------------------------------------------------- + */ + +CZone * +glPenFindCZones(chanList) + GCRChannel *chanList; /* All the channels in the routing problem */ +{ + CZone *czList; + DensMap *dmap; + GCRChannel *ch; + + czList = (CZone *) NULL; + for (ch = chanList; ch; ch = ch->gcr_next) + { + dmap = ((GlobChan *) ch->gcr_client)->gc_postDens; + czList = glPenScanDens(czList, ch, &dmap[CZ_COL], CZ_COL); + czList = glPenScanDens(czList, ch, &dmap[CZ_ROW], CZ_ROW); + } + + return czList; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenScanDens -- + * + * Scan for portions of a density map where the density exceeds the + * capacity, and allocate a CZone for each such range. + * + * Results: + * Returns a pointer to a CZone list with the new elements + * described above prepended to czList. + * + * Side effects: + * Allocates memory. + * + * ---------------------------------------------------------------------------- + */ + +CZone * +glPenScanDens(czList, ch, dm, type) + CZone *czList; /* Prepend to this list */ + GCRChannel *ch; /* Which channel is being processed */ + DensMap *dm; /* Map to search */ + int type; /* Type of zone: CZ_ROW or CZ_COL */ +{ + short *val = dm->dm_value; + CZone *cz; + int i; + + /* Nothing to do if the capacity is never exceeded */ + if (dm->dm_max <= dm->dm_cap) + return czList; + + /* + * Simple state machine to find the start and end of + * each zone of excess density. If cz is NULL then + * we're currently out of a zone; otherwise, we're + * building one up. Consider elements of the density + * map from 1 .. dm->dm_size. + */ + cz = (CZone *) NULL; + for (i = 1; i < dm->dm_size; i++) + { + if (cz) + { + if (val[i] <= dm->dm_cap) + { + /* End of congested zone */ + cz->cz_hi = i - 1; + cz = (CZone *) NULL; + } + } + else + { + if (val[i] > dm->dm_cap) + { + /* Beginning of congested zone */ + cz = (CZone *) mallocMagic((unsigned) (sizeof (CZone))); + cz->cz_chan = ch; + cz->cz_type = type; + cz->cz_lo = i; + cz->cz_penalty = 0; + cz->cz_nets = (NetSet *) NULL; + cz->cz_next = czList; + czList = cz; + } + } + } + + /* Take care of case when a CZone extends all the way to the end */ + if (cz) cz->cz_hi = dm->dm_size - 1; + + return czList; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenAssignCosts -- + * + * Find all nets that cross a congested zone and determine how expensive + * it would be to reroute each if they had to avoid that zone. Once this + * cost is determined for all nets affected, pick the N least-cost nets, + * where N is the number of nets that would have to be re-routed in order + * to reduce the number running through the congested zone to be within + * its capacity (N should always be greater than zero). Prepend a CZone + * to the np_pens list of each of these N nets NetClients, with a cz_penalty + * equal to the cost of the most-expensive-to-reroute net. + * + * Results: + * None. + * + * Side effects: + * Allocates memory for the CZones placed on each NetClient's np_pens + * list; see above for details. + * + * ---------------------------------------------------------------------------- + */ + +void +glPenAssignCosts(cz, netList) + CZone *cz; /* A single CZone being processed */ + NLNetList *netList; /* List of all nets; we look for nets that cross + * this zone. + */ +{ + int oldCost, newCost, maxCost, numCross, density; + NetSet *crossNets, *ns, **crossArray, **nsap; + GlobChan *gc; + DensMap *dm; + CZone *czNew; + NetClient *nc; + List *list; + + /* Find the nets that use this congested zone */ + crossNets = glPenFindCrossingNets(cz, netList); + + /* + * For each net in the set, determine how expensive it would be + * if it couldn't use this congested zone at all. + */ + maxCost = 0; + numCross = 0; + for (ns = crossNets; ns; ns = ns->ns_next) + { + oldCost = 0; + nc = (NetClient *) ns->ns_net->nnet_cdata; + + for (list = nc->nc_paths; list; list = LIST_TAIL(list)) + oldCost += ((GlPoint *) LIST_FIRST(list))->gl_cost; + newCost = glPenRerouteNetCost(cz, ns->ns_net); + ns->ns_cost = newCost - oldCost; + if (ns->ns_cost > maxCost) maxCost = ns->ns_cost; + numCross++; + } + + /* + * Sort the NetSets on the crossNets list in order of increasing + * ns_cost, leaving crossArray[i] pointing to the i'th smallest + * NetSet. + */ + crossArray = (NetSet **) mallocMagic((unsigned) (numCross * sizeof (NetSet *))); + for (ns = crossNets, nsap = crossArray; ns; ns = ns->ns_next) *nsap++ = ns; + qsort(crossArray, numCross, sizeof (NetSet *), glPenSortNetSet); + + /* + * Now comes the fun part. + * We must select a group of nets to assign a penalty of maxCost. + * The best nets to receive this penalty are those whose cost + * to reroute around 'cz' is least. However, we also want to + * assign this penalty to the minimum number of nets necessary + * to eliminate the congestion at 'cz' (i.e, to reduce the + * density to equal the channel capacity). + * + * The approach below is to start pulling nets out of the + * congested zone, in order of increasing ns_cost, until + * the congestion disappears. + */ + gc = (GlobChan *) cz->cz_chan->gcr_client; + dm = &gc->gc_postDens[cz->cz_type]; + density = glDMMaxInRange(dm, cz->cz_lo, cz->cz_hi); + nsap = crossArray; + while (density > dm->dm_cap) + { + ns = *nsap++; + nc = (NetClient *) ns->ns_net->nnet_cdata; + czNew = (CZone *) mallocMagic((unsigned) (sizeof (CZone))); + *czNew = *cz; + czNew->cz_penalty = maxCost; + czNew->cz_nets = (NetSet *) NULL; + czNew->cz_next = nc->nc_pens; + nc->nc_pens = czNew; + + /* Update 'dm' to reflect the absence of the net */ + density = glPenDeleteNet(dm, nc->nc_paths, cz); + } + + /* Cleanup */ + for (ns = crossNets; ns; ns = ns->ns_next) + freeMagic((char *) ns); + freeMagic((char *) crossArray); +} + +/* + * glPenSortNetSet -- + * + * Called by qsort() to compare the ns_cost values of two NetSets + * pointed to by *ns1 and *ns2 respectively. + * + * Results: + * (*ns1)->ns_cost ? (*ns2)->ns_cost returns + * --------------------------------- ------- + * > 1 + * < -1 + * = 0 + * + * Side effects: + * None. + */ + +int +glPenSortNetSet(ns1, ns2) + NetSet **ns1, **ns2; +{ + if ((*ns1)->ns_cost > (*ns2)->ns_cost) return 1; + if ((*ns1)->ns_cost < (*ns2)->ns_cost) return -1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenFindCrossingNets -- + * + * Find all the nets in 'netList' whose routes cross through the + * congested zone 'cz'. + * + * Results: + * Returns a list of NetSet structs pointing to the nets + * found to cross through 'cz'. + * + * Side effects: + * Allocates memory. + * + * ---------------------------------------------------------------------------- + */ + + /* Structure passed to glPenFindCrossingFunc() via glPenEnumCross() */ +struct glCrossClient +{ + NLNet *rcc_net; /* Net whose segments are being enumerated */ + NetSet *rcc_set; /* NetSet being built up */ +}; + +NetSet * +glPenFindCrossingNets(cz, netList) + CZone *cz; /* A single CZone being processed */ + NLNetList *netList; /* List of all nets; we look for nets that cross + * this zone. + */ +{ + struct glCrossClient rcc; + List *list; + NLNet *net; + + rcc.rcc_set = (NetSet *) NULL; + for (net = netList->nnl_nets; net; net = net->nnet_next) + { + rcc.rcc_net = net; + for (list = ((NetClient *) net->nnet_cdata)->nc_paths; + list; + list = LIST_TAIL(list)) + { + if (glPenEnumCross(cz, (GlPoint *) LIST_FIRST(list), + glPenFindCrossingFunc, (ClientData) &rcc)) + break; + } + } + + return rcc.rcc_set; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenFindCrossingFunc -- + * + * Filter function for glPenFindCrossingNets() above, called by + * glPenEnumCross() for each segment on an GlPoint that crosses + * through the CZone 'cz'. + * + * Results: + * Always returns 1. + * + * Side effects: + * Allocates a NetSet for rcc->rcc_net and prepends it + * to the NetSet list rcc->rcc_set. + * + * ---------------------------------------------------------------------------- + */ + + /*ARGSUSED*/ +int +glPenFindCrossingFunc(cz, srcPin, dstPin, rcc) + CZone *cz; /* UNUSED */ + GCRPin *srcPin, *dstPin; /* UNUSED */ + struct glCrossClient *rcc; +{ + NetSet *ns; + + ns = (NetSet *) mallocMagic((unsigned) (sizeof (NetSet))); + ns->ns_net = rcc->rcc_net; + ns->ns_cost = 0; + ns->ns_next = rcc->rcc_set; + rcc->rcc_set = ns; + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenEnumCross -- + * + * Find all the segments on the GlPoint 'rp' that pass through the CZone 'cz'. + * For each segment, call the supplied procedure (*func)(), which should be + * of the following form: + * + * int + * (*func)(cz, srcPin, dstPin, cdata) + * CZone *cz; --- same as our argument 'cz' + * GCRPin *srcPin, *dstPin; --- two pins in cz's channel + * ClientData cdata; --- same as our argument 'cdata' + * { + * } + * + * This procedure should return 0 if glPenEnumCross() is to continue + * visiting further segments of the GlPoint, or a non-zero value if + * we are to stop visiting further segments. + * + * Results: + * Returns 0 if the end of the GlPoint was reached without + * (*func)() returning a non-zero value (or if no segments + * crossed through 'cz'). Returns 1 if (*func)() returned + * a non-zero value for some segment. + * + * Side effects: + * Whatever (*func)() does. + * + * ---------------------------------------------------------------------------- + */ + +int +glPenEnumCross(cz, rp, func, cdata) + CZone *cz; /* Look for segments passing through here */ + GlPoint *rp; /* List of GlPoints (linked by gl_path ptrs) */ + int (*func)(); /* Apply to each segment passing through cz */ + ClientData cdata; /* Passed to (*func)() */ +{ + GCRPin *srcPin, *dstPin; + int cSrc, cDst; + + for ( ; rp->gl_path; rp = rp->gl_path) + { + /* Only interested if this segment is in cz_chan */ + srcPin = rp->gl_path->gl_pin; + if (srcPin->gcr_ch != cz->cz_chan) + continue; + dstPin = rp->gl_pin; + if (dstPin->gcr_ch != srcPin->gcr_ch) + dstPin = dstPin->gcr_linked; + + if (cz->cz_type == CZ_ROW) + { + cSrc = srcPin->gcr_y; + cDst = dstPin->gcr_y; + } + else + { + cSrc = srcPin->gcr_x; + cDst = dstPin->gcr_x; + } + + if ((cSrc >= cz->cz_lo && cSrc <= cz->cz_hi) + || (cDst >= cz->cz_lo && cDst <= cz->cz_hi)) + { + if ((*func)(cz, srcPin, dstPin, cdata)) + return 1; + } + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenRerouteNetCost -- + * + * Determine how expensive it would be for net 'net' if it couldn't + * be routed through 'cz'. + * + * Results: + * Cost value. + * + * Side effects: + * Frees memory; resets the nc_paths list to NULL. + * + * ---------------------------------------------------------------------------- + */ + +int +glPenRerouteNetCost(cz, net) + CZone *cz; + NLNet *net; /* Net to be rerouted */ +{ + NetClient *nc = (NetClient *) net->nnet_cdata; + CZone fakeCZ; + int cost; + + /* Prepend a fake CZone with infinite cost */ + fakeCZ = *cz; + fakeCZ.cz_penalty = INFINITY; + fakeCZ.cz_next = nc->nc_pens; + nc->nc_pens = &fakeCZ; + + /* + * Set the channel penalties and perform a normal routing, + * but just sum the cost of the resultant path instead of + * storing it anywhere. + */ + cost = 0; + glPenSetPerChan(net); + glMultiSteiner((CellUse *) NULL, net, glProcessLoc, glPenRouteCost, + (ClientData) TRUE, (ClientData) &cost); + glPenClearPerChan(net); + + /* Remove the fake CZone */ + nc->nc_pens = nc->nc_pens->cz_next; + + return cost; +} + + /*ARGSUSED*/ +int +glPenRouteCost(rootUse, bestPath, pNetId, pCost) + CellUse *rootUse; /* UNUSED */ + GlPoint *bestPath; /* Best path for this segment */ + NetId *pNetId; /* UNUSED */ + int *pCost; /* Add bestPath->gl_cost to this */ +{ + *pCost += bestPath->gl_cost; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenDeleteNet -- + * + * Modify the density map 'dm' to reflect the absence of all + * segments on 'list' (a List each of whose elements is the first + * GlPoints on a path of GlPoints) that pass through the CZone 'cz'. + * Only the entries of the density map that lie between cz->cz_lo + * and cz->cz_hi (inclusive) are affected. + * + * Results: + * Returns the new maximum density in 'dm' in the range + * cz->cz_lo through cz->cz_hi inclusive. + * + * Side effects: + * Modifies 'dm' as described above. + * + * ---------------------------------------------------------------------------- + */ + +int +glPenDeleteNet(dm, list, cz) + DensMap *dm; /* Update this map */ + List *list; /* List of paths */ + CZone *cz; /* Remove all segments passing through 'cz' from 'dm' */ +{ + for ( ; list; list = LIST_TAIL(list)) + (void) glPenEnumCross(cz, (GlPoint *) LIST_FIRST(list), + glPenDeleteFunc, (ClientData) dm); + + return glDMMaxInRange(dm, cz->cz_lo, cz->cz_hi); +} + +/* + * glPenDeleteFunc -- + * + * Do the real work of glPenDeleteNet() above. Called by glPenEnumCross() + * for each segment of the global routing of a net that passes through 'cz'. + * Updates 'dm' to reflect the ripping up of that portion of the segment + * that actually passes through 'cz'; portions of 'dm' that lie outside + * of 'cz' (cz->cz_lo through cz->cz_hi inclusive) are unaffected. + * + * Results: + * Always returns 0. + * + * Side effects: + * Modifies 'dm' as described in the comments for glPenDeleteNet(). + */ + +int +glPenDeleteFunc(cz, srcPin, dstPin, dm) + CZone *cz; /* Being passed through by srcPin..dstPin */ + GCRPin *srcPin, *dstPin; /* Two pins in cz->cz_chan */ + DensMap *dm; /* Remove srcPin..dstPin segment from 'dm' */ +{ + int n; + int lo, hi; + + if (cz->cz_type == CZ_COL) + { + /* Find range of columns spanned by the net */ + lo = MIN(srcPin->gcr_x, dstPin->gcr_x); + hi = MAX(srcPin->gcr_x, dstPin->gcr_x); + } + else + { + /* Find range of rows spanned by the net */ + lo = MIN(srcPin->gcr_y, dstPin->gcr_y); + hi = MAX(srcPin->gcr_y, dstPin->gcr_y); + } + + /* Clip so we don't modify entries of 'dm' outside of 'cz' */ + lo = MAX(lo, cz->cz_lo); + lo = MIN(lo, cz->cz_hi); + hi = MIN(hi, cz->cz_hi); + hi = MAX(hi, cz->cz_lo); + + /* Rip up this segment */ + for (n = lo; n <= hi; n++) + dm->dm_value[n]--; + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenCleanNet -- + * + * Free the GlPoints in a net's nc_paths list. + * + * Results: + * None. + * + * Side effects: + * Frees memory; resets the nc_paths list to NULL. + * + * ---------------------------------------------------------------------------- + */ + +void +glPenCleanNet(net) + NLNet *net; +{ + List *list; + NetClient *nc; + + nc = (NetClient *) net->nnet_cdata; + for (list = nc->nc_paths; list; list = LIST_TAIL(list)) + glPathFreePerm((GlPoint *) LIST_FIRST(list)); + ListDealloc(list); + nc->nc_paths = (List *) NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenSavePath -- + * + * Make a permanent copy of the GlPoint list 'path', and prepend the + * first element to the list being maintained for pNetId->netid_net's + * NetClient nc_paths field. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +glPenSavePath(rootUse, path, pNetId) + CellUse *rootUse; /* UNUSED */ + GlPoint *path; /* Path linked via gl_path pointers */ + NetId *pNetId; /* Net and segment identifier */ +{ + GlPoint *newpath; + NetClient *nc; + + nc = (NetClient *) pNetId->netid_net->nnet_cdata; + + /* Keep a permanent copy of the path */ + newpath = glPathCopyPerm(path); + LIST_ADD(newpath, nc->nc_paths); +} + +/* + * ---------------------------------------------------------------------------- + * + * glPenDensitySet -- + * + * Updates the density in the gc_postDens map in each channel + * reflect all of the paths for 'net'. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +glPenDensitySet(net) + NLNet *net; +{ + NetClient *nc = (NetClient *) net->nnet_cdata; + GCRPin *srcPin, *dstPin; + GlPoint *rp; + GlPoint *path; + List *list; + NetId netid; + + netid.netid_net = net; + netid.netid_seg = 0; + + for (list = ((NetClient *) net->nnet_cdata)->nc_paths; + list; + list = LIST_TAIL(list)) + { + path = (GlPoint *) LIST_FIRST(list); + for (rp = path; rp->gl_path; rp = rp->gl_path) + { + srcPin = rp->gl_path->gl_pin; + dstPin = rp->gl_pin; + if (dstPin->gcr_ch != srcPin->gcr_ch) dstPin = dstPin->gcr_linked; + glDensAdjust(((GlobChan *) srcPin->gcr_ch->gcr_client)->gc_postDens, + srcPin, dstPin, netid); + } + } +} diff --git a/grouter/groutePin.c b/grouter/groutePin.c new file mode 100644 index 00000000..56a62f4b --- /dev/null +++ b/grouter/groutePin.c @@ -0,0 +1,480 @@ +/* + * groutePin.c -- + * + * Global signal router code to implement operations on pins at + * the boundaries of channels. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char sccsid[] = "@(#)groutePin.c 4.9 MAGIC (Berkeley) 12/8/85"; +#endif /* not lint */ + +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/styles.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "debug/debug.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "textio/textio.h" + + +/* + * ---------------------------------------------------------------------------- + * + * glPointToPin -- + * + * Given a point somewhere on the perimeter of a channel, determine + * which pin it refers to. + * + * Results: + * Pointer to the pin struct whose location is given by pt. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +GCRPin * +glPointToPin(ch, side, point) + GCRChannel *ch; /* The channel containing the point */ + int side; /* Side of ch that point lies on */ + Point *point; /* The point to be converted to a pin */ +{ + int coord; + + switch (side) + { + case GEO_NORTH: + coord = (point->p_x - ch->gcr_origin.p_x) / RtrGridSpacing; + ASSERT(coord <= ch->gcr_length && coord >= 1, "glPointToPin"); + return &ch->gcr_tPins[coord]; + break; + + case GEO_SOUTH: + coord = (point->p_x - ch->gcr_origin.p_x) / RtrGridSpacing; + ASSERT(coord <= ch->gcr_length && coord >= 1, "glPointToPin"); + return &ch->gcr_bPins[coord]; + break; + + case GEO_EAST: + coord = (point->p_y - ch->gcr_origin.p_y) / RtrGridSpacing; + ASSERT(coord <= ch->gcr_width && coord >= 1, "glPointToPin"); + return &ch->gcr_rPins[coord]; + break; + + case GEO_WEST: + coord = (point->p_y - ch->gcr_origin.p_y) / RtrGridSpacing; + ASSERT(coord <= ch->gcr_width && coord >= 1, "glPointToPin"); + return &ch->gcr_lPins[coord]; + break; + } + + /* + * The pin is not on a side of the channel. + * Recover by returning a strange value which should + * not hurt anything. + */ + ASSERT(FALSE, "Pin not on side of channel in glPointToPin"); + return &ch->gcr_lPins[0]; +} + +/* + * ---------------------------------------------------------------------------- + * + * GLInitPins -- + * + * Initialize the global-router specific information for the pins + * around the periphery of the channel 'ch': + * + * gcr_ch Points back to the channel. + * gcr_cost Set to INFINITY. + * gcr_side Set to the side of the channel to which this pin + * belongs (GEO_NORTH, GEO_SOUTH, etc). + * gcr_point Set to the absolute (edit cell) coordinates + * of the crossing point associated with this pin. + * gcr_linked Points to the pin on the other side of this pin's + * crossing, or is NULL if there is no other pin. + * The gcr_linked field is set to NULL if crossing + * from a pin to the neighboring channel would exit + * a river-routing channel from an illegal side. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +GLInitPins(ch) + GCRChannel *ch; +{ + glPinArrayInit(ch, GEO_NORTH, ch->gcr_tPins, ch->gcr_length); + glPinArrayInit(ch, GEO_SOUTH, ch->gcr_bPins, ch->gcr_length); + glPinArrayInit(ch, GEO_WEST, ch->gcr_lPins, ch->gcr_width); + glPinArrayInit(ch, GEO_EAST, ch->gcr_rPins, ch->gcr_width); +} + +int +glPinArrayInit(ch, side, pins, nPins) + GCRChannel *ch; + GCRPin *pins; + int nPins; +{ + GCRPin *pin, *linked; + GCRChannel *adjacent; + GCRPin *lastPin; + Point point, p; + bool markLinked; + int otherSide; + Tile *tp; + + /* + * If exiting this channel from an illegal side, all gcr_linked fields + * are set to NULL. + */ + markLinked = TRUE; + switch (side) + { + case GEO_EAST: + case GEO_WEST: + if (ch->gcr_type == CHAN_VRIVER) + markLinked = FALSE; + break; + case GEO_NORTH: + case GEO_SOUTH: + if (ch->gcr_type == CHAN_HRIVER) + markLinked = FALSE; + break; + } + + lastPin = &pins[nPins + 1]; + for (pin = pins; pin <= lastPin; pin++) + { + pin->gcr_ch = ch; + pin->gcr_side = side; + pin->gcr_cost = INFINITY; + pin->gcr_linked = (GCRPin *) NULL; + otherSide = GeoOppositePos[side]; + + /* Figure out the crossing point */ + switch (side) + { + case GEO_WEST: + point.p_y = ch->gcr_origin.p_y + pin->gcr_y * RtrGridSpacing; + point.p_x = ch->gcr_area.r_xbot; + break; + case GEO_SOUTH: + point.p_x = ch->gcr_origin.p_x + pin->gcr_x * RtrGridSpacing; + point.p_y = ch->gcr_area.r_ybot; + break; + case GEO_EAST: + point.p_y = ch->gcr_origin.p_y + pin->gcr_y * RtrGridSpacing; + point.p_x = ch->gcr_area.r_xtop; + break; + case GEO_NORTH: + point.p_x = ch->gcr_origin.p_x + pin->gcr_x * RtrGridSpacing; + point.p_y = ch->gcr_area.r_ytop; + break; + default: + ASSERT(FALSE, "bad pin side in rtrInitPinArray"); + break; + } + pin->gcr_point = point; + + /* Don't set gcr_linked if exiting the channel from an illegal side */ + if (!markLinked) + continue; + + if (pin > pins && pin < lastPin) + { + /* + * Find the adjacent channel at that point. + * If one exists, find the pin in it that shares + * this pin's crossing. + */ + p = point; + if (side == GEO_WEST) p.p_x--; + if (side == GEO_SOUTH) p.p_y--; + tp = TiSrPointNoHint(RtrChannelPlane, &p); + if (adjacent = (GCRChannel *) tp->ti_client) + { + /* Only link if entering the linked channel from a legal side */ + linked = glPointToPin(adjacent, otherSide, &point); + switch (side) + { + case GEO_EAST: + case GEO_WEST: + if (adjacent->gcr_type != CHAN_VRIVER) + pin->gcr_linked = linked; + break; + case GEO_NORTH: + case GEO_SOUTH: + if (adjacent->gcr_type != CHAN_HRIVER) + pin->gcr_linked = linked; + break; + } + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * GLBlockPins -- + * + * Propagate blocked pin information. If a pin is blocked on one side + * of a channel BOUNDARY, it is blocked on the other side as well. If + * a pin on one side of a river-routing CHANNEL is blocked, the pin on + * the other side gets blocked too. Several iterations may be necessary + * to propagate blockages across all channel boundaries and river-routing + * channels. + * + * Also propagate obstacle flags for pins. If a pin's obstacle flags + * contain GCROBST, then set this bit in gcr_linked's flags as well. + * + * Results: + * TRUE if the blockage state of any pins changed, FALSE + * otherwise. The caller should iterate over all channels + * until no pins change any more. + * + * Side effects: + * Propagating a blockage to a pin consists of marking its + * gcr_pId with GCR_BLOCKEDNETID, and setting the GCRBLK flag + * in its gcr_pFlags (this latter only happens for gcr_linked + * pins, not for pins on the opposite side of a river-routing + * channel from a blocked pin). + * + * ---------------------------------------------------------------------------- + */ + +bool +GLBlockPins(ch) + GCRChannel *ch; +{ + bool changed; + + changed = FALSE; + if (glPinArrayBlock(ch, ch->gcr_tPins, ch->gcr_bPins, ch->gcr_length)) + changed = TRUE; + if (glPinArrayBlock(ch, ch->gcr_bPins, ch->gcr_tPins, ch->gcr_length)) + changed = TRUE; + if (glPinArrayBlock(ch, ch->gcr_lPins, ch->gcr_rPins, ch->gcr_width)) + changed = TRUE; + if (glPinArrayBlock(ch, ch->gcr_rPins, ch->gcr_lPins, ch->gcr_width)) + changed = TRUE; + + return changed; +} + +bool +glPinArrayBlock(ch, pins, opins, nPins) + GCRChannel *ch; /* Channel pins belong to */ + GCRPin *pins; /* Processing this side of channel */ + GCRPin *opins; /* Pins on opposite side; used only if ch is a + * river-routing channel. + */ + int nPins; /* Number of internal pins (not counting pins[0]) */ +{ + bool changed, isRiver = (ch->gcr_type != CHAN_NORMAL); + GCRPin *pin, *opin, *linked; + GCRPin *lastPin; + + changed = FALSE; + lastPin = &pins[nPins]; + for (pin = pins + 1, opin = opins + 1; pin <= lastPin; pin++, opin++) + { + linked = pin->gcr_linked; + + /* Propagate blockages */ + if (pin->gcr_pId == GCR_BLOCKEDNETID) + { + if (linked && linked->gcr_pId == (GCRNet *) NULL) + { + linked->gcr_pFlags |= GCRBLK; + linked->gcr_pId = GCR_BLOCKEDNETID; + changed = TRUE; + } + if (isRiver && opin->gcr_pId == (GCRNet *) NULL) + opin->gcr_pId = GCR_BLOCKEDNETID, changed = TRUE; + } + + /* Propagate obstacle flags */ + if ((pin->gcr_pFlags & GCROBST) && linked) + linked->gcr_pFlags |= GCROBST; + } + + return changed; +} + +/* + * ---------------------------------------------------------------------------- + * + * GLLinkPins -- + * + * Link the "usable" pins along each side of a channel into a doubly-linked + * list headed by the zero-th pin along that side. Usable pins (for purposes + * of global routing) are those that are unassigned (gcr_pId == 0) and that + * have gcr_linked != NULL. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +GLLinkPins(ch) + GCRChannel *ch; +{ + glPinArrayLink(ch->gcr_tPins, ch->gcr_length); + glPinArrayLink(ch->gcr_bPins, ch->gcr_length); + glPinArrayLink(ch->gcr_lPins, ch->gcr_width); + glPinArrayLink(ch->gcr_rPins, ch->gcr_width); +} + +int +glPinArrayLink(pins, nPins) + GCRPin *pins; + int nPins; +{ + GCRPin *pin, *lastPin, *lastValid; + + lastPin = &pins[nPins]; + lastValid = pins; + lastValid->gcr_pPrev = lastValid->gcr_pNext = (GCRPin *) NULL; + for (pin = pins + 1; pin <= lastPin; pin++) + { + pin->gcr_pNext = pin->gcr_pPrev = (GCRPin *) NULL; + if (pin->gcr_linked && pin->gcr_pId == (GCRNet *) NULL) + { + lastValid->gcr_pNext = pin; + pin->gcr_pPrev = lastValid; + lastValid = pin; + } + if (DebugIsSet(glDebugID, glDebShowPins)) + glShowPin(pin); + } +} + +glShowPin(pin) + GCRPin *pin; +{ + char mesg[256]; + Rect r, area; + Point p; + + p = pin->gcr_point; + switch (pin->gcr_side) + { + case GEO_NORTH: + p.p_y = RTR_GRIDDOWN(p.p_y, RtrOrigin.p_y); + break; + case GEO_SOUTH: + p.p_y = RTR_GRIDUP(p.p_y, RtrOrigin.p_y); + break; + case GEO_EAST: + p.p_x = RTR_GRIDDOWN(p.p_x, RtrOrigin.p_x); + break; + case GEO_WEST: + p.p_x = RTR_GRIDUP(p.p_x, RtrOrigin.p_x); + break; + } + + r.r_ll = r.r_ur = p; + r.r_xtop += 4, r.r_ytop += 4; + + area = pin->gcr_ch->gcr_area; + (void) sprintf(mesg, + "ChanType=%d grid=(%d,%d) point=(%d,%d) Net=%d, linked=0x%x", + pin->gcr_ch->gcr_type, + pin->gcr_x, pin->gcr_y, + pin->gcr_point.p_x, pin->gcr_point.p_y, + pin->gcr_pId, pin->gcr_linked); + if (pin->gcr_pId || pin->gcr_linked == NULL) + (void) strcat(mesg, " **BLOCKED**"); + else DBWFeedbackAdd(&r, mesg, EditCellUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); +#ifdef notdef + nrShowRect(EditCellUse->cu_def, &r, STYLE_SOLIDHIGHLIGHTS); + nrMore(mesg); + nrShowRect(EditCellUse->cu_def, &r, STYLE_ERASEHIGHLIGHTS); +#endif /* notdef */ +} + +/* + * ---------------------------------------------------------------------------- + * + * GLFixStemPins -- + * + * Only some of the crossing points marked during stem assignment were + * actually used during global routing. The unused ones have gcr_pSeg + * equal to GCR_STEMSEGID and must be unmarked here (otherwise the channel + * router will try to route them!). + * + * Results: + * None. + * + * Side effects: + * For each pin on the boundary of 'ch' that is marked as in use + * (gcr_pId != 0 && gcr_pId != GCR_BLOCKEDNETID) and that has a segment + * id of GCR_STEMSEGID (gcr_pSeg == GCR_STEMSEGID), mark it as unused + * (gcr_pId == 0). + * + * ---------------------------------------------------------------------------- + */ + +int +GLFixStemPins(ch) + GCRChannel *ch; +{ + glPinArrayFixStems(ch->gcr_tPins, ch->gcr_length); + glPinArrayFixStems(ch->gcr_bPins, ch->gcr_length); + glPinArrayFixStems(ch->gcr_lPins, ch->gcr_width); + glPinArrayFixStems(ch->gcr_rPins, ch->gcr_width); +} + +int +glPinArrayFixStems(pins, nPins) + GCRPin *pins; + int nPins; +{ + GCRPin *pin, *lastPin; + + lastPin = &pins[nPins]; + for (pin = pins + 1; pin <= lastPin; pin++) + if (pin->gcr_pId + && pin->gcr_pId != GCR_BLOCKEDNETID + && pin->gcr_pSeg == GCR_STEMSEGID) + { + pin->gcr_pId = (GCRNet *) NULL; + } +} diff --git a/grouter/grouteTest.c b/grouter/grouteTest.c new file mode 100644 index 00000000..b54bcff3 --- /dev/null +++ b/grouter/grouteTest.c @@ -0,0 +1,598 @@ +/* + * grouteTest.c -- + * + * Testing code for the global router. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/grouter/grouteTest.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "textio/txcommands.h" +#include "utils/main.h" +#include "utils/utils.h" +#include "commands/commands.h" +#include "utils/malloc.h" +#include "utils/styles.h" +#include "utils/netlist.h" + +bool glInitialized = FALSE; + +ClientData glDebugID = 0; + +int glDebAllPoints = 0; +int glDebChan = 0; +int glDebCross = 0; +int glDebFast = 0; +int glDebHeap = 0; +int glDebHisto = 0; +int glDebLog = 0; +int glDebGreedy = 0; +int glDebMaze = 0; +int glDebNet = 0; +int glDebNewHeaps = 0; +int glDebPen = 0; +int glDebShowPins = 0; +int glDebStemsOnly = 0; +int glDebStraight = 0; +int glDebTiles = 0; +int glDebVerbose = 0; + +/* Statistics */ +int glCrossingsSeen; /* Total crossings seen */ +int glCrossingsAdded; /* Total crossings added to heap */ +int glCrossingsExpanded; /* Total crossings expanded from */ +int glCrossingsUsed; /* Total crossings used */ +int glGoodRoutes; /* Good point to point routes */ +int glBadRoutes; /* Bad point to point routes */ +int glNoRoutes; + +/* Used in debugging; if set, we only route a single net */ +char *glOnlyNet = NULL; + +/* + * Used to remember the number of frontier points visited, and the + * number of points removed from the top of the heap, for each two + * point net routed. + */ +GlNetHisto *glNetHistoList = NULL; + +/* Forward declarations */ +void GlInit(); +void glShowCross(); + + +/* + * ---------------------------------------------------------------------------- + * + * GlTest -- + * + * Command interface for testing the global router. + * + * Results: + * None. + * + * Side effects: + * Depends on the command; see below. + * + * ---------------------------------------------------------------------------- + */ + +void +GlTest(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int glDebugSides(); + typedef enum { CLRDEBUG, ONLYNET, SETDEBUG, SHOWDEBUG, SIDES } cmdType; + Rect editArea; + int n; + static struct + { + char *cmd_name; + cmdType cmd_val; + } cmds[] = { + "clrdebug", CLRDEBUG, + "onlynet", ONLYNET, + "setdebug", SETDEBUG, + "showdebug", SHOWDEBUG, + "sides", SIDES, + 0 + }; + + if (!glInitialized) + GlInit(); + + if (cmd->tx_argc == 1) + { + TxError("Must give subcommand\n"); + goto badCmd; + } + + n = LookupStruct(cmd->tx_argv[1], (LookupTable *) cmds, sizeof cmds[0]); + if (n < 0) + { + TxError("Unrecognized subcommand: %s\n", cmd->tx_argv[1]); +badCmd: + TxError("Valid subcommands:"); + for (n = 0; cmds[n].cmd_name; n++) + TxError(" %s", cmds[n].cmd_name); + TxError("\n"); + return; + } + + switch (cmds[n].cmd_val) + { + case SETDEBUG: + DebugSet(glDebugID, cmd->tx_argc - 2, &cmd->tx_argv[2], TRUE); + break; + case CLRDEBUG: + DebugSet(glDebugID, cmd->tx_argc - 2, &cmd->tx_argv[2], FALSE); + break; + case SHOWDEBUG: + DebugShow(glDebugID); + break; + case SIDES: + if (!ToolGetEditBox(&editArea)) return; + n = -1; + if (cmd->tx_argc > 2) + { + if (!StrIsInt(cmd->tx_argv[2])) + { + TxError("Minimum channel width must be numeric\n"); + break; + } + n = atoi(cmd->tx_argv[2]); + } + (void) rtrEnumSides(EditCellUse, &editArea, n, + glDebugSides, (ClientData) NULL); + case ONLYNET: + if (cmd->tx_argc == 2) + { + if (glOnlyNet) + TxPrintf("Routing only net: %s\n", glOnlyNet); + else + TxPrintf("Routing all nets.\n"); + } + else if (cmd->tx_argc == 3) + { + if (strcmp(cmd->tx_argv[2], "-") == 0) + { + if (glOnlyNet) + { + freeMagic(glOnlyNet); + glOnlyNet = NULL; + } + TxPrintf("Routing all nets.\n"); + } + else + { + (void) StrDup(&glOnlyNet, cmd->tx_argv[2]); + TxPrintf("Routing only net: %s\n", glOnlyNet); + } + } + else TxError("Usage: *groute onlynet [net | -]\n"); + break; + } +} + +int +glDebugSides(side) + Side *side; +{ + char mesg[256]; + CellDef *def = EditCellUse->cu_def; + Rect r; + + GeoTransRect(&side->side_trans, &side->side_search, &r); + ShowRect(def, &r, STYLE_SOLIDHIGHLIGHTS); + (void) sprintf(mesg, "SEARCH %d %d %d %d\n", + r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop); + TxMore(mesg); + ShowRect(def, &r, STYLE_ERASEHIGHLIGHTS); + + GeoTransRect(&side->side_trans, &side->side_used, &r); + ShowRect(def, &r, STYLE_MEDIUMHIGHLIGHTS); + (void) sprintf(mesg, "USED %d %d %d %d\n", + r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop); + TxMore(mesg); + ShowRect(def, &r, STYLE_ERASEHIGHLIGHTS); + + (void) TxPrintf("--------\n"); + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * GlInit -- + * + * One-time-only initialization for the global router. + * Called after technology initialization. + * + * Results: + * None. + * + * Side effects: + * Register ourself with the debug module and list all + * debugging flags. + * + * ---------------------------------------------------------------------------- + */ + +void +GlInit() +{ + int n; + static struct + { + char *di_name; + int *di_id; + } dflags[] = { + "allpoints", &glDebAllPoints, + "chan", &glDebChan, + "cross", &glDebCross, + "fast", &glDebFast, + "heap", &glDebHeap, + "histo", &glDebHisto, + "log", &glDebLog, + "greedy", &glDebGreedy, + "maze", &glDebMaze, + "net", &glDebNet, + "newheaps", &glDebNewHeaps, + "penalties", &glDebPen, + "showpins", &glDebShowPins, + "stemsonly", &glDebStemsOnly, + "straight", &glDebStraight, + "tiles", &glDebTiles, + "verbose", &glDebVerbose, + 0 + }; + + if (glInitialized) + return; + + glInitialized = TRUE; + + /* Register ourselves with the debugging module */ + glDebugID = DebugAddClient("grouter", sizeof dflags/sizeof dflags[0]); + for (n = 0; dflags[n].di_name; n++) + *(dflags[n].di_id) = DebugAddFlag(glDebugID, dflags[n].di_name); +} + +/* + * ---------------------------------------------------------------------------- + * + * glShowPath -- + * + * Display the crossing points along an entire path for debugging. + * The type of crossing point is indicated by 'kind'. + * + * Results: + * None. + * + * Side effects: + * Causes redisplay. + * + * ---------------------------------------------------------------------------- + */ + +void +glShowPath(dest, root, kind) + GlPoint *dest, *root; + int kind; +{ + static NetId dummyId = { 0, 0 }; + GlPoint *temp; + + for (temp = dest; temp != root; temp = temp->gl_path) + glShowCross(temp->gl_pin, dummyId, kind); +} + +/* + * ---------------------------------------------------------------------------- + * + * glShowCross -- + * + * Display a crossing point for debugging. + * Two kinds of crossing points can be shown: CROSS_TEMP, which + * is only being considered, and CROSS_PERM, which has been permanently + * assigned to a net. In addition, CROSS_ERASE will cause the crossing + * point to be erased. + * + * Results: + * None. + * + * Side effects: + * Causes redisplay. + * + * ---------------------------------------------------------------------------- + */ + +void +glShowCross(pin, netId, kind) + GCRPin *pin; /* Pin itself */ + NetId netId; /* Identifies net and segment for this pin */ + int kind; /* Determines kind of display; see above */ +{ + char *name, name1[1024], name2[1024]; + int style; + Rect r; + + switch (kind) + { + case CROSS_TEMP: + name = "temp"; + style = STYLE_MEDIUMHIGHLIGHTS; + break; + case CROSS_PERM: + name = "PERM"; + style = STYLE_SOLIDHIGHLIGHTS; + break; + case CROSS_ERASE: + name = (char *) NULL; + style = STYLE_ERASEHIGHLIGHTS; + break; + } + + if (name && DebugIsSet(glDebugID, glDebMaze)) + { + (void) strcpy(name1, NLNetName(pin->gcr_pId)); + (void) strcpy(name2, NLNetName(netId.netid_net)); + TxPrintf("%s (%d,%d), Net %s/%d->%s/%d, Ch %d\n", + name, pin->gcr_point.p_x, pin->gcr_point.p_y, + name1, pin->gcr_pSeg, name2, netId.netid_seg, pin->gcr_ch); + } + + r.r_ll = r.r_ur = pin->gcr_point; + r.r_xtop += RtrMetalWidth; + r.r_ytop += RtrMetalWidth; + ShowRect(EditCellUse->cu_def, &r, style); +} + +/* + * ---------------------------------------------------------------------------- + * + * glHistoAdd -- + * + * Remember the number of heap, frontier, and starting points + * used during a given route by adding them to the GlNetHisto + * list. + * + * Results: + * None. + * + * Side effects: + * Allocates memory; prepends a new entry to glNetHistoList. + * + * ---------------------------------------------------------------------------- + */ + +void +glHistoAdd(heapPtsBefore, frontierPtsBefore, startPtsBefore) + int heapPtsBefore, frontierPtsBefore, startPtsBefore; +{ + GlNetHisto *gh; + + gh = (GlNetHisto *) mallocMagic((unsigned) (sizeof (GlNetHisto))); + gh->glh_heap = glCrossingsExpanded - heapPtsBefore; + gh->glh_frontier = glCrossingsAdded - frontierPtsBefore; + gh->glh_start = startPtsBefore; + gh->glh_next = glNetHistoList; + glNetHistoList = gh; +} + +/* + * ---------------------------------------------------------------------------- + * + * glHistoDump -- + * + * Dump the information accumulated by glHistoAdd() above + * to the file HISTO.out in the current directory. + * + * Results: + * None. + * + * Side effects: + * Creates HISTO.out. + * + * ---------------------------------------------------------------------------- + */ + +void +glHistoDump() +{ + static char hname[] = "HISTO.out"; + int lastsize, count, total; + GlNetHisto *gh; + Heap histoHeap; + HeapEntry entry; + FILE *fp; + + fp = fopen(hname, "w"); + if (fp == NULL) + { + perror(hname); + return; + } + + /* Raw data */ + fprintf(fp, "--------- raw data ---------\n"); + fprintf(fp, "%9s %9s %9s\n", "HEAP", "FRONTIER", "START"); + for (gh = glNetHistoList; gh; gh = gh->glh_next) + { + fprintf(fp, "%9d %9d %9d\n", + gh->glh_heap, gh->glh_frontier, gh->glh_start); + } + + /* Output sorted by number of heap points */ + fprintf(fp, "--------- by heap points ---------\n"); + HeapInit(&histoHeap, 128, FALSE, FALSE); + for (gh = glNetHistoList; gh; gh = gh->glh_next) + HeapAddInt(&histoHeap, gh->glh_heap, (char *) gh); + count = lastsize = total = 0; + while (HeapRemoveTop(&histoHeap, &entry)) + { + gh = (GlNetHisto *) entry.he_id; + if (gh->glh_heap != lastsize) + { + if (count > 0) + fprintf(fp, "%d: %d\n", lastsize, count); + lastsize = gh->glh_heap; + count = 0; + } + count++, total++; + } + HeapKill(&histoHeap, (void (*)()) NULL); + if (count > 0) + fprintf(fp, "%d: %d\n", lastsize, count); + fprintf(fp, "TOTAL: %d\n", total); + + /* Output sorted by number of frontier points */ + fprintf(fp, "--------- by frontier points ---------\n"); + HeapInit(&histoHeap, 128, FALSE, FALSE); + for (gh = glNetHistoList; gh; gh = gh->glh_next) + HeapAddInt(&histoHeap, gh->glh_frontier, (char *) gh); + count = lastsize = total = 0; + while (HeapRemoveTop(&histoHeap, &entry)) + { + gh = (GlNetHisto *) entry.he_id; + if (gh->glh_frontier != lastsize) + { + if (count > 0) + fprintf(fp, "%d: %d\n", lastsize, count); + lastsize = gh->glh_frontier; + count = 0; + } + count++, total++; + } + HeapKill(&histoHeap, (void (*)()) NULL); + if (count > 0) + fprintf(fp, "%d: %d\n", lastsize, count); + fprintf(fp, "TOTAL: %d\n", total); + + /* Free memory */ + for (gh = glNetHistoList; gh; gh = gh->glh_next) + freeMagic((char *) gh); + glNetHistoList = NULL; + + /* Done */ + (void) fclose(fp); +} + +/* + * ---------------------------------------------------------------------------- + * + * glStatsInit -- + * + * Initialize statistics and debugging info for this + * global routing session. + * + * Results: + * None. + * + * Side effects: + * Zeroes lots of global counters. + * Zeroes glNetHistoList. + * May create the crossings log file ("CROSSINGS.log") and + * leave glLogFile pointing to the open file. + * + * ---------------------------------------------------------------------------- + */ + +void +glStatsInit() +{ + char *logFileName = "CROSSINGS.log"; + + glCrossingsSeen = 0; + glCrossingsAdded = 0; + glCrossingsExpanded = 0; + glCrossingsUsed = 0; + glGoodRoutes = 0; + glBadRoutes = 0; + glNoRoutes = 0; + glNumTries = 0; + + glNetHistoList = NULL; + if (DebugIsSet(glDebugID, glDebLog)) + { + glLogFile = fopen(logFileName, "w"); + if (glLogFile == (FILE *) NULL) + perror(logFileName); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * glStatsDone -- + * + * Print statistics accumulated during this routing session. + * + * Results: + * None. + * + * Side effects: + * Prints statistics. + * + * ---------------------------------------------------------------------------- + */ + +void +glStatsDone(numNets, numTerms) + int numNets; + int numTerms; +{ + + if (DebugIsSet(glDebugID, glDebVerbose)) + { + TxPrintf("\n"); + TxPrintf(" %d nets, %d terminals.\n", numNets, numTerms); + TxPrintf(" %d good, %d bad two-point routes,\n", + glGoodRoutes, glBadRoutes); + TxPrintf(" %d failed when considering penalties,\n", glNoRoutes); + TxPrintf(" %d total connections.\n", glGoodRoutes + glBadRoutes); + TxPrintf(" %d crossings seen, %d added to heap.\n", + glCrossingsSeen, glCrossingsAdded); + TxPrintf(" %d crossings %d used.\n", + glCrossingsExpanded, glCrossingsUsed); + } + + if (DebugIsSet(glDebugID, glDebLog) && glLogFile) + (void) fclose(glLogFile); + if (DebugIsSet(glDebugID, glDebHisto)) + glHistoDump(); +} diff --git a/grouter/grouteTile.c b/grouter/grouteTile.c new file mode 100644 index 00000000..774f95f3 --- /dev/null +++ b/grouter/grouteTile.c @@ -0,0 +1,394 @@ +/* grouteTile.c - + * + * Global signal router code for tile and channel related things. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char sccsid[] = "@(#)grouteTile.c 4.3 MAGIC (Berkeley) 10/31/85"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "debug/debug.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "utils/styles.h" +#include "textio/textio.h" + +bool GlDebugCrossings = FALSE; + +#define isSpaceTile(tile) (TiGetBody(tile) == NULL) + + +/* + * ---------------------------------------------------------------------------- + * + * glAdjacentChannel -- + * + * Figure out which channel borders the given channel at the given + * point. If the given channel is NULL, then assume the point is at + * the edge of a cell, and return the channel adjacent to the cell. + * + * Results: + * Pointer to the adjacent channel, or NULL if none exists. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +GCRChannel * +glAdjacentChannel(ch, point) + GCRChannel *ch; /* The tile corresponding to a channel */ + Point *point; /* A point somewhere on the channel edge */ +{ + Point p; + int side; + + ASSERT(ch!=(GCRChannel *) NULL, "Null channel in glAdjacentChannel"); + side = glPointToSide(ch, point); + + p = * point; + switch(side) + { + case GEO_NORTH: + case GEO_EAST: + break; + case GEO_SOUTH: + p.p_y--; + break; + case GEO_WEST: + p.p_x--; + break; + default: + ASSERT(FALSE, "glAdjacentChannel point not on channel"); + return((GCRChannel *) NULL); + break; + } + + return (glTileToChannel(TiSrPointNoHint(RtrChannelPlane, &p))); +} + +/* + * ---------------------------------------------------------------------------- + * + * glBadChannel -- + * + * Decide if a prospective channel is okay to use in global routing + * propagation. If it creates a loop for the particular path under + * investigation, then forget it. If it doesn't exist, then forget it. + * + * Results: + * FALSE if the channel is okay to use, otherwise TRUE. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +glBadChannel(oldCh, newCh, entryPt) + GCRChannel *oldCh; /* The current channel */ + GCRChannel *newCh; /* See if this new one is okay to use */ + GlPoint *entryPt; /* List of previously used points */ +{ + GlPoint *temp; + + /* Reject a null channel */ + if ((oldCh == (GCRChannel *) NULL) || (newCh == (GCRChannel *) NULL)) + return (TRUE); + + /* Reject the channel if using it creates a loop in the routing path */ + for (temp = entryPt; temp != (GlPoint *) NULL; temp = temp->gl_parent) + if (temp->gl_ch == newCh) + return (TRUE); + + return (FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * glDebug -- + * + * Code to display crossing points on the screen. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +glDebug(point, text, value, size) + Point *point; /* Location to be marked */ + char *text; /* Text to associate with error paint */ + int value; /* An integer value to go into the text */ + int size; /* How big to make the error paint box */ +{ + char buffer1[1024], buffer2[1024]; + Rect area; + + if (!GlDebugCrossings) + return; + + (void) strcpy(buffer1, text); + (void) sprintf(buffer2, "(value = %d)", value); + (void) strcat(buffer1, buffer2); + area.r_ll.p_x = point->p_x - size; + area.r_ur.p_x = point->p_x + size; + area.r_ll.p_y = point->p_y - size; + area.r_ur.p_y = point->p_y + size; + DBWFeedbackAdd(&area, buffer1, EditCellUse->cu_def, 1, + STYLE_PALEHIGHLIGHTS); + GrFlush(); + (void) sprintf(buffer2, "%s --more--", buffer1); + (void) TxGetLinePrompt(buffer1, sizeof buffer1, buffer2); + if (buffer1[0] == 'q') + GlDebugCrossings = FALSE; + TxPrintf("\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * glPointToChannel -- + * + * Given a point and a direction, return a pointer to the channel + * adjacent to the given point, in the given direction. The point + * must be on the edge of a channel. If on the edge of a cell, the + * point location must be the modified location returned by RtrStemTip. + * + * Results: + * Pointer to the channel. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +GCRChannel * +glPointToChannel(point, dir) + Point *point; /* The point from which the channel is found */ + int dir; /* The direction in which the search goes */ +{ + Point p; + + p = *point; + switch (dir) + { + case GEO_NORTH: + case GEO_EAST: + break; + case GEO_SOUTH: + p.p_y--; + break; + case GEO_WEST: + p.p_x--; + break; + default: + ASSERT(FALSE, "glPointToChannel: bad direction argument"); + return ((GCRChannel *) NULL); + } + return (glTileToChannel(TiSrPointNoHint(RtrChannelPlane, &p))); +} + +/* + * ---------------------------------------------------------------------------- + * + * glPointToSide -- + * + * Given a point somewhere on the perimeter of a channel, determine + * which side it is on. The channel is given to prevent ambiguity, + * since the point may fall on a border between two channels. + * + * Results: + * The compass direction corresponding to the side of the channel on + * which the point lies. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +glPointToSide(ch, pt) + GCRChannel * ch; /* Channel containing the given point */ + Point * pt; /* The point on some side of the channel*/ +{ + + /* The point is on the left */ + if (ch->gcr_area->r_xbot == pt->p_x) + return (GEO_WEST); + + /* The point is on the bottom */ + if (ch->gcr_area->r_ybot == pt->p_y) + return (GEO_SOUTH); + + /* The point is on the right */ + if (ch->gcr_area->r_xtop == pt->p_x) + return (GEO_EAST); + + /* The point is on the top */ + if (ch->gcr_area->r_ytop == pt->p_y) + return (GEO_NORTH); + + ASSERT(FALSE, "glPointToSide point not on edge"); + return (GEO_CENTER); +} + +/* + * ---------------------------------------------------------------------------- + * + * glSide -- + * + * Determine which side of a cell a terminal label is on by looking on + * the channel plane for channel tiles in each of the quadrants. A + * terminal label must not fall on space or on a corner. It must lie + * on a flat edge of a cell tile. + * + * Are all these calls to TiSrPoint really necessary? I think so, + * because a label might fall on the edge of a particular tile but + * still appear over contiguous cell tiles. + * + * Results: + * A direction GEO_NORTH, SOUTH, EAST, WEST, or CENTER if internal or + * a corner. This indicates the side of the cell on which the terminal + * lies. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +glSide(point) + Point *point; /* The lower left point of the label rectangle */ +{ + int glSrFunc(); + Tile *t; + Point p; + + p = *point; + t = TiSrPoint((Tile *) NULL, RtrChannelPlane, &p); + + if(TiGetBody(t) != NULL) /* _?|X_ */ + { /* ?|? */ + p.p_x--; + t = TiSrPoint(t, RtrChannelPlane, &p); + if(TiGetBody(t) != NULL) /* _X|X_ */ + { /* ?|? */ + p.p_y--; + t = TiSrPoint(t, RtrChannelPlane, &p); + if(TiGetBody(t) != NULL) /* _X|X_ */ + return(GEO_CENTER); /* X|? */ + p.p_x++; + t = TiSrPoint(t, RtrChannelPlane, &p); + if(TiGetBody(t) != NULL) /* _X|X_ */ + return(GEO_CENTER); /* |X */ + else return(GEO_SOUTH); + } + else /* __|X_ */ + { /* ?|? */ + p.p_y--; + t = TiSrPoint(t, RtrChannelPlane, &p); + if(TiGetBody(t) != NULL) /* __|X_ */ + return(GEO_CENTER); /* X|? */ + p.p_x++; + t = TiSrPoint(t, RtrChannelPlane, &p); + if(TiGetBody(t) != NULL) /* __|X_ */ + return(GEO_WEST); /* |X */ + } + } + else /* Forget about S or W */ + { + p.p_x--; + t = TiSrPoint(t, RtrChannelPlane, &p); + if(TiGetBody(t) != NULL) /* _X|__ */ + { /* ?|? */ + p.p_y--; + t = TiSrPoint(t, RtrChannelPlane, &p); + if(TiGetBody(t) == NULL) /* _X|__ */ + return(GEO_CENTER); /* |? */ + p.p_x++; + t = TiSrPoint(t, RtrChannelPlane, &p); + if(TiGetBody(t) != NULL) /* _X|__ */ + return(GEO_CENTER); /* X|X */ + else return(GEO_EAST); + } + else /* __|__ */ + { /* ?|? */ + p.p_y--; + t = TiSrPoint(t, RtrChannelPlane, &p); + if(TiGetBody(t) == NULL) /* __|__ */ + return(GEO_CENTER); /* |? */ + p.p_x++; + t = TiSrPoint(t, RtrChannelPlane, &p); + if(TiGetBody(t) != NULL) /* __|__ */ + return(GEO_NORTH); /* X|X */ + } + } + return(GEO_CENTER); +} + +/* + * ---------------------------------------------------------------------------- + * + * glTileToChannel -- + * + * Figure out which channel corresponds to the given tile. + * + * Results: + * Pointer to the channel. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +GCRChannel * +glTileToChannel(tile) + Tile *tile; /* Should point to a channel (space) tile */ +{ + HashEntry *he; + + if (!isSpaceTile(tile)) + return ((GCRChannel *) NULL); + he = HashLookOnly(&RtrTileToChannel, (char *) tile); + if (he == (HashEntry *) NULL) + return ((GCRChannel *) NULL); + return (GCRChannel *) HashGetValue(he); +} diff --git a/grouter/grouter.h b/grouter/grouter.h new file mode 100644 index 00000000..1e1de64a --- /dev/null +++ b/grouter/grouter.h @@ -0,0 +1,267 @@ +/* + * grouter.h -- + * + * Header file for the global router. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * sccsid "@(#)grouter.h 4.5 MAGIC (Berkeley) 10/31/85" + */ + +#ifndef _GROUTER_H +#define _GROUTER_H + +#include "router/router.h" +#include "gcr/gcr.h" + +/* + * Density means the number of signals passing through a particular + * point of a channel. Since there are two directions in which + * signals can run, there are two density maps: one for the number + * of signals crossing horizontally across each vertical column + * (d_RowsByCol), and the other for the number of signals crossing + * vertically across each horizontal row (d_ColsByRow). The maximum + * density is just the maximum value for each of these two maps. + * The indices of the two maps parallel those of the channel's + * columns and rows, which include the pseudo-columns/rows at + * the two ends of the channel as well as the ones in the interior. + * However, the zero-th and last entries of the two maps are ignored. + */ +typedef struct +{ + short *dm_value; /* Contains dm_size elements, but element 0 + * is unused. + */ + int dm_size; /* Number of elements in dm_value array */ + int dm_max; /* Maximum over dm_value[1 .. dm_size-1] */ + int dm_cap; /* Capacity: if dm_value[i] exceeds dm_cap, + * then the channel is overcommitted at + * position (row or column) i. + */ +} DensMap; + +/* + * Each channel's gcr_client field points to one of these structures + * during global routing. The information contained here includes + * density maps and net penalties. The net penalty gc_penalty is + * set differently for each net. + */ +typedef struct +{ + DensMap gc_prevDens[2];/* Density prior to global routing */ + DensMap gc_postDens[2];/* Density including routed signals */ + struct czone *gc_penList; /* Penalties and areas applicable to + * this channel. Updated for each + * net being routed. + */ +} GlobChan; + +/* + * Each net's nnet_cdata field will point to one of the following structures, + * which is used to remember several pieces of information. The primary + * one, which is the result of the penalty computation, is nc_pens, a + * NULL-terminated list of NetPen structs that will be used during the + * regular global routing phase. + * + * During the penalty computation, nc_paths (a NULL-terminated List of + * the head GlPoint in each of several paths) is used to point to all + * of the GlPoints that comprise the global routing of the net. + */ +typedef struct +{ + /* Holds onto previous nnet_cdata field; restored after global routing */ + ClientData nc_saveClient; + + /* The result of the penalty computation phase */ + struct czone *nc_pens; /* Penalty for each congested zone */ + + /* Used only during the penalty computation phase */ + struct list *nc_paths; /* List of heads of GlPoint paths */ +} NetClient; + +/* + * The following structure represents a congested region of a channel. + * Such a region is one where the number of nets that want to pass + * through it is greater than the number of available tracks or + * columns. There can be two kinds of region: row or column. + * The cz_type field tells which kind of region it is, and cz_lo + * and cz_hi are the pin coordinates (not the edit coordinates) + * of the range of pins this congested zone applies to. + * + * A congested zone is as large a contiguous region of overcommitted + * tracks or columns as possible. + * + * The cz_penalty field is used in several different ways. During the + * penalty computation phase of global routing, it is used to store the + * incremental cost for a net to avoid this congested region. In the + * nc_pens list of a NetClient (after penalties have been computed), + * it represents the penalty that should be applied to a net for + * using this congested zone. + */ +typedef struct czone +{ + struct chan *cz_chan; /* Which channel is affected */ + int cz_type; /* See below */ + int cz_lo, cz_hi; /* Inclusive range of pin coordinates + * that are congested. + */ + int cz_penalty; /* Penalty for this net using cz_chan */ + struct netset *cz_nets; /* Nets passing through here */ + struct czone *cz_next; /* Next penalty on list */ +} CZone; + +/* Types of congested zones */ +#define CZ_ROW 0 /* Cz_lo and cz_hi are row coordinates */ +#define CZ_COL 1 /* Cz_lo and cz_hi are column coordinates */ + +/* + * Used in building up sets of nets affected by a given congested zone. + * It is used to store the cost of that net avoiding that zone. + */ +typedef struct netset +{ + struct nlNet *ns_net; /* Net belonging to the set */ + int ns_cost; /* Cost of avoiding our CZone */ + struct netset *ns_next; /* Next in NULL-terminated list */ +} NetSet; + +/* + * In order to prevent the channel router from trying to connect two + * independent segments of a net that both happen to pass through a + * channel, if they are already connected elsewhere, the global router + * assigns a "segment" identifier to each distinct two-point component + * of the global route. The following structure bundles together a + * unique identifier for a net with this segment identifier, using + * this information to set up the pins for channel routing. + */ +typedef struct +{ + struct nlNet *netid_net; + int netid_seg; +} NetId; + +#define SAMENET(p, nId, sId) \ + ( ((NLNet *) (p)->gcr_pId == (nId)) && (p)->gcr_pSeg == (sId)) + +/* + * -------------------------------------------------------------------- + * + * GlPoint -- + * + * This is the key data structure used by the global router. + * It is used to remember intermediate crossing points along a path + * from a source terminal to a destination terminal. Each GlPoint + * points back (via gl_path) to the point from which it was reached. + * This structure forms a forest of inverted trees, rooted at each + * of the starting points for the route. The leaves in these inverted + * trees (those GlPoints that aren't pointed to by any others) represent + * partial paths that may eventually be extended to the destination + * point for a global route. The cost stored in each GlPoint tells + * how expensive it was to reach that GlPoint from the starting point + * of the path used to reach it. + * + * The coordinates of the crossing point and the channel containing it + * are stored in the GCRPin pointed to by gl_pin. + * + * -------------------------------------------------------------------- + */ + +typedef struct glpoint +{ + GCRPin *gl_pin; /* Crossing point */ + Tile *gl_tile; /* Tile for gl_pin in glChanPlane */ + struct glpoint *gl_path; /* Point we came from */ + int gl_cost; /* Cost of path to get here */ +} GlPoint; + +/* + * -------------------------------------------------------------------- + * To allow easy freeing of GlPoints, we allocate them from our own + * special heap which can be freed in one fell swoop. + * -------------------------------------------------------------------- + */ +#define POINTSPERSEG 200 /* Number of GlPoints per segment */ + +typedef struct glPage +{ + struct glPage *glp_next; + int glp_free; + GlPoint glp_array[POINTSPERSEG]; +} GlPage; + +/* First, last, and current GlPages on list for allocating GlPoints */ +extern GlPage *glPathFirstPage; +extern GlPage *glPathLastPage; +extern GlPage *glPathCurPage; + +/* -------------------------- Miscellaneous --------------------------- */ + +/* TRUE if pin is available for use as a crossing point */ +#define PINOK(pin) ((pin)->gcr_pId == NULL && (pin)->gcr_linked) + +/* ------- Plane holding channel structure during global routing ------ */ + +/* + * Types of tiles in glChanPlane are CHAN_NORMAL, CHAN_HRIVER, CHAN_VRIVER, + * or CHAN_BLOCKED (defined here). + */ +#define CHAN_BLOCKED 3 /* Unusable area */ + +/* Macro to test a tile for penetrability */ +#define NOTBLOCKED(tp) (TiGetType(tp) != CHAN_BLOCKED) + +/* Plane to hold channel information */ +extern Plane *glChanPlane; + +/* Dummy celldef whose PL_DRC_CHECK plane is identical to glChanPlane above */ +extern CellDef *glChanDef; +extern CellUse *glChanUse; + +/* ------------------------ Intramodule exports ----------------------- */ + + /* Internal procedures */ +GlPoint *glPathNew(); +GlPoint *glPathCopyPerm(); +GlPoint *glProcessLoc(); +Tile *glChanPinToTile(); +void glCrossMark(); + + /* Penalties for crossings */ +extern int glJogPenalty; +extern int glObsPenalty1; +extern int glObsPenalty2; +extern int glNbrPenalty1; +extern int glNbrPenalty2; +extern int glOrphanPenalty; +extern int glChanPenalty; +extern bool glPenaltiesScaled; + + /* Statistics */ +extern int glCrossingsUsed; +extern int glCrossingsAdded; +extern int glCrossingsExpanded; +extern int glCrossingsSeen; +extern int glGoodRoutes; +extern int glBadRoutes; +extern int glNoRoutes; + + /* Used when finding a global signal path */ +extern Heap glMazeHeap; /* Search point heap */ + + /* Debugging information */ +extern bool glInitialized; /* TRUE if registered with debug module */ +extern ClientData glDebugID; /* Our identity with the debugging module */ +#include "grouteDebug.h" /* Can add flags without total recompile */ + +#endif /* _GROUTER_H */ diff --git a/irouter/Depend b/irouter/Depend new file mode 100644 index 00000000..46a00038 --- /dev/null +++ b/irouter/Depend @@ -0,0 +1,34 @@ +irCommand.o: irCommand.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/hash.h ../tiles/tile.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../graphics/graphics.h ../windows/windows.h ../dbwind/dbwind.h \ + ../dbwind/dbwtech.h ../textio/txcommands.h ../utils/main.h \ + ../utils/utils.h ../commands/commands.h ../utils/styles.h \ + ../utils/malloc.h ../utils/list.h ../mzrouter/mzrouter.h \ + ../irouter/irouter.h ../irouter/irInternal.h ../irouter/irDebug.h +irMain.o: irMain.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../drc/drc.h ../select/select.h \ + ../utils/signals.h ../textio/textio.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../debug/debug.h ../utils/undo.h \ + ../textio/txcommands.h ../utils/malloc.h ../utils/list.h \ + ../mzrouter/mzrouter.h ../irouter/irouter.h ../irouter/irInternal.h \ + ../mzrouter/mzrouter.h ../irouter/irDebug.h +irRoute.o: irRoute.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../tiles/tile.h ../database/database.h ../drc/drc.h ../textio/textio.h \ + ../windows/windows.h ../utils/main.h ../dbwind/dbwind.h ../debug/debug.h \ + ../utils/undo.h ../utils/signals.h ../utils/malloc.h ../utils/list.h \ + ../utils/geofast.h ../utils/touchingtypes.h ../select/select.h \ + ../mzrouter/mzrouter.h ../irouter/irouter.h ../irouter/irInternal.h \ + ../mzrouter/mzrouter.h ../irouter/irDebug.h +irTestCmd.o: irTestCmd.c ../utils/magic.h ../utils/geometry.h \ + ../utils/hash.h ../tiles/tile.h ../database/database.h \ + ../utils/signals.h ../textio/textio.h ../irouter/irouter.h \ + ../graphics/graphics.h ../windows/windows.h ../dbwind/dbwind.h \ + ../dbwind/dbwtech.h ../textio/txcommands.h ../utils/main.h \ + ../utils/utils.h ../commands/commands.h ../utils/styles.h \ + ../utils/malloc.h ../utils/list.h ../mzrouter/mzrouter.h \ + ../irouter/irInternal.h ../mzrouter/mzrouter.h ../irouter/irDebug.h +irUtils.o: irUtils.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../utils/list.h \ + ../mzrouter/mzrouter.h ../irouter/irouter.h ../irouter/irInternal.h \ + ../irouter/irDebug.h diff --git a/irouter/Makefile b/irouter/Makefile new file mode 100644 index 00000000..e2488397 --- /dev/null +++ b/irouter/Makefile @@ -0,0 +1,10 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/irouter/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +MODULE = irouter +MAGICDIR = .. +SRCS = irCommand.c irMain.c irRoute.c irTestCmd.c irUtils.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/irouter/irCommand.c b/irouter/irCommand.c new file mode 100644 index 00000000..700ba795 --- /dev/null +++ b/irouter/irCommand.c @@ -0,0 +1,2670 @@ +/* + * irCommand.c -- + * + * Command interface for interactive router. This file processes command + * lines beginning with the `iroute' command. + * + * (The "wizard" command, `*iroute', for testing, debugging, etc., + * is processed in irTestCmd.c.) + * + * ********************************************************************* + * * Copyright (C) 1987, 1990 Michael H. Arnold, Walter S. Scott, and * + * * the Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/irouter/irCommand.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "dbwind/dbwtech.h" +#include "textio/txcommands.h" +#include "utils/main.h" +#include "utils/utils.h" +#include "commands/commands.h" +#include "utils/styles.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "mzrouter/mzrouter.h" +#include "irouter/irouter.h" +#include "irouter/irInternal.h" + +/* window command issued to */ +static MagWindow *irWindow; + +/* Subcommand table - declared here since its referenced before defined */ +typedef struct +{ + char *sC_name; /* name of iroute subcommand */ + void (*sC_proc)(); /* Procedure implementing this subcommand */ + char *sC_commentString; /* describes subcommand */ + char *sC_usage; /* command syntax */ + +} SubCmdTableE; +extern SubCmdTableE irSubcommands[]; + + +/* + * ---------------------------------------------------------------------------- + * + * irSetNoisyAutoInt + * + * Set integer parameter, interpeting the string "AUTOMATIC" (or prefix) + * as -1. + * + * Results: + * None. + * + * Side effects: + * If valueS is a nonnull string, interpret and set parm + * accordingly. + * + * If valueS is null, the parameter value is left unaltered. + * + * If file is nonnull parameter value is written to file. + * + * If file is null, parameter value is written to magic text window via + * TxPrintf + * + * If file is (FILE *)1, parameter value is returned as a Tcl object + * + * ---------------------------------------------------------------------------- + */ + +void +irSetNoisyAutoInt(parm, valueS, file) + int *parm; + char *valueS; + FILE *file; +{ + int which; + + /* special value Table */ +#define V_AUTOMATIC -1 + static struct + { + char *sv_name; /* name */ + int sv_type; + } specialValues[] = { + "automatic", V_AUTOMATIC, + 0 + }; + + /* If value non-null set parm */ + if(valueS!=NULL) + { + int i; + + /* check if special value */ + which = LookupStruct( + valueS, + (char **) specialValues, + sizeof specialValues[0]); + + if(which == -1) + { + TxError("Ambiguous value: '%s'\n",valueS); + TxError("Value must be 'AUTOMATIC', or a nonnegative integer\n"); + return; + } + else if (which >= 0 ) + { + /* special value */ + int type = specialValues[which].sv_type; + + if(type == V_AUTOMATIC) + { + *parm = -1; + } + else + { + /* should not ever get here */ + ASSERT(FALSE,"irSetNoisyAutoInt"); + } + } + else if(StrIsInt(valueS) && (i=atoi(valueS))>=0) + { + *parm = i; + } + else + { + TxError("Bad value: \"%s\"\n", valueS); + TxError("Value must be 'AUTOMATIC', or a nonnegative integer\n"); + return; + } + } + + /* Print parm value */ + if(file) + { + if(*parm == -1) + { + fprintf(file,"AUTOMATIC"); + } + else + { + fprintf(file, "%8d ",*parm); + } + } + else + { + if(*parm == -1) + { + TxPrintf("AUTOMATIC"); + } + else + { + TxPrintf("%8d ",*parm); + } + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irLSet -- + * + * Set and display Route Layer parameter . + * + * Results: + * None. + * + * Side effects: + * Call low level routine of appropriate type to set/display parameter. + * Value of parm can be displayed either in Magic text window (file is + * NULL) or to a file. + * + * ---------------------------------------------------------------------------- + */ + +#ifdef MAGIC_WRAPPER + +/* irLSetActive -- */ +Tcl_Obj * +irLSetActive(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewBooleanObj(rL->rl_routeType.rt_active); + SetNoisyBool(&(rL->rl_routeType.rt_active), s, file); + return NULL; +} + +/* irLSetWidth -- */ +Tcl_Obj * +irLSetWidth(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewIntObj(rL->rl_routeType.rt_width); + SetNoisyInt(&(rL->rl_routeType.rt_width),s,file); + return NULL; +} + +/* irLSetLength -- */ +Tcl_Obj * +irLSetLength(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewIntObj(rL->rl_routeType.rt_length); + SetNoisyInt(&(rL->rl_routeType.rt_length),s,file); + return NULL; +} + +/* irLSetHCost -- */ +Tcl_Obj * +irLSetHCost(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewIntObj(rL->rl_hCost); + SetNoisyInt(&(rL->rl_hCost),s,file); + return NULL; +} + +/* irLSetVCost -- */ +Tcl_Obj * +irLSetVCost(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewIntObj(rL->rl_vCost); + SetNoisyInt(&(rL->rl_vCost),s,file); + return NULL; +} + +/* irLSetJogCost -- */ +Tcl_Obj * +irLSetJogCost(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewIntObj(rL->rl_jogCost); + SetNoisyInt(&(rL->rl_jogCost),s,file); + return NULL; +} + +/* irLSetHintCost -- */ +Tcl_Obj * +irLSetHintCost(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewIntObj(rL->rl_hintCost); + SetNoisyInt(&(rL->rl_hintCost),s,file); + return NULL; +} + +/* irLSetOverCost -- */ +Tcl_Obj * +irLSetOverCost(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewIntObj(rL->rl_overCost); + SetNoisyInt(&(rL->rl_overCost),s,file); + return NULL; +} + +#else + +/* irLSetActive -- */ +void +irLSetActive(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + SetNoisyBool(&(rL->rl_routeType.rt_active),s,file); +} + +/* irLSetWidth -- */ +void +irLSetWidth(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + SetNoisyInt(&(rL->rl_routeType.rt_width),s,file); +} + +/* irLSetLength -- */ +void +irLSetLength(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + SetNoisyInt(&(rL->rl_routeType.rt_length),s,file); +} + +/* irLSetHCost -- */ +void +irLSetHCost(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + SetNoisyInt(&(rL->rl_hCost),s,file); +} + +/* irLSetVCost -- */ +void +irLSetVCost(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + SetNoisyInt(&(rL->rl_vCost),s,file); +} + +/* irLSetJogCost -- */ +void +irLSetJogCost(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + SetNoisyInt(&(rL->rl_jogCost),s,file); +} + + +/* irLSetHintCost -- */ +void +irLSetHintCost(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + SetNoisyInt(&(rL->rl_hintCost),s,file); +} + +/* irLSetOverCost -- */ +void +irLSetOverCost(rL,s,file) + RouteLayer *rL; + char *s; + FILE *file; +{ + SetNoisyInt(&(rL->rl_overCost),s,file); +} + +#endif + + +/* + * ---------------------------------------------------------------------------- + * + * irCSet -- + * + * Set and display contact parameter . + * + * Results: + * None. + * + * Side effects: + * Call low level routine of appropriate type to set/display parameter. + * Value of parm can be displayed either in Magic text window (file is + * NULL) or to a file. + * + * ---------------------------------------------------------------------------- + */ + +#ifdef MAGIC_WRAPPER + +/* irCSetActive -- */ +Tcl_Obj * +irCSetActive(rC,s, file) + RouteContact *rC; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewBooleanObj(rC->rc_routeType.rt_active); + SetNoisyBool(&(rC->rc_routeType.rt_active),s,file); + return NULL; +} + +/* irCSetWidth -- */ +Tcl_Obj * +irCSetWidth(rC,s,file) + RouteContact *rC; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewIntObj(rC->rc_routeType.rt_width); + SetNoisyInt(&(rC->rc_routeType.rt_width),s,file); + return NULL; +} + +/* irCSetLength-- */ +Tcl_Obj * +irCSetLength(rC,s,file) + RouteContact *rC; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewIntObj(rC->rc_routeType.rt_length); + SetNoisyInt(&(rC->rc_routeType.rt_length),s,file); + return NULL; +} + +/* irCSetCost -- */ +Tcl_Obj * +irCSetCost(rC,s,file) + RouteContact *rC; + char *s; + FILE *file; +{ + if (file == (FILE *)1) + return Tcl_NewIntObj(rC->rc_cost); + SetNoisyInt(&(rC->rc_cost),s,file); + return NULL; +} + +#else + +/* irCSetActive -- */ +void +irCSetActive(rC,s, file) + RouteContact *rC; + char *s; + FILE *file; +{ + SetNoisyBool(&(rC->rc_routeType.rt_active),s,file); +} + +/* irCSetWidth -- */ +void +irCSetWidth(rC,s,file) + RouteContact *rC; + char *s; + FILE *file; +{ + SetNoisyInt(&(rC->rc_routeType.rt_width),s,file); +} + +/* irCSetLength -- */ +void +irCSetLength(rC,s,file) + RouteContact *rC; + char *s; + FILE *file; +{ + SetNoisyInt(&(rC->rc_routeType.rt_length),s,file); +} + +/* irCSetCost -- */ +void +irCSetCost(rC,s,file) + RouteContact *rC; + char *s; + FILE *file; +{ + SetNoisyInt(&(rC->rc_cost),s,file); +} + + +#endif + + +/* + * ---------------------------------------------------------------------------- + * + * irSrSet -- + * + * Set and display search parameter . + * + * Results: + * None. + * + * Side effects: + * Call low level routine of appropriate type to set/display parameter. + * Value of parm can be displayed either in Magic text window (file is + * NULL) or to a file. + * + * ---------------------------------------------------------------------------- + */ + + +/* irSrSetRate -- */ +void +irSrSetRate(s,file) + char *s; + FILE *file; +{ + SetNoisyDI(&irMazeParms->mp_wRate,s,file); +} + +/* irSrSetWidth -- */ +void +irSrSetWidth(s,file) + char *s; + FILE *file; +{ + SetNoisyDI(&(irMazeParms->mp_wWidth),s,file); +} + + +/* + * ---------------------------------------------------------------------------- + * + * irWzdSet -- + * + * Set and display wizard parameter . + * + * Results: + * None. + * + * Side effects: + * Call low level routine of appropriate type to set/display parameter. + * Value of parm can be displayed either in Magic text window (file is + * NULL) or to a file. + * + * ---------------------------------------------------------------------------- + */ + +/* irWzdSetBloomCost -- */ +void +irWzdSetBloomCost(s,file) + char *s; + FILE *file; +{ + SetNoisyDI(&(irMazeParms->mp_bloomDeltaCost),s,file); +} + +/* irWzdSetBloomLimit -- */ +void +irWzdSetBloomLimit(s,file) + char *s; + FILE *file; +{ + SetNoisyDI(&(irMazeParms->mp_bloomLimit),s,file); +} + +/* irWzdSetBoundsIncrement -- */ +void +irWzdSetBoundsIncrement(s,file) + char *s; + FILE *file; +{ + irSetNoisyAutoInt(&(irMazeParms->mp_boundsIncrement),s,file); +} + +/* irWzdSetEstimate -- */ +void +irWzdSetEstimate(s,file) + char *s; + FILE *file; +{ + SetNoisyBool(&(irMazeParms->mp_estimate),s,file); +} + +/* irWzdSetExpandEndpoints-- */ +void +irWzdSetExpandEndpoints(s, file) +char *s; +FILE *file; +{ + SetNoisyBool(&(irMazeParms->mp_expandEndpoints),s,file); +} + +/* irWzdSetPenalty -- */ +void +irWzdSetPenalty(s, file) + char *s; + FILE *file; +{ + if(s) + { + /* arg given, set penalty to it */ + float value; + if(sscanf(s,"%f",&value)==1) + { + irMazeParms->mp_penalty.rf_mantissa = + (int) (value * (1<mp_penalty.rf_nExponent)); + } + else + { + TxError("Bad penalty value: %s\n",s); + } + } + + /* print the current penalty factor. */ + if(file) + { + fprintf(file,"%f", + (double)irMazeParms->mp_penalty.rf_mantissa / + (double)(1<mp_penalty.rf_nExponent)); + } + else + { + TxPrintf("%f", + (double)irMazeParms->mp_penalty.rf_mantissa / + (double)(1<mp_penalty.rf_nExponent)); + } + + return; +} + +/* irWzdSetPenetration-- */ +void +irWzdSetPenetration(s, file) +char *s; +FILE *file; +{ + irSetNoisyAutoInt(&(irMazeParms->mp_maxWalkLength),s,file); +} + +/* irWzdSetWindow -- */ +void +irWzdSetWindow(s, file) +char *s; +FILE *file; +{ + int which; + int i, type; + + /* special arg Table */ +#define SP_COMMAND -1 +#define SP_DOT -2 + static struct + { + char *sp_name; /* name */ + int sp_type; + } specialArgs[] = { + "command", SP_COMMAND, + ".", SP_DOT, + 0 + }; + + if(s!=NULL) + /* set parameter */ + { + /* check if special arg */ + which = LookupStruct( + s, + (char **) specialArgs, + sizeof specialArgs[0]); + + if(which == -1) + { + TxError("Ambiguous argument: '%s'\n",s); + TxError("Argument must 'COMMAND', '.', or a nonneg. integer\n"); + return; + } + else if (which >= 0 ) + { + /* special argument */ + type = specialArgs[which].sp_type; + if(type == SP_COMMAND) + { + irRouteWid = -1; + } + else + { + ASSERT(type==SP_DOT,"wzdSetWindow"); + if(irWindow==NULL) + { + TxError("Point to a layout window first!\n"); + return; + } + else + irRouteWid = irWindow->w_wid; + } + } + else if(StrIsInt(s) && (i=atoi(s))>=0) + { + irRouteWid = i; + } + else + { + TxError("Bad argument: \"%s\"\n", s); + TxError("Argument must be 'COMMAND', '.', or a nonneg. integer\n"); + return; + } + } + + /* Print current value of parm */ + if(file) + { + if(irRouteWid == -1) + { + fprintf(file,"COMMAND"); + } + else + { + fprintf(file,"%d",irRouteWid); + } + } + else + { + if(irRouteWid == -1) + { + TxPrintf("COMMAND"); + } + else + { + TxPrintf("%d",irRouteWid); + } + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irContactsCmd -- + * + * Irouter subcommand to set and display parameters on contacts. + * + * Results: + * None. + * + * Side effects: + * Modify contact parameters and display them. + * + * ---------------------------------------------------------------------------- + */ + +/* Contact Parameter Table */ +static struct +{ + char *cP_name; /* name of parameter */ +#ifdef MAGIC_WRAPPER + Tcl_Obj *(*cP_proc)(); /* Procedure processing this parameter */ +#else + void (*cP_proc)(); /* Procedure processing this parameter */ +#endif +} cParms[] = { + "active", irCSetActive, + "width", irCSetWidth, + "length", irCSetLength, + "cost", irCSetCost, + 0 +}; + +/* NEXTVALUE - returns pointer to next value arg (string). */ +#define NEXTVALUE \ +( \ + (argc <= 4) ? NULL : \ + (nV_i >= argc-1) ? cmd->tx_argv[nV_i=4] : cmd->tx_argv[++nV_i] \ +) + +void +irContactsCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + TileType tileType; + RouteContact *rC; + + int argc = cmd->tx_argc; + int which, n; + int nV_i; /* Used by NEXTVALUE, must be initialized */ + bool doList = FALSE; + +#ifdef MAGIC_WRAPPER + /* Check for "-list" option */ + if (!strncmp(cmd->tx_argv[argc - 1], "-list", 5)) + { + doList = TRUE; + argc--; + } +#endif + + nV_i = argc - 1; + + /* Process by case */ + if(argc == 2 || + (argc == 3 && (strcmp(cmd->tx_argv[2],"*")==0)) || + (argc >= 4 && + (strcmp(cmd->tx_argv[2],"*")==0) && + (strcmp(cmd->tx_argv[3],"*")==0))) + { + /* PROCESS ALL PARMS FOR ALL CONTACT TYPES */ + +#ifdef MAGIC_WRAPPER + if (doList) + { + Tcl_Obj *alllist, *rlist, *rname, *robj; + alllist = Tcl_NewListObj(0, NULL); + + /* Process contact parms */ + for (rC = irRouteContacts; rC != NULL; rC = rC->rc_next) + { + rlist = Tcl_NewListObj(0, NULL); + rname = Tcl_NewStringObj( + DBTypeLongNameTbl[rC->rc_routeType.rt_tileType], -1); + Tcl_ListObjAppendElement(magicinterp, rlist, rname); + for (n = 0; cParms[n].cP_name; n++) + { + robj = (*cParms[n].cP_proc)(rC, NEXTVALUE, (FILE *)1); + Tcl_ListObjAppendElement(magicinterp, rlist, robj); + } + Tcl_ListObjAppendElement(magicinterp, alllist, rlist); + } + Tcl_SetObjResult(magicinterp, alllist); + } + else +#endif + { + /* Print Contact Heading */ + TxPrintf("%-12.12s ", "contact"); + for(n=0; cParms[n].cP_name; n++) + { + TxPrintf("%8.8s ",cParms[n].cP_name); + } + TxPrintf("\n"); + + TxPrintf("%-12.12s ", irRepeatChar(strlen("contact"),'-')); + for(n=0; cParms[n].cP_name; n++) + { + TxPrintf("%8.8s ",irRepeatChar(strlen(cParms[n].cP_name),'-')); + } + TxPrintf("\n"); + + /* Process contact parms */ + for (rC=irRouteContacts; rC!= NULL; rC=rC->rc_next) + { + TxPrintf("%-12.12s ", + DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]); + for(n=0; cParms[n].cP_name; n++) + { + (*cParms[n].cP_proc)(rC,NEXTVALUE,NULL); + } + TxPrintf("\n"); + } + } + } + else if(argc==3 || + (argc >= 4 && (strcmp(cmd->tx_argv[3],"*")==0))) + { + /* PROCESS ALL PARMS ASSOCIATED WITH CONTACT */ + /* convert layer string to tileType */ + tileType = DBTechNameType(cmd->tx_argv[2]); + if(tileType<0) + { + TxError("Unrecognized layer (type): \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + + if(rC=irFindRouteContact(tileType)) + { + /* Print Contact Heading */ + TxPrintf("%-12.12s ", "contact"); + for(n=0; cParms[n].cP_name; n++) + { + TxPrintf("%8.8s ",cParms[n].cP_name); + } + TxPrintf("\n"); + + TxPrintf("%-12.12s ", irRepeatChar(strlen("contact"),'-')); + for(n=0; cParms[n].cP_name; n++) + { + TxPrintf("%8.8s ",irRepeatChar(strlen(cParms[n].cP_name),'-')); + } + TxPrintf("\n"); + + /* Process contact parms */ + TxPrintf("%-12.12s ", + DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]); + for(n=0; cParms[n].cP_name; n++) + { + (*cParms[n].cP_proc)(rC,NEXTVALUE,NULL); + } + TxPrintf("\n"); + } + else + { + TxError("Unrecognized route-contact: \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + } + else if(argc>=4 && strcmp(cmd->tx_argv[2],"*")==0) + { + /* PROCESS A COLUMN (THE VALUES OF A PARAMETER FOR ALL CONTACTS) */ + + /* Lookup parameter name in contact parm table */ + which = LookupStruct( + cmd->tx_argv[3], + (char **) cParms, + sizeof cParms[0]); + + /* Process table lookup */ + if (which == -1) + { + /* AMBIGUOUS PARAMETER */ + TxError("Ambiguous parameter: \"%s\"\n", + cmd->tx_argv[3]); + return; + } + else if (which<0) + { + /* PARAMETER NOT FOUND */ + TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]); + TxError("Valid contact parameters are: "); + for (n = 0; cParms[n].cP_name; n++) + TxError(" %s", cParms[n].cP_name); + TxError("\n"); + return; + } + + else + { + /* CONTACT PARAMETER FOUND */ + + /* Print Heading */ + TxPrintf("%-12.12s ", "contact"); + TxPrintf("%8.8s ",cParms[which].cP_name); + TxPrintf("\n"); + + TxPrintf("%-12.12s ", irRepeatChar(strlen("contact"),'-')); + TxPrintf("%8.8s ", + irRepeatChar(strlen(cParms[which].cP_name),'-')); + TxPrintf("\n"); + + /* Process contact parm */ + for (rC=irRouteContacts; rC!= NULL; rC=rC->rc_next) + { + TxPrintf("%-12.12s ", + DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]); + (*cParms[which].cP_proc)(rC,NEXTVALUE,NULL); + TxPrintf("\n"); + } + } + } + else if(argc>=4) + { + /* PROCESS PARAMETER ASSOCIATED WITH CONTACT */ + /* convert layer string to tileType */ + tileType = DBTechNameType(cmd->tx_argv[2]); + if(tileType<0) + { + TxError("Unrecognized layer (type): \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + + if(rC=irFindRouteContact(tileType)) + { + /* Lookup contact parameter name in table */ + which = LookupStruct( + cmd->tx_argv[3], + (char **) cParms, + sizeof cParms[0]); + + /* Process result of lookup */ + if (which >= 0) + { + /* parameter found - call proc that processes it + * NULL second arg means display only + */ + (*cParms[which].cP_proc)(rC,NEXTVALUE,NULL); + TxPrintf("\n"); + } + else if (which == -1) + { + /* ambiguous parameter - complain */ + TxError("Ambiguous parameter: \"%s\"\n", + cmd->tx_argv[3]); + return; + } + else + { + /* unrecognized parameter - complain */ + TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]); + TxError("Valid contact parameters are: "); + for (n = 0; cParms[n].cP_name; n++) + TxError(" %s", cParms[n].cP_name); + TxError("\n"); + return; + } + } + else + { + TxError("Unrecognized route-contact: \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + + } + + /* Give warning if number of parm values didn't come out even */ + if (nV_i != argc-1) + { + TxError("Warning: Number of parameter values didn't match number of parameters.\n"); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irHelpCmd -- + * + * Irouter subcommand to describe available commands. (Driven by command + * table, defined above IRCommand()). + * + * Results: + * None. + * + * Side effects: + * Display requested help info. + * + * ---------------------------------------------------------------------------- + */ + + /*ARGSUSED*/ +void +irHelpCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int n; + int which; + + if(cmd->tx_argc == 2) + { + /* No arg, so print summary of commands */ + TxPrintf("\niroute - route from cursor to box\n\n"); + for(n=0; irSubcommands[n].sC_name!=NULL; n++) + { + TxPrintf("iroute %s - %s\n", + irSubcommands[n].sC_name, + irSubcommands[n].sC_commentString); + } + TxPrintf("\niroute help "); + TxPrintf(" - print usage info for subcommand.\n\n"); + } + else + { + /* Lookup subcommand in table, and printed associated help info */ + which = LookupStruct( + cmd->tx_argv[2], + (char **) irSubcommands, + sizeof irSubcommands[0]); + + /* Process result of lookup */ + if (which >= 0) + { + /* subcommand found - call print out its comment string and usage */ + TxPrintf("\niroute %s - %s\n", + irSubcommands[which].sC_name, + irSubcommands[which].sC_commentString); + TxPrintf("\nusage:\niroute %s\n", + irSubcommands[which].sC_usage); + } + else if (which == -1) + { + /* ambiguous subcommand - complain */ + TxError("Ambiguous iroute subcommand: \"%s\"\n", cmd->tx_argv[2]); + } + else + { + /* unrecognized subcommand - complain */ + TxError("Unrecognized iroute subcommand: \"%s\"\n", + cmd->tx_argv[2]); + TxError("Valid iroute irSubcommands are: "); + for (n = 0; irSubcommands[n].sC_name; n++) + TxError(" %s", irSubcommands[n].sC_name); + TxError("\n"); + } + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irLayersCmd -- + * + * Irouter subcommand to set and display parameters on route layers. + * + * Results: + * None. + * + * Side effects: + * Modify contact parameters and display them. + * + * ---------------------------------------------------------------------------- + */ + +/* Layer Parameter Table */ +static struct +{ + char *lP_name; /* name of parameter */ +#ifdef MAGIC_WRAPPER + Tcl_Obj *(*lP_proc)(); /* procedure processing this parameter */ +#else + void (*lP_proc)(); /* procedure processing this parameter */ +#endif +} lParms[] = { + "active", irLSetActive, + "width", irLSetWidth, + "length", irLSetLength, + "hCost", irLSetHCost, + "vCost", irLSetVCost, + "jogCost", irLSetJogCost, + "hintCost", irLSetHintCost, + "overCost", irLSetOverCost, + 0 +}; + +/* NEXTVALUE - returns pointer to next value arg (string). */ +#define NEXTVALUE \ +( \ + (argc <= 4) ? NULL : \ + (nV_i >= argc-1) ? cmd->tx_argv[nV_i=4] : cmd->tx_argv[++nV_i] \ +) + + /*ARGSUSED*/ +void +irLayersCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + TileType tileType; + RouteLayer *rL; + bool doList = FALSE; + + int argc = cmd->tx_argc; + int which, n; + int nV_i; /* Used by NEXTVALUE, must be initialized */ + +#ifdef MAGIC_WRAPPER + /* Check for "-list" option */ + if (!strncmp(cmd->tx_argv[argc - 1], "-list", 5)) + { + doList = TRUE; + argc--; + } +#endif + + nV_i = argc - 1; + + /* Process by case */ + if(argc == 2 || + (argc == 3 && (strcmp(cmd->tx_argv[2],"*")==0)) || + (argc >= 4 && + (strcmp(cmd->tx_argv[2],"*")==0) && + (strcmp(cmd->tx_argv[3],"*")==0))) + { + /* PROCESS ALL PARMS FOR ALL ROUTE LAYERS */ + +#ifdef MAGIC_WRAPPER + if (doList) + { + Tcl_Obj *alllist, *rlist, *robj, *rname; + alllist = Tcl_NewListObj(0, NULL); + + /* Process parms for each route layer */ + for (rL = irRouteLayers; rL != NULL; rL = rL->rl_next) + { + rlist = Tcl_NewListObj(0, NULL); + rname = Tcl_NewStringObj( + DBTypeLongNameTbl[rL->rl_routeType.rt_tileType], -1); + Tcl_ListObjAppendElement(magicinterp, rlist, rname); + for (n = 0; lParms[n].lP_name; n++) + { + robj = (*lParms[n].lP_proc)(rL, NEXTVALUE, (FILE *)1); + Tcl_ListObjAppendElement(magicinterp, rlist, robj); + } + Tcl_ListObjAppendElement(magicinterp, alllist, rlist); + } + Tcl_SetObjResult(magicinterp, alllist); + } + else +#endif + { + /* Print Route Layer Heading */ + TxPrintf("%-12.12s ", "layer"); + for(n=0; lParms[n].lP_name; n++) + { + TxPrintf("%8.8s ",lParms[n].lP_name); + } + TxPrintf("\n"); + + TxPrintf("%-12.12s ", irRepeatChar(strlen("layer"),'-')); + for(n=0; lParms[n].lP_name; n++) + { + TxPrintf("%8.8s ", irRepeatChar(strlen(lParms[n].lP_name),'-')); + } + TxPrintf("\n"); + + /* Process parms for each route layer */ + for (rL=irRouteLayers; rL!= NULL; rL=rL->rl_next) + { + TxPrintf("%-12.12s ", + DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]); + for(n=0; lParms[n].lP_name; n++) + { + (*lParms[n].lP_proc)(rL,NEXTVALUE,NULL); + } + TxPrintf("\n"); + } + } + } + else if(argc==3 || + (argc >= 4 && (strcmp(cmd->tx_argv[3],"*")==0))) + { + /* PROCESS ALL PARMS ASSOCIATED WITH ROUTE LAYER */ + /* convert layer string to tileType */ + tileType = DBTechNameType(cmd->tx_argv[2]); + if(tileType<0) + { + TxError("Unrecognized layer (type): \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + + if (rL=irFindRouteLayer(tileType)) + { + /* Print Route Layer Heading */ + TxPrintf("%-12.12s ", "layer"); + for(n=0; lParms[n].lP_name; n++) + { + TxPrintf("%8.8s ",lParms[n].lP_name); + } + TxPrintf("\n"); + + TxPrintf("%-12.12s ", irRepeatChar(strlen("layer"),'-')); + for(n=0; lParms[n].lP_name; n++) + { + TxPrintf("%8.8s ", irRepeatChar(strlen(lParms[n].lP_name),'-')); + } + TxPrintf("\n"); + + /* Process parms for route layer */ + TxPrintf("%-12.12s ", + DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]); + for(n=0; lParms[n].lP_name; n++) + { + (*lParms[n].lP_proc)(rL,NEXTVALUE,NULL); + } + TxPrintf("\n"); + } + else + { + TxError("Unrecognized route layer or contact: \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + } + else if(argc>=4 && strcmp(cmd->tx_argv[2],"*")==0) + { + /* PROCESS A COLUMN (THE VALUES OF A PARAMETER FOR ALL LAYERS) */ + + /* Lookup parameter name in layer parm table */ + which = LookupStruct( + cmd->tx_argv[3], + (char **) lParms, + sizeof lParms[0]); + + /* Process table lookup */ + if (which == -1) + { + /* AMBIGUOUS PARAMETER */ + TxError("Ambiguous parameter: \"%s\"\n", + cmd->tx_argv[3]); + return; + } + + else if (which<0) + { + /* PARAMETER NOT FOUND */ + TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]); + TxError("Valid layer parameters are: "); + for (n = 0; lParms[n].lP_name; n++) + TxError(" %s", lParms[n].lP_name); + TxError("\n"); + return; + } + + else + { + /* LAYER PARAMETER FOUND */ + + /* Print Heading */ + TxPrintf("%-12.12s ", "layer"); + TxPrintf("%8.8s ",lParms[which].lP_name); + TxPrintf("\n"); + + TxPrintf("%-12.12s ", irRepeatChar(strlen("layer"),'-')); + TxPrintf("%8.8s ", + irRepeatChar(strlen(lParms[which].lP_name),'-')); + TxPrintf("\n"); + + /* Process parm for each route layer */ + for (rL=irRouteLayers; rL!= NULL; rL=rL->rl_next) + { + TxPrintf("%-12.12s ", + DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]); + (*lParms[which].lP_proc)(rL,NEXTVALUE,NULL); + TxPrintf("\n"); + } + + } + } + else if(argc>=4) + { + /* PROCESS PARAMETER ASSOCIATED WITH ROUTE LAYER */ + /* convert layer string to tileType */ + tileType = DBTechNameType(cmd->tx_argv[2]); + if(tileType<0) + { + TxError("Unrecognized layer (type): \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + + if (rL=irFindRouteLayer(tileType)) + { + /* Lookup route layer parameter name in table */ + which = LookupStruct( + cmd->tx_argv[3], + (char **) lParms, + sizeof lParms[0]); + + /* Process result of lookup */ + if (which >= 0) + { + /* parameter found - call proc that processes it + * NULL second arg means display only + */ + (*lParms[which].lP_proc)(rL,NEXTVALUE,NULL); + TxPrintf("\n"); + } + else if (which == -1) + { + /* ambiguous parameter - complain */ + TxError("Ambiguous parameter: \"%s\"\n", + cmd->tx_argv[3]); + return; + } + else + { + /* unrecognized parameter - complain */ + TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]); + TxError("Valid route layer parameters are: "); + for (n = 0; lParms[n].lP_name; n++) + TxError(" %s", lParms[n].lP_name); + TxError("\n"); + return; + } + } + else + { + TxError("Unrecognized layer: \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + } + + /* Give warning if number of parm values didn't come out even */ + if (nV_i != argc-1) + { + TxError("Warning: Number of parameter values didn't match number of parameters.\n"); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irRouteCmd -- + * + * Irouter subcommand to actually do a route. + * + * Results: + * None. + * + * Side effects: + * Compute a route and paint it into edit cell. + * + * ---------------------------------------------------------------------------- + */ + +/* Route options Table */ +static char* rOptions[] = { + "-dbox", /* 0 */ + "-dlabel", /* 1 */ + "-dlayers", /* 2 */ + "-drect", /* 3 */ + "-dselection",/* 4 */ + "-scursor", /* 5 */ + "-slabel", /* 6 */ + "-slayers", /* 7 */ + "-spoint", /* 8 */ +#ifdef MAGIC_WRAPPER + "-timeout", /* 9 */ +#endif + NULL +}; + +void +irRouteCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + Point *startPtArg = NULL; /* pts to start point, if given on command */ + Rect *destRectArg = NULL; /* pts to dest rect, if given on command */ + char *startLabel = NULL; /* pts to labelname, if given on command */ + char *destLabel = NULL; /* pts to labelname, if given on command */ + List *startLayers = NULL; + List *destLayers = NULL; + int startType; /* type of start specifier */ + int destType; /* type of destination specifier */ + Point startPt; + Rect destRect; + int irResult = MZ_NO_ACTION; + int i; /* index of arg being processed */ + int argc = cmd->tx_argc; + char **argv = cmd->tx_argv; + + TileTypeBitMask layerMask; + RouteLayer *rL; + + /* set startType and destType to defaults */ + startType = ST_CURSOR; + destType = DT_BOX; + + /* skip over cmd name args */ + i = 2; + + /* process options */ + while(i=argc) + { + TxError("Missing label.\n"); + goto leaveClean; + } + destLabel = argv[i]; + break; + case 2: + /* dLayers */ + if(++i>=argc) + { + TxError("Missing layer list.\n"); + goto leaveClean; + } + (void) CmdParseLayers(argv[i],&layerMask); + for(rL=irRouteLayers; rL!=NULL; rL=rL->rl_next) + { + if(TTMaskHasType(&layerMask,rL->rl_routeType.rt_tileType) && + rL->rl_routeType.rt_active) + { + LIST_ADD(rL, destLayers); + } + } + if(destLayers==NULL) + { + TxError("No active route layers in destination list!\n"); + goto leaveClean; + } + break; + case 3: + /* dRect */ + destType = DT_RECT; + if(++i>=argc) + { + TxError("Incomplete coordinates.\n"); + goto leaveClean; + } + if(!StrIsNumeric(argv[i])) + { + TxError("Non coordinate: %s\n",argv[i]); + goto leaveClean; + } + destRect.r_xbot = cmdParseCoord(w, argv[i], FALSE, TRUE); + + if(++i>=argc) + { + TxError("Incomplete coordinates.\n"); + goto leaveClean; + } + if(!StrIsNumeric(argv[i])) + { + TxError("Nonnumeric coordinate: %s\n",argv[i]); + goto leaveClean; + } + destRect.r_ybot = cmdParseCoord(w, argv[i], FALSE, FALSE); + + if(++i>=argc) + { + TxError("Incomplete coordinates.\n"); + goto leaveClean; + } + if(!StrIsNumeric(argv[i])) + { + TxError("Nonnumeric coordinate: %s\n",argv[i]); + goto leaveClean; + } + destRect.r_xtop = cmdParseCoord(w, argv[i], FALSE, TRUE); + + if(++i>=argc) + { + TxError("Incomplete coordinates.\n"); + goto leaveClean; + } + if(!StrIsNumeric(argv[i])) + { + TxError("Nonnumeric coordinate: %s\n",argv[i]); + goto leaveClean; + } + destRect.r_ytop = cmdParseCoord(w, argv[i], FALSE, FALSE); + + destRectArg = &destRect; + break; + case 4: + /* dSelection */ + destType = DT_SELECTION; + break; + case 5: + /* sCursor */ + startType = ST_CURSOR; + break; + case 6: + /* sLabel */ + startType = ST_LABEL; + if(++i>=argc) + { + TxError("Missing label.\n"); + goto leaveClean; + } + startLabel = argv[i]; + break; + case 7: + /* sLayers */ + if(++i>=argc) + { + TxError("Missing layer list.\n"); + goto leaveClean; + } + (void) CmdParseLayers(argv[i],&layerMask); + for(rL=irRouteLayers; rL!=NULL; rL=rL->rl_next) + { + if(TTMaskHasType(&layerMask, + rL->rl_routeType.rt_tileType) && + rL->rl_routeType.rt_active) + { + LIST_ADD(rL, startLayers); + } + } + if(startLayers==NULL) + { + TxError("No active route layers in start list!\n"); + goto leaveClean; + } + break; + case 8: + /* sPoint */ + startType = ST_POINT; + if(++i>=argc) + { + TxError("Incomplete coordinates.\n"); + goto leaveClean; + } + if(!StrIsNumeric(argv[i])) + { + TxError("Nonnumeric coordinate: %s\n",argv[i]); + goto leaveClean; + } + startPt.p_x = cmdParseCoord(w, argv[i], FALSE, TRUE); + if(++i>=argc) + { + TxError("Incomplete coordinates.\n"); + goto leaveClean; + } + if(!StrIsNumeric(argv[i])) + { + TxError("Nonnumeric coordinate: %s\n",argv[i]); + goto leaveClean; + } + startPt.p_y = cmdParseCoord(w, argv[i], FALSE, FALSE); + + startPtArg = &startPt; + break; +#ifdef MAGIC_WRAPPER + case 9: + if(++i>=argc) + { + TxError("No timeout value given.\n"); + goto leaveClean; + } + if(!StrIsInt(argv[i])) + { + TxError("Noninteger timeout value: %s\n",argv[i]); + goto leaveClean; + } + SigRemoveTimer(); + SigTimerInterrupts(); + SigSetTimer(atoi(argv[i])); + break; +#endif + default: + /* shouldn't happen */ + ASSERT(FALSE,"irRouteCmd"); + break; + } + + /* advance to next option */ + ++i; + } + + /* We're done parsing the command, call irRoute to do the real work */ + irResult = irRoute(w, startType, startPtArg, startLabel, startLayers, + destType, destRectArg, destLabel, destLayers); + +#ifdef MAGIC_WRAPPER + SigTimerDisplay(); + + /* Set Tcl Result to irResult */ + switch (irResult) + { + case MZ_SUCCESS: + Tcl_SetResult(magicinterp, "Route success", 0); + break; + case MZ_CURRENT_BEST: + Tcl_SetResult(magicinterp, "Route best before interrupt", 0); + break; + case MZ_FAILURE: + Tcl_SetResult(magicinterp, "Route failure", 0); + break; + case MZ_UNROUTABLE: + Tcl_SetResult(magicinterp, "Route unroutable", 0); + break; + case MZ_INTERRUPTED: + Tcl_SetResult(magicinterp, "Route interrupted", 0); + break; + case MZ_ALREADY_ROUTED: + Tcl_SetResult(magicinterp, "Route already routed", 0); + break; + } +#endif + +leaveClean: + ListDealloc(startLayers); + ListDealloc(destLayers); + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irSearchCmd -- + * + * Irouter subcommand to set and display search parameters. + * + * Results: + * None. + * + * Side effects: + * Modify search parameters and display them. + * + * ---------------------------------------------------------------------------- + */ + +/* Search Parameter Table */ +static struct +{ + char *srP_name; /* name of parameter */ + void (*srP_proc)(); /* Procedure processing this parameter */ +} srParms[] = { + "rate", irSrSetRate, + "width", irSrSetWidth, + 0 +}; + +void +irSearchCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + + /* Process by case */ + if(cmd->tx_argc == 2) + /* print values of all parms */ + { + int n; + + for(n=0; srParms[n].srP_name; n++) + { + TxPrintf(" %s=", srParms[n].srP_name); + (*srParms[n].srP_proc)(NULL,NULL); + } + TxPrintf("\n"); + } + else if(cmd->tx_argc == 3 || cmd->tx_argc == 4) + /* process single parameter */ + { + int which; + + /* Lookup parameter name in contact parm table */ + which = LookupStruct( + cmd->tx_argv[2], + (char **) srParms, + sizeof srParms[0]); + + /* Process table lookup */ + if (which == -1) + /* parameter ambiguous */ + { + TxError("Ambiguous parameter: \"%s\"\n", + cmd->tx_argv[2]); + return; + } + else if (which<0) + /* parameter not found */ + { + int n; + + TxError("Unrecognized parameter: %s\n", cmd->tx_argv[2]); + TxError("Valid search parameters are: "); + for (n = 0; srParms[n].srP_name; n++) + TxError(" %s", srParms[n].srP_name); + TxError("\n"); + return; + } + else + /* parameter found - process it */ + { + char *arg; + + if(cmd->tx_argc == 3) + /* just want current value - use null argument */ + { + arg = NULL; + } + else + /* setting parameter, arg = value string */ + { + arg = cmd->tx_argv[3]; + } + + TxPrintf(" %s=", srParms[which].srP_name); + (*srParms[which].srP_proc)(arg,NULL); + TxPrintf("\n"); + } + + } + else + /* Too many arguments */ + { + TxError("Too many args on 'iroute search'\n"); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irSpacingsCmd -- + * + * Irouter subcommand to set and display minimum spacings between + * routetypes. + * + * + * Results: + * None. + * + * Side effects: + * Modify and display spacing parameters. + * + * ---------------------------------------------------------------------------- + */ + +void +irSpacingsCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + TileType tileType; + RouteType *rT; + char *s; + int which, value, argI, i, n; + + /* Special Value Table */ + static struct + { + char *sV_name; /* name of value */ + int sV_value; /* corresponding interger value */ + } sValue[] = { + "n", -1, + "nil", -1, + "none", -1, + "null", -1, + 0 + }; + + /* Subcell Table */ + static struct + { + char *sT_name; /* name of value */ + int sT_value; /* corresponding interger value */ + } subcellTable[] = { + "subcell", TT_SUBCELL, + 0 + }; + + /* Process by case */ + if(cmd->tx_argc == 2) + { + /* NO ARGS TO SPACING REQUEST - DISPLAY ALL SPACINGS */ + + /* Print spacings for each route type */ + for (rT=irRouteTypes; rT!= NULL; rT=rT->rt_next) + { + TxPrintf("%s: ", + DBTypeLongNameTbl[rT->rt_tileType]); + for (i=0;irt_spacing[i]>=0) + TxPrintf("%s=%d ",DBTypeLongNameTbl[i],rT->rt_spacing[i]); + if(rT->rt_spacing[TT_SUBCELL]>=0) + TxPrintf("%s=%d ","SUBCELL",rT->rt_spacing[TT_SUBCELL]); + TxPrintf("\n\n"); + } + } + else if(cmd->tx_argc==3) + { + /* ONE ARG TO SPACING REQUEST */ + + if (strcmp(cmd->tx_argv[2],"CLEAR")==0) + { + /* CLEAR ALL SPACINGS */ + for (rT=irRouteTypes; rT!= NULL; rT=rT->rt_next) + /* <=TT_MAXTYPES below includes TT_SUBCELL */ + for (i=0;i<=TT_MAXTYPES;i++) + rT->rt_spacing[i]= -1; + } + else + { + /* PRINT SPACINGS FOR GIVEN ROUTE LAYER */ + + /* convert layer string to tileType */ + tileType = DBTechNameType(cmd->tx_argv[2]); + if(tileType<0) + { + TxError("Unrecognized layer (type): \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + + if (rT=irFindRouteType(tileType)) + { + + TxPrintf("%s: ", + DBTypeLongNameTbl[rT->rt_tileType]); + for (i=0;irt_spacing[i]>=0) + TxPrintf("%s=%d ", + DBTypeLongNameTbl[i],rT->rt_spacing[i]); + if(rT->rt_spacing[TT_SUBCELL]>=0) + TxPrintf("%s=%d ","SUBCELL",rT->rt_spacing[TT_SUBCELL]); + TxPrintf("\n\n"); + } + else + { + TxError("Unrecognized route layer or contact: \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + } + } + else if(cmd->tx_argc==4) + { + /* PRINT VALUE OF GIVEN SPACING */ + + /* convert layer string to tileType */ + tileType = DBTechNameType(cmd->tx_argv[2]); + if(tileType<0) + { + TxError("Unrecognized layer (type): \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + + if ((rT=irFindRouteType(tileType))==NULL) + { + TxError("Unrecognized route layer or contact: \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + + /* convert type-string spacing is "to" to tiletype */ + tileType = DBTechNameType(cmd->tx_argv[3]); + if(tileType<0) + { + /* if not a real type, check to see if "SUBCELL" */ + which = LookupStruct( + cmd->tx_argv[3], + (char **) subcellTable, + sizeof subcellTable[0]); + if ( which>= 0) + tileType = TT_SUBCELL; + } + if(tileType<0) + { + TxError("Unrecognized layer (type): \"%.20s\"\n", + cmd->tx_argv[3]); + return; + } + + /* Print current value of spacing */ + if(rT->rt_spacing[tileType] >= 0) + TxPrintf("\t%d\n",rT->rt_spacing[tileType]); + else + TxPrintf("\tNIL\n"); + } + else if(EVEN(cmd->tx_argc)) + { + /* TYPE PARMS DON'T PAIR EVENLY WITH VALUE PARMS */ + TxError("Type and value args don't pair evenly.\n"); + TxError("Usage: *iroute spacing [routeType] [type1] [value1] [type2 value2] ... [typen valuen]\n"); + } + else + { + /* SET SPACINGS */ + + /* convert layer string to tileType */ + tileType = DBTechNameType(cmd->tx_argv[2]); + if(tileType<0) + { + TxError("Unrecognized layer (type): \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + + if ((rT=irFindRouteType(tileType))==NULL) + { + TxError("Unrecognized route layer or contact: \"%.20s\"\n", + cmd->tx_argv[2]); + return; + } + + /* Prepend tab to echo of new values */ + TxPrintf("\t"); + + /* process type/value pairs */ + for (argI=3; argItx_argc; argI +=2) + { + /* convert type-string spacing is "to" to tiletype */ + tileType = DBTechNameType(cmd->tx_argv[argI]); + if(tileType<0) + { + /* if not a real type, check to see if "SUBCELL" */ + which = LookupStruct( + cmd->tx_argv[argI], + (char **) subcellTable, + sizeof subcellTable[0]); + if ( which>= 0) + tileType = TT_SUBCELL; + } + if(tileType<0) + { + TxError("\nUnrecognized layer (type): \"%.20s\"\n", + cmd->tx_argv[argI]); + continue; + } + + /* convert value-string to integer */ + s = cmd->tx_argv[argI+1]; + if (StrIsNumeric(s)) + { + value = cmdParseCoord(w, s, TRUE, FALSE); + if (value < -1) + { + TxError("\nBad spacing value: %d\n",value); + TxError("Valid spacing values are: "); + TxError(" -1"); + for (n = 0; sValue[n].sV_name; n++) + TxError(" %s", sValue[n].sV_name); + TxError("\n"); + return; + } + } + else + { + /* Lookup in special value table */ + which = LookupStruct( + s, + (char **) sValue, + sizeof sValue[0]); + + /* Process result of lookup */ + if (which >= 0) + { + /* special value found, set string accordingly */ + value = sValue[which].sV_value; + } + else if (which == -1) + { + /* ambiguous value - complain */ + TxError("\nAmbiguous value: \"%s\"\n",s); + continue; + } + else + { + /* unrecognized value - complain */ + TxError("Bad spacing value: %s\n",s); + TxError("Valid spacing values are: "); + TxError(" -1"); + for (n = 0; sValue[n].sV_name; n++) + TxError(" %s", sValue[n].sV_name); + TxError("\n"); + continue; + } + } + + /* Set value in route type */ + rT->rt_spacing[tileType]=value; + + /* Print new value */ + if(rT->rt_spacing[tileType] != -1) + TxPrintf(" %s=%d", + (tileType == TT_SUBCELL ? + "SUBCELL" : DBTypeLongNameTbl[tileType]), + rT->rt_spacing[tileType]); + else + TxPrintf(" %s=NIL", + (tileType==TT_SUBCELL ? + "SUBCELL" : DBTypeLongNameTbl[tileType])); + } + TxPrintf("\n"); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irVerbosityCmd -- + * + * Irouter subcommand to set amount of messages given by irouter and mzrouter. + * + * Results: + * None. + * + * Side effects: + * Sets verbosity parameter + * + * ---------------------------------------------------------------------------- + */ + +void +irVerbosityCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if(cmd->tx_argc >3) + { + TxError("'iroute verbosity' only takes one arg!\n"); + return; + } + + if(cmd->tx_argc == 3) + { + int i; + + /* ONE ARG */ + if(StrIsInt(cmd->tx_argv[2]) && (i=atoi(cmd->tx_argv[2]))>=0) + { + irMazeParms->mp_verbosity = i; + } + else + { + TxError("Bad argument: \"%s\"\n", cmd->tx_argv[2]); + TxError("Argument must be a nonnegative integer\n"); + return; + } + } + + /* Print current value of verbosity */ + switch (irMazeParms->mp_verbosity) + { + case 0: + /* shhhhh! we're in silent mode */ + break; + + case 1: + TxPrintf("\t1 (Brief messages)\n"); + break; + + default: + ASSERT(irMazeParms->mp_verbosity>=2,"irVerbosityCmd"); + TxPrintf("\t%d (Lots of statistics)\n", + irMazeParms->mp_verbosity); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irVersionCmd -- + * + * Irouter subcommand to display irouter version string. + * + * Results: + * None. + * + * Side effects: + * Displays version string. + * + * ---------------------------------------------------------------------------- + */ + +void +irVersionCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + + if(cmd->tx_argc == 2) + { + /* Print out version string */ + TxPrintf("\tIrouter version %s\n", IROUTER_VERSION); + } + else + { + TxError("Too many args on 'iroute version'\n"); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irWizardCmd -- + * + * Irouter subcommand to set and display less frequently modified parameters. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +/* Wizard Parameter Table */ +static struct +{ + char *wzdP_name; /* name of parameter */ + void (*wzdP_proc)(); /* Procedure processing this parameter */ +} wzdParms[] = { + "bloom", irWzdSetBloomCost, + "bloomLimit", irWzdSetBloomLimit, + "boundsIncrement", irWzdSetBoundsIncrement, + "estimate", irWzdSetEstimate, + "expandEndpoints", irWzdSetExpandEndpoints, + "penalty", irWzdSetPenalty, + "penetration", irWzdSetPenetration, + "window", irWzdSetWindow, + 0 +}; + +void +irWizardCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + + /* Process by case */ + if(cmd->tx_argc == 2) + /* print values of all parms */ + { + int n; + + for(n=0; wzdParms[n].wzdP_name; n++) + { + TxPrintf(" %s=", wzdParms[n].wzdP_name); + (*wzdParms[n].wzdP_proc)(NULL,NULL); + TxPrintf("\n"); + } + } + else if(cmd->tx_argc == 3 || cmd->tx_argc == 4) + /* process single parameter */ + { + int which; + + /* Lookup parameter name in contact parm table */ + which = LookupStruct( + cmd->tx_argv[2], + (char **) wzdParms, + sizeof wzdParms[0]); + + /* Process table lookup */ + if (which == -1) + /* parameter ambiguous */ + { + TxError("Ambiguous parameter: \"%s\"\n", + cmd->tx_argv[2]); + return; + } + else if (which<0) + /* parameter not found */ + { + int n; + + TxError("Unrecognized parameter: %s\n", cmd->tx_argv[2]); + TxError("Valid wizard parameters are: "); + for (n = 0; wzdParms[n].wzdP_name; n++) + TxError(" %s", wzdParms[n].wzdP_name); + TxError("\n"); + return; + } + else + /* parameter found - process it */ + { + char *arg; + + if(cmd->tx_argc == 3) + /* just want current value - use null argument */ + { + arg = NULL; + } + else + /* setting parameter, arg = value string */ + { + arg = cmd->tx_argv[3]; + } + + TxPrintf(" %s=", wzdParms[which].wzdP_name); + (*wzdParms[which].wzdP_proc)(arg,NULL); + TxPrintf("\n"); + } + + } + else + /* Too many arguments */ + { + TxError("Too many args on 'iroute wizard'\n"); + } + + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * irSaveParametersCmd -- + * + * Irouter subcommand to create "source" file setting all irouter parameters + * (except ref. window) to current value - to reset to these values just + * source the file with `:source'. + * + * Results: + * None. + * + * Side effects: + * Write file of Magic commands to set parms. to current values. + * + * NOTE: + * Note defined after all other commands, so it can make use of + * datastructures defined just in front of other commands, + * such as the search parameter table. + * ---------------------------------------------------------------------------- + */ + +void +irSaveParametersCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + FILE *saveFile; + RouteContact *rC; + RouteLayer *rL; + + /* make sure exactly one arg given */ + if(cmd->tx_argc !=3) + { + if(cmd->tx_argc == 2) + TxError("Must specify save file!\n"); + else + TxError("Too many args on ':iroute saveParameter'\n"); + return; + } + + /* open save file */ + saveFile = fopen(cmd->tx_argv[2], "w"); + if (saveFile == NULL) + { + TxError("Could not open file '%s' for writing.\n", cmd->tx_argv[2]); + return; + } + + /* write header comment */ + fprintf(saveFile,"# Irouter version %s\n", IROUTER_VERSION); + fprintf(saveFile,"#\n"); + fprintf(saveFile, + "# This is a Magic command file generated by the Magic command\n"); + fprintf(saveFile,"#\t:iroute saveParameters\n"); + fprintf(saveFile,"# To restore these parameter settings,"); + fprintf(saveFile," use the Magic `:source' command.\n\n"); + + /* turn verbosity down to errors and warnings, to avoid lots of + * gibberish when the file is sourced. + */ + fprintf(saveFile,":iroute verbosity 0\n"); + + /* save CONTACT parameters */ + for (rC=irRouteContacts; rC!= NULL; rC=rC->rc_next) + { + int n; + + fprintf(saveFile,":iroute contact %s * ", + DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]); + for(n=0; cParms[n].cP_name; n++) + { + (*cParms[n].cP_proc)(rC,NULL,saveFile); + } + fprintf(saveFile,"\n"); + } + + /* save LAYER parameters */ + for (rL=irRouteLayers; rL!= NULL; rL=rL->rl_next) + { + int n; + + fprintf(saveFile,":iroute layer %s * ", + DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]); + for(n=0; lParms[n].lP_name; n++) + { + (*lParms[n].lP_proc)(rL,NULL,saveFile); + } + fprintf(saveFile,"\n"); + } + + /* save SEARCH parameters */ + { + int n; + + for(n=0; srParms[n].srP_name; n++) + { + fprintf(saveFile,":iroute search %s ", + srParms[n].srP_name); + (*srParms[n].srP_proc)(NULL,saveFile); + fprintf(saveFile,"\n"); + } + } + + /* save SPACINGS */ + { + RouteType *rT; + int i; + + fprintf(saveFile,":iroute spacings CLEAR\n"); + for (rT=irRouteTypes; rT!= NULL; rT=rT->rt_next) + { + for (i=0;irt_spacing[i]>=0) + fprintf(saveFile,":iroute spacings %s %s %d\n", + DBTypeLongNameTbl[rT->rt_tileType], + DBTypeLongNameTbl[i], + rT->rt_spacing[i]); + if(rT->rt_spacing[TT_SUBCELL]>=0) + fprintf(saveFile,":iroute spacings %s %s %d\n", + DBTypeLongNameTbl[rT->rt_tileType], + "SUBCELL", + rT->rt_spacing[TT_SUBCELL]); + } + } + + /* save WIZARD parameters */ + { + int n; + + for(n=0; wzdParms[n].wzdP_name; n++) + { + fprintf(saveFile,":iroute wizard %s ", + wzdParms[n].wzdP_name); + (*wzdParms[n].wzdP_proc)(NULL,saveFile); + fprintf(saveFile,"\n"); + } + } + + /* save VERBOSITY parameter (done last so :source is silent) */ + fprintf(saveFile,":iroute verbosity %d\n", + irMazeParms->mp_verbosity); + + (void) fclose(saveFile); + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * IRCommand -- + * + * Command interface for interactive router. Processes `:iroute' command + * lines. + * + * Results: + * None. + * + * Side effects: + * Depends on the command; see below. + * + * Organization: + * We select a procedure based on the first keyword (argv[0]) + * and call it to do the work of implementing the subcommand. Each + * such procedure is of the following form: + * + * int + * proc(argc, argv) + * int argc; + * char *argv[]; + * { + * } + * + * ---------------------------------------------------------------------------- + */ + +/*--- Subcommand Table ---*/ + +SubCmdTableE irSubcommands[] = { + "contacts", irContactsCmd, + "set route-contact parameters", + "contacts [type] [parameter] [value1] ... [valuen]\n\ +\t(can use '*' for type or parameter)", + + "help", irHelpCmd, + "summarize iroute subcommands", + "help [subcommand]", + + "layers", irLayersCmd, + "set route-layer parameters", + "layers [type] [parameter] [value1] ... [valuen]\n\ +\t(can use '*' for type or parameter)", + + "route", irRouteCmd, + "connect point to node(s)", + "route [options]\n\ +\t-sLayers layers = layers route may start on.\n\ +\t-sCursor = start route at cursor (DEFAULT)\n\ +\t-sLabel name = start route at label of given name\n\ +\t-sPoint x y = start route at given coordinates\n\ +\t-dLayers layers = layers route may end on.\n\ +\t-dBox = route to box (DEFAULT)\n\ +\t-dLabel name = route to label of given name\n\ +\t-dRect xbot ybot xtop ytop = route to rectangle of given coordinates\n\ +\t-dSelection = route to selection", + + "saveParameters", irSaveParametersCmd, + "write out all irouter parameters\n\ +\t(can be read back with :source)", + "saveParameters ", + + "search", irSearchCmd, + "set parameters controlling the internal search for routes", + "search [searchParameter] [value]", + + "spacings", irSpacingsCmd, + "set minimum spacing between route-type and arbitrary type", + "spacings [route-type] [type] [spacing] ... [typen spacingn]\n\ +\t(types can be 'SUBCELL', spacing can be 'nil')\n\ +iroute spacings CLEAR\n\ +\t(sets all spacings to nil)", + + "verbosity", irVerbosityCmd, + "control the amount of messages printed", + "verbosity [level]\n\ +\t(0 = errors and warnings only, 1 = brief, 2 = lots of statistics)", + + "version", irVersionCmd, + "identify irouter version", + "version", + + "wizard", irWizardCmd, + "set miscellaneous parameters", + "wizard [wizardParameter] [value]", + + 0 +}, *subCmdP; + +void +IRCommand(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int n; + int which; + + /* make sure we have maze parameters */ + if(irMazeParms==NULL) + { + TxError("Need irouter style in mzrouter section of technology file"); + TxError(" to use irouter.\n"); + return; + } + + /* make window available to all subroutines */ + irWindow = w; + + /* If in silent mode, turn printing off */ + if(irMazeParms->mp_verbosity==0) + { + TxPrintOff(); + } + + if(cmd->tx_argc == 1) + { + int irResult; + + /* No subcommand specified - so just route from cursor to box + * No endpts or layers explicitly given on cmd, so args are + * NULL below. + */ + irResult = irRoute(w, ST_CURSOR, + (Point*)NULL, (char*)NULL, (List*)NULL, + DT_BOX, (Point*)NULL, (char*)NULL, (List*)NULL); + +#ifdef MAGIC_WRAPPER + /* Set Tcl Result to irResult */ + switch (irResult) + { + case MZ_SUCCESS: + Tcl_SetResult(magicinterp, "Route success", 0); + break; + case MZ_CURRENT_BEST: + Tcl_SetResult(magicinterp, "Route best before interrupt", 0); + break; + case MZ_FAILURE: + Tcl_SetResult(magicinterp, "Route failure", 0); + break; + case MZ_UNROUTABLE: + Tcl_SetResult(magicinterp, "Route unroutable", 0); + break; + case MZ_INTERRUPTED: + Tcl_SetResult(magicinterp, "Route interrupted", 0); + break; + case MZ_ALREADY_ROUTED: + Tcl_SetResult(magicinterp, "Route already routed", 0); + break; + } +#endif + + } + else + { + /* Lookup subcommand in table */ + which = LookupStruct( + cmd->tx_argv[1], + (char **) irSubcommands, + sizeof irSubcommands[0]); + + /* Process result of lookup */ + if (which >= 0) + { + /* subcommand found - call proc that implements it */ + subCmdP = &irSubcommands[which]; + (*subCmdP->sC_proc)(w,cmd); + } + else if (which == -1) + { + /* ambiguous subcommand - complain */ + TxError("Ambiguous iroute subcommand: \"%s\"\n", cmd->tx_argv[1]); + } + else + { + /* unrecognized subcommand - complain */ + TxError("Unrecognized iroute subcommand: \"%s\"\n", + cmd->tx_argv[1]); + TxError("Valid iroute irSubcommands are: "); + for (n = 0; irSubcommands[n].sC_name; n++) + TxError(" %s", irSubcommands[n].sC_name); + TxError("\n"); + } + } + + /* turn printing back on, and return */ + TxPrintOn(); + return; +} diff --git a/irouter/irDebug.h b/irouter/irDebug.h new file mode 100644 index 00000000..564ce652 --- /dev/null +++ b/irouter/irDebug.h @@ -0,0 +1,37 @@ +/* + * irDebug.h -- + * + * Declarations of debugging flag "handles" for interactive router. + * + * This include file is referenced inside mzInternal.h, hence hiding this + * file from make. This is so that debuging flags can be added without + * forcing recompilation of everything. + * + * Debug flags are defined and registered with the debug module in irMain.c + * NOTE: the values of the externs defined below are NOT THE FLAG VALUES, + * rather they are handles for the flags - flags are tested with calls to + * DebugIsSet(). + * + * Flags can be examined or set by the user via the ":*iroute debug" command. + * + * ********************************************************************* + * * Copyright (C) 1987, 1990 Michael H. Arnold, Walter S. Scott, and * + * * the Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/irouter/irDebug.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + */ + +extern int irDebEndPts; /* traces endpoint processing */ +extern int irDebNoClean; /* doesn't cleanup after route, so data strucs + * can be examined. + */ diff --git a/irouter/irInternal.h b/irouter/irInternal.h new file mode 100644 index 00000000..edfd00a2 --- /dev/null +++ b/irouter/irInternal.h @@ -0,0 +1,78 @@ +/* + * irInternal.h -- + * + * This file defines data structures and constants and declares + * variables INTERNAL TO THE IROUTER + * but shared by two or more source files. + * + * Structures etc. that are exported by the irouter are defined in + * irouter.h. + * + * Structures etc. that are local to a given source + * file are declared at the top of that source file. + * + * Structures, etc., specific to a given function are usually defined at + * the head of that function. + * + * ********************************************************************* + * * Copyright (C) 1987, 1990 Michael H. Arnold, Walter S. Scott, and * + * * the Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/irouter/irInternal.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _IRINTERNAL_H +#define _IRINTERNAL_H + +#include "irouter/irouter.h" +#include "mzrouter/mzrouter.h" + +/* ------------------------ Version String -------------------------- */ +#define IROUTER_VERSION "1.0" + +/* ------------------------ Debugging flags ------------------------- */ +#include "irDebug.h" +extern ClientData irDebugID; + +/* ------------------------ Routines Global to IRouter --------------- */ +extern RouteType *irFindRouteType(); +extern RouteLayer *irFindRouteLayer(); +extern RouteContact *irFindRouteContact(); + +extern char *irRepeatChar(); + +/* ------------------------ Data Global to IRouter ------------------- */ +extern MazeParameters *irMazeParms; + +/* irRouteLayer, Contact, and Type pointers should be identical to + * corresponding fields in irMazeParms. They are referenced directly + * instead of through parms struc for historical reasons + */ +extern RouteLayer *irRouteLayers; +extern RouteContact *irRouteContacts; +extern RouteType *irRouteTypes; + +extern int irRouteWid; /* Reference window for subcell expansion + modes */ + +/* start types = methods of specifying route start */ +#define ST_CURSOR 1 +#define ST_LABEL 2 +#define ST_POINT 3 + +/* dest types = methods of specifying route destination */ +#define DT_BOX 1 +#define DT_LABEL 2 +#define DT_RECT 3 +#define DT_SELECTION 4 + +#endif /* _IRINTERNAL_H */ diff --git a/irouter/irMain.c b/irouter/irMain.c new file mode 100644 index 00000000..a36dfdee --- /dev/null +++ b/irouter/irMain.c @@ -0,0 +1,161 @@ +/* + * irMain.c -- + * + * Global data, and initialization code for the irouter. + * + * OTHER ENTRY POINTS FOR MODULE (not in this file): + * `:iroute' command - IRCommand() in irCommand.c + * `:*iroute' command - IRTest() in irTestCmd.c + * + * ********************************************************************* + * * Copyright (C) 1987, 1990 Michael H. Arnold, Walter S. Scott, and * + * * the Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/irouter/irMain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +/*--- includes --- */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" +#include "select/select.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "debug/debug.h" +#include "utils/undo.h" +#include "textio/txcommands.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "../mzrouter/mzrouter.h" +#include "irouter/irouter.h" +#include "irouter/irInternal.h" + +/*------------------------------ Global Data ------------------------------*/ + +/* Debug flags */ +ClientData irDebugID; +int irDebEndPts; /* values identify flags to debug module */ +int irDebNoClean; +int irRouteWid = -1; /* if >=0, wid of window to use for determining + * subcell expansion, and route cell. + */ + +MazeParameters *irMazeParms = NULL; /* parameter settings passed to maze router */ + +/* the following RouteEtc pointers should have the same value as the + * corresponding fileds in irMazeParms. They exist for historical + * reasons. + */ +RouteLayer *irRouteLayers; +RouteContact *irRouteContacts; +RouteType *irRouteTypes; + + +/* + * ---------------------------------------------------------------------------- + * + * IRDebugInit -- + * + * This procedure is called when Magic starts up, and should not be + * called again. + * + * Results: + * None. + * + * Side effects: + * Register ourselves with debug module + * Setup some internal datastructures. + * + * ---------------------------------------------------------------------------- + */ + +void +IRDebugInit() +{ + int n; + /* debug struct */ + static struct + { + char *di_name; + int *di_id; + } dflags[] = { + "endpts", &irDebEndPts, + "noclean", &irDebNoClean, + 0 + }; + + /* Register with debug module */ + + irDebugID = DebugAddClient("irouter", sizeof dflags/sizeof dflags[0]); + for (n = 0; dflags[n].di_name; n++) + *(dflags[n].di_id) = DebugAddFlag(irDebugID, dflags[n].di_name); + + + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * IRAfterTech -- + * + * This routine should be called after technology initialization or reloading, + * and should be called *after* the maze routere has been initialized. + * + * Results: + * None. + * + * Side effects: + * Register ourselves with debug module + * Setup some internal datastructures. + * + * ---------------------------------------------------------------------------- + */ + +void +IRAfterTech() +{ + /* Initialize the irouter maze parameters with a copy of the "irouter" + * style (default) parameters. + */ + + if (irMazeParms != NULL) + { + /* Free any existing parameters */ + MZFreeParameters(irMazeParms); + irMazeParms = NULL; + } + irMazeParms = MZCopyParms(MZFindStyle("irouter")); + + if (irMazeParms != NULL) + { + /* set global type lists from current irouter parms. + * These lists are often referenced directly rather than through + * the parameter structure for historical reasons. + */ + + irRouteLayers = irMazeParms->mp_rLayers; + irRouteContacts = irMazeParms->mp_rContacts; + irRouteTypes = irMazeParms->mp_rTypes; + } +} diff --git a/irouter/irRoute.c b/irouter/irRoute.c new file mode 100644 index 00000000..b112869b --- /dev/null +++ b/irouter/irRoute.c @@ -0,0 +1,1187 @@ +/* + * irRoute.c -- + * + * Sets up route and calls maze router to do it. + * + * ********************************************************************* + * * Copyright (C) 1987, 1990 Michael H. Arnold, Walter S. Scott, and * + * * the Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/irouter/irRoute.c,v 1.3 2008/12/11 04:20:08 tim Exp $"; +#endif /* not lint */ + +/* --- Includes --- */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "drc/drc.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "debug/debug.h" +#include "utils/undo.h" +#include "utils/signals.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "utils/geofast.h" +#include "utils/touchingtypes.h" +#include "select/select.h" +#include "../mzrouter/mzrouter.h" +#include "irouter/irouter.h" +#include "irouter/irInternal.h" + +/* --- Routines local to this file that are referenced before they are + * defined --- */ +List *irChooseEndPtLayers(); + +/* -------------------- Structures Local to this File -------------------- */ + +/* clientdata structure passed to filter functions when searching for + * start and destination labels. + */ +typedef struct labelSearchData +{ + Rect lsd_locRect; /* set to labels location by filter func */ + char *lsd_name; /* label name to search for */ + TileType lsd_type; /* layer that label is attached to */ + int lsd_result; /* code giving result of search */ +} LabelSearchData; + +/* result codes for lsd_result above */ +#define LSR_NOTFOUND 10 +#define LSR_NOTUNIQUE 20 +#define LSR_FOUND 30 + + +/* + * ---------------------------------------------------------------------------- + * + * irRoute -- + * + * Top level procedure for the routing code. Initializes things, and + * calls the maze router to make a connection. + * + * Results: + * Passes back the result code of MZRoute() (see mzrouter.h for codes) + * + * Side effects: + * Paint route into editcell. + * + * ---------------------------------------------------------------------------- + */ + +int +irRoute(cmdWindow, startType, argStartPt, argStartLabel, argStartLayers, + destType, argDestRect, argDestLabel, argDestLayers) + MagWindow *cmdWindow; /* window route command issued to */ + int startType; /* how start is specified */ + Point *argStartPt; /* location to route from (in edit cell coords) */ + char *argStartLabel; /* label to route from */ + List *argStartLayers; /* OK route layers to start route on */ + int destType; /* how dest is specified */ + Rect *argDestRect; /* location to route to (in edit cell coords) */ + char *argDestLabel; /* label to route to */ + List *argDestLayers; /* OK route layers to end route on */ +{ + CellUse *routeUse; /* Toplevel cell visible during routing */ + int expansionMask; /* Subcell expansion modes to use during + * routing */ + Point startPt; /* start and dest terminals */ + List *startLayers = NULL; + Rect destRect; + List *destLayers = NULL; + RoutePath *path = NULL; /* resulting path */ + TileType startLayer = TT_SPACE; + int mzResult = MZ_NO_ACTION; + + /* determine routeUse and expansionMask for this route. */ + { + MagWindow *window = NULL; + + /* find global reference window */ + if(irRouteWid>=0) + { + window = WindSearchWid(irRouteWid); + if (window == NULL) + { + TxError("Couldn't find route window (%d),", irRouteWid); + TxError("using command window as reference.\n"); + } + } + + /* if no global reference window, use window command issued from */ + if(window == NULL) + { + window = cmdWindow; + } + + /* If reference window is nil, complain and exit */ + if(window==NULL) + { + TxError("Point to a layout window first.\n"); + return mzResult; + } + + /* Set expansion mask to window route cmd issued to. Used + * during searches. Subcells are treated as expanded if expanded in + * window cmd issued to. + */ + expansionMask = ((DBWclientRec *)(window->w_clientData))->dbw_bitmask; + + /* Set routeUse to rootuse of reference window - + * everything "visible" in + * the reference window is visible + * during routing. + * But resulting route + * is painted into edit cell. This distinction is important only + * in the case of a subedit. If the user subedits a cell, the + * context of the parent(s) will guide the route, but the route + * will be painted into the edit cell. + */ + routeUse = (CellUse *) (window->w_surfaceID); + + /* make sure cmd issued from window in which edit cell + * is being edited */ + if (!EditCellUse || EditRootDef != routeUse->cu_def) + { + TxError("Nothing being edited in route window.\n"); + return mzResult; + } + } + + /* initialize mzrouter */ + MZInitRoute(irMazeParms, routeUse, expansionMask); + + /* Figure out start coordinates */ + { + Point irGetStartPoint(); + + startPt = irGetStartPoint(startType, + argStartPt, + argStartLabel, + &startLayer, + routeUse); + + /* check for failure */ + if(startPt.p_x == MINFINITY) goto abort; + } + + /* Set maze router dest area(s) */ + + if(destType == DT_SELECTION) + /* add destination area for each selected area on an appropriate layer */ + { + int irSelectedTileFunc(); + + if(argDestLayers == NULL) + /* no layer arg specified, generate dest areas for each active + * route layer + */ + { + RouteLayer *rL; + + for (rL = irRouteLayers; rL != NULL; rL = rL->rl_next) + { + if(rL->rl_routeType.rt_active) + { + /* set dest area for each selected tile + * of type connecting to rL + */ + SelEnumPaint( + &(DBConnectTbl[rL->rl_routeType.rt_tileType]), + FALSE, /* TRUE = restricted to edit cell */ + NULL, /* not used */ + irSelectedTileFunc, + (ClientData *) rL /* type of destarea */ + ); + } + } + } + else + /* generate dest areas for layers that are both specified and active */ + { + List *l; + + for(l=argDestLayers; l!=NULL; l=LIST_TAIL(l)) + { + RouteLayer *rL = (RouteLayer *) LIST_FIRST(l); + + if(rL->rl_routeType.rt_active) + { + /* set dest area for each selected tile + * of type connecting to rL + */ + SelEnumPaint( + &(DBConnectTbl[rL->rl_routeType.rt_tileType]), + FALSE, /* TRUE = restricted to edit cell */ + NULL, /* not used */ + irSelectedTileFunc, + (ClientData *) rL /* type of destarea */ + ); + } + } + } + } + else + /* dest is defined by rectangle */ + { + Rect irGetDestRect(); + TileType destLayer = TT_SPACE; + + destRect = irGetDestRect(destType, + argDestRect, + argDestLabel, + &destLayer, + routeUse); + + /* check for failure */ + if(destRect.r_xtop == MINFINITY) goto abort; + + /* set a maze router dest area for extent of destRect + * on each permitted dest layer. + */ + if (destLayer != TT_SPACE) + { + RouteLayer *rL; + + /* layer type returned by irGetDestRect */ + + for(rL = irRouteLayers; rL != NULL; rL = rL->rl_next) + { + if (rL->rl_routeType.rt_active && + TTMaskHasType(&(DBConnectTbl[destLayer]), + rL->rl_routeType.rt_tileType)) + { + MZAddDest(&destRect, rL->rl_routeType.rt_tileType); + break; + } + } + } + else if (argDestLayers == NULL) + { + /* no layer arg specified, permit all active route layers */ + RouteLayer *rL; + + for (rL = irRouteLayers; rL != NULL; rL = rL->rl_next) + { + if(rL->rl_routeType.rt_active) + { + MZAddDest(&destRect,rL->rl_routeType.rt_tileType); + } + } + } + else + /* permit only layers that are both specified and active */ + { + List *l; + + for(l=argDestLayers; l!=NULL; l=LIST_TAIL(l)) + { + RouteLayer *rL = (RouteLayer *) LIST_FIRST(l); + + if(rL->rl_routeType.rt_active) + { + MZAddDest(&destRect,rL->rl_routeType.rt_tileType); + + } + } + } + } + + if (startLayer != TT_SPACE) + { + RouteLayer *rL; + + /* layer type returned by irGetStartPoint */ + + for (rL = irRouteLayers; rL != NULL; rL = rL->rl_next) + { + if (rL->rl_routeType.rt_active && + TTMaskHasType(&(DBConnectTbl[startLayer]), + rL->rl_routeType.rt_tileType)) + + { + MZAddStart(&startPt, rL->rl_routeType.rt_tileType); + break; + } + } + } + else + { + /* Determine OK start layers */ + + List *l; + + startLayers = irChooseEndPtLayers( + routeUse, + expansionMask, + &startPt, + argStartLayers, + "start"); + if(SigInterruptPending) goto abort; + + if(DebugIsSet(irDebugID,irDebEndPts)) + { + TxPrintf("----- startLayers:\n"); + MZPrintRLListNames(startLayers); + } + + /* Set maze router start point(s) - one for each ok layer */ + + for(l=startLayers; l!=NULL;l=LIST_TAIL(l)) + { + RouteLayer *rL = (RouteLayer *)LIST_FIRST(l); + TileType type = rL->rl_routeType.rt_tileType; + + MZAddStart(&startPt, type); + } + } + + /* Do the Route */ + path = MZRoute(&mzResult); + /* If MZRoute is interrupted it returns best path + * found so far. + */ + + if(SigInterruptPending) + { + if(path==NULL) + { + goto abort; + } + else + { + TxError("Search Interrupted!\n"); + TxPrintf("Using best path found prior to interrupt.\n"); + + /* Clear interrupt to allow paint back of path */ + SigInterruptPending = FALSE; + } + } + + /* paint route back into edit cell */ + if (path) + { + + RouteLayer *finalRL = path->rp_rLayer; + CellUse *resultUse; + + /* Have MazeRouter paint path into resultCell */ + resultUse = MZPaintPath(path); + if(SigInterruptPending) goto abort; + + /* Copy to edit cell transforming from root to edit + * coords. + * Also select the entire route. + * This paint job is undoable. + */ + { + SearchContext scx; + + scx.scx_use = resultUse; + scx.scx_area = resultUse->cu_def->cd_bbox; + scx.scx_trans = RootToEditTransform; + (void) DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, EditCellUse); + DBReComputeBbox(EditCellUse->cu_def); + } + + /* Select the route */ + { + SearchContext scx; + + /* Clear selection, and set selection display for reference + * window and other windows containing routeUse as root. + */ + SelectClear(); + if(SelectRootDef != routeUse->cu_def) + { + SelectRootDef = routeUse->cu_def; + SelSetDisplay(SelectUse, SelectRootDef); + } + + /* Copy route to selection cell, notifying undo of change */ + scx.scx_use = resultUse; + scx.scx_area = resultUse->cu_def->cd_bbox; + scx.scx_trans = GeoIdentityTransform; + SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL); + (void) DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, SelectUse); + SelRememberForUndo(FALSE, SelectRootDef, &(scx.scx_area)); + + /* Setup redisplay */ + DBReComputeBbox(SelectDef); + DBWHLRedraw(SelectRootDef, &(scx.scx_area), TRUE); + DBWAreaChanged(SelectDef, &SelectDef->cd_bbox, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + } + + /* Notify dbwind module (for redisplay), and DRC module + * of changed area */ + { + Rect changedArea; + + GeoTransRect( + &RootToEditTransform, + &(resultUse->cu_def->cd_bbox), + &changedArea); + DBWAreaChanged(EditCellUse->cu_def, &changedArea, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + DRCCheckThis(EditCellUse->cu_def, TT_CHECKPAINT, &changedArea); + + } + + /* Make sure we got here without interruption */ + if(SigInterruptPending) goto abort; + + TxPrintf("Done Routing.\n"); + TxFlushOut(); + } + else + { + TxError("Route Failed.\n"); + } + +abort: + if(SigInterruptPending) + { + TxError("Route Interrupted!\n"); + } + + ListDealloc(startLayers); + ListDealloc(destLayers); + + /* reclaim storage used by mzrouter */ + if(!DebugIsSet(irDebugID, irDebNoClean)) + { + MZClean(); + } + + return mzResult; +} + + +/* + * --------------------------------------------------------------------- + * + * irGetStartPoint -- + * + * Compute start point. + * + * Results: + * Returns point. + * + * Side effects: + * Returns start layer type in startLayerPtr. + * + * --------------------------------------------------------------------- + */ + +Point +irGetStartPoint(startType, argStartPt, argStartLabel, startLayerPtr, routeUse) + int startType; /* how start is specified */ + Point *argStartPt; /* location to route from + * (in edit cell coords) */ + char *argStartLabel; /* label to route from */ + TileType *startLayerPtr; /* layer type (returned value) */ + CellUse *routeUse; /* toplevel cell visible to router */ +{ + Point startPt; + + switch (startType) + { + case ST_POINT: + /* start point coords given */ + { + /* convert from edit to routeUse coords (= root coordinates) */ + GeoTransPoint(&EditToRootTransform,argStartPt,&startPt); + } + break; + + case ST_CURSOR: + /* use cursor */ + { + MagWindow *pointWindow; + + pointWindow = ToolGetPoint(&startPt, (Rect *) NULL); + + if (pointWindow == NULL) + { + TxError("Can not use cursor as start:"); + TxError(" cursor not in layout window.\n"); + goto abort; + } + + if (routeUse->cu_def != + ((CellUse *)pointWindow->w_surfaceID)->cu_def) + { + TxError("Can not use cursor as start:"); + TxError("cursor not in routecell.\n"); + goto abort; + } + } + break; + + case ST_LABEL: + /* label name given */ + { + int irSelLabelsFunc(); + int irAllLabelsFunc(); + LabelSearchData lSD; + lSD.lsd_name = argStartLabel; /* name to match */ + lSD.lsd_result = LSR_NOTFOUND; + + /* first search selection */ + (void) SelEnumLabels(&DBAllTypeBits, + FALSE, /* TRUE = search only edit cell */ + (bool *) NULL, + irSelLabelsFunc, + (ClientData) &lSD); + + if(SigInterruptPending) goto abort; + + if (lSD.lsd_result == LSR_NOTUNIQUE) + { + TxError("Warning: Start label '%s' not unique.\n", argStartLabel); + } + else if (lSD.lsd_result == LSR_NOTFOUND) + /* No selected label matched, so search all labels */ + { + + (void) DBSrLabelLoc(routeUse, + argStartLabel, + irAllLabelsFunc, + (ClientData) &lSD); + + if(SigInterruptPending) goto abort; + + if (lSD.lsd_result == LSR_NOTUNIQUE) + { + TxError("Warning: Start label '%s' not unique.\n", argStartLabel); + } + else if (lSD.lsd_result == LSR_NOTFOUND) + { + TxError("Start label '%s' not found.\n", + argStartLabel); + goto abort; + } + } + + startPt = lSD.lsd_locRect.r_ll; + if (startLayerPtr) *startLayerPtr = lSD.lsd_type; + } + break; + + default: + /* shouldn't happen */ + { + ASSERT(FALSE,"irGetStartPoint"); + } + break; + } + + return startPt; + +abort: + startPt.p_x = MINFINITY; + startPt.p_y = MINFINITY; + return startPt; +} + + +/* + * --------------------------------------------------------------------- + * + * irGetDestRect -- + * + * Compute destination rectangle. + * + * Results: + * Returns rect. + * + * Side effects: + * Returns layer type in destLayerPtr. + * + * --------------------------------------------------------------------- + */ + +Rect +irGetDestRect(destType, argDestRect, argDestLabel, destLayerPtr, routeUse) + int destType; /* how dest is specified */ + Rect *argDestRect; /* location to route to + * (in edit cell coords) */ + char *argDestLabel; /* label to route to */ + TileType *destLayerPtr; /* layer type (returned value) */ + CellUse *routeUse; /* toplevel cell visible to router */ +{ + Rect destRect; + + switch (destType) + { + case DT_RECT: + /* dest rect coords given */ + { + /* convert from edit to routeUse coords (= root coordinates) */ + GeoTransRect(&EditToRootTransform,argDestRect,&destRect); + } + break; + + case DT_LABEL: + /* dest rect given as label */ + { + int irSelLabelsFunc(); + int irAllLabelsFunc(); + LabelSearchData lSD; + lSD.lsd_name = argDestLabel; /* name to match */ + lSD.lsd_result = LSR_NOTFOUND; + + /* first search selection */ + (void) SelEnumLabels(&DBAllTypeBits, + FALSE, /* TRUE = search only edit cell */ + (bool *) NULL, + irSelLabelsFunc, + (ClientData) &lSD); + if(SigInterruptPending) goto abort; + + if (lSD.lsd_result == LSR_NOTUNIQUE) + { + TxError("Warning: Destination label '%s' not unique.\n", argDestLabel); + } + else if (lSD.lsd_result == LSR_NOTFOUND) + { + /* No selected label matched, so search all labels */ + (void) DBSrLabelLoc(routeUse, + argDestLabel, + irAllLabelsFunc, + (ClientData) &lSD); + if(SigInterruptPending) goto abort; + + if (lSD.lsd_result == LSR_NOTUNIQUE) + { + TxError("Warning: Destination label '%s' not unique.\n", + argDestLabel); + } + else if (lSD.lsd_result == LSR_NOTFOUND) + { + TxError("Destination label '%s' not found.\n", + argDestLabel); + goto abort; + } + } + + destRect = lSD.lsd_locRect; + if (destLayerPtr) *destLayerPtr = lSD.lsd_type; + } + break; + + case DT_BOX: + /* use box as dest rect */ + { + CellDef *boxDef; + Rect box; + + if(!ToolGetBox(&boxDef,&box)) + { + TxError("Can not use box for dest: No Box.\n"); + goto abort; + } + + if (boxDef != routeUse->cu_def) + { + TxError("Can not use box for dest: "); + TxError("box not in route cell.\n"); + goto abort; + } + + destRect = box; + } + break; + + default: + /* shouldn't happen */ + { + ASSERT(FALSE,"irGetDestRect"); + } + break; + } + + return destRect; + +abort: + destRect.r_xbot = MINFINITY; + destRect.r_ybot = MINFINITY; + destRect.r_xtop = MINFINITY; + destRect.r_ytop = MINFINITY; + return destRect; +} + +/* + * --------------------------------------------------------------------- + * + * irSelLabelsFunc -- + * + * Called by SelEnumLabels on behalf of irRoute above, to find selected + * label of given name. + * + * Results: + * Returns 0 on first match, 1 on second match (to terminate search) + * + * Side effects: + * Sets locRect in clientdata arg location off matching label. + * + * --------------------------------------------------------------------- + */ + +int +irSelLabelsFunc(label, cellUse, transform, clientData) + Label *label; + CellUse *cellUse; + Transform *transform; + ClientData clientData; +{ + LabelSearchData *lsd = (LabelSearchData *)clientData; + CellDef *cellDef = cellUse->cu_def; + + if (strcmp(lsd->lsd_name, label->lab_text) != 0) + { + /* this label doesn't match, continue search */ + return 0; + } + else if (lsd->lsd_result == LSR_FOUND) + { + /* second match, set result and terminate search */ + lsd->lsd_result = LSR_NOTUNIQUE; + return 1; + } + else + { + /* first match, set location, result, and continue search */ + GeoTransRect(transform, + &(label->lab_rect), &(lsd->lsd_locRect)); + lsd->lsd_result = LSR_FOUND; + lsd->lsd_type = label->lab_type; + return 0; + } +} + + +/* + * --------------------------------------------------------------------- + * + * irAllLabelsFunc -- + * + * Called by DBSrLabelLoc on behalf of irRoute above, to convert labelName + * to location of label with matching name. + * + * Results: + * Returns 0 on first match, 1 on second match (to terminate search) + * + * Side effects: + * Sets locRect in clientdata arg to location of matching label. + * + * --------------------------------------------------------------------- + */ + +int +irAllLabelsFunc(rect, name, label, clientData) + Rect *rect; + char *name; + Label *label; + ClientData clientData; +{ + LabelSearchData *lsd = (LabelSearchData *)clientData; + + if (lsd->lsd_result == LSR_FOUND) + { + if (GEO_SAMERECT(lsd->lsd_locRect, *rect)) return 0; + + /* second match, so set result and terminate search */ + lsd->lsd_result = LSR_NOTUNIQUE; + return 1; + } + else + { + /* first match, so set location, result, and continue search */ + lsd->lsd_locRect = *rect; + lsd->lsd_type = label->lab_type; + lsd->lsd_result = LSR_FOUND; + return 0; + } +} + + +/* + * --------------------------------------------------------------------- + * + * irSelectedTileFunc -- + * + * Called by SelEnumPaint on behalf of irRoute above, to process tile + * associated with selection rect. + * + * Results: + * Always returns 0 to continue search. + * + * Side effects: + * Call MzAddDest on selected area. + * + * --------------------------------------------------------------------- + */ + +int +irSelectedTileFunc(rect, type, c) + Rect *rect; + TileType type; + ClientData c; +{ + RouteLayer *rL = (RouteLayer *) c; + MZAddDest(rect, rL->rl_routeType.rt_tileType); + + /* return 0 to continue search */ + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * LayerInTouchingContact -- + * + * A Predicate. Checks whether the given routeLayer is a component of a + * contact type in touchingTypes. Used by irChooseEndPtLayers below. + * + * Results: + * TRUE if the RouteLayer is a component of a contact type in + * touchingTypes, else FALSE. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +LayerInTouchingContact(rL,touchingTypes) + RouteLayer *rL; + TileTypeBitMask touchingTypes; +{ + RouteContact *rC; + + for(rC=irRouteContacts; rC!=NULL; rC=rC->rc_next) + { + if(TTMaskHasType(&touchingTypes,rC->rc_routeType.rt_tileType) && + (rC->rc_rLayer1==rL || rC->rc_rLayer2==rL)) + return(TRUE); + } + + return(FALSE); +} + + +/* + * ---------------------------------------------------------------------------- + * + * irChooseEndPtLayers -- + * + * Figure out what layers are ok at an endpoint - if ambiguous ask user. + * + * Results: + * List of ok layers at endpoint. + * + * Side effects: + * May query user about intended layers at an endpoint. + * + * ---------------------------------------------------------------------------- + */ + +List * +irChooseEndPtLayers(routeUse,expansionMask,endPt,argLayers,endPtName) + CellUse *routeUse; + int expansionMask; /* mask of expanded subcells */ + Point *endPt; + List *argLayers; + char *endPtName; +{ + List *activeLayers; + List *presentLayers; + List *presentContacts; + List *presentContactLayers; + + static char *actionNames[] = { "no", "yes", 0 }; + + List *l; + RouteLayer *rL; + + if (DebugIsSet(irDebugID, irDebEndPts)) + { + TxPrintf("----- argLayers:\n"); + MZPrintRLListNames(argLayers); + } + + /* find activeLayers among argLayers (or irRouteLayers if argLayers NULL) */ + activeLayers = NULL; + if(argLayers) + { + /* layers given in arg, search these */ + for(l=argLayers; l!=NULL; l=LIST_TAIL(l)) + { + rL = (RouteLayer*) LIST_FIRST(l); + if(rL->rl_routeType.rt_active) + { + LIST_ADD(rL,activeLayers); + } + } + } + else + { + /* no layers given as arg, so search all route layers */ + for(rL=irRouteLayers; rL!=NULL; rL=rL->rl_next) + if(rL->rl_routeType.rt_active) + { + LIST_ADD(rL,activeLayers); + } + } + + if (DebugIsSet(irDebugID, irDebEndPts)) + { + TxPrintf("----- activeLayers:\n"); + MZPrintRLListNames(activeLayers); + } + + /* make lists of contacts (connecting two active layers) and + * active layers which are present at the end point. + */ + { + TileTypeBitMask touchingTypes; + RouteContact *rC; + + touchingTypes = TouchingTypes(routeUse, expansionMask, endPt); + + /* Make list of present and active contacts */ + presentContacts = NULL; + presentContactLayers = NULL; + for(rC =irRouteContacts; rC!=NULL; rC=rC->rc_next) + { + if(TTMaskHasType(&touchingTypes,rC->rc_routeType.rt_tileType) && + ListContainsP(rC->rc_rLayer1, activeLayers) && + ListContainsP(rC->rc_rLayer2, activeLayers)) + { + LIST_ADD(rC, presentContacts); + LIST_ADD(rC->rc_rLayer1, presentContactLayers); + LIST_ADD(rC->rc_rLayer2, presentContactLayers); + } + } + + if (DebugIsSet(irDebugID, irDebEndPts)) + { + TxPrintf("----- presentContacts:\n"); + MZPrintRCListNames(presentContacts); + + TxPrintf("----- presentContactLayers:\n"); + MZPrintRLListNames(presentContactLayers); + } + + + /* make list of present layers that are not constituents of contacts + * above. If a contact is touching the endpt but one of + * its constituent layers in not active, the other constituent + * layer is treated as a presentLayer. + */ + presentLayers = NULL; + for(l=activeLayers; l!=NULL; l=LIST_TAIL(l)) + { + rL = (RouteLayer *) LIST_FIRST(l); + if((TTMaskHasType(&touchingTypes,rL->rl_routeType.rt_tileType) || + LayerInTouchingContact(rL,touchingTypes)) && + !ListContainsP(rL, presentContactLayers)) + { + LIST_ADD(rL,presentLayers); + } + } + + if (DebugIsSet(irDebugID, irDebEndPts)) + { + TxPrintf("----- presentLayers:\n"); + MZPrintRLListNames(presentLayers); + } + } + + /* return appropriate layer list. */ + { + int numContacts, numLayers; + + numContacts = ListLength(presentContacts); + numLayers = ListLength(presentLayers); + + if(numLayers == 0 && numContacts == 0) + { + /* No Layers present at endpt, return list of all active layers */ + ListDealloc(presentLayers); + ListDealloc(presentContacts); + ListDealloc(presentContactLayers); + + return(activeLayers); + } + else if(numLayers == 1 && numContacts == 0) + { + /* Exactly one layer is both active and present, return list + * containing only this layer. + */ + ListDealloc(activeLayers); + ListDealloc(presentContacts); + ListDealloc(presentContactLayers); + + return(presentLayers); + } + else if(numLayers == 0 && numContacts == 1) + { + /* Just one active contact under endpoint, + * return layers connecting to that contact. + */ + List *l; + RouteContact *rC; + + rC = (RouteContact *) LIST_FIRST(presentContacts); + l = (List *) NULL; + LIST_ADD(rC->rc_rLayer1,l); + LIST_ADD(rC->rc_rLayer2,l); + + ListDealloc(activeLayers); + ListDealloc(presentLayers); + ListDealloc(presentContacts); + ListDealloc(presentContactLayers); + + return(l); + } + else + { + /* Multiple nodes active and present, ask user which one + * he wants to route to. + */ + char answer[100]; + RouteLayer *rL; + RouteLayer *pickedRL; + RouteContact *rC; + RouteContact *pickedRC; + + TxPrintf("Multiple nodes present at %s point:", + endPtName); + for(l=presentContacts; l!=NULL; l=LIST_TAIL(l)) + { + rC=(RouteContact *) LIST_FIRST(l); + TxPrintf(" %s", + DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]); + } + for(l=presentLayers; l!=NULL; l=LIST_TAIL(l)) + { + rL=(RouteLayer *) LIST_FIRST(l); + TxPrintf(" %s", + DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]); + } + TxPrintf("\n"); + + for(pickedRC=FALSE,l=presentContacts; l && !pickedRC; l=LIST_TAIL(l)) + { + rC = (RouteContact *) LIST_FIRST(l); + if (!LIST_TAIL(l) && !presentLayers) + { + /* last choice, so take it */ + pickedRC = rC; + } + else + { + /* ask user */ + TxPrintf("Connect to %s? [yes] ", + DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]); + if (TxGetLine(answer, sizeof answer) == NULL || + answer[0] == '\0') + (void) strcpy(answer,"yes"); + + if(Lookup(answer, actionNames) == 1) + { + /* Yes */ + pickedRC = rC; + } + } + } + + if(pickedRC) + { + List *l; + + l=NULL; + LIST_ADD(rC->rc_rLayer1,l); + LIST_ADD(rC->rc_rLayer2,l); + ListDealloc(activeLayers); + ListDealloc(presentLayers); + ListDealloc(presentContacts); + ListDealloc(presentContactLayers); + + return(l); + } + + for(pickedRL=NULL,l=presentLayers; l && !pickedRL; l=LIST_TAIL(l)) + { + rL = (RouteLayer *) LIST_FIRST(l); + if(!LIST_TAIL(l)) + { + /* Last choice so choose it automatically */ + pickedRL=rL; + } + else + { + /* Ask user */ + TxPrintf("Connect to %s? [yes] ", + DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]); + if (TxGetLine(answer, sizeof answer) == NULL || + answer[0] == '\0') + (void) strcpy(answer,"yes"); + + if(Lookup(answer, actionNames) == 1) + { + /* Yes */ + pickedRL = rL; + } + } + } + + if(pickedRL) + { + l=NULL; + LIST_ADD(rL,l); + ListDealloc(activeLayers); + ListDealloc(presentLayers); + ListDealloc(presentContacts); + ListDealloc(presentContactLayers); + + return(l); + } + + /* User didn't pick anything, return null list */ + { + ListDealloc(activeLayers); + ListDealloc(presentLayers); + ListDealloc(presentContacts); + ListDealloc(presentContactLayers); + + return(NULL); + } + + } + } +} diff --git a/irouter/irTestCmd.c b/irouter/irTestCmd.c new file mode 100644 index 00000000..39c5b472 --- /dev/null +++ b/irouter/irTestCmd.c @@ -0,0 +1,311 @@ +/* + * irTestCmd.c -- + * + * Code to process the `*iroute' command. + * `*iroute' is a wizard command for debugging and testing. + * + * ********************************************************************* + * * Copyright (C) 1987, 1990 Michael H. Arnold, Walter S. Scott, and * + * * the Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/irouter/irTestCmd.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "irouter/irouter.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "dbwind/dbwtech.h" +#include "textio/txcommands.h" +#include "utils/main.h" +#include "utils/utils.h" +#include "commands/commands.h" +#include "utils/styles.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "../mzrouter/mzrouter.h" +#include "irouter/irInternal.h" + +/* Subcommand table - declared here since its referenced before defined */ +typedef struct +{ + char *sC_name; /* name of iroute subcommand */ + void (*sC_proc)(); /* Procedure implementing this subcommand */ + char *sC_commentString; + char *sC_usage; +} TestCmdTableE; +extern TestCmdTableE irTestCommands[]; + + +/* + * ---------------------------------------------------------------------------- + * + * irDebugTstCmd -- + * + * irouter wizard command (`:*iroute') to set/clear debug flags. + * + * Results: + * None. + * + * Side effects: + * Modify debug flags. + * + * ---------------------------------------------------------------------------- + */ + +void +irDebugTstCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int result; + bool value; + + if (cmd->tx_argc > 4) + { + TxPrintf("Too many args on '*iroute debug'\n"); + return; + } + else if (cmd->tx_argc == 4) + { + /* two args, set or clear first arg according to second */ + + result = SetNoisyBool(&value,cmd->tx_argv[3], (FILE *) NULL); + if (result == 0) + { + TxPrintf("\n"); + DebugSet(irDebugID,1,&(cmd->tx_argv[2]),(bool) value); + } + else + TxError("Unknown boolean value %s\n", cmd->tx_argv[2]); + } + else + { + /* list current values of flags */ + DebugShow(irDebugID); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irHelpTstCmd -- + * + * irouter wizard command (`:*iroute') to print help info on irouter wizard + * commands. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +irHelpTstCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int n; + int which; + + if(cmd->tx_argc == 2) + { + /* No arg, so print summary of commands */ + for(n=0; irTestCommands[n].sC_name!=NULL; n++) + { + TxPrintf("*iroute %s - %s\n", + irTestCommands[n].sC_name, + irTestCommands[n].sC_commentString); + } + TxPrintf("\n*iroute help [subcmd] - "); + TxPrintf("Print usage info for subcommand.\n"); + } + else + { + /* Lookup subcommand in table, and printed associated help info */ + which = LookupStruct( + cmd->tx_argv[2], + (char **) irTestCommands, + sizeof irTestCommands[0]); + + /* Process result of lookup */ + if (which >= 0) + { + /* subcommand found - print out its comment string and usage */ + TxPrintf("*iroute %s - %s\n", + irTestCommands[which].sC_name, + irTestCommands[which].sC_commentString); + TxPrintf("Usage: *iroute %s\n", + irTestCommands[which].sC_usage); + } + else if (which == -1) + { + /* ambiguous subcommand - complain */ + TxError("Ambiguous *iroute subcommand: \"%s\"\n", cmd->tx_argv[2]); + } + else + { + /* unrecognized subcommand - complain */ + TxError("Unrecognized iroute subcommand: \"%s\"\n", + cmd->tx_argv[2]); + TxError("Valid *iroute subcommands are: "); + for (n = 0; irTestCommands[n].sC_name; n++) + TxError(" %s", irTestCommands[n].sC_name); + TxError("\n"); + } + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * irParmsTstCmd -- + * + * irouter wizard command (`:*iroute') to dump parms. + * commands. + * + * Results: + * None. + * + * Side effects: + * Dump routelayers and routecontacts. + * + * ---------------------------------------------------------------------------- + */ + +void +irParmsTstCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + + MZPrintRLs(irRouteLayers); + TxMore(""); + MZPrintRCs(irRouteContacts); + + return; +} + +/*--------------------------- Command Table ------------------------------ */ +TestCmdTableE irTestCommands[] = { + "debug", irDebugTstCmd, + "set or clear debug flags", + "debug [flag] [value]", + + "help", irHelpTstCmd, + "summarize *iroute subcommands", + "help [subcommand]", + + "parms", irParmsTstCmd, + "print internal data structures", + "parms", + + 0 + }, *irTestCmdP; + + +/* + * ---------------------------------------------------------------------------- + * + * IRTest -- + * + * Command interface for testing the interactive router. + * + * Results: + * None. + * + * Side effects: + * Depends on the command; see below. + * + * Organization: + * We select a procedure based on the first keyword (argv[0]) + * and call it to do the work of implementing the rule. Each + * such procedure is of the following form: + * + * int + * proc(argc, argv) + * int argc; + * char *argv[]; + * { + * } + * + * ---------------------------------------------------------------------------- + */ + +void +IRTest(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int n; + int which; + + + if(cmd->tx_argc == 1) + { + /* No subcommand specified. */ + TxPrintf("Must specify subcommand."); + TxPrintf(" (type '*iroute help' for summary)\n"); + } + else + { + /* Lookup subcommand in table */ + which = LookupStruct( + cmd->tx_argv[1], + (char **) irTestCommands, + sizeof irTestCommands[0]); + + /* Process result of lookup */ + if (which >= 0) + { + /* subcommand found - call proc that implements it */ + irTestCmdP = &irTestCommands[which]; + (*irTestCmdP->sC_proc)(w,cmd); + } + else if (which == -1) + { + /* ambiguous subcommand - complain */ + TxError("Ambiguous subcommand: \"%s\"\n", cmd->tx_argv[1]); + } + else + { + /* unrecognized subcommand - complain */ + TxError("Unrecognized subcommand: \"%s\"\n", cmd->tx_argv[1]); + TxError("Valid subcommands:"); + for (n = 0; irTestCommands[n].sC_name; n++) + TxError(" %s", irTestCommands[n].sC_name); + TxError("\n"); + } + } + + return; +} diff --git a/irouter/irUtils.c b/irouter/irUtils.c new file mode 100644 index 00000000..9192f80d --- /dev/null +++ b/irouter/irUtils.c @@ -0,0 +1,164 @@ +/* + * irUtils.c --- + * + * Misc. utility routines for irouter. + * + * + * ********************************************************************* + * * Copyright (C) 1987, 1990 Michael H. Arnold, Walter S. Scott, and * + * * the Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/irouter/irUtils.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/list.h" +#include "mzrouter/mzrouter.h" +#include "irouter/irouter.h" +#include "irouter/irInternal.h" + + +/* + * ---------------------------------------------------------------------------- + * + * irFindRouteType -- + * + * Search irRouteLayers and irRouteContacts lists for routeType of given + * tile type. + * + * Results: + * pointer to routetype struc if found, else Null. + * + * ---------------------------------------------------------------------------- + */ + +RouteType * +irFindRouteType(type) + TileType type; +{ + RouteType *rT; + + /* Search list of routetypes for one with appropriate type */ + for (rT = irRouteTypes; + rT && rT->rt_tileType!=type; + rT=rT->rt_next) + ; + + /* return result */ + return(rT); +} + + +/* + * ---------------------------------------------------------------------------- + * + * irFindRouteLayer -- + * + * search irRouteLayers struc for given tiletype. + * + * Results: + * pointer to routelayer struc if found, else Null. + * + * ---------------------------------------------------------------------------- + */ + +RouteLayer * +irFindRouteLayer(type) + TileType type; +{ + RouteLayer *rL; + + /* Search list of routelayers for one with appropriate type */ + for (rL = irRouteLayers; + rL && rL->rl_routeType.rt_tileType!=type; + rL=rL->rl_next) + ; + + /* return result */ + return(rL); +} + + +/* + * ---------------------------------------------------------------------------- + * + * irFindRouteContact -- + * + * Search irRoutecontacts for given tiletype. + * + * Results: + * pointer to routecontact struc if found, else Null. + * + * ---------------------------------------------------------------------------- + */ + +RouteContact * +irFindRouteContact(type) + TileType type; +{ + RouteContact *rC; + + /* Search list of routecontacts for one with appropriate type */ + for (rC = irRouteContacts; + rC && rC->rc_routeType.rt_tileType!=type; + rC=rC->rc_next) + ; + + /* return result */ + return(rC); +} + + +/* + * ---------------------------------------------------------------------------- + * + * irRepeatChar -- + * + * Build temporary string consisting of n repetitions of a character. + * + * Results: + * Pointer to temporary string. + * + * Side effects: + * RepeatString set to desired string. + * + * Note: + * A call to this procedure destroys old strings previously built + * by the procedure. + * + * ---------------------------------------------------------------------------- + */ + +char RepeatString[100]; + +char * +irRepeatChar(n,c) + int n; + char c; +{ + int i; + for(i=0; i +#include +#include +#include +#include +#include +#include /* for roundf() function, if std=c99 */ + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/undo.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/malloc.h" +#include "graphics/graphics.h" +#include "utils/main.h" +#include "cif/cif.h" +#include "lef/lefInt.h" + +/* + *------------------------------------------------------------ + * + * DefAddRoutes -- + * + * Parse a network route statement from the DEF file, + * and add it to the linked list representing the route. + * + * Results: + * Returns the last token encountered. + * + * Side Effects: + * Reads from input stream; + * Adds information to the layout database. + * + *------------------------------------------------------------ + */ + +char * +DefAddRoutes(rootDef, f, oscale, special, defLayerMap) + CellDef *rootDef; /* Cell to paint */ + FILE *f; /* Input file */ + float oscale; /* Scale factor between LEF and magic units */ + bool special; /* True if this section is SPECIALNETS */ + LefMapping *defLayerMap; /* magic-to-lef layer mapping array */ +{ + char *token; + LinkedRect *routeList, *newRoute = NULL, *routeTop = NULL; + Point refp; /* reference point */ + bool valid = FALSE; /* is there a valid reference point? */ + bool initial = TRUE; + Rect locarea; + float x, y, z, w; + int routeWidth, paintWidth, saveWidth; + TileType routeLayer, paintLayer; + HashEntry *he; + lefLayer *lefl; + + while (initial || (token = LefNextToken(f, TRUE)) != NULL) + { + /* Get next point, token "NEW", or via name */ + if (initial || !strcmp(token, "NEW") || !strcmp(token, "new")) + { + /* initial pass is like a NEW record, but has no NEW keyword */ + initial = FALSE; + + /* invalidate reference point */ + valid = FALSE; + + token = LefNextToken(f, TRUE); + + he = HashLookOnly(&LefInfo, token); + if (he != NULL) + { + lefl = (lefLayer *)HashGetValue(he); + if (lefl) routeLayer = lefl->type; + } + else + { + /* The fallback position is to match the DEF name to the */ + /* magic layer name. This is ad-hoc, and the declaration */ + /* of type mappings in the lef section of the techfile is */ + /* preferred. */ + + routeLayer = DBTechNameType(LefLower(token)); + lefl = NULL; + } + + if (routeLayer < 0) + { + LefError("Unknown layer type \"%s\" for NEW route\n", token); + continue; + } + paintLayer = routeLayer; + + if (special) + { + /* SPECIALNETS has the additional width */ + token = LefNextToken(f, TRUE); + if (sscanf(token, "%f", &w) != 1) + { + LefError("Bad width in special net\n"); + continue; + } + if (w != 0) + paintWidth = (int)roundf(w / oscale); + else + paintWidth = (lefl) ? lefl->info.route.width : + DEFAULT_WIDTH * DBLambda[1] / DBLambda[0]; + saveWidth = paintWidth; + } + else + paintWidth = (lefl) ? lefl->info.route.width : + DEFAULT_WIDTH * DBLambda[1] / DBLambda[0]; + } + else if (*token != '(') /* via name */ + { + /* A '+' or ';' record ends the route */ + if (*token == ';' || *token == '+') + break; + + else if (valid == FALSE) + { + LefError("Route has via name \"%s\" but no points!\n", token); + continue; + } + he = HashLookOnly(&LefInfo, token); + if (he != NULL) + { + lefl = (lefLayer *)HashGetValue(he); + newRoute = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); + + /* The area to paint is derived from the via definitions. */ + + if (lefl != NULL) + { + LinkedRect *viaRoute, *addRoute; + + /* If there is a LinkedRect structure for the via, */ + /* add those records to the route first. */ + + for (viaRoute = lefl->info.via.lr; viaRoute != NULL; + viaRoute = viaRoute->r_next) + { + addRoute = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); + addRoute->r_next = NULL; + addRoute->r_type = viaRoute->r_type; + addRoute->r_r = viaRoute->r_r; + + addRoute->r_r.r_xbot += refp.p_x; + addRoute->r_r.r_ybot += refp.p_y; + addRoute->r_r.r_xtop += refp.p_x; + addRoute->r_r.r_ytop += refp.p_y; + + addRoute->r_r.r_xbot >>= 1; + addRoute->r_r.r_ybot >>= 1; + addRoute->r_r.r_xtop >>= 1; + addRoute->r_r.r_ytop >>= 1; + + if (routeTop) + routeList->r_next = addRoute; + else + routeTop = addRoute; + + routeList = addRoute; + } + + paintLayer = lefl->type; + + newRoute->r_r.r_xbot = refp.p_x + lefl->info.via.area.r_xbot; + newRoute->r_r.r_ybot = refp.p_y + lefl->info.via.area.r_ybot; + newRoute->r_r.r_xtop = refp.p_x + lefl->info.via.area.r_xtop; + newRoute->r_r.r_ytop = refp.p_y + lefl->info.via.area.r_ytop; + + newRoute->r_r.r_xbot >>= 1; + newRoute->r_r.r_ybot >>= 1; + newRoute->r_r.r_xtop >>= 1; + newRoute->r_r.r_ytop >>= 1; + + } + else if ((paintLayer = DBTechNameType(LefLower(token))) >= 0) + { + LefError("Error: Via \"%s\" named but undefined.\n", token); + newRoute->r_r.r_xbot = refp.p_x - paintWidth; + newRoute->r_r.r_ybot = refp.p_y - paintWidth; + newRoute->r_r.r_xtop = refp.p_x + paintWidth; + newRoute->r_r.r_ytop = refp.p_y + paintWidth; + + newRoute->r_r.r_xbot >>= 1; + newRoute->r_r.r_ybot >>= 1; + newRoute->r_r.r_xtop >>= 1; + newRoute->r_r.r_ytop >>= 1; + } + else + LefError("Via name \"%s\" unknown in route.\n", token); + + /* After the via, the new route layer becomes whatever */ + /* residue of the via was NOT the previous route layer. */ + /* This is absolutely impossible to make consistent */ + /* with the DEF spec, but there you have it. . . */ + + if (DBIsContact(paintLayer)) + { + TileTypeBitMask *rMask = DBResidueMask(paintLayer); + TileType stype; + + for (stype = TT_TECHDEPBASE; stype < DBNumUserLayers; stype++) + if (TTMaskHasType(rMask, stype)) + if (stype != routeLayer) + { + /* Diagnostic */ + /* + TxPrintf("Contact %s: In=%s Out=%s\n", + DBTypeLongNameTbl[paintLayer], + DBTypeLongNameTbl[routeLayer], + DBTypeLongNameTbl[stype]); + */ + routeLayer = stype; + lefl = defLayerMap[routeLayer].lefInfo; + if (special) + paintWidth = saveWidth; + else + paintWidth = (lefl) ? lefl->info.route.width + : DEFAULT_WIDTH * DBLambda[1] / DBLambda[0]; + break; + } + } + } + else + LefError("Via name \"%s\" unknown in route.\n", token); + } + else + { + /* Revert to the routing layer type, in case we painted a via */ + paintLayer = routeLayer; + + /* Record current reference point */ + locarea.r_xbot = refp.p_x; + locarea.r_ybot = refp.p_y; + + /* Read an (X Y) point */ + token = LefNextToken(f, TRUE); /* read X */ + if (*token == '*') + { + if (valid == FALSE) + { + LefError("No reference point for \"*\" wildcard\n"); + goto endCoord; + } + } + else if (sscanf(token, "%f", &x) == 1) + { + refp.p_x = (int)roundf((2 * x) / oscale); + } + else + { + LefError("Cannot parse X coordinate.\n"); + goto endCoord; + } + token = LefNextToken(f, TRUE); /* read Y */ + if (*token == '*') + { + if (valid == FALSE) + { + LefError("No reference point for \"*\" wildcard\n"); + freeMagic(newRoute); + newRoute = NULL; + goto endCoord; + } + } + else if (sscanf(token, "%f", &y) == 1) + { + refp.p_y = (int)roundf((2 * y) / oscale); + } + else + { + LefError("Cannot parse Y coordinate.\n"); + goto endCoord; + } + + /* Extension is half-width for regular nets, 0 for special nets */ + /* 0 for special nets is *not* how the 5.3 spec reads, but it */ + /* is apparently how everyone interprets it, and is true for */ + /* 5.6 spec. */ + + z = (special) ? 0 : paintWidth; + token = LefNextToken(f, TRUE); + if (*token != ')') + { + /* non-default route extension */ + if (sscanf(token, "%f", &z) != 1) + LefError("Can't parse route extension value.\n"); + + /* all values will be divided by 2, so we need */ + /* to multiply up by 2 now. */ + + else + z *= 2; + } + + /* Indicate that we have a valid reference point */ + + if (valid == FALSE) + { + valid = TRUE; + } + else if ((locarea.r_xbot != refp.p_x) && (locarea.r_ybot != refp.p_y)) + { + /* Skip over nonmanhattan segments, reset the reference */ + /* point, and output a warning. */ + + LefError("Can't deal with nonmanhattan geometry in route.\n"); + locarea.r_xbot = refp.p_x; + locarea.r_ybot = refp.p_y; + } + else + { + newRoute = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); + + /* Route coordinates become the centerline of the */ + /* segment. "refp" is kept in 1/2 lambda units so */ + /* we should always end up with integer units. */ + + locarea.r_xtop = refp.p_x; + locarea.r_ytop = refp.p_y; + + GeoCanonicalRect(&locarea, &newRoute->r_r); + + if (newRoute->r_r.r_xbot == newRoute->r_r.r_xtop) + { + newRoute->r_r.r_xbot -= paintWidth; + newRoute->r_r.r_xtop += paintWidth; + } + else + { + newRoute->r_r.r_xbot -= z; + newRoute->r_r.r_xtop += z; + } + + if (newRoute->r_r.r_ybot == newRoute->r_r.r_ytop) + { + newRoute->r_r.r_ybot -= paintWidth; + newRoute->r_r.r_ytop += paintWidth; + } + else + { + newRoute->r_r.r_ybot -= z; + newRoute->r_r.r_ytop += z; + } + + /* If we don't have integer units here, we should */ + /* rescale the magic internal grid. */ + + newRoute->r_r.r_xbot >>= 1; + newRoute->r_r.r_ybot >>= 1; + newRoute->r_r.r_xtop >>= 1; + newRoute->r_r.r_ytop >>= 1; + } + +endCoord: + /* Find the closing parenthesis for the coordinate pair */ + while (*token != ')') + token = LefNextToken(f, TRUE); + } + + /* Link in the new route segment */ + if (newRoute) + { + newRoute->r_type = paintLayer; + newRoute->r_next = NULL; + + if (routeTop) + routeList->r_next = newRoute; + else + routeTop = newRoute; + + routeList = newRoute; + newRoute = NULL; + } + } + + /* Process each segment and paint into the layout */ + + while (routeTop != NULL) + { + /* paint */ + DBPaint(rootDef, &routeTop->r_r, routeTop->r_type); + + /* advance to next point and free record (1-delayed) */ + freeMagic((char *)routeTop); + routeTop = routeTop->r_next; + } + return token; /* Pass back the last token found */ +} + +/* + *------------------------------------------------------------ + * + * DefReadNets -- + * + * Read a NETS or SPECIALNETS section from a DEF file. + * + * Results: + * None. + * + * Side Effects: + * Many. Networks are created, and geometry may be + * painted into the database top-level cell. + * + *------------------------------------------------------------ + */ + +enum def_net_keys {DEF_NET_START = 0, DEF_NET_END}; +enum def_netprop_keys { + DEF_NETPROP_USE = 0, DEF_NETPROP_ROUTED, DEF_NETPROP_FIXED, + DEF_NETPROP_COVER, DEF_NETPROP_SOURCE, DEF_NETPROP_WEIGHT, + DEF_NETPROP_PROPERTY}; + +void +DefReadNets(f, rootDef, sname, oscale, special, total) + FILE *f; + CellDef *rootDef; + char *sname; + float oscale; + bool special; /* True if this section is SPECIALNETS */ + int total; +{ + char *token; + int keyword, subkey; + int processed = 0; + LefMapping *defLayerMap; + + static char *net_keys[] = { + "-", + "END", + NULL + }; + + static char *net_property_keys[] = { + "USE", + "ROUTED", + "FIXED", + "COVER", + "SOURCE", + "WEIGHT", + "PROPERTY", + NULL + }; + + defLayerMap = defMakeInverseLayerMap(); + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + keyword = Lookup(token, net_keys); + if (keyword < 0) + { + LefError("Unknown keyword \"%s\" in NET " + "definition; ignoring.\n", token); + LefEndStatement(f); + continue; + } + + switch (keyword) + { + case DEF_NET_START: + + /* Get net name */ + /* Presently, we ignore net names completely. */ + token = LefNextToken(f, TRUE); + + /* Update the record of the number of nets processed */ + /* and spit out a message for every 5% finished. */ + + LefEstimate(processed++, total, + (special) ? "special nets" : "nets"); + + /* Process all properties */ + while (token && (*token != ';')) + { + /* All connections are ignored, and we go */ + /* go directly to the first property ("+") key */ + + if (*token != '+') + { + token = LefNextToken(f, TRUE); + continue; + } + else + token = LefNextToken(f, TRUE); + + subkey = Lookup(token, net_property_keys); + if (subkey < 0) + { + LefError("Unknown net property \"%s\" in " + "NET definition; ignoring.\n", token); + continue; + } + switch (subkey) + { + case DEF_NETPROP_USE: + /* Presently, we ignore this */ + break; + case DEF_NETPROP_ROUTED: + case DEF_NETPROP_FIXED: + case DEF_NETPROP_COVER: + token = DefAddRoutes(rootDef, f, oscale, special, + defLayerMap); + break; + } + } + break; + + case DEF_NET_END: + if (!LefParseEndStatement(f, sname)) + { + LefError("Net END statement missing.\n"); + keyword = -1; + } + break; + } + if (keyword == DEF_NET_END) break; + } + + if (processed == total) + TxPrintf(" Processed %d%s nets total.\n", processed, + (special) ? " special" : ""); + else + LefError("Warning: Number of nets read (%d) does not match " + "the number declared (%d).\n", processed, total); + + freeMagic((char *)defLayerMap); +} + +/* + *------------------------------------------------------------ + * + * DefReadUseLocation -- + * + * Read location and orientation of a cell use + * Syntax: ( X Y ) O + * + * Results: + * 0 on success, -1 on failure + * + * Side Effects: + * Transform is placed in the location pointed to by "tptr". + * This routine can be used for placement of geometry (as + * opposed to cell uses) by setting "use" to NULL, and using + * the resulting transform to modify the geometry. + *------------------------------------------------------------ + */ +enum def_orient {DEF_NORTH, DEF_SOUTH, DEF_EAST, DEF_WEST, + DEF_FLIPPED_NORTH, DEF_FLIPPED_SOUTH, DEF_FLIPPED_EAST, + DEF_FLIPPED_WEST}; + +int +DefReadLocation(use, f, oscale, tptr) + CellUse *use; + FILE *f; + float oscale; + Transform *tptr; +{ + Rect *r, tr; + int keyword; + char *token; + float x, y; + Transform t2; + + static char *orientations[] = { + "N", "S", "E", "W", "FN", "FS", "FE", "FW" + }; + + token = LefNextToken(f, TRUE); + if (*token != '(') goto parse_error; + token = LefNextToken(f, TRUE); + if (sscanf(token, "%f", &x) != 1) goto parse_error; + token = LefNextToken(f, TRUE); + if (sscanf(token, "%f", &y) != 1) goto parse_error; + token = LefNextToken(f, TRUE); + if (*token != ')') goto parse_error; + token = LefNextToken(f, TRUE); + + keyword = Lookup(token, orientations); + if (keyword < 0) + { + LefError("Unknown macro orientation \"%s\".\n", token); + return -1; + } + + /* The standard transformations are all defined to rotate */ + /* or flip about the origin. However, DEF defines them */ + /* around the center such that the lower left corner is */ + /* unchanged after the transformation. Case conditions */ + /* restore the lower-left corner position. */ + + if (use) + r = &use->cu_def->cd_bbox; + else + r = &GeoNullRect; + + switch (keyword) + { + case DEF_NORTH: + *tptr = GeoIdentityTransform; + break; + case DEF_SOUTH: + *tptr = Geo180Transform; + break; + case DEF_EAST: + *tptr = Geo90Transform; + break; + case DEF_WEST: + *tptr = Geo270Transform; + break; + case DEF_FLIPPED_NORTH: + *tptr = GeoSidewaysTransform; + break; + case DEF_FLIPPED_SOUTH: + *tptr = GeoUpsideDownTransform; + break; + case DEF_FLIPPED_EAST: + *tptr = GeoRef135Transform; + break; + case DEF_FLIPPED_WEST: + *tptr = GeoRef45Transform; + break; + } + GeoTransRect(tptr, r, &tr); + GeoTranslateTrans(tptr, -tr.r_xbot, -tr.r_ybot, &t2); + GeoTranslateTrans(&t2, (int)roundf(x / oscale), (int)roundf(y / oscale), tptr); + if (use) + DBSetTrans(use, tptr); + return 0; + +parse_error: + LefError("Cannot parse location: must be ( X Y ) orient\n"); + return -1; +} + +/* + *------------------------------------------------------------ + * + * DefReadPins -- + * + * Read a PINS section from a DEF file. + * + * Results: + * None. + * + * Side Effects: + * Generates paint and labels in the layout. + * + *------------------------------------------------------------ + */ + +enum def_pins_keys {DEF_PINS_START = 0, DEF_PINS_END}; +enum def_pins_prop_keys { + DEF_PINS_PROP_NET = 0, DEF_PINS_PROP_DIR, + DEF_PINS_PROP_LAYER, DEF_PINS_PROP_USE, + DEF_PINS_PROP_PLACED, DEF_PINS_PROP_FIXED}; + +void +DefReadPins(f, rootDef, sname, oscale, total) + FILE *f; + CellDef *rootDef; + char *sname; + float oscale; + int total; +{ + char *token; + char pinname[LEF_LINE_MAX]; + int keyword, subkey, values; + int processed = 0; + int pinDir = PORT_CLASS_DEFAULT; + TileType curlayer = -1; + Rect *currect, topRect; + Transform t; + lefLayer *lefl; + bool pending = FALSE; + + static char *pin_keys[] = { + "-", + "END", + NULL + }; + + static char *pin_property_keys[] = { + "NET", + "DIRECTION", + "LAYER", + "USE", + "PLACED", + "FIXED", + NULL + }; + + static char *pin_classes[] = { + "DEFAULT", + "INPUT", + "OUTPUT TRISTATE", + "OUTPUT", + "INOUT", + "FEEDTHRU", + NULL + }; + + static int lef_class_to_bitmask[] = { + PORT_CLASS_DEFAULT, + PORT_CLASS_INPUT, + PORT_CLASS_TRISTATE, + PORT_CLASS_OUTPUT, + PORT_CLASS_BIDIRECTIONAL, + PORT_CLASS_FEEDTHROUGH + }; + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + keyword = Lookup(token, pin_keys); + + if (keyword < 0) + { + LefError("Unknown keyword \"%s\" in PINS " + "definition; ignoring.\n", token); + LefEndStatement(f); + continue; + } + switch (keyword) + { + case DEF_PINS_START: /* "-" keyword */ + + // Flag an error if a pin was waiting on a layer + // specification that was never given. + + if (pending) + { + LefError("Pin specified without layer, was not placed.\n"); + } + + /* Update the record of the number of pins */ + /* processed and spit out a message for every 5% done. */ + + LefEstimate(processed++, total, "pins"); + + /* Get pin name */ + token = LefNextToken(f, TRUE); + if (sscanf(token, "%2047s", pinname) != 1) + { + LefError("Bad pin statement: Need pin name\n"); + LefEndStatement(f); + break; + } + pending = FALSE; + + /* Now do a search through the line for "+" entries */ + /* And process each. */ + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + if (*token == ';') break; + if (*token != '+') continue; + + token = LefNextToken(f, TRUE); + subkey = Lookup(token, pin_property_keys); + if (subkey < 0) + { + LefError("Unknown pin property \"%s\" in " + "PINS definition; ignoring.\n", token); + continue; + } + switch (subkey) + { + case DEF_PINS_PROP_USE: + case DEF_PINS_PROP_NET: + /* Get the net name, but ignore it */ + token = LefNextToken(f, TRUE); + break; + case DEF_PINS_PROP_DIR: + token = LefNextToken(f, TRUE); + subkey = Lookup(token, pin_classes); + if (subkey < 0) + LefError("Unknown pin class\n"); + else + pinDir = lef_class_to_bitmask[subkey]; + break; + case DEF_PINS_PROP_LAYER: + curlayer = LefReadLayer(f, FALSE); + currect = LefReadRect(f, curlayer, oscale); + if (pending) + { + GeoTransRect(&t, currect, &topRect); + DBPaint(rootDef, &topRect, curlayer); + DBPutLabel(rootDef, &topRect, -1, pinname, curlayer, + pinDir); + pending = FALSE; + } + break; + case DEF_PINS_PROP_FIXED: + case DEF_PINS_PROP_PLACED: + DefReadLocation(NULL, f, oscale, &t); + if (curlayer == -1) + pending = TRUE; + else + { + GeoTransRect(&t, currect, &topRect); + DBPaint(rootDef, &topRect, curlayer); + DBPutLabel(rootDef, &topRect, -1, pinname, curlayer, + pinDir); + } + break; + } + } + + break; + + case DEF_PINS_END: + if (!LefParseEndStatement(f, sname)) + { + LefError("Pins END statement missing.\n"); + keyword = -1; + } + break; + } + if (keyword == DEF_PINS_END) break; + } + + if (processed == total) + TxPrintf(" Processed %d pins total.\n", processed); + else + LefError("Warning: Number of pins read (%d) does not match " + "the number declared (%d).\n", processed, total); +} + +/* + *------------------------------------------------------------ + * + * DefReadVias -- + * + * Read a VIAS section from a DEF file. + * + * Results: + * None. + * + * Side Effects: + * Technically, this routine should be creating a cell for + * each defined via. For now, it just computes the bounding + * rectangle and layer. + * + *------------------------------------------------------------ + */ + +enum def_vias_keys {DEF_VIAS_START = 0, DEF_VIAS_END}; +enum def_vias_prop_keys { + DEF_VIAS_PROP_RECT = 0}; + +void +DefReadVias(f, sname, oscale, total) + FILE *f; + char *sname; + float oscale; + int total; +{ + char *token; + char vianame[LEF_LINE_MAX]; + int keyword, subkey, values; + int processed = 0; + TileType curlayer; + Rect *currect; + lefLayer *lefl; + HashEntry *he; + + static char *via_keys[] = { + "-", + "END", + NULL + }; + + static char *via_property_keys[] = { + "RECT", + NULL + }; + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + keyword = Lookup(token, via_keys); + + if (keyword < 0) + { + LefError("Unknown keyword \"%s\" in VIAS " + "definition; ignoring.\n", token); + LefEndStatement(f); + continue; + } + switch (keyword) + { + case DEF_VIAS_START: /* "-" keyword */ + + /* Update the record of the number of vias */ + /* processed and spit out a message for every 5% done. */ + + LefEstimate(processed++, total, "vias"); + + /* Get via name */ + token = LefNextToken(f, TRUE); + if (sscanf(token, "%2047s", vianame) != 1) + { + LefError("Bad via statement: Need via name\n"); + LefEndStatement(f); + break; + } + he = HashFind(&LefInfo, vianame); + lefl = (lefLayer *)HashGetValue(he); + if (lefl == NULL) + { + lefl = (lefLayer *)mallocMagic(sizeof(lefLayer)); + lefl->type = -1; + lefl->obsType = -1; + lefl->lefClass = CLASS_VIA; + lefl->info.via.area = GeoNullRect; + lefl->info.via.cell = (CellDef *)NULL; + lefl->info.via.lr = (LinkedRect *)NULL; + HashSetValue(he, lefl); + lefl->canonName = (char *)he->h_key.h_name; + } + else + { + LefError("Warning: Composite via \"%s\" redefined.\n", vianame); + lefl = LefRedefined(lefl, vianame); + } + + /* Now do a search through the line for "+" entries */ + /* And process each. */ + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + if (*token == ';') break; + if (*token != '+') continue; + + token = LefNextToken(f, TRUE); + subkey = Lookup(token, via_property_keys); + if (subkey < 0) + { + LefError("Unknown via property \"%s\" in " + "VIAS definition; ignoring.\n", token); + continue; + } + switch (subkey) + { + case DEF_VIAS_PROP_RECT: + curlayer = LefReadLayer(f, FALSE); + LefAddViaGeometry(f, lefl, curlayer, oscale); + break; + } + } + break; + + case DEF_VIAS_END: + if (!LefParseEndStatement(f, sname)) + { + LefError("Vias END statement missing.\n"); + keyword = -1; + } + break; + } + if (keyword == DEF_VIAS_END) break; + } + + if (processed == total) + TxPrintf(" Processed %d vias total.\n", processed); + else + LefError("Warning: Number of vias read (%d) does not match " + "the number declared (%d).\n", processed, total); +} + +/* + *------------------------------------------------------------ + * + * DefReadComponents -- + * + * Read a COMPONENTS section from a DEF file. + * + * Results: + * None. + * + * Side Effects: + * Many. Cell definitions and uses are created and added to + * the database. + * + *------------------------------------------------------------ + */ + +enum def_comp_keys {DEF_COMP_START = 0, DEF_COMP_END}; +enum def_prop_keys { + DEF_PROP_FIXED = 0, DEF_PROP_COVER, + DEF_PROP_PLACED, DEF_PROP_UNPLACED, + DEF_PROP_SOURCE, DEF_PROP_WEIGHT, DEF_PROP_FOREIGN, + DEF_PROP_REGION, DEF_PROP_GENERATE, DEF_PROP_PROPERTY, + DEF_PROP_EEQMASTER}; + +void +DefReadComponents(f, rootDef, sname, oscale, total) + FILE *f; + CellDef *rootDef; + char *sname; + float oscale; + int total; +{ + CellDef *defMacro; + CellUse *defUse; + Transform t; + char *token; + char usename[512]; + int keyword, subkey, values; + int processed = 0; + + static char *component_keys[] = { + "-", + "END", + NULL + }; + + static char *property_keys[] = { + "FIXED", + "COVER", + "PLACED", + "UNPLACED", + "SOURCE", + "WEIGHT", + "FOREIGN", + "REGION", + "GENERATE", + "PROPERTY", + "EEQMASTER", + NULL + }; + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + keyword = Lookup(token, component_keys); + + if (keyword < 0) + { + LefError("Unknown keyword \"%s\" in COMPONENT " + "definition; ignoring.\n", token); + LefEndStatement(f); + continue; + } + switch (keyword) + { + case DEF_COMP_START: /* "-" keyword */ + + /* Update the record of the number of components */ + /* processed and spit out a message for every 5% done. */ + + LefEstimate(processed++, total, "subcell instances"); + + /* Get use and macro names */ + token = LefNextToken(f, TRUE); + if (sscanf(token, "%511s", usename) != 1) + { + LefError("Bad component statement: Need use and macro names\n"); + LefEndStatement(f); + break; + } + token = LefNextToken(f, TRUE); + + /* Find the corresponding macro definition */ + defUse = NULL; + defMacro = DBCellLookDef(token); + + if (defMacro == (CellDef *)NULL) + { + /* Before giving up, assume that this cell has a */ + /* magic .mag layout file. */ + defMacro = DBCellNewDef(token, (char *)NULL); + defMacro->cd_flags &= ~CDNOTFOUND; + if (!DBCellRead(defMacro, (char *)NULL, TRUE, NULL)) + { + LefError("Cell %s is not defined. Maybe you have not " + "read the corresponding LEF file?\n", + token); + LefEndStatement(f); + DBCellDeleteDef(defMacro); + defMacro = NULL; + } + else + DBReComputeBbox(defMacro); + } + + /* Create a use for this celldef in the edit cell */ + /* Don't process properties for cells we could not find */ + + if ((defMacro == NULL) || ((defUse = DBCellNewUse(defMacro, usename)) + == NULL)) + { + LefEndStatement(f); + break; + } + DBLinkCell(defUse, rootDef); + + /* Now do a search through the line for "+" entries */ + /* And process each. */ + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + if (*token == ';') break; + if (*token != '+') continue; + + token = LefNextToken(f, TRUE); + subkey = Lookup(token, property_keys); + if (subkey < 0) + { + LefError("Unknown component property \"%s\" in " + "COMPONENT definition; ignoring.\n", token); + continue; + } + switch (subkey) + { + case DEF_PROP_PLACED: + case DEF_PROP_UNPLACED: + case DEF_PROP_FIXED: + case DEF_PROP_COVER: + DefReadLocation(defUse, f, oscale, &t); + break; + case DEF_PROP_SOURCE: + case DEF_PROP_WEIGHT: + case DEF_PROP_FOREIGN: + case DEF_PROP_REGION: + case DEF_PROP_GENERATE: + case DEF_PROP_PROPERTY: + case DEF_PROP_EEQMASTER: + token = LefNextToken(f, TRUE); + break; + } + } + + /* Place the cell */ + if (defUse != NULL) + { + DBPlaceCell(defUse, rootDef); + defUse = NULL; + } + break; + + case DEF_COMP_END: + if (!LefParseEndStatement(f, sname)) + { + LefError("Component END statement missing.\n"); + keyword = -1; + } + + /* Finish final call by placing the cell use */ + if ((total > 0) && (defUse != NULL)) + { + DBPlaceCell(defUse, rootDef); + defUse = NULL; + } + break; + } + if (keyword == DEF_COMP_END) break; + } + + if (processed == total) + TxPrintf(" Processed %d subcell instances total.\n", processed); + else + LefError("Warning: Number of subcells read (%d) does not match " + "the number declared (%d).\n", processed, total); +} + +/* + *------------------------------------------------------------ + * + * DefRead -- + * + * Read a .def file into a magic layout. + * + * Results: + * None. + * + * Side Effects: + * Many. Cell definitions and uses are created and added to + * the database. + * + *------------------------------------------------------------ + */ + +/* Enumeration of sections defined in DEF files */ + +enum def_sections {DEF_VERSION = 0, DEF_NAMESCASESENSITIVE, + DEF_UNITS, DEF_DESIGN, DEF_REGIONS, DEF_ROW, DEF_TRACKS, + DEF_GCELLGRID, DEF_DIVIDERCHAR, DEF_BUSBITCHARS, + DEF_PROPERTYDEFINITIONS, DEF_DEFAULTCAP, DEF_TECHNOLOGY, + DEF_HISTORY, DEF_DIEAREA, DEF_COMPONENTS, DEF_VIAS, + DEF_PINS, DEF_PINPROPERTIES, DEF_SPECIALNETS, + DEF_NETS, DEF_IOTIMINGS, DEF_SCANCHAINS, + DEF_CONSTRAINTS, DEF_GROUPS, DEF_EXTENSION, + DEF_END}; + +void +DefRead(inName) + char *inName; +{ + CellDef *rootDef; + FILE *f; + char *filename; + char *token; + int keyword, dscale, total; + float oscale; + + static char *sections[] = { + "VERSION", + "NAMESCASESENSITIVE", + "UNITS", + "DESIGN", + "REGIONS", + "ROW", + "TRACKS", + "GCELLGRID", + "DIVIDERCHAR", + "BUSBITCHARS", + "PROPERTYDEFINITIONS", + "DEFAULTCAP", + "TECHNOLOGY", + "HISTORY", + "DIEAREA", + "COMPONENTS", + "VIAS", + "PINS", + "PINPROPERTIES", + "SPECIALNETS", + "NETS", + "IOTIMINGS", + "SCANCHAINS", + "CONSTRAINTS", + "GROUPS", + "BEGINEXT", + "END", + NULL + }; + + /* Make sure we have a valid LefInfo hash table, even if it's empty */ + if (LefInfo.ht_table == (HashEntry **) NULL) + LefTechInit(); + + f = lefFileOpen(NULL, inName, ".def", "r", &filename); + + if (f == NULL) + { +#ifdef MAGIC_WRAPPER + TxError("Cannot open input file %s (%s).\n", filename, + strerror(errno)); +#else + TxError("Cannot open input file: "); + perror(filename); +#endif + return; + } + + /* Initialize */ + + TxPrintf("Reading DEF data from file %s.\n", filename); + TxPrintf("This action cannot be undone.\n"); + UndoDisable(); + + /* This works for CIF reads; maybe should only do this if the top */ + /* cell is (UNNAMED)? */ + + rootDef = EditCellUse->cu_def; + DBCellRenameDef(rootDef, inName); + oscale = CIFGetOutputScale(1000); + lefCurrentLine = 0; + + /* Read file contents */ + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + keyword = Lookup(token, sections); + if (keyword < 0) + { + LefError("Unknown keyword \"%s\" in DEF file; ignoring.\n", token); + LefEndStatement(f); + continue; + } + switch (keyword) + { + case DEF_VERSION: + LefEndStatement(f); + break; + case DEF_NAMESCASESENSITIVE: + LefEndStatement(f); + break; + case DEF_TECHNOLOGY: + token = LefNextToken(f, TRUE); + if (strcmp(token, DBTechName)) + { + LefError("Warning: DEF technology name \"%s\" does not" + " match current magic technology name \"%s\"\n", + token, DBTechName); + } + LefEndStatement(f); + break; + case DEF_REGIONS: + LefSkipSection(f, sections[DEF_REGIONS]); + break; + case DEF_DESIGN: + token = LefNextToken(f, TRUE); + DBCellRenameDef(rootDef, token); + LefEndStatement(f); + break; + case DEF_UNITS: + token = LefNextToken(f, TRUE); + token = LefNextToken(f, TRUE); + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &dscale) != 1) + { + LefError("Invalid syntax for UNITS statement.\n"); + LefError("Assuming default value of 100\n"); + dscale = 100; + } + /* We don't care if the scale is 100, 200, 1000, or 2000. */ + /* Do we need to deal with numeric roundoff issues? */ + oscale *= (float)dscale; + LefEndStatement(f); + break; + case DEF_ROW: + LefEndStatement(f); + break; + case DEF_TRACKS: + LefEndStatement(f); + break; + case DEF_GCELLGRID: + LefEndStatement(f); + break; + case DEF_DIVIDERCHAR: + LefEndStatement(f); + break; + case DEF_BUSBITCHARS: + LefEndStatement(f); + break; + case DEF_HISTORY: + LefEndStatement(f); + break; + case DEF_DIEAREA: + LefEndStatement(f); + break; + case DEF_PROPERTYDEFINITIONS: + LefSkipSection(f, sections[DEF_PROPERTYDEFINITIONS]); + break; + case DEF_DEFAULTCAP: + LefSkipSection(f, sections[DEF_DEFAULTCAP]); + break; + case DEF_COMPONENTS: + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &total) != 1) total = 0; + LefEndStatement(f); + DefReadComponents(f, rootDef, sections[DEF_COMPONENTS], oscale, total); + break; + case DEF_VIAS: + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &total) != 1) total = 0; + LefEndStatement(f); + DefReadVias(f, sections[DEF_VIAS], oscale, total); + break; + case DEF_PINS: + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &total) != 1) total = 0; + LefEndStatement(f); + DefReadPins(f, rootDef, sections[DEF_PINS], oscale, total); + break; + case DEF_PINPROPERTIES: + LefSkipSection(f, sections[DEF_PINPROPERTIES]); + break; + case DEF_SPECIALNETS: + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &total) != 1) total = 0; + LefEndStatement(f); + DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE, total); + break; + case DEF_NETS: + token = LefNextToken(f, TRUE); + if (sscanf(token, "%d", &total) != 1) total = 0; + LefEndStatement(f); + DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE, total); + break; + case DEF_IOTIMINGS: + LefSkipSection(f, sections[DEF_IOTIMINGS]); + break; + case DEF_SCANCHAINS: + LefSkipSection(f, sections[DEF_SCANCHAINS]); + break; + case DEF_CONSTRAINTS: + LefSkipSection(f, sections[DEF_CONSTRAINTS]); + break; + case DEF_GROUPS: + LefSkipSection(f, sections[DEF_GROUPS]); + break; + case DEF_EXTENSION: + LefSkipSection(f, sections[DEF_EXTENSION]); + break; + case DEF_END: + if (!LefParseEndStatement(token, "DESIGN")) + { + LefError("END statement out of context.\n"); + keyword = -1; + } + break; + } + if (keyword == DEF_END) break; + } + TxPrintf("DEF read: Processed %d lines.\n", lefCurrentLine); + LefError(NULL); /* print statement of errors, if any, and reset */ + + /* Cleanup */ + + DBAdjustLabels(rootDef, &TiPlaneRect); + DBReComputeBbox(rootDef); + DBWAreaChanged(rootDef, &rootDef->cd_bbox, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + DBCellSetModified(rootDef, TRUE); + + if (f != NULL) fclose(f); + UndoEnable(); +} diff --git a/lef/defWrite.c b/lef/defWrite.c new file mode 100644 index 00000000..c9848ef9 --- /dev/null +++ b/lef/defWrite.c @@ -0,0 +1,1956 @@ +/* + * defWrite.c -- + * + * This module incorporates the LEF/DEF format for standard-cell place and + * route. + * + * + * Version 0.1 (June 9, 2004): DEF output for layouts, to include netlist + * from the extracted layout. + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/lef/defWrite.c,v 1.2 2008/02/10 19:30:21 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/tech.h" +#include "utils/malloc.h" +#include "utils/undo.h" +#include "cif/cif.h" +#include "extflat/extflat.h" +#include "lef/lefInt.h" +#include "drc/drc.h" /* for querying width,spacing rules */ + +/*----------------------------------------------------------------------*/ +/* Structures used by various routines */ +/*----------------------------------------------------------------------*/ + +typedef struct { + float scale; + FILE *f; + CellDef *def; + + Tile *tile; /* Values of the last calculated route */ + TileType type; + float x, y, extlen; + unsigned char orient; + + LefMapping *MagicToLefTbl; + int outcolumn; /* Current column of output in file */ + unsigned char specialmode; /* What nets to write as SPECIALNETS */ +} DefData; + +typedef struct { + float scale; + int total; + int plane; + TileTypeBitMask *mask; + LefMapping *MagicToLefTbl; +} CViaData; + +/*----------------------------------------------------------------------*/ + +char *defGetType(); /* Forward declaration */ + +/*----------------------------------------------------------------------*/ + + +/* + * ---------------------------------------------------------------------------- + * + * defWriteHeader -- + * + * This routine generates DEF header output for a cell or cell hierarchy. + * + * Results: + * None. + * + * Side effects: + * Writes output to the open file "f". + * + * ---------------------------------------------------------------------------- + */ + +void +defWriteHeader(def, f, oscale) + CellDef *def; /* Def for which to generate DEF output */ + FILE *f; /* Output to this file */ + float oscale; +{ + TileType type; + + TxPrintf("Diagnostic: Write DEF header for cell %s\n", def->cd_name); + + /* NOTE: This routine corresponds to Envisia LEF/DEF Language */ + /* Reference version 5.3 (May 31, 2000) */ + + fprintf(f, "VERSION 5.3 ;\n"); + fprintf(f, " NAMESCASESENSITIVE ON ;\n"); + fprintf(f, " DIVIDERCHAR \"/\" ;\n"); + + /* Declare that buses are denoted with parentheses, since magic */ + /* uses brackets for arrays and instances. */ + fprintf(f, " BUSBITCHARS \"()\" ;\n"); + + /* Design name, taken from the cell def name */ + fprintf(f, " DESIGN %s ;\n", def->cd_name); + + /* Technology name, taken from the magic tech file. */ + /* (which may not be a good idea. . . may need a tech definition */ + /* in the tech file "lef" section to specifically name the LEF/DEF */ + /* technology). */ + fprintf(f, " TECHNOLOGY %s ;\n", DBTechName); + + /* As I understand it, this refers to the scalefactor of the GDS */ + /* file output. Magic does all GDS in nanometers, so the LEF */ + /* scalefactor (conversion to microns) is always 1000. */ + fprintf(f, " UNITS DISTANCE MICRONS 1000 ;\n"); + + /* Die area, taken from the cell def bounding box. */ + fprintf(f, " DIEAREA ( %.10g %.10g ) ( %.10g %.10g ) ;\n", + (float)def->cd_bbox.r_xbot * oscale, + (float)def->cd_bbox.r_ybot * oscale, + (float)def->cd_bbox.r_xtop * oscale, + (float)def->cd_bbox.r_ytop * oscale); + + fprintf(f, "\n"); +} + +/* + *------------------------------------------------------------ + * + * defTransPos -- + * + * Determine the DEF orientation of a specific magic + * transformation matrix. + * + * Results: + * The position, in DEF string format ("N" for north, etc.) + * This is a static string + * + * Side Effects: + * None. + * + *------------------------------------------------------------ + */ + +char * +defTransPos(Transform *t) +{ + static char *def_orient[] = { + "N", "S", "E", "W", "FN", "FS", "FE", "FW" + }; + + bool ew; /* east-or-west identifier */ + bool sw; /* south-or-west identifier */ + bool flip; + int pos = 0; + + ew = ((t->t_a == 0) && (t->t_e == 0)) ? TRUE : FALSE; + if (ew) + { + flip = ((t->t_b * t->t_d) > 0) ? TRUE : FALSE; + sw = (t->t_d > 0) ? TRUE : FALSE; + } + else + { + flip = ((t->t_a * t->t_e) < 0) ? TRUE : FALSE; + sw = (t->t_e > 0) ? FALSE : TRUE; + } + + if (flip) pos += 4; + if (ew) pos += 2; + if (sw) pos += 1; + + return def_orient[pos]; +} + +/* + *------------------------------------------------------------ + * + * defCountNets -- + * + * First-pass function to count the number of different + * nets used. If "allSpecial" is TRUE, consider all + * geometry to be SPECIALNETS. + * + * Results: + * A NetCount structure holding the regular and special + * net totals upon completion. + * + * Side Effects: + * None. + * + *------------------------------------------------------------ + */ + +NetCount +defCountNets(rootDef, allSpecial) + CellDef *rootDef; + bool allSpecial; +{ + NetCount total; + int defnodeCount(); + + total.regular = (allSpecial) ? -1 : 0; + total.special = 0; + total.has_nets = TRUE; + + TxPrintf("Diagnostic: Finding all nets in cell %s\n", rootDef->cd_name); + TxPrintf("(This can take a while!)\n"); + + /* Read in the extracted file */ + EFInit(); + + /* There are no arguments for extflat, but we need to call the */ + /* routine to initialize a few things such as the search path. */ + EFArgs(0, NULL, NULL, NULL, NULL); + + EFScale = 0.0; /* Allows EFScale to be set to the scale value */ + + if (EFReadFile(rootDef->cd_name, TRUE, FALSE, TRUE)) + { + EFFlatBuild(rootDef->cd_name, EF_FLATNODES | EF_NOFLATSUBCKT); + EFVisitNodes(defnodeCount, (ClientData)&total); + } + else + { + TxError("Warning: Circuit has no .ext file; no nets written.\n"); + TxError("Run extract on this circuit if you want nets in the output.\n"); + EFDone(); + total.has_nets = FALSE; + } + + if (allSpecial) total.regular = 0; + return total; +} + +/* Callback function used by defCountNets */ + +int +defnodeCount(node, res, cap, total) + EFNode *node; + int res; /* not used */ + EFCapValue cap; /* not used */ + NetCount *total; +{ + HierName *hierName; + char ndn[256]; + char *cp, clast; + + /* Ignore power and ground lines, which we will treat */ + /* as SPECIALNETS types. */ + + hierName = (HierName *) node->efnode_name->efnn_hier; + + if (!(hierName->hn_parent)) /* Extra processing of top-level nodes */ + { + char *pwr; + cp = hierName->hn_name; + clast = *(cp + strlen(cp) - 1); + + /* Global nodes are marked as "special nets" */ + if (clast == '!') + node->efnode_flags |= EF_SPECIAL; + +#ifdef MAGIC_WRAPPER + /* Check if name is defined in array "globals" */ + pwr = (char *)Tcl_GetVar2(magicinterp, "globals", cp, TCL_GLOBAL_ONLY); + if (pwr) + { + /* Diagnostic */ + TxPrintf("Node %s is defined in the \"globals\" array\n"); + node->efnode_flags |= EF_SPECIAL; + } + + /* Check against Tcl variables $VDD and $GND */ + pwr = (char *)Tcl_GetVar(magicinterp, "VDD", TCL_GLOBAL_ONLY); + if (pwr && (!strcmp(cp, pwr))) + { + /* Diagnostic */ + TxPrintf("Node %s matches VDD variable definition!\n"); + node->efnode_flags |= EF_SPECIAL; + } + + pwr = (char *)Tcl_GetVar(magicinterp, "GND", TCL_GLOBAL_ONLY); + if (pwr && (!strcmp(cp, pwr))) + { + /* Diagnostic */ + TxPrintf("Node %s matches GND variable definition!\n"); + node->efnode_flags |= EF_SPECIAL; + } + + /* If a node has not been marked as SPECIAL, does not connect */ + /* to a port, and does not have an internally-generated name, */ + /* then mark it as "special". */ + if (!(node->efnode_flags & (EF_SPECIAL | EF_PORT)) && + (clast != '#')) + node->efnode_flags |= EF_SPECIAL; +#endif + } + + if (total->regular < 0) + { + /* "allspecial" options: all nets written as SPECIALNETS */ + + if ((node->efnode_flags & EF_SPECIAL) || (node->efnode_flags & EF_PORT)) + total->special++; + } + else + { + /* We only count nodes having a port connection as "regular" nets */ + + if (node->efnode_flags & EF_SPECIAL) + total->special++; + else if (node->efnode_flags & EF_PORT) + total->regular++; + } + + return 0; /* Keep going. . . */ +} + +/* + * ---------------------------------------------------------------------------- + * + * defHNsprintf -- + * + * Create a hierarchical node name for the DEF output file.. + * + * Results: + * None. + * + * Side effects: + * Changes the area pointed to by str + * + * ---------------------------------------------------------------------------- + */ + +void +defHNsprintf(str, hierName, divchar) + char *str; + HierName *hierName; + char divchar; +{ + bool trimGlob, trimLocal; + char *s, *cp, c; + char *defHNsprintfPrefix(); + + s = str; + if (hierName->hn_parent) str = defHNsprintfPrefix(hierName->hn_parent, str, + divchar); + + /* Make the name conform to valid LEF/DEF syntax. This means */ + /* no pound signs or semicolons (which are illegal characters, */ + /* along with space and newline which won't be found in the */ + /* magic name anyway), or dashes, asterisks, or percent signs */ + /* (which are interpreted as wildcard characters by LEF/DEF). */ + + cp = hierName->hn_name; + while (c = *cp++) + { + switch (c) + { + case '#': /* Ignore---this is the final character */ + /* in internally-generated node names. */ + break; + case ';': + case '-': + case '*': + case '%': + *str++ = '_'; + break; + default: + *str++ = c; + break; + } + } + *str++ = '\0'; +} + +char *defHNsprintfPrefix(hierName, str, divchar) + HierName *hierName; + char *str; + char divchar; +{ + char *cp, c; + + if (hierName->hn_parent) + str = defHNsprintfPrefix(hierName->hn_parent, str); + + cp = hierName->hn_name; + while (*str++ = *cp++) ; + *(--str) = divchar; + return ++str; +} + + +/* + *------------------------------------------------------------ + * + * nodeDefName --- + * + * Determine the node name to write to the DEF file + * for the given hierachical name structure from + * extflat. + * + *------------------------------------------------------------ + */ + +char * +nodeDefName(hname) + HierName *hname; +{ + EFNodeName *nn; + HashEntry *he; + EFNode *node; + static char nodeName[256]; + + he = EFHNLook(hname, (char *) NULL, "nodeName"); + if (he == NULL) + return "errorNode"; + nn = (EFNodeName *) HashGetValue(he); + node = nn->efnn_node; + + defHNsprintf(nodeName, node->efnode_name->efnn_hier, '/'); + return nodeName; +} + +/* + *------------------------------------------------------------ + * + * defCheckForBreak -- + * + * Add the number "addlen" to the column value of + * the output. If the DEF file output has reached or + * exceeds this value, write a newline character to + * the output and reset the column count. + * + * Results: + * None. + * + * Side effects: + * Output to DEF file; resets defdata->outcolumn + * + *------------------------------------------------------------ + */ + +#define MAX_DEF_COLUMNS 70 + +void +defCheckForBreak(addlen, defdata) + int addlen; + DefData *defdata; +{ + defdata->outcolumn += addlen; + if (defdata->outcolumn > MAX_DEF_COLUMNS) + { + fprintf(defdata->f, "\n "); + defdata->outcolumn = 6 + addlen; + } +} + +/* + *------------------------------------------------------------ + * + * defWriteRouteWidth --- + * + * Write the width of a SPECIALNET route to the output. + * + *------------------------------------------------------------ + */ + +void +defWriteRouteWidth(defdata, width) + DefData *defdata; + int width; +{ + float oscale = defdata->scale; + char numstr[12]; + sprintf(numstr, "%.10g", ((float)width * defdata->scale)); + defCheckForBreak(strlen(numstr) + 1, defdata); + fprintf(defdata->f, "%s ", numstr); +} + +/* + *------------------------------------------------------------ + * + * defWriteCoord -- + * + * Output a coordinate pair in DEF syntax. We supply the + * point to be written AND the previously written point + * so we can make use of the "*" notation in the DEF point + * format. If the point to be written is not an extension + * of the previous point, "prevpt" should be NULL. + * + * Results: + * None. + * + * Side Effects: + * Output written to the DEF file. + * + *------------------------------------------------------------ + */ + +void +defWriteCoord(defdata, x, y, orient) + DefData *defdata; + float x, y; + unsigned char orient; +{ + FILE *f = defdata->f; + char numstr[12]; + int ctot = 4; + + /* The "12" here is just a fudge factor; it is not crucial */ + /* to limit the output to exactly MAX_DEF_COLUMNS, and it */ + /* is easier to assume that the output of a coordinate */ + /* pair is about 12 characters average rather than try to */ + /* predetermine what the actual output length will be. */ + + if ((defdata->outcolumn + 12) > MAX_DEF_COLUMNS) + { + fprintf(f, "\n "); + defdata->outcolumn = 6; + } + + fprintf(f, " ( "); + if ((orient == GEO_NORTH) || (orient == GEO_SOUTH)) + { + fprintf(f, "* "); + ctot += 2; + } + else + { + sprintf(numstr, "%.10g", x); + fprintf(f, "%s ", numstr); + ctot += strlen(numstr) + 1; + } + + if ((orient == GEO_EAST) || (orient == GEO_WEST)) + { + fprintf(f, "* "); + ctot += 2; + } + else + { + sprintf(numstr, "%.10g", y); + fprintf(f, "%s ", numstr); + ctot += strlen(numstr) + 1; + } + + fprintf(f, ")"); + defdata->outcolumn += ctot; +} + +/* + *------------------------------------------------------------ + * + * defWriteNets -- + * + * Output the NETS section of a DEF file. We make use of + * the connectivity search routines used by "getnode" to + * determine unique notes and assign a net name to each. + * Then, we generate the geometry output for each NET + * entry. + * + * Results: + * None. + * + * Side Effects: + * Output written to the DEF output file. + * + *------------------------------------------------------------ + */ + +void +defWriteNets(f, rootDef, oscale, MagicToLefTable, specialmode) + FILE *f; /* File to write to */ + CellDef *rootDef; /* Cell definition to use */ + float oscale; /* Output scale factor */ + LefMapping *MagicToLefTable; /* Magic to LEF layer mapping */ + unsigned char specialmode; /* What to write as a SPECIALNET */ +{ + DefData defdata; + int defnodeVisit(); + + defdata.f = f; + defdata.scale = oscale; + defdata.def = rootDef; + defdata.MagicToLefTbl = MagicToLefTable; + defdata.outcolumn = 0; + defdata.specialmode = specialmode; + + EFVisitNodes(defnodeVisit, (ClientData)&defdata); +} + +int +defnodeVisit(node, res, cap, defdata) + EFNode *node; + int res; + EFCapValue cap; + DefData *defdata; +{ + HierName *hierName; + char *ndn; + char ndn2[256]; + FILE *f = defdata->f; + CellDef *def = defdata->def; + float oscale = defdata->scale; + TileTypeBitMask tmask, *rmask; + TileType magictype; + EFNodeName *thisnn; + int defNetGeometryFunc(); /* Forward declaration */ + + /* For regular nets, only count those nodes having port */ + /* connections. For special nets, only count those nodes */ + /* that were marked with the EF_SPECIAL flag while counting */ + /* nets. */ + + if (defdata->specialmode == DO_REGULAR) + { + if (!(node->efnode_flags & EF_PORT)) + return 0; + } + else if (defdata->specialmode == DO_SPECIAL) + { + if (!(node->efnode_flags & EF_SPECIAL)) + return 0; + } + else /* ALL_SPECIAL */ + { + if (!(node->efnode_flags & EF_PORT) && + !(node->efnode_flags & EF_SPECIAL)) + return 0; + } + + hierName = (HierName *) node->efnode_name->efnn_hier; + ndn = nodeDefName(hierName); + defHNsprintf(ndn2, node->efnode_name->efnn_hier, '/'); + if (strcmp(ndn, ndn2)) + { + TxError("Node mismatch: %s vs. %s\n", ndn, ndn2); + } + + fprintf(f, " - %s", ndn); + defdata->outcolumn = 5 + strlen(ndn); + + /* Find all the node names that are port connections. */ + /* For now, we will just use anything connecting one level */ + /* down in the hierarchy. This is not definitive, however, */ + /* and we should confirm that the connection is an actual */ + /* port. */ + + for (thisnn = node->efnode_name; thisnn != NULL; thisnn = thisnn->efnn_next) + { + char locndn[256]; + hierName = thisnn->efnn_hier; + if (hierName->hn_parent && !hierName->hn_parent->hn_parent) + { + /* This is just another kludgy check for a non-port and */ + /* will eventually be removed. */ + char endc = *(hierName->hn_name + strlen(hierName->hn_name) - 1); + if (endc != '#') + { + defHNsprintf(locndn, thisnn->efnn_hier, ' '); + defCheckForBreak(5 + strlen(locndn), defdata); + fprintf(f, " ( %s )", locndn); + } + } + } + + /* TT_SPACE indicates that a layer name must be the next */ + /* thing to be written to the DEF file. */ + defdata->type = TT_SPACE; + defdata->tile = (Tile *)NULL; + + /* Net geometry (this should be an option!)--- */ + /* Use the DBconnect routines to find all geometry */ + /* connected to a specific node. This is a */ + /* redundant search---we've already done this once */ + /* when extracting the circuit. But, because the */ + /* DEF file requires a count of nodes up front, we */ + /* would have to do it twice anyway. In this case, */ + /* we only do it once here, since the results of */ + /* the first pass are picked up from the .ext file. */ + + magictype = DBTechNameType(EFLayerNames[node->efnode_type]); + + /* Note that the type of the node might be defined by the type */ + /* in the subcircuit itself, so we need to search for any type */ + /* that might validly connect to it, not just the type itself. */ + /* TTMaskSetOnlyType(&tmask, magictype); */ + TTMaskZero(&tmask); + TTMaskSetMask(&tmask, &DBConnectTbl[magictype]); + + DBSrConnect(def, &node->efnode_loc, &tmask, DBConnectTbl, + &TiPlaneRect, defNetGeometryFunc, + (ClientData)defdata); + + if (defdata->tile == (Tile *)NULL) + { + /* No route layer? It's possible that something connects to */ + /* the port location but doesn't overlap. Try painting the */ + /* node type in def and trying again. */ + + Rect rport; + SearchContext scx; + int defPortTileFunc(); /* Fwd declaration */ + + scx.scx_area = node->efnode_loc; + scx.scx_use = def->cd_parents; + scx.scx_trans = GeoIdentityTransform; + DBTreeSrUniqueTiles(&scx, &tmask, 0, defPortTileFunc, (ClientData)&rport); + + /* Add the residue types to any contact type */ + if (DBIsContact(magictype)) + { + rmask = DBResidueMask(magictype); + TTMaskSetMask(&tmask, rmask); + TTMaskSetType(&tmask, magictype); + } + /* Expand the rectangle around the port to overlap any */ + /* connecting material. */ + rport.r_xbot--; + rport.r_ybot--; + rport.r_xtop++; + rport.r_ytop++; + DBSrConnect(def, &rport, &tmask, DBConnectTbl, &TiPlaneRect, + defNetGeometryFunc, (ClientData)defdata); + } + + /* Was there a last record pending? If so, write it. */ + if (defdata->tile != (Tile *)NULL) + { + if (defdata->orient != GEO_CENTER) + defWriteCoord(defdata, defdata->x, defdata->y, defdata->orient); + + defdata->outcolumn = 0; + } + fprintf(f, " ;\n"); + + return 0; /* Keep going */ +} + +/* Callback function for DBTreeSrUniqueTiles. When no routed areas */ +/* were found, we assume that there was no routing material overlapping */ +/* the port. So, we need to find the area of a tile defining the port */ +/* so we can look for attaching material. */ + +int +defPortTileFunc(tile, cx) + Tile *tile; + TreeContext *cx; +{ + SearchContext *scx = cx->tc_scx; + Rect *rport = (Rect *)cx->tc_filter->tf_arg; + Rect r; + + TiToRect(tile, &r); + GeoTransRect(&scx->scx_trans, &r, rport); + + /* Diagnostic */ + /* + TxPrintf("Port tile at (%d %d) to (%d %d)\n", + rport->r_xbot, rport->r_ybot, + rport->r_xtop, rport->r_ytop); + */ + + return 1; /* No need to check further */ +} + +/* Callback function for writing geometry of the network to */ +/* the DEF file. */ + +int +defNetGeometryFunc(tile, plane, defdata) + Tile *tile; /* Tile being visited */ + int plane; /* Plane of the tile being visited */ + DefData *defdata; /* Data passed to this function */ +{ + FILE *f = defdata->f; + CellDef *def = defdata->def; + float oscale = defdata->scale; + TileTypeBitMask *rMask, *r2Mask; + TileType rtype, r2type, ttype = TiGetType(tile); + Rect r; + unsigned char orient; + bool sameroute = FALSE; + int routeWidth, w, h, midlinex2; + float x1, y1, x2, y2, extlen; + lefLayer *lefType; + char *lefName, viaName[24]; + LefMapping *MagicToLefTable = defdata->MagicToLefTbl; + + TiToRect(tile, &r); + + /* Treat contacts here exactly the same way as defCountVias */ + + if (DBIsContact(ttype)) + { + Rect r2; + Tile *tp; + + rMask = NULL; + if (ttype >= DBNumUserLayers) + { + /* Stacked contact types need to be broken into their */ + /* constituent types. Process only if we are on the home */ + /* plane of one of the constituent types. */ + + rMask = DBResidueMask(ttype); + for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++) + if (TTMaskHasType(rMask, rtype)) + if (DBPlane(rtype) == plane) + { + ttype = rtype; + break; + } + if (rtype == DBNumUserLayers) + return 0; + + } + else + if (DBPlane(ttype) != plane) + return 0; + + /* Boundary search on stacked contact types to include any */ + /* tile areas belonging to ttype. */ + + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) /* Top */ + { + r2type = TiGetBottomType(tp); + if (r2type == ttype) + { + if (!rMask) return 0; + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else if (r2type >= DBNumUserLayers) + { + r2Mask = DBResidueMask(r2type); + if (TTMaskHasType(r2Mask, ttype)) + return 0; + } + } + + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) /* Left */ + { + r2type = TiGetRightType(tp); + if (r2type == ttype) + { + if (!rMask) return 0; + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else if (r2type >= DBNumUserLayers) + { + r2Mask = DBResidueMask(r2type); + if (TTMaskHasType(r2Mask, ttype)) + return 0; + } + } + + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) /* Bottom */ + { + r2type = TiGetTopType(tp); + if (r2type == ttype) + { + if (!rMask) return 0; + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else if (r2type >= DBNumUserLayers) + { + r2Mask = DBResidueMask(r2type); + if (TTMaskHasType(r2Mask, ttype)) + return 0; + } + } + + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) /* Right */ + { + r2type = TiGetLeftType(tp); + if (r2type == ttype) + { + if (!rMask) return 0; + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else if (r2type >= DBNumUserLayers) + { + r2Mask = DBResidueMask(r2type); + if (TTMaskHasType(r2Mask, ttype)) + return 0; + } + } + } + + /* Layer names are taken from the LEF database. */ + + lefName = MagicToLefTable[ttype].lefName; + lefType = MagicToLefTable[ttype].lefInfo; + + orient = GEO_EAST; + w = r.r_xtop - r.r_xbot; + h = r.r_ytop - r.r_ybot; + midlinex2 = (r.r_ytop + r.r_ybot); + + if (defdata->specialmode != DO_REGULAR) + { + routeWidth = (h > w) ? w : h; + if ((lefType && lefType->lefClass == CLASS_VIA) + || (!lefType && DBIsContact(ttype))) + orient = GEO_CENTER; + } + else + { + routeWidth = 0; + if ((lefType && (lefType->lefClass == CLASS_VIA)) + || (!lefType && DBIsContact(ttype))) + orient = GEO_CENTER; + else if (lefType) + routeWidth = lefType->info.route.width; + + if (routeWidth == 0) + routeWidth = DRCGetDefaultLayerWidth(ttype); + } + + if (orient != GEO_CENTER) /* not a via type */ + { + if (h != routeWidth) + { + if ((w == routeWidth) || ((routeWidth == 0) && (h > w))) + { + orient = GEO_NORTH; + midlinex2 = (r.r_xtop + r.r_xbot); + } + } + + /* Warn if the route is not equal to the default route width--- */ + /* This means a regular net should have been a special net. */ + if ((h != routeWidth) && (w != routeWidth)) + { + /* Diagnostic */ + TxPrintf("Net has width %d, default width is %d\n", + (h > w) ? h : w, routeWidth); + } + + /* Find the route orientation and centerline endpoint coordinates */ + + if (orient == GEO_EAST) + { + y1 = (midlinex2 * oscale) / 2; + y2 = y1; + + x1 = r.r_xbot * oscale; + x2 = r.r_xtop * oscale; + if (routeWidth == 0) routeWidth = h; + extlen = (defdata->specialmode != DO_REGULAR) ? + 0 : (routeWidth * oscale) / 2; + } + else /* vertical orientation */ + { + x1 = (midlinex2 * oscale) / 2; + x2 = x1; + + y1 = r.r_ybot * oscale; + y2 = r.r_ytop * oscale; + if (routeWidth == 0) routeWidth = w; + extlen = (defdata->specialmode != DO_REGULAR) ? + 0 : (routeWidth * oscale) / 2; + } + } + else /* Type is a via */ + { + y1 = y2 = (midlinex2 * oscale) / 2; + x1 = x2 = ((r.r_xtop + r.r_xbot) * oscale) / 2; + extlen = 0; + } + + /* For contact types, find the residues of the contact */ + + if (orient == GEO_CENTER) + { + TileType stype; + + rtype = r2type = TT_SPACE; + rMask = DBResidueMask(ttype); + for (stype = TT_TECHDEPBASE; stype < DBNumUserLayers; stype++) + { + if (TTMaskHasType(rMask, stype)) + { + if ((stype == defdata->type) || (defdata->tile == (Tile *)NULL)) + rtype = stype; + else + r2type = stype; + } + } + } + + /* If we previously visited a tile, write out its second */ + /* coordinate pair, adjusting the position if necessary to */ + /* make the wire extensions line up correctly. If they */ + /* don't line up, we assume a dogleg route and add */ + /* coordinate pairs as necessary to generate the correct */ + /* geometry in the DEF output. */ + + if (defdata->tile) + { + Rect r2; + TiToRect(defdata->tile, &r2); + /* Only consider the endpoint of the previous tile at X2,Y2 */ + /* And the endpoint of the current tile at X1,Y1 */ + if (defdata->orient == GEO_EAST) + r2.r_xbot = r2.r_xtop - 1; + else if (defdata->orient == GEO_NORTH) + r2.r_ybot = r2.r_ytop - 1; + + if (orient == GEO_EAST) + r.r_xtop = r.r_xbot + 1; + else if (orient == GEO_NORTH) + r.r_ytop = r.r_ybot + 1; + + /* "sameroute" is true only if rectangles touch in the */ + /* direction of the route. */ + /* NOTE: We should compute this FIRST and use it to determine */ + /* the current route direction! */ + /* Another hack---for special nets, don't continue routes that */ + /* have different widths, even if they're connected in the */ + /* direction of travel. A separate record will be written for */ + /* the segment of different width. */ + + if (GEO_TOUCH(&r, &r2)) + { + if (defdata->orient == GEO_EAST) + { + if ((r.r_xbot == r2.r_xtop) || (r.r_xtop == r2.r_xbot)) + { + sameroute = TRUE; + if ((defdata->specialmode != DO_REGULAR) && + (r.r_ytop != r2.r_ytop || r.r_ybot != r2.r_ybot)) + sameroute = FALSE; + } + } + else if (defdata->orient == GEO_NORTH) + { + if ((r.r_ybot == r2.r_ytop) || (r.r_ytop == r2.r_ybot)) + { + sameroute = TRUE; + if ((defdata->specialmode != DO_REGULAR) && + (r.r_xtop != r2.r_xtop || r.r_xbot != r2.r_xbot)) + sameroute = FALSE; + } + } + else + sameroute = TRUE; + } + + /* We should NOT continue a route from a via for a special net, */ + /* because the spec for this situation is too vaguely defined. */ + + if (sameroute && (defdata->specialmode != DO_REGULAR) && + defdata->orient == GEO_CENTER) + sameroute = FALSE; + } + + + /* Determine if we need to write a NEW (type) record. We do this */ + /* if 1) this is the first tile visited (except that we don't */ + /* write "NEW"), 2) the current tile doesn't touch the last tile */ + /* visited, or 3) the current type is not equal to the last type. */ + + if ((!sameroute) || (ttype != defdata->type)) + { + /* This is not a continuation of the last route. Output */ + /* the last route position, and start a NEW record. */ + + if ((sameroute) && (ttype != defdata->type) && + (orient == GEO_CENTER) && + (rtype == defdata->type)) + { + /* Adjust previous route to centerpoint of the via. If the */ + /* via is not centered on the route, add segments to create */ + /* the proper alignment. */ + if ((defdata->orient == GEO_NORTH) && (x1 == defdata->x)) + defWriteCoord(defdata, defdata->x, y1, defdata->orient); + else if ((defdata->orient == GEO_EAST) && (y1 == defdata->y)) + defWriteCoord(defdata, x1, defdata->y, defdata->orient); + else if (defdata->orient == GEO_EAST) + { + defWriteCoord(defdata, x1, defdata->y, defdata->orient); + defWriteCoord(defdata, x1, y1, GEO_NORTH); + } + else if (defdata->orient == GEO_NORTH) + { + defWriteCoord(defdata, defdata->x, y1, defdata->orient); + defWriteCoord(defdata, x1, y1, GEO_EAST); + } + + /* Via type continues route */ + snprintf(viaName, (size_t)24, "_%.10g_%.10g", + ((float)w * oscale), ((float)h * oscale)); + defCheckForBreak(strlen(lefName) + strlen(viaName) + 2, defdata); + fprintf(f, " %s%s ", lefName, viaName); + } + else + { + /* New route segment. Complete the last route segment. */ + if (defdata->tile) + { + /* Don't write out a segment for a via */ + if (defdata->orient != GEO_CENTER) + defWriteCoord(defdata, + defdata->x - ((defdata->orient == GEO_EAST) ? + defdata->extlen : 0), + defdata->y - ((defdata->orient == GEO_NORTH) ? + defdata->extlen : 0), defdata->orient); + + fprintf(f, "\n NEW "); + defdata->outcolumn = 10; + } + else + { + /* First record printed for this node */ + fprintf(f, "\n + ROUTED "); + defdata->outcolumn = 15; + } + + /* This is the first tile segment visited in the */ + /* current type---use GEO_CENTER so that no */ + /* coordinate wildcards ("*") get written. */ + + if (orient == GEO_CENTER) + { + char *rName; + + /* Type can be zero (space) if the first tile */ + /* encountered is a via. If so, use the 1st */ + /* residue of the contact as the route layer */ + /* type. */ + + rName = defGetType((rtype == TT_SPACE) ? r2type : rtype, NULL); + + /* The first layer in a record may not be a via name */ + + defCheckForBreak(strlen(rName) + 1, defdata); + fprintf(f, "%s ", rName); + if (defdata->specialmode != DO_REGULAR) + defWriteRouteWidth(defdata, routeWidth); + defWriteCoord(defdata, x1, y1, GEO_CENTER); + snprintf(viaName, (size_t)24, "_%.10g_%.10g", + ((float)w * oscale), ((float)h * oscale)); + defCheckForBreak(strlen(lefName) + strlen(viaName) + 2, defdata); + fprintf(f, " %s%s ", lefName, viaName); + } + else + { + defCheckForBreak(strlen(lefName) + 1, defdata); + fprintf(f, "%s ", lefName); + if (defdata->specialmode != DO_REGULAR) + defWriteRouteWidth(defdata, routeWidth); + + /* defWriteCoord(defdata, x1, y1, GEO_CENTER); */ + defWriteCoord(defdata, + x1 + ((orient == GEO_EAST) ? extlen : 0), + y1 + ((orient == GEO_NORTH) ? extlen : 0), + GEO_CENTER); + } + } + } + else if (sameroute) + { + /* Adjust the previous route segment to match the new segment, */ + /* and write out the previous route segment record. */ + if ((orient == defdata->orient) && (defdata->x != x1) && (defdata->y != x2)) + { + /* Dogleg---insert extra segment */ + defWriteCoord(defdata, + defdata->x - ((defdata->orient == GEO_EAST) ? + defdata->extlen : 0), + defdata->y - ((defdata->orient == GEO_NORTH) ? + defdata->extlen : 0), defdata->orient); + defWriteCoord(defdata, x1 + ((orient == GEO_EAST) ? extlen : 0), + y1 + ((orient == GEO_NORTH) ? extlen : 0), orient); + } + else + { + if (defdata->orient == GEO_EAST) + { + if (((defdata->x + defdata->extlen) == x1) || + ((defdata->x - defdata->extlen) == x1)) + defWriteCoord(defdata, x1, defdata->y, defdata->orient); + else + { + /* Don't know how to connect the route segments. */ + /* End the original route and start a new one. */ + defWriteCoord(defdata, + defdata->x - ((defdata->orient == GEO_EAST) ? + defdata->extlen : 0), + defdata->y - ((defdata->orient == GEO_NORTH) ? + defdata->extlen : 0), defdata->orient); + fprintf(f, "\n NEW %s", lefName); + defdata->outcolumn = 10 + strlen(lefName); + if (defdata->specialmode != DO_REGULAR) + { + fprintf(f, " "); + defdata->outcolumn++; + defWriteRouteWidth(defdata, routeWidth); + } + defWriteCoord(defdata, + x1 + ((orient == GEO_EAST) ? extlen : 0), + y1 + ((orient == GEO_NORTH) ? extlen : 0), + GEO_CENTER); + } + } + else if (defdata->orient == GEO_NORTH) + { + if (((defdata->y + defdata->extlen) == y1) || + ((defdata->y - defdata->extlen) == y1)) + defWriteCoord(defdata, defdata->x, y1, defdata->orient); + else + { + /* Don't know how to connect the route segments. */ + /* End the original route and start a new one. */ + defWriteCoord(defdata, + defdata->x - ((defdata->orient == GEO_EAST) ? + defdata->extlen : 0), + defdata->y - ((defdata->orient == GEO_NORTH) ? + defdata->extlen : 0), defdata->orient); + fprintf(f, "\n NEW %s", lefName); + if (defdata->specialmode != DO_REGULAR) { + fprintf(f, " "); + defdata->outcolumn++; + defWriteRouteWidth(defdata, routeWidth); + } + defdata->outcolumn = 10 + strlen(lefName); + defWriteCoord(defdata, + x1 + ((orient == GEO_EAST) ? extlen : 0), + y1 + ((orient == GEO_NORTH) ? extlen : 0), + GEO_CENTER); + } + } + else /* last record was a via */ + { + /* Continuing route from via to other connecting layer type */ + /* Bend to meet via center---insert extra segment */ + + if ((orient == GEO_NORTH) && (x1 != defdata->x)) + defWriteCoord(defdata, x1, defdata->y, GEO_EAST); + + else if ((orient == GEO_EAST) && (y1 != defdata->y)) + defWriteCoord(defdata, defdata->x, y1, GEO_NORTH); + } + } + } + + /* After a contact type, the route coordinates may continue in the */ + /* routing type connected by the contact to the type that was */ + /* previously seen connected to the contact. */ + + /* NOTE! The above comment matches the example on page 203 of the */ + /* LEF/DEF reference manual. However, it is obvious that it is */ + /* logically fallacious. A via can be declared to be multiple */ + /* types, and there is no way to know which type continues the */ + /* route without it being explicitly stated. Nevertheless, that */ + /* is the way it's implemented. . . */ + + if ((orient == GEO_CENTER) && (rtype != TT_SPACE) && (r2type != TT_SPACE)) + defdata->type = r2type; + else if (orient == GEO_CENTER) + defdata->type = TT_SPACE; + else + defdata->type = ttype; + + defdata->x = x2; + defdata->y = y2; + defdata->extlen = extlen; + defdata->tile = tile; + defdata->orient = orient; + return 0; /* Keep going */ +} + +/* + *------------------------------------------------------------ + * + * defCountVias -- + * + * First-pass function to count the number of different + * vias used, and retain this information for the netlist + * output. + * + * Results: + * The total number of via definitions to be written. + * + * Side Effects: + * None. + * + *------------------------------------------------------------ + */ + +int +defCountVias(rootDef, MagicToLefTable, oscale) + CellDef *rootDef; + LefMapping *MagicToLefTable; + float oscale; +{ + TileTypeBitMask contactMask, *rmask; + TileType ttype, stype; + int pNum; + CViaData cviadata; + int defCountViaFunc(); + + cviadata.scale = oscale; + cviadata.total = 0; + cviadata.MagicToLefTbl = MagicToLefTable; + + for (pNum = PL_SELECTBASE; pNum < DBNumPlanes; pNum++) + { + cviadata.plane = pNum; + + /* Only search for contacts that are on their *home* plane */ + + TTMaskZero(&contactMask); + for (ttype = TT_TECHDEPBASE; ttype < DBNumUserLayers; ttype++) + if (DBIsContact(ttype) && TTMaskHasType(&DBPlaneTypes[pNum], ttype)) + TTMaskSetType(&contactMask, ttype); + + /* Also search all stacked types whose residue contact types */ + /* are in the mask just generated. */ + + for (ttype = DBNumUserLayers; ttype < DBNumTypes; ttype++) + { + if (!DBIsContact(ttype)) continue; + rmask = DBResidueMask(ttype); + for (stype = TT_TECHDEPBASE; stype < DBNumUserLayers; stype++) + if (TTMaskHasType(rmask, stype)) + { + TTMaskSetType(&contactMask, ttype); + break; + } + } + cviadata.mask = &contactMask; + + DBSrPaintArea((Tile *)NULL, rootDef->cd_planes[pNum], + &TiPlaneRect, &contactMask, + defCountViaFunc, (ClientData)&cviadata); + } + return cviadata.total; +} + +/* Callback function used by defCountVias */ + +int +defCountViaFunc(tile, cviadata) + Tile *tile; + CViaData *cviadata; +{ + TileType ttype = TiGetType(tile), ctype, rtype; + TileTypeBitMask *rmask, *rmask2; + Tile *tp; + char *lname, vname[100], *vp; + Rect r, r2; + int w, h, offx, offy; + float oscale = cviadata->scale; + lefLayer *lefl; + HashEntry *he; + LefMapping *MagicToLefTable = cviadata->MagicToLefTbl; + + /* Techfiles are allowed not to declare a LEF entry, in which */ + /* case we would need to initialize the hash table. */ + if (LefInfo.ht_table == (HashEntry **) NULL) LefTechInit(); + + /* Find the canonical type */ + if (ttype >= DBNumUserLayers) + { + rmask = DBResidueMask(ttype); + for (ctype = TT_TECHDEPBASE; ctype < DBNumUserLayers; ctype++) + if (TTMaskHasType(rmask, ctype)) + break; + if (ctype == DBNumUserLayers) + return 1; /* Error condition */ + } + else + { + rmask = NULL; + ctype = ttype; + } + + /* Generate a via name from the layer name and tile size */ + + lname = MagicToLefTable[ctype].lefName; + TiToRect(tile, &r); + + /* Boundary search. WARNING: This code is quite naive. The */ + /* assumption is that all contacts are rectangular, and therefore */ + /* any contact area consisting of multiple tiles must be an amalgam */ + /* of regular and/or stacked types. This whole thing should be */ + /* replaced by calls to generate layers via the CIF/Calma code. */ + + /* Top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + { + rtype = TiGetBottomType(tp); + if (rtype == ctype) + { + if (!rmask) return 0; /* ignore tile but continue search */ + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else if (rtype >= DBNumUserLayers) + { + rmask2 = DBResidueMask(rtype); + if (TTMaskHasType(rmask2, ctype)) + return 0; + } + } + + /* Left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + { + rtype = TiGetRightType(tp); + if (rtype == ctype) + { + if (!rmask) return 0; /* ignore tile but continue search */ + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else if (rtype >= DBNumUserLayers) + { + rmask2 = DBResidueMask(rtype); + if (TTMaskHasType(rmask2, ctype)) + return 0; + } + } + + /* Bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + { + rtype = TiGetTopType(tp); + if (rtype == ctype) + { + if (!rmask) return 0; /* ignore tile but continue search */ + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else if (rtype >= DBNumUserLayers) + { + rmask2 = DBResidueMask(rtype); + if (TTMaskHasType(rmask2, ctype)) + return 0; + } + } + + /* Right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + { + rtype = TiGetLeftType(tp); + if (rtype == ctype) + { + if (!rmask) return 0; /* ignore tile but continue search */ + TiToRect(tp, &r2); + GeoInclude(&r2, &r); + } + else if (rtype >= DBNumUserLayers) + { + rmask2 = DBResidueMask(rtype); + if (TTMaskHasType(rmask2, ctype)) + return 0; + } + } + + /* All values for the via rect are in 1/2 lambda to account */ + /* for a centerpoint not on the internal grid. */ + + r.r_xbot <<= 1; + r.r_xtop <<= 1; + r.r_ybot <<= 1; + r.r_ytop <<= 1; + + w = r.r_xtop - r.r_xbot; + h = r.r_ytop - r.r_ybot; + offx = (w >> 1); + offy = (h >> 1); + + /* Center the via area on the origin */ + r.r_xbot = -offx; + r.r_ybot = -offy; + r.r_xtop = -offx + w; + r.r_ytop = -offy + h; + + sprintf(vname, "%s_%.10g_%.10g", lname, + ((float)offx * oscale), ((float)offy * oscale)); + + he = HashFind(&LefInfo, vname); + lefl = (lefLayer *)HashGetValue(he); + if (lefl == NULL) + { + cviadata->total++; /* Increment the count of uses */ + lefl = (lefLayer *)mallocMagic(sizeof(lefLayer)); + lefl->type = ttype; + lefl->obsType = -1; + lefl->lefClass = CLASS_VIA; + lefl->info.via.area = r; + lefl->info.via.cell = (CellDef *)NULL; + lefl->info.via.lr = (LinkedRect *)NULL; + lefl->refCnt = 0; /* These entries will be removed after writing */ + HashSetValue(he, lefl); + lefl->canonName = (char *)he->h_key.h_name; + } + return 0; /* Keep the search going */ +} + +/* + *------------------------------------------------------------ + * + * defGetType -- + * + * Retrieve the LEF/DEF name of a magic layer from the + * LefInfo hash table. + * + * Results: + * The "official" LEF/DEF layer name of the magic type. + * + * Side Effects: + * If "lefptr" is non-NULL, it is filled with a pointer + * to the appropriate lefLayer entry, or NULL if there + * is no corresponding entry. + *------------------------------------------------------------ + */ + +char * +defGetType(ttype, lefptr) + TileType ttype; + lefLayer **lefptr; +{ + HashSearch hs; + HashEntry *he; + lefLayer *lefl; + int contact = DBIsContact(ttype) ? CLASS_VIA : CLASS_ROUTE; + + /* Pick up information from the original LefInfo hash table */ + /* entries created during read-in of the tech file. */ + + if (LefInfo.ht_table != (HashEntry **) NULL) + { + HashStartSearch(&hs); + while (he = HashNext(&LefInfo, &hs)) + { + lefl = (lefLayer *)HashGetValue(he); + if (lefl && (lefl->type == ttype) && (contact == lefl->lefClass)) + { + if (lefptr) *lefptr = lefl; + return lefl->canonName; + } + } + } + + /* If we got here, there is no entry; use the database name */ + if (lefptr) *lefptr = (lefLayer *)NULL; + return DBTypeLongNameTbl[ttype]; +} + +/* + *------------------------------------------------------------ + * + * defWriteVias -- + * + * Output the VIAS section of a DEF file. We equate magic + * contact areas with DEF "VIAS". A separate via entry is + * generated for each unique geometry. The exact output + * is determined from the CIF output rules. + * + * Results: + * None. + * + * Side Effects: + * Output written to the DEF output file. + * + *------------------------------------------------------------ + */ + +void +defWriteVias(f, rootDef, oscale, lefMagicToLefLayer) + FILE *f; /* File to write to */ + CellDef *rootDef; /* Cell definition to use */ + float oscale; /* Output scale factor */ + LefMapping *lefMagicToLefLayer; +{ + HashSearch hs; + HashEntry *he; + lefLayer *lefl; + TileTypeBitMask *rMask; + TileType ttype; + + /* Pick up information from the LefInfo hash table */ + /* created by fucntion defCountVias() */ + + if (LefInfo.ht_table != (HashEntry **) NULL) + { + HashStartSearch(&hs); + while (he = HashNext(&LefInfo, &hs)) + { + int size, sep, border; + char *us1, *us2; + lefl = (lefLayer *)HashGetValue(he); + if (!lefl) continue; + + /* Only count the generated vias of the type name_sizex_sizey */ + + if ((us1 = strchr(lefl->canonName, '_')) == NULL || + (us2 = strrchr(lefl->canonName, '_')) == us1) + continue; + + if (lefl->lefClass == CLASS_VIA) + { + fprintf(f, " - %s", (char *)lefl->canonName); + + /* Generate squares for the area as determined */ + /* by the cifoutput section of the tech file */ + + rMask = DBResidueMask(lefl->type); + for (ttype = TT_TECHDEPBASE; ttype < DBNumUserLayers; ttype++) + if (TTMaskHasType(rMask, ttype)) + fprintf(f, "\n + RECT %s ( %.10g %.10g ) ( %.10g %.10g )", + lefMagicToLefLayer[ttype].lefName, + (float)(lefl->info.via.area.r_xbot) * oscale / 2, + (float)(lefl->info.via.area.r_ybot) * oscale / 2, + (float)(lefl->info.via.area.r_xtop) * oscale / 2, + (float)(lefl->info.via.area.r_ytop) * oscale / 2); + + /* Handle the contact cuts. */ + + if (CIFGetContactSize(lefl->type, &size, &sep, &border)) + { + int i, j, nAc, nUp, pitch, left; + Rect square, *r = &lefl->info.via.area; + + pitch = size + sep; + nAc = (r->r_xtop - r->r_xbot + sep - (2 * border)) / pitch; + if (nAc == 0) + { + left = (r->r_xbot + r->r_xtop - size) / 2; + if (left >= r->r_xbot) nAc = 1; + } + else + left = (r->r_xbot + r->r_xtop + sep - (nAc * pitch)) / 2; + + nUp = (r->r_ytop - r->r_ybot + sep - (2 * border)) / pitch; + if (nUp == 0) + { + square.r_ybot = (r->r_ybot + r->r_ytop - size) / 2; + if (square.r_ybot >= r->r_ybot) nUp = 1; + } + else + square.r_ybot = (r->r_ybot + r->r_ytop + sep - (nUp * pitch)) / 2; + + for (i = 0; i < nUp; i++) + { + square.r_ytop = square.r_ybot + size; + square.r_xbot = left; + for (j = 0; j < nAc; j++) + { + square.r_xtop = square.r_xbot + size; + + fprintf(f, "\n + RECT %s ( %.10g %.10g )" + " ( %.10g %.10g )", + lefMagicToLefLayer[lefl->type].lefName, + (float)(square.r_xbot) * oscale / 2, + (float)(square.r_ybot) * oscale / 2, + (float)(square.r_xtop) * oscale / 2, + (float)(square.r_ytop) * oscale / 2); + square.r_xbot += pitch; + } + square.r_ybot += pitch; + } + } + else + /* If we can't find the CIF/GDS parameters for cut */ + /* generation, then output a single rectangle the */ + /* size of the contact tile. */ + { + fprintf(f, "\n + RECT %s ( %.10g %.10g ) ( %.10g %.10g )", + lefMagicToLefLayer[lefl->type].lefName, + (float)(lefl->info.via.area.r_xbot) * oscale / 2, + (float)(lefl->info.via.area.r_ybot) * oscale / 2, + (float)(lefl->info.via.area.r_xtop) * oscale / 2, + (float)(lefl->info.via.area.r_ytop) * oscale / 2); + } + fprintf(f, " ;\n"); + } + } + } +} + +/* + *------------------------------------------------------------ + * + * defCountComponents -- + * + * First-pass function to count the number of cell + * uses (components) to be written to the DEF output + * file. + * + * Results: + * The total number of uses to be written. + * + * Side Effects: + * None. + * + *------------------------------------------------------------ + */ + +int +defCountComponents(rootDef) + CellDef *rootDef; +{ + pointertype total; + int defCountCompFunc(); + + TxPrintf("Diagnostic: Finding all components of cell %s\n", rootDef->cd_name); + + total = 0; + DBCellEnum(rootDef, defCountCompFunc, (ClientData)&total); + return (int)total; +} + +/* Callback function used by defCountComponents */ + +int +defCountCompFunc(cellUse, total) + CellUse *cellUse; + pointertype *total; +{ + /* Ignore any cellUse that does not have an identifier string. */ + if (cellUse->cu_id == NULL) return 0; + + (*total)++; /* Increment the count of uses */ + + return 0; /* Keep the search going */ +} + +/* + *------------------------------------------------------------ + * + * defWriteComponents -- + * + * Output the COMPONENTS section of the DEF file. This + * is a listing of all cell uses, their placement, and + * orientation. + * + * Results: + * None. + * + * Side Effects: + * Output to the DEF file. + * + *------------------------------------------------------------ + */ + +void +defWriteComponents(f, rootDef, oscale) + FILE *f; /* File to write to */ + CellDef *rootDef; /* Cell definition to use */ + float oscale; /* Output scale factor */ +{ + DefData defdata; + int defComponentFunc(); /* Forward declaration */ + + defdata.f = f; + defdata.scale = oscale; + + DBCellEnum(rootDef, defComponentFunc, (ClientData)&defdata); +} + +/* Callback function used by defWriteComponents */ + +int +defComponentFunc(cellUse, defdata) + CellUse *cellUse; + DefData *defdata; +{ + FILE *f = defdata->f; + float oscale = defdata->scale; + + /* Ignore any cellUse that does not have an identifier string. */ + if (cellUse->cu_id == NULL) return 0; + + fprintf(f, " - %s %s\n + PLACED ( %.10g %.10g ) %s ;\n", + cellUse->cu_id, cellUse->cu_def->cd_name, + (float)cellUse->cu_bbox.r_xbot * oscale, + (float)cellUse->cu_bbox.r_ybot * oscale, + defTransPos(&cellUse->cu_transform)); + + return 0; /* Keep the search going */ +} + +/* + *------------------------------------------------------------ + * + * defMakeInverseLayerMap --- + * + * Generate an array of pointers to lefLayer structures for each + * magic type so we can do a quick lookup when searching over tiles. + * + * Results: + * Pointer to the inverse layer map. + * + * Side effects: + * Memory is allocated for the map structure array. + * + *------------------------------------------------------------ + */ + +LefMapping * +defMakeInverseLayerMap() +{ + LefMapping *lefMagicToLefLayer; + lefLayer *lefl; + TileType i; + char *lefname; + + lefMagicToLefLayer = (LefMapping *)mallocMagic(DBNumUserLayers + * sizeof(LefMapping)); + for (i = TT_TECHDEPBASE; i < DBNumUserLayers; i++) + { + lefname = defGetType(i, &lefl); + lefMagicToLefLayer[i].lefName = lefname; + lefMagicToLefLayer[i].lefInfo = lefl; + } + return lefMagicToLefLayer; +} + +/* + *------------------------------------------------------------ + * + * DefWriteAll -- + * + * Results: + * + * Side Effects: + * + *------------------------------------------------------------ + */ + +/* To do: routine DefWriteAll(). */ + +/* DEF does not handle hierarchy. However, we should assume that we */ +/* want to write out a DEF file for each cell in the hierarchy. But, */ +/* we should stop at any cells defining ports, assuming that they are */ +/* standard cells and not part of the routing. */ + +/* Maybe there should be a method for specifying that any hierarchy */ +/* should be flattened when writing to the DEF file output. */ + + +/* + *------------------------------------------------------------ + * + * DefWriteCell -- + * + * Write DEF-format output for the indicated cell. + * + * Results: + * None. + * + * Side effects: + * Writes a single .def file to disk. + * + *------------------------------------------------------------ + */ + +void +DefWriteCell(def, outName, allSpecial) + CellDef *def; /* Cell being written */ + char *outName; /* Name of output file, or NULL. */ + bool allSpecial; /* Treat all nets as SPECIALNETS? */ +{ + char *filename; + FILE *f; + NetCount nets; + int total; + float scale = CIFGetOutputScale(1); /* Note that "1" here corresponds + * to "1000" in the header UNITS line + */ + LefMapping *lefMagicToLefLayer; + int i; + lefLayer *lefl; + HashEntry *he; + + f = lefFileOpen(def, outName, ".def", "w", &filename); + + TxPrintf("Generating DEF output %s for cell %s:\n", filename, def->cd_name); + + if (f == NULL) + { +#ifdef MAGIC_WRAPPER + TxError("Cannot open output file %s (%s).\n", filename, + strerror(errno)); +#else + TxError("Cannot open output file: "); + perror(filename); +#endif + return; + } + + defWriteHeader(def, f, scale); + + lefMagicToLefLayer = defMakeInverseLayerMap(); + + /* Vias---magic contact areas are reported as vias. */ + total = defCountVias(def, lefMagicToLefLayer, scale); + fprintf(f, "VIAS %d ;\n", total); + if (total > 0) + defWriteVias(f, def, scale, lefMagicToLefLayer); + fprintf(f, "END VIAS\n\n"); + + /* Components (i.e., cell uses) */ + total = defCountComponents(def); + fprintf(f, "COMPONENTS %d ;\n", total); + if (total > 0) + defWriteComponents(f, def, scale); + fprintf(f, "END COMPONENTS\n\n"); + + /* Pins---assume no pins (for now) */ + fprintf(f, "PINS 0 ;\nEND PINS\n\n"); + + /* Count the number of nets and "special" nets */ + nets = defCountNets(def, allSpecial); + + /* "Special" nets---nets matching $GND, $VDD, or $globals(*) */ + + fprintf(f, "SPECIALNETS %d ;\n", nets.special); + if (nets.special > 0) + defWriteNets(f, def, scale, lefMagicToLefLayer, (allSpecial) ? + ALL_SPECIAL : DO_SPECIAL); + fprintf(f, "END SPECIALNETS\n\n"); + + /* "Regular" nets */ + fprintf(f, "NETS %d ;\n", nets.regular); + if (nets.regular > 0) + defWriteNets(f, def, scale, lefMagicToLefLayer, DO_REGULAR); + fprintf(f, "END NETS\n\n"); + + if (nets.has_nets) { + EFFlatDone(); + EFDone(); + } + + fprintf(f, "END DESIGN\n\n"); + fclose(f); + + freeMagic((char *)lefMagicToLefLayer); + lefRemoveGeneratedVias(); +} + diff --git a/lef/lef.h b/lef/lef.h new file mode 100644 index 00000000..ba9ed52e --- /dev/null +++ b/lef/lef.h @@ -0,0 +1,24 @@ +/* + * lef.h -- + * + * Contains definitions for things that are exported by the + * lef module. + * + */ + +#ifndef _LEF_H +#define _LEF_H + +#include "utils/magic.h" + +/* Procedures for reading the technology file: */ + +extern void LefTechInit(); +extern bool LefTechLine(); +extern void LefTechScale(); + +/* Initialization: */ + +extern void LefInit(); + +#endif /* _LEF_H */ diff --git a/lef/lefCmd.c b/lef/lefCmd.c new file mode 100644 index 00000000..53f61176 --- /dev/null +++ b/lef/lefCmd.c @@ -0,0 +1,220 @@ +/* + * lefCmd.c -- + * + * Commands for the LEF module only. + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/lef/lefCmd.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" +#include "textio/txcommands.h" +#include "commands/commands.h" + + +/* + * ---------------------------------------------------------------------------- + * + * CmdLef -- + * + * Implement the "lef" and "def" commands: generate LEF-format output + * for a layout, or read LEF- or DEF-format files. + * + * Usage: + * lef [options] + * def [options] + * + * Results: + * Always return 0. + * + * Side effects: + * Generates LEF-format output on disk somewhere, or reads + * LEF- or DEF-format files, generating cell definitions and + * uses in the process. + * + * ---------------------------------------------------------------------------- + */ + +/* These definitions must correspond to the ordering in cmdLefOption[] below */ + +#define LEF_READ 0 +#define LEF_WRITE 1 +#define LEF_WRITEALL 2 +#define LEF_HELP 3 + +void +CmdLef(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int option; + char **msg, *namep; + CellUse *selectedUse; + CellDef *selectedDef; + bool is_lef; + bool lefImport = FALSE; /* Indicates whether or not we + * read cells from .mag files + * when the FOREIGN statement + * is encountered in a macro. + */ + bool lefTopCell = TRUE; /* Indicates whether or not we + * write the top-level cell to + * LEF, or just the subcells. + */ + bool allSpecial = FALSE; /* Indicates whether we should + * treat all geometry as "special" + * nets in DEF format output. + */ + + static char *cmdLefOption[] = + { + "read [filename] read a LEF file filename[.lef]\n" + " read [filename] -import read a LEF file; import cells from .mag files", + "write [cell] write LEF for current or indicated cell", + "writeall write all cells including the top-level cell\n" + " writeall -notop write all subcells of the top-level cell", + "help print this help information", + NULL + }; + + static char *cmdDefOption[] = + { + "read [filename] read a DEF file filename[.def]", + "write [cell] [-allspecial] write DEF for current or indicated cell", + "writeall (use \"flatten -nosubckt\" + \"def" + " write\" instead)", + "help print this help information", + NULL + }; + + /* Determine whether this function has been called via the "lef" or + * the "def" command. + */ + is_lef = (cmd->tx_argv[0][0] == 'd') ? FALSE : TRUE; + + if (cmd->tx_argc < 2) + option = LEF_HELP; + else + { + option = Lookup(cmd->tx_argv[1], cmdLefOption); + if (option < 0) + { + TxError("\"%s\" isn't a valid %s option.\n", cmd->tx_argv[1], + cmd->tx_argv[0]); + option = LEF_HELP; + } + } + + if (option != LEF_HELP) + { + selectedUse = CmdGetSelectedCell((Transform *)NULL); + if (selectedUse == NULL) + { + windCheckOnlyWindow(&w, DBWclientID); + if (w == (MagWindow *) NULL) + { + if (ToolGetBox(&selectedDef,NULL) == FALSE) + { + TxError("Point to a window first\n"); + return; + } + selectedUse = selectedDef->cd_parents; + } + else + selectedUse = (CellUse *)w->w_surfaceID; + } + } + + switch (option) + { + case LEF_READ: + if (cmd->tx_argc != 3) + { + if (cmd->tx_argc == 4) + { + if (*(cmd->tx_argv[3]) == '-') + if (!strncmp(cmd->tx_argv[3], "-import", 7)) + lefImport = TRUE; + } + else + goto wrongNumArgs; + } + namep = cmd->tx_argv[2]; + if (is_lef) + LefRead(namep, lefImport); + else + DefRead(namep); + break; + case LEF_WRITEALL: + if (!is_lef) + { + TxError("Sorry, can't write hierarchical DEF at this time.\n"); + TxError("Try \"def write\"\n"); + } + else + { + if (cmd->tx_argc == 3) + if (*(cmd->tx_argv[2]) == '-') + if (!strncmp(cmd->tx_argv[2], "-notop", 6)) + lefTopCell = FALSE; + + LefWriteAll(selectedUse, lefTopCell); + } + break; + case LEF_WRITE: + if (!is_lef) + { + allSpecial = FALSE; + if (cmd->tx_argc == 4) + { + if (*(cmd->tx_argv[3]) == '-') + { + if (!strncmp(cmd->tx_argv[3], "-allspec", 8)) + allSpecial = TRUE; + else goto wrongNumArgs; + } + else goto wrongNumArgs; + } + else if (cmd->tx_argc != 3) goto wrongNumArgs; + } + else if (cmd->tx_argc != 2) goto wrongNumArgs; + if (selectedUse == NULL) + { + TxError("No cell selected\n"); + return; + } + if (cmd->tx_argc == 2) + namep = selectedUse->cu_def->cd_name; + else + namep = cmd->tx_argv[2]; + if (!is_lef) + DefWriteCell(selectedUse->cu_def, namep, allSpecial); + else + LefWriteCell(selectedUse->cu_def, namep, selectedUse->cu_def + == EditRootDef); + break; + case LEF_HELP: +wrongNumArgs: + TxPrintf("The \"%s\" options are:\n", cmd->tx_argv[0]); + msg = (is_lef) ? &(cmdLefOption[0]) : &(cmdDefOption[0]); + for (; *msg != NULL; msg++) + { + TxPrintf(" %s %s\n", cmd->tx_argv[0], *msg); + } + break; + } +} diff --git a/lef/lefInt.h b/lef/lefInt.h new file mode 100644 index 00000000..e6568423 --- /dev/null +++ b/lef/lefInt.h @@ -0,0 +1,137 @@ +/* + * lefInt.h -- + * + * This file defines things that are used by internal LEF routines in + * various files. + * + * rcsid $Header: /usr/cvsroot/magic-8.0/lef/lefInt.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _LEFINT_H +#define _LEFINT_H + +#include "utils/magic.h" + +/* Some constants for LEF and DEF files */ + +#define LEF_LINE_MAX 2048 /* Maximum length fixed by LEF/DEF specifications */ +#define LEF_MAX_ERRORS 100 /* Max # errors to report; limits output if */ + /* something is really wrong about the file */ + +#define DEFAULT_WIDTH 3 /* Default metal width for routes if undefined */ +#define DEFAULT_SPACING 4 /* Default spacing between metal if undefined */ + +/* Structure holding the counts of regular and special nets */ + +typedef struct +{ + int regular; + int special; + bool has_nets; +} NetCount; + +/* Various modes for writing nets. */ +#define DO_REGULAR 0 +#define DO_SPECIAL 1 +#define ALL_SPECIAL 2 /* treat all nets as SPECIALNETS */ + +/* For a linked list of rectangular areas, use the LinkedRect structure */ +/* defined in utils/geometry.h. */ + +/* Structure used for returning information about polygon geometry */ + +typedef struct _linkedPoint { + Point pos; + TileType type; + struct _linkedPoint *point_next; +} linkedPoint; + +/* Structure used to maintain default routing information for each */ +/* routable layer type. */ + +typedef struct { + int width; /* width, in lambda */ + int spacing; /* minimum spacing rule, in lambda */ + int pitch; /* route pitch, in lambda */ + bool hdirection; /* horizontal direction preferred */ +} lefRoute; + +/* Structure used to maintain default generation information for each */ +/* via or viarule (contact) type. If "cell" is non-NULL, then the via */ +/* is saved in a cell (pointed to by "cell"), and "area" describes the */ +/* bounding box. Otherwise, the via is formed by magic type "type" */ +/* with a minimum area "area" for a single contact. */ + +typedef struct { + Rect area; /* Area of single contact, or cell bbox */ + /* in units of 1/2 lambda */ + CellDef *cell; /* Cell for fixed via def, or NULL */ + LinkedRect *lr; /* Extra information for vias with */ + /* more complicated geometry. */ + TileType obsType; /* Secondary obstruction type */ +} lefVia; + +/* Defined types for "lefClass" in the lefLayer structure */ + +#define CLASS_ROUTE 0 /* routing layer */ +#define CLASS_VIA 1 /* via or cut layer */ +#define CLASS_MASTER 2 /* masterslice layer */ +#define CLASS_OVERLAP 3 /* overlap layer */ +#define CLASS_BOUND 4 /* boundary-defining layer */ +#define CLASS_IGNORE 5 /* inactive layer */ + +/* Structure defining a route or via layer and matching it to a magic */ +/* layer type. This structure is saved in the LefInfo hash table. */ +/* To allow multiple names to refer to the same structure, we keep a */ +/* reference count of the number of times a hash table value points to */ +/* this structure. */ + +typedef struct { + TileType type; /* magic tile type, or -1 for none */ + TileType obsType; /* magic type to use if this is an obstruction */ + short refCnt; /* reference count for memory deallocation */ + char * canonName; /* name to use when writing LEF output */ + unsigned char lefClass; /* is this a via, route, or masterslice layer */ + union { + lefRoute route; /* for route layers */ + lefVia via; /* for contacts */ + } info; +} lefLayer; + +/* Inverse mapping structure for returning the primary LEF */ +/* layer corresponding to a magic tile type. */ + +typedef struct { + char *lefName; /* Primary name of LEF layer */ + lefLayer *lefInfo; /* Pointer to information about the layer */ +} LefMapping; + +/* External declaration of global variables */ +extern int lefCurrentLine; +extern HashTable LefInfo; + +/* Forward declarations */ + +int lefDefInitFunc(), lefDefPushFunc(); +FILE *lefFileOpen(); + +char *LefGetInput(); +int LefParseEndStatement(); +void LefSkipSection(); +void LefEndStatement(); +CellDef *lefFindCell(); +char *LefNextToken(); +char *LefLower(); +LinkedRect *LefReadGeometry(); +void LefEstimate(); +lefLayer *LefRedefined(); +void LefAddViaGeometry(); +Rect *LefReadRect(); +TileType LefReadLayer(); + +LefMapping *defMakeInverseLayerMap(); + +void LefError(char *, ...); /* Variable argument procedure requires */ + /* parameter list. */ + +#endif /* _LEFINT_H */ diff --git a/lef/lefRead.c b/lef/lefRead.c new file mode 100644 index 00000000..258cea08 --- /dev/null +++ b/lef/lefRead.c @@ -0,0 +1,2067 @@ +/* + * lefRead.c -- + * + * This module incorporates the LEF/DEF format for standard-cell place and + * route. + * + * Version 0.1 (September 26, 2003): LEF input handling. Includes creation + * of cells from macro statements, handling of pins, ports, obstructions, and + * associated geometry. + * + * Note that techfile compatibility requires that each layer name appearing + * in the LEF file should be present as an alias for the appropriate magic + * tile type in the technology file. Layer names are not case sensitive. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/lef/lefRead.c,v 1.2 2008/12/17 18:40:04 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include /* for roundf() function, if std=c99 */ + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/undo.h" +#include "database/database.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "dbwind/dbwind.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "cif/cif.h" +#include "cif/CIFint.h" /* Access to CIFCurStyle. . . */ +#include "lef/lefInt.h" + +/* ---------------------------------------------------------------------*/ + +/* Current line number for reading */ +int lefCurrentLine; + +/* Cell reading hash tables */ +HashTable LefCellTable; +HashTable lefDefInitHash; + +/* + *------------------------------------------------------------ + * + * LefEstimate -- + * + * Estimate the time to completion based on the time, + * the total number of items to process, and the number + * of items processed so far. Attempts to report about + * every 5 seconds or so. + * + * Results: + * None. + * + * Side Effects: + * May print to output. + * + *------------------------------------------------------------ + */ + +#define PRINT_INTERVAL 5 /* print status at 4 second intervals */ + +void +LefEstimate(processed, total, item_name) + int processed; + int total; + char *item_name; +{ + static int check_interval, partition; + static struct timeval tv_start; + static float last_time; + struct timeval tv; + struct timezone tz; + float cur_time, time_left; + + if (!total) return; + + if (processed == 0) /* Initialization */ + { + gettimeofday(&tv_start, &tz); + GrDisplayStatus = DISPLAY_IN_PROGRESS; + SigSetTimer(PRINT_INTERVAL); + } + else if (processed == total - 1) + { + GrDisplayStatus = DISPLAY_IDLE; + SigRemoveTimer(); + } + else if (GrDisplayStatus == DISPLAY_BREAK_PENDING) + { + gettimeofday(&tv, &tz); + cur_time = (float)(tv.tv_sec - tv_start.tv_sec) + + ((float)(tv.tv_usec - tv_start.tv_usec) / 1.0e6); + time_left = (((float)total / (float)processed) - 1) * cur_time; + + /* not likely to happen, but we don't want a divide-by-0 error */ + if (cur_time == 0.0) cur_time = 1.0e-6; + + TxPrintf(" Processed %d of %d %s (%2.1f%%).", processed, total, + item_name, (float)(100 * processed) / (float)total); + TxPrintf(" Est. time remaining: %2.1fs\n", time_left); + TxFlushOut(); + +#ifdef MAGIC_WRAPPER + /* We need to let Tk paint the console display */ + while (Tcl_DoOneEvent(TCL_DONT_WAIT) != 0); +#endif + + GrDisplayStatus = DISPLAY_IN_PROGRESS; + SigSetTimer(PRINT_INTERVAL); + } +} + +/* This is the original version, which doesn't use the system itimer */ +/* and which is not very good at maintaining constant intervals. */ + +#if 0 +void +LefEstimate(processed, total, item_name) + int processed; + int total; + char *item_name; +{ + static int check_interval, partition; + static struct timeval tv_start; + static float last_time; + struct timeval tv; + struct timezone tz; + float cur_time, time_left; + + if (!total) return; + + if (processed == 0) /* Initialization */ + { + GrDisplayStatus = DISPLAY_IN_PROGRESS; + + check_interval = 100; + gettimeofday(&tv_start, &tz); + last_time = 0.0; + } + + if (processed > check_interval) + { + gettimeofday(&tv, &tz); + cur_time = (float)(tv.tv_sec - tv_start.tv_sec) + + ((float)(tv.tv_usec - tv_start.tv_usec) / 1.0e6); + time_left = (((float)total / (float)processed) - 1) * cur_time; + + /* not likely to happen, but we don't want a divide-by-0 error */ + if (cur_time == 0.0) cur_time = 1.0e-6; + + partition = (int)((float)processed * (float)PRINT_INTERVAL / cur_time); + + /* partition is never less than 1 nor greater than 5% of the total */ + if (partition == 0) partition = 1; + if (partition > (total / 20)) partition = (total / 20); + + check_interval += partition; + + /* Don't print anything in intervals faster than 1 second */ + if ((cur_time - last_time) < 1.0) return; + last_time = cur_time; + + TxPrintf(" Processed %d of %d %s (%2.1f%%).", processed, total, + item_name, (float)(100 * processed) / (float)total); + TxPrintf(" Est. time remaining: %2.1fs\n", time_left); + TxFlushOut(); + } +} + +#endif /* 0 */ + + +/* + *------------------------------------------------------------ + * + * LefNextToken -- + * + * Move to the next token in the stream input. + * If "ignore_eol" is FALSE, then the end-of-line character + * "\n" will be returned as a token when encountered. + * Otherwise, end-of-line will be ignored. + * + * Results: + * Pointer to next token to parse + * + * Side Effects: + * May read a new line from the specified file. + * + * Warnings: + * The return result of LefNextToken will be overwritten by + * subsequent calls to LefNextToken if more than one line of + * input is parsed. + * + *------------------------------------------------------------ + */ + +char * +LefNextToken(f, ignore_eol) + FILE *f; + bool ignore_eol; +{ + static char line[LEF_LINE_MAX + 2]; /* input buffer */ + static char *nexttoken = NULL; /* pointer to next token */ + static char *curtoken; /* pointer to current token */ + static char eol_token='\n'; + + /* Read a new line if necessary */ + + if (nexttoken == NULL) + { + for(;;) + { + if (fgets(line, LEF_LINE_MAX + 1, f) == NULL) return NULL; + lefCurrentLine++; + curtoken = line; + while (isspace(*curtoken) && (*curtoken != '\n') && (*curtoken != '\0')) + curtoken++; /* skip leading whitespace */ + + if ((*curtoken != '#') && (*curtoken != '\n') && (*curtoken != '\0')) + { + nexttoken = curtoken; + break; + } + } + if (!ignore_eol) + return &eol_token; + } + else + curtoken = nexttoken; + + /* Find the next token; set to NULL if none (end-of-line). */ + /* Treat quoted material as a single token. */ + + if (*nexttoken == '\"') { + nexttoken++; + while (((*nexttoken != '\"') || (*(nexttoken - 1) == '\\')) && + (*nexttoken != '\0')) { + if (*nexttoken == '\n') { + if (fgets(nexttoken + 1, LEF_LINE_MAX - + (size_t)(nexttoken - line), f) == NULL) + return NULL; + } + nexttoken++; + } + if (*nexttoken == '\"') + nexttoken++; + } + else { + while (!isspace(*nexttoken) && (*nexttoken != '\0') && (*nexttoken != '\n')) + nexttoken++; /* skip non-whitespace (move past current token) */ + } + + /* Terminate the current token */ + if (*nexttoken != '\0') *nexttoken++ = '\0'; + + while (isspace(*nexttoken) && (*nexttoken != '\0') && (*nexttoken != '\n')) + nexttoken++; /* skip any whitespace */ + + if ((*nexttoken == '#') || (*nexttoken == '\n') || (*nexttoken == '\0')) + nexttoken = NULL; + + return curtoken; +} + +/* + *------------------------------------------------------------ + * + * LefError -- + * + * Print an error message (via TxError) giving the line + * number of the input file on which the error occurred. + * + * Results: + * None. + * + * Side Effects: + * Prints to the output (stderr). + * + *------------------------------------------------------------ + */ + +void +LefError(char *fmt, ...) +{ + static int errors = 0; + va_list args; + + if (fmt == NULL) /* Special case: report any errors and reset */ + { + if (errors) + { + TxPrintf("LEF Read: encountered %d error%s total.\n", errors, + (errors == 1) ? "" : "s"); + errors = 0; + } + return; + } + + if (errors < LEF_MAX_ERRORS) + { + TxError("LEF Read, Line %d: ", lefCurrentLine); + va_start(args, fmt); + Vfprintf(stderr, fmt, args); + va_end(args); + TxFlushErr(); + } + else if (errors == LEF_MAX_ERRORS) + TxError("LEF Read: Further errors will not be reported.\n"); + + errors++; +} + +/* + *------------------------------------------------------------ + * + * LefParseEndStatement -- + * + * Check if the string passed in "lineptr" contains the + * appropriate matching keyword. Sections in LEF files + * should end with "END (keyword)" or "END". To check + * against the latter case, "match" should be NULL. + * + * Results: + * 1 if the line matches the expected end statement, + * 0 if not. Return -1 if the last token read was + * "END", indicating to the caller that either an + * error has occurred or, in the case of a section + * skip, the routine needs to be called again. + * + * Side effects: + * None. + * + *------------------------------------------------------------ + */ + +int +LefParseEndStatement(f, match) + FILE *f; + char *match; +{ + char *token; + int keyword, words; + char *match_name[2]; + + static char *end_section[] = { + "END", + "ENDEXT", + NULL + }; + + match_name[0] = match; + match_name[1] = NULL; + + token = LefNextToken(f, (match == NULL) ? FALSE : TRUE); + if (token == NULL) + { + LefError("Bad file read while looking for END statement\n"); + return 0; + } + + /* END or ENDEXT */ + if ((*token == '\n') && (match == NULL)) return 1; + + /* END */ + else { + keyword = LookupFull(token, match_name); + if (keyword == 0) + return 1; + else + { + /* Check for END followed by END */ + keyword = LookupFull(token, end_section); + if (keyword == 0) + return -1; + else + return 0; + } + } +} + +/* + *------------------------------------------------------------ + * + * LefSkipSection -- + * + * Skip to the "END" record of a LEF input section + * String "section" must follow the "END" statement in + * the file to be considered a match; however, if + * section = NULL, then "END" must have no strings + * following. + * + * Results: + * None. + * + * Side Effects: + * Reads input from the specified file. Prints an + * error message if the expected END record cannot + * be found. + * + *------------------------------------------------------------ + */ + +void +LefSkipSection(f, section) + FILE *f; + char *section; +{ + char *token; + int keyword, result; + static char *end_section[] = { + "END", + "ENDEXT", + NULL + }; + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + if ((keyword = Lookup(token, end_section)) == 0) + { + result = -1; + while (result == -1) + { + result = LefParseEndStatement(f, section); + if (result == 1) return; + } + } + else if (keyword == 1) + { + if (!strcmp(section, "BEGINEXT")) + return; + } + } + + LefError("Section %s has no END record!\n", section); + return; +} + +/* + *------------------------------------------------------------ + * + * lefFindCell -- + * + * Search for an existing cell of the given name. If + * it exists, return a pointer to the cell def. If not, + * create a new cell def with the given name and return + * a pointer to it. + * + *------------------------------------------------------------ + */ + +CellDef * +lefFindCell(name) + char *name; /* Name of the cell to search for */ +{ + HashEntry *h; + CellDef *def; + + h = HashFind(&LefCellTable, name); + if (HashGetValue(h) == 0) + { + def = DBCellLookDef(name); + if (def == NULL) + { + def = DBCellNewDef(name, (char *)NULL); + DBReComputeBbox(def); + } + HashSetValue(h, def); + } + return (CellDef *) HashGetValue(h); +} + +/* + *------------------------------------------------------------ + * + * LefLower -- + * + * Convert a token in a LEF or DEF file to all-lowercase. + * + *------------------------------------------------------------ + */ + +char * +LefLower(token) + char *token; +{ + char *tptr; + + for (tptr = token; *tptr != '\0'; tptr++) + *tptr = tolower(*tptr); + + return token; +} + +/* + *------------------------------------------------------------ + * LefRedefined -- + * + * In preparation for redefining a LEF layer, we need + * to first check if there are multiple names associated + * with the lefLayer entry. If so, split the entry into + * two copies, so that the redefinition doesn't affect + * the other LEF names. + * + * Results: + * Pointer to a lefLayer, which may or may not be the + * same one presented to the subroutine. + * + * Side Effects: + * May add an entry to the list of LEF layers. + * + *------------------------------------------------------------ + */ + +lefLayer * +LefRedefined(lefl, redefname) + lefLayer *lefl; + char *redefname; +{ + lefLayer *slef, *newlefl; + char *altName; + LinkedRect *viaLR; + HashSearch hs; + HashEntry *he; + int records; + + /* check if more than one entry points to the same */ + /* lefLayer record. If so, we will also record the */ + /* name of the first type that is not the same as */ + /* "redefname". */ + + records = 0; + altName = NULL; + HashStartSearch(&hs); + while (he = HashNext(&LefInfo, &hs)) + { + slef = (lefLayer *)HashGetValue(he); + if (slef == lefl) + records++; + if (altName == NULL) + if (strcmp((char *)he->h_key.h_name, redefname)) + altName = (char *)he->h_key.h_name; + } + if (records == 1) + { + /* Only one name associated with the record, so */ + /* just clear all the allocated information. */ + + for (viaLR = lefl->info.via.lr; viaLR != NULL; viaLR = viaLR->r_next) + freeMagic(viaLR); + newlefl = lefl; + } + else + { + he = HashFind(&LefInfo, redefname); + newlefl = (lefLayer *)mallocMagic(sizeof(lefLayer)); + newlefl->refCnt = 1; + newlefl->canonName = (char *)he->h_key.h_name; + HashSetValue(he, newlefl); + + /* If the canonical name of the original entry */ + /* is "redefname", then change it. */ + + if (!strcmp(lefl->canonName, redefname)) + if (altName != NULL) + lefl->canonName = altName; + } + newlefl->type = -1; + newlefl->obsType = -1; + newlefl->info.via.area = GeoNullRect; + newlefl->info.via.cell = (CellDef *)NULL; + newlefl->info.via.lr = (LinkedRect *)NULL; + + return newlefl; +} + +/* + *------------------------------------------------------------ + * LefReadLayers -- + * + * Read a LEF "LAYER" record from the file, and + * match the LEF layer to a magic tile type. + * If "obstruct" is TRUE, returns the layer mapping + * for obstruction geometry as defined in the + * technology file (if it exists), and up to two + * types are returned (the second in the 3rd argument + * pointer). + * + * Results: + * Returns a magic TileType or -1 if no matching + * tile type is found. + * + * Side Effects: + * Reads input from file f; + * + *------------------------------------------------------------ + */ + +TileType +LefReadLayers(f, obstruct, lreturn, rreturn) + FILE *f; + bool obstruct; + TileType *lreturn; + Rect **rreturn; +{ + char *token; + TileType curlayer = -1; + lefLayer *lefl = NULL; + + token = LefNextToken(f, TRUE); + if (*token == ';') + { + LefError("Bad Layer statement\n"); + return -1; + } + else + { + HashEntry *he = HashLookOnly(&LefInfo, token); + if (he) + { + lefl = (lefLayer *)HashGetValue(he); + if (lefl && obstruct) + { + /* Use the obstruction type, if it is defined */ + curlayer = lefl->obsType; + if ((curlayer < 0) && (lefl->lefClass != CLASS_IGNORE)) + curlayer = lefl->type; + else if (lefl->lefClass == CLASS_VIA) + if (lreturn) *lreturn = lefl->info.via.obsType; + } + else if (lefl) + { + if (lefl->lefClass != CLASS_IGNORE) + curlayer = lefl->type; + if (lefl->lefClass == CLASS_VIA) + if (rreturn) *rreturn = &(lefl->info.via.area); + } + + if (rreturn) + { + if (lefl->lefClass == CLASS_VIA) + *rreturn = &(lefl->info.via.area); + else + *rreturn = &GeoNullRect; + } + } + else + { + /* fallback: compare name to magic types */ + + curlayer = DBTechNameType(token); + if (curlayer < 0) + { + (void) LefLower(token); + curlayer = DBTechNameType(token); + } + } + if ((curlayer < 0) && ((!lefl) || (lefl->lefClass != CLASS_IGNORE))) + { + LefError("Don't know how to parse layer \"%s\"\n", token); + LefError("Try adding this name to the LEF techfile section\n"); + } + } + return curlayer; +} + +/* + *------------------------------------------------------------ + * LefReadLayer -- + * + * Read a LEF "LAYER" record from the file, and + * match the LEF layer to a magic tile type. + * If "obstruct" is TRUE, returns the layer mapping + * for obstruction geometry as defined in the + * technology file (if it exists). + * + * Results: + * Returns a magic TileType or -1 if no matching + * tile type is found. + * + * Side Effects: + * Reads input from file f; + * + *------------------------------------------------------------ + */ + +TileType +LefReadLayer(f, obstruct) + FILE *f; + bool obstruct; +{ + return LefReadLayers(f, obstruct, (TileType *)NULL, (Rect **)NULL); +} + +/* + *------------------------------------------------------------ + * LefReadRect -- + * + * Read a LEF "RECT" record from the file, and + * return a Rect in magic coordinates. + * + * Results: + * Returns a pointer to a Rect containing the magic + * coordinates, or NULL if an error occurred. + * + * Side Effects: + * Reads input from file f; + * + * Note: + * LEF/DEF does NOT define a RECT record as having (...) + * pairs, only routes. However, at least one DEF file + * contains this syntax, so it is checked. + * + *------------------------------------------------------------ + */ + +Rect * +LefReadRect(f, curlayer, oscale) + FILE *f; + TileType curlayer; + float oscale; +{ + char *token; + float llx, lly, urx, ury; + static Rect paintrect; + bool needMatch = FALSE; + + token = LefNextToken(f, TRUE); + if (*token == '(') + { + token = LefNextToken(f, TRUE); + needMatch = TRUE; + } + if (!token || sscanf(token, "%f", &llx) != 1) goto parse_error; + token = LefNextToken(f, TRUE); + if (!token || sscanf(token, "%f", &lly) != 1) goto parse_error; + token = LefNextToken(f, TRUE); + if (needMatch) + { + if (*token != ')') goto parse_error; + else token = LefNextToken(f, TRUE); + needMatch = FALSE; + } + if (*token == '(') + { + token = LefNextToken(f, TRUE); + needMatch = TRUE; + } + if (!token || sscanf(token, "%f", &urx) != 1) goto parse_error; + token = LefNextToken(f, TRUE); + if (!token || sscanf(token, "%f", &ury) != 1) goto parse_error; + if (needMatch) + { + token = LefNextToken(f, TRUE); + if (*token != ')') goto parse_error; + } + if (curlayer < 0) + LefError("No layer defined for RECT.\n"); + else + { + /* Scale coordinates (microns to magic internal units) */ + /* Need to scale grid if necessary! */ + + paintrect.r_xbot = (int)roundf(llx / oscale); + paintrect.r_ybot = (int)roundf(lly / oscale); + paintrect.r_xtop = (int)roundf(urx / oscale); + paintrect.r_ytop = (int)roundf(ury / oscale); + + /* Diagnostic */ + /* + TxPrintf(" Painting %s at (%d, %d), (%d, %d) in cell %s.\n", + DBTypeLongNameTbl[curlayer], + paintrect.r_xbot, paintrect.r_ybot, + paintrect.r_xtop, paintrect.r_ytop, + lefMacro->cd_name); + */ + } + return (&paintrect); + +parse_error: + LefError("Bad port geometry: RECT requires 4 values.\n"); + return (Rect *)NULL; +} + +/* + *------------------------------------------------------------ + * LefReadPolygon -- + * + * Read a LEF "POLYGON" record from the file, and + * return a linked point structure. + * + * Results: + * Returns a pointer to a Rect containing the magic + * coordinates, or NULL if an error occurred. + * + * Side Effects: + * Reads input from file f; + * + * Note: + * LEF/DEF does NOT define a RECT record as having (...) + * pairs, only routes. However, at least one DEF file + * contains this syntax, so it is checked. + * + *------------------------------------------------------------ + */ + +Point * +LefReadPolygon(f, curlayer, oscale, ppoints) + FILE *f; + TileType curlayer; + float oscale; + int *ppoints; +{ + LinkedRect *lr = NULL, *newRect; + Point *plist = NULL; + char *token; + float px, py; + int lpoints = 0; + + while (1) + { + token = LefNextToken(f, TRUE); + if (token == NULL || *token == ';') break; + if (sscanf(token, "%f", &px) != 1) + { + LefError("Bad X value in polygon.\n"); + LefEndStatement(f); + break; + } + + token = LefNextToken(f, TRUE); + if (token == NULL || *token == ';') + { + LefError("Missing Y value in polygon point!\n"); + break; + } + if (sscanf(token, "%f", &py) != 1) + { + LefError("Bad Y value in polygon.\n"); + LefEndStatement(f); + break; + } + + /* Use the rect structure for convenience; we only */ + /* use the r_ll point of the rect to store each point */ + /* as we read it in. */ + + newRect = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); + newRect->r_r.r_xbot = (int)roundf(px / oscale); + newRect->r_r.r_ybot = (int)roundf(py / oscale); + newRect->r_next = lr; + lr = newRect; + lpoints++; + } + + *ppoints = lpoints; + if (lpoints == 0) return NULL; + + /* Convert LinkedRect structure into a simple point list */ + + plist = (Point *)mallocMagic(lpoints * sizeof(Point)); + lpoints = 0; + while (lr != NULL) + { + plist[*ppoints - lpoints - 1].p_x = lr->r_r.r_xbot; + plist[*ppoints - lpoints - 1].p_y = lr->r_r.r_ybot; + freeMagic(lr); + lpoints++; + lr = lr->r_next; + } + return plist; +} + +/* + *------------------------------------------------------------ + * LefPaintPolygon -- + * + * Paint a polygon into the CellDef indicated by lefMacro. + * + *------------------------------------------------------------ + */ + +LinkedRect * +LefPaintPolygon(lefMacro, pointList, points, curlayer, keep) + CellDef *lefMacro; + Point *pointList; + int points; + TileType curlayer; + bool keep; +{ + int pNum; + PaintUndoInfo ui; + LinkedRect *rlist = NULL, *rptr; + + ui.pu_def = lefMacro; + for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) + { + if (DBPaintOnPlane(curlayer, pNum)) + { + ui.pu_pNum = pNum; + rlist = PaintPolygon(pointList, points, lefMacro->cd_planes[pNum], + DBStdPaintTbl(curlayer, pNum), &ui, keep); + + /* Annotate each rectangle in the list with the type painted */ + if (keep) + for (rptr = rlist; rptr; rptr = rptr->r_next) + rptr->r_type = curlayer; + } + } + return rlist; +} + +/* + *------------------------------------------------------------ + * LefReadGeometry -- + * + * Read Geometry information from a LEF file. + * Used for PORT records and OBS statements. + * + * Results: + * Returns a linked list of all areas and types + * painted. However, if "do_list" is FALSE, then + * LefReadGeometry always returns NULL. + * + * Note that do_list is always TRUE for PORT + * records and FALSE for OBS statements, and so in + * addition to determining what the return value is, + * it also determines what layer is returned by + * function LefReadLayer(). + * + * Side Effects: + * Reads input from file f; + * Paints into the CellDef lefMacro. + * + *------------------------------------------------------------ + */ + +enum lef_geometry_keys {LEF_LAYER = 0, LEF_WIDTH, LEF_PATH, + LEF_RECT, LEF_POLYGON, LEF_VIA, LEF_GEOMETRY_END}; + +LinkedRect * +LefReadGeometry(lefMacro, f, oscale, do_list) + CellDef *lefMacro; + FILE *f; + float oscale; + bool do_list; +{ + TileType curlayer = -1, otherlayer = -1; + + char *token; + int keyword; + LinkedRect *newRect, *rectList; + Point *pointList; + int points; + Rect *paintrect, *contact; + + static char *geometry_keys[] = { + "LAYER", + "WIDTH", + "PATH", + "RECT", + "POLYGON", + "VIA", + "END", + NULL + }; + + rectList = NULL; + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + keyword = Lookup(token, geometry_keys); + if (keyword < 0) + { + LefError("Unknown keyword \"%s\" in LEF file; ignoring.\n", token); + LefEndStatement(f); + continue; + } + switch (keyword) + { + case LEF_LAYER: + curlayer = LefReadLayers(f, (do_list) ? FALSE : TRUE, &otherlayer, + &contact); + LefEndStatement(f); + break; + case LEF_WIDTH: + LefEndStatement(f); + break; + case LEF_PATH: + LefEndStatement(f); + break; + case LEF_RECT: + paintrect = (curlayer < 0) ? NULL : LefReadRect(f, curlayer, oscale); + if (paintrect) + { + /* Paint the area, if a CellDef is defined */ + if (lefMacro) + { + // Cut layers defined as contacts use the contact + // dimensions, not the dimension from the LEF file + if (DBIsContact(curlayer) && !(GEO_RECTNULL(contact))) + { + paintrect->r_xbot = (paintrect->r_xbot + paintrect->r_xtop); + paintrect->r_ybot = (paintrect->r_ybot + paintrect->r_ytop); + paintrect->r_xtop = paintrect->r_xbot + contact->r_xtop; + paintrect->r_ytop = paintrect->r_ybot + contact->r_ytop; + paintrect->r_xbot += contact->r_xbot; + paintrect->r_ybot += contact->r_ybot; + paintrect->r_xbot >>= 1; + paintrect->r_ybot >>= 1; + paintrect->r_xtop >>= 1; + paintrect->r_ytop >>= 1; + } + DBPaint(lefMacro, paintrect, curlayer); + + if ((!do_list) && (otherlayer != -1)) + DBPaint(lefMacro, paintrect, otherlayer); + } + + /* Remember the area and layer */ + if (do_list) + { + newRect = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); + newRect->r_type = curlayer; + newRect->r_r = *paintrect; + newRect->r_next = rectList; + rectList = newRect; + } + } + LefEndStatement(f); + break; + case LEF_POLYGON: + pointList = LefReadPolygon(f, curlayer, oscale, &points); + if (pointList) + { + if (lefMacro) + { + LinkedRect *rectNew, *rectTest; + + rectNew = LefPaintPolygon(lefMacro, pointList, points, + curlayer, TRUE); + + // Add the new list of rectangles to the current list + // of rectangles to be made into port labels. + + if (rectList != NULL) + { + for (rectTest = rectList; rectTest && rectTest->r_next; + rectTest = rectTest->r_next); + rectTest->r_next = rectNew; + } + else + rectList = rectNew; + + if ((!do_list) && (otherlayer != -1)) + LefPaintPolygon(lefMacro, pointList, points, otherlayer); + } + freeMagic(pointList); + } + break; + case LEF_VIA: + LefEndStatement(f); + break; + case LEF_GEOMETRY_END: + if (LefParseEndStatement(f, NULL) == 0) + { + LefError("Geometry (PORT or OBS) END statement missing.\n"); + keyword = -1; + } + break; + } + if (keyword == LEF_GEOMETRY_END) break; + } + return rectList; +} + +/* + *------------------------------------------------------------ + * LefReadPort -- + * + * A wrapper for LefReadGeometry, which adds a label + * to the last rectangle generated by the geometry + * parsing. + * + * Results: + * None. + * + * Side Effects: + * Reads input from file f; + * Paints into the CellDef lefMacro. + * + *------------------------------------------------------------ + */ + +void +LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale) + CellDef *lefMacro; + FILE *f; + char *pinName; + int pinNum, pinDir, pinUse; + float oscale; +{ + Label *newlab; + LinkedRect *rectList; + + rectList = LefReadGeometry(lefMacro, f, oscale, TRUE); + + while (rectList != NULL) + { + if (pinNum >= 0) + { + /* Label this area */ + DBPutLabel(lefMacro, &rectList->r_r, -1, pinName, rectList->r_type, 0); + + /* Set this label to be a port */ + + if (lefMacro->cd_labels == NULL) + LefError("Internal error: No labels in cell!\n"); + else + { + newlab = lefMacro->cd_lastLabel; + if (strcmp(newlab->lab_text, pinName)) + LefError("Internal error: Can't find the label!\n"); + else /* Make this a port */ + newlab->lab_flags = pinNum | pinUse | pinDir | PORT_DIR_MASK; + } + /* DBAdjustLabels(lefMacro, &rectList->area); */ + } + + freeMagic((char *)rectList); + rectList = rectList->r_next; + } +} + +/* + *------------------------------------------------------------ + * LefReadPin -- + * + * Read a PIN statement from a LEF file. + * + * Results: + * None. + * + * Side Effects: + * Reads input from file f; + * Paints into the CellDef lefMacro. + * + *------------------------------------------------------------ + */ + +enum lef_pin_keys {LEF_DIRECTION = 0, LEF_USE, LEF_PORT, LEF_CAPACITANCE, + LEF_PIN_END}; + +void +LefReadPin(lefMacro, f, pinname, pinNum, oscale) + CellDef *lefMacro; + FILE *f; + char *pinname; + int pinNum; + float oscale; +{ + char *token; + int keyword, subkey; + int pinDir = PORT_CLASS_DEFAULT; + int pinUse = PORT_USE_DEFAULT; + + static char *pin_keys[] = { + "DIRECTION", + "USE", + "PORT", + "CAPACITANCE", + "END", + NULL + }; + + static char *pin_classes[] = { + "DEFAULT", + "INPUT", + "OUTPUT", + "OUTPUT TRISTATE", + "INOUT", + "FEEDTHRU", + NULL + }; + + static int lef_class_to_bitmask[] = { + PORT_CLASS_DEFAULT, + PORT_CLASS_INPUT, + PORT_CLASS_OUTPUT, + PORT_CLASS_TRISTATE, + PORT_CLASS_BIDIRECTIONAL, + PORT_CLASS_FEEDTHROUGH + }; + + static char *pin_uses[] = { + "DEFAULT", + "SIGNAL", + "ANALOG", + "POWER", + "GROUND", + "CLOCK", + NULL + }; + + static int lef_use_to_bitmask[] = { + PORT_USE_DEFAULT, + PORT_USE_SIGNAL, + PORT_USE_ANALOG, + PORT_USE_POWER, + PORT_USE_GROUND, + PORT_USE_CLOCK + }; + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + keyword = Lookup(token, pin_keys); + if (keyword < 0) + { + LefError("Unknown keyword \"%s\" in LEF file; ignoring.\n", token); + LefEndStatement(f); + continue; + } + switch (keyword) + { + case LEF_DIRECTION: + token = LefNextToken(f, TRUE); + subkey = Lookup(token, pin_classes); + if (subkey < 0) + LefError("Improper DIRECTION statement\n"); + else + pinDir = lef_class_to_bitmask[subkey]; + LefEndStatement(f); + break; + case LEF_USE: + token = LefNextToken(f, TRUE); + subkey = Lookup(token, pin_uses); + if (subkey < 0) + LefError("Improper USE statement\n"); + else + pinUse = lef_use_to_bitmask[subkey]; + LefEndStatement(f); + break; + case LEF_PORT: + LefReadPort(lefMacro, f, pinname, pinNum, pinDir, pinUse, oscale); + break; + case LEF_CAPACITANCE: + LefEndStatement(f); /* Ignore. . . */ + break; + case LEF_PIN_END: + if (LefParseEndStatement(f, pinname) == 0) + { + LefError("Pin END statement missing.\n"); + keyword = -1; + } + break; + } + if (keyword == LEF_PIN_END) break; + } +} + +/* + *------------------------------------------------------------ + * LefEndStatement -- + * + * Read file input to EOF or a ';' token (end-of-statement) + * + *------------------------------------------------------------ + */ + +void +LefEndStatement(f) + FILE *f; +{ + char *token; + + while ((token = LefNextToken(f, TRUE)) != NULL) + if (*token == ';') break; +} + +/* + *------------------------------------------------------------ + * + * LefReadMacro -- + * + * Read in a MACRO section from a LEF file. + * + * Results: + * None. + * + * Side Effects: + * Creates a new cell definition in the magic database. + * + *------------------------------------------------------------ + */ + +enum lef_macro_keys {LEF_CLASS = 0, LEF_SIZE, LEF_ORIGIN, + LEF_SYMMETRY, LEF_SOURCE, LEF_SITE, LEF_PIN, LEF_OBS, + LEF_TIMING, LEF_FOREIGN, LEF_MACRO_END}; + +void +LefReadMacro(f, mname, oscale, importForeign) + FILE *f; /* LEF file being read */ + char *mname; /* name of the macro */ + float oscale; /* scale factor um->magic units */ + bool importForeign; /* Whether we should try to read + * in a cell. + */ +{ + CellDef *lefMacro; + HashEntry *he; + + char *token, tsave[128]; + int keyword, pinNum; + float x, y; + bool has_size, is_imported = FALSE; + Rect lefBBox; + + static char *macro_keys[] = { + "CLASS", + "SIZE", + "ORIGIN", + "SYMMETRY", + "SOURCE", + "SITE", + "PIN", + "OBS", + "TIMING", + "FOREIGN", + "END", + NULL + }; + + /* Start by creating a new celldef */ + + he = HashFind(&lefDefInitHash, mname); + if (HashGetValue(he)) + { + int suffix; + char newname[256]; + + for (suffix = 1; HashGetValue(he) != NULL; suffix++) + { + sprintf(newname, "%250s_%d", mname, suffix); + he = HashFind(&lefDefInitHash, newname); + } + LefError("Cell \"%s\" was already defined in this file. " + "Renaming this cell \"%s\"\n", mname, newname); + lefMacro = DBCellLookDef(newname); + if (lefMacro == NULL) + { + lefMacro = lefFindCell(newname); + DBCellClearDef(lefMacro); + DBCellSetAvail(lefMacro); + HashSetValue(he, lefMacro); + is_imported = FALSE; + } + else + is_imported = TRUE; + } + else + { + lefMacro = DBCellLookDef(mname); + if (lefMacro == NULL) + { + lefMacro = lefFindCell(mname); + DBCellClearDef(lefMacro); + DBCellSetAvail(lefMacro); + HashSetValue(he, lefMacro); + is_imported = FALSE; + } + else + is_imported = TRUE; + } + + /* Initial values */ + pinNum = 1; + has_size = FALSE; + lefBBox.r_xbot = 0; + lefBBox.r_ybot = 0; + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + keyword = Lookup(token, macro_keys); + if (keyword < 0) + { + LefError("Unknown keyword \"%s\" in LEF file; ignoring.\n", token); + LefEndStatement(f); + continue; + } + switch (keyword) + { + case LEF_CLASS: + token = LefNextToken(f, TRUE); + if (*token != '\n') + DBPropPut(lefMacro, "LEFclass", StrDup((char **)NULL, token)); + LefEndStatement(f); + break; + case LEF_SIZE: + token = LefNextToken(f, TRUE); + if (!token || sscanf(token, "%f", &x) != 1) goto size_error; + token = LefNextToken(f, TRUE); /* skip keyword "BY" */ + if (!token) goto size_error; + token = LefNextToken(f, TRUE); + if (!token || sscanf(token, "%f", &y) != 1) goto size_error; + + lefBBox.r_xtop = (int)roundf(x / oscale) + lefBBox.r_xbot; + lefBBox.r_ytop = (int)roundf(y / oscale) + lefBBox.r_ybot; + has_size = TRUE; + LefEndStatement(f); + break; +size_error: + LefError("Bad macro SIZE; requires values X BY Y.\n"); + LefEndStatement(f); + break; + case LEF_ORIGIN: + token = LefNextToken(f, TRUE); + if (!token || sscanf(token, "%f", &x) != 1) goto origin_error; + token = LefNextToken(f, TRUE); + if (!token || sscanf(token, "%f", &y) != 1) goto origin_error; + + lefBBox.r_xbot = -(int)roundf(x / oscale); + lefBBox.r_ybot = -(int)roundf(y / oscale); + if (has_size) + { + lefBBox.r_xtop += lefBBox.r_xbot; + lefBBox.r_ytop += lefBBox.r_ybot; + } + LefEndStatement(f); + break; +origin_error: + LefError("Bad macro ORIGIN; requires 2 values.\n"); + LefEndStatement(f); + break; + case LEF_SYMMETRY: + strcpy(tsave, ""); + token = LefNextToken(f, TRUE); + while (*token != ';') + { + sprintf(tsave + strlen(tsave), " %s", token); + token = LefNextToken(f, TRUE); + } + DBPropPut(lefMacro, "LEFsymmetry", StrDup((char **)NULL, tsave + 1)); + break; + case LEF_SOURCE: + token = LefNextToken(f, TRUE); + if (*token != '\n') + DBPropPut(lefMacro, "LEFsource", StrDup((char **)NULL, token)); + LefEndStatement(f); + break; + case LEF_SITE: + token = LefNextToken(f, TRUE); + if (*token != '\n') + DBPropPut(lefMacro, "LEFsite", StrDup((char **)NULL, token)); + LefEndStatement(f); + break; + case LEF_PIN: + token = LefNextToken(f, TRUE); + /* Diagnostic */ + /* + TxPrintf(" Macro defines pin %s\n", token); + */ + sprintf(tsave, "%.127s", token); + if (is_imported) + LefSkipSection(f, tsave); + else + LefReadPin(lefMacro, f, tsave, pinNum++, oscale); + break; + case LEF_OBS: + /* Diagnostic */ + /* + TxPrintf(" Macro defines obstruction\n"); + */ + if (is_imported) + LefSkipSection(f, NULL); + else + LefReadGeometry(lefMacro, f, oscale, FALSE); + break; + case LEF_TIMING: + LefSkipSection(f, macro_keys[LEF_TIMING]); + break; + case LEF_FOREIGN: + if (importForeign) + { + token = LefNextToken(f, TRUE); + sprintf(tsave, "%.127s", token); + + /* To do: Read and apply X and Y offsets */ + } + LefEndStatement(f); + break; + case LEF_MACRO_END: + if (LefParseEndStatement(f, mname) == 0) + { + LefError("Macro END statement missing.\n"); + keyword = -1; + } + break; + } + if (keyword == LEF_MACRO_END) break; + } + + /* Finish up creating the cell */ + + if (is_imported) + { + /* Redefine cell bounding box to match the LEF macro */ + /* Leave "extended" to mark the original bounding box */ + + if (has_size) + { + lefMacro->cd_bbox = lefBBox; + lefMacro->cd_flags |= CDFIXEDBBOX; + } + } + else + { + DBAdjustLabelsNew(lefMacro, &TiPlaneRect, 1); + + if (!has_size) + { + LefError(" Macro does not define size: computing from geometry\n"); + DBReComputeBbox(lefMacro); + } + else + { + char *propstr = (char *)mallocMagic(64); + int reducer = DBCellFindScale(lefMacro); + + lefMacro->cd_bbox = lefBBox; + lefMacro->cd_extended = lefBBox; + } + + /* Fix the bounding box and do not allow edits */ + lefMacro->cd_flags |= /* CDNOEDIT | */ CDFIXEDBBOX; + + DRCCheckThis(lefMacro, TT_CHECKPAINT, &lefMacro->cd_bbox); + } + DBWAreaChanged(lefMacro, &lefMacro->cd_bbox, DBW_ALLWINDOWS, + &DBAllButSpaceBits); +} + +/* + *------------------------------------------------------------ + * + * LefAddViaGeometry -- + * + * Read in geometry for a VIA section from a LEF or DEF + * file. + * + * Results: + * None. + * + * Side Effects: + * Adds to the lefLayer record for a via definition. + * + *------------------------------------------------------------ + */ + +void +LefAddViaGeometry(f, lefl, curlayer, oscale) + FILE *f; /* LEF file being read */ + lefLayer *lefl; /* pointer to via info */ + TileType curlayer; /* current tile type */ + float oscale; /* output scaling */ +{ + Rect *currect; + LinkedRect *viaLR; + + /* Rectangles for vias are read in units of 1/2 lambda */ + currect = LefReadRect(f, curlayer, (oscale / 2)); + if (currect == NULL) return; + + /* Don't create any geometry for unknown layers! */ + if (curlayer < 0) return; + + /* For LEF contact types matching magic contact types, */ + /* size the LEF contact cut to cover the minimum */ + /* rectangle in the other layers that satisfies the */ + /* CIF/GDS contact generation. */ + + if (DBIsContact(curlayer) && CIFCurStyle != NULL) + { + int edgeSize = 0, contSize, halfSize; + float fcontSize; + + /* Get the minimum size of a contact (cut + borders) from cifoutput */ + contSize = CIFGetContactSize(curlayer, &edgeSize, NULL, NULL); + + /* All internal LEF via geometry values are doubled */ + contSize <<= 1; + edgeSize <<= 1; + + if (contSize % CIFCurStyle->cs_scaleFactor == 0) + contSize /= CIFCurStyle->cs_scaleFactor; + else + contSize = contSize / CIFCurStyle->cs_scaleFactor + 1; + + if (edgeSize % CIFCurStyle->cs_scaleFactor == 0) + edgeSize /= CIFCurStyle->cs_scaleFactor; + else + edgeSize = edgeSize / CIFCurStyle->cs_scaleFactor + 1; + + if (edgeSize > 0 && contSize > 0) + { + /* Flag a warning if the cut size is different from what's expected */ + if ((currect->r_xtop - currect->r_xbot != edgeSize) || + (currect->r_ytop - currect->r_ybot != edgeSize)) + { + LefError("Warning: Cut size for magic type \"%s\" (%d x %d) does " + "not match LEF/DEF\n", + DBTypeLongNameTbl[lefl->type], + edgeSize, edgeSize); + LefError(" via cut size (%d x %d). Magic layer cut size will " + "be used!\n", + currect->r_xtop - currect->r_xbot, + currect->r_ytop - currect->r_ybot); + } + + halfSize = contSize >> 1; + currect->r_xbot = ((currect->r_xbot + currect->r_xtop) / 2) - halfSize; + currect->r_ybot = ((currect->r_ybot + currect->r_ytop) / 2) - halfSize; + currect->r_xtop = currect->r_xbot + contSize; + currect->r_ytop = currect->r_ybot + contSize; + } + } + + if (GEO_SAMERECT(lefl->info.via.area, GeoNullRect)) + { + lefl->info.via.area = *currect; + lefl->type = curlayer; + } + else + { + viaLR = (LinkedRect *)mallocMagic(sizeof(LinkedRect)); + viaLR->r_next = lefl->info.via.lr; + lefl->info.via.lr = viaLR; + viaLR->r_type = curlayer; + viaLR->r_r = *currect; + + /* Make sure that the primary record is a contact type. */ + if (DBIsContact(curlayer) && !DBIsContact(lefl->type)) + { + viaLR->r_type = lefl->type; + lefl->type = curlayer; + viaLR->r_r = lefl->info.via.area; + lefl->info.via.area = *currect; + } + } +} + +/* + *------------------------------------------------------------ + * + * LefReadLayerSection -- + * + * Read in a LAYER, VIA, or VIARULE section from a LEF file. + * + * Results: + * None. + * + * Side Effects: + * Adds to the LEF layer info hash table. + * + *------------------------------------------------------------ + */ + +enum lef_layer_keys {LEF_LAYER_TYPE=0, LEF_LAYER_WIDTH, LEF_LAYER_SPACING, + LEF_LAYER_PITCH, LEF_LAYER_DIRECTION, LEF_LAYER_OFFSET, + LEF_VIA_DEFAULT, LEF_VIA_LAYER, LEF_VIA_RECT, + LEF_VIARULE_VIA, LEF_LAYER_END}; + +void +LefReadLayerSection(f, lname, mode, lefl) + FILE *f; /* LEF file being read */ + char *lname; /* name of the layer */ + int mode; /* layer, via, or viarule */ + lefLayer *lefl; /* pointer to layer info */ +{ + char *token; + int keyword, typekey; + Rect viaArea; + TileType curlayer = -1; + float fvalue, oscale; + + /* These are defined in the order of CLASS_* in lefInt.h */ + static char *layer_type_keys[] = { + "ROUTING", + "CUT", + "MASTERSLICE", + "OVERLAP", + NULL + }; + + static char *layer_keys[] = { + "TYPE", + "WIDTH", + "SPACING", + "PITCH", + "DIRECTION", + "OFFSET", + "DEFAULT", + "LAYER", + "RECT", + "VIA", + "END", + NULL + }; + + oscale = CIFGetOutputScale(1000); + viaArea = GeoNullRect; + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + keyword = Lookup(token, layer_keys); + if (keyword < 0) + { + LefError("Unknown keyword \"%s\" in LEF file; ignoring.\n", token); + LefEndStatement(f); + continue; + } + switch (keyword) + { + case LEF_LAYER_TYPE: + token = LefNextToken(f, TRUE); + if (*token != '\n') + { + typekey = Lookup(token, layer_type_keys); + if (typekey < 0) + LefError("Unknown layer type \"%s\" in LEF file; " + "ignoring.\n", token); + } + if (lefl->lefClass != typekey) + LefError("Attempt to reclassify layer %s from %s to %s\n", + lname, layer_type_keys[lefl->lefClass], + layer_type_keys[typekey]); + LefEndStatement(f); + break; + case LEF_LAYER_WIDTH: + token = LefNextToken(f, TRUE); + sscanf(token, "%f", &fvalue); + if (lefl->lefClass == CLASS_ROUTE) + lefl->info.route.width = (int)roundf(fvalue / oscale); + LefEndStatement(f); + break; + case LEF_LAYER_SPACING: + token = LefNextToken(f, TRUE); + sscanf(token, "%f", &fvalue); + if (lefl->lefClass == CLASS_ROUTE) + lefl->info.route.spacing = (int)roundf(fvalue / oscale); + LefEndStatement(f); + break; + case LEF_LAYER_PITCH: + token = LefNextToken(f, TRUE); + sscanf(token, "%f", &fvalue); + if (lefl->lefClass == CLASS_ROUTE) + lefl->info.route.pitch = (int)roundf(fvalue / oscale); + LefEndStatement(f); + break; + case LEF_LAYER_DIRECTION: + token = LefNextToken(f, TRUE); + LefLower(token); + if (lefl->lefClass == CLASS_ROUTE) + lefl->info.route.hdirection = (token[0] == 'h') ? TRUE : FALSE; + LefEndStatement(f); + break; + case LEF_LAYER_OFFSET: + LefEndStatement(f); + break; + case LEF_VIA_DEFAULT: + /* Do nothing; especially, don't look for end-of-statement! */ + break; + case LEF_VIA_LAYER: + curlayer = LefReadLayer(f, FALSE); + LefEndStatement(f); + break; + case LEF_VIA_RECT: + LefAddViaGeometry(f, lefl, curlayer, oscale); + LefEndStatement(f); + break; + case LEF_VIARULE_VIA: + LefEndStatement(f); + break; + case LEF_LAYER_END: + if (LefParseEndStatement(f, lname) == 0) + { + LefError("Layer END statement missing.\n"); + keyword = -1; + } + break; + } + if (keyword == LEF_LAYER_END) break; + } +} + +/* + *------------------------------------------------------------ + * + * LefRead -- + * + * Read a .lef file into a magic layout. + * + * Results: + * None. + * + * Side Effects: + * Many. Cell definitions and uses are created and added to + * the database. + * + *------------------------------------------------------------ + */ + +enum lef_sections {LEF_VERSION = 0, LEF_NAMESCASESENSITIVE, + LEF_PROPERTYDEFS, LEF_UNITS, LEF_SECTION_LAYER, + LEF_SECTION_VIA, LEF_SECTION_VIARULE, + LEF_SECTION_SPACING, LEF_SECTION_SITE, LEF_PROPERTY, + LEF_NOISETABLE, LEF_CORRECTIONTABLE, LEF_IRDROP, + LEF_ARRAY, LEF_SECTION_TIMING, LEF_EXTENSION, LEF_MACRO, + LEF_END}; + +void +LefRead(inName, importForeign) + char *inName; + bool importForeign; +{ + FILE *f; + char *filename; + char *token; + char tsave[128]; + int keyword; + float oscale; + HashEntry *he; + lefLayer *lefl; + + static char *sections[] = { + "VERSION", + "NAMESCASESENSITIVE", + "PROPERTYDEFINITIONS", + "UNITS", + "LAYER", + "VIA", + "VIARULE", + "SPACING", + "SITE", + "PROPERTY", + "NOISETABLE", + "CORRECTIONTABLE", + "IRDROP", + "ARRAY", + "TIMING", + "BEGINEXT", + "MACRO", + "END", + NULL + }; + + /* Make sure we have a valid LefInfo hash table, even if it's empty */ + if (LefInfo.ht_table == (HashEntry **) NULL) + LefTechInit(); + + f = lefFileOpen(NULL, inName, ".lef", "r", &filename); + + if (f == NULL) + { +#ifdef MAGIC_WRAPPER + TxError("Cannot open input file %s (%s).\n", filename, + strerror(errno)); +#else + TxError("Cannot open input file: "); + perror(filename); +#endif + return; + } + + TxPrintf("Reading LEF data from file %s.\n", filename); + TxPrintf("This action cannot be undone.\n"); + UndoDisable(); + + /* Initialize */ + HashInit(&LefCellTable, 32, HT_STRINGKEYS); + HashInit(&lefDefInitHash, 32, HT_STRINGKEYS); + oscale = CIFGetOutputScale(1000); + + while ((token = LefNextToken(f, TRUE)) != NULL) + { + keyword = Lookup(token, sections); + if (keyword < 0) + { + LefError("Unknown keyword \"%s\" in LEF file; ignoring.\n", token); + LefEndStatement(f); + continue; + } + switch (keyword) + { + case LEF_VERSION: + LefEndStatement(f); + break; + case LEF_NAMESCASESENSITIVE: + LefEndStatement(f); + break; + case LEF_PROPERTYDEFS: + LefSkipSection(f, sections[LEF_PROPERTYDEFS]); + break; + case LEF_UNITS: + LefSkipSection(f, sections[LEF_UNITS]); + break; + + case LEF_SECTION_VIA: + case LEF_SECTION_VIARULE: + token = LefNextToken(f, TRUE); + sprintf(tsave, "%.127s", token); + he = HashFind(&LefInfo, token); + lefl = (lefLayer *)HashGetValue(he); + if (lefl == NULL) + { + lefl = (lefLayer *)mallocMagic(sizeof(lefLayer)); + lefl->type = -1; + lefl->obsType = -1; + lefl->refCnt = 1; + lefl->lefClass = CLASS_VIA; + lefl->info.via.area = GeoNullRect; + lefl->info.via.cell = (CellDef *)NULL; + lefl->info.via.lr = (LinkedRect *)NULL; + HashSetValue(he, lefl); + LefReadLayerSection(f, tsave, keyword, lefl); + lefl->canonName = (char *)he->h_key.h_name; + } + else if (keyword == LEF_SECTION_VIARULE) + /* If we've already seen this via, don't reprocess. */ + /* This deals with VIA followed by VIARULE. We */ + /* really ought to have special processing for the */ + /* VIARULE section. . . */ + LefSkipSection(f, tsave); + else + { + LefError("Warning: Cut type \"%s\" redefined.\n", token); + lefl = LefRedefined(lefl, token); + LefReadLayerSection(f, tsave, keyword, lefl); + } + break; + + case LEF_SECTION_LAYER: + token = LefNextToken(f, TRUE); + sprintf(tsave, "%.127s", token); + he = HashLookOnly(&LefInfo, token); + if (he == NULL) + { + TileType mtype = DBTechNameType(token); + if (mtype < 0) + mtype = DBTechNameType(LefLower(token)); + if (mtype < 0) + { + LefError("Layer %s cannot be mapped to any magic layer!\n", + token); + LefSkipSection(f, tsave); + break; + } + else if (DBIsContact(mtype) && (keyword == LEF_SECTION_LAYER)) + { + LefError("Layer %s maps to a magic contact layer; " + "must be defined in lef section of techfile\n", + token); + LefSkipSection(f, tsave); + break; + } + else if (!DBIsContact(mtype) && (keyword != LEF_SECTION_LAYER)) + { + LefError("Via %s maps to a non-contact magic layer; " + "must be defined in lef section of techfile\n", + token); + LefSkipSection(f, tsave); + break; + } + else + { + he = HashFind(&LefInfo, token); + lefl = (lefLayer *)mallocMagic(sizeof(lefLayer)); + lefl->type = mtype; + lefl->obsType = -1; + lefl->refCnt = 1; + lefl->lefClass = (DBIsContact(mtype)) ? CLASS_VIA : CLASS_ROUTE; + HashSetValue(he, lefl); + lefl->canonName = (char *)he->h_key.h_name; + } + } + else + { + lefl = (lefLayer *)HashGetValue(he); + if (lefl && lefl->type < 0) + { + LefError("Layer %s is only defined for obstructions!\n", token); + LefSkipSection(f, tsave); + break; + } + } + LefReadLayerSection(f, tsave, keyword, lefl); + break; + + case LEF_SECTION_SPACING: + LefSkipSection(f, sections[LEF_SECTION_SPACING]); + break; + case LEF_SECTION_SITE: + token = LefNextToken(f, TRUE); + TxPrintf("LEF file: Defines site %s (ignored)\n", token); + sprintf(tsave, "%.127s", token); + LefSkipSection(f, tsave); + break; + case LEF_PROPERTY: + LefSkipSection(f, NULL); + break; + case LEF_NOISETABLE: + LefSkipSection(f, sections[LEF_NOISETABLE]); + break; + case LEF_CORRECTIONTABLE: + LefSkipSection(f, sections[LEF_CORRECTIONTABLE]); + break; + case LEF_IRDROP: + LefSkipSection(f, sections[LEF_IRDROP]); + break; + case LEF_ARRAY: + LefSkipSection(f, sections[LEF_ARRAY]); + break; + case LEF_SECTION_TIMING: + LefSkipSection(f, sections[LEF_SECTION_TIMING]); + break; + case LEF_EXTENSION: + LefSkipSection(f, sections[LEF_EXTENSION]); + break; + case LEF_MACRO: + token = LefNextToken(f, TRUE); + /* Diagnostic */ + /* + TxPrintf("LEF file: Defines new cell %s\n", token); + */ + sprintf(tsave, "%.127s", token); + LefReadMacro(f, tsave, oscale, importForeign); + break; + case LEF_END: + if (LefParseEndStatement(f, "LIBRARY") == 0) + { + LefError("END statement out of context.\n"); + keyword = -1; + } + break; + } + if (keyword == LEF_END) break; + } + TxPrintf("LEF read: Processed %d lines.\n", lefCurrentLine); + LefError(NULL); /* print statement of errors, if any */ + + /* Cleanup */ + HashKill(&LefCellTable); + HashKill(&lefDefInitHash); + if (f != NULL) fclose(f); + UndoEnable(); +} diff --git a/lef/lefTech.c b/lef/lefTech.c new file mode 100644 index 00000000..007ad0db --- /dev/null +++ b/lef/lefTech.c @@ -0,0 +1,448 @@ +/* + * lefTech.c -- + * + * This module incorporates the LEF/DEF format for standard-cell place and + * route. Defines technology file layer mapping between LEF and magic layer + * types. + * + * Version 0.1 (December 5, 2003): LEF section of the technology file. + * Lets the technology file state how layers declared in the LEF and DEF + * files should correspond to magic layout units. If these are not + * declared, magic will attempt to relate layer names in the LEF file to + * magic layer names and their aliases. The LEF section allows the declaration + * of obstruction layer names, which may be the same as actual layer names in + * the LEF or DEF file, but which should declare a type that takes up space + * on the routing plane but does not connect to any other material. Otherwise, + * some LEF/DEF files will end up merging ports together with the obstruction + * layer. + * + * Layer name case sensitivity should depend on the + * NAMESCASESENSITIVE [ON|OFF] LEF instruction! + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/lef/lefTech.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "lef/lefInt.h" +#include "drc/drc.h" + +/* ---------------------------------------------------------------------*/ + +/* Layer and Via routing information table. */ + +HashTable LefInfo; + +/* + *----------------------------------------------------------------------------- + * LefInit -- + * + * Things that need to be initialized on startup, before the technology + * file is read in. + * + * Results: + * None. + * + * Side effects: + * Hash Table initialization. + * + *----------------------------------------------------------------------------- + */ + +void +LefInit() +{ + /* Ensure that the table has a null entry so we don't run HashKill */ + /* on it when we to the tech initialization. */ + + LefInfo.ht_table = (HashEntry **) NULL; +} + +/* + *----------------------------------------------------------------------------- + * LefTechInit -- + * + * Called once at beginning of technology file read-in to initialize + * data structures. + * + * Results: + * None. + * + * Side effects: + * Clears out the LEF layer info table. Because multiple LEF names + * can point to the same record, this is handled by reference count. + * ---------------------------------------------------------------------------- + */ + +void +LefTechInit() +{ + HashSearch hs; + HashEntry *he; + lefLayer *lefl; + + if (LefInfo.ht_table != (HashEntry **) NULL) + { + HashStartSearch(&hs); + while (he = HashNext(&LefInfo, &hs)) + { + lefl = (lefLayer *)HashGetValue(he); + if (!lefl) continue; + lefl->refCnt--; + if (lefl->refCnt <= 0) + { + /* Via detailed information, if it exists, */ + /* needs to have its allocated memory free'd. */ + + if (lefl->lefClass == CLASS_VIA) + if (lefl->info.via.lr != NULL) + freeMagic(lefl->info.via.lr); + + freeMagic(lefl); + } + } + HashKill(&LefInfo); + } + HashInit(&LefInfo, 32, HT_STRINGKEYS); +} + +/* + *----------------------------------------------------------------------------- + * lefRemoveGeneratedVias -- + * + * Remove the Generated Vias created during a DEF file write + * from the LEF layer hash table. By design, each of these + * generated layers gets a refCnt of zero, so they are easy + * to find. + * + * Results: + * None. + * + * Side effects: + * Memory freed in the hash table. + * + *----------------------------------------------------------------------------- + */ + +void +lefRemoveGeneratedVias() +{ + HashSearch hs; + HashEntry *he; + lefLayer *lefl; + + if (LefInfo.ht_table != (HashEntry **) NULL) + { + HashStartSearch(&hs); + while (he = HashNext(&LefInfo, &hs)) + { + lefl = (lefLayer *)HashGetValue(he); + if (!lefl) continue; + if (lefl->refCnt == 0) + { + if (lefl->lefClass == CLASS_VIA) + if (lefl->info.via.lr != NULL) + freeMagic(lefl->info.via.lr); + + freeMagic(lefl); + HashSetValue(he, NULL); + } + } + } +} + +/* + *----------------------------------------------------------------------------- + * LefTechLine -- + * + * This procedure is invoked by the technology module once for + * each line in the "lef" section of the technology file. + * + * Results: + * Always returns TRUE (otherwise the technology module would + * abort Magic with a fatal error). + * + * Side effects: + * Builds up the LEF layer table, prints error messages if necessary. + * ---------------------------------------------------------------------------- + */ + +#define LEFTECH_OBS 0 +#define LEFTECH_LAYER 1 +#define LEFTECH_ROUTE 2 +#define LEFTECH_ROUTING 3 +#define LEFTECH_MASTER 4 +#define LEFTECH_CUT 5 +#define LEFTECH_CONTACT 6 +#define LEFTECH_OVERLAP 7 +#define LEFTECH_BOUND 8 +#define LEFTECH_IGNORE 9 + +bool +LefTechLine(sectionName, argc, argv) + char *sectionName; /* Name of this section (unused). */ + int argc; /* Number of arguments on line. */ + char *argv[]; /* Pointers to fields of line. */ +{ + bool isObstruction, isContact, isInactive; + HashEntry *he; + TileType mtype, mtype2 = -1; + TileTypeBitMask mmask; + lefLayer *lefl, *newlefl; + int i, option; + static char *keywords[] = { + "obstruction", "layer", "route", "routing", "masterslice", + "cut", "contact", "overlap", "bound", "ignore", NULL + }; + + option = Lookup(argv[0], keywords); + if (option < 0) + { + TechError("Unknown LEF section keyword: %s. Line ignored.\n", argv[0]); + return TRUE; + } + + if ((option != LEFTECH_IGNORE) && (argc < 3)) + { + TechError("No LEF layer names present!\n"); + return TRUE; + } + + isInactive = FALSE; + switch (option) + { + case LEFTECH_IGNORE: + isInactive = TRUE; + break; + case LEFTECH_OBS: + isObstruction = TRUE; + break; + default: + isObstruction = FALSE; + } + + TTMaskZero(&mmask); + i = 0; + + if (!isInactive) + { + DBTechNoisyNameMask(argv[1], &mmask); + for (mtype2 = TT_TECHDEPBASE; mtype2 < DBNumUserLayers; mtype2++) + { + if (TTMaskHasType(&mmask, mtype2)) + { + if (++i == 1) + mtype = mtype2; + else + break; + } + } + if (mtype2 == DBNumUserLayers) mtype2 = -1; + + if (i == 0) + { + LefError("Bad magic layer type \"%s\" in LEF layer definition.\n", argv[1]); + return TRUE; + } + else if ((i == 2) && (option != LEFTECH_OBS)) + { + LefError("Can only define multiple types for via obstruction layers.\n"); + return TRUE; + } + else if (i > 2) + { + LefError("Too many types in LEF layer definition.\n"); + return TRUE; + } + + isContact = DBIsContact(mtype); + if (option == LEFTECH_LAYER) + option = (isContact) ? LEFTECH_CUT : LEFTECH_ROUTE; + else if (isContact && (option != LEFTECH_CUT && option != LEFTECH_CONTACT)) + TechError("Attempt to define cut type %s as %s.\n", + DBTypeLongNameTbl[mtype], keywords[option]); + else if (!isContact && (option == LEFTECH_CUT || option == LEFTECH_CONTACT)) + TechError("Attempt to define non-cut type %s as a cut.\n", + DBTypeLongNameTbl[mtype]); + } + + /* All other aliases are stuffed in the hash table but point to the */ + /* same record as the first. If any name is repeated, then report */ + /* an error condition. */ + + newlefl = NULL; + for (i = 2 - isInactive; i < argc; i++) + { + he = HashFind(&LefInfo, argv[i]); + lefl = (lefLayer *)HashGetValue(he); + if (lefl == NULL) + { + /* Create an entry in the hash table for this layer or obstruction */ + + if (newlefl == NULL) + { + float oscale = CIFGetOutputScale(1000); + + newlefl = (lefLayer *)mallocMagic(sizeof(lefLayer)); + newlefl->refCnt = 0; + newlefl->type = -1; + newlefl->obsType = -1; + if (!isInactive) + { + if (isObstruction) + newlefl->obsType = mtype; + else + newlefl->type = mtype; + } + newlefl->canonName = (char *)he->h_key.h_name; + + /* Fill in default values per type */ + + switch (option) + { + case LEFTECH_CUT: + newlefl->lefClass = CLASS_VIA; + newlefl->info.via.area = GeoNullRect; + newlefl->info.via.cell = (CellDef *)NULL; + newlefl->info.via.lr = (LinkedRect *)NULL; + newlefl->info.via.obsType = mtype2; + break; + case LEFTECH_CONTACT: + newlefl->lefClass = CLASS_VIA; + newlefl->info.via.area.r_xtop = DRCGetDefaultLayerWidth(mtype); + newlefl->info.via.area.r_ytop = newlefl->info.via.area.r_xtop; + newlefl->info.via.area.r_xbot = -newlefl->info.via.area.r_xtop; + newlefl->info.via.area.r_ybot = -newlefl->info.via.area.r_ytop; + newlefl->info.via.cell = (CellDef *)NULL; + newlefl->info.via.lr = (LinkedRect *)NULL; + newlefl->info.via.obsType = mtype2; + break; + case LEFTECH_ROUTE: + case LEFTECH_ROUTING: + case LEFTECH_OBS: + newlefl->lefClass = CLASS_ROUTE; + newlefl->info.route.width = DRCGetDefaultLayerWidth(mtype); + if (newlefl->info.route.width == 0) + newlefl->info.route.width = DEFAULT_WIDTH; + newlefl->info.route.spacing = + DRCGetDefaultLayerSpacing(mtype, mtype); + if (newlefl->info.route.spacing == 0) + newlefl->info.route.spacing = DEFAULT_SPACING; + newlefl->info.route.pitch = 0; + newlefl->info.route.hdirection = TRUE; + break; + case LEFTECH_BOUND: + newlefl->lefClass = CLASS_BOUND; + break; + case LEFTECH_MASTER: + newlefl->lefClass = CLASS_MASTER; + break; + case LEFTECH_OVERLAP: + newlefl->lefClass = CLASS_OVERLAP; + break; + case LEFTECH_IGNORE: + newlefl->lefClass = CLASS_IGNORE; + break; + } + + } + HashSetValue(he, newlefl); + newlefl->refCnt++; + } + else if (lefl->lefClass != CLASS_IGNORE) + { + if ((lefl->obsType == -1) && isObstruction) + { +// if (DBIsContact(lefl->type) != isContact) +// TechError("Error: Cannot mix layer and via types\n"); +// else + { + lefl->obsType = mtype; + if (lefl->lefClass == CLASS_VIA) + lefl->info.via.obsType = mtype2; + } + } + else if ((lefl->type == -1) && !isObstruction) + { +// if (DBIsContact(lefl->obsType) != isContact) +// TechError("Error: Cannot mix layer and via types\n"); +// else + lefl->type = mtype; + + } + else + TechError("LEF name %s already used for magic type %s\n", + argv[i], DBTypeLongNameTbl[lefl->type]); + } + } + return TRUE; +} + +/* + *----------------------------------------------------------------------------- + * LefTechScale -- + * + * Change parameters of the LEF section as required when + * redefining magic's internal grid relative to the technology lambda. + * + * ---------------------------------------------------------------------------- + */ + +void +LefTechScale(scalen, scaled) + int scalen, scaled; +{ + HashSearch hs; + HashEntry *he; + lefLayer *lefl; + + if (LefInfo.ht_table != (HashEntry **) NULL) + { + HashStartSearch(&hs); + while (he = HashNext(&LefInfo, &hs)) + { + lefl = (lefLayer *)HashGetValue(he); + if (!lefl) continue; + if (lefl->refCnt >= 1) + { + /* Avoid scaling more than once. . . */ + if (lefl->refCnt > 1) lefl->refCnt = -lefl->refCnt; + if (lefl->lefClass == CLASS_VIA) + { + DBScalePoint(&lefl->info.via.area.r_ll, scaled, scalen); + DBScalePoint(&lefl->info.via.area.r_ur, scaled, scalen); + } + else if (lefl->lefClass == CLASS_ROUTE) + { + lefl->info.route.width *= scaled; + lefl->info.route.width /= scalen; + lefl->info.route.spacing *= scaled; + lefl->info.route.spacing /= scalen; + lefl->info.route.pitch *= scaled; + lefl->info.route.pitch /= scalen; + } + } + } + + /* Return all refCnt values to normal */ + HashStartSearch(&hs); + while (he = HashNext(&LefInfo, &hs)) + { + lefl = (lefLayer *)HashGetValue(he); + if (!lefl) continue; + if (lefl->refCnt < 0) + lefl->refCnt = -lefl->refCnt; + } + } +} diff --git a/lef/lefWrite.c b/lef/lefWrite.c new file mode 100644 index 00000000..6f71897f --- /dev/null +++ b/lef/lefWrite.c @@ -0,0 +1,1062 @@ +/* + * lefWrite.c -- + * + * This module incorporates the LEF/DEF format for standard-cell place and + * route. + * + * Version 0.1 (May 1, 2003): LEF output for cells, to include pointer to + * GDS, automatic generation of GDS if not already made, bounding box export, + * port export, export of irouter "fence", "magnet", and "rotate" layers + * for defining router hints, and generating areas for obstructions and + * pin layers. + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/lef/lefWrite.c,v 1.3 2010/06/24 12:37:18 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/tech.h" +#include "utils/utils.h" +#include "utils/malloc.h" +#include "utils/stack.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "graphics/graphics.h" +#include "utils/main.h" +#include "utils/undo.h" +#include "cif/cif.h" +#include "lef/lefInt.h" + +/* ---------------------------------------------------------------------*/ + +/* Stack of cell definitions */ +Stack *lefDefStack; + +/* + * --------------------------------------------------------------------- + * + * lefFileOpen -- + * + * Open the .lef file corresponding to a .mag file. + * If def->cd_file is non-NULL, the .lef file is just def->cd_file with + * the trailing .mag replaced by .lef. Otherwise, the .lef file is just + * def->cd_name followed by .lef. + * + * Results: + * Return a pointer to an open FILE, or NULL if the .lef + * file could not be opened in the specified mode. + * + * Side effects: + * Opens a file. + * + * ---------------------------------------------------------------------------- + */ + +FILE * +lefFileOpen(def, file, suffix, mode, prealfile) + CellDef *def; /* Cell whose .lef file is to be written. Should + * be NULL if file is being opened for reading. + */ + char *file; /* If non-NULL, open 'name'.lef; otherwise, + * derive filename from 'def' as described + * above. + */ + char *suffix; /* Either ".lef" for LEF files or ".def" for DEF files */ + char *mode; /* Either "r" or "w", the mode in which the LEF/DEF + * file is to be opened. + */ + char **prealfile; /* If this is non-NULL, it gets set to point to + * a string holding the name of the LEF/DEF file. + */ +{ + char namebuf[512], *name, *endp, *ends; + int len; + FILE *rfile; + + if (file) + name = file; + else if (def && def->cd_file) + name = def->cd_file; + else if (def) + name = def->cd_name; + else + { + TxError("LEF file open: No file name or cell given\n"); + return NULL; + } + + // Strip off suffix, if there is one + + ends = strrchr(name, '/'); + if (ends == NULL) + ends = name; + else + ends++; + + if (endp = strrchr(ends, '.')) + { + if (!strcmp(endp, suffix)) + { + len = endp - name; + if (len > sizeof namebuf - 1) len = sizeof namebuf - 1; + (void) strncpy(namebuf, name, len); + namebuf[len] = '\0'; + name = namebuf; + } + } + + /* Try once as-is, and if this fails, try stripping any leading */ + /* path information in case cell is in a read-only directory (mode */ + /* "read" only, and if def is non-NULL). */ + + if ((rfile = PaOpen(name, mode, suffix, Path, CellLibPath, prealfile)) != NULL) + return rfile; + + if (def) + { + if (name == def->cd_name) return NULL; + name = def->cd_name; + return (PaOpen(name, mode, suffix, Path, CellLibPath, prealfile)); + } + else + return NULL; +} + + +/* + * ---------------------------------------------------------------------------- + * + * lefWriteHeader -- + * + * This routine generates LEF header output for a cell or cell hierarchy. + * Although the LEF/DEF spec does not define a "header" per se, this is + * considered to be all LEF output not including the MACRO calls. The + * header, therefore, defines layers, process routing rules, units + * (lambda), and so forth. + * + * Results: + * None. + * + * Side effects: + * Writes output to the open file "f". + * + * ---------------------------------------------------------------------------- + */ + +void +lefWriteHeader(def, f) + CellDef *def; /* Def for which to generate LEF output */ + FILE *f; /* Output to this file */ +{ + TileType type; + + UndoDisable(); + + TxPrintf("Diagnostic: Write LEF header for cell %s\n", def->cd_name); + + /* NOTE: This routine corresponds to Envisia LEF/DEF Language */ + /* Reference version 5.3 (May 31, 2000) */ + + fprintf(f, "VERSION 5.3 ;\n"); + fprintf(f, " NAMESCASESENSITIVE ON ;\n"); + fprintf(f, " NOWIREEXTENSIONATPIN ON ;\n"); + fprintf(f, " DIVIDERCHAR \"/\" ;\n"); + + /* As I understand it, this refers to the scalefactor of the GDS */ + /* file output. Magic does all GDS in nanometers, so the LEF */ + /* scalefactor (conversion to microns) is always 1000. */ + + fprintf(f, "UNITS\n"); + fprintf(f, " DATABASE MICRONS 1000 ;\n"); + fprintf(f, "END UNITS\n"); + fprintf(f, "\n"); + + /* Layers (minimal information) */ + + if (LefInfo.ht_table != (HashEntry **)NULL) + { + HashSearch hs; + HashEntry *he; + lefLayer *lefl; + + float oscale = CIFGetOutputScale(1000); /* lambda->micron conversion */ + + HashStartSearch(&hs); + while (he = HashNext(&LefInfo, &hs)) + { + lefl = (lefLayer *)HashGetValue(he); + if (!lefl) continue; + + if (lefl->refCnt > 0) + { + /* Avoid writing more than one entry per defined layer */ + if (lefl->refCnt > 1) lefl->refCnt = -lefl->refCnt; + + /* Ignore obstruction-only layers */ + if (lefl->type == -1) continue; + + /* Ignore VIA types, report only CUT types here */ + else if ((lefl->lefClass == CLASS_VIA) + && lefl->info.via.cell != NULL) continue; + + /* Ignore boundary types */ + else if (lefl->lefClass == CLASS_BOUND) continue; + + fprintf(f, "LAYER %s\n", lefl->canonName); + if (lefl->lefClass == CLASS_VIA) + { + int cutarea; + cutarea = (lefl->info.via.area.r_xtop - lefl->info.via.area.r_xbot); + cutarea *= (lefl->info.via.area.r_ytop - lefl->info.via.area.r_ybot); + fprintf(f, " TYPE CUT ;\n"); + if (cutarea > 0) + fprintf(f, " CUT AREA %f ;\n", + (float)cutarea * oscale * oscale); + } + else if (lefl->lefClass == CLASS_ROUTE) + { + fprintf(f, " TYPE ROUTING ;\n"); + if (lefl->info.route.pitch > 0) + fprintf(f, " PITCH %f ;\n", (float)(lefl->info.route.pitch) + * oscale); + if (lefl->info.route.width > 0) + fprintf(f, " WIDTH %f ;\n", (float)(lefl->info.route.width) + * oscale); + if (lefl->info.route.spacing > 0) + fprintf(f, " SPACING %f ;\n", (float)(lefl->info.route.spacing) + * oscale); + /* No sense in providing direction info unless we know the width */ + if (lefl->info.route.width > 0) + fprintf(f, " DIRECTION %s ;\n", (lefl->info.route.hdirection) + ? "HORIZONTAL" : "VERTICAL"); + } + else if (lefl->lefClass == CLASS_MASTER) + { + fprintf(f, " TYPE MASTERSLICE ;\n"); + } + else if (lefl->lefClass == CLASS_OVERLAP) + { + fprintf(f, " TYPE OVERLAP ;\n"); + } + fprintf(f, "END %s\n\n", lefl->canonName); + } + } + + /* Return reference counts to normal */ + HashStartSearch(&hs); + while (he = HashNext(&LefInfo, &hs)) + { + lefl = (lefLayer *)HashGetValue(he); + if (lefl && lefl->refCnt < 0) + lefl->refCnt = -lefl->refCnt; + } + } + + /* Vias (to be completed, presumably) */ + /* Rules (to be completed, presumably) */ + + UndoEnable(); +} + +#define LEF_MODE_PORT 0 +#define LEF_MODE_OBSTRUCT 1 + +typedef struct +{ + FILE *file; /* file to write to */ + TileType *lastType; /* last type output, so we minimize LAYER + * statements. + */ + CellDef *lefYank; /* CellDef to write into */ + LefMapping *lefMagicMap; /* Layer inverse mapping table */ + TileTypeBitMask rmask; /* mask of routing layer types */ + Point origin; /* origin of cell */ + float oscale; /* units scale conversion factor */ + int lefMode; /* can be LEF_MODE_PORT when searching + * connections into ports, or + * LEF_MODE_OBSTRUCT when generating + * obstruction geometry. LEF polyons + * must be manhattan, so if we find a + * split tile, LEF_MODE_PORT ignores it, + * and LEF_MODE_OBSTRUCT outputs the + * whole tile. + */ +} lefClient; + +/* + * ---------------------------------------------------------------------------- + * + * Callback function to find the cell boundary based on the specified + * boundary layer type. Typically this will be a single rectangle on + * its own plane, but for completeness, all geometry in the cell is + * checked, and the bounding rectangle adjusted to fit that area. + * + * Return 0 to keep the search going. + * ---------------------------------------------------------------------------- + */ + +int +lefGetBound(tile, cdata) + Tile *tile; + ClientData cdata; +{ + Rect *boundary = (Rect *)cdata; + Rect area; + + TiToRect(tile, &area); + GeoInclude(&area, boundary); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * lefYankGeometry -- + * + * Function called from SimSrConnect() that copies geometry from + * the cell into a yank buffer cell, one pin connection at a time. + * + * Return 0 to keep the search going. + * ---------------------------------------------------------------------------- + */ + +int +lefYankGeometry(tile, cdata) + Tile *tile; + ClientData cdata; +{ + lefClient *lefdata = (lefClient *)cdata; + Rect area; + TileType ttype, otype, ptype; + LefMapping *lefMagicToLefLayer; + TileTypeBitMask *sMask; + + /* To enumerate obstructions, we search all tiles in the */ + /* cell, and ignore all of those which were electrically */ + /* connected to any pin. These will have the tile's */ + /* ti_client record set to 1. */ + + /* Because DBSrPaintArea will look at each tile once and */ + /* only once, we can reset the ti_client record here, so */ + /* everything is back to normal after LEF output. */ + + if (lefdata->lefMode == LEF_MODE_OBSTRUCT) + if (tile->ti_client == (ClientData)1) + { + tile->ti_client = (ClientData)CLIENTDEFAULT; + return 0; + } + + otype = TiGetTypeExact(tile); + + if (IsSplit(tile)) + ttype = (otype & TT_SIDE) ? SplitRightType(tile) : + SplitLeftType(tile); + else + ttype = otype; + + /* Output geometry only for defined routing layers */ + /* If we have encountered a contact type, then */ + /* decompose into constituent layers and see if any */ + /* of them are in the route layer masks. */ + + if (DBIsContact(ttype)) + { + sMask = DBResidueMask(ttype); + + /* First check if lefdata->lastType is in the residue, */ + /* and process first. */ + + if (TTMaskHasType(sMask, *(lefdata->lastType))) + ttype = *(lefdata->lastType); + else + { + /* And if not, then switch to the first routing */ + /* layer that is represented in sMask. If none, */ + /* then return. */ + + for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) + if (TTMaskHasType(&lefdata->rmask, ttype)) + if (TTMaskHasType(sMask, ttype)) + break; + + if (ttype == DBNumTypes) return 0; + } + } + else + { + if (!TTMaskHasType(&lefdata->rmask, ttype)) return 0; + sMask = NULL; + } + lefMagicToLefLayer = lefdata->lefMagicMap; + + TiToRect(tile, &area); + + while (ttype < DBNumTypes) + { + if (lefMagicToLefLayer[ttype].lefInfo != NULL) + { + if (IsSplit(tile)) + // Set only the side being yanked + ptype = (otype & (TT_DIAGONAL | TT_SIDE | TT_DIRECTION)) | + ((otype & TT_SIDE) ? (ttype << 14) : ttype); + else + ptype = ttype; + DBPaint(lefdata->lefYank, &area, ptype); + } + + if (sMask == NULL) break; + + for (++ttype; ttype < DBNumTypes; ttype++) + if (TTMaskHasType(&lefdata->rmask, ttype)) + if (TTMaskHasType(sMask, ttype)) + break; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * lefWriteGeometry -- + * + * Function called from SimSrConnect() that outputs a RECT + * record for each tile called. Note that LEF does not define + * nonmanhattan geometry (see above, comments in lefClient typedef). + * + * Return 0 to keep the search going. + * ---------------------------------------------------------------------------- + */ + +int +lefWriteGeometry(tile, cdata) + Tile *tile; + ClientData cdata; +{ + lefClient *lefdata = (lefClient *)cdata; + FILE *f = lefdata->file; + float scale = lefdata->oscale; + TileType ttype, otype = TiGetTypeExact(tile); + LefMapping *lefMagicToLefLayer = lefdata->lefMagicMap; + + /* Get layer type */ + if (IsSplit(tile)) + ttype = (otype & TT_SIDE) ? SplitRightType(tile) : + SplitLeftType(tile); + else + ttype = otype; + + /* Only LEF routing layer types will be in the yank buffer */ + + if (!TTMaskHasType(&lefdata->rmask, ttype)) return 0; + + if (ttype != *(lefdata->lastType)) + { + if (lefMagicToLefLayer[ttype].lefInfo != NULL) + fprintf(f, " LAYER %s ;\n", + lefMagicToLefLayer[ttype].lefName); + *(lefdata->lastType) = ttype; + } + + if (IsSplit(tile)) + if (otype & TT_SIDE) + { + if (otype & TT_DIRECTION) + fprintf(f, " POLYGON %.4f %.4f %.4f %.4f %.4f %.4f ;\n", + scale * (float)(LEFT(tile) - lefdata->origin.p_x), + scale * (float)(TOP(tile) - lefdata->origin.p_y), + scale * (float)(RIGHT(tile) - lefdata->origin.p_x), + scale * (float)(TOP(tile) - lefdata->origin.p_y), + scale * (float)(RIGHT(tile) - lefdata->origin.p_x), + scale * (float)(BOTTOM(tile) - lefdata->origin.p_y)); + else + fprintf(f, " POLYGON %.4f %.4f %.4f %.4f %.4f %.4f ;\n", + scale * (float)(RIGHT(tile) - lefdata->origin.p_x), + scale * (float)(TOP(tile) - lefdata->origin.p_y), + scale * (float)(RIGHT(tile) - lefdata->origin.p_x), + scale * (float)(BOTTOM(tile) - lefdata->origin.p_y), + scale * (float)(LEFT(tile) - lefdata->origin.p_x), + scale * (float)(BOTTOM(tile) - lefdata->origin.p_y)); + } + else + { + if (otype & TT_DIRECTION) + fprintf(f, " POLYGON %.4f %.4f %.4f %.4f %.4f %.4f ;\n", + scale * (float)(LEFT(tile) - lefdata->origin.p_x), + scale * (float)(TOP(tile) - lefdata->origin.p_y), + scale * (float)(RIGHT(tile) - lefdata->origin.p_x), + scale * (float)(BOTTOM(tile) - lefdata->origin.p_y), + scale * (float)(LEFT(tile) - lefdata->origin.p_x), + scale * (float)(BOTTOM(tile) - lefdata->origin.p_y)); + else + fprintf(f, " POLYGON %.4f %.4f %.4f %.4f %.4f %.4f ;\n", + scale * (float)(LEFT(tile) - lefdata->origin.p_x), + scale * (float)(TOP(tile) - lefdata->origin.p_y), + scale * (float)(RIGHT(tile) - lefdata->origin.p_x), + scale * (float)(TOP(tile) - lefdata->origin.p_y), + scale * (float)(LEFT(tile) - lefdata->origin.p_x), + scale * (float)(BOTTOM(tile) - lefdata->origin.p_y)); + } + else + fprintf(f, " RECT %.4f %.4f %.4f %.4f ;\n", + scale * (float)(LEFT(tile) - lefdata->origin.p_x), + scale * (float)(BOTTOM(tile) - lefdata->origin.p_y), + scale * (float)(RIGHT(tile) - lefdata->origin.p_x), + scale * (float)(TOP(tile) - lefdata->origin.p_y)); + + return 0; +} + +/* + * When called from SimSrConnect(), the callback function needs another + * argument for the plane. + */ + +int +lefYankGeometry2(tile, plane, cdata) + Tile *tile; + Plane *plane; + ClientData cdata; +{ + return lefYankGeometry(tile, cdata); +} + +/* + * ---------------------------------------------------------------------------- + * + * MakeLegalLEFSyntax -- + * + * Follow syntactical rules of the LEF spec. Most notably, Magic + * node names often contain the hash mark '#', which is illegal + * in LEF output. Other illegal LEF characters are space, newline, + * semicolon, and for literal names: dash, asterisk, and percent. + * All of the above will be replaced with underscores if found. + * + * Results: + * Returns an allocated string containing the modified result, or + * else returns the original string pointer. It is the responsibility + * of the calling function to free the result if it is not equal to + * the argument. + * + * Side effects: + * Allocated memory. + * + * ---------------------------------------------------------------------------- + */ + +char * +MakeLegalLEFSyntax(text) + char *text; +{ + static char *badLEFchars = ";# -*$\n"; + char *cptr, *bptr; + char *rstr; + + for (cptr = text; *cptr != '\0'; cptr++) + for (bptr = badLEFchars; *bptr != '\0'; bptr++) + if (*cptr == *bptr) break; + + if (*cptr == '\0' && *bptr == '\0') + return text; + + rstr = StrDup((char **)NULL, text); + + for (cptr = rstr; *cptr != '\0'; cptr++) + for (bptr = badLEFchars; bptr != '\0'; bptr++) + if (*cptr == *bptr) + { + *cptr = '_'; + break; + } + + return rstr; +} + +/* + * ---------------------------------------------------------------------------- + * + * lefWriteMacro -- + * + * This routine generates LEF output for a cell in the form of a LEF + * "MACRO" block. Includes information on cell dimensions, pins, + * ports (physical layout associated with pins), and routing obstructions. + * + * Results: + * None. + * + * Side effects: + * Writes output to the open file "f". + * + * ---------------------------------------------------------------------------- + */ + +void +lefWriteMacro(def, f, scale) + CellDef *def; /* Def for which to generate LEF output */ + FILE *f; /* Output to this file */ + float scale; /* Output distance units conversion factor */ +{ + bool propfound; + char *propvalue, *class = NULL; + Label *lab, *clab; + Rect boundary; + TileTypeBitMask lmask, boundmask; + TileType ttype; + lefClient lc; + int idx, pNum; + char *LEFtext; + HashSearch hs; + HashEntry *he; + + UndoDisable(); + + TxPrintf("Diagnostic: Writing LEF output for cell %s\n", def->cd_name); + + /* Set up client record. */ + + lc.file = f; + lc.lastType = &ttype; + lc.oscale = scale; + lc.lefMagicMap = defMakeInverseLayerMap(); + lc.lefYank = DBCellNewDef("lefYank", (char *)NULL); + DBCellSetAvail(lc.lefYank); + lc.lefYank->cd_flags |= CDINTERNAL; + + TxPrintf("Diagnostic: Scale value is %f\n", lc.oscale); + + /* Which layers are routing layers are defined in the tech file. */ + + TTMaskZero(&lc.rmask); + TTMaskZero(&boundmask); + HashStartSearch(&hs); + while (he = HashNext(&LefInfo, &hs)) + { + TileTypeBitMask *lrmask; + lefLayer *lefl = (lefLayer *)HashGetValue(he); + if (lefl && (lefl->lefClass == CLASS_ROUTE || lefl->lefClass == CLASS_VIA)) + if (lefl->type != -1) + { + TTMaskSetType(&lc.rmask, lefl->type); + if (DBIsContact(lefl->type)) + { + lrmask = DBResidueMask(lefl->type); + TTMaskSetMask(&lc.rmask, lrmask); + } + else + { + // Contact types whose residues contain a route + // layer are included + for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) + if (DBIsContact(ttype)) + { + lrmask = DBResidueMask(ttype); + TTMaskSetMask(&lc.rmask, lrmask); + } + } + } + + if (lefl && (lefl->lefClass == CLASS_BOUND)) + if (lefl->type != -1) + TTMaskSetType(&boundmask, lefl->type); + } + + /* Any layer which has a port label attached to it should by */ + /* necessity be considered a routing layer. Usually this will not */ + /* add anything to the mask already created. */ + + for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next) + if (lab->lab_flags & PORT_DIR_MASK) + TTMaskSetType(&lc.rmask, lab->lab_type); + + /* NOTE: This routine corresponds to Envisia LEF/DEF Language */ + /* Reference version 5.3 (May 31, 2000) */ + + /* Macro header information (to be completed) */ + + fprintf(f, "MACRO %s\n", def->cd_name); + + /* LEF data is stored in the "cd_props" hash table. If the hash */ + /* table is NULL or a specific property undefined, then the LEF */ + /* value takes the default. Generally, LEF properties which have */ + /* default values are optional, so in this case we will leave those */ + /* entries blank. */ + + propvalue = (char *)DBPropGet(def, "LEFclass", &propfound); + if (propfound) + { + fprintf(f, " CLASS %s\n", propvalue); + class = propvalue; + } + + propvalue = (char *)DBPropGet(def, "LEFsource", &propfound); + if (propfound) + fprintf(f, " SOURCE %s\n", propvalue); + + fprintf(f, " FOREIGN %s ;\n", def->cd_name); + + /* If a boundary class was declared in the LEF section, then use */ + /* that layer type to define the boundary. Otherwise, the cell */ + /* boundary is defined by the magic database. If the boundary */ + /* class is used, and the boundary layer corner is not on the */ + /* origin, then shift all geometry by the difference. */ + + if (!TTMaskIsZero(&boundmask)) + { + for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) + DBSrPaintArea((Tile *)NULL, def->cd_planes[pNum], + &TiPlaneRect, &boundmask, lefGetBound, + (ClientData)(&boundary)); + } + else + boundary = def->cd_bbox; + + /* Apparently ORIGIN is not reliable! Assume origin must be (0,0) */ + /* and adjust all geometry instead of adjusting the origin. */ + +/* + fprintf(f, " ORIGIN %.4f %.4f ;\n", + lc.oscale * (float)boundary.r_xbot, + lc.oscale * (float)boundary.r_ybot); +*/ + fprintf(f, " ORIGIN 0.00 0.00 ;\n"); + lc.origin = boundary.r_ll; + + fprintf(f, " SIZE %.4f BY %.4f ;\n", + lc.oscale * (float)(boundary.r_xtop - boundary.r_xbot), + lc.oscale * (float)(boundary.r_ytop - boundary.r_ybot)); + + propvalue = (char *)DBPropGet(def, "LEFsymmetry", &propfound); + if (propfound) + fprintf(f, " SYMMETRY %s\n", propvalue); + + /* List of pins (ports) (to be refined?) */ + + lc.lefMode = LEF_MODE_PORT; + + for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next) + { + if (lab->lab_flags & PORT_DIR_MASK) + { + /* Ignore ports which we have already visited. */ + if (lab->lab_flags & PORT_VISITED) continue; + + idx = lab->lab_flags & PORT_NUM_MASK; + fprintf(f, " PIN %s\n", lab->lab_text); + if (lab->lab_flags & PORT_CLASS_MASK) + { + fprintf(f, " DIRECTION "); + switch(lab->lab_flags & PORT_CLASS_MASK) + { + case PORT_CLASS_INPUT: + fprintf(f, "INPUT"); + break; + case PORT_CLASS_OUTPUT: + fprintf(f, "OUTPUT"); + break; + case PORT_CLASS_TRISTATE: + fprintf(f, "OUTPUT TRISTATE"); + break; + case PORT_CLASS_BIDIRECTIONAL: + fprintf(f, "INOUT"); + break; + case PORT_CLASS_FEEDTHROUGH: + fprintf(f, "FEEDTHRU"); + break; + } + fprintf(f, " ;\n"); + } + if (lab->lab_flags & PORT_USE_MASK) + { + fprintf(f, " USE "); + switch(lab->lab_flags & PORT_USE_MASK) + { + case PORT_USE_SIGNAL: + fprintf(f, "SIGNAL"); + break; + case PORT_USE_ANALOG: + fprintf(f, "ANALOG"); + break; + case PORT_USE_POWER: + fprintf(f, "POWER"); + break; + case PORT_USE_GROUND: + fprintf(f, "GROUND"); + break; + case PORT_USE_CLOCK: + fprintf(f, "CLOCK"); + break; + } + fprintf(f, " ;\n"); + } + + /* Query pin geometry for SHAPE (to be done?) */ + + /* Generate port layout geometry using SimSrConnect() */ + /* Selects all electrically-connected material into the */ + /* select def. Output all the layers and geometries of */ + /* the select def. */ + /* */ + /* We use SimSrConnect() and not DBSrConnect() because */ + /* SimSrConnect() leaves "marks" (tile->ti_client = 1) */ + /* which allows us to later search through all tiles for */ + /* anything that is not connected to a port, and generate */ + /* an "obstruction" record for it. */ + /* */ + /* Note: Use DBIsContact() to check if the layer is a VIA. */ + /* Presently, I am treating contacts like any other layer. */ + + for (clab = lab; clab != NULL; clab = clab->lab_next) + { + if ((clab->lab_flags & PORT_NUM_MASK) == idx) + { + Rect labr = clab->lab_rect; + + /* Deal with degenerate (line or point) labels */ + /* by growing by 1 in each direction. */ + + if (labr.r_xtop - labr.r_xbot == 0) + { + labr.r_xtop++; + labr.r_xbot--; + } + if (labr.r_ytop - labr.r_ybot == 0) + { + labr.r_ytop++; + labr.r_ybot--; + } + + fprintf(f, " PORT\n"); + + TTMaskSetOnlyType(&lmask, clab->lab_type); + + ttype = TT_SPACE; + SimSrConnect(def, &labr, &lmask, DBConnectTbl, + &TiPlaneRect, lefYankGeometry2, (ClientData) &lc); + + for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) + { + DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum], + &TiPlaneRect, &lc.rmask, + lefWriteGeometry, (ClientData) &lc); + DBClearPaintPlane(lc.lefYank->cd_planes[pNum]); + } + + fprintf(f, " END\n"); /* end of port geometries */ + clab->lab_flags |= PORT_VISITED; + } + } + LEFtext = MakeLegalLEFSyntax(lab->lab_text); + fprintf(f, " END %s\n", lab->lab_text); /* end of pin */ + if (LEFtext != lab->lab_text) freeMagic(LEFtext); + } + } + + /* Clear all PORT_VISITED bits in labels */ + for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next) + if (lab->lab_flags & PORT_DIR_MASK) + lab->lab_flags &= ~(PORT_VISITED); + + /* List of routing obstructions */ + + lc.lefMode = LEF_MODE_OBSTRUCT; + ttype = TT_SPACE; + + /* Restrict to routing planes only */ + + fprintf(f, " OBS\n"); + for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) + { + DBSrPaintArea((Tile *)NULL, def->cd_planes[pNum], + &TiPlaneRect, &lc.rmask, + lefYankGeometry, (ClientData) &lc); + + DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum], + &TiPlaneRect, &lc.rmask, + lefWriteGeometry, (ClientData) &lc); + } + + fprintf(f, " END\n"); /* end of obstruction geometries */ + + fprintf(f, "END %s\n", def->cd_name); /* end of macro */ + + SigDisableInterrupts(); + freeMagic(lc.lefMagicMap); + DBCellClearDef(lc.lefYank); + SigEnableInterrupts(); + + UndoEnable(); +} + +/* + *------------------------------------------------------------ + * + * LefWriteAll -- + * + * Write LEF-format output for each cell, beginning with + * the top-level cell use "rootUse". + * + * Results: + * None. + * + * Side effects: + * Writes a .lef file to disk. + * + *------------------------------------------------------------ + */ + +void +LefWriteAll(rootUse, writeTopCell) + CellUse *rootUse; + bool writeTopCell; +{ + CellDef *def, *rootdef; + FILE *f; + char *filename; + float scale = CIFGetOutputScale(1000); /* conversion to microns */ + + rootdef = rootUse->cu_def; + + /* Make sure the entire subtree is read in */ + DBCellReadArea(rootUse, &rootdef->cd_bbox); + + /* Fix up bounding boxes if they've changed */ + DBFixMismatch(); + + /* Mark all defs as being unvisited */ + (void) DBCellSrDefs(0, lefDefInitFunc, (ClientData) 0); + + /* Recursively visit all defs in the tree and push on stack */ + lefDefStack = StackNew(100); + (void) lefDefPushFunc(rootUse); + + /* Open the file for output */ + + f = lefFileOpen(rootdef, (char *)NULL, ".lef", "w", &filename); + + TxPrintf("Generating LEF output %s for hierarchy rooted at cell %s:\n", + filename, rootdef->cd_name); + + if (f == NULL) + { +#ifdef MAGIC_WRAPPER + TxError("Cannot open output file %s (%s).\n", filename, + strerror(errno)); +#else + TxError("Cannot open output file: "); + perror(filename); +#endif + return; + } + + /* Now generate LEF output for all the cells we just found */ + + lefWriteHeader(rootdef, f); + + while (def = (CellDef *) StackPop(lefDefStack)) + { + def->cd_client = (ClientData) 0; + if (!SigInterruptPending) + if ((writeTopCell == TRUE) || (def != rootdef)) + lefWriteMacro(def, f, scale); + } + + fclose(f); + StackFree(lefDefStack); +} + +/* + * Function to initialize the client data field of all + * cell defs, in preparation for generating LEF output + * for a subtree rooted at a particular def. + */ + +int +lefDefInitFunc(def) + CellDef *def; +{ + def->cd_client = (ClientData) 0; + return (0); +} + +/* + * Function to push each cell def on lefDefStack + * if it hasn't already been pushed, and then recurse + * on all that def's children. + */ + +int +lefDefPushFunc(use) + CellUse *use; +{ + CellDef *def = use->cu_def; + + if (def->cd_client || (def->cd_flags & CDINTERNAL)) + return (0); + + def->cd_client = (ClientData) 1; + StackPush((ClientData) def, lefDefStack); + (void) DBCellEnum(def, lefDefPushFunc, (ClientData) 0); + return (0); +} + +/* + *------------------------------------------------------------ + * + * LefWriteCell -- + * + * Write LEF-format output for the indicated cell. + * + * Results: + * None. + * + * Side effects: + * Writes a single .lef file to disk. + * + *------------------------------------------------------------ + */ + +void +LefWriteCell(def, outName, isRoot) + CellDef *def; /* Cell being written */ + char *outName; /* Name of output file, or NULL. */ + bool isRoot; /* Is this the root cell? */ +{ + char *filename; + FILE *f; + float scale = CIFGetOutputScale(1000); + + f = lefFileOpen(def, outName, ".lef", "w", &filename); + + TxPrintf("Generating LEF output %s for cell %s:\n", filename, def->cd_name); + + if (f == NULL) + { +#ifdef MAGIC_WRAPPER + TxError("Cannot open output file %s (%s).\n", filename, + strerror(errno)); +#else + TxError("Cannot open output file: "); + perror(filename); +#endif + return; + } + + if (isRoot) + lefWriteHeader(def, f); + lefWriteMacro(def, f, scale); + fclose(f); +} + diff --git a/lef/tcllef.c b/lef/tcllef.c new file mode 100644 index 00000000..44ebaa85 --- /dev/null +++ b/lef/tcllef.c @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------*/ +/* tcllef.c */ +/* */ +/* Allows the "lef" feature to be loaded as a module */ +/* under the Tcl/Tk version of magic. Loading is */ +/* automatic upon invoking the "lef" command. */ +/*--------------------------------------------------------------*/ + +#ifdef LEF_AUTO + +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "commands/commands.h" +#include "utils/tech.h" +#include "dbwind/dbwind.h" + +/* External routines */ + +extern void CmdLef(); + +/* + * ---------------------------------------------------------------------------- + * + * Tcl package initialization function + * + * ---------------------------------------------------------------------------- + */ + +int +Magiclef_Init(interp) + Tcl_Interp *interp; +{ + /* Sanity checks! */ + if (interp == NULL) return TCL_ERROR; + if (Tcl_PkgRequire(interp, "Tclmagic", MAGIC_VERSION, 0) == NULL) + return TCL_ERROR; + if (Tcl_InitStubs(interp, "8.1", 0) == NULL) return TCL_ERROR; + + TxPrintf("Auto-loading LEF/DEF module\n"); + TxFlushOut(); + + /* Replace the auto-load function with the ones defined in */ + /* this package in the command functions list. */ + + if (WindReplaceCommand(DBWclientID, "lef", CmdLef) < 0) + return TCL_ERROR; + + if (WindReplaceCommand(DBWclientID, "def", CmdLef) < 0) + return TCL_ERROR; + + Tcl_PkgProvide(interp, "MagicLEF", MAGIC_VERSION); + return TCL_OK; +} + +#endif /* LEF_AUTO */ diff --git a/lisp/Depend b/lisp/Depend new file mode 100644 index 00000000..66f52c37 --- /dev/null +++ b/lisp/Depend @@ -0,0 +1,33 @@ +lispMain.o: lispMain.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h ../textio/textio.h \ + ../utils/signals.h ../utils/malloc.h +lispEval.o: lispEval.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h ../textio/textio.h \ + ../utils/malloc.h lispA-Z.h lisp.h lispargs.h ../utils/signals.h +lispPrint.o: lispPrint.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h ../textio/textio.h \ + ../utils/malloc.h lispargs.h ../utils/signals.h ../utils/hash.h +lispParse.o: lispParse.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h ../textio/textio.h \ + ../utils/hash.h ../utils/malloc.h +lispA-Z.o: lispA-Z.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h lispargs.h ../textio/textio.h \ + ../utils/malloc.h +lispGC.o: lispGC.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h ../textio/textio.h \ + ../utils/malloc.h lispargs.h +lispFrame.o: lispFrame.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h ../textio/textio.h \ + ../utils/malloc.h +lispTrace.o: lispTrace.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h ../textio/textio.h \ + ../utils/malloc.h +lispArith.o: lispArith.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h lispargs.h ../textio/textio.h \ + ../utils/malloc.h +lispString.o: lispString.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h lispargs.h ../textio/textio.h \ + ../utils/malloc.h +lispIO.o: lispIO.c ../lisp/lisp.h lispInt.h ../utils/magic.h \ + ../utils/geometry.h ../textio/txcommands.h lispargs.h ../textio/textio.h \ + ../utils/malloc.h ../utils/utils.h ../utils/signals.h diff --git a/lisp/Makefile b/lisp/Makefile new file mode 100644 index 00000000..e9a0f1d3 --- /dev/null +++ b/lisp/Makefile @@ -0,0 +1,23 @@ +# +# rscid $Header: +# + +MODULE = lisp +MAGICDIR = .. +SRCS = lispMain.c lispEval.c lispPrint.c lispParse.c lispA-Z.c \ + lispGC.c lispFrame.c lispTrace.c lispMagic.c lispArith.c \ + lispString.c lispIO.c +SCMSRC = default.scm box.scm label.scm draw.scm drc.scm \ + stack.scm layout.scm prs.scm help.scm gate.scm \ + sel.scm + +include ${MAGICDIR}/defs.mak + +INST_SCMSRC = ${SCMSRC:%=$(DESTDIR)${SCMDIR}/%} + +install: ${INST_SCMSRC} + +$(DESTDIR)${SCMDIR}/%: scm/% + ${CP} scm/$* $(DESTDIR)$(SCMDIR)/$* + +include ${MAGICDIR}/rules.mak diff --git a/lisp/README b/lisp/README new file mode 100644 index 00000000..f9fb28ab --- /dev/null +++ b/lisp/README @@ -0,0 +1,23 @@ +This is a mini-scheme interpreter, even though the files are all named +lisp*.{c,h}. + +This interpreter is *extremely* slow. I can think of lots of ways to +improve its memory usage and performance (a factor of 5 improvement +seems easy), but it is very robust and it works. :) Besides, it turns +out that the bottleneck in most common tasks is magic itself, not the +interpreter. + +The memory usage of this interpreter is ridiculously high. Collect garbage +often. :) Garbage collection is done automatically based on the +variable scm-gc-frequency at the top-level . . . i.e., when you see +magic's ">" prompt. To collect garbage at intermediate points in the +computation, you have to call "collect-garbage" explicitly. + + +-Rajit Manohar + Computer Systems Laboratory + Cornell University + Ithaca NY 14853 + http://www.csl.cornell.edu/~rajit/ + +$Id: README,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ diff --git a/lisp/lisp.h b/lisp/lisp.h new file mode 100644 index 00000000..27b6a8fb --- /dev/null +++ b/lisp/lisp.h @@ -0,0 +1,38 @@ +/************************************************************************* + * + * lisp.h -- + * + * This module defines things that are exported by the + * mini-scheme interpreter command line language to the rest + * of the world. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lisp.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ +#ifndef __LISP_H__ +#define __LISP_H__ + +/* + Interface to the Lisp interpreter from the textio module +*/ + +extern void LispEvaluate(); +extern void LispInit(); +extern void LispSetTech(); +extern void LispSetEdit(); + +#endif /* __LISP_H__ */ + diff --git a/lisp/lispA-Z.c b/lisp/lispA-Z.c new file mode 100644 index 00000000..e44b9f94 --- /dev/null +++ b/lisp/lispA-Z.c @@ -0,0 +1,1572 @@ +/************************************************************************* + * + * lispA-Z.c -- + * + * This module contains the builtin mini-scheme functions. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispA-Z.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "lispargs.h" +#include "textio/textio.h" +#include "utils/malloc.h" + + +/* + *============================================================================= + * + * + * Functions that test the type of their argument. + * + * + *============================================================================= + */ + +/*----------------------------------------------------------------------------- + * + * LispIsBool -- + * + * Return '#t' or '#f', depending on whether the type of the object. + * is a boolean. + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispIsBool (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *r; + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n",name); + RETURN; + } + r = LispNewObj (); + LTYPE(r) = S_BOOL; + LBOOL(r) = !!(r && LTYPE(ARG1(s)) == S_BOOL); + return r; +} + + +/*----------------------------------------------------------------------------- + * + * LispIsSym -- + * + * Return '#t' or '#f', depending on whether the type of the object + * is a symbol. + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispIsSym (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *r; + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n",name); + RETURN; + } + r = LispNewObj (); + LTYPE(r) = S_BOOL; + LBOOL(r) = !!(r && LTYPE(ARG1(s)) == S_SYM); + return r; +} + +/*----------------------------------------------------------------------------- + * + * LispIsNumber -- + * + * Return '#t' or '#f', depending on whether the type of the object + * is a number. + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispIsNumber (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *r; + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n",name); + RETURN; + } + r = LispNewObj (); + LTYPE(r) = S_BOOL; + LBOOL(r) = !!(r && (LTYPE(ARG1(s)) == S_INT || + LTYPE(ARG1(s)) == S_FLOAT)); + return r; +} + + +/*----------------------------------------------------------------------------- + * + * LispIsString -- + * + * Return '#t' or '#f', depending on whether the type of the object + * is a string. + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispIsString (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *r; + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n",name); + RETURN; + } + r = LispNewObj (); + LTYPE(r) = S_BOOL; + LBOOL(r) = !!(r && LTYPE(ARG1(s)) == S_STRING); + return r; +} + + + +/*----------------------------------------------------------------------------- + * + * LispIsProc -- + * + * Return '#t' or '#f', depending on whether the type of the object + * is a procedure. + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispIsProc (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *r; + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n",name); + RETURN; + } + r = LispNewObj (); + LTYPE(r) = S_BOOL; + LBOOL(r) = !!(r && (LTYPE(ARG1(s)) == S_LAMBDA || + LTYPE(ARG1(s)) == S_LAMBDA_BUILTIN || + LTYPE(ARG1(s)) == S_MAGIC_BUILTIN)); + return r; +} + + + +/*----------------------------------------------------------------------------- + * + * LispIsList -- + * + * Return '#t' or '#f', depending on whether the type of the object + * is a list. + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispIsList (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *r; + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n",name); + RETURN; + } + r = LispNewObj (); + LTYPE(r) = S_BOOL; + if (LTYPE(ARG1(s)) != S_LIST) + LBOOL(r) = 0; + else { + s = LLIST(ARG1(s)); + while (s && LTYPE(CDR(s)) == S_LIST) + s = LLIST(CDR(s)); + if (s) + LBOOL(r) = 0; + else + LBOOL(r) = 1; + } + return r; +} + + + +/*----------------------------------------------------------------------------- + * + * LispIsPair -- + * + * Return '#t' or '#f', depending on whether the type of the object + * is a pair. + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispIsPair (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *r; + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n",name); + RETURN; + } + r = LispNewObj (); + LTYPE(r) = S_BOOL; + if (LTYPE(ARG1(s)) != S_LIST) + LBOOL(r) = 0; + else { + s = LLIST(ARG1(s)); + while (s && LTYPE(CDR(s)) == S_LIST) + s = LLIST(CDR(s)); + if (s) + LBOOL(r) = 1; + else + LBOOL(r) = 0; + } + return r; +} + + + +static +int +EqualObjects (l1,l2) + LispObj *l1; + LispObj *l2; +{ + if (LTYPE(l1) != LTYPE(l2)) return 0; + switch (LTYPE(l1)) { + case S_LIST: + return LLIST(l1) == LLIST(l2); + break; + case S_SYM: + return LSYM(l1) == LSYM(l2); + break; + case S_MAGIC_BUILTIN: + return LSYM(l1) == LSYM(l2); + break; + case S_LAMBDA_BUILTIN: + return LBUILTIN(l1) == LBUILTIN(l2); + break; + case S_LAMBDA: + return LUSERDEF(l1) == LUSERDEF(l2); + break; + case S_INT: + return LINTEGER(l1) == LINTEGER(l2); + break; + case S_FLOAT: + return LFLOAT(l1) == LFLOAT(l2); + break; + case S_STRING: + return strcmp (LSTR(l1),LSTR(l2)); + break; + case S_BOOL: + return (LBOOL(l1) == LBOOL(l2)); + break; + default: + return 0; + break; + } +} + + + +/*----------------------------------------------------------------------------- + * + * LispEqv -- + * + * Compare two objects. + * + * Results: + * Result of comparison. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispEqv (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + if (!ARG1P(s) || !ARG2P(s) || ARG3P(s)) { + TxPrintf ("Usage: (%s obj1 obj2)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LINTEGER(l) = EqualObjects (ARG1(s), ARG2(s)); + return l; +} + + + + +/* + *============================================================================= + * + * + * List manipulation + * + * + *============================================================================= + */ + +/*----------------------------------------------------------------------------- + * + * LispCar -- + * + * Return car field of sexp. First argument must be a list. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispCar (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_LIST || !LLIST(ARG1(s)) || ARG2P(s)) { + TxPrintf ("Usage: (%s pair)\n",name); + RETURN; + } + return CAR(LLIST(ARG1(s))); +} + + + +/*----------------------------------------------------------------------------- + * + * LispCdr -- + * + * Return cdr field. First argument must be a list. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispCdr (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_LIST || !LLIST(ARG1(s)) || ARG2P(s)) { + TxPrintf ("Usage: (%s pair)\n",name); + RETURN; + } + return CDR(LLIST(ARG1(s))); +} + + + +/*----------------------------------------------------------------------------- + * + * LispCons -- + * + * Return a cons cell whose car field is arg1, and cdr field is arg2 + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispCons (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + Sexp *t; + + if (!ARG1P(s) || !ARG2P(s) || ARG3P(s)) { + TxPrintf ("Usage: (%s obj1 obj2)\n",name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_LIST; + t = LLIST(l) = LispNewSexp (); + CAR(t) = ARG1(s); + CDR(t) = ARG2(s); + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispNull -- + * + * Determines whether a list is the empty list. + * + * Results: + * #t => empty list + * #f => otherwise + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispNull (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s list)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = (LTYPE(ARG1(s)) == S_LIST && LLIST(ARG1(s)) == NULL) ? 1 : 0; + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispList -- + * + * Takes a list of objects and returns a new sexp with those + * objects as members of the list. + * + * Results: + * The newly created list. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispList (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + l = LispNewObj (); + LTYPE(l) = S_LIST; + LLIST(l) = s; + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispLength -- + * + * Computes the length of a list. + * + * Results: + * integer . . . the length of the list. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispLength (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + int len; + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_LIST || ARG2P(s)) { + TxPrintf ("Usage: (%s list)\n", name); + RETURN; + } + len = 0; + s = LLIST(ARG1(s)); + while (s) { + len++; + if (LTYPE(CDR(s)) == S_LIST) + s = LLIST(CDR(s)); + else + break; + } + if (s) { + TxPrintf ("Usage: (%s list)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_INT; + LINTEGER(l) = len; + return l; +} + + + + + + +/* + *============================================================================= + * + * + * Binding mechanisms and side-effects + * + * + *============================================================================= + */ + +/*----------------------------------------------------------------------------- + * + * LispDefine -- + * + * Add a binding to the current frame. + * (define symbol #lambda) + * + * Results: + * None. + * + * Side effects: + * Modifies frame. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispDefine (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + + LispCollectAllocQ = 0; + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_SYM || ARG3P(s)) { + TxPrintf ("Usage: (%s symbol obj)\n", name); + RETURN; + } + LispAddBinding (ARG1(s), LispCopyObj(ARG2(s)), f); + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 1; + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispSetBang -- + * + * "set!" lisp builtin. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispSetBang (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_SYM || ARG3P(s)) { + TxPrintf ("Usage: (%s symbol obj)\n", name); + RETURN; + } + LispCollectAllocQ = 0; + if (LispModifyBinding (ARG1(s), ARG2(s), f)) { + return ARG2(s); + } + else { + TxPrintf ("%s: unknown symbol [%s]\n", name, LSYM(ARG1(s))); + RETURN; + } +} + + + +/*----------------------------------------------------------------------------- + * + * LispLet -- + * + * Let bindings. + * (let binding-list body) + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispLet (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *body, *l; + Sexp *frame, *saved; + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_LIST || ARG3P(s)) { + TxPrintf ("Usage: (%s list obj)\n", name); + RETURN; + } + frame = LispFramePush (f); + body = ARG2(s); + s = LLIST(ARG1(s)); + + LispGCAddSexp (saved = s); + LispGCAddSexp (f); + LispGCAddSexp (frame); + + while (s) { + if (LTYPE(CAR(s)) != S_LIST || LTYPE(CDR(s)) != S_LIST) { + TxPrintf ("%s: binding must be a list\n", name); + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + if (LTYPE(CAR(LLIST(CAR(s)))) != S_SYM) { + TxPrintf ("%s: can only bind to a symbol\n", name); + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + l = LispEval (CAR(LLIST(CDR(LLIST(CAR(s))))),f); + if (l == NULL) { + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + return NULL; + } + LispAddBinding (CAR(LLIST(CAR(s))), l, frame); + s = LLIST(CDR(s)); + } + + body = LispEval (body, frame); + + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + + return body; +} + + + +/*----------------------------------------------------------------------------- + * + * LispLetRec -- + * + * Letrec bindings. + * (letrec binding-list body) + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispLetRec (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *body, *l; + Sexp *frame, *saved; + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_LIST || ARG3P(s)) { + TxPrintf ("Usage: (%s list obj)\n", name); + RETURN; + } + frame = LispFramePush (f); + body = ARG2(s); + s = LLIST(ARG1(s)); + + LispGCAddSexp (saved = s); + LispGCAddSexp (f); + LispGCAddSexp (frame); + + while (s) { + if (LTYPE(CAR(s)) != S_LIST || LTYPE(CDR(s)) != S_LIST) { + TxPrintf ("%s: binding must be a list\n", name); + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + if (LTYPE(CAR(LLIST(CAR(s)))) != S_SYM) { + TxPrintf ("%s: can only bind to a symbol\n", name); + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + l = LispEval (CAR(LLIST(CDR(LLIST(CAR(s))))),frame); + if (l == NULL) { + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + return NULL; + } + LispAddBinding (CAR(LLIST(CAR(s))), l, frame); + s = LLIST(CDR(s)); + } + + body = LispEval (body, frame); + + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + + return body; +} + + + +/*----------------------------------------------------------------------------- + * + * LispLetStar -- + * + * LetStar bindings. + * (let* binding-list body) + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispLetStar (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *body, *l; + Sexp *frame, *saved; + + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_LIST || ARG3P(s)) { + TxPrintf ("Usage: (%s list obj)\n", name); + RETURN; + } + + body = ARG2(s); + s = LLIST(ARG1(s)); + frame = f; + + LispGCAddSexp (saved = s); + LispGCAddSexp (f); + LispGCAddSexp (frame); + + while (s) { + LispGCRemoveSexp (frame); + frame = LispFramePush (frame); + LispGCAddSexp (frame); + if (LTYPE(CAR(s)) != S_LIST || LTYPE(CDR(s)) != S_LIST) { + TxPrintf ("%s: binding must be a list\n", name); + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + if (LTYPE(CAR(LLIST(CAR(s)))) != S_SYM) { + TxPrintf ("%s: can only bind to a symbol\n", name); + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + l = LispEval (CAR(LLIST(CDR(LLIST(CAR(s))))),frame); + if (l == NULL) { + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + return NULL; + } + LispAddBinding (CAR(LLIST(CAR(s))), l, frame); + s = LLIST(CDR(s)); + } + + body = LispEval (body, frame); + + LispGCRemoveSexp (frame); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + + return body; +} + + + + +/*----------------------------------------------------------------------------- + * + * LispSetCarBang -- + * + * Modifies the pair + * + * Results: + * New binding for pair + * + * Side effects: + * Of course! + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispSetCarBang (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_LIST || !LLIST(ARG1(s)) || ARG3P(s)) { + TxPrintf ("Usage: (%s pair obj)\n", name); + RETURN; + } + LispCollectAllocQ = 0; + CAR(LLIST(ARG1(s))) = ARG2(s); + return ARG1(s); +} + + +/*----------------------------------------------------------------------------- + * + * LispSetCdrBang -- + * + * Modifies the pair + * + * Results: + * New binding for pair + * + * Side effects: + * Of course! + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispSetCdrBang (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_LIST || !LLIST(ARG1(s)) || ARG3P(s)) { + TxPrintf ("Usage: (%s pair obj)\n", name); + RETURN; + } + LispCollectAllocQ = 0; + CDR(LLIST(ARG1(s))) = ARG2(s); + return ARG1(s); +} + + + + +/* + *============================================================================= + * + * + * Control over what gets evaluated + * + * + *============================================================================= + */ + + +/*----------------------------------------------------------------------------- + * + * Lispeval -- + * + * Evaluate argument. + * (eval object) + * + * Results: + * result of evaluating its argument. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +Lispeval (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n", name); + RETURN; + } + return LispEval (ARG1(s),f); +} + + + +/*----------------------------------------------------------------------------- + * + * LispQuote -- + * + * Return quoted argument. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispQuote (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n",name); + RETURN; + } + return ARG1(s); +} + + + + +/* + *============================================================================= + * + * + * Control flow: sequencing and conditional execution + * + * + *============================================================================= + */ + +/*----------------------------------------------------------------------------- + * + * LispIf -- + * + * Conditional evaluation. + * (if condition sexp1 sexp2) + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispIf (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + if (!ARG1P(s) || !ARG2P(s) || !ARG3P(s) || LTYPE(ARG1(s)) != S_BOOL + || ARG4P(s)) { + TxPrintf ("Usage: (%s bool obj1 obj2)\n", name); + RETURN; + } + + /* s might be collected before this function returns. But that's okay. */ + + if (LBOOL(ARG1(s))) + return LispEval (ARG2(s), f); + else + return LispEval (ARG3(s), f); +} + + + +/*----------------------------------------------------------------------------- + * + * LispCond -- + * + * cond evaluation + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispCond (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + LispObj *m; + Sexp *t, *saved; + + if (!ARG1P(s)) { + TxPrintf ("Usage: (%s (bool val) ...)\n", name); + RETURN; + } + + LispGCAddSexp (saved = s); + LispGCAddSexp (f); + + while (ARG1P(s)) { + if (LTYPE(CDR(s)) != S_LIST) { + TxPrintf ("%s: argument is not a list!\n", name); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + m = ARG1(s); + if (LTYPE(m) != S_LIST) { + TxPrintf ("%s: argument is not a list\n", name); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + if (LTYPE(CDR(LLIST(m))) != S_LIST || !LLIST(CDR(LLIST(m)))) { + TxPrintf ("%s: argument is not a list\n", name); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + if (LTYPE(CDR(LLIST(CDR(LLIST(m))))) != S_LIST || LLIST(CDR(LLIST(CDR(LLIST(m)))))) { + TxPrintf ("%s: argument is not a list with two elements\n", name); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + + l = LispEval (CAR(LLIST(m)),f); + + if (!l) { + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + return NULL; + } + + if (LTYPE(l) != S_BOOL) { + TxPrintf ("%s: first arg in list must be of type boolean\n", name); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + RETURN; + } + + if (LBOOL(l)) { + l = LispEval (CAR(LLIST(CDR(LLIST(m)))),f); + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + return l; + } + s = LLIST(CDR(s)); + } + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 0; + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispBegin -- + * + * (begin a b c d . . .) + * Evaluates its arguments in order (l->r) and returns the result + * of the last evaluation. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispBegin (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l, *m; + Sexp *saved; + + if (!s) { + TxPrintf ("Usage: (%s obj1 ...)\n", name); + RETURN; + } + + LispGCAddSexp (saved = s); + LispGCAddSexp (f); + + while (s && LTYPE(CDR(s)) == S_LIST) { + l = LispEval (CAR(s),f); + if (l == NULL) { + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + return NULL; + } + s = LLIST(CDR(s)); + } + if (s && LTYPE(CDR(s)) != S_LIST) { + m = LispEval (CDR(s),f); + if (m == NULL) { + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + return NULL; + } + s = LispNewSexp (); + CAR(s) = l; + CDR(s) = m; + l = LispNewObj (); + LTYPE(l) = S_LIST; + LLIST(l) = s; + } + LispGCRemoveSexp (f); + LispGCRemoveSexp (saved); + return l; +} + + + +/* + *============================================================================= + * + * + * Functions + * + * + *============================================================================= + */ + +/*----------------------------------------------------------------------------- + * + * LispApply -- + * + * Apply lambda to a list. + * (apply #lambda list) + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +Lispapply (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG2(s)) != S_LIST || + (LTYPE(ARG1(s)) != S_LAMBDA && LTYPE(ARG1(s)) != S_LAMBDA_BUILTIN && + LTYPE(ARG1(s)) != S_MAGIC_BUILTIN) || ARG3P(s)) { + TxPrintf ("Usage: (%s proc list)\n", name); + RETURN; + } + if (LTYPE(ARG1(s)) == S_LAMBDA_BUILTIN) + return LispBuiltinApply (LBUILTIN(ARG1(s)), LLIST(ARG2(s)), f); + else if (LTYPE(ARG1(s)) == S_MAGIC_BUILTIN) + return LispMagicSend (LSYM(ARG1(s)), LLIST(ARG2(s)), f); + else + return LispApply (LUSERDEF(ARG1(s)), LLIST(ARG2(s)), f); +} + + + +/*----------------------------------------------------------------------------- + * + * LispLambda -- + * + * Return a "lambda" construction. + * (lambda list list) + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispLambda (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + Sexp *s1; + int number; + Sexp *arglist; + Sexp *frame; + LispObj *evallist; + + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_LIST || ARG3P(s)) { + TxPrintf ("Usage: (%s list obj)\n", name); + RETURN; + } + /* check first argument */ + number = 0; + s1 = LLIST(ARG1(s)); + while (s1 && LTYPE(CDR(s1)) == S_LIST) { + if (LTYPE(CAR(s1)) != S_SYM) { + TxPrintf ("%s: all arguments must be symbols\n", name); + RETURN; + } + number++; + s1 = LLIST(CDR(s1)); + } + if (s1) + number=-(number+1); /* dotted-pair args! */ + arglist = LLIST(ARG1(s)); + frame = f; + evallist = ARG2(s); + s1 = LispNewSexp (); + CAR(s1) = evallist; + CDR(s1) = LispNewObj (); + LTYPE(CDR(s1)) = S_LIST; + LLIST(CDR(s1)) = NULL; + s = s1; + s1 = LispNewSexp (); + CDR(s1) = LispNewObj (); + LTYPE(CDR(s1)) = S_LIST; + LLIST(CDR(s1)) = s; + CAR(s1) = LispNewObj (); + LTYPE(CAR(s1)) = S_LIST; + LLIST(CAR(s1)) = frame; + s = s1; + s1 = LispNewSexp (); + CDR(s1) = LispNewObj (); + LTYPE(CDR(s1)) = S_LIST; + LLIST(CDR(s1)) = s; + CAR(s1) = LispNewObj (); + LTYPE(CAR(s1)) = S_LIST; + LLIST(CAR(s1)) = arglist; + s = s1; + s1 = LispNewSexp (); + CDR(s1) = LispNewObj (); + LTYPE(CDR(s1)) = S_LIST; + LLIST(CDR(s1)) = s; + CAR(s1) = LispNewObj (); + LTYPE(CAR(s1)) = S_INT; + LINTEGER(CAR(s1)) = number; + l = LispNewObj (); + LTYPE(l) = S_LAMBDA; + LUSERDEF(l) = s1; + return l; +} + + + +/* + *============================================================================= + * + * + * Debugging/error reporting + * + * + *============================================================================= + */ + +/*----------------------------------------------------------------------------- + * + * LispDisplayObj -- + * + * (display-object s) + * Prints object out to screen. + * + * + * Results: + * returns #t. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispDisplayObj (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n", name); + RETURN; + } + TxPrintf (" => type: "); + LispPrintType (stdout,ARG1(s)); TxPrintf ("\n"); + TxPrintf (" value: "); + LispPrint (stdout,ARG1(s)); + TxPrintf ("\n"); + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 1; + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispPrintObj -- + * + * (print-object s) + * Prints object out to screen, no newlines + * + * + * Results: + * returns #t. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispPrintObj (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + if (!ARG1P(s) || ARG2P(s)) { + TxPrintf ("Usage: (%s obj)\n", name); + RETURN; + } + LispPrint (stdout,ARG1(s)); + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 1; + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispError -- + * + * Echo error and abort evaluation. + * + * Results: + * NULL + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispError (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + int i,j; + char *str; + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || ARG2P(s)) { + TxPrintf ("Usage: (%s str)\n", name); + RETURN; + } + i = 0; j = 0; + str = (char *) mallocMagic((unsigned) (strlen(LSTR(ARG1(s)))+1)); + strcpy (str, LSTR(ARG1(s))); + while (str[i]) { + if (str[i] == '\\') + i++; + str[j] = str[i]; + i++; j++; + } + str[j] = '\0'; + TxPrintf ("%s\n", str); + freeMagic(str); + RETURN; +} + + + +/*----------------------------------------------------------------------------- + * + * LispShowFrame -- + * + * Display the current frame. + * + * Results: + * None. + * + * Side effects: + * Text appears in window. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispShowFrame (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + + if (ARG1P(s)) { + TxPrintf ("Usage: (%s)\n", name); + RETURN; + } + + TxPrintf (" >> "); + l = LispNewObj (); + LTYPE(l) = S_LIST; + LLIST(l) = f; + LispPrint (stdout,l); + TxPrintf ("\n"); + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 1; + return l; +} diff --git a/lisp/lispA-Z.h b/lisp/lispA-Z.h new file mode 100644 index 00000000..1a12f37f --- /dev/null +++ b/lisp/lispA-Z.h @@ -0,0 +1,135 @@ +/************************************************************************* + * + * lispA-Z.h -- + * + * Declarations for builtins. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispA-Z.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include + +#include "lisp.h" +#include "lispInt.h" + + +/* + * predicates + */ +extern LispObj *LispIsBool (); +extern LispObj *LispIsSym (); +extern LispObj *LispIsList (); +extern LispObj *LispIsPair (); +extern LispObj *LispIsNumber (); +extern LispObj *LispIsString (); +extern LispObj *LispIsProc (); +extern LispObj *LispEqv (); + +/* + * lists + */ +extern LispObj *LispCar (); +extern LispObj *LispCdr (); +extern LispObj *LispCons (); +extern LispObj *LispNull (); +extern LispObj *LispList (); +extern LispObj *LispLength (); + +/* + * controlling evaluation + */ +extern LispObj *LispQuote (); +extern LispObj *Lispeval (); +extern LispObj *LispLambda (); +extern LispObj *Lispapply (); + +/* + * definitions and side-effects + */ +extern LispObj *LispDefine (); +extern LispObj *LispSetBang (); +extern LispObj *LispLet (); +extern LispObj *LispLetRec (); +extern LispObj *LispLetStar (); +extern LispObj *LispSetCarBang (); +extern LispObj *LispSetCdrBang (); + +/* + * arithmetic + */ +extern LispObj *LispAdd (); +extern LispObj *LispSub (); +extern LispObj *LispMult (); +extern LispObj *LispDiv (); +extern LispObj *LispTruncate (); +extern LispObj *LispZeroQ (); +extern LispObj *LispPositiveQ (); +extern LispObj *LispNegativeQ (); + +/* + * control flow + */ +extern LispObj *LispBegin (); +extern LispObj *LispIf (); +extern LispObj *LispCond (); + +/* + * debugging + */ +extern LispObj *LispShowFrame (); +extern LispObj *LispDisplayObj (); +extern LispObj *LispPrintObj (); +extern LispObj *LispError (); + +/* + * I/O + */ +extern LispObj *LispLoad (); +extern LispObj *LispWrite (); +extern LispObj *LispSpawn (); +extern LispObj *LispWait (); + +/* + * utilities + */ +extern LispObj *LispCollectGarbage (); + +/* + * String functions + */ +extern LispObj *LispStrCat (); +extern LispObj *LispSymbolToString (); +extern LispObj *LispStringToSymbol (); +extern LispObj *LispNumberToString (); +extern LispObj *LispStringToNumber (); +extern LispObj *LispStringLength (); +extern LispObj *LispStringCompare (); +extern LispObj *LispStringRef (); +extern LispObj *LispStringSet (); +extern LispObj *LispSubString (); + +/* + * magic interaction + */ +extern LispObj *LispGetPaint (); +extern LispObj *LispGetSelPaint (); +extern LispObj *LispGetbox (); +extern LispObj *LispGetPoint (); +extern LispObj *LispGetLabel (); +extern LispObj *LispGetSelLabel (); +extern LispObj *LispGetCellNames (); +extern LispObj *LispEvalMagic (); diff --git a/lisp/lispArith.c b/lisp/lispArith.c new file mode 100644 index 00000000..ce47200a --- /dev/null +++ b/lisp/lispArith.c @@ -0,0 +1,369 @@ +/************************************************************************* + * + * lispArith.c -- + * + * This module contains the builtin mini-scheme arithmetic functions. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispArith.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "lispargs.h" +#include "textio/textio.h" +#include "utils/malloc.h" + + +/*----------------------------------------------------------------------------- + * + * LispAdd -- + * + * "+" + * + * Results: + * Returns the sum of two arguments. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +LispObj * +LispAdd (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + double d; + + if (!ARG1P(s) || !ARG2P(s) || !NUMBER(LTYPE(ARG1(s))) || + !NUMBER(LTYPE(ARG2(s))) || ARG3P(s)) { + TxPrintf ("Usage: (%s num1 num2)\n", name); + RETURN; + } + l = LispNewObj (); + if (LTYPE(ARG1(s)) == S_FLOAT || LTYPE(ARG2(s)) == S_FLOAT) { + LTYPE(l) = S_FLOAT; + d = LTYPE(ARG1(s)) == S_FLOAT ? LFLOAT(ARG1(s)) : LINTEGER(ARG1(s)); + d+= LTYPE(ARG2(s)) == S_FLOAT ? LFLOAT(ARG2(s)) : LINTEGER(ARG2(s)); + LFLOAT(l) = d; + } + else { + LTYPE(l) = S_INT; + LINTEGER(l) = LINTEGER(ARG1(s))+LINTEGER(ARG2(s)); + } + return l; +} + + +/*----------------------------------------------------------------------------- + * + * LispSub -- + * + * "-" + * + * Results: + * Returns the difference of two arguments. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +LispObj * +LispSub (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + double d; + + if (!ARG1P(s) || !ARG2P(s) || !NUMBER(LTYPE(ARG1(s))) || + !NUMBER(LTYPE(ARG2(s))) || ARG3P(s)) { + TxPrintf ("Usage: (%s num1 num2)\n", name); + RETURN; + } + if (!NUMBER(LTYPE(ARG1(s))) || !NUMBER(LTYPE(ARG2(s)))) { + TxPrintf ("%s: requires two numbers\n", name); + RETURN; + } + l = LispNewObj (); + if (LTYPE(ARG1(s)) == S_FLOAT || LTYPE(ARG2(s)) == S_FLOAT) { + LTYPE(l) = S_FLOAT; + d = LTYPE(ARG1(s)) == S_FLOAT ? LFLOAT(ARG1(s)) : LINTEGER(ARG1(s)); + d-= LTYPE(ARG2(s)) == S_FLOAT ? LFLOAT(ARG2(s)) : LINTEGER(ARG2(s)); + LFLOAT(l) = d; + } + else { + LTYPE(l) = S_INT; + LINTEGER(l) = LINTEGER(ARG1(s))-LINTEGER(ARG2(s)); + } + return l; +} + + +/*----------------------------------------------------------------------------- + * + * LispMult -- + * + * "*" + * + * Results: + * Returns the product of two arguments. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +LispObj * +LispMult (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + double d; + + if (!ARG1P(s) || !ARG2P(s) || !NUMBER(LTYPE(ARG1(s))) || + !NUMBER(LTYPE(ARG2(s))) || ARG3P(s)) { + TxPrintf ("Usage: (%s num1 num2)\n", name); + RETURN; + } + l = LispNewObj (); + if (LTYPE(ARG1(s)) == S_FLOAT || LTYPE(ARG2(s)) == S_FLOAT) { + d = LTYPE(ARG1(s)) == S_FLOAT ? LFLOAT(ARG1(s)) : LINTEGER(ARG1(s)); + d *= (LTYPE(ARG2(s)) == S_FLOAT ? LFLOAT(ARG2(s)) : LINTEGER(ARG2(s))); + LTYPE(l) = S_FLOAT; + LFLOAT(l) = d; + } + else { + LTYPE(l) = S_INT; + LINTEGER(l) = LINTEGER(ARG1(s))*LINTEGER(ARG2(s)); + } + return l; +} + +/*----------------------------------------------------------------------------- + * + * LispDiv -- + * + * "/" + * + * Results: + * Returns the quotient of two arguments. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +LispObj * +LispDiv (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + double d; + + if (!ARG1P(s) || !ARG2P(s) || !NUMBER(LTYPE(ARG1(s))) || + !NUMBER(LTYPE(ARG2(s))) || ARG3P(s)) { + TxPrintf ("Usage: (%s num1 num2)\n", name); + RETURN; + } + l = LispNewObj (); + if (LTYPE(ARG1(s)) == S_FLOAT || LTYPE(ARG2(s)) == S_FLOAT) { + LTYPE(l) = S_FLOAT; + d = LTYPE(ARG1(s)) == S_FLOAT ? LFLOAT(ARG1(s)) : LINTEGER(ARG1(s)); + if ((LTYPE(ARG2(s)) == S_FLOAT && LFLOAT(ARG2(s)) == 0) || + (LTYPE(ARG2(s)) == S_INT && LINTEGER(ARG2(s)) == 0)) { + TxPrintf ("Division by zero\n"); + RETURN; + } + d /= LTYPE(ARG2(s)) == S_FLOAT ? LFLOAT(ARG2(s)) : LINTEGER(ARG2(s)); + LFLOAT(l) = d; + } + else { + if (LINTEGER(ARG2(s)) == 0) { + TxPrintf ("Division by zero\n"); + RETURN; + } + d = (double)LINTEGER(ARG1(s))/(double)LINTEGER(ARG2(s)); + if (d == ((int)d)) { + LTYPE(l) = S_INT; + LINTEGER(l) = (int)d; + } + else { + LTYPE(l) = S_FLOAT; + LFLOAT(l) = d; + } + } + return l; +} + + +/*----------------------------------------------------------------------------- + * + * LispTruncate -- + * + * Truncate a number. + * + * Results: + * Returns an integer. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +LispObj * +LispTruncate (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + double d; + + if (!ARG1P(s) || !NUMBER(LTYPE(ARG1(s))) || ARG2P(s)) { + TxPrintf ("Usage: (%s num)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_INT; + if (LTYPE(ARG1(s)) == S_FLOAT) + LINTEGER(l) = (int)LFLOAT(ARG1(s)); + else + LBOOL(l) = LINTEGER(ARG1(s)); + return l; +} + + +/*----------------------------------------------------------------------------- + * + * LispZeroQ -- + * + * Checks if argument is zero. + * + * Results: + * Returns a boolean. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +LispObj * +LispZeroQ (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + double d; + + if (!ARG1P(s) || !NUMBER(LTYPE(ARG1(s))) || ARG2P(s)) { + TxPrintf ("Usage: (%s num)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_BOOL; + if (LTYPE(ARG1(s)) == S_FLOAT) + LBOOL(l) = LFLOAT(ARG1(s)) == 0 ? 1 : 0; + else + LBOOL(l) = LINTEGER(ARG1(s)) == 0 ? 1 : 0; + return l; +} + + +/*----------------------------------------------------------------------------- + * + * LispPositiveQ -- + * + * Checks if argument is positive. + * + * Results: + * Returns a boolean. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +LispObj * +LispPositiveQ (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + double d; + + if (!ARG1P(s) || !NUMBER(LTYPE(ARG1(s))) || ARG2P(s)) { + TxPrintf ("Usage: (%s num)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_BOOL; + if (LTYPE(ARG1(s)) == S_FLOAT) + LBOOL(l) = LFLOAT(ARG1(s)) > 0 ? 1 : 0; + else + LBOOL(l) = LINTEGER(ARG1(s)) > 0 ? 1 : 0; + return l; +} + + +/*----------------------------------------------------------------------------- + * + * LispNegativeQ -- + * + * Checks if argument is negative. + * + * Results: + * Returns a boolean. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +LispObj * +LispNegativeQ (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + double d; + + if (!ARG1P(s) || !NUMBER(LTYPE(ARG1(s))) || ARG2P(s)) { + TxPrintf ("Usage: (%s num)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_BOOL; + if (LTYPE(ARG1(s)) == S_FLOAT) + LBOOL(l) = LFLOAT(ARG1(s)) < 0 ? 1 : 0; + else + LBOOL(l) = LINTEGER(ARG1(s)) < 0 ? 1 : 0; + return l; +} diff --git a/lisp/lispEval.c b/lisp/lispEval.c new file mode 100644 index 00000000..2d7f5d89 --- /dev/null +++ b/lisp/lispEval.c @@ -0,0 +1,650 @@ +/************************************************************************* + * + * lispEval.c -- + * + * This module contains the core of the mini-scheme interpreter. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispEval.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "lispA-Z.h" +#include "lispargs.h" +#include "utils/signals.h" + +struct LispBuiltinFn { + char *name; + int id; + int lazy; /* != 0 if lazy */ + LispObj *(*f) (); /* built-in */ +}; + +static struct LispBuiltinFn FnTable[] = { + +/*------------------------------------------------------------------------ + * E a g e r F u n c t i o n s + *------------------------------------------------------------------------ + */ + + /* inspect arguments */ + + { "boolean?", -1, 0, LispIsBool }, + { "symbol?", -1, 0, LispIsSym }, + { "list?", -1, 0, LispIsList }, + { "pair?", -1, 0, LispIsPair }, + { "number?", -1, 0, LispIsNumber }, + { "string?", -1, 0, LispIsString }, + { "procedure?", -1, 0, LispIsProc }, + + /* standard list manipulation */ + + { "car", -1, 0, LispCar }, + { "cdr", -1, 0, LispCdr }, + { "cons", -1, 0, LispCons }, + { "set-car!", -1, 0, LispSetCarBang }, + { "set-cdr!", -1, 0, LispSetCdrBang }, + { "null?", -1, 0, LispNull }, + { "list", -1, 0, LispList }, + { "length", -1, 0, LispLength }, + + { "eval", -1, 0, Lispeval }, + { "apply", -1, 0, Lispapply }, + + { "eqv?", -1, 0, LispEqv }, + + /* math */ + { "+", -1, 0, LispAdd }, + { "*", -1, 0, LispMult }, + { "-", -1, 0, LispSub }, + { "/", -1, 0, LispDiv }, + { "truncate", -1, 0, LispTruncate }, + + + /* comparison */ + { "zero?", -1, 0, LispZeroQ }, + { "positive?", -1, 0, LispPositiveQ }, + { "negative?", -1, 0, LispNegativeQ }, + + /* string manipulation */ + { "string-append", -1, 0, LispStrCat }, + { "symbol->string", -1, 0, LispSymbolToString }, + { "string->symbol", -1, 0, LispStringToSymbol }, + { "number->string", -1, 0, LispNumberToString }, + { "string->number", -1, 0, LispStringToNumber }, + { "string-length", -1, 0, LispStringLength }, + { "string-compare", -1, 0, LispStringCompare }, + { "string-ref", -1, 0, LispStringRef }, + { "string-set!", -1, 0, LispStringSet }, + { "substring", -1, 0, LispSubString }, + + /* file I/O and spawn/wait */ + { "load-scm", -1, 0, LispLoad }, + { "save-scm", -1, 0, LispWrite }, + { "spawn", -1, 0, LispSpawn }, + { "wait", -1, 0, LispWait }, + + /* utilities */ + { "collect-garbage", -1, 0, LispCollectGarbage }, + + /* debugging help */ + + { "error", -1, 0, LispError }, + { "showframe", -1, 0, LispShowFrame }, + { "display-object", -1, 0, LispDisplayObj }, + { "print-object", -1, 0, LispPrintObj }, + + /* magic */ + { "getpoint", -1, 0, LispGetPoint }, + { "getbox", -1, 0, LispGetbox }, + { "getpaint", -1, 0, LispGetPaint }, + { "getselpaint", -1, 0, LispGetSelPaint }, + { "getlabel", -1, 0, LispGetLabel }, + { "getsellabel", -1, 0, LispGetSelLabel }, + { "getcellnames", -1, 0, LispGetCellNames }, + { "magic", -1, 1, LispEvalMagic }, /* lazy */ + +/*------------------------------------------------------------------------ + * N o t - s o - e a g e r F u n c t i o n s + *------------------------------------------------------------------------ + */ + /* lazy functions, don't evaluate any arguments */ + { "quote", -1, 1, LispQuote }, + { "lambda", -1, 1, LispLambda }, + { "let", -1, 1, LispLet }, + { "let*", -1, 1, LispLetStar }, + { "letrec", -1, 1, LispLetRec }, + { "cond", -1, 1, LispCond }, + + { "begin", -1, 1, LispBegin }, + + /* define: evaluate only second argument */ + { "define", -1, 2, LispDefine }, + { "set!", -1, 2, LispSetBang }, + + /* if: evaluate only first argument */ + { "if", -1, 3, LispIf }, + + { NULL, 0, 0, NULL } +}; + +static LispObj *evalList (); + + + +/*------------------------------------------------------------------------ + * + * LispFnInit -- + * + * Initialize function table. + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +void +LispFnInit () +{ + int i; + for (i=0; FnTable[i].name; i++) { + (void) LispNewString (FnTable[i].name); + FnTable[i].id = LispStringId (FnTable[i].name); + } +} + + +/*----------------------------------------------------------------------------- + * + * ispair -- + * + * Checks if its argument is a dotted-pair. + * + * Results: + * 1 if dotted-pair, zero otherwise. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +int +ispair (s) + Sexp *s; +{ + while (s && LTYPE(CDR(s)) == S_LIST) + s = LLIST(CDR(s)); + if (s) + return 1; + else + return 0; +} + + +/*------------------------------------------------------------------------ + * + * lookup -- + * + * Lookup a name in a frame. + * + * Results: + * Returns result of lookup. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +LispObj * +lookup (s,f) + char *s; + Sexp *f; +{ + LispObj *l; + Sexp *f1; + int i, k; + + /* keywords have precedence */ + k = LispStringId (s); + for (i=0; FnTable[i].name; i++) + if (FnTable[i].id == k) { + l = LispNewObj (); + LTYPE(l) = S_LAMBDA_BUILTIN; + LBUILTIN(l) = i; + return l; + } + /* look in frame */ + l = LispFrameLookup (s,f); + if (l) return l; + /* assume that it is a magic command */ + l = LispNewObj (); + LTYPE(l) = S_MAGIC_BUILTIN; + LSYM(l) = s; + return l; +} + + +/*------------------------------------------------------------------------ + * + * LispMagicSend -- + * + * Send magic command to magic window. + * + * Results: + * Returns #t if magic command exists, #f otherwise. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ +LispObj * +LispMagicSend (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + int trace; + LispObj *l; + int argc; + char *argv[TX_MAXARGS]; + char argstring[TX_MAX_CMDLEN]; + int k = 0; + int i, j; + + argc = 1; + argv[0] = name; + while (s) { + l = CAR(s); + if (LTYPE(CDR(s)) != S_LIST) { + TxPrintf ("%s: invalid argument!\n",name); + RETURN; + } + s = LLIST(CDR(s)); + switch (LTYPE(l)) { + case S_INT: + argv[argc] = argstring+k; + sprintf (argstring+k, "%d", LINTEGER(l)); + k = k + strlen(argstring+k)+1; + break; + case S_FLOAT: + argv[argc] = argstring+k; + sprintf (argstring+k, "%lf", LFLOAT(l)); + k = k + strlen(argstring+k)+1; + break; + case S_STRING: + /* undo one level of literal parsing . . . */ + argv[argc] = LSTR(l); + i = 0; j = 0; + while (argv[argc][i]) { + if (argv[argc][i] == '\\') + i++; + argv[argc][j] = argv[argc][i]; + i++; j++; + } + argv[argc][j] = '\0'; + break; + case S_BOOL: + argv[argc] = argstring+k; + sprintf (argstring+k, "#%c", LINTEGER(l) ? 't' : 'f'); + k = k + strlen(argstring+k)+1; + break; + case S_SYM: + argv[argc] = LSYM(l); + break; + case S_LAMBDA: + TxPrintf ("%s: Type #proc in magic command argument.\n",name); + RETURN; + break; + case S_LAMBDA_BUILTIN: + argv[argc] = FnTable[LBUILTIN(l)].name; + break; + case S_MAGIC_BUILTIN: + argv[argc] = LSYM(l); + break; + case S_LIST: + TxPrintf ("%s: Type #list in magic command argument.\n",name); + RETURN; + break; + default: + argc--; + break; + } + argc++; + } + l = LispFrameLookup (LispNewString ("scm-trace-magic"), f); + if (!l) + trace = 0; + else if (LTYPE(l) != S_BOOL) { + TxPrintf ("magic-dispatch: scm-trace-magic is not a boolean\n"); + RETURN; + } + else + trace = LBOOL(l); + if (!TxLispDispatch (argc, argv, trace, lispInFile)) + RETURN; + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 1; + return l; +} + + +/*----------------------------------------------------------------------------- + * + * LispApply -- + * + * Evaluate a lambda. + * s = definition of the lambda + * l = list of arguments + * f = frame + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispApply (s,l,f) + Sexp *s; + Sexp *l; + Sexp *f; +{ + int len; + int dp; + Sexp *t, *tp; + int number, anum; + Sexp *arglist; + Sexp *frame; + LispObj *eval; + + number = LINTEGER(ARG1(s)); + arglist = LLIST(ARG2(s)); + dp = ispair (arglist); + frame = LLIST(ARG3(s)); + eval = ARG4(s); + len=0; + tp = NULL; + t = l; + while (t && LTYPE(CDR(t)) == S_LIST) { + tp = t; + t = LLIST(CDR(t)); + len++; + } + anum = (number < 0) ? -number : number; + if (len < anum) { + TxPrintf ("apply: mismatch in # of arguments. Expected %d, got %d\n", + anum, len); + RETURN; + } + t = arglist; + f = LispFramePush (frame); + while (t && LTYPE(CDR(t)) == S_LIST) { + LispAddBinding (CAR(t),LispCopyObj(CAR(l)),f); + t = LLIST(CDR(t)); + l = LLIST(CDR(l)); + } + if (t) { + LispAddBinding (CAR(t),LispCopyObj(CAR(l)),f); + LispAddBinding (CDR(t),LispCopyObj(CDR(l)),f); + } + eval = LispEval (eval, f); + return eval; +} + + + +/*----------------------------------------------------------------------------- + * + * LispBuiltinApply -- + * + * Apply a builtin function to a list + * + * Results: + * The results of the builtin function + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispBuiltinApply (num,s,f) + int num; + Sexp *s; + Sexp *f; +{ + return FnTable[num].f(FnTable[num].name, s, f); +} + + +/*------------------------------------------------------------------------ + * + * evalList -- + * + * Evaluate list + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +static +LispObj * +evalList (s,f) + Sexp *s; + Sexp *f; +{ + LispObj *l; + Sexp *t; + + if (!s) { + l = LispNewObj (); + LTYPE(l) = S_LIST; + LLIST(l) = NULL; + return l; + } + /* evaluate car field */ + s = LispCopySexp (s); + + LispGCAddSexp (s); + CAR(s) = LispEval (CAR(s),f); + LispGCRemoveSexp (s); + + if (!CAR(s)) + return NULL; + + if (LTYPE(CAR(s)) != S_MAGIC_BUILTIN && + LTYPE(CAR(s)) != S_LAMBDA_BUILTIN && + LTYPE(CAR(s)) != S_LAMBDA) { + TxPrintf ("eval: First argument of list is not a procedure.\n"); + TxPrintf ("\t"); + if (CAR(s)) LispPrint (stdout, CAR(s)); + else TxPrintf ("()"); + TxPrintf ("\n"); + RETURN; + } + /* evaluate rest of list, if the car field corresponds to a non-lazy + function. + */ + if (LTYPE(CAR(s)) == S_LAMBDA_BUILTIN) { + LispGCAddSexp (s); + if (FnTable[LBUILTIN(CAR(s))].lazy == 2) { + LispStackPush (FnTable[LBUILTIN(CAR(s))].name); + /* define: evaluate second argument only */ + CDR(s) = LispCopyObj (CDR(s)); + if (LTYPE(CDR(s)) != S_LIST || LLIST(CDR(s)) == NULL) { + TxPrintf ("define: argument error\n"); + LispGCRemoveSexp (s); + RETURNPOP; + } + LLIST(CDR(s)) = LispCopySexp (LLIST(CDR(s))); + t = LLIST(CDR(s)); + if (LTYPE(CDR(t)) != S_LIST || LLIST(CDR(t)) == NULL) { + TxPrintf ("define: argument error\n"); + LispGCRemoveSexp (s); + RETURNPOP; + } + CDR(t) = LispCopyObj (CDR(t)); + LLIST(CDR(t)) = LispCopySexp (LLIST(CDR(t))); + t = LLIST(CDR(t)); + CAR(t) = LispEval (CAR(t),f); + LispStackPop (); + if (!CAR(t)) { + LispGCRemoveSexp (s); + return NULL; + } + } + else if (FnTable[LBUILTIN(CAR(s))].lazy == 3) { + /* if: evaluate first argument only */ + LispStackPush (FnTable[LBUILTIN(CAR(s))].name); + CDR(s) = LispCopyObj (CDR(s)); + if (LTYPE(CDR(s)) != S_LIST || LLIST(CDR(s)) == NULL) { + TxPrintf ("if: argument error\n"); + LispGCRemoveSexp (s); + RETURNPOP; + } + LLIST(CDR(s)) = LispCopySexp (LLIST(CDR(s))); + t = LLIST(CDR(s)); + CAR(t) = LispEval (CAR(t),f); + LispStackPop (); + if (!CAR(t)) { + LispGCRemoveSexp (s); + return NULL; + } + } + LispGCRemoveSexp (s); + } + if (!(LTYPE(CAR(s)) == S_LAMBDA_BUILTIN && FnTable[LBUILTIN(CAR(s))].lazy)) { + LispGCAddSexp (s); + if (LTYPE(CAR(s)) == S_LAMBDA_BUILTIN) + LispStackPush (FnTable[LBUILTIN(CAR(s))].name); + else if (LTYPE(CAR(s)) == S_MAGIC_BUILTIN) + LispStackPush (LSYM(CAR(s))); + else { + char *str; + str = LispFrameRevLookup (CAR(s),f); + LispStackPush (str ? str : "#proc-userdef"); + } + t = s; + while (LTYPE(CDR(t)) == S_LIST && LLIST(CDR(t))) { + CDR(t) = LispCopyObj (CDR(t)); + LLIST(CDR(t)) = LispCopySexp (LLIST(CDR(t))); + t = LLIST(CDR(t)); + CAR(t) = LispEval (CAR(t),f); + if (CAR(t) == NULL) { + LispStackPop (); + LispGCRemoveSexp (s); + return NULL; + } + } + if (LTYPE(CDR(t)) != S_LIST) { + CDR(t) = LispEval (CDR(t),f); + if (CDR(t) == NULL) { + LispStackPop (); + LispGCRemoveSexp (s); + return NULL; + } + } + LispStackPop (); + LispGCRemoveSexp (s); + } + if (LTYPE(CDR(s)) != S_LIST) { + /* a dotted pair . . . */ + l = LispNewObj (); + LTYPE(l) = S_LIST; + LLIST(l) = s; + return l; + } + /* dispatch function */ + if (LTYPE(CAR(s)) == S_LAMBDA_BUILTIN) { + LispStackPush (FnTable[LBUILTIN(CAR(s))].name); + l = LispBuiltinApply (LBUILTIN(CAR(s)), LLIST(CDR(s)), f); + LispStackPop (); + } + else if (LTYPE(CAR(s)) == S_LAMBDA) { + char *str; + str = LispFrameRevLookup (CAR(s),f); + LispStackPush (str ? str : "#proc-userdef"); + l = LispApply (LUSERDEF(CAR(s)), LLIST(CDR(s)),f); + LispStackPop (); + } + else { + LispStackPush (LSYM(CAR(s))); + l = LispMagicSend (LSYM(CAR(s)),LLIST(CDR(s)), f); + LispStackPop (); + } + return l; +} + + + + +/*------------------------------------------------------------------------ + * + * LispEval -- + * + * Evaluate object in a frame. + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +LispObj * +LispEval (l,f) + LispObj *l; + Sexp *f; +{ + LispObj *ret; + + if (SigInterruptPending) return NULL; + + if (LTYPE(l) == S_LIST) { + LispGCAddSexp (f); + ret = evalList (LLIST(l),f); + LispGCRemoveSexp (f); + return ret; + } + else if (LTYPE(l) == S_SYM) + return lookup (LSYM(l),f); + else + return l; +} diff --git a/lisp/lispFrame.c b/lisp/lispFrame.c new file mode 100644 index 00000000..4b8afb76 --- /dev/null +++ b/lisp/lispFrame.c @@ -0,0 +1,302 @@ +/************************************************************************* + * + * lispFrame.c -- + * + * This module contains routines that muck around with frames. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispFrame.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + + +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "textio/textio.h" +#include "utils/malloc.h" + +/*------------------------------------------------------------------------ + * + * A frame is a list of a list of dotted-pairs. + * Each dotted-pair is a ( name . binding ). + * + *------------------------------------------------------------------------ + */ + +Sexp *LispMainFrame = NULL; /* toplevel frame */ +LispObj *LispMainFrameObj = NULL; + +/*----------------------------------------------------------------------------- + * + * LispFrameInit -- + * + * Initialize top-level frame. + * + * Results: + * None. + * + * Side effects: + * modifies LispMainFrame + * + *----------------------------------------------------------------------------- + */ + +void +LispFrameInit () +{ + LispMainFrame = LispNewSexp (); + CAR(LispMainFrame) = LispNewObj (); + CDR(LispMainFrame) = LispNewObj (); + LTYPE(CAR(LispMainFrame)) = S_LIST; + LTYPE(CDR(LispMainFrame)) = S_LIST; + LLIST(CAR(LispMainFrame)) = NULL; + LLIST(CDR(LispMainFrame)) = NULL; + + LispGCAddSexp (LispMainFrame); +} + + +/* + returns (name val) thing if exists, else null +*/ +static +Sexp * +findbinding (name,f) + char *name; + Sexp *f; +{ + Sexp *t, *t1; + + t = f; + while (t) { + t1 = LLIST(CAR(t)); + while (t1) { + if (LSYM(CAR(LLIST(CAR(t1)))) == name) + return LLIST(CAR(t1)); + t1 = LLIST(CDR(t1)); + } + t = LLIST(CDR(t)); + } + return NULL; +} + + + +/* + returns (name val) thing if exists, else null +*/ +static +Sexp * +revfindbinding (l,f) + LispObj *l; + Sexp *f; +{ + Sexp *t, *t1; + + t = f; + while (t) { + t1 = LLIST(CAR(t)); + while (t1) { + if (CDR(LLIST(CAR(t1))) == l) + return LLIST(CAR(t1)); + t1 = LLIST(CDR(t1)); + } + t = LLIST(CDR(t)); + } + return NULL; +} + + +/*------------------------------------------------------------------------ + * + * LispFrameLookup -- + * + * Lookup symbol in frame. The arguments must be canonicalized using + * the LispNewString() function, since string comparisons are done + * using pointer equality. + * + * Results: + * Returns pointer to symbol if found, NULL otherwise. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +LispObj * +LispFrameLookup (s,f) + char *s; + Sexp *f; +{ + Sexp *f1; + f1 = findbinding (s,f); + if (!f1) + return NULL; + else + return CDR(f1); +} + + +/*------------------------------------------------------------------------ + * + * LispFrameRevLookup -- + * + * Lookup object in frame. This returns the symbol corresponding to + * the object. Used for debugging purposes. + * + * Results: + * Returns symbol if found, NULL otherwise. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +char * +LispFrameRevLookup (l,f) + LispObj *l; + Sexp *f; +{ + Sexp *f1; + f1 = revfindbinding (l,f); + if (!f1) + return NULL; + else + return LSYM(CAR(f1)); +} + + + +/*------------------------------------------------------------------------ + * + * LispAddBinding -- + * + * Add a ( name . value ) binding to the frame. + * + * Results: + * modifies the frame. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +void +LispAddBinding (name,val,f) + LispObj *name; + LispObj *val; + Sexp *f; +{ + Sexp *t; + LispObj *l; + + if (LTYPE(name) != S_SYM) { + TxPrintf ("LispAddBinding: invalid argument!\n"); + return; + } + if (f) { + t = LLIST(CAR(f)); + while (t) { + if (LSYM(name) == LSYM(CAR(LLIST(CAR(t))))) { + CDR(LLIST(CAR(t))) = val; + return; + } + t = LLIST(CDR(t)); + } + } + t = LispNewSexp (); + CAR(t) = name; + CDR(t) = val; + l = LispNewObj (); + LTYPE(l) = S_LIST; + LLIST(l) = t; + t = LispNewSexp (); + CAR(t) = l; + CDR(t) = CAR(f); + l = LispNewObj (); + LTYPE(l) = S_LIST; + LLIST(l) = t; + CAR(f) = l; +} + + +/*------------------------------------------------------------------------ + * + * LispModifyBinding -- + * + * Modify a ( name . value ) binding from the frame. + * + * Results: + * Returns 0 on failure, and non-zero on success. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +int +LispModifyBinding (name,val,f) + LispObj *name; + LispObj *val; + Sexp *f; +{ + Sexp *t; + LispObj *l; + + if (LTYPE(name) != S_SYM) return 0; + if (t = findbinding (LSYM(name),f)) { + CDR(t) = val; + return 1; + } + return 0; +} + + +/*----------------------------------------------------------------------------- + * + * LispFramePush -- + * + * Return a new frame which consists of the old frame augmented by + * the empty list. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +Sexp * +LispFramePush (f) + Sexp *f; +{ + Sexp *nf; + nf = LispNewSexp (); + CAR(nf) = LispNewObj (); + CDR(nf) = LispNewObj (); + LTYPE(CAR(nf)) = S_LIST; + LLIST(CAR(nf)) = NULL; + LTYPE(CDR(nf)) = S_LIST; + LLIST(CDR(nf)) = f; + return nf; +} diff --git a/lisp/lispGC.c b/lisp/lispGC.c new file mode 100644 index 00000000..509943cf --- /dev/null +++ b/lisp/lispGC.c @@ -0,0 +1,584 @@ +/************************************************************************* + * + * lispGC.c -- + * + * This module contains the garbage collector. + * (N.B. This is really inefficient!) + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispGC.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include +#include +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "lispargs.h" + +/* + garbage collection trickery. :) +*/ +#define GC_TO_PTR(type,x) ((type)(((unsigned long) x) & ~3)) + +#define GC_SWMARK(type,x,v) x=(type)((((unsigned long)x)&~3) | ((v)&3)) +#define GC_SWMARKED(x,v) ((((unsigned long) x)&3) == (v)) +#define GC_MARKVAL(x) (((unsigned long)x)&3) + +#define GC_MARK(type,x) GC_SWMARK(type,x,1) +#define GC_UNMARK(type,x) GC_SWMARK(type,x,0) +#define GC_MARKED(x) GC_SWMARKED(x,1) + +static Sexp *SexpMainAllocQ = NULL; +static Sexp *SexpMainAllocQTail = NULL; + +static Sexp *SexpAllocQ = NULL; +static Sexp *SexpAllocQTail = NULL; + +static Sexp *SexpFreeQ = NULL; +static Sexp *SexpFreeQTail = NULL; + +static LispObj *LispObjMainAllocQ = NULL; +static LispObj *LispObjMainAllocQTail = NULL; + +static LispObj *LispObjAllocQ = NULL; +static LispObj *LispObjAllocQTail = NULL; + +static LispObj *LispObjFreeQ = NULL; +static LispObj *LispObjFreeQTail = NULL; + +static Sexp *MarkedSexpQ; +static LispObj *MarkedObjQ; + +int LispGCHasWork; +int LispCollectAllocQ; + +/*----------------------------------------------------------------------------- + * + * LispNewObj -- + * + * Get a new object from the free list. + * + * Results: + * Returns the new object. + * + * Side effects: + * Modifies free list. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispNewObj () +{ + LispObj *s; + if (LispObjFreeQ) { + s = LispObjFreeQ; + LispObjFreeQ = LispObjFreeQ->n; + if (LTYPE(s) == S_STRING) + freeMagic(LSTR(s)); + } + else { + s = (LispObj *) mallocMagic((unsigned) (sizeof(LispObj))); + } + s->t = S_INT; + s->u.l = NULL; + if (!LispObjAllocQ) + LispObjAllocQTail = s; + s->n = LispObjAllocQ; + LispObjAllocQ = s; + return s; +} + + +/*----------------------------------------------------------------------------- + * + * LispCopyObj -- + * + * Create a copy of an object. + * + * Results: + * Returns the new object. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispCopyObj (l) + LispObj *l; +{ + LispObj *s; + s = LispNewObj (); + LTYPE(s) = LTYPE(l); + switch (LTYPE(s)) { + case S_LIST: + LLIST(s) = LLIST(l); + break; + case S_SYM: + LSYM(s) = LSYM(l); + break; + case S_MAGIC_BUILTIN: + LSYM(s) = LSYM(l); + break; + case S_LAMBDA_BUILTIN: + LBUILTIN(s) = LBUILTIN(l); + break; + case S_LAMBDA: + LUSERDEF(s) = LUSERDEF(l); + break; + case S_INT: + LINTEGER(s) = LINTEGER(l); + break; + case S_FLOAT: + LFLOAT(s) = LFLOAT(l); + break; + case S_STRING: + LSTR(s) = (char *) mallocMagic((unsigned) (strlen(LSTR(l))+1)); + strcpy (LSTR(s),LSTR(l)); + break; + case S_BOOL: + LBOOL(s) = LBOOL(l); + break; + default: + TxError ("Fatal error in copy-object!\n"); + break; + } + return s; +} + + +/*----------------------------------------------------------------------------- + * + * LispNewSexp -- + * + * Get a Sexp from the free list. + * + * Results: + * Returns the new Sexp. + * + * Side effects: + * Modifies the free list. + * + *----------------------------------------------------------------------------- + */ + +Sexp * +LispNewSexp () +{ + Sexp *s; + if (SexpFreeQ) { + s = SexpFreeQ; + SexpFreeQ = SexpFreeQ->n; + } + else { + s = (Sexp *) mallocMagic((unsigned) (sizeof(Sexp))); + } + CAR(s) = NULL; + CDR(s) = NULL; + if (!SexpAllocQ) + SexpAllocQTail = s; + s->n = SexpAllocQ; + SexpAllocQ = s; + return s; +} + +/*----------------------------------------------------------------------------- + * + * LispCopySexp -- + * + * Return a copy of an Sexp. + * + * Results: + * Returns the new Sexp. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +Sexp * +LispCopySexp (s) + Sexp *s; +{ + Sexp *t; + t = LispNewSexp (); + CAR(t) = CAR(s); + CDR(t) = CDR(s); + return t; +} + + +/*========================================================================*/ + +/* + * + * + * The garbage collector is rather interesting. It has two modes of + * operation. When evaluation has not executed any "define", "set!", + * "set-car!", or "set-cdr!" commands (the only ones which have side-effects), + * everything allocated during the last evaluation is collected without + * running a marking algorithm. As a result, normal magic commands will + * be executed with O(1) garbage collection overhead. Note that strings + * are free'd when the object is reused. + * + * Scheme functions without side-effects will also execute with O(1) + * garbage collection overhead. + * + * The full mark/collect algorithm is executed once every 50 times the + * real garbage collector is called :P This "constant-factor" + * speedup actually makes a big difference in practice. + * + * The marking algorithm is O(NUSE), where NUSE = # of used nodes. We use + * the Schorr-Waite-Deutch algorithm for a non-recursive traversal of the + * nodes in use. + * + * The collection phase is O(NALLOC), where NALLOC = # of allocated nodes. + * It could be reduced to O(NUSE) by changing the allocation list to one + * that is doubly-linked. + * + * + */ + + +/* + * + * Merge the main and current alloc q into the current alloc q. + * + */ +static +void +mergealloc () +{ + Sexp *s; + LispObj *l; + + if (!SexpAllocQ) { + SexpAllocQ = SexpMainAllocQ; + SexpAllocQTail = SexpMainAllocQTail; + } + else { + SexpAllocQTail->n = SexpMainAllocQ; + if (SexpMainAllocQ) + SexpAllocQTail = SexpMainAllocQTail; + } + if (!LispObjAllocQ) { + LispObjAllocQ = LispObjMainAllocQ; + LispObjAllocQTail = LispObjMainAllocQTail; + } + else { + LispObjAllocQTail->n = LispObjMainAllocQ; + if (LispObjMainAllocQ) + LispObjAllocQTail = LispObjMainAllocQTail; + } +} + + +#define NIL(x) ((LTYPE(x) != S_LIST && LTYPE(x) != S_LAMBDA) || (LLIST(x) == NULL)) + +static +void +mark_sw (l) + LispObj *l; +{ + LispObj *m; + LispObj *t0,*t1,*t2,*t3; + int mark; + + /* mark all the nodes */ + m = NULL; + while (l != NULL) { + GC_SWMARK(LispObj *, l->n, 1); + GC_SWMARK(Sexp *, LLIST(l)->n, GC_MARKVAL (LLIST(l)->n)+1); + if (GC_MARKVAL(LLIST(l)->n) == 3 || + (!NIL(CAR(LLIST(l))) && GC_MARKVAL(LLIST(CAR(LLIST(l)))->n) == 0)) { + t0=l; t1=CAR(LLIST(l)); t2=CDR(LLIST(l)); t3=m; + CAR(LLIST(l))=t2; CDR(LLIST(l))=t3; m=t0; l=t1; + } + else { + GC_SWMARK (LispObj *, CAR(LLIST(l))->n, 1); + t0=CAR(LLIST(l)); t1=CDR(LLIST(l)); t2=m; + CAR(LLIST(l))=t1; CDR(LLIST(l))=t2; m=t0; + } + } +} + +static +void +collect_sw () +{ + /* all marked objects have non-zero mark */ + /* stoll through the alloc Q and split it into two things: + freeQ, mainallocQ + */ + SexpMainAllocQ = NULL; + while (SexpAllocQ) { + if (GC_MARKVAL (SexpAllocQ->n) != 0) { + /* used */ + if (!SexpMainAllocQ) { + SexpMainAllocQ = SexpAllocQ; + SexpMainAllocQTail = SexpAllocQ; + } + else { + SexpMainAllocQTail->n = SexpAllocQ; + SexpMainAllocQTail = SexpAllocQ; + } + } + else { + if (!SexpFreeQ) { + SexpFreeQ = SexpAllocQ; + SexpFreeQTail = SexpAllocQ; + } + else { + SexpFreeQTail->n = SexpAllocQ; + SexpFreeQTail = SexpAllocQ; + } + } + SexpAllocQ = GC_TO_PTR(Sexp*, SexpAllocQ->n); + } + if (SexpFreeQ) + SexpFreeQTail->n = NULL; + if (SexpMainAllocQ) + SexpMainAllocQTail->n = NULL; + SexpAllocQ = NULL; + + LispObjMainAllocQ = NULL; + while (LispObjAllocQ) { + if (GC_MARKVAL (LispObjAllocQ->n) != 0) { + /* used */ + if (!LispObjMainAllocQ) { + LispObjMainAllocQ = LispObjAllocQ; + LispObjMainAllocQTail = LispObjAllocQ; + } + else { + LispObjMainAllocQTail->n = LispObjAllocQ; + LispObjMainAllocQTail = LispObjAllocQ; + } + } + else { + if (LTYPE(LispObjAllocQ) == S_STRING) { + freeMagic(LSTR(LispObjAllocQ)); + LTYPE(LispObjAllocQ) = S_INT; + } + if (!LispObjFreeQ) { + LispObjFreeQ = LispObjAllocQ; + LispObjFreeQTail = LispObjAllocQ; + } + else { + LispObjFreeQTail->n = LispObjAllocQ; + LispObjFreeQTail = LispObjAllocQ; + } + } + LispObjAllocQ = GC_TO_PTR(LispObj*, LispObjAllocQ->n); + } + if (LispObjFreeQ) + LispObjFreeQTail->n = NULL; + if (LispObjMainAllocQ) + LispObjMainAllocQTail->n = NULL; + LispObjAllocQ = NULL; +} + + +/*----------------------------------------------------------------------------- + * + * LispGC -- + * + * Run the garbage collector, assuming all reachable nodes are reachable + * from the Sexp passed to the garbage collector. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +static int skip_gc = 50; /* make this bigger if it is too slow :) */ + +void +LispGC (fl) + LispObj *fl; +{ + LispObj *l; + + if (LispCollectAllocQ) { + /* + * The last evaluation did not have any side-effects. + * Collect everything allocated on the last pass and put it + * back into the free list. + * + */ + if (LispObjFreeQ) { + LispObjFreeQTail->n = LispObjAllocQ; + if (LispObjAllocQ) + LispObjFreeQTail = LispObjAllocQTail; + } + else { + LispObjFreeQ = LispObjAllocQ; + LispObjFreeQTail = LispObjAllocQTail; + } + if (SexpFreeQ) { + SexpFreeQTail->n = SexpAllocQ; + if (SexpAllocQ) + SexpFreeQTail = SexpAllocQTail; + } + else { + SexpFreeQ = SexpAllocQ; + SexpFreeQTail = SexpAllocQTail; + } + LispObjAllocQ = NULL; + SexpAllocQ = NULL; + return; + } + if (skip_gc-- > 0) { + LispGCHasWork = 1; + mergealloc (); + SexpMainAllocQ = SexpAllocQ; + SexpMainAllocQTail = SexpAllocQTail; + LispObjMainAllocQ = LispObjAllocQ; + LispObjMainAllocQTail = LispObjAllocQTail; + SexpAllocQ = NULL; + LispObjAllocQ = NULL; + return; + } + skip_gc = 50; + + if (fl) { + extern Sexp *LispMainFrame; + + l = LispFrameLookup (LispNewString ("scm-gc-frequency"), LispMainFrame); + if (l && LTYPE(l) == S_INT && LINTEGER(l) >= 0) + skip_gc = LINTEGER(l); + } + + if (fl) { + mergealloc (); + mark_sw(fl); + collect_sw (); + LispObjAllocQ = NULL; + } + LispGCHasWork = 0; +} + + +/*----------------------------------------------------------------------------- + * + * LispCollectGarbage -- + * + * Force garbage collection after this evaluation. + * + * Results: + * Returns #t + * + * Side effects: + * none. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispCollectGarbage (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + extern LispObj *LispMainFrameObj; + + if (ARG1P(s)) { + TxPrintf ("Usage: (%s)\n", name); + RETURN; + } + skip_gc = 0; + LispCollectAllocQ = 0; + LispGC (LispMainFrameObj); + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 1; + return l; +} + + + +/*------------------------------------------------------------------------ + * + * LispGCAddSexp -- + * + * Add an sexp to the list of roots used for garbage collection. + * + * Results: + * None. + * + * Side effects: + * Modifies LispMainFrameObj list. + * + *------------------------------------------------------------------------ + */ + +void LispGCAddSexp (s) + Sexp *s; +{ + extern LispObj *LispMainFrameObj; + Sexp *t; + + t = LispNewSexp (); + CAR(t) = LispNewObj (); + LTYPE(CAR(t)) = S_LIST; + LLIST(CAR(t)) = s; + CDR(t) = LispMainFrameObj; + + LispMainFrameObj = LispNewObj (); + LTYPE(LispMainFrameObj) = S_LIST; + LLIST(LispMainFrameObj) = t; +} + + + +/*------------------------------------------------------------------------ + * + * LispGCRemoveSexp -- + * + * Remove an Sexp from the list of roots for garbage collection. + * + * Results: + * None. + * + * Side effects: + * Modifies LispMainFrameObj list. + * + *------------------------------------------------------------------------ + */ + +void LispGCRemoveSexp (s) + Sexp *s; +{ + extern LispObj *LispMainFrameObj; + LispObj *l; + + if (LLIST(CAR(LLIST(LispMainFrameObj))) != s) { + TxError ("Fatal internal error. Proceed at your own risk!\n"); + return; + } + + LispMainFrameObj = CDR(LLIST(LispMainFrameObj)); +} diff --git a/lisp/lispIO.c b/lisp/lispIO.c new file mode 100644 index 00000000..4d12d019 --- /dev/null +++ b/lisp/lispIO.c @@ -0,0 +1,381 @@ +/************************************************************************* + * + * lispIO.c -- + * + * This module contains the builtin mini-scheme I/O functions. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispIO.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "lispargs.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "utils/utils.h" +#include "utils/signals.h" + +/*----------------------------------------------------------------------------- + * + * LispLoad -- + * + * ("load-scm" "filename") + * Reads and evaluates file. + * + * + * Results: + * #t => file was opened successfully. + * #f => failure. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispLoad (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + extern int LispEchoResult; + LispObj *l, *inp, *res; + FILE *fp; + int val, pos; + char *buffer, *tmp; + int buflen; + int nest; + int line; + + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || ARG2P(s)) { + TxPrintf ("Usage: (%s string)\n", name); + RETURN; + } + l = LispFrameLookup (LispNewString ("scm-library-path"), f); + if (!l) + tmp = NULL; + else if (LTYPE(l) != S_STRING) { + TxPrintf ("%s: scm-library-path is not a string\n", name); + RETURN; + } + else + tmp = LSTR(l); + if (!(fp = PaOpen (LSTR(ARG1(s)), "r", NULL, ".", tmp, NULL))) { + TxPrintf ("%s: could not open file %s for reading\n",name,LSTR(ARG1(s))); + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 0; + RETURN; + } + + LispGCAddSexp (s); + + buffer = (char *) mallocMagic((unsigned) (buflen = 4096)); + pos = 0; + nest = 0; + line = 1; + while ((val = fgetc (fp)) != EOF) { + if (pos == buflen) { + int i; + /* extend buffer */ + tmp = buffer; + buflen += 1024; + buffer = (char *) mallocMagic((unsigned) buflen); + for (i=0; i < pos; i++) + buffer[i] = tmp[i]; + freeMagic(tmp); + } + if (val == ';') { + /* skip to eol */ + while ((val = fgetc(fp)) != EOF && val != '\n') + ; + if (val == '\n') line++; + continue; + } + if (val == '\n') line++; + if (val == '\t' || val == '\n') val = ' '; + /* skip white space at nesting level zero */ + if (nest == 0 && isspace (val)) + continue; + if (nest == 0 && val != '(') { + TxPrintf ("Error reading file %s, line %d\n", LSTR(ARG1(s)), line); + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 0; + freeMagic(buffer); + fclose (fp); + LispGCRemoveSexp (s); + RETURN; + } + buffer[pos++] = val; + if (val == '(') + nest++; + else if (val == ')') { + nest--; + if (nest == 0) { + buffer[pos] = '\0'; + inp = LispParseString (buffer); + if (inp) { + res = LispEval (inp, f); + inp = LispFrameLookup (LispNewString ("scm-echo-result"), f); + if (res && inp && LTYPE(inp) == S_BOOL && LBOOL(inp)) { + LispPrint (stdout,res); + TxPrintf ("\n"); + } + if (!res) { + if (!SigInterruptPending) + TxPrintf ("Error evaluating file %s, line %d\n", + LSTR(ARG1(s)), line); + freeMagic(buffer); + fclose (fp); + LispGCRemoveSexp (s); + RETURN; + } + } + else { + TxPrintf ("Error parsing file %s, line %d\n", LSTR(ARG1(s)), line); + freeMagic(buffer); + fclose (fp); + LispGCRemoveSexp (s); + RETURN; + } + pos = 0; + } + if (nest < 0) { + TxPrintf ("Error reading file %s, line %d\n", LSTR(ARG1(s)), line); + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 0; + freeMagic(buffer); + fclose (fp); + LispGCRemoveSexp (s); + return l; + } + } + else if (val == '\"') { + while ((val = fgetc (fp)) != EOF && val != '\"') { + if (val == '\n') line++; + if (pos > buflen-1) { + /* extend buffer */ + int i; + tmp = buffer; + buflen += 1024; + buffer = (char *) mallocMagic((unsigned) (buflen)); + for (i=0; i < pos; i++) + buffer[i] = tmp[i]; + freeMagic(tmp); + } + buffer[pos++] = val; + if (val == '\\') { + val = fgetc (fp); + buffer[pos++] = val; + if (val == '\n') line++; + } + } + if (val == EOF) { + TxPrintf ("Error reading file %s, line %d\n", LSTR(ARG1(s)), line); + freeMagic(buffer); + fclose (fp); + LispGCRemoveSexp (s); + RETURN; + } + buffer[pos++] = val; + } + } + freeMagic(buffer); + fclose (fp); + if (pos > 0) { + TxPrintf ("Error reading file %s, line %d\n", LSTR(ARG1(s)), line); + LispGCRemoveSexp (s); + RETURN; + } + else { + LispGCRemoveSexp (s); + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 1; + } + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispWrite -- + * + * Write an object to a file. + * + * Results: + * none. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispWrite (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + FILE *fp; + LispObj *l; + + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || !ARG2P(s) || ARG3P(s)) { + TxPrintf ("Usage: (%s str obj)\n", name); + RETURN; + } + if (!(fp = PaOpen (LSTR(ARG1(s)), "a", NULL, ".", NULL, NULL))) { + TxPrintf ("%s: could not open file %s for writing\n",name,LSTR(ARG1(s))); + RETURN; + } + fprintf (fp, ";\n"); + LispPrint (fp,ARG2(s)); + fprintf (fp, "\n"); + fclose (fp); + l = LispNewObj (); + LTYPE(l) = S_BOOL; + LBOOL(l) = 1; + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispSpawn -- + * + * (spawn list-of-strings) + * Reads and evaluates file. + * + * + * Results: + * pid => the pid of the spawned process. + * -1 => if spawn failed. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispSpawn (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + int pid; + Sexp *t; + char **argv; + int n; + + if (!ARG1P(s)) { + TxPrintf ("Usage: (%s string-list)\n", name); + RETURN; + } + + t = s; + n = 1; + while (ARG1P(t)) { + if (LTYPE(CAR(t)) != S_STRING) { + TxPrintf ("Usage: (%s string-list)\n", name); + RETURN; + } + n++; + t = LLIST(CDR(t)); + } + argv = (char **) mallocMagic((unsigned) (sizeof(char*)*n)); + t = s; + n = 0; + while (ARG1P(t)) { + argv[n] = LSTR(CAR(t)); + n++; + t = LLIST(CDR(t)); + } + argv[n] = NULL; + + FORK_f(pid); + if (pid < 0) { + TxPrintf ("Error: could not fork a process!\n"); + freeMagic(argv); + RETURN; + } + else if (pid == 0) { + int i; + /* try closing all files, so that we don't mess up the state of + the parent */ + for (i=3; i < 256; i++) + close (i); + execvp (argv[0], argv); + _exit (1000); + } + freeMagic(argv); + l = LispNewObj (); + LTYPE(l) = S_INT; + LINTEGER(l) = pid; + return l; +} + + +/*----------------------------------------------------------------------------- + * + * LispWait -- + * + * (wait pid) + * Wait for pid to terminate. + * + * Results: + * The status, error if the pid is an invalid pid. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispWait (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + int stat; + + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_INT) { + TxPrintf ("Usage: (%s pid)\n", name); + RETURN; + } + + if (WaitPid (LINTEGER(ARG1(s)), &stat) < 0) { + TxPrintf ("%s: waiting for an invalid pid\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_INT; + LINTEGER(l) = stat; + return l; +} diff --git a/lisp/lispInt.h b/lisp/lispInt.h new file mode 100644 index 00000000..a7fc178a --- /dev/null +++ b/lisp/lispInt.h @@ -0,0 +1,150 @@ +/************************************************************************* + * + * lispInt.h -- + * + * Internals of the lisp module. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispInt.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ +#ifndef __LISPINT_H__ +#define __LISPINT_H__ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "textio/txcommands.h" + +/* + Lisp Sexp's are allocated in blocks of the following size +*/ +#define LISP_SEXP_BLKSZ 1000 +#define LISP_MAX_LEN (TX_MAX_CMDLEN+3) + + +enum Sexp_types { + S_LIST, + S_SYM, + S_MAGIC_BUILTIN, + S_LAMBDA_BUILTIN, + S_LAMBDA, + S_INT, + S_FLOAT, + S_STRING, + S_BOOL +}; + +#define ATOM(t) ((t) == S_INT || (t) == S_FLOAT || \ + (t) == S_STRING || (t) == S_BOOL) + + +#define LTYPE(l) ((l)->t) +#define LLIST(m) ((m)->u.l) +#define LUSERDEF(m) ((m)->u.l) +#define LBUILTIN(m) ((m)->u.i) +#define LSYM(l) ((l)->u.s) +#define LSTR(l) ((l)->u.s) +#define LBOOL(l) ((l)->u.i) +#define LFLOAT(l) ((l)->u.d) +#define LINTEGER(l) ((l)->u.i) + +#define TYPECAR(s) LTYPE((s)->l[0]) +#define TYPECDR(s) LTYPE((s)->l[1]) + +#define LCAR(s) LLIST(CAR(s)) +#define SYMCAR(s) LSYM((s)->l[0]) +#define STRCAR(s) LSTR((s)->l[0]) +#define INTCAR(s) LINTEGER((s)->l[0]) +#define FLOATCAR(s) LFLOAT((s)->l[0]) +#define BOOLCAR(s) LBOOL((s)->l[0]) + +#define LCDR(s) LLIST((s)->l[1]) +#define SYMCDR(s) LSYM((s)->l[1]) +#define STRCDR(s) LSTR((s)->l[1]) +#define INTCDR(s) LINTEGER((s)->l[1]) +#define FLOATCDR(s) LFLOAT((s)->l[1]) +#define BOOLCDR(s) LBOOL((s)->l[1]) + +#define CAR(s) ((s)->l[0]) +#define CDR(s) ((s)->l[1]) + + + +#define NBITS (sizeof(unsigned int)*8) + +struct Sexp; + +typedef struct LispObj { + struct LispObj *n; + unsigned char t; /* type */ + union { + struct Sexp *l; + int i; + double d; + char *s; + } u; +} LispObj; + +typedef struct Sexp { + struct Sexp *n; + LispObj *l[2]; +} Sexp; + +/* + * Internal commands + */ +extern void LispDispatch(); + +extern LispObj *LispNewObj (); +extern LispObj *LispCopyObj (); +extern Sexp *LispNewSexp (); +extern Sexp *LispCopySexp (); + +extern LispObj *LispEval (); +extern LispObj *LispApply (); +extern LispObj *LispMagicSend (); +extern LispObj *LispBuiltinApply (); +extern void LispPrint (); +extern void LispPrintType (); + +extern LispObj *LispParseString (); +extern LispObj *LispAtomParse (); +extern char *LispNewString (); +extern int LispStringId (); +extern void LispFnInit (); + +extern void LispGC (); +extern int LispGCHasWork; +extern int LispCollectAllocQ; +extern void LispGCAddSexp (); +extern void LispGCRemoveSexp (); + +extern LispObj *LispFrameLookup (); +extern char *LispFrameRevLookup (); +extern void LispFrameInit (); +extern int LispModifyFrame (); +extern void LispAddBinding (); +extern Sexp *LispFramePush (); + +extern void LispStackPush (); +extern void LispStackPop (); +extern void LispStackDisplay (); +extern void LispStackClear (); + +extern int lispInFile; /* flag used for :setpoint */ + +#endif /* __LISPINT_H__ */ diff --git a/lisp/lispMagic.c b/lisp/lispMagic.c new file mode 100644 index 00000000..06fc5a27 --- /dev/null +++ b/lisp/lispMagic.c @@ -0,0 +1,589 @@ +/************************************************************************* + * + * lispMagic.c -- + * + * This module contains the builtin mini-scheme functions that interact + * with magic's data structures. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispMagic.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "lispargs.h" +#include "utils/geofast.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" +#include "commands/commands.h" +#include "utils/utils.h" +#include "select/select.h" + + +static LispObj *_internal_list; + +/*------------------------------------------------------------------------ + * + * LispGetbox -- + * + * Returns a list with (llx,lly,urx,ury) corresponding to the current + * box, or #f if the command failed otherwise. + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + * + *------------------------------------------------------------------------ + */ + +LispObj * +LispGetbox (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + Rect editbox; + Rect rootBox; + CellDef *rootBoxDef; + + if (ARG1P(s)) { + TxPrintf ("Usage: (%s)\n", name); + RETURN; + } + /* + This code adapted from the commands/CmdAB.c code for + "box" + */ + if (!ToolGetBox (&rootBoxDef, &rootBox)) { + TxPrintf ("%s: Box tool must be present\n", name); + RETURN; + } + if (EditRootDef == rootBoxDef) + { + char buf[128]; + + (void) ToolGetEditBox(&editbox); + sprintf (buf, "(%d %d %d %d)", editbox.r_xbot, editbox.r_ybot, + editbox.r_xtop, editbox.r_ytop); + return LispParseString (buf); + } + else + { + TxPrintf ("%s: box not in cell being edited.\n",name); + RETURN; + } +} + + +/*------------------------------------------------------------------------ + * + * LispGetPoint -- + * + * Returns a list with (x,y) corresponding to the current point + * + * Results: + * Returns result of evaluation. + * + * Side effects: + * None. + * + * + *------------------------------------------------------------------------ + */ + +LispObj * +LispGetPoint (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + MagWindow *w; + char buf[128]; + Rect editRect, rootRect; + CellDef *rootDef; + extern TxCommand *WindCurrentCmd; + + if (ARG1P(s)) { + TxPrintf ("Usage: (%s)\n", name); + RETURN; + } + + if ((w = ToolGetPoint((Point *) NULL, &rootRect)) != (MagWindow *) NULL) + { + rootDef = ((CellUse *)w->w_surfaceID)->cu_def; + if (EditRootDef == rootDef) + { + GeoTransRect(&RootToEditTransform, &rootRect, &editRect); + sprintf (buf, "(%d %d %d %d)", editRect.r_xbot, editRect.r_ybot, + WindCurrentCmd->tx_p.p_x, WindCurrentCmd->tx_p.p_y); + } + else { + sprintf (buf, "(%d %d %d %d)", rootRect.r_xbot, rootRect.r_ybot, + WindCurrentCmd->tx_p.p_x, WindCurrentCmd->tx_p.p_y); + } + } + else { + TxPrintf ("%s: point is not in a window\n", name); + RETURN; + } + return LispParseString (buf); +} + + +/*----------------------------------------------------------------------------- + * + * LispGetPaint -- + * + * Get paint under the current box for a particular layer. + * + * Results: + * List containing paint description. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +static int +lispprinttile (tile,cxp) + Tile *tile; + TreeContext *cxp; +{ + TileType type; + Transform tt; + Rect sourceRect, targetRect; + Rect *arg; + SearchContext *scx = cxp->tc_scx; + LispObj *l; + static char getpaint_buf[128]; + + if ((type = TiGetType(tile)) == TT_SPACE) + return 0; + + TITORECT(tile, &targetRect); + + /* Transform to target coordinates */ + GEOTRANSRECT(&scx->scx_trans, &targetRect, &sourceRect); + + /* Clip against the target area */ + arg = (Rect *) cxp->tc_filter->tf_arg; + + GEOCLIP(&sourceRect, arg); + + /* go to edit coordinates from root coordinates */ + GEOTRANSRECT (&RootToEditTransform, &sourceRect, &targetRect); + + sprintf (getpaint_buf, "((\"%s\" %d %d %d %d))", + DBTypeShortName (type), + targetRect.r_xbot, targetRect.r_ybot, + targetRect.r_xtop, targetRect.r_ytop); + l = LispParseString (getpaint_buf); + CDR(LLIST(l)) = _internal_list; + _internal_list = l; + return 0; +} + + +LispObj * +LispGetPaint (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + SearchContext scx; + TileTypeBitMask mask; + int windowMask, xMask; + DBWclientRec *crec; + MagWindow *window; + CellUse *PaintUse, *u; + CellDef *def; + + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || ARG2P(s)) { + TxPrintf ("Usage: (%s str)\n", name); + RETURN; + } + bzero (&scx, sizeof(SearchContext)); + window = ToolGetBoxWindow (&scx.scx_area, &windowMask); + if (window == NULL) { + TxPrintf ("%s: Box tool must be present.\n", name); + RETURN; + } + xMask = ((DBWclientRec *) window->w_clientData)->dbw_bitmask; + if ((windowMask & ~xMask) != 0) + { + window = CmdGetRootPoint((Point *) NULL, (Rect *) NULL); + xMask = ((DBWclientRec *) window->w_clientData)->dbw_bitmask; + if ((windowMask & xMask) == 0) + { + TxPrintf("The box is in more than one window; use the cursor\n"); + TxPrintf("to select the one you want to select from.\n"); + RETURN; + } + } + if (CmdParseLayers (LSTR(ARG1(s)), &mask)) { + if (TTMaskEqual (&mask, &DBSpaceBits)) + CmdParseLayers ("*,label", &mask); + TTMaskClearType(&mask,TT_SPACE); + } + else { + TxPrintf ("%s: invalid layer specification\n", name); + RETURN; + } + scx.scx_use = (CellUse *) window->w_surfaceID; + scx.scx_trans = GeoIdentityTransform; + crec = (DBWclientRec *) window->w_clientData; + + _internal_list = LispNewObj (); + LTYPE(_internal_list) = S_LIST; + LLIST(_internal_list) = NULL; + + (void) DBTreeSrTiles(&scx, &mask, xMask, lispprinttile, + (ClientData) &scx.scx_area); + + return _internal_list; +} + + +/*----------------------------------------------------------------------------- + * + * LispGetSelPaint -- + * + * Get paint in the current selection + * + * Results: + * List containing paint description. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispGetSelPaint (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + SearchContext scx; + TileTypeBitMask mask; + + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || ARG2P(s)) { + TxPrintf ("Usage: (%s str)\n", name); + RETURN; + } + bzero (&scx, sizeof(SearchContext)); + if (CmdParseLayers (LSTR(ARG1(s)), &mask)) { + if (TTMaskEqual (&mask, &DBSpaceBits)) + CmdParseLayers ("*,label", &mask); + TTMaskClearType(&mask,TT_SPACE); + } + else { + TxPrintf ("%s: invalid layer specification\n", name); + RETURN; + } + if (SelectUse) + scx.scx_use = SelectUse; + else { + TxPrintf ("%s: no selection present", name); + RETURN; + } + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = SelectUse->cu_bbox; + _internal_list = LispNewObj (); + LTYPE(_internal_list) = S_LIST; + LLIST(_internal_list) = NULL; + (void) DBTreeSrTiles(&scx, &mask, 0, lispprinttile, + (ClientData) &scx.scx_area); + return _internal_list; +} + + + + +/*----------------------------------------------------------------------------- + * + * LispGetLabel -- + * + * Return a list of labels + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +static int +lispprintlabel (scx, label, tpath, cdarg) + SearchContext *scx; + Label *label; + TerminalPath *tpath; + ClientData cdarg; +{ + LispObj *l; + Rect sourceRect, targetRect; + static char buf[128]; + char *nm, *p; + int bad; + + /* Transform to target coordinates */ + GEOTRANSRECT(&scx->scx_trans, &label->lab_rect, &sourceRect); + + bad = 0; + for (nm = label->lab_text; *nm; nm++) + if (*nm == '\"') + bad++; + if (bad) { + int i; + nm = (char *) mallocMagic((unsigned) (strlen(label->lab_text)+1+bad)); + p = nm; + for (i=0; label->lab_text[i]; i++) { + if (label->lab_text[i] == '\"') + *p++ = '\\'; + *p++ = label->lab_text[i]; + } + *p = '\0'; + } + else + nm = label->lab_text; + + /* go to edit coords from root coords */ + GEOTRANSRECT (&RootToEditTransform, &sourceRect, &targetRect); + + sprintf (buf, "((\"%s\" \"%s\" %d %d %d %d))", + nm, + DBTypeShortName (label->lab_type), + targetRect.r_xbot, targetRect.r_ybot, + targetRect.r_xtop, targetRect.r_ytop); + if (bad) + freeMagic(nm); + l = LispParseString (buf); + CDR(LLIST(l)) = _internal_list; + _internal_list = l; + return 0; +} + +LispObj * +LispGetLabel (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + SearchContext scx; + TileTypeBitMask mask; + int windowMask, xMask; + DBWclientRec *crec; + MagWindow *window; + CellUse *PaintUse, *u; + CellDef *def; + + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || ARG2P(s)) { + TxPrintf ("Usage: (%s str)\n", name); + RETURN; + } + bzero (&scx, sizeof(SearchContext)); + window = ToolGetBoxWindow (&scx.scx_area, &windowMask); + if (window == NULL) { + TxPrintf ("%s: Box tool must be present.\n", name); + RETURN; + } + xMask = ((DBWclientRec *) window->w_clientData)->dbw_bitmask; + if ((windowMask & ~xMask) != 0) + { + window = CmdGetRootPoint((Point *) NULL, (Rect *) NULL); + xMask = ((DBWclientRec *) window->w_clientData)->dbw_bitmask; + if ((windowMask & xMask) == 0) + { + TxPrintf("The box is in more than one window; use the cursor\n"); + TxPrintf("to select the one you want to select from.\n"); + RETURN; + } + } + CmdParseLayers ("*,space,label", &mask); + scx.scx_use = (CellUse *) window->w_surfaceID; + scx.scx_trans = GeoIdentityTransform; + crec = (DBWclientRec *) window->w_clientData; + + _internal_list = LispNewObj (); + LTYPE(_internal_list) = S_LIST; + LLIST(_internal_list) = NULL; + + (void) DBSearchLabel (&scx, &mask, xMask, LSTR(ARG1(s)), + lispprintlabel, (ClientData) &scx.scx_area); + + return _internal_list; +} + + +/*----------------------------------------------------------------------------- + * + * LispGetSelLabel -- + * + * Return a list of labels in current selection + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispGetSelLabel (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + SearchContext scx; + TileTypeBitMask mask; + + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || ARG2P(s)) { + TxPrintf ("Usage: (%s str)\n", name); + RETURN; + } + bzero (&scx, sizeof(SearchContext)); + CmdParseLayers ("*,label", &mask); + TTMaskClearType(&mask,TT_SPACE); + if (SelectUse) + scx.scx_use = SelectUse; + else { + TxPrintf ("%s: no selection present", name); + RETURN; + } + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = SelectUse->cu_bbox; + + _internal_list = LispNewObj (); + LTYPE(_internal_list) = S_LIST; + LLIST(_internal_list) = NULL; + + (void) DBSearchLabel (&scx, &mask, 0, LSTR(ARG1(s)), + lispprintlabel, (ClientData) &scx.scx_area); + + return _internal_list; +} + + +/*----------------------------------------------------------------------------- + * + * LispGetCellNames -- + * + * Get cell names and their locations in the current edit cell + * + * Results: + * List containing cell description + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +static +int lispprintcell (use,cdarg) + CellUse *use; + ClientData cdarg; +{ + static char cellbuffer[1024]; + LispObj *l; + + sprintf (cellbuffer, "((\"%s\" %d %d %d %d %d %d %d %d %d %d))", + use->cu_id, + use->cu_bbox.r_xbot, use->cu_bbox.r_ybot, + use->cu_bbox.r_xtop, use->cu_bbox.r_ytop, + use->cu_xlo, use->cu_xhi, + use->cu_ylo, use->cu_yhi, + use->cu_xsep, use->cu_ysep); + + l = LispParseString (cellbuffer); + + CDR(LLIST(l)) = _internal_list; + _internal_list = l; + return 0; +} + + +LispObj * +LispGetCellNames (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + static char cellbuffer[1024]; + LispObj *l; + + if (ARG1P(s)) { + TxPrintf ("Usage: (%s)\n", name); + RETURN; + } + + _internal_list = LispNewObj (); + LTYPE(_internal_list) = S_LIST; + LLIST(_internal_list) = NULL; + + (void) DBCellEnum (EditCellUse ? EditCellUse->cu_def : EditRootDef, + lispprintcell, (ClientData) NULL); + + return _internal_list; +} + + + +/*----------------------------------------------------------------------------- + * + * LispEvalMagic -- + * + * Force its argument to be a magic function + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispEvalMagic (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_SYM || ARG2P(s)) { + TxPrintf ("Usage: (%s symbol)\n",name); + RETURN; + } + l = LispCopyObj(ARG1(s)); + LTYPE(l) = S_MAGIC_BUILTIN; + return l; +} + diff --git a/lisp/lispMain.c b/lisp/lispMain.c new file mode 100644 index 00000000..7dcafb84 --- /dev/null +++ b/lisp/lispMain.c @@ -0,0 +1,229 @@ +/************************************************************************* + * + * lispMain.c -- + * + * This module contains the mini-scheme interpreter interface. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispMain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "textio/textio.h" +#include "utils/signals.h" +#include "utils/malloc.h" + + +int lispInFile; /* global variable used within the lisp + module used to figure out whether we're + in a file */ + + +/*------------------------------------------------------------------------ + * + * LispEvaluate -- + * + * Evaluate the command-line as a lisp expression, and generate + * a list of commands in a local Cmd queue. + * + * Results: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ +void +LispEvaluate (argc, argv, inFile) + int argc; + char **argv; + int inFile; +{ + extern Sexp *LispMainFrame; + extern LispObj *LispMainFrameObj; + LispObj *l, *res; + char output_buf[LISP_MAX_LEN]; + int i,j,k; + static int my_depth = 0; + int old_infile; + + old_infile = lispInFile; + lispInFile = inFile; + my_depth ++; + /* + * convert input string into a lisp line. + */ + k=0; + output_buf[k++] = '('; + for (i=0; i < argc; i++) { + for (j=0; argv[i][j]; j++) { + if (argv[i][j] < 32) + output_buf[k++] = '\\'; + output_buf[k++] = argv[i][j]; + } + output_buf[k++] = ' '; + } + output_buf[k++] = ')'; + output_buf[k] = '\0'; + + if (my_depth == 1) + LispCollectAllocQ = 1; + + l = LispFrameLookup (LispNewString ("scm-echo-parser-input"), + LispMainFrame); + if (l && LTYPE(l) == S_BOOL && LBOOL(l)) + TxPrintf (" [ %s ]\n", output_buf); + l = LispParseString (output_buf); + res = LispFrameLookup (LispNewString ("scm-echo-parser-output"), + LispMainFrame); + if (l) { + if (res && LTYPE(res) == S_BOOL && LBOOL(res)) { + TxPrintf (" >> "); + LispPrint (stdout, l); + TxPrintf ("\n\n"); + } + if (SigInterruptOnSigIO >= 0) SigInterruptOnSigIO = 0; + SigInterruptPending = FALSE; + res = LispEval(l,LispMainFrame); + } + if (l && res) { + l = LispFrameLookup (LispNewString ("scm-echo-result"),LispMainFrame); + if (l && LTYPE(l) == S_BOOL && LBOOL(l)) { + LispPrint (stdout, res); + TxPrintf ("\n"); + } + } + else { + if (SigInterruptPending) + TxPrintf ("[Evaluation Interrupted]\n"); + } + /* collect garbage */ + if (my_depth == 1) + LispGC (LispMainFrameObj); + my_depth--; + lispInFile = old_infile; +} + + +/*------------------------------------------------------------------------ + * + * LispInit -- + * + * Initialize lisp builtins. + * + * Results: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +void +LispInit () +{ + extern LispObj *LispMainFrameObj; + + LispMainFrameObj = LispNewObj (); + LTYPE(LispMainFrameObj) = S_LIST; + LLIST(LispMainFrameObj) = NULL; + + LispFnInit (); + LispFrameInit (); + LispGCHasWork = 0; + LispCollectAllocQ = 0; + LispGC (LispMainFrameObj); + + LispSetEdit ("*unknown*"); +} + + +/*------------------------------------------------------------------------ + * + * LispSetTech -- + * + * Sets the scheme variable "technology" to the technology name. + * + * Results: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +void +LispSetTech (s) + char *s; +{ + extern Sexp *LispMainFrame; + extern LispObj *LispMainFrameObj; + LispObj *l, *m; + + m = LispNewObj (); + LTYPE(m) = S_SYM; + LSYM(m) = LispNewString ("technology"); + l = LispNewObj (); + LTYPE(l) = S_STRING; + LSTR(l) = (char *) mallocMagic((unsigned) (strlen(s)+1)); + strcpy (LSTR(l),s); + LispAddBinding (m, l, LispMainFrame); + LispCollectAllocQ = 0; + LispGC (LispMainFrameObj); +} + + + +/*------------------------------------------------------------------------ + * + * LispSetEdit -- + * + * Sets the edit cell name + * + * Results: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +void +LispSetEdit (s) + char *s; +{ + extern Sexp *LispMainFrame; + extern LispObj *LispMainFrameObj; + LispObj *l, *m; + + m = LispNewObj (); + LTYPE(m) = S_SYM; + LSYM(m) = LispNewString ("edit-cell"); + l = LispNewObj (); + LTYPE(l) = S_STRING; + LSTR(l) = (char *) mallocMagic((unsigned) (strlen(s)+1)); + strcpy (LSTR(l),s); + LispAddBinding (m, l, LispMainFrame); + LispCollectAllocQ = 0; + LispGC (LispMainFrameObj); +} diff --git a/lisp/lispParse.c b/lisp/lispParse.c new file mode 100644 index 00000000..8effd275 --- /dev/null +++ b/lisp/lispParse.c @@ -0,0 +1,415 @@ +/************************************************************************* + * + * lispParse.c -- + * + * This module contains the mini-scheme command-line parser (ugh). + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispParse.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "textio/textio.h" +#include "utils/hash.h" +#include "utils/malloc.h" + +#define IsSpace(c) ((c) == ' ') + +#define BeginIdChar(c) (isalpha(c) || (c) == '+' || (c) == '-' || \ + (c) == '.' || (c) == '*' || (c) == '/' || \ + (c) == '<' || (c) == '=' || (c) == '>' || \ + (c) == '!' || (c) == '?' || (c) == ':' || \ + (c) == '$' || (c) == '%' || (c) == '_' || \ + (c) == '&' || (c) == '~' || (c) == '^' || \ + (c) == '#' || (c) == '@' || (c) == ',') + +#define IsIdChar(c) (BeginIdChar(c) || isdigit(c) || ((c) == '[') || \ + ((c) == ']')) + +#define ISEND(c) ((c) == '\0' || isspace(c) || (c) == ')' || (c) == '(') + +/*----------------------------------------------------------------------------- + * + * Various string munging functions + * + *----------------------------------------------------------------------------- + */ + +/* + strip whitespace from left: returns new string pointer +*/ +static char * +stripleft (s) + char *s; +{ + while (*s && IsSpace (*s)) + s++; + return s; +} + +#define STRINGTAB 1000 + +static int nstrings = 0; +HashTable Strings; + + +/*----------------------------------------------------------------------------- + * + * LispNewString -- + * + * Returns a unique string pointer corresponding to string "s" + * + *----------------------------------------------------------------------------- + */ +char *LispNewString (s) + char *s; +{ + int i; + HashEntry *h; + + if (nstrings == 0) + HashInit (&Strings, STRINGTAB, HT_STRINGKEYS); + + h = HashLookOnly (&Strings, s); + if (h) + i = (int) HashGetValue(h); + else { + i = nstrings++; + h = HashFind (&Strings, s); + HashSetValue (h, i); + } + return h->h_key.h_name; +} + +/*----------------------------------------------------------------------------- + * + * LispStringId -- + * + * Returns an integer identifier associated with string, used for + * faster function table lookup. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +int +LispStringId (s) + char *s; +{ + int i; + HashEntry *h; + + h = HashLookOnly (&Strings, s); + if (!h) + i = -1; + else + i = (int)HashGetValue (h); + return i; +} + +/*----------------------------------------------------------------------------- + * + * LispAtomParse -- + * + * Parse an atom. + * If within a quote, 'quoted' is 1. + * + * Results: + * Returns pointer to an object. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispAtomParse (pstr,quoted) + int quoted; + char **pstr; +{ + char *str = *pstr; + char *q, c; + LispObj *l; + int r; + char *t; + + l = LispNewObj (); + + if ((*str == '+' || *str == '-' || *str == '.') && ISEND(*(str+1))) { + str++; + *str = '\0'; + LTYPE(l) = S_SYM; + LSYM(l) = LispNewString (str-1); + *pstr = str+1; + return l; + } + if ((isdigit(*str) || *str == '.' || *str == '-' || *str == '+') && + (isdigit(str[1]) || str[1] == '.' || str[1] == '-' || str[1] == '+' + || ISEND(str[1]))) { + /* eat leading sign */ + q = str; + r = 0; + if (*str == '-' || *str == '+') + str++; + if (!*str) { + TxPrintf ("Invalid number\n"); + *pstr = str; + return NULL; + } + while (*str && isdigit (*str)) + str++; + if (*str && *str == '.') { + r = 1; + str++; + } + while (*str && isdigit(*str)) + str++; + c = *str; + *str = '\0'; + if (r) { + LTYPE(l) = S_FLOAT; + sscanf (q, "%lf", &LFLOAT(l)); + } + else { + LTYPE(l) = S_INT; + sscanf (q, "%d", &LINTEGER(l)); + } + *str = c; + } + else if (*str == '\"') { + str++; + q = str; + while (*str != '\"') { + if (!*str) { + TxPrintf ("Unterminated string\n"); + *pstr = str; + return NULL; + } + if (*str == '\\') { + if (*(str+1)) + str++; + else { + TxPrintf ("Trailing character constant\n"); + *pstr = str; + return NULL; + } + } + str++; + } + *str = '\0'; + LTYPE(l) = S_STRING; + LSTR(l) = (char *) mallocMagic((unsigned) (strlen (q)+1)); + strcpy (LSTR(l), q); + *str = '\"'; + str++; + } + else if (!quoted && str[0] == '#' && (str[1] == 't'|| str[1] == 'f') && + ISEND(str[2])) { + LTYPE(l) = S_BOOL; + LBOOL(l) = (str[1] == 't') ? 1 : 0; + str+=2; + } + else if (BeginIdChar(*str) || (*str == '\\')) { + int nest; + + LTYPE(l) = S_SYM; + t = q = str; + if (*str == '\\') { + *t = *++str; + t++; + str++; + } + nest = 0; + while (*str && IsIdChar (*str) || *str == '(' || (*str == ')' && nest>0)) { + *t = *str; + if (*str == '(') nest++; + if (*str == ')') nest--; + str++; + if (*str == '\\') { + *t = *++str; + str++; + } + t++; + } + c = *t; + *t = '\0'; + LSYM(l) = LispNewString (q); + *t = c; + } + else { + TxPrintf ("Unparsable input character: %c\n", *str); + *pstr = str; + return NULL; + } + *pstr = str; + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispIParse -- + * + * Parse a string to a Sexp. + * + * Results: + * Returns pointer to a Sexp. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +Sexp * +LispIParse (pstr) + char **pstr; +{ + char *str = *pstr; + Sexp *s; + Sexp *ret = NULL; + Sexp **sptr; + + str = stripleft (str); + if (!*str) { + TxPrintf ("Input malformed\n"); + return NULL; + } + while (*str != ')') { + if (!*str) { + TxPrintf ("Input malformed: missing )\n"); + return NULL; + } + s = LispNewSexp (); + if (*str == '(') { + CAR(s) = LispNewObj (); + LTYPE(CAR(s)) = S_LIST; + str++; + LLIST(CAR(s)) = LispIParse (&str); + if (*str != ')') { + *pstr = str; + return NULL; + } + str++; + } + else if (*str == '\'') { + LispObj *l; + Sexp *t; + t = s; + CAR(s) = LispNewObj (); + LTYPE(CAR(s)) = S_SYM; + LSYM(CAR(s)) = LispNewString ("quote"); + CDR(s) = LispNewObj (); + LTYPE(CDR(s)) = S_LIST; + LLIST(CDR(s)) = LispNewSexp (); + s = LLIST(CDR(s)); + CDR(s) = LispNewObj (); + LTYPE(CDR(s)) = S_LIST; + LLIST(CDR(s)) = NULL; + str++; + str = stripleft (str); + if (*str == '(') { + str++; + CAR(s) = LispNewObj (); + LTYPE(CAR(s)) = S_LIST; + LLIST(CAR(s)) = LispIParse (&str); + if (*str != ')') { + *pstr = str; + return NULL; + } + str++; + } + else { + if (!(CAR(s) = LispAtomParse (&str,1))) { + *pstr = str; + return NULL; + } + } + *pstr = str; + l = LispNewObj (); + LTYPE(l) = S_LIST; + LLIST(l) = t; + t = LispNewSexp (); + CAR(t) = l; + s = t; + } + else { + if (!(CAR(s) = LispAtomParse (&str,0))) { + *pstr = str; + return NULL; + } + } + CDR(s) = LispNewObj (); + LTYPE(CDR(s)) = S_LIST; + if (ret == NULL) + ret = s; + else + *sptr = s; + sptr = &LLIST(CDR(s)); + str = stripleft (str); + } + if (ret) + *sptr = NULL; + *pstr = str; + return ret; +} + + +/*----------------------------------------------------------------------------- + * + * LispParseString -- + * + * Parse string to a lisp object. + * + * Results: + * Returns pointer to the object. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispParseString (str) + char *str; +{ + LispObj *l; + + str = stripleft (str); + if (*str != '(') + l = LispAtomParse (&str,0); + else { + str++; + l = LispNewObj (); + LTYPE(l) = S_LIST; + LLIST(l) = LispIParse (&str); + if (LLIST(l) && *str != ')') + l = NULL; + } + return l; +} diff --git a/lisp/lispPrint.c b/lisp/lispPrint.c new file mode 100644 index 00000000..45290625 --- /dev/null +++ b/lisp/lispPrint.c @@ -0,0 +1,339 @@ + /************************************************************************* + * + * lispPrint.c -- + * + * Stuff that prints out the internals of lists. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispPrint.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "lispargs.h" +#include "utils/signals.h" +#include "utils/hash.h" + +#define IsSpace(c) ((c) == ' ') + +/* + Print t into s, expanding control characters. + flag = 1: put quotes around if spaces present + flag = 0: don't +*/ +static +void +LispBufPrintName (s,t,flag) + char *s, *t; + int flag; +{ + int i,j, spc; + i=0; + spc=0; + for (j=0; t[j]; j++) + if (IsSpace (t[j])) { + spc=1; + break; + } + if (spc && flag) s[i++] = '\"'; + for (j=0; t[j]; j++) + if (t[j] >= 32) + s[i++] = t[j]; + else { + s[i++] = '^'; + s[i++] = t[j]+64; + } + if (spc && flag) + s[i++] = '\"'; + s[i]='\0'; +} + +/*------------------------------------------------------------------------ + * + * LispPrint -- + * + * Print the object out to the text stream. + * + * Results: + * None. + * + * Side effects: + * Output appears in text window. + * + *------------------------------------------------------------------------ + */ + +static char obuf[128]; +static HashTable PrintTable, GenTable; +static int num_refs; + +static void +_LispPrint (fp,l) + FILE *fp; + LispObj *l; +{ + HashEntry *h; + int i; + if (SigInterruptPending) return; + h = HashLookOnly (&PrintTable, l); + if (h) { + i = (int) HashGetValue (h); + if (i) { + /* i > 0 */ + if (fp == stdout) TxPrintf ("#%d", i); + else fprintf (fp, "#%d", i); + return; + } + else { + /* not printed; set the print tag */ + HashSetValue (h, ++num_refs); + if (fp == stdout) TxPrintf ("#%d:", num_refs); + else fprintf (fp, "#%d:", num_refs); + } + } + switch (LTYPE(l)) { + case S_INT: + if (fp == stdout) TxPrintf ("%d", LINTEGER(l)); + else fprintf (fp,"%d", LINTEGER(l)); + break; + case S_FLOAT: + if (fp == stdout) TxPrintf ("%lf", LFLOAT(l)); + else fprintf (fp, "%lf", LFLOAT(l)); + break; + case S_STRING: + LispBufPrintName (obuf, LSTR(l),0); + if (fp == stdout) TxPrintf ("\"%s\"", obuf); + else fprintf (fp, "\"%s\"", obuf); + break; + case S_BOOL: + if (fp == stdout) TxPrintf ("#%c", LINTEGER(l) ? 't' : 'f'); + else fprintf (fp, "#%c", LINTEGER(l) ? 't' : 'f'); + break; + case S_SYM: + LispBufPrintName (obuf, LSYM(l),1); + if (fp == stdout) TxPrintf ("%s", obuf); + else fprintf (fp, "%s", obuf); + break; + case S_LIST: + if (fp == stdout) TxPrintf ("("); + else fprintf (fp, "("); + if (LLIST(l)) { + Sexp *s; + s = LLIST(l); + _LispPrint (fp,CAR(s)); + while ((LTYPE(CDR(s)) == S_LIST) && LLIST(CDR(s))) { + if (fp == stdout) TxPrintf (" "); + else fprintf (fp, " "); + h = HashLookOnly (&PrintTable, CDR(s)); + if (h) { + i = (int) HashGetValue (h); + if (i) { + /* i > 0 */ + if (fp == stdout) TxPrintf ("#%d", i); + else fprintf (fp, "#%d", i); + goto done; + } + else { + /* not printed; set the print tag */ + HashSetValue (h, ++num_refs); + if (fp == stdout) TxPrintf ("#%d:", num_refs); + else fprintf (fp, "#%d:", num_refs); + } + } + s = LLIST(CDR(s)); + _LispPrint (fp,CAR(s)); + } + if (LTYPE(CDR(s)) != S_LIST) { + if (fp == stdout) TxPrintf (" . "); + else fprintf (fp, " . "); + _LispPrint (fp,CDR(s)); + } + } +done: + if (fp == stdout) TxPrintf (")"); + else fprintf (fp, ")"); + break; + case S_LAMBDA: + if (fp == stdout) TxPrintf ("(lambda "); + else fprintf (fp, "(lambda "); + _LispPrint (fp,ARG2(LUSERDEF(l))); + if (fp == stdout) TxPrintf (" "); + else fprintf (fp, " "); + _LispPrint (fp,ARG4(LUSERDEF(l))); + if (fp == stdout) TxPrintf (")"); + else fprintf (fp, ")"); + break; + case S_LAMBDA_BUILTIN: + case S_MAGIC_BUILTIN: + if (fp == stdout) TxPrintf ("#proc"); + else fprintf (fp, "#proc"); + break; + default: + break; + } +} + + +static void +_LispGenTable (l) + LispObj *l; +{ + HashEntry *h; + int i; + if (SigInterruptPending) return; + h = HashLookOnly (&GenTable, l); + if (h) { + i = (int) HashGetValue (h); + i++; + HashSetValue (h, i); + return; + } + h = HashFind (&GenTable, l); + HashSetValue (h, 0); + switch (LTYPE(l)) { + case S_INT: + case S_FLOAT: + case S_STRING: + case S_BOOL: + case S_SYM: + case S_LAMBDA_BUILTIN: + case S_MAGIC_BUILTIN: + break; + case S_LIST: + if (LLIST(l)) { + Sexp *s; + s = LLIST(l); + _LispGenTable (CAR(s)); + while ((LTYPE(CDR(s)) == S_LIST) && LLIST(CDR(s))) { + h = HashLookOnly (&GenTable, CDR(s)); + if (h) { + i = (int) HashGetValue (h); + i++; + HashSetValue (h, i); + return; + } + h = HashFind (&GenTable, CDR(s)); + HashSetValue (h, 0); + s = LLIST(CDR(s)); + _LispGenTable (CAR(s)); + } + if (LTYPE(CDR(s)) != S_LIST) { + _LispGenTable (CDR(s)); + } + } + break; + case S_LAMBDA: + _LispGenTable (ARG2(LUSERDEF(l))); + _LispGenTable (ARG4(LUSERDEF(l))); + break; + default: + break; + } +} + + +void +LispPrint (fp, l) + FILE *fp; + LispObj *l; +{ + HashEntry *h; + HashSearch hs; + int i; + + num_refs = 0; + HashInit (&PrintTable, 128, HT_WORDKEYS); + HashInit (&GenTable, 128, HT_WORDKEYS); + _LispGenTable (l); + HashStartSearch (&hs); + while (h = HashNext (&GenTable, &hs)) { + i = (int) HashGetValue (h); + if (i) { + h = HashFind (&PrintTable, h->h_key.h_ptr); + HashSetValue (h, 0); + } + } + _LispPrint (fp,l); + HashKill (&PrintTable); + HashKill (&GenTable); +} + + +/*------------------------------------------------------------------------ + * + * LispPrintType -- + * + * Print the type of the object out to the text stream. + * + * Results: + * None. + * + * Side effects: + * Output appears in text window. + * + *------------------------------------------------------------------------ + */ + +void +LispPrintType (fp,l) + FILE *fp; + LispObj *l; +{ + switch (LTYPE(l)) { + case S_INT: + if (fp == stdout) TxPrintf ("#integer"); + else fprintf (fp, "#integer"); + break; + case S_FLOAT: + if (fp == stdout) TxPrintf ("#float"); + else fprintf (fp, "#float"); + break; + case S_STRING: + if (fp == stdout) TxPrintf ("#string"); + else fprintf (fp, "#string"); + break; + case S_BOOL: + if (fp == stdout) TxPrintf ("#boolean"); + else fprintf (fp, "#boolean"); + break; + case S_SYM: + if (fp == stdout) TxPrintf ("#symbol"); + else fprintf (fp, "#symbol"); + break; + case S_LIST: + if (fp == stdout) TxPrintf ("#list"); + else fprintf (fp, "#list"); + break; + case S_LAMBDA: + if (fp == stdout) TxPrintf ("#proc-userdef"); + else fprintf (fp, "#proc-userdef"); + break; + case S_LAMBDA_BUILTIN: + if (fp == stdout) TxPrintf ("#proc-builtin"); + else fprintf (fp, "#proc-builtin"); + break; + case S_MAGIC_BUILTIN: + if (fp == stdout) TxPrintf ("#proc-magic"); + else fprintf (fp, "#proc-magic"); + break; + default: + break; + } +} diff --git a/lisp/lispString.c b/lisp/lispString.c new file mode 100644 index 00000000..f7d538a2 --- /dev/null +++ b/lisp/lispString.c @@ -0,0 +1,434 @@ +/************************************************************************* + * + * lispString.c -- + * + * This module contains the builtin mini-scheme string functions. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispString.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + +#include + +#include "lisp/lisp.h" +#include "lispInt.h" +#include "lispargs.h" +#include "textio/textio.h" +#include "utils/malloc.h" + + +/*----------------------------------------------------------------------------- + * + * LispStrCat -- + * + * Concatenate two strings. + * + * Results: + * Returns the concatenated string. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ +LispObj * +LispStrCat (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_STRING || + LTYPE(ARG2(s)) != S_STRING || ARG3P(s)) { + TxPrintf ("Usage: (%s str1 str2)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_STRING; + LSTR(l) = (char *) mallocMagic((unsigned) (strlen(LSTR(ARG1(s)))+strlen(LSTR(ARG2(s)))+1)); + strcpy (LSTR(l),LSTR(ARG1(s))); + strcat (LSTR(l),LSTR(ARG2(s))); + return l; +} + + +/*----------------------------------------------------------------------------- + * + * LispSymbolToString -- + * + * Returns the string name for a symbol. + * + * Results: + * New string. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispSymbolToString (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_SYM || ARG2P(s)) { + TxPrintf ("Usage: (%s symbol)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_STRING; + LSTR(l) = (char *) mallocMagic((unsigned) (strlen(LSYM(ARG1(s)))+1)); + strcpy (LSTR(l), LSYM(ARG1(s))); + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispStringToSymbol -- + * + * Symbol named "string" + * + * Results: + * The symbol. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispStringToSymbol (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || ARG2P(s)) { + TxPrintf ("Usage: (%s string)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_SYM; + LSYM(l) = LispNewString (LSTR(ARG1(s))); + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispNumberToString -- + * + * Convert number to string. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispNumberToString (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + char buf[128]; + + if (!ARG1P(s) || !NUMBER(LTYPE(ARG1(s))) || ARG2P(s)) { + TxPrintf ("Usage: (%s num)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_STRING; + if (LTYPE(ARG1(s)) == S_FLOAT) + sprintf (buf, "%lf", LFLOAT(ARG1(s))); + else + sprintf (buf, "%d", LINTEGER(ARG1(s))); + LSTR(l) = (char *) mallocMagic((unsigned) (strlen(buf)+1)); + strcpy (LSTR(l),buf); + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispStringToNumber -- + * + * Number named "string" + * + * Results: + * The number. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispStringToNumber (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + char *str; + int r; + + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || ARG2P(s)) { + TxPrintf ("Usage: (%s string)\n", name); + RETURN; + } + str = LSTR(ARG1(s)); + l = LispNewObj (); + if (isdigit(*str) || *str == '.' || *str == '-' || *str == '+') { + r = 0; + if (*str == '-' || *str == '+') + str++; + if (!*str) { + TxPrintf ("String is not a number.\n"); + RETURN; + } + while (*str && isdigit (*str)) + str++; + if (*str && *str == '.') { + r = 1; + str++; + } + while (*str && isdigit(*str)) + str++; + *str = '\0'; + if (r) { + LTYPE(l) = S_FLOAT; + sscanf (LSTR(ARG1(s)), "%lf", &LFLOAT(l)); + } + else { + LTYPE(l) = S_INT; + sscanf (LSTR(ARG1(s)), "%d", &LINTEGER(l)); + } + } + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispStringLength -- + * + * Compute length of string. + * + * Results: + * Returns length. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispStringLength (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + if (!ARG1P(s) || LTYPE(ARG1(s)) != S_STRING || ARG2P(s)) { + TxPrintf ("Usage: (%s string)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_INT; + LINTEGER(l) = strlen (LSTR(ARG1(s))); + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispStringCompare -- + * + * Compare two strings. + * + * Results: + * An integer. + * 0 => str1 == str2 + * (>0) => str1 > str2 + * (<0) => str1 < str2 + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispStringCompare (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_STRING || + LTYPE(ARG2(s)) != S_STRING || ARG3P(s)) { + TxPrintf ("Usage: (%s str1 str2)\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_INT; + LINTEGER(l) = strcmp (LSTR(ARG1(s)),LSTR(ARG2(s))); + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispStringRef -- + * + * Return character k from a string. + * + * Results: + * An integer. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispStringRef (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + if (!ARG1P(s) || !ARG2P(s) || LTYPE(ARG1(s)) != S_STRING || + LTYPE(ARG2(s)) != S_INT || ARG3P(s)) { + TxPrintf ("Usage: (%s str int)\n", name); + RETURN; + } + if (strlen (LSTR(ARG1(s))) <= LINTEGER(ARG2(s)) || LINTEGER(ARG2(s)) < 0) { + TxPrintf ("%s: integer argument out of range.\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_INT; + LINTEGER(l) = LSTR(ARG1(s))[LINTEGER(ARG2(s))]; + return l; +} + + + +/*----------------------------------------------------------------------------- + * + * LispStringSet -- + * + * Set kth string character to the appropriate integer. + * + * Results: + * boolean. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispStringSet (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + + if (!ARG1P(s) || !ARG2P(s) || !ARG3P(s) || + LTYPE(ARG1(s)) != S_STRING || LTYPE(ARG2(s)) != S_INT || + LTYPE(ARG3(s)) != S_INT || ARG4P(s)) { + TxPrintf ("Usage: (%s str int int)\n", name); + RETURN; + } + if (strlen (LSTR(ARG1(s))) <= LINTEGER(ARG2(s)) || LINTEGER(ARG2(s)) < 0) { + TxPrintf ("%s: integer argument out of range.\n", name); + RETURN; + } + l = LispNewObj(); + LSTR(ARG1(s))[LINTEGER(ARG2(s))] = LINTEGER(ARG3(s)); + LTYPE(l) = S_BOOL; + LBOOL(l) = 1; + return l; +} + + +/*----------------------------------------------------------------------------- + * + * LispSubString -- + * + * Return a substring from a string. + * + * Results: + * String. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +LispObj * +LispSubString (name,s,f) + char *name; + Sexp *s; + Sexp *f; +{ + LispObj *l; + + if (!ARG1P(s) || !ARG2P(s) || !ARG3P(s) || + LTYPE(ARG1(s)) != S_STRING || LTYPE(ARG2(s)) != S_INT || + LTYPE(ARG3(s)) != S_INT || ARG4P(s)) { + TxPrintf ("Usage: (%s str int int)\n", name); + RETURN; + } + if (!(0 <= LINTEGER(ARG2(s)) && LINTEGER(ARG2(s)) <= LINTEGER(ARG3(s)) && + LINTEGER(ARG3(s)) <= strlen(LSTR(ARG1(s))))) { + TxPrintf ("%s: integer argument out of range.\n", name); + RETURN; + } + l = LispNewObj (); + LTYPE(l) = S_STRING; + LSTR(l) = (char*) mallocMagic((unsigned) (LINTEGER(ARG3(s))-LINTEGER(ARG2(s))+1)); + strncpy (LSTR(l), LSTR(ARG1(s))+LINTEGER(ARG2(s)), + LINTEGER(ARG3(s))-LINTEGER(ARG2(s))); + LSTR(l)[LINTEGER(ARG3(s))-LINTEGER(ARG2(s))] = '\0'; + return l; +} diff --git a/lisp/lispTrace.c b/lisp/lispTrace.c new file mode 100644 index 00000000..29784a1e --- /dev/null +++ b/lisp/lispTrace.c @@ -0,0 +1,186 @@ +/************************************************************************* + * + * lispTrace.c -- + * + * This module manipulates the stack trace information used for + * error reporting. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispTrace.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ + + +#include +#include "lisp/lisp.h" +#include "lispInt.h" +#include "textio/textio.h" +#include "utils/malloc.h" + + +typedef struct stack { + struct stack *n; + char *s; + struct stack *next; +} TRACE; + +static TRACE *current = NULL; + +static TRACE *freeQ = NULL; + +static +TRACE * +StackNew () +{ + TRACE *t; + if (freeQ) { + t = freeQ; + freeQ = freeQ->n; + } + else { + t = (TRACE *) mallocMagic((unsigned) (sizeof(TRACE))); + } + t->n = NULL; + return t; +} + +static +void +StackFree (t) + TRACE *t; +{ + t->n = freeQ; + freeQ = t; +} + + +/*------------------------------------------------------------------------ + * + * LispStackPush -- + * + * Push a name onto the call stack. + * + * Results: + * none. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +void +LispStackPush (name) + char *name; +{ + TRACE *t; + t = StackNew(); + t->s = name; + t->next = current; + current = t; +} + + +/*------------------------------------------------------------------------ + * + * LispStackPop -- + * + * Pop a frame off the evaluation stack. + * + * Results: + * none. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +void +LispStackPop () +{ + TRACE *t; + t = current; + if (!current) + TxError ("Internal error!\n"); + else { + current = current->next; + StackFree (t); + } +} + + +/*------------------------------------------------------------------------ + * + * LispStackDisplay -- + * + * Display call stack. + * + * Results: + * none. + * + * Side effects: + * text appears in window. + * + *------------------------------------------------------------------------ + */ + +void +LispStackDisplay () +{ + extern Sexp *LispMainFrame; + LispObj *l; + TRACE *t = current; + int i = 0; + int depth; + l = LispFrameLookup (LispNewString ("scm-stack-display-depth"), + LispMainFrame); + if (l && LTYPE(l) == S_INT) + depth = LINTEGER(l); + else + depth = 5; + if (depth > 0) + TxPrintf ("Stack trace:\n"); + while (t && i < depth) { + i++; + TxPrintf ("\tcalled from: %s\n", t->s); + t = t->next; + } + if (i < depth) + TxPrintf ("\tcalled from: -top-level-\n"); +} + + +/*------------------------------------------------------------------------ + * + * LispStackClear -- + * + * Clear the call stack. + * + * Results: + * none. + * + * Side effects: + * none. + * + *------------------------------------------------------------------------ + */ + +void +LispStackClear () +{ + while (current) + LispStackPop (); +} diff --git a/lisp/lispargs.h b/lisp/lispargs.h new file mode 100644 index 00000000..53d48d5a --- /dev/null +++ b/lisp/lispargs.h @@ -0,0 +1,49 @@ +/************************************************************************* + * + * lispargs.h -- + * + * Macros for looking at various entries in a list. + * + * (c) 1996 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies. The California Institute of Technology makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. Export of this + * software outside of the United States of America may require an + * export license. + * + * $Id: lispargs.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + * requires: lispInt.h + * + *************************************************************************/ + +#define ARG1P(s) (s) +#define ARG1(s) CAR(s) + +#define EARG2P(s) (LTYPE(CDR(s)) != S_LIST || LLIST(CDR(s))) +#define ARG2P(s) (LTYPE(CDR(s)) == S_LIST && LLIST(CDR(s))) +#define ARG2(s) CAR(LLIST(CDR(s))) + +#define ARG3P(s) (LTYPE(CDR(LLIST(CDR(s)))) == S_LIST && LLIST(CDR(LLIST(CDR(s))))) +#define ARG3(s) CAR(LLIST(CDR(LLIST(CDR(s))))) + +#define ARG4P(s) (LTYPE(CDR(LLIST(CDR(LLIST(CDR(s)))))) == S_LIST && LLIST(CDR(LLIST(CDR(LLIST(CDR(s))))))) +#define ARG4(s) CAR(LLIST(CDR(LLIST(CDR(LLIST(CDR(s))))))) + +/* + what i'd really like is + do { ... } while (0) + because that forces the user to use ";" at the end . . . but + Sun's cc thinks you should be warned about such statements -sigh- +*/ +#define RETURN { LispStackDisplay (); return NULL; } +#define RETURNPOP { LispStackDisplay (); LispStackPop(); return NULL; } + + +#define NUMBER(t) ((t) == S_INT || (t) == S_FLOAT) diff --git a/lisp/scm/box.scm b/lisp/scm/box.scm new file mode 100644 index 00000000..66df3b47 --- /dev/null +++ b/lisp/scm/box.scm @@ -0,0 +1,81 @@ +;------------------------------------------------------------------------- +; +; Save and restore box position and cursor movement. +; +; (c) 1996 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: box.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +; Requires: default.scm +; +;------------------------------------------------------------------------- + +(define box.list ()) + +(define box.=? + (lambda (b1 b2) + (and (and (=? (car b1) (car b2)) (=? (cadr b1) (cadr b2))) + (and (=? (caddr b1) (caddr b2)) (=? (caddr b1) (caddr b2))) + ) + ) + ) + +(define box.push + (lambda (pos) + (set! box.list (cons pos box.list)) + ) + ) + +(define box.pop + (lambda () + (if (null? box.list) + (echo "Box list is empty") + (let ((x (car box.list))) + (begin + (set! box.list (cdr box.list)) + (if (box.=? x (getbox)) #t (eval (cons 'box x))) + ) + ) + ) + ) + ) + +; +; Magic's move command is buggy . . . -sigh- +; +(define box.move + (lambda (dx dy) + (let* ((x (getbox)) + (nllx (+ dx (car x))) + (nlly (+ dy (cadr x))) + (nurx (+ dx (caddr x))) + (nury (+ dy (cadddr x)))) + (box nllx nlly nurx nury) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Convex "box"-hull of two boxes +;------------------------------------------------------------------------ +(define box.hull + (lambda (b1 b2) + (list (min (car b1) (car b2)) + (min (cadr b1) (cadr b2)) + (max (caddr b1) (caddr b2)) + (max (cadddr b1) (cadddr b2)) + ) + ) + ) diff --git a/lisp/scm/default.scm b/lisp/scm/default.scm new file mode 100644 index 00000000..7a7ed32d --- /dev/null +++ b/lisp/scm/default.scm @@ -0,0 +1,171 @@ +;------------------------------------------------------------------------- +; +; Some standard scheme functions. +; +; (c) 1996 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: default.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +;------------------------------------------------------------------------- + +; +; Manipulating booleans +; +(define and (lambda (x y) (if x y #f))) +(define or (lambda (x y) (if x #t y))) +(define not (lambda (x) (if x #f #t))) + +; +; MIT-scheme defines "sequence" +; +(define sequence begin) + +; +; A looping construct +; +(define repeat + (lambda (N obj-with-side-effects) + (if (positive? N) + (begin (obj-with-side-effects) + (repeat (- N 1) obj-with-side-effects)) + #t + ) + ) + ) + + +; +; More list stuff . . . +; +(define caar (lambda (x) (car (car x)))) +(define cadr (lambda (x) (car (cdr x)))) +(define cdar (lambda (x) (cdr (car x)))) +(define cddr (lambda (x) (cdr (cdr x)))) +(define caaar (lambda (x) (car (car (car x))))) +(define caadr (lambda (x) (car (car (cdr x))))) +(define cadar (lambda (x) (car (cdr (car x))))) +(define cdaar (lambda (x) (cdr (car (car x))))) +(define caddr (lambda (x) (car (cdr (cdr x))))) +(define cdadr (lambda (x) (cdr (car (cdr x))))) +(define cddar (lambda (x) (cdr (cdr (car x))))) +(define cdddr (lambda (x) (cdr (cdr (cdr x))))) +(define caaaar (lambda (x) (car (car (car (car x)))))) +(define caaadr (lambda (x) (car (car (car (cdr x)))))) +(define caadar (lambda (x) (car (car (cdr (car x)))))) +(define cadaar (lambda (x) (car (cdr (car (car x)))))) +(define caaddr (lambda (x) (car (car (cdr (cdr x)))))) +(define cadadr (lambda (x) (car (cdr (car (cdr x)))))) +(define caddar (lambda (x) (car (cdr (cdr (car x)))))) +(define cadddr (lambda (x) (car (cdr (cdr (cdr x)))))) +(define cdaaar (lambda (x) (cdr (car (car (car x)))))) +(define cdaadr (lambda (x) (cdr (car (car (cdr x)))))) +(define cdadar (lambda (x) (cdr (car (cdr (car x)))))) +(define cddaar (lambda (x) (cdr (cdr (car (car x)))))) +(define cdaddr (lambda (x) (cdr (car (cdr (cdr x)))))) +(define cddadr (lambda (x) (cdr (cdr (car (cdr x)))))) +(define cdddar (lambda (x) (cdr (cdr (cdr (car x)))))) +(define cddddr (lambda (x) (cdr (cdr (cdr (cdr x)))))) + + +(define append + (lambda (l1 l2) + (if (null? l1) l2 + (cons (car l1) (append (cdr l1) l2)) + ) + ) + ) + +(define reverse + (letrec ((reverse-helper + (lambda (name rest) + (if (null? rest) name + (reverse-helper (cons (car rest) name) (cdr rest)) + ) + ) + ) + ) + (lambda (l) + (reverse-helper () l) + ) + ) + ) + + + +; +; Some arithmetic +; +(define =? (lambda (x y) (zero? (- x y)))) +(define ? (lambda (x y) (positive? (- x y)))) +(define >=? (lambda (x y) (or (>? x y) (=? x y)))) +(define <=? (lambda (x y) (or (? x y) x y))) +(define min (lambda (x y) (if (? (lambda (x y) (positive? (string-compare x y)))) + +(define string-list? + (lambda (x) + (cond ((null? x) #t) + ((string? (car x)) (string-list? (cdr x))) + (#t #f) + ) + ) + ) + + +; +; Generally useful functions . . . +; +(define mapcar + (lambda (f l) (if (null? l) l (cons (f (car l)) (mapcar f (cdr l))))) + ) + +; +; Debugging support +; +(define debug-object (lambda (x) (begin (display-object x) x))) + +; +; Initial value of various constants. +; +(define scm-echo-result #f) ; disable echoing of results + +(define scm-trace-magic #f) ; don't trace magic commands + +(define scm-echo-parser-input #f) ; don't display parser input string + +(define scm-echo-parser-output #f) ; don't display parser output + +(define scm-stack-display-depth 0) ; default # of items displayed + ; increase this when debugging scm code + +(define scm-gc-frequency 5) ; collect garbage every so often + + +; +; Unix "system" +; +(define system (lambda (str) (wait (spawn "sh" "-c" str)))) diff --git a/lisp/scm/draw.scm b/lisp/scm/draw.scm new file mode 100644 index 00000000..c5debd69 --- /dev/null +++ b/lisp/scm/draw.scm @@ -0,0 +1,90 @@ +;------------------------------------------------------------------------- +; +; Simple rectangle drawing commands +; +; (c) 1996 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: draw.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +; Requires: box.scm, drc.scm, label.scm +; +;------------------------------------------------------------------------- + +; +; Draw a layer from current lower left corner of box +; +(define draw.layer-nr + (lambda (layer dx dy) + (let* ((pos (getbox)) + (llx (car pos)) + (lly (cadr pos))) + (begin (define nx (+ llx dx)) + (define ny (+ lly dy)) + (box llx lly nx ny) + (paint layer) + (list llx lly nx ny) + ) + ) + ) + ) + + +(define draw.layer + (lambda (layer dx dy) + (let ((pos (getbox))) + (begin (box.push pos) + (let ((x (draw.layer-nr layer dx dy))) + (begin + (box.pop) + x + ) + ) + ) + ) + ) + ) + + +; +; Draw a series of vertical rectangles with labels. +; +(define draw.vert-rectangles-with-labels + (lambda (layer-name dx dy spacing labels) + (if (null? labels) + #t + (begin (draw.layer-nr layer-name dx dy) + (label.draw (car labels) layer-name) + (box.move 0 (+ spacing dy)) + (draw.vert-rectangles-with-labels + layer-name dx dy spacing (cdr labels)) + ) + ) + ) + ) + +; +; Draw a series of vertical rectangles +; +(define draw.vert-rectangles + (lambda (layer-name dx dy spacing number) + (repeat number + (lambda () + (begin (draw.layer-nr layer-name dx dy) + (box.move 0 (+ spacing dy)) + ) + ) + ) + ) + ) + diff --git a/lisp/scm/drc.scm b/lisp/scm/drc.scm new file mode 100644 index 00000000..b2875a7f --- /dev/null +++ b/lisp/scm/drc.scm @@ -0,0 +1,133 @@ +;------------------------------------------------------------------------- +; +; Design-rule file +; +; (c) 1996 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: drc.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +; Requires: default.scm +; +;------------------------------------------------------------------------- + + +;------------------------------------------------------------------------ +; Look for name in a name list +;------------------------------------------------------------------------ +(define drc.find-name + (lambda (name name-list) + (cond ((null? name-list) (echo + (string-append "Could not find: " name) + )) + ((string=? name (caar name-list)) (cadar name-list)) + (#t (drc.find-name name (cdr name-list))) + ) + ) + ) + +;------------------------------------------------------------------------ +; +; Spacing rules: +; +; Tight metal rules: m3: 3, m1,m2: 2 +; +;------------------------------------------------------------------------ + +(define drc.min-spacing + (let ((spacing + (cond + ((string=? technology "scmos") + '(("poly" 2) + ("m1" 3) + ("m2" 3) + ("m3" 4) + ("contact-gate" 1) + ("contact-contact" 2) + ("pdiff-ndiff" 10) + ("pdiff-pdiff" 3) + ("ndiff-ndiff" 3) + )) + ((string=? technology "SCN5M_DEEP.12") + '(("poly" 4) + ("m1" 3) + ("m2" 3) + ("m3" 4) + ("contact-gate" 1) + ("contact-contact" 2) + ("pdiff-ndiff" 12) + ("pdiff-pdiff" 3) + ("ndiff-ndiff" 3) + )) + (#t + '(("poly" 3) + ("m1" 3) + ("m2" 3) + ("m3" 4) + ("contact-gate" 1) + ("contact-contact" 2) + ("pdiff-ndiff" 12) + ("pdiff-pdiff" 3) + ("ndiff-ndiff" 3) + )) + ) + ) + ) + (lambda (layer-name) (drc.find-name layer-name spacing)) + ) + ) + +; +; Width rules +; + +(define drc.min-width + (let ((width '(("poly" 2) + ("m1" 3) + ("m2" 3) + ("m3" 5) + ("contact" 4) + ) + ) + ) + (lambda (layer-name) (drc.find-name layer-name width)) + ) + ) + +; +; Overhang rules +; + +(define drc.min-overhang + (let ((overhang + (cond + ((string=? technology "SCN5M_DEEP.12") + '(("gate-pdiff" 4) + ("pdiff-gate" 4) + ("gate-poly" 2) + ("poly-gate" 2) + ("gate-ndiff" 4) + ("ndiff-gate" 4) + )) + (#t + '(("gate-pdiff" 3) + ("pdiff-gate" 3) + ("gate-poly" 2) + ("poly-gate" 2) + ("gate-ndiff" 3) + ("ndiff-gate" 3) + )) + ))) + (lambda (layer-name) (drc.find-name layer-name overhang)) + ) + ) diff --git a/lisp/scm/gate.scm b/lisp/scm/gate.scm new file mode 100644 index 00000000..09dad38b --- /dev/null +++ b/lisp/scm/gate.scm @@ -0,0 +1,193 @@ +;------------------------------------------------------------------------- +; +; Standard gates +; +; (c) 1996 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: gate.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +;------------------------------------------------------------------------- + + +;------------------------------------------------------------------------ +; Draw c-element +;------------------------------------------------------------------------ +(define gate.c + (eval + (list + 'lambda + (cons 'widthp (cons 'widthn (cons 'output 'names))) + '(begin + (if (and (and (number? widthn) (number? widthp)) + (and (string? output) (string-list? names))) + #t + (error "Usage: gate.c \"out\" \"n1\" \"n2\" ...") + ) + (box.push (getbox)) + (define pstk (stack.p widthp (cons '("Vdd!") (append names (list (list output)))))) + (box.move (+ widthp (drc.min-spacing "pdiff-ndiff")) 0) + (define nstk (stack.n widthn (cons '("GND!") (append names (list (list output)))))) + (box.pop) + (box.hull pstk nstk) + ) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Draw folded c-element +;------------------------------------------------------------------------ +(define gate.cf + (eval + (list + 'lambda + (cons 'widthp (cons 'widthn (cons 'output 'names))) + '(let ((plist (cons '("Vdd!") names)) + (nlist (cons '("GND!") names))) + (begin + (if (and (and (number? widthn) (number? widthp)) + (and (string? output) (string-list? names))) + #t + (error "Usage: gate.cf \"out\" \"n1\" \"n2\" ...") + ) + (box.push (getbox)) + (define pstk + (stack.p + widthp + (append (append plist (list (list output))) (reverse plist)) + ) + ) + (box.move (+ widthp (drc.min-spacing "pdiff-ndiff")) 0) + (define nstk + (stack.n + widthn + (append (append nlist (list (list output))) (reverse nlist)) + ) + ) + (box.pop) + (box.hull pstk nstk) + ) + ) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Draw inverter +;------------------------------------------------------------------------ +(define gate.inv + (lambda (widthp widthn output input) + (begin + (if (and (and (number? widthn) (number? widthp)) + (and (string? output) (string? input))) + #t + (error "Usage: gate.inv \"out\" \"inp\"") + ) + (box.push (getbox)) + (define pstk (stack.p widthp (list (list "Vdd!") input (list output)))) + (box.move (+ widthp (drc.min-spacing "pdiff-ndiff")) 0) + (define nstk (stack.n widthn (list (list "GND!") input (list output)))) + (box.pop) + (box.hull pstk nstk) + ) + ) + ) + +(define gate.nor ()) +(define gate.nand ()) + +(letrec + ( + (interleave-power-output + (lambda (name-list power output) ;even/odd is encoded by l/nl power + (if (null? name-list) (list + (if (string? power) (list power) (list output)) + ) + (cons (if (string? power) + (list power) + (list output) + ) + (cons (car name-list) + (interleave-power-output + (cdr name-list) + (if (string? power) (list power) (car power)) output) + ) + ) + ) + ) + ) + ) + (begin +;------------------------------------------------------------------------ +; Draw a nor gate +;------------------------------------------------------------------------ + (set! + gate.nor + (eval + (list + 'lambda + (cons 'widthp (cons 'widthn (cons 'output 'names))) + '(begin + (if (and (and (number? widthn) (number? widthp)) + (and (string? output) (string-list? names))) + #t + (error "Usage: gate.nor \"out\" \"n1\" \"n2\" ...") + ) + (box.push (getbox)) + (define pstk + (stack.p widthp (cons '("Vdd!") (append names (list (list output))))) + ) + (box.move (+ widthp (drc.min-spacing "pdiff-ndiff")) 0) + (define nstk + (stack.n widthn (interleave-power-output names "GND!" output)) + ) + (box.pop) + (box.hull pstk nstk) + ) + ) + ) + ) +;------------------------------------------------------------------------ +; Draw a nand gate +;------------------------------------------------------------------------ + (set! + gate.nand + (eval + (list + 'lambda + (cons 'widthp (cons 'widthn (cons 'output 'names))) + '(begin + (if (and (and (number? widthn) (number? widthp)) + (and (string? output) (string-list? names))) + #t + (error "Usage: gate.nand \"out\" \"n1\" \"n2\" ...") + ) + (box.push (getbox)) + (define pstk + (stack.p widthp (interleave-power-output names "Vdd!" output)) + ) + (box.move (+ widthp (drc.min-spacing "pdiff-ndiff")) 0) + (define nstk + (stack.n widthn (cons '("GND!") (append names (list (list output))))) + ) + (box.pop) + (box.hull pstk nstk) + ) + ) + ) + ) + ) + ) diff --git a/lisp/scm/help.scm b/lisp/scm/help.scm new file mode 100644 index 00000000..9ffcc5f7 --- /dev/null +++ b/lisp/scm/help.scm @@ -0,0 +1,168 @@ +;------------------------------------------------------------------------- +; +; (c) 1997 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; All Rights Reserved +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: help.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +;------------------------------------------------------------------------- + + +;------------------------------------------------------------------------ +; +; Help for scheme commands +; +;------------------------------------------------------------------------ + +(define scm-help ()) +(define scm-add-help ()) + + (letrec ( + (scm-help-list ()) + (module-name (lambda (x) (car x))) + (module-long-form (lambda (x) (cadr x))) + (module-fns (lambda (x) (caddr x))) + (dump-module-list + (lambda (l) + (if (null? l) #t + (begin + (echo + (string-append + (string-append (module-name (car l)) " :: ") + (module-long-form (car l)) + ) + ) + (dump-module-list (cdr l)) + ) + ) + ) + ) + (dump-help + (lambda (l name) + (cond ((null? l) (echo "Module not found")) + ((string=? (module-name (car l)) name) + (begin + (echo) + (echo (module-fns (car l)))) + ) + (#t (dump-help (cdr l) name)) + ) + ) + ) + ) + (begin + (set! scm-help + (lambda (name) + (cond ((and (procedure? name) + (eqv? name ?)) + (begin + (echo "Available help:") + (echo) + (dump-module-list scm-help-list) + (collect-garbage) + ) + ) + ((not (string? name)) + (echo "Argument to scm-help must be a string")) + ((string=? name "?") + (begin + (echo "Available modules:") (echo) + (dump-module-list scm-help-list) + (collect-garbage) + ) + ) + (#t (dump-help scm-help-list name)) + ) + ) + ) + (set! scm-add-help + (lambda (name long-form fns) + (set! scm-help-list (cons (list name long-form fns) scm-help-list)) + ) + ) + ) + ) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; +; Everyone should put their help file in their own particular +; implementation directory. +; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(scm-add-help + "sel" "Selection commands" +"Selection: + + :sel.netlist \"nm\" Selects a netlist labelled nm restricted by the box. + All labels named nm under the box are selected along + with whatever is electrically connected to them. + + :sel.push Pushes current selection onto selection stack + :sel.pop Pops top of selection stack + + :sel.cmp Compares current selection with the top-of-stack. The + List of labels that are different are bound to the label + search list and can be browsed using label.find-next." +) + + +(scm-add-help + "prs" "Production-rule drawing" +"Production rule drawing: + + :prs.draw w \"rule\" Draws transistor stacks for production rule with + diffusion width w. + + :prs.talldraw w \"rule\" Same as prs.draw, only doesn't squish out diffusion + between poly and contacts for intermediate nodes. + + :prs.mgn pw nw \"r1\" ... Draws list of rules, sharing contacts if possible. + + :prs.tallmgn pw nw \"r1\" Same as before, except unsquished diffusion." +) + +(scm-add-help + "label" "Label manipulation" +"Label Manipulation + + :label.rename \"n1\" \"n2\" renames all instances of n1 under the current + box with n2. + + :label.swap \"n1\" \"n2\" renames all instances of n1 with n2 and n2 with + n1 under the current box. + + :label.search \"n\" looks for all labels matching n under box. + :label.find-next moves box to the next label position." +) + +(scm-add-help + "gate" "Standard gates" +"Standard gate generation + +The gate generation commands are of the form + :command pw nw o i1 i2 ... iN +pw and nw specify the width of the p- and n-diffusion stacks. o is the output, +and i1 thru iN are the inputs. + + :gate.c pw nw o i1 .. iN C-element + :gate.cf pw nw o i1 .. iN Folded C-element + :gate.inv pw nw o i Inverter + :gate.nor pw nw o i1 .. iN NOR gate + :gate.nand pw nw o i1 .. iN NAND gate" +) diff --git a/lisp/scm/label.scm b/lisp/scm/label.scm new file mode 100644 index 00000000..900a7def --- /dev/null +++ b/lisp/scm/label.scm @@ -0,0 +1,292 @@ +;------------------------------------------------------------------------- +; +; Labels +; +; (c) 1996 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: label.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +; Requires: box.scm +; +;------------------------------------------------------------------------- + + +;------------------------------------------------------------------------ +; +; Create a labeller, horizontal or vertical +; +;------------------------------------------------------------------------ +(define label.vert ()) +(define label.horiz ()) + +(letrec ((labeller + (lambda (name) + (let ((x 0)) + (lambda () + (begin (label (string-append name (number->string x))) + (set! x (+ x 1)) + ) + ) + ) + ) + )) + (begin + (set! label.vert + (lambda (name bit-pitch) + (begin + (if (and (string? name) (number? bit-pitch)) + #t + (error "Usage: label.vert \"name\" ") + ) + (let ((lbl (labeller name))) + (lambda () (begin (lbl) (box.move 0 bit-pitch))) + ) + ) + ) + ) + (set! label.horiz + (lambda (name bit-pitch) + (begin + (if (and (string? name) (number? bit-pitch)) + #t + (error "Usage: label.horiz \"name\" ") + ) + (let ((lbl (labeller name))) + (lambda () (begin (lbl) (box.move bit-pitch 0))) + ) + ) + ) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Place a label at (1,1) relative to the bottom left of the current +; box. +;------------------------------------------------------------------------ +(define label.draw + (lambda (name layer) + (let* ((x (getbox)) (lx (+ 1 (car x))) (ly (+ 1 (cadr x)))) + (begin + (if (and (string? name) (string? layer)) + #t + (error "Usage: label.draw \"name\" \"layername\"") + ) + (box.push x) + (eval (cons 'box '(lx ly lx ly))) + (label name up layer) + (box.pop) + #t + ) + ) + ) + ) + + +;------------------------------------------------------------------------ +; +; Quote globbing characters +; +;------------------------------------------------------------------------ +(define label.backslashify ()) +(letrec ( + ; + ; put the list of characters you want backslashified here + ; + (quote-list (list (string-ref "[" 0) + (string-ref "]" 0) + (string-ref "*" 0))) + + ; + ; ah well . . . needs to be fixed, but can't without sacrificing + ; backward compatibility with old .src file; or by completely + ; changing command behavior when parsing .scm files. Ah well. + ; + (quoted-backslash (substring "\\" 0 1)) ; -sigh- whatever works + + (string-to-list-helper + (lambda (str pos) + (if (=? pos (string-length str)) () + (cons (substring str pos (+ pos 1)) + (string-to-list-helper str (+ 1 pos)) + ) + ) + ) + ) + + ; + ; Takes a string and cuts it into a list of strings each + ; containing a single character + ; + (string-to-list (lambda (str) (string-to-list-helper str 0))) + + ; + ; Appends a list of strings into a single one + ; + (list-to-string + (lambda (l) + (if (null? l) "" + (string-append (car l) (list-to-string (cdr l))) + ) + ) + ) + + ; + ; Checks to see if x is a member of l + ; + (is-member? (lambda (x l) + (cond ((null? l) #f) + ((=? x (car l)) #t) + (#t (is-member? x (cdr l))) + ) + ) + ) + + ; + ; Function that takes a one-character string and adds + ; a backslash to it if it has to be backslashified. + ; + (convert + (lambda (str) + (if (is-member? (string-ref str 0) quote-list) + (string-append quoted-backslash str) str) + ) + ) + ) +;------------------------------------------------------------------------ +; After all those helper functions in the nested scope, this function +; is just a one-liner . . . +;------------------------------------------------------------------------ + (set! label.backslashify + (lambda (str) (list-to-string (mapcar convert (string-to-list str)))) + ) + ) + +;------------------------------------------------------------------------ +; Rename all labels under the current box +;------------------------------------------------------------------------ +(define label.rename ()) +(define label.allren ()) +(define label.swap ()) + +(letrec ((rename-helper + (lambda (poslist name) + (if (null? poslist) + #t + (begin (eval (cons 'box (cddar poslist))) + (erase label) + (label name up (cadar poslist)) + (rename-helper (cdr poslist) name) + ) + ) + ) + )) + (begin + (set! label.rename + (lambda (name1 name2) + (begin + (if (and (string? name1) (string? name2)) + #t + (error "Usage: label.rename \"name1\" \"name2\"") + ) + (box.push (getbox)) + (rename-helper (getlabel (label.backslashify name1)) name2) + (box.pop) + ) + ) + ) + (set! label.allren + (lambda (name1 name2) + (begin + (if (and (string? name1) (string? name2)) + #t + (error "Usage: label.allren \"name1\" \"name2\"") + ) + (box.push (getbox)) + (rename-helper (getlabel name1) name2) + (box.pop) + ) + ) + ) + (set! label.swap + (lambda (name1 name2) + (begin + (if (and (string? name1) (string? name2)) + #t + (error "Usage: label.swap \"name1\" \"name2\"") + ) + (box.push (getbox)) + (define x1 (getlabel (label.backslashify name1))) + (define x2 (getlabel (label.backslashify name2))) + (rename-helper x1 name2) + (rename-helper x2 name1) + (box.pop) + ) + ) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Search for all labels matching a string under the current box. +;------------------------------------------------------------------------ +(define label.search ()) +(define label.find-next ()) +(define label.set! ()) +(define drc.search ()) +(define drc.find-next ()) + +(let ((label-list ()) (drc-list ())) + (begin + (set! label.set! (lambda (l) (set! label-list l))) + (set! drc.search (lambda () (set! drc-list (mapcar (lambda (l) (cons "err" l)) (getpaint "err"))))) + (set! label.search + (lambda (name) + (begin + (if (string? name) + #t + (error "Usage: label.search \"name\"") + ) + (set! label-list (getlabel name)) + ) + ) + ) + (set! label.find-next + (lambda () + (if (null? label-list) (echo "No more labels") + (begin + (eval (cons 'box (cddar label-list))) + (box w 2) + (box h 2) + (set! label-list (cdr label-list)) + ) + ) + ) + ) + (set! drc.find-next + (lambda () + (if (null? drc-list) (echo "No more labels") + (begin + (eval (cons 'box (cddar drc-list))) + (box w 2) + (box h 2) + (set! drc-list (cdr drc-list)) + ) + ) + ) + ) + ) + ) diff --git a/lisp/scm/layout.scm b/lisp/scm/layout.scm new file mode 100644 index 00000000..e72678e6 --- /dev/null +++ b/lisp/scm/layout.scm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------- +; +; Top-level layout file +; +; (c) 1996 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: layout.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +;------------------------------------------------------------------------- + +(echo "Loading modules:") +(echo -n "[help]") +(load-scm "help.scm") +(echo -n "[box]") +(load-scm "box.scm") +(echo -n "[drc]") +(collect-garbage) +(load-scm "drc.scm") +(echo -n "[label]") +(load-scm "label.scm") +(echo -n "[draw]") +(load-scm "draw.scm") +(collect-garbage) +(echo -n "[stack]") +(load-scm "stack.scm") +(echo -n "[prs]") +(load-scm "prs.scm") +(collect-garbage) +(echo -n "[gate]") +(load-scm "gate.scm") +(echo -n "[sel]") +(load-scm "sel.scm") +(echo "") +(collect-garbage) +(echo "Use scm-help ? for help on some scheme functions") diff --git a/lisp/scm/prs.scm b/lisp/scm/prs.scm new file mode 100644 index 00000000..c1a55f9b --- /dev/null +++ b/lisp/scm/prs.scm @@ -0,0 +1,1605 @@ +;------------------------------------------------------------------------- +; +; Drawing transistor stacks for production rules. +; +; (c) 1996 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: prs.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +;------------------------------------------------------------------------- + + +;------------------------------------------------------------------------------ +; +; Production rule parser +; ~~~~~~~~~~~~~~~~~~~~~~ +; +; (prs.parse "production-rule-string") +; +; Returns a parse tree for the production rule, or prints out an error +; message. +; +; A production rule is of the form: expr -> rhs [+/-] +; The resulting parse tree has the following format: +; +; Top level: (expr "rhs") +; expr: (and expr expr) +; (or expr expr) +; (not id) +; id +; +; Observe that the production rules must be in negation-normal form. +; +;------------------------------------------------------------------------------ +(define prs.parse ()) + +(letrec + ( + (parse-string "") ; the current string being parsed + (parse-position 0) ; current position in the string + (parse-string-len 0) ; string length + (or-char (string-ref "|" 0)) ; constants + (and-char (string-ref "&" 0)) + (not-char (string-ref "~" 0)) + (plus-char (string-ref "+" 0)) + (minus-char (string-ref "-" 0)) + (lparens-char (string-ref "(" 0)) + (rparens-char (string-ref ")" 0)) + + (startid? ; #t if the character is a valid + ; start character for an identifier + (let ((lc-a (string-ref "a" 0)) + (uc-a (string-ref "A" 0)) + (lc-z (string-ref "z" 0)) + (uc-z (string-ref "Z" 0)) + (us (string-ref "_" 0)) + ) + (lambda (x) + (cond + ((and (>=? x lc-a) (<=? x lc-z)) #t) + ((and (>=? x uc-a) (<=? x uc-z)) #t) + ((=? x us) #t) + (#t #f) + ) + ) + ) + ) + + (idchar? ; #t if the character is a valid + ; character in an identifier + (let ((lc-a (string-ref "a" 0)) + (uc-a (string-ref "A" 0)) + (lc-z (string-ref "z" 0)) + (uc-z (string-ref "Z" 0)) + (lbrack (string-ref "[" 0)) + (rbrack (string-ref "]" 0)) + (us (string-ref "_" 0)) + (dot (string-ref "." 0)) + (bang (string-ref "!" 0)) + (zero (string-ref "0" 0)) + (nine (string-ref "9" 0)) + ) + (lambda (x) + (cond + ((and (>=? x lc-a) (<=? x lc-z)) #t) + ((and (>=? x uc-a) (<=? x uc-z)) #t) + ((and (>=? x zero) (<=? x nine)) #t) + ((=? x us) #t) + ((=? x bang) #t) + ((=? x dot) #t) + ((=? x lbrack) #t) + ((=? x rbrack) #t) + (#t #f) + ) + ) + ) + ) + + (prs.error ; Print an error message out to the + ; screen, and abort evaluation + (lambda (str) + (begin + (echo + -n + (string-append + "Error" + (if (zero? parse-position) + "," + (string-append + ", parsed `" + (string-append (substring parse-string 0 parse-position) "',") + ) + ) + ) + ) + (echo -n "looking at: ") + (echo + (string-append + (string-append + "`" + (substring parse-string parse-position parse-string-len) + ) + "'" + ) + ) + (error str) + ) + ) + ) + + (have? ; #t if the next character matches + ; its argument exactly. If so, the + ; position in the string is advanced + ; and skip trailing whitespace. + (lambda (char) + (if (=? (string-ref parse-string parse-position) char) + (begin + (set! parse-position (+ parse-position 1)) + #t + ) + #f + ) + ) + ) + + (skipspace ; skip leading spaces + (lambda () + (cond ((=? parse-position parse-string-len) #t) + ((=? (string-ref parse-string parse-position) + (string-ref " " 0)) + (begin + (set! parse-position (+ parse-position 1)) + (skipspace) + ) + ) + (#t #t) + ) + ) + ) + + (skipchar ; Expect to see a specific character + ; and skip it. Report an error if + ; invalid character + (lambda (char) + (if (have? char) #t (prs.error (string-append + "Expected: " + (string-set! " " 0 char)) + ) + ) + ) + ) + + (skip ; Expect to see a string, and skip it + ; Reports an error otherwise. + ; len is the length of the string. + (lambda (str len) + (letrec + ((len2 (+ len parse-position)) + (helper + (lambda (pos1 pos2) + (cond + ((=? pos1 len) + (begin + (set! parse-position pos2) + #t + )) + ((=? pos2 len2) + (prs.error (string-append "Expected: " str))) + ((=? (string-ref parse-string pos2) + (string-ref str pos1)) + (helper (+ pos1 1) (+ pos2 1)) + ) + (#t (prs.error (string-append "Expected: " str))) + ) + ) + ) + ) + (helper 0 parse-position) + ) + ) + ) + + (expr ; Parse an expression + (lambda () + (begin + (define x (term)) + (cond + ((=? parse-position parse-string-len) x) + ((have? or-char) (begin (skipspace) (list 'or x (expr)))) + (#t x) + ) + ) + ) + ) + + (term ; Parse a term + (lambda () + (begin + (define x (factor)) + (cond + ((=? parse-position parse-string-len) x) + ((have? and-char) (begin (skipspace) (list 'and x (term)))) + (#t x) + ) + ) + ) + ) + + (factor ; parse a factor + (lambda () + (cond + ((have? not-char) (begin (skipspace) (list 'not (variable)))) + ((have? lparens-char) + (begin + (skipspace) + (define x (expr)) + (skipchar rparens-char) + (skipspace) + x + ) + ) + (#t (variable)) + ) + ) + ) + + (variable ; parse a variable + (lambda () + (letrec ((helper + (lambda (pos) + (cond + ((=? parse-string-len pos) pos) + ((idchar? (string-ref parse-string pos)) + (helper (+ pos 1)) + ) + (#t pos) + ) + ) + )) + (begin + (if (=? parse-string-len parse-position) + (prs.error "Expected an identifier") + #t) + (if (startid? (string-ref parse-string parse-position)) + #t + (prs.error "Expected an identifier") + ) + (define x (helper (+ parse-position 1))) + (define y (substring parse-string parse-position x)) + (set! parse-position x) + (skipspace) + y + ) + ) + ) + ) + ) + (set! + prs.parse + (lambda (str) + (begin + (set! parse-string str) + (set! parse-position 0) + (set! parse-string-len (string-length str)) + (skipspace) + (define x (expr)) + (skipspace) + (skip "->" 2) + (skipspace) + (define y (variable)) + (collect-garbage) + (cond ((have? plus-char) (list x y)) + ((have? minus-char) (list x y)) + (#t (prs.error "Expected a `+' or `-'")) + ) + ) + ) + ) + ) + + + +;------------------------------------------------------------------------------ +; +; Drawing a production rule +; ~~~~~~~~~~~~~~~~~~~~~~~~~ +; +; (prs.draw width "production-rule") +; +; Draws the transistor stacks for the specified production rules, +; with diffusion stacks "width" wide. +; +; +; (prs.mgn widthp widthn "prs1" "prs2" . . .) +; +; Draw transistor stacks for the production rules specified. The network +; is generated assuming that the rules for all the pull-up networks are +; pairwise mutually exclusive, and that the rules for all the pull-down +; networks are pairwise mutually exclusive. This permits a degree of +; gate-sharing. (Not currently implemented) +; +;------------------------------------------------------------------------------ +; +; Network description: +; +; ("node" ("gate" ref-to-node)) ("gate" ref-to-node) . . .) +; +; +; A stack: +; ("node" "edge" "node" "edge" "node" "edge") +; +; +; Temporary description: +; ("node" ref-to-a-stack ref-to-e1 ref-to-e2 . . .) +; +; edge = (label ref-v1 ref-v2), or (label) +; +; + +(define prs.net-add-edge ()) +(define prs.net-find ()) +(define prs.gen-stacks ()) + +(letrec + ( + (stacks-so-far ()) ; stacks that have been generated + ; by the algorithm so far + +;------------------------------------------------------------------------ +; Insert an empty list as the second element after the node for each +; node in the network. This is used for folding loops back into the main +; transistor stack chain, if possible. +;------------------------------------------------------------------------ + (add-empty-path + (lambda (net) + (if (null? net) #t + (begin + (set-cdr! (car net) (cons () (cdar net))) + (add-empty-path (cdr net)) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Delete leading edges which have already been inspected by the stack +; generation algorithm. Inspected edges have their node references +; deleted, and so the list representing the edge has length 1. +;------------------------------------------------------------------------ + (strip-used-edges + (lambda (noderef) + (cond + ((null? (cddr noderef)) #t) + ((=? (length (caddr noderef)) 1) + (begin (set-cdr! (cdr noderef) (cdddr noderef)) + (strip-used-edges noderef) + ) + ) + (#t #t) + ) + ) + ) + +;------------------------------------------------------------------------ +; Generate one stack, eliminating edges used from the graph. The stack +; begins from the node pointed to by network. +;------------------------------------------------------------------------ + (generate-stack + (lambda (network) + (if (null? (cddr network)) (list network) + (cons network + (cons + (car (caddr network)) + (begin + (define edge (caddr network)) + (define n1 (cadr edge)) + (define n2 (caddr edge)) + (set-cdr! (caddr network) ()) + (set-cdr! (cdr network) (cdddr network)) + (strip-used-edges n1) + (strip-used-edges n2) + (generate-stack (if (eqv? n1 network) n2 n1)) + ) + ) + ) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Returns the last-but-1 cons cell in a stack, setting a node to a loop +; node if it has been used in a previously defined stack. +;------------------------------------------------------------------------ + (last-but-1-element + (lambda (stk) + (if (null? (cddr stk)) stk (last-but-1-element (cdr stk))) + ) + ) + + +;------------------------------------------------------------------------ +; Generate all stacks. Iterate the stack generation phase until all edges +; have been inspected. +;------------------------------------------------------------------------ + (all-stacks + (lambda (network) + (cond + ((null? network) #t) + ((null? (cddar network)) (all-stacks (cdr network))) + (#t + (begin + (define stk (generate-stack (car network))) + (set! stacks-so-far (cons stk stacks-so-far)) + (all-stacks network) + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Last member of a list +;------------------------------------------------------------------------ + (listlast + (lambda (l) + (if (null? (cdr l)) (car l) (listlast (cdr l))) + ) + ) + + +;------------------------------------------------------------------------ +; Returns a list of all internal nodes in all stacks that need to be +; kept around. A node needs to be kept if there are two references to +; it. +;------------------------------------------------------------------------ + (all-used-contacts + (lambda (stacks) + (if (null? stacks) () + (append (loose-ends (car stacks)) (allends (cdr stacks))) + ) + ) + ) + +;------------------------------------------------------------------------ +; Return #t if string val is a member of list l. +;------------------------------------------------------------------------ + (ismember? + (lambda (val l) + (cond + ((null? l) #f) + ((string=? val (car l)) #t) + (#t (ismember? val (cdr l))) + ) + ) + ) + +;------------------------------------------------------------------------ +; Strip internal nodes that are not from in list l from the transistor +; stack. +;------------------------------------------------------------------------ + (stripothers-1 + (lambda (stack) + (cond + ((null? stack) ()) + ((list? (car stack)) + (if (>? (cadar stack) 1) + (cons (car stack) (stripothers-1 (cdr stack))) + (stripothers-1 (cdr stack)) + ) + ) + (#t (cons (car stack) (stripothers-1 (cdr stack)))) + ) + ) + ) + +;------------------------------------------------------------------------ +; Strip internal nodes that are not in list l from all the stacks. +;------------------------------------------------------------------------ + (stripothers + (lambda (stacks) + (if (null? stacks) () + (cons + (stripothers-1 (car stacks)) + (stripothers (cdr stacks)) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; #t if the character is a digit, #f otherwise. +;------------------------------------------------------------------------ + (digitchar? + (let ((zero (string-ref "0" 0)) + (nine (string-ref "9" 0)) + ) + (lambda (x) + (and (>=? x zero) (<=? x nine)) + ) + ) + ) + +;------------------------------------------------------------------------ +; Returns #t if the string represents an internal node +;------------------------------------------------------------------------ + (internal-node? + (let ((x (string-ref "_" 0))) + (lambda (str) + (if (=? (string-ref str 0) x) + (if (>? (string-length str) 1) + (if (digitchar? (string-ref str 1)) + #t + #f + ) + #f + ) + #f + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Initialize a node's usecount +;------------------------------------------------------------------------ + (set-usecount-1 + (lambda (stack) + (cond + ((null? stack) #t) + ((list? (car stack)) + (begin + (set-car! (cdar stack) + (if (number? (cadar stack)) + (+ 1 (cadar stack)) + (if (internal-node? (caar stack)) 1 2) + ) + ) + (set-usecount-1 (cdr stack)) + ) + ) + (#t (set-usecount-1 (cdr stack))) + ) + ) + ) + + (set-usecount + (lambda (stacks) + (cond + ((null? stacks) #t) + ((null? (car stacks)) (set-usecount (cdr stacks))) + (#t (begin (set-usecount-1 (car stacks)) + (set-usecount (cdr stacks))) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Eliminate all internal nodes that are not required to construct the +; transistor stacks. +;------------------------------------------------------------------------ + (strip-dummy-contacts + (lambda () + (begin + (set-usecount stacks-so-far) + (set! stacks-so-far (stripothers stacks-so-far)) + ) + ) + ) + +;------------------------------------------------------------------------ +; Returns #t if the stack is a loop stack. +;------------------------------------------------------------------------ + (isloop? + (lambda (stack) + (eqv? (car stack) (cadr (last-but-1-element stack))) + ) + ) + +;------------------------------------------------------------------------ +; Separate loop and non-loop stacks. +;------------------------------------------------------------------------ + (split-stacks + (lambda (stacks) + (if (null? stacks) (list () () ) + (let ((x (split-stacks (cdr stacks)))) + (if (isloop? (car stacks)) + (cons (cons (car stacks) (car x)) (cdr x)) + (cons (car x) (list (cons (car stacks) (cadr x)))) + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Add a path to an existing stack +;------------------------------------------------------------------------ + (addpath + (lambda (head stk) + (if (null? stk) #t + (begin + (if (list? (car stk)) + (if (null? (cadar stk)) + (set-car! (cdar stk) (list stk head)) + #t + ) + #t + ) + (addpath head (cdr stk)) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; See if there is a node on this path which belongs to an existing +; loop path +;------------------------------------------------------------------------ + (check-path + (lambda (stack) + (cond + ((null? stack) ()) + ((list? (car stack)) + (if (null? (cadar stack)) (check-path (cdr stack)) stack) + ) + (#t (check-path (cdr stack))) + ) + ) + ) + +;------------------------------------------------------------------------ +; Merge loop stacks +;------------------------------------------------------------------------ + (merge-loops + (lambda (stacks) + (if (null? stacks) #t + (begin + (define lb1 (last-but-1-element (car stacks))) + (define cur (check-path (car stacks))) + (addpath stacks (car stacks)) + (if (null? cur) (merge-loops (cdr stacks)) + (begin + (define cell (caadar cur)) + (define oldcdr (cdr cell)) + (define head (car stacks)) + + (set-cdr! cell (cdr cur)) + (set-cdr! lb1 head) + (set-cdr! cur oldcdr) + + (set-car! stacks ()) + (merge-loops (cdr stacks)) + ) + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Fix non-loops. +;------------------------------------------------------------------------ + (merge-nonloops + (lambda (stacks) + (if (null? stacks) #t + (begin + (define cur (check-path (car stacks))) + (if (null? cur) (merge-nonloops (cdr stacks)) + (begin + (define cell (caadar cur)) + (define oldcdr (cdr cur)) + (define head (car (cdadar cur))) + (if (zero? (length (car head))) + #t + (begin + (define lb1 (last-but-1-element (car head))) + + (set-cdr! cur (cdr cell)) + (set-cdr! lb1 (car head)) + (set-cdr! cell oldcdr) + + (set-car! head ()) + ) + ) + (merge-nonloops (cdr stacks)) + ) + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Match first/last with first/last +;------------------------------------------------------------------------ + (find-stack-match-1 + (lambda (first last stack) + (let ((x (car (reverse stack))) + (y (car stack))) + (cond + ((eqv? first y) 1) + ((eqv? first x) 2) + ((eqv? last y) 3) + ((eqv? last x) 4) + (#t ()) + ) + ) + ) + ) + + (find-stack-match + (lambda (first last stacks) + (cond ((null? stacks) ()) + ((null? (car stacks)) (find-stack-match first last (cdr stacks))) + (#t (let ((x (find-stack-match-1 first last (car stacks)))) + (if (null? x) + (find-stack-match first last (cdr stacks)) + (list x stacks) + ) + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Fix straight lines that might now be linked because of the merge +; loops with non-loops phase. +;------------------------------------------------------------------------ + (fix-non-loops + (lambda (stacks) + (if (null? stacks) #t + (if (null? (car stacks)) (fix-non-loops (cdr stacks)) + (begin + (define stk (find-stack-match + (caar stacks) + (car (reverse (car stacks))) + (cdr stacks) + ) + ) + (if (null? stk) #t + (begin + (define stks-new (cadr stk)) + (cond + ((=? (car stk) 1) + (begin + (define x (reverse (car stacks))) + (define y (last-but-1-element x)) + (set-cdr! y (car stks-new)) + (set-car! stks-new x) + ) + ) + ((=? (car stk) 2) + (begin + (define x (car stks-new)) + (define y (last-but-1-element x)) + (set-cdr! y (car stacks)) + ) + ) + ((=? (car stk) 3) + (begin + (define x (car stacks)) + (define y (last-but-1-element x)) + (set-cdr! y (car stks-new)) + (set-car! stks-new x) + ) + ) + (#t + (begin + (define x (reverse (car stacks))) + (define y (last-but-1-element (car stks-new))) + (set-cdr! y (car x)) + ) + ) + ) + (set-car! stacks ()) + ) + ) + (fix-non-loops (cdr stacks)) + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Fix loops. Fold any loops into existing stacks, if possible. +;------------------------------------------------------------------------ + (fix-loops + (lambda () + (begin + (define both (split-stacks stacks-so-far)) + (define loop (car both)) + (define non-loop (cadr both)) + (merge-loops loop) + (merge-nonloops non-loop) + (set! stacks-so-far (append loop non-loop)) + (fix-non-loops stacks-so-far) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Convert network node references into node names in a transistor stack. +; Given a node reference in a stack (in which case it would be a contact, +; which is represented by a ("name")---see stack.scm), the name is the +; first member of the node list. +;------------------------------------------------------------------------ + (refs-to-names + (lambda (stk) + (if (null? stk) () + (let ((x (if (list? (car stk)) (list (caar stk)) (car stk)))) + (cons x (refs-to-names (cdr stk)))) + ) + ) + ) + +;------------------------------------------------------------------------ +; Convert all network node references into node names. +;------------------------------------------------------------------------ + (cleanup-stacks + (lambda (stacks) + (cond + ((null? stacks) ()) + ((null? (car stacks)) (cleanup-stacks (cdr stacks))) + (#t (cons (refs-to-names (car stacks)) (cleanup-stacks (cdr stacks)))) + ) + ) + ) + +;------------------------------------------------------------------------ +; A contact is global if it ends in a ! +;------------------------------------------------------------------------ + (global-node? + (let ((bang (string-ref "!" 0))) + (lambda (str) + (=? bang (string-ref str (- (string-length str) 1))) + ) + ) + ) + +;------------------------------------------------------------------------ +; Locate a global variable contact if possible +;------------------------------------------------------------------------ + (locate-global-contact + (lambda (stack) + (if (null? stack) () + (if (list? (car stack)) + (if (global-node? (caar stack)) stack + (locate-global-contact (cdr stack)) + ) + (locate-global-contact (cdr stack)) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Locate any contact +;------------------------------------------------------------------------ + (locate-any-contact + (lambda (stack) + (if (null? stack) () + (if (list? (car stack)) + (if (internal-node? (caar stack)) + (locate-any-contact (cdr stack)) + stack + ) + (locate-any-contact (cdr stack)) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Locate a contact that is not an internal node +;------------------------------------------------------------------------ + (user-contact + (lambda (stack) + (begin + (define x (locate-global-contact stack)) + (if (null? x) (locate-any-contact stack) x) + ) + ) + ) + +;------------------------------------------------------------------------ +; Rotate a single stack if possible so that the end-point is not an +; internal node +;------------------------------------------------------------------------ + (loop-unravel + (lambda (stack) + (begin + (define x (user-contact stack)) + (if (null? x) stack + (begin + (define hd (list (car x))) + (define y (last-but-1-element stack)) + (set-cdr! hd (cdr x)) + (set-cdr! x ()) + (set-cdr! y stack) + hd + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; If one of the final stacks is a loop stack, then you should try to make +; sure that the end-points are not internal nodes, and are preferably +; global nodes. +;------------------------------------------------------------------------ + (rotate-loops + (lambda (stacks) + (if (null? stacks) #t + (cond + ((null? (car stacks)) (rotate-loops (cdr stacks))) + ((isloop? (car stacks)) + (begin + (cond + ((internal-node? (caaar stacks)) + (set-car! stacks (loop-unravel (car stacks))) + ) + ((not (global-node? (caaar stacks))) + (set-car! stacks (loop-unravel (car stacks))) + ) + (#t #t) + ) + (rotate-loops (cdr stacks)) + ) + ) + (#t (rotate-loops (cdr stacks))) + ) + ) + ) + ) + ) + + (begin + +;------------------------------------------------------------------------ +; Exported function: generate transistor stacks from a network +; description. +;------------------------------------------------------------------------ + (set! + prs.gen-stacks + (lambda (network) + (begin + (set! stacks-so-far ()) ; clear stacks + (add-empty-path network) ; add empty path + (all-stacks network) ; generate all stacks + (fix-loops) ; associate nodes with stacks + (rotate-loops stacks-so-far) ; rotate loops if possible so that + ; the stack ends are existing nodes + (strip-dummy-contacts) ; eliminate dummy nodes + (set! stacks-so-far (cleanup-stacks stacks-so-far)) + stacks-so-far ; return + ) + ) + ) + +;------------------------------------------------------------------------ +; find a node in a network. +;------------------------------------------------------------------------ + (set! + prs.net-find + (lambda (net node) + (cond + ((null? net) ()) + ((string=? (caar net) node) (car net)) + (#t (prs.net-find (cdr net) node)) + ) + ) + ) + +;------------------------------------------------------------------------ +; Add an edge to a network. Use this function to construct the network +; graph. +;------------------------------------------------------------------------ + (set! + prs.net-add-edge + (lambda (network n1 g n2) + (begin + (define ref-n1 (prs.net-find network n1)) ; find node 1 + (define ref-n2 (prs.net-find network n2)) ; find node 2 + (define edge (list g ref-n1 ref-n2)) ; create edge + (set-cdr! ref-n1 (cons edge (cdr ref-n1))) ; add edge to node 1 + (set-cdr! ref-n2 (cons edge (cdr ref-n2))) ; add edge to node 2 + ) + ) + ) + ) + ) + + +;------------------------------------------------------------------------ +(define prs.mgn ()) +(define prs.mgn-node ()) +(define prs.mgn-internal-node ()) +(define prs.mgn-init-p-net ()) +(define prs.mgn-init-n-net ()) +(define prs.mgn-edge ()) +(define prs.mgn-draw-p ()) +(define prs.mgn-draw-n ()) +(define prs.mgn-draw-tallp ()) +(define prs.mgn-draw-talln ()) +(define prs.draw ()) +(define prs.tallmgn ()) +(define prs.talldraw ()) +(define prs.draw-net ()) + +(letrec + ( + (gate.network ()) + (nodenumber 0) + +;------------------------------------------------------------------------ +; Generates a fresh internal node name +;------------------------------------------------------------------------ + (fresh-internal-node! + (lambda () + (begin + (define nn + (string-append (string-append "_" (number->string nodenumber)) "#") + ) + (set! nodenumber (+ 1 nodenumber)) + nn + ) + ) + ) + +;------------------------------------------------------------------------ +; Checks if "char" is the last non-whitespace character in "str" +;------------------------------------------------------------------------ + (ischarend? + (lambda (str char) + (letrec ((len (string-length str)) + (space (string-ref " " 0)) + (helper + (lambda (pos) + (cond + ((zero? pos) #f) + ((=? char (string-ref str pos)) #t) + ((=? space (string-ref str pos)) (helper (- pos 1))) + (#t #f) + ) + ) + )) + (helper (- len 1)) + ) + ) + ) + +;------------------------------------------------------------------------ +; Extracts production rules ending with the character specified by the +; first character in string "last". The production rules are specified +; by a list of strings. +;------------------------------------------------------------------------ + (getprs + (lambda (rule-list last) + (cond ((null? rule-list) ()) + ((ischarend? (car rule-list) (string-ref last 0)) + (cons (car rule-list) (getprs (cdr rule-list) last))) + (#t (getprs (cdr rule-list) last)) + ) + ) + ) + +;------------------------------------------------------------------------ +; +; Simple transistor network generation +; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +; +; Direct generation of a simple network for a production rule is done by +; the intuitive rules for drawing transistors for a pull-up/pull-down: +; +; Given two gate networks *-n1-* and *-n2-*, their and-combination is +; given by *-n1-+-n2-*, and their or-combination is given by +; *-n1-* +; `-n2-' +; In the first case, we need to generate a name for the intermediate +; node name in the network graph. +; +; A partial network *-n-* is represented by a list of potential edges. +; An edge (transistor) is a list (x "label" y), where x and y represent +; the end-points. If an end-point is not connected, it is a number (0). +; Connected end-points are strings. +; +; The or-combination of two networks is simply the union of the two +; networks, and the and-combination is generated by generating a new +; name for the intermediate node, connecting all right end-points of +; network n1 to that node, and connecting all left end-points of network +; n2 to the same node. The final network is the union of the two networks. +; +; The left and right end-points for the entire network corresponding to +; a pull-up/pull-down are connected to the power supply and output +; respectively. +; +;------------------------------------------------------------------------ + +;------------------------------------------------------------------------ +; Connect the right hanging nodes to str deleting any edges that were +; generated as a result, and return the new edge list. +;------------------------------------------------------------------------ + (fillright + (lambda (l str) + (cond + ((null? l) ()) + ((number? (caddar l)) + (begin + (set-car! (cddar l) str) + (if (number? (caar l)) + (cons (car l) (fillright (cdr l) str)) + (begin + (prs.net-add-edge gate.network (caar l) (cadar l) (caddar l)) + (fillright (cdr l) str) + ) + ) + ) + ) + (#t (cons (car l) (fillright (cdr l) str))) + ) + ) + ) + +;------------------------------------------------------------------------ +; Connect the left hanging edges to node str deleting any edges that +; were generated as a result, and return the new edge list. +;------------------------------------------------------------------------ + (fillleft + (lambda (l str) + (cond + ((null? l) ()) + ((number? (caar l)) + (begin + (set-car! (car l) str) + (if (number? (caddar l)) + (cons (car l) (fillleft (cdr l) str)) + (begin + (prs.net-add-edge gate.network (caar l) (cadar l) (caddar l)) + (fillleft (cdr l) str) + ) + ) + )) + (#t (cons (car l) (fillleft (cdr l) str))) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Generate the network for a boolean expression. "tree" is the parse tree +; for the expression, and "type" is zero for a pull-down chain and one +; for a pull-up chain. +;------------------------------------------------------------------------ + (gen-1-network + (lambda (tree type) + (cond + ((string? tree) + (if (zero? type) + (list (list 0 tree 0)) + (error "A pull-up must use inverted variables only") + ) + ) + ((eqv? 'not (car tree)) + (if (zero? type) + (error "A pull-down must use uninverted variables only") + (list (list 0 (cadr tree) 0)) + ) + ) + (#t + (begin + (define l (gen-1-network (cadr tree) type)) + (define r (gen-1-network (caddr tree) type)) + (if (eqv? 'and (car tree)) + (begin + (define nn (fresh-internal-node!)) + (set! gate.network (cons (list nn) gate.network)) + (set! l (fillright l nn)) + (set! r (fillleft r nn)) + ) + #t + ) + (append l r) + ) + ) + (#t (error "This should not happen!")) + ) + ) + ) + +;------------------------------------------------------------------------ +; Generate network corresponding to a production rule. +;------------------------------------------------------------------------ + (gen-one-network + (lambda (rule type) + (begin + (define prs (prs.parse rule)) + (define l (gen-1-network (car prs) type)) + (if (null? (prs.net-find gate.network (cadr prs))) + (set! gate.network (cons (list (cadr prs)) gate.network)) + #t + ) + (fillleft l (if (zero? type) "GND!" "Vdd!")) + (fillright l (cadr prs)) + ) + ) + ) + +;------------------------------------------------------------------------ +; Generate a network corresponding to all the rules. The rules must all be +; either describing pull-ups or pull-downs. +;------------------------------------------------------------------------ + (gen-network + (lambda (rules type) + (if (null? rules) #t + (begin + (gen-one-network (car rules) type) + (gen-network (cdr rules) type) + ) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Draw all the stacks in "stacks" with width "width" using function +; "draw", spaced horizontally by "spacing". +;------------------------------------------------------------------------ + (drawstacks + (lambda (draw width stacks spacing) + (if (null? stacks) + (begin + (box.move (uminus spacing) 0) + () + ) + (begin + (define ret-box (draw width (car stacks))) + (box.move spacing 0) + (define ret2-box (drawstacks draw width (cdr stacks) spacing)) + (if (null? ret2-box) + ret-box + (list (min (car ret-box) (car ret2-box)) + (min (cadr ret-box) (cadr ret2-box)) + (max (caddr ret-box) (caddr ret2-box)) + (max (cadddr ret-box) (cadddr ret2-box)) + ) + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Create and draw all the stacks for a set of rules. +;------------------------------------------------------------------------ + (genstacks + (lambda (draw width rules type supply) + (begin + (echo -n "Generating network...") + (set! gate.network (list (list supply))) + (gen-network rules type) + (echo -n "generating stacks...") + (define stacks (prs.gen-stacks gate.network)) + (echo "done.") + (drawstacks draw width stacks + (+ width + (max + (drc.min-spacing + (if (zero? type) "ndiff-ndiff" "pdiff-pdiff")) + (+ (drc.min-spacing "poly") + (* 2 (drc.min-overhang "gate-poly")) + ) + ) + ) + ) + ) + ) + ) + ) + (begin + (set! + prs.mgn-internal-node + (lambda () + (begin + (define nn (fresh-internal-node!)) + (set! gate.network (cons (list nn) gate.network)) + nn + ) + ) + ) + (set! + prs.mgn-node + (lambda (name) + (begin + (if (string? name) #t + (error "Usage: prs.mgn-node \"name\"") + ) + (set! gate.network (cons (list name) gate.network)) + name + ) + ) + ) + (set! + prs.mgn-init-p-net + (lambda () + (set! gate.network (list (list "Vdd!"))) + ) + ) + (set! + prs.mgn-init-n-net + (lambda () + (set! gate.network (list (list "GND!"))) + ) + ) + (set! + prs.mgn-edge + (lambda (n1 lab n2) + (if (string-list? (list n1 lab n2)) + (prs.net-add-edge gate.network n1 lab n2) + (error "Usage: prs.mgn-edge node1 \"gate\" node2") + ) + ) + ) + (set! + prs.mgn-draw-p + (lambda (width) + (begin + (if (number? width) + #t + (error "Usage: prs.mgn-draw-p ") + ) + (box.push (getbox)) + (echo -n "generating stacks...") + (define stacks (prs.gen-stacks gate.network)) + (echo "done.") + (define d + (drawstacks stack.p width stacks + (+ width + (max + (drc.min-spacing "pdiff-pdiff") + (+ (drc.min-spacing "poly") + (* 2 (drc.min-overhang "gate-poly")) + ) + ) + ) + )) + (box.pop) + (collect-garbage) + d + ) + ) + ) + (set! + prs.mgn-draw-n + (lambda (width) + (begin + (if (number? width) #t + (error "Usage: prs.mgn-draw-n ") + ) + (box.push (getbox)) + (echo -n "generating stacks...") + (define stacks (prs.gen-stacks gate.network)) + (echo "done.") + (define d + (drawstacks stack.n width stacks + (+ width + (max + (drc.min-spacing "ndiff-ndiff") + (+ (drc.min-spacing "poly") + (* 2 (drc.min-overhang "gate-poly")) + ) + ) + ) + )) + (box.pop) + (collect-garbage) + d + ) + ) + ) + (set! + prs.mgn-draw-tallp + (lambda (width) + (begin + (if (number? width) #t + (error "Usage: prs.mgn-draw-tallp ") + ) + (box.push (getbox)) + (echo -n "generating stacks...") + (define stacks (prs.gen-stacks gate.network)) + (echo "done.") + (define d + (drawstacks stack.tallp width stacks + (+ width + (max + (drc.min-spacing "pdiff-pdiff") + (+ (drc.min-spacing "poly") + (* 2 (drc.min-overhang "gate-poly")) + ) + ) + ) + )) + (box.pop) + (collect-garbage) + d + ) + ) + ) + (set! + prs.mgn-draw-talln + (lambda (width) + (begin + (if (number? width) #t + (error "Usage: prs.mgn-draw-talln ") + ) + (box.push (getbox)) + (echo -n "generating stacks...") + (define stacks (prs.gen-stacks gate.network)) + (echo "done.") + (define d + (drawstacks stack.talln width stacks + (+ width + (max + (drc.min-spacing "ndiff-ndiff") + (+ (drc.min-spacing "poly") + (* 2 (drc.min-overhang "gate-poly")) + ) + ) + ) + )) + (box.pop) + (collect-garbage) + d + ) + ) + ) + (set! + prs.mgn + (eval (list + 'lambda + (cons 'widthp (cons 'widthn 'rule-list)) + '(let* ((p-rules (getprs rule-list "+")) + (n-rules (getprs rule-list "-")) + ) + (begin + (if (and (and (number? widthp) (number? widthn)) + (string-list? rule-list)) + #t + (error "Usage: prs.mgn \"prs1\" ...") + ) + (box.push (getbox)) + (define r1 + (genstacks stack.p widthp p-rules 1 "Vdd!") + ) + (box.move (+ widthp (drc.min-spacing "pdiff-ndiff")) 0) + (define r2 + (genstacks stack.n widthn n-rules 0 "GND!") + ) + (box.pop) + (collect-garbage) + (list r1 r2) + ) + ) + ) + ) + ) + (set! + prs.draw + (lambda (width rule) + (let + ((x (list rule))) + (begin + (if (and (number? width) (string? rule)) #t + (error "Usage: prs.draw \"prs\"") + ) + (if (ischarend? rule (string-ref "+" 0)) + (genstacks stack.p width x 1 "Vdd!") + (genstacks stack.n width x 0 "GND!") + ) + ) + ) + ) + ) + (set! + prs.draw-net + (lambda (rule) + (begin + (if (string? rule) #t + (error "Usage: prs.draw-net \"prs\"") + ) + (if (ischarend? rule (string-ref "+" 0)) + (gen-one-network rule 1) + (gen-one-network rule 0) + ) + ) + ) + ) + (set! + prs.tallmgn + (eval (list + 'lambda + (cons 'widthp (cons 'widthn 'rule-list)) + '(let* ((p-rules (getprs rule-list "+")) + (n-rules (getprs rule-list "-")) + ) + (begin + (if (and (and (number? widthp) (number? widthn)) + (string-list? rule-list)) + #t + (error "Usage: prs.tallmgn \"prs1\" ...") + ) + (box.push (getbox)) + (define r1 + (genstacks stack.tallp widthp p-rules 1 "Vdd!") + ) + (box.move (+ widthp (drc.min-spacing "pdiff-ndiff")) 0) + (define r2 + (genstacks stack.talln widthn n-rules 0 "GND!") + ) + (box.pop) + (collect-garbage) + (list r1 r2) + ) + ) + ) + ) + ) + (set! + prs.talldraw + (lambda (width rule) + (let + ((x (list rule))) + (begin + (if (and (number? width) (string? rule)) #t + (error "Usage: prs.talldraw \"prs\"") + ) + (if (ischarend? rule (string-ref "+" 0)) + (genstacks stack.tallp width x 1 "Vdd!") + (genstacks stack.talln width x 0 "GND!") + ) + ) + ) + ) + ) + ) + ) + + +(define prs.mgn-fresh-node + (let ((x 0)) + (lambda () + (begin + (define name (string-append + (string-append "_i" (number->string x)) + "#" + ) + ) + (set! x (+ x 1)) + (prs.mgn-node name) + ) + ) + ) + ) + +(define prs.mgn-output-edge + (lambda (a b c) + (prs.mgn-edge a b c) + ) + ) + diff --git a/lisp/scm/sel.scm b/lisp/scm/sel.scm new file mode 100644 index 00000000..c8053d15 --- /dev/null +++ b/lisp/scm/sel.scm @@ -0,0 +1,154 @@ +;------------------------------------------------------------------------- +; +; (c) 1997 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; All Rights Reserved +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: sel.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +;------------------------------------------------------------------------- + + +;------------------------------------------------------------------------ +; Extract fields from label return value +;------------------------------------------------------------------------ +(define label.ret-pos (lambda (l) (cddr l))) +(define label.ret-name (lambda (l) (car l))) +(define label.ret-layer (lambda (l) (cadr l))) + + +;------------------------------------------------------------------------ +; Select all netlists from the labels under the current box which match +; the specified name. +;------------------------------------------------------------------------ +(define sel.netlist + (letrec ( + (sel-netlist-helper + (lambda (l) + (if (null? l) #t + (begin + (eval (cons 'box (label.ret-pos (car l)))) + (repeat 6 (lambda () (select more box (label.ret-layer (car l))))) + (sel-netlist-helper (cdr l)) + ) + ) + ) + ) + ) + (lambda (name) + (begin + (if (string? name) #t + (error "Usage: sel.netlist \"name\"") + ) + (box.push (getbox)) + (define x (getlabel name)) + (if (null? x) + (echo "No netlist selected") + (sel-netlist-helper x) + ) + (box.pop) + ) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Compare two selections +;------------------------------------------------------------------------ +(define sel.stack ()) +(define sel.push + (lambda () + (set! sel.stack (cons (getsellabel "*") sel.stack)) + ) + ) + +(define sel.pop + (lambda () + (if (null? sel.stack) + (echo "Selection stack is empty") + (set! sel.stack (cdr sel.stack)) + ) + ) + ) + + +(define sel.cmp + (letrec ((equal-labs + (lambda (a b) + (and + (and + (string=? (car a) (car b)) + (string=? (cadr a) (cadr b)) + ) + (and + (=? (caddr a) (caddr b)) + (=? (cadddr a) (cadddr b)) + ) + ) + ) + ) + (search + (lambda (a b) + (cond ((null? b) #f) + ((equal-labs a (car b)) #t) + (#t (search a (cdr b))) + ) + ) + ) + (helper + (lambda (a b c) + (cond ((null? a) c) + ((search (car a) b) (helper (cdr a) b c)) + (#t (helper (cdr a) b (cons (car a) c))) + ) + ) + ) + ) + (lambda () + (if (null? sel.stack) + (echo "Selection stack is empty") + (begin + (define x (getsellabel "*")) + (label.set! + (append (helper x (car sel.stack) (list)) + (helper (car sel.stack) x (list)) + ) + ) + (set! x ()) + (collect-garbage) + ) + ) + ) + ) + ) + +(define duplabel + (lambda () + (begin + (box.push (getbox)) + (select clear) + (define x (getpoint)) + (set! x (list (car x) (cadr x) (car x) (cadr x))) + (repeat 6 (lambda () (select more))) + (define y (getsellabel "*")) + (apply box x) + (select clear) + (if (=? 0 (length y)) + (begin (error "duplabel: no labels on netlist") (box.pop)) + (label (caar y)) + ) + (box.pop) + ) + ) + ) diff --git a/lisp/scm/stack.scm b/lisp/scm/stack.scm new file mode 100644 index 00000000..a4537ac6 --- /dev/null +++ b/lisp/scm/stack.scm @@ -0,0 +1,517 @@ +;------------------------------------------------------------------------- +; +; Transistor stacks +; +; (c) 1996 California Institute of Technology +; Department of Computer Science +; Pasadena, CA 91125. +; +; Permission to use, copy, modify, and distribute this software +; and its documentation for any purpose and without fee is hereby +; granted, provided that the above copyright notice appear in all +; copies. The California Institute of Technology makes no representations +; about the suitability of this software for any purpose. It is +; provided "as is" without express or implied warranty. Export of this +; software outside of the United States of America may require an +; export license. +; +; $Id: stack.scm,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +; +;------------------------------------------------------------------------- + + +(define stack.p ()) +(define stack.n ()) +(define stack.tallp ()) +(define stack.talln ()) + +(letrec + ( + (flush-left-contacts 0) ; # of contacts that were placed + ; flush left in the middle of a + ; stack + + +;------------------------------------------------------------------------ +; The height of the transistor stack, assuming that the poly wires were +; not jogged and that there were no contacts in the middle of the +; stack. +;------------------------------------------------------------------------ + (height-raw + (lambda (num-transistors type) + (+ (+ (* (- num-transistors 1) + (+ (drc.min-spacing "poly") (drc.min-width "poly")) + ) + (* 2 (drc.min-overhang (string-append "gate-" + (string-append type "diff") + ) + ) + ) + ) + (drc.min-width "poly") + ) + ) + ) + +;------------------------------------------------------------------------ +; The height of the transistor stack +;------------------------------------------------------------------------ + (height + (lambda (num-transistors type) + (+ (height-raw num-transistors type) + (* flush-left-contacts (- (+ (* 2 (drc.min-spacing "contact-gate")) + (drc.min-width "contact") + ) + (drc.min-spacing "poly") + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Draw a poly wire. The wire jogs around contacts and is spaced so that +; there all the diffusion between the contact/poly/poly is squished out. +; Returns the new position of "dx" +;------------------------------------------------------------------------ + (draw-poly + (lambda (name dx y fullwidth a0 a1 a2 a3) + (let* ((cur (getbox)) + (nx (+ (car cur) dx)) + (cury (cadr cur)) + ) + (begin + (if (>? dx a2) + (begin + (box (car cur) cury (+ (car cur) fullwidth) (+ cury a3)) + (paint "poly") + ) + (begin + (box (car cur) cury (+ nx a0) (+ cury a3)) + (paint "poly") + (box (+ nx a1) (- cury y) (+ nx a0) cury) + (paint "poly") + (box (+ nx a1) (- cury y) + (+ (car cur) fullwidth) (+ (- cury y) a3) + ) + (paint "poly") + ) + ) + (eval (cons 'box cur)) + (if (positive? (string-length name)) + (label.draw name "poly") + () + ) + (box (car cur) (+ cury a0) (car cur) (+ cury a0)) + (+ dx a0) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Draw a contact. Placed in the "notch" of a poly wire if possible, or +; placed flush left. Returns the new "dx" value. +;------------------------------------------------------------------------ + (draw-contact + (lambda (name dx y a0 a1 a2 a3 a4 a5 yinc newdx type lastcontact big) + (let* ((cur (getbox)) + (nx (+ (car cur) dx)) + (cury (cadr cur)) + ) + (begin + (if (>? dx a0) + (begin + (set! flush-left-contacts + (+ flush-left-contacts (if lastcontact 0 1)) + ) + (box (+ (car cur) a4) (+ (- cury a5) a1) + (+ (+ (car cur) a4) a2) (+ (- cury a5) a3) + ) + (paint type) + (if (positive? (string-length name)) + (label.draw name type) + () + ) + (box (car cur) (+ cury y) (car cur) (+ cury y)) + (if lastcontact big newdx) + ) + (begin + (box (+ nx a1) (+ (- (- cury y) a5) a1) + (+ nx a3) (+ (- (- cury y) a5) a3)) + (paint type) + (if (positive? (string-length name)) + (label.draw name type) + () + ) + (box (car cur) cury (car cur) cury) + (if lastcontact dx (+ dx y)) + ) + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Actually draws the stacks. c-name is either "pdc" or "ndc", depending +; on the type of stack. +;------------------------------------------------------------------------ + (drawing-aux + (let* ( + (ca1 (drc.min-spacing "contact-gate")) + (ca2 (drc.min-width "contact")) + (ca3 (+ ca1 ca2)) + (ca4 (drc.min-overhang "poly-gate")) + (ca5 (drc.min-spacing "poly")) + (ca6 (drc.min-width "poly")) + (dxp (drc.min-overhang "pdiff-gate")) + (dxn (drc.min-overhang "ndiff-gate")) + (y (max 0 (+ ca2 (- (* 2 ca1) ca5)))) + ) + (lambda (nl gw dx c-name) + (if (null? nl) + (list dx y) + (drawing-aux + (cdr nl) gw + (if (list? (car nl)) + (draw-contact (caar nl) dx y (- (- gw ca1) ca2) + ca1 ca2 ca3 ca4 ca5 + (+ ca5 ca6) + (- (+ ca4 ca3) ca5) + c-name (null? (cdr nl)) (+ gw ca4) + ) + (draw-poly (car nl) dx y (+ gw ca4) + (+ ca5 ca6) ca5 + (- (- gw (+ ca5 ca6)) + (if (=? (string-ref c-name 0) + (string-ref "p" 0) + ) + dxp + dxn)) + ca6) + ) + c-name + ) + ) + ) + ) + ) + +;------------------------------------------------------------------------ +; Returns the number of gates in the stack. +;------------------------------------------------------------------------ + (count-gates + (lambda (l) + (if (null? l) 0 + (+ (count-gates (cdr l)) (if (list? (car l)) 0 1)) + ) + ) + ) + + +;------------------------------------------------------------------------ +; Draws the transistor stacks and paints the diffusion layers. +;------------------------------------------------------------------------ + (pn + (lambda (name-list gate-width type) + (let* ((dx-y + (begin (box.push (getbox)) + (set! flush-left-contacts 0) + (if (list? (car name-list)) + (begin + (box.move 0 + (- (drc.min-overhang + (string-append + "gate-" + (string-append type "diff")) + ) + (+ (drc.min-width "contact") + (drc.min-spacing "contact-gate") + ) + ) + ) + (draw.layer (string-append type "dc") + (drc.min-width "contact") + (drc.min-width "contact") + ) + (if (positive? (string-length (caar name-list))) + (label.draw (caar name-list) (string-append type "dc")) + () + ) + (box.move (uminus (drc.min-overhang "gate-poly")) + (+ (drc.min-width "contact") + (drc.min-spacing "contact-gate") + ) + + ) + (drawing-aux (cdr name-list) + (+ gate-width + (drc.min-overhang "gate-poly") + ) + gate-width + (string-append type "dc") + ) + ) + (begin + (box.move (uminus (drc.min-overhang "gate-poly")) + (drc.min-overhang "gate-pdiff") + ) + (drawing-aux name-list + (+ gate-width + (drc.min-overhang "gate-poly") + ) + gate-width + (string-append type "dc") + ) + ) + ) + ) + ) + (dx (car dx-y)) + (y (cadr dx-y)) + (strip (+ (- dx (drc.min-overhang "poly-gate")) + (drc.min-overhang (string-append type "diff-gate")) + )) + ) + (begin + (box.pop) + (define ret-box + (draw.layer (string-append type "diff") (min strip gate-width) + (height (count-gates name-list) type)) + ) + (if ( stack-desc") + ) + (pn p-list gate-width "p") + ) + ) + ) +;------------------------------------------------------------------------ +; Draw n-transistor stack, jogging poly to remove diffusion +;------------------------------------------------------------------------ + (set! stack.n + (lambda (gate-width n-list) + (begin + (if (and (number? gate-width) (is-a-stack? n-list)) + #t + (error "Usage: stack.n stack-desc") + ) + (pn n-list gate-width "n") + ) + ) + ) +;------------------------------------------------------------------------ +; Draw p-transistor stack, straight poly +;------------------------------------------------------------------------ + (set! stack.tallp + (lambda (gate-width p-list) + (begin + (if (and (number? gate-width) (is-a-stack? p-list)) + #t + (error "Usage: stack.tallp stack-desc") + ) + (pntall p-list gate-width "p") + ) + ) + ) +;------------------------------------------------------------------------ +; Draw n-transistor stack, straight poly +;------------------------------------------------------------------------ + (set! stack.talln + (lambda (gate-width n-list) + (begin + (if (and (number? gate-width) (is-a-stack? n-list)) + #t + (error "Usage: stack.talln stack-desc") + ) + (pntall n-list gate-width "n") + ) + ) + ) + ) + ) diff --git a/magic/Depend b/magic/Depend new file mode 100644 index 00000000..5393d58d --- /dev/null +++ b/magic/Depend @@ -0,0 +1 @@ +magicTop.o: magicTop.c ../utils/magic.h ../utils/malloc.h diff --git a/magic/Makefile b/magic/Makefile new file mode 100644 index 00000000..42c9ae23 --- /dev/null +++ b/magic/Makefile @@ -0,0 +1,70 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/magic/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +MODULE = magic +MAGICDIR = .. +SRCS = magicTop.c + +include ${MAGICDIR}/defs.mak + +EXTRA_LIBS = ${MAGICDIR}/cmwind/libcmwind.o ${MAGICDIR}/commands/libcommands.o \ + ${MAGICDIR}/database/libdatabase.o ${MAGICDIR}/dbwind/libdbwind.o \ + ${MAGICDIR}/drc/libdrc.o ${MAGICDIR}/debug/libdebug.o \ + ${MAGICDIR}/extract/libextract.o ${MAGICDIR}/graphics/libgraphics.o \ + ${MAGICDIR}/select/libselect.o ${MAGICDIR}/textio/libtextio.o \ + ${MAGICDIR}/tiles/libtiles.o ${MAGICDIR}/windows/libwindows.o \ + ${MAGICDIR}/wiring/libwiring.o ${MAGICDIR}/resis/libresis.o \ + ${MAGICDIR}/sim/libsim.o ${MAGICDIR}/netmenu/libnetmenu.o \ + ${MAGICDIR}/plow/libplow.o ${MAGICDIR}/utils/libutils.o \ + ${MAIN_EXTRA_LIBS} + +BITMAPS = up.xbm down.xbm left.xbm right.xbm zoom.xbm lock.xbm +DEST_XBM = $(BITMAPS:%=$(DESTDIR)${TCLDIR}/bitmaps/%) + +DFLAGS += -DMAGIC_DATE="\"`date`\"" +LIBS += ${GR_LIBS} ${READLINE_LIBS} -lm ${LD_EXTRA_LIBS} \ + ${OA_LIBS} ${TOP_EXTRA_LIBS} +CLEANS += tclmagic${SHDLIB_EXT} libtclmagic${SHDLIB_EXT}.a proto.magicrc + +main: magic proto.magicrc + +tcl-main: tclmagic${SHDLIB_EXT} proto.magicrc + +tclmagic${SHDLIB_EXT}: ${EXTRA_LIBS} + @echo --- making magic Tcl library \(tclmagic${SHDLIB_EXT}\) + ${RM} tclmagic${SHDLIB_EXT} + ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} ${LD_RUN_PATH} \ + ${EXTRA_LIBS} -lc ${LIBS} + +proto.magicrc: proto.magicrc.m4 + sed -e /CAD_DIR/s%CAD_DIR%${LIBDIR}%g proto.magicrc.m4 | \ + ${M4} ${GR_DFLAGS} ${DFLAGS} > proto.magicrc + +install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${SYSDIR}/.magicrc \ + $(DESTDIR)${SYSDIR}/magicps.pro + +install-tcl: $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} $(DESTDIR)${SYSDIR}/.magicrc \ + $(DESTDIR)${SYSDIR}/.initrc $(DESTDIR)${SYSDIR}/magicps.pro ${DEST_XBM} + +$(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT}: tclmagic${SHDLIB_EXT} + ${RM} $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} + ${CP} tclmagic${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} + +$(DESTDIR)${TCLDIR}/bitmaps/%: bitmaps/% + ${RM} $(DESTDIR)${TCLDIR}/bitmaps/$* + ${CP} bitmaps/$* $(DESTDIR)${TCLDIR}/bitmaps/$* + +$(DESTDIR)${SYSDIR}/.magicrc: proto.magicrc + ${RM} $(DESTDIR)${SYSDIR}/.magicrc + ${CP} proto.magicrc $(DESTDIR)${SYSDIR}/.magicrc + +$(DESTDIR)${SYSDIR}/.initrc: proto.initrc + ${RM} $(DESTDIR)${SYSDIR}/.initrc + ${CP} proto.initrc $(DESTDIR)${SYSDIR}/.initrc + +$(DESTDIR)${SYSDIR}/magicps.pro: magicps.pro + ${RM} $(DESTDIR)${SYSDIR}/magicps.pro + ${CP} magicps.pro $(DESTDIR)${SYSDIR}/magicps.pro + +include ${MAGICDIR}/rules.mak diff --git a/magic/bitmaps/down.xbm b/magic/bitmaps/down.xbm new file mode 100644 index 00000000..2e191d69 --- /dev/null +++ b/magic/bitmaps/down.xbm @@ -0,0 +1,6 @@ +#define down_width 13 +#define down_height 13 +static unsigned char down_bits[] = { + 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, + 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07, 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, + 0x40, 0x00}; diff --git a/magic/bitmaps/left.xbm b/magic/bitmaps/left.xbm new file mode 100644 index 00000000..581acbc9 --- /dev/null +++ b/magic/bitmaps/left.xbm @@ -0,0 +1,6 @@ +#define left_width 13 +#define left_height 13 +static unsigned char left_bits[] = { + 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 0x7c, 0x00, 0xfe, 0x1f, + 0xff, 0x1f, 0xfe, 0x1f, 0x7c, 0x00, 0x78, 0x00, 0x70, 0x00, 0x60, 0x00, + 0x40, 0x00}; diff --git a/magic/bitmaps/lock.xbm b/magic/bitmaps/lock.xbm new file mode 100644 index 00000000..4521c1fc --- /dev/null +++ b/magic/bitmaps/lock.xbm @@ -0,0 +1,6 @@ +#define lock_width 13 +#define lock_height 13 +static unsigned char lock_bits[] = { + 0x00, 0x00, 0xe0, 0x00, 0x10, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, + 0xfc, 0x07, 0xfc, 0x07, 0xbc, 0x07, 0xbc, 0x07, 0xbc, 0x07, 0xfc, 0x07, + 0x00, 0x00}; diff --git a/magic/bitmaps/right.xbm b/magic/bitmaps/right.xbm new file mode 100644 index 00000000..1a4dfcc0 --- /dev/null +++ b/magic/bitmaps/right.xbm @@ -0,0 +1,6 @@ +#define right_width 13 +#define right_height 13 +static unsigned char right_bits[] = { + 0x40, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x03, 0xc0, 0x07, 0xff, 0x0f, + 0xff, 0x1f, 0xff, 0x0f, 0xc0, 0x07, 0xc0, 0x03, 0xc0, 0x01, 0xc0, 0x00, + 0x40, 0x00}; diff --git a/magic/bitmaps/up.xbm b/magic/bitmaps/up.xbm new file mode 100644 index 00000000..1f061282 --- /dev/null +++ b/magic/bitmaps/up.xbm @@ -0,0 +1,6 @@ +#define up_width 13 +#define up_height 13 +static unsigned char up_bits[] = { + 0x40, 0x00, 0xe0, 0x00, 0xf0, 0x01, 0xf8, 0x03, 0xfc, 0x07, 0xfe, 0x0f, + 0xff, 0x1f, 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, + 0xe0, 0x00}; diff --git a/magic/bitmaps/zoom.xbm b/magic/bitmaps/zoom.xbm new file mode 100644 index 00000000..5ecbeae3 --- /dev/null +++ b/magic/bitmaps/zoom.xbm @@ -0,0 +1,6 @@ +#define zoom_width 13 +#define zoom_height 13 +static unsigned char zoom_bits[] = { + 0xff, 0x1f, 0xff, 0x1f, 0x03, 0x18, 0x03, 0x18, 0xf3, 0x19, 0xf3, 0x19, + 0xb3, 0x19, 0xf3, 0x19, 0xf3, 0x19, 0x03, 0x18, 0x03, 0x18, 0xff, 0x1f, + 0xff, 0x1f}; diff --git a/magic/magicTop.c b/magic/magicTop.c new file mode 100644 index 00000000..f81fa04d --- /dev/null +++ b/magic/magicTop.c @@ -0,0 +1,65 @@ +/* magicTop.c - + * + * The top level of the Magic VLSI Layout system. + * + * This top level is purposely very short and is located directly in + * the directory used to remake Magic. This is so that other + * programs may use all of Magic as a library but still provide their + * own 'main' procedure. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/magic/magicTop.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/malloc.h" + +/*--------------------------------------------------------------------------- + * main: + * + * Top level of Magic. Do NOT add code to this routine, as all code + * should go into `main.c' in the `main' directory. + * + * Results: + * None. + * + * Side Effects: + * Invokes Magic to edit a VLSI design. + * + *---------------------------------------------------------------------------- + */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + magicMain(argc, argv); + exit(0); +} + +/* String containing the version number of magic. Don't change the string + * here, nor its format. It is updated by the Makefile in this directory. + * + * The version string originates at the top of scripts/config. + */ + +char *MagicVersion = MAGIC_VERSION; +char *MagicRevision = MAGIC_REVISION; +char *MagicCompileTime = MAGIC_DATE; diff --git a/magic/magicps.pro b/magic/magicps.pro new file mode 100644 index 00000000..d0561dd8 --- /dev/null +++ b/magic/magicps.pro @@ -0,0 +1,71 @@ +%%BeginProlog +% +% PostScript prolog for output from magic plot +% Version: 1.0 +% written by Tim Edwards 4/05/00 JHU Applied Physics Laboratory +% +%%BeginResource: procset MAGICproc 1.0 1 +% supporting definitions + +/MAGICsave save def + +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/ninit { /nChars matrix currentmatrix dup 0 get 0 eq {1} {0} + ifelse get abs 72 8.5 mul mul 64 div ceiling cvi def } def +/minit { 1 1 dtransform abs dup 1 exch div /onePix exch def + dup /resY exch def 1 exch div /iresY exch def + abs dup /resX exch def 1 exch div /iresX exch def + /bX 64 iresX mul def /bY 64 iresY mul def + /pattFont StipplePattern definefont pop + /patterns /pattFont findfont [iresX 64 mul 0 0 iresY 64 mul 0 0] makefont def + /ca nChars 1 add string def + } def +/StipplePattern 45 dict def +StipplePattern begin + /FontType 3 def + /FontMatrix [1 0 0 1 0 0] def + /FontBBox [0 0 1 1] def + /Encoding 256 array def + /PattName (P0) def + /tmpStr 1 string def + /NoPatt {<00>} def + 0 1 255 { Encoding exch /NoPatt put } for + /BuildChar { + 1 0 0 0 1 1 setcachedevice exch begin Encoding exch get load + 64 64 true [64 0 0 64 0 0] 5 -1 roll imagemask end } def +end +/dp { StipplePattern begin dup 30 tmpStr cvrs PattName exch 1 exch + putinterval PattName cvn dup Encoding exch 4 -1 roll exch put exch + store end } def +/sf { findfont exch scalefont setfont } bind def +/sp { patterns setfont 2 setlinewidth } def +/lb { gsave translate 0 0 moveto /just exch def gsave dup true charpath + flattenpath pathbbox grestore exch 4 -1 roll exch sub 3 1 roll sub + just 4 and 0 gt {just 8 and 0 eq {0.5 mul} if}{pop 0} ifelse exch + just 1 and 0 gt {just 2 and 0 eq {0.5 mul} if}{pop 0} ifelse exch + rmoveto show grestore } def +/sl { 0 1 nChars { exch dup 3 1 roll ca 3 1 roll put } for pop } def +/sc { setcmykcolor } bind def +/l1 { onePix setlinewidth } def +/l2 { onePix 2 mul setlinewidth } def +/l3 { onePix 3 mul setlinewidth } def +/ml { moveto lineto stroke } bind def +/vl { moveto 0 exch rlineto stroke } bind def +/hl { moveto 0 rlineto stroke } bind def +/mr { rectstroke } bind def +/ms { rectfill } bind def +/mx { 4 copy rectstroke 4 -1 roll 4 -1 roll 4 copy moveto rlineto stroke + 3 -1 roll dup neg 4 1 roll add moveto rlineto stroke } bind def +/pl { gsave translate /d exch def 0 d neg moveto 0 d lineto stroke + d neg 0 moveto d 0 lineto stroke grestore } bind def +/bx { x resX mul cvi 63 not and dup iresX mul exch + w resX mul sub abs 63 add cvi 64 idiv /w exch def + y resY mul cvi 63 not and dup iresY mul exch + h resY mul sub abs 63 add cvi 64 idiv /h exch def + /ch ca 0 w getinterval def + moveto h { ch gsave show grestore 0 bY rmoveto } repeat grestore } def +/fb {/h exch def /w exch def /y exch def /x exch def gsave newpath + x y moveto w y lineto w h lineto x h lineto closepath clip bx } def +/tb {1 sub 3 1 roll gsave newpath moveto {lineto} repeat closepath clip pathbbox + /h exch def /w exch def /y exch def /x exch def bx } def + diff --git a/magic/proto.initrc b/magic/proto.initrc new file mode 100644 index 00000000..ff40b7e5 --- /dev/null +++ b/magic/proto.initrc @@ -0,0 +1,4 @@ +# $(CAD_ROOT)/magic/sys/.initrc +# System wide initialization file for magic +# May be used to override default startup +catch {source ${CAD_ROOT}/magic/sys/site.pre} diff --git a/magic/proto.magicrc.m4 b/magic/proto.magicrc.m4 new file mode 100644 index 00000000..1346b58d --- /dev/null +++ b/magic/proto.magicrc.m4 @@ -0,0 +1,310 @@ +# $(CAD_ROOT)/magic/sys/.magicrc +# System wide start up file for magic, defines default macros. +# +# rcsid $Header: /usr/cvsroot/magic-8.0/magic/proto.magicrc.m4,v 1.4 2008/12/11 04:20:09 tim Exp $ +# +dnl +dnl Source file proto.magicrc.m4 +dnl Process this file with the m4 macro processor +dnl +changequote([,])dnl +ifdef([MAGIC_WRAPPER],[dnl +puts stdout "Processing system .magicrc file" +])dnl (MAGIC_WRAPPER) +ifelse(USE_NEW_MACROS,1,[dnl +############################################################################### +# Default .magicrc macro file (new macros) +############################################################################### +# A key +macro a "select visible" +macro A "select more visible" +macro ^A "select less visible" +# B key +macro b "box" +macro B "findbox" +# C key +macro c "copy" +# D key +macro d "delete" +macro ^D "erase $" +# E key +macro e "edit" +# F key +macro f "sideways" +macro F "upsidedown" +# G key +macro g "grid" +macro G "grid 2" +# I key +macro i "select cell" +macro I "select more cell" +ifdef([XLIB],[macro Control_XK_i "select less cell"],[dnl]) +# L key +ifdef([USE_READLINE],[imacro l "label "],[dnl]) +ifdef([MAGIC_WRAPPER],[imacro l "label "],[dnl]) +macro L "shell ls" +macro ^L "redraw" +# M key +macro m "move" +macro M "stretch" +# N key +macro ^N "" +# O key +macro o "openwindow" +macro O "closewindow" +# P key +ifdef([USE_READLINE],[imacro p "paint "],[dnl]) +ifdef([MAGIC_WRAPPER],[imacro p "paint "],[dnl]) +# Q key +ifdef([XLIB],[macro Control_Shift_XK_q "quit"],[dnl]) +# R key +macro r "clockwise" +macro R "clockwise 270" +macro ^R "clockwise 180" +# S key +macro s "select" +macro S "select more" +macro ^S "select less" +ifdef([XLIB],[macro Control_Shift_XK_s "undo ; select"],[dnl]) +# U key +macro u "undo" +macro U "redo" +# V key +macro v "view" +macro V "xview" +# W key +macro w "writeall" +macro W "writeall force" +# X key +macro x "expand" +macro X "unexpand" +macro ^X "expand toggle" +# Z key +macro z "zoom .5" +macro Z "zoom 2" +macro ^Z "findbox zoom" +ifdef([XLIB],[macro Control_Shift_XK_z "center"],[dnl]) +# Question mark +macro ? "drc why" +macro / "select area; what ; select clear" +# Comma key +macro , "select clear" +# Exclamation mark +ifdef([USE_READLINE],[imacro ! "shell "],[dnl]) +# Space bar +macro " " "tool" +# Colon and semicolon (interactive command) +imacro XK_colon ":" +imacro XK_semicolon ":" +ifdef([XLIB],[dnl +macro Shift_XK_space "tool box" +macro Control_XK_space "tool wiring" +# Arrow keys (X11 versions only) +macro XK_Left "scroll l .1 w" +macro Shift_XK_Left "scroll l 1 w" +macro Control_XK_Left "box grow w 1" +macro Control_Shift_XK_Left "box shrink e 1" +macro XK_Right "scroll r .1 w" +macro Shift_XK_Right "scroll r 1 w" +macro Control_XK_Right "box grow e 1" +macro Control_Shift_XK_Right "box shrink w 1" +macro XK_Up "scroll u .1 w" +macro Shift_XK_Up "scroll u 1 w" +macro Control_XK_Up "box grow n 1" +macro Control_Shift_XK_Up "box shrink s 1" +macro XK_Down "scroll d .1 w" +macro Shift_XK_Down "scroll d 1 w" +macro Control_XK_Down "box grow s 1" +macro Control_Shift_XK_Down "box shrink n 1" +# Keypad keys (X11 versions only) +# Functions duplicated for use both with Num_Lock ON and OFF +macro XK_KP_Delete "box size 0 0" +macro XK_KP_Insert "box size 4 4" +macro XK_KP_0 "box size 7 2" +macro Shift_XK_KP_0 "box size 7 2" +macro XK_0 "box size 7 2" +macro Control_XK_KP_0 "box size 2 7" +macro Control_XK_KP_Insert "box size 2 7" +macro XK_KP_End "move sw 1" +macro XK_KP_Down "move d 1" +macro XK_KP_2 "stretch d 1" +macro Shift_XK_KP_2 "stretch d 1" +macro XK_2 "stretch d 1" +macro XK_KP_Next "move se 1" +macro XK_KP_Left "move l 1" +macro XK_KP_4 "stretch l 1" +macro Shift_XK_KP_4 "stretch l 1" +macro XK_4 "stretch l 1" +macro XK_KP_Begin "findbox zoom" +macro XK_KP_5 "findbox" +macro Shift_XK_KP_5 "findbox" +macro XK_5 "findbox" +macro XK_KP_Right "move r 1" +macro XK_KP_6 "stretch r 1" +macro Shift_XK_KP_6 "stretch r 1" +macro XK_6 "stretch r 1" +macro XK_KP_Home "move nw 1" +macro XK_KP_Up "move u 1" +macro XK_KP_8 "stretch u 1" +macro Shift_XK_KP_8 "stretch u 1" +macro XK_8 "stretch u 1" +macro XK_KP_Prior "move ne 1" +# Scroll wheel bindings +macro XK_Pointer_Button4 "scroll u .05 w" +macro XK_Pointer_Button5 "scroll d .05 w" +# Quick macro function keys for scmos tech (X11 versions only) +macro XK_F1 "paint ndiff" +macro XK_F2 "paint pdiff" +macro XK_F3 "paint poly" +macro XK_F4 "paint poly2" +macro XK_F5 "paint m1" +macro XK_F6 "paint m2" +macro XK_F7 "paint m3" +macro XK_F8 "paint m4" +macro XK_F9 "paint ndc" +macro XK_F10 "paint pdc" +macro XK_F11 "paint pc" +macro XK_F12 "paint via" +])dnl (ifdef XLIB) +],[dnl (else !USE_NEW_MACROS) +############################################################################### +# Default .magicrc macro file (original) +############################################################################### +echo "" +macro s "select" +macro S "select more" +macro a "select area" +macro A "select more area" +macro f "select cell" +macro C "select clear" +macro d "delete" +macro ^D "erase $" +macro t "move" +macro T "stretch" +macro c "copy" +macro ^X "expand toggle" +macro x "expand" +macro X "unexpand" +macro q "move left 1" +macro w "move down 1" +macro e "move up 1" +macro r "move right 1" +macro Q "stretch left 1" +macro W "stretch down 1" +macro E "stretch up 1" +macro R "stretch right 1" +macro g "gridspace" +macro G "gridspace 2" +macro u "undo" +macro U "redo" +macro v "view" +macro z "findbox zoom" +macro Z "zoom 2" +macro b "box" +macro B "findbox" +macro , "center" +macro y "drc why" +macro ^L "redraw" +macro y "drc why" +macro ? "help" +macro o "openwindow" +macro O "closewindow" +macro " " "tool" +imacro XK_colon ":" +imacro XK_semicolon ":" +macro ^R "iroute route -dBox" +macro ^N "iroute route -dSelection" +])dnl (ifdef USE_NEW_MACROS) +# Allow some box manipulation from all tools. +ifdef([MAGIC_WRAPPER],[ +macro Control_Button1 "*bypass box move bl cursor" +macro Control_Button2 "*bypass paint cursor" +macro Control_Button3 "*bypass box corner ur cursor" +# Box tool button bindings +macro Button1 "*bypass box move bl cursor" +macro Shift_Button1 "*bypass box corner bl cursor" +macro Button2 "*bypass paint cursor" +macro Shift_Button2 "*bypass erase cursor" +macro Button3 "*bypass box corner ur cursor" +macro Shift_Button3 "*bypass box move ur cursor" +],[ +macro Control_Button1 "box move bl cursor" +macro Control_Button2 "paint cursor" +macro Control_Button3 "box corner ur cursor" +# Box tool button bindings +macro Button1 "box move bl cursor" +macro Shift_Button1 "box corner bl cursor" +macro Button2 "paint cursor" +macro Shift_Button2 "erase cursor" +macro Button3 "box corner ur cursor" +macro Shift_Button3 "box move ur cursor" +]) +# Color window button bindings +macro color Button1 "pushbutton left" +macro color Button2 "pushbutton middle" +macro color Button3 "pushbutton right" +macro color u "undo" +macro color U "redo" +macro color plus "color next" +macro color minus "color last" +# Netlist window button bindings +macro netlist Button1 "pushbutton left" +macro netlist Button2 "pushbutton middle" +macro netlist Button3 "pushbutton right" +# Wind3D window key bindings +macro wind3d L "level up" +macro wind3d l "level down" +macro wind3d C "cif" +macro wind3d " " "defaults" +macro wind3d ^L "refresh" +macro wind3d Z "zoom 2.0 1 rel" +macro wind3d z "zoom 0.5 1 rel" +macro wind3d 1 "view 0 10 0 rel" +macro wind3d 2 "view 0 -10 0 rel" +macro wind3d 3 "view 10 0 0 rel" +macro wind3d 4 "view -10 0 0 rel" +macro wind3d 5 "view 0 0 10 rel" +macro wind3d 6 "view 0 0 -10 rel" +macro wind3d 7 "view 0 1 0 rel" +macro wind3d 8 "view 0 -1 0 rel" +macro wind3d 9 "view 1 0 0 rel" +macro wind3d 0 "view -1 0 0 rel" +ifdef([XLIB],[dnl +macro wind3d XK_Up "scroll 0 -0.25 0 rel" +macro wind3d XK_Down "scroll 0 0.25 0 rel" +macro wind3d XK_Left "scroll 0.25 0 0 rel" +macro wind3d XK_Right "scroll -0.25 0 0 rel" +macro wind3d XK_minus "view 0 0 1 rel" +macro wind3d XK_equal "view 0 0 -1 rel" +macro wind3d XK_greater "zoom 1 2.0 rel" +macro wind3d XK_less "zoom 1 0.5 rel" +])dnl (ifdef XLIB) +# +# Load basic set of fonts +# +setlabel font FreeSans.pt3 0.58 +setlabel font FreeSerif.pt3 0.58 +setlabel font FreeMono.pt3 0.6 +# +# Additions for Tcl GUI wrapper +# +changequote(<,>)dnl +ifelse(MAGIC_WRAPPER,1,,)dnl (MAGIC_WRAPPER) +changequote([,])dnl +# +ifdef([SCHEME_INTERPRETER],[dnl +# +# additions for default scm path +# +define scm-library-path "CAD_DIR/lib/magic/scm" +load-scm "default.scm" +load-scm "layout.scm" +])dnl (SCHEME_INTERPRETER) diff --git a/magic/symbol.map b/magic/symbol.map new file mode 100644 index 00000000..b0450555 --- /dev/null +++ b/magic/symbol.map @@ -0,0 +1,277 @@ +MAGIC_8.0 { + global: Exttosim_Init; + Exttospice_Init; + Tclmagic_Init; + Tclmagic_SafeInit; + Tclplot_Init; + Tclroute_Init; + Magiclef_Init; + ArgStr; + CIFGetOutputScale; + CellLibPath; + CmdCheckForPaintFunc; + CmdFuncs; + CmdGetEditPoint; + CmdGetRootPoint; + CmdGetSelectedCell; + CmdLongCommands; + CmdParseLayers; + DBAdjustLabels; + DBAllButSpaceAndDRCBits; + DBAllButSpaceBits; + DBAllTypeBits; + DBBoundPlane; + DBCellClearDef; + DBCellCopyCells; + DBCellCopyDefBody; + DBCellCopyPaint; + DBCellDeleteUse; + DBCellEnum; + DBCellLookDef; + DBCellNewDef; + DBCellNewUse; + DBCellReadArea; + DBCellSetAvail; + DBCellSrArea; + DBCellSrDefs; + DBClearPaintPlane; + DBConnPlanes; + DBConnectTbl; + DBDeleteCell; + DBErase; + DBFixMismatch; + DBFreePaintPlane; + DBImageBits; + DBIsSubcircuit; + DBLayerTypeMaskTbl; + DBNewPlane; + DBNewYank; + DBNoTreeSrTiles; + DBNumPlanes; + DBNumTypes; + DBPaint; + DBPaintPlane; + DBPaintPlaneVert; + DBPaintResultTbl; + DBPlaceCell; + DBPlaneLongNameTbl; + DBPlaneTypes; + DBPrintUseId; + DBPropGet; + DBPutLabel; + DBReComputeBbox; + DBSeeTypesAll; + DBSetTrans; + DBSpaceBits; + DBSrLabelLoc; + DBSrPaintArea; + DBTechMinSetPlanes; + DBTechName; + DBTechNamePlane; + DBTechNameType; + DBTechNoisyNameMask; + DBTechNoisyNameType; + DBTechSubsetLayers; + DBTechTypesToPlanes; + DBTreeSrCells; + DBTreeSrLabels; + DBTreeSrTiles; + DBTypeLongNameTbl; + DBTypePaintPlanesTbl; + DBTypePlaneTbl; + DBTypeShortName; + DBUndoEraseLabel; + DBUndoPutLabel; + DBUnLinkCell; + DBUserLayerBits; + DBWAreaChanged; + DBWFeedbackAdd; + DBWFeedbackClear; + DBWFeedbackCount; + DBWHLAddClient; + DBWHLRedraw; + DBWNumStyles; + DBWSetBox; + DBWStyleToTypesTbl; + DBWStyleType; + DBWclientID; + DBWriteResultTbl; + DBZeroTypeBits; + DIMaxInt; + DIZero; + DQInit; + DQPopFront; + DQPushRear; + DRCCatchUp; + DRCCheckThis; + DRCRulesTbl; + DebugAddClient; + DebugAddFlag; + DebugSet; + DebugShow; + DebugAddClient; + DebugAddFlag; + DebugSet; + DebugShow; + DoubleMultI; + DoubleMultII; + DoubleString; + DoubleToDFloat; + EditCellUse; + EditRootDef; + EditToRootTransform; + ExtGetDevInfo; + ExtCompareStyle; + Geo180Transform; + Geo270Transform; + Geo90Transform; + GeoClip; + GeoClipPoint; + GeoIdentityTransform; + GeoInclude; + GeoIncludeAll; + GeoIncludePoint; + GeoInvertTrans; + GeoNameToPos; + GeoNullRect; + GeoOppositePos; + GeoScale; + GeoSidewaysTransform; + GeoTransPoint; + GeoTransPos; + GeoTransRect; + GeoTransTrans; + GeoTransTranslate; + GeoTranslateTrans; + GrClipTriangle; + GrFastBox; + GrGetColor; + GrSetStuff; + GrStippleTable; + GrStyleTable; + HashFind; + HashFreeKill; + HashInit; + HashInitClient; + HashKill; + HashLookOnly; + HashNext; + HashStartSearch; + HeapAddDInt; + HeapAddInt; + HeapInit; + HeapInitType; + HeapKill; + HeapLookAtTop; + HeapRemoveTop; + ListContainsP; + ListDealloc; + ListDeallocC; + ListLength; + ListPop; + ListReverse; + Lookup; + LookupStruct; + MagAtof; + Match; + NLBuild; + NLFree; + NLNetName; + NLSort; + NMEnumNets; + NMHasList; + NMNetlistName; + NMNewNetlist; + NMUnsetCell; + NMinit; + Path; + PaOpen; + PaVisitAddClient; + PaVisitFiles; + PaVisitFree; + PaVisitInit; + RootToEditTransform; + RtrContactWidth; + RtrMetalWidth; + RtrPolyWidth; + RunStats; + SelEnumCells; + SelEnumLabels; + SelEnumPaint; + SelRememberForUndo; + SelSetDisplay; + SelectClear; + SelectDef; + SelectRootDef; + SelectUse; + SetNoisyBool; + SetNoisyDI; + SetNoisyInt; + ShowRect; + SigDisableInterrupts; + SigEnableInterrupts; + SigInterruptPending; + SimSrConnect; + StackFree; + StackLook; + StackNew; + StackPop; + StackPush; + StrDup; + StrIsInt; + StrIsNumeric; + StrIsWhite; + SysLibPath; + Tcl_printf; + TechAddClient; + TechDefault; + TechError; + TechHalo; + TechLoad; + TechSectionGetMask; + TiAlloc; + TiFreePlane; + TiJoinX; + TiJoinY; + TiPlaneRect; + TiSplitX; + TiSplitY; + TiSrArea; + TiSrPoint; + TiToRect; + ToolGetBox; + ToolGetEditBox; + ToolGetPoint; + ToolMoveBox; + ToolMoveCorner; + TouchingTypes; + TxError; + TxFlush; + TxFlushErr; + TxFlushOut; + TxGetLine; + TxGetLinePrompt; + TxMore; + TxPrintOff; + TxPrintOn; + TxPrintf; + UndoBackward; + UndoDisable; + UndoEnable; + WindReplaceCommand; + WindSurfaceToScreen; + WindSearchWid; + WindUpdate; + callocMagic; + cmdParseCoord; + dbSetPlaneTile; + debugClients; + extDevTable; + freeMagic; + magicinterp; + mallocMagic; + maskToPrint; + niceabort; + windCheckOnlyWindow; + local: *; +}; diff --git a/mzrouter/Depend b/mzrouter/Depend new file mode 100644 index 00000000..c8dd6a0d --- /dev/null +++ b/mzrouter/Depend @@ -0,0 +1,100 @@ +mzBlock.o: mzBlock.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/malloc.h \ + ../utils/list.h ../debug/debug.h ../utils/heap.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzDebug.o: mzDebug.c ../utils/magic.h ../utils/signals.h \ + ../textio/textio.h ../utils/hash.h ../utils/geometry.h ../tiles/tile.h \ + ../database/database.h ../utils/malloc.h ../utils/list.h ../utils/heap.h \ + ../mzrouter/mzrouter.h ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzEstimate.o: mzEstimate.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/malloc.h \ + ../utils/list.h ../debug/debug.h ../utils/heap.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzXtndDown.o: mzXtndDown.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../utils/list.h ../debug/debug.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzXtndLeft.o: mzXtndLeft.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../utils/list.h ../debug/debug.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzXtndRght.o: mzXtndRght.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../utils/list.h ../debug/debug.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzXtndUp.o: mzXtndUp.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../utils/list.h ../debug/debug.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzHint.o: mzHint.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/malloc.h \ + ../utils/list.h ../debug/debug.h ../utils/heap.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzInit.o: mzInit.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../drc/drc.h ../select/select.h \ + ../utils/signals.h ../textio/textio.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../debug/debug.h ../utils/undo.h \ + ../textio/txcommands.h ../utils/malloc.h ../utils/list.h ../utils/heap.h \ + ../mzrouter/mzrouter.h ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzNumLine.o: mzNumLine.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/malloc.h \ + ../utils/list.h ../debug/debug.h ../utils/heap.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzMain.o: mzMain.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../drc/drc.h ../select/select.h \ + ../utils/signals.h ../textio/textio.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../debug/debug.h ../utils/undo.h \ + ../textio/txcommands.h ../utils/malloc.h ../utils/main.h \ + ../utils/geofast.h ../utils/list.h ../utils/heap.h \ + ../utils/touchingtypes.h ../mzrouter/mzrouter.h ../utils/list.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzSearch.o: mzSearch.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../utils/hash.h ../utils/heap.h ../tiles/tile.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../utils/malloc.h ../utils/list.h ../debug/debug.h ../utils/styles.h \ + ../windows/windows.h ../dbwind/dbwind.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzStart.o: mzStart.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../utils/list.h ../debug/debug.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzSubrs.o: mzSubrs.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../drc/drc.h ../select/select.h \ + ../utils/signals.h ../textio/textio.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../debug/debug.h ../utils/undo.h \ + ../textio/txcommands.h ../utils/malloc.h ../utils/main.h \ + ../utils/geofast.h ../utils/list.h ../utils/touchingtypes.h \ + ../utils/heap.h ../mzrouter/mzrouter.h ../mzrouter/mzInternal.h \ + ../mzrouter/mzDebug.h +mzTech.o: mzTech.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../utils/signals.h ../textio/textio.h ../wiring/wiring.h \ + ../utils/utils.h ../utils/tech.h ../utils/malloc.h ../utils/list.h \ + ../windows/windows.h ../utils/main.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzTestCmd.o: mzTestCmd.c ../utils/magic.h ../utils/geometry.h \ + ../utils/hash.h ../tiles/tile.h ../database/database.h \ + ../utils/signals.h ../textio/textio.h ../irouter/irouter.h \ + ../graphics/graphics.h ../windows/windows.h ../dbwind/dbwind.h \ + ../dbwind/dbwtech.h ../textio/txcommands.h ../utils/main.h \ + ../utils/utils.h ../commands/commands.h ../utils/styles.h \ + ../utils/malloc.h ../utils/list.h ../utils/heap.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h +mzWalk.o: mzWalk.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \ + ../database/database.h ../utils/signals.h ../textio/textio.h \ + ../utils/list.h ../debug/debug.h ../mzrouter/mzrouter.h \ + ../mzrouter/mzInternal.h ../mzrouter/mzDebug.h diff --git a/mzrouter/Makefile b/mzrouter/Makefile new file mode 100644 index 00000000..fb183134 --- /dev/null +++ b/mzrouter/Makefile @@ -0,0 +1,13 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/mzrouter/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +MODULE = mzrouter +MAGICDIR = .. +SRCS = mzBlock.c mzDebug.c mzEstimate.c mzXtndDown.c \ + mzXtndLeft.c mzXtndRght.c mzXtndUp.c mzHint.c mzInit.c mzNumLine.c \ + mzMain.c mzSearch.c mzStart.c mzSubrs.c mzTech.c mzTestCmd.c \ + mzWalk.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/mzrouter/mzBlock.c b/mzrouter/mzBlock.c new file mode 100644 index 00000000..c72f0d9f --- /dev/null +++ b/mzrouter/mzBlock.c @@ -0,0 +1,1479 @@ +/* + * mzBlock.c -- + * + * Construction of blockage planes. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * A blockage plane is used to determine the legal areas for routing. + * Each point on the interior of a space tile in a blockage plane is + * a legal position to place the lower-left corner of a piece of wiring. + * + * To build a blockage plane, each solid mask tile in the + * layout is bloated in + * all four directions and painted into the blockage plane. To the + * top and right, it is only bloated by the minimum separation from + * that tile to routing on that plane (s). To the bottom and left, + * though, it is bloated by this distance PLUS one less than the + * minimum width of routing on that layer (w-1): + * + * + * + * s+w-1 s + * <-------> <--> + * +---------------------------+ ^ + * | | | s + * | +---------------+ | v + * | |. . . . . . . .| | + * | | . . tile. . . | | + * | |. . . . . . . .| | + * | +---------------+ | ^ + * | | | + * | blockage | | s+w-1 + * | | | + * +---------------------------+ v + * + * Blockage planes are kept for each routeLayer and routeContact. They + * are part of ther RouteType datastructure. + * + * There are two blockage planes for each routeType. One is merged into + * maximal horizontal strips, and the other + * into maximal vertical strips. (To be done---there's no reason to + * have separate routines for maximal vertical strips; just use max + * horizontal strips routines with x and y appropriately swapped). + * + * Start and destination nodes are treated differently, by considering + * the areas in which a route's lower left corner can be placed that will + * let the route terminate without DRC errors. This is the following: + * + * w-1 w-1 + * <-----> <----> + * +-------------+-----+ ^ + * |. . . . . . .|. . .| | w-1 + * | . . . . . . | . . | | + * +-----+. . . . . . .+-----+ v + * | | . . . . . . . . . | + * | |. . .tile . . . . .| + * | | . . . . . . . . . | + * +-----+-------------+-----+ ^ + * | | | + * | | | w-1 + * +-------------+ v + * + * The upper-right corner of the tile is a keep-out area, where a route + * would violate width rules. The rest of the tile is valid for placement + * of a route's lower left corner, as well as two extension areas to the + * left and bottom. + * + * (to be done)---Both start and dest areas should not trim back the + * upper corners of tiles that are connected to other start/dest tiles, + * since that would leave unnecessary holes in the routable areas. + * Not doing this tends to cause troubles when the start/dest nodes are + * broken up into many tiles. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzBlock.c,v 1.2 2010/10/22 15:02:15 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "textio/textio.h" +#include "utils/heap.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + +/* Forward declarations */ +extern void mzPaintBlockType(); + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildMaskDataBlocks -- + * + * Build blockage info from paint in buildArea. + * + * The design rules are used + * to build a map of blocked areas in blockage planes of RouteTypes. + * This map will consist of TT_SPACE tiles, where a zero-width + * path will yield a + * legal route when flushed out to wire width paint, and various + * types of block tiles. Multiple block types are needed to handle route + * termination at the destination node properly. + * + * TT_BLOCKED and TT_SAMENODE are generated from the mask data + * (SAMENODE areas are only blocked by the destination node itself). + * + * In addition to blockage planes for route layers, there are + * blockage planes for contacts, assumed to connect two planes. + * Both planes of mask information + * are effectively AND-ed together to form the blockage plane for + * that type of contact. + * + * Results: + * None. + * + * Side effects: + * Paints into Blockage planes in RouteTypes + * + * ---------------------------------------------------------------------------- + */ + +void +mzBuildMaskDataBlocks(buildArea) + Rect *buildArea; /* Area over which blockage planes will be built */ +{ + Rect searchArea; + int pNum; + int mzPaintSameNodeFunc(); /* Fwd declaration */ + + /* search area = build area + context */ + searchArea.r_xbot = buildArea->r_xbot - mzContextRadius; + searchArea.r_ybot = buildArea->r_ybot - mzContextRadius; + searchArea.r_xtop = buildArea->r_xtop + mzContextRadius; + searchArea.r_ytop = buildArea->r_ytop + mzContextRadius; + + /* Paint SAMENODE on all destination areas */ + /* (all areas that were painted into mzDestAreasUse->cu_def) */ + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + DBSrPaintArea((Tile *)NULL, mzDestAreasUse->cu_def->cd_planes[pNum], + &searchArea, &DBAllButSpaceAndDRCBits, + mzPaintSameNodeFunc, (ClientData)buildArea); + } + + /* Build the blockage planes on all layers, ignore unexpanded subcells + * (unexpanded in reference window) + */ + { + int mzBuildBlockFunc(); + SearchContext scx; + + scx.scx_area = searchArea; + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = mzRouteUse; + + (void) DBTreeSrTiles( + &scx, + &DBAllButSpaceAndDRCBits, + mzCellExpansionMask, + mzBuildBlockFunc, + (ClientData) buildArea); + } + + /* Add blocks at unexpanded subcells on all blockage planes + * + * NOTE: A 0 expansion mask is special cased since + * the mzrotuer interpets a 0 mask to mean all subcells are + * expanded, + * while DBTreeSrCells() takes a 0 mask to mean all subcells are + * unexpanded. + */ + + if(mzCellExpansionMask != 0) + { + int mzBlockSubcellsFunc(); + SearchContext scx; + + scx.scx_area = searchArea; + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = mzRouteUse; + + DBTreeSrCells( + &scx, + mzCellExpansionMask, + mzBlockSubcellsFunc, + (ClientData) buildArea); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildBlockFunc -- + * + * Filter function called via DBTreeSrTiles on behalf of mzBuildBlock() + * above, for each solid tile in the area of interest. Paints TT_BLOCKED + * (TT_SAMENODE if the tile is marked) areas on each of the planes + * affected by this tile. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into Blockage Planes in RouteType structures. + * + * ---------------------------------------------------------------------------- + */ + +int +mzBuildBlockFunc(tile, cxp) + + Tile *tile; + TreeContext *cxp; +{ + SearchContext *scx = cxp->tc_scx; + Rect *buildArea = (Rect *) (cxp->tc_filter->tf_arg); + Rect r, rDest; + + /* Transform to result coordinates */ + TITORECT(tile, &r); + GEOCLIP(&r, &scx->scx_area); + GEOTRANSRECT(&scx->scx_trans, &r, &rDest); + + mzPaintBlockType(&rDest, TiGetType(tile), buildArea, TT_BLOCKED); + return (0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzBlockSubcellsFunc -- + * + * Filter function called via DBTreeSrTiles on behalf of mzBuildBlock() + * above, for each unexpanded subcell in the area of interest, + * a "blocked" area (TT_BLOCKED) is painted on each blockage plane for + * the bounding box of the subcell, bloated by the maximum design rule + * spacing on that plane. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into Blockage Planes in RouteType structures. + * + * ---------------------------------------------------------------------------- + */ + +int +mzBlockSubcellsFunc(scx, cdarg) + SearchContext *scx; + ClientData cdarg; +{ + Rect r, rDest; + Rect *buildArea = (Rect *) cdarg; + + /* Transform bounding box to result coords */ + r = scx->scx_use->cu_def->cd_bbox; + GEOTRANSRECT(&scx->scx_trans, &r, &rDest); + + if((int)(scx->scx_use->cu_client) != MZ_EXPAND_DEST) + /* cell over part of dest node, paint normal blocks onto affected + * planes. + * (area is bloated by appropriate spacing on each affected plane) + */ + { + mzPaintBlockType(&rDest, TT_SUBCELL, buildArea, TT_BLOCKED); + } + else + /* cell is over part of dest node, paint samenode blocks */ + { + mzPaintBlockType(&rDest, TT_SUBCELL, buildArea, TT_SAMENODE); + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * mzPaintSameNodeFunc -- + * + * Add TT_SAMENODE paint into the route layer block plane for each + * tile found in mzDestAreasUse->cu_def + * + * Results: + * Always return 0 to keep the search going. + * + * ---------------------------------------------------------------------------- + */ + +int +mzPaintSameNodeFunc(Tile *t, Rect *buildArea) +{ + Rect r; + TileType ttype; + + ttype = TiGetType(t); + TiToRect(t, &r); + + mzPaintBlockType(&r, ttype, buildArea, TT_SAMENODE); + + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzPaintBlockType -- + * + * Add "blockType" paint appropriate to data tile of given location + * and type to blockage planes of all relevant routeTypes. + * + * The blockage tiles painted are bloated versions of the data tiles. + * + * Results: + * None. + * + * Side effects: + * Modifies blockage planes in RouteType structures. + * + * ---------------------------------------------------------------------------- + */ + +void +mzPaintBlockType(r, type, buildArea, blockType) + Rect *r; + TileType type; + Rect *buildArea; + TileType blockType; +{ + RouteType *rT; + TileType locBlockType; + + /* process routeTypes */ + for (rT=mzActiveRTs; rT!=NULL; rT=rT->rt_nextActive) + { + Rect rblock; + + /* Added by Tim 7/28/06 --- Ignore those planes that don't interact! */ + + if (!(DBTypePlaneMaskTbl[type] & DBTypePlaneMaskTbl[rT->rt_tileType])) + continue; + + /* if there is a constraint between RouteType and type, paint a block */ + + locBlockType = blockType; + + if (rT->rt_bloatBot[type] >= 0) + { + int bot, top; + + /* If we're painting TT_BLOCKED, make sure we're not painting */ + /* on top of a start or dest area (has TT_SAMENODE) */ + + if (blockType != TT_SAMENODE) + { + RouteContact *rC; + Tile *tp = rT->rt_hBlock->pl_hint; + GOTOPOINT(tp, &r->r_ll); + if (TiGetType(tp) == TT_SAMENODE) + { + /* This can fail to paint a proper blockage on a */ + /* contact plane when the terminal is in one plane */ + /* and the blocking route is on the other. So, if */ + /* painting into a contact plane, check that the */ + /* tile in the residue layer that is "type" is also */ + /* covered in TT_SAMENODE, or this is a block. */ + + if (DBIsContact(rT->rt_tileType)) + { + for (rC = mzRouteContacts; rC != NULL; rC = rC->rc_next) + { + if (rC->rc_routeType.rt_tileType == rT->rt_tileType) + { + Tile *tp2; + if (rC->rc_rLayer1->rl_routeType.rt_tileType == type) + { + tp2 = rC->rc_rLayer1-> + rl_routeType.rt_hBlock->pl_hint; + GOTOPOINT(tp2, &r->r_ll); + if (TiGetType(tp) == TT_SAMENODE) break; + } + else if (rC->rc_rLayer2->rl_routeType.rt_tileType + == type) + { + tp2 = rC->rc_rLayer2-> + rl_routeType.rt_hBlock->pl_hint; + GOTOPOINT(tp2, &r->r_ll); + if (TiGetType(tp) == TT_SAMENODE) break; + } + } + } + if (rC != NULL) continue; + } + else + continue; + } + } + else + { + /* If the tile type is a contact of the same + * type as the route type, draw a block layer, not SAMENODE. + * This prevents the maze router from attempting to place + * a contact too close to an existing one, causing a DRC + * error. + */ + if ((DBIsContact(type)) && (rT->rt_tileType == type)) + locBlockType = TT_BLOCKED; + } + + /* Compute blockage rectangle */ + bot = rT->rt_bloatBot[type]; + top = rT->rt_bloatTop[type]; + + if (locBlockType != TT_SAMENODE) + { + rblock.r_xbot = r->r_xbot - bot; + rblock.r_ybot = r->r_ybot - bot; + + rblock.r_xtop = r->r_xtop + top; + rblock.r_ytop = r->r_ytop + top; + } + else + { + int wless = bot - top + 1; + + /* SAMENODE: valid route can start in one of */ + /* two overlapping rectangles as computed */ + /* below. The left and bottom sides are */ + /* extended by the route width, but the */ + /* corners are prohibited. */ + + rblock.r_xbot = r->r_xbot - wless; + rblock.r_ybot = r->r_ybot; + + rblock.r_xtop = r->r_xtop; + rblock.r_ytop = r->r_ytop - wless; + + GEOCLIP(&rblock, buildArea); + if (!GEO_RECTNULL(&rblock)) + { + DBPaintPlane(rT->rt_hBlock, &rblock, + mzBlockPaintTbl[blockType], + (PaintUndoInfo *) NULL); + DBPaintPlaneVert(rT->rt_vBlock, &rblock, + mzBlockPaintTbl[blockType], + (PaintUndoInfo *) NULL); + } + + rblock.r_xbot = r->r_xbot; + rblock.r_ybot = r->r_ybot - wless; + + rblock.r_xtop = r->r_xtop - wless; + rblock.r_ytop = r->r_ytop; + } + + /* clip to build area */ + + GEOCLIP(&rblock, buildArea); + if (!GEO_RECTNULL(&rblock)) + { + /* and paint it */ + + DBPaintPlane(rT->rt_hBlock, &rblock, + mzBlockPaintTbl[locBlockType], + (PaintUndoInfo *) NULL); + DBPaintPlaneVert(rT->rt_vBlock, &rblock, + mzBlockPaintTbl[locBlockType], + (PaintUndoInfo *) NULL); + } + } + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildFenceBlocks -- + * + * Blocks regions of fence parity opposite of the destination-point. + * (Fence boundaries can not be crossed). + * + * Results: + * None. + * + * Side effects: + * Blockage Planes modified. + * + * ---------------------------------------------------------------------------- + */ + +void +mzBuildFenceBlocks(buildArea) + Rect *buildArea; /* Area over which planes modified */ +{ + int mzBuildFenceBlocksFunc(); + Rect searchArea; + + + /* search area = build area + context */ + searchArea.r_xbot = buildArea->r_xbot - mzContextRadius; + searchArea.r_ybot = buildArea->r_ybot - mzContextRadius; + searchArea.r_xtop = buildArea->r_xtop + mzContextRadius; + searchArea.r_ytop = buildArea->r_ytop + mzContextRadius; + + /* If route inside fence, gen blocks at space tiles. + * if route outside fence, gen blocks at fence tiles. + */ + if(mzInsideFence) + { + DBSrPaintArea(NULL, /* no hint tile */ + mzHFencePlane, + &searchArea, + &DBSpaceBits, + mzBuildFenceBlocksFunc, + (ClientData) buildArea); + } + else + { + DBSrPaintArea(NULL, /* no hint tile */ + mzHFencePlane, + &searchArea, + &DBAllButSpaceBits, + mzBuildFenceBlocksFunc, + (ClientData) buildArea); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildFenceBlocksFunc -- + * + * Called by DBSrPaintArea for tile in given area on fence plane where routing + * is prohibited. These areas are blocked, + * adjusting for wire width on each blockage plane. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into blockage planes. + * + * ---------------------------------------------------------------------------- + */ + +int +mzBuildFenceBlocksFunc(tile, buildArea) + Tile *tile; + Rect *buildArea; /* clip to this area before painting */ +{ + RouteType *rT; + int d; + Rect r, rAdjusted; + TileType tt = TiGetType(tile); + + /* Get boundary of tile */ + TITORECT(tile, &r); + + for (rT=mzActiveRTs; rT!=NULL; rT=rT->rt_nextActive) + { + /* Added by Tim 7/28/06 --- Ignore those planes that don't interact! */ + /* Revised 8/22/06---Fence tiles are supposed to block all layers! */ + + // if (!(DBTypePlaneMaskTbl[tt] & DBTypePlaneMaskTbl[rT->rt_tileType])) + // continue; + + /* adjust to compensate for wire width */ + d = rT->rt_effWidth - 1; + rAdjusted.r_xbot = r.r_xbot - d; + rAdjusted.r_xtop = r.r_xtop; + rAdjusted.r_ybot = r.r_ybot - d; + rAdjusted.r_ytop = r.r_ytop; + + /* clip to area being generated. */ + GEOCLIP(&rAdjusted, buildArea); + + /* Paint into blockage planes */ + DBPaintPlane(rT->rt_hBlock, + &rAdjusted, + mzBlockPaintTbl[TT_BLOCKED], + (PaintUndoInfo *) NULL); + DBPaintPlaneVert(rT->rt_vBlock, + &rAdjusted, + mzBlockPaintTbl[TT_BLOCKED], + (PaintUndoInfo *) NULL); + } + + /* return 0 - to continue search */ + return(0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendBlockBoundsR -- + * + * Generate blockage information around given rect. + * Info required for radius of twice the bounds-increment around the rect. + * The gen area is broken down into areas which have not already been gened. + * Blockage info is generated for these subregions. + * + * Results: + * None. + * + * Side effects: + * Paints into Blockage planes in RouteTypes + * Updates bounds plane. + * + * ---------------------------------------------------------------------------- + */ + +void +mzExtendBlockBoundsR(rect) + Rect *rect; +{ + Rect area; + TileTypeBitMask genMask; + /* Generate twice the required bounds increment, so we don't have + * to regenerate as soon as we move from the center of the newly + * generated region. + */ + int genBoundsIncrement = mzBoundsIncrement * 2; + int mzExtendBlockFunc(); + + /* keep stats */ + mzBlockGenCalls++; + + /* mark area about rect in which blockage plane required to be present */ + area.r_xbot = rect->r_xbot - genBoundsIncrement; + area.r_ybot = rect->r_ybot - genBoundsIncrement; + area.r_xtop = rect->r_xtop + genBoundsIncrement; + area.r_ytop = rect->r_ytop + genBoundsIncrement; + + + DBPaintPlane(mzHBoundsPlane, + &area, + mzBoundsPaintTbl[TT_GENBLOCK], + (PaintUndoInfo *) NULL); + + /* Generate blockage planes under each GENBLOCK tile = regions in + * new area where blockage planes not previously generated + */ + TTMaskZero(&genMask); + TTMaskSetType(&genMask,TT_GENBLOCK); + DBSrPaintArea(NULL, /* no hint tile */ + mzHBoundsPlane, + &area, + &genMask, + mzExtendBlockFunc, + (ClientData) NULL); + + /* Paint area INBOUNDS in both bounds planes + *(blockage planes now generated here) + */ + DBPaintPlane(mzHBoundsPlane, + &area, + mzBoundsPaintTbl[TT_INBOUNDS], + (PaintUndoInfo *) NULL); + DBPaintPlaneVert(mzVBoundsPlane, + &area, + mzBoundsPaintTbl[TT_INBOUNDS], + (PaintUndoInfo *) NULL); + + return; +} + +#define RECT_AREA(r) \ + ((double)(r.r_xtop - r.r_xbot)*(double)(r.r_ytop - r.r_ybot)) + + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendBlockFunc -- + * + * Called by DBSrPaintArea for rectangles where blockage info must be + * generated. + * + * Results: + * Return 0 always (to continue the search) + * + * Side effects: + * Paints into Blockage planes in RouteTypes + * + * ---------------------------------------------------------------------------- + */ + +int +mzExtendBlockFunc(tile, cdarg) + Tile *tile; + ClientData cdarg; +{ + Rect area; + + /* Get location of tile */ + TITORECT(tile, &area); + + /* Don't actually generate blocks outside of user supplied + * route area hint. + */ + if(mzBoundsHint) + { + GEOCLIP(&area,mzBoundsHint); + if((area.r_xbot > area.r_xtop) || (area.r_ybot > area.r_ytop)) + /*no overlap just return */ + { + return 0; + } + } + + /* Grow clip area by 2 units to take care of boundary conditions. */ + area.r_xbot -= 2; + area.r_xtop += 2; + area.r_ybot -= 2; + area.r_ytop += 2; + + mzBuildMaskDataBlocks(&area); + mzBuildFenceBlocks(&area); + + /* keep stats */ + mzBlockGenArea += RECT_AREA(area); + + /* return 0 to continue search */ + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendBlockBounds -- + * + * Generate blockage information around given point. + * Info required for radius of twice the bounds-increment around the point. + * The gen area is broken down into areas which have not already been gened. + * Blockage info is generated for these subregions. + * + * Results: + * None. + * + * Side effects: + * Paints into Blockage planes in RouteTypes + * Updates bounds plane. + * + * ---------------------------------------------------------------------------- + */ + +void +mzExtendBlockBounds(point) + Point *point; +{ + Rect rect; + + rect.r_ll = *point; + rect.r_ur = *point; + + mzExtendBlockBoundsR(&rect); + + return; +} + +/* + * This struc is used to store generated walks, since it is necessary + * to defer painting walks until all are generated. + */ +typedef struct +{ + RouteType * w_rT; + Rect w_rect; + TileType w_type; +} Walk; + +/* global used to store walks prior to painting them */ +List *mzWalkList; + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildDestAreaBlocks -- + * + * Generate blockage information around all dest areas, and do special dest + * area processing (generation of dest area blocks and walks). In addition + * dest area alignment coords are added to the alignment structures. + * + * TT_DEST_AREA and TT_*_WALK regions are generated from the special dest area + * cell. Dest areas are regions to connect to and walks are regions blocked + * only by dest nodes and directly adjacent to a dest area. Walks are + * routed through by special termination code. + * + * Results: + * None. + * + * Side effects: + * Modifies blockage planes. + * Modifies alignment strucs. + * Updates bounds plane. + * + * ---------------------------------------------------------------------------- + */ + +void +mzBuildDestAreaBlocks() +{ + int mzDestAreaFunc(); + int mzDestWalksFunc(); + int mzLRCWalksFunc(); + int mzUDCWalksFunc(); + SearchContext scx; + + /* initialize global walk list */ + mzWalkList = NULL; + + /* Compute bounding box for dest areas cell */ + DBReComputeBbox(mzDestAreasUse->cu_def); + + /* Process dest areas in dest area cell one by one. + * - generates normal blockage info. + * - paints dest area into appropriate blockage planes. + * - generates alignments. + * - generates list of walks. + * + * Walks are not actually painted yet because existing + * walks can interfere with the generation of new ones. + */ + + scx.scx_area = mzBoundingRect; + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = mzDestAreasUse; + + /* clip area to bounding box to avoid overflow during transforms */ + GEOCLIP(&(scx.scx_area), &(mzDestAreasUse->cu_def->cd_bbox)); + + (void) DBTreeSrTiles( &scx, &DBAllButSpaceAndDRCBits, + 0, mzDestAreaFunc, (ClientData) NULL); + + (void) DBTreeSrTiles( &scx, &DBAllButSpaceAndDRCBits, + 0, mzDestWalksFunc, (ClientData) NULL); + + (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, + 0, mzUDCWalksFunc, (ClientData) NULL); + + (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, + 0, mzLRCWalksFunc, (ClientData) NULL); + + /* Paint walks into blockage planes (and dealloc walk list) */ + + { + List *l; + + for(l = mzWalkList; l!= NULL; l=LIST_TAIL(l)) + { + Walk *walk = (Walk *) LIST_FIRST(l); + + /* Diagnostic---something is wrong here! */ + if (walk->w_type > TT_MAXROUTETYPES) + { + TxError("Fatal: Bad destination walk!\n"); + continue; /* Try to go on anyway */ + } + + DBPaintPlane(walk->w_rT->rt_hBlock, + &(walk->w_rect), + mzBlockPaintTbl[walk->w_type], + (PaintUndoInfo *) NULL); + + DBPaintPlaneVert(walk->w_rT->rt_vBlock, + &(walk->w_rect), + mzBlockPaintTbl[walk->w_type], + (PaintUndoInfo *) NULL); + } + + ListDeallocC(mzWalkList); + } + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzDestAreaFunc -- + * + * Pregenerate blockage info around the destination area + * + * Results: + * Returns 0 on success. In case we are stymied by an incomplete + * techfile entry for the maze router, return with 1 to stop the + * whole process. + * + * Side effects: + * Generates blockage info. + * + * ---------------------------------------------------------------------------- + */ + +int +mzDestAreaFunc(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + SearchContext *scx = cxp->tc_scx; + TileType type = TiGetType(tile); + Rect r, rect; + RouteType *rT; + + /* Transform to result coordinates */ + TITORECT(tile, &r); + GEOTRANSRECT(&scx->scx_trans, &r, &rect); + + mzExtendBlockBoundsR(&rect); + + /* find route type for this dest area */ + + rT = mzActiveRTs; + while ((rT != NULL) && (rT->rt_tileType != type)) + rT = rT->rt_nextActive; + + /* This can happen if the techfile does not completely define */ + /* the gaRoute info. . . */ + if (rT == NULL) + return 1; + + /* Draw the routable destination area (see comments at top of file). */ + + r.r_xtop = rect.r_xtop - rT->rt_width; + r.r_ytop = rect.r_ytop; + r.r_xbot = rect.r_xbot; + r.r_ybot = rect.r_ybot - rT->rt_width; + + /* paint dest area into blockage planes of appropriate route type */ + DBPaintPlane(rT->rt_hBlock, &r, mzBlockPaintTbl[TT_DEST_AREA], + (PaintUndoInfo *) NULL); + + DBPaintPlaneVert(rT->rt_vBlock, &r, mzBlockPaintTbl[TT_DEST_AREA], + (PaintUndoInfo *) NULL); + + r.r_xtop = rect.r_xtop; + r.r_ytop = rect.r_ytop - rT->rt_width; + r.r_xbot = rect.r_xbot - rT->rt_width; + r.r_ybot = rect.r_ybot; + + /* paint dest area into blockage planes of appropriate route type */ + DBPaintPlane(rT->rt_hBlock, &r, mzBlockPaintTbl[TT_DEST_AREA], + (PaintUndoInfo *) NULL); + + DBPaintPlaneVert(rT->rt_vBlock, &r, mzBlockPaintTbl[TT_DEST_AREA], + (PaintUndoInfo *) NULL); + + /* continue with next dest area */ + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * mzDestWalksFunc -- + * + * Generate walks around each destination area tile, showing the router + * the direct "walk" into the destination area from points around the + * perimeter. This prevents the routing algorithm from having to blindly + * find the exact destination area; it only has to get close enough to + * be told how to paint a path directly to the destination node. + * + * Results: + * Returns 0 on success. In case we are stymied by an incomplete + * techfile entry for the maze router, return with 1 to stop the + * whole process. + * + * Side effects: + * Generates walk tiles in the blockage planes + * + * ---------------------------------------------------------------------------- + */ + +int +mzDestWalksFunc(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + SearchContext *scx = cxp->tc_scx; + TileType type = TiGetType(tile); + Rect r, rect; + RouteType *rT; + int mzHWalksFunc(); + int mzVWalksFunc(); + int mzUDCWalksFunc(); + int mzLRCWalksFunc(); + TileTypeBitMask destAreaMask; + + /* Transform to result coordinates */ + TITORECT(tile, &r); + GEOTRANSRECT(&scx->scx_trans, &r, &rect); + + /* find route type for this dest area */ + + rT = mzActiveRTs; + while ((rT != NULL) && (rT->rt_tileType != type)) + rT = rT->rt_nextActive; + + /* This can happen if the techfile does not completely define */ + /* the gaRoute info. . . */ + if (rT == NULL) + return 1; + + /* Generate alignments and walks for dest areas. + * + * Since the above dest area may be partially blocked, the blockage + * planes are searched for DEST_AREA tiles underneath + * the dest area painted above to build lists of dest tiles. + * + * walks are accumulated into a list for painting after ALL walks + * have been calculated. + * + */ + + TTMaskSetOnlyType(&destAreaMask, TT_DEST_AREA); + + DBSrPaintArea(NULL, /* no hint tile */ + rT->rt_hBlock, &rect, + &destAreaMask, mzHWalksFunc, + (ClientData) rT); + + DBSrPaintArea(NULL, /* no hint tile */ + rT->rt_vBlock, &rect, + &destAreaMask, mzVWalksFunc, + (ClientData) rT); + + DBSrPaintArea(NULL, /* no hint tile */ + rT->rt_hBlock, &rect, + &destAreaMask, mzLRCWalksFunc, + (ClientData) rT); + + DBSrPaintArea(NULL, /* no hint tile */ + rT->rt_vBlock, &rect, + &destAreaMask, mzUDCWalksFunc, + (ClientData) rT); + + /* continue with next dest area */ + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzHWalksFunc -- + * + * Generate walks to top and bottom, and alignment y-coords for TT_DESTAREA + * (Walks are added to list for painting after search completes.) + * + * Results: + * Returns 0 always. + * + * Side effects: + * Adds to walks list and alignment structure. + * + * ---------------------------------------------------------------------------- + */ + +int +mzHWalksFunc(tile, cdarg) + Tile *tile; + ClientData cdarg; +{ + RouteType *rT = (RouteType *) cdarg; + + /* Add dest area coordinates to dest alignment structure */ + { + mzNLInsert(&mzXAlignNL, LEFT(tile)); + mzNLInsert(&mzXAlignNL, RIGHT(tile)); + } + + /* compute LEFT_WALK(s) */ + { + Walk *walk; + Tile *tLeft = BL(tile); + + /* Build walks for blocks to left of tile */ + while(BOTTOM(tLeft)w_rT = rT; + walk->w_type = TT_LEFT_WALK; + walk->w_rect.r_ybot = MAX(BOTTOM(tile),BOTTOM(tLeft)); + walk->w_rect.r_ytop = MIN(TOP(tile),TOP(tLeft)); + walk->w_rect.r_xtop = RIGHT(tLeft); + walk->w_rect.r_xbot = MAX(LEFT(tLeft), + RIGHT(tLeft)-mzMaxWalkLength); + LIST_ADD(walk, mzWalkList); + } + + /* move to next tile up */ + tLeft = RT(tLeft); + } + } + + /* compute RIGHT_WALK */ + { + Walk *walk; + Tile *tRight = TR(tile); + + /* Build walks for blocks to right of tile */ + while(TOP(tRight)>BOTTOM(tile)) + { + if(TiGetType(tRight)==TT_SAMENODE) + { + walk = (Walk *) mallocMagic((unsigned) (sizeof(Walk))); + walk->w_rT = rT; + walk->w_type = TT_RIGHT_WALK; + walk->w_rect.r_ybot = MAX(BOTTOM(tile),BOTTOM(tRight)); + walk->w_rect.r_ytop = MIN(TOP(tile),TOP(tRight)); + walk->w_rect.r_xbot = LEFT(tRight); + walk->w_rect.r_xtop = MIN(RIGHT(tRight), + LEFT(tRight)+mzMaxWalkLength); + LIST_ADD(walk, mzWalkList); + } + + /* move to next tile down */ + tRight = LB(tRight); + } + } + + /* return 0 - to continue search */ + return(0); +} + + + +/* + * ---------------------------------------------------------------------------- + * + * mzVWalksFunc -- + * + * Generate walks to top and bottom, and alignment y-coords for TT_DESTAREA + * (Walks are added to list for painting after search completes.) + * + * Results: + * Returns 0 always. + * + * Side effects: + * Adds to walks list and alignment structure. + * + * ---------------------------------------------------------------------------- + */ + +int +mzVWalksFunc(tile, cdarg) + Tile *tile; + ClientData cdarg; +{ + RouteType *rT = (RouteType *) cdarg; + + /* Add dest area coordinates to dest alignment structure */ + { + mzNLInsert(&mzYAlignNL, BOTTOM(tile)); + mzNLInsert(&mzYAlignNL, TOP(tile)); + } + + /* compute BOTTOM_WALK */ + { + Walk *walk; + Tile *tBelow = LB(tile); + + /* Build walks for blocks to below tile */ + while(LEFT(tBelow)w_rT = rT; + walk->w_type = TT_BOTTOM_WALK; + walk->w_rect.r_xbot = MAX(LEFT(tile),LEFT(tBelow)); + walk->w_rect.r_xtop = MIN(RIGHT(tile),RIGHT(tBelow)); + walk->w_rect.r_ytop = TOP(tBelow); + walk->w_rect.r_ybot = MAX(BOTTOM(tBelow), + TOP(tBelow)-mzMaxWalkLength); + LIST_ADD(walk, mzWalkList); + } + + /* move to next tile to left */ + tBelow = TR(tBelow); + } + } + + /* compute TOP_WALK */ + { + Walk *walk; + Tile *tAbove = RT(tile); + + + /* Build walks for blocks above tile */ + while(RIGHT(tAbove)>LEFT(tile)) + { + if(TiGetType(tAbove)==TT_SAMENODE) + { + walk = (Walk *) mallocMagic((unsigned) (sizeof(Walk))); + walk->w_rT = rT; + walk->w_type = TT_TOP_WALK; + walk->w_rect.r_xbot = MAX(LEFT(tile),LEFT(tAbove));; + walk->w_rect.r_xtop = MIN(RIGHT(tile),RIGHT(tAbove)); + walk->w_rect.r_ybot = BOTTOM(tAbove); + walk->w_rect.r_ytop = MIN(TOP(tAbove), + BOTTOM(tAbove)+mzMaxWalkLength); + LIST_ADD(walk, mzWalkList); + } + + /* move to next tile to right */ + tAbove = BL(tAbove); + } + } + + /* return 0 - to continue search */ + return(0); +} + +/* + * Structure to pass data between mzLRCWalksFunc, mzUDCWalksFunc, and mzCWalksFunc2 + */ +typedef struct walkContactFuncData +{ + Rect *wd_bounds; /* dest area bounds */ + RouteLayer *wd_rL; /* Route layer of walk_contact */ + int wd_walk; /* TT_ABOVE_*_WALK or TT_BELOW_*_WALK */ +} WalkContactFuncData; + + +/* + * ---------------------------------------------------------------------------- + * + * mzLRCWalksFunc -- + * + * Search dest area for regions where contacts are ok, and paint + * CONTACT_WALK(s) there in adjacent layers. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into adjacent blocakge planes. + * + * ---------------------------------------------------------------------------- + */ + +int +mzLRCWalksFunc(tile, cdarg) + Tile *tile; + ClientData cdarg; +{ + RouteType *rT = (RouteType *) cdarg; /* RouteType of this dest area */ + RouteContact *rC; + Rect rect; + int walkType; + + /* set rect to boundary of this dest area */ + TITORECT(tile, &rect); + + /* process contact types that can connect to this dest area */ + for (rC = mzRouteContacts; rC != NULL; rC = rC->rc_next) + { + RouteLayer *rLOther = NULL; + + /* skip inactive contact types */ + if (!(rC->rc_routeType.rt_active)) continue; + + /* Find layer connecting to dest area FROM */ + if (&(rC->rc_rLayer1->rl_routeType) == rT) + { + rLOther = rC->rc_rLayer2; + walkType = TT_ABOVE_LR_WALK; + } + else if (&(rC->rc_rLayer2->rl_routeType) == rT) + { + rLOther = rC->rc_rLayer1; + walkType = TT_BELOW_LR_WALK; + } + + /* If current contact type (RC) permits connection to dest area, + * insert CONTACT_WALK(s) into blockage planes for other layer. + */ + if (rLOther) + { + /* process contact-OK tiles in blockage plane for this contact */ + int mzCWalksFunc2(); + WalkContactFuncData wD; + TileTypeBitMask contactOKMask; + + TTMaskSetOnlyType(&contactOKMask, TT_SPACE); + TTMaskSetType(&contactOKMask, TT_SAMENODE); + + wD.wd_bounds = ▭ + wD.wd_rL = rLOther; + wD.wd_walk = walkType; + + /* search for OK places for contact in the horizontal plane */ + /* and paint them. */ + + DBSrPaintArea(NULL, /* no hint tile */ + rC->rc_routeType.rt_hBlock, + &rect, + &contactOKMask, + mzCWalksFunc2, + (ClientData) &wD); + } + } + + /* return 0 - to continue search */ + return(0); +} + +/* + * ---------------------------------------------------------------------------- + * + * mzUDCWalksFunc -- + * + * Search dest area for regions where contacts are ok, and paint + * CONTACT_WALK(s) there in adjacent layers. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into adjacent blocakge planes. + * + * ---------------------------------------------------------------------------- + */ + +int +mzUDCWalksFunc(tile, cdarg) + Tile *tile; + ClientData cdarg; +{ + RouteType *rT = (RouteType *) cdarg; /* RouteType of this dest area */ + RouteContact *rC; + Rect rect; + int walkType; + + /* set rect to boundary of this dest area */ + TITORECT(tile, &rect); + + /* process contact types that can connect to this dest area */ + for (rC = mzRouteContacts; rC != NULL; rC = rC->rc_next) + { + RouteLayer *rLOther = NULL; + + /* skip inactive contact types */ + if (!(rC->rc_routeType.rt_active)) continue; + + /* Find layer connecting to dest area FROM */ + if (&(rC->rc_rLayer1->rl_routeType) == rT) + { + rLOther = rC->rc_rLayer2; + walkType = TT_ABOVE_UD_WALK; + } + else if (&(rC->rc_rLayer2->rl_routeType) == rT) + { + rLOther = rC->rc_rLayer1; + walkType = TT_BELOW_UD_WALK; + } + + /* If current contact type (RC) permits connection to dest area, + * insert CONTACT_WALK(s) into blockage planes for other layer. + */ + if (rLOther) + { + /* process contact-OK tiles in blockage plane for this contact */ + int mzCWalksFunc2(); + WalkContactFuncData wD; + TileTypeBitMask contactOKMask; + + TTMaskSetOnlyType(&contactOKMask, TT_SPACE); + TTMaskSetType(&contactOKMask, TT_SAMENODE); + + wD.wd_bounds = ▭ + wD.wd_rL = rLOther; + wD.wd_walk = walkType; + + /* search for OK places for contact in the vertical plane */ + /* and paint them. */ + + DBSrPaintArea(NULL, /* no hint tile */ + rC->rc_routeType.rt_vBlock, + &rect, + &contactOKMask, + mzCWalksFunc2, + (ClientData) &wD); + } + } + + /* return 0 - to continue search */ + return(0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzCWalksFunc2 -- + * + * Called for tiles on contact plane where contact is OK that overlap a + * dest area. We paint a CONTACT_WALK on the blockage planes for the + * other routeLayer, the one the contact connects to the dest area. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into blockage planes for "other" route layer. + * + * ---------------------------------------------------------------------------- + */ + +int +mzCWalksFunc2(tile, cdarg) + Tile *tile; + ClientData cdarg; +{ + WalkContactFuncData *wD = (WalkContactFuncData *) cdarg; + Rect rect; + Walk *walk; + + /* rect = tile clipped dest area bounds. */ + TITORECT(tile, &rect); + GEOCLIP(&rect, wD->wd_bounds); + + /* To-do: check if non-square contacts fit? */ + + /* Build walks for contacts above or below the tile */ + { + walk = (Walk *) mallocMagic((unsigned) (sizeof(Walk))); + walk->w_rT = &(wD->wd_rL->rl_routeType); + walk->w_type = wD->wd_walk; + walk->w_rect = rect; + LIST_ADD(walk, mzWalkList); + } + + /* return 0 - to continue search */ + return(0); +} + diff --git a/mzrouter/mzDebug.c b/mzrouter/mzDebug.c new file mode 100644 index 00000000..eeb7ab7e --- /dev/null +++ b/mzrouter/mzDebug.c @@ -0,0 +1,564 @@ +/* + * mzDebug.c -- + * + * Routines for debugging. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$$"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/hash.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "utils/heap.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + +/* extra variables for use with dbx */ +RoutePath *mzDPath; +Tile *mzTile; +int mz; + +/* Forward declarations */ +extern void mzPrintRL(); +extern void mzPrintRT(); +extern void mzPrintRC(); +extern void mzPrintRP(); +extern void mzPrintPathHead(); + + +/* + * ---------------------------------------------------------------------------- + * + * MZPrintRCListNames -- + * + * Print names of route contacts linked together by external "list" + * + * Results: + * None. + * + * Side effects: + * None + * + * ---------------------------------------------------------------------------- + */ + +void +MZPrintRCListNames(l) + List *l; +{ + RouteContact *rC; + + TxPrintf("\t"); + + for(;l!=NULL; l=LIST_TAIL(l)) + { + rC = (RouteContact *) LIST_FIRST(l); + TxPrintf("%s ",DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]); + } + + TxPrintf("\n"); + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * MZPrintRLListNames -- + * + * Print names of route Layers linked together by external "list" + * + * Results: + * None. + * + * Side effects: + * None + * + * ---------------------------------------------------------------------------- + */ + +void +MZPrintRLListNames(l) + List *l; +{ + RouteLayer *rL; + + TxPrintf("\t"); + + for(;l!=NULL; l=LIST_TAIL(l)) + { + rL = (RouteLayer *) LIST_FIRST(l); + TxPrintf("%s ",DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]); + } + + TxPrintf("\n"); + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * MZPrintRLs -- + * + * Print list of RouteLayer strucs. + * + * Results: + * None. + * + * Side effects: + * None + * + * ---------------------------------------------------------------------------- + */ + +void +MZPrintRLs(rL) + RouteLayer *rL; +{ + while(rL!=NULL) + { + mzPrintRL(rL); + rL = rL->rl_next; + + if(rL!=NULL) TxMore(""); + } + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzPrintRL -- + * + * Print single RouteLayer struc. + * + * Results: + * None. + * + * Side effects: + * None + * + * ---------------------------------------------------------------------------- + */ + +void +mzPrintRL(rL) + RouteLayer *rL; +{ + List *cL; + + TxPrintf("ROUTE LAYER:\n"); + mzPrintRT(&(rL->rl_routeType)); + TxPrintf("\tplaneNum = %d (%s)\n",rL->rl_planeNum, + DBPlaneLongNameTbl[rL->rl_planeNum]); + + TxPrintf("\tcontactL = "); + for (cL=rL->rl_contactL; cL!=NULL; cL=LIST_TAIL(cL)) + { + TxPrintf("%s", + DBTypeLongNameTbl[ + ((RouteContact*) LIST_FIRST(cL))-> + rc_routeType.rt_tileType]); + + if(((RouteContact*) LIST_FIRST(cL))->rc_rLayer1 == rL) + TxPrintf("(to %s) ", DBTypeLongNameTbl[ + ((RouteContact*) LIST_FIRST(cL))-> + rc_rLayer2->rl_routeType.rt_tileType]); + else + TxPrintf("(to %s) ", DBTypeLongNameTbl[ + ((RouteContact*) LIST_FIRST(cL))-> + rc_rLayer1->rl_routeType.rt_tileType]); + } + TxPrintf("\n"); + + TxPrintf("\thCost = %d\n", + rL->rl_hCost); + TxPrintf("\tvCost = %d\n", + rL->rl_vCost); + TxPrintf("\tjogCost = %d\n", + rL->rl_jogCost); + TxPrintf("\thintCost = %d\n",rL->rl_hintCost); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzPrintRouteType -- + * + * Print routeType struc. + * + * Results: + * None. + * + * Side effects: + * None + * + * ---------------------------------------------------------------------------- + */ + +void +mzPrintRT(rT) + RouteType *rT; +{ + int i; + + TxPrintf("\tROUTETYPE:\n"); + TxPrintf("\t\ttileType = %s\n", DBTypeLongNameTbl[rT->rt_tileType]); + TxPrintf("\t\tactive = %s\n", (rT->rt_active ? "TRUE" : "FALSE")); + TxPrintf("\t\twidth = %d\n",rT->rt_width); + + TxPrintf("\t\tspacing = "); + for (i=0;irt_spacing[i]>=0) + TxPrintf("%s(%d) ",DBTypeLongNameTbl[i],rT->rt_spacing[i]); + if(rT->rt_spacing[TT_SUBCELL]>=0) + TxPrintf("%s(%d) ","SUBCELL",rT->rt_spacing[TT_SUBCELL]); + TxPrintf("\n"); + + TxPrintf("\t\teffWidth = %d\n",rT->rt_effWidth); + + for (i=0;irt_bloatBot[i]>=0) + TxPrintf("%s(%d) ",DBTypeLongNameTbl[i],rT->rt_bloatBot[i]); + if(rT->rt_spacing[TT_SUBCELL]>=0) + TxPrintf("%s(%d) ","SUBCELL",rT->rt_bloatBot[TT_SUBCELL]); + TxPrintf("\n"); + + for (i=0;irt_bloatTop[i]>=0) + TxPrintf("%s(%d) ",DBTypeLongNameTbl[i],rT->rt_bloatTop[i]); + if(rT->rt_spacing[TT_SUBCELL]>=0) + TxPrintf("%s(%d) ","SUBCELL",rT->rt_bloatTop[TT_SUBCELL]); + TxPrintf("\n"); + + TxPrintf("\t\tnext = %s\n", + (rT->rt_next ? DBTypeLongNameTbl[rT->rt_next->rt_tileType] : "(nil)")); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * MZPrintRCs -- + * + * Print list of RouteLayer strucs. + * + * Results: + * None. + * + * Side effects: + * None + * + * ---------------------------------------------------------------------------- + */ + +void +MZPrintRCs(rC) + RouteContact *rC; +{ + while(rC!=NULL) + { + mzPrintRC(rC); + rC = rC->rc_next; + if(rC!=NULL) TxMore(""); + } + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzPrintRC -- + * + * Print single RouteContact struc. + * + * Results: + * None. + * + * Side effects: + * None + * + * ---------------------------------------------------------------------------- + */ + +void +mzPrintRC(rC) + RouteContact *rC; +{ + TxPrintf("ROUTE CONTACT:\n"); + mzPrintRT(&(rC->rc_routeType)); + + TxPrintf("\trLayer1 = %s\n", + DBTypeLongNameTbl[rC->rc_rLayer1->rl_routeType.rt_tileType]); + TxPrintf("\trLayer2 = %s\n", + DBTypeLongNameTbl[rC->rc_rLayer2->rl_routeType.rt_tileType]); + + TxPrintf("\tcost = %d\n", + rC->rc_cost); + + return; +} + + + +/* + * ---------------------------------------------------------------------------- + * + * mzPrintRPs -- + * + * Print list of RoutePath strucs. + * + * Results: + * None. + * + * Side effects: + * None + * + * ---------------------------------------------------------------------------- + */ + +void +mzPrintRPs(path) + RoutePath *path; +{ + while(path!=NULL) + { + mzPrintRP(path); + path = path->rp_back; + } + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzPrintRP -- + * + * Print single RoutePath struc. + * + * Results: + * None. + * + * Side effects: + * None + * + * ---------------------------------------------------------------------------- + */ + +void +mzPrintRP(path) + RoutePath *path; +{ + TxPrintf("ROUTE PATH:"); + TxPrintf(" layer = %s", + DBTypeLongNameTbl[path->rp_rLayer->rl_routeType.rt_tileType]); + TxPrintf(" entry = (%d, %d)", path->rp_entry.p_x, path->rp_entry.p_y); + TxPrintf(" cost = %.0f", + (double)(path->rp_cost)); + TxPrintf(" extCode = { "); + if (path->rp_extendCode & EC_RIGHT) + { + TxPrintf("right "); + } + if (path->rp_extendCode & EC_LEFT) + { + TxPrintf("left "); + } + if (path->rp_extendCode & EC_UP) + { + TxPrintf("up"); + } + if (path->rp_extendCode & EC_DOWN) + { + TxPrintf("down "); + } + if (path->rp_extendCode & (EC_UDCONTACTS | EC_LRCONTACTS)) + { + TxPrintf("contacts "); + } + + TxPrintf("}\n"); + + return; +} + +/* mzPrintPathHead -- */ +void +mzPrintPathHead(path) + RoutePath *path; +{ + + if(path==NULL) + { + TxPrintf(" NULL Path.\n"); + } + else + { + TxPrintf(" point=(%d,%d), layer=%s, orient = '%c'", + path->rp_entry.p_x, + path->rp_entry.p_y, + DBTypeLongNameTbl[path->rp_rLayer->rl_routeType.rt_tileType], + path->rp_orient); + TxPrintf(", togo=%.0f", + (double)(path->rp_togo)); + TxPrintf(", cost=%.0f\n", + (double)(path->rp_cost)); + + TxPrintf(" extendCode = { "); + if (path->rp_extendCode & EC_RIGHT) + { + TxPrintf("right "); + } + if (path->rp_extendCode & EC_LEFT) + { + TxPrintf("left "); + } + if (path->rp_extendCode & EC_UP) + { + TxPrintf("up "); + } + if (path->rp_extendCode & EC_DOWN) + { + TxPrintf("down "); + } + if (path->rp_extendCode & (EC_LRCONTACTS | EC_UDCONTACTS)) + { + TxPrintf("contacts "); + } + + TxPrintf("}\n"); + } + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * mzDumpTags -- + * + * Dump tags on data tiles (for debugging). + * + * Results: + * None. + * + * Side effects: + * info written to file or via TxPrintf() + * + * ---------------------------------------------------------------------------- + */ + +void +mzDumpTags(area) + Rect *area; +{ + int mzDumpTagsFunc(); + SearchContext scx; + + /* mzke sure mzRouteUse is initialed */ + if(mzRouteUse == NULL) + { + TxPrintf("Can not dump tags, until mzRouteUse is initialed.\n"); + TxPrintf("(Do an iroute first.)\n"); + return; + } + + /* look at all data tiles under box. */ + scx.scx_area = *area; + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = mzRouteUse; + + (void) DBTreeSrTiles( + &scx, + &DBAllTypeBits, + 0, /* look inside all subcells */ + mzDumpTagsFunc, + (ClientData) NULL); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzDumpTagsFunc -- + * + * Filter function called above, dumps tag info for all tiles in search area. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Dumps info associated with tile. + * + * ---------------------------------------------------------------------------- + */ + +int +mzDumpTagsFunc(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + SearchContext *scx = cxp->tc_scx; + Rect r; + + /* if tile has no client data attached, skip it */ + if (tile->ti_client == (ClientData)CLIENTDEFAULT) + return 0; + + /* Get boundary of tile */ + TITORECT(tile, &r); + + /* print tile bounds */ + TxPrintf("tile %x (x: %d to %d, y: %d to %d)\n", + (pointertype) tile, r.r_xbot, r.r_xtop, r.r_ybot, r.r_ytop); + + /* dump rects attached to client field */ + { + List *l; + for(l=(List *) (tile->ti_client); l!=NULL; l=LIST_TAIL(l)) + { + Rect *rTerm = (Rect *) LIST_FIRST(l); + + TxPrintf("\tattached dest area (x: %d to %d, y: %d to %d)\n", + rTerm->r_xbot, + rTerm->r_xtop, + rTerm->r_ybot, + rTerm->r_ytop); + } + } + + /* continue search */ + return 0; +} + diff --git a/mzrouter/mzDebug.h b/mzrouter/mzDebug.h new file mode 100644 index 00000000..2ad5cead --- /dev/null +++ b/mzrouter/mzDebug.h @@ -0,0 +1,37 @@ +/* + * mzDebug.h -- + * + * Declarations of debugging flag "handles" for maze router. + * + * This include file is referenced inside mzInternal.h, hence hiding this + * file from make. This is so that debuging flags can be added without + * forcing recompilation of everything. + * + * Debug flags are defined and registered with the debug module in mzInit.c + * NOTE: the values of the externs defined below are NOT THE FLAG VALUES, + * rather they are handles for the flags - flags are tested with calls to + * DebugIsSet(). + * + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/mzrouter/mzDebug.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + */ + +extern int mzDebStep; /* single step - pauses after each path extension, + and prints statistics */ +extern int mzDebMaze; /* traces maze router - details on selection of + best path and extension from it. */ + diff --git a/mzrouter/mzEstimate.c b/mzrouter/mzEstimate.c new file mode 100644 index 00000000..d9675aee --- /dev/null +++ b/mzrouter/mzEstimate.c @@ -0,0 +1,2024 @@ +/* + * mzEstimate.c -- + * + * Management of tile plane for estimation of remaining cost to completion. + * + * Contains code for building estimation plane (just prior to route), and + * routine for computing estimates (using the estimation plane) during routing. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * EXPLANATION OF ESTIMATION CODE: + * The purpose of the estimation code is to estimate cost to completion + * from any point to the destintation taking into account the need to + * detour around major obstactles such as subcells and fences. + * + * The estimation plane permits multiple destination area (routes are + * made to what ever area is easiest to reach). The mzrouter also permits + * multiple start points of course. + * + * To achieve this purpose, prior to beginning the search for a route an + * estimation plane is generated with info that allows quick estimation + * of cost to completion during routing. + * + * The estimation plane contains + * ``solid'' tiles for major obstacles (subcells and fences) and space + * tiles. The space tiles are split on the extensions of solid tile edges + * so that one can always get from a solid tile corner straight out to + * the next blocking solid tile along tile edges. Space tiles are also split + * outward in each direction from the destination point. + * + * Estimators are generated for each tile in the estimation plane that allow + * estimates to be made for points in that tile. An estimator consists + * of five numbers: + * (x0,y0,hcost,vcost,cost0) + * that are used in the following formula: + * EstCost = (x - x0)*hcost + (y -y0)*vcost + cost0. + * An estimator represents the approximate cost of a path beginning at any + * point (x,y) in the current tile and proceedings horizontally and then + * vertically + * (or vice versa) to the tile corner (x0,y0) and then following the cheapest + * path along tile-edges to a destination area. The cheapest path from + * (x0,y0) is precomputed and has cost cost0. Currently only + * tile corners (x0,y0) of the tile the estimator is attached to are used + * for estimators. Estimators are also generated for paths from edges of + * a tile straight across to the nearest dest area (with out jogs). These + * "straight shot" estimators have zero hcost or vcost. + * Several estimators are attached to each + * tile, and the least cost one is used for any given (x,y). + * + * The estimation plane is generated in the following steps: + * + * 1. Generate solid tiles for unexpanded subcells (if subcells + can not be routed across on any active layer) and fences. + * + * 2. Split space tiles along extended edges of solid tiles and + * destination areas. + * + * 3. Assign a horizontal and vertical cost for routing in each tile. + * Cost for space tiles is cost of min active route-layer, cost for + * solid tiles is INFINITY. (could be more sophisticated - e.g. + * if routing is allowed over subcells on an expensive layer.) + * + * 4. Apply djikstra's shortest path algorithm to graph whose vertices + * are tile-corners and whose edges are tile edges. Weight on + * hor edges is min hor cost of the two adjacent tiles, weight on + * vertical edges is min of vert costs of adjacent tiles. Djikstra's + * algor. computes least cost path along tile-edges to + * destination for all tile corners + * (e.g. it generates all the cost0's for the estimators). + * + * 5. Build estimators for each tile - currently one estimator is built + * for each corner of the tile. + * + * 6. Trim away redundant estimators - currently if an estimator e0 is + * always cheaper than a second e1, e1 is thrown away. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzEstimate.c,v 1.2 2008/06/01 18:37:44 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "textio/textio.h" +#include "utils/heap.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + +/* largest finite tile plane coordinates, need to reduce INFINITY and MINFINITY + * defined in tile.h because of some funny buisness off at infinity? + */ + +/* Special case mips machines because of a compiler bug, as of 8/9/89 */ +#ifdef mips +static int MAX_FINITE_COORDINATE = (INFINITY-10); +static int MIN_FINITE_COORDINATE = (MINFINITY+10); +#else +#define MAX_FINITE_COORDINATE (INFINITY-10) +#define MIN_FINITE_COORDINATE (MINFINITY+10) +#endif + +/*----------- Vertex structure for shortest path algorithm ---------------*/ +typedef struct vertex +{ + int vx_status; /* which corner in tile, IN set when min distance + * to vertex determined (shortest path algor) */ + Tile *vx_tile; /* tile vertex is attached to */ + dlong vx_cost; /* Min cost from here to destination point */ +} Vertex; + +#define VX_CORNER 7 +#define VX_NONE 0 +#define VX_L_LEFT 1 +#define VX_U_LEFT 2 +#define VX_L_RIGHT 4 +#define VX_IN 8 + +/* Estimators for estimating cost from point within tile, (x,y), along a + * certain path to destination. + * + * EstCost = (x - x0) * hCost + (y - y0) * vCost + cost0 + */ +typedef struct estimate +{ + int e_x0; + int e_y0; + dlong e_cost0; + int e_hCost; + int e_vCost; + struct estimate *e_next; +} Estimate; + +/* --------------- tileCosts structure --------------------------------------*/ +/* One of these is associated with each tile in the mzEstimate plane. They + * are pointed to by the client fields of the tiles. + */ +typedef struct tileCosts +{ + int tc_hCost; /* horizontal cost / unit distance */ + int tc_vCost; /* vertical cost / unit distance */ + Vertex tc_vxLLeft; /* Vertices corresponding to 3 corners of this tile */ + Vertex tc_vxULeft; + Vertex tc_vxLRight; + Estimate *tc_estimates; /* path estimates for point in this tile */ +} TileCosts; + +/*---------------- static data, local to this file --------------------------*/ +bool mzEstimateExists = FALSE; /* Set on first call to mzBuildEstimate */ + +/* Forward declarations */ +extern void mzCleanEstimate(); +extern void mzBuildCornerEstimators(); +extern void mzBuildStraightShotEstimators(); +extern void mzSplitTiles(); +extern void mzAssignVertexCosts(); +extern void mzAddVertex(); + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildEstimate -- + * Setup contents of Estimation plane. + * + * Results: + * None + * + * Side effects: + * Add tiles to mzEstimate plane, create a tileCost struc for each tile + * complete with estimates. + * + * ---------------------------------------------------------------------------- + */ + +void +mzBuildEstimate() +{ + /* Clear estimation plane, reclaiming storage */ + if(mzEstimateExists) + { + mzCleanEstimate(); + } + mzEstimateExists = TRUE; /* Set flag, so we know to clean next time */ + + /* Now build the estimate plane from scratch */ + if(mzEstimate) + { + bool subcellsOpaque; + + /* determine whether subcells can be crossed on any active layer */ + { + RouteLayer *rL; + + subcellsOpaque = TRUE; + for(rL = mzActiveRLs; + rL!=NULL && subcellsOpaque; + rL=rL->rl_nextActive) + { + if(rL->rl_routeType.rt_spacing[TT_SUBCELL] < 0) + { + subcellsOpaque = FALSE; + } + } + } + + /* If over-the-cell routing is not possible, + * add a tile to the estimation plane for each unexpanded subcell. + * + * NOTE: A 0 expansion mask is special cased since + * the mzrouter interpets a 0 mask to mean all subcells are + * expanded, + * while DBTreeSrCells() takes a 0 mask to mean all subcells are + * unexpanded. + */ + if(mzCellExpansionMask != 0 && subcellsOpaque) + { + int mzAddSubcellEstFunc(); + SearchContext scx; + + scx.scx_area = mzBoundingRect; + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = mzRouteUse; + + /* clip area to bounding box to avoid overflow during transfroms */ + GEOCLIP(&(scx.scx_area),&(mzRouteUse->cu_def->cd_bbox)); + + DBTreeSrCells( + &scx, + mzCellExpansionMask, + mzAddSubcellEstFunc, + (ClientData) &mzBoundingRect); + } + + /* If route is OUTSIDE fence, add ``fence'' tiles to estimation plane + * for each FENCE tile on fence plane. + * If route is INSIDE fence, add ``fence'' tiles for each SPACE tile on + * the fence plane. + */ + { + int mzAddFenceEstFunc(); + + if(mzInsideFence) + { + + DBSrPaintArea(NULL, /* no hint tile */ + mzHFencePlane, + &mzBoundingRect, + &DBSpaceBits, + mzAddFenceEstFunc, + (ClientData) &mzBoundingRect); + } + else + { + + DBSrPaintArea(NULL, /* no hint tile */ + mzHFencePlane, + &mzBoundingRect, + &DBAllButSpaceBits, + mzAddFenceEstFunc, + (ClientData) &mzBoundingRect); + } + } + } + + /* Add a tile to the estimation plane for each dest area, and cut + * holes at the walks leading to the dest areas + */ + { + int mzProcessDestEstFunc(); + SearchContext scx; + + scx.scx_area = mzBoundingRect; + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = mzDestAreasUse; + + /* clip area to bounding box to avoid overflow during transforms */ + GEOCLIP(&(scx.scx_area),&(mzDestAreasUse->cu_def->cd_bbox)); + + (void) DBTreeSrTiles( + &scx, + &DBAllButSpaceAndDRCBits, + 0, + mzProcessDestEstFunc, + (ClientData) NULL); + } + + /*--- Split space tiles at edges of solid tiles. ---*/ + { + int mzBuildSolidsListFunc(); + List *solidsList = NULL; + List *l; + + /* Build list of all solid, + * i.e. nonspace, tiles on estimation plane. */ + DBSrPaintArea(NULL, /* no hint tile */ + mzEstimatePlane, + &TiPlaneRect, /* max paintable rect. */ + &DBAllButSpaceBits, + mzBuildSolidsListFunc, + (ClientData) &solidsList); + + /* Split tiles along perpendiculars of solid tile corners. */ + for(l=solidsList; l!=NULL; l = LIST_TAIL(l)) + { + Tile *solid = (Tile *) LIST_FIRST(l); + Point p; + + /* lower left corner */ + mzSplitTiles(mzEstimatePlane,&(solid->ti_ll)); + + /* top left corner */ + p.p_x = LEFT(solid); + p.p_y = TOP(solid); + mzSplitTiles(mzEstimatePlane,&p); + + /* top right corner */ + p.p_x = RIGHT(solid); + mzSplitTiles(mzEstimatePlane,&p); + + /* bottom right corner */ + p.p_y = BOTTOM(solid); + mzSplitTiles(mzEstimatePlane,&p); + } + + /* Free up solids list */ + ListDealloc(solidsList); + } + + /* Assign costs to tiles in estimation plane: + * Dest tiles - 0 cost. + * Space tiles - min active costs. + * Fence tiles - infinite cost. + * Subcell tiles - infinite cost. + */ + { + int mzAssignCostsFunc(); + TileCosts spaceCosts; + RouteLayer *rL; + + /* set space costs to min costs of active layers */ + spaceCosts.tc_hCost = INT_MAX; + spaceCosts.tc_vCost = INT_MAX; + for(rL = mzRouteLayers; rL!=NULL; rL=rL->rl_next) + { + if(rL->rl_routeType.rt_active) + { + if(rL->rl_hCost < spaceCosts.tc_hCost) + spaceCosts.tc_hCost = rL->rl_hCost; + if(rL->rl_vCost < spaceCosts.tc_vCost) + spaceCosts.tc_vCost = rL->rl_vCost; + } + } + + /* visit all tiles in estimate plane attaching cost structures + * (including vertices) to the client fields. Horizontal and + * vertical costs are assigned. + */ + DBSrPaintArea(NULL, /* no hint tile */ + mzEstimatePlane, + &TiPlaneRect, + &DBAllTypeBits, + mzAssignCostsFunc, + (ClientData) &spaceCosts); + } + + /* Apply djikstra shortest path algorithm to determine minimum costs + * to vertices in tile edge graph. + */ + mzAssignVertexCosts(); + + /* Build cost estimates for each tile in estimate plane */ + { + int mzBuildEstimatesFunc(); + + DBSrPaintArea(NULL, /* no hint tile */ + mzEstimatePlane, + &TiPlaneRect, + &DBAllTypeBits, + mzBuildEstimatesFunc, + (ClientData) NULL); + } + + /* Trim away redundant cost estimates on tiles */ + { + int mzTrimEstimatesFunc(); + + DBSrPaintArea(NULL, /* no hint tile */ + mzEstimatePlane, + &TiPlaneRect, + &DBAllTypeBits, + mzTrimEstimatesFunc, + (ClientData) NULL); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzCleanEstimate -- + * + * Clear estimate plane and reclaim storage. + * + * Results: + * None + * + * Side effects: + * See Above. + * + * ---------------------------------------------------------------------------- + */ + +void +mzCleanEstimate() +{ + if (mzEstimateExists) + { + int mzReclaimTCFunc(); + + SigDisableInterrupts(); /* Make atomic so we don't forget to reclaim + * anything nor reclaim it twice. + */ + + /* visit all tiles in estimate plane reclaiming attached + * cost structures. + */ + DBSrPaintArea(NULL, /* no hint tile */ + mzEstimatePlane, + &TiPlaneRect, /* max paintable rect */ + &DBAllTypeBits, + mzReclaimTCFunc, + (ClientData) NULL); + + DBClearPaintPlane(mzEstimatePlane); + + mzEstimateExists = FALSE; + + SigEnableInterrupts(); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzReclaimTCFunc -- + * + * Free TileCost struc (prior to erasing old estimate plane.) + * + * Results: + * Returns 0 always. + * + * Side effects: + * Frees TileCost pointed to by client field in tile struc. Clears + * client field pointer - just a precaution. + * + * ---------------------------------------------------------------------------- + */ + +int +mzReclaimTCFunc(tile, notUsed) + Tile *tile; + ClientData notUsed; +{ + if (tile->ti_client != (ClientData)CLIENTDEFAULT) + { + TileCosts *tc = ((TileCosts *) (tile->ti_client)); + Estimate *e; + + /* free estimates attached to tilecosts struc */ + for(e=tc->tc_estimates; e!=NULL; e=e->e_next) + { + freeMagic((char *) e); + } + + /* free tilecosts struc */ + freeMagic((char *) (tile->ti_client)); + + /* reset client field in tile */ + tile->ti_client = ((ClientData) CLIENTDEFAULT); + } + + /* return 0 - to continue traversal of old estimate plane */ + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzProcessDestEstFunc -- + * + * Filter function called via DBTreeSrTiles on behalf of mzBuildEstimate() + * above, for each dest area in the area of interest. Searches blockage + * planes for dest tiles and walks under dest area and paints corresponding + * tiles in estimation plane. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into mzEstimatePlane + * + * ---------------------------------------------------------------------------- + */ + +int +mzProcessDestEstFunc(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + SearchContext *scx = cxp->tc_scx; + TileType type = TiGetType(tile); + RouteType *rT; + Rect r, rect; + + /* Transform to result coordinates */ + TITORECT(tile, &r); + GEOTRANSRECT(&scx->scx_trans, &r, &rect); + + /* Grow rect by max walk size in all directions so we find walks as + * well as the dest area. + */ + rect.r_xbot -= mzMaxWalkLength; + rect.r_ybot -= mzMaxWalkLength; + rect.r_xtop += mzMaxWalkLength; + rect.r_ytop += mzMaxWalkLength; + + /* find route type for this dest area */ + { + rT = mzActiveRTs; + while ((rT->rt_tileType != type) && (rT!=NULL)) + { + rT = rT->rt_nextActive; + } + ASSERT(rT!=NULL,"mzAddDestTileEstFunc"); + } + + /* process dest and walk tiles below dest area */ + { + int mzDestTileEstFunc(); + TileTypeBitMask destMask; + + TTMaskSetOnlyType(&destMask, TT_DEST_AREA); + TTMaskSetType(&destMask, TT_LEFT_WALK); + TTMaskSetType(&destMask, TT_RIGHT_WALK); + TTMaskSetType(&destMask, TT_TOP_WALK); + TTMaskSetType(&destMask, TT_BOTTOM_WALK); + + DBSrPaintArea(NULL, /* no hint tile */ + rT->rt_hBlock, + &rect, + &destMask, + mzDestTileEstFunc, + (ClientData) NULL); + } + + return 0; +} + + + +/* + * ---------------------------------------------------------------------------- + * + * mzDestTileEstFunc -- + * + * Paint dest area into estimate plane, or cut whole over walks. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Modifies estimate plane. + * + * ---------------------------------------------------------------------------- + */ + +int +mzDestTileEstFunc(tile, cdarg) + Tile *tile; + ClientData cdarg; +{ + Rect rect; + + /* set rect to bounding box of tile */ + TITORECT(tile, &rect); + + if(TiGetType(tile)==TT_DEST_AREA) + /* paint dest area into estimate plane */ + { + DBPaintPlane(mzEstimatePlane, + &rect, + mzEstimatePaintTbl[TT_EST_DEST], + (PaintUndoInfo *) NULL); + } + else + /* cut hole for walk in estimate plane */ + { + DBPaintPlane(mzEstimatePlane, + &rect, + mzEstimatePaintTbl[TT_SPACE], + (PaintUndoInfo *) NULL); + } + + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzAddSubcellEstFunc -- + * + * Filter function called via DBTreeSrTiles on behalf of mzBuildEstimate() + * above, for each unexpanded subcell in the area of interest, + * a TT_EST_SUBCELL tile is painted on each estimate plane for + * the bounding box of the subcell. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into mzEstimatePlane + * + * ---------------------------------------------------------------------------- + */ + +int +mzAddSubcellEstFunc(scx, cdarg) + SearchContext *scx; + ClientData cdarg; +{ + Rect r, rDest; + + /* Transform bounding box to result coords */ + r = scx->scx_use->cu_def->cd_bbox; + GEOTRANSRECT(&scx->scx_trans, &r, &rDest); + + /* paint subcell block onto estimate plane */ + DBPaintPlane(mzEstimatePlane, + &rDest, + mzEstimatePaintTbl[TT_EST_SUBCELL], + (PaintUndoInfo *) NULL); + + /* continue search */ + return (0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzAddFenceEstFunc -- + * + * Filter function called via DBSrPaintArea on behalf of mzBuildEstimate() + * above, for each fence tile in the area of interest, + * a TT_EST_FENCE tile is painted on the estimate plane for + * each nonspace tile on the fence plane. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into mzEstimatePlane + * + * ---------------------------------------------------------------------------- + */ + +int +mzAddFenceEstFunc(tile, buildArea) + Tile *tile; + Rect *buildArea; /* currently ignored */ +{ + Rect r; + + /* Get boundary of tile */ + TITORECT(tile, &r); + + /* paint fence into estimate plane */ + DBPaintPlane(mzEstimatePlane, + &r, + mzEstimatePaintTbl[TT_EST_FENCE], + (PaintUndoInfo *) NULL); + + /* continue search */ + return (0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildSolidsList -- + * + * Called by DBSrPaintArea for each solid tile in estimation plane + * Creates list of these tiles. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Adds to list passed as arg. + * + * ---------------------------------------------------------------------------- + */ + +int +mzBuildSolidsListFunc(tile, listPtr) + Tile *tile; + List **listPtr; /* pointer to list to add tile to */ +{ + LIST_ADD(tile,*listPtr); + + /* return 0 - to continue search */ + return(0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzAssignCostsFunc -- + * + * Assigns horizontal and vertical costs to tiles in estimate plane. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Adds to list passed as arg. + * + * ---------------------------------------------------------------------------- + */ +int +mzAssignCostsFunc(tile, spaceCosts) + Tile *tile; + TileCosts *spaceCosts; /* costs to assign to space tiles */ +{ + Tile *tRight, *tUp; + TileCosts *newCosts; + Vertex *v; + + /* Alloc TileCosts struc for this tile, and attach it */ + newCosts = (TileCosts *) mallocMagic((unsigned) (sizeof(TileCosts))); + tile->ti_client = (ClientData) newCosts; + + /* Assign hor and vert costs for tile */ + switch(TiGetType(tile)) + { + case TT_EST_DEST: + newCosts->tc_hCost = 0; + newCosts->tc_vCost = 0; + break; + + case TT_SPACE: + *newCosts = *spaceCosts; + break; + + case TT_EST_FENCE: + case TT_EST_SUBCELL: + newCosts->tc_hCost = INT_MAX; + newCosts->tc_vCost = INT_MAX; + break; + + default: + /* unrecognized tile type */ + ASSERT(FALSE,"mzAssignCostsFunc"); + } + + /* add lower-left vertex */ + v = &(newCosts->tc_vxLLeft); + v->vx_status = VX_L_LEFT; + v->vx_tile = tile; + v->vx_cost = COST_MAX; + + /* add lower-right vertex, if at 'T' */ + NEXT_TILE_RIGHT(tRight, tile, BOTTOM(tile)); + if (BOTTOM(tRight)!=BOTTOM(tile)) + { + /* lower-right vertex at 'T', so add it */ + v = &(newCosts->tc_vxLRight); + v->vx_status = VX_L_RIGHT; + v->vx_tile = tile; + v->vx_cost = COST_MAX; + } + else + { + /* no 'T' */ + newCosts->tc_vxLRight.vx_status = VX_NONE; + } + + /* add upper-left vertex, if at 'T' */ + NEXT_TILE_UP(tUp, tile, LEFT(tile)); + if (LEFT(tUp)!=LEFT(tile)) + { + /* upper-left vertex at 'T', so add it */ + v = &(newCosts->tc_vxULeft); + v->vx_status = VX_U_LEFT; + v->vx_tile = tile; + v->vx_cost = COST_MAX; + } + else + { + /* no 'T' */ + newCosts->tc_vxULeft.vx_status = VX_NONE; + } + + /* initial estimates to NULL list */ + newCosts->tc_estimates = NULL; + + /* return 0 - to continue traversal of estimate plane */ + return(0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzDestInitialAssignFunc + * + * Add one vertex of dest tile to adjacency heap to initialize graph for + * Djikstra's shortest path computation. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Initials cost to zero and adds a vertex to adjacency heap. + * + * ---------------------------------------------------------------------------- + */ +int +mzDestInitialAssignFunc(tile, cdarg) + Tile *tile; + ClientData cdarg; +{ + Heap *adjHeap = (Heap *) cdarg; + Vertex *v; + + /* get lower left vertex */ + v = &(((TileCosts *)(tile->ti_client))->tc_vxLLeft); + + /* cost from dest is zero */ + v->vx_cost = 0; + + /* add vertex to adjHeap */ + HeapAddDLong(adjHeap, 0, (char *) v); + + /* return 0 - to continue search */ + return(0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildEstimatesFunc -- + * + * Build path estimates for this tile. + * (For now builds + * + one estimate for each corner of the tile. + * + one estimate for no jog path to destination in each direction where + * this is possible.) + * + * Results: + * Returns 0 always. + * + * Side effects: + * Adds estimates to TileCost struc attached to tile. + * + * ---------------------------------------------------------------------------- + */ + +int +mzBuildEstimatesFunc(tile, notUsed) + Tile *tile; + ClientData notUsed; +{ + + mzBuildCornerEstimators(tile); + mzBuildStraightShotEstimators(tile); + + /* return 0 - to continue traversal of estimate plane */ + return(0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildCornerEstimators -- + * + * Build path estimates for paths via corners of this tile. + * + * Results: + * None. + * + * Side effects: + * Adds estimates to TileCost struc attached to tile. + * + * ---------------------------------------------------------------------------- + */ + +void +mzBuildCornerEstimators(tile) + Tile *tile; +{ + TileCosts *tc = (TileCosts *) (tile->ti_client); + Vertex *vLLeft = NULL; + Vertex *vULeft = NULL; + Vertex *vLRight = NULL; + Vertex *vURight = NULL; + + /* find vertex strucs corresponding to four corners. + * (NULL, for corners at infinity) + */ + { + Tile *tUp, *tRight, *tDiag; + Tile *tRT, *tTR; + + if(LEFT(tile)>=MIN_FINITE_COORDINATE) + { + if(BOTTOM(tile)>=MIN_FINITE_COORDINATE) + { + /* Lower Left */ + vLLeft = &(tc->tc_vxLLeft); + } + + if(TOP(tile)<=MAX_FINITE_COORDINATE) + { + /* Upper Left */ + NEXT_TILE_UP(tUp, tile, LEFT(tile)); + if (LEFT(tUp)tc_vxULeft); + } + else + { + /* no 'T', stored with tUp */ + vULeft = &(((TileCosts *)(tUp->ti_client))->tc_vxLLeft); + } + } + } + + if(RIGHT(tile)<=MAX_FINITE_COORDINATE) + { + if(BOTTOM(tile)>=MIN_FINITE_COORDINATE) + { + /* Lower Right */ + NEXT_TILE_RIGHT(tRight, tile, BOTTOM(tile)); + if (BOTTOM(tRight)tc_vxLRight); + } + else + { + /* no 'T', stored with tRight */ + vLRight = &(((TileCosts *)(tRight->ti_client))->tc_vxLLeft); + } + } + + if(TOP(tile)<=MAX_FINITE_COORDINATE) + { + /* Upper Right */ + tRT = RT(tile); /* right top corner stitch (up) */ + tTR = TR(tile); /* top right corner stitch (to right) */ + if(RIGHT(tRT)>RIGHT(tile)) + { + /* upper right at 'T' stored with tTR */ + vURight = &(((TileCosts *)(tTR->ti_client))->tc_vxULeft); + } + else if (TOP(tTR)>TOP(tile)) + { + /* upper right at 'T' stored with tRT */ + vURight = &(((TileCosts *)(tRT->ti_client))->tc_vxLRight); + } + else + { + /* no 'T', stored in own tile */ + NEXT_TILE_UP(tDiag, tTR, RIGHT(tile)); + vURight = &(((TileCosts *)(tDiag->ti_client))->tc_vxLLeft); + } + } + } + } + + /* Build estimates */ + { + Estimate *e; + + /* Estimate for lower left corner */ + if (vLLeft) + { + e = (Estimate *) mallocMagic((unsigned) (sizeof(Estimate))); + e->e_x0 = LEFT(tile); + e->e_y0 = BOTTOM(tile); + e->e_cost0 = vLLeft->vx_cost; + e->e_hCost = tc->tc_hCost; + e->e_vCost = tc->tc_vCost; + e->e_next = tc->tc_estimates; + tc->tc_estimates = e; + } + + /* Estimate for lower right corner */ + if (vLRight) + { + e = (Estimate *) mallocMagic((unsigned) (sizeof(Estimate))); + e->e_x0 = RIGHT(tile); + e->e_y0 = BOTTOM(tile); + e->e_cost0 = vLRight->vx_cost; + e->e_hCost = tc->tc_hCost; + e->e_vCost = tc->tc_vCost; + e->e_next = tc->tc_estimates; + tc->tc_estimates = e; + } + + /* Estimate for upper right corner */ + if (vURight) + { + e = (Estimate *) mallocMagic((unsigned) (sizeof(Estimate))); + e->e_x0 = RIGHT(tile); + e->e_y0 = TOP(tile); + e->e_cost0 = vURight->vx_cost; + e->e_hCost = tc->tc_hCost; + e->e_vCost = tc->tc_vCost; + e->e_next = tc->tc_estimates; + tc->tc_estimates = e; + } + + /* Estimate for upper left corner */ + if (vULeft) + { + e = (Estimate *) mallocMagic((unsigned)(sizeof(Estimate))); + e->e_x0 = LEFT(tile); + e->e_y0 = TOP(tile); + e->e_cost0 = vULeft->vx_cost; + e->e_hCost = tc->tc_hCost; + e->e_vCost = tc->tc_vCost; + e->e_next = tc->tc_estimates; + tc->tc_estimates = e; + } + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildStraightShotEstimators -- + * + * Build path estimates for paths straight to dest area (no jogs) + * + * Results: + * None. + * + * Side effects: + * Adds estimates to TileCost struc attached to tile. + * + * ---------------------------------------------------------------------------- + */ +void +mzBuildStraightShotEstimators(tile) + Tile *tile; +{ + TileCosts *tc = (TileCosts *) (tile->ti_client); + + /* straight right */ + { + Tile *tSolid = tile; + + /* get first solid tile to right */ + while(TiGetType(tSolid)==TT_SPACE && + tSolid!=mzEstimatePlane->pl_right) + { + tSolid = TR(tSolid); + } + + /* if dest tile, build estimator */ + if(TiGetType(tSolid) == TT_EST_DEST) + { + Estimate *e; + + e = (Estimate *) mallocMagic((unsigned)(sizeof(Estimate))); + e->e_x0 = RIGHT(tile); + e->e_y0 = 0; + if (tc->tc_hCost == INT_MAX) + e->e_cost0 = COST_MAX; + else + e->e_cost0 = (dlong) (LEFT(tSolid) - RIGHT(tile)) * tc->tc_hCost; + e->e_hCost = tc->tc_hCost; + e->e_vCost = 0; + e->e_next = tc->tc_estimates; + tc->tc_estimates = e; + } + } + + /* straight left */ + { + Tile *tSolid = tile; + + /* get first solid tile to left */ + while(TiGetType(tSolid)==TT_SPACE && + tSolid!=mzEstimatePlane->pl_left) + { + tSolid = BL(tSolid); + } + + /* if dest tile, build estimator */ + if(TiGetType(tSolid) == TT_EST_DEST) + { + Estimate *e; + + e = (Estimate *) mallocMagic((unsigned)(sizeof(Estimate))); + e->e_x0 = LEFT(tile); + e->e_y0 = 0; + if (tc->tc_hCost == INT_MAX) + e->e_cost0 = COST_MAX; + else + e->e_cost0 = (dlong) (RIGHT(tSolid) - LEFT(tile)) * tc->tc_hCost; + e->e_hCost = tc->tc_hCost; + e->e_vCost = 0; + e->e_next = tc->tc_estimates; + tc->tc_estimates = e; + } + } + + /* straight up */ + { + Tile *tSolid = tile; + + /* get first solid tile above */ + while(TiGetType(tSolid)==TT_SPACE && + tSolid!=mzEstimatePlane->pl_top) + { + tSolid = RT(tSolid); + } + + /* if dest tile, build estimator */ + if(TiGetType(tSolid) == TT_EST_DEST) + { + Estimate *e; + + e = (Estimate *) mallocMagic((unsigned)(sizeof(Estimate))); + e->e_x0 = 0; + e->e_y0 = TOP(tile); + if (tc->tc_vCost == INT_MAX) + e->e_cost0 = COST_MAX; + else + e->e_cost0 = (dlong) (BOTTOM(tSolid) - TOP(tile)) * tc->tc_vCost; + e->e_hCost = 0; + e->e_vCost = tc->tc_vCost; + e->e_next = tc->tc_estimates; + tc->tc_estimates = e; + } + } + + /* straight down */ + { + Tile *tSolid = tile; + + /* get first solid tile below */ + while(TiGetType(tSolid)==TT_SPACE && + tSolid!=mzEstimatePlane->pl_bottom) + { + tSolid = LB(tSolid); + } + + /* if dest tile, build estimator */ + if(TiGetType(tSolid) == TT_EST_DEST) + { + Estimate *e; + + e = (Estimate *) mallocMagic((unsigned)(sizeof(Estimate))); + e->e_x0 = 0; + e->e_y0 = BOTTOM(tile); + if (tc->tc_vCost == INT_MAX) + e->e_cost0 = COST_MAX; + else + e->e_cost0 = (dlong)(TOP(tSolid) - BOTTOM(tile)) * tc->tc_vCost; + e->e_hCost = 0; + e->e_vCost = tc->tc_vCost; + e->e_next = tc->tc_estimates; + tc->tc_estimates = e; + } + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * AlwaysAsGood -- + * + * Compares two estimators. + * + * Results: + * Returns TRUE iff est1 is always less than or equal to est2. + * + * Side effects: + * modifies estimates list in TileCost struc attached to tile, + * specifically sets floating origin coords. (Floating coords + * are those with corresponding cost field of 0, hence + * there value does not matter when computing estimates. They + * are set here as a convience, to permit uniform treatment of + * all estimators within this function.) + * + * + * + * ---------------------------------------------------------------------------- + */ + +bool +AlwaysAsGood(est1, est2, tile) + Estimate *est1; + Estimate *est2; + Tile *tile; +{ + if(est1->e_cost0 > est2->e_cost0) + { + return FALSE; + } + else + /* check if using est1 even from est2 origin + * is cheaper than using est2 */ + { + /* If est2 x origin is floating, set to worst case */ + if(est2->e_hCost == 0) + { + est2->e_x0 = (ABS(LEFT(tile) - est1->e_x0) > + ABS(RIGHT(tile) - est1->e_x0)) ? + LEFT(tile) : RIGHT(tile); + } + + /* If est2 y origin is floating, set to worst case */ + if(est2->e_vCost == 0) + { + est2->e_y0 = (ABS(BOTTOM(tile) - est1->e_y0) > + ABS(TOP(tile) - est1->e_y0)) ? + BOTTOM(tile) : TOP(tile); + } + + /* now compute the cost from est2 origin using est1 */ + + { + dlong hCost, vCost, cost; + + if ((est1->e_hCost == INT_MAX) || (est1->e_vCost == INT_MAX)) + return FALSE; + + hCost = (dlong) (est1->e_hCost * + ABS(est2->e_x0 - est1->e_x0)); + vCost = (dlong) (est1->e_vCost * + ABS(est2->e_y0 - est1->e_y0)); + + cost = hCost + vCost; + cost += est1->e_cost0; + + return (cost <= est2->e_cost0); + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzTrimEstimatesFunc -- + * + * Throw away redundant cost estimates. + * + * Results: + * Returns 0 always. + * + * Side effects: + * modifies estimates list in TileCost struc attached to tile. + * + * ---------------------------------------------------------------------------- + */ + +int +mzTrimEstimatesFunc(tile, notUsed) + Tile *tile; + ClientData notUsed; +{ + TileCosts *tc = (TileCosts *) (tile->ti_client); + Estimate *e; + Estimate *reqEstimates = NULL; + + e = tc->tc_estimates; + while(e) + { + Estimate *e2; + bool found = FALSE; + + /* Check if a required estimate is always as good as e */ + for(e2 = reqEstimates; e2!= NULL && !found; e2=e2->e_next) + { + if(AlwaysAsGood(e2,e,tile)) + { + found = TRUE; + } + } + + /* Check if a not-yet-processed estimate is always as good as e */ + for(e2 = e->e_next; e2!= NULL && !found; e2=e2->e_next) + { + if(AlwaysAsGood(e2,e,tile)) + { + found = TRUE; + } + } + + /* Throw away e if redundant, else save on reqEstimates list, and + * continue with next unprocessed estimate. + */ + { + Estimate *eNext = e->e_next; + if(found) + /* Throw away */ + { + freeMagic((char *) e); + } + else + /* Add to required list */ + { + e->e_next = reqEstimates; + reqEstimates = e; + } + e = eNext; + } + } + + /* save required estimate list */ + tc->tc_estimates = reqEstimates; + + /* return 0 - to continue traversal of estimate plane */ + return(0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzSplitTiles -- + * + * Split space tiles in four directions from point - stopping at solid tiles. + * + * Results: + * None + * + * Side effects: + * Modifies tile structure of plane. + * + * ---------------------------------------------------------------------------- + */ + +void +mzSplitTiles(plane, point) + Plane * plane; + Point * point; /* origin from which tiles split */ +{ + Tile *pointTile = TiSrPointNoHint(plane, point); + Tile *t; + int x = point->p_x; + int y = point->p_y; + + /* Don't split from infinite points */ + if(xMAX_FINITE_COORDINATE || + yMAX_FINITE_COORDINATE) + { + return; + } + + /* split tiles to right of point */ + { + /* init t to tile to right of pointTile */ + NEXT_TILE_RIGHT(t,pointTile,y); + + while (TiGetType(t)==TT_SPACE && BOTTOM(t)!=y && t!=plane->pl_right) + { + /* split t */ + t=TiSplitY(t, y); + + /* move one tile to right */ + NEXT_TILE_RIGHT(t,t,y); + } + } + + /* split tiles up from point */ + { + /* init t to tile above pointTile */ + NEXT_TILE_UP(t,pointTile,x) + + while (TiGetType(t)==TT_SPACE && LEFT(t)!=x && t!=plane->pl_top) + { + /* split t */ + t=TiSplitX(t, x); + + /* move one tile up */ + NEXT_TILE_UP(t,t,x); + } + } + + /* split tiles to left of point */ + { + /* init t to tile to left of pointTile */ + NEXT_TILE_LEFT(t,pointTile,y); + + while (TiGetType(t)==TT_SPACE && BOTTOM(t)!=y && t!=plane->pl_left) + { + /* split t */ + t = TiSplitY(t, y); + + /* move one tile to left */ + NEXT_TILE_LEFT(t,t,y); + } + } + + /* split tiles down from point */ + { + /* init t to tile below pointTile */ + NEXT_TILE_DOWN(t,pointTile,x); + + while (TiGetType(t)==TT_SPACE && LEFT(t)!=x && t!=plane->pl_bottom) + { + /* split t */ + t=TiSplitX(t, x); + + /* move one tile down */ + NEXT_TILE_DOWN(t,t,x); + } + } + + /* finally, if point is in a SPACE tile, split it in four */ + if(TiGetType(pointTile)==TT_SPACE) + { + t = pointTile; + if(x != LEFT(t)) + { + Tile *tOther = TiSplitX(t, x); + if(y != BOTTOM(tOther)) + TiSplitY(tOther, y); + } + if(y != BOTTOM(t)) + TiSplitY(t, y); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzAssignVertexCosts -- + * + * Applies Djikstra's shortest path algorithm to compute minimum cost to + * each tile corner, assuming cost along edge is minimum of cost associated + * with adjacent tiles times length of the edge. (Hor costs for hor. edges, + * vertical costs for vertical edges.) + * + * Treats estimate plane as a graph, with tile corners as vertices and + * tile edges as nodes. Weights + * + * Results: + * None. + * + * Side effects: + * Fills in vertex costs in strucs hanging of clientData fields of + * tiles in estimation plane. + * + * ---------------------------------------------------------------------------- + */ + +void +mzAssignVertexCosts() +{ + Heap adjHeap; /* vertices adjacent to the IN set are put here */ + HeapEntry buf, *he; + Tile *t; + + /* Initialize Heap */ + HeapInitType(&adjHeap, 1024, FALSE, FALSE, HE_DLONG); + + /* Initial at least one vertex of each dest term to zero cost and add + * to adjHeap. Zero cost will be propagated to other vertices of dest + * terms since hcost and vcost are 0 for dest tiles. + */ + { + int mzDestInitialAssignFunc(); + TileTypeBitMask destOnly; + + TTMaskSetOnlyType(&destOnly, TT_EST_DEST); + + DBSrPaintArea(NULL, /* no hint tile */ + mzEstimatePlane, + &mzBoundingRect, + &destOnly, + mzDestInitialAssignFunc, + (ClientData) &adjHeap); + } + + /* keep adding least cost ADJACENT vertex to IN until no ADJACENT vertices + * left. (Vertices adjacent to the addvertex are added to adjHeap.) + */ + while((he = HeapRemoveTop(&adjHeap,&buf))!=NULL) + { + Vertex *v = (Vertex *)(he->he_id); + if (!(v->vx_status & VX_IN)) + { + /* vertex not already IN, so process it */ + mzAddVertex(v,&adjHeap); + } + } + + /* Free heap */ + HeapKill(&adjHeap, (void (*)()) NULL); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzAddVertex -- + * + * Subroutine of mzAssignVertexCosts. + * Adds least cost vertex on adjHeap to IN set. Adds vertices adjacent to + * new IN vertex to adjHeap, or adjusts there cost if they are already there. + * + * Results: + * None. + * + * Side effects: + * Modifies adjHeap and vertex strucs attached to tiles + * on estimation plane. + * + * ---------------------------------------------------------------------------- + */ + +void +mzAddVertex(vxThis, adjHeap) + Vertex *vxThis; + Heap *adjHeap; +{ + Tile *tThis; /* Tile vxThis is attached to */ + Point loc; /* location of vxThis */ + Tile *tLoc; /* Tile containing location of vxThis */ + Tile *tLeft, *tRight, *tAbove, *tBelow; /* Neighbors of tLoc */ + + /* Mark this vertex IN */ + vxThis->vx_status |= VX_IN; + + /* Ignore if we're already at maximum cost */ + if (vxThis->vx_cost == COST_MAX) return; + + /* compute location of this vertex, and tile containing that loc */ + tThis = vxThis->vx_tile; + switch (vxThis->vx_status & VX_CORNER) + { + case VX_L_LEFT: + loc.p_x = LEFT(tThis); + loc.p_y = BOTTOM(tThis); + tLoc = tThis; + break; + + case VX_L_RIGHT: + loc.p_x = RIGHT(tThis); + loc.p_y = BOTTOM(tThis); + NEXT_TILE_RIGHT(tLoc, tThis, BOTTOM(tThis)); + break; + + case VX_U_LEFT: + loc.p_x = LEFT(tThis); + loc.p_y = TOP(tThis); + NEXT_TILE_UP(tLoc, tThis, LEFT(tThis)); + break; + } + + /* find tiles neighboring loc */ + NEXT_TILE_LEFT(tLeft, tLoc, loc.p_y); + NEXT_TILE_RIGHT(tRight, tLoc, loc.p_y); + NEXT_TILE_UP(tAbove, tLoc, loc.p_x); + NEXT_TILE_DOWN(tBelow, tLoc, loc.p_x); + + /* process adjacent vertex ABOVE */ + { + Vertex *vxAbove; + int yAbove; + + /* Check for no edge above */ + if(LEFT(tLoc)!=loc.p_x) + goto noAbove; + + if(TOP(tLeft) < TOP(tLoc)) + { + /* T from left */ + vxAbove = &(((TileCosts *)(RT(tLeft)->ti_client))->tc_vxLRight); + yAbove = TOP(tLeft); + } + else + { + if(LEFT(tAbove)==LEFT(tLoc)) + { + /* no T */ + vxAbove = &(((TileCosts *)(tAbove->ti_client))->tc_vxLLeft); + yAbove = BOTTOM(tAbove); + } + else + { + /* T from bottom */ + vxAbove = &(((TileCosts *)(tLoc->ti_client))->tc_vxULeft); + yAbove = BOTTOM(tAbove); + } + } + + /* adjust cost */ + { + int rate, distance; + dlong newCost; + + if(yAbove > MAX_FINITE_COORDINATE) goto noAbove; + + rate = MIN(((TileCosts *)(tLoc->ti_client))->tc_vCost, + ((TileCosts *)(tLeft->ti_client))->tc_vCost); + + if(rate == INT_MAX) goto noAbove; + + distance = yAbove - loc.p_y; + newCost = (dlong) (rate * distance); + newCost += vxThis->vx_cost; + + if(newCost < vxAbove->vx_cost) + { + vxAbove->vx_cost = newCost; + HeapAddDLong(adjHeap, newCost, (char *) vxAbove); + } + } + noAbove:; + } + + + /* process adjacent vertex to RIGHT */ + { + Vertex *vxRight; + int xRight; + + /* Check for no edge to RIGHT */ + if(BOTTOM(tLoc)!=loc.p_y) + goto noRight; + + if(RIGHT(tBelow) < RIGHT(tLoc)) + { + /* T from below */ + vxRight = &(((TileCosts *)(TR(tBelow)->ti_client))->tc_vxULeft); + xRight = RIGHT(tBelow); + } + else + { + if(BOTTOM(tRight)==BOTTOM(tLoc)) + { + /* no T */ + vxRight = &(((TileCosts *)(tRight->ti_client))->tc_vxLLeft); + xRight = LEFT(tRight); + } + else + { + /* T from left */ + vxRight = &(((TileCosts *)(tLoc->ti_client))->tc_vxLRight); + xRight = LEFT(tRight); + } + } + + /* adjust cost */ + { + int rate, distance; + dlong newCost; + + if(xRight > MAX_FINITE_COORDINATE) goto noRight; + + rate = MIN( + ((TileCosts *)(tLoc->ti_client))->tc_hCost, + ((TileCosts *)(tBelow->ti_client))->tc_hCost); + + if(rate == INT_MAX) goto noRight; + + distance = xRight - loc.p_x; + newCost = (dlong) (rate * distance); + newCost += vxThis->vx_cost; + + if (newCost < vxRight->vx_cost) + { + vxRight->vx_cost = newCost; + HeapAddDLong(adjHeap, newCost, (char *) vxRight); + } + } + noRight:; + } + + /* For going down and to the left, we want tiles to contain their + * right and upper edges. Adjust tLoc and neighbors accordingly. + * The trick is to center tLoc and neighbors around loc - (1,1). + */ + { + Point locMinus; + + /* locMinus used to get tiles for loc, that contain top and right + * edges. + */ + + locMinus = loc; + --(locMinus.p_x); + --(locMinus.p_y); + + if(BOTTOM(tLoc)>locMinus.p_y) + NEXT_TILE_DOWN(tLoc, tLoc, loc.p_x); + if(LEFT(tLoc)>locMinus.p_x) + NEXT_TILE_LEFT(tLoc, tLoc, locMinus.p_y); + + /* find tiles neighboring loc */ + NEXT_TILE_LEFT(tLeft, tLoc, locMinus.p_y); + NEXT_TILE_RIGHT(tRight, tLoc, locMinus.p_y); + NEXT_TILE_UP(tAbove, tLoc, locMinus.p_x); + NEXT_TILE_DOWN(tBelow, tLoc, locMinus.p_x); + } + + /* process adjacent vertex BELOW */ + { + Vertex *vxBelow; + int yBelow; + + /* Check for no edge below */ + if(RIGHT(tLoc)!=loc.p_x) + goto noBelow; + + if(BOTTOM(tRight) >= BOTTOM(tLoc)) + { + /* LowerLeft of tRight */ + vxBelow = &(((TileCosts *)(tRight->ti_client))->tc_vxLLeft); + yBelow = BOTTOM(tRight); + } + else + { + /* T from Left */ + vxBelow = &(((TileCosts *)(tLoc->ti_client))->tc_vxLRight); + yBelow = BOTTOM(tLoc); + } + + /* adjust cost */ + { + int rate, distance; + dlong newCost; + + if(yBelow < MIN_FINITE_COORDINATE) goto noBelow; + + rate = MIN( + ((TileCosts *)(tLoc->ti_client))->tc_vCost, + ((TileCosts *)(tRight->ti_client))->tc_vCost); + + if(rate == INT_MAX) goto noBelow; + + distance = loc.p_y - yBelow; + newCost = (dlong) (rate * distance); + newCost += vxThis->vx_cost; + + if(newCost < vxBelow->vx_cost) + { + vxBelow->vx_cost = newCost; + HeapAddDLong(adjHeap, newCost, (char *) vxBelow); + } + } + noBelow:; + } + + /* process adjacent vertex to LEFT */ + { + Vertex *vxLeft; + int xLeft; + + /* Check for no edge to Left */ + if(TOP(tLoc)!=loc.p_y) + goto noLeft; + + if(LEFT(tAbove) >= LEFT(tLoc)) + { + /* LowerLeft of tAbove */ + vxLeft = &(((TileCosts *)(tAbove->ti_client))->tc_vxLLeft); + xLeft = LEFT(tAbove); + } + else + { + /* T from Bottom */ + vxLeft = &(((TileCosts *)(tLoc->ti_client))->tc_vxULeft); + xLeft = LEFT(tLoc); + } + + /* adjust cost */ + { + int rate, distance; + dlong newCost; + + if(xLeft < MIN_FINITE_COORDINATE) goto noLeft; + + rate = MIN( + ((TileCosts *)(tLoc->ti_client))->tc_hCost, + ((TileCosts *)(tAbove->ti_client))->tc_hCost); + + if(rate == INT_MAX) goto noLeft; + + distance = loc.p_x - xLeft; + newCost = (dlong) (rate * distance); + newCost += vxThis->vx_cost; + + if(newCost < vxLeft->vx_cost) + { + vxLeft->vx_cost = newCost; + HeapAddDLong(adjHeap, newCost, (char *) vxLeft); + } + } +noLeft:; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * mzEstimatedCost -- + * + * Results: + * Estimated cost of route from point to destination. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +// changed from DoubleInt to dlong +dlong +mzEstimatedCost(point) + Point *point; +{ + Tile *t = TiSrPointNoHint(mzEstimatePlane, point); + TileCosts *tc = ((TileCosts *) t->ti_client); + Estimate *e; + dlong bestCost; + + bestCost = COST_MAX; + for (e=tc->tc_estimates; e!=NULL; e=e->e_next) + { + dlong hCost, vCost, cost; + + if (e->e_hCost == INT_MAX || e->e_vCost == INT_MAX) continue; + + hCost = (dlong)e->e_hCost * (dlong)ABS(point->p_x - e->e_x0); + vCost = (dlong)e->e_vCost * (dlong)ABS(point->p_y - e->e_y0); + + cost = hCost + vCost; + cost += e->e_cost0; + + if(cost < bestCost) + bestCost = cost; + } + + return bestCost; +} + +/* + * ---------------------------------------------------------------------------- + * + * mzDumpEstimates -- + * + * Dump info in estimate plane (for debugging). + * + * Results: + * None. + * + * Side effects: + * info written to file or via TxPrintf() + * + * ---------------------------------------------------------------------------- + */ + +void +mzDumpEstimates(area,fd) + Rect *area; + FILE *fd; +{ + int mzDumpEstFunc(); + + if(mzEstimateExists) + { + /* Visit each tile in the Estimate plane - dumping associated info */ + DBSrPaintArea(NULL, /* no hint tile */ + mzEstimatePlane, + area, + &DBAllTypeBits, + mzDumpEstFunc, + (ClientData) fd); + } + else + { + TxPrintf("No estimate plane!\n"); + TxPrintf("(Must ``:*ir deb noclean true'' and do a route first.)\n"); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzDumpEstFunc -- + * + * Filter function called via DBSrPaintArea on behalf of mzDumpEstimates() + * above, for each estimate tile in the area of interest, + * the info associated with each tile is dumped. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Dumps info associated with tile. + * + * ---------------------------------------------------------------------------- + */ + +int +mzDumpEstFunc(tile, fd) + Tile *tile; + FILE *fd; +{ + Rect r; + TileCosts *tilec = (TileCosts *) tile->ti_client; + + /* Get boundary of tile */ + TITORECT(tile, &r); + + /* dump info, to file if provided, else to screen */ + if(fd) + { + fprintf(fd,"\ntile %p\t\t (x: %d to %d, y: %d to %d)\n", + tile, r.r_xbot, r.r_xtop, r.r_ybot, r.r_ytop); + fprintf(fd,"\thcost = %d ", + tilec->tc_hCost); + fprintf(fd,"vcost = %d \n", + tilec->tc_vCost); + { + char str[100]; + Estimate *e; + + fprintf(fd,"\tEstimates:\n"); + + for(e=tilec->tc_estimates; e!=NULL; e=e->e_next) + { + fprintf(fd,"\t\t%"DLONG_PREFIX"d + ABS(x - %d)*%d + ABS(y - %d)*%d\n", + e->e_cost0,e->e_x0,e->e_hCost, + e->e_y0,e->e_vCost); + } + } + } + else + { + TxPrintf("\ntile %x\t\t (x: %d to %d, y: %d to %d)\n", + (pointertype) tile, r.r_xbot, r.r_xtop, r.r_ybot, r.r_ytop); + TxPrintf("\thcost = %d, ", + tilec->tc_hCost); + TxPrintf("vcost = %d \n", + tilec->tc_vCost); + { + char str[100]; + Estimate *e; + + TxPrintf("\tEstimates:\n"); + + for(e=tilec->tc_estimates; e!=NULL; e=e->e_next) + { + TxPrintf("\t\t%lld + ABS(x - %d)*%d + ABS(y - %d)*%d\n", + e->e_cost0,e->e_x0,e->e_hCost, + e->e_y0,e->e_vCost); + } + } + } + + /* continue search */ + return (0); +} diff --git a/mzrouter/mzHint.c b/mzrouter/mzHint.c new file mode 100644 index 00000000..13928474 --- /dev/null +++ b/mzrouter/mzHint.c @@ -0,0 +1,196 @@ +/* + * mzHint.c -- + * + * Builds global hint fence and rotate planes from hint info in mask data. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * There are two global hint planes. One is merged into + * maximal horizontal strips, and the other + * into maximal vertical strips. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzHint.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "textio/textio.h" +#include "utils/heap.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildHFR -- + * + * Traverse cells in database, building global Hint, Fence and Rotate + * planes. This serves two functions: + * 1. It flattens the hierarchy. + * 2. It creates max-vertical strip versions of hint and rotate. + * (VFencePlane not needed since fence info is translated into + * blockages in block planes) + * Results: + * None. + * + * Side effects: + * Global Hint, Fence and Rotate planes built up. + * + * ---------------------------------------------------------------------------- + */ + +void +mzBuildHFR(srcUse, area) + CellUse *srcUse; /* Search this cell and children for mask info */ + Rect *area; /* Area over which planes will be built */ +{ + int mzBuildHFRFunc(); + SearchContext scx; + + /* Clear global hint planes */ + { + /* Clear Hint Planes */ + DBClearPaintPlane(mzHHintPlane); + DBClearPaintPlane(mzVHintPlane); + + /* Clear Fence Plane + * (only one plane since this info is converted to info in blockage + * planes prior to maze routing) */ + DBClearPaintPlane(mzHFencePlane); + + /* Clear Rotate Planes */ + DBClearPaintPlane(mzHRotatePlane); + DBClearPaintPlane(mzVRotatePlane); + } + + /* set up search context */ + scx.scx_area = *area; + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = srcUse; + + /* clip search area to bounding box to avoid overflow during transfroms */ + GEOCLIP(&(scx.scx_area),&(srcUse->cu_def->cd_bbox)); + + if(mzTopHintsOnly) + /* Search the TOP LEVEL cell ONLY, processing each tile on hint plane */ + { + (void) DBNoTreeSrTiles(&scx, + &mzHintTypesMask, + mzCellExpansionMask, + mzBuildHFRFunc, + (ClientData) NULL); + } + else + /* Search the cell tree, processing each tile on hint plane + * in expanded cell. + */ + { + (void) DBTreeSrTiles(&scx, + &mzHintTypesMask, + mzCellExpansionMask, + mzBuildHFRFunc, + (ClientData) NULL); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildHFRFunc -- + * + * Called by DBTreeSrTiles for each solid tile found on hint planes. + * "Copies" tiles into global hint, fence and rotate planes. + * + * Results: + * Returns 0 always. + * + * Side effects: + * Paints into global hint, fence and rotate planes. + * + * ---------------------------------------------------------------------------- + */ + +int +mzBuildHFRFunc(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + SearchContext *scx = cxp->tc_scx; + Rect r, rDest; + + /* Transform to result coordinates */ + TITORECT(tile, &r); + GEOCLIP(&r, &scx->scx_area); + GEOTRANSRECT(&scx->scx_trans, &r, &rDest); + + if(TiGetType(tile)==TT_MAGNET) + { + /* Paint into global hint planes */ + DBPaintPlane(mzHHintPlane, + &rDest, + DBStdPaintTbl(TT_MAGNET, PL_M_HINT), + (PaintUndoInfo *) NULL); + DBPaintPlaneVert(mzVHintPlane, + &rDest, + DBStdPaintTbl(TT_MAGNET, PL_M_HINT), + (PaintUndoInfo *) NULL); + } + else if(TiGetType(tile)==TT_FENCE) + { + /* Paint into global fence plane + * (no vert plane required for fence, since fence + * translated to blocks in blockage planes) + */ + DBPaintPlane(mzHFencePlane, + &rDest, + DBStdPaintTbl(TT_FENCE, PL_F_HINT), + (PaintUndoInfo *) NULL); + } + else + { + ASSERT(TiGetType(tile)==TT_ROTATE,"mzBuildHFRFunc"); + + /* Paint into global rotate planes */ + DBPaintPlane(mzHRotatePlane, + &rDest, + DBStdPaintTbl(TT_ROTATE, PL_R_HINT), + (PaintUndoInfo *) NULL); + DBPaintPlaneVert(mzVRotatePlane, + &rDest, + DBStdPaintTbl(TT_ROTATE, PL_R_HINT), + (PaintUndoInfo *) NULL); + } + + /* return 0 - to continue search */ + return(0); +} diff --git a/mzrouter/mzInit.c b/mzrouter/mzInit.c new file mode 100644 index 00000000..2c7489f8 --- /dev/null +++ b/mzrouter/mzInit.c @@ -0,0 +1,371 @@ +/* + * mzInit.c -- + * + * Initialization code for maze router module. + * Called after technology file readin. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzInit.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" +#include "select/select.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "debug/debug.h" +#include "utils/undo.h" +#include "textio/txcommands.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "utils/heap.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + + +/*---- Static Data (local to this file) ----*/ + +/* Dummy cells used to display global hint planes */ +CellDef *mzHHintDef = (CellDef *) NULL; +CellUse *mzHHintUse = (CellUse *) NULL; +CellDef *mzVHintDef = (CellDef *) NULL; +CellUse *mzVHintUse = (CellUse *) NULL; + +/* Dummy cells used to display global fence planes */ +CellDef *mzHFenceDef = (CellDef *) NULL; +CellUse *mzHFenceUse = (CellUse *) NULL; + +/* Dummy cells used to display global rotate planes */ +CellDef *mzHRotateDef = (CellDef *) NULL; +CellUse *mzHRotateUse = (CellUse *) NULL; +CellDef *mzVRotateDef = (CellDef *) NULL; +CellUse *mzVRotateUse = (CellUse *) NULL; + +/* Dummy cells used to display global bounds planes */ +CellDef *mzHBoundsDef = (CellDef *) NULL; +CellUse *mzHBoundsUse = (CellUse *) NULL; +CellDef *mzVBoundsDef = (CellDef *) NULL; +CellUse *mzVBoundsUse = (CellUse *) NULL; + +/* Dummy cell used to display blockage plane */ +CellDef *mzBlockDef = (CellDef *) NULL; +CellUse *mzBlockUse = (CellUse *) NULL; + +/* Dummy cell used to display estimate plane */ +CellDef *mzEstimateDef = (CellDef *) NULL; +CellUse *mzEstimateUse = (CellUse *) NULL; + +/* Forward declarations */ +extern void mzBuildPlanes(); + + +/* + * ---------------------------------------------------------------------------- + * + * MZInit -- + * + * This procedure is called when Magic starts up, after + * technology initialization. + * + * Results: + * None. + * + * Side effects: + * Register ourselves with debug module + * Setup datastructures. + * + * ---------------------------------------------------------------------------- + */ + +void +MZInit() +{ + int n; + + /* Debug structure */ + static struct + { + char *di_name; + int *di_id; + } dflags[] = { + "steppath", &mzDebStep, + "maze", &mzDebMaze, + 0 + }; + + /* Register with debug module */ + mzDebugID = DebugAddClient("mzrouter", sizeof dflags/sizeof dflags[0]); + for (n = 0; dflags[n].di_name; n++) + *(dflags[n].di_id) = DebugAddFlag(mzDebugID, dflags[n].di_name); + + /* Finalize parameters */ + MZAfterTech(); + + /* Setup internal tile planes and associated paint tables, cells for + * display during debugging, etc. + */ + mzBuildPlanes(); + + /* Initialize destination alignment structures */ + mzNLInit(&mzXAlignNL, INITIAL_ALIGN_SIZE); + mzNLInit(&mzYAlignNL, INITIAL_ALIGN_SIZE); + + /* Setup result cell */ + DBNewYank("__mz_result", &mzResultUse, &mzResultDef); +} + +/* + * ---------------------------------------------------------------------------- + * + * MZAttachHintPlanes -- + * + * Reattaches the global pointers to the various hint planes. Should be + * called anytime the plane structures are altered (on initialization, and + * in response to DBScaleEverything()) + * + * Results: + * None. + * + * Side Effects: + * Global pointers modified. + * ---------------------------------------------------------------------------- + */ + +void +MZAttachHintPlanes() +{ + mzHHintPlane = mzHHintDef->cd_planes[PL_M_HINT]; + mzVHintPlane = mzVHintDef->cd_planes[PL_M_HINT]; + + mzHFencePlane = mzHFenceDef->cd_planes[PL_F_HINT]; + mzEstimatePlane = mzEstimateDef->cd_planes[PL_M_HINT]; + + mzHRotatePlane = mzHRotateDef->cd_planes[PL_R_HINT]; + mzVRotatePlane = mzVRotateDef->cd_planes[PL_R_HINT]; + + mzHBoundsPlane = mzHBoundsDef->cd_planes[PL_M_HINT]; + mzVBoundsPlane = mzVBoundsDef->cd_planes[PL_M_HINT]; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzBuildPlanes -- + * + * Setup internal type masks, paint tables, planes, and cells for debugging. + * + * Results: + * None. + * + * Side effects: + * Internal cells allocated. + * + * ---------------------------------------------------------------------------- + */ + +void +mzBuildPlanes() +{ + /* --------- Setup mask of all hint types --------------- */ + + /* mzHintTypesMask */ + TTMaskZero(&mzHintTypesMask); + TTMaskSetType(&mzHintTypesMask,TT_MAGNET); + TTMaskSetType(&mzHintTypesMask,TT_FENCE); + TTMaskSetType(&mzHintTypesMask,TT_ROTATE); + + /* --------- Blockage planes ----------------------------------------- */ + /* (Blockage planes indicate where the router is allowed to route on + * each route-type. 0-width routes are made and then flushed out + * to design rule correct paths after routing completes). There are + * two blockage planes for each routing layer or and routing + * contact - one organized into maximal vertical strips, and one into + * horizontal strips). + */ + + /* Setup paint table for blockage planes */ + { + int r,s; + + /* Indices are "paint", "have". The entry value designates "result" */ + + /* Blockage painting is governed by strict priority order: + * you always get the higher numbered type, + * EXCEPT that painting space always gives space. + */ + for (r = 0; r < TT_MAXROUTETYPES; r++) + { + for (s = 0; s < TT_MAXROUTETYPES; s++) + { + if(r == TT_SPACE) + { + mzBlockPaintTbl[r][s] = TT_SPACE; + } + else + { + mzBlockPaintTbl[r][s] = MAX(r,s); + } + } + } + } + + /* Create dummy cell for displaying blockage planes + * (see *mzroute showblock command in mzTest.c) + */ + DBNewYank("__BLOCK", &mzBlockUse,&mzBlockDef); + DBFreePaintPlane(mzBlockDef->cd_planes[PL_M_HINT]); + TiFreePlane(mzBlockDef->cd_planes[PL_M_HINT]); + mzBlockDef->cd_planes[PL_M_HINT] = NULL; + + /* -- Setup mask of valid tile types on which to start a route path -- */ + /* mzStartTypesMask */ + TTMaskZero(&mzStartTypesMask); + TTMaskSetType(&mzStartTypesMask,TT_SAMENODE); + TTMaskSetType(&mzStartTypesMask,TT_ABOVE_UD_WALK); + TTMaskSetType(&mzStartTypesMask,TT_BELOW_UD_WALK); + TTMaskSetType(&mzStartTypesMask,TT_ABOVE_LR_WALK); + TTMaskSetType(&mzStartTypesMask,TT_BELOW_LR_WALK); + TTMaskSetType(&mzStartTypesMask,TT_LEFT_WALK); + TTMaskSetType(&mzStartTypesMask,TT_RIGHT_WALK); + TTMaskSetType(&mzStartTypesMask,TT_TOP_WALK); + TTMaskSetType(&mzStartTypesMask,TT_BOTTOM_WALK); + TTMaskSetType(&mzStartTypesMask,TT_DEST_AREA); + + /*------------- Bounds Planes --------------------------------------- */ + /* (Blockage planes are generated incrementally. The two global bounds + * planes record the areas for which blockage planes have already been + * generated.) */ + + /* Setup paint table for bounds planes */ + { + int r,s; + + /* Indices are "paint", "have". The entry value designates "result" */ + + /* (Want TT_INBLOCK to persist when TT_GENBLOCK painted on top, + * so that + * after painting TT_GENBLOCK over region to be expanded TT_GENBLOCK + * tiles give subregions that haven't already been expanded. + */ + + /* Default is to get what you paint */ + for (r = 0; r < TT_MAXROUTETYPES; r++) + for (s = 0; s < TT_MAXROUTETYPES; s++) + mzBoundsPaintTbl[r][s] = r; + + /* Nothing changes TT_INBOUNDS except TT_SPACE */ + for (r = 0; r < TT_MAXROUTETYPES; r++) + if (r != TT_SPACE) + mzBoundsPaintTbl[r][TT_INBOUNDS] = TT_INBOUNDS; + } + + /* Create global bounds planes - + * and attach to dummy cells for display during debugging */ + + DBNewYank("__HBOUNDS", &mzHBoundsUse,&mzHBoundsDef); + DBNewYank("__VBOUNDS", &mzVBoundsUse,&mzVBoundsDef); + + /*------------- Dest Area Internal Cell ------------------------------ */ + /* (Destination area'a are painted here to make sure there is always + * something for the router to connect to. This cell is used along + * with mzRouteUse to generate blockage planes.) + */ + + DBNewYank("__DESTAREAS", &mzDestAreasUse,&mzDestAreasDef); + + /* ------------ Estimate Plane ------------------------------------- */ + /* (The global estimation plane provides info. for estimating cost to + * completion for partial paths, that factor in large blocks such as + * fences and subcells.) + */ + + /* Setup paint table for estimate plane */ + { + int r,s; + + /* Indices are "paint", "have". The entry value designates "result" */ + + /* Estimate painting is governed by priority order: + * you always get the higher numbered type, + * EXCEPT that painting space always gives space + */ + for (r = 0; r < TT_MAXROUTETYPES; r++) + { + for (s = 0; s < TT_MAXROUTETYPES; s++) + { + if(r == TT_SPACE) + { + mzEstimatePaintTbl[r][s] = TT_SPACE; + } + else + { + mzEstimatePaintTbl[r][s] = MAX(r,s); + } + } + } + } + + /* Create global estimate plane + * and attach to dummy cells for display during debugging */ + + DBNewYank("__ESTIMATE", &mzEstimateUse,&mzEstimateDef); + + /* ----------- Hint Planes ---------------------------------------- */ + /* (Global hint planes store all hints visible to router - unencumbered + * by cell structure and fence and rotate regions.) + */ + + /* Create global hint planes - + * and attach to dummy cells for display during debugging */ + + DBNewYank("__HHINT", &mzHHintUse,&mzHHintDef); + DBNewYank("__VHINT", &mzVHintUse,&mzVHintDef); + + /* --------------- Fence Plane ---------------------------------- + * (Global fence plane gives location of all fences visible to router - + * unencumbered by cell structure and hint and rotate regions.)*/ + + /* Create global fence plane + * and attach to dummy cells for display during debugging */ + + DBNewYank("__HFENCE", &mzHFenceUse,&mzHFenceDef); + + /* --------------- Rotate Planes ------------------------------- + * (Global rotate plane gives location of all rotate regions visible + * to router - + * unencumbered by cell structure and hint and rotate regions.) */ + + /* Create global rotate planes + * and attach to dummy cells for display during debugging */ + + DBNewYank("__HROTATE", &mzHRotateUse,&mzHRotateDef); + DBNewYank("__VROTATE", &mzVRotateUse,&mzVRotateDef); + + MZAttachHintPlanes(); + + return; +} diff --git a/mzrouter/mzInternal.h b/mzrouter/mzInternal.h new file mode 100644 index 00000000..b1578410 --- /dev/null +++ b/mzrouter/mzInternal.h @@ -0,0 +1,482 @@ +/* + * mzInternal.h -- + * + * This file defines data structures, variables, and constants internal to + * the maze router module. + * + * + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid $Header: /usr/cvsroot/magic-8.0/mzrouter/mzInternal.h,v 1.2 2008/06/01 18:37:44 tim Exp $ + */ + +#ifndef _MZINTERNAL_H +#define _MZINTERNAL_H + +/* + * Structures etc. that are exported by the mzrouter are defined in + * mzrouter.h. + * + * Structures (etc.) defined here are shared between files in this module. + * + * Structures local to a given source + * file are defined at the top of that source file. + * + * Structures specific to a given function are defined at + * the head of that function. + */ + +#ifndef _MZROUTER_H +#include "mzrouter/mzrouter.h" +#endif + +#ifndef _HEAP_H +#include "utils/heap.h" +#endif + +/* ------------------------ Version String --------------------------- */ +#define MZROUTER_VERSION "0.6" + +/* ------------------------ Debugging flags ----------------------------- */ +extern ClientData mzDebugID; +#include "mzDebug.h" + +/* ---------- Default Parameter Values ----------------------------------- */ + +/* Penalty factor applied to cost estimate in excess of max window bound + * represented as mantissa / 2**nExponent + */ +/* (2048/2**1 = 1028) */ +#define DEF_PENALTY_MANTISSA 2048 +#define DEF_PENALTY_NEXPONENT 1 + +/* Window rate in cost/bloom */ +#define DEF_WINDOW_RATE 500 + +/* Window width in cost */ +#define DEF_WINDOW_WIDTH 10000 + +/* Maximum cost increase allowed during blooming */ +#define DEF_BLOOM_DELTA_COST 1 + +/* minimum radius of blockage plane info required around point being expanded. + * value of -1 causes mzrouter to compute its own best guess. + * (Areas twice this size are gened. whenever the minimum is not met.) + */ +#define DEF_BOUNDS_INCREMENT -1 + +/* If reset, degenerate estimation plane used (just 4 tiles - one for each + * quadrant with respect to destination point). + */ +#define DEF_ESTIMATE 1 +/* If set, routes may start or terminate at any geometry that is + * electrically connected to specified start or dest regions. + */ +#define DEF_EXPAND_ENDPOINTS 1 +#define MZ_EXPAND_START 1 /* ClientData type for start tiles */ +#define MZ_EXPAND_DEST 0 /* ClientData type for dest tiles */ +#define MZ_EXPAND_NONE CLIENTDEFAULT /* Normal ClientData type */ + +/* If set only hints in toplevel cell are recognized - speeds up processing + * of hint planes when there are lots of expanded subcells. + */ +#define DEF_TOP_HINTS_ONLY 0 +/* Maximum distance route can penetrate blocked areas to reach destination. + * Note only "same node" blockage will be penetrated, i.e. blocks steming from + * spacing to unrelated nodes are always honored. + * + * A value of -1 causes the max penetration to be recomputed prior to each + * route based on the design rules for the active routetypes. + */ +#define DEF_MAX_WALK_LENGTH -1 +/* controls message printing: 0 = errors and warnings only, 1 = brief, 2 = + * lots of statistics. + */ +#define DEF_VERBOSITY 1 +/* if positive, puts upper limit on number of blooms during search. + * After limit is reached routing is terminated and best complete route + * to date is returned. + */ +#define DEF_BLOOM_LIMIT 0 + +/* This struc used to make list of named parameter sets for maze routing. + * Only the MazeParameters themselves are passed to the routines + * in this module. + */ +typedef struct mazestyle +{ + char *ms_name; /* name of style */ + List *ms_spacingL; /* used to store spacing during tech readin. */ + MazeParameters ms_parms; /* parameter settings for this style */ + struct mazestyle *ms_next; +} MazeStyle; + + +/* ----- TileTypes, Paint Tables, and Paint Planes, and Internal Cells ---- */ +/* RESULT CELL */ +extern CellDef *mzResultDef; +extern CellUse *mzResultUse; + +/* Types are offset to coincide with hint types. + * This facilitates display for debugging. + */ +#define TT_OFF (TT_MAGNET - 1) + +/* BLOCKAGE PLANES - AND CELL FOR DISPLAY */ +/* Higher numbered blockage types ALWAYS take priority during painting */ + + /* Start or destination terminal */ +#define TT_SAMENODE (1 + TT_OFF) + /* Block due to start or destination terminal */ +#define TT_SAMENODE_BLOCK (2 + TT_OFF) + /* Can reach dest via contact */ +#define TT_ABOVE_UD_WALK (3 + TT_OFF) +#define TT_BELOW_UD_WALK (4 + TT_OFF) +#define TT_ABOVE_LR_WALK (5 + TT_OFF) +#define TT_BELOW_LR_WALK (6 + TT_OFF) + /* Approach to dest area */ +#define TT_LEFT_WALK (7 + TT_OFF) +#define TT_RIGHT_WALK (8 + TT_OFF) +#define TT_TOP_WALK (9 + TT_OFF) +#define TT_BOTTOM_WALK (10 + TT_OFF) + /* route destination area */ +#define TT_DEST_AREA (11 + TT_OFF) + /* Can't route in this space */ +#define TT_BLOCKED (12 + TT_OFF) + +#define TT_MAXROUTETYPES (1 + TT_BLOCKED) + +extern PaintResultType mzBlockPaintTbl[TT_MAXROUTETYPES][TT_MAXROUTETYPES]; +extern CellDef *mzBlockDef ; + +/* BOUNDS PLANE */ + /* Blockage planes generated here */ +#define TT_INBOUNDS (1 + TT_OFF) +#define TT_GENBLOCK (2 + TT_OFF) +extern PaintResultType mzBoundsPaintTbl[TT_MAXROUTETYPES][TT_MAXROUTETYPES]; +extern Plane *mzHBoundsPlane; +extern Plane *mzVBoundsPlane; + +/* ESTIMATION PLANE */ +#define TT_EST_SUBCELL (1 + TT_OFF) +#define TT_EST_FENCE (2 + TT_OFF) +#define TT_EST_DEST (3 + TT_OFF) +extern PaintResultType mzEstimatePaintTbl[TT_MAXROUTETYPES][TT_MAXROUTETYPES]; +extern Plane *mzEstimatePlane; + +/* HINT TYPES */ +extern TileTypeBitMask mzHintTypesMask; /* map of hint, fence + and rotate types */ +extern TileTypeBitMask mzStartTypesMask; /* mask of valid types for a route start */ + +/* HINT (magnet) PLANES */ +extern Plane *mzHHintPlane; +extern Plane *mzVHintPlane; + +/* FENCE PLANE */ +extern Plane *mzHFencePlane; + +/* ROTATE PLANES */ +extern Plane *mzHRotatePlane; +extern Plane *mzVRotatePlane; + +/* Number Lines - used to mark points aligned with dest tile corners */ +typedef struct numberLine +{ + int nl_sizeAlloced; /* Number of entries allocated */ + int nl_sizeUsed; + int *nl_entries; +} NumberLine; + +/* + * Macros for allocating segments of a RoutePath. + * During maze-routing, we allocate RoutePaths from our own private area. + * When the time comes to return a RoutePath, it is copied to permanent + * storage (i.e., mallocMagic/freeMagic-managed) and the rest of the + * temporary storage is reclaimed. This approach avoids the need for + * additional pointers in each RoutePath that would otherwise be required + * for storage reclamation. + */ +#define PATHSPERSEG 200 /* Number of RoutePaths per segment */ + +typedef struct routePage +{ + struct routePage *rpp_next; + int rpp_free; + RoutePath rpp_array[PATHSPERSEG]; +} RoutePage; + +/* First, last, and current RoutePages on list for allocating RoutePaths */ +extern RoutePage *mzFirstPage; +extern RoutePage *mzLastPage; +extern RoutePage *mzCurPage; + +/* Allocate a new RoutePath */ +#define NEWPATH() \ + ((mzCurPage == NULL \ + || mzCurPage->rpp_free >= PATHSPERSEG) \ + ? mzAllocRPath() \ + : (RoutePath *) (&mzCurPage->rpp_array[mzCurPage->rpp_free++])) + +/*------------------- Start and Dest Terminals ---------------------------- */ +/* A start or destination terminal is a rectangle and a type to connect + * on. This struct is used to create lists of legal start and destination + * areas. (This structure also used in other situations requiring rects + * with an associated tiletype.) + */ +typedef struct +{ + Rect cr_rect; + TileType cr_type; +} ColoredRect; + +/*----------------------Path Hash Table and Queues ----------------------- */ + +/* + * The following hash table is used to index points + * so that redundant extension from points reached more than once + * is avoided. + * It is indexed by (x,y,routeLayer, orientation). Orientation is either + * Horizontal, vertical, or original (point on layer). Horizontal and + * vertical entries to the point are both extended from since they + * may vary in number of jogs and hence cost. + */ +typedef struct +{ + Point pk_point; /* (x, y) */ + RouteLayer *pk_rLayer; /* "z" - Layer we are on */ + int pk_orient; /* Because of jogCost, we must distinguish + * between endpts of horizontal and vertical + * segments. + */ +#if SIZEOF_VOID_P == 8 + unsigned pk_buffer; /* Structure size will be to word boundary! + * make sure we don't pass an uninitialized + * byte block to the hash function! + */ +#endif +} PointKey; + +extern HashTable mzPointHash; +#define INITHASHSIZE 64 + +/* Queues for partial paths */ +extern Heap mzMaxToGoHeap; /* paths nearer destination than WINDOW */ +extern Heap mzMinCostHeap; /* paths in WINDOW */ +extern Heap mzMinAdjCostHeap; /* paths farther from dest than WINDOW*/ +extern List *mzBloomStack; /* paths in current local focus */ +extern List *mzStraightStack; /* focus paths being extended in straightline*/ +extern List *mzDownHillStack; /* focus paths followed only until cost + increases */ +extern List *mzWalkStack; /* paths inside walk (i.e. inside blocked + * area adjacent to destination. + */ +extern Heap mzMinCostCompleteHeap; /* completed paths */ +#define INITHEAPSIZE 64 + +/* ------------------------ Routines Global to MazeRouter --------------- */ +extern RoutePath *mzAllocRPath(); +extern char *mzCost2String(); +extern char *mzDICost2String(); +extern RouteType *mzFindRouteType(); +extern void mzNLClear(); +extern int *mzNLGetContainingInterval(); +extern void mzNLInit(); +extern void mzNLInsert(); +extern void mzTechFinal(); +extern int mzPaintContact(); +extern TileTypeBitMask mzTouchingTypes(); + +extern void mzAddPoint(RoutePath *, Point *, RouteLayer *, int, int, dlong *); +extern void mzWalkRight(RoutePath *); +extern void mzWalkLeft(RoutePath *); +extern void mzWalkUp(RoutePath *); +extern void mzWalkDown(RoutePath *); +extern void mzWalkContact(RoutePath *); +extern dlong mzEstimatedCost(Point *); +extern RoutePath *mzSearch(); + + +/* --------------------- Variables Global to MazeRouter ----------------- */ + +/* Use a maximum cost which we can add to without overflowing */ +#define COST_MAX (DLONG_MAX >> 2) + +/* Parameter sets for mzrouting - from tech file. */ +extern MazeStyle *mzStyles; + +/* Source of path currently being extended */ +extern int mzPathSource; +#define SOURCE_INIT 0 +#define SOURCE_BLOOM 1 +#define SOURCE_STRAIGHT 2 +#define SOURCE_DOWNHILL 3 +#define SOURCE_WALK 4 + +/* Paint generated by router */ +extern CellDef *mzResultDef; +extern CellUse *mzResultUse; + +/* Cell to do routing in */ +extern CellUse *mzRouteUse; + +/* Mask giving expanded subcells */ +extern int mzCellExpansionMask; + +/* Don't route outside of this area */ +extern Rect mzBoundingRect; + +/* List of Route starting terminals */ +extern List *mzStartTerms; + +/* Cell containing dest areas */ +extern CellDef *mzDestAreasDef; +extern CellUse *mzDestAreasUse; + +/* dest terminal alignment coordinates */ +extern NumberLine mzXAlignNL; +extern NumberLine mzYAlignNL; +/* initial size of above number lines */ +#define INITIAL_ALIGN_SIZE 100 + +/* Fence parity */ +extern bool mzInsideFence; + +/* largest design rule distance - used during incremental blockage gen. */ +extern int mzContextRadius; + +/* Route types */ +extern RouteLayer *mzRouteLayers; +extern RouteLayer *mzActiveRLs; +extern RouteContact *mzRouteContacts; +extern RouteType *mzRouteTypes; +extern RouteType *mzActiveRTs; + +/* minimum radius of blockage plane info required around point being expanded. + * (Areas twice this size are gened. whenever the minimum is not met.) + */ +extern int mzBoundsIncrement; + +/* If reset, degenerate estimation plane used (just 4 tiles - one for each + * quadrant with respect to destination point). + */ +extern int mzEstimate; +/* If set, routes may terminate at any geometry that is + * electrically connected to specified dest areas (default TRUE) + */ +extern int mzExpandDests; +/* If set, routes may start at any geometry that is + * electrically connected to specified start areas (default TRUE) + */ +extern int mzExpandStarts; +/* If set, only hints in toplevel cell are recognized */ +extern int mzTopHintsOnly; +/* Maximum distance route will extend into blocked area to connect to dest. */ +extern int mzMaxWalkLength; +/* limits area of route for performance, + * NOTE: IF NONNULL, USER MUST MAKE SURE ROUTE IS ACTUALLY LIMITED TO THIS + * AREA WITH FENCES, OTHERWISE THE RESULT IS UNPREDICTABLE. + */ +extern Rect *mzBoundsHint; + +/* how generous to be with messages */ +extern int mzVerbosity; +/* if positive, limit on number of blooms */ +extern int mzBloomLimit; + +/* minimum estimated total cost for initial paths */ +extern dlong mzMinInitialCost; + +/* Parameters controlling search */ +extern RouteFloat mzPenalty; +extern dlong mzWRate; +extern dlong mzBloomDeltaCost; +extern dlong mzWWidth; + +/* Statistics */ +extern dlong mzInitialEstimate; /* Initial estimated cost of route */ +extern int mzNumBlooms; +extern int mzNumOutsideBlooms; /* num blooms from outside window */ +extern int mzNumComplete; /* number of complete paths so far */ +extern int mzBlockGenCalls; /* # of calls to blockage gen. code */ +extern double mzBlockGenArea; /* area over which blockage planes + * have been gened. */ +extern int mzNumPathsGened; /* number of partial paths added to heap */ +extern int mzNumPaths; /* number of paths processed */ +extern int mzReportInterval; /* frequency that # of paths etc. + * is reported. */ +extern int mzPathsTilReport; /* counts down to next path report */ + +/* Variables controlling search */ +extern dlong mzWInitialMinToGo; +extern dlong mzWInitialMaxToGo; +extern dlong mzBloomMaxCost; + +/* Search status */ +extern dlong mzWindowMinToGo; /* Window location */ +extern dlong mzWindowMaxToGo; + +/* Marked cell list */ +extern List *mzMarkedCellsList; + +/* ------------ Interesting Point Macros -------------------------------- */ +/* The following macros are used in the low-level routines for finding + * the NEXT interesting point to the Right, Left, Up and Down. + * + * The macros are used to choose the first among 2 interesting points. + */ +#define PRUNE_TO_MIN(a,new,reasonSet,reason) \ + if (1) \ + { \ + if((new)<(a)) \ + { \ + (a) = (new); \ + (reasonSet) = (reason); \ + } \ + else if ((new)==(a)) \ + { \ + (reasonSet) |= (reason); \ + } \ + } else + +#define PRUNE_TO_MAX(a,new,reasonSet,reason) \ + if (1) \ + { \ + if((new)>(a)) \ + { \ + (a) = (new); \ + (reasonSet) = (reason); \ + } \ + else if ((new)==(a)) \ + { \ + (reasonSet) |= (reason); \ + } \ + } else + +#define RC_JOG 1 +#define RC_ALIGNOTHER 2 +#define RC_CONTACT 4 +#define RC_ALIGNGOAL 8 +#define RC_HINT 16 +#define RC_ROTBEFORE 32 +#define RC_ROTINSIDE 64 +#define RC_BOUNDS 128 +#define RC_WALK 256 +#define RC_WALKUDC 512 +#define RC_WALKLRC 1024 +#define RC_DONE 2048 + +#endif /* _MZINTERNAL_H */ diff --git a/mzrouter/mzMain.c b/mzrouter/mzMain.c new file mode 100644 index 00000000..0bdcd766 --- /dev/null +++ b/mzrouter/mzMain.c @@ -0,0 +1,1318 @@ +/* + * mzMain.c -- + * + * Global Data Definitions and interface procedures for the Maze Router. + * + * OTHER ENTRY POINTS (not in this file): + * Technology readin - mzTech.c + * Initialization (after tech readin) - mzInit.c + * Test command interface - TestCmd.c + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzMain.c,v 1.3 2010/06/24 12:37:19 tim Exp $"; +#endif /* not lint */ + +/*--- includes --- */ +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" +#include "select/select.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "debug/debug.h" +#include "utils/undo.h" +#include "textio/txcommands.h" +#include "utils/malloc.h" +#include "utils/main.h" +#include "utils/geofast.h" +#include "../utils/list.h" +#include "utils/heap.h" +#include "utils/touchingtypes.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + +/*---- Global Data Definitions ----*/ +/* (Actual storage for static global structures for maze router defined here)*/ + +/* Debug flags */ +ClientData mzDebugID; +int mzDebMaze; /* identify flags to debug module */ +int mzDebStep; + +/* parameter sets - from tech file */ +MazeStyle *mzStyles = NULL; + +/* Toplevel cell visible to the router */ +CellUse *mzRouteUse; + +/* Route types */ +/* (Specifies what types are permitted during routing, and related design + * rules.) + */ +RouteType *mzRouteTypes; +RouteType *mzActiveRTs; /* Only route types that are turned on */ +RouteLayer *mzRouteLayers; +RouteLayer *mzActiveRLs; /* Only route layers that are turned on */ +RouteContact *mzRouteContacts; + +/* Routing is confined to this rectangle */ +Rect mzBoundingRect; + +/* Expansion mask - defines which subcells to treat as expanded */ +int mzCellExpansionMask; + +/* If reset, degenerate estimation plane used (just 4 tiles - one for each + * quadrant with respect to destination point). + */ +int mzEstimate; + +/* If set dest areas are expanded to include all electrically + * connected geometry. + */ +int mzExpandEndpoints; +/* If set only hints in toplevel cell are recognized */ +int mzTopHintsOnly; + +/* Maximum distance route will extend into blocked area to connect to dest. + * terminal. If set to -1, a max value is computed as a function of the + * design rules for the active route types prior to each route. + */ +int mzMaxWalkLength; + +/* if nonnull, limits area of search for performance. + * (NOTE: USER MUST LIMIT ROUTE TO THIS AREA WITH FENCES - OTHERWISE + * RESULT IS UNPREDICTABLE). + */ +Rect *mzBoundsHint; + +/* how many messages to print */ +int mzVerbosity; +/* if positive, upper bound on number of blooms */ +int mzBloomLimit; + +/* maskdata unexpanded subcells, marked because they are part of + * dest. nodes. */ +List *mzMarkedCellsList; + +/* start terminals */ +List *mzStartTerms; + +/* internal cell for dest areas */ +CellDef *mzDestAreasDef = (CellDef *) NULL; +CellUse *mzDestAreasUse = (CellUse *) NULL; + +/* Fence parity */ +bool mzInsideFence; + +/* largest design rule distance - used during incremental blockage gen. */ +int mzContextRadius; + +/* Internal cell for completed route */ +CellDef *mzResultDef = (CellDef *) NULL; +CellUse *mzResultUse = (CellUse *) NULL; + +/* HINT PLANES */ +TileTypeBitMask mzHintTypesMask; +Plane *mzHHintPlane; +Plane *mzVHintPlane; + +/* FENCE PLANE */ +TileTypeBitMask mzFenceTypesMask; +Plane *mzHFencePlane; + +/* ROTATE PLANES */ +TileTypeBitMask mzRotateTypesMask; +Plane *mzHRotatePlane; +Plane *mzVRotatePlane; + +/* BOUNDS PLANES */ +PaintResultType mzBoundsPaintTbl[TT_MAXROUTETYPES][TT_MAXROUTETYPES]; +Plane *mzHBoundsPlane; +Plane *mzVBoundsPlane; + +/* BLOCKAGE PLANES */ +TileTypeBitMask mzStartTypesMask; +PaintResultType mzBlockPaintTbl[TT_MAXROUTETYPES][TT_MAXROUTETYPES]; + +/* ESTIMATE PLANE */ +PaintResultType mzEstimatePaintTbl[TT_MAXROUTETYPES][TT_MAXROUTETYPES]; +Plane *mzEstimatePlane; + +/* dest terminal alignment coordinates */ +NumberLine mzXAlignNL; +NumberLine mzYAlignNL; + +/* minimum radius of blockage plane info required around point being expanded. + * (Areas twice this size are gened. whenever the minimum is not met.) + */ +int mzBoundsIncrement; + +/* minimum estimated total cost for initial path */ +dlong mzMinInitialCost; + +/* where current path came from */ +int mzPathSource; + +/* Parameters controlling search */ +RouteFloat mzPenalty; +dlong mzWRate; +dlong mzBloomDeltaCost; +dlong mzWWidth; + +/* Statistics */ +dlong mzInitialEstimate; /* Initial estimated cost of route */ +int mzNumBlooms; +int mzNumOutsideBlooms; /* num blooms from outside window */ +int mzNumComplete; /* number of complete paths so far */ +int mzBlockGenCalls; /* # of calls to blockage gen. code */ +double mzBlockGenArea; /* area over which blockage planes + have been gened. */ +int mzNumPathsGened; /* number of partial paths added to heap */ +int mzNumPaths; /* number of paths processed */ +int mzReportInterval; /* frequency that # of paths etc. + * is reported. */ +int mzPathsTilReport; /* counts down to next path report */ + +/* Variables controlling search */ +dlong mzWInitialMinToGo; +dlong mzWInitialMaxToGo; +dlong mzBloomMaxCost; + +/* Search status */ +dlong mzWindowMinToGo; /* Window location */ +dlong mzWindowMaxToGo; + +/* Hash table to avoid repeated expansion from same point during search */ +HashTable mzPointHash; + +/* Queues for partial paths */ +Heap mzMaxToGoHeap; /* paths nearer destination than WINDOW */ +Heap mzMinCostHeap; /* paths in WINDOW */ +Heap mzMinAdjCostHeap; /* paths farther from dest than WINDOW*/ +List *mzBloomStack; /* paths in current local focus */ +List *mzStraightStack; /* focus paths expanded in a straight line */ +List *mzDownHillStack; /* focus paths expanded as long as + * estimated total cost doesn't increase. + */ +List *mzWalkStack; /* paths in walks, i.e. blocks adjacent + * to dest areas. + */ +Heap mzMinCostCompleteHeap; /* completed paths */ + +/*----------- static data - referenced only in this file ------------------- */ + +/* set when storage that needs to be reclaimed has been allocated by router */ +bool mzDirty = FALSE; + +/* set when path queues and hast table have been allocated */ +bool mzPathsDirty = FALSE; + +/* macro for adding address pairs to translation table */ +#define ADDR_TBL_EQUIV(a1,a2) \ +if(TRUE) \ +{ \ + HashSetValue(HashFind(&aT, (char *) (a1)), (char *) (a2)); \ + HashSetValue(HashFind(&aT, (char *) (a2)), (char *) (a1)); \ +} else + +/* macro for translating address to address paired with it in address table */ +#define ADDR_TBL(type,a) \ +if (TRUE) \ +{ \ + HashEntry *he = HashLookOnly(&aT, (char *) (a)); \ + if(he) \ + { \ + a = (type) HashGetValue(he); \ + } \ +} else + + +/* + * ---------------------------------------------------------------------------- + * + * MZCopyParms -- + * + * Allocate and setup duplicate maze parameters with same values. + * (Duplicates substructures as well) + * + * Results: + * Pointer to new parameters. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +MazeParameters * +MZCopyParms(oldParms) + MazeParameters *oldParms; /* Maze routing parameters */ +{ + MazeParameters *newParms; + HashTable aT; /* Address translation hash table */ + + /* If passed NULL parms, just return NULL */ + if(oldParms==NULL) + { + return NULL; + } + + /* Initialize address translation table */ + HashInit(&aT, 1000, HT_WORDKEYS); + + /* allocate new structure and copy MazeParameters */ + { + newParms = (MazeParameters *) mallocMagic((unsigned)(sizeof(MazeParameters))); + *newParms = *oldParms; + } + + /* Copy RouteLayers (and sub-structures) */ + { + RouteLayer *rLOld; + + for(rLOld = oldParms->mp_rLayers; + rLOld != NULL; + rLOld = rLOld->rl_next) + { + RouteLayer *rLNew; + + /* allocate and equivalence new rL and its rT */ + { + rLNew = (RouteLayer *) mallocMagic((unsigned)(sizeof(RouteLayer))); + ADDR_TBL_EQUIV(rLOld, rLNew); + ADDR_TBL_EQUIV(&(rLOld->rl_routeType),&(rLNew->rl_routeType)); + } + + /* copy the rL */ + *rLNew = *rLOld; + + /* make a copy of the routeLayer contact list */ + LIST_COPY(rLOld->rl_contactL, rLNew->rl_contactL); + + /* allocate new blockage planes */ + rLNew->rl_routeType.rt_hBlock = DBNewPlane((ClientData) TT_SPACE); + rLNew->rl_routeType.rt_vBlock = DBNewPlane((ClientData) TT_SPACE); + } + } + + /* Copy RouteContacts (and sub-structures) */ + { + RouteContact *rCOld; + + for(rCOld = oldParms->mp_rContacts; + rCOld != NULL; + rCOld = rCOld->rc_next) + { + RouteContact *rCNew; + + /* allocate and equivalence new rC and its rT */ + { + rCNew = (RouteContact *) mallocMagic((unsigned)(sizeof(RouteContact))); + ADDR_TBL_EQUIV(rCOld, rCNew); + ADDR_TBL_EQUIV(&(rCOld->rc_routeType),&(rCNew->rc_routeType)); + } + + /* copy the rC */ + *rCNew = *rCOld; + + rCNew->rc_routeType.rt_hBlock = DBNewPlane((ClientData) TT_SPACE); + rCNew->rc_routeType.rt_vBlock = DBNewPlane((ClientData) TT_SPACE); + } + } + + /* Translate addresses in MazeParameters */ + ADDR_TBL(RouteLayer *, newParms->mp_rLayers); + ADDR_TBL(RouteContact *, newParms->mp_rContacts); + ADDR_TBL(RouteType *, newParms->mp_rTypes); + + /* Translate addresses in RouteLayers (and sub-structures) */ + { + RouteLayer *rLOld; + + for(rLOld = oldParms->mp_rLayers; + rLOld != NULL; + rLOld = rLOld->rl_next) + { + RouteLayer *rLNew = rLOld; + ADDR_TBL(RouteLayer *, rLNew); + + ADDR_TBL(RouteLayer *, rLNew->rl_next); + ADDR_TBL(RouteType *, rLNew->rl_routeType.rt_next); + + /* translate RouteContact addresses in contact list */ + { + List *l; + for(l = rLNew->rl_contactL; l!=NULL; l=LIST_TAIL(l)) + { + ADDR_TBL(ClientData, LIST_FIRST(l)); + } + } + + } + } + + /* Translate addresses in RouteContacts (and sub-structures) */ + { + RouteContact *rCOld; + + for(rCOld = oldParms->mp_rContacts; + rCOld != NULL; + rCOld = rCOld->rc_next) + { + RouteContact *rCNew =rCOld; + ADDR_TBL(RouteContact *, rCNew); + + ADDR_TBL(RouteLayer *, rCNew->rc_rLayer1); + ADDR_TBL(RouteLayer *, rCNew->rc_rLayer2); + ADDR_TBL(RouteContact *, rCNew->rc_next); + ADDR_TBL(RouteType *, rCNew->rc_routeType.rt_next); + } + } + + HashKill(&aT); + return newParms; +} + + +/* + * ---------------------------------------------------------------------------- + * + * MZFindStyle -- + * + * Find style of given name. + * + * Results: + * Pointer to maze parameters for given style, or NULL if not found. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +MazeParameters * +MZFindStyle(name) +char *name; /* name of style we are looking for */ +{ + MazeStyle *style = mzStyles; + + while(style!=NULL && strcmp(name,style->ms_name)!=0) + { + style = style->ms_next; + } + + if(style==NULL) + { + return NULL; + } + else + { + return &(style->ms_parms); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * MZInitRoute -- + * + * + * Set up datastructures for maze route, and initialize per/route statistics + * + * Results: + * None. + * + * Side effects: + * See above. + * + * NOTE: RouteUse supplied as parm to MZInitRoute is toplevel cell visible + * to router. However resulting route is painted to current edit cell. + * + * ---------------------------------------------------------------------------- + */ + +void +MZInitRoute(parms, routeUse, expansionMask) + MazeParameters *parms; /* Maze routing parameters */ + CellUse *routeUse; /* toplevel cell router sees */ + int expansionMask; /* which subcells are expanded - NOTE: the + * maze router interpets a 0 mask to mean + * all cells are expanded + */ +{ + /* Disable undo to avoid overhead on paint operations to internal planes */ + UndoDisable(); + + /* Clean up after last route - if necessary */ + if(mzDirty) + { + MZClean(); + } + + /* Set dirty flag - since we are about to alloc storage for this route */ + mzDirty = TRUE; + + /* initial source of paths is initialization routine */ + mzPathSource = SOURCE_INIT; + + /* initial estimated cost is infinity */ + mzMinInitialCost = COST_MAX; + + /* initialize per-route statistics */ + mzBlockGenCalls = 0; + mzBlockGenArea = 0.0; + mzNumComplete = 0; + mzNumPathsGened = 0; + mzNumPaths = 0; + mzNumBlooms = 0; + mzNumOutsideBlooms = 0; + mzPathsTilReport = mzReportInterval; + + /* Make supplied parms current */ + + mzRouteLayers = parms->mp_rLayers; + mzRouteContacts = parms->mp_rContacts; + mzRouteTypes = parms->mp_rTypes; + + mzPenalty = parms->mp_penalty; + mzWWidth = parms->mp_wWidth; + mzWRate = parms->mp_wRate; + mzBloomDeltaCost = parms->mp_bloomDeltaCost; + + mzBoundsIncrement = parms->mp_boundsIncrement; + mzEstimate = parms->mp_estimate; + mzExpandEndpoints = parms->mp_expandEndpoints; + mzTopHintsOnly = parms->mp_topHintsOnly; + + mzMaxWalkLength = parms->mp_maxWalkLength; + mzBoundsHint = parms->mp_boundsHint; + mzVerbosity = parms->mp_verbosity; + mzBloomLimit = parms->mp_bloomLimit; + + /* Some parms are computed from the supplied ones */ + mzComputeDerivedParms(); + + /* set route cell (toplevel cell visible during routing */ + mzRouteUse = routeUse; + + /* set expansion mask */ + mzCellExpansionMask = expansionMask; + + /* Build hint fence and rotate planes */ + mzBuildHFR(mzRouteUse, &mzBoundingRect); + + /* Initialize Blockage Planes */ + { + RouteType *rT; + + /* Clear bounds planes = regions for which blockage + has been generated */ + DBClearPaintPlane(mzHBoundsPlane); + DBClearPaintPlane(mzVBoundsPlane); + + /* Clear blockage planes */ + for (rT=mzRouteTypes; rT!=NULL; rT=rT->rt_next) + { + DBClearPaintPlane(rT->rt_hBlock); + DBClearPaintPlane(rT->rt_vBlock); + } + } + + /* Initialize Dest Area Cell */ + DBCellClearDef(mzDestAreasUse->cu_def); + /* take our hold off undo */ + UndoEnable(); + + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * MZAddStart -- + * + * Add a starting terminal for the maze router. + * + * Results: + * None. + * + * Side effects: + * Builds mzStartTerms list. + * + * ---------------------------------------------------------------------------- + */ + +void +MZAddStart(point, type) + Point *point; + TileType type; +{ + /* Disable undo to avoid overhead on paint operations to internal planes */ + UndoDisable(); + + /* check fence parity */ + if(mzStartTerms == NULL) + { + /* This is first start terminal, set fence parity by it, i.e. + * whether route is inside or outside of fence + */ + Tile *tFencePlane = TiSrPointNoHint(mzHFencePlane, point); + mzInsideFence = (TiGetType(tFencePlane) != TT_SPACE); + + /* If inside fence, clip mzBounds to fence bounding box + * to save processing. + */ + if(mzInsideFence) + { + Rect r; + + DBBoundPlane(mzHFencePlane, &r); + r.r_xbot -= 2*mzContextRadius; + r.r_ybot -= 2*mzContextRadius; + r.r_xtop += 2*mzContextRadius; + r.r_ytop += 2*mzContextRadius; + GEOCLIP(&mzBoundingRect, &r); + } + } + else + { + /* not first start terminal, check for consistency with respect + * to fence parity. + */ + Tile *tFencePlane = TiSrPointNoHint(mzHFencePlane, point); + int newInside = (TiGetType(tFencePlane) != TT_SPACE); + + if(newInside != mzInsideFence) + { + TxPrintf("Start points on both sides of fence. "); + TxPrintf("Arbitrarily choosing those %s fence.\n", + (mzInsideFence ? "inside" : "outside")); + + return; + } + } + + /* Mark tiles connected to start point */ + + /* Comment added by Tim 8/5/06 */ + /* TO DO: If mzExpandEndpoints is FALSE, mzMarkConnectedTiles */ + /* should still add all tiles immediately under the point to the */ + /* start list. */ + + { + Rect rect; + + /* build degenerate rect containing point to initiate the + * marking process; + */ + rect.r_ll = *point; + rect.r_ur = *point; + + mzMarkConnectedTiles(&rect, type, (mzExpandEndpoints) ? + MZ_EXPAND_START : MZ_EXPAND_NONE); + } + + /* Take our hold off undo */ + UndoEnable(); + + /* and return */ + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * MZAddDest -- + * + * Add a destination terminal. + * + * Results: + * none. + * + * Side effects: + * Paints dest area into mzDestAreasDef. + * + * Marks mask data tiles connected to supplied dest area (rect and type + * passed to this func), also keeps list of marked tiles for cleanup. + * + * Tiles are marked with TRUE on the clientdata field. The default + * clientdata value of CLIENTDEFAULT should be restored by the router + * before it returns. + * + * ---------------------------------------------------------------------------- + */ + +void +MZAddDest(rect, type) + Rect *rect; + TileType type; +{ + ColoredRect *dTerm; + + UndoDisable(); + + /* If we're not marking all connected tiles, we need to paint */ + /* this specific rectangle into the mzDestAreasUse cell. */ + + if (!mzExpandEndpoints) + { + RouteLayer *rL; + + for(rL = mzRouteLayers; rL != NULL; rL = rL->rl_next) + { + if (rL->rl_routeType.rt_active && + TTMaskHasType(&(DBConnectTbl[type]), + rL->rl_routeType.rt_tileType)) + DBPaint(mzDestAreasUse->cu_def, rect, + rL->rl_routeType.rt_tileType); + } + } + + /* Mark all tiles connected to dest terminal and paint them into */ + /* the mzDestAreasUse cell. */ + + mzMarkConnectedTiles(rect, type, + (mzExpandEndpoints) ? MZ_EXPAND_DEST : MZ_EXPAND_NONE); + + UndoEnable(); + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * MZRoute -- + * + * Do the route. + * + * Results: + * Zero-width route path. NOTE: route path is allocated from temporary + * storage that will be reused for next route. + * + * Side effects: + * + * + * ---------------------------------------------------------------------------- + */ + +RoutePath * +MZRoute(mzResult) + int *mzResult; /* Place to put result code */ +{ + RoutePath *path; /* handle for result of search */ + ColoredRect *term; + List *terms; + + /* Disable undo to avoid overhead on paint operations to internal planes */ + UndoDisable(); + + /* Clear result cell */ + DBCellClearDef(mzResultDef); + + /* 1st pass over start terminals: */ + /* paint TT_SAMENODE on each start terminal */ + + for(terms = mzStartTerms; terms != NULL; terms = LIST_TAIL(terms)) + { + term = (ColoredRect *) LIST_FIRST(terms); + mzPaintBlockType(&term->cr_rect, term->cr_type, &mzBoundingRect, + TT_SAMENODE); + } + + /* Generate dest areas and walks in blockage planes. + * (also adds alignment coords for dest areas to alignment structs.) + */ + mzBuildDestAreaBlocks(); + + /* Check that there is an unblocked destination */ + if (mzXAlignNL.nl_sizeUsed == 2) + { + /* No alignment marks, so no destination areas */ + TxPrintf("No reachable destination area!\n"); + if (mzResult) *mzResult = MZ_UNROUTABLE; + goto abort; + } + + /* Build Estimate Plane. + * (allowing for end points in unexpanded subcells) + */ + mzBuildEstimate(); + if (SigInterruptPending) + { + if (mzResult) *mzResult = MZ_INTERRUPTED; + goto abort; + } + + /* allocating queues and hashtable so set dirty flag */ + mzPathsDirty = TRUE; + + /* + * Initialize queues (actually heaps and lists) for partial paths + * Double Precision Integer keys used in cost keyed heaps + * to avoid overflow. + */ + HeapInitType(&mzMaxToGoHeap, INITHEAPSIZE, TRUE, FALSE, HE_DLONG); + HeapInitType(&mzMinCostHeap, INITHEAPSIZE, FALSE, FALSE, HE_DLONG); + HeapInitType(&mzMinAdjCostHeap, INITHEAPSIZE, FALSE, FALSE, HE_DLONG); + HeapInitType(&mzMinCostCompleteHeap, INITHEAPSIZE, FALSE, FALSE, HE_DLONG); + mzBloomStack = NULL; + mzStraightStack = NULL; + mzDownHillStack = NULL; + mzWalkStack = NULL; + + /* + * A hash table is used to hold all points reached, + * so we can avoid redundant expansion. + */ + HashInit(&mzPointHash, INITHASHSIZE, HashSize(sizeof (PointKey))); + + /* Build blockage planes at start points and create initial + * partial paths + */ + + /* set bloom threshold to zero, so that initial points are placed + * on Max ToGo heap. + */ + mzBloomMaxCost = 0; + + /* 2nd pass over start terminals: generate initial paths */ + /* for each start point */ + + for(terms = mzStartTerms; terms != NULL; terms = LIST_TAIL(terms)) + { + term = (ColoredRect *) LIST_FIRST(terms); + mzExtendBlockBounds(&(term->cr_rect.r_ll)); + + if (mzStart(term) == FALSE) + { + if (mzResult) *mzResult = MZ_ALREADY_ROUTED; + goto abort; + } + } + + /* initialize search window */ + /* estimated total cost is min estimated cost for initial paths */ + + mzInitialEstimate = mzMinInitialCost; + + mzWInitialMinToGo = mzInitialEstimate; + mzWInitialMaxToGo = mzWInitialMinToGo + mzWWidth; + + /* Make sure we got here without interruption */ + if (SigInterruptPending) goto abort; + + /* Do the route */ + path = mzSearch(mzResult); + /* On interruption mzSearch returns best complete path + * found prior to interruption + */ + + UndoEnable(); + return path; + +abort: + UndoEnable(); + return NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * MZCleanupPath -- + * + * Given a RoutePath constructed by mzRoute, check for conditions that + * result in DRC errors, and correct them. Conditions checked and + * the method to fix are as follows: + * + * 1) contact1->(any)->contact2 where contacts are the same type and + * would overlap to produce a non-rectangular area. + * FIX: replace second contact with its residues. + * + * 2) contact1->(any)->contact2 where contacts are the same type and + * would be spaced closer than the allowed contact->contact minimum + * DRC space. + * FIX: fill the area between the two contacts with the contact + * residue types. + * + * 3a) route1-(bend)->route2->contact where length(route2) is less than + * the spacing rule type(route2)->type(contact). + * FIX: pull route2 segment toward the inside corner of the bend + * until the route segment edge aligns with the contact edge. + * + * 3b) contact->route2-(bend)->route1, the reverse of the above. + * + * + * Results: + * None. + * + * Side effects: + * Messes with the path list. + * + * ---------------------------------------------------------------------------- + */ + +void +MZCleanupPath(pathList) + RoutePath *pathList; +{ + RoutePath *path, *n1path, *n2path, *n3path; + RoutePath *spath, *cpath, *mpath; + RouteType *rT; + RouteContact *rC, *rC1, *rC2; + TileType ctype, ctype1, ctype2; + int pathlength, hdist, vdist, cdist1, cdist2; + + + /* 1st pass: Consolidate multiple V or H routes */ + for (path = pathList; path != NULL; path = path->rp_back) + { + n1path = path->rp_back; + while (n1path && (((n1path->rp_orient == 'V') && (path->rp_orient == 'V')) || + ((n1path->rp_orient == 'H') && (path->rp_orient == 'H')))) + { + /* NOTE: Route paths are allocated by a special procedure; */ + /* DON'T use freeMagic() on them! */ + path->rp_back = n1path->rp_back; + n1path = path->rp_back; + } + } + + /* 2nd pass: Look for route paths causing DRC errors */ + for (path = pathList; path != NULL; path = path->rp_back) + { + /* Pick up the next two path segments, if they exist */ + n1path = path->rp_back; + n2path = (n1path) ? n1path->rp_back : NULL; + + if (n2path && (n1path->rp_rLayer != n2path->rp_rLayer)) + { + /* Search backward until we reach the next contact */ + for (spath = n2path->rp_back; spath && spath->rp_back; + spath = spath->rp_back) + { + cpath = spath->rp_back; + if (spath->rp_rLayer != cpath->rp_rLayer) + { + rC1 = MZGetContact(n1path, n2path); + rC2 = MZGetContact(spath, cpath); + hdist = abs(n1path->rp_entry.p_x - spath->rp_entry.p_x); + vdist = abs(n1path->rp_entry.p_y - spath->rp_entry.p_y); + ctype1 = rC1->rc_routeType.rt_tileType; + ctype2 = rC2->rc_routeType.rt_tileType; + cdist1 = rC1->rc_routeType.rt_width; + cdist2 = rC2->rc_routeType.rt_width; + + /* To-do: split into cases based on ctype1 vs. ctype2 */ + if ((cpath->rp_rLayer == n1path->rp_rLayer) && + (hdist < cdist1 && vdist < cdist1) && + (hdist > 0) && (vdist > 0)) + { + /* Case 1 */ + TxPrintf("Diagnostic: Overlapping contacts (%d:%d) at %d %d\n", + hdist, vdist, + path->rp_entry.p_x, path->rp_entry.p_y); + + /* Replace orient code of one contact with 'C', */ + /* to be handled by mzPaintContact */ + + if (n1path->rp_extendCode > EC_ALL + && n1path->rp_orient != 'C') + spath->rp_orient = 'C'; + else + n1path->rp_orient = 'C'; + + break; + } + hdist += rC1->rc_routeType.rt_width; + vdist += rC1->rc_routeType.rt_width; + cdist1 = rC1->rc_routeType.rt_spacing[ctype1]; + if (hdist < cdist1 && vdist < cdist1 && hdist > 0 && vdist > 0) + { + /* Case 2 */ + TxPrintf("Diagnostic: Contacts too close (%d:%d) at %d %d\n", + hdist, vdist, + n1path->rp_entry.p_x, n1path->rp_entry.p_y); + + /* Replace orient code of route with 'M' if contacts */ + /* are the same type, 'N' if they're different. */ + /* To be handled by MZPaintPath */ + + for (mpath = n1path; mpath != spath; mpath = mpath->rp_back) + if (mpath->rp_orient != 'O') + { + if (cpath->rp_rLayer == n1path->rp_rLayer) + mpath->rp_orient = 'M'; + else + mpath->rp_orient = 'N'; + } + break; + } + + break; /* Stop searching after 1st contact found */ + } + } + } + + /* Pick up the following path segment, if it exists */ + n3path = (n2path) ? n2path->rp_back : NULL; + + /* Cases 3a and 3b */ + if (n3path != NULL) + { + /* Cases 3a: route1->route2->contact */ + + if (n2path->rp_orient == 'O' && + n1path->rp_orient != 'O' && + path->rp_orient != 'O' && + n1path->rp_orient != path->rp_orient) + { + rT = &(n1path->rp_rLayer->rl_routeType); + rC = MZGetContact(n2path, n3path); + ctype = rC->rc_routeType.rt_tileType; + + if (n1path->rp_orient == 'V') + { + if (n1path->rp_entry.p_y > n2path->rp_entry.p_y) + { + /* Case 3a.1: route down to contact */ + pathlength = n1path->rp_entry.p_y - n2path->rp_entry.p_y + - rC->rc_routeType.rt_width; + if (pathlength > 0 && pathlength < rT->rt_bloatTop[ctype]) + { + TxPrintf("Diagnostic: Path needs fix for type " + "3a.1 DRC error at (%d, %d) dist %d\n", + path->rp_entry.p_x, path->rp_entry.p_y, + pathlength); + } + } + else + { + /* Case 3a.2: route up to contact */ + pathlength = n2path->rp_entry.p_y - n1path->rp_entry.p_y + - rT->rt_width; + if (pathlength > 0 && pathlength < rT->rt_bloatTop[ctype]) + { + TxPrintf("Diagnostic: Path needs fix for type " + "3a.2 DRC error at (%d, %d) dist %d\n", + path->rp_entry.p_x, path->rp_entry.p_y, + pathlength); + } + } + } + else + { + if (n1path->rp_entry.p_x > n2path->rp_entry.p_x) + { + /* Case 3a.3: route left to contact */ + pathlength = n1path->rp_entry.p_x - n2path->rp_entry.p_x + - rC->rc_routeType.rt_width; + if (pathlength > 0 && pathlength < rT->rt_bloatTop[ctype]) + { + TxPrintf("Diagnostic: Path needs fix for type " + "3a.3 DRC error at (%d, %d) dist %d\n", + path->rp_entry.p_x, path->rp_entry.p_y, + pathlength); + } + } + else + { + /* Case 3a.4: route right to contact */ + pathlength = n2path->rp_entry.p_x - n1path->rp_entry.p_x + - rT->rt_width; + if (pathlength > 0 && pathlength < rT->rt_bloatTop[ctype]) + { + TxPrintf("Diagnostic: Path needs fix for type " + "3a.4 DRC error at (%d, %d) dist %d\n", + path->rp_entry.p_x, path->rp_entry.p_y, + pathlength); + } + } + } + } + + /* Cases 3b: contact->route1->route2 */ + + if (n1path->rp_orient == 'O' && + n2path->rp_orient != 'O' && + n3path->rp_orient != 'O' && + n2path->rp_orient != n3path->rp_orient) + { + rT = &(n2path->rp_rLayer->rl_routeType); + rC = MZGetContact(n1path, path); + ctype = rC->rc_routeType.rt_tileType; + + if (n2path->rp_orient == 'V') + { + if (n2path->rp_entry.p_y > n1path->rp_entry.p_y) + { + /* Case 3b.1: route down from contact */ + pathlength = n2path->rp_entry.p_y - n1path->rp_entry.p_y + - rC->rc_routeType.rt_width; + if (pathlength > 0 && pathlength < rT->rt_bloatTop[ctype]) + { + TxPrintf("Diagnostic: Path needs fix for type " + "3b.1 DRC error at (%d, %d) dist %d\n", + path->rp_entry.p_x, path->rp_entry.p_y, + pathlength); + } + } + else + { + /* Case 3b.2: route up from contact */ + pathlength = n1path->rp_entry.p_y - n2path->rp_entry.p_y + - rT->rt_width; + if (pathlength > 0 && pathlength < rT->rt_bloatTop[ctype]) + { + TxPrintf("Diagnostic: Path needs fix for type " + "3b.2 DRC error at (%d, %d) dist %d\n", + path->rp_entry.p_x, path->rp_entry.p_y, + pathlength); + } + } + } + else + { + if (n2path->rp_entry.p_x > n1path->rp_entry.p_x) + { + /* Case 3b.3: route left from contact */ + pathlength = n2path->rp_entry.p_x - n1path->rp_entry.p_x + - rC->rc_routeType.rt_width; + if (pathlength > 0 && pathlength < rT->rt_bloatTop[ctype]) + { + TxPrintf("Diagnostic: Path needs fix for type " + "3b.3 DRC error at (%d, %d) dist %d\n", + path->rp_entry.p_x, path->rp_entry.p_y, + pathlength); + } + } + else + { + /* Case 3b.4: route right from contact */ + pathlength = n1path->rp_entry.p_x - n2path->rp_entry.p_x + - rT->rt_width; + if (pathlength > 0 && pathlength < rT->rt_bloatTop[ctype]) + { + TxPrintf("Diagnostic: Path needs fix for type " + "3b.4 DRC error at (%d, %d) dist %d\n", + path->rp_entry.p_x, path->rp_entry.p_y, + pathlength); + } + } + } + } + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * MZPaintPath -- + * + * Given a RoutePath constructed by mzRoute, convert it to paint. + * The input RoutePath specifies a sequence of points completely, so + * each leg can be painted as we go. + * + * Results: + * Pointer to result cell containing painted path. + * + * Side effects: + * Paints into result cell. + * + * ---------------------------------------------------------------------------- + */ + +CellUse * +MZPaintPath(pathList) + RoutePath *pathList; +{ + RoutePath *path, *prev; + RouteLayer *last_rL = NULL; + int cwidth = 0; + + /* + * First, check the path for common problems causing DRC errors + */ + MZCleanupPath(pathList); + + /* + * Each segment of the path contains no bends, so is + * either horizontal, vertical, or a contact. + */ + for (path = pathList; + (prev = path->rp_back)!= NULL && !SigInterruptPending; + path = prev) + { + RouteLayer *rL; + Rect r; + int t; + + /* + * Special handling for a contact if different planes. + * In this case, no x- or y- motion is allowed. + */ + if (path->rp_rLayer != prev->rp_rLayer) + { + ASSERT(path->rp_entry.p_x == prev->rp_entry.p_x, "MZPaintPath"); + ASSERT(path->rp_entry.p_y == prev->rp_entry.p_y, "MZPaintPath"); + cwidth = mzPaintContact(path, prev); + last_rL = path->rp_rLayer; + continue; + } + + /* + * Leg on the same plane. + * Generate a box between the start and end points + * with the width specified for this layer. + * Flip the rectangle as necessary to ensure that + * LL <= UR. + */ + r.r_ll = path->rp_entry; + r.r_ur = prev->rp_entry; + if (r.r_xbot > r.r_xtop) + t = r.r_xbot, r.r_xbot = r.r_xtop, r.r_xtop = t; + if (r.r_ybot > r.r_ytop) + t = r.r_ybot, r.r_ybot = r.r_ytop, r.r_ytop = t; + if (path->rp_orient == 'M' || path->rp_orient == 'N') + { + r.r_xtop += cwidth; + r.r_ytop += cwidth; + } + else + { + r.r_xtop += path->rp_rLayer->rl_routeType.rt_width; + r.r_ytop += path->rp_rLayer->rl_routeType.rt_width; + } + + rL = path->rp_rLayer; + DBPaintPlane(mzResultDef->cd_planes[rL->rl_planeNum], &r, + DBStdPaintTbl(rL->rl_routeType.rt_tileType, + rL->rl_planeNum), (PaintUndoInfo *) NULL); + + /* Routes between close contacts of the same type should paint */ + /* both residue types. */ + + if ((path->rp_orient == 'M') && (last_rL != NULL)) + { + DBPaintPlane(mzResultDef->cd_planes[last_rL->rl_planeNum], &r, + DBStdPaintTbl(last_rL->rl_routeType.rt_tileType, + last_rL->rl_planeNum), (PaintUndoInfo *) NULL); + } + } + + /* Update bounding box of result cell */ + DBReComputeBbox(mzResultDef); + + /* return pointer to result cell use */ + return mzResultUse; + +} + + +/* + * ---------------------------------------------------------------------------- + * + * MZClean -- + * + * Reclaim storage space gobbled up during route, and reset tile client + * fields. After a MZInitRoute() has been issued, MZClean() should always + * be called prior to returning from Magic command. + * + * Results: + * None + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +MZClean() +{ + if(mzDirty) + { + /* clear estimate plane */ + mzCleanEstimate(); + + /* Reclaim storage and reset mzStartList */ + { + ListDeallocC(mzStartTerms); + mzStartTerms = NULL; + } + + /* Reset dest alignment structures */ + mzNLClear(&mzXAlignNL); + mzNLClear(&mzYAlignNL); + + /* Unmark marked tiles, and cells and dealloc marked lists */ + { + List *l; + + /* Reset Marked subcell client fields to CLIENTDEFAULT */ + for(l=mzMarkedCellsList; l!=NULL; l=LIST_TAIL(l)) + { + CellUse *cu = (CellUse *) LIST_FIRST(l); + + /* Restore celluse client field to its "unmarked" value */ + cu->cu_client = (ClientData) CLIENTDEFAULT; + } + + /* Dealloc list of marked cells */ + ListDealloc(mzMarkedCellsList); + mzMarkedCellsList = NULL; + } + + /* Free up route-path queues */ + if(mzPathsDirty) + { + HeapKill(&mzMaxToGoHeap, (void (*)()) NULL); + HeapKill(&mzMinCostHeap, (void (*)()) NULL); + HeapKill(&mzMinAdjCostHeap, (void (*)()) NULL); + HeapKill(&mzMinCostCompleteHeap, (void (*)()) NULL); + ListDealloc(mzBloomStack); + ListDealloc(mzStraightStack); + ListDealloc(mzDownHillStack); + ListDealloc(mzWalkStack); + + /* Free up hash table */ + HashKill(&mzPointHash); + + /* Reclaims route path entries */ + mzFreeAllRPaths(); + + /* reset flag */ + mzPathsDirty = FALSE; + } + + /* reset flag */ + mzDirty = FALSE; + } + + return; +} diff --git a/mzrouter/mzNumLine.c b/mzrouter/mzNumLine.c new file mode 100644 index 00000000..a4308391 --- /dev/null +++ b/mzrouter/mzNumLine.c @@ -0,0 +1,268 @@ +/* + * mzNumberLine.c -- + * + * Implements datastructure that permits division of line into intervals + * (end points) are integers, and given any interger, allows (quick) access to + * the interval containing that integer. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzNumLine.c,v 1.2 2010/10/22 15:02:15 tim Exp $"; +#endif /* not lint */ + +/* -- includes -- */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "textio/textio.h" +#include "utils/heap.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + + +/* + * ---------------------------------------------------------------------------- + * + * mzNLInit - + * + * Initial a number line. + * + * Results: + * None. + * + * Side effects: + * Allocs entires array and sets number line to the single interval + * from MINFINITY to INFINITY. + * + * ---------------------------------------------------------------------------- + */ + +void +mzNLInit(nL, size) + NumberLine *nL; + int size; /*initial size of number line */ +{ + int *entries; + size = MAX(size, 2); + + nL->nl_sizeAlloced = size; + nL->nl_sizeUsed = 2; + + entries = (int *) mallocMagic((unsigned)(sizeof(int)*size)); + entries[0] = MINFINITY; + entries[1] = INFINITY; + + nL->nl_entries = entries; + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzNLInsert - + * + * Add new division point to numberline. + * + * Results: + * None. + * + * Side effects: + * Modifiy number line, allocate larger entry array if necessary. + * + * ---------------------------------------------------------------------------- + */ + +void +mzNLInsert(nL,x) + NumberLine *nL; + int x; /* new point */ +{ + + int lowI, highI; + + /* find entries bounding x */ + { + lowI = 0; + highI = nL->nl_sizeUsed - 1; + + + while(highI-lowI > 1) + { + int newI = lowI + (highI - lowI)/2; + int newV = nL->nl_entries[newI]; + + if(newV <= x) + { + lowI = newI; + } + if(newV >= x) + { + highI = newI; + } + } + } + + /* if x is already an entry, just return */ + if(lowI == highI) + { + return; + } + + /* if number line is full, allocate twice as big an entry array */ + if(nL->nl_sizeUsed == nL->nl_sizeAlloced) + { + int *newEntries; + int newSize; + + /* allocate new entry array */ + newSize = nL->nl_sizeUsed*2; + newEntries = (int *) mallocMagic(sizeof(int) * (unsigned)(newSize)); + + /* copy old entries to new */ + { + int *sentinel = &(nL->nl_entries[nL->nl_sizeAlloced]); + int *source = nL->nl_entries; + int *target = newEntries; + while(source != sentinel) + { + *(target++) = *(source++); + } + } + + /* free up old array */ + freeMagic(nL->nl_entries); + + /* update numberline */ + nL->nl_sizeAlloced = newSize; + nL->nl_entries = newEntries; + } + + /* move larger entries down one to make room */ + { + int * sentinel = &((nL->nl_entries)[lowI]); + int * target = &((nL->nl_entries)[nL->nl_sizeUsed]); + int * source = target-1; + + while(source!=sentinel) + { + *(target--) = *(source--); + } + } + + /* insert new entry */ + (nL->nl_entries)[highI] = x; + + /* update entry count */ + (nL->nl_sizeUsed)++; + + /* and return */ + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzNLGetContainingInterval - + * + * Find interval containing x (by binary search) + * + * Results: + * Pointer to array of two ints bounding x. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int * +mzNLGetContainingInterval(nL,x) + NumberLine *nL; + int x; /* new point */ +{ + + int lowI, highI; + + /* find entries bounding x */ + { + lowI = 0; + highI = nL->nl_sizeUsed - 1; + + while(highI-lowI > 1) + { + int newI = lowI + (highI - lowI)/2; + int newV = nL->nl_entries[newI]; + + if(newV <= x) + { + lowI = newI; + } + if(newV >= x) + { + highI = newI; + } + } + } + + /* return pointer to bounding entries */ + return &((nL->nl_entries)[lowI]); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzNLClear - + * + * Clears numberline to single interval from MINFINITY to INFINITY. + * + * Results: + * None. + * + * Side effects: + * See above. CURRENTLY WE LEAVE THE ALLOCATED SIZE OF THE NUMBERLINE + * ALONE. + * + * ---------------------------------------------------------------------------- + */ + +void +mzNLClear(nL) + NumberLine *nL; +{ + + nL->nl_entries[0] = MINFINITY; + nL->nl_entries[1] = INFINITY; + nL->nl_sizeUsed = 2; + + return; +} diff --git a/mzrouter/mzSearch.c b/mzrouter/mzSearch.c new file mode 100644 index 00000000..47b63868 --- /dev/null +++ b/mzrouter/mzSearch.c @@ -0,0 +1,1518 @@ +/* + * mzSearch.c -- + * + * Search strategy for maze router. + * Low level of Maze router (finding next interesting point) is done in + * mzSearchRight.c etc. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * SEARCH STRATEGY: + * + * Partial paths are expanded one interesting point at a time - that is a + * path is expanded to the next interesting point left, right, up and down + * and vias to neighboring layers are considered, then a new (though possibly + * one of the extensions just created) path is selected for expansion. + * + * The "search strategy" employed determines which partial-path is + * chosen for exansion at each stage. + * + * A windowed search strategy is used. At any given time the window + * bounds define a minimum and maximum distance to the goal. Partial paths + * are divided into three groups: those farther from the goal than the + * window, those within the window, and those nearer to the goal than the + * window. The window begins at the start point and is slowly shifted + * toward the goal over time. Normally the partial-path of least + * estimated-total-cost WITHIN + * the window is chosen for expansion, although a further path (i.e. one + * beyond the window) that has exceptionally low estimated-total-cost is + * sometimes chosen instead. When the trailing edge of the window reaches + * the goal, the search is deemed complete and the lowest cost complete + * path found is returned. However if no complete-path has been found + * searching will continue until the first complete path is found. + * The idea behind the windowed search is to + * expand the paths that promise to give the best (lowest cost) solution, but + * to slowly shift attention toward the goal to avoid the VERY long time + * it would take to examine all possible paths. + * + * In the case of many partial paths within the window, the above search may + * be too scattered; "blooming" is used to give a local-focus to the search + * by examining a number of expansions + * from a given partial path before going on to consider other paths. Blooming + * is equivalent to searching the move tree in chess before applyng static + * evaluations of "final" positions. In practice it makes the router behave + * much better. + * + * The search strategy is implemented with three heaps and four stacks: + * + * mzMaxToGoHeap - keeps partial paths NEARER the goal than the window. + * these paths are not yet eligible for expansion. + * Whenever the window is moved, the top elements of + * this heap (i.e. those furthest from the goal) are + * moved onto the mzMinCostHeap (i.e. into the window). + * + * mzMinCostHeap - keeps partial paths inside the window. the top of this + * heap, i.e. the least cost path inside + * the window, is compared with the least (penalized) cost of + * the paths beyond the window, and the lesser of these + * two is chosen for expansion. + * + * mzMinAdjCostHeap - keeps partial paths that are further from the goal + * than the + * window. These paths are sorted by adjusted cost. + * Adjusted cost is estimated-total-cost plus a penalty + * proportial to the distance of the path from the window. + * The ordering of the paths is independent of the current + * window position - so a "reference position" is used to + * avoid recomputing adjusted costs for these paths + * everytime the window moves. The adjusted cost of the + * top (least cost) element is normalized to the current + * window position before comparison with the least cost + * path on the mzMinCostHeap. The idea behind the + * mzMinAdjCostHeap is + * to discourage searching of paths beyond the window, but + * to do so in a gentle and flexible way, so that + * behaviour will degrade gracefully under unusual + * circumstances rather than fail catastrophically. + * For example, if the window moves too fast and all the + * reasonable paths are left behind, the search will + * degenerate to a simple cost-based search biased towards + * paths nearer to completion - a startegy that is + * adequate in many situations. + * + * mzBloomStack - paths in current local focus = all expansions of a given + * partial-path that do not exceed a given estimated-cost + * (also see stacks below) + * + * mzStraightStack - focus paths being extended in straight line. + * + * mzDownHillStack - focus paths followed only until cost increases. + * + * mzWalkStack - paths inside walk (i.e. inside blocked area adjacent to + * destination. + * + * If the walk stack is not empty the next path is taken from there (thus + * paths that have reached the threshold of a dest area are given priority.) + * + * Next priority is given to the down hill stack, thus a focus path is always + * expanded until the estimated cost increases. + * + * Next the straight stack is processed. The purpose of this stack is to + * consider straight extensions in all directions to some given minimum + * distance. + * + * Next the bloom stack itself is processed. All extensions derived from + * the bloom stack are placed on one of the stacks until a fixed cost increment + * is exceeded (in practice a small increment is used, thus the local focus + * is only extended in straight lines, and then downhill). + * + * If all the stacks are empty, a new focus is pickd from the heaps and + * the bloom stack is initialized with it. + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzSearch.c,v 1.2 2010/06/24 12:37:19 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "utils/styles.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + +/* Forward declarations */ + +extern void mzExtendViaLRContacts(); +extern void mzExtendViaUDContacts(); +extern void mzBloomInit(); +extern void mzMakeStatReport(); +extern void mzExtendPath(RoutePath *); + + +/* + * ---------------------------------------------------------------------------- + * + * mzSearch -- + * + * Find a path between one of the starting terminals and the + * destination. The path must lie within the + * area mzBoundingRect. + * + * Results: + * Returns a pointer to best complete RoutePath found (NULL + * if none found). This RoutePath may be passed to + * MZPaintPath() to be converted into paint. + * + * Side effects: + * Allocates RoutePaths from our own private storage area. + * The caller must copy these to permanent storage with + * mzCopyPath() prior to calling MZClean; otherwise, + * the returned RoutePath will be lost. + * + * ---------------------------------------------------------------------------- + */ +RoutePath * +mzSearch(mzResult) + int *mzResult; +{ + RoutePath *path; /* solution */ + bool morePartialPaths = TRUE; + bool bloomLimitHit = FALSE; + bool windowSweepDoneAndCompletePathFound = FALSE; + + /* Report intial cost estimate */ + if(mzVerbosity>=VERB_STATS) + { + TxPrintf("Initial Cost Estimate: %.0f\n", + (double)(mzInitialEstimate)); + } + + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("\nBEGINNING SEARCH.\n"); + TxPrintf("\tmzWRate = %.0f\n", (double)(mzWRate)); + TxPrintf("\tmzWInitialMinToGo = %.0f\n", (double)(mzWInitialMinToGo)); + TxPrintf("\tmzWInitialMaxToGo = %.0f\n", (double)(mzWInitialMaxToGo)); + TxPrintf("\tmzBloomDeltaCost = %.0f\n", (double)(mzBloomDeltaCost)); + } + + while (morePartialPaths && + !windowSweepDoneAndCompletePathFound && + !bloomLimitHit && + !SigInterruptPending) + /* Find next path to extend from */ + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("\nABOUT TO SELECT NEXT PATH TO EXTEND.\n"); + TxMore(""); + } + + /* pop a stack */ + path = NULL; + if(mzWalkStack != NULL) + { + mzPathSource = SOURCE_WALK; + path = (RoutePath *) ListPop(&mzWalkStack); + + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("POPPING TOP OF WALK STACK for extension.\n"); + mzPrintPathHead(path); + } + } + else if(mzDownHillStack != NULL) + { + mzPathSource = SOURCE_DOWNHILL; + path = (RoutePath *) ListPop(&mzDownHillStack); + + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("POPPING TOP OF DOWNHILL STACK for extension.\n"); + mzPrintPathHead(path); + } + } + else if(mzStraightStack != NULL) + { + mzPathSource = SOURCE_STRAIGHT; + path = (RoutePath *) ListPop(&mzStraightStack); + + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("POPPING TOP OF STRAIGHT STACK for extension.\n"); + mzPrintPathHead(path); + } + } + else if(mzBloomStack != NULL) + { + mzPathSource = SOURCE_BLOOM; + path = (RoutePath *) ListPop(&mzBloomStack); + + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("POPPING TOP OF BLOOM STACK for extension.\n"); + mzPrintPathHead(path); + } + } + + /* Stacks contained a path, go about the buisness of extending it */ + if(path) + { + /* Check hashtable to see if path already obsolete, + * (i.e. cheaper path to its enpt found.) + */ + { + HashEntry *he; + PointKey pk; + RoutePath *hashedPath; + + pk.pk_point = path->rp_entry; + pk.pk_rLayer = path->rp_rLayer; + pk.pk_orient = path->rp_orient; +#if SIZEOF_VOID_P == 8 + pk.pk_buffer = 0; /* Otherwise the hash function screws up */ +#endif + + he = HashFind(&mzPointHash, (char *) &pk); + hashedPath = (RoutePath *) HashGetValue(he); + ASSERT(hashedPath!=NULL,"mzFindPath"); + + if (path!=hashedPath) + { + /* DEBUG - report path rejected due to hash value. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("HASH LOOKUP reveals better path, REJECT path.\n"); + } + + /* better path to this pt already exists, + * skip to next path + */ + continue; + } + } + + /* Make sure blockage planes have been generated around the path + * end. + */ + { + Point *point = &(path->rp_entry); + Tile *tp = TiSrPointNoHint(mzHBoundsPlane, point); + + if (TiGetType(tp)==TT_SPACE || + point->p_x == LEFT(tp) || point->p_x == RIGHT(tp)) + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("Path ends on vertical boundary of blockage"); + TxPrintf(" planes, BLOCKAGE PLANES BEING EXTENDED.\n"); + } + + mzExtendBlockBounds(point); + if(SigInterruptPending) continue; + } + + else + { + + tp = TiSrPointNoHint(mzVBoundsPlane, point); + if (point->p_y == BOTTOM(tp) || point->p_y == TOP(tp)) + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("Path ends on horizontal boundary"); + TxPrintf("of blockage planes, BLOCKAGE PLANES"); + TxPrintf("BEING EXTENDED.\n"); + } + + mzExtendBlockBounds(point); + if(SigInterruptPending) continue; + } + } + } + + /* DEBUG - if single-stepping, print data, show path end visually, + * and pause. + */ + if (DebugIsSet(mzDebugID, mzDebStep)) + { + Rect box; + CellDef *boxDef; + + /* print stats on this path */ + { + int i; + RoutePath *p; + + /* path # */ + TxPrintf("READY TO EXTEND PATH "); + TxPrintf("(blooms: %d, points-processed: %d):\n", + mzNumBlooms, + mzNumPaths); + mzPrintPathHead(path); + + /* # of segments in path segments */ + i=0; + for(p=path; p->rp_back!=0; p=p->rp_back) + i++; + TxPrintf(" (%d segments in path)\n", i); + } + + /* move box to path end-point */ + if(ToolGetBox(&boxDef,&box)) + { + int deltaX = box.r_xtop - box.r_xbot; + int deltaY = box.r_ytop - box.r_ybot; + box.r_ll = path->rp_entry; + box.r_ur.p_x = path->rp_entry.p_x + deltaX; + box.r_ur.p_y = path->rp_entry.p_y + deltaY; + DBWSetBox(mzRouteUse->cu_def, &box); + WindUpdate(); + } + + /* wait for user to continue */ + TxMore(""); + } + + /* Extend Path */ + mzExtendPath(path); + + /* update statistics */ + mzNumPaths++; /* increment number of paths processed */ + if(--mzPathsTilReport == 0) + { + mzPathsTilReport = mzReportInterval; + mzMakeStatReport(); + } + + } + else + /* stacks are empty, choose path from heaps to initial them with */ + { + HeapEntry maxToGoTopBuf, minCostTopBuf, buf; + HeapEntry *maxToGoTop, *minCostTop, *minAdjCostTop; + + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("BLOOM STACK EMPTY. "); + TxPrintf("Choosing path from heaps to initial it with.\n"); + } + + /* If the bloom limit has been exceeded, stop searching */ + if(mzBloomLimit >0 && + mzNumBlooms > mzBloomLimit) + { + if(mzVerbosity>=VERB_BRIEF) + { + TxPrintf("Bloom limit (%d) hit.\n", mzBloomLimit); + } + + bloomLimitHit = TRUE; + continue; + } + + /* set window thresholds */ + { + dlong offset; + + offset = (dlong) (mzWRate * mzNumBlooms); + + if(offset <= mzWInitialMinToGo) + { + mzWindowMinToGo = mzWInitialMinToGo - offset; + } + else + { + mzWindowMinToGo = 0; + } + + if(offset <= mzWInitialMaxToGo) + { + mzWindowMaxToGo = mzWInitialMaxToGo - offset; + } + else + { + mzWindowMaxToGo = 0; + } + + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("New window thresholds: "); + TxPrintf("windowMinToGo = %.0f, ", + (double)mzWindowMinToGo); + TxPrintf("windowMaxToGo = %.0f\n ", + (double)mzWindowMaxToGo); + } + } + + /* If window sweep is complete, and a complete path + * has been found, stop searching. + */ + if((mzWindowMaxToGo == 0) && + HeapLookAtTop(&mzMinCostCompleteHeap)) + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("WINDOW SWEEP DONE AND COMPLETE PATH EXISTS."); + TxPrintf(" Stop searching.\n"); + } + + windowSweepDoneAndCompletePathFound = TRUE; + continue; + } + + /* Move points that meet the minTogo threshold to window + * (Points are moved from the MaxToGo heap to the minCost heap) + */ + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("Moving paths into window "); + TxPrintf("(maxTogoHeap -> minCostHeap): \n"); + } + + while((maxToGoTop=HeapRemoveTop(&mzMaxToGoHeap, + &maxToGoTopBuf)) != NULL && + (maxToGoTop->he_union.hu_dlong >= mzWindowMinToGo)) + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + mzPrintPathHead((RoutePath*)(maxToGoTop->he_id)); + } + + HeapAddDLong(&mzMinCostHeap, + ((RoutePath *)(maxToGoTop->he_id))->rp_cost, + (char *) (maxToGoTop->he_id)); + } + if(maxToGoTop!=NULL) + { + HeapAddDLong(&mzMaxToGoHeap, + maxToGoTop->he_union.hu_dlong, + (char *) (maxToGoTop->he_id)); + } + } + + /* Clear top of minCostHeap of points that no longer meet the + * mzWindowMaxToGo threshold. + * (minCostHeap -> minAdjCostHeap) + */ + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("Moving paths out of window "); + TxPrintf("(minCostHeap -> minAdjCostHeap): \n"); + } + + while((minCostTop=HeapRemoveTop(&mzMinCostHeap, + &minCostTopBuf))!=NULL && + (((RoutePath *)(minCostTop->he_id))->rp_togo > + mzWindowMaxToGo)) + { + dlong adjCost; + + /* compute adjusted cost */ + adjCost = (dlong)((RoutePath *)(minCostTop->he_id))->rp_togo; + adjCost = (dlong)(adjCost * mzPenalty.rf_mantissa); + adjCost = adjCost >> mzPenalty.rf_nExponent; + adjCost += minCostTop->he_union.hu_dlong; + + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + mzPrintPathHead((RoutePath*)(minCostTop->he_id)); + TxPrintf(" Heap-key adjCost = %.0f\n", (double)adjCost); + } + + /* add to adjusted cost heap */ + HeapAddDLong(&mzMinAdjCostHeap, adjCost, + (char *) (minCostTop->he_id)); + } + + if(minCostTop!=NULL) + { + HeapAddDLong(&mzMinCostHeap, + minCostTop->he_union.hu_dlong, + (char *) (minCostTop->he_id)); + } + } + + /* Peek at tops of heaps + * (equal cost elements might have got shuffled above when + * we placed the last poped element back on the heap.) + */ + minAdjCostTop = HeapLookAtTop(&mzMinAdjCostHeap); + maxToGoTop = HeapLookAtTop(&mzMaxToGoHeap); + minCostTop = HeapLookAtTop(&mzMinCostHeap); + + /* Print tops of maxToGo, minCost and minAdjCost heaps */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("Max togo top:\n"); + if(maxToGoTop) + { + mzPrintPathHead((RoutePath*)(maxToGoTop->he_id)); + } + else + { + TxPrintf(" nil\n"); + } + TxPrintf("Min cost top:\n"); + if(minCostTop) + { + mzPrintPathHead((RoutePath*)(minCostTop->he_id)); + } + else + { + TxPrintf(" nil\n"); + } + TxPrintf("Min adjcost top:\n"); + if(minAdjCostTop) + { + TxPrintf(" Heap-key adjCost: %.0f\n", + (double)(minAdjCostTop->he_union.hu_dlong)); + } + else + { + TxPrintf(" nil\n"); + } + } + + if(minCostTop && minAdjCostTop) + /* need to compare minCostTop and minAdjCostTop */ + { + /* compute adjusted cost corresponding to current window + * position (we only penalize for amount toGo exceeding + * mzWindowMaxToGo) + */ + dlong cost, adjCost; + + cost =(dlong)((RoutePath *)(minAdjCostTop->he_id))->rp_cost; + adjCost = (dlong)((RoutePath *)(minAdjCostTop->he_id))->rp_togo; + ASSERT(adjCost >= mzWindowMaxToGo,"mzSearch"); + adjCost -= mzWindowMaxToGo; + adjCost *= mzPenalty.rf_mantissa; + adjCost = adjCost >> mzPenalty.rf_nExponent; + adjCost += cost; + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("WINDOW-CORRECTED ADJCOST: %.0f\n", + (double)(adjCost)); + } + if(minCostTop->he_union.hu_dlong <= adjCost) + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("INITIALIZING BLOOM STACK "); + TxPrintf("WITH TOP OF MIN COST HEAP.\n"); + } + minCostTop = HeapRemoveTop(&mzMinCostHeap, &buf); + mzBloomInit((RoutePath *) (minCostTop->he_id)); + } + else + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("INITIALIZING BLOOM STACK "); + TxPrintf("WITH TOP OF MIN ADJCOST HEAP.\n"); + } + minAdjCostTop = HeapRemoveTop(&mzMinAdjCostHeap, &buf); + mzBloomInit((RoutePath *) (minAdjCostTop->he_id)); + mzNumOutsideBlooms++; + } + } + else if(minCostTop) + /* minAdjCostHeap empty, so bloom from minCostTop */ + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("INITIALIZING BLOOM STACK "); + TxPrintf("WITH TOP OF MIN COST HEAP.\n"); + } + minCostTop = HeapRemoveTop(&mzMinCostHeap, &buf); + mzBloomInit((RoutePath *) (minCostTop->he_id)); + } + else if(minAdjCostTop) + /* minCost Heap empty, so bloom from minAdjCostTop */ + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("INITIALIZING BLOOM STACK "); + TxPrintf("WITH TOP OF MIN ADJCOST HEAP.\n"); + } + minAdjCostTop = HeapRemoveTop(&mzMinAdjCostHeap, &buf); + mzBloomInit((RoutePath *) (minAdjCostTop->he_id)); + mzNumOutsideBlooms++; + } + else + /* minCost and minAdjCost heaps empty, + * bloom from top of TOGO heap */ + { + if(maxToGoTop) + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("INITIALIZING BLOOM STACK "); + TxPrintf("WITH TOP OF MAX TOGO HEAP.\n"); + } + maxToGoTop = HeapRemoveTop(&mzMaxToGoHeap, &buf); + mzBloomInit((RoutePath *) (maxToGoTop->he_id)); + mzNumOutsideBlooms++; + } + else + /* No paths left to extend from */ + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("NO PATHS LEFT TO EXTEND FROM.\n"); + } + morePartialPaths = FALSE; + } + } + } + } + + /* Give final stat report. */ + mzMakeStatReport(); + + /* Return best complete path */ + { + HeapEntry heEntry; + + if(HeapRemoveTop(&mzMinCostCompleteHeap,&heEntry)) + { + if (mzResult) + { + if (SigInterruptPending) + *mzResult = MZ_CURRENT_BEST; + else + *mzResult = MZ_SUCCESS; + } + return (RoutePath *)(heEntry.he_id); + } + else + { + if (mzResult) + { + if (SigInterruptPending) + *mzResult = MZ_INTERRUPTED; + else + *mzResult = MZ_FAILURE; + } + return NULL; + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendPath -- + * + * Spread out to next interesting point in four directions, and to adjacent + * layers through contacts. + * + * Results: + * None. + * + * Side effects: + * Adds new routepaths to the queues (ie. heaps and bloomstack). + * + * ---------------------------------------------------------------------------- + */ + +void +mzExtendPath(path) + RoutePath *path; +{ + int extendCode = path->rp_extendCode; + + if (extendCode & EC_RIGHT) + { + mzExtendRight(path); + } + + if (extendCode & EC_LEFT) + { + mzExtendLeft(path); + } + + if (extendCode & EC_UP) + { + mzExtendUp(path); + } + + if (extendCode & EC_DOWN) + { + mzExtendDown(path); + } + + if (extendCode & EC_UDCONTACTS) + { + mzExtendViaUDContacts(path); + } + if (extendCode & EC_LRCONTACTS) + { + mzExtendViaLRContacts(path); + } + + if (extendCode >= EC_WALKRIGHT) + { + if (extendCode & EC_WALKRIGHT) + { + mzWalkRight(path); + } + else if (extendCode & EC_WALKLEFT) + { + mzWalkLeft(path); + } + + else if (extendCode & EC_WALKUP) + { + mzWalkUp(path); + } + + else if (extendCode & EC_WALKDOWN) + { + mzWalkDown(path); + } + else if (extendCode & EC_WALKUDCONTACT) + { + mzWalkUDContact(path); + } + else if (extendCode & EC_WALKLRCONTACT) + { + mzWalkLRContact(path); + } + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendViaLRContacts -- + * + * Spread from a point to other planes reachable from it, + * by using contacts. Stacked contacts are allowed. Search the horizontal + * block plane. Limit to areas that fit the contact minimum length. + * + * Results None. + * + * Side effects: + * Adds RoutePaths to the heap (mzReservePathCostHeap). + * + * ---------------------------------------------------------------------------- + */ +void +mzExtendViaLRContacts(path) + RoutePath *path; +{ + Point p = path->rp_entry, *lastCpos = NULL; + RouteLayer *rLayer = path->rp_rLayer; + RouteContact *rC; + List *cL; + RouteLayer *newRLayer; + Tile *tp; + TileType type, lastCtype = TT_SPACE; + RoutePath *spath; + int bendDist = 0; + + /* DEBUG - trace calls to this routine */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("EXTENDING WITH CONTACTS (HORIZONTAL)\n"); + + /* Check what the last contact was and remember its */ + /* position. Do not allow two contacts of the same */ + /* type within a DRC error distance of each other. */ + + for (spath = path; spath && spath->rp_back && (spath->rp_orient != 'O'); + spath = spath->rp_back); + if (spath->rp_back) + { + lastCpos = &spath->rp_entry; + rC = MZGetContact(spath, spath->rp_back); + lastCtype = rC->rc_routeType.rt_tileType; + } + + /* Check where the last route bend is. Don't allow a */ + /* contact within a DRC error distance of a bend. */ + + if (path) + { + if (path->rp_orient == 'V') + { + for (spath = path->rp_back; spath && spath->rp_orient == 'V'; + spath = spath->rp_back); + if (spath && spath->rp_orient == 'H') + bendDist = spath->rp_entry.p_y - p.p_y; + if (bendDist < 0) + bendDist += rLayer->rl_routeType.rt_width; + } + else if (path->rp_orient == 'H') + { + for (spath = path->rp_back; spath && spath->rp_orient == 'H'; + spath = spath->rp_back); + if (spath && spath->rp_orient == 'V') + bendDist = spath->rp_entry.p_x - p.p_x; + if (bendDist < 0) + bendDist += rLayer->rl_routeType.rt_width; + } + } + + /* Loop through contacts that connect to current rLayer */ + for (cL=rLayer->rl_contactL; cL!=NULL; cL=LIST_TAIL(cL)) + { + rC = (RouteContact *) LIST_FIRST(cL); + + /* Don't use inactive contacts */ + if (!(rC->rc_routeType.rt_active)) + continue; + + /* Get "other" route Layer contact connects to */ + if (rC->rc_rLayer1 == rLayer) + { + newRLayer = rC->rc_rLayer2; + } + else + { + ASSERT(rC->rc_rLayer2 == rLayer, + "mzExtendViaLRContacts"); + newRLayer = rC->rc_rLayer1; + } + + /* Don't spread to inactive layers */ + if (!(newRLayer->rl_routeType.rt_active)) continue; + + /* Find tile on contact plane that contains point. */ + + tp = TiSrPointNoHint(rC->rc_routeType.rt_hBlock, &p); + type = TiGetType(tp); + + /* 1. If blocked, don't place a contact */ + if ((type != TT_SPACE) && (type != TT_SAMENODE)) + continue; + + /* 2. If tile space is not long enough for the contact, don't place */ + if (RIGHT(tp) - p.p_x <= rC->rc_routeType.rt_length + - rC->rc_routeType.rt_width) + continue; + + /* 3. Check distance from last contact, if the same type */ + if (rC->rc_routeType.rt_tileType == lastCtype) + { + int cdist = rC->rc_routeType.rt_spacing[lastCtype] + + rC->rc_routeType.rt_width; + if ((abs(p.p_x - lastCpos->p_x) < cdist) && + (abs(p.p_y - lastCpos->p_y) < cdist)) + continue; + } + + /* 4. Check distance to last route bend */ + if (bendDist != 0) + { + int cwidth = rC->rc_routeType.rt_width; + int spacing = rC->rc_routeType.rt_spacing[rLayer->rl_routeType.rt_tileType]; + if (bendDist > cwidth && bendDist < cwidth + spacing) + continue; + if (bendDist < 0 && bendDist > -spacing) + continue; + } + + /* OK to drop a contact here */ + { + dlong conCost; + int extendCode; + + /* set contact cost */ + conCost = (dlong) rC->rc_cost; + + /* determine appropriate extendcode */ + tp = TiSrPointNoHint(newRLayer->rl_routeType.rt_hBlock, &p); + type = TiGetType(tp); + + switch (type) + { + case TT_SPACE: + case TT_SAMENODE: + extendCode = EC_RIGHT | EC_LEFT | EC_UP | EC_DOWN; + break; + + case TT_LEFT_WALK: + extendCode = EC_WALKRIGHT; + break; + + case TT_RIGHT_WALK: + extendCode = EC_WALKLEFT; + break; + + case TT_TOP_WALK: + extendCode = EC_WALKDOWN; + break; + + case TT_BOTTOM_WALK: + extendCode = EC_WALKUP; + break; + + case TT_ABOVE_LR_WALK: + case TT_BELOW_LR_WALK: + /* TO DO: Check if stacked contacts are allowed! */ + extendCode = EC_WALKLRCONTACT; + break; + + case TT_ABOVE_UD_WALK: + case TT_BELOW_UD_WALK: + /* TO DO: Check if stacked contacts are allowed! */ + extendCode = EC_WALKUDCONTACT; + break; + + case TT_DEST_AREA: + + extendCode = EC_COMPLETE; + break; + + default: + /* this shouldn't happen */ + ASSERT(FALSE,"mzExtendViaLRContacts"); + continue; + } + + /* Finally add point after contact */ + mzAddPoint(path, &p, newRLayer, 'O', extendCode, &conCost); + } + } + + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendViaUDContacts -- + * + * Spread from a point to other planes reachable from it, + * by using contacts. Stacked contacts are allowed. Search the vertical + * block plane. Limit to areas that fit the contact minimum length. + * + * Results None. + * + * Side effects: + * Adds RoutePaths to the heap (mzReservePathCostHeap). + * + * ---------------------------------------------------------------------------- + */ +void +mzExtendViaUDContacts(path) + RoutePath *path; +{ + Point p = path->rp_entry, *lastCpos = NULL; + RouteLayer *rLayer = path->rp_rLayer; + RouteContact *rC; + List *cL; + RouteLayer *newRLayer; + Tile *tp; + TileType type, lastCtype = TT_SPACE; + RoutePath *spath; + int bendDist = 0; + + /* DEBUG - trace calls to this routine */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("EXTENDING WITH CONTACTS (VERTICAL)\n"); + + /* Check what the last contact was and remember its */ + /* position. Do not allow two contacts of the same */ + /* type within a DRC error distance of each other. */ + + for (spath = path; spath && spath->rp_back && (spath->rp_orient != 'X'); + spath = spath->rp_back); + if (spath->rp_back) + { + lastCpos = &spath->rp_entry; + rC = MZGetContact(spath, spath->rp_back); + lastCtype = rC->rc_routeType.rt_tileType; + } + + /* Check where the last route bend is. Don't allow a */ + /* contact within a DRC error distance of a bend. */ + + if (path) + { + if (path->rp_orient == 'V') + { + for (spath = path->rp_back; spath && spath->rp_orient == 'V'; + spath = spath->rp_back); + if (spath && spath->rp_orient == 'H') + bendDist = spath->rp_entry.p_y - p.p_y; + if (bendDist < 0) + bendDist += rLayer->rl_routeType.rt_width; + } + else if (path->rp_orient == 'H') + { + for (spath = path->rp_back; spath && spath->rp_orient == 'H'; + spath = spath->rp_back); + if (spath && spath->rp_orient == 'V') + bendDist = spath->rp_entry.p_x - p.p_x; + if (bendDist < 0) + bendDist += rLayer->rl_routeType.rt_width; + } + } + + /* Loop through contacts that connect to current rLayer */ + for (cL=rLayer->rl_contactL; cL!=NULL; cL=LIST_TAIL(cL)) + { + rC = (RouteContact *) LIST_FIRST(cL); + + /* Don't use inactive contacts */ + if (!(rC->rc_routeType.rt_active)) + continue; + + /* Get "other" route Layer contact connects to */ + if (rC->rc_rLayer1 == rLayer) + { + newRLayer = rC->rc_rLayer2; + } + else + { + ASSERT(rC->rc_rLayer2 == rLayer, + "mzExtendViaUDContacts"); + newRLayer = rC->rc_rLayer1; + } + + /* Don't spread to inactive layers */ + if (!(newRLayer->rl_routeType.rt_active)) continue; + + /* Find tile on contact plane that contains point. */ + + tp = TiSrPointNoHint(rC->rc_routeType.rt_vBlock, &p); + type = TiGetType(tp); + + /* 1. If blocked, don't place a contact */ + if ((type != TT_SPACE) && (type != TT_SAMENODE)) + continue; + + /* 2. If tile space is not long enough for the contact, don't place */ + if (TOP(tp) - p.p_y <= rC->rc_routeType.rt_length + - rC->rc_routeType.rt_width) + continue; + + /* 3. Check distance from last contact, if the same type */ + if (rC->rc_routeType.rt_tileType == lastCtype) + { + int cdist = rC->rc_routeType.rt_spacing[lastCtype] + + rC->rc_routeType.rt_width; + if ((abs(p.p_x - lastCpos->p_x) < cdist) && + (abs(p.p_y - lastCpos->p_y) < cdist)) + continue; + } + + /* 4. Check distance to last route bend */ + if (bendDist != 0) + { + int cwidth = rC->rc_routeType.rt_width; + int spacing = rC->rc_routeType.rt_spacing[rLayer->rl_routeType.rt_tileType]; + if (bendDist > cwidth && bendDist < cwidth + spacing) + continue; + if (bendDist < 0 && bendDist > -spacing) + continue; + } + + /* OK to drop a contact here */ + { + dlong conCost; + int extendCode; + + /* set contact cost */ + conCost = (dlong) rC->rc_cost; + + /* determine appropriate extendcode */ + tp = TiSrPointNoHint(newRLayer->rl_routeType.rt_vBlock, &p); + type = TiGetType(tp); + + switch (type) + { + case TT_SPACE: + case TT_SAMENODE: + extendCode = EC_RIGHT | EC_LEFT | EC_UP | EC_DOWN; + break; + + case TT_LEFT_WALK: + extendCode = EC_WALKRIGHT; + break; + + case TT_RIGHT_WALK: + extendCode = EC_WALKLEFT; + break; + + case TT_TOP_WALK: + extendCode = EC_WALKDOWN; + break; + + case TT_BOTTOM_WALK: + extendCode = EC_WALKUP; + break; + + case TT_ABOVE_LR_WALK: + case TT_BELOW_LR_WALK: + /* TO DO: Check if stacked contacts are allowed! */ + extendCode = EC_WALKLRCONTACT; + break; + + case TT_ABOVE_UD_WALK: + case TT_BELOW_UD_WALK: + /* TO DO: Check if stacked contacts are allowed! */ + extendCode = EC_WALKUDCONTACT; + break; + + case TT_DEST_AREA: + + extendCode = EC_COMPLETE; + break; + + default: + /* this shouldn't happen */ + ASSERT(FALSE,"mzExtendViaUDContacts"); + continue; + } + + /* Finally add point after contact */ + mzAddPoint(path, &p, newRLayer, 'X', extendCode, &conCost); + } + } + + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * mzAddPoint -- + * + * Process interesting point. If point within bounds and not redundant, + * link to previous path, update cost, and add to heap. + * + * + * Results: + * None. + * + * Side effects: + * Adds a RoutePath to the heap. + * + * ---------------------------------------------------------------------------- + */ +void +mzAddPoint(path, p, rLayer, orient, extendCode, costptr) + RoutePath *path; /* path that new point extends */ + Point *p; /* new point */ + RouteLayer *rLayer; /* Route Layer of new point */ + int orient; /* 'H' = endpt of hor seg, 'V' = endpt of vert seg, + * 'O' = LR contact, 'X' = UD contact, + * 'B' = first point in path and blocked + */ + int extendCode; /* interesting directions to extend in */ + dlong *costptr; /* Incremental cost of new path segment */ + +{ + RoutePath *newPath; + RoutePath *hashedPath; + HashEntry *he; + PointKey pk; + dlong togo, cost; + + /* DEBUG - print candidate frontier point */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("mzAddPoint called: point=(%d,%d), layer=%s, orient='%c'\n", + p->p_x, p->p_y, + DBTypeLongNameTbl[rLayer->rl_routeType.rt_tileType], + orient); + } + + cost = *costptr; + ASSERT(cost >= 0,"mzAddPoint"); + + /* Ignore if outside of bounding box */ + if (!GEO_ENCLOSE(p, &mzBoundingRect)) + return; + + /* get estimated distance togo */ + if(extendCode == EC_COMPLETE) + togo = 0; + else + togo = mzEstimatedCost(p); + + /* compute (total) cost for new path */ + { + /* initially cost = cost of new leg in path */ + + /* Add jogcost if appropriate */ + + if (path != NULL && + path->rp_rLayer == rLayer && + path->rp_orient != 'O' && path->rp_orient != 'X' && + path->rp_orient != orient) + { + cost += rLayer->rl_jogCost; + } + + /* Add estimated total cost prior to new point, + * (or cost so far in the case of initial paths). + */ + if (path != NULL) + { + cost += path->rp_cost; + } + /* If not initial path, subtract out old estimated cost togo */ + if (mzPathSource != SOURCE_INIT) + { + cost -= path->rp_togo; + } + + /* Add new estimated cost to completion */ + cost += togo; + } + + /* Check hash table to see if cheaper path to this point already + * found - if so don't add this point. + */ + pk.pk_point = *p; + pk.pk_rLayer = rLayer; + pk.pk_orient = orient; +#if SIZEOF_VOID_P == 8 + pk.pk_buffer = 0; /* Otherwise the hash function screws up */ +#endif + + he = HashFind(&mzPointHash, (char *) &pk); + hashedPath = (RoutePath *) HashGetValue(he); + + if (hashedPath != NULL && (hashedPath->rp_cost <= cost)) + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("new point NOT added, at least as good " + "path to pt already exists: "); + TxPrintf("new cost = %.0f, ", + (double)(cost)); + TxPrintf("cheapest cost = %.0f\n", + (double)(hashedPath->rp_cost)); + } + return; + } + + /* If initial path, update min initial cost */ + if(mzPathSource==SOURCE_INIT) + { + if(cost < mzMinInitialCost) + { + mzMinInitialCost = cost; + } + } + + /* Create new path element */ + newPath = NEWPATH(); + newPath->rp_rLayer = rLayer; + newPath->rp_entry = *p; + newPath->rp_orient = orient; + newPath->rp_cost = cost; + newPath->rp_extendCode = extendCode; + newPath->rp_togo = togo; + newPath->rp_back = path; + + /* keep statistics */ + mzNumPathsGened++; + + /* Enter in hash table */ + HashSetValue(he, (ClientData) newPath); + + /* Add to appropriate queue or stack */ + if(extendCode == EC_COMPLETE) + { + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("PATH COMPLETE (WALKED IN). Add to complete heap.\n"); + } + + HeapAddDLong(&mzMinCostCompleteHeap, newPath->rp_cost, + (char *) newPath); + + /* compute stats and make completed path report */ + { + mzNumComplete++; + + if(mzVerbosity>=VERB_STATS) + { + dlong cost, excessCost; + double excessPercent; + + mzMakeStatReport(); + + TxPrintf("PATH #%d ", mzNumComplete); + + + cost = newPath->rp_cost; + TxPrintf("cst:%.0f, ", (double)(newPath->rp_cost)); + if(cost < mzInitialEstimate) + { + TxPrintf("(= EC_WALKRIGHT) + { + LIST_ADD(newPath, mzWalkStack); + } + else + { + switch(mzPathSource) + { + case SOURCE_BLOOM: + if(orient=='O') + { + /* just changing layers, add back to bloom */ + LIST_ADD(newPath, mzBloomStack); + } + else if((orient=='H' && rLayer->rl_hCost<=rLayer->rl_vCost) || + (orient=='V' && rLayer->rl_vCost<=rLayer->rl_hCost)) + { + /* going in preferred direction */ + LIST_ADD(newPath, mzStraightStack); + } + else + { + /* non preferred, add to heaps */ + HeapAddDLong(&mzMaxToGoHeap, togo, (char *) newPath); + } + break; + + case SOURCE_STRAIGHT: + if(path->rp_orient==orient && (cost < mzBloomMaxCost)) + { + /* straight and within bounds, keep going*/ + LIST_ADD(newPath, mzStraightStack); + } + else + { + /* from here on, follow downhill only */ + LIST_ADD(newPath, mzDownHillStack); + } + break; + + case SOURCE_DOWNHILL: + { + dlong oldCostPlusOne; + + oldCostPlusOne = path->rp_cost + 1; + if(cost rp_cost + mzBloomDeltaCost; + + mzNumBlooms++; + + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * mzMakeStatReport -- + * + * Print out route statistics + * + * Results: + * None. + * + * Side effects: + * Output via TxPrintf() + * + * ---------------------------------------------------------------------------- + */ + +void +mzMakeStatReport() +{ + + /* if we aren't being verbose, skip this */ + if(mzVerbosity + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + +/* Forward declarations */ + +extern bool mzExtendInitPath(RoutePath *, RouteLayer *, Point, dlong, int, int); + +extern bool mzAddInitialContacts(); + +/* + * ---------------------------------------------------------------------------- + * + * Simple search function for start tiles. This function is called only if + * a tile of type TT_SAMENODE is found in the search area. + * + * Results: + * Always return 1 (break on the first acceptable tile found) + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +mzFindSamenodeFunc(Tile *tile, Point *point) +{ + *point = tile->ti_ll; + return 1; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzStart -- + * + * Establish initial path segments from start term, considering inital + * contacts and leading out of any SAMENODE blocks + * present at start point. + * + * Results: + * TRUE normally, FALSE if mzExtendInitPath discovered that the + * start node is already connected to the destination node. + * + * Side effects: + * mzAddPoint() called to add paths to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ + +#define EC_ALL_DIRECTIONS (EC_RIGHT | EC_LEFT | EC_UP | EC_DOWN) + +bool +mzStart(term) + ColoredRect *term; +{ + RouteLayer *rL; + RouteContact *rC; + Tile *tp; + bool returnCode = TRUE; + Point point; + int result; + Rect srect; + + /* Find routelayer corresponding to type */ + for(rL = mzActiveRLs; rL != NULL; rL = rL->rl_nextActive) + { + if(rL->rl_routeType.rt_tileType == term->cr_type) break; + } + + /* Expand area to bottom and left to make sure we can find */ + /* SAMENODE tiles to the bottom and left of the terminal. */ + + srect = term->cr_rect; + srect.r_xbot--; + srect.r_ybot--; + + /* Added by Tim 8/2/06---for start terminals on contact layers, */ + /* run mzExtendInitPath for layer1 and set rL to layer2. */ + + if ((rL == NULL) && DBIsContact(term->cr_type)) + { + for (rC = mzRouteContacts ; rC != NULL; rC = rC->rc_next) + { + if (!(rC->rc_routeType.rt_active)) continue; + + if (TTMaskHasType(&(DBConnectTbl[term->cr_type]), + rC->rc_rLayer1->rl_routeType.rt_tileType) && + TTMaskHasType(&(DBConnectTbl[term->cr_type]), + rC->rc_rLayer2->rl_routeType.rt_tileType)) + { + /* Search block plane for first unblocked tile */ + result = DBSrPaintArea((Tile *)NULL, + rC->rc_rLayer1->rl_routeType.rt_hBlock, + &srect, &mzStartTypesMask, + mzFindSamenodeFunc, &point); + + if (result == 1) + { + returnCode = mzExtendInitPath(NULL, rC->rc_rLayer1, + point, (dlong)0, 0, EC_ALL_DIRECTIONS); + rL = rC->rc_rLayer2; + break; + } + } + } + } + + /* If no corresponding route layer, check for layers that connect */ + + if (rL == NULL) + { + for (rL = mzActiveRLs; rL != NULL; rL = rL->rl_nextActive) + { + if (TTMaskHasType(&(DBConnectTbl[term->cr_type]), + rL->rl_routeType.rt_tileType)) + break; + } + } + + /* If no corresponding route layer, return. */ + /* This does not need a warning. The search for connected tiles adds */ + /* tile types that may not correspond to an active route layer. Just */ + /* ignore such tiles. */ + + if (rL == NULL) + return returnCode; + + /* Find a valid start point in this terminal */ + + result = DBSrPaintArea((Tile *)NULL, rL->rl_routeType.rt_hBlock, + &srect, &mzStartTypesMask, mzFindSamenodeFunc, &point); + + if (result == 1) + { + /* call mzExtendInitPath to do the real work */ + + returnCode = mzExtendInitPath(NULL, /* path so far */ + rL, /* layer of new point */ + point, /* start point */ + (dlong)0, /* cost of new segment */ + 0, /* length of path so far */ + EC_ALL_DIRECTIONS); /* how to extend init path */ + } + return returnCode; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendInitPath -- + * + * Central routine for recursively building up initial path inside + * SAMENODE. Adds specified point to an initial path, if resulting + * path end is outside block, mzAddPoint() is called to add init path + * to appropriate queue. + * + * Results: + * TRUE normally, FALSE if a zero-length route was detected (start + * node and destination node are already connected). + * + * Side effects: + * Initial paths built up. + * mzAddPoint() eventually called to add init paths to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +bool +mzExtendInitPath(path, rL, point, cost, length, directions) + RoutePath *path; /* Initial Path, being extended */ + RouteLayer *rL; /* routelayer of new point */ + Point point; /* new point for initPath */ + dlong cost; /* cost of new segment */ + int length; /* length of path (excluding new segment) */ + int directions; /* directions to extend init path in */ +{ + Tile *tp; + bool returnCode = TRUE; + int orient; + int extendCode = 0; + + /* Get tile in rL blockage plane under new point */ + + tp = TiSrPointNoHint(rL->rl_routeType.rt_hBlock, &point); + + /* If new point blocked by a different node, just return */ + + if (TiGetType(tp) == TT_BLOCKED) + return returnCode; + + /* Consider initial contacts */ + + if (path == NULL) + returnCode = mzAddInitialContacts(rL, point); + + /* If no SAMENODE block, call mzAddPoint() to and initial path to + * appropriate queue. + */ + + switch (TiGetType(tp)) + { + /* Use standard extend code on TT_SAMENODE areas. */ + /* (Tim, 10/4/06) */ + + case TT_SAMENODE: + case TT_SPACE: + extendCode = EC_ALL_DIRECTIONS | EC_UDCONTACTS | EC_LRCONTACTS; + break; + + case TT_LEFT_WALK: + extendCode = EC_WALKRIGHT; + break; + + case TT_RIGHT_WALK: + extendCode = EC_WALKLEFT; + break; + + case TT_TOP_WALK: + extendCode = EC_WALKDOWN; + break; + + case TT_BOTTOM_WALK: + extendCode = EC_WALKUP; + break; + + case TT_ABOVE_LR_WALK: + case TT_BELOW_LR_WALK: + extendCode = EC_WALKLRCONTACT; + break; + + case TT_ABOVE_UD_WALK: + case TT_BELOW_UD_WALK: + extendCode = EC_WALKUDCONTACT; + break; + + case TT_DEST_AREA: + TxError("Zero length route!\n"); + extendCode = EC_COMPLETE; + returnCode = FALSE; + break; + } + + if (extendCode == 0) return FALSE; /* This shouldn't happen */ + + /* determine orientation of new segment */ + + if (path == NULL) + orient = 'O'; + else if (path->rp_rLayer != rL) + { + if (path->rp_entry.p_x == point.p_x) + orient = 'X'; + else + orient = 'O'; + } + else if (path->rp_entry.p_x == point.p_x) + orient = 'V'; + else + { + ASSERT(path->rp_entry.p_y==point.p_y,"mzExtendInitPath"); + orient = 'H'; + } + + /* Add initial path to appropriate queue */ + mzAddPoint(path, &point, rL, orient, extendCode, &cost); + + return returnCode; +} + +/* + * ---------------------------------------------------------------------------- + * + * mzAddInitialContacts -- + * + * + * Results: + * TRUE normally, FALSE if zero-length route + * + * Side effects: + * Calls mzExtendInitPath to add contact to initial path. + * + * ---------------------------------------------------------------------------- + */ + +bool +mzAddInitialContacts(rL, point) + RouteLayer *rL; /* routelayer of initial point */ + Point point; /* initial point */ +{ + List *cL; + Tile *tp; + RouteContact *rC; + RouteLayer *newRLayer; + dlong conCost; + RoutePath *initPath; + bool returnCode = TRUE; + + /* Loop through contacts that connect to current rLayer */ + for (cL=rL->rl_contactL; cL!=NULL; cL=LIST_TAIL(cL)) + { + rC = (RouteContact *) LIST_FIRST(cL); + + /* Don't use inactive contacts */ + if (!(rC->rc_routeType.rt_active)) continue; + + /* Get "other" route Layer contact connects to */ + if (rC->rc_rLayer1 == rL) + { + newRLayer = rC->rc_rLayer2; + } + else + { + ASSERT(rC->rc_rLayer2 == rL,"mzStart"); + newRLayer = rC->rc_rLayer1; + } + + /* Don't spread to inactive layers */ + if (!(newRLayer->rl_routeType.rt_active)) continue; + + /* Don't place contact if blocked */ + + tp = TiSrPointNoHint(rC->rc_routeType.rt_hBlock, &point); + if (TiGetType(tp) == TT_SAMENODE) + { + /* Check if the size of the tile meets min length requirement */ + if (RIGHT(tp) - point.p_x <= rC->rc_routeType.rt_length + - rC->rc_routeType.rt_width) + { + + /* compute cost of contact */ + + conCost = (dlong) rC->rc_cost; + + /* build path consisting of initial point */ + + initPath = NEWPATH(); + initPath->rp_rLayer = rL; + initPath->rp_entry = point; + initPath->rp_orient = 'O'; + initPath->rp_cost = 0; + initPath->rp_back = NULL; + + /* Extend thru new point */ + returnCode = mzExtendInitPath(initPath, newRLayer, point, + conCost, 0, EC_ALL_DIRECTIONS); + } + } + + /* Check vertical planes for contact points, too */ + tp = TiSrPointNoHint(rC->rc_routeType.rt_vBlock, &point); + if (TiGetType(tp) != TT_SAMENODE) + continue; + + /* Check if the size of the tile meets min length requirement */ + if (TOP(tp) - point.p_y <= rC->rc_routeType.rt_length + - rC->rc_routeType.rt_width) + continue; + + /* compute cost of contact */ + + conCost = (dlong) rC->rc_cost; + + /* build path consisting of initial point */ + + initPath = NEWPATH(); + initPath->rp_rLayer = rL; + initPath->rp_entry = point; + initPath->rp_orient = 'X'; + initPath->rp_cost = 0; + initPath->rp_back = NULL; + + /* Extend thru new point */ + returnCode = mzExtendInitPath(initPath, newRLayer, point, conCost, + 0, EC_ALL_DIRECTIONS); + } + return returnCode; +} + diff --git a/mzrouter/mzSubrs.c b/mzrouter/mzSubrs.c new file mode 100644 index 00000000..55fbed64 --- /dev/null +++ b/mzrouter/mzSubrs.c @@ -0,0 +1,817 @@ +/* + * mzSubrs.c -- + * + * Misc. surport routines for the Maze router. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzSubrs.c,v 1.2 2008/06/01 18:37:44 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "drc/drc.h" +#include "select/select.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "debug/debug.h" +#include "utils/undo.h" +#include "textio/txcommands.h" +#include "utils/malloc.h" +#include "utils/main.h" +#include "utils/geofast.h" +#include "utils/list.h" +#include "utils/touchingtypes.h" +#include "utils/heap.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + + + +/* + * ---------------------------------------------------------------------------- + * + * mzComputeDerivedParms -- + * + * Processes current parms deriving some parameters from others. + * + * Results: + * None + * + * Side effects: + * Modifies current parms. + * + * ---------------------------------------------------------------------------- + */ + +void +mzComputeDerivedParms() +{ + RouteContact *rC; + RouteLayer *rL; + RouteType *rT; + + /* Compute active routelayer list */ + mzActiveRLs = NULL; + for(rL=mzRouteLayers; rL!=NULL; rL=rL->rl_next) + { + if(rL->rl_routeType.rt_active) + { + rL->rl_nextActive = mzActiveRLs; + mzActiveRLs = rL; + } + } + + /* Compute active routetype list */ + mzActiveRTs = NULL; + for(rT=mzRouteTypes; rT!=NULL; rT=rT->rt_next) + { + if(rT->rt_active) + { + rT->rt_nextActive = mzActiveRTs; + mzActiveRTs = rT; + } + } + + /* Compute bloats and effWidth for route layers. + * Since we are routing bottom left edge of wires: + * bloat to bottom = spacing + width - 1; + * bloat to top = spacing + */ + for(rL=mzRouteLayers; rL!=NULL; rL=rL->rl_next) + { + RouteType *rT = &(rL->rl_routeType); + int i; + + rT->rt_effWidth = rT->rt_width; + + for(i=0;i<=TT_MAXTYPES;i++) + { + if(rT->rt_spacing[i]>=0) + { + rT->rt_bloatBot[i] = rT->rt_width + rT->rt_spacing[i] - 1; + rT->rt_bloatTop[i] = rT->rt_spacing[i]; + } + else + { + rT->rt_bloatBot[i] = -1; + rT->rt_bloatTop[i] = -1; + } + } + } + + /* contact widths and bloats are max of components */ + for(rC=mzRouteContacts; rC!=NULL; rC=rC->rc_next) + { + RouteType *rT = &(rC->rc_routeType); + RouteType *rT1 = &(rC->rc_rLayer1->rl_routeType); + RouteType *rT2 = &(rC->rc_rLayer2->rl_routeType); + int i; + + rT->rt_effWidth = MAX(MAX(rT1->rt_width,rT2->rt_width),rT->rt_width); + + for(i=0;i<=TT_MAXTYPES;i++) + { + int bot, bot1, bot2; + int top, top1, top2; + + if(rT->rt_spacing[i]>=0) + { + bot = rT->rt_width + rT->rt_spacing[i] - 1; + top = rT->rt_spacing[i]; + } + else + { + bot = -1; + top = -1; + } + + if(rT1->rt_spacing[i]>=0) + { + bot1 = rT1->rt_width + rT1->rt_spacing[i] - 1; + top1 = rT1->rt_spacing[i]; + } + else + { + bot1 = -1; + top1 = -1; + } + + if(rT2->rt_spacing[i]>=0) + { + bot2 = rT2->rt_width + rT2->rt_spacing[i] - 1; + top2 = rT2->rt_spacing[i]; + } + else + { + bot2 = -1; + top2 = -1; + } + + rT->rt_bloatBot[i] = MAX(MAX(bot1,bot2),bot); + rT->rt_bloatTop[i] = MAX(MAX(top1,top2),top); + } + } + + /* + * compute context radius = how much to bloat blockage area + * to be built to obtain search area for mask data. + */ + { + int i; + + mzContextRadius = 0; + for(rT=mzActiveRTs; rT!=NULL; rT=rT->rt_nextActive) + for(i=0;i<=TT_MAXTYPES;i++) + mzContextRadius = MAX(mzContextRadius,rT->rt_bloatBot[i]); + } + + /* If max walk length is -1, set to twice the context radius */ + if(mzMaxWalkLength==-1) + { + mzMaxWalkLength = mzContextRadius * 2; + } + + /* If bounds increment is -1, set to 30 times min active pitch */ + if(mzBoundsIncrement==-1) + { + int minPitch = INFINITY; + + for(rL=mzActiveRLs; rL!=NULL; rL=rL->rl_nextActive) + { + RouteType *rT = &(rL->rl_routeType); + int pitch = rT->rt_width + rT->rt_spacing[rT->rt_tileType]; + + minPitch = MIN(minPitch, pitch); + } + + if(minPitch==INFINITY) + /* Don't coredump just because no active rL's */ + { + mzBoundsIncrement = 100; + } + else + { + mzBoundsIncrement = 30*minPitch; + } + } + + /* Set up (global) bounding rect for route */ + if(mzBoundsHint) + /* Blockage gen will be confined to user supplied hint (+ 2 units) + * generate slightly larger bounds for other purposes (estimate generation + * and marking of tiles connected to dest nodes, for example) to avoid + * edge effects. + */ + { + mzBoundingRect = *mzBoundsHint; + + mzBoundingRect.r_xbot -= 2*mzContextRadius; + mzBoundingRect.r_ybot -= 2*mzContextRadius; + mzBoundingRect.r_xtop += 2*mzContextRadius; + mzBoundingRect.r_ytop += 2*mzContextRadius; + } + else + /* No user supplied bounds, shrink maximum paintable rect by a + * conservative amount (to avoid overflow during blockage + * plane generation etc.) + */ + { + int maxWidth, maxSpacing, safeHalo; + RouteType *rT; + + mzBoundingRect = TiPlaneRect; + + maxWidth = 0; + maxSpacing = 0; + for (rT = mzRouteTypes; rT!=NULL; rT=rT->rt_next) + { + int i; + + maxWidth = MAX(maxWidth,rT->rt_width); + for(i=0;irt_spacing[i]); + } + safeHalo = 3 * (maxSpacing + maxWidth + 2); + + mzBoundingRect.r_xbot += safeHalo; + mzBoundingRect.r_xtop -= safeHalo; + mzBoundingRect.r_ybot += safeHalo; + mzBoundingRect.r_ytop -= safeHalo; + + ASSERT(mzBoundingRect.r_xbot < mzBoundingRect.r_xtop, + "mzComputeDerivedParms"); + ASSERT(mzBoundingRect.r_ybot < mzBoundingRect.r_ytop, + "mzComputeDerivedParms"); + } +} + +int mzMakeEndpoints; /* Set to MZ_EXPAND_START, MZ_EXPAND_DEST, or + * MZ_EXPAND_NONE. + */ +/* + * ---------------------------------------------------------------------------- + * + * mzMarkConnectedTiles -- + * + * Marks tiles connected to given area on given layer in mask data. + * Used to mark tiles that are part of start or dest nodes. + * + * If mzExpandEndpoints is set, also adds dest areas for connected tiles. + * + * Results: + * none. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +mzMarkConnectedTiles(rect, type, expandType) + Rect *rect; + TileType type; + int expandType; +{ + List *expandList = NULL; /* areas remaining to be expanded from */ + + /* set global controlling the creation of dest areas for each connected + * tile found. + */ + mzMakeEndpoints = expandType; + + /* Create colored rect corresponding to passed args and initial + * expandList with it. + */ + { + ColoredRect *e; + e = (ColoredRect *) mallocMagic((unsigned)(sizeof(ColoredRect))); + e->cr_type = type; + e->cr_rect = *rect; + LIST_ADD(e, expandList); + } + + /* repeatedly expand from top area on expandList */ + while(expandList) + { + ColoredRect *e = (ColoredRect *) LIST_FIRST(expandList); + SearchContext scx; + TileTypeBitMask typeMask; + int mzConnectedTileFunc(); + + /* Restrict marking to route bounds */ + if(GEO_OVERLAP(&mzBoundingRect, &(e->cr_rect))) + { + /* Set search area to colored rect */ + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = mzRouteUse; + scx.scx_area = e->cr_rect; + + /* Grow search area by one unit in each direction so that in + * addition to overlapping + * tiles we also get those that just touch it. + */ + scx.scx_area.r_xbot -= 1; + scx.scx_area.r_ybot -= 1; + scx.scx_area.r_xtop += 1; + scx.scx_area.r_ytop += 1; + + /* Build type mask with just the type of e set */ + TTMaskSetOnlyType(&typeMask, e->cr_type); + + /* search for connecting tiles, mark them, and add them to + * expandList (They are inserted + * AFTER the first (= current) element.) + */ + (void) + DBTreeSrTiles( + &scx, + &(DBConnectTbl[e->cr_type]), /* enumerate all + * tiles of connecting + * types */ + mzCellExpansionMask, + mzConnectedTileFunc, + (ClientData) expandList); + } + + /* Done processing top element of expandList, toss it */ + e = (ColoredRect *) ListPop(&expandList); + freeMagic((char *) e); + } + + + /* mark unexpanded subcells intersecting dest area */ + { + if(mzCellExpansionMask != 0) + { + int mzConnectedSubcellFunc(); + SearchContext scx; + + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = mzRouteUse; + scx.scx_area = *rect; + + /* clip area to bounding box to avoid overflow during transforms */ + GEOCLIP(&(scx.scx_area),&(mzRouteUse->cu_def->cd_bbox)); + + /* clip to route bounds for performance */ + GEOCLIP(&(scx.scx_area),&mzBoundingRect); + + DBTreeSrCells( + &scx, + mzCellExpansionMask, + mzConnectedSubcellFunc, + (ClientData) NULL); + } + } + + return; +} + + +/* + * --------------------------------------------------------------------- + * + * mzConnectedTileFunc -- + * + * Called by MZAddDest to mark mask data tile connected to a dest terminal. + + * + * Results: + * Always returns 0 to continue search. + * + * Side effects: + * Mark clientdata fileds of connected tiles. + * Add freshly marked tiles to expandList (for recursive expansion). + * If mzExpandEndpoints is set, also adds dest areas for connected + * tiles. + * + * --------------------------------------------------------------------- + */ + +int +mzConnectedTileFunc(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + /* If tile not marked, mark it, add it to marked list, and add + * corresponding area to expand list. Mark start tiles MZ_EXPAND_START + * and destination tiles MZ_EXPAND_DEST so that we don't have to run + * the tile cleanup routing (in MZClean()) unnecessarily between + * MZAddStart() and MZAddDest(). + */ + + if ((int)tile->ti_client != mzMakeEndpoints) + { + SearchContext *scx = cxp->tc_scx; + List *expandList = (List *) (cxp->tc_filter->tf_arg); + Rect rRaw, r; + + /* Get bounding box of tile */ + TITORECT(tile, &rRaw); + GEOTRANSRECT(&scx->scx_trans, &rRaw, &r); + + /* mark tile with destination type */ + tile->ti_client = (ClientData) mzMakeEndpoints; + + /* Add tiles connected to Start to mzStartTerms */ + /* (Added by Tim, August 2006) */ + + if (mzMakeEndpoints == MZ_EXPAND_START) + { + ColoredRect *newTerm; + extern List *mzStartTerms; + + newTerm = (ColoredRect *) mallocMagic((unsigned)(sizeof(ColoredRect))); + newTerm->cr_rect = r; + newTerm->cr_type = TiGetType(tile); + LIST_ADD(newTerm, mzStartTerms); + } + + /* Add dest area (if appropriate). Don't paint contact types, */ + /* or the planes will get fractured up, possibly into areas too */ + /* small to place a valid route. */ + + else if (mzMakeEndpoints == MZ_EXPAND_DEST) + { + RouteLayer *rL; + TileType ttype = TiGetType(tile); + + for(rL=mzRouteLayers; rL!=NULL; rL=rL->rl_next) + { + if (rL->rl_routeType.rt_active && + TTMaskHasType(&(DBConnectTbl[ttype]), + rL->rl_routeType.rt_tileType)) + { + DBPaint(mzDestAreasUse->cu_def, + &r, + rL->rl_routeType.rt_tileType); + } + } + } + + /* add entry to expandList */ + { + ColoredRect *e; + + /* build colored rect corresponding to tile */ + e = (ColoredRect *) mallocMagic((unsigned)(sizeof(ColoredRect))); + e->cr_type = TiGetType(tile); + e->cr_rect = r; + + /* add new entry to second position of expandList (just + * past current entry) + */ + LIST_ADD(e, LIST_TAIL(expandList)); + } + } + + /* return 0 to continue search */ + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzConnectedSubcellFunc -- + * + * Called by MZAddDest to mark subcells overlapping a dest terminal. + * (The blockage generation code treats marked subcells as same-node geometry, + * allowing walks and dest areas near them.) + * + * Results: + * Always returns 0 (to continue search) + * + * Side effects: + * Mark client field in subcell use, and add use to list of marked + * subcells. + * + * ---------------------------------------------------------------------------- + */ + +int +mzConnectedSubcellFunc(scx, cdarg) + SearchContext *scx; + ClientData cdarg; +{ + CellUse *cu = scx->scx_use; + + /* If not already marked, mark celluse and add to marked list */ + if (cu->cu_client == (ClientData)MZ_EXPAND_NONE) + { + cu->cu_client = (ClientData)MZ_EXPAND_DEST; + LIST_ADD(cu, mzMarkedCellsList); + } + + /* continue search */ + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * mzGetContact -- + * + * Get the RouteContact record that matches the contact type between + * planes path->rp_rLayer and prev->rp_rLayer, + * + * Results: + * A pointer to the appropriate RouteContact structure, or NULL if + * none exists (which shouldn't happen). + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +RouteContact * +MZGetContact(path, prev) + RoutePath *path, *prev; +{ + RouteContact *rC; + List *cL; + + /* Find RouteContact connecting the route layers of path and prev. */ + + for (cL = path->rp_rLayer->rl_contactL; cL != NULL && + ((RouteContact*)LIST_FIRST(cL))->rc_rLayer1 != prev->rp_rLayer && + ((RouteContact*)LIST_FIRST(cL))->rc_rLayer2 != prev->rp_rLayer; + cL = LIST_TAIL(cL)); + + ASSERT(cL != NULL, "mzPaintContact"); + rC = ((RouteContact*)LIST_FIRST(cL)); + + return rC; +} + +/* + * ---------------------------------------------------------------------------- + * + * mzPaintContact -- + * + * Paint a single contact between planes path->rp_rLayer and prev->rp_rLayer, + * + * Results: + * None. + * + * Side effects: + * Updates both mask and blockage planes. + * + * ---------------------------------------------------------------------------- + */ + +int +mzPaintContact(path, prev) + RoutePath *path, *prev; +{ + RouteContact *rC; + int pNum, pNumC, cWidth; + Rect r; + TileType cType; + + rC = MZGetContact(path, prev); + + /* compute the contact tileType */ + cType = rC->rc_routeType.rt_tileType; + cWidth = rC->rc_routeType.rt_width; + + /* compute bounds of contact tile */ + r.r_ll = path->rp_entry; + + if (path->rp_orient == 'X') + { + r.r_xtop = r.r_xbot + cWidth; + r.r_ytop = r.r_ybot + rC->rc_routeType.rt_length; + } + else if (path->rp_orient == 'O') + { + r.r_xtop = r.r_xbot + rC->rc_routeType.rt_length; + r.r_ytop = r.r_ybot + cWidth; + } + else /* Type "C", residues only */ + { + r.r_xtop = r.r_xbot + cWidth; + r.r_ytop = r.r_ybot + cWidth; + } + + /* Paint the contact on all connected mask planes */ + /* (should just let DBPaint() do this. . . ) */ + + if (DBIsContact(cType)) + { + if (path->rp_orient != 'C') + { + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (PlaneMaskHasPlane(DBConnPlanes[cType], pNum)) + DBPaintPlane(mzResultDef->cd_planes[pNum], + &r, DBStdPaintTbl(cType, pNum), + (PaintUndoInfo *) NULL); + } + else + { + /* Paint residues, not the contact type, to avoid DRC errors */ + RouteLayer *rL; + + rL = rC->rc_rLayer1; + DBPaintPlane(mzResultDef->cd_planes[rL->rl_planeNum], &r, + DBStdPaintTbl(rL->rl_routeType.rt_tileType, + rL->rl_planeNum), (PaintUndoInfo *)NULL); + rL = rC->rc_rLayer2; + DBPaintPlane(mzResultDef->cd_planes[rL->rl_planeNum], &r, + DBStdPaintTbl(rL->rl_routeType.rt_tileType, + rL->rl_planeNum), (PaintUndoInfo *)NULL); + } + } + return cWidth; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzCopyPath -- + * + * Copy a RoutePath from the temporary arena into permanent storage + * allocated via mallocMagic. + * + * Results: + * Returns a pointer to a copy of the RoutePath passed to us + * as an argument. + * + * Side effects: + * Allocates memory. + * + * ---------------------------------------------------------------------------- + */ + +RoutePath * +mzCopyPath(path) + RoutePath *path; +{ + RoutePath *newHead, *newPrev, *new; + + newPrev = newHead = (RoutePath *) NULL; + for (newPrev = NULL; path; newPrev = new, path = path->rp_back) + { + new = (RoutePath *) mallocMagic((unsigned)(sizeof (RoutePath))); + *new = *path; + if (newPrev) newPrev->rp_back = new; + if (newHead == NULL) newHead = new; + } + + return (newHead); +} + +/*--------------- Static variables only referenced by RPath allocation + and deallocation routines below ----------------------- */ + +/* First, last, and current RoutePages on list for allocating RoutePaths */ +RoutePage *mzFirstPage = NULL; +RoutePage *mzLastPage = NULL; +RoutePage *mzCurPage = NULL; + + +/* + * ---------------------------------------------------------------------------- + * + * mzAllocRPath -- + * + * Allocate a new RoutePath from our temporary RoutePath arena. + * + * Results: + * Returns a pointer to a newly allocated RoutePath. + * This RoutePath is NOT allocated directly via + * mallocMagic/freeMagic, + * but rather via our own temporary mechanism. It goes away + * once mzFreeAllTemp() gets called, so callers that wish to + * retain the "best" RoutePath must call mzCopyPath() to + * preserve it. + * + * Side effects: + * May allocate memory. + * + * ---------------------------------------------------------------------------- + */ + +RoutePath * +mzAllocRPath() +{ + /* Skip to next page if this one is full */ + if (mzCurPage && mzCurPage->rpp_free >= PATHSPERSEG) + mzCurPage = mzCurPage->rpp_next; + + /* If out of pages, allocate a new one */ + if (mzCurPage == NULL) + { + mzCurPage = (RoutePage *) mallocMagic((unsigned)(sizeof (RoutePage))); + mzCurPage->rpp_next = (RoutePage *) NULL; + mzCurPage->rpp_free = 0; + if (mzLastPage == NULL) + mzFirstPage = mzLastPage = mzCurPage; + else + mzLastPage->rpp_next = mzCurPage, mzLastPage = mzCurPage; + } + + return (&mzCurPage->rpp_array[mzCurPage->rpp_free++]); +} + +/* + * ---------------------------------------------------------------------------- + * + * mzFreeAllRPaths -- + * + * Reset the temporary arena used for allocating RoutePaths. + * + * Results: + * None. + * + * Side effects: + * Any RoutePaths in the arena become available again for + * allocation. Callers wishing to preserve paths must + * do so by calling mzCopyPath(). + * + * ---------------------------------------------------------------------------- + */ + +void +mzFreeAllRPaths() +{ + RoutePage *rpage; + + for (rpage = mzFirstPage; rpage; rpage = rpage->rpp_next) + { + /* Mark page of RoutePaths as being free */ + rpage->rpp_free = 0; + + /* Can stop after processing the last page used in this cycle */ + if (rpage == mzCurPage) + break; + } + + /* Start allocating again from the first page on the list */ + mzCurPage = mzFirstPage; +} + +/* + * ---------------------------------------------------------------------------- + * + * mzPresent -- + * + * Predicate, checkes if type corresponding to rL is set in touchingTypes + * mask. + * + * Results: + * TRUE if RL in touchingTypes, else FALSE + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +mzPresent(rL,touchingTypes) + RouteLayer *rL; + TileTypeBitMask *touchingTypes; +{ + List *l; + + /* return true if rL present */ + if(TTMaskHasType(touchingTypes, rL->rl_routeType.rt_tileType)) + return TRUE; + + /* return true if rL present as part of contact */ + for(l=rL->rl_contactL; l!=NULL; l=LIST_TAIL(l)) + { + RouteContact *rC = (RouteContact *)LIST_FIRST(l); + if(TTMaskHasType(touchingTypes, rC->rc_routeType.rt_tileType) && + (rC->rc_rLayer1==rL || rC->rc_rLayer2==rL)) + return TRUE; + } + + return FALSE; +} diff --git a/mzrouter/mzTech.c b/mzrouter/mzTech.c new file mode 100644 index 00000000..24daf80c --- /dev/null +++ b/mzrouter/mzTech.c @@ -0,0 +1,1397 @@ +/* + * mzTech.c -- + * + * Technology file read-in for the maze router. + * Processes mzrouter and drc sections of tech file to + * set up maze routing parameter sets. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzTech.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "wiring/wiring.h" +#include "utils/utils.h" +#include "utils/tech.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + +/* Procedures referenced before they are defined + * (these procedures are local to this file) + */ +RouteType *mzFindRouteType(); +RouteLayer *mzFindRouteLayer(); +RouteContact *mzFindRouteContact(); + +/* Techspacing structure - + * + * This structure is used to build a temporary list of spacings from + * spacing lines in the mzrouter section of the technology file. Spacings are + * copied to RouteTypes after technology readin completes. + */ +typedef struct techspacing +{ + RouteType *ts_routeType; + TileType ts_tileType; + int ts_spacing; + struct techspacing *ts_next; +} TechSpacing; +TechSpacing *mzTechSpacingList = NULL; /* Temporary list of explicit spacings. + * Generated by spacing lines in + * mzrouter + * section. Used in mzTechFinal to + * set spacings ispacings n RouteTypes + * after technology readin completes. + */ + +/* mask of all routetypes - referenced in this file only */ +TileTypeBitMask mzRTypesMask; /* And of bitmaps for tileTypes of + * all routeTypes of all styles + * (note image types for + * contacts included). + */ + +/* Forward declarations */ +extern void mzTechStyle(); +extern void mzStyleEnd(); +extern void mzSetParmDefaults(); +extern void mzTechLayer(); +extern void mzTechNotActive(); +extern void mzTechSpacing(); +extern void mzTechSearch(); +extern void mzTechWidth(); +extern void mzTechContact(); +extern void mzInitRouteType(); +extern void mzUpdateSpacing(); + +void mzWidthRule(int, char **); +void mzSpacingRule(int, char **); +void mzEdgeRule(int, char **); + +/* + * ---------------------------------------------------------------------------- + * + * MZFreeParameters --- + * + * Deallocate memory for a maze router style parameters structure. + * + * Results: + * None. + * + * Side effects: + * Memory free'd. + * + * ---------------------------------------------------------------------------- + */ + +void +MZFreeParameters(params) + MazeParameters *params; +{ + RouteLayer *rL; + RouteContact *rC; + + for (rL = params->mp_rLayers; rL; rL = rL->rl_next) + { + ListDealloc(rL->rl_contactL); + TiFreePlane(rL->rl_routeType.rt_hBlock); + TiFreePlane(rL->rl_routeType.rt_vBlock); + freeMagic(rL); + } + + for (rC = params->mp_rContacts; rC; rC = rC->rc_next) + freeMagic(rC); +} + + +/* + * ---------------------------------------------------------------------------- + * + * MZTechInit -- + * + * Initialize the technology datastructures for the maze router. + * This routine is made a client of the tech module in main/main.c. + * It is called when the beginning of the "mzrouter" section is encountered. + * + * Results: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +MZTechInit() +{ + MazeStyle *style; + + /* Clear out any old information */ + if (mzStyles != NULL) + { + for (style = mzStyles; style != NULL; style = style->ms_next) + { + MZFreeParameters(&(style->ms_parms)); + freeMagic(style->ms_name); + freeMagic(style); + } + } + + /* Initially no route types defined */ + mzRTypesMask = DBZeroTypeBits; + + /* Initially no maze styles are defined */ + mzStyles = NULL; + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * MZTechFinal -- + * + * Close out final style. + * This routine is made a client of the tech module in main/main.c. + * It is called when the end of the "mzrouter" section is encountered. + * + * Results: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +MZTechFinal() +{ + if(mzStyles) + { + mzStyleEnd(); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * MZAfterTech -- + * + * Finish up tech datastructures. + * This routine called by MZInit after tech file readin, or after grid + * rescaling, when the DRC rules are re-evaluated at the new scale. It + * derives all of the maze router width and spacing rules from the DRC + * rule set. + * + * Results: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +MZAfterTech() +{ + MazeStyle *style; + RouteType *rT; + int i, maxSpacing; + + /* Fill all width and spacing rules from DRC tables */ + + for(style=mzStyles; style!=NULL; style=style->ms_next) + { + for(rT=style->ms_parms.mp_rTypes; rT!=NULL; rT=rT->rt_next) + { + rT->rt_width = DRCGetDefaultLayerWidth(rT->rt_tileType); + for (i = 0; i < TT_MAXTYPES; i++) + rT->rt_spacing[i] = DRCGetDefaultLayerSpacing(rT->rt_tileType, i); + + /* We assume square contacts and no area minimums unless */ + /* specifically set by a wizard command (for now, at least) */ + rT->rt_length = rT->rt_width; + } + } + + /* Adjust spacings for all styles */ + + for(style=mzStyles; style!=NULL; style=style->ms_next) + { + List *l; + + /* add (non SUBCELL) spacings in spacingL to spacing + * arrays in RouteTypes */ + for(l=style->ms_spacingL; l!=NULL; l=LIST_TAIL(l)) + { + TechSpacing *tS = (TechSpacing *) LIST_FIRST(l); + + if(tS->ts_tileType != TT_SUBCELL) + { + tS->ts_routeType->rt_spacing[tS->ts_tileType] = tS->ts_spacing; + } + } + + /* Compute spacing to unexpanded subcells for each routeType + * = maximum of all spacings for that route type + */ + for(rT=style->ms_parms.mp_rTypes; rT!=NULL; rT=rT->rt_next) + { + maxSpacing = 0; + for(i=0;irt_spacing[i]); + rT->rt_spacing[TT_SUBCELL] = maxSpacing; + } + + /* add SUBCELL spacings in spacingL to spacing + * arrays in RouteTypes */ + for(l=style->ms_spacingL; l!=NULL; l=LIST_TAIL(l)) + { + TechSpacing *tS = (TechSpacing *) LIST_FIRST(l); + + if(tS->ts_tileType == TT_SUBCELL) + { + tS->ts_routeType->rt_spacing[tS->ts_tileType] = tS->ts_spacing; + } + } + + /* free up spacing list */ + ListDeallocC(style->ms_spacingL); + style->ms_spacingL = NULL; + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * MZTechLine -- + * + * This routine is made a client of the tech module in main/main.c. + * It is invoked during technology file readin, once for each line + * in the mzrouter section of the technology file. + * + * On each invocation one line of the "mzrouter" section is processed. + * + * Results: + * TRUE always. + * + * Side effects: + * An element is built and added to the RouteLayers or RouteContacts + * list. Or in the case of spacing request, the spacing is added to + * the deferred spacing list for processing in mzTechFinal after + * technology readin is completed. + * + * Note: + * The mzrouter section of the technology file must preceed the drc + * section. Thus the route layers and contacts are known prior + * to design rule processsing. + * + * ---------------------------------------------------------------------------- + */ + +bool +MZTechLine(sectionName, argc, argv) + char *sectionName; /* Unused */ + int argc; + char *argv[]; +{ + if(strcmp(argv[0], "style") == 0) + { + mzTechStyle(argc, argv); + } + else if(mzStyles == NULL) + { + TechError("Missing style line.\n"); + } + else if (strcmp(argv[0], "layer") == 0) + { + mzTechLayer(argc, argv); + } + else if (strcmp(argv[0], "contact") == 0) + { + mzTechContact(argc, argv); + } + else if (strcmp(argv[0], "notactive") == 0) + { + mzTechNotActive(argc, argv); + } + else if (strcmp(argv[0], "spacing") == 0) + { + mzTechSpacing(argc, argv); + } + else if (strcmp(argv[0], "search") == 0) + { + mzTechSearch(argc, argv); + } + else if (strcmp(argv[0], "width") == 0) + { + mzTechWidth(argc, argv); + } + else + { + TechError("Unrecognized keyword: \"%s\"\n", argv[0]); + } + + return (TRUE); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzTechStyle -- + * + * Process a "style" line from the "mzrouter" section of the tech file. + * Each set of lines in the "mzrouter" section of the tech file is headed + * by a style line that gives a name to the set of parameters. + * Style lines have the form: + * + * style + * + * Results: + * None. + * + * Side effects: + * Complete previous style and initial this one. + * + * ---------------------------------------------------------------------------- + */ + +void +mzTechStyle(argc, argv) + int argc; + char *argv[]; +{ + + /* if there is a previous style, complete processing on it */ + if(mzStyles) + { + mzStyleEnd(); + } + + /* alloc new style */ + { + MazeStyle *new; + new = (MazeStyle*) mallocMagic((unsigned)(sizeof (MazeStyle))); + + new->ms_name = StrDup(NULL, argv[1]); + new->ms_spacingL = NULL; + new->ms_next = mzStyles; + mzStyles = new; + } + + /* set default parameters */ + mzSetParmDefaults(&(mzStyles->ms_parms)); + + /* reset temporary lists */ + mzRouteLayers = NULL; + mzRouteContacts = NULL; + mzRouteTypes = NULL; + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzStyleEnd -- + * + * Close out style. (Saves temporary lists in parms for style.) + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +mzStyleEnd() +{ + /* Reverse mzRouteLayer, mzRouteContacts and mzRouteTypes lists + * so they are displayed in order they appear in tech file. + */ + { + RouteLayer *newRLList; + RouteContact *newRCList; + RouteType *newRTList; + + newRLList = NULL; + while(mzRouteLayers!=NULL) + { + RouteLayer *rL = mzRouteLayers; + mzRouteLayers = rL->rl_next; + rL->rl_next = newRLList; + newRLList = rL; + } + mzRouteLayers = newRLList; + + newRCList = NULL; + while(mzRouteContacts!=NULL) + { + RouteContact *rC = mzRouteContacts; + mzRouteContacts = rC->rc_next; + rC->rc_next = newRCList; + newRCList = rC; + } + mzRouteContacts = newRCList; + + newRTList = NULL; + while(mzRouteTypes!=NULL) + { + RouteType *rT = mzRouteTypes; + mzRouteTypes = rT->rt_next; + rT->rt_next = newRTList; + newRTList = rT; + } + mzRouteTypes = newRTList; + } + + /* Copy lists to parm structure for this style */ + mzStyles->ms_parms.mp_rLayers = mzRouteLayers; + mzStyles->ms_parms.mp_rContacts = mzRouteContacts; + mzStyles->ms_parms.mp_rTypes = mzRouteTypes; + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzSetParmDefaults -- + * + * Results: + * None. + * + * Side effects: + * Sets default parameter values. + * + * ---------------------------------------------------------------------------- + */ +void +mzSetParmDefaults(parms) + MazeParameters *parms; +{ + + /* initialize penalty factor for excess cost togo */ + parms->mp_penalty.rf_mantissa = DEF_PENALTY_MANTISSA; + parms->mp_penalty.rf_nExponent = DEF_PENALTY_NEXPONENT; + + /* Initialize other Search Control Parameters */ + parms->mp_wRate = (dlong) DEF_WINDOW_RATE; + parms->mp_wWidth = (dlong) DEF_WINDOW_WIDTH; + parms->mp_bloomDeltaCost = (dlong) DEF_BLOOM_DELTA_COST; + + /* initialize blockage generation increment */ + parms->mp_boundsIncrement = DEF_BOUNDS_INCREMENT; + + /* Estimation flags (if set nontrivial estimation used) */ + parms->mp_estimate = DEF_ESTIMATE; + + /* endpoint expansion flag, if set start and dest areas are + * expanded to include all electrically connected areas. + */ + parms->mp_expandEndpoints = DEF_EXPAND_ENDPOINTS; + + /* If set, only hints in toplevel cell are recognized */ + parms->mp_topHintsOnly = DEF_TOP_HINTS_ONLY; + + /* Maximum penetration into node (or subcell) blockage to reach + * destination. + */ + parms->mp_maxWalkLength = DEF_MAX_WALK_LENGTH; + + /* If nonnull, limits search area for performance + * NOTE: IF NONNULL, IT IS THE USERS RESPONSIBILITY TO CONFINE THE + * ROUTE TO WITHIN THIS AREA BY FENCES. + */ + parms->mp_boundsHint = NULL; + + /* Amount of messages printed */ + parms->mp_verbosity = DEF_VERBOSITY; + + /* If positive, limit on number of blooms during search */ + parms->mp_bloomLimit = DEF_BLOOM_LIMIT; + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzTechLayer -- + * + * Process a "layer" line from the "mzrouter" section of the tech file. + * A layer line defines a route layer. It has the following form: + * + * layer layername hcost vcost jogcost hintcost overcost + * + * Results: + * None. + * + * Side effects: + * Builds and adds an element to the RouteLayers list. + * RouteType also added to RouteTypes list. + * + * ---------------------------------------------------------------------------- + */ + +void +mzTechLayer(argc, argv) + int argc; + char *argv[]; +{ + RouteLayer *new; + TileType tileType; + + /* Check the argument count */ + if (argc < 4 || argc > 7) + { + TechError("Malformed \"layer\" line, should be: \"layer name hCost vCost [jogCost [hintCost [overCost]]]\"\n"); + return; + } + + /* get the tiletype */ + tileType = DBTechNoisyNameType(argv[1]); + if (tileType < 0) return; + + /* make sure we don't already have a routeLayer on same plane */ + { + RouteLayer *rL; + + for(rL=mzRouteLayers; rL!=NULL; rL=rL->rl_next) + { + if(DBTypePlaneTbl[rL->rl_routeType.rt_tileType] == + DBTypePlaneTbl[tileType]) + { + TechError("Attempt to define two route layers on same plane: %s and %s\n", + DBTypeLongNameTbl[tileType], + DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]); + return; + } + } + } + + /* Allocate new route layer */ + new = (RouteLayer *) callocMagic((unsigned) (sizeof (RouteLayer))); + + /* Initialize RouteType section */ + mzInitRouteType(&(new->rl_routeType),tileType); + + /* Initialize list of contacts connecting this layer to NULL */ + new->rl_contactL = NULL; + + /* set the plane */ + new->rl_planeNum = DBPlane(new->rl_routeType.rt_tileType); + if (new->rl_planeNum < 0) + { + TechError("Type \"%s\" appears on more than one plane\n", argv[1]); + return; + } + + /* set hCost */ + if (!StrIsInt(argv[2])) + { + TechError("Cost arguments to \"layer\" line must be numeric\n"); + return; + } + new->rl_hCost = atoi(argv[2]); + if (new->rl_hCost <= 0) + { + TechError("hCost must be > 0\n"); + return; + } + + /* set vCost */ + if (!StrIsInt(argv[3])) + { + TechError("Cost arguments to \"layer\" line must be numeric\n"); + return; + } + new->rl_vCost = atoi(argv[3]); + if (new->rl_vCost <= 0) + { + TechError("vCost must be > 0\n"); + return; + } + + /* Other costs are optional, and default to 1 */ + new->rl_jogCost = 1; + new->rl_hintCost = 1; + new->rl_overCost = 1; + + /* set jogCost */ + if (argc > 4) + { + if (!StrIsInt(argv[4])) + { + TechError("Cost arguments to \"layer\" line must be numeric\n"); + return; + } + new->rl_jogCost = atoi(argv[4]); + if (new->rl_jogCost <= 0) + { + TechError("jogCost must be > 0\n"); + return; + } + } + + /* set hintCost */ + if (argc > 5) + { + if (!StrIsInt(argv[5])) + { + TechError("Cost arguments to \"layer\" line must be numeric\n"); + return; + } + new->rl_hintCost = atoi(argv[5]); + if (new->rl_hintCost <= 0) + { + TechError("hintCost must be > 0\n"); + return; + } + } + + /* set overCost */ + if (argc > 6) + { + if (!StrIsInt(argv[6])) + { + TechError("Cost arguments to \"layer\" line must be numeric\n"); + return; + } + new->rl_overCost = atoi(argv[6]); + if (new->rl_overCost <= 0) + { + TechError("overCost must be > 0\n"); + return; + } + } + + /* Add new route layer to list */ + new->rl_next = mzRouteLayers; + mzRouteLayers = new; + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzTechNotActive -- + * + * Process a "notactive" line from the "mzrouter" section of the tech file. + * A notactive line specifies routetype(s) that are to be initially unavail. + * to the router. + * + * spacing routeType1 ... [routeTypen] + * + * Valid spacings are nonnegative integers, or "nil: if no spacing applies. + * + * Results: + * None. + * + * Side effects: + * Build and add an element to spacing list + * + * ---------------------------------------------------------------------------- + */ + +void +mzTechNotActive(argc, argv) + int argc; + char *argv[]; +{ + int argI; + TileType tileType; + RouteType *rT; + + /* check number of arguments */ + if(argc < 2) + { + TechError("Bad form on mzroute notactive.\n"); + TechError("Usage: notactive routeType1 ... [routeTypen]\n"); + return; + } + + /* process args */ + for(argI = 1; argIrt_active = FALSE; + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzTechSpacing -- + * + * Process a "spacing" line from the "mzrouter" section of the tech file. + * A spacing line defines spacings from a routetype (layer or contact) to + * other type(s). These spacings are stored on a list on technology readin + * and then actually set in the routeType structure after technology readin + * is complete. This is so they will overide default values based on the + * DRC section. + * + * spacing routeType type1 spacing1 ... [typen] [spacingn] + * + * Valid spacings are nonnegative integers, or "nil: if no spacing applies. + * + * Results: + * None. + * + * Side effects: + * Build and add an element to spacing list + * + * ---------------------------------------------------------------------------- + */ + +void +mzTechSpacing(argc, argv) + int argc; + char *argv[]; +{ + TechSpacing *new; + TileType tileType; + RouteType *rT; + int argI, value, which; + char *s; + + /* Subcell Table */ + static struct + { + char *sT_name; /* name of value */ + int sT_value; /* corresponding interger value */ + } subcellTable[] = { + "subcell", TT_SUBCELL, + 0 + }; + + /* check number of arguments */ + if(argc <4 || ODD(argc)) + { + TechError("Bad form on mzroute spacing.\n"); + TechError("Usage: spacing routeType type1 spacing1 ... [typen spacingn]\n"); + return; + } + + /* convert first arg to routeType */ + tileType = DBTechNoisyNameType(argv[1]); + if(tileType < 0) return; + rT = mzFindRouteType(tileType); + if(rT==NULL) + { + TechError("Unrecognized route type: \"%.20s\"\n", + argv[1]); + return; + } + + for(argI = 2; argI= 0) + tileType = TT_SUBCELL; + } + if(tileType<0) + { + TechError("Unrecognized layer (type): \"%.20s\"\n", + argv[argI]); + continue; + } + + /* convert argI+1 to value */ + s = argv[argI+1]; + value = -2; + if (StrIsInt(s)) + { + value = atoi(s); + if (value < 0) + { + TechError("Bad spacing value: %d\n",value); + TechError("Valid values are nonnegative integers and \"NIL\".\n"); + return; + } + } + else if (strcmp(s,"NIL")==0) + { + value = -1; + } + else + { + TechError("Bad spacing value: %s\n",s); + TechError("Valid values are nonnegative integers and \"NIL\".\n"); + return; + } + + /* add entry to spacing list */ + new = (TechSpacing*) mallocMagic((unsigned)(sizeof (TechSpacing))); + new->ts_routeType = rT; + new->ts_tileType = tileType; + new->ts_spacing = value; + LIST_ADD(new, mzStyles->ms_spacingL); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzTechSearch -- + * + * Process a "search" line from the "mzrouter" section of the tech file. + * A search line sets several parameters controlling the search. + * It has the form: + * + * search + * + * Rate and width must be positive integers, penalty a non-negative decimal. + * Search lines are optional, if none is given for a style default values + * are assigned. + * + * Results: + * None. + * + * Side effects: + * Set rate width and penalty parms for this style. + * + * ---------------------------------------------------------------------------- + */ + +void +mzTechSearch(argc, argv) + int argc; + char *argv[]; +{ + /* check number of arguments */ + if(argc != 4) + { + TechError("Bad form on search.\n"); + TechError("Usage: search \n"); + return; + } + + /* set WINDOW RATE */ + if (!StrIsInt(argv[1])) + { + TechError("Bad rate: %s\n",argv[1]); + TechError("Rate must be a positive integer.\n"); + } + else + { + int value = atoi(argv[1]); + if (value <= 0) + { + TechError("Bad rate: %d\n",value); + TechError("Rate must be a positive integer.\n"); + } + else + { + mzStyles->ms_parms.mp_wRate = (dlong) value; + } + } + + /* set WINDOW WIDTH */ + if (!StrIsInt(argv[2])) + { + TechError("Bad width: %s\n",argv[2]); + TechError("Width must be a positive integer.\n"); + } + else + { + int value = atoi(argv[2]); + if (value <= 0) + { + TechError("Bad width: %d\n",value); + TechError("Width must be a positive integer.\n"); + } + else + { + mzStyles->ms_parms.mp_wWidth = (dlong) value; + } + } + + /* set PENALTY */ + { + float value; + + if(sscanf(argv[3],"%f",&value)!=1) + { + TxError("Bad penalty value: %s\n",argv[3]); + TxError("Penalty must be non-negative decimal.\n"); + } + else + { + if(value<0) + { + TxError("Bad penalty value: %f\n", value); + TxError("Penalty must be non-negative decimal.\n"); + } + else + { + mzStyles->ms_parms.mp_penalty.rf_mantissa + = (int) (value * + (1<ms_parms.mp_penalty.rf_nExponent)); + } + } + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzTechWidth -- + * + * Process "width" line from the "mzrouter" section of the tech file. + * A width line defines a routing width for a given route type. It + * has the form. + * + * width + * + * Valid widths are positive integers. + * + * Results: + * None. + * + * Side effects: + * Set width for given routetype in current style. + * + * ---------------------------------------------------------------------------- + */ + +void +mzTechWidth(argc, argv) + int argc; + char *argv[]; +{ + TileType tileType; + RouteType *rT; + int value; + + /* check number of arguments */ + if (argc !=3 && argc != 4) + { + TechError("Bad form on mzroute width.\n"); + TechError("Usage: width []\n"); + return; + } + + /* convert first arg to routeType */ + tileType = DBTechNoisyNameType(argv[1]); + if(tileType < 0) return; + rT = mzFindRouteType(tileType); + if(rT==NULL) + { + TechError("Unrecognized route type: \"%.20s\"\n", + argv[1]); + return; + } + + /* convert 2nd arg to int */ + { + if (!StrIsInt(argv[2])) + { + TechError("Bad width: %s\n",argv[2]); + TechError("Width must be a positive integer.\n"); + return; + } + + value = atoi(argv[2]); + if (value <= 0) + { + TechError("Bad width: %d\n",value); + TechError("Width must be a positive integer.\n"); + return; + } + } + + /* set width */ + rT->rt_width = value; + + /* convert 3rd arg, if any, to int */ + if (argc == 4) + { + if (!StrIsInt(argv[3])) + { + TechError("Bad minimum length: %s\n",argv[3]); + TechError("Length must be a positive integer.\n"); + return; + } + + value = atoi(argv[3]); + if (value <= 0) + { + TechError("Bad minimum length: %d\n",value); + TechError("Length must be a positive integer.\n"); + return; + } + rT->rt_length = value; + } + else + { + /* By default, set minimum length requirement to width */ + rT->rt_length = rT->rt_width; + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzTechContact -- + * + * Process a "contact" line from the "mzrouter" section of the tech file. + * A contact line defines a contact between route layers. It has the form: + * + * contact conlayer routelayer1 routelayer2 cost + * + * Results: + * None. + * + * Side effects: + * Build and add an element to RouteContacts list. + * + * ---------------------------------------------------------------------------- + */ + +void +mzTechContact(argc, argv) + int argc; + char *argv[]; +{ + RouteContact *new; + TileType type, tileType; + + /* check arg count */ + if (argc != 5) + { + TechError("Malformed \"contact\" line, should be: contact layer " + "layer1 layer2 cost\n"); + return; + } + + /* get tiletype */ + tileType = DBTechNoisyNameType(argv[1]); + if(tileType < 0) return; + + /* allocate new route contact */ + new = (RouteContact *) callocMagic((unsigned) (sizeof (RouteContact))); + + /* initialize RouteType section: + * sets route type, initializes spacing array, etc. + */ + mzInitRouteType(&(new->rc_routeType),tileType); + + /* set first route layer */ + type = DBTechNoisyNameType(argv[2]); + if(type<0) return; + new->rc_rLayer1 = mzFindRouteLayer(type); + if (new->rc_rLayer1==NULL) + { + TechError("route layer must be declared before used in contact.\n"); + return; + } + + /* add this contact to contacts list of first route layer */ + LIST_ADD(new, new->rc_rLayer1->rl_contactL); + + /* set second route layer */ + type = DBTechNoisyNameType(argv[3]); + if(type<0) return; + new->rc_rLayer2 = mzFindRouteLayer(type); + if (new->rc_rLayer2==NULL) + { + TechError("route layer must be declared before used in contact.\n"); + return; + } + + /* add this contact to contacts list of second route layer */ + LIST_ADD(new, new->rc_rLayer2->rl_contactL); + + /* set cost */ + if (!StrIsInt(argv[4])) + { + TechError("Cost argument to \"contact\" line must be numeric\n"); + return; + } + new->rc_cost = atoi(argv[4]); + if (new->rc_cost <= 0) + { + TechError("Cost must be > 0\n"); + return; + } + + /* add route contact to list */ + new->rc_next = mzRouteContacts; + mzRouteContacts = new; + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzInitRouteType -- + * + * Initialize RouteType struc. + * + * Results: + * None. + * + * Side effects: + * Element added to mzRouteTypes list. + * Types ORed into mzRTypesMask. + * + * ---------------------------------------------------------------------------- + */ + +void +mzInitRouteType(rT,tileType) + RouteType *rT; + TileType tileType; +{ + int t; + + /* Get mask of all image types of routeType. + * RouteLayers will have one bit set in mask. RouteContacts will have + * two bits set, one for the contact "home" type, and one for the contact + * image type on the plane it connects to. + */ + TileTypeBitMask *imageTypeMask = &(DBLayerTypeMaskTbl[tileType]); + + /* set tileType */ + rT->rt_tileType = tileType; + + /* initialize as active */ + rT->rt_active = TRUE; + + /* initialize spacing array (gives spacing between + * RouteType and all tiletypes) + */ + for (t=0;t= 0 ) { + if(TTMaskIntersect(&(DBPlaneTypes[DBTypePlaneTbl[t]]),imageTypeMask) + && t!=TT_SPACE) + { + /* initialize to zero spacing - i.e. no overlap allowed */ + rT->rt_spacing[t] = 0; + } + else + { + /* otherwise no default spacing restriction applys */ + rT->rt_spacing[t] = -1; + } + } + } + + /* Initialize Blockage Planes */ + rT->rt_hBlock = DBNewPlane((ClientData) TT_SPACE); + rT->rt_vBlock = DBNewPlane((ClientData) TT_SPACE); + + /* Add to RouteType list */ + rT->rt_next = mzRouteTypes; + mzRouteTypes = rT; + + /* OR type and images into global route types mask */ + TTMaskSetMask(&mzRTypesMask,imageTypeMask); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzFindRouteType -- + * + * Search RouteLayer and RouteContact lists for routeType of given + * tile type. + * + * Results: + * pointer to routetype struc if found, else Null. + * + * ---------------------------------------------------------------------------- + */ + +RouteType * +mzFindRouteType(type) + TileType type; +{ + RouteType *rT; + + /* Search list of routetypes for one with appropriate type */ + for (rT = mzRouteTypes; + rT && rT->rt_tileType!=type; + rT=rT->rt_next) + ; + + /* return result */ + return(rT); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzFindRouteLayer -- + * + * Find routelayer struc for given tiletype. + * + * Results: + * pointer to routelayer struc if found, else Null. + * + * ---------------------------------------------------------------------------- + */ + +RouteLayer * +mzFindRouteLayer(type) + TileType type; +{ + RouteLayer *rL; + + /* Search list of routelayers for one with appropriate type */ + for (rL = mzRouteLayers; + rL && rL->rl_routeType.rt_tileType!=type; + rL=rL->rl_next) + ; + + /* return result */ + return(rL); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzFindRouteContact -- + * + * Find routecontact struc for given tiletype. + * + * Results: + * pointer to routecontact struc if found, else Null. + * + * ---------------------------------------------------------------------------- + */ + +RouteContact * +mzFindRouteContact(type) + TileType type; +{ + RouteContact *rC; + + /* Search list of routecontacts for one with appropriate type */ + for (rC = mzRouteContacts; + rC && rC->rc_routeType.rt_tileType!=type; + rC=rC->rc_next) + ; + + /* return result */ + return(rC); +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzUpdateSpacing -- + * + * Add spacing requirement to RouteType. + * (RouteTypes are routing layers and contact layers used by the router.) + * + * Results: + * None. + * + * SideEffects: + * RouteType struc modifed. + * + * ---------------------------------------------------------------------------- + */ + +void +mzUpdateSpacing(rType,tType,distance) + RouteType *rType; /* Route Type to which spacing applies */ + TileType tType; /* spacing from this tiletype */ + int distance; /* min spacing betweeen rType and tType */ +{ + rType->rt_spacing[tType] = + MAX(rType->rt_spacing[tType],distance); + +#ifdef debugmha + TxPrintf("UPDATESPACING:\n"); + TxPrintf("\troute type = %s\n",DBTypeLongNameTbl[rType->rt_tileType]); + TxPrintf("\tother type = %s\n",DBTypeLongNameTbl[tType]); + TxPrintf("\tdistance = %d\n",distance); +#endif /* debugmha */ + + return; +} + diff --git a/mzrouter/mzTestCmd.c b/mzrouter/mzTestCmd.c new file mode 100644 index 00000000..02e79438 --- /dev/null +++ b/mzrouter/mzTestCmd.c @@ -0,0 +1,619 @@ +/* + * mzTestCmd.c -- + * + * Code to process the `*mzroute' command. + * `*mzroute' is a wizard command for debugging and testing the maze router. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzTestCmd.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "irouter/irouter.h" +#include "graphics/graphics.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "dbwind/dbwtech.h" +#include "textio/txcommands.h" +#include "utils/main.h" +#include "utils/utils.h" +#include "commands/commands.h" +#include "utils/styles.h" +#include "utils/malloc.h" +#include "utils/list.h" +#include "utils/heap.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + +/* Subcommand table - declared here since its referenced before defined */ +typedef struct +{ + char *sC_name; /* name of iroute subcommand */ + void (*sC_proc)(); /* Procedure implementing this + subcommand */ + char *sC_commentString; + char *sC_usage; +} TestCmdTableE; +extern TestCmdTableE mzTestCommands[]; + + +/* + * ---------------------------------------------------------------------------- + * + * mzDebugTstCmd -- + * + * mzrouter wizard command (`:*mzroute') to set/clear debug flags. + * + * Results: + * None. + * + * Side effects: + * Modify debug flags. + * + * ---------------------------------------------------------------------------- + */ + +void +mzDebugTstCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int result; + bool value; + + if (cmd->tx_argc > 4) + { + TxPrintf("Too many args on '*mzroute debug'\n"); + return; + } + else if (cmd->tx_argc == 4) + { + /* two args, set or clear first arg according to second */ + + result = SetNoisyBool(&value,cmd->tx_argv[3], NULL); + if (result == 0) + { + TxPrintf("\n"); + DebugSet(mzDebugID,1,&(cmd->tx_argv[2]),(bool) value); + } + else + TxError("Bad boolean value %s---try true or false.\n", + cmd->tx_argv[3]); + } + else + { + /* list current values of flags */ + DebugShow(mzDebugID); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzDumpEstimatesTstCmd -- + * + * mzrouter wizard command (`:*mzroute') to dump estimate plane info + * associated with tiles under the box. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +mzDumpEstimatesTstCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (cmd->tx_argc > 2) + { + TxPrintf("Too many args on '*mzroute dumpEstimates'\n"); + return; + } + else + { + CellDef *boxDef; + Rect box; + + /* Use box for dump area */ + if(!ToolGetBox(&boxDef,&box)) + { + TxError("No Box.\n"); + return; + } + + /* Call dump routine to do the real work */ + mzDumpEstimates(&box,(FILE *) NULL); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzDumpTagsTstCmd -- + * + * mzrouter wizard command (`:*mzroute') to dump tag info + * associated with tiles under the box. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +mzDumpTagsTstCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (cmd->tx_argc > 2) + { + TxPrintf("Too many args on '*mzroute dumpTags'\n"); + return; + } + else + { + CellDef *boxDef; + Rect box; + + /* Use box for dump area */ + if(!ToolGetBox(&boxDef,&box)) + { + TxError("No Box.\n"); + return; + } + + /* Call dump routine to do the real work */ + mzDumpTags(&box); + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzHelpTstCmd -- + * + * mzrouter wizard command (`:*iroute') to print help info on mzrouter wizard + * commands. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +mzHelpTstCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int n; + int which; + + if(cmd->tx_argc == 2) + { + /* No arg, so print summary of commands */ + for(n=0; mzTestCommands[n].sC_name!=NULL; n++) + { + TxPrintf("*mzroute %s - %s\n", + mzTestCommands[n].sC_name, + mzTestCommands[n].sC_commentString); + } + TxPrintf("\n*mzroute help [subcmd] - "); + TxPrintf("Print usage info for subcommand.\n"); + } + else + { + /* Lookup subcommand in table, and printed associated help info */ + which = LookupStruct( + cmd->tx_argv[2], + (LookupTable *) mzTestCommands, + sizeof mzTestCommands[0]); + + /* Process result of lookup */ + if (which >= 0) + { + /* subcommand found - print out its comment string and usage */ + TxPrintf("*mzroute %s - %s\n", + mzTestCommands[which].sC_name, + mzTestCommands[which].sC_commentString); + TxPrintf("Usage: *mzroute %s\n", + mzTestCommands[which].sC_usage); + } + else if (which == -1) + { + /* ambiguous subcommand - complain */ + TxError("Ambiguous *mzroute subcommand: \"%s\"\n", + cmd->tx_argv[2]); + } + else + { + /* unrecognized subcommand - complain */ + TxError("Unrecognized iroute subcommand: \"%s\"\n", + cmd->tx_argv[2]); + TxError("Valid *mzroute subcommands are: "); + for (n = 0; mzTestCommands[n].sC_name; n++) + TxError(" %s", mzTestCommands[n].sC_name); + TxError("\n"); + } + } + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzNumberLineTstCmd -- + * + * mzrouter wizard command (`:*mzroute') to exercise numberline code. + * + * Results: + * None. + * + * Side effects: + * fiddle with some number lines. + * + * ---------------------------------------------------------------------------- + */ + +void +mzNumberLineTstCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + NumberLine myLine; + int *result; + + mzNLInit(&myLine, 2); + + TxPrintf("Inserting 10\n"); + mzNLInsert(&myLine, 10); + + TxPrintf("Inserting 10\n"); + mzNLInsert(&myLine, 10); + + TxPrintf("Inserting -10\n"); + mzNLInsert(&myLine, -10); + + TxPrintf("Inserting 0\n"); + mzNLInsert(&myLine, 0); + + TxPrintf("Inserting 20\n"); + mzNLInsert(&myLine, 20); + + TxPrintf("Inserting -20\n"); + mzNLInsert(&myLine, -20); + + TxPrintf("Inserting 0\n"); + mzNLInsert(&myLine, 0); + + result = mzNLGetContainingInterval(&myLine, 35); + TxPrintf("query = 35, result = (%d, %d)\n", + *result, *(result+1)); + + result = mzNLGetContainingInterval(&myLine, -35); + TxPrintf("query = -35, result = (%d, %d)\n", + *result, *(result+1)); + + result = mzNLGetContainingInterval(&myLine, 0); + TxPrintf("query = 0, result = (%d, %d)\n", + *result, *(result+1)); + + result = mzNLGetContainingInterval(&myLine, 5); + TxPrintf("query = 5, result = (%d, %d)\n", + *result, *(result+1)); + + result = mzNLGetContainingInterval(&myLine, 12); + TxPrintf("query = 12, result = (%d, %d)\n", + *result, *(result+1)); + + result = mzNLGetContainingInterval(&myLine, -12); + TxPrintf("query = -12, result = (%d, %d)\n", + *result, *(result+1)); + + result = mzNLGetContainingInterval(&myLine, 20); + TxPrintf("query = 20, result = (%d, %d)\n", + *result, *(result+1)); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzParmsTstCmd -- + * + * mzrouter wizard command (`:*mzroute') to dump current route types. + * + * Results: + * None. + * + * Side effects: + * Dump routelayers and routecontacts. + * + * ---------------------------------------------------------------------------- + */ + +void +mzParmsTstCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + + MZPrintRLs(mzRouteLayers); + TxMore(""); + MZPrintRCs(mzRouteContacts); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzPlaneTstCmd -- + * + * mzrouter wizard command (`:*mzroute') to display internal tile structure + * of a blockage plane. + * + * Results: + * None. + * + * Side effects: + * Dump routelayers and routecontacts. + * + * ---------------------------------------------------------------------------- + */ + +void +mzPlaneTstCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + TileType t; + RouteType *rT; + char *layerName; + + /* check number of args */ + if(cmd->tx_argc != 3) + { + TxError("Usage: *mzroute plane route-layer"); + TxError("makes corresponding blockage plane visible)\n "); + return; + } + + /* Get layer name from args*/ + layerName = cmd->tx_argv[2]; + + /* convert name to type */ + t = DBTechNameType(layerName); + if(t == -1) + { + TxPrintf("`%s' is ambiguous\n",layerName); + return; + } + if(t == -2) + { + TxPrintf("`%s' type not recognized\n",layerName); + return; + } + + /* convert type to route type */ + rT = mzFindRouteType(t); + if(rT == NULL) + { + TxPrintf("`%s' is not a routeType ", layerName); + TxPrintf("- so there is no associated blockage plane.\n"); + return; + } + + /* Attach Blockage plane of routeType to "__BLOCK" cell for display */ + mzBlockDef->cd_planes[PL_M_HINT] = rT->rt_hBlock; + + /* Display it */ + DBWAreaChanged(mzBlockDef, + &TiPlaneRect, + DBW_ALLWINDOWS, + &DBAllButSpaceBits); + WindUpdate(); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzVersionCmd -- + * + * mzrouter wizard subcommand (`*mzroute version') to display mzrouter + * version string. + * + * Results: + * None. + * + * Side effects: + * Displays version string. + * + * ---------------------------------------------------------------------------- + */ + +void +mzVersionCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + + if(cmd->tx_argc == 2) + { + /* Print out version string */ + TxPrintf("\tMzrouter version %s\n", MZROUTER_VERSION); + } + else + { + TxPrintf("Too many args on 'mzroute version'\n"); + } + + return; +} + + + +/* + * ---------------------------------------------------------------------------- + * + * MZTest -- + * + * Command interface for testing the maze router. + * + * Results: + * None. + * + * Side effects: + * Depends on the command; see below. + * + * Organization: + * We select a procedure based on the first keyword (argv[0]) + * and call it to do the work of implementing the rule. Each + * such procedure is of the following form: + * + * int + * proc(argc, argv) + * int argc; + * char *argv[]; + * { + * } + * + * ---------------------------------------------------------------------------- + */ + +/*--------------------------- Command Table ------------------------------ */ + +TestCmdTableE mzTestCommands[] = { + "debug", mzDebugTstCmd, + "set or clear debug flags", + "debug [flag] [value]", + + "dumpEstimates", mzDumpEstimatesTstCmd, + "print global estimate info for tiles under box", + "dumpEstimates", + + "dumpTags", mzDumpTagsTstCmd, + "print tag info on data tiles under box", + "dumpTags", + + "help", mzHelpTstCmd, + "summarize *mzroute subcommands", + "help [subcommand]", + + "numberLine", mzNumberLineTstCmd, + "exercise numberline code", + "numberLine", + + "parms", mzParmsTstCmd, + "print internal data structures", + "parms", + + "plane", mzPlaneTstCmd, + "make internal tile plane visible", + "plane [plane]", + + "version", mzVersionCmd, + "identify mzrouter version", + "version", + + 0 + }, *mzTestCmdP; + +void +MZTest(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int n; + int which; + + + if(cmd->tx_argc == 1) + { + /* No subcommand specified. */ + TxPrintf("Must specify subcommand."); + TxPrintf(" (type '*mzroute help' for summary)\n"); + } + else + { + /* Lookup subcommand in table */ + which = LookupStruct( + cmd->tx_argv[1], + (LookupTable *) mzTestCommands, + sizeof mzTestCommands[0]); + + /* Process result of lookup */ + if (which >= 0) + { + /* subcommand found - call proc that implements it */ + mzTestCmdP = &mzTestCommands[which]; + (*mzTestCmdP->sC_proc)(w,cmd); + } + else if (which == -1) + { + /* ambiguous subcommand - complain */ + TxError("Ambiguous subcommand: \"%s\"\n", cmd->tx_argv[1]); + } + else + { + /* unrecognized subcommand - complain */ + TxError("Unrecognized subcommand: \"%s\"\n", cmd->tx_argv[1]); + TxError("Valid subcommands:"); + for (n = 0; mzTestCommands[n].sC_name; n++) + TxError(" %s", mzTestCommands[n].sC_name); + TxError("\n"); + } + } + + return; +} diff --git a/mzrouter/mzWalk.c b/mzrouter/mzWalk.c new file mode 100644 index 00000000..65dfd38d --- /dev/null +++ b/mzrouter/mzWalk.c @@ -0,0 +1,690 @@ +/* + * mzWalk.c -- + * + * Code for Completing final legs of route within the blocked areas ajacent to + * dest areas. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header:"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + + +/* + * ---------------------------------------------------------------------------- + * + * mzWalkRight -- + * + * Extend path inside a to-the-right walk. + * + * Results: + * None. + * + * Side effects: + * mzAddPoint() called to add extended path to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +void +mzWalkRight(path) + RoutePath *path; +{ + Point pOrg; /* point to extend from */ + Point pNew; /* next interesting point in direction of extension */ + dlong segCost; /* cost of segment between pOrg and pNew */ + int extendCode; /* Interesting directions to extend in */ + Tile *tpThis; /* Tile containing org point */ + + /* DEBUG - trace calls to this routine. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("WALKING RIGHT\n"); + + /* pOrg = current end of path */ + pOrg = path->rp_entry; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_hBlock,&pOrg); + + /* org point should be in walk to left of dest area */ + ASSERT(TiGetType(tpThis)==TT_LEFT_WALK,"mzWalkRight"); + + /* traverse to right edge of this walk to get to dest area */ + pNew.p_x = RIGHT(tpThis); + pNew.p_y = pOrg.p_y; + + /* mark as complete path */ + extendCode = EC_COMPLETE; + + /* compute cost of path segment from pOrg to pNew */ + { + Tile *tp; + bool rotate; + + tp = TiSrPointNoHint(mzVRotatePlane, &pOrg); + rotate = (TiGetType(tp) != TT_SPACE); + + if (rotate) + segCost = (dlong) ((pNew.p_x - pOrg.p_x) * + path->rp_rLayer->rl_vCost); + else + segCost = (dlong) ((pNew.p_x - pOrg.p_x) * + path->rp_rLayer->rl_hCost); + } + + /* Compute additional cost for paralleling nearest hint segment */ + /* (Start at low end of segment and move to high end computing hint cost + * as we go) + */ + { + Tile *tp; + dlong hintCost; + int deltaUp, deltaDown, delta; + Point lowPt; + + for(lowPt = pOrg; lowPt.p_x < pNew.p_x; lowPt.p_x = RIGHT(tp)) + { + /* find tile in hint plane containing lowPt */ + tp = TiSrPointNoHint(mzVHintPlane,&lowPt); + + /* find nearest hint segment and add appropriate cost */ + if(TiGetType(tp) != TT_MAGNET) + { + deltaUp = (TiGetType(RT(tp)) == TT_MAGNET) ? + TOP(tp) - lowPt.p_y : -1; + deltaDown = (TiGetType(LB(tp)) == TT_MAGNET) ? + lowPt.p_y - BOTTOM(tp) : -1; + + /* delta = distance to nearest hint */ + if (deltaUp < 0) + { + if (deltaDown < 0) + delta = 0; + else + delta = deltaDown; + } + else + { + if (deltaDown < 0) + delta = deltaUp; + else + delta = MIN(deltaUp,deltaDown); + } + + if(delta>0) + { + hintCost = (dlong) ((MIN(RIGHT(tp),pNew.p_x) - lowPt.p_x) * + path->rp_rLayer->rl_hintCost); + hintCost *= delta; + segCost += hintCost; + } + } + } + } + + /* Process the new point */ + mzAddPoint(path, &pNew, path->rp_rLayer, 'H', extendCode, &segCost); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzWalkLeft -- + * + * Extend path inside a to-the-left walk. + * + * Results: + * None. + * + * Side effects: + * mzAddPoint() called to add extended path to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +void +mzWalkLeft(path) + RoutePath *path; +{ + Point pOrg; /* point to extend from */ + Point pNew; /* next interesting point in direction of extension */ + dlong segCost; /* cost of segment between pOrg and pNew */ + int extendCode; /* Interesting directions to extend in */ + Tile *tpThis; /* Tile containing org point */ + RouteType *rtype; /* Structure of material type at destination */ + + /* DEBUG - trace calls to this routine. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("WALKING LEFT\n"); + + /* pOrg = current end of path */ + pOrg = path->rp_entry; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_hBlock,&pOrg); + rtype = &path->rp_rLayer->rl_routeType; + + /* org point should be in walk to right of dest area */ + ASSERT(TiGetType(tpThis)==TT_RIGHT_WALK,"mzWalkLeft"); + + /* traverse just past left edge of this walk to get to dest area */ + + pNew.p_x = LEFT(tpThis) - 1; + pNew.p_y = pOrg.p_y; + + /* mark as complete path */ + extendCode = EC_COMPLETE; + + /* compute cost of path segment from pOrg to pNew */ + { + Tile *tp; + bool rotate; + + tp = TiSrPointNoHint(mzVRotatePlane, &pOrg); + rotate = (TiGetType(tp) != TT_SPACE); + + if (rotate) + segCost = (dlong) ((pOrg.p_x - pNew.p_x) * + path->rp_rLayer->rl_vCost); + else + segCost = (dlong) ((pOrg.p_x - pNew.p_x) * + path->rp_rLayer->rl_hCost); + } + + /* Compute additional cost for paralleling nearest hint segment */ + /* (Start at low end of segment and move to high end computing hint cost + * as we go) + */ + { + Tile *tp; + dlong hintCost; + int deltaUp, deltaDown, delta; + Point lowPt; + + for(lowPt = pNew; lowPt.p_x < pOrg.p_x; lowPt.p_x = RIGHT(tp)) + { + /* find tile in hint plane containing lowPt */ + tp = TiSrPointNoHint(mzVHintPlane,&lowPt); + + /* find nearest hint segment and add appropriate cost */ + if(TiGetType(tp) != TT_MAGNET) + { + deltaUp = (TiGetType(RT(tp)) == TT_MAGNET) ? + TOP(tp) - lowPt.p_y : -1; + deltaDown = (TiGetType(LB(tp)) == TT_MAGNET) ? + lowPt.p_y - BOTTOM(tp) : -1; + + /* delta = distance to nearest hint */ + if (deltaUp < 0) + { + if (deltaDown < 0) + delta = 0; + else + delta = deltaDown; + } + else + { + if (deltaDown < 0) + delta = deltaUp; + else + delta = MIN(deltaUp,deltaDown); + } + + if(delta>0) + { + hintCost = (dlong) ((MIN(RIGHT(tp),pOrg.p_x) - lowPt.p_x) * + path->rp_rLayer->rl_hintCost); + hintCost *= delta; + segCost += hintCost; + } + } + } + } + + /* Process the new point */ + mzAddPoint(path, &pNew, path->rp_rLayer, 'H', extendCode, &segCost); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzWalkUp -- + * + * Extend path inside a up-walk. + * + * Results: + * None. + * + * Side effects: + * mzAddPoint() called to add extended path to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +void +mzWalkUp(path) + RoutePath *path; +{ + Point pOrg; /* point to extend from */ + Point pNew; /* next interesting point in direction of extension */ + dlong segCost; /* cost of segment between pOrg and pNew */ + int extendCode; /* Interesting directions to extend in */ + Tile *tpThis; /* Tile containing org point */ + + /* DEBUG - trace calls to this routine. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("WALKING UP\n"); + + /* pOrg = current end of path */ + pOrg = path->rp_entry; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_vBlock,&pOrg); + + /* org point should be in walk to left of dest area */ + ASSERT(TiGetType(tpThis)==TT_BOTTOM_WALK,"mzWalkUp"); + + /* traverse to top edge of this walk to get to dest area */ + pNew.p_x = pOrg.p_x; + pNew.p_y = TOP(tpThis); + + /* mark as complete path */ + extendCode = EC_COMPLETE; + + /* compute cost of path segment from pOrg to pNew */ + { + Tile *tp; + bool rotate; + + tp = TiSrPointNoHint(mzHRotatePlane, &pOrg); + rotate = (TiGetType(tp) != TT_SPACE); + + if (rotate) + segCost = (dlong) ((pNew.p_y - pOrg.p_y) * + path->rp_rLayer->rl_hCost); + else + segCost = (dlong) ((pNew.p_y - pOrg.p_y) * + path->rp_rLayer->rl_vCost); + } + + /* Compute additional cost for paralleling nearest hint segment */ + /* (Start at low end of segment and move to high end computing hint cost + * as we go) + */ + { + Tile *tp; + dlong hintCost; + int deltaRight, deltaLeft, delta; + Point lowPt; + + for(lowPt = pOrg; lowPt.p_y < pNew.p_y; lowPt.p_y = TOP(tp)) + { + /* find tile in hint plane containing lowPt */ + tp = TiSrPointNoHint(mzHHintPlane,&lowPt); + + /* find nearest hint segment and add appropriate cost */ + if(TiGetType(tp) != TT_MAGNET) + { + deltaRight = (TiGetType(TR(tp)) == TT_MAGNET) ? + RIGHT(tp) - lowPt.p_x : -1; + deltaLeft = (TiGetType(BL(tp)) == TT_MAGNET) ? + lowPt.p_x - LEFT(tp) : -1; + + /* delta = distance to nearest hint */ + if (deltaRight < 0) + { + if (deltaLeft < 0) + delta = 0; + else + delta = deltaLeft; + } + else + { + if (deltaLeft < 0) + delta = deltaRight; + else + delta = MIN(deltaRight,deltaLeft); + } + + if(delta>0) + { + hintCost = (dlong) ((MIN(TOP(tp),pNew.p_y) - lowPt.p_y) * + path->rp_rLayer->rl_hintCost); + hintCost *= delta; + segCost += hintCost; + } + } + } + } + + /* Process the new point */ + mzAddPoint(path, &pNew, path->rp_rLayer, 'V', extendCode, &segCost); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzWalkDown -- + * + * Extend path inside a down-walk. + * + * Results: + * None. + * + * Side effects: + * mzAddPoint() called to add extended path to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +void +mzWalkDown(path) + RoutePath *path; +{ + Point pOrg; /* point to extend from */ + Point pNew; /* next interesting point in direction of extension */ + dlong segCost; /* cost of segment between pOrg and pNew */ + int extendCode; /* Interesting directions to extend in */ + Tile *tpThis; /* Tile containing org point */ + RouteType *rtype; /* Structure of material at destination */ + + /* DEBUG - trace calls to this routine. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("WALKING DOWN\n"); + + /* pOrg = current end of path */ + pOrg = path->rp_entry; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_vBlock,&pOrg); + rtype = &path->rp_rLayer->rl_routeType; + + /* org point should be in walk to left of dest area */ + ASSERT(TiGetType(tpThis)==TT_TOP_WALK,"mzWalkDown"); + + /* traverse to just past edge of this walk to get to dest area */ + pNew.p_x = pOrg.p_x; + pNew.p_y = BOTTOM(tpThis) - 1; + + /* mark as complete path */ + extendCode = EC_COMPLETE; + + /* compute cost of path segment from pOrg to pNew */ + { + Tile *tp; + bool rotate; + + tp = TiSrPointNoHint(mzHRotatePlane, &pOrg); + rotate = (TiGetType(tp) != TT_SPACE); + + if (rotate) + segCost = (dlong) ((pOrg.p_y - pNew.p_y) * + path->rp_rLayer->rl_hCost); + else + segCost = (dlong) ((pOrg.p_y - pNew.p_y) * + path->rp_rLayer->rl_vCost); + } + + /* Compute additional cost for paralleling nearest hint segment */ + /* (Start at low end of segment and move to high end computing hint cost + * as we go) + */ + { + Tile *tp; + dlong hintCost; + int deltaRight, deltaLeft, delta; + Point lowPt; + + for(lowPt = pNew; lowPt.p_y < pOrg.p_y; lowPt.p_y = TOP(tp)) + { + /* find tile in hint plane containing lowPt */ + tp = TiSrPointNoHint(mzHHintPlane,&lowPt); + + /* find nearest hint segment and add appropriate cost */ + if(TiGetType(tp) != TT_MAGNET) + { + deltaRight = (TiGetType(TR(tp)) == TT_MAGNET) ? + RIGHT(tp) - lowPt.p_x : -1; + deltaLeft = (TiGetType(BL(tp)) == TT_MAGNET) ? + lowPt.p_x - LEFT(tp) : -1; + + /* delta = distance to nearest hint */ + if (deltaRight < 0) + { + if (deltaLeft < 0) + delta = 0; + else + delta = deltaLeft; + } + else + { + if (deltaLeft < 0) + delta = deltaRight; + else + delta = MIN(deltaRight,deltaLeft); + } + + if(delta>0) + { + hintCost = (dlong) ((MIN(TOP(tp),pOrg.p_y) - lowPt.p_y) * + path->rp_rLayer->rl_hintCost); + hintCost *= delta; + segCost += hintCost; + } + } + } + } + + /* Process the new point */ + mzAddPoint(path, &pNew, path->rp_rLayer, 'V', extendCode, &segCost); + + return; +} + + +/* + * ---------------------------------------------------------------------------- + * + * mzWalkLRContact -- + * + * Extend path to dest area (above or below) via contact. + * + * Results: + * None. + * + * Side effects: + * mzAddPoint() called to add extended path to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +void +mzWalkLRContact(path) + RoutePath *path; +{ + Point pOrg; /* point to extend from */ + int extendCode; /* Interesting directions to extend in */ + RouteContact *rC; /* Route contact to make connection with */ + RouteLayer *newRL; /* Route layer of dest area */ + dlong conCost; /* Cost of final contact */ + int walkType; /* TT_ABOVE_LR_WALK or TT_BELOW_LR_WALK */ + Tile *tpThis; /* Tile containing org point */ + Tile *tpCont; /* Tile allowing contact placement */ + + /* DEBUG - trace calls to this routine. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("WALKING HOME VIA LR CONTACT\n"); + + /* pOrg = current end of path */ + pOrg = path->rp_entry; + + /* get blockage plane tile under pOrg. Contact walks were painted */ + /* into the hBlock plane. */ + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_hBlock,&pOrg); + + walkType = TiGetType(tpThis); + + /* find contact type that connects to route layer. */ + for(rC=mzRouteContacts; rC!=NULL; rC=rC->rc_next) + { + /* if not active, skip it */ + if(!(rC->rc_routeType.rt_active)) continue; + + /* if it doesn't connect to both current and dest layers, skip it */ + if((walkType == TT_BELOW_LR_WALK) && (rC->rc_rLayer1 != path->rp_rLayer)) + continue; + + if((walkType == TT_ABOVE_LR_WALK) && (rC->rc_rLayer2 != path->rp_rLayer)) + continue; + + /* if contact blocked, skip it */ + tpCont = TiSrPointNoHint(rC->rc_routeType.rt_hBlock, &pOrg); + if (TiGetType(tpCont) == TT_BLOCKED) + continue; + + /* if contact is non-square and doesn't fit, skip it */ + if (RIGHT(tpThis) - pOrg.p_x <= rC->rc_routeType.rt_length + - rC->rc_routeType.rt_width) + continue; + + /* if we got this far we found our contact, break out of the loop */ + break; + } + + /* There should always be an rC that works */ + ASSERT(rC!=NULL,"mzWalkLRContact"); + + if (rC == NULL) return; /* For now, non-square contacts may cause this + * point to be reached. Fix in mzBlock.c? + */ + + /* Compute the new route layer */ + newRL = (rC->rc_rLayer1 != path->rp_rLayer) ? rC->rc_rLayer1 : rC->rc_rLayer2; + + /* compute contact cost */ + conCost = (dlong) rC->rc_cost; + + /* Add final point */ + mzAddPoint(path, &pOrg, newRL, 'O', EC_COMPLETE, &conCost); + + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * mzWalkUDContact -- + * + * Extend path to dest area (above or below) via contact. + * + * Results: + * None. + * + * Side effects: + * mzAddPoint() called to add extended path to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +void +mzWalkUDContact(path) + RoutePath *path; +{ + Point pOrg; /* point to extend from */ + int extendCode; /* Interesting directions to extend in */ + RouteContact *rC; /* Route contact to make connection with */ + RouteLayer *newRL; /* Route layer of dest area */ + dlong conCost; /* Cost of final contact */ + int walkType; /* TT_ABOVE_UD_WALK or TT_BELOW_UD_WALK */ + Tile *tpThis; /* Tile containing org point */ + Tile *tpCont; /* Tile allowing contact placement */ + + /* DEBUG - trace calls to this routine. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("WALKING HOME VIA UD CONTACT\n"); + + /* pOrg = current end of path */ + pOrg = path->rp_entry; + + /* get blockage plane tile under pOrg. Contact walks were painted */ + /* into the hBlock plane. */ + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_vBlock,&pOrg); + + walkType = TiGetType(tpThis); + + /* find contact type that connects to route layer. */ + for(rC=mzRouteContacts; rC!=NULL; rC=rC->rc_next) + { + /* if not active, skip it */ + if(!(rC->rc_routeType.rt_active)) continue; + + /* if it doesn't connect to both current and dest layers, skip it */ + if((walkType == TT_BELOW_UD_WALK) && (rC->rc_rLayer1 != path->rp_rLayer)) + continue; + + if((walkType == TT_ABOVE_UD_WALK) && (rC->rc_rLayer2 != path->rp_rLayer)) + continue; + + /* if contact blocked, skip it */ + tpCont = TiSrPointNoHint(rC->rc_routeType.rt_vBlock, &pOrg); + if (TiGetType(tpCont) == TT_BLOCKED) + continue; + + /* if contact is non-square and doesn't fit, skip it */ + if (TOP(tpThis) - pOrg.p_y <= rC->rc_routeType.rt_length + - rC->rc_routeType.rt_width) + continue; + + /* if we got this far we found our contact, break out of the loop */ + break; + } + + /* There should always be an rC that works */ + ASSERT(rC!=NULL,"mzWalkUDContact"); + + if (rC == NULL) return; /* For now, non-square contacts may cause this + * point to be reached. Fix in mzBlock.c? + */ + + /* Compute the new route layer */ + newRL = (rC->rc_rLayer1 != path->rp_rLayer) ? rC->rc_rLayer1 : rC->rc_rLayer2; + + /* compute contact cost */ + conCost = (dlong) rC->rc_cost; + + /* Add final point */ + mzAddPoint(path, &pOrg, newRL, 'X', EC_COMPLETE, &conCost); + + return; +} diff --git a/mzrouter/mzXtndDown.c b/mzrouter/mzXtndDown.c new file mode 100644 index 00000000..f67527dc --- /dev/null +++ b/mzrouter/mzXtndDown.c @@ -0,0 +1,634 @@ +/* + * mzExtendDown.c -- + * + * Code for finding next interesting point down. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzXtndDown.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendDown -- + * + * Find next interesting point down. + * + * Results: + * None. + * + * Side effects: + * mzAddPoint() called to added extended path to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +void +mzExtendDown(path) + RoutePath *path; +{ + Point pOrg; /* point to extend from */ + Point pStep; /* one unit from pOrg in direction of extension */ + Point pNew; /* next interesting point in direction of extension */ + dlong segCost; /* cost of segment between pOrg and pNew */ + RouteLayer *rL; /* temp variable for routelayers */ + int reasons; /* Reasons point is interesting. Used to + * avoid extensions in uninteresting directions. + */ + int extendCode; /* Interesting directions to extend in */ + bool overroute = FALSE; /* Is crossing another route layer */ + TileType ntype; + Tile *tpThis; + + /* DEBUG - trace calls to this routine. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("EXTENDING DOWN\n"); + + /* pOrg = current end of path */ + pOrg = path->rp_entry; + + /* pStep = point just one unit beyond pOrg */ + pStep = pOrg; + --(pStep.p_y); + + /* Initial pNew to BOUNDS edge. Must stop there + * since blockage planes haven't been generated past there. + */ + { + Tile *tp; + + /* get bounds tile under pOrg */ + tp = TiSrPointNoHint(mzVBoundsPlane, &pOrg); + pNew.p_x = pOrg.p_x; + pNew.p_y = BOTTOM(tp); + reasons = RC_BOUNDS; + } + + /* + * Initial pNew to next pt where there is a change in the amount of + * space on the BLOCKAGE plane in the direction perpendicular to the + * extension. (A special case of this is a actual block + * of the extension). Want to consider jogs at such points. + * + */ + { + Tile *tpNext; + bool covered; + + /* get tpThis, extending bounds plane and iterating, until + * completely covered by bounds plane. + */ + covered = FALSE; + while(!covered) + { + Tile *tpBounds; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_hBlock, + &pOrg); + + /* org point should not be blocked */ + ASSERT(TiGetType(tpThis) == TT_SPACE, "mzExtendDown"); + + /* check to see if covered, if not extend bounds and start over */ + covered = TRUE; + tpBounds = TiSrPointNoHint(mzHBoundsPlane, &pOrg); + while(covered && TOP(tpBounds)>=BOTTOM(tpThis) && + TOP(tpBounds)>=mzRouteUse->cu_def->cd_bbox.r_ybot) + { + if(TiGetType(tpBounds) == TT_SPACE) + { + /* hit edge of bounds before jog found */ + goto downEndJog; + } + else if(RIGHT(tpBounds)<=RIGHT(tpThis) && + RIGHT(tpBounds)<=mzRouteUse->cu_def->cd_bbox.r_xtop) + { + Point p; + + p.p_x = RIGHT(tpBounds); + p.p_y = MIN(TOP(tpBounds), pOrg.p_y); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + else if(LEFT(tpBounds)>=LEFT(tpThis) && + LEFT(tpBounds)>=mzRouteUse->cu_def->cd_bbox.r_xbot) + { + Point p; + p.p_x = LEFT(tpBounds); + p.p_y = MIN(TOP(tpBounds), pOrg.p_y); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + + /* move to next tile in bounds plane */ + if(covered) + { + NEXT_TILE_DOWN(tpBounds, tpBounds, pOrg.p_x); + } + } + } + + /* also get next tile over */ + NEXT_TILE_DOWN(tpNext, tpThis, pOrg.p_x); + ntype = TiGetType(tpNext); + + if ((ntype != TT_SPACE) && (ntype != TT_SAMENODE)) + { + /* path blocked */ + if(BOTTOM(tpThis)==pOrg.p_y) + { + /* pOrg right up against block */ + if(ntype==TT_TOP_WALK) + { + /* Block is walk, enter it */ + pNew.p_y = pOrg.p_y - 1; + reasons = RC_WALK; + goto donePruning; + } + else if (ntype == TT_ABOVE_UD_WALK || + ntype == TT_BELOW_UD_WALK) + { + /* Block is contact walk, enter it */ + pNew.p_y = pOrg.p_y - 1; + reasons = RC_WALKUDC; + goto donePruning; + } + else if (ntype == TT_ABOVE_LR_WALK || + ntype == TT_BELOW_LR_WALK) + { + /* Block is contact walk, enter it */ + pNew.p_y = pOrg.p_y - 1; + reasons = RC_WALKLRC; + goto donePruning; + } + else if (ntype == TT_DEST_AREA) + { + /* Block is destination, enter it */ + pNew.p_y = pOrg.p_y - 1; + reasons = RC_DONE; + goto donePruning; + } + else + { + /* Path blocked from expansion, just return */ + return; + } + } + else + { + /* prune pNew to just this side of block */ + PRUNE_TO_MAX(pNew.p_y, BOTTOM(tpThis), reasons, RC_JOG); + } + } + else + { + /* path not blocked */ + if((RIGHT(tpNext)LEFT(tpThis)) && + BOTTOM(tpThis)rl_nextActive) + { + Tile *tpNext; + TileType tpType; + bool covered; + + /* skip current layer (already handled above) */ + if(rL == path->rp_rLayer) + { + continue; + } + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(rL->rl_routeType.rt_hBlock, + &pOrg); + + tpType = TiGetType(tpThis); + + if ((tpType != TT_SPACE) && (tpType != TT_SAMENODE)) + { + /* ORG POINT BLOCKED */ + /* this case handled by contact code below, so skip to next layer*/ + + continue; + } + else + { + /* ORG POINT NOT BLOCKED, LOOK FOR NARROWING OR GROWING OF SPACE */ + + /* get tpThis, extending bounds plane and iterating, until + * completely covered by bounds plane. + */ + covered = FALSE; + while(!covered) + { + Tile *tpBounds; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(rL->rl_routeType.rt_hBlock, &pOrg); + + /* org point should not be blocked */ + ASSERT(TiGetType(tpThis)==TT_SPACE,"mzExtendDown, other"); + + /* check to see if covered, + if not extend bounds and start over */ + covered = TRUE; + tpBounds = TiSrPointNoHint(mzHBoundsPlane, &pOrg); + while(covered && TOP(tpBounds)>=BOTTOM(tpThis) && + TOP(tpBounds)>=mzRouteUse->cu_def->cd_bbox.r_ybot) + { + if(TiGetType(tpBounds) == TT_SPACE) + { + /* hit edge of bounds before jog found */ + goto downNextLayer; + } + else if(RIGHT(tpBounds)<=RIGHT(tpThis) && + RIGHT(tpBounds)<= + mzRouteUse->cu_def->cd_bbox.r_xtop) + { + Point p; + + p.p_x = RIGHT(tpBounds); + p.p_y = MIN(TOP(tpBounds), pOrg.p_y); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + else if(LEFT(tpBounds)>=LEFT(tpThis) && + LEFT(tpBounds)>=mzRouteUse->cu_def->cd_bbox.r_xbot) + { + Point p; + p.p_x = LEFT(tpBounds); + p.p_y = MIN(TOP(tpBounds), pOrg.p_y); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + + /* move to next tile in bounds plane */ + if(covered) + { + NEXT_TILE_DOWN(tpBounds, tpBounds, pOrg.p_x); + } + } + } + + /* get next tile over */ + NEXT_TILE_DOWN(tpNext, tpThis, pOrg.p_x); + ntype = TiGetType(tpNext); + + if ((ntype != TT_SPACE) && (ntype != TT_SAMENODE)) + { + /* path blocked */ + if(BOTTOM(tpThis)==pOrg.p_y) + { + /* pOrg right up against obstacle, can't extend so + go to next layer */ + continue; + } + else + { + /* prune pNew to just this side of block */ + PRUNE_TO_MAX(pNew.p_y, + BOTTOM(tpThis), + reasons, + RC_ALIGNOTHER); + } + } + else + { + /* path not blocked */ + if((RIGHT(tpNext)LEFT(tpThis)) + && BOTTOM(tpThis)rp_rLayer->rl_contactL; cL!=NULL; cL=LIST_TAIL(cL)) + { + /* find tile in contact blockage plane under pOrg */ + tp = TiSrPointNoHint( + ((RouteContact*) LIST_FIRST(cL))->rc_routeType.rt_hBlock, + &pStep); + tpType = TiGetType(tp); + + if ((tpType == TT_SPACE) || (tpType == TT_SAMENODE)) + { + /* SPACE TILE */ + if(TOP(tp)-1 < pOrg.p_y) + /* prune to beginning of tile */ + PRUNE_TO_MAX(pNew.p_y, TOP(tp)-1, reasons, RC_CONTACT); + else + /* prune to end of tile */ + PRUNE_TO_MAX(pNew.p_y, BOTTOM(tp), reasons, RC_CONTACT); + } + else + { + /* BLOCK TILE - so prune to just beyond tile */ + PRUNE_TO_MAX(pNew.p_y, BOTTOM(tp)-1, reasons, RC_CONTACT); + if (tpType == TT_BLOCKED) overroute = TRUE; + } + } + } + + donePruning:; + /* DONE PRUNING pNew */ + + /* debug - print point and reasons its interesting. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("Done Pruning, new point: (%d, %d) ", + pNew.p_x, pNew.p_y); + TxPrintf("is interesting because:\n "); + if(reasons & RC_JOG) + { + TxPrintf("jog "); + } + if(reasons & RC_ALIGNOTHER) + { + TxPrintf("alignOther "); + } + if(reasons & RC_CONTACT) + { + TxPrintf("contact "); + } + if(reasons & RC_ALIGNGOAL) + { + TxPrintf("alignGoal "); + } + if(reasons & RC_HINT) + { + TxPrintf("hint "); + } + if(reasons & RC_ROTBEFORE) + { + TxPrintf("rotBefore "); + } + if(reasons & RC_ROTINSIDE) + { + TxPrintf("rotInside "); + } + if(reasons & RC_BOUNDS) + { + TxPrintf("bounds "); + } + if(reasons & RC_WALK) + { + TxPrintf("walk "); + } + if(reasons & RC_WALKLRC || reasons & RC_WALKUDC) + { + TxPrintf("walkc "); + } + if(reasons & RC_DONE) + { + TxPrintf("done "); + } + TxPrintf("\n"); + } + + /* Compute extend code - i.e. interesting directions to extend from + * new point */ + if(reasons & (RC_WALK | RC_WALKLRC | RC_WALKUDC | RC_DONE)) + { + if(reasons & RC_WALK) + { + extendCode = EC_WALKDOWN; + } + else if(reasons & RC_WALKUDC) + { + extendCode = EC_WALKUDCONTACT; + } + else if(reasons & RC_WALKLRC) + { + extendCode = EC_WALKLRCONTACT; + } + else + { + extendCode = EC_COMPLETE; + } + } + else + { + /* initial with just straight ahead */ + extendCode = EC_DOWN; + + if(reasons & (RC_ALIGNOTHER | RC_CONTACT | RC_ALIGNGOAL | + RC_HINT | RC_ROTINSIDE)) + { + extendCode |= EC_UDCONTACTS | EC_LRCONTACTS; + } + + if(reasons & (RC_JOG | RC_ALIGNGOAL | RC_HINT | RC_ROTINSIDE)) + { + extendCode |= EC_RIGHT | EC_LEFT; + } + } + + /* If we end inside SAMENODE, then the cost at this point is */ + /* set to zero, if we are at the start or if the previous cost was */ + /* zero. */ + + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_hBlock, &pNew); + if (TiGetType(tpThis) == TT_SAMENODE) + if ((!path->rp_back) || (path->rp_back->rp_cost == (dlong)0)) + path->rp_cost = (dlong)0; + + /* compute cost of path segment from pOrg to pNew */ + { + Tile *tp; + bool rotate; + + tp = TiSrPointNoHint(mzHRotatePlane, &pOrg); + rotate = (TiGetType(tp) != TT_SPACE); + + if (rotate) + segCost = (dlong) ((pOrg.p_y - pNew.p_y) * path->rp_rLayer->rl_hCost); + else if (overroute) + segCost = (dlong) ((pOrg.p_y - pNew.p_y) * path->rp_rLayer->rl_overCost); + else + segCost = (dlong) ((pOrg.p_y - pNew.p_y) * path->rp_rLayer->rl_vCost); + } + + /* Compute additional cost for paralleling nearest hint segment */ + /* (Start at low end of segment and move to high end computing hint cost + * as we go) + */ + { + Tile *tp; + dlong hintCost; + int deltaRight, deltaLeft, delta; + Point lowPt; + + for(lowPt = pNew; lowPt.p_y < pOrg.p_y; lowPt.p_y = TOP(tp)) + { + /* find tile in hint plane containing lowPt */ + tp = TiSrPointNoHint(mzHHintPlane,&lowPt); + + /* find nearest hint segment and add appropriate cost */ + if(TiGetType(tp) != TT_MAGNET) + { + deltaRight = (TiGetType(TR(tp)) == TT_MAGNET) ? + RIGHT(tp) - lowPt.p_x : -1; + deltaLeft = (TiGetType(BL(tp)) == TT_MAGNET) ? + lowPt.p_x - LEFT(tp) : -1; + + /* delta = distance to nearest hint */ + if (deltaRight < 0) + { + if (deltaLeft < 0) + delta = 0; + else + delta = deltaLeft; + } + else + { + if (deltaLeft < 0) + delta = deltaRight; + else + delta = MIN(deltaRight,deltaLeft); + } + + if(delta>0) + { + hintCost = (dlong) ((MIN(TOP(tp),pOrg.p_y) - lowPt.p_y) * + path->rp_rLayer->rl_hintCost); + hintCost = (dlong)(hintCost * delta); + segCost += hintCost; + } + } + } + } + + /* Process the new point */ + mzAddPoint(path, &pNew, path->rp_rLayer, 'V', extendCode, &segCost); + + return; +} + diff --git a/mzrouter/mzXtndLeft.c b/mzrouter/mzXtndLeft.c new file mode 100644 index 00000000..ba5ed7ea --- /dev/null +++ b/mzrouter/mzXtndLeft.c @@ -0,0 +1,639 @@ +/* + * mzExtendLeft.c -- + * + * Code for finding next interesting point to left. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzXtndLeft.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendLeft -- + * + * Find next interesting point to the left. + * + * Results: + * None. + * + * Side effects: + * mzAddPoint() called to added extended path to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +void +mzExtendLeft(path) + RoutePath *path; +{ + Point pOrg; /* point to extend from */ + Point pStep; /* one unit from pOrg in direction of extension */ + Point pNew; /* next interesting point in direction of extension */ + dlong segCost; /* cost of segment between pOrg and pNew */ + RouteLayer *rL; /* temp variable for routelayers */ + int reasons; /* Reasons point is interesting. Used to + * avoid extensions in uninteresting directions. + */ + int extendCode; /* Interesting directions to extend in */ + bool overroute = FALSE; /* Is crossing another route layer */ + TileType ntype; + Tile *tpThis; + + /* DEBUG - trace calls to this routine. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("EXTENDING LEFT\n"); + + /* pOrg = current end of path */ + pOrg = path->rp_entry; + + /* pStep = point just one unit beyond pOrg */ + pStep = pOrg; + --(pStep.p_x); + + + /* Initial pNew to BOUNDS edge. Must stop there + * since blockage planes haven't been generated past there. + */ + { + Tile *tp; + + /* get bounds tile under pOrg */ + tp = TiSrPointNoHint(mzHBoundsPlane, &pOrg); + pNew.p_x = LEFT(tp); + pNew.p_y = pOrg.p_y; + reasons = RC_BOUNDS; + } + + /* + * Initial pNew to next pt where there is a change in the amount of + * space on the BLOCKAGE plane in the direction perpendicular to the + * extension. (A special case of this is an actual block + * of the extension). Want to consider jogs at such points. + * + */ + { + Tile *tpNext; + bool covered; + + /* get tpThis, extending bounds plane and iterating, until + * completely covered by bounds plane. + */ + covered = FALSE; + while(!covered) + { + Tile *tpBounds; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_vBlock, + &pOrg); + + /* org point should not be blocked */ + ASSERT(TiGetType(tpThis) == TT_SPACE, "mzExtendLeft"); + + + /* check to see if covered, if not extend bounds and start over */ + covered = TRUE; + tpBounds = TiSrPointNoHint(mzVBoundsPlane, &pOrg); + while(covered && RIGHT(tpBounds)>=LEFT(tpThis) && + RIGHT(tpBounds)>=mzRouteUse->cu_def->cd_bbox.r_xbot) + { + if(TiGetType(tpBounds) == TT_SPACE) + { + /* hit edge of bounds before jog found */ + goto leftEndJog; + } + else if(TOP(tpBounds)<=TOP(tpThis) && + TOP(tpBounds)<=mzRouteUse->cu_def->cd_bbox.r_ytop) + { + Point p; + + p.p_x = MIN(RIGHT(tpBounds), pOrg.p_x); + p.p_y = TOP(tpBounds); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + else if(BOTTOM(tpBounds)>=BOTTOM(tpThis) && + BOTTOM(tpBounds)>=mzRouteUse->cu_def->cd_bbox.r_ybot) + { + Point p; + p.p_x = MIN(RIGHT(tpBounds), pOrg.p_x); + p.p_y = BOTTOM(tpBounds); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + + /* move to next tile in bounds plane */ + if(covered) + { + NEXT_TILE_LEFT(tpBounds, tpBounds, pOrg.p_y); + } + } + } + + /* also get next tile over */ + NEXT_TILE_LEFT(tpNext, tpThis, pOrg.p_y); + ntype = TiGetType(tpNext); + + if ((ntype != TT_SPACE) && (ntype != TT_SAMENODE)) + { + /* path blocked */ + if (LEFT(tpThis) == pOrg.p_x) + { + /* pOrg right up against block */ + if (ntype == TT_RIGHT_WALK) + { + /* Block is walk, enter it */ + pNew.p_x = pOrg.p_x - 1; + reasons = RC_WALK; + goto donePruning; + } + else if (ntype == TT_ABOVE_LR_WALK || + ntype == TT_BELOW_LR_WALK) + { + /* Block is contact walk, enter it */ + pNew.p_x = pOrg.p_x - 1; + reasons = RC_WALKLRC; + goto donePruning; + } + else if (ntype == TT_ABOVE_UD_WALK || + ntype == TT_BELOW_UD_WALK) + { + /* Block is contact walk, enter it */ + pNew.p_x = pOrg.p_x - 1; + reasons = RC_WALKUDC; + goto donePruning; + } + else if (ntype == TT_DEST_AREA) + { + /* Block is destination, enter it */ + pNew.p_x = pOrg.p_x - 1; + reasons = RC_DONE; + goto donePruning; + } + else + { + /* Path blocked from expansion, just return */ + return; + } + } + else + { + /* prune pNew to just this side of block */ + PRUNE_TO_MAX(pNew.p_x, LEFT(tpThis), reasons, RC_JOG); + } + } + else + { + /* path not blocked */ + if((TOP(tpNext)BOTTOM(tpThis)) && + LEFT(tpThis)rl_nextActive) + { + Tile *tpNext; + TileType tpType; + bool covered; + + /* skip current layer (already handled above) */ + if(rL == path->rp_rLayer) + { + continue; + } + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(rL->rl_routeType.rt_vBlock, + &pOrg); + + tpType = TiGetType(tpThis); + + if ((tpType != TT_SPACE) && (tpType != TT_SAMENODE)) + { + /* ORG POINT BLOCKED */ + /* this case handled by contact code below, so skip to next layer*/ + + continue; + } + else + { + /* ORG POINT NOT BLOCKED, LOOK FOR NARROWING OR GROWING OF SPACE */ + + /* get tpThis, extending bounds plane and iterating, until + * completely covered by bounds plane. + */ + covered = FALSE; + while(!covered) + { + Tile *tpBounds; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(rL->rl_routeType.rt_vBlock, + &pOrg); + + /* org point should not be blocked */ + ASSERT(TiGetType(tpThis)==TT_SPACE, + "mzExtendLeft, others"); + + /* check to see if covered, + if not extend bounds and start over */ + covered = TRUE; + tpBounds = TiSrPointNoHint(mzVBoundsPlane, &pOrg); + while(covered && RIGHT(tpBounds)>=LEFT(tpThis) && + RIGHT(tpBounds)>=mzRouteUse->cu_def->cd_bbox.r_xbot) + { + if(TiGetType(tpBounds) == TT_SPACE) + { + /* hit edge of bounds before jog found */ + goto leftNextLayer; + } + else if(TOP(tpBounds)<=TOP(tpThis) && + TOP(tpBounds)<=mzRouteUse->cu_def->cd_bbox.r_ytop) + { + Point p; + + p.p_x = MIN(RIGHT(tpBounds), pOrg.p_x); + p.p_y = TOP(tpBounds); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + else if(BOTTOM(tpBounds)>=BOTTOM(tpThis) && + BOTTOM(tpBounds)>= + mzRouteUse->cu_def->cd_bbox.r_ybot) + { + Point p; + p.p_x = MIN(RIGHT(tpBounds), pOrg.p_x); + p.p_y = BOTTOM(tpBounds); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + + /* move to next tile in bounds plane */ + if(covered) + { + NEXT_TILE_LEFT(tpBounds, tpBounds, pOrg.p_y); + } + } + } + + /* get next tile over */ + NEXT_TILE_LEFT(tpNext, tpThis, pOrg.p_y); + ntype = TiGetType(tpNext); + + if ((ntype != TT_SPACE) && (ntype != TT_SAMENODE)) + { + /* path blocked */ + if(LEFT(tpThis)==pOrg.p_x) + { + /* pOrg right up against obstacle, can't extend so + go to next layer */ + continue; + } + else + { + /* prune pNew to just this side of block */ + PRUNE_TO_MAX(pNew.p_x, + LEFT(tpThis), + reasons, + RC_ALIGNOTHER); + } + } + else + { + /* path not blocked */ + if((TOP(tpNext)BOTTOM(tpThis)) + && LEFT(tpThis)rp_rLayer->rl_contactL; cL!=NULL; cL=LIST_TAIL(cL)) + { + /* find tile in contact blockage plane under pOrg */ + tp = TiSrPointNoHint( + ((RouteContact*) LIST_FIRST(cL))->rc_routeType.rt_hBlock, + &pStep); + tpType = TiGetType(tp); + + if ((tpType == TT_SPACE) || (tpType == TT_SAMENODE)) + { + /* SPACE TILE */ + if(RIGHT(tp)-1 < pOrg.p_x) + /* prune to beginning of tile */ + PRUNE_TO_MAX(pNew.p_x, RIGHT(tp)-1, reasons, RC_CONTACT); + else + /* prune to end of tile */ + PRUNE_TO_MAX(pNew.p_x, LEFT(tp), reasons, RC_CONTACT); + } + else + { + /* BLOCK TILE - so prune to just beyond tile */ + PRUNE_TO_MAX(pNew.p_x, LEFT(tp)-1, reasons, RC_CONTACT); + if (tpType == TT_BLOCKED) overroute = TRUE; + } + } + } + + donePruning:; + /* DONE PRUNING pNew */ + + /* debug - print point and reasons its interesting. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("Done Pruning, new point: (%d, %d) ", + pNew.p_x, pNew.p_y); + TxPrintf("is interesting because:\n "); + if(reasons & RC_JOG) + { + TxPrintf("jog "); + } + if(reasons & RC_ALIGNOTHER) + { + TxPrintf("alignOther "); + } + if(reasons & RC_CONTACT) + { + TxPrintf("contact "); + } + if(reasons & RC_ALIGNGOAL) + { + TxPrintf("alignGoal "); + } + if(reasons & RC_HINT) + { + TxPrintf("hint "); + } + if(reasons & RC_ROTBEFORE) + { + TxPrintf("rotBefore "); + } + if(reasons & RC_ROTINSIDE) + { + TxPrintf("rotInside "); + } + if(reasons & RC_BOUNDS) + { + TxPrintf("bounds "); + } + if(reasons & RC_WALK) + { + TxPrintf("walk "); + } + if(reasons & RC_WALKLRC || reasons & RC_WALKUDC) + { + TxPrintf("walkc "); + } + if(reasons & RC_DONE) + { + TxPrintf("done "); + } + TxPrintf("\n"); + } + + /* Compute extend code - i.e. interesting directions to extend from + * new point */ + if(reasons & (RC_WALK | RC_WALKUDC | RC_WALKLRC | RC_DONE)) + { + if(reasons & RC_WALK) + { + extendCode = EC_WALKLEFT; + } + else if(reasons & RC_WALKUDC) + { + extendCode = EC_WALKUDCONTACT; + } + else if(reasons & RC_WALKLRC) + { + extendCode = EC_WALKLRCONTACT; + } + else + { + extendCode = EC_COMPLETE; + } + } + else + { + /* initial with just straight ahead */ + extendCode = EC_LEFT; + + if(reasons & (RC_ALIGNOTHER | RC_CONTACT | RC_ALIGNGOAL | + RC_HINT | RC_ROTINSIDE)) + { + extendCode |= EC_UDCONTACTS | EC_LRCONTACTS; + } + + if(reasons & (RC_JOG | RC_ALIGNGOAL | RC_HINT | RC_ROTINSIDE)) + { + extendCode |= EC_UP | EC_DOWN; + } + } + + /* If we end inside SAMENODE, then the cost to this point is */ + /* zeroed, and that section of the path will not be painted. */ + + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_vBlock, &pNew); + if (TiGetType(tpThis) == TT_SAMENODE) + if ((!path->rp_back) || (path->rp_back->rp_cost == (dlong)0)) + path->rp_cost = (dlong)0; + + /* compute cost of path segment from pOrg to pNew */ + { + Tile *tp; + bool rotate; + + tp = TiSrPointNoHint(mzVRotatePlane, &pOrg); + rotate = (TiGetType(tp) != TT_SPACE); + + if (rotate) + segCost = (dlong) ((pOrg.p_x - pNew.p_x) * + path->rp_rLayer->rl_vCost); + else if (overroute) + segCost = (dlong) ((pOrg.p_x - pNew.p_x) * + path->rp_rLayer->rl_overCost); + else + segCost = (dlong) ((pOrg.p_x - pNew.p_x) * + path->rp_rLayer->rl_hCost); + } + + /* Compute additional cost for paralleling nearest hint segment */ + /* (Start at low end of segment and move to high end computing hint cost + * as we go) + */ + { + Tile *tp; + dlong hintCost; + int deltaUp, deltaDown, delta; + Point lowPt; + + for(lowPt = pNew; lowPt.p_x < pOrg.p_x; lowPt.p_x = RIGHT(tp)) + { + /* find tile in hint plane containing lowPt */ + tp = TiSrPointNoHint(mzVHintPlane,&lowPt); + + /* find nearest hint segment and add appropriate cost */ + if(TiGetType(tp) != TT_MAGNET) + { + deltaUp = (TiGetType(RT(tp)) == TT_MAGNET) ? + TOP(tp) - lowPt.p_y : -1; + deltaDown = (TiGetType(LB(tp)) == TT_MAGNET) ? + lowPt.p_y - BOTTOM(tp) : -1; + + /* delta = distance to nearest hint */ + if (deltaUp < 0) + { + if (deltaDown < 0) + delta = 0; + else + delta = deltaDown; + } + else + { + if (deltaDown < 0) + delta = deltaUp; + else + delta = MIN(deltaUp,deltaDown); + } + + if(delta>0) + { + hintCost = (dlong) ((MIN(RIGHT(tp),pOrg.p_x) - lowPt.p_x) * + path->rp_rLayer->rl_hintCost); + hintCost *= delta; + segCost += hintCost; + } + } + } + } + + /* Process the new point */ + mzAddPoint(path, &pNew, path->rp_rLayer, 'H', extendCode, &segCost); + + return; +} diff --git a/mzrouter/mzXtndRght.c b/mzrouter/mzXtndRght.c new file mode 100644 index 00000000..df35929b --- /dev/null +++ b/mzrouter/mzXtndRght.c @@ -0,0 +1,634 @@ +/* + * mzExtendRight.c -- + * + * Code for finding next interesting point to the right. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzXtndRght.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendRight -- + * + * Find next interesting point to the right. + * + * Results: + * None. + * + * Side effects: + * mzAddPoint() called to added extended path to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +void +mzExtendRight(path) +RoutePath *path; +{ + Point pOrg; /* point to extend from */ + Point pStep; /* one unit from pOrg in direction of extension */ + Point pNew; /* next interesting point in direction of extension */ + dlong segCost; /* cost of segment between pOrg and pNew */ + RouteLayer *rL; /* temp variable for routelayers */ + int reasons; /* Reasons point is interesting. Used to + * avoid extensions in uninteresting directions. + */ + int extendCode; /* Interesting directions to extend in */ + bool overroute = FALSE; /* Is crossing another route layer */ + TileType ntype; + Tile *tpThis; + + /* debug - trace calls to this routine. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("EXTENDING RIGHT\n"); + } + + /* pOrg = current end of path */ + pOrg = path->rp_entry; + + /* pStep = point just one unit beyond pOrg */ + pStep = pOrg; + ++(pStep.p_x); + + /* Initial pNew to BOUNDS edge. Must stop there + * since blockage planes haven't been generated past there. + */ + { + Tile *tp; + + /* get bounds tile under pOrg */ + tp = TiSrPointNoHint(mzHBoundsPlane, &pOrg); + pNew.p_x = RIGHT(tp); + pNew.p_y = pOrg.p_y; + reasons = RC_BOUNDS; + } + + /* + * Initial pNew to next pt where there is a change in the amount of + * space on the BLOCKAGE plane in the direction perpendicular to the + * extension. (A special case of this is a actual block + * of the extension). Want to consider jogs at such points. + * + */ + { + Tile *tpNext; + bool covered; + + /* get tpThis, extending bounds plane and iterating, until + * completely covered by bounds plane. + */ + covered = FALSE; + while(!covered) + { + Tile *tpBounds; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_vBlock, + &pOrg); + + /* org point should not be blocked */ + ASSERT(TiGetType(tpThis) == TT_SPACE, "mzExtendRght"); + + + /* check to see if covered, if not extend bounds and start over */ + covered = TRUE; + tpBounds = TiSrPointNoHint(mzVBoundsPlane, &pOrg); + while(covered && LEFT(tpBounds)<=RIGHT(tpThis) && + LEFT(tpBounds)<=mzRouteUse->cu_def->cd_bbox.r_xtop) + { + if(TiGetType(tpBounds) == TT_SPACE) + { + /* hit edge of bounds before jog found */ + goto rightEndJog; + } + else if(TOP(tpBounds)<=TOP(tpThis) && + TOP(tpBounds)<=mzRouteUse->cu_def->cd_bbox.r_ytop) + { + Point p; + + p.p_x = MAX(LEFT(tpBounds), pOrg.p_x); + p.p_y = TOP(tpBounds); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + else if(BOTTOM(tpBounds)>=BOTTOM(tpThis) && + BOTTOM(tpBounds)>=mzRouteUse->cu_def->cd_bbox.r_ybot) + { + Point p; + p.p_x = MAX(LEFT(tpBounds), pOrg.p_x); + p.p_y = BOTTOM(tpBounds); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + + /* move to next tile in bounds plane */ + if(covered) + { + NEXT_TILE_RIGHT(tpBounds, tpBounds, pOrg.p_y); + } + } + } + + /* also get next tile over */ + NEXT_TILE_RIGHT(tpNext, tpThis, pOrg.p_y); + ntype = TiGetType(tpNext); + + if ((ntype != TT_SPACE) && (ntype != TT_SAMENODE)) + { + /* path blocked */ + if (LEFT(tpNext) == pStep.p_x) + { + /* pOrg right up against block */ + if (ntype == TT_LEFT_WALK) + { + /* Block is walk, enter it */ + pNew.p_x = pOrg.p_x + 1; + reasons = RC_WALK; + goto donePruning; + } + else if (ntype == TT_ABOVE_LR_WALK || + ntype == TT_BELOW_LR_WALK) + { + /* Block is contact walk, enter it */ + pNew.p_x = pOrg.p_x + 1; + reasons = RC_WALKLRC; + goto donePruning; + } + else if (ntype == TT_ABOVE_UD_WALK || + ntype == TT_BELOW_UD_WALK) + { + /* Block is contact walk, enter it */ + pNew.p_x = pOrg.p_x + 1; + reasons = RC_WALKUDC; + goto donePruning; + } + else if (ntype == TT_DEST_AREA) + { + /* Block is detination, enter it */ + pNew.p_x = pOrg.p_x + 1; + reasons = RC_DONE; + goto donePruning; + } + else + { + /* Path blocked from expansion, just return */ + return; + } + } + else + { + /* prune pNew to just this side of block */ + PRUNE_TO_MIN(pNew.p_x, LEFT(tpNext)-1, reasons, RC_JOG); + } + } + else + { + /* path not blocked */ + if((TOP(tpNext)BOTTOM(tpThis)) && + RIGHT(tpThis)-1>pOrg.p_x) + { + /* space is constricting, prune pNew to far + * end of this tile + */ + PRUNE_TO_MIN(pNew.p_x, LEFT(tpNext)-1, reasons, RC_JOG); + } + else + { + /* prune to just inside next tile */ + PRUNE_TO_MIN(pNew.p_x, LEFT(tpNext), reasons, RC_JOG); + } + } + rightEndJog:; + } + + /* + * Prune pNew to next pt where there is a change in the amount of + * space on other active BLOCKAGE planes in the direction perpendicular + * to the + * extension. (A special case of this is a actual block + * of the extension). Want to consider jogs at such points. + * + */ + for(rL=mzActiveRLs; rL!=NULL; rL=rL->rl_nextActive) + { + Tile *tpNext; + TileType tpType; + bool covered; + + /* skip current layer (already handled above) */ + if(rL == path->rp_rLayer) + { + continue; + } + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(rL->rl_routeType.rt_vBlock, + &pOrg); + tpType = TiGetType(tpThis); + + if ((tpType != TT_SPACE) && (tpType != TT_SAMENODE)) + { + /* ORG POINT BLOCKED */ + /* this case handled by contact code below, so skip to next layer*/ + + continue; + } + else + { + /* ORG POINT NOT BLOCKED, LOOK FOR NARROWING OR GROWING OF SPACE */ + + /* get tpThis, extending bounds plane and iterating, until + * completely covered by bounds plane. + */ + covered = FALSE; + while(!covered) + { + Tile *tpBounds; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(rL->rl_routeType.rt_vBlock, + &pOrg); + + /* org point should not be blocked */ + ASSERT(TiGetType(tpThis)==TT_SPACE, + "mzExtendRight, others"); + + /* check to see if covered, + if not extend bounds and start over */ + covered = TRUE; + tpBounds = TiSrPointNoHint(mzVBoundsPlane, &pOrg); + while(covered && LEFT(tpBounds)<=RIGHT(tpThis) && + LEFT(tpBounds)<=mzRouteUse->cu_def->cd_bbox.r_xtop) + { + if(TiGetType(tpBounds) == TT_SPACE) + { + /* hit edge of bounds before jog found */ + goto rightNextLayer; + } + else if(TOP(tpBounds)<=TOP(tpThis) && + TOP(tpBounds)<=mzRouteUse->cu_def->cd_bbox.r_ytop) + { + Point p; + + p.p_x = MAX(LEFT(tpBounds), pOrg.p_x); + p.p_y = TOP(tpBounds); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + else if(BOTTOM(tpBounds)>=BOTTOM(tpThis) && + BOTTOM(tpBounds)>= + mzRouteUse->cu_def->cd_bbox.r_ybot) + { + Point p; + p.p_x = MAX(LEFT(tpBounds), pOrg.p_x); + p.p_y = BOTTOM(tpBounds); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + + /* move to next tile in bounds plane */ + if(covered) + { + NEXT_TILE_RIGHT(tpBounds, tpBounds, pOrg.p_y); + } + } + } + + /* get next tile over */ + NEXT_TILE_RIGHT(tpNext, tpThis, pOrg.p_y); + ntype = TiGetType(tpNext); + + if ((ntype != TT_SPACE) && (ntype != TT_SAMENODE)) + { + /* path blocked */ + if(LEFT(tpNext)==pStep.p_x) + { + /* pOrg right up against obstacle, can't extend so + go to next layer */ + continue; + } + else + { + /* prune pNew to just this side of block */ + PRUNE_TO_MIN(pNew.p_x, + LEFT(tpNext)-1, + reasons, + RC_ALIGNOTHER); + } + } + else + { + /* path not blocked */ + if((TOP(tpNext)BOTTOM(tpThis)) + && RIGHT(tpThis)-1>pOrg.p_x) + { + /* space is constricting, prune pNew to far + * end of this tile + */ + PRUNE_TO_MIN(pNew.p_x, + LEFT(tpNext)-1, + reasons, + RC_ALIGNOTHER); + } + else + { + /* prune pNew to just inside next tile */ + PRUNE_TO_MIN(pNew.p_x, + LEFT(tpNext), + reasons, + RC_ALIGNOTHER); + } + } + } + rightNextLayer:; + } + + /* Prune pNew to next alignment with a DESTINATION terminal */ + { + int *xAlign = &(mzNLGetContainingInterval(&mzXAlignNL,pOrg.p_x)[1]); + PRUNE_TO_MIN(pNew.p_x, *xAlign, reasons, RC_ALIGNGOAL); + } + + /* Prune pNew to alignment with perpendicular HINT edges */ + { + Tile *tp; + + tp = TiSrPointNoHint(mzVHintPlane, &pOrg); + PRUNE_TO_MIN(pNew.p_x, RIGHT(tp), reasons, RC_HINT); + } + + /* Prune pNew to either side of tile edges on ROTATE plane (organized + * into maximum strips in perpendicular direction). Jogging + * at such points can effect cost. + * NOTE: Also must have intermediate path points at boundaries between + * rotate and non-rotate since edge cost different in these regions. + */ + { + Tile *tp; + + tp = TiSrPointNoHint(mzVRotatePlane, &pStep); + + if(LEFT(tp) > pOrg.p_x) + /* prune to beginning of tile */ + PRUNE_TO_MIN(pNew.p_x, LEFT(tp), reasons, RC_ROTBEFORE); + else + /* prune to end of tile */ + PRUNE_TO_MIN(pNew.p_x, RIGHT(tp)-1, reasons, RC_ROTINSIDE); + } + + /* Prune to just before or just after CONTACT BLOCKS. + * These are last and first opportunites for contacts. + */ + { + List *cL; + Tile *tp; + TileType tpType; + + /* Loop thru contact types connecting to current route layer */ + for (cL=path->rp_rLayer->rl_contactL; cL!=NULL; cL=LIST_TAIL(cL)) + { + /* find tile in contact blockage plane under pOrg */ + tp = TiSrPointNoHint( + ((RouteContact*) LIST_FIRST(cL))->rc_routeType.rt_hBlock, + &pStep); + tpType = TiGetType(tp); + + if ((tpType == TT_SPACE) || (tpType == TT_SAMENODE)) + { + /* SPACE TILE */ + if(LEFT(tp) > pOrg.p_x) + /* prune to beginning of tile */ + PRUNE_TO_MIN(pNew.p_x, LEFT(tp), reasons, RC_CONTACT); + else + /* prune to end of tile */ + PRUNE_TO_MIN(pNew.p_x, RIGHT(tp)-1, reasons, RC_CONTACT); + } + else + { + /* BLOCK TILE - so prune to just beyond tile */ + PRUNE_TO_MIN(pNew.p_x, RIGHT(tp), reasons, RC_CONTACT); + if (tpType == TT_BLOCKED) overroute = TRUE; + } + } + } + + donePruning:; + /* DONE PRUNING pNew */ + + /* debug - print point and reasons its interesting. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("Done Pruning, new point: (%d, %d) ", + pNew.p_x, pNew.p_y); + TxPrintf("is interesting because:\n "); + if(reasons & RC_JOG) + { + TxPrintf("jog "); + } + if(reasons & RC_ALIGNOTHER) + { + TxPrintf("alignOther "); + } + if(reasons & RC_CONTACT) + { + TxPrintf("contact "); + } + if(reasons & RC_ALIGNGOAL) + { + TxPrintf("alignGoal "); + } + if(reasons & RC_HINT) + { + TxPrintf("hint "); + } + if(reasons & RC_ROTBEFORE) + { + TxPrintf("rotBefore "); + } + if(reasons & RC_ROTINSIDE) + { + TxPrintf("rotInside "); + } + if(reasons & RC_BOUNDS) + { + TxPrintf("bounds "); + } + if(reasons & RC_WALK) + { + TxPrintf("walk "); + } + if(reasons & RC_WALKLRC || reasons & RC_WALKUDC) + { + TxPrintf("walkc "); + } + if(reasons & RC_DONE) + { + TxPrintf("done "); + } + TxPrintf("\n"); + } + + /* Compute extend code - i.e. interesting directions to extend from + * new point */ + if(reasons & (RC_WALK | RC_WALKLRC | RC_WALKUDC | RC_DONE)) + { + if(reasons & RC_WALK) + { + extendCode = EC_WALKRIGHT; + } + else if(reasons & RC_WALKLRC) + { + extendCode = EC_WALKLRCONTACT; + } + else if(reasons & RC_WALKUDC) + { + extendCode = EC_WALKUDCONTACT; + } + else + { + extendCode = EC_COMPLETE; + } + } + else + { + /* initial with just straight ahead */ + extendCode = EC_RIGHT; + + if(reasons & (RC_ALIGNOTHER | RC_CONTACT | RC_ALIGNGOAL | + RC_HINT | RC_ROTINSIDE)) + { + extendCode |= EC_UDCONTACTS | EC_LRCONTACTS; + } + + if(reasons & (RC_JOG | RC_ALIGNGOAL | RC_HINT | RC_ROTINSIDE)) + { + extendCode |= EC_UP | EC_DOWN; + } + } + + /* If we end inside SAMENODE, then the cost to this point is */ + /* zeroed, and that section of the path will not be painted. */ + + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_vBlock, &pNew); + if (TiGetType(tpThis) == TT_SAMENODE) + if ((!path->rp_back) || (path->rp_back->rp_cost == (dlong)0)) + path->rp_cost = (dlong)0; + + /* compute cost of path segment from pOrg to pNew */ + { + Tile *tp; + bool rotate; + + tp = TiSrPointNoHint(mzVRotatePlane, &pOrg); + rotate = (TiGetType(tp) != TT_SPACE); + + if (rotate) + segCost = (dlong) ((pNew.p_x - pOrg.p_x) * + path->rp_rLayer->rl_vCost); + else if (overroute) + segCost = (dlong) ((pNew.p_x - pOrg.p_x) * + path->rp_rLayer->rl_overCost); + else + segCost = (dlong) ((pNew.p_x - pOrg.p_x) * + path->rp_rLayer->rl_hCost); + } + + /* Compute additional cost for paralleling nearest hint segment */ + /* (Start at low end of segment and move to high end computing hint cost + * as we go) + */ + { + Tile *tp; + dlong hintCost; + int deltaUp, deltaDown, delta; + Point lowPt; + + for(lowPt = pOrg; lowPt.p_x < pNew.p_x; lowPt.p_x = RIGHT(tp)) + { + /* find tile in hint plane containing lowPt */ + tp = TiSrPointNoHint(mzVHintPlane,&lowPt); + + /* find nearest hint segment and add appropriate cost */ + if(TiGetType(tp) != TT_MAGNET) + { + deltaUp = (TiGetType(RT(tp)) == TT_MAGNET) ? + TOP(tp) - lowPt.p_y : -1; + deltaDown = (TiGetType(LB(tp)) == TT_MAGNET) ? + lowPt.p_y - BOTTOM(tp) : -1; + + /* delta = distance to nearest hint */ + if (deltaUp < 0) + { + if (deltaDown < 0) + delta = 0; + else + delta = deltaDown; + } + else + { + if (deltaDown < 0) + delta = deltaUp; + else + delta = MIN(deltaUp,deltaDown); + } + + if(delta>0) + { + hintCost = (dlong) ((MIN(RIGHT(tp),pNew.p_x) - lowPt.p_x) * + path->rp_rLayer->rl_hintCost); + hintCost *= delta; + segCost += hintCost; + } + } + } + } + + /* Process the new point */ + mzAddPoint(path, &pNew, path->rp_rLayer, 'H', extendCode, &segCost); + + return; +} diff --git a/mzrouter/mzXtndUp.c b/mzrouter/mzXtndUp.c new file mode 100644 index 00000000..a57b2268 --- /dev/null +++ b/mzrouter/mzXtndUp.c @@ -0,0 +1,632 @@ +/* + * mzExtendUp.c -- + * + * Code for finding next interesting point up. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/mzrouter/mzXtndUp.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "database/database.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/list.h" +#include "debug/debug.h" +#include "mzrouter/mzrouter.h" +#include "mzrouter/mzInternal.h" + + +/* + * ---------------------------------------------------------------------------- + * + * mzExtendUp -- + * + * Find next interesting point up. + * + * Results: + * None. + * + * Side effects: + * mzAddPoint() called to added extended path to appropriate queue. + * + * ---------------------------------------------------------------------------- + */ +void +mzExtendUp(path) + RoutePath *path; +{ + Point pOrg; /* point to extend from */ + Point pStep; /* one unit from pOrg in direction of extension */ + Point pNew; /* next interesting point in direction of extension */ + dlong segCost; /* cost of segment between pOrg and pNew */ + RouteLayer *rL; /* temp variable for routelayers */ + int reasons; /* Reasons point is interesting. Used to + * avoid extensions in uninteresting directions. + */ + int extendCode; /* Interesting directions to extend in */ + bool overroute = FALSE; /* Is crossing another route layer */ + TileType ntype; + Tile *tpThis; + + /* DEBUG - trace calls to this routine. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + TxPrintf("EXTENDING UP\n"); + + /* pOrg = current end of path */ + pOrg = path->rp_entry; + + /* pStep = point just one unit beyond pOrg */ + pStep = pOrg; + ++(pStep.p_y); + + /* Initial pNew to BOUNDS edge. Must stop there + * since blockage planes haven't been generated past there. + */ + { + Tile *tp; + + /* get bounds tile under pOrg */ + tp = TiSrPointNoHint(mzVBoundsPlane, &pOrg); + pNew.p_x = pOrg.p_x; + pNew.p_y = TOP(tp); + reasons = RC_BOUNDS; + } + + /* + * Initial pNew to next pt where there is a change in the amount of + * space on the BLOCKAGE plane in the direction perpendicular to the + * extension. (A special case of this is a actual block + * of the extension). Want to consider jogs at such points. + * + */ + { + Tile *tpNext; + bool covered; + + /* get tpThis, extending bounds plane and iterating, until + * completely covered by bounds plane. + */ + covered = FALSE; + while(!covered) + { + Tile *tpBounds; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_hBlock, + &pOrg); + + /* org point should not be blocked */ + ASSERT(TiGetType(tpThis) == TT_SPACE, "mzExtendUp"); + + /* check to see if covered, if not extend bounds and start over */ + covered = TRUE; + tpBounds = TiSrPointNoHint(mzHBoundsPlane, &pOrg); + while(covered && BOTTOM(tpBounds)<=TOP(tpThis) && + BOTTOM(tpBounds)<=mzRouteUse->cu_def->cd_bbox.r_ytop) + { + if(TiGetType(tpBounds) == TT_SPACE) + { + /* hit edge of bounds before jog found */ + goto upEndJog; + } + else if(RIGHT(tpBounds)<=RIGHT(tpThis) && + RIGHT(tpBounds)<=mzRouteUse->cu_def->cd_bbox.r_xtop) + { + Point p; + + p.p_x = RIGHT(tpBounds); + p.p_y = MAX(BOTTOM(tpBounds), pOrg.p_y); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + else if(LEFT(tpBounds)>=LEFT(tpThis) && + LEFT(tpBounds)>=mzRouteUse->cu_def->cd_bbox.r_xbot) + { + Point p; + p.p_x = LEFT(tpBounds); + p.p_y = MAX(BOTTOM(tpBounds), pOrg.p_y); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + + /* move to next tile in bounds plane */ + if(covered) + { + NEXT_TILE_UP(tpBounds, tpBounds, pOrg.p_x); + } + } + } + + /* also get next tile over */ + NEXT_TILE_UP(tpNext, tpThis, pOrg.p_x); + ntype = TiGetType(tpNext); + + if ((ntype != TT_SPACE) && (ntype != TT_SAMENODE)) + { + /* path blocked */ + if (BOTTOM(tpNext) == pStep.p_y) + { + /* pOrg right up against block */ + if (ntype == TT_BOTTOM_WALK) + { + /* Block is walk, enter it */ + pNew.p_y = pOrg.p_y + 1; + reasons = RC_WALK; + goto donePruning; + } + else if (ntype == TT_ABOVE_LR_WALK || + ntype == TT_BELOW_LR_WALK) + { + /* Block is contact walk, enter it */ + pNew.p_y = pOrg.p_y + 1; + reasons = RC_WALKLRC; + goto donePruning; + } + else if (ntype == TT_ABOVE_UD_WALK || + ntype == TT_BELOW_UD_WALK) + { + /* Block is contact walk, enter it */ + pNew.p_y = pOrg.p_y + 1; + reasons = RC_WALKUDC; + goto donePruning; + } + else if (ntype == TT_DEST_AREA) + { + /* Block is destination, enter it */ + pNew.p_y = pOrg.p_y + 1; + reasons = RC_DONE; + goto donePruning; + } + else + { + /* Path blocked from expansion, just return */ + return; + } + } + else + { + /* prune pNew to just this side of block */ + PRUNE_TO_MIN(pNew.p_y, BOTTOM(tpNext)-1, reasons, RC_JOG); + } + } + else + { + /* path not blocked */ + if((RIGHT(tpNext)LEFT(tpThis)) && + TOP(tpThis)-1>pOrg.p_y) + { + /* space is constricting, prune pNew to far + * end of this tile + */ + PRUNE_TO_MIN(pNew.p_y, BOTTOM(tpNext)-1, reasons, RC_JOG); + } + else + { + /* prune pNew to just inside next tile */ + PRUNE_TO_MIN(pNew.p_y, BOTTOM(tpNext), reasons, RC_JOG); + pNew.p_y = BOTTOM(tpNext); + } + } + upEndJog:; + } + + /* + * Prune pNew to next pt where there is a change in the amount of + * space on other active BLOCKAGE planes in the direction perpendicular + * to the + * extension. (A special case of this is a actual block + * of the extension). Want to consider jogs at such points. + * + */ + for(rL=mzActiveRLs; rL!=NULL; rL=rL->rl_nextActive) + { + Tile *tpNext; + TileType tpType; + bool covered; + + /* skip current layer (already handled above) */ + if(rL == path->rp_rLayer) + { + continue; + } + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(rL->rl_routeType.rt_hBlock, + &pOrg); + + tpType = TiGetType(tpThis); + if ((tpType != TT_SPACE) && (tpType != TT_SAMENODE)) + { + /* ORG POINT BLOCKED */ + /* this case handled by contact code below, so skip to next layer*/ + + continue; + } + else + { + /* ORG POINT NOT BLOCKED, LOOK FOR NARROWING OR GROWING OF SPACE */ + + /* get tpThis, extending bounds plane and iterating, until + * completely covered by bounds plane. + */ + covered = FALSE; + while(!covered) + { + Tile *tpBounds; + + /* get blockage plane tile under pOrg */ + tpThis = TiSrPointNoHint(rL->rl_routeType.rt_hBlock, &pOrg); + + /* org point should not be blocked */ + ASSERT(TiGetType(tpThis)==TT_SPACE,"mzExtendUp, other"); + + /* check to see if covered, + if not extend bounds and start over */ + covered = TRUE; + tpBounds = TiSrPointNoHint(mzHBoundsPlane, &pOrg); + while(covered && BOTTOM(tpBounds)<=TOP(tpThis) && + BOTTOM(tpBounds)<=mzRouteUse->cu_def->cd_bbox.r_ytop) + { + if(TiGetType(tpBounds) == TT_SPACE) + { + /* hit edge of bounds before jog found */ + goto upNextLayer; + } + else if(RIGHT(tpBounds)<=RIGHT(tpThis) && + RIGHT(tpBounds)<= + mzRouteUse->cu_def->cd_bbox.r_xtop) + { + Point p; + + p.p_x = RIGHT(tpBounds); + p.p_y = MAX(BOTTOM(tpBounds), pOrg.p_y); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + else if(LEFT(tpBounds)>=LEFT(tpThis) && + LEFT(tpBounds)>=mzRouteUse->cu_def->cd_bbox.r_xbot) + { + Point p; + p.p_x = LEFT(tpBounds); + p.p_y = MAX(BOTTOM(tpBounds), pOrg.p_y); + + mzExtendBlockBounds(&p); + if(SigInterruptPending) return; + + covered = FALSE; + } + + /* move to next tile in bounds plane */ + if(covered) + { + NEXT_TILE_UP(tpBounds, tpBounds, pOrg.p_x); + } + } + } + + /* get next tile over */ + NEXT_TILE_UP(tpNext, tpThis, pOrg.p_x); + ntype = TiGetType(tpNext); + + if ((ntype != TT_SPACE) && (ntype != TT_SAMENODE)) + { + /* path blocked */ + if(BOTTOM(tpNext)==pStep.p_y) + { + /* pOrg right up against obstacle, can't extend so + go to next layer */ + continue; + } + else + { + /* prune pNew to just this side of block */ + PRUNE_TO_MIN(pNew.p_y, + BOTTOM(tpNext)-1, + reasons, + RC_ALIGNOTHER); + } + } + else + { + /* path not blocked */ + if((RIGHT(tpNext)LEFT(tpThis)) && + TOP(tpThis)-1>pOrg.p_y) + { + /* space is constricting, prune pNew to far + * end of this tile + */ + PRUNE_TO_MIN(pNew.p_y, + BOTTOM(tpNext)-1, + reasons, + RC_ALIGNOTHER); + } + else + { + /* prune pNew to just inside next tile */ + PRUNE_TO_MIN(pNew.p_y, + BOTTOM(tpNext), + reasons, + RC_ALIGNOTHER); + } + } + } + upNextLayer:; + } + + /* Prune pNew to next alignment with a DESTINATION terminal */ + { + int *yAlign = &(mzNLGetContainingInterval(&mzYAlignNL,pOrg.p_y)[1]); + PRUNE_TO_MIN(pNew.p_y, *yAlign, reasons, RC_ALIGNGOAL); + } + + /* Prune pNew to alignment with perpendicular HINT edges */ + { + Tile *tp; + + tp = TiSrPointNoHint(mzHHintPlane, &pOrg); + PRUNE_TO_MIN(pNew.p_y, TOP(tp), reasons, RC_HINT); + } + + /* Prune pNew to either side of tile edges on ROTATE plane (organized + * into maximum strips in perpendicular direction). Jogging + * at such points can effect cost. + * NOTE: Also must have intermediate path points at boundaries between + * rotate and non-rotate since edge cost different in these regions. + */ + { + Tile *tp; + + tp = TiSrPointNoHint(mzHRotatePlane, &pStep); + + if(BOTTOM(tp) > pOrg.p_y) + /* prune to beginning of tile */ + PRUNE_TO_MIN(pNew.p_y, BOTTOM(tp), reasons, RC_ROTBEFORE); + else + /* prune to end of tile */ + PRUNE_TO_MIN(pNew.p_y, TOP(tp)-1, reasons, RC_ROTINSIDE); + } + + /* Prune to just before or just after CONTACT BLOCKS. + * These are last and first opportunites for contacts. + */ + { + List *cL; + Tile *tp; + TileType tpType; + + /* Loop thru contact types connecting to current route layer */ + for (cL=path->rp_rLayer->rl_contactL; cL!=NULL; cL=LIST_TAIL(cL)) + { + /* find tile in contact blockage plane under pOrg */ + tp = TiSrPointNoHint( + ((RouteContact*) LIST_FIRST(cL))->rc_routeType.rt_hBlock, + &pStep); + + tpType = TiGetType(tp); + if ((tpType == TT_SPACE) || (tpType == TT_SAMENODE)) + { + /* SPACE TILE */ + if(BOTTOM(tp) > pOrg.p_y) + /* prune to beginning of tile */ + PRUNE_TO_MIN(pNew.p_y, BOTTOM(tp), reasons, RC_CONTACT); + else + /* prune to end of tile */ + PRUNE_TO_MIN(pNew.p_y, TOP(tp)-1, reasons, RC_CONTACT); + } + else + { + /* BLOCK TILE - so prune to just beyond tile */ + PRUNE_TO_MIN(pNew.p_y, TOP(tp), reasons, RC_CONTACT); + if (tpType == TT_BLOCKED) overroute = TRUE; + } + } + } + + donePruning:; + /* DONE PRUNING pNew */ + + /* debug - print point and reasons its interesting. */ + if (DebugIsSet(mzDebugID, mzDebMaze)) + { + TxPrintf("Done Pruning, new point: (%d, %d) ", + pNew.p_x, pNew.p_y); + TxPrintf("is interesting because:\n "); + if(reasons & RC_JOG) + { + TxPrintf("jog "); + } + if(reasons & RC_ALIGNOTHER) + { + TxPrintf("alignOther "); + } + if(reasons & RC_CONTACT) + { + TxPrintf("contact "); + } + if(reasons & RC_ALIGNGOAL) + { + TxPrintf("alignGoal "); + } + if(reasons & RC_HINT) + { + TxPrintf("hint "); + } + if(reasons & RC_ROTBEFORE) + { + TxPrintf("rotBefore "); + } + if(reasons & RC_ROTINSIDE) + { + TxPrintf("rotInside "); + } + if(reasons & RC_BOUNDS) + { + TxPrintf("bounds "); + } + if(reasons & RC_WALK) + { + TxPrintf("walk "); + } + if(reasons & RC_WALKUDC || reasons & RC_WALKLRC) + { + TxPrintf("walkc "); + } + if(reasons & RC_DONE) + { + TxPrintf("done "); + } + TxPrintf("\n"); + } + + /* Compute extend code - i.e. interesting directions to extend from + * new point */ + if(reasons & (RC_WALK | RC_WALKUDC | RC_WALKLRC | RC_DONE)) + { + if(reasons & RC_WALK) + { + extendCode = EC_WALKUP; + } + else if(reasons & RC_WALKUDC) + { + extendCode = EC_WALKUDCONTACT; + } + else if(reasons & RC_WALKLRC) + { + extendCode = EC_WALKLRCONTACT; + } + else + { + extendCode = EC_COMPLETE; + } + } + else + { + /* initial with just straight ahead */ + extendCode = EC_UP; + + if(reasons & (RC_ALIGNOTHER | RC_CONTACT | RC_ALIGNGOAL | + RC_HINT | RC_ROTINSIDE)) + { + extendCode |= EC_UDCONTACTS | EC_LRCONTACTS; + } + + if(reasons & (RC_JOG | RC_ALIGNGOAL | RC_HINT | RC_ROTINSIDE)) + { + extendCode |= EC_RIGHT | EC_LEFT; + } + } + + /* If we end inside SAMENODE, then the cost to this point is */ + /* zeroed, and that section of the path will not be painted. */ + + tpThis = TiSrPointNoHint(path->rp_rLayer->rl_routeType.rt_hBlock, &pNew); + if (TiGetType(tpThis) == TT_SAMENODE) + if ((!path->rp_back) || (path->rp_back->rp_cost == (dlong)0)) + path->rp_cost = (dlong)0; + + /* compute cost of path segment from pOrg to pNew */ + { + Tile *tp; + bool rotate; + + tp = TiSrPointNoHint(mzHRotatePlane, &pOrg); + rotate = (TiGetType(tp) != TT_SPACE); + + if (rotate) + segCost = (dlong) ((pNew.p_y - pOrg.p_y) * + path->rp_rLayer->rl_hCost); + else if (overroute) + segCost = (dlong) ((pNew.p_y - pOrg.p_y) * + path->rp_rLayer->rl_overCost); + else + segCost = (dlong) ((pNew.p_y - pOrg.p_y) * + path->rp_rLayer->rl_vCost); + } + + /* Compute additional cost for paralleling nearest hint segment */ + /* (Start at low end of segment and move to high end computing hint cost + * as we go) + */ + { + Tile *tp; + dlong hintCost; + int deltaRight, deltaLeft, delta; + Point lowPt; + + for(lowPt = pOrg; lowPt.p_y < pNew.p_y; lowPt.p_y = TOP(tp)) + { + /* find tile in hint plane containing lowPt */ + tp = TiSrPointNoHint(mzHHintPlane,&lowPt); + + /* find nearest hint segment and add appropriate cost */ + if(TiGetType(tp) != TT_MAGNET) + { + deltaRight = (TiGetType(TR(tp)) == TT_MAGNET) ? + RIGHT(tp) - lowPt.p_x : -1; + deltaLeft = (TiGetType(BL(tp)) == TT_MAGNET) ? + lowPt.p_x - LEFT(tp) : -1; + + /* delta = distance to nearest hint */ + if (deltaRight < 0) + { + if (deltaLeft < 0) + delta = 0; + else + delta = deltaLeft; + } + else + { + if (deltaLeft < 0) + delta = deltaRight; + else + delta = MIN(deltaRight,deltaLeft); + } + + if(delta>0) + { + hintCost = (dlong) ((MIN(TOP(tp),pNew.p_y) - lowPt.p_y) * + path->rp_rLayer->rl_hintCost); + hintCost *= delta; + segCost += hintCost; + } + } + } + } + + /* Process the new point */ + mzAddPoint(path, &pNew, path->rp_rLayer, 'V', extendCode, &segCost); + + return; +} diff --git a/mzrouter/mzrouter.h b/mzrouter/mzrouter.h new file mode 100644 index 00000000..1a9633e0 --- /dev/null +++ b/mzrouter/mzrouter.h @@ -0,0 +1,348 @@ +/* + * mzrouter.h -- + * + * This file defines the interface provided by the maze router + * module to the rest of Magic. + * + * ********************************************************************* + * * Copyright (C) 1988, 1990 Michael H. Arnold and the Regents of the * + * * University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/mzrouter/mzrouter.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _MZROUTER_H +#define _MZROUTER_H + +#include "database/database.h" +#include "utils/geometry.h" +#include "utils/list.h" + +/* This module does not support a command level interface: it is accessed + * by other modules (such as the irouter and the garouter) via procedure + * calls. + * + * NOTE: a wizard command interface (`*mzroute') IS provided for testing. + * (see mzTestCmd.c) + */ + +/* PARAMETER STRUCTURES */ +/*----------------------------- RouteType ----------------------------------*/ + +/* + * Contains information about a tile type used by the router. + * + * This structure is contained in both RouteLayer and RouteContacts strucs. + * It contains information that is relevant to both route layers and layers + * used for contacts by the router. + * + * *DERIVED* = member computed by MZInitRoute() prior to each route. + * + */ + +typedef struct +routetype +{ + /* IDENTIFICATION */ + TileType rt_tileType; /* "Home" tile type of this layer */ + + /* STATUS */ + bool rt_active; /* Maze router uses type only if this flag + set */ + + /* DESIGN RULES */ + int rt_width; /* Width of path or contact */ + int rt_length; /* Length of contact or minimum */ + /* length of a path to satisfy */ + /* minimum area requirements */ + int rt_spacing[TT_MAXTYPES + 1]; /* spacings to various types + last entry is SUBCELL spacing */ + + /* DERIVATIVE DESIGN RULES - computed from DESIGN RULES above. + * for contact routeTypes, max design rules for components used, so + * that a contact will not be placed unless there is space for wires + * on both connected layers. + * + * bloatTop = spacing + * bloatBot = spacing + width - 1 + */ + int rt_effWidth; /* *DERIVED* - for contact, + * max of component width */ + int rt_bloatBot[TT_MAXTYPES + 1]; /* *DERIVED* - bloat distance + * to bottom and left */ + int rt_bloatTop[TT_MAXTYPES + 1]; /* *DERIVED* - bloat distance to + * top and right */ + + /* BLOCKAGE PLANES */ + Plane *rt_hBlock; /* Blockage plane for layer organized into maximal + horizontal strips */ + Plane *rt_vBlock; /* Blockage plane for layer organized into maximal + vertical strips */ + + struct routetype *rt_next; /* For convenience, all route types are + * threaded + * together. (This threading is in addition + * to the routeLayers list and the + * routeContacts list. + */ + struct routetype *rt_nextActive; /* *DERIVED* - This list built in + * MZInitRoute() */ +} RouteType; + +/*--------------------------- RouteLayer ----------------------------------*/ + +/* + * The RouteLayers list contains one of these structures for each + * layer on which routing is permitted. The structure is a + * handle for all information relevant to a route layer. + * + * *DERIVED* = member computed by MZInitRoute() prior to each route. + * + */ + +typedef struct routelayer +{ + /* TYPE */ + RouteType rl_routeType; /* Contains info. relevant to both + route layers and contact types */ + + /* PLANE NUMBER */ + int rl_planeNum; /* Plane number of layer */ + + /* CONTACTS */ + List *rl_contactL; /* list of contact types that connect to this layer */ + + /* COST */ + int rl_hCost; /* cost per unit length for horizontal segments */ + int rl_vCost; /* cost per unit length for vertical segments */ + int rl_jogCost; /* cost of a jog */ + int rl_hintCost; /* cost per unit area for deviation from hint */ + int rl_overCost; /* cost per unit length for crossing another route layer */ + + /* NEXT ROUTE LAYER */ + struct routelayer *rl_next; + struct routelayer *rl_nextActive; /* *DERIVED* - Only accurate after + * MZInitRoute() */ +} RouteLayer; + +/*---------------------------- RouteContact ------------------------------*/ +/* + * This sturcture describes a type of contact to be used during routing. + * Contacts connect two route layers. + */ + +typedef struct routecontact +{ + /* TYPE */ + RouteType rc_routeType; /* Contains info. relevant to both + route layers and contact types */ + + /* LAYERS CONNECTED */ + RouteLayer *rc_rLayer1; /* Layers connected by this type of contact */ + RouteLayer *rc_rLayer2; + + /* COST */ + int rc_cost; + + /* NEXT ROUTE CONTACT */ + struct routecontact *rc_next; /* next in RouteContacts list */ + +} RouteContact; + +/* ----------------------------- Paths ----------------------------------- */ + +/* + * Zero-width path segment structure. Paths and partial-paths built from + * these structures during search. + * + * Can be flushed out to paint via MZPaintPath(). + * + */ +typedef struct rpath +{ + struct rpath *rp_back; /* Pointer to previous leg of path */ + RouteLayer *rp_rLayer; /* Route layer of this segment */ + int rp_orient; /* orientation of this segment, + * 'H' = hor, 'V' = vert, 'O' = contact + * or start point. + */ + Point rp_entry; /* Cost was computed to this point */ + int rp_extendCode; /* directions to extend */ + dlong rp_cost; /* estimated total cost */ + dlong rp_togo; /* estimated cost to completion */ +} RoutePath; + +/* extension codes */ +#define EC_RIGHT 1 +#define EC_LEFT 2 +#define EC_UP 4 +#define EC_DOWN 8 +#define EC_UDCONTACTS 16 +#define EC_LRCONTACTS 32 +#define EC_ALL 63 + +#define EC_WALKRIGHT 64 +#define EC_WALKLEFT 128 +#define EC_WALKUP 256 +#define EC_WALKDOWN 512 +#define EC_WALKUDCONTACT 1024 +#define EC_WALKLRCONTACT 2048 + +#define EC_COMPLETE 4096 + +/*----------------------- Soft Floating Point ----------------------------- */ +/* (Floating Point Format for our own software-implemented floating-point. + * Used for the penalty factor for costs outside the window.) + */ + +/* Note: nExponent must be >=0 + * To multiply dlong by routeFloat, first multiply by mantissa, then + * shift right nExponent number of bits. + */ +typedef struct routeFloat +{ + int rf_mantissa; + int rf_nExponent; +} RouteFloat; + +/*---------------------------- MazeParameters ------------------------------*/ + +/* + * This sturcture contains all maze router parameters, including design rules. + */ +typedef struct mazeparameters +{ + RouteLayer *mp_rLayers; /* list of route layers */ + RouteContact *mp_rContacts; /* list of route contacts */ + RouteType *mp_rTypes; /* list of all route types */ + + RouteFloat mp_penalty; /* Penalty for lagging behind window */ + /* BY NP---changed from DoubleInt to dlong */ + dlong mp_wWidth; /* Window width */ + dlong mp_wRate; /* Rate of motion for window */ + dlong mp_bloomDeltaCost; /* Max increment. in cost while blooming */ + int mp_boundsIncrement; /* min radius of blockage info required + * around point being extended - twice the + * increment is generated whenever gen. is + * necessary. + */ + bool mp_estimate; /* If set, nontrivial estimation of cost + * to completion is used - factoring in + * blocks due to subcells and fences. + */ + + bool mp_expandEndpoints; /* If set, routes may start or terminate anywhere + * that is electrically connected + * to specified start or dest regions. + */ + + bool mp_topHintsOnly; /* If set, only hints in the top cell presented + * to the router are recognized - used by + * garouter to speed up processing. + */ + + int mp_maxWalkLength; /* max distance into blocked area route + * will extend in order to connect to + * a destination terminal. If set to -1, + * max distance is computed as a function + * of design rules for active layers prior + * to each route. + */ + + Rect *mp_boundsHint; /* If nonnull, improves perfomrnace by limiting + * estimation, bounds generation etc to this + * area. + * NOTE: IF SET IT IS THE USERS RESPONSIBILITY + * TO CONTAIN THE ROUTE WITHIN THIS AREA + * VIA FENCES - ELSE BIZARRE BEHAVIOUR + * IS POSSIBLE. + */ + + int mp_verbosity; /* amount of messages printed: + * 0 = errors and warnings only, + * 1 = brief + * 2 = lots of statistics. + */ + + int mp_bloomLimit; /* if positive, puts upper limit on number of + * blooms in maze search before router + * terminates. + * + * If negative or 0, no limit is imposed. + */ +} MazeParameters; +#define VERB_WARNONLY 0 +#define VERB_BRIEF 1 +#define VERB_STATS 2 + +/* Return codes for MZRoute() */ + +#define MZ_NO_ACTION -1 /* Never ran MZRoute() */ +#define MZ_SUCCESS 0 /* Successful route */ +#define MZ_CURRENT_BEST 1 /* Interrupted, returned best choice so far */ +#define MZ_ALREADY_ROUTED 2 /* Start node = Dest node already */ +#define MZ_FAILURE 3 /* Route failed for some reason */ +#define MZ_UNROUTABLE 4 /* Failed to generate a walk to the dest node */ +#define MZ_INTERRUPTED 5 /* Interrupted, no route was found */ + +/* INTERFACE PROCEDURES */ +/* Call sequence for routing: + * 1. MZInitRoute() + * 2. MZAddStart()'s and MZAddDest()'s + * 3. MZRoute() + * 4. MZPaintPath() + * 5. MZClean() + * + * NOTE: IF THE SEQUENCE IS ABORTED PART WAY THROUGH BE SURE AND CALL MZClean() + * PRIOR TO RETURNING TO MAGIC COMMAND PROCESSOR. THIS IS NECESSARY TO + * RESTORE TILE CLIENTDATA TO INITIAL STATE. + */ +extern MazeParameters *MZFindStyle(); /* return parms of given style */ +extern MazeParameters *MZCopyParms(); /* Create new MazeParameters */ + +extern void MZInitRoute(); /* Initialize route */ +extern void MZAddStart(); /* After MzInitRoute, to add start points */ +extern void MZAddDest(); /* After MZInitRoute, to add dest area */ +extern RoutePath *MZRoute(); /* After MZAddStart, and MZAddDest + * to do search */ +extern CellUse *MZPaintPath(); /* Turns path into actual paint */ +extern void MZClean(); /* Reclaim storage */ +extern void MZTest(); /* Wizard command interface (`*mzroute') */ +extern RouteType *MZFindRouteType(); +extern RouteLayer *MZFindRouteLayer(); +extern RouteContact *MZGetContact(); +extern RouteContact *MZRouteContact(); +extern void MZPrintRLs(); /* Allows clients to dump maze parms */ +extern void MZPrintRCs(); +extern void MZPrintRLListNames(); +extern void MZPrintRCListNames(); +extern void MZFreeParameters(MazeParameters *); + +extern void MZInit(); +extern void MZAfterTech(); + +/* TECHNOLOGY FILE PROCESSING PROCEDURES */ + /* "mzrouter" section */ +extern void MZTechInit(); +extern bool MZTechLine(); +extern void MZTechFinal(); + + /* plane scaling pointer recovery */ + +extern void MZAttachHintPlanes(); + +/* EXPORTED VARIABLES */ + +/* Major cost unit */ +extern int mzMajorCostUnit; + +#endif /* _MZROUTER_H */ diff --git a/net2ir/Depend b/net2ir/Depend new file mode 100644 index 00000000..ce71b0c3 --- /dev/null +++ b/net2ir/Depend @@ -0,0 +1,2 @@ +net2ir.o: net2ir.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/malloc.h ../utils/utils.h diff --git a/net2ir/Makefile b/net2ir/Makefile new file mode 100644 index 00000000..9bdb7038 --- /dev/null +++ b/net2ir/Makefile @@ -0,0 +1,23 @@ +# +# rcsid = "$Header: /usr/cvsroot/magic-8.0/net2ir/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" +# + +MODULE = net2ir +MAGICDIR = .. +SRCS = net2ir.c + +EXTRA_LIBS = ${MAGICDIR}/utils/libutils.a + +include ${MAGICDIR}/defs.mak + +tcl-main: + echo "Nothing to do here" + +main: net2ir + +install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} + +install-tcl: + echo "Nothing to do here" + +include ${MAGICDIR}/rules.mak diff --git a/net2ir/net2ir.c b/net2ir/net2ir.c new file mode 100644 index 00000000..69fa0e87 --- /dev/null +++ b/net2ir/net2ir.c @@ -0,0 +1,158 @@ +/* + * net2ir -- + * + * Given a feedback file produced by the Magic :find command (from + * the netlist menu) followed by :feed save, giving label locations and + * layers, and a netlist + * file, produce a set of irouter commands to route the two-point + * nets in the order in which they appear in the netlist file. + * + * Usage: + * net2ir feedfile netfile + * + * Produces the commands on its standard output. + */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "utils/utils.h" + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/net2ir/net2ir.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* lint */ + +#define INITHASHSIZE 128 +#define LINESIZE 1024 + +/* + * Hash table of all feedback information giving label locations. + * Keyed by the label name; the contents are a structure giving + * the label location and its layer. + */ +HashTable feedHash; + +typedef struct +{ + char *li_layer; + char *li_label; + Rect li_area; +} LabInfo; + +int +main(argc, argv) + char *argv[]; +{ + char line1[LINESIZE], line2[LINESIZE], layer[LINESIZE], label[LINESIZE]; + HashEntry *he; + LabInfo *li; + int nterms; + FILE *fp; + char *cp; + Rect r; + + if (argc != 3) + { + fprintf(stderr, "Usage: net2ir feedfile netfile\n"); + exit (1); + } + + /* Process the feedback file, building the hash table of label locs */ + HashInit(&feedHash, INITHASHSIZE, HT_STRINGKEYS); + fp = fopen(argv[1], "r"); + if (fp == NULL) + { + perror(argv[1]); + exit (1); + } + + while (fgets(line1, sizeof line1, fp)) + { +getfirst: + if (sscanf(line1, "box %d %d %d %d", &r.r_xbot, &r.r_ybot, + &r.r_xtop, &r.r_ytop) != 4) + continue; + if (fgets(line2, sizeof line2, fp) == NULL) + break; + if (sscanf(line2, "feedback add \"%[^;];%[^\"]", layer, label) != 2) + { + strcpy(line1, line2); + goto getfirst; + } + + he = HashFind(&feedHash, label); + if (HashGetValue(he)) + { + fprintf(stderr, + "Warning: multiple locs for label %s; 2nd loc ignored.\n", + label); + continue; + } + li = (LabInfo *) mallocMagic((unsigned) (sizeof (LabInfo))); + GEO_EXPAND(&r, -1, &li->li_area); + li->li_label = StrDup((char **) NULL, label); + li->li_layer = StrDup((char **) NULL, layer); + HashSetValue(he, (ClientData) li); + } + (void) fclose(fp); + + /* Process the net file */ + fp = fopen(argv[2], "r"); + if (fp == NULL) + { + perror(argv[2]); + exit (1); + } + + nterms = 0; + while (fgets(line1, sizeof line1, fp)) + { + if (isspace(line1[0]) || line1[0] == '\0') + { + nterms = 0; + continue; + } + + if (cp = strchr(line1, '\n')) + *cp = '\0'; + + if (nterms >= 2) + { + fprintf(stderr, "Net with >2 terms ignored: %s\n", line1); + continue; + } + + he = HashLookOnly(&feedHash, line1); + if (he == NULL || (li = (LabInfo *) HashGetValue(he)) == NULL) + { + fprintf(stderr, "No location for terminal %s\n", line1); + continue; + } + + if(nterms == 0) + { + printf(":iroute route -slayers %s -sPoint %d %d ", + li->li_layer, + li->li_area.r_xbot, + li->li_area.r_ybot); + } + else + { + printf("-dlayers %s -dRect %d %d %d %d\n", + li->li_layer, + li->li_area.r_xbot, + li->li_area.r_ybot, + li->li_area.r_xtop, + li->li_area.r_ytop); + } + nterms++; + } + exit(0); +} + diff --git a/netmenu/Depend b/netmenu/Depend new file mode 100644 index 00000000..fc9a91a5 --- /dev/null +++ b/netmenu/Depend @@ -0,0 +1,46 @@ +NMbutton.o: NMbutton.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../windows/windows.h ../graphics/graphics.h ../dbwind/dbwind.h \ + ../textio/textio.h ../textio/txcommands.h ../netmenu/nmInt.h \ + ../netmenu/netmenu.h ../utils/styles.h ../utils/main.h +NMcmdAK.o: NMcmdAK.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../windows/windows.h \ + ../textio/txcommands.h ../netmenu/nmInt.h ../netmenu/netmenu.h \ + ../utils/main.h ../textio/textio.h ../utils/malloc.h +NMcmdLZ.o: NMcmdLZ.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../windows/windows.h \ + ../textio/txcommands.h ../netmenu/nmInt.h ../netmenu/netmenu.h \ + ../dbwind/dbwind.h ../utils/styles.h ../utils/main.h ../textio/textio.h +NMlabel.o: NMlabel.c ../utils/magic.h ../utils/geometry.h \ + ../utils/utils.h ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../windows/windows.h ../utils/main.h ../dbwind/dbwind.h \ + ../netmenu/nmInt.h ../textio/textio.h ../textio/txcommands.h \ + ../commands/commands.h ../utils/styles.h ../utils/malloc.h +NMmain.o: NMmain.c ../utils/magic.h ../utils/geometry.h \ + ../windows/windows.h ../graphics/graphics.h ../graphics/glyphs.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../dbwind/dbwind.h ../textio/textio.h ../utils/styles.h \ + ../textio/txcommands.h ../netmenu/nmInt.h ../netmenu/netmenu.h \ + ../utils/undo.h +NMnetlist.o: NMnetlist.c ../utils/magic.h ../utils/utils.h \ + ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../windows/windows.h ../utils/main.h \ + ../textio/textio.h ../netmenu/nmInt.h ../utils/undo.h ../utils/malloc.h \ + ../netmenu/netmenu.h +NMshowpt.o: NMshowpt.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../windows/windows.h ../graphics/graphics.h ../dbwind/dbwind.h \ + ../utils/styles.h ../utils/main.h ../utils/malloc.h +NMshowcell.o: NMshowcell.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../windows/windows.h ../graphics/graphics.h ../dbwind/dbwind.h \ + ../utils/styles.h ../textio/textio.h ../utils/main.h ../netmenu/nmInt.h +NMundo.o: NMundo.c ../utils/magic.h ../utils/geometry.h \ + ../windows/windows.h ../netmenu/netmenu.h ../netmenu/nmInt.h \ + ../utils/undo.h ../utils/utils.h +NMwiring.o: NMwiring.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/main.h \ + ../netmenu/netmenu.h ../netmenu/nmInt.h ../textio/textio.h \ + ../utils/styles.h ../drc/drc.h ../utils/malloc.h ../router/router.h \ + ../utils/utils.h diff --git a/netmenu/Makefile b/netmenu/Makefile new file mode 100644 index 00000000..51eb7fdf --- /dev/null +++ b/netmenu/Makefile @@ -0,0 +1,11 @@ +# +# rcsid =$Header: /usr/cvsroot/magic-8.0/netmenu/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +MODULE = netmenu +MAGICDIR = .. +SRCS = NMbutton.c NMcmdAK.c NMcmdLZ.c NMlabel.c NMmain.c \ + NMnetlist.c NMshowpt.c NMshowcell.c NMundo.c NMwiring.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/netmenu/NMbutton.c b/netmenu/NMbutton.c new file mode 100644 index 00000000..3ff58b3b --- /dev/null +++ b/netmenu/NMbutton.c @@ -0,0 +1,509 @@ +/* NMbutton.c - + * + * This file contains routines that respond to button pushes + * in database windows when the netlist button handler is active. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/netmenu/NMbutton.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "dbwind/dbwind.h" +#include "textio/textio.h" +#include "textio/txcommands.h" +#include "netmenu/nmInt.h" +#include "netmenu/netmenu.h" +#include "utils/styles.h" +#include "utils/main.h" + +/* The following static holds the name of the current net. */ + +char *NMCurNetName = NULL; + +/* Maximimum amount of storage to hold terminal name: */ + +#define MAXTERMLENGTH 200 + +/* + * ---------------------------------------------------------------------------- + * + * NMButtonNetList -- + * + * This procedure is invoked when the button to switch netlists + * is clicked. + * + * Results: + * None. + * + * Side effects: + * The user is asked to type in a netlist name, and this name is + * used as the current netlist. If the right button was clicked, + * use the name of the edit cell as the name of the netlist. + * + * ---------------------------------------------------------------------------- + */ + +void +NMButtonNetList(window, cmd, nmButton, point) + MagWindow *window; /* Where button was clicked (not used). */ + NetButton *nmButton; /* Data structure for button (not used). */ + TxCommand *cmd; /* Used to figure out which button it was. */ + Point *point; /* Not used. */ +{ +#define MAXLENGTH 200 + char newName[MAXLENGTH]; + if (cmd->tx_button == TX_RIGHT_BUTTON) + NMNewNetlist(EditCellUse->cu_def->cd_name); + else + { + TxPrintf("New net list name: "); + if (TxGetLine(newName, MAXLENGTH) == NULL) newName[0] == 0; + if (newName[0] == 0) return; + NMNewNetlist(newName); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * nmButtonSetup -- + * + * This procedure does miscellaneous button dirty work. It + * makes sure that there's a current netlist (and prints an + * error if not), and finds the nearest terminal to the point + * location. + * + * Results: + * If everything is OK, the return value is a pointer to a + * statically-allocated string holding the nearest terminal + * location. If there's any problem, NULL is returned. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +char * +nmButtonSetup() +{ + Point rootPoint, editPoint; + Rect rootArea, searchArea, tmp1, tmp2; + int expand; + static char termName[MAXTERMLENGTH]; + MagWindow *w; + +#define SEARCHPIXELS 20 + + if (NMNetListButton.nmb_text == NULL) + { + TxError("There's no current netlist; please select one.\n"); + return NULL; + } + + /* Compute an area (in edit cell coordinates) that's SEARCHPIXELS + * around the cursor position, so that anything even close can + * be used to find a terminal. + */ + + w = ToolGetPoint(&rootPoint, &rootArea); + if (w == NULL) return NULL; + if (((CellUse *)(w->w_surfaceID))->cu_def != EditRootDef) + { + TxError("Sorry, but you have to use a window that's being edited.\n"); + return NULL; + } + tmp1.r_xbot = tmp1.r_ybot = tmp1.r_ytop = 0; + tmp1.r_xtop = SEARCHPIXELS; + WindScreenToSurface(w, &tmp1, &tmp2); + expand = tmp2.r_xtop - tmp2.r_xbot; + rootArea.r_xbot -= expand; + rootArea.r_xtop += expand; + rootArea.r_ybot -= expand; + rootArea.r_ytop += expand; + GeoTransPoint(&RootToEditTransform, &rootPoint, &editPoint); + GeoTransRect(&RootToEditTransform, &rootArea, &searchArea); + + if (!DBNearestLabel(EditCellUse, &searchArea, &editPoint, 0, + (Rect *) NULL, termName, MAXTERMLENGTH)) + { + TxPrintf("There's no terminal near the cursor.\n"); + return NULL; + } + + if(strchr(termName, '/')==0) + { + TxPrintf("You can't route to a terminal in the Edit cell!"); + TxPrintf(" Please select one in a subcell.\n"); + return NULL; + } + return termName; +} + +/* + * ---------------------------------------------------------------------------- + * + * NMButtonRight -- + * + * This procedure is invoked when the right button is pushed over + * a database window. It toggles the nearest terminal into or + * out of the current net. + * + * Results: + * None. + * + * Side effects: + * A terminal is added to or removed from a net, and the highlight + * information on the display is updated. + * + * ---------------------------------------------------------------------------- + */ + +void +NMButtonRight(w, cmd) + MagWindow *w; /* Window in which button was pushed. */ + TxCommand *cmd; /* Detailed information about command. */ +{ + char *name; + extern int nmButHighlightFunc(), nmButUnHighlightFunc(); + extern int nmButCheckFunc(), nmNewRefFunc(), nmFindNetNameFunc(); + + name = nmButtonSetup(); + if (name == NULL) return; + + if (NMCurNetName == NULL) + { + TxError("Use the left button to select a net first.\n"); + return; + } + + /* See if this terminal is already in the current net. */ + + if (NMEnumTerms(name, nmButCheckFunc, (ClientData) NMCurNetName)) + { + /* In the net already. Delete it from the net. But first, + * find another terminal in the net to use as a reference + * for the current net. If not, then null out the current net. + */ + + if (strcmp(name, NMCurNetName) == 0) + { + NMSelectNet((char *) NULL); + (void) NMEnumTerms(name, nmNewRefFunc, (ClientData) name); + } + NMUndo(name, NMCurNetName, NMUE_REMOVE); + (void) NMDeleteTerm(name); + (void) DBSrLabelLoc(EditCellUse, name, nmButUnHighlightFunc, + (ClientData) NULL); + TxPrintf("Removing \"%s\" from net.\n", name); + } + else + { + /* Not in the net already: add it in. But first, see if + * the terminal is already in a net. If it is, then remove + * it from that net. + */ + + if (NMTermInList(name) != NULL) + { + char *netName = name; + (void) NMEnumTerms(name, nmFindNetNameFunc, (ClientData) &netName); + if (netName != name) + { + TxPrintf("\"%s\" was already in a net;", name); + TxPrintf(" I'm removing it from the old net.\n"); + } + NMUndo(name, netName, NMUE_REMOVE); + (void) NMDeleteTerm(name); + } + NMUndo(name, NMCurNetName, NMUE_ADD); + (void) NMAddTerm(name, NMCurNetName); + (void) DBSrLabelLoc(EditCellUse, name, nmButHighlightFunc, + (ClientData) NULL); + TxPrintf("Adding \"%s\" to net.\n", name); + } +} + +/* This check function merely returns TRUE if a terminal in + * the net being enumerated matches some other given terminal. + */ + +int +nmButCheckFunc(name1, name2) + char *name1; /* Name of terminal in net. */ + char *name2; /* Name of other terminal. */ +{ + if (strcmp(name1, name2) == 0) return 1; + return 0; +} + +/* This function looks for a name of a terminal in a net that + * is different from a given name. The different name, if any, + * is stored in the clientdata. + */ + +int +nmFindNetNameFunc(name1, pname2) + char *name1; /* Name of terminal in net. */ + char **pname2; /* Pointer to name to be replaced with + * different name, if there is a different + * name in the net. + */ +{ + if (strcmp(name1, *pname2) == 0) return 0; + *pname2 = name1; + return 1; /* Abort search with new name. */ +} + + /* ARGSUSED */ +int +nmButHighlightFunc(area, name, label, pExists) + Rect *area; /* Area of the label. */ + char *name; /* Name of label. */ + Label *label; /* Pointer to label */ + bool *pExists; /* We just set this to TRUE. */ +{ + Rect rootArea; + Point point; + + GeoTransRect(&EditToRootTransform, area, &rootArea); + point.p_x = (rootArea.r_xbot + rootArea.r_xtop)/2; + point.p_y = (rootArea.r_ybot + rootArea.r_ytop)/2; + NMAddPoint(&point); + if (pExists != NULL) *pExists = TRUE; + return 0; +} + +int +nmButUnHighlightFunc(area) + Rect *area; /* Area of the label. */ +{ + Rect rootArea; + Point point; + + GeoTransRect(&EditToRootTransform, area, &rootArea); + point.p_x = (rootArea.r_xbot + rootArea.r_xtop)/2; + point.p_y = (rootArea.r_ybot + rootArea.r_ytop)/2; + NMDeletePoint(&point); + return 0; +} + +int +nmNewRefFunc(name, oldRef) + char *name; /* Name of a terminal in the net. */ + char *oldRef; /* Name we don't want to use as net reference + * anymore. + */ +{ + if (strcmp(name, oldRef) != 0) + { + NMSelectNet(name); + return 1; /* Abort search: we've found what we want. */ + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * NMSelectNet -- + * + * This routine selects a net and highlights it on the screen. + * + * Results: + * None. + * + * Side effects: + * The net containing terminal is selected. If there used to + * be a net selected, it is unselected. If name is NULL, + * all this procedure does is to unselect the previous net. + * + * ---------------------------------------------------------------------------- + */ + +void +NMSelectNet(name) + char *name; /* Gives name of terminal in net to be + * be selected. + */ +{ + extern int nmSelNetFunc(); + + NMUndo(name, NMCurNetName, NMUE_SELECT); + NMCurNetName = NULL; + NMClearPoints(); + + if (name == NULL) return; + + /* If this terminal isn't already in a net, return. */ + + NMCurNetName = NMTermInList(name); + TxPrintf("Selected net is now \"%s\".\n", NMCurNetName); + if (NMCurNetName == NULL) return; + + /* Highlight the entire net. */ + + (void) NMEnumTerms(name, nmSelNetFunc, (ClientData) NULL); +} + +/* For each terminal in the net, highlight each instance of the terminal. */ + +int +nmSelNetFunc(name) + char *name; +{ + bool exists; + + exists = FALSE; + (void) DBSrLabelLoc(EditCellUse, name, nmButHighlightFunc, + (ClientData) &exists); + if (!exists) TxPrintf("%s: not in circuit!\n", name); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * NMButtonLeft -- + * + * This procedure is invoked when the left button is pushed + * over a database window. It selects a new net. + * + * Results: + * None. + * + * Side effects: + * If there is a terminal near the cursor, it is selected as the + * current net and is highlighted on the screen. + * + * ---------------------------------------------------------------------------- + */ + +void +NMButtonLeft(w, cmd) + MagWindow *w; /* Window in which button was pushed. */ + TxCommand *cmd; /* Detailed information about the command. */ +{ + char *name; + + name = nmButtonSetup(); + if (name == NULL) + { + NMSelectNet((char *) NULL); + return; + } + + /* If this terminal isn't already in a net, start a new net. */ + + if (NMTermInList(name) == NULL) (void) NMAddTerm(name, name); + NMSelectNet(name); +} + +/* + * ---------------------------------------------------------------------------- + * + * NMButtonMiddle -- + * + * This procedure is invoked when the middle button is pressed in + * a database window. It joins the net of the nearest terminal + * into the current net. + * + * Results: + * None. + * + * Side effects: + * Two nets are joined together. The highlights on the screen + * reflect this. + * + * ---------------------------------------------------------------------------- + */ + +void +NMButtonMiddle(w, cmd) + MagWindow *w; /* Window in which button was pushed. */ + TxCommand *cmd; /* Detailed information about command. */ +{ + char *name; + + name = nmButtonSetup(); + if (name == NULL) return; + + if (NMCurNetName == NULL) + { + TxPrintf("Use the left button to select a name first.\n"); + return; + } + + /* Go through the new terminal's net and add everything to + * the list of stuff to be redisplayed. After this is done, + * join the nets. Note: if the terminal isn't in any net + * at all, make a new terminal. + */ + + if (NMTermInList(name) == NULL) (void) NMAddTerm(name, name); + (void) NMEnumTerms(name, nmSelNetFunc, (ClientData) NULL); + NMJoinNets(name, NMCurNetName); + + TxPrintf("Merging net \"%s\" into current net.\n", name); +} + +/* + * ---------------------------------------------------------------------------- + * + * NMButtonProc -- + * + * This is an alternate handler for button pushes in database + * windows. It is invoked from the dbwind module when netlist + * editing is in progress. This procedure just dispatches to + * the correct command procedure for the button. + * + * Results: + * None. + * + * Side effects: + * Whatever the command procedure for the button does. + * + * ---------------------------------------------------------------------------- + */ + +void +NMButtonProc(w, cmd) + MagWindow *w; /* Window in which button was pushed. */ + TxCommand *cmd; /* Detailed information about exactly what happened. */ +{ + if (cmd->tx_buttonAction != TX_BUTTON_DOWN) return; + switch (cmd->tx_button) + { + case TX_LEFT_BUTTON: + NMButtonLeft(w, cmd); + break; + case TX_RIGHT_BUTTON: + NMButtonRight(w, cmd); + break; + case TX_MIDDLE_BUTTON: + NMButtonMiddle(w, cmd); + break; + } +} diff --git a/netmenu/NMcmdAK.c b/netmenu/NMcmdAK.c new file mode 100644 index 00000000..165ca305 --- /dev/null +++ b/netmenu/NMcmdAK.c @@ -0,0 +1,605 @@ +/* NMcmd.c - + * + * This file contains routines to interpret commands typed inside + * netlist windows. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/netmenu/NMcmdAK.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "textio/txcommands.h" +#include "netmenu/nmInt.h" +#include "netmenu/netmenu.h" +#include "utils/main.h" +#include "textio/textio.h" +#include "utils/malloc.h" + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdAdd -- + * + * Add a terminal to another terminal's net, removing it from + * its old net (if it was in one). + * + * Usage: + * add term1 term2 + * + * Results: + * None. + * + * Side effects: + * The current netlist is modified. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +void +NMCmdAdd(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + if (cmd->tx_argc != 3) + { + TxError("Usage: add term1 term2\n"); + return; + } + if (!NMHasList()) + { + TxError("Select a netlist first.\n"); + return; + } + (void) NMAddTerm(cmd->tx_argv[1], cmd->tx_argv[2]); +} + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdCleanup -- + * + * Check the current netlist for terminals that aren't present in + * the design and for nets with only one terminal. When found, + * tell the user and try to clean up automatically wherever + * possible. + * + * Usage: + * cleanup + * + * Results: + * None. + * + * Side effects: + * The current netlist is modified. + * + * ---------------------------------------------------------------------------- + */ + +/* The following definitions and variables are shared between the + * procedures that implement the cleanup command. + */ + +struct nmcleanup +{ + char *nmcl_name; /* Name of terminal. */ + int nmcl_problem; /* Problem with this net: see defs. below. */ + struct nmcleanup *nmcl_next;/* Troubles are linked together into list. */ +}; + +#define NMCL_ONETERM 1 +#define NMCL_NOLABEL 2 + +static struct nmcleanup *nmCleanupList; + /* List of problem terminals, formulated + * during first pass. These are processed + * during the second pass. + */ +static int nmCleanupCount; /* How many terminals have been seen in the + * current net. + */ +static char *nmCleanupTerm; /* Current (or previous) terminal in list. */ + +extern int nmCleanupFunc1(), nmCleanupFunc2(); +extern void nmCleanupNet(); + + /* ARGSUSED */ +void +NMCmdCleanup(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + extern int nmCleanupFunc1(); /* Forward reference. */ + struct nmcleanup *p; + + if (cmd->tx_argc != 1) + { + TxError("Usage: cleanup\n"); + return; + } + if (!NMHasList()) + { + TxError("Select a netlist first.\n"); + return; + } + + /* Pass 1: collect information about problem areas. */ + + nmCleanupList = NULL; + nmCleanupCount = 0; + nmCleanupTerm = NULL; + (void) NMEnumNets(nmCleanupFunc1, (ClientData) NULL); + nmCleanupNet(); + + /* Pass 2: go over the list and ask the user what to do. This + * needs to be done in two passes because it may modify the + * netlist, and that is a dangerous thing to do while a search + * is in progress. + */ + + for (p = nmCleanupList; p != NULL; p = p->nmcl_next) + { + char answer[30]; + int indx, defaultValue; + static char *options[] = {"abort", "dnet", "dterm", "skip", NULL}; + + if (p->nmcl_problem == NMCL_ONETERM) + { + TxPrintf("Net \"%s\" has less than two terminals.\n", p->nmcl_name); + defaultValue = 1; + } + else + { + TxPrintf("\"%s\" doesn't exist in the circuit.\n", p->nmcl_name); + defaultValue = 2; + } + do + { + TxPrintf("Delete terminal (dterm), delete net (dnet), "); + TxPrintf("skip, or abort command? [%s] ", options[defaultValue]); + if (TxGetLine(answer, sizeof answer) == NULL) continue; + if (answer[0] == 0) indx = defaultValue; + else indx = Lookup(answer, options); + } while (indx < 0); + switch (indx) + { + case 0: + while (p != NULL) + { + freeMagic((char *) p); + p = p->nmcl_next; + } + return; + case 1: + NMDeleteNet(p->nmcl_name); + break; + case 2: + NMDeleteTerm(p->nmcl_name); + break; + } + freeMagic((char *) p); + } + + if (nmCleanupList == NULL) + TxPrintf("No problems found.\n"); +} + +/* Search function for NMCmdCleanup. This one is called for each + * terminal name. Always return 0 to keep the search from aborting. + */ + + /* ARGSUSED */ +int +nmCleanupFunc1(name, firstInNet, cdarg) + char *name; /* Name of terminal. */ + bool firstInNet; /* TRUE means first terminal of new net. */ + ClientData cdarg; /* Not used. */ +{ + int count; + struct nmcleanup *p; + + if (firstInNet) + { + nmCleanupNet(); + nmCleanupCount = 0; + } + count = 0; + nmCleanupTerm = name; + (void) DBSrLabelLoc(EditCellUse, name, nmCleanupFunc2, + (ClientData) &count); + if (count == 0) + { + p = (struct nmcleanup *) mallocMagic(sizeof(struct nmcleanup)); + p->nmcl_name = name; + p->nmcl_problem = NMCL_NOLABEL; + p->nmcl_next = nmCleanupList; + nmCleanupList = p; + } + else nmCleanupCount += count; + return 0; +} + +/* Another search function for NMCleanup, called by DBSrLabelLoc. + * This function just counts the terminal instances for a net. + */ + + /* ARGSUSED */ +int +nmCleanupFunc2(rect, name, label, pCount) + Rect *rect; /* Not used. */ + char *name; /* Not used. */ + Label *label; /* Not used. */ + int *pCount; /* Pointer to word to be incremented. */ +{ + *pCount += 1; + return 0; +} + +/* Called after each net has been seen, to make sure there were at + * least two terminal instances for the net. + */ + +void +nmCleanupNet() +{ + struct nmcleanup *p; + + if ((nmCleanupTerm != NULL) && (nmCleanupCount < 2)) + { + p = (struct nmcleanup *) mallocMagic(sizeof(struct nmcleanup)); + p->nmcl_name = nmCleanupTerm; + p->nmcl_problem = NMCL_ONETERM; + p->nmcl_next = nmCleanupList; + nmCleanupList = p; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdCull -- + * + * Check the current netlist against routing in the edit cell + * to remove nets that are already wired correctly. + * + * Usage: + * cull + * + * Results: + * None. + * + * Side effects: + * Feedback is created where there are problems with the routing. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +void +NMCmdCull(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + if (cmd->tx_argc != 1) + { + TxError("Usage: cull\n"); + return; + } + if (!NMHasList()) + { + TxError("Select a netlist first.\n"); + return; + } + NMCull(); +} + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdDnet -- + * + * Delete the net containing a particular named terminal. + * + * Usage: + * dnet name name ... + * + * Results: + * None. + * + * Side effects: + * The current netlist is modified. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +void +NMCmdDnet(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + int i; + + if (!NMHasList()) + { + TxError("Select a netlist first.\n"); + return; + } + if (cmd->tx_argc < 2) + { + if (NMCurNetName != NULL) + { + char *name; + name = NMCurNetName; + NMSelectNet((char *) NULL); + NMDeleteNet(name); + } + return; + } + for (i = 1; i < cmd->tx_argc; i++) + { + if (NMTermInList(cmd->tx_argv[i]) != NULL) + NMDeleteNet(cmd->tx_argv[i]); + else + { + TxError("\"%s\" isn't in the current netlist.", cmd->tx_argv[i]); + TxError(" Do you have the right netlist?.\n"); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdDterm -- + * + * Delete a particular terminal from its net. + * + * Usage: + * dterm name name ... + * + * Results: + * None. + * + * Side effects: + * The given terminal is removed from its net (if it's in a net). + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +void +NMCmdDterm(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + int i; + if (cmd->tx_argc < 2) + { + TxError("Usage: dterm name name ...\n"); + return; + } + if (!NMHasList()) + { + TxError("Select a netlist first.\n"); + return; + } + for (i = 1; i < cmd->tx_argc; i++) + { + if (NMTermInList(cmd->tx_argv[i]) != NULL) + NMDeleteTerm(cmd->tx_argv[i]); + else + { + TxError("\"%s\" isn't in the current netlist.", cmd->tx_argv[i]); + TxError(" Do you have the right netlist?.\n"); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdExtract -- + * + * Starting from paint underneath the box, chase out all + * electrically-connected material in the edit cell, locate + * terminals it touches, and put the terminals into a new + * net. + * + * Usage: + * extract + * + * Results: + * None. + * + * Side effects: + * The current netlist is modified. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +void +NMCmdExtract(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + if (cmd->tx_argc != 1) + { + TxError("Usage: extract\n"); + return; + } +/* + if (!NMHasList()) + { + TxError("Select a netlist first.\n"); + return; + } +*/ + NMExtract(); +} + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdFindLabels -- + * + * Use the current label as a search pattern and create feedback + * areas for all instances of labels with that pattern that lie + * beneath the box. + * + * Results: + * None. + * + * Side effects: + * New feedback areas get created. + * + * ---------------------------------------------------------------------------- + */ + + /*ARGSUSED*/ +void +NMCmdFindLabels(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + TileTypeBitMask mask, *pMask; + char *pattern; + + if (cmd->tx_argc < 2 || cmd->tx_argc > 3) + { + TxError("Usage: find pattern [layers]\n"); + return; + } + + pattern = cmd->tx_argv[1]; + pMask = (TileTypeBitMask *) NULL; + if (cmd->tx_argc == 3) + { + if (!CmdParseLayers(cmd->tx_argv[2], &mask)) + return; + pMask = &mask; + } + NMShowLabel(pattern, pMask); +} + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdFlush -- + * + * Flush a netlist, replacing it once again with the contents + * from disk. + * + * Usage: + * flush [netlist] + * + * Results: + * None. + * + * Side effects: + * Changes made to netlist "netlist" may be lost. + * + * ---------------------------------------------------------------------------- + */ + /* ARGSUSED */ +void +NMCmdFlush(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + char *name; + + if (cmd->tx_argc >= 3) + { + TxError("Usage: flush [netlist]\n"); + return; + } + if (cmd->tx_argc == 1) + { + name = NMNetListButton.nmb_text; + if (name[0] == 0) + { + TxError("There's no current netlist to flush.\n"); + return; + } + } + else name = cmd->tx_argv[1]; + + NMFlushNetlist(name); +} + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdJoinNets -- + * + * Join two nets together into a single net. + * + * Usage: + * joinnets term1 term2 + * + * Results: + * None. + * + * Side effects: + * The current netlist is modified. + * + * Notes + * This command was previously called "join" but conflicts with + * the Tcl command of the same name, and for which the syntax is + * not distinct. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +void +NMCmdJoinNets(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + if (cmd->tx_argc != 3) + { + TxError("Usage: joinnets term1 term2\n"); + return; + } + if (!NMHasList()) + { + TxError("Select a netlist first.\n"); + return; + } + if (NMTermInList(cmd->tx_argv[1]) == (char *) NULL) + { + TxError("\"%s\" isn't in a net, so can't join it.\n", + cmd->tx_argv[1]); + return; + } + if (NMTermInList(cmd->tx_argv[2]) == (char *) NULL) + { + TxError("\"%s\" isn't in a net, so can't join it.\n", + cmd->tx_argv[2]); + return; + } + NMJoinNets(cmd->tx_argv[1], cmd->tx_argv[2]); +} diff --git a/netmenu/NMcmdLZ.c b/netmenu/NMcmdLZ.c new file mode 100644 index 00000000..5522968a --- /dev/null +++ b/netmenu/NMcmdLZ.c @@ -0,0 +1,572 @@ +/* NMcmdLZ.c - + * + * This file contains routines to interpret commands typed inside + * netlist windows. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/netmenu/NMcmdLZ.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "textio/txcommands.h" +#include "netmenu/nmInt.h" +#include "netmenu/netmenu.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "utils/main.h" +#include "textio/textio.h" + + +#ifdef ROUTE_MODULE + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdMeasure -- + * + * Measure the metal, poly, and contacts on the selected net. If "all" + * is specified, then measure for all nets. + * + * Results: + * None. + * + * Side effects: + * Prints the routing statistics. + * + * ---------------------------------------------------------------------------- + */ + /* ARGSUSED */ +void +NMCmdMeasure(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + FILE * fp, * fopen(); + + if (cmd->tx_argc > 3) + { + TxError("Usage: measure [all [filename]]\n"); + return; + } + if (cmd->tx_argc == 1) + NMMeasureNet(); + else + if (NMNetlistName() == (char *) NULL) + { + TxError("First select a net list!\n"); + return; + } + else + if (strcmp(cmd->tx_argv[1], "all") != 0) + { + TxError("Unknown option \"%s\"\n", cmd->tx_argv[1]); + return; + } + else + if (cmd->tx_argc == 2) + NMMeasureAll((FILE *) NULL); + else + { + if((fp = fopen(cmd->tx_argv[2], "w"))==NULL) + { + TxError("Can't open %s\n", cmd->tx_argv[2]); + return; + } + TxPrintf("Log file is %s\n", cmd->tx_argv[2]); + NMMeasureAll(fp); + (void) fclose(fp); + } +} + +#endif + + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdNetlist -- + * + * Select a particular netlist for working on. + * + * Usage: + * netlist [name] + * + * (name defaults to the name of the edit cell) + * + * Results: + * None. + * + * Side effects: + * The netlist name.net is read from disk (if it hasn't already + * been loaded before) and is made the current netlist. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +void +NMCmdNetlist(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + if (cmd->tx_argc > 2) + { + TxError("Usage: netlist [name]\n"); + return; + } + if (cmd->tx_argc < 2) + NMNewNetlist(EditCellUse->cu_def->cd_name); + else NMNewNetlist(cmd->tx_argv[1]); +} + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdPrint -- + * + * Prints out the terminals in the current net. + * + * Usage: + * print + * + * Results: + * None. + * + * Side effects: + * Stuff is printed. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +void +NMCmdPrint(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + extern int nmCmdPrintFunc(); + int gotAny; + char *name; + + if (cmd->tx_argc == 1) + { + if (NMCurNetName == NULL) + { + TxError("Can't print current net: there's nothing selected!\n"); + return; + } + name = NMCurNetName; + } + else + { + name = cmd->tx_argv[1]; + if (cmd->tx_argc != 2) + { + TxError("Usage: print [name]\n"); + return; + } + } + + gotAny = FALSE; + (void) NMEnumTerms(name, nmCmdPrintFunc, (ClientData) &gotAny); + if (gotAny == FALSE) + TxError("There's nothing in the current net!\n"); +} + +int +nmCmdPrintFunc(name, pGotAny) + char *name; /* Name of terminal. */ + int *pGotAny; /* Pointer to integer, initially FALSE. */ +{ + if (*pGotAny == FALSE) + { + TxPrintf("Nodes in net:\n"); + *pGotAny = TRUE; + } + TxPrintf(" %s\n", name); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * NMCmdPushButton -- + * + * Perform the default button action for the netlist window. + * This allows button actions to be bound to keys or buttons + * arbitrarily, rather than being hardwired into the source. + * + * Usage: + * pushbutton button + * + * Results: + * None. + * + * Side effects: + * Invokes the command associated with the button action. + * + * ---------------------------------------------------------------------------- + */ + +void +NMCmdPushButton(w, cmd) + MagWindow *w; /* Netlist window. */ + TxCommand *cmd; /* Contains the command's argc and argv. */ +{ + int button, action; + static char *NMButton[] = {"left", "middle", "right", NULL}; + + if (cmd->tx_argc != 2) + { + TxError("Usage: pushbutton

\n", __LINE__)); + } + $in_menu = 0; + $in_menu_listing = 0; + next; + } + if ($in_menu) + { + my ($node, $name, $descr); + if (/^\*\s+($NODERE)::/o) + { + $node = $1; + $descr = $'; + } + elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) + { + $name = $1; + $node = $2; + $descr = $'; + } + elsif (/^\*/) + { + warn "$ERROR Bad menu line: $_"; + } + else + { + if ($in_menu_listing) + { + $in_menu_listing = 0; + push(@lines2, &debug("\n", __LINE__)); + } + # should be like verbatim -- preseve spaces, etc + s/ /\ /g; + $_ .= "
\n"; + push(@lines2, $_); + } + if ($node) + { + if (! $in_menu_listing) + { + $in_menu_listing = 1; + push(@lines2, &debug("\n", __LINE__)); + } + # look for continuation + while ($lines[0] =~ /^\s+\w+/) + { + $descr .= shift(@lines); + } + &menu_entry($node, $name, $descr); + } + next; + } + # + # printindex + # + PrintIndex(\@lines2, $2, $1), next + if (/^\@printindex\s+(\w+)/); + # + # simple style substitutions + # + $_ = &substitute_style($_); + # + # xref + # + while (/\@(x|px|info|)ref{([^{}]+)(}?)/) { + # note: Texinfo may accept other characters + ($type, $nodes, $full) = ($1, $2, $3); + ($before, $after) = ($`, $'); + if (! $full && $after) { + warn "$ERROR Bad xref (no ending } on line): $_"; + $_ = "$before$;0${type}ref\{$nodes$after"; + next; # while xref + } + if ($type eq 'x') { + $type = "$T2H_WORDS->{$T2H_LANG}->{'See'} "; + } elsif ($type eq 'px') { + $type = "$T2H_WORDS->{$T2H_LANG}->{'see'} "; + } elsif ($type eq 'info') { + $type = "$T2H_WORDS->{$T2H_LANG}->{'See'} Info"; + } else { + $type = ''; + } + unless ($full) { + $next = shift(@lines); + $next = &substitute_style($next); + chop($nodes); # remove final newline + if ($next =~ /\}/) { # split on 2 lines + $nodes .= " $`"; + $after = $'; + } else { + $nodes .= " $next"; + $next = shift(@lines); + $next = &substitute_style($next); + chop($nodes); + if ($next =~ /\}/) { # split on 3 lines + $nodes .= " $`"; + $after = $'; + } else { + warn "$ERROR Bad xref (no ending }): $_"; + $_ = "$before$;0xref\{$nodes$after"; + unshift(@lines, $next); + next; # while xref + } + } + } + $nodes =~ s/\s+/ /g; # remove useless spaces + @args = split(/\s*,\s*/, $nodes); + $node = $args[0]; # the node is always the first arg + $node = &normalise_node($node); + $sec = $args[2] || $args[1] || $node2sec{$node}; + $href = $node2href{$node}; + if (@args == 5) { # reference to another manual + $sec = $args[2] || $node; + $man = $args[4] || $args[3]; + $_ = "${before}${type}$T2H_WORDS->{$T2H_LANG}->{'section'} `$sec' in \@cite{$man}$after"; + } elsif ($type =~ /Info/) { # inforef + warn "$ERROR Wrong number of arguments: $_" unless @args == 3; + ($nn, $_, $in) = @args; + $_ = "${before}${type} file `$in', node `$nn'$after"; + } elsif ($sec && $href && ! $T2H_SHORT_REF) { + $_ = "${before}${type}"; + $_ .= "$T2H_WORDS->{$T2H_LANG}->{'section'} " if ${type}; + $_ .= &t2h_anchor('', $href, $sec) . $after; + } + elsif ($href) + { + $_ = "${before}${type} " . + &t2h_anchor('', $href, $args[2] || $args[1] || $node) . + $after; + } + else { + warn "$ERROR Undefined node ($node): $_"; + $_ = "$before$;0xref{$nodes}$after"; + } + } + + # replace images + s[\@image\s*{(.+?)}] + { + my @args = split (/\s*,\s*/, $1); + my $base = $args[0]; + my $image = + LocateIncludeFile("$base.png") || + LocateIncludeFile("$base.jpg") || + LocateIncludeFile("$base.gif"); + warn "$ERROR no image file for $base: $_" unless ($image && -e $image); + "\"$base\""; + ($T2H_CENTER_IMAGE ? + "
\"$base\"
" : + "\"$base\""); + }eg; + + # + # try to guess bibliography references or glossary terms + # + unless (/^/) { + $done .= $pre . &t2h_anchor('', $href, $what); + } else { + $done .= "$pre$what"; + } + $_ = $post; + } + $_ = $done . $_; + } + if ($T2H_USE_GLOSSARY) { + $done = ''; + while (/\b\w+\b/) { + ($pre, $what, $post) = ($`, $&, $'); + $entry = $what; + $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/; + $href = $gloss2href{$entry}; + if (defined($href) && $post !~ /^[^<]*<\/A>/) { + $done .= $pre . &t2h_anchor('', $href, $what); + } else { + $done .= "$pre$what"; + } + $_ = $post; + } + $_ = $done . $_; + } + } + # otherwise + push(@lines2, $_); +} +print "# end of pass 2\n" if $T2H_VERBOSE; + +# +# split style substitutions +# +while (@lines2) { + $_ = shift(@lines2); + # + # special case (protected sections) + # + if (/^$PROTECTTAG/o) { + push(@lines3, $_); + next; + } + # + # split style substitutions + # + $old = ''; + while ($old ne $_) { + $old = $_; + if (/\@(\w+)\{/) { + ($before, $style, $after) = ($`, $1, $'); + if (defined($style_map{$style})) { + $_ = $after; + $text = ''; + $after = ''; + $failed = 1; + while (@lines2) { + if (/\}/) { + $text .= $`; + $after = $'; + $failed = 0; + last; + } else { + $text .= $_; + $_ = shift(@lines2); + } + } + if ($failed) { + die "* Bad syntax (\@$style) after: $before\n"; + } else { + $text = &apply_style($style, $text); + $_ = "$before$text$after"; + } + } + } + } + # otherwise + push(@lines3, $_); +} +print "# end of pass 3\n" if $T2H_VERBOSE; + +#+++############################################################################ +# # +# Pass 4: foot notes, final cleanup # +# # +#---############################################################################ + +@foot_lines = (); # footnotes +@doc_lines = (); # final document +$end_of_para = 0; # true if last line is

+ +while (@lines3) { + $_ = shift(@lines3); + # + # special case (protected sections) + # + if (/^$PROTECTTAG/o) { + push(@doc_lines, $_); + $end_of_para = 0; + next; + } + # + # footnotes + # + while (/\@footnote([^\{\s]+)\{/) { + ($before, $d, $after) = ($`, $1, $'); + $_ = $after; + $text = ''; + $after = ''; + $failed = 1; + while (@lines3) { + if (/\}/) { + $text .= $`; + $after = $'; + $failed = 0; + last; + } else { + $text .= $_; + $_ = shift(@lines3); + } + } + if ($failed) { + die "* Bad syntax (\@footnote) after: $before\n"; + } else { + $foot_num++; + $docid = "DOCF$foot_num"; + $footid = "FOOT$foot_num"; + $foot = "($foot_num)"; + push(@foot_lines, "

" . &t2h_anchor($footid, "$d#$docid", $foot) . "

\n"); + $text = "

$text" unless $text =~ /^\s*

/; + push(@foot_lines, "$text\n"); + $_ = $before . &t2h_anchor($docid, "$docu_foot#$footid", $foot) . $after; + } + } + # + # remove unnecessary

+ # + if (/^\s*

\s*$/) { + next if $end_of_para++; + } else { + $end_of_para = 0; + } + # otherwise + push(@doc_lines, $_); +} + +print "# end of pass 4\n" if $T2H_VERBOSE; + +#+++############################################################################ +# # +# Pass 5: print things # +# # +#---############################################################################ + +$T2H_L2H = &l2h_FinishToLatex if ($T2H_L2H); +$T2H_L2H = &l2h_ToHtml if ($T2H_L2H); +$T2H_L2H = &l2h_InitFromHtml if ($T2H_L2H); + +# fix node2up, node2prev, node2next, if desired +if ($has_top_command) +{ + for $section (keys %sec2number) + { + $node = $sec2node{$section}; + $node2up{$node} = Sec2UpNode($section) unless $node2up{$node}; + $node2prev{$node} = Sec2PrevNode($section) unless $node2prev{$node}; + $node2next{$node} = Sec2NextNode($section) unless $node2next{$node}; + } +} + +# prepare %T2H_THISDOC +$T2H_THISDOC{fulltitle} = $value{'_title'} || $value{'_settitle'} || "Untitled Document"; +$T2H_THISDOC{title} = $value{'_settitle'} || $T2H_THISDOC{fulltitle}; +$T2H_THISDOC{author} = $value{'_author'}; +$T2H_THISDOC{subtitle} = $value{'_subtitle'}; +$T2H_THISDOC{shorttitle} = $value{'_shorttitle'}; +for $key (keys %T2H_THISDOC) +{ + $_ = &substitute_style($T2H_THISDOC{$key}); + &unprotect_texi; + s/\s*$//; + $T2H_THISDOC{$key} = $_; +} + +# if no sections, then simply print document as is +unless (@sections) +{ + print "# Writing content into $docu_top_file \n" if $T2H_VERBOSE; + open(FILE, "> $docu_top_file") + || die "$ERROR: Can't open $docu_top_file for writing: $!\n"; + + &$T2H_print_page_head(\*FILE); + $T2H_THIS_SECTION = \@doc_lines; + t2h_print_lines(\*FILE); + &$T2H_print_foot_navigation(\*FILE); + &$T2H_print_page_foot(\*FILE); + close(FILE); + goto Finish; +} + +# initialize $T2H_HREF, $T2H_NAME +%T2H_HREF = + ( + 'First' , sec_href($sections[0]), + 'Last', sec_href($sections[$#sections]), + 'About', $docu_about. '#SEC_About', + ); + +# prepare TOC, OVERVIEW, TOP +$T2H_TOC = \@toc_lines; +$T2H_OVERVIEW = \@stoc_lines; +if ($has_top) +{ + while (1) + { + $_ = shift @doc_lines; + last if /$TOPEND/; + push @$T2H_TOP, $_; + } + $T2H_HREF{'Top'} = $docu_top . '#SEC_Top'; +} +else +{ + $T2H_HREF{'Top'} = $T2H_HREF{First}; +} + +$node2href{Top} = $T2H_HREF{Top}; +$T2H_HREF{Contents} = $docu_toc.'#SEC_Contents' if @toc_lines; +$T2H_HREF{Overview} = $docu_stoc.'#SEC_OVERVIEW' if @stoc_lines; + +# settle on index +if ($T2H_INDEX_CHAPTER) +{ + $T2H_HREF{Index} = $node2href{normalise_node($T2H_INDEX_CHAPTER)}; + warn "$ERROR T2H_INDEX_CHAPTER '$T2H_INDEX_CHAPTER' not found\n" + unless $T2H_HREF{Index}; +} +if (! $T2H_HREF{Index} && $first_index_chapter) +{ + $T2H_INDEX_CHAPTER = $first_index_chapter; + $T2H_HREF{Index} = $node2href{$T2H_INDEX_CHAPTER}; +} + +print "# Using '" . clean_name($T2H_INDEX_CHAPTER) . "' as index page\n" + if ($T2H_VERBOSE && $T2H_HREF{Index}); + +%T2H_NAME = + ( + 'First', clean_name($sec2node{$sections[0]}), + 'Last', clean_name($sec2node{$sections[$#sections]}), + 'About', $T2H_WORDS->{$T2H_LANG}->{'About_Title'}, + 'Contents', $T2H_WORDS->{$T2H_LANG}->{'ToC_Title'}, + 'Overview', $T2H_WORDS->{$T2H_LANG}->{'Overview_Title'}, + 'Index' , clean_name($T2H_INDEX_CHAPTER), + 'Top', clean_name($T2H_TOP_HEADING || $T2H_THISDOC{'title'} || $T2H_THISDOC{'shorttitle'}), + ); + +############################################################################# +# print frame and frame toc file +# +if ( $T2H_FRAMES ) +{ + open(FILE, "> $docu_frame_file") + || die "$ERROR: Can't open $docu_frame_file for writing: $!\n"; + print "# Creating frame in $docu_frame_file ...\n" if $T2H_VERBOSE; + &$T2H_print_frame(\*FILE); + close(FILE); + + open(FILE, "> $docu_toc_frame_file") + || die "$ERROR: Can't open $docu_toc_frame_file for writing: $!\n"; + print "# Creating toc frame in $docu_frame_file ...\n" if $T2H_VERBOSE; + &$T2H_print_toc_frame(\*FILE); + close(FILE); +} + + +############################################################################# +# print Top +# +open(FILE, "> $docu_top_file") + || die "$ERROR: Can't open $docu_top_file for writing: $!\n"; +&$T2H_print_page_head(\*FILE) unless ($T2H_SPLIT); + +if ($has_top) +{ + print "# Creating Top in $docu_top_file ...\n" if $T2H_VERBOSE; + $T2H_THIS_SECTION = $T2H_TOP; + $T2H_HREF{This} = $T2H_HREF{Top}; + $T2H_NAME{This} = $T2H_NAME{Top}; + &$T2H_print_Top(\*FILE); +} + +close(FILE) if $T2H_SPLIT; + +############################################################################# +# Print sections +# +$T2H_NODE{Forward} = $sec2node{$sections[0]}; +$T2H_NAME{Forward} = &clean_name($sec2node{$sections[0]}); +$T2H_HREF{Forward} = sec_href($sections[0]); +$T2H_NODE{This} = 'Top'; +$T2H_NAME{This} = $T2H_NAME{Top}; +$T2H_HREF{This} = $T2H_HREF{Top}; +if ($T2H_SPLIT) +{ + print "# writing " . scalar(@sections) . + " sections in $docu_rdir$docu_name"."_[1..$doc_num]" + if $T2H_VERBOSE; + $previous = ($T2H_SPLIT eq 'chapter' ? $CHAPTEREND : $SECTIONEND); + undef $FH; + $doc_num = 0; +} +else +{ + print "# writing " . scalar(@sections) . " sections in $docu_top_file ..." + if $T2H_VERBOSE; + $FH = \*FILE; + $previous = ''; +} + +$counter = 0; +# loop through sections +while ($section = shift(@sections)) +{ + if ($T2H_SPLIT && ($T2H_SPLIT eq 'section' || $previous eq $CHAPTEREND)) + { + if ($FH) + { + #close previous page + &$T2H_print_chapter_footer($FH) if $T2H_SPLIT eq 'chapter'; + &$T2H_print_page_foot($FH); + close($FH); + undef $FH; + } + } + $T2H_NAME{Back} = $T2H_NAME{This}; + $T2H_HREF{Back} = $T2H_HREF{This}; + $T2H_NODE{Back} = $T2H_NODE{This}; + $T2H_NAME{This} = $T2H_NAME{Forward}; + $T2H_HREF{This} = $T2H_HREF{Forward}; + $T2H_NODE{This} = $T2H_NODE{Forward}; + if ($sections[0]) + { + $T2H_NODE{Forward} = $sec2node{$sections[0]}; + $T2H_NAME{Forward} = &clean_name($T2H_NODE{Forward}); + $T2H_HREF{Forward} = sec_href($sections[0]); + } + else + { + undef $T2H_HREF{Forward}, $T2H_NODE{Forward}, $T2H_NAME{Forward}; + } + + $node = $node2up{$T2H_NODE{This}}; + $T2H_HREF{Up} = $node2href{$node}; + if ($T2H_HREF{Up} eq $T2H_HREF{This} || ! $T2H_HREF{Up}) + { + $T2H_NAME{Up} = $T2H_NAME{Top}; + $T2H_HREF{Up} = $T2H_HREF{Top}; + $T2H_NODE{Up} = 'Up'; + } + else + { + $T2H_NAME{Up} = &clean_name($node); + $T2H_NODE{Up} = $node; + } + + $node = $T2H_NODE{This}; + $node = $node2prev{$node}; + $T2H_NAME{Prev} = &clean_name($node); + $T2H_HREF{Prev} = $node2href{$node}; + $T2H_NODE{Prev} = $node; + + $node = $T2H_NODE{This}; + if ($node2up{$node} && $node2up{$node} ne 'Top'&& + ($node2prev{$node} eq $T2H_NODE{Back} || ! $node2prev{$node})) + { + $node = $node2up{$node}; + while ($node && $node ne $node2up{$node} && ! $node2prev{$node}) + { + $node = $node2up{$node}; + } + $node = $node2prev{$node} + unless $node2up{$node} eq 'Top' || ! $node2up{$node}; + } + else + { + $node = $node2prev{$node}; + } + $T2H_NAME{FastBack} = &clean_name($node); + $T2H_HREF{FastBack} = $node2href{$node}; + $T2H_NODE{FastBack} = $node; + + $node = $T2H_NODE{This}; + $node = $node2next{$node}; + $T2H_NAME{Next} = &clean_name($node); + $T2H_HREF{Next} = $node2href{$node}; + $T2H_NODE{Next} = $node; + + $node = $T2H_NODE{This}; + if ($node2up{$node} && $node2up{$node} ne 'Top'&& + ($node2next{$node} eq $T2H_NODE{Forward} || ! $node2next{$node})) + { + $node = $node2up{$node}; + while ($node && $node ne $node2up{$node} && ! $node2next{$node}) + { + $node = $node2up{$node}; + } + } + $node = $node2next{$node}; + $T2H_NAME{FastForward} = &clean_name($node); + $T2H_HREF{FastForward} = $node2href{$node}; + $T2H_NODE{FastForward} = $node; + + if (! defined($FH)) + { + my $file = $T2H_HREF{This}; + $file =~ s/\#.*$//; + open(FILE, "> $docu_rdir$file") || + die "$ERROR: Can't open $docu_rdir$file for writing: $!\n"; + $FH = \*FILE; + &$T2H_print_page_head($FH); + t2h_print_label($FH); + &$T2H_print_chapter_header($FH) if $T2H_SPLIT eq 'chapter'; + } + else + { + t2h_print_label($FH); + } + + $T2H_THIS_SECTION = []; + while (@doc_lines) { + $_ = shift(@doc_lines); + last if ($_ eq $SECTIONEND || $_ eq $CHAPTEREND); + push(@$T2H_THIS_SECTION, $_); + } + $previous = $_; + &$T2H_print_section($FH); + + if ($T2H_VERBOSE) + { + $counter++; + print "." if $counter =~ /00$/; + } +} +if ($T2H_SPLIT) +{ + &$T2H_print_chapter_footer($FH) if $T2H_SPLIT eq 'chapter'; + &$T2H_print_page_foot($FH); + close($FH); +} +print "\n" if $T2H_VERBOSE; + +############################################################################# +# Print ToC, Overview, Footnotes +# +undef $T2H_HREF{Prev}; +undef $T2H_HREF{Next}; +undef $T2H_HREF{Back}; +undef $T2H_HREF{Forward}; +undef $T2H_HREF{Up}; + +if (@foot_lines) +{ + print "# writing Footnotes in $docu_foot_file...\n" if $T2H_VERBOSE; + open (FILE, "> $docu_foot_file") || die "$ERROR: Can't open $docu_foot_file for writing: $!\n" + if $T2H_SPLIT; + $T2H_HREF{This} = $docu_foot; + $T2H_NAME{This} = $T2H_WORDS->{$T2H_LANG}->{'Footnotes_Title'}; + $T2H_THIS_SECTION = \@foot_lines; + &$T2H_print_Footnotes(\*FILE); + close(FILE) if $T2H_SPLIT; +} + +if (@toc_lines) +{ + print "# writing Toc in $docu_toc_file...\n" if $T2H_VERBOSE; + open (FILE, "> $docu_toc_file") || die "$ERROR: Can't open $docu_toc_file for writing: $!\n" + if $T2H_SPLIT; + $T2H_HREF{This} = $T2H_HREF{Contents}; + $T2H_NAME{This} = $T2H_NAME{Contents}; + $T2H_THIS_SECTION = \@toc_lines; + &$T2H_print_Toc(\*FILE); + close(FILE) if $T2H_SPLIT; +} + +if (@stoc_lines) +{ + print "# writing Overview in $docu_stoc_file...\n" if $T2H_VERBOSE; + open (FILE, "> $docu_stoc_file") || die "$ERROR: Can't open $docu_stoc_file for writing: $!\n" + if $T2H_SPLIT; + + $T2H_HREF{This} = $T2H_HREF{Overview}; + $T2H_NAME{This} = $T2H_NAME{Overview}; + $T2H_THIS_SECTION = \@stoc_lines; + unshift @$T2H_THIS_SECTION, "

\n"; + push @$T2H_THIS_SECTION, "\n
\n"; + &$T2H_print_Overview(\*FILE); + close(FILE) if $T2H_SPLIT; +} + +if ($about_body = &$T2H_about_body()) +{ + print "# writing About in $docu_about_file...\n" if $T2H_VERBOSE; + open (FILE, "> $docu_about_file") || die "$ERROR: Can't open $docu_about_file for writing: $!\n" + if $T2H_SPLIT; + + $T2H_HREF{This} = $T2H_HREF{About}; + $T2H_NAME{This} = $T2H_NAME{About}; + $T2H_THIS_SECTION = [$about_body]; + &$T2H_print_About(\*FILE); + close(FILE) if $T2H_SPLIT; +} + +unless ($T2H_SPLIT) +{ + &$T2H_print_page_foot(\*FILE); + close (FILE); +} + +Finish: +&l2h_FinishFromHtml if ($T2H_L2H); +&l2h_Finish if($T2H_L2H); +print "# that's all folks\n" if $T2H_VERBOSE; + +exit(0); + +#+++############################################################################ +# # +# Low level functions # +# # +#---############################################################################ + +sub LocateIncludeFile +{ + my $file = shift; + my $dir; + + return $file if (-e $file && -r $file); + foreach $dir (@T2H_INCLUDE_DIRS) + { + return "$dir/$file" if (-e "$dir/$file" && -r "$dir/$file"); + } + return undef; +} + +sub clean_name +{ + local ($_); + $_ = &remove_style($_[0]); + &unprotect_texi; + return $_; +} + +sub update_sec_num { + local($name, $level) = @_; + my $ret; + + $level--; # here we start at 0 + if ($name =~ /^appendix/ || defined(@appendix_sec_num)) { + # appendix style + if (defined(@appendix_sec_num)) { + &incr_sec_num($level, @appendix_sec_num); + } else { + @appendix_sec_num = ('A', 0, 0, 0); + } + $ret = join('.', @appendix_sec_num[0..$level]); + } else { + # normal style + if (defined(@normal_sec_num)) + { + &incr_sec_num($level, @normal_sec_num); + } + else + { + @normal_sec_num = (1, 0, 0, 0); + } + $ret = join('.', @normal_sec_num[0..$level]); + } + + $ret .= "." if $level == 0; + return $ret; +} + +sub incr_sec_num { + local($level, $l); + $level = shift(@_); + $_[$level]++; + foreach $l ($level+1 .. 3) { + $_[$l] = 0; + } +} + +sub Sec2UpNode +{ + my $sec = shift; + my $num = $sec2number{$sec}; + + return '' unless $num; + return 'Top' unless $num =~ /\.\d+/; + $num =~ s/\.[^\.]*$//; + $num = $num . '.' unless $num =~ /\./; + return $sec2node{$number2sec{$num}}; +} + +sub Sec2PrevNode +{ + my $sec = shift; + my $num = $sec2number{$sec}; + my ($i, $post); + + if ($num =~ /(\w+)(\.$|$)/) + { + $num = $`; + $i = $1; + $post = $2; + if ($i eq 'A') + { + $i = $normal_sec_num[0]; + } + elsif ($i ne '1') + { + # unfortunately, -- operator is not magical + $i = chr(ord($i) + 1); + } + else + { + return ''; + } + return $sec2node{$number2sec{$num . $i . $post}} + } + return ''; +} + +sub Sec2NextNode +{ + my $sec = shift; + my $num = $sec2number{$sec}; + my $i; + + if ($num =~ /(\w+)(\.$|$)/) + { + $num = $`; + $i = $1; + $post = $2; + if ($post eq '.' && $i eq $normal_sec_num[0]) + { + $i = 'A'; + } + else + { + $i++; + } + return $sec2node{$number2sec{$num . $i . $post}} + } + return ''; +} + +sub check { + local($_, %seen, %context, $before, $match, $after); + + while (<>) { + if (/\@(\*|\.|\:|\@|\{|\})/) { + $seen{$&}++; + $context{$&} .= "> $_" if $T2H_VERBOSE; + $_ = "$`XX$'"; + redo; + } + if (/\@(\w+)/) { + ($before, $match, $after) = ($`, $&, $'); + if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address + $seen{'e-mail address'}++; + $context{'e-mail address'} .= "> $_" if $T2H_VERBOSE; + } else { + $seen{$match}++; + $context{$match} .= "> $_" if $T2H_VERBOSE; + } + $match =~ s/^\@/X/; + $_ = "$before$match$after"; + redo; + } + } + + foreach (sort(keys(%seen))) { + if ($T2H_VERBOSE) { + print "$_\n"; + print $context{$_}; + } else { + print "$_ ($seen{$_})\n"; + } + } +} + +sub open { + local($name) = @_; + + ++$fh_name; + if (open($fh_name, $name)) { + unshift(@fhs, $fh_name); + } else { + warn "$ERROR Can't read file $name: $!\n"; + } +} + +sub init_input { + @fhs = (); # hold the file handles to read + @input_spool = (); # spooled lines to read + $fh_name = 'FH000'; + &open($docu); +} + +sub next_line { + local($fh, $line); + + if (@input_spool) { + $line = shift(@input_spool); + return($line); + } + while (@fhs) { + $fh = $fhs[0]; + $line = <$fh>; + return($line) if $line; + close($fh); + shift(@fhs); + } + return(undef); +} + +# used in pass 1, use &next_line +sub skip_until { + local($tag) = @_; + local($_); + + while ($_ = &next_line) { + return if /^\@end\s+$tag\s*$/; + } + die "* Failed to find '$tag' after: " . $lines[$#lines]; +} + +# used in pass 1 for l2h use &next_line +sub string_until { + local($tag) = @_; + local($_, $string); + + while ($_ = &next_line) { + return $string if /^\@end\s+$tag\s*$/; +# $_ =~ s/hbox/mbox/g; + $string = $string.$_; + } + die "* Failed to find '$tag' after: " . $lines[$#lines]; +} + +# +# HTML stacking to have a better HTML output +# + +sub html_reset { + @html_stack = ('html'); + $html_element = 'body'; +} + +sub html_push { + local($what) = @_; + push(@html_stack, $html_element); + $html_element = $what; +} + +sub html_push_if { + local($what) = @_; + push(@html_stack, $html_element) + if ($html_element && $html_element ne 'P'); + $html_element = $what; +} + +sub html_pop { + $html_element = pop(@html_stack); +} + +sub html_pop_if { + local($elt); + + if (@_) { + foreach $elt (@_) { + if ($elt eq $html_element) { + $html_element = pop(@html_stack) if @html_stack; + last; + } + } + } else { + $html_element = pop(@html_stack) if @html_stack; + } +} + +sub html_debug { + local($what, $line) = @_; + if ($T2H_DEBUG & $DEBUG_HTML) + { + $what = "\n" unless $what; + return("$what") + } + return($what); +} + +# to debug the output... +sub debug { + local($what, $line) = @_; + return("$what") + if $T2H_DEBUG & $DEBUG_HTML; + return($what); +} + +sub SimpleTexi2Html +{ + local $_ = $_[0]; + &protect_texi; + &protect_html; + $_ = substitute_style($_); + $_[0] = $_; +} + +sub normalise_node { + local $_ = $_[0]; + s/\s+/ /g; + s/ $//; + s/^ //; + &protect_texi; + &protect_html; + $_ = substitute_style($_); + $_[0] = $_; +} + +sub menu_entry +{ + my ($node, $name, $descr) = @_; + my ($href, $entry); + + &normalise_node($node); + $href = $node2href{$node}; + if ($href) + { + $descr =~ s/^\s+//; + $descr =~ s/\s*$//; + $descr = SimpleTexi2Html($descr); + if ($T2H_NUMBER_SECTIONS && !$T2H_NODE_NAME_IN_MENU && $node2sec{$node}) + { + $entry = $node2sec{$node}; + $name = ''; + } + else + { + &normalise_node($name); + $entry = ($name && ($name ne $node || ! $T2H_AVOID_MENU_REDUNDANCY) + ? "$name : $node" : $node); + } + + if ($T2H_AVOID_MENU_REDUNDANCY && $descr) + { + my $clean_entry = $entry; + $clean_entry =~ s/^.*? // if ($clean_entry =~ /^([A-Z]|\d+)\.[\d\.]* /); + $clean_entry =~ s/[^\w]//g; + my $clean_descr = $descr; + $clean_descr =~ s/[^\w]//g; + $descr = '' if ($clean_entry eq $clean_descr) + } + push(@lines2,&debug('
\n", __LINE__)); + } + elsif ($node =~ /^\(.*\)\w+/) + { + push(@lines2,&debug('\n", __LINE__)) + } + else + { + warn "$ERROR Undefined node of menu_entry ($node): $_"; + } +} + +sub do_ctrl { "^$_[0]" } + +sub do_email { + local($addr, $text) = split(/,\s*/, $_[0]); + + $text = $addr unless $text; + &t2h_anchor('', "mailto:$addr", $text); +} + +sub do_sc +{ + # l2h does this much better + return &l2h_ToLatex("{\\sc ".&unprotect_html($_[0])."}") if ($T2H_L2H); + return "\U$_[0]\E"; +} + +sub do_math +{ + return &l2h_ToLatex("\$".&unprotect_html($_[0])."\$") if ($T2H_L2H); + return "".$text.""; +} + +sub do_uref { + local($url, $text, $only_text) = split(/,\s*/, $_[0]); + + $text = $only_text if $only_text; + $text = $url unless $text; + &t2h_anchor('', $url, $text); +} + +sub do_url { &t2h_anchor('', $_[0], $_[0]) } + +sub do_acronym +{ + return '' . $_[0] . ''; +} + +sub do_accent +{ + return "&$_[0]acute;" if $_[1] eq 'H'; + return "$_[0]." if $_[1] eq 'dotaccent'; + return "$_[0]*" if $_[1] eq 'ringaccent'; + return "$_[0]".'[' if $_[1] eq 'tieaccent'; + return "$_[0]".'(' if $_[1] eq 'u'; + return "$_[0]_" if $_[1] eq 'ubaraccent'; + return ".$_[0]" if $_[1] eq 'udotaccent'; + return "$_[0]<" if $_[1] eq 'v'; + return "&$_[0]cedil;" if $_[1] eq ','; + return "$_[0]" if $_[1] eq 'dotless'; + return undef; +} + +sub apply_style { + local($texi_style, $text) = @_; + local($style); + + $style = $style_map{$texi_style}; + if (defined($style)) { # known style + if ($style =~ /^\"/) { # add quotes + $style = $'; + $text = "\`$text\'"; + } + if ($style =~ /^\&/) { # custom + $style = $'; + $text = &$style($text, $texi_style); + } elsif ($style) { # good style + $text = "<$style>$text"; + } else { # no style + } + } else { # unknown style + $text = undef; + } + return($text); +} + +# remove Texinfo styles +sub remove_style { + local($_) = @_; + 1 while(s/\@\w+{([^\{\}]+)}/$1/g); + return($_); +} + +sub remove_things +{ + local ($_) = @_; + s|\@(\w+)\{\}|$1|g; + return $_; +} + +sub substitute_style { + local($_) = @_; + local($changed, $done, $style, $text); + + &simple_substitutions; + $changed = 1; + while ($changed) { + $changed = 0; + $done = ''; + while (/\@(\w+){([^\{\}]+)}/ || /\@(,){([^\{\}]+)}/) { + $text = &apply_style($1, $2); + if ($text) { + $_ = "$`$text$'"; + $changed = 1; + } else { + $done .= "$`\@$1"; + $_ = "{$2}$'"; + } + } + $_ = $done . $_; + } + return($_); +} + +sub t2h_anchor { + local($name, $href, $text, $newline, $extra_attribs) = @_; + local($result); + + $result = " + $what =~ s/\&/\&\#38;/g; + $what =~ s/\/\&\#62;/g; + # restore anything in quotes + # this fixes my problem where I had: + # < IMG SRC="leftarrow.gif" ALT="<--" > but what if I wanted < in my ALT text ?? + # maybe byte stuffing or some other technique should be used. + $what =~ s/\"([^\&]+)\&\#60;(.*)\"/"$1<$2"/g; + $what =~ s/\"([^\&]+)\&\#62;(.*)\"/"$1>$2"/g; + $what =~ s/\"([^\&]+)\&\#38;(.*)\"/"$1&$2"/g; + # but recognize some HTML things + $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g; # + $what =~ s/\&\#60;A ([^\&]+)\&\#62;//g; # + $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;//g; # + return($what); +} + +sub unprotect_texi { + s/$;0/\@/go; + s/$;1/\{/go; + s/$;2/\}/go; + s/$;3/\`/go; + s/$;4/\'/go; +} + +sub Unprotect_texi +{ + local $_ = shift; + &unprotect_texi; + return($_); +} + +sub unprotect_html { + local($what) = @_; + $what =~ s/\&\#38;/\&/g; + $what =~ s/\&\#60;/\/g; + return($what); +} + +sub t2h_print_label +{ + my $fh = shift; + my $href = shift || $T2H_HREF{This}; + $href =~ s/.*#(.*)$/$1/; + print $fh qq{\n}; +} + +############################################################################## + + # These next few lines are legal in both Perl and nroff. + +.00 ; # finish .ig + +'di \" finish diversion--previous line must be blank +.nr nl 0-1 \" fake up transition to first page again +.nr % 0 \" start at page 1 +'; __END__ ############# From here on it's a standard manual page ############ +.so /usr/local/man/man1/texi2html.1 diff --git a/readline/readline-4.3/doc/texinfo.tex b/readline/readline-4.3/doc/texinfo.tex new file mode 100644 index 00000000..c49af9f4 --- /dev/null +++ b/readline/readline-4.3/doc/texinfo.tex @@ -0,0 +1,5992 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% +% Load plain if necessary, i.e., if running under initex. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi +% +\def\texinfoversion{1999-09-25.10} +% +% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 +% Free Software Foundation, Inc. +% +% This texinfo.tex file is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License as +% published by the Free Software Foundation; either version 2, or (at +% your option) any later version. +% +% This texinfo.tex file is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the implied warranty +% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +% General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this texinfo.tex file; see the file COPYING. If not, write +% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% +% In other words, you are welcome to use, share and improve this program. +% You are forbidden to forbid anyone else to use, share and improve +% what you give them. Help stamp out software-hoarding! +% +% Please try the latest version of texinfo.tex before submitting bug +% reports; you can get the latest version from: +% ftp://ftp.gnu.org/gnu/texinfo.tex +% (and all GNU mirrors, see http://www.gnu.org/order/ftp.html) +% ftp://texinfo.org/tex/texinfo.tex +% ftp://us.ctan.org/macros/texinfo/texinfo.tex +% (and all CTAN mirrors, finger ctan@us.ctan.org for a list). +% /home/gd/gnu/doc/texinfo.tex on the GNU machines. +% The texinfo.tex in any given Texinfo distribution could well be out +% of date, so if that's what you're using, please check. +% Texinfo has a small home page at http://texinfo.org/. +% +% Send bug reports to bug-texinfo@gnu.org. Please include including a +% complete document in each bug report with which we can reproduce the +% problem. Patches are, of course, greatly appreciated. +% +% To process a Texinfo manual with TeX, it's most reliable to use the +% texi2dvi shell script that comes with the distribution. For a simple +% manual foo.texi, however, you can get away with this: +% tex foo.texi +% texindex foo.?? +% tex foo.texi +% tex foo.texi +% dvips foo.dvi -o # or whatever, to process the dvi file; this makes foo.ps. +% The extra runs of TeX get the cross-reference information correct. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. +% +% It is possible to adapt texinfo.tex for other languages. You can get +% the existing language-specific files from ftp://ftp.gnu.org/gnu/texinfo/. + +\message{Loading texinfo [version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}% + \catcode`+=\active \catcode`\_=\active} + +% Save some parts of plain tex whose names we will redefine. +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexi=\i +\let\ptexlbrace=\{ +\let\ptexrbrace=\} +\let\ptexstar=\* +\let\ptext=\t + +% We never want plain's outer \+ definition in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + +\message{Basics,} +\chardef\other=12 + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Set up fixed words for English if not already set. +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordin\undefined \gdef\putwordin{in}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi +\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi +\ifx\putwordof\undefined \gdef\putwordof{of}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi +\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi +% +\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi +\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi +\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi +\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi +\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi +\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi +\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi +\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi +\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi +\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi +\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi +\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi +% +\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi +\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi +\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi +\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi +\ifx\putwordDeftypevar\undefined\gdef\putwordDeftypevar{Variable}\fi +\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi +\ifx\putwordDeftypefun\undefined\gdef\putwordDeftypefun{Function}\fi + +% Ignore a token. +% +\def\gobble#1{} + +\hyphenation{ap-pen-dix} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{eshell} +\hyphenation{white-space} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen \bindingoffset +\newdimen \normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\ifx\eTeXversion\undefined +\def\loggingall{\tracingcommands2 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% +\else +\def\loggingall{\tracingcommands3 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \tracingscantokens1 \tracingassigns1 \tracingifs1 + \tracinggroups1 \tracingnesting2 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% +\fi + +% For @cropmarks command. +% Do @cropmarks to get crop marks. +% +\newif\ifcropmarks +\let\cropmarks = \cropmarkstrue +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines +\newdimen\cornerlong \cornerlong=1pc +\newdimen\cornerthick \cornerthick=.3pt +\newdimen\topandbottommargin \topandbottommargin=.75in + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). + \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to + % take effect in \write's, yet the group defined by the \vbox ends + % before the \shipout runs. + % + \escapechar = `\\ % use backslash in output files. + \indexdummies % don't expand commands in the output. + \normalturnoffactive % \ in index entries must not stay \, e.g., if + % the page break happens to be in the middle of an example. + \shipout\vbox{% + \ifcropmarks \vbox to \outervsize\bgroup + \hsize = \outerhsize + \vskip-\topandbottommargin + \vtop to0pt{% + \line{\ewtop\hfil\ewtop}% + \nointerlineskip + \line{% + \vbox{\moveleft\cornerthick\nstop}% + \hfill + \vbox{\moveright\cornerthick\nstop}% + }% + \vss}% + \vskip\topandbottommargin + \line\bgroup + \hfil % center the page within the outer (page) hsize. + \ifodd\pageno\hskip\bindingoffset\fi + \vbox\bgroup + \fi + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingxxx.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 2\baselineskip + \unvbox\footlinebox + \fi + % + \ifpdfmakepagedest \pdfmkdest{\the\pageno} \fi + % + \ifcropmarks + \egroup % end of \vbox\bgroup + \hfil\egroup % end of (centering) \line\bgroup + \vskip\topandbottommargin plus1fill minus1fill + \boxmaxdepth = \cornerthick + \vbox to0pt{\vss + \line{% + \vbox{\moveleft\cornerthick\nsbot}% + \hfill + \vbox{\moveright\cornerthick\nsbot}% + }% + \nointerlineskip + \line{\ewbot\hfil\ewbot}% + }% + \egroup % \vbox from first cropmarks clause + \fi + }% end of \shipout\vbox + }% end of group with \turnoffactive + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment; press RETURN to continue} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Press RETURN to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +% Single-spacing is done by various environments (specifically, in +% \nonfillstart and \quotations). +\newskip\singlespaceskip \singlespaceskip = 12.5pt +\def\singlespace{% + % Why was this kern here? It messes up equalizing space above and below + % environments. --karl, 6may93 + %{\advance \baselineskip by -\singlespaceskip + %\kern \baselineskip}% + \setleading \singlespaceskip +} + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt\char64}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. +\def\mylbrace {{\tt\char123}} +\def\myrbrace {{\tt\char125}} +\let\{=\mylbrace +\let\}=\myrbrace +\begingroup + % Definitions to produce actual \{ & \} command in an index. + \catcode`\{ = 12 \catcode`\} = 12 + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\@ = 0 \catcode`\\ = 12 + @gdef@lbracecmd[\{]% + @gdef@rbracecmd[\}]% +@endgroup + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H. +\let\, = \c +\let\dotaccent = \. +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \t +\let\ubaraccent = \b +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown +% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ptexi + \else\ifx\temp\jmacro \j + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=3000 } + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below produces a box with normal height and large + % depth; thus, TeX puts \baselineskip glue before it, and (when the + % next line of text is done) \lineskip glue after it. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + \endgroup % End the \group. + }% + % + \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Ensure vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % If the @need value is less than one line space, it's useless. + \dimen0 = #1\mil + \dimen2 = \ht\strutbox + \advance\dimen2 by \dp\strutbox + \ifdim\dimen0 > \dimen2 + % + % Do a \strut just to make the height of this box be normal, so the + % normal leading is inserted relative to the preceding line. + % And a page break here is fine. + \vtop to #1\mil{\strut\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak + \fi +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in a typewriter +% font as three actual period characters. +% +\def\dots{% + \leavevmode + \hbox to 1.5em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \leavevmode + \hbox to 2em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% + \spacefactor=3000 +} + + +% @page forces the start of a new page +% +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph. + +\def\inmargin#1{% +\strut\vadjust{\nobreak\kern-\strutdepth + \vtop to \strutdepth{\baselineskip\strutdepth\vss + \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}} +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} + +%\hbox{{\rm#1}}\hfil\break}} + +% @include file insert text of that file as input. +% Allow normal characters that we make active in the argument (a file name). +\def\include{\begingroup + \catcode`\\=12 + \catcode`~=12 + \catcode`^=12 + \catcode`_=12 + \catcode`|=12 + \catcode`<=12 + \catcode`>=12 + \catcode`+=12 + \parsearg\includezzz} +% Restore active chars for included file. +\def\includezzz#1{\endgroup\begingroup + % Read the included file in a group so nested @include's work. + \def\thisfile{#1}% + \input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line outputs that line, centered + +\def\center{\parsearg\centerzzz} +\def\centerzzz #1{{\advance\hsize by -\leftskip +\advance\hsize by -\rightskip +\centerline{#1}}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\begingroup \catcode`\^^M=\other% +\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% +\commentxxx} +{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} + +\let\c=\comment + +% @paragraphindent NCHARS +% We'll use ems for NCHARS, close enough. +% We cannot implement @paragraphindent asis, though. +% +\def\asisword{asis} % no translation, these are keywords +\def\noneword{none} +% +\def\paragraphindent{\parsearg\doparagraphindent} +\def\doparagraphindent#1{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \defaultparindent = 0pt + \else + \defaultparindent = #1em + \fi + \fi + \parindent = \defaultparindent +} + +% @exampleindent NCHARS +% We'll use ems for NCHARS like @paragraphindent. +% It seems @exampleindent asis isn't necessary, but +% I preserve it to make it similar to @paragraphindent. +\def\exampleindent{\parsearg\doexampleindent} +\def\doexampleindent#1{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \lispnarrowing = 0pt + \else + \lispnarrowing = #1em + \fi + \fi +} + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math means output in math mode. +% We don't use $'s directly in the definition of \math because control +% sequences like \math are expanded when the toc file is written. Then, +% we read the toc file back, the $'s will be normal characters (as they +% should be, according to the definition of Texinfo). So we must use a +% control sequence to switch into and out of math mode. +% +% This isn't quite enough for @math to work properly in indices, but it +% seems unlikely it will ever be needed there. +% +\let\implicitmath = $ +\def\math#1{\implicitmath #1\implicitmath} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +% @refill is a no-op. +\let\refill=\relax + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate (before @setfilename). +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \iflinks + \readauxfile + \fi % \openindices needs to do some work in any case. + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. + % Just to be on the safe side, close the input stream before the \input. + \openin 1 texinfo.cnf + \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi + \closein1 + \temp + % + \comment % Ignore the actual filename. +} + +% Called from \setfilename. +% +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + + +\message{pdf,} +% adobe `portable' document format +\newcount\tempnum +\newcount\lnkcount +\newtoks\filename +\newcount\filenamelength +\newcount\pgn +\newtoks\toksA +\newtoks\toksB +\newtoks\toksC +\newtoks\toksD +\newbox\boxA +\newcount\countA +\newif\ifpdf +\newif\ifpdfmakepagedest + +\ifx\pdfoutput\undefined + \pdffalse + \let\pdfmkdest = \gobble + \let\pdfurl = \gobble + \let\endlink = \relax + \let\linkcolor = \relax + \let\pdfmakeoutlines = \relax +\else + \pdftrue + \pdfoutput = 1 + \input pdfcolor + \def\dopdfimage#1#2#3{% + \def\imagewidth{#2}% + \def\imageheight{#3}% + \ifnum\pdftexversion < 14 + \pdfimage + \else + \pdfximage + \fi + \ifx\empty\imagewidth\else width \imagewidth \fi + \ifx\empty\imageheight\else height \imageheight \fi + {#1.pdf}% + \ifnum\pdftexversion < 14 \else + \pdfrefximage \pdflastximage + \fi} + \def\pdfmkdest#1{\pdfdest name{#1@} xyz} + \def\pdfmkpgn#1{#1@} + \let\linkcolor = \Cyan + \def\endlink{\Black\pdfendlink} + % Adding outlines to PDF; macros for calculating structure of outlines + % come from Petr Olsak + \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% + \else \csname#1\endcsname \fi} + \def\advancenumber#1{\tempnum=\expnumber{#1}\relax + \advance\tempnum by1 + \expandafter\xdef\csname#1\endcsname{\the\tempnum}} + \def\pdfmakeoutlines{{% + \openin 1 \jobname.toc + \ifeof 1\else\bgroup + \closein 1 + \indexnofonts + \def\tt{} + % thanh's hack / proper braces in bookmarks + \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace + \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace + % + \def\chapentry ##1##2##3{} + \def\unnumbchapentry ##1##2{} + \def\secentry ##1##2##3##4{\advancenumber{chap##2}} + \def\unnumbsecentry ##1##2{} + \def\subsecentry ##1##2##3##4##5{\advancenumber{sec##2.##3}} + \def\unnumbsubsecentry ##1##2{} + \def\subsubsecentry ##1##2##3##4##5##6{\advancenumber{subsec##2.##3.##4}} + \def\unnumbsubsubsecentry ##1##2{} + \input \jobname.toc + \def\chapentry ##1##2##3{% + \pdfoutline goto name{\pdfmkpgn{##3}}count-\expnumber{chap##2}{##1}} + \def\unnumbchapentry ##1##2{% + \pdfoutline goto name{\pdfmkpgn{##2}}{##1}} + \def\secentry ##1##2##3##4{% + \pdfoutline goto name{\pdfmkpgn{##4}}count-\expnumber{sec##2.##3}{##1}} + \def\unnumbsecentry ##1##2{% + \pdfoutline goto name{\pdfmkpgn{##2}}{##1}} + \def\subsecentry ##1##2##3##4##5{% + \pdfoutline goto name{\pdfmkpgn{##5}}count-\expnumber{subsec##2.##3.##4}{##1}} + \def\unnumbsubsecentry ##1##2{% + \pdfoutline goto name{\pdfmkpgn{##2}}{##1}} + \def\subsubsecentry ##1##2##3##4##5##6{% + \pdfoutline goto name{\pdfmkpgn{##6}}{##1}} + \def\unnumbsubsubsecentry ##1##2{% + \pdfoutline goto name{\pdfmkpgn{##2}}{##1}} + \input \jobname.toc + \egroup\fi + }} + \def\makelinks #1,{% + \def\params{#1}\def\E{END}% + \ifx\params\E + \let\nextmakelinks=\relax + \else + \let\nextmakelinks=\makelinks + \ifnum\lnkcount>0,\fi + \picknum{#1}% + \startlink attr{/Border [0 0 0]} + goto name{\pdfmkpgn{\the\pgn}}% + \linkcolor #1% + \advance\lnkcount by 1% + \endlink + \fi + \nextmakelinks + } + \def\picknum#1{\expandafter\pn#1} + \def\pn#1{% + \def\p{#1}% + \ifx\p\lbrace + \let\nextpn=\ppn + \else + \let\nextpn=\ppnn + \def\first{#1} + \fi + \nextpn + } + \def\ppn#1{\pgn=#1\gobble} + \def\ppnn{\pgn=\first} + \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \ifx\p\space\else\addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \fi + \nextsp} + \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} + \ifnum\pdftexversion < 14 + \let \startlink \pdfannotlink + \else + \let \startlink \pdfstartlink + \fi + \def\pdfurl#1{% + \begingroup + \normalturnoffactive\def\@{@}% + \leavevmode\Red + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + % #1 + \endgroup} + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS| + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \startlink attr{/Border [0 0 0]} goto name{\mkpgn{#1}} + \linkcolor #1\endlink} + \def\mkpgn#1{#1@} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\fi % \ifx\pdfoutput + + +\message{fonts,} +% Font-change commands. + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this one. +\def\ttsl{\tenttsl} + +% Use Computer Modern fonts at \magstephalf (11pt). +\newcount\mainmagstep +\mainmagstep=\magstephalf + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor +\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +\ifx\bigger\relax +\let\mainmagstep=\magstep1 +\setfont\textrm\rmshape{12}{1000} +\setfont\texttt\ttshape{12}{1000} +\else +\setfont\textrm\rmshape{10}{\mainmagstep} +\setfont\texttt\ttshape{10}{\mainmagstep} +\fi +% Instead of cmb10, you many want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10. +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\setfont\defbf\bxshape{10}{\magstep1} %was 1314 +\setfont\deftt\ttshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\setfont\smallrm\rmshape{9}{1000} +\setfont\smalltt\ttshape{9}{1000} +\setfont\smallbf\bfshape{10}{900} +\setfont\smallit\itshape{9}{1000} +\setfont\smallsl\slshape{9}{1000} +\setfont\smallsf\sfshape{9}{1000} +\setfont\smallsc\scshape{10}{900} +\setfont\smallttsl\ttslshape{10}{900} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 + +% Fonts for title page: +\setfont\titlerm\rmbshape{12}{\magstep3} +\setfont\titleit\itbshape{10}{\magstep4} +\setfont\titlesl\slbshape{10}{\magstep4} +\setfont\titlett\ttbshape{12}{\magstep3} +\setfont\titlettsl\ttslshape{10}{\magstep4} +\setfont\titlesf\sfbshape{17}{\magstep1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} + +% Chapter (and unnumbered) fonts (17.28pt). +\setfont\chaprm\rmbshape{12}{\magstep2} +\setfont\chapit\itbshape{10}{\magstep3} +\setfont\chapsl\slbshape{10}{\magstep3} +\setfont\chaptt\ttbshape{12}{\magstep2} +\setfont\chapttsl\ttslshape{10}{\magstep3} +\setfont\chapsf\sfbshape{17}{1000} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +% Section fonts (14.4pt). +\setfont\secrm\rmbshape{12}{\magstep1} +\setfont\secit\itbshape{10}{\magstep2} +\setfont\secsl\slbshape{10}{\magstep2} +\setfont\sectt\ttbshape{12}{\magstep1} +\setfont\secttsl\ttslshape{10}{\magstep2} +\setfont\secsf\sfbshape{12}{\magstep1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad. +% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded. +% \setfont\ssecsl\slshape{10}{\magstep1} +% \setfont\ssectt\ttshape{10}{\magstep1} +% \setfont\ssecsf\sfshape{10}{\magstep1} + +%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx. +%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than +%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1. +%\setfont\ssectt\ttshape{10}{1315} +%\setfont\ssecsf\sfshape{10}{1315} + +%\let\ssecbf=\ssecrm + +% Subsection fonts (13.15pt). +\setfont\ssecrm\rmbshape{12}{\magstephalf} +\setfont\ssecit\itbshape{10}{1315} +\setfont\ssecsl\slbshape{10}{1315} +\setfont\ssectt\ttbshape{12}{\magstephalf} +\setfont\ssecttsl\ttslshape{10}{1315} +\setfont\ssecsf\sfbshape{12}{\magstephalf} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{\magstep1} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled 1315 +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts, we +% don't bother to reset \scriptfont and \scriptscriptfont (which would +% also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy + \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf + \textfont\ttfam = \tentt \textfont\sffam = \tensf +} + + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam +% \tenbf}, for example. By redefining \tenbf, we obviate the need to +% redefine \bf itself. +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl + \resetmathfonts} +\def\titlefonts{% + \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl + \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc + \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy + \let\tenttsl=\titlettsl + \resetmathfonts \setleading{25pt}} +\def\titlefont#1{{\titlefonts\rm #1}} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl + \resetmathfonts \setleading{19pt}} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl + \resetmathfonts \setleading{16pt}} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl + \resetmathfonts \setleading{15pt}} +\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf? +\def\smallfonts{% + \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl + \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc + \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy + \let\tenttsl=\smallttsl + \resetmathfonts \setleading{11pt}} + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Define these so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000} +\setfont\shortcontbf\bxshape{12}{1000} +\setfont\shortcontsl\slshape{12}{1000} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi} +\def\smartslanted#1{{\sl #1}\futurelet\next\smartitalicx} +\def\smartitalic#1{{\it #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartslanted +\let\dfn=\smartslanted +\let\emph=\smartitalic +\let\cite=\smartslanted + +\def\b#1{{\bf #1}} +\let\strong=\b + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +\def\t#1{% + {\tt \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont=\t +\def\samp#1{`\tclose{#1}'\null} +\setfont\keyrm\rmshape{8}{1000} +\font\keysy=cmsy9 +\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% + \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% + \vbox{\hrule\kern-0.4pt + \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% + \kern-0.4pt\hrule}% + \kern-.06em\raise0.4pt\hbox{\angleright}}}} +% The old definition, with no lozenge: +%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +% @file, @option are the same as @samp. +\let\file=\samp +\let\option=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate at a dash. +% -- rms. +{ + \catcode`\-=\active + \catcode`\_=\active + % + \global\def\code{\begingroup + \catcode`\-=\active \let-\codedash + \catcode`\_=\active \let_\codeunder + \codex + } + % + % If we end up with any active - characters when handling the index, + % just treat them as a normal -. + \global\def\indexbreaks{\catcode`\-=\active \let-\realdash} +} + +\def\realdash{-} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}} +\def\codex #1{\tclose{#1}\endgroup} + +%\let\exp=\tclose %Was temporary + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\def\kbdinputstyle{\parsearg\kbdinputstylexxx} +\def\kbdinputstylexxx#1{% + \def\arg{#1}% + \ifx\arg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\arg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\arg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is kbdinputdistinct. (Too much of a hassle to call the macro, +% the catcodes are wrong for parsearg to work.) +\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl} + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\kbdfont\look}}\fi +\else{\tclose{\kbdfont\look}}\fi} + +% For @url, @env, @command quotes seem unnecessary, so use \code. +\let\url=\code +\let\env=\code +\let\command=\code + +% @uref (abbreviation for `urlref') takes an optional (comma-separated) +% second argument specifying the text to display and an optional third +% arg as text to display instead of (rather than in addition to) the url +% itself. First (mandatory) arg is the url. Perhaps eventually put in +% a hypertex \special here. +% +\def\uref#1{\douref #1,,,\finish} +\def\douref#1,#2,#3,#4\finish{\begingroup + \unsepspaces + \pdfurl{#1}% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \ifpdf + \unhbox0 % PDF: 2nd arg given, show only it + \else + \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url + \fi + \else + \code{#1}% only url given, so show it + \fi + \fi + \endlink +\endgroup} + +% rms does not like angle brackets --karl, 17may97. +% So now @email is just like @uref, unless we are pdf. +% +%\def\email#1{\angleleft{\tt #1}\angleright} +\ifpdf + \def\email#1{\doemail#1,,\finish} + \def\doemail#1,#2,#3\finish{\begingroup + \unsepspaces + \pdfurl{mailto:#1}% + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi + \endlink + \endgroup} +\else + \let\email=\uref +\fi + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +% @l was never documented to mean ``switch to the Lisp font'', +% and it is not used as such in any manual I can find. We need it for +% Polish suppressed-l. --karl, 22sep96. +%\def\l#1{{\li #1}\null} + +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @acronym downcases the argument and prints in smallcaps. +\def\acronym#1{{\smallcaps \lowercase{#1}}} + +% @pounds{} is a sterling sign. +\def\pounds{{\it\$}} + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\newif\ifseenauthor +\newif\iffinishedtitlepage + +% Do an implicit @contents or @shortcontents after @end titlepage if the +% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. +% +\newif\ifsetcontentsaftertitlepage + \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue +\newif\ifsetshortcontentsaftertitlepage + \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefonts\rm ##1} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + % + % If they want short, they certainly want long too. + \ifsetshortcontentsaftertitlepage + \shortcontents + \contents + \global\let\shortcontents = \relax + \global\let\contents = \relax + \fi + % + \ifsetcontentsaftertitlepage + \contents + \global\let\contents = \relax + \global\let\shortcontents = \relax + \fi + % + \ifpdf \pdfmakepagedesttrue \fi + % + \HEADINGSon +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks\evenheadline % headline on even pages +\newtoks\oddheadline % headline on odd pages +\newtoks\evenfootline % footline on even pages +\newtoks\oddfootline % footline on odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + +\def\evenheading{\parsearg\evenheadingxxx} +\def\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% + \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% + % + % Leave some space for the footline. Hopefully ok to assume + % @evenfooting will not be used by itself. + \global\advance\pageheight by -\baselineskip + \global\advance\vsize by -\baselineskip +} + +\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{ +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} +\let\contentsalignmacro = \chappager + +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} + +% Subroutines used in generating headings +% Produces Day Month Year style of output. +\def\today{% + \number\day\space + \ifcase\month + \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr + \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug + \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec + \fi + \space\number\year} + +% @settitle line... specifies the title of the document, for headings. +% It generates no output of its own. +\def\thistitle{\putwordNoTitle} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue. + \nobreak + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. + \noindent + % Do this with kerns and \unhbox so that if there is a footnote in + % the item text, it can migrate to the main vertical list and + % eventually be printed. + \nobreak\kern-\tableindent + \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 + \unhbox0 + \nobreak\kern\dimen0 + \endgroup + \itemxneedsnegativevskiptrue + \fi +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +% Contains a kludge to get @end[description] to work. +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +% @table, @ftable, @vtable. +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Necessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey #1#2{% +\aboveenvbreak % +\itemmax=\itemindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \itemindent % +\exdentamount=\itemindent +\parindent = 0pt % +\parskip = \smallskipamount % +\ifdim \parskip=0pt \parskip=2pt \fi% +\def#2{\endgraf\afterenvbreak\endgroup}% +\def\itemcontents{#1}% +\let\item=\itemizeitem} + +% Set sfcode to normal for the chars that usually have another value. +% These are `.?!:;,' +\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000 + \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 } + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a . + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \itemizey{#1.}\Eenumerate\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{In hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. +% +% For those who want to use more than one line's worth of words in +% the preamble, break the line within one argument and it +% will parse correctly, i.e., +% +% @multitable {Column 1 template} {Column 2 template} {Column 3 +% template} +% Not: +% @multitable {Column 1 template} {Column 2 template} +% {Column 3 template} + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab, @multitable or @end multitable do not need to be on their +% own lines, but it will not hurt if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +% Macros used to set up halign preamble: +% +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +% #1 is the part of the @columnfraction before the decimal point, which +% is presumably either 0 or the empty string (but we don't check, we +% just throw it away). #2 is the decimal part, which we use as the +% percent of \hsize for this column. +\def\pickupwholefraction#1.#2 {% + \global\advance\colcount by 1 + \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}% + \setuptable +} + +\newcount\colcount +\def\setuptable#1{% + \def\firstarg{#1}% + \ifx\firstarg\xendsetuptable + \let\go = \relax + \else + \ifx\firstarg\xcolumnfractions + \global\setpercenttrue + \else + \ifsetpercent + \let\go\pickupwholefraction + \else + \global\advance\colcount by 1 + \setbox0=\hbox{#1\unskip }% Add a normal word space as a separator; + % typically that is always in the input, anyway. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi + \fi + \ifx\go\pickupwholefraction + % Put the argument back for the \pickupwholefraction call, so + % we'll always have a period there to be parsed. + \def\go{\pickupwholefraction#1}% + \else + \let\go = \setuptable + \fi% + \fi + \go +} + +% This used to have \hskip1sp. But then the space in a template line is +% not enough. That is bad. So let's go back to just & until we +% encounter the problem it was intended to solve again. +% --karl, nathan@acm.org, 20apr99. +\def\tab{&} + +% @multitable ... @end multitable definitions: +% +\def\multitable{\parsearg\dotable} +\def\dotable#1{\bgroup + \vskip\parskip + \let\item\crcr + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + \def\Emultitable{\global\setpercentfalse\cr\egroup\egroup}% + % + % To parse everything between @multitable and @item: + \setuptable#1 \endsetuptable + % + % \everycr will reset column counter, \colcount, at the end of + % each line. Every column entry will cause \colcount to advance by one. + % The table preamble + % looks at the current \colcount to find the correct column width. + \everycr{\noalign{% + % + % \filbreak%% keeps underfull box messages off when table breaks over pages. + % Maybe so, but it also creates really weird page breaks when the table + % breaks over pages. Wouldn't \vfil be better? Wait until the problem + % manifests itself, so it can be fixed for real --karl. + \global\colcount=0\relax}}% + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. + \halign\bgroup&\global\advance\colcount by 1\relax + \multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively marking + % characters. + \noindent\ignorespaces##\unskip\multistrut}\cr +} + +\def\setmultitablespacing{% test to see if user has set \multitablelinespace. +% If so, do nothing. If not, give it an appropriate dimension based on +% current baselineskip. +\ifdim\multitablelinespace=0pt +\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip +\global\advance\multitablelinespace by-\ht0 +%% strut to put in table in case some entry doesn't have descenders, +%% to keep lines equally spaced +\let\multistrut = \strut +\else +%% FIXME: what is \box0 supposed to be? +\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 +width0pt\relax} \fi +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} + + +\message{conditionals,} +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% + \let\chapter=\relax + \let\unnumbered=\relax + \let\top=\relax + \let\unnumberedsec=\relax + \let\unnumberedsection=\relax + \let\unnumberedsubsec=\relax + \let\unnumberedsubsection=\relax + \let\unnumberedsubsubsec=\relax + \let\unnumberedsubsubsection=\relax + \let\section=\relax + \let\subsec=\relax + \let\subsubsec=\relax + \let\subsection=\relax + \let\subsubsection=\relax + \let\appendix=\relax + \let\appendixsec=\relax + \let\appendixsection=\relax + \let\appendixsubsec=\relax + \let\appendixsubsection=\relax + \let\appendixsubsubsec=\relax + \let\appendixsubsubsection=\relax + \let\contents=\relax + \let\smallbook=\relax + \let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +\def\ignoremorecommands{% + \let\defcodeindex = \relax + \let\defcv = \relax + \let\deffn = \relax + \let\deffnx = \relax + \let\defindex = \relax + \let\defivar = \relax + \let\defmac = \relax + \let\defmethod = \relax + \let\defop = \relax + \let\defopt = \relax + \let\defspec = \relax + \let\deftp = \relax + \let\deftypefn = \relax + \let\deftypefun = \relax + \let\deftypeivar = \relax + \let\deftypeop = \relax + \let\deftypevar = \relax + \let\deftypevr = \relax + \let\defun = \relax + \let\defvar = \relax + \let\defvr = \relax + \let\ref = \relax + \let\xref = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\settitle = \relax + \let\setchapternewpage = \relax + \let\setchapterstyle = \relax + \let\everyheading = \relax + \let\evenheading = \relax + \let\oddheading = \relax + \let\everyfooting = \relax + \let\evenfooting = \relax + \let\oddfooting = \relax + \let\headings = \relax + \let\include = \relax + \let\lowersections = \relax + \let\down = \relax + \let\raisesections = \relax + \let\up = \relax + \let\set = \relax + \let\clear = \relax + \let\item = \relax +} + +% Ignore @ignore ... @end ignore. +% +\def\ignore{\doignore{ignore}} + +% Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text. +% +\def\ifinfo{\doignore{ifinfo}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifnottex{\doignore{ifnottex}} +\def\html{\doignore{html}} +\def\menu{\doignore{menu}} +\def\direntry{\doignore{direntry}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory = \comment + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + % This @ is a catcode 12 token (that is the normal catcode of @ in + % this texinfo.tex file). We change the catcode of @ below to match. + \long\def\doignoretext##1@end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode32 = 10 + % + % Ignore braces, too, so mismatched braces don't cause trouble. + \catcode`\{ = 9 + \catcode`\} = 9 + % + % We must not have @c interpreted as a control sequence. + \catcode`\@ = 12 + % + % Make the letter c a comment character so that the rest of the line + % will be ignored. This way, the document can have (for example) + % @c @end ifinfo + % and the @end ifinfo will be properly ignored. + % (We've just changed @ to catcode 12.) + \catcode`\c = 14 + % + % And now expand that command. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{WARNING: for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{ (See ftp://ftp.gnu.org/pub/gnu/TeX.README.)} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \global\warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the change of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook: make the current font be a dummy font. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because not all sites + % might have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm=\nullfont \let\tenit=\nullfont \let\tensl=\nullfont + \let\tenbf=\nullfont \let\tentt=\nullfont \let\smallcaps=\nullfont + \let\tensf=\nullfont + % Similarly for index fonts (mostly for their use in smallexample). + \let\smallrm=\nullfont \let\smallit=\nullfont \let\smallsl=\nullfont + \let\smallbf=\nullfont \let\smalltt=\nullfont \let\smallsc=\nullfont + \let\smallsf=\nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex + \def\tex{\doignore{tex}}% + % Do not execute macro definitions. + % `c' is a comment character, so the word `macro' will get cut off. + \def\macro{\doignore{ma}}% +} + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. Make sure the catcode of space is correct to avoid +% losing inside @example, for instance. +% +\def\set{\begingroup\catcode` =10 + \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR. + \parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi + \endgroup +} +% Can't use \xdef to pre-expand #2 and save some time, since \temp or +% \next or other control sequences that we've defined might get us into +% an infinite loop. Consider `@set foo @cite{bar}'. +\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +{ + \catcode`\_ = \active + % + % We might end up with active _ or - characters in the argument if + % we're called from @code, as @code{@value{foo-bar_}}. So \let any + % such active characters to their normal equivalents. + \gdef\value{\begingroup + \catcode`\-=12 \catcode`\_=12 + \indexbreaks \let_\normalunderscore + \valuexxx} +} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} + +% We have this subroutine so that we can handle at least some @value's +% properly in indexes (we \let\value to this in \indexdummies). Ones +% whose names contain - or _ still won't work, but we can't do anything +% about that. The command has to be fully expandable, since the result +% winds up in the index file. This means that if the variable's value +% contains other Texinfo commands, it's almost certain it will fail +% (although perhaps we could fix that with sufficient work to do a +% one-level expansion on the result, instead of complete). +% +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\ifsetxxx} +\def\ifsetxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifsetfail + \else + \expandafter\ifsetsucceed + \fi +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\ifclearxxx} +\def\ifclearxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifclearsucceed + \else + \expandafter\ifclearfail + \fi +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex, @ifnothtml, @ifnotinfo always succeed; we read the text +% following, through the first @end iftex (etc.). Make `@end iftex' +% (etc.) valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\def\ifnothtml{\conditionalsucceed{ifnothtml}} +\def\ifnotinfo{\conditionalsucceed{ifnotinfo}} +\defineunmatchedend{iftex} +\defineunmatchedend{ifnothtml} +\defineunmatchedend{ifnotinfo} + +% We can't just want to start a group at @iftex (for example) and end it +% at @end iftex, since then @set commands inside the conditional have no +% effect (they'd get reverted at the end of the group). So we must +% define \Eiftex to redefine itself to be its previous value. (We can't +% just define it to fail again with an ``unmatched end'' error, since +% the @ifset might be nested.) +% +\def\conditionalsucceed#1{% + \edef\temp{% + % Remember the current value of \E#1. + \let\nece{prevE#1} = \nece{E#1}% + % + % At the `@end #1', redefine \E#1 to be its previous value. + \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}% + }% + \temp +} + +% We need to expand lots of \csname's, but we don't want to expand the +% control sequences after we've constructed them. +% +\def\nece#1{\expandafter\noexpand\csname#1\endcsname} + +% @defininfoenclose. +\let\definfoenclose=\comment + + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. +% +\def\newindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 % Open the file + \fi + \expandafter\xdef\csname#1index\endcsname{% % Define @#1index + \noexpand\doindex{#1}} +} + +% @defindex foo == \newindex{foo} + +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. + +\def\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}} +} + +\def\defcodeindex{\parsearg\newcodeindex} + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +% The \closeout helps reduce unnecessary open files; the limit on the +% Acorn RISC OS is a mere 16 files. +\def\synindex#1 #2 {% + \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname + \expandafter\closeout\csname#1indfile\endcsname + \expandafter\let\csname#1indfile\endcsname=\synindexfoo + \expandafter\xdef\csname#1index\endcsname{% define \xxxindex + \noexpand\doindex{#2}}% +} + +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +\def\syncodeindex#1 #2 {% + \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname + \expandafter\closeout\csname#1indfile\endcsname + \expandafter\let\csname#1indfile\endcsname=\synindexfoo + \expandafter\xdef\csname#1index\endcsname{% define \xxxindex + \noexpand\docodeindex{#2}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +\def\indexdummies{% +\def\ { }% +% Take care of the plain tex accent commands. +\def\"{\realbackslash "}% +\def\`{\realbackslash `}% +\def\'{\realbackslash '}% +\def\^{\realbackslash ^}% +\def\~{\realbackslash ~}% +\def\={\realbackslash =}% +\def\b{\realbackslash b}% +\def\c{\realbackslash c}% +\def\d{\realbackslash d}% +\def\u{\realbackslash u}% +\def\v{\realbackslash v}% +\def\H{\realbackslash H}% +% Take care of the plain tex special European modified letters. +\def\oe{\realbackslash oe}% +\def\ae{\realbackslash ae}% +\def\aa{\realbackslash aa}% +\def\OE{\realbackslash OE}% +\def\AE{\realbackslash AE}% +\def\AA{\realbackslash AA}% +\def\o{\realbackslash o}% +\def\O{\realbackslash O}% +\def\l{\realbackslash l}% +\def\L{\realbackslash L}% +\def\ss{\realbackslash ss}% +% Take care of texinfo commands likely to appear in an index entry. +% (Must be a way to avoid doing expansion at all, and thus not have to +% laboriously list every single command here.) +\def\@{@}% will be @@ when we switch to @ as escape char. +% Need these in case \tex is in effect and \{ is a \delimiter again. +% But can't use \lbracecmd and \rbracecmd because texindex assumes +% braces and backslashes are used only as delimiters. +\let\{ = \mylbrace +\let\} = \myrbrace +\def\_{{\realbackslash _}}% +\def\w{\realbackslash w }% +\def\bf{\realbackslash bf }% +%\def\rm{\realbackslash rm }% +\def\sl{\realbackslash sl }% +\def\sf{\realbackslash sf}% +\def\tt{\realbackslash tt}% +\def\gtr{\realbackslash gtr}% +\def\less{\realbackslash less}% +\def\hat{\realbackslash hat}% +\def\TeX{\realbackslash TeX}% +\def\dots{\realbackslash dots }% +\def\result{\realbackslash result}% +\def\equiv{\realbackslash equiv}% +\def\expansion{\realbackslash expansion}% +\def\print{\realbackslash print}% +\def\error{\realbackslash error}% +\def\point{\realbackslash point}% +\def\copyright{\realbackslash copyright}% +\def\tclose##1{\realbackslash tclose {##1}}% +\def\code##1{\realbackslash code {##1}}% +\def\uref##1{\realbackslash uref {##1}}% +\def\url##1{\realbackslash url {##1}}% +\def\env##1{\realbackslash env {##1}}% +\def\command##1{\realbackslash command {##1}}% +\def\option##1{\realbackslash option {##1}}% +\def\dotless##1{\realbackslash dotless {##1}}% +\def\samp##1{\realbackslash samp {##1}}% +\def\,##1{\realbackslash ,{##1}}% +\def\t##1{\realbackslash t {##1}}% +\def\r##1{\realbackslash r {##1}}% +\def\i##1{\realbackslash i {##1}}% +\def\b##1{\realbackslash b {##1}}% +\def\sc##1{\realbackslash sc {##1}}% +\def\cite##1{\realbackslash cite {##1}}% +\def\key##1{\realbackslash key {##1}}% +\def\file##1{\realbackslash file {##1}}% +\def\var##1{\realbackslash var {##1}}% +\def\kbd##1{\realbackslash kbd {##1}}% +\def\dfn##1{\realbackslash dfn {##1}}% +\def\emph##1{\realbackslash emph {##1}}% +\def\acronym##1{\realbackslash acronym {##1}}% +% +% Handle some cases of @value -- where the variable name does not +% contain - or _, and the value does not contain any +% (non-fully-expandable) commands. +\let\value = \expandablevalue +% +\unsepspaces +% Turn off macro expansion +\turnoffmacros +} + +% If an index command is used in an @example environment, any spaces +% therein should become regular spaces in the raw index file, not the +% expansion of \tie (\\leavevmode \penalty \@M \ ). +{\obeyspaces + \gdef\unsepspaces{\obeyspaces\let =\space}} + +% \indexnofonts no-ops all font-change commands. +% This is used when outputting the strings to sort the index by. +\def\indexdummyfont#1{#1} +\def\indexdummytex{TeX} +\def\indexdummydots{...} + +\def\indexnofonts{% +% Just ignore accents. +\let\,=\indexdummyfont +\let\"=\indexdummyfont +\let\`=\indexdummyfont +\let\'=\indexdummyfont +\let\^=\indexdummyfont +\let\~=\indexdummyfont +\let\==\indexdummyfont +\let\b=\indexdummyfont +\let\c=\indexdummyfont +\let\d=\indexdummyfont +\let\u=\indexdummyfont +\let\v=\indexdummyfont +\let\H=\indexdummyfont +\let\dotless=\indexdummyfont +% Take care of the plain tex special European modified letters. +\def\oe{oe}% +\def\ae{ae}% +\def\aa{aa}% +\def\OE{OE}% +\def\AE{AE}% +\def\AA{AA}% +\def\o{o}% +\def\O{O}% +\def\l{l}% +\def\L{L}% +\def\ss{ss}% +\let\w=\indexdummyfont +\let\t=\indexdummyfont +\let\r=\indexdummyfont +\let\i=\indexdummyfont +\let\b=\indexdummyfont +\let\emph=\indexdummyfont +\let\strong=\indexdummyfont +\let\cite=\indexdummyfont +\let\sc=\indexdummyfont +%Don't no-op \tt, since it isn't a user-level command +% and is used in the definitions of the active chars like <, >, |... +%\let\tt=\indexdummyfont +\let\tclose=\indexdummyfont +\let\code=\indexdummyfont +\let\url=\indexdummyfont +\let\uref=\indexdummyfont +\let\env=\indexdummyfont +\let\acronym=\indexdummyfont +\let\command=\indexdummyfont +\let\option=\indexdummyfont +\let\file=\indexdummyfont +\let\samp=\indexdummyfont +\let\kbd=\indexdummyfont +\let\key=\indexdummyfont +\let\var=\indexdummyfont +\let\TeX=\indexdummytex +\let\dots=\indexdummydots +\def\@{@}% +} + +% To define \realbackslash, we must make \ not be an escape. +% We must first make another character (@) an escape +% so we do not become unable to do a definition. + +{\catcode`\@=0 \catcode`\\=\other + @gdef@realbackslash{\}} + +\let\indexbackslash=0 %overridden during \printindex. +\let\SETmarginindex=\relax % put index entries in margin (undocumented)? + +% For \ifx comparisons. +\def\emptymacro{\empty} + +% Most index entries go through here, but \dosubind is the general case. +% +\def\doind#1#2{\dosubind{#1}{#2}\empty} + +% Workhorse for all \fooindexes. +% #1 is name of index, #2 is stuff to put there, #3 is subentry -- +% \empty if called from \doind, as we usually are. The main exception +% is with defuns, which call us directly. +% +\def\dosubind#1#2#3{% + % Put the index entry in the margin if desired. + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% + \fi + {% + \count255=\lastpenalty + {% + \indexdummies % Must do this here, since \bf, etc expand at this stage + \escapechar=`\\ + {% + \let\folio = 0% We will expand all macros now EXCEPT \folio. + \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + \def\thirdarg{#3}% + % + % If third arg is present, precede it with space in sort key. + \ifx\thirdarg\emptymacro + \let\subentry = \empty + \else + \def\subentry{ #3}% + \fi + % + % First process the index entry with all font commands turned + % off to get the string to sort by. + {\indexnofonts \xdef\indexsorttmp{#2\subentry}}% + % + % Now the real index entry with the fonts. + \toks0 = {#2}% + % + % If third (subentry) arg is present, add it to the index + % string. And include a space. + \ifx\thirdarg\emptymacro \else + \toks0 = \expandafter{\the\toks0 \space #3}% + \fi + % + % Set up the complete index entry, with both the sort key + % and the original text, including any font commands. We write + % three arguments to \entry to the .?? file, texindex reduces to + % two when writing the .??s sorted result. + \edef\temp{% + \write\csname#1indfile\endcsname{% + \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}% + }% + % + % If a skip is the last thing on the list now, preserve it + % by backing up by \lastskip, doing the \write, then inserting + % the skip again. Otherwise, the whatsit generated by the + % \write will make \lastskip zero. The result is that sequences + % like this: + % @end defun + % @tindex whatever + % @defun ... + % will have extra space inserted, because the \medbreak in the + % start of the @defun won't see the skip inserted by the @end of + % the previous defun. + % + % But don't do any of this if we're not in vertical mode. We + % don't want to do a \vskip and prematurely end a paragraph. + % + % Avoid page breaks due to these extra skips, too. + % + \iflinks + \ifvmode + \skip0 = \lastskip + \ifdim\lastskip = 0pt \else \nobreak\vskip-\lastskip \fi + \fi + % + \temp % do the write + % + % + \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi + \fi + }% + }% + \penalty\count255 + }% +} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% @printindex causes a particular index (the ??s file) to get printed. +% It does not print any chapter heading (usually an @unnumbered). +% +\def\printindex{\parsearg\doprintindex} +\def\doprintindex#1{\begingroup + \dobreak \chapheadingskip{10000}% + % + \smallfonts \rm + \tolerance = 9500 + \indexbreaks + % + % See if the index file exists and is nonempty. + % Change catcode of @ here so that if the index file contains + % \initial {@} + % as its first line, TeX doesn't complain about mismatched braces + % (because it thinks @} is a control sequence). + \catcode`\@ = 11 + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + \putwordIndexNonexistent + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + \putwordIndexIsEmpty + \else + % Index files are almost Texinfo source, but we use \ as the escape + % character. It would be better to use @, but that's too big a change + % to make right now. + \def\indexbackslash{\rawbackslashxx}% + \catcode`\\ = 0 + \escapechar = `\\ + \begindoublecolumns + \input \jobname.#1s + \enddoublecolumns + \fi + \fi + \closein 1 +\endgroup} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +\def\initial#1{{% + % Some minor font changes for the special characters. + \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt + % + % Remove any glue we may have, we'll be inserting our own. + \removelastskip + % + % We like breaks before the index initials, so insert a bonus. + \penalty -300 + % + % Typeset the initial. Making this add up to a whole number of + % baselineskips increases the chance of the dots lining up from column + % to column. It still won't often be perfect, because of the stretch + % we need before each entry, but it's better. + % + % No shrink because it confuses \balancecolumns. + \vskip 1.67\baselineskip plus .5\baselineskip + \leftline{\secbf #1}% + \vskip .33\baselineskip plus .1\baselineskip + % + % Do our best not to break after the initial. + \nobreak +}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry#1#2{\begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent = 2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % A bit of stretch before each entry for the benefit of balancing columns. + \vskip 0pt plus1pt + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#2}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd\ \else% + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + \ #2% The page number ends the paragraph. + \fi + \fi% + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm + +\def\secondary #1#2{ +{\parfillskip=0in \parskip=0in +\hangindent =1in \hangafter=1 +\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par +}} + +% Define two-column mode, which we use to typeset indexes. +% Adapted from the TeXbook, page 416, which is to say, +% the manmac.tex format used to print the TeXbook itself. +\catcode`\@=11 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % Grab any single-column material above us. + \output = {% + % + % Here is a possibility not foreseen in manmac: if we accumulate a + % whole lot of material, we might end up calling this \output + % routine twice in a row (see the doublecol-lose test, which is + % essentially a couple of indexes with @setchapternewpage off). In + % that case we just ship out what is in \partialpage with the normal + % output routine. Generally, \partialpage will be empty when this + % runs and this will be a no-op. See the indexspread.tex test case. + \ifvoid\partialpage \else + \onepageout{\pagecontents\partialpage}% + \fi + % + \global\setbox\partialpage = \vbox{% + % Unvbox the main output page. + \unvbox\PAGE + \kern-\topskip \kern\baselineskip + }% + }% + \eject % run that output routine to set \partialpage + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \advance\vsize by -\ht\partialpage + \vsize = 2\vsize +} + +% The double-column output routine for all double-column pages except +% the last. +% +\def\doublecolumnout{% + \splittopskip=\topskip \splitmaxdepth=\maxdepth + % Get the available space for the double columns -- the normal + % (undoubled) page height minus any material left over from the + % previous page. + \dimen@ = \vsize + \divide\dimen@ by 2 + % + % box0 will be the left-hand column, box2 the right. + \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \onepageout\pagesofar + \unvbox255 + \penalty\outputpenalty +} +\def\pagesofar{% + % Re-output the contents of the output page -- any previous material, + % followed by the two boxes we just split, in box0 and box2. + \unvbox\partialpage + % + \hsize = \doublecolumnhsize + \wd0=\hsize \wd2=\hsize + \hbox to\pagewidth{\box0\hfil\box2}% +} +\def\enddoublecolumns{% + \output = {% + % Split the last of the double-column material. Leave it on the + % current page, no automatic page break. + \balancecolumns + % + % If we end up splitting too much material for the current page, + % though, there will be another page break right after this \output + % invocation ends. Having called \balancecolumns once, we do not + % want to call it again. Therefore, reset \output to its normal + % definition right away. (We hope \balancecolumns will never be + % called on to balance too much material, but if it is, this makes + % the output somewhat more palatable.) + \global\output = {\onepageout{\pagecontents\PAGE}}% + }% + \eject + \endgroup % started in \begindoublecolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize (after the + % \endgroup where \vsize got restored). + \pagegoal = \vsize +} +\def\balancecolumns{% + % Called at the end of the double column material. + \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \dimen@ = \ht0 + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% + \splittopskip = \topskip + % Loop until we get a decent breakpoint. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht3>\dimen@ + \global\advance\dimen@ by 1pt + \repeat + }% + %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% + \setbox0=\vbox to\dimen@{\unvbox1}% + \setbox2=\vbox to\dimen@{\unvbox3}% + % + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Chapters, sections, etc. + +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +% \def\appendixletter{\char\the\appendixno} +% We do the following for the sake of pdftex, which needs the actual +% letter in the expansion, not just typeset. +\def\appendixletter{% + \ifnum\appendixno=`A A% + \else\ifnum\appendixno=`B B% + \else\ifnum\appendixno=`C C% + \else\ifnum\appendixno=`D D% + \else\ifnum\appendixno=`E E% + \else\ifnum\appendixno=`F F% + \else\ifnum\appendixno=`G G% + \else\ifnum\appendixno=`H H% + \else\ifnum\appendixno=`I I% + \else\ifnum\appendixno=`J J% + \else\ifnum\appendixno=`K K% + \else\ifnum\appendixno=`L L% + \else\ifnum\appendixno=`M M% + \else\ifnum\appendixno=`N N% + \else\ifnum\appendixno=`O O% + \else\ifnum\appendixno=`P P% + \else\ifnum\appendixno=`Q Q% + \else\ifnum\appendixno=`R R% + \else\ifnum\appendixno=`S S% + \else\ifnum\appendixno=`T T% + \else\ifnum\appendixno=`U U% + \else\ifnum\appendixno=`V V% + \else\ifnum\appendixno=`W W% + \else\ifnum\appendixno=`X X% + \else\ifnum\appendixno=`Y Y% + \else\ifnum\appendixno=`Z Z% + % The \the is necessary, despite appearances, because \appendixletter is + % expanded while writing the .toc file. \char\appendixno is not + % expandable, thus it is written literally, thus all appendixes come out + % with the same letter (or @) in the toc without it. + \else\char\the\appendixno + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise. +\def\thischapter{} +\def\thissection{} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +} + +% @chapter, @appendix, @unnumbered. +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}% +\chapmacro {#1}{\the\chapno}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +% We don't substitute the actual chapter name into \thischapter +% because we don't want its macros evaluated now. +\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}% + {\the\chapno}}}% +\temp +\donoderef +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec +} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \appendixno by 1 +\message{\putwordAppendix\space \appendixletter}% +\chapmacro {#1}{\putwordAppendix{} \appendixletter}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}% + {\putwordAppendix{} \appendixletter}}}% +\temp +\appendixnoderef +\global\let\section = \appendixsec +\global\let\subsection = \appendixsubsec +\global\let\subsubsection = \appendixsubsubsec +} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\def\centerchap{\parsearg\centerchapyyy} +\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} + +% @top is like @unnumbered. +\outer\def\top{\parsearg\unnumberedyyy} + +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{% +\secno=0 \subsecno=0 \subsubsecno=0 +% +% This used to be simply \message{#1}, but TeX fully expands the +% argument to \message. Therefore, if #1 contained @-commands, TeX +% expanded them. For example, in `@unnumbered The @cite{Book}', TeX +% expanded @cite (which turns out to cause errors because \cite is meant +% to be executed, not expanded). +% +% Anyway, we don't want the fully-expanded definition of @cite to appear +% as a result of the \message, we just want `@cite' itself. We use +% \the to achieve this: TeX expands \the only once, +% simply yielding the contents of . (We also do this for +% the toc entries.) +\toks0 = {#1}\message{(\the\toks0)}% +% +\unnumbchapmacro {#1}% +\gdef\thischapter{#1}\gdef\thissection{#1}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash unnumbchapentry{\the\toks0}}}% +\temp +\unnumbnoderef +\global\let\section = \unnumberedsec +\global\let\subsection = \unnumberedsubsec +\global\let\subsubsection = \unnumberedsubsubsec +} + +% Sections. +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}% + {\the\chapno}{\the\secno}}}% +\temp +\donoderef +\nobreak +} + +\outer\def\appendixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}% + {\appendixletter}{\the\secno}}}% +\temp +\appendixnoderef +\nobreak +} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{% +\plainsecheading {#1}\gdef\thissection{#1}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsecentry{\the\toks0}}}% +\temp +\unnumbnoderef +\nobreak +} + +% Subsections. +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}% + {\the\chapno}{\the\secno}{\the\subsecno}}}% +\temp +\donoderef +\nobreak +} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}% + {\appendixletter}{\the\secno}{\the\subsecno}}}% +\temp +\appendixnoderef +\nobreak +} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{% +\plainsubsecheading {#1}\gdef\thissection{#1}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsecentry% + {\the\toks0}}}% +\temp +\unnumbnoderef +\nobreak +} + +% Subsubsections. +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}% + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}% +\temp +\donoderef +\nobreak +} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}% + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}% +\temp +\appendixnoderef +\nobreak +} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{% +\plainsubsubsecheading {#1}\gdef\thissection{#1}% +\toks0 = {#1}% +\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsubsecentry% + {\the\toks0}}}% +\temp +\unnumbnoderef +\nobreak +} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% +{\advance\chapheadingskip by 10pt \chapbreak }% +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +% @heading, @subheading, @subsubheading. +\def\heading{\parsearg\plainsecheading} +\def\subheading{\parsearg\plainsubsecheading} +\def\subsubheading{\parsearg\plainsubsubsecheading} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip\chapheadingskip + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain +\global\let\centerchapmacro=\centerchfplain} + +% Plain chapter opening. +% #1 is the text, #2 the chapter number or empty if unnumbered. +\def\chfplain#1#2{% + \pchapsepmacro + {% + \chapfonts \rm + \def\chapnum{#2}% + \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}% + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title + \nobreak +} + +% Plain opening for unnumbered. +\def\unnchfplain#1{\chfplain{#1}{}} + +% @centerchap -- centered and unnumbered. +\let\centerparametersmaybe = \relax +\def\centerchfplain#1{{% + \def\centerparametersmaybe{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt + }% + \chfplain{#1}{}% +}} + +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\nobreak +} + +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} + +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\nobreak +} + +\def\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen +\global\let\centerchapmacro=\centerchfopen} + + +% Section titles. +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} +\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}} +\def\plainsecheading#1{\sectionheading{sec}{}{#1}} + +% Subsection titles. +\newskip \subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} +\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}} +\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}} + +% Subsubsection titles. +\let\subsubsecheadingskip = \subsecheadingskip +\let\subsubsecheadingbreak = \subsecheadingbreak +\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}} +\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}} + + +% Print any size section title. +% +% #1 is the section type (sec/subsec/subsubsec), #2 is the section +% number (maybe empty), #3 the text. +\def\sectionheading#1#2#3{% + {% + \expandafter\advance\csname #1headingskip\endcsname by \parskip + \csname #1headingbreak\endcsname + }% + {% + % Switch to the right set of fonts. + \csname #1fonts\endcsname \rm + % + % Only insert the separating space if we have a section number. + \def\secnum{#2}% + \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}% + % + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 % zero if no section number + \unhbox0 #3}% + }% + \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak +} + + +\message{toc,} +% Table of contents. +\newwrite\tocfile + +% Write an entry to the toc file, opening it if necessary. +% Called from @chapter, etc. We supply {\folio} at the end of the +% argument, which will end up as the last argument to the \...entry macro. +% +% We open the .toc file here instead of at @setfilename or any other +% given time so that @contents can be put in the document anywhere. +% +\newif\iftocfileopened +\def\writetocentry#1{% + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + \iflinks \write\tocfile{#1{\folio}}\fi +} + +\newskip\contentsrightmargin \contentsrightmargin=1in +\newcount\savepageno +\newcount\lastnegativepageno \lastnegativepageno = -1 + +% Finish up the main text and prepare to read what we've written +% to \tocfile. +% +\def\startcontents#1{% + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund + \contentsalignmacro + \immediate\closeout\tocfile + % + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \savepageno = \pageno + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + % We can't do this, because then an actual ^ in a section + % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97. + %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. + % + % Roman numerals for page numbers. + \ifnum \pageno>0 \pageno = \lastnegativepageno \fi +} + + +% Normal (long) toc. +\def\contents{% + \startcontents{\putwordTOC}% + \openin 1 \jobname.toc + \ifeof 1 \else + \closein 1 + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \pdfmakeoutlines + \endgroup + \lastnegativepageno = \pageno + \pageno = \savepageno +} + +% And just the chapters. +\def\summarycontents{% + \startcontents{\putwordShortTOC}% + % + \let\chapentry = \shortchapentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\unnumbsecentry ##1##2{} + \def\subsecentry ##1##2##3##4##5{} + \def\unnumbsubsecentry ##1##2{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \def\unnumbsubsubsecentry ##1##2{} + \openin 1 \jobname.toc + \ifeof 1 \else + \closein 1 + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \pageno = \savepageno +} +\let\shortcontents = \summarycontents + +\ifpdf + \pdfcatalog{/PageMode /UseOutlines}% +\fi + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapter-level things, for both the long and short contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} + +% See comments in \dochapentry re vbox and related settings +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#3\egroup}% +} + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +% +\newdimen\shortappendixwidth +% +\def\shortchaplabel#1{% + % Compute width of word "Appendix", may change with language. + \setbox0 = \hbox{\shortcontrm \putwordAppendix}% + \shortappendixwidth = \wd0 + % + % We typeset #1 in a box of constant width, regardless of the text of + % #1, so the chapter titles will come out aligned. + \setbox0 = \hbox{#1}% + \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi + % + % This space should be plenty, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + \advance\dimen0 by 1.1em + \hbox to \dimen0{#1\hfil}% +} + +\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} +\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno\bgroup#2\egroup}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}} + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno\bgroup#2\egroup}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +\def\tocentry#1#2{\begingroup + \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks + % Do not use \turnoffactive in these arguments. Since the toc is + % typeset in cmr, so characters such as _ would come out wrong; we + % have to do the usual translation tricks. + \entry{#1}{#2}% +\endgroup} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} +% @foo ... @end foo. + +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% Furthermore, these definitions must come after we define our fonts. +\newbox\dblarrowbox \newbox\longdblarrowbox +\newbox\pushcharbox \newbox\bullbox +\newbox\equivbox \newbox\errorbox + +%{\tentt +%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil} +%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil} +%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil} +%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil} +% Adapted from the manmac format (p.420 of TeXbook) +%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex +% depth .1ex\hfil} +%} + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +\def\point{$\star$} +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% Adapted from the TeXbook's \boxit. +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} + +\global\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{ + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} + +% The @error{} command. +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie + \catcode `\%=14 + \catcode 43=12 % plus + \catcode`\"=12 + \catcode`\==12 + \catcode`\|=12 + \catcode`\<=12 + \catcode`\>=12 + \escapechar=`\\ + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\*=\ptexstar + \let\t=\ptext + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +\let\Etex=\endgroup} + +% Define @lisp ... @endlisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @endlisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% Make each space character in the input produce a normal interword +% space in the output. Don't allow a line break at this space, as this +% is used only in environments like @example, where each line of input +% should produce a line of output anyway. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces% +\global\let\obeyedspace= } + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip +% +\def\aboveenvbreak{{\advance\envskipamount by \parskip +\endgraf \ifdim\lastskip<\envskipamount +\removelastskip \penalty-50 \vskip\envskipamount \fi}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +% @cartouche ... @end cartouche: draw rectangle w/rounded corners around +% environment contents. +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\long\def\cartouche{% +\begingroup + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt %we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \singlespace + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% Define the \E... control sequence only if we are inside the particular +% environment, so the error checking in \end will work. +% +% To end an @example-like environment, we first end the paragraph (via +% \afterenvbreak's vertical glue), and then the group. That way we keep +% the zero \parskip that the environments set -- \parskip glue will be +% inserted at the beginning of the next paragraph in the document, after +% the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup} + +% @lisp: indented, narrowed, typewriter font. +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return +} + +% @example: Same as @lisp. +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} + +% @small... is usually equivalent to the non-small (@smallbook +% redefines). We must call \example (or whatever) last in the +% definition, since it reads the return following the @example (or +% whatever) command. +% +% This actually allows (for example) @end display inside an +% @smalldisplay. Too bad, but makeinfo will catch the error anyway. +% +\def\smalldisplay{\begingroup\def\Esmalldisplay{\nonfillfinish\endgroup}\display} +\def\smallexample{\begingroup\def\Esmallexample{\nonfillfinish\endgroup}\lisp} +\def\smallformat{\begingroup\def\Esmallformat{\nonfillfinish\endgroup}\format} +\def\smalllisp{\begingroup\def\Esmalllisp{\nonfillfinish\endgroup}\lisp} + +% Real @smallexample and @smalllisp (when @smallbook): use smaller fonts. +% Originally contributed by Pavel@xerox. +\def\smalllispx{\begingroup + \def\Esmalllisp{\nonfillfinish\endgroup}% + \def\Esmallexample{\nonfillfinish\endgroup}% + \smallfonts + \lisp +} + +% @display: same as @lisp except keep current font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} + +% @smalldisplay (when @smallbook): @display plus smaller fonts. +% +\def\smalldisplayx{\begingroup + \def\Esmalldisplay{\nonfillfinish\endgroup}% + \smallfonts \rm + \display +} + +% @format: same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} + +% @smallformat (when @smallbook): @format plus smaller fonts. +% +\def\smallformatx{\begingroup + \def\Esmallformat{\nonfillfinish\endgroup}% + \smallfonts \rm + \format +} + +% @flushleft (same as @format). +% +\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format} + +% @flushright. +% +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble +} + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. +% +\def\quotation{% + \begingroup\inENV %This group ends at the end of the @quotation body + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \singlespace + \parindent=0pt + % We have retained a nonzero parskip for the environment, since we're + % doing normal filling. So to avoid extra space below the environment... + \def\Equotation{\parskip = 0pt \nonfillfinish}% + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \let\nonarrowing = \relax + \fi +} + + +\message{defuns,} +% @defun etc. + +% Allow user to change definition object font (\df) internally +\def\setdeffont #1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deftypemargin \deftypemargin=12pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount +% define \functionparens, which makes ( and ) and & do special things. +% \functionparens affects the group it is contained in. +\def\activeparens{% +\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active +\catcode`\[=\active \catcode`\]=\active} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} +% This is used to turn on special parens +% but make & act ordinary (given that it's active). +\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested + \global\advance\parencount by 1 +} +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. + % also in that case restore the outer-level definition of (. + \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi + \global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 } +\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 } +\let\ampnr = \& +\def\lbrb{{\bf\char`\[}} +\def\rbrb{{\bf\char`\]}} + +% Active &'s sneak into the index arguments, so make sure it's defined. +{ + \catcode`& = 13 + \global\let& = \ampnr +} + +% First, defname, which formats the header line itself. +% #1 should be the function name. +% #2 should be the type of definition, such as "Function". + +\def\defname #1#2{% +% Get the values of \leftskip and \rightskip as they were +% outside the @def... +\dimen2=\leftskip +\advance\dimen2 by -\defbodyindent +\noindent +\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}% +\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line +\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations +\parshape 2 0in \dimen0 \defargsindent \dimen1 +% Now output arg 2 ("Function" or some such) +% ending at \deftypemargin from the right margin, +% but stuck inside a box of width 0 so it does not interfere with linebreaking +{% Adjust \hsize to exclude the ambient margins, +% so that \rightline will obey them. +\advance \hsize by -\dimen2 +\rlap{\rightline{{\rm #2}\hskip -1.25pc }}}% +% Make all lines underfull and no complaints: +\tolerance=10000 \hbadness=10000 +\advance\leftskip by -\defbodyindent +\exdentamount=\defbodyindent +{\df #1}\enskip % Generate function name +} + +% Actually process the body of a definition +% #1 should be the terminating control sequence, such as \Edefun. +% #2 should be the "another name" control sequence, such as \defunx. +% #3 should be the control sequence that actually processes the header, +% such as \defunheader. + +\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\activeparens\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % 61 is `=' +\obeylines\activeparens\spacesplit#3} + +% #1 is the \E... control sequence to end the definition (which we define). +% #2 is the \...x control sequence for consecutive fns (which we define). +% #3 is the control sequence to call to resume processing. +% #4, delimited by the space, is the class name. +% +\def\defmethparsebody#1#2#3#4 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#4}}} + +% Used for @deftypemethod and @deftypeivar. +% #1 is the \E... control sequence to end the definition (which we define). +% #2 is the \...x control sequence for consecutive fns (which we define). +% #3 is the control sequence to call to resume processing. +% #4, delimited by a space, is the class name. +% #5 is the method's return type. +% +\def\deftypemethparsebody#1#2#3#4 #5 {\begingroup\inENV + \medbreak + \def#1{\endgraf\endgroup\medbreak}% + \def#2##1 ##2 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}{##2}}}% + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent + \begingroup\obeylines\activeparens\spacesplit{#3{#4}{#5}}} + +% Used for @deftypeop. The change from \deftypemethparsebody is an +% extra argument at the beginning which is the `category', instead of it +% being the hardwired string `Method' or `Instance Variable'. We have +% to account for this both in the \...x definition and in parsing the +% input at hand. Thus also need a control sequence (passed as #5) for +% the \E... definition to assign the category name to. +% +\def\deftypeopparsebody#1#2#3#4#5 #6 {\begingroup\inENV + \medbreak + \def#1{\endgraf\endgroup\medbreak}% + \def#2##1 ##2 ##3 {% + \def#4{##1}% + \begingroup\obeylines\activeparens\spacesplit{#3{##2}{##3}}}% + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent + \begingroup\obeylines\activeparens\spacesplit{#3{#5}{#6}}} + +\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#5}}} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. + +\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % +\obeylines\spacesplit#3} + +% This is used for \def{tp,vr}parsebody. It could probably be used for +% some of the others, too, with some judicious conditionals. +% +\def\parsebodycommon#1#2#3{% + \begingroup\inENV % + \medbreak % + % Define the end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent + \begingroup\obeylines +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{#3{#4}}% +} + +% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the +% type is just `struct', because we lose the braces in `{struct +% termios}' when \spacesplit reads its undelimited argument. Sigh. +% \let\deftpparsebody=\defvrparsebody +% +% So, to get around this, we put \empty in with the type name. That +% way, TeX won't find exactly `{...}' as an undelimited argument, and +% won't strip off the braces. +% +\def\deftpparsebody #1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{\parsetpheaderline{#3{#4}}}\empty +} + +% Fine, but then we have to eventually remove the \empty *and* the +% braces (if any). That's what this does. +% +\def\removeemptybraces\empty#1\relax{#1} + +% After \spacesplit has done its work, this is called -- #1 is the final +% thing to call, #2 the type name (which starts with \empty), and #3 +% (which might be empty) the arguments. +% +\def\parsetpheaderline#1#2#3{% + #1{\removeemptybraces#2\relax}{#3}% +}% + +\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\spacesplit{#3{#5}}} + +% Split up #2 at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. + +{\obeylines +\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}% +\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{% +\ifx\relax #3% +#1{#2}{}\else #1{#2}{#3#4}\fi}} + +% So much for the things common to all kinds of definitions. + +% Define @defun. + +% First, define the processing that is wanted for arguments of \defun +% Use this to expand the args and terminate the paragraph they make up + +\def\defunargs#1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Set the font temporarily and use \font in case \setfont made \tensl a macro. +{\tensl\hyphenchar\font=0}% +#1% +{\tensl\hyphenchar\font=45}% +\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi% +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\nobreak\vskip -\parskip\nobreak +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Use \boldbraxnoamp, not \functionparens, so that & is not special. +\boldbraxnoamp +\tclose{#1}% avoid \code because of side effects on active chars +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\nobreak\vskip -\parskip\nobreak +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDeffunc}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\doind {fn}{\code{#2}}% Make entry in function index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{\putwordDeftypefun}% +\deftypefunargs {#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% \defheaderxcond#1\relax$$$ +% puts #1 in @code, followed by a space, but does nothing if #1 is null. +\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\doind {fn}{\code{#3}}% Make entry in function index +\begingroup +\normalparens % notably, turn off `&' magic, which prevents +% at least some C++ text from working +\defname {\defheaderxcond#2\relax$$$#3}{#1}% +\deftypefunargs {#4}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDefmac}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDefspec}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defop CATEGORY CLASS OPERATION ARG... +% +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} +% +\def\defopheader#1#2#3{% +\dosubind {fn}{\code{#2}}{\putwordon\ #1}% Make entry in function index +\begingroup\defname {#2}{\defoptype\ \putwordon\ #1}% +\defunargs {#3}\endgroup % +} + +% @deftypeop CATEGORY CLASS TYPE OPERATION ARG... +% +\def\deftypeop #1 {\def\deftypeopcategory{#1}% + \deftypeopparsebody\Edeftypeop\deftypeopx\deftypeopheader + \deftypeopcategory} +% +% #1 is the class name, #2 the data type, #3 the operation name, #4 the args. +\def\deftypeopheader#1#2#3#4{% + \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{\defheaderxcond#2\relax$$$#3} + {\deftypeopcategory\ \putwordon\ \code{#1}}% + \deftypefunargs{#4}% + \endgroup +} + +% @deftypemethod CLASS TYPE METHOD ARG... +% +\def\deftypemethod{% + \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader} +% +% #1 is the class name, #2 the data type, #3 the method name, #4 the args. +\def\deftypemethodheader#1#2#3#4{% + \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{\defheaderxcond#2\relax$$$#3}{\putwordMethodon\ \code{#1}}% + \deftypefunargs{#4}% + \endgroup +} + +% @deftypeivar CLASS TYPE VARNAME +% +\def\deftypeivar{% + \deftypemethparsebody\Edeftypeivar\deftypeivarx\deftypeivarheader} +% +% #1 is the class name, #2 the data type, #3 the variable name. +\def\deftypeivarheader#1#2#3{% + \dosubind{vr}{\code{#3}}{\putwordof\ \code{#1}}% entry in variable index + \begingroup + \defname{#3}{\putwordInstanceVariableof\ \code{#1}}% + \defvarargs{#3}% + \endgroup +} + +% @defmethod == @defop Method +% +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} +% +% #1 is the class name, #2 the method name, #3 the args. +\def\defmethodheader#1#2#3{% + \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{#2}{\putwordMethodon\ \code{#1}}% + \defunargs{#3}% + \endgroup +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{\putwordof\ #1}% Make entry in var index +\begingroup\defname {#2}{\defcvtype\ \putwordof\ #1}% +\defvarargs {#3}\endgroup % +} + +% @defivar CLASS VARNAME == @defcv {Instance Variable} CLASS VARNAME +% +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} +% +\def\defivarheader#1#2#3{% + \dosubind {vr}{\code{#2}}{\putwordof\ #1}% entry in var index + \begingroup + \defname{#2}{\putwordInstanceVariableof\ #1}% + \defvarargs{#3}% + \endgroup +} + +% @defvar +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% +\interlinepenalty=10000 +\endgraf\nobreak\vskip -\parskip\nobreak} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{\putwordDefvar}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{\putwordDefopt}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name, perhaps followed by text that +% is actually part of the data type, which should not be put into the index. +\def\deftypevarheader #1#2{% +\dovarind#2 \relax% Make entry in variables index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{\putwordDeftypevar}% +\interlinepenalty=10000 +\endgraf\nobreak\vskip -\parskip\nobreak +\endgroup} +\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\dovarind#3 \relax% +\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1} +\interlinepenalty=10000 +\endgraf\nobreak\vskip -\parskip\nobreak +\endgroup} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% These definitions are used if you use @defunx (etc.) +% anywhere other than immediately after a @defun or @defunx. +% +\def\defcvx#1 {\errmessage{@defcvx in invalid context}} +\def\deffnx#1 {\errmessage{@deffnx in invalid context}} +\def\defivarx#1 {\errmessage{@defivarx in invalid context}} +\def\defmacx#1 {\errmessage{@defmacx in invalid context}} +\def\defmethodx#1 {\errmessage{@defmethodx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\defopx#1 {\errmessage{@defopx in invalid context}} +\def\defspecx#1 {\errmessage{@defspecx in invalid context}} +\def\deftpx#1 {\errmessage{@deftpx in invalid context}} +\def\deftypefnx#1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypefunx#1 {\errmessage{@deftypefunx in invalid context}} +\def\deftypeivarx#1 {\errmessage{@deftypeivarx in invalid context}} +\def\deftypemethodx#1 {\errmessage{@deftypemethodx in invalid context}} +\def\deftypeopx#1 {\errmessage{@deftypeopx in invalid context}} +\def\deftypevarx#1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx#1 {\errmessage{@deftypevrx in invalid context}} +\def\defunx#1 {\errmessage{@defunx in invalid context}} +\def\defvarx#1 {\errmessage{@defvarx in invalid context}} +\def\defvrx#1 {\errmessage{@defvrx in invalid context}} + + +\message{macros,} +% @macro. + +% To do this right we need a feature of e-TeX, \scantokens, +% which we arrange to emulate with a temporary file in ordinary TeX. +\ifx\eTeXversion\undefined + \newwrite\macscribble + \def\scanmacro#1{% + \begingroup \newlinechar`\^^M + % Undo catcode changes of \startcontents and \doprintindex + \catcode`\@=0 \catcode`\\=12 \escapechar=`\@ + % Append \endinput to make sure that TeX does not see the ending newline. + \toks0={#1\endinput}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \let\xeatspaces\eatspaces + \input \jobname.tmp + \endgroup +} +\else +\def\scanmacro#1{% +\begingroup \newlinechar`\^^M +% Undo catcode changes of \startcontents and \doprintindex +\catcode`\@=0 \catcode`\\=12 \escapechar=`\@ +\let\xeatspaces\eatspaces\scantokens{#1\endinput}\endgroup} +\fi + +\newcount\paramno % Count of parameters +\newtoks\macname % Macro name +\newif\ifrecursive % Is it recursive? +\def\macrolist{} % List of all defined macros in the form + % \do\macro1\do\macro2... + +% Utility routines. +% Thisdoes \let #1 = #2, except with \csnames. +\def\cslet#1#2{% +\expandafter\expandafter +\expandafter\let +\expandafter\expandafter +\csname#1\endcsname +\csname#2\endcsname} + +% Trim leading and trailing spaces off a string. +% Concepts from aro-bend problem 15 (see CTAN). +{\catcode`\@=11 +\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} +\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} +\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} +\def\unbrace#1{#1} +\unbrace{\gdef\trim@@@ #1 } #2@{#1} +} + +% Trim a single trailing ^^M off a string. +{\catcode`\^^M=12\catcode`\Q=3% +\gdef\eatcr #1{\eatcra #1Q^^MQ}% +\gdef\eatcra#1^^MQ{\eatcrb#1Q}% +\gdef\eatcrb#1Q#2Q{#1}% +} + +% Macro bodies are absorbed as an argument in a context where +% all characters are catcode 10, 11 or 12, except \ which is active +% (as in normal texinfo). It is necessary to change the definition of \. + +% It's necessary to have hard CRs when the macro is executed. This is +% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% body, and then making it the \newlinechar in \scanmacro. + +\def\macrobodyctxt{% + \catcode`\~=12 + \catcode`\^=12 + \catcode`\_=12 + \catcode`\|=12 + \catcode`\<=12 + \catcode`\>=12 + \catcode`\+=12 + \catcode`\{=12 + \catcode`\}=12 + \catcode`\@=12 + \catcode`\^^M=12 + \usembodybackslash} + +\def\macroargctxt{% + \catcode`\~=12 + \catcode`\^=12 + \catcode`\_=12 + \catcode`\|=12 + \catcode`\<=12 + \catcode`\>=12 + \catcode`\+=12 + \catcode`\@=12 + \catcode`\\=12} + +% \mbodybackslash is the definition of \ in @macro bodies. +% It maps \foo\ => \csname macarg.foo\endcsname => #N +% where N is the macro parameter number. +% We define \csname macarg.\endcsname to be \realbackslash, so +% \\ in macro replacement text gets you a backslash. + +{\catcode`@=0 @catcode`@\=@active + @gdef@usembodybackslash{@let\=@mbodybackslash} + @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} +} +\expandafter\def\csname macarg.\endcsname{\realbackslash} + +\def\macro{\recursivefalse\parsearg\macroxxx} +\def\rmacro{\recursivetrue\parsearg\macroxxx} + +\def\macroxxx#1{% + \getargs{#1}% now \macname is the macname and \argl the arglist + \ifx\argl\empty % no arguments + \paramno=0% + \else + \expandafter\parsemargdef \argl;% + \fi + \if1\csname ismacro.\the\macname\endcsname + \message{Warning: redefining \the\macname}% + \else + \expandafter\ifx\csname \the\macname\endcsname \relax + \else \errmessage{The name \the\macname\space is reserved}\fi + \global\cslet{macsave.\the\macname}{\the\macname}% + \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% + % Add the macroname to \macrolist + \toks0 = \expandafter{\macrolist\do}% + \xdef\macrolist{\the\toks0 + \expandafter\noexpand\csname\the\macname\endcsname}% + \fi + \begingroup \macrobodyctxt + \ifrecursive \expandafter\parsermacbody + \else \expandafter\parsemacbody + \fi} + +\def\unmacro{\parsearg\unmacroxxx} +\def\unmacroxxx#1{% + \if1\csname ismacro.#1\endcsname + \global\cslet{#1}{macsave.#1}% + \global\expandafter\let \csname ismacro.#1\endcsname=0% + % Remove the macro name from \macrolist + \begingroup + \edef\tempa{\expandafter\noexpand\csname#1\endcsname}% + \def\do##1{% + \def\tempb{##1}% + \ifx\tempa\tempb + % remove this + \else + \toks0 = \expandafter{\newmacrolist\do}% + \edef\newmacrolist{\the\toks0\expandafter\noexpand\tempa}% + \fi}% + \def\newmacrolist{}% + % Execute macro list to define \newmacrolist + \macrolist + \global\let\macrolist\newmacrolist + \endgroup + \else + \errmessage{Macro #1 not defined}% + \fi +} + +% This makes use of the obscure feature that if the last token of a +% is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. +\def\getargs#1{\getargsxxx#1{}} +\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} +\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacargs#1{\def\argl{#1}} + +% Parse the optional {params} list. Set up \paramno and \paramlist +% so \defmacro knows what to do. Define \macarg.blah for each blah +% in the params list, to be ##N where N is the position in that list. +% That gets used by \mbodybackslash (above). + +% We need to get `macro parameter char #' into several definitions. +% The technique used is stolen from LaTeX: let \hash be something +% unexpandable, insert that wherever you need a #, and then redefine +% it to # just before using the token list produced. +% +% The same technique is used to protect \eatspaces till just before +% the macro is used. + +\def\parsemargdef#1;{\paramno=0\def\paramlist{}% + \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} +\def\parsemargdefxxx#1,{% + \if#1;\let\next=\relax + \else \let\next=\parsemargdefxxx + \advance\paramno by 1% + \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname + {\xeatspaces{\hash\the\paramno}}% + \edef\paramlist{\paramlist\hash\the\paramno,}% + \fi\next} + +% These two commands read recursive and nonrecursive macro bodies. +% (They're different since rec and nonrec macros end differently.) + +\long\def\parsemacbody#1@end macro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\long\def\parsermacbody#1@end rmacro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% + +% This defines the macro itself. There are six cases: recursive and +% nonrecursive macros of zero, one, and many arguments. +% Much magic with \expandafter here. +% \xdef is used so that macro definitions will survive the file +% they're defined in; @include reads the file inside a group. +\def\defmacro{% + \let\hash=##% convert placeholders to macro parameter chars + \ifrecursive + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\scanmacro{\temp}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup\noexpand\scanmacro{\temp}}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \fi + \else + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \expandafter\noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \fi + \fi} + +\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} + +% \braceorline decides whether the next nonwhitespace character is a +% {. If so it reads up to the closing }, if not, it reads the whole +% line. Whatever was read is then fed to the next control sequence +% as an argument (by \parsebrace or \parsearg) +\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx} +\def\braceorlinexxx{% + \ifx\nchar\bgroup\else + \expandafter\parsearg + \fi \next} + +% We mant to disable all macros during \shipout so that they are not +% expanded by \write. +\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}% + \edef\next{\macrolist}\expandafter\endgroup\next} + + +% @alias. +% We need some trickery to remove the optional spaces around the equal +% sign. Just make them active and then expand them all to nothing. +\def\alias{\begingroup\obeyspaces\parsearg\aliasxxx} +\def\aliasxxx #1{\aliasyyy#1\relax} +\def\aliasyyy #1=#2\relax{\ignoreactivespaces +\edef\next{\global\let\expandafter\noexpand\csname#1\endcsname=% + \expandafter\noexpand\csname#2\endcsname}% +\expandafter\endgroup\next} + + +\message{cross references,} +% @xref etc. + +\newwrite\auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% @inforef is relatively simple. +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +% @node's job is to define \lastnode. +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx [#1,]} +\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +% The sectioning commands (@chapter, etc.) call these. +\def\donoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Ysectionnumberandtype}% + \global\let\lastnode=\relax + \fi +} +\def\unnumbnoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}% + \global\let\lastnode=\relax + \fi +} +\def\appendixnoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Yappendixletterandtype}% + \global\let\lastnode=\relax + \fi +} + + +% @anchor{NAME} -- define xref target at arbitrary point. +% +\newcount\savesfregister +\gdef\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} +\gdef\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} +\gdef\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} + +% \setref{NAME}{SNT} defines a cross-reference point NAME, namely +% NAME-title, NAME-pg, and NAME-SNT. Called from \foonoderef. We have +% to set \indexdummies so commands such as @code in a section title +% aren't expanded. It would be nicer not to expand the titles in the +% first place, but there's so many layers that that is hard to do. +% +\def\setref#1#2{{% + \indexdummies + \pdfmkdest{#1}% + \dosetq{#1-title}{Ytitle}% + \dosetq{#1-pg}{Ypagenumber}% + \dosetq{#1-snt}{#2}% +}} + +% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is +% the node name, #2 the name of the Info cross-reference, #3 the printed +% node name, #4 the name of the Info file, #5 the name of the printed +% manual. All but the node name can be omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \unsepspaces + \def\printedmanual{\ignorespaces #5}% + \def\printednodename{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual}% + \setbox0=\hbox{\printednodename}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printednodename{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1 > 0pt + % It is in another manual, so we don't have it. + \def\printednodename{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printednodename{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printednodename{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifpdf + \leavevmode + \getfilename{#4}% + \ifnum\filenamelength>0 + \startlink attr{/Border [0 0 0]}% + goto file{\the\filename.pdf} name{#1@}% + \else + \startlink attr{/Border [0 0 0]}% + goto name{#1@}% + \fi + \linkcolor + \fi + % + \ifdim \wd1 > 0pt + \putwordsection{} ``\printednodename'' \putwordin{} \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\normalturnoffactive + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + }% + % [mynode], + [\printednodename],\space + % page 3 + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi + \endlink +\endgroup} + +% \dosetq is the interface for calls from other macros + +% Use \normalturnoffactive so that punctuation chars such as underscore +% and backslash work in node names. (\turnoffactive doesn't do \.) +\def\dosetq#1#2{% + {\let\folio=0% + \normalturnoffactive + \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}% + \iflinks + \next + \fi + }% +} + +% \internalsetq {foo}{page} expands into +% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...} +% When the aux file is read, ' is the escape character + +\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq + +\def\Ypagenumber{\folio} + +\def\Ytitle{\thissection} + +\def\Ynothing{} + +\def\Ysectionnumberandtype{% +\ifnum\secno=0 \putwordChapter\xreftie\the\chapno % +\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\def\Yappendixletterandtype{% +\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}% +\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\gdef\xreftie{'tie} + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Non-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. + +\def\refx#1#2{% + \expandafter\ifx\csname X#1\endcsname\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \csname X#1\endcsname + \fi + #2% Output the suffix in any case. +} + +% This is the macro invoked by entries in the aux file. +% +\def\xrdef#1{\begingroup + % Reenable \ as an escape while reading the second argument. + \catcode`\\ = 0 + \afterassignment\endgroup + \expandafter\gdef\csname X#1\endcsname +} + +% Read the last existing aux file, if any. No error if none exists. +\def\readauxfile{\begingroup + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \catcode`\^^]=\other + \catcode`\^^^=\other + \catcode`\^^_=\other + \catcode`\@=\other + \catcode`\^=\other + % It was suggested to define this as 7, which would allow ^^e4 etc. + % in xref tags, i.e., node names. But since ^^e4 notation isn't + % supported in the main text, it doesn't seem desirable. Furthermore, + % that is not enough: for node names that actually contain a ^ + % character, we would end up writing a line like this: 'xrdef {'hat + % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first + % argument, and \hat is not an expandable control sequence. It could + % all be worked out, but why? Either we support ^^ or we don't. + % + % The other change necessary for this was to define \auxhat: + % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter + % and then to call \auxhat in \setq. + % + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\$=\other + \catcode`\#=\other + \catcode`\&=\other + \catcode`+=\other % avoid \+ for paranoia even though we've turned it off + % Make the characters 128-255 be printing characters + {% + \count 1=128 + \def\loop{% + \catcode\count 1=\other + \advance\count 1 by 1 + \ifnum \count 1<256 \loop \fi + }% + }% + % The aux file uses ' as the escape (for now). + % Turn off \ as an escape so we do not lose on + % entries which were dumped with control sequences in their names. + % For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^ + % Reference to such entries still does not work the way one would wish, + % but at least they do not bomb out when the aux file is read in. + \catcode`\{=1 + \catcode`\}=2 + \catcode`\%=\other + \catcode`\'=0 + \catcode`\\=\other + % + \openin 1 \jobname.aux + \ifeof 1 \else + \closein 1 + \input \jobname.aux + \global\havexrefstrue + \global\warnedobstrue + \fi + % Open the new aux file. TeX will close it automatically at exit. + \openout\auxfile=\jobname.aux +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \footnotezzz +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +% Oh yes, they do; otherwise, @ifset and anything else that uses +% \parseargline fail inside footnotes because the tokens are fixed when +% the footnote is read. --karl, 16nov96. +% +\long\gdef\footnotezzz{\insert\footins\bgroup + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + \smallfonts \rm + % + % Hang the footnote text off the number. + \hang + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + \futurelet\next\fo@t +} +\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t + \else\let\next\f@t\fi \next} +\def\f@@t{\bgroup\aftergroup\@foot\let\next} +\def\f@t#1{#1\@foot} +\def\@foot{\strut\par\egroup} + +}%end \catcode `\@=11 + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + +% @image. We use the macros from epsf.tex to support this. +% If epsf.tex is not installed and @image is used, we complain. +% +% Check for and read epsf.tex up front. If we read it only at @image +% time, we might be inside a group, and then its definitions would get +% undone and the next image would fail. +\openin 1 = epsf.tex +\ifeof 1 \else + \closein 1 + % Do not bother showing banner with post-v2.7 epsf.tex (available in + % doc/epsf.tex until it shows up on ctan). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +% +% We will only complain once about lack of epsf.tex. +\newif\ifwarnednoepsf +\newhelp\noepsfhelp{epsf.tex must be installed for images to + work. It is also included in the Texinfo distribution, or you can get + it from ftp://tug.org/tex/epsf.tex.} +% +\def\image#1{% + \ifx\epsfbox\undefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \imagexxx #1,,,\finish + \fi +} +% +% Arguments to @image: +% #1 is (mandatory) image filename; we tack on .eps extension. +% #2 is (optional) width, #3 is (optional) height. +% #4 is just the usual extra ignored arg for parsing this stuff. +\def\imagexxx#1,#2,#3,#4\finish{% + \ifpdf + \centerline{\dopdfimage{#1}{#2}{#3}}% + \else + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + \begingroup + \catcode`\^^M = 5 % in case we're inside an example + % If the image is by itself, center it. + \ifvmode + \nobreak\bigskip + % Usually we'll have text after the image which will insert + % \parskip glue, so insert it here too to equalize the space + % above and below. + \nobreak\vskip\parskip + \nobreak + \centerline{\epsfbox{#1.eps}}% + \bigbreak + \else + % In the middle of a paragraph, no extra space. + \epsfbox{#1.eps}% + \fi + \endgroup + \fi +} + + +\message{localization,} +% and i18n. + +% @documentlanguage is usually given very early, just after +% @setfilename. If done too late, it may not override everything +% properly. Single argument is the language abbreviation. +% It would be nice if we could set up a hyphenation file here. +% +\def\documentlanguage{\parsearg\dodocumentlanguage} +\def\dodocumentlanguage#1{% + \tex % read txi-??.tex file in plain TeX. + % Read the file if it exists. + \openin 1 txi-#1.tex + \ifeof1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \let\temp = \relax + \else + \def\temp{\input txi-#1.tex }% + \fi + \temp + \endgroup +} +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? In the current directory +should work if nowhere else does.} + + +% @documentencoding should change something in TeX eventually, most +% likely, but for now just recognize it. +\let\documentencoding = \comment + + +% Page size parameters. +% +\newdimen\defaultparindent \defaultparindent = 15pt + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness = 10000 + +% Don't be so finicky about underfull hboxes, either. +\hbadness = 2000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. We call this whenever the paper size is set. +% +\def\setemergencystretch{% + \ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% + \else + \emergencystretch = .15\hsize + \fi +} + +% Parameters in order: 1) textheight; 2) textwidth; 3) voffset; +% 4) hoffset; 5) binding offset; 6) topskip. Then whoever calls us can +% set \parskip and call \setleading for \baselineskip. +% +\def\internalpagesizes#1#2#3#4#5#6{% + \voffset = #3\relax + \topskip = #6\relax + \splittopskip = \topskip + % + \vsize = #1\relax + \advance\vsize by \topskip + \outervsize = \vsize + \advance\outervsize by 2\topandbottommargin + \pageheight = \vsize + % + \hsize = #2\relax + \outerhsize = \hsize + \advance\outerhsize by 0.5in + \pagewidth = \hsize + % + \normaloffset = #4\relax + \bindingoffset = #5\relax + % + \parindent = \defaultparindent + \setemergencystretch +} + +% @letterpaper (the default). +\def\letterpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \setleading{13.2pt}% + % + % If page is nothing but text, make it come out even. + \internalpagesizes{46\baselineskip}{6in}{\voffset}{.25in}{\bindingoffset}{36pt}% +}} + +% Use @smallbook to reset parameters for 7x9.5 (or so) format. +\def\smallbook{{\globaldefs = 1 + \parskip = 2pt plus 1pt + \setleading{12pt}% + % + \internalpagesizes{7.5in}{5.in}{\voffset}{.25in}{\bindingoffset}{16pt}% + % + \lispnarrowing = 0.3in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \deftypemargin = 0pt + \defbodyindent = .5cm + % + \let\smalldisplay = \smalldisplayx + \let\smallexample = \smalllispx + \let\smallformat = \smallformatx + \let\smalllisp = \smalllispx +}} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{{\globaldefs = 1 + \setleading{12pt}% + \parskip = 3pt plus 2pt minus 1pt + % + \internalpagesizes{53\baselineskip}{160mm}{\voffset}{4mm}{\bindingoffset}{44pt}% + % + \tolerance = 700 + \hfuzz = 1pt +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin +% 29mm, hence bottom margin 28mm, nominal side margin 3cm. +\def\afourlatex{{\globaldefs = 1 + \setleading{13.6pt}% + % + \afourpaper + \internalpagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}% + % + \globaldefs = 0 +}} + +% Use @afourwide to print on European A4 paper in wide format. +\def\afourwide{% + \afourpaper + \internalpagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}% + % + \globaldefs = 0 +} + +% @pagesizes TEXTHEIGHT[,TEXTWIDTH] +% Perhaps we should allow setting the margins, \topskip, \parskip, +% and/or leading, also. Or perhaps we should compute them somehow. +% +\def\pagesizes{\parsearg\pagesizesxxx} +\def\pagesizesxxx#1{\pagesizesyyy #1,,\finish} +\def\pagesizesyyy#1,#2,#3\finish{{% + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi + \globaldefs = 1 + % + \parskip = 3pt plus 2pt minus 1pt + \setleading{13.2pt}% + % + \internalpagesizes{#1}{\hsize}{\voffset}{\normaloffset}{\bindingoffset}{44pt}% +}} + +% Set default to letter. +% +\letterpaper + + +\message{and turning on texinfo input format.} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\catcode`\$=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} +\def\normaldollar{$} + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} + +% Same as above, but check for italic font. Actually this also catches +% non-italic slanted fonts since it is impossible to distinguish them from +% italic fonts. But since this is only used by $ and it uses \sl anyway +% this is not a problem. +\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt\char34}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt\char126}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}} + +\catcode`\|=\active +\def|{{\tt\char124}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +\catcode`\$=\active +\def${\ifusingit{{\sl\$}}\normaldollar} +%\catcode 27=\active +%\def^^[{$\diamondsuit$} + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`+=\active +\catcode`\_=\active + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +\catcode`\@=0 + +% \rawbackslashxx output one backslash character in current font +\global\chardef\rawbackslashxx=`\\ +%{\catcode`\\=\other +%@gdef@rawbackslashxx{\}} + +% \rawbackslash redefines \ as input to do \rawbackslashxx. +{\catcode`\\=\active +@gdef@rawbackslash{@let\=@rawbackslashxx }} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +% \catcode 17=0 % Define control-q +\catcode`\\=\active + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +@def@turnoffactive{@let"=@normaldoublequote +@let\=@realbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus +@let$=@normaldollar} + +@def@normalturnoffactive{@let"=@normaldoublequote +@let\=@normalbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus +@let$=@normaldollar} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\{ in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also back turn on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{% + @ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active + @catcode`@_=@active +} + +% Say @foo, not \foo, in error messages. +@escapechar = `@@ + +% These look ok in all fonts, so just make them not special. +@catcode`@& = @other +@catcode`@# = @other +@catcode`@% = @other + +@c Set initial fonts. +@textfonts +@rm + + +@c Local variables: +@c eval: (add-hook 'write-file-hooks 'time-stamp) +@c page-delimiter: "^\\\\message" +@c time-stamp-start: "def\\\\texinfoversion{" +@c time-stamp-format: "%:y-%02m-%02d.%02H" +@c time-stamp-end: "}" +@c End: diff --git a/readline/readline-4.3/emacs_keymap.c b/readline/readline-4.3/emacs_keymap.c new file mode 100644 index 00000000..ca9d1343 --- /dev/null +++ b/readline/readline-4.3/emacs_keymap.c @@ -0,0 +1,873 @@ +/* emacs_keymap.c -- the keymap for emacs_mode in readline (). */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (BUFSIZ) +#include +#endif /* !BUFSIZ */ + +#include "readline.h" + +/* An array of function pointers, one for each possible key. + If the type byte is ISKMAP, then the pointer is the address of + a keymap. */ + +KEYMAP_ENTRY_ARRAY emacs_standard_keymap = { + + /* Control keys. */ + { ISFUNC, rl_set_mark }, /* Control-@ */ + { ISFUNC, rl_beg_of_line }, /* Control-a */ + { ISFUNC, rl_backward_char }, /* Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */ + { ISFUNC, rl_delete }, /* Control-d */ + { ISFUNC, rl_end_of_line }, /* Control-e */ + { ISFUNC, rl_forward_char }, /* Control-f */ + { ISFUNC, rl_abort }, /* Control-g */ + { ISFUNC, rl_rubout }, /* Control-h */ + { ISFUNC, rl_complete }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, rl_clear_screen }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_get_next_history }, /* Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */ + { ISFUNC, rl_get_previous_history }, /* Control-p */ + { ISFUNC, rl_quoted_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISKMAP, (rl_command_func_t *)emacs_ctlx_keymap }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */ + { ISKMAP, (rl_command_func_t *)emacs_meta_keymap }, /* Control-[ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */ + { ISFUNC, rl_char_search }, /* Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */ + { ISFUNC, rl_undo_command }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, rl_insert }, /* SPACE */ + { ISFUNC, rl_insert }, /* ! */ + { ISFUNC, rl_insert }, /* " */ + { ISFUNC, rl_insert }, /* # */ + { ISFUNC, rl_insert }, /* $ */ + { ISFUNC, rl_insert }, /* % */ + { ISFUNC, rl_insert }, /* & */ + { ISFUNC, rl_insert }, /* ' */ + { ISFUNC, rl_insert }, /* ( */ + { ISFUNC, rl_insert }, /* ) */ + { ISFUNC, rl_insert }, /* * */ + { ISFUNC, rl_insert }, /* + */ + { ISFUNC, rl_insert }, /* , */ + { ISFUNC, rl_insert }, /* - */ + { ISFUNC, rl_insert }, /* . */ + { ISFUNC, rl_insert }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_insert }, /* 0 */ + { ISFUNC, rl_insert }, /* 1 */ + { ISFUNC, rl_insert }, /* 2 */ + { ISFUNC, rl_insert }, /* 3 */ + { ISFUNC, rl_insert }, /* 4 */ + { ISFUNC, rl_insert }, /* 5 */ + { ISFUNC, rl_insert }, /* 6 */ + { ISFUNC, rl_insert }, /* 7 */ + { ISFUNC, rl_insert }, /* 8 */ + { ISFUNC, rl_insert }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, rl_insert }, /* : */ + { ISFUNC, rl_insert }, /* ; */ + { ISFUNC, rl_insert }, /* < */ + { ISFUNC, rl_insert }, /* = */ + { ISFUNC, rl_insert }, /* > */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_insert }, /* A */ + { ISFUNC, rl_insert }, /* B */ + { ISFUNC, rl_insert }, /* C */ + { ISFUNC, rl_insert }, /* D */ + { ISFUNC, rl_insert }, /* E */ + { ISFUNC, rl_insert }, /* F */ + { ISFUNC, rl_insert }, /* G */ + { ISFUNC, rl_insert }, /* H */ + { ISFUNC, rl_insert }, /* I */ + { ISFUNC, rl_insert }, /* J */ + { ISFUNC, rl_insert }, /* K */ + { ISFUNC, rl_insert }, /* L */ + { ISFUNC, rl_insert }, /* M */ + { ISFUNC, rl_insert }, /* N */ + { ISFUNC, rl_insert }, /* O */ + { ISFUNC, rl_insert }, /* P */ + { ISFUNC, rl_insert }, /* Q */ + { ISFUNC, rl_insert }, /* R */ + { ISFUNC, rl_insert }, /* S */ + { ISFUNC, rl_insert }, /* T */ + { ISFUNC, rl_insert }, /* U */ + { ISFUNC, rl_insert }, /* V */ + { ISFUNC, rl_insert }, /* W */ + { ISFUNC, rl_insert }, /* X */ + { ISFUNC, rl_insert }, /* Y */ + { ISFUNC, rl_insert }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, rl_insert }, /* [ */ + { ISFUNC, rl_insert }, /* \ */ + { ISFUNC, rl_insert }, /* ] */ + { ISFUNC, rl_insert }, /* ^ */ + { ISFUNC, rl_insert }, /* _ */ + { ISFUNC, rl_insert }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, rl_insert }, /* a */ + { ISFUNC, rl_insert }, /* b */ + { ISFUNC, rl_insert }, /* c */ + { ISFUNC, rl_insert }, /* d */ + { ISFUNC, rl_insert }, /* e */ + { ISFUNC, rl_insert }, /* f */ + { ISFUNC, rl_insert }, /* g */ + { ISFUNC, rl_insert }, /* h */ + { ISFUNC, rl_insert }, /* i */ + { ISFUNC, rl_insert }, /* j */ + { ISFUNC, rl_insert }, /* k */ + { ISFUNC, rl_insert }, /* l */ + { ISFUNC, rl_insert }, /* m */ + { ISFUNC, rl_insert }, /* n */ + { ISFUNC, rl_insert }, /* o */ + { ISFUNC, rl_insert }, /* p */ + { ISFUNC, rl_insert }, /* q */ + { ISFUNC, rl_insert }, /* r */ + { ISFUNC, rl_insert }, /* s */ + { ISFUNC, rl_insert }, /* t */ + { ISFUNC, rl_insert }, /* u */ + { ISFUNC, rl_insert }, /* v */ + { ISFUNC, rl_insert }, /* w */ + { ISFUNC, rl_insert }, /* x */ + { ISFUNC, rl_insert }, /* y */ + { ISFUNC, rl_insert }, /* z */ + + /* Final punctuation. */ + { ISFUNC, rl_insert }, /* { */ + { ISFUNC, rl_insert }, /* | */ + { ISFUNC, rl_insert }, /* } */ + { ISFUNC, rl_insert }, /* ~ */ + { ISFUNC, rl_rubout }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Pure 8-bit characters (128 - 159). + These might be used in some + character sets. */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + + /* ISO Latin-1 characters (160 - 255) */ + { ISFUNC, rl_insert }, /* No-break space */ + { ISFUNC, rl_insert }, /* Inverted exclamation mark */ + { ISFUNC, rl_insert }, /* Cent sign */ + { ISFUNC, rl_insert }, /* Pound sign */ + { ISFUNC, rl_insert }, /* Currency sign */ + { ISFUNC, rl_insert }, /* Yen sign */ + { ISFUNC, rl_insert }, /* Broken bar */ + { ISFUNC, rl_insert }, /* Section sign */ + { ISFUNC, rl_insert }, /* Diaeresis */ + { ISFUNC, rl_insert }, /* Copyright sign */ + { ISFUNC, rl_insert }, /* Feminine ordinal indicator */ + { ISFUNC, rl_insert }, /* Left pointing double angle quotation mark */ + { ISFUNC, rl_insert }, /* Not sign */ + { ISFUNC, rl_insert }, /* Soft hyphen */ + { ISFUNC, rl_insert }, /* Registered sign */ + { ISFUNC, rl_insert }, /* Macron */ + { ISFUNC, rl_insert }, /* Degree sign */ + { ISFUNC, rl_insert }, /* Plus-minus sign */ + { ISFUNC, rl_insert }, /* Superscript two */ + { ISFUNC, rl_insert }, /* Superscript three */ + { ISFUNC, rl_insert }, /* Acute accent */ + { ISFUNC, rl_insert }, /* Micro sign */ + { ISFUNC, rl_insert }, /* Pilcrow sign */ + { ISFUNC, rl_insert }, /* Middle dot */ + { ISFUNC, rl_insert }, /* Cedilla */ + { ISFUNC, rl_insert }, /* Superscript one */ + { ISFUNC, rl_insert }, /* Masculine ordinal indicator */ + { ISFUNC, rl_insert }, /* Right pointing double angle quotation mark */ + { ISFUNC, rl_insert }, /* Vulgar fraction one quarter */ + { ISFUNC, rl_insert }, /* Vulgar fraction one half */ + { ISFUNC, rl_insert }, /* Vulgar fraction three quarters */ + { ISFUNC, rl_insert }, /* Inverted questionk mark */ + { ISFUNC, rl_insert }, /* Latin capital letter a with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter a with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter a with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter a with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter a with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter a with ring above */ + { ISFUNC, rl_insert }, /* Latin capital letter ae */ + { ISFUNC, rl_insert }, /* Latin capital letter c with cedilla */ + { ISFUNC, rl_insert }, /* Latin capital letter e with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter e with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter e with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter e with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter i with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter i with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter i with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter i with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter eth (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin capital letter n with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter o with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter o with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter o with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter o with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter o with diaeresis */ + { ISFUNC, rl_insert }, /* Multiplication sign */ + { ISFUNC, rl_insert }, /* Latin capital letter o with stroke */ + { ISFUNC, rl_insert }, /* Latin capital letter u with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter u with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter u with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter u with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter Y with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter thorn (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin small letter sharp s (German) */ + { ISFUNC, rl_insert }, /* Latin small letter a with grave */ + { ISFUNC, rl_insert }, /* Latin small letter a with acute */ + { ISFUNC, rl_insert }, /* Latin small letter a with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter a with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter a with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter a with ring above */ + { ISFUNC, rl_insert }, /* Latin small letter ae */ + { ISFUNC, rl_insert }, /* Latin small letter c with cedilla */ + { ISFUNC, rl_insert }, /* Latin small letter e with grave */ + { ISFUNC, rl_insert }, /* Latin small letter e with acute */ + { ISFUNC, rl_insert }, /* Latin small letter e with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter e with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter i with grave */ + { ISFUNC, rl_insert }, /* Latin small letter i with acute */ + { ISFUNC, rl_insert }, /* Latin small letter i with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter i with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter eth (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin small letter n with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter o with grave */ + { ISFUNC, rl_insert }, /* Latin small letter o with acute */ + { ISFUNC, rl_insert }, /* Latin small letter o with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter o with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter o with diaeresis */ + { ISFUNC, rl_insert }, /* Division sign */ + { ISFUNC, rl_insert }, /* Latin small letter o with stroke */ + { ISFUNC, rl_insert }, /* Latin small letter u with grave */ + { ISFUNC, rl_insert }, /* Latin small letter u with acute */ + { ISFUNC, rl_insert }, /* Latin small letter u with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter u with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter y with acute */ + { ISFUNC, rl_insert }, /* Latin small letter thorn (Icelandic) */ + { ISFUNC, rl_insert } /* Latin small letter y with diaeresis */ +#endif /* KEYMAP_SIZE > 128 */ +}; + +KEYMAP_ENTRY_ARRAY emacs_meta_keymap = { + + /* Meta keys. Just like above, but the high bit is set. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-f */ + { ISFUNC, rl_abort }, /* Meta-Control-g */ + { ISFUNC, rl_backward_kill_word }, /* Meta-Control-h */ + { ISFUNC, rl_tab_insert }, /* Meta-Control-i */ + { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-l */ + { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-q */ + { ISFUNC, rl_revert_line }, /* Meta-Control-r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-t */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-x */ + { ISFUNC, rl_yank_nth_arg }, /* Meta-Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-z */ + + { ISFUNC, rl_complete }, /* Meta-Control-[ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-\ */ + { ISFUNC, rl_backward_char_search }, /* Meta-Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-^ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, rl_set_mark }, /* Meta-SPACE */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-! */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-" */ + { ISFUNC, rl_insert_comment }, /* Meta-# */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-$ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-% */ + { ISFUNC, rl_tilde_expand }, /* Meta-& */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-' */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-( */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-) */ + { ISFUNC, rl_insert_completions }, /* Meta-* */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-+ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-, */ + { ISFUNC, rl_digit_argument }, /* Meta-- */ + { ISFUNC, rl_yank_last_arg}, /* Meta-. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-/ */ + + /* Regular digits. */ + { ISFUNC, rl_digit_argument }, /* Meta-0 */ + { ISFUNC, rl_digit_argument }, /* Meta-1 */ + { ISFUNC, rl_digit_argument }, /* Meta-2 */ + { ISFUNC, rl_digit_argument }, /* Meta-3 */ + { ISFUNC, rl_digit_argument }, /* Meta-4 */ + { ISFUNC, rl_digit_argument }, /* Meta-5 */ + { ISFUNC, rl_digit_argument }, /* Meta-6 */ + { ISFUNC, rl_digit_argument }, /* Meta-7 */ + { ISFUNC, rl_digit_argument }, /* Meta-8 */ + { ISFUNC, rl_digit_argument }, /* Meta-9 */ + + /* A little more punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-: */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-; */ + { ISFUNC, rl_beginning_of_history }, /* Meta-< */ + { ISFUNC, rl_possible_completions }, /* Meta-= */ + { ISFUNC, rl_end_of_history }, /* Meta-> */ + { ISFUNC, rl_possible_completions }, /* Meta-? */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-@ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-A */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-B */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-C */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-D */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-E */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-F */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-G */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-H */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-I */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-J */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-K */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-L */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-M */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-N */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-O */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-P */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-Q */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-R */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-S */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-T */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-U */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-V */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-W */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-X */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-Y */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-Z */ + + /* Some more punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-[ */ /* was rl_arrow_keys */ + { ISFUNC, rl_delete_horizontal_space }, /* Meta-\ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-^ */ + { ISFUNC, rl_yank_last_arg }, /* Meta-_ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-` */ + + /* Lowercase alphabet. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-a */ + { ISFUNC, rl_backward_word }, /* Meta-b */ + { ISFUNC, rl_capitalize_word }, /* Meta-c */ + { ISFUNC, rl_kill_word }, /* Meta-d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-e */ + { ISFUNC, rl_forward_word }, /* Meta-f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-i */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-k */ + { ISFUNC, rl_downcase_word }, /* Meta-l */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-m */ + { ISFUNC, rl_noninc_forward_search }, /* Meta-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-o */ /* was rl_arrow_keys */ + { ISFUNC, rl_noninc_reverse_search }, /* Meta-p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-q */ + { ISFUNC, rl_revert_line }, /* Meta-r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-s */ + { ISFUNC, rl_transpose_words }, /* Meta-t */ + { ISFUNC, rl_upcase_word }, /* Meta-u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-x */ + { ISFUNC, rl_yank_pop }, /* Meta-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-z */ + + /* Final punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-{ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-| */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-} */ + { ISFUNC, rl_tilde_expand }, /* Meta-~ */ + { ISFUNC, rl_backward_kill_word }, /* Meta-rubout */ + +#if KEYMAP_SIZE > 128 + /* Undefined keys. */ + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 } +#endif /* KEYMAP_SIZE > 128 */ +}; + +KEYMAP_ENTRY_ARRAY emacs_ctlx_keymap = { + + /* Control keys. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */ + { ISFUNC, rl_abort }, /* Control-g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-i */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-l */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-q */ + { ISFUNC, rl_re_read_init_file }, /* Control-r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-t */ + { ISFUNC, rl_undo_command }, /* Control-u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-w */ + { ISFUNC, rl_exchange_point_and_mark }, /* Control-x */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-[ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* SPACE */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* " */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* # */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* $ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* % */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* & */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */ + { ISFUNC, rl_start_kbd_macro }, /* ( */ + { ISFUNC, rl_end_kbd_macro }, /* ) */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* * */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* + */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* , */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* - */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* . */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* / */ + + /* Regular digits. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 0 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 1 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 2 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 3 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 4 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 5 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 6 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 7 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 8 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* : */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ; */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* < */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* = */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* > */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ? */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_do_lowercase_version }, /* A */ + { ISFUNC, rl_do_lowercase_version }, /* B */ + { ISFUNC, rl_do_lowercase_version }, /* C */ + { ISFUNC, rl_do_lowercase_version }, /* D */ + { ISFUNC, rl_do_lowercase_version }, /* E */ + { ISFUNC, rl_do_lowercase_version }, /* F */ + { ISFUNC, rl_do_lowercase_version }, /* G */ + { ISFUNC, rl_do_lowercase_version }, /* H */ + { ISFUNC, rl_do_lowercase_version }, /* I */ + { ISFUNC, rl_do_lowercase_version }, /* J */ + { ISFUNC, rl_do_lowercase_version }, /* K */ + { ISFUNC, rl_do_lowercase_version }, /* L */ + { ISFUNC, rl_do_lowercase_version }, /* M */ + { ISFUNC, rl_do_lowercase_version }, /* N */ + { ISFUNC, rl_do_lowercase_version }, /* O */ + { ISFUNC, rl_do_lowercase_version }, /* P */ + { ISFUNC, rl_do_lowercase_version }, /* Q */ + { ISFUNC, rl_do_lowercase_version }, /* R */ + { ISFUNC, rl_do_lowercase_version }, /* S */ + { ISFUNC, rl_do_lowercase_version }, /* T */ + { ISFUNC, rl_do_lowercase_version }, /* U */ + { ISFUNC, rl_do_lowercase_version }, /* V */ + { ISFUNC, rl_do_lowercase_version }, /* W */ + { ISFUNC, rl_do_lowercase_version }, /* X */ + { ISFUNC, rl_do_lowercase_version }, /* Y */ + { ISFUNC, rl_do_lowercase_version }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* [ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* \ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ^ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* _ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* d */ + { ISFUNC, rl_call_last_kbd_macro }, /* e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* i */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* l */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* q */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* t */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* x */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* z */ + + /* Final punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* { */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* | */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* } */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ~ */ + { ISFUNC, rl_backward_kill_line }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Undefined keys. */ + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 } +#endif /* KEYMAP_SIZE > 128 */ +}; diff --git a/readline/readline-4.3/examples/Inputrc b/readline/readline-4.3/examples/Inputrc new file mode 100644 index 00000000..d7fdb42e --- /dev/null +++ b/readline/readline-4.3/examples/Inputrc @@ -0,0 +1,81 @@ +# My ~/.inputrc file is in -*- text -*- for easy editing with Emacs. +# +# Notice the various bindings which are conditionalized depending +# on which program is running, or what terminal is active. +# + +# Copyright (C) 1989-2002 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +# In all programs, all terminals, make sure this is bound. +"\C-x\C-r": re-read-init-file + +# Hp terminals (and some others) have ugly default behaviour for C-h. +"\C-h": backward-delete-char +"\e\C-h": backward-kill-word +"\C-xd": dump-functions + +# In xterm windows, make the arrow keys do the right thing. +$if TERM=xterm +"\e[A": previous-history +"\e[B": next-history +"\e[C": forward-char +"\e[D": backward-char + +# alternate arrow key prefix +"\eOA": previous-history +"\eOB": next-history +"\eOC": forward-char +"\eOD": backward-char + +# Under Xterm in Bash, we bind local Function keys to do something useful. +$if Bash +"\e[11~": "Function Key 1" +"\e[12~": "Function Key 2" +"\e[13~": "Function Key 3" +"\e[14~": "Function Key 4" +"\e[15~": "Function Key 5" + +# I know the following escape sequence numbers are 1 greater than +# the function key. Don't ask me why, I didn't design the xterm terminal. +"\e[17~": "Function Key 6" +"\e[18~": "Function Key 7" +"\e[19~": "Function Key 8" +"\e[20~": "Function Key 9" +"\e[21~": "Function Key 10" +$endif +$endif + +# For Bash, all terminals, add some Bash specific hacks. +$if Bash +"\C-xv": show-bash-version +"\C-x\C-e": shell-expand-line + +# Here is one for editing my path. +"\C-xp": "$PATH\C-x\C-e\C-e\"\C-aPATH=\":\C-b" + +# Make C-x r read my mail in emacs. +# "\C-xr": "emacs -f rmail\C-j" +$endif + +# For FTP, different hacks: +$if Ftp +"\C-xg": "get \M-?" +"\C-xt": "put \M-?" +"\M-.": yank-last-arg +$endif + +" ": self-insert diff --git a/readline/readline-4.3/examples/Makefile.in b/readline/readline-4.3/examples/Makefile.in new file mode 100644 index 00000000..72c9904f --- /dev/null +++ b/readline/readline-4.3/examples/Makefile.in @@ -0,0 +1,104 @@ +# +# This is the Makefile for the readline examples subdirectory. +# +# Copyright (C) 1994 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. +RL_LIBRARY_VERSION = @LIBVERSION@ + +SHELL = @MAKE_SHELL@ +RM = rm -f + +srcdir = @srcdir@ +VPATH = .:@srcdir@ +top_srcdir = @top_srcdir@ +BUILD_DIR = . + +# Support an alternate destination root directory for package building +DESTDIR = + +DEFS = @DEFS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LOCAL_CFLAGS = @LOCAL_CFLAGS@ -DREADLINE_LIBRARY -DRL_LIBRARY_VERSION='"$(RL_LIBRARY_VERSION)"' +CPPFLAGS = @CPPFLAGS@ + +INCLUDES = -I$(srcdir) -I$(top_srcdir) -I.. + +CCFLAGS = $(DEFS) $(LOCAL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) +LDFLAGS = -g -L.. @LDFLAGS@ + +READLINE_LIB = ../libreadline.a +HISTORY_LIB = ../libhistory.a + +TERMCAP_LIB = @TERMCAP_LIB@ + +.c.o: + ${RM} $@ + $(CC) $(CCFLAGS) -c $< + +EXECUTABLES = fileman rltest rl rlcat rlversion histexamp +OBJECTS = fileman.o rltest.o rl.o rlversion.o histexamp.o + +all: $(EXECUTABLES) +everything: all rlfe + +rl: rl.o $(READLINE_LIB) + $(CC) $(LDFLAGS) -o $@ rl.o -lreadline $(TERMCAP_LIB) + +rlcat: rlcat.o $(READLINE_LIB) + $(CC) $(LDFLAGS) -o $@ rlcat.o -lreadline $(TERMCAP_LIB) + +fileman: fileman.o $(READLINE_LIB) + $(CC) $(LDFLAGS) -o $@ fileman.o -lreadline $(TERMCAP_LIB) + +rltest: rltest.o $(READLINE_LIB) + $(CC) $(LDFLAGS) -o $@ rltest.o -lreadline $(TERMCAP_LIB) + +rlversion: rlversion.o $(READLINE_LIB) + $(CC) $(LDFLAGS) -o $@ rlversion.o -lreadline $(TERMCAP_LIB) + +histexamp: histexamp.o $(HISTORY_LIB) + $(CC) $(LDFLAGS) -o $@ histexamp.o -lhistory $(TERMCAP_LIB) + +clean mostlyclean: + $(RM) $(OBJECTS) + $(RM) $(EXECUTABLES) *.exe + $(RM) rlfe.o rlfe + +distclean maintainer-clean: clean + $(RM) Makefile + +fileman.o: fileman.c +rltest.o: rltest.c +rl.o: rl.c +rlversion.o: rlversion.c +histexamp.o: histexamp.c + +fileman.o: $(top_srcdir)/readline.h +rltest.o: $(top_srcdir)/readline.h +rl.o: $(top_srcdir)/readline.h +rlversion.o: $(top_srcdir)/readline.h +histexamp.o: $(top_srcdir)/history.h + +# Stuff for Per Bothner's `rlfe' program + +rlfe: rlfe.o $(READLINE_LIB) $(HISTORY_LIB) + $(CC) $(LDFLAGS) -o $@ rlfe.o -lreadline -lhistory ${TERMCAP_LIB} + +rlfe.o: rlfe.c + +rlfe.o: $(top_srcdir)/readline.h +rlfe.o: $(top_srcdir)/history.h diff --git a/readline/readline-4.3/examples/excallback.c b/readline/readline-4.3/examples/excallback.c new file mode 100644 index 00000000..3d4bb189 --- /dev/null +++ b/readline/readline-4.3/examples/excallback.c @@ -0,0 +1,188 @@ +/* +From: Jeff Solomon +Date: Fri, 9 Apr 1999 10:13:27 -0700 (PDT) +To: chet@po.cwru.edu +Subject: new readline example +Message-ID: <14094.12094.527305.199695@mrclean.Stanford.EDU> + +Chet, + +I've been using readline 4.0. Specifically, I've been using the perl +version Term::ReadLine::Gnu. It works great. + +Anyway, I've been playing around the alternate interface and I wanted +to contribute a little C program, callback.c, to you that you could +use as an example of the alternate interface in the /examples +directory of the readline distribution. + +My example shows how, using the alternate interface, you can +interactively change the prompt (which is very nice imo). Also, I +point out that you must roll your own terminal setting when using the +alternate interface because readline depreps (using your parlance) the +terminal while in the user callback. I try to demostrate what I mean +with an example. I've included the program below. + +To compile, I just put the program in the examples directory and made +the appropriate changes to the EXECUTABLES and OBJECTS line and added +an additional target 'callback'. + +I compiled on my Sun Solaris2.6 box using Sun's cc. + +Let me know what you think. + +Jeff +*/ + +#if defined (HAVE_CONFIG_H) +#include +#endif + +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include /* xxx - should make this more general */ + +#ifdef READLINE_LIBRARY +# include "readline.h" +#else +# include +#endif + +/* This little examples demonstrates the alternate interface to using readline. + * In the alternate interface, the user maintains control over program flow and + * only calls readline when STDIN is readable. Using the alternate interface, + * you can do anything else while still using readline (like talking to a + * network or another program) without blocking. + * + * Specifically, this program highlights two importants features of the + * alternate interface. The first is the ability to interactively change the + * prompt, which can't be done using the regular interface since rl_prompt is + * read-only. + * + * The second feature really highlights a subtle point when using the alternate + * interface. That is, readline will not alter the terminal when inside your + * callback handler. So let's so, your callback executes a user command that + * takes a non-trivial amount of time to complete (seconds). While your + * executing the command, the user continues to type keystrokes and expects them + * to be re-echoed on the new prompt when it returns. Unfortunately, the default + * terminal configuration doesn't do this. After the prompt returns, the user + * must hit one additional keystroke and then will see all of his previous + * keystrokes. To illustrate this, compile and run this program. Type "sleep" at + * the prompt and then type "bar" before the prompt returns (you have 3 + * seconds). Notice how "bar" is re-echoed on the prompt after the prompt + * returns? This is what you expect to happen. Now comment out the 4 lines below + * the line that says COMMENT LINE BELOW. Recompile and rerun the program and do + * the same thing. When the prompt returns, you should not see "bar". Now type + * "f", see how "barf" magically appears? This behavior is un-expected and not + * desired. + */ + +void process_line(char *line); +int change_prompt(void); +char *get_prompt(void); + +int prompt = 1; +char prompt_buf[40], line_buf[256]; +tcflag_t old_lflag; +cc_t old_vtime; +struct termios term; + +int +main() +{ + fd_set fds; + + /* Adjust the terminal slightly before the handler is installed. Disable + * canonical mode processing and set the input character time flag to be + * non-blocking. + */ + if( tcgetattr(STDIN_FILENO, &term) < 0 ) { + perror("tcgetattr"); + exit(1); + } + old_lflag = term.c_lflag; + old_vtime = term.c_cc[VTIME]; + term.c_lflag &= ~ICANON; + term.c_cc[VTIME] = 1; + /* COMMENT LINE BELOW - see above */ + if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 ) { + perror("tcsetattr"); + exit(1); + } + + rl_add_defun("change-prompt", change_prompt, CTRL('t')); + rl_callback_handler_install(get_prompt(), process_line); + + while(1) { + FD_ZERO(&fds); + FD_SET(fileno(stdin), &fds); + + if( select(FD_SETSIZE, &fds, NULL, NULL, NULL) < 0) { + perror("select"); + exit(1); + } + + if( FD_ISSET(fileno(stdin), &fds) ) { + rl_callback_read_char(); + } + } +} + +void +process_line(char *line) +{ + if( line == NULL ) { + fprintf(stderr, "\n", line); + + /* reset the old terminal setting before exiting */ + term.c_lflag = old_lflag; + term.c_cc[VTIME] = old_vtime; + if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 ) { + perror("tcsetattr"); + exit(1); + } + exit(0); + } + + if( strcmp(line, "sleep") == 0 ) { + sleep(3); + } else { + fprintf(stderr, "|%s|\n", line); + } + + free (line); +} + +int +change_prompt(void) +{ + /* toggle the prompt variable */ + prompt = !prompt; + + /* save away the current contents of the line */ + strcpy(line_buf, rl_line_buffer); + + /* install a new handler which will change the prompt and erase the current line */ + rl_callback_handler_install(get_prompt(), process_line); + + /* insert the old text on the new line */ + rl_insert_text(line_buf); + + /* redraw the current line - this is an undocumented function. It invokes the + * redraw-current-line command. + */ + rl_refresh_line(0, 0); +} + +char * +get_prompt(void) +{ + /* The prompts can even be different lengths! */ + sprintf(prompt_buf, "%s", + prompt ? "Hit ctrl-t to toggle prompt> " : "Pretty cool huh?> "); + return prompt_buf; +} diff --git a/readline/readline-4.3/examples/fileman.c b/readline/readline-4.3/examples/fileman.c new file mode 100644 index 00000000..340eee73 --- /dev/null +++ b/readline/readline-4.3/examples/fileman.c @@ -0,0 +1,485 @@ +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +/* fileman.c -- A tiny application which demonstrates how to use the + GNU Readline library. This application interactively allows users + to manipulate files and their modes. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#ifdef HAVE_SYS_FILE_H +# include +#endif +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include + +#if defined (HAVE_STRING_H) +# include +#else /* !HAVE_STRING_H */ +# include +#endif /* !HAVE_STRING_H */ + +#ifdef HAVE_STDLIB_H +# include +#endif + +#ifdef READLINE_LIBRARY +# include "readline.h" +# include "history.h" +#else +# include +# include +#endif + +extern char *xmalloc (); + +/* The names of functions that actually do the manipulation. */ +int com_list PARAMS((char *)); +int com_view PARAMS((char *)); +int com_rename PARAMS((char *)); +int com_stat PARAMS((char *)); +int com_pwd PARAMS((char *)); +int com_delete PARAMS((char *)); +int com_help PARAMS((char *)); +int com_cd PARAMS((char *)); +int com_quit PARAMS((char *)); + +/* A structure which contains information on the commands this program + can understand. */ + +typedef struct { + char *name; /* User printable name of the function. */ + rl_icpfunc_t *func; /* Function to call to do the job. */ + char *doc; /* Documentation for this function. */ +} COMMAND; + +COMMAND commands[] = { + { "cd", com_cd, "Change to directory DIR" }, + { "delete", com_delete, "Delete FILE" }, + { "help", com_help, "Display this text" }, + { "?", com_help, "Synonym for `help'" }, + { "list", com_list, "List files in DIR" }, + { "ls", com_list, "Synonym for `list'" }, + { "pwd", com_pwd, "Print the current working directory" }, + { "quit", com_quit, "Quit using Fileman" }, + { "rename", com_rename, "Rename FILE to NEWNAME" }, + { "stat", com_stat, "Print out statistics on FILE" }, + { "view", com_view, "View the contents of FILE" }, + { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } +}; + +/* Forward declarations. */ +char *stripwhite (); +COMMAND *find_command (); + +/* The name of this program, as taken from argv[0]. */ +char *progname; + +/* When non-zero, this global means the user is done using this program. */ +int done; + +char * +dupstr (s) + char *s; +{ + char *r; + + r = xmalloc (strlen (s) + 1); + strcpy (r, s); + return (r); +} + +main (argc, argv) + int argc; + char **argv; +{ + char *line, *s; + + progname = argv[0]; + + initialize_readline (); /* Bind our completer. */ + + /* Loop reading and executing lines until the user quits. */ + for ( ; done == 0; ) + { + line = readline ("FileMan: "); + + if (!line) + break; + + /* Remove leading and trailing whitespace from the line. + Then, if there is anything left, add it to the history list + and execute it. */ + s = stripwhite (line); + + if (*s) + { + add_history (s); + execute_line (s); + } + + free (line); + } + exit (0); +} + +/* Execute a command line. */ +int +execute_line (line) + char *line; +{ + register int i; + COMMAND *command; + char *word; + + /* Isolate the command word. */ + i = 0; + while (line[i] && whitespace (line[i])) + i++; + word = line + i; + + while (line[i] && !whitespace (line[i])) + i++; + + if (line[i]) + line[i++] = '\0'; + + command = find_command (word); + + if (!command) + { + fprintf (stderr, "%s: No such command for FileMan.\n", word); + return (-1); + } + + /* Get argument to command, if any. */ + while (whitespace (line[i])) + i++; + + word = line + i; + + /* Call the function. */ + return ((*(command->func)) (word)); +} + +/* Look up NAME as the name of a command, and return a pointer to that + command. Return a NULL pointer if NAME isn't a command name. */ +COMMAND * +find_command (name) + char *name; +{ + register int i; + + for (i = 0; commands[i].name; i++) + if (strcmp (name, commands[i].name) == 0) + return (&commands[i]); + + return ((COMMAND *)NULL); +} + +/* Strip whitespace from the start and end of STRING. Return a pointer + into STRING. */ +char * +stripwhite (string) + char *string; +{ + register char *s, *t; + + for (s = string; whitespace (*s); s++) + ; + + if (*s == 0) + return (s); + + t = s + strlen (s) - 1; + while (t > s && whitespace (*t)) + t--; + *++t = '\0'; + + return s; +} + +/* **************************************************************** */ +/* */ +/* Interface to Readline Completion */ +/* */ +/* **************************************************************** */ + +char *command_generator PARAMS((const char *, int)); +char **fileman_completion PARAMS((const char *, int, int)); + +/* Tell the GNU Readline library how to complete. We want to try to complete + on command names if this is the first word in the line, or on filenames + if not. */ +initialize_readline () +{ + /* Allow conditional parsing of the ~/.inputrc file. */ + rl_readline_name = "FileMan"; + + /* Tell the completer that we want a crack first. */ + rl_attempted_completion_function = fileman_completion; +} + +/* Attempt to complete on the contents of TEXT. START and END bound the + region of rl_line_buffer that contains the word to complete. TEXT is + the word to complete. We can use the entire contents of rl_line_buffer + in case we want to do some simple parsing. Return the array of matches, + or NULL if there aren't any. */ +char ** +fileman_completion (text, start, end) + const char *text; + int start, end; +{ + char **matches; + + matches = (char **)NULL; + + /* If this word is at the start of the line, then it is a command + to complete. Otherwise it is the name of a file in the current + directory. */ + if (start == 0) + matches = rl_completion_matches (text, command_generator); + + return (matches); +} + +/* Generator function for command completion. STATE lets us know whether + to start from scratch; without any state (i.e. STATE == 0), then we + start at the top of the list. */ +char * +command_generator (text, state) + const char *text; + int state; +{ + static int list_index, len; + char *name; + + /* If this is a new word to complete, initialize now. This includes + saving the length of TEXT for efficiency, and initializing the index + variable to 0. */ + if (!state) + { + list_index = 0; + len = strlen (text); + } + + /* Return the next name which partially matches from the command list. */ + while (name = commands[list_index].name) + { + list_index++; + + if (strncmp (name, text, len) == 0) + return (dupstr(name)); + } + + /* If no names matched, then return NULL. */ + return ((char *)NULL); +} + +/* **************************************************************** */ +/* */ +/* FileMan Commands */ +/* */ +/* **************************************************************** */ + +/* String to pass to system (). This is for the LIST, VIEW and RENAME + commands. */ +static char syscom[1024]; + +/* List the file(s) named in arg. */ +com_list (arg) + char *arg; +{ + if (!arg) + arg = ""; + + sprintf (syscom, "ls -FClg %s", arg); + return (system (syscom)); +} + +com_view (arg) + char *arg; +{ + if (!valid_argument ("view", arg)) + return 1; + +#if defined (__MSDOS__) + /* more.com doesn't grok slashes in pathnames */ + sprintf (syscom, "less %s", arg); +#else + sprintf (syscom, "more %s", arg); +#endif + return (system (syscom)); +} + +com_rename (arg) + char *arg; +{ + too_dangerous ("rename"); + return (1); +} + +com_stat (arg) + char *arg; +{ + struct stat finfo; + + if (!valid_argument ("stat", arg)) + return (1); + + if (stat (arg, &finfo) == -1) + { + perror (arg); + return (1); + } + + printf ("Statistics for `%s':\n", arg); + + printf ("%s has %d link%s, and is %d byte%s in length.\n", + arg, + finfo.st_nlink, + (finfo.st_nlink == 1) ? "" : "s", + finfo.st_size, + (finfo.st_size == 1) ? "" : "s"); + printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime)); + printf (" Last access at: %s", ctime (&finfo.st_atime)); + printf (" Last modified at: %s", ctime (&finfo.st_mtime)); + return (0); +} + +com_delete (arg) + char *arg; +{ + too_dangerous ("delete"); + return (1); +} + +/* Print out help for ARG, or for all of the commands if ARG is + not present. */ +com_help (arg) + char *arg; +{ + register int i; + int printed = 0; + + for (i = 0; commands[i].name; i++) + { + if (!*arg || (strcmp (arg, commands[i].name) == 0)) + { + printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc); + printed++; + } + } + + if (!printed) + { + printf ("No commands match `%s'. Possibilties are:\n", arg); + + for (i = 0; commands[i].name; i++) + { + /* Print in six columns. */ + if (printed == 6) + { + printed = 0; + printf ("\n"); + } + + printf ("%s\t", commands[i].name); + printed++; + } + + if (printed) + printf ("\n"); + } + return (0); +} + +/* Change to the directory ARG. */ +com_cd (arg) + char *arg; +{ + if (chdir (arg) == -1) + { + perror (arg); + return 1; + } + + com_pwd (""); + return (0); +} + +/* Print out the current working directory. */ +com_pwd (ignore) + char *ignore; +{ + char dir[1024], *s; + + s = getcwd (dir, sizeof(dir) - 1); + if (s == 0) + { + printf ("Error getting pwd: %s\n", dir); + return 1; + } + + printf ("Current directory is %s\n", dir); + return 0; +} + +/* The user wishes to quit using this program. Just set DONE non-zero. */ +com_quit (arg) + char *arg; +{ + done = 1; + return (0); +} + +/* Function which tells you that you can't do this. */ +too_dangerous (caller) + char *caller; +{ + fprintf (stderr, + "%s: Too dangerous for me to distribute. Write it yourself.\n", + caller); +} + +/* Return non-zero if ARG is a valid argument for CALLER, else print + an error message and return zero. */ +int +valid_argument (caller, arg) + char *caller, *arg; +{ + if (!arg || !*arg) + { + fprintf (stderr, "%s: Argument required.\n", caller); + return (0); + } + + return (1); +} diff --git a/readline/readline-4.3/examples/histexamp.c b/readline/readline-4.3/examples/histexamp.c new file mode 100644 index 00000000..45651dfb --- /dev/null +++ b/readline/readline-4.3/examples/histexamp.c @@ -0,0 +1,112 @@ +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#include + +#ifdef READLINE_LIBRARY +# include "history.h" +#else +# include +#endif + +main (argc, argv) + int argc; + char **argv; +{ + char line[1024], *t; + int len, done = 0; + + line[0] = 0; + + using_history (); + while (!done) + { + printf ("history$ "); + fflush (stdout); + t = fgets (line, sizeof (line) - 1, stdin); + if (t && *t) + { + len = strlen (t); + if (t[len - 1] == '\n') + t[len - 1] = '\0'; + } + + if (!t) + strcpy (line, "quit"); + + if (line[0]) + { + char *expansion; + int result; + + using_history (); + + result = history_expand (line, &expansion); + if (result) + fprintf (stderr, "%s\n", expansion); + + if (result < 0 || result == 2) + { + free (expansion); + continue; + } + + add_history (expansion); + strncpy (line, expansion, sizeof (line) - 1); + free (expansion); + } + + if (strcmp (line, "quit") == 0) + done = 1; + else if (strcmp (line, "save") == 0) + write_history ("history_file"); + else if (strcmp (line, "read") == 0) + read_history ("history_file"); + else if (strcmp (line, "list") == 0) + { + register HIST_ENTRY **the_list; + register int i; + + the_list = history_list (); + if (the_list) + for (i = 0; the_list[i]; i++) + printf ("%d: %s\n", i + history_base, the_list[i]->line); + } + else if (strncmp (line, "delete", 6) == 0) + { + int which; + if ((sscanf (line + 6, "%d", &which)) == 1) + { + HIST_ENTRY *entry = remove_history (which); + if (!entry) + fprintf (stderr, "No such entry %d\n", which); + else + { + free (entry->line); + free (entry); + } + } + else + { + fprintf (stderr, "non-numeric arg given to `delete'\n"); + } + } + } +} diff --git a/readline/readline-4.3/examples/manexamp.c b/readline/readline-4.3/examples/manexamp.c new file mode 100644 index 00000000..9c6cf2c7 --- /dev/null +++ b/readline/readline-4.3/examples/manexamp.c @@ -0,0 +1,112 @@ +/* manexamp.c -- The examples which appear in the documentation are here. */ + +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#include +#include + +/* **************************************************************** */ +/* */ +/* How to Emulate gets () */ +/* */ +/* **************************************************************** */ + +/* A static variable for holding the line. */ +static char *line_read = (char *)NULL; + +/* Read a string, and return a pointer to it. Returns NULL on EOF. */ +char * +rl_gets () +{ + /* If the buffer has already been allocated, return the memory + to the free pool. */ + if (line_read) + { + free (line_read); + line_read = (char *)NULL; + } + + /* Get a line from the user. */ + line_read = readline (""); + + /* If the line has any text in it, save it on the history. */ + if (line_read && *line_read) + add_history (line_read); + + return (line_read); +} + +/* **************************************************************** */ +/* */ +/* Writing a Function to be Called by Readline. */ +/* */ +/* **************************************************************** */ + +/* Invert the case of the COUNT following characters. */ +invert_case_line (count, key) + int count, key; +{ + register int start, end; + + start = rl_point; + + if (count < 0) + { + direction = -1; + count = -count; + } + else + direction = 1; + + /* Find the end of the range to modify. */ + end = start + (count * direction); + + /* Force it to be within range. */ + if (end > rl_end) + end = rl_end; + else if (end < 0) + end = -1; + + if (start > end) + { + int temp = start; + start = end; + end = temp; + } + + if (start == end) + return; + + /* Tell readline that we are modifying the line, so save the undo + information. */ + rl_modifying (start, end); + + for (; start != end; start += direction) + { + if (_rl_uppercase_p (rl_line_buffer[start])) + rl_line_buffer[start] = _rl_to_lower (rl_line_buffer[start]); + else if (_rl_lowercase_p (rl_line_buffer[start])) + rl_line_buffer[start] = _rl_to_upper (rl_line_buffer[start]); + } + + /* Move point to on top of the last character changed. */ + rl_point = end - direction; +} diff --git a/readline/readline-4.3/examples/readlinebuf.h b/readline/readline-4.3/examples/readlinebuf.h new file mode 100644 index 00000000..d9fdb3c9 --- /dev/null +++ b/readline/readline-4.3/examples/readlinebuf.h @@ -0,0 +1,139 @@ +/******************************************************************************* + * $Revision: 1.1.1.1 $ + * $Date: 2008/02/03 20:43:50 $ + * $Author: tim $ + * + * Contents: A streambuf which uses the GNU readline library for line I/O + * (c) 2001 by Dimitris Vyzovitis [vyzo@media.mit.edu] + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ******************************************************************************/ + +#ifndef _READLINEBUF_H_ +#define _READLINEBUF_H_ + +#include +#include +#include +#include +#include + +#include +#include + +#if (defined __GNUC__) && (__GNUC__ < 3) +#include +#else +#include +using std::streamsize; +using std::streambuf; +#endif + +class readlinebuf : public streambuf { +public: +#if (defined __GNUC__) && (__GNUC__ < 3) + typedef char char_type; + typedef int int_type; + typedef streampos pos_type; + typedef streamoff off_type; +#endif + static const int_type eof = EOF; // this is -1 + static const int_type not_eof = 0; + +private: + const char* prompt_; + bool history_; + char* line_; + int low_; + int high_; + +protected: + + virtual int_type showmanyc() const { return high_ - low_; } + + virtual streamsize xsgetn( char_type* buf, streamsize n ) { + int rd = n > (high_ - low_)? (high_ - low_) : n; + memcpy( buf, line_, rd ); + low_ += rd; + + if ( rd < n ) { + low_ = high_ = 0; + free( line_ ); // free( NULL ) is a noop + line_ = readline( prompt_ ); + if ( line_ ) { + high_ = strlen( line_ ); + if ( history_ && high_ ) add_history( line_ ); + rd += xsgetn( buf + rd, n - rd ); + } + } + + return rd; + } + + virtual int_type underflow() { + if ( high_ == low_ ) { + low_ = high_ = 0; + free( line_ ); // free( NULL ) is a noop + line_ = readline( prompt_ ); + if ( line_ ) { + high_ = strlen( line_ ); + if ( history_ && high_ ) add_history( line_ ); + } + } + + if ( low_ < high_ ) return line_[low_]; + else return eof; + } + + virtual int_type uflow() { + int_type c = underflow(); + if ( c != eof ) ++low_; + return c; + } + + virtual int_type pbackfail( int_type c = eof ) { + if ( low_ > 0 ) --low_; + else if ( c != eof ) { + if ( high_ > 0 ) { + char* nl = (char*)realloc( line_, high_ + 1 ); + if ( nl ) { + line_ = (char*)memcpy( nl + 1, line_, high_ ); + high_ += 1; + line_[0] = char( c ); + } else return eof; + } else { + assert( !line_ ); + line_ = (char*)malloc( sizeof( char ) ); + *line_ = char( c ); + high_ = 1; + } + } else return eof; + + return not_eof; + } + +public: + readlinebuf( const char* prompt = NULL, bool history = true ) + : prompt_( prompt ), history_( history ), + line_( NULL ), low_( 0 ), high_( 0 ) { + setbuf( 0, 0 ); + } + + +}; + +#endif diff --git a/readline/readline-4.3/examples/rl.c b/readline/readline-4.3/examples/rl.c new file mode 100644 index 00000000..d2604895 --- /dev/null +++ b/readline/readline-4.3/examples/rl.c @@ -0,0 +1,151 @@ +/* + * rl - command-line interface to read a line from the standard input + * (or another fd) using readline. + * + * usage: rl [-p prompt] [-u unit] [-d default] [-n nchars] + */ + +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include +#include "posixstat.h" + +#if defined (READLINE_LIBRARY) +# include "readline.h" +# include "history.h" +#else +# include +# include +#endif + +extern int optind; +extern char *optarg; + +#if !defined (strchr) && !defined (__STDC__) +extern char *strrchr(); +#endif + +static char *progname; +static char *deftext; + +static int +set_deftext () +{ + if (deftext) + { + rl_insert_text (deftext); + deftext = (char *)NULL; + rl_startup_hook = (rl_hook_func_t *)NULL; + } + return 0; +} + +static void +usage() +{ + fprintf (stderr, "%s: usage: %s [-p prompt] [-u unit] [-d default] [-n nchars]\n", + progname, progname); +} + +int +main (argc, argv) + int argc; + char **argv; +{ + char *temp, *prompt; + struct stat sb; + int opt, fd, nch; + FILE *ifp; + + progname = strrchr(argv[0], '/'); + if (progname == 0) + progname = argv[0]; + else + progname++; + + /* defaults */ + prompt = "readline$ "; + fd = nch = 0; + deftext = (char *)0; + + while ((opt = getopt(argc, argv, "p:u:d:n:")) != EOF) + { + switch (opt) + { + case 'p': + prompt = optarg; + break; + case 'u': + fd = atoi(optarg); + if (fd < 0) + { + fprintf (stderr, "%s: bad file descriptor `%s'\n", progname, optarg); + exit (2); + } + break; + case 'd': + deftext = optarg; + break; + case 'n': + nch = atoi(optarg); + if (nch < 0) + { + fprintf (stderr, "%s: bad value for -n: `%s'\n", progname, optarg); + exit (2); + } + break; + default: + usage (); + exit (2); + } + } + + if (fd != 0) + { + if (fstat (fd, &sb) < 0) + { + fprintf (stderr, "%s: %d: bad file descriptor\n", progname, fd); + exit (1); + } + ifp = fdopen (fd, "r"); + rl_instream = ifp; + } + + if (deftext && *deftext) + rl_startup_hook = set_deftext; + + if (nch > 0) + rl_num_chars_to_read = nch; + + temp = readline (prompt); + + /* Test for EOF. */ + if (temp == 0) + exit (1); + + printf ("%s\n", temp); + exit (0); +} diff --git a/readline/readline-4.3/examples/rlcat.c b/readline/readline-4.3/examples/rlcat.c new file mode 100644 index 00000000..176b9f44 --- /dev/null +++ b/readline/readline-4.3/examples/rlcat.c @@ -0,0 +1,174 @@ +/* + * rlcat - cat(1) using readline + * + * usage: rlcat + */ + +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include "posixstat.h" + +#include +#include +#include +#include + +#ifndef errno +extern int errno; +#endif + +#if defined (READLINE_LIBRARY) +# include "readline.h" +# include "history.h" +#else +# include +# include +#endif + +extern int optind; +extern char *optarg; + +static int stdcat(); + +static char *progname; +static int vflag; + +static void +usage() +{ + fprintf (stderr, "%s: usage: %s [-vEVN] [filename]\n", progname, progname); +} + +int +main (argc, argv) + int argc; + char **argv; +{ + char *temp; + int opt, Vflag, Nflag; + + progname = strrchr(argv[0], '/'); + if (progname == 0) + progname = argv[0]; + else + progname++; + + vflag = Vflag = Nflag = 0; + while ((opt = getopt(argc, argv, "vEVN")) != EOF) + { + switch (opt) + { + case 'v': + vflag = 1; + break; + case 'V': + Vflag = 1; + break; + case 'E': + Vflag = 0; + break; + case 'N': + Nflag = 1; + break; + default: + usage (); + exit (2); + } + } + + argc -= optind; + argv += optind; + + if (isatty(0) == 0 || argc || Nflag) + return stdcat(argc, argv); + + rl_variable_bind ("editing-mode", Vflag ? "vi" : "emacs"); + while (temp = readline ("")) + { + if (*temp) + add_history (temp); + printf ("%s\n", temp); + } + + return (ferror (stdout)); +} + +static int +fcopy(fp) + FILE *fp; +{ + int c; + char *x; + + while ((c = getc(fp)) != EOF) + { + if (vflag && isascii ((unsigned char)c) && isprint((unsigned char)c) == 0) + { + x = rl_untranslate_keyseq (c); + if (fputs (x, stdout) != 0) + return 1; + } + else if (putchar (c) == EOF) + return 1; + } + return (ferror (stdout)); +} + +int +stdcat (argc, argv) + int argc; + char **argv; +{ + int i, fd, r; + char *s; + FILE *fp; + + if (argc == 0) + return (fcopy(stdin)); + + for (i = 0, r = 1; i < argc; i++) + { + if (*argv[i] == '-' && argv[i][1] == 0) + fp = stdin; + else + { + fp = fopen (argv[i], "r"); + if (fp == 0) + { + fprintf (stderr, "%s: %s: cannot open: %s\n", progname, argv[i], strerror(errno)); + continue; + } + } + r = fcopy (fp); + if (fp != stdin) + fclose(fp); + } + return r; +} diff --git a/readline/readline-4.3/examples/rlfe.c b/readline/readline-4.3/examples/rlfe.c new file mode 100644 index 00000000..d634d7ce --- /dev/null +++ b/readline/readline-4.3/examples/rlfe.c @@ -0,0 +1,1042 @@ +/* A front-end using readline to "cook" input lines for Kawa. + * + * Copyright (C) 1999 Per Bothner + * + * This front-end program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * Some code from Johnson & Troan: "Linux Application Development" + * (Addison-Wesley, 1998) was used directly or for inspiration. + */ + +/* PROBLEMS/TODO: + * + * Only tested under Linux; needs to be ported. + * + * When running mc -c under the Linux console, mc does not recognize + * mouse clicks, which mc does when not running under fep. + * + * Pasting selected text containing tabs is like hitting the tab character, + * which invokes readline completion. We don't want this. I don't know + * if this is fixable without integrating fep into a terminal emulator. + * + * Echo suppression is a kludge, but can only be avoided with better kernel + * support: We need a tty mode to disable "real" echoing, while still + * letting the inferior think its tty driver to doing echoing. + * Stevens's book claims SCR$ and BSD4.3+ have TIOCREMOTE. + * + * The latest readline may have some hooks we can use to avoid having + * to back up the prompt. + * + * Desirable readline feature: When in cooked no-echo mode (e.g. password), + * echo characters are they are types with '*', but remove them when done. + * + * A synchronous output while we're editing an input line should be + * inserted in the output view *before* the input line, so that the + * lines being edited (with the prompt) float at the end of the input. + * + * A "page mode" option to emulate more/less behavior: At each page of + * output, pause for a user command. This required parsing the output + * to keep track of line lengths. It also requires remembering the + * output, if we want an option to scroll back, which suggests that + * this should be integrated with a terminal emulator like xterm. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef READLINE_LIBRARY +# include "readline.h" +# include "history.h" +#else +# include +# include +#endif + +#ifndef COMMAND +#define COMMAND "/bin/sh" +#endif +#ifndef COMMAND_ARGS +#define COMMAND_ARGS COMMAND +#endif + +#ifndef HAVE_MEMMOVE +#ifndef memmove +# if __GNUC__ > 1 +# define memmove(d, s, n) __builtin_memcpy(d, s, n) +# else +# define memmove(d, s, n) memcpy(d, s, n) +# endif +#else +# define memmove(d, s, n) memcpy(d, s, n) +#endif +#endif + +#define APPLICATION_NAME "Rlfe" + +#ifndef errno +extern int errno; +#endif + +extern int optind; +extern char *optarg; + +static char *progname; +static char *progversion; + +static int in_from_inferior_fd; +static int out_to_inferior_fd; + +/* Unfortunately, we cannot safely display echo from the inferior process. + The reason is that the echo bit in the pty is "owned" by the inferior, + and if we try to turn it off, we could confuse the inferior. + Thus, when echoing, we get echo twice: First readline echoes while + we're actually editing. Then we send the line to the inferior, and the + terminal driver send back an extra echo. + The work-around is to remember the input lines, and when we see that + line come back, we supress the output. + A better solution (supposedly available on SVR4) would be a smarter + terminal driver, with more flags ... */ +#define ECHO_SUPPRESS_MAX 1024 +char echo_suppress_buffer[ECHO_SUPPRESS_MAX]; +int echo_suppress_start = 0; +int echo_suppress_limit = 0; + +/* #define DEBUG */ + +static FILE *logfile = NULL; + +#ifdef DEBUG +FILE *debugfile = NULL; +#define DPRINT0(FMT) (fprintf(debugfile, FMT), fflush(debugfile)) +#define DPRINT1(FMT, V1) (fprintf(debugfile, FMT, V1), fflush(debugfile)) +#define DPRINT2(FMT, V1, V2) (fprintf(debugfile, FMT, V1, V2), fflush(debugfile)) +#else +#define DPRINT0(FMT) /* Do nothing */ +#define DPRINT1(FMT, V1) /* Do nothing */ +#define DPRINT2(FMT, V1, V2) /* Do nothing */ +#endif + +struct termios orig_term; + +static int rlfe_directory_completion_hook __P((char **)); +static int rlfe_directory_rewrite_hook __P((char **)); +static char *rlfe_filename_completion_function __P((const char *, int)); + +/* Pid of child process. */ +static pid_t child = -1; + +static void +sig_child (int signo) +{ + int status; + wait (&status); + DPRINT0 ("(Child process died.)\n"); + tcsetattr(STDIN_FILENO, TCSANOW, &orig_term); + exit (0); +} + +volatile int propagate_sigwinch = 0; + +/* sigwinch_handler + * propagate window size changes from input file descriptor to + * master side of pty. + */ +void sigwinch_handler(int signal) { + propagate_sigwinch = 1; +} + +/* get_master_pty() takes a double-indirect character pointer in which + * to put a slave name, and returns an integer file descriptor. + * If it returns < 0, an error has occurred. + * Otherwise, it has returned the master pty file descriptor, and fills + * in *name with the name of the corresponding slave pty. + * Once the slave pty has been opened, you are responsible to free *name. + */ + +int get_master_pty(char **name) { + int i, j; + /* default to returning error */ + int master = -1; + + /* create a dummy name to fill in */ + *name = strdup("/dev/ptyXX"); + + /* search for an unused pty */ + for (i=0; i<16 && master <= 0; i++) { + for (j=0; j<16 && master <= 0; j++) { + (*name)[5] = 'p'; + (*name)[8] = "pqrstuvwxyzPQRST"[i]; + (*name)[9] = "0123456789abcdef"[j]; + /* open the master pty */ + if ((master = open(*name, O_RDWR)) < 0) { + if (errno == ENOENT) { + /* we are out of pty devices */ + free (*name); + return (master); + } + } + else { + /* By substituting a letter, we change the master pty + * name into the slave pty name. + */ + (*name)[5] = 't'; + if (access(*name, R_OK|W_OK) != 0) + { + close(master); + master = -1; + } + } + } + } + if ((master < 0) && (i == 16) && (j == 16)) { + /* must have tried every pty unsuccessfully */ + free (*name); + return (master); + } + + (*name)[5] = 't'; + + return (master); +} + +/* get_slave_pty() returns an integer file descriptor. + * If it returns < 0, an error has occurred. + * Otherwise, it has returned the slave file descriptor. + */ + +int get_slave_pty(char *name) { + struct group *gptr; + gid_t gid; + int slave = -1; + + /* chown/chmod the corresponding pty, if possible. + * This will only work if the process has root permissions. + * Alternatively, write and exec a small setuid program that + * does just this. + */ + if ((gptr = getgrnam("tty")) != 0) { + gid = gptr->gr_gid; + } else { + /* if the tty group does not exist, don't change the + * group on the slave pty, only the owner + */ + gid = -1; + } + + /* Note that we do not check for errors here. If this is code + * where these actions are critical, check for errors! + */ + chown(name, getuid(), gid); + /* This code only makes the slave read/writeable for the user. + * If this is for an interactive shell that will want to + * receive "write" and "wall" messages, OR S_IWGRP into the + * second argument below. + */ + chmod(name, S_IRUSR|S_IWUSR); + + /* open the corresponding slave pty */ + slave = open(name, O_RDWR); + return (slave); +} + +/* Certain special characters, such as ctrl/C, we want to pass directly + to the inferior, rather than letting readline handle them. */ + +static char special_chars[20]; +static int special_chars_count; + +static void +add_special_char(int ch) +{ + if (ch != 0) + special_chars[special_chars_count++] = ch; +} + +static int eof_char; + +static int +is_special_char(int ch) +{ + int i; +#if 0 + if (ch == eof_char && rl_point == rl_end) + return 1; +#endif + for (i = special_chars_count; --i >= 0; ) + if (special_chars[i] == ch) + return 1; + return 0; +} + +static char buf[1024]; +/* buf[0 .. buf_count-1] is the what has been emitted on the current line. + It is used as the readline prompt. */ +static int buf_count = 0; + +int num_keys = 0; + +static void +null_prep_terminal (int meta) +{ +} + +static void +null_deprep_terminal () +{ +} + +char pending_special_char; + +static void +line_handler (char *line) +{ + if (line == NULL) + { + char buf[1]; + DPRINT0("saw eof!\n"); + buf[0] = '\004'; /* ctrl/d */ + write (out_to_inferior_fd, buf, 1); + } + else + { + static char enter[] = "\r"; + /* Send line to inferior: */ + int length = strlen (line); + if (length > ECHO_SUPPRESS_MAX-2) + { + echo_suppress_start = 0; + echo_suppress_limit = 0; + } + else + { + if (echo_suppress_limit + length > ECHO_SUPPRESS_MAX - 2) + { + if (echo_suppress_limit - echo_suppress_start + length + <= ECHO_SUPPRESS_MAX - 2) + { + memmove (echo_suppress_buffer, + echo_suppress_buffer + echo_suppress_start, + echo_suppress_limit - echo_suppress_start); + echo_suppress_limit -= echo_suppress_start; + echo_suppress_start = 0; + } + else + { + echo_suppress_limit = 0; + } + echo_suppress_start = 0; + } + memcpy (echo_suppress_buffer + echo_suppress_limit, + line, length); + echo_suppress_limit += length; + echo_suppress_buffer[echo_suppress_limit++] = '\r'; + echo_suppress_buffer[echo_suppress_limit++] = '\n'; + } + write (out_to_inferior_fd, line, length); + if (pending_special_char == 0) + { + write (out_to_inferior_fd, enter, sizeof(enter)-1); + if (*line) + add_history (line); + } + free (line); + } + rl_callback_handler_remove (); + buf_count = 0; + num_keys = 0; + if (pending_special_char != 0) + { + write (out_to_inferior_fd, &pending_special_char, 1); + pending_special_char = 0; + } +} + +/* Value of rl_getc_function. + Use this because readline should read from stdin, not rl_instream, + points to the pty (so readline has monitor its terminal modes). */ + +int +my_rl_getc (FILE *dummy) +{ + int ch = rl_getc (stdin); + if (is_special_char (ch)) + { + pending_special_char = ch; + return '\r'; + } + return ch; +} + +static void +usage() +{ + fprintf (stderr, "%s: usage: %s [-l filename] [-a] [-n appname] [-hv] [command [arguments...]]\n", + progname, progname); +} + +int +main(int argc, char** argv) +{ + char *path; + int i, append; + int master; + char *name, *logfname, *appname; + int in_from_tty_fd; + struct sigaction act; + struct winsize ws; + struct termios t; + int maxfd; + fd_set in_set; + static char empty_string[1] = ""; + char *prompt = empty_string; + int ioctl_err = 0; + + if ((progname = strrchr (argv[0], '/')) == 0) + progname = argv[0]; + else + progname++; + progversion = RL_LIBRARY_VERSION; + + append = 0; + appname = APPLICATION_NAME; + logfname = (char *)NULL; + + while ((i = getopt (argc, argv, "ahl:n:v")) != EOF) + { + switch (i) + { + case 'l': + logfname = optarg; + break; + case 'n': + appname = optarg; + break; + case 'a': + append = 1; + break; + case 'h': + usage (); + exit (0); + case 'v': + fprintf (stderr, "%s version %s\n", progname, progversion); + exit (0); + default: + usage (); + exit (2); + } + } + + argc -= optind; + argv += optind; + + if (logfname) + { + logfile = fopen (logfname, append ? "a" : "w"); + if (logfile == 0) + fprintf (stderr, "%s: warning: could not open log file %s: %s\n", + progname, logfname, strerror (errno)); + } + + rl_readline_name = appname; + +#ifdef DEBUG + debugfile = fopen("LOG", "w"); +#endif + + if ((master = get_master_pty(&name)) < 0) + { + perror("ptypair: could not open master pty"); + exit(1); + } + + DPRINT1("pty name: '%s'\n", name); + + /* set up SIGWINCH handler */ + act.sa_handler = sigwinch_handler; + sigemptyset(&(act.sa_mask)); + act.sa_flags = 0; + if (sigaction(SIGWINCH, &act, NULL) < 0) + { + perror("ptypair: could not handle SIGWINCH "); + exit(1); + } + + if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) + { + perror("ptypair: could not get window size"); + exit(1); + } + + if ((child = fork()) < 0) + { + perror("cannot fork"); + exit(1); + } + + if (child == 0) + { + int slave; /* file descriptor for slave pty */ + + /* We are in the child process */ + close(master); + +#ifdef TIOCSCTTY + if ((slave = get_slave_pty(name)) < 0) + { + perror("ptypair: could not open slave pty"); + exit(1); + } + free(name); +#endif + + /* We need to make this process a session group leader, because + * it is on a new PTY, and things like job control simply will + * not work correctly unless there is a session group leader + * and process group leader (which a session group leader + * automatically is). This also disassociates us from our old + * controlling tty. + */ + if (setsid() < 0) + { + perror("could not set session leader"); + } + + /* Tie us to our new controlling tty. */ +#ifdef TIOCSCTTY + if (ioctl(slave, TIOCSCTTY, NULL)) + { + perror("could not set new controlling tty"); + } +#else + if ((slave = get_slave_pty(name)) < 0) + { + perror("ptypair: could not open slave pty"); + exit(1); + } + free(name); +#endif + + /* make slave pty be standard in, out, and error */ + dup2(slave, STDIN_FILENO); + dup2(slave, STDOUT_FILENO); + dup2(slave, STDERR_FILENO); + + /* at this point the slave pty should be standard input */ + if (slave > 2) + { + close(slave); + } + + /* Try to restore window size; failure isn't critical */ + if (ioctl(STDOUT_FILENO, TIOCSWINSZ, &ws) < 0) + { + perror("could not restore window size"); + } + + /* now start the shell */ + { + static char* command_args[] = { COMMAND_ARGS, NULL }; + if (argc < 1) + execvp(COMMAND, command_args); + else + execvp(argv[0], &argv[0]); + } + + /* should never be reached */ + exit(1); + } + + /* parent */ + signal (SIGCHLD, sig_child); + free(name); + + /* Note that we only set termios settings for standard input; + * the master side of a pty is NOT a tty. + */ + tcgetattr(STDIN_FILENO, &orig_term); + + t = orig_term; + eof_char = t.c_cc[VEOF]; + /* add_special_char(t.c_cc[VEOF]);*/ + add_special_char(t.c_cc[VINTR]); + add_special_char(t.c_cc[VQUIT]); + add_special_char(t.c_cc[VSUSP]); +#if defined (VDISCARD) + add_special_char(t.c_cc[VDISCARD]); +#endif + +#if 0 + t.c_lflag |= (ICANON | ISIG | ECHO | ECHOCTL | ECHOE | \ + ECHOK | ECHOKE | ECHONL | ECHOPRT ); +#else + t.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOCTL | ECHOE | \ + ECHOK | ECHOKE | ECHONL | ECHOPRT ); +#endif + t.c_iflag |= IGNBRK; + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + tcsetattr(STDIN_FILENO, TCSANOW, &t); + in_from_inferior_fd = master; + out_to_inferior_fd = master; + rl_instream = fdopen (master, "r"); + rl_getc_function = my_rl_getc; + + rl_prep_term_function = null_prep_terminal; + rl_deprep_term_function = null_deprep_terminal; + rl_callback_handler_install (prompt, line_handler); + +#if 1 + rl_directory_completion_hook = rlfe_directory_completion_hook; + rl_completion_entry_function = rlfe_filename_completion_function; +#else + rl_directory_rewrite_hook = rlfe_directory_rewrite_hook; +#endif + + in_from_tty_fd = STDIN_FILENO; + FD_ZERO (&in_set); + maxfd = in_from_inferior_fd > in_from_tty_fd ? in_from_inferior_fd + : in_from_tty_fd; + for (;;) + { + int num; + FD_SET (in_from_inferior_fd, &in_set); + FD_SET (in_from_tty_fd, &in_set); + + num = select(maxfd+1, &in_set, NULL, NULL, NULL); + + if (propagate_sigwinch) + { + struct winsize ws; + if (ioctl (STDIN_FILENO, TIOCGWINSZ, &ws) >= 0) + { + ioctl (master, TIOCSWINSZ, &ws); + } + propagate_sigwinch = 0; + continue; + } + + if (num <= 0) + { + perror ("select"); + exit (-1); + } + if (FD_ISSET (in_from_tty_fd, &in_set)) + { + extern int readline_echoing_p; + struct termios term_master; + int do_canon = 1; + int ioctl_ret; + + DPRINT1("[tty avail num_keys:%d]\n", num_keys); + + /* If we can't get tty modes for the master side of the pty, we + can't handle non-canonical-mode programs. Always assume the + master is in canonical echo mode if we can't tell. */ + ioctl_ret = tcgetattr(master, &term_master); + + if (ioctl_ret >= 0) + { + DPRINT2 ("echo:%d, canon:%d\n", + (term_master.c_lflag & ECHO) != 0, + (term_master.c_lflag & ICANON) != 0); + do_canon = (term_master.c_lflag & ICANON) != 0; + readline_echoing_p = (term_master.c_lflag & ECHO) != 0; + } + else + { + if (ioctl_err == 0) + DPRINT1("tcgetattr on master fd failed: errno = %d\n", errno); + ioctl_err = 1; + } + + if (do_canon == 0 && num_keys == 0) + { + char ch[10]; + int count = read (STDIN_FILENO, ch, sizeof(ch)); + write (out_to_inferior_fd, ch, count); + } + else + { + if (num_keys == 0) + { + int i; + /* Re-install callback handler for new prompt. */ + if (prompt != empty_string) + free (prompt); + prompt = malloc (buf_count + 1); + if (prompt == NULL) + prompt = empty_string; + else + { + memcpy (prompt, buf, buf_count); + prompt[buf_count] = '\0'; + DPRINT1("New prompt '%s'\n", prompt); +#if 0 /* ifdef HAVE_RL_ALREADY_PROMPTED -- doesn't work */ + rl_already_prompted = buf_count > 0; +#else + if (buf_count > 0) + write (1, "\r", 1); +#endif + } + rl_callback_handler_install (prompt, line_handler); + } + num_keys++; + rl_callback_read_char (); + } + } + else /* input from inferior. */ + { + int i; + int count; + int old_count; + if (buf_count > (sizeof(buf) >> 2)) + buf_count = 0; + count = read (in_from_inferior_fd, buf+buf_count, + sizeof(buf) - buf_count); + if (count <= 0) + { + DPRINT0 ("(Connection closed by foreign host.)\n"); + tcsetattr(STDIN_FILENO, TCSANOW, &orig_term); + exit (0); + } + old_count = buf_count; + + /* Do some minimal carriage return translation and backspace + processing before logging the input line. */ + if (logfile) + { +#ifndef __GNUC__ + char *b; +#else + char b[count + 1]; +#endif + int i, j; + +#ifndef __GNUC__ + b = malloc (count + 1); + if (b) { +#endif + for (i = 0; i < count; i++) + b[i] = buf[buf_count + i]; + b[i] = '\0'; + for (i = j = 0; i <= count; i++) + { + if (b[i] == '\r') + { + if (b[i+1] != '\n') + b[j++] = '\n'; + } + else if (b[i] == '\b') + { + if (i) + j--; + } + else + b[j++] = b[i]; + } + fprintf (logfile, "%s", b); + +#ifndef __GNUC__ + free (b); + } +#endif + } + + /* Look for any pending echo that we need to suppress. */ + while (echo_suppress_start < echo_suppress_limit + && count > 0 + && buf[buf_count] == echo_suppress_buffer[echo_suppress_start]) + { + count--; + buf_count++; + echo_suppress_start++; + } + + /* Write to the terminal anything that was not suppressed. */ + if (count > 0) + write (1, buf + buf_count, count); + + /* Finally, look for a prompt candidate. + * When we get around to going input (from the keyboard), + * we will consider the prompt to be anything since the last + * line terminator. So we need to save that text in the + * initial part of buf. However, anything before the + * most recent end-of-line is not interesting. */ + buf_count += count; +#if 1 + for (i = buf_count; --i >= old_count; ) +#else + for (i = buf_count - 1; i-- >= buf_count - count; ) +#endif + { + if (buf[i] == '\n' || buf[i] == '\r') + { + i++; + memmove (buf, buf+i, buf_count - i); + buf_count -= i; + break; + } + } + DPRINT2("-> i: %d, buf_count: %d\n", i, buf_count); + } + } +} + +/* + * + * FILENAME COMPLETION FOR RLFE + * + */ + +#ifndef PATH_MAX +# define PATH_MAX 1024 +#endif + +#define DIRSEP '/' +#define ISDIRSEP(x) ((x) == '/') +#define PATHSEP(x) (ISDIRSEP(x) || (x) == 0) + +#define DOT_OR_DOTDOT(x) \ + ((x)[0] == '.' && (PATHSEP((x)[1]) || \ + ((x)[1] == '.' && PATHSEP((x)[2])))) + +#define FREE(x) if (x) free(x) + +#define STRDUP(s, x) do { \ + s = strdup (x);\ + if (s == 0) \ + return ((char *)NULL); \ + } while (0) + +static int +get_inferior_cwd (path, psize) + char *path; + size_t psize; +{ + int n; + static char procfsbuf[PATH_MAX] = { '\0' }; + + if (procfsbuf[0] == '\0') + sprintf (procfsbuf, "/proc/%d/cwd", (int)child); + n = readlink (procfsbuf, path, psize); + if (n < 0) + return n; + if (n > psize) + return -1; + path[n] = '\0'; + return n; +} + +static int +rlfe_directory_rewrite_hook (dirnamep) + char **dirnamep; +{ + char *ldirname, cwd[PATH_MAX], *retdir, *ld; + int n, ldlen; + + ldirname = *dirnamep; + + if (*ldirname == '/') + return 0; + + n = get_inferior_cwd (cwd, sizeof(cwd) - 1); + if (n < 0) + return 0; + if (n == 0) /* current directory */ + { + cwd[0] = '.'; + cwd[1] = '\0'; + n = 1; + } + + /* Minimally canonicalize ldirname by removing leading `./' */ + for (ld = ldirname; *ld; ) + { + if (ISDIRSEP (ld[0])) + ld++; + else if (ld[0] == '.' && PATHSEP(ld[1])) + ld++; + else + break; + } + ldlen = (ld && *ld) ? strlen (ld) : 0; + + retdir = (char *)malloc (n + ldlen + 3); + if (retdir == 0) + return 0; + if (ldlen) + sprintf (retdir, "%s/%s", cwd, ld); + else + strcpy (retdir, cwd); + free (ldirname); + + *dirnamep = retdir; + + DPRINT1("rl_directory_rewrite_hook returns %s\n", retdir); + return 1; +} + +/* Translate *DIRNAMEP to be relative to the inferior's CWD. Leave a trailing + slash on the result. */ +static int +rlfe_directory_completion_hook (dirnamep) + char **dirnamep; +{ + char *ldirname, *retdir; + int n, ldlen; + + ldirname = *dirnamep; + + if (*ldirname == '/') + return 0; + + n = rlfe_directory_rewrite_hook (dirnamep); + if (n == 0) + return 0; + + ldirname = *dirnamep; + ldlen = (ldirname && *ldirname) ? strlen (ldirname) : 0; + + if (ldlen == 0 || ldirname[ldlen - 1] != '/') + { + retdir = (char *)malloc (ldlen + 3); + if (retdir == 0) + return 0; + if (ldlen) + strcpy (retdir, ldirname); + else + retdir[ldlen++] = '.'; + retdir[ldlen] = '/'; + retdir[ldlen+1] = '\0'; + free (ldirname); + + *dirnamep = retdir; + } + + DPRINT1("rl_directory_completion_hook returns %s\n", retdir); + return 1; +} + +static char * +rlfe_filename_completion_function (text, state) + const char *text; + int state; +{ + static DIR *directory; + static char *filename = (char *)NULL; + static char *dirname = (char *)NULL, *ud = (char *)NULL; + static int flen, udlen; + char *temp; + struct dirent *dentry; + + if (state == 0) + { + if (directory) + { + closedir (directory); + directory = 0; + } + FREE (dirname); + FREE (filename); + FREE (ud); + + if (text && *text) + STRDUP (filename, text); + else + { + filename = malloc(1); + if (filename == 0) + return ((char *)NULL); + filename[0] = '\0'; + } + dirname = (text && *text) ? strdup (text) : strdup ("."); + if (dirname == 0) + return ((char *)NULL); + + temp = strrchr (dirname, '/'); + if (temp) + { + strcpy (filename, ++temp); + *temp = '\0'; + } + else + { + dirname[0] = '.'; + dirname[1] = '\0'; + } + + STRDUP (ud, dirname); + udlen = strlen (ud); + + rlfe_directory_completion_hook (&dirname); + + directory = opendir (dirname); + flen = strlen (filename); + + rl_filename_completion_desired = 1; + } + + dentry = 0; + while (directory && (dentry = readdir (directory))) + { + if (flen == 0) + { + if (DOT_OR_DOTDOT(dentry->d_name) == 0) + break; + } + else + { + if ((dentry->d_name[0] == filename[0]) && + (strlen (dentry->d_name) >= flen) && + (strncmp (filename, dentry->d_name, flen) == 0)) + break; + } + } + + if (dentry == 0) + { + if (directory) + { + closedir (directory); + directory = 0; + } + FREE (dirname); + FREE (filename); + FREE (ud); + dirname = filename = ud = 0; + return ((char *)NULL); + } + + if (ud == 0 || (ud[0] == '.' && ud[1] == '\0')) + temp = strdup (dentry->d_name); + else + { + temp = malloc (1 + udlen + strlen (dentry->d_name)); + strcpy (temp, ud); + strcpy (temp + udlen, dentry->d_name); + } + return (temp); +} diff --git a/readline/readline-4.3/examples/rltest.c b/readline/readline-4.3/examples/rltest.c new file mode 100644 index 00000000..99f083b2 --- /dev/null +++ b/readline/readline-4.3/examples/rltest.c @@ -0,0 +1,87 @@ +/* **************************************************************** */ +/* */ +/* Testing Readline */ +/* */ +/* **************************************************************** */ + +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if defined (HAVE_CONFIG_H) +#include +#endif + +#include +#include + +#ifdef READLINE_LIBRARY +# include "readline.h" +# include "history.h" +#else +# include +# include +#endif + +extern HIST_ENTRY **history_list (); + +main () +{ + char *temp, *prompt; + int done; + + temp = (char *)NULL; + prompt = "readline$ "; + done = 0; + + while (!done) + { + temp = readline (prompt); + + /* Test for EOF. */ + if (!temp) + exit (1); + + /* If there is anything on the line, print it and remember it. */ + if (*temp) + { + fprintf (stderr, "%s\r\n", temp); + add_history (temp); + } + + /* Check for `command' that we handle. */ + if (strcmp (temp, "quit") == 0) + done = 1; + + if (strcmp (temp, "list") == 0) + { + HIST_ENTRY **list; + register int i; + + list = history_list (); + if (list) + { + for (i = 0; list[i]; i++) + fprintf (stderr, "%d: %s\r\n", i, list[i]->line); + } + } + free (temp); + } + exit (0); +} diff --git a/readline/readline-4.3/examples/rlversion.c b/readline/readline-4.3/examples/rlversion.c new file mode 100644 index 00000000..53949d1e --- /dev/null +++ b/readline/readline-4.3/examples/rlversion.c @@ -0,0 +1,43 @@ +/* + * rlversion -- print out readline's version number + */ + +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include +#include "posixstat.h" + +#ifdef READLINE_LIBRARY +# include "readline.h" +#else +# include +#endif + +main() +{ + printf ("%s\n", rl_library_version ? rl_library_version : "unknown"); + exit (0); +} diff --git a/readline/readline-4.3/funmap.c b/readline/readline-4.3/funmap.c new file mode 100644 index 00000000..fe9a1da4 --- /dev/null +++ b/readline/readline-4.3/funmap.c @@ -0,0 +1,253 @@ +/* funmap.c -- attach names to functions. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#if !defined (BUFSIZ) +#include +#endif /* BUFSIZ */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include "rlconf.h" +#include "readline.h" + +#include "xmalloc.h" + +#ifdef __STDC__ +typedef int QSFUNC (const void *, const void *); +#else +typedef int QSFUNC (); +#endif + +extern int _rl_qsort_string_compare PARAMS((char **, char **)); + +FUNMAP **funmap; +static int funmap_size; +static int funmap_entry; + +/* After initializing the function map, this is the index of the first + program specific function. */ +int funmap_program_specific_entry_start; + +static FUNMAP default_funmap[] = { + { "abort", rl_abort }, + { "accept-line", rl_newline }, + { "arrow-key-prefix", rl_arrow_keys }, + { "backward-byte", rl_backward_byte }, + { "backward-char", rl_backward_char }, + { "backward-delete-char", rl_rubout }, + { "backward-kill-line", rl_backward_kill_line }, + { "backward-kill-word", rl_backward_kill_word }, + { "backward-word", rl_backward_word }, + { "beginning-of-history", rl_beginning_of_history }, + { "beginning-of-line", rl_beg_of_line }, + { "call-last-kbd-macro", rl_call_last_kbd_macro }, + { "capitalize-word", rl_capitalize_word }, + { "character-search", rl_char_search }, + { "character-search-backward", rl_backward_char_search }, + { "clear-screen", rl_clear_screen }, + { "complete", rl_complete }, + { "copy-backward-word", rl_copy_backward_word }, + { "copy-forward-word", rl_copy_forward_word }, + { "copy-region-as-kill", rl_copy_region_to_kill }, + { "delete-char", rl_delete }, + { "delete-char-or-list", rl_delete_or_show_completions }, + { "delete-horizontal-space", rl_delete_horizontal_space }, + { "digit-argument", rl_digit_argument }, + { "do-lowercase-version", rl_do_lowercase_version }, + { "downcase-word", rl_downcase_word }, + { "dump-functions", rl_dump_functions }, + { "dump-macros", rl_dump_macros }, + { "dump-variables", rl_dump_variables }, + { "emacs-editing-mode", rl_emacs_editing_mode }, + { "end-kbd-macro", rl_end_kbd_macro }, + { "end-of-history", rl_end_of_history }, + { "end-of-line", rl_end_of_line }, + { "exchange-point-and-mark", rl_exchange_point_and_mark }, + { "forward-backward-delete-char", rl_rubout_or_delete }, + { "forward-byte", rl_forward_byte }, + { "forward-char", rl_forward_char }, + { "forward-search-history", rl_forward_search_history }, + { "forward-word", rl_forward_word }, + { "history-search-backward", rl_history_search_backward }, + { "history-search-forward", rl_history_search_forward }, + { "insert-comment", rl_insert_comment }, + { "insert-completions", rl_insert_completions }, + { "kill-whole-line", rl_kill_full_line }, + { "kill-line", rl_kill_line }, + { "kill-region", rl_kill_region }, + { "kill-word", rl_kill_word }, + { "menu-complete", rl_menu_complete }, + { "next-history", rl_get_next_history }, + { "non-incremental-forward-search-history", rl_noninc_forward_search }, + { "non-incremental-reverse-search-history", rl_noninc_reverse_search }, + { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again }, + { "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again }, + { "overwrite-mode", rl_overwrite_mode }, +#ifdef __CYGWIN__ + { "paste-from-clipboard", rl_paste_from_clipboard }, +#endif + { "possible-completions", rl_possible_completions }, + { "previous-history", rl_get_previous_history }, + { "quoted-insert", rl_quoted_insert }, + { "re-read-init-file", rl_re_read_init_file }, + { "redraw-current-line", rl_refresh_line}, + { "reverse-search-history", rl_reverse_search_history }, + { "revert-line", rl_revert_line }, + { "self-insert", rl_insert }, + { "set-mark", rl_set_mark }, + { "start-kbd-macro", rl_start_kbd_macro }, + { "tab-insert", rl_tab_insert }, + { "tilde-expand", rl_tilde_expand }, + { "transpose-chars", rl_transpose_chars }, + { "transpose-words", rl_transpose_words }, + { "tty-status", rl_tty_status }, + { "undo", rl_undo_command }, + { "universal-argument", rl_universal_argument }, + { "unix-line-discard", rl_unix_line_discard }, + { "unix-word-rubout", rl_unix_word_rubout }, + { "upcase-word", rl_upcase_word }, + { "yank", rl_yank }, + { "yank-last-arg", rl_yank_last_arg }, + { "yank-nth-arg", rl_yank_nth_arg }, + { "yank-pop", rl_yank_pop }, + +#if defined (VI_MODE) + { "vi-append-eol", rl_vi_append_eol }, + { "vi-append-mode", rl_vi_append_mode }, + { "vi-arg-digit", rl_vi_arg_digit }, + { "vi-back-to-indent", rl_vi_back_to_indent }, + { "vi-bWord", rl_vi_bWord }, + { "vi-bword", rl_vi_bword }, + { "vi-change-case", rl_vi_change_case }, + { "vi-change-char", rl_vi_change_char }, + { "vi-change-to", rl_vi_change_to }, + { "vi-char-search", rl_vi_char_search }, + { "vi-column", rl_vi_column }, + { "vi-complete", rl_vi_complete }, + { "vi-delete", rl_vi_delete }, + { "vi-delete-to", rl_vi_delete_to }, + { "vi-eWord", rl_vi_eWord }, + { "vi-editing-mode", rl_vi_editing_mode }, + { "vi-end-word", rl_vi_end_word }, + { "vi-eof-maybe", rl_vi_eof_maybe }, + { "vi-eword", rl_vi_eword }, + { "vi-fWord", rl_vi_fWord }, + { "vi-fetch-history", rl_vi_fetch_history }, + { "vi-first-print", rl_vi_first_print }, + { "vi-fword", rl_vi_fword }, + { "vi-goto-mark", rl_vi_goto_mark }, + { "vi-insert-beg", rl_vi_insert_beg }, + { "vi-insertion-mode", rl_vi_insertion_mode }, + { "vi-match", rl_vi_match }, + { "vi-movement-mode", rl_vi_movement_mode }, + { "vi-next-word", rl_vi_next_word }, + { "vi-overstrike", rl_vi_overstrike }, + { "vi-overstrike-delete", rl_vi_overstrike_delete }, + { "vi-prev-word", rl_vi_prev_word }, + { "vi-put", rl_vi_put }, + { "vi-redo", rl_vi_redo }, + { "vi-replace", rl_vi_replace }, + { "vi-search", rl_vi_search }, + { "vi-search-again", rl_vi_search_again }, + { "vi-set-mark", rl_vi_set_mark }, + { "vi-subst", rl_vi_subst }, + { "vi-tilde-expand", rl_vi_tilde_expand }, + { "vi-yank-arg", rl_vi_yank_arg }, + { "vi-yank-to", rl_vi_yank_to }, +#endif /* VI_MODE */ + + {(char *)NULL, (rl_command_func_t *)NULL } +}; + +int +rl_add_funmap_entry (name, function) + const char *name; + rl_command_func_t *function; +{ + if (funmap_entry + 2 >= funmap_size) + { + funmap_size += 64; + funmap = (FUNMAP **)xrealloc (funmap, funmap_size * sizeof (FUNMAP *)); + } + + funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP)); + funmap[funmap_entry]->name = name; + funmap[funmap_entry]->function = function; + + funmap[++funmap_entry] = (FUNMAP *)NULL; + return funmap_entry; +} + +static int funmap_initialized; + +/* Make the funmap contain all of the default entries. */ +void +rl_initialize_funmap () +{ + register int i; + + if (funmap_initialized) + return; + + for (i = 0; default_funmap[i].name; i++) + rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function); + + funmap_initialized = 1; + funmap_program_specific_entry_start = i; +} + +/* Produce a NULL terminated array of known function names. The array + is sorted. The array itself is allocated, but not the strings inside. + You should free () the array when you done, but not the pointrs. */ +const char ** +rl_funmap_names () +{ + const char **result; + int result_size, result_index; + + /* Make sure that the function map has been initialized. */ + rl_initialize_funmap (); + + for (result_index = result_size = 0, result = (const char **)NULL; funmap[result_index]; result_index++) + { + if (result_index + 2 > result_size) + { + result_size += 20; + result = (const char **)xrealloc (result, result_size * sizeof (char *)); + } + + result[result_index] = funmap[result_index]->name; + result[result_index + 1] = (char *)NULL; + } + + qsort (result, result_index, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); + return (result); +} diff --git a/readline/readline-4.3/histexpand.c b/readline/readline-4.3/histexpand.c new file mode 100644 index 00000000..5ed8bae8 --- /dev/null +++ b/readline/readline-4.3/histexpand.c @@ -0,0 +1,1491 @@ +/* histexpand.c -- history expansion. */ + +/* Copyright (C) 1989, 1992 Free Software Foundation, Inc. + + This file contains the GNU History Library (the Library), a set of + routines for managing the text of previously typed lines. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_UNISTD_H) +# ifndef _MINIX +# include +# endif +# include +#endif + +#include "rlmbutil.h" + +#include "history.h" +#include "histlib.h" + +#include "rlshell.h" +#include "xmalloc.h" + +#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>" +#define HISTORY_QUOTE_CHARACTERS "\"'`" + +typedef int _hist_search_func_t PARAMS((const char *, int)); + +extern int rl_byte_oriented; /* declared in mbutil.c */ + +static char error_pointer; + +static char *subst_lhs; +static char *subst_rhs; +static int subst_lhs_len; +static int subst_rhs_len; + +static char *get_history_word_specifier PARAMS((char *, char *, int *)); +static char *history_find_word PARAMS((char *, int)); + +static char *quote_breaks PARAMS((char *)); + +/* Variables exported by this file. */ +/* The character that represents the start of a history expansion + request. This is usually `!'. */ +char history_expansion_char = '!'; + +/* The character that invokes word substitution if found at the start of + a line. This is usually `^'. */ +char history_subst_char = '^'; + +/* During tokenization, if this character is seen as the first character + of a word, then it, and all subsequent characters upto a newline are + ignored. For a Bourne shell, this should be '#'. Bash special cases + the interactive comment character to not be a comment delimiter. */ +char history_comment_char = '\0'; + +/* The list of characters which inhibit the expansion of text if found + immediately following history_expansion_char. */ +char *history_no_expand_chars = " \t\n\r="; + +/* If set to a non-zero value, single quotes inhibit history expansion. + The default is 0. */ +int history_quotes_inhibit_expansion = 0; + +/* Used to split words by history_tokenize_internal. */ +char *history_word_delimiters = HISTORY_WORD_DELIMITERS; + +/* If set, this points to a function that is called to verify that a + particular history expansion should be performed. */ +rl_linebuf_func_t *history_inhibit_expansion_function; + +/* **************************************************************** */ +/* */ +/* History Expansion */ +/* */ +/* **************************************************************** */ + +/* Hairy history expansion on text, not tokens. This is of general + use, and thus belongs in this library. */ + +/* The last string searched for by a !?string? search. */ +static char *search_string; + +/* The last string matched by a !?string? search. */ +static char *search_match; + +/* Return the event specified at TEXT + OFFSET modifying OFFSET to + point to after the event specifier. Just a pointer to the history + line is returned; NULL is returned in the event of a bad specifier. + You pass STRING with *INDEX equal to the history_expansion_char that + begins this specification. + DELIMITING_QUOTE is a character that is allowed to end the string + specification for what to search for in addition to the normal + characters `:', ` ', `\t', `\n', and sometimes `?'. + So you might call this function like: + line = get_history_event ("!echo:p", &index, 0); */ +char * +get_history_event (string, caller_index, delimiting_quote) + const char *string; + int *caller_index; + int delimiting_quote; +{ + register int i; + register char c; + HIST_ENTRY *entry; + int which, sign, local_index, substring_okay; + _hist_search_func_t *search_func; + char *temp; + + /* The event can be specified in a number of ways. + + !! the previous command + !n command line N + !-n current command-line minus N + !str the most recent command starting with STR + !?str[?] + the most recent command containing STR + + All values N are determined via HISTORY_BASE. */ + + i = *caller_index; + + if (string[i] != history_expansion_char) + return ((char *)NULL); + + /* Move on to the specification. */ + i++; + + sign = 1; + substring_okay = 0; + +#define RETURN_ENTRY(e, w) \ + return ((e = history_get (w)) ? e->line : (char *)NULL) + + /* Handle !! case. */ + if (string[i] == history_expansion_char) + { + i++; + which = history_base + (history_length - 1); + *caller_index = i; + RETURN_ENTRY (entry, which); + } + + /* Hack case of numeric line specification. */ + if (string[i] == '-') + { + sign = -1; + i++; + } + + if (_rl_digit_p (string[i])) + { + /* Get the extent of the digits and compute the value. */ + for (which = 0; _rl_digit_p (string[i]); i++) + which = (which * 10) + _rl_digit_value (string[i]); + + *caller_index = i; + + if (sign < 0) + which = (history_length + history_base) - which; + + RETURN_ENTRY (entry, which); + } + + /* This must be something to search for. If the spec begins with + a '?', then the string may be anywhere on the line. Otherwise, + the string must be found at the start of a line. */ + if (string[i] == '?') + { + substring_okay++; + i++; + } + + /* Only a closing `?' or a newline delimit a substring search string. */ + for (local_index = i; c = string[i]; i++) +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int v; + mbstate_t ps; + + memset (&ps, 0, sizeof (mbstate_t)); + /* These produce warnings because we're passing a const string to a + function that takes a non-const string. */ + _rl_adjust_point ((char *)string, i, &ps); + if ((v = _rl_get_char_len ((char *)string + i, &ps)) > 1) + { + i += v - 1; + continue; + } + } + else +#endif /* HANDLE_MULTIBYTE */ + if ((!substring_okay && (whitespace (c) || c == ':' || + (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) || + string[i] == delimiting_quote)) || + string[i] == '\n' || + (substring_okay && string[i] == '?')) + break; + + which = i - local_index; + temp = (char *)xmalloc (1 + which); + if (which) + strncpy (temp, string + local_index, which); + temp[which] = '\0'; + + if (substring_okay && string[i] == '?') + i++; + + *caller_index = i; + +#define FAIL_SEARCH() \ + do { \ + history_offset = history_length; free (temp) ; return (char *)NULL; \ + } while (0) + + /* If there is no search string, try to use the previous search string, + if one exists. If not, fail immediately. */ + if (*temp == '\0' && substring_okay) + { + if (search_string) + { + free (temp); + temp = savestring (search_string); + } + else + FAIL_SEARCH (); + } + + search_func = substring_okay ? history_search : history_search_prefix; + while (1) + { + local_index = (*search_func) (temp, -1); + + if (local_index < 0) + FAIL_SEARCH (); + + if (local_index == 0 || substring_okay) + { + entry = current_history (); + history_offset = history_length; + + /* If this was a substring search, then remember the + string that we matched for word substitution. */ + if (substring_okay) + { + FREE (search_string); + search_string = temp; + + FREE (search_match); + search_match = history_find_word (entry->line, local_index); + } + else + free (temp); + + return (entry->line); + } + + if (history_offset) + history_offset--; + else + FAIL_SEARCH (); + } +#undef FAIL_SEARCH +#undef RETURN_ENTRY +} + +/* Function for extracting single-quoted strings. Used for inhibiting + history expansion within single quotes. */ + +/* Extract the contents of STRING as if it is enclosed in single quotes. + SINDEX, when passed in, is the offset of the character immediately + following the opening single quote; on exit, SINDEX is left pointing + to the closing single quote. */ +static void +hist_string_extract_single_quoted (string, sindex) + char *string; + int *sindex; +{ + register int i; + + for (i = *sindex; string[i] && string[i] != '\''; i++) + ; + + *sindex = i; +} + +static char * +quote_breaks (s) + char *s; +{ + register char *p, *r; + char *ret; + int len = 3; + + for (p = s; p && *p; p++, len++) + { + if (*p == '\'') + len += 3; + else if (whitespace (*p) || *p == '\n') + len += 2; + } + + r = ret = (char *)xmalloc (len); + *r++ = '\''; + for (p = s; p && *p; ) + { + if (*p == '\'') + { + *r++ = '\''; + *r++ = '\\'; + *r++ = '\''; + *r++ = '\''; + p++; + } + else if (whitespace (*p) || *p == '\n') + { + *r++ = '\''; + *r++ = *p++; + *r++ = '\''; + } + else + *r++ = *p++; + } + *r++ = '\''; + *r = '\0'; + return ret; +} + +static char * +hist_error(s, start, current, errtype) + char *s; + int start, current, errtype; +{ + char *temp; + const char *emsg; + int ll, elen; + + ll = current - start; + + switch (errtype) + { + case EVENT_NOT_FOUND: + emsg = "event not found"; + elen = 15; + break; + case BAD_WORD_SPEC: + emsg = "bad word specifier"; + elen = 18; + break; + case SUBST_FAILED: + emsg = "substitution failed"; + elen = 19; + break; + case BAD_MODIFIER: + emsg = "unrecognized history modifier"; + elen = 29; + break; + case NO_PREV_SUBST: + emsg = "no previous substitution"; + elen = 24; + break; + default: + emsg = "unknown expansion error"; + elen = 23; + break; + } + + temp = (char *)xmalloc (ll + elen + 3); + strncpy (temp, s + start, ll); + temp[ll] = ':'; + temp[ll + 1] = ' '; + strcpy (temp + ll + 2, emsg); + return (temp); +} + +/* Get a history substitution string from STR starting at *IPTR + and return it. The length is returned in LENPTR. + + A backslash can quote the delimiter. If the string is the + empty string, the previous pattern is used. If there is + no previous pattern for the lhs, the last history search + string is used. + + If IS_RHS is 1, we ignore empty strings and set the pattern + to "" anyway. subst_lhs is not changed if the lhs is empty; + subst_rhs is allowed to be set to the empty string. */ + +static char * +get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr) + char *str; + int *iptr, delimiter, is_rhs, *lenptr; +{ + register int si, i, j, k; + char *s; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; +#endif + + s = (char *)NULL; + i = *iptr; + +#if defined (HANDLE_MULTIBYTE) + memset (&ps, 0, sizeof (mbstate_t)); + _rl_adjust_point (str, i, &ps); +#endif + + for (si = i; str[si] && str[si] != delimiter; si++) +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int v; + if ((v = _rl_get_char_len (str + si, &ps)) > 1) + si += v - 1; + else if (str[si] == '\\' && str[si + 1] == delimiter) + si++; + } + else +#endif /* HANDLE_MULTIBYTE */ + if (str[si] == '\\' && str[si + 1] == delimiter) + si++; + + if (si > i || is_rhs) + { + s = (char *)xmalloc (si - i + 1); + for (j = 0, k = i; k < si; j++, k++) + { + /* Remove a backslash quoting the search string delimiter. */ + if (str[k] == '\\' && str[k + 1] == delimiter) + k++; + s[j] = str[k]; + } + s[j] = '\0'; + if (lenptr) + *lenptr = j; + } + + i = si; + if (str[i]) + i++; + *iptr = i; + + return s; +} + +static void +postproc_subst_rhs () +{ + char *new; + int i, j, new_size; + + new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len); + for (i = j = 0; i < subst_rhs_len; i++) + { + if (subst_rhs[i] == '&') + { + if (j + subst_lhs_len >= new_size) + new = (char *)xrealloc (new, (new_size = new_size * 2 + subst_lhs_len)); + strcpy (new + j, subst_lhs); + j += subst_lhs_len; + } + else + { + /* a single backslash protects the `&' from lhs interpolation */ + if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&') + i++; + if (j >= new_size) + new = (char *)xrealloc (new, new_size *= 2); + new[j++] = subst_rhs[i]; + } + } + new[j] = '\0'; + free (subst_rhs); + subst_rhs = new; + subst_rhs_len = j; +} + +/* Expand the bulk of a history specifier starting at STRING[START]. + Returns 0 if everything is OK, -1 if an error occurred, and 1 + if the `p' modifier was supplied and the caller should just print + the returned string. Returns the new index into string in + *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */ +static int +history_expand_internal (string, start, end_index_ptr, ret_string, current_line) + char *string; + int start, *end_index_ptr; + char **ret_string; + char *current_line; /* for !# */ +{ + int i, n, starting_index; + int substitute_globally, want_quotes, print_only; + char *event, *temp, *result, *tstr, *t, c, *word_spec; + int result_len; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; + + memset (&ps, 0, sizeof (mbstate_t)); +#endif + + result = (char *)xmalloc (result_len = 128); + + i = start; + + /* If it is followed by something that starts a word specifier, + then !! is implied as the event specifier. */ + + if (member (string[i + 1], ":$*%^")) + { + char fake_s[3]; + int fake_i = 0; + i++; + fake_s[0] = fake_s[1] = history_expansion_char; + fake_s[2] = '\0'; + event = get_history_event (fake_s, &fake_i, 0); + } + else if (string[i + 1] == '#') + { + i += 2; + event = current_line; + } + else + { + int quoted_search_delimiter = 0; + + /* If the character before this `!' is a double or single + quote, then this expansion takes place inside of the + quoted string. If we have to search for some text ("!foo"), + allow the delimiter to end the search string. */ +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int c, l; + l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY); + c = string[l]; + /* XXX - original patch had i - 1 ??? If i == 0 it would fail. */ + if (i && (c == '\'' || c == '"')) + quoted_search_delimiter = c; + } + else +#endif /* HANDLE_MULTIBYTE */ + if (i && (string[i - 1] == '\'' || string[i - 1] == '"')) + quoted_search_delimiter = string[i - 1]; + + event = get_history_event (string, &i, quoted_search_delimiter); + } + + if (event == 0) + { + *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND); + free (result); + return (-1); + } + + /* If a word specifier is found, then do what that requires. */ + starting_index = i; + word_spec = get_history_word_specifier (string, event, &i); + + /* There is no such thing as a `malformed word specifier'. However, + it is possible for a specifier that has no match. In that case, + we complain. */ + if (word_spec == (char *)&error_pointer) + { + *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC); + free (result); + return (-1); + } + + /* If no word specifier, than the thing of interest was the event. */ + temp = word_spec ? savestring (word_spec) : savestring (event); + FREE (word_spec); + + /* Perhaps there are other modifiers involved. Do what they say. */ + want_quotes = substitute_globally = print_only = 0; + starting_index = i; + + while (string[i] == ':') + { + c = string[i + 1]; + + if (c == 'g') + { + substitute_globally = 1; + i++; + c = string[i + 1]; + } + + switch (c) + { + default: + *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER); + free (result); + free (temp); + return -1; + + case 'q': + want_quotes = 'q'; + break; + + case 'x': + want_quotes = 'x'; + break; + + /* :p means make this the last executed line. So we + return an error state after adding this line to the + history. */ + case 'p': + print_only++; + break; + + /* :t discards all but the last part of the pathname. */ + case 't': + tstr = strrchr (temp, '/'); + if (tstr) + { + tstr++; + t = savestring (tstr); + free (temp); + temp = t; + } + break; + + /* :h discards the last part of a pathname. */ + case 'h': + tstr = strrchr (temp, '/'); + if (tstr) + *tstr = '\0'; + break; + + /* :r discards the suffix. */ + case 'r': + tstr = strrchr (temp, '.'); + if (tstr) + *tstr = '\0'; + break; + + /* :e discards everything but the suffix. */ + case 'e': + tstr = strrchr (temp, '.'); + if (tstr) + { + t = savestring (tstr); + free (temp); + temp = t; + } + break; + + /* :s/this/that substitutes `that' for the first + occurrence of `this'. :gs/this/that substitutes `that' + for each occurrence of `this'. :& repeats the last + substitution. :g& repeats the last substitution + globally. */ + + case '&': + case 's': + { + char *new_event; + int delimiter, failed, si, l_temp; + + if (c == 's') + { + if (i + 2 < (int)strlen (string)) + { +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + _rl_adjust_point (string, i + 2, &ps); + if (_rl_get_char_len (string + i + 2, &ps) > 1) + delimiter = 0; + else + delimiter = string[i + 2]; + } + else +#endif /* HANDLE_MULTIBYTE */ + delimiter = string[i + 2]; + } + else + break; /* no search delimiter */ + + i += 3; + + t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len); + /* An empty substitution lhs with no previous substitution + uses the last search string as the lhs. */ + if (t) + { + FREE (subst_lhs); + subst_lhs = t; + } + else if (!subst_lhs) + { + if (search_string && *search_string) + { + subst_lhs = savestring (search_string); + subst_lhs_len = strlen (subst_lhs); + } + else + { + subst_lhs = (char *) NULL; + subst_lhs_len = 0; + } + } + + FREE (subst_rhs); + subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len); + + /* If `&' appears in the rhs, it's supposed to be replaced + with the lhs. */ + if (member ('&', subst_rhs)) + postproc_subst_rhs (); + } + else + i += 2; + + /* If there is no lhs, the substitution can't succeed. */ + if (subst_lhs_len == 0) + { + *ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST); + free (result); + free (temp); + return -1; + } + + l_temp = strlen (temp); + /* Ignore impossible cases. */ + if (subst_lhs_len > l_temp) + { + *ret_string = hist_error (string, starting_index, i, SUBST_FAILED); + free (result); + free (temp); + return (-1); + } + + /* Find the first occurrence of THIS in TEMP. */ + si = 0; + for (failed = 1; (si + subst_lhs_len) <= l_temp; si++) + if (STREQN (temp+si, subst_lhs, subst_lhs_len)) + { + int len = subst_rhs_len - subst_lhs_len + l_temp; + new_event = (char *)xmalloc (1 + len); + strncpy (new_event, temp, si); + strncpy (new_event + si, subst_rhs, subst_rhs_len); + strncpy (new_event + si + subst_rhs_len, + temp + si + subst_lhs_len, + l_temp - (si + subst_lhs_len)); + new_event[len] = '\0'; + free (temp); + temp = new_event; + + failed = 0; + + if (substitute_globally) + { + si += subst_rhs_len; + l_temp = strlen (temp); + substitute_globally++; + continue; + } + else + break; + } + + if (substitute_globally > 1) + { + substitute_globally = 0; + continue; /* don't want to increment i */ + } + + if (failed == 0) + continue; /* don't want to increment i */ + + *ret_string = hist_error (string, starting_index, i, SUBST_FAILED); + free (result); + free (temp); + return (-1); + } + } + i += 2; + } + /* Done with modfiers. */ + /* Believe it or not, we have to back the pointer up by one. */ + --i; + + if (want_quotes) + { + char *x; + + if (want_quotes == 'q') + x = sh_single_quote (temp); + else if (want_quotes == 'x') + x = quote_breaks (temp); + else + x = savestring (temp); + + free (temp); + temp = x; + } + + n = strlen (temp); + if (n >= result_len) + result = (char *)xrealloc (result, n + 2); + strcpy (result, temp); + free (temp); + + *end_index_ptr = i; + *ret_string = result; + return (print_only); +} + +/* Expand the string STRING, placing the result into OUTPUT, a pointer + to a string. Returns: + + -1) If there was an error in expansion. + 0) If no expansions took place (or, if the only change in + the text was the de-slashifying of the history expansion + character) + 1) If expansions did take place + 2) If the `p' modifier was given and the caller should print the result + + If an error ocurred in expansion, then OUTPUT contains a descriptive + error message. */ + +#define ADD_STRING(s) \ + do \ + { \ + int sl = strlen (s); \ + j += sl; \ + if (j >= result_len) \ + { \ + while (j >= result_len) \ + result_len += 128; \ + result = (char *)xrealloc (result, result_len); \ + } \ + strcpy (result + j - sl, s); \ + } \ + while (0) + +#define ADD_CHAR(c) \ + do \ + { \ + if (j >= result_len - 1) \ + result = (char *)xrealloc (result, result_len += 64); \ + result[j++] = c; \ + result[j] = '\0'; \ + } \ + while (0) + +int +history_expand (hstring, output) + char *hstring; + char **output; +{ + register int j; + int i, r, l, passc, cc, modified, eindex, only_printing; + char *string; + + /* The output string, and its length. */ + int result_len; + char *result; + +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; + mbstate_t ps; +#endif + + /* Used when adding the string. */ + char *temp; + + if (output == 0) + return 0; + + /* Setting the history expansion character to 0 inhibits all + history expansion. */ + if (history_expansion_char == 0) + { + *output = savestring (hstring); + return (0); + } + + /* Prepare the buffer for printing error messages. */ + result = (char *)xmalloc (result_len = 256); + result[0] = '\0'; + + only_printing = modified = 0; + l = strlen (hstring); + + /* Grovel the string. Only backslash and single quotes can quote the + history escape character. We also handle arg specifiers. */ + + /* Before we grovel forever, see if the history_expansion_char appears + anywhere within the text. */ + + /* The quick substitution character is a history expansion all right. That + is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact, + that is the substitution that we do. */ + if (hstring[0] == history_subst_char) + { + string = (char *)xmalloc (l + 5); + + string[0] = string[1] = history_expansion_char; + string[2] = ':'; + string[3] = 's'; + strcpy (string + 4, hstring); + l += 4; + } + else + { +#if defined (HANDLE_MULTIBYTE) + memset (&ps, 0, sizeof (mbstate_t)); +#endif + + string = hstring; + /* If not quick substitution, still maybe have to do expansion. */ + + /* `!' followed by one of the characters in history_no_expand_chars + is NOT an expansion. */ + for (i = 0; string[i]; i++) + { +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int v; + v = _rl_get_char_len (string + i, &ps); + if (v > 1) + { + i += v - 1; + continue; + } + } +#endif /* HANDLE_MULTIBYTE */ + + cc = string[i + 1]; + /* The history_comment_char, if set, appearing at the beginning + of a word signifies that the rest of the line should not have + history expansion performed on it. + Skip the rest of the line and break out of the loop. */ + if (history_comment_char && string[i] == history_comment_char && + (i == 0 || member (string[i - 1], history_word_delimiters))) + { + while (string[i]) + i++; + break; + } + else if (string[i] == history_expansion_char) + { + if (!cc || member (cc, history_no_expand_chars)) + continue; + /* If the calling application has set + history_inhibit_expansion_function to a function that checks + for special cases that should not be history expanded, + call the function and skip the expansion if it returns a + non-zero value. */ + else if (history_inhibit_expansion_function && + (*history_inhibit_expansion_function) (string, i)) + continue; + else + break; + } + /* XXX - at some point, might want to extend this to handle + double quotes as well. */ + else if (history_quotes_inhibit_expansion && string[i] == '\'') + { + /* If this is bash, single quotes inhibit history expansion. */ + i++; + hist_string_extract_single_quoted (string, &i); + } + else if (history_quotes_inhibit_expansion && string[i] == '\\') + { + /* If this is bash, allow backslashes to quote single + quotes and the history expansion character. */ + if (cc == '\'' || cc == history_expansion_char) + i++; + } + } + + if (string[i] != history_expansion_char) + { + free (result); + *output = savestring (string); + return (0); + } + } + + /* Extract and perform the substitution. */ + for (passc = i = j = 0; i < l; i++) + { + int tchar = string[i]; + + if (passc) + { + passc = 0; + ADD_CHAR (tchar); + continue; + } + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int k, c; + + c = tchar; + memset (mb, 0, sizeof (mb)); + for (k = 0; k < MB_LEN_MAX; k++) + { + mb[k] = (char)c; + memset (&ps, 0, sizeof (mbstate_t)); + if (_rl_get_char_len (mb, &ps) == -2) + c = string[++i]; + else + break; + } + if (strlen (mb) > 1) + { + ADD_STRING (mb); + break; + } + } +#endif /* HANDLE_MULTIBYTE */ + + if (tchar == history_expansion_char) + tchar = -3; + else if (tchar == history_comment_char) + tchar = -2; + + switch (tchar) + { + default: + ADD_CHAR (string[i]); + break; + + case '\\': + passc++; + ADD_CHAR (tchar); + break; + + case '\'': + { + /* If history_quotes_inhibit_expansion is set, single quotes + inhibit history expansion. */ + if (history_quotes_inhibit_expansion) + { + int quote, slen; + + quote = i++; + hist_string_extract_single_quoted (string, &i); + + slen = i - quote + 2; + temp = (char *)xmalloc (slen); + strncpy (temp, string + quote, slen); + temp[slen - 1] = '\0'; + ADD_STRING (temp); + free (temp); + } + else + ADD_CHAR (string[i]); + break; + } + + case -2: /* history_comment_char */ + if (i == 0 || member (string[i - 1], history_word_delimiters)) + { + temp = (char *)xmalloc (l - i + 1); + strcpy (temp, string + i); + ADD_STRING (temp); + free (temp); + i = l; + } + else + ADD_CHAR (string[i]); + break; + + case -3: /* history_expansion_char */ + cc = string[i + 1]; + + /* If the history_expansion_char is followed by one of the + characters in history_no_expand_chars, then it is not a + candidate for expansion of any kind. */ + if (member (cc, history_no_expand_chars)) + { + ADD_CHAR (string[i]); + break; + } + +#if defined (NO_BANG_HASH_MODIFIERS) + /* There is something that is listed as a `word specifier' in csh + documentation which means `the expanded text to this point'. + That is not a word specifier, it is an event specifier. If we + don't want to allow modifiers with `!#', just stick the current + output line in again. */ + if (cc == '#') + { + if (result) + { + temp = (char *)xmalloc (1 + strlen (result)); + strcpy (temp, result); + ADD_STRING (temp); + free (temp); + } + i++; + break; + } +#endif + + r = history_expand_internal (string, i, &eindex, &temp, result); + if (r < 0) + { + *output = temp; + free (result); + if (string != hstring) + free (string); + return -1; + } + else + { + if (temp) + { + modified++; + if (*temp) + ADD_STRING (temp); + free (temp); + } + only_printing = r == 1; + i = eindex; + } + break; + } + } + + *output = result; + if (string != hstring) + free (string); + + if (only_printing) + { + add_history (result); + return (2); + } + + return (modified != 0); +} + +/* Return a consed string which is the word specified in SPEC, and found + in FROM. NULL is returned if there is no spec. The address of + ERROR_POINTER is returned if the word specified cannot be found. + CALLER_INDEX is the offset in SPEC to start looking; it is updated + to point to just after the last character parsed. */ +static char * +get_history_word_specifier (spec, from, caller_index) + char *spec, *from; + int *caller_index; +{ + register int i = *caller_index; + int first, last; + int expecting_word_spec = 0; + char *result; + + /* The range of words to return doesn't exist yet. */ + first = last = 0; + result = (char *)NULL; + + /* If we found a colon, then this *must* be a word specification. If + it isn't, then it is an error. */ + if (spec[i] == ':') + { + i++; + expecting_word_spec++; + } + + /* Handle special cases first. */ + + /* `%' is the word last searched for. */ + if (spec[i] == '%') + { + *caller_index = i + 1; + return (search_match ? savestring (search_match) : savestring ("")); + } + + /* `*' matches all of the arguments, but not the command. */ + if (spec[i] == '*') + { + *caller_index = i + 1; + result = history_arg_extract (1, '$', from); + return (result ? result : savestring ("")); + } + + /* `$' is last arg. */ + if (spec[i] == '$') + { + *caller_index = i + 1; + return (history_arg_extract ('$', '$', from)); + } + + /* Try to get FIRST and LAST figured out. */ + + if (spec[i] == '-') + first = 0; + else if (spec[i] == '^') + first = 1; + else if (_rl_digit_p (spec[i]) && expecting_word_spec) + { + for (first = 0; _rl_digit_p (spec[i]); i++) + first = (first * 10) + _rl_digit_value (spec[i]); + } + else + return ((char *)NULL); /* no valid `first' for word specifier */ + + if (spec[i] == '^' || spec[i] == '*') + { + last = (spec[i] == '^') ? 1 : '$'; /* x* abbreviates x-$ */ + i++; + } + else if (spec[i] != '-') + last = first; + else + { + i++; + + if (_rl_digit_p (spec[i])) + { + for (last = 0; _rl_digit_p (spec[i]); i++) + last = (last * 10) + _rl_digit_value (spec[i]); + } + else if (spec[i] == '$') + { + i++; + last = '$'; + } +#if 0 + else if (!spec[i] || spec[i] == ':') + /* check against `:' because there could be a modifier separator */ +#else + else + /* csh seems to allow anything to terminate the word spec here, + leaving it as an abbreviation. */ +#endif + last = -1; /* x- abbreviates x-$ omitting word `$' */ + } + + *caller_index = i; + + if (last >= first || last == '$' || last < 0) + result = history_arg_extract (first, last, from); + + return (result ? result : (char *)&error_pointer); +} + +/* Extract the args specified, starting at FIRST, and ending at LAST. + The args are taken from STRING. If either FIRST or LAST is < 0, + then make that arg count from the right (subtract from the number of + tokens, so that FIRST = -1 means the next to last token on the line). + If LAST is `$' the last arg from STRING is used. */ +char * +history_arg_extract (first, last, string) + int first, last; + const char *string; +{ + register int i, len; + char *result; + int size, offset; + char **list; + + /* XXX - think about making history_tokenize return a struct array, + each struct in array being a string and a length to avoid the + calls to strlen below. */ + if ((list = history_tokenize (string)) == NULL) + return ((char *)NULL); + + for (len = 0; list[len]; len++) + ; + + if (last < 0) + last = len + last - 1; + + if (first < 0) + first = len + first - 1; + + if (last == '$') + last = len - 1; + + if (first == '$') + first = len - 1; + + last++; + + if (first >= len || last > len || first < 0 || last < 0 || first > last) + result = ((char *)NULL); + else + { + for (size = 0, i = first; i < last; i++) + size += strlen (list[i]) + 1; + result = (char *)xmalloc (size + 1); + result[0] = '\0'; + + for (i = first, offset = 0; i < last; i++) + { + strcpy (result + offset, list[i]); + offset += strlen (list[i]); + if (i + 1 < last) + { + result[offset++] = ' '; + result[offset] = 0; + } + } + } + + for (i = 0; i < len; i++) + free (list[i]); + free (list); + + return (result); +} + +#define slashify_in_quotes "\\`\"$" + +/* Parse STRING into tokens and return an array of strings. If WIND is + not -1 and INDP is not null, we also want the word surrounding index + WIND. The position in the returned array of strings is returned in + *INDP. */ +static char ** +history_tokenize_internal (string, wind, indp) + const char *string; + int wind, *indp; +{ + char **result; + register int i, start, result_index, size; + int len, delimiter; + + /* If we're searching for a string that's not part of a word (e.g., " "), + make sure we set *INDP to a reasonable value. */ + if (indp && wind != -1) + *indp = -1; + + /* Get a token, and stuff it into RESULT. The tokens are split + exactly where the shell would split them. */ + for (i = result_index = size = 0, result = (char **)NULL; string[i]; ) + { + delimiter = 0; + + /* Skip leading whitespace. */ + for (; string[i] && whitespace (string[i]); i++) + ; + if (string[i] == 0 || string[i] == history_comment_char) + return (result); + + start = i; + + if (member (string[i], "()\n")) + { + i++; + goto got_token; + } + + if (member (string[i], "<>;&|$")) + { + int peek = string[i + 1]; + + if (peek == string[i] && peek != '$') + { + if (peek == '<' && string[i + 2] == '-') + i++; + i += 2; + goto got_token; + } + else + { + if ((peek == '&' && (string[i] == '>' || string[i] == '<')) || + ((peek == '>') && (string[i] == '&')) || + ((peek == '(') && (string[i] == '$'))) + { + i += 2; + goto got_token; + } + } + if (string[i] != '$') + { + i++; + goto got_token; + } + } + + /* Get word from string + i; */ + + if (member (string[i], HISTORY_QUOTE_CHARACTERS)) + delimiter = string[i++]; + + for (; string[i]; i++) + { + if (string[i] == '\\' && string[i + 1] == '\n') + { + i++; + continue; + } + + if (string[i] == '\\' && delimiter != '\'' && + (delimiter != '"' || member (string[i], slashify_in_quotes))) + { + i++; + continue; + } + + if (delimiter && string[i] == delimiter) + { + delimiter = 0; + continue; + } + + if (!delimiter && (member (string[i], history_word_delimiters))) + break; + + if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS)) + delimiter = string[i]; + } + + got_token: + + /* If we are looking for the word in which the character at a + particular index falls, remember it. */ + if (indp && wind != -1 && wind >= start && wind < i) + *indp = result_index; + + len = i - start; + if (result_index + 2 >= size) + result = (char **)xrealloc (result, ((size += 10) * sizeof (char *))); + result[result_index] = (char *)xmalloc (1 + len); + strncpy (result[result_index], string + start, len); + result[result_index][len] = '\0'; + result[++result_index] = (char *)NULL; + } + + return (result); +} + +/* Return an array of tokens, much as the shell might. The tokens are + parsed out of STRING. */ +char ** +history_tokenize (string) + const char *string; +{ + return (history_tokenize_internal (string, -1, (int *)NULL)); +} + +/* Find and return the word which contains the character at index IND + in the history line LINE. Used to save the word matched by the + last history !?string? search. */ +static char * +history_find_word (line, ind) + char *line; + int ind; +{ + char **words, *s; + int i, wind; + + words = history_tokenize_internal (line, ind, &wind); + if (wind == -1 || words == 0) + return ((char *)NULL); + s = words[wind]; + for (i = 0; i < wind; i++) + free (words[i]); + for (i = wind + 1; words[i]; i++) + free (words[i]); + free (words); + return s; +} diff --git a/readline/readline-4.3/histfile.c b/readline/readline-4.3/histfile.c new file mode 100644 index 00000000..60a91251 --- /dev/null +++ b/readline/readline-4.3/histfile.c @@ -0,0 +1,479 @@ +/* histfile.c - functions to manipulate the history file. */ + +/* Copyright (C) 1989, 1992 Free Software Foundation, Inc. + + This file contains the GNU History Library (the Library), a set of + routines for managing the text of previously typed lines. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +/* The goal is to make the implementation transparent, so that you + don't have to know what data types are used, just what functions + you can call. I think I have done that. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#include +#ifndef _MINIX +# include +#endif +#include "posixstat.h" +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#if defined (__EMX__) || defined (__CYGWIN__) +# undef HAVE_MMAP +#endif + +#ifdef HAVE_MMAP +# include + +# ifdef MAP_FILE +# define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE) +# define MAP_WFLAGS (MAP_FILE|MAP_SHARED) +# else +# define MAP_RFLAGS MAP_PRIVATE +# define MAP_WFLAGS MAP_SHARED +# endif + +# ifndef MAP_FAILED +# define MAP_FAILED ((void *)-1) +# endif + +#endif /* HAVE_MMAP */ + +/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment + on win 95/98/nt), we want to open files with O_BINARY mode so that there + is no \n -> \r\n conversion performed. On other systems, we don't want to + mess around with O_BINARY at all, so we ensure that it's defined to 0. */ +#if defined (__EMX__) || defined (__CYGWIN__) +# ifndef O_BINARY +# define O_BINARY 0 +# endif +#else /* !__EMX__ && !__CYGWIN__ */ +# undef O_BINARY +# define O_BINARY 0 +#endif /* !__EMX__ && !__CYGWIN__ */ + +#include +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +#include "history.h" +#include "histlib.h" + +#include "rlshell.h" +#include "xmalloc.h" + +/* Return the string that should be used in the place of this + filename. This only matters when you don't specify the + filename to read_history (), or write_history (). */ +static char * +history_filename (filename) + const char *filename; +{ + char *return_val; + const char *home; + int home_len; + + return_val = filename ? savestring (filename) : (char *)NULL; + + if (return_val) + return (return_val); + + home = sh_get_env_value ("HOME"); + + if (home == 0) + { + home = "."; + home_len = 1; + } + else + home_len = strlen (home); + + return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */ + strcpy (return_val, home); + return_val[home_len] = '/'; +#if defined (__MSDOS__) + strcpy (return_val + home_len + 1, "_history"); +#else + strcpy (return_val + home_len + 1, ".history"); +#endif + + return (return_val); +} + +/* Add the contents of FILENAME to the history list, a line at a time. + If FILENAME is NULL, then read from ~/.history. Returns 0 if + successful, or errno if not. */ +int +read_history (filename) + const char *filename; +{ + return (read_history_range (filename, 0, -1)); +} + +/* Read a range of lines from FILENAME, adding them to the history list. + Start reading at the FROM'th line and end at the TO'th. If FROM + is zero, start at the beginning. If TO is less than FROM, read + until the end of the file. If FILENAME is NULL, then read from + ~/.history. Returns 0 if successful, or errno if not. */ +int +read_history_range (filename, from, to) + const char *filename; + int from, to; +{ + register char *line_start, *line_end; + char *input, *buffer, *bufend; + int file, current_line, chars_read; + struct stat finfo; + size_t file_size; + + buffer = (char *)NULL; + input = history_filename (filename); + file = open (input, O_RDONLY|O_BINARY, 0666); + + if ((file < 0) || (fstat (file, &finfo) == -1)) + goto error_and_exit; + + file_size = (size_t)finfo.st_size; + + /* check for overflow on very large files */ + if (file_size != finfo.st_size || file_size + 1 < file_size) + { +#if defined (EFBIG) + errno = EFBIG; +#elif defined (EOVERFLOW) + errno = EOVERFLOW; +#endif + goto error_and_exit; + } + +#ifdef HAVE_MMAP + /* We map read/write and private so we can change newlines to NULs without + affecting the underlying object. */ + buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0); + if ((void *)buffer == MAP_FAILED) + goto error_and_exit; + chars_read = file_size; +#else + buffer = (char *)malloc (file_size + 1); + if (buffer == 0) + goto error_and_exit; + + chars_read = read (file, buffer, file_size); +#endif + if (chars_read < 0) + { + error_and_exit: + chars_read = errno; + if (file >= 0) + close (file); + + FREE (input); +#ifndef HAVE_MMAP + FREE (buffer); +#endif + + return (chars_read); + } + + close (file); + + /* Set TO to larger than end of file if negative. */ + if (to < 0) + to = chars_read; + + /* Start at beginning of file, work to end. */ + bufend = buffer + chars_read; + current_line = 0; + + /* Skip lines until we are at FROM. */ + for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++) + if (*line_end == '\n') + { + current_line++; + line_start = line_end + 1; + } + + /* If there are lines left to gobble, then gobble them now. */ + for (line_end = line_start; line_end < bufend; line_end++) + if (*line_end == '\n') + { + *line_end = '\0'; + + if (*line_start) + add_history (line_start); + + current_line++; + + if (current_line >= to) + break; + + line_start = line_end + 1; + } + + FREE (input); +#ifndef HAVE_MMAP + FREE (buffer); +#else + munmap (buffer, file_size); +#endif + + return (0); +} + +/* Truncate the history file FNAME, leaving only LINES trailing lines. + If FNAME is NULL, then use ~/.history. Returns 0 on success, errno + on failure. */ +int +history_truncate_file (fname, lines) + const char *fname; + int lines; +{ + char *buffer, *filename, *bp; + int file, chars_read, rv; + struct stat finfo; + size_t file_size; + + buffer = (char *)NULL; + filename = history_filename (fname); + file = open (filename, O_RDONLY|O_BINARY, 0666); + rv = 0; + + /* Don't try to truncate non-regular files. */ + if (file == -1 || fstat (file, &finfo) == -1) + { + rv = errno; + if (file != -1) + close (file); + goto truncate_exit; + } + + if (S_ISREG (finfo.st_mode) == 0) + { + close (file); +#ifdef EFTYPE + rv = EFTYPE; +#else + rv = EINVAL; +#endif + goto truncate_exit; + } + + file_size = (size_t)finfo.st_size; + + /* check for overflow on very large files */ + if (file_size != finfo.st_size || file_size + 1 < file_size) + { + close (file); +#if defined (EFBIG) + rv = errno = EFBIG; +#elif defined (EOVERFLOW) + rv = errno = EOVERFLOW; +#else + rv = errno = EINVAL; +#endif + goto truncate_exit; + } + + buffer = (char *)malloc (file_size + 1); + if (buffer == 0) + { + close (file); + goto truncate_exit; + } + + chars_read = read (file, buffer, file_size); + close (file); + + if (chars_read <= 0) + { + rv = (chars_read < 0) ? errno : 0; + goto truncate_exit; + } + + /* Count backwards from the end of buffer until we have passed + LINES lines. */ + for (bp = buffer + chars_read - 1; lines && bp > buffer; bp--) + { + if (*bp == '\n') + lines--; + } + + /* If this is the first line, then the file contains exactly the + number of lines we want to truncate to, so we don't need to do + anything. It's the first line if we don't find a newline between + the current value of i and 0. Otherwise, write from the start of + this line until the end of the buffer. */ + for ( ; bp > buffer; bp--) + if (*bp == '\n') + { + bp++; + break; + } + + /* Write only if there are more lines in the file than we want to + truncate to. */ + if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1)) + { + write (file, bp, chars_read - (bp - buffer)); + +#if defined (__BEOS__) + /* BeOS ignores O_TRUNC. */ + ftruncate (file, chars_read - (bp - buffer)); +#endif + + close (file); + } + + truncate_exit: + + FREE (buffer); + + free (filename); + return rv; +} + +/* Workhorse function for writing history. Writes NELEMENT entries + from the history list to FILENAME. OVERWRITE is non-zero if you + wish to replace FILENAME with the entries. */ +static int +history_do_write (filename, nelements, overwrite) + const char *filename; + int nelements, overwrite; +{ + register int i; + char *output; + int file, mode, rv; + size_t cursize; + +#ifdef HAVE_MMAP + mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY; +#else + mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY; +#endif + output = history_filename (filename); + rv = 0; + + if ((file = open (output, mode, 0600)) == -1) + { + FREE (output); + return (errno); + } + +#ifdef HAVE_MMAP + cursize = overwrite ? 0 : lseek (file, 0, SEEK_END); +#endif + + if (nelements > history_length) + nelements = history_length; + + /* Build a buffer of all the lines to write, and write them in one syscall. + Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */ + { + HIST_ENTRY **the_history; /* local */ + register int j; + int buffer_size; + char *buffer; + + the_history = history_list (); + /* Calculate the total number of bytes to write. */ + for (buffer_size = 0, i = history_length - nelements; i < history_length; i++) + buffer_size += 1 + strlen (the_history[i]->line); + + /* Allocate the buffer, and fill it. */ +#ifdef HAVE_MMAP + if (ftruncate (file, buffer_size+cursize) == -1) + goto mmap_error; + buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize); + if ((void *)buffer == MAP_FAILED) + { +mmap_error: + rv = errno; + FREE (output); + close (file); + return rv; + } +#else + buffer = (char *)malloc (buffer_size); + if (buffer == 0) + { + rv = errno; + FREE (output); + close (file); + return rv; + } +#endif + + for (j = 0, i = history_length - nelements; i < history_length; i++) + { + strcpy (buffer + j, the_history[i]->line); + j += strlen (the_history[i]->line); + buffer[j++] = '\n'; + } + +#ifdef HAVE_MMAP + if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0) + rv = errno; +#else + if (write (file, buffer, buffer_size) < 0) + rv = errno; + free (buffer); +#endif + } + + close (file); + + FREE (output); + + return (rv); +} + +/* Append NELEMENT entries to FILENAME. The entries appended are from + the end of the list minus NELEMENTs up to the end of the list. */ +int +append_history (nelements, filename) + int nelements; + const char *filename; +{ + return (history_do_write (filename, nelements, HISTORY_APPEND)); +} + +/* Overwrite FILENAME with the current history. If FILENAME is NULL, + then write the history list to ~/.history. Values returned + are as in read_history ().*/ +int +write_history (filename) + const char *filename; +{ + return (history_do_write (filename, history_length, HISTORY_OVERWRITE)); +} diff --git a/readline/readline-4.3/histlib.h b/readline/readline-4.3/histlib.h new file mode 100644 index 00000000..c39af718 --- /dev/null +++ b/readline/readline-4.3/histlib.h @@ -0,0 +1,82 @@ +/* histlib.h -- internal definitions for the history library. */ +/* Copyright (C) 1989, 1992 Free Software Foundation, Inc. + + This file contains the GNU History Library (the Library), a set of + routines for managing the text of previously typed lines. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_HISTLIB_H_) +#define _HISTLIB_H_ + +#if defined (HAVE_STRING_H) +# include +#else +# include +#endif /* !HAVE_STRING_H */ + +#if !defined (STREQ) +#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0)) +#define STREQN(a, b, n) (((n) == 0) ? (1) \ + : ((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0)) +#endif + +#ifndef savestring +#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x)) +#endif + +#ifndef whitespace +#define whitespace(c) (((c) == ' ') || ((c) == '\t')) +#endif + +#ifndef _rl_digit_p +#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9') +#endif + +#ifndef _rl_digit_value +#define _rl_digit_value(c) ((c) - '0') +#endif + +#ifndef member +# ifndef strchr +extern char *strchr (); +# endif +#define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0) +#endif + +#ifndef FREE +# define FREE(x) if (x) free (x) +#endif + +/* Possible history errors passed to hist_error. */ +#define EVENT_NOT_FOUND 0 +#define BAD_WORD_SPEC 1 +#define SUBST_FAILED 2 +#define BAD_MODIFIER 3 +#define NO_PREV_SUBST 4 + +/* Possible definitions for history starting point specification. */ +#define ANCHORED_SEARCH 1 +#define NON_ANCHORED_SEARCH 0 + +/* Possible definitions for what style of writing the history file we want. */ +#define HISTORY_APPEND 0 +#define HISTORY_OVERWRITE 1 + +/* Some variable definitions shared across history source files. */ +extern int history_offset; + +#endif /* !_HISTLIB_H_ */ diff --git a/readline/readline-4.3/history.c b/readline/readline-4.3/history.c new file mode 100644 index 00000000..4242f33e --- /dev/null +++ b/readline/readline-4.3/history.c @@ -0,0 +1,381 @@ +/* History.c -- standalone history library */ + +/* Copyright (C) 1989, 1992 Free Software Foundation, Inc. + + This file contains the GNU History Library (the Library), a set of + routines for managing the text of previously typed lines. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +/* The goal is to make the implementation transparent, so that you + don't have to know what data types are used, just what functions + you can call. I think I have done that. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif +# include +#endif + +#include "history.h" +#include "histlib.h" + +#include "xmalloc.h" + +/* The number of slots to increase the_history by. */ +#define DEFAULT_HISTORY_GROW_SIZE 50 + +/* **************************************************************** */ +/* */ +/* History Functions */ +/* */ +/* **************************************************************** */ + +/* An array of HIST_ENTRY. This is where we store the history. */ +static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL; + +/* Non-zero means that we have enforced a limit on the amount of + history that we save. */ +static int history_stifled; + +/* The current number of slots allocated to the input_history. */ +static int history_size; + +/* If HISTORY_STIFLED is non-zero, then this is the maximum number of + entries to remember. */ +int history_max_entries; +int max_input_history; /* backwards compatibility */ + +/* The current location of the interactive history pointer. Just makes + life easier for outside callers. */ +int history_offset; + +/* The number of strings currently stored in the history list. */ +int history_length; + +/* The logical `base' of the history array. It defaults to 1. */ +int history_base = 1; + +/* Return the current HISTORY_STATE of the history. */ +HISTORY_STATE * +history_get_history_state () +{ + HISTORY_STATE *state; + + state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE)); + state->entries = the_history; + state->offset = history_offset; + state->length = history_length; + state->size = history_size; + state->flags = 0; + if (history_stifled) + state->flags |= HS_STIFLED; + + return (state); +} + +/* Set the state of the current history array to STATE. */ +void +history_set_history_state (state) + HISTORY_STATE *state; +{ + the_history = state->entries; + history_offset = state->offset; + history_length = state->length; + history_size = state->size; + if (state->flags & HS_STIFLED) + history_stifled = 1; +} + +/* Begin a session in which the history functions might be used. This + initializes interactive variables. */ +void +using_history () +{ + history_offset = history_length; +} + +/* Return the number of bytes that the primary history entries are using. + This just adds up the lengths of the_history->lines. */ +int +history_total_bytes () +{ + register int i, result; + + for (i = result = 0; the_history && the_history[i]; i++) + result += strlen (the_history[i]->line); + + return (result); +} + +/* Returns the magic number which says what history element we are + looking at now. In this implementation, it returns history_offset. */ +int +where_history () +{ + return (history_offset); +} + +/* Make the current history item be the one at POS, an absolute index. + Returns zero if POS is out of range, else non-zero. */ +int +history_set_pos (pos) + int pos; +{ + if (pos > history_length || pos < 0 || !the_history) + return (0); + history_offset = pos; + return (1); +} + +/* Return the current history array. The caller has to be carefull, since this + is the actual array of data, and could be bashed or made corrupt easily. + The array is terminated with a NULL pointer. */ +HIST_ENTRY ** +history_list () +{ + return (the_history); +} + +/* Return the history entry at the current position, as determined by + history_offset. If there is no entry there, return a NULL pointer. */ +HIST_ENTRY * +current_history () +{ + return ((history_offset == history_length) || the_history == 0) + ? (HIST_ENTRY *)NULL + : the_history[history_offset]; +} + +/* Back up history_offset to the previous history entry, and return + a pointer to that entry. If there is no previous entry then return + a NULL pointer. */ +HIST_ENTRY * +previous_history () +{ + return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL; +} + +/* Move history_offset forward to the next history entry, and return + a pointer to that entry. If there is no next entry then return a + NULL pointer. */ +HIST_ENTRY * +next_history () +{ + return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset]; +} + +/* Return the history entry which is logically at OFFSET in the history array. + OFFSET is relative to history_base. */ +HIST_ENTRY * +history_get (offset) + int offset; +{ + int local_index; + + local_index = offset - history_base; + return (local_index >= history_length || local_index < 0 || !the_history) + ? (HIST_ENTRY *)NULL + : the_history[local_index]; +} + +/* Place STRING at the end of the history list. The data field + is set to NULL. */ +void +add_history (string) + const char *string; +{ + HIST_ENTRY *temp; + + if (history_stifled && (history_length == history_max_entries)) + { + register int i; + + /* If the history is stifled, and history_length is zero, + and it equals history_max_entries, we don't save items. */ + if (history_length == 0) + return; + + /* If there is something in the slot, then remove it. */ + if (the_history[0]) + { + free (the_history[0]->line); + free (the_history[0]); + } + + /* Copy the rest of the entries, moving down one slot. */ + for (i = 0; i < history_length; i++) + the_history[i] = the_history[i + 1]; + + history_base++; + } + else + { + if (history_size == 0) + { + history_size = DEFAULT_HISTORY_GROW_SIZE; + the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *)); + history_length = 1; + } + else + { + if (history_length == (history_size - 1)) + { + history_size += DEFAULT_HISTORY_GROW_SIZE; + the_history = (HIST_ENTRY **) + xrealloc (the_history, history_size * sizeof (HIST_ENTRY *)); + } + history_length++; + } + } + + temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + temp->line = savestring (string); + temp->data = (char *)NULL; + + the_history[history_length] = (HIST_ENTRY *)NULL; + the_history[history_length - 1] = temp; +} + +/* Make the history entry at WHICH have LINE and DATA. This returns + the old entry so you can dispose of the data. In the case of an + invalid WHICH, a NULL pointer is returned. */ +HIST_ENTRY * +replace_history_entry (which, line, data) + int which; + const char *line; + histdata_t data; +{ + HIST_ENTRY *temp, *old_value; + + if (which >= history_length) + return ((HIST_ENTRY *)NULL); + + temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + old_value = the_history[which]; + + temp->line = savestring (line); + temp->data = data; + the_history[which] = temp; + + return (old_value); +} + +/* Remove history element WHICH from the history. The removed + element is returned to you so you can free the line, data, + and containing structure. */ +HIST_ENTRY * +remove_history (which) + int which; +{ + HIST_ENTRY *return_value; + register int i; + + if (which >= history_length || !history_length) + return_value = (HIST_ENTRY *)NULL; + else + { + return_value = the_history[which]; + + for (i = which; i < history_length; i++) + the_history[i] = the_history[i + 1]; + + history_length--; + } + + return (return_value); +} + +/* Stifle the history list, remembering only MAX number of lines. */ +void +stifle_history (max) + int max; +{ + register int i, j; + + if (max < 0) + max = 0; + + if (history_length > max) + { + /* This loses because we cannot free the data. */ + for (i = 0, j = history_length - max; i < j; i++) + { + free (the_history[i]->line); + free (the_history[i]); + } + + history_base = i; + for (j = 0, i = history_length - max; j < max; i++, j++) + the_history[j] = the_history[i]; + the_history[j] = (HIST_ENTRY *)NULL; + history_length = j; + } + + history_stifled = 1; + max_input_history = history_max_entries = max; +} + +/* Stop stifling the history. This returns the previous maximum + number of history entries. The value is positive if the history + was stifled, negative if it wasn't. */ +int +unstifle_history () +{ + if (history_stifled) + { + history_stifled = 0; + return (history_max_entries); + } + else + return (-history_max_entries); +} + +int +history_is_stifled () +{ + return (history_stifled); +} + +void +clear_history () +{ + register int i; + + /* This loses because we cannot free the data. */ + for (i = 0; i < history_length; i++) + { + free (the_history[i]->line); + free (the_history[i]); + the_history[i] = (HIST_ENTRY *)NULL; + } + + history_offset = history_length = 0; +} diff --git a/readline/readline-4.3/history.h b/readline/readline-4.3/history.h new file mode 100644 index 00000000..58b5de46 --- /dev/null +++ b/readline/readline-4.3/history.h @@ -0,0 +1,246 @@ +/* History.h -- the names of functions that you can call in history. */ +/* Copyright (C) 1989, 1992 Free Software Foundation, Inc. + + This file contains the GNU History Library (the Library), a set of + routines for managing the text of previously typed lines. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#ifndef _HISTORY_H_ +#define _HISTORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined READLINE_LIBRARY +# include "rlstdc.h" +# include "rltypedefs.h" +#else +# include +# include +#endif + +#ifdef __STDC__ +typedef void *histdata_t; +#else +typedef char *histdata_t; +#endif + +/* The structure used to store a history entry. */ +typedef struct _hist_entry { + char *line; + histdata_t data; +} HIST_ENTRY; + +/* A structure used to pass the current state of the history stuff around. */ +typedef struct _hist_state { + HIST_ENTRY **entries; /* Pointer to the entries themselves. */ + int offset; /* The location pointer within this array. */ + int length; /* Number of elements within this array. */ + int size; /* Number of slots allocated to this array. */ + int flags; +} HISTORY_STATE; + +/* Flag values for the `flags' member of HISTORY_STATE. */ +#define HS_STIFLED 0x01 + +/* Initialization and state management. */ + +/* Begin a session in which the history functions might be used. This + just initializes the interactive variables. */ +extern void using_history PARAMS((void)); + +/* Return the current HISTORY_STATE of the history. */ +extern HISTORY_STATE *history_get_history_state PARAMS((void)); + +/* Set the state of the current history array to STATE. */ +extern void history_set_history_state PARAMS((HISTORY_STATE *)); + +/* Manage the history list. */ + +/* Place STRING at the end of the history list. + The associated data field (if any) is set to NULL. */ +extern void add_history PARAMS((const char *)); + +/* A reasonably useless function, only here for completeness. WHICH + is the magic number that tells us which element to delete. The + elements are numbered from 0. */ +extern HIST_ENTRY *remove_history PARAMS((int)); + +/* Make the history entry at WHICH have LINE and DATA. This returns + the old entry so you can dispose of the data. In the case of an + invalid WHICH, a NULL pointer is returned. */ +extern HIST_ENTRY *replace_history_entry PARAMS((int, const char *, histdata_t)); + +/* Clear the history list and start over. */ +extern void clear_history PARAMS((void)); + +/* Stifle the history list, remembering only MAX number of entries. */ +extern void stifle_history PARAMS((int)); + +/* Stop stifling the history. This returns the previous amount the + history was stifled by. The value is positive if the history was + stifled, negative if it wasn't. */ +extern int unstifle_history PARAMS((void)); + +/* Return 1 if the history is stifled, 0 if it is not. */ +extern int history_is_stifled PARAMS((void)); + +/* Information about the history list. */ + +/* Return a NULL terminated array of HIST_ENTRY which is the current input + history. Element 0 of this list is the beginning of time. If there + is no history, return NULL. */ +extern HIST_ENTRY **history_list PARAMS((void)); + +/* Returns the number which says what history element we are now + looking at. */ +extern int where_history PARAMS((void)); + +/* Return the history entry at the current position, as determined by + history_offset. If there is no entry there, return a NULL pointer. */ +extern HIST_ENTRY *current_history PARAMS((void)); + +/* Return the history entry which is logically at OFFSET in the history + array. OFFSET is relative to history_base. */ +extern HIST_ENTRY *history_get PARAMS((int)); + +/* Return the number of bytes that the primary history entries are using. + This just adds up the lengths of the_history->lines. */ +extern int history_total_bytes PARAMS((void)); + +/* Moving around the history list. */ + +/* Set the position in the history list to POS. */ +extern int history_set_pos PARAMS((int)); + +/* Back up history_offset to the previous history entry, and return + a pointer to that entry. If there is no previous entry, return + a NULL pointer. */ +extern HIST_ENTRY *previous_history PARAMS((void)); + +/* Move history_offset forward to the next item in the input_history, + and return the a pointer to that entry. If there is no next entry, + return a NULL pointer. */ +extern HIST_ENTRY *next_history PARAMS((void)); + +/* Searching the history list. */ + +/* Search the history for STRING, starting at history_offset. + If DIRECTION < 0, then the search is through previous entries, + else through subsequent. If the string is found, then + current_history () is the history entry, and the value of this function + is the offset in the line of that history entry that the string was + found in. Otherwise, nothing is changed, and a -1 is returned. */ +extern int history_search PARAMS((const char *, int)); + +/* Search the history for STRING, starting at history_offset. + The search is anchored: matching lines must begin with string. + DIRECTION is as in history_search(). */ +extern int history_search_prefix PARAMS((const char *, int)); + +/* Search for STRING in the history list, starting at POS, an + absolute index into the list. DIR, if negative, says to search + backwards from POS, else forwards. + Returns the absolute index of the history element where STRING + was found, or -1 otherwise. */ +extern int history_search_pos PARAMS((const char *, int, int)); + +/* Managing the history file. */ + +/* Add the contents of FILENAME to the history list, a line at a time. + If FILENAME is NULL, then read from ~/.history. Returns 0 if + successful, or errno if not. */ +extern int read_history PARAMS((const char *)); + +/* Read a range of lines from FILENAME, adding them to the history list. + Start reading at the FROM'th line and end at the TO'th. If FROM + is zero, start at the beginning. If TO is less than FROM, read + until the end of the file. If FILENAME is NULL, then read from + ~/.history. Returns 0 if successful, or errno if not. */ +extern int read_history_range PARAMS((const char *, int, int)); + +/* Write the current history to FILENAME. If FILENAME is NULL, + then write the history list to ~/.history. Values returned + are as in read_history (). */ +extern int write_history PARAMS((const char *)); + +/* Append NELEMENT entries to FILENAME. The entries appended are from + the end of the list minus NELEMENTs up to the end of the list. */ +extern int append_history PARAMS((int, const char *)); + +/* Truncate the history file, leaving only the last NLINES lines. */ +extern int history_truncate_file PARAMS((const char *, int)); + +/* History expansion. */ + +/* Expand the string STRING, placing the result into OUTPUT, a pointer + to a string. Returns: + + 0) If no expansions took place (or, if the only change in + the text was the de-slashifying of the history expansion + character) + 1) If expansions did take place + -1) If there was an error in expansion. + 2) If the returned line should just be printed. + + If an error ocurred in expansion, then OUTPUT contains a descriptive + error message. */ +extern int history_expand PARAMS((char *, char **)); + +/* Extract a string segment consisting of the FIRST through LAST + arguments present in STRING. Arguments are broken up as in + the shell. */ +extern char *history_arg_extract PARAMS((int, int, const char *)); + +/* Return the text of the history event beginning at the current + offset into STRING. Pass STRING with *INDEX equal to the + history_expansion_char that begins this specification. + DELIMITING_QUOTE is a character that is allowed to end the string + specification for what to search for in addition to the normal + characters `:', ` ', `\t', `\n', and sometimes `?'. */ +extern char *get_history_event PARAMS((const char *, int *, int)); + +/* Return an array of tokens, much as the shell might. The tokens are + parsed out of STRING. */ +extern char **history_tokenize PARAMS((const char *)); + +/* Exported history variables. */ +extern int history_base; +extern int history_length; +extern int history_max_entries; +extern char history_expansion_char; +extern char history_subst_char; +extern char *history_word_delimiters; +extern char history_comment_char; +extern char *history_no_expand_chars; +extern char *history_search_delimiter_chars; +extern int history_quotes_inhibit_expansion; + +/* Backwards compatibility */ +extern int max_input_history; + +/* If set, this function is called to decide whether or not a particular + history expansion should be treated as a special case for the calling + application and not expanded. */ +extern rl_linebuf_func_t *history_inhibit_expansion_function; + +#ifdef __cplusplus +} +#endif + +#endif /* !_HISTORY_H_ */ diff --git a/readline/readline-4.3/histsearch.c b/readline/readline-4.3/histsearch.c new file mode 100644 index 00000000..d94fd6cd --- /dev/null +++ b/readline/readline-4.3/histsearch.c @@ -0,0 +1,195 @@ +/* histsearch.c -- searching the history list. */ + +/* Copyright (C) 1989, 1992 Free Software Foundation, Inc. + + This file contains the GNU History Library (the Library), a set of + routines for managing the text of previously typed lines. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif +# include +#endif + +#include "history.h" +#include "histlib.h" + +/* The list of alternate characters that can delimit a history search + string. */ +char *history_search_delimiter_chars = (char *)NULL; + +static int history_search_internal PARAMS((const char *, int, int)); + +/* Search the history for STRING, starting at history_offset. + If DIRECTION < 0, then the search is through previous entries, else + through subsequent. If ANCHORED is non-zero, the string must + appear at the beginning of a history line, otherwise, the string + may appear anywhere in the line. If the string is found, then + current_history () is the history entry, and the value of this + function is the offset in the line of that history entry that the + string was found in. Otherwise, nothing is changed, and a -1 is + returned. */ + +static int +history_search_internal (string, direction, anchored) + const char *string; + int direction, anchored; +{ + register int i, reverse; + register char *line; + register int line_index; + int string_len; + HIST_ENTRY **the_history; /* local */ + + i = history_offset; + reverse = (direction < 0); + + /* Take care of trivial cases first. */ + if (string == 0 || *string == '\0') + return (-1); + + if (!history_length || ((i == history_length) && !reverse)) + return (-1); + + if (reverse && (i == history_length)) + i--; + +#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0) + + the_history = history_list (); + string_len = strlen (string); + while (1) + { + /* Search each line in the history list for STRING. */ + + /* At limit for direction? */ + if ((reverse && i < 0) || (!reverse && i == history_length)) + return (-1); + + line = the_history[i]->line; + line_index = strlen (line); + + /* If STRING is longer than line, no match. */ + if (string_len > line_index) + { + NEXT_LINE (); + continue; + } + + /* Handle anchored searches first. */ + if (anchored == ANCHORED_SEARCH) + { + if (STREQN (string, line, string_len)) + { + history_offset = i; + return (0); + } + + NEXT_LINE (); + continue; + } + + /* Do substring search. */ + if (reverse) + { + line_index -= string_len; + + while (line_index >= 0) + { + if (STREQN (string, line + line_index, string_len)) + { + history_offset = i; + return (line_index); + } + line_index--; + } + } + else + { + register int limit; + + limit = line_index - string_len + 1; + line_index = 0; + + while (line_index < limit) + { + if (STREQN (string, line + line_index, string_len)) + { + history_offset = i; + return (line_index); + } + line_index++; + } + } + NEXT_LINE (); + } +} + +/* Do a non-anchored search for STRING through the history in DIRECTION. */ +int +history_search (string, direction) + const char *string; + int direction; +{ + return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); +} + +/* Do an anchored search for string through the history in DIRECTION. */ +int +history_search_prefix (string, direction) + const char *string; + int direction; +{ + return (history_search_internal (string, direction, ANCHORED_SEARCH)); +} + +/* Search for STRING in the history list. DIR is < 0 for searching + backwards. POS is an absolute index into the history list at + which point to begin searching. */ +int +history_search_pos (string, dir, pos) + const char *string; + int dir, pos; +{ + int ret, old; + + old = where_history (); + history_set_pos (pos); + if (history_search (string, dir) == -1) + { + history_set_pos (old); + return (-1); + } + ret = where_history (); + history_set_pos (old); + return ret; +} diff --git a/readline/readline-4.3/input.c b/readline/readline-4.3/input.c new file mode 100644 index 00000000..841f05d1 --- /dev/null +++ b/readline/readline-4.3/input.c @@ -0,0 +1,540 @@ +/* input.c -- character input functions for readline. */ + +/* Copyright (C) 1994 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include +#if defined (HAVE_SYS_FILE_H) +# include +#endif /* HAVE_SYS_FILE_H */ + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_SELECT) +# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX) +# include +# endif +#endif /* HAVE_SELECT */ +#if defined (HAVE_SYS_SELECT_H) +# include +#endif + +#if defined (FIONREAD_IN_SYS_IOCTL) +# include +#endif + +#include +#include + +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +/* Some standard library routines. */ +#include "readline.h" + +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + +/* What kind of non-blocking I/O do we have? */ +#if !defined (O_NDELAY) && defined (O_NONBLOCK) +# define O_NDELAY O_NONBLOCK /* Posix style */ +#endif + +/* Non-null means it is a pointer to a function to run while waiting for + character input. */ +rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL; + +rl_getc_func_t *rl_getc_function = rl_getc; + +static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */ + +static int ibuffer_space PARAMS((void)); +static int rl_get_char PARAMS((int *)); +static int rl_gather_tyi PARAMS((void)); + +/* **************************************************************** */ +/* */ +/* Character Input Buffering */ +/* */ +/* **************************************************************** */ + +static int pop_index, push_index; +static unsigned char ibuffer[512]; +static int ibuffer_len = sizeof (ibuffer) - 1; + +#define any_typein (push_index != pop_index) + +int +_rl_any_typein () +{ + return any_typein; +} + +/* Return the amount of space available in the buffer for stuffing + characters. */ +static int +ibuffer_space () +{ + if (pop_index > push_index) + return (pop_index - push_index - 1); + else + return (ibuffer_len - (push_index - pop_index)); +} + +/* Get a key from the buffer of characters to be read. + Return the key in KEY. + Result is KEY if there was a key, or 0 if there wasn't. */ +static int +rl_get_char (key) + int *key; +{ + if (push_index == pop_index) + return (0); + + *key = ibuffer[pop_index++]; + + if (pop_index >= ibuffer_len) + pop_index = 0; + + return (1); +} + +/* Stuff KEY into the *front* of the input buffer. + Returns non-zero if successful, zero if there is + no space left in the buffer. */ +int +_rl_unget_char (key) + int key; +{ + if (ibuffer_space ()) + { + pop_index--; + if (pop_index < 0) + pop_index = ibuffer_len - 1; + ibuffer[pop_index] = key; + return (1); + } + return (0); +} + +/* If a character is available to be read, then read it and stuff it into + IBUFFER. Otherwise, just return. Returns number of characters read + (0 if none available) and -1 on error (EIO). */ +static int +rl_gather_tyi () +{ + int tty; + register int tem, result; + int chars_avail; + char input; +#if defined(HAVE_SELECT) + fd_set readfds, exceptfds; + struct timeval timeout; +#endif + + tty = fileno (rl_instream); + +#if defined (HAVE_SELECT) + FD_ZERO (&readfds); + FD_ZERO (&exceptfds); + FD_SET (tty, &readfds); + FD_SET (tty, &exceptfds); + timeout.tv_sec = 0; + timeout.tv_usec = _keyboard_input_timeout; + result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout); + if (result <= 0) + return 0; /* Nothing to read. */ +#endif + + result = -1; +#if defined (FIONREAD) + errno = 0; + result = ioctl (tty, FIONREAD, &chars_avail); + if (result == -1 && errno == EIO) + return -1; +#endif + +#if defined (O_NDELAY) + if (result == -1) + { + tem = fcntl (tty, F_GETFL, 0); + + fcntl (tty, F_SETFL, (tem | O_NDELAY)); + chars_avail = read (tty, &input, 1); + + fcntl (tty, F_SETFL, tem); + if (chars_avail == -1 && errno == EAGAIN) + return 0; + } +#endif /* O_NDELAY */ + + /* If there's nothing available, don't waste time trying to read + something. */ + if (chars_avail <= 0) + return 0; + + tem = ibuffer_space (); + + if (chars_avail > tem) + chars_avail = tem; + + /* One cannot read all of the available input. I can only read a single + character at a time, or else programs which require input can be + thwarted. If the buffer is larger than one character, I lose. + Damn! */ + if (tem < ibuffer_len) + chars_avail = 0; + + if (result != -1) + { + while (chars_avail--) + rl_stuff_char ((*rl_getc_function) (rl_instream)); + } + else + { + if (chars_avail) + rl_stuff_char (input); + } + + return 1; +} + +int +rl_set_keyboard_input_timeout (u) + int u; +{ + int o; + + o = _keyboard_input_timeout; + if (u > 0) + _keyboard_input_timeout = u; + return (o); +} + +/* Is there input available to be read on the readline input file + descriptor? Only works if the system has select(2) or FIONREAD. + Uses the value of _keyboard_input_timeout as the timeout; if another + readline function wants to specify a timeout and not leave it up to + the user, it should use _rl_input_queued(timeout_value_in_microseconds) + instead. */ +int +_rl_input_available () +{ +#if defined(HAVE_SELECT) + fd_set readfds, exceptfds; + struct timeval timeout; +#endif +#if !defined (HAVE_SELECT) && defined(FIONREAD) + int chars_avail; +#endif + int tty; + + tty = fileno (rl_instream); + +#if defined (HAVE_SELECT) + FD_ZERO (&readfds); + FD_ZERO (&exceptfds); + FD_SET (tty, &readfds); + FD_SET (tty, &exceptfds); + timeout.tv_sec = 0; + timeout.tv_usec = _keyboard_input_timeout; + return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0); +#else + +#if defined (FIONREAD) + if (ioctl (tty, FIONREAD, &chars_avail) == 0) + return (chars_avail); +#endif + +#endif + + return 0; +} + +int +_rl_input_queued (t) + int t; +{ + int old_timeout, r; + + old_timeout = rl_set_keyboard_input_timeout (t); + r = _rl_input_available (); + rl_set_keyboard_input_timeout (old_timeout); + return r; +} + +void +_rl_insert_typein (c) + int c; +{ + int key, t, i; + char *string; + + i = key = 0; + string = (char *)xmalloc (ibuffer_len + 1); + string[i++] = (char) c; + + while ((t = rl_get_char (&key)) && + _rl_keymap[key].type == ISFUNC && + _rl_keymap[key].function == rl_insert) + string[i++] = key; + + if (t) + _rl_unget_char (key); + + string[i] = '\0'; + rl_insert_text (string); + free (string); +} + +/* Add KEY to the buffer of characters to be read. Returns 1 if the + character was stuffed correctly; 0 otherwise. */ +int +rl_stuff_char (key) + int key; +{ + if (ibuffer_space () == 0) + return 0; + + if (key == EOF) + { + key = NEWLINE; + rl_pending_input = EOF; + RL_SETSTATE (RL_STATE_INPUTPENDING); + } + ibuffer[push_index++] = key; + if (push_index >= ibuffer_len) + push_index = 0; + + return 1; +} + +/* Make C be the next command to be executed. */ +int +rl_execute_next (c) + int c; +{ + rl_pending_input = c; + RL_SETSTATE (RL_STATE_INPUTPENDING); + return 0; +} + +/* Clear any pending input pushed with rl_execute_next() */ +int +rl_clear_pending_input () +{ + rl_pending_input = 0; + RL_UNSETSTATE (RL_STATE_INPUTPENDING); + return 0; +} + +/* **************************************************************** */ +/* */ +/* Character Input */ +/* */ +/* **************************************************************** */ + +/* Read a key, including pending input. */ +int +rl_read_key () +{ + int c; + + rl_key_sequence_length++; + + if (rl_pending_input) + { + c = rl_pending_input; + rl_clear_pending_input (); + } + else + { + /* If input is coming from a macro, then use that. */ + if (c = _rl_next_macro_key ()) + return (c); + + /* If the user has an event function, then call it periodically. */ + if (rl_event_hook) + { + while (rl_event_hook && rl_get_char (&c) == 0) + { + (*rl_event_hook) (); + if (rl_done) /* XXX - experimental */ + return ('\n'); + if (rl_gather_tyi () < 0) /* XXX - EIO */ + { + rl_done = 1; + return ('\n'); + } + } + } + else + { + if (rl_get_char (&c) == 0) + c = (*rl_getc_function) (rl_instream); + } + } + + return (c); +} + +int +rl_getc (stream) + FILE *stream; +{ + int result; + unsigned char c; + + while (1) + { + result = read (fileno (stream), &c, sizeof (unsigned char)); + + if (result == sizeof (unsigned char)) + return (c); + + /* If zero characters are returned, then the file that we are + reading from is empty! Return EOF in that case. */ + if (result == 0) + return (EOF); + +#if defined (__BEOS__) + if (errno == EINTR) + continue; +#endif + +#if defined (EWOULDBLOCK) +# define X_EWOULDBLOCK EWOULDBLOCK +#else +# define X_EWOULDBLOCK -99 +#endif + +#if defined (EAGAIN) +# define X_EAGAIN EAGAIN +#else +# define X_EAGAIN -99 +#endif + + if (errno == X_EWOULDBLOCK || errno == X_EAGAIN) + { + if (sh_unset_nodelay_mode (fileno (stream)) < 0) + return (EOF); + continue; + } + +#undef X_EWOULDBLOCK +#undef X_EAGAIN + + /* If the error that we received was SIGINT, then try again, + this is simply an interrupted system call to read (). + Otherwise, some error ocurred, also signifying EOF. */ + if (errno != EINTR) + return (EOF); + } +} + +#if defined (HANDLE_MULTIBYTE) +/* read multibyte char */ +int +_rl_read_mbchar (mbchar, size) + char *mbchar; + int size; +{ + int mb_len = 0; + size_t mbchar_bytes_length; + wchar_t wc; + mbstate_t ps, ps_back; + + memset(&ps, 0, sizeof (mbstate_t)); + memset(&ps_back, 0, sizeof (mbstate_t)); + + while (mb_len < size) + { + RL_SETSTATE(RL_STATE_MOREINPUT); + mbchar[mb_len++] = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps); + if (mbchar_bytes_length == (size_t)(-1)) + break; /* invalid byte sequence for the current locale */ + else if (mbchar_bytes_length == (size_t)(-2)) + { + /* shorted bytes */ + ps = ps_back; + continue; + } + else if (mbchar_bytes_length > (size_t)(0)) + break; + } + + return mb_len; +} + +/* Read a multibyte-character string whose first character is FIRST into + the buffer MB of length MBLEN. Returns the last character read, which + may be FIRST. Used by the search functions, among others. Very similar + to _rl_read_mbchar. */ +int +_rl_read_mbstring (first, mb, mblen) + int first; + char *mb; + int mblen; +{ + int i, c; + mbstate_t ps; + + c = first; + memset (mb, 0, mblen); + for (i = 0; i < mblen; i++) + { + mb[i] = (char)c; + memset (&ps, 0, sizeof (mbstate_t)); + if (_rl_get_char_len (mb, &ps) == -2) + { + /* Read more for multibyte character */ + RL_SETSTATE (RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE (RL_STATE_MOREINPUT); + } + else + break; + } + return c; +} +#endif /* HANDLE_MULTIBYTE */ diff --git a/readline/readline-4.3/isearch.c b/readline/readline-4.3/isearch.c new file mode 100644 index 00000000..c1ea5b30 --- /dev/null +++ b/readline/readline-4.3/isearch.c @@ -0,0 +1,560 @@ +/* **************************************************************** */ +/* */ +/* I-Search and Searching */ +/* */ +/* **************************************************************** */ + +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif + +#include "rldefs.h" +#include "rlmbutil.h" + +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +/* Variables exported to other files in the readline library. */ +char *_rl_isearch_terminators = (char *)NULL; + +/* Variables imported from other files in the readline library. */ +extern HIST_ENTRY *_rl_saved_line_for_history; + +/* Forward declarations */ +static int rl_search_history PARAMS((int, int)); + +/* Last line found by the current incremental search, so we don't `find' + identical lines many times in a row. */ +static char *prev_line_found; + +/* Last search string and its length. */ +static char *last_isearch_string; +static int last_isearch_string_len; + +static char *default_isearch_terminators = "\033\012"; + +/* Search backwards through the history looking for a string which is typed + interactively. Start with the current line. */ +int +rl_reverse_search_history (sign, key) + int sign, key; +{ + return (rl_search_history (-sign, key)); +} + +/* Search forwards through the history looking for a string which is typed + interactively. Start with the current line. */ +int +rl_forward_search_history (sign, key) + int sign, key; +{ + return (rl_search_history (sign, key)); +} + +/* Display the current state of the search in the echo-area. + SEARCH_STRING contains the string that is being searched for, + DIRECTION is zero for forward, or 1 for reverse, + WHERE is the history list number of the current line. If it is + -1, then this line is the starting one. */ +static void +rl_display_search (search_string, reverse_p, where) + char *search_string; + int reverse_p, where; +{ + char *message; + int msglen, searchlen; + + searchlen = (search_string && *search_string) ? strlen (search_string) : 0; + + message = (char *)xmalloc (searchlen + 33); + msglen = 0; + +#if defined (NOTDEF) + if (where != -1) + { + sprintf (message, "[%d]", where + history_base); + msglen = strlen (message); + } +#endif /* NOTDEF */ + + message[msglen++] = '('; + + if (reverse_p) + { + strcpy (message + msglen, "reverse-"); + msglen += 8; + } + + strcpy (message + msglen, "i-search)`"); + msglen += 10; + + if (search_string) + { + strcpy (message + msglen, search_string); + msglen += searchlen; + } + + strcpy (message + msglen, "': "); + + rl_message ("%s", message); + free (message); + (*rl_redisplay_function) (); +} + +/* Search through the history looking for an interactively typed string. + This is analogous to i-search. We start the search in the current line. + DIRECTION is which direction to search; >= 0 means forward, < 0 means + backwards. */ +static int +rl_search_history (direction, invoking_key) + int direction, invoking_key; +{ + /* The string that the user types in to search for. */ + char *search_string; + + /* The current length of SEARCH_STRING. */ + int search_string_index; + + /* The amount of space that SEARCH_STRING has allocated to it. */ + int search_string_size; + + /* The list of lines to search through. */ + char **lines, *allocated_line; + + /* The length of LINES. */ + int hlen; + + /* Where we get LINES from. */ + HIST_ENTRY **hlist; + + register int i; + int orig_point, orig_mark, orig_line, last_found_line; + int c, found, failed, sline_len; + int n, wstart, wlen; +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; +#endif + + /* The line currently being searched. */ + char *sline; + + /* Offset in that line. */ + int line_index; + + /* Non-zero if we are doing a reverse search. */ + int reverse; + + /* The list of characters which terminate the search, but are not + subsequently executed. If the variable isearch-terminators has + been set, we use that value, otherwise we use ESC and C-J. */ + char *isearch_terminators; + + RL_SETSTATE(RL_STATE_ISEARCH); + orig_point = rl_point; + orig_mark = rl_mark; + last_found_line = orig_line = where_history (); + reverse = direction < 0; + hlist = history_list (); + allocated_line = (char *)NULL; + + isearch_terminators = _rl_isearch_terminators ? _rl_isearch_terminators + : default_isearch_terminators; + + /* Create an arrary of pointers to the lines that we want to search. */ + rl_maybe_replace_line (); + i = 0; + if (hlist) + for (i = 0; hlist[i]; i++); + + /* Allocate space for this many lines, +1 for the current input line, + and remember those lines. */ + lines = (char **)xmalloc ((1 + (hlen = i)) * sizeof (char *)); + for (i = 0; i < hlen; i++) + lines[i] = hlist[i]->line; + + if (_rl_saved_line_for_history) + lines[i] = _rl_saved_line_for_history->line; + else + { + /* Keep track of this so we can free it. */ + allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer)); + strcpy (allocated_line, &rl_line_buffer[0]); + lines[i] = allocated_line; + } + + hlen++; + + /* The line where we start the search. */ + i = orig_line; + + rl_save_prompt (); + + /* Initialize search parameters. */ + search_string = (char *)xmalloc (search_string_size = 128); + *search_string = '\0'; + search_string_index = 0; + prev_line_found = (char *)0; /* XXX */ + + /* Normalize DIRECTION into 1 or -1. */ + direction = (direction >= 0) ? 1 : -1; + + rl_display_search (search_string, reverse, -1); + + sline = rl_line_buffer; + sline_len = strlen (sline); + line_index = rl_point; + + found = failed = 0; + for (;;) + { + rl_command_func_t *f = (rl_command_func_t *)NULL; + + /* Read a key and decide how to proceed. */ + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + c = _rl_read_mbstring (c, mb, MB_LEN_MAX); +#endif + + /* Translate the keys we do something with to opcodes. */ + if (c >= 0 && _rl_keymap[c].type == ISFUNC) + { + f = _rl_keymap[c].function; + + if (f == rl_reverse_search_history) + c = reverse ? -1 : -2; + else if (f == rl_forward_search_history) + c = !reverse ? -1 : -2; + else if (f == rl_rubout) + c = -3; + else if (c == CTRL ('G')) + c = -4; + else if (c == CTRL ('W')) /* XXX */ + c = -5; + else if (c == CTRL ('Y')) /* XXX */ + c = -6; + } + + /* The characters in isearch_terminators (set from the user-settable + variable isearch-terminators) are used to terminate the search but + not subsequently execute the character as a command. The default + value is "\033\012" (ESC and C-J). */ + if (strchr (isearch_terminators, c)) + { + /* ESC still terminates the search, but if there is pending + input or if input arrives within 0.1 seconds (on systems + with select(2)) it is used as a prefix character + with rl_execute_next. WATCH OUT FOR THIS! This is intended + to allow the arrow keys to be used like ^F and ^B are used + to terminate the search and execute the movement command. + XXX - since _rl_input_available depends on the application- + settable keyboard timeout value, this could alternatively + use _rl_input_queued(100000) */ + if (c == ESC && _rl_input_available ()) + rl_execute_next (ESC); + break; + } + +#define ENDSRCH_CHAR(c) \ + ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G'))) + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + if (c >= 0 && strlen (mb) == 1 && ENDSRCH_CHAR (c)) + { + /* This sets rl_pending_input to c; it will be picked up the next + time rl_read_key is called. */ + rl_execute_next (c); + break; + } + } + else +#endif + if (c >= 0 && ENDSRCH_CHAR (c)) + { + /* This sets rl_pending_input to c; it will be picked up the next + time rl_read_key is called. */ + rl_execute_next (c); + break; + } + + switch (c) + { + case -1: + if (search_string_index == 0) + { + if (last_isearch_string) + { + search_string_size = 64 + last_isearch_string_len; + search_string = (char *)xrealloc (search_string, search_string_size); + strcpy (search_string, last_isearch_string); + search_string_index = last_isearch_string_len; + rl_display_search (search_string, reverse, -1); + break; + } + continue; + } + else if (reverse) + --line_index; + else if (line_index != sline_len) + ++line_index; + else + rl_ding (); + break; + + /* switch directions */ + case -2: + direction = -direction; + reverse = direction < 0; + break; + + /* delete character from search string. */ + case -3: /* C-H, DEL */ + /* This is tricky. To do this right, we need to keep a + stack of search positions for the current search, with + sentinels marking the beginning and end. But this will + do until we have a real isearch-undo. */ + if (search_string_index == 0) + rl_ding (); + else + search_string[--search_string_index] = '\0'; + + break; + + case -4: /* C-G */ + rl_replace_line (lines[orig_line], 0); + rl_point = orig_point; + rl_mark = orig_mark; + rl_restore_prompt(); + rl_clear_message (); + if (allocated_line) + free (allocated_line); + free (lines); + RL_UNSETSTATE(RL_STATE_ISEARCH); + return 0; + + case -5: /* C-W */ + /* skip over portion of line we already matched */ + wstart = rl_point + search_string_index; + if (wstart >= rl_end) + { + rl_ding (); + break; + } + + /* if not in a word, move to one. */ + if (rl_alphabetic(rl_line_buffer[wstart]) == 0) + { + rl_ding (); + break; + } + n = wstart; + while (n < rl_end && rl_alphabetic(rl_line_buffer[n])) + n++; + wlen = n - wstart + 1; + if (search_string_index + wlen + 1 >= search_string_size) + { + search_string_size += wlen + 1; + search_string = (char *)xrealloc (search_string, search_string_size); + } + for (; wstart < n; wstart++) + search_string[search_string_index++] = rl_line_buffer[wstart]; + search_string[search_string_index] = '\0'; + break; + + case -6: /* C-Y */ + /* skip over portion of line we already matched */ + wstart = rl_point + search_string_index; + if (wstart >= rl_end) + { + rl_ding (); + break; + } + n = rl_end - wstart + 1; + if (search_string_index + n + 1 >= search_string_size) + { + search_string_size += n + 1; + search_string = (char *)xrealloc (search_string, search_string_size); + } + for (n = wstart; n < rl_end; n++) + search_string[search_string_index++] = rl_line_buffer[n]; + search_string[search_string_index] = '\0'; + break; + + default: + /* Add character to search string and continue search. */ + if (search_string_index + 2 >= search_string_size) + { + search_string_size += 128; + search_string = (char *)xrealloc (search_string, search_string_size); + } +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int j, l; + for (j = 0, l = strlen (mb); j < l; ) + search_string[search_string_index++] = mb[j++]; + } + else +#endif + search_string[search_string_index++] = c; + search_string[search_string_index] = '\0'; + break; + } + + for (found = failed = 0;;) + { + int limit = sline_len - search_string_index + 1; + + /* Search the current line. */ + while (reverse ? (line_index >= 0) : (line_index < limit)) + { + if (STREQN (search_string, sline + line_index, search_string_index)) + { + found++; + break; + } + else + line_index += direction; + } + if (found) + break; + + /* Move to the next line, but skip new copies of the line + we just found and lines shorter than the string we're + searching for. */ + do + { + /* Move to the next line. */ + i += direction; + + /* At limit for direction? */ + if (reverse ? (i < 0) : (i == hlen)) + { + failed++; + break; + } + + /* We will need these later. */ + sline = lines[i]; + sline_len = strlen (sline); + } + while ((prev_line_found && STREQ (prev_line_found, lines[i])) || + (search_string_index > sline_len)); + + if (failed) + break; + + /* Now set up the line for searching... */ + line_index = reverse ? sline_len - search_string_index : 0; + } + + if (failed) + { + /* We cannot find the search string. Ding the bell. */ + rl_ding (); + i = last_found_line; + continue; /* XXX - was break */ + } + + /* We have found the search string. Just display it. But don't + actually move there in the history list until the user accepts + the location. */ + if (found) + { + prev_line_found = lines[i]; + rl_replace_line (lines[i], 0); + rl_point = line_index; + last_found_line = i; + rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i); + } + } + + /* The searching is over. The user may have found the string that she + was looking for, or else she may have exited a failing search. If + LINE_INDEX is -1, then that shows that the string searched for was + not found. We use this to determine where to place rl_point. */ + + /* First put back the original state. */ + strcpy (rl_line_buffer, lines[orig_line]); + + rl_restore_prompt (); + + /* Save the search string for possible later use. */ + FREE (last_isearch_string); + last_isearch_string = search_string; + last_isearch_string_len = search_string_index; + + if (last_found_line < orig_line) + rl_get_previous_history (orig_line - last_found_line, 0); + else + rl_get_next_history (last_found_line - orig_line, 0); + + /* If the string was not found, put point at the end of the last matching + line. If last_found_line == orig_line, we didn't find any matching + history lines at all, so put point back in its original position. */ + if (line_index < 0) + { + if (last_found_line == orig_line) + line_index = orig_point; + else + line_index = strlen (rl_line_buffer); + rl_mark = orig_mark; + } + + rl_point = line_index; + /* Don't worry about where to put the mark here; rl_get_previous_history + and rl_get_next_history take care of it. */ + + rl_clear_message (); + + FREE (allocated_line); + free (lines); + + RL_UNSETSTATE(RL_STATE_ISEARCH); + + return 0; +} diff --git a/readline/readline-4.3/keymaps.c b/readline/readline-4.3/keymaps.c new file mode 100644 index 00000000..12506d3a --- /dev/null +++ b/readline/readline-4.3/keymaps.c @@ -0,0 +1,150 @@ +/* keymaps.c -- Functions and keymaps for the GNU Readline library. */ + +/* Copyright (C) 1988,1989 Free Software Foundation, Inc. + + This file is part of GNU Readline, a library for reading lines + of text with interactive input and history editing. + + Readline is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + Readline is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Readline; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include /* for FILE * definition for readline.h */ + +#include "readline.h" +#include "rlconf.h" + +#include "emacs_keymap.c" + +#if defined (VI_MODE) +#include "vi_keymap.c" +#endif + +#include "xmalloc.h" + +/* **************************************************************** */ +/* */ +/* Functions for manipulating Keymaps. */ +/* */ +/* **************************************************************** */ + + +/* Return a new, empty keymap. + Free it with free() when you are done. */ +Keymap +rl_make_bare_keymap () +{ + register int i; + Keymap keymap = (Keymap)xmalloc (KEYMAP_SIZE * sizeof (KEYMAP_ENTRY)); + + for (i = 0; i < KEYMAP_SIZE; i++) + { + keymap[i].type = ISFUNC; + keymap[i].function = (rl_command_func_t *)NULL; + } + + for (i = 'A'; i < ('Z' + 1); i++) + { + keymap[i].type = ISFUNC; + keymap[i].function = rl_do_lowercase_version; + } + + return (keymap); +} + +/* Return a new keymap which is a copy of MAP. */ +Keymap +rl_copy_keymap (map) + Keymap map; +{ + register int i; + Keymap temp = rl_make_bare_keymap (); + + for (i = 0; i < KEYMAP_SIZE; i++) + { + temp[i].type = map[i].type; + temp[i].function = map[i].function; + } + return (temp); +} + +/* Return a new keymap with the printing characters bound to rl_insert, + the uppercase Meta characters bound to run their lowercase equivalents, + and the Meta digits bound to produce numeric arguments. */ +Keymap +rl_make_keymap () +{ + register int i; + Keymap newmap; + + newmap = rl_make_bare_keymap (); + + /* All ASCII printing characters are self-inserting. */ + for (i = ' '; i < 127; i++) + newmap[i].function = rl_insert; + + newmap[TAB].function = rl_insert; + newmap[RUBOUT].function = rl_rubout; /* RUBOUT == 127 */ + newmap[CTRL('H')].function = rl_rubout; + +#if KEYMAP_SIZE > 128 + /* Printing characters in some 8-bit character sets. */ + for (i = 128; i < 160; i++) + newmap[i].function = rl_insert; + + /* ISO Latin-1 printing characters should self-insert. */ + for (i = 160; i < 256; i++) + newmap[i].function = rl_insert; +#endif /* KEYMAP_SIZE > 128 */ + + return (newmap); +} + +/* Free the storage associated with MAP. */ +void +rl_discard_keymap (map) + Keymap map; +{ + int i; + + if (!map) + return; + + for (i = 0; i < KEYMAP_SIZE; i++) + { + switch (map[i].type) + { + case ISFUNC: + break; + + case ISKMAP: + rl_discard_keymap ((Keymap)map[i].function); + break; + + case ISMACR: + free ((char *)map[i].function); + break; + } + } +} diff --git a/readline/readline-4.3/keymaps.h b/readline/readline-4.3/keymaps.h new file mode 100644 index 00000000..66fa2a5e --- /dev/null +++ b/readline/readline-4.3/keymaps.h @@ -0,0 +1,103 @@ +/* keymaps.h -- Manipulation of readline keymaps. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#ifndef _KEYMAPS_H_ +#define _KEYMAPS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (READLINE_LIBRARY) +# include "rlstdc.h" +# include "chardefs.h" +# include "rltypedefs.h" +#else +# include +# include +# include +#endif + +/* A keymap contains one entry for each key in the ASCII set. + Each entry consists of a type and a pointer. + FUNCTION is the address of a function to run, or the + address of a keymap to indirect through. + TYPE says which kind of thing FUNCTION is. */ +typedef struct _keymap_entry { + char type; + rl_command_func_t *function; +} KEYMAP_ENTRY; + +/* This must be large enough to hold bindings for all of the characters + in a desired character set (e.g, 128 for ASCII, 256 for ISO Latin-x, + and so on) plus one for subsequence matching. */ +#define KEYMAP_SIZE 257 +#define ANYOTHERKEY KEYMAP_SIZE-1 + +/* I wanted to make the above structure contain a union of: + union { rl_command_func_t *function; struct _keymap_entry *keymap; } value; + but this made it impossible for me to create a static array. + Maybe I need C lessons. */ + +typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE]; +typedef KEYMAP_ENTRY *Keymap; + +/* The values that TYPE can have in a keymap entry. */ +#define ISFUNC 0 +#define ISKMAP 1 +#define ISMACR 2 + +extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap; +extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap; + +/* Return a new, empty keymap. + Free it with free() when you are done. */ +extern Keymap rl_make_bare_keymap PARAMS((void)); + +/* Return a new keymap which is a copy of MAP. */ +extern Keymap rl_copy_keymap PARAMS((Keymap)); + +/* Return a new keymap with the printing characters bound to rl_insert, + the lowercase Meta characters bound to run their equivalents, and + the Meta digits bound to produce numeric arguments. */ +extern Keymap rl_make_keymap PARAMS((void)); + +/* Free the storage associated with a keymap. */ +extern void rl_discard_keymap PARAMS((Keymap)); + +/* These functions actually appear in bind.c */ + +/* Return the keymap corresponding to a given name. Names look like + `emacs' or `emacs-meta' or `vi-insert'. */ +extern Keymap rl_get_keymap_by_name PARAMS((const char *)); + +/* Return the current keymap. */ +extern Keymap rl_get_keymap PARAMS((void)); + +/* Set the current keymap to MAP. */ +extern void rl_set_keymap PARAMS((Keymap)); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYMAPS_H_ */ diff --git a/readline/readline-4.3/kill.c b/readline/readline-4.3/kill.c new file mode 100644 index 00000000..a616b920 --- /dev/null +++ b/readline/readline-4.3/kill.c @@ -0,0 +1,652 @@ +/* kill.c -- kill ring management. */ + +/* Copyright (C) 1994 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_UNISTD_H) +# include /* for _POSIX_VERSION */ +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +/* **************************************************************** */ +/* */ +/* Killing Mechanism */ +/* */ +/* **************************************************************** */ + +/* What we assume for a max number of kills. */ +#define DEFAULT_MAX_KILLS 10 + +/* The real variable to look at to find out when to flush kills. */ +static int rl_max_kills = DEFAULT_MAX_KILLS; + +/* Where to store killed text. */ +static char **rl_kill_ring = (char **)NULL; + +/* Where we are in the kill ring. */ +static int rl_kill_index; + +/* How many slots we have in the kill ring. */ +static int rl_kill_ring_length; + +static int _rl_copy_to_kill_ring PARAMS((char *, int)); +static int region_kill_internal PARAMS((int)); +static int _rl_copy_word_as_kill PARAMS((int, int)); +static int rl_yank_nth_arg_internal PARAMS((int, int, int)); + +/* How to say that you only want to save a certain amount + of kill material. */ +int +rl_set_retained_kills (num) + int num; +{ + return 0; +} + +/* Add TEXT to the kill ring, allocating a new kill ring slot as necessary. + This uses TEXT directly, so the caller must not free it. If APPEND is + non-zero, and the last command was a kill, the text is appended to the + current kill ring slot, otherwise prepended. */ +static int +_rl_copy_to_kill_ring (text, append) + char *text; + int append; +{ + char *old, *new; + int slot; + + /* First, find the slot to work with. */ + if (_rl_last_command_was_kill == 0) + { + /* Get a new slot. */ + if (rl_kill_ring == 0) + { + /* If we don't have any defined, then make one. */ + rl_kill_ring = (char **) + xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *)); + rl_kill_ring[slot = 0] = (char *)NULL; + } + else + { + /* We have to add a new slot on the end, unless we have + exceeded the max limit for remembering kills. */ + slot = rl_kill_ring_length; + if (slot == rl_max_kills) + { + register int i; + free (rl_kill_ring[0]); + for (i = 0; i < slot; i++) + rl_kill_ring[i] = rl_kill_ring[i + 1]; + } + else + { + slot = rl_kill_ring_length += 1; + rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *)); + } + rl_kill_ring[--slot] = (char *)NULL; + } + } + else + slot = rl_kill_ring_length - 1; + + /* If the last command was a kill, prepend or append. */ + if (_rl_last_command_was_kill && rl_editing_mode != vi_mode) + { + old = rl_kill_ring[slot]; + new = (char *)xmalloc (1 + strlen (old) + strlen (text)); + + if (append) + { + strcpy (new, old); + strcat (new, text); + } + else + { + strcpy (new, text); + strcat (new, old); + } + free (old); + free (text); + rl_kill_ring[slot] = new; + } + else + rl_kill_ring[slot] = text; + + rl_kill_index = slot; + return 0; +} + +/* The way to kill something. This appends or prepends to the last + kill, if the last command was a kill command. if FROM is less + than TO, then the text is appended, otherwise prepended. If the + last command was not a kill command, then a new slot is made for + this kill. */ +int +rl_kill_text (from, to) + int from, to; +{ + char *text; + + /* Is there anything to kill? */ + if (from == to) + { + _rl_last_command_was_kill++; + return 0; + } + + text = rl_copy_text (from, to); + + /* Delete the copied text from the line. */ + rl_delete_text (from, to); + + _rl_copy_to_kill_ring (text, from < to); + + _rl_last_command_was_kill++; + return 0; +} + +/* Now REMEMBER! In order to do prepending or appending correctly, kill + commands always make rl_point's original position be the FROM argument, + and rl_point's extent be the TO argument. */ + +/* **************************************************************** */ +/* */ +/* Killing Commands */ +/* */ +/* **************************************************************** */ + +/* Delete the word at point, saving the text in the kill ring. */ +int +rl_kill_word (count, key) + int count, key; +{ + int orig_point; + + if (count < 0) + return (rl_backward_kill_word (-count, key)); + else + { + orig_point = rl_point; + rl_forward_word (count, key); + + if (rl_point != orig_point) + rl_kill_text (orig_point, rl_point); + + rl_point = orig_point; + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; + } + return 0; +} + +/* Rubout the word before point, placing it on the kill ring. */ +int +rl_backward_kill_word (count, ignore) + int count, ignore; +{ + int orig_point; + + if (count < 0) + return (rl_kill_word (-count, ignore)); + else + { + orig_point = rl_point; + rl_backward_word (count, ignore); + + if (rl_point != orig_point) + rl_kill_text (orig_point, rl_point); + + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; + } + return 0; +} + +/* Kill from here to the end of the line. If DIRECTION is negative, kill + back to the line start instead. */ +int +rl_kill_line (direction, ignore) + int direction, ignore; +{ + int orig_point; + + if (direction < 0) + return (rl_backward_kill_line (1, ignore)); + else + { + orig_point = rl_point; + rl_end_of_line (1, ignore); + if (orig_point != rl_point) + rl_kill_text (orig_point, rl_point); + rl_point = orig_point; + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; + } + return 0; +} + +/* Kill backwards to the start of the line. If DIRECTION is negative, kill + forwards to the line end instead. */ +int +rl_backward_kill_line (direction, ignore) + int direction, ignore; +{ + int orig_point; + + if (direction < 0) + return (rl_kill_line (1, ignore)); + else + { + if (!rl_point) + rl_ding (); + else + { + orig_point = rl_point; + rl_beg_of_line (1, ignore); + if (rl_point != orig_point) + rl_kill_text (orig_point, rl_point); + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; + } + } + return 0; +} + +/* Kill the whole line, no matter where point is. */ +int +rl_kill_full_line (count, ignore) + int count, ignore; +{ + rl_begin_undo_group (); + rl_point = 0; + rl_kill_text (rl_point, rl_end); + rl_mark = 0; + rl_end_undo_group (); + return 0; +} + +/* The next two functions mimic unix line editing behaviour, except they + save the deleted text on the kill ring. This is safer than not saving + it, and since we have a ring, nobody should get screwed. */ + +/* This does what C-w does in Unix. We can't prevent people from + using behaviour that they expect. */ +int +rl_unix_word_rubout (count, key) + int count, key; +{ + int orig_point; + + if (rl_point == 0) + rl_ding (); + else + { + orig_point = rl_point; + if (count <= 0) + count = 1; + + while (count--) + { + while (rl_point && whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + while (rl_point && (whitespace (rl_line_buffer[rl_point - 1]) == 0)) + rl_point--; + } + + rl_kill_text (orig_point, rl_point); + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; + } + return 0; +} + +/* Here is C-u doing what Unix does. You don't *have* to use these + key-bindings. We have a choice of killing the entire line, or + killing from where we are to the start of the line. We choose the + latter, because if you are a Unix weenie, then you haven't backspaced + into the line at all, and if you aren't, then you know what you are + doing. */ +int +rl_unix_line_discard (count, key) + int count, key; +{ + if (rl_point == 0) + rl_ding (); + else + { + rl_kill_text (rl_point, 0); + rl_point = 0; + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; + } + return 0; +} + +/* Copy the text in the `region' to the kill ring. If DELETE is non-zero, + delete the text from the line as well. */ +static int +region_kill_internal (delete) + int delete; +{ + char *text; + + if (rl_mark != rl_point) + { + text = rl_copy_text (rl_point, rl_mark); + if (delete) + rl_delete_text (rl_point, rl_mark); + _rl_copy_to_kill_ring (text, rl_point < rl_mark); + } + + _rl_last_command_was_kill++; + return 0; +} + +/* Copy the text in the region to the kill ring. */ +int +rl_copy_region_to_kill (count, ignore) + int count, ignore; +{ + return (region_kill_internal (0)); +} + +/* Kill the text between the point and mark. */ +int +rl_kill_region (count, ignore) + int count, ignore; +{ + int r, npoint; + + npoint = (rl_point < rl_mark) ? rl_point : rl_mark; + r = region_kill_internal (1); + _rl_fix_point (1); + rl_point = npoint; + return r; +} + +/* Copy COUNT words to the kill ring. DIR says which direction we look + to find the words. */ +static int +_rl_copy_word_as_kill (count, dir) + int count, dir; +{ + int om, op, r; + + om = rl_mark; + op = rl_point; + + if (dir > 0) + rl_forward_word (count, 0); + else + rl_backward_word (count, 0); + + rl_mark = rl_point; + + if (dir > 0) + rl_backward_word (count, 0); + else + rl_forward_word (count, 0); + + r = region_kill_internal (0); + + rl_mark = om; + rl_point = op; + + return r; +} + +int +rl_copy_forward_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_copy_backward_word (-count, key)); + + return (_rl_copy_word_as_kill (count, 1)); +} + +int +rl_copy_backward_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_copy_forward_word (-count, key)); + + return (_rl_copy_word_as_kill (count, -1)); +} + +/* Yank back the last killed text. This ignores arguments. */ +int +rl_yank (count, ignore) + int count, ignore; +{ + if (rl_kill_ring == 0) + { + _rl_abort_internal (); + return -1; + } + + _rl_set_mark_at_pos (rl_point); + rl_insert_text (rl_kill_ring[rl_kill_index]); + return 0; +} + +/* If the last command was yank, or yank_pop, and the text just + before point is identical to the current kill item, then + delete that text from the line, rotate the index down, and + yank back some other text. */ +int +rl_yank_pop (count, key) + int count, key; +{ + int l, n; + + if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) || + !rl_kill_ring) + { + _rl_abort_internal (); + return -1; + } + + l = strlen (rl_kill_ring[rl_kill_index]); + n = rl_point - l; + if (n >= 0 && STREQN (rl_line_buffer + n, rl_kill_ring[rl_kill_index], l)) + { + rl_delete_text (n, rl_point); + rl_point = n; + rl_kill_index--; + if (rl_kill_index < 0) + rl_kill_index = rl_kill_ring_length - 1; + rl_yank (1, 0); + return 0; + } + else + { + _rl_abort_internal (); + return -1; + } +} + +/* Yank the COUNTh argument from the previous history line, skipping + HISTORY_SKIP lines before looking for the `previous line'. */ +static int +rl_yank_nth_arg_internal (count, ignore, history_skip) + int count, ignore, history_skip; +{ + register HIST_ENTRY *entry; + char *arg; + int i, pos; + + pos = where_history (); + + if (history_skip) + { + for (i = 0; i < history_skip; i++) + entry = previous_history (); + } + + entry = previous_history (); + + history_set_pos (pos); + + if (entry == 0) + { + rl_ding (); + return -1; + } + + arg = history_arg_extract (count, count, entry->line); + if (!arg || !*arg) + { + rl_ding (); + return -1; + } + + rl_begin_undo_group (); + + _rl_set_mark_at_pos (rl_point); + +#if defined (VI_MODE) + /* Vi mode always inserts a space before yanking the argument, and it + inserts it right *after* rl_point. */ + if (rl_editing_mode == vi_mode) + { + rl_vi_append_mode (1, ignore); + rl_insert_text (" "); + } +#endif /* VI_MODE */ + + rl_insert_text (arg); + free (arg); + + rl_end_undo_group (); + return 0; +} + +/* Yank the COUNTth argument from the previous history line. */ +int +rl_yank_nth_arg (count, ignore) + int count, ignore; +{ + return (rl_yank_nth_arg_internal (count, ignore, 0)); +} + +/* Yank the last argument from the previous history line. This `knows' + how rl_yank_nth_arg treats a count of `$'. With an argument, this + behaves the same as rl_yank_nth_arg. */ +int +rl_yank_last_arg (count, key) + int count, key; +{ + static int history_skip = 0; + static int explicit_arg_p = 0; + static int count_passed = 1; + static int direction = 1; + static int undo_needed = 0; + int retval; + + if (rl_last_func != rl_yank_last_arg) + { + history_skip = 0; + explicit_arg_p = rl_explicit_arg; + count_passed = count; + direction = 1; + } + else + { + if (undo_needed) + rl_do_undo (); + if (count < 1) + direction = -direction; + history_skip += direction; + if (history_skip < 0) + history_skip = 0; + } + + if (explicit_arg_p) + retval = rl_yank_nth_arg_internal (count_passed, key, history_skip); + else + retval = rl_yank_nth_arg_internal ('$', key, history_skip); + + undo_needed = retval == 0; + return retval; +} + +/* A special paste command for users of Cygnus's cygwin32. */ +#if defined (__CYGWIN__) +#include + +int +rl_paste_from_clipboard (count, key) + int count, key; +{ + char *data, *ptr; + int len; + + if (OpenClipboard (NULL) == 0) + return (0); + + data = (char *)GetClipboardData (CF_TEXT); + if (data) + { + ptr = strchr (data, '\r'); + if (ptr) + { + len = ptr - data; + ptr = (char *)xmalloc (len + 1); + ptr[len] = '\0'; + strncpy (ptr, data, len); + } + else + ptr = data; + _rl_set_mark_at_pos (rl_point); + rl_insert_text (ptr); + if (ptr != data) + free (ptr); + CloseClipboard (); + } + return (0); +} +#endif /* __CYGWIN__ */ diff --git a/readline/readline-4.3/macro.c b/readline/readline-4.3/macro.c new file mode 100644 index 00000000..b73c3af9 --- /dev/null +++ b/readline/readline-4.3/macro.c @@ -0,0 +1,262 @@ +/* macro.c -- keyboard macros for readline. */ + +/* Copyright (C) 1994 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_UNISTD_H) +# include /* for _POSIX_VERSION */ +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +/* **************************************************************** */ +/* */ +/* Hacking Keyboard Macros */ +/* */ +/* **************************************************************** */ + +/* The currently executing macro string. If this is non-zero, + then it is a malloc ()'ed string where input is coming from. */ +char *rl_executing_macro = (char *)NULL; + +/* The offset in the above string to the next character to be read. */ +static int executing_macro_index; + +/* The current macro string being built. Characters get stuffed + in here by add_macro_char (). */ +static char *current_macro = (char *)NULL; + +/* The size of the buffer allocated to current_macro. */ +static int current_macro_size; + +/* The index at which characters are being added to current_macro. */ +static int current_macro_index; + +/* A structure used to save nested macro strings. + It is a linked list of string/index for each saved macro. */ +struct saved_macro { + struct saved_macro *next; + char *string; + int sindex; +}; + +/* The list of saved macros. */ +static struct saved_macro *macro_list = (struct saved_macro *)NULL; + +/* Set up to read subsequent input from STRING. + STRING is free ()'ed when we are done with it. */ +void +_rl_with_macro_input (string) + char *string; +{ + _rl_push_executing_macro (); + rl_executing_macro = string; + executing_macro_index = 0; + RL_SETSTATE(RL_STATE_MACROINPUT); +} + +/* Return the next character available from a macro, or 0 if + there are no macro characters. */ +int +_rl_next_macro_key () +{ + if (rl_executing_macro == 0) + return (0); + + if (rl_executing_macro[executing_macro_index] == 0) + { + _rl_pop_executing_macro (); + return (_rl_next_macro_key ()); + } + + return (rl_executing_macro[executing_macro_index++]); +} + +/* Save the currently executing macro on a stack of saved macros. */ +void +_rl_push_executing_macro () +{ + struct saved_macro *saver; + + saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro)); + saver->next = macro_list; + saver->sindex = executing_macro_index; + saver->string = rl_executing_macro; + + macro_list = saver; +} + +/* Discard the current macro, replacing it with the one + on the top of the stack of saved macros. */ +void +_rl_pop_executing_macro () +{ + struct saved_macro *macro; + + FREE (rl_executing_macro); + rl_executing_macro = (char *)NULL; + executing_macro_index = 0; + + if (macro_list) + { + macro = macro_list; + rl_executing_macro = macro_list->string; + executing_macro_index = macro_list->sindex; + macro_list = macro_list->next; + free (macro); + } + + if (rl_executing_macro == 0) + RL_UNSETSTATE(RL_STATE_MACROINPUT); +} + +/* Add a character to the macro being built. */ +void +_rl_add_macro_char (c) + int c; +{ + if (current_macro_index + 1 >= current_macro_size) + { + if (current_macro == 0) + current_macro = (char *)xmalloc (current_macro_size = 25); + else + current_macro = (char *)xrealloc (current_macro, current_macro_size += 25); + } + + current_macro[current_macro_index++] = c; + current_macro[current_macro_index] = '\0'; +} + +void +_rl_kill_kbd_macro () +{ + if (current_macro) + { + free (current_macro); + current_macro = (char *) NULL; + } + current_macro_size = current_macro_index = 0; + + FREE (rl_executing_macro); + rl_executing_macro = (char *) NULL; + executing_macro_index = 0; + + RL_UNSETSTATE(RL_STATE_MACRODEF); +} + +/* Begin defining a keyboard macro. + Keystrokes are recorded as they are executed. + End the definition with rl_end_kbd_macro (). + If a numeric argument was explicitly typed, then append this + definition to the end of the existing macro, and start by + re-executing the existing macro. */ +int +rl_start_kbd_macro (ignore1, ignore2) + int ignore1, ignore2; +{ + if (RL_ISSTATE (RL_STATE_MACRODEF)) + { + _rl_abort_internal (); + return -1; + } + + if (rl_explicit_arg) + { + if (current_macro) + _rl_with_macro_input (savestring (current_macro)); + } + else + current_macro_index = 0; + + RL_SETSTATE(RL_STATE_MACRODEF); + return 0; +} + +/* Stop defining a keyboard macro. + A numeric argument says to execute the macro right now, + that many times, counting the definition as the first time. */ +int +rl_end_kbd_macro (count, ignore) + int count, ignore; +{ + if (RL_ISSTATE (RL_STATE_MACRODEF) == 0) + { + _rl_abort_internal (); + return -1; + } + + current_macro_index -= rl_key_sequence_length - 1; + current_macro[current_macro_index] = '\0'; + + RL_UNSETSTATE(RL_STATE_MACRODEF); + + return (rl_call_last_kbd_macro (--count, 0)); +} + +/* Execute the most recently defined keyboard macro. + COUNT says how many times to execute it. */ +int +rl_call_last_kbd_macro (count, ignore) + int count, ignore; +{ + if (current_macro == 0) + _rl_abort_internal (); + + if (RL_ISSTATE (RL_STATE_MACRODEF)) + { + rl_ding (); /* no recursive macros */ + current_macro[--current_macro_index] = '\0'; /* erase this char */ + return 0; + } + + while (count--) + _rl_with_macro_input (savestring (current_macro)); + return 0; +} + +void +rl_push_macro_input (macro) + char *macro; +{ + _rl_with_macro_input (macro); +} diff --git a/readline/readline-4.3/mbutil.c b/readline/readline-4.3/mbutil.c new file mode 100644 index 00000000..8794d02d --- /dev/null +++ b/readline/readline-4.3/mbutil.c @@ -0,0 +1,345 @@ +/* mbutil.c -- readline multibyte character utility functions */ + +/* Copyright (C) 2001 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include +#include "posixjmp.h" + +#if defined (HAVE_UNISTD_H) +# include /* for _POSIX_VERSION */ +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#if defined (TIOCSTAT_IN_SYS_IOCTL) +# include +#endif /* TIOCSTAT_IN_SYS_IOCTL */ + +/* Some standard library routines. */ +#include "readline.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +/* Declared here so it can be shared between the readline and history + libraries. */ +#if defined (HANDLE_MULTIBYTE) +int rl_byte_oriented = 0; +#else +int rl_byte_oriented = 1; +#endif + +/* **************************************************************** */ +/* */ +/* Multibyte Character Utility Functions */ +/* */ +/* **************************************************************** */ + +#if defined(HANDLE_MULTIBYTE) + +static int +_rl_find_next_mbchar_internal (string, seed, count, find_non_zero) + char *string; + int seed, count, find_non_zero; +{ + size_t tmp = 0; + mbstate_t ps; + int point = 0; + wchar_t wc; + + memset(&ps, 0, sizeof (mbstate_t)); + if (seed < 0) + seed = 0; + if (count <= 0) + return seed; + + point = seed + _rl_adjust_point(string, seed, &ps); + /* if this is true, means that seed was not pointed character + started byte. So correct the point and consume count */ + if (seed < point) + count --; + + while (count > 0) + { + tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps); + if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2) + { + /* invalid bytes. asume a byte represents a character */ + point++; + count--; + /* reset states. */ + memset(&ps, 0, sizeof(mbstate_t)); + } + else if (tmp == (size_t)0) + /* found '\0' char */ + break; + else + { + /* valid bytes */ + point += tmp; + if (find_non_zero) + { + if (wcwidth (wc) == 0) + continue; + else + count--; + } + else + count--; + } + } + + if (find_non_zero) + { + tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps); + while (wcwidth (wc) == 0) + { + point += tmp; + tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps); + if (tmp == (size_t)(0) || tmp == (size_t)(-1) || tmp == (size_t)(-2)) + break; + } + } + return point; +} + +static int +_rl_find_prev_mbchar_internal (string, seed, find_non_zero) + char *string; + int seed, find_non_zero; +{ + mbstate_t ps; + int prev, non_zero_prev, point, length; + size_t tmp; + wchar_t wc; + + memset(&ps, 0, sizeof(mbstate_t)); + length = strlen(string); + + if (seed < 0) + return 0; + else if (length < seed) + return length; + + prev = non_zero_prev = point = 0; + while (point < seed) + { + tmp = mbrtowc (&wc, string + point, length - point, &ps); + if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2) + { + /* in this case, bytes are invalid or shorted to compose + multibyte char, so assume that the first byte represents + a single character anyway. */ + tmp = 1; + /* clear the state of the byte sequence, because + in this case effect of mbstate is undefined */ + memset(&ps, 0, sizeof (mbstate_t)); + } + else if (tmp == 0) + break; /* Found '\0' char. Can this happen? */ + else + { + if (find_non_zero) + { + if (wcwidth (wc) != 0) + prev = point; + } + else + prev = point; + } + + point += tmp; + } + + return prev; +} + +/* return the number of bytes parsed from the multibyte sequence starting + at src, if a non-L'\0' wide character was recognized. It returns 0, + if a L'\0' wide character was recognized. It returns (size_t)(-1), + if an invalid multibyte sequence was encountered. It returns (size_t)(-2) + if it couldn't parse a complete multibyte character. */ +int +_rl_get_char_len (src, ps) + char *src; + mbstate_t *ps; +{ + size_t tmp; + + tmp = mbrlen((const char *)src, (size_t)strlen (src), ps); + if (tmp == (size_t)(-2)) + { + /* shorted to compose multibyte char */ + if (ps) + memset (ps, 0, sizeof(mbstate_t)); + return -2; + } + else if (tmp == (size_t)(-1)) + { + /* invalid to compose multibyte char */ + /* initialize the conversion state */ + if (ps) + memset (ps, 0, sizeof(mbstate_t)); + return -1; + } + else if (tmp == (size_t)0) + return 0; + else + return (int)tmp; +} + +/* compare the specified two characters. If the characters matched, + return 1. Otherwise return 0. */ +int +_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2) + char *buf1; + int pos1; + mbstate_t *ps1; + char *buf2; + int pos2; + mbstate_t *ps2; +{ + int i, w1, w2; + + if ((w1 = _rl_get_char_len (&buf1[pos1], ps1)) <= 0 || + (w2 = _rl_get_char_len (&buf2[pos2], ps2)) <= 0 || + (w1 != w2) || + (buf1[pos1] != buf2[pos2])) + return 0; + + for (i = 1; i < w1; i++) + if (buf1[pos1+i] != buf2[pos2+i]) + return 0; + + return 1; +} + +/* adjust pointed byte and find mbstate of the point of string. + adjusted point will be point <= adjusted_point, and returns + differences of the byte(adjusted_point - point). + if point is invalied (point < 0 || more than string length), + it returns -1 */ +int +_rl_adjust_point(string, point, ps) + char *string; + int point; + mbstate_t *ps; +{ + size_t tmp = 0; + int length; + int pos = 0; + + length = strlen(string); + if (point < 0) + return -1; + if (length < point) + return -1; + + while (pos < point) + { + tmp = mbrlen (string + pos, length - pos, ps); + if((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2) + { + /* in this case, bytes are invalid or shorted to compose + multibyte char, so assume that the first byte represents + a single character anyway. */ + pos++; + /* clear the state of the byte sequence, because + in this case effect of mbstate is undefined */ + if (ps) + memset (ps, 0, sizeof (mbstate_t)); + } + else if (tmp == 0) + pos++; + else + pos += tmp; + } + + return (pos - point); +} + +int +_rl_is_mbchar_matched (string, seed, end, mbchar, length) + char *string; + int seed, end; + char *mbchar; + int length; +{ + int i; + + if ((end - seed) < length) + return 0; + + for (i = 0; i < length; i++) + if (string[seed + i] != mbchar[i]) + return 0; + return 1; +} +#endif /* HANDLE_MULTIBYTE */ + +/* Find next `count' characters started byte point of the specified seed. + If flags is MB_FIND_NONZERO, we look for non-zero-width multibyte + characters. */ +#undef _rl_find_next_mbchar +int +_rl_find_next_mbchar (string, seed, count, flags) + char *string; + int seed, count, flags; +{ +#if defined (HANDLE_MULTIBYTE) + return _rl_find_next_mbchar_internal (string, seed, count, flags); +#else + return (seed + count); +#endif +} + +/* Find previous character started byte point of the specified seed. + Returned point will be point <= seed. If flags is MB_FIND_NONZERO, + we look for non-zero-width multibyte characters. */ +#undef _rl_find_prev_mbchar +int +_rl_find_prev_mbchar (string, seed, flags) + char *string; + int seed, flags; +{ +#if defined (HANDLE_MULTIBYTE) + return _rl_find_prev_mbchar_internal (string, seed, flags); +#else + return ((seed == 0) ? seed : seed - 1); +#endif +} diff --git a/readline/readline-4.3/misc.c b/readline/readline-4.3/misc.c new file mode 100644 index 00000000..f3775d30 --- /dev/null +++ b/readline/readline-4.3/misc.c @@ -0,0 +1,496 @@ +/* misc.c -- miscellaneous bindable readline functions. */ + +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_LOCALE_H) +# include +#endif + +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + +static int rl_digit_loop PARAMS((void)); +static void _rl_history_set_point PARAMS((void)); + +/* Forward declarations used in this file */ +void _rl_free_history_entry PARAMS((HIST_ENTRY *)); + +/* If non-zero, rl_get_previous_history and rl_get_next_history attempt + to preserve the value of rl_point from line to line. */ +int _rl_history_preserve_point = 0; + +/* Saved target point for when _rl_history_preserve_point is set. Special + value of -1 means that point is at the end of the line. */ +int _rl_history_saved_point = -1; + +/* **************************************************************** */ +/* */ +/* Numeric Arguments */ +/* */ +/* **************************************************************** */ + +/* Handle C-u style numeric args, as well as M--, and M-digits. */ +static int +rl_digit_loop () +{ + int key, c, sawminus, sawdigits; + + rl_save_prompt (); + + RL_SETSTATE(RL_STATE_NUMERICARG); + sawminus = sawdigits = 0; + while (1) + { + if (rl_numeric_arg > 1000000) + { + sawdigits = rl_explicit_arg = rl_numeric_arg = 0; + rl_ding (); + rl_restore_prompt (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return 1; + } + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); + RL_SETSTATE(RL_STATE_MOREINPUT); + key = c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (c < 0) + { + _rl_abort_internal (); + return -1; + } + + /* If we see a key bound to `universal-argument' after seeing digits, + it ends the argument but is otherwise ignored. */ + if (_rl_keymap[c].type == ISFUNC && + _rl_keymap[c].function == rl_universal_argument) + { + if (sawdigits == 0) + { + rl_numeric_arg *= 4; + continue; + } + else + { + RL_SETSTATE(RL_STATE_MOREINPUT); + key = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + rl_restore_prompt (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return (_rl_dispatch (key, _rl_keymap)); + } + } + + c = UNMETA (c); + + if (_rl_digit_p (c)) + { + rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0'; + sawdigits = rl_explicit_arg = 1; + } + else if (c == '-' && rl_explicit_arg == 0) + { + rl_numeric_arg = sawminus = 1; + rl_arg_sign = -1; + } + else + { + /* Make M-- command equivalent to M--1 command. */ + if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0) + rl_explicit_arg = 1; + rl_restore_prompt (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return (_rl_dispatch (key, _rl_keymap)); + } + } + + /*NOTREACHED*/ +} + +/* Add the current digit to the argument in progress. */ +int +rl_digit_argument (ignore, key) + int ignore, key; +{ + rl_execute_next (key); + return (rl_digit_loop ()); +} + +/* What to do when you abort reading an argument. */ +int +rl_discard_argument () +{ + rl_ding (); + rl_clear_message (); + _rl_init_argument (); + return 0; +} + +/* Create a default argument. */ +int +_rl_init_argument () +{ + rl_numeric_arg = rl_arg_sign = 1; + rl_explicit_arg = 0; + return 0; +} + +/* C-u, universal argument. Multiply the current argument by 4. + Read a key. If the key has nothing to do with arguments, then + dispatch on it. If the key is the abort character then abort. */ +int +rl_universal_argument (count, key) + int count, key; +{ + rl_numeric_arg *= 4; + return (rl_digit_loop ()); +} + +/* **************************************************************** */ +/* */ +/* History Utilities */ +/* */ +/* **************************************************************** */ + +/* We already have a history library, and that is what we use to control + the history features of readline. This is our local interface to + the history mechanism. */ + +/* While we are editing the history, this is the saved + version of the original line. */ +HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL; + +/* Set the history pointer back to the last entry in the history. */ +void +_rl_start_using_history () +{ + using_history (); + if (_rl_saved_line_for_history) + _rl_free_history_entry (_rl_saved_line_for_history); + + _rl_saved_line_for_history = (HIST_ENTRY *)NULL; +} + +/* Free the contents (and containing structure) of a HIST_ENTRY. */ +void +_rl_free_history_entry (entry) + HIST_ENTRY *entry; +{ + if (entry == 0) + return; + if (entry->line) + free (entry->line); + free (entry); +} + +/* Perhaps put back the current line if it has changed. */ +int +rl_maybe_replace_line () +{ + HIST_ENTRY *temp; + + temp = current_history (); + /* If the current line has changed, save the changes. */ + if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) + { + temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list); + free (temp->line); + free (temp); + } + return 0; +} + +/* Restore the _rl_saved_line_for_history if there is one. */ +int +rl_maybe_unsave_line () +{ + if (_rl_saved_line_for_history) + { + rl_replace_line (_rl_saved_line_for_history->line, 0); + rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data; + _rl_free_history_entry (_rl_saved_line_for_history); + _rl_saved_line_for_history = (HIST_ENTRY *)NULL; + rl_point = rl_end; /* rl_replace_line sets rl_end */ + } + else + rl_ding (); + return 0; +} + +/* Save the current line in _rl_saved_line_for_history. */ +int +rl_maybe_save_line () +{ + if (_rl_saved_line_for_history == 0) + { + _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + _rl_saved_line_for_history->line = savestring (rl_line_buffer); + _rl_saved_line_for_history->data = (char *)rl_undo_list; + } + return 0; +} + +int +_rl_free_saved_history_line () +{ + if (_rl_saved_line_for_history) + { + _rl_free_history_entry (_rl_saved_line_for_history); + _rl_saved_line_for_history = (HIST_ENTRY *)NULL; + } + return 0; +} + +static void +_rl_history_set_point () +{ + rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) + ? _rl_history_saved_point + : rl_end; + if (rl_point > rl_end) + rl_point = rl_end; + +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + rl_point = 0; +#endif /* VI_MODE */ + + if (rl_editing_mode == emacs_mode) + rl_mark = (rl_point == rl_end ? 0 : rl_end); +} + +void +rl_replace_from_history (entry, flags) + HIST_ENTRY *entry; + int flags; /* currently unused */ +{ + rl_replace_line (entry->line, 0); + rl_undo_list = (UNDO_LIST *)entry->data; + rl_point = rl_end; + rl_mark = 0; + +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + { + rl_point = 0; + rl_mark = rl_end; + } +#endif +} + +/* **************************************************************** */ +/* */ +/* History Commands */ +/* */ +/* **************************************************************** */ + +/* Meta-< goes to the start of the history. */ +int +rl_beginning_of_history (count, key) + int count, key; +{ + return (rl_get_previous_history (1 + where_history (), key)); +} + +/* Meta-> goes to the end of the history. (The current line). */ +int +rl_end_of_history (count, key) + int count, key; +{ + rl_maybe_replace_line (); + using_history (); + rl_maybe_unsave_line (); + return 0; +} + +/* Move down to the next history line. */ +int +rl_get_next_history (count, key) + int count, key; +{ + HIST_ENTRY *temp; + + if (count < 0) + return (rl_get_previous_history (-count, key)); + + if (count == 0) + return 0; + + rl_maybe_replace_line (); + + /* either not saved by rl_newline or at end of line, so set appropriately. */ + if (_rl_history_saved_point == -1 && (rl_point || rl_end)) + _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; + + temp = (HIST_ENTRY *)NULL; + while (count) + { + temp = next_history (); + if (!temp) + break; + --count; + } + + if (temp == 0) + rl_maybe_unsave_line (); + else + { + rl_replace_from_history (temp, 0); + _rl_history_set_point (); + } + return 0; +} + +/* Get the previous item out of our interactive history, making it the current + line. If there is no previous history, just ding. */ +int +rl_get_previous_history (count, key) + int count, key; +{ + HIST_ENTRY *old_temp, *temp; + + if (count < 0) + return (rl_get_next_history (-count, key)); + + if (count == 0) + return 0; + + /* either not saved by rl_newline or at end of line, so set appropriately. */ + if (_rl_history_saved_point == -1 && (rl_point || rl_end)) + _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; + + /* If we don't have a line saved, then save this one. */ + rl_maybe_save_line (); + + /* If the current line has changed, save the changes. */ + rl_maybe_replace_line (); + + temp = old_temp = (HIST_ENTRY *)NULL; + while (count) + { + temp = previous_history (); + if (temp == 0) + break; + + old_temp = temp; + --count; + } + + /* If there was a large argument, and we moved back to the start of the + history, that is not an error. So use the last value found. */ + if (!temp && old_temp) + temp = old_temp; + + if (temp == 0) + rl_ding (); + else + { + rl_replace_from_history (temp, 0); + _rl_history_set_point (); + } + return 0; +} + +/* **************************************************************** */ +/* */ +/* Editing Modes */ +/* */ +/* **************************************************************** */ +/* How to toggle back and forth between editing modes. */ +int +rl_vi_editing_mode (count, key) + int count, key; +{ +#if defined (VI_MODE) + _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ + rl_editing_mode = vi_mode; + rl_vi_insertion_mode (1, key); +#endif /* VI_MODE */ + + return 0; +} + +int +rl_emacs_editing_mode (count, key) + int count, key; +{ + rl_editing_mode = emacs_mode; + _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ + _rl_keymap = emacs_standard_keymap; + return 0; +} + +/* Function for the rest of the library to use to set insert/overwrite mode. */ +void +_rl_set_insert_mode (im, force) + int im, force; +{ +#ifdef CURSOR_MODE + _rl_set_cursor (im, force); +#endif + + rl_insert_mode = im; +} + +/* Toggle overwrite mode. A positive explicit argument selects overwrite + mode. A negative or zero explicit argument selects insert mode. */ +int +rl_overwrite_mode (count, key) + int count, key; +{ + if (rl_explicit_arg == 0) + _rl_set_insert_mode (rl_insert_mode ^ 1, 0); + else if (count > 0) + _rl_set_insert_mode (RL_IM_OVERWRITE, 0); + else + _rl_set_insert_mode (RL_IM_INSERT, 0); + + return 0; +} diff --git a/readline/readline-4.3/nls.c b/readline/readline-4.3/nls.c new file mode 100644 index 00000000..706c8195 --- /dev/null +++ b/readline/readline-4.3/nls.c @@ -0,0 +1,225 @@ +/* nls.c -- skeletal internationalization code. */ + +/* Copyright (C) 1996 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_LOCALE_H) +# include +#endif + +#include + +#include "rldefs.h" +#include "readline.h" +#include "rlshell.h" +#include "rlprivate.h" + +#if !defined (HAVE_SETLOCALE) +/* A list of legal values for the LANG or LC_CTYPE environment variables. + If a locale name in this list is the value for the LC_ALL, LC_CTYPE, + or LANG environment variable (using the first of those with a value), + readline eight-bit mode is enabled. */ +static char *legal_lang_values[] = +{ + "iso88591", + "iso88592", + "iso88593", + "iso88594", + "iso88595", + "iso88596", + "iso88597", + "iso88598", + "iso88599", + "iso885910", + "koi8r", + 0 +}; + +static char *normalize_codeset PARAMS((char *)); +static char *find_codeset PARAMS((char *, size_t *)); +#endif /* !HAVE_SETLOCALE */ + +/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value + to decide the defaults for 8-bit character input and output. Returns + 1 if we set eight-bit mode. */ +int +_rl_init_eightbit () +{ +/* If we have setlocale(3), just check the current LC_CTYPE category + value, and go into eight-bit mode if it's not C or POSIX. */ +#if defined (HAVE_SETLOCALE) + char *t; + + /* Set the LC_CTYPE locale category from environment variables. */ + t = setlocale (LC_CTYPE, ""); + if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0)) + { + _rl_meta_flag = 1; + _rl_convert_meta_chars_to_ascii = 0; + _rl_output_meta_chars = 1; + return (1); + } + else + return (0); + +#else /* !HAVE_SETLOCALE */ + char *lspec, *t; + int i; + + /* We don't have setlocale. Finesse it. Check the environment for the + appropriate variables and set eight-bit mode if they have the right + values. */ + lspec = sh_get_env_value ("LC_ALL"); + if (lspec == 0) lspec = sh_get_env_value ("LC_CTYPE"); + if (lspec == 0) lspec = sh_get_env_value ("LANG"); + if (lspec == 0 || (t = normalize_codeset (lspec)) == 0) + return (0); + for (i = 0; t && legal_lang_values[i]; i++) + if (STREQ (t, legal_lang_values[i])) + { + _rl_meta_flag = 1; + _rl_convert_meta_chars_to_ascii = 0; + _rl_output_meta_chars = 1; + break; + } + free (t); + return (legal_lang_values[i] ? 1 : 0); + +#endif /* !HAVE_SETLOCALE */ +} + +#if !defined (HAVE_SETLOCALE) +static char * +normalize_codeset (codeset) + char *codeset; +{ + size_t namelen, i; + int len, all_digits; + char *wp, *retval; + + codeset = find_codeset (codeset, &namelen); + + if (codeset == 0) + return (codeset); + + all_digits = 1; + for (len = 0, i = 0; i < namelen; i++) + { + if (ISALNUM ((unsigned char)codeset[i])) + { + len++; + all_digits &= _rl_digit_p (codeset[i]); + } + } + + retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1); + if (retval == 0) + return ((char *)0); + + wp = retval; + /* Add `iso' to beginning of an all-digit codeset */ + if (all_digits) + { + *wp++ = 'i'; + *wp++ = 's'; + *wp++ = 'o'; + } + + for (i = 0; i < namelen; i++) + if (ISALPHA ((unsigned char)codeset[i])) + *wp++ = _rl_to_lower (codeset[i]); + else if (_rl_digit_p (codeset[i])) + *wp++ = codeset[i]; + *wp = '\0'; + + return retval; +} + +/* Isolate codeset portion of locale specification. */ +static char * +find_codeset (name, lenp) + char *name; + size_t *lenp; +{ + char *cp, *language, *result; + + cp = language = name; + result = (char *)0; + + while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',') + cp++; + + /* This does not make sense: language has to be specified. As + an exception we allow the variable to contain only the codeset + name. Perhaps there are funny codeset names. */ + if (language == cp) + { + *lenp = strlen (language); + result = language; + } + else + { + /* Next is the territory. */ + if (*cp == '_') + do + ++cp; + while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_'); + + /* Now, finally, is the codeset. */ + result = cp; + if (*cp == '.') + do + ++cp; + while (*cp && *cp != '@'); + + if (cp - result > 2) + { + result++; + *lenp = cp - result; + } + else + { + *lenp = strlen (language); + result = language; + } + } + + return result; +} +#endif /* !HAVE_SETLOCALE */ diff --git a/readline/readline-4.3/parens.c b/readline/readline-4.3/parens.c new file mode 100644 index 00000000..54ef1f36 --- /dev/null +++ b/readline/readline-4.3/parens.c @@ -0,0 +1,179 @@ +/* parens.c -- Implementation of matching parentheses feature. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#include "rlconf.h" + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#if defined (FD_SET) && !defined (HAVE_SELECT) +# define HAVE_SELECT +#endif + +#if defined (HAVE_SELECT) +# include +#endif /* HAVE_SELECT */ +#if defined (HAVE_SYS_SELECT_H) +# include +#endif + +#if defined (HAVE_STRING_H) +# include +#else /* !HAVE_STRING_H */ +# include +#endif /* !HAVE_STRING_H */ + +#if !defined (strchr) && !defined (__STDC__) +extern char *strchr (), *strrchr (); +#endif /* !strchr && !__STDC__ */ + +#include "readline.h" +#include "rlprivate.h" + +static int find_matching_open PARAMS((char *, int, int)); + +/* Non-zero means try to blink the matching open parenthesis when the + close parenthesis is inserted. */ +#if defined (HAVE_SELECT) +int rl_blink_matching_paren = 1; +#else /* !HAVE_SELECT */ +int rl_blink_matching_paren = 0; +#endif /* !HAVE_SELECT */ + +static int _paren_blink_usec = 500000; + +/* Change emacs_standard_keymap to have bindings for paren matching when + ON_OR_OFF is 1, change them back to self_insert when ON_OR_OFF == 0. */ +void +_rl_enable_paren_matching (on_or_off) + int on_or_off; +{ + if (on_or_off) + { /* ([{ */ + rl_bind_key_in_map (')', rl_insert_close, emacs_standard_keymap); + rl_bind_key_in_map (']', rl_insert_close, emacs_standard_keymap); + rl_bind_key_in_map ('}', rl_insert_close, emacs_standard_keymap); + } + else + { /* ([{ */ + rl_bind_key_in_map (')', rl_insert, emacs_standard_keymap); + rl_bind_key_in_map (']', rl_insert, emacs_standard_keymap); + rl_bind_key_in_map ('}', rl_insert, emacs_standard_keymap); + } +} + +int +rl_set_paren_blink_timeout (u) + int u; +{ + int o; + + o = _paren_blink_usec; + if (u > 0) + _paren_blink_usec = u; + return (o); +} + +int +rl_insert_close (count, invoking_key) + int count, invoking_key; +{ + if (rl_explicit_arg || !rl_blink_matching_paren) + _rl_insert_char (count, invoking_key); + else + { +#if defined (HAVE_SELECT) + int orig_point, match_point, ready; + struct timeval timer; + fd_set readfds; + + _rl_insert_char (1, invoking_key); + (*rl_redisplay_function) (); + match_point = + find_matching_open (rl_line_buffer, rl_point - 2, invoking_key); + + /* Emacs might message or ring the bell here, but I don't. */ + if (match_point < 0) + return -1; + + FD_ZERO (&readfds); + FD_SET (fileno (rl_instream), &readfds); + timer.tv_sec = 0; + timer.tv_usec = _paren_blink_usec; + + orig_point = rl_point; + rl_point = match_point; + (*rl_redisplay_function) (); + ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); + rl_point = orig_point; +#else /* !HAVE_SELECT */ + _rl_insert_char (count, invoking_key); +#endif /* !HAVE_SELECT */ + } + return 0; +} + +static int +find_matching_open (string, from, closer) + char *string; + int from, closer; +{ + register int i; + int opener, level, delimiter; + + switch (closer) + { + case ']': opener = '['; break; + case '}': opener = '{'; break; + case ')': opener = '('; break; + default: + return (-1); + } + + level = 1; /* The closer passed in counts as 1. */ + delimiter = 0; /* Delimited state unknown. */ + + for (i = from; i > -1; i--) + { + if (delimiter && (string[i] == delimiter)) + delimiter = 0; + else if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, string[i])) + delimiter = string[i]; + else if (!delimiter && (string[i] == closer)) + level++; + else if (!delimiter && (string[i] == opener)) + level--; + + if (!level) + break; + } + return (i); +} diff --git a/readline/readline-4.3/posixdir.h b/readline/readline-4.3/posixdir.h new file mode 100644 index 00000000..505e2795 --- /dev/null +++ b/readline/readline-4.3/posixdir.h @@ -0,0 +1,57 @@ +/* posixdir.h -- Posix directory reading includes and defines. */ + +/* Copyright (C) 1987,1991 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + Bash is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with Bash; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +/* This file should be included instead of or . */ + +#if !defined (_POSIXDIR_H_) +#define _POSIXDIR_H_ + +#if defined (HAVE_DIRENT_H) +# include +# define D_NAMLEN(d) (strlen ((d)->d_name)) +#else +# if defined (HAVE_SYS_NDIR_H) +# include +# endif +# if defined (HAVE_SYS_DIR_H) +# include +# endif +# if defined (HAVE_NDIR_H) +# include +# endif +# if !defined (dirent) +# define dirent direct +# endif /* !dirent */ +# define D_NAMLEN(d) ((d)->d_namlen) +#endif /* !HAVE_DIRENT_H */ + +#if defined (STRUCT_DIRENT_HAS_D_INO) && !defined (STRUCT_DIRENT_HAS_D_FILENO) +# define d_fileno d_ino +#endif + +#if defined (_POSIX_SOURCE) && (!defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO)) +/* Posix does not require that the d_ino field be present, and some + systems do not provide it. */ +# define REAL_DIR_ENTRY(dp) 1 +#else +# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) +#endif /* _POSIX_SOURCE */ + +#endif /* !_POSIXDIR_H_ */ diff --git a/readline/readline-4.3/posixjmp.h b/readline/readline-4.3/posixjmp.h new file mode 100644 index 00000000..b52aa003 --- /dev/null +++ b/readline/readline-4.3/posixjmp.h @@ -0,0 +1,40 @@ +/* posixjmp.h -- wrapper for setjmp.h with changes for POSIX systems. */ + +/* Copyright (C) 1987,1991 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + Bash is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with Bash; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#ifndef _POSIXJMP_H_ +#define _POSIXJMP_H_ + +#include + +/* This *must* be included *after* config.h */ + +#if defined (HAVE_POSIX_SIGSETJMP) +# define procenv_t sigjmp_buf +# if !defined (__OPENNT) +# undef setjmp +# define setjmp(x) sigsetjmp((x), 1) +# undef longjmp +# define longjmp(x, n) siglongjmp((x), (n)) +# endif /* !__OPENNT */ +#else +# define procenv_t jmp_buf +#endif + +#endif /* _POSIXJMP_H_ */ diff --git a/readline/readline-4.3/posixstat.h b/readline/readline-4.3/posixstat.h new file mode 100644 index 00000000..c93b5288 --- /dev/null +++ b/readline/readline-4.3/posixstat.h @@ -0,0 +1,142 @@ +/* posixstat.h -- Posix stat(2) definitions for systems that + don't have them. */ + +/* Copyright (C) 1987,1991 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + Bash is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with Bash; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +/* This file should be included instead of . + It relies on the local sys/stat.h to work though. */ +#if !defined (_POSIXSTAT_H_) +#define _POSIXSTAT_H_ + +#include + +#if defined (STAT_MACROS_BROKEN) +# undef S_ISBLK +# undef S_ISCHR +# undef S_ISDIR +# undef S_ISFIFO +# undef S_ISREG +# undef S_ISLNK +#endif /* STAT_MACROS_BROKEN */ + +/* These are guaranteed to work only on isc386 */ +#if !defined (S_IFDIR) && !defined (S_ISDIR) +# define S_IFDIR 0040000 +#endif /* !S_IFDIR && !S_ISDIR */ +#if !defined (S_IFMT) +# define S_IFMT 0170000 +#endif /* !S_IFMT */ + +/* Posix 1003.1 5.6.1.1 file types */ + +/* Some Posix-wannabe systems define _S_IF* macros instead of S_IF*, but + do not provide the S_IS* macros that Posix requires. */ + +#if defined (_S_IFMT) && !defined (S_IFMT) +#define S_IFMT _S_IFMT +#endif +#if defined (_S_IFIFO) && !defined (S_IFIFO) +#define S_IFIFO _S_IFIFO +#endif +#if defined (_S_IFCHR) && !defined (S_IFCHR) +#define S_IFCHR _S_IFCHR +#endif +#if defined (_S_IFDIR) && !defined (S_IFDIR) +#define S_IFDIR _S_IFDIR +#endif +#if defined (_S_IFBLK) && !defined (S_IFBLK) +#define S_IFBLK _S_IFBLK +#endif +#if defined (_S_IFREG) && !defined (S_IFREG) +#define S_IFREG _S_IFREG +#endif +#if defined (_S_IFLNK) && !defined (S_IFLNK) +#define S_IFLNK _S_IFLNK +#endif +#if defined (_S_IFSOCK) && !defined (S_IFSOCK) +#define S_IFSOCK _S_IFSOCK +#endif + +/* Test for each symbol individually and define the ones necessary (some + systems claiming Posix compatibility define some but not all). */ + +#if defined (S_IFBLK) && !defined (S_ISBLK) +#define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK) /* block device */ +#endif + +#if defined (S_IFCHR) && !defined (S_ISCHR) +#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) /* character device */ +#endif + +#if defined (S_IFDIR) && !defined (S_ISDIR) +#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) /* directory */ +#endif + +#if defined (S_IFREG) && !defined (S_ISREG) +#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) /* file */ +#endif + +#if defined (S_IFIFO) && !defined (S_ISFIFO) +#define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO) /* fifo - named pipe */ +#endif + +#if defined (S_IFLNK) && !defined (S_ISLNK) +#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) /* symbolic link */ +#endif + +#if defined (S_IFSOCK) && !defined (S_ISSOCK) +#define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) /* socket */ +#endif + +/* + * POSIX 1003.1 5.6.1.2 File Modes + */ + +#if !defined (S_IRWXU) +# if !defined (S_IREAD) +# define S_IREAD 00400 +# define S_IWRITE 00200 +# define S_IEXEC 00100 +# endif /* S_IREAD */ + +# if !defined (S_IRUSR) +# define S_IRUSR S_IREAD /* read, owner */ +# define S_IWUSR S_IWRITE /* write, owner */ +# define S_IXUSR S_IEXEC /* execute, owner */ + +# define S_IRGRP (S_IREAD >> 3) /* read, group */ +# define S_IWGRP (S_IWRITE >> 3) /* write, group */ +# define S_IXGRP (S_IEXEC >> 3) /* execute, group */ + +# define S_IROTH (S_IREAD >> 6) /* read, other */ +# define S_IWOTH (S_IWRITE >> 6) /* write, other */ +# define S_IXOTH (S_IEXEC >> 6) /* execute, other */ +# endif /* !S_IRUSR */ + +# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#endif /* !S_IRWXU */ + +/* These are non-standard, but are used in builtins.c$symbolic_umask() */ +#define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH) +#define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH) +#define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) + +#endif /* _POSIXSTAT_H_ */ diff --git a/readline/readline-4.3/readline.c b/readline/readline-4.3/readline.c new file mode 100644 index 00000000..43c0c627 --- /dev/null +++ b/readline/readline-4.3/readline.c @@ -0,0 +1,974 @@ +/* readline.c -- a general facility for reading lines of input + with emacs style editing and completion. */ + +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include "posixstat.h" +#include +#if defined (HAVE_SYS_FILE_H) +# include +#endif /* HAVE_SYS_FILE_H */ + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_LOCALE_H) +# include +#endif + +#include +#include "posixjmp.h" + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#if defined (__EMX__) +# define INCL_DOSPROCESS +# include +#endif /* __EMX__ */ + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + +#ifndef RL_LIBRARY_VERSION +# define RL_LIBRARY_VERSION "4.3" +#endif + +#ifndef RL_READLINE_VERSION +# define RL_READLINE_VERSION 0x0403 +#endif + +extern void _rl_free_history_entry PARAMS((HIST_ENTRY *)); + +/* Forward declarations used in this file. */ +static char *readline_internal PARAMS((void)); +static void readline_initialize_everything PARAMS((void)); + +static void bind_arrow_keys_internal PARAMS((Keymap)); +static void bind_arrow_keys PARAMS((void)); + +static void readline_default_bindings PARAMS((void)); + +/* **************************************************************** */ +/* */ +/* Line editing input utility */ +/* */ +/* **************************************************************** */ + +const char *rl_library_version = RL_LIBRARY_VERSION; + +int rl_readline_version = RL_READLINE_VERSION; + +/* True if this is `real' readline as opposed to some stub substitute. */ +int rl_gnu_readline_p = 1; + +/* A pointer to the keymap that is currently in use. + By default, it is the standard emacs keymap. */ +Keymap _rl_keymap = emacs_standard_keymap; + +/* The current style of editing. */ +int rl_editing_mode = emacs_mode; + +/* The current insert mode: input (the default) or overwrite */ +int rl_insert_mode = RL_IM_DEFAULT; + +/* Non-zero if we called this function from _rl_dispatch(). It's present + so functions can find out whether they were called from a key binding + or directly from an application. */ +int rl_dispatching; + +/* Non-zero if the previous command was a kill command. */ +int _rl_last_command_was_kill = 0; + +/* The current value of the numeric argument specified by the user. */ +int rl_numeric_arg = 1; + +/* Non-zero if an argument was typed. */ +int rl_explicit_arg = 0; + +/* Temporary value used while generating the argument. */ +int rl_arg_sign = 1; + +/* Non-zero means we have been called at least once before. */ +static int rl_initialized; + +#if 0 +/* If non-zero, this program is running in an EMACS buffer. */ +static int running_in_emacs; +#endif + +/* Flags word encapsulating the current readline state. */ +int rl_readline_state = RL_STATE_NONE; + +/* The current offset in the current input line. */ +int rl_point; + +/* Mark in the current input line. */ +int rl_mark; + +/* Length of the current input line. */ +int rl_end; + +/* Make this non-zero to return the current input_line. */ +int rl_done; + +/* The last function executed by readline. */ +rl_command_func_t *rl_last_func = (rl_command_func_t *)NULL; + +/* Top level environment for readline_internal (). */ +procenv_t readline_top_level; + +/* The streams we interact with. */ +FILE *_rl_in_stream, *_rl_out_stream; + +/* The names of the streams that we do input and output to. */ +FILE *rl_instream = (FILE *)NULL; +FILE *rl_outstream = (FILE *)NULL; + +/* Non-zero means echo characters as they are read. Defaults to no echo; + set to 1 if there is a controlling terminal, we can get its attributes, + and the attributes include `echo'. Look at rltty.c:prepare_terminal_settings + for the code that sets it. */ +int readline_echoing_p = 0; + +/* Current prompt. */ +char *rl_prompt = (char *)NULL; +int rl_visible_prompt_length = 0; + +/* Set to non-zero by calling application if it has already printed rl_prompt + and does not want readline to do it the first time. */ +int rl_already_prompted = 0; + +/* The number of characters read in order to type this complete command. */ +int rl_key_sequence_length = 0; + +/* If non-zero, then this is the address of a function to call just + before readline_internal_setup () prints the first prompt. */ +rl_hook_func_t *rl_startup_hook = (rl_hook_func_t *)NULL; + +/* If non-zero, this is the address of a function to call just before + readline_internal_setup () returns and readline_internal starts + reading input characters. */ +rl_hook_func_t *rl_pre_input_hook = (rl_hook_func_t *)NULL; + +/* What we use internally. You should always refer to RL_LINE_BUFFER. */ +static char *the_line; + +/* The character that can generate an EOF. Really read from + the terminal driver... just defaulted here. */ +int _rl_eof_char = CTRL ('D'); + +/* Non-zero makes this the next keystroke to read. */ +int rl_pending_input = 0; + +/* Pointer to a useful terminal name. */ +const char *rl_terminal_name = (const char *)NULL; + +/* Non-zero means to always use horizontal scrolling in line display. */ +int _rl_horizontal_scroll_mode = 0; + +/* Non-zero means to display an asterisk at the starts of history lines + which have been modified. */ +int _rl_mark_modified_lines = 0; + +/* The style of `bell' notification preferred. This can be set to NO_BELL, + AUDIBLE_BELL, or VISIBLE_BELL. */ +int _rl_bell_preference = AUDIBLE_BELL; + +/* String inserted into the line by rl_insert_comment (). */ +char *_rl_comment_begin; + +/* Keymap holding the function currently being executed. */ +Keymap rl_executing_keymap; + +/* Non-zero means to erase entire line, including prompt, on empty input lines. */ +int rl_erase_empty_line = 0; + +/* Non-zero means to read only this many characters rather than up to a + character bound to accept-line. */ +int rl_num_chars_to_read; + +/* Line buffer and maintenence. */ +char *rl_line_buffer = (char *)NULL; +int rl_line_buffer_len = 0; + +/* Forward declarations used by the display, termcap, and history code. */ + +/* **************************************************************** */ +/* */ +/* `Forward' declarations */ +/* */ +/* **************************************************************** */ + +/* Non-zero means do not parse any lines other than comments and + parser directives. */ +unsigned char _rl_parsing_conditionalized_out = 0; + +/* Non-zero means to convert characters with the meta bit set to + escape-prefixed characters so we can indirect through + emacs_meta_keymap or vi_escape_keymap. */ +int _rl_convert_meta_chars_to_ascii = 1; + +/* Non-zero means to output characters with the meta bit set directly + rather than as a meta-prefixed escape sequence. */ +int _rl_output_meta_chars = 0; + +/* **************************************************************** */ +/* */ +/* Top Level Functions */ +/* */ +/* **************************************************************** */ + +/* Non-zero means treat 0200 bit in terminal input as Meta bit. */ +int _rl_meta_flag = 0; /* Forward declaration */ + +/* Set up the prompt and expand it. Called from readline() and + rl_callback_handler_install (). */ +int +rl_set_prompt (prompt) + const char *prompt; +{ + FREE (rl_prompt); + rl_prompt = prompt ? savestring (prompt) : (char *)NULL; + + rl_visible_prompt_length = rl_expand_prompt (rl_prompt); + return 0; +} + +/* Read a line of input. Prompt with PROMPT. An empty PROMPT means + none. A return value of NULL means that EOF was encountered. */ +char * +readline (prompt) + const char *prompt; +{ + char *value; + + /* If we are at EOF return a NULL string. */ + if (rl_pending_input == EOF) + { + rl_clear_pending_input (); + return ((char *)NULL); + } + + rl_set_prompt (prompt); + + rl_initialize (); + (*rl_prep_term_function) (_rl_meta_flag); + +#if defined (HANDLE_SIGNALS) + rl_set_signals (); +#endif + + value = readline_internal (); + (*rl_deprep_term_function) (); + +#if defined (HANDLE_SIGNALS) + rl_clear_signals (); +#endif + + return (value); +} + +#if defined (READLINE_CALLBACKS) +# define STATIC_CALLBACK +#else +# define STATIC_CALLBACK static +#endif + +STATIC_CALLBACK void +readline_internal_setup () +{ + char *nprompt; + + _rl_in_stream = rl_instream; + _rl_out_stream = rl_outstream; + + if (rl_startup_hook) + (*rl_startup_hook) (); + + /* If we're not echoing, we still want to at least print a prompt, because + rl_redisplay will not do it for us. If the calling application has a + custom redisplay function, though, let that function handle it. */ + if (readline_echoing_p == 0 && rl_redisplay_function == rl_redisplay) + { + if (rl_prompt && rl_already_prompted == 0) + { + nprompt = _rl_strip_prompt (rl_prompt); + fprintf (_rl_out_stream, "%s", nprompt); + fflush (_rl_out_stream); + free (nprompt); + } + } + else + { + if (rl_prompt && rl_already_prompted) + rl_on_new_line_with_prompt (); + else + rl_on_new_line (); + (*rl_redisplay_function) (); + } + +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + rl_vi_insertion_mode (1, 0); +#endif /* VI_MODE */ + + if (rl_pre_input_hook) + (*rl_pre_input_hook) (); +} + +STATIC_CALLBACK char * +readline_internal_teardown (eof) + int eof; +{ + char *temp; + HIST_ENTRY *entry; + + /* Restore the original of this history line, iff the line that we + are editing was originally in the history, AND the line has changed. */ + entry = current_history (); + + if (entry && rl_undo_list) + { + temp = savestring (the_line); + rl_revert_line (1, 0); + entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL); + _rl_free_history_entry (entry); + + strcpy (the_line, temp); + free (temp); + } + + /* At any rate, it is highly likely that this line has an undo list. Get + rid of it now. */ + if (rl_undo_list) + rl_free_undo_list (); + + /* Restore normal cursor, if available. */ + _rl_set_insert_mode (RL_IM_INSERT, 0); + + return (eof ? (char *)NULL : savestring (the_line)); +} + +STATIC_CALLBACK int +#if defined (READLINE_CALLBACKS) +readline_internal_char () +#else +readline_internal_charloop () +#endif +{ + static int lastc, eof_found; + int c, code, lk; + + lastc = -1; + eof_found = 0; + +#if !defined (READLINE_CALLBACKS) + while (rl_done == 0) + { +#endif + lk = _rl_last_command_was_kill; + + code = setjmp (readline_top_level); + + if (code) + (*rl_redisplay_function) (); + + if (rl_pending_input == 0) + { + /* Then initialize the argument and number of keys read. */ + _rl_init_argument (); + rl_key_sequence_length = 0; + } + + RL_SETSTATE(RL_STATE_READCMD); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_READCMD); + + /* EOF typed to a non-blank line is a . */ + if (c == EOF && rl_end) + c = NEWLINE; + + /* The character _rl_eof_char typed to blank line, and not as the + previous character is interpreted as EOF. */ + if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end) + { +#if defined (READLINE_CALLBACKS) + RL_SETSTATE(RL_STATE_DONE); + return (rl_done = 1); +#else + eof_found = 1; + break; +#endif + } + + lastc = c; + _rl_dispatch ((unsigned char)c, _rl_keymap); + + /* If there was no change in _rl_last_command_was_kill, then no kill + has taken place. Note that if input is pending we are reading + a prefix command, so nothing has changed yet. */ + if (rl_pending_input == 0 && lk == _rl_last_command_was_kill) + _rl_last_command_was_kill = 0; + +#if defined (VI_MODE) + /* In vi mode, when you exit insert mode, the cursor moves back + over the previous character. We explicitly check for that here. */ + if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) + rl_vi_check (); +#endif /* VI_MODE */ + + if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read) + { + (*rl_redisplay_function) (); + rl_newline (1, '\n'); + } + + if (rl_done == 0) + (*rl_redisplay_function) (); + + /* If the application writer has told us to erase the entire line if + the only character typed was something bound to rl_newline, do so. */ + if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline && + rl_point == 0 && rl_end == 0) + _rl_erase_entire_line (); + +#if defined (READLINE_CALLBACKS) + return 0; +#else + } + + return (eof_found); +#endif +} + +#if defined (READLINE_CALLBACKS) +static int +readline_internal_charloop () +{ + int eof = 1; + + while (rl_done == 0) + eof = readline_internal_char (); + return (eof); +} +#endif /* READLINE_CALLBACKS */ + +/* Read a line of input from the global rl_instream, doing output on + the global rl_outstream. + If rl_prompt is non-null, then that is our prompt. */ +static char * +readline_internal () +{ + int eof; + + readline_internal_setup (); + eof = readline_internal_charloop (); + return (readline_internal_teardown (eof)); +} + +void +_rl_init_line_state () +{ + rl_point = rl_end = rl_mark = 0; + the_line = rl_line_buffer; + the_line[0] = 0; +} + +void +_rl_set_the_line () +{ + the_line = rl_line_buffer; +} + +/* Do the command associated with KEY in MAP. + If the associated command is really a keymap, then read + another key, and dispatch into that map. */ +int +_rl_dispatch (key, map) + register int key; + Keymap map; +{ + return _rl_dispatch_subseq (key, map, 0); +} + +int +_rl_dispatch_subseq (key, map, got_subseq) + register int key; + Keymap map; + int got_subseq; +{ + int r, newkey; + char *macro; + rl_command_func_t *func; + + if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) + { + if (map[ESC].type == ISKMAP) + { + if (RL_ISSTATE (RL_STATE_MACRODEF)) + _rl_add_macro_char (ESC); + map = FUNCTION_TO_KEYMAP (map, ESC); + key = UNMETA (key); + rl_key_sequence_length += 2; + return (_rl_dispatch (key, map)); + } + else + rl_ding (); + return 0; + } + + if (RL_ISSTATE (RL_STATE_MACRODEF)) + _rl_add_macro_char (key); + + r = 0; + switch (map[key].type) + { + case ISFUNC: + func = map[key].function; + if (func) + { + /* Special case rl_do_lowercase_version (). */ + if (func == rl_do_lowercase_version) + return (_rl_dispatch (_rl_to_lower (key), map)); + + rl_executing_keymap = map; + +#if 0 + _rl_suppress_redisplay = (map[key].function == rl_insert) && _rl_input_available (); +#endif + + rl_dispatching = 1; + RL_SETSTATE(RL_STATE_DISPATCHING); + r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key); + RL_UNSETSTATE(RL_STATE_DISPATCHING); + rl_dispatching = 0; + + /* If we have input pending, then the last command was a prefix + command. Don't change the state of rl_last_func. Otherwise, + remember the last command executed in this variable. */ + if (rl_pending_input == 0 && map[key].function != rl_digit_argument) + rl_last_func = map[key].function; + } + else if (map[ANYOTHERKEY].function) + { + /* OK, there's no function bound in this map, but there is a + shadow function that was overridden when the current keymap + was created. Return -2 to note that. */ + _rl_unget_char (key); + return -2; + } + else if (got_subseq) + { + /* Return -1 to note that we're in a subsequence, but we don't + have a matching key, nor was one overridden. This means + we need to back up the recursion chain and find the last + subsequence that is bound to a function. */ + _rl_unget_char (key); + return -1; + } + else + { + _rl_abort_internal (); + return -1; + } + break; + + case ISKMAP: + if (map[key].function != 0) + { +#if defined (VI_MODE) + /* The only way this test will be true is if a subsequence has been + bound starting with ESC, generally the arrow keys. What we do is + check whether there's input in the queue, which there generally + will be if an arrow key has been pressed, and, if there's not, + just dispatch to (what we assume is) rl_vi_movement_mode right + away. This is essentially an input test with a zero timeout. */ + if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap + && _rl_input_queued (0) == 0) + return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key))); +#endif + + rl_key_sequence_length++; + + if (key == ESC) + RL_SETSTATE(RL_STATE_METANEXT); + RL_SETSTATE(RL_STATE_MOREINPUT); + newkey = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (key == ESC) + RL_UNSETSTATE(RL_STATE_METANEXT); + + if (newkey < 0) + { + _rl_abort_internal (); + return -1; + } + + r = _rl_dispatch_subseq (newkey, FUNCTION_TO_KEYMAP (map, key), got_subseq || map[ANYOTHERKEY].function); + + if (r == -2) + /* We didn't match anything, and the keymap we're indexed into + shadowed a function previously bound to that prefix. Call + the function. The recursive call to _rl_dispatch_subseq has + already taken care of pushing any necessary input back onto + the input queue with _rl_unget_char. */ + r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)); + else if (r && map[ANYOTHERKEY].function) + { + /* We didn't match (r is probably -1), so return something to + tell the caller that it should try ANYOTHERKEY for an + overridden function. */ + _rl_unget_char (key); + return -2; + } + else if (r && got_subseq) + { + /* OK, back up the chain. */ + _rl_unget_char (key); + return -1; + } + } + else + { + _rl_abort_internal (); + return -1; + } + break; + + case ISMACR: + if (map[key].function != 0) + { + macro = savestring ((char *)map[key].function); + _rl_with_macro_input (macro); + return 0; + } + break; + } +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap && + key != ANYOTHERKEY && + _rl_vi_textmod_command (key)) + _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign); +#endif + return (r); +} + +/* **************************************************************** */ +/* */ +/* Initializations */ +/* */ +/* **************************************************************** */ + +/* Initialize readline (and terminal if not already). */ +int +rl_initialize () +{ + /* If we have never been called before, initialize the + terminal and data structures. */ + if (!rl_initialized) + { + RL_SETSTATE(RL_STATE_INITIALIZING); + readline_initialize_everything (); + RL_UNSETSTATE(RL_STATE_INITIALIZING); + rl_initialized++; + RL_SETSTATE(RL_STATE_INITIALIZED); + } + + /* Initialize the current line information. */ + _rl_init_line_state (); + + /* We aren't done yet. We haven't even gotten started yet! */ + rl_done = 0; + RL_UNSETSTATE(RL_STATE_DONE); + + /* Tell the history routines what is going on. */ + _rl_start_using_history (); + + /* Make the display buffer match the state of the line. */ + rl_reset_line_state (); + + /* No such function typed yet. */ + rl_last_func = (rl_command_func_t *)NULL; + + /* Parsing of key-bindings begins in an enabled state. */ + _rl_parsing_conditionalized_out = 0; + +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + _rl_vi_initialize_line (); +#endif + + /* Each line starts in insert mode (the default). */ + _rl_set_insert_mode (RL_IM_DEFAULT, 1); + + return 0; +} + +#if 0 +#if defined (__EMX__) +static void +_emx_build_environ () +{ + TIB *tibp; + PIB *pibp; + char *t, **tp; + int c; + + DosGetInfoBlocks (&tibp, &pibp); + t = pibp->pib_pchenv; + for (c = 1; *t; c++) + t += strlen (t) + 1; + tp = environ = (char **)xmalloc ((c + 1) * sizeof (char *)); + t = pibp->pib_pchenv; + while (*t) + { + *tp++ = t; + t += strlen (t) + 1; + } + *tp = 0; +} +#endif /* __EMX__ */ +#endif + +/* Initialize the entire state of the world. */ +static void +readline_initialize_everything () +{ +#if 0 +#if defined (__EMX__) + if (environ == 0) + _emx_build_environ (); +#endif +#endif + +#if 0 + /* Find out if we are running in Emacs -- UNUSED. */ + running_in_emacs = sh_get_env_value ("EMACS") != (char *)0; +#endif + + /* Set up input and output if they are not already set up. */ + if (!rl_instream) + rl_instream = stdin; + + if (!rl_outstream) + rl_outstream = stdout; + + /* Bind _rl_in_stream and _rl_out_stream immediately. These values + may change, but they may also be used before readline_internal () + is called. */ + _rl_in_stream = rl_instream; + _rl_out_stream = rl_outstream; + + /* Allocate data structures. */ + if (rl_line_buffer == 0) + rl_line_buffer = (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); + + /* Initialize the terminal interface. */ + if (rl_terminal_name == 0) + rl_terminal_name = sh_get_env_value ("TERM"); + _rl_init_terminal_io (rl_terminal_name); + + /* Bind tty characters to readline functions. */ + readline_default_bindings (); + + /* Initialize the function names. */ + rl_initialize_funmap (); + + /* Decide whether we should automatically go into eight-bit mode. */ + _rl_init_eightbit (); + + /* Read in the init file. */ + rl_read_init_file ((char *)NULL); + + /* XXX */ + if (_rl_horizontal_scroll_mode && _rl_term_autowrap) + { + _rl_screenwidth--; + _rl_screenchars -= _rl_screenheight; + } + + /* Override the effect of any `set keymap' assignments in the + inputrc file. */ + rl_set_keymap_from_edit_mode (); + + /* Try to bind a common arrow key prefix, if not already bound. */ + bind_arrow_keys (); + + /* Enable the meta key, if this terminal has one. */ + if (_rl_enable_meta) + _rl_enable_meta_key (); + + /* If the completion parser's default word break characters haven't + been set yet, then do so now. */ + if (rl_completer_word_break_characters == (char *)NULL) + rl_completer_word_break_characters = rl_basic_word_break_characters; +} + +/* If this system allows us to look at the values of the regular + input editing characters, then bind them to their readline + equivalents, iff the characters are not bound to keymaps. */ +static void +readline_default_bindings () +{ + rl_tty_set_default_bindings (_rl_keymap); +} + +/* Bind some common arrow key sequences in MAP. */ +static void +bind_arrow_keys_internal (map) + Keymap map; +{ + Keymap xkeymap; + + xkeymap = _rl_keymap; + _rl_keymap = map; + +#if defined (__MSDOS__) + _rl_bind_if_unbound ("\033[0A", rl_get_previous_history); + _rl_bind_if_unbound ("\033[0B", rl_backward_char); + _rl_bind_if_unbound ("\033[0C", rl_forward_char); + _rl_bind_if_unbound ("\033[0D", rl_get_next_history); +#endif + + _rl_bind_if_unbound ("\033[A", rl_get_previous_history); + _rl_bind_if_unbound ("\033[B", rl_get_next_history); + _rl_bind_if_unbound ("\033[C", rl_forward_char); + _rl_bind_if_unbound ("\033[D", rl_backward_char); + _rl_bind_if_unbound ("\033[H", rl_beg_of_line); + _rl_bind_if_unbound ("\033[F", rl_end_of_line); + + _rl_bind_if_unbound ("\033OA", rl_get_previous_history); + _rl_bind_if_unbound ("\033OB", rl_get_next_history); + _rl_bind_if_unbound ("\033OC", rl_forward_char); + _rl_bind_if_unbound ("\033OD", rl_backward_char); + _rl_bind_if_unbound ("\033OH", rl_beg_of_line); + _rl_bind_if_unbound ("\033OF", rl_end_of_line); + + _rl_keymap = xkeymap; +} + +/* Try and bind the common arrow key prefixes after giving termcap and + the inputrc file a chance to bind them and create `real' keymaps + for the arrow key prefix. */ +static void +bind_arrow_keys () +{ + bind_arrow_keys_internal (emacs_standard_keymap); + +#if defined (VI_MODE) + bind_arrow_keys_internal (vi_movement_keymap); + bind_arrow_keys_internal (vi_insertion_keymap); +#endif +} + +/* **************************************************************** */ +/* */ +/* Saving and Restoring Readline's state */ +/* */ +/* **************************************************************** */ + +int +rl_save_state (sp) + struct readline_state *sp; +{ + if (sp == 0) + return -1; + + sp->point = rl_point; + sp->end = rl_end; + sp->mark = rl_mark; + sp->buffer = rl_line_buffer; + sp->buflen = rl_line_buffer_len; + sp->ul = rl_undo_list; + sp->prompt = rl_prompt; + + sp->rlstate = rl_readline_state; + sp->done = rl_done; + sp->kmap = _rl_keymap; + + sp->lastfunc = rl_last_func; + sp->insmode = rl_insert_mode; + sp->edmode = rl_editing_mode; + sp->kseqlen = rl_key_sequence_length; + sp->inf = rl_instream; + sp->outf = rl_outstream; + sp->pendingin = rl_pending_input; + sp->macro = rl_executing_macro; + + sp->catchsigs = rl_catch_signals; + sp->catchsigwinch = rl_catch_sigwinch; + + return (0); +} + +int +rl_restore_state (sp) + struct readline_state *sp; +{ + if (sp == 0) + return -1; + + rl_point = sp->point; + rl_end = sp->end; + rl_mark = sp->mark; + the_line = rl_line_buffer = sp->buffer; + rl_line_buffer_len = sp->buflen; + rl_undo_list = sp->ul; + rl_prompt = sp->prompt; + + rl_readline_state = sp->rlstate; + rl_done = sp->done; + _rl_keymap = sp->kmap; + + rl_last_func = sp->lastfunc; + rl_insert_mode = sp->insmode; + rl_editing_mode = sp->edmode; + rl_key_sequence_length = sp->kseqlen; + rl_instream = sp->inf; + rl_outstream = sp->outf; + rl_pending_input = sp->pendingin; + rl_executing_macro = sp->macro; + + rl_catch_signals = sp->catchsigs; + rl_catch_sigwinch = sp->catchsigwinch; + + return (0); +} diff --git a/readline/readline-4.3/readline.h b/readline/readline-4.3/readline.h new file mode 100644 index 00000000..f11b3d03 --- /dev/null +++ b/readline/readline-4.3/readline.h @@ -0,0 +1,799 @@ +/* Readline.h -- the names of functions callable from within readline. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_READLINE_H_) +#define _READLINE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (READLINE_LIBRARY) +# include "rlstdc.h" +# include "rltypedefs.h" +# include "keymaps.h" +# include "tilde.h" +#else +# include +# include +# include +# include +#endif + +/* Hex-encoded Readline version number. */ +#define RL_READLINE_VERSION 0x0403 /* Readline 4.3 */ +#define RL_VERSION_MAJOR 4 +#define RL_VERSION_MINOR 3 + +/* Readline data structures. */ + +/* Maintaining the state of undo. We remember individual deletes and inserts + on a chain of things to do. */ + +/* The actions that undo knows how to undo. Notice that UNDO_DELETE means + to insert some text, and UNDO_INSERT means to delete some text. I.e., + the code tells undo what to undo, not how to undo it. */ +enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END }; + +/* What an element of THE_UNDO_LIST looks like. */ +typedef struct undo_list { + struct undo_list *next; + int start, end; /* Where the change took place. */ + char *text; /* The text to insert, if undoing a delete. */ + enum undo_code what; /* Delete, Insert, Begin, End. */ +} UNDO_LIST; + +/* The current undo list for RL_LINE_BUFFER. */ +extern UNDO_LIST *rl_undo_list; + +/* The data structure for mapping textual names to code addresses. */ +typedef struct _funmap { + const char *name; + rl_command_func_t *function; +} FUNMAP; + +extern FUNMAP **funmap; + +/* **************************************************************** */ +/* */ +/* Functions available to bind to key sequences */ +/* */ +/* **************************************************************** */ + +/* Bindable commands for numeric arguments. */ +extern int rl_digit_argument PARAMS((int, int)); +extern int rl_universal_argument PARAMS((int, int)); + +/* Bindable commands for moving the cursor. */ +extern int rl_forward_byte PARAMS((int, int)); +extern int rl_forward_char PARAMS((int, int)); +extern int rl_forward PARAMS((int, int)); +extern int rl_backward_byte PARAMS((int, int)); +extern int rl_backward_char PARAMS((int, int)); +extern int rl_backward PARAMS((int, int)); +extern int rl_beg_of_line PARAMS((int, int)); +extern int rl_end_of_line PARAMS((int, int)); +extern int rl_forward_word PARAMS((int, int)); +extern int rl_backward_word PARAMS((int, int)); +extern int rl_refresh_line PARAMS((int, int)); +extern int rl_clear_screen PARAMS((int, int)); +extern int rl_arrow_keys PARAMS((int, int)); + +/* Bindable commands for inserting and deleting text. */ +extern int rl_insert PARAMS((int, int)); +extern int rl_quoted_insert PARAMS((int, int)); +extern int rl_tab_insert PARAMS((int, int)); +extern int rl_newline PARAMS((int, int)); +extern int rl_do_lowercase_version PARAMS((int, int)); +extern int rl_rubout PARAMS((int, int)); +extern int rl_delete PARAMS((int, int)); +extern int rl_rubout_or_delete PARAMS((int, int)); +extern int rl_delete_horizontal_space PARAMS((int, int)); +extern int rl_delete_or_show_completions PARAMS((int, int)); +extern int rl_insert_comment PARAMS((int, int)); + +/* Bindable commands for changing case. */ +extern int rl_upcase_word PARAMS((int, int)); +extern int rl_downcase_word PARAMS((int, int)); +extern int rl_capitalize_word PARAMS((int, int)); + +/* Bindable commands for transposing characters and words. */ +extern int rl_transpose_words PARAMS((int, int)); +extern int rl_transpose_chars PARAMS((int, int)); + +/* Bindable commands for searching within a line. */ +extern int rl_char_search PARAMS((int, int)); +extern int rl_backward_char_search PARAMS((int, int)); + +/* Bindable commands for readline's interface to the command history. */ +extern int rl_beginning_of_history PARAMS((int, int)); +extern int rl_end_of_history PARAMS((int, int)); +extern int rl_get_next_history PARAMS((int, int)); +extern int rl_get_previous_history PARAMS((int, int)); + +/* Bindable commands for managing the mark and region. */ +extern int rl_set_mark PARAMS((int, int)); +extern int rl_exchange_point_and_mark PARAMS((int, int)); + +/* Bindable commands to set the editing mode (emacs or vi). */ +extern int rl_vi_editing_mode PARAMS((int, int)); +extern int rl_emacs_editing_mode PARAMS((int, int)); + +/* Bindable commands to change the insert mode (insert or overwrite) */ +extern int rl_overwrite_mode PARAMS((int, int)); + +/* Bindable commands for managing key bindings. */ +extern int rl_re_read_init_file PARAMS((int, int)); +extern int rl_dump_functions PARAMS((int, int)); +extern int rl_dump_macros PARAMS((int, int)); +extern int rl_dump_variables PARAMS((int, int)); + +/* Bindable commands for word completion. */ +extern int rl_complete PARAMS((int, int)); +extern int rl_possible_completions PARAMS((int, int)); +extern int rl_insert_completions PARAMS((int, int)); +extern int rl_menu_complete PARAMS((int, int)); + +/* Bindable commands for killing and yanking text, and managing the kill ring. */ +extern int rl_kill_word PARAMS((int, int)); +extern int rl_backward_kill_word PARAMS((int, int)); +extern int rl_kill_line PARAMS((int, int)); +extern int rl_backward_kill_line PARAMS((int, int)); +extern int rl_kill_full_line PARAMS((int, int)); +extern int rl_unix_word_rubout PARAMS((int, int)); +extern int rl_unix_line_discard PARAMS((int, int)); +extern int rl_copy_region_to_kill PARAMS((int, int)); +extern int rl_kill_region PARAMS((int, int)); +extern int rl_copy_forward_word PARAMS((int, int)); +extern int rl_copy_backward_word PARAMS((int, int)); +extern int rl_yank PARAMS((int, int)); +extern int rl_yank_pop PARAMS((int, int)); +extern int rl_yank_nth_arg PARAMS((int, int)); +extern int rl_yank_last_arg PARAMS((int, int)); +/* Not available unless __CYGWIN__ is defined. */ +#ifdef __CYGWIN__ +extern int rl_paste_from_clipboard PARAMS((int, int)); +#endif + +/* Bindable commands for incremental searching. */ +extern int rl_reverse_search_history PARAMS((int, int)); +extern int rl_forward_search_history PARAMS((int, int)); + +/* Bindable keyboard macro commands. */ +extern int rl_start_kbd_macro PARAMS((int, int)); +extern int rl_end_kbd_macro PARAMS((int, int)); +extern int rl_call_last_kbd_macro PARAMS((int, int)); + +/* Bindable undo commands. */ +extern int rl_revert_line PARAMS((int, int)); +extern int rl_undo_command PARAMS((int, int)); + +/* Bindable tilde expansion commands. */ +extern int rl_tilde_expand PARAMS((int, int)); + +/* Bindable terminal control commands. */ +extern int rl_restart_output PARAMS((int, int)); +extern int rl_stop_output PARAMS((int, int)); + +/* Miscellaneous bindable commands. */ +extern int rl_abort PARAMS((int, int)); +extern int rl_tty_status PARAMS((int, int)); + +/* Bindable commands for incremental and non-incremental history searching. */ +extern int rl_history_search_forward PARAMS((int, int)); +extern int rl_history_search_backward PARAMS((int, int)); +extern int rl_noninc_forward_search PARAMS((int, int)); +extern int rl_noninc_reverse_search PARAMS((int, int)); +extern int rl_noninc_forward_search_again PARAMS((int, int)); +extern int rl_noninc_reverse_search_again PARAMS((int, int)); + +/* Bindable command used when inserting a matching close character. */ +extern int rl_insert_close PARAMS((int, int)); + +/* Not available unless READLINE_CALLBACKS is defined. */ +extern void rl_callback_handler_install PARAMS((const char *, rl_vcpfunc_t *)); +extern void rl_callback_read_char PARAMS((void)); +extern void rl_callback_handler_remove PARAMS((void)); + +/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */ +/* VI-mode bindable commands. */ +extern int rl_vi_redo PARAMS((int, int)); +extern int rl_vi_undo PARAMS((int, int)); +extern int rl_vi_yank_arg PARAMS((int, int)); +extern int rl_vi_fetch_history PARAMS((int, int)); +extern int rl_vi_search_again PARAMS((int, int)); +extern int rl_vi_search PARAMS((int, int)); +extern int rl_vi_complete PARAMS((int, int)); +extern int rl_vi_tilde_expand PARAMS((int, int)); +extern int rl_vi_prev_word PARAMS((int, int)); +extern int rl_vi_next_word PARAMS((int, int)); +extern int rl_vi_end_word PARAMS((int, int)); +extern int rl_vi_insert_beg PARAMS((int, int)); +extern int rl_vi_append_mode PARAMS((int, int)); +extern int rl_vi_append_eol PARAMS((int, int)); +extern int rl_vi_eof_maybe PARAMS((int, int)); +extern int rl_vi_insertion_mode PARAMS((int, int)); +extern int rl_vi_movement_mode PARAMS((int, int)); +extern int rl_vi_arg_digit PARAMS((int, int)); +extern int rl_vi_change_case PARAMS((int, int)); +extern int rl_vi_put PARAMS((int, int)); +extern int rl_vi_column PARAMS((int, int)); +extern int rl_vi_delete_to PARAMS((int, int)); +extern int rl_vi_change_to PARAMS((int, int)); +extern int rl_vi_yank_to PARAMS((int, int)); +extern int rl_vi_delete PARAMS((int, int)); +extern int rl_vi_back_to_indent PARAMS((int, int)); +extern int rl_vi_first_print PARAMS((int, int)); +extern int rl_vi_char_search PARAMS((int, int)); +extern int rl_vi_match PARAMS((int, int)); +extern int rl_vi_change_char PARAMS((int, int)); +extern int rl_vi_subst PARAMS((int, int)); +extern int rl_vi_overstrike PARAMS((int, int)); +extern int rl_vi_overstrike_delete PARAMS((int, int)); +extern int rl_vi_replace PARAMS((int, int)); +extern int rl_vi_set_mark PARAMS((int, int)); +extern int rl_vi_goto_mark PARAMS((int, int)); + +/* VI-mode utility functions. */ +extern int rl_vi_check PARAMS((void)); +extern int rl_vi_domove PARAMS((int, int *)); +extern int rl_vi_bracktype PARAMS((int)); + +/* VI-mode pseudo-bindable commands, used as utility functions. */ +extern int rl_vi_fWord PARAMS((int, int)); +extern int rl_vi_bWord PARAMS((int, int)); +extern int rl_vi_eWord PARAMS((int, int)); +extern int rl_vi_fword PARAMS((int, int)); +extern int rl_vi_bword PARAMS((int, int)); +extern int rl_vi_eword PARAMS((int, int)); + +/* **************************************************************** */ +/* */ +/* Well Published Functions */ +/* */ +/* **************************************************************** */ + +/* Readline functions. */ +/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */ +extern char *readline PARAMS((const char *)); + +extern int rl_set_prompt PARAMS((const char *)); +extern int rl_expand_prompt PARAMS((char *)); + +extern int rl_initialize PARAMS((void)); + +/* Undocumented; unused by readline */ +extern int rl_discard_argument PARAMS((void)); + +/* Utility functions to bind keys to readline commands. */ +extern int rl_add_defun PARAMS((const char *, rl_command_func_t *, int)); +extern int rl_bind_key PARAMS((int, rl_command_func_t *)); +extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap)); +extern int rl_unbind_key PARAMS((int)); +extern int rl_unbind_key_in_map PARAMS((int, Keymap)); +extern int rl_unbind_function_in_map PARAMS((rl_command_func_t *, Keymap)); +extern int rl_unbind_command_in_map PARAMS((const char *, Keymap)); +extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap)); +extern int rl_generic_bind PARAMS((int, const char *, char *, Keymap)); +extern int rl_variable_bind PARAMS((const char *, const char *)); + +/* Backwards compatibility, use rl_generic_bind instead. */ +extern int rl_macro_bind PARAMS((const char *, const char *, Keymap)); + +/* Undocumented in the texinfo manual; not really useful to programs. */ +extern int rl_translate_keyseq PARAMS((const char *, char *, int *)); +extern char *rl_untranslate_keyseq PARAMS((int)); + +extern rl_command_func_t *rl_named_function PARAMS((const char *)); +extern rl_command_func_t *rl_function_of_keyseq PARAMS((const char *, Keymap, int *)); + +extern void rl_list_funmap_names PARAMS((void)); +extern char **rl_invoking_keyseqs_in_map PARAMS((rl_command_func_t *, Keymap)); +extern char **rl_invoking_keyseqs PARAMS((rl_command_func_t *)); + +extern void rl_function_dumper PARAMS((int)); +extern void rl_macro_dumper PARAMS((int)); +extern void rl_variable_dumper PARAMS((int)); + +extern int rl_read_init_file PARAMS((const char *)); +extern int rl_parse_and_bind PARAMS((char *)); + +/* Functions for manipulating keymaps. */ +extern Keymap rl_make_bare_keymap PARAMS((void)); +extern Keymap rl_copy_keymap PARAMS((Keymap)); +extern Keymap rl_make_keymap PARAMS((void)); +extern void rl_discard_keymap PARAMS((Keymap)); + +extern Keymap rl_get_keymap_by_name PARAMS((const char *)); +extern char *rl_get_keymap_name PARAMS((Keymap)); +extern void rl_set_keymap PARAMS((Keymap)); +extern Keymap rl_get_keymap PARAMS((void)); +/* Undocumented; used internally only. */ +extern void rl_set_keymap_from_edit_mode PARAMS((void)); +extern char *rl_get_keymap_name_from_edit_mode PARAMS((void)); + +/* Functions for manipulating the funmap, which maps command names to functions. */ +extern int rl_add_funmap_entry PARAMS((const char *, rl_command_func_t *)); +extern const char **rl_funmap_names PARAMS((void)); +/* Undocumented, only used internally -- there is only one funmap, and this + function may be called only once. */ +extern void rl_initialize_funmap PARAMS((void)); + +/* Utility functions for managing keyboard macros. */ +extern void rl_push_macro_input PARAMS((char *)); + +/* Functions for undoing, from undo.c */ +extern void rl_add_undo PARAMS((enum undo_code, int, int, char *)); +extern void rl_free_undo_list PARAMS((void)); +extern int rl_do_undo PARAMS((void)); +extern int rl_begin_undo_group PARAMS((void)); +extern int rl_end_undo_group PARAMS((void)); +extern int rl_modifying PARAMS((int, int)); + +/* Functions for redisplay. */ +extern void rl_redisplay PARAMS((void)); +extern int rl_on_new_line PARAMS((void)); +extern int rl_on_new_line_with_prompt PARAMS((void)); +extern int rl_forced_update_display PARAMS((void)); +extern int rl_clear_message PARAMS((void)); +extern int rl_reset_line_state PARAMS((void)); +extern int rl_crlf PARAMS((void)); + +#if (defined (__STDC__) || defined (__cplusplus)) && defined (USE_VARARGS) && defined (PREFER_STDARG) +extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2))); +#else +extern int rl_message (); +#endif + +extern int rl_show_char PARAMS((int)); + +/* Undocumented in texinfo manual. */ +extern int rl_character_len PARAMS((int, int)); + +/* Save and restore internal prompt redisplay information. */ +extern void rl_save_prompt PARAMS((void)); +extern void rl_restore_prompt PARAMS((void)); + +/* Modifying text. */ +extern void rl_replace_line PARAMS((const char *, int)); +extern int rl_insert_text PARAMS((const char *)); +extern int rl_delete_text PARAMS((int, int)); +extern int rl_kill_text PARAMS((int, int)); +extern char *rl_copy_text PARAMS((int, int)); + +/* Terminal and tty mode management. */ +extern void rl_prep_terminal PARAMS((int)); +extern void rl_deprep_terminal PARAMS((void)); +extern void rl_tty_set_default_bindings PARAMS((Keymap)); + +extern int rl_reset_terminal PARAMS((const char *)); +extern void rl_resize_terminal PARAMS((void)); +extern void rl_set_screen_size PARAMS((int, int)); +extern void rl_get_screen_size PARAMS((int *, int *)); + +extern char *rl_get_termcap PARAMS((const char *)); + +/* Functions for character input. */ +extern int rl_stuff_char PARAMS((int)); +extern int rl_execute_next PARAMS((int)); +extern int rl_clear_pending_input PARAMS((void)); +extern int rl_read_key PARAMS((void)); +extern int rl_getc PARAMS((FILE *)); +extern int rl_set_keyboard_input_timeout PARAMS((int)); + +/* `Public' utility functions . */ +extern void rl_extend_line_buffer PARAMS((int)); +extern int rl_ding PARAMS((void)); +extern int rl_alphabetic PARAMS((int)); + +/* Readline signal handling, from signals.c */ +extern int rl_set_signals PARAMS((void)); +extern int rl_clear_signals PARAMS((void)); +extern void rl_cleanup_after_signal PARAMS((void)); +extern void rl_reset_after_signal PARAMS((void)); +extern void rl_free_line_state PARAMS((void)); + +extern int rl_set_paren_blink_timeout PARAMS((int)); + +/* Undocumented. */ +extern int rl_maybe_save_line PARAMS((void)); +extern int rl_maybe_unsave_line PARAMS((void)); +extern int rl_maybe_replace_line PARAMS((void)); + +/* Completion functions. */ +extern int rl_complete_internal PARAMS((int)); +extern void rl_display_match_list PARAMS((char **, int, int)); + +extern char **rl_completion_matches PARAMS((const char *, rl_compentry_func_t *)); +extern char *rl_username_completion_function PARAMS((const char *, int)); +extern char *rl_filename_completion_function PARAMS((const char *, int)); + +extern int rl_completion_mode PARAMS((rl_command_func_t *)); + +#if 0 +/* Backwards compatibility (compat.c). These will go away sometime. */ +extern void free_undo_list PARAMS((void)); +extern int maybe_save_line PARAMS((void)); +extern int maybe_unsave_line PARAMS((void)); +extern int maybe_replace_line PARAMS((void)); + +extern int ding PARAMS((void)); +extern int alphabetic PARAMS((int)); +extern int crlf PARAMS((void)); + +extern char **completion_matches PARAMS((char *, rl_compentry_func_t *)); +extern char *username_completion_function PARAMS((const char *, int)); +extern char *filename_completion_function PARAMS((const char *, int)); +#endif + +/* **************************************************************** */ +/* */ +/* Well Published Variables */ +/* */ +/* **************************************************************** */ + +/* The version of this incarnation of the readline library. */ +extern const char *rl_library_version; /* e.g., "4.2" */ +extern int rl_readline_version; /* e.g., 0x0402 */ + +/* True if this is real GNU readline. */ +extern int rl_gnu_readline_p; + +/* Flags word encapsulating the current readline state. */ +extern int rl_readline_state; + +/* Says which editing mode readline is currently using. 1 means emacs mode; + 0 means vi mode. */ +extern int rl_editing_mode; + +/* Insert or overwrite mode for emacs mode. 1 means insert mode; 0 means + overwrite mode. Reset to insert mode on each input line. */ +extern int rl_insert_mode; + +/* The name of the calling program. You should initialize this to + whatever was in argv[0]. It is used when parsing conditionals. */ +extern const char *rl_readline_name; + +/* The prompt readline uses. This is set from the argument to + readline (), and should not be assigned to directly. */ +extern char *rl_prompt; + +/* The line buffer that is in use. */ +extern char *rl_line_buffer; + +/* The location of point, and end. */ +extern int rl_point; +extern int rl_end; + +/* The mark, or saved cursor position. */ +extern int rl_mark; + +/* Flag to indicate that readline has finished with the current input + line and should return it. */ +extern int rl_done; + +/* If set to a character value, that will be the next keystroke read. */ +extern int rl_pending_input; + +/* Non-zero if we called this function from _rl_dispatch(). It's present + so functions can find out whether they were called from a key binding + or directly from an application. */ +extern int rl_dispatching; + +/* Non-zero if the user typed a numeric argument before executing the + current function. */ +extern int rl_explicit_arg; + +/* The current value of the numeric argument specified by the user. */ +extern int rl_numeric_arg; + +/* The address of the last command function Readline executed. */ +extern rl_command_func_t *rl_last_func; + +/* The name of the terminal to use. */ +extern const char *rl_terminal_name; + +/* The input and output streams. */ +extern FILE *rl_instream; +extern FILE *rl_outstream; + +/* If non-zero, then this is the address of a function to call just + before readline_internal () prints the first prompt. */ +extern rl_hook_func_t *rl_startup_hook; + +/* If non-zero, this is the address of a function to call just before + readline_internal_setup () returns and readline_internal starts + reading input characters. */ +extern rl_hook_func_t *rl_pre_input_hook; + +/* The address of a function to call periodically while Readline is + awaiting character input, or NULL, for no event handling. */ +extern rl_hook_func_t *rl_event_hook; + +/* The address of the function to call to fetch a character from the current + Readline input stream */ +extern rl_getc_func_t *rl_getc_function; + +extern rl_voidfunc_t *rl_redisplay_function; + +extern rl_vintfunc_t *rl_prep_term_function; +extern rl_voidfunc_t *rl_deprep_term_function; + +/* Dispatch variables. */ +extern Keymap rl_executing_keymap; +extern Keymap rl_binding_keymap; + +/* Display variables. */ +/* If non-zero, readline will erase the entire line, including any prompt, + if the only thing typed on an otherwise-blank line is something bound to + rl_newline. */ +extern int rl_erase_empty_line; + +/* If non-zero, the application has already printed the prompt (rl_prompt) + before calling readline, so readline should not output it the first time + redisplay is done. */ +extern int rl_already_prompted; + +/* A non-zero value means to read only this many characters rather than + up to a character bound to accept-line. */ +extern int rl_num_chars_to_read; + +/* The text of a currently-executing keyboard macro. */ +extern char *rl_executing_macro; + +/* Variables to control readline signal handling. */ +/* If non-zero, readline will install its own signal handlers for + SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */ +extern int rl_catch_signals; + +/* If non-zero, readline will install a signal handler for SIGWINCH + that also attempts to call any calling application's SIGWINCH signal + handler. Note that the terminal is not cleaned up before the + application's signal handler is called; use rl_cleanup_after_signal() + to do that. */ +extern int rl_catch_sigwinch; + +/* Completion variables. */ +/* Pointer to the generator function for completion_matches (). + NULL means to use rl_filename_completion_function (), the default + filename completer. */ +extern rl_compentry_func_t *rl_completion_entry_function; + +/* If rl_ignore_some_completions_function is non-NULL it is the address + of a function to call after all of the possible matches have been + generated, but before the actual completion is done to the input line. + The function is called with one argument; a NULL terminated array + of (char *). If your function removes any of the elements, they + must be free()'ed. */ +extern rl_compignore_func_t *rl_ignore_some_completions_function; + +/* Pointer to alternative function to create matches. + Function is called with TEXT, START, and END. + START and END are indices in RL_LINE_BUFFER saying what the boundaries + of TEXT are. + If this function exists and returns NULL then call the value of + rl_completion_entry_function to try to match, otherwise use the + array of strings returned. */ +extern rl_completion_func_t *rl_attempted_completion_function; + +/* The basic list of characters that signal a break between words for the + completer routine. The initial contents of this variable is what + breaks words in the shell, i.e. "n\"\\'`@$>". */ +extern const char *rl_basic_word_break_characters; + +/* The list of characters that signal a break between words for + rl_complete_internal. The default list is the contents of + rl_basic_word_break_characters. */ +extern const char *rl_completer_word_break_characters; + +/* List of characters which can be used to quote a substring of the line. + Completion occurs on the entire substring, and within the substring + rl_completer_word_break_characters are treated as any other character, + unless they also appear within this list. */ +extern const char *rl_completer_quote_characters; + +/* List of quote characters which cause a word break. */ +extern const char *rl_basic_quote_characters; + +/* List of characters that need to be quoted in filenames by the completer. */ +extern const char *rl_filename_quote_characters; + +/* List of characters that are word break characters, but should be left + in TEXT when it is passed to the completion function. The shell uses + this to help determine what kind of completing to do. */ +extern const char *rl_special_prefixes; + +/* If non-zero, then this is the address of a function to call when + completing on a directory name. The function is called with + the address of a string (the current directory name) as an arg. It + changes what is displayed when the possible completions are printed + or inserted. */ +extern rl_icppfunc_t *rl_directory_completion_hook; + +/* If non-zero, this is the address of a function to call when completing + a directory name. This function takes the address of the directory name + to be modified as an argument. Unlike rl_directory_completion_hook, it + only modifies the directory name used in opendir(2), not what is displayed + when the possible completions are printed or inserted. It is called + before rl_directory_completion_hook. I'm not happy with how this works + yet, so it's undocumented. */ +extern rl_icppfunc_t *rl_directory_rewrite_hook; + +/* Backwards compatibility with previous versions of readline. */ +#define rl_symbolic_link_hook rl_directory_completion_hook + +/* If non-zero, then this is the address of a function to call when + completing a word would normally display the list of possible matches. + This function is called instead of actually doing the display. + It takes three arguments: (char **matches, int num_matches, int max_length) + where MATCHES is the array of strings that matched, NUM_MATCHES is the + number of strings in that array, and MAX_LENGTH is the length of the + longest string in that array. */ +extern rl_compdisp_func_t *rl_completion_display_matches_hook; + +/* Non-zero means that the results of the matches are to be treated + as filenames. This is ALWAYS zero on entry, and can only be changed + within a completion entry finder function. */ +extern int rl_filename_completion_desired; + +/* Non-zero means that the results of the matches are to be quoted using + double quotes (or an application-specific quoting mechanism) if the + filename contains any characters in rl_word_break_chars. This is + ALWAYS non-zero on entry, and can only be changed within a completion + entry finder function. */ +extern int rl_filename_quoting_desired; + +/* Set to a function to quote a filename in an application-specific fashion. + Called with the text to quote, the type of match found (single or multiple) + and a pointer to the quoting character to be used, which the function can + reset if desired. */ +extern rl_quote_func_t *rl_filename_quoting_function; + +/* Function to call to remove quoting characters from a filename. Called + before completion is attempted, so the embedded quotes do not interfere + with matching names in the file system. */ +extern rl_dequote_func_t *rl_filename_dequoting_function; + +/* Function to call to decide whether or not a word break character is + quoted. If a character is quoted, it does not break words for the + completer. */ +extern rl_linebuf_func_t *rl_char_is_quoted_p; + +/* Non-zero means to suppress normal filename completion after the + user-specified completion function has been called. */ +extern int rl_attempted_completion_over; + +/* Set to a character describing the type of completion being attempted by + rl_complete_internal; available for use by application completion + functions. */ +extern int rl_completion_type; + +/* Character appended to completed words when at the end of the line. The + default is a space. Nothing is added if this is '\0'. */ +extern int rl_completion_append_character; + +/* If set to non-zero by an application completion function, + rl_completion_append_character will not be appended. */ +extern int rl_completion_suppress_append; + +/* Up to this many items will be displayed in response to a + possible-completions call. After that, we ask the user if she + is sure she wants to see them all. The default value is 100. */ +extern int rl_completion_query_items; + +/* If non-zero, a slash will be appended to completed filenames that are + symbolic links to directory names, subject to the value of the + mark-directories variable (which is user-settable). This exists so + that application completion functions can override the user's preference + (set via the mark-symlinked-directories variable) if appropriate. + It's set to the value of _rl_complete_mark_symlink_dirs in + rl_complete_internal before any application-specific completion + function is called, so without that function doing anything, the user's + preferences are honored. */ +extern int rl_completion_mark_symlink_dirs; + +/* If non-zero, then disallow duplicates in the matches. */ +extern int rl_ignore_completion_duplicates; + +/* If this is non-zero, completion is (temporarily) inhibited, and the + completion character will be inserted as any other. */ +extern int rl_inhibit_completion; + +/* Definitions available for use by readline clients. */ +#define RL_PROMPT_START_IGNORE '\001' +#define RL_PROMPT_END_IGNORE '\002' + +/* Possible values for do_replace argument to rl_filename_quoting_function, + called by rl_complete_internal. */ +#define NO_MATCH 0 +#define SINGLE_MATCH 1 +#define MULT_MATCH 2 + +/* Possible state values for rl_readline_state */ +#define RL_STATE_NONE 0x00000 /* no state; before first call */ + +#define RL_STATE_INITIALIZING 0x00001 /* initializing */ +#define RL_STATE_INITIALIZED 0x00002 /* initialization done */ +#define RL_STATE_TERMPREPPED 0x00004 /* terminal is prepped */ +#define RL_STATE_READCMD 0x00008 /* reading a command key */ +#define RL_STATE_METANEXT 0x00010 /* reading input after ESC */ +#define RL_STATE_DISPATCHING 0x00020 /* dispatching to a command */ +#define RL_STATE_MOREINPUT 0x00040 /* reading more input in a command function */ +#define RL_STATE_ISEARCH 0x00080 /* doing incremental search */ +#define RL_STATE_NSEARCH 0x00100 /* doing non-inc search */ +#define RL_STATE_SEARCH 0x00200 /* doing a history search */ +#define RL_STATE_NUMERICARG 0x00400 /* reading numeric argument */ +#define RL_STATE_MACROINPUT 0x00800 /* getting input from a macro */ +#define RL_STATE_MACRODEF 0x01000 /* defining keyboard macro */ +#define RL_STATE_OVERWRITE 0x02000 /* overwrite mode */ +#define RL_STATE_COMPLETING 0x04000 /* doing completion */ +#define RL_STATE_SIGHANDLER 0x08000 /* in readline sighandler */ +#define RL_STATE_UNDOING 0x10000 /* doing an undo */ +#define RL_STATE_INPUTPENDING 0x20000 /* rl_execute_next called */ + +#define RL_STATE_DONE 0x80000 /* done; accepted line */ + +#define RL_SETSTATE(x) (rl_readline_state |= (x)) +#define RL_UNSETSTATE(x) (rl_readline_state &= ~(x)) +#define RL_ISSTATE(x) (rl_readline_state & (x)) + +struct readline_state { + /* line state */ + int point; + int end; + int mark; + char *buffer; + int buflen; + UNDO_LIST *ul; + char *prompt; + + /* global state */ + int rlstate; + int done; + Keymap kmap; + + /* input state */ + rl_command_func_t *lastfunc; + int insmode; + int edmode; + int kseqlen; + FILE *inf; + FILE *outf; + int pendingin; + char *macro; + + /* signal state */ + int catchsigs; + int catchsigwinch; + + /* reserved for future expansion, so the struct size doesn't change */ + char reserved[64]; +}; + +extern int rl_save_state PARAMS((struct readline_state *)); +extern int rl_restore_state PARAMS((struct readline_state *)); + +#ifdef __cplusplus +} +#endif + +#endif /* _READLINE_H_ */ diff --git a/readline/readline-4.3/rlconf.h b/readline/readline-4.3/rlconf.h new file mode 100644 index 00000000..c651fd8b --- /dev/null +++ b/readline/readline-4.3/rlconf.h @@ -0,0 +1,60 @@ +/* rlconf.h -- readline configuration definitions */ + +/* Copyright (C) 1994 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RLCONF_H_) +#define _RLCONF_H_ + +/* Define this if you want the vi-mode editing available. */ +#define VI_MODE + +/* Define this to get an indication of file type when listing completions. */ +#define VISIBLE_STATS + +/* This definition is needed by readline.c, rltty.c, and signals.c. */ +/* If on, then readline handles signals in a way that doesn't screw. */ +#define HANDLE_SIGNALS + +/* Ugly but working hack for binding prefix meta. */ +#define PREFIX_META_HACK + +/* The final, last-ditch effort file name for an init file. */ +#define DEFAULT_INPUTRC "~/.inputrc" + +/* If defined, expand tabs to spaces. */ +#define DISPLAY_TABS + +/* If defined, use the terminal escape sequence to move the cursor forward + over a character when updating the line rather than rewriting it. */ +/* #define HACK_TERMCAP_MOTION */ + +/* The string inserted by the `insert comment' command. */ +#define RL_COMMENT_BEGIN_DEFAULT "#" + +/* Define this if you want code that allows readline to be used in an + X `callback' style. */ +#define READLINE_CALLBACKS + +/* Define this if you want the cursor to indicate insert or overwrite mode. */ +/* #define CURSOR_MODE */ + +#endif /* _RLCONF_H_ */ diff --git a/readline/readline-4.3/rldefs.h b/readline/readline-4.3/rldefs.h new file mode 100644 index 00000000..4a28bd1e --- /dev/null +++ b/readline/readline-4.3/rldefs.h @@ -0,0 +1,156 @@ +/* rldefs.h -- an attempt to isolate some of the system-specific defines + for readline. This should be included after any files that define + system-specific constants like _POSIX_VERSION or USG. */ + +/* Copyright (C) 1987,1989 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RLDEFS_H_) +#define _RLDEFS_H_ + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#include "rlstdc.h" + +#if defined (_POSIX_VERSION) && !defined (TERMIOS_MISSING) +# define TERMIOS_TTY_DRIVER +#else +# if defined (HAVE_TERMIO_H) +# define TERMIO_TTY_DRIVER +# else +# define NEW_TTY_DRIVER +# endif +#endif + +/* Posix macro to check file in statbuf for directory-ness. + This requires that be included before this test. */ +#if defined (S_IFDIR) && !defined (S_ISDIR) +# define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) +#endif + +/* Decide which flavor of the header file describing the C library + string functions to include and include it. */ + +#if defined (HAVE_STRING_H) +# include +#else /* !HAVE_STRING_H */ +# include +#endif /* !HAVE_STRING_H */ + +#if !defined (strchr) && !defined (__STDC__) +extern char *strchr (), *strrchr (); +#endif /* !strchr && !__STDC__ */ + +#if defined (PREFER_STDARG) +# include +#else +# if defined (PREFER_VARARGS) +# include +# endif +#endif + +#if defined (HAVE_STRCASECMP) +#define _rl_stricmp strcasecmp +#define _rl_strnicmp strncasecmp +#else +extern int _rl_stricmp PARAMS((char *, char *)); +extern int _rl_strnicmp PARAMS((char *, char *, int)); +#endif + +#if defined (HAVE_STRPBRK) +# define _rl_strpbrk(a,b) strpbrk((a),(b)) +#else +extern char *_rl_strpbrk PARAMS((const char *, const char *)); +#endif + +#if !defined (emacs_mode) +# define no_mode -1 +# define vi_mode 0 +# define emacs_mode 1 +#endif + +#if !defined (RL_IM_INSERT) +# define RL_IM_INSERT 1 +# define RL_IM_OVERWRITE 0 +# +# define RL_IM_DEFAULT RL_IM_INSERT +#endif + +/* If you cast map[key].function to type (Keymap) on a Cray, + the compiler takes the value of map[key].function and + divides it by 4 to convert between pointer types (pointers + to functions and pointers to structs are different sizes). + This is not what is wanted. */ +#if defined (CRAY) +# define FUNCTION_TO_KEYMAP(map, key) (Keymap)((int)map[key].function) +# define KEYMAP_TO_FUNCTION(data) (rl_command_func_t *)((int)(data)) +#else +# define FUNCTION_TO_KEYMAP(map, key) (Keymap)(map[key].function) +# define KEYMAP_TO_FUNCTION(data) (rl_command_func_t *)(data) +#endif + +#ifndef savestring +#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x)) +#endif + +/* Possible values for _rl_bell_preference. */ +#define NO_BELL 0 +#define AUDIBLE_BELL 1 +#define VISIBLE_BELL 2 + +/* Definitions used when searching the line for characters. */ +/* NOTE: it is necessary that opposite directions are inverses */ +#define FTO 1 /* forward to */ +#define BTO -1 /* backward to */ +#define FFIND 2 /* forward find */ +#define BFIND -2 /* backward find */ + +/* Possible values for the found_quote flags word used by the completion + functions. It says what kind of (shell-like) quoting we found anywhere + in the line. */ +#define RL_QF_SINGLE_QUOTE 0x01 +#define RL_QF_DOUBLE_QUOTE 0x02 +#define RL_QF_BACKSLASH 0x04 +#define RL_QF_OTHER_QUOTE 0x08 + +/* Default readline line buffer length. */ +#define DEFAULT_BUFFER_SIZE 256 + +#if !defined (STREQ) +#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0)) +#define STREQN(a, b, n) (((n) == 0) ? (1) \ + : ((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0)) +#endif + +#if !defined (FREE) +# define FREE(x) if (x) free (x) +#endif + +#if !defined (SWAP) +# define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) +#endif + +/* CONFIGURATION SECTION */ +#include "rlconf.h" + +#endif /* !_RLDEFS_H_ */ diff --git a/readline/readline-4.3/rlmbutil.h b/readline/readline-4.3/rlmbutil.h new file mode 100644 index 00000000..27ca32bf --- /dev/null +++ b/readline/readline-4.3/rlmbutil.h @@ -0,0 +1,108 @@ +/* rlmbutil.h -- utility functions for multibyte characters. */ + +/* Copyright (C) 2001 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RL_MBUTIL_H_) +#define _RL_MBUTIL_H_ + +#include "rlstdc.h" + +/************************************************/ +/* check multibyte capability for I18N code */ +/************************************************/ + +/* For platforms which support the ISO C amendement 1 functionality we + support user defined character classes. */ + /* Solaris 2.5 has a bug: must be included before . */ +#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H) +# include +# include +# if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */ +# define HANDLE_MULTIBYTE 1 +# endif +#endif + +/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ +#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T) +# define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0) +# define mbsrtowcs(dest, src, len, ps) (mbsrtowcs) (dest, src, len, 0) +# define wcrtomb(s, wc, ps) (wcrtomb) (s, wc, 0) +# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) +# define mbrlen(s, n, ps) (mbrlen) (s, n, 0) +# define mbstate_t int +#endif + +/* Make sure MB_LEN_MAX is at least 16 on systems that claim to be able to + handle multibyte chars (some systems define MB_LEN_MAX as 1) */ +#ifdef HANDLE_MULTIBYTE +# include +# if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16) +# undef MB_LEN_MAX +# endif +# if !defined (MB_LEN_MAX) +# define MB_LEN_MAX 16 +# endif +#endif + +/************************************************/ +/* end of multibyte capability checks for I18N */ +/************************************************/ + +/* + * Flags for _rl_find_prev_mbchar and _rl_find_next_mbchar: + * + * MB_FIND_ANY find any multibyte character + * MB_FIND_NONZERO find a non-zero-width multibyte character + */ + +#define MB_FIND_ANY 0x00 +#define MB_FIND_NONZERO 0x01 + +extern int _rl_find_prev_mbchar PARAMS((char *, int, int)); +extern int _rl_find_next_mbchar PARAMS((char *, int, int, int)); + +#ifdef HANDLE_MULTIBYTE + +extern int _rl_compare_chars PARAMS((char *, int, mbstate_t *, char *, int, mbstate_t *)); +extern int _rl_get_char_len PARAMS((char *, mbstate_t *)); +extern int _rl_adjust_point PARAMS((char *, int, mbstate_t *)); + +extern int _rl_read_mbchar PARAMS((char *, int)); +extern int _rl_read_mbstring PARAMS((int, char *, int)); + +extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int)); + +#else /* !HANDLE_MULTIBYTE */ + +#undef MB_LEN_MAX +#undef MB_CUR_MAX + +#define MB_LEN_MAX 1 +#define MB_CUR_MAX 1 + +#define _rl_find_prev_mbchar(b, i, f) (((i) == 0) ? (i) : ((i) - 1)) +#define _rl_find_next_mbchar(b, i1, i2, f) ((i1) + (i2)) + +#endif /* !HANDLE_MULTIBYTE */ + +extern int rl_byte_oriented; + +#endif /* _RL_MBUTIL_H_ */ diff --git a/readline/readline-4.3/rlprivate.h b/readline/readline-4.3/rlprivate.h new file mode 100644 index 00000000..ccb91446 --- /dev/null +++ b/readline/readline-4.3/rlprivate.h @@ -0,0 +1,284 @@ +/* rlprivate.h -- functions and variables global to the readline library, + but not intended for use by applications. */ + +/* Copyright (C) 1999 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RL_PRIVATE_H_) +#define _RL_PRIVATE_H_ + +#include "rlconf.h" /* for VISIBLE_STATS */ +#include "rlstdc.h" +#include "posixjmp.h" /* defines procenv_t */ + +/************************************************************************* + * * + * Global functions undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ + +/************************************************************************* + * * + * Global variables undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ + +/* complete.c */ +extern int rl_complete_with_tilde_expansion; +#if defined (VISIBLE_STATS) +extern int rl_visible_stats; +#endif /* VISIBLE_STATS */ + +/* readline.c */ +extern int rl_line_buffer_len; +extern int rl_arg_sign; +extern int rl_visible_prompt_length; +extern int readline_echoing_p; +extern int rl_key_sequence_length; +extern int rl_byte_oriented; + +/* display.c */ +extern int rl_display_fixed; + +/* parens.c */ +extern int rl_blink_matching_paren; + +/************************************************************************* + * * + * Global functions and variables unsed and undocumented * + * * + *************************************************************************/ + +/* kill.c */ +extern int rl_set_retained_kills PARAMS((int)); + +/* terminal.c */ +extern void _rl_set_screen_size PARAMS((int, int)); + +/* undo.c */ +extern int _rl_fix_last_undo_of_type PARAMS((int, int, int)); + +/* util.c */ +extern char *_rl_savestring PARAMS((const char *)); + +/************************************************************************* + * * + * Functions and variables private to the readline library * + * * + *************************************************************************/ + +/* NOTE: Functions and variables prefixed with `_rl_' are + pseudo-global: they are global so they can be shared + between files in the readline library, but are not intended + to be visible to readline callers. */ + +/************************************************************************* + * Undocumented private functions * + *************************************************************************/ + +#if defined(READLINE_CALLBACKS) + +/* readline.c */ +extern void readline_internal_setup PARAMS((void)); +extern char *readline_internal_teardown PARAMS((int)); +extern int readline_internal_char PARAMS((void)); + +#endif /* READLINE_CALLBACKS */ + +/* bind.c */ +extern void _rl_bind_if_unbound PARAMS((const char *, rl_command_func_t *)); + +/* complete.c */ +extern char _rl_find_completion_word PARAMS((int *, int *)); +extern void _rl_free_match_list PARAMS((char **)); + +/* display.c */ +extern char *_rl_strip_prompt PARAMS((char *)); +extern void _rl_move_cursor_relative PARAMS((int, const char *)); +extern void _rl_move_vert PARAMS((int)); +extern void _rl_save_prompt PARAMS((void)); +extern void _rl_restore_prompt PARAMS((void)); +extern char *_rl_make_prompt_for_search PARAMS((int)); +extern void _rl_erase_at_end_of_line PARAMS((int)); +extern void _rl_clear_to_eol PARAMS((int)); +extern void _rl_clear_screen PARAMS((void)); +extern void _rl_update_final PARAMS((void)); +extern void _rl_redisplay_after_sigwinch PARAMS((void)); +extern void _rl_clean_up_for_exit PARAMS((void)); +extern void _rl_erase_entire_line PARAMS((void)); +extern int _rl_current_display_line PARAMS((void)); + +/* input.c */ +extern int _rl_any_typein PARAMS((void)); +extern int _rl_input_available PARAMS((void)); +extern int _rl_input_queued PARAMS((int)); +extern void _rl_insert_typein PARAMS((int)); +extern int _rl_unget_char PARAMS((int)); + +/* macro.c */ +extern void _rl_with_macro_input PARAMS((char *)); +extern int _rl_next_macro_key PARAMS((void)); +extern void _rl_push_executing_macro PARAMS((void)); +extern void _rl_pop_executing_macro PARAMS((void)); +extern void _rl_add_macro_char PARAMS((int)); +extern void _rl_kill_kbd_macro PARAMS((void)); + +/* misc.c */ +extern int _rl_init_argument PARAMS((void)); +extern void _rl_start_using_history PARAMS((void)); +extern int _rl_free_saved_history_line PARAMS((void)); +extern void _rl_set_insert_mode PARAMS((int, int)); + +/* nls.c */ +extern int _rl_init_eightbit PARAMS((void)); + +/* parens.c */ +extern void _rl_enable_paren_matching PARAMS((int)); + +/* readline.c */ +extern void _rl_init_line_state PARAMS((void)); +extern void _rl_set_the_line PARAMS((void)); +extern int _rl_dispatch PARAMS((int, Keymap)); +extern int _rl_dispatch_subseq PARAMS((int, Keymap, int)); + +/* rltty.c */ +extern int _rl_disable_tty_signals PARAMS((void)); +extern int _rl_restore_tty_signals PARAMS((void)); + +/* terminal.c */ +extern void _rl_get_screen_size PARAMS((int, int)); +extern int _rl_init_terminal_io PARAMS((const char *)); +#ifdef _MINIX +extern void _rl_output_character_function PARAMS((int)); +#else +extern int _rl_output_character_function PARAMS((int)); +#endif +extern void _rl_output_some_chars PARAMS((const char *, int)); +extern int _rl_backspace PARAMS((int)); +extern void _rl_enable_meta_key PARAMS((void)); +extern void _rl_control_keypad PARAMS((int)); +extern void _rl_set_cursor PARAMS((int, int)); + +/* text.c */ +extern void _rl_fix_point PARAMS((int)); +extern int _rl_replace_text PARAMS((const char *, int, int)); +extern int _rl_insert_char PARAMS((int, int)); +extern int _rl_overwrite_char PARAMS((int, int)); +extern int _rl_overwrite_rubout PARAMS((int, int)); +extern int _rl_rubout_char PARAMS((int, int)); +#if defined (HANDLE_MULTIBYTE) +extern int _rl_char_search_internal PARAMS((int, int, char *, int)); +#else +extern int _rl_char_search_internal PARAMS((int, int, int)); +#endif +extern int _rl_set_mark_at_pos PARAMS((int)); + +/* util.c */ +extern int _rl_abort_internal PARAMS((void)); +extern char *_rl_strindex PARAMS((const char *, const char *)); +extern int _rl_qsort_string_compare PARAMS((char **, char **)); +extern int (_rl_uppercase_p) PARAMS((int)); +extern int (_rl_lowercase_p) PARAMS((int)); +extern int (_rl_pure_alphabetic) PARAMS((int)); +extern int (_rl_digit_p) PARAMS((int)); +extern int (_rl_to_lower) PARAMS((int)); +extern int (_rl_to_upper) PARAMS((int)); +extern int (_rl_digit_value) PARAMS((int)); + +/* vi_mode.c */ +extern void _rl_vi_initialize_line PARAMS((void)); +extern void _rl_vi_reset_last PARAMS((void)); +extern void _rl_vi_set_last PARAMS((int, int, int)); +extern int _rl_vi_textmod_command PARAMS((int)); +extern void _rl_vi_done_inserting PARAMS((void)); + +/************************************************************************* + * Undocumented private variables * + *************************************************************************/ + +/* bind.c */ +extern const char *_rl_possible_control_prefixes[]; +extern const char *_rl_possible_meta_prefixes[]; + +/* complete.c */ +extern int _rl_complete_show_all; +extern int _rl_complete_mark_directories; +extern int _rl_complete_mark_symlink_dirs; +extern int _rl_print_completions_horizontally; +extern int _rl_completion_case_fold; +extern int _rl_match_hidden_files; +extern int _rl_page_completions; + +/* display.c */ +extern int _rl_vis_botlin; +extern int _rl_last_c_pos; +extern int _rl_suppress_redisplay; +extern char *rl_display_prompt; + +/* isearch.c */ +extern char *_rl_isearch_terminators; + +/* macro.c */ +extern char *_rl_executing_macro; + +/* misc.c */ +extern int _rl_history_preserve_point; +extern int _rl_history_saved_point; + +/* readline.c */ +extern int _rl_horizontal_scroll_mode; +extern int _rl_mark_modified_lines; +extern int _rl_bell_preference; +extern int _rl_meta_flag; +extern int _rl_convert_meta_chars_to_ascii; +extern int _rl_output_meta_chars; +extern char *_rl_comment_begin; +extern unsigned char _rl_parsing_conditionalized_out; +extern Keymap _rl_keymap; +extern FILE *_rl_in_stream; +extern FILE *_rl_out_stream; +extern int _rl_last_command_was_kill; +extern int _rl_eof_char; +extern procenv_t readline_top_level; + +/* terminal.c */ +extern int _rl_enable_keypad; +extern int _rl_enable_meta; +extern char *_rl_term_clreol; +extern char *_rl_term_clrpag; +extern char *_rl_term_im; +extern char *_rl_term_ic; +extern char *_rl_term_ei; +extern char *_rl_term_DC; +extern char *_rl_term_up; +extern char *_rl_term_dc; +extern char *_rl_term_cr; +extern char *_rl_term_IC; +extern int _rl_screenheight; +extern int _rl_screenwidth; +extern int _rl_screenchars; +extern int _rl_terminal_can_insert; +extern int _rl_term_autowrap; + +/* undo.c */ +extern int _rl_doing_an_undo; +extern int _rl_undo_group_level; + +#endif /* _RL_PRIVATE_H_ */ diff --git a/readline/readline-4.3/rlshell.h b/readline/readline-4.3/rlshell.h new file mode 100644 index 00000000..3c03fbad --- /dev/null +++ b/readline/readline-4.3/rlshell.h @@ -0,0 +1,34 @@ +/* rlshell.h -- utility functions normally provided by bash. */ + +/* Copyright (C) 1999 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RL_SHELL_H_) +#define _RL_SHELL_H_ + +#include "rlstdc.h" + +extern char *sh_single_quote PARAMS((char *)); +extern void sh_set_lines_and_columns PARAMS((int, int)); +extern char *sh_get_env_value PARAMS((const char *)); +extern char *sh_get_home_dir PARAMS((void)); +extern int sh_unset_nodelay_mode PARAMS((int)); + +#endif /* _RL_SHELL_H_ */ diff --git a/readline/readline-4.3/rlstdc.h b/readline/readline-4.3/rlstdc.h new file mode 100644 index 00000000..d6a22b37 --- /dev/null +++ b/readline/readline-4.3/rlstdc.h @@ -0,0 +1,45 @@ +/* stdc.h -- macros to make source compile on both ANSI C and K&R C + compilers. */ + +/* Copyright (C) 1993 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + Bash is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with Bash; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RL_STDC_H_) +#define _RL_STDC_H_ + +/* Adapted from BSD /usr/include/sys/cdefs.h. */ + +/* A function can be defined using prototypes and compile on both ANSI C + and traditional C compilers with something like this: + extern char *func PARAMS((char *, char *, int)); */ + +#if !defined (PARAMS) +# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) +# define PARAMS(protos) protos +# else +# define PARAMS(protos) () +# endif +#endif + +#ifndef __attribute__ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ +# define __attribute__(x) +# endif +#endif + +#endif /* !_RL_STDC_H_ */ diff --git a/readline/readline-4.3/rltty.c b/readline/readline-4.3/rltty.c new file mode 100644 index 00000000..755efeba --- /dev/null +++ b/readline/readline-4.3/rltty.c @@ -0,0 +1,911 @@ +/* rltty.c -- functions to prepare and restore the terminal for readline's + use. */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include +#include +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#include "rldefs.h" + +#if defined (GWINSZ_IN_SYS_IOCTL) +# include +#endif /* GWINSZ_IN_SYS_IOCTL */ + +#include "rltty.h" +#include "readline.h" +#include "rlprivate.h" + +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal; +rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal; + +static void block_sigint PARAMS((void)); +static void release_sigint PARAMS((void)); + +static void set_winsize PARAMS((int)); + +/* **************************************************************** */ +/* */ +/* Signal Management */ +/* */ +/* **************************************************************** */ + +#if defined (HAVE_POSIX_SIGNALS) +static sigset_t sigint_set, sigint_oset; +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) +static int sigint_oldmask; +# endif /* HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + +static int sigint_blocked; + +/* Cause SIGINT to not be delivered until the corresponding call to + release_sigint(). */ +static void +block_sigint () +{ + if (sigint_blocked) + return; + +#if defined (HAVE_POSIX_SIGNALS) + sigemptyset (&sigint_set); + sigemptyset (&sigint_oset); + sigaddset (&sigint_set, SIGINT); + sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset); +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) + sigint_oldmask = sigblock (sigmask (SIGINT)); +# else /* !HAVE_BSD_SIGNALS */ +# if defined (HAVE_USG_SIGHOLD) + sighold (SIGINT); +# endif /* HAVE_USG_SIGHOLD */ +# endif /* !HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + + sigint_blocked = 1; +} + +/* Allow SIGINT to be delivered. */ +static void +release_sigint () +{ + if (sigint_blocked == 0) + return; + +#if defined (HAVE_POSIX_SIGNALS) + sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL); +#else +# if defined (HAVE_BSD_SIGNALS) + sigsetmask (sigint_oldmask); +# else /* !HAVE_BSD_SIGNALS */ +# if defined (HAVE_USG_SIGHOLD) + sigrelse (SIGINT); +# endif /* HAVE_USG_SIGHOLD */ +# endif /* !HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + + sigint_blocked = 0; +} + +/* **************************************************************** */ +/* */ +/* Saving and Restoring the TTY */ +/* */ +/* **************************************************************** */ + +/* Non-zero means that the terminal is in a prepped state. */ +static int terminal_prepped; + +static _RL_TTY_CHARS _rl_tty_chars, _rl_last_tty_chars; + +/* If non-zero, means that this process has called tcflow(fd, TCOOFF) + and output is suspended. */ +#if defined (__ksr1__) +static int ksrflow; +#endif + +/* Dummy call to force a backgrounded readline to stop before it tries + to get the tty settings. */ +static void +set_winsize (tty) + int tty; +{ +#if defined (TIOCGWINSZ) + struct winsize w; + + if (ioctl (tty, TIOCGWINSZ, &w) == 0) + (void) ioctl (tty, TIOCSWINSZ, &w); +#endif /* TIOCGWINSZ */ +} + +#if defined (NEW_TTY_DRIVER) + +/* Values for the `flags' field of a struct bsdtty. This tells which + elements of the struct bsdtty have been fetched from the system and + are valid. */ +#define SGTTY_SET 0x01 +#define LFLAG_SET 0x02 +#define TCHARS_SET 0x04 +#define LTCHARS_SET 0x08 + +struct bsdtty { + struct sgttyb sgttyb; /* Basic BSD tty driver information. */ + int lflag; /* Local mode flags, like LPASS8. */ +#if defined (TIOCGETC) + struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */ +#endif +#if defined (TIOCGLTC) + struct ltchars ltchars; /* 4.2 BSD editing characters */ +#endif + int flags; /* Bitmap saying which parts of the struct are valid. */ +}; + +#define TIOTYPE struct bsdtty + +static TIOTYPE otio; + +static void save_tty_chars PARAMS((TIOTYPE *)); +static int _get_tty_settings PARAMS((int, TIOTYPE *)); +static int get_tty_settings PARAMS((int, TIOTYPE *)); +static int _set_tty_settings PARAMS((int, TIOTYPE *)); +static int set_tty_settings PARAMS((int, TIOTYPE *)); + +static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *)); + +static void +save_tty_chars (tiop) + TIOTYPE *tiop; +{ + _rl_last_tty_chars = _rl_tty_chars; + + if (tiop->flags & SGTTY_SET) + { + _rl_tty_chars.t_erase = tiop->sgttyb.sg_erase; + _rl_tty_chars.t_kill = tiop->sgttyb.sg_kill; + } + + if (tiop->flags & TCHARS_SET) + { + _rl_tty_chars.t_intr = tiop->tchars.t_intrc; + _rl_tty_chars.t_quit = tiop->tchars.t_quitc; + _rl_tty_chars.t_start = tiop->tchars.t_startc; + _rl_tty_chars.t_stop = tiop->tchars.t_stopc; + _rl_tty_chars.t_eof = tiop->tchars.t_eofc; + _rl_tty_chars.t_eol = '\n'; + _rl_tty_chars.t_eol2 = tiop->tchars.t_brkc; + } + + if (tiop->flags & LTCHARS_SET) + { + _rl_tty_chars.t_susp = tiop->ltchars.t_suspc; + _rl_tty_chars.t_dsusp = tiop->ltchars.t_dsuspc; + _rl_tty_chars.t_reprint = tiop->ltchars.t_rprntc; + _rl_tty_chars.t_flush = tiop->ltchars.t_flushc; + _rl_tty_chars.t_werase = tiop->ltchars.t_werasc; + _rl_tty_chars.t_lnext = tiop->ltchars.t_lnextc; + } + + _rl_tty_chars.t_status = -1; +} + +static int +get_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ + set_winsize (tty); + + tiop->flags = tiop->lflag = 0; + + if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0) + return -1; + tiop->flags |= SGTTY_SET; + +#if defined (TIOCLGET) + if (ioctl (tty, TIOCLGET, &(tiop->lflag)) == 0) + tiop->flags |= LFLAG_SET; +#endif + +#if defined (TIOCGETC) + if (ioctl (tty, TIOCGETC, &(tiop->tchars)) == 0) + tiop->flags |= TCHARS_SET; +#endif + +#if defined (TIOCGLTC) + if (ioctl (tty, TIOCGLTC, &(tiop->ltchars)) == 0) + tiop->flags |= LTCHARS_SET; +#endif + + return 0; +} + +static int +set_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ + if (tiop->flags & SGTTY_SET) + { + ioctl (tty, TIOCSETN, &(tiop->sgttyb)); + tiop->flags &= ~SGTTY_SET; + } + readline_echoing_p = 1; + +#if defined (TIOCLSET) + if (tiop->flags & LFLAG_SET) + { + ioctl (tty, TIOCLSET, &(tiop->lflag)); + tiop->flags &= ~LFLAG_SET; + } +#endif + +#if defined (TIOCSETC) + if (tiop->flags & TCHARS_SET) + { + ioctl (tty, TIOCSETC, &(tiop->tchars)); + tiop->flags &= ~TCHARS_SET; + } +#endif + +#if defined (TIOCSLTC) + if (tiop->flags & LTCHARS_SET) + { + ioctl (tty, TIOCSLTC, &(tiop->ltchars)); + tiop->flags &= ~LTCHARS_SET; + } +#endif + + return 0; +} + +static void +prepare_terminal_settings (meta_flag, oldtio, tiop) + int meta_flag; + TIOTYPE oldtio, *tiop; +{ + readline_echoing_p = (oldtio.sgttyb.sg_flags & ECHO); + + /* Copy the original settings to the structure we're going to use for + our settings. */ + tiop->sgttyb = oldtio.sgttyb; + tiop->lflag = oldtio.lflag; +#if defined (TIOCGETC) + tiop->tchars = oldtio.tchars; +#endif +#if defined (TIOCGLTC) + tiop->ltchars = oldtio.ltchars; +#endif + tiop->flags = oldtio.flags; + + /* First, the basic settings to put us into character-at-a-time, no-echo + input mode. */ + tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD); + tiop->sgttyb.sg_flags |= CBREAK; + + /* If this terminal doesn't care how the 8th bit is used, then we can + use it for the meta-key. If only one of even or odd parity is + specified, then the terminal is using parity, and we cannot. */ +#if !defined (ANYP) +# define ANYP (EVENP | ODDP) +#endif + if (((oldtio.sgttyb.sg_flags & ANYP) == ANYP) || + ((oldtio.sgttyb.sg_flags & ANYP) == 0)) + { + tiop->sgttyb.sg_flags |= ANYP; + + /* Hack on local mode flags if we can. */ +#if defined (TIOCLGET) +# if defined (LPASS8) + tiop->lflag |= LPASS8; +# endif /* LPASS8 */ +#endif /* TIOCLGET */ + } + +#if defined (TIOCGETC) +# if defined (USE_XON_XOFF) + /* Get rid of terminal output start and stop characters. */ + tiop->tchars.t_stopc = -1; /* C-s */ + tiop->tchars.t_startc = -1; /* C-q */ + + /* If there is an XON character, bind it to restart the output. */ + if (oldtio.tchars.t_startc != -1) + rl_bind_key (oldtio.tchars.t_startc, rl_restart_output); +# endif /* USE_XON_XOFF */ + + /* If there is an EOF char, bind _rl_eof_char to it. */ + if (oldtio.tchars.t_eofc != -1) + _rl_eof_char = oldtio.tchars.t_eofc; + +# if defined (NO_KILL_INTR) + /* Get rid of terminal-generated SIGQUIT and SIGINT. */ + tiop->tchars.t_quitc = -1; /* C-\ */ + tiop->tchars.t_intrc = -1; /* C-c */ +# endif /* NO_KILL_INTR */ +#endif /* TIOCGETC */ + +#if defined (TIOCGLTC) + /* Make the interrupt keys go away. Just enough to make people happy. */ + tiop->ltchars.t_dsuspc = -1; /* C-y */ + tiop->ltchars.t_lnextc = -1; /* C-v */ +#endif /* TIOCGLTC */ +} + +#else /* !defined (NEW_TTY_DRIVER) */ + +#if !defined (VMIN) +# define VMIN VEOF +#endif + +#if !defined (VTIME) +# define VTIME VEOL +#endif + +#if defined (TERMIOS_TTY_DRIVER) +# define TIOTYPE struct termios +# define DRAIN_OUTPUT(fd) tcdrain (fd) +# define GETATTR(tty, tiop) (tcgetattr (tty, tiop)) +# ifdef M_UNIX +# define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop)) +# else +# define SETATTR(tty, tiop) (tcsetattr (tty, TCSADRAIN, tiop)) +# endif /* !M_UNIX */ +#else +# define TIOTYPE struct termio +# define DRAIN_OUTPUT(fd) +# define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop)) +# define SETATTR(tty, tiop) (ioctl (tty, TCSETAW, tiop)) +#endif /* !TERMIOS_TTY_DRIVER */ + +static TIOTYPE otio; + +static void save_tty_chars PARAMS((TIOTYPE *)); +static int _get_tty_settings PARAMS((int, TIOTYPE *)); +static int get_tty_settings PARAMS((int, TIOTYPE *)); +static int _set_tty_settings PARAMS((int, TIOTYPE *)); +static int set_tty_settings PARAMS((int, TIOTYPE *)); + +static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *)); + +#if defined (FLUSHO) +# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO) +#else +# define OUTPUT_BEING_FLUSHED(tp) 0 +#endif + +static void +save_tty_chars (tiop) + TIOTYPE *tiop; +{ + _rl_last_tty_chars = _rl_tty_chars; + + _rl_tty_chars.t_eof = tiop->c_cc[VEOF]; + _rl_tty_chars.t_eol = tiop->c_cc[VEOL]; +#ifdef VEOL2 + _rl_tty_chars.t_eol2 = tiop->c_cc[VEOL2]; +#endif + _rl_tty_chars.t_erase = tiop->c_cc[VERASE]; +#ifdef VWERASE + _rl_tty_chars.t_werase = tiop->c_cc[VWERASE]; +#endif + _rl_tty_chars.t_kill = tiop->c_cc[VKILL]; +#ifdef VREPRINT + _rl_tty_chars.t_reprint = tiop->c_cc[VREPRINT]; +#endif + _rl_tty_chars.t_intr = tiop->c_cc[VINTR]; + _rl_tty_chars.t_quit = tiop->c_cc[VQUIT]; +#ifdef VSUSP + _rl_tty_chars.t_susp = tiop->c_cc[VSUSP]; +#endif +#ifdef VDSUSP + _rl_tty_chars.t_dsusp = tiop->c_cc[VDSUSP]; +#endif +#ifdef VSTART + _rl_tty_chars.t_start = tiop->c_cc[VSTART]; +#endif +#ifdef VSTOP + _rl_tty_chars.t_stop = tiop->c_cc[VSTOP]; +#endif +#ifdef VLNEXT + _rl_tty_chars.t_lnext = tiop->c_cc[VLNEXT]; +#endif +#ifdef VDISCARD + _rl_tty_chars.t_flush = tiop->c_cc[VDISCARD]; +#endif +#ifdef VSTATUS + _rl_tty_chars.t_status = tiop->c_cc[VSTATUS]; +#endif +} + +#if defined (_AIX) || defined (_AIX41) +/* Currently this is only used on AIX */ +static void +rltty_warning (msg) + char *msg; +{ + fprintf (stderr, "readline: warning: %s\n", msg); +} +#endif + +#if defined (_AIX) +void +setopost(tp) +TIOTYPE *tp; +{ + if ((tp->c_oflag & OPOST) == 0) + { + rltty_warning ("turning on OPOST for terminal\r"); + tp->c_oflag |= OPOST|ONLCR; + } +} +#endif + +static int +_get_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ + int ioctl_ret; + + while (1) + { + ioctl_ret = GETATTR (tty, tiop); + if (ioctl_ret < 0) + { + if (errno != EINTR) + return -1; + else + continue; + } + if (OUTPUT_BEING_FLUSHED (tiop)) + { +#if defined (FLUSHO) && defined (_AIX41) + rltty_warning ("turning off output flushing"); + tiop->c_lflag &= ~FLUSHO; + break; +#else + continue; +#endif + } + break; + } + + return 0; +} + +static int +get_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ + set_winsize (tty); + + if (_get_tty_settings (tty, tiop) < 0) + return -1; + +#if defined (_AIX) + setopost(tiop); +#endif + + return 0; +} + +static int +_set_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ + while (SETATTR (tty, tiop) < 0) + { + if (errno != EINTR) + return -1; + errno = 0; + } + return 0; +} + +static int +set_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ + if (_set_tty_settings (tty, tiop) < 0) + return -1; + +#if 0 + +#if defined (TERMIOS_TTY_DRIVER) +# if defined (__ksr1__) + if (ksrflow) + { + ksrflow = 0; + tcflow (tty, TCOON); + } +# else /* !ksr1 */ + tcflow (tty, TCOON); /* Simulate a ^Q. */ +# endif /* !ksr1 */ +#else + ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */ +#endif /* !TERMIOS_TTY_DRIVER */ + +#endif /* 0 */ + + return 0; +} + +static void +prepare_terminal_settings (meta_flag, oldtio, tiop) + int meta_flag; + TIOTYPE oldtio, *tiop; +{ + readline_echoing_p = (oldtio.c_lflag & ECHO); + + tiop->c_lflag &= ~(ICANON | ECHO); + + if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE) + _rl_eof_char = oldtio.c_cc[VEOF]; + +#if defined (USE_XON_XOFF) +#if defined (IXANY) + tiop->c_iflag &= ~(IXON | IXOFF | IXANY); +#else + /* `strict' Posix systems do not define IXANY. */ + tiop->c_iflag &= ~(IXON | IXOFF); +#endif /* IXANY */ +#endif /* USE_XON_XOFF */ + + /* Only turn this off if we are using all 8 bits. */ + if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag) + tiop->c_iflag &= ~(ISTRIP | INPCK); + + /* Make sure we differentiate between CR and NL on input. */ + tiop->c_iflag &= ~(ICRNL | INLCR); + +#if !defined (HANDLE_SIGNALS) + tiop->c_lflag &= ~ISIG; +#else + tiop->c_lflag |= ISIG; +#endif + + tiop->c_cc[VMIN] = 1; + tiop->c_cc[VTIME] = 0; + +#if defined (FLUSHO) + if (OUTPUT_BEING_FLUSHED (tiop)) + { + tiop->c_lflag &= ~FLUSHO; + oldtio.c_lflag &= ~FLUSHO; + } +#endif + + /* Turn off characters that we need on Posix systems with job control, + just to be sure. This includes ^Y and ^V. This should not really + be necessary. */ +#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE) + +#if defined (VLNEXT) + tiop->c_cc[VLNEXT] = _POSIX_VDISABLE; +#endif + +#if defined (VDSUSP) + tiop->c_cc[VDSUSP] = _POSIX_VDISABLE; +#endif + +#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */ +} +#endif /* NEW_TTY_DRIVER */ + +/* Put the terminal in CBREAK mode so that we can detect key presses. */ +void +rl_prep_terminal (meta_flag) + int meta_flag; +{ + int tty; + TIOTYPE tio; + + if (terminal_prepped) + return; + + /* Try to keep this function from being INTerrupted. */ + block_sigint (); + + tty = fileno (rl_instream); + + if (get_tty_settings (tty, &tio) < 0) + { + release_sigint (); + return; + } + + otio = tio; + + save_tty_chars (&otio); + + prepare_terminal_settings (meta_flag, otio, &tio); + + if (set_tty_settings (tty, &tio) < 0) + { + release_sigint (); + return; + } + + if (_rl_enable_keypad) + _rl_control_keypad (1); + + fflush (rl_outstream); + terminal_prepped = 1; + RL_SETSTATE(RL_STATE_TERMPREPPED); + + release_sigint (); +} + +/* Restore the terminal's normal settings and modes. */ +void +rl_deprep_terminal () +{ + int tty; + + if (!terminal_prepped) + return; + + /* Try to keep this function from being interrupted. */ + block_sigint (); + + tty = fileno (rl_instream); + + if (_rl_enable_keypad) + _rl_control_keypad (0); + + fflush (rl_outstream); + + if (set_tty_settings (tty, &otio) < 0) + { + release_sigint (); + return; + } + + terminal_prepped = 0; + RL_UNSETSTATE(RL_STATE_TERMPREPPED); + + release_sigint (); +} + +/* **************************************************************** */ +/* */ +/* Bogus Flow Control */ +/* */ +/* **************************************************************** */ + +int +rl_restart_output (count, key) + int count, key; +{ + int fildes = fileno (rl_outstream); +#if defined (TIOCSTART) +#if defined (apollo) + ioctl (&fildes, TIOCSTART, 0); +#else + ioctl (fildes, TIOCSTART, 0); +#endif /* apollo */ + +#else /* !TIOCSTART */ +# if defined (TERMIOS_TTY_DRIVER) +# if defined (__ksr1__) + if (ksrflow) + { + ksrflow = 0; + tcflow (fildes, TCOON); + } +# else /* !ksr1 */ + tcflow (fildes, TCOON); /* Simulate a ^Q. */ +# endif /* !ksr1 */ +# else /* !TERMIOS_TTY_DRIVER */ +# if defined (TCXONC) + ioctl (fildes, TCXONC, TCOON); +# endif /* TCXONC */ +# endif /* !TERMIOS_TTY_DRIVER */ +#endif /* !TIOCSTART */ + + return 0; +} + +int +rl_stop_output (count, key) + int count, key; +{ + int fildes = fileno (rl_instream); + +#if defined (TIOCSTOP) +# if defined (apollo) + ioctl (&fildes, TIOCSTOP, 0); +# else + ioctl (fildes, TIOCSTOP, 0); +# endif /* apollo */ +#else /* !TIOCSTOP */ +# if defined (TERMIOS_TTY_DRIVER) +# if defined (__ksr1__) + ksrflow = 1; +# endif /* ksr1 */ + tcflow (fildes, TCOOFF); +# else +# if defined (TCXONC) + ioctl (fildes, TCXONC, TCOON); +# endif /* TCXONC */ +# endif /* !TERMIOS_TTY_DRIVER */ +#endif /* !TIOCSTOP */ + + return 0; +} + +/* **************************************************************** */ +/* */ +/* Default Key Bindings */ +/* */ +/* **************************************************************** */ + +/* Set the system's default editing characters to their readline equivalents + in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */ +void +rltty_set_default_bindings (kmap) + Keymap kmap; +{ + TIOTYPE ttybuff; + int tty = fileno (rl_instream); + +#if defined (NEW_TTY_DRIVER) + +#define SET_SPECIAL(sc, func) \ + do \ + { \ + int ic; \ + ic = sc; \ + if (ic != -1 && kmap[(unsigned char)ic].type == ISFUNC) \ + kmap[(unsigned char)ic].function = func; \ + } \ + while (0) + + if (get_tty_settings (tty, &ttybuff) == 0) + { + if (ttybuff.flags & SGTTY_SET) + { + SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout); + SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard); + } + +# if defined (TIOCGLTC) + if (ttybuff.flags & LTCHARS_SET) + { + SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout); + SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert); + } +# endif /* TIOCGLTC */ + } + +#else /* !NEW_TTY_DRIVER */ + +#define SET_SPECIAL(sc, func) \ + do \ + { \ + unsigned char uc; \ + uc = ttybuff.c_cc[sc]; \ + if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \ + kmap[uc].function = func; \ + } \ + while (0) + + if (get_tty_settings (tty, &ttybuff) == 0) + { + SET_SPECIAL (VERASE, rl_rubout); + SET_SPECIAL (VKILL, rl_unix_line_discard); + +# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER) + SET_SPECIAL (VLNEXT, rl_quoted_insert); +# endif /* VLNEXT && TERMIOS_TTY_DRIVER */ + +# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER) + SET_SPECIAL (VWERASE, rl_unix_word_rubout); +# endif /* VWERASE && TERMIOS_TTY_DRIVER */ + } +#endif /* !NEW_TTY_DRIVER */ +} + +/* New public way to set the system default editing chars to their readline + equivalents. */ +void +rl_tty_set_default_bindings (kmap) + Keymap kmap; +{ + rltty_set_default_bindings (kmap); +} + +#if defined (HANDLE_SIGNALS) + +#if defined (NEW_TTY_DRIVER) +int +_rl_disable_tty_signals () +{ + return 0; +} + +int +_rl_restore_tty_signals () +{ + return 0; +} +#else + +static TIOTYPE sigstty, nosigstty; +static int tty_sigs_disabled = 0; + +int +_rl_disable_tty_signals () +{ + if (tty_sigs_disabled) + return 0; + + if (_get_tty_settings (fileno (rl_instream), &sigstty) < 0) + return -1; + + nosigstty = sigstty; + + nosigstty.c_lflag &= ~ISIG; + nosigstty.c_iflag &= ~IXON; + + if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0) + return (_set_tty_settings (fileno (rl_instream), &sigstty)); + + tty_sigs_disabled = 1; + return 0; +} + +int +_rl_restore_tty_signals () +{ + int r; + + if (tty_sigs_disabled == 0) + return 0; + + r = _set_tty_settings (fileno (rl_instream), &sigstty); + + if (r == 0) + tty_sigs_disabled = 0; + + return r; +} +#endif /* !NEW_TTY_DRIVER */ + +#endif /* HANDLE_SIGNALS */ diff --git a/readline/readline-4.3/rltty.h b/readline/readline-4.3/rltty.h new file mode 100644 index 00000000..029a3fbc --- /dev/null +++ b/readline/readline-4.3/rltty.h @@ -0,0 +1,82 @@ +/* rltty.h - tty driver-related definitions used by some library files. */ + +/* Copyright (C) 1995 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RLTTY_H_) +#define _RLTTY_H_ + +/* Posix systems use termios and the Posix signal functions. */ +#if defined (TERMIOS_TTY_DRIVER) +# include +#endif /* TERMIOS_TTY_DRIVER */ + +/* System V machines use termio. */ +#if defined (TERMIO_TTY_DRIVER) +# include +# if !defined (TCOON) +# define TCOON 1 +# endif +#endif /* TERMIO_TTY_DRIVER */ + +/* Other (BSD) machines use sgtty. */ +#if defined (NEW_TTY_DRIVER) +# include +#endif + +#include "rlwinsize.h" + +/* Define _POSIX_VDISABLE if we are not using the `new' tty driver and + it is not already defined. It is used both to determine if a + special character is disabled and to disable certain special + characters. Posix systems should set to 0, USG systems to -1. */ +#if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE) +# if defined (_SVR4_VDISABLE) +# define _POSIX_VDISABLE _SVR4_VDISABLE +# else +# if defined (_POSIX_VERSION) +# define _POSIX_VDISABLE 0 +# else /* !_POSIX_VERSION */ +# define _POSIX_VDISABLE -1 +# endif /* !_POSIX_VERSION */ +# endif /* !_SVR4_DISABLE */ +#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */ + +typedef struct _rl_tty_chars { + char t_eof; + char t_eol; + char t_eol2; + char t_erase; + char t_werase; + char t_kill; + char t_reprint; + char t_intr; + char t_quit; + char t_susp; + char t_dsusp; + char t_start; + char t_stop; + char t_lnext; + char t_flush; + char t_status; +} _RL_TTY_CHARS; + +#endif /* _RLTTY_H_ */ diff --git a/readline/readline-4.3/rltypedefs.h b/readline/readline-4.3/rltypedefs.h new file mode 100644 index 00000000..f3280e9f --- /dev/null +++ b/readline/readline-4.3/rltypedefs.h @@ -0,0 +1,88 @@ +/* rltypedefs.h -- Type declarations for readline functions. */ + +/* Copyright (C) 2000 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#ifndef _RL_TYPEDEFS_H_ +#define _RL_TYPEDEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Old-style */ + +#if !defined (_FUNCTION_DEF) +# define _FUNCTION_DEF + +typedef int Function (); +typedef void VFunction (); +typedef char *CPFunction (); +typedef char **CPPFunction (); + +#endif /* _FUNCTION_DEF */ + +/* New style. */ + +#if !defined (_RL_FUNCTION_TYPEDEF) +# define _RL_FUNCTION_TYPEDEF + +/* Bindable functions */ +typedef int rl_command_func_t PARAMS((int, int)); + +/* Typedefs for the completion system */ +typedef char *rl_compentry_func_t PARAMS((const char *, int)); +typedef char **rl_completion_func_t PARAMS((const char *, int, int)); + +typedef char *rl_quote_func_t PARAMS((char *, int, char *)); +typedef char *rl_dequote_func_t PARAMS((char *, int)); + +typedef int rl_compignore_func_t PARAMS((char **)); + +typedef void rl_compdisp_func_t PARAMS((char **, int, int)); + +/* Type for input and pre-read hook functions like rl_event_hook */ +typedef int rl_hook_func_t PARAMS((void)); + +/* Input function type */ +typedef int rl_getc_func_t PARAMS((FILE *)); + +/* Generic function that takes a character buffer (which could be the readline + line buffer) and an index into it (which could be rl_point) and returns + an int. */ +typedef int rl_linebuf_func_t PARAMS((char *, int)); + +/* `Generic' function pointer typedefs */ +typedef int rl_intfunc_t PARAMS((int)); +#define rl_ivoidfunc_t rl_hook_func_t +typedef int rl_icpfunc_t PARAMS((char *)); +typedef int rl_icppfunc_t PARAMS((char **)); + +typedef void rl_voidfunc_t PARAMS((void)); +typedef void rl_vintfunc_t PARAMS((int)); +typedef void rl_vcpfunc_t PARAMS((char *)); +typedef void rl_vcppfunc_t PARAMS((char **)); +#endif /* _RL_FUNCTION_TYPEDEF */ + +#ifdef __cplusplus +} +#endif + +#endif /* _RL_TYPEDEFS_H_ */ diff --git a/readline/readline-4.3/rlwinsize.h b/readline/readline-4.3/rlwinsize.h new file mode 100644 index 00000000..7838154d --- /dev/null +++ b/readline/readline-4.3/rlwinsize.h @@ -0,0 +1,57 @@ +/* rlwinsize.h -- an attempt to isolate some of the system-specific defines + for `struct winsize' and TIOCGWINSZ. */ + +/* Copyright (C) 1997 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RLWINSIZE_H_) +#define _RLWINSIZE_H_ + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +/* Try to find the definitions of `struct winsize' and TIOGCWINSZ */ + +#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ) +# include +#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */ + +#if defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL) +# include +#endif /* STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */ + +/* Not in either of the standard places, look around. */ +#if !defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL) +# if defined (HAVE_SYS_STREAM_H) +# include +# endif /* HAVE_SYS_STREAM_H */ +# if defined (HAVE_SYS_PTEM_H) /* SVR4.2, at least, has it here */ +# include +# define _IO_PTEM_H /* work around SVR4.2 1.1.4 bug */ +# endif /* HAVE_SYS_PTEM_H */ +# if defined (HAVE_SYS_PTE_H) /* ??? */ +# include +# endif /* HAVE_SYS_PTE_H */ +#endif /* !STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */ + +#endif /* _RL_WINSIZE_H */ + diff --git a/readline/readline-4.3/savestring.c b/readline/readline-4.3/savestring.c new file mode 100644 index 00000000..c7ebeb1e --- /dev/null +++ b/readline/readline-4.3/savestring.c @@ -0,0 +1,36 @@ +/* savestring.c */ + +/* Copyright (C) 1998 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#include +#ifdef HAVE_STRING_H +# include +#endif +#include "xmalloc.h" + +/* Backwards compatibility, now that savestring has been removed from + all `public' readline header files. */ +char * +savestring (s) + const char *s; +{ + return ((char *)strcpy ((char *)xmalloc (1 + strlen (s)), (s))); +} diff --git a/readline/readline-4.3/search.c b/readline/readline-4.3/search.c new file mode 100644 index 00000000..7e0d60b5 --- /dev/null +++ b/readline/readline-4.3/search.c @@ -0,0 +1,465 @@ +/* search.c - code for non-incremental searching in emacs and vi modes. */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + + This file is part of the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif + +#include "rldefs.h" +#include "rlmbutil.h" + +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +#ifdef abs +# undef abs +#endif +#define abs(x) (((x) >= 0) ? (x) : -(x)) + +extern HIST_ENTRY *_rl_saved_line_for_history; + +/* Functions imported from the rest of the library. */ +extern int _rl_free_history_entry PARAMS((HIST_ENTRY *)); + +static char *noninc_search_string = (char *) NULL; +static int noninc_history_pos; + +static char *prev_line_found = (char *) NULL; + +static int rl_history_search_len; +static int rl_history_search_pos; +static char *history_search_string; +static int history_string_size; + +static void make_history_line_current PARAMS((HIST_ENTRY *)); +static int noninc_search_from_pos PARAMS((char *, int, int)); +static void noninc_dosearch PARAMS((char *, int)); +static void noninc_search PARAMS((int, int)); +static int rl_history_search_internal PARAMS((int, int)); +static void rl_history_search_reinit PARAMS((void)); + +/* Make the data from the history entry ENTRY be the contents of the + current line. This doesn't do anything with rl_point; the caller + must set it. */ +static void +make_history_line_current (entry) + HIST_ENTRY *entry; +{ + rl_replace_line (entry->line, 0); + rl_undo_list = (UNDO_LIST *)entry->data; + + if (_rl_saved_line_for_history) + _rl_free_history_entry (_rl_saved_line_for_history); + _rl_saved_line_for_history = (HIST_ENTRY *)NULL; +} + +/* Search the history list for STRING starting at absolute history position + POS. If STRING begins with `^', the search must match STRING at the + beginning of a history line, otherwise a full substring match is performed + for STRING. DIR < 0 means to search backwards through the history list, + DIR >= 0 means to search forward. */ +static int +noninc_search_from_pos (string, pos, dir) + char *string; + int pos, dir; +{ + int ret, old; + + if (pos < 0) + return -1; + + old = where_history (); + if (history_set_pos (pos) == 0) + return -1; + + RL_SETSTATE(RL_STATE_SEARCH); + if (*string == '^') + ret = history_search_prefix (string + 1, dir); + else + ret = history_search (string, dir); + RL_UNSETSTATE(RL_STATE_SEARCH); + + if (ret != -1) + ret = where_history (); + + history_set_pos (old); + return (ret); +} + +/* Search for a line in the history containing STRING. If DIR is < 0, the + search is backwards through previous entries, else through subsequent + entries. */ +static void +noninc_dosearch (string, dir) + char *string; + int dir; +{ + int oldpos, pos; + HIST_ENTRY *entry; + + if (string == 0 || *string == '\0' || noninc_history_pos < 0) + { + rl_ding (); + return; + } + + pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir); + if (pos == -1) + { + /* Search failed, current history position unchanged. */ + rl_maybe_unsave_line (); + rl_clear_message (); + rl_point = 0; + rl_ding (); + return; + } + + noninc_history_pos = pos; + + oldpos = where_history (); + history_set_pos (noninc_history_pos); + entry = current_history (); +#if defined (VI_MODE) + if (rl_editing_mode != vi_mode) +#endif + history_set_pos (oldpos); + + make_history_line_current (entry); + + rl_point = 0; + rl_mark = rl_end; + + rl_clear_message (); +} + +/* Search non-interactively through the history list. DIR < 0 means to + search backwards through the history of previous commands; otherwise + the search is for commands subsequent to the current position in the + history list. PCHAR is the character to use for prompting when reading + the search string; if not specified (0), it defaults to `:'. */ +static void +noninc_search (dir, pchar) + int dir; + int pchar; +{ + int saved_point, saved_mark, c; + char *p; +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; +#endif + + rl_maybe_save_line (); + saved_point = rl_point; + saved_mark = rl_mark; + + /* Use the line buffer to read the search string. */ + rl_line_buffer[0] = 0; + rl_end = rl_point = 0; + + p = _rl_make_prompt_for_search (pchar ? pchar : ':'); + rl_message (p, 0, 0); + free (p); + +#define SEARCH_RETURN rl_restore_prompt (); RL_UNSETSTATE(RL_STATE_NSEARCH); return + + RL_SETSTATE(RL_STATE_NSEARCH); + /* Read the search string. */ + while (1) + { + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + c = _rl_read_mbstring (c, mb, MB_LEN_MAX); +#endif + + if (c == 0) + break; + + switch (c) + { + case CTRL('H'): + case RUBOUT: + if (rl_point == 0) + { + rl_maybe_unsave_line (); + rl_clear_message (); + rl_point = saved_point; + rl_mark = saved_mark; + SEARCH_RETURN; + } + _rl_rubout_char (1, c); + break; + + case CTRL('W'): + rl_unix_word_rubout (1, c); + break; + + case CTRL('U'): + rl_unix_line_discard (1, c); + break; + + case RETURN: + case NEWLINE: + goto dosearch; + /* NOTREACHED */ + break; + + case CTRL('C'): + case CTRL('G'): + rl_maybe_unsave_line (); + rl_clear_message (); + rl_point = saved_point; + rl_mark = saved_mark; + rl_ding (); + SEARCH_RETURN; + + default: +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_insert_text (mb); + else +#endif + _rl_insert_char (1, c); + break; + } + (*rl_redisplay_function) (); + } + + dosearch: + rl_mark = saved_mark; + + /* If rl_point == 0, we want to re-use the previous search string and + start from the saved history position. If there's no previous search + string, punt. */ + if (rl_point == 0) + { + if (!noninc_search_string) + { + rl_ding (); + SEARCH_RETURN; + } + } + else + { + /* We want to start the search from the current history position. */ + noninc_history_pos = where_history (); + FREE (noninc_search_string); + noninc_search_string = savestring (rl_line_buffer); + } + + rl_restore_prompt (); + noninc_dosearch (noninc_search_string, dir); + RL_UNSETSTATE(RL_STATE_NSEARCH); +} + +/* Search forward through the history list for a string. If the vi-mode + code calls this, KEY will be `?'. */ +int +rl_noninc_forward_search (count, key) + int count, key; +{ + noninc_search (1, (key == '?') ? '?' : 0); + return 0; +} + +/* Reverse search the history list for a string. If the vi-mode code + calls this, KEY will be `/'. */ +int +rl_noninc_reverse_search (count, key) + int count, key; +{ + noninc_search (-1, (key == '/') ? '/' : 0); + return 0; +} + +/* Search forward through the history list for the last string searched + for. If there is no saved search string, abort. */ +int +rl_noninc_forward_search_again (count, key) + int count, key; +{ + if (!noninc_search_string) + { + rl_ding (); + return (-1); + } + noninc_dosearch (noninc_search_string, 1); + return 0; +} + +/* Reverse search in the history list for the last string searched + for. If there is no saved search string, abort. */ +int +rl_noninc_reverse_search_again (count, key) + int count, key; +{ + if (!noninc_search_string) + { + rl_ding (); + return (-1); + } + noninc_dosearch (noninc_search_string, -1); + return 0; +} + +static int +rl_history_search_internal (count, dir) + int count, dir; +{ + HIST_ENTRY *temp; + int ret, oldpos; + + rl_maybe_save_line (); + temp = (HIST_ENTRY *)NULL; + + /* Search COUNT times through the history for a line whose prefix + matches history_search_string. When this loop finishes, TEMP, + if non-null, is the history line to copy into the line buffer. */ + while (count) + { + ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir); + if (ret == -1) + break; + + /* Get the history entry we found. */ + rl_history_search_pos = ret; + oldpos = where_history (); + history_set_pos (rl_history_search_pos); + temp = current_history (); + history_set_pos (oldpos); + + /* Don't find multiple instances of the same line. */ + if (prev_line_found && STREQ (prev_line_found, temp->line)) + continue; + prev_line_found = temp->line; + count--; + } + + /* If we didn't find anything at all, return. */ + if (temp == 0) + { + rl_maybe_unsave_line (); + rl_ding (); + /* If you don't want the saved history line (last match) to show up + in the line buffer after the search fails, change the #if 0 to + #if 1 */ +#if 0 + if (rl_point > rl_history_search_len) + { + rl_point = rl_end = rl_history_search_len; + rl_line_buffer[rl_end] = '\0'; + rl_mark = 0; + } +#else + rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */ + rl_mark = rl_end; +#endif + return 1; + } + + /* Copy the line we found into the current line buffer. */ + make_history_line_current (temp); + + rl_point = rl_history_search_len; + rl_mark = rl_end; + + return 0; +} + +static void +rl_history_search_reinit () +{ + rl_history_search_pos = where_history (); + rl_history_search_len = rl_point; + prev_line_found = (char *)NULL; + if (rl_point) + { + if (rl_history_search_len >= history_string_size - 2) + { + history_string_size = rl_history_search_len + 2; + history_search_string = (char *)xrealloc (history_search_string, history_string_size); + } + history_search_string[0] = '^'; + strncpy (history_search_string + 1, rl_line_buffer, rl_point); + history_search_string[rl_point + 1] = '\0'; + } + _rl_free_saved_history_line (); +} + +/* Search forward in the history for the string of characters + from the start of the line to rl_point. This is a non-incremental + search. */ +int +rl_history_search_forward (count, ignore) + int count, ignore; +{ + if (count == 0) + return (0); + + if (rl_last_func != rl_history_search_forward && + rl_last_func != rl_history_search_backward) + rl_history_search_reinit (); + + if (rl_history_search_len == 0) + return (rl_get_next_history (count, ignore)); + return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1)); +} + +/* Search backward through the history for the string of characters + from the start of the line to rl_point. This is a non-incremental + search. */ +int +rl_history_search_backward (count, ignore) + int count, ignore; +{ + if (count == 0) + return (0); + + if (rl_last_func != rl_history_search_forward && + rl_last_func != rl_history_search_backward) + rl_history_search_reinit (); + + if (rl_history_search_len == 0) + return (rl_get_previous_history (count, ignore)); + return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1)); +} diff --git a/readline/readline-4.3/shell.c b/readline/readline-4.3/shell.c new file mode 100644 index 00000000..ad27cc14 --- /dev/null +++ b/readline/readline-4.3/shell.c @@ -0,0 +1,196 @@ +/* shell.c -- readline utility functions that are normally provided by + bash when readline is linked as part of the shell. */ + +/* Copyright (C) 1997 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_STRING_H) +# include +#else +# include +#endif /* !HAVE_STRING_H */ + +#if defined (HAVE_LIMITS_H) +# include +#endif + +#include +#include + +#include + +#include "rlstdc.h" +#include "rlshell.h" +#include "xmalloc.h" + +#if !defined (HAVE_GETPW_DECLS) +extern struct passwd *getpwuid PARAMS((uid_t)); +#endif /* !HAVE_GETPW_DECLS */ + +#ifndef NULL +# define NULL 0 +#endif + +#ifndef CHAR_BIT +# define CHAR_BIT 8 +#endif + +/* Nonzero if the integer type T is signed. */ +#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) + +/* Bound on length of the string representing an integer value of type T. + Subtract one for the sign bit if T is signed; + 302 / 1000 is log10 (2) rounded up; + add one for integer division truncation; + add one more for a minus sign if t is signed. */ +#define INT_STRLEN_BOUND(t) \ + ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \ + + 1 + TYPE_SIGNED (t)) + +/* All of these functions are resolved from bash if we are linking readline + as part of bash. */ + +/* Does shell-like quoting using single quotes. */ +char * +sh_single_quote (string) + char *string; +{ + register int c; + char *result, *r, *s; + + result = (char *)xmalloc (3 + (4 * strlen (string))); + r = result; + *r++ = '\''; + + for (s = string; s && (c = *s); s++) + { + *r++ = c; + + if (c == '\'') + { + *r++ = '\\'; /* insert escaped single quote */ + *r++ = '\''; + *r++ = '\''; /* start new quoted string */ + } + } + + *r++ = '\''; + *r = '\0'; + + return (result); +} + +/* Set the environment variables LINES and COLUMNS to lines and cols, + respectively. */ +void +sh_set_lines_and_columns (lines, cols) + int lines, cols; +{ + char *b; + +#if defined (HAVE_PUTENV) + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1); + sprintf (b, "LINES=%d", lines); + putenv (b); + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1); + sprintf (b, "COLUMNS=%d", cols); + putenv (b); +#else /* !HAVE_PUTENV */ +# if defined (HAVE_SETENV) + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1); + sprintf (b, "%d", lines); + setenv ("LINES", b, 1); + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1); + sprintf (b, "%d", cols); + setenv ("COLUMNS", b, 1); +# endif /* HAVE_SETENV */ +#endif /* !HAVE_PUTENV */ +} + +char * +sh_get_env_value (varname) + const char *varname; +{ + return ((char *)getenv (varname)); +} + +char * +sh_get_home_dir () +{ + char *home_dir; + struct passwd *entry; + + home_dir = (char *)NULL; + entry = getpwuid (getuid ()); + if (entry) + home_dir = entry->pw_dir; + return (home_dir); +} + +#if !defined (O_NDELAY) +# if defined (FNDELAY) +# define O_NDELAY FNDELAY +# endif +#endif + +int +sh_unset_nodelay_mode (fd) + int fd; +{ + int flags, bflags; + + if ((flags = fcntl (fd, F_GETFL, 0)) < 0) + return -1; + + bflags = 0; + +#ifdef O_NONBLOCK + bflags |= O_NONBLOCK; +#endif + +#ifdef O_NDELAY + bflags |= O_NDELAY; +#endif + + if (flags & bflags) + { + flags &= ~bflags; + return (fcntl (fd, F_SETFL, flags)); + } + + return 0; +} diff --git a/readline/readline-4.3/shlib/Makefile.in b/readline/readline-4.3/shlib/Makefile.in new file mode 100644 index 00000000..0cba57e4 --- /dev/null +++ b/readline/readline-4.3/shlib/Makefile.in @@ -0,0 +1,437 @@ +## -*- text -*- ## +# Makefile for the GNU readline library shared library support. +# +# Copyright (C) 1998 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +RL_LIBRARY_VERSION = @LIBVERSION@ +RL_LIBRARY_NAME = readline + +srcdir = @srcdir@ +VPATH = .:@top_srcdir@ +topdir = @top_srcdir@ +BUILD_DIR = @BUILD_DIR@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +CC = @CC@ +RANLIB = @RANLIB@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +RM = rm -f +CP = cp +MV = mv +LN = ln + +SHELL = @MAKE_SHELL@ + +host_os = @host_os@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ + +# Support an alternate destination root directory for package building +DESTDIR = + +CFLAGS = @CFLAGS@ +LOCAL_CFLAGS = @LOCAL_CFLAGS@ -DRL_LIBRARY_VERSION='"$(RL_LIBRARY_VERSION)"' +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@ @CFLAGS@ + +DEFS = @DEFS@ +LOCAL_DEFS = @LOCAL_DEFS@ + +# +# These values are generated for configure by ${topdir}/support/shobj-conf. +# If your system is not supported by that script, but includes facilities for +# dynamic loading of shared objects, please update the script and send the +# changes to bash-maintainers@gnu.org. +# +SHOBJ_CC = @SHOBJ_CC@ +SHOBJ_CFLAGS = @SHOBJ_CFLAGS@ +SHOBJ_LD = @SHOBJ_LD@ + +SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@ +SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@ +SHOBJ_LIBS = @SHOBJ_LIBS@ + +SHLIB_XLDFLAGS = @SHLIB_XLDFLAGS@ +SHLIB_LIBS = @SHLIB_LIBS@ +SHLIB_LIBSUFF = @SHLIB_LIBSUFF@ + +SHLIB_LIBVERSION = @SHLIB_LIBVERSION@ + +SHLIB_STATUS = @SHLIB_STATUS@ + +# shared library versioning +SHLIB_MAJOR= @SHLIB_MAJOR@ +# shared library systems like SVR4's do not use minor versions +SHLIB_MINOR= .@SHLIB_MINOR@ + +# For libraries which include headers from other libraries. +INCLUDES = -I. -I.. -I$(topdir) + +CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) $(INCLUDES) $(LOCAL_CFLAGS) $(CFLAGS) + +.SUFFIXES: .so + +.c.so: + ${RM} $@ + $(SHOBJ_CC) -c $(CCFLAGS) $(SHOBJ_CFLAGS) -o $*.o $< + $(MV) $*.o $@ + +# The name of the main library target. + +SHARED_READLINE = libreadline.$(SHLIB_LIBVERSION) +SHARED_HISTORY = libhistory.$(SHLIB_LIBVERSION) +SHARED_LIBS = $(SHARED_READLINE) $(SHARED_HISTORY) + +# The C code source files for this library. +CSOURCES = $(topdir)/readline.c $(topdir)/funmap.c $(topdir)/keymaps.c \ + $(topdir)/vi_mode.c $(topdir)/parens.c $(topdir)/rltty.c \ + $(topdir)/complete.c $(topdir)/bind.c $(topdir)/isearch.c \ + $(topdir)/display.c $(topdir)/signals.c $(topdir)/emacs_keymap.c \ + $(topdir)/vi_keymap.c $(topdir)/util.c $(topdir)/kill.c \ + $(topdir)/undo.c $(topdir)/macro.c $(topdir)/input.c \ + $(topdir)/callback.c $(topdir)/terminal.c $(topdir)/xmalloc.c \ + $(topdir)/history.c $(topdir)/histsearch.c $(topdir)/histexpand.c \ + $(topdir)/histfile.c $(topdir)/nls.c $(topdir)/search.c \ + $(topdir)/shell.c $(topdir)/savestring.c $(topdir)/tilde.c \ + $(topdir)/text.c $(topdir)/misc.c $(topdir)/compat.c \ + $(topdir)/mbutil.c + +# The header files for this library. +HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \ + posixstat.h posixdir.h posixjmp.h tilde.h rlconf.h rltty.h \ + ansi_stdlib.h tcap.h xmalloc.h rlprivate.h rlshell.h rlmbutil.h + +SHARED_HISTOBJ = history.so histexpand.so histfile.so histsearch.so shell.so \ + mbutil.so +SHARED_TILDEOBJ = tilde.so +SHARED_OBJ = readline.so vi_mode.so funmap.so keymaps.so parens.so search.so \ + rltty.so complete.so bind.so isearch.so display.so signals.so \ + util.so kill.so undo.so macro.so input.so callback.so terminal.so \ + text.so nls.so misc.so xmalloc.so $(SHARED_HISTOBJ) $(SHARED_TILDEOBJ) \ + compat.so + +########################################################################## + +all: $(SHLIB_STATUS) + +supported: $(SHARED_LIBS) + +unsupported: + @echo "Your system and compiler (${host_os}-${CC}) are not supported by the" + @echo "${topdir}/support/shobj-conf script." + @echo "If your operating system provides facilities for creating" + @echo "shared libraries, please update the script and re-run configure." + @echo "Please send the changes you made to bash-maintainers@gnu.org" + @echo "for inclusion in future bash and readline releases." + +$(SHARED_READLINE): $(SHARED_OBJ) + $(RM) $@ + $(SHOBJ_LD) ${SHOBJ_LDFLAGS} ${SHLIB_XLDFLAGS} -o $@ $(SHARED_OBJ) $(SHLIB_LIBS) + +$(SHARED_HISTORY): $(SHARED_HISTOBJ) xmalloc.so + $(RM) $@ + $(SHOBJ_LD) ${SHOBJ_LDFLAGS} ${SHLIB_XLDFLAGS} -o $@ $(SHARED_HISTOBJ) xmalloc.so $(SHLIB_LIBS) + +# Since tilde.c is shared between readline and bash, make sure we compile +# it with the right flags when it's built as part of readline +tilde.so: tilde.c + ${RM} $@ + $(SHOBJ_CC) -c $(CCFLAGS) $(SHOBJ_CFLAGS) -DREADLINE_LIBRARY -c -o tilde.o $(topdir)/tilde.c + $(MV) tilde.o $@ + +installdirs: $(topdir)/support/mkdirs + -$(SHELL) $(topdir)/support/mkdirs $(DESTDIR)$(libdir) + +install: installdirs $(SHLIB_STATUS) + $(SHELL) $(topdir)/support/shlib-install -O $(host_os) -d $(DESTDIR)$(libdir) -i "$(INSTALL_DATA)" $(SHARED_HISTORY) + $(SHELL) $(topdir)/support/shlib-install -O $(host_os) -d $(DESTDIR)$(libdir) -i "$(INSTALL_DATA)" $(SHARED_READLINE) + @echo install: you may need to run ldconfig + +uninstall: + $(SHELL) $(topdir)/support/shlib-install -O $(host_os) -d $(DESTDIR)$(libdir) -U $(SHARED_HISTORY) + $(SHELL) $(topdir)/support/shlib-install -O $(host_os) -d $(DESTDIR)$(libdir) -U $(SHARED_READLINE) + @echo uninstall: you may need to run ldconfig + +clean mostlyclean: force + $(RM) $(SHARED_OBJ) $(SHARED_LIBS) + +distclean maintainer-clean: clean + $(RM) Makefile + +force: + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: + +# Dependencies +bind.so: $(topdir)/ansi_stdlib.h $(topdir)/posixstat.h +bind.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +bind.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +bind.so: $(topdir)/rltypedefs.h +bind.so: $(topdir)/tilde.h $(topdir)/history.h +compat.so: $(topdir)/rlstdc.h +callback.so: $(topdir)/rlconf.h +callback.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h +callback.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +callback.so: $(topdir)/rltypedefs.h +callback.so: $(topdir)/tilde.h +complete.so: $(topdir)/ansi_stdlib.h posixdir.h $(topdir)/posixstat.h +complete.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +complete.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +complete.so: $(topdir)/rltypedefs.h +complete.so: $(topdir)/tilde.h +display.so: $(topdir)/ansi_stdlib.h $(topdir)/posixstat.h +display.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +display.so: $(topdir)/tcap.h +display.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +display.so: $(topdir)/rltypedefs.h +display.so: $(topdir)/tilde.h $(topdir)/history.h +funmap.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +funmap.so: $(topdir)/rltypedefs.h +funmap.so: $(topdir)/rlconf.h $(topdir)/ansi_stdlib.h +funmap.so: ${BUILD_DIR}/config.h $(topdir)/tilde.h +histexpand.so: $(topdir)/ansi_stdlib.h +histexpand.so: $(topdir)/history.h $(topdir)/histlib.h $(topdir)/rltypedefs.h +histexpand.so: ${BUILD_DIR}/config.h +histfile.so: $(topdir)/ansi_stdlib.h +histfile.so: $(topdir)/history.h $(topdir)/histlib.h $(topdir)/rltypedefs.h +histfile.so: ${BUILD_DIR}/config.h +history.so: $(topdir)/ansi_stdlib.h +history.so: $(topdir)/history.h $(topdir)/histlib.h $(topdir)/rltypedefs.h +history.so: ${BUILD_DIR}/config.h +histsearch.so: $(topdir)/ansi_stdlib.h +histsearch.so: $(topdir)/history.h $(topdir)/histlib.h $(topdir)/rltypedefs.h +histsearch.so: ${BUILD_DIR}/config.h +input.so: $(topdir)/ansi_stdlib.h +input.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +input.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +input.so: $(topdir)/rltypedefs.h +input.so: $(topdir)/tilde.h +isearch.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +isearch.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +isearch.so: $(topdir)/rltypedefs.h +isearch.so: $(topdir)/ansi_stdlib.h $(topdir)/history.h $(topdir)/tilde.h +keymaps.so: emacs_keymap.c vi_keymap.c +keymaps.so: $(topdir)/keymaps.h $(topdir)/chardefs.h $(topdir)/rlconf.h +keymaps.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +keymaps.so: $(topdir)/rltypedefs.h +keymaps.so: ${BUILD_DIR}/config.h $(topdir)/ansi_stdlib.h $(topdir)/tilde.h +kill.so: $(topdir)/ansi_stdlib.h +kill.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +kill.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +kill.so: $(topdir)/tilde.h $(topdir)/history.h $(topdir)/rltypedefs.h +macro.so: $(topdir)/ansi_stdlib.h +macro.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +macro.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +macro.so: $(topdir)/tilde.h $(topdir)/history.h $(topdir)/rltypedefs.h +mbutil.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +mbutil.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/rltypedefs.h +mbutil.so: $(topdir)/chardefs.h $(topdir)/rlstdc.h +misc.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +misc.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +misc.so: $(topdir)/rltypedefs.h +misc.so: $(topdir)/history.h $(topdir)/tilde.h $(topdir)/ansi_stdlib.h +nls.so: $(topdir)/ansi_stdlib.h +nls.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +nls.o: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +nls.o: $(topdir)/rltypedefs.h +nls.o: $(topdir)/tilde.h $(topdir)/history.h $(topdir)/rlstdc.h +parens.so: $(topdir)/rlconf.h ${BUILD_DIR}/config.h +parens.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +parens.so: $(topdir)/rltypedefs.h +parens.so: $(topdir)/tilde.h +rltty.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +rltty.so: $(topdir)/rltty.h $(topdir)/tilde.h +rltty.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +rltty.so: $(topdir)/rltypedefs.h +search.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +search.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +search.so: $(topdir)/ansi_stdlib.h $(topdir)/history.h $(topdir)/tilde.h +search.so: $(topdir)/rltypedefs.h +signals.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +signals.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +signals.so: $(topdir)/history.h $(topdir)/tilde.h +signals.so: $(topdir)/rltypedefs.h +terminal.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +terminal.so: $(topdir)/tcap.h +terminal.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +terminal.so: $(topdir)/tilde.h $(topdir)/history.h +terminal.so: $(topdir)/rltypedefs.h +text.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +text.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +text.so: $(topdir)/rltypedefs.h +text.so: $(topdir)/history.h $(topdir)/tilde.h $(topdir)/ansi_stdlib.h +tilde.so: $(topdir)/ansi_stdlib.h ${BUILD_DIR}/config.h $(topdir)/tilde.h +undo.so: $(topdir)/ansi_stdlib.h +undo.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +undo.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +undo.so: $(topdir)/rltypedefs.h +undo.so: $(topdir)/tilde.h $(topdir)/history.h +util.so: $(topdir)/posixjmp.h $(topdir)/ansi_stdlib.h +util.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +util.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +util.so: $(topdir)/rltypedefs.h $(topdir)/tilde.h +vi_mode.so: $(topdir)/rldefs.h ${BUILD_DIR}/config.h $(topdir)/rlconf.h +vi_mode.so: $(topdir)/readline.h $(topdir)/keymaps.h $(topdir)/chardefs.h +vi_mode.so: $(topdir)/history.h $(topdir)/ansi_stdlib.h $(topdir)/tilde.h +vi_mode.so: $(topdir)/rltypedefs.h +xmalloc.so: ${BUILD_DIR}/config.h +xmalloc.so: $(topdir)/ansi_stdlib.h + +bind.so: $(topdir)/rlshell.h +histfile.so: $(topdir)/rlshell.h +nls.so: $(topdir)/rlshell.h +readline.so: $(topdir)/rlshell.h +shell.so: $(topdir)/rlshell.h +terminal.so: $(topdir)/rlshell.h +histexpand.so: $(topdir)/rlshell.h + +bind.so: $(topdir)/rlprivate.h +callback.so: $(topdir)/rlprivate.h +complete.so: $(topdir)/rlprivate.h +display.so: $(topdir)/rlprivate.h +input.so: $(topdir)/rlprivate.h +isearch.so: $(topdir)/rlprivate.h +kill.so: $(topdir)/rlprivate.h +macro.so: $(topdir)/rlprivate.h +mbutil.so: $(topdir)/rlprivate.h +misc.so: $(topdir)/rlprivate.h +nls.so: $(topdir)/rlprivate.h +parens.so: $(topdir)/rlprivate.h +readline.so: $(topdir)/rlprivate.h +rltty.so: $(topdir)/rlprivate.h +search.so: $(topdir)/rlprivate.h +signals.so: $(topdir)/rlprivate.h +terminal.so: $(topdir)/rlprivate.h +text.so: $(topdir)/rlprivate.h +undo.so: $(topdir)/rlprivate.h +util.so: $(topdir)/rlprivate.h +vi_mode.so: $(topdir)/rlprivate.h + +bind.so: $(topdir)/xmalloc.h +complete.so: $(topdir)/xmalloc.h +display.so: $(topdir)/xmalloc.h +funmap.so: $(topdir)/xmalloc.h +histexpand.so: $(topdir)/xmalloc.h +histfile.so: $(topdir)/xmalloc.h +history.so: $(topdir)/xmalloc.h +input.so: $(topdir)/xmalloc.h +isearch.so: $(topdir)/xmalloc.h +keymaps.so: $(topdir)/xmalloc.h +kill.so: $(topdir)/xmalloc.h +macro.so: $(topdir)/xmalloc.h +mbutil.so: $(topdir)/xmalloc.h +misc.so: $(topdir)/xmalloc.h +readline.so: $(topdir)/xmalloc.h +savestring.so: $(topdir)/xmalloc.h +search.so: $(topdir)/xmalloc.h +shell.so: $(topdir)/xmalloc.h +terminal.so: $(topdir)/xmalloc.h +text.so: $(topdir)/xmalloc.h +tilde.so: $(topdir)/xmalloc.h +undo.so: $(topdir)/xmalloc.h +util.so: $(topdir)/xmalloc.h +vi_mode.so: $(topdir)/xmalloc.h +xmalloc.so: $(topdir)/xmalloc.h + +complete.o: $(topdir)/rlmbutil.h +display.o: $(topdir)/rlmbutil.h +histexpand.o: $(topdir)/rlmbutil.h +input.o: $(topdir)/rlmbutil.h +isearch.o: $(topdir)/rlmbutil.h +mbutil.o: $(topdir)/rlmbutil.h +misc.o: $(topdir)/rlmbutil.h +readline.o: $(topdir)/rlmbutil.h +search.o: $(topdir)/rlmbutil.h +text.o: $(topdir)/rlmbutil.h +vi_mode.o: $(topdir)/rlmbutil.h + +bind.so: $(topdir)/bind.c +callback.so: $(topdir)/callback.c +compat.so: $(topdir)/compat.c +complete.so: $(topdir)/complete.c +display.so: $(topdir)/display.c +funmap.so: $(topdir)/funmap.c +input.so: $(topdir)/input.c +isearch.so: $(topdir)/isearch.c +keymaps.so: $(topdir)/keymaps.c $(topdir)/emacs_keymap.c $(topdir)/vi_keymap.c +kill.so: $(topdir)/kill.c +macro.so: $(topdir)/macro.c +mbutil.so: $(topdir)/mbutil.c +misc.so: $(topdir)/mbutil.c +nls.so: $(topdir)/nls.c +parens.so: $(topdir)/parens.c +readline.so: $(topdir)/readline.c +rltty.so: $(topdir)/rltty.c +savestring.so: $(topdir)/savestring.c +search.so: $(topdir)/search.c +shell.so: $(topdir)/shell.c +signals.so: $(topdir)/signals.c +terminal.so: $(topdir)/terminal.c +text.so: $(topdir)/terminal.c +tilde.so: $(topdir)/tilde.c +undo.so: $(topdir)/undo.c +util.so: $(topdir)/util.c +vi_mode.so: $(topdir)/vi_mode.c +xmalloc.so: $(topdir)/xmalloc.c + +histexpand.so: $(topdir)/histexpand.c +histfile.so: $(topdir)/histfile.c +history.so: $(topdir)/history.c +histsearch.so: $(topdir)/histsearch.c + +bind.so: bind.c +callback.so: callback.c +comapt.so: compat.c +complete.so: complete.c +display.so: display.c +funmap.so: funmap.c +input.so: input.c +isearch.so: isearch.c +keymaps.so: keymaps.c emacs_keymap.c vi_keymap.c +kill.so: kill.c +macro.so: macro.c +mbutil.so: mbutil.c +misc.so: misc.c +nls.so: nls.c +parens.so: parens.c +readline.so: readline.c +rltty.so: rltty.c +savestring.so: savestring.c +search.so: search.c +signals.so: signals.c +shell.so: shell.c +terminal.so: terminal.c +text.so: terminal.c +tilde.so: tilde.c +undo.so: undo.c +util.so: util.c +vi_mode.so: vi_mode.c +xmalloc.so: xmalloc.c + +histexpand.so: histexpand.c +histfile.so: histfile.c +history.so: history.c +histsearch.so: histsearch.c diff --git a/readline/readline-4.3/signals.c b/readline/readline-4.3/signals.c new file mode 100644 index 00000000..0a1468b6 --- /dev/null +++ b/readline/readline-4.3/signals.c @@ -0,0 +1,398 @@ +/* signals.c -- signal handling support for readline. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include /* Just for NULL. Yuck. */ +#include +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +#if defined (GWINSZ_IN_SYS_IOCTL) +# include +#endif /* GWINSZ_IN_SYS_IOCTL */ + +#if defined (HANDLE_SIGNALS) +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" + +#if !defined (RETSIGTYPE) +# if defined (VOID_SIGHANDLER) +# define RETSIGTYPE void +# else +# define RETSIGTYPE int +# endif /* !VOID_SIGHANDLER */ +#endif /* !RETSIGTYPE */ + +#if defined (VOID_SIGHANDLER) +# define SIGHANDLER_RETURN return +#else +# define SIGHANDLER_RETURN return (0) +#endif + +/* This typedef is equivalent to the one for Function; it allows us + to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ +typedef RETSIGTYPE SigHandler (); + +#if defined (HAVE_POSIX_SIGNALS) +typedef struct sigaction sighandler_cxt; +# define rl_sigaction(s, nh, oh) sigaction(s, nh, oh) +#else +typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt; +# define sigemptyset(m) +#endif /* !HAVE_POSIX_SIGNALS */ + +static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); +static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); + +/* Exported variables for use by applications. */ + +/* If non-zero, readline will install its own signal handlers for + SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */ +int rl_catch_signals = 1; + +/* If non-zero, readline will install a signal handler for SIGWINCH. */ +#ifdef SIGWINCH +int rl_catch_sigwinch = 1; +#endif + +static int signals_set_flag; +static int sigwinch_set_flag; + +/* **************************************************************** */ +/* */ +/* Signal Handling */ +/* */ +/* **************************************************************** */ + +static sighandler_cxt old_int, old_term, old_alrm, old_quit; +#if defined (SIGTSTP) +static sighandler_cxt old_tstp, old_ttou, old_ttin; +#endif +#if defined (SIGWINCH) +static sighandler_cxt old_winch; +#endif + +/* Readline signal handler functions. */ + +static RETSIGTYPE +rl_signal_handler (sig) + int sig; +{ +#if defined (HAVE_POSIX_SIGNALS) + sigset_t set; +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) + long omask; +# else /* !HAVE_BSD_SIGNALS */ + sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */ +# endif /* !HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + + RL_SETSTATE(RL_STATE_SIGHANDLER); + +#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) + /* Since the signal will not be blocked while we are in the signal + handler, ignore it until rl_clear_signals resets the catcher. */ + if (sig == SIGINT || sig == SIGALRM) + rl_set_sighandler (sig, SIG_IGN, &dummy_cxt); +#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */ + + switch (sig) + { + case SIGINT: + rl_free_line_state (); + /* FALLTHROUGH */ + +#if defined (SIGTSTP) + case SIGTSTP: + case SIGTTOU: + case SIGTTIN: +#endif /* SIGTSTP */ + case SIGALRM: + case SIGTERM: + case SIGQUIT: + rl_cleanup_after_signal (); + +#if defined (HAVE_POSIX_SIGNALS) + sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); + sigdelset (&set, sig); +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) + omask = sigblock (0); +# endif /* HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + +#if defined (__EMX__) + signal (sig, SIG_ACK); +#endif + + kill (getpid (), sig); + + /* Let the signal that we just sent through. */ +#if defined (HAVE_POSIX_SIGNALS) + sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) + sigsetmask (omask & ~(sigmask (sig))); +# endif /* HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + + rl_reset_after_signal (); + } + + RL_UNSETSTATE(RL_STATE_SIGHANDLER); + SIGHANDLER_RETURN; +} + +#if defined (SIGWINCH) +static RETSIGTYPE +rl_sigwinch_handler (sig) + int sig; +{ + SigHandler *oh; + +#if defined (MUST_REINSTALL_SIGHANDLERS) + sighandler_cxt dummy_winch; + + /* We don't want to change old_winch -- it holds the state of SIGWINCH + disposition set by the calling application. We need this state + because we call the application's SIGWINCH handler after updating + our own idea of the screen size. */ + rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch); +#endif + + RL_SETSTATE(RL_STATE_SIGHANDLER); + rl_resize_terminal (); + + /* If another sigwinch handler has been installed, call it. */ + oh = (SigHandler *)old_winch.sa_handler; + if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL) + (*oh) (sig); + + RL_UNSETSTATE(RL_STATE_SIGHANDLER); + SIGHANDLER_RETURN; +} +#endif /* SIGWINCH */ + +/* Functions to manage signal handling. */ + +#if !defined (HAVE_POSIX_SIGNALS) +static int +rl_sigaction (sig, nh, oh) + int sig; + sighandler_cxt *nh, *oh; +{ + oh->sa_handler = signal (sig, nh->sa_handler); + return 0; +} +#endif /* !HAVE_POSIX_SIGNALS */ + +/* Set up a readline-specific signal handler, saving the old signal + information in OHANDLER. Return the old signal handler, like + signal(). */ +static SigHandler * +rl_set_sighandler (sig, handler, ohandler) + int sig; + SigHandler *handler; + sighandler_cxt *ohandler; +{ + sighandler_cxt old_handler; +#if defined (HAVE_POSIX_SIGNALS) + struct sigaction act; + + act.sa_handler = handler; + act.sa_flags = 0; /* XXX - should we set SA_RESTART for SIGWINCH? */ + sigemptyset (&act.sa_mask); + sigemptyset (&ohandler->sa_mask); + sigaction (sig, &act, &old_handler); +#else + old_handler.sa_handler = (SigHandler *)signal (sig, handler); +#endif /* !HAVE_POSIX_SIGNALS */ + + /* XXX -- assume we have memcpy */ + /* If rl_set_signals is called twice in a row, don't set the old handler to + rl_signal_handler, because that would cause infinite recursion. */ + if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler) + memcpy (ohandler, &old_handler, sizeof (sighandler_cxt)); + + return (ohandler->sa_handler); +} + +static void +rl_maybe_set_sighandler (sig, handler, ohandler) + int sig; + SigHandler *handler; + sighandler_cxt *ohandler; +{ + sighandler_cxt dummy; + SigHandler *oh; + + sigemptyset (&dummy.sa_mask); + oh = rl_set_sighandler (sig, handler, ohandler); + if (oh == (SigHandler *)SIG_IGN) + rl_sigaction (sig, ohandler, &dummy); +} + +int +rl_set_signals () +{ + sighandler_cxt dummy; + SigHandler *oh; + + if (rl_catch_signals && signals_set_flag == 0) + { + rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int); + rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term); + rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit); + + oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm); + if (oh == (SigHandler *)SIG_IGN) + rl_sigaction (SIGALRM, &old_alrm, &dummy); +#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART) + /* If the application using readline has already installed a signal + handler with SA_RESTART, SIGALRM will cause reads to be restarted + automatically, so readline should just get out of the way. Since + we tested for SIG_IGN above, we can just test for SIG_DFL here. */ + if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART)) + rl_sigaction (SIGALRM, &old_alrm, &dummy); +#endif /* HAVE_POSIX_SIGNALS */ + +#if defined (SIGTSTP) + rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp); +#endif /* SIGTSTP */ + +#if defined (SIGTTOU) + rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou); +#endif /* SIGTTOU */ + +#if defined (SIGTTIN) + rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin); +#endif /* SIGTTIN */ + + signals_set_flag = 1; + } + +#if defined (SIGWINCH) + if (rl_catch_sigwinch && sigwinch_set_flag == 0) + { + rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch); + sigwinch_set_flag = 1; + } +#endif /* SIGWINCH */ + + return 0; +} + +int +rl_clear_signals () +{ + sighandler_cxt dummy; + + if (rl_catch_signals && signals_set_flag == 1) + { + sigemptyset (&dummy.sa_mask); + + rl_sigaction (SIGINT, &old_int, &dummy); + rl_sigaction (SIGTERM, &old_term, &dummy); + rl_sigaction (SIGQUIT, &old_quit, &dummy); + rl_sigaction (SIGALRM, &old_alrm, &dummy); + +#if defined (SIGTSTP) + rl_sigaction (SIGTSTP, &old_tstp, &dummy); +#endif /* SIGTSTP */ + +#if defined (SIGTTOU) + rl_sigaction (SIGTTOU, &old_ttou, &dummy); +#endif /* SIGTTOU */ + +#if defined (SIGTTIN) + rl_sigaction (SIGTTIN, &old_ttin, &dummy); +#endif /* SIGTTIN */ + + signals_set_flag = 0; + } + +#if defined (SIGWINCH) + if (rl_catch_sigwinch && sigwinch_set_flag == 1) + { + sigemptyset (&dummy.sa_mask); + rl_sigaction (SIGWINCH, &old_winch, &dummy); + sigwinch_set_flag = 0; + } +#endif + + return 0; +} + +/* Clean up the terminal and readline state after catching a signal, before + resending it to the calling application. */ +void +rl_cleanup_after_signal () +{ + _rl_clean_up_for_exit (); + (*rl_deprep_term_function) (); + rl_clear_signals (); + rl_clear_pending_input (); +} + +/* Reset the terminal and readline state after a signal handler returns. */ +void +rl_reset_after_signal () +{ + (*rl_prep_term_function) (_rl_meta_flag); + rl_set_signals (); +} + +/* Free up the readline variable line state for the current line (undo list, + any partial history entry, any keyboard macros in progress, and any + numeric arguments in process) after catching a signal, before calling + rl_cleanup_after_signal(). */ +void +rl_free_line_state () +{ + register HIST_ENTRY *entry; + + rl_free_undo_list (); + + entry = current_history (); + if (entry) + entry->data = (char *)NULL; + + _rl_kill_kbd_macro (); + rl_clear_message (); + _rl_init_argument (); +} + +#endif /* HANDLE_SIGNALS */ diff --git a/readline/readline-4.3/support/config.guess b/readline/readline-4.3/support/config.guess new file mode 100755 index 00000000..56681081 --- /dev/null +++ b/readline/readline-4.3/support/config.guess @@ -0,0 +1,1393 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-03-20' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int dummy(){}" > $dummy.c ; + for c in cc gcc c89 c99 ; do + ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; + if test $? = 0 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $dummy.c $dummy.o $dummy.rel ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +elif (test -f /usr/5bin/uname) >/dev/null 2>&1 ; then # bash + PATH=$PATH:/usr/5bin +fi + +UNAME=`(uname) 2>/dev/null` || UNAME=unknown # bash +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + # NOTE -- begin cases added for bash (mostly legacy) -- NOTE + mac68k:machten:*:*) + echo mac68k-apple-machten${UNAME_RELEASE} + exit 0 ;; + concurrent*:*:*:*) + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo concurrent-concurrent-sysv3 + else + echo concurrent-concurrent-bsd + fi + exit 0 ;; + ppc*:SunOS:5.*:*) + echo ppc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sparc:UNIX_SV:4.*:*) + echo sparc-unknown-sysv${UNAME_RELEASE} + exit 0 ;; + mips:UNIX_SV:4.*:*) + echo mips-mips-sysv${UNAME_RELEASE} + exit 0 ;; + mips:OSF*1:*:*) + echo mips-mips-osf1 + exit 0 ;; + mips:4.4BSD:*:*) + echo mips-mips-bsd4.4 + exit 0 ;; + MIS*:SMP_DC.OSx:*:dcosx) # not the same as below + echo pyramid-pyramid-sysv4 + exit 0 ;; + news*:NEWS*:*:*) + echo mips-sony-newsos${UNAME_RELEASE} + exit 0 ;; + *370:AIX:*:*) + echo ibm370-ibm-aix${UNAME_RELEASE} + exit 0 ;; + ksr1:OSF*1:*:*) + echo ksr1-ksr-osf1 + exit 0 ;; + esa:OSF*1:*:* | ESA:OSF*:*:*) + echo esa-ibm-osf1 + exit 0 ;; + DNP*:DNIX:*:*) + echo m68k-dnix-sysv + exit 0 ;; + *3b2*:*:*:*) + echo we32k-att-sysv3 + exit 0 ;; + Alpha*:Windows_NT:*:SP*) + echo alpha-pc-opennt + exit 0 ;; + *:Windows_NT:*:SP*) + echo i386-pc-opennt + exit 0 ;; + + # NOTE -- end legacy cases added for bash -- NOTE + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + vax:OpenBSD:*:*) # bash + echo vax-dec-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:3*) + echo i386-pc-interix3 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c + test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +# NOTE -- Begin fallback cases added for bash -- NOTE +case "$UNAME" in +uts) echo uts-amdahl-sysv${UNAME_RELEASE}; exit 0 ;; +esac + +if [ -f /bin/fxc.info ]; then + echo fxc-alliant-concentrix + exit 0 +fi +# NOTE -- End fallback cases added for bash -- NOTE + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/readline/readline-4.3/support/config.sub b/readline/readline-4.3/support/config.sub new file mode 100644 index 00000000..538dc098 --- /dev/null +++ b/readline/readline-4.3/support/config.sub @@ -0,0 +1,1497 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-03-07' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dsp16xx \ + | fr30 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el | mips64vr4300 \ + | mips64vr4300el | mips64vr5000 | mips64vr5000el \ + | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ + | mipsisa32 | mipsisa64 \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ + | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ + | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + + # NOTE -- BEGIN cases added for Bash -- NOTE + butterfly-bbn* | cadmus-* | ews*-nec | masscomp-masscomp \ + | tandem-* | symmetric-* | drs6000-icl | *-*ardent | concurrent-* \ + | ksr1-* | esa-ibm | fxc-alliant | *370-amdahl | sx[45]*-nec ) + ;; + # NOTE -- END cases added for Bash -- NOTE + + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax | multimax) # bash + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hbullx20-bull) + basic_machine=m68k-bull # bash + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + ibm032-*) + basic_machine=ibmrt-ibm # bash + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386-go32) + basic_machine=i386-pc # bash + os=-go32 + ;; + i386-mingw32) + basic_machine=i386-pc # bash + os=-mingw32 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + luna88k-omron* | m88k-omron*) # bash + basic_machine=m88k-omron + ;; + magicstation*) + basic_machine=magicstation-unknown # bash + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + odt | odt3 | odt4) # SCO Open Desktop + basic_machine=i386-pc # bash + os=-sco3.2v4 + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + osr5 | sco5) # SCO Open Server + basic_machine=i386-pc # bash + os=-sco3.2v5 + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3d) + basic_machine=alpha-cray + os=-unicos + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + uw2 | unixware | unixware2) # bash + basic_machine=i386-pc + os=-sysv4.2uw2.1 + ;; + uw7 | unixware7) # bash + basic_machine=i386-pc + os=-sysv5uw7 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh3eb | sh4eb) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware7*) # bash + os=-sysv5uw7 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + # NOTE -- BEGIN CASES ADDED FOR Bash -- NOTE + -powerux* | -superux*) + ;; + # NOTE -- END CASES ADDED FOR Bash -- NOTE + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + -sysvr5) # bash + os=-sysv5 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -lynxos*) # bash + vendor=lynx + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/readline/readline-4.3/support/install.sh b/readline/readline-4.3/support/install.sh new file mode 100755 index 00000000..0cac004e --- /dev/null +++ b/readline/readline-4.3/support/install.sh @@ -0,0 +1,247 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +tranformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/readline/readline-4.3/support/mkdirs b/readline/readline-4.3/support/mkdirs new file mode 100755 index 00000000..ce4fb235 --- /dev/null +++ b/readline/readline-4.3/support/mkdirs @@ -0,0 +1,48 @@ +#! /bin/sh +# +# mkdirs - a work-alike for `mkdir -p' +# +# Chet Ramey +# chet@po.cwru.edu + +# Copyright (C) 1996-2002 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +for dir +do + + test -d "$dir" && continue + + tomake=$dir + while test -n "$dir" ; do + # dir=${dir%/*} + # dir=`expr "$dir" ':' '\(/.*\)/[^/]*'` + if dir=`expr "$dir" ':' '\(.*\)/[^/]*'`; then + tomake="$dir $tomake" + else + dir= + fi + done + + for d in $tomake + do + test -d "$d" && continue + echo mkdir "$d" + mkdir "$d" + done +done + +exit 0 diff --git a/readline/readline-4.3/support/mkdist b/readline/readline-4.3/support/mkdist new file mode 100755 index 00000000..06e6155f --- /dev/null +++ b/readline/readline-4.3/support/mkdist @@ -0,0 +1,120 @@ +#! /bin/bash - +# +# mkdist - make a distribution directory from a master manifest file +# +# usage: mkdist [-m manifest] [-s srcdir] [-r rootname] [-v] version +# +# SRCDIR defaults to src +# MANIFEST defaults to $SRCDIR/MANIFEST +# +# Chet Ramey +# chet@po.cwru.edu + +# Copyright (C) 1996-2002 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +SRCDIR=src +ROOTNAME=bash + +usage() +{ + echo usage: mkdist [-m manifest] [-s srcdir] [-r rootname] [-v] version 1>&2 + exit 2 +} + +vmsg() +{ + if [ -n "$verbose" ]; then + echo mkdist: "$@" + fi +} + +while getopts m:s:r:v name +do + case $name in + m) MANIFEST=$OPTARG ;; + s) SRCDIR=$OPTARG ;; + r) ROOTNAME=$OPTARG ;; + v) verbose=yes ;; + ?) usage ;; + esac +done + +: ${MANIFEST:=$SRCDIR/MANIFEST} + +vmsg using $MANIFEST + +shift $(( $OPTIND - 1 )) + +if [ $# -lt 1 ]; then + usage +fi + +version=$1 +newdir=${ROOTNAME}-$version + +vmsg creating distribution for $ROOTNAME version $version in $newdir + +if [ ! -d $newdir ]; then + mkdir $newdir || { echo $0: cannot make directory $newdir 1>&2 ; exit 1; } +fi + +dirmode=755 +filmode=644 + +while read fname type mode +do + [ -z "$fname" ] && continue + + case "$fname" in + \#*) continue ;; + esac + + case "$type" in + d) mkdir $newdir/$fname ;; + f) cp -p $SRCDIR/$fname $newdir/$fname ;; + s) ln -s $mode $newdir/$fname ; mode= ;; # symlink + l) ln $mode $newdir/$fname ; mode= ;; # hard link + *) echo "unknown file type $type" 1>&2 ;; + esac + + if [ -n "$mode" ]; then + chmod $mode $newdir/$fname + fi + +done < $MANIFEST + +# cut off the `-alpha' in something like `2.0-alpha', leaving just the +# numeric version +#version=${version%%-*} + +#case "$version" in +#*.*.*) vers=${version%.*} ;; +#*.*) vers=${version} ;; +#esac + +#echo $vers > $newdir/.distribution + +#case "$version" in +#*.*.*) plevel=${version##*.} ;; +#*) plevel=0 ;; +#esac +#[ -z "$plevel" ] && plevel=0 +#echo ${plevel} > $newdir/.patchlevel + +vmsg $newdir created + +exit 0 diff --git a/readline/readline-4.3/support/shlib-install b/readline/readline-4.3/support/shlib-install new file mode 100755 index 00000000..654cfa9d --- /dev/null +++ b/readline/readline-4.3/support/shlib-install @@ -0,0 +1,156 @@ +#! /bin/sh +# +# shlib-install - install a shared library and do any necessary host-specific +# post-installation configuration (like ldconfig) +# +# usage: shlib-install [-D] -O host_os -d installation-dir -i install-prog [-U] library +# +# Chet Ramey +# chet@po.cwru.edu + +# +# defaults +# +INSTALLDIR=/usr/local/lib +LDCONFIG=ldconfig + +PROGNAME=`basename $0` +USAGE="$PROGNAME [-D] -O host_os -d installation-dir -i install-prog [-U] library" + +# process options + +while [ $# -gt 0 ]; do + case "$1" in + -O) shift; host_os="$1"; shift ;; + -d) shift; INSTALLDIR="$1"; shift ;; + -i) shift; INSTALLPROG="$1" ; shift ;; + -D) echo=echo ; shift ;; + -U) uninstall=true ; shift ;; + -*) echo "$USAGE" >&2 ; exit 2;; + *) break ;; + esac +done + +# set install target name +LIBNAME="$1" + +if [ -z "$LIBNAME" ]; then + echo "$USAGE" >&2 + exit 2 +fi + +OLDSUFF=old +MV=mv +RM="rm -f" +LN="ln -s" + +# pre-install + +if [ -z "$uninstall" ]; then + ${echo} $RM ${INSTALLDIR}/${LIBNAME}.${OLDSUFF} + if [ -f "$INSTALLDIR/$LIBNAME" ]; then + ${echo} $MV $INSTALLDIR/$LIBNAME ${INSTALLDIR}/${LIBNAME}.${OLDSUFF} + fi +fi + +# install/uninstall + +if [ -z "$uninstall" ] ; then + ${echo} eval ${INSTALLPROG} $LIBNAME ${INSTALLDIR}/${LIBNAME} +else + ${echo} ${RM} ${INSTALLDIR}/${LIBNAME} +fi + +# post-install/uninstall + +# HP-UX and Darwin/MacOS X require that a shared library have execute permission +case "$host_os" in +hpux*|darwin*|macosx*) + if [ -z "$uninstall" ]; then + chmod 555 ${INSTALLDIR}/${LIBNAME} + fi ;; +*) ;; +esac + +case "$LIBNAME" in +*.*.[0-9].[0-9]) # libname.so.M.N + LINK2=`echo $LIBNAME | sed 's:\(.*\..*\.[0-9]\)\.[0-9]:\1:'` # libname.so.M + LINK1=`echo $LIBNAME | sed 's:\(.*\..*\)\.[0-9]\.[0-9]:\1:'` # libname.so + ;; +*.*.[0-9]) # libname.so.M + LINK1=`echo $LIBNAME | sed 's:\(.*\..*\)\.[0-9]:\1:'` # libname.so + ;; +*.[0-9]) # libname.M + LINK1=`echo $LIBNAME | sed 's:\(.*\)\.[0-9]:\1:'` # libname + ;; +*.[0-9].[0-9].dylib) # libname.M.N.dylib + LINK2=`echo $LIBNAME | sed 's:\(.*\.[0-9]\)\.[0-9]:\1:'` # libname.M.dylib + LINK1=`echo $LIBNAME | sed 's:\(.*\)\.[0-9]\.[0-9]:\1:'` # libname.dylib +esac + +INSTALL_LINK1='cd $INSTALLDIR ; ln -s $LIBNAME $LINK1' +INSTALL_LINK2='cd $INSTALLDIR ; ln -s $LIBNAME $LINK2' + +# +# Create symlinks to the installed library. This section is incomplete. +# +case "$host_os" in +*linux*|bsdi4*|*gnu*|darwin*|macosx*) + # libname.so.M -> libname.so.M.N + ${echo} ${RM} ${INSTALLDIR}/$LINK2 + if [ -z "$uninstall" ]; then + ${echo} ln -s $LIBNAME ${INSTALLDIR}/$LINK2 + fi + + # libname.so -> libname.so.M.N + ${echo} ${RM} ${INSTALLDIR}/$LINK1 + if [ -z "$uninstall" ]; then + ${echo} ln -s $LIBNAME ${INSTALLDIR}/$LINK1 + fi + ;; + +solaris2*|aix4.[2-9]*|osf*|irix[56]*|sysv[45]*|dgux*) + # libname.so -> libname.so.M + ${echo} ${RM} ${INSTALLDIR}/$LINK1 + if [ -z "$uninstall" ]; then + ${echo} ln -s $LIBNAME ${INSTALLDIR}/$LINK1 + fi + ;; + + +# FreeBSD 3.x and above can have either a.out or ELF shared libraries +freebsd[3-9]*|freebsdelf[3-9]*|freebsdaout[3-9]*) + if [ -x /usr/bin/objformat ] && [ "`/usr/bin/objformat`" = "elf" ]; then + # libname.so -> libname.so.M + ${echo} ${RM} ${INSTALLDIR}/$LINK1 + if [ -z "$uninstall" ]; then + ${echo} ln -s $LIBNAME ${INSTALLDIR}/$LINK1 + fi + else + # libname.so.M -> libname.so.M.N + ${echo} ${RM} ${INSTALLDIR}/$LINK2 + if [ -z "$uninstall" ]; then + ${echo} ln -s $LIBNAME ${INSTALLDIR}/$LINK2 + fi + + # libname.so -> libname.so.M.N + ${echo} ${RM} ${INSTALLDIR}/$LINK1 + if [ -z "$uninstall" ]; then + ${echo} ln -s $LIBNAME ${INSTALLDIR}/$LINK1 + fi + fi + ;; + +hpux1*) + # libname.sl -> libname.M + ${echo} ${RM} ${INSTALLDIR}/$LINK1.sl + if [ -z "$uninstall" ]; then +# ${echo} ln -s $LIBNAME ${INSTALLDIR}/${LINK1}.sl + ${echo} ln -s $LIBNAME ${INSTALLDIR}/${LINK1} + fi + ;; + +*) ;; +esac + +exit 0 diff --git a/readline/readline-4.3/support/shobj-conf b/readline/readline-4.3/support/shobj-conf new file mode 100755 index 00000000..6bd7fb12 --- /dev/null +++ b/readline/readline-4.3/support/shobj-conf @@ -0,0 +1,458 @@ +#! /bin/sh +# +# shobj-conf -- output a series of variable assignments to be substituted +# into a Makefile by configure which specify system-dependent +# information for creating shared objects that may be loaded +# into bash with `enable -f' +# +# usage: shobj-conf [-C compiler] -c host_cpu -o host_os -v host_vendor +# +# Chet Ramey +# chet@po.cwru.edu + +# Copyright (C) 1996-2002 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +# +# defaults +# +SHOBJ_STATUS=supported +SHLIB_STATUS=supported + +SHOBJ_CC=cc +SHOBJ_CFLAGS= +SHOBJ_LD= +SHOBJ_LDFLAGS= +SHOBJ_XLDFLAGS= +SHOBJ_LIBS= + +SHLIB_XLDFLAGS= +SHLIB_LIBS= +SHLIB_LIBSUFF='so' + +SHLIB_LIBVERSION='$(SHLIB_LIBSUFF)' + +PROGNAME=`basename $0` +USAGE="$PROGNAME [-C compiler] -c host_cpu -o host_os -v host_vendor" + +while [ $# -gt 0 ]; do + case "$1" in + -C) shift; SHOBJ_CC="$1"; shift ;; + -c) shift; host_cpu="$1"; shift ;; + -o) shift; host_os="$1"; shift ;; + -v) shift; host_vendor="$1"; shift ;; + *) echo "$USAGE" >&2 ; exit 2;; + esac +done + +case "${host_os}-${SHOBJ_CC}" in +sunos4*-*gcc*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD=/usr/bin/ld + SHOBJ_LDFLAGS='-assert pure-text' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +sunos4*) + SHOBJ_CFLAGS=-pic + SHOBJ_LD=/usr/bin/ld + SHOBJ_LDFLAGS='-assert pure-text' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +sunos5*-*gcc*|solaris2*-*gcc*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='${CC}' + # This line works for the Solaris linker in /usr/ccs/bin/ld + SHOBJ_LDFLAGS='-shared -Wl,-i -Wl,-h,$@' + # This line works for the GNU ld +# SHOBJ_LDFLAGS='-shared -Wl,-h,$@' + +# SHLIB_XLDFLAGS='-R $(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sunos5*|solaris2*) + SHOBJ_CFLAGS='-K pic' + SHOBJ_LD=/usr/ccs/bin/ld + SHOBJ_LDFLAGS='-G -dy -z text -i -h $@' + +# SHLIB_XLDFLAGS='-R $(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +# All versions of Linux or the semi-mythical GNU Hurd. +linux*|gnu*) + SHOBJ_CFLAGS=-fPIC + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-soname,$@' + + SHLIB_XLDFLAGS='-Wl,-rpath,$(libdir) -Wl,-soname,`basename $@ $(SHLIB_MINOR)`' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +freebsd2* | netbsd*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-x -Bshareable' + + SHLIB_XLDFLAGS='-R$(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +# FreeBSD-3.x ELF +freebsd[3-9]*|freebsdelf[3-9]*|freebsdaout[3-9]*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='${CC}' + + if [ -x /usr/bin/objformat ] && [ "`/usr/bin/objformat`" = "elf" ]; then + SHOBJ_LDFLAGS='-shared -Wl,-soname,$@' + + SHLIB_XLDFLAGS='-Wl,-rpath,$(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + else + SHOBJ_LDFLAGS='-shared' + + SHLIB_XLDFLAGS='-R$(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + fi + ;; + +# Darwin/MacOS X +darwin*|macosx*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=supported + + SHOBJ_CFLAGS='-dynamic -fno-common' + + SHOBJ_LD=/usr/bin/libtool + + SHLIB_LIBVERSION='$(SHLIB_MAJOR)$(SHLIB_MINOR).$(SHLIB_LIBSUFF)' + SHLIB_LIBSUFF='dylib' + + SHOBJ_LDFLAGS='-dynamic' + SHLIB_XLDFLAGS='-arch_only `/usr/bin/arch` -install_name $(libdir)/$@ -current_version $(SHLIB_MAJOR)$(SHLIB_MINOR) -compatibility_version $(SHLIB_MAJOR) -v' + + SHLIB_LIBS='-lSystem' + ;; + +openbsd*) + SHOBJ_CFLAGS=-fPIC + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_XLDFLAGS='-R$(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +bsdi2*) + SHOBJ_CC=shlicc2 + SHOBJ_CFLAGS= + SHOBJ_LD=ld + SHOBJ_LDFLAGS=-r + SHOBJ_LIBS=-lc_s.2.1.0 + + # BSD/OS 2.x and 3.x `shared libraries' are too much of a pain in + # the ass -- they require changing {/usr/lib,etc}/shlib.map on + # each system, and the library creation process is byzantine + SHLIB_STATUS=unsupported + ;; + +bsdi3*) + SHOBJ_CC=shlicc2 + SHOBJ_CFLAGS= + SHOBJ_LD=ld + SHOBJ_LDFLAGS=-r + SHOBJ_LIBS=-lc_s.3.0.0 + + # BSD/OS 2.x and 3.x `shared libraries' are too much of a pain in + # the ass -- they require changing {/usr/lib,etc}/shlib.map on + # each system, and the library creation process is byzantine + SHLIB_STATUS=unsupported + ;; + +bsdi4*) + # BSD/OS 4.x now supports ELF and SunOS-style dynamically-linked + # shared libraries. gcc 2.x is the standard compiler, and the + # `normal' gcc options should work as they do in Linux. + + SHOBJ_CFLAGS=-fPIC + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-soname,$@' + + SHLIB_XLDFLAGS='-Wl,-soname,`basename $@ $(SHLIB_MINOR)`' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' + ;; + +osf*-*gcc*) + # Fix to use gcc linker driver from bfischer@TechFak.Uni-Bielefeld.DE + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-soname,$@' + + SHLIB_XLDFLAGS='-rpath $(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +osf*) + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-shared -soname $@ -expect_unresolved "*"' + + SHLIB_XLDFLAGS='-rpath $(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +aix4.[2-9]*-*gcc*) # lightly tested by jik@cisco.com + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='ld' + SHOBJ_LDFLAGS='-bdynamic -bnoentry -bexpall' + SHOBJ_XLDFLAGS='-G' + + SHLIB_XLDFLAGS='-bM:SRE' + SHLIB_LIBS='-lcurses -lc' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +aix4.[2-9]*) + SHOBJ_CFLAGS=-K + SHOBJ_LD='ld' + SHOBJ_LDFLAGS='-bdynamic -bnoentry -bexpall' + SHOBJ_XLDFLAGS='-G' + + SHLIB_XLDFLAGS='-bM:SRE' + SHLIB_LIBS='-lcurses -lc' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +# +# THE FOLLOWING ARE UNTESTED -- and some may not support the dlopen interface +# +irix[56]*-*gcc*) + SHOBJ_CFLAGS='-fpic' + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-soname,$@' + + SHLIB_XLDFLAGS='-Wl,-rpath,$(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +irix[56]*) + SHOBJ_CFLAGS='-K PIC' + SHOBJ_LD=ld +# SHOBJ_LDFLAGS='-call_shared -hidden_symbol -no_unresolved -soname $@' +# Change from David Kaelbling . If you have problems, +# remove the `-no_unresolved' + SHOBJ_LDFLAGS='-shared -no_unresolved -soname $@' + + SHLIB_XLDFLAGS='-rpath $(libdir)' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +hpux9*-*gcc*) + # must use gcc; the bundled cc cannot compile PIC code + SHOBJ_CFLAGS='-fpic' + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-b -Wl,+s' + + SHLIB_XLDFLAGS='-Wl,+b,$(libdir)' + SHLIB_LIBSUFF='sl' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +hpux9*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=unsupported + + # If you are using the HP ANSI C compiler, you can uncomment and use + # this code (I have not tested it) +# SHOBJ_STATUS=supported +# SHLIB_STATUS=supported +# +# SHOBJ_CFLAGS='+z' +# SHOBJ_LD='ld' +# SHOBJ_LDFLAGS='-b +s' +# +# SHLIB_XLDFLAGS='+b $(libdir)' +# SHLIB_LIBSUFF='sl' +# SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + + ;; + +hpux10*-*gcc*) + # must use gcc; the bundled cc cannot compile PIC code + SHOBJ_CFLAGS='-fpic' + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared -Wl,-b -Wl,+s' + + SHLIB_XLDFLAGS='-Wl,+h,$@ -Wl,+b,$(libdir)' + SHLIB_LIBSUFF='sl' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +hpux10*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=unsupported + + # If you are using the HP ANSI C compiler, you can uncomment and use + # this code (I have not tested it) +# SHOBJ_STATUS=supported +# SHLIB_STATUS=supported +# +# SHOBJ_CFLAGS='+z' +# SHOBJ_LD='ld' +# SHOBJ_LDFLAGS='-b +s +h $@' +# +# SHLIB_XLDFLAGS='+b $(libdir)' +# SHLIB_LIBSUFF='sl' +# SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + + ;; + +hpux11*-*gcc*) + # must use gcc; the bundled cc cannot compile PIC code + SHOBJ_CFLAGS='-fpic' + SHOBJ_LD='${CC}' +# SHOBJ_LDFLAGS='-shared -Wl,-b -Wl,-B,symbolic -Wl,+s -Wl,+std -Wl,+h,$@' + SHOBJ_LDFLAGS='-shared -fpic -Wl,-b -Wl,+s -Wl,+h,$@' + + SHLIB_XLDFLAGS='-Wl,+b,$(libdir)' + SHLIB_LIBSUFF='sl' + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +hpux11*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=unsupported + + # If you are using the HP ANSI C compiler, you can uncomment and use + # this code (I have not tested it) +# SHOBJ_STATUS=supported +# SHLIB_STATUS=supported +# +# SHOBJ_CFLAGS='+z' +# SHOBJ_LD='ld' +# SHOBJ_LDFLAGS='-b +s +h $@' +# +# SHLIB_XLDFLAGS='+b $(libdir)' +# SHLIB_LIBSUFF='sl' +# SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + + ;; + +sysv4*-*gcc*) + SHOBJ_CFLAGS=-shared + SHOBJ_LDFLAGS='-shared -h $@' + SHOBJ_LD='${CC}' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sysv4*) + SHOBJ_CFLAGS='-K PIC' + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-dy -z text -G -h $@' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sco3.2v5*-*gcc*) + SHOBJ_CFLAGS='-fpic' # DEFAULTS TO ELF + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sco3.2v5*) + SHOBJ_CFLAGS='-K pic -b elf' + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-G -b elf -dy -z text -h $@' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sysv5uw7*-*gcc*) + SHOBJ_CFLAGS='-fpic' + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +sysv5uw7*) + SHOBJ_CFLAGS='-K PIC' + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-G -dy -z text -h $@' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +dgux*-*gcc*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +dgux*) + SHOBJ_CFLAGS='-K pic' + SHOBJ_LD=ld + SHOBJ_LDFLAGS='-G -dy -h $@' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +msdos*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=unsupported + ;; + +# +# Rely on correct gcc configuration for everything else +# +*-*gcc*) + SHOBJ_CFLAGS=-fpic + SHOBJ_LD='${CC}' + SHOBJ_LDFLAGS='-shared' + + SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' + ;; + +*) + SHOBJ_STATUS=unsupported + SHLIB_STATUS=unsupported + ;; + +esac + +echo SHOBJ_CC=\'"$SHOBJ_CC"\' +echo SHOBJ_CFLAGS=\'"$SHOBJ_CFLAGS"\' +echo SHOBJ_LD=\'"$SHOBJ_LD"\' +echo SHOBJ_LDFLAGS=\'"$SHOBJ_LDFLAGS"\' +echo SHOBJ_XLDFLAGS=\'"$SHOBJ_XLDFLAGS"\' +echo SHOBJ_LIBS=\'"$SHOBJ_LIBS"\' + +echo SHLIB_XLDFLAGS=\'"$SHLIB_XLDFLAGS"\' +echo SHLIB_LIBS=\'"$SHLIB_LIBS"\' +echo SHLIB_LIBSUFF=\'"$SHLIB_LIBSUFF"\' +echo SHLIB_LIBVERSION=\'"$SHLIB_LIBVERSION"\' + +echo SHOBJ_STATUS=\'"$SHOBJ_STATUS"\' +echo SHLIB_STATUS=\'"$SHLIB_STATUS"\' + +exit 0 diff --git a/readline/readline-4.3/support/wcwidth.c b/readline/readline-4.3/support/wcwidth.c new file mode 100644 index 00000000..ace9a3ab --- /dev/null +++ b/readline/readline-4.3/support/wcwidth.c @@ -0,0 +1,236 @@ +/* + * This is an implementation of wcwidth() and wcswidth() as defined in + * "The Single UNIX Specification, Version 2, The Open Group, 1997" + * + * + * Markus Kuhn -- 2001-09-08 -- public domain + */ + +#include + +struct interval { + unsigned short first; + unsigned short last; +}; + +/* auxiliary function for binary search in interval table */ +static int bisearch(wchar_t ucs, const struct interval *table, int max) { + int min = 0; + int mid; + + if (ucs < table[0].first || ucs > table[max].last) + return 0; + while (max >= min) { + mid = (min + max) / 2; + if (ucs > table[mid].last) + min = mid + 1; + else if (ucs < table[mid].first) + max = mid - 1; + else + return 1; + } + + return 0; +} + + +/* The following functions define the column width of an ISO 10646 + * character as follows: + * + * - The null character (U+0000) has a column width of 0. + * + * - Other C0/C1 control characters and DEL will lead to a return + * value of -1. + * + * - Non-spacing and enclosing combining characters (general + * category code Mn or Me in the Unicode database) have a + * column width of 0. + * + * - Other format characters (general category code Cf in the Unicode + * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0. + * + * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) + * have a column width of 0. + * + * - Spacing characters in the East Asian Wide (W) or East Asian + * FullWidth (F) category as defined in Unicode Technical + * Report #11 have a column width of 2. + * + * - All remaining characters (including all printable + * ISO 8859-1 and WGL4 characters, Unicode control characters, + * etc.) have a column width of 1. + * + * This implementation assumes that wchar_t characters are encoded + * in ISO 10646. + */ + +int wcwidth(wchar_t ucs) +{ + /* sorted list of non-overlapping intervals of non-spacing characters */ + static const struct interval combining[] = { + { 0x0300, 0x034E }, { 0x0360, 0x0362 }, { 0x0483, 0x0486 }, + { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 }, + { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, + { 0x05C4, 0x05C4 }, { 0x064B, 0x0655 }, { 0x0670, 0x0670 }, + { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, + { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A }, + { 0x07A6, 0x07B0 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C }, + { 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 }, + { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC }, + { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 }, + { 0x0A02, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 }, + { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 }, + { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 }, + { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 0x0B01, 0x0B01 }, + { 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, + { 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, + { 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, + { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, + { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, + { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA }, + { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 }, + { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 }, + { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD }, + { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, + { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 }, + { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC }, + { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, { 0x1032, 0x1032 }, + { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, { 0x1058, 0x1059 }, + { 0x1160, 0x11FF }, { 0x17B7, 0x17BD }, { 0x17C6, 0x17C6 }, + { 0x17C9, 0x17D3 }, { 0x180B, 0x180E }, { 0x18A9, 0x18A9 }, + { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x206A, 0x206F }, + { 0x20D0, 0x20E3 }, { 0x302A, 0x302F }, { 0x3099, 0x309A }, + { 0xFB1E, 0xFB1E }, { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, + { 0xFFF9, 0xFFFB } + }; + + /* test for 8-bit control characters */ + if (ucs == 0) + return 0; + if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) + return -1; + + /* binary search in table of non-spacing characters */ + if (bisearch(ucs, combining, + sizeof(combining) / sizeof(struct interval) - 1)) + return 0; + + /* if we arrive here, ucs is not a combining or C0/C1 control character */ + + return 1 + + (ucs >= 0x1100 && + (ucs <= 0x115f || /* Hangul Jamo init. consonants */ + (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a && + ucs != 0x303f) || /* CJK ... Yi */ + (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ + (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ + (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ + (ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */ + (ucs >= 0xffe0 && ucs <= 0xffe6) || + (ucs >= 0x20000 && ucs <= 0x2ffff))); +} + + +int wcswidth(const wchar_t *pwcs, size_t n) +{ + int w, width = 0; + + for (;*pwcs && n-- > 0; pwcs++) + if ((w = wcwidth(*pwcs)) < 0) + return -1; + else + width += w; + + return width; +} + + +/* + * The following function is the same as wcwidth(), except that + * spacing characters in the East Asian Ambiguous (A) category as + * defined in Unicode Technical Report #11 have a column width of 2. + * This experimental variant might be useful for users of CJK legacy + * encodings who want to migrate to UCS. It is not otherwise + * recommended for general use. + */ +static int wcwidth_cjk(wchar_t ucs) +{ + /* sorted list of non-overlapping intervals of East Asian Ambiguous + * characters */ + static const struct interval ambiguous[] = { + { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 }, + { 0x00AA, 0x00AA }, { 0x00AD, 0x00AE }, { 0x00B0, 0x00B4 }, + { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 }, + { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 }, + { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED }, + { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA }, + { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 }, + { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B }, + { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 }, + { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 }, + { 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 }, + { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE }, + { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 }, + { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA }, + { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 }, + { 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB }, + { 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB }, + { 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0300, 0x034E }, + { 0x0360, 0x0362 }, { 0x0391, 0x03A1 }, { 0x03A3, 0x03A9 }, + { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 }, { 0x0401, 0x0401 }, + { 0x0410, 0x044F }, { 0x0451, 0x0451 }, { 0x2010, 0x2010 }, + { 0x2013, 0x2016 }, { 0x2018, 0x2019 }, { 0x201C, 0x201D }, + { 0x2020, 0x2022 }, { 0x2024, 0x2027 }, { 0x2030, 0x2030 }, + { 0x2032, 0x2033 }, { 0x2035, 0x2035 }, { 0x203B, 0x203B }, + { 0x203E, 0x203E }, { 0x2074, 0x2074 }, { 0x207F, 0x207F }, + { 0x2081, 0x2084 }, { 0x20AC, 0x20AC }, { 0x2103, 0x2103 }, + { 0x2105, 0x2105 }, { 0x2109, 0x2109 }, { 0x2113, 0x2113 }, + { 0x2116, 0x2116 }, { 0x2121, 0x2122 }, { 0x2126, 0x2126 }, + { 0x212B, 0x212B }, { 0x2153, 0x2155 }, { 0x215B, 0x215E }, + { 0x2160, 0x216B }, { 0x2170, 0x2179 }, { 0x2190, 0x2199 }, + { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 }, { 0x21D4, 0x21D4 }, + { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 }, { 0x2202, 0x2203 }, + { 0x2207, 0x2208 }, { 0x220B, 0x220B }, { 0x220F, 0x220F }, + { 0x2211, 0x2211 }, { 0x2215, 0x2215 }, { 0x221A, 0x221A }, + { 0x221D, 0x2220 }, { 0x2223, 0x2223 }, { 0x2225, 0x2225 }, + { 0x2227, 0x222C }, { 0x222E, 0x222E }, { 0x2234, 0x2237 }, + { 0x223C, 0x223D }, { 0x2248, 0x2248 }, { 0x224C, 0x224C }, + { 0x2252, 0x2252 }, { 0x2260, 0x2261 }, { 0x2264, 0x2267 }, + { 0x226A, 0x226B }, { 0x226E, 0x226F }, { 0x2282, 0x2283 }, + { 0x2286, 0x2287 }, { 0x2295, 0x2295 }, { 0x2299, 0x2299 }, + { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF }, { 0x2312, 0x2312 }, + { 0x2329, 0x232A }, { 0x2460, 0x24BF }, { 0x24D0, 0x24E9 }, + { 0x2500, 0x254B }, { 0x2550, 0x2574 }, { 0x2580, 0x258F }, + { 0x2592, 0x2595 }, { 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, + { 0x25B2, 0x25B3 }, { 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, + { 0x25C0, 0x25C1 }, { 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, + { 0x25CE, 0x25D1 }, { 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, + { 0x2605, 0x2606 }, { 0x2609, 0x2609 }, { 0x260E, 0x260F }, + { 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 }, + { 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 }, + { 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F }, + { 0x273D, 0x273D }, { 0x3008, 0x300B }, { 0x3014, 0x3015 }, + { 0x3018, 0x301B }, { 0xFFFD, 0xFFFD } + }; + + /* binary search in table of non-spacing characters */ + if (bisearch(ucs, ambiguous, + sizeof(ambiguous) / sizeof(struct interval) - 1)) + return 2; + + return wcwidth(ucs); +} + + +int wcswidth_cjk(const wchar_t *pwcs, size_t n) +{ + int w, width = 0; + + for (;*pwcs && n-- > 0; pwcs++) + if ((w = wcwidth_cjk(*pwcs)) < 0) + return -1; + else + width += w; + + return width; +} diff --git a/readline/readline-4.3/tcap.h b/readline/readline-4.3/tcap.h new file mode 100644 index 00000000..58ab894d --- /dev/null +++ b/readline/readline-4.3/tcap.h @@ -0,0 +1,60 @@ +/* tcap.h -- termcap library functions and variables. */ + +/* Copyright (C) 1996 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RLTCAP_H_) +#define _RLTCAP_H_ + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#if defined (HAVE_TERMCAP_H) +# if defined (__linux__) && !defined (SPEED_T_IN_SYS_TYPES) +# include "rltty.h" +# endif +# include +#else + +/* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC. + Unfortunately, PC is a global variable used by the termcap library. */ +#ifdef PC +# undef PC +#endif + +extern char PC; +extern char *UP, *BC; + +extern short ospeed; + +extern int tgetent (); +extern int tgetflag (); +extern int tgetnum (); +extern char *tgetstr (); + +extern int tputs (); + +extern char *tgoto (); + +#endif /* HAVE_TERMCAP_H */ + +#endif /* !_RLTCAP_H_ */ diff --git a/readline/readline-4.3/terminal.c b/readline/readline-4.3/terminal.c new file mode 100644 index 00000000..f3f5b6c4 --- /dev/null +++ b/readline/readline-4.3/terminal.c @@ -0,0 +1,662 @@ +/* terminal.c -- controlling the terminal with termcap. */ + +/* Copyright (C) 1996 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include "posixstat.h" +#include +#if defined (HAVE_SYS_FILE_H) +# include +#endif /* HAVE_SYS_FILE_H */ + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_LOCALE_H) +# include +#endif + +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ) +# include +#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */ + +#include "rltty.h" +#include "tcap.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + +#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay) +#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc) + +/* **************************************************************** */ +/* */ +/* Terminal and Termcap */ +/* */ +/* **************************************************************** */ + +static char *term_buffer = (char *)NULL; +static char *term_string_buffer = (char *)NULL; + +static int tcap_initialized; + +#if !defined (__linux__) +# if defined (__EMX__) || defined (NEED_EXTERN_PC) +extern +# endif /* __EMX__ || NEED_EXTERN_PC */ +char PC, *BC, *UP; +#endif /* __linux__ */ + +/* Some strings to control terminal actions. These are output by tputs (). */ +char *_rl_term_clreol; +char *_rl_term_clrpag; +char *_rl_term_cr; +char *_rl_term_backspace; +char *_rl_term_goto; +char *_rl_term_pc; + +/* Non-zero if we determine that the terminal can do character insertion. */ +int _rl_terminal_can_insert = 0; + +/* How to insert characters. */ +char *_rl_term_im; +char *_rl_term_ei; +char *_rl_term_ic; +char *_rl_term_ip; +char *_rl_term_IC; + +/* How to delete characters. */ +char *_rl_term_dc; +char *_rl_term_DC; + +#if defined (HACK_TERMCAP_MOTION) +char *_rl_term_forward_char; +#endif /* HACK_TERMCAP_MOTION */ + +/* How to go up a line. */ +char *_rl_term_up; + +/* A visible bell; char if the terminal can be made to flash the screen. */ +static char *_rl_visible_bell; + +/* Non-zero means the terminal can auto-wrap lines. */ +int _rl_term_autowrap; + +/* Non-zero means that this terminal has a meta key. */ +static int term_has_meta; + +/* The sequences to write to turn on and off the meta key, if this + terminal has one. */ +static char *_rl_term_mm; +static char *_rl_term_mo; + +/* The key sequences output by the arrow keys, if this terminal has any. */ +static char *_rl_term_ku; +static char *_rl_term_kd; +static char *_rl_term_kr; +static char *_rl_term_kl; + +/* How to initialize and reset the arrow keys, if this terminal has any. */ +static char *_rl_term_ks; +static char *_rl_term_ke; + +/* The key sequences sent by the Home and End keys, if any. */ +static char *_rl_term_kh; +static char *_rl_term_kH; +static char *_rl_term_at7; /* @7 */ + +/* Insert key */ +static char *_rl_term_kI; + +/* Cursor control */ +static char *_rl_term_vs; /* very visible */ +static char *_rl_term_ve; /* normal */ + +static void bind_termcap_arrow_keys PARAMS((Keymap)); + +/* Variables that hold the screen dimensions, used by the display code. */ +int _rl_screenwidth, _rl_screenheight, _rl_screenchars; + +/* Non-zero means the user wants to enable the keypad. */ +int _rl_enable_keypad; + +/* Non-zero means the user wants to enable a meta key. */ +int _rl_enable_meta = 1; + +#if defined (__EMX__) +static void +_emx_get_screensize (swp, shp) + int *swp, *shp; +{ + int sz[2]; + + _scrsize (sz); + + if (swp) + *swp = sz[0]; + if (shp) + *shp = sz[1]; +} +#endif + +/* Get readline's idea of the screen size. TTY is a file descriptor open + to the terminal. If IGNORE_ENV is true, we do not pay attention to the + values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being + non-null serve to check whether or not we have initialized termcap. */ +void +_rl_get_screen_size (tty, ignore_env) + int tty, ignore_env; +{ + char *ss; +#if defined (TIOCGWINSZ) + struct winsize window_size; +#endif /* TIOCGWINSZ */ + +#if defined (TIOCGWINSZ) + if (ioctl (tty, TIOCGWINSZ, &window_size) == 0) + { + _rl_screenwidth = (int) window_size.ws_col; + _rl_screenheight = (int) window_size.ws_row; + } +#endif /* TIOCGWINSZ */ + +#if defined (__EMX__) + _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight); +#endif + + /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV + is unset. */ + if (_rl_screenwidth <= 0) + { + if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS"))) + _rl_screenwidth = atoi (ss); + +#if !defined (__DJGPP__) + if (_rl_screenwidth <= 0 && term_string_buffer) + _rl_screenwidth = tgetnum ("co"); +#endif + } + + /* Environment variable LINES overrides setting of "li" if IGNORE_ENV + is unset. */ + if (_rl_screenheight <= 0) + { + if (ignore_env == 0 && (ss = sh_get_env_value ("LINES"))) + _rl_screenheight = atoi (ss); + +#if !defined (__DJGPP__) + if (_rl_screenheight <= 0 && term_string_buffer) + _rl_screenheight = tgetnum ("li"); +#endif + } + + /* If all else fails, default to 80x24 terminal. */ + if (_rl_screenwidth <= 1) + _rl_screenwidth = 80; + + if (_rl_screenheight <= 0) + _rl_screenheight = 24; + + /* If we're being compiled as part of bash, set the environment + variables $LINES and $COLUMNS to new values. Otherwise, just + do a pair of putenv () or setenv () calls. */ + sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth); + + if (_rl_term_autowrap == 0) + _rl_screenwidth--; + + _rl_screenchars = _rl_screenwidth * _rl_screenheight; +} + +void +_rl_set_screen_size (rows, cols) + int rows, cols; +{ + if (rows == 0 || cols == 0) + return; + + _rl_screenheight = rows; + _rl_screenwidth = cols; + + if (_rl_term_autowrap == 0) + _rl_screenwidth--; + + _rl_screenchars = _rl_screenwidth * _rl_screenheight; +} + +void +rl_set_screen_size (rows, cols) + int rows, cols; +{ + _rl_set_screen_size (rows, cols); +} + +void +rl_get_screen_size (rows, cols) + int *rows, *cols; +{ + if (rows) + *rows = _rl_screenheight; + if (cols) + *cols = _rl_screenwidth; +} + +void +rl_resize_terminal () +{ + if (readline_echoing_p) + { + _rl_get_screen_size (fileno (rl_instream), 1); + if (CUSTOM_REDISPLAY_FUNC ()) + rl_forced_update_display (); + else + _rl_redisplay_after_sigwinch (); + } +} + +struct _tc_string { + const char *tc_var; + char **tc_value; +}; + +/* This should be kept sorted, just in case we decide to change the + search algorithm to something smarter. */ +static struct _tc_string tc_strings[] = +{ + { "@7", &_rl_term_at7 }, + { "DC", &_rl_term_DC }, + { "IC", &_rl_term_IC }, + { "ce", &_rl_term_clreol }, + { "cl", &_rl_term_clrpag }, + { "cr", &_rl_term_cr }, + { "dc", &_rl_term_dc }, + { "ei", &_rl_term_ei }, + { "ic", &_rl_term_ic }, + { "im", &_rl_term_im }, + { "kH", &_rl_term_kH }, /* home down ?? */ + { "kI", &_rl_term_kI }, /* insert */ + { "kd", &_rl_term_kd }, + { "ke", &_rl_term_ke }, /* end keypad mode */ + { "kh", &_rl_term_kh }, /* home */ + { "kl", &_rl_term_kl }, + { "kr", &_rl_term_kr }, + { "ks", &_rl_term_ks }, /* start keypad mode */ + { "ku", &_rl_term_ku }, + { "le", &_rl_term_backspace }, + { "mm", &_rl_term_mm }, + { "mo", &_rl_term_mo }, +#if defined (HACK_TERMCAP_MOTION) + { "nd", &_rl_term_forward_char }, +#endif + { "pc", &_rl_term_pc }, + { "up", &_rl_term_up }, + { "vb", &_rl_visible_bell }, + { "vs", &_rl_term_vs }, + { "ve", &_rl_term_ve }, +}; + +#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string)) + +/* Read the desired terminal capability strings into BP. The capabilities + are described in the TC_STRINGS table. */ +static void +get_term_capabilities (bp) + char **bp; +{ +#if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */ + register int i; + + for (i = 0; i < NUM_TC_STRINGS; i++) +# ifdef __LCC__ + *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp); +# else + *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp); +# endif +#endif + tcap_initialized = 1; +} + +int +_rl_init_terminal_io (terminal_name) + const char *terminal_name; +{ + const char *term; + char *buffer; + int tty, tgetent_ret; + + term = terminal_name ? terminal_name : sh_get_env_value ("TERM"); + _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL; + tty = rl_instream ? fileno (rl_instream) : 0; + _rl_screenwidth = _rl_screenheight = 0; + + if (term == 0) + term = "dumb"; + + /* I've separated this out for later work on not calling tgetent at all + if the calling application has supplied a custom redisplay function, + (and possibly if the application has supplied a custom input function). */ + if (CUSTOM_REDISPLAY_FUNC()) + { + tgetent_ret = -1; + } + else + { + if (term_string_buffer == 0) + term_string_buffer = (char *)xmalloc(2032); + + if (term_buffer == 0) + term_buffer = (char *)xmalloc(4080); + + buffer = term_string_buffer; + + tgetent_ret = tgetent (term_buffer, term); + } + + if (tgetent_ret <= 0) + { + FREE (term_string_buffer); + FREE (term_buffer); + buffer = term_buffer = term_string_buffer = (char *)NULL; + + _rl_term_autowrap = 0; /* used by _rl_get_screen_size */ + +#if defined (__EMX__) + _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight); + _rl_screenwidth--; +#else /* !__EMX__ */ + _rl_get_screen_size (tty, 0); +#endif /* !__EMX__ */ + + /* Defaults. */ + if (_rl_screenwidth <= 0 || _rl_screenheight <= 0) + { + _rl_screenwidth = 79; + _rl_screenheight = 24; + } + + /* Everything below here is used by the redisplay code (tputs). */ + _rl_screenchars = _rl_screenwidth * _rl_screenheight; + _rl_term_cr = "\r"; + _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL; + _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL; + _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL; + _rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL; + _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL; + _rl_term_mm = _rl_term_mo = (char *)NULL; + _rl_term_ve = _rl_term_vs = (char *)NULL; +#if defined (HACK_TERMCAP_MOTION) + term_forward_char = (char *)NULL; +#endif + _rl_terminal_can_insert = term_has_meta = 0; + + /* Reasonable defaults for tgoto(). Readline currently only uses + tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we + change that later... */ + PC = '\0'; + BC = _rl_term_backspace = "\b"; + UP = _rl_term_up; + + return 0; + } + + get_term_capabilities (&buffer); + + /* Set up the variables that the termcap library expects the application + to provide. */ + PC = _rl_term_pc ? *_rl_term_pc : 0; + BC = _rl_term_backspace; + UP = _rl_term_up; + + if (!_rl_term_cr) + _rl_term_cr = "\r"; + + _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn"); + + _rl_get_screen_size (tty, 0); + + /* "An application program can assume that the terminal can do + character insertion if *any one of* the capabilities `IC', + `im', `ic' or `ip' is provided." But we can't do anything if + only `ip' is provided, so... */ + _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic); + + /* Check to see if this terminal has a meta key and clear the capability + variables if there is none. */ + term_has_meta = (tgetflag ("km") || tgetflag ("MT")); + if (!term_has_meta) + _rl_term_mm = _rl_term_mo = (char *)NULL; + + /* Attempt to find and bind the arrow keys. Do not override already + bound keys in an overzealous attempt, however. */ + + bind_termcap_arrow_keys (emacs_standard_keymap); + +#if defined (VI_MODE) + bind_termcap_arrow_keys (vi_movement_keymap); + bind_termcap_arrow_keys (vi_insertion_keymap); +#endif /* VI_MODE */ + + return 0; +} + +/* Bind the arrow key sequences from the termcap description in MAP. */ +static void +bind_termcap_arrow_keys (map) + Keymap map; +{ + Keymap xkeymap; + + xkeymap = _rl_keymap; + _rl_keymap = map; + + _rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history); + _rl_bind_if_unbound (_rl_term_kd, rl_get_next_history); + _rl_bind_if_unbound (_rl_term_kr, rl_forward); + _rl_bind_if_unbound (_rl_term_kl, rl_backward); + + _rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */ + _rl_bind_if_unbound (_rl_term_at7, rl_end_of_line); /* End */ + + _rl_keymap = xkeymap; +} + +char * +rl_get_termcap (cap) + const char *cap; +{ + register int i; + + if (tcap_initialized == 0) + return ((char *)NULL); + for (i = 0; i < NUM_TC_STRINGS; i++) + { + if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0) + return *(tc_strings[i].tc_value); + } + return ((char *)NULL); +} + +/* Re-initialize the terminal considering that the TERM/TERMCAP variable + has changed. */ +int +rl_reset_terminal (terminal_name) + const char *terminal_name; +{ + _rl_init_terminal_io (terminal_name); + return 0; +} + +/* A function for the use of tputs () */ +#ifdef _MINIX +void +_rl_output_character_function (c) + int c; +{ + putc (c, _rl_out_stream); +} +#else /* !_MINIX */ +int +_rl_output_character_function (c) + int c; +{ + return putc (c, _rl_out_stream); +} +#endif /* !_MINIX */ + +/* Write COUNT characters from STRING to the output stream. */ +void +_rl_output_some_chars (string, count) + const char *string; + int count; +{ + fwrite (string, 1, count, _rl_out_stream); +} + +/* Move the cursor back. */ +int +_rl_backspace (count) + int count; +{ + register int i; + + if (_rl_term_backspace) + for (i = 0; i < count; i++) + tputs (_rl_term_backspace, 1, _rl_output_character_function); + else + for (i = 0; i < count; i++) + putc ('\b', _rl_out_stream); + return 0; +} + +/* Move to the start of the next line. */ +int +rl_crlf () +{ +#if defined (NEW_TTY_DRIVER) + if (_rl_term_cr) + tputs (_rl_term_cr, 1, _rl_output_character_function); +#endif /* NEW_TTY_DRIVER */ + putc ('\n', _rl_out_stream); + return 0; +} + +/* Ring the terminal bell. */ +int +rl_ding () +{ + if (readline_echoing_p) + { + switch (_rl_bell_preference) + { + case NO_BELL: + default: + break; + case VISIBLE_BELL: + if (_rl_visible_bell) + { + tputs (_rl_visible_bell, 1, _rl_output_character_function); + break; + } + /* FALLTHROUGH */ + case AUDIBLE_BELL: + fprintf (stderr, "\007"); + fflush (stderr); + break; + } + return (0); + } + return (-1); +} + +/* **************************************************************** */ +/* */ +/* Controlling the Meta Key and Keypad */ +/* */ +/* **************************************************************** */ + +void +_rl_enable_meta_key () +{ +#if !defined (__DJGPP__) + if (term_has_meta && _rl_term_mm) + tputs (_rl_term_mm, 1, _rl_output_character_function); +#endif +} + +void +_rl_control_keypad (on) + int on; +{ +#if !defined (__DJGPP__) + if (on && _rl_term_ks) + tputs (_rl_term_ks, 1, _rl_output_character_function); + else if (!on && _rl_term_ke) + tputs (_rl_term_ke, 1, _rl_output_character_function); +#endif +} + +/* **************************************************************** */ +/* */ +/* Controlling the Cursor */ +/* */ +/* **************************************************************** */ + +/* Set the cursor appropriately depending on IM, which is one of the + insert modes (insert or overwrite). Insert mode gets the normal + cursor. Overwrite mode gets a very visible cursor. Only does + anything if we have both capabilities. */ +void +_rl_set_cursor (im, force) + int im, force; +{ + if (_rl_term_ve && _rl_term_vs) + { + if (force || im != rl_insert_mode) + { + if (im == RL_IM_OVERWRITE) + tputs (_rl_term_vs, 1, _rl_output_character_function); + else + tputs (_rl_term_ve, 1, _rl_output_character_function); + } + } +} diff --git a/readline/readline-4.3/text.c b/readline/readline-4.3/text.c new file mode 100644 index 00000000..2a7b724f --- /dev/null +++ b/readline/readline-4.3/text.c @@ -0,0 +1,1540 @@ +/* text.c -- text handling commands for readline. */ + +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_LOCALE_H) +# include +#endif + +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#if defined (__EMX__) +# define INCL_DOSPROCESS +# include +#endif /* __EMX__ */ + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + +/* Forward declarations. */ +static int rl_change_case PARAMS((int, int)); +static int _rl_char_search PARAMS((int, int, int)); + +/* **************************************************************** */ +/* */ +/* Insert and Delete */ +/* */ +/* **************************************************************** */ + +/* Insert a string of text into the line at point. This is the only + way that you should do insertion. _rl_insert_char () calls this + function. Returns the number of characters inserted. */ +int +rl_insert_text (string) + const char *string; +{ + register int i, l; + + l = (string && *string) ? strlen (string) : 0; + if (l == 0) + return 0; + + if (rl_end + l >= rl_line_buffer_len) + rl_extend_line_buffer (rl_end + l); + + for (i = rl_end; i >= rl_point; i--) + rl_line_buffer[i + l] = rl_line_buffer[i]; + strncpy (rl_line_buffer + rl_point, string, l); + + /* Remember how to undo this if we aren't undoing something. */ + if (_rl_doing_an_undo == 0) + { + /* If possible and desirable, concatenate the undos. */ + if ((l == 1) && + rl_undo_list && + (rl_undo_list->what == UNDO_INSERT) && + (rl_undo_list->end == rl_point) && + (rl_undo_list->end - rl_undo_list->start < 20)) + rl_undo_list->end++; + else + rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL); + } + rl_point += l; + rl_end += l; + rl_line_buffer[rl_end] = '\0'; + return l; +} + +/* Delete the string between FROM and TO. FROM is inclusive, TO is not. + Returns the number of characters deleted. */ +int +rl_delete_text (from, to) + int from, to; +{ + register char *text; + register int diff, i; + + /* Fix it if the caller is confused. */ + if (from > to) + SWAP (from, to); + + /* fix boundaries */ + if (to > rl_end) + { + to = rl_end; + if (from > to) + from = to; + } + if (from < 0) + from = 0; + + text = rl_copy_text (from, to); + + /* Some versions of strncpy() can't handle overlapping arguments. */ + diff = to - from; + for (i = from; i < rl_end - diff; i++) + rl_line_buffer[i] = rl_line_buffer[i + diff]; + + /* Remember how to undo this delete. */ + if (_rl_doing_an_undo == 0) + rl_add_undo (UNDO_DELETE, from, to, text); + else + free (text); + + rl_end -= diff; + rl_line_buffer[rl_end] = '\0'; + return (diff); +} + +/* Fix up point so that it is within the line boundaries after killing + text. If FIX_MARK_TOO is non-zero, the mark is forced within line + boundaries also. */ + +#define _RL_FIX_POINT(x) \ + do { \ + if (x > rl_end) \ + x = rl_end; \ + else if (x < 0) \ + x = 0; \ + } while (0) + +void +_rl_fix_point (fix_mark_too) + int fix_mark_too; +{ + _RL_FIX_POINT (rl_point); + if (fix_mark_too) + _RL_FIX_POINT (rl_mark); +} +#undef _RL_FIX_POINT + +int +_rl_replace_text (text, start, end) + const char *text; + int start, end; +{ + int n; + + rl_begin_undo_group (); + rl_delete_text (start, end + 1); + rl_point = start; + n = rl_insert_text (text); + rl_end_undo_group (); + + return n; +} + +/* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is + non-zero, we free the current undo list. */ +void +rl_replace_line (text, clear_undo) + const char *text; + int clear_undo; +{ + int len; + + len = strlen (text); + if (len >= rl_line_buffer_len) + rl_extend_line_buffer (len); + strcpy (rl_line_buffer, text); + rl_end = len; + + if (clear_undo) + rl_free_undo_list (); + + _rl_fix_point (1); +} + +/* **************************************************************** */ +/* */ +/* Readline character functions */ +/* */ +/* **************************************************************** */ + +/* This is not a gap editor, just a stupid line input routine. No hair + is involved in writing any of the functions, and none should be. */ + +/* Note that: + + rl_end is the place in the string that we would place '\0'; + i.e., it is always safe to place '\0' there. + + rl_point is the place in the string where the cursor is. Sometimes + this is the same as rl_end. + + Any command that is called interactively receives two arguments. + The first is a count: the numeric arg pased to this command. + The second is the key which invoked this command. +*/ + +/* **************************************************************** */ +/* */ +/* Movement Commands */ +/* */ +/* **************************************************************** */ + +/* Note that if you `optimize' the display for these functions, you cannot + use said functions in other functions which do not do optimizing display. + I.e., you will have to update the data base for rl_redisplay, and you + might as well let rl_redisplay do that job. */ + +/* Move forward COUNT bytes. */ +int +rl_forward_byte (count, key) + int count, key; +{ + if (count < 0) + return (rl_backward_byte (-count, key)); + + if (count > 0) + { + int end = rl_point + count; +#if defined (VI_MODE) + int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end; +#else + int lend = rl_end; +#endif + + if (end > lend) + { + rl_point = lend; + rl_ding (); + } + else + rl_point = end; + } + + if (rl_end < 0) + rl_end = 0; + + return 0; +} + +#if defined (HANDLE_MULTIBYTE) +/* Move forward COUNT characters. */ +int +rl_forward_char (count, key) + int count, key; +{ + int point; + + if (MB_CUR_MAX == 1 || rl_byte_oriented) + return (rl_forward_byte (count, key)); + + if (count < 0) + return (rl_backward_char (-count, key)); + + if (count > 0) + { + point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); + +#if defined (VI_MODE) + if (rl_end <= point && rl_editing_mode == vi_mode) + point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO); +#endif + + if (rl_point == point) + rl_ding (); + + rl_point = point; + + if (rl_end < 0) + rl_end = 0; + } + + return 0; +} +#else /* !HANDLE_MULTIBYTE */ +int +rl_forward_char (count, key) + int count, key; +{ + return (rl_forward_byte (count, key)); +} +#endif /* !HANDLE_MULTIBYTE */ + +/* Backwards compatibility. */ +int +rl_forward (count, key) + int count, key; +{ + return (rl_forward_char (count, key)); +} + +/* Move backward COUNT bytes. */ +int +rl_backward_byte (count, key) + int count, key; +{ + if (count < 0) + return (rl_forward_byte (-count, key)); + + if (count > 0) + { + if (rl_point < count) + { + rl_point = 0; + rl_ding (); + } + else + rl_point -= count; + } + + if (rl_point < 0) + rl_point = 0; + + return 0; +} + +#if defined (HANDLE_MULTIBYTE) +/* Move backward COUNT characters. */ +int +rl_backward_char (count, key) + int count, key; +{ + int point; + + if (MB_CUR_MAX == 1 || rl_byte_oriented) + return (rl_backward_byte (count, key)); + + if (count < 0) + return (rl_forward_char (-count, key)); + + if (count > 0) + { + point = rl_point; + + while (count > 0 && point > 0) + { + point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO); + count--; + } + if (count > 0) + { + rl_point = 0; + rl_ding (); + } + else + rl_point = point; + } + + return 0; +} +#else +int +rl_backward_char (count, key) + int count, key; +{ + return (rl_backward_byte (count, key)); +} +#endif + +/* Backwards compatibility. */ +int +rl_backward (count, key) + int count, key; +{ + return (rl_backward_char (count, key)); +} + +/* Move to the beginning of the line. */ +int +rl_beg_of_line (count, key) + int count, key; +{ + rl_point = 0; + return 0; +} + +/* Move to the end of the line. */ +int +rl_end_of_line (count, key) + int count, key; +{ + rl_point = rl_end; + return 0; +} + +/* XXX - these might need changes for multibyte characters */ +/* Move forward a word. We do what Emacs does. */ +int +rl_forward_word (count, key) + int count, key; +{ + int c; + + if (count < 0) + return (rl_backward_word (-count, key)); + + while (count) + { + if (rl_point == rl_end) + return 0; + + /* If we are not in a word, move forward until we are in one. + Then, move forward until we hit a non-alphabetic character. */ + c = rl_line_buffer[rl_point]; + if (rl_alphabetic (c) == 0) + { + while (++rl_point < rl_end) + { + c = rl_line_buffer[rl_point]; + if (rl_alphabetic (c)) + break; + } + } + + if (rl_point == rl_end) + return 0; + + while (++rl_point < rl_end) + { + c = rl_line_buffer[rl_point]; + if (rl_alphabetic (c) == 0) + break; + } + --count; + } + + return 0; +} + +/* Move backward a word. We do what Emacs does. */ +int +rl_backward_word (count, key) + int count, key; +{ + int c; + + if (count < 0) + return (rl_forward_word (-count, key)); + + while (count) + { + if (!rl_point) + return 0; + + /* Like rl_forward_word (), except that we look at the characters + just before point. */ + + c = rl_line_buffer[rl_point - 1]; + if (rl_alphabetic (c) == 0) + { + while (--rl_point) + { + c = rl_line_buffer[rl_point - 1]; + if (rl_alphabetic (c)) + break; + } + } + + while (rl_point) + { + c = rl_line_buffer[rl_point - 1]; + if (rl_alphabetic (c) == 0) + break; + else + --rl_point; + } + + --count; + } + + return 0; +} + +/* Clear the current line. Numeric argument to C-l does this. */ +int +rl_refresh_line (ignore1, ignore2) + int ignore1, ignore2; +{ + int curr_line; + + curr_line = _rl_current_display_line (); + + _rl_move_vert (curr_line); + _rl_move_cursor_relative (0, rl_line_buffer); /* XXX is this right */ + + _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */ + + rl_forced_update_display (); + rl_display_fixed = 1; + + return 0; +} + +/* C-l typed to a line without quoting clears the screen, and then reprints + the prompt and the current input line. Given a numeric arg, redraw only + the current line. */ +int +rl_clear_screen (count, key) + int count, key; +{ + if (rl_explicit_arg) + { + rl_refresh_line (count, key); + return 0; + } + + _rl_clear_screen (); /* calls termcap function to clear screen */ + rl_forced_update_display (); + rl_display_fixed = 1; + + return 0; +} + +int +rl_arrow_keys (count, c) + int count, c; +{ + int ch; + + RL_SETSTATE(RL_STATE_MOREINPUT); + ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + switch (_rl_to_upper (ch)) + { + case 'A': + rl_get_previous_history (count, ch); + break; + + case 'B': + rl_get_next_history (count, ch); + break; + + case 'C': + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_forward_char (count, ch); + else + rl_forward_byte (count, ch); + break; + + case 'D': + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_backward_char (count, ch); + else + rl_backward_byte (count, ch); + break; + + default: + rl_ding (); + } + + return 0; +} + +/* **************************************************************** */ +/* */ +/* Text commands */ +/* */ +/* **************************************************************** */ + +#ifdef HANDLE_MULTIBYTE +static char pending_bytes[MB_LEN_MAX]; +static int pending_bytes_length = 0; +static mbstate_t ps = {0}; +#endif + +/* Insert the character C at the current location, moving point forward. + If C introduces a multibyte sequence, we read the whole sequence and + then insert the multibyte char into the line buffer. */ +int +_rl_insert_char (count, c) + int count, c; +{ + register int i; + char *string; +#ifdef HANDLE_MULTIBYTE + int string_size; + char incoming[MB_LEN_MAX + 1]; + int incoming_length = 0; + mbstate_t ps_back; + static int stored_count = 0; +#endif + + if (count <= 0) + return 0; + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX == 1 || rl_byte_oriented) + { + incoming[0] = c; + incoming[1] = '\0'; + incoming_length = 1; + } + else + { + wchar_t wc; + size_t ret; + + if (stored_count <= 0) + stored_count = count; + else + count = stored_count; + + ps_back = ps; + pending_bytes[pending_bytes_length++] = c; + ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps); + + if (ret == (size_t)-2) + { + /* Bytes too short to compose character, try to wait for next byte. + Restore the state of the byte sequence, because in this case the + effect of mbstate is undefined. */ + ps = ps_back; + return 1; + } + else if (ret == (size_t)-1) + { + /* Invalid byte sequence for the current locale. Treat first byte + as a single character. */ + incoming[0] = pending_bytes[0]; + incoming[1] = '\0'; + incoming_length = 1; + pending_bytes_length--; + memmove (pending_bytes, pending_bytes + 1, pending_bytes_length); + /* Clear the state of the byte sequence, because in this case the + effect of mbstate is undefined. */ + memset (&ps, 0, sizeof (mbstate_t)); + } + else if (ret == (size_t)0) + { + incoming[0] = '\0'; + incoming_length = 0; + pending_bytes_length--; + /* Clear the state of the byte sequence, because in this case the + effect of mbstate is undefined. */ + memset (&ps, 0, sizeof (mbstate_t)); + } + else + { + /* We successfully read a single multibyte character. */ + memcpy (incoming, pending_bytes, pending_bytes_length); + incoming[pending_bytes_length] = '\0'; + incoming_length = pending_bytes_length; + pending_bytes_length = 0; + } + } +#endif /* HANDLE_MULTIBYTE */ + + /* If we can optimize, then do it. But don't let people crash + readline because of extra large arguments. */ + if (count > 1 && count <= 1024) + { +#if defined (HANDLE_MULTIBYTE) + string_size = count * incoming_length; + string = (char *)xmalloc (1 + string_size); + + i = 0; + while (i < string_size) + { + strncpy (string + i, incoming, incoming_length); + i += incoming_length; + } + incoming_length = 0; + stored_count = 0; +#else /* !HANDLE_MULTIBYTE */ + string = (char *)xmalloc (1 + count); + + for (i = 0; i < count; i++) + string[i] = c; +#endif /* !HANDLE_MULTIBYTE */ + + string[i] = '\0'; + rl_insert_text (string); + free (string); + + return 0; + } + + if (count > 1024) + { + int decreaser; +#if defined (HANDLE_MULTIBYTE) + string_size = incoming_length * 1024; + string = (char *)xmalloc (1 + string_size); + + i = 0; + while (i < string_size) + { + strncpy (string + i, incoming, incoming_length); + i += incoming_length; + } + + while (count) + { + decreaser = (count > 1024) ? 1024 : count; + string[decreaser*incoming_length] = '\0'; + rl_insert_text (string); + count -= decreaser; + } + + free (string); + incoming_length = 0; + stored_count = 0; +#else /* !HANDLE_MULTIBYTE */ + char str[1024+1]; + + for (i = 0; i < 1024; i++) + str[i] = c; + + while (count) + { + decreaser = (count > 1024 ? 1024 : count); + str[decreaser] = '\0'; + rl_insert_text (str); + count -= decreaser; + } +#endif /* !HANDLE_MULTIBYTE */ + + return 0; + } + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX == 1 || rl_byte_oriented) + { +#endif + /* We are inserting a single character. + If there is pending input, then make a string of all of the + pending characters that are bound to rl_insert, and insert + them all. */ + if (_rl_any_typein ()) + _rl_insert_typein (c); + else + { + /* Inserting a single character. */ + char str[2]; + + str[1] = '\0'; + str[0] = c; + rl_insert_text (str); + } +#if defined (HANDLE_MULTIBYTE) + } + else + { + rl_insert_text (incoming); + stored_count = 0; + } +#endif + + return 0; +} + +/* Overwrite the character at point (or next COUNT characters) with C. + If C introduces a multibyte character sequence, read the entire sequence + before starting the overwrite loop. */ +int +_rl_overwrite_char (count, c) + int count, c; +{ + int i; +#if defined (HANDLE_MULTIBYTE) + char mbkey[MB_LEN_MAX]; + int k; + + /* Read an entire multibyte character sequence to insert COUNT times. */ + if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) + k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX); +#endif + + for (i = 0; i < count; i++) + { + rl_begin_undo_group (); + + if (rl_point < rl_end) + rl_delete (1, c); + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_insert_text (mbkey); + else +#endif + _rl_insert_char (1, c); + + rl_end_undo_group (); + } + + return 0; +} + +int +rl_insert (count, c) + int count, c; +{ + return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c) + : _rl_overwrite_char (count, c)); +} + +/* Insert the next typed character verbatim. */ +int +rl_quoted_insert (count, key) + int count, key; +{ + int c; + +#if defined (HANDLE_SIGNALS) + _rl_disable_tty_signals (); +#endif + + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + +#if defined (HANDLE_SIGNALS) + _rl_restore_tty_signals (); +#endif + + return (_rl_insert_char (count, c)); +} + +/* Insert a tab character. */ +int +rl_tab_insert (count, key) + int count, key; +{ + return (_rl_insert_char (count, '\t')); +} + +/* What to do when a NEWLINE is pressed. We accept the whole line. + KEY is the key that invoked this command. I guess it could have + meaning in the future. */ +int +rl_newline (count, key) + int count, key; +{ + rl_done = 1; + + if (_rl_history_preserve_point) + _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; + + RL_SETSTATE(RL_STATE_DONE); + +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + { + _rl_vi_done_inserting (); + _rl_vi_reset_last (); + } +#endif /* VI_MODE */ + + /* If we've been asked to erase empty lines, suppress the final update, + since _rl_update_final calls rl_crlf(). */ + if (rl_erase_empty_line && rl_point == 0 && rl_end == 0) + return 0; + + if (readline_echoing_p) + _rl_update_final (); + return 0; +} + +/* What to do for some uppercase characters, like meta characters, + and some characters appearing in emacs_ctlx_keymap. This function + is just a stub, you bind keys to it and the code in _rl_dispatch () + is special cased. */ +int +rl_do_lowercase_version (ignore1, ignore2) + int ignore1, ignore2; +{ + return 0; +} + +/* This is different from what vi does, so the code's not shared. Emacs + rubout in overwrite mode has one oddity: it replaces a control + character that's displayed as two characters (^X) with two spaces. */ +int +_rl_overwrite_rubout (count, key) + int count, key; +{ + int opoint; + int i, l; + + if (rl_point == 0) + { + rl_ding (); + return 1; + } + + opoint = rl_point; + + /* L == number of spaces to insert */ + for (i = l = 0; i < count; i++) + { + rl_backward_char (1, key); + l += rl_character_len (rl_line_buffer[rl_point], rl_point); /* not exactly right */ + } + + rl_begin_undo_group (); + + if (count > 1 || rl_explicit_arg) + rl_kill_text (opoint, rl_point); + else + rl_delete_text (opoint, rl_point); + + /* Emacs puts point at the beginning of the sequence of spaces. */ + opoint = rl_point; + _rl_insert_char (l, ' '); + rl_point = opoint; + + rl_end_undo_group (); + + return 0; +} + +/* Rubout the character behind point. */ +int +rl_rubout (count, key) + int count, key; +{ + if (count < 0) + return (rl_delete (-count, key)); + + if (!rl_point) + { + rl_ding (); + return -1; + } + + if (rl_insert_mode == RL_IM_OVERWRITE) + return (_rl_overwrite_rubout (count, key)); + + return (_rl_rubout_char (count, key)); +} + +int +_rl_rubout_char (count, key) + int count, key; +{ + int orig_point; + unsigned char c; + + /* Duplicated code because this is called from other parts of the library. */ + if (count < 0) + return (rl_delete (-count, key)); + + if (rl_point == 0) + { + rl_ding (); + return -1; + } + + if (count > 1 || rl_explicit_arg) + { + orig_point = rl_point; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_backward_char (count, key); + else +#endif + rl_backward_byte (count, key); + rl_kill_text (orig_point, rl_point); + } + else + { +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX == 1 || rl_byte_oriented) + { +#endif + c = rl_line_buffer[--rl_point]; + rl_delete_text (rl_point, rl_point + 1); +#if defined (HANDLE_MULTIBYTE) + } + else + { + int orig_point; + + orig_point = rl_point; + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + c = rl_line_buffer[rl_point]; + rl_delete_text (rl_point, orig_point); + } +#endif /* HANDLE_MULTIBYTE */ + + /* I don't think that the hack for end of line is needed for + multibyte chars. */ +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX == 1 || rl_byte_oriented) +#endif + if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos) + { + int l; + l = rl_character_len (c, rl_point); + _rl_erase_at_end_of_line (l); + } + } + + return 0; +} + +/* Delete the character under the cursor. Given a numeric argument, + kill that many characters instead. */ +int +rl_delete (count, key) + int count, key; +{ + int r; + + if (count < 0) + return (_rl_rubout_char (-count, key)); + + if (rl_point == rl_end) + { + rl_ding (); + return -1; + } + + if (count > 1 || rl_explicit_arg) + { + int orig_point = rl_point; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_forward_char (count, key); + else +#endif + rl_forward_byte (count, key); + + r = rl_kill_text (orig_point, rl_point); + rl_point = orig_point; + return r; + } + else + { + int new_point; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + else + new_point = rl_point + 1; + + return (rl_delete_text (rl_point, new_point)); + } +} + +/* Delete the character under the cursor, unless the insertion + point is at the end of the line, in which case the character + behind the cursor is deleted. COUNT is obeyed and may be used + to delete forward or backward that many characters. */ +int +rl_rubout_or_delete (count, key) + int count, key; +{ + if (rl_end != 0 && rl_point == rl_end) + return (_rl_rubout_char (count, key)); + else + return (rl_delete (count, key)); +} + +/* Delete all spaces and tabs around point. */ +int +rl_delete_horizontal_space (count, ignore) + int count, ignore; +{ + int start = rl_point; + + while (rl_point && whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + start = rl_point; + + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + if (start != rl_point) + { + rl_delete_text (start, rl_point); + rl_point = start; + } + return 0; +} + +/* Like the tcsh editing function delete-char-or-list. The eof character + is caught before this is invoked, so this really does the same thing as + delete-char-or-list-or-eof, as long as it's bound to the eof character. */ +int +rl_delete_or_show_completions (count, key) + int count, key; +{ + if (rl_end != 0 && rl_point == rl_end) + return (rl_possible_completions (count, key)); + else + return (rl_delete (count, key)); +} + +#ifndef RL_COMMENT_BEGIN_DEFAULT +#define RL_COMMENT_BEGIN_DEFAULT "#" +#endif + +/* Turn the current line into a comment in shell history. + A K*rn shell style function. */ +int +rl_insert_comment (count, key) + int count, key; +{ + char *rl_comment_text; + int rl_comment_len; + + rl_beg_of_line (1, key); + rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT; + + if (rl_explicit_arg == 0) + rl_insert_text (rl_comment_text); + else + { + rl_comment_len = strlen (rl_comment_text); + if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len)) + rl_delete_text (rl_point, rl_point + rl_comment_len); + else + rl_insert_text (rl_comment_text); + } + + (*rl_redisplay_function) (); + rl_newline (1, '\n'); + + return (0); +} + +/* **************************************************************** */ +/* */ +/* Changing Case */ +/* */ +/* **************************************************************** */ + +/* The three kinds of things that we know how to do. */ +#define UpCase 1 +#define DownCase 2 +#define CapCase 3 + +/* Uppercase the word at point. */ +int +rl_upcase_word (count, key) + int count, key; +{ + return (rl_change_case (count, UpCase)); +} + +/* Lowercase the word at point. */ +int +rl_downcase_word (count, key) + int count, key; +{ + return (rl_change_case (count, DownCase)); +} + +/* Upcase the first letter, downcase the rest. */ +int +rl_capitalize_word (count, key) + int count, key; +{ + return (rl_change_case (count, CapCase)); +} + +/* The meaty function. + Change the case of COUNT words, performing OP on them. + OP is one of UpCase, DownCase, or CapCase. + If a negative argument is given, leave point where it started, + otherwise, leave it where it moves to. */ +static int +rl_change_case (count, op) + int count, op; +{ + register int start, end; + int inword, c; + + start = rl_point; + rl_forward_word (count, 0); + end = rl_point; + + if (count < 0) + SWAP (start, end); + + /* We are going to modify some text, so let's prepare to undo it. */ + rl_modifying (start, end); + + for (inword = 0; start < end; start++) + { + c = rl_line_buffer[start]; + switch (op) + { + case UpCase: + rl_line_buffer[start] = _rl_to_upper (c); + break; + + case DownCase: + rl_line_buffer[start] = _rl_to_lower (c); + break; + + case CapCase: + rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c); + inword = rl_alphabetic (rl_line_buffer[start]); + break; + + default: + rl_ding (); + return -1; + } + } + rl_point = end; + return 0; +} + +/* **************************************************************** */ +/* */ +/* Transposition */ +/* */ +/* **************************************************************** */ + +/* Transpose the words at point. If point is at the end of the line, + transpose the two words before point. */ +int +rl_transpose_words (count, key) + int count, key; +{ + char *word1, *word2; + int w1_beg, w1_end, w2_beg, w2_end; + int orig_point = rl_point; + + if (!count) + return 0; + + /* Find the two words. */ + rl_forward_word (count, key); + w2_end = rl_point; + rl_backward_word (1, key); + w2_beg = rl_point; + rl_backward_word (count, key); + w1_beg = rl_point; + rl_forward_word (1, key); + w1_end = rl_point; + + /* Do some check to make sure that there really are two words. */ + if ((w1_beg == w2_beg) || (w2_beg < w1_end)) + { + rl_ding (); + rl_point = orig_point; + return -1; + } + + /* Get the text of the words. */ + word1 = rl_copy_text (w1_beg, w1_end); + word2 = rl_copy_text (w2_beg, w2_end); + + /* We are about to do many insertions and deletions. Remember them + as one operation. */ + rl_begin_undo_group (); + + /* Do the stuff at word2 first, so that we don't have to worry + about word1 moving. */ + rl_point = w2_beg; + rl_delete_text (w2_beg, w2_end); + rl_insert_text (word1); + + rl_point = w1_beg; + rl_delete_text (w1_beg, w1_end); + rl_insert_text (word2); + + /* This is exactly correct since the text before this point has not + changed in length. */ + rl_point = w2_end; + + /* I think that does it. */ + rl_end_undo_group (); + free (word1); + free (word2); + + return 0; +} + +/* Transpose the characters at point. If point is at the end of the line, + then transpose the characters before point. */ +int +rl_transpose_chars (count, key) + int count, key; +{ +#if defined (HANDLE_MULTIBYTE) + char *dummy; + int i, prev_point; +#else + char dummy[2]; +#endif + int char_length; + + if (count == 0) + return 0; + + if (!rl_point || rl_end < 2) + { + rl_ding (); + return -1; + } + + rl_begin_undo_group (); + + if (rl_point == rl_end) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + --rl_point; + count = 1; + } + +#if defined (HANDLE_MULTIBYTE) + prev_point = rl_point; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else +#endif + rl_point--; + +#if defined (HANDLE_MULTIBYTE) + char_length = prev_point - rl_point; + dummy = (char *)xmalloc (char_length + 1); + for (i = 0; i < char_length; i++) + dummy[i] = rl_line_buffer[rl_point + i]; + dummy[i] = '\0'; +#else + dummy[0] = rl_line_buffer[rl_point]; + dummy[char_length = 1] = '\0'; +#endif + + rl_delete_text (rl_point, rl_point + char_length); + + rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); + + _rl_fix_point (0); + rl_insert_text (dummy); + rl_end_undo_group (); + +#if defined (HANDLE_MULTIBYTE) + free (dummy); +#endif + + return 0; +} + +/* **************************************************************** */ +/* */ +/* Character Searching */ +/* */ +/* **************************************************************** */ + +int +#if defined (HANDLE_MULTIBYTE) +_rl_char_search_internal (count, dir, smbchar, len) + int count, dir; + char *smbchar; + int len; +#else +_rl_char_search_internal (count, dir, schar) + int count, dir, schar; +#endif +{ + int pos, inc; +#if defined (HANDLE_MULTIBYTE) + int prepos; +#endif + + pos = rl_point; + inc = (dir < 0) ? -1 : 1; + while (count) + { + if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end)) + { + rl_ding (); + return -1; + } + +#if defined (HANDLE_MULTIBYTE) + pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY) + : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); +#else + pos += inc; +#endif + do + { +#if defined (HANDLE_MULTIBYTE) + if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len)) +#else + if (rl_line_buffer[pos] == schar) +#endif + { + count--; + if (dir < 0) + rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY) + : pos; + else + rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY) + : pos; + break; + } +#if defined (HANDLE_MULTIBYTE) + prepos = pos; +#endif + } +#if defined (HANDLE_MULTIBYTE) + while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos + : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos); +#else + while ((dir < 0) ? pos-- : ++pos < rl_end); +#endif + } + return (0); +} + +/* Search COUNT times for a character read from the current input stream. + FDIR is the direction to search if COUNT is non-negative; otherwise + the search goes in BDIR. So much is dependent on HANDLE_MULTIBYTE + that there are two separate versions of this function. */ +#if defined (HANDLE_MULTIBYTE) +static int +_rl_char_search (count, fdir, bdir) + int count, fdir, bdir; +{ + char mbchar[MB_LEN_MAX]; + int mb_len; + + mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX); + + if (count < 0) + return (_rl_char_search_internal (-count, bdir, mbchar, mb_len)); + else + return (_rl_char_search_internal (count, fdir, mbchar, mb_len)); +} +#else /* !HANDLE_MULTIBYTE */ +static int +_rl_char_search (count, fdir, bdir) + int count, fdir, bdir; +{ + int c; + + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (count < 0) + return (_rl_char_search_internal (-count, bdir, c)); + else + return (_rl_char_search_internal (count, fdir, c)); +} +#endif /* !HANDLE_MULTIBYTE */ + +int +rl_char_search (count, key) + int count, key; +{ + return (_rl_char_search (count, FFIND, BFIND)); +} + +int +rl_backward_char_search (count, key) + int count, key; +{ + return (_rl_char_search (count, BFIND, FFIND)); +} + +/* **************************************************************** */ +/* */ +/* The Mark and the Region. */ +/* */ +/* **************************************************************** */ + +/* Set the mark at POSITION. */ +int +_rl_set_mark_at_pos (position) + int position; +{ + if (position > rl_end) + return -1; + + rl_mark = position; + return 0; +} + +/* A bindable command to set the mark. */ +int +rl_set_mark (count, key) + int count, key; +{ + return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point)); +} + +/* Exchange the position of mark and point. */ +int +rl_exchange_point_and_mark (count, key) + int count, key; +{ + if (rl_mark > rl_end) + rl_mark = -1; + + if (rl_mark == -1) + { + rl_ding (); + return -1; + } + else + SWAP (rl_point, rl_mark); + + return 0; +} diff --git a/readline/readline-4.3/tilde.c b/readline/readline-4.3/tilde.c new file mode 100644 index 00000000..154f7f81 --- /dev/null +++ b/readline/readline-4.3/tilde.c @@ -0,0 +1,458 @@ +/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */ + +/* Copyright (C) 1988,1989 Free Software Foundation, Inc. + + This file is part of GNU Readline, a library for reading lines + of text with interactive input and history editing. + + Readline is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + Readline is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Readline; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif +# include +#endif + +#if defined (HAVE_STRING_H) +# include +#else /* !HAVE_STRING_H */ +# include +#endif /* !HAVE_STRING_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include +#include + +#include "tilde.h" + +#if defined (TEST) || defined (STATIC_MALLOC) +static void *xmalloc (), *xrealloc (); +#else +# include "xmalloc.h" +#endif /* TEST || STATIC_MALLOC */ + +#if !defined (HAVE_GETPW_DECLS) +extern struct passwd *getpwuid PARAMS((uid_t)); +extern struct passwd *getpwnam PARAMS((const char *)); +#endif /* !HAVE_GETPW_DECLS */ + +#if !defined (savestring) +#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x)) +#endif /* !savestring */ + +#if !defined (NULL) +# if defined (__STDC__) +# define NULL ((void *) 0) +# else +# define NULL 0x0 +# endif /* !__STDC__ */ +#endif /* !NULL */ + +/* If being compiled as part of bash, these will be satisfied from + variables.o. If being compiled as part of readline, they will + be satisfied from shell.o. */ +extern char *sh_get_home_dir PARAMS((void)); +extern char *sh_get_env_value PARAMS((const char *)); + +/* The default value of tilde_additional_prefixes. This is set to + whitespace preceding a tilde so that simple programs which do not + perform any word separation get desired behaviour. */ +static const char *default_prefixes[] = + { " ~", "\t~", (const char *)NULL }; + +/* The default value of tilde_additional_suffixes. This is set to + whitespace or newline so that simple programs which do not + perform any word separation get desired behaviour. */ +static const char *default_suffixes[] = + { " ", "\n", (const char *)NULL }; + +/* If non-null, this contains the address of a function that the application + wants called before trying the standard tilde expansions. The function + is called with the text sans tilde, and returns a malloc()'ed string + which is the expansion, or a NULL pointer if the expansion fails. */ +tilde_hook_func_t *tilde_expansion_preexpansion_hook = (tilde_hook_func_t *)NULL; + +/* If non-null, this contains the address of a function to call if the + standard meaning for expanding a tilde fails. The function is called + with the text (sans tilde, as in "foo"), and returns a malloc()'ed string + which is the expansion, or a NULL pointer if there is no expansion. */ +tilde_hook_func_t *tilde_expansion_failure_hook = (tilde_hook_func_t *)NULL; + +/* When non-null, this is a NULL terminated array of strings which + are duplicates for a tilde prefix. Bash uses this to expand + `=~' and `:~'. */ +char **tilde_additional_prefixes = (char **)default_prefixes; + +/* When non-null, this is a NULL terminated array of strings which match + the end of a username, instead of just "/". Bash sets this to + `:' and `=~'. */ +char **tilde_additional_suffixes = (char **)default_suffixes; + +static int tilde_find_prefix PARAMS((const char *, int *)); +static int tilde_find_suffix PARAMS((const char *)); +static char *isolate_tilde_prefix PARAMS((const char *, int *)); +static char *glue_prefix_and_suffix PARAMS((char *, const char *, int)); + +/* Find the start of a tilde expansion in STRING, and return the index of + the tilde which starts the expansion. Place the length of the text + which identified this tilde starter in LEN, excluding the tilde itself. */ +static int +tilde_find_prefix (string, len) + const char *string; + int *len; +{ + register int i, j, string_len; + register char **prefixes; + + prefixes = tilde_additional_prefixes; + + string_len = strlen (string); + *len = 0; + + if (*string == '\0' || *string == '~') + return (0); + + if (prefixes) + { + for (i = 0; i < string_len; i++) + { + for (j = 0; prefixes[j]; j++) + { + if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0) + { + *len = strlen (prefixes[j]) - 1; + return (i + *len); + } + } + } + } + return (string_len); +} + +/* Find the end of a tilde expansion in STRING, and return the index of + the character which ends the tilde definition. */ +static int +tilde_find_suffix (string) + const char *string; +{ + register int i, j, string_len; + register char **suffixes; + + suffixes = tilde_additional_suffixes; + string_len = strlen (string); + + for (i = 0; i < string_len; i++) + { +#if defined (__MSDOS__) + if (string[i] == '/' || string[i] == '\\' /* || !string[i] */) +#else + if (string[i] == '/' /* || !string[i] */) +#endif + break; + + for (j = 0; suffixes && suffixes[j]; j++) + { + if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0) + return (i); + } + } + return (i); +} + +/* Return a new string which is the result of tilde expanding STRING. */ +char * +tilde_expand (string) + const char *string; +{ + char *result; + int result_size, result_index; + + result_index = result_size = 0; + if (result = strchr (string, '~')) + result = (char *)xmalloc (result_size = (strlen (string) + 16)); + else + result = (char *)xmalloc (result_size = (strlen (string) + 1)); + + /* Scan through STRING expanding tildes as we come to them. */ + while (1) + { + register int start, end; + char *tilde_word, *expansion; + int len; + + /* Make START point to the tilde which starts the expansion. */ + start = tilde_find_prefix (string, &len); + + /* Copy the skipped text into the result. */ + if ((result_index + start + 1) > result_size) + result = (char *)xrealloc (result, 1 + (result_size += (start + 20))); + + strncpy (result + result_index, string, start); + result_index += start; + + /* Advance STRING to the starting tilde. */ + string += start; + + /* Make END be the index of one after the last character of the + username. */ + end = tilde_find_suffix (string); + + /* If both START and END are zero, we are all done. */ + if (!start && !end) + break; + + /* Expand the entire tilde word, and copy it into RESULT. */ + tilde_word = (char *)xmalloc (1 + end); + strncpy (tilde_word, string, end); + tilde_word[end] = '\0'; + string += end; + + expansion = tilde_expand_word (tilde_word); + free (tilde_word); + + len = strlen (expansion); +#ifdef __CYGWIN__ + /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when + $HOME for `user' is /. On cygwin, // denotes a network drive. */ + if (len > 1 || *expansion != '/' || *string != '/') +#endif + { + if ((result_index + len + 1) > result_size) + result = (char *)xrealloc (result, 1 + (result_size += (len + 20))); + + strcpy (result + result_index, expansion); + result_index += len; + } + free (expansion); + } + + result[result_index] = '\0'; + + return (result); +} + +/* Take FNAME and return the tilde prefix we want expanded. If LENP is + non-null, the index of the end of the prefix into FNAME is returned in + the location it points to. */ +static char * +isolate_tilde_prefix (fname, lenp) + const char *fname; + int *lenp; +{ + char *ret; + int i; + + ret = (char *)xmalloc (strlen (fname)); +#if defined (__MSDOS__) + for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++) +#else + for (i = 1; fname[i] && fname[i] != '/'; i++) +#endif + ret[i - 1] = fname[i]; + ret[i - 1] = '\0'; + if (lenp) + *lenp = i; + return ret; +} + +/* Return a string that is PREFIX concatenated with SUFFIX starting at + SUFFIND. */ +static char * +glue_prefix_and_suffix (prefix, suffix, suffind) + char *prefix; + const char *suffix; + int suffind; +{ + char *ret; + int plen, slen; + + plen = (prefix && *prefix) ? strlen (prefix) : 0; + slen = strlen (suffix + suffind); + ret = (char *)xmalloc (plen + slen + 1); + if (plen) + strcpy (ret, prefix); + strcpy (ret + plen, suffix + suffind); + return ret; +} + +/* Do the work of tilde expansion on FILENAME. FILENAME starts with a + tilde. If there is no expansion, call tilde_expansion_failure_hook. + This always returns a newly-allocated string, never static storage. */ +char * +tilde_expand_word (filename) + const char *filename; +{ + char *dirname, *expansion, *username; + int user_len; + struct passwd *user_entry; + + if (filename == 0) + return ((char *)NULL); + + if (*filename != '~') + return (savestring (filename)); + + /* A leading `~/' or a bare `~' is *always* translated to the value of + $HOME or the home directory of the current user, regardless of any + preexpansion hook. */ + if (filename[1] == '\0' || filename[1] == '/') + { + /* Prefix $HOME to the rest of the string. */ + expansion = sh_get_env_value ("HOME"); + + /* If there is no HOME variable, look up the directory in + the password database. */ + if (expansion == 0) + expansion = sh_get_home_dir (); + + return (glue_prefix_and_suffix (expansion, filename, 1)); + } + + username = isolate_tilde_prefix (filename, &user_len); + + if (tilde_expansion_preexpansion_hook) + { + expansion = (*tilde_expansion_preexpansion_hook) (username); + if (expansion) + { + dirname = glue_prefix_and_suffix (expansion, filename, user_len); + free (username); + free (expansion); + return (dirname); + } + } + + /* No preexpansion hook, or the preexpansion hook failed. Look in the + password database. */ + dirname = (char *)NULL; + user_entry = getpwnam (username); + if (user_entry == 0) + { + /* If the calling program has a special syntax for expanding tildes, + and we couldn't find a standard expansion, then let them try. */ + if (tilde_expansion_failure_hook) + { + expansion = (*tilde_expansion_failure_hook) (username); + if (expansion) + { + dirname = glue_prefix_and_suffix (expansion, filename, user_len); + free (expansion); + } + } + free (username); + /* If we don't have a failure hook, or if the failure hook did not + expand the tilde, return a copy of what we were passed. */ + if (dirname == 0) + dirname = savestring (filename); + } + else + { + free (username); + dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len); + } + + endpwent (); + return (dirname); +} + + +#if defined (TEST) +#undef NULL +#include + +main (argc, argv) + int argc; + char **argv; +{ + char *result, line[512]; + int done = 0; + + while (!done) + { + printf ("~expand: "); + fflush (stdout); + + if (!gets (line)) + strcpy (line, "done"); + + if ((strcmp (line, "done") == 0) || + (strcmp (line, "quit") == 0) || + (strcmp (line, "exit") == 0)) + { + done = 1; + break; + } + + result = tilde_expand (line); + printf (" --> %s\n", result); + free (result); + } + exit (0); +} + +static void memory_error_and_abort (); + +static void * +xmalloc (bytes) + size_t bytes; +{ + void *temp = (char *)malloc (bytes); + + if (!temp) + memory_error_and_abort (); + return (temp); +} + +static void * +xrealloc (pointer, bytes) + void *pointer; + int bytes; +{ + void *temp; + + if (!pointer) + temp = malloc (bytes); + else + temp = realloc (pointer, bytes); + + if (!temp) + memory_error_and_abort (); + + return (temp); +} + +static void +memory_error_and_abort () +{ + fprintf (stderr, "readline: out of virtual memory\n"); + abort (); +} + +/* + * Local variables: + * compile-command: "gcc -g -DTEST -o tilde tilde.c" + * end: + */ +#endif /* TEST */ diff --git a/readline/readline-4.3/tilde.h b/readline/readline-4.3/tilde.h new file mode 100644 index 00000000..f8182c99 --- /dev/null +++ b/readline/readline-4.3/tilde.h @@ -0,0 +1,78 @@ +/* tilde.h: Externally available variables and function in libtilde.a. */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_TILDE_H_) +# define _TILDE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* A function can be defined using prototypes and compile on both ANSI C + and traditional C compilers with something like this: + extern char *func PARAMS((char *, char *, int)); */ + +#if !defined (PARAMS) +# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) +# define PARAMS(protos) protos +# else +# define PARAMS(protos) () +# endif +#endif + +typedef char *tilde_hook_func_t PARAMS((char *)); + +/* If non-null, this contains the address of a function that the application + wants called before trying the standard tilde expansions. The function + is called with the text sans tilde, and returns a malloc()'ed string + which is the expansion, or a NULL pointer if the expansion fails. */ +extern tilde_hook_func_t *tilde_expansion_preexpansion_hook; + +/* If non-null, this contains the address of a function to call if the + standard meaning for expanding a tilde fails. The function is called + with the text (sans tilde, as in "foo"), and returns a malloc()'ed string + which is the expansion, or a NULL pointer if there is no expansion. */ +extern tilde_hook_func_t *tilde_expansion_failure_hook; + +/* When non-null, this is a NULL terminated array of strings which + are duplicates for a tilde prefix. Bash uses this to expand + `=~' and `:~'. */ +extern char **tilde_additional_prefixes; + +/* When non-null, this is a NULL terminated array of strings which match + the end of a username, instead of just "/". Bash sets this to + `:' and `=~'. */ +extern char **tilde_additional_suffixes; + +/* Return a new string which is the result of tilde expanding STRING. */ +extern char *tilde_expand PARAMS((const char *)); + +/* Do the work of tilde expansion on FILENAME. FILENAME starts with a + tilde. If there is no expansion, call tilde_expansion_failure_hook. */ +extern char *tilde_expand_word PARAMS((const char *)); + +#ifdef __cplusplus +} +#endif + +#endif /* _TILDE_H_ */ diff --git a/readline/readline-4.3/undo.c b/readline/readline-4.3/undo.c new file mode 100644 index 00000000..25c287b5 --- /dev/null +++ b/readline/readline-4.3/undo.c @@ -0,0 +1,263 @@ +/* readline.c -- a general facility for reading lines of input + with emacs style editing and completion. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_UNISTD_H) +# include /* for _POSIX_VERSION */ +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +/* Non-zero tells rl_delete_text and rl_insert_text to not add to + the undo list. */ +int _rl_doing_an_undo = 0; + +/* How many unclosed undo groups we currently have. */ +int _rl_undo_group_level = 0; + +/* The current undo list for THE_LINE. */ +UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL; + +/* **************************************************************** */ +/* */ +/* Undo, and Undoing */ +/* */ +/* **************************************************************** */ + +/* Remember how to undo something. Concatenate some undos if that + seems right. */ +void +rl_add_undo (what, start, end, text) + enum undo_code what; + int start, end; + char *text; +{ + UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); + temp->what = what; + temp->start = start; + temp->end = end; + temp->text = text; + temp->next = rl_undo_list; + rl_undo_list = temp; +} + +/* Free the existing undo list. */ +void +rl_free_undo_list () +{ + while (rl_undo_list) + { + UNDO_LIST *release = rl_undo_list; + rl_undo_list = rl_undo_list->next; + + if (release->what == UNDO_DELETE) + free (release->text); + + free (release); + } + rl_undo_list = (UNDO_LIST *)NULL; +} + +/* Undo the next thing in the list. Return 0 if there + is nothing to undo, or non-zero if there was. */ +int +rl_do_undo () +{ + UNDO_LIST *release; + int waiting_for_begin, start, end; + +#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i))) + + start = end = waiting_for_begin = 0; + do + { + if (!rl_undo_list) + return (0); + + _rl_doing_an_undo = 1; + RL_SETSTATE(RL_STATE_UNDOING); + + /* To better support vi-mode, a start or end value of -1 means + rl_point, and a value of -2 means rl_end. */ + if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT) + { + start = TRANS (rl_undo_list->start); + end = TRANS (rl_undo_list->end); + } + + switch (rl_undo_list->what) + { + /* Undoing deletes means inserting some text. */ + case UNDO_DELETE: + rl_point = start; + rl_insert_text (rl_undo_list->text); + free (rl_undo_list->text); + break; + + /* Undoing inserts means deleting some text. */ + case UNDO_INSERT: + rl_delete_text (start, end); + rl_point = start; + break; + + /* Undoing an END means undoing everything 'til we get to a BEGIN. */ + case UNDO_END: + waiting_for_begin++; + break; + + /* Undoing a BEGIN means that we are done with this group. */ + case UNDO_BEGIN: + if (waiting_for_begin) + waiting_for_begin--; + else + rl_ding (); + break; + } + + _rl_doing_an_undo = 0; + RL_UNSETSTATE(RL_STATE_UNDOING); + + release = rl_undo_list; + rl_undo_list = rl_undo_list->next; + free (release); + } + while (waiting_for_begin); + + return (1); +} +#undef TRANS + +int +_rl_fix_last_undo_of_type (type, start, end) + int type, start, end; +{ + UNDO_LIST *rl; + + for (rl = rl_undo_list; rl; rl = rl->next) + { + if (rl->what == type) + { + rl->start = start; + rl->end = end; + return 0; + } + } + return 1; +} + +/* Begin a group. Subsequent undos are undone as an atomic operation. */ +int +rl_begin_undo_group () +{ + rl_add_undo (UNDO_BEGIN, 0, 0, 0); + _rl_undo_group_level++; + return 0; +} + +/* End an undo group started with rl_begin_undo_group (). */ +int +rl_end_undo_group () +{ + rl_add_undo (UNDO_END, 0, 0, 0); + _rl_undo_group_level--; + return 0; +} + +/* Save an undo entry for the text from START to END. */ +int +rl_modifying (start, end) + int start, end; +{ + if (start > end) + { + SWAP (start, end); + } + + if (start != end) + { + char *temp = rl_copy_text (start, end); + rl_begin_undo_group (); + rl_add_undo (UNDO_DELETE, start, end, temp); + rl_add_undo (UNDO_INSERT, start, end, (char *)NULL); + rl_end_undo_group (); + } + return 0; +} + +/* Revert the current line to its previous state. */ +int +rl_revert_line (count, key) + int count, key; +{ + if (!rl_undo_list) + rl_ding (); + else + { + while (rl_undo_list) + rl_do_undo (); + } + return 0; +} + +/* Do some undoing of things that were done. */ +int +rl_undo_command (count, key) + int count, key; +{ + if (count < 0) + return 0; /* Nothing to do. */ + + while (count) + { + if (rl_do_undo ()) + count--; + else + { + rl_ding (); + break; + } + } + return 0; +} diff --git a/readline/readline-4.3/util.c b/readline/readline-4.3/util.c new file mode 100644 index 00000000..c7bd360e --- /dev/null +++ b/readline/readline-4.3/util.c @@ -0,0 +1,338 @@ +/* util.c -- readline utility functions */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include +#include "posixjmp.h" + +#if defined (HAVE_UNISTD_H) +# include /* for _POSIX_VERSION */ +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +#if defined (TIOCSTAT_IN_SYS_IOCTL) +# include +#endif /* TIOCSTAT_IN_SYS_IOCTL */ + +/* Some standard library routines. */ +#include "readline.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +/* **************************************************************** */ +/* */ +/* Utility Functions */ +/* */ +/* **************************************************************** */ + +/* Return 0 if C is not a member of the class of characters that belong + in words, or 1 if it is. */ + +int _rl_allow_pathname_alphabetic_chars = 0; +static const char *pathname_alphabetic_chars = "/-_=~.#$"; + +int +rl_alphabetic (c) + int c; +{ + if (ALPHABETIC (c)) + return (1); + + return (_rl_allow_pathname_alphabetic_chars && + strchr (pathname_alphabetic_chars, c) != NULL); +} + +/* How to abort things. */ +int +_rl_abort_internal () +{ + rl_ding (); + rl_clear_message (); + _rl_init_argument (); + rl_clear_pending_input (); + + RL_UNSETSTATE (RL_STATE_MACRODEF); + while (rl_executing_macro) + _rl_pop_executing_macro (); + + rl_last_func = (rl_command_func_t *)NULL; + longjmp (readline_top_level, 1); + return (0); +} + +int +rl_abort (count, key) + int count, key; +{ + return (_rl_abort_internal ()); +} + +int +rl_tty_status (count, key) + int count, key; +{ +#if defined (TIOCSTAT) + ioctl (1, TIOCSTAT, (char *)0); + rl_refresh_line (count, key); +#else + rl_ding (); +#endif + return 0; +} + +/* Return a copy of the string between FROM and TO. + FROM is inclusive, TO is not. */ +char * +rl_copy_text (from, to) + int from, to; +{ + register int length; + char *copy; + + /* Fix it if the caller is confused. */ + if (from > to) + SWAP (from, to); + + length = to - from; + copy = (char *)xmalloc (1 + length); + strncpy (copy, rl_line_buffer + from, length); + copy[length] = '\0'; + return (copy); +} + +/* Increase the size of RL_LINE_BUFFER until it has enough space to hold + LEN characters. */ +void +rl_extend_line_buffer (len) + int len; +{ + while (len >= rl_line_buffer_len) + { + rl_line_buffer_len += DEFAULT_BUFFER_SIZE; + rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len); + } + + _rl_set_the_line (); +} + + +/* A function for simple tilde expansion. */ +int +rl_tilde_expand (ignore, key) + int ignore, key; +{ + register int start, end; + char *homedir, *temp; + int len; + + end = rl_point; + start = end - 1; + + if (rl_point == rl_end && rl_line_buffer[rl_point] == '~') + { + homedir = tilde_expand ("~"); + _rl_replace_text (homedir, start, end); + return (0); + } + else if (rl_line_buffer[start] != '~') + { + for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--) + ; + start++; + } + + end = start; + do + end++; + while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end); + + if (whitespace (rl_line_buffer[end]) || end >= rl_end) + end--; + + /* If the first character of the current word is a tilde, perform + tilde expansion and insert the result. If not a tilde, do + nothing. */ + if (rl_line_buffer[start] == '~') + { + len = end - start + 1; + temp = (char *)xmalloc (len + 1); + strncpy (temp, rl_line_buffer + start, len); + temp[len] = '\0'; + homedir = tilde_expand (temp); + free (temp); + + _rl_replace_text (homedir, start, end); + } + + return (0); +} + +/* **************************************************************** */ +/* */ +/* String Utility Functions */ +/* */ +/* **************************************************************** */ + +/* Determine if s2 occurs in s1. If so, return a pointer to the + match in s1. The compare is case insensitive. */ +char * +_rl_strindex (s1, s2) + register const char *s1, *s2; +{ + register int i, l, len; + + for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++) + if (_rl_strnicmp (s1 + i, s2, l) == 0) + return ((char *) (s1 + i)); + return ((char *)NULL); +} + +#ifndef HAVE_STRPBRK +/* Find the first occurrence in STRING1 of any character from STRING2. + Return a pointer to the character in STRING1. */ +char * +_rl_strpbrk (string1, string2) + const char *string1, *string2; +{ + register const char *scan; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; + register int i, v; + + memset (&ps, 0, sizeof (mbstate_t)); +#endif + + for (; *string1; string1++) + { + for (scan = string2; *scan; scan++) + { + if (*string1 == *scan) + return ((char *)string1); + } +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + v = _rl_get_char_len (string1, &ps); + if (v > 1) + string += v - 1; /* -1 to account for auto-increment in loop */ + } +#endif + } + return ((char *)NULL); +} +#endif + +#if !defined (HAVE_STRCASECMP) +/* Compare at most COUNT characters from string1 to string2. Case + doesn't matter. */ +int +_rl_strnicmp (string1, string2, count) + char *string1, *string2; + int count; +{ + register char ch1, ch2; + + while (count) + { + ch1 = *string1++; + ch2 = *string2++; + if (_rl_to_upper(ch1) == _rl_to_upper(ch2)) + count--; + else + break; + } + return (count); +} + +/* strcmp (), but caseless. */ +int +_rl_stricmp (string1, string2) + char *string1, *string2; +{ + register char ch1, ch2; + + while (*string1 && *string2) + { + ch1 = *string1++; + ch2 = *string2++; + if (_rl_to_upper(ch1) != _rl_to_upper(ch2)) + return (1); + } + return (*string1 - *string2); +} +#endif /* !HAVE_STRCASECMP */ + +/* Stupid comparison routine for qsort () ing strings. */ +int +_rl_qsort_string_compare (s1, s2) + char **s1, **s2; +{ +#if defined (HAVE_STRCOLL) + return (strcoll (*s1, *s2)); +#else + int result; + + result = **s1 - **s2; + if (result == 0) + result = strcmp (*s1, *s2); + + return result; +#endif +} + +/* Function equivalents for the macros defined in chardefs.h. */ +#define FUNCTION_FOR_MACRO(f) int (f) (c) int c; { return f (c); } + +FUNCTION_FOR_MACRO (_rl_digit_p) +FUNCTION_FOR_MACRO (_rl_digit_value) +FUNCTION_FOR_MACRO (_rl_lowercase_p) +FUNCTION_FOR_MACRO (_rl_pure_alphabetic) +FUNCTION_FOR_MACRO (_rl_to_lower) +FUNCTION_FOR_MACRO (_rl_to_upper) +FUNCTION_FOR_MACRO (_rl_uppercase_p) + +/* Backwards compatibility, now that savestring has been removed from + all `public' readline header files. */ +#undef _rl_savestring +char * +_rl_savestring (s) + const char *s; +{ + return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s))); +} diff --git a/readline/readline-4.3/vi_keymap.c b/readline/readline-4.3/vi_keymap.c new file mode 100644 index 00000000..53a67c67 --- /dev/null +++ b/readline/readline-4.3/vi_keymap.c @@ -0,0 +1,877 @@ +/* vi_keymap.c -- the keymap for vi_mode in readline (). */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (BUFSIZ) +#include +#endif /* !BUFSIZ */ + +#include "readline.h" + +#if 0 +extern KEYMAP_ENTRY_ARRAY vi_escape_keymap; +#endif + +/* The keymap arrays for handling vi mode. */ +KEYMAP_ENTRY_ARRAY vi_movement_keymap = { + /* The regular control keys come first. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */ + { ISFUNC, rl_vi_eof_maybe }, /* Control-d */ + { ISFUNC, rl_emacs_editing_mode }, /* Control-e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */ + { ISFUNC, rl_abort }, /* Control-g */ + { ISFUNC, rl_backward_char }, /* Control-h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, rl_clear_screen }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_get_next_history }, /* Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */ + { ISFUNC, rl_get_previous_history }, /* Control-p */ + { ISFUNC, rl_quoted_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */ + + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-[ */ /* vi_escape_keymap */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */ + { ISFUNC, rl_vi_undo }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, rl_forward_char }, /* SPACE */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* " */ + { ISFUNC, rl_insert_comment }, /* # */ + { ISFUNC, rl_end_of_line }, /* $ */ + { ISFUNC, rl_vi_match }, /* % */ + { ISFUNC, rl_vi_tilde_expand }, /* & */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ( */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ) */ + { ISFUNC, rl_vi_complete }, /* * */ + { ISFUNC, rl_get_next_history}, /* + */ + { ISFUNC, rl_vi_char_search }, /* , */ + { ISFUNC, rl_get_previous_history }, /* - */ + { ISFUNC, rl_vi_redo }, /* . */ + { ISFUNC, rl_vi_search }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_beg_of_line }, /* 0 */ + { ISFUNC, rl_vi_arg_digit }, /* 1 */ + { ISFUNC, rl_vi_arg_digit }, /* 2 */ + { ISFUNC, rl_vi_arg_digit }, /* 3 */ + { ISFUNC, rl_vi_arg_digit }, /* 4 */ + { ISFUNC, rl_vi_arg_digit }, /* 5 */ + { ISFUNC, rl_vi_arg_digit }, /* 6 */ + { ISFUNC, rl_vi_arg_digit }, /* 7 */ + { ISFUNC, rl_vi_arg_digit }, /* 8 */ + { ISFUNC, rl_vi_arg_digit }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* : */ + { ISFUNC, rl_vi_char_search }, /* ; */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* < */ + { ISFUNC, rl_vi_complete }, /* = */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* > */ + { ISFUNC, rl_vi_search }, /* ? */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_vi_append_eol }, /* A */ + { ISFUNC, rl_vi_prev_word}, /* B */ + { ISFUNC, rl_vi_change_to }, /* C */ + { ISFUNC, rl_vi_delete_to }, /* D */ + { ISFUNC, rl_vi_end_word }, /* E */ + { ISFUNC, rl_vi_char_search }, /* F */ + { ISFUNC, rl_vi_fetch_history }, /* G */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* H */ + { ISFUNC, rl_vi_insert_beg }, /* I */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* J */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* K */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* L */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* M */ + { ISFUNC, rl_vi_search_again }, /* N */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* O */ + { ISFUNC, rl_vi_put }, /* P */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Q */ + { ISFUNC, rl_vi_replace }, /* R */ + { ISFUNC, rl_vi_subst }, /* S */ + { ISFUNC, rl_vi_char_search }, /* T */ + { ISFUNC, rl_revert_line }, /* U */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* V */ + { ISFUNC, rl_vi_next_word }, /* W */ + { ISFUNC, rl_rubout }, /* X */ + { ISFUNC, rl_vi_yank_to }, /* Y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* [ */ + { ISFUNC, rl_vi_complete }, /* \ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */ + { ISFUNC, rl_vi_first_print }, /* ^ */ + { ISFUNC, rl_vi_yank_arg }, /* _ */ + { ISFUNC, rl_vi_goto_mark }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, rl_vi_append_mode }, /* a */ + { ISFUNC, rl_vi_prev_word }, /* b */ + { ISFUNC, rl_vi_change_to }, /* c */ + { ISFUNC, rl_vi_delete_to }, /* d */ + { ISFUNC, rl_vi_end_word }, /* e */ + { ISFUNC, rl_vi_char_search }, /* f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* g */ + { ISFUNC, rl_backward_char }, /* h */ + { ISFUNC, rl_vi_insertion_mode }, /* i */ + { ISFUNC, rl_get_next_history }, /* j */ + { ISFUNC, rl_get_previous_history }, /* k */ + { ISFUNC, rl_forward_char }, /* l */ + { ISFUNC, rl_vi_set_mark }, /* m */ + { ISFUNC, rl_vi_search_again }, /* n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* o */ + { ISFUNC, rl_vi_put }, /* p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* q */ + { ISFUNC, rl_vi_change_char }, /* r */ + { ISFUNC, rl_vi_subst }, /* s */ + { ISFUNC, rl_vi_char_search }, /* t */ + { ISFUNC, rl_vi_undo }, /* u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* v */ + { ISFUNC, rl_vi_next_word }, /* w */ + { ISFUNC, rl_vi_delete }, /* x */ + { ISFUNC, rl_vi_yank_to }, /* y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* z */ + + /* Final punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* { */ + { ISFUNC, rl_vi_column }, /* | */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* } */ + { ISFUNC, rl_vi_change_case }, /* ~ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Undefined keys. */ + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 } +#endif /* KEYMAP_SIZE > 128 */ +}; + + +KEYMAP_ENTRY_ARRAY vi_insertion_keymap = { + /* The regular control keys come first. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, rl_insert }, /* Control-a */ + { ISFUNC, rl_insert }, /* Control-b */ + { ISFUNC, rl_insert }, /* Control-c */ + { ISFUNC, rl_vi_eof_maybe }, /* Control-d */ + { ISFUNC, rl_insert }, /* Control-e */ + { ISFUNC, rl_insert }, /* Control-f */ + { ISFUNC, rl_insert }, /* Control-g */ + { ISFUNC, rl_rubout }, /* Control-h */ + { ISFUNC, rl_complete }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_insert }, /* Control-k */ + { ISFUNC, rl_insert }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_insert }, /* Control-n */ + { ISFUNC, rl_insert }, /* Control-o */ + { ISFUNC, rl_insert }, /* Control-p */ + { ISFUNC, rl_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISFUNC, rl_insert }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, rl_insert }, /* Control-z */ + + { ISFUNC, rl_vi_movement_mode }, /* Control-[ */ + { ISFUNC, rl_insert }, /* Control-\ */ + { ISFUNC, rl_insert }, /* Control-] */ + { ISFUNC, rl_insert }, /* Control-^ */ + { ISFUNC, rl_vi_undo }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, rl_insert }, /* SPACE */ + { ISFUNC, rl_insert }, /* ! */ + { ISFUNC, rl_insert }, /* " */ + { ISFUNC, rl_insert }, /* # */ + { ISFUNC, rl_insert }, /* $ */ + { ISFUNC, rl_insert }, /* % */ + { ISFUNC, rl_insert }, /* & */ + { ISFUNC, rl_insert }, /* ' */ + { ISFUNC, rl_insert }, /* ( */ + { ISFUNC, rl_insert }, /* ) */ + { ISFUNC, rl_insert }, /* * */ + { ISFUNC, rl_insert }, /* + */ + { ISFUNC, rl_insert }, /* , */ + { ISFUNC, rl_insert }, /* - */ + { ISFUNC, rl_insert }, /* . */ + { ISFUNC, rl_insert }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_insert }, /* 0 */ + { ISFUNC, rl_insert }, /* 1 */ + { ISFUNC, rl_insert }, /* 2 */ + { ISFUNC, rl_insert }, /* 3 */ + { ISFUNC, rl_insert }, /* 4 */ + { ISFUNC, rl_insert }, /* 5 */ + { ISFUNC, rl_insert }, /* 6 */ + { ISFUNC, rl_insert }, /* 7 */ + { ISFUNC, rl_insert }, /* 8 */ + { ISFUNC, rl_insert }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, rl_insert }, /* : */ + { ISFUNC, rl_insert }, /* ; */ + { ISFUNC, rl_insert }, /* < */ + { ISFUNC, rl_insert }, /* = */ + { ISFUNC, rl_insert }, /* > */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_insert }, /* A */ + { ISFUNC, rl_insert }, /* B */ + { ISFUNC, rl_insert }, /* C */ + { ISFUNC, rl_insert }, /* D */ + { ISFUNC, rl_insert }, /* E */ + { ISFUNC, rl_insert }, /* F */ + { ISFUNC, rl_insert }, /* G */ + { ISFUNC, rl_insert }, /* H */ + { ISFUNC, rl_insert }, /* I */ + { ISFUNC, rl_insert }, /* J */ + { ISFUNC, rl_insert }, /* K */ + { ISFUNC, rl_insert }, /* L */ + { ISFUNC, rl_insert }, /* M */ + { ISFUNC, rl_insert }, /* N */ + { ISFUNC, rl_insert }, /* O */ + { ISFUNC, rl_insert }, /* P */ + { ISFUNC, rl_insert }, /* Q */ + { ISFUNC, rl_insert }, /* R */ + { ISFUNC, rl_insert }, /* S */ + { ISFUNC, rl_insert }, /* T */ + { ISFUNC, rl_insert }, /* U */ + { ISFUNC, rl_insert }, /* V */ + { ISFUNC, rl_insert }, /* W */ + { ISFUNC, rl_insert }, /* X */ + { ISFUNC, rl_insert }, /* Y */ + { ISFUNC, rl_insert }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, rl_insert }, /* [ */ + { ISFUNC, rl_insert }, /* \ */ + { ISFUNC, rl_insert }, /* ] */ + { ISFUNC, rl_insert }, /* ^ */ + { ISFUNC, rl_insert }, /* _ */ + { ISFUNC, rl_insert }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, rl_insert }, /* a */ + { ISFUNC, rl_insert }, /* b */ + { ISFUNC, rl_insert }, /* c */ + { ISFUNC, rl_insert }, /* d */ + { ISFUNC, rl_insert }, /* e */ + { ISFUNC, rl_insert }, /* f */ + { ISFUNC, rl_insert }, /* g */ + { ISFUNC, rl_insert }, /* h */ + { ISFUNC, rl_insert }, /* i */ + { ISFUNC, rl_insert }, /* j */ + { ISFUNC, rl_insert }, /* k */ + { ISFUNC, rl_insert }, /* l */ + { ISFUNC, rl_insert }, /* m */ + { ISFUNC, rl_insert }, /* n */ + { ISFUNC, rl_insert }, /* o */ + { ISFUNC, rl_insert }, /* p */ + { ISFUNC, rl_insert }, /* q */ + { ISFUNC, rl_insert }, /* r */ + { ISFUNC, rl_insert }, /* s */ + { ISFUNC, rl_insert }, /* t */ + { ISFUNC, rl_insert }, /* u */ + { ISFUNC, rl_insert }, /* v */ + { ISFUNC, rl_insert }, /* w */ + { ISFUNC, rl_insert }, /* x */ + { ISFUNC, rl_insert }, /* y */ + { ISFUNC, rl_insert }, /* z */ + + /* Final punctuation. */ + { ISFUNC, rl_insert }, /* { */ + { ISFUNC, rl_insert }, /* | */ + { ISFUNC, rl_insert }, /* } */ + { ISFUNC, rl_insert }, /* ~ */ + { ISFUNC, rl_rubout }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Pure 8-bit characters (128 - 159). + These might be used in some + character sets. */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + + /* ISO Latin-1 characters (160 - 255) */ + { ISFUNC, rl_insert }, /* No-break space */ + { ISFUNC, rl_insert }, /* Inverted exclamation mark */ + { ISFUNC, rl_insert }, /* Cent sign */ + { ISFUNC, rl_insert }, /* Pound sign */ + { ISFUNC, rl_insert }, /* Currency sign */ + { ISFUNC, rl_insert }, /* Yen sign */ + { ISFUNC, rl_insert }, /* Broken bar */ + { ISFUNC, rl_insert }, /* Section sign */ + { ISFUNC, rl_insert }, /* Diaeresis */ + { ISFUNC, rl_insert }, /* Copyright sign */ + { ISFUNC, rl_insert }, /* Feminine ordinal indicator */ + { ISFUNC, rl_insert }, /* Left pointing double angle quotation mark */ + { ISFUNC, rl_insert }, /* Not sign */ + { ISFUNC, rl_insert }, /* Soft hyphen */ + { ISFUNC, rl_insert }, /* Registered sign */ + { ISFUNC, rl_insert }, /* Macron */ + { ISFUNC, rl_insert }, /* Degree sign */ + { ISFUNC, rl_insert }, /* Plus-minus sign */ + { ISFUNC, rl_insert }, /* Superscript two */ + { ISFUNC, rl_insert }, /* Superscript three */ + { ISFUNC, rl_insert }, /* Acute accent */ + { ISFUNC, rl_insert }, /* Micro sign */ + { ISFUNC, rl_insert }, /* Pilcrow sign */ + { ISFUNC, rl_insert }, /* Middle dot */ + { ISFUNC, rl_insert }, /* Cedilla */ + { ISFUNC, rl_insert }, /* Superscript one */ + { ISFUNC, rl_insert }, /* Masculine ordinal indicator */ + { ISFUNC, rl_insert }, /* Right pointing double angle quotation mark */ + { ISFUNC, rl_insert }, /* Vulgar fraction one quarter */ + { ISFUNC, rl_insert }, /* Vulgar fraction one half */ + { ISFUNC, rl_insert }, /* Vulgar fraction three quarters */ + { ISFUNC, rl_insert }, /* Inverted questionk mark */ + { ISFUNC, rl_insert }, /* Latin capital letter a with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter a with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter a with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter a with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter a with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter a with ring above */ + { ISFUNC, rl_insert }, /* Latin capital letter ae */ + { ISFUNC, rl_insert }, /* Latin capital letter c with cedilla */ + { ISFUNC, rl_insert }, /* Latin capital letter e with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter e with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter e with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter e with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter i with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter i with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter i with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter i with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter eth (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin capital letter n with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter o with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter o with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter o with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter o with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter o with diaeresis */ + { ISFUNC, rl_insert }, /* Multiplication sign */ + { ISFUNC, rl_insert }, /* Latin capital letter o with stroke */ + { ISFUNC, rl_insert }, /* Latin capital letter u with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter u with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter u with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter u with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter Y with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter thorn (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin small letter sharp s (German) */ + { ISFUNC, rl_insert }, /* Latin small letter a with grave */ + { ISFUNC, rl_insert }, /* Latin small letter a with acute */ + { ISFUNC, rl_insert }, /* Latin small letter a with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter a with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter a with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter a with ring above */ + { ISFUNC, rl_insert }, /* Latin small letter ae */ + { ISFUNC, rl_insert }, /* Latin small letter c with cedilla */ + { ISFUNC, rl_insert }, /* Latin small letter e with grave */ + { ISFUNC, rl_insert }, /* Latin small letter e with acute */ + { ISFUNC, rl_insert }, /* Latin small letter e with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter e with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter i with grave */ + { ISFUNC, rl_insert }, /* Latin small letter i with acute */ + { ISFUNC, rl_insert }, /* Latin small letter i with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter i with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter eth (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin small letter n with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter o with grave */ + { ISFUNC, rl_insert }, /* Latin small letter o with acute */ + { ISFUNC, rl_insert }, /* Latin small letter o with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter o with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter o with diaeresis */ + { ISFUNC, rl_insert }, /* Division sign */ + { ISFUNC, rl_insert }, /* Latin small letter o with stroke */ + { ISFUNC, rl_insert }, /* Latin small letter u with grave */ + { ISFUNC, rl_insert }, /* Latin small letter u with acute */ + { ISFUNC, rl_insert }, /* Latin small letter u with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter u with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter y with acute */ + { ISFUNC, rl_insert }, /* Latin small letter thorn (Icelandic) */ + { ISFUNC, rl_insert } /* Latin small letter y with diaeresis */ +#endif /* KEYMAP_SIZE > 128 */ +}; + +/* Unused for the time being. */ +#if 0 +KEYMAP_ENTRY_ARRAY vi_escape_keymap = { + /* The regular control keys come first. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-h */ + { ISFUNC, rl_tab_insert}, /* Control-i */ + { ISFUNC, rl_emacs_editing_mode}, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-l */ + { ISFUNC, rl_emacs_editing_mode}, /* Control-m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-q */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-t */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-x */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */ + + { ISFUNC, rl_vi_movement_mode }, /* Control-[ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */ + { ISFUNC, rl_vi_undo }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* SPACE */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* " */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* # */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* $ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* % */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* & */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ( */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ) */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* * */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* + */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* , */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* - */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* . */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_vi_arg_digit }, /* 0 */ + { ISFUNC, rl_vi_arg_digit }, /* 1 */ + { ISFUNC, rl_vi_arg_digit }, /* 2 */ + { ISFUNC, rl_vi_arg_digit }, /* 3 */ + { ISFUNC, rl_vi_arg_digit }, /* 4 */ + { ISFUNC, rl_vi_arg_digit }, /* 5 */ + { ISFUNC, rl_vi_arg_digit }, /* 6 */ + { ISFUNC, rl_vi_arg_digit }, /* 7 */ + { ISFUNC, rl_vi_arg_digit }, /* 8 */ + { ISFUNC, rl_vi_arg_digit }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* : */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ; */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* < */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* = */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* > */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ? */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_do_lowercase_version }, /* A */ + { ISFUNC, rl_do_lowercase_version }, /* B */ + { ISFUNC, rl_do_lowercase_version }, /* C */ + { ISFUNC, rl_do_lowercase_version }, /* D */ + { ISFUNC, rl_do_lowercase_version }, /* E */ + { ISFUNC, rl_do_lowercase_version }, /* F */ + { ISFUNC, rl_do_lowercase_version }, /* G */ + { ISFUNC, rl_do_lowercase_version }, /* H */ + { ISFUNC, rl_do_lowercase_version }, /* I */ + { ISFUNC, rl_do_lowercase_version }, /* J */ + { ISFUNC, rl_do_lowercase_version }, /* K */ + { ISFUNC, rl_do_lowercase_version }, /* L */ + { ISFUNC, rl_do_lowercase_version }, /* M */ + { ISFUNC, rl_do_lowercase_version }, /* N */ + { ISFUNC, rl_do_lowercase_version }, /* O */ + { ISFUNC, rl_do_lowercase_version }, /* P */ + { ISFUNC, rl_do_lowercase_version }, /* Q */ + { ISFUNC, rl_do_lowercase_version }, /* R */ + { ISFUNC, rl_do_lowercase_version }, /* S */ + { ISFUNC, rl_do_lowercase_version }, /* T */ + { ISFUNC, rl_do_lowercase_version }, /* U */ + { ISFUNC, rl_do_lowercase_version }, /* V */ + { ISFUNC, rl_do_lowercase_version }, /* W */ + { ISFUNC, rl_do_lowercase_version }, /* X */ + { ISFUNC, rl_do_lowercase_version }, /* Y */ + { ISFUNC, rl_do_lowercase_version }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, rl_arrow_keys }, /* [ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* \ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ^ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* _ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* i */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* l */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* n */ + { ISFUNC, rl_arrow_keys }, /* o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* q */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* t */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* x */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* z */ + + /* Final punctuation. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* { */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* | */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* } */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ~ */ + { ISFUNC, rl_backward_kill_word }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Undefined keys. */ + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 } +#endif /* KEYMAP_SIZE > 128 */ +}; +#endif diff --git a/readline/readline-4.3/vi_mode.c b/readline/readline-4.3/vi_mode.c new file mode 100644 index 00000000..89303644 --- /dev/null +++ b/readline/readline-4.3/vi_mode.c @@ -0,0 +1,1488 @@ +/* vi_mode.c -- A vi emulation mode for Bash. + Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +/* **************************************************************** */ +/* */ +/* VI Emulation Mode */ +/* */ +/* **************************************************************** */ +#include "rlconf.h" + +#if defined (VI_MODE) + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include + +/* Some standard library routines. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +#ifndef member +#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) +#endif + +/* Non-zero means enter insertion mode. */ +static int _rl_vi_doing_insert; + +/* Command keys which do movement for xxx_to commands. */ +static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|"; + +/* Keymap used for vi replace characters. Created dynamically since + rarely used. */ +static Keymap vi_replace_map; + +/* The number of characters inserted in the last replace operation. */ +static int vi_replace_count; + +/* If non-zero, we have text inserted after a c[motion] command that put + us implicitly into insert mode. Some people want this text to be + attached to the command so that it is `redoable' with `.'. */ +static int vi_continued_command; +static char *vi_insert_buffer; +static int vi_insert_buffer_size; + +static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ +static int _rl_vi_last_repeat = 1; +static int _rl_vi_last_arg_sign = 1; +static int _rl_vi_last_motion; +#if defined (HANDLE_MULTIBYTE) +static char _rl_vi_last_search_mbchar[MB_LEN_MAX]; +#else +static int _rl_vi_last_search_char; +#endif +static int _rl_vi_last_replacement; + +static int _rl_vi_last_key_before_insert; + +static int vi_redoing; + +/* Text modification commands. These are the `redoable' commands. */ +static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; + +/* Arrays for the saved marks. */ +static int vi_mark_chars['z' - 'a' + 1]; + +static void _rl_vi_stuff_insert PARAMS((int)); +static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); +static int rl_digit_loop1 PARAMS((void)); + +void +_rl_vi_initialize_line () +{ + register int i; + + for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) + vi_mark_chars[i] = -1; +} + +void +_rl_vi_reset_last () +{ + _rl_vi_last_command = 'i'; + _rl_vi_last_repeat = 1; + _rl_vi_last_arg_sign = 1; + _rl_vi_last_motion = 0; +} + +void +_rl_vi_set_last (key, repeat, sign) + int key, repeat, sign; +{ + _rl_vi_last_command = key; + _rl_vi_last_repeat = repeat; + _rl_vi_last_arg_sign = sign; +} + +/* Is the command C a VI mode text modification command? */ +int +_rl_vi_textmod_command (c) + int c; +{ + return (member (c, vi_textmod)); +} + +static void +_rl_vi_stuff_insert (count) + int count; +{ + rl_begin_undo_group (); + while (count--) + rl_insert_text (vi_insert_buffer); + rl_end_undo_group (); +} + +/* Bound to `.'. Called from command mode, so we know that we have to + redo a text modification command. The default for _rl_vi_last_command + puts you back into insert mode. */ +int +rl_vi_redo (count, c) + int count, c; +{ + int r; + + if (!rl_explicit_arg) + { + rl_numeric_arg = _rl_vi_last_repeat; + rl_arg_sign = _rl_vi_last_arg_sign; + } + + r = 0; + vi_redoing = 1; + /* If we're redoing an insert with `i', stuff in the inserted text + and do not go into insertion mode. */ + if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer) + { + _rl_vi_stuff_insert (count); + /* And back up point over the last character inserted. */ + if (rl_point > 0) + rl_point--; + } + else + r = _rl_dispatch (_rl_vi_last_command, _rl_keymap); + vi_redoing = 0; + + return (r); +} + +/* A placeholder for further expansion. */ +int +rl_vi_undo (count, key) + int count, key; +{ + return (rl_undo_command (count, key)); +} + +/* Yank the nth arg from the previous line into this line at point. */ +int +rl_vi_yank_arg (count, key) + int count, key; +{ + /* Readline thinks that the first word on a line is the 0th, while vi + thinks the first word on a line is the 1st. Compensate. */ + if (rl_explicit_arg) + rl_yank_nth_arg (count - 1, 0); + else + rl_yank_nth_arg ('$', 0); + + return (0); +} + +/* With an argument, move back that many history lines, else move to the + beginning of history. */ +int +rl_vi_fetch_history (count, c) + int count, c; +{ + int wanted; + + /* Giving an argument of n means we want the nth command in the history + file. The command number is interpreted the same way that the bash + `history' command does it -- that is, giving an argument count of 450 + to this command would get the command listed as number 450 in the + output of `history'. */ + if (rl_explicit_arg) + { + wanted = history_base + where_history () - count; + if (wanted <= 0) + rl_beginning_of_history (0, 0); + else + rl_get_previous_history (wanted, c); + } + else + rl_beginning_of_history (count, 0); + return (0); +} + +/* Search again for the last thing searched for. */ +int +rl_vi_search_again (count, key) + int count, key; +{ + switch (key) + { + case 'n': + rl_noninc_reverse_search_again (count, key); + break; + + case 'N': + rl_noninc_forward_search_again (count, key); + break; + } + return (0); +} + +/* Do a vi style search. */ +int +rl_vi_search (count, key) + int count, key; +{ + switch (key) + { + case '?': + rl_noninc_forward_search (count, key); + break; + + case '/': + rl_noninc_reverse_search (count, key); + break; + + default: + rl_ding (); + break; + } + return (0); +} + +/* Completion, from vi's point of view. */ +int +rl_vi_complete (ignore, key) + int ignore, key; +{ + if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) + { + if (!whitespace (rl_line_buffer[rl_point + 1])) + rl_vi_end_word (1, 'E'); + rl_point++; + } + + if (key == '*') + rl_complete_internal ('*'); /* Expansion and replacement. */ + else if (key == '=') + rl_complete_internal ('?'); /* List possible completions. */ + else if (key == '\\') + rl_complete_internal (TAB); /* Standard Readline completion. */ + else + rl_complete (0, key); + + if (key == '*' || key == '\\') + { + _rl_vi_set_last (key, 1, rl_arg_sign); + rl_vi_insertion_mode (1, key); + } + return (0); +} + +/* Tilde expansion for vi mode. */ +int +rl_vi_tilde_expand (ignore, key) + int ignore, key; +{ + rl_tilde_expand (0, key); + _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */ + rl_vi_insertion_mode (1, key); + return (0); +} + +/* Previous word in vi mode. */ +int +rl_vi_prev_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_vi_next_word (-count, key)); + + if (rl_point == 0) + { + rl_ding (); + return (0); + } + + if (_rl_uppercase_p (key)) + rl_vi_bWord (count, key); + else + rl_vi_bword (count, key); + + return (0); +} + +/* Next word in vi mode. */ +int +rl_vi_next_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_vi_prev_word (-count, key)); + + if (rl_point >= (rl_end - 1)) + { + rl_ding (); + return (0); + } + + if (_rl_uppercase_p (key)) + rl_vi_fWord (count, key); + else + rl_vi_fword (count, key); + return (0); +} + +/* Move to the end of the ?next? word. */ +int +rl_vi_end_word (count, key) + int count, key; +{ + if (count < 0) + { + rl_ding (); + return -1; + } + + if (_rl_uppercase_p (key)) + rl_vi_eWord (count, key); + else + rl_vi_eword (count, key); + return (0); +} + +/* Move forward a word the way that 'W' does. */ +int +rl_vi_fWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + /* Skip until whitespace. */ + while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + + /* Now skip whitespace. */ + while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + return (0); +} + +int +rl_vi_bWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point > 0) + { + /* If we are at the start of a word, move back to whitespace so + we will go back to the start of the previous word. */ + if (!whitespace (rl_line_buffer[rl_point]) && + whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + if (rl_point > 0) + { + while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point])); + rl_point++; + } + } + return (0); +} + +int +rl_vi_eWord (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + if (!whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Move to the next non-whitespace character (to the start of the + next word). */ + while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point])); + + if (rl_point && rl_point < rl_end) + { + /* Skip whitespace. */ + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Skip until whitespace. */ + while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Move back to the last character of the word. */ + rl_point--; + } + } + return (0); +} + +int +rl_vi_fword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < (rl_end - 1)) + { + /* Move to white space (really non-identifer). */ + if (_rl_isident (rl_line_buffer[rl_point])) + { + while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + else /* if (!whitespace (rl_line_buffer[rl_point])) */ + { + while (!_rl_isident (rl_line_buffer[rl_point]) && + !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + + /* Move past whitespace. */ + while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + return (0); +} + +int +rl_vi_bword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point > 0) + { + int last_is_ident; + + /* If we are at the start of a word, move back to whitespace + so we will go back to the start of the previous word. */ + if (!whitespace (rl_line_buffer[rl_point]) && + whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + /* If this character and the previous character are `opposite', move + back so we don't get messed up by the rl_point++ down there in + the while loop. Without this code, words like `l;' screw up the + function. */ + last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]); + if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) || + (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident)) + rl_point--; + + while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + if (rl_point > 0) + { + if (_rl_isident (rl_line_buffer[rl_point])) + while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point])); + else + while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) && + !whitespace (rl_line_buffer[rl_point])); + rl_point++; + } + } + return (0); +} + +int +rl_vi_eword (count, ignore) + int count, ignore; +{ + while (count-- && rl_point < rl_end - 1) + { + if (!whitespace (rl_line_buffer[rl_point])) + rl_point++; + + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + if (rl_point < rl_end) + { + if (_rl_isident (rl_line_buffer[rl_point])) + while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point])); + else + while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point]) + && !whitespace (rl_line_buffer[rl_point])); + } + rl_point--; + } + return (0); +} + +int +rl_vi_insert_beg (count, key) + int count, key; +{ + rl_beg_of_line (1, key); + rl_vi_insertion_mode (1, key); + return (0); +} + +int +rl_vi_append_mode (count, key) + int count, key; +{ + if (rl_point < rl_end) + { + if (MB_CUR_MAX == 1 || rl_byte_oriented) + rl_point++; + else + { + int point = rl_point; + rl_forward_char (1, key); + if (point == rl_point) + rl_point = rl_end; + } + } + rl_vi_insertion_mode (1, key); + return (0); +} + +int +rl_vi_append_eol (count, key) + int count, key; +{ + rl_end_of_line (1, key); + rl_vi_append_mode (1, key); + return (0); +} + +/* What to do in the case of C-d. */ +int +rl_vi_eof_maybe (count, c) + int count, c; +{ + return (rl_newline (1, '\n')); +} + +/* Insertion mode stuff. */ + +/* Switching from one mode to the other really just involves + switching keymaps. */ +int +rl_vi_insertion_mode (count, key) + int count, key; +{ + _rl_keymap = vi_insertion_keymap; + _rl_vi_last_key_before_insert = key; + return (0); +} + +static void +_rl_vi_save_insert (up) + UNDO_LIST *up; +{ + int len, start, end; + + if (up == 0) + { + if (vi_insert_buffer_size >= 1) + vi_insert_buffer[0] = '\0'; + return; + } + + start = up->start; + end = up->end; + len = end - start + 1; + if (len >= vi_insert_buffer_size) + { + vi_insert_buffer_size += (len + 32) - (len % 32); + vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); + } + strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); + vi_insert_buffer[len-1] = '\0'; +} + +void +_rl_vi_done_inserting () +{ + if (_rl_vi_doing_insert) + { + /* The `C', `s', and `S' commands set this. */ + rl_end_undo_group (); + /* Now, the text between rl_undo_list->next->start and + rl_undo_list->next->end is what was inserted while in insert + mode. It gets copied to VI_INSERT_BUFFER because it depends + on absolute indices into the line which may change (though they + probably will not). */ + _rl_vi_doing_insert = 0; + _rl_vi_save_insert (rl_undo_list->next); + vi_continued_command = 1; + } + else + { + if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list) + _rl_vi_save_insert (rl_undo_list); + /* XXX - Other keys probably need to be checked. */ + else if (_rl_vi_last_key_before_insert == 'C') + rl_end_undo_group (); + while (_rl_undo_group_level > 0) + rl_end_undo_group (); + vi_continued_command = 0; + } +} + +int +rl_vi_movement_mode (count, key) + int count, key; +{ + if (rl_point > 0) + rl_backward_char (1, key); + + _rl_keymap = vi_movement_keymap; + _rl_vi_done_inserting (); + return (0); +} + +int +rl_vi_arg_digit (count, c) + int count, c; +{ + if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) + return (rl_beg_of_line (1, c)); + else + return (rl_digit_argument (count, c)); +} + +/* Change the case of the next COUNT characters. */ +#if defined (HANDLE_MULTIBYTE) +static int +_rl_vi_change_mbchar_case (count) + int count; +{ + wchar_t wc; + char mb[MB_LEN_MAX+1]; + int mblen; + mbstate_t ps; + + memset (&ps, 0, sizeof (mbstate_t)); + if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0) + count--; + while (count-- && rl_point < rl_end) + { + mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); + if (iswupper (wc)) + wc = towlower (wc); + else if (iswlower (wc)) + wc = towupper (wc); + else + { + /* Just skip over chars neither upper nor lower case */ + rl_forward_char (1, 0); + continue; + } + + /* Vi is kind of strange here. */ + if (wc) + { + mblen = wctomb (mb, wc); + if (mblen >= 0) + mb[mblen] = '\0'; + rl_begin_undo_group (); + rl_delete (1, 0); + rl_insert_text (mb); + rl_end_undo_group (); + rl_vi_check (); + } + else + rl_forward_char (1, 0); + } + + return 0; +} +#endif + +int +rl_vi_change_case (count, ignore) + int count, ignore; +{ + char c = 0; + + /* Don't try this on an empty line. */ + if (rl_point >= rl_end) + return (0); + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + return (_rl_vi_change_mbchar_case (count)); +#endif + + while (count-- && rl_point < rl_end) + { + if (_rl_uppercase_p (rl_line_buffer[rl_point])) + c = _rl_to_lower (rl_line_buffer[rl_point]); + else if (_rl_lowercase_p (rl_line_buffer[rl_point])) + c = _rl_to_upper (rl_line_buffer[rl_point]); + else + { + /* Just skip over characters neither upper nor lower case. */ + rl_forward_char (1, c); + continue; + } + + /* Vi is kind of strange here. */ + if (c) + { + rl_begin_undo_group (); + rl_delete (1, c); + _rl_insert_char (1, c); + rl_end_undo_group (); + rl_vi_check (); + } + else + rl_forward_char (1, c); + } + return (0); +} + +int +rl_vi_put (count, key) + int count, key; +{ + if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) + rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + + rl_yank (1, key); + rl_backward_char (1, key); + return (0); +} + +int +rl_vi_check () +{ + if (rl_point && rl_point == rl_end) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + rl_point--; + } + return (0); +} + +int +rl_vi_column (count, key) + int count, key; +{ + if (count > rl_end) + rl_end_of_line (1, key); + else + rl_point = count - 1; + return (0); +} + +int +rl_vi_domove (key, nextkey) + int key, *nextkey; +{ + int c, save; + int old_end; + + rl_mark = rl_point; + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + *nextkey = c; + + if (!member (c, vi_motion)) + { + if (_rl_digit_p (c)) + { + save = rl_numeric_arg; + rl_numeric_arg = _rl_digit_value (c); + rl_digit_loop1 (); + rl_numeric_arg *= save; + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); /* real command */ + RL_UNSETSTATE(RL_STATE_MOREINPUT); + *nextkey = c; + } + else if (key == c && (key == 'd' || key == 'y' || key == 'c')) + { + rl_mark = rl_end; + rl_beg_of_line (1, c); + _rl_vi_last_motion = c; + return (0); + } + else + return (-1); + } + + _rl_vi_last_motion = c; + + /* Append a blank character temporarily so that the motion routines + work right at the end of the line. */ + old_end = rl_end; + rl_line_buffer[rl_end++] = ' '; + rl_line_buffer[rl_end] = '\0'; + + _rl_dispatch (c, _rl_keymap); + + /* Remove the blank that we added. */ + rl_end = old_end; + rl_line_buffer[rl_end] = '\0'; + if (rl_point > rl_end) + rl_point = rl_end; + + /* No change in position means the command failed. */ + if (rl_mark == rl_point) + return (-1); + + /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next + word. If we are not at the end of the line, and we are on a + non-whitespace character, move back one (presumably to whitespace). */ + if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && + !whitespace (rl_line_buffer[rl_point])) + rl_point--; + + /* If cw or cW, back up to the end of a word, so the behaviour of ce + or cE is the actual result. Brute-force, no subtlety. */ + if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) + { + /* Don't move farther back than where we started. */ + while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + /* Posix.2 says that if cw or cW moves the cursor towards the end of + the line, the character under the cursor should be deleted. */ + if (rl_point == rl_mark) + rl_point++; + else + { + /* Move past the end of the word so that the kill doesn't + remove the last letter of the previous word. Only do this + if we are not at the end of the line. */ + if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) + rl_point++; + } + } + + if (rl_mark < rl_point) + SWAP (rl_point, rl_mark); + + return (0); +} + +/* A simplified loop for vi. Don't dispatch key at end. + Don't recognize minus sign? + Should this do rl_save_prompt/rl_restore_prompt? */ +static int +rl_digit_loop1 () +{ + int key, c; + + RL_SETSTATE(RL_STATE_NUMERICARG); + while (1) + { + if (rl_numeric_arg > 1000000) + { + rl_explicit_arg = rl_numeric_arg = 0; + rl_ding (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return 1; + } + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); + RL_SETSTATE(RL_STATE_MOREINPUT); + key = c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (c >= 0 && _rl_keymap[c].type == ISFUNC && + _rl_keymap[c].function == rl_universal_argument) + { + rl_numeric_arg *= 4; + continue; + } + + c = UNMETA (c); + if (_rl_digit_p (c)) + { + if (rl_explicit_arg) + rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); + else + rl_numeric_arg = _rl_digit_value (c); + rl_explicit_arg = 1; + } + else + { + rl_clear_message (); + rl_stuff_char (key); + break; + } + } + + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return (0); +} + +int +rl_vi_delete_to (count, key) + int count, key; +{ + int c; + + if (_rl_uppercase_p (key)) + rl_stuff_char ('$'); + else if (vi_redoing) + rl_stuff_char (_rl_vi_last_motion); + + if (rl_vi_domove (key, &c)) + { + rl_ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. */ + if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + rl_kill_text (rl_point, rl_mark); + return (0); +} + +int +rl_vi_change_to (count, key) + int count, key; +{ + int c, start_pos; + + if (_rl_uppercase_p (key)) + rl_stuff_char ('$'); + else if (vi_redoing) + rl_stuff_char (_rl_vi_last_motion); + + start_pos = rl_point; + + if (rl_vi_domove (key, &c)) + { + rl_ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. c[wW] are handled by special-case code in rl_vi_domove(), + and already leave the mark at the correct location. */ + if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + /* The cursor never moves with c[wW]. */ + if ((_rl_to_upper (c) == 'W') && rl_point < start_pos) + rl_point = start_pos; + + if (vi_redoing) + { + if (vi_insert_buffer && *vi_insert_buffer) + rl_begin_undo_group (); + rl_delete_text (rl_point, rl_mark); + if (vi_insert_buffer && *vi_insert_buffer) + { + rl_insert_text (vi_insert_buffer); + rl_end_undo_group (); + } + } + else + { + rl_begin_undo_group (); /* to make the `u' command work */ + rl_kill_text (rl_point, rl_mark); + /* `C' does not save the text inserted for undoing or redoing. */ + if (_rl_uppercase_p (key) == 0) + _rl_vi_doing_insert = 1; + _rl_vi_set_last (key, count, rl_arg_sign); + rl_vi_insertion_mode (1, key); + } + + return (0); +} + +int +rl_vi_yank_to (count, key) + int count, key; +{ + int c, save = rl_point; + + if (_rl_uppercase_p (key)) + rl_stuff_char ('$'); + + if (rl_vi_domove (key, &c)) + { + rl_ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. */ + if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + rl_begin_undo_group (); + rl_kill_text (rl_point, rl_mark); + rl_end_undo_group (); + rl_do_undo (); + rl_point = save; + + return (0); +} + +int +rl_vi_delete (count, key) + int count, key; +{ + int end; + + if (rl_end == 0) + { + rl_ding (); + return -1; + } + + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); + else + end = rl_point + count; + + if (end >= rl_end) + end = rl_end; + + rl_kill_text (rl_point, end); + + if (rl_point > 0 && rl_point == rl_end) + rl_backward_char (1, key); + return (0); +} + +int +rl_vi_back_to_indent (count, key) + int count, key; +{ + rl_beg_of_line (1, key); + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + return (0); +} + +int +rl_vi_first_print (count, key) + int count, key; +{ + return (rl_vi_back_to_indent (1, key)); +} + +int +rl_vi_char_search (count, key) + int count, key; +{ +#if defined (HANDLE_MULTIBYTE) + static char *target; + static int mb_len; +#else + static char target; +#endif + static int orig_dir, dir; + + if (key == ';' || key == ',') + dir = key == ';' ? orig_dir : -orig_dir; + else + { + if (vi_redoing) +#if defined (HANDLE_MULTIBYTE) + target = _rl_vi_last_search_mbchar; +#else + target = _rl_vi_last_search_char; +#endif + else + { +#if defined (HANDLE_MULTIBYTE) + mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); + target = _rl_vi_last_search_mbchar; +#else + RL_SETSTATE(RL_STATE_MOREINPUT); + _rl_vi_last_search_char = target = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); +#endif + } + + switch (key) + { + case 't': + orig_dir = dir = FTO; + break; + + case 'T': + orig_dir = dir = BTO; + break; + + case 'f': + orig_dir = dir = FFIND; + break; + + case 'F': + orig_dir = dir = BFIND; + break; + } + } + +#if defined (HANDLE_MULTIBYTE) + return (_rl_char_search_internal (count, dir, target, mb_len)); +#else + return (_rl_char_search_internal (count, dir, target)); +#endif +} + +/* Match brackets */ +int +rl_vi_match (ignore, key) + int ignore, key; +{ + int count = 1, brack, pos, tmp, pre; + + pos = rl_point; + if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) + { + pre = rl_point; + rl_forward_char (1, key); + if (pre == rl_point) + break; + } + } + else + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && + rl_point < rl_end - 1) + rl_forward_char (1, key); + + if (brack <= 0) + { + rl_point = pos; + rl_ding (); + return -1; + } + } + + pos = rl_point; + + if (brack < 0) + { + while (count) + { + tmp = pos; + if (MB_CUR_MAX == 1 || rl_byte_oriented) + pos--; + else + { + pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); + if (tmp == pos) + pos--; + } + if (pos >= 0) + { + int b = rl_vi_bracktype (rl_line_buffer[pos]); + if (b == -brack) + count--; + else if (b == brack) + count++; + } + else + { + rl_ding (); + return -1; + } + } + } + else + { /* brack > 0 */ + while (count) + { + if (MB_CUR_MAX == 1 || rl_byte_oriented) + pos++; + else + pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY); + + if (pos < rl_end) + { + int b = rl_vi_bracktype (rl_line_buffer[pos]); + if (b == -brack) + count--; + else if (b == brack) + count++; + } + else + { + rl_ding (); + return -1; + } + } + } + rl_point = pos; + return (0); +} + +int +rl_vi_bracktype (c) + int c; +{ + switch (c) + { + case '(': return 1; + case ')': return -1; + case '[': return 2; + case ']': return -2; + case '{': return 3; + case '}': return -3; + default: return 0; + } +} + +/* XXX - think about reading an entire mbchar with _rl_read_mbchar and + inserting it in one bunch instead of the loop below (like in + rl_vi_char_search or _rl_vi_change_mbchar_case. Set c to mbchar[0] + for test against 033 or ^C. Make sure that _rl_read_mbchar does + this right. */ +int +rl_vi_change_char (count, key) + int count, key; +{ + int c; + + if (vi_redoing) + c = _rl_vi_last_replacement; + else + { + RL_SETSTATE(RL_STATE_MOREINPUT); + _rl_vi_last_replacement = c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + } + + if (c == '\033' || c == CTRL ('C')) + return -1; + + while (count-- && rl_point < rl_end) + { + rl_begin_undo_group (); + + rl_delete (1, c); +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + while (_rl_insert_char (1, c)) + { + RL_SETSTATE (RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE (RL_STATE_MOREINPUT); + } + else +#endif + _rl_insert_char (1, c); + if (count == 0) + rl_backward_char (1, c); + + rl_end_undo_group (); + } + return (0); +} + +int +rl_vi_subst (count, key) + int count, key; +{ + /* If we are redoing, rl_vi_change_to will stuff the last motion char */ + if (vi_redoing == 0) + rl_stuff_char ((key == 'S') ? 'c' : ' '); /* `S' == `cc', `s' == `c ' */ + + return (rl_vi_change_to (count, 'c')); +} + +int +rl_vi_overstrike (count, key) + int count, key; +{ + if (_rl_vi_doing_insert == 0) + { + _rl_vi_doing_insert = 1; + rl_begin_undo_group (); + } + + if (count > 0) + { + _rl_overwrite_char (count, key); + vi_replace_count += count; + } + + return (0); +} + +int +rl_vi_overstrike_delete (count, key) + int count, key; +{ + int i, s; + + for (i = 0; i < count; i++) + { + if (vi_replace_count == 0) + { + rl_ding (); + break; + } + s = rl_point; + + if (rl_do_undo ()) + vi_replace_count--; + + if (rl_point == s) + rl_backward_char (1, key); + } + + if (vi_replace_count == 0 && _rl_vi_doing_insert) + { + rl_end_undo_group (); + rl_do_undo (); + _rl_vi_doing_insert = 0; + } + return (0); +} + +int +rl_vi_replace (count, key) + int count, key; +{ + int i; + + vi_replace_count = 0; + + if (!vi_replace_map) + { + vi_replace_map = rl_make_bare_keymap (); + + for (i = ' '; i < KEYMAP_SIZE; i++) + vi_replace_map[i].function = rl_vi_overstrike; + + vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; + vi_replace_map[ESC].function = rl_vi_movement_mode; + vi_replace_map[RETURN].function = rl_newline; + vi_replace_map[NEWLINE].function = rl_newline; + + /* If the normal vi insertion keymap has ^H bound to erase, do the + same here. Probably should remove the assignment to RUBOUT up + there, but I don't think it will make a difference in real life. */ + if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && + vi_insertion_keymap[CTRL ('H')].function == rl_rubout) + vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; + + } + _rl_keymap = vi_replace_map; + return (0); +} + +#if 0 +/* Try to complete the word we are standing on or the word that ends with + the previous character. A space matches everything. Word delimiters are + space and ;. */ +int +rl_vi_possible_completions() +{ + int save_pos = rl_point; + + if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') + { + while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && + rl_line_buffer[rl_point] != ';') + rl_point++; + } + else if (rl_line_buffer[rl_point - 1] == ';') + { + rl_ding (); + return (0); + } + + rl_possible_completions (); + rl_point = save_pos; + + return (0); +} +#endif + +/* Functions to save and restore marks. */ +int +rl_vi_set_mark (count, key) + int count, key; +{ + int ch; + + RL_SETSTATE(RL_STATE_MOREINPUT); + ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (ch < 'a' || ch > 'z') + { + rl_ding (); + return -1; + } + ch -= 'a'; + vi_mark_chars[ch] = rl_point; + return 0; +} + +int +rl_vi_goto_mark (count, key) + int count, key; +{ + int ch; + + RL_SETSTATE(RL_STATE_MOREINPUT); + ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (ch == '`') + { + rl_point = rl_mark; + return 0; + } + else if (ch < 'a' || ch > 'z') + { + rl_ding (); + return -1; + } + + ch -= 'a'; + if (vi_mark_chars[ch] == -1) + { + rl_ding (); + return -1; + } + rl_point = vi_mark_chars[ch]; + return 0; +} + +#endif /* VI_MODE */ diff --git a/readline/readline-4.3/xmalloc.c b/readline/readline-4.3/xmalloc.c new file mode 100644 index 00000000..8985d340 --- /dev/null +++ b/readline/readline-4.3/xmalloc.c @@ -0,0 +1,88 @@ +/* xmalloc.c -- safe versions of malloc and realloc */ + +/* Copyright (C) 1991 Free Software Foundation, Inc. + + This file is part of GNU Readline, a library for reading lines + of text with interactive input and history editing. + + Readline is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + Readline is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Readline; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +#include +#endif + +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include "xmalloc.h" + +/* **************************************************************** */ +/* */ +/* Memory Allocation and Deallocation. */ +/* */ +/* **************************************************************** */ + +static void +memory_error_and_abort (fname) + char *fname; +{ + fprintf (stderr, "%s: out of virtual memory\n", fname); + exit (2); +} + +/* Return a pointer to free()able block of memory large enough + to hold BYTES number of bytes. If the memory cannot be allocated, + print an error message and abort. */ +PTR_T +xmalloc (bytes) + size_t bytes; +{ + PTR_T temp; + + temp = malloc (bytes); + if (temp == 0) + memory_error_and_abort ("xmalloc"); + return (temp); +} + +PTR_T +xrealloc (pointer, bytes) + PTR_T pointer; + size_t bytes; +{ + PTR_T temp; + + temp = pointer ? realloc (pointer, bytes) : malloc (bytes); + + if (temp == 0) + memory_error_and_abort ("xrealloc"); + return (temp); +} + +/* Use this as the function to call when adding unwind protects so we + don't need to know what free() returns. */ +void +xfree (string) + PTR_T string; +{ + if (string) + free (string); +} diff --git a/readline/readline-4.3/xmalloc.h b/readline/readline-4.3/xmalloc.h new file mode 100644 index 00000000..9cb08ba2 --- /dev/null +++ b/readline/readline-4.3/xmalloc.h @@ -0,0 +1,46 @@ +/* xmalloc.h -- memory allocation that aborts on errors. */ + +/* Copyright (C) 1999 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_XMALLOC_H_) +#define _XMALLOC_H_ + +#if defined (READLINE_LIBRARY) +# include "rlstdc.h" +#else +# include +#endif + +#ifndef PTR_T + +#ifdef __STDC__ +# define PTR_T void * +#else +# define PTR_T char * +#endif + +#endif /* !PTR_T */ + +extern PTR_T xmalloc PARAMS((size_t)); +extern PTR_T xrealloc PARAMS((void *, size_t)); +extern void xfree PARAMS((void *)); + +#endif /* _XMALLOC_H_ */ diff --git a/resis/Depend b/resis/Depend new file mode 100644 index 00000000..b73eacf7 --- /dev/null +++ b/resis/Depend @@ -0,0 +1,81 @@ +ResMain.o: ResMain.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/tech.h \ + ../textio/txcommands.h ../resis/resis.h +ResJunct.o: ResJunct.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../database/databaseInt.h ../utils/malloc.h \ + ../textio/textio.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../windows/windows.h ../dbwind/dbwind.h \ + ../utils/stack.h ../utils/tech.h ../textio/txcommands.h ../resis/resis.h +ResMakeRes.o: ResMakeRes.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/tech.h \ + ../textio/txcommands.h ../resis/resis.h +ResSimple.o: ResSimple.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/stack.h ../utils/tech.h \ + ../textio/txcommands.h ../resis/resis.h +ResPrint.o: ResPrint.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/utils.h ../cif/cif.h \ + ../utils/tech.h ../textio/txcommands.h ../utils/stack.h \ + ../utils/styles.h ../resis/resis.h +ResReadSim.o: ResReadSim.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/utils.h ../utils/tech.h \ + ../textio/txcommands.h ../resis/resis.h +ResConDCS.o: ResConDCS.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../utils/signals.h ../windows/windows.h ../dbwind/dbwind.h \ + ../utils/tech.h ../textio/txcommands.h ../resis/resis.h +ResRex.o: ResRex.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../utils/undo.h ../database/database.h ../utils/malloc.h \ + ../textio/textio.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../windows/windows.h ../dbwind/dbwind.h \ + ../utils/utils.h ../utils/tech.h ../textio/txcommands.h ../resis/resis.h +ResBasic.o: ResBasic.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/tech.h \ + ../textio/txcommands.h ../resis/resis.h +ResMerge.o: ResMerge.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../resis/resis.h +ResChecks.o: ResChecks.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/utils.h ../utils/tech.h \ + ../textio/txcommands.h ../utils/stack.h ../resis/resis.h +ResFract.o: ResFract.c ../utils/magic.h ../utils/geometry.h \ + ../textio/txcommands.h ../tiles/tile.h ../utils/signals.h \ + ../utils/hash.h ../database/database.h ../database/databaseInt.h \ + ../utils/malloc.h ../windows/windows.h ../utils/main.h +ResUtils.o: ResUtils.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/stack.h ../utils/tech.h \ + ../textio/txcommands.h ../resis/resis.h +ResDebug.o: ResDebug.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/utils.h ../utils/tech.h \ + ../textio/txcommands.h ../utils/stack.h ../resis/resis.h diff --git a/resis/Makefile b/resis/Makefile new file mode 100644 index 00000000..9cba56fd --- /dev/null +++ b/resis/Makefile @@ -0,0 +1,12 @@ +# +# rscid $Header: +# + +MODULE = resis +MAGICDIR = .. +SRCS = ResMain.c ResJunct.c ResMakeRes.c ResSimple.c ResPrint.c \ + ResReadSim.c ResConDCS.c ResRex.c ResBasic.c ResMerge.c ResChecks.c \ + ResFract.c ResUtils.c ResDebug.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/resis/ResBasic.c b/resis/ResBasic.c new file mode 100644 index 00000000..24721e10 --- /dev/null +++ b/resis/ResBasic.c @@ -0,0 +1,386 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResBasic.c,v 1.3 2010/06/24 12:37:56 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "resis/resis.h" + +int resSubTranFunc(); + +/* + *-------------------------------------------------------------------------- + * + * resNodeIsPort -- + * + * If the given position is inside any port declared on the tile, + * change the node name to the port name. Remove the port + * declaration if it was used. + * + *-------------------------------------------------------------------------- + */ + +void +resNodeIsPort(node, x, y, tile) + resNode *node; + int x; + int y; + Tile *tile; +{ + Rect *rect; + Point p; + resPort *pl, *lp; + tileJunk *junk = (tileJunk *)(tile->ti_client); + + p.p_x = x; + p.p_y = y; + + for (pl = junk->portList; pl; pl = pl->rp_nextPort) + { + rect = &(pl->rp_bbox); + if (GEO_ENCLOSE(&p, rect)) + { + node->rn_name = pl->rp_nodename; + if (junk->portList == pl) + junk->portList = pl->rp_nextPort; + else + { + for (lp = junk->portList; lp && (lp->rp_nextPort != pl); + lp = lp->rp_nextPort); + lp->rp_nextPort = pl->rp_nextPort; + } + freeMagic(pl); + break; + } + } +} + +/* + *-------------------------------------------------------------------------- + * + * resAllPortNodes -- + * + * Generate new nodes and breakpoints for every unused port declared + * on a tile. + * + *-------------------------------------------------------------------------- + */ + +void +resAllPortNodes(tile, list) + Tile *tile; + resNode **list; +{ + int x, y; + resNode *resptr; + resPort *pl; + tileJunk *junk = (tileJunk *)(tile->ti_client); + + for (pl = junk->portList; pl; pl = pl->rp_nextPort) + { + x = pl->rp_loc.p_x; + y = pl->rp_loc.p_y; + resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); + InitializeNode(resptr, x, y, RES_NODE_ORIGIN); + resptr->rn_status = TRUE; + resptr->rn_noderes = 0; + resptr->rn_name = pl->rp_nodename; + ResAddToQueue(resptr, list); + NEWBREAK(resptr, tile, x, y, NULL); + freeMagic(pl); + } +} + +/* + *-------------------------------------------------------------------------- + * + * ResEachTile--for each tile, make a list of all possible current sources/ + * sinks including contacts, transistors, and junctions. Once this + * list is made, calculate the resistor nextwork for the tile. + * + * Results: returns TRUE or FALSE depending on whether a node was + * involved in a merge. + * + * Side Effects: creates Nodes, transistors, junctions, and breakpoints. + * + * + *-------------------------------------------------------------------------- + */ + +bool +ResEachTile(tile, startpoint) + Tile *tile; + Point *startpoint; + +{ + Tile *tp; + resNode *resptr; + cElement *ce; + TileType t1, t2; + int xj, yj, i; + bool merged; + tElement *tcell; + tileJunk *tstructs= (tileJunk *)(tile->ti_client); + + ResTileCount++; + + /* Process startpoint, if any. */ + + if (IsSplit(tile)) + { + t1 = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); + } + else + t1 = TiGetTypeExact(tile); + + if (startpoint != (Point *) NULL) + { + int x = startpoint->p_x; + int y = startpoint->p_y; + resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); + InitializeNode(resptr, x, y, RES_NODE_ORIGIN); + resptr->rn_status = TRUE; + resptr->rn_noderes = 0; + ResAddToQueue(resptr, &ResNodeQueue); + NEWBREAK(resptr, tile, x, y, NULL); + resCurrentNode = resptr; + resNodeIsPort(resptr, x, y, tile); + } + + if TTMaskHasType(&(ExtCurStyle->exts_transMask), t1) + { + /* + * The transistor is put in the center of the tile. This is fine + * for single tile transistors, but not as good for multiple ones. + */ + + if (tstructs->tj_status & RES_TILE_TRAN) + { + if (tstructs->transistorList->rt_gate == NULL) + { + int x = (LEFT(tile) + RIGHT(tile)) >> 1; + int y = (TOP(tile) + BOTTOM(tile)) >> 1; + + resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); + tstructs->transistorList->rt_gate = resptr; + tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement))); + tcell->te_thist = tstructs->transistorList; + tcell->te_nextt = NULL; + + InitializeNode(resptr, x, y, RES_NODE_JUNCTION); + resptr->rn_te = tcell; + ResAddToQueue(resptr, &ResNodeQueue); + resNodeIsPort(resptr, x, y, tile); + + NEWBREAK(resptr, tile, resptr->rn_loc.p_x, + resptr->rn_loc.p_y, NULL); + } + } + } + +#ifdef ARIEL + if (i = ExtCurStyle->exts_plugSignalNum[t1]) + { + tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement))); + + tcell->te_thist= ResImageAddPlug(tile, i, resCurrentNode); + tcell->te_nextt = resCurrentNode->rn_te; + resCurrentNode->rn_te = tcell; + } + if (TTMaskHasType(&ResSubsTypeBitMask,t1) && + (ResOptionsFlags & ResOpt_DoSubstrate)) + { + int pNum; + Rect tileArea; + TileTypeBitMask *mask = &ExtCurStyle->exts_subsTransistorTypes[t1]; + + TiToRect(tile,&tileArea); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + if (TTMaskIntersect(&DBPlaneTypes[pNum], mask)) + { + (void)DBSrPaintArea((Tile *) NULL, + ResUse->cu_def->cd_planes[pNum], + &tileArea, mask, resSubTranFunc, (ClientData) tile); + } + } + } +#endif + + /* Process all the contact points */ + ce = tstructs->contactList; + while (ce != (cElement *) NULL) + { + ResContactPoint *cp = ce->ce_thisc; + cElement *oldce; + if (cp->cp_cnode[0] == (resNode *) NULL) + { + ResDoContacts(cp, &ResNodeQueue, &ResResList); + } + oldce = ce; + ce = ce->ce_nextc; + freeMagic((char *)oldce); + } + tstructs->contactList = NULL; + + /* + * Walk the four sides of the tile looking for adjoining connecting + * materials. + */ + + /* left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) + { + t2 = TiGetRightType(tp); + if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && + TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) + /* found transistor */ + { + xj = LEFT(tile); + yj = (TOP(tp) + BOTTOM(tp)) >> 1; + ResNewSDTransistor(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue); + } + if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2) + /* tile is junction */ + { + /*junction rn_loc */ + xj = LEFT(tile); + yj = (MAX(BOTTOM(tile), BOTTOM(tp)) + MIN(TOP(tile), TOP(tp))) >> 1; + (void) ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue); + } + } + + /* right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) + { + t2 = TiGetLeftType(tp); + if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && + TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) + /* found transistor */ + { + xj = RIGHT(tile); + yj = (TOP(tp)+BOTTOM(tp))>>1; + ResNewSDTransistor(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue); + } + if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1], t2) + /* tile is junction */ + { + /*junction rn_loc */ + xj = RIGHT(tile); + yj = (MAX(BOTTOM(tile),BOTTOM(tp)) + MIN(TOP(tile), TOP(tp))) >> 1; + (void)ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue); + } + } + + /* top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) + { + t2 = TiGetBottomType(tp); + if(TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && + TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + /* found transistor */ + { + yj = TOP(tile); + xj = (LEFT(tp)+RIGHT(tp))>>1; + ResNewSDTransistor(tile,tp,xj,yj,BOTTOMEDGE, &ResNodeQueue); + } + if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1],t2) + /* tile is junction */ + { + yj = TOP(tile); + xj = (MAX(LEFT(tile),LEFT(tp)) + MIN(RIGHT(tile),RIGHT(tp))) >> 1; + ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue); + } + } + + /* bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) + { + t2 = TiGetTopType(tp); + if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && + TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) + /* found transistor */ + { + yj = BOTTOM(tile); + xj = (LEFT(tp) + RIGHT(tp)) >> 1; + ResNewSDTransistor(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue); + } + if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2) + /* tile is junction */ + { + yj = BOTTOM(tile); + xj = (MAX(LEFT(tile),LEFT(tp)) + MIN(RIGHT(tile),RIGHT(tp))) >> 1; + ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue); + } + } + tstructs->tj_status |= RES_TILE_DONE; + + resAllPortNodes(tile, &ResNodeQueue); + + merged = ResCalcTileResistance(tile, tstructs, &ResNodeQueue, + &ResNodeList); + + return(merged); +} + +/* + *------------------------------------------------------------------------- + * + * resSubTranFunc -- called when DBSrPaintArea finds a transistor within + * a substrate area. + * + * Results: always returns 0 to keep search going. + * + * Side Effects: allocates substrate node. + * + *------------------------------------------------------------------------- + */ + +int +resSubTranFunc(tile,tp) + Tile *tile,*tp; + + +{ + tileJunk *junk = (tileJunk *)(tile->ti_client); + resNode *resptr; + tElement *tcell; + int x,y; + + if (junk->transistorList->rt_subs== NULL) + { + resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); + junk->transistorList->rt_subs = resptr; + junk->tj_status |= RES_TILE_TRAN; + tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement))); + tcell->te_thist = junk->transistorList; + tcell->te_nextt = NULL; + x = (LEFT(tile)+RIGHT(tile))>>1; + y = (TOP(tile)+BOTTOM(tile))>>1; + + InitializeNode(resptr,x,y,RES_NODE_JUNCTION); + resptr->rn_te = tcell; + ResAddToQueue(resptr,&ResNodeQueue); + + NEWBREAK(resptr,tp,x,y,NULL); + } + return 0; +} diff --git a/resis/ResChecks.c b/resis/ResChecks.c new file mode 100644 index 00000000..458f32ed --- /dev/null +++ b/resis/ResChecks.c @@ -0,0 +1,153 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResChecks.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/utils.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "utils/stack.h" +#include "resis/resis.h" + +#ifdef PARANOID + +/* + *------------------------------------------------------------------------- + * + * ResSanityChecks -- Checks that resistor and node lists are consistant. + * Make sure that all resistors are connected, and that each node + * to which a resistor is connected has the correct pointer in its list. + * + * Results: none + * + * Side Effects: prints out error messages if it finds something bogus. + * + *------------------------------------------------------------------------- + */ + +void +ResSanityChecks(nodename,resistorList,nodeList,tranlist) + char *nodename; + resResistor *resistorList; + resNode *nodeList; + resTransistor *tranlist; + +{ + resResistor *resistor; + resNode *node; + resTransistor *tran; + resElement *rcell; + static Stack *resSanityStack = NULL; + int reached,foundorigin; + + if (resSanityStack == NULL) + { + resSanityStack = StackNew(64); + } + for (node = nodeList; node != NULL; node=node->rn_more) + { + node->rn_status &= ~RES_REACHED_NODE; + if (node->rn_why == RES_NODE_ORIGIN) + STACKPUSH((ClientData) node, resSanityStack); + } + for (resistor = resistorList; resistor != NULL; resistor = resistor->rr_nextResistor) + { + resistor->rr_status &= ~RES_REACHED_RESISTOR; + } + + /* Check 1- Are the resistors and nodes all connected? */ + while (!StackEmpty(resSanityStack)) + { + node = (resNode *)STACKPOP(resSanityStack); + if (node->rn_status & RES_REACHED_NODE) continue; + node->rn_status |= RES_REACHED_NODE; + for (rcell = node->rn_re; rcell != NULL; rcell=rcell->re_nextEl) + { + resistor = rcell->re_thisEl; + if (resistor->rr_status & RES_REACHED_RESISTOR) continue; + resistor->rr_status |= RES_REACHED_RESISTOR; + if (resistor->rr_connection1 != node && + resistor->rr_connection2 != node) + { + TxError("Stray resElement pointer- node %s, pointer %d\n",nodename,rcell); + continue; + } + if ((resistor->rr_connection1->rn_status & RES_REACHED_NODE) == 0) + { + STACKPUSH((ClientData)resistor->rr_connection1,resSanityStack); + } + if ((resistor->rr_connection2->rn_status & RES_REACHED_NODE) == 0) + { + STACKPUSH((ClientData)resistor->rr_connection2,resSanityStack); + } + } + } + for (resistor = resistorList; resistor != NULL; resistor = resistor->rr_nextResistor) + { + if ((resistor->rr_status & RES_REACHED_RESISTOR) == 0) + { + TxError("Unreached resistor in %s\n",nodename); + } + resistor->rr_status &= ~RES_REACHED_RESISTOR; + } + for (tran = tranlist; tran != NULL; tran = tran->rt_nextTran) + { + int i; + + if (tran->rt_status & RES_TRAN_PLUG) continue; + reached = FALSE; + for (i=0;i != RT_TERMCOUNT;i++) + { + if (tran->rt_terminals[i] != NULL) + { + reached = TRUE; + if ((tran->rt_terminals[i]->rn_status & RES_REACHED_NODE) == 0) + { + TxError("Transistor node %d unreached in %s\n",i,nodename); + } + } + } + if (reached == 0) + { + TxError("Unreached transistor in %s at %d %d\n", + nodename, + tran->rt_inside.r_xbot, + tran->rt_inside.r_ybot); + } + } + foundorigin = 0; + for (node = nodeList; node != NULL; node=node->rn_more) + { + if ((node->rn_status & RES_REACHED_NODE) == 0) + { + TxError("Unreached node in %s at %d, %d\n",nodename,node->rn_loc.p_x,node->rn_loc.p_y); + } + node->rn_status &= ~RES_REACHED_NODE; + if (node->rn_why & RES_NODE_ORIGIN) + { + foundorigin = 1; + } + } + if (foundorigin == 0) + { + TxError("Starting node not found in %s\n",nodename); + } +} +#endif diff --git a/resis/ResConDCS.c b/resis/ResConDCS.c new file mode 100644 index 00000000..aea2ab4a --- /dev/null +++ b/resis/ResConDCS.c @@ -0,0 +1,540 @@ +/* ResConnectDCS.c -- + * + * This contains a slightly modified version of DBTreeCopyConnect. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResConDCS.c,v 1.5 2010/06/24 12:37:56 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "resis/resis.h" + +typedef struct +{ + Rect area; /* Area to process */ + TileTypeBitMask *connectMask; /* Connection mask for search */ + TileType dinfo; /* Info about triangular search areas */ +} conSrArea; + +struct conSrArg2 +{ + CellUse *csa2_use; /* Destination use */ + TileTypeBitMask *csa2_connect; /* Table indicating what connects + * to what. + */ + SearchContext *csa2_topscx; /* Original top-level search context */ + int csa2_xMask; /* Cell window mask for search */ + Rect *csa2_bounds; /* Area that limits the search */ + + conSrArea *csa2_list; /* List of areas to process */ + int csa2_top; /* Index of next area to process */ + int csa2_size; /* Max. number bins in area list */ +}; + +#define CSA2_LIST_START_SIZE 256 + +extern int dbcUnconnectFunc(); +extern int dbcConnectLabelFunc(); +extern int dbcConnectFuncDCS(); +#ifdef ARIEL +extern int resSubSearchFunc(); +#endif + +static ResTranTile *TransList = NULL; +static TileTypeBitMask DiffTypeBitMask; +TileTypeBitMask ResSubsTypeBitMask; + +/* Forward declarations */ +extern void ResCalcPerimOverlap(); + + +/* + * ---------------------------------------------------------------------------- + * + * dbcConnectFuncDCS -- the same as dbcConnectFunc, except that it does + * some extra searching around diffusion tiles looking for + * transistors. + * + * Results: + * Always returns 0 to keep the search from aborting. + * + * Side effects: + * Adds a new record to the current check list. May also add new + * ResTranTile structures. + * + * ---------------------------------------------------------------------------- + */ + +int +dbcConnectFuncDCS(tile, cx) + Tile *tile; + TreeContext *cx; + +{ + struct conSrArg2 *csa2; + Rect tileArea, *srArea, tranArea, newarea; + ResTranTile *thisTran; + TileTypeBitMask notConnectMask, *connectMask; + Tile *tp; + TileType t2, t1, loctype, ctype; + TileType dinfo = 0; + SearchContext *scx = cx->tc_scx; + SearchContext scx2; + int pNum; + CellDef *def; + + TiToRect(tile, &tileArea); + srArea = &scx->scx_area; + + if (((tileArea.r_xbot >= srArea->r_xtop-1) || + (tileArea.r_xtop <= srArea->r_xbot+1)) && + ((tileArea.r_ybot >= srArea->r_ytop-1) || + (tileArea.r_ytop <= srArea->r_ybot+1))) + return 0; + + + + t1 = TiGetType(tile); + if TTMaskHasType(&DiffTypeBitMask,t1) + { + /* left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) + { + t2 = TiGetType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && + TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + { + TiToRect(tp, &tranArea); + thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); + ResCalcPerimOverlap(thisTran,tp); + GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); + thisTran->type = TiGetType(tp); + thisTran->nextTran = TransList; + TransList = thisTran; + } + } + /*right*/ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) + { + t2 = TiGetType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && + TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + { + TiToRect(tp, &tranArea); + thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); + GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); + thisTran->type = TiGetType(tp); + thisTran->nextTran = TransList; + TransList = thisTran; + ResCalcPerimOverlap(thisTran,tp); + } + } + /*top*/ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) + { + t2 = TiGetType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && + TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + { + TiToRect(tp, &tranArea); + thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); + GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); + thisTran->type = TiGetType(tp); + thisTran->nextTran = TransList; + TransList = thisTran; + ResCalcPerimOverlap(thisTran,tp); + } + } + /*bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) + { + t2 = TiGetType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && + TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + { + TiToRect(tp, &tranArea); + thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); + GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); + thisTran->type = TiGetType(tp); + thisTran->nextTran = TransList; + TransList = thisTran; + ResCalcPerimOverlap(thisTran,tp); + } + } + } + else if TTMaskHasType(&(ExtCurStyle->exts_transMask),t1) + { + TiToRect(tile, &tranArea); + thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); + ResCalcPerimOverlap(thisTran,tile); + GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); + thisTran->type = TiGetType(tile); + thisTran->nextTran = TransList; + TransList = thisTran; + } + /* in some cases (primarily bipolar technology), we'll want to extract + transistors whose substrate terminals are part of the given region. + The following does that check. (10-11-88) + */ +#ifdef ARIEL + if (TTMaskHasType(&ResSubsTypeBitMask,t1) && (ResOptionsFlags & ResOpt_DoSubstrate)) + { + TileTypeBitMask *mask = &ExtCurStyle->exts_subsTransistorTypes[t1]; + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + if (TTMaskIntersect(&DBPlaneTypes[pNum], mask)) + { + (void)DBSrPaintArea((Tile *) NULL, + scx->scx_use->cu_def->cd_planes[pNum], + &tileArea,mask,resSubSearchFunc, (ClientData) cx); + } + } + } +#endif + GeoTransRect(&scx->scx_trans, &tileArea, &newarea); + + csa2 = (struct conSrArg2 *)cx->tc_filter->tf_arg; + GeoClip(&newarea, csa2->csa2_bounds); + if (GEO_RECTNULL(&newarea)) return 0; + + loctype = TiGetTypeExact(tile); + + /* Resolve geometric transformations on diagonally-split tiles */ + + if (IsSplit(tile)) + { + dinfo = DBTransformDiagonal(loctype, &scx->scx_trans); + loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); + } + + pNum = cx->tc_plane; + connectMask = &csa2->csa2_connect[loctype]; + + if (DBIsContact(loctype)) + { + /* The mask of contact types must include all stacked contacts */ + + TTMaskZero(¬ConnectMask); + TTMaskSetMask(¬ConnectMask, &DBNotConnectTbl[loctype]); + } + else + { + TTMaskCom2(¬ConnectMask, connectMask); + } + + def = csa2->csa2_use->cu_def; + + if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum], + dinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc, + (ClientData)NULL) == 0) + return 0; + + DBNMPaintPlane(def->cd_planes[pNum], dinfo, + &newarea, DBStdPaintTbl(loctype, pNum), + (PaintUndoInfo *) NULL); + + /* Check the source def for any labels belonging to this */ + /* tile area and plane, and add them to the destination */ + + scx2 = *csa2->csa2_topscx; + scx2.scx_area = newarea; + DBTreeSrLabels(&scx2, connectMask, csa2->csa2_xMask, NULL, + TF_LABEL_ATTACH, dbcConnectLabelFunc, + (ClientData)csa2); + // DBCellCopyLabels(&scx2, connectMask, csa2->csa2_xMask, csa2->csa2_use, NULL); + + /* Only extend those sides bordering the diagonal tile */ + + if (dinfo & TT_DIAGONAL) + { + if (dinfo & TT_SIDE) /* right */ + newarea.r_xtop += 1; + else /* left */ + newarea.r_xbot -= 1; + if (((dinfo & TT_SIDE) >> 1) + == (dinfo & TT_DIRECTION)) /* top */ + newarea.r_ytop += 1; + else /* bottom */ + newarea.r_ybot -= 1; + } + else + { + newarea.r_xbot -= 1; + newarea.r_ybot -= 1; + newarea.r_xtop += 1; + newarea.r_ytop += 1; + } + + /* Register the area and connection mask as needing to be processed */ + + if (++csa2->csa2_top == csa2->csa2_size) + { + /* Reached list size limit---need to enlarge the list */ + /* Double the size of the list every time we hit the limit */ + + conSrArea *newlist; + int i, lastsize = csa2->csa2_size; + + csa2->csa2_size *= 2; + + newlist = (conSrArea *)mallocMagic(csa2->csa2_size * sizeof(conSrArea)); + memcpy((void *)newlist, (void *)csa2->csa2_list, + (size_t)lastsize * sizeof(conSrArea)); + // for (i = 0; i < lastsize; i++) + // { + // newlist[i].area = csa2->csa2_list[i].area; + // newlist[i].connectMask = csa2->csa2_list[i].connectMask; + // newlist[i].dinfo = csa2->csa2_list[i].dinfo; + // } + freeMagic((char *)csa2->csa2_list); + csa2->csa2_list = newlist; + } + + csa2->csa2_list[csa2->csa2_top].area = newarea; + csa2->csa2_list[csa2->csa2_top].connectMask = connectMask; + csa2->csa2_list[csa2->csa2_top].dinfo = dinfo; + + return 0; +} + + +/* + *------------------------------------------------------------------------- + * + * ResCalcPerimOverlap-- + * + * Results: + * None. + * + * Side Effects: + * + *------------------------------------------------------------------------- + */ + +void +ResCalcPerimOverlap(trans, tile) + ResTranTile *trans; + Tile *tile; + +{ + Tile *tp; + int t1; + int overlap; + + trans->perim = (TOP(tile)-BOTTOM(tile)-LEFT(tile)+RIGHT(tile))<<1; + overlap =0; + + t1 = TiGetType(tile); + /* left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) + { + if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]),TiGetType(tp)) + { + overlap += MIN(TOP(tile),TOP(tp))- + MAX(BOTTOM(tile),BOTTOM(tp)); + } + + } + /*right*/ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) + { + if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]),TiGetType(tp)) + { + overlap += MIN(TOP(tile),TOP(tp))- + MAX(BOTTOM(tile),BOTTOM(tp)); + } + + } + /*top*/ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) + { + if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]),TiGetType(tp)) + { + overlap += MIN(RIGHT(tile),RIGHT(tp))- + MAX(LEFT(tile),LEFT(tp)); + } + + } + /*bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) + { + if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]),TiGetType(tp)) + { + overlap += MIN(RIGHT(tile),RIGHT(tp))- + MAX(LEFT(tile),LEFT(tp)); + } + + } + trans->overlap = overlap; +} + + +/* + * ---------------------------------------------------------------------------- + * + * DBTreeCopyConnectDCS -- + * + * Basically the same as DBTreeCopyConnect, except it calls + * dbcConnectFuncDCS. + * + * Results: + * Linked list of transistors. + * + * Side effects: + * The contents of the result cell are modified. + * + * ---------------------------------------------------------------------------- + */ + +ResTranTile * +DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) + SearchContext *scx; + TileTypeBitMask *mask; + int xMask; + TileTypeBitMask *connect; + Rect *area; + CellUse *destUse; + +{ + static int first = 1; + struct conSrArg2 csa2; + int tran, pNum; + char *tran_name; + TileTypeBitMask *newmask; + ResTranTile *CurrentT; + CellDef *def = destUse->cu_def; + TileType newtype; + + csa2.csa2_use = destUse; + csa2.csa2_xMask = xMask; + csa2.csa2_bounds = area; + csa2.csa2_connect = connect; + csa2.csa2_topscx = scx; + + csa2.csa2_size = CSA2_LIST_START_SIZE; + csa2.csa2_list = (conSrArea *)mallocMagic(CSA2_LIST_START_SIZE + * sizeof(conSrArea)); + csa2.csa2_top = -1; + + if (first) + { + TTMaskZero(&DiffTypeBitMask); + TTMaskZero(&ResSubsTypeBitMask); + for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) + { + tran_name = (ExtCurStyle->exts_transName)[tran]; + if ((tran_name != NULL) && (strcmp(tran_name, "None"))) + { + TTMaskSetMask(&DiffTypeBitMask, + &(ExtCurStyle->exts_transSDTypes[tran][0])); + TTMaskSetMask(&ResSubsTypeBitMask, + &(ExtCurStyle->exts_transSubstrateTypes[tran])); + } + } + first = 0; + } + + TransList = NULL; + DBTreeSrTiles(scx, mask, xMask, dbcConnectFuncDCS, (ClientData) &csa2); + while (csa2.csa2_top >= 0) + { + newmask = csa2.csa2_list[csa2.csa2_top].connectMask; + scx->scx_area = csa2.csa2_list[csa2.csa2_top].area; + newtype = csa2.csa2_list[csa2.csa2_top].dinfo; + csa2.csa2_top--; + if (newtype & TT_DIAGONAL) + DBTreeSrNMTiles(scx, newtype, newmask, xMask, dbcConnectFuncDCS, + (ClientData) &csa2); + else + DBTreeSrTiles(scx, newmask, xMask, dbcConnectFuncDCS, (ClientData) &csa2); + } + freeMagic((char *)csa2.csa2_list); + + for (CurrentT = TransList; CurrentT != NULL; CurrentT=CurrentT->nextTran) + { + TileType t = CurrentT->type; + TileType nt; + TileTypeBitMask *residues = DBResidueMask(t); + + for (nt = TT_TECHDEPBASE; nt < DBNumTypes; nt++) + { + if (TTMaskHasType(residues, nt)) + { + pNum = DBPlane(nt); + DBPaintPlane(def->cd_planes[pNum], &CurrentT->area, + DBStdPaintTbl(nt, pNum), (PaintUndoInfo *) NULL); + } + } + } + + DBReComputeBbox(def); + return(TransList); +} + + +#ifdef ARIEL +/* + *------------------------------------------------------------------------- + * + * resSubSearchFunc -- + * + * called when DBSrPaintArea finds a transistor within + * a substrate area. + * + * Results: + * Always return 0 to keep the search alive. + * + * Side Effects: + * + *------------------------------------------------------------------------- + */ + +int +resSubSearchFunc(tile,cx) + Tile *tile; + TreeContext *cx; + + +{ + ResTranTile *thisTran; + Rect tranArea; + TileType t = TiGetType(tile); + + /* Right now, we're only going to extract substrate terminals for + devices with only one diffusion terminal, principally bipolar + devices. + */ + if (ExtCurStyle->exts_transSDCount[t] >1) return 0; + TiToRect(tile, &tranArea); + thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); + GeoTransRect(&cx->tc_scx->scx_trans, &tranArea, &thisTran->area); + thisTran->type = t; + thisTran->nextTran = TransList; + TransList = thisTran; + ResCalcPerimOverlap(thisTran,tile); + + return 0; +} + +#endif /* ARIEL */ diff --git a/resis/ResDebug.c b/resis/ResDebug.c new file mode 100644 index 00000000..4a6a4682 --- /dev/null +++ b/resis/ResDebug.c @@ -0,0 +1,147 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResDebug.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/utils.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "utils/stack.h" +#include "resis/resis.h" + +#define MAXNAME 1000 +#define KV_TO_mV 1000000 + + +/* + *------------------------------------------------------------------------- + * + * ResPrintNodeList-- Prints out all the nodes in nodelist. + * + * + * Results: + * None. + * + * Side effects: + * prints out the 'nodes' in list to fp. + * + *------------------------------------------------------------------------- + */ + +void +ResPrintNodeList(fp,list) + FILE *fp; + resNode *list; + +{ + + for (; list != NULL; list = list->rn_more) + { + fprintf(fp, "node %p: (%d %d) r= %d\n", + list,list->rn_loc.p_x,list->rn_loc.p_y,list->rn_noderes); + } +} + +/* + *------------------------------------------------------------------------- + * + * ResPrintResistorList-- + * + * + * results: none + * + * + * side effects: prints out Resistors in list to file fp. + * + *------------------------------------------------------------------------- + */ +void +ResPrintResistorList(fp,list) + FILE *fp; + resResistor *list; + +{ + for (; list != NULL; list = list->rr_nextResistor) + { + if (fp == stdout) + TxPrintf("r (%d,%d) (%d,%d) r=%d\n", + list->rr_connection1->rn_loc.p_x, + list->rr_connection1->rn_loc.p_y, + list->rr_connection2->rn_loc.p_x, + list->rr_connection2->rn_loc.p_y, + list->rr_value); + else + fprintf(fp, "r (%d,%d) (%d,%d) r=%d\n", + list->rr_connection1->rn_loc.p_x, + list->rr_connection1->rn_loc.p_y, + list->rr_connection2->rn_loc.p_x, + list->rr_connection2->rn_loc.p_y, + list->rr_value); + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResPrintTransistorList-- + * + * + * Results: none + * + * Side effects: prints out transistors in list to file fp. + * + *------------------------------------------------------------------------- + */ + +void +ResPrintTransistorList(fp,list) + FILE *fp; + resTransistor *list; + +{ + static char termtype[] = {'g','s','d','c'}; + int i; + for (; list != NULL; list = list->rt_nextTran) + { + if (list->rt_status & RES_TRAN_PLUG) continue; + if (fp == stdout) + TxPrintf("t w %d l %d ", list->rt_width, list->rt_length); + else + fprintf(fp, "t w %d l %d ", list->rt_width, list->rt_length); + for (i=0; i!= RT_TERMCOUNT;i++) + { + if (list->rt_terminals[i] == NULL) continue; + if (fp == stdout) + TxPrintf("%c (%d,%d) ",termtype[i], + list->rt_terminals[i]->rn_loc.p_x, + list->rt_terminals[i]->rn_loc.p_y); + else + fprintf(fp, "%c (%d,%d) ",termtype[i], + list->rt_terminals[i]->rn_loc.p_x, + list->rt_terminals[i]->rn_loc.p_y); + + } + if (fp == stdout) + TxPrintf("\n"); + else + fprintf(fp,"\n"); + } +} diff --git a/resis/ResFract.c b/resis/ResFract.c new file mode 100644 index 00000000..09a42a45 --- /dev/null +++ b/resis/ResFract.c @@ -0,0 +1,477 @@ +/* + * ResFract.c + * + * routines to convert a maximum horizontal rectangles database + * into one fractured in the manner of Horowitz's '83 Transactions + * on CAD paper. + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResFract.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "textio/txcommands.h" +#include "tiles/tile.h" +#include "utils/signals.h" +#include "utils/hash.h" +#include "database/database.h" +#include "database/databaseInt.h" +#include "utils/malloc.h" +#include "windows/windows.h" +#include "utils/main.h" + +extern Tile *ResSplitX(); + + +Tile *resSrTile; +Tile *resTopTile; +Plane *resFracPlane; + +/* Forward declarations */ + +extern void ResCheckConcavity(); + + +/* + * -------------------------------------------------------------------- + * + * ResFracture -- Convert a maxiumum horizontal strips cell def into + * one where the split at each concave corner is in the direction + * with the least material of the same tiletype. This is done + * using TiSplitX and TiJoinY. Joins are only done on tiles with + * the same time; this implies that contacts should first be erased + * using ResDissolve contacts. + * + * We can't use DBSrPaintArea because the fracturing + * routines modify the database. This is essentially the same routine + * except that has to be careful that it doesn't merge away the + * current tile in the search. + * + * + * -------------------------------------------------------------------- + */ + +int +ResFracture(plane, rect) + Plane *plane; + Rect *rect; +{ + Point start; + Tile *tpnew; + TileType tt; + + resFracPlane = plane; + + start.p_x = rect->r_xbot; + start.p_y = rect->r_ytop - 1; + resSrTile = plane->pl_hint; + GOTOPOINT(resSrTile, &start); + + /* Each iteration visits another tile on the LHS of the search area */ + while (TOP(resSrTile) > rect->r_ybot) + { + /* Each iteration enumerates another tile */ +enumerate: + plane->pl_hint = resSrTile; + if (SigInterruptPending) + return (1); + + if ((tt=TiGetType(resSrTile)) != TT_SPACE) + { + resTopTile = RT(resSrTile); + while (RIGHT(resTopTile) > LEFT(resSrTile)) + { + TileType ntt = TiGetType(resTopTile); + + if (ntt != tt) + { + resTopTile=BL(resTopTile); + continue; + } + /* ok, we may have found a concave corner */ + ResCheckConcavity(resSrTile,resTopTile,tt); + if (resTopTile == NULL) break; + if (BOTTOM(resTopTile) != TOP(resSrTile)) + { + resTopTile = RT(resSrTile); + } + else + { + resTopTile=BL(resTopTile); + } + } + + } + + tpnew = TR(resSrTile); + if (LEFT(tpnew) < rect->r_xtop) + { + while (BOTTOM(tpnew) >= rect->r_ytop) tpnew = LB(tpnew); + if (BOTTOM(tpnew) >= BOTTOM(resSrTile) || BOTTOM(resSrTile) <= rect->r_ybot) + { + resSrTile = tpnew; + goto enumerate; + } + } + + /* Each iteration returns one tile further to the left */ + while (LEFT(resSrTile) > rect->r_xbot) + { + if (BOTTOM(resSrTile) <= rect->r_ybot) + return (0); + tpnew = LB(resSrTile); + resSrTile = BL(resSrTile); + if (BOTTOM(tpnew) >= BOTTOM(resSrTile) || BOTTOM(resSrTile) <= rect->r_ybot) + { + resSrTile = tpnew; + goto enumerate; + } + } + + /* At left edge -- walk down to next tile along the left edge */ + for (resSrTile = LB(resSrTile); RIGHT(resSrTile) <= rect->r_xbot; resSrTile = TR(resSrTile)) + /* Nothing */; + } + return (0); +} + +/* + *------------------------------------------------------------------------- + * + * ResCheckConcavity -- Called when two tiles of the same type are found. + * These tiles can form concave edges 4 different ways; check for + * each such case. When one is found, call the resWalk routines to + * decide whether any tiles need to be split. + * + * Results: none. + * + * Side Effects: may change the plane on which it acts. Can also modify + * the global variable resTopTile. + * + *------------------------------------------------------------------------- + */ + +void +ResCheckConcavity(bot,top,tt) + Tile *bot,*top; + TileType tt; + +{ + Tile *tp; + int xlen,ylen; + /* corner #1: + XXXXXXX + YYYYYYY + ^--here + */ + if (RIGHT(top) > RIGHT(bot) && TiGetType(TR(bot)) != tt) + { + int xpos = RIGHT(bot); + int ypos = BOTTOM(top); + xlen = xpos - resWalkleft(top,tt,xpos,ypos,NULL); + ylen = resWalkup(top,tt,xpos,ypos,NULL) - ypos; + if (xlen > ylen) + { + (void) resWalkup(top,tt,xpos,ypos,ResSplitX); + } + } + if (resTopTile == NULL) return; + /* corner #2: + v--here + XXXXXXX + YYYYYYY + */ + if (RIGHT(top) < RIGHT(bot)) + { + for (tp = TR(top);BOTTOM(tp) > BOTTOM(top);tp=LB(tp)); + if (TiGetType(tp) != tt) + { + int xpos = RIGHT(top); + int ypos = BOTTOM(top); + xlen = xpos-resWalkleft(top,tt,xpos,ypos,NULL); + ylen = ypos-resWalkdown(bot,tt,xpos,ypos,NULL); + if (xlen > ylen) + { + (void) resWalkdown(bot,tt,xpos,ypos,ResSplitX); + } + } + } + if (resTopTile == NULL) return; + /* corner #3: + XXXXXXX + YYYYYYY + ^--here + */ + if (LEFT(top) < LEFT(bot)) + { + for (tp = BL(bot);TOP(tp) < TOP(bot);tp=RT(tp)); + if (TiGetType(tp) != tt) + { + int xpos = LEFT(bot); + int ypos = BOTTOM(top); + xlen = resWalkright(top,tt,xpos,ypos,NULL)- xpos; + ylen = resWalkup(top,tt,xpos,ypos,NULL) - ypos; + if (xlen > ylen) + { + (void) resWalkup(top,tt,xpos,ypos,ResSplitX); + } + } + } + if (resTopTile == NULL) return; + /* corner #4: + v--here + XXXXXXX + YYYYYYY + */ + if (LEFT(top) > LEFT(bot) && TiGetType(BL(top)) != tt) + { + int xpos = LEFT(top); + int ypos = BOTTOM(top); + xlen = resWalkright(top,tt,xpos,ypos,NULL)- xpos; + ylen = ypos-resWalkdown(bot,tt,xpos,ypos,NULL); + if (xlen > ylen) + { + (void) resWalkdown(bot,tt,xpos,ypos,ResSplitX); + } + } +} + +/* + *------------------------------------------------------------------------- + * + * resWalk{up,down,left,right} -- move in the specified direction looking + * for tiles of a given type. + * + * Results: returns the coordinate that is the farthest point in the specified + * direction that one can walk and still be surrounded by material of + * a given type. + * + * Side Effects: if func is non-NULL, it is called on each tile intersected + * by the path. (Note that if the path moves along the edge of a tile, + * func is not called.) + * + *------------------------------------------------------------------------- + */ + +int +resWalkup(tile,tt,xpos,ypos,func) + Tile *tile; + TileType tt; + int xpos,ypos; + Tile * (*func)(); + +{ + Point pt; + Tile *tp; + + pt.p_x = xpos; + while (TiGetType(tile) == tt) + { + if (xpos == LEFT(tile)) + { + /* walk up left edge */ + for (tp = BL(tile);TOP(tp) <= ypos;tp=RT(tp)); + for (;BOTTOM(tp) < TOP(tile);tp=RT(tp)) + { + if (TiGetType(tp) != tt) return(BOTTOM(tp)); + } + } + else + { + if (func) tile = (*func)(tile,xpos); + } + pt.p_y = TOP(tile); + GOTOPOINT(tile,&pt); + } + return(BOTTOM(tile)); +} + +int +resWalkdown(tile,tt,xpos,ypos,func) + Tile *tile; + TileType tt; + int xpos,ypos; + Tile * (*func)(); + +{ + Point pt; + Tile *tp; + Tile *endt; + + pt.p_x = xpos; + while (TiGetType(tile) == tt) + { + if (xpos == LEFT(tile)) + { + /* walk up left edge */ + endt = NULL; + for (tp = BL(tile);BOTTOM(tp) < TOP(tile);tp=RT(tp)) + { + if (TiGetType(tp) != tt) + { + if (BOTTOM(tp) < ypos) endt = tp; + } + } + if (endt) + { + return TOP(endt); + } + } + else + { + if (func) tile = (*func)(tile,xpos); + } + pt.p_y = BOTTOM(tile)-1; + GOTOPOINT(tile,&pt); + } + return(TOP(tile)); +} + +int +resWalkright(tile,tt,xpos,ypos,func) + Tile *tile; + TileType tt; + int xpos,ypos; + Tile * (*func)(); + +{ + Point pt; + Tile *tp; + + pt.p_y = ypos; + while (TiGetType(tile) == tt) + { + if (ypos == BOTTOM(tile)) + { + /* walk along bottom edge */ + for (tp = LB(tile);LEFT(tp) < xpos;tp=TR(tp)); + for (;LEFT(tp) < RIGHT(tile);tp=TR(tp)) + { + if (TiGetType(tp) != tt) return(LEFT(tp)); + } + } + else + { + if (func) tile = (*func)(tile,ypos); + } + pt.p_x = RIGHT(tile); + GOTOPOINT(tile,&pt); + } + return(LEFT(tile)); +} + +int +resWalkleft(tile,tt,xpos,ypos,func) + Tile *tile; + TileType tt; + int xpos,ypos; + Tile * (*func)(); + +{ + Point pt; + Tile *tp; + Tile *endt; + + pt.p_y = ypos; + while (TiGetType(tile) == tt) + { + if (ypos == BOTTOM(tile)) + { + /* walk along bottom edge */ + endt = NULL; + for (tp = LB(tile);LEFT(tp) < RIGHT(tile);tp=TR(tp)) + { + if (TiGetType(tp) != tt) + { + if (LEFT(tp) < xpos) endt = tp; + } + } + if (endt) + { + return RIGHT(endt); + } + } + else + { + if (func) tile = (*func)(tile,ypos); + } + pt.p_x = LEFT(tile)-1; + GOTOPOINT(tile,&pt); + } + return(RIGHT(tile)); +} + +/* + *------------------------------------------------------------------------- + * + * ResSplitX -- calls TiSplitX, sets the tiletype, + * then tries to join tiles that share a common long edge. + * + * Results: returns new tile if tile was destroyed by a Join function. + * + * Side Effects: modifies the tile plane and the global variables + * resSrTile and resTopTile. + * + *------------------------------------------------------------------------- + */ +Tile * +ResSplitX(tile,x) + Tile *tile; + int x; + +{ + TileType tt = TiGetType(tile); + Tile *tp = TiSplitX(tile,x); + Tile *tp2; + + TiSetBody(tp,tt); + /* check to see if we can combine with the tiles above or below us */ + tp2 = RT(tile); + if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tile) && RIGHT(tp2) == RIGHT(tile)) + { + if (tp2 == resSrTile) + { + if (resTopTile == tile) resTopTile = NULL; + TiJoinY(tp2,tile,resFracPlane); + tile = tp2; + } + else + { + if (resTopTile == tp2) resTopTile = NULL; + TiJoinY(tile,tp2,resFracPlane); + } + } + tp2 = LB(tile); + if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tile) && RIGHT(tp2) == RIGHT(tile)) + { + if (tp2 == resSrTile) + { + if (resTopTile == tile) resTopTile = NULL; + TiJoinY(tp2,tile,resFracPlane); + tile = tp2; + } + else + { + if (resTopTile == tp2) resTopTile = NULL; + TiJoinY(tile,tp2,resFracPlane); + } + } + /* do the same checks with the newly created tile */ + tp2 = RT(tp); + if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tp) && RIGHT(tp2) == RIGHT(tp)) + { + TiJoinY(tp2,tp,resFracPlane); + tp = tp2; + } + tp2 = LB(tp); + if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tp) && RIGHT(tp2) == RIGHT(tp)) + { + TiJoinY(tp2,tp,resFracPlane); + } + return tile; +} diff --git a/resis/ResJunct.c b/resis/ResJunct.c new file mode 100644 index 00000000..97034eec --- /dev/null +++ b/resis/ResJunct.c @@ -0,0 +1,162 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResJunct.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "database/databaseInt.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/stack.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "resis/resis.h" + + + +/* + *------------------------------------------------------------------------- + * + * ResNewSDTransistor-- called when a transistor is reached via a piece of + * diffusion. (Transistors reached via poly, i.e. + * gates, are handled by ResEachTile.) + * + * Results:none + * + * Side Effects: determines to which terminal (source or drain) node + * is connected. Makes new node if node hasn't already been created . + * Allocates breakpoint in current tile for transistor. + * + *------------------------------------------------------------------------- + */ + +void +ResNewSDTransistor(tile,tp,xj,yj,direction,PendingList) + Tile *tile,*tp; + int xj,yj,direction; + resNode **PendingList; +{ + resNode *resptr; + resTransistor *resFet; + tElement *tcell; + int newnode; + tileJunk *j; + + newnode = FALSE; + j = (tileJunk *) tp->ti_client; + resFet = j->transistorList; + if ((j->sourceEdge & direction) != 0) + { + if (resFet->rt_source == (resNode *) NULL) + { + resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); + newnode = TRUE; + resFet->rt_source = resptr; + } + else + { + resptr = resFet->rt_source; + } + } + else + { + if (resFet->rt_drain == (resNode *) NULL) + { + resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); + newnode = TRUE; + resFet->rt_drain = resptr; + } + else + { + resptr = resFet->rt_drain; + } + } + if (newnode) + { + tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement))); + tcell->te_nextt = NULL; + tcell->te_thist = j->transistorList; + InitializeNode(resptr,xj,yj,RES_NODE_TRANSISTOR); + resptr->rn_te = tcell; + ResAddToQueue(resptr,PendingList); + } + NEWBREAK(resptr,tile,xj,yj,NULL); +} + +/* + *------------------------------------------------------------------------- + * + * ResProcessJunction-- Called whenever a tile connecting to the tile being + * worked on is found. If a junction is already present, its address is + * returned. Otherwise, a new junction is made. + * + * Results: None. + * + * Side Effects: Junctions may be created. + * + *------------------------------------------------------------------------- + */ + +void +ResProcessJunction(tile, tp, xj, yj, NodeList) + Tile *tile, *tp; + int xj,yj; + resNode **NodeList; +{ + ResJunction *junction; + resNode *resptr; + jElement *jcell; + tileJunk *j0 = (tileJunk *)tile->ti_client; + tileJunk *j2 = (tileJunk *)tp->ti_client; + +#ifdef PARANOID + if (tile == tp) + { + TxError("Junction being made between tile and itself \n"); + return; + } +#endif + + if (j2->tj_status & RES_TILE_DONE) return; + resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); + resptr->rn_te = (tElement *) NULL; + junction = (ResJunction *) mallocMagic((unsigned)(sizeof(ResJunction))); + jcell = (jElement *) mallocMagic((unsigned)(sizeof(jElement))); + InitializeNode(resptr,xj,yj,RES_NODE_JUNCTION); + resptr->rn_je = jcell; + ResAddToQueue(resptr,NodeList); + + jcell->je_thisj = junction; + jcell->je_nextj = NULL; + junction->rj_status = FALSE; + junction->rj_jnode = resptr; + junction->rj_Tile[0] = tile; + junction->rj_Tile[1] = tp; + junction->rj_loc.p_x =xj; + junction->rj_loc.p_y =yj; + junction->rj_nextjunction[0] = j0->junctionList; + j0->junctionList = junction; + junction->rj_nextjunction[1] = j2->junctionList; + j2->junctionList = junction; + + NEWBREAK(junction->rj_jnode,tile, + junction->rj_loc.p_x,junction->rj_loc.p_y,NULL); + + NEWBREAK(junction->rj_jnode,tp, + junction->rj_loc.p_x,junction->rj_loc.p_y,NULL); + +} diff --git a/resis/ResMain.c b/resis/ResMain.c new file mode 100644 index 00000000..1548be5e --- /dev/null +++ b/resis/ResMain.c @@ -0,0 +1,1000 @@ +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResMain.c,v 1.4 2010/06/24 12:37:56 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "resis/resis.h" + +CellUse *ResUse=NULL; /* Our use and def */ +CellDef *ResDef=NULL; +TileTypeBitMask ResConnectWithSD[NT]; /* A mask that goes from */ + /* SD's to transistors. */ +TileTypeBitMask ResCopyMask[NT]; /* Indicates which tiles */ + /* are to be copied. */ +resResistor *ResResList=NULL; /* Resistor list */ +resNode *ResNodeList=NULL; /* Processed Nodes */ +resTransistor *ResTransList=NULL; /* Transistors */ +ResContactPoint *ResContactList=NULL; /* Contacts */ +resNode *ResNodeQueue=NULL; /* Pending nodes */ +resNode *ResOriginNode=NULL; /* node where R=0 */ +resNode *resCurrentNode; +int ResTileCount=0; /* Number of tiles rn_status */ +extern Region *ResFirst(); +extern Tile *FindStartTile(); +extern int ResEachTile(); +extern int ResLaplaceTile(); +extern ResSimNode *ResInitializeNode(); + +extern HashTable ResNodeTable; + + + +/* + *-------------------------------------------------------------------------- + * + * ResInitializeConn-- + * + * Sets up mask by Source/Drain type of transistors. This is + * exts_transSDtypes turned inside out. + * + * Results: none + * + * Side Effects: Sets up ResConnectWithSD. + * + *------------------------------------------------------------------------- + */ + +void +ResInitializeConn() +{ + TileType tran, diff; + char *tran_name; + + for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) + { + tran_name = (ExtCurStyle->exts_transName)[tran]; + if ((tran_name != NULL) && (strcmp(tran_name, "None"))) + { + for (diff = TT_TECHDEPBASE; diff < TT_MAXTYPES; diff++) + { + if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[tran][0]), diff) + TTMaskSetType(&ResConnectWithSD[diff],tran); + + if TTMaskHasType(&(ExtCurStyle->exts_transSubstrateTypes[tran]),diff) + TTMaskSetType(&ResConnectWithSD[diff],tran); + } + } + TTMaskSetMask(&ResConnectWithSD[tran],&DBConnectTbl[tran]); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * ResGetReCell -- + * + * This procedure makes sure that ResUse,ResDef + * have been properly initialized to refer to a cell definition + * named "__RESIS__". + * + * Results: + * None. + * + * Side effects: + * A new cell use and/or def are created if necessary. + * + * -------------------------------------------------------------------------- + */ + +void +ResGetReCell() +{ + if (ResUse != NULL) return; + ResDef = DBCellLookDef("__RESIS__"); + if (ResDef == NULL) + { + ResDef = DBCellNewDef("__RESIS__", (char *) NULL); + ASSERT (ResDef != (CellDef *) NULL, "ResGetReCell"); + DBCellSetAvail(ResDef); + ResDef->cd_flags |= CDINTERNAL; + } + ResUse = DBCellNewUse(ResDef, (char *) NULL); + DBSetTrans(ResUse, &GeoIdentityTransform); + ResUse->cu_expandMask = CU_DESCEND_SPECIAL; + +} + +/* + *-------------------------------------------------------------------------- + * + * ResDissolveContacts-- + * + * results: none + * + * Side Effects: All contacts in the design are broken into their + * constituent + * layers. There should be no contacts in ResDef after this procedure + * runs. + * + * + *------------------------------------------------------------------------ + */ +void +ResDissolveContacts(contacts) + ResContactPoint *contacts; +{ + TileType t, oldtype; + Tile *tp; + TileTypeBitMask residues; + + for (; contacts != (ResContactPoint *) NULL; contacts = contacts->cp_nextcontact) + + { + oldtype=contacts->cp_type; +#ifdef PARANOID + if (oldtype == TT_SPACE) + { + TxError("Error in Contact Dissolving for %s \n",ResCurrentNode); + } +#endif + + DBFullResidueMask(oldtype, &residues); + + DBErase(ResUse->cu_def, &(contacts->cp_rect), oldtype); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + if (TTMaskHasType(&residues, t)) + { + if (TTMaskHasType(&ExtCurStyle->exts_transMask, t)) + continue; + DBPaint(ResUse->cu_def, &(contacts->cp_rect), t); + } + } + + tp = ResDef->cd_planes[DBPlane(contacts->cp_type)]->pl_hint; + GOTOPOINT(tp,&(contacts->cp_rect.r_ll)); +#ifdef PARANOID + if (TiGetTypeExact(tp) == contacts->cp_type) + { + TxError("Error in Contact Preprocess Routines\n"); + } +#endif + } +} + +/* + *--------------------------------------------------------------------------- + * + * ResMakePortBreakpoints -- + * + * Search for nodes which are ports, and force them to be breakpoints + * in the "tileJunk" field of their respective tiles in ResUse. This + * ensures that connected nodes that stretch between two ports will + * not be assumed to be "hanging" nodes. + * + * Do the same thing for labels. + * + *---------------------------------------------------------------------------- + */ +void +ResMakePortBreakpoints(def) + CellDef *def; +{ + Plane *plane; + Rect *rect; + TileTypeBitMask mask; + HashSearch hs; + HashEntry *entry; + ResSimNode *node; + int ResAddBreakpointFunc(); /* Forward Declaration */ + + HashStartSearch(&hs); + while((entry = HashNext(&ResNodeTable,&hs)) != NULL) + { + node=(ResSimNode *) HashGetValue(entry); + if (node->status & PORTNODE) + { + plane = def->cd_planes[DBPlane(node->rs_ttype)]; + rect = &(node->rs_bbox); + + TTMaskSetOnlyType(&mask, node->rs_ttype); + (void) DBSrPaintArea((Tile *) NULL, plane, rect, &mask, + ResAddBreakpointFunc, (ClientData)node); + } + } +} + +/* + *--------------------------------------------------------------------------- + * + * ResMakeLabelBreakpoints -- + * + * Search for labels that are part of a node, and force them to be + * breakpoints in the "tileJunk" field of their respective tiles in + * ResUse. This ensures (among other things) that pins of a top level + * cell will be retained and become the endpoint of a net. + * + *---------------------------------------------------------------------------- + */ +void +ResMakeLabelBreakpoints(def) + CellDef *def; +{ + Plane *plane; + Rect *rect; + TileTypeBitMask mask; + HashEntry *entry; + ResSimNode *node; + Label *slab; + int ResAddBreakpointFunc(); /* Forward Declaration */ + + for (slab = def->cd_labels; slab != NULL; slab = slab->lab_next) + { + entry = HashFind(&ResNodeTable, slab->lab_text); + node = ResInitializeNode(entry); + + node->drivepoint = slab->lab_rect.r_ll; + node->rs_bbox = slab->lab_rect; + node->location = slab->lab_rect.r_ll; + node->rs_ttype = slab->lab_type; + node->type = slab->lab_type; + + plane = def->cd_planes[DBPlane(slab->lab_type)]; + rect = &(node->rs_bbox); + + TTMaskSetOnlyType(&mask, slab->lab_type); + (void) DBSrPaintArea((Tile *) NULL, plane, rect, &mask, + ResAddBreakpointFunc, (ClientData)node); + + } +} + +/* + *---------------------------------------------------------------------------- + * + * ResAddBreakpointFunc -- + * + * Add a breakpoint to the "tileJunk" structure of the tile + * + *---------------------------------------------------------------------------- + */ + +int +ResAddBreakpointFunc(tile, node) + Tile *tile; + ResSimNode *node; +{ + tileJunk *junk; + + if (tile->ti_client == (ClientData) CLIENTDEFAULT) + return 0; + + NEWPORT(node, tile); + + return 0; +} + + +/* + *--------------------------------------------------------------------------- + * + * ResFindNewContactTiles -- + * + * + * Results: none + * + * Side Effects: dissolving contacts eliminated the tiles that + * contacts->nextcontact pointed to. This procedure finds the tile now under + * center and sets that tile's ti_client field to point to the contact. The + * old value of clientdata is set to nextTilecontact. + * + *---------------------------------------------------------------------------- + */ + +void +ResFindNewContactTiles(contacts) + ResContactPoint *contacts; +{ + int pNum; + Tile *tile; + TileTypeBitMask mask; + + for (; contacts != (ResContactPoint *) NULL; contacts = contacts->cp_nextcontact) + { + DBFullResidueMask(contacts->cp_type, &mask); + for (pNum=PL_TECHDEPBASE; pNumcd_planes[pNum]->pl_hint; + GOTOPOINT(tile, &(contacts->cp_center)); +#ifdef PARANOID + if (tile == (Tile *) NULL) + { + TxError("Error: setting contact tile to null\n"); + } +#endif + if ((IsSplit(tile) && TTMaskHasType(&mask, TiGetRightType(tile))) + || TTMaskHasType(&mask, TiGetType(tile))) + { + tileJunk *j = (tileJunk *)tile->ti_client; + cElement *ce; + + ce = (cElement *) mallocMagic((unsigned) (sizeof(cElement))); + contacts->cp_tile[contacts->cp_currentcontact] = tile; + ce->ce_thisc = contacts; + ce->ce_nextc = j->contactList; + (contacts->cp_currentcontact) += 1; + j->contactList = ce; + } + } +#ifdef PARANOID + if (contacts->cp_currentcontact > LAYERS_PER_CONTACT) + { + TxError("Error: Not enough space allocated for contact nodes\n"); + } +#endif + } +} + +/* + *-------------------------------------------------------------------------- + * + * ResProcessTiles--Calls ResEachTile with processed tiles belonging to + * nodes in ResNodeQueue. When all the tiles corresponding + * to a node have been processed, the node is moved to + * ResNodeList. + * + * Results: Return 1 if any error occurred, 0 otherwise. + * + * Side Effects: Cleans extraneous linked lists from nodes. + * + *-------------------------------------------------------------------------- + */ + +int +ResProcessTiles(goodies, origin) + Point *origin; + ResGlobalParams *goodies; + +{ + Tile *startTile; + int tilenum,merged; + resNode *resptr2; + jElement *workingj; + cElement *workingc; + ResFixPoint *fix; + resNode *resptr; + int (*tilefunc)(); + +#ifdef LAPLACE + tilefunc = (ResOptionsFlags & ResOpt_DoLaplace)?ResLaplaceTile:ResEachTile; +#else + tilefunc = ResEachTile; +#endif + + if (ResOptionsFlags & ResOpt_Signal) + { + startTile = FindStartTile(goodies, origin); + if (startTile == NULL) return(1); + resCurrentNode = NULL; + (void) (*tilefunc)(startTile, origin); + } +#ifdef ARIEL + else if (ResOptionsFlags & ResOpt_Power) + { + for (fix = ResFixList; fix != NULL;fix=fix->fp_next) + { + Tile *tile = fix->fp_tile; + if (tile == NULL) + { + + tile = ResDef->cd_planes[DBPlane(fix->fp_ttype)]->pl_hint; + GOTOPOINT(tile, &(fix->fp_loc)); + if (TiGetTypeExact(tile) != TT_SPACE) + { + fix->fp_tile = tile; + } + else + { + tile = NULL; + } + } + if (tile != NULL) + { + int x = fix->fp_loc.p_x; + int y = fix->fp_loc.p_y; + resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); + InitializeNode(resptr, x, y, RES_NODE_ORIGIN); + resptr->rn_status = TRUE; + resptr->rn_noderes = 0; + ResAddToQueue(resptr, &ResNodeQueue); + fix->fp_node = resptr; + NEWBREAK(resptr, tile, x, y, NULL); + } + } + for (fix = ResFixList; fix != NULL; fix = fix->fp_next) + { + Tile *tile = fix->fp_tile; + + if (tile != NULL && (((tileJunk *)tile->ti_client)->tj_status & + RES_TILE_DONE) == 0) + { + resCurrentNode = fix->fp_node; + (void) (*tilefunc)(tile, (Point *)NULL); + } + } + } +#endif +#ifdef PARANOID + else + { + TxError("Unknown analysis type in ResProcessTiles\n"); + } +#endif + + /* Process Everything else */ + + while (ResNodeQueue != NULL) + { + /* + * merged keeps track of whether another node gets merged into + * the current one. If it does, then the node must be processed + * because additional junctions or contacts were added + */ + + resptr2 = ResNodeQueue; + merged = FALSE; + + /* Process all junctions associated with node */ + + for (workingj = resptr2->rn_je; workingj != NULL; workingj = workingj->je_nextj) + { + ResJunction *rj = workingj->je_thisj; + if (rj->rj_status == FALSE) + { + for (tilenum = 0; tilenum < TILES_PER_JUNCTION; tilenum++) + { + Tile *tile = rj->rj_Tile[tilenum]; + tileJunk *j = (tileJunk *) tile->ti_client; + + if ((j->tj_status & RES_TILE_DONE) == 0) + { + resCurrentNode = resptr2; + merged |= (*tilefunc)(tile,(Point *)NULL); + } + if (merged & ORIGIN) break; + } + if (merged & ORIGIN) break; + rj->rj_status = TRUE; + } + } + + /* Next, Process all contacts. */ + + for (workingc = resptr2->rn_ce;workingc != NULL;workingc = workingc->ce_nextc) + { + ResContactPoint *cp = workingc->ce_thisc; + + if (merged & ORIGIN) break; + if (cp->cp_status == FALSE) + { + int newstatus = TRUE; + for (tilenum = 0; tilenum < cp->cp_currentcontact; tilenum++) + { + Tile *tile = cp->cp_tile[tilenum]; + tileJunk *j = (tileJunk *) tile->ti_client; + + if ((j->tj_status & RES_TILE_DONE) == 0) + { + if (cp->cp_cnode[tilenum] == resptr2) + { + resCurrentNode = resptr2; + merged |= (*tilefunc)(tile,(Point *)NULL); + } + else + { + newstatus = FALSE; + } + } + if (merged & ORIGIN) break; + } + if (merged & ORIGIN) break; + cp->cp_status = newstatus; + } + } + + /* + * If nothing new has been added via a merge, then the node is + * finished. It is removed from the pending queue, added to the + * done list, cleaned up, and passed to ResDoneWithNode + */ + + if (merged == FALSE) + { + ResRemoveFromQueue(resptr2,&ResNodeQueue); + resptr2->rn_more = ResNodeList; + resptr2->rn_less = NULL; + resptr2->rn_status &= ~PENDING; + resptr2->rn_status |= FINISHED | MARKED; + if (ResNodeList != NULL) + { + ResNodeList->rn_less = resptr2; + } + if (resptr2->rn_noderes == 0) + { + ResOriginNode=resptr2; + } + ResNodeList = resptr2; + ResCleanNode(resptr2, FALSE, &ResNodeList, &ResNodeQueue); + ResDoneWithNode(resptr2); + } + } + return(0); +} + +/*------------------------------------------------------------------------- + * + * ResExtractNet-- extracts the resistance net at the specified + * rn_loc. If the resulting net is greater than the tolerance, + * simplify and return the resulting network. + * + * Results: 0 iff it worked. + * + * Side effects: Produces a resistance network for the node. + * + * + *------------------------------------------------------------------------- + */ + +bool +ResExtractNet(startlist,goodies,cellname) + ResFixPoint *startlist; + ResGlobalParams *goodies; + char *cellname; +{ + SearchContext scx; + int pNum; + ResTranTile *TranTiles,*lasttile; + TileTypeBitMask FirstTileMask; + Point startpoint; + ResFixPoint *fix; + static int first = 1; + + /* Make sure all global network variables are reset */ + + ResResList=NULL; + ResNodeList=NULL; + ResTransList=NULL; + ResNodeQueue=NULL; + ResContactList = NULL; + ResOriginNode = NULL; + + /* Pass back network pointers */ + + goodies->rg_maxres = 0; + goodies->rg_tilecount = 0; + + /*set up internal stuff if this is the first time through */ + + if (first) + { + ResInitializeConn(); + first = 0; + ResGetReCell(); + } + + /* Initialize Cell */ + + if (cellname) + { + CellDef *def = DBCellLookDef(cellname); + if (def == (CellDef *) NULL) + { + TxError("Error: No such cell \"%s\"\n", cellname); + return TRUE; + } + scx.scx_use = DBCellNewUse(def, (char *)NULL); + DBSetTrans (scx.scx_use, &GeoIdentityTransform); + scx.scx_trans = GeoIdentityTransform; + } + else + { + MagWindow *w = ToolGetBoxWindow(&scx.scx_area, (int *) NULL); + if (w == (MagWindow *) NULL) + { + TxError("Sorry, the box must appear in one of the windows.\n"); + return TRUE; + } + scx.scx_use = (CellUse *) w->w_surfaceID; + scx.scx_trans = GeoIdentityTransform; + } + + DBCellClearDef(ResUse->cu_def); + + + /* Copy Paint */ + TranTiles = NULL; + lasttile = NULL; + for (fix = startlist; fix != NULL;fix=fix->fp_next) + { + ResTranTile *newtrantiles,*tmp; + +#ifdef ARIEL + if ((ResOptionsFlags & ResOpt_Power) && + strcmp(fix->fp_name,goodies->rg_name) != 0) continue; +#endif + + scx.scx_area.r_ll.p_x = fix->fp_loc.p_x-2; + scx.scx_area.r_ll.p_y = fix->fp_loc.p_y-2; + scx.scx_area.r_ur.p_x = fix->fp_loc.p_x+2; + scx.scx_area.r_ur.p_y = fix->fp_loc.p_y+2; + startpoint = fix->fp_loc; + TTMaskSetOnlyType(&FirstTileMask,fix->fp_ttype); + + newtrantiles = DBTreeCopyConnectDCS(&scx, &FirstTileMask, 0, + ResCopyMask, &TiPlaneRect, ResUse); + + for (tmp = newtrantiles; tmp && tmp->nextTran; tmp = tmp->nextTran); + if (newtrantiles) + { + if (TranTiles) + { + lasttile->nextTran = newtrantiles; + } + else + { + TranTiles = newtrantiles; + } + lasttile = tmp; + } + } + + ExtResetTiles(scx.scx_use->cu_def, extUnInit); + + /* find all contacts in design and note their position */ + + ResContactList = (ResContactPoint *) ExtFindRegions(ResUse->cu_def, + &(ResUse->cu_def->cd_bbox), + &DBAllButSpaceAndDRCBits, + ResConnectWithSD, extUnInit, ResFirst, + ResEach); + ExtResetTiles(ResUse->cu_def,extUnInit); + + /* + * dissolve the contacts and find which tiles now cover the point + * where the tile used to be. + */ + + ResDissolveContacts(ResContactList); + + /* Add "junk" fields to tiles */ + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + Plane *plane = ResUse->cu_def->cd_planes[pNum]; + Rect *rect = &ResUse->cu_def->cd_bbox; + ResFracture(plane,rect); + (void) DBSrPaintClient((Tile *) NULL,plane,rect, + &DBAllButSpaceAndDRCBits, + (ClientData) CLIENTDEFAULT, ResAddPlumbing, + (ClientData) &ResTransList); + } + + /* Finish preprocessing. */ + + ResMakePortBreakpoints(ResUse->cu_def); + ResMakeLabelBreakpoints(ResUse->cu_def); + ResFindNewContactTiles(ResContactList); + ResPreProcessTransistors(TranTiles, ResTransList, ResUse->cu_def); + +#ifdef LAPLACE + if (ResOptionsFlags & ResOpt_DoLaplace) + { + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + Plane *plane = ResUse->cu_def->cd_planes[pNum]; + Rect *rect = &ResUse->cu_def->cd_bbox; + Res1d(plane,rect); + } + } +#endif + +#ifdef ARIEL + if (ResOptionsFlags & ResOpt_Power) + { + for (fix = startlist; fix != NULL;fix=fix->fp_next) + { + fix->fp_tile = ResUse->cu_def->cd_planes[DBPlane(fix->fp_ttype)]->pl_hint; + GOTOPOINT(fix->fp_tile,&fix->fp_loc); + if (TiGetTypeExact(fix->fp_tile) == TT_SPACE) fix->fp_tile = NULL; + } + } +#endif + + /* do extraction */ + if (ResProcessTiles(goodies, &startpoint) != 0) return TRUE; + return FALSE; +} + + +/* + *------------------------------------------------------------------------- + * + * ResCleanUpEverything--After each net is extracted by ResExtractNet, + * the resulting memory must be freed up, and varius trash swept under + * the carpet in preparation for the next extraction. + * + * Results: none + * + * Side Effects: Frees up memory formerly occupied by network elements. + * + *------------------------------------------------------------------------- + */ + +void +ResCleanUpEverything() +{ + + int pNum; + resResistor *oldRes; + resTransistor *oldTran; + ResContactPoint *oldCon; + + /* check integrity of internal database. Free up lists. */ + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + (void) DBSrPaintClient((Tile *) NULL,ResUse->cu_def->cd_planes[pNum], + &(ResUse->cu_def->cd_bbox),&DBAllButSpaceAndDRCBits, + (ClientData) CLIENTDEFAULT,ResRemovePlumbing, + (ClientData) NULL); + + } + + while (ResNodeList != NULL) + { + ResCleanNode(ResNodeList,TRUE,&ResNodeList,&ResNodeQueue); + } + while (ResContactList != NULL) + { + oldCon = ResContactList; + ResContactList = oldCon->cp_nextcontact; + freeMagic((char *)oldCon); + } + while (ResResList != NULL) + { + oldRes = ResResList; + ResResList = ResResList->rr_nextResistor; + freeMagic((char *)oldRes); + } + while (ResTransList != NULL) + { + oldTran = ResTransList; + ResTransList = ResTransList->rt_nextTran; + if ((oldTran->rt_status & RES_TRAN_SAVE) == 0) + { + freeMagic((char *)oldTran); + } + } + + DBCellClearDef(ResUse->cu_def); +} + + + +/* + *------------------------------------------------------------------------- + * + * FindStartTile-- To start the extraction, we need to find the first driver. + * The sim file gives us the location of a point in or near (within 1 + * unit) of the transistor. FindStartTile looks for the transistor, then + * for adjoining diffusion. The diffusion tile is returned. + * + * Results: returns source diffusion tile, if it exists. Otherwise, return + * NULL. + * + * Side Effects: none + * + *------------------------------------------------------------------------- + */ + +Tile * +FindStartTile(goodies, SourcePoint) + Point *SourcePoint; + ResGlobalParams *goodies; + +{ + Point workingPoint; + Tile *tile, *tp; + int pnum, t1, t2; + + workingPoint.p_x = goodies->rg_tranloc->p_x; + workingPoint.p_y = goodies->rg_tranloc->p_y; + pnum = DBPlane(goodies->rg_ttype); + + /* for drivepoints, we don't have to find a transistor */ + if (goodies->rg_status & DRIVEONLY) + { + tile = ResUse->cu_def->cd_planes[pnum]->pl_hint; + GOTOPOINT(tile, &workingPoint); + SourcePoint->p_x = workingPoint.p_x; + SourcePoint->p_y = workingPoint.p_y; + if (TiGetTypeExact(tile) == goodies->rg_ttype) + return tile; + else + { + /* On the other hand, drivepoints derived from subcircuit */ + /* boundaries lie on tile boundaries, and GOTOPOINT() will */ + /* pick the tile on the wrong side for TOP and RIGHT */ + /* segment coincidences. */ + + if (workingPoint.p_x == LEFT(tile)) + { + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) + if (TiGetRightType(tp) == goodies->rg_ttype) + return(tp); + } + else if (workingPoint.p_y == BOTTOM(tile)) + { + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) + if (TiGetTopType(tp) == goodies->rg_ttype) + return(tp); + } + } + TxError("Couldn't find wire at %d %d\n", + goodies->rg_tranloc->p_x, goodies->rg_tranloc->p_y); + return NULL; + } + + tile = ResUse->cu_def->cd_planes[pnum]->pl_hint; + GOTOPOINT(tile, &workingPoint); + + if (IsSplit(tile)) + { + if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetLeftType(tile)) != 0) + { + t1 = TiGetLeftType(tile); + TiSetBody(tile, t1 & ~TT_SIDE); + } + else if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetRightType(tile)) != 0) + { + t1 = TiGetRightType(tile); + TiSetBody(tile, t1 & TT_SIDE); + } + else + { + TxError("Couldn't find transistor at %d %d\n", + goodies->rg_tranloc->p_x, goodies->rg_tranloc->p_y); + return(NULL); + } + } + else if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetType(tile)) == 0) + { + TxError("Couldn't find transistor at %d %d\n", + goodies->rg_tranloc->p_x, goodies->rg_tranloc->p_y); + return(NULL); + } + else + t1 = TiGetType(tile); + + /* left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) + { + t2 = TiGetRightType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + { + SourcePoint->p_x = LEFT(tile); + SourcePoint->p_y = (MIN(TOP(tile),TOP(tp))+ + MAX(BOTTOM(tile),BOTTOM(tp)))>>1; + return(tp); + } + } + + /* right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) + { + t2 = TiGetLeftType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + { + SourcePoint->p_x = RIGHT(tile); + SourcePoint->p_y = (MIN(TOP(tile),TOP(tp))+ + MAX(BOTTOM(tile),BOTTOM(tp)))>>1; + return(tp); + } + } + + /* top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) + { + t2 = TiGetBottomType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + { + SourcePoint->p_y = TOP(tile); + SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp))+ + MAX(LEFT(tile),LEFT(tp)))>>1; + return(tp); + } + } + + /* bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) + { + t2 = TiGetTopType(tp); + if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + { + SourcePoint->p_y = BOTTOM(tile); + SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp))+ + MAX(LEFT(tile),LEFT(tp)))>>1; + return(tp); + } + } + return((Tile *) NULL); +} + +/* + *------------------------------------------------------------------------- + * + * ResGetTransistor-- Once the net is extracted, we still have to equate + * the sim file transistors with the layout transistors. ResGetTransistor + * looks for a transistor at the given location. + * + * Results: returns transistor structure at location TransistorPoint, if it + * exists. + * + * Side Effects: none + * + *------------------------------------------------------------------------- + */ + +resTransistor * +ResGetTransistor(pt) + Point *pt; + +{ + Point workingPoint; + Tile *tile; + int pnum; + + workingPoint.p_x = (*pt).p_x; + workingPoint.p_y = (*pt).p_y; + + for (pnum= PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++) + { + if (TTMaskIntersect(&ExtCurStyle->exts_transMask,&DBPlaneTypes[pnum]) == 0) + { + continue; + } + /*start at hint tile for transistor plane */ + tile = ResUse->cu_def->cd_planes[pnum]->pl_hint; + GOTOPOINT(tile,&workingPoint); + + if (IsSplit(tile)) + { + if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetLeftType(tile)) + || TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetRightType(tile))) + return(((tileJunk *)tile->ti_client)->transistorList); + } + else if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetType(tile))) + { + return(((tileJunk *)tile->ti_client)->transistorList); + } + } + return (NULL); +} diff --git a/resis/ResMakeRes.c b/resis/ResMakeRes.c new file mode 100644 index 00000000..1ff30a22 --- /dev/null +++ b/resis/ResMakeRes.c @@ -0,0 +1,966 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResMakeRes.c,v 1.3 2010/06/24 12:37:56 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "resis/resis.h" + +/* Forward declarations */ +bool ResCalcNearTransistor(); +bool ResCalcNorthSouth(); +bool ResCalcEastWest(); + + +/* + *-------------------------------------------------------------------------- + * + * ResCalcTileResistance-- Given a set of partitions for a tile, the tile can + * be converted into resistors. To do this, nodes are sorted in the + * direction of current flow. Resistors are created by counting squares + * between successive breakpoints. Breakpoints with the same coordinate + * are combined. + * + * Results: returns TRUE if the startnode was involved in a merge. + * + * Side Effects: Resistor structures are produced. Some nodes may be + * eliminated. + *-------------------------------------------------------------------------- + * + */ + +bool +ResCalcTileResistance(tile, junk, pendingList, doneList) + Tile *tile; + tileJunk *junk; + resNode **pendingList, **doneList; + +{ + int MaxX = MINFINITY, MinX = INFINITY; + int MaxY = MINFINITY, MinY = INFINITY; + int transistor; + bool merged; + Breakpoint *p1; + + merged = FALSE; + transistor = FALSE; + + if ((p1 = junk->breakList) == NULL) return FALSE; + for (; p1; p1 = p1->br_next) + { + int x = p1->br_loc.p_x; + int y = p1->br_loc.p_y; + if (x > MaxX) MaxX = x; + if (x < MinX) MinX = x; + if (y > MaxY) MaxY = y; + if (y < MinY) MinY = y; + if (p1->br_this->rn_why == RES_NODE_TRANSISTOR) + { + transistor = TRUE; + } + } + + /* Finally, produce resistors for partition. Keep track of */ + /* whether or not the node was involved in a merge. */ + + if (transistor) + { + merged |= ResCalcNearTransistor(tile, pendingList, doneList, &ResResList); + } + else if (MaxY-MinY > MaxX-MinX) + { + merged |= ResCalcNorthSouth(tile, pendingList, doneList, &ResResList); + } + else + { + merged |= ResCalcEastWest(tile, pendingList, doneList, &ResResList); + } + + /* + * For all the new resistors, propagate the resistance from the origin + * to the new nodes. + */ + + return(merged); +} + + +/* + *------------------------------------------------------------------------- + * + * ResCalcEastWest-- Makes resistors from an EastWest partition. + * + * Results: Returns TRUE if the sacredNode was involved in a merge. + * + * Side Effects: Makes resistors. Frees breakpoints. + * + *------------------------------------------------------------------------- + */ + +bool +ResCalcEastWest(tile, pendingList, doneList, resList) + Tile *tile; + resNode **pendingList, **doneList; + resResistor **resList; +{ + int height; + bool merged; + Breakpoint *p1, *p2, *p3; + resResistor *resistor; + resElement *element; + resNode *currNode; + float rArea; + tileJunk *junk = (tileJunk *)tile->ti_client; + + merged = FALSE; + height = TOP(tile) - BOTTOM(tile); + + /* + * One Breakpoint? No resistors need to be made. Free up the first + * breakpoint, then return. + */ + + p1 = junk->breakList; + if (p1->br_next == NULL) + { + p1->br_this->rn_float.rn_area += height * (LEFT(tile) - RIGHT(tile)); + freeMagic((char *)p1); + junk->breakList = NULL; + return(merged); + } + + /* re-sort nodes left to right. */ + + ResSortBreaks(&junk->breakList, TRUE); + + /* + * Eliminate breakpoints with the same X coordinate and merge + * their nodes. + */ + + p2= junk->breakList; + + /* add extra left area to leftmost node */ + + p2->br_this->rn_float.rn_area += height*(p2->br_loc.p_x-LEFT(tile)); + while (p2->br_next != NULL) + { + p1 = p2; + p2 = p2->br_next; + if (p2->br_loc.p_x == p1->br_loc.p_x) + { + if (p2->br_this == p1->br_this) + { + currNode = NULL; + p1->br_next = p2->br_next; + freeMagic((char *)p2); + p2 = p1; + } + else if (p2->br_this == resCurrentNode) + { + currNode = p1->br_this; + ResMergeNodes(p2->br_this,p1->br_this,pendingList,doneList); + merged = TRUE; + freeMagic((char *)p1); + } + else if (p1->br_this == resCurrentNode) + { + currNode = p2->br_this; + p1->br_next = p2->br_next; + ResMergeNodes(p1->br_this,p2->br_this,pendingList,doneList); + merged = TRUE; + freeMagic((char *)p2); + p2 = p1; + } + else + { + currNode = p1->br_this; + ResMergeNodes(p2->br_this,p1->br_this,pendingList,doneList); + freeMagic((char *)p1); + } + + /* + * Was the node used in another junk or breakpoint? + * If so, replace the old node with the new one. + */ + p3 = p2->br_next; + while (p3 != NULL) + { + if (p3->br_this == currNode) + { + p3->br_this = p2->br_this; + } + p3 = p3->br_next; + } + } + + /* + * If the X coordinates don't match, make a resistor between + * the breakpoints. + */ + + else + { + resistor = (resResistor *) mallocMagic((unsigned) (sizeof(resResistor))); + resistor->rr_nextResistor = (*resList); + resistor->rr_lastResistor = NULL; + if ((*resList) != NULL) (*resList)->rr_lastResistor = resistor; + (*resList) = resistor; + resistor->rr_connection1 = p1->br_this; + resistor->rr_connection2 = p2->br_this; + element = (resElement *) mallocMagic((unsigned) (sizeof(resElement))); + element->re_nextEl = p1->br_this->rn_re; + element->re_thisEl = resistor; + p1->br_this->rn_re = element; + element = (resElement *) mallocMagic((unsigned) (sizeof(resElement))); + element->re_nextEl = p2->br_this->rn_re; + element->re_thisEl = resistor; + p2->br_this->rn_re = element; + resistor->rr_cl = (TOP(tile) + BOTTOM(tile)) >> 1; + resistor->rr_width = height; + + if (IsSplit(tile)) + { + resistor->rr_tt = (SplitSide(tile)) ? SplitRightType(tile) + : SplitLeftType(tile); + resistor->rr_status = RES_DIAGONAL; + resistor->rr_status |= (SplitDirection(tile)) ? RES_NS + : RES_EW; + + } + else + { + resistor->rr_status = RES_EW; + resistor->rr_tt = TiGetTypeExact(tile); + } +#ifdef ARIEL + resistor->rr_csArea = height * + ExtCurStyle->exts_thick[resistor->rr_tt]; +#endif + resistor->rr_value = + (ExtCurStyle->exts_sheetResist[resistor->rr_tt] + * (p2->br_loc.p_x-p1->br_loc.p_x)) / height; + rArea = ((p2->br_loc.p_x-p1->br_loc.p_x) * height) / 2; + resistor->rr_connection1->rn_float.rn_area += rArea; + resistor->rr_connection2->rn_float.rn_area += rArea; + resistor->rr_float.rr_area = 0; + + freeMagic((char *)p1); + } + } + p2->br_this->rn_float.rn_area += height * (RIGHT(tile) - p2->br_loc.p_x); + freeMagic((char *)p2); + junk->breakList = NULL; + return(merged); +} + + +/* + *------------------------------------------------------------------------- + * + * ResCalcNorthSouth-- Makes resistors from a NorthSouth partition + * + * Results: Returns TRUE if the resCurrentNode was involved in a merge. + * + * Side Effects: Makes resistors. Frees breakpoints + * + *------------------------------------------------------------------------- + */ + +bool +ResCalcNorthSouth(tile, pendingList, doneList, resList) + Tile *tile; + resNode **pendingList, **doneList; + resResistor **resList; +{ + int width; + bool merged; + Breakpoint *p1, *p2, *p3; + resResistor *resistor; + resElement *element; + resNode *currNode; + float rArea; + tileJunk *junk = (tileJunk *)tile->ti_client; + + merged = FALSE; + width = RIGHT(tile)-LEFT(tile); + + /* + * One Breakpoint? No resistors need to be made. Free up the first + * breakpoint, then return. + */ + + p1 = junk->breakList; + if (p1->br_next == NULL) + { + p1->br_this->rn_float.rn_area += width * (TOP(tile) - BOTTOM(tile)); + freeMagic((char *)p1); + junk->breakList = NULL; + return(merged); + } + + /* re-sort nodes south to north. */ + ResSortBreaks(&junk->breakList, FALSE); + + /* + * Eliminate breakpoints with the same Y coordinate and merge + * their nodes. + */ + + p2 = junk->breakList; + + /* add extra left area to leftmost node */ + + p2->br_this->rn_float.rn_area += width * (p2->br_loc.p_y - BOTTOM(tile)); + while (p2->br_next != NULL) + { + p1 = p2; + p2 = p2->br_next; + if (p1->br_loc.p_y == p2->br_loc.p_y) + { + if (p2->br_this == p1->br_this) + { + currNode = NULL; + p1->br_next = p2->br_next; + freeMagic((char *)p2); + p2 = p1; + } + else if (p2->br_this == resCurrentNode) + { + currNode = p1->br_this; + ResMergeNodes(p2->br_this,p1->br_this,pendingList,doneList); + freeMagic((char *)p1); + merged = TRUE; + } + else if (p1->br_this == resCurrentNode) + { + currNode = p2->br_this; + p1->br_next = p2->br_next; + ResMergeNodes(p1->br_this,p2->br_this,pendingList,doneList); + merged = TRUE; + freeMagic((char *)p2); + p2 = p1; + } + else + { + currNode = p1->br_this; + ResMergeNodes(p2->br_this,p1->br_this,pendingList,doneList); + freeMagic((char *)p1); + } + + /* + * Was the node used in another junk or breakpoint? + * If so, replace the old node with the new one. + */ + p3 = p2->br_next; + while (p3 != NULL) + { + if (p3->br_this == currNode) + { + p3->br_this = p2->br_this; + } + p3 = p3->br_next; + } + } + + /* + * If the Y coordinates don't match, make a resistor between + * the breakpoints. + */ + + else + { + resistor = (resResistor *) mallocMagic((unsigned) (sizeof(resResistor))); + resistor->rr_nextResistor = (*resList); + resistor->rr_lastResistor = NULL; + if ((*resList) != NULL) (*resList)->rr_lastResistor = resistor; + (*resList) = resistor; + resistor->rr_connection1 = p1->br_this; + resistor->rr_connection2 = p2->br_this; + element = (resElement *) mallocMagic((unsigned) (sizeof(resElement))); + element->re_nextEl = p1->br_this->rn_re; + element->re_thisEl = resistor; + p1->br_this->rn_re = element; + element = (resElement *) mallocMagic((unsigned) (sizeof(resElement))); + element->re_nextEl = p2->br_this->rn_re; + element->re_thisEl = resistor; + p2->br_this->rn_re = element; + resistor->rr_cl = (LEFT(tile) + RIGHT(tile)) >> 1; + resistor->rr_width = width; + if (IsSplit(tile)) + { + resistor->rr_tt = (SplitSide(tile)) ? SplitRightType(tile) + : SplitLeftType(tile); + resistor->rr_status = RES_DIAGONAL; + resistor->rr_status |= (SplitDirection(tile)) ? RES_NS + : RES_EW; + } + else + { + resistor->rr_status = RES_NS; + resistor->rr_tt = TiGetTypeExact(tile); + } +#ifdef ARIEL + resistor->rr_csArea = width + * ExtCurStyle->exts_thick[resistor->rr_tt]; +#endif + resistor->rr_value = + (ExtCurStyle->exts_sheetResist[resistor->rr_tt] + * (p2->br_loc.p_y-p1->br_loc.p_y)) / width; + rArea = ((p2->br_loc.p_y-p1->br_loc.p_y) * width) / 2; + resistor->rr_connection1->rn_float.rn_area += rArea; + resistor->rr_connection2->rn_float.rn_area += rArea; + resistor->rr_float.rr_area = 0; + freeMagic((char *)p1); + } + } + p2->br_this->rn_float.rn_area += width * (TOP(tile) - p2->br_loc.p_y); + freeMagic((char *)p2); + junk->breakList = NULL; + return(merged); +} + + +/* + *------------------------------------------------------------------------- + * + * ResCalcNearTransistor-- Calculating the direction of current flow near + * transistors is tricky because there are two adjoining regions with + * vastly different sheet resistances. ResCalcNearTransistor is called + * whenever a diffusion tile adjoining a real tile is found. It makes + * a guess at the correct direction of current flow, removes extra + * breakpoints, and call either ResCalcEastWest or ResCalcNorthSouth + * + * Results: + * TRUE if merging occurred, FALSE if not. + * + * Side Effects: Makes resistors. Frees breakpoints + * + *------------------------------------------------------------------------- + */ + +bool +ResCalcNearTransistor(tile, pendingList, doneList, resList) + Tile *tile; + resNode **pendingList, **doneList; + resResistor **resList; + +{ + bool merged; + int trancount,tranedge,deltax,deltay; + Breakpoint *p1,*p2,*p3; + tileJunk *junk = (tileJunk *)tile->ti_client; + + + merged = FALSE; + + /* + One Breakpoint? No resistors need to be made. Free up the first + breakpoint, then return. + */ + + if (junk->breakList->br_next == NULL) + { + freeMagic((char *)junk->breakList); + junk->breakList = NULL; + return(merged); + } + /* count the number of transistor breakpoints */ + /* mark which edge they connect to */ + trancount = 0; + tranedge = 0; + for (p1=junk->breakList; p1 != NULL;p1 = p1->br_next) + { + if (p1->br_this->rn_why == RES_NODE_TRANSISTOR) + { + trancount++; + if (p1->br_loc.p_x == LEFT(tile)) tranedge |= LEFTEDGE; + else if (p1->br_loc.p_x == RIGHT(tile)) tranedge |= RIGHTEDGE; + else if (p1->br_loc.p_y == TOP(tile)) tranedge |= TOPEDGE; + else if (p1->br_loc.p_y == BOTTOM(tile)) tranedge |= BOTTOMEDGE; + } + } + /* use distance from transistor to next breakpoint as determinant */ + /* if there is only one transistor or if all the transitors are along */ + /* the same edge. */ + if (trancount == 1 || + (tranedge & LEFTEDGE) == tranedge || + (tranedge & RIGHTEDGE) == tranedge || + (tranedge & TOPEDGE) == tranedge || + (tranedge & BOTTOMEDGE) == tranedge) + { + ResSortBreaks(&junk->breakList,TRUE); + p2 = NULL; + for (p1=junk->breakList; p1 != NULL;p1 = p1->br_next) + { + if (p1->br_this->rn_why == RES_NODE_TRANSISTOR) + { + break; + } + if (p1->br_next != NULL && + (p1->br_loc.p_x != p1->br_next->br_loc.p_x || + p1->br_loc.p_y != p1->br_next->br_loc.p_y)) + + { + p2 = p1; + } + } + deltax=INFINITY; + for (p3 = p1->br_next; + p3 != NULL && + p3->br_loc.p_x == p1->br_loc.p_x && + p3->br_loc.p_y == p1->br_loc.p_y; p3 = p3->br_next); + if (p3 != NULL) + { + if (p3->br_crect) + { + if (p3->br_crect->r_ll.p_x > p1->br_loc.p_x) + { + deltax = p3->br_crect->r_ll.p_x-p1->br_loc.p_x; + } + else if (p3->br_crect->r_ur.p_x < p1->br_loc.p_x) + { + deltax = p1->br_loc.p_x-p3->br_crect->r_ur.p_x; + } + else + { + deltax=0; + } + } + else + { + deltax = abs(p1->br_loc.p_x-p3->br_loc.p_x); + } + } + if (p2 != NULL) + { + if (p2->br_crect) + { + if (p2->br_crect->r_ll.p_x > p1->br_loc.p_x) + { + deltax = MIN(deltax,p2->br_crect->r_ll.p_x-p1->br_loc.p_x); + } + else if (p2->br_crect->r_ur.p_x < p1->br_loc.p_x) + { + deltax = MIN(deltax,p1->br_loc.p_x-p2->br_crect->r_ur.p_x); + } + else + { + deltax=0; + } + } + else + { + deltax = MIN(deltax,abs(p1->br_loc.p_x-p2->br_loc.p_x)); + } + } + + /* re-sort nodes south to north. */ + ResSortBreaks(&junk->breakList,FALSE); + p2 = NULL; + for (p1=junk->breakList; p1 != NULL;p1 = p1->br_next) + { + if (p1->br_this->rn_why == RES_NODE_TRANSISTOR) + { + break; + } + if (p1->br_next != NULL && + (p1->br_loc.p_x != p1->br_next->br_loc.p_x || + p1->br_loc.p_y != p1->br_next->br_loc.p_y)) + + { + p2 = p1; + } + } + deltay=INFINITY; + for (p3 = p1->br_next; + p3 != NULL && + p3->br_loc.p_x == p1->br_loc.p_x && + p3->br_loc.p_y == p1->br_loc.p_y; p3 = p3->br_next); + if (p3 != NULL) + { + if (p3->br_crect) + { + if (p3->br_crect->r_ll.p_y > p1->br_loc.p_y) + { + deltay = p3->br_crect->r_ll.p_y-p1->br_loc.p_y; + } + else if (p3->br_crect->r_ur.p_y < p1->br_loc.p_y) + { + deltay = p1->br_loc.p_y-p3->br_crect->r_ur.p_y; + } + else + { + deltay=0; + } + } + else + { + deltay = abs(p1->br_loc.p_y-p3->br_loc.p_y); + } + } + if (p2!= NULL) + { + if (p2->br_crect) + { + if (p2->br_crect->r_ll.p_y > p1->br_loc.p_y) + { + deltay = MIN(deltay,p2->br_crect->r_ll.p_y-p1->br_loc.p_y); + } + else if (p2->br_crect->r_ur.p_y < p1->br_loc.p_y) + { + deltay = MIN(deltay,p1->br_loc.p_y-p2->br_crect->r_ur.p_y); + } + else + { + deltay=0; + } + } + else + { + deltay = MIN(deltay,abs(p1->br_loc.p_y-p2->br_loc.p_y)); + } + } + if (deltay > deltax) + { + return(ResCalcNorthSouth(tile,pendingList,doneList,resList)); + } + else + { + return(ResCalcEastWest(tile,pendingList,doneList,resList)); + } + + } + /* multiple transistors connected to the partition */ + else + { + if (tranedge == 0) + { + TxError("Error in transistor current direction routine\n"); + return(merged); + } + /* check to see if the current flow is north-south */ + /* possible north-south conditions: */ + /* 1. there are transistors along the top and bottom edges */ + /* but not along the left or right */ + /* 2. there are transistors along two sides at right angles, */ + /* and the tile is wider than it is tall. */ + + if ((tranedge & TOPEDGE) && + (tranedge & BOTTOMEDGE) && + !(tranedge & LEFTEDGE) && + !(tranedge & RIGHTEDGE) || + (tranedge & TOPEDGE || tranedge & BOTTOMEDGE) && + (tranedge & LEFTEDGE || tranedge & RIGHTEDGE) && + RIGHT(tile)-LEFT(tile) > TOP(tile)-BOTTOM(tile)) + { + /* re-sort nodes south to north. */ + ResSortBreaks(&junk->breakList,FALSE); + + /* eliminate duplicate S/D pointers */ + for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next) + { + if (p1->br_this->rn_why == RES_NODE_TRANSISTOR && + (p1->br_loc.p_y == BOTTOM(tile) || + p1->br_loc.p_y == TOP(tile))) + { + p3 = NULL; + p2 = junk->breakList; + while ( p2 != NULL) + { + if (p2->br_this == p1->br_this && + p2 != p1 && + p2->br_loc.p_y != BOTTOM(tile) && + p2->br_loc.p_y != TOP(tile)) + { + if (p3 == NULL) + { + junk->breakList = p2->br_next; + freeMagic((char *) p2); + p2 = junk->breakList; + } + else + { + p3->br_next = p2->br_next; + freeMagic((char *) p2); + p2 = p3->br_next; + } + } + else + { + p3 = p2; + p2 = p2->br_next; + } + } + } + } + return(ResCalcNorthSouth(tile,pendingList,doneList,resList)); + } + else + { + /* eliminate duplicate S/D pointers */ + for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next) + { + if (p1->br_this->rn_why == RES_NODE_TRANSISTOR && + (p1->br_loc.p_x == LEFT(tile) || + p1->br_loc.p_x == RIGHT(tile))) + { + p3 = NULL; + p2 = junk->breakList; + while ( p2 != NULL) + { + if (p2->br_this == p1->br_this && + p2 != p1 && + p2->br_loc.p_x != LEFT(tile) && + p2->br_loc.p_x != RIGHT(tile)) + { + if (p3 == NULL) + { + junk->breakList = p2->br_next; + freeMagic((char *) p2); + p2 = junk->breakList; + } + else + { + p3->br_next = p2->br_next; + freeMagic((char *) p2); + p2 = p3->br_next; + } + } + else + { + p3 = p2; + p2 = p2->br_next; + } + } + } + } + return(ResCalcEastWest(tile,pendingList,doneList,resList)); + } + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResDoContacts-- Add node (or nodes) for a contact. If there are contact + * resistances, also add a resistor. + * + * Results: + * None. + * + * Side Effects: Creates nodes and resistors + * + *------------------------------------------------------------------------- + */ + +void +ResDoContacts(contact, nodes, resList) + ResContactPoint *contact; + resNode **nodes; + resResistor **resList; +{ + resNode *resptr; + cElement *ccell; + int tilenum, squaresx, squaresy, viawidth; + int minside, spacing, border; + float squaresf; + resResistor *resistor; + resElement *element; + static int too_small = 1; + + minside = CIFGetContactSize(contact->cp_type, &viawidth, &spacing, &border); + + if ((ExtCurStyle->exts_viaResist[contact->cp_type] == 0) || (viawidth == 0)) + { + int x = contact->cp_center.p_x; + int y = contact->cp_center.p_y; + + resptr = (resNode *) mallocMagic((unsigned) (sizeof(resNode))); + InitializeNode(resptr,x,y,RES_NODE_CONTACT); + ResAddToQueue(resptr,nodes); + + ccell = (cElement *) mallocMagic((unsigned) (sizeof(cElement))); + ccell->ce_nextc = resptr->rn_ce; + resptr->rn_ce = ccell; + ccell->ce_thisc = contact; + + /* add 1 celement for each layer of contact */ + + for (tilenum=0; tilenum < contact->cp_currentcontact; tilenum++) + { + Tile *tile = contact->cp_tile[tilenum]; + + contact->cp_cnode[tilenum] = resptr; + NEWBREAK(resptr, tile, contact->cp_center.p_x, + contact->cp_center.p_y, &contact->cp_rect); + } + } + else + { + if ((contact->cp_width < minside) || (contact->cp_height < minside)) + { + if (too_small) + { + TxError("Warning: %s at %d %d smaller than extract section allows\n", + DBTypeLongNameTbl[contact->cp_type], + contact->cp_center.p_x, contact->cp_center.p_y); + too_small = 0; + } + squaresx = squaresy = 1; + } + else + { + viawidth += spacing; + squaresf = (float)(contact->cp_width - minside) / (float)viawidth; + squaresf *= ExtCurStyle->exts_unitsPerLambda; + squaresf /= (float)viawidth; + squaresx = (int)squaresf; + squaresx++; + + squaresf = (float)(contact->cp_height - minside) / (float)viawidth; + squaresf *= ExtCurStyle->exts_unitsPerLambda; + squaresf /= (float)viawidth; + squaresy = (int)squaresf; + squaresy++; + } + for (tilenum=0; tilenum < contact->cp_currentcontact; tilenum++) + { + int x = contact->cp_center.p_x; + int y = contact->cp_center.p_y; + Tile *tile = contact->cp_tile[tilenum]; + + resptr = (resNode *) mallocMagic((unsigned) (sizeof(resNode))); + InitializeNode(resptr,x,y,RES_NODE_CONTACT); + ResAddToQueue(resptr,nodes); + + /* add contact pointer to node */ + + ccell = (cElement *) mallocMagic((unsigned) (sizeof(cElement))); + ccell->ce_nextc = resptr->rn_ce; + resptr->rn_ce = ccell; + ccell->ce_thisc = contact; + + contact->cp_cnode[tilenum] = resptr; + NEWBREAK(resptr, tile, contact->cp_center.p_x, + contact->cp_center.p_y, &contact->cp_rect); + + /* add resistors here */ + + if (tilenum > 0) + { + resistor = (resResistor *) mallocMagic((unsigned) (sizeof(resResistor))); + resistor->rr_nextResistor = (*resList); + resistor->rr_lastResistor = NULL; + if ((*resList) != NULL) (*resList)->rr_lastResistor = resistor; + (*resList) = resistor; + resistor->rr_connection1 = contact->cp_cnode[tilenum-1]; + resistor->rr_connection2 = contact->cp_cnode[tilenum]; + + element = (resElement *) mallocMagic((unsigned) (sizeof(resElement))); + element->re_nextEl = contact->cp_cnode[tilenum-1]->rn_re; + element->re_thisEl = resistor; + contact->cp_cnode[tilenum-1]->rn_re = element; + element = (resElement *) mallocMagic((unsigned)(sizeof(resElement))); + element->re_nextEl = contact->cp_cnode[tilenum]->rn_re; + element->re_thisEl = resistor; + contact->cp_cnode[tilenum]->rn_re = element; + + /* Need to figure out how to handle the multiple nodes */ + /* and multiple resistors necessary to determine the */ + /* correct geometry for the geometry extractor. For */ + /* now, extract as one big glob. */ + + /* rr_cl doesn't need to represent centerline; use for */ + /* # squares in y direction instead; use rr_width for */ + /* # squares in x direction. */ + + resistor->rr_cl = squaresy; + resistor->rr_width = squaresx; + resistor->rr_value = + ExtCurStyle->exts_viaResist[contact->cp_type] / + (squaresx * squaresy); +#ifdef ARIEL + resistor->rr_csArea = + ExtCurStyle->exts_thick[contact->cp_type] / + (squaresx * squaresy); +#endif + resistor->rr_tt = contact->cp_type; + resistor->rr_float.rr_area= 0; + resistor->rr_status = 0; + } + } + } +} + +/* + *------------------------------------------------------------------------- + * + *------------------------------------------------------------------------- + */ + +void +ResSortBreaks(masterlist, xsort) + Breakpoint **masterlist; + int xsort; +{ + Breakpoint *p1, *p2, *p3, *p4; + bool changed; + + changed = TRUE; + while (changed == TRUE) + { + changed = FALSE; + p1 = NULL; + p2 = *masterlist; + p3 = p2->br_next; + while (p3 != NULL) + { + if (xsort == TRUE && p2->br_loc.p_x > p3->br_loc.p_x || + xsort == FALSE && p2->br_loc.p_y > p3->br_loc.p_y) + { + changed = TRUE; + if (p1 == NULL) + { + *masterlist = p3; + } + else + { + p1->br_next = p3; + } + p2->br_next = p3->br_next; + p3->br_next = p2; + p4 = p2; + p2 = p3; + p3 = p4; + } + else + { + p1 = p2; + p2 = p3; + p3 = p3->br_next; + } + } + } +} + diff --git a/resis/ResMerge.c b/resis/ResMerge.c new file mode 100644 index 00000000..8e619330 --- /dev/null +++ b/resis/ResMerge.c @@ -0,0 +1,1064 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResMerge.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "resis/resis.h" + +TileTypeBitMask ResNoMergeMask[NT]; + +/* Forward declarations */ + +extern void ResMergeNodes(); +extern void ResDeleteResPointer(); +extern void ResEliminateResistor(); +extern void ResCleanNode(); +extern void ResFixBreakPoint(); + + +/* + *------------------------------------------------------------------------- + * + * ResDoneWithNode--After all connections to node are made, ResDoneWithNode + * is called. It checks for parallel, series, loop, triangle, + * and single conections, and simplifies the network where possible. + * + * Results: none + * + * Side Effects: deletes resistors and/or nodes. + * + *------------------------------------------------------------------------- + */ + +void +ResDoneWithNode(resptr) + resNode *resptr; + +{ + int status; + resNode *resptr2; + resElement *rcell1; + resResistor *rr1; + + resptr2 = NULL; + resptr->rn_status |= TRUE; + status = UNTOUCHED; + + /* are there any resistors? */ + + if (resptr->rn_re == NULL) + { + return; + } + + /* Special handling for geometry option */ + + if (ResOptionsFlags & ResOpt_Geometry) return; + + /* Eliminate resistors with connections to one terminal and */ + /* resistors with value 0. */ + + for (rcell1 = resptr->rn_re; rcell1 != NULL; rcell1 = rcell1->re_nextEl) + { + rr1 = rcell1->re_thisEl; + if (rr1->rr_connection1 == rr1->rr_connection2) + { + ResDeleteResPointer(resptr,rr1); + ResDeleteResPointer(resptr,rr1); + resptr->rn_float.rn_area += rr1->rr_float.rr_area; + ResEliminateResistor(rr1,&ResResList); + status = LOOP; + ResDoneWithNode(resptr); + break; + + } + else if (rr1->rr_value == 0) + { + ResDeleteResPointer(rr1->rr_connection1,rr1); + ResDeleteResPointer(rr1->rr_connection2,rr1); + if (rr1->rr_connection1 == resptr) + { + resptr2 = rr1->rr_connection2; + }else + { + resptr2 = rr1->rr_connection1; + } + ResMergeNodes(resptr2,resptr,&ResNodeQueue,&ResNodeList); + resptr2->rn_float.rn_area += rr1->rr_float.rr_area; + ResEliminateResistor(rr1,&ResResList); + if ((resptr2->rn_status & TRUE) == TRUE) + { + resptr2->rn_status &= ~TRUE; + ResDoneWithNode(resptr2); + } + resptr2 = NULL; + status = SINGLE; + break; + } + } + + /* Eliminations that can be only if there are no transistors connected */ + /* to node. Series and dangling connections fall in this group. */ + + if ((resptr->rn_te == NULL) && (resptr->rn_why != RES_NODE_ORIGIN) + && (status == UNTOUCHED)) + { + status = ResSeriesCheck(resptr); + } + if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN)) + { + status = ResParallelCheck(resptr); + } + if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN)) + { + status = ResTriangleCheck(resptr); + } +} + + +/* + *------------------------------------------------------------------------ + * + * ResFixRes-- + * + * Results: none + * + * Side Effects: ResFixRes combines two resistors in series. the second + * Resistor is eliminated. Resptr is the node that is "cut out" of the + * network. + * + *------------------------------------------------------------------------ + */ + +void +ResFixRes(resptr,resptr2,resptr3,elimResis,newResis) + resNode *resptr,*resptr2,*resptr3; + resResistor *elimResis, *newResis; + +{ + resElement *thisREl; + + resptr3->rn_float.rn_area += newResis->rr_value*resptr->rn_float.rn_area/((float)(newResis->rr_value+elimResis->rr_value)); + resptr2->rn_float.rn_area += elimResis->rr_value*resptr->rn_float.rn_area/((float)(newResis->rr_value+elimResis->rr_value)); + newResis->rr_value += elimResis->rr_value; + ASSERT(newResis->rr_value > 0,"series"); + newResis->rr_float.rr_area += elimResis->rr_float.rr_area; +#ifdef ARIEL + if (elimResis->rr_csArea && elimResis->rr_csArea < newResis->rr_csArea || newResis->rr_csArea == 0) + { + newResis->rr_csArea = elimResis->rr_csArea; + newResis->rr_tt = elimResis->rr_tt; + } +#endif + for (thisREl = resptr3->rn_re; (thisREl != NULL); thisREl = thisREl->re_nextEl) + { + if (thisREl->re_thisEl == elimResis) + { + (thisREl->re_thisEl = newResis); + break; + } + + } + if (thisREl == NULL) TxError("Resistor not found in duo\n"); + ResDeleteResPointer(resptr,elimResis); + ResDeleteResPointer(resptr,newResis); + ResEliminateResistor(elimResis, &ResResList); + ResCleanNode(resptr, TRUE,&ResNodeList,&ResNodeQueue); +} + +/* + *------------------------------------------------------------------------ + * + * ResFixParallel-- + * + * Results: none + * + * Side Effects: ResFixParallel combines two resistors in parallel. T + * The second Resistor is eliminated. + * + * + *------------------------------------------------------------------------ + */ + +void +ResFixParallel(elimResis,newResis) + resResistor *elimResis,*newResis; + +{ + if ((newResis->rr_value+elimResis->rr_value) != 0) + { + newResis->rr_value = (((float) newResis->rr_value)* + ((float)elimResis->rr_value))/ + ((float)(newResis->rr_value+ + elimResis->rr_value)); + ASSERT(newResis->rr_value >= 0,"parallel"); + } + else + { + newResis->rr_value =0; + } + newResis->rr_float.rr_area += elimResis->rr_float.rr_area; +#ifdef ARIEL + newResis->rr_csArea += elimResis->rr_csArea; +#endif + ResDeleteResPointer(elimResis->rr_connection1,elimResis); + ResDeleteResPointer(elimResis->rr_connection2,elimResis); + ResEliminateResistor(elimResis,&ResResList); +} + +/* + *------------------------------------------------------------------------- + * + * ResSeriesCheck -- for nodes with no transistors, sees if a series + or loop combination is possible. + * + * Results: returns SINGLE,LOOP,or SERIES if succesful. + * + * Side Effects: may delete some nodes and resistors. + * + *------------------------------------------------------------------------- + */ + +int +ResSeriesCheck(resptr) + resNode *resptr; + +{ + resResistor *rr1,*rr2; + resNode *resptr2,*resptr3; + int status=UNTOUCHED; + resElement *res_next; + + rr1 = resptr->rn_re->re_thisEl; + res_next = resptr->rn_re->re_nextEl; + + if (res_next == NULL) + /* node with only one connection */ + { + resptr2 = (rr1->rr_connection1 == resptr)?rr1->rr_connection2: + rr1->rr_connection1; + + ResDeleteResPointer(rr1->rr_connection1,rr1); + ResDeleteResPointer(rr1->rr_connection2,rr1); + resptr2->rn_float.rn_area += rr1->rr_float.rr_area+ + resptr->rn_float.rn_area; + ResEliminateResistor(rr1,&ResResList); + ResCleanNode(resptr,TRUE,&ResNodeList,&ResNodeQueue); + status = SINGLE; + if (resptr2->rn_status & TRUE) + { + resptr2->rn_status &= ~TRUE; + ResDoneWithNode(resptr2); + } + resptr2 = NULL; + } + else if (res_next->re_nextEl == NULL) + { + rr2 = res_next->re_thisEl; + if (!TTMaskHasType(ResNoMergeMask+rr1->rr_tt,rr2->rr_tt)) + { + if (rr1->rr_connection1 == resptr) + { + + if (rr2->rr_connection1 == resptr) + { + resptr2 = rr1->rr_connection2; + if (rr1->rr_connection2 == + rr2->rr_connection2) + { + status = LOOP; + ResDeleteResPointer(rr1->rr_connection1,rr1); + ResDeleteResPointer(rr1->rr_connection2,rr1); + ResDeleteResPointer(rr2->rr_connection1,rr2); + ResDeleteResPointer(rr2->rr_connection2,rr2); + resptr2->rn_float.rn_area += rr1->rr_float.rr_area + + rr2->rr_float.rr_area + + resptr->rn_float.rn_area; + ResEliminateResistor(rr1,&ResResList); + ResEliminateResistor(rr2,&ResResList); + ResCleanNode(resptr,TRUE,&ResNodeList,&ResNodeQueue); + }else + { + status = SERIES; + resptr3 = rr2->rr_connection2; + rr1->rr_connection1 = rr2->rr_connection2; + ResFixRes(resptr,resptr2,resptr3,rr2,rr1); + } + if ((resptr2->rn_status & TRUE) == TRUE) + { + resptr2->rn_status &= ~TRUE; + ResDoneWithNode(resptr2); + } + resptr2 = NULL; + }else + { + resptr2 = rr1->rr_connection2; + if (rr1->rr_connection2 == rr2->rr_connection1) + { + status = LOOP; + ResDeleteResPointer(rr1->rr_connection1,rr1); + ResDeleteResPointer(rr1->rr_connection2,rr1); + ResDeleteResPointer(rr2->rr_connection1,rr2); + ResDeleteResPointer(rr2->rr_connection2,rr2); + resptr2->rn_float.rn_area += rr1->rr_float.rr_area + + rr2->rr_float.rr_area + + resptr->rn_float.rn_area; + ResEliminateResistor(rr1,&ResResList); + ResEliminateResistor(rr2,&ResResList); + ResCleanNode(resptr,TRUE,&ResNodeList,&ResNodeQueue); + }else + { + status = SERIES; + resptr3 = rr2->rr_connection1; + rr1->rr_connection1 = rr2->rr_connection1; + ResFixRes(resptr,resptr2,resptr3,rr2,rr1); + } + if ((resptr2->rn_status & TRUE) == TRUE) + { + resptr2->rn_status &= ~TRUE; + ResDoneWithNode(resptr2); + } + resptr2 = NULL; + } + }else + { + if (rr2->rr_connection1 == resptr) + { + resptr2 = rr1->rr_connection1; + if (rr1->rr_connection1 == rr2->rr_connection2) + { + status = LOOP; + ResDeleteResPointer(rr1->rr_connection1,rr1); + ResDeleteResPointer(rr1->rr_connection2,rr1); + ResDeleteResPointer(rr2->rr_connection1,rr2); + ResDeleteResPointer(rr2->rr_connection2,rr2); + resptr2->rn_float.rn_area += rr1->rr_float.rr_area + + rr2->rr_float.rr_area + + resptr->rn_float.rn_area; + ResEliminateResistor(rr1,&ResResList); + ResEliminateResistor(rr2,&ResResList); + ResCleanNode(resptr,TRUE,&ResNodeList,&ResNodeQueue); + }else + { + status = SERIES; + resptr3 = rr2->rr_connection2; + rr1->rr_connection2 = + rr2->rr_connection2; + ResFixRes(resptr,resptr2,resptr3,rr2,rr1); + } + if ((resptr2->rn_status & TRUE) == TRUE) + { + resptr2->rn_status &= ~TRUE; + ResDoneWithNode(resptr2); + } + resptr2 = NULL; + }else + { + resptr2 = rr1->rr_connection1; + if (rr1->rr_connection1 == rr2->rr_connection1) + { + status = LOOP; + ResDeleteResPointer(rr1->rr_connection1,rr1); + ResDeleteResPointer(rr1->rr_connection2,rr1); + ResDeleteResPointer(rr2->rr_connection1,rr2); + ResDeleteResPointer(rr2->rr_connection2,rr2); + resptr2->rn_float.rn_area += rr1->rr_float.rr_area + + rr2->rr_float.rr_area + + resptr->rn_float.rn_area; + ResEliminateResistor(rr1,&ResResList); + ResEliminateResistor(rr2,&ResResList); + ResCleanNode(resptr,TRUE,&ResNodeList,&ResNodeQueue); + }else + { + status = SERIES; + resptr3 = rr2->rr_connection1; + rr1->rr_connection2 = + rr2->rr_connection1; + ResFixRes(resptr,resptr2,resptr3,rr2,rr1); + } + if ((resptr2->rn_status & TRUE) == TRUE) + { + resptr2->rn_status &= ~TRUE; + ResDoneWithNode(resptr2); + } + resptr2 = NULL; + } + } + } + } + return status; +} + + +/* + *------------------------------------------------------------------------- + * + * ResParallelCheck -- tries to do parallel combinations of transistors. + * + * Results: returns PARALLEL if successful + * + * Side Effects: may delete resistors and nodes. + * + *------------------------------------------------------------------------- + */ + +int +ResParallelCheck(resptr) + resNode *resptr; + +{ + resResistor *r1,*r2; + resNode *resptr2,*resptr3; + int status=UNTOUCHED; + resElement *rcell1,*rcell2; + + + for (rcell1 = resptr->rn_re; + rcell1->re_nextEl != NULL; rcell1 = rcell1->re_nextEl) + { + r1 = rcell1->re_thisEl; + + for (rcell2 = rcell1->re_nextEl; + rcell2 != NULL; rcell2 = rcell2->re_nextEl) + + { + r2 = rcell2->re_thisEl; + if (TTMaskHasType(ResNoMergeMask+r1->rr_tt,r2->rr_tt)) continue; + if (((r1->rr_connection1 == r2->rr_connection1) && + (r1->rr_connection2 == r2->rr_connection2))|| + ((r1->rr_connection1 == r2->rr_connection2) && + (r1->rr_connection2 == r2->rr_connection1))) + { + resptr3 = (r1->rr_connection1 == resptr) ? + r1->rr_connection2 : r1->rr_connection1; + ResFixParallel(r1,r2); + status = PARALLEL; + resptr2 = NULL; + if (resptr3->rn_status & TRUE) + { + resptr2 = resptr3; + resptr2->rn_status &= ~TRUE; + } + ResDoneWithNode(resptr); + if (resptr2 != NULL) ResDoneWithNode(resptr2); + break; + } + } + if (status == PARALLEL) break; + } + return status; +} + + +/* + *------------------------------------------------------------------------- + * + * ResTriangleCheck -- looks for places to do the traingle-to-Y conversion. + * + * Results: returns TRIANGLE if successful. + * + * Side Effects: may allocate a new node. + * + *------------------------------------------------------------------------- + */ + +int +ResTriangleCheck(resptr) + resNode *resptr; + +{ + resResistor *rr1,*rr2,*rr3; + int status=UNTOUCHED; + float r1,r2,r3,denom; + resNode *n1,*n2,*n3; + resElement *rcell1,*rcell2,*rcell3,*element; + + for (rcell1 = resptr->rn_re; + rcell1->re_nextEl != NULL; rcell1 = rcell1->re_nextEl) + { + rr1 = rcell1->re_thisEl; + n1 = (rr1->rr_connection1 == resptr)?rr1->rr_connection2: + rr1->rr_connection1; + + for (rcell2 = rcell1->re_nextEl; + rcell2 != NULL; rcell2 = rcell2->re_nextEl) + { + rr2 = rcell2->re_thisEl; + if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr2->rr_tt)) + continue; + n2 = (rr2->rr_connection1 == resptr) ? rr2->rr_connection2 : + rr2->rr_connection1; + for (rcell3 = n1->rn_re; + rcell3 != NULL; rcell3 = rcell3->re_nextEl) + { + rr3 = rcell3->re_thisEl; + if (TTMaskHasType(ResNoMergeMask+rr1->rr_tt,rr3->rr_tt)) + continue; + if (TTMaskHasType(ResNoMergeMask+rr2->rr_tt,rr3->rr_tt)) + continue; + + if (((rr3->rr_connection1 != n1) || + (rr3->rr_connection2 != n2)) && + ((rr3->rr_connection2 != n1) || + (rr3->rr_connection1 != n2))) continue; + + status = TRIANGLE; + if ((denom=rr1->rr_value+rr2->rr_value+rr3->rr_value) != 0.0) + { + denom = 1.0/denom; + /*calculate new values for resistors */ + r1 = (((float) rr1->rr_value)* + ((float) rr2->rr_value))*denom; + + r2 = (((float) rr2->rr_value)* + ((float) rr3->rr_value))*denom; + + r3 = (((float) rr1->rr_value)* + ((float) rr3->rr_value))*denom; + + rr1->rr_value = r1+0.5; + rr2->rr_value = r2+0.5; + rr3->rr_value = r3+0.5; + ASSERT(rr1->rr_value >= 0,"Triangle"); + ASSERT(rr2->rr_value >= 0,"Triangle"); + ASSERT(rr3->rr_value >= 0,"Triangle"); + } + else + { + rr1->rr_value = 0; + rr2->rr_value = 0; + rr3->rr_value = 0; + } + n3 = (resNode *) mallocMagic((unsigned) (sizeof(resNode))); + /* Where should the new node be `put'? It */ + /* is arbitrarily assigned to the location */ + /* occupied by the first node. */ + + InitializeNode(n3,resptr->rn_loc.p_x,resptr->rn_loc.p_y,TRIANGLE); + n3->rn_status = FINISHED | TRUE | MARKED; + + n3->rn_less = NULL; + n3->rn_more = ResNodeList; + ResNodeList->rn_less = n3; + ResNodeList = n3; + if (resptr == rr1->rr_connection1) + { + ResDeleteResPointer(rr1->rr_connection2,rr1); + rr1->rr_connection2 = n3; + } + else + { + ResDeleteResPointer(rr1->rr_connection1,rr1); + rr1->rr_connection1 = n3; + } + if (n2 == rr2->rr_connection1) + { + ResDeleteResPointer(rr2->rr_connection2,rr2); + rr2->rr_connection2 = n3; + } + else + { + ResDeleteResPointer(rr2->rr_connection1,rr2); + rr2->rr_connection1 = n3; + } + if (n1 == rr3->rr_connection1) + { + ResDeleteResPointer(rr3->rr_connection2,rr3); + rr3->rr_connection2 = n3; + } + else + { + ResDeleteResPointer(rr3->rr_connection1,rr3); + rr3->rr_connection1 = n3; + } + element = (resElement *) mallocMagic((unsigned)(sizeof(resElement))); + element->re_nextEl = NULL; + element->re_thisEl = rr1; + n3->rn_re = element; + element = (resElement *) mallocMagic((unsigned)(sizeof(resElement))); + element->re_nextEl = n3->rn_re; + element->re_thisEl = rr2; + n3->rn_re = element; + element = (resElement *) mallocMagic((unsigned)(sizeof(resElement))); + element->re_nextEl = n3->rn_re; + element->re_thisEl = rr3; + n3->rn_re = element; + if ((n1->rn_status & TRUE) == TRUE) + { + n1->rn_status &= ~TRUE; + } + else + { + n1 = NULL; + } + if ((n2->rn_status & TRUE) == TRUE) + { + n2->rn_status &= ~TRUE; + } + else + { + n2 = NULL; + } + ResDoneWithNode(resptr); + if (n1 != NULL) ResDoneWithNode(n1); + if (n2 != NULL) ResDoneWithNode(n2); + break; + } + if (status == TRIANGLE) break; + } + if (status == TRIANGLE) break; + } + return status; +} + +/* + *-------------------------------------------------------------------------- + * + * ResMergeNodes-- + * + * results: none + * + * side effects: appends all the cElement, jElement, tElement and + * resElement structures from node 2 onto node 1. Node 2 is + * then eliminated. + * + *--------------------------------------------------------------------------- + */ + +void +ResMergeNodes(node1,node2,pendingList,doneList) + resNode *node1,*node2,**pendingList,**doneList; + + { + resElement *workingRes,*tRes; + tElement *workingFet,*tFet; + jElement *workingJunc,*tJunc; + cElement *workingCon,*tCon; + Tile *tile; + int i; + + /* sanity check */ + if (node1 == node2) return; + if (node1 == NULL || node2 == NULL) + { + TxError("Attempt to merge NULL node\n"); + return; + } + + /* don't want to merge away startpoint */ + if (node2->rn_why & RES_NODE_ORIGIN) + { + node1->rn_why = RES_NODE_ORIGIN; + } + + /* set node resistance */ + if (node1->rn_noderes >node2->rn_noderes) + { + node1->rn_noderes = node2->rn_noderes; + if ((node1->rn_status & FINISHED) != FINISHED) + { + ResRemoveFromQueue(node1,pendingList); + ResAddToQueue(node1,pendingList); + } + } + node1->rn_float.rn_area += node2->rn_float.rn_area; + + + /* combine relevant flags */ + node1->rn_status |= (node2->rn_status & RN_MAXTDI); + + /*merge transistor lists */ + workingFet = node2->rn_te; + while (workingFet != NULL) + { + if (workingFet->te_thist->rt_status & RES_TRAN_PLUG) + { + ResPlug *plug = (ResPlug *) workingFet->te_thist; + if (plug->rpl_node == node2) + { + plug->rpl_node = node1; + } + else + { + TxError("Bad plug node: is (%d %d), should be (%d %d)\n", + plug->rpl_node->rn_loc,node2->rn_loc); + plug->rpl_node = NULL; + } + } + else + { + + int j; + + for (j=0;j!= RT_TERMCOUNT;j++) + if (workingFet->te_thist->rt_terminals[j] == node2) + { + workingFet->te_thist->rt_terminals[j] = node1; + } + } + tFet = workingFet; + workingFet = workingFet->te_nextt; + tFet->te_nextt = node1->rn_te; + node1->rn_te = tFet; + } + + /* append junction lists */ + workingJunc = node2->rn_je; + while (workingJunc != NULL) + { + tJunc = workingJunc; + for (i=0; ije_thisj->rj_Tile[i]; + junk = (tileJunk *) tile->ti_client; + + if ((junk->tj_status & RES_TILE_DONE) == FALSE) + { + ResFixBreakPoint(&junk->breakList,node2,node1); + } + } + tJunc->je_thisj->rj_jnode = node1; + workingJunc = workingJunc->je_nextj; + tJunc->je_nextj = node1->rn_je; + node1->rn_je = tJunc; + } + + /* Append connection lists */ + workingCon = node2->rn_ce; + while (workingCon != NULL) + { + tCon = workingCon; + for (i=0; i ce_thisc->cp_currentcontact;i++) + { + if (workingCon->ce_thisc->cp_cnode[i] == node2) + { + tileJunk *junk; + + workingCon->ce_thisc->cp_cnode[i] = node1; + tile =tCon->ce_thisc->cp_tile[i]; + junk = (tileJunk *) tile->ti_client; + if ((junk->tj_status & RES_TILE_DONE) == FALSE) + { + ResFixBreakPoint(&junk->breakList,node2,node1); + } + } + } + workingCon = workingCon->ce_nextc; + tCon->ce_nextc = node1->rn_ce; + node1->rn_ce = tCon; + } + + /* Moves resistors to new node */ + workingRes = node2->rn_re; + while (workingRes != NULL) + { + if (workingRes->re_thisEl->rr_connection1 == node2) + { + workingRes->re_thisEl->rr_connection1 = node1; + } + else if (workingRes->re_thisEl->rr_connection2 == node2) + { + workingRes->re_thisEl->rr_connection2 = node1; + } + else + { + TxError("Resistor not found.\n"); + } + tRes = workingRes; + workingRes = workingRes->re_nextEl; + tRes->re_nextEl = node1->rn_re; + node1->rn_re = tRes; + } + if ((node2->rn_status & FINISHED) == FINISHED) + { + ResRemoveFromQueue(node2,doneList); + } + else + { + ResRemoveFromQueue(node2,pendingList); + } + if (node2->rn_client != (ClientData)NULL) + { + freeMagic((char *)node2->rn_client); + node2->rn_client = (ClientData)NULL; + } + { + node2->rn_re = (resElement *) CLIENTDEFAULT; + node2->rn_ce = (cElement *) CLIENTDEFAULT; + node2->rn_je = (jElement *) CLIENTDEFAULT; + node2->rn_te = (tElement *) CLIENTDEFAULT; + node2->rn_more = (resNode *) CLIENTDEFAULT; + node2->rn_less = (resNode *) CLIENTDEFAULT; + } + freeMagic((char *)node2); + } + + +/* + *------------------------------------------------------------------------- + * + * ResDeleteResPointer-- Deletes the pointer from a node to a resistor. + * Used when a resistor is deleted. + * + * Results:none + * + * Side Effects: Modifies a node's resistor list. + * + *------------------------------------------------------------------------- + */ + +void +ResDeleteResPointer(node,resistor) + resNode *node; + resResistor *resistor; + +{ + resElement *rcell1,*rcell2; + int notfound=TRUE; + + rcell1 = NULL; + rcell2 = node->rn_re; + while (rcell2 != NULL) + { + if (rcell2->re_thisEl == resistor) + { + notfound=FALSE; + if (rcell1 != NULL) + { + rcell1->re_nextEl = rcell2->re_nextEl; + }else + { + node->rn_re = rcell2->re_nextEl; + } + /* Set fields to null just in case there are any stray */ + /* pointers to structure. */ + rcell2->re_thisEl = NULL; + rcell2->re_nextEl = NULL; + freeMagic((char *)rcell2); + break; + } + rcell1 = rcell2; + rcell2 = rcell2->re_nextEl; + } + if (notfound) + { + TxError("Missing rptr at (%d %d).\n", + node->rn_loc.p_x,node->rn_loc.p_y); + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResEliminateResistor-- + * + * Results:none + * + * Side Effects: Deletes a resistor. Does not delete pointers from nodes to + * resistor. + * + *------------------------------------------------------------------------- + */ + +void +ResEliminateResistor(resistor,homelist) + resResistor *resistor,**homelist; + +{ + if (resistor->rr_lastResistor == NULL) + { + *homelist = resistor->rr_nextResistor; + }else + { + resistor->rr_lastResistor->rr_nextResistor = resistor->rr_nextResistor; + } + if (resistor->rr_nextResistor != NULL) + { + resistor->rr_nextResistor->rr_lastResistor = resistor->rr_lastResistor; + } + + /* set everything to null so that any stray pointers will cause */ + /* immediate death instead of a slow lingering one. */ + resistor->rr_nextResistor = NULL; + resistor->rr_lastResistor = NULL; + resistor->rr_connection1 = NULL; + resistor->rr_connection2 = NULL; + freeMagic((char *)resistor); +} + + +/* + *------------------------------------------------------------------------- + * + * ResCleanNode--removes the linked lists of junctions and contacts after + * they are no longer needed. If the 'junk' option is used, + * the node is eradicated. + * + * Results: + * None. + * + * Side Effects: frees memory + * + *------------------------------------------------------------------------- + */ + +void +ResCleanNode(resptr,junk,homelist1,homelist2) + resNode *resptr; + int junk; + resNode **homelist1; + resNode **homelist2; +{ + resElement *rcell; + cElement *ccell; + jElement *jcell; + tElement *tcell; + + /* free up contact and junction lists */ + while (resptr->rn_ce != NULL) + { + ccell = resptr->rn_ce; + resptr->rn_ce = resptr->rn_ce->ce_nextc; + freeMagic((char *)ccell); + } + while (resptr->rn_je != NULL) + { + jcell = resptr->rn_je; + resptr->rn_je = resptr->rn_je->je_nextj; + freeMagic((char *)jcell->je_thisj); + freeMagic((char *)jcell); + } + if (junk == TRUE) + { + if (resptr->rn_client != (ClientData)NULL) + { + freeMagic((char *)resptr->rn_client); + resptr->rn_client = (ClientData)NULL; + } + while (resptr->rn_te != NULL) + { + tcell = resptr->rn_te; + resptr->rn_te = resptr->rn_te->te_nextt; + freeMagic((char *)tcell); + } + while (resptr->rn_re != NULL) + { + rcell = resptr->rn_re; + resptr->rn_re = resptr->rn_re->re_nextEl; + freeMagic((char *)rcell); + } + if (resptr->rn_less != NULL) + { + resptr->rn_less->rn_more = resptr->rn_more; + }else + { + if (*homelist1 == resptr) + { + *homelist1 = resptr->rn_more; + } + else if (*homelist2 == resptr) + { + *homelist2 = resptr->rn_more; + } + else + { + TxError("Error: Attempted to eliminate node from wrong list.\n"); + } + } + if (resptr->rn_more != NULL) + { + resptr->rn_more->rn_less = resptr->rn_less; + } + + { + resptr->rn_re = (resElement *) CLIENTDEFAULT; + resptr->rn_ce = (cElement *) CLIENTDEFAULT; + resptr->rn_je = (jElement *) CLIENTDEFAULT; + resptr->rn_te = (tElement *) CLIENTDEFAULT; + resptr->rn_more = (resNode *) CLIENTDEFAULT; + resptr->rn_less = (resNode *) CLIENTDEFAULT; + } + freeMagic((char *)resptr); + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResFixBreakPoint--moves breakpoints from one node to another, checking + * first to see whether the target node already has the breakpoint. + * Used when nodes are merged. + * + * Results: none + * + * Side Effects: may free up memory if breakpoint is already present. + * + *------------------------------------------------------------------------- + */ + +void +ResFixBreakPoint(sourcelist,origNode,newNode) + Breakpoint **sourcelist; + resNode *origNode,*newNode; + +{ + Breakpoint *bp,*bp2,*bp3,*bp4; + int alreadypresent; + + alreadypresent = FALSE; + for (bp4 = *sourcelist; bp4 != NULL; bp4 = bp4->br_next) + { + if (bp4->br_this == newNode) + { + alreadypresent = TRUE; + break; + } + } + bp2 = NULL; + bp = *sourcelist; + while (bp != NULL) + { + if (bp->br_this == origNode) + { + if (alreadypresent) + { + if (bp2 == NULL) + { + *sourcelist = bp->br_next; + }else + { + bp2->br_next = bp->br_next; + } + bp3 = bp; + bp = bp->br_next; + + if (bp3->br_crect != NULL && bp4->br_crect == NULL) + { + bp4->br_crect = bp3->br_crect; + } + freeMagic((char *)bp3); + continue; + }else + { + (bp->br_this = newNode); + } + } + bp2 = bp; + bp = bp->br_next; + } + +} diff --git a/resis/ResPrint.c b/resis/ResPrint.c new file mode 100644 index 00000000..0c93cfcd --- /dev/null +++ b/resis/ResPrint.c @@ -0,0 +1,730 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResPrint.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/utils.h" +#include "cif/cif.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "utils/stack.h" +#include "utils/styles.h" +#include "resis/resis.h" + +#define MAXNAME 1000 +#define KV_TO_mV 1000000 + +extern ResSimNode *ResInitializeNode(); + + +/* + *------------------------------------------------------------------------- + * + * ResPrintExtRes-- Print resistor network to output file. + * + * Results:none + * + * Side Effects:prints network. + * + *------------------------------------------------------------------------- + */ + +void +ResPrintExtRes(outextfile,resistors,nodename) + FILE *outextfile; + resResistor *resistors; + char *nodename; + +{ + int nodenum=0; + char newname[MAXNAME]; + HashEntry *entry; + ResSimNode *node,*ResInitializeNode(); + + for (; resistors != NULL; resistors=resistors->rr_nextResistor) + { + /* + These names shouldn't be null; they should either be set by + the transistor name or by the node printing routine. This + code is included in case the resistor network is printed + before the nodes. + */ + if (resistors->rr_connection1->rn_name == NULL) + { + (void)sprintf(newname,"%s%s%d",nodename,".r",nodenum++); + entry = HashFind(&ResNodeTable,newname); + node = ResInitializeNode(entry); + resistors->rr_connection1->rn_name = node->name; + node->oldname = nodename; + } + if (resistors->rr_connection2->rn_name == NULL) + { + (void)sprintf(newname,"%s%s%d",nodename,".r",nodenum++); + entry = HashFind(&ResNodeTable,newname); + node = ResInitializeNode(entry); + resistors->rr_connection2->rn_name = node->name; + node->oldname = nodename; + } + if (ResOptionsFlags & ResOpt_DoExtFile) + { + fprintf(outextfile, "resist \"%s\" \"%s\" %d\n", + resistors->rr_connection1->rn_name, + resistors->rr_connection2->rn_name, + (int) (resistors->rr_value/ExtCurStyle->exts_resistScale)); + } + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResPrintExtTran-- Print out all transistors that have had at least + * one terminal changed. + * + * Results:none + * + * Side Effects:prints transistor lines to output file + * + *------------------------------------------------------------------------- + */ + +void +ResPrintExtTran(outextfile, transistors) + FILE *outextfile; + RTran *transistors; +{ + TileType t; + char *subsName; + + for (; transistors != NULL; transistors = transistors->nextTran) + { + if (transistors->status & TRUE) + { + if (ResOptionsFlags & ResOpt_DoExtFile) + { + t = transistors->layout->rt_trantype; + subsName = ExtCurStyle->exts_transSubstrateName[t]; + +#ifdef MAGIC_WRAPPER + /* Substrate variable name substitution */ + if (subsName && subsName[0] == '$' && subsName[1] != '$') + { + char *varsub = (char *)Tcl_GetVar(magicinterp, &subsName[1], + TCL_GLOBAL_ONLY); + if (varsub != NULL) subsName = varsub; + } +#endif + + /* Output according to device type */ + + /* fet type xl yl xh yh area perim sub gate t1 t2 */ + fprintf(outextfile,"fet %s %d %d %d %d %d %d " + "%s \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n", + ExtCurStyle->exts_transName[t], + transistors->layout->rt_inside.r_ll.p_x, + transistors->layout->rt_inside.r_ll.p_y, + transistors->layout->rt_inside.r_ll.p_x + 1, + transistors->layout->rt_inside.r_ll.p_y + 1, + transistors->layout->rt_area, + transistors->layout->rt_perim, + subsName, + transistors->gate->name, + transistors->layout->rt_length * 2, + transistors->rs_gattr, + transistors->source->name, + transistors->layout->rt_width, + transistors->rs_sattr, + transistors->drain->name, + transistors->layout->rt_width, + transistors->rs_dattr); + } + } + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResPrintExtNode-- Prints out all the nodes in the extracted net. + * + * Results:none + * + * Side Effects: Prints out extracted net. It may add new nodes to the + * node hash table. + * + *------------------------------------------------------------------------- + */ + +void +ResPrintExtNode(outextfile, nodelist, nodename) + FILE *outextfile; + resNode *nodelist; + char *nodename; + +{ + int nodenum=0; + char newname[MAXNAME],tmpname[MAXNAME],*cp; + HashEntry *entry; + ResSimNode *node,*ResInitializeNode(); + bool DoKillNode = TRUE; + resNode *snode = nodelist; + + /* If any of the subnode names match the original node name, then */ + /* we don't want to rip out that node with a "killnode" statement. */ + + for (; nodelist != NULL; nodelist = nodelist->rn_more) + if (nodelist->rn_name != NULL) + if (!strcmp(nodelist->rn_name, nodename)) + { + DoKillNode = FALSE; + break; + } + + if ((ResOptionsFlags & ResOpt_DoExtFile) && DoKillNode) + { + fprintf(outextfile,"killnode \"%s\"\n",nodename); + } + + /* Create "rnode" entries for each subnode */ + + for (; snode != NULL; snode = snode->rn_more) + { + if (snode->rn_name == NULL) + { + (void)sprintf(tmpname,"%s",nodename); + + cp = tmpname + strlen(tmpname) - 1; + if (*cp == '!' || *cp == '#') *cp = '\0'; + + (void)sprintf(newname,"%s%s%d",tmpname,".n",nodenum++); + entry = HashFind(&ResNodeTable,newname); + node = ResInitializeNode(entry); + snode->rn_name = node->name; + node->oldname = nodename; + } + + if (ResOptionsFlags & ResOpt_DoExtFile) + { + /* rnode name R C x y type (R is always 0) */ + fprintf(outextfile, "rnode \"%s\" 0 %g %d %d %d\n", + snode->rn_name, + (snode->rn_float.rn_area/ + ExtCurStyle->exts_capScale), + snode->rn_loc.p_x, + snode->rn_loc.p_y, + /* the following is TEMPORARILY set to 0 */ + 0); + } + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResPrintStats -- Prints out the node name, the number of transistors, + * and the number of nodes for each net added. Also keeps a running + * track of the totals. + * + * Results: + * + * Side Effects: + * + *------------------------------------------------------------------------- + */ + +void +ResPrintStats(goodies,name) + ResGlobalParams *goodies; + char *name; +{ + static int totalnets=0,totalnodes=0,totalresistors=0; + int nodes,resistors; + resNode *node; + resResistor *res; + + if (goodies == NULL) + { + TxError("nets:%d nodes:%d resistors:%d\n", + totalnets,totalnodes,totalresistors); + totalnets=0; + totalnodes=0; + totalresistors=0; + return; + } + nodes=0; + resistors=0; + totalnets++; + for (node = ResNodeList; node != NULL; node=node->rn_more) + + { + nodes++; + totalnodes++; + } + for (res = ResResList; res != NULL; res=res->rr_nextResistor) + { + resistors++; + totalresistors++; + } + TxError("%s %d %d\n",name,nodes,resistors); +} + +/* + *------------------------------------------------------------------------- + * + * Write the nodename to the output. If the name does not exist, the node + * ID number is used as the name. Assumes that node has either a valid + * name or valid ID record. + * + *------------------------------------------------------------------------- + */ + +void +resWriteNodeName(fp, nodeptr) + FILE *fp; + resNode *nodeptr; +{ + if (nodeptr->rn_name == NULL) + fprintf(fp, "N%d", nodeptr->rn_id); + else + fprintf(fp, "N%s", nodeptr->rn_name); +} + +/* + *------------------------------------------------------------------------- + * + * Write a description of the resistor network geometry, compatible + * with FastHenry (mainly for doing inductance extraction) + * + *------------------------------------------------------------------------- + */ + +void +ResPrintFHNodes(fp, nodelist, nodename, nidx, celldef) + FILE *fp; + resNode *nodelist; + char *nodename; + int *nidx; + CellDef *celldef; +{ + char newname[16]; + resNode *nodeptr; + resResistor *resptr, *contact_res; + resElement *elemptr; + float oscale, height; + int np; + + if (fp == NULL) return; + + oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */ + + fprintf(fp, "\n* List of nodes in network\n"); + for (nodeptr = nodelist; nodeptr; nodeptr = nodeptr->rn_more) + { + if (nodeptr->rn_name == NULL) + { + nodeptr->rn_id = (*nidx); + (*nidx)++; + } + else + { + HashEntry *entry; + ResSimNode *simnode; + + /* If we process another sim file node while doing this */ + /* one, mark it as status "REDUNDANT" so we don't duplicate */ + /* the entry. */ + + entry = HashFind(&ResNodeTable, nodeptr->rn_name); + simnode = (ResSimNode *)HashGetValue(entry); + if (simnode != NULL) + simnode->status |= REDUNDANT; + } + resWriteNodeName(fp, nodeptr); + + /* Height of the layer is the height of the first non-contact */ + /* layer type connected to any resistor connected to this node. */ + + contact_res = (resResistor *)NULL; + for (elemptr = nodeptr->rn_re; elemptr; elemptr = elemptr->re_nextEl) + { + resptr = elemptr->re_thisEl; + if (!DBIsContact(resptr->rr_tt)) + { + height = ExtCurStyle->exts_height[resptr->rr_tt]; + if (height == 0) + { + int pnum = DBPlane(resptr->rr_tt); + int hnum = ExtCurStyle->exts_planeOrder[pnum]; + height = 0.1 * hnum; + } + } + else + contact_res = resptr; + } + height *= oscale; + + fprintf(fp, " x=%1.2f y=%1.2f z=%1.2f\n", + (float)nodeptr->rn_loc.p_x * oscale, + (float)nodeptr->rn_loc.p_y * oscale, + height); + + /* If it's a contact region and has more than one contact, add */ + /* contact points as individual nodes and connect to the main */ + /* node with an "equiv" record. */ + + if (contact_res != (resResistor *)NULL && + (contact_res->rr_cl > 1 || + contact_res->rr_width > 1)) + { + int i, j, edge, spacing; + float del, cx, cy, cxb, cyb; + + CIFGetContactSize(contact_res->rr_tt, &edge, &spacing, NULL); + + del = (float)(spacing + edge) / (oscale * 100); + + cxb = (float)(contact_res->rr_cl - 1) / 2; + for (i = 0; i < contact_res->rr_cl; i++) + { + cx = del * ((float)i - cxb); + cyb = (float)(contact_res->rr_width - 1) / 2; + for (j = 0; j < contact_res->rr_width; j++) + { + cy = del * ((float)j - cyb); + resWriteNodeName(fp, nodeptr); + fprintf(fp, "_%d_%d ", i, j); + fprintf(fp, "x=%1.2f y=%1.2f z=%1.2f\n", + ((float)nodeptr->rn_loc.p_x + cx) * oscale, + ((float)nodeptr->rn_loc.p_y + cy) * oscale, + height); + } + } + + /* Short all the contact nodes together with .equiv records */ + + fprintf(fp, ".equiv "); + resWriteNodeName(fp, nodeptr); + for (i = 0; i < contact_res->rr_cl; i++) + { + for (j = 0; j < contact_res->rr_width; j++) + { + fprintf(fp, " "); + resWriteNodeName(fp, nodeptr); + fprintf(fp, "_%d_%d", i, j); + } + } + fprintf(fp, "\n"); + } + } + + fprintf(fp, "\n* List of externally-connected ports\n.external"); + np = 0; + for (nodeptr = nodelist; nodeptr; nodeptr = nodeptr->rn_more) + { + if (nodeptr->rn_name != NULL) + { + if (np < 2) + { + Label *lab; + + fprintf(fp, " N%s", nodeptr->rn_name); + + /* This part is sort of a hack---need a better hook to */ + /* the original label this external port connects to, */ + /* rather than search for it every time we write an */ + /* external connection. */ + + for (lab = celldef->cd_labels; lab != NULL; lab = lab->lab_next) + if (lab->lab_flags & PORT_DIR_MASK) + if (!strcmp(lab->lab_text, nodeptr->rn_name)) + { + if ((lab->lab_flags & PORT_NUM_MASK) != ResPortIndex) + { + lab->lab_flags &= (~(PORT_NUM_MASK)); + lab->lab_flags |= ResPortIndex; + TxPrintf("Port %s reassigned index %d\n", + lab->lab_text, + lab->lab_flags & PORT_NUM_MASK); + celldef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP); + } + ResPortIndex++; + } + } + else + { + if (np == 2) + fprintf(fp, "\n* Warning! external nodes not recorded:"); + fprintf(fp, " N%s", nodeptr->rn_name); + } + np++; + } + } + fprintf(fp, "\n\n"); + + /* Shouldn't this work? */ + +/* + fprintf(fp, "\n* List of externally-connected ports\n"); + for (nodeptr = nodelist; nodeptr; nodeptr = nodeptr->rn_more) + if (nodeptr->rn_name != NULL) + fprintf(fp, ".external N%s Nsub\n", nodeptr->rn_name); + + fprintf(fp, "\n"); +*/ +} + +/* + *------------------------------------------------------------------------- + * ResPrintFHRects -- + * Generate FastHenry segment output to the FastHenry data file + * "fp". + * + * Results: + * None. + * + * Side effects: + * Stuff written to the stream file "fp". + * + *------------------------------------------------------------------------- + */ + +void +ResPrintFHRects(fp, reslist, nodename, eidx) + FILE *fp; + resResistor *reslist; + char *nodename; + int *eidx; /* element (segment) index */ +{ + resResistor *resistors; + float oscale, thick, cwidth; + int edge; + + if (fp == NULL) return; + + oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */ + + fprintf(fp, "* Segments connecting nodes in network\n"); + for (resistors = reslist; resistors; resistors = resistors->rr_nextResistor) + { + if (DBIsContact(resistors->rr_tt) && + (resistors->rr_cl > 1 || resistors->rr_width > 1)) + { + int i, j; + + CIFGetContactSize(resistors->rr_tt, &edge, NULL, NULL); + + /* 100 is for centimicrons to microns conversion */ + cwidth = (float)edge / 100; + + /* for contacts, rr_cl = squares in x, rr_width = squares in y */ + + for (i = 0; i < resistors->rr_cl; i++) + { + for (j = 0; j < resistors->rr_width; j++) + { + fprintf(fp, "E%d ", *eidx); + resWriteNodeName(fp, resistors->rr_connection1); + fprintf(fp, "_%d_%d ", i, j); + resWriteNodeName(fp, resistors->rr_connection2); + fprintf(fp, "_%d_%d ", i, j); + + /* Vias are vertical and so w and h are the dimensions of */ + /* the via hole. For other layers, h is layer thickness. */ + + fprintf(fp, "w=%1.2f h=%1.2f\n", cwidth, cwidth); + + (*eidx)++; + } + } + } + else + { + fprintf(fp, "E%d ", *eidx); + resWriteNodeName(fp, resistors->rr_connection1); + fprintf(fp, " "); + resWriteNodeName(fp, resistors->rr_connection2); + + if (DBIsContact(resistors->rr_tt)) + { + CIFGetContactSize(resistors->rr_tt, &edge, NULL, NULL); + /* 100 for centimicrons to microns conversion */ + cwidth = (float)edge / 100; + fprintf(fp, " w=%1.2f h=%1.2f\n", cwidth, cwidth); + } + else + { + /* For non-via layers, h is layer thickness. */ + + thick = ExtCurStyle->exts_thick[resistors->rr_tt]; + if (thick == 0) thick = 0.05; + fprintf(fp, " w=%1.2f h=%1.2f\n", + (float)resistors->rr_width * oscale, + thick * oscale); + + } + (*eidx)++; + } + } +} + +/* + *------------------------------------------------------------------------- + * + * ResPrintReference -- + * + * Write the reference plane (substrate) definition to the geometry + * (FastHenry) file output. + * + * NOTE: For now, I am assuming that substrate = ground (GND). + * However, a transistor list is passed, and it should be parsed + * for substrate devices, allowing the creation of VDD and GND + * reference planes for both substrate and wells. + * + * Another note: For now, I am assuming a uniform reference + * plane of the size of the cell bounding box. It may be + * preferable to search tiles and generate multiple, connected + * reference planes. Or it may be desirable to have an effectively + * infinite reference plane by extending it far out from the + * subcircuit bounding box. + * + *------------------------------------------------------------------------- + */ + +void +ResPrintReference(fp, transistors, cellDef) + FILE *fp; + RTran *transistors; + CellDef *cellDef; +{ + char *outfile = cellDef->cd_name; + Rect *bbox = &(cellDef->cd_bbox); + int numsegsx, numsegsy; + float oscale, llx, lly, urx, ury; + + oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */ + llx = (float)bbox->r_xbot * oscale; + lly = (float)bbox->r_ybot * oscale; + urx = (float)bbox->r_xtop * oscale; + ury = (float)bbox->r_ytop * oscale; + + fprintf(fp, "* FastHenry output for magic cell %s\n\n", outfile); + fprintf(fp, ".Units um\n"); + fprintf(fp, ".Default rho=0.02 nhinc=3 nwinc=3 rh=2 rw=2\n\n"); + fprintf(fp, "* Reference plane (substrate, ground)\n"); + + fprintf(fp, "Gsub x1=%1.2f y1=%1.2f z1=0 x2=%1.2f y2=%1.2f z2=0\n", + llx, lly, urx, lly); + fprintf(fp, "+ x3=%1.2f y3=%1.2f z3=0\n", urx, ury); + + /* Grid the reference plane at 20 lambda intervals. This */ + /* may warrant a more rigorous treatment. 20 is arbitrary. */ + /* Minimum number of segments is 4 (also arbitrary). */ + + numsegsx = (bbox->r_xtop - bbox->r_xbot) / 20; + numsegsy = (bbox->r_ytop - bbox->r_ybot) / 20; + if (numsegsx < 4) numsegsx = 4; + if (numsegsy < 4) numsegsy = 4; + + fprintf(fp, "+ thick=0.1 seg1=%d seg2=%d\n", numsegsx, numsegsy); + + fprintf(fp, "+ Ngp (%1.2f,%1.2f,0)\n", llx, lly); + + fprintf(fp, "\nNsub x=%1.2f y=%1.2f z=0\n", llx, lly); + fprintf(fp, ".Equiv Nsub Ngp\n"); +} + +/* + *------------------------------------------------------------------------- + * ResCreateCenterlines -- + * Generate centerline markers on the layout that correspond to + * network routes. Use the "DBWelement" mechanism. + * + * Results: + * 0 on success, -1 if a window cannot be found. + * + * Side effects: + * Database "line" elements are generated in the layout. + * + *------------------------------------------------------------------------- + */ + +int +ResCreateCenterlines(reslist, nidx, def) + resResistor *reslist; + int *nidx; + CellDef *def; +{ + resResistor *resistors; + resNode *nodeptr; + Rect r, rcanon; + MagWindow *w; /* should be passed from up in CmdExtResis. . . */ + char name[128]; + + w = ToolGetBoxWindow (&r, (int *)NULL); + if (w == (MagWindow *)NULL) + windCheckOnlyWindow(&w, DBWclientID); + if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID)) { + TxError("Put the cursor in a layout window.\n"); + return -1; + } + + for (resistors = reslist; resistors; resistors = resistors->rr_nextResistor) + { + /* Ignore vias */ + + if (!DBIsContact(resistors->rr_tt)) + { + nodeptr = resistors->rr_connection1; + r.r_xbot = nodeptr->rn_loc.p_x; + r.r_ybot = nodeptr->rn_loc.p_y; + if (nodeptr->rn_name == NULL) + { + nodeptr->rn_id = (*nidx); + (*nidx)++; + sprintf(name, "N%d_", nodeptr->rn_id); + } + else + sprintf(name, "N%s_", nodeptr->rn_name); + + nodeptr = resistors->rr_connection2; + r.r_xtop = nodeptr->rn_loc.p_x; + r.r_ytop = nodeptr->rn_loc.p_y; + GeoCanonicalRect(&r, &rcanon); + if (nodeptr->rn_name == NULL) + { + nodeptr->rn_id = (*nidx); + (*nidx)++; + sprintf(name + strlen(name), "%d", nodeptr->rn_id); + } + else + strcat(name, nodeptr->rn_name); + + /* Note that if any element exists with name "name" */ + /* it will be deleted (overwritten). */ + DBWElementAddLine(w, name, &rcanon, def, STYLE_YELLOW1); + } + } + return 0; +} + diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c new file mode 100644 index 00000000..c6b377b1 --- /dev/null +++ b/resis/ResReadSim.c @@ -0,0 +1,866 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResReadSim.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +/* + *------------------------------------------------------------------------- + * + * ResReadSim.c -- Routines to parse .sim files + * + *------------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/utils.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "resis/resis.h" + + +/* constants defining where various fields can be found in .sim files. */ +#define RTRAN_LENGTH 4 +#define RTRAN_WIDTH 5 +#define RTRAN_TRANX 6 +#define RTRAN_TRANY 7 +#define RTRAN_ATTR 8 +#define RTRAN_NUM_ATTR 3 +#define RESNODENAME 1 +#define NODERESISTANCE 2 +#define COUPLETERMINAL1 1 +#define COUPLETERMINAL2 2 +#define COUPLEVALUE 3 +#define REALNAME 1 +#define ALIASNAME 2 +#define NODECIFCOMMAND 0 +#define NODENODENAME 1 +#define NODENODEX 2 +#define NODENODEY 3 +#define NODETYPE 4 +#define NODE_BBOX_LL_X 5 +#define NODE_BBOX_LL_Y 6 +#define NODE_BBOX_UR_X 7 +#define NODE_BBOX_UR_Y 8 +#define NODELAMBDA 2 +#define NODEUNITS 1 +#define ATTRIBUTENODENAME 1 +#define ATTRIBUTEVALUE 2 + +#define RES_EXT_ATTR 0 +#define RES_EXT_ATTR_NAME 1 +#define RES_EXT_ATTR_X 2 +#define RES_EXT_ATTR_Y 3 +#define RES_EXT_ATTR_TILE 6 +#define RES_EXT_ATTR_TEXT 7 + + +#define MAXTOKEN 256 +#define MAXLINE 40 +#define MAXDIGIT 20 + + +ResSimNode *ResInitializeNode(); + +ResSimNode *ResOriginalNodes; /*Linked List of Nodes */ +static float lambda=1.0; /* Scale factor */ +char RTRAN_NOATTR[1]={'0'}; +ResFixPoint *ResFixList; + +#define nodeinit(n)\ +{\ + (n)->rn_more = ResNodeList;\ + (n)->rn_less = NULL;\ + if (ResNodeList)\ + ResNodeList->rn_less = n;\ + ResNodeList = n;\ + (n)->rn_te = NULL;\ + (n)->rn_re = NULL;\ + (n)->rn_je=NULL;\ + (n)->rn_ce=NULL;\ + (n)->rn_noderes=RES_INFINITY;\ + (n)->location.p_x=MINFINITY;\ + (n)->location.p_y=MINFINITY;\ + (n)->rn_why=0;\ + (n)->rn_status = TRUE;\ +} + +/* Forward declarations */ + +extern void ResSimProcessDrivePoints(); + + +/* + *------------------------------------------------------------------------- + * + * ResReadSim-- + * + * Results: returns 0 if sim file is correct, 1 if not. + * + * Side Effects:Reads in SimTable and makes a hash table of nodes. + * + *------------------------------------------------------------------------- + */ + +int +ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc) + char *simfile; + int (*fetproc)(),(*capproc)(),(*resproc)(); + int (*attrproc)(),(*mergeproc)(); + +{ + char line[MAXLINE][MAXTOKEN]; + int result,fettype,extfile; + FILE *fp, *fopen(); + + fp = PaOpen(simfile,"r",".sim",".",(char *) NULL, (char **) NULL); + if (fp == NULL) + { + TxError("Cannot open file %s%s\n",simfile,".sim"); + return(1); + } + extfile = 0; + + /*read in file */ + while (gettokens(line,fp) != 0) + { + fettype = MINFINITY; + switch(line[0][0]) + { + case '|': + if (strcmp(line[NODEUNITS],"units:") == 0) + { + lambda = (float)atof(line[NODELAMBDA]); + if (lambda == 0.0) lambda = 1.0; + } + result=0; + break; + case 'e': fettype = DBTechNameType("efet"); + break; + case 'd': fettype = DBTechNameType("dfet"); + break; + case 'n': fettype = DBTechNameType("nfet"); + break; + case 'p': fettype = DBTechNameType("pfet"); + break; + case 'b': fettype = DBTechNameType("bnpn"); + break; + case 'C': if (capproc) result = (*capproc)(line); + break; + case 'R': if (resproc)result = (*resproc)(line); + break; + case '=': if (mergeproc)result = (*mergeproc)(line); + break; + case 'A': if (attrproc) result = + (*attrproc)(line[ATTRIBUTENODENAME], + line[ATTRIBUTEVALUE], + simfile, &extfile); + break; + case 'D': + case 'c': + case 'r': break; + default: result = 1; + (void)fclose(fp); + break; + } + if (fettype == -1) + { + TxError("Error in Reading tran line of sim file.\n"); + result = 1; + } + else if (fettype != MINFINITY) + { + float sheetr; + + sheetr=(float)ExtCurStyle->exts_linearResist[fettype]; + result = (*fetproc)(line,sheetr,fettype); + } + if (result != 0) + { + TxError("Error in sim file %s\n",line[0]); + return(1); + } + } + (void)fclose(fp); + return(result); +} + + +/* + *------------------------------------------------------------------------- + * + * ResReadNode-- Reads in a node file, puts location of nodes into node + * structures. + * + * Results: returns 0 if nodes file is correct, 1 if not. + * + * Side Effects:see above + * + *------------------------------------------------------------------------- + */ + +int +ResReadNode(nodefile) + char *nodefile; + +{ + char line[MAXLINE][MAXTOKEN]; + FILE *fp, *fopen(); + HashEntry *entry; + ResSimNode *node; + char *cp; + + fp = PaOpen(nodefile,"r",".nodes",".", (char *) NULL, (char **) NULL); + if (fp == NULL) + { + TxError("Cannot open file %s%s\n",nodefile,".nodes"); + return(1); + } + while (gettokens(line,fp) != 0) + { + entry = HashFind(&ResNodeTable,line[NODENODENAME]); + node = ResInitializeNode(entry); + + node->location.p_x = (int)((float)atof(line[NODENODEX])/lambda); + node->location.p_y = (int)((float)atof(line[NODENODEY])/lambda); +#ifdef ARIEL + node->rs_bbox.r_xbot = (int)((float)atof(line[NODE_BBOX_LL_X])/lambda); + node->rs_bbox.r_ybot = (int)((float)atof(line[NODE_BBOX_LL_Y])/lambda); + node->rs_bbox.r_xtop = (int)((float)atof(line[NODE_BBOX_UR_X])/lambda); + node->rs_bbox.r_ytop = (int)((float)atof(line[NODE_BBOX_UR_Y])/lambda); +#endif + if (cp = strchr(line[NODETYPE], ';')) *cp = '\0'; + node->type = DBTechNameType(line[NODETYPE]); + + if (node->type == -1) + { + TxError("Bad tile type name in %s.nodes file for node %s\n",nodefile,node->name); + TxError("Did you use the newest version of ext2sim?\n"); + (void)fclose(fp); + return(1); + } + } + (void)fclose(fp); + return(0); +} + +/* + *------------------------------------------------------------------------- + * + * getline-- Gets a line from the current input file and breaks it into + * tokens. + * + * Results:returns the number of tokens in the current line + * + * Side Effects: loads up its input line with the tokens. + * + *------------------------------------------------------------------------- + */ + +int +gettokens(line,fp) + char line[][MAXTOKEN]; + FILE *fp; + +{ + int i=0,j=0; + int c; + + while ((c = getc(fp)) != EOF && c != '\n') + { + switch(c) + { + case ' ': + case ' ' : line[i++][j] = '\0'; + j=0; + break; + default: line[i][j++] = c; + break; + } + } + if (c == '\n') + { + line[i++][j] = '\0'; + j=0; + } + for(j=i;j < MAXLINE;j++) + { + line[j][0] = '\0'; + } + return(i); +} + + +/* + *------------------------------------------------------------------------- + * + * ResSimTransistor-- Processes a transistor line from a sim file. + * + * Results: returns 0 if line was added correctly. + * + * Side Effects: Allocates transistors and adds nodes to the node hash table. + * + *------------------------------------------------------------------------- + */ + +int +ResSimTransistor(line,rpersquare,ttype) + char line[][MAXTOKEN]; + float rpersquare; + TileType ttype; + +{ + RTran *transistor; + int rvalue,i,j,k; + char *newattr,tmpattr[MAXTOKEN]; + static int nowarning = TRUE; + + transistor = (RTran *) mallocMagic((unsigned) (sizeof(RTran))); + if ((line[RTRAN_WIDTH][0] == '\0') || (line[RTRAN_LENGTH][0] == '\0')) + { + TxError("error in input file:\n"); + return(1); + } + else + { + if (nowarning && rpersquare == 0) + { + TxError("Warning- FET resistance not included or set to zero in technology file-\n"); + TxError("All driven nodes will be extracted\n"); + nowarning = FALSE; + } + transistor->resistance = MagAtof(line[RTRAN_LENGTH]) * rpersquare/MagAtof(line[RTRAN_WIDTH]); + } + transistor->tnumber = ++Maxtnumber; + transistor->status = FALSE; + transistor->nextTran = ResTranList; + transistor->location.p_x = atoi(line[RTRAN_TRANX]); + transistor->location.p_y = atoi(line[RTRAN_TRANY]); + transistor->rs_gattr=RTRAN_NOATTR; + transistor->rs_sattr=RTRAN_NOATTR; + transistor->rs_dattr=RTRAN_NOATTR; + transistor->rs_ttype = ttype; + + /* sim attributes look like g=a1,a2 */ + /* ext attributes are "a1","a2" */ + /* do conversion from one to the other here */ + + for (i=RTRAN_ATTR;i < RTRAN_ATTR+RTRAN_NUM_ATTR;i++) + { + if (line[i][0] == '\0') break; + k=0; + tmpattr[k++]='"'; + for (j=2;line[i][j] != '\0';j++) + { + if (line[i][j] == ',') + { + tmpattr[k++] = '"'; + tmpattr[k++] = ','; + tmpattr[k++] = '"'; + } + else + { + tmpattr[k++] = line[i][j]; + } + } + tmpattr[k++]='"'; + tmpattr[k++]='\0'; + newattr = (char *) mallocMagic((unsigned) k); + strncpy(newattr,tmpattr,k); + switch (line[i][0]) + { + case 'g': transistor->rs_gattr = newattr; break; + case 's': transistor->rs_sattr = newattr; break; + case 'd': transistor->rs_dattr = newattr; break; + default: TxError("Bad fet attribute\n"); + break; + } + } + ResTranList = transistor; + transistor->layout = NULL; + rvalue = ResSimNewNode(line[GATE],GATE,transistor) + + ResSimNewNode(line[SOURCE],SOURCE,transistor) + + ResSimNewNode(line[DRAIN],DRAIN,transistor); + + return(rvalue); +} + + +/* + *------------------------------------------------------------------------- + * + * ResSimNewNode-- Adds a new node to the Node Hash Table. + * + * Results: returns zero if node is added correctly, one otherwise. + * + * Side Effects: Allocates a new ResSimNode + * + *------------------------------------------------------------------------- + */ + +int +ResSimNewNode(line,type,transistor) + char line[]; + int type; + RTran *transistor; + +{ + HashEntry *entry; + ResSimNode *node; + tranPtr *tptr; + + if (line[0] == '\0') + { + TxError("Missing transistor connection\n"); + return(1); + } + entry = HashFind(&ResNodeTable,line); + node = ResInitializeNode(entry); + tptr = (tranPtr *) mallocMagic((unsigned) (sizeof(tranPtr))); + tptr->thisTran = transistor; + tptr->nextTran = node->firstTran; + node->firstTran = tptr; + tptr->terminal = type; + switch(type) + { + case GATE: transistor->gate = node; + break; + case SOURCE: transistor->source = node; + break; + case DRAIN: transistor->drain = node; + break; + default: TxError("Bad Terminal Specifier\n"); + break; + } + return(0); +} + + +/* + *------------------------------------------------------------------------- + * + * ResSimCapacitor-- Adds the capacitance from a C line to the appropriate + * node. Coupling capacitors are added twice, moving the capacitance + * to the substrate. + * + * Results: + * Always return 0 + * + * Side Effects: modifies capacitance field of ResSimNode. + * + *------------------------------------------------------------------------- + */ + +int +ResSimCapacitor(line) + char line[][MAXTOKEN]; + +{ + HashEntry *entry1,*entry2; + ResSimNode *node1,*node2; + + if (line[COUPLETERMINAL1][0] == 0 || line[COUPLETERMINAL2][0] == 0) + { + TxError("Bad Capacitor\n"); + return(1); + } + entry1 = HashFind(&ResNodeTable,line[COUPLETERMINAL1]); + node1 = ResInitializeNode(entry1); + if (ResOptionsFlags & ResOpt_Signal) + { + node1->capacitance += MagAtof(line[COUPLEVALUE]); + if (strcmp(line[COUPLETERMINAL2],"GND") == 0 || + strcmp(line[COUPLETERMINAL2],"Vdd") == 0) + { + return(0); + } + entry2 = HashFind(&ResNodeTable,line[COUPLETERMINAL2]); + node2 = ResInitializeNode(entry2); + node2->capacitance += MagAtof(line[COUPLEVALUE]); + return(0); + } + if (strcmp(line[COUPLETERMINAL2],"GND") == 0 ) + { + node1->capacitance += MagAtof(line[COUPLEVALUE]); + return(0); + } + if (strcmp(line[COUPLETERMINAL2],"Vdd") == 0 ) + { + node1->cap_vdd += MagAtof(line[COUPLEVALUE]); + return(0); + } + entry2 = HashFind(&ResNodeTable,line[COUPLETERMINAL2]); + node2 = ResInitializeNode(entry2); + if (strcmp(line[COUPLETERMINAL1],"GND") == 0 ) + { + node2->capacitance += MagAtof(line[COUPLEVALUE]); + return(0); + } + if (strcmp(line[COUPLETERMINAL1],"Vdd") == 0 ) + { + node2->cap_vdd += MagAtof(line[COUPLEVALUE]); + return(0); + } + node1->cap_couple += MagAtof(line[COUPLEVALUE]); + node2->cap_couple += MagAtof(line[COUPLEVALUE]); + return(0); + +} + + +/* + *------------------------------------------------------------------------- + * + * ResSimResistor-- Adds the capacitance from a R line to the appropriate + * node. + * + * Results + * Return 0 to keep search going, 1 to abort + * + * Side Effects: modifies resistance field of ResSimNode + * + *------------------------------------------------------------------------- + */ + +int +ResSimResistor(line) + char line[][MAXTOKEN]; + +{ + HashEntry *entry; + ResSimNode *node; + + if (line[RESNODENAME][0] == 0) + { + TxError("Bad Resistor\n"); + return(1); + } + entry = HashFind(&ResNodeTable,line[RESNODENAME]); + node = ResInitializeNode(entry); + if (node->resistance != 0) + { + TxError("Duplicate Resistance Entries\n"); + return(1); + } + node->resistance = MagAtof(line[NODERESISTANCE]); + return(0); +} + + + +/* + *------------------------------------------------------------------------- + * + * ResSimAttribute--checks to see if a node attribute is a resistance + * attribute. If it is, add it to the correct node's status flag. + * Only works with 5.0 1/line attributes + * + * Results: + * Return 0 to keep search going, 1 to abort + * + * Side Effects: modifies resistance field of ResSimNode + * + *------------------------------------------------------------------------- + */ + +int +ResSimAttribute(aname,avalue,rootname,readextfile) + char *aname,*avalue,*rootname; + int *readextfile; + +{ + HashEntry *entry; + ResSimNode *node; + char digit[MAXDIGIT]; + int i; + static int notwarned=TRUE; + + if (aname[0] == 0) + { + TxError("Bad Resistor\n"); + return(1); + } + entry = HashFind(&ResNodeTable,aname); + node = ResInitializeNode(entry); + if (strncmp(avalue,"res:skip",8) == 0) + { + if (node->status & FORCE) + { + TxError("Warning: Node %s is both forced and skipped\n",aname); + } + else + { + node->status |= SKIP; + } + } + else if (strncmp(avalue,"res:force",9) == 0) + { + if (node->status & SKIP) + { + TxError("Warning: Node %s is both skipped and forced \n",aname); + } + else + { + node->status |= FORCE; + } + } + else if (strncmp(avalue,"res:min=",8) == 0) + { + node->status |= MINSIZE; + for(i=0,avalue += 8; *avalue != '\0' && *avalue != ','; avalue++) + { + digit[i++] = *avalue; + } + digit[i++]='\0'; + node->minsizeres=MagAtof(digit); + } + else if (strncmp(avalue,"res:drive",9) == 0 && + (ResOptionsFlags & ResOpt_Signal)) + { + if (*readextfile == 0) + { + ResSimProcessDrivePoints(rootname); + *readextfile = 1; + } + /* is the attribute in root.ext? */ + if (node->drivepoint.p_x != INFINITY) + { + node->status |= DRIVELOC; + } + else + { + if (notwarned) + TxError("Drivepoint for %s not defined in %s.ext; is it defined in a child cell?\n",node->name,rootname); + notwarned = FALSE; + } + } +#ifdef ARIEL + else if (strncmp(avalue,"res:fix",7) == 0 && + (ResOptionsFlags & ResOpt_Power)) + { + if (*readextfile == 0) + { + ResSimProcessFixPoints(rootname); + *readextfile = 1; + } + } +#endif + if (avalue = strchr(avalue,',')) + { + (void) ResSimAttribute(aname,avalue+1,rootname,readextfile); + } + return(0); +} + + +/* + *------------------------------------------------------------------------- + * + * ResSimProcessDrivePoints -- if the sim file contains a res:drive attribute, + * and we are doing a signal extraction, + * we need to search through the .ext file looking for attr labels that + * contain this text. For efficiency, the .ext file is only parsed when + * the first res:drive is encountered. res:drive labels only work if + * they are in the root cell. + * + * Results: + * None. + * + * Side Effects: + * + *------------------------------------------------------------------------- + */ + +void +ResSimProcessDrivePoints(filename) + char *filename; + +{ + char line[MAXLINE][MAXTOKEN]; + FILE *fp; + HashEntry *entry; + ResSimNode *node; + + fp = PaOpen(filename,"r",".ext",".",(char *) NULL,(char **) NULL); + if (fp == NULL) + { + TxError("Cannot open file %s%s\n",filename,".ext"); + return; + } + while (gettokens(line,fp) != 0) + { + if (strncmp(line[RES_EXT_ATTR],"attr",4) != 0 || + strncmp(line[RES_EXT_ATTR_TEXT],"\"res:drive\"",11) != 0) continue; + + entry = HashFind(&ResNodeTable,line[RES_EXT_ATTR_NAME]); + node = ResInitializeNode(entry); + node->drivepoint.p_x = atoi(line[RES_EXT_ATTR_X]); + node->drivepoint.p_y = atoi(line[RES_EXT_ATTR_Y]); + node->rs_ttype = DBTechNoisyNameType(line[RES_EXT_ATTR_TILE]); + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResSimProcessFixPoints -- if the sim file contains a "res:fix:name" label + * and we are checking for power supply noise, then we have to + * parse the .ext file looking for the fix label locations. This + * is only done after the first res:fix label is encountered. + * + * + * Results: + * None. + * + * Side Effects: + * For each new name, allocate memory + * + *------------------------------------------------------------------------- + */ + +void +ResSimProcessFixPoints(filename) + char *filename; +{ + char line[MAXLINE][MAXTOKEN],*label,*c; + FILE *fp; + ResFixPoint *thisfix; + + fp = PaOpen(filename,"r",".ext",".",(char *) NULL,(char **) NULL); + if (fp == NULL) + { + TxError("Cannot open file %s%s\n",filename,".ext"); + return; + } + while (gettokens(line,fp) != 0) + { + if (strncmp(line[RES_EXT_ATTR],"attr",4) != 0 || + strncmp(line[RES_EXT_ATTR_TEXT],"\"res:fix",8) != 0) continue; + label = line[RES_EXT_ATTR_TEXT]; + label += 8; + if (*label == ':') label++; + if ((c=strrchr(label,'"')) != NULL) *c='\0'; + else if (*label == '\0'); + else + { + TxError("Bad res:fix attribute label %s\n", + line[RES_EXT_ATTR_TEXT]); + *label ='\0'; + } + thisfix = (ResFixPoint *) mallocMagic((unsigned) (sizeof(ResFixPoint)+strlen(label))); + thisfix->fp_next = ResFixList; + ResFixList = thisfix; + thisfix->fp_loc.p_x = atoi(line[RES_EXT_ATTR_X]); + thisfix->fp_loc.p_y = atoi(line[RES_EXT_ATTR_Y]); + thisfix->fp_ttype = DBTechNoisyNameType(line[RES_EXT_ATTR_TILE]); + thisfix->fp_tile=NULL; + strcpy(thisfix->fp_name,label); + } +} + + + /* + *------------------------------------------------------------------------- + * + * ResSimMerge-- Processes = line in sim file + * + * Results: Success/Failure + * + * Side Effects: The forward field of one node is set to point to the + * other node. All of the junkt from the first node is moved to + * the second node. + * + *------------------------------------------------------------------------- + */ + +int +ResSimMerge(line) + char line[][MAXTOKEN]; + +{ + ResSimNode *node; + tranPtr *ptr; + + if ((line[ALIASNAME][0] == '\0') || (line[REALNAME][0] == '\0')) + { + TxError("Bad node alias line\n"); + return(1); + } + node = ResInitializeNode(HashFind(&ResNodeTable,line[ALIASNAME])); + node->status |= FORWARD; + node->forward = ResInitializeNode(HashFind(&ResNodeTable,line[REALNAME])); + node->forward->resistance += node->resistance; + node->forward->capacitance += node->capacitance; + while (node->firstTran != NULL) + { + ptr=node->firstTran; + node->firstTran = node->firstTran->nextTran; + ptr->nextTran = node->forward->firstTran; + node->forward->firstTran = ptr; + } + return(0); +} + +/* + *------------------------------------------------------------------------- + * + * ResInitializeNode-- Gets the node corresponding to a given hash table + * entry. If no such node exists, one is created. + * + * Results:Returns ResSimNode corresponding to entry. + * + * Side Effects: May allocate a new ResSimNode. + * + *------------------------------------------------------------------------- + */ + +ResSimNode * +ResInitializeNode(entry) + HashEntry *entry; +{ + ResSimNode *node; + + if ((node = (ResSimNode *) HashGetValue(entry)) == NULL) + { + node = (ResSimNode *) mallocMagic((unsigned)(sizeof(ResSimNode))); + HashSetValue(entry,(char *) node); + node->nextnode = ResOriginalNodes; + ResOriginalNodes = node; + node->status = FALSE; + node->forward = (ResSimNode *) NULL; + node->capacitance = 0; + node->cap_vdd = 0; + node->cap_couple = 0; + node->resistance = 0; + node->type = 0; + node->firstTran = NULL; + node->name = entry->h_key.h_name; + node->oldname = NULL; + node->drivepoint.p_x = INFINITY; + node->drivepoint.p_y = INFINITY; + node->rs_sublist[0]=NULL; + node->rs_sublist[1]=NULL; + } + while (node->status & FORWARD) + { + node = node->forward; + } + return(node); +} diff --git a/resis/ResRex.c b/resis/ResRex.c new file mode 100644 index 00000000..8be566a4 --- /dev/null +++ b/resis/ResRex.c @@ -0,0 +1,1666 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResRex.c,v 1.3 2010/03/08 13:33:33 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/undo.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/utils.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "resis/resis.h" +#ifdef LAPLACE +#include "laplace.h" +#endif + +#define INITFLATSIZE 1024 +#define MAXNAME 1000 + + +/* time constants are produced by multiplying attofarads by milliohms, */ +/* giving zeptoseconds (yes, really. Look it up). This constant */ +/* converts zeptoseconts to nanoseconds. */ +#define Z_TO_N 1e12 + +/* ResSimNode is a node read in from a sim file */ + + +HashTable ResNodeTable; /* Hash table of sim file nodes */ +RTran *ResTranList; /* Linked list of Sim transistors */ +ResGlobalParams gparams; /* Junk passed between */ + /* ResCheckSimNodes and */ + /* ResExtractNet. */ +int Maxtnumber; /*maximum transistor number */ +extern ResSimNode *ResOriginalNodes; /*Linked List of Nodes */ +int resNodeNum; + +#ifdef LAPLACE +int ResOptionsFlags = ResOpt_Simplify|ResOpt_Tdi|ResOpt_DoExtFile|ResOpt_CacheLaplace; +#else +int ResOptionsFlags = ResOpt_Simplify|ResOpt_Tdi|ResOpt_DoExtFile; +#endif +char *ResCurrentNode; + +FILE *ResExtFile; +FILE *ResLumpFile; +FILE *ResFHFile; + +int ResPortIndex; /* Port ordering to backannotate into magic */ + +/* external declarations */ +extern ResSimNode *ResInitializeNode(); +extern CellUse *CmdGetSelectedCell(); + +/* Structure stores information required to be sent to ExtResisForDef() */ +typedef struct +{ + float tolerance; + float tdiTolerance; + float frequency; + CellDef *mainDef; +} ResisData; + +/* + *------------------------------------------------------------------------- + * + * ExtResisForDef -- + * + * Do resistance network extraction for the indicated CellDef. + * + *------------------------------------------------------------------------- + */ + +void +ExtResisForDef(celldef, resisdata) + CellDef *celldef; + ResisData *resisdata; +{ + RTran *oldTran; + HashSearch hs; + HashEntry *entry; + tranPtr *tptr,*oldtptr; + ResSimNode *node; + int result; + + ResTranList = NULL; + ResOriginalNodes = NULL; + + Maxtnumber = 0; + HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS); + /* read in .sim file */ + result = ResReadSim(celldef->cd_name, + ResSimTransistor,ResSimCapacitor,ResSimResistor, + ResSimAttribute,ResSimMerge) == 0; + + if (result == 0) + /* read in .nodes file */ + result = ResReadNode(celldef->cd_name); + + /* Check for subcircuit ports */ + if (ResOptionsFlags & ResOpt_Blackbox) + result &= ResCheckBlackbox(celldef); + else + result &= ResCheckPorts(celldef); + + if (result == 0) + { + /* Extract networks for nets that require it. */ + if (!(ResOptionsFlags & ResOpt_FastHenry) || + DBIsSubcircuit(celldef)) + ResCheckSimNodes(celldef, resisdata); + + if (ResOptionsFlags & ResOpt_Stat) + ResPrintStats((ResGlobalParams *)NULL,""); + } + + HashStartSearch(&hs); + while((entry = HashNext(&ResNodeTable,&hs)) != NULL) + { + node=(ResSimNode *) HashGetValue(entry); + tptr = node->firstTran; + if (node == NULL) + { + TxError("Error: NULL Hash entry!\n"); + TxFlushErr(); + } + while (tptr != NULL) + { + oldtptr = tptr; + tptr = tptr->nextTran; + freeMagic((char *)oldtptr); + } + freeMagic((char *) node); + } + HashKill(&ResNodeTable); + while (ResTranList != NULL) + { + oldTran = ResTranList; + ResTranList = ResTranList->nextTran; + if (oldTran->layout != NULL) + { + freeMagic((char *)oldTran->layout); + oldTran->layout = NULL; + } + freeMagic((char *)oldTran); + } +} + + +/* + *------------------------------------------------------------------------- + * + * CmdExtResis-- reads in sim file and layout, and produces patches to the + * .ext files and .sim files that include resistors. + * + * Results: + * None. + * + * Side Effects: Produces .res.sim file and .res.ext file for all nets that + * require resistors. + * + *------------------------------------------------------------------------- + */ + +void +CmdExtResis(win, cmd) + MagWindow *win; + TxCommand *cmd; +{ + int i, j, k, option, value, saveFlags; + static int init=1; + static float tolerance, tdiTolerance, fhFrequency; + CellDef *mainDef; + CellUse *selectedUse; + ResisData resisdata; + char *endptr; /* for use with strtod() */ + + extern int resSubcircuitFunc(); /* Forward declaration */ + + static char *onOff[] = + { + "off", + "on", + NULL + }; + + static char *cmdExtresisCmd[] = + { + "tolerance [value] set ratio between resistor and transistor tol.", + "all extract all the nets", + "simplify [on/off] turn on/off simplification of resistor nets", + "extout [on/off] turn on/off writing of .res.ext file", + "lumped [on/off] turn on/off writing of updated lumped resistances", + "silent [on/off] turn on/off printing of net statistics", + "skip mask don't extract these types", + "box type extract the signal under the box on layer type", + "cell cellname extract the network for the cell named cellname", + "blackbox [on/off] treat subcircuits with ports as black boxes", + "fasthenry [freq] extract subcircuit network geometry into .fh file", + "geometry extract network centerline geometry (experimental)", + "help print this message", +#ifdef LAPLACE + "laplace [on/off] solve Laplace's equation using FEM", +#endif + NULL + }; + +typedef enum { + RES_BAD=-2, RES_AMBIG, RES_TOL, + RES_ALL, RES_SIMP, RES_EXTOUT, RES_LUMPED, + RES_SILENT, RES_SKIP, RES_BOX, RES_CELL, RES_BLACKBOX, + RES_FASTHENRY, RES_GEOMETRY, RES_HELP, +#ifdef LAPLACE + RES_LAPLACE, +#endif + RES_RUN +} ResOptions; + + if (init) + { + for (i = 0; i < NT; i++) + { + TTMaskZero(&(ResCopyMask[i])); + TTMaskSetMask(&ResCopyMask[i], &DBConnectTbl[i]); + } + tolerance = 1; + tdiTolerance = 1; + fhFrequency = 10e6; /* 10 MHz default */ + init = 0; + } + + option = (cmd->tx_argc > 1) ? Lookup(cmd->tx_argv[1], cmdExtresisCmd) + : RES_RUN; + + switch (option) + { + case RES_SIMP: + case RES_EXTOUT: + case RES_LUMPED: + case RES_SILENT: + case RES_BLACKBOX: + if (cmd->tx_argc > 2) + { + value = Lookup(cmd->tx_argv[2], onOff); + if (value < 0) + { + TxError("Value must be either \"on\" or \"off\".\n"); + return; + } + } + break; + } + + switch (option) + { + case RES_TOL: + ResOptionsFlags |= ResOpt_ExplicitRtol; + if (cmd->tx_argc > 2) + { + tolerance = MagAtof(cmd->tx_argv[2]); + if (tolerance <= 0) + { + TxError("Usage: %s tolerance [value]\n", cmd->tx_argv[0]); + return; + } + tdiTolerance = tolerance; + } + else + { +#ifdef MAGIC_WRAPPER + Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)tdiTolerance)); +#else + TxPrintf("Tolerance ratio is %g.\n", tdiTolerance); +#endif + } + return; + + case RES_ALL: + ResOptionsFlags |= ResOpt_ExtractAll; + break; + + case RES_GEOMETRY: + saveFlags = ResOptionsFlags; + ResOptionsFlags |= ResOpt_Geometry | ResOpt_ExtractAll; + ResOptionsFlags &= ~(ResOpt_DoExtFile | ResOpt_DoLumpFile + | ResOpt_Simplify | ResOpt_Tdi); + break; + + case RES_FASTHENRY: + if (cmd->tx_argc == 3) + { + double tmpf = strtod(cmd->tx_argv[2], &endptr); + if (endptr == cmd->tx_argv[2]) + { + TxError("Cannot parse frequency value. Assuming default\n"); + TxError("Frequency = %2.1f Hz\n", fhFrequency); + } + else + fhFrequency = (float)tmpf; + } + saveFlags = ResOptionsFlags; + ResOptionsFlags |= ResOpt_FastHenry | ResOpt_ExtractAll; + ResOptionsFlags &= ~(ResOpt_DoExtFile | ResOpt_DoLumpFile + | ResOpt_Simplify | ResOpt_Tdi); + break; + + case RES_BLACKBOX: + if (cmd->tx_argc == 2) + { + value = (ResOptionsFlags & ResOpt_Blackbox) ? + TRUE : FALSE; + TxPrintf("%s\n", onOff[value]); + } + else + { + value = Lookup(cmd->tx_argv[2], onOff); + + if (value) + ResOptionsFlags |= ResOpt_Blackbox; + else + ResOptionsFlags &= ~ResOpt_Blackbox; + } + return; + case RES_SIMP: + if (cmd->tx_argc == 2) + { + value = (ResOptionsFlags & (ResOpt_Simplify | ResOpt_Tdi)) ? + TRUE : FALSE; + TxPrintf("%s\n", onOff[value]); + } + else + { + value = Lookup(cmd->tx_argv[2], onOff); + + if (value) + ResOptionsFlags |= ResOpt_Simplify | ResOpt_Tdi; + else + ResOptionsFlags &= ~(ResOpt_Simplify | ResOpt_Tdi); + } + return; + case RES_EXTOUT: + if (cmd->tx_argc == 2) + { + value = (ResOptionsFlags & ResOpt_DoExtFile) ? + TRUE : FALSE; + TxPrintf("%s\n", onOff[value]); + } + else + { + value = Lookup(cmd->tx_argv[2], onOff); + if (value) + ResOptionsFlags |= ResOpt_DoExtFile; + else + ResOptionsFlags &= ~ResOpt_DoExtFile; + } + return; + case RES_LUMPED: + if (cmd->tx_argc == 2) + { + value = (ResOptionsFlags & ResOpt_DoLumpFile) ? + TRUE : FALSE; + TxPrintf("%s\n", onOff[value]); + } + else + { + value = Lookup(cmd->tx_argv[2], onOff); + if (value) + ResOptionsFlags |= ResOpt_DoLumpFile; + else + ResOptionsFlags &= ~ResOpt_DoLumpFile; + } + return; + case RES_SILENT: + if (cmd->tx_argc == 2) + { + value = (ResOptionsFlags & ResOpt_RunSilent) ? + TRUE : FALSE; + TxPrintf("%s\n", onOff[value]); + } + else + { + value = Lookup(cmd->tx_argv[2], onOff); + if (value) + ResOptionsFlags |= ResOpt_RunSilent; + else + ResOptionsFlags &= ~ResOpt_RunSilent; + } + return; + + case RES_SKIP: + if (cmd->tx_argc > 2) + { + j = DBTechNoisyNameType(cmd->tx_argv[2]); + if (j >= 0) + for (k = TT_TECHDEPBASE; k < TT_MAXTYPES; k++) + TTMaskClearType(&ResCopyMask[k], j); + TTMaskZero(&(ResCopyMask[j])); + } + else + { + for (i = 0; i != NT; i++) + { + TTMaskZero(&(ResCopyMask[i])); + TTMaskSetMask(&ResCopyMask[i], &DBConnectTbl[i]); + } + } + return; + + case RES_HELP: + for (i = 0; cmdExtresisCmd[i] != NULL; i++) + TxPrintf("%s\n", cmdExtresisCmd[i]); + return; + + case RES_BOX: + { + TileType tt; + CellDef *def; + Rect rect; + int oldoptions; + ResFixPoint fp; + + if (ToolGetBoxWindow((Rect *) NULL, (int *) NULL) == NULL) + { + TxError("Sorry, the box must appear in one of the windows.\n"); + return; + } + + if (cmd->tx_argc != 3) return; + tt = DBTechNoisyNameType(cmd->tx_argv[2]); + if (tt <= 0 || ToolGetBox(&def, &rect)== FALSE) return; + gparams.rg_tranloc = &rect.r_ll; + gparams.rg_ttype = tt; + gparams.rg_status = DRIVEONLY; + oldoptions = ResOptionsFlags; + ResOptionsFlags = ResOpt_DoSubstrate|ResOpt_Signal|ResOpt_Box; +#ifdef LAPLACE + ResOptionsFlags |= (oldoptions & (ResOpt_CacheLaplace|ResOpt_DoLaplace)); + LaplaceMatchCount = 0; + LaplaceMissCount = 0; +#endif + fp.fp_ttype = tt; + fp.fp_loc = rect.r_ll; + fp.fp_next = NULL; + if (ResExtractNet(&fp, &gparams, NULL) != 0) return; + ResPrintResistorList(stdout,ResResList); + ResPrintTransistorList(stdout,ResTransList); +#ifdef LAPLACE + if (ResOptionsFlags & ResOpt_DoLaplace) + { + TxPrintf("Laplace solved: %d matched %d\n", + LaplaceMissCount,LaplaceMatchCount); + } +#endif + + ResOptionsFlags = oldoptions; + return; + } + case RES_CELL: + selectedUse = CmdGetSelectedCell((Transform *) NULL); + if (selectedUse == NULL) + { + TxError("No cell selected\n"); + return; + } + mainDef = selectedUse->cu_def; + ResOptionsFlags &= ~ResOpt_ExtractAll; + break; + + case RES_RUN: + ResOptionsFlags &= ~ResOpt_ExtractAll; + break; +#ifdef LAPLACE + case RES_LAPLACE: + LaplaceParseString(cmd); + return; +#endif + case RES_AMBIG: + TxPrintf("Ambiguous option: %s\n",cmd->tx_argv[1]); + TxFlushOut(); + return; + case RES_BAD: + TxPrintf("Unknown option: %s\n",cmd->tx_argv[1]); + TxFlushOut(); + return; + default: + return; + } + +#ifdef LAPLACE + LaplaceMatchCount = 0; + LaplaceMissCount = 0; +#endif + /* turn off undo stuff */ + UndoDisable(); + + if (!ToolGetBox(&mainDef,(Rect *) NULL)) + { + TxError("Couldn't find def corresponding to box\n"); + if ((option == RES_FASTHENRY) || (option == RES_GEOMETRY)) + ResOptionsFlags = saveFlags; + return; + } + ResOptionsFlags |= ResOpt_Signal; +#ifdef ARIEL + ResOptionsFlags &= ~ResOpt_Power; +#endif + + resisdata.tolerance = tolerance; + resisdata.tdiTolerance = tdiTolerance; + resisdata.frequency = fhFrequency; + resisdata.mainDef = mainDef; + + /* Do subcircuits (if any) first */ + if (!(ResOptionsFlags & ResOpt_Blackbox)) + (void) DBCellSrDefs(0, resSubcircuitFunc, (ClientData) &resisdata); + + ExtResisForDef(mainDef, &resisdata); + + /* turn back on undo stuff */ + UndoEnable(); +#ifdef LAPLACE + if (ResOptionsFlags & ResOpt_DoLaplace) + { + TxPrintf("Laplace solved: %d matched %d\n", + LaplaceMissCount, LaplaceMatchCount); + } +#endif + + /* Revert to the original flags in the case of FastHenry or */ + /* geometry centerline extraction. */ + + if ((option == RES_FASTHENRY) || (option == RES_GEOMETRY)) + ResOptionsFlags = saveFlags; + + return; +} + +/* + *------------------------------------------------------------------------- + * + * resSubcircuitFunc -- + * For each encountered cell, call the resistance extractor. + * + * Results: + * Always return 0 to keep search alive. + * + * Side Effects: + * Does resistance extraction for an entire cell. + * + *------------------------------------------------------------------------- + */ + +int +resSubcircuitFunc(cellDef, rdata) + CellDef *cellDef; + ResisData *rdata; +{ + if (cellDef != rdata->mainDef) + if (DBIsSubcircuit(cellDef)) + ExtResisForDef(cellDef, rdata); + return 0; +} + + + +/* + *------------------------------------------------------------------------- + * + * Callback routine for ResCheckBlackBox. For each label found in a + * subcell, transform the label position back to the top level and + * add to the list of nodes for extresis. + * + *------------------------------------------------------------------------- + */ + +int +resPortFunc(scx, lab, tpath, result) + SearchContext *scx; + Label *lab; + TerminalPath *tpath; + int *result; +{ + Rect r; + int pclass, puse; + Point portloc; + HashEntry *entry; + ResSimNode *node; + + GeoTransRect(&scx->scx_trans, &lab->lab_rect, &r); + + // To be expanded. Currently this handles digital signal inputs + // and outputs, for standard cells. + + if (lab->lab_flags & PORT_DIR_MASK) { + pclass = lab->lab_flags & PORT_CLASS_MASK; + puse = lab->lab_flags & PORT_USE_MASK; + + // Ad hoc rule: If port use is not declared, but port + // direction is either INPUT or OUTPUT, then use SIGNAL is implied. + + if ((puse == 0) && ((pclass == PORT_CLASS_INPUT) + || (pclass == PORT_CLASS_OUTPUT))) + puse = PORT_USE_SIGNAL; + + if (puse == PORT_USE_SIGNAL || puse == PORT_USE_CLOCK) { + + if (lab->lab_flags & (PORT_DIR_NORTH | PORT_DIR_SOUTH)) + portloc.p_x = (r.r_xbot + r.r_xtop) >> 1; + else if (lab->lab_flags & (PORT_DIR_EAST | PORT_DIR_WEST)) + portloc.p_y = (r.r_ybot + r.r_ytop) >> 1; + + if (lab->lab_flags & PORT_DIR_NORTH) + portloc.p_y = r.r_ytop; + if (lab->lab_flags & PORT_DIR_SOUTH) + portloc.p_y = r.r_ybot; + if (lab->lab_flags & PORT_DIR_EAST) + portloc.p_x = r.r_xtop; + if (lab->lab_flags & PORT_DIR_WEST) + portloc.p_x = r.r_xbot; + + if ((pclass == PORT_CLASS_INPUT) || (pclass == PORT_CLASS_OUTPUT)) { + int len; + char *nodename; + + // Port name is the instance name / pin name + // To do: Make use of tpath + len = strlen(scx->scx_use->cu_id) + strlen(lab->lab_text) + 2; + nodename = (char *) mallocMagic((unsigned) len); + sprintf(nodename, "%s/%s", scx->scx_use->cu_id, lab->lab_text); + + entry = HashFind(&ResNodeTable, nodename); + node = ResInitializeNode(entry); + + /* Digital outputs are drivers */ + if (pclass == PORT_CLASS_OUTPUT) node->status |= FORCE; + + node->drivepoint = portloc; + node->status |= DRIVELOC | PORTNODE; + node->rs_bbox = r; + node->location = portloc; + node->rs_ttype = lab->lab_type; + node->type = lab->lab_type; + + *result = 0; + freeMagic(nodename); + } + } + } + return 0; /* Keep the search going */ +} + +/* + *------------------------------------------------------------------------- + * + * ResCheckBlackbox-- + * + * For standard cell parasitic extraction, search all children + * of cellDef for ports, and add each port to the list of nodes + * for extresist to process. If the port use is "ground" or + * "power", then don't process the node. If the port class is + * "output", then make this node a (forced) driver. + * + * Results: 0 if one or more nodes was created, 1 otherwise + * + * Side Effects: Adds driving nodes to the extresis network database. + * + *------------------------------------------------------------------------- + */ + +int +ResCheckBlackbox(cellDef) + CellDef *cellDef; +{ + int result = 1; + SearchContext scx; + CellUse dummy; + + dummy.cu_expandMask = 0; + dummy.cu_transform = GeoIdentityTransform; + dummy.cu_def = cellDef; + dummy.cu_id = NULL; + + scx.scx_area = cellDef->cd_bbox; + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = (CellUse *)&dummy; + + /* Do a search on all children */ + + DBTreeSrLabels(&scx, &DBAllButSpaceAndDRCBits, 0, NULL, + TF_LABEL_ATTACH, resPortFunc, (ClientData)&result); + + return result; +} + +/* + *------------------------------------------------------------------------- + * + * ResCheckPorts-- + * + * Subcircuit boundaries mark an area which is to be checked + * explicitly for geometry information. Because there may be + * no transistors in the subcircuit cell, we must find the ports + * into the subcircuit and declare them to be "driving" nodes so + * the extresis algorithm will treat them as being part of valid + * networks. + * + * Results: 0 if one or more nodes was created, 1 otherwise + * + * Side Effects: Adds driving nodes to the extresis network database. + * + *------------------------------------------------------------------------- + */ + +int +ResCheckPorts(cellDef) + CellDef *cellDef; +{ + Point portloc; + Label *lab; + HashEntry *entry; + ResSimNode *node; + int result = 1; + + for (lab = cellDef->cd_labels; lab; lab = lab->lab_next) + { + if (lab->lab_flags & PORT_DIR_MASK) + { + /* Get drivepoint from the port connection direction(s) */ + /* NOTE: This is not rigorous! */ + + if (lab->lab_flags & (PORT_DIR_NORTH | PORT_DIR_SOUTH)) + portloc.p_x = (lab->lab_rect.r_xbot + lab->lab_rect.r_xtop) >> 1; + else if (lab->lab_flags & (PORT_DIR_EAST | PORT_DIR_WEST)) + portloc.p_y = (lab->lab_rect.r_ybot + lab->lab_rect.r_ytop) >> 1; + + if (lab->lab_flags & PORT_DIR_NORTH) + portloc.p_y = lab->lab_rect.r_ytop; + if (lab->lab_flags & PORT_DIR_SOUTH) + portloc.p_y = lab->lab_rect.r_ybot; + if (lab->lab_flags & PORT_DIR_EAST) + portloc.p_x = lab->lab_rect.r_xtop; + if (lab->lab_flags & PORT_DIR_WEST) + portloc.p_x = lab->lab_rect.r_xbot; + + entry = HashFind(&ResNodeTable, lab->lab_text); + result = 0; + if ((node = (ResSimNode *) HashGetValue(entry)) != NULL) + { + TxError("Port: name = %s exists, forcing drivepoint\n", + lab->lab_text); + TxError("Location is (%d, %d); drivepoint (%d, %d)\n", + node->location.p_x, node->location.p_y, + portloc.p_x, portloc.p_y); + TxFlushErr(); + node->drivepoint = portloc; + node->status |= FORCE; + } + else + { + /* This is a port, but it's merged with another node. */ + /* We have to make sure it's listed as a separate node */ + /* and a drivepoint. */ + + node = ResInitializeNode(entry); + TxError("Port: name = %s is new node 0x%x\n", + lab->lab_text, node); + TxError("Location is (%d, %d); drivepoint (%d, %d)\n", + portloc.p_x, portloc.p_y, + portloc.p_x, portloc.p_y); + node->location = portloc; + node->drivepoint = node->location; + } + node->status |= DRIVELOC | PORTNODE; + node->rs_bbox = lab->lab_rect; + node->rs_ttype = lab->lab_type; + node->type = lab->lab_type; + } + } + return result; +} + +/* + *------------------------------------------------------------------------- + * + * ResCheckSimNodes-- check to see if lumped resistance is greater than the + * transistor resistance; if it is, Extract the net + * resistance. If the maximum point to point resistance + * in the extracted net is still creater than the + * tolerance, then output the extracted net. + * + * Results: none + * + * Side Effects: Writes networks to .res.ext and .res.sim files. + * + *------------------------------------------------------------------------- + */ + +void +ResCheckSimNodes(celldef, resisdata) + CellDef *celldef; + ResisData *resisdata; +{ + ResSimNode *node; + tranPtr *ptr; + float ftolerance, rctolerance, minRes, cumRes; + int failed1=0; + int failed3=0; + int total =0; + char *outfile = celldef->cd_name; + float tol = resisdata->tolerance; + float rctol = resisdata->tdiTolerance; + int nidx = 1, eidx = 1; /* node & segment counters for geom. */ + + if (ResOptionsFlags & ResOpt_DoExtFile) + { + ResExtFile = PaOpen(outfile,"w",".res.ext",".",(char *) NULL, (char **) NULL); + } + else + { + ResExtFile = NULL; + } + if (ResOptionsFlags & ResOpt_DoLumpFile) + { + ResLumpFile = PaOpen(outfile,"w",".res.lump",".",(char *) NULL, (char **) NULL); + } + else + { + ResLumpFile = NULL; + } + if (ResOptionsFlags & ResOpt_FastHenry) + { + char *geofilename; + ResFHFile = PaOpen(outfile,"w",".fh",".",(char *) NULL, &geofilename); + TxPrintf("Writing FastHenry-format geometry file \"%s\"\n", geofilename); + ResPortIndex = 0; + } + else + { + ResFHFile = NULL; + } + + if (ResExtFile == NULL && (ResOptionsFlags & ResOpt_DoExtFile) + || (ResOptionsFlags & ResOpt_DoLumpFile) && ResLumpFile == NULL + || (ResOptionsFlags & ResOpt_FastHenry) && ResFHFile == NULL) + { + TxError("Couldn't open output file\n"); + return; + } + + /* + * Write reference plane (substrate) definition and end statement + * to the FastHenry geometry file. + */ + if (ResOptionsFlags & ResOpt_FastHenry) + { + ResPrintReference(ResFHFile, ResTranList, celldef); + } + + for (node = ResOriginalNodes; node != NULL; node=node->nextnode) + { + ResCurrentNode = node->name; + if (!(ResOptionsFlags & ResOpt_FastHenry)) + { + /* Hack!! Don't extract Vdd or GND lines */ + + char *last4, *last3; + last4 = node->name+strlen(node->name)-4; + last3 = node->name+strlen(node->name)-3; + + if ((strncmp(last4,"Vdd!",4) == 0 || + strncmp(last4,"VDD!",4) == 0 || + strncmp(last4,"vdd!",4) == 0 || + strncmp(last4,"Gnd!",4) == 0 || + strncmp(last4,"gnd!",4) == 0 || + strncmp(last4,"GND!",4) == 0 || + strncmp(last3,"Vdd",3) == 0 || + strncmp(last3,"VDD",3) == 0 || + strncmp(last3,"vdd",3) == 0 || + strncmp(last3,"Gnd",3) == 0 || + strncmp(last3,"gnd",3) == 0 || + strncmp(last3,"GND",3) == 0) && + (node->status & FORCE) != FORCE) continue; + } + + /* Has this node been merged away or is it marked as skipped? */ + /* If so, skip it */ + if ((node->status & (FORWARD | REDUNDANT)) || + ((node->status & SKIP) && + (ResOptionsFlags & ResOpt_ExtractAll) == 0)) + continue; + total++; + + ResSortByGate(&node->firstTran); + /* Find largest SD transistor connected to node. */ + + minRes = FLT_MAX; + gparams.rg_tranloc = (Point *) NULL; + gparams.rg_status = FALSE; + gparams.rg_nodecap = node->capacitance; + + /* the following is only used if there is a drivepoint */ + /* to identify which tile the drivepoint is on. */ + gparams.rg_ttype = node->rs_ttype; + + for (ptr = node->firstTran; ptr != NULL; ptr=ptr->nextTran) + { + RTran *t1; + RTran *t2; + + if (ptr->terminal == GATE) + { + break; + } + else + { + /* get cumulative resistance of all transistors */ + /* with same connections. */ + cumRes = ptr->thisTran->resistance; + t1 = ptr->thisTran; + for (; ptr->nextTran != NULL; ptr = ptr->nextTran) + { + t1 = ptr->thisTran; + t2 = ptr->nextTran->thisTran; + if (t1->gate != t2->gate) break; + if ((t1->source != t2->source || + t1->drain != t2->drain) && + (t1->source != t2->drain || + t1->drain != t2->source)) break; + + /* do parallel combination */ + if (cumRes != 0.0 && t2->resistance != 0.0) + { + cumRes = (cumRes * t2->resistance) / + (cumRes + t2->resistance); + } + else + { + cumRes = 0; + } + } + if (minRes > cumRes) + { + minRes = cumRes; + gparams.rg_tranloc = &t1->location; + gparams.rg_ttype = t1->rs_ttype; + } + } + } + + /* special handling for FORCE and DRIVELOC labels: */ + /* set minRes = node->minsizeres if it exists, 0 otherwise */ + + if (node->status & (FORCE|DRIVELOC)) + { + if (node->status & MINSIZE) + { + minRes = node->minsizeres; + } + else + { + minRes = 0; + } + if (node->status & DRIVELOC) + { + gparams.rg_tranloc = &node->drivepoint; + gparams.rg_status |= DRIVEONLY; + } + } + if (gparams.rg_tranloc == NULL && node->status & FORCE) + { + TxError("Node %s has force label but no drive point or " + "driving transistor\n",node->name); + } + if (minRes == FLT_MAX || gparams.rg_tranloc == NULL) + { + continue; + } + gparams.rg_bigtranres = (int)minRes*OHMSTOMILLIOHMS; + if (rctol == 0.0 || tol == 0.0) + { + ftolerance = 0.0; + rctolerance = 0.0; + } + else + { + ftolerance = minRes/tol; + rctolerance = minRes/rctol; + } + + /* + * Is the transistor resistance greater than the lumped node + * resistance? If so, extract net. + */ + + if (node->resistance > ftolerance || node->status & FORCE || + (ResOpt_ExtractAll & ResOptionsFlags)) + { + ResFixPoint fp; + + failed1++; + fp.fp_loc = node->location; + fp.fp_ttype = node->type; + fp.fp_next = NULL; + if (ResExtractNet(&fp, &gparams, outfile) != 0) + { + TxError("Error in extracting node %s\n",node->name); + // break; // Don't stop for one error. . . + } + else + { + ResDoSimplify(ftolerance,rctol,&gparams); + if (ResOptionsFlags & ResOpt_DoLumpFile) + { + ResWriteLumpFile(node); + } + if (gparams.rg_maxres >= ftolerance || + gparams.rg_maxres >= rctolerance || + (ResOptionsFlags & ResOpt_ExtractAll)) + { + resNodeNum = 0; + failed3 += ResWriteExtFile(celldef, node, tol, rctol, + &nidx, &eidx); + } + } +#ifdef PARANOID + ResSanityChecks(node->name,ResResList,ResNodeList,ResTransList); +#endif + ResCleanUpEverything(); + } + } + + /* + * Print out all transistors which have had at least one terminal changed + * by resistance extraction. + */ + + if (ResOptionsFlags & ResOpt_DoExtFile) + { + ResPrintExtTran(ResExtFile,ResTranList); + } + + /* + * Write end statement to the FastHenry geometry file. + * (Frequency range should be user-specified. . .) + */ + + if (ResOptionsFlags & ResOpt_FastHenry) + { + Label *lab; + + fprintf(ResFHFile, "\n.freq fmin=%2.1g fmax=%2.1g\n", + resisdata->frequency, resisdata->frequency); + + /*----------------------------------------------------------------------*/ + /* Write (in comment lines) the order in which arguments are written */ + /* to a SPICE subcircuit call when Magic runs ext2spice (exttospice). */ + /* At present, it is the responsibility of the program that generates */ + /* SPICE from FastHenry output to use this information to appropriately */ + /* order the arguments in the ".subckt" definition. */ + /*----------------------------------------------------------------------*/ + + fprintf(ResFHFile, "\n* Order of arguments to SPICE subcircuit call:\n"); + for (lab = celldef->cd_labels; lab != NULL; lab = lab->lab_next) + if (lab->lab_flags & PORT_DIR_MASK) + fprintf(ResFHFile, "* %d %s\n", lab->lab_flags & PORT_NUM_MASK, + lab->lab_text); + + fprintf(ResFHFile, "\n.end\n"); + } + + /* Output statistics about extraction */ + + if (total) + { + TxError("Total Nets: %d\nNets extracted: " + "%d (%f)\nNets output: %d (%f)\n", total, failed1, + (float)failed1 / (float)total, failed3, + (float)failed3 / (float)total); + } + else + { + TxError("Total Nodes: %d\n",total); + } + + /* close output files */ + + if (ResExtFile != NULL) + { + (void) fclose(ResExtFile); + } + if (ResLumpFile != NULL) + { + (void) fclose(ResLumpFile); + } + if (ResFHFile != NULL) + { + (void) fclose(ResFHFile); + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResFixUpConnections-- Changes the connection to a terminal of the sim + * transistor. The new name is formed by appending .t# to the old name. + * The new name is added to the hash table of node names. + * + * Results:none + * + * Side Effects: Allocates new ResSimNodes. Modifies the terminal connections + * of sim Transistors. + * + *------------------------------------------------------------------------- + */ + +void +ResFixUpConnections(simTran, layoutTran, simNode, nodename) + RTran *simTran; + resTransistor *layoutTran; + ResSimNode *simNode; + char *nodename; + +{ + static char newname[MAXNAME], oldnodename[MAXNAME]; + int notdecremented; + resNode *gate, *source, *drain; + + /* If we aren't doing output (i.e. this is just a statistical run) */ + /* don't patch up networks. This cuts down on memory use. */ + + if ((ResOptionsFlags & (ResOpt_DoRsmFile | ResOpt_DoExtFile)) == 0) + { + return; + } + if (simTran->layout == NULL) + { + layoutTran->rt_status |= RES_TRAN_SAVE; + simTran->layout = layoutTran; + } + simTran->status |= TRUE; + if (strcmp(nodename,oldnodename) != 0) + { + strcpy(oldnodename,nodename); + } + (void)sprintf(newname,"%s%s%d",nodename,".t",resNodeNum++); + notdecremented = TRUE; + + if (simTran->gate == simNode) + { + if ((gate=layoutTran->rt_gate) != NULL) + { + /* cosmetic addition: If the layout tran already has a */ + /* name, the new one won't be used, so we decrement resNodeNum */ + if (gate->rn_name != NULL) + { + resNodeNum--; + notdecremented = FALSE; + } + + ResFixTranName(newname,GATE,simTran,gate); + gate->rn_name = simTran->gate->name; + (void)sprintf(newname,"%s%s%d",nodename,".t",resNodeNum++); + } + else + { + TxError("Missing gate connection\n"); + } + } + if (simTran->source == simNode) + { + if (simTran->drain == simNode) + { + if ((source=layoutTran->rt_source) && + (drain=layoutTran->rt_drain)) + { + if (source->rn_name != NULL && notdecremented) + { + resNodeNum--; + notdecremented = FALSE; + } + ResFixTranName(newname,SOURCE,simTran,source); + source->rn_name = simTran->source->name; + (void)sprintf(newname,"%s%s%d",nodename,".t",resNodeNum++); + if (drain->rn_name != NULL) resNodeNum--; + ResFixTranName(newname,DRAIN,simTran,drain); + drain->rn_name = simTran->drain->name; + /* one to each */ + } + else + { + TxError("Missing SD connection\n"); + } + } + else + { + if (source=layoutTran->rt_source) + { + if (drain=layoutTran->rt_drain) + { + if (source != drain) + { + if (drain->rn_why & RES_NODE_ORIGIN) + { + ResMergeNodes(drain, source, &ResNodeQueue, + &ResNodeList); + ResDoneWithNode(drain); + source = drain; + } + else + { + ResMergeNodes(source, drain, &ResNodeQueue, + &ResNodeList); + ResDoneWithNode(source); + drain = source; + } + } + layoutTran->rt_drain = (resNode *)NULL; + if (source->rn_name != NULL) resNodeNum--; + ResFixTranName(newname,SOURCE,simTran,source); + source->rn_name = simTran->source->name; + } + else + { + if (source->rn_name != NULL && notdecremented) + { + resNodeNum--; + notdecremented = FALSE; + } + ResFixTranName(newname,SOURCE,simTran,source); + source->rn_name = simTran->source->name; + } + + } + else + { + TxError("missing SD connection\n"); + } + } + } + else if (simTran->drain == simNode) + { + if (source=layoutTran->rt_source) + { + if (drain=layoutTran->rt_drain) + { + if (drain != source) + { + if (drain->rn_why & ORIGIN) + { + ResMergeNodes(drain, source, &ResNodeQueue, + &ResNodeList); + ResDoneWithNode(drain); + source = drain; + } + else + { + ResMergeNodes(source, drain, &ResNodeQueue, + &ResNodeList); + ResDoneWithNode(source); + drain = source; + } + } + layoutTran->rt_source = (resNode *) NULL; + if (drain->rn_name != NULL) + { + resNodeNum--; + notdecremented = FALSE; + } + ResFixTranName(newname, DRAIN, simTran, drain); + drain->rn_name = simTran->drain->name; + } + else + { + if (source->rn_name != NULL && notdecremented) + { + resNodeNum--; + notdecremented = FALSE; + } + ResFixTranName(newname,DRAIN,simTran,source); + source->rn_name = simTran->drain->name; + } + } + else + { + TxError("missing SD connection\n"); + } + } + else + { + resNodeNum--; + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResFixTranName-- Moves transistor connection to new node. + * + * Results: + * None. + * + * Side Effects: May create a new node. Creates a new transistor pointer. + * + *------------------------------------------------------------------------- + */ + +void +ResFixTranName(line,type,transistor,layoutnode) + char line[]; + int type; + RTran *transistor; + resNode *layoutnode; + +{ + HashEntry *entry; + ResSimNode *node; + tranPtr *tptr; + + if (layoutnode->rn_name != NULL) + { + entry = HashFind(&ResNodeTable,layoutnode->rn_name); + node = ResInitializeNode(entry); + + } + else + { + entry = HashFind(&ResNodeTable,line); + node = ResInitializeNode(entry); + } + tptr = (tranPtr *) mallocMagic((unsigned) (sizeof(tranPtr))); + tptr->thisTran = transistor; + tptr->nextTran = node->firstTran; + node->firstTran = tptr; + tptr->terminal = type; + switch(type) + { + case GATE: + node->oldname = transistor->gate->name; + transistor->gate = node; + break; + case SOURCE: + node->oldname = transistor->source->name; + transistor->source = node; + break; + case DRAIN: + node->oldname = transistor->drain->name; + transistor->drain = node; + break; + default: + TxError("Bad Terminal Specifier\n"); + break; + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResSortByGate--sorts transistor pointers whose terminal field is either + * drain or source by gate node number, then by drain (source) number. + * This places transistors with identical connections next to one + * another. + * + * Results: none + * + * Side Effects: modifies order of transistors + * + *------------------------------------------------------------------------- + */ + +void +ResSortByGate(TranpointerList) + tranPtr **TranpointerList; +{ + int changed=TRUE; + int localchange=TRUE; + tranPtr *working, *last=NULL, *current, *gatelist=NULL; + + working = *TranpointerList; + while (working != NULL) + { + if (working->terminal == GATE) + { + current = working; + working = working->nextTran; + if (last == NULL) + { + *TranpointerList = working; + } + else + { + last->nextTran = working; + } + current->nextTran = gatelist; + gatelist = current; + } + else + { + last = working; + working = working->nextTran; + } + } + while (changed == TRUE) + { + changed = localchange = FALSE; + working = *TranpointerList; + last = NULL; + while (working != NULL && (current = working->nextTran) != NULL) + { + RTran *w = working->thisTran; + RTran *c = current->thisTran; + + if (w->gate > c->gate) + { + changed = TRUE; + localchange = TRUE; + } + else if (w->gate == c->gate && + (working->terminal == SOURCE && + current->terminal == SOURCE && + w->drain > c->drain || + working->terminal == SOURCE && + current->terminal == DRAIN && + w->drain > c->source || + working->terminal == DRAIN && + current->terminal == SOURCE && + w->source > c->drain || + working->terminal == DRAIN && + current->terminal == DRAIN && + w->source > c->source)) + { + changed = TRUE; + localchange = TRUE; + } + else + { + last = working; + working = working->nextTran; + continue; + } + if (localchange) + { + localchange = FALSE; + if (last == NULL) + { + *TranpointerList = current; + } + else + { + last->nextTran = current; + } + working->nextTran = current->nextTran; + current->nextTran = working; + last = current; + } + } + } + if (working == NULL) + { + *TranpointerList = gatelist; + } + else + { + if (working->nextTran != NULL) + { + TxError("Bad Transistor pointer in sort\n"); + } + else + { + working->nextTran = gatelist; + } + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResWriteLumpFile + * + * Results: none + * + * Side Effects: + * + *------------------------------------------------------------------------- + */ + +void +ResWriteLumpFile(node) + ResSimNode *node; +{ + int lumpedres; + + if (ResOptionsFlags & ResOpt_Tdi) + { + if (gparams.rg_nodecap != 0) + { + lumpedres = (int)((gparams.rg_Tdi/gparams.rg_nodecap + -(float)(gparams.rg_bigtranres))/OHMSTOMILLIOHMS); + } + else + { + lumpedres = 0; + } + } + else + { + lumpedres = gparams.rg_maxres; + } + fprintf(ResLumpFile,"R %s %d\n", node->name, lumpedres); +} + + +/* + *------------------------------------------------------------------------- + * + * ResAlignNodes -- + * Attempt to put nodes onto a Manhattan grid. + * At the same time, assign height values to nodes and thickness + * values to resistors. + * + *------------------------------------------------------------------------- + */ + +void +ResAlignNodes(nodelist, reslist) + resNode *nodelist; + resResistor *reslist; +{ + resResistor *resistor; + resNode *node1; + short i; + + for (resistor = reslist; resistor->rr_nextResistor != NULL; + resistor = resistor->rr_nextResistor) + { + /* Don't try to align nodes which came from split */ + /* tiles; we assume that the geometry there is */ + /* supposed to be non-Manhattan. */ + + if (resistor->rr_status & RES_DIAGONAL) continue; + + for (i = 0; i < 2; i++) + { + node1 = resistor->rr_node[i]; + if (resistor->rr_status & RES_EW) + { + if (node1->rn_loc.p_y != resistor->rr_cl) + { + if (node1->rn_status & RES_NODE_YADJ) + TxError("Warning: contention over node Y position\n"); + node1->rn_loc.p_y = resistor->rr_cl; + node1->rn_status |= RES_NODE_YADJ; + } + } + else if (resistor->rr_status & RES_NS) + { + if (node1->rn_loc.p_x != resistor->rr_cl) + { + if (node1->rn_status & RES_NODE_XADJ) + TxError("Warning: contention over node X position\n"); + node1->rn_loc.p_x = resistor->rr_cl; + node1->rn_status |= RES_NODE_XADJ; + } + } + } + } +} + +/* + *------------------------------------------------------------------------- + * + * ResWriteExtFile -- + * + * Results: + * 1 if output was generated + * 0 if no output was generated + * + * Side Effects: + * + *------------------------------------------------------------------------- + */ + +int +ResWriteExtFile(celldef, node, tol, rctol, nidx, eidx) + CellDef *celldef; + ResSimNode *node; + float tol, rctol; + int *nidx, *eidx; +{ + float RCtran; + char *cp, newname[MAXNAME]; + tranPtr *ptr; + resTransistor *layoutFet, *ResGetTransistor(); + + RCtran = gparams.rg_bigtranres * gparams.rg_nodecap; + + if (tol == 0.0 ||(node->status & FORCE) || + (ResOptionsFlags & ResOpt_ExtractAll)|| + (ResOptionsFlags & ResOpt_Simplify)==0|| + (rctol+1)*RCtran < rctol*gparams.rg_Tdi) + { + ASSERT(gparams.rg_Tdi != -1,"ResWriteExtFile"); + (void)sprintf(newname,"%s",node->name); + cp = newname+strlen(newname)-1; + if (*cp == '!' || *cp == '#') *cp = '\0'; + if ((rctol+1)*RCtran < rctol*gparams.rg_Tdi || + (ResOptionsFlags & ResOpt_Tdi) == 0) + { + if ((ResOptionsFlags & (ResOpt_RunSilent|ResOpt_Tdi)) == ResOpt_Tdi) + { + TxError("Adding %s; Tnew = %.2fns,Told = %.2fns\n", + node->name,gparams.rg_Tdi/Z_TO_N, RCtran/Z_TO_N); + } + } + for (ptr = node->firstTran; ptr != NULL; ptr=ptr->nextTran) + { + if (layoutFet = ResGetTransistor(&ptr->thisTran->location)) + { + ResFixUpConnections(ptr->thisTran,layoutFet,node,newname); + } + } + if (ResOptionsFlags & ResOpt_DoExtFile) + { + ResPrintExtNode(ResExtFile,ResNodeList,node->name); + ResPrintExtRes(ResExtFile,ResResList,newname); + } + if (ResOptionsFlags & ResOpt_FastHenry) + { + if (ResResList) + ResAlignNodes(ResNodeList, ResResList); + ResPrintFHNodes(ResFHFile, ResNodeList, node->name, nidx, celldef); + ResPrintFHRects(ResFHFile, ResResList, newname, eidx); + } + if (ResOptionsFlags & ResOpt_Geometry) + { + if (ResResList) + ResAlignNodes(ResNodeList, ResResList); + if (ResCreateCenterlines(ResResList, nidx, celldef) < 0) + return 0; + } + return 1; + } + else return 0; +} + diff --git a/resis/ResSimple.c b/resis/ResSimple.c new file mode 100644 index 00000000..b4147523 --- /dev/null +++ b/resis/ResSimple.c @@ -0,0 +1,1163 @@ +/* + *------------------------------------------------------------------------- + * + * ResSimplify -- contains routines used to simplify signal nets. + * + * + * + *------------------------------------------------------------------------- + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResSimple.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/stack.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "resis/resis.h" + +#define MILLIOHMSPEROHM 1000 + +/* Forward declarations */ +void ResSetPathRes(); +void resPathNode(); +void resPathRes(); +Heap ResistorHeap; +int resRemoveLoops = FALSE; + +/* Forward declarations */ + +extern void ResMoveTransistors(); +extern void ResAddResistorToList(); + + + +/* + *------------------------------------------------------------------------- + * + * ResSimplifyNet- Reduces complete (?) net produced by ResProcessTiles into + * something a little less chaotic. + * + * Results: none + * + * Side Effects: Can eliminate nodes and resistors, and move transistors from + * one node to another. + * + *------------------------------------------------------------------------- + */ + +void +ResSimplifyNet(nodelist,biglist,reslist,tolerance) + resNode **nodelist,**biglist; + resResistor **reslist; + float tolerance; + +{ + resElement *resisptr; + resNode *node,*otherNode,*node1,*node2; + resResistor *resistor1 = NULL,*resistor2 = NULL; + int numdrive = 0, numreceive = 0; + int MarkedReceivers,UnMarkedReceivers,NumberOfDrivers,PendingReceivers; + + if (*nodelist == NULL) return; + node = *nodelist; + node->rn_status |= MARKED | FINISHED; + *nodelist = node->rn_more; + if (node->rn_more != NULL) + { + node->rn_more->rn_less = (resNode *) NULL; + } + node->rn_more = *biglist; + if (*biglist != (resNode *) NULL) + { + (*biglist)->rn_less = node; + } + *biglist = node; + + /* + Walk though resistors. Mark uninitialized ones and assign them + A direction. Keep track of the number of resistors pointing in + each direction. + */ + for (resisptr = node->rn_re; resisptr != NULL; resisptr = resisptr->re_nextEl) + { + if (((resisptr->re_thisEl->rr_status & RES_MARKED) == RES_MARKED) && + (resisptr->re_thisEl->rr_connection2 == node)) + { + if (resistor1 == NULL) + { + resistor1 = resisptr->re_thisEl; + } + else + { + resistor2 = resisptr->re_thisEl; + } + numdrive++; + } + else + { + /* + Resistor direction is from node1 to node2. If the resistor + is not marked, mark it and make sure the direction is + set properly. + */ + + if ((resisptr->re_thisEl->rr_status & RES_MARKED) != RES_MARKED) + { + if (resisptr->re_thisEl->rr_connection2 == node) + { + resisptr->re_thisEl->rr_connection2 = resisptr->re_thisEl->rr_connection1; + resisptr->re_thisEl->rr_connection1 = node; + } + resisptr->re_thisEl->rr_status |= RES_MARKED; + } + if (resistor1 == NULL) + { + resistor1 = resisptr->re_thisEl; + } + else + { + resistor2 = resisptr->re_thisEl; + } + numreceive++; + } + } + + /* + Is the node reached by one resistor? If it is, check the resistor's + other end. Check the number of drivers at the other end. If it is + more than 1, delete the current resistor to break the deadlock. + */ + if (numreceive == 0 && numdrive == 1 && node->rn_why != RES_NODE_ORIGIN) + { + resistor1->rr_status |= RES_DEADEND; + if (resistor1->rr_value < tolerance) + { + otherNode = (resistor1->rr_connection1 == node) ? resistor1->rr_connection2 : resistor1->rr_connection1; + MarkedReceivers = 0; + UnMarkedReceivers = 0; + NumberOfDrivers = 0; + PendingReceivers = 0; + resistor2 = resistor1; + for (resisptr = otherNode->rn_re; resisptr != NULL; resisptr=resisptr->re_nextEl) + { + if (resisptr->re_thisEl->rr_connection1 == otherNode) + { + if ((resisptr->re_thisEl->rr_connection2->rn_status & MARKED) != MARKED) + { + PendingReceivers++; + } + if (resisptr->re_thisEl->rr_status & RES_DEADEND || + resisptr->re_thisEl->rr_value > tolerance) + { + MarkedReceivers++; + resistor2 = (resisptr->re_thisEl->rr_value >= resistor2->rr_value) ? resisptr->re_thisEl : resistor2; + } + else + { + UnMarkedReceivers++; + } + } + else + { + NumberOfDrivers++; + } + } + /* other recievers at far end? If so, reschedule other node; + deadlock will be settled from that node. + */ + if ((MarkedReceivers+UnMarkedReceivers+NumberOfDrivers == 2) || + (UnMarkedReceivers == 0 && MarkedReceivers > 1 && resistor2 == resistor1 && PendingReceivers == 0)) + { + if (otherNode->rn_status & MARKED) + { + otherNode->rn_status &= ~MARKED; + ResRemoveFromQueue(otherNode,biglist); + otherNode->rn_less= NULL; + otherNode->rn_more = *nodelist; + if (*nodelist != NULL) + { + (*nodelist)->rn_less = otherNode; + } + *nodelist = otherNode; + } + return; + } + + /* + Break loop here. More than one driver indicates a loop; + remove deadend, allowing drivers to be merged + */ + else if (UnMarkedReceivers == 0 && (MarkedReceivers == 1 && NumberOfDrivers > 1 || resistor2 != resistor1)) + + { + otherNode->rn_float.rn_area += resistor1->rr_float.rr_area; + otherNode->rn_status &= ~RES_DONE_ONCE; + ResDeleteResPointer(resistor1->rr_connection1,resistor1); + ResDeleteResPointer(resistor1->rr_connection2,resistor1); + ResEliminateResistor(resistor1,reslist); + ResMergeNodes(otherNode,node,nodelist,biglist); + if (otherNode->rn_status & MARKED) + { + otherNode->rn_status &= ~MARKED; + ResRemoveFromQueue(otherNode,biglist); + otherNode->rn_less= NULL; + otherNode->rn_more = *nodelist; + if (*nodelist != NULL) + { + (*nodelist)->rn_less = otherNode; + } + *nodelist = otherNode; + } + ResDoneWithNode(otherNode); + } + } + + } + /* + Two resistors in series? Combine them and move transistors to + appropriate end. + */ + else if (numdrive+numreceive == 2 && + (resistor1->rr_value < tolerance && resistor2->rr_value < tolerance)) + { + if ((resistor1->rr_status & RES_MARKED) == 0 && (resistor1->rr_connection2 == node)) + { + resistor1->rr_connection2 = resistor1->rr_connection1; + resistor1->rr_connection1 = node; + } + resistor1->rr_status |= RES_MARKED; + if ((resistor2->rr_status & RES_MARKED) == 0 && (resistor2->rr_connection2 == node)) + { + resistor2->rr_connection2 = resistor2->rr_connection1; + resistor2->rr_connection1 = node; + } + resistor2->rr_status |= RES_MARKED; + node1 = (resistor1->rr_connection1 == node) ? resistor1->rr_connection2 : resistor1->rr_connection1; + node2 = (resistor2->rr_connection1 == node) ? resistor2->rr_connection2 : resistor2->rr_connection1; + otherNode = (resistor1->rr_status & RES_DEADEND && + resistor1->rr_value < tolerance / 2) || + ((resistor2->rr_status & RES_DEADEND) == 0 && + resistor1->rr_value < resistor2->rr_value) ? node1 : node2; + + /* + make one big resistor out of two little ones, eliminating + the current node. Transistors connected to this node are + moved to either end depending on their resistance. + */ + ResMoveTransistors(node,otherNode); + otherNode->rn_noderes = MIN(node->rn_noderes,otherNode->rn_noderes); + node2->rn_float.rn_area += resistor1->rr_value*node->rn_float.rn_area/(resistor1->rr_value+resistor2->rr_value); + node1->rn_float.rn_area += resistor2->rr_value*node->rn_float.rn_area/(resistor1->rr_value+resistor2->rr_value); + resistor1->rr_value += resistor2->rr_value; + resistor1->rr_float.rr_area +=resistor2->rr_float.rr_area; + if (resistor1 == *reslist) + { + *reslist = resistor1->rr_nextResistor; + } + else + { + resistor1->rr_lastResistor->rr_nextResistor = resistor1->rr_nextResistor; + } + if (resistor1->rr_nextResistor != NULL) + { + resistor1->rr_nextResistor->rr_lastResistor = resistor1->rr_lastResistor; + } + ResAddResistorToList(resistor1,reslist); + ResDeleteResPointer(node,resistor1); + ResDeleteResPointer(node,resistor2); + ResDeleteResPointer(node2,resistor2); + if (resistor1->rr_connection1 == node) + { + resistor1->rr_connection1 = node2; + } + else + { + resistor1->rr_connection2 = node2; + } + resisptr = (resElement *) mallocMagic((unsigned)(sizeof(resElement))); + resisptr->re_thisEl = resistor1; + resisptr->re_nextEl = node2->rn_re; + node2->rn_re = resisptr; + ResEliminateResistor(resistor2,reslist); + otherNode->rn_status |= (node->rn_status & RN_MAXTDI); + ResCleanNode(node,TRUE,biglist,nodelist); + node1->rn_status &= ~RES_DONE_ONCE; + if (node1->rn_status & MARKED) + { + node1->rn_status &= ~MARKED; + ResRemoveFromQueue(node1,biglist); + node1->rn_less= NULL; + node1->rn_more = *nodelist; + if (*nodelist != NULL) + { + (*nodelist)->rn_less = node1; + } + *nodelist = node1; + } + node2->rn_status &= ~RES_DONE_ONCE; + if (node2->rn_status & MARKED) + { + node2->rn_status &= ~MARKED; + ResRemoveFromQueue(node2,biglist); + node2->rn_less= NULL; + node2->rn_more = *nodelist; + if (*nodelist != NULL) + { + (*nodelist)->rn_less = node2; + } + *nodelist = node2; + } + ResDoneWithNode(node1); + } + + /* + Last resort- keep propagating down the tree. To avoid looping, + mark each node when it is reached. Don't reschedule node if + none of the connections to it have changed since it was marked + */ + else if (numreceive > 0 && (node->rn_status & RES_DONE_ONCE) == 0) + { + node->rn_status |= RES_DONE_ONCE; + for (resisptr = node->rn_re; resisptr != NULL; resisptr = resisptr->re_nextEl) + { + if (resisptr->re_thisEl->rr_connection1 == node) + { + /* + elements with a resistance greater than the + tolerance should only be propagated past once- + loops may occur otherwise. + */ + if (resisptr->re_thisEl->rr_status & RES_DONE_ONCE) + { + continue; + } + if (resisptr->re_thisEl->rr_connection2->rn_status & MARKED) + { + /* + mark big resistors so we only process them + once. + */ + if (resisptr->re_thisEl->rr_value > tolerance) + { + resisptr->re_thisEl->rr_status |= RES_DONE_ONCE; + } + resisptr->re_thisEl->rr_connection2->rn_status &= ~MARKED; + ResRemoveFromQueue(resisptr->re_thisEl->rr_connection2,biglist); + resisptr->re_thisEl->rr_connection2->rn_less= NULL; + resisptr->re_thisEl->rr_connection2->rn_more = *nodelist; + if (*nodelist != NULL) + { + (*nodelist)->rn_less = resisptr->re_thisEl->rr_connection2; + } + *nodelist = resisptr->re_thisEl->rr_connection2; + } + } + } + } +} + + + +/* + *------------------------------------------------------------------------- + * + * ResMoveTransistors-- move transistors from one node1 to node2 + * + * Results: none + * + * Side Effects: Changes transistor connections and node tElements. + * + *------------------------------------------------------------------------- + */ + +void +ResMoveTransistors(node1,node2) + resNode *node1,*node2; + +{ + tElement *tranptr,*oldptr; + resTransistor *transistor; + + tranptr = node1->rn_te; + while (tranptr != NULL) + { + transistor = tranptr->te_thist; + oldptr = tranptr; + tranptr = tranptr->te_nextt; + if (transistor->rt_status & RES_TRAN_PLUG) + { + if (((ResPlug *)(transistor))->rpl_node == node1) + { + ((ResPlug *)(transistor))->rpl_node = node2; + } + else + { + TxError("Bad node connection in plug\n"); + } + } + else + { + if (transistor->rt_gate == node1) + { + transistor->rt_gate = node2; + } + else if (transistor->rt_source == node1) + { + transistor->rt_source = node2; + } + else if (transistor->rt_drain == node1) + { + transistor->rt_drain = node2; + } + else + { + TxError("Missing Transistor connection in squish routines at %d, %d\n",node1->rn_loc.p_x,node1->rn_loc.p_y); + } + } + oldptr->te_nextt = node2->rn_te; + node2->rn_te = oldptr; + } + node1->rn_te = NULL; +} + + +/* + *------------------------------------------------------------------------- + * + * ResScrunchNet-- Last ditch net simplification. Used to break deadlocks + * in ResSimplifyNet. Resistors are sorted by value. The smallest + * resistor is combined with its smallest neighbor, and ResSimplifyNet + * is called. This continues until the smallest resistor is greater + * than the tolerance. + * + * Results:none + * + * Side Effects: Nodes and resistors are eliminated. + * + *------------------------------------------------------------------------- + */ + +void +ResScrunchNet(reslist,pendingList,biglist,tolerance) + resResistor **reslist; + resNode **pendingList,**biglist; + float tolerance; + +{ + resResistor *locallist=NULL,*current,*working; + resNode *node1,*node2; + resElement *rcell1; + int c1,c2; + + /* sort resistors by size */ + current = *reslist; + while (current != NULL) + { + working = current; + current = current->rr_nextResistor; + if (working == *reslist) + { + *reslist = current; + } + else + { + working->rr_lastResistor->rr_nextResistor = current; + } + if (current != NULL) + { + current->rr_lastResistor = working->rr_lastResistor; + } + ResAddResistorToList(working,&locallist); + } + + + *reslist = locallist; + while (*reslist != NULL && (*reslist)->rr_value < tolerance) + { + current = *reslist; + if (current->rr_nextResistor == NULL) + { + break; + } + working = NULL; + c1=0; + c2=0; + + /* search for next smallest adjoining resistor */ + for (rcell1 = current->rr_connection1->rn_re; rcell1 != NULL; rcell1 = rcell1->re_nextEl) + { + if (rcell1->re_thisEl != current) + { + c1++; + if (working == NULL) + { + working = rcell1->re_thisEl; + node1 = current->rr_connection1; + } + else + { + if (working->rr_value > rcell1->re_thisEl->rr_value) + { + node1 = current->rr_connection1; + working = rcell1->re_thisEl; + } + } + } + } + for (rcell1 = current->rr_connection2->rn_re; rcell1 != NULL; rcell1 = rcell1->re_nextEl) + { + if (rcell1->re_thisEl != current) + { + c2++; + if (working == NULL) + { + working = rcell1->re_thisEl; + node1 = current->rr_connection2; + } + else + { + if (working->rr_value > rcell1->re_thisEl->rr_value) + { + node1 = current->rr_connection2; + working = rcell1->re_thisEl; + } + } + } + } + /* + if the current resistor isn't a deadend, add its value and + area to that of the next smallest one. If it is a deadend, + simply add its area to its node. + */ + if (c1 != 0 && c2 != 0) + { + working->rr_value += current->rr_value; + working->rr_float.rr_area += current->rr_float.rr_area; + } + else + { + node1->rn_float.rn_area += current->rr_float.rr_area; + } + /* + Move everything from from one end of the ressistor to the + other and eliminate the resistor. + */ + node2 = (current->rr_connection1 == node1) ? current->rr_connection2 : current->rr_connection1; + ResDeleteResPointer(current->rr_connection1,current); + ResDeleteResPointer(current->rr_connection2,current); + working->rr_lastResistor->rr_nextResistor = working->rr_nextResistor; + if (working->rr_nextResistor != NULL) + { + working->rr_nextResistor->rr_lastResistor = working->rr_lastResistor; + } + ResEliminateResistor(current,reslist); + ResAddResistorToList(working,reslist); + if (node2->rn_why & RES_NODE_ORIGIN) + { + ResMergeNodes(node2,node1,pendingList,biglist); + node1 = node2; + } + else + { + ResMergeNodes(node1,node2,pendingList,biglist); + } + + /* + Try further simplification on net using ResDoneWithNode and + ResSimplifyNet. + */ + ResRemoveFromQueue(node1,biglist); + ResAddToQueue(node1,pendingList); + node1->rn_status &= ~(RES_DONE_ONCE | FINISHED); + ResDoneWithNode(node1); + while (*pendingList != NULL) + { + ResSimplifyNet(pendingList,biglist,reslist,tolerance); + } + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResAddResistorToList-- Adds resistor to list according to its value + * (smallest first). + * + * Results:none + * + * Side Effects: modifies locallist. + * + *------------------------------------------------------------------------- + */ + +void +ResAddResistorToList(resistor,locallist) + resResistor *resistor,**locallist; + +{ + resResistor *local,*last=NULL; + + for (local = *locallist; local != NULL; local = local->rr_nextResistor) + { + if (local->rr_value >= resistor->rr_value) + { + break; + } + last = local; + } + if (local != NULL) + { + resistor->rr_nextResistor = local; + resistor->rr_lastResistor = local->rr_lastResistor; + if (local->rr_lastResistor == NULL) + { + *locallist = resistor; + } + else + { + local->rr_lastResistor->rr_nextResistor = resistor; + } + local->rr_lastResistor = resistor; + } + else + { + if (last != NULL) + { + last->rr_nextResistor = resistor; + resistor->rr_lastResistor = last; + resistor->rr_nextResistor = NULL; + } + else + { + resistor->rr_nextResistor = NULL; + resistor->rr_lastResistor = NULL; + *locallist = resistor; + } + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResdistributeSubstrateCapacitance-- + * + * Results: + * None. + * + * Side Effects: + * takes total capacitance to VDD or GND in a node and distributes + * it onto the new nodes. + * + *------------------------------------------------------------------------- + */ + +void +ResDistributeCapacitance(nodelist,totalcap) + resNode *nodelist; + float totalcap; + +{ + float totalarea=0,capperarea; + resNode *workingNode; + resElement *rptr; + + for (workingNode = nodelist; workingNode != NULL; workingNode=workingNode->rn_more) + { + for (rptr = workingNode->rn_re; rptr != NULL; rptr=rptr->re_nextEl) + { + if (rptr->re_thisEl->rr_float.rr_area != 0.0) + { + TxError("Nonnull resistor area\n"); + } +/* workingNode->rn_float.rn_area += rptr->re_thisEl->rr_float.rr_area/2; */ + } + totalarea += workingNode->rn_float.rn_area; + } + if (totalarea == 0) + { + TxError("Error: Node with no area.\n"); + return; + } + capperarea = FEMTOTOATTO*totalcap/totalarea; + for (workingNode = nodelist; workingNode != NULL; workingNode=workingNode->rn_more) + { + workingNode->rn_float.rn_area *= capperarea; + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResCalculateChildCapacitance-- calculates capacitance of this node and + * all downstream nodes. + * + * Results: Returns capacitance of this node and children nodes if connected + * to a tree- returns -1 If the subtree contains loops. + * + * Side Effects: Adds RCDelayStuff fields to nodes. + * + *------------------------------------------------------------------------- + */ + +float +ResCalculateChildCapacitance(me) + resNode *me; + +{ + RCDelayStuff *myC; + resElement *workingRes; + resTransistor *tran; + float childcap; + tElement *tptr; + int t; + + + if (me->rn_client != (ClientData) NULL) /* we have a loop */ + { + return(-1); + } + myC = (RCDelayStuff *) mallocMagic((unsigned) (sizeof(RCDelayStuff))); + me->rn_client = (ClientData) myC; + + /* This following assumes that ResDistributeCapacitance has been run */ + /* and the the resulting capacitance value is stored in the area field */ + myC->rc_Cdownstream = me->rn_float.rn_area; + + /* get capacitance for all connected gates */ + for (tptr = me->rn_te; tptr != NULL; tptr = tptr->te_nextt) + { + tran = tptr->te_thist; + t = TiGetType(tran->rt_tile); + if (tran->rt_gate == me) + { + myC->rc_Cdownstream += + tran->rt_length* + tran->rt_width* + ExtCurStyle->exts_transGateCap[t]+ + (tran->rt_width+tran->rt_width)* + ExtCurStyle->exts_transSDCap[t]; + + } + } + + /* Calculate child Capacitance */ + for (workingRes = me->rn_re; workingRes != NULL; workingRes=workingRes->re_nextEl) + { + if (workingRes->re_thisEl->rr_connection1 == me && + (workingRes->re_thisEl->rr_status & RES_TDI_IGNORE) == 0) + { + childcap = ResCalculateChildCapacitance(workingRes->re_thisEl->rr_connection2); + if (childcap == -1) + { + return(-1); + } + myC->rc_Cdownstream +=childcap; + } + } + return(myC->rc_Cdownstream); +} + + +/* + *------------------------------------------------------------------------- + * + * ResCalculateTDi- Calculates TDi numbers for all the nodes in the circuit. + * + * Results: none + * + * Side Effects: sets the rc_Tdi fields of the RCDelayStuff fields of the + * nodes. + * + *------------------------------------------------------------------------- + */ + +void +ResCalculateTDi(node,resistor,resistorvalue) + resNode *node; + resResistor *resistor; + int resistorvalue; + +{ + resElement *workingRes; + RCDelayStuff *rcd = (RCDelayStuff *)node->rn_client; + RCDelayStuff *rcd2; + + ASSERT(rcd != NULL,"ResCalculateTdi"); + if (resistor == NULL) + { + rcd->rc_Tdi = rcd->rc_Cdownstream*(float)resistorvalue; + } + else + { + rcd2 = (RCDelayStuff *)resistor->rr_connection1->rn_client; + ASSERT(rcd2 != NULL,"ResCalculateTdi"); + rcd->rc_Tdi=rcd->rc_Cdownstream*(float)resistor->rr_value + + rcd2->rc_Tdi; + + } + + for (workingRes = node->rn_re; workingRes != NULL; workingRes=workingRes->re_nextEl) + { + if (workingRes->re_thisEl->rr_connection1 == node && + (workingRes->re_thisEl->rr_status & RES_TDI_IGNORE) == 0) + { + ResCalculateTDi(workingRes->re_thisEl->rr_connection2, + workingRes->re_thisEl, + workingRes->re_thisEl->rr_value); + } + } +} + +/* + *------------------------------------------------------------------------- + * + * ResPruneTree-- Designed to be run just after ResCalculateTDi to prune all + * branches off the tree whose end node value of Tdi is less than the + * tolerance. This eliminates many resistors in nets with high fanout. + * + * Results: none + * + * Side Effects: May Eliminate Resistors and Merge Nodes + * + *------------------------------------------------------------------------- + */ + +void +ResPruneTree(node,minTdi,nodelist1,nodelist2,resistorlist) + resNode *node,**nodelist1,**nodelist2; + float minTdi; + resResistor **resistorlist; + +{ + resResistor *currentRes; + resElement *current; + + current = node->rn_re; + while(current != NULL) + { + currentRes = current->re_thisEl; + current = current->re_nextEl; + /* if branch points outward, call routine on subtrees */ + if (currentRes->rr_connection1 == node) + { + ResPruneTree(currentRes->rr_connection2, minTdi,nodelist1,nodelist2,resistorlist); + } + } + /* We eliminate this branch if */ + /* 1. It is a terminal node, i.e. it is the connected */ + /* to only one resistor. */ + /* 2. The direction of this resistor is toward the node */ + /* (This prevents the root from being eliminated */ + /* 3. The time constant TDI is less than the tolerance. */ + if (node->rn_re != NULL && + node->rn_re->re_nextEl == NULL && + node->rn_re->re_thisEl->rr_connection2 == node) + { + if (node->rn_client == (ClientData)NULL) + { + TxError("Internal Error in Tree Pruning: Missing TDi value.\n"); + } + else if (((RCDelayStuff *)(node->rn_client))->rc_Tdi < minTdi) + { + currentRes = node->rn_re->re_thisEl; + ResDeleteResPointer(currentRes->rr_connection1,currentRes); + ResDeleteResPointer(currentRes->rr_connection2,currentRes); + ResMergeNodes(currentRes->rr_connection1,currentRes->rr_connection2,nodelist2,nodelist1); /* Patched 7/5/94 */ + ResEliminateResistor(currentRes,resistorlist); + } + } +} + +int +ResDoSimplify(tolerance,rctol,goodies) + float tolerance; + float rctol; + ResGlobalParams *goodies; + +{ + resNode *node,*slownode; + float bigres = 0; + float millitolerance; + float totalcap; + resResistor *res; + + + resRemoveLoops = FALSE; + ResSetPathRes(); + for (node = ResNodeList; node != NULL; node = node->rn_more) + { + bigres = MAX(bigres,node->rn_noderes); + } + + bigres /= OHMSTOMILLIOHMS; /* convert from milliohms to ohms */ + goodies->rg_maxres = bigres; + +#ifdef PARANOID + ResSanityChecks("ExtractSingleNet",ResResList,ResNodeList,ResTransList); +#endif + + /* Is extracted network still greater than the tolerance? */ + /* Even if it isn't, we still let the next section run if */ + /* we're calculating lumped values so that the capacitance */ + /* values get calculated correctly. */ + + (void) ResDistributeCapacitance(ResNodeList,goodies->rg_nodecap); + + if ((tolerance > bigres || (ResOptionsFlags &ResOpt_Simplify)==0) && + (ResOptionsFlags &ResOpt_DoLumpFile)==0) + { + return(0); + } + res = ResResList; + while (res) + { + resResistor *oldres = res; + + res = res->rr_nextResistor; + oldres->rr_status &= ~RES_HEAP; + if (oldres->rr_status & RES_TDI_IGNORE) + { + ResDeleteResPointer(oldres->rr_node[0],oldres); + ResDeleteResPointer(oldres->rr_node[1],oldres); + ResEliminateResistor(oldres,&ResResList); + } + } + + if (ResOptionsFlags & ResOpt_Tdi) + { + if (goodies->rg_nodecap != -1 && + (totalcap = ResCalculateChildCapacitance(ResOriginNode)) != -1) + { + RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client; + + if (rc != (RCDelayStuff *)NULL) + { + goodies->rg_nodecap = totalcap; + ResCalculateTDi(ResOriginNode,(resResistor *)NULL, + goodies->rg_bigtranres); + goodies->rg_Tdi = rc->rc_Tdi; + slownode = ResNodeList; + for (node = ResNodeList; node != NULL; node = node->rn_more) + { + rc = (RCDelayStuff *)node->rn_client; + if (rc && (goodies->rg_Tdi < rc->rc_Tdi)) + { + slownode = node; + goodies->rg_Tdi = rc->rc_Tdi; + } + } + slownode->rn_status |= RN_MAXTDI; + } + else + goodies->rg_Tdi = 0; + } + else + { + goodies->rg_Tdi = -1; + } + } + else + { + goodies->rg_Tdi = 0; + } + if ((rctol+1)*goodies->rg_bigtranres*goodies->rg_nodecap > + rctol*goodies->rg_Tdi && + (ResOptionsFlags & ResOpt_Tdi) && + goodies->rg_Tdi != -1) + { + return(0); + } + + /* Simplify network; resistors are still in milliohms, so use + millitolerance. + */ + + if (ResOptionsFlags & ResOpt_Simplify) + { + + millitolerance = tolerance*MILLIOHMSPEROHM; + + /* + Start simplification at driver (R=0). Remove it from the done list + and add it to the pending list. Call ResSimplifyNet as long as nodes + remain in the pending list. + */ + for (node = ResNodeList; node != NULL ;node = node->rn_more) + { + if (node->rn_noderes == 0) + { + ResOriginNode = node; + } + node->rn_status |= FINISHED; + } + if (ResOriginNode != NULL) + { + + /* if Tdi is enabled, prune all branches whose end nodes have */ + /* time constants less than the tolerance. */ + + if ((ResOptionsFlags & ResOpt_Tdi) && + goodies->rg_Tdi != -1 && + rctol != 0) + { + ResPruneTree(ResOriginNode, + (rctol+1)*goodies->rg_bigtranres*goodies->rg_nodecap/rctol, + &ResNodeList,&ResNodeQueue,&ResResList); + } + ResOriginNode->rn_status &= ~MARKED; + if (ResOriginNode->rn_less == NULL) + { + ResNodeList = ResOriginNode->rn_more; + } + else + { + ResOriginNode->rn_less->rn_more = ResOriginNode->rn_more; + } + if (ResOriginNode->rn_more != NULL) + { + ResOriginNode->rn_more->rn_less = ResOriginNode->rn_less; + } + ResOriginNode->rn_more = NULL; + ResOriginNode->rn_less = NULL; + ResNodeQueue = ResOriginNode; + while (ResNodeQueue != NULL) + { + ResSimplifyNet(&ResNodeQueue,&ResNodeList,&ResResList,millitolerance); + } + + /* + Call ResScrunchNet to eliminate any remaining under tolerance + resistors. + */ + ResScrunchNet(&ResResList,&ResNodeQueue,&ResNodeList,millitolerance); + } + } + return(0); + +} + +void +ResSetPathRes() + +{ + HeapEntry he; + resNode *node; + static int init=1; + + if (init) + { + init = 0; + HeapInit(&ResistorHeap,128,FALSE,FALSE); + } + + for (node = ResNodeList; node != NULL ;node = node->rn_more) + { + if (node->rn_noderes == 0) + { + ResOriginNode = node; + node->rn_status |= FINISHED; + } + else + { + node->rn_noderes = RES_INFINITY; + node->rn_status &= ~FINISHED; + } + } + if (ResOriginNode == NULL) + { + resTransistor *res = ResGetTransistor(gparams.rg_tranloc); + ResOriginNode = res->rt_source; + ResOriginNode->rn_why = RES_NODE_ORIGIN; + ResOriginNode->rn_noderes = 0; + } + ASSERT(ResOriginNode != NULL,"ResDoSimplify"); + resPathNode(ResOriginNode); + while (HeapRemoveTop(&ResistorHeap,&he)) + { + resPathRes((resResistor *) he.he_id); + } +} + +void +resPathNode(node) + resNode *node; + +{ + resElement *re; + + node->rn_status |= FINISHED; + for (re = node->rn_re;re;re=re->re_nextEl) + { + resResistor *res = re->re_thisEl; + resNode *node2; + + if (res->rr_status & RES_HEAP) continue; + if ((node2=res->rr_node[0]) == node) node2 = res->rr_node[1]; + if ((node2->rn_status & FINISHED) == 0) + { + HeapAddInt(&ResistorHeap, node->rn_noderes + res->rr_value, + (char *)res); + } + } +} + +void +resPathRes(res) + resResistor *res; + +{ + resNode *node0,*node1; + int flag0,flag1; + + res->rr_status |= RES_HEAP; + res->rr_status &= ~RES_MARKED; + node0 = res->rr_node[0]; + node1 = res->rr_node[1]; + flag0 = node0->rn_status & FINISHED; + flag1 = node1->rn_status & FINISHED; + if (flag0 && flag1) + { + res->rr_status |= RES_TDI_IGNORE; + if (resRemoveLoops) + { + ResDeleteResPointer(node0,res); + ResDeleteResPointer(node1,res); + ResEliminateResistor(res,&ResResList); + } + } + else if (flag0) + { + node1->rn_noderes = node0->rn_noderes+res->rr_value; + resPathNode(node1); + } + else + { + ASSERT(flag1,"ResPathRes"); + res->rr_node[0] = node1; + res->rr_node[1] = node0; + node0->rn_noderes = node1->rn_noderes+res->rr_value; + resPathNode(node0); + } +} diff --git a/resis/ResUtils.c b/resis/ResUtils.c new file mode 100644 index 00000000..5548f4e1 --- /dev/null +++ b/resis/ResUtils.c @@ -0,0 +1,725 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResUtils.c,v 1.3 2010/06/24 12:37:56 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/stack.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "resis/resis.h" + + +/* + * --------------------------------------------------------------------------- + * + * ResFirst -- Checks to see if tile is a contact. If it is, allocate a + * contact structure. + * + * + * Results: Always returns NULL (in the form of a Region pointer) + * + * Side effects: + * Memory is allocated by ResFirst. + * We cons the newly allocated region onto the front of the existing + * region list. + * + * + * ------------------------------------------------------------------------- + */ + +Region * +ResFirst(tile, arg) + Tile *tile; + FindRegion *arg; +{ + ResContactPoint *reg; + TileType t; + int i; + + if (IsSplit(tile)) + { + t = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); + } + else + t = TiGetType(tile); + + if (DBIsContact(t)) + { + reg = (ResContactPoint *) mallocMagic((unsigned) (sizeof(ResContactPoint))); + reg->cp_center.p_x = (LEFT(tile)+RIGHT(tile))>>1; + reg->cp_center.p_y = (TOP(tile)+BOTTOM(tile))>>1; + reg->cp_status = FALSE; + reg->cp_type = t; + reg->cp_width = RIGHT(tile)-LEFT(tile); + reg->cp_height = TOP(tile)-BOTTOM(tile); + for (i=0; i< LAYERS_PER_CONTACT; i++) + { + reg->cp_tile[i] = (Tile *) NULL; + reg->cp_cnode[i] = (resNode *) NULL; + } + reg->cp_currentcontact = 0; + reg->cp_rect.r_ll.p_x = tile->ti_ll.p_x; + reg->cp_rect.r_ll.p_y = tile->ti_ll.p_y; + reg->cp_rect.r_ur.p_x = RIGHT(tile); + reg->cp_rect.r_ur.p_y = TOP(tile); + reg->cp_contactTile = tile; + /* Prepend it to the region list */ + reg->cp_nextcontact = (ResContactPoint *) arg->fra_region; + arg->fra_region = (Region *) reg; + } + return((Region *) NULL); +} + +/* + *-------------------------------------------------------------------------- + * + * ResEach-- + * + * ResEach calls ResFirst unless this is the first contact, in which case it + * has alreay been processed + * + * results: returns 0 + * + * Side Effects: see ResFirst + * + * ------------------------------------------------------------------------- + */ + +int +ResEach(tile, pNum, arg) + Tile *tile; + int pNum; + FindRegion *arg; +{ + + if ( ((ResContactPoint *)(arg->fra_region))->cp_contactTile != tile) + { + (void) ResFirst(tile, arg); + } + return(0); +} + +/* + *------------------------------------------------------------------------- + * + * ResAddPlumbing-- Each tile is a tileJunk structure associated with it + * to keep track of various things used by the extractor. ResAddPlumbing + * adds this structure and sets the tile's ClientData field to point to it. + * If the tile is a transistor, then a transistor structure is also added; + * all connected transistor tiles are enumerated and their transistorList + * fields set to the new structure. + * + * Results: always returns 0 + * + * Side Effects:see above + * + *------------------------------------------------------------------------- + */ + +int +ResAddPlumbing(tile, arg) + Tile *tile; + ClientData *arg; + +{ + tileJunk *Junk,*junk2; + static Stack *resTransStack=NULL; + TileType loctype, t1; + Tile *tp1,*tp2,*source; + resTransistor *resFet; + + if (resTransStack == NULL) + { + resTransStack = StackNew(64); + } + if (tile->ti_client == (ClientData) CLIENTDEFAULT) + { + if (IsSplit(tile)) + { + loctype = (SplitSide(tile)) ? SplitRightType(tile) : + SplitLeftType(tile); + } + else + loctype = TiGetTypeExact(tile); + + junk2 = resAddField(tile); + if (TTMaskHasType(&(ExtCurStyle->exts_transMask), loctype)) + { + resFet = (resTransistor *) mallocMagic((unsigned)(sizeof(resTransistor))); + { + int i; + for (i=0; i != RT_TERMCOUNT;i++) + resFet->rt_terminals[i] = (resNode *) NULL; + } + resFet->rt_tile = tile; + resFet->rt_inside.r_ll.p_x = LEFT(tile); + resFet->rt_inside.r_ll.p_y = BOTTOM(tile); + resFet->rt_inside.r_ur.p_x = RIGHT(tile); + resFet->rt_inside.r_ur.p_y = TOP(tile); + resFet->rt_trantype = loctype; + resFet->rt_tiles = 0; + resFet->rt_length = 0; + resFet->rt_width = 0; + resFet->rt_perim = 0; + resFet->rt_area = 0; + resFet->rt_status = 0; + resFet->rt_nextTran = (resTransistor *) *arg; + *arg = (ClientData)resFet; + junk2->transistorList = resFet; + junk2->tj_status |= RES_TILE_TRAN; + + source = NULL; + /* find diffusion (if present) to be source contact */ + + /* top */ + for (tp2= RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2)) + { + if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + TiGetBottomType(tp2)) + { + junk2->sourceEdge |= TOPEDGE; + source = tp2; + Junk = resAddField(source); + Junk->tj_status |= RES_TILE_SD; + break; + } + } + + /*bottom*/ + if (source == NULL) + for (tp2= LB(tile); LEFT(tp2) < RIGHT(tile); tp2 = TR(tp2)) + { + if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + TiGetTopType(tp2)) + { + junk2->sourceEdge |= BOTTOMEDGE; + source = tp2; + Junk = resAddField(source); + Junk->tj_status |= RES_TILE_SD; + break; + } + } + + /*right*/ + if (source == NULL) + for (tp2= TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = LB(tp2)) + { + if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + TiGetLeftType(tp2)) + { + junk2->sourceEdge |= RIGHTEDGE; + source = tp2; + Junk = resAddField(source); + Junk->tj_status |= RES_TILE_SD; + break; + } + } + + /*left*/ + if (source == NULL) + for (tp2= BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = RT(tp2)) + { + if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + TiGetRightType(tp2)) + { + source = tp2; + Junk = resAddField(source); + Junk->tj_status |= RES_TILE_SD; + junk2->sourceEdge |= LEFTEDGE; + break; + } + } + + /* We need to know whether a given diffusion tile connects to + * the source or to the drain of a transistor. A single + * diffusion tile is marked, and all connecting diffusion tiles + * are enumerated and called the source. Any other SD tiles + * are assumed to be the drain. BUG: this does not work + * correctly with multi SD structures. + */ + + if (source != (Tile *) NULL) + { + STACKPUSH((ClientData) (source),resTransStack); + } + while (!StackEmpty(resTransStack)) + { + tp1 = (Tile *) STACKPOP(resTransStack); + if (IsSplit(tp1)) + { + t1 = (SplitSide(tp1)) ? SplitRightType(tp1) : + SplitLeftType(tp1); + } + else + t1 = TiGetTypeExact(tp1); + + /* top */ + for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) + { + if (TiGetBottomType(tp2) == t1) + { + tileJunk *j= resAddField(tp2); + if ((j->tj_status & RES_TILE_SD) ==0) + { + j->tj_status |= RES_TILE_SD; + STACKPUSH((ClientData)tp2,resTransStack); + } + } + } + /*bottom*/ + for (tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) + { + if (TiGetTopType(tp2) == t1) + { + tileJunk *j= resAddField(tp2); + if ((j->tj_status & RES_TILE_SD) == 0) + { + j->tj_status |= RES_TILE_SD; + STACKPUSH((ClientData) (tp2),resTransStack); + } + } + } + /*right*/ + for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) + { + if (TiGetLeftType(tp2) == t1) + { + tileJunk *j= resAddField(tp2); + if ((j->tj_status & RES_TILE_SD) == 0) + { + j->tj_status |= RES_TILE_SD; + STACKPUSH((ClientData) (tp2),resTransStack); + } + } + } + /*left*/ + for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) + { + if (TiGetRightType(tp2) == t1) + { + tileJunk *j= resAddField(tp2); + if ((j->tj_status & RES_TILE_SD) == 0) + { + j->tj_status |= RES_TILE_SD; + STACKPUSH((ClientData) (tp2),resTransStack); + } + } + } + } + /* find rest of transistor; search for source edges */ + + STACKPUSH((ClientData) (tile), resTransStack); + while (!StackEmpty(resTransStack)) + { + tileJunk *j0; + + tp1= (Tile *) STACKPOP(resTransStack); + if (IsSplit(tp1)) + { + t1 = (SplitSide(tp1)) ? SplitRightType(tp1) : + SplitLeftType(tp1); + } + else + t1 = TiGetTypeExact(tp1); + + j0 = (tileJunk *) tp1->ti_client; + /* top */ + for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) + { + if ((TiGetBottomType(tp2) == t1) && + (tp2->ti_client == (ClientData) CLIENTDEFAULT)) + { + Junk = resAddField(tp2); + STACKPUSH((ClientData)(tp2),resTransStack); + Junk->transistorList = resFet; + Junk->tj_status |= RES_TILE_TRAN; + + } + else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + TiGetBottomType(tp2)) + { + Junk = resAddField(tp2); + if (Junk->tj_status & RES_TILE_SD) + { + j0->sourceEdge |= TOPEDGE; + } + } + } + /*bottom*/ + for (tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) + { + if ((TiGetTopType(tp2) == t1) && + (tp2->ti_client == (ClientData) CLIENTDEFAULT)) + { + Junk = resAddField(tp2); + STACKPUSH((ClientData)(tp2),resTransStack); + Junk->transistorList = resFet; + Junk->tj_status |= RES_TILE_TRAN; + } + else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + TiGetTopType(tp2)) + { + Junk = resAddField(tp2); + if (Junk->tj_status & RES_TILE_SD) + { + j0->sourceEdge |= BOTTOMEDGE; + } + } + } + /*right*/ + for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) + { + if ((TiGetLeftType(tp2) == t1) && + (tp2->ti_client == (ClientData) CLIENTDEFAULT)) + { + Junk = resAddField(tp2); + STACKPUSH((ClientData)(tp2),resTransStack); + Junk->transistorList = resFet; + Junk->tj_status |= RES_TILE_TRAN; + } + else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + TiGetLeftType(tp2)) + { + Junk = resAddField(tp2); + if (Junk->tj_status & RES_TILE_SD) + { + j0->sourceEdge |= RIGHTEDGE; + } + } + } + /*left*/ + for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) + { + if ((TiGetRightType(tp2) == t1) && + (tp2->ti_client == (ClientData) CLIENTDEFAULT)) + { + Junk = resAddField(tp2); + STACKPUSH((ClientData)(tp2),resTransStack); + Junk->transistorList = resFet; + Junk->tj_status |= RES_TILE_TRAN; + } + else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + TiGetRightType(tp2)) + { + Junk = resAddField(tp2); + if (Junk->tj_status & RES_TILE_SD) + { + j0->sourceEdge |= LEFTEDGE; + } + } + } + } + + /* unmark all tiles marked as being part of source */ + + if (source != (Tile *) NULL) + { + tileJunk *j = (tileJunk *) source->ti_client; + + STACKPUSH((ClientData) (source),resTransStack); + j->tj_status &= ~RES_TILE_SD; + } + while (!StackEmpty(resTransStack)) + { + tp1 = (Tile *) STACKPOP(resTransStack); + if (IsSplit(tp1)) + { + t1 = (SplitSide(tp1)) ? SplitRightType(tp1) : + SplitLeftType(tp1); + } + else + t1 = TiGetTypeExact(tp1); + + /* top */ + for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) + { + tileJunk *j2 = (tileJunk *) tp2->ti_client; + if (TiGetBottomType(tp2) == t1) + { + if (j2->tj_status & RES_TILE_SD) + { + j2->tj_status &= ~RES_TILE_SD; + STACKPUSH((ClientData) tp2,resTransStack); + } + } + } + /*bottom*/ + for(tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) + { + tileJunk *j2 = (tileJunk *) tp2->ti_client; + if (TiGetTopType(tp2) == t1) + { + if (j2->tj_status & RES_TILE_SD) + { + j2->tj_status &= ~RES_TILE_SD; + STACKPUSH((ClientData) tp2,resTransStack); + } + } + } + /*right*/ + for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) + { + tileJunk *j2 = (tileJunk *) tp2->ti_client; + if (TiGetLeftType(tp2) == t1) + { + if (j2->tj_status & RES_TILE_SD) + { + j2->tj_status &= ~RES_TILE_SD; + STACKPUSH((ClientData) tp2,resTransStack); + } + } + } + /*left*/ + for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) + { + tileJunk *j2 = (tileJunk *) tp2->ti_client; + if (TiGetRightType(tp2) == t1) + { + if (j2->tj_status & RES_TILE_SD) + { + j2->tj_status &= ~RES_TILE_SD; + STACKPUSH((ClientData) tp2,resTransStack); + } + } + } + } + } + } + return(0); +} + +/* + *------------------------------------------------------------------------- + * + * ResRemovePlumbing-- Removes and deallocates all the tileJunk fields. + * + * Results: returns 0 + * + * Side Effects: frees up memory; resets tile->ti_client fields to CLIENTDEFAULT + * + *------------------------------------------------------------------------- + */ + +int +ResRemovePlumbing(tile, arg) + Tile *tile; + ClientData *arg; + +{ + + if (tile->ti_client != (ClientData) CLIENTDEFAULT) + { + freeMagic(((char *)(tile->ti_client))); + tile->ti_client = (ClientData) CLIENTDEFAULT; + } + return(0); +} + + +/* + *------------------------------------------------------------------------- + * + * ResPreprocessTransistors-- Given a list of all the transistor tiles and + * a list of all the transistors, this procedure calculates the width and + * length. The width is set equal to the sum of all edges that touch + * diffusion divided by 2. The length is the remaining perimeter divided by + * 2*tiles. The perimeter and area fields of transistor structures are also + * fixed. + * + * Results: none + * + * Side Effects: sets length and width of transistors. "ResTransTile" + * structures are freed. + * + *------------------------------------------------------------------------- + */ + +void +ResPreProcessTransistors(TileList, TransistorList, Def) + ResTranTile *TileList; + resTransistor *TransistorList; + CellDef *Def; +{ + Tile *tile; + ResTranTile *oldTile; + tileJunk *tstruct; + TileType tt, residue; + int pNum; + + while (TileList != (ResTranTile *) NULL) + { + tt = TileList->type; + if (DBIsContact(tt)) + { + /* Find which residue of the contact is a transistor type. */ + TileTypeBitMask ttresidues; + + DBFullResidueMask(tt, &ttresidues); + + for (residue = TT_TECHDEPBASE; residue < DBNumUserLayers; residue++) + { + if (TTMaskHasType(&ttresidues, residue)) + { + if (TTMaskHasType(&ExtCurStyle->exts_transMask, residue)) + { + pNum = DBPlane(residue); + break; + } + } + } + } + else + pNum = DBPlane(tt); /* always correct for non-contact types */ + + tile = (Def->cd_planes[pNum])->pl_hint; + GOTOPOINT(tile, &(TileList->area.r_ll)); + + tt = TiGetType(tile); + tstruct = (tileJunk *) tile->ti_client; + + if (!TTMaskHasType(&ExtCurStyle->exts_transMask, tt) || + tstruct->transistorList == NULL) + { + TxError("Bad Transistor Location at %d,%d\n", + TileList->area.r_ll.p_x, + TileList->area.r_ll.p_y); + } + else if ((tstruct->tj_status & RES_TILE_MARK) == 0) + { + resTransistor *rt = tstruct->transistorList; + + tstruct->tj_status |= RES_TILE_MARK; + rt->rt_perim += TileList->perim; + rt->rt_length += TileList->overlap; + rt->rt_area += (TileList->area.r_xtop - TileList->area.r_xbot) + * (TileList->area.r_ytop - TileList->area.r_ybot); + rt->rt_tiles++; + } + oldTile = TileList; + TileList = TileList->nextTran; + freeMagic((char *)oldTile); + } + + for(; TransistorList != NULL;TransistorList = TransistorList->rt_nextTran) + { + int width = TransistorList->rt_perim; + int length = TransistorList->rt_length; + if (TransistorList->rt_tiles != 0) + { + if (length) + { + TransistorList->rt_length = (float) length / + ((float)((TransistorList->rt_tiles) << 1)); + TransistorList->rt_width = (width-length) >> 1; + } + else + { + double perimeter = TransistorList->rt_perim; + double area = TransistorList->rt_area; + + perimeter /= 4.0; + + TransistorList->rt_width = perimeter + + sqrt(perimeter * perimeter-area); + TransistorList->rt_length = (TransistorList->rt_perim + - 2 * TransistorList->rt_width) >> 1; + } + } + } +} + + +/* + *------------------------------------------------------------------------- + * + * ResAddToQueue-- adds new nodes to list of nodes requiring processing. + * + * Side Effects: nodes are added to list (i.e they have their linked list + * pointers modified.) + * + *------------------------------------------------------------------------- + */ +void +ResAddToQueue(node,list) + resNode *node,**list; +{ + + node->rn_more = *list; + node->rn_less = NULL; + if (*list) (*list)->rn_less = node; + *list = node; +} + + +/* + *------------------------------------------------------------------------- + * + * ResRemoveFromQueue-- removes node from queue. Complains if it notices + * that the node isn't in the supplied list. + * + * Results: none + * + * Side Effects: modifies nodelist + * + *------------------------------------------------------------------------- + */ + +void +ResRemoveFromQueue(node,list) + resNode *node,**list; + +{ + + if (node->rn_less != NULL) + { + node->rn_less->rn_more = node->rn_more; + } + else + { + if (node != (*list)) + { + TxError("Error: Attempt to remove node from wrong list\n"); + } + else + { + *list = node->rn_more; + } + } + if (node->rn_more != NULL) + { + node->rn_more->rn_less = node->rn_less; + } + node->rn_more = NULL; + node->rn_less = NULL; +} +tileJunk * +resAddField(tile) + Tile *tile; + +{ + tileJunk *Junk; + if ((Junk=(tileJunk *)tile->ti_client) == (tileJunk *) CLIENTDEFAULT) + { + Junk = (tileJunk *) mallocMagic((unsigned) (sizeof(tileJunk))); + ResJunkInit(Junk); + tile->ti_client = (ClientData) Junk; + } + return Junk; +} diff --git a/resis/ResWrite.c b/resis/ResWrite.c new file mode 100644 index 00000000..a026cd54 --- /dev/null +++ b/resis/ResWrite.c @@ -0,0 +1,229 @@ + +/* + *------------------------------------------------------------------------- + * + * Write.c -- Dumps network + * + * + *------------------------------------------------------------------------- + */ + +#define MILLITOKILO 1e-6 + + +#ifndef lint +static char sccsid[] = "@(#)Write.c 4.10 MAGIC (Stanford Addition) 07/86"; +#endif /* not lint */ +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/stack.h" +#include "utils/tech.h" +#include "textio/txcommands.h" +#include "resis/resis.h" + +#define RT_SIZE 0xf +#define MAXTOKEN 256 +#define TRANFLATSIZE 1024 +#define RESGROUPSIZE 256 + +void +ResPrintNetwork(filename, reslist) + char *filename; + resResistor *reslist; + +{ + char bigname[255],name1[255],name2[255]; + + FILE *fp; + int i=1; + + sprintf(bigname,"%s.%s",filename,"res"); + fp = fopen(bigname,"w"); + if (fp != NULL) + { + for (;reslist;reslist=reslist->rr_nextResistor) + { + if (reslist->rr_connection1->rn_id == 0) + { + reslist->rr_connection1->rn_id = i++; + } + if (reslist->rr_connection2->rn_id == 0) + { + reslist->rr_connection2->rn_id = i++; + } + if (reslist->rr_connection1->rn_why == RES_NODE_ORIGIN) + { + sprintf(name1,"gnd"); + } + else + { + sprintf(name1,"n%d_%d_%d", + reslist->rr_connection1->rn_id, + reslist->rr_connection1->rn_loc.p_x, + reslist->rr_connection1->rn_loc.p_y); + } + if (reslist->rr_connection2->rn_why == RES_NODE_ORIGIN) + { + sprintf(name2,"gnd"); + } + else + { + sprintf(name2,"n%d_%d_%d", + reslist->rr_connection2->rn_id, + reslist->rr_connection2->rn_loc.p_x, + reslist->rr_connection2->rn_loc.p_y); + } + fprintf(fp,"r %s %s %f\n",name1,name2, + (float)(reslist->rr_value)*MILLITOKILO); + } + } + fclose(fp); +} + +void +ResPrintCurrents(filename,extension,node) + char *filename; + float extension; + resNode *node; + +{ + char bigname[255]; + FILE *fp; + int resCurrentPrintFunc(); + + sprintf(bigname,"%s.%d",filename,abs((int)(extension))); + + fp = fopen(bigname,"w"); + if (fp != NULL) + { + (void) ResTreeWalk(node,NULL,resCurrentPrintFunc, + RES_DO_FIRST,RES_NO_LOOP,RES_NO_FLAGS,fp); + } + fclose(fp); +} + + + +/* + *------------------------------------------------------------------------- + * + * resCurrentPrintFunc -- prints out a node of network in form compatible with + * the linear network solver. Designed for use with ResTreeWalk. + * + * + *------------------------------------------------------------------------- + */ + +void +resCurrentPrintFunc(node,resistor,filename) + resNode *node; + resResistor *resistor; + FILE *filename; + +{ + tElement *workingTran; + float i_sum=0.0; + + for (workingTran = node->rn_te; workingTran != NULL; + workingTran=workingTran->te_nextt) + { + if ((workingTran->te_thist->rt_status & RES_TRAN_PLUG) || + workingTran->te_thist->rt_gate != node) + i_sum += workingTran->te_thist->rt_i; + } + if (i_sum != 0.0) + { + if (node->rn_why == RES_NODE_ORIGIN) + { + fprintf(filename,"i gnd %f\n",i_sum); + + } + else + { + fprintf(filename,"i n%d_%d %f\n",node->rn_loc.p_x, + node->rn_loc.p_y,i_sum); + } + } + +} + +void +ResDeviceCounts() +{ + int i,j,k; + resNode *n; + resTransistor *t; + resResistor *r; + + for (n=ResNodeList,i=0;n!=NULL;n=n->rn_more,i++); + for (t=ResTransList,j=0;t!=NULL;t=t->rt_nextTran,j++); + for (r=ResResList,k=0;r!=NULL;r=r->rr_nextResistor,k++); + TxError("n=%d t=%d r=%d\n",i,j,k); + TxFlushErr(); +} + + +void +ResWriteECLFile(filename,reslist,nodelist) + char *filename; + resResistor *reslist; + resNode *nodelist; + +{ + char newname[100],*tmpname,*per; + FILE *fp; + int nodenum = 0; + + strcpy(newname,filename); + if (per = strrchr(newname,'.')) *per = '\0'; + strcat(newname,".res"); + + if ((fp = fopen(newname,"w")) == NULL) + { + TxError("Can't open %s\n",newname); + return; + } + for (;nodelist;nodelist=nodelist->rn_more) + { + if (nodelist->rn_name == NULL) + { + if (nodelist->rn_noderes == 0) + { + strcpy(newname,"gnd"); + } + else + { + (void)sprintf(newname,"n%d_%d_%d",nodelist->rn_loc.p_x, + nodelist->rn_loc.p_y,nodenum++); + } + tmpname = (char *) mallocMagic((unsigned) (strlen(newname)+1)); + strcpy(tmpname,newname); + nodelist->rn_name = tmpname; + } + } + for (;reslist;reslist = reslist->rr_nextResistor) + { + + fprintf(fp,"r %s %s %f %s %d\n", + reslist->rr_node[0]->rn_name,reslist->rr_node[1]->rn_name, + /* /1000.0 gets ohms from milliohms */ + (float)(reslist->rr_value)/1000.0, + DBTypeShortName(reslist->rr_tt),reslist->rr_csArea); + } + fclose(fp); +} diff --git a/resis/resis.h b/resis/resis.h new file mode 100644 index 00000000..2848cba8 --- /dev/null +++ b/resis/resis.h @@ -0,0 +1,685 @@ + /* Header files for resistance extraction */ + +/* Type declarations */ + +/* contact points: keeps track where contacts are and what tiles they + refer to both before and after processing. +*/ + +#ifndef _RESIS_H +#define _RESIS_H + +#define LAYERS_PER_CONTACT 3 +#define TILES_PER_JUNCTION 2 + +typedef struct contactpoint +{ + struct contactpoint *cp_nextcontact;/* Next contact in linked */ + /* list. */ + Point cp_center; /*Center of contact */ + Rect cp_rect; /* Tile rectangle */ + Tile *cp_contactTile; + /* + The following two keep + track of the tiles where + the contact was before + preprocessing, and the + next contact in that tile's + area. + */ + + Tile *cp_tile[LAYERS_PER_CONTACT]; + int cp_currentcontact; /* keeps track of tile + being processed + */ + TileType cp_type; /* Type of contact */ + int cp_width; /* Width (in x) of contact region */ + int cp_height; /* Height (in y) of contact region */ + struct resnode *cp_cnode[LAYERS_PER_CONTACT];/* this contact's nodes */ + int cp_status; /* status of processing on + this contact + */ +} ResContactPoint; + +typedef struct resistor +{ + struct resistor *rr_nextResistor; /* Doubly linked list pointers */ + struct resistor *rr_lastResistor; + struct resnode *rr_node[2]; + float rr_value; /* Resistor's value in milliohms */ + int rr_status; /* Status bit used for processing */ + union + { + float rr_area; /* area in resistor. Used to */ + /* distribute capacitance */ + float rr_i; /* Branch current in mA */ + } rr_float; + int rr_cl; /* resistor centerline for geometry */ + int rr_width; /* resistor width for geometry */ + TileType rr_tt; /* type that composes this */ + /* resistor. */ +#ifdef ARIEL + int rr_csArea; /* crosssectional area in lamba**2*/ +#endif +} resResistor; + +#define rr_connection1 rr_node[0] +#define rr_connection2 rr_node[1] + +#define RT_GATE 0 +#define RT_SOURCE 1 +#define RT_DRAIN 2 +#define RT_SUBS 3 +#define RT_TERMCOUNT 4 +typedef struct transistor +{ + int rt_status; /* status bits */ + struct transistor *rt_nextTran; /* next transistor in linked list */ + /* terminals of transistor */ + struct resnode *rt_terminals[RT_TERMCOUNT]; + int rt_perim; /* info about transistor */ + int rt_area; /* used in .ext and .sim file */ + int rt_length; /* patches. */ + int rt_width; + int rt_tiles; /* number of tiles in transistor */ + int rt_trantype; /* tiletype of transistor. */ + Rect rt_inside; /* 1x1 rectangle inside transistor */ + Tile *rt_tile; /* pointer to a tile in transistor */ +#ifdef ARIEL + float rt_i; /* Current injected from this tran */ + /* in milliamps */ +#endif +} resTransistor; + +#define rt_gate rt_terminals[RT_GATE] +#define rt_source rt_terminals[RT_SOURCE] +#define rt_drain rt_terminals[RT_DRAIN] +#define rt_subs rt_terminals[RT_SUBS] + +/* + a junction is formed when two tiles that connect are next to one another. +*/ + +typedef struct junction +{ + struct junction *rj_nextjunction[TILES_PER_JUNCTION]; + Tile *rj_Tile[TILES_PER_JUNCTION]; + Point rj_loc; + int rj_status; + struct resnode *rj_jnode; +} ResJunction; + +/* + * A port is declared for subcircuits; its name overrides any locally- + * generated node name. + */ + +typedef struct resport +{ + struct resport *rp_nextPort; + Rect rp_bbox; + Point rp_loc; + char *rp_nodename; +} resPort; + +/* + ?element are 'cons' cells used to make linked lists of their referential + structures. +*/ + +typedef struct reselement +{ + struct reselement *re_nextEl; + resResistor *re_thisEl; +} resElement; + +typedef struct relement +{ + struct relement *rel_nextEl; + struct relement *rel_lastEl; + resResistor *rel_thisEl; +} rElement; + +typedef struct jelement +{ + struct jelement *je_nextj; + ResJunction *je_thisj; +} jElement; + +typedef struct telement +{ + struct telement *te_nextt; + resTransistor *te_thist; +} tElement; + +typedef struct celement +{ + struct celement *ce_nextc; + ResContactPoint *ce_thisc; +} cElement; + +/* + Nodes formed from network. These are linked both forwards and backwords + to other nodes. Lists of transistors, resistors, junctions, and contacts + corresponding to this node are kept. +*/ +typedef struct resnode +{ + struct resnode *rn_more; /* doubly linked list pointers */ + struct resnode *rn_less; + tElement *rn_te; /* widgets connected to this node */ + resElement *rn_re; + jElement *rn_je; + cElement *rn_ce; + int rn_noderes; /* resistance from origin node */ + Point rn_loc; /* location of node */ + unsigned rn_why; /* Why is there a node here? */ + int rn_status; /* Status bits */ + union { /* At various times, we need to */ + /* keep track of the node area, */ + /* node capacitance, and node */ + /* voltage. Since none of these */ + /* values is used concurrently */ + /* only one word of storage is */ + /* needed. */ + float rn_area; /* area of resistors collapsed */ + /* into node. */ + float rn_cap; /* capacitance of node. */ + } rn_float; + char *rn_name; /* Pointer to hash table name */ + /* for this node. */ + ClientData rn_client; /* Random pointer */ + int rn_id; +}resNode; + +typedef struct nelement +{ + struct nelement *ne_nextEl; + struct nelement *ne_lastEl; + resNode *ne_thisEl; +} nElement; + +/* + Breakpoints are places on a tile which may serve as sources/sinks of + current. When resistance is calculated for a tile. this is calculated + between these points. +*/ + +typedef struct breakpoint +{ + struct breakpoint *br_next; + resNode *br_this; + Point br_loc; + Rect *br_crect; +} Breakpoint; + +/* + Each tile needs to keep track of the following things associated with it. + Since there are too many things to fit in the single ti_client field, + this 1 to 6 adaptor is used. +*/ + +typedef struct tilejunk +{ + cElement *contactList; /*widgets connected to this tile */ + resTransistor *transistorList; + resPort *portList; + ResJunction *junctionList; + Breakpoint *breakList; + int sourceEdge; /* used in transistor tiles to keep + of which diffusion edges are + the transistor's source + */ + int tj_status; /* status of tile processing */ +} tileJunk; + +/* ResTransTile keeps track of the location and type of transistors. + These areas are painted into our copied def after the tree is totally + flattened. (They can't be painted right away becasue the copy routine + uses the new def to keep track of where it is in the design. It is also + used when transistors are preproceesed. +*/ + +typedef struct restrantile +{ + struct restrantile *nextTran; + Rect area; + TileType type; + int perim; + int overlap; +} ResTranTile; + +/* + Goodies contains random stuff passed between the node extractor + and ResCheckSimNodes. The location of a start tile and the resistive + tolerance are passed down, while the derived network is passed back. +*/ + +typedef struct goodstuff +{ + TileType rg_ttype; + float rg_maxres; + float rg_nodecap; + float rg_Tdi; + int rg_bigtranres; + int rg_tilecount; + int rg_status; + Point *rg_tranloc; + char *rg_name; +} ResGlobalParams; + +/* Used in RC delay calculations for Tdi filter */ +/* Attaches to rn_client field of resNode */ + +typedef struct rcdelaystuff +{ + float rc_Cdownstream; /* capacitance down the tree from node */ + float rc_Tdi; /* Tdi for node */ +} RCDelayStuff; + + +/* ResSim.c type declarations */ + +typedef struct rtran +{ + struct rtran *nextTran; /* Next transistor in linked list */ + struct rtran *realTran; /* Single Lumped Transistor for */ + /* transistors connected in parallel */ + resTransistor *layout; /* pointer to resTransistor that */ + /* corresponds to RTran */ + int status; + struct ressimnode *gate; /* Terminals of transistor. */ + struct ressimnode *source; + struct ressimnode *drain; + Point location; /* Location of lower left point of */ + /* transistor. */ + float resistance; /* "Resistance" of transistor. */ + int tnumber; /* Transistor number */ + int rs_ttype; /* transistor type */ + char *rs_gattr; /* Gate attributes, if any */ + char *rs_sattr; + char *rs_dattr; +} RTran; + +typedef struct ressimnode +{ + struct ressimnode *nextnode; /* next node in OriginalNodes */ + /* linked list. */ + int status; + struct ressimnode *forward; /* If node has been merged, this */ + /* points to the merged node. */ + float capacitance; /* capacitance between node and */ + /* GND for power connections */ + /* and all capacitance for every */ + /* thing else. */ + float cap_vdd; /* capacitance to VDD (used for */ + /* power calculations only */ + float cap_couple; /* coupling capacitance */ + float resistance; /* lumped resistance */ + float minsizeres; /* Minimum size resistor allowed */ + Point drivepoint; /* optional, user specified drive */ + /* point for network. */ + TileType rs_ttype; /* tiletype of drivepoint */ + Point location; /* location of bottom of leftmost */ + /* tile in the lowest numbered */ + /* plane contained in the node . */ + Rect rs_bbox; /* location of bottom of leftmost */ + /* tile in the lowest numbered */ + /* plane contained in the node . */ + TileType type; /* Tile type of tile at location */ + struct tranptr *firstTran; /* linked list of transistors */ + /* connected to node. */ + char *name; /* Pointer to name of node stored */ + /* in hash table. */ + char *oldname; /* Pointer to previous name of */ + /* node, if it exists */ + tElement *rs_sublist[2]; /* pointers to Gnd and Vdd sub */ + /* strate connections, + if they exist */ +} ResSimNode; + +#define RES_SUB_GND 0 +#define RES_SUB_VDD 1 + +/* `cons' cell for linked list of transistors connected to node */ + +typedef struct tranptr +{ + struct tranptr *nextTran; + struct rtran *thisTran; + int terminal; /* which terminal of transistor */ + /* is connected to node. */ +} tranPtr; + +/* ResTime.c type declarations */ + +typedef struct resevent /* Raw event list read in from rsim/tv */ +{ + int rv_node; /* node number */ + int rv_final; /* final value; (0,1, or X) */ + int rv_tmin; /* minimum event time in units of 100ps */ + int rv_tmax; /* maximum event time in units of 100ps */ + float rv_i; /* event current in milliamps */ + resTransistor *rv_tran; /* transistor where charge drains */ +} ResEvent; + +typedef struct reseventcell +{ + ResEvent *rl_this; + struct reseventcell *rl_next; +} REcell; + +typedef struct rescurrentevent /* processed event used to feed relaxer */ +{ + struct rescurrentevent *ri_next; + float ri_i; + resTransistor *ri_tran; +} ResCurrentEvent; + +typedef struct restimebin /* Holds one timestep's worth of Events */ +{ + struct restimebin *rb_next; + struct restimebin *rb_last; + int rb_start; + int rb_end; + ResCurrentEvent *rb_first; +} ResTimeBin; + +typedef struct resfixpoint /* Keeps track of where voltage sources are */ +{ + struct resfixpoint *fp_next; + Point fp_loc; + TileType fp_ttype; + int fp_status; + Tile *fp_tile; + resNode *fp_node; + char fp_name[1]; +} ResFixPoint; + +typedef struct clump +{ + unsigned rp_status; + rElement *rp_grouplist; + nElement *rp_nodelist; + rElement *rp_downlist; + rElement *rp_singlelist; +} ResClump; + +/* the first two fields of this plug must be the the same as for + resTransistor +*/ +typedef struct plug +{ + float rpl_i; /* current injected through + this plug + */ + int rpl_status; /* status bits for this plug */ + struct plug *rpl_next; /* next plug in this bin */ + Point rpl_loc; /*location of plug */ + int rpl_type; /*type of plug */ + resNode *rpl_node; /* this point's node */ +} ResPlug; + +typedef struct capval +{ + float cap[1][2]; /* multipliers telling what portion of capacitance is + to Vdd and what part is to ground. Right now, + coupling capacitance is counted twice, so + cap[0]+cap[1] = (c_vdd+c_gnd+2*c_couple)/ + (c_vdd+c_gnd+c_couple); + */ +} ResCapVal; + +/* node flags */ +#define RES_REACHED_NODE 0x00200000 +#define RES_NODE_XADJ 0x00400000 +#define RES_NODE_YADJ 0x00800000 + +/* type of node flags */ +#define RES_NODE_JUNCTION 0x00000001 +#define RES_NODE_TRANSISTOR 0x00000002 +#define RES_NODE_CONTACT 0x00000004 +#define RES_NODE_ORIGIN 0x00000008 + +/* resistor flags */ +#define RES_DEADEND 0x00001000 +#define RES_DONE_ONCE 0x00002000 +#define RES_MARKED 0x00000100 +#define RES_EW 0x00000200 +#define RES_NS 0x00000400 +#define RES_DIAGONAL 0x00000800 +#define RES_TDI_IGNORE 0x00010000 +#define RES_REACHED_RESISTOR 0x00100000 +#define RES_HEAP 0x00200000 + +/* transistor flags */ +#define RES_TRAN_SAVE 0x00000001 +#define RES_TRAN_PLUG 0x00000002 + +/* flags for tiles */ +/* A tile which is part of a source/drain region. */ +#define RES_TILE_SD 0x1 +/* A tile which is actually a transistor */ +#define RES_TILE_TRAN 0x2 +/* Indicates whether the tile has been processed or not */ +#define RES_TILE_DONE 0x4 +/*a temporary marking flag */ +#define RES_TILE_MARK 0x8 +/* indicates that tile has unidirectional current flow */ +#ifdef LAPLACE +#define RES_TILE_1D 0x10 +#define RES_TILE_GDONE 0x20 +#endif +/* tree walking flags */ +#define RES_LOOP_OK 1 +#define RES_NO_LOOP 1 +#define RES_DO_LAST 0 +#define RES_DO_FIRST 1 +#define RES_NO_FLAGS 0 + + +/* ResSim Constants */ +#define FORWARD 0x0000010 +#define SKIP 0x0000020 +#define FORCE 0x0000040 +#define MINSIZE 0x0000080 +#define DRIVELOC 0x0000100 +#define PORTNODE 0x0000200 +#define REDUNDANT 0x0000400 + +/* Capacitance table constants */ +#define RES_CAP_GND 0 +#define RES_CAP_VDD 1 +#define RES_CAP_COUPLE 2 + +#define OHMSTOMILLIOHMS 1000 +#define FEMTOTOATTO 1000 +#define ATTOTOFEMTO 0.001 + +#define UNTOUCHED 0 +#define SERIES 1 +#define PARALLEL 2 +#define LOOP 4 +#define SINGLE 8 +#define TRIANGLE 32 + +#define PENDING 2 +#define FINISHED 4 + +#define LEFTEDGE 1 +#define RIGHTEDGE 4 +#define TOPEDGE 8 +#define BOTTOMEDGE 16 + +#define RN_MAXTDI 0x00001000 + +#define MARKED 0x00000100 + +#define GATE 1 +#define SOURCE 2 +#define DRAIN 3 + +#define DRIVEONLY 0x00001000 +#define ORIGIN 0x00000008 + +/* magic's normal value of infinity is too small- */ +/* 67108863 is only 67K ohms. */ + +#define RES_INFINITY 0x3FFFFFFF + +#define ResCheckIntegrity + +/* The following turns on and off various options */ + +#define ResOpt_ExtractAll 0x00000002 +#define ResOpt_Simplify 0x00000004 +#define ResOpt_DoExtFile 0x00000008 +#define ResOpt_DoRsmFile 0x00000010 +#define ResOpt_DoLumpFile 0x00000020 +#define ResOpt_RunSilent 0x00000040 +#define ResOpt_ExplicitRtol 0x00000080 +#define ResOpt_ExplicitTditol 0x00000100 +#define ResOpt_Tdi 0x00000200 +#define ResOpt_Stat 0x00000400 +#define ResOpt_Power 0x00000800 +#define ResOpt_Signal 0x00001000 +#define ResOpt_Pname 0x00002000 +#define ResOpt_Geometry 0x00004000 +#define ResOpt_FastHenry 0x00008000 +#define ResOpt_Blackbox 0x00010000 +#define ResOpt_Dump 0x00020000 +#define ResOpt_DoSubstrate 0x00040000 +#define ResOpt_GndPlugs 0x00200000 +#define ResOpt_VddPlugs 0x00400000 +#define ResOpt_CMOS 0x00800000 +#define ResOpt_Bipolar 0x01000000 +#define ResOpt_Box 0x02000000 +#ifdef LAPLACE +#define ResOpt_DoLaplace 0x04000000 +#define ResOpt_CacheLaplace 0x08000000 +#define ResOpt_Checkpoint 0x80000000 +#endif + +#define ResOpt_VDisplay 0x10000000 +#define ResOpt_IDisplay 0x20000000 +#define ResOpt_PDisplay 0x40000000 + +/* Assorted Variables */ + +extern RTran *ResTranList; +extern REcell *ResBigEventList; +extern int ResOptionsFlags; +extern char *ResCurrentNode; +extern int Maxtnumber; +extern ResSimNode *ResOriginalNodes; +#ifdef ARIEL +extern int ResMinEventTime; +extern int ResMaxEventTime; +typedef float ResCapElement[2]; +extern ResCapElement *ResCapTableMax; +extern ResCapElement *ResCapTableMin; +extern HashTable ResPlugTable; +#endif + +extern CellUse *ResUse; +extern CellDef *ResDef; +extern TileTypeBitMask ResConnectWithSD[NT]; +extern TileTypeBitMask ResCopyMask[NT]; +extern resResistor *ResResList; +extern resNode *ResNodeList; +extern resTransistor *ResTransList; +extern ResContactPoint *ResContactList; +extern resNode *ResNodeQueue; +extern resNode *ResOriginNode; +extern resNode *resCurrentNode; +extern HashTable ResNodeTable; +extern HashTable ResSimTranTable; +extern ResFixPoint *ResFixList; +extern int ResTileCount; +extern ResSimNode **ResNodeArray; +extern CellDef *mainDef; +extern TileTypeBitMask ResSubsTypeBitMask; +extern HashTable ResTranTable; +extern TileTypeBitMask ResNoMergeMask[NT]; +extern ResGlobalParams gparams; +extern int ResPortIndex; + +extern int ResSimTransistor(); +extern int ResSimCombineParallel(); +extern int ResSimCapacitor(); +extern int ResSimResistor(); +extern int ResSimAttribute(); +extern int ResSimMerge(); +extern int dbSrConnectStartFunc(); +extern int ResEach(),ResAddPlumbing(),ResRemovePlumbing(); +extern float ResCalculateChildCapacitance(); +extern ResTranTile *DBTreeCopyConnectDCS(); +extern Tile *ResFindTile(); +extern resTransistor *ResImageAddPlug(); +extern resTransistor *ResGetTransistor(); +extern tileJunk *resAddField(); +extern int ResCheckPorts(); +extern int ResCheckBlackbox(); +extern void ResCheckSimNodes(); +extern void ResSortByGate(); +extern void ResFixTranName(); +extern void ResWriteLumpFile(); +extern void ResSortBreaks(); + + +/* macros */ + +#define InitializeNode(node,x,y,why) \ +{\ + (node)->rn_te = NULL;\ + (node)->rn_id=0;\ + (node)->rn_float.rn_area = 0.0;\ + (node)->rn_name = NULL;\ + (node)->rn_client = (ClientData)NULL;\ + (node)->rn_noderes = RES_INFINITY;\ + (node)->rn_je = NULL;\ + (node)->rn_status = FALSE;\ + (node)->rn_loc.p_x = (x);\ + (node)->rn_loc.p_y = (y);\ + (node)->rn_why = (why);\ + (node)->rn_ce = (cElement *) NULL;\ + (node)->rn_re = (resElement *) NULL;\ +} + +#define ResJunkInit(Junk) \ +{ \ + Junk->contactList = (cElement *) NULL; \ + Junk->transistorList = (resTransistor *) NULL; \ + Junk->junctionList = (ResJunction *) NULL; \ + Junk->breakList = (Breakpoint *) NULL; \ + Junk->portList = (resPort *) NULL; \ + Junk->tj_status = FALSE; \ + Junk->sourceEdge = 0 ; \ +} + +#define NEWBREAK(node,tile,px,py,crect)\ +{\ + Breakpoint *bp;\ + tileJunk *jX_ = (tileJunk *)((tile)->ti_client); \ + bp = (Breakpoint *) mallocMagic((unsigned)(sizeof(Breakpoint))); \ + bp->br_next= jX_->breakList; \ + bp->br_this = (node); \ + bp->br_loc.p_x = px; \ + bp->br_loc.p_y = py; \ + bp->br_crect = (Rect *) (crect); \ + jX_->breakList = bp; \ +} + +#define NEWPORT(node,tile)\ +{\ + resPort *rp;\ + tileJunk *pX_ = (tileJunk *)((tile)->ti_client); \ + rp = (resPort *) mallocMagic((unsigned)(sizeof(resPort))); \ + rp->rp_nextPort = pX_->portList; \ + rp->rp_bbox = node->rs_bbox; \ + rp->rp_loc = node->drivepoint; \ + rp->rp_nodename = node->name; \ + pX_->portList = rp; \ +} + +#endif /* _RESIS_H */ diff --git a/router/Depend b/router/Depend new file mode 100644 index 00000000..954936a7 --- /dev/null +++ b/router/Depend @@ -0,0 +1,68 @@ +rtrCmd.o: rtrCmd.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/styles.h \ + ../utils/geometry.h ../tiles/tile.h ../utils/hash.h ../utils/utils.h \ + ../database/database.h ../windows/windows.h ../dbwind/dbwind.h \ + ../utils/main.h ../textio/txcommands.h ../select/select.h \ + ../commands/commands.h ../utils/heap.h ../router/router.h \ + ../utils/netlist.h ../netmenu/netmenu.h ../gcr/gcr.h \ + ../grouter/grouter.h ../grouter/grouteDebug.h +rtrMain.o: rtrMain.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/heap.h ../tiles/tile.h ../database/database.h ../gcr/gcr.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/main.h \ + ../utils/signals.h ../router/rtrDcmpose.h ../netmenu/netmenu.h \ + ../router/router.h ../grouter/grouter.h ../grouter/grouteDebug.h \ + ../utils/netlist.h ../textio/textio.h ../utils/runstats.h +rtrDcmpose.o: rtrDcmpose.c ../utils/magic.h ../textio/textio.h \ + ../utils/geometry.h ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../windows/windows.h ../utils/main.h \ + ../dbwind/dbwind.h ../utils/heap.h ../utils/undo.h ../router/router.h \ + ../router/rtrDcmpose.h ../gcr/gcr.h ../grouter/grouter.h \ + ../grouter/grouteDebug.h ../utils/netlist.h ../utils/styles.h \ + ../utils/malloc.h ../netmenu/netmenu.h ../debug/debug.h +rtrFdback.o: rtrFdback.c ../utils/magic.h ../utils/geometry.h \ + ../utils/styles.h ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../windows/windows.h ../utils/main.h ../utils/utils.h ../gcr/gcr.h \ + ../router/router.h ../utils/heap.h ../grouter/grouter.h \ + ../grouter/grouteDebug.h ../utils/netlist.h ../textio/textio.h \ + ../dbwind/dbwind.h ../utils/malloc.h +rtrHazards.o: rtrHazards.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../gcr/gcr.h ../utils/malloc.h +rtrChannel.o: rtrChannel.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../utils/hash.h ../utils/heap.h ../tiles/tile.h \ + ../database/database.h ../gcr/gcr.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/signals.h ../utils/main.h ../router/router.h \ + ../router/rtrDcmpose.h ../grouter/grouter.h ../grouter/grouteDebug.h \ + ../textio/textio.h ../utils/styles.h +rtrPaint.o: rtrPaint.c ../utils/magic.h ../utils/geometry.h \ + ../utils/hash.h ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../gcr/gcr.h ../utils/signals.h ../router/router.h ../grouter/grouter.h \ + ../grouter/grouteDebug.h ../windows/windows.h ../dbwind/dbwind.h \ + ../utils/main.h +rtrPin.o: rtrPin.c ../utils/magic.h ../utils/geometry.h ../utils/styles.h \ + ../utils/hash.h ../utils/heap.h ../debug/debug.h ../tiles/tile.h \ + ../database/database.h ../gcr/gcr.h ../windows/windows.h ../utils/main.h \ + ../dbwind/dbwind.h ../utils/signals.h ../router/router.h \ + ../grouter/grouter.h ../grouter/grouteDebug.h ../textio/textio.h +rtrSide.o: rtrSide.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/heap.h ../utils/malloc.h ../debug/debug.h ../tiles/tile.h \ + ../database/database.h ../router/router.h ../gcr/gcr.h \ + ../grouter/grouter.h ../grouter/grouteDebug.h ../textio/textio.h \ + ../windows/windows.h ../utils/main.h ../utils/signals.h +rtrStem.o: rtrStem.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../tiles/tile.h ../database/database.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../router/router.h ../gcr/gcr.h \ + ../utils/heap.h ../grouter/grouter.h ../grouter/grouteDebug.h \ + ../utils/netlist.h ../textio/textio.h ../utils/main.h ../utils/malloc.h \ + ../debug/debug.h ../utils/signals.h ../utils/maxrect.h +rtrTech.o: rtrTech.c ../utils/magic.h ../utils/utils.h \ + ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/tech.h ../textio/textio.h \ + ../windows/windows.h ../dbwind/dbwind.h ../router/router.h +rtrVia.o: rtrVia.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../utils/heap.h ../database/database.h \ + ../windows/windows.h ../dbwind/dbwind.h ../utils/main.h \ + ../netmenu/netmenu.h ../textio/textio.h ../utils/styles.h \ + ../utils/malloc.h ../gcr/gcr.h ../router/router.h ../router/routerInt.h +rtrTravers.o: rtrTravers.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../utils/signals.h ../utils/malloc.h ../router/router.h \ + ../windows/windows.h ../utils/main.h ../gcr/gcr.h ../router/routerInt.h diff --git a/router/Makefile b/router/Makefile new file mode 100644 index 00000000..5883fdee --- /dev/null +++ b/router/Makefile @@ -0,0 +1,37 @@ +# +# rcsid="$Header: /usr/cvsroot/magic-8.0/router/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" +# + +MODULE = router +MAGICDIR = .. +SRCS = rtrCmd.c rtrMain.c rtrDcmpose.c rtrFdback.c rtrHazards.c \ + rtrChannel.c rtrPaint.c rtrPin.c rtrSide.c rtrStem.c rtrTech.c \ + rtrVia.c rtrTravers.c + +include ${MAGICDIR}/defs.mak + +LIBS += ${LD_EXTRA_LIBS} ${SUB_EXTRA_LIBS} +CLEANS += tclroute${SHDLIB_EXT} tclroute.o + +EXTRA_LIBS = ${MAGICDIR}/garouter/libgarouter.o \ + ${MAGICDIR}/mzrouter/libmzrouter.o ${MAGICDIR}/irouter/libirouter.o \ + ${MAGICDIR}/grouter/libgrouter.o ${MAGICDIR}/gcr/libgcr.o + +tcl-main: tclroute.o tclroute${SHDLIB_EXT} + +tclroute.o: tclroute.c + ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} tclroute.c -c -o tclroute.o + +tclroute${SHDLIB_EXT}: tclroute.o ${OBJS} + @echo --- making Tcl auto-load module \(tclroute${SHDLIB_EXT}\) + ${RM} tclroute${SHDLIB_EXT} + ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} tclroute.o ${OBJS} \ + ${EXTRA_LIBS} -lc ${LIBS} + +install-tcl: $(DESTDIR)${TCLDIR}/tclroute${SHDLIB_EXT} + +$(DESTDIR)${TCLDIR}/tclroute${SHDLIB_EXT}: tclroute${SHDLIB_EXT} + ${RM} $(DESTDIR)${TCLDIR}/tclroute${SHDLIB_EXT} + ${CP} tclroute${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/tclroute${SHDLIB_EXT} + +include ${MAGICDIR}/rules.mak diff --git a/router/router.h b/router/router.h new file mode 100644 index 00000000..e11a2ef1 --- /dev/null +++ b/router/router.h @@ -0,0 +1,193 @@ +/* + * router.h -- + * + * This file defines the interface provided by the router module, + * which is the top-level module that controls routing. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid="$Header: /usr/cvsroot/magic-8.0/router/router.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + */ + +#ifndef _ROUTER_H +#define _ROUTER_H + +#include "database/database.h" +#include "utils/geometry.h" + +/* Masks of directions */ +#define DIRTOMASK(d) (1 << (d)) +#define DIRMASKHASDIR(m, d) ((m) & DIRTOMASK(d)) +#define DIR_EAST DIRTOMASK(GEO_EAST) +#define DIR_WEST DIRTOMASK(GEO_WEST) +#define DIR_NORTH DIRTOMASK(GEO_NORTH) +#define DIR_SOUTH DIRTOMASK(GEO_SOUTH) + +/* + * The following describes the structure used during stem generation. + * It represents one side of a group of one or more cells; we are + * considering terminals coming out of this side into nearby channels. + */ +typedef struct side +{ + int side_side; /* GEO_NORTH, etc: space lies to this side */ + Transform side_trans; /* Transform from coords of this side back + * to original def coordinates if this Side + * was transformed. + */ + + /* The following are in transformed space */ + Rect side_line; /* Coordinates of the boundary: this is either + * a zero-width or a zero-height rectangle. + */ + Rect side_search; /* Search this area to find all cells that + * belong to this Side. + */ + Rect side_used; /* Area reserved for stems; channels cannot + * be created over this area. At a minimum + * this extends to the next grid point outside + * a cell that is far enough away to ensure + * that no design-rule violations are possible + * with material in the inside of the cell. + */ + struct side *side_next; /* Next Side in a list of these structs */ +} Side; + +/* + * The following information describes the two layers used for routing. + * The terms "metal" and "poly" are used for "layer1" and "layer2" + * respectively. They may not actually end up being metal and poly + * (in two-layer metal processes, "poly" will actually be routed in + * the second metal layer). "Metal" is considered to be the preferred + * layer. + */ +extern TileType RtrMetalType; /* Tile type to paint for "metal" */ +extern TileType RtrPolyType; /* Tile type to paint for "poly" */ +/* extern int RtrMetalWidth; */ /* Widths of wires on each layer */ +/* extern int RtrPolyWidth; */ /* (see dbwind/dbwind.h) */ + +/* Contacts to connect the two routing layers */ +extern TileType RtrContactType; /* Tile type to use for contacts */ +/* extern int RtrContactWidth; */ /* Size of contacts (square) */ + /* (see dbwind/dbwind.h) */ +extern int RtrContactOffset; /* Distance between grid line and + * bottom of contact. + */ +extern int RtrMetalSurround; /* After painting a contact, paint + * additional metal for this distance + * around contact. + */ +extern int RtrPolySurround; /* After painting a contact, paint + * additional poly for this distance + * around contact. + */ + +/* Grid spacing for routing */ +extern int RtrGridSpacing; + +/* + * The following stuff describes how far separated the routing must + * be from other material, including both paint and subcells. + */ +extern int RtrSubcellSepUp; /* This is the closest that a routing + * grid line may be above a subcell. + */ +extern int RtrSubcellSepDown; /* The closest a grid line may be + * below a subcell. + */ +extern TileTypeBitMask RtrMetalObstacles;/* Paint layers that the "metal" + * routing layer cannot run across. + */ +extern TileTypeBitMask RtrPolyObstacles;/* Same for "poly" layer. */ +extern int RtrPaintSepsUp[]; /* Array giving, for each tile type, + * how far above material of that + * type the nearest useable routing + * grid line is. + */ +extern int RtrPaintSepsDown[]; /* Array telling how far below paint + * the nearest useable routing grid + * line is. + */ +extern int RtrMetalSeps[]; /* Array giving, for each tile type, + * how away from material of that + * type the nearest metal can be. + */ +extern int RtrPolySeps[]; /* Array telling how far away from poly + * each type of material can be. + */ + +/* Used for creating over-cell channels */ +extern HashTable rtrChannelSplitTbl; + +/* Private procedures */ +int rtrMakeChannel(); + +/* Globals shared by the various pieces of routing code */ +extern int RtrViaLimit; +extern bool RtrDoMMax; +extern bool RtrMazeStems; +extern Rect RouteArea; +extern Plane * RtrChannelPlane; +extern HashTable RtrTileToChannel; +extern float RtrEndConst; +extern struct chan *RtrChannelList; /* Use (struct chan *) to allow this + * file to before after gcr.h + */ +/* + * The origin point for the routing grid: may not + * necessarily be (0,0). + */ +extern Point RtrOrigin; + +/* + * The following macros are used to locate the next higher or + * lower grid line from a given point. The 'o' parameter is + * the coordinate of the origin. + */ +#define RTR_GRIDUP(x, o) ( \ + ( ((x)-(o)) % RtrGridSpacing ) \ + ? ( (x) + (((x) > (o)) ? RtrGridSpacing : 0) \ + - ( ((x)-(o)) % RtrGridSpacing ) ) \ + : (x)) +#define RTR_GRIDDOWN(x, o) ( \ + ( ((x)-(o)) % RtrGridSpacing) \ + ? ((x) - (((x) > (o)) ? 0 : RtrGridSpacing) \ + - ( ((x)-(o)) % RtrGridSpacing)) \ + : (x)) + + + +/* Determine whether or not a tile corresponds to empty space */ +#define RtrIsSpaceTile(tile) (TiGetBody(tile) == (ClientData) NULL) + +/* Technology file reading */ +extern void RtrTechInit(), RtrTechFinal(); +extern bool RtrTechLine(); + +/* Overall procedure to do routing */ +extern void Route(); + +/* Painting and locating stems */ +extern Side *rtrAssignStems(); +extern void RtrPaintAllStems(); +extern bool RtrPaintStem(); +extern void RtrFBPaint(); +extern void RtrFBSwitch(); +extern void rtrFBAdd(); +extern void RtrPaintContact(); +extern void RtrPaintStats(); +extern CellDef *RtrFindChannelDef(); +extern struct pin *RtrPointToPin(); + +#endif /* _ROUTER_H */ diff --git a/router/routerInt.h b/router/routerInt.h new file mode 100644 index 00000000..67bd4ead --- /dev/null +++ b/router/routerInt.h @@ -0,0 +1,33 @@ +/* + * routerInt.h - + * + * Internal definitions for Router module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid="$Header: /usr/cvsroot/magic-8.0/router/routerInt.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + */ + +/* + * Declarations local to the router module, + * but global to all source files within the router module. + */ + +#ifndef _ROUTERINT_H +#define _ROUTERINT_H + +extern int rtrTarget; /* Via minimization, target type */ +extern int rtrReplace; /* Via minimization, replacement type */ +extern int rtrDelta; /* Change in layer width */ + +#endif /* _ROUTERINT_H */ diff --git a/router/rtrChannel.c b/router/rtrChannel.c new file mode 100644 index 00000000..7d448a2a --- /dev/null +++ b/router/rtrChannel.c @@ -0,0 +1,599 @@ +/* rtrChannel.c - + * + * Code to handle channels and the obstacles within them. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrChannel.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "utils/main.h" +#include "router/router.h" +#include "router/rtrDcmpose.h" +#include "grouter/grouter.h" +#include "textio/textio.h" +#include "utils/styles.h" + +/* + * Maps a tile pointer to a channel structure. + * We use this rather than the client fields of tiles because + * they are already used to hold flags during channel decomposition. + */ +HashTable RtrTileToChannel; + +/* Plane in __CHANNEL__ def holding channel tiles */ +Plane *RtrChannelPlane; + +/* List of channels created from decomposed tile plane */ +GCRChannel *RtrChannelList = NULL; + +/* Multiplier for when to make end connections */ +#ifndef lint +float RtrEndConst = 1.0; +#else +float RtrEndConst; /* Sun lint brain death */ +#endif /* lint */ + +/* Forward declarations */ +extern int rtrChannelObstacleMark(); +extern void rtrChannelObstaclePins(); + + +/* + * ---------------------------------------------------------------------------- + * + * RtrChannelRoute -- + * + * This procedure invokes the channel router for the channel 'ch'. + * If the channel is taller than it is wide, swap in x and y before + * routing. If the channel has more pins on the left edge than the + * right, flip left to right before routing. + * + * Results: + * None. + * + * Side effects: + * The parameter *pCount is incremented by the number of errors that + * occurred while routing this channel. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrChannelRoute(ch, pCount) + GCRChannel *ch; + int *pCount; +{ + GCRChannel *flipped, *flipped_again, *copy; + int errs1, errs2; + + /* + * Mark unused stem-tip crossing points as unused once again. + * (They had been marked as blocked during global routing so + * the global router wouldn't try to use them to route over + * cell tops, thereby making it impossible to generate a stem). + */ + RtrPinsFixStems(ch); + + /* + * If the channel is taller than it is long, flip it before + * routing, in order to give the router a better chance of success. + */ + if (ch->gcr_width < ch->gcr_length) + { + flipped = GCRNewChannel(ch->gcr_length, ch->gcr_width); + GCRNoFlip(ch, flipped); + errs1 = GCRroute(flipped); + if (errs1 == 0) + { + /* Save the routing results back in ch. Clean up and return */ + GCRNoFlip(flipped, ch); + RtrFBPaint(0); + goto bottom; + } + + /* Try again with a left-right flip */ + RtrFBSwitch(); + flipped_again = GCRNewChannel(ch->gcr_length, ch->gcr_width); + GCRFlipLeftRight(ch, flipped_again); + errs2 = GCRroute(flipped_again); + if (GcrDebug) + TxError(" Rerouting a channel with %d errors...", errs1); + if (errs2 < errs1) + { + errs1 = errs2; + GCRFlipLeftRight(flipped_again, ch); + if (GcrDebug) + TxError(" to get %d errors\n", errs1); + RtrFBPaint(1); + } + else + { + GCRNoFlip(flipped, ch); + if(GcrDebug) + TxError(" unsuccessfully.\n"); + RtrFBPaint(0); + } + GCRFreeChannel(flipped_again); + goto bottom; + } + else + { + flipped = GCRNewChannel(ch->gcr_width, ch->gcr_length); + GCRFlipXY(ch, flipped); + errs1 = GCRroute(flipped); + if(errs1 == 0) + { + GCRFlipXY(flipped, ch); + RtrFBPaint(0); + goto bottom; + } + + RtrFBSwitch(); + flipped_again = GCRNewChannel(flipped->gcr_length, flipped->gcr_width); + GCRFlipXY(ch, flipped_again); + copy = GCRNewChannel(flipped->gcr_length, flipped->gcr_width); + GCRFlipLeftRight(flipped_again, copy); + if(GcrDebug) + TxError(" Rerouting a channel with %d errors ...", errs1); + errs2 = GCRroute(copy); + if(errs2 < errs1) + { + errs1 = errs2; + GCRFlipLeftRight(copy, flipped); + if(GcrDebug) + TxError(" successfully, with %d errors\n", errs1); + RtrFBPaint(1); + } + else + { + RtrFBPaint(0); + if(GcrDebug) + TxError(" unsuccessfully\n"); + } + + GCRFlipXY(flipped, ch); + GCRFreeChannel(flipped_again); + } + +bottom: + GCRFreeChannel(flipped); + if (errs1 > 0) + gcrSaveChannel(ch); + *pCount += errs1; + RtrMilestonePrint(); +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrChannelBounds -- + * + * Figure out the dimensions of the given channel. + * + * Results: + * None. + * + * Side effects: + * The parameters plength and pwidth are filled in with the number + * of usable columns and rows in channel. The Point pointed to + * by 'origin' is filled in with x and y coords to go in + * ch->origin. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrChannelBounds(loc, pLength, pWidth, origin) + Rect *loc; /* Area the channel is to occupy */ + int *pLength; /* Filled in with # columns in channel */ + int *pWidth; /* Filled in with # rows in channel */ + Point *origin; /* Filled in with coords of (0,0) grid point + * (one grid line below and to left of first + * usable grid point) + */ +{ + char mesg[256]; + int hi, lo; + + /* Find rightmost and leftmost grid contained within channel area */ + hi = RTR_GRIDDOWN(loc->r_xtop, RtrOrigin.p_x); + lo = RTR_GRIDUP(loc->r_xbot, RtrOrigin.p_x); + origin->p_x = lo - RtrGridSpacing; + if (hi < lo) + { + (void) sprintf(mesg, "Degenerate channel at (%d, %d) (%d, %d)", + loc->r_xbot, loc->r_ybot, loc->r_xtop, loc->r_ytop); + DBWFeedbackAdd(loc, mesg, EditCellUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); + TxError("%s\n", mesg); + } + *pLength = (hi - lo) / RtrGridSpacing + 1; + + /* Find topmost and bottommost grid contained within channel area */ + hi = RTR_GRIDDOWN(loc->r_ytop, RtrOrigin.p_y); + lo = RTR_GRIDUP(loc->r_ybot, RtrOrigin.p_y); + origin->p_y = lo - RtrGridSpacing; + if (hi < lo) + { + (void) sprintf(mesg, "Degenerate channel at (%d, %d) (%d, %d)", + loc->r_xbot, loc->r_ybot, loc->r_xtop, loc->r_ytop); + DBWFeedbackAdd(loc, mesg, EditCellUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); + TxError("%s\n", mesg); + } + *pWidth = (hi - lo) / RtrGridSpacing + 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrChannelObstacles -- + * + * Searches a channel area for obstacles. Sets the channel obstacle map + * to indicate which grid locations have obstacles. Uses DBTreeSrTiles() + * to search for obstacles, rather than DBSrPaintArea, since channels can + * lie over existing cells. + * + * Mark obstacles to channel crossings. Reserve blocked pins for net + * GCR_BLOCKEDNETID. Flag obstructed pins to allow the size of their + * accompanying obstacle to be set later (by RtrHazards()). + * + * Only obstacles in this channel are considered; GLBlockPins() must be + * called later to propagate the obstacle information from the border of + * this channel to adjacent channels. + * + * NOTE: RtrChannelObstacles() and those procedures it calls are heavily + * tuned for speed, since DBTreeSrTiles can cause flat searching of + * large portions of a design hierarchy if invoked over the tops of cells. + * + * Results: + * None. + * + * Side effects: + * Sets the channel obstacle map. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrChannelObstacles(use, ch) + CellUse *use; + GCRChannel * ch; +{ + int l, w, up = RtrSubcellSepUp, down = RtrSubcellSepDown; + TileTypeBitMask allObs; + SearchContext scx; + + /* + * Set the obstacle maps in the metal and poly planes. + * Ensure that the combination of this channel and its + * neighbors are sufficient to cover all obstacles in + * the area between the outermost tracks/columns of this + * channel and those of its neighbors. + */ + if (RtrSubcellSepUp + RtrSubcellSepDown < RtrGridSpacing) + { + /* Shouldn't happen; this is just insurance */ + up = RtrGridSpacing - RtrSubcellSepDown; + } + l = ch->gcr_length + 1; + w = ch->gcr_width + 1; + scx.scx_area.r_ll = scx.scx_area.r_ur = ch->gcr_origin; + scx.scx_area.r_xbot -= up; + scx.scx_area.r_ybot -= up; + scx.scx_area.r_xtop += l * RtrGridSpacing + down; + scx.scx_area.r_ytop += w * RtrGridSpacing + down; + scx.scx_use = use; + scx.scx_trans = GeoIdentityTransform; + TTMaskSetMask3(&allObs, &RtrMetalObstacles, &RtrPolyObstacles); + (void) DBTreeSrTiles(&scx, &allObs, 0, rtrChannelObstacleMark, (ClientData) ch); + + rtrChannelObstaclePins(ch); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrChannelObstaclePins -- + * + * Mark obstacles to channel crossings. An obstacle affects a channel + * crossing if it lies within the area from the first track of this + * channel to the first track of the next channel. Reserve blocked pins + * for net GCR_BLOCKEDNETID (ILLEGAL). Flag obstructed pins to allow the + * size of their accompanying obstacle to be set later. + * + * Results: + * None. + * + * Side effects: + * Sets the channel obstacle map. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrChannelObstaclePins(ch) + GCRChannel *ch; +{ + short **res; + int row, col, end; + + res = ch->gcr_result; + end = ch->gcr_length + 1; + for (row = 1; row <= ch->gcr_width; row++) + { + if (BLOCK(res[0][row])) + { + ch->gcr_lPins[row].gcr_pId = GCR_BLOCKEDNETID; + ch->gcr_lPins[row].gcr_pFlags = GCRBLK; + } + else if (!CLEAR(res[0][row])) ch->gcr_lPins[row].gcr_pFlags = GCROBST; + + if (BLOCK(res[end][row])) + { + ch->gcr_rPins[row].gcr_pId = GCR_BLOCKEDNETID; + ch->gcr_rPins[row].gcr_pFlags = GCRBLK; + } + else if (!CLEAR(res[end][row])) ch->gcr_rPins[row].gcr_pFlags = GCROBST; + } + + end = ch->gcr_width+1; + for (col = 1; col <= ch->gcr_length; col++) + { + if (BLOCK(res[col][0])) + { + ch->gcr_bPins[col].gcr_pId = GCR_BLOCKEDNETID; + ch->gcr_bPins[col].gcr_pFlags = GCRBLK; + } + else if (!CLEAR(res[col][0])) ch->gcr_bPins[col].gcr_pFlags = GCROBST; + + if (BLOCK(res[col][end])) + { + ch->gcr_tPins[col].gcr_pId = GCR_BLOCKEDNETID; + ch->gcr_tPins[col].gcr_pFlags = GCRBLK; + } + else if (!CLEAR(res[col][end])) ch->gcr_tPins[col].gcr_pFlags = GCROBST; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrChannelObstacleMark -- + * + * Search routine called by DBTreeSrTiles() from RtrChannelObstacles + * for each tile found in the given area. If the tile is an obstacle, + * mark locations in the channel flag map to indicate their presence. + * + * In addition to setting the GCRBLKM/GCRBLKP flags, we set the bits + * GCRBLKT/GCRBLKC to indicate whether the obstacle blocks a track or + * a column. These latter bits are used only for initializing the + * density information for global routing, and should be reset to + * zero prior to calling the channel router (since they conflict + * with the bits used to show routing). + * + * Results: + * Always returns 0. + * + * Side effects: + * Sets the obstacle map for obstacles in a given channel. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrChannelObstacleMark(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + short **mcol, *mrow, *mrowend, mask; + GCRChannel *ch = (GCRChannel *) cxp->tc_filter->tf_arg; + TileType type = TiGetType(tile); + int loX, numX, loY; + short **mcolend; + int n; + Rect r, r2; + + mask = 0; + if (TTMaskHasType(&RtrMetalObstacles, type)) mask |= GCRBLKM; + if (TTMaskHasType(&RtrPolyObstacles, type)) mask |= GCRBLKP; + if (mask == 0) + return (0); + + TITORECT(tile, &r); + GEOTRANSRECT(&cxp->tc_scx->scx_trans, &r, &r2); + + /* + * Determine the range of columns in this channel that are blocked + * by the obstacle: find the grid coordinates enclosing the tile. + * Clip to a grid 1 larger than the size of the channel. + */ + n = r2.r_xbot - RtrPaintSepsDown[type] + 1; + n = (RTR_GRIDUP(n, RtrOrigin.p_x) - ch->gcr_origin.p_x) / RtrGridSpacing; + loX = MAX(n, 0); + n = r2.r_xtop + RtrPaintSepsUp[type] - 1; + n = (RTR_GRIDUP(n, RtrOrigin.p_x) - ch->gcr_origin.p_x) / RtrGridSpacing; + numX = MIN(n, ch->gcr_length + 1) - loX; + + /* Do the same thing for the rows (n will be the number of rows) */ + n = r2.r_ybot - RtrPaintSepsDown[type] + 1; + n = (RTR_GRIDUP(n, RtrOrigin.p_y) - ch->gcr_origin.p_y) / RtrGridSpacing; + loY = MAX(n, 0); + n = r2.r_ytop + RtrPaintSepsUp[type] - 1; + n = (RTR_GRIDDOWN(n, RtrOrigin.p_y) - ch->gcr_origin.p_y) / RtrGridSpacing; + n = MIN(n, ch->gcr_width + 1) - loY; + + /* + * Figure out whether tracks or columns are being blocked, + * for purposes of the density initialization. + */ + if ((mask & (GCRBLKM|GCRBLKP)) == (GCRBLKM|GCRBLKP)) + { + /* 2-layer obstacles block both tracks and columns */ + mask |= GCRBLKT|GCRBLKC; + } + else if (numX < n) + { + /* Tall and narrow obstacles block columns */ + mask |= GCRBLKC; + } + else + { + /* Short and wide obstacles block tracks */ + mask |= GCRBLKT; + } + + /* + * Now set the flags in the channel. + * The following loop is tuned for speed. + */ + mcol = &ch->gcr_result[loX]; + mcolend = &mcol[numX]; + while (mcol <= mcolend) + { + mrow = &(*mcol++)[loY]; + mrowend = &mrow[n]; + while (mrow <= mrowend) + *mrow++ |= mask; + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrChannelDensity -- + * + * Adjusts the density variables gcr_dRowsByCol and gcr_dColsByRow + * to reflect the commitment of tracks or columns to existing wiring; + * for each column or track blocked by material, the density for + * that track is incremented. Also updates gcr_dMaxByCol and + * gcr_dMaxByRow, the maximum column and track densities. + * + * Results: + * None. + * + * Side effects: + * Initializes ch->gcr_dRowsByCol, ch->gcr_dColsByRow arrays + * and the corresponding maximum values ch->gcr_dMaxByCol + * and ch->gcr_dMaxByRow. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrChannelDensity(ch) + GCRChannel *ch; +{ + short *hdens, *vdens, *rptr; + int col, density; + short *hdend, *vdend; + + /* + * Adjust the density information for global routing. + * Whether a column or track is blocked is indicated by the + * presence of the GCRBLKC/GCRBLKT flags in the result array. + * If both bits are set, then both a column and a track are + * blocked. + */ + hdens = &ch->gcr_dRowsByCol[1]; + hdend = &ch->gcr_dRowsByCol[ch->gcr_length]; + for (col = 1; hdens <= hdend; hdens++, col++) + { + vdens = &ch->gcr_dColsByRow[1]; + vdend = &ch->gcr_dColsByRow[ch->gcr_width]; + rptr = &ch->gcr_result[col][1]; + for ( ; vdens <= vdend; vdens++, rptr++) + { + if (*rptr & GCRBLKT) *hdens += 1; + if (*rptr & GCRBLKC) *vdens += 1; + } + } + +#ifdef IDENSITY + bcopy((char *) ch->gcr_dColsByRow, (char *) ch->gcr_iColsByRow, + (ch->gcr_width + 2) * sizeof (short)); + bcopy((char *) ch->gcr_dRowsByCol, (char *) ch->gcr_iRowsByCol, + (ch->gcr_length + 2) * sizeof (short)); +#endif /* IDENSITY */ + + /* Compute the maximum row and column density */ + + /* Column density */ + density = 0; + hdens = &ch->gcr_dRowsByCol[1]; + hdend = &ch->gcr_dRowsByCol[ch->gcr_length]; + for ( ; hdens <= hdend; hdens++) + if (*hdens > density) density = *hdens; + ch->gcr_dMaxByCol = density; + + /* Row density */ + density = 0; + vdens = &ch->gcr_dColsByRow[1]; + vdend = &ch->gcr_dColsByRow[ch->gcr_width]; + for ( ; vdens <= vdend; vdens++) + if (*vdens > density) density = *vdens; + ch->gcr_dMaxByRow = density; +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrChannelCleanObstacles -- + * + * Clears the GCRBLKC/GCRBLKT bits in the result array of 'ch'. + * + * Results: + * None. + * + * Side effects: + * Resets the GCRBLKC/GCRBLKT flags in the result array, + * since these bits are also used to mean something else + * by the channel router. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrChannelCleanObstacles(ch) + GCRChannel *ch; +{ + short *rptr; + int row, rtop; + int col, ctop; + + ctop = ch->gcr_length + 1; + rtop = ch->gcr_width + 1; + for (col = 0; col <= ctop; col++) + { + rptr = &ch->gcr_result[col][0]; + for (row = 0; row <= rtop; row++) + *rptr++ &= ~(GCRBLKT|GCRBLKC); + } +} diff --git a/router/rtrCmd.c b/router/rtrCmd.c new file mode 100644 index 00000000..ea419ac0 --- /dev/null +++ b/router/rtrCmd.c @@ -0,0 +1,791 @@ +/* + * RouteCmd.c -- + * + * Commands for the route modules only. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrCmd.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/styles.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/utils.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" +#include "textio/txcommands.h" +#include "select/select.h" +#include "commands/commands.h" +#include "utils/heap.h" +#include "router/router.h" +#include "utils/netlist.h" +#include "netmenu/netmenu.h" +#include "gcr/gcr.h" +#include "grouter/grouter.h" + +/* Global variable initialization */ + +bool RtrMazeStems = FALSE; /* Set by default to original behavior */ + +/* + * ---------------------------------------------------------------------------- + * + * CmdGARouterTest -- + * + * Debugging of gate-array router. + * + * Usage: + * *garoute cmd [args] + * + * Results: + * None. + * + * Side effects: + * See comments in GATest() in garouter/gaTest.c for details. + * + * ---------------------------------------------------------------------------- + */ + +void +CmdGARouterTest(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + GATest(w, cmd); +} + +/* + * ---------------------------------------------------------------------------- + * + * CmdGRouterTest -- + * + * Debugging of global router. + * + * Usage: + * *groute cmd [args] + * + * Results: + * None. + * + * Side effects: + * See comments in GlTest() in grouter/glTest.c for details. + * + * ---------------------------------------------------------------------------- + */ + +void +CmdGRouterTest(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + GlTest(w, cmd); +} + +/* + * ---------------------------------------------------------------------------- + * + * CmdIRouterTest -- + * + * Debugging of interactive router. + * + * Usage: + * *iroute [subcmd] [args] + * + * Results: + * None. + * + * Side effects: + * See comments in IRTest() in irouter/irTestCmd.c for details. + * + * ---------------------------------------------------------------------------- + */ + +void +CmdIRouterTest(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + IRTest(w, cmd); +} + +/* + * ---------------------------------------------------------------------------- + * + * CmdMZRouterTest -- + * + * Debugging of maze router. + * + * Usage: + * *mzroute [subcmd] [args] + * + * Results: + * None. + * + * Side effects: + * See comments in MZTest() in mzrouter/mzTestCmd.c for details. + * + * ---------------------------------------------------------------------------- + */ + +void +CmdMZRouterTest(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + MZTest(w, cmd); +} + +/* + * ---------------------------------------------------------------------------- + * + * CmdChannel -- + * + * Implement the "channel" command. Generate a cell __CHANNEL__ showing + * the channel structure for the edit cell, within the area of the box. + * + * Useage: + * :channel [netlist] + * :channel [-] + * + * Results: + * None. + * + * Side effects: + * Creates a __CHANNEL__ def if it does not already exist. Paints + * on the error layer of that def. Uses the feedback layer to display + * the channels that result. + * + * ---------------------------------------------------------------------------- + */ + +void +CmdChannel(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + Rect newBox; + CellDef *def, *RtrDecomposeName(); + char *name; + extern int cmdChannelFunc(); /* Forward declaration. */ + + if (cmd->tx_argc > 3) + { + TxError("Usage: %s [netlist | -]\n", cmd->tx_argv[0]); + return; + } + + if (!ToolGetEditBox(&newBox)) + return; + + name = (char *) NULL; + if (cmd->tx_argc == 2) + name = cmd->tx_argv[1]; + + if (RtrDecomposeName(EditCellUse, &newBox, name) == (CellDef *) NULL) + { + TxError("\nRouting area (box) is too small to hold useful channels.\n"); + return; + } + TxPrintf("\n"); + + /* Display the channels using feedback. */ + + def = DBCellLookDef("__CHANNEL__"); + if (def == NULL) return; + (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], + &newBox, &DBSpaceBits, cmdChannelFunc, + (ClientData) NULL); +} + +int +cmdChannelFunc(tile) + Tile *tile; +{ + Rect area, rootArea; + + TiToRect(tile, &area); + GeoTransRect(&EditToRootTransform, &area, &rootArea); + DBWFeedbackAdd(&area, "Channel area", EditRootDef, 1, + STYLE_OUTLINEHIGHLIGHTS); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * CmdGaRoute -- + * + * Command interface for gate-array routing. + * + * Results: + * None. + * + * Side effects: + * Depends on the command; see below. + * + * ---------------------------------------------------------------------------- + */ + +void +CmdGaRoute(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + typedef enum { CHANNEL, GEN, HELP, NOWARN, RESET, ROUTE, WARN } cmdType; + static char *chanTypeName[] = { "NORMAL", "HRIVER", "VRIVER" }; + extern bool GAStemWarn; + char *name, *channame; + int n, chanType; + Rect editArea; + FILE *f; + static struct + { + char *cmd_name; + cmdType cmd_val; + } cmds[] = { + "channel xl yl xh yh [type]\n\ +channel [type] define a channel", CHANNEL, + "generate type [file] generate channel definition commands", + GEN, + "help print this message", HELP, + "nowarn only warn if all locations of a terminal\n\ + are unreachable", NOWARN, + "route [netlist] route the current cell",ROUTE, + "reset clear all channel definitions", RESET, + "warn leave feedback for each location of a\n\ + terminal that is unreachable", WARN, + 0 + }; + + GAInit(); + if (cmd->tx_argc == 1) + goto doRoute; + + n = LookupStruct(cmd->tx_argv[1], (LookupTable *) cmds, sizeof cmds[0]); + if (n < 0) + { + if (n == -1) + TxError("Ambiguous option: \"%s\"\n", cmd->tx_argv[1]); + else + TxError("Unrecognized routing command: %s\n", cmd->tx_argv[1]); + TxError(" Type \"garoute help\" for help.\n"); + return; + } + + switch (cmds[n].cmd_val) + { + case HELP: + TxPrintf("Gate-array router commands have the form:\n"); + TxPrintf("\"garoute option\", where option is one of:\n\n"); + for (n = 0; cmds[n].cmd_name; n++) + TxPrintf("%s\n", cmds[n].cmd_name); + TxPrintf("\n"); + break; + case WARN: + if (cmd->tx_argc != 2) goto badWarn; + GAStemWarn = TRUE; + TxPrintf( + "Will leave feedback for each unusable terminal loc.\n"); + break; + case NOWARN: + if (cmd->tx_argc != 2) + { +badWarn: + TxError("Usage: \"garoute warn\" or \"garoute nowarn\"\n"); + return; + } + GAStemWarn = FALSE; + TxPrintf( + "Will only leave feedback if all locs for a terminal are unusable.\n"); + break; + case RESET: + TxPrintf("Clearing all channel information.\n"); + GAClearChannels(); + break; + case GEN: + if (cmd->tx_argc < 3 || cmd->tx_argc > 4) + { + TxError("Usage: garoute generate type [file]\n"); + return; + } + if (!ToolGetEditBox(&editArea)) + return; + channame = cmd->tx_argv[2]; + f = stdout; + if (cmd->tx_argc == 4) + { + f = fopen(cmd->tx_argv[3], "w"); + if (f == NULL) + { + perror(cmd->tx_argv[3]); + return; + } + } + if (channame[0] == 'h') GAGenChans(CHAN_HRIVER, &editArea, f); + else if (channame[0] == 'v') GAGenChans(CHAN_VRIVER, &editArea, f); + else + { + TxError("Unrecognized channel type: %s\n", channame); + TxError("Legal types are \"h\" or \"v\"\n"); + } + if (f != stdout) + (void) fclose(f); + break; + case CHANNEL: + channame = (char *) NULL; + if (cmd->tx_argc == 2 || cmd->tx_argc == 3) + { + if (!ToolGetEditBox(&editArea)) + return; + if (cmd->tx_argc == 3) + channame = cmd->tx_argv[2]; + else + chanType = CHAN_NORMAL; /* default */ + } + else if (cmd->tx_argc == 6 || cmd->tx_argc == 7) + { + editArea.r_xbot = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE); + editArea.r_ybot = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE); + editArea.r_xtop = cmdParseCoord(w, cmd->tx_argv[4], FALSE, TRUE); + editArea.r_ytop = cmdParseCoord(w, cmd->tx_argv[5], FALSE, FALSE); + chanType = CHAN_NORMAL; + if (cmd->tx_argc == 7) + channame = cmd->tx_argv[6]; + } + else goto badChanCmd; + if (channame) + { + if (channame[0] == 'h') chanType = CHAN_HRIVER; + else if (channame[0] == 'v') chanType = CHAN_VRIVER; + else + { + TxError("Unrecognized channel type: %s\n", channame); + goto badChanCmd; + } + } + TxPrintf("Channel [%s] %d %d %d %d\n", chanTypeName[chanType], + editArea.r_xbot, editArea.r_ybot, + editArea.r_xtop, editArea.r_ytop); + if (!GADefineChannel(chanType, &editArea)) + { + TxError("Channel definition failed.\n"); + break; + } + break; + case ROUTE: + doRoute: + if (cmd->tx_argc > 3) + { + TxError("Usage: garoute route [netlist]\n"); + break; + } + name = (char *) NULL; + if (cmd->tx_argc == 3) + name = cmd->tx_argv[2]; + n = GARouteCmd(EditCellUse, name); + if (n < 0) + TxError("Couldn't route at all.\n"); + else if (n > 0) + TxPrintf("%d routing error%s.\n", n, n == 1 ? "" : "s"); + else + TxPrintf("No routing errors.\n"); + break; + } + return; + +badChanCmd: + TxError("Usage: garoute channel xlo ylo xhi yhi [type]\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * CmdIRoute -- + * + * Interactive route command. + * Calls command entry point in irouter/irCommand.c + * + * Usage: + * iroute [subcmd [args]] + * (See irCommand.c for details.) + * + * Results: + * None. + * + * Side effects: + * Depends on subcommand, see irCommand.c + * + * ---------------------------------------------------------------------------- + */ + +void +CmdIRoute(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + IRCommand(w,cmd); + + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * CmdRoute -- + * + * Route the nets in the current netlist. + * + * Results: + * None. + * + * Side effects: + * Modifies the edit cell. + * + * ---------------------------------------------------------------------------- + */ + +#define ROUTERCHECKS 0 +#define ROUTERDEBUG 1 +#define ROUTERFILE 2 +#define ROUTERSHOWMAP 3 +#define ROUTERSHOWRES 4 +#define ROUTERSHOWEND 5 +#define ROUTEREND 6 +#define ROUTERHELP 7 +#define ROUTERJOG 8 +#define ROUTERMMAX 9 +#define ROUTERNETLIST 10 +#define ROUTEROBST 11 +#define ROUTERORIGIN 12 +#define ROUTERSTATS 13 +#define ROUTERSETTINGS 14 +#define ROUTERSTEADY 15 +#define ROUTERTECHINFO 16 +#define ROUTERVIAS 17 +#define ROUTERVIAMIN 18 +#define ROUTERMAZESTEMS 19 + +void +CmdRoute(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int option; + GCRChannel *ch; + Rect area; + NLNetList netList; + char *netListName; + + static char *cmdRouteOption[] = + { + "*checks toggle column checking", + "*debug toggle router trace messages", + "*file route from a channel data file", + "*map toggle channel obstacle map display", + "*showcolumns toggle channel column text display", + "*showfinal toggle text display of final channels", + + "end set channel router end constant", + "help print this help information", + "jog int set minimum jog length (grid units)", + "metal toggle metal maximization", + "netlist set current netlist", + "obstacle set obstacle constant", + "origin [x y] print or set routing grid origin", + "stats print and clear previous route statistics", + "settings show router parameters", + "steady set steady net constant", + "tech show router technology information", + "vias set metal maximization via limit (grid units)", + "viamin via minimization", + "mazestems use maze router to route channel stems to pins", + NULL + }; + + if (cmd->tx_argc == 1) + { + if (!ToolGetEditBox(&area)) + return; + Route(EditCellUse, &area); + return; + } + + option = Lookup(cmd->tx_argv[1], cmdRouteOption); + if (option == -1) + { + TxError("Ambiguous routing option: \"%s\"\n", cmd->tx_argv[1]); + goto usage2; + } + if (option < 0) + goto usage; + + switch (option) + { + /* These first few options are for wizards only. + */ + case ROUTERDEBUG: + GcrDebug= !GcrDebug; + TxPrintf("Router debug tracing: %s\n", GcrDebug ? "on" : "off"); + break; + case ROUTERCHECKS: + GcrNoCheck= !GcrNoCheck; + TxPrintf("Router column checking: %s\n", GcrNoCheck ? "on" : "off"); + break; + case ROUTERFILE: + /* Display routing problems from file directly on the screen. + */ + if(cmd->tx_argc!=3) + goto wrongNumArgs; + if((ch = GCRRouteFromFile(cmd->tx_argv[2])) == (GCRChannel *) NULL) + TxError("Bad channel from file %s\n", cmd->tx_argv[2]); + else RtrPaintBack(ch, EditCellUse->cu_def); + break; + case ROUTERSHOWRES: + GcrShowResult= !GcrShowResult; + TxPrintf("Show channel columns: %s\n", GcrShowResult ? "on":"off"); + break; + case ROUTERSHOWEND: + GcrShowEnd= !GcrShowEnd; + TxPrintf("Show finished channels: %s\n", GcrShowEnd ? "on" : "off"); + break; + case ROUTERSHOWMAP: + GcrShowMap= !GcrShowMap; + TxPrintf("Show channel maps: %s\n", GcrShowMap ? "on" : "off"); + break; + + case ROUTERHELP: + TxPrintf("Router commands have the form \"route option\",\n"); + TxPrintf("where option is one of:\n\n"); + if(cmd->tx_argc==2) + for (option=ROUTEREND; option<= ROUTERMAZESTEMS; option++) + TxPrintf(" %s\n", cmdRouteOption[option]); + else + if((cmd->tx_argc==3) && !strcmp(cmd->tx_argv[2], "*wizard")) + for (option=0; option !=ROUTEREND; option++) + TxPrintf(" %s\n", cmdRouteOption[option]); + TxPrintf("\n"); + break; + case ROUTERSTATS: + RtrPaintStats(TT_SPACE, 0); + break; + case ROUTERSETTINGS: + TxPrintf("Router parameter settings:\n"); + TxPrintf(" Channel end constant... %f\n", RtrEndConst); + TxPrintf(" Metal maximization..... %s\n", RtrDoMMax ? "on":"off"); + TxPrintf(" Minimum jog length..... %d\n", GCRMinJog); + TxPrintf(" Net list............... \"%s\"\n", NMNetlistName()); + TxPrintf(" Obstacle constant...... %f\n", GCRObstDist); + TxPrintf(" Steady net constant.... %d\n", GCRSteadyNet); + TxPrintf(" Via limit.............. %d\n", RtrViaLimit); + TxPrintf(" Maze route stems....... %s\n", RtrMazeStems ? "yes" : "no"); + if((cmd->tx_argc!=3) || strcmp(cmd->tx_argv[2], "*wizard")) + break; + TxPrintf("\n"); + TxPrintf(" Debug tracing.......... %s\n", GcrDebug ? "on":"off"); + TxPrintf(" Column checking........ %s\n", GcrNoCheck?"on":"off"); + TxPrintf(" Show channel columns... %s\n", + GcrShowResult ? "on" : "off"); + TxPrintf(" Show finished channels %s\n", GcrShowEnd?"on":"off"); + TxPrintf(" Show channel maps...... %s\n", GcrShowMap?"on":"off"); + break; + case ROUTERTECHINFO: + TxPrintf("Router Technology Information:\n"); + TxPrintf(" Preferred layer..... %s; width %d\n", + DBTypeLongName(RtrMetalType), RtrMetalWidth); + TxPrintf(" Alternate layer..... %s; width %d\n", + DBTypeLongName(RtrPolyType), RtrPolyWidth); + TxPrintf(" Contacts............ %s; ", + DBTypeLongName(RtrContactType)); + TxPrintf("width %d; offset %d; surrounds %d, %d\n", RtrContactWidth, + RtrContactOffset, RtrMetalSurround, RtrPolySurround); + TxPrintf(" Subcell separations: %d up; %d down\n", + RtrSubcellSepUp, RtrSubcellSepDown); + TxPrintf(" Router grid spacing: %d\n", RtrGridSpacing); + break; + case ROUTERMMAX: + RtrDoMMax= !RtrDoMMax; + TxPrintf("Metal maximization: %s\n", RtrDoMMax ? "on" : "off"); + break; + case ROUTERVIAS: + if(cmd->tx_argc!=2) + { + if(cmd->tx_argc!=3) + goto wrongNumArgs; + if(!sscanf(cmd->tx_argv[2], "%d", &RtrViaLimit)) + TxError("Bad value for via limit\n"); + } + TxPrintf("Via limit is %d\n", RtrViaLimit); + break; + case ROUTEREND: + if(cmd->tx_argc!=2) + { + if(cmd->tx_argc!=3) + goto wrongNumArgs; + if(!sscanf(cmd->tx_argv[2], "%f", &RtrEndConst)) + TxError("Bad value for channel end distance\n"); + } + TxPrintf("Channel end constant is %f\n", RtrEndConst); + break; + case ROUTERJOG: + if(cmd->tx_argc!=2) + { + if(cmd->tx_argc!=3) + goto wrongNumArgs; + if(!sscanf(cmd->tx_argv[2], "%d", &GCRMinJog)) + TxError("Bad value for minimum jog length\n"); + } + TxPrintf("Minimum jog length is %d\n", GCRMinJog); + break; + case ROUTEROBST: + if(cmd->tx_argc!=2) + { + if(cmd->tx_argc!=3) + goto wrongNumArgs; + if(!sscanf(cmd->tx_argv[2], "%f", &GCRObstDist)) + TxError("Bad value for obstacle constant\n"); + } + TxPrintf("Obstacle constant is %f\n", GCRObstDist); + break; + case ROUTERSTEADY: + if(cmd->tx_argc!=2) + { + if(cmd->tx_argc!=3) + goto wrongNumArgs; + if(!sscanf(cmd->tx_argv[2], "%d", &GCRSteadyNet)) + TxError("Bad value for steady net constant\n"); + } + TxPrintf("Steady net constant is %d\n", GCRSteadyNet); + break; + case ROUTERNETLIST: + if(cmd->tx_argc!=2) + { + if(cmd->tx_argc!=3) + goto wrongNumArgs; + NMNewNetlist(cmd->tx_argv[2]); + } + TxPrintf("Current list is \"%s\"\n", NMNetlistName()); + break; + case ROUTERORIGIN: + if (cmd->tx_argc != 2) + { + if (cmd->tx_argc != 4) + goto wrongNumArgs; + RtrOrigin.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE); + RtrOrigin.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE); + break; + } + TxPrintf("Routing grid origin = (%d,%d)\n", + RtrOrigin.p_x, RtrOrigin.p_y); + break; + case ROUTERVIAMIN: + if (!ToolGetEditBox(&area)) + return; + if (!NMHasList()) + { + netListName = EditCellUse->cu_def->cd_name; + TxPrintf("No netlist selected yet; using \"%s\".\n", netListName); + NMNewNetlist(netListName); + } + else + netListName = NMNetlistName(); + + if ( NLBuild(EditCellUse, &netList)) + { + int nvia; + + nvia = RtrViaMinimize(EditCellUse->cu_def); + DBWAreaChanged(EditCellUse->cu_def, &area, + DBW_ALLWINDOWS, &DBAllButSpaceBits); + WindUpdate(); + TxPrintf("\n%d vias removed\n",nvia); + NLFree(&netList); + } + break; + case ROUTERMAZESTEMS: + RtrMazeStems = !RtrMazeStems; + TxPrintf("Maze route channel stems: %s\n", RtrMazeStems ? "yes" : "no"); + break; + } /* switch*/ + return; + +wrongNumArgs: + TxError("Wrong number of arguments to %s option.\n", cmd->tx_argv[1]); + TxError("Type \":route help\" for help.\n"); + return; +usage: + TxError("\"%s\" isn't a valid router option.", cmd->tx_argv[1]); + +usage2: + TxError(" Type \"route help\" for help.\n"); + return; +} + +/* + * ---------------------------------------------------------------------------- + * CmdSeeFlags -- + * + * Display router-generated flags on the highlight layer. User points + * to a channel and invokes the command with an argument naming the + * flag to be displayed. + * + * Results: + * None. + * + * Side effects: + * Paints highlights on the screen. Allocates a special cell def and + * initializes a hash table glTileToChannel the first time it is called. + * ---------------------------------------------------------------------------- + */ + +void +CmdSeeFlags(w, cmd) + MagWindow * w; + TxCommand *cmd; +{ + Rect rootRect; + Point point; + MagWindow * window; + + window = CmdGetRootPoint(&point, &rootRect); + if (window == (MagWindow *) NULL) + return; + + if(cmd->tx_argc > 2) + { + TxError("Useage: %s [flag name]\n", cmd->tx_argv[0]); + return; + } + if(cmd->tx_argc == 2) + { + GCRShow(&point, cmd->tx_argv[1]); + TxError("%s: flag highlights turned on.\n", cmd->tx_argv[0]); + } + else + { + NMUnsetCell(); + TxError("%s: flag highlights turned off.\n", cmd->tx_argv[0]); + } +} + diff --git a/router/rtrDcmpose.c b/router/rtrDcmpose.c new file mode 100644 index 00000000..fdfcb419 --- /dev/null +++ b/router/rtrDcmpose.c @@ -0,0 +1,1023 @@ +/* + * rtrDcmpose.c -- + * + * Channel decomposition module. + * + * Create a cell tile plane where each space tile in the error + * plane represents a channel to be separately routed by the + * channel router. + * + * Enumerate cell tile corners, choosing the shortest horizontal or + * vertical extention from a corner to another cell or a previously + * defined channel boundary. Split or merge tiles accordingly. + * + * The ti_client field of space tiles is used is a boolean flag + * in order to distinguish between horizontal edges generated by + * the original plane and horizontal edges defining channels. This + * is done in the new, generated plane--not in the original plane. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrDcmpose.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/heap.h" +#include "utils/undo.h" +#include "router/router.h" +#include "router/rtrDcmpose.h" +#include "gcr/gcr.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "utils/styles.h" +#include "utils/malloc.h" +#include "netmenu/netmenu.h" +#include "debug/debug.h" + +/* The following tile types are used during channel decomposition */ +#define CELLTILE 1 /* Cell tile -- no channels here */ +#define USERCHAN 2 /* User-defined channel */ + +bool rtrDidInit = FALSE; /* TRUE when rtrTileToChannel initialized */ + +/* Area being routed; set in RtrDecompose */ +Rect RouteArea; + +/* Forward declarations */ +extern int rtrSrCells(); +extern void rtrRoundRect(); +extern void rtrHashKill(); +extern void rtrSplitToArea(); +extern void rtrMarkChannel(); +extern void rtrMerge(); + +bool rtrUseCorner(); + +/* + * ---------------------------------------------------------------------------- + * + * RtrDecomposeName -- + * + * Interface to commands module; perform channel decomposition + * over the area 'area', as though we would be routing the netlist + * with the name 'name'. If 'name' is NULL, don't assume any + * netlist; if it is the string "-", use the current netlist. + * + * Results: + * Pointer to the def holding the decomposed channel tiles. If + * the area is too small to be useful, returns NULL. + * + * Side effects: + * See RtrDecompose(). + * + * ---------------------------------------------------------------------------- + */ + +CellDef * +RtrDecomposeName(routeUse, area, name) + CellUse *routeUse; /* Cell to be decomposed */ + Rect *area; /* Confine channels to this area */ + char *name; /* Name of netlist if non-NULL; otherwise, use the + * name of the current netlist or that of routeUse + * as described above. + */ +{ + NLNetList netList, *netListPtr = (NLNetList *) NULL; + CellDef *def; + + if (name) + { + if (strcmp(name, "-") == 0) + name = routeUse->cu_def->cd_name; + NMNewNetlist(name); + + if (NLBuild(routeUse, &netList) <= 0) + TxError("No nets in netlist.\n"); + else + netListPtr = &netList; + } + + def = RtrDecompose(routeUse, area, netListPtr); + + /* Clean up global routing information */ + if (netListPtr) + NLFree(netListPtr); + + return (def); +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrDecompose -- + * + * Top level function of the channel decomposition code. Initialize + * and then enumerate subcells of the edit cell for processing. + * Channels can currently appear only in empty space where there + * are no subcells. + * + * The list of all nets to route is pointed to by 'netList'; this + * will eventually be used when support for over-cell channels is + * put back in. + * + * Results: + * Pointer to the def holding the decomposed channel tiles. If + * the area is too small to be useful, returns NULL. + * + * Side effects: + * The DRC error plane of the returned cell def is marked with space + * tiles [ NO LONGER MAXIMAL HORIZONTAL ] representing channels. + * Modifies area to round it down to even grid points. Modifies + * RouteArea to hold final routing area. + * + * ---------------------------------------------------------------------------- + */ + +CellDef * +RtrDecompose(routeUse, area, netList) + CellUse *routeUse; + Rect *area; + NLNetList *netList; +{ + SearchContext scx; + CellDef *cdTo; + int tmp; + + /* + * Redoing the channel structure invalidates the RtrTileToChannel table. + * Reinitialize the hash table before proceeding. + */ + if (rtrDidInit) rtrHashKill(&RtrTileToChannel); + HashInit(&RtrTileToChannel, 128, 1); + rtrDidInit = TRUE; + + /* + * Round area up so that its edges are at the canonical places + * halfway between grid points. + */ + tmp = RTR_GRIDUP(area->r_xtop, RtrOrigin.p_x) - RtrGridSpacing/2; + if (tmp < area->r_xtop) area->r_xtop = tmp + RtrGridSpacing; + else area->r_xtop = tmp; + tmp = RTR_GRIDUP(area->r_xbot, RtrOrigin.p_x) - RtrGridSpacing/2; + if (tmp > area->r_xbot) area->r_xbot = tmp - RtrGridSpacing; + else area->r_xbot = tmp; + tmp = RTR_GRIDUP(area->r_ytop, RtrOrigin.p_y) - RtrGridSpacing/2; + if (tmp < area->r_ytop) area->r_ytop = tmp + RtrGridSpacing; + else area->r_ytop = tmp; + tmp = RTR_GRIDUP(area->r_ybot, RtrOrigin.p_y) - RtrGridSpacing/2; + if (tmp > area->r_ybot) area->r_ybot = tmp - RtrGridSpacing; + else area->r_ybot = tmp; + RouteArea = *area; + if (GEO_RECTNULL(area)) return NULL; + + cdTo = RtrFindChannelDef(); + + /* + * Paint non-space tiles in both the DRC check and error planes where + * cells are in the source def. Pass the search area to rtrSrCells() + * vi the global RouteArea. The code in rtrSrCells() takes care of + * leaving empty space wherever there are __CHANNEL__ labels. + * + * We make two copies of the channel information because it isn't + * safe to be both searching and updating the same plane. Thus, + * one plane (DRC check) is used for searching, but updates are + * made in the other plane. + */ + UndoDisable(); + DBClearPaintPlane(cdTo->cd_planes[PL_DRC_ERROR]); + DBClearPaintPlane(cdTo->cd_planes[PL_DRC_CHECK]); + + scx.scx_use = routeUse; + scx.scx_area = RouteArea; + scx.scx_trans = GeoIdentityTransform; + (void) DBCellSrArea(&scx, rtrSrCells, (ClientData) cdTo); + + /* Split space tiles to the edges of the routing area */ + rtrSplitToArea(&RouteArea, cdTo); + + /* + * Clear the valid flags for horizontal edges for all space tiles in + * the error plane of the result cell. + */ + (void) TiSrArea((Tile *) NULL, cdTo->cd_planes[PL_DRC_ERROR], &RouteArea, + rtrSrClear, (ClientData) &RouteArea); + + /* + * Enumerate all tiles in the given area. + * If a tile is not a space tile, then perform the corner + * extension algorithm. + */ + (void) TiSrArea((Tile *) NULL, cdTo->cd_planes[PL_DRC_CHECK], &RouteArea, + rtrSrFunc, (ClientData) (cdTo->cd_planes[PL_DRC_ERROR])); + + /* Allow the modified area to be redisplayed if the cell is visible */ + DBReComputeBbox(cdTo); + DBWAreaChanged(cdTo, &RouteArea, DBW_ALLWINDOWS, &DBAllButSpaceBits); + UndoEnable(); + + return (cdTo); +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrFindChannelDef -- + * + * Return a pointer to the __CHANNEL__ cell def that holds the + * channel structure. Creates this cell if it doesn't exist + * + * Results: + * Pointer to the __CHANNEL__ def. + * + * Side effects: + * May create the __CHANNEL__ def if it doesn't already exist. + * If it creates the def, marks it as CDINTERNAL. + * + * ---------------------------------------------------------------------------- + */ + +CellDef * +RtrFindChannelDef() +{ + CellDef *def; + + /* Create our target cell */ + if ((def = DBCellLookDef("__CHANNEL__")) == (CellDef *) NULL) + { + def = DBCellNewDef("__CHANNEL__", (char *) NULL); + DBCellSetAvail(def); + def->cd_flags |= CDINTERNAL; + } + + return (def); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrSrCells -- + * + * Paints a silhouette of the cell tile plane. For each cell, paint + * error paint into the error plane of the CellDef 'def'. Clip any + * paints to the global RouteArea. If the cell is an array, enumerate + * each of its instances separately; this allows connections on interior + * edges of the array. + * + * Results: + * Returns 0 to keep DBCellSrArea from aborting the search. + * + * Side effects: + * Paints into both the DRC check and DRC error planes of the celldef + * given by 'def'. The area of each cell is expanded before painting, + * out to points midway between grid lines. The points are chosen + * so that any routing on grid lines outside the painted area will + * be far enough from the cell not to cause design-rule violations + * (this distance is determined by RtrSubcellSep). In addition, one + * extra grid line is left along side cells to jog terminals over + * to grid points. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrSrCells(scx, targetDef) + SearchContext *scx; /* The cell to be painted */ + CellDef *targetDef; /* The def into which the silhouette is painted */ +{ + CellDef *def = scx->scx_use->cu_def; + Rect rootBbox, gridBbox; + + /* + * Transform the enumerated cell use outlines to get the outline + * of the cell within its parent. + */ + RtrMilestonePrint(); + GeoTransRect(&scx->scx_trans, &def->cd_bbox, &rootBbox); + + /* + * First, move down the bottom and left boundaries of the cell + * to a safe point midway between grid lines. + */ + gridBbox = rootBbox; + rtrRoundRect(&gridBbox, RtrSubcellSepUp, RtrSubcellSepDown, TRUE); + + /* Clip to the routing area and paint into the channel planes */ + GeoClip(&gridBbox, &RouteArea); + (void) DBPaintPlane(targetDef->cd_planes[PL_DRC_CHECK], &gridBbox, + DBStdWriteTbl(CELLTILE), (PaintUndoInfo *) NULL); + (void) DBPaintPlane(targetDef->cd_planes[PL_DRC_ERROR], &gridBbox, + DBStdWriteTbl(CELLTILE), (PaintUndoInfo *) NULL); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrRoundRect -- + * + * Round a rectangle out to the nearest grid line, and + * extend to a point halfway to the next grid point (if + * roundUp is TRUE) or back half a grid from the nearest + * grid line (if roundUp is FALSE). + * + * The halfway points are chosen to be RtrGridSpacing/2 + * down or to the left from grid lines. Before rounding, + * we add sepUp to the top and right, and sepDown to the + * bottom and left. + * + * Results: + * None. + * + * Side effects: + * Modifies 'r' as indicated above. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrRoundRect(r, sepUp, sepDown, roundUp) + Rect *r; + int sepUp, sepDown; + bool roundUp; +{ + int halfGrid = RtrGridSpacing / 2; + + r->r_xbot = RTR_GRIDDOWN(r->r_xbot - sepDown, RtrOrigin.p_x); + r->r_ybot = RTR_GRIDDOWN(r->r_ybot - sepDown, RtrOrigin.p_y); + if (roundUp) + { + r->r_xbot -= halfGrid; + r->r_ybot -= halfGrid; + } + else + { + r->r_xbot += RtrGridSpacing - halfGrid; + r->r_ybot += RtrGridSpacing - halfGrid; + } + + /* + * Move up the top and right boundaries. Note: it's important + * that we always SUBTRACT halfgrid from a grid point rather + * than adding sometimes: if RtrGridSpacing is odd, then adding + * and subtracting give different results. + */ + r->r_xtop = RTR_GRIDUP(r->r_xtop + sepUp, RtrOrigin.p_x); + r->r_ytop = RTR_GRIDUP(r->r_ytop + sepUp, RtrOrigin.p_y); + if (roundUp) + { + r->r_xtop += RtrGridSpacing - halfGrid; + r->r_ytop += RtrGridSpacing - halfGrid; + } + else + { + r->r_xtop -= halfGrid; + r->r_ytop -= halfGrid; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrHashKill -- + * + * Free the remaining storage in channels in the hash table. + * Kill the table. + * + * Results: + * None. + * + * Side effects: + * Memory gets freed. The global RtrTileToChannel gets cleared. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrHashKill(ht) + HashTable *ht; +{ + HashEntry *he; + HashSearch hs; + + HashStartSearch(&hs); + while (he = HashNext(ht, &hs)) + GCRFreeChannel((GCRChannel *) HashGetValue(he)); + HashKill(ht); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrSplitToArea -- + * + * Clip space tiles to the edges of the (given) routing area. + * + * Results: + * None. + * + * Side effects: + * Changes tiles in the data base. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrSplitToArea(area, def) + Rect *area; /* Routing area */ + CellDef *def; /* Def holding routing results */ +{ + Tile *tile; + Point p; + + /* + * First split top and bottom space tiles, if any. + * Note, there is at most one space tile spanning the top + * of the routing area, due to the horizontal strip property + * plus the earlier clipping of cell tiles to the routing area. + */ + p = area->r_ur; + tile = TiSrPoint((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], &p); + if ((TOP(tile) > area->r_ytop) && (BOTTOM(tile) < area->r_ytop)) + (void) TiSplitY(tile, area->r_ytop); + + p.p_y = area->r_ll.p_y - 1; + tile = TiSrPoint((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], &p); + if ((BOTTOM(tile) < area->r_ybot) && (TOP(tile) > area->r_ybot)) + tile = TiSplitY(tile, area->r_ybot); + + /* + * Search up the left edge of the routing area, + * looking for space tiles spanning the edge. + * If found, split them. + */ + p = area->r_ll; + while (p.p_y < area->r_ytop) + { + tile = TiSrPoint(tile, def->cd_planes[PL_DRC_ERROR], &p); + if ((LEFT(tile) < p.p_x) && (RIGHT(tile) > p.p_x)) + tile = TiSplitX(tile, p.p_x); + p.p_y = TOP(tile); + } + + /* Do the right edge of the routing area in the same manner */ + p.p_x = area->r_xtop; + p.p_y = area->r_ybot; + while (p.p_y < area->r_ytop) + { + tile = TiSrPoint(tile, def->cd_planes[PL_DRC_ERROR], &p); + if ((LEFT(tile) < p.p_x) && (RIGHT(tile) > p.p_x)) + tile = TiSplitX(tile, p.p_x); + p.p_y = TOP(tile); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrSrClear -- + * + * TiSrArea function for each tile in the error plane of the __CHANNEL__ + * def. Sets the flags to 0 in internal space tiles, marking horizontal + * invalid. Mark edges at the boundary of the routing region as valid. + * + * Results: + * Always returns 0. + * + * Side effects: + * Sets flags in tiles. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrSrClear(tile, area) + Tile *tile; + Rect *area; +{ + /* Clear all */ + rtrCLEAR(tile, -1); + + if (TiGetBody(tile) == (ClientData) NULL) + { + /* Mark horizontal edges touching box */ + if (TOP(tile) == area->r_ytop) + { + /* Mark top */ + rtrMARK(tile, rtrNW); + rtrMARK(tile, rtrNE); + } + if (BOTTOM(tile) == area->r_ytop) + { + /* Mark bottom */ + rtrMARK(tile, rtrSW); + rtrMARK(tile, rtrSE); + } + } + else + { + /* Mark all flags in a non-space tile */ + + /* Mark top */ + rtrMARK(tile, rtrNW); + rtrMARK(tile, rtrNE); + + /* Mark bottom */ + rtrMARK(tile, rtrSW); + rtrMARK(tile, rtrSE); + } + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrSrFunc -- + * + * Search function called from TiSrArea for each tile in the cell tile + * plane. Do this search in the OLD TILE PLANE. Process corners + * bordering space tiles. + * + * Results: + * Returns a 0 to TiSrArea so it won't abort the search. + * + * Side effects: + * Modifies the result plane to reflect the channel structure. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrSrFunc(tile, plane) + Tile *tile; /* Candidate cell tile */ + Plane *plane; /* Plane in which searches take place */ +{ + Tile *tiles[3]; + Point p; + + /* Ignore space tiles */ + if (TiGetBody(tile) == (ClientData) NULL) + return (0); + + /* + * Check each corner of this cell tile to see if it is convex, + * and no marked boundary is incident upon it. + */ + p = tile->ti_ll; + if (rtrUseCorner(&p, rtrSW, plane, tiles)) + rtrMarkChannel(plane, tiles, &p, rtrSW); + + p.p_y = TOP(tile); + if (rtrUseCorner(&p, rtrNW, plane, tiles)) + rtrMarkChannel(plane, tiles, &p, rtrNW); + + p.p_x = RIGHT(tile); + if (rtrUseCorner(&p, rtrNE, plane, tiles)) + rtrMarkChannel(plane, tiles, &p, rtrNE); + + p.p_y = BOTTOM(tile); + if (rtrUseCorner(&p, rtrSE, plane, tiles)) + rtrMarkChannel(plane, tiles, &p, rtrSE); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrUseCorner -- + * + * Search for legal corners upon which to apply the channel definition + * algorithm. Check both horizontal tiles for markings, since only + * one (the shorter) might be marked. + * + * Results: + * Return FALSE if the corner is not convex or a legal boundary already + * extends from the corner. Otherwise return TRUE. + * + * Side effects: + * Return pointers to space tiles adjacent to the corner. + * tiles[0] is not modified by this routine. + * tiles[1] is the spanning tile above or below the corner. + * tiles[2] is the side tile left or right of the corner. + * + * ---------------------------------------------------------------------------- + */ + +bool +rtrUseCorner(point, corner, plane, tiles) + Point *point; /* Point at which a cell corner is found */ + int corner; /* Selects NE, NW, SE, or SW cell corner */ + Plane *plane; /* Plane to be searched for tiles */ + Tile *tiles[]; /* Return pointers to found space tiles */ +{ + Point p0, p1; + Tile * tile; + + /* Reject a corner if it lies on the boundary of the routing area */ + if (point->p_x <= RouteArea.r_xbot + || point->p_x >= RouteArea.r_xtop + || point->p_y <= RouteArea.r_ybot + || point->p_y >= RouteArea.r_ytop) + { + return (FALSE); + } + + /* + * Search the area above (below) the corner. If two space tiles, then a + * vertical boundary marks a channel edge. If one top (bottom) tile and + * one side tile, and the horizontal edge is not marked, then the corner + * is okay. + */ + p1 = p0 = *point; + switch (corner) + { + case rtrNE: + p1.p_y--; + break; + case rtrNW: + p1.p_x--; + p1.p_y--; + break; + case rtrSE: + p0.p_y--; + break; + case rtrSW: + p0.p_y--; + p1.p_x--; + break; + default: + ASSERT(FALSE, "rtrUseCorner corner botch"); + break; + } + + tile = tiles[1] = TiSrPoint((Tile *) NULL, plane, &p0); + if( (TiGetBody(tile) != (ClientData) NULL) || (LEFT(tile) == point->p_x) + || (RIGHT(tile) == point->p_x) ) + return(FALSE); /* Vertical boundary at corner */ + + tile = tiles[2] = TiSrPoint((Tile *) NULL, plane, &p1); + if(TiGetBody(tile) != (ClientData) NULL) + return(FALSE); /* Not a corner */ + + switch(corner) + { + case rtrNE: return(!rtrMARKED(tile, rtrNW)); break; + case rtrNW: return(!rtrMARKED(tile, rtrNE)); break; + case rtrSE: return(!rtrMARKED(tile, rtrSW)); break; + case rtrSW: return(!rtrMARKED(tile, rtrSE)); break; + } + return(FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrMarkChannel -- + * + * Find the shortest segment from the corner to another boundary. + * Split and merge space tiles to reflect channel structure. Update + * edge status in the tile plane. + * + * Results: + * None. + * + * Side effects: + * Modifies the result plane to reflect channel definition. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrMarkChannel(plane, tiles, point, corner) + Plane *plane; /* Plane for searching */ + Tile *tiles[]; /* Bordering space tiles */ + Point *point; /* Coordinates of corner */ + int corner; /* Corner of tile to process */ +{ + int xDist, yDist, d1, d2, lastY; + Tile *tile, *new; + Point curPt; + bool pos; + + pos = ((corner == rtrNE) || (corner == rtrSE)); + xDist = rtrXDist(tiles, point->p_x, pos); + yDist = rtrYDist(tiles, point, ((corner==rtrNE) || (corner==rtrNW)), plane); + + if (xDist < yDist) /* Choose and mark the horizontal boundary */ + { + if(pos) + { + d1 = RIGHT(tiles[1]); + d2 = RIGHT(tiles[2]); + if(corner == rtrNE) + { + rtrMARK(tiles[2], rtrNW); + if(d1 >= d2) rtrMARK(tiles[2], rtrNE); + if(d1 <= d2) rtrMARK(tiles[1], rtrSE); + } + else + { + rtrMARK(tiles[2], rtrSW); + if(d1 >= d2) rtrMARK(tiles[2], rtrSE); + if(d1 <= d2) rtrMARK(tiles[1], rtrNE); + } + } + else + { + d1 = LEFT(tiles[1]); + d2 = LEFT(tiles[2]); + if(corner == rtrNW) + { + rtrMARK(tiles[2], rtrNE); + if(d1 >= d2) rtrMARK(tiles[2], rtrNW); + if(d1 <= d2) rtrMARK(tiles[1], rtrSW); + } + else + { + rtrMARK(tiles[2], rtrSE); + if(d1 >= d2) rtrMARK(tiles[2], rtrSW); + if(d1 <= d2) rtrMARK(tiles[1], rtrNW); + } + } + } + else /* Choose the vertical boundary */ + { + /* + * Split a sequence of space tiles starting with tiles[0] + * (the bottom tile), for yDist at the point->p_y. + * Merge tiles where possible. + */ + tile=tiles[0]; + curPt.p_x=point->p_x; + curPt.p_y=BOTTOM(tile); + + lastY = point->p_y; + if((corner == rtrNW) || (corner == rtrNE)) lastY += yDist; + + while(TRUE) + { + ASSERT(TiGetBody(tile) == (ClientData)NULL, + "rtrMerge: merge cell tile"); + new = TiSplitX(tile, curPt.p_x); + ASSERT(TiGetBody(new) == (ClientData)NULL, "rtrMerge: merge cell new"); + + /* Fix horizontal flags in 'new' tile and (old) 'tile' tile */ + if (rtrMARKED(tile,rtrNE)) rtrMARK(new,rtrNE); + else rtrCLEAR(new,rtrNE); + if (rtrMARKED(tile,rtrSE)) rtrMARK(new,rtrSE); + else rtrCLEAR(new,rtrNE); + + /* + * Clear these flags: + * couldn't cross the boundary unless it was clear. + */ + rtrCLEAR(new, rtrNW); + rtrCLEAR(new, rtrSW); + rtrCLEAR(tile, rtrNE); + rtrCLEAR(tile, rtrSE); + + /* Merge tile and new with lower neighbors if possible */ + rtrMerge(new, LB(new), plane); + rtrMerge(tile, LB(tile), plane); + + /* Find next (higher) tile to split */ + if (TOP(tile) >= lastY) break; + curPt.p_y = TOP(tile); + tile=TiSrPoint(tile, plane, &curPt); + } + + /* Merge new and tile with upper neighbors if possible */ + rtrMerge(RT(new), new, plane); + rtrMerge(RT(tile), tile, plane); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrYDist -- + * + * Finds the distance from a point to an upper or lower channel boundary. + * + * Results: + * The integer distance from the point to the boundary. + * + * Side effects: + * Return a pointer to the bottom tile in the split sequence. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrYDist(tiles, point, up, plane) + Tile *tiles[]; /* Start tile in [1]. Put bottom tile in [0] */ + Point *point; /* Point from which distance is measure */ + bool up; /* TRUE if search up, FALSE if down */ + Plane *plane; /* Cell plane for search */ +{ + Tile *current = tiles[1], *next; + int x, yStart, flag; + Point p; + + p = *point; + x = p.p_x; + yStart = p.p_y; + + for (;;) + { + if (up) + { + p.p_y = TOP(current); + if (p.p_y >= RouteArea.r_ytop) break; + } + else + { + p.p_y = BOTTOM(current); + if (p.p_y <= RouteArea.r_ybot) break; + p.p_y--; + } + + /* + * See if we ran into a cell tile. Since the cell tile defines + * the boundary of a channel, terminate the search. If going + * down, reset the y coordinate to the bottom of the last good + * channel. + */ + next = TiSrPoint(current, plane, &p); + if (TiGetBody(next) != (ClientData) NULL) + { + if (!up) p.p_y++; + break; + } + + /* Done if a vertical boundary */ + if (LEFT(next) == x || RIGHT(next) == x) + break; + + /* + * Classify as one of the following cases: + * + * __|_n_|__ |___c___| __|_n__| |__ c|__ |__n|__ __|_c__| + * | c | | n | | c| | n | |c | | n| + * (A) (B) (C) (D) (E) (F) + */ + if (LEFT(current) < LEFT(next)) + { + if (RIGHT(current) > RIGHT(next)) + { + if (up) flag = rtrMARKED(next, rtrSW); /*(A)*/ + else flag = rtrMARKED(next, rtrNW); /*(B)*/ + } + else + { + if (up) flag = rtrMARKED(current, rtrNE); /*(C)*/ + else flag = rtrMARKED(current, rtrSE); /*(D)*/ + } + } + else + { + if (up) flag = rtrMARKED(current, rtrNW); /*(E)*/ + else flag = rtrMARKED(current, rtrSW); /*(F)*/ + } + + if (flag) + { + if (!up) p.p_y = BOTTOM(current); + break; + } + current = next; + } + + if (up) + { + tiles[0] = tiles[1]; + return (p.p_y - yStart); + } + else + { + tiles[0] = current; + return (yStart - p.p_y); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrXDist -- + * + * Finds the distance from a point to a left or right channel boundary. + * + * Results: + * The integer distance from the point to the boundary. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrXDist(tiles, x, isRight) + Tile *tiles[]; /* Space tiles bordering the corner */ + int x; /* Starting x for distance calculation */ + bool isRight; /* TRUE if right, FALSE if left */ +{ + int l0, l1; + + if (isRight) + l0 = RIGHT(tiles[1]) - x, l1 = RIGHT(tiles[2]) - x; + else + l0 = x - LEFT(tiles[1]), l1 = x - LEFT(tiles[2]); + + return (MIN(l0, l1)); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrMerge -- + * + * Merge two space tiles provided they share a common horizontal edge. + * The upper is the first argument tile. + * + * Results: + * None. + * + * Side effects: + * Updates the horizontal flags in the resulting tile. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrMerge(tup, tdn, plane) + Tile *tup, *tdn; + Plane *plane; +{ + Tile *side; + + /* Skip if either is a cell tile */ + if (TiGetBody(tup) != (ClientData) NULL + || TiGetBody(tdn) != (ClientData) NULL) + return; + + if (LEFT(tdn) != LEFT(tup) || RIGHT(tdn) != RIGHT(tup)) + return; + + /* + * Set flags for the result. + * Relies on TiJoinY to preserve the first arg as the composite tile. + */ + ASSERT( (BOTTOM(tdn)>=RouteArea.r_ybot) && (TOP(tup)<=RouteArea.r_ytop), + "rtrMerge: merging with a tile outside the routing area"); + + if (rtrMARKED(tdn, rtrSW)) rtrMARK(tup, rtrSW); else rtrCLEAR(tup, rtrSW); + if (rtrMARKED(tdn, rtrSE)) rtrMARK(tup, rtrSE); else rtrCLEAR(tup, rtrSE); + TiJoinY(tup, tdn, plane); + + /* + * Merge sideways if the result of the join matches a tile on either side, + * provided the neighbor is a space tile and is inside the routing area. + */ + side = BL(tup); + if (TiGetBody(side) == (ClientData) NULL + && LEFT(side) >= RouteArea.r_xbot + && TOP(side) == TOP(tup) + && BOTTOM(side) == BOTTOM(tup)) + TiJoinX(tup, side, plane); + + side = TR(tup); + if (TiGetBody(side) == (ClientData) NULL + && RIGHT(side) <= RouteArea.r_xtop + && TOP(side) == TOP(tup) + && BOTTOM(side) == BOTTOM(tup)) + TiJoinX(tup, side, plane); +} diff --git a/router/rtrDcmpose.h b/router/rtrDcmpose.h new file mode 100644 index 00000000..2d4d51f9 --- /dev/null +++ b/router/rtrDcmpose.h @@ -0,0 +1,74 @@ +/* + * rtrDecompose.h -- + * + * Routines to do channel decomposition. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid="$Header: /usr/cvsroot/magic-8.0/router/rtrDcmpose.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + */ + +#ifndef _RTRDECOMPOSE_H +#define _RTRDECOMPOSE_H + +#define rtrNW 1 /* Corner codes : */ +#define rtrSW 2 /* NW=1 ______ NE=8 */ +#define rtrSE 4 /* | | */ +#define rtrNE 8 /* SW=2 |____| SE=4 */ + +/* One horizontal space tile edge may touch an arbitrary number of other tiles: + * _______________________________________________ + * |CELL| |CELL| + * ________**********|____|====|____|****_________ + * |CELL| SPACE |CELL| + * __|____|**********______**************|____|___ + * |CELL| + * __________________|____|_______________________ + * + * Flags indicate permanently marked edges. There are 4 flags, one for each + * overlapping corner edge marked above (*). Test a horizontal edge by + * looking at the tiles on both sides of the edge. If one edge is completely + * spanned by the other marked above (=), then use either of its tile's two + * lower flag bits (they should be identical). + * + * Edge spans can only overlap (*), at the extreme leftmost and/or rightmost + * horizontal tile-to-tile edges. Four flag bits: topLeft, topRight, + * bottomLeft, and bottomRight, are used to test a particular edge. + */ + +/* rtrMARKED(t,s) Tile * t; int s; + * Return 1 if the indicated horizontal boundary of a tile is marked. + */ +#define rtrMARKED(t,s) (((int) (t)->ti_client) & (s)) + +/* rtrMARK(t,s) Tile * t; int s; + * Mark the indicated horizontal tile edge as a valid channel boundary. + */ +#define rtrMARK(t,s) \ + ((t)->ti_client = (ClientData) (((int) (t)->ti_client)&(s))) + +/* rtrCLEAR(t,s) Tile * t; int s; + * Clear the indicated horizontal tile edge as a valid channel boundary. + */ +#define rtrCLEAR(t,s) \ + ((t)->ti_client = (ClientData) (((int) (t)->ti_client)&(!s))) + +/* Private Procedures */ +int rtrSrPaint(); +int rtrSrClear(); +int rtrSrFunc(); + +/* Exported Procedures */ +CellDef * RtrDecompose(); + +#endif /* _RTRDECOMPOSE_H */ diff --git a/router/rtrFdback.c b/router/rtrFdback.c new file mode 100644 index 00000000..9ef0914d --- /dev/null +++ b/router/rtrFdback.c @@ -0,0 +1,236 @@ +/* rtrFeedback.c - + * + * Code to manage feedback from the channel router. If there are + * errors during channel routing, the router reroutes in a different + * direction to try to reduce the number of errors. It has to save + * feedback from these attempts until it knows which version of the + * routing is the real one, whose errors should appear in the layout. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrFdback.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/styles.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "utils/utils.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "utils/heap.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "dbwind/dbwind.h" +#include "utils/malloc.h" + +/* This module maintains two linked lists of feedback information, one for + * each of the possible attempts at channel routing. The information consists + * of a box covering the area to be marked with feedback, and the text of + * a feedback message associated with the area. + */ +typedef struct rtrFb +{ + Rect rtr_R; /* Box for feedback paint */ + char * rtr_c; /* Text for feedback */ + struct rtrFb * rtr_Fnext; /* Link to next feedback */ +} RtrFB; + +RtrFB * rtrFList[] = {(RtrFB *) NULL, (RtrFB *) NULL}; /* Lists of feedback */ +int rtrFNum; /* Says which list is active */ + + +/* + * ---------------------------------------------------------------------------- + * + * RtrChannelError -- + * + * This utility procedure is provided for use by the channel router + * (which isn't supposed to know anything about the rest of Magic). + * This procedure just enters a feedback area to describe an error + * that occurred at a particular location in a channel. + * + * Results: + * None. + * + * Side effects: + * A new feedback area is created. + * Remembers this channel in the table of channels to be dumped + * at the end of routing (for debugging the channel router). + * + * ---------------------------------------------------------------------------- + */ + +void +RtrChannelError(ch, col, track, msg, net) + GCRChannel *ch; /* Channel where error occurred. */ + int col; /* Column where error occurred. */ + int track; /* Track where error occurred. */ + char *msg; /* Message identifying error. */ + NLNet *net; /* Net where error occurred */ +{ + Rect box; + Point old, new; + char buff[2048]; + char * netname; + + if (net) + { + netname = NLNetName(net); + if ((strlen(netname) + strlen(msg)) >= 2048) + netname = "too long"; + (void) sprintf(buff, "Net `%s', channel %p: ", netname, ch); + } + else + { + (void) sprintf(buff, "channel %p: ", ch); + } + (void) strcat(buff, msg); + old.p_x = col; + old.p_y = track; + GeoTransPoint(&ch->gcr_transform, &old, &new); + box.r_xbot = ch->gcr_origin.p_x + (new.p_x * RtrGridSpacing) - 2; + box.r_xtop = box.r_xbot + 4; + box.r_ybot = ch->gcr_origin.p_y + (new.p_y * RtrGridSpacing) - 2; + box.r_ytop = box.r_ybot + 4; + + (void) rtrFBAdd(&box, buff); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrFBClear -- + * + * Initialization for the module, on each channel invocation. + * + * Results: + * None. + * + * Side effects: + * Frees memory and initializes list pointers to NULL. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrFBClear() +{ + RtrFB * temp; + + for(temp=rtrFList[0]; temp!=(RtrFB *) NULL; rtrFList[0]=temp) + { + temp=temp->rtr_Fnext; + freeMagic(rtrFList[0]->rtr_c); + freeMagic((char *) rtrFList[0]); + } + for(temp=rtrFList[1]; temp!=(RtrFB *) NULL; rtrFList[1]=temp) + { + temp=temp->rtr_Fnext; + freeMagic(rtrFList[1]->rtr_c); + freeMagic((char *) rtrFList[1]); + } + rtrFNum=0; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrFBAdd -- + * + * Save the information needed to generate a feedback rectangle. + * + * Results: + * None. + * + * Side effects: + * Memory is allocated. Global variables get changed. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrFBAdd(r, t) + Rect * r; + char * t; +{ + RtrFB * new; + + new=(RtrFB *) mallocMagic((unsigned) sizeof(RtrFB)); + ASSERT(new!=(RtrFB *) NULL, "Malloc failed in rtrFBSave"); + new->rtr_R= *r; + new->rtr_c=StrDup((char **) NULL, t); + new->rtr_Fnext=rtrFList[rtrFNum]; + rtrFList[rtrFNum]=new; +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrFBPaint -- + * + * Paint the information from the selected list into the given design. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrFBPaint(num) + int num; /* Selects which list to use */ +{ + RtrFB *temp; + + for (temp = rtrFList[num]; temp; temp = temp->rtr_Fnext) + DBWFeedbackAdd(&temp->rtr_R, temp->rtr_c, EditCellUse->cu_def, + 1, STYLE_PALEHIGHLIGHTS); + rtrFBClear(); +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrFBSwitch -- + * + * Switch from list 0 to list 1 to record feedback patches. + * + * Results: + * None. + * + * Side effects: + * Changes this module's global keeping track of which list. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrFBSwitch() +{ + ASSERT(rtrFNum==0, "RtrFBSwitch"); + rtrFNum=1; +} diff --git a/router/rtrHazards.c b/router/rtrHazards.c new file mode 100644 index 00000000..2b0ecbf3 --- /dev/null +++ b/router/rtrHazards.c @@ -0,0 +1,597 @@ +/* rtrHazards.c - + * + * Code to set hazard flags at each grid point in a channel. These flags + * are used during channel routing and global routing. + * + * HAZARD FLAGS indicate that the channel router should try to move + * tracks out of the flagged areas, in order to avoid routing over + * blocked areas or obstacles which are wider than they are tall. The + * hazards cover the obstacle, an area immediately ahead of the obstacle, + * and one grid line above and below the obstacle (considering the + * direction of routing) which allows for column contacts. + * The size of the hazard is the product of the global variable + * GCRObstDist and the height of the obstacle. + * + * Hazards are generated for each of the four possible routing directions + * across the channel, though the channel will be routed from left to. + * right. Hazards in the other orientations are used only by the global + * router, in choosing channel-to-channel crossings. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrHazards.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "gcr/gcr.h" +#include "utils/malloc.h" + +/* Forward declarations */ + +extern void rtrFindEnds(); +extern void rtrFlag(); + + +/* + * ---------------------------------------------------------------------------- + * + * RtrHazards -- + * + * Scan the channel obstacle map. Set flags for hazards. Mark left and + * right hazards in one pass, since the height to width ratio is the + * same regardless of direction. Similarly, mark top and bottom hazards + * in another pass. + * + * For left and right hazards: + * Use a top to bottom, left to right point by point scan, comparing the + * width of an obstacle to its height at each grid location. If the + * width is greater than the height, or if the location is blocked: + * (1) Find the height of the obstacle by finding the lowest consecutive + * location for which the condition holds; + * (2) Find the width of the obstacle by extending the line of height to + * the left and right, until some edge of the obstacle is found; + * (3) Paint a hazard over the obstacle plus extensions. Extend left + * a distance proportional to the height of the obstacle. Extend up + * and down by 1 grid line. + * + * For top and bottom hazards: + * As above, with "top" and "bottom" interchanged with "left" and "right", + * and GCRVU and GCRVD substituted for GCRVR and GCRVL. + * + * Results: + * None. + * + * Side effects: + * Memory is allocated and released. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrHazards(ch) + GCRChannel *ch; /* The channel to be flagged */ +{ + short **map, **rtrHeights(), **rtrWidths(), **height, **width; + short *hcol, *wcol, *mcol; + int row, col, bot, top, left, right, maxcol; + + height = rtrHeights(ch); + width = rtrWidths(ch); + + /* + * Scan the channel, looking for a place where obstacle height < width or + * blocked on both layers, and not previously marked. For each such point, + * find the tallest, then widest rectangle containing the point. + */ + map = ch->gcr_result; + for (col = 1; col <= ch->gcr_length; col++) + { + /* + * If there is an obstacle over the crossing, set the Size field of the + * crossing point to indicate how large the obstacle is in the direction + * of the net's travel. This could not be done at the time the GCROBST + * flag was set (RtrChannelObstacles), since heights and widths were not + * yet computed. Extend the obstacle marking outwards 1 grid. + */ + if (ch->gcr_bPins[col].gcr_pFlags == GCROBST) + ch->gcr_bPins[col].gcr_pSize = height[col][1]; + else if (ch->gcr_bPins[col-1].gcr_pFlags == GCROBST) + ch->gcr_bPins[col].gcr_pFlags |= GCRTCC; + else if (ch->gcr_bPins[col+1].gcr_pFlags == GCROBST) + ch->gcr_bPins[col].gcr_pFlags |= GCRTCC; + + if (ch->gcr_tPins[col].gcr_pFlags == GCROBST) + ch->gcr_tPins[col].gcr_pSize = height[col][ch->gcr_width]; + else if (ch->gcr_tPins[col-1].gcr_pFlags == GCROBST) + ch->gcr_tPins[col].gcr_pFlags |= GCRTCC; + else if (ch->gcr_tPins[col+1].gcr_pFlags == GCROBST) + ch->gcr_tPins[col].gcr_pFlags |= GCRTCC; + + hcol = height[col]; + wcol = width[col]; + mcol = map[col]; + for (row = 1; row <= ch->gcr_width; row++) + { + if ((hcol[row] < wcol[row] && !(mcol[row]&GCRVL)) + || BLOCK(mcol[row])) + { + /* + * Find the far side of the region where height < width. + * This is not necessarily row - height - 1 since the + * width may vary. + */ + for (bot = row; row <= ch->gcr_width; row++) + if (hcol[row] >= wcol[row] && !BLOCK(mcol[row])) + break; + top = row - 1; + + /* + * Extend left and right through contiguous material. + * Mark the hazard flags. + */ + left = col; + rtrFindEnds(ch, TRUE, bot, top, &left, &right); + rtrFlag(ch, left, right, bot, top, TRUE); + } + } + } + + /* Go the other way to get the upper and lower flags */ + for (row = 1; row <= ch->gcr_width; row++) + { + /* + * If there is an obstacle over the crossing, set the Size field of the + * crossing point to indicate how large the obstacle is in the direction + * of the net's travel. This could not be done at the time the GCROBST + * flag was set (RtrChannelObstacles), since heights and widths were not + * yet computed. Put GCRTCC markings at the edges. + */ + if (ch->gcr_lPins[row].gcr_pFlags == GCROBST) + ch->gcr_lPins[row].gcr_pSize = width[1][row]; + else if (ch->gcr_lPins[row-1].gcr_pFlags == GCROBST) + ch->gcr_lPins[row].gcr_pFlags |= GCRTCC; + else if (ch->gcr_lPins[row+1].gcr_pFlags == GCROBST) + ch->gcr_lPins[row].gcr_pFlags |= GCRTCC; + + if (ch->gcr_rPins[row].gcr_pFlags == GCROBST) + ch->gcr_rPins[row].gcr_pSize = width[ch->gcr_length][row]; + else if (ch->gcr_rPins[row-1].gcr_pFlags == GCROBST) + ch->gcr_rPins[row].gcr_pFlags |= GCRTCC; + else if (ch->gcr_rPins[row+1].gcr_pFlags == GCROBST) + ch->gcr_rPins[row].gcr_pFlags |= GCRTCC; + + for (col = 1; col <= ch->gcr_length; col++) + { + if ((height[col][row] > width[col][row] && !(map[col][row]&GCRVU)) + || BLOCK(map[col][row])) + { + /* + * Find the far side of the region where height > width. + * This is not necessarily col + width - 1 since the width + * may vary. + */ + for (left = col; col <= ch->gcr_length; col++) + if (height[col][row] <= width[col][row] && + !BLOCK(map[col][row])) + break; + right = col - 1; + + /* + * Extend up and down through contiguous material. + * Mark the hazard flags. + */ + bot = row; + rtrFindEnds(ch, FALSE, left, right, &bot, &top); + rtrFlag(ch, left, right, bot, top, FALSE); + } + } + } + + /* Free storage for height and width */ + maxcol = ch->gcr_length + 1; + for (col = 0; col <= maxcol; col++) + { + freeMagic((char *) height[col]); + freeMagic((char *) width[col]); + } + freeMagic((char *) height); + freeMagic((char *) width); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrHeights -- + * + * Find the heights of all obstacles in the given channel. + * + * Results: + * A pointer to an array of obstacle heights for the given channel. + * + * Side effects: + * Mallocs the memory for the heights array. + * + * ---------------------------------------------------------------------------- + */ + +short ** +rtrHeights(ch) + GCRChannel * ch; /* Channel to be processed */ +{ + short **heights, *obstacles, *hcol; + int i, row; + int col, start, n; + unsigned lenWds, widWds; + + /* + * Malloc and initialize an array to hold the obstacle height + * at each point. + */ + lenWds = ch->gcr_length + 2; + widWds = ch->gcr_width + 2; + heights = (short **) mallocMagic((unsigned) (lenWds * sizeof (short *))); + for (col = 0; col < (int) lenWds; col++) + { + heights[col] = (short *) mallocMagic((unsigned) (widWds * sizeof (short))); + for (row = 0; row < (int) widWds; row++) + heights[col][row] = 0; + } + + /* + * Scan over the obstacle map. + * At the start of an obstacle, scan downward to find the height + * of contiguous material on either or both of the layers. Set + * the obstacle height for every location in the vertical strip + * just scanned. + */ + for (col = 1; col <= ch->gcr_length; col++) + { + hcol = heights[col]; + obstacles = ch->gcr_result[col]; + for (row = 1; row <= ch->gcr_width; row++) + { + obstacles++; + if (CLEAR(*obstacles)) continue; + + /* Found an obstacle of some sort, so scan to its end */ + for (start = row; row <= ch->gcr_width && !CLEAR(*obstacles); row++) + obstacles++; + + /* + * Set height values at every grid point touched + * in this column by the obstacle. + */ + n = row - start; + for (i = start; i < row; i++) + hcol[i] = n; + } + } + + return (heights); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrWidths -- + * + * Find the widths of all obstacles in the given channel. + * + * Results: + * A pointer to an array of obstacle widths for the given channel. + * + * Side effects: + * Mallocs the memory for the widths array. + * + * ---------------------------------------------------------------------------- + */ + +short ** +rtrWidths(ch) + GCRChannel * ch; +{ + short **widths, **map; + int col, i; + unsigned lenWds, widWds; + int row, start, n; + + /* + * Malloc and initialize an array to hold the obstacle width + * at each point. + */ + lenWds = ch->gcr_length + 2; + widWds = ch->gcr_width + 2; + widths = (short **) mallocMagic((unsigned) (lenWds * sizeof (short *))); + for (col = 0; col < (int) lenWds; col++) + { + widths[col] = (short *) mallocMagic((unsigned) (widWds * sizeof (short))); + for (row = 0; row < (int) widWds; row++) + widths[col][row] = 0; + } + map = ch->gcr_result; + + /* + * Scan over the obstacle map. + * At the start of an obstacle, scan right to find the width + * of contiguous material on either or both of the layers. + * Set the obstacle width for every location in the horizontal + * strip just scanned. + */ + for (row = 1; row <= ch->gcr_width; row++) + { + for (col = 1; col <= ch->gcr_length; col++) + { + if (CLEAR(map[col][row])) continue; + + /* Found an obstacle of some sort, so scan to its end */ + for (start = col; col <= ch->gcr_length; col++) + if (CLEAR(map[col][row])) + break; + + /* Set width values at every grid point touched in this column + * by the obstacle. + */ + n = col - start; + for (i = start; i < col; i++) + widths[i][row] = n; + } + } + + return(widths); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrFindEnds -- + * + * Given the top and bottom y values for an obstacle, extend left and right + * to find edges (isHoriz == TRUE). + * + * Given the left and right x values for an obstacle, extend up and down + * to find edges (isHoriz == FALSE). + * + * Results: + * None. + * + * Side effects: + * Returns the two values in * lo and * hi. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrFindEnds(ch, isHoriz, bot, top, lo, hi) + GCRChannel *ch; + int isHoriz; /* 1 if to find horizontal ends */ + int bot; /* Low range to be scanned */ + int top; /* High range to be scanned */ + int *lo; /* Low range of result. Also starting col or row. */ + int *hi; /* High range of result */ +{ + int col, row; + short **map; + + map = ch->gcr_result; + if (isHoriz) + { + /* + * Extend right, through contiguous vertical material from bot to top. + * In this and the next loop "bot" and "top" refer to the lower and + * upper ranges of the vertical strip whose left and right edges are + * sought. + */ + for (col = *lo + 1; col <= ch->gcr_length; col++) + for (row = bot; row <= top; row++) + if (CLEAR(map[col][row])) + goto gotHH; + +gotHH: + /* Found the right edge of material */ + *hi = col - 1; + + /* + * Extend left, through contiguous vertical material + * from bot to top. + */ + for (col = *lo - 1; col > 0; col--) + for (row = bot; row <= top; row++) + if (CLEAR(map[col][row])) + goto gotHL; + +gotHL: + /* Found the left edge of material */ + *lo = col + 1; + } + else + { + /* + * Extend up, through contiguous horizontal material from bot to top. + * In this and the next loop, "bot" and "top" actually refer to the + * left and right limits of the material whose end is sought. + */ + for (row = *lo + 1; row <= ch->gcr_width; row++) + for (col = bot; col <= top; col++) + if (CLEAR(map[col][row])) + goto gotVH; +gotVH: + /* Found the upper edge of material */ + *hi = row - 1; + + /* + * Extend down, through contiguous horizontal material + * from bot to top. + */ + for (row = *lo - 1; row > 0; row--) + for (col = bot; col <= top; col++) + if(CLEAR(map[col][row])) + goto gotVL; +gotVL: + /* Found the lower edge of material */ + *lo = row + 1; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrFlag -- + * + * 1. Set hazard flags in the channel flag array for a given hazard generating + * region and surrounding area. For horizontal regions (isHoriz==TRUE) + * set flags for left to right routing and for right to left routing. + * For vertical regions set flags for top to bottom routing and for + * bottom to top routing. + * + * For a given direction set the hazard flags in the region itself, in an + * area ahead of the region and on one track on either side of the region. + * The size of the area ahead of the region is a product of the height + * of the region and the global variable GCRObstDist. + * + * The boxed area generates flags in the area outlined in 'x'. + * + * xxxxxxxxxxxxxx xxxxxxxxxxxxxx + * --------- x ---------x ---------- x--------- x + * | | x | x | | x | x + * --------- x ---------x ---------- x--------- x + * xxxxxxxxxxxxxx xxxxxxxxxxxxxx + * + * 2. Set GCRHAZRD flags, obstacle size, and obstacle distance for each + * pin which falls in the shadow of a hazard. The size measure says how + * much material there is in the direction the net travels, while the + * distance measure says how far the material is from the pin. Obstacle + * information (for covered pins) is handled in another location. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrFlag(ch, cl, cr, rb, rt, isHoriz) + GCRChannel * ch; /* Channel whose flag array is to be set */ + int cl, cr; /* Left and right limits of columns to be set */ + int rb, rt; /* Bottom and top limits of rows to be set */ + bool isHoriz; /* TRUE if left/right flags, else top/bottom */ +{ + int extra, limit, r, c; + short ** map; + + map = ch->gcr_result; + if(isHoriz) + { + extra = 0.99999 + GCRObstDist * (rt - rb + 1); + limit = cl - extra; + if(limit <= 0) + { + /* Hazard extends over the left edge of the channel. Mark the pins. + * When setting distance to the nearest obstacle, rely on the left to + * right sweep so the closest hazard is found first. + */ + for(r = rb - 1; r <= rt + 1; r++) + if(!ch->gcr_lPins[r].gcr_pFlags) + { + ch->gcr_lPins[r].gcr_pFlags = GCRHAZRD; + ch->gcr_lPins[r].gcr_pDist = cl; + ch->gcr_lPins[r].gcr_pSize = cr - cl; + } + limit = 0; + } + for(c = limit; c < cl; c++) + for(r = rb - 1; r <= rt + 1; r++) + map[c][r] |= GCRVL; + + for(c = cl; c <= cr; c++) + for(r = rb - 1; r <= rb + 1; r++) + map[c][r] |= (GCRVL | GCRVR); + + limit = cr + extra; + if(limit >= ch->gcr_length) + { + /* Hazard extends over the right edge of the channel. Mark the pins. + * When setting distance to the nearest obstacle, rely on the left to + * right sweep so the closest hazard is found last. + */ + for(r = rb - 1; r <= rt + 1; r++) + { + if(!ch->gcr_rPins[r].gcr_pFlags) + ch->gcr_rPins[r].gcr_pFlags = GCRHAZRD; + if(ch->gcr_rPins[r].gcr_pFlags == GCRHAZRD) + { + ch->gcr_rPins[r].gcr_pDist = ch->gcr_length - cr; + ch->gcr_rPins[r].gcr_pSize = cr - cl; + } + } + limit = ch->gcr_length; + } + for(c = cr + 1; c <= limit; c++) + for(r = rb - 1; r <= rt + 1; r++) + map[c][r] |= GCRVR; + } + else + { + extra = 0.99999 + GCRObstDist * (cr - cl + 1); + limit = rb - extra; + if(limit < 0) + { + /* Hazard extends over the bottom edge of the channel. Mark the pins. + */ + for(c = cl - 1; c <= cr + 1; c++) + if(!ch->gcr_bPins[c].gcr_pFlags) + { + ch->gcr_bPins[c].gcr_pFlags = GCRHAZRD; + ch->gcr_bPins[c].gcr_pDist = rb; + ch->gcr_bPins[c].gcr_pSize = rt - rb; + } + limit = 0; + } + for(r = limit; r < rb; r++) + for(c = cl - 1 ; c <= cr + 1; c++) + map[c][r] |= GCRVD; + + for(r = rb; r <= rt; r++) + for(c = cl - 1; c <= cr + 1; c++) + map[c][r] |= (GCRVD | GCRVU); + + limit = rt + extra; + if(limit >= ch->gcr_width) + { + /* Hazard extends over the top edge of the channel. Mark the pins. + */ + for(c = cl - 1; c <= cr + 1; c++) + { + if(!ch->gcr_tPins[c].gcr_pFlags) + ch->gcr_tPins[c].gcr_pFlags = GCRHAZRD; + if(ch->gcr_tPins[c].gcr_pFlags == GCRHAZRD) + { + ch->gcr_tPins[c].gcr_pDist = ch->gcr_width - rt; + ch->gcr_tPins[c].gcr_pSize = rt - rb; + } + } + limit = ch->gcr_width; + } + for(r = rt + 1; r <= limit; r++) + for(c = cl - 1 ; c <= cr + 1; c++) + map[c][r] |= GCRVU; + } +} diff --git a/router/rtrMain.c b/router/rtrMain.c new file mode 100644 index 00000000..45aa49a4 --- /dev/null +++ b/router/rtrMain.c @@ -0,0 +1,280 @@ +/* rtrMain.c - + * + * Top level routing code, and glue that doesn't belong elsewhere. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrMain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" +#include "utils/signals.h" +#include "router/rtrDcmpose.h" +#include "netmenu/netmenu.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "netmenu/netmenu.h" +#include "utils/runstats.h" + +/* Forward declarations */ + +extern int rtrMakeChannel(); +void RtrMilestoneStart(char *); +void RtrMilestoneDone(); + + +/* + * The origin point for the routing grid. + * Set by the "route origin" command. + */ +Point RtrOrigin = { 0, 0 }; + +/* + * ---------------------------------------------------------------------------- + * + * Route -- + * + * Top level procedure for the routing code. + * + * Route all channels in the cell routeUse->cu_def, based on net lists + * in the net list hash table. There currently is no check that the net + * list belongs to the edit cell. + * + * Results: + * None. + * + * Side effects: + * Memory for channels is allocated and set. The channel structure is + * kept around to allow flags to be examined and displayed on the screen. + * Leaves paint in routeUse->cu_def. + * + * ---------------------------------------------------------------------------- + */ + +void +Route(routeUse, routeArea) + CellUse *routeUse; + Rect *routeArea; +{ + CellDef *channelDef; + int errs, numNets; + NLNetList netList; + char *netListName; + + /* Read the netlist into an internal NLNetList structure */ + if (!NMHasList()) + { + netListName = routeUse->cu_def->cd_name; + TxPrintf("No netlist selected yet; using \"%s\".\n", netListName); + NMNewNetlist(netListName); + } + else netListName = NMNetlistName(); + RtrMilestoneStart("Building netlist"); + numNets = NLBuild(routeUse, &netList); + RtrMilestoneDone(); + if (numNets == 0) + { + TxError("No nets to route.\n"); + return; + } + + /* + * Create a plane whose space tiles correspond to channels. + * See the comments in RtrDecompose() for details. + */ + RtrMilestoneStart("Channel decomposition"); + channelDef = RtrDecompose(routeUse, routeArea, &netList); + RtrMilestoneDone(); + if (channelDef == NULL) + { + TxError("Routing area (box) is too small to be of any use.\n"); + goto done; + } + RtrChannelPlane = channelDef->cd_planes[PL_DRC_ERROR]; + + /* + * Enumerate all space tiles in the channel plane, generating a + * channel for each one. Initialize each channel's dimensions, + * but don't do anything else. + */ + RtrChannelList = (GCRChannel *) NULL; + (void) TiSrArea((Tile *) NULL, RtrChannelPlane, &RouteArea, + rtrMakeChannel, (ClientData) &RouteArea); + if (!SigInterruptPending) + { + errs = GARoute(RtrChannelList, routeUse, &netList); + if (errs == 0) + TxPrintf("No routing errors.\n"); + else if (errs == 1) + TxPrintf("There was one routing error: see feedback.\n"); + else TxPrintf("There were %d routing errors: see feedback.\n", errs); + } + +done: + /* Clean up global routing information */ + NLFree(&netList); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrMakeChannel -- + * + * Function passed to TiSrArea to enumerate space tiles and convert them + * to channels. Clip all tiles against the box 'clipBox'. Don't set + * hazards for this channel; that has to happen after stem assignment. + * + * Results: + * Return 0 to keep the search going, 1 to abort. + * + * Side effects: + * Hashes space tile pointers from the channel cell's drc error plane + * to get a pointer to a malloc'ed channel structure. + * + * Prepends this channel to the list being built in RtrChannelList. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrMakeChannel(tile, clipBox) + Tile *tile; /* Potential channel tile; we create a channel whose + * area is equal to that of this tile if the type of + * this tile is TT_SPACE. + */ + Rect *clipBox; /* If non-NULL, clip the channel area to this box */ +{ + int length, width; + HashEntry *entry; + GCRChannel *ch; + Point origin; + Rect bbox; + + if (SigInterruptPending) return (1); + if (TiGetBody(tile) != (ClientData) NULL) return (0); + + entry = HashFind(&RtrTileToChannel, (char *) tile); + ASSERT(HashGetValue(entry) == (char *) 0, "rtrMakeChannel"); + TITORECT(tile, &bbox); + GeoClip(&bbox, clipBox); + + /* + * Figure out how many columns and rows will fit in the area, + * then create and initialize a channel. + */ + RtrChannelBounds(&bbox, &length, &width, &origin); + ch = GCRNewChannel(length, width); + ch->gcr_area = bbox; + ch->gcr_origin = origin; + ch->gcr_type = CHAN_NORMAL; + + /* Remember that we've processed it */ + HashSetValue(entry, (char *) ch); + + /* Prepend to RtrChannelList */ + ch->gcr_next = RtrChannelList; + RtrChannelList = ch; + + return(0); +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrRunStats -- + * RtrMilestoneStart -- + * RtrMilestoneDone -- + * RtrMilestonePrint -- + * + * Miscellaneous procedures for debugging/timing. + * Calling RtrRunStats() prints out the time since the last call + * and the total amount of memory used in the heap. The procedures + * RtrMilestoneStart() and RtrMilestoneDone() should be used to bracket + * calls to the various pieces of the router: the former announces + * that the router is about to enter a given section, and the latter + * says it is done and tells how long it took. During a given section, + * RtrMilestonePrint() will print '#' if no errors have occurred since + * the last call; otherwise, it will print a '!'. + * + * Results: + * None. + * + * Side effects: + * Output to terminal. + * + * ---------------------------------------------------------------------------- + */ + + /* The following are both set by RtrMilestoneStart() */ +static char *rtrMilestoneName; /* Name of the current section */ +static struct tms rtrStartTime; /* Starting time of the current section */ +static int rtrFeedCount; /* Most recent # of feedback areas */ + +void +RtrRunStats() +{ + char *RunStats(); + static struct tms last, delta; + + TxPrintf("%s\n", RunStats(RS_TINCR|RS_MEM, &last, &delta)); + TxFlush(); +} + +void +RtrMilestoneStart(event) + char *event; +{ + rtrMilestoneName = event; + TxPrintf("%s: ", event); + TxFlush(); + (void) times(&rtrStartTime); + rtrFeedCount = DBWFeedbackCount; +} + +void +RtrMilestoneDone() +{ + struct tms tend; + + times(&tend); + TxPrintf("\n%s time: %.1fu %.1fs\n", rtrMilestoneName, + (tend.tms_utime - rtrStartTime.tms_utime) / 60.0, + (tend.tms_stime - rtrStartTime.tms_stime) / 60.0); +} + +void +RtrMilestonePrint() +{ + TxPrintf("%c", (DBWFeedbackCount > rtrFeedCount) ? '!' : '#'); + TxFlush(); + rtrFeedCount = DBWFeedbackCount; +} diff --git a/router/rtrPaint.c b/router/rtrPaint.c new file mode 100644 index 00000000..4f5327fb --- /dev/null +++ b/router/rtrPaint.c @@ -0,0 +1,677 @@ +/* rtrPaint.c - + * + * This file provides procedures that do metal-maximization + * on channel routing results, then paint the results back + * into the edit cell. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/router/rtrPaint.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "utils/signals.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" + +int RtrViaLimit = 2; +int rtrMetalLength = 0; +int rtrPolyLength = 0; +int rtrViaCount = 0; +bool RtrDoMMax = TRUE; + +/* Forward declarations */ + +extern void rtrPaintRows(); +extern void rtrPaintColumns(); +extern void rtrMaxMetal(); + +bool rtrMetalOkay(); +bool rtrDoVia(); + +/* + * ---------------------------------------------------------------------------- + * RtrPaintBack -- + * + * Maximizes metal, then paints the channel routing results + * back into the edit cell. + * + * Results: + * None. + * + * Side effects: + * Metal-maximize flags are set in the channels, and mucho + * paint is added to the edit cell. + * ---------------------------------------------------------------------------- + */ + +void +RtrPaintBack(ch, def) + GCRChannel * ch; + CellDef *def; +{ + if(RtrDoMMax) /*Change poly to metal where possible */ + rtrMaxMetal(ch); + + rtrPaintRows(def, ch); + rtrPaintColumns(def, ch); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrPaintRows -- + * + * This procedure scans a given channel for material in the + * rows (and also for contacts). It outputs the relevant + * material as paint in a cell. + * + * Results: + * None. + * + * Side effects: + * The paint planes of def get modified. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrPaintRows(def, ch) + CellDef *def; /* Def into which paint will go */ + GCRChannel *ch; /* Channel being painted */ +{ + TileType curType, nextType; + short **result, code; + int row, col; + Rect paint, contact; + PaintUndoInfo ui; + + ui.pu_def = def; + result = ch->gcr_result; + for (row = 0; row <= ch->gcr_width && !SigInterruptPending; row++) + { + /* + * For each row, this algorithm just marches across the row + * processing runs of similar material. When the material + * changes, then paint the previous run (if the previous + * run wasn't space). CurType records the kind of material + * currently occupying the track; it's one of RtrMetalType, + * RtrPolyType, or TT_SPACE. NextType records the kind of + * material that will occupy the track in the next column. + */ + curType = TT_SPACE; + for (col = 0; col <= ch->gcr_length; col++) + { + if (rtrDoVia(ch, col, row)) + { + /* + * Contact is needed. Must use a more general form of + * painting here, because contacts appear on several layers. + */ + contact.r_xbot = ch->gcr_origin.p_x + (col * RtrGridSpacing) + + RtrContactOffset; + contact.r_xtop = contact.r_xbot + RtrContactWidth; + contact.r_ybot = ch->gcr_origin.p_y + (row * RtrGridSpacing) + + RtrContactOffset; + contact.r_ytop = contact.r_ybot + RtrContactWidth; + RtrPaintContact(def, &contact); + } + + /* + * Figure out what material is to be present in the track + * between this column and the next to the right. + */ + code = result[col][row]; + if (code & GCRR) + { + if ((result[col+1][row] & GCRBLKM) + || (code & GCRBLKM)) + nextType = RtrPolyType; + else nextType = RtrMetalType; + } + else nextType = TT_SPACE; + + /* If the new type is different from the old, paint the old, + * and store the start of the new run. + */ + + if (nextType != curType) + { + if (curType != TT_SPACE) + { + paint.r_xtop = ch->gcr_origin.p_x + (col * RtrGridSpacing); + RtrPaintStats(curType, paint.r_xtop-paint.r_xbot); + if (curType == RtrMetalType) + paint.r_xtop += RtrMetalWidth; + else paint.r_xtop += RtrPolyWidth; + ui.pu_pNum = DBPlane(curType); + DBPaintPlane(def->cd_planes[ui.pu_pNum], &paint, + DBStdPaintTbl(curType, ui.pu_pNum), &ui); + } + + paint.r_xbot = ch->gcr_origin.p_x + (col * RtrGridSpacing); + paint.r_ybot = ch->gcr_origin.p_y + (row * RtrGridSpacing); + if (nextType == RtrMetalType) + { + paint.r_ytop = paint.r_ybot + RtrMetalWidth; + } + else + { + /* This code also gets executed when nextType is TT_SPACE, + * but it doesn't matter. + */ + paint.r_ytop = paint.r_ybot + RtrPolyWidth; + } + if (col == 0) paint.r_xbot = ch->gcr_area.r_xbot; + } + curType = nextType; + } + + /* + * At the end of the row, we have to output any ongoing material. + * This material extends all the way to the RHS channel boundary. + */ + if (curType != TT_SPACE) + { + paint.r_xtop = ch->gcr_area.r_xtop; + RtrPaintStats(curType, paint.r_xtop - paint.r_xbot); + ui.pu_pNum = DBPlane(curType); + DBPaintPlane(def->cd_planes[ui.pu_pNum], &paint, + DBStdPaintTbl(curType, ui.pu_pNum), &ui); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrPaintColumns -- + * + * This procedure scans the result array for a channel, and paints + * material into def to correspond to stuff in the columns of the + * channel. + * + * Results: + * None. + * + * Side effects: + * Paint is added to the planes of def, corresponding to vertical + * wiring in the channel. Contacts are not painted by this procedure, + * but poly is replaced with metal where maximization has occurred + * and where there are obstacles. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrPaintColumns(def, ch) + CellDef * def; + GCRChannel * ch; +{ + TileType curType; /* Describes what kind of material currently + * occupies the column. It's either RtrMetalType, + * RtrPolyType, or TT_SPACE. + */ + TileType nextType; /* Material that is going to occupy the column next. */ + Rect paint; /* Area to paint. */ + PaintUndoInfo ui; + int row, col; + short *column, code; + + ui.pu_def = def; + for (col = 0; col <= ch->gcr_length; col++) + { + if (SigInterruptPending) return; + column = ch->gcr_result[col]; + curType = TT_SPACE; + + for (row = 0; row <= ch->gcr_width; row++) + { + /* Figure out what material needs to be present in this + * column between this row and the next one above. + */ + + code = column[row]; + if (code & GCRU) + { + if ((code & GCRVM) || (code & GCRBLKP) + || (column[row+1] & GCRBLKP)) + nextType = RtrMetalType; + else nextType = RtrPolyType; + } + else nextType = TT_SPACE; + + /* If the new type is different from the old, paint the old, + * and store the start of the new run. + */ + + if (nextType != curType) + { + if (curType != TT_SPACE) + { + paint.r_ytop = ch->gcr_origin.p_y + (row * RtrGridSpacing); + RtrPaintStats(curType, paint.r_ytop-paint.r_ybot); + if (curType == RtrMetalType) + paint.r_ytop += RtrMetalWidth; + else paint.r_ytop += RtrPolyWidth; + ui.pu_pNum = DBPlane(curType); + DBPaintPlane(def->cd_planes[ui.pu_pNum], &paint, + DBStdPaintTbl(curType, ui.pu_pNum), &ui); + } + + paint.r_xbot = ch->gcr_origin.p_x + (col * RtrGridSpacing); + paint.r_ybot = ch->gcr_origin.p_y + (row * RtrGridSpacing); + if (nextType == RtrMetalType) + { + paint.r_xtop = paint.r_xbot + RtrMetalWidth; + } + else /* Poly or space. */ + { + paint.r_xtop = paint.r_xbot + RtrPolyWidth; + } + if (row == 0) paint.r_ybot = ch->gcr_area.r_ybot; + } + curType = nextType; + } + + /* + * At the top of the column, we have to output any ongoing material. + * This material extends all the way to the top channel boundary. + */ + if (curType != TT_SPACE) + { + paint.r_ytop = ch->gcr_area.r_ytop; + RtrPaintStats(curType, paint.r_ytop-paint.r_ybot); + ui.pu_pNum = DBPlane(curType); + DBPaintPlane(def->cd_planes[ui.pu_pNum], &paint, + DBStdPaintTbl(curType, ui.pu_pNum), &ui); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrDoVia -- + * + * Decide whether a via should be placed, but don't do the actual + * painting. Do this based on the flag bits in adjacent locations. + * Look in all four directions from this location to see what kind + * of material converges on the location where we already know is + * a contact. If the material is of both metal and poly, then need + * a via. + * + * Results: + * TRUE if a via should be placed. Otherwise FALSE. + * + * Side effects: + * May set the flag GCRXX in the current location, to indicate that + * a real via was placed. This is used later when painting the + * vertical runs. + * + * ---------------------------------------------------------------------------- + */ + +bool +rtrDoVia(ch, col, row) + GCRChannel *ch; /* The channel undergoing display */ + int col; /* The x coordinate of the location considered */ + int row; /* The y coordinate of the location considered */ +{ + short up, down, left, right, mask; + short **result, code; + + result = ch->gcr_result; + code = result[col][row]; + if (code & (GCRBLKM|GCRBLKP)) + return (FALSE); + + if (!(code & GCRX)) + { + if (col == 0 && (code & GCRR) && (result[1][row] & GCRBLKM)) + return (TRUE); + + if (col == 1 && (code & GCRR) && + (result[0][row] & GCRR) && (result[0][row] & GCRBLKM)) + return (TRUE); + /* + * else + * if((row == 0) && !(code & GCRBLKP) && (code & GCRU) && + * (result[col][1] & GCRBLKP)) + * return(TRUE); + */ + return (FALSE); + } + + right = result[col+1][row]; + if (col == 0) left = code; + else left = result[col-1][row]; + up = result[col][row+1]; + if (row == 0) down = 0; + else down = result[col][row-1]; + + /* Build up a mask that indicates what layers route to this point. + * If both poly (GCRBLKP) and metal (GCRBLKM) are present, then + * place the contact. + */ + mask = 0; + if (code & GCRU) + { + if ((code & GCRVM) || (up & GCRBLKP)) mask |= GCRBLKM; + else mask |= GCRBLKP; + } + if (code & GCRR) + { + if (right & GCRBLKM) mask |= GCRBLKP; + else mask |= GCRBLKM; + } + if (down & GCRU) + { + if (down & (GCRVM|GCRBLKP)) mask |= GCRBLKM; + else mask |= GCRBLKP; + } + if (left & GCRR) + { + if (left & GCRBLKM) mask |= GCRBLKP; + else mask |= GCRBLKM; + } + + if ((mask & (GCRBLKM|GCRBLKP)) == (GCRBLKM|GCRBLKP)) + { + result[col][row] |= GCRXX; + return (TRUE); + } + + return(FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrMaxMetal -- + * + * Increase metal in the result by converting vertical polysilicon to + * metal wherever possible. Look at adjacent channels to avoid screwing + * up the channel/channel connections. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrMaxMetal(ch) + GCRChannel * ch; +{ + bool needLowX, needHiX, hasLowX, hasHiX, active, cross; + int x, y, i, bottom, top; + short **res, *col, code; + +/* Scan each column in the channel from bottom to top */ + res=ch->gcr_result; + for(x=1; x<=ch->gcr_length; x++) /* For each column in the channel */ + { + /* Set the starting layer. Look down to see if the next channel allows + * a starting run in metal. + */ + col = res[x]; + if((col[0] & GCRU) && rtrMetalOkay(ch, x, GEO_SOUTH) && + ! (col[0] & GCRBLKM)) + { + active = TRUE; + bottom = 0; + needLowX = FALSE; + hasLowX = FALSE; + } + else active = FALSE; + + for(y=1; y <= ch->gcr_width+1; y++) /* For each row in the channel */ + { + /* Scan up from the bottom of the column, looking for the start or end + * of a vertical poly run. + */ + code = col[y]; + cross = ((code & GCRR) && (res[x - 1][y] & GCRR) && !(code & GCRX)); + if(!active) + { + /* No current poly run. See if this location starts one: up, + * not metal blocked, and either a contact or else not crossing + * a metal line. + */ + if(!(code & GCRBLKM) && (code & GCRU) && !cross) + { + active = TRUE; + top = bottom = y; + needLowX = !((code & GCRR) && (res[x-1][y] & GCRR)); + hasLowX = code & GCRX; + } + continue; + } + else + { + /* Currently extending a poly run. See if this location ends one: + * a metal obstacle, + * an unconnected track crossing + * an end of column + * top of the channel + */ + if((code & GCRBLKM) || cross) + { + /* This location is blocked. Back off one track and convert + * the bottom..top span to metal. + */ + top = y - 1; + hasHiX = col[top] & GCRX; + needHiX = TRUE; + } + else + /* If we've reached the top of the channel, see if metal can + * continue into the next channel. Watch out: must have this + * check before the GCRU check, because the top row NEVER has + * GCRU set, even if wire extends to next channel. + */ + if(y > ch->gcr_width) + { + if(rtrMetalOkay(ch, x, GEO_NORTH)) + { + top = y; + needHiX = FALSE; + hasHiX = FALSE; + } + else + { + top = y -1; + hasHiX = col[top] & GCRX; + needHiX = TRUE; + } + } + else + if(!(code & GCRU)) + { + /* The vertical wire ends at this grid point */ + top = y; + needHiX = FALSE; + hasHiX = TRUE; + } + else continue; + } + + /* Can convert the run from bottom to top into metal. Only + * do so if no new vias are created, an existing via is moved, + * or at least RtrViaLimit units are converted to metal. + */ + if( (bottom < top) && + ( ((needLowX + needHiX - hasHiX - hasLowX) <= 1) || + ((top - bottom) >= RtrViaLimit) ) ) + { + for(i = bottom; i< top; i++) + col[i]|=GCRVM; + if(needLowX) col[bottom]|=GCRX; + if(needHiX) col[top]|=GCRX; + } + active = FALSE; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrMetalOkay -- + * + * Look at the given column in the next channel to see if it is + * okay to paint metal into it. It is okay if the corresponding + * location is not metal blocked, and has no metal first track crossing. + * It's automatically ok if the adjacent channel is a cell: stems + * can connect to either layer. + * + * It is not necessary to do this for track crossings, since they + * are metal unless some metal obstacle prevents the crossing, and + * the crossing will be found and noted in glBlock. + * + * Results: + * TRUE if okay to paint metal. Otherwise FALSE. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +rtrMetalOkay(ch, col, dir) + GCRChannel *ch; /* The originating channel for the search */ + int col; /* The crossing column in the originating channel */ + int dir; /* Direction of the crossing NORTH or SOUTH */ +{ + GCRChannel *newCh; + GCRPin *pin; + short flags; + int newCol; + + switch (dir) + { + case GEO_NORTH: pin = &ch->gcr_tPins[col]; break; + case GEO_SOUTH: pin = &ch->gcr_bPins[col]; break; + } + + /* If adjacent to a cell, can use either layer */ + if (pin->gcr_linked == NULL) + return (TRUE); + + newCh = pin->gcr_linked->gcr_ch; + newCol = pin->gcr_linked->gcr_x; + + if (dir == GEO_NORTH) + flags = newCh->gcr_result[newCol][1]; + else + flags = newCh->gcr_result[newCol][newCh->gcr_width]; + + if (flags & (GCRX|GCRXX)) + return (TRUE); + + return ((flags & (GCRBLKM|GCRR)) == 0); +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrPaintContact -- + * + * This procedure is called to paint contacts in the router. It + * paints in material for the contact, plus for any surrounds that + * are required by the technology file. + * + * Results: + * None. + * + * Side effects: + * Material is added to the edit cell. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrPaintContact(def, area) + CellDef *def; /* Cell in which to paint contact. */ + Rect *area; /* Area in which to paint the contact. */ +{ + Rect larger; + + RtrPaintStats(RtrContactType, 0); + DBPaint(def, area, RtrContactType); + if (RtrMetalSurround != 0) + { + GEO_EXPAND(area, RtrMetalSurround, &larger); + DBPaint(def, &larger, RtrMetalType); + } + if (RtrPolySurround != 0) + { + GEO_EXPAND(area, RtrPolySurround, &larger); + DBPaint(def, &larger, RtrPolyType); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrPaintStats -- + * + * Keep statistics on current routing. + * + * Results: + * None. + * + * Side effects: + * Updates the global variables for statistics. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrPaintStats(type, distance) + TileType type; + int distance; +{ + if (distance < 0) distance = -distance; + + if (type == RtrMetalType) rtrMetalLength += distance; + else if (type == RtrPolyType) rtrPolyLength += distance; + else if (type == RtrContactType) rtrViaCount++; + else + { + TxPrintf("Total length %d; Metal %d; Poly %d; Vias %d\n", + rtrMetalLength + rtrPolyLength, rtrMetalLength, rtrPolyLength, + rtrViaCount); + rtrMetalLength = 0; + rtrPolyLength = 0; + rtrViaCount = 0; + } +} diff --git a/router/rtrPin.c b/router/rtrPin.c new file mode 100644 index 00000000..89d98830 --- /dev/null +++ b/router/rtrPin.c @@ -0,0 +1,489 @@ +/* + * rtrPin.c -- + * + * Code for linking together the pins in adjacent channels. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * Lawrence Livermore National Laboratory + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrPin.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/styles.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "debug/debug.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "gcr/gcr.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "dbwind/dbwind.h" +#include "utils/signals.h" +#include "router/router.h" +#include "grouter/grouter.h" +#include "textio/textio.h" + +/* Forward declarations */ +bool rtrPinArrayBlock(); +void rtrPinShow(GCRPin *); + + +/* + * ---------------------------------------------------------------------------- + * + * RtrPinsInit -- + * + * Initialize the global-router specific information for the pins + * around the periphery of the channel 'ch': + * + * gcr_ch Points back to the channel. + * gcr_cost Set to INFINITY. + * gcr_side Set to the side of the channel to which this pin + * belongs (GEO_NORTH, GEO_SOUTH, etc). + * gcr_point Set to the absolute (edit cell) coordinates + * of the crossing point associated with this pin. + * gcr_linked Points to the pin on the other side of this pin's + * crossing, or is NULL if there is no other pin. + * The gcr_linked field is set to NULL if crossing + * from a pin to the neighboring channel would exit + * a river-routing channel from an illegal side. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrPinsInit(ch) + GCRChannel *ch; +{ + rtrPinArrayInit(ch, GEO_NORTH, ch->gcr_tPins, ch->gcr_length); + rtrPinArrayInit(ch, GEO_SOUTH, ch->gcr_bPins, ch->gcr_length); + rtrPinArrayInit(ch, GEO_WEST, ch->gcr_lPins, ch->gcr_width); + rtrPinArrayInit(ch, GEO_EAST, ch->gcr_rPins, ch->gcr_width); +} + +int +rtrPinArrayInit(ch, side, pins, nPins) + GCRChannel *ch; + GCRPin *pins; + int nPins; +{ + GCRPin *pin, *linked; + GCRChannel *adjacent; + GCRPin *lastPin; + Point point, p; + bool markLinked; + int otherSide; + Tile *tp; + + /* + * If exiting this channel from an illegal side, all gcr_linked fields + * are set to NULL. + */ + markLinked = TRUE; + switch (side) + { + case GEO_EAST: + case GEO_WEST: + if (ch->gcr_type == CHAN_VRIVER) + markLinked = FALSE; + break; + case GEO_NORTH: + case GEO_SOUTH: + if (ch->gcr_type == CHAN_HRIVER) + markLinked = FALSE; + break; + } + + lastPin = &pins[nPins + 1]; + for (pin = pins; pin <= lastPin; pin++) + { + pin->gcr_ch = ch; + pin->gcr_side = side; + pin->gcr_cost = INFINITY; + pin->gcr_linked = (GCRPin *) NULL; + otherSide = GeoOppositePos[side]; + + /* Figure out the crossing point */ + switch (side) + { + case GEO_WEST: + point.p_y = ch->gcr_origin.p_y + pin->gcr_y * RtrGridSpacing; + point.p_x = ch->gcr_area.r_xbot; + break; + case GEO_SOUTH: + point.p_x = ch->gcr_origin.p_x + pin->gcr_x * RtrGridSpacing; + point.p_y = ch->gcr_area.r_ybot; + break; + case GEO_EAST: + point.p_y = ch->gcr_origin.p_y + pin->gcr_y * RtrGridSpacing; + point.p_x = ch->gcr_area.r_xtop; + break; + case GEO_NORTH: + point.p_x = ch->gcr_origin.p_x + pin->gcr_x * RtrGridSpacing; + point.p_y = ch->gcr_area.r_ytop; + break; + default: + ASSERT(FALSE, "bad pin side in rtrInitPinArray"); + break; + } + pin->gcr_point = point; + + /* Don't set gcr_linked if exiting the channel from an illegal side */ + if (!markLinked) + continue; + + if (pin > pins && pin < lastPin) + { + /* + * Find the adjacent channel at that point. + * If one exists, find the pin in it that shares + * this pin's crossing. + */ + p = point; + if (side == GEO_WEST) p.p_x--; + if (side == GEO_SOUTH) p.p_y--; + tp = TiSrPointNoHint(RtrChannelPlane, &p); + if (adjacent = (GCRChannel *) tp->ti_client) + { + /* Only link if entering the linked channel from a legal side */ + linked = RtrPointToPin(adjacent, otherSide, &point); + switch (side) + { + case GEO_EAST: + case GEO_WEST: + if (adjacent->gcr_type != CHAN_VRIVER) + pin->gcr_linked = linked; + break; + case GEO_NORTH: + case GEO_SOUTH: + if (adjacent->gcr_type != CHAN_HRIVER) + pin->gcr_linked = linked; + break; + } + } + } + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrPointToPin -- + * + * Given a point somewhere on the perimeter of a channel, determine + * which pin it refers to. + * + * Results: + * Pointer to the pin struct whose location is given by pt. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +GCRPin * +RtrPointToPin(ch, side, point) + GCRChannel *ch; /* The channel containing the point */ + int side; /* Side of ch that point lies on */ + Point *point; /* The point to be converted to a pin */ +{ + int coord; + + switch (side) + { + case GEO_NORTH: + coord = (point->p_x - ch->gcr_origin.p_x) / RtrGridSpacing; + ASSERT(coord <= ch->gcr_length && coord >= 1, "RtrPointToPin"); + return &ch->gcr_tPins[coord]; + break; + + case GEO_SOUTH: + coord = (point->p_x - ch->gcr_origin.p_x) / RtrGridSpacing; + ASSERT(coord <= ch->gcr_length && coord >= 1, "RtrPointToPin"); + return &ch->gcr_bPins[coord]; + break; + + case GEO_EAST: + coord = (point->p_y - ch->gcr_origin.p_y) / RtrGridSpacing; + ASSERT(coord <= ch->gcr_width && coord >= 1, "RtrPointToPin"); + return &ch->gcr_rPins[coord]; + break; + + case GEO_WEST: + coord = (point->p_y - ch->gcr_origin.p_y) / RtrGridSpacing; + ASSERT(coord <= ch->gcr_width && coord >= 1, "RtrPointToPin"); + return &ch->gcr_lPins[coord]; + break; + } + + /* + * The pin is not on a side of the channel. + * Recover by returning a strange value which should + * not hurt anything. + */ + ASSERT(FALSE, "Pin not on side of channel in RtrPointToPin"); + return &ch->gcr_lPins[0]; +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrPinsBlock -- + * + * Propagate blocked pin information. If a pin is blocked on one side + * of a channel BOUNDARY, it is blocked on the other side as well. If + * a pin on one side of a river-routing CHANNEL is blocked, the pin on + * the other side gets blocked too. Several iterations may be necessary + * to propagate blockages across all channel boundaries and river-routing + * channels. + * + * Also propagate obstacle flags for pins. If a pin's obstacle flags + * contain GCROBST, then set this bit in gcr_linked's flags as well. + * + * Results: + * TRUE if the blockage state of any pins changed, FALSE + * otherwise. The caller should iterate over all channels + * until no pins change any more. + * + * Side effects: + * Propagating a blockage to a pin consists of marking its + * gcr_pId with GCR_BLOCKEDNETID, and setting the GCRBLK flag + * in its gcr_pFlags (this latter only happens for gcr_linked + * pins, not for pins on the opposite side of a river-routing + * channel from a blocked pin). + * + * ---------------------------------------------------------------------------- + */ + +bool +RtrPinsBlock(ch) + GCRChannel *ch; +{ + bool changed; + + changed = FALSE; + if (rtrPinArrayBlock(ch, ch->gcr_tPins, ch->gcr_bPins, ch->gcr_length)) + changed = TRUE; + if (rtrPinArrayBlock(ch, ch->gcr_bPins, ch->gcr_tPins, ch->gcr_length)) + changed = TRUE; + if (rtrPinArrayBlock(ch, ch->gcr_lPins, ch->gcr_rPins, ch->gcr_width)) + changed = TRUE; + if (rtrPinArrayBlock(ch, ch->gcr_rPins, ch->gcr_lPins, ch->gcr_width)) + changed = TRUE; + + return changed; +} + +bool +rtrPinArrayBlock(ch, pins, opins, nPins) + GCRChannel *ch; /* Channel pins belong to */ + GCRPin *pins; /* Processing this side of channel */ + GCRPin *opins; /* Pins on opposite side; used only if ch is a + * river-routing channel. + */ + int nPins; /* Number of internal pins (not counting pins[0]) */ +{ + bool changed, isRiver = (ch->gcr_type != CHAN_NORMAL); + GCRPin *pin, *opin, *linked; + GCRPin *lastPin; + + changed = FALSE; + lastPin = &pins[nPins]; + for (pin = pins + 1, opin = opins + 1; pin <= lastPin; pin++, opin++) + { + linked = pin->gcr_linked; + + /* Propagate blockages */ + if (pin->gcr_pId == GCR_BLOCKEDNETID) + { + if (linked && linked->gcr_pId == (GCRNet *) NULL) + { + linked->gcr_pFlags |= GCRBLK; + linked->gcr_pId = GCR_BLOCKEDNETID; + changed = TRUE; + } + if (isRiver && opin->gcr_pId == (GCRNet *) NULL) + opin->gcr_pId = GCR_BLOCKEDNETID, changed = TRUE; + } + + /* Propagate obstacle flags */ + if ((pin->gcr_pFlags & GCROBST) && linked) + linked->gcr_pFlags |= GCROBST; + } + + return changed; +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrPinsLink -- + * + * Link the "usable" pins along each side of a channel into a doubly-linked + * list headed by the zero-th pin along that side. Usable pins (for purposes + * of global routing) are those that are unassigned (gcr_pId == 0) and that + * have gcr_linked != NULL. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrPinsLink(ch) + GCRChannel *ch; +{ + rtrPinArrayLink(ch->gcr_tPins, ch->gcr_length); + rtrPinArrayLink(ch->gcr_bPins, ch->gcr_length); + rtrPinArrayLink(ch->gcr_lPins, ch->gcr_width); + rtrPinArrayLink(ch->gcr_rPins, ch->gcr_width); +} + +int +rtrPinArrayLink(pins, nPins) + GCRPin *pins; + int nPins; +{ + GCRPin *pin, *lastPin, *lastValid; + + lastPin = &pins[nPins]; + lastValid = pins; + lastValid->gcr_pPrev = lastValid->gcr_pNext = (GCRPin *) NULL; + for (pin = pins + 1; pin <= lastPin; pin++) + { + pin->gcr_pNext = pin->gcr_pPrev = (GCRPin *) NULL; + if (pin->gcr_linked && pin->gcr_pId == (GCRNet *) NULL) + { + lastValid->gcr_pNext = pin; + pin->gcr_pPrev = lastValid; + lastValid = pin; + } + if (DebugIsSet(glDebugID, glDebShowPins)) + rtrPinShow(pin); + } + return 0; +} + +void rtrPinShow(pin) + GCRPin *pin; +{ + char mesg[256]; + Rect r, area; + Point p; + + p = pin->gcr_point; + switch (pin->gcr_side) + { + case GEO_NORTH: + p.p_y = RTR_GRIDDOWN(p.p_y, RtrOrigin.p_y); + break; + case GEO_SOUTH: + p.p_y = RTR_GRIDUP(p.p_y, RtrOrigin.p_y); + break; + case GEO_EAST: + p.p_x = RTR_GRIDDOWN(p.p_x, RtrOrigin.p_x); + break; + case GEO_WEST: + p.p_x = RTR_GRIDUP(p.p_x, RtrOrigin.p_x); + break; + } + + r.r_ll = r.r_ur = p; + r.r_xtop += 4, r.r_ytop += 4; + + area = pin->gcr_ch->gcr_area; + (void) sprintf(mesg, + "ChanType=%d grid=(%d,%d) point=(%d,%d) Net=%"DLONG_PREFIX"d, linked=%p", + pin->gcr_ch->gcr_type, + pin->gcr_x, pin->gcr_y, + pin->gcr_point.p_x, pin->gcr_point.p_y, + (dlong) pin->gcr_pId, pin->gcr_linked); + if (pin->gcr_pId || pin->gcr_linked == NULL) + (void) strcat(mesg, " **BLOCKED**"); + else DBWFeedbackAdd(&r, mesg, EditCellUse->cu_def, 1, STYLE_PALEHIGHLIGHTS); +#ifdef notdef + ShowRect(EditCellUse->cu_def, &r, STYLE_SOLIDHIGHLIGHTS); + TxMore(mesg); + ShowRect(EditCellUse->cu_def, &r, STYLE_ERASEHIGHLIGHTS); +#endif /* notdef */ +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrPinsFixStems -- + * + * Only some of the crossing points marked during stem assignment were + * actually used during global routing. The unused ones have gcr_pSeg + * equal to GCR_STEMSEGID and must be unmarked here (otherwise the channel + * router will try to route them!). + * + * Results: + * None. + * + * Side effects: + * For each pin on the boundary of 'ch' that is marked as in use + * (gcr_pId != 0 && gcr_pId != GCR_BLOCKEDNETID) and that has a segment + * id of GCR_STEMSEGID (gcr_pSeg == GCR_STEMSEGID), mark it as unused + * (gcr_pId == 0). + * + * ---------------------------------------------------------------------------- + */ + +void +RtrPinsFixStems(ch) + GCRChannel *ch; +{ + rtrPinArrayFixStems(ch->gcr_tPins, ch->gcr_length); + rtrPinArrayFixStems(ch->gcr_bPins, ch->gcr_length); + rtrPinArrayFixStems(ch->gcr_lPins, ch->gcr_width); + rtrPinArrayFixStems(ch->gcr_rPins, ch->gcr_width); +} + +int +rtrPinArrayFixStems(pins, nPins) + GCRPin *pins; + int nPins; +{ + GCRPin *pin, *lastPin; + + lastPin = &pins[nPins]; + for (pin = pins + 1; pin <= lastPin; pin++) + if (pin->gcr_pId + && pin->gcr_pId != GCR_BLOCKEDNETID + && pin->gcr_pSeg == GCR_STEMSEGID) + { + pin->gcr_pId = (GCRNet *) NULL; + } + return 0; +} diff --git a/router/rtrSide.c b/router/rtrSide.c new file mode 100644 index 00000000..deb36781 --- /dev/null +++ b/router/rtrSide.c @@ -0,0 +1,483 @@ +/* + * rtrSide.c - + * + * Contains procedures for enumerating the sides of groups of + * collinear cells. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrSide.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "utils/malloc.h" +#include "debug/debug.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "router/router.h" +#include "gcr/gcr.h" +#include "grouter/grouter.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "utils/signals.h" + +/* + * Local data used for communicating with filter functions. + * This procedure is non-reentrant because it needs to use a temporary + * plane for holding the transformed cell plane it uses for searching. + */ + + /* Transform information */ +int rtrSideSide; /* Which sides of cells are being visited */ +Transform rtrSideTrans; /* Transform from rtrSideTransDef back to + * the original cell plane. + */ + + /* Transformed coords */ +Rect rtrSideArea; /* Area being searched */ +CellDef *rtrSideTransDef = NULL;/* Holds a copy of original cell plane, but + * transformed so the direction of Side being + * processed is always GEO_EAST (the rhs). + */ +CellUse *rtrSideTransUse = NULL;/* Cell use for above */ +Plane *rtrSideTransPlane; /* Points to the cell plane of either the + * original def (if processing GEO_EAST + * sides), or of rtrSideTransDef if processing + * other sides. + */ + + /* Filter function */ +int (*rtrSideFunc)(); /* Function called for each Side found */ +ClientData rtrSideCdata; /* Passed to (*rtrSideFunc)() */ +int rtrSideMinChanWidth; /* See comments in rtrEnumSides() */ + +/* Forward declarations */ +int rtrEnumSidesFunc(); +int rtrSideInitClient(); +int rtrSideLookCellsFunc(); + +/* + * ---------------------------------------------------------------------------- + * + * rtrEnumSides -- + * + * Enumerate each colinear boundary between a cell and empty space + * in the cell 'def' that lies entirely within the area 'area'. + * Colinear boundaries occur when, for example, two vertically + * abutting cells share the same right-hand coordinate: + * + * +-------+ ^ + * | | | + * | A | | + * | | | + * +----+-------+ | colinear boundary + * | | | + * | B | | + * | | | + * +------------+ v + * + * The parameter minChannelWidth is a threshold on how much space + * must exist between a cell and its neighbors in order for us + * to enumerate a Side facing in a particular direction. It is + * interpreted as follows: + * + * --------+ | | +------- + * | | | | + * cell1 | A <----- minChannelWidth ----> B | cell2 + * | | | | + * --------+ | | +------- + * + * The line 'A' is the closest legal grid line to cell1, as is 'B' + * the closest legal grid line to cell2 (the nearest neighbor to cell1 + * along its RHS). If these are not at least minChannelWidth apart, + * don't enumerate the RHS of cell1. + * + * Applies the supplied function to each boundary found. This + * function should be of the following form: + * + * int + * (*func)(side, cdata) + * Side *side; + * ClientData cdata; + * { + * } + * + * The Side it is passed has side_trans set to the transform from the + * canonical orientation (where side appears to be on the RHS of a group + * of cells) to the original orientation. Side_line is set to a zero- + * width rectangle along the boundary being processed, in transformed + * coordinates. Also in transformed coordinates are side_search, set + * to a 1-unit wide rectangle along the boundary but extending in the + * direction of the cells' interiors, and side_used extending in the + * opposite direction from side_search to the nearest usable grid + * point. Side_next is set to NULL. + * + * The function should return 0 if we should continue enumerating + * Sides, or 1 if we should abort. + * + * Results: + * Returns 0 if we completed successfully, or 1 if (*func)() + * returned 1 or we were interrupted (SigInterruptPending != 0). + * + * Side effects: + * Whatever is done by the client procedure. + * We use the ti_client fields of the tiles in the cell tile + * plane for markings, and reset them to their uninitialized + * value when done (CLIENTDEFAULT). + * + * ---------------------------------------------------------------------------- + */ + +int +rtrEnumSides(use, area, minChannelWidth, func, cdata) + CellUse *use; /* Enumerate sides of use->cu_def */ + Rect *area; /* Only consider sides inside this area; + * this does not include sides along the + * border. + */ + int minChannelWidth; /* See above */ + int (*func)(); /* Applied to each Side found */ + ClientData cdata; /* Passed to (*func)() */ +{ + /* Create the yank buffer if it doesn't exist */ + if (rtrSideTransUse == NULL) + DBNewYank("__side_def__", &rtrSideTransUse, &rtrSideTransDef); + + /* Initialize stuff to pass to our clients */ + rtrSideMinChanWidth = minChannelWidth; + rtrSideFunc = func; + rtrSideCdata = cdata; + + /* + * Search each of four different directions for Sides. + * To make matters easy, we transform the original cell tile + * plane to make it always look as though we're searching for + * Sides on the RHS of cells. + */ + if (rtrSideProcess(use, GEO_EAST, area, &GeoIdentityTransform)) return 1; + if (rtrSideProcess(use, GEO_WEST, area, &GeoSidewaysTransform)) return 1; + if (rtrSideProcess(use, GEO_NORTH, area, &Geo270Transform)) return 1; + if (rtrSideProcess(use, GEO_SOUTH, area, &Geo90Transform)) return 1; + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrSideProcess -- + * + * Process all Sides that lie on 'side' of a cell (GEO_NORTH, + * GEO_SOUTH, etc). Does the real work of rtrEnumSides() + * above. + * + * The caller must initialize (*rtrSideFunc)(), rtrSideCdata, + * and rtrSideMinChanWidth before calling this procedure. + * + * Results: + * Returns 0 if we completed successfully, or 1 if (*func)() + * returned 1 or we were interrupted (SigInterruptPending != 0). + * + * Side effects: + * Whatever is done by the client procedure (*rtrSideFunc)() + * that was initialized by rtrEnumSides() above. We use the + * ti_client fields of the tiles in the cell tile plane for + * markings, and reset them to their uninitialized value when + * done (CLIENTDEFAULT). However, the cell plane of use->cu_def + * is only used when side == GEO_EAST; for other directions, + * the cell plane modified is that of rtrSideTransDef. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrSideProcess(use, side, area, trans) + CellUse *use; /* Enumerating Sides of use->cu_def */ + int side; /* Which sides (GEO_NORTH, etc) of cells to process */ + Rect *area; /* Find sides in this area (in use->cu_def coords) */ + Transform *trans; /* Transform from use->cu_def coords to those of the + * cell tile plane where we actually try to find Sides. + */ +{ + SearchContext scx; + int retval; + + rtrSideSide = side; + GeoInvertTrans(trans, &rtrSideTrans); + GeoTransRect(trans, area, &rtrSideArea); + switch (side) + { + /* EAST (easy case since we don't have to transform) */ + case GEO_EAST: + rtrSideTransPlane = use->cu_def->cd_planes[PL_CELL]; + break; + + /* Other cases use the transformed plane */ + case GEO_SOUTH: + case GEO_NORTH: + case GEO_WEST: + rtrSideTransPlane = rtrSideTransDef->cd_planes[PL_CELL]; + scx.scx_area = *area; + scx.scx_use = use; + scx.scx_trans = *trans; + DBCellClearDef(rtrSideTransDef); + DBCellCopyCells(&scx, rtrSideTransUse, (Rect *) NULL); + break; + } + + /* Initialize all client fields to NULL in the cell tile plane */ + (void) TiSrArea((Tile *) NULL, rtrSideTransPlane, &rtrSideArea, + rtrSideInitClient, (ClientData) INFINITY); + + /* Process all Sides for this direction */ + retval = TiSrArea((Tile *) NULL, rtrSideTransPlane, &rtrSideArea, + rtrEnumSidesFunc, (ClientData) NULL); + + /* Clean up; be absolutely sure to reset client info */ + if (side == GEO_EAST) + { + SigDisableInterrupts(); + (void) TiSrArea((Tile *) NULL, rtrSideTransPlane, area, + rtrSideInitClient, (ClientData) CLIENTDEFAULT); + SigEnableInterrupts(); + } + + return (retval); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrSideInitClient -- + * + * Called for each tile in the area over which Sides are being enumerated. + * Initializes ti_client for each tile to the value cdata. + * + * Results: + * Always returns 0. + * + * Side effects: + * Sets tile->ti_client. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrSideInitClient(tile, client) + Tile *tile; + ClientData client; +{ + tile->ti_client = client; + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrEnumSidesFunc -- + * + * Called for each tile during an area enumeration of the cell + * tile plane rtrSideTransPlane. + * + * Results: + * Returns 0 if we completed successfully, or 1 if (*func)() + * returned 1 or we were interrupted (SigInterruptPending != 0). + * + * Side effects: + * Whatever is done by the client procedure. + * We use the ti_client fields of the tiles in the cell tile + * plane for markings, and reset them to their uninitialized + * value when done (CLIENTDEFAULT). + * + * ---------------------------------------------------------------------------- + */ + +int +rtrEnumSidesFunc(tile) + Tile *tile; +{ + int ybot, ytop, yprev, sep, x, origin; + Tile *tp, *tpB; + Side side; + + /* Skip if already processed, out of the area, or not a cell tile */ + yprev = (int) tile->ti_client; + ybot = MAX(BOTTOM(tile), rtrSideArea.r_ybot); + if (yprev <= ybot || tile->ti_body == (ClientData) NULL + || RIGHT(tile) >= rtrSideArea.r_xtop) + return (0); + + switch (rtrSideSide) + { + case GEO_NORTH: + case GEO_SOUTH: + origin = RtrOrigin.p_y; + break; + case GEO_EAST: + case GEO_WEST: + origin = RtrOrigin.p_x; + break; + } + + /* + * Figure out the minimum width of space tiles we are willing to consider. + * This is to ensure that there's at least rtrSideMinChanWidth worth of + * usable channel space along this Side; if there isn't, we will terminate + * each Side as soon as we hit a space tile that's too narrow. + */ + x = RIGHT(tile); + if (rtrSideMinChanWidth >= 0) + { + switch (rtrSideSide) + { + case GEO_NORTH: + case GEO_EAST: + x = RTR_GRIDUP(x + RtrSubcellSepUp, origin); + x = RTR_GRIDUP(x + rtrSideMinChanWidth, origin) + + RtrSubcellSepDown; + break; + case GEO_SOUTH: + case GEO_WEST: + x = RTR_GRIDUP(x + RtrSubcellSepDown, origin); + x = RTR_GRIDUP(x + rtrSideMinChanWidth, origin) + + RtrSubcellSepUp; + break; + } + } + + /* + * Walk down the outside of the RHS as far as possible, + * first skipping all non-space tiles (or space tiles that + * are too narrow) and then stopping when we come to usable + * space or if the LHS of the outside tile changes from the + * previous one. + * + * Once we've found the biggest stretch formed by the + * space tiles on the RHS, we turn them into one or more + * Sides by looking at the cell tiles on the LHS. + */ + + /* + * Skip non-space tiles; give up if we leave the side + * of the original cell tile since we'll be certain to + * process the rest of the side when we see later tiles. + */ + yprev = MIN(yprev, rtrSideArea.r_ytop); + for (tp = TR(tile); + BOTTOM(tp) >= yprev || tp->ti_body || RIGHT(tp) < x; + tp = LB(tp)) + { + if (LEFT(tp) != RIGHT(tile) || TOP(tp) <= ybot) + { + /* Processed this tile completely */ + tile->ti_client = (ClientData) ybot; + return (0); + } + } + + /* + * Now tp is a usable space tile to the right of tile. + * Continue walking down to find the longest stretch + * of collinear space. + */ + ytop = MIN(TOP(tile), TOP(tp)); + ytop = MIN(ytop, yprev); + while (tp->ti_body == (ClientData) NULL && TOP(tp) > rtrSideArea.r_ybot + && LEFT(tp) == RIGHT(tile) + && RIGHT(tp) >= x) + { + tpB = tp; + tp = LB(tp); + } + ybot = MAX(BOTTOM(tpB), rtrSideArea.r_ybot); + + side.side_trans = rtrSideTrans; + side.side_side = rtrSideSide; + side.side_next = (Side *) NULL; + side.side_line.r_xbot = side.side_line.r_xtop = RIGHT(tile); + side.side_line.r_ybot = side.side_line.r_ytop = ybot; + side.side_search.r_xtop = RIGHT(tile); + side.side_search.r_xbot = RIGHT(tile) - 1; + side.side_used.r_xbot = RIGHT(tile); + sep = (rtrSideSide == GEO_NORTH || rtrSideSide == GEO_EAST) + ? RtrSubcellSepUp + : RtrSubcellSepDown; + side.side_used.r_xtop = RTR_GRIDUP(RIGHT(tile) + sep, origin); + + /* Walk back up the inside (LHS) of the edge just found */ + for (tp = BL(tpB); BOTTOM(tp) < ytop; tp = RT(tp)) + { + if (TOP(tp) > ybot) + { + if (tp->ti_body == (ClientData) NULL) + { + if (side.side_line.r_ytop > side.side_line.r_ybot) + if (rtrSidePassToClient(&side)) + return (1); + side.side_line.r_ybot = TOP(tp); + } + else + { + side.side_line.r_ytop = MIN(TOP(tp), ytop); + tp->ti_client = (ClientData) ybot; + } + } + } + + /* If the Side extended all the way to the top */ + if (side.side_line.r_ytop > side.side_line.r_ybot) + if (rtrSidePassToClient(&side)) + return (1); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrSidePassToClient -- + * + * Make side->side_search and side->side_used cover the same + * vertical span as side->side_line, and then call the client + * procedure (*rtrSideFunc)(). + * + * Results: + * Returns what the client procedure returned. + * + * Side effects: + * Whatever is done by the client procedure. + * See above for other effects. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrSidePassToClient(side) + Side *side; +{ + side->side_search.r_ybot = side->side_line.r_ybot; + side->side_search.r_ytop = side->side_line.r_ytop; + side->side_used.r_ybot = side->side_line.r_ybot; + side->side_used.r_ytop = side->side_line.r_ytop; + return ((*rtrSideFunc)(side, rtrSideCdata)); +} + diff --git a/router/rtrStem.c b/router/rtrStem.c new file mode 100644 index 00000000..106b8994 --- /dev/null +++ b/router/rtrStem.c @@ -0,0 +1,1314 @@ +/* + * rtrStem.c - + * + * This file contains procedures associated with stems. Stems + * are little pieces of paint used to make connections between + * non-grid-aligned terminals in cells and grid lines at the + * edges of channels. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrStem.c,v 1.2 2008/12/04 16:21:44 tim Exp $"; +#endif /* not lint */ + + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "router/router.h" +#include "gcr/gcr.h" +#include "utils/heap.h" +#include "grouter/grouter.h" +#include "utils/netlist.h" +#include "textio/textio.h" +#include "utils/main.h" +#include "utils/malloc.h" +#include "debug/debug.h" +#include "utils/signals.h" +#include "utils/maxrect.h" + +/* Used when searching for stems */ +typedef struct +{ + int stem_dist; /* Distance of nearest channel */ + int stem_dir; /* Direction from loc */ + Point stem_start; /* Best candidate stem tip point */ + int stem_lo, stem_hi; /* Range of stem points to consider + * (one coordinate will be the same + * as stem_start; the other will vary + * down to stem_lo and up to stem_hi). + */ +} StemInfo; + +static struct dirs /* List of directions for stems */ +{ + int dr_dir; /* Direction */ +} + dirs[] = { GEO_NORTH, GEO_SOUTH, GEO_EAST, GEO_WEST, 0 }; + +#define MAKEBOX(p, r, width, offset) { \ + (r)->r_xbot = (p)->p_x + (offset); \ + (r)->r_xtop = (r)->r_xbot + (width); \ + (r)->r_ybot = (p)->p_y + (offset); \ + (r)->r_ytop = (r)->r_ybot + (width);} + + +/* Forward declarations */ +extern GCRChannel *rtrStemSearch(); +extern GCRPin *rtrStemTip(); +extern GCRPin *rtrStemTryPin(); +extern void rtrStemRange(); + +bool rtrTreeSrArea(); +bool rtrSrArea(); +bool rtrStemMask(); +bool RtrComputeJogs(); + + +/* + * ---------------------------------------------------------------------------- + * + * RtrStemProcessAll -- + * + * Actually iterate over a netlist assigning crossing points. + * The real work is done by the caller-supplied procedure (*func)(), + * which should be of the following form: + * + * bool + * (*func)(use, doWarn, loc, term, net, netList) + * CellUse *use; + * bool doWarn; + * NLTermLoc *loc; + * NLTerm *term; + * NLNet *net; + * NLNetList *netList; + * { + * } + * + * It should return TRUE if it was possible to assign a stem tip + * to 'loc', or FALSE if no location was possible. It may also + * append new NLTermLocs to 'loc', with the last appended NLTermLoc + * pointing to loc->nloc_next. + * + * If the argument 'doWarn' to RtrStemProcessAll() is TRUE, then + * feedback is left for each NLTermLoc for a given NLTerm that cannot + * be assigned a stem tip; if doWarn is FALSE, then feedback is only + * left if ALL NLTermLocs for a NLTerm can't be assigned a stem tip. + * + * Results: + * None. + * + * Side effects: + * Whatever (*func)() does. + * Sets the nloc_stem, nloc_dir, nloc_chan fields + * for each NLTermLoc assigned a stem tip. When it isn't + * possible to assign any crossing points to a NLTermLoc, + * it is deleted from the list and we leave feedback. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrStemProcessAll(use, netList, doWarn, func) + CellUse *use; + NLNetList *netList; + bool doWarn; + bool (*func)(); +{ + NLTermLoc *loc, *locFirst, *locPrev, *locNext; + Rect errArea; + bool gotAny; + NLTerm *term; + NLNet *net; + + RtrMilestoneStart("Assigning stems"); + for (net = netList->nnl_nets; net; net = net->nnet_next) + { + for (term = net->nnet_terms; term; term = term->nterm_next) + { + /* + * First pass: walk through the list assigning stem tips to + * locations. Because (*func)() can append new NLTermLocs + * to 'loc', we remember loc->nloc_next BEFORE calling + * (*func)() so we only hit unassigned NLTermLocs in + * the list. + */ + gotAny = FALSE; + for (loc = term->nterm_locs; loc; loc = locNext) + { + if (SigInterruptPending) + goto out; + locNext = loc->nloc_next; + if ((*func)(use, doWarn, loc, term, net, netList)) + gotAny = TRUE; + } + + /* + * Go through the list nuking NLTermLocs for which no channel + * and crossing could be assigned (i.e, which were unusable). + * If we weren't generating feedback for each unusable location + * in the first pass, leave feedback here for all locations if + * they all turned out to be unusable. + */ + locPrev = locFirst = (NLTermLoc *) NULL; + for (loc = term->nterm_locs; loc; loc = loc->nloc_next) + { + if (loc->nloc_chan == (GCRChannel *) NULL) + { + if (!gotAny && !doWarn) + { + GEO_EXPAND(&loc->nloc_rect, 1, &errArea); + DBWFeedbackAdd(&errArea, + "No crossing reachable from terminal", + use->cu_def, 1, STYLE_PALEHIGHLIGHTS); + } + + /* Nuke it */ + if (locPrev) locPrev->nloc_next = loc->nloc_next; + freeMagic((char *) loc); + continue; + } + locPrev = loc; + if (locFirst == (NLTermLoc *) NULL) + locFirst = loc; + } + + /* Nuke any leading elements */ + term->nterm_locs = locFirst; + } + + RtrMilestonePrint(); + } + +out: + RtrMilestoneDone(); +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrStemAssignExt -- + * + * Assign a stem tip to a NLTermLoc 'loc' that lies outside of any + * routing channels. We do this by picking a direction from 'loc' + * in which a channel lies, and then assigning a stem tip on the + * boundary of that channel as the crossing point. + * + * Results: + * TRUE if the terminal is okay. + * + * Side effects: + * Sets loc->nloc_chan, loc->nloc_stem, and loc->nloc_dir. + * Marks the pin at the crossing point with 'net' and a + * segment-id of GCR_STEMSEGID. (This segment-id is recognized + * by the global router as an unrouted stem). + * + * Note: + * It is the responsibility of the caller to make sure that + * information about routing channels has been set up in + * RtrChannelPlane before this procedure is called. + * + * ---------------------------------------------------------------------------- + */ + +bool +RtrStemAssignExt(use, doWarn, loc, term, net) + CellUse *use; /* Cell being routed (for feedback) */ + bool doWarn; /* If TRUE, leave feedback for each bad loc */ + NLTermLoc *loc; /* Location being assigned */ + NLTerm *term; /* For nterm_name */ + NLNet *net; /* For marking pin */ +{ + TileType type = loc->nloc_label->lab_type; + int dirMask, termWidth, pins; + Rect r, errorArea; + char errorMesg[200]; + struct dirs *dr; + GCRPin *pin; + int rtrStemExpandFunc(); + + dirMask = 0; + + /* Compute initial range of directions we'll try */ + r = loc->nloc_rect; + termWidth = MAX(r.r_xtop - r.r_xbot, r.r_ytop - r.r_ybot); + + if (termWidth == 0) + { + /* Expand degenerate pins into the layers on which they're connected */ + int result; + Rect rdegen = r; + TileTypeBitMask lmask; + SearchContext scx; + + rdegen.r_xbot--; + rdegen.r_ybot--; + rdegen.r_xtop++; + rdegen.r_ytop++; + + scx.scx_use = use; + scx.scx_area = rdegen; + scx.scx_trans = GeoIdentityTransform; + + TTMaskSetOnlyType(&lmask, type); + result = DBTreeSrTiles(&scx, &lmask, 0, rtrStemExpandFunc, + (ClientData)&r); + + termWidth = MAX(r.r_xtop - r.r_xbot, r.r_ytop - r.r_ybot); + + if (result == 0 || termWidth == 0) + { + sprintf(errorMesg, "Terminal is degenerate"); + goto fail; + } + } + + /* + * Ensure that the terminal is at least wide enough and on + * a legal layer. + */ + termWidth = MAX(r.r_xtop - r.r_xbot, r.r_ytop - r.r_ybot); + if (TTMaskHasType(&DBConnectTbl[RtrMetalType], type)) + { + if (termWidth < RtrMetalWidth) + { + sprintf(errorMesg, "Terminal must be %d wide to connect to %s", + RtrMetalWidth, DBTypeLongName(RtrMetalType)); + goto fail; + } + if ( (r.r_xtop - r.r_xbot) >= RtrMetalWidth ) + dirMask |= (DIR_NORTH|DIR_SOUTH); + if ( (r.r_ytop - r.r_ybot) >= RtrMetalWidth ) + dirMask |= (DIR_EAST|DIR_WEST); + } + else if (TTMaskHasType(&DBConnectTbl[RtrPolyType], type)) + { + if (termWidth < RtrPolyWidth) + { + sprintf(errorMesg, "Terminal must be %d wide to connect to %s", + RtrMetalWidth, DBTypeLongName(RtrMetalType)); + goto fail; + } + if ( (r.r_xtop - r.r_xbot) >= RtrPolyWidth ) + dirMask |= (DIR_NORTH|DIR_SOUTH); + if ( (r.r_ytop - r.r_ybot) >= RtrPolyWidth ) + dirMask |= (DIR_EAST|DIR_WEST); + } + else if (RtrMazeStems) + { + /* Modified by Tim 7/27/06 --- */ + /* Try to find a contact type that connects to this type */ + /* for now, we just set type to be RtrPolyType. To be */ + /* done: mark this pin as requiring a contact, or draw */ + /* it here. */ + + type = RtrPolyType; + + if (termWidth < RtrPolyWidth) + { + sprintf(errorMesg, "Terminal must be %d wide to connect to %s", + RtrMetalWidth, DBTypeLongName(RtrMetalType)); + goto fail; + } + if ( (r.r_xtop - r.r_xbot) >= RtrPolyWidth ) + dirMask |= (DIR_NORTH|DIR_SOUTH); + if ( (r.r_ytop - r.r_ybot) >= RtrPolyWidth ) + dirMask |= (DIR_EAST|DIR_WEST); + + } + else + { + sprintf(errorMesg, "Can't have terminal on %s layer: must connect " + "to %s or %s (try setting mazestems option?)", + DBTypeLongName(type), + DBTypeLongName(RtrMetalType), + DBTypeLongName(RtrPolyType)); + goto fail; + } + + /* + * Overall algorithm: find the nearest channel in + * allowable directions and try to assign a stem tip + * in that direction. + */ + + pins = 0; + loc->nloc_chan == (GCRChannel *) NULL; + for ( dr = dirs; dr->dr_dir; dr++) + { + StemInfo si; + + /* + * Try in turn each direction. + */ + if ( DIRMASKHASDIR(dirMask, dr->dr_dir) ) + { + si.stem_dir = -1; + si.stem_dist = INFINITY; + rtrStemRange(loc, dr->dr_dir, &si); + if (si.stem_dir != -1) + { + if (pin = rtrStemTip(loc, &si, use)) + { + /* Mark the pin as taken */ + pins++; + pin->gcr_pId = (GCRNet *) net; + pin->gcr_pSeg = GCR_STEMSEGID; + } + } + } + } + + if (pins) + return (TRUE); + + /* Complain if no stem tip could be assigned */ + + (void) sprintf(errorMesg, "Can't find a channel in any direction from terminal"); + +fail: + if (doWarn) + { + GEO_EXPAND(&r, 1, &errorArea); + DBWFeedbackAdd(&errorArea, errorMesg, use->cu_def, + 1, STYLE_PALEHIGHLIGHTS); + } + return (FALSE); +} + +/* Routine to expand rectangle into touching tiles of a label's type. */ + +int +rtrStemExpandFunc(Tile *t, TreeContext *cxp) +{ + SearchContext *scx = cxp->tc_scx; + Rect rsrc; + Rect *r = (Rect *)cxp->tc_filter->tf_arg; + CellDef *def = scx->scx_use->cu_def; + Rect *rtest; + TileType ttype; + Point p; + + TiToRect(t, &rsrc); + ttype = TiGetType(t); + + p.p_x = (rsrc.r_xtop + rsrc.r_xbot) / 2; + p.p_y = (rsrc.r_ytop + rsrc.r_ybot) / 2; + + rtest = FindMaxRectangle(&TiPlaneRect, def->cd_planes[cxp->tc_plane], &p, + &DBConnectTbl[ttype]); + if (rtest) + { + GeoTransRect(&scx->scx_trans, rtest, r); /* Copy the final rectangle */ + return 1; + } + else + return 0; /* Probably should report an error and stop */ +} + + +/* + * ---------------------------------------------------------------------------- + * + * rtrStemTip -- + * + * Given a terminal, this procedure finds the channel crossing point + * to which its stem will extend. Ensures that the pin at that grid + * point isn't blocked, and hasn't already been assigned to another + * terminal. + * + * Results: + * Returns a pointer to the pin at the crossing if successful, + * or NULL on a failure. + * + * Side effects: + * Fills in loc->nloc_stem, loc->nloc_dir, and loc->nloc_chan + * with the location of a channel crossing point, the direction to + * reach it, and the channel containing it respectively. The + * crossing point is the nearest place where a grid-line crosses + * into a channel. One, but probably not both, of the point's + * coordinates will be grid-aligned. If FALSE is returned, then + * point is not defined. Rectangular labels and those inside cells + * are handled by searching outward for the nearest channel boundary. + * + * The value of loc_dir is a direction, or -1. For example, GEO_NORTH + * means that the stem runs northward (the terminal is on the top + * of a cell). A value of -1 means that something was wrong with + * the terminal (not on a routable layer, too small, wrong shape, + * etc.) + * + * ---------------------------------------------------------------------------- + */ + +GCRPin * +rtrStemTip(loc, si, use) + NLTermLoc *loc; /* Location whose stem tip is being found */ + StemInfo *si; /* Stem information */ + CellUse *use; +{ + Point plo, phi; + int *lo, *hi; + GCRPin *pin; + + /* + * Try each crossing point in the best direction, starting from the + * stem_start point and working outward toward stem_lo and stem_hi. + */ + if (pin = rtrStemTryPin(loc, si->stem_dir, &si->stem_start, use)) + return (pin); + + plo = phi = si->stem_start; + switch (si->stem_dir) + { + case GEO_NORTH: case GEO_SOUTH: lo = &plo.p_x; hi = &phi.p_x; break; + case GEO_EAST: case GEO_WEST: lo = &plo.p_y; hi = &phi.p_y; break; + } + + for ( ; *lo >= si->stem_lo || *hi <= si->stem_hi; + *lo -= RtrGridSpacing, *hi += RtrGridSpacing) + { + if (*lo >= si->stem_lo && + (pin = rtrStemTryPin(loc, si->stem_dir, &plo, use))) + return (pin); + if (*hi >= si->stem_hi && + (pin = rtrStemTryPin(loc, si->stem_dir, &phi, use))) + return (pin); + } + return ((GCRPin *) NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrAbort -- + * DBTreeSrTile function. Called to abort tile search + * if a tile is found in the stem bounding box. + * + * Results: + * Always returns 1 to abort DBTreeSrTiles. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrAbort(tile) + Tile *tile; +{ + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrStemTryPin -- + * + * Check to see if a particular crossing point is available. If it is, + * assign it to loc. + * + * Results: + * Returns a pointer to the GCRPin for the crossing if successful, + * or NULL on failure. + * + * Side effects: + * Fills in loc->nloc_stem, loc->nloc_dir, and loc->nloc_chan + * with the location of a channel crossing point, the direction to + * reach it, and the channel containing it respectively. + * + * ---------------------------------------------------------------------------- + */ + +GCRPin * +rtrStemTryPin(loc, dir, p, use) + NLTermLoc *loc; /* Try to assign the GCRPin for p to this loc */ + int dir; /* Direction away from loc that p lies */ + Point *p; /* Crossing point to try */ + CellUse *use; +{ + Point pSearch; + GCRChannel *ch; + GCRPin *pin; + Tile *tp; + + pSearch = *p; + if (dir == GEO_SOUTH) pSearch.p_y--; + if (dir == GEO_WEST) pSearch.p_x--; + + /* Make sure there's a channel there */ + tp = TiSrPointNoHint(RtrChannelPlane, &pSearch); + if (TiGetType(tp) != TT_SPACE) + return ((GCRPin *) NULL); + ch = (GCRChannel *) tp->ti_client; + if (ch == (GCRChannel *) NULL || ch->gcr_type != CHAN_NORMAL) + return ((GCRPin *) NULL); + + /* + * Ensure that the pin is on the proper channel boundary. + * Remember, dir is the direction in which 'ch' lies from 'loc', + * so the actual SIDE of 'ch' we want to compare with 'p' is + * opposite from the direction (e.g, dir == GEO_NORTH means + * look at the TOP of ch). + */ + switch (dir) + { + case GEO_NORTH: + if (p->p_y != ch->gcr_area.r_ybot) return ((GCRPin *) NULL); + break; + case GEO_SOUTH: + if (p->p_y != ch->gcr_area.r_ytop) return ((GCRPin *) NULL); + break; + case GEO_EAST: + if (p->p_x != ch->gcr_area.r_xbot) return ((GCRPin *) NULL); + break; + case GEO_WEST: + if (p->p_x != ch->gcr_area.r_xtop) return ((GCRPin *) NULL); + break; + } + + /* Find the pin for the crossing */ + pin = RtrPointToPin(ch, GeoOppositePos[dir], p); + if (pin == (GCRPin *) NULL || pin->gcr_pId) + return ((GCRPin *) NULL); + ASSERT(pin->gcr_point.p_x == p->p_x, "rtrStemTryPin"); + ASSERT(pin->gcr_point.p_y == p->p_y, "rtrStemTryPin"); + + /* + * Verify stem extending to channel will not overlap + * material in the edit cell or nested subcells. + */ + + if ( rtrTreeSrArea(loc, dir, p, use) ) + return (GCRPin *) NULL; + + /* + * Assign crossing to loc. + * If a previous loc has been assigned, + * allocate a new location for the terminal and link into list. + */ + + if ( loc->nloc_chan ) + { + NLTermLoc *nloc; + + nloc = (NLTermLoc *) mallocMagic((unsigned) (sizeof (NLTermLoc))); + *nloc = *loc; + loc->nloc_next = nloc; + loc = nloc; + } + + loc->nloc_stem = *p; + loc->nloc_dir = dir; + loc->nloc_chan = ch; + loc->nloc_pin = pin; + return (pin); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrTreeSrArea -- + * Search edit cell and nested subcells + * for material which might short or cause design rule constraints + * with a generated stem. + * The checking is primitive and just looks for tiles in + * the area of the stem bounding box using upper limits for + * tile separations. + * + * Results: + * Returns TRUE if conflicting material is present. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +rtrTreeSrArea(loc, dir, p, use) + NLTermLoc *loc; /* Terminal location under consideration */ + int dir; /* Direction away from loc that p lies */ + Point *p; /* Point at channel boundary */ + CellUse *use; /* Parent cell use */ +{ + Rect tmp, tmp1, tmp2; + Point contact, jog, start; + int i, width = MAX(RtrMetalWidth, RtrPolyWidth); + int delta; + + /* + * Compute intersection points for a jogged stem. + */ + RtrComputeJogs(loc, p, dir, &contact, &jog, &start, width); + + /* + * Compute maximum separation. + */ + delta = 0; + for ( i = 0; i < TT_MAXTYPES; i++) + { + delta = MAX(delta,RtrMetalSeps[i]); + delta = MAX(delta,RtrPolySeps[i]); + } + + /* + * Compute bounding boxes for stem sgements and check each area. + */ + MAKEBOX(&start, &tmp1, width, 0); + MAKEBOX(&jog, &tmp, width, 0); + GeoInclude(&tmp1, &tmp); + if ( rtrSrArea(dir,use, &tmp,delta) ) + return TRUE; + + MAKEBOX(&jog, &tmp1, width, 0); + MAKEBOX(&contact, &tmp, width, 0); + GeoInclude(&tmp1, &tmp); + if ( rtrSrArea(dir,use, &tmp,delta) ) + return TRUE; + + MAKEBOX(&contact, &tmp1, width, 0); + MAKEBOX(p, &tmp, width, 0); + GeoInclude(&tmp1, &tmp); + if ( rtrSrArea(dir,use, &tmp,delta) ) + return TRUE; + + /* + * If debug, display stem bounding box as feedback. + */ + + if (DebugIsSet(glDebugID, glDebStemsOnly)) + { + char errorMesg[256]; + + MAKEBOX(&start, &tmp1, width, 0); + MAKEBOX(p, &tmp, width, 0); + GeoInclude(&tmp1, &tmp); + sprintf(errorMesg, + "Stem tip for terminal %s", loc->nloc_term->nterm_name); + DBWFeedbackAdd(&tmp, errorMesg, use->cu_def, + 1, STYLE_PALEHIGHLIGHTS); + } + + return FALSE; +} + +bool +rtrSrArea(dir,use,tmp,delta) + int dir; + CellUse *use; + Rect *tmp; + int delta; +{ + SearchContext scx; + TileTypeBitMask r1mask, r2mask; + + /* + * Expand box in appropriate direction. + */ + switch ( dir ) + { + case GEO_NORTH: + tmp->r_xbot -= delta; + tmp->r_xtop += delta; + tmp->r_ytop += delta; + break; + case GEO_SOUTH: + tmp->r_xbot -= delta; + tmp->r_xtop += delta; + tmp->r_ybot -= delta; + break; + case GEO_EAST: + tmp->r_ytop += delta; + tmp->r_ybot -= delta; + tmp->r_xtop += delta; + break; + case GEO_WEST: + tmp->r_ytop += delta; + tmp->r_ybot -= delta; + tmp->r_xbot -= delta; + break; + } + + /* + * Search edit cell and nested subcells for tiles. + */ + scx.scx_use = use; + scx.scx_area = *tmp; + scx.scx_trans = GeoIdentityTransform; + + /* Modified by Tim 7/27/06--- + * + * Search ONLY those planes containing route materials types 1 and 2. + * If either plane (or both) is free of material, we can create a + * stem. Only do this if we have chosen to maze route the stem. The + * standard stem generator doesn't know how to contact an internal + * pin from a different plane. + */ + + if (RtrMazeStems) + { + + TTMaskClearMask3(&r1mask, &DBPlaneTypes[DBPlane(RtrPolyType)], &DBSpaceBits); + TTMaskClearMask3(&r2mask, &DBPlaneTypes[DBPlane(RtrMetalType)], &DBSpaceBits); + + if (DBTreeSrTiles(&scx, &r1mask, 0, rtrAbort, (ClientData)0) == 0) + return FALSE; + + if (DBTreeSrTiles(&scx, &r2mask, 0, rtrAbort, (ClientData)0) == 0) + return FALSE; + + return TRUE; /* Can't create stem---both planes blocked */ + } + else /* Traditional behavior */ + { + if (DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, rtrAbort, (ClientData)0) ) + return TRUE; + return FALSE; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrStemRange -- + * + * Search outward from 'loc' in direction 'dir' for the nearest space tile + * that lies inside the routing area. If one is found, and it's closer + * than si->stem_dist, set the following information in *si: + * + * stem_dist distance to the new channel + * stem_dir dir + * stem_start the closest crossing point on the boundary of + * the space tile we just found. + * stem_lo, + * stem_hi the range of crossing points to consider; + * chosen to extend a certain number of grid + * lines to either side of the terminal. + * + * Results: + * None. + * + * Side effects: + * May modify *si as described above. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrStemRange(loc, dir, si) + NLTermLoc *loc; /* Terminal we're trying to find a stem for */ + int dir; /* Direction away from loc that we're searching */ + StemInfo *si; /* Fill this in if this direction looks best so far */ +{ + Rect *area = &loc->nloc_rect; + Point start, near, center; + int dist, halfGrid; + GCRChannel *ch; + + /* + * Pick the X or Y grid lines such that a contact on that grid line + * will have its center closest to the center of the terminal. + * (One of these values will determine the grid line on which + * the stem tip lies; the other coordinate of the stem tip will + * be that of the channel boundary, determined below). + */ + center.p_x = rtrStemContactLine(area->r_xbot, area->r_xtop, RtrOrigin.p_x); + center.p_y = rtrStemContactLine(area->r_ybot, area->r_ytop, RtrOrigin.p_y); + + /* Search outward in 'dir' for the nearest channel */ + ch = rtrStemSearch(¢er, dir, &start); + if (ch == (GCRChannel *) NULL) + return; + + /* Find the nearest point of 'area' to 'start' */ + near = start; + GeoClipPoint(&near, area); + + /* + * If the distance between near and start is less than for + * previously visited crossings, remember this side in 'si'. + */ + dist = ABSDIFF(near.p_x, start.p_x) + ABSDIFF(near.p_y, start.p_y); + + si->stem_dir = dir; + si->stem_dist = dist; + si->stem_start = start; + + /* Set the range of grid lines that we will visit */ + halfGrid = RtrGridSpacing/2; + switch (dir) + { + case GEO_NORTH: + case GEO_SOUTH: + si->stem_lo = RTR_GRIDUP(area->r_xbot - halfGrid, + RtrOrigin.p_x); + si->stem_hi = RTR_GRIDDOWN(area->r_xtop + halfGrid, + RtrOrigin.p_x); + break; + case GEO_EAST: + case GEO_WEST: + si->stem_lo = RTR_GRIDUP(area->r_ybot - halfGrid, + RtrOrigin.p_y); + si->stem_hi = RTR_GRIDDOWN(area->r_ytop + halfGrid, + RtrOrigin.p_y); + break; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrStemContactLine -- + * + * Pick the X or Y grid lines such that a contact on that grid line + * will have its center closest to the center of the terminal. + * + * Results: + * Returns the grid line described above. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrStemContactLine(lo, hi, origin) + int lo, hi; /* Bottom and top, or left and right of terminal */ + int origin; /* Coordinate of routing grid origin */ +{ + int center; + + /* + * The following code is tricky because we want to round DOWN always + * in the division by 2, and C rounds towards zero. + */ + center = lo + hi + RtrGridSpacing - RtrContactWidth; + if (center < 0) center -= 1; + center = RTR_GRIDDOWN(center / 2 + RtrContactOffset, origin); + + return (center); +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrStemSearch -- + * + * Search outward in direction 'dir' from the Point 'center' for + * a channel inside the routing area. If one is found, set + * *point to the crossing on the boundary of that channel that + * is grid-aligned with 'center'. + * + * Results: + * Returns the channel found, or NULL if none could be found. + * + * Side effects: + * Modifies *point. + * + * ---------------------------------------------------------------------------- + */ + +GCRChannel * +rtrStemSearch(center, dir, point) + Point *center; + int dir; + Point *point; +{ + Tile *tile; + GCRChannel *ch; + + *point = *center; + for (;;) + { + if (!GEO_ENCLOSE(point, &RouteArea)) + return ((GCRChannel *) NULL); + tile = TiSrPointNoHint(RtrChannelPlane, point); + if (TiGetType(tile) == TT_SPACE) + { + if (ch = (GCRChannel *) tile->ti_client) + break; + return ((GCRChannel *) NULL); + } + switch (dir) + { + case GEO_NORTH: point->p_y = TOP(tile); break; + case GEO_SOUTH: point->p_y = BOTTOM(tile) - 1; break; + case GEO_EAST: point->p_x = RIGHT(tile); break; + case GEO_WEST: point->p_x = LEFT(tile) - 1; break; + } + + } + + /* Pick a crossing point on the channel boundary */ + switch (dir) + { + case GEO_NORTH: point->p_y = ch->gcr_area.r_ybot; break; + case GEO_SOUTH: point->p_y = ch->gcr_area.r_ytop; break; + case GEO_EAST: point->p_x = ch->gcr_area.r_xbot; break; + case GEO_WEST: point->p_x = ch->gcr_area.r_xtop; break; + } + + return (ch); +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrStemPaintExt -- + * + * This procedure places paint in the cell 'use->cu_def' to wire up a stem. + * The location of the stem has been pre-determined when the + * NLNetList was built; all we do is implement this decision. + * + * Results: + * TRUE is returned if the stem was wired successfully. FALSE + * is returned if there was something wrong with the terminal + * that prevented a stem from being created. This includes + * the case where no routing material was present at the + * stem target location, as might result when the stem was + * not used by the global router. + * + * Side effects: + * Paint is added to cell 'use->cu_def'. This procedure actually does + * two things. First, it routes the terminal out to a point where + * the router can connect to it. Second, it adds a contact along + * the way if one is needed to change layers to the routing material + * at the tip of the stem. Note: this procedure must not be called + * until AFTER the routing paint has been placed, since it uses + * the type of routing paint to determine whether or not to place + * a contact. If there's no routing paint, then it doesn't wire + * a stem at all. + * + * Leaves feedback if there was an error. + * + * ---------------------------------------------------------------------------- + */ + +bool +RtrStemPaintExt(use, loc) + CellUse *use; + NLTermLoc *loc; /* Terminal whose stem is to be painted */ +{ + TileTypeBitMask startMask; /* Possible layers for first part of stem */ + TileTypeBitMask finalMask; /* Possible layers for last part of stem */ + TileType startType; /* Layer actually chosen for start */ + TileType finalType; /* Layer actually chosen for end */ + Point start; /* Somewhere along terminal area */ + Point jog; /* Where the stem crosses the first usable + * grid line as it runs out from the cell. + */ + Point contact; /* A second grid point, where a contact can + * be placed if necessary. This is a the + * nearest grid crossing to crossing outside + * the channel. + */ + Rect tmp, paintArea, feedback; + char *reason, buf[256]; + GCRPin *pin; + short flags; + int width; + + /* + * Find the pin in the channel adjacent to loc to which this + * stem is being routed. If this pin wasn't used, there's no + * point in routing a stem to it so we return. + */ + pin = loc->nloc_pin; + if (pin->gcr_pId == (GCRNet *) NULL) + return (TRUE); + + /* Use crossing already computed */ + if (loc->nloc_dir < 0) + { + reason = "Couldn't find crossing point for stem"; + goto failure; + } + + /* Figure out what kind of material the stem must connect to */ + flags = pin->gcr_ch->gcr_result[pin->gcr_x][pin->gcr_y]; + if (!rtrStemMask(use, loc, flags, &startMask, &finalMask)) + { + reason = "Terminal is not on a legal routing layer"; + goto failure; + } + + /* Don't complain if no routing material is present */ + if (!TTMaskHasType(&finalMask, RtrMetalType) + && !TTMaskHasType(&finalMask, RtrPolyType)) + return (FALSE); + + rtrStemTypes(&startMask, &finalMask, &startType, &finalType); + + width = (startType == RtrPolyType) ? RtrPolyWidth : RtrMetalWidth; + + /* + * Compute jog points. + */ + + if ( RtrComputeJogs(loc, &loc->nloc_stem, loc->nloc_dir, + &contact, &jog, &start, width) ) + { + (void) sprintf(buf, + "Internal error: bad direction (%d) loc->nloc_dir", + loc->nloc_dir); + reason = buf; + goto failure; + } + + /* Now just connect the dots! */ + + /* The first segment runs from the terminal out towards the channel */ + MAKEBOX(&start, &tmp, width, 0); + MAKEBOX(&jog, &paintArea, width, 0); + (void) GeoInclude(&tmp, &paintArea); + RtrPaintStats(startType, start.p_x-jog.p_x+start.p_y-jog.p_y); + DBPaint(use->cu_def, &paintArea, startType); + + /* + * For the second segment (over to the contact position), be careful. + * If there's going to be a contact, widen this segment so there can't + * be any design-rule-violating slivers left between the segment above + * and the contact. Also place the contact. + */ + MAKEBOX(&jog, &tmp, width, 0); + if (startType != finalType) + { + MAKEBOX(&contact, &paintArea, RtrContactWidth, RtrContactOffset); + RtrPaintContact(use->cu_def, &paintArea); + } + else MAKEBOX(&contact, &paintArea, width, 0); + (void) GeoInclude(&tmp, &paintArea); + RtrPaintStats(startType, jog.p_x-contact.p_x+jog.p_y-contact.p_y); + DBPaint(use->cu_def, &paintArea, startType); + + /* Figure out what type to enter the channel with */ + width = (finalType == RtrMetalType) ? RtrMetalWidth : RtrPolyWidth; + + /* Make the last run down to the channel */ + MAKEBOX(&contact, &tmp, width, 0); + MAKEBOX(&loc->nloc_stem, &paintArea, width, 0); + (void) GeoInclude(&tmp, &paintArea); + RtrPaintStats(finalType, + contact.p_x-loc->nloc_stem.p_x+contact.p_y-loc->nloc_stem.p_y); + DBPaint(use->cu_def, &paintArea, finalType); + return (TRUE); + +failure: + GEO_EXPAND(&loc->nloc_rect, 1, &feedback); + DBWFeedbackAdd(&feedback, reason, use->cu_def, 1, STYLE_PALEHIGHLIGHTS); + return (FALSE); +} + +/* + * Figure out what kind of material the stem must connect to. + * If BOTH routing layers are present at the stem tip, select the + * vertical or horizontal layer, depending on the direction of + * the stem. If there's a contact out there, then either layer + * is OK. + */ + +bool +rtrStemMask(routeUse, loc, flags, startMask, finalMask) + CellUse *routeUse; /* Cell being routed */ + NLTermLoc *loc; /* Terminal */ + int flags; /* Blockage flags in the channel at the + * crossing point. If a layer is marked + * as blocked in these flags, it is excluded + * from finalMask since the channel router + * will not have used it for routing a + * signal. + */ + TileTypeBitMask *startMask; /* Possible types for terminal */ + TileTypeBitMask *finalMask; /* Possible types for stem tip */ +{ + Rect tmp; + + /* + * Figure out what kind of material the stem must connect to. + * If BOTH routing layers are present at the stem tip, select the + * vertical or horizontal layer, depending on the direction of + * the stem. If there's a contact out there, then either layer + * is OK. + */ + tmp.r_xbot = loc->nloc_stem.p_x - 1; + tmp.r_xtop = loc->nloc_stem.p_x + 1; + tmp.r_ybot = loc->nloc_stem.p_y - 1; + tmp.r_ytop = loc->nloc_stem.p_y + 1; + DBSeeTypesAll(routeUse, &tmp, 0, finalMask); + if (TTMaskHasType(finalMask, RtrMetalType) && + TTMaskHasType(finalMask, RtrPolyType)) + { + if (loc->nloc_dir == GEO_NORTH || loc->nloc_dir == GEO_SOUTH) + TTMaskClearType(finalMask, RtrMetalType); + else TTMaskClearType(finalMask, RtrPolyType); + } + if (flags & GCRBLKM) TTMaskClearType(finalMask, RtrMetalType); + if (flags & GCRBLKP) TTMaskClearType(finalMask, RtrPolyType); + + if (TTMaskHasType(finalMask, RtrContactType)) + { + TTMaskSetType(finalMask, RtrMetalType); + TTMaskSetType(finalMask, RtrPolyType); + } + + /* Now figure out what kind of material we'll be using for the + * first and last parts of the stem. Use the same material in + * both places if possible. + */ + *startMask = DBConnectTbl[loc->nloc_label->lab_type]; + if (!TTMaskHasType(startMask, RtrMetalType) + && !TTMaskHasType(startMask, RtrPolyType)) + { + return (FALSE); + } + + return (TRUE); +} + +int +rtrStemTypes(startMask, finalMask, startType, finalType) + TileTypeBitMask *startMask, *finalMask; + TileType *startType, *finalType; +{ + if (!TTMaskHasType(finalMask, RtrMetalType)) + { + *finalType = RtrPolyType; + if (TTMaskHasType(startMask, RtrPolyType)) + *startType = RtrPolyType; + else *startType = RtrMetalType; + } + else if (!TTMaskHasType(finalMask, RtrPolyType)) + { + *finalType = RtrMetalType; + if (TTMaskHasType(startMask, RtrMetalType)) + *startType = RtrMetalType; + else *startType = RtrPolyType; + } + else + { + /* Both types are present in the channel; either will do */ + if (TTMaskHasType(startMask, RtrMetalType)) + *startType = *finalType = RtrMetalType; + else *startType = *finalType = RtrPolyType; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrComputeJogs -- + * Compute points defining the jog required to connect a + * terminal to a grid line in an adjacent channel. + * This can be used to determine the stem bounding box + * or to actually paint the stem. + * + * Results: + * TRUE on success, FALSE on failure. + * + * Side effects: + * Returns contact, jog, and start points, passed via pointer. + * + * ---------------------------------------------------------------------------- + */ + +bool +RtrComputeJogs(loc, stem, dir, contact, jog, start, width) + NLTermLoc *loc; /* Terminal whose stem is to be painted */ + Point *stem; /* Point intersecting channel*/ + Point *start; /* Somewhere along terminal area */ + Point *jog; /* Where the stem crosses the first usable + * grid line as it runs out from the cell. + */ + Point *contact; /* A second grid point, where a contact can + * be placed if necessary. This is a the + * nearest grid crossing to crossing outside + * the channel. + */ +{ + Rect *area; + area = &loc->nloc_rect; + + /* In the following code, we compute two jog points in the stem. + * The stem will run out from the terminal to the first usable + * grid line, then jog over to a grid line in the other direction, + * then jog down to the channel boundary. The second jog is called + * the contact point, since we change layers here if that is + * necessary. + */ + switch (dir) + { + case GEO_NORTH: + contact->p_y = RTR_GRIDDOWN(stem->p_y, RtrOrigin.p_y); + contact->p_x = stem->p_x; + *jog = *contact; + if (jog->p_x < area->r_xbot) + jog->p_x = area->r_xbot; + else if (jog->p_x > (area->r_xtop - width)) + jog->p_x = area->r_xtop - width; + start->p_x = jog->p_x; + start->p_y = area->r_ytop; + break; + + case GEO_SOUTH: + contact->p_y = RTR_GRIDUP(stem->p_y, RtrOrigin.p_y); + contact->p_x = stem->p_x; + *jog = *contact; + if (jog->p_x < area->r_xbot) + jog->p_x = area->r_xbot; + else if (jog->p_x > (area->r_xtop - width)) + jog->p_x = area->r_xtop - width; + start->p_x = jog->p_x; + start->p_y = area->r_ybot - width; + break; + + case GEO_EAST: + contact->p_x = RTR_GRIDDOWN(stem->p_x, RtrOrigin.p_x); + contact->p_y = stem->p_y; + *jog = *contact; + if (jog->p_y < area->r_ybot) + jog->p_y = area->r_ybot; + else if (jog->p_y > (area->r_ytop - width)) + jog->p_y = area->r_ytop - width; + start->p_y = jog->p_y; + start->p_x = area->r_xtop; + break; + + case GEO_WEST: + contact->p_x = RTR_GRIDUP(stem->p_x, RtrOrigin.p_x); + contact->p_y = stem->p_y; + *jog = *contact; + if (jog->p_y < area->r_ybot) + jog->p_y = area->r_ybot; + else if (jog->p_y > (area->r_ytop - width)) + jog->p_y = area->r_ytop - width; + start->p_y = jog->p_y; + start->p_x = area->r_xbot - width; + break; + + default: + return TRUE; + } + return FALSE; +} diff --git a/router/rtrTech.c b/router/rtrTech.c new file mode 100644 index 00000000..724ce297 --- /dev/null +++ b/router/rtrTech.c @@ -0,0 +1,445 @@ +/* rtrTech.c - + * + * This file processes the part of technology files that + * provides information to the router. It sets up information + * giving, for example, the layers to use for routing, their + * widths, and so on. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrTech.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/utils.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/tech.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "router/router.h" + +/* The global routing variables are defined below. See router.h + * for a description of what they mean. + */ + +/* These are used by non-router modules (maybe they shouldn't be?) so */ +/* they are defined in dbwind/DBWdisplay.c, one of the places where */ +/* they are used. */ + +/* int RtrMetalWidth, RtrPolyWidth, RtrContactWidth; */ + +TileType RtrMetalType, RtrPolyType, RtrContactType; +int RtrContactOffset; +int RtrMetalSurround, RtrPolySurround; +int RtrGridSpacing; +int RtrSubcellSepUp, RtrSubcellSepDown; +TileTypeBitMask RtrMetalObstacles, RtrPolyObstacles; +int RtrPaintSepsUp[TT_MAXTYPES], RtrPaintSepsDown[TT_MAXTYPES]; + +/* The arrays below are used to hold the obstacle information separately + * for the two routing layers. These are used temporarily while reading + * the technology file, but also used directly by the maze router. Eventually + * the info is combined and put into RtrPaintSepsUp and RtrPaintSepsDown. + */ + +int RtrMetalSeps[TT_MAXTYPES], RtrPolySeps[TT_MAXTYPES]; + + +/* + * ---------------------------------------------------------------------------- + * + * RtrTechInit -- + * + * This routine is called once just before reading the router + * section of the technology file. + * + * Results: + * None. + * + * Side effects: + * Initializes the data structures. The main idea is to make + * things consistent so that if there is an empty router section, + * the router won't crash if it's invoked (it probably won't + * generate nice routing, but at least it won't core dump). + * + * ---------------------------------------------------------------------------- + */ + +void +RtrTechInit() +{ + int i; + RtrMetalType = RtrPolyType = RtrContactType = TT_SPACE; + RtrMetalWidth = RtrPolyWidth = RtrContactWidth = 2; + RtrContactOffset = 0; + RtrMetalSurround = 0; + RtrPolySurround = 0; + RtrGridSpacing = 4; + RtrSubcellSepUp = 4; + RtrSubcellSepDown = 4; + TTMaskZero(&RtrMetalObstacles); + TTMaskZero(&RtrPolyObstacles); + for (i=0; i= 0) RtrMetalType = type; + width = atoi(argv[2]); + if (width <= 0) + TechError("Layer1 width must be positive; %d is illegal.\n", + width); + else RtrMetalWidth = width; + TTMaskZero(&RtrMetalObstacles); + argc -= 3; + nextArg = &(argv[3]); + while (argc >= 2) + { + DBTechNoisyNameMask(*nextArg, &mask); + distance = atoi(nextArg[1]); + if (distance < 0) + { + TechError("Layer1 obstacle separation must be positive; %d is illegal.\n", + distance); + } + else for (i=0; i= 0) RtrPolyType = type; + width = atoi(argv[2]); + if (width <= 0) + TechError("Layer2 width must be positive; %d is illegal.\n", + width); + else RtrPolyWidth = width; + TTMaskZero(&RtrPolyObstacles); + argc -= 3; + nextArg = &(argv[3]); + while (argc >= 2) + { + DBTechNoisyNameMask(*nextArg, &mask); + distance = atoi(nextArg[1]); + if (distance < 0) + { + TechError("Layer2 obstacle separation must be positive: %d is illegal.\n", + distance); + } + else for (i=0; i= 0) RtrContactType = type; + width = atoi(argv[2]); + if (width <= 0) + TechError("Contact width must be positive; %d is illegal.\n", + width); + else RtrContactWidth = width; + RtrContactOffset = 0; + if (argc == 5) + { + if (!StrIsInt(argv[3])) + TechError("Metal contact surround \"%s\" isn't integral.\n", + argv[3]); + else + { + RtrMetalSurround = atoi(argv[3]); + if (RtrMetalSurround < 0) + { + TechError("Metal contact surround \"%s\" mustn't be negative.\n", argv[3]); + RtrMetalSurround = 0; + } + } + if (!StrIsInt(argv[4])) + TechError("Poly contact surround \"%s\" isn't integral.\n", + argv[4]); + else + { + RtrPolySurround = atoi(argv[4]); + if (RtrPolySurround < 0) + { + TechError("Poly contact surround \"%s\" mustn't be negative.\n", argv[4]); + RtrPolySurround = 0; + } + } + } + return TRUE; + } + + /* Next, look for a gridspacing line. */ + + if (strcmp(argv[0], "gridspacing") == 0) + { + if (argc != 2) goto wrongNumArgs; + i = atoi(argv[1]); + if (i <= 0) + TechError("Gridspacing must be positive; %d is illegal.\n", i); + else RtrGridSpacing = i; + return TRUE; + } + + TechError("Unknown router statement \"%s\".\n", argv[0]); + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrTechFinal -- + * + * Called once at the very end of the router section of the technology + * file. + * + * Results: + * None. + * + * Side effects: + * Compute the actual subcell and paint separations, based on + * the technology file information. + * + * ---------------------------------------------------------------------------- + */ + +void +RtrTechFinal() +{ + int i, above, below; + + /* Pick a contact offset so that the contacts are more-or-less + * centered on the routing material. Use the wider routing material + * to make this decision; otherwise, the material might end up + * sticking out past the edge of the contact. When rounding, round + * down (since this works better if the two routing layers are different + * widths). + */ + + i = RtrMetalWidth; + if (RtrPolyWidth > i) i = RtrPolyWidth; + RtrContactOffset = - (RtrContactWidth + 1 - i)/2; + + /* The actual actual distance from a paint layer to a grid line + * is a combination of how far the paint must be from routing + * material, and where routing material goes relative to the + * grid line. + */ + + RtrSubcellSepUp = RtrSubcellSepDown = 0; + + /* Compute how far above and below grid lines the routing layers run, + * and compensate the obstacle separations accordingly. This is + * determined by the contact size and location. + */ + + above = RtrContactWidth + RtrContactOffset; + below = - RtrContactOffset; + + for (i=0; i < TT_MAXTYPES; i++) + { + int metal, poly; + if (TTMaskHasType(&RtrMetalObstacles, i)) + metal = RtrMetalSeps[i] + RtrMetalSurround; + else metal = 0; + if (TTMaskHasType(&RtrPolyObstacles, i)) + poly = RtrPolySeps[i] + RtrPolySurround; + else poly = 0; + if (metal < poly) metal = poly; + RtrPaintSepsDown[i] = metal + above; + RtrPaintSepsUp[i] = metal + below; + if (RtrPaintSepsDown[i] > RtrSubcellSepDown) + RtrSubcellSepDown = RtrPaintSepsDown[i]; + if (RtrPaintSepsUp[i] > RtrSubcellSepUp) + RtrSubcellSepUp = RtrPaintSepsUp[i]; + } + +#ifdef notdef + TxPrintf("Routing information:\n"); + TxPrintf(" Layer1 is %s, width %d.\n", + DBTypeLongName(RtrMetalType), RtrMetalWidth); + if (!TTMaskEqual(&RtrMetalObstacles, &DBZeroTypeBits)) + { + TxPrintf(" Layer1 obstacles are:"); + for (i=0; i + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/signals.h" +#include "utils/malloc.h" +#include "router/router.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "gcr/gcr.h" +#include "router/routerInt.h" + +int rtrTarget; /* Via minimization, target type */ +int rtrReplace; /* Via minimization, replacement type */ +int rtrDelta; /* Change in layer width */ + +/* General note for rtrSrTraverse: + * + * The connectivity extractor works in two passes, in order to avoid + * circularities. During the first pass, each connected tile gets + * marked, using the ti_client field. This marking is needed to + * avoid infinite searches on circular structures. The second pass + * is used to clear the markings again. + */ + +/* The following structure is used to hold several pieces + * of information that must be passed through multiple + * levels of search function. + */ + +struct conSrArg +{ + CellDef *csa_def; /* Definition being searched. */ + int csa_pNum; /* Index of plane being searched. */ + TileTypeBitMask *csa_connect; /* Table indicating what connects + * to what. + */ + int (*csa_clientFunc)(); /* Client function to call. */ + ClientData csa_clientData; /* Argument for clientFunc. */ + bool csa_clear; /* FALSE means pass 1, TRUE + * means pass 2. + */ + Rect csa_bounds; /* Area that limits search. */ +}; + +/* + * The search path is maintained on the C runtime stack + * with rtrTileStack sructures. Each entry on the stack + * points back to the previous connected tile. + */ + +struct rtrTileStack +{ + Tile *ts_tile; /* Tile at this level in the stack */ + struct rtrTileStack *ts_link; /* Pointer to previous stack entry */ + struct conSrArg *ts_csa; /* Pointer to search arguments */ +}; + +/* + * ---------------------------------------------------------------------------- + * + * rtrSrTraverse -- + * + * This function is almost identical to DBSrConnect + * in that it searches through a cell to find all + * paint that is electrically connected to things + * in a given starting area. + * It differs in that it maintains a stack + * (on the C runtime stack) of the search path. + * This enables the client routine to examine + * the stack and recognize patterns of material + * in the connection path. Since the connection path + * is a tree, a stack is convenient data structure for + * recording a particular path originating from a single node. + * + * Results: + * 0 is returned if the search finished normally. 1 is returned + * if the search was aborted. + * + * Side effects: + * The search starts from one (random) non-space tile in "startArea" + * that matches the types in the mask parameter. For every paint + * tile that is electrically connected to the initial tile and that + * intersects the rectangle "bounds", func is called. Func should + * have the following form: + * + * int + * func(tile, clientData) + * Tile *tile; + * ClientData clientData; + * { + * } + * + * The clientData passed to func is the same one that was passed + * to us. Func returns 0 under normal conditions; if it returns + * 1 then the search is aborted. + * + * *** WARNING *** + * + * Func should not modify any paint during the search, since this + * will mess up pointers kept by these procedures and likely cause + * a core-dump. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrSrTraverse(def, startArea, mask, connect, bounds, func, clientData) + CellDef *def; /* Cell definition in which to carry out + * the connectivity search. Only paint + * in this definition is considered. + */ + Rect *startArea; /* Area to search for an initial tile. Only + * tiles OVERLAPPING the area are considered. + * This area should have positive x and y + * dimensions. + */ + TileTypeBitMask *mask; /* Only tiles of one of these types are used + * as initial tiles. + */ + TileTypeBitMask *connect; /* Pointer to a table indicating what tile + * types connect to what other tile types. + * Each entry gives a mask of types that + * connect to tiles of a given type. + */ + Rect *bounds; /* Area, in coords of scx->scx_use->cu_def, + * that limits the search: only tiles + * overalapping this area will be returned. + * Use TiPlaneRect to search everywhere. + */ + int (*func)(); /* Function to apply at each connected tile. */ + ClientData clientData; /* Client data for above function. */ + +{ + struct conSrArg csa; + struct rtrTileStack ts; + int startPlane, result; + Tile *startTile; /* Starting tile for search. */ + extern int rtrSrTraverseFunc(); /* Forward declaration. */ + extern int rtrSrTraverseStartFunc(); + + result = 0; + csa.csa_def = def; + csa.csa_bounds = *bounds; + + /* Find a starting tile (if there are many tiles underneath the + * starting area, pick any one). The search function just saves + * the tile address and returns. + */ + + startTile = NULL; + for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++) + { + if (DBSrPaintArea((Tile *) NULL, + def->cd_planes[startPlane], startArea, mask, + rtrSrTraverseStartFunc, (ClientData) &startTile) != 0) break; + } + if (startTile == NULL) + return 0; + + /* Pass 1. During this pass the client function gets called. */ + + csa.csa_clientFunc = func; + csa.csa_clientData = clientData; + csa.csa_clear = FALSE; + csa.csa_connect = connect; + csa.csa_pNum = startPlane; + + ts.ts_tile = (Tile *) NULL; + ts.ts_link = (struct rtrTileStack *) NULL; + ts.ts_csa = &csa; + + if (rtrSrTraverseFunc(startTile, &ts) != 0) + result = 1; + + /* Pass 2. Don't call any client function, just clear the marks. + * Don't allow any interruptions. + */ + + SigDisableInterrupts(); + csa.csa_clientFunc = NULL; + csa.csa_clear = TRUE; + csa.csa_pNum = startPlane; + (void) rtrSrTraverseFunc(startTile, &ts); + SigEnableInterrupts(); + + return result; +} + +int +rtrSrTraverseStartFunc(tile, pTile) + Tile *tile; /* This will be the starting tile. */ + Tile **pTile; /* We store tile's address here. */ +{ + *pTile = tile; + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrSrTraverseFunc -- + * + * This search function gets called by DBSrPaintArea as part + * of rtrSrTraverse, and also recursively by itself. Each invocation + * is made to process a single tile that is of interest. + * This function is copied from dbSrConnectFunc and differs by + * maintaining a stack (on the C-run time stack) of the search + * path. + * + * Results: + * 0 is returned unless the client function returns a non-zero + * value, in which case 1 is returned. + * + * Side effects: + * If this tile has been seen before, then just return + * immediately. If this tile hasn't been seen before, it is + * marked and the client procedure is called. A NULL client + * procedure is not called, of course. In addition, we scan + * the tiles perimeter for any connected tiles, and call + * ourselves recursively on them. + * + * Design note: + * This one procedure is used during both the marking and clearing + * passes, so "seen before" is a function both of the ti_client + * field in the tile and the csa_clear value. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrSrTraverseFunc(tile, ts) + Tile *tile; /* Tile that is connected. */ + struct rtrTileStack *ts; /* Contains information about the search. */ +{ + Tile *t2; + Rect tileArea; + int i; + TileTypeBitMask *connectMask; + TileType ttype; + unsigned int planes; + struct conSrArg *csa = ts->ts_csa; + struct rtrTileStack nts; + + nts.ts_csa = csa; + nts.ts_tile = tile; + nts.ts_link = ts; + + TiToRect(tile, &tileArea); + ttype = TiGetType(tile); + + /* Make sure this tile overlaps the area we're interested in. */ + + if (!GEO_OVERLAP(&tileArea, &csa->csa_bounds)) return 0; + + /* See if we've already been here before, and mark the tile as already + * visited. + */ + + if (csa->csa_clear) + { + if (tile->ti_client == (ClientData) CLIENTDEFAULT) return 0; + tile->ti_client = (ClientData) CLIENTDEFAULT; + } + else + { + if (tile->ti_client != (ClientData) CLIENTDEFAULT) return 0; + tile->ti_client = (ClientData) 1; + } + + /* Call the client function, if there is one. */ + + if (csa->csa_clientFunc != NULL) + { + if ((*csa->csa_clientFunc)(tile, &nts) != 0) + return 1; + } + + /* Now search around each of the four sides of this tile for + * connected tiles. For each one found, call ourselves + * recursively. + */ + + connectMask = &csa->csa_connect[ttype]; + + /* Left side: */ + + for (t2 = BL(tile); BOTTOM(t2) < tileArea.r_ytop; t2 = RT(t2)) + { + if (TTMaskHasType(connectMask, TiGetType(t2))) + { + if (csa->csa_clear) + { + if (t2->ti_client == (ClientData) CLIENTDEFAULT) continue; + } + else if (t2->ti_client != (ClientData) CLIENTDEFAULT) continue; + if (rtrSrTraverseFunc(t2, &nts) != 0) return 1; + } + } + + /* Bottom side: */ + + for (t2 = LB(tile); LEFT(t2) < tileArea.r_xtop; t2 = TR(t2)) + { + if (TTMaskHasType(connectMask, TiGetType(t2))) + { + if (csa->csa_clear) + { + if (t2->ti_client == (ClientData) CLIENTDEFAULT) continue; + } + else if (t2->ti_client != (ClientData) CLIENTDEFAULT) continue; + if (rtrSrTraverseFunc(t2, &nts) != 0) return 1; + } + } + + /* Right side: */ + + for (t2 = TR(tile); ; t2 = LB(t2)) + { + if (TTMaskHasType(connectMask, TiGetType(t2))) + { + if (csa->csa_clear) + { + if (t2->ti_client == (ClientData) CLIENTDEFAULT) goto nextRight; + } + else if (t2->ti_client != (ClientData) CLIENTDEFAULT) goto nextRight; + if (rtrSrTraverseFunc(t2, &nts) != 0) return 1; + } + nextRight: if (BOTTOM(t2) <= tileArea.r_ybot) break; + } + + /* Top side: */ + + for (t2 = RT(tile); ; t2 = BL(t2)) + { + if (TTMaskHasType(connectMask, TiGetType(t2))) + { + if (csa->csa_clear) + { + if (t2->ti_client == (ClientData) CLIENTDEFAULT) goto nextTop; + } + else if (t2->ti_client != (ClientData) CLIENTDEFAULT) goto nextTop; + if (rtrSrTraverseFunc(t2, &nts) != 0) return 1; + } + nextTop: if (LEFT(t2) <= tileArea.r_xbot) break; + } + + /* Lastly, check to see if this tile connects to anything on + * other planes. If so, search those planes. + */ + + planes = DBConnPlanes[ttype]; + planes &= ~(csa->csa_pNum); + if (planes != 0) + { + struct conSrArg newcsa; + + newcsa = *csa; + nts.ts_csa = &newcsa; + for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) + { + newcsa.csa_pNum = i; + if (DBSrPaintArea((Tile *) NULL, + newcsa.csa_def->cd_planes[i], + &tileArea, connectMask, rtrSrTraverseFunc, + (ClientData) &nts) != 0) + return 1; + } + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrExamineTile -- + * + * Examine a tile to see if it overlaps or connects + * the target tile. + * + * Results: + * Returns 1 if tile overlaps or connects + * the target tile. This means the target tile + * cannot be moved to another routing layer. + * Returns 0 otherwise. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrExamineTile(tile, cdata) + Tile *tile; + ClientData cdata; +{ + if ( TiGetType(tile) == rtrTarget ) + return 1; + + if ( (tile != (Tile *) cdata) && + (TiGetType(tile) == rtrReplace) ) + return 1; + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrExamineStack -- + * + * Examine a segment of the traversal path + * and identify segments of replacement material + * connected by vias at both ends and not overlapped + * or electrically connected to other routing material. + * + * Results: + * Always returns 0 to continue search. + * + * Side effects: + * Segments of replacement material are added to a list + * for later conversion to the target material. + * The vias are added to a list for later removal. + * They can't be processed now as pointers would get + * fouled up for the area search. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrExamineStack(tile, ts) + Tile *tile; + struct rtrTileStack *ts; +{ + int i; + Tile *tp[3]; + struct conSrArg *csa = ts->ts_csa; + CellDef *def = csa->csa_def; + + /* + * Collect topmost three elements of the stack. + */ + + i = 0; + while ( i < 3 && ts && ts->ts_tile ) + { + tp[i++] = ts->ts_tile; + ts = ts->ts_link; + } + + if ( i == 3 ) + { + /* + * Identify pattern -- *via* *replacement_material* *via* + */ + + if ( DBIsContact(TiGetType(tp[0])) && + (TiGetType(tp[1]) == rtrReplace) && + DBIsContact(TiGetType(tp[2]))) + { + int plane; + Rect area; + TileTypeBitMask mask; + int deltax = rtrDelta, deltay = rtrDelta; + + /* + * Search for overlapping or + * electrically connected routing material. + */ + + TTMaskZero(&mask); + TTMaskSetType(&mask, RtrPolyType); + TTMaskSetType(&mask, RtrMetalType); + TITORECT(tp[1], &area); + area.r_xbot--; + area.r_xtop++; + for ( plane = PL_PAINTBASE; plane < DBNumPlanes; plane++ ) + if ( DBPaintOnPlane(RtrPolyType, plane) || + DBPaintOnPlane(RtrMetalType, plane) ) + if ( DBSrPaintArea((Tile *)NULL, def->cd_planes[plane], + &area, &mask, rtrExamineTile, (ClientData) tp[1]) ) + return 0; + + /* + * Mark areas for later processing. + */ + + if ( rtrDelta < 0 ) + { + if ( (TOP(tp[1]) == BOTTOM(tp[0])) || (TOP(tp[1]) == BOTTOM(tp[2]))) + deltay = 0; + if ( (RIGHT(tp[1]) == LEFT(tp[0])) || (RIGHT(tp[1]) == LEFT(tp[2]))) + deltax = 0; + } + + rtrListVia (tp[0]); + rtrListArea(tp[1], rtrReplace, rtrTarget, deltax, deltay); + rtrListVia (tp[2]); + } + } + return 0; +} diff --git a/router/rtrVia.c b/router/rtrVia.c new file mode 100644 index 00000000..f0a9d5fe --- /dev/null +++ b/router/rtrVia.c @@ -0,0 +1,576 @@ +/* rtrVia.c.c - + * + * This file contains procedures that minimize vias and + * maximize metal. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/router/rtrVia.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" +#include "netmenu/netmenu.h" +#include "textio/textio.h" +#include "utils/styles.h" +#include "utils/malloc.h" +#include "gcr/gcr.h" +#include "router/router.h" +#include "router/routerInt.h" + +/* + * The following structures are used to hold information about + * areas to be erased/modified/painted during via minimization. + */ + +struct arealist +{ + Rect ap_erase; /* Area to be erased. */ + Rect ap_paint; /* Area to be painted. */ + int ap_oldtype; /* Type to be erased */ + int ap_newtype; /* Type to be painted */ + struct arealist *ap_next; /* Next item in list, or NULL for end. */ +}; + +struct vialist +{ + Rect vp_area; /* Via area to be examined. */ + struct vialist *vp_next; /* Next item in list, or NULL for end. */ +}; + +struct paintlist +{ + Rect pl_area; /* Extension segment to paint */ + struct paintlist *pl_next;/* Next extension to paint */ +}; + +struct srinfo +{ + Rect *si_area; /* Expanded area surrounding via */ + Rect *si_varea; /* Exact area of via */ + Rect si_extend; /* Extended stub within si_varea */ + Tile *si_tile; /* Reference tile */ + Plane *si_plane; /* Plane being searched */ + TileTypeBitMask si_mask; /* Tile type mask */ +}; + +struct vialist *rtrViaList; /* List of vias to be processed */ +struct arealist *rtrAreaList; /* List of areas to be processed */ +struct paintlist *rtrPaintList; /* List of extension segments to paint */ + +int rtrVias; /* Count of vias eliminated */ +int rtrExamineStack(); /* Examines the tile stack for + replacement segments to be converted + to the target material */ + + +/* + * ---------------------------------------------------------------------------- + * + * rtrFollowLocFunc -- + * + * This function is called once for each terminal location in + * a netlist. It invokes a procedure to follow all electrically + * connected paths from the terminal. + * + * Results: + * Always returns 0 to keep the search from aborting. + * + * Side effects: + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +rtrFollowLocFunc(rect, name, label, area) + Rect *rect; /* Area of the terminal, edit cell coords. */ + char *name; /* Name of the terminal (ignored). */ + Label *label; /* Pointer to the label, used to find out + * what layer the label's attached to. + */ + Rect *area; /* We GeoInclude into this all the areas of + * all the tiles we delete. + */ +{ + CellDef *def = EditCellUse->cu_def; + Rect initialArea; + + GEO_EXPAND(rect, 1, &initialArea); + (void) rtrSrTraverse(def, &initialArea, + &DBConnectTbl[label->lab_type], DBConnectTbl, + &TiPlaneRect, rtrExamineStack, 0); + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrFollowName -- + * + * This function gets called during via minimization. It's invoked + * once for each terminal name in the netlist. It calls + * DBSrLabelLoc to invoke rtrFollowLocFunc for each terminal + * location associated with the name. + * + * Results: + * Always returns 0 to keep the search from aborting. + * + * Side effects: + * Nothing here, but a list of segments of poly are generated. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +rtrFollowName(name, firstInNet, area) + char *name; /* Name of terminal. */ + bool firstInNet; /* Ignored by this procedure. */ + Rect *area; /* Passed through as ClientData to + * rtrFollowLocFunc. + */ +{ + if ( firstInNet ) + { + RtrMilestonePrint("#"); + (void) DBSrLabelLoc(EditCellUse, name, rtrFollowLocFunc, (ClientData) area); + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrCheckTypes -- + * Abort area search if both poly and metal are adjacent to via. + * + * Results: + * Returns 1 if poly and metal connect to via. + * Returns zero otherwise. + * + * Side effects: + * Type of connecting material returned in cdata parameter. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrCheckTypes(tile, cdata) + Tile *tile; + ClientData cdata; +{ + int type; + int lastType = * (int *) cdata; + + type = TiGetType(tile); + if ( (type == RtrMetalType) || (type == RtrPolyType) ) + { + if ( lastType ) + { + if ( lastType != type ) + return 1; + } + else + *(int *)cdata = type; + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrExtandStub -- + * Generate an extension of a piece of routing material + * by extending into the area of the via. + * + * Results: + * None. + * + * Side effects: + * Extension segment returned in *stub*. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrExtend(tile,area,stub) + Tile *tile; /* Tile adjacent to via */ + Rect *area; /* Area occupied by via */ + Rect *stub; /* Extension of routing material + into area of via */ +{ + if ( (TOP(tile) == area->r_ybot) || (BOTTOM(tile) == area->r_ytop) ) + { + stub->r_xbot = MAX(area->r_xbot, LEFT(tile)); + stub->r_xtop = MIN(area->r_xtop, RIGHT(tile)); + stub->r_ybot = area->r_ybot; + stub->r_ytop = area->r_ytop; + } + else if ( (LEFT(tile) == area->r_xtop) || (RIGHT(tile) == area->r_xbot) ) + { + stub->r_xbot = area->r_xbot; + stub->r_xtop = area->r_xtop; + stub->r_ybot = MAX(area->r_ybot, BOTTOM(tile)); + stub->r_ytop = MIN(area->r_ytop, TOP(tile)); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrStubGen -- + * Generate an extension segment for a piece of routing material. + * + * Results: + * Return 0 to keep the search going. + * + * Side effects: + * Extension segment entry added to rtrPaintList list for later painting. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrStubGen(tile, si) + Tile *tile; + struct srinfo *si; +{ + Rect area; + struct paintlist *pl; + + if ( tile != si->si_tile ) + { + pl = (struct paintlist *) mallocMagic((unsigned) (sizeof(*pl))); + pl->pl_next = rtrPaintList; + rtrPaintList = pl; + + /* + * Generate extension segment relative to reference segment. + */ + + rtrExtend(tile, si->si_varea, &pl->pl_area); + GeoClip(&pl->pl_area, &si->si_extend); + TITORECT(tile, &area); + GeoClip(&area, si->si_area); + (void) GeoInclude(&area, &pl->pl_area); + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrReferenceTile -- + * Store a reference tile and corresponding extension stub. + * Recursively call DBSrPaintArea to generate extension + * stubs intersecting the reference stub. Each tile + * adjacent to the via will in turn be a reference tile. + * + * Results: + * Always returns 0 to continue search. + * + * Side effects: + * Tile pointer and extension stub stored in *srinfo* structure. + * + * ---------------------------------------------------------------------------- + */ + + +int +rtrReferenceTile(tile, si) + Tile *tile; + struct srinfo *si; +{ + si->si_tile = tile; + rtrExtend(tile, si->si_varea, &si->si_extend); + (void) DBSrPaintArea(tile, si->si_plane, si->si_area, + &si->si_mask, rtrStubGen, (ClientData) si); + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * rtrViaCheck -- + * Check to see if a via is necessary. + * If only one routing layer connects to the via, + * delete the via and replace with extended segments of routing material. + * + * Results: + * None. + * + * Side effects: + * Via erased. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrViaCheck(area, def) + Rect *area; + CellDef *def; +{ + Rect r; + int type, plane; + struct paintlist *pl; + TileTypeBitMask mask; + + /* + * Search around via for connecting pieces of metal or poly. + */ + + GEO_EXPAND(area, 1, &r); + type = 0; + TTMaskZero(&mask); + TTMaskSetType(&mask, RtrPolyType); + TTMaskSetType(&mask, RtrMetalType); + for ( plane = PL_PAINTBASE; plane < DBNumPlanes; plane++ ) + if ( DBPaintOnPlane(RtrPolyType, plane) || + DBPaintOnPlane(RtrMetalType, plane) ) + if ( DBSrPaintArea((Tile *)NULL, def->cd_planes[plane], + &r, &mask, rtrCheckTypes, (ClientData) &type) ) + return; + + /* + * No metal or poly connects to this via. + * Enumerate all connecting routing material + * and build a list if extension segments to replace the via. + */ + + rtrPaintList = (struct paintlist *) NULL; + for ( plane = PL_PAINTBASE; plane < DBNumPlanes; plane++ ) + if ( DBPaintOnPlane(type, plane) ) + { + struct srinfo si; + + si.si_area = &r; + si.si_varea = area; + si.si_plane = def->cd_planes[plane]; + TTMaskZero(&si.si_mask); + TTMaskSetType(&si.si_mask, type); + (void) DBSrPaintArea((Tile *)NULL, si.si_plane, + &r, &mask, rtrReferenceTile, (ClientData) &si); + } + + /* + * Erase via and paint extensions. + */ + + DBErase(def, area, RtrContactType); + for ( pl = rtrPaintList; pl; pl = pl->pl_next) + { + DBPaint(def, &pl->pl_area, type); + freeMagic( (char *)pl ); + } + + rtrVias++; + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrListArea -- + * Append an entry into a linked list + * of areas to be processed. + * + * Results: + * None. + * + * Side effects: + * rtrAreaList points to a new list entry + * which is linked into the existing list. + * + * ---------------------------------------------------------------------------- + */ + +void +rtrListArea(tile, oldType, newType, deltax, deltay) + Tile *tile; + int oldType; + int newType; + int deltax; + int deltay; +{ + struct arealist *ap; + + ap = (struct arealist *) mallocMagic((unsigned) (sizeof(*ap))); + TITORECT(tile, &ap->ap_erase); + TITORECT(tile, &ap->ap_paint); + + /* + * Adjust size of paint to correspond to new layer. + */ + + ap->ap_paint.r_xtop += deltax; + ap->ap_paint.r_ytop += deltay; + + ap->ap_oldtype = oldType; + ap->ap_newtype = newType; + ap->ap_next = rtrAreaList; + rtrAreaList = ap; +} + +/* + * ---------------------------------------------------------------------------- + * + * rtrListVia -- + * Append an entry into a linked list + * of areas to be processed. + * + * Results: + * Always return 0 to keep the search going. + * + * Side effects: + * rtrViaList points to new list entry + * which is linked in front of existing list. + * Always returns 0 to continue search if called from + * DBSrPaintArea. + * + * ---------------------------------------------------------------------------- + */ + +int +rtrListVia(tile) + Tile *tile; +{ + struct vialist *vp; + + vp = (struct vialist *) mallocMagic((unsigned)(sizeof(*vp))); + TITORECT(tile, &vp->vp_area); + vp->vp_next = rtrViaList; + rtrViaList = vp; + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * RtrViaMinimize -- + * Minimize vias and maximize metal. + * + * Results: + * Return number of vias elminiated. + * + * Side effects: + * On the first pass, segments of poly + * are replaced with metal and connecting vias are erased. + * On the second pass, segments of metal + * are replaced with poly and connecting vias are erased. + * + * ---------------------------------------------------------------------------- + */ + +int +RtrViaMinimize(def) + CellDef *def; +{ + Rect area; + struct vialist *vp; + struct arealist *ap; + + /* + * Pass 1 -- + * Enumerate every terminal in the netlist + * to follow all electrically connected paths. + * Generate a list of segments of poly not overlapped by metal + * and terminated at each end by vias. + * These segments of poly are replaced with metal + * and the connecting via's are removed. + */ + + rtrVias = 0; + rtrTarget = RtrMetalType; + rtrReplace = RtrPolyType; + rtrDelta = RtrMetalWidth - RtrPolyWidth; + + area = GeoNullRect; + rtrViaList = (struct vialist *) NULL; + rtrAreaList = (struct arealist *) NULL; + (void) NMEnumNets(rtrFollowName, (ClientData) &area); + + /* + * Replace poly with metal where appropriate. + */ + + for ( ap = rtrAreaList; ap; ap = ap->ap_next) + { + DBErase(def, &ap->ap_erase, ap->ap_oldtype); + DBPaint(def, &ap->ap_paint, ap->ap_newtype); + freeMagic( (char *)ap); + } + + /* + * Eliminate unnecessary vias. + */ + + for ( vp = rtrViaList; vp; vp = vp->vp_next) + { + rtrViaCheck(&vp->vp_area, def); + freeMagic( (char *)vp); + } + + /* + * Pass 2 -- + * Repeat the entire process replacing metal with poly. + */ + + rtrTarget = RtrPolyType; + rtrReplace = RtrMetalType; + rtrDelta = RtrPolyWidth - RtrMetalWidth; + + area = GeoNullRect; + rtrViaList = (struct vialist *) NULL; + rtrAreaList = (struct arealist *) NULL; + (void) NMEnumNets(rtrFollowName, (ClientData) &area); + + /* + * Erase poly and replace with metal. + */ + + for ( ap = rtrAreaList; ap; ap = ap->ap_next) + { + DBErase(def, &ap->ap_erase, ap->ap_oldtype); + DBPaint(def, &ap->ap_paint, ap->ap_newtype); + freeMagic( (char *)ap); + } + + /* + * Eliminate unnecessary vias. + */ + + for ( vp = rtrViaList; vp; vp = vp->vp_next) + { + rtrViaCheck(&vp->vp_area, def); + freeMagic( (char *)vp); + } + + return rtrVias; +} diff --git a/router/tclroute.c b/router/tclroute.c new file mode 100644 index 00000000..b77e93f9 --- /dev/null +++ b/router/tclroute.c @@ -0,0 +1,95 @@ +/*--------------------------------------------------------------*/ +/* tclroute.c */ +/* */ +/* Allows the "router" feature to be loaded as a module */ +/* under the Tcl/Tk version of magic. Loading is */ +/* automatic upon invoking one of the router commands. */ +/*--------------------------------------------------------------*/ + +#ifdef ROUTE_AUTO + +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "utils/list.h" +#include "database/database.h" +#include "windows/windows.h" +#include "commands/commands.h" +#include "utils/tech.h" +#include "dbwind/dbwind.h" +#include "router/router.h" +#include "gcr/gcr.h" +#include "grouter/grouter.h" +#include "mzrouter/mzrouter.h" + +/* External routines */ + +extern void CmdRoute(), CmdIRoute(), CmdGaRoute(); +extern void CmdChannel(), CmdSeeFlags(); +extern void CmdGARouterTest(), CmdGRouterTest(); +extern void CmdIRouterTest(), CmdMZRouterTest(); + +/* + * ---------------------------------------------------------------------------- + * + * Tcl package initialization function + * + * ---------------------------------------------------------------------------- + */ + +int +Tclroute_Init(interp) + Tcl_Interp *interp; +{ + SectionID invsec; + + /* Sanity checks! */ + if (interp == NULL) return TCL_ERROR; + if (Tcl_PkgRequire(interp, "Tclmagic", MAGIC_VERSION, 0) == NULL) + return TCL_ERROR; + if (Tcl_InitStubs(interp, "8.1", 0) == NULL) return TCL_ERROR; + + TxPrintf("Auto-loading ROUTE module\n"); + TxFlushOut(); + + /* Replace the auto-load function with the ones defined in */ + /* this package in the command functions list. */ + + WindReplaceCommand(DBWclientID, "route", CmdRoute); + WindReplaceCommand(DBWclientID, "garoute", CmdRoute); + WindReplaceCommand(DBWclientID, "iroute", CmdIRoute); + WindReplaceCommand(DBWclientID, "channels", CmdChannel); + WindReplaceCommand(DBWclientID, "*garoute", CmdGARouterTest); + WindReplaceCommand(DBWclientID, "*groute", CmdGRouterTest); + WindReplaceCommand(DBWclientID, "*iroute", CmdIRouterTest); + WindReplaceCommand(DBWclientID, "*mzroute", CmdMZRouterTest); + WindReplaceCommand(DBWclientID, "*seeflags", CmdSeeFlags); + + /* Now we need to do TechAddClient and reload the tech file */ + + TechAddClient("mzrouter", MZTechInit, MZTechLine, MZTechFinal, + (SectionID) 0, (SectionID *) 0, FALSE); + TechAddClient("router", RtrTechInit, RtrTechLine, RtrTechFinal, + (SectionID) 0, (SectionID *) 0, FALSE); + + /* Initialization functions */ + NMinit(); + MZInit(); + IRInit(); + + invsec = TechSectionGetMask("drc", NULL); + invsec &= TechSectionGetMask("mzrouter", NULL); + invsec &= TechSectionGetMask("router", NULL); + if (!TechLoad(NULL, invsec)) return TCL_ERROR; + + Tcl_PkgProvide(interp, "Route", MAGIC_VERSION); + return TCL_OK; +} + +#endif /* ROUTE_AUTO */ diff --git a/rules.mak b/rules.mak new file mode 100644 index 00000000..1fa3e75a --- /dev/null +++ b/rules.mak @@ -0,0 +1,60 @@ +# You shouldn't need to edit this file, see the defs.mak file + +module: lib${MODULE}.o + +depend: ${DEPEND_FILE} + +# New Depend file generating line (Tim Edwards, 1/25/06). This gets around +# problems with gcc. The purpose of "make depend" is to generate a list of +# all local dependencies, but gcc insists that anything that is in, for +# example, the /usr/X11R6 path should also be included. The sed scripts +# (respectively) do: 1) remove comment lines generated by gcc, 2) remove +# any header (.h) files with an absolute path (beginning with "/"), and +# 3) remove isolated backslash-returns just to clean things up a bit. + +${DEPEND_FILE}: + ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${DEPEND_FLAG} ${DEPSRCS} | \ + sed -e "/#/D" -e "/ \//s/ \/.*\.h//" -e "/ \\\/D" \ + > ${DEPEND_FILE} + +# Original Depend file generating line: +# ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${DEPEND_FLAG} ${SRCS} > ${DEPEND_FILE} + +.c.o: + @echo --- compiling ${MODULE}/$*.o + ${RM} $*.o + ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} -c $*.c + +lib${MODULE}.o: ${OBJS} + @echo --- linking lib${MODULE}.o + ${RM} lib${MODULE}.o + ${LINK} ${OBJS} -o lib${MODULE}.o ${EXTERN_LIBS} + +lib: lib${MODULE}.a + +lib${MODULE}.a: ${OBJS} ${LIB_OBJS} + @echo --- archiving lib${MODULE}.a + ${RM} lib${MODULE}.a + ${AR} ${ARFLAGS} lib${MODULE}.a ${OBJS} ${LIB_OBJS} + ${RANLIB} lib${MODULE}.a + +${MODULE}: lib${MODULE}.o ${EXTRA_LIBS} + @echo --- building main ${MODULE} + ${RM} ${MODULE} + ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} lib${MODULE}.o ${EXTRA_LIBS} -o ${MODULE} ${LIBS} + +${DESTDIR}${BINDIR}/${MODULE}${EXEEXT}: ${MODULE}${EXEEXT} + ${RM} ${DESTDIR}${BINDIR}/${MODULE}${EXEEXT} + ${CP} ${MODULE}${EXEEXT} ${DESTDIR}${BINDIR} + +../database/database.h: ../database/database.h.in + @echo --- making header file database/database.h + ${SCRIPTS}/makedbh ../database/database.h.in ../database/database.h + +clean: + ${RM} ${CLEANS} + +tags: ${SRCS} ${LIB_SRCS} + ctags ${SRCS} ${LIB_SRCS} + +include ${DEPEND_FILE} diff --git a/scmos/COPYRIGHT b/scmos/COPYRIGHT new file mode 100644 index 00000000..b92446d9 --- /dev/null +++ b/scmos/COPYRIGHT @@ -0,0 +1,37 @@ +/* + * (C) Copyright 1992,1994 by + * + * Jen-I Pi pi@isi.edu + * The MOSIS Service + * USC Information Sciences Institute + * 4676 Admiralty Way + * Marina del Rey, CA 90292 + * (310) 822-1511 x640 fax (310)823-5624 + * + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this technology + * file and its associated documentation for any purpose and without + * fee is hereby granted, provided that the above copyright notice + * appears in all copies and that both that copyright notice and this + * permission notice appear in supporting documentation, and that the + * name of the University of Southern California not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The University of + * Southern California makes no representations about the suitability + * of this technology file for any purpose. This technology file is + * provided "as is" without express or implied warranty and the + * University of Southern California retains the right to change its + * content at any time without notice any other party. + * + * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS TECHNOLOGY FILE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF + * SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS TECHNOLOGY FILE. + * + */ + diff --git a/scmos/Makefile b/scmos/Makefile new file mode 100644 index 00000000..e77e9e00 --- /dev/null +++ b/scmos/Makefile @@ -0,0 +1,103 @@ +####################################################################### +# +# MOSIS distribution Version 8.2 +# +####################################################################### +# +# The intent in magic version 7.2 was to convert all the "c" style +# files to m4. However, given the number of files, and the fact that +# they are out of date and should all be replaced anyway, this doesn't +# seem to be worth the effort. Therefore, some trivial things (like +# minimum.tech) have been converted to m4 and the rest have been left +# alone. +# +####################################################################### + +MAGICDIR = .. + +include ${MAGICDIR}/defs.mak + +SC_M4 = ${M4} +SC_CPP = ${CPP} -I./extract_template + +FILES = mos.7bit.dstyle mos.7bit.std.cmap \ + mos.24bit.dstyle mos.24bit.std.cmap \ + mos.7bit.mraster_dstyle mos.7bit.mraster.cmap \ + mos.OpenGL.dstyle mos.OpenGL.std.cmap +TECHFILES = minimum.tech gdsquery.tech scmos.tech scmos-tm.tech \ + scmos-sub.tech scmosWR.tech + +CIFin = cif_template/objs/CIFin +CIFout = cif_template/objs/CIFout +ICIFin = cif_template/objs/IBMCIFin +ICIFout = cif_template/objs/IBMCIFout +HCIFin = cif_template/objs/TMCIFin +HCIFout = cif_template/objs/TMCIFout +SCIFin = cif_template/objs/SUBCIFin +SCIFout = cif_template/objs/SUBCIFout + +OBJS =$(CIFin) $(CIFout) $(HCIFin) $(HCIFout) $(SCIFin) $(SCIFout) + +DEPEND = scmos.tech.in \ + extract_template/scmosExt.tech.in \ + extract_template/scmosExt26b-sub.tech.in \ + extract_template/scmosExt060_orb.tech.in \ + extract_template/scmosExt080.tech.in \ + extract_template/scmosExt100.tech.in \ + extract_template/scmosExt34.tech.in \ + extract_template/scmosExt14b-sub.tech.in \ + extract_template/scmosExtDiag.tech.in \ + extract_template/scmosExt14b-tm.tech.in + +all: $(OBJS) $(DEPEND) ${TECHFILES} + +install-tcl: all + for i in ${FILES} ${TECHFILES}; do \ + ${CP} $$i $(DESTDIR)${SYSDIR}; done + +install: all + for i in ${FILES} ${TECHFILES}; do \ + ${CP} $$i $(DESTDIR)${SYSDIR}; done + +scmos.tech: $(OBJS) + sed -e 's/\\/\\\\/' scmos.tech.in > scmos.tech.out + $(SC_CPP) -DV5 -DSTANDARD scmos.tech.out > scmos.tech + $(RM) scmos.tech.out + +scmos-tm.tech: $(OBJS) + sed -e 's/\\/\\\\/' scmos.tech.in > scmos.tech.out + $(SC_CPP) -DV5 -DHPTECH -DTIGHTMETAL scmos.tech.out > scmos-tm.tech + $(RM) scmos.tech.out + +scmos-sub.tech: $(OBJS) + sed -e 's/\\/\\\\/' scmos.tech.in > scmos.tech.out + $(SC_CPP) -DV5 -DSUBMICRON scmos.tech.out > scmos-sub.tech + $(RM) scmos.tech.out + +scmosWR.tech: $(OBJS) + sed -e 's/\\/\\\\/' scmos.tech.in > scmos.tech.out + $(SC_CPP) -DV5 -DSTANDARD -DWELL_ROUTE_CHECK scmos.tech.out > scmosWR.tech + $(RM) scmos.tech.out + +minimum.tech: minimum.tech.m4 + $(SC_M4) minimum.tech.m4 > minimum.tech + +gdsquery.tech: gdsquery.tech.m4 + $(SC_M4) gdsquery.tech.m4 > gdsquery.tech + +$(CIFin): +$(CIFout): +$(ICIFin): +$(ICIFout): +$(HCIFin): +$(HCIFout): +$(SCIFin): +$(SCIFout): + cd cif_template; ${MAKE} clean; ${MAKE}; + +$(DESTDIR)${SYSDIR}/%: % + cp $* $(DESTDIR)${SYSDIR}/$* + +clean:; + -rm -f *.tech *.tech27 + cd cif_template && ${MAKE} clean; diff --git a/scmos/README b/scmos/README new file mode 100644 index 00000000..4bdc86a7 --- /dev/null +++ b/scmos/README @@ -0,0 +1,123 @@ +####################################################################### +# # +# MOSIS distribution Version 8.2 # +# # +# This is a version control header file for MOSIS's distribution of # +# Magic related technology files and system libraries.... # +# # +# Modified by Jen-I Pi, MOSIS Project, USC/ISI 06/02/1995 # +# Please send bug reports/comments to mosis@mosis.edu :-) # +# # +####################################################################### + +INTRODUCTION + + This officail MOSIS SCMOS technology release consists a famaly of + SCMOS technology files for Magic version 6.4.4 (available from + anonymous FTP gatekeeper.dec.com): + + * "scmos" - standard SCMOS technology for MOSIS process with + minimum feature length larger than 1.5 micron. + ORBIT 2.0 micron analog, ORBIT 1.2 micron processes + are supported. + * "scmos-tm" - SCMOS technology with tighter metal spacing rules + for metal1 and metal2. + HP-CMOS34, HP-CMOS26B (lambda=0.5 micron) and + HP-CMOS14B (lambda=0.35 micron) processes are + supported. + * "scmos-sub" - SCMOS technology for HP's sub-micron CMOS processes. + HP-CMOS26G (lambda=0.40 micron) and CMOS14B + (lambda=0.30 micron) processes are supported. + * "scmos-ibm" - SCMOS technology for IBM CMSX-2185 process. + (not supported anymore, but it's there in case...) + + To invoke Magic with appropriate technology selection, you need to + use the '-T' command option. For example, the command + + "magic -Tscmos-sub" + + start Magic with "scmos-sub" designated for HP's submicron processes. + + MOSIS's distribution of Magic technolofy file for SCMOS technology + now has CIFinput and CIFoutput section in templates so that it will + be easier to maintain. It also supports two layers, "open" and + "pstop" for micro-machined design fabrication in CMOS process as + described by Janet C. Marshall's paper in IEEE Circuit and Devices, + Vol. 8, N0. 6, 1992. this layer is now in a 'preliminary' stage. + + Before installation, please read the file 'COPYRIGHT' for copyright + notice. + +INSTALLATION + + Please install the latest release of Magic (version 6.4.4) available + from anonymous FTP gatekeeper.dec.com. + + To generate all technology files, simply type + + "make" if your are using Magic 6.4.x, or + + "make version3" if your are using Magic 6.3.x + + To install all technology files into the standard ~cad library, just type + + "make install" + + to you system (Unix) prompt. You might want to check the path for + standard ~cad/lib/magic/lib first before you do this... + +IRSIM PARAMETERS + + Parameter files of various MOSIS supported process for IRSIM + switch-level simulator can be found under the sub-directory + "irsim_parameters". + +DOCUMENTATION + + Please read the file UPDATE for the lates update information... + + In the doc subdirectory, you can find a preliminary PostScript file + for MOSIS's SCMOS Technology Manual. Warning: This manualscript is + in a very preliminary stage, if you have any problem with it don't + hesitate to discuss it further with me...(pi@isi.edu) + +EXAMPLE + + In the 'examples' subdirectory, we have: + + palette.mag - palette of all layers available in MOSIS's SCMOS tech- + nology". Turn your DRC off before viewing it!! + + ccd.mag - An example of a buried channel CCD layout. + + float_gate.mag - An example of a floating-gate device. + + wellcap.mag - An example of layout of linear capacitors available + from SCNLC technology, i.e. HP's 1.2um process. + + npn.mag - An example of a Bipolar NPN transistor layout. For ORBIT's + 2um lower-noise Analog process. + + large_npn.mag - A large NPN bipolar transistor consists of smalls + unit transistors. + + all.mag - An example of part of the design rules... NOT Complete... + + m3padframe.mag - A TinyChip padframe for HP's 1.0um process. Notice + that those m1 strip is required to complete a DRC free pad. + These pads use all three metal layers. + + inf_source - An example of micromachined device fabrication. This + layout is a reproduction of Fig. 8 of Janet C. Marshall's + article titled "High Level Melds Micromachined Devices with + Foundries", IEEE Circuits and Devices, Vol. 8, No. 6, pp. + 10-17, Nov. 1992. A complete NIST MEMS library is also + available from MOSIS's anonymous FTP archive. + +BUGs + + send you bug report or suggestions to mosis@mosis.edu + +Jen-I Pi ****** 05/24/95 +The MOSIS Service, USC/ISI +(310) 822-1511 x640 diff --git a/scmos/cif_template/COPYRIGHT b/scmos/cif_template/COPYRIGHT new file mode 100644 index 00000000..59608929 --- /dev/null +++ b/scmos/cif_template/COPYRIGHT @@ -0,0 +1,37 @@ +/* + * (C) Copyright 1992,1994,1995 by + * + * Jen-I Pi pi@isi.edu + * The MOSIS Service + * USC Information Sciences Institute + * 4676 Admiralty Way + * Marina del Rey, CA 90292 + * (310) 822-1511 x640 fax (310)823-5624 + * + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this technology + * file and its associated documentation for any purpose and without + * fee is hereby granted, provided that the above copyright notice + * appears in all copies and that both that copyright notice and this + * permission notice appear in supporting documentation, and that the + * name of the University of Southern California not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The University of + * Southern California makes no representations about the suitability + * of this technology file for any purpose. This technology file is + * provided "as is" without express or implied warranty and the + * University of Southern California retains the right to change its + * content at any time without notice any other party. + * + * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS TECHNOLOGY FILE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF + * SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS TECHNOLOGY FILE. + * + */ + diff --git a/scmos/cif_template/Makefile b/scmos/cif_template/Makefile new file mode 100644 index 00000000..0c654441 --- /dev/null +++ b/scmos/cif_template/Makefile @@ -0,0 +1,67 @@ +MAGICDIR = ../.. + +MKDIR = $(MAGICDIR)/scripts/mkdirs +OBJS_DIR = objs +CIFIN = $(OBJS_DIR)/CIFin +CIFOUT = $(OBJS_DIR)/CIFout +IBMCIFIN = $(OBJS_DIR)/IBMCIFin +IBMCIFOUT = $(OBJS_DIR)/IBMCIFout +TMCIFIN = $(OBJS_DIR)/TMCIFin +TMCIFOUT = $(OBJS_DIR)/TMCIFout +SUBCIFIN = $(OBJS_DIR)/SUBCIFin +SUBCIFOUT = $(OBJS_DIR)/SUBCIFout + +SED_CMD = sed -e "s/\\\\/\\\\\\\\/" -e "/^\#/D" -e "s/(gen )/(gen)/" -e "s/(nowell )/(nowell)/" -e "s/(nwell )/(nwell)/" -e "s/(pwell )/(pwell)/" + +include ${MAGICDIR}/defs.mak + +SC_CPP = ${CPP} + +all: $(OBJS_DIR) $(CIFIN) $(CIFOUT) $(IBMCIFIN) $(IBMCIFOUT) $(TMCIFIN) \ + $(TMCIFOUT) $(SUBCIFIN) $(SUBCIFOUT) + +clean:; + rm -f $(CIFIN) $(CIFOUT) $(IBMCIFIN) $(IBMCIFOUT) $(TMCIFIN) \ + $(TMCIFOUT) $(SUBCIFIN) $(SUBCIFOUT) + +scg: cifout.c cifout-cmos26b.gen cifout.gen cifout.nw\ + cifout.others cifout.pw cifout.scgnw cifout.scgpw + rm -f $(CIFOUT) + $(SC_CPP) scgcifout.c | ${SED_CMD} > $(CIFOUT) + +$(OBJS_DIR): + $(MKDIR) $(OBJS_DIR) + +$(CIFIN): cifin.c cifin-cmos26b.gen cifin.gen cifin.nw cifin.oldnw\ + cifin.others cifin.pw cifin-ami16.gen + rm -f $(CIFIN) + $(SC_CPP) -DSTANDARD cifin.c | ${SED_CMD} > $(CIFIN) + +$(CIFOUT): cifout.c cifout-cmos26b.gen cifout.gen cifout.nw\ + cifout.others cifout.pw cifout-ami16.gen + rm -f $(CIFOUT) + $(SC_CPP) -DSTANDARD cifout.c | ${SED_CMD} > $(CIFOUT) + +$(IBMCIFIN): cifin.c cifin-ibm.gen + rm -f $(IBMCIFIN) + $(SC_CPP) -DIBM cifin.c | ${SED_CMD} > $(IBMCIFIN) + +$(IBMCIFOUT): cifout.c cifout-ibm.gen + rm -f $(IBMCIFOUT) + $(SC_CPP) -DIBM cifout.c | ${SED_CMD} > $(IBMCIFOUT) + +$(TMCIFIN): cifin.c cifin-cmos26b.gen + rm -f $(TMCIFIN) + $(SC_CPP) -DTIGHTMETAL cifin.c | ${SED_CMD} > $(TMCIFIN) + +$(TMCIFOUT): cifout.c cifout-cmos26b.gen + rm -f $(TMCIFOUT) + $(SC_CPP) -DTIGHTMETAL cifout.c | ${SED_CMD} > $(TMCIFOUT) + +$(SUBCIFIN): cifin.c cifin-cmos26g.gen cifin-cmos14b.gen + rm -f $(SUBCIFIN) + $(SC_CPP) -DSUBMICRON cifin.c | ${SED_CMD} > $(SUBCIFIN) + +$(SUBCIFOUT): cifout.c cifout-cmos26g.gen cifout-cmos14b.gen + rm -f $(SUBCIFOUT) + $(SC_CPP) -DSUBMICRON cifout.c | ${SED_CMD} > $(SUBCIFOUT) diff --git a/scmos/cif_template/README b/scmos/cif_template/README new file mode 100644 index 00000000..ed599544 --- /dev/null +++ b/scmos/cif_template/README @@ -0,0 +1,15 @@ +This directory contains template files for MOSIS's SCMOS technology +for Magic layout editor. + +A simple command "make" should be able to generate all appropriate +files needed. You can also use "make clean" to remove all files and +then "make all" to generate all-style files. + +After all CIF input/output styles has been generated, you'll have to +go to the scmos directory to 're-make' the SCMOS technology file. + +Gook luck, + +Jen-I pi@isi.edu :-) +The MOSIS Services, USC/ISI +(310) 822-1511 x640 diff --git a/scmos/cif_template/calc.lambda b/scmos/cif_template/calc.lambda new file mode 100644 index 00000000..1e5bf151 --- /dev/null +++ b/scmos/cif_template/calc.lambda @@ -0,0 +1,166 @@ +/* undefine all local define's used first ... */ +#define OPEN +#undef scaleunit +#undef lambda_1 +#undef lambda_2 +#undef lambda_3 +#undef lambda_4 +#undef lambda_5 +#undef lambda_6 +#undef lambda_7 +#undef lambda_8 +#undef lambda_9 +#undef lambda_v +#undef lambda_half +#undef pad_via +#undef pad_glass +/* for 2.0 micron process... */ +#if (lambda_value==100) +#define lambda_half 50 +#define lambda_v 1.0(cif_tech) +#define scaleunit 50 +#define lambda_1 100 +#define lambda_2 200 +#define lambda_3 300 +#define lambda_4 400 +#define lambda_5 500 +#define lambda_6 600 +#define lambda_7 700 +#define lambda_8 800 +#define pad_via 500 +#define pad_glass 600 +/* for 3.0 micron process... */ +#elif (lambda_value==150) +#define lambda_half 75 +#define lambda_v 1.5(cif_tech) +#define scaleunit 25 +#define lambda_1 150 +#define lambda_2 300 +#define lambda_3 450 +#define lambda_4 600 +#define lambda_5 750 +#define lambda_6 900 +#define lambda_7 1050 +#define lambda_8 1200 +#define pad_via 450 +#define pad_glass 600 +/* for 1.6 micron process... */ +#elif (lambda_value==80) +#define lambda_half 40 +#define lambda_v 0.8(cif_tech) +#define scaleunit 40 +#define lambda_1 80 +#define lambda_2 160 +#define lambda_3 240 +#define lambda_4 320 +#define lambda_5 400 +#define lambda_6 480 +#define lambda_7 560 +#define lambda_8 640 +#define pad_via 560 +#define pad_glass 640 +/* for 1.2 micron process... */ +#elif (lambda_value==60) +#define lambda_half 30 +#define lambda_v 0.6(cif_tech) +#define scaleunit 30 +#define lambda_1 60 +#define lambda_2 120 +#define lambda_3 180 +#define lambda_4 240 +#define lambda_5 300 +#define lambda_6 360 +#define lambda_7 420 +#define lambda_8 480 +#define pad_via 300 +#define pad_glass 600 +/* for HP CMOS26B - 1.0 micron process... */ +#elif (lambda_value==50) +#define lambda_half 25 +#define lambda_v 0.5(cif_tech) +#define scaleunit 5 +#define lambda_1 50 +#define lambda_2 100 +#define lambda_3 150 +#define lambda_4 200 +#define lambda_5 250 +#define lambda_6 300 +#define lambda_7 350 +#define lambda_8 400 +#define pad_via1 300 +#define pad_via2 200 +#define pad_glass 600 +/* for HP CMOS26G - 0.8 micron process... */ +#elif (lambda_value==40) +#define lambda_half 20 +#define lambda_v 0.40(cif_tech) +#define scaleunit 5 +#define lambda_1 40 +#define lambda_2 80 +#define lambda_3 120 +#define lambda_4 160 +#define lambda_5 200 +#define lambda_6 240 +#define lambda_7 280 +#define lambda_8 320 +#undef pad_via2 +#undef pad_via1 +#define pad_via1 300 +#define pad_via2 200 +#define pad_glass 600 +/* for HP CMOS14B - 0.6 micron process... */ +#elif (lambda_value==35) +#define lambda_half 20 +#define lambda_v 0.35(cif_tech) +#define scaleunit 5 +#define lambda_1 35 +#define lambda_2 70 +#define lambda_3 105 +#define lambda_4 140 +#define lambda_5 175 +#define lambda_6 210 +#define lambda_7 245 +#define lambda_8 280 +#undef pad_via1 +#undef pad_via2 +#define pad_via1 300 +#define pad_via2 200 +#define pad_glass 600 +/* for HP CMOS14B - 0.6 micron process... */ +#elif (lambda_value==30) +#define lambda_half 15 +#define lambda_v 0.30(cif_tech) +#define scaleunit 15 +#define lambda_1 30 +#define lambda_2 60 +#define lambda_3 90 +#define lambda_4 120 +#define lambda_5 150 +#define lambda_6 180 +#define lambda_7 210 +#define lambda_8 240 +#undef pad_via1 +#undef pad_via2 +#define pad_via1 300 +#define pad_via2 210 +#define pad_glass 600 +/* for 0.4 micron process... */ +#elif (lambda_value==20) +#define lambda_half 10 +#define lambda_v 0.20(cif_tech) +#define scaleunit 10 +#define lambda_1 20 +#define lambda_2 40 +#define lambda_3 60 +#define lambda_4 80 +#define lambda_5 100 +#define lambda_6 120 +#define lambda_7 140 +#define lambda_8 160 +#undef pad_via1 +#undef pad_via2 +#define pad_via1 300 +#define pad_via2 300 +#define pad_glass 600 +#endif +#undef lambda_value diff --git a/scmos/cif_template/cifin-ami16.gen b/scmos/cif_template/cifin-ami16.gen new file mode 100644 index 00000000..290262cd --- /dev/null +++ b/scmos/cif_template/cifin-ami16.gen @@ -0,0 +1,268 @@ +/* available devices: + * nfet,pfet,enfet,epfet,nffet,pffet + * poly capacitor + * bipolar NPN transistor + * micro-machined devices + */ +#define cif_tech gen +style lambda=lambda_v + scalefactor lambda_1 + layer nwell CWN + labels CWN + layer pwell CWP + labels CWP + layer hnwell CVN + labels CWN + layer hpwell CVP + labels CWP + layer poly CPG + labels CPG + layer pdiff CSP + and CAA + and CWN + layer ndiff CSN + and CAA + and CWP + and-not CCD + layer nsd CWN + and CSN + and CAA + layer psd CWP + and CSP + and CAA + layer hpdiff CSP + and CAA + and CVN + layer hndiff CSN + and CAA + and CVP + layer hnsd CVN + and CSN + and CAA + layer hpsd CVP + and CSP + and CAA + layer pbase CBA + labels CBA + layer nfet CPG + and CAA + and CSN + and CWP + and-not CCD + layer pfet CAA + and CPG + and CSP + and CWN + layer hnfet CPG + and CAA + and CSN + and CVP + and-not CCD + layer hpfet CAA + and CPG + and CSP + and CVN + layer enfet CEL + and CAA + and CSN + and CWP + and-not CCD + layer epfet CAA + and CEL + and CSP + and CWN + layer nffet CEL + and CAA + and CSN + and CPG + and CWP + and-not CCD + layer pffet CAA + and CPG + and CEL + and CSP + and CWN + layer ndc CCA + grow lambda_1 + and CAA + and CWP + and CSN + and CMF + layer pdc CCA + grow lambda_1 + and CAA + and CWN + and CSP + and CMF + layer nsc CCA + grow lambda_1 + and CAA + and CSN + and CWN + and CMF + layer psc CCA + grow lambda_1 + and CAA + and CSP + and CWP + and CMF + layer hndc CCA + grow lambda_2 + and CAA + and CVP + and CSN + and CMF + layer hpdc CCA + grow lambda_2 + and CAA + and CVN + and CSP + and CMF + layer hnsc CCA + grow lambda_2 + and CAA + and CSN + and CVN + and CMF + layer hpsc CCA + grow lambda_2 + and CAA + and CSP + and CVP + and CMF + layer gc CCC + layer m2c CVA + grow lambda_1 + and CMS + and CMF + labels CMS + layer electrode CEL + labels CEL + layer ec CCE + grow lambda_1 + and CMF + and CEL + labels CMF + layer cc CCE + grow lambda_1 + and CMF + and CEL + and CPG + labels CMF + layer cap CPG + and CEL + and-not CAA + labels CEL + layer pbc CCA + grow lambda_1 + and CBA + and CMF + labels CBA + layer col CBA + grow 1600 + and-not CBA + and CX + and CAA + and CSN + and CWN + labels CAA + layer clc CBA + grow 1600 + and-not CBA + and CCA + grow lambda_1 + and CX + and CAA + and CSN + and CWN + and CMF + labels CCA + layer emit CBA + and CSN + shrink lambda_2 + labels CBA + layer emc CCA + grow lambda_1 + and CBA + and CSN + and CMF + labels CBA + layer pc CCP + grow lambda_1 + and CPG + and CMF + layer bd CAA + and CCD + and-not CSN + grow lambda_2 + and CAA + labels CCD + layer nbd CSN + shrink lambda_2 + and CCD + and CAA + labels CCD + layer nbdc CCA + grow lambda_1 + and CCD + and CSN + and CAA + labels CCD + layer glass COG +#ifdef OPEN + layer open CAA + and CCA + and CVA + and COG + and COP + layer pstop CAA + and CPS + and CSP + and-not CWP + and-not CWN +#endif + layer pad CMF + shrink lambda_1 + and CMS + shrink lambda_5 + and CVA + shrink lambda_1 + and COG + grow lambda_6 + and XP + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + + calma CVP 21 * + calma CVN 22 * +#ifdef OPEN + calma COP 23 * + calma CPS 24 * +#endif + calma CCC 25 * + calma XP 26 * + calma CWP 41 * + calma CWN 42 * + calma CAA 43 * + calma CSP 44 * + calma CSN 45 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CCE 55 * + calma CEL 56 * + calma CCD 57 * + calma CBA 58 * + calma CX 63 * +/* + calma CVS 61 * + calma CMT 62 * + */ + +#undef cif_tech diff --git a/scmos/cif_template/cifin-cmos14b.gen b/scmos/cif_template/cifin-cmos14b.gen new file mode 100644 index 00000000..04355cb1 --- /dev/null +++ b/scmos/cif_template/cifin-cmos14b.gen @@ -0,0 +1,140 @@ +/* For IBM triple metal process... No CCD, Bipolar, Poly2 layers. +/* This is prelimanary, please let me know if anything here seems + abnormal to you... pi@lepton.isi.edu 1/13/94 */ +#ifdef NOWELL +#undef cif_tech +#define cif_tech nowell +style lambda=lambda_v +#else +#undef cif_tech +#define cif_tech sub +style lambda=lambda_v +#endif + scalefactor lambda_1 +#ifndef NOWELL + layer nwell CWN + labels CWN + layer pwell CWP + labels CWP +#endif + layer m3 CMT + /* to avoid a CIF read problem around pads */ + and-not XP + labels CMT + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer ndop CSN + and-not CWP + and CAA + layer pdop CSP + and CAA + and-not CWP + and-not CPS + layer pdiff CSP + and CWN + and CAA + layer ndiff CSN + and CWP + and CAA + layer nsd CWN + and CSN + and CAA + layer psd CSP + and CWP + and CAA + layer pbase CBA + labels CBA + layer nfet CPG + and CAA + and CSN + labels CPG + layer pfet CAA + and CPG + and CSP + labels CPG + layer ndc CCA + grow lambda_1 + and CAA + and CWP + and CSN + and CMF + layer pdc CCA + grow lambda_1 + and CAA + and CWN + and CSP + and CMF + layer nsc CCA + grow lambda_1 + and CAA + and CSN + and CWN + and CMF + layer psc CCA + grow lambda_1 + and CAA + and CSP + and CWP + and CMF + layer pbc CCA + grow lambda_1 + and CBA + and CMF + labels CBA + layer m3c CVS + grow lambda_1 + and CMT + and CMS + and-not XP + layer m2c CVA + grow lambda_1 + and CMS + and CMF + layer pc CCP + grow lambda_1 + and CPG + and CMF + layer gc CCC + layer glass COG + labels COG +#ifdef OPEN + layer open CAA + and CCA + and CVA + and COG + and COP + layer pstop CAA + and CPS + and CSP + and-not CWP + and-not CWN +#endif + /* assume all contact are in place .. */ + layer pad COG + grow pad_glass + and XP + +#ifdef OPEN + calma COP 23 * + calma CPS 24 * +#endif + calma CCC 25 * + calma XP 26 * + calma CWP 41 * + calma CWN 42 * + calma CAA 43 * + calma CSP 44 * + calma CSN 45 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CVS 61 * + calma CMT 62 * diff --git a/scmos/cif_template/cifin-cmos26b.gen b/scmos/cif_template/cifin-cmos26b.gen new file mode 100644 index 00000000..f441a553 --- /dev/null +++ b/scmos/cif_template/cifin-cmos26b.gen @@ -0,0 +1,145 @@ +/* For HP CMOS26B process... No CCD, Bipolar, Poly2 layers. + Two types of pad layer are supported, one (the pad layer) + contains both metal1 and metal2 layer while the other (the + pad2 layer) contains all three metals with all necessary via + properly defined... */ +/* This is prelimanary, please let me know if anything here seems + abnormal to you... pi@lepton.isi.edu 3/15/93 */ +#ifdef NOWELL +#undef cif_tech +#define cif_tech nowell +style lambda=lambda_v +#else +#undef cif_tech +#define cif_tech sub +style lambda=lambda_v +#endif + scalefactor lambda_1 +#ifndef NOWELL + layer nwell CWN + labels CWN + layer pwell CWP + labels CWP +#endif + layer m3 CMT + /* to avoid a CIF read problem around pads */ + and-not XP + labels CMT + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer ndop CSN + and-not CWP + and CAA + layer pdop CSP + and CAA + and-not CWP + and-not CPS + layer pdiff CSP + and CWN + and CAA + layer ndiff CSN + and CWP + and CAA + layer nsd CWN + and CSN + and CAA + layer psd CSP + and CWP + and CAA + layer pbase CBA + labels CBA + layer nfet CPG + and CAA + and CSN + labels CPG + layer pfet CAA + and CPG + and CSP + labels CPG + layer ndc CCA + grow lambda_1 + and CAA + and CWP + and CSN + and CMF + layer pdc CCA + grow lambda_1 + and CAA + and CWN + and CSP + and CMF + layer nsc CCA + grow lambda_1 + and CAA + and CSN + and CWN + and CMF + layer psc CCA + grow lambda_1 + and CAA + and CSP + and CWP + and CMF + layer pbc CCA + grow lambda_1 + and CBA + and CMF + labels CBA + layer m3c CVS + grow lambda_1 + and CMT + and CMS + and-not XP + layer m2c CVA + grow lambda_1 + and CMS + and CMF + layer pc CCP + grow lambda_1 + and CPG + and CMF + layer gc CCC + layer glass COG + labels COG +#ifdef OPEN + layer open CAA + and CCA + and CVA + and COG + and COP + layer pstop CAA + and CPS + and CSP + and-not CWP + and-not CWN +#endif + /* assume all contact are in place .. */ + layer pad COG + grow pad_glass + and XP + +#ifdef OPEN + calma COP 23 * + calma CPS 24 * +#endif + calma CCC 25 * + calma XP 26 * + calma CWP 41 * + calma CWN 42 * + calma CAA 43 * + calma CSP 44 * + calma CSN 45 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CVS 61 * + calma CMT 62 * + diff --git a/scmos/cif_template/cifin-cmos26g.gen b/scmos/cif_template/cifin-cmos26g.gen new file mode 100644 index 00000000..b0835acd --- /dev/null +++ b/scmos/cif_template/cifin-cmos26g.gen @@ -0,0 +1,143 @@ +/* For HP CMOS26B process... No CCD, Bipolar, Poly2 layers. + Two types of pad layer are supported, one (the pad layer) + contains both metal1 and metal2 layer while the other (the + pad2 layer) contains all three metals with all necessary via + properly defined... */ +/* This is prelimanary, please let me know if anything here seems + abnormal to you... pi@lepton.isi.edu 3/15/93 */ +#ifdef NOWELL +#undef cif_tech +#define cif_tech nowell +style lambda=lambda_v +#else +#undef cif_tech +#define cif_tech sub +style lambda=lambda_v +#endif + scalefactor lambda_1 +#ifndef NOWELL + layer nwell CWN + labels CWN + layer pwell CWP + labels CWP +#endif + layer m3 CMT + /* to avoid a CIF read problem around pads */ + and-not XP + labels CMT + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer ndop CSN + and-not CWP + and CAA + layer pdop CSP + and CAA + and-not CWP + and-not CPS + layer pdiff CSP + and CWN + and CAA + layer ndiff CSN + and CWP + and CAA + layer nsd CWN + and CSN + and CAA + layer psd CSP + and CWP + and CAA + layer pbase CBA + labels CBA + layer nfet CPG + and CAA + and CSN + labels CPG + layer pfet CAA + and CPG + and CSP + labels CPG + layer ndc CCA + grow lambda_1 + and CAA + and CWP + and CSN + and CMF + layer pdc CCA + grow lambda_1 + and CAA + and CWN + and CSP + and CMF + layer nsc CCA + grow lambda_1 + and CAA + and CSN + and CWN + and CMF + layer psc CCA + grow lambda_1 + and CAA + and CSP + and CWP + and CMF + layer pbc CCA + grow lambda_1 + and CBA + and CMF + labels CBA + layer m3c CVS + grow lambda_1 + and CMT + and CMS + and-not XP + layer m2c CVA + grow lambda_1 + and CMS + and CMF + layer pc CCP + grow lambda_1 + and CPG + and CMF + layer gc CCC + layer glass COG + labels COG +#ifdef OPEN + layer open CAA + and CCA + and CVA + and COG + and COP + layer pstop CAA + and CPS + and CSP + and-not CWP + and-not CWN +#endif + /* assume all contact are in place .. */ + layer pad COG + grow pad_glass + and XP + +#ifdef OPEN + calma COP 23 * + calma CPS 24 * +#endif + calma CWP 41 * + calma CWN 42 * + calma CAA 43 * + calma CSP 44 * + calma CSN 45 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CVS 61 * + calma CMT 62 * + calma CCC 63 * diff --git a/scmos/cif_template/cifin-cmosn.gen b/scmos/cif_template/cifin-cmosn.gen new file mode 100644 index 00000000..f4e1163d --- /dev/null +++ b/scmos/cif_template/cifin-cmosn.gen @@ -0,0 +1,89 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor + micro-machined devices +*/ +#define cif_tech cmosn +style lambda=lambda_v + scalefactor lambda_1 + layer nwell NWN + labels NWN + layer pwell NWP + labels NWP + layer m2 NMS + labels NMS + layer m1 NMF + labels NMF + layer poly NPG + labels NPG + layer pdiff NSP + and NAA + and NWN + layer ndiff NSN + and NAA + layer nsd NWN + and NSN + and NAA + layer psd NSP + and NAA + and-not NWN + layer nfet NPG + and NAA + and NSN + layer pfet NAA + and NPG + and NSP + layer enfet NEL + and NAA + and NSN + layer epfet NAA + and NEL + and NSP + layer electrode NEL + labels NEL + layer cap NPG + and NEL + and-not NAA + labels NEL + layer gc NCT + layer m2c NVA + and NMS + and NMF + labels NMS + layer open NAA + and NCT + and NVA + and NOG + and NOP + layer pstop NAA + and NPS + and NSP + and-not NWP + and-not NWN + layer pad NMF + shrink lambda_1 + and NMS + shrink lambda_5 + and NVA + shrink lambda_1 + and NOG + grow lambda_6 + and XP + + calma NWN 1 * + calma NWP 2 * + calma NAA 3 * + calma NPG 4 * + calma NEL 5 * + calma NSN 7 * + calma NSP 8 * + calma NCT 9 * + calma NMF 10 * + calma NVA 11 * + calma NMS 12 * + calma NOG 13 * + +#undef cif_tech diff --git a/scmos/cif_template/cifin-cmosn.nw b/scmos/cif_template/cifin-cmosn.nw new file mode 100644 index 00000000..496d9b8c --- /dev/null +++ b/scmos/cif_template/cifin-cmosn.nw @@ -0,0 +1,128 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor +*/ +#define cif_tech cmosn +style lambda=lambda_v + scalefactor lambda_1 + layer nwell CWN + labels CWN + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer psd CAA + and CSP + layer pdiff CWN + and CAA + and CSP + labels CSP + layer ndiff CAA + and CSN + labels CSN + layer nsd CWN + and CSN + and CAA + layer nfet CPG + and CAA + and CSN + layer pfet CAA + and CPG + and CSP + and CWN + layer enfet CEL + and CAA + and CSN + layer epfet CAA + and CEL + and CSP + and CWN + layer nffet CAA + and CEL + and CPG + and CSN + layer pffet CAA + and CEL + and CPG + and CSP + and CWN + layer m2c CVA + grow lambda_1 + and CMS + and CMF + layer electrode CEL + labels CEL + layer ec CCC + grow lambda_1 + and CMF + and CEL + layer cc CCC + grow lambda_1 + and CMF + and CEL + and CPG + labels CCC + layer cap CPG + and CEL + and-not CAA + layer psc CCC + grow lambda_1 + and CAA + and CSP + and CMF + layer ndc CCC + grow lambda_1 + and CAA + and CSN + and CMF + layer pdc CCC + grow lambda_1 + and CAA + and CWN + and CSP + and CMF + layer nsc CCC + grow lambda_1 + and CAA + and CSN + and CWN + and CMF + layer pbc CCC + grow lambda_1 + and CBA + and CMF + layer pc CCC + grow lambda_1 + and CPG + and CMF + labels CCC + layer glass COG + labels COG + layer pad CMF + shrink lambda_1 + and CMS + shrink lambda_5 + and CVA + shrink lambda_1 + and COG + grow lambda_6 + and XP + + calma CWN 1 * + calma CAA 3 * + calma CSP 8 * + calma CSN 7 * + calma CPG 4 * + calma CCC 9 * + calma CMF 10 * + calma CVA 11 * + calma CMS 12 * + calma COG 13 * + calma CEL 5 * + +#undef cif_tech diff --git a/scmos/cif_template/cifin-cmosx.gen b/scmos/cif_template/cifin-cmosx.gen new file mode 100644 index 00000000..2f585315 --- /dev/null +++ b/scmos/cif_template/cifin-cmosx.gen @@ -0,0 +1,135 @@ +/* For IBM triple metal process... No CCD, Bipolar, Poly2 layers. +/* This is prelimanary, please let me know if anything here seems + abnormal to you... pi@lepton.isi.edu 3/14/95 */ +#ifdef NOWELL +style lambda=0.4(cmosx-nowell) +#else +style lambda=0.4(cmosx) +#endif + scalefactor lambda_1 +#ifndef NOWELL + layer nwell CWN + labels CWN + layer pwell CWP + labels CWN +#endif + layer m3 CMT + /* to avoid a CIF read problem around pads */ + and-not XP + labels CMT + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer ndop CSN + and-not CWP + and CAA + layer pdop CSP + and CAA + and-not CWP + and-not CPS + layer pdiff CSP + and CWN + and CAA + layer ndiff CSN + and CWP + and CAA + layer nsd CWN + and CSN + and CAA + layer psd CSP + and CWP + and CAA + layer pbase CBA + labels CBA + layer nfet CPG + and CAA + and CSN + labels CPG + layer pfet CAA + and CPG + and CSP + labels CPG + layer ndc CCA + grow lambda_1 + and CAA + and CWP + and CSN + and CMF + layer pdc CCA + grow lambda_1 + and CAA + and CWN + and CSP + and CMF + layer nsc CCA + grow lambda_1 + and CAA + and CSN + and CWN + and CMF + layer psc CCA + grow lambda_1 + and CAA + and CSP + and CWP + and CMF + layer pbc CCA + grow lambda_1 + and CBA + and CMF + labels CBA + layer m3c CVS + grow lambda_1 + and CMT + and CMS + and-not XP + layer m2c CVA + grow lambda_1 + and CMS + and CMF + layer pc CCA + grow lambda_1 + and CPG + and CMF + layer gc CCC + layer glass COG + labels COG +#ifdef OPEN + layer open CAA + and CCA + and CVA + and COG + and COP + layer pstop CAA + and CPS + and CSP + and-not CWP + and-not CWN +#endif + /* assume all contact are in place .. */ + layer pad CMF + shrink 100 + and CMS + shrink 100 + and CMT + shrink 500 + and COG + grow 500 + and XP + + calma CWN 1 * + calma CWP 2 * + calma CAA 3 * + calma CPG 4 * + calma CSN 7 * + calma CSP 8 * + calma CCA 9 * + calma CMF 10 * + calma CVA 11 * + calma CMS 12 * + calma COG 13 * + calma CVS 14 * + calma CMT 15 * diff --git a/scmos/cif_template/cifin-hp-cif.nw b/scmos/cif_template/cifin-hp-cif.nw new file mode 100644 index 00000000..1b605134 --- /dev/null +++ b/scmos/cif_template/cifin-hp-cif.nw @@ -0,0 +1,62 @@ +/* available devices: + nfet,pfet +*/ +#define cif_tech hp +style lambda=lambda_v + scalefactor lambda_1 + layer nwell CWN + labels CWN + layer m3 CMT + labels CMT + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer psd CSP + and-not CWN + layer pdiff CWN + and CSP + labels CSP + layer ndiff CSN + and-not CWN + labels CSN + layer nsd CWN + and CSN + layer nfet CPG + and CSN + and-not CWN + layer pfet CPG + and CSP + and CWN + layer m3c CVS + labels CVS + layer m2c CVA + labels CVA + layer gc CCA + labels CCA + layer glass COG + labels COG + layer pad CMF + shrink lambda_1 + and CMS + shrink lambda_5 + and CVA + shrink lambda_1 + and COG + grow lambda_6 + + calma CWN 1 * + calma CPG 4 * + calma CCA 8 * + calma CMF 9 * + calma CVA 10 * + calma CMS 11 * + calma CVS 12 * + calma CMT 13 * + calma COG 14 * + calma CSN 21 * + calma CSP 22 * + +#undef cif_tech diff --git a/scmos/cif_template/cifin-hp.nw b/scmos/cif_template/cifin-hp.nw new file mode 100644 index 00000000..98c96227 --- /dev/null +++ b/scmos/cif_template/cifin-hp.nw @@ -0,0 +1,90 @@ +/* available devices: + nfet,pfet +*/ +#define cif_tech hp +style lambda=lambda_v + scalefactor lambda_1 + layer nwell CWN + labels CWN + layer m3 CMT + labels CMT + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer psd CSP + and-not CWN + layer pdiff CWN + and CSP + labels CSP + layer ndiff CSN + and-not CWN + labels CSN + layer nsd CWN + and CSN + layer nfet CPG + and CSN + and-not CWN + layer pfet CPG + and CSP + and CWN + layer m3c CVS + grow lambda_1 + and CMT + and CMS + layer m2c CVA + grow lambda_1 + and CMS + and CMF + layer psc CCA + grow lambda_1 + and-not CWN + and CSP + and CMF + layer ndc CCA + grow lambda_1 + and-not CWN + and CSN + and CMF + layer pdc CCA + grow lambda_1 + and CAA + and CWN + and CSP + and CMF + layer nsc CCA + grow lambda_1 + and CSN + and CWN + and CMF + layer pc CCA + grow lambda_1 + and CPG + and CMF + labels CPG + layer glass COG + labels COG + layer pad CMF + shrink lambda_1 + and CMS + shrink lambda_5 + and CVA + shrink lambda_1 + and COG + grow lambda_6 + + calma CWN 1 * + calma CPG 4 * + calma CCA 8 * + calma CMF 9 * + calma CVA 10 * + calma CMS 11 * + calma CVS 12 * + calma CMT 13 * + calma COG 14 * + calma CSN 21 * + calma CSP 22 * + +#undef cif_tech diff --git a/scmos/cif_template/cifin-ibm.gen b/scmos/cif_template/cifin-ibm.gen new file mode 100644 index 00000000..4bcc0945 --- /dev/null +++ b/scmos/cif_template/cifin-ibm.gen @@ -0,0 +1,139 @@ +/* For IBM triple metal process... No CCD, Bipolar, Poly2 layers. +/* This is prelimanary, please let me know if anything here seems + abnormal to you... pi@lepton.isi.edu 1/13/94 */ +#ifdef NOWELL +style lambda=0.4(nowell) +#else +style lambda=0.4(ibm) +#endif + scalefactor lambda_1 +#ifndef NOWELL + layer nwell CWN + labels CWN +#endif + layer m3 CMT + /* to avoid a CIF read problem around pads */ + and-not XP + labels CMT + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer ndop CSN + and-not CWP + and CAA + layer pdop CSP + and CAA + and-not CWP + and-not CPS + layer pdiff CSP + and CWN + and CAA + layer ndiff CSN + and CWP + and CAA + layer nsd CWN + and CSN + and CAA + layer psd CSP + and CWP + and CAA + layer pbase CBA + labels CBA + layer nfet CPG + and CAA + and CSN + labels CPG + layer pfet CAA + and CPG + and CSP + labels CPG + layer ndc CCA + grow 50 + and CAA + and CWP + and CSN + and CMF + layer pdc CCA + grow 50 + and CAA + and CWN + and CSP + and CMF + layer nsc CCA + grow 50 + and CAA + and CSN + and CWN + and CMF + layer psc CCA + grow 50 + and CAA + and CSP + and CWP + and CMF + layer pbc CCA + grow 50 + and CBA + and CMF + labels CBA + layer m3c CVS + grow 50 + and CMT + and CMS + and-not XP + layer m2c CVA + grow 50 + and CMS + and CMF + layer pc CCP + grow 50 + and CPG + and CMF + layer gc CCC + layer glass COG + labels COG +#ifdef OPEN + layer open CAA + and CCA + and CVA + and COG + and COP + layer pstop CAA + and CPS + and CSP + and-not CWP + and-not CWN +#endif + /* assume all contact are in place .. */ + layer pad CMF + shrink 100 + and CMS + shrink 100 + and CMT + shrink 500 + and COG + grow 500 + and XP + +#ifdef OPEN + calma COP 23 * + calma CPS 24 * +#endif + calma CWP 41 * + calma CWN 42 * + calma CAA 43 * + calma CSP 44 * + calma CSN 45 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CVS 61 * + calma CMT 62 * + calma CCC 63 * diff --git a/scmos/cif_template/cifin.c b/scmos/cif_template/cifin.c new file mode 100644 index 00000000..6f386b6a --- /dev/null +++ b/scmos/cif_template/cifin.c @@ -0,0 +1,142 @@ +#ifdef STANDARD + +/* 3.0 micron technology - not supported anymore +#define lambda_value 150 +#include "calc.lambda" +#include "cifin.gen" +#include "cifin.nw" +#include "cifin.oldnw" +#include "cifin.pw" +*/ + +/* ORBIT 2.0 micron technology */ +#define lambda_value 100 +#include "calc.lambda" +#include "cifin.gen" +#include "cifin.nw" +#include "cifin.oldnw" +#include "cifin.pw" +#define NOWELL +#include "cifin.gen" +#undef NOWELL + +/* ORBIT 1.6 micron technology - not supported, but retained for ORBIT */ +#define lambda_value 80 +#include "calc.lambda" +#include "cifin-ami16.gen" +#include "cifin.nw" +#include "cifin.oldnw" +#include "cifin.pw" +#define NOWELL +#include "cifin.gen" +#undef NOWELL + +/* 1.2 micron technology */ +#define lambda_value 60 +#include "calc.lambda" +#include "cifin.gen" +#include "cifin.nw" +#include "cifin.oldnw" +#include "cifin.pw" +#define NOWELL +#include "cifin.gen" +#undef NOWELL + +/* 1.2 micron technology - for Mentor Graphics CMOSN technology */ + +#define lambda_value 100 +#include "calc.lambda" +#include "cifin-cmosn.gen" + + +/* all other technology */ +/* +#include "cifin.others" +*/ + +#endif /* Standard SCMOS technologies */ + +#ifdef TIGHTMETAL + +/* HP CMOS34 1.2 micron technology */ +#define lambda_value 60 +#include "calc.lambda" +#include "cifin.gen" +#include "cifin.nw" +#include "cifin.oldnw" +#define NOWELL +#include "cifin.gen" +#undef NOWELL + +/* HP CMOS26B 1.0 micron technology */ +#define lambda_value 50 +#include "calc.lambda" +#include "cifin-cmos26b.gen" +#include "cifin.nw" +#include "cifin.oldnw" +#define NOWELL +#include "cifin-cmos26b.gen" +#undef NOWELL + +/* HP CMOS14B 0.6 micron technology */ +#define lambda_value 35 +#include "calc.lambda" +#include "cifin-cmos14b.gen" + +/* read HP's layer assignment from Mentor */ +/* +#define lambda_value 20 +#include "calc.lambda" +#include "cifin-hp-cif.nw" +*/ + +/* This is just testing... +#define lambda_value 20 +#include "calc.lambda" +#include "cifin.cascade" +*/ + +#endif /* Tight Metal Technologies ends here .... */ + +#ifdef SUBMICRON + +/* HP CMOS26G 0.8 micron technology */ +#define lambda_value 40 +#include "calc.lambda" +#include "cifin-cmos26g.gen" +#define NOWELL +#include "cifin-cmos26g.gen" +#undef NOWELL +#include "cifin.nw" + +/* HP CMOS14B 0.6 micron technology */ +#define lambda_value 30 +#include "calc.lambda" +#include "cifin-cmos14b.gen" +#define NOWELL +#include "cifin-cmos14b.gen" +#undef NOWELL + +/* 0.8 micron CMOSX technology */ +/* +#define lambda_value 40 +#include "calc.lambda" +#include "cifin-cmosx.gen" +#define NOWELL +#include "cifin-cmosx.gen" +#undef NOWELL +*/ + +#endif /* HP CMOS26G and CMOS14B process */ + + +#ifdef IBM /* IBM */ +/* 0.8 micron technology */ +#define lambda_value 40 +#include "calc.lambda" +#include "cifin-ibm.gen" +#define NOWELL +#include "cifin-ibm.gen" +#include "cifin.nw" +#undef NOWELL +#endif /* IBM */ diff --git a/scmos/cif_template/cifin.cascade b/scmos/cif_template/cifin.cascade new file mode 100644 index 00000000..101742d1 --- /dev/null +++ b/scmos/cif_template/cifin.cascade @@ -0,0 +1,91 @@ +/* + For CIF file generated by CASCADE's Epoch... +*/ +#define cif_tech cascade +style lambda=lambda_v + scalefactor lambda_1 + layer nwell CNW + labels CNW + layer pwell CPW + labels CPW + layer m2 CM2 + labels CM2 + layer m1 CM + labels CM + layer poly CP + labels CP + layer pdiff CPP + and CD + and CNW + layer ndiff CNP + and CD + and CPW + layer nsd CNW + and CNP + and CD + layer psd CPW + and CPP + and CD + layer nfet CP + and CD + and CNP + layer pfet CD + and CP + and CPP + layer ndc CC + grow lambda_1 + and CD + and CPW + and CNP + and CM + layer pdc CC + grow lambda_1 + and CD + and CNW + and CPP + and CM + layer nsc CC + grow lambda_1 + and CD + and CNP + and CNW + and CM + layer psc CC + grow lambda_1 + and CD + and CPP + and CPW + and CM + layer m2c CV + grow lambda_1 + and CM2 + and CM + labels CM2 + layer pc CC + grow lambda_1 + and CP + and CM + layer glass CG + layer pad CM + shrink lambda_1 + and CM2 + shrink lambda_5 + and CV + shrink lambda_1 + and CG + grow lambda_6 + + + calma CNW 1 * + calma CPW 2 * + calma CD 3 * + calma CP 4 * + calma CPP 31 * + calma CNP 32 * + calma CC 9 * + calma CM 10 * + calma CV 11 * + calma CM2 12 * + calma CG 13 * + +#undef cif_tech diff --git a/scmos/cif_template/cifin.gen b/scmos/cif_template/cifin.gen new file mode 100644 index 00000000..30d3d94c --- /dev/null +++ b/scmos/cif_template/cifin.gen @@ -0,0 +1,227 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor + micro-machined devices + metal3 and via2 +*/ +#ifndef NOWELL +#define cif_tech gen +#else +#define cif_tech nowell +#endif +style lambda=lambda_v + scalefactor lambda_1 +#ifndef NOWELL + layer nwell CWN + labels CWN + layer pwell CWP + labels CWP +#endif + layer poly CPG + labels CPG + layer pdiff CSP + and CAA + and CWN + layer ndiff CWP + or CWC + and CAA + and CSN + and-not CCD + layer nsd CWN + and CSN + and CAA + layer psd CWP + and CSP + and CAA + layer pbase CBA + labels CBA + layer nfet CPG + and CAA + and CSN + and-not CCD + layer pfet CAA + and CPG + and CSP + layer enfet CEL + and CAA + and CSN + and-not CCD + layer epfet CAA + and CEL + and CSP + layer nffet CAA + and CEL + and CPG + and CSN + and CWP + layer pffet CAA + and CEL + and CPG + and CSP + and CWN + layer ndc CWP + or CWC + and CCA + grow lambda_1 + and CAA + and CSN + and CMF + layer pdc CCA + grow lambda_1 + and CAA + and CWN + and CSP + and CMF + layer nsc CCA + grow lambda_1 + and CAA + and CSN + and CWN + and CMF + layer psc CCA + grow lambda_1 + and CAA + and CSP + and CWP + and CMF + layer gc CCC + layer m2c CVA + grow lambda_1 + and CMS + and CMF + labels CMS + layer m3c CVS + grow lambda_1 + and CMT + and CMS + and-not XP + layer electrode CEL + labels CEL + layer ec CCE + grow lambda_1 + and CMF + and CEL + labels CMF + layer cc CCE + grow lambda_1 + and CMF + and CEL + and CPG + labels CMF + layer cap CPG + and CEL + and-not CAA + labels CEL + layer pbc CCA + grow lambda_1 + and CBA + and CMF + labels CBA + layer col CX + and CAA + and CSN + and CWN + labels CAA + layer clc CCA + grow lambda_1 + and CX + and CAA + and CSN + and CWN + and CMF + labels CCA + layer emit CBA + and CSN + shrink lambda_2 + labels CBA + layer emc CCA + grow lambda_1 + and CBA + and CSN + and CMF + labels CBA + layer pc CCP + grow lambda_1 + and CPG + and CMF + layer nbd CSN + shrink lambda_2 + and CCD + and CAA + and-not CPG + layer nbdc CCA + grow lambda_1 + and CCD + and CSN + and CAA + layer bd CPG + or CEL + and CCD + and CAA + labels CCD + /* place the Cap well at the end, so that we can read linear */ + /* capacitor correctly... */ + layer cwell CWC + labels CWC + layer glass COG +#ifdef OPEN + layer open CAA + and CCA + and CVA + and COG + and COP + layer pstop CAA + and CPS + and CSP + and-not CWP + and-not CWN +#endif + layer pad CMF + shrink lambda_1 + and CMS + shrink lambda_5 + and CVA + shrink lambda_1 + and XP + and COG + grow lambda_6 + layer m1 CMF + labels CMF + layer m2 CMS + labels CMS + layer m3 CMT + /* to avoid a CIF read problem around pads */ + and-not XP + labels CMT + +#ifdef OPEN + calma COP 23 * + calma CPS 24 * +#endif + calma CCC 25 * + calma XP 26 * + calma CWP 41 * + calma CWN 42 * + calma CAA 43 * + calma CSP 44 * + calma CSN 45 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CCE 55 * + calma CEL 56 * + calma CCD 57 * + calma CBA 58 * + calma CWC 59 * + calma CVS 61 * + calma CMT 62 * + calma CX 63 * + +#undef cif_tech diff --git a/scmos/cif_template/cifin.nw b/scmos/cif_template/cifin.nw new file mode 100644 index 00000000..4272419b --- /dev/null +++ b/scmos/cif_template/cifin.nw @@ -0,0 +1,212 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor +*/ +#undef cif_tech +#define cif_tech nwell +style lambda=lambda_v + scalefactor lambda_1 + layer nwell CWN + labels CWN + layer m3 CMT + /* to avoid a CIF read problem around pads */ + and-not XP + labels CMT + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer psd CAA + and CSP + and-not CPS + layer pdiff CWN + and CAA + and CSP + labels CSP + layer ndiff CAA + and CSN + and-not CCD + labels CSN + layer nsd CWN + and CSN + and CAA + layer pbase CBA + labels CBA + layer nfet CPG + and CAA + and CSN + and-not CCD + layer pfet CAA + and CPG + and CSP + and CWN + layer enfet CEL + and CAA + and CSN + and-not CCD + layer epfet CAA + and CEL + and CSP + and CWN + layer nffet CAA + and CEL + and CPG + and CSN + layer pffet CAA + and CEL + and CPG + and CSP + and CWN + layer m3c CVS + grow lambda_1 + and CMT + and CMS + and-not XP + layer m2c CVA + grow lambda_1 + and CMS + and CMF + layer electrode CEL + labels CEL + layer ec CCE + or CCC + grow lambda_1 + and CMF + and CEL + layer cc CCE + grow lambda_1 + and CMF + and CEL + and CPG + labels CCE + layer cap CPG + and CEL + and-not CAA + layer psc CCA + grow lambda_1 + and CAA + and CSP + and CMF + layer ndc CCA + or CCC + grow lambda_1 + and CAA + and CSN + and CMF + layer pdc CCA + or CCC + grow lambda_1 + and CAA + and CWN + and CSP + and CMF + layer nsc CCA + or CCC + grow lambda_1 + and CAA + and CSN + and CWN + and CMF + layer pbc CCA + or CCC + grow lambda_1 + and CBA + and CMF + layer emit CBA + and CSN + shrink lambda_2 + layer emc CCA + grow lambda_1 + and CBA + and CSN + and CMF + layer col CX + and CAA + and CSN + and CWN + layer clc CCA + grow lambda_1 + and CX + and CAA + and CSN + and CWN + and CMF + layer pc CCP + or CCC + grow lambda_1 + and CPG + and CMF + labels CCP + layer nbd CSN + shrink lambda_2 + and CCD + and CAA + and-not CPG + layer nbdc CCA + grow lambda_1 + and CCD + and CSN + and CAA + layer bd CPG + or CEL + and CCD + and CAA + labels CCD + /* place the Cap well at the end, so that we can read linear */ + /* capacitor correctly... */ + layer cwell CWC + labels CWC + layer glass COG + labels COG +#ifdef OPEN + layer open CAA + and CCA + and CVA + and COG + and COP + layer pstop CAA + and CPS + and CSP + and-not CWN +#endif + layer pad CMF + shrink lambda_1 + and CMS + shrink lambda_5 + and CVA + shrink lambda_1 + and XP + and COG + grow lambda_6 + +#ifdef OPEN + calma COP 23 * + calma CPS 24 * +#endif + calma XP 26 * + calma CWN 42 * + calma CAA 43 * + calma CSP 44 * + calma CSN 45 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CCE 55 * + calma CEL 56 * + calma CCD 57 * + calma CBA 58 * + calma CWC 59 * + calma CVS 61 * + calma CMT 62 * + calma CX 63 * + +#undef cif_tech diff --git a/scmos/cif_template/cifin.oldnw b/scmos/cif_template/cifin.oldnw new file mode 100644 index 00000000..1f42935a --- /dev/null +++ b/scmos/cif_template/cifin.oldnw @@ -0,0 +1,178 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor +*/ +#define cif_tech oldnwell +style lambda=lambda_v + scalefactor lambda_1 + layer cwell CWC + layer nwell CWN + labels CWN + layer m3 CMT + /* to avoid a CIF read problem around pads */ + and-not XP + labels CMT + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer psd CAA + layer pdiff CWN + and CAA + layer ndiff CAA + and CSN + and-not CCD + layer nsd CWN + and CSN + and CAA + layer pbase CBA + labels CBA + layer nfet CPG + and CAA + and CSN + and-not CCD + layer pfet CAA + and CPG + and CWN + layer enfet CEL + and CAA + and CSN + and-not CCD + layer epfet CAA + and CEL + and CWN + layer nffet CAA + and CEL + and CPG + and CSN + labels CEL + layer pffet CAA + and CEL + and CPG + and CWN + labels CEL + layer m2c CVA + grow 150 + shrink 50 + and CMS + and CMF + layer electrode CEL + labels CEL + layer ec CCE + grow lambda_1 + and CMF + and CEL + layer cc CCE + grow lambda_1 + and CMF + and CEL + and CPG + layer cap CPG + and CEL + and-not CAA + labels CEL + layer psc CCA + grow lambda_1 + and CAA + and CMF + layer ndc CCA + grow lambda_1 + and CAA + and CSN + and CMF + layer pdc CCA + grow lambda_1 + and CAA + and CWN + and CMF + layer nsc CCA + grow lambda_1 + and CAA + and CSN + and CWN + and CMF + layer m3c CVS + grow lambda_1 + and CMT + and CMS + and-not XP + layer gc CCC + layer pbc CCA + grow lambda_1 + and CBA + and CMF + layer col CX + and CAA + and CSN + and CWN + labels CAA + layer clc CCA + grow lambda_1 + and CX + and CAA + and CSN + and CWN + and CMF + labels CCA + layer emit CBA + and CSN + shrink lambda_2 + layer emc CCA + grow lambda_1 + and CBA + and CSN + and CMF + layer pc CCP + grow lambda_1 + and CPG + and CMF + layer nbd CSN + shrink lambda_2 + and CCD + and CAA + and-not CPG + layer nbdc CCA + grow lambda_1 + and CCD + and CSN + and CAA + layer bd CPG + or CEL + and CCD + and CAA + labels CCD + layer glass COG + layer pad CMF + shrink lambda_1 + and CMS + shrink lambda_5 + and CVA + shrink lambda_1 + and COG + grow lambda_6 + and XP + + calma CWN 42 * + calma CAA 43 * + /* NO CSP layer for old style of CIF files */ + calma CSN 45 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CCE 55 * + calma CEL 56 * + calma CCD 57 * + calma CBA 58 * + calma CWC 59 * + calma CX 60 * + +#undef cif_tech diff --git a/scmos/cif_template/cifin.others b/scmos/cif_template/cifin.others new file mode 100644 index 00000000..c03e03ff --- /dev/null +++ b/scmos/cif_template/cifin.others @@ -0,0 +1,575 @@ +/* There is a need to read layouts in SCGA CIF lsyrs. This input + * style is a first-order approximation. I've try this only on a + * single example You maight have problems with some of the new DRC + * rules. Both NPN transistors and BCCD devices are NOT included... + */ +style lambda=1.0(SCGA) + scalefactor 100 + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer psd + and CAA + and-not CWG + and-not CSG + layer nsd CAA + and CWG + layer pdiff CAA + and-not CSG + and CWG + layer ndiff CSG + and CAA + and-not CWG + and-not CCD + layer pbase CBA + labels CBA + layer nfet CPG + and CAA + and CSG + and-not CWG + and-not CCD + layer pfet CPG + and CAA + and CWG + layer enfet CEL + and CAA + and CSG + and-not CWG + and-not CCD + layer epfet CEL + and CAA + and CWG + layer psc CCA + grow 100 + and CAA + and-not CWG + and CMF + layer nsc CCA + grow 100 + and CAA + and CWG + and CMF + layer ndc CCA + grow 100 + and CAA + and CSG + and-not CWG + and CMF + layer pdc CCA + grow 100 + and CAA + and CWG + and-not CSG + and CMF + layer m2c CVA + grow 150 + shrink 50 + and CMS + and CMF + labels CMS + layer electrode CEL + labels CEL + layer ec CCE + grow 100 + and CMF + and CEL + labels CMF + layer cc CCE + grow 100 + and CMF + and CEL + and CPG + labels CMF + layer cap CPG + and CEL + and-not CAA + labels CEL + layer pc CCP + grow 100 + and CPG + and CMF +/* layer pbc CCA + grow 100 + and CBA + and CMF + labels CBA + layer col CX + and CAA + and CSN + and CWN + labels CAA + layer clc CCA + grow 100 + and CX + and CAA + and CSN + and CWN + and CMF + labels CCA + layer emit CBA + and CSN + shrink 200 + labels CBA + layer emc CCA + grow 100 + and CBA + and CSN + and CMF + labels CBA + layer nbd CSN + shrink 200 + and CCD + and CAA + and-not CPG + layer nbdc CCA + grow 100 + and CCD + and CSN + and CAA + layer bd CPG + or CEL + and CCD + and CAA + labels CCD +*/ + layer glass COG + layer pad CMF + shrink 100 + and CMS + shrink 500 + and CVA + shrink 100 + and COG + grow 600 + and XP + calma CWG 53 * + calma CAA 43 * + calma CSG 54 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CCE 55 * + calma CEL 56 * + calma CCD 57 * + calma CBA 58 * + +style cbpm3u + scalefactor 50 + layer pwell CW + labels CW + layer m2 CM2,CQ + labels CM2,CQ + layer m1 CM + labels CM + layer poly CP + labels CP + layer nsd CD + and CNS + layer ndiff CD + and CW + and CNS + layer pdiff CD + and CS + layer psd CW + and CS + and CD + layer pfet CP + and CD + and CS + layer nfet CD + and CP + and CW + and CNS + layer m2c CC2,CV + grow 150 + and CM2,CQ + and CM + layer pc CC + grow 150 + and CP + and CM + layer nsc CC + grow 150 + and CD + and CNS + and CM + layer pdc CC + grow 150 + and CD + and CS + and CM + layer ndc CC + grow 150 + and CD + and CW + and CM + and CNS + layer psc CC + grow 150 + and CD + and CS + and CW + and CM + layer glass CG + layer pad CM + and CM2,CQ + shrink 500 + and CC2,CV + and CG + grow 500 + calma CW 1 * + calma CD 3 * + calma CP 4 * + calma CS 5 * + calma CNS 6 * + calma CC 7 * + calma CM 8 * + calma CG 9 * + calma CV 13 * + calma CQ 14 * + +style oldcbpm3u + scalefactor 50 + layer pwell CW + labels CW + layer m2 CM2,CQ + labels CM2,CQ + layer m1 CM + labels CM + layer poly CP + labels CP + layer nsd CD + layer ndiff CD + and CW + layer pdiff CD + and CS + layer psd CW + and CS + and CD + layer pfet CP + and CD + and CS + layer nfet CD + and CP + and CW + layer m2c CC2,CV + grow 150 + and CM2,CQ + and CM + layer pc CC + grow 150 + and CP + and CM + layer nsc CC + grow 150 + and CD + and CM + layer pdc CC + grow 150 + and CD + and CS + and CM + layer ndc CC + grow 150 + and CD + and CW + and CM + layer psc CC + grow 150 + and CD + and CS + and CW + and CM + layer glass CG + layer pad CM + and CM2,CQ + shrink 500 + and CC2,CV + and CG + grow 500 + calma CW 1 * + calma CD 3 * + calma CP 4 * + calma CS 5 * + calma CC 7 * + calma CM 8 * + calma CG 9 * + calma CV 13 * + calma CQ 14 * + +style oldcbpe2u + scalefactor 100 + layer pwell CW + labels CW + layer m2 CM2,CQ + labels CM2,CQ + layer m1 CM + labels CM + layer poly CP + labels CP + layer nsd CD + layer ndiff CD + and CW + layer pdiff CD + and CS + layer psd CW + and CS + and CD + layer pfet CP + and CD + and CS + layer nfet CD + and CP + and CW + layer m2c CC2,CV + grow 150 + and CM2,CQ + and CM + layer electrode CE + labels CE + layer pc CC + grow 150 + and CP + and CM + layer capc CC + grow 150 + and CE + and CM + layer nsc CC + grow 150 + and CD + and CM + layer pdc CC + grow 150 + and CD + and CS + and CM + layer ndc CC + grow 150 + and CD + and CW + and CM + layer psc CC + grow 150 + and CD + and CS + and CW + and CM + layer glass CG + layer pad CM + and CM2,CQ + shrink 500 + and CC2,CV + and CG + grow 500 + calma CW 1 * + calma CD 3 * + calma CP 4 * + calma CS 5 * + calma CC 7 * + calma CM 8 * + calma CG 9 * + calma CV 13 * + calma CQ 14 * + +/* +style JPL + scalefactor 20 + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer pdiff CSP + and CAA + and CWN + layer ndiff CSN + and CAA + and CWP + and-not CCD + layer nsd CWN + and CSN + and CAA + layer psd CWP + and CSP + and CAA + layer nfet CPG + and CAA + and CSN + and-not CCD + layer pfet CAA + and CPG + and CSP + layer enfet CEL + and CAA + and CSN + and-not CCD + layer epfet CAA + and CEL + and CSP + layer ndc CCA + grow lambda_1 + and CAA + and CWP + and CSN + and CMF + layer pdc CCA + grow lambda_1 + and CAA + and CWN + and CSP + and CMF + layer nsc CCA + grow lambda_1 + and CAA + and CSN + and CWN + and CMF + layer psc CCA + grow lambda_1 + and CAA + and CSP + and CWP + and CMF + layer gc CCC + layer m2c CVA + grow lambda_1 + and CMS + and CMF + labels CMS + layer electrode CEL + labels CEL + layer ec CCE + grow lambda_1 + and CMF + and CEL + labels CMF + layer cc CCE + grow lambda_1 + and CMF + and CEL + and CPG + labels CMF + layer cap CPG + and CEL + and-not CAA + labels CEL + layer pbc CCA + grow lambda_1 + and CBA + and CMF + labels CBA + layer col CX + and CAA + and CSN + and CWN + labels CAA + layer clc CCA + grow lambda_1 + and CX + and CAA + and CSN + and CWN + and CMF + labels CCA + layer emit CBA + and CSN + shrink lambda_2 + labels CBA + layer emc CCA + grow lambda_1 + and CBA + and CSN + and CMF + labels CBA + layer pc CCP + grow lambda_1 + and CPG + and CMF + layer bd CAA + and CCD + and-not CSN + grow lambda_2 + and CAA + labels CCD + layer nbd CSN + shrink lambda_2 + and CCD + and CAA + labels CCD + layer nbdc CCA + grow lambda_1 + and CCD + and CSN + and CAA + labels CCD + layer glass COG +#ifdef OPEN + layer open CAA + and CCA + and CVA + and COG + layer pstop CAA + and CSP + and-not CWP + and-not CWN +#endif + layer pad CMF + shrink lambda_1 + and CMS + shrink lambda_5 + and CVA + shrink lambda_1 + and COG + grow lambda_6 + and XP + layer error_p CER + + calma CWP 41 * + calma CWN 42 * + calma CAA 43 * + calma CSP 44 * + calma CSN 45 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CCE 55 * + calma CEL 56 * + calma CCD 57 * + calma CBA 58 * + calma CWC 59 * + calma CX 60 * + calma CER 61 * + calma CCC 63 * + +#undef cif_tech +*/ + + +/* These follwoing technologies are for DRC error display */ +/* Remove comment if you want to install them... +style lambda=1.0(error) + scalefactor 100 + layer error_s CX +style lambda=0.8(error) + scalefactor 80 + layer error_s CX +style lambda=0.6(error) + scalefactor 60 + layer gc CX +style lambda=0.5(error) + scalefactor 50 + layer error_s CX +*/ diff --git a/scmos/cif_template/cifin.pw b/scmos/cif_template/cifin.pw new file mode 100644 index 00000000..ed95011c --- /dev/null +++ b/scmos/cif_template/cifin.pw @@ -0,0 +1,142 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor +*/ +#define cif_tech pwell +style lambda=lambda_v + scalefactor lambda_1 + layer pwell CWP + labels CWP + layer m3 CMT + /* to avoid a CIF read problem around pads */ + and-not XP + labels CMT + layer m2 CMS + labels CMS + layer m1 CMF + labels CMF + layer poly CPG + labels CPG + layer nsd CAA + and CSN + layer ndiff CWP + and CSN + and CAA + layer pdiff CAA + and CSP + and-not CPS + layer psd CWP + and CSP + and CAA + layer pfet CPG + and CAA + and CSP + layer nfet CAA + and CPG + and CSN + and CWP + layer epfet CEL + and CAA + and CSP + layer enfet CAA + and CEL + and CSN + and CWP + layer m2c CVA + grow lambda_1 + and CMS + and CMF + labels CMS + layer electrode CEL + labels CEL + layer ec CCE + grow lambda_1 + and CMF + and CEL + labels CMF + layer cc CCE + grow lambda_1 + and CMF + and CEL + and CPG + labels CMF + layer cap CPG + and CEL + and-not CAA + labels CEL + layer nsc CCA + grow lambda_1 + and CAA + and CSN + and CMF + layer pdc CCA + grow lambda_1 + and CAA + and CSP + and CMF + layer ndc CCA + grow lambda_1 + and CSN + and CAA + and CWP + and CMF + layer psc CCA + grow lambda_1 + and CAA + and CSP + and CWP + and CMF + layer pc CCP + grow lambda_1 + and CPG + and CMF + layer m3c CVS + grow lambda_1 + and CMT + and CMS + and-not XP + layer glass COG +#ifdef OPEN + layer open CAA + and CCA + and CVA + and COG + and COP + layer pstop CAA + and CPS + and CSP + and-not CWP +#endif + layer pad CMF + shrink lambda_1 + and CMS + shrink lambda_5 + and CVA + shrink lambda_1 + and XP + and COG + grow lambda_6 + + +#ifdef OPEN + calma COP 23 * + calma CPS 24 * +#endif + calma XP 26 * + calma CWP 41 * + calma CAA 43 * + calma CSP 44 * + calma CSN 45 * + calma CPG 46 * + calma CCP 47 * + calma CCA 48 * + calma CMF 49 * + calma CVA 50 * + calma CMS 51 * + calma COG 52 * + calma CCE 55 * + calma CEL 56 * + calma CVS 61 * + calma CMT 62 * + +#undef cif_tech diff --git a/scmos/cif_template/cifin26g.c b/scmos/cif_template/cifin26g.c new file mode 100644 index 00000000..c1132e72 --- /dev/null +++ b/scmos/cif_template/cifin26g.c @@ -0,0 +1,24 @@ + +/* 0.8 micron technology */ +#define lambda_value 40 +#include "calc.lambda" +#include "cifin-cmos26g.gen" +#define NOWELL +#include "cifin-cmos26g.gen" +#undef NOWELL + +/* 0.8 micron technology */ +#define lambda_value 30 +#include "calc.lambda" +#include "cifin-cmos14b.gen" +#define NOWELL +#include "cifin-cmos14b.gen" +#undef NOWELL + +/* 0.8 micron CMOSX technology */ +#define lambda_value 40 +#include "calc.lambda" +#include "cifin-cmosx.gen" +#define NOWELL +#include "cifin-cmosx.gen" +#undef NOWELL diff --git a/scmos/cif_template/cifout-ami16.gen b/scmos/cif_template/cifout-ami16.gen new file mode 100644 index 00000000..4a49177c --- /dev/null +++ b/scmos/cif_template/cifout-ami16.gen @@ -0,0 +1,176 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + hnfet,hpfet + poly capacitor + bipolar NPN transistor + micro-machined devices +*/ +#define cif_tech gen +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CVN hnwell + bloat-or allHVPDiff,hpfet * lambda_7 + bloat-or allHVNOhmic * lambda_3 + calma 40 1 + layer CVP hpwell + bloat-or allHVNDiff,hnfet * lambda_7 + bloat-or allHVPOhmic * lambda_3 + calma 39 1 + layer CWN nwell + bloat-or pbase,pbc/act * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 + bloat-or allPOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA clc + grow lambda_1 + or em,emc,col + or allActive + or allHVDiff,allHVOhmic,hnfet,hpfet +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" while CIF input */ + /* use CX layer for high-voltage MOSFETs too... (for cifin) */ + layer CX col,clc + grow lambda_1 +/* or allHVDiff,allHVOhmic,hnfet,hpfet + or hnw,hpw */ + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separatelt */ + layer CCA ndc,pdc,BiCut + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCA hndc,hpdc + squares lambda_2 lambda_2 lambda_2 + calma 48 1 + layer CCA hnsc,hpsc + squares lambda_2 lambda_2 lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or allHVNDiff * lambda_2 allHVPOhmic 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or allHVPDiff * lambda_2 allHVNOhmic 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or allHVNDiff * lambda_2 allHVPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or hnfet * lambda_2 hndiff lambda_3 allHVPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or allHVNOhmic * lambda_2 allHVPDiff 0 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or allHVPDiff * lambda_2 allHVNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or hpfet * lambda_2 hpdiff lambda_3 allHVNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or allHVPOhmic * lambda_2 allHVNDiff 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout-cmos14b-sub.gen b/scmos/cif_template/cifout-cmos14b-sub.gen new file mode 100644 index 00000000..9a82f333 --- /dev/null +++ b/scmos/cif_template/cifout-cmos14b-sub.gen @@ -0,0 +1,135 @@ +/* For HP CMOS14B process... No CCD, Bipolar, Poly2 layers. */ +/* This is prelimanary, please let me know if anything here seems + abnormal to you... pi@lepton.isi.edu 3/02/95 */ +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWN nwell + bloat-or allPDiff,PFet * lambda_6 + bloat-or allNOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_6 pdop 0 + bloat-or allPOhmic * lambda_3 ndop 0 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMT allMetal3,pad + labels m3 + calma 62 1 + layer CMS pad + grow lambda_2 + or allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_4 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA allActive + or ndop,pdop +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + layer CVS pad + shrink pad_via2 +#ifdef OPEN + or open +#endif + calma 61 1 + layer CVS m3c + squares lambda_1 lambda_2 lambda_3 + calma 61 1 + layer CVA pad + shrink pad_via1 +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + /* Generic contact to (active,poly)... + NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 48 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc + squares lambda_1 lambda_2 lambda_3 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_1 lambda_2 lambda_3 + calma 48 1 + layer CCP pc + squares lambda_1 lambda_2 lambda_3 + calma 47 1 + /* temp CIF layer - All diffusion N-Select layers */ + templayer XTN + bloat-or allNDiff,ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + bloat-or nbd,nbdc * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + /* temp CIF layer - All diffusion P-Select layers */ + templayer XTP + bloat-or allPDiff,pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic,pdop 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff,pdop 0 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP + bloat-or allPDiff * lambda_2 allNOhmic,ndop 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff,ndop 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout-cmos14b.gen b/scmos/cif_template/cifout-cmos14b.gen new file mode 100644 index 00000000..a24d960e --- /dev/null +++ b/scmos/cif_template/cifout-cmos14b.gen @@ -0,0 +1,135 @@ +/* For HP CMOS14B process... No CCD, Bipolar, Poly2 layers. */ +/* This is prelimanary, please let me know if anything here seems + abnormal to you... pi@lepton.isi.edu 3/02/95 */ +style lambda=lambda_v + scalefactor lambda_1 calmaonly + layer CWN nwell + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 pdop 0 + bloat-or allPOhmic * lambda_3 ndop 0 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMT allMetal3,pad + labels m3 + calma 62 1 + layer CMS pad + grow lambda_2 + or allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_4 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA allActive + or ndop,pdop +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + layer CVS pad + shrink pad_via2 +#ifdef OPEN + or open +#endif + calma 61 1 + layer CVS m3c + squares lambda_1 lambda_2 lambda_3 + calma 61 1 + layer CVA pad + shrink pad_via1 +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + /* Generic contact to (active,poly)... + NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 48 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + /* temp CIF layer - All diffusion N-Select layers */ + templayer XTN + bloat-or allNDiff,ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + bloat-or nbd,nbdc * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + /* temp CIF layer - All diffusion P-Select layers */ + templayer XTP + bloat-or allPDiff,pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic,pdop 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff,pdop 0 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP + bloat-or allPDiff * lambda_2 allNOhmic,ndop 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff,ndop 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout-cmos26b.gen b/scmos/cif_template/cifout-cmos26b.gen new file mode 100644 index 00000000..22136806 --- /dev/null +++ b/scmos/cif_template/cifout-cmos26b.gen @@ -0,0 +1,158 @@ +/* For HP CMOS26B process... No CCD, Bipolar, Poly2 layers. + Two types of pad layer are supported, one (the pad layer) + contains both metal1 and metal2 layer while the other (the + pad2 layer) contains all three metals with all necessary via + properly defined... */ +/* This is prelimanary, please let me know if anything here seems + abnormal to you... pi@lepton.isi.edu 3/15/93 */ +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWN nwell + bloat-or pbase,pbc/act * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/act * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 pdop 0 + bloat-or allPOhmic * lambda_3 ndop 0 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMT allMetal3,pad + labels m3 + calma 62 1 + layer CMS pad + grow lambda_2 + or allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_4 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA allActive + or ndop,pdop +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + layer CVS pad + shrink pad_via2 +#ifdef OPEN + or open +#endif + calma 61 1 + layer CVS m3c + squares lambda_1 lambda_2 lambda_3 + calma 61 1 + layer CVA pad + shrink pad_via1 +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + /* Generic contact to (active,poly)... + NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 48 1 + /* A contact under the pad is required by HP rule.... numbers here */ + /* are fixed */ + layer CCA pad + shrink 400 + calma 48 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + /* temp CIF layer - All diffusion N-Select layers */ + templayer XTN + bloat-or allNDiff,ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + bloat-or nbd,nbdc * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + /* temp CIF layer - All diffusion P-Select layers */ + templayer XTP + bloat-or allPDiff,pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic,pdop 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff,pdop 0 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP + bloat-or allPDiff * lambda_2 allNOhmic,ndop 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff,ndop 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + + render CWN 12 -0.2 0.2 + render CAA 2 -0.15 0.15 + render CPG 1 0.025 0.05 + render CEL 14 0.1 0.05 + render CCC 19 0.0 0.2 + render CCA 19 0.0 0.2 + render CCP 19 0.075 0.125 + render CMF 20 0.2 0.05 + render CVA 19 0.25 0.05 + render CMS 21 0.3 0.05 + +#undef cif_tech diff --git a/scmos/cif_template/cifout-cmos26g.gen b/scmos/cif_template/cifout-cmos26g.gen new file mode 100644 index 00000000..f73b4cd5 --- /dev/null +++ b/scmos/cif_template/cifout-cmos26g.gen @@ -0,0 +1,137 @@ + +style lambda=0.40(sub) + scalefactor lambda_1 scaleunit + layer CWN nwell + bloat-or allPDiff,PFet * lambda_6 + bloat-or allNOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_6 pdop 0 + bloat-or allPOhmic * lambda_3 ndop 0 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMT allMetal3,pad + labels m3 + calma 62 1 + layer CMS pad + grow lambda_2 + or allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_4 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA allActive + or ndop,pdop +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + layer CVS pad + shrink pad_via2 + or open + calma 61 1 + layer CVS m3c + squares lambda_1 lambda_2 lambda_3 + calma 61 1 + layer CVA pad + shrink pad_via1 +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + /* Generic contact to (active,poly)... + NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 48 1 + /* A contact under the pad is required by HP rule.... numbers here */ + /* are fixed */ + layer CCA pad + shrink 400 + calma 48 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc + squares lambda_1 lambda_2 lambda_3 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_1 lambda_2 lambda_3 + calma 48 1 + layer CCP pc + squares lambda_1 lambda_2 lambda_3 + calma 47 1 + /* temp CIF layer - All diffusion N-Select layers */ + templayer XTN + bloat-or allNDiff,ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + bloat-or nbd,nbdc * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + /* temp CIF layer - All diffusion P-Select layers */ + templayer XTP + bloat-or allPDiff,pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic,pdop 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff,pdop 0 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP + bloat-or allPDiff * lambda_2 allNOhmic,ndop 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff,ndop 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech + diff --git a/scmos/cif_template/cifout-cmos26g.soi b/scmos/cif_template/cifout-cmos26g.soi new file mode 100644 index 00000000..62756b7d --- /dev/null +++ b/scmos/cif_template/cifout-cmos26g.soi @@ -0,0 +1,133 @@ + +style lambda=0.40(soi) + scalefactor lambda_1 scaleunit + layer CWN nwell + bloat-or allPDiff,PFet * lambda_6 + bloat-or allNOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_6 pdop 0 + bloat-or allPOhmic * lambda_3 ndop 0 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMT allMetal3,pad + labels m3 + calma 62 1 + layer CMS pad + grow lambda_2 + or allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_4 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA allActive + or ndop,pdop +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + layer CVS pad + shrink lambda_3 + squares lambda_3 + or open + calma 61 1 + layer CVS m3c + squares lambda_1 lambda_2 lambda_3 + calma 61 1 + layer CVA pad + squares lambda_3 +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + /* Generic contact to (active,poly)... + NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 48 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc + squares lambda_1 lambda_2 lambda_3 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_1 lambda_2 lambda_3 + calma 48 1 + layer CCP pc + squares lambda_1 lambda_2 lambda_3 + calma 47 1 + /* temp CIF layer - All diffusion N-Select layers */ + templayer XTN + bloat-or allNDiff,ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + bloat-or nbd,nbdc * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + /* temp CIF layer - All diffusion P-Select layers */ + templayer XTP + bloat-or allPDiff,pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic,pdop 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff,pdop 0 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP + bloat-or allPDiff * lambda_2 allNOhmic,ndop 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff,ndop 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech + diff --git a/scmos/cif_template/cifout-cmos34.gen b/scmos/cif_template/cifout-cmos34.gen new file mode 100644 index 00000000..63c6166f --- /dev/null +++ b/scmos/cif_template/cifout-cmos34.gen @@ -0,0 +1,164 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet,hvnfet,hvpfet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor + micro-machined devices + "pad" layer generate *no* metal3 +*/ +#define cif_tech gen +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWC cwell + calma 59 1 + layer CWN nwell + bloat-or pbase,pbc/act * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 + bloat-or allPOhmic * lambda_3 + and-not CWC + shrink lambda_3 + grow lambda_3 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA clc + grow lambda_1 + or em,emc,col,pbase,pbc + or allActive + or allHVDiff + or allCCDiff +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" while CIF input */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 48 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separatelt */ + layer CCA ndc,pdc,BiCut,nbdc + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff,ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + bloat-or nbd,nbdc,wcap * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff,pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or nbd,nbdc,wcap * lambda_2 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer CCD allCCDiff + grow lambda_2 + calma 57 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout-cmos34.nw b/scmos/cif_template/cifout-cmos34.nw new file mode 100644 index 00000000..003fc081 --- /dev/null +++ b/scmos/cif_template/cifout-cmos34.nw @@ -0,0 +1,146 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor + metal3 and via2 + "pad" layer generate *no* metal3 +*/ +#define cif_tech nwell +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWC cwell + calma 59 1 + layer CWN nwell + bloat-or pbase,pbc/a * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA clc + grow lambda_1 + or em,emc,col,pbase,pbc + or allActive + or allHVDiff + or allCCDiff +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will NOT in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc,BiCut,nbdc + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + layer CSN clc + grow lambda_1 + or emc,emit,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer CCD allCCDiff + grow lambda_2 + calma 57 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout-cmos34.pw b/scmos/cif_template/cifout-cmos34.pw new file mode 100644 index 00000000..43b86bf6 --- /dev/null +++ b/scmos/cif_template/cifout-cmos34.pw @@ -0,0 +1,126 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + meatl3 and via2 + "pad" layer generate *no* metal3 +*/ +#define cif_tech pwell +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 + bloat-or allPOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + /* "clc" here for safety reason */ + layer CAA clc + grow lambda_1 + or em,emc,col + or allActive + or allHVDiff +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" which CIF input */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc,BiCut + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN + bloat-or allNDiff * lambda_2 allPOhmic 0 + templayer XTP + bloat-or allPDiff * lambda_2 allNOhmic 0 + layer CSP + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + calma 44 1 + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or ndop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + and-not CSP + calma 45 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout-cmosn.gen b/scmos/cif_template/cifout-cmosn.gen new file mode 100644 index 00000000..a0ad67fd --- /dev/null +++ b/scmos/cif_template/cifout-cmosn.gen @@ -0,0 +1,97 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + micro-machined devices +*/ +#define cif_tech cmosn +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer NWN nwell + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 1 1 + layer NWP pwell + bloat-or allNDiff,NFet * lambda_5 + bloat-or allPOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 2 1 + layer NMS allMetal2 + labels m2 + calma 12 1 + layer NMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 10 1 + layer NPG cap + or allPoly + labels poly,nfet,pfet + calma 4 1 + layer NAA allActive + or open,pstop + labels ndiff,pdiff + calma 3 1 + layer NVA pad + shrink pad_via + or open + calma 11 1 + layer NVA m2c + calma 11 1 + layer NEL allPoly2 + calma 5 1 + layer NCT gc + or capc + or ec + calma 9 1 + /* temp CIF layer for select generation */ + templayer XTN + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or ndop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + templayer XTP + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or pdop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer NSN + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer NSP + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + bloat-min pstop * lambda_2 open 0 + and-not XTN + and-not NSN + calma 44 1 + layer NOG pad + shrink pad_glass + or glass + or open + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + +#undef cif_tech diff --git a/scmos/cif_template/cifout-cmosn.nw b/scmos/cif_template/cifout-cmosn.nw new file mode 100644 index 00000000..4f4d0835 --- /dev/null +++ b/scmos/cif_template/cifout-cmosn.nw @@ -0,0 +1,123 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor +*/ +#define cif_tech nwell +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWC cwell + calma 59 1 + layer CWN nwell + bloat-or pbase,pbc/a * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA clc + grow lambda_1 + or em,emc,col + or allActive + or allHVDiff + or allCCDiff + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will NOT in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc,BiCut,nbdc + squares lambda_2 + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + layer CSN clc + grow lambda_1 + or emc,emit,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTN + and-not CSN + calma 44 1 + layer CCD allCCDiff + grow lambda_2 + calma 57 1 + layer COG pad + shrink pad_glass + or glass + labels pad + calma 52 1 + layer XP pad + shrink pad_glass +#undef cif_tech diff --git a/scmos/cif_template/cifout-cmosx.gen b/scmos/cif_template/cifout-cmosx.gen new file mode 100644 index 00000000..cc7fd3de --- /dev/null +++ b/scmos/cif_template/cifout-cmosx.gen @@ -0,0 +1,131 @@ +/* This is prelimanary, please let me know if anything here seems + abnormal to you... pi@lepton.isi.edu 3/02/95 */ +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWN nwell + bloat-or allPDiff,PFet * lambda_6 + bloat-or allNOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 1 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_6 pdop 0 + bloat-or allPOhmic * lambda_3 ndop 0 + grow lambda_3 + shrink lambda_3 + calma 2 1 + layer CMT allMetal3,pad + labels m3 + calma 15 1 + layer CMS pad + grow lambda_2 + or allMetal2 + labels m2 + calma 12 1 + layer CMF pad + grow lambda_4 + or allMetal1 + labels homeMetal1 + calma 10 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 4 1 + layer CAA allActive + or ndop,pdop +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 3 1 + layer CVS pad + shrink pad_via2 +#ifdef OPEN + or open +#endif + calma 14 1 + layer CVS m3c + squares lambda_1 lambda_2 lambda_3 + calma 14 1 + layer CVA pad + shrink pad_via1 +#ifdef OPEN + or open +#endif + calma 11 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 11 1 + /* Generic contact to (active,poly)... + NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 9 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc + squares lambda_1 lambda_2 lambda_3 +#ifdef OPEN + or open +#endif + calma 9 1 + layer CCA nsc,psc + squares lambda_1 lambda_2 lambda_3 + calma 9 1 + layer CCP pc + squares lambda_1 lambda_2 lambda_3 + calma 9 1 + /* temp CIF layer - All diffusion N-Select layers */ + templayer XTN + bloat-or allNDiff,ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + bloat-or nbd,nbdc * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + /* temp CIF layer - All diffusion P-Select layers */ + templayer XTP + bloat-or allPDiff,pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic,pdop 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff,pdop 0 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 7 1 + layer CSP + bloat-or allPDiff * lambda_2 allNOhmic,ndop 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff,ndop 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 8 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 16 1 +/* + layer XP pad + calma 26 1 +*/ + +#undef cif_tech diff --git a/scmos/cif_template/cifout-ibm.gen b/scmos/cif_template/cifout-ibm.gen new file mode 100644 index 00000000..84c0833d --- /dev/null +++ b/scmos/cif_template/cifout-ibm.gen @@ -0,0 +1,135 @@ + +style lambda=0.4(ibm) + scalefactor lambda_1 scaleunit + layer CWN nwell + bloat-or pbase,pbc/act * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/act * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 pdop 0 + bloat-or allPOhmic * lambda_3 ndop 0 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMT allMetal3,pad + labels m3 + calma 62 1 + layer CMS pad + grow lambda_2 + or allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_4 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA allActive + or ndop,pdop +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + layer CVS pad + shrink lambda_2 + or open + calma 61 1 + layer CVS m3c + squares lambda_1 lambda_2 lambda_3 + calma 61 1 + layer CVA pad + shrink lambda_5 +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + /* Generic contact to (active,poly)... + NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + /* temp CIF layer - All diffusion N-Select layers */ + templayer XTN + bloat-or allNDiff,ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + bloat-or nbd,nbdc * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + /* temp CIF layer - All diffusion P-Select layers */ + templayer XTP + bloat-or allPDiff,pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic,pdop 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff,pdop 0 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP + bloat-or allPDiff * lambda_2 allNOhmic,ndop 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff,ndop 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech + diff --git a/scmos/cif_template/cifout-orbit.gen b/scmos/cif_template/cifout-orbit.gen new file mode 100644 index 00000000..9e8bc1ea --- /dev/null +++ b/scmos/cif_template/cifout-orbit.gen @@ -0,0 +1,176 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet,hvnfet,hvpfet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor + micro-machined devices + metal3 and via2 + "pad" layer generate *no* metal3 +*/ +#define cif_tech gen +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWC cwell + calma 59 1 + layer CWN nwell + bloat-or pbase,pbc/act * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 + bloat-or allPOhmic * lambda_3 + and-not CWC + shrink lambda_3 + grow lambda_3 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA clc + grow lambda_1 + or em,emc,col,pbase,pbc + or allActive + or allHVDiff + or allCCDiff +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" while CIF input */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 48 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separatelt */ + layer CCA ndc,pdc,BiCut,nbdc + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff,ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + bloat-or nbd,nbdc,wcap * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff,pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or nbd,nbdc,wcap * lambda_2 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer CCD allCCDiff + grow lambda_2 + calma 57 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + + render CWN 12 -0.2 0.2 + render CAA 2 -0.15 0.15 + render CPG 1 0.025 0.05 + render CEL 14 0.1 0.05 + render CCC 19 0.0 0.2 + render CCA 19 0.0 0.2 + render CCP 19 0.075 0.125 + render CMF 20 0.2 0.05 + render CVA 19 0.25 0.05 + render CMS 21 0.3 0.05 + +#undef cif_tech diff --git a/scmos/cif_template/cifout-orbit.nw b/scmos/cif_template/cifout-orbit.nw new file mode 100644 index 00000000..003fc081 --- /dev/null +++ b/scmos/cif_template/cifout-orbit.nw @@ -0,0 +1,146 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor + metal3 and via2 + "pad" layer generate *no* metal3 +*/ +#define cif_tech nwell +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWC cwell + calma 59 1 + layer CWN nwell + bloat-or pbase,pbc/a * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA clc + grow lambda_1 + or em,emc,col,pbase,pbc + or allActive + or allHVDiff + or allCCDiff +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will NOT in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc,BiCut,nbdc + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + layer CSN clc + grow lambda_1 + or emc,emit,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer CCD allCCDiff + grow lambda_2 + calma 57 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout-orbit.pw b/scmos/cif_template/cifout-orbit.pw new file mode 100644 index 00000000..43b86bf6 --- /dev/null +++ b/scmos/cif_template/cifout-orbit.pw @@ -0,0 +1,126 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + meatl3 and via2 + "pad" layer generate *no* metal3 +*/ +#define cif_tech pwell +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 + bloat-or allPOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + /* "clc" here for safety reason */ + layer CAA clc + grow lambda_1 + or em,emc,col + or allActive + or allHVDiff +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" which CIF input */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc,BiCut + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN + bloat-or allNDiff * lambda_2 allPOhmic 0 + templayer XTP + bloat-or allPDiff * lambda_2 allNOhmic 0 + layer CSP + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + calma 44 1 + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or ndop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + and-not CSP + calma 45 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout.c b/scmos/cif_template/cifout.c new file mode 100644 index 00000000..c9c3fb8e --- /dev/null +++ b/scmos/cif_template/cifout.c @@ -0,0 +1,116 @@ + +#ifdef STANDARD + +/* standard CMOS processes, ORBIT specifically... */ +/* 3.0 micron technology - not supported anymore +#define lambda_value 150 +#include "calc.lambda" +#include "cifout.gen" +#include "cifout.nw" +#include "cifout.pw" +*/ + +/* ORBIT 2.0 micron technology */ +#define lambda_value 100 +#include "calc.lambda" +#include "cifout-orbit.gen" +#include "cifout-orbit.nw" +#include "cifout-orbit.pw" +/* just testing... +#include "cifout.test" +*/ + +/* ORBIT 1.6 micron technology - not supported, but retained for ORBIT */ +#define lambda_value 80 +#include "calc.lambda" +#include "cifout-ami16.gen" +/* just the generic style is enough at the moment... +#include "cifout-ami16.nw" +#include "cifout-ami16.pw" + */ + +/* ORBIT 1.2 micron technology - ORBIT 1.2 micron process supported... */ +#define lambda_value 60 +#include "calc.lambda" +#include "cifout-orbit.gen" +#include "cifout-orbit.nw" +#include "cifout-orbit.pw" + +/* 1.2 micron technology - for Mentor Graphics CMOSN technology */ +/* not supported yet, for my own test... */ +/* +#define lambda_value 20 +#include "calc.lambda" +#include "cifout-cmosn.nw" +*/ + +#endif /* Standard SCMOS technologies */ + +#ifdef TIGHTMETAL + +/* HP CMOS34 1.2 micron technology */ +#define lambda_value 60 +#include "calc.lambda" +#include "cifout-cmos34.gen" +#include "cifout-cmos34.nw" +#include "cifout-cmos34.pw" + +/* HP CMOS26b 1.0 micron technology */ +#undef cif_tech +#define cif_tech sub +#define lambda_value 50 +#include "calc.lambda" +#include "cifout-cmos26b.gen" + +/* HP CMOS26b 1.0 micron technology */ +/* This is used for generation of standard 2.0 micron layout for Cadence tool */ +/* +#define lambda_value 100 +#include "calc.lambda" +#include "cifout-cmos26b.gen" + */ + +/* HP CMOS14b 0.6 micron technology */ +#undef cif_tech +#define cif_tech sub +#define lambda_value 35 +#include "calc.lambda" +#include "cifout-cmos14b.gen" + +#endif /* Tight Metal SCMOS technologies */ + +#ifdef SUBMICRON + +/* HP CMOS26G 0.8 micron technology */ +#define lambda_value 40 +#include "calc.lambda" +#include "cifout-cmos26g.gen" + +/* HP CMOS14B 0.6 micron technology */ +#define cif_tech sub +#define lambda_value 30 +#include "calc.lambda" +#include "cifout-cmos14b-sub.gen" + +/* This one is used for an internal SOI technology */ +#define lambda_value 40 +#include "calc.lambda" +#include "cifout-cmos26g.soi" + +/* This one is used for an internal SOI technology */ +#define cif_tech cmosx +#define lambda_value 40 +#include "calc.lambda" +#include "cifout-cmosx.gen" + +#endif /* HP CMOS26G and HP CMOS14B */ + + +#ifdef IBM + +/* IBM CMSX2185 0.8 micron technology */ +#define lambda_value 40 +#include "calc.lambda" +#include "cifout-ibm.gen" + +#endif /* IBM */ diff --git a/scmos/cif_template/cifout.gen b/scmos/cif_template/cifout.gen new file mode 100644 index 00000000..cbb6fb91 --- /dev/null +++ b/scmos/cif_template/cifout.gen @@ -0,0 +1,180 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet,hvnfet,hvpfet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor + micro-machined devices + "pad" layer generate *no* metal3 +*/ +#define cif_tech gen +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWC cwell + calma 59 1 + layer CWN nwell + bloat-or pbase,pbc/act * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 + bloat-or allPOhmic * lambda_3 + and-not CWC + shrink lambda_3 + grow lambda_3 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMT allMetal3 + labels m3 + calma 62 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA clc + grow lambda_1 + or em,emc,col,pbase,pbc + or allActive + or allHVDiff + or allCCDiff +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" while CIF input */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 48 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separatelt */ + layer CCA ndc,pdc,BiCut,nbdc + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + grow lambda_2 + shrink lambda_2 + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff,ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + bloat-or nbd,nbdc,wcap * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff,pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or nbd,nbdc,wcap * lambda_2 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer CCD allCCDiff + grow lambda_2 + calma 57 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + + render CWN 12 -0.2 0.2 + render CAA 2 -0.15 0.15 + render CPG 1 0.025 0.05 + render CEL 14 0.1 0.05 + render CCC 19 0.0 0.2 + render CCA 19 0.0 0.2 + render CCP 19 0.075 0.125 + render CMF 20 0.2 0.05 + render CVA 19 0.25 0.05 + render CMS 21 0.3 0.05 + +#undef cif_tech diff --git a/scmos/cif_template/cifout.gen-old b/scmos/cif_template/cifout.gen-old new file mode 100644 index 00000000..05bab7cc --- /dev/null +++ b/scmos/cif_template/cifout.gen-old @@ -0,0 +1,155 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet,hvnfet,hvpfet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor + micro-machined devices +*/ +#define cif_tech gen +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWC cwell + calma 59 1 + layer CWN nwell + bloat-or pbase,pbc/act * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 + bloat-or allPOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA clc + grow lambda_1 + or em,emc,col + or allActive + or allHVDiff + or allCCDiff +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" while CIF input */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + /* contacts for pdc/nsc (ndc/psc) must be generated separatelt */ + layer CCA ndc,pdc,BiCut,nbdc + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or pdop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + layer CSN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or nbd,nbdc,wcap * lambda_2 + bloat-or ndop * lambda_2 allPOhmic,allPDiff,pdop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 allNOhmic,allNDiff,ndop 0 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer CCD allCCDiff + grow lambda_2 + calma 57 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout.nw b/scmos/cif_template/cifout.nw new file mode 100644 index 00000000..502f035a --- /dev/null +++ b/scmos/cif_template/cifout.nw @@ -0,0 +1,158 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor + metal3 and via2 + "pad" layer generate *no* metal3 +*/ +#define cif_tech nwell +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWC cwell + calma 59 1 + layer CWN nwell + bloat-or pbase,pbc/a * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CMT allMetal3 + labels m3 + calma 62 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA clc + grow lambda_1 + or em,emc,col,pbase,pbc + or allActive + or allHVDiff + or allCCDiff +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + layer CVS pad + shrink lambda_2 +#ifdef OPEN + or open +#endif + calma 61 1 + layer CVS m3c + squares lambda_1 lambda_2 lambda_3 + calma 61 1 + /* use CX layer to distinguish "col" and "nsd" */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will NOT in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc,BiCut,nbdc + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + layer CSN clc + grow lambda_1 + or emc,emit,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + and-not CSN + calma 44 1 + layer CCD allCCDiff + grow lambda_2 + calma 57 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout.others b/scmos/cif_template/cifout.others new file mode 100644 index 00000000..4fe9165a --- /dev/null +++ b/scmos/cif_template/cifout.others @@ -0,0 +1,70 @@ +/* this style is provided for interface only */ +/* usually you should not submit CIF files designed with SCMOS rules */ +/* for CBPM 3U runs. The bloating and shrinking will be incorrrect */ +style cbpm3u + scalefactor 50 25 + layer CW pwell + bloat-or ndiff,ndc,nfet * 750 + bloat-or psc,ppd * 450 + grow 450 + shrink 450 + calma 1 1 + layer CQ allMetal2 + labels m2 + calma 14 1 + layer CM pad + grow 150 + or allMetal1 + labels homeMetal1 + calma 8 1 + layer CP allPoly + labels poly,nfet,pfet + calma 4 1 + layer CD allActive + labels ndiff,pdiff + calma 3 1 + layer CV pad + shrink 450 + calma 13 1 + layer CV m2c + squares 150 300 450 + calma 13 1 + layer CC ndc,pdc,nsc,psc,pc + squares 300 + calma 7 1 + templayer TNF + bloat-or nfet ndiff 450 poly 300 + layer CS + bloat-or pdiff,pfet,pdc/a * 300 nsd,nsc/a 0 + bloat-or pfet * 300 pdiff 450 nsd,nsc/a 0 + bloat-or psc/a,psd * 300 ndiff,ndc/a,nfet 0 + and-not TNF + grow 150 + shrink 150 + calma 5 1 + layer CG pad + shrink 600 + or glass + calma 9 1 + layer XP pad + + +/* These following technologies are used to generate CIF */ +/* used for for DRC batch jobs. Remove comment if you want to */ +/* install it... +style lambda=1.5(error) + scalefactor 150 25 + layer CX error_s,error_p,error_ps +style lambda=1.0(error) + scalefactor 100 50 + layer CX error_s,error_p,error_ps +style lambda=0.8(error) + scalefactor 80 40 + layer CX error_s,error_p,error_ps +style lambda=0.6(error) + scalefactor 60 30 + layer CX error_s,error_p,error_ps +style lambda=0.5(error) + scalefactor 50 25 + layer CX error_s,error_p,error_ps +*/ diff --git a/scmos/cif_template/cifout.pw b/scmos/cif_template/cifout.pw new file mode 100644 index 00000000..12afcb58 --- /dev/null +++ b/scmos/cif_template/cifout.pw @@ -0,0 +1,138 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + meatl3 and via2 + "pad" layer generate *no* metal3 +*/ +#define cif_tech pwell +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWP pwell + bloat-or allNDiff,NFet * lambda_5 + bloat-or allPOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 41 1 + layer CMT allMetal3 + labels m3 + calma 62 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + /* "clc" here for safety reason */ + layer CAA clc + grow lambda_1 + or em,emc,col + or allActive + or allHVDiff +#ifdef OPEN + or open,pstop +#endif + labels ndiff,pdiff + calma 43 1 + layer CVS pad + shrink lambda_2 +#ifdef OPEN + or open +#endif + calma 61 1 + layer CVS m3c + squares lambda_1 lambda_2 lambda_3 + calma 61 1 + /* use CX layer to distinguish "col" and "nsd" which CIF input */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via +#ifdef OPEN + or open +#endif + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc,BiCut + squares lambda_2 +#ifdef OPEN + or open +#endif + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN + bloat-or allNDiff * lambda_2 allPOhmic 0 + templayer XTP + bloat-or allPDiff * lambda_2 allNOhmic 0 + layer CSP + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half +#ifdef OPEN + bloat-min pstop * lambda_2 open 0 +#endif + and-not XTN + calma 44 1 + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or ndop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + and-not CSP + calma 45 1 + layer COP open + calma 23 1 + layer CPS pstop + calma 24 1 + layer COG pad + shrink pad_glass + or glass +#ifdef OPEN + or open +#endif + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + calma 26 1 + +#undef cif_tech diff --git a/scmos/cif_template/cifout.scgnw b/scmos/cif_template/cifout.scgnw new file mode 100644 index 00000000..797eae27 --- /dev/null +++ b/scmos/cif_template/cifout.scgnw @@ -0,0 +1,124 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor +*/ +#define cif_tech scg_nwell +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWC cwell + calma 59 1 + layer CWG nwell + bloat-or pbase,pbc/a * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 53 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA em,emc + grow lambda_1 + or clc,pbc + grow lambda_1 + or col + or allActive + or allHVDiff + or allCCDiff + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, generic contact will NOT in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc,BiCut,nbdc + squares lambda_2 + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + layer CSG emit,emc + grow lambda_1 + or clc + grow lambda_1 + or col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + and-not XTP + calma 54 1 +/* + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 + and-not XTN + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + calma 44 1 +*/ + layer CCD allCCDiff + grow lambda_2 + calma 57 1 + layer COG pad + shrink pad_glass + or glass + calma 52 1 + layer XP pad + shrink pad_glass + +#undef cif_tech diff --git a/scmos/cif_template/cifout.scgpw b/scmos/cif_template/cifout.scgpw new file mode 100644 index 00000000..25c54f6f --- /dev/null +++ b/scmos/cif_template/cifout.scgpw @@ -0,0 +1,94 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor. NO Bipolar stuff +*/ +#define cif_tech scg_pwell +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWG pwell + bloat-or allNDiff,NFet * lambda_5 + bloat-or allPOhmic * lambda_3 + grow lambda_3 + shrink lambda_3 + calma 53 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA + or allActive + or allHVDiff + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" which CIF input */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will not in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc,BiCut + squares lambda_2 + calma 48 1 + layer CCA nsc,psc + squares lambda_2 + calma 48 1 + layer CCP pc + squares lambda_2 + calma 47 1 + /* temp CIF layer for select generation */ + templayer XTN + bloat-or allNDiff * lambda_2 allPOhmic 0 + layer CSG + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 + and-not XTN + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + calma 54 1 +/* + layer CSN + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or ndop * lambda_2 + and-not XTP + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + calma 45 1 +*/ + layer COG pad + shrink pad_glass + or glass + calma 52 1 + layer XP pad + shrink pad_glass + +#undef cif_tech diff --git a/scmos/cif_template/cifout.test b/scmos/cif_template/cifout.test new file mode 100644 index 00000000..9c5b356f --- /dev/null +++ b/scmos/cif_template/cifout.test @@ -0,0 +1,124 @@ +/* available devices: + nfet,pfet,enfet,epfet,nffet,pffet + poly capacitor + bipolar NPN transistor + buried CCD devices + linear capacitor +*/ +#define cif_tech test +style lambda=lambda_v + scalefactor lambda_1 scaleunit + layer CWC cwell + calma 59 1 + layer CWN nwell + bloat-or pbase,pbc/a * lambda_6 + bloat-or allPDiff,PFet * lambda_5 + bloat-or allNOhmic * lambda_3 + bloat-or clc/a * lambda_1 + or col + grow lambda_3 + shrink lambda_3 + calma 42 1 + layer CMS allMetal2 + labels m2 + calma 51 1 + layer CMF pad + grow lambda_1 + or allMetal1 + labels homeMetal1 + calma 49 1 + layer CPG cap,cc + or allPoly + labels poly,nfet,pfet + calma 46 1 + layer CAA clc + grow lambda_1 + or em,emc,col + or allActive + or allHVDiff + or allCCDiff + labels ndiff,pdiff + calma 43 1 + /* use CX layer to distinguish "col" and "nsd" */ + layer CX col,clc + grow lambda_1 + calma 60 1 + layer CVA pad + shrink pad_via + calma 50 1 + layer CVA m2c + squares lambda_1 lambda_2 lambda_3 + calma 50 1 + layer CEL allPoly2 + calma 56 1 + layer CCE capc,ec + squares lambda_2 + calma 55 1 + /* NOTE: no calma layer spec. for CCC, contact will NOT in + stream file */ + layer CCC gc + calma 63 1 + /* contacts for pdc/nsc (ndc/psc) must be generated separately */ + layer CCA ndc,pdc,BiCut,nbdc + squares 150 200 200 + calma 48 1 + layer CCA nsc,psc + squares 150 200 200 + calma 48 1 + layer CCP pc + squares 150 200 200 + calma 47 1 + layer CBA emc,emit + grow lambda_4 + bloat-or pbc * lambda_1 + or pbase + calma 58 1 + /* temp CIF layer for select generation */ + templayer XTN clc + grow lambda_1 + or em,emc,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + templayer XTP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + layer CSN clc + grow lambda_1 + or emc,emit,col + grow lambda_2 + bloat-or allNDiff * lambda_2 allPOhmic 0 + bloat-or NFet * lambda_2 ndiff lambda_3 allPOhmic 0 + bloat-or allNOhmic * lambda_2 allPDiff 0 + bloat-or nbd,nbdc,ndop,wcap * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTP + calma 45 1 + layer CSP pbc + grow lambda_1 + bloat-or allPDiff * lambda_2 allNOhmic 0 + bloat-or PFet * lambda_2 pdiff lambda_3 allNOhmic 0 + bloat-or allPOhmic * lambda_2 allNDiff 0 + bloat-or pdop * lambda_2 + grow lambda_1 + shrink lambda_1 + shrink lambda_half + grow lambda_half + and-not XTN + and-not CSN + calma 44 1 + layer CCD allCCDiff + grow lambda_2 + calma 57 1 + layer COG pad + shrink pad_glass + or glass + labels pad + calma 52 1 + layer XP pad + shrink pad_glass + +#undef cif_tech diff --git a/scmos/cif_template/cifout26g.c b/scmos/cif_template/cifout26g.c new file mode 100644 index 00000000..8f8d52d7 --- /dev/null +++ b/scmos/cif_template/cifout26g.c @@ -0,0 +1,14 @@ + +/* 0.8 micron technology */ +#define lambda_value 40 +#include "calc.lambda" +#include "cifout-cmos26g.gen" + +/* This one is used for an internal SOI technology */ +#include "cifout-cmos26g.soi" + +/* 0.6 micron technology */ +#define cif_tech hp14b +#define lambda_value 30 +#include "calc.lambda" +#include "cifout-cmos14b.gen" diff --git a/scmos/cif_template/scgcifout.c b/scmos/cif_template/scgcifout.c new file mode 100644 index 00000000..c31cb37f --- /dev/null +++ b/scmos/cif_template/scgcifout.c @@ -0,0 +1,42 @@ +/* 2.0 micron technology */ +#define lambda_value 100 +#include "calc.lambda" +#include "cifout.gen" +#include "cifout.nw" +#include "cifout.pw" +#include "cifout.scgnw" +#include "cifout.scgpw" +/* 3.0 micron technology - not supported +#define lambda_value 150 +#include "calc.lambda" +#include "cifout.gen" +#include "cifout.nw" +#include "cifout.pw" +*/ +/* 1.6 micron technology - not supported, but retained for ORBIT */ +#define lambda_value 80 +#include "calc.lambda" +#include "cifout.gen" +#include "cifout.nw" +#include "cifout.pw" +#include "cifout.scgnw" +#include "cifout.scgpw" +/* 1.2 micron technology */ +#define lambda_value 60 +#include "calc.lambda" +#include "cifout.gen" +#include "cifout.nw" +#include "cifout.pw" +#include "cifout.scgnw" +#include "cifout.scgpw" +/* 1.0 micron technology */ +#define lambda_value 50 +#include "calc.lambda" +#include "cifout.cmos26-gen" +/* 0.8 micron technology + NOT included in this distribution +#define lambda_value 40 +#include "calc.lambda" +#include "cifout.cmos14-gen" */ +/* all other technology */ +#include "cifout.others" diff --git a/scmos/doc/scmos-hpsub-rules b/scmos/doc/scmos-hpsub-rules new file mode 100644 index 00000000..27da9ff3 --- /dev/null +++ b/scmos/doc/scmos-hpsub-rules @@ -0,0 +1,85 @@ +******************************************************************** +** Notes for the use of special Magic technology file "scmos-sub" ** +** for HP's CMOS26G process with lambda = 0.4 micron. ** +** for HP's CMOS14B process with lambda = 0.3 micron. ** +******************************************************************** + +To submit a design in this technology, please specify "SCN3M_SUBM" +in your technology field when triple metals are used in the design. +If your design use only double metals, please use 'SCN_SUBM'. + +The following set of rules in conventional MOSIS SCMOS technology has +been modified in order to better match HP's submicron CMOS processes, +specifically, CMOS26G and CMOS14TB. + +====================================================================== + Description Rule # SCMOS SCMOS SCMOS_SUBM + (Tight Metal) (submicron rules) +====================================================================== +WELL_W 1.1 10 10 12 (4.8) +WELL_S_DIFF 1.2 9 9 18 (7.2) +WELL_O_ACT_XTOR 2.3 5 5 6 (2.4) +WELL_S_ACT_XTOR 2.3 5 5 6 (2.4) +POLY_S 3.2 2 2 3 (1.2) +CON_S 5B.3,6B.3 2 2 3 (1.2) +M1_W 7.1 3 3 3 (1.2) +M1_S 7.2 3 2 3 (1.2) +M2_W 9.1 3 3 3 (1.2) +M2_S 9.2 4 3 3 (1.2) +M3_W 15.1 6 6 5 (2.0) +M3_S 15.2 4 4 3 (1.2) +====================================================================== + +The HP CMOS26G process is a derivative of the HP CMOS26B process with +most of the rules intact except a 3.5 micron metal3 pitch (reduced +from previous 5.0 micron pitch). Please refer to the on-line process +specification file more detal - +(ftp://ftp.mosis.edu:pub/mosis/vendors/hp-cmos26b-g/scn08-hp-specs.inf) + +The HP CMOS14TB process is a low-voltage (3.3Volt) CMOS one-poly, +three-metal process with 0.6 micron minimum drawn channel length. +Please refer to the on-line process specification file more detal - +(ftp://ftp.mosis.edu:pub/mosis/vendors/hp-cmos14b/scn06_hp_specs.inf) + +A special Magic technology file is prepared for designs targeted +for this process - "scmos-sub". The beta version of this technology +file can be obtained on our anonymous FTP server ftp.mosis.edu +(128.9.0.32) under pub/mosis/magic directory. Two files are there for +your retrieval: + + (1) scmos-sub.tech + (2) scmos-sub.tech26 + +You'll have to install the second file (with C-style comments removed) +in the usual Magic library directory to be able to use it. + +******************************************************************** +** TIPS for the transformation of traditional SCMOS layout to ** +** SCMOS-SUB layout ** +******************************************************************** + +Most of the problems happens in the following cases: + + (1) Poly spacing is now 3 lambda instead of 2 lambda previously. + You'll have to stretch the seriously-connected MOSFETs now. + (2) contact spacing is now 3 instead of 2 previously. This should be + taken care of automatically by the CIF output generator. but it + now requires the designer to use special sized contacts + (ndc,pdc,nsc,psc,pc) so that the resulting contacts will be on + the grid. You should verify this by the use of ":cif see CCA" + command. + (3) Due to the 3 lambda spacing rule for contacts, previously abutted + diffusion/substrate contacts now have to be separated by one + lambda. + +I have the follwoing three files to illustrate the necessary changes +as described above: + + (1) scmos-div4.mag : standard SCMOS divide-by-4 cell. + (2) hp26g-div4-v1.mag : HP CMOS26G divide-by-4 cell with DRC + violation of diffusion/substrate contact spacing rule. + (3) hp26g-div4-v2.mag : correct CMOS26G divide-by-4 cell. + +they can be obtained at the same FTP site under pub/pi/layout/hp26g +directory. + diff --git a/scmos/doc/scmos-rules-rev7.ps b/scmos/doc/scmos-rules-rev7.ps new file mode 100644 index 00000000..e4d9caea --- /dev/null +++ b/scmos/doc/scmos-rules-rev7.ps @@ -0,0 +1,4236 @@ +%!PS-Adobe-2.0 +%%Creator: dvips 5.47 Copyright 1986-91 Radical Eye Software +%%Title: rules.dvi +%%Pages: 28 1 +%%BoundingBox: 0 0 612 792 +%%EndComments +%%BeginProcSet: tex.pro +/TeXDict 200 dict def TeXDict begin /N /def load def /B{bind def}N /S /exch +load def /X{S N}B /TR /translate load N /isls false N /vsize 10 N /@rigin{ +isls{[0 1 -1 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +Resolution VResolution vsize neg mul TR matrix currentmatrix dup dup 4 get +round 4 exch put dup dup 5 get round 5 exch put setmatrix}N /@letter{/vsize 10 +N}B /@landscape{/isls true N /vsize -1 N}B /@a4{/vsize 10.6929133858 N}B /@a3{ +/vsize 15.5531 N}B /@ledger{/vsize 16 N}B /@legal{/vsize 13 N}B /@manualfeed{ +statusdict /manualfeed true put}B /@copies{/#copies X}B /FMat[1 0 0 -1 0 0]N +/FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{/nn 8 dict N nn begin +/FontType 3 N /FontMatrix fntrx N /FontBBox FBB N string /base X array +/BitMaps X /BuildChar{CharBuilder}N /Encoding IE N end dup{/foo setfont}2 +array copy cvx N load 0 nn put /ctr 0 N[}B /df{/sf 1 N /fntrx FMat N df-tail} +B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0]N df-tail}B /E{pop nn dup definefont +setfont}B /ch-width{ch-data dup length 5 sub get}B /ch-height{ch-data dup +length 4 sub get}B /ch-xoff{128 ch-data dup length 3 sub get sub}B /ch-yoff{ +ch-data dup length 2 sub get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B +/ch-image{ch-data dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 +N /rw 0 N /rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S +dup /base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx 0 +ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff setcachedevice +ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff .1 add]{ch-image} +imagemask restore}B /D{/cc X dup type /stringtype ne{]}if nn /base get cc ctr +put nn /BitMaps get S ctr S sf 1 ne{dup dup length 1 sub dup 2 index S get sf +div put}if put /ctr ctr 1 add N}B /I{cc 1 add D}B /bop{userdict /bop-hook +known{bop-hook}if /SI save N @rigin 0 0 moveto}N /eop{clear SI restore +showpage userdict /eop-hook known{eop-hook}if}N /@start{userdict /start-hook +known{start-hook}if /VResolution X /Resolution X 1000 div /DVImag X /IE 256 +array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for}N /p /show load N +/RMat[1 0 0 -1 0 0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X +/rulex X V}B /V statusdict begin /product where{pop product dup length 7 ge{0 +7 getinterval(Display)eq}{pop false}ifelse}{false}ifelse end{{gsave TR -.1 -.1 +TR 1 1 scale rulex ruley false RMat{BDot}imagemask grestore}}{{gsave TR -.1 +-.1 TR rulex ruley scale 1 1 false RMat{BDot}imagemask grestore}}ifelse B /a{ +moveto}B /delta 0 N /tail{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{ +S p tail}B /c{-4 M}B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B +/j{3 M}B /k{4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w +}B /q{p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{clear SS restore}B end +%%EndProcSet +%%BeginProcSet: special.pro +TeXDict begin /SDict 200 dict N SDict begin /@SpecialDefaults{/hs 612 N /vs +792 N /ho 0 N /vo 0 N /hsc 1 N /vsc 1 N /ang 0 N /CLIP false N /BBcalc false N +/p 3 def}B /@scaleunit 100 N /@hscale{@scaleunit div /hsc X}B /@vscale{ +@scaleunit div /vsc X}B /@hsize{/hs X /CLIP true N}B /@vsize{/vs X /CLIP true +N}B /@hoffset{/ho X}B /@voffset{/vo X}B /@angle{/ang X}B /@rwi{10 div /rwi X} +B /@llx{/llx X}B /@lly{/lly X}B /@urx{/urx X}B /@ury{/ury X /BBcalc true N}B +/magscale true def end /@MacSetUp{userdict /md known{userdict /md get type +/dicttype eq{md begin /letter{}N /note{}N /legal{}N /od{txpose 1 0 mtx +defaultmatrix dtransform S atan/pa X newpath clippath mark{transform{ +itransform moveto}}{transform{itransform lineto}}{6 -2 roll transform 6 -2 +roll transform 6 -2 roll transform{itransform 6 2 roll itransform 6 2 roll +itransform 6 2 roll curveto}}{{closepath}}pathforall newpath counttomark array +astore /gc xdf pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{ +PaintBlack}if}N /txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR +pop 1 -1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 +get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip +not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 TR}if +yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{noflips{TR pop pop 270 +rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 -1 scale ppr 3 get +ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip not +and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg sub neg 0 TR}if yflip xflip +not and{TR pop pop 270 rotate ppr 2 get ppr 0 get neg sub neg 0 S TR}if} +ifelse scaleby96{ppr aload pop 4 -1 roll add 2 div 3 1 roll add 2 div 2 copy +TR .96 dup scale neg S neg S TR}if}N /cp{pop pop showpage pm restore}N end}if} +if}N /normalscale{Resolution 72 div VResolution 72 div neg scale magscale{ +DVImag dup scale}if}N /psfts{S 65536 div N}N /startTexFig{/psf$SavedState save +N userdict maxlength dict begin /magscale false def normalscale currentpoint +TR /psf$ury psfts /psf$urx psfts /psf$lly psfts /psf$llx psfts /psf$y psfts +/psf$x psfts currentpoint /psf$cy X /psf$cx X /psf$sx psf$x psf$urx psf$llx +sub div N /psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy scale psf$cx +psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR /showpage{}N +/erasepage{}N /copypage{}N /p 3 def @MacSetUp}N /doclip{psf$llx psf$lly +psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 roll moveto 6 -1 roll +S lineto S lineto S lineto closepath clip newpath moveto}N /endTexFig{end +psf$SavedState restore}N /@beginspecial{SDict begin /SpecialSave save N gsave +normalscale currentpoint TR @SpecialDefaults}N /@setspecial{CLIP{newpath 0 0 +moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto closepath clip}if ho vo TR +hsc vsc scale ang rotate BBcalc{rwi urx llx sub div dup scale llx neg lly neg +TR}if /showpage{}N /erasepage{}N /copypage{}N newpath}N /@endspecial{grestore +clear SpecialSave restore end}N /@defspecial{SDict begin}N /@fedspecial{end}B +/li{lineto}B /rl{rlineto}B /rc{rcurveto}B /np{/SaveX currentpoint /SaveY X N 1 +setlinecap newpath}N /st{stroke SaveX SaveY moveto}N /fil{fill SaveX SaveY +moveto}N /ellipse{/endangle X /startangle X /yrad X /xrad X /savematrix matrix +currentmatrix N TR xrad yrad scale 0 0 1 startangle endangle arc savematrix +setmatrix}N end +%%EndProcSet +TeXDict begin 1000 300 300 @start /Fa 1 23 df<0180300380700380700380700700E007 +00E00700E00700E00E01C00E01C00E01C00E01C01C03881C03881C03881E07883E19903BE0E038 +0000380000700000700000700000700000E00000E00000C00000151B7F9119>22 +D E /Fb 1 23 df<0030003000780078007800780078007800F000F000F000F000F000F000F000 +F001E001E001E001E001E001E001E001E003C003C003C003C003C003C003C003C0078007800780 +078207800782078007820F800F040F800F040F8017040FC027081EE0C3881E3F00F01E0000001E +0000003C0000003C0000003C0000003C00000078000000780000007800000078000000F0000000 +F0000000600000001F277E9924>22 D E /Fc 1 3 df<60000018F0000038780000783C0000F0 +1E0001E00F0003C00780078003C00F0001E01E0000F03C0000787800003CF000001FE000000FC0 +0000078000000FC000001FE000003CF0000078780000F03C0001E01E0003C00F00078007800F00 +03C01E0001E03C0000F078000078F0000038600000181D1D789C2E>2 D +E /Fd 1 16 df<03F0000FFC001FFE003FFF007FFF807FFF80FFFFC0FFFFC0FFFFC0FFFFC0FFFF +C0FFFFC0FFFFC0FFFFC07FFF807FFF803FFF001FFE000FFC0003F00012147D9519>15 +D E /Fe 3 51 df<00300000300000300000300000300000300000300000300000300000300000 +3000FFFFFCFFFFFC00300000300000300000300000300000300000300000300000300000300000 +300016187E931B>43 D<03000700FF000700070007000700070007000700070007000700070007 +00070007000700070007007FF00C157E9412>49 D<0F8030E040708030C038E038403800380070 +0070006000C00180030006000C08080810183FF07FF0FFF00D157E9412>I +E /Ff 20 120 df<03FC000FFF003C1FC07007E07C07F0FE03F0FE03F8FE03F8FE01F87C01F838 +03F80003F80003F00003F00007E00007C0000F80001F00003E0000380000700000E01801C01803 +80180700180E00380FFFF01FFFF03FFFF07FFFF0FFFFF0FFFFF015207D9F1C>50 +D<00FE0007FFC00F07E01E03F03F03F03F81F83F81F83F81F81F03F81F03F00003F00003E00007 +C0001F8001FE0001FF000007C00001F00001F80000FC0000FC3C00FE7E00FEFF00FEFF00FEFF00 +FEFF00FC7E01FC7801F81E07F00FFFC001FE0017207E9F1C>I<07FC001FFF803F07C03F03E03F +01E03F01F01E01F00001F00001F0003FF003FDF01FC1F03F01F07E01F0FC01F0FC01F0FC01F0FC +01F07E02F07E0CF81FF87F07E03F18167E951B>97 DI<00FF8007FFE00F83F01F03F03E03F07E03F07C01E07C0000FC00 +00FC0000FC0000FC0000FC0000FC00007C00007E00007E00003E00301F00600FC0E007FF8000FE +0014167E9519>I<0001FE000001FE0000003E0000003E0000003E0000003E0000003E0000003E +0000003E0000003E0000003E0000003E0000003E0001FC3E0007FFBE000F81FE001F007E003E00 +3E007E003E007C003E00FC003E00FC003E00FC003E00FC003E00FC003E00FC003E00FC003E00FC +003E007C003E007C003E003E007E001E00FE000F83BE0007FF3FC001FC3FC01A237EA21F>I<00 +FE0007FF800F87C01E01E03E01F07C00F07C00F8FC00F8FC00F8FFFFF8FFFFF8FC0000FC0000FC +00007C00007C00007E00003E00181F00300FC07003FFC000FF0015167E951A>I104 D<1C003E007F007F007F003E001C +000000000000000000000000000000FF00FF001F001F001F001F001F001F001F001F001F001F00 +1F001F001F001F001F001F001F001F00FFE0FFE00B247EA310>I108 DII<00FE0007FFC00F83E01E00 +F03E00F87C007C7C007C7C007CFC007EFC007EFC007EFC007EFC007EFC007EFC007E7C007C7C00 +7C3E00F81F01F00F83E007FFC000FE0017167E951C>II114 +D<0FF3003FFF00781F00600700E00300E00300F00300FC00007FE0007FF8003FFE000FFF0001FF +00000F80C00780C00380E00380E00380F00700FC0E00EFFC00C7F00011167E9516>I<01800001 +80000180000180000380000380000780000780000F80003F8000FFFF00FFFF000F80000F80000F +80000F80000F80000F80000F80000F80000F80000F80000F80000F81800F81800F81800F81800F +81800F830007C30003FE0000F80011207F9F16>IIII E /Fg 38 122 df<003F07E00001C09C18000380F01800 +0701F03C000E01E03C000E00E018000E00E000000E00E000000E00E000000E00E000000E00E000 +00FFFFFFFC000E00E01C000E00E01C000E00E01C000E00E01C000E00E01C000E00E01C000E00E0 +1C000E00E01C000E00E01C000E00E01C000E00E01C000E00E01C000E00E01C000E00E01C000E00 +E01C000E00E01C007FC7FCFF80211D809C23>14 D<60F0F0701010101020204080040C7C830C> +44 D<60F0F06004047C830C>46 D<07E01830201C201C781E780E781E381E001C001C00180030 +006007E00030001C001C000E000F000F700FF80FF80FF80FF00E401C201C183007E0101D7E9B15 +>51 D<000C00000C00001C00003C00003C00005C0000DC00009C00011C00031C00021C00041C00 +0C1C00081C00101C00301C00201C00401C00C01C00FFFFC0001C00001C00001C00001C00001C00 +001C00001C0001FFC0121C7F9B15>I<300C3FF83FF03FC020002000200020002000200023E024 +302818301C200E000E000F000F000F600FF00FF00FF00F800E401E401C2038187007C0101D7E9B +15>I<00F0030C06040C0E181E301E300C700070006000E3E0E430E818F00CF00EE006E007E007 +E007E007E007600760077006300E300C18180C3003E0101D7E9B15>I<4000007FFF807FFF007F +FF0040020080040080040080080000100000100000200000600000400000C00000C00001C00001 +800001800003800003800003800003800007800007800007800007800007800007800003000011 +1D7E9B15>I<03E00C301008200C20066006600660067006780C3E083FB01FE007F007F818FC30 +7E601E600FC007C003C003C003C00360026004300C1C1007E0101D7E9B15>I<03C00C30181830 +0C700C600EE006E006E007E007E007E007E0076007700F300F18170C2707C700060006000E300C +780C78187010203030C00F80101D7E9B15>I<000600000006000000060000000F0000000F0000 +000F00000017800000178000001780000023C0000023C0000023C0000041E0000041E0000041E0 +000080F0000080F0000180F8000100780001FFF80003007C0002003C0002003C0006003E000400 +1E0004001E000C001F001E001F00FF80FFF01C1D7F9C1F>65 D<001F808000E061800180198007 +0007800E0003801C0003801C00018038000180780000807800008070000080F0000000F0000000 +F0000000F0000000F0000000F0000000F0000000F0000000700000807800008078000080380000 +801C0001001C0001000E000200070004000180080000E03000001FC000191E7E9C1E>67 +DI73 D78 +D<003F800000E0E0000380380007001C000E000E001C0007003C00078038000380780003C07800 +03C0700001C0F00001E0F00001E0F00001E0F00001E0F00001E0F00001E0F00001E0F00001E070 +0001C0780003C0780003C0380003803C0007801C0007000E000E0007001C000380380000E0E000 +003F80001B1E7E9C20>I82 D<1FC000307000783800781C00301C00001C00001C00 +01FC000F1C00381C00701C00601C00E01C40E01C40E01C40603C40304E801F870012127E9115> +97 DI<07E00C301878307870306000E000E000E000E000 +E000E00060007004300418080C3007C00E127E9112>I<003F0000070000070000070000070000 +070000070000070000070000070000070003E7000C1700180F00300700700700600700E00700E0 +0700E00700E00700E00700E00700600700700700300700180F000C370007C7E0131D7E9C17>I< +03E00C301818300C700E6006E006FFFEE000E000E000E00060007002300218040C1803E00F127F +9112>I<00F8018C071E061E0E0C0E000E000E000E000E000E00FFE00E000E000E000E000E000E +000E000E000E000E000E000E000E000E000E000E007FE00F1D809C0D>I<00038003C4C00C38C0 +1C3880181800381C00381C00381C00381C001818001C38000C300013C000100000300000180000 +1FF8001FFF001FFF803003806001C0C000C0C000C0C000C06001803003001C0E0007F800121C7F +9215>II<18003C003C0018000000000000000000000000 +000000FC001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C00FF80 +091D7F9C0C>I108 +DII<03F0000E1C00180600300300700380600180E001C0E001C0E001C0E001C0E001C0E001C0 +6001807003803003001806000E1C0003F00012127F9115>II114 +D<1F9030704030C010C010E010F8007F803FE00FF000F880388018C018C018E010D0608FC00D12 +7F9110>I<04000400040004000C000C001C003C00FFE01C001C001C001C001C001C001C001C00 +1C001C101C101C101C101C100C100E2003C00C1A7F9910>IIII121 +D E /Fh 8 58 df<1F0060C06060F070F030603000700070006000C001C0018002000400081010 +1020207FE0FFE00C137E9211>50 D<0FC030707038703870380038003000E00FC0007000380018 +001C601CF01CF018E03860701FC00E137F9211>I<006000E000E00160026006600C6008601060 +20606060C060FFFC0060006000600060006003FC0E137F9211>I<60607FC07F80440040004000 +40004F0070C040E0006000700070E070E070E06040E021C01F000C137E9211>I<07C00C201070 +207060006000C000CF00D0C0E060C020C030C030C03040306020206010C00F000C137E9211>I< +40007FFC7FF8401080108020004000800100010003000200060006000E000E000E000E000E0004 +000E147E9311>I<0FC0107020186018601870183C303F600F800FE031F06078C01CC00CC00CC0 +0C601830300FC00E137F9211>I<0F00308060404060C020C030C030C0304030607030B00F3000 +3000200060E040E08041003E000C137E9211>I E /Fi 4 113 df<03800000E00000F000007000 +007000007800003800003800003C00001C00001C00001C00001E00000E00000E00000F00000700 +000700000780000780000F80001B800031C00021C00041C000C1E00180E00300E00600F00C0070 +1C0070380078700038E00038C0001C16237DA21C>21 D<00C00C01C01C01C01C03803803803803 +80380380380700700700700700700700700E00E00E00E00E00E00E00E11E01C21E01C21E03C21E +04C43F08C439F038380000380000700000700000700000700000E00000E00000E00000E00000C0 +000018207E941D>I<70F8F8F87005057C840E>58 D<03C0F004631C04740E08780E0870070870 +0708700F00E00F00E00F00E00F00E00F01C01E01C01E01C01E01C03C03803803803803C07003C0 +E0072180071E000700000700000E00000E00000E00000E00001C00001C00001C0000FFC000181F +819418>112 D E /Fj 35 122 df<00001FFC00000001FFFF00000007FFFF8000001FF807C000 +007FC003E00000FF0007F00000FE000FF00001FE000FF00003FC000FF00003FC000FF00003FC00 +0FF00003FC0007E00003FC0001800003FC0000000003FC0000000003FC0000000003FC00000000 +03FC00FFF800FFFFFFFFF800FFFFFFFFF800FFFFFFFFF80003FC0007F80003FC0007F80003FC00 +07F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F800 +03FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC00 +07F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F80003FC0007F800 +03FC0007F80003FC0007F80003FC0007F80003FC0007F8007FFFE0FFFFC07FFFE0FFFFC07FFFE0 +FFFFC02A327FB12E>12 D45 +D<0001E0000003E000000FE000007FE0001FFFE000FFFFE000FFBFE000E03FE000003FE000003F +E000003FE000003FE000003FE000003FE000003FE000003FE000003FE000003FE000003FE00000 +3FE000003FE000003FE000003FE000003FE000003FE000003FE000003FE000003FE000003FE000 +003FE000003FE000003FE000003FE000003FE000003FE000003FE000003FE000003FE000003FE0 +00003FE000003FE000003FE000003FE0007FFFFFF07FFFFFF07FFFFFF01C2E7AAD29>49 +D<003FF00001FFFE0007FFFF800FC07FE01E001FF03C000FF87F0007FC7F8007FEFFC007FEFFC0 +03FEFFC003FFFFC003FF7F8003FF7F8003FF3F0003FF000003FF000003FE000003FE000007FC00 +0007FC00000FF800000FF000001FE000001FC000003F8000007F000000FE000001F8000001F000 +0003E00000078007000F0007001E0007003C000F0078000E00F0000E01C0001E03FFFFFE07FFFF +FE0FFFFFFE1FFFFFFE3FFFFFFE7FFFFFFCFFFFFFFCFFFFFFFCFFFFFFFC202E7CAD29>I<000FFC +0000007FFF800001F01FE00003C00FF000070007F8000FE007FC000FF007FC001FF007FE001FF8 +07FE001FF807FE001FF807FE001FF807FE000FF007FC0007E007FC00018007FC0000000FF80000 +000FF00000001FE00000001FC00000007F8000001FFE0000001FFC0000001FFF800000001FF000 +000007F800000003FC00000003FE00000003FF00000001FF80000001FF800E0001FFC03F8001FF +C07FC001FFC07FC001FFC0FFE001FFC0FFE001FFC0FFE001FF80FFE001FF80FFC003FF007F8003 +FF003F0003FE001F0007FC000FE01FF80007FFFFE00001FFFF8000001FFC0000222E7DAD29>I< +0000007800000000F800000001F800000003F800000007F800000007F80000000FF80000001FF8 +0000003FF80000007FF800000077F8000000F7F8000001E7F8000003C7F800000787F800000707 +F800000F07F800001E07F800003C07F800007807F800007007F80000F007F80001E007F80003C0 +07F800078007F8000F0007F8000F0007F8001E0007F8003C0007F800780007F800F00007F800FF +FFFFFFF0FFFFFFFFF0FFFFFFFFF000000FF80000000FF80000000FF80000000FF80000000FF800 +00000FF80000000FF80000000FF80000000FF800000FFFFFF0000FFFFFF0000FFFFFF0242E7EAD +29>I<0C0000380FC003F80FFFFFF80FFFFFF00FFFFFE00FFFFFC00FFFFF800FFFFE000FFFFC00 +0FFFF0000FFF00000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0FF8 +000F7FFF000FFFFFC00FF01FE00F800FF00F0007F80E0007FC000003FC000003FE000003FE0000 +03FF000003FF1E0003FF3F0003FF7F8003FFFF8003FFFFC003FFFFC003FEFF8003FEFF8003FE7F +0007FC7C0007F83C000FF01E001FE00FC07FC007FFFF8001FFFE00003FE000202E7CAD29>I<00 +0003FF80018000003FFFF003800001FFFFFC0F800007FF007F1F80001FF8000FBF80003FE00003 +FF8000FF800000FF8001FF0000007F8003FE0000003F8007FC0000003F8007FC0000001F800FF8 +0000001F801FF80000000F801FF00000000F803FF000000007803FF000000007807FF000000007 +807FE000000007807FE000000000007FE00000000000FFE00000000000FFE00000000000FFE000 +00000000FFE00000000000FFE00000000000FFE00000000000FFE00000000000FFE00000000000 +FFE000000000007FE000000000007FE000000000007FE000000000007FF000000003803FF00000 +0003803FF000000003801FF000000003801FF800000007800FF8000000070007FC000000070007 +FC0000000E0003FE0000001E0001FF0000003C0000FF8000007800003FE00000F000001FF80003 +E0000007FF003F80000001FFFFFE000000003FFFF80000000003FF80000031317BB03C>67 +DI< +FFFFFFFFFFF0FFFFFFFFFFF0FFFFFFFFFFF000FFC0003FF000FFC00007F800FFC00003F800FFC0 +0000F800FFC00000F800FFC000007800FFC000007800FFC000003800FFC000003800FFC0000038 +00FFC000001C00FFC000001C00FFC007001C00FFC007001C00FFC007000000FFC007000000FFC0 +07000000FFC00F000000FFC01F000000FFC03F000000FFFFFF000000FFFFFF000000FFFFFF0000 +00FFC03F000000FFC01F000000FFC00F000000FFC007000000FFC007000000FFC007000000FFC0 +07000000FFC007000000FFC000000000FFC000000000FFC000000000FFC000000000FFC0000000 +00FFC000000000FFC000000000FFC000000000FFC000000000FFC000000000FFC000000000FFC0 +000000FFFFFFF00000FFFFFFF00000FFFFFFF000002E317EB034>70 D<000003FF80018000003F +FFF003800001FFFFFC0F800007FF007F1F80001FF8000FBF80003FE00003FF8000FF800000FF80 +01FF0000007F8003FE0000003F8007FC0000003F8007FC0000001F800FF80000001F801FF80000 +000F801FF00000000F803FF000000007803FF000000007807FF000000007807FE000000007807F +E000000000007FE00000000000FFE00000000000FFE00000000000FFE00000000000FFE0000000 +0000FFE00000000000FFE00000000000FFE00000000000FFE00000000000FFE00007FFFFFE7FE0 +0007FFFFFE7FE00007FFFFFE7FE0000001FF807FF0000001FF803FF0000001FF803FF0000001FF +801FF0000001FF801FF8000001FF800FF8000001FF8007FC000001FF8007FC000001FF8003FE00 +0001FF8001FF000001FF8000FF800001FF80003FE00003FF80001FF80007FF800007FF803F3F80 +0001FFFFFE1F8000003FFFF80780000003FFC0018037317BB041>I73 +D76 DI<00000FFE0000000000FFFFE000000007FFFFFC +0000001FFC07FF0000003FE000FF800000FF80003FE00001FF00001FF00003FE00000FF80007FC +000007FC0007FC000007FC000FF8000003FE001FF8000003FF001FF0000001FF003FF0000001FF +803FF0000001FF803FF0000001FF807FE0000000FFC07FE0000000FFC07FE0000000FFC0FFE000 +0000FFE0FFE0000000FFE0FFE0000000FFE0FFE0000000FFE0FFE0000000FFE0FFE0000000FFE0 +FFE0000000FFE0FFE0000000FFE0FFE0000000FFE0FFE0000000FFE0FFE0000000FFE07FE00000 +00FFC07FE0000000FFC07FF0000001FFC07FF0000001FFC03FF0000001FF803FF0000001FF801F +F8000003FF001FF8000003FF000FFC000007FE000FFC000007FE0007FE00000FFC0003FF00001F +F80001FF80003FF00000FFC0007FE000003FE000FF8000001FFC07FF00000007FFFFFC00000000 +FFFFE0000000000FFE00000033317BB03E>79 D82 D<001FF0018000FFFF03 +8003FFFFC78007F00FFF800F8001FF801F00007F803F00001F803E00000F807E00000F807E0000 +0780FE00000780FE00000780FE00000380FF00000380FF00000380FF80000000FFE00000007FFC +0000007FFFE000007FFFFE00003FFFFFC0001FFFFFF0001FFFFFF8000FFFFFFC0003FFFFFE0001 +FFFFFF00007FFFFF80001FFFFF800000FFFFC0000007FFC0000000FFE00000003FE00000003FE0 +0000001FE06000001FE0E000000FE0E000000FE0E000000FE0E000000FC0F000000FC0F000000F +C0F800001F80FC00001F80FF00003F00FFC0007E00FFFC01FC00F1FFFFF800E03FFFE000C007FF +000023317BB02E>I<007FF8000003FFFF000007FFFFC0000FE01FE0001FF007F0001FF003F800 +1FF003FC001FF001FE000FE001FE0007C001FE00010001FE00000001FE00000001FE000001FFFE +00003FFFFE0001FFF1FE0007FE01FE000FF001FE001FC001FE003F8001FE007F8001FE00FF0001 +FE00FF0001FE00FF0001FE00FF0001FE00FF0003FE007F8003FE007FC00EFE003FF03CFF000FFF +F87FF807FFF03FF800FF800FF825207E9F28>97 D<01F8000000FFF8000000FFF8000000FFF800 +00000FF800000007F800000007F800000007F800000007F800000007F800000007F800000007F8 +00000007F800000007F800000007F800000007F800000007F800000007F800000007F80FF00007 +F87FFE0007F9FFFF8007FFE03FC007FF000FE007FE0007F007F80003F807F80003FC07F80003FC +07F80001FE07F80001FE07F80001FE07F80001FF07F80001FF07F80001FF07F80001FF07F80001 +FF07F80001FF07F80001FF07F80001FF07F80001FE07F80001FE07F80001FE07F80003FC07F800 +03FC07FC0007F807FE0007F007F7001FE007E3E07FC007C1FFFF0007807FFE0007001FE0002832 +7EB12E>I<0007FF00007FFFE000FFFFF003FC03F807F007FC0FE007FC1FE007FC3FC007FC3FC0 +03F87FC001F07F8000407F800000FF800000FF800000FF800000FF800000FF800000FF800000FF +800000FF8000007F8000007FC000007FC000003FC0000E3FE0000E1FE0001C0FF0001C07F80078 +03FF01F000FFFFE0007FFF800007FC001F207D9F25>I<00000007E0000003FFE0000003FFE000 +0003FFE00000003FE00000001FE00000001FE00000001FE00000001FE00000001FE00000001FE0 +0000001FE00000001FE00000001FE00000001FE00000001FE00000001FE00000001FE0000FF81F +E0007FFF1FE001FFFFDFE003FE03FFE007F800FFE00FE0003FE01FE0001FE03FC0001FE03FC000 +1FE07F80001FE07F80001FE07F80001FE0FF80001FE0FF80001FE0FF80001FE0FF80001FE0FF80 +001FE0FF80001FE0FF80001FE0FF80001FE07F80001FE07F80001FE07F80001FE03FC0001FE03F +C0001FE01FC0003FE00FE0007FE007F001FFE003FC07DFF001FFFF9FFF007FFE1FFF000FF01FFF +28327DB12E>I<0007FC0000003FFF800000FFFFE00003FC07F00007F801F8000FE000FC001FE0 +007E003FC0007E003FC0003F007FC0003F007F80003F007F80003F80FF80003F80FF80003F80FF +FFFFFF80FFFFFFFF80FFFFFFFF80FF80000000FF80000000FF800000007F800000007F80000000 +3FC00000003FC00003801FC00003801FE00007800FF0000F0007F8001E0003FE00FC0000FFFFF8 +00003FFFE0000003FF000021207E9F26>I<0000FF000007FFC0001FFFE0003FC7F0007F0FF800 +FE0FF801FE0FF801FC0FF803FC07F003FC03E003FC01C003FC000003FC000003FC000003FC0000 +03FC000003FC000003FC0000FFFFF800FFFFF800FFFFF80003FC000003FC000003FC000003FC00 +0003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC +000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003 +FC000003FC000003FC00007FFFF0007FFFF0007FFFF0001D327EB119>I<001FF007E000FFFE3F +F001FFFF7FF807F83FF1F80FE00FE1F80FE00FE0F01FC007F0601FC007F0003FC007F8003FC007 +F8003FC007F8003FC007F8003FC007F8001FC007F0001FC007F0000FE00FE0000FE00FE00007F8 +3FC00007FFFF000006FFFE00000E1FF000000E000000001E000000001E000000001F000000001F +800000001FFFFFC0000FFFFFF8000FFFFFFE0007FFFFFF0003FFFFFF8007FFFFFFC01FFFFFFFE0 +3F00007FE07E00000FF0FC000007F0FC000003F0FC000003F0FC000003F0FC000003F07E000007 +E03F00000FC01FC0003F800FF801FF0007FFFFFE0000FFFFF000001FFF8000252F7E9F29>I<03 +C0000FF0000FF0001FF8001FF8001FFC001FF8001FF8000FF0000FF00003C00000000000000000 +000000000000000000000000000000000001F800FFF800FFF800FFF8000FF80007F80007F80007 +F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007 +F80007F80007F80007F80007F80007F80007F80007F80007F800FFFF80FFFF80FFFF8011337DB2 +17>105 D<01F800FFF800FFF800FFF8000FF80007F80007F80007F80007F80007F80007F80007 +F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007 +F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007 +F80007F80007F80007F80007F80007F80007F80007F80007F80007F800FFFFC0FFFFC0FFFFC012 +327DB117>108 D<03F007F8000FF000FFF03FFF007FFE00FFF07FFF80FFFF00FFF0F03FC1E07F +800FF1C01FE3803FC007F3000FE6001FC007F6000FFC001FE007FE000FFC001FE007FC000FF800 +1FE007FC000FF8001FE007F8000FF0001FE007F8000FF0001FE007F8000FF0001FE007F8000FF0 +001FE007F8000FF0001FE007F8000FF0001FE007F8000FF0001FE007F8000FF0001FE007F8000F +F0001FE007F8000FF0001FE007F8000FF0001FE007F8000FF0001FE007F8000FF0001FE007F800 +0FF0001FE007F8000FF0001FE007F8000FF0001FE007F8000FF0001FE007F8000FF0001FE007F8 +000FF0001FE0FFFFC1FFFF83FFFFFFFFC1FFFF83FFFFFFFFC1FFFF83FFFF40207D9F47>I<03F0 +07F80000FFF03FFF0000FFF07FFF8000FFF0F03FC0000FF1C01FE00007F3000FE00007F6000FF0 +0007FE000FF00007FC000FF00007FC000FF00007F8000FF00007F8000FF00007F8000FF00007F8 +000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF0 +0007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8 +000FF00007F8000FF00007F8000FF000FFFFC1FFFF80FFFFC1FFFF80FFFFC1FFFF8029207D9F2E +>I<0007FE0000003FFFC00000FFFFF00003FC03FC0007F000FE000FE0007F001FC0003F803FC0 +003FC03FC0003FC07F80001FE07F80001FE07F80001FE0FF80001FF0FF80001FF0FF80001FF0FF +80001FF0FF80001FF0FF80001FF0FF80001FF0FF80001FF07F80001FE07F80001FE07F80001FE0 +3FC0003FC03FC0003FC01FE0007F800FE0007F0007F801FE0003FE07FC0001FFFFF800003FFFC0 +000007FE000024207E9F29>I<01F80FF000FFF87FFE00FFF9FFFF80FFFFE07FC00FFF001FE007 +FE000FF007F80007F807F80007FC07F80003FC07F80003FE07F80003FE07F80001FE07F80001FF +07F80001FF07F80001FF07F80001FF07F80001FF07F80001FF07F80001FF07F80001FF07F80001 +FE07F80003FE07F80003FE07F80003FC07F80007FC07FC0007F807FE000FF007FF001FE007FBE0 +7FC007F9FFFF0007F87FFE0007F81FE00007F800000007F800000007F800000007F800000007F8 +00000007F800000007F800000007F800000007F800000007F800000007F8000000FFFFC00000FF +FFC00000FFFFC00000282E7E9F2E>I<03F03F00FFF07FC0FFF1FFE0FFF3C7F00FF38FF807F70F +F807F60FF807FE0FF807FC07F007FC03E007FC008007F8000007F8000007F8000007F8000007F8 +000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007 +F8000007F8000007F8000007F80000FFFFE000FFFFE000FFFFE0001D207E9F22>114 +D<00FF870007FFEF001FFFFF003F007F003C001F0078000F00F8000700F8000700F8000700FC00 +0700FF000000FFF800007FFFC0003FFFF0003FFFFC000FFFFE0007FFFF0001FFFF80001FFF8000 +00FFC000001FC060000FC0E00007C0E00007C0F00007C0F8000780F8000F80FE000F00FF803E00 +FFFFFC00F3FFF800C07FC0001A207D9F21>I<0038000038000038000038000038000078000078 +0000780000F80000F80001F80003F80007F8001FF800FFFFFEFFFFFEFFFFFE07F80007F80007F8 +0007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F8 +0007F80707F80707F80707F80707F80707F80707F80703F80E03FC0E01FE1C00FFF8007FF0000F +E0182E7EAD20>I<01F80003F000FFF801FFF000FFF801FFF000FFF801FFF0000FF8001FF00007 +F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000F +F00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007 +F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8000FF00007F8001F +F00007F8001FF00003F8003FF00003F8006FF00001FE03CFF80000FFFF8FFF80007FFF0FFF8000 +0FFC0FFF8029207D9F2E>I121 D E /Fk 34 122 df45 +D<07000F800F800F000E00000000000000000000000000000000000000000000007000F800F800 +F000E00009157A940F>58 D<0000030000000300000007000000070000000F0000000F0000001F +0000002F0000002F0000004F0000004F8000008780000087800001078000020780000207800004 +0780000407800008078000080780001007800030078000200780007FFF80004007C0008007C000 +8003C0010003C0030003C0020003C0040003C0040003C00C0003C03C0007C0FF003FFC1E237DA2 +24>65 D<00007F00800003808100000E00630000380027000070001F0000E0000E0001C0000E00 +0380000E000700000E000F000004000E000004001E000004003C000004003C0000080078000000 +0078000000007800000000F000000000F000000000F000000000F000000000F000000000E00000 +0000E000002000E000002000E000004000E000004000F000008000700000800070000100003800 +02000018000400001C0008000006003000000381C0000000FE000000212479A223>67 +D<00FFFFF000000F003C00000F000E00000F000700001E000380001E000380001E0001C0001E00 +01C0003C0001C0003C0001E0003C0001E0003C0001E000780001E000780001E000780001E00078 +0001E000F00003C000F00003C000F00003C000F00003C001E000078001E000078001E000070001 +E0000F0003C0000E0003C0001C0003C0003C0003C00038000780007000078000E000078001C000 +07800700000F801C0000FFFFF0000023227DA125>I<00FFFFFF000F000F000F0003000F000300 +1E0003001E0003001E0002001E0002003C0002003C0002003C0102003C01000078020000780200 +0078060000780E0000FFFC0000F00C0000F00C0000F00C0001E0080001E0080001E0080001E000 +0003C0000003C0000003C0000003C00000078000000780000007800000078000000F800000FFFC +000020227DA120>70 D<00007F00800003808100000E00630000380027000070001F0000E0000E +0001C0000E000380000E000700000E000F000004000E000004001E000004003C000004003C0000 +0800780000000078000000007800000000F000000000F000000000F000000000F000000000F000 +3FFC00E00001E000E00001E000E00001E000E00003C000E00003C000F00003C000700003C00070 +00078000380007800018000F80001C0013800006002300000381C1000000FE000000212479A226 +>I<00FFF8000F00000F00000F00001E00001E00001E00001E00003C00003C00003C00003C0000 +780000780000780000780000F00000F00000F00000F00001E00001E00001E00001E00003C00003 +C00003C00003C0000780000780000780000780000F8000FFF80015227DA113>73 +D<00FFFC00000F8000000F0000000F0000001E0000001E0000001E0000001E0000003C0000003C +0000003C0000003C00000078000000780000007800000078000000F0000000F0000000F0000000 +F0000001E0000001E0000001E0002001E0002003C0004003C0004003C0008003C0008007800180 +078001000780030007800F000F803E00FFFFFE001B227DA11F>76 D<00FF800007FC000F80000F +80000F80001780000F80001780001780002F000013C0002F000013C0004F000013C0008F000023 +C0009E000023C0011E000023C0011E000023C0021E000043C0043C000043C0043C000043C0083C +000041E0083C000081E01078000081E02078000081E02078000081E04078000101E040F0000101 +E080F0000101E100F0000101E100F0000200F201E0000200F201E0000200F401E0000200F801E0 +000400F803C0000400F003C0000400F003C0000C00E003C0001E00C007C000FFC0C07FFC002E22 +7DA12C>I<0000FE0000078380000C00E0003800700070003800E0003801C0001C0380001C0700 +001C0F00001E1E00001E1C00001E3C00001E3C00001E7800001E7800001E7800001EF000003CF0 +00003CF000003CF0000078F0000078E0000078E00000F0E00000F0E00001E0E00001C0F00003C0 +F00007807000070078000E0038001C001C0038000E00E0000703800001FC00001F2479A225>79 +D<00FFFFE0000F0038000F001E000F000E001E0007001E0007001E0007001E0007003C000F003C +000F003C000F003C001E0078001E0078003C00780078007800E000F003C000FFFE0000F0000000 +F0000001E0000001E0000001E0000001E0000003C0000003C0000003C0000003C0000007800000 +0780000007800000078000000F800000FFF8000020227DA121>I<0001F020000E0C40001802C0 +003001C0006001C000E0018000C0018001C0018001C0018003C0010003C0010003C0000003C000 +0003E0000001F8000001FF000000FFE000007FF000001FF8000003FC0000007C0000003C000000 +1E0000001E0000001E0020001C0020001C0020001C002000180060003800600030007000600070 +00C000C8018000C607000081FC00001B247DA21B>83 D86 D<00F8C00185C00705C00E03800E03801C03803C0380380700 +780700780700780700F00E00F00E00F00E00F00E10F01C20701C20703C20305C40308C400F0780 +14157B9419>97 D<03C03F8003800380038007000700070007000E000E000E000E001C001CF81D +0C1E0E3C0638073807380F700F700F700F700FE01EE01EE01EE03CE038E038607060E031C01F00 +10237BA216>I<007E0001C1000301800703800E07801C07803C00003800007800007800007800 +00F00000F00000F00000F00000F00100700100700200300C001830000FC00011157B9416>I<00 +003C0003F80000380000380000380000700000700000700000700000E00000E00000E00000E000 +01C000F9C00185C00705C00E03800E03801C03803C0380380700780700780700780700F00E00F0 +0E00F00E00F00E10F01C20701C20703C20305C40308C400F078016237BA219>I<00F803840E02 +1C023C0238027804F018FFE0F000F000E000E000E000E000E002E0026004701830600F800F157A +9416>I<00003E0000470000CF00018F0001860003800003800003800007000007000007000007 +00000700000E0000FFF0000E00000E00000E00001C00001C00001C00001C00001C000038000038 +0000380000380000380000700000700000700000700000700000E00000E00000E00000E00000C0 +0001C00001C000718000F18000F300006200003C0000182D82A20F>I<001F180030B800E0B801 +C07001C0700380700780700700E00F00E00F00E00F00E01E01C01E01C01E01C01E01C01E03800E +03800E0780060B8006170001E700000700000700000E00000E00000E00701C00F01800F0300060 +E0003F8000151F7E9416>I<00F0000FE00000E00000E00000E00001C00001C00001C00001C000 +038000038000038000038000070000071F0007218007C0C00F00E00F00E00E00E00E00E01C01C0 +1C01C01C01C01C01C0380380380380380380380704700708700E08700E10700610E006206003C0 +16237DA219>I<00C001E001C001C0000000000000000000000000000000001C00230043004300 +8700870087000E000E001C001C001C00380038003840708070807080710032001C000B217BA00F +>I<01E01FC001C001C001C0038003800380038007000700070007000E000E000E000E001C001C +001C001C0038003800380038007000700070007100E200E200E200E200640038000B237CA20C> +108 D<1C0F80F8002610C10C00476066060087807807008780780700870070070087007007000E +00E00E000E00E00E000E00E00E000E00E00E001C01C01C001C01C01C001C01C01C001C01C03820 +380380384038038070403803807080380380308070070031003003001E0023157B9428>I<1C0F +002631C04740C08780E08780E08700E08700E00E01C00E01C00E01C00E01C01C03801C03801C03 +801C0704380708380E08380E103806107006203003C016157B941B>I<007E0001C30003818007 +01C00E01C01C01E03C01E03801E07801E07801E07801E0F003C0F003C0F00380F0078070070070 +0E00700C0030180018700007C00013157B9419>I<01C1F002621804741C08780C08700E08700E +08701E00E01E00E01E00E01E00E01E01C03C01C03C01C03C01C07803807003807003C0E003C1C0 +072380071E000700000700000E00000E00000E00000E00001C00001C00001C0000FFC000171F7F +9419>I<1C1F002620804741C08783C08703C08701808700000E00000E00000E00000E00001C00 +001C00001C00001C000038000038000038000038000070000030000012157B9415>114 +D<00FC000183000200800401800C03800C03000C00000F00000FF00007FC0003FE00003E00000F +00000700700700F00600F00600E004004008002030001FC00011157D9414>I<00C001C001C001 +C001C003800380038003800700FFF8070007000E000E000E000E001C001C001C001C0038003800 +38003810702070207040708031001E000D1F7C9E10>I<1E00602300E04380E04381C08381C087 +01C08701C00703800E03800E03800E03801C07001C07001C07001C07081C0E10180E101C0E101C +1E200C262007C3C015157B941A>I<1E03802307C04387C04383C08381C08700C08700C0070080 +0E00800E00800E00801C01001C01001C01001C02001C02001C04001C08001C08000C300003C000 +12157B9416>I<1E00302300704380704380E08380E08700E08700E00701C00E01C00E01C00E01 +C01C03801C03801C03801C03801C07001C07001C07001C0F000C3E0003CE00000E00000E00001C +00601C00F03800F03000E0600080C0004380003E0000141F7B9418>121 +D E /Fl 80 127 df<001F83E000706E3000C07C780180F8780380F07807007000070070000700 +7000070070000700700007007000070070000700700007007000FFFFFFC0070070000700700007 +007000070070000700700007007000070070000700700007007000070070000700700007007000 +070070000700700007007000070070000700700007007000070078007FE3FF801D2380A21C>11 +D<001FC0000070200000C010000180380003807800070078000700300007000000070000000700 +000007000000070000000700000007000000FFFFF8000700780007003800070038000700380007 +003800070038000700380007003800070038000700380007003800070038000700380007003800 +07003800070038000700380007003800070038007FE1FF80192380A21B>I<001FD80000703800 +00C078000180780003807800070038000700380007003800070038000700380007003800070038 +000700380007003800FFFFF8000700380007003800070038000700380007003800070038000700 +380007003800070038000700380007003800070038000700380007003800070038000700380007 +00380007003800070038007FF3FF80192380A21B>I<000FC07F00007031C08000E00B00400180 +1E00E003803E01E007003C01E007001C00C007001C000007001C000007001C000007001C000007 +001C000007001C000007001C0000FFFFFFFFE007001C01E007001C00E007001C00E007001C00E0 +07001C00E007001C00E007001C00E007001C00E007001C00E007001C00E007001C00E007001C00 +E007001C00E007001C00E007001C00E007001C00E007001C00E007001C00E007001C00E07FF1FF +CFFE272380A229>I<07070F1E1C38604080080976A218>19 D<70F8FCFC740404040408081010 +2040060F7CA20E>39 D<00200040008001000300060004000C000C001800180030003000300070 +00600060006000E000E000E000E000E000E000E000E000E000E000E000E000E000E00060006000 +60007000300030003000180018000C000C0004000600030001000080004000200B327CA413>I< +800040002000100018000C000400060006000300030001800180018001C000C000C000C000E000 +E000E000E000E000E000E000E000E000E000E000E000E000E000C000C000C001C0018001800180 +030003000600060004000C00180010002000400080000B327DA413>I<70F8FCFC740404040408 +0810102040060F7C840E>44 DI<70F8F8F87005057C840E>I<00008000 +0180000180000300000300000300000600000600000600000C00000C00000C0000180000180000 +180000300000300000300000600000600000600000C00000C00000C00001800001800001800001 +80000300000300000300000600000600000600000C00000C00000C000018000018000018000030 +0000300000300000600000600000600000C00000C00000C0000011317DA418>I<01F000071C00 +0C06001803003803803803807001C07001C07001C07001C0F001E0F001E0F001E0F001E0F001E0 +F001E0F001E0F001E0F001E0F001E0F001E0F001E0F001E0F001E07001C07001C07001C07803C0 +3803803803801C07000C0600071C0001F00013227EA018>I<008003800F80F380038003800380 +038003800380038003800380038003800380038003800380038003800380038003800380038003 +80038003800380038007C0FFFE0F217CA018>I<03F0000C1C001007002007804003C04003C080 +03E0F003E0F801E0F801E0F801E02003E00003E00003C00003C0000780000700000E00001C0000 +180000300000600000C0000180000100000200200400200800201800603000403FFFC07FFFC0FF +FFC013217EA018>I<03F8000C1E001007002007804007C07807C07803C07807C03807C0000780 +000780000700000F00000E0000380003F000001C00000F000007800007800003C00003C00003E0 +2003E07003E0F803E0F803E0F003C04003C0400780200780100F000C1C0003F00013227EA018> +I<000200000600000E00000E00001E00001E00002E00004E00004E00008E00008E00010E00020E +00020E00040E00040E00080E00100E00100E00200E00200E00400E00800E00FFFFF8000E00000E +00000E00000E00000E00000E00000E00001F0001FFF015217FA018>I<1000801E07001FFF001F +FE001FF80013E00010000010000010000010000010000010000010F800130E0014070018038010 +03800001C00001C00001E00001E00001E00001E07001E0F001E0F001E0E001C08001C04003C040 +03802007001006000C1C0003F00013227EA018>I<007E0001C1000300800601C00E03C01C03C0 +180180380000380000780000700000700000F0F800F30C00F40600F40300F80380F801C0F001C0 +F001E0F001E0F001E0F001E0F001E07001E07001E07001E03801C03801C01803801C03000C0600 +070C0001F00013227EA018>I<4000006000007FFFE07FFFC07FFFC0400080C001008001008002 +0080020000040000080000080000100000300000200000600000600000600000E00000C00000C0 +0001C00001C00001C00001C00003C00003C00003C00003C00003C00003C00003C00003C0000180 +0013237DA118>I<01F800060E000803001001802001802000C06000C06000C06000C07000C078 +01803E01003F02001FC4000FF80003F80003FC00067F00083F80100F803007C06001C06000E0C0 +00E0C00060C00060C00060C000606000406000C03000801803000E0E0003F00013227EA018>I< +01F000060C000C0600180700380380700380700380F001C0F001C0F001C0F001E0F001E0F001E0 +F001E0F001E07001E07003E03803E01805E00C05E00619E003E1E00001C00001C00001C0000380 +000380300300780700780600700C002018001030000FC00013227EA018>I<70F8F8F870000000 +000000000000000070F8F8F87005157C940E>I<70F8F8F870000000000000000000000070F8F8 +F87808080808101010204040051F7C940E>I61 +D<000FE00000701C0000800200030001800400004008000020080000201007C010201830082030 +08084060040440C0078441C0038481C00382838003828380038283800382838003828380038283 +8003828380038281C0038241C0038240C007824060078420300B84201831881007C0F008000000 +08000000040000000300000E00800078007007C0000FFC001F237DA226>64 +D<0001800000018000000180000003C0000003C0000003C0000005E0000005E000000DF0000008 +F0000008F0000010F800001078000010780000203C0000203C0000203C0000401E0000401E0000 +401E0000800F0000800F0000FFFF000100078001000780030007C0020003C0020003C0040003E0 +040001E0040001E00C0000F00C0000F03E0001F8FF800FFF20237EA225>II<0007E0100038183000E0063001C00170038000F007 +0000F00E0000701E0000701C0000303C0000303C0000307C0000107800001078000010F8000000 +F8000000F8000000F8000000F8000000F8000000F8000000F800000078000000780000107C0000 +103C0000103C0000101C0000201E0000200E000040070000400380008001C0010000E002000038 +1C000007E0001C247DA223>II< +FFFFFFC00F8007C0078001C0078000C00780004007800040078000600780002007800020078000 +2007802020078020000780200007802000078060000780E00007FFE0000780E000078060000780 +200007802000078020000780200807800008078000080780001007800010078000100780003007 +80003007800070078000E00F8003E0FFFFFFE01D227EA121>II<0007F008003C0C1800E0021801C001B8038000F8070000780F00 +00381E0000381E0000183C0000183C0000187C0000087800000878000008F8000000F8000000F8 +000000F8000000F8000000F8000000F8000000F8001FFF780000F8780000787C0000783C000078 +3C0000781E0000781E0000780F00007807000078038000B801C000B800E00318003C0C080007F0 +0020247DA226>III<03FFF0001F00000F +00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F +00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00700F00F80F00F80F +00F80E00F01E00401C0020380018700007C00014237EA119>IIIII<000FE00000783C0000E00E0003C00780078003C00F0001E00E0000E01E0000F03C000078 +3C0000787C00007C7C00007C7800003C7800003CF800003EF800003EF800003EF800003EF80000 +3EF800003EF800003EF800003EF800003E7800003C7C00007C7C00007C3C0000783E0000F81E00 +00F00F0001E00F0001E0078003C003C0078000E00E0000783C00000FE0001F247DA226>II82 D<03F0200C0C601802603001E07000E0600060E00060E00060E00020 +E00020E00020F00000F000007800007F00003FF0001FFE000FFF0003FF80003FC00007E00001E0 +0000F00000F0000070800070800070800070800070C00060C00060E000C0F000C0C80180C60700 +81FC0014247DA21B>I<7FFFFFF87807807860078018400780084007800840078008C007800C80 +078004800780048007800480078004000780000007800000078000000780000007800000078000 +000780000007800000078000000780000007800000078000000780000007800000078000000780 +000007800000078000000780000007800000078000000FC00003FFFF001E227EA123>IIII<7FF807 +FF0007E001F80003C000E00003E000C00001E000800000F001000000F80300000078020000007C +040000003E0C0000001E080000001F100000000FB000000007A000000007C000000003E0000000 +01E000000001F000000003F80000000278000000047C0000000C3E000000081E000000101F0000 +00300F80000020078000004007C00000C003E000008001E000010001F000030000F000070000F8 +001F8001FC00FFE007FFC022227FA125>II< +7FFFFE7E003E78003C7000786000784000F0C000F0C001E08003C08003C0800780000780000F00 +001F00001E00003C00003C0000780000780000F00001F00001E00103C00103C001078001078003 +0F00031E00021E00023C00063C000E78001EF8007EFFFFFE18227DA11E>II93 D<0FE0001838003C0C003C0E00 +18070000070000070000070000FF0007C7001E07003C0700780700700700F00708F00708F00708 +F00F087817083C23900FC1E015157E9418>97 D<0E0000FE00001E00000E00000E00000E00000E +00000E00000E00000E00000E00000E00000E00000E00000E1F000E61C00E80600F00300E00380E +003C0E001C0E001E0E001E0E001E0E001E0E001E0E001E0E001E0E001C0E003C0E00380F00700C +80600C41C0083F0017237FA21B>I<01FE000703000C07801C0780380300780000700000F00000 +F00000F00000F00000F00000F00000F000007000007800403800401C00800C010007060001F800 +12157E9416>I<0000E0000FE00001E00000E00000E00000E00000E00000E00000E00000E00000 +E00000E00000E00000E001F8E00704E00C02E01C01E03800E07800E07000E0F000E0F000E0F000 +E0F000E0F000E0F000E0F000E07000E07800E03800E01801E00C02E0070CF001F0FE17237EA21B +>I<01FC000707000C03801C01C03801C07801E07000E0F000E0FFFFE0F00000F00000F00000F0 +0000F000007000007800203800201C00400E008007030000FC0013157F9416>I<003C00C6018F +038F030F070007000700070007000700070007000700FFF8070007000700070007000700070007 +00070007000700070007000700070007000700070007807FF8102380A20F>I<00007001F19807 +1E180E0E181C07001C07003C07803C07803C07803C07801C07001C07000E0E000F1C0019F00010 +00001000001800001800001FFE000FFFC00FFFE03800F0600030400018C00018C00018C0001860 +00306000303800E00E038003FE0015217F9518>I<0E0000FE00001E00000E00000E00000E0000 +0E00000E00000E00000E00000E00000E00000E00000E00000E1F800E60C00E80E00F00700F0070 +0E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E0070 +0E00700E0070FFE7FF18237FA21B>I<1C003E003E003E001C0000000000000000000000000000 +0000000E00FE001E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E00 +0E000E00FFC00A227FA10E>I<01C003E003E003E001C000000000000000000000000000000000 +01E00FE001E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000 +E000E000E000E000E000E000E060E0F0C0F18061803E000B2C82A10F>I<0E0000FE00001E0000 +0E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E03FC0E01F0 +0E01C00E01800E02000E04000E08000E10000E38000EF8000F1C000E1E000E0E000E07000E0780 +0E03C00E01C00E01E00E00F00E00F8FFE3FE17237FA21A>I<0E00FE001E000E000E000E000E00 +0E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E +000E000E000E000E000E000E000E00FFE00B237FA20E>I<0E1FC07F00FE60E183801E807201C0 +0F003C00E00F003C00E00E003800E00E003800E00E003800E00E003800E00E003800E00E003800 +E00E003800E00E003800E00E003800E00E003800E00E003800E00E003800E00E003800E00E0038 +00E00E003800E0FFE3FF8FFE27157F942A>I<0E1F80FE60C01E80E00F00700F00700E00700E00 +700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00 +70FFE7FF18157F941B>I<01FC000707000C01801800C03800E0700070700070F00078F00078F0 +0078F00078F00078F00078F000787000707800F03800E01C01C00E038007070001FC0015157F94 +18>I<0E1F00FE61C00E80600F00700E00380E003C0E001C0E001E0E001E0E001E0E001E0E001E +0E001E0E001E0E003C0E003C0E00380F00700E80E00E41C00E3F000E00000E00000E00000E0000 +0E00000E00000E00000E00000E0000FFE000171F7F941B>I<01F8200704600E02601C01603801 +E07800E07800E0F000E0F000E0F000E0F000E0F000E0F000E0F000E07000E07800E03801E01C01 +E00C02E0070CE001F0E00000E00000E00000E00000E00000E00000E00000E00000E00000E0000F +FE171F7E941A>I<0E3CFE461E8F0F0F0F060F000E000E000E000E000E000E000E000E000E000E +000E000E000E000F00FFF010157F9413>I<0F8830786018C018C008C008E008F0007F803FE00F +F001F8003C801C800C800CC00CC008E018D0308FC00E157E9413>I<0200020002000200060006 +0006000E001E003E00FFF80E000E000E000E000E000E000E000E000E000E000E000E040E040E04 +0E040E040E040708030801F00E1F7F9E13>I<0E0070FE07F01E00F00E00700E00700E00700E00 +700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00F00E00F00601700382 +7800FC7F18157F941B>IIIII<3FFFC0380380300780 +200700600E00401C00403C0040380000700000E00001E00001C0000380400700400F00400E00C0 +1C0080380080780180700780FFFF8012157F9416>I<0E021F04238841F080E00F057CA018>126 +D E /Fm 9 117 df<7FFCFFF8FFF8FFF80E047A8E15>45 D<003FFFE0003FFFE00001F8000001 +F0000001F0000001F0000001F0000003E0000003E0000003E0000003E0000007C0000007C00000 +07C0000007C000000F8000000F8000000F8000000F8000001F0000001F0000001F0000001F0000 +003E0000003E0000003E0000003E0000007C0000007C0000007C0000007C000000F8000000F800 +0000F8000000F8000001F0000001F0000001F0000003F00000FFFF8000FFFF80001B297DA817> +73 D<0003FFFC0003FFFC00000FC000000F8000000F8000000F8000000F8000001F0000001F00 +00001F0000001F0000003E0000003E0000003E0000003E0000007C0000007C0000007C0000007C +000000F8000000F8000000F8000000F8000001F0000001F0000001F0000001F0000003E0000003 +E0000003E0000003E0003807C0007C07C000FC07C000FC0F8000F80F8000F00F0000C01E0000C0 +3C00004078000030F000001F8000001E2A7AA81F>I<003FFFFF80003FFFFFF00001F801F80001 +F0007C0001F0003E0001F0003E0001F0003F0003E0003F0003E0003F0003E0003F0003E0003F00 +07C0007E0007C0007E0007C0007E0007C000FC000F8000F8000F8001F0000F8003E0000F8007C0 +001F001F00001FFFFC00001F000000001F000000003E000000003E000000003E000000003E0000 +00007C000000007C000000007C000000007C00000000F800000000F800000000F800000000F800 +000001F000000001F000000001F000000003F00000007FFF800000FFFF80000028297CA829>80 +D<001F800070C001C0600380600700600F00601E00603E00C03C00C07C03807C1E007FF000F800 +00F80000F80000F80000F80000F00000F00000F000207000607800C03801801807000C1C0007F0 +00131A79991B>101 D<001C003E003E003C003800000000000000000000000000000000000007 +800CE0186030F030F060F060F061E0C1E001E003C003C00780078007800F000F000F0C1E0C1E0C +1E183C181C301C200C4007800F287BA712>105 D<07807C0008C1870010E2038030F4038030FC +03C060F803C060F003C060F003C0C1E0078001E0078001E0078001E0078003C00F0003C00F0003 +C00F0003C01E0007801E0007801E0C07803C0C07803C080F003C180F0078100F0038300F003860 +1E0018C00C000F001E1A7B9922>110 D<000FC000787000E03803C01C07801C0F001E1F001E1E +001F3E001F3C001F7C001F7C001FF8003EF8003EF8003EF8003CF0007CF00078F000F8F000F070 +01E07801C03803801807000E1C0003F000181A79991F>I<00300078007800F000F000F000F001 +E001E001E001E0FFFFFFFF03C003C007800780078007800F000F000F000F001E001E001E001E00 +3C003C063C063C0C780C78183810383018400F8010257AA414>116 D E +/Fn 51 123 df<0007F81F80003C067060007003E0F000E007C1F001C00FC1F003C00F80E00780 +078040078007800007800780000780078000078007800007800780000780078000078007800007 +800780000780078000FFFFFFFF00FFFFFFFF000780078000078007800007800780000780078000 +078007800007800780000780078000078007800007800780000780078000078007800007800780 +000780078000078007800007800780000780078000078007800007800780000780078000078007 +80000780078000078007C000FFF87FFE00FFF87FFE00242A7FA923>11 D<0007F800003C060000 +70010000E0070001C00F8003C00F8007800F800780070007800000078000000780000007800000 +07800000078000000780000007800000FFFFFF80FFFFFF8007800F800780078007800780078007 +800780078007800780078007800780078007800780078007800780078007800780078007800780 +07800780078007800780078007800780078007800780078007800780078007800780FFF87FFCFF +F87FFC1E2A7FA921>I<0004000800100020004000C0018003000300060006000E000C001C0018 +0038003800380030007000700070007000F000F000E000E000E000E000E000E000E000E000E000 +E000E000F000F0007000700070007000300038003800380018001C000C000E0006000600030003 +00018000C0004000200010000800040E3D7BAC17>40 D<800040002000100008000C0006000300 +03000180018001C000C000E0006000700070007000300038003800380038003C003C001C001C00 +1C001C001C001C001C001C001C001C001C003C003C003800380038003800300070007000700060 +00E000C001C0018001800300030006000C00080010002000400080000E3D7DAC17>I<78FCFCFE +FE7A02020202040404081010204007127B8511>44 DI<78FCFCFC +FC7806067B8511>I<00000600000E00000E00001C00001C00001C000038000038000038000070 +0000700000E00000E00000E00001C00001C00001C0000380000380000380000700000700000700 +000E00000E00000E00001C00001C00001C0000380000380000700000700000700000E00000E000 +00E00001C00001C00001C0000380000380000380000700000700000700000E00000E00000E0000 +1C00001C0000380000380000380000700000700000700000E00000E00000C00000173C7DAC1E> +I<007F000001C1C0000780F0000F0078000E0038001C001C003C001E003C001E003C001E007800 +0F0078000F0078000F0078000F00F8000F80F8000F80F8000F80F8000F80F8000F80F8000F80F8 +000F80F8000F80F8000F80F8000F80F8000F80F8000F80F8000F80F8000F80F8000F8078000F00 +78000F0078000F0078000F003C001E003C001E003C001E001C001C000E0038000F0078000780F0 +0001C1C000007F000019297EA71E>I<00100000700001F0000FF000FEF000F0F00000F00000F0 +0000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F0 +0000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F0 +0000F00000F00000F00001F8007FFFE07FFFE013287BA71E>I<00FE0007FF800E07E01803F020 +01F82000F840007C40007CF8007EFC007EFC003EFC003EFC003E78007E00007E00007C00007C00 +00F80000F80001F00001E00003C0000780000700000E00001C0000380000700000600000C00001 +80020300020600040C000418000410000C3FFFFC7FFFF8FFFFF8FFFFF817287DA71E>I<007F00 +0003FFC0000701F0000C00F80010007C001C007C003E007E003E003E003E003E001E003E000C00 +7E0000007C0000007C00000078000000F0000000E0000001C0000007000000FF00000001E00000 +00F0000000780000003C0000003E0000001F0000001F0000001F8000001F8030001F8078001F80 +FC001F80FC001F80FC001F00F8001F0040003F0040003E0030007C001800F8000F01F00003FFC0 +00007F000019297EA71E>I<00006000000060000000E0000001E0000001E0000003E0000003E0 +000005E0000009E0000009E0000011E0000021E0000021E0000041E0000081E0000081E0000101 +E0000201E0000201E0000401E0000801E0000801E0001001E0003001E0002001E0004001E000C0 +01E000FFFFFF80FFFFFF800001E0000001E0000001E0000001E0000001E0000001E0000001E000 +0001E0000003F000007FFF80007FFF8019287EA71E>I<1800181F00F01FFFE01FFFC01FFF801F +FF0011F800100000100000100000100000100000100000100000100000107E001183801600C018 +00E010007000007800003C00003C00003C00003E00003E00003E70003EF8003EF8003EF8003EF8 +003C80003C40007C4000782000783000F01801E00E07C007FF0001FC0017297DA71E>I<000FE0 +00003FF80000F81C0001E00C0003801E0007803E000F003E000E001C001E0000001C0000003C00 +00003C0000007C0000007800000078000000F83F0000F840E000F9807000F9003800FA001C00FC +001E00FC001E00FC000F00F8000F00F8000F80F8000F80F8000F80F8000F8078000F8078000F80 +78000F807C000F803C000F003C000F001C001E001E001E000E003C000700780003C0F00001FFC0 +00007F000019297EA71E>I<20000000380000003FFFFF803FFFFF803FFFFF007FFFFF00600002 +004000040040000400400008008000100080002000000020000000400000008000000080000001 +000000030000000200000006000000060000000C0000000C0000001C0000001C0000001C000000 +38000000380000003800000078000000780000007800000078000000F8000000F8000000F80000 +00F8000000F8000000F8000000F8000000F8000000700000192A7DA81E>I<007F000001FFC000 +0381F000060078000C003C001C001C0018000E0038000E0038000E0038000E003C000E003C000E +003E001C001F8018001FC038000FF0600007F8C00003FF800001FF0000007FC00000FFE000030F +F8000603FC001C01FE0038007E0030003F0070000F0070000780E0000780E0000380E0000380E0 +000380E0000380F0000300700007007800060038000C001E0038000F80F00003FFE000007F0000 +19297EA71E>I<007F000001FFC00007C1E0000F0070001E0038001C003C003C001C0078001E00 +78001E00F8000F00F8000F00F8000F00F8000F00F8000F80F8000F80F8000F80F8000F8078000F +8078001F803C001F803C001F801C002F800E004F800700CF8003810F80007E0F8000000F000000 +0F0000000F0000001E0000001E0000001E0000003C001C003C003E0078003E0070003C00E00018 +01C0001C0780000FFE000003F8000019297EA71E>I<78FCFCFCFC780000000000000000000000 +00000078FCFCFCFC78061A7B9911>I<00001800000000180000000018000000003C000000003C +000000003C000000007E000000007E00000000FF000000009F000000009F000000011F80000001 +0F800000010F8000000207C000000207C000000207C000000403E000000403E000000403E00000 +0801F000000801F000001801F800001000F800001000F800002000FC000020007C00003FFFFC00 +007FFFFE000040003E000040003E000080001F000080001F000080001F000100000F800100000F +800100000F8002000007C007000007C01F80000FE0FFF000FFFFFFF000FFFF282A7EA92D>65 +D<0000FF00100007FFE030001FC07830003E000C7000F80006F001F00003F003E00001F007C000 +00F00F800000700F800000701F000000303F000000303E000000303E000000107E000000107E00 +0000107C00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC +00000000FC00000000FC000000007C000000007E000000007E000000103E000000103E00000010 +3F000000101F000000200F800000200F8000006007C000004003E000008001F000018000F80003 +00003E000E00001FC038000007FFE0000000FF8000242B7DA92B>67 DII77 DI80 D<00FE010003FF83000F81E3001E0037003C001F0038000F007800070070000700F0000300 +F0000300F0000300F0000100F8000100F8000100FC0000007C0000007F0000003FE000001FFF00 +000FFFE00007FFF80003FFFC00007FFE000007FF0000007F0000001F8000000F80000007C00000 +07C0800003C0800003C0800003C0800003C0C00003C0C0000380C0000380E0000780F0000700F8 +000E00EE001C00C3C07800C1FFF000803FC0001A2B7DA921>83 D<01FC00000E0780001001C000 +3C00E0003E00F0003E0078001C00780008007800000078000000780000007800007FF80003E078 +000F8078001F0078003E0078007C00780078007820F8007820F8007820F8007820F800F8207C00 +F8203C013C401F063FC007F80F001B1A7E991E>97 D<07800000FF800000FF8000000F80000007 +800000078000000780000007800000078000000780000007800000078000000780000007800000 +07800000078000000783F000078C1C0007B0070007A0038007C003C0078001E0078001E0078000 +F0078000F0078000F8078000F8078000F8078000F8078000F8078000F8078000F8078000F00780 +00F0078001F0078001E0078001C007C003C00740078007200E0006181C000407E0001D2A7FA921 +>I<007F8001C0700780080F003C1E007C3C007C3C00387C0010780000F80000F80000F80000F8 +0000F80000F80000F80000F800007800007C00003C00043C00041E00080F001007802001C0C000 +7F00161A7E991B>I<00000F000001FF000001FF0000001F0000000F0000000F0000000F000000 +0F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F00003F0F0001 +C0CF0003802F000F001F001E001F001C000F003C000F007C000F0078000F0078000F00F8000F00 +F8000F00F8000F00F8000F00F8000F00F8000F00F8000F0078000F0078000F003C000F003C000F +001E001F000E002F0007004F8001C18FF8007E0FF81D2A7EA921>I<007E0003C3800700E00E00 +F01C00703C00783C003878003C78003CF8003CF8003CFFFFFCF80000F80000F80000F80000F800 +007800007C00003C00043C00041E00080E001007002001C0C0007F00161A7E991B>I<001F0000 +70C000E1E001C3E003C3E00381C007808007800007800007800007800007800007800007800007 +8000078000FFFE00FFFE0007800007800007800007800007800007800007800007800007800007 +800007800007800007800007800007800007800007800007800007800007800007800007C000FF +FE00FFFE00132A7FA912>I<0000078001FC1840070721C00E03C1C01E03C0803C01E0003C01E0 +007C01F0007C01F0007C01F0007C01F0007C01F0003C01E0003C01E0001E03C0000E0380001707 +000011FC0000300000003000000030000000380000001C0000001FFFC0000FFFF80007FFFC001C +003E0030000F007000070060000380E0000380E0000380E0000380E00003807000070070000700 +38000E000C0018000780F00000FF80001A287E9A1E>I<07800000FF800000FF8000000F800000 +078000000780000007800000078000000780000007800000078000000780000007800000078000 +0007800000078000000783F800078C1C0007900E0007A0070007A0078007C0078007C007800780 +078007800780078007800780078007800780078007800780078007800780078007800780078007 +800780078007800780078007800780078007800780078007800780FFFCFFFCFFFCFFFC1E2A7FA9 +21>I<07000F801F801F800F80070000000000000000000000000000000000000007807F807F80 +0F8007800780078007800780078007800780078007800780078007800780078007800780078007 +800780FFF8FFF80D297FA811>I<0780FF80FF800F800780078007800780078007800780078007 +800780078007800780078007800780078007800780078007800780078007800780078007800780 +07800780078007800780078007800780FFFCFFFC0E2A7FA911>108 D<0781F800FC00FF860E03 +0700FF98070C03800FA0079003C007A003D001E007C003E001E007C003E001E0078003C001E007 +8003C001E0078003C001E0078003C001E0078003C001E0078003C001E0078003C001E0078003C0 +01E0078003C001E0078003C001E0078003C001E0078003C001E0078003C001E0078003C001E007 +8003C001E0078003C001E0078003C001E0FFFC7FFE3FFFFFFC7FFE3FFF301A7F9933>I<0783F8 +00FF8C1C00FF900E000FA0070007A0078007C0078007C007800780078007800780078007800780 +078007800780078007800780078007800780078007800780078007800780078007800780078007 +800780078007800780078007800780FFFCFFFCFFFCFFFC1E1A7F9921>I<007F000001C1C00007 +0070000E0038001C001C003C001E003C001E0078000F0078000F00F8000F80F8000F80F8000F80 +F8000F80F8000F80F8000F80F8000F80F8000F8078000F0078000F003C001E003C001E001E003C +000E0038000700700001C1C000007F0000191A7E991E>I<0783F000FF8C1C00FFB00F0007A007 +8007C003C0078003E0078001E0078001F0078001F0078000F8078000F8078000F8078000F80780 +00F8078000F8078000F8078000F0078001F0078001F0078001E0078003C007C003C007C0078007 +A00E0007983C000787E00007800000078000000780000007800000078000000780000007800000 +078000000780000007800000FFFC0000FFFC00001D267F9921>I<003F008001E0C18003802180 +0F0013801E000B801E000F803C0007807C0007807C00078078000780F8000780F8000780F80007 +80F8000780F8000780F8000780F80007807C0007807C0007803C0007803E000F801E000F800F00 +17800780278001E0C780007F078000000780000007800000078000000780000007800000078000 +0007800000078000000780000007800000FFFC0000FFFC1E267E9920>I<0787C0FF98E0FF91F0 +0FA1F007C1F007C0E007C000078000078000078000078000078000078000078000078000078000 +07800007800007800007800007800007800007800007C000FFFE00FFFE00141A7F9917>I<07F8 +401C06C03001C06000C06000C0E00040E00040F00040F800007E00007FF0003FFE000FFF0003FF +80003FC00007C08001E08001E0C000E0C000E0C000E0E000C0F001C0F80180C4070083F800131A +7E9918>I<0080000080000080000080000180000180000180000380000380000780000F80001F +FF80FFFF8007800007800007800007800007800007800007800007800007800007800007800007 +800007800007804007804007804007804007804007804007804003C08001C08000E100003E0012 +257FA417>I<07800780FF80FF80FF80FF800F800F800780078007800780078007800780078007 +800780078007800780078007800780078007800780078007800780078007800780078007800780 +078007800780078007800F8007800F800380178001C027C000E047FC003F87FC1E1A7F9921>I< +FFF00FF8FFF00FF80F8003C0078003800780010003C0020003C0020003E0020001E0040001E004 +0000F0080000F0080000F818000078100000781000003C2000003C2000003E6000001E4000001E +4000000F8000000F8000000700000007000000070000000200001D1A7F9920>IIII<7FFFF87800F06001F04001E04003C0C007C0800780800F00801F0000 +1E00003C00007C0000780000F00001F00001E00403C00407C0040780040F000C1F00081E00083C +00187C00387800F8FFFFF8161A7E991B>I E /Fo 48 122 df<0001FF81FE00001FFFEFFF8000 +7F80FF87C000FC00FE0FE001F801FE0FE003F801FC0FE007F001FC0FE007F001FC07C007F001FC +000007F001FC000007F001FC000007F001FC000007F001FC000007F001FC000007F001FC0000FF +FFFFFFF800FFFFFFFFF800FFFFFFFFF80007F001FC000007F001FC000007F001FC000007F001FC +000007F001FC000007F001FC000007F001FC000007F001FC000007F001FC000007F001FC000007 +F001FC000007F001FC000007F001FC000007F001FC000007F001FC000007F001FC000007F001FC +000007F001FC000007F001FC000007F001FC000007F001FC00007FFF1FFFE0007FFF1FFFE0007F +FF1FFFE0002B2A7FA928>11 D<00030007000E001C0038007000F001E003C003C007C007800F80 +0F001F001F003F003E003E007E007E007E007C007C00FC00FC00FC00FC00FC00FC00FC00FC00FC +00FC00FC00FC007C007C007E007E007E003E003E003F001F001F000F000F80078007C003C003C0 +01E000F000700038001C000E00070003103C7AAC1B>40 D<8000C000E000700038001C001E000F +000780078007C003C003E001E001F001F001F800F800F800FC00FC00FC007C007C007E007E007E +007E007E007E007E007E007E007E007E007E007C007C00FC00FC00FC00F800F801F801F001F001 +E003E003C007C0078007800F001E001C0038007000E000C00080000F3C7BAC1B>I<1C007F007F +00FF80FFC0FFC07FC07FC01CC000C000C00180018001800300030006000C001800300020000A15 +7B8813>44 DI<1C003E007F00FF80 +FF80FF807F003E001C0009097B8813>I<000E00001E00007E0007FE00FFFE00FFFE00F8FE0000 +FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000 +FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000 +FE0000FE0000FE007FFFFE7FFFFE7FFFFE17277BA622>49 D<00FF800003FFF0000FFFFC001F03 +FE003800FF007C007F80FE003FC0FF003FC0FF003FE0FF001FE0FF001FE07E001FE03C003FE000 +003FE000003FC000003FC000007F8000007F000000FE000000FC000001F8000003F0000003E000 +00078000000F0000001E0000003C00E0007000E000E000E001C001C0038001C0070001C00FFFFF +C01FFFFFC03FFFFFC07FFFFFC0FFFFFF80FFFFFF80FFFFFF801B277DA622>I<007F800003FFF0 +0007FFFC000F81FE001F00FF003F80FF003F807F803F807F803F807F801F807F800F007F800000 +FF000000FF000000FE000001FC000001F8000007F00000FFC00000FFF0000001FC0000007E0000 +007F0000007F8000003FC000003FC000003FE000003FE03C003FE07E003FE0FF003FE0FF003FE0 +FF003FC0FF007FC07E007F807C007F003F01FE001FFFFC0007FFF00000FF80001B277DA622>I< +380000003E0000003FFFFFF03FFFFFF03FFFFFF07FFFFFE07FFFFFC07FFFFF807FFFFF0070000E +0070000E0070001C00E0003800E0007000E000E0000000E0000001C00000038000000780000007 +8000000F0000000F0000001F0000001F0000003F0000003E0000003E0000007E0000007E000000 +7E0000007E000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE0000 +007C0000003800001C297CA822>55 D<000003800000000007C00000000007C0000000000FE000 +0000000FE0000000000FE0000000001FF0000000001FF0000000003FF8000000003FF800000000 +3FF80000000073FC0000000073FC00000000F3FE00000000E1FE00000000E1FE00000001C0FF00 +000001C0FF00000003C0FF80000003807F80000007807FC0000007003FC0000007003FC000000E +003FE000000E001FE000001E001FF000001C000FF000001FFFFFF000003FFFFFF800003FFFFFF8 +0000780007FC0000700003FC0000700003FC0000E00001FE0000E00001FE0001E00001FF0001C0 +0000FF0001C00000FF00FFFE001FFFFEFFFE001FFFFEFFFE001FFFFE2F297EA834>65 +DI<00003FF001800003FFFE0380000FFFFF878000 +3FF007DF8000FF8001FF8001FE00007F8003FC00003F8007F000001F800FF000000F801FE00000 +07801FE0000007803FC0000007803FC0000003807FC0000003807F80000003807F8000000000FF +8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF800000 +0000FF8000000000FF80000000007F80000000007F80000000007FC0000003803FC0000003803F +C0000003801FE0000003801FE0000007000FF00000070007F000000E0003FC00001E0001FE0000 +3C0000FF8000F800003FF007E000000FFFFFC0000003FFFF000000003FF8000029297CA832>I< +FFFFFFF80000FFFFFFFF8000FFFFFFFFE00003FC001FF80003FC0007FC0003FC0001FE0003FC00 +00FF0003FC00007F8003FC00003FC003FC00001FC003FC00001FE003FC00001FE003FC00000FF0 +03FC00000FF003FC00000FF003FC00000FF003FC00000FF803FC00000FF803FC00000FF803FC00 +000FF803FC00000FF803FC00000FF803FC00000FF803FC00000FF803FC00000FF803FC00000FF8 +03FC00000FF003FC00000FF003FC00000FF003FC00001FE003FC00001FE003FC00001FC003FC00 +003FC003FC00007F8003FC00007F0003FC0001FE0003FC0003FC0003FC001FF800FFFFFFFFE000 +FFFFFFFF8000FFFFFFFC00002D297DA835>III<00007FE003000003FFFC0700001FFFFF0F00003FF00FFF0000 +FF8001FF0001FE0000FF0003F800003F0007F000003F000FF000001F001FE000000F001FE00000 +0F003FC000000F003FC0000007007FC0000007007F80000007007F8000000000FF8000000000FF +8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF800000 +0000FF8001FFFFF87F8001FFFFF87F8001FFFFF87FC00000FF003FC00000FF003FC00000FF001F +E00000FF001FE00000FF000FF00000FF0007F00000FF0003F80000FF0001FE0000FF0000FF8001 +FF00003FF007BF00001FFFFF1F000003FFFE0F0000007FF003002D297CA836>I73 D76 DII<0000FFE000000007FFFC +0000003FC07F8000007F001FC00001FC0007F00003F80003F80007F00001FC000FF00001FE001F +E00000FF001FE00000FF003FC000007F803FC000007F807FC000007FC07F8000003FC07F800000 +3FC07F8000003FC0FF8000003FE0FF8000003FE0FF8000003FE0FF8000003FE0FF8000003FE0FF +8000003FE0FF8000003FE0FF8000003FE0FF8000003FE0FF8000003FE07F8000003FC07FC00000 +7FC07FC000007FC03FC000007F803FC000007F801FE00000FF001FE00000FF000FF00001FE0007 +F00001FC0003F80003F80001FC0007F00000FF001FE000003FC07F8000000FFFFE00000000FFE0 +00002B297CA834>II82 D<007F806003FFF0E007FFF9E00F807FE01F001FE03E0007E07C0003E07C0001E0 +FC0001E0FC0001E0FC0000E0FE0000E0FE0000E0FF000000FFC000007FFE00007FFFE0003FFFFC +001FFFFE000FFFFF8007FFFFC003FFFFE000FFFFE00007FFF000007FF000000FF8000007F80000 +03F8600001F8E00001F8E00001F8E00001F8F00001F0F00001F0F80003F0FC0003E0FF0007C0FF +E01F80F3FFFF00E0FFFE00C01FF0001D297CA826>I<7FFFFFFFFFC07FFFFFFFFFC07FFFFFFFFF +C07F803FC03FC07E003FC007C078003FC003C078003FC003C070003FC001C0F0003FC001E0F000 +3FC001E0E0003FC000E0E0003FC000E0E0003FC000E0E0003FC000E0E0003FC000E000003FC000 +0000003FC0000000003FC0000000003FC0000000003FC0000000003FC0000000003FC000000000 +3FC0000000003FC0000000003FC0000000003FC0000000003FC0000000003FC0000000003FC000 +0000003FC0000000003FC0000000003FC0000000003FC0000000003FC0000000003FC000000000 +3FC0000000003FC00000007FFFFFE000007FFFFFE000007FFFFFE0002B287EA730>I86 DI<01FF800007FFF0000F81F8001FC07E001FC07E001FC03F000F803F8007003F8000003F +8000003F8000003F80000FFF8000FFFF8007FC3F800FE03F803F803F803F003F807F003F80FE00 +3F80FE003F80FE003F80FE003F807E007F807F00DF803F839FFC0FFF0FFC01FC03FC1E1B7E9A21 +>97 DI<001FF80000FFFE0003F01F0007E0 +3F800FC03F801F803F803F801F007F800E007F0000007F000000FF000000FF000000FF000000FF +000000FF000000FF000000FF0000007F0000007F0000007F8000003F8001C01F8001C00FC00380 +07E0070003F01E0000FFFC00001FE0001A1B7E9A1F>I<00003FF80000003FF80000003FF80000 +0003F800000003F800000003F800000003F800000003F800000003F800000003F800000003F800 +000003F800000003F800000003F800000003F800001FE3F80000FFFBF80003F03FF80007E00FF8 +000FC007F8001F8003F8003F8003F8007F0003F8007F0003F8007F0003F800FF0003F800FF0003 +F800FF0003F800FF0003F800FF0003F800FF0003F800FF0003F8007F0003F8007F0003F8007F00 +03F8003F8003F8001F8003F8000F8007F80007C00FF80003F03BFF8000FFF3FF80003FC3FF8021 +2A7EA926>I<003FE00001FFF80003F07E0007C01F000F801F801F800F803F800FC07F000FC07F +0007C07F0007E0FF0007E0FF0007E0FFFFFFE0FFFFFFE0FF000000FF000000FF0000007F000000 +7F0000007F0000003F8000E01F8000E00FC001C007E0038003F81F0000FFFE00001FF0001B1B7E +9A20>I<0007F0003FFC00FE3E01F87F03F87F03F07F07F07F07F03E07F00007F00007F00007F0 +0007F00007F00007F000FFFFC0FFFFC0FFFFC007F00007F00007F00007F00007F00007F00007F0 +0007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F0 +0007F0007FFF807FFF807FFF80182A7EA915>I<00FF81F003FFE7F80FC1FE7C1F80FC7C1F007C +383F007E107F007F007F007F007F007F007F007F007F007F007F007F003F007E001F007C001F80 +FC000FC1F8001FFFE00018FF800038000000380000003C0000003E0000003FFFF8001FFFFF001F +FFFF800FFFFFC007FFFFE01FFFFFF03E0007F07C0001F8F80000F8F80000F8F80000F8F80000F8 +7C0001F03C0001E01F0007C00FC01F8003FFFE00007FF0001E287E9A22>II<07000FC01FE03FE03FE03FE01FE00FC0070000000000000000 +00000000000000FFE0FFE0FFE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0 +0FE00FE00FE00FE00FE00FE00FE00FE0FFFEFFFEFFFE0F2B7DAA14>I108 DII<003FE00001FFFC00 +03F07E000FC01F801F800FC03F800FE03F0007E07F0007F07F0007F07F0007F0FF0007F8FF0007 +F8FF0007F8FF0007F8FF0007F8FF0007F8FF0007F8FF0007F87F0007F07F0007F03F800FE03F80 +0FE01F800FC00FC01F8007F07F0001FFFC00003FE0001D1B7E9A22>II114 D<03FE300FFFF01E03F03800F0700070F00070F00070F80070FC0000FFE000 +7FFE007FFF803FFFE01FFFF007FFF800FFF80003FC0000FC60007CE0003CF0003CF00038F80038 +FC0070FF01E0F7FFC0C1FF00161B7E9A1B>I<00700000700000700000700000F00000F00000F0 +0001F00003F00003F00007F0001FFFF0FFFFF0FFFFF007F00007F00007F00007F00007F00007F0 +0007F00007F00007F00007F00007F00007F00007F00007F03807F03807F03807F03807F03807F0 +3803F03803F87001F86000FFC0001F8015267FA51B>III121 D E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 300 +TeXDict begin +%%EndSetup +%%Page: 1 1 +bop 410 195 a Fo(MOSIS)23 b(Scalable)f(CMOS)g(Design)g(Rules)806 +351 y Fn(\()p Fo(revision)g(7)p Fn(\))866 498 y Fm(Jen-I)h(Pi)772 +633 y Fl(the)16 b Fk(MOSIS)h Fl(Service)654 693 y(Information)f(Sciences)f +(Institute)621 753 y(Univ)o(ersit)o(y)e(of)k(Southern)f(California)753 +813 y(4676)i(Admiralt)o(y)c(W)l(a)o(y)692 873 y(Marina)i(del)f(Rey)l(,)g(CA)i +(90292)868 934 y(pi@isi.edu)814 994 y(August)g(1,)f(1995)0 +1160 y Fj(1)83 b(In)n(tro)r(duction)0 1284 y Fo(1.1)70 b(SCMOS)22 +b(Design)g(Rules)0 1377 y Fl(This)17 b(do)q(cumen)o(t)e(de\014nes)h(the)g +(o\016cial)g(la)o(y)o(out)g(design)h(rules)f(for)h(MOSIS)e(scalable)i(CMOS)f +(\(SCMOS\))0 1437 y(design)g(tec)o(hnology)l(.)21 b(It)16 b(sup)q(ercedes)g +(all)g(previous)g(revisions.)73 1497 y(In)k(SCMOS)g(tec)o(hnology)l(,)g +(circuit)f(geometries)f(are)i(dra)o(wn)h(according)f(to)h(Mead)f(and)g(Con)o +(w)o(a)o(y's)0 1557 y Fi(\025)p Fl(-based)k(metho)q(dology)e([3].)39 +b(The)22 b(unit)g(of)h(measuremen)o(t,)d Fi(\025)p Fl(,)k(can)f(easily)f(b)q +(e)g(scaled)g(to)h(di\013eren)o(t)0 1617 y(fabrication)16 b(pro)q(cesses)h +(as)g(semiconductor)e(tec)o(hnology)h(adv)m(ances.)73 1678 +y(A)21 b(user)h(design)f(submitted)f(to)i(MOSIS)e(in)h(SCMOS)h(tec)o(hnology) +f(should)h(b)q(e)f(in)g(either)g(Calma)0 1738 y(GDSI)q(I)i(format)g([1])g(or) +g(Caltec)o(h)g(In)o(termediate)d(F)l(orm)i(\(CIF)h(v)o(ersion)f(2.0\))i([3].) +42 b(Eac)o(h)23 b(design)g(has)0 1798 y(a)d(tec)o(hnology)f +Fk(designation)i Fl(that)f(go)q(es)h(with)e(it)g(for)h(the)f(purp)q(ose)i(of) +e(MOSIS's)g(data)i(prep.)31 b(A)o(t)18 b(the)0 1858 y(momen)o(t,)10 +b(three)i(designations)i(are)e(used)h(to)g(sp)q(ecify)f(CMOS)h(pro)q(cesses.) +21 b(Eac)o(h)12 b(designation)i(ma)o(y)d(ha)o(v)o(e)0 1918 +y(one)19 b(or)g(more)e Fk(options)i Fl(asso)q(ciated)g(for)g(the)g(purp)q +(ose)g(of)g(either)f(\(1\))h(sp)q(ecial)f(features)g(for)h(the)g(target)0 +1979 y(pro)q(cess)f(or)f(\(2\))h(the)f(presence)f(of)i(no)o(v)o(el)e(device)f +(in)i(the)g(design.)24 b(A)o(t)16 b(the)h(time)e(of)j(writing,)f(MOSIS)f(is)0 +2039 y(o\013ering)g(six)f(CMOS)h(pro)q(cesses)g(from)e(three)h(di\013eren)o +(t)g(foundries)h(with)f(dra)o(wn)h(feature)f(sizes)g(ranging)0 +2099 y(from)g(2.0)i Fi(\026)p Fl(m)e(do)o(wn)i(to)f(0.6)h Fi(\026)p +Fl(m.)73 2159 y(A)g(list)g(of)h(the)f(things)h(that)g(ha)o(v)o(e)f(either)f +(b)q(een)i(revised)e(or)i(added)g(since)f(our)h(last)f(release)g(can)h(b)q(e) +0 2219 y(found)f(in)f(App)q(endix)f(A.)h(Please)g(refer)f(to)i(the)f(sp)q +(eci\014c)f(sections)h(for)h(detailed)e(descriptions.)0 2386 +y Fj(2)83 b(Standard)27 b(SCMOS)0 2495 y Fl(The)19 b(standard)i(CMOS)f(tec)o +(hnology)f(accessed)g(b)o(y)g(MOSIS)g(is)g(a)h(single)f(p)q(olysilicon,)g +(double)g(metal,)0 2555 y(bulk)d(CMOS)g(pro)q(cess)h(with)f(enhancemen)o +(t-mo)q(de)d Fk(n)p Fl(-MOSFET)k(and)g Fk(p)p Fl(-MOSFET)f(devices)f([4].)963 +2828 y(1)p eop +%%Page: 2 2 +bop 0 195 a Fo(2.1)70 b(W)-6 b(ell)21 b(Fla)n(v)n(or)0 287 +y Fl(Three)f(t)o(yp)q(es)f(of)i Fk(designation)g Fl(are)f(used)g(to)g +(indicate)f(the)h(\015a)o(v)o(or)g(of)g(the)g(w)o(ell)e(\(substrate\))j(used) +f(for)0 348 y(fabrication)c(as)h(sho)o(wn)g(in)f(T)l(able)g(1.)p +499 461 952 2 v 498 522 2 61 v 507 522 V 533 504 a(Designation)p +808 522 V 50 w(Description)p 1441 522 V 1450 522 V 499 523 +952 2 v 498 583 2 61 v 507 583 V 533 565 a(SCN)p 808 583 V +202 w(Scalable)g(CMOS)g(N-w)o(ell)p 1441 583 V 1450 583 V 498 +644 V 507 644 V 533 626 a(SCP)p 808 644 V 206 w(Scalable)g(CMOS)g(P-w)o(ell)p +1441 644 V 1450 644 V 498 704 V 507 704 V 533 686 a(SCE)p 808 +704 V 206 w(Scalable)g(CMOS)g(Either-w)o(ell)p 1441 704 V 1450 +704 V 499 705 952 2 v 537 840 a(T)l(able)g(1:)22 b(SCMOS)16 +b(w)o(ell)f(\015a)o(v)o(or)h(designations)73 968 y(The)k(SCN)g(and)h(SCP)g +(designations)f(with)g(a)h(submitted)d(pro)s(ject)i(are)g(designed)g(for)g +(fabrication)0 1028 y(of)d(the)g(sp)q(eci\014ed)g(w)o(ell)e(only)l(.)24 +b(F)l(or)17 b(con)o(v)o(enience,)d(in)j(b)q(oth)h(cases,)f(a)g(pro)s(ject)g +(ma)o(y)e(include)h(the)h('other')0 1088 y(w)o(ell,)k(but)g(it)g(will)g(alw)o +(a)o(ys)g(b)q(e)g(ignored.)37 b(SCE)22 b(pro)s(jects)f(are)g(used)h(for)f +(fabrication)h(in)f(an)o(y)g(CMOS)0 1148 y(pro)q(cess,)d(N-w)o(ell)e(or)i +(P-w)o(ell)f(\()p Fk(either)p Fl(\).)25 b(A)17 b(pro)s(ject)g(with)g(SCE)h +(designation)g(m)o(ust)e(include)h Fk(b)n(oth)g Fl(w)o(ells)0 +1208 y(\(and)22 b(corresp)q(ondingly)l(,)g(w)o(ell/substrate)e(con)o(tacts)i +(for)f(prop)q(er)h(bias\).)36 b(F)l(or)21 b(an)o(y)g(giv)o(en)f(fabrication)0 +1269 y(pro)q(cess,)f(the)f('other')g(w)o(ell)f(will)g(b)q(e)i(ignored)f +(during)h(the)f(mask)f(generation.)28 b(If)18 b(t)o(win-tub)g(pro)q(cesses)0 +1329 y(are)e(o\013ered)h(in)f(the)g(future,)f(b)q(oth)i(w)o(ells)f(will)f(b)q +(e)h(used.)0 1473 y Fo(2.2)70 b(SCMOS)22 b(Options)0 1566 y +Fl(SCMOS)15 b(options)h(are)g(used)f(to)h(designate)f(pro)s(jects)g(whic)o(h) +g(use)g(additional)g(la)o(y)o(ers)g(b)q(ey)o(ond)g(the)g(stan-)0 +1626 y(dard)h(CMOS)f(tec)o(hnology)l(.)20 b(Eac)o(h)c(option)f(is)g(named)f +(b)o(y)h(a)h(designator)g(that)f(is)g(tac)o(k)o(ed)f(on)o(to)i(the)f(basic)0 +1686 y(designator)k(for)g(its)g(w)o(ell)e(\015a)o(v)o(or.)28 +b(Reader)19 b(should)g(note)g(that)g(not)g(all)f(p)q(ossible)h(com)o +(binations)e(\(with)0 1746 y(w)o(ell)11 b(\015a)o(v)o(or\))i(are)g(actually)f +(a)o(v)m(ailable.)19 b(The)13 b(curren)o(tly)e(a)o(v)m(ailable)h(SCMOS)h +(options)g(are)g(listed)f(in)g(T)l(able)0 1806 y(2.)73 1867 +y(In)24 b(addition)g(to)g(the)g(options)g(in)g(T)l(able)g(2,)h(t)o(w)o(o)f +(undeclared)f(options)i(also)f(exist.)44 b(One)23 b(with)0 +1927 y(resp)q(ect)18 b(to)h(the)g(existence)e(of)i Fk(high)h(voltage)g +Fl(MOSFET)f(devices;)f(the)g(other,)h(a)g Fk(tight)h(metal)g +Fl(rule)e(for)0 1987 y(high-densit)o(y)c(metal)f(in)o(terconnections.)20 +b(F)l(or)15 b(options)g(a)o(v)m(ailable)f(to)i(sp)q(eci\014c)e(pro)q(cess,)h +(please)g(refer)f(to)0 2047 y(T)l(able)i(3)h(for)f(the)g(curren)o(t)g(MOSIS)f +(o\013erings.)0 2192 y Fo(2.3)70 b(SCMOS)22 b(O\013erings)0 +2284 y Fl(MOSIS)14 b(is)h(curren)o(tly)f(o\013ering)h(the)g(fabrication)g +(pro)q(cesses)h(as)f(sho)o(wn)h(in)f(T)l(able)g(3.)21 b(F)l(or)15 +b(eac)o(h)g(pro)q(cess,)0 2344 y(the)e(list)g(of)h(appropriate)h(SCMOS)e(tec) +o(hnology)h(designations)g(is)f(listed.)20 b(Note)13 b(that)h(whenev)o(er)f +(SCNxx)0 2404 y(app)q(ears)i(in)e(the)h(table,)f(SCExx)h(is)g(also)g +(appropriate.)21 b(Lik)o(ewise,)13 b(whenev)o(er)f(SCPxx)i(app)q(ears,)h +(SCExx)0 2465 y(is)h(also)h(appropriate.)p 0 2608 780 2 v 56 +2639 a Fh(2)75 2654 y Fg(CCD)c(la)o(y)o(er)h(not)f(included.)56 +2689 y Fh(2)75 2704 y Fg(CCD)g(la)o(y)o(er)h(not)f(included.)963 +2828 y Fl(2)p eop +%%Page: 3 3 +bop 49 387 1853 2 v 48 447 2 61 v 57 447 V 82 429 a Fl(Designation)p +358 447 V 51 w(Long)17 b(form)p 769 447 V 188 w(Description)p +1892 447 V 1901 447 V 49 449 1853 2 v 48 509 2 61 v 57 509 +V 191 491 a(E)p 358 509 V 160 w(Electro)q(de)p 769 509 V 207 +w(Adds)g(a)f(second)h(p)q(olysilicon)e(la)o(y)o(er)g(\()p Ff(electro)r(de)p +Fl(\))p 1892 509 V 1901 509 V 48 569 V 57 569 V 358 569 V 769 +569 V 794 551 a(that)i(can)g(serv)o(e)e(as)i(either)e(one)h(of)h(electro)q +(de)e(of)i(a)f(p)q(oly)p 1892 569 V 1901 569 V 48 630 V 57 +630 V 358 630 V 769 630 V 794 612 a(capacitor)h(or)f(as)h(a)g(gate)g(for)f +(transistors.)22 b(A)16 b(con)o(tact)p 1892 630 V 1901 630 +V 48 690 V 57 690 V 358 690 V 769 690 V 794 672 a(la)o(y)o(er)f(\()p +Ff(electro)r(de)p 1159 672 17 2 v 18 w(con)n(tact)p Fl(\))i(to)f(metal)f +(also)h(exists.)p 1892 690 2 61 v 1901 690 V 49 691 1853 2 +v 48 752 2 61 v 57 752 V 190 734 a(A)p 358 752 V 157 w(Analog)p +769 752 V 260 w(Adds)h(electro)q(de)e(la)o(y)o(er)g(\(as)i(in)f(E)g(option\)) +h(plus)f(a)p 1892 752 V 1901 752 V 48 812 V 57 812 V 358 812 +V 769 812 V 794 794 a Ff(pbase)h Fl(la)o(y)o(er)e(for)h(the)g(construction)h +(of)f(v)o(ertical)f(NPN)p 1892 812 V 1901 812 V 48 872 V 57 +872 V 358 872 V 769 872 V 794 854 a(transistor.)22 b(A)16 b +Ff(buried)p 1247 854 17 2 v 20 w(ccd)g Fl(la)o(y)o(er)f(is)h(also)h(presen)o +(t.)p 1892 872 2 61 v 1901 872 V 48 932 V 57 932 V 358 932 +V 769 932 V 794 914 a(for)g(buried-c)o(hannel)e(CCD)i(applications)p +1892 932 V 1901 932 V 49 934 1853 2 v 48 994 2 61 v 57 994 +V 173 976 a(3M)p 358 994 V 142 w(T)l(riple)e(Metal)p 769 994 +V 144 w(Adds)i(second)f(via)g(\()p Ff(via2)p Fl(\))g(and)h(third)e(metal)g +(\()p Ff(metal3)p Fl(\))p 1892 994 V 1901 994 V 48 1054 V 57 +1054 V 358 1054 V 769 1054 V 794 1036 a(la)o(y)o(ers.)p 1892 +1054 V 1901 1054 V 49 1056 1853 2 v 48 1116 2 61 v 57 1116 +V 175 1098 a(LC)p 358 1116 V 144 w(Linear)h(Capacitor)p 769 +1116 V 50 w(Adds)h(a)f Ff(cap)p 1047 1098 17 2 v 21 w(w)n(ell)g +Fl(la)o(y)o(er)f(for)h(the)g(implem)o(en)o(tation)d(of)p 1892 +1116 2 61 v 1901 1116 V 48 1176 V 57 1176 V 358 1176 V 769 +1176 V 794 1158 a(linear)j(capacitors.)p 1892 1176 V 1901 1176 +V 49 1178 1853 2 v 48 1238 2 61 v 57 1238 V 127 1220 15 2 v +142 1220 a(MEMS)p 358 1238 2 61 v 92 w(Micromec)o(hanic)o(al)p +769 1238 V 50 w(Adds)h(t)o(w)o(o)f(new)g(la)o(y)o(ers,)f Ff(mems)p +1411 1220 17 2 v 17 w(op)r(en)h Fl(and)p 1892 1238 2 61 v 1901 +1238 V 48 1298 V 57 1298 V 358 1298 V 384 1280 a(Systems)p +769 1298 V 236 w Ff(mems)p 941 1280 17 2 v 18 w(etc)n(h)p 1061 +1280 V 20 w(stop)g Fl(for)h(the)f(purp)q(ose)h(of)f(micro-)p +1892 1298 2 61 v 1901 1298 V 48 1359 V 57 1359 V 358 1359 V +769 1359 V 794 1340 a(mec)o(hanical)e(device)h(construction.)p +1892 1359 V 1901 1359 V 49 1360 1853 2 v 585 1494 a(T)l(able)h(2:)21 +b(SCMOS)c(tec)o(hnology)f(options)p 121 1957 1709 2 v 120 2017 +2 61 v 129 2017 V 154 1999 a(F)l(oundry)p 356 2017 V 50 w(Pro)q(cess)p +788 2017 V 273 w(Lam)o(b)q(da)p 1012 2017 V 50 w(Options)p +1820 2017 V 1829 2017 V 121 2019 1709 2 v 120 2079 2 61 v 129 +2079 V 154 2061 a(Orbit)p 356 2079 V 111 w(2.0)g Fi(\026)p +Fl(m)g(N-w)o(ell)p 788 2079 V 142 w(1.0)h Fi(\026)p Fl(m)p +1012 2079 V 62 w(SCNA,)e(SCNE,)h(SCN,)f(SCNA)p 1632 2061 15 +2 v 17 w(MEMS)p 1820 2079 2 61 v 1829 2079 V 120 2139 V 129 +2139 V 154 2121 a(Orbit)p 356 2139 V 111 w(2.0)h Fi(\026)p +Fl(m)g(P-w)o(ell)p 788 2139 V 146 w(1.0)h Fi(\026)p Fl(m)p +1012 2139 V 62 w(SCPE,)f(SCP)l(,)g(SCPE)p 1448 2121 15 2 v +19 w(MEMS)p 1820 2139 2 61 v 1829 2139 V 120 2200 V 129 2200 +V 154 2181 a(AMI)p 356 2200 V 128 w(1.5)g Fi(\026)p Fl(m)g(N-w)o(ell)p +788 2200 V 142 w(0.8)h Fi(\026)p Fl(m)p 1012 2200 V 62 w(SCNA)1174 +2163 y Fe(1)1193 2181 y Fl(,)f(SCNE,)f(SCN,)h(High)g(V)l(oltage)p +1820 2200 V 1829 2200 V 120 2260 V 129 2260 V 154 2242 a(Orbit)p +356 2260 V 111 w(1.2)g Fi(\026)p Fl(m)g(N-w)o(ell)p 788 2260 +V 142 w(0.6)h Fi(\026)p Fl(m)p 1012 2260 V 62 w(SCNA)1174 2224 +y Fe(2)p 1820 2260 V 1828 2260 V 120 2320 V 128 2320 V 154 +2302 a Fl(HP)p 356 2320 V 158 w(AMOSI/CMOS34)p 788 2320 V 62 +w(0.6)g Fi(\026)p Fl(m)p 1012 2320 V 62 w(SCNLC,)f(SCN,)g(Tigh)o(t)g(Metal)p +1820 2320 V 1829 2320 V 120 2380 V 129 2380 V 154 2362 a(HP)p +356 2380 V 158 w(CMOS26B/G)p 788 2380 V 154 w(0.5)h Fi(\026)p +Fl(m)p 1012 2380 V 62 w(SCN3M,)e(SCN,)h(Tigh)o(t)g(Metal)p +1820 2380 V 1829 2380 V 121 2382 1709 2 v 488 2516 a(T)l(able)g(3:)22 +b(MOSIS)15 b(SCMOS)i(tec)o(hnology)e(o\013erings)963 2828 y(3)p +eop +%%Page: 4 4 +bop 0 203 a Fj(3)83 b(CIF)27 b(and)g(GDS)h(La)n(y)n(er)e(Sp)r(eci\014cation)0 +313 y Fl(Design)17 b(geometries)e(\(or)h(mask)g(features\))g(can)h(b)q(e)g +(represen)o(ted)e(either)h(in)g(GDS-I)q(I)h(or)g(Caltec)o(h)f(In)o(ter-)0 +373 y(mediate)d(F)l(orm)h(\(CIF)h(V)l(ersion)g(2.0\).)21 b(While)14 +b(the)h(former)f(is)h(co)q(ded)h(in)e(binary)i(format,)e(the)h(latter)g(is)g +(a)0 433 y(plain)g(text)g(\014le)f(and)i(can)f(b)q(e)h(easily)e(in)o +(terpreted.)19 b(F)l(or)d(detailed)e(syn)o(tax)h(and)h(seman)o(tic)d(sp)q +(eci\014cations)0 493 y(of)k(Calma/GDS-I)q(I)f(or)g(CIF,)g(please)g(refer)f +(to)i([1])f(and)g([3])g(resp)q(ectiv)o(ely)l(.)73 554 y(In)f(GDS)g(I)q(I)f +(format,)g(a)h(mask)f(la)o(y)o(er)f(is)i(sp)q(eci\014ed)f(b)o(y)g(a)h(la)o(y) +o(er)f(n)o(um)o(b)q(er)f(b)q(et)o(w)o(een)h(0)h(and)g(63.)22 +b(MOSIS)0 614 y(no)o(w)h(reserv)o(es)f(la)o(y)o(ers)g(n)o(um)o(b)q(erd)g +(from)f(21)j(to)g(62)f(for)h(mask)e(sp)q(eci\014cation)h(and)g(future)g +(extension.)0 674 y(La)o(y)o(ers)c(de\014ned)f(out)i(of)f(this)g(range)g(can) +g(b)q(e)g(used)g(b)o(y)g(customers)f(for)h(their)f(o)o(wn)h(purp)q(ose.)31 +b(MOSIS)0 734 y(will)15 b(ignore)h(all)f(geometry)g(information)f(on)j(these) +e(la)o(y)o(ers)g(\(0)h(to)h(20)f(and)h(63\))f(and)h(map)e(it)g(to)i(the)e +(CIF)0 794 y(commen)o(t)c(la)o(y)o(er)h(\(CX\))i(if)g(necessary)l(.)20 +b(In)14 b(this)g(revision,)f(6)h(new)g(la)o(y)o(ers)f(are)h(added)h(starting) +f(from)f(la)o(y)o(er)0 855 y(n)o(um)o(b)q(er)h(21.)73 956 y +Fd(\017)24 b Fl(CVP)f(\(la)o(y)o(er)g(21\))h(is)f(used)h(to)g(indicate)e +(high-v)o(oltage)i Fk(p)p Fl(-t)o(yp)q(e)f(area.)44 b(More)23 +b(comprehensiv)o(e)122 1017 y(information)15 b(can)i(b)q(e)f(found)h(in)f +([2].)73 1118 y Fd(\017)24 b Fl(CVN)16 b(\(la)o(y)o(er)e(22\))j(is)f(used)h +(to)f(indicate)g(high-v)o(oltage)g Fk(p)p Fl(-t)o(yp)q(e)g(area.)73 +1220 y Fd(\017)24 b Fl(COP)17 b(\(la)o(y)o(er)d(23\))j(is)f(used)h(to)f +(indicate)g(substrate)h(pit)e(op)q(ening)i(area)g(for)g(MEMS)e(devices.)73 +1322 y Fd(\017)24 b Fl(CPS)17 b(\(la)o(y)o(er)e(24\))i(is)f(used)g(to)h +(indicate)e(substrate)i Fi(p)1095 1304 y Fe(+)1141 1322 y Fl(etc)o(hing-stop) +f(area)h(for)f(MEMS)g(devices.)73 1423 y Fd(\017)24 b Fl(CCC)17 +b(\(la)o(y)o(er)e(25\))i(is)f(used)g(for)h(generic)e(con)o(tact.)73 +1525 y Fd(\017)24 b Fl(XP)16 b(\(la)o(y)o(er)f(26\))i(is)f(used)g(to)h +(indicated)e(pad)i(lo)q(cation.)73 1627 y(Users)i(should)g(b)q(e)g(a)o(w)o +(are)g(that)g(there)g(exist)f(only)g Fk(one)i Fl(t)o(yp)q(e)e(of)h(ph)o +(ysical)f(con)o(tact)h(\(i.e.)28 b(b)q(et)o(w)o(een)0 1687 +y(\014rst)19 b(metal)f(and)h(p)q(oly)g(or)h(activ)o(e\),)e(though)i(sev)o +(eral)e(ha)o(v)o(e)g(b)q(een)h(de\014ned)g(for)g(historical)g(reason)g(and)0 +1747 y(are)e(retained)g(for)h(bac)o(kw)o(ard)f(compatibilit)o(y)l(.)22 +b(A)17 b(complete)e(list)i(of)g(SCMOS)h(la)o(y)o(ers)e(can)i(b)q(e)f(found)h +(in)0 1807 y(T)l(able)e(4)h(on)g(next)e(page.)0 1974 y Fj(4)83 +b(Sub-micron)25 b(Rules)0 2083 y Fl(The)18 b(SCMOS)g(design)h(rules)e(ha)o(v) +o(e)h(b)q(een)g(historically)e(designed)i(for)h(1.0)f(-)h(3.0)f(micron)f +(CMOS)h(tec)o(h-)0 2143 y(nology)l(.)j(T)l(o)15 b(tak)o(e)e(full)h(adv)m(an)o +(tage)h(of)g(adv)m(anced)f(submicron)f(pro)q(cess)i(tec)o(hnology)l(,)f(a)g +(set)h(of)f(rules)g(ha)o(v)o(e)0 2204 y(b)q(een)i(selected)f(to)i(b)q(e)f(mo) +q(di\014ed)f(to)i(\014t)f(our)h(foundry's)f(rules.)73 2264 +y(T)l(able)j(5)h(lists)f(those)h(rules)f(in)g(MOSIS's)g(HP)g(CMOS26G)h(pro)q +(cess)g(that)g(are)f(di\013eren)o(t)g(b)q(et)o(w)o(een)0 2324 +y(SCN3M)e(and)h(SCN3M)p 452 2324 15 2 v 17 w(26G)g(tec)o(hnology)f(sp)q +(eci\014cation)g(with)g Fi(\025)g Fl(equals)g(to)h(0.5)f(and)h(0.4)f +Fi(\026)p Fl(m)f(resp)q(ec-)0 2384 y(tiv)o(ely)l(.)963 2828 +y(4)p eop +%%Page: 5 5 +bop 86 660 1778 2 v 85 721 2 61 v 94 721 V 119 703 a Fl(SCMOS)17 +b(la)o(y)o(er)p 602 721 V 217 w(CIF)f(name)p 1157 721 V 339 +w(GDS)h(I)q(I)e(n)o(um)o(b)q(er)p 1540 721 V 48 w(GDS)i(I)q(I)f(t)o(yp)q(e)p +1855 721 V 1864 721 V 86 722 1778 2 v 85 783 2 61 v 94 783 +V 119 764 a(P)p 155 764 15 2 v 18 w(HIGH)p 303 764 V 17 w(V)o(OL)l(T)l(A)o +(GE)p 602 783 2 61 v 73 w(CVP)p 1157 783 V 592 w(21)p 1540 +783 V 317 w(-)p 1855 783 V 1864 783 V 85 843 V 94 843 V 119 +825 a(N)p 159 825 15 2 v 17 w(HIGH)p 306 825 V 17 w(V)o(OL)l(T)l(A)o(GE)p +602 843 2 61 v 70 w(CVN)p 1157 843 V 588 w(22)p 1540 843 V +317 w(-)p 1855 843 V 1864 843 V 85 903 V 94 903 V 119 885 a(MEMS)p +272 885 15 2 v 18 w(OPEN)p 602 903 2 61 v 200 w(COP)p 1157 +903 V 591 w(23)p 1540 903 V 317 w(-)p 1855 903 V 1864 903 V +85 963 V 94 963 V 119 945 a(MEMS)p 272 945 15 2 v 18 w(ETCH)p +430 945 V 17 w(STOP)p 602 963 2 61 v 51 w(CPS)p 1157 963 V +602 w(24)p 1540 963 V 317 w(-)p 1855 963 V 1864 963 V 85 1023 +V 94 1023 V 119 1005 a(P)l(ADS)p 602 1023 V 379 w(XP)p 1157 +1023 V 627 w(26)p 1540 1023 V 317 w(-)p 1855 1023 V 1864 1023 +V 85 1083 V 94 1083 V 119 1065 a(P)p 155 1065 15 2 v 18 w(WELL)p +602 1083 2 61 v 315 w(CWP)p 1157 1083 V 579 w(41)p 1540 1083 +V 317 w(-)p 1855 1083 V 1864 1083 V 85 1144 V 94 1144 V 119 +1126 a(N)p 159 1126 15 2 v 17 w(WELL)p 602 1144 2 61 v 312 +w(CWN)p 1157 1144 V 575 w(42)p 1540 1144 V 317 w(-)p 1855 1144 +V 1864 1144 V 85 1204 V 94 1204 V 119 1186 a(A)o(CTIVE)p 602 +1204 V 315 w(CAA)p 1157 1204 V 588 w(43)p 1540 1204 V 317 w(-)p +1855 1204 V 1864 1204 V 85 1264 V 94 1264 V 119 1246 a(P)p +155 1246 15 2 v 18 w(PLUS)p 300 1246 V 18 w(SELECT)p 602 1264 +2 61 v 120 w(CSP)p 1157 1264 V 602 w(44)p 1540 1264 V 317 w(-)p +1855 1264 V 1864 1264 V 85 1324 V 94 1324 V 119 1306 a(N)p +159 1306 15 2 v 17 w(PLUS)p 303 1306 V 18 w(SELECT)p 602 1324 +2 61 v 117 w(CSN)p 1157 1324 V 598 w(45)p 1540 1324 V 317 w(-)p +1855 1324 V 1864 1324 V 85 1384 V 94 1384 V 119 1366 a(POL)l(Y)p +602 1384 V 375 w(CPG)p 1157 1384 V 591 w(46)p 1540 1384 V 317 +w(-)p 1855 1384 V 1864 1384 V 85 1445 V 94 1445 V 119 1427 +a(CONT)l(A)o(CT)p 602 1445 V 262 w(CCC,)g(CCP)l(,)g(CCA,)g(CCE)p +1157 1445 V 75 w(25,)h(47,)f(48,)h(55)p 1540 1445 V 199 w(-)p +1855 1445 V 1864 1445 V 85 1505 V 94 1505 V 119 1487 a(MET)l(AL1)p +602 1505 V 309 w(CMF)p 1157 1505 V 585 w(49)p 1540 1505 V 317 +w(-)p 1855 1505 V 1864 1505 V 85 1565 V 94 1565 V 119 1547 +a(VIA)p 602 1565 V 417 w(CV)-5 b(A)p 1157 1565 V 593 w(50)p +1540 1565 V 317 w(-)p 1855 1565 V 1864 1565 V 85 1625 V 94 +1625 V 119 1607 a(MET)l(AL2)p 602 1625 V 309 w(CMS)p 1157 1625 +V 590 w(51)p 1540 1625 V 317 w(-)p 1855 1625 V 1864 1625 V +85 1685 V 94 1685 V 119 1667 a(GLASS)p 602 1685 V 350 w(COG)p +1157 1685 V 586 w(52)p 1540 1685 V 317 w(-)p 1855 1685 V 1864 +1685 V 85 1746 V 94 1746 V 119 1728 a(ELECTR)o(ODE)p 602 1746 +V 200 w(CEL)p 1157 1746 V 599 w(56)p 1540 1746 V 317 w(-)p +1855 1746 V 1864 1746 V 85 1806 V 94 1806 V 119 1788 a(BURIED)p +318 1788 15 2 v 17 w(CCD)p 602 1806 2 61 v 189 w(CCD)p 1157 +1806 V 590 w(57)p 1540 1806 V 317 w(-)p 1855 1806 V 1864 1806 +V 85 1866 V 94 1866 V 119 1848 a(PBASE)p 602 1866 V 344 w(CBA)p +1157 1866 V 590 w(58)p 1540 1866 V 317 w(-)p 1855 1866 V 1864 +1866 V 85 1926 V 94 1926 V 119 1908 a(CAP)p 227 1908 15 2 v +18 w(WELL)p 602 1926 2 61 v 243 w(CW)o(C)p 1157 1926 V 578 +w(59)p 1540 1926 V 317 w(-)p 1855 1926 V 1864 1926 V 85 1986 +V 94 1986 V 119 1968 a(VIA2)p 602 1986 V 393 w(CVS)p 1157 1986 +V 598 w(61)p 1540 1986 V 317 w(-)p 1855 1986 V 1864 1986 V +85 2047 V 94 2047 V 119 2028 a(MET)l(AL3)p 602 2047 V 309 w(CMT)p +1157 2047 V 582 w(62)p 1540 2047 V 317 w(-)p 1855 2047 V 1864 +2047 V 85 2107 V 94 2107 V 119 2089 a(COMMENT)p 602 2107 V +241 w(CX)p 1157 2107 V 549 w(0)17 b(-)f(20,)h(63)p 1540 2107 +V 241 w(-)p 1855 2107 V 1864 2107 V 86 2108 1778 2 v 444 2243 +a(T)l(able)f(4:)22 b(SCMOS)16 b(tec)o(hnology)g(CIF)g(and)h(GDS)g(la)o(y)o +(ers)963 2828 y(5)p eop +%%Page: 6 6 +bop 96 931 1758 2 v 95 992 2 61 v 104 992 V 640 992 V 897 992 +V 950 973 a Fl(SCMOS)p 1173 992 V 138 w(SCMOS)p 1518 992 V +112 w(SCMOS)p 1719 973 15 2 v 17 w(26G)p 1845 992 2 61 v 1854 +992 V 95 1052 V 104 1052 V 129 1034 a(Description)p 640 1052 +V 347 w(Rule)p 897 1052 V 1173 1052 V 380 w(\(Tigh)o(t)16 b(Metal\))p +1518 1052 V 1845 1052 V 1854 1052 V 95 1112 V 104 1112 V 640 +1112 V 897 1112 V 923 1094 a Fi(\025)e Fl(=)g(0)p Fi(:)p Fl(5)p +Fi(\026)p Fl(m)p 1173 1112 V 83 w Fi(\025)g Fl(=)g(0)p Fi(:)p +Fl(5)p Fi(\026)p Fl(m)p 1518 1112 V 109 w Fi(\025)g Fl(=)g(0)p +Fi(:)p Fl(4)p Fi(\026)p Fl(m)p 1845 1112 V 1854 1112 V 96 1114 +1758 2 v 95 1174 2 61 v 104 1174 V 129 1156 a(WELL)p 275 1156 +15 2 v 19 w(W)p 640 1174 2 61 v 397 w(1.1)p 897 1174 V 211 +w(10)p 1173 1174 V 263 w(10)p 1518 1174 V 288 w(12)p 1845 1174 +V 1854 1174 V 95 1234 V 104 1234 V 129 1216 a(WELL)p 275 1216 +15 2 v 19 w(S)p 321 1216 V 18 w(DIFF)p 640 1234 2 61 v 283 +w(1.2)p 897 1234 V 224 w(9)p 1173 1234 V 286 w(9)p 1518 1234 +V 300 w(18)p 1845 1234 V 1854 1234 V 95 1294 V 104 1294 V 129 +1276 a(WELL)p 275 1276 15 2 v 19 w(O)p 332 1276 V 18 w(A)o(CT)p +456 1276 V 17 w(XTOR)p 640 1294 2 61 v 122 w(2.3)p 897 1294 +V 224 w(5)p 1173 1294 V 286 w(5)p 1518 1294 V 312 w(6)p 1845 +1294 V 1854 1294 V 95 1354 V 104 1354 V 129 1336 a(WELL)p 275 +1336 15 2 v 19 w(S)p 321 1336 V 18 w(A)o(CT)p 445 1336 V 17 +w(XTOR)p 640 1354 2 61 v 133 w(2.3)p 897 1354 V 224 w(5)p 1173 +1354 V 286 w(5)p 1518 1354 V 312 w(6)p 1845 1354 V 1854 1354 +V 95 1415 V 104 1415 V 129 1396 a(POL)l(Y)p 266 1396 15 2 v +18 w(S)p 640 1415 2 61 v 430 w(3.2)p 897 1415 V 224 w(2)p 1173 +1415 V 286 w(2)p 1518 1415 V 312 w(3)p 1845 1415 V 1854 1415 +V 95 1475 V 104 1475 V 129 1457 a(CON)p 242 1457 15 2 v 18 +w(S)p 640 1475 2 61 v 381 w(5B.3,6B.3)p 897 1475 V 151 w(2)p +1173 1475 V 286 w(2)p 1518 1475 V 312 w(3)p 1845 1475 V 1854 +1475 V 95 1535 V 104 1535 V 129 1517 a(M1)p 201 1517 15 2 v +18 w(W)p 640 1535 2 61 v 472 w(7.1)p 897 1535 V 224 w(3)p 1173 +1535 V 286 w(3)p 1518 1535 V 312 w(3)p 1845 1535 V 1854 1535 +V 95 1595 V 104 1595 V 129 1577 a(M1)p 201 1577 15 2 v 18 w(S)p +640 1595 2 61 v 495 w(7.2)p 897 1595 V 224 w(3)p 1173 1595 +V 286 w(2)p 1518 1595 V 312 w(3)p 1845 1595 V 1854 1595 V 95 +1655 V 104 1655 V 129 1637 a(M2)p 201 1637 15 2 v 18 w(W)p +640 1655 2 61 v 472 w(9.1)p 897 1655 V 224 w(3)p 1173 1655 +V 286 w(3)p 1518 1655 V 312 w(3)p 1845 1655 V 1854 1655 V 95 +1716 V 104 1716 V 129 1697 a(M2)p 201 1697 15 2 v 18 w(S)p +640 1716 2 61 v 495 w(9.2)p 897 1716 V 224 w(4)p 1173 1716 +V 286 w(3)p 1518 1716 V 312 w(3)p 1845 1716 V 1854 1716 V 95 +1776 V 104 1776 V 129 1758 a(M3)p 201 1758 15 2 v 18 w(W)p +640 1776 2 61 v 460 w(15.1)p 897 1776 V 212 w(6)p 1173 1776 +V 286 w(6)p 1518 1776 V 312 w(5)p 1845 1776 V 1854 1776 V 95 +1836 V 104 1836 V 129 1818 a(M3)p 201 1818 15 2 v 18 w(S)p +640 1836 2 61 v 483 w(15.2)p 897 1836 V 212 w(4)p 1173 1836 +V 286 w(4)p 1518 1836 V 312 w(3)p 1845 1836 V 1854 1836 V 96 +1838 1758 2 v 545 1972 a(T)l(able)i(5:)22 b(SCMOS)16 b(options)h(for)g +(CMOS26G)963 2828 y(6)p eop +%%Page: 7 7 +bop 0 203 a Fj(5)83 b(SCMOS)27 b(Design)g(Rules)0 327 y Fo(W)-6 +b(ell)21 b(\(CWN,)h(CWP\))30 456 y Fn(1.1)102 b(Minim)n(um)18 +b(width)1073 b(10)30 531 y(1.2)102 b(Minim)n(um)18 b(spacing)g(b)r(et)n(w)n +(een)i(w)n(ells)f(at)h(di\013eren)n(t)g(p)r(oten)n(tial)92 +b(9)30 606 y(1.3)102 b(Minim)n(um)18 b(spacing)g(b)r(et)n(w)n(een)i(w)n(ells) +f(at)h(same)e(p)r(oten)n(tial)178 b(0)19 b(or)i(6)30 680 y(1.4)102 +b(Minim)n(um)18 b(spacing)g(b)r(et)n(w)n(een)i(w)n(ells)f(of)h(di\013eren)n +(t)g(t)n(yp)r(e)209 755 y(\(if)g(b)r(oth)g(are)g(dra)n(wn\))993 +b(0)263 1114 y + 22497362 15721841 8880537 18155765 31377899 33877606 startTexFig +263 1114 a +%%BeginDocument: ciffig/well2.ps +/$F2psDict 32 dict def $F2psDict begin $F2psDict /mtrx matrix put + end /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def +$F2psBegin +-45.000000 662.000000 translate +0.900000 -0.900000 scale +1.000 setlinewidth +newpath 292.000 307.000 moveto 294.000 299.000 lineto 296.000 307.000 lineto stroke +newpath 294 299 moveto 294 329 lineto stroke +newpath 296.000 321.000 moveto 294.000 329.000 lineto 292.000 321.000 lineto stroke + [1 3.000000] 0 setdash +newpath 199 329 moveto 279 329 lineto 279 429 lineto 199 429 lineto closepath stroke + [] 0 setdash +newpath 349.000 316.000 moveto 341.000 314.000 lineto 349.000 312.000 lineto stroke +newpath 341 314 moveto 417 314 lineto stroke +newpath 409.000 312.000 moveto 417.000 314.000 lineto 409.000 316.000 lineto stroke +newpath 429.000 186.000 moveto 421.000 184.000 lineto 429.000 182.000 lineto stroke +newpath 421 184 moveto 497 184 lineto stroke +newpath 489.000 182.000 moveto 497.000 184.000 lineto 489.000 186.000 lineto stroke +newpath 289.000 186.000 moveto 281.000 184.000 lineto 289.000 182.000 lineto stroke +newpath 281 184 moveto 337 184 lineto stroke +newpath 329.000 182.000 moveto 337.000 184.000 lineto 329.000 186.000 lineto stroke + [4.000000] 0 setdash +newpath 499 299 moveto 579 299 lineto 579 199 lineto 499 199 lineto closepath stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 339 299 moveto 419 299 lineto 419 199 lineto 339 199 lineto closepath stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 199 299 moveto 279 299 lineto 279 199 lineto 199 199 lineto closepath stroke + [] 0 setdash +/fn0.16 /Times-Roman findfont 17.777778 scalefont def +fn0.16 setfont +(1.4) 265 320 moveto 1 -1 scale show 1 -1 scale +/fn0.12 /Times-Roman findfont 13.333333 scalefont def +fn0.12 setfont +(CWN) 544 293 moveto 1 -1 scale show 1 -1 scale +(CWN) 384 294 moveto 1 -1 scale show 1 -1 scale +(CWN) 245 294 moveto 1 -1 scale show 1 -1 scale +(CWP) 247 424 moveto 1 -1 scale show 1 -1 scale +/fn0.15 /Times-Roman findfont 16.666667 scalefont def +fn0.15 setfont +(1.3) 448 178 moveto 1 -1 scale show 1 -1 scale +(1.2) 297 177 moveto 1 -1 scale show 1 -1 scale +(1.1) 369 334 moveto 1 -1 scale show 1 -1 scale +showpage +$F2psEnd +%%EndDocument + 263 1114 a + endTexFig +963 2828 a Fl(7)p eop +%%Page: 8 8 +bop 0 198 a Fo(Activ)n(e)21 b(\(CAA\))30 327 y Fn(2.1)102 b(Minim)n(um)18 +b(width)1073 b(3)30 402 y(2.2)102 b(Minim)n(um)18 b(spacing)1028 +b(3)30 477 y(2.3)102 b(Source/drain)20 b(activ)n(e)f(to)h(w)n(ell)f(edge)652 +b(5)30 551 y(2.4)102 b(Substrate/w)n(ell)20 b(con)n(tact)g(activ)n(e)e(to)j +(w)n(ell)e(edge)399 b(3)30 626 y(2.5)102 b(Minim)n(um)18 b(spacing)g(b)r(et)n +(w)n(een)i(activ)n(e)f(of)h(di\013eren)n(t)g(implan)n(t)100 +b(0)19 b(or)i(4)338 1045 y + 20129218 17300602 0 0 20129218 17300602 startTexFig +338 1045 a +%%BeginDocument: ciffig/active.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-122.0 358.0 translate 0.900 -0.900 scale +0.500 setlinewidth +n 442.000 229.000 m 444.000 221.000 l 446.000 229.000 l gs 2 setlinejoin col0 s gr +n 444 221 m 444 247 l gs col0 s gr +n 446.000 239.000 m 444.000 247.000 l 442.000 239.000 l gs 2 setlinejoin col0 s gr +n 442.000 259.000 m 444.000 251.000 l 446.000 259.000 l gs 2 setlinejoin col0 s gr +n 444 251 m 444 277 l gs col0 s gr +n 446.000 269.000 m 444.000 277.000 l 442.000 269.000 l gs 2 setlinejoin col0 s gr +n 259.000 126.000 m 251.000 124.000 l 259.000 122.000 l gs 2 setlinejoin col0 s gr +n 251 124 m 277 124 l gs col0 s gr +n 269.000 122.000 m 277.000 124.000 l 269.000 126.000 l gs 2 setlinejoin col0 s gr +n 339.000 126.000 m 331.000 124.000 l 339.000 122.000 l gs 2 setlinejoin col0 s gr +n 331 124 m 367 124 l gs col0 s gr +n 359.000 122.000 m 367.000 124.000 l 359.000 126.000 l gs 2 setlinejoin col0 s gr +n 339.000 376.000 m 331.000 374.000 l 339.000 372.000 l gs 2 setlinejoin col0 s gr +n 331 374 m 367 374 l gs col0 s gr +n 359.000 372.000 m 367.000 374.000 l 359.000 376.000 l gs 2 setlinejoin col0 s gr +n 259.000 376.000 m 251.000 374.000 l 259.000 372.000 l gs 2 setlinejoin col0 s gr +n 251 374 m 277 374 l gs col0 s gr +n 269.000 372.000 m 277.000 374.000 l 269.000 376.000 l gs 2 setlinejoin col0 s gr +n 162.000 169.000 m 164.000 161.000 l 166.000 169.000 l gs 2 setlinejoin col0 s gr +n 164 161 m 164 197 l gs col0 s gr +n 166.000 189.000 m 164.000 197.000 l 162.000 189.000 l gs 2 setlinejoin col0 s gr +n 162.000 309.000 m 164.000 301.000 l 166.000 309.000 l gs 2 setlinejoin col0 s gr +n 164 301 m 164 337 l gs col0 s gr +n 166.000 329.000 m 164.000 337.000 l 162.000 329.000 l gs 2 setlinejoin col0 s gr +n 439 249 m 459 249 l gs col0 s gr + 1 setlinecap [1 3.000000] 3.000000 setdash +n 349 239 m 429 239 l 429 139 l 349 139 l clp gs col0 s gr + [] 0 setdash 0 setlinecap + [4.000000] 0 setdash +n 349 359 m 429 359 l 429 259 l 349 259 l clp gs col0 s gr + [] 0 setdash + 1 setlinecap [1 3.000000] 3.000000 setdash +n 179 359 m 349 359 l 349 279 l 179 279 l clp gs col0 s gr + [] 0 setdash 0 setlinecap + [4.000000] 0 setdash +n 179 219 m 349 219 l 349 139 l 179 139 l clp gs col0 s gr + [] 0 setdash +n 302.000 259.000 m 304.000 251.000 l 306.000 259.000 l gs 2 setlinejoin col0 s gr +n 304 251 m 304 297 l gs col0 s gr +n 306.000 289.000 m 304.000 297.000 l 302.000 289.000 l gs 2 setlinejoin col0 s gr +n 302.000 209.000 m 304.000 201.000 l 306.000 209.000 l gs 2 setlinejoin col0 s gr +n 304 201 m 304 247 l gs col0 s gr +n 306.000 239.000 m 304.000 247.000 l 302.000 239.000 l gs 2 setlinejoin col0 s gr +n 135 249 m 160 249 l gs col0 s gr +n 159 249 m 439 249 l gs col0 s gr +0.000 setlinewidth +n 199 299 m 249 299 l 249 339 l 199 339 l clp gs 0.75 setgray fill gr +n 279 299 m 329 299 l 329 339 l 279 339 l clp gs 0.75 setgray fill gr +n 369 279 m 409 279 l 409 339 l 369 339 l clp gs 0.75 setgray fill gr +n 369 219 m 409 219 l 409 159 l 369 159 l clp gs 0.75 setgray fill gr +n 279 199 m 329 199 l 329 159 l 279 159 l clp gs 0.75 setgray fill gr +n 199 199 m 249 199 l 249 159 l 199 159 l clp gs 0.75 setgray fill gr +/Times-Roman findfont 12.00 scalefont setfont +211 184 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +211 324 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +293 324 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +377 194 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +376 316 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +293 184 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +403 234 m +gs 1 -1 scale (CSP) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +184 354 m +gs 1 -1 scale (CSP) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +183 214 m +gs 1 -1 scale (CSN) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +400 355 m +gs 1 -1 scale (CSN) col0 show gr +/Times-Roman findfont 9.00 scalefont setfont +159 229 m +gs 1 -1 scale (_) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +169 243 m +gs 1 -1 scale (region) col0 show gr +/Times-Roman findfont 9.00 scalefont setfont +159 258 m +gs 1 -1 scale (_) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +146 243 m +gs 1 -1 scale (P) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +169 273 m +gs 1 -1 scale (region) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +145 273 m +gs 1 -1 scale (N) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +137 325 m +gs 1 -1 scale (2.1) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +338 118 m +gs 1 -1 scale (2.5) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +253 118 m +gs 1 -1 scale (2.2) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +137 186 m +gs 1 -1 scale (2.1) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +274 238 m +gs 1 -1 scale (2.3) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +453 241 m +gs 1 -1 scale (2.4) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +313 273 m +gs 1 -1 scale (2.3) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +452 272 m +gs 1 -1 scale (2.4) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +336 397 m +gs 1 -1 scale (2.5) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +252 396 m +gs 1 -1 scale (2.2) col0 show gr +$F2psEnd +%%EndDocument + 338 1045 a + endTexFig +963 2828 a Fl(8)p eop +%%Page: 9 9 +bop 0 198 a Fo(P)n(oly)23 b(\(CPG\))30 327 y Fn(3.1)102 b(Minim)n(um)18 +b(width)1073 b(2)30 402 y(3.2)102 b(Minim)n(um)18 b(spacing)1028 +b(2)30 477 y(3.3)102 b(Minim)n(um)18 b(gate)h(extension)f(of)i(activ)n(e)607 +b(2)30 551 y(3.4)102 b(Minim)n(um)18 b(activ)n(e)g(extension)h(of)h(plo)n(y) +607 b(3)30 626 y(3.5)102 b(Minim)n(um)18 b(\014eld)h(p)r(oly)g(to)h(activ)n +(e)733 b(1)548 940 y + 13485260 14471987 0 0 13485260 14471987 startTexFig +548 940 a +%%BeginDocument: ciffig/poly.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-182.0 291.0 translate 0.900 -0.900 scale +0.500 setlinewidth +n 377.000 247.000 m 379.000 239.000 l 381.000 247.000 l gs 2 setlinejoin col0 s gr +n 379 239 m 379 269 l gs col0 s gr +n 381.000 261.000 m 379.000 269.000 l 377.000 261.000 l gs 2 setlinejoin col0 s gr +n 399 164 m 399 177 l gs col0 s gr +n 401.000 169.000 m 399.000 177.000 l 397.000 169.000 l gs 2 setlinejoin col0 s gr +n 399 214 m 399 201 l gs col0 s gr +n 397.000 209.000 m 399.000 201.000 l 401.000 209.000 l gs 2 setlinejoin col0 s gr +n 359 234 m 359 221 l gs col0 s gr +n 357.000 229.000 m 359.000 221.000 l 361.000 229.000 l gs 2 setlinejoin col0 s gr +n 359 184 m 359 197 l gs col0 s gr +n 361.000 189.000 m 359.000 197.000 l 357.000 189.000 l gs 2 setlinejoin col0 s gr +n 354 299 m 341 299 l gs col0 s gr +n 349.000 301.000 m 341.000 299.000 l 349.000 297.000 l gs 2 setlinejoin col0 s gr +n 304 299 m 317 299 l gs col0 s gr +n 309.000 297.000 m 317.000 299.000 l 309.000 301.000 l gs 2 setlinejoin col0 s gr +n 274 99 m 261 99 l gs col0 s gr +n 269.000 101.000 m 261.000 99.000 l 269.000 97.000 l gs 2 setlinejoin col0 s gr +n 234 99 m 247 99 l gs col0 s gr +n 239.000 97.000 m 247.000 99.000 l 239.000 101.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 229 179 m 249 179 l 249 129 l 229 129 l clp gs 0.50 setgray fill gr +n 229 239 m 249 239 l 249 279 l 229 279 l clp gs 0.50 setgray fill gr +n 229 219 m 259 219 l 259 239 l 229 239 l clp gs 0.50 setgray fill gr +n 229 179 m 259 179 l 259 199 l 229 199 l clp gs 0.50 setgray fill gr +n 259 239 m 319 239 l 319 219 l 259 219 l clp gs 0.30 setgray fill gr +n 259 199 m 319 199 l 319 179 l 259 179 l clp gs 0.30 setgray fill gr +n 259 239 m 319 239 l 319 269 l 259 269 l clp gs 0.75 setgray fill gr +n 259 219 m 319 219 l 319 199 l 259 199 l clp gs 0.75 setgray fill gr +n 319 239 m 339 239 l 339 219 l 319 219 l clp gs 0.50 setgray fill gr +n 319 199 m 339 199 l 339 179 l 319 179 l clp gs 0.50 setgray fill gr +n 259 179 m 319 179 l 319 159 l 259 159 l clp gs 0.75 setgray fill gr +n 259 159 m 379 159 l 379 119 l 259 119 l clp gs 0.75 setgray fill gr +/Times-Roman findfont 12.00 scalefont setfont +288 263 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +202 167 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +203 264 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +339 138 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +387 260 m +gs 1 -1 scale (3.4) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +243 91 m +gs 1 -1 scale (3.5) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +407 195 m +gs 1 -1 scale (3.1) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +367 216 m +gs 1 -1 scale (3.2) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +319 323 m +gs 1 -1 scale (3.3) col0 show gr +$F2psEnd +%%EndDocument + 548 940 a + endTexFig +963 2828 a Fl(9)p eop +%%Page: 10 10 +bop 0 198 a Fo(Select)20 b(\(CSN,)j(CSP\))30 327 y Fn(4.1)102 +b(Minim)n(um)18 b(select)g(spacing)g(to)j(c)n(hannel)e(of)h(transistor)g(to) +209 402 y(ensure)g(adequate)f(source/drain)g(width)556 b(3)30 +477 y(4.2)102 b(Minim)n(um)18 b(select)g(o)n(v)n(erlap)h(of)h(activ)n(e)630 +b(2)30 551 y(4.3)102 b(Minim)n(um)18 b(select)g(o)n(v)n(erlap)h(of)h(con)n +(tact)593 b(1)30 626 y(4.4)102 b(Minim)n(um)18 b(select)g(width)i(and)g +(spacing)580 b(2)209 701 y(\(Note:)26 b(P-select)18 b(and)i(N-select)e(ma)n +(y)g(b)r(e)i(coinciden)n(t,)e(but)229 775 y(m)n(ust)h Fm(not)g +Fn(o)n(v)n(erlap\))308 1165 y + 21050163 14669332 0 0 21050163 14669332 startTexFig +308 1165 a +%%BeginDocument: ciffig/select.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-112.0 302.0 translate 0.900 -0.900 scale +0.500 setlinewidth +n 174 125 m 189 125 l gs col0 s gr +n 181.000 123.000 m 189.000 125.000 l 181.000 127.000 l gs 2 setlinejoin col0 s gr +n 208.000 127.000 m 200.000 125.000 l 208.000 123.000 l gs 2 setlinejoin col0 s gr +n 200 125 m 215 125 l gs col0 s gr +n 217.000 106.000 m 209.000 104.000 l 217.000 102.000 l gs 2 setlinejoin col0 s gr +n 209 104 m 224 104 l gs col0 s gr +n 184 104 m 199 104 l gs col0 s gr +n 191.000 102.000 m 199.000 104.000 l 191.000 106.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 159 179 m 169 179 l 169 159 l 159 159 l clp gs 0.75 setgray fill gr +n 189 179 m 209 179 l 209 159 l 189 159 l clp gs 0.75 setgray fill gr +n 159 159 m 209 159 l 209 149 l 159 149 l clp gs 0.75 setgray fill gr +n 169 159 m 189 159 l 189 179 l 169 179 l clp gs 0.00 setgray fill gr +0.500 setlinewidth +n 174 314 m 161 314 l gs col0 s gr +n 169.000 316.000 m 161.000 314.000 l 169.000 312.000 l gs 2 setlinejoin col0 s gr +n 124 314 m 137 314 l gs col0 s gr +n 129.000 312.000 m 137.000 314.000 l 129.000 316.000 l gs 2 setlinejoin col0 s gr +n 272.000 199.000 m 274.000 191.000 l 276.000 199.000 l gs 2 setlinejoin col0 s gr +n 274 191 m 274 217 l gs col0 s gr +n 276.000 209.000 m 274.000 217.000 l 272.000 209.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 359 239 m 449 239 l 449 219 l 359 219 l clp gs 0.35 setgray fill gr +n 159 239 m 239 239 l 239 219 l 159 219 l clp gs 0.35 setgray fill gr +n 419 159 m 439 159 l 439 149 l 419 149 l clp gs 0.75 setgray fill gr +n 359 179 m 419 179 l 419 149 l 359 149 l clp gs 0.75 setgray fill gr +n 359 219 m 439 219 l 439 179 l 359 179 l clp gs 0.75 setgray fill gr +n 419 179 m 439 179 l 439 159 l 419 159 l clp gs 0.00 setgray fill gr +n 229 179 m 239 179 l 239 159 l 229 159 l clp gs 0.75 setgray fill gr +n 209 159 m 239 159 l 239 149 l 209 149 l clp gs 0.75 setgray fill gr +n 159 219 m 239 219 l 239 179 l 159 179 l clp gs 0.75 setgray fill gr +0.500 setlinewidth +n 209 179 m 229 179 l 229 159 l 209 159 l clp gs 0.00 setgray fill gr +gs col0 s gr +1.000 setlinewidth + 1 setlinecap [1 3.000000] 3.000000 setdash +n 409 189 m 469 189 l gs col0 s gr + [] 0 setdash 0 setlinecap + 1 setlinecap [1 3.000000] 3.000000 setdash +n 409 109 m 409 189 l gs col0 s gr + [] 0 setdash 0 setlinecap + 1 setlinecap [1 3.000000] 3.000000 setdash +n 339 109 m 409 109 l gs col0 s gr + [] 0 setdash 0 setlinecap + 1 setlinecap [1 3.000000] 3.000000 setdash +n 469 299 m 469 189 l gs col0 s gr + [] 0 setdash 0 setlinecap + 1 setlinecap [1 3.000000] 3.000000 setdash +n 339 299 m 469 299 l gs col0 s gr + [] 0 setdash 0 setlinecap + 1 setlinecap [1 3.000000] 3.000000 setdash +n 339 109 m 339 299 l gs col0 s gr + [] 0 setdash 0 setlinecap + 1 setlinecap [1 3.000000] 3.000000 setdash +n 199 189 m 259 189 l 259 129 l 199 129 l clp gs col0 s gr + [] 0 setdash 0 setlinecap +0.500 setlinewidth +n 319 109 m 319 319 l gs col0 s gr + [4.000000] 0 setdash +n 409 129 m 469 129 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 469 189 m 469 129 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 409 189 m 469 189 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 409 129 m 409 189 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 199 129 m 199 189 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 139 129 m 199 129 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 139 129 m 139 299 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 199 189 m 259 189 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 259 299 m 259 189 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 139 299 m 259 299 l gs col0 s gr + [] 0 setdash +0.000 setlinewidth +n 459 269 m 479 269 l 479 239 l 459 239 l clp gs 0.50 setgray fill gr +n 449 239 m 479 239 l 479 219 l 449 219 l clp gs 0.50 setgray fill gr +n 439 219 m 449 219 l 449 149 l 439 149 l clp gs 0.75 setgray fill gr +n 439 279 m 449 279 l 449 239 l 439 239 l clp gs 0.75 setgray fill gr +n 359 149 m 389 149 l 389 129 l 359 129 l clp gs 0.75 setgray fill gr +n 359 279 m 439 279 l 439 239 l 359 239 l clp gs 0.75 setgray fill gr +n 159 279 m 239 279 l 239 239 l 159 239 l clp gs 0.75 setgray fill gr +n 339 239 m 359 239 l 359 219 l 339 219 l clp gs 0.50 setgray fill gr +n 239 239 m 339 239 l 339 219 l 239 219 l clp gs 0.50 setgray fill gr +n 139 239 m 159 239 l 159 219 l 139 219 l clp gs 0.50 setgray fill gr +/Times-Roman findfont 15.00 scalefont setfont +185 122 m +gs 1 -1 scale (4.3) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +232 174 m +gs 1 -1 scale (CCA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +231 144 m +gs 1 -1 scale (CSP) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +441 144 m +gs 1 -1 scale (CSN) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +208 275 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +278 253 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +416 274 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +343 294 m +gs 1 -1 scale (CSP) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +143 295 m +gs 1 -1 scale (CSN) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +275 335 m +gs 1 -1 scale (CWP) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +439 335 m +gs 1 -1 scale (CWN) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +196 100 m +gs 1 -1 scale (4.3) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +138 334 m +gs 1 -1 scale (4.2) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +280 211 m +gs 1 -1 scale (4.1) col0 show gr +$F2psEnd +%%EndDocument + 308 1165 a + endTexFig +951 2828 a Fl(10)p eop +%%Page: 11 11 +bop 0 198 a Fo(Simpl)o(e)19 b(Con)n(tact)k(to)g(P)n(oly)g(\(CCP\))30 +327 y Fn(5.1.a)55 b(Exact)19 b(con)n(tact)h(size)1017 b(2)19 +b Fc(\002)i Fn(2)30 402 y(5.2.a)55 b(Minim)n(um)18 b(p)r(oly)g(o)n(v)n(erlap) +902 b(1.5)30 477 y(5.3.a)55 b(Minim)n(um)18 b(con)n(tact)h(spacing)818 +b(2)615 1136 y + 11380244 7630684 0 0 11380244 7630684 startTexFig +615 1136 a +%%BeginDocument: ciffig/contact1.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-238.0 267.0 translate 0.900 -0.900 scale +n 264 204 m 394 204 l 394 254 l 264 254 l clp gs 0.70 setgray fill gr +0.500 setlinewidth +n 414 234 m 414 221 l gs col0 s gr +n 412.000 229.000 m 414.000 221.000 l 416.000 229.000 l gs 2 setlinejoin col0 s gr +n 414 189 m 414 204 l gs col0 s gr +n 416.000 196.000 m 414.000 204.000 l 412.000 196.000 l gs 2 setlinejoin col0 s gr +n 372 189 m 359 189 l gs col0 s gr +n 367.000 191.000 m 359.000 189.000 l 367.000 187.000 l gs 2 setlinejoin col0 s gr +n 326 189 m 339 189 l gs col0 s gr +n 331.000 187.000 m 339.000 189.000 l 331.000 191.000 l gs 2 setlinejoin col0 s gr +n 314 274 m 301 274 l gs col0 s gr +n 309.000 276.000 m 301.000 274.000 l 309.000 272.000 l gs 2 setlinejoin col0 s gr +n 264 274 m 277 274 l gs col0 s gr +n 269.000 272.000 m 277.000 274.000 l 269.000 276.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 359 239 m 379 239 l 379 219 l 359 219 l clp gs 0.00 setgray fill gr +n 319 239 m 339 239 l 339 219 l 319 219 l clp gs 0.00 setgray fill gr +n 279 239 m 299 239 l 299 219 l 279 219 l clp gs 0.00 setgray fill gr +/Times-Roman findfont 16.00 scalefont setfont +422 218 m +gs 1 -1 scale (5.2.a) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +333 181 m +gs 1 -1 scale (5.3.a) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +272 296 m +gs 1 -1 scale (5.1.a) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +269 217 m +gs 1 -1 scale (CCP) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +372 255 m +gs 1 -1 scale (CPG) col0 show gr +$F2psEnd +%%EndDocument + 615 1136 a + endTexFig +951 2828 a Fl(11)p eop +%%Page: 12 12 +bop 0 198 a Fo(Simpl)o(e)19 b(Con)n(tact)k(to)g(Activ)n(e)e(\(CCA\))30 +327 y Fn(6.1.a)55 b(Exact)19 b(con)n(tact)h(size)1017 b(2)19 +b Fc(\002)i Fn(2)30 402 y(6.2.a)55 b(Minim)n(um)18 b(activ)n(e)g(o)n(v)n +(erlap)862 b(1.5)30 477 y(6.3.a)55 b(Minim)n(um)18 b(con)n(tact)h(spacing)818 +b(2)30 551 y(6.4.a)55 b(Minim)n(um)18 b(spacing)g(to)i(gate)g(of)g +(transistor)489 b(2)590 1120 y + 12169625 10788208 0 0 12169625 10788208 startTexFig +590 1120 a +%%BeginDocument: ciffig/acon1.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-216.0 305.0 translate 0.900 -0.900 scale +0.500 setlinewidth +n 404 254 m 404 241 l gs col0 s gr +n 402.000 249.000 m 404.000 241.000 l 406.000 249.000 l gs 2 setlinejoin col0 s gr +n 404 204 m 404 217 l gs col0 s gr +n 406.000 209.000 m 404.000 217.000 l 402.000 209.000 l gs 2 setlinejoin col0 s gr +n 354 179 m 341 179 l gs col0 s gr +n 349.000 181.000 m 341.000 179.000 l 349.000 177.000 l gs 2 setlinejoin col0 s gr +n 304 179 m 317 179 l gs col0 s gr +n 309.000 177.000 m 317.000 179.000 l 309.000 181.000 l gs 2 setlinejoin col0 s gr +n 314 204 m 301 204 l gs col0 s gr +n 309.000 206.000 m 301.000 204.000 l 309.000 202.000 l gs 2 setlinejoin col0 s gr +n 264 204 m 277 204 l gs col0 s gr +n 269.000 202.000 m 277.000 204.000 l 269.000 206.000 l gs 2 setlinejoin col0 s gr +n 296 294 m 279 294 l gs col0 s gr +n 287.000 296.000 m 279.000 294.000 l 287.000 292.000 l gs 2 setlinejoin col0 s gr +n 244 294 m 257 294 l gs col0 s gr +n 249.000 292.000 m 257.000 294.000 l 249.000 296.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 339 219 m 359 219 l 359 279 l 339 279 l clp gs 0.35 setgray fill gr +n 339 219 m 359 219 l 359 199 l 339 199 l clp gs 0.50 setgray fill gr +n 319 259 m 339 259 l 339 239 l 319 239 l clp gs 0.75 setgray fill gr +n 279 259 m 299 259 l 299 239 l 279 239 l clp gs 0.75 setgray fill gr +n 239 259 m 259 259 l 259 239 l 239 239 l clp gs 0.75 setgray fill gr +n 239 239 m 339 239 l 339 219 l 239 219 l clp gs 0.75 setgray fill gr +n 359 279 m 389 279 l 389 219 l 359 219 l clp gs 0.75 setgray fill gr +n 239 279 m 339 279 l 339 259 l 239 259 l clp gs 0.75 setgray fill gr +n 339 279 m 359 279 l 359 319 l 339 319 l clp gs 0.50 setgray fill gr +n 299 259 m 319 259 l 319 239 l 299 239 l clp gs 0.00 setgray fill gr +n 259 259 m 279 259 l 279 239 l 259 239 l clp gs 0.00 setgray fill gr +/Times-Roman findfont 16.00 scalefont setfont +273 198 m +gs 1 -1 scale (6.3.a) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +411 236 m +gs 1 -1 scale (6.2.a) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +312 170 m +gs 1 -1 scale (6.4.a) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +251 316 m +gs 1 -1 scale (6.1.a) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +247 235 m +gs 1 -1 scale (CCA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +305 275 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +339 338 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +364 274 m +gs 1 -1 scale (CAA) col0 show gr +$F2psEnd +%%EndDocument + 590 1120 a + endTexFig +951 2828 a Fl(12)p eop +%%Page: 13 13 +bop 0 202 a Fo(Alternativ)n(e)343 180 y Fg(3)387 202 y Fo(Con)n(tact)22 +b(to)h(P)n(oly)g(\(CCP\))30 331 y Fn(5.1.b)52 b(Exact)19 b(con)n(tact)h(size) +1017 b(2)19 b Fc(\002)i Fn(2)30 405 y(5.2.b)52 b(Minim)n(um)18 +b(p)r(oly)g(o)n(v)n(erlap)902 b(1)30 480 y(5.3.b)52 b(Minim)n(um)18 +b(con)n(tact)h(spacing)818 b(2)30 555 y(5.4.b)52 b(Minim)n(um)18 +b(spacing)g(to)i(other)h(p)r(oly)666 b(4)30 630 y(5.5.b)52 +b(Minim)n(um)18 b(spacing)g(to)i(activ)n(e)f(\(one)h(con)n(tact\))417 +b(2)30 704 y(5.6.b)52 b(Minim)n(um)18 b(spacing)g(to)i(activ)n(e)f(\(man)n(y) +g(con)n(tacts\))340 b(3)202 1019 y + 24405032 15327150 0 0 24405032 15327150 startTexFig +202 1019 a +%%BeginDocument: ciffig/contact2.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-151.0 357.0 translate 0.900 -0.900 scale +n 459 259 m 479 259 l 479 299 l 459 299 l clp gs 0.35 setgray fill gr +0.500 setlinewidth +n 294 374 m 279 374 l gs 0.50 setgray fill gr +gs col0 s gr +n 287.000 376.000 m 279.000 374.000 l 287.000 372.000 l gs 2 setlinejoin col0 s gr +n 244 374 m 259 374 l gs 0.50 setgray fill gr +gs col0 s gr +n 251.000 372.000 m 259.000 374.000 l 251.000 376.000 l gs 2 setlinejoin col0 s gr +n 304 159 m 289 159 l gs 0.50 setgray fill gr +gs col0 s gr +n 297.000 161.000 m 289.000 159.000 l 297.000 157.000 l gs 2 setlinejoin col0 s gr +n 254 159 m 269 159 l gs 0.50 setgray fill gr +gs col0 s gr +n 261.000 157.000 m 269.000 159.000 l 261.000 161.000 l gs 2 setlinejoin col0 s gr +n 539 334 m 539 319 l gs 0.50 setgray fill gr +gs col0 s gr +n 537.000 327.000 m 539.000 319.000 l 541.000 327.000 l gs 2 setlinejoin col0 s gr +n 539 284 m 539 299 l gs 0.50 setgray fill gr +gs col0 s gr +n 541.000 291.000 m 539.000 299.000 l 537.000 291.000 l gs 2 setlinejoin col0 s gr +n 367.000 251.000 m 359.000 249.000 l 367.000 247.000 l gs 2 setlinejoin col0 s gr +n 359 249 m 409 249 l gs 0.50 setgray fill gr +gs col0 s gr +n 401.000 247.000 m 409.000 249.000 l 401.000 251.000 l gs 2 setlinejoin col0 s gr +n 209 164 m 209 179 l gs 0.50 setgray fill gr +gs col0 s gr +n 211.000 171.000 m 209.000 179.000 l 207.000 171.000 l gs 2 setlinejoin col0 s gr +n 209 204 m 209 189 l gs 0.50 setgray fill gr +gs col0 s gr +n 207.000 197.000 m 209.000 189.000 l 211.000 197.000 l gs 2 setlinejoin col0 s gr +n 207.000 307.000 m 209.000 299.000 l 211.000 307.000 l gs 2 setlinejoin col0 s gr +n 209 299 m 209 329 l gs 0.50 setgray fill gr +gs col0 s gr +n 211.000 321.000 m 209.000 329.000 l 207.000 321.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth + [4.000000] 0 setdash +n 229 349 m 239 349 l 239 329 l 229 329 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 379 359 m 389 359 l 389 329 l 379 329 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 339 349 m 359 349 l 359 329 l 339 329 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 299 349 m 319 349 l 319 329 l 299 329 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 259 349 m 279 349 l 279 329 l 259 329 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 229 329 m 389 329 l 389 319 l 229 319 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 359 349 m 379 349 l 379 329 l 359 329 l clp gs 0.00 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 229 359 m 379 359 l 379 349 l 229 349 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 229 299 m 369 299 l 369 259 l 229 259 l clp gs 0.75 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 449 339 m 459 339 l 459 319 l 449 319 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 479 339 m 489 339 l 489 319 l 479 319 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 449 349 m 489 349 l 489 339 l 449 339 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 459 309 m 479 309 l 479 299 l 459 299 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 449 309 m 489 309 l 489 319 l 449 319 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 459 319 m 479 319 l 479 339 l 459 339 l clp gs 0.00 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 479 299 m 519 299 l 519 259 l 479 259 l clp gs 0.75 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 419 299 m 459 299 l 459 259 l 419 259 l clp gs 0.75 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 459 219 m 479 219 l 479 259 l 459 259 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 339 189 m 359 189 l 359 159 l 339 159 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 339 219 m 359 219 l 359 209 l 339 209 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 359 219 m 369 219 l 369 179 l 359 179 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 329 219 m 339 219 l 339 179 l 329 179 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 229 209 m 269 209 l 269 189 l 229 189 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 289 209 m 299 209 l 299 189 l 289 189 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 259 189 m 299 189 l 299 179 l 259 179 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 259 219 m 299 219 l 299 209 l 259 209 l clp gs 0.50 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 339 209 m 359 209 l 359 189 l 339 189 l clp gs 0.00 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 269 209 m 289 209 l 289 189 l 269 189 l clp gs 0.00 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 319 349 m 339 349 l 339 329 l 319 329 l clp gs 0.00 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 279 349 m 299 349 l 299 329 l 279 329 l clp gs 0.00 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 239 349 m 259 349 l 259 329 l 239 329 l clp gs 0.00 setgray fill gr + [] 0 setdash + [4.000000] 0 setdash +n 409 239 m 429 239 l 429 149 l 409 149 l clp gs 0.50 setgray fill gr + [] 0 setdash +/Times-Roman findfont 16.00 scalefont setfont +545 315 m +gs 1 -1 scale (5.5.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +368 243 m +gs 1 -1 scale (5.4.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +262 151 m +gs 1 -1 scale (5.1.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +167 190 m +gs 1 -1 scale (5.2.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +167 320 m +gs 1 -1 scale (5.6.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +252 396 m +gs 1 -1 scale (5.3.b) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +440 353 m +gs 1 -1 scale (CCP) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +337 331 m +gs 1 -1 scale (CCP) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +492 292 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +434 178 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +288 292 m +gs 1 -1 scale (CAA) col0 show gr +$F2psEnd +%%EndDocument + 202 1019 a + endTexFig +0 2658 780 2 v 56 2688 a Fh(3)75 2704 y Fg(If)13 b(y)o(ou)h(ha)o(v)o(e)f +(di\016culties)h(with)f(half)g(lam)o(b)q(da)f(rule.)951 2828 +y Fl(13)p eop +%%Page: 14 14 +bop 0 202 a Fo(Alternativ)n(e)343 180 y Fg(4)387 202 y Fo(Con)n(tact)22 +b(to)h(Activ)n(e)e(\(CCA\))30 331 y Fn(6.1.b)52 b(Exact)19 +b(con)n(tact)h(size)1017 b(2)19 b Fc(\002)i Fn(2)30 405 y(6.2.b)52 +b(Minim)n(um)18 b(activ)n(e)g(o)n(v)n(erlap)862 b(1)30 480 +y(6.3.b)52 b(Minim)n(um)18 b(con)n(tact)h(spacing)818 b(2)30 +555 y(6.4.b)52 b(Minim)n(um)18 b(spacing)g(to)i(di\013usion)g(activ)n(e)541 +b(5)30 630 y(6.5.b)52 b(Minim)n(um)18 b(spacing)g(to)i(gate)g(of)g +(transistor)489 b(2)30 704 y(6.6.b)52 b(Minim)n(um)18 b(sap)r(cing)g(to)i +(\014eld)g(p)r(oly)e(\(one)i(con)n(tact\))326 b(2)30 779 y(6.7.b)52 +b(Minim)n(um)18 b(spacing)g(to)i(\014eld)g(p)r(oly)f(\(man)n(y)g(con)n +(tacts\))250 b(3)30 854 y(6.8.b)52 b(Minim)n(um)18 b(spacing)g(to)i(p)r(oly)f +(con)n(tact)613 b(4)310 988 y + 20984381 14932459 0 0 20984381 14932459 startTexFig +310 988 a +%%BeginDocument: ciffig/acon2.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-171.0 333.0 translate 0.900 -0.900 scale +n 299 329 m 389 329 l 389 369 l 299 369 l clp gs 0.75 setgray fill gr +0.500 setlinewidth +n 487.000 289.000 m 489.000 281.000 l 491.000 289.000 l gs 2 setlinejoin col0 s gr +n 489 281 m 489 317 l gs col0 s gr +n 491.000 309.000 m 489.000 317.000 l 487.000 309.000 l gs 2 setlinejoin col0 s gr +n 499 274 m 499 261 l gs col0 s gr +n 497.000 269.000 m 499.000 261.000 l 501.000 269.000 l gs 2 setlinejoin col0 s gr +n 499 214 m 499 227 l gs col0 s gr +n 501.000 219.000 m 499.000 227.000 l 497.000 219.000 l gs 2 setlinejoin col0 s gr +n 319 304 m 319 291 l gs col0 s gr +n 317.000 299.000 m 319.000 291.000 l 321.000 299.000 l gs 2 setlinejoin col0 s gr +n 319 264 m 319 277 l gs col0 s gr +n 321.000 269.000 m 319.000 277.000 l 317.000 269.000 l gs 2 setlinejoin col0 s gr +n 334 139 m 321 139 l gs col0 s gr +n 329.000 141.000 m 321.000 139.000 l 329.000 137.000 l gs 2 setlinejoin col0 s gr +n 284 139 m 297 139 l gs col0 s gr +n 289.000 137.000 m 297.000 139.000 l 289.000 141.000 l gs 2 setlinejoin col0 s gr +n 229 184 m 229 197 l gs col0 s gr +n 231.000 189.000 m 229.000 197.000 l 227.000 189.000 l gs 2 setlinejoin col0 s gr +n 229 234 m 229 221 l gs col0 s gr +n 227.000 229.000 m 229.000 221.000 l 231.000 229.000 l gs 2 setlinejoin col0 s gr +n 249 224 m 249 237 l gs col0 s gr +n 251.000 229.000 m 249.000 237.000 l 247.000 229.000 l gs 2 setlinejoin col0 s gr +n 249 274 m 249 261 l gs col0 s gr +n 247.000 269.000 m 249.000 261.000 l 251.000 269.000 l gs 2 setlinejoin col0 s gr +n 227.000 289.000 m 229.000 281.000 l 231.000 289.000 l gs 2 setlinejoin col0 s gr +n 229 281 m 229 327 l gs col0 s gr +n 231.000 319.000 m 229.000 327.000 l 227.000 319.000 l gs 2 setlinejoin col0 s gr +n 474 194 m 461 194 l gs col0 s gr +n 469.000 196.000 m 461.000 194.000 l 469.000 192.000 l gs 2 setlinejoin col0 s gr +n 424 194 m 437 194 l gs col0 s gr +n 429.000 192.000 m 437.000 194.000 l 429.000 196.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 269 289 m 309 289 l 309 279 l 269 279 l clp gs 0.75 setgray fill gr +n 269 279 m 279 279 l 279 199 l 269 199 l clp gs 0.75 setgray fill gr +n 299 279 m 309 279 l 309 199 l 299 199 l clp gs 0.75 setgray fill gr +n 279 219 m 299 219 l 299 199 l 279 199 l clp gs 0.75 setgray fill gr +n 459 341 m 469 341 l 469 309 l 459 309 l clp gs 0.50 setgray fill gr +n 279 259 m 299 259 l 299 239 l 279 239 l clp gs 0.75 setgray fill gr +n 269 199 m 309 199 l 309 179 l 269 179 l clp gs 0.35 setgray fill gr +n 439 319 m 459 319 l 459 309 l 439 309 l clp gs 0.50 setgray fill gr +n 439 349 m 469 349 l 469 339 l 439 339 l clp gs 0.50 setgray fill gr +n 429 309 m 439 309 l 439 349 l 429 349 l clp gs 0.50 setgray fill gr +n 459 279 m 479 279 l 479 259 l 459 259 l clp gs 0.75 setgray fill gr +n 419 279 m 439 279 l 439 259 l 419 259 l clp gs 0.75 setgray fill gr +n 379 279 m 399 279 l 399 259 l 379 259 l clp gs 0.75 setgray fill gr +n 349 279 m 359 279 l 359 259 l 349 259 l clp gs 0.75 setgray fill gr +n 349 339 m 389 339 l 389 289 l 349 289 l clp gs 0.75 setgray fill gr +n 349 289 m 479 289 l 479 279 l 349 279 l clp gs 0.75 setgray fill gr +n 349 259 m 479 259 l 479 249 l 349 249 l clp gs 0.75 setgray fill gr +n 349 289 m 479 289 l 479 279 l 349 279 l clp gs 0.75 setgray fill gr +n 339 229 m 479 229 l 479 209 l 339 209 l clp gs 0.50 setgray fill gr +n 319 199 m 339 199 l 339 229 l 319 229 l clp gs 0.50 setgray fill gr +n 309 199 m 339 199 l 339 179 l 309 179 l clp gs 0.50 setgray fill gr +n 249 199 m 269 199 l 269 179 l 249 179 l clp gs 0.50 setgray fill gr +n 269 179 m 310 179 l 310 148 l 269 148 l clp gs 0.75 setgray fill gr +n 439 339 m 459 339 l 459 320 l 439 320 l clp gs 0.00 setgray fill gr +n 439 280 m 459 280 l 459 259 l 439 259 l clp gs 0.00 setgray fill gr +n 400 280 m 420 280 l 420 259 l 400 259 l clp gs 0.00 setgray fill gr +n 359 280 m 380 280 l 380 259 l 359 259 l clp gs 0.00 setgray fill gr +n 279 280 m 299 280 l 299 259 l 279 259 l clp gs 0.00 setgray fill gr +n 279 240 m 299 240 l 299 220 l 279 220 l clp gs 0.00 setgray fill gr +/Times-Roman findfont 16.00 scalefont setfont +509 248 m +gs 1 -1 scale (6.7.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +500 304 m +gs 1 -1 scale (6.8.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +306 320 m +gs 1 -1 scale (6.2.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +434 188 m +gs 1 -1 scale (6.1.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +294 131 m +gs 1 -1 scale (6.6.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +191 216 m +gs 1 -1 scale (6.5.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +211 258 m +gs 1 -1 scale (6.3.b) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +190 308 m +gs 1 -1 scale (6.4.b) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +376 257 m +gs 1 -1 scale (CCA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +304 359 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +348 203 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +276 170 m +gs 1 -1 scale (CAA) col0 show gr +$F2psEnd +%%EndDocument + 310 988 a + endTexFig +0 2658 780 2 v 56 2688 a Fh(4)75 2704 y Fg(If)13 b(y)o(ou)h(ha)o(v)o(e)f +(di\016culties)h(with)f(half)g(lam)o(b)q(da)f(rule.)951 2828 +y Fl(14)p eop +%%Page: 15 15 +bop 0 198 a Fo(Metal1)22 b(\(CMF\))30 327 y Fn(7.1)102 b(Minim)n(um)18 +b(width)1073 b(3)30 402 y(7.2.a)55 b(Minim)n(um)18 b(spacing)1028 +b(3)30 477 y(7.2.b)157 455 y Fg(5)209 477 y Fn(Minim)n(um)18 +b(tigh)n(t)i(metal)e(spacing)718 b(2)30 551 y(7.3)102 b(Minim)n(um)18 +b(o)n(v)n(erlap)h(of)h(p)r(oly)f(con)n(tact)623 b(1)30 626 +y(7.4)102 b(Minim)n(um)18 b(o)n(v)n(erlap)h(of)h(activ)n(e)f(con)n(tact)583 +b(1)498 1180 y + 15064023 10196172 0 0 15064023 10196172 startTexFig +498 1180 a +%%BeginDocument: ciffig/metal1.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-176.0 294.0 translate 0.900 -0.900 scale +0.500 setlinewidth +n 404 174 m 391 174 l gs col0 s gr +n 399.000 176.000 m 391.000 174.000 l 399.000 172.000 l gs 2 setlinejoin col0 s gr +n 364 174 m 377 174 l gs col0 s gr +n 369.000 172.000 m 377.000 174.000 l 369.000 176.000 l gs 2 setlinejoin col0 s gr +n 222.000 199.000 m 224.000 191.000 l 226.000 199.000 l gs 2 setlinejoin col0 s gr +n 224 191 m 224 217 l gs col0 s gr +n 226.000 209.000 m 224.000 217.000 l 222.000 209.000 l gs 2 setlinejoin col0 s gr +n 417.000 239.000 m 419.000 231.000 l 421.000 239.000 l gs 2 setlinejoin col0 s gr +n 419 231 m 419 257 l gs col0 s gr +n 421.000 249.000 m 419.000 257.000 l 417.000 249.000 l gs 2 setlinejoin col0 s gr +n 274 304 m 261 304 l gs col0 s gr +n 269.000 306.000 m 261.000 304.000 l 269.000 302.000 l gs 2 setlinejoin col0 s gr +n 234 304 m 247 304 l gs col0 s gr +n 239.000 302.000 m 247.000 304.000 l 239.000 306.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 259 219 m 289 219 l 289 189 l 259 189 l clp gs 0.60 setgray fill gr +n 279 279 m 289 279 l 289 259 l 279 259 l clp gs 0.60 setgray fill gr +n 279 279 m 284 279 l 284 259 l 279 259 l clp gs 0.60 setgray fill gr +n 249 279 m 259 279 l 259 259 l 249 259 l clp gs 0.60 setgray fill gr +n 249 259 m 289 259 l 289 249 l 249 249 l clp gs 0.60 setgray fill gr +n 249 289 m 289 289 l 289 279 l 249 279 l clp gs 0.60 setgray fill gr +n 349 219 m 359 219 l 359 199 l 349 199 l clp gs 0.40 setgray fill gr +n 379 219 m 389 219 l 389 199 l 379 199 l clp gs 0.40 setgray fill gr +n 349 199 m 389 199 l 389 189 l 349 189 l clp gs 0.40 setgray fill gr +n 349 229 m 389 229 l 389 219 l 349 219 l clp gs 0.40 setgray fill gr +n 359 289 m 379 289 l 379 259 l 359 259 l clp gs 0.40 setgray fill gr +n 379 289 m 399 289 l 399 259 l 379 259 l clp gs 0.90 setgray fill gr +n 289 289 m 359 289 l 359 259 l 289 259 l clp gs 0.90 setgray fill gr +n 359 289 m 379 289 l 379 309 l 359 309 l clp gs 0.50 setgray fill gr +n 359 229 m 379 229 l 379 259 l 359 259 l clp gs 0.50 setgray fill gr +n 289 219 m 349 219 l 349 189 l 289 189 l clp gs 0.90 setgray fill gr +n 239 219 m 259 219 l 259 189 l 239 189 l clp gs 0.90 setgray fill gr +n 259 189 m 289 189 l 289 159 l 259 159 l clp gs 0.75 setgray fill gr +n 259 249 m 289 249 l 289 219 l 259 219 l clp gs 0.75 setgray fill gr +0.500 setlinewidth +n 359 219 m 379 219 l 379 199 l 359 199 l clp gs 0.00 setgray fill gr +gs col0 s gr +n 259 279 m 279 279 l 279 259 l 259 259 l clp gs 0.00 setgray fill gr +gs col0 s gr +/Times-Roman findfont 12.00 scalefont setfont +383 218 m +gs 1 -1 scale (CCP) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +232 277 m +gs 1 -1 scale (CCA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +359 325 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +262 177 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +313 279 m +gs 1 -1 scale (CMF) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +303 209 m +gs 1 -1 scale (CMF) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +242 326 m +gs 1 -1 scale (7.4) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +373 167 m +gs 1 -1 scale (7.3) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +427 252 m +gs 1 -1 scale (7.2) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +195 211 m +gs 1 -1 scale (7.1) col0 show gr +$F2psEnd +%%EndDocument + 498 1180 a + endTexFig +0 2658 780 2 v 56 2688 a Fh(5)75 2704 y Fg(Only)13 b(allo)o(w)o(ed)g(b)q(et)o +(w)o(een)i(minim)n(um)10 b(width)j(wires,)h(otherwise)h(use)g(regular)f +(spacing)g(rule.)951 2828 y Fl(15)p eop +%%Page: 16 16 +bop 0 198 a Fo(Via1)23 b(\(CV)-8 b(A\))30 327 y Fn(8.1)102 +b(Exact)19 b(size)1228 b(2)19 b Fc(\002)i Fn(2)30 402 y(8.2)102 +b(Minim)n(um)18 b(via1)g(spacing)901 b(3)30 477 y(8.3)102 b(Minim)n(um)18 +b(o)n(v)n(erlap)h(b)n(y)h(metal1)754 b(1)30 551 y(8.4)102 b(Minim)n(um)18 +b(spacing)g(to)i(con)n(tact)746 b(2)30 626 y(8.5)102 b(Minim)n(um)18 +b(spacing)g(to)i(p)r(oly)f(or)i(activ)n(e)d(edge)441 b(2)227 +1120 y + 23615652 9801483 8288501 21115944 31904153 30917427 startTexFig +227 1120 a +%%BeginDocument: ciffig/via1.ps +/$F2psDict 32 dict def $F2psDict begin $F2psDict /mtrx matrix put + end /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def +$F2psBegin +39.000000 578.000000 translate +0.900000 -0.900000 scale +newpath 349 199 moveto 359 199 lineto 359 179 lineto 349 179 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray +newpath 379 199 moveto 389 199 lineto 389 179 lineto 379 179 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray +newpath 349 179 moveto 389 179 lineto 389 169 lineto 349 169 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray +newpath 344 209 moveto 389 209 lineto 389 199 lineto 344 199 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray +newpath 259 199 moveto 269 199 lineto 269 179 lineto 259 179 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray +newpath 209 199 moveto 239 199 lineto 239 179 lineto 209 179 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray +newpath 179 199 moveto 189 199 lineto 189 179 lineto 179 179 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray +newpath 179 179 moveto 269 179 lineto 269 169 lineto 179 169 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray +newpath 179 209 moveto 269 209 lineto 269 199 lineto 179 199 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray +newpath 359 199 moveto 379 199 lineto 379 179 lineto 359 179 lineto closepath 0.20 setgray + gsave fill grestore 0.00 setgray +newpath 239 199 moveto 259 199 lineto 259 179 lineto 239 179 lineto closepath 0.20 setgray + gsave fill grestore 0.00 setgray +newpath 189 199 moveto 209 199 lineto 209 179 lineto 189 179 lineto closepath 0.20 setgray + gsave fill grestore 0.00 setgray +1.000 setlinewidth +newpath 367.000 236.000 moveto 359.000 234.000 lineto 367.000 232.000 lineto stroke +newpath 359 234 moveto 379 234 lineto stroke +newpath 371.000 232.000 moveto 379.000 234.000 lineto 371.000 236.000 lineto stroke +newpath 387.000 146.000 moveto 379.000 144.000 lineto 387.000 142.000 lineto stroke +newpath 379 144 moveto 399 144 lineto stroke +newpath 391.000 142.000 moveto 399.000 144.000 lineto 391.000 146.000 lineto stroke +newpath 217.000 266.000 moveto 209.000 264.000 lineto 217.000 262.000 lineto stroke +newpath 209 264 moveto 239 264 lineto stroke +newpath 231.000 262.000 moveto 239.000 264.000 lineto 231.000 266.000 lineto stroke +0.000 setlinewidth +newpath 269 169 moveto 349 169 lineto 349 209 lineto 269 209 lineto closepath 0.90 setgray + gsave fill grestore 0.00 setgray +newpath 159 219 moveto 289 219 lineto 289 249 lineto 159 249 lineto closepath 0.75 setgray + gsave fill grestore 0.00 setgray +newpath 159 139 moveto 289 139 lineto 289 159 lineto 159 159 lineto closepath 0.35 setgray + gsave fill grestore 0.00 setgray +1.000 setlinewidth +newpath 399 179 moveto 419 179 lineto 419 199 lineto 399 199 lineto closepath gsave fill grestore stroke +newpath 122.000 167.000 moveto 124.000 159.000 lineto 126.000 167.000 lineto stroke +newpath 124 159 moveto 124 179 lineto stroke +newpath 126.000 171.000 moveto 124.000 179.000 lineto 122.000 171.000 lineto stroke +newpath 122.000 207.000 moveto 124.000 199.000 lineto 126.000 207.000 lineto stroke +newpath 124 199 moveto 124 219 lineto stroke +newpath 126.000 211.000 moveto 124.000 219.000 lineto 122.000 211.000 lineto stroke + [4.000000] 0 setdash +newpath 139 209 moveto 269 209 lineto 269 169 lineto 139 169 lineto closepath stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 349 209 moveto 429 209 lineto 429 169 lineto 349 169 lineto closepath stroke + [] 0 setdash +newpath 459 224 moveto 459 211 lineto stroke +newpath 457.000 219.000 moveto 459.000 211.000 lineto 461.000 219.000 lineto stroke +newpath 459 184 moveto 459 197 lineto stroke +newpath 461.000 189.000 moveto 459.000 197.000 lineto 457.000 189.000 lineto stroke +newpath 339 159 moveto 439 159 lineto 439 219 lineto 339 219 lineto closepath stroke +/fn0.15 /Times-Roman findfont 16.666667 scalefont def +fn0.15 setfont +(8.5) 96 215 moveto 1 -1 scale show 1 -1 scale +(8.5) 96 177 moveto 1 -1 scale show 1 -1 scale +/fn0.12 /Times-Roman findfont 13.333333 scalefont def +fn0.12 setfont +(CAA) 439 154 moveto 1 -1 scale show 1 -1 scale +(CVA) 325 182 moveto 1 -1 scale show 1 -1 scale +(CCA) 402 212 moveto 1 -1 scale show 1 -1 scale +(CVA) 213 184 moveto 1 -1 scale show 1 -1 scale +(CMS) 293 203 moveto 1 -1 scale show 1 -1 scale +(CMF) 144 205 moveto 1 -1 scale show 1 -1 scale +(CAA) 212 238 moveto 1 -1 scale show 1 -1 scale +(CPG) 214 132 moveto 1 -1 scale show 1 -1 scale +fn0.15 setfont +(8.4) 378 134 moveto 1 -1 scale show 1 -1 scale +(8.3) 473 210 moveto 1 -1 scale show 1 -1 scale +(8.2) 214 286 moveto 1 -1 scale show 1 -1 scale +(8.1) 359 257 moveto 1 -1 scale show 1 -1 scale +showpage +$F2psEnd +%%EndDocument + 227 1120 a + endTexFig +951 2828 a Fl(16)p eop +%%Page: 17 17 +bop 0 198 a Fo(Metal2)22 b(\(CMS\))30 327 y Fn(9.1)102 b(Minim)n(um)18 +b(width)1073 b(3)30 402 y(9.2.a)55 b(Minim)n(um)18 b(spacing)1028 +b(4)30 477 y(9.2.b)157 455 y Fg(6)209 477 y Fn(Minim)n(um)18 +b(tigh)n(t)i(metal)e(spacing)718 b(3)30 551 y(9.3)102 b(Minim)n(um)18 +b(o)n(v)n(erlap)h(of)h(via1)838 b(1)515 1226 y + 14537768 8880537 0 0 14537768 8880537 startTexFig +515 1226 a +%%BeginDocument: ciffig/metal2.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-162.0 324.0 translate 0.900 -0.900 scale +n 319 289 m 339 289 l 339 279 l 319 279 l clp gs 0.80 setgray fill gr +n 319 319 m 339 319 l 339 309 l 319 309 l clp gs 0.80 setgray fill gr +n 339 319 m 349 319 l 349 279 l 339 279 l clp gs 0.80 setgray fill gr +n 309 319 m 319 319 l 319 279 l 309 279 l clp gs 0.80 setgray fill gr +n 319 309 m 339 309 l 339 289 l 319 289 l clp gs 0.20 setgray fill gr +0.500 setlinewidth +n 394 294 m 394 307 l gs col0 s gr +n 396.000 299.000 m 394.000 307.000 l 392.000 299.000 l gs 2 setlinejoin col0 s gr +n 394 334 m 394 321 l gs col0 s gr +n 392.000 329.000 m 394.000 321.000 l 396.000 329.000 l gs 2 setlinejoin col0 s gr +n 392.000 219.000 m 394.000 211.000 l 396.000 219.000 l gs 2 setlinejoin col0 s gr +n 394 211 m 394 237 l gs col0 s gr +n 396.000 229.000 m 394.000 237.000 l 392.000 229.000 l gs 2 setlinejoin col0 s gr +n 222.000 249.000 m 224.000 241.000 l 226.000 249.000 l gs 2 setlinejoin col0 s gr +n 224 241 m 224 277 l gs col0 s gr +n 226.000 269.000 m 224.000 277.000 l 222.000 269.000 l gs 2 setlinejoin col0 s gr + [4.000000] 0 setdash +n 309 279 m 349 279 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 349 359 m 349 279 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 319 359 m 349 359 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 319 319 m 319 359 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 309 319 m 319 319 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 309 279 m 309 319 l gs col0 s gr + [] 0 setdash +0.000 setlinewidth + 1 setlinecap [1 3.000000] 3.000000 setdash +n 349 309 m 379 309 l 379 279 l 349 279 l clp gs 0.80 setgray fill gr + [] 0 setdash 0 setlinecap +n 239 279 m 309 279 l 309 309 l 239 309 l clp gs 0.80 setgray fill gr +n 239 239 m 379 239 l 379 209 l 239 209 l clp gs 0.80 setgray fill gr +/Times-Roman findfont 16.00 scalefont setfont +179 257 m +gs 1 -1 scale (9.2.a) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +179 275 m +gs 1 -1 scale (9.2.b) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +260 301 m +gs 1 -1 scale (CMS) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +334 285 m +gs 1 -1 scale (CVA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +259 233 m +gs 1 -1 scale (CMS) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +322 354 m +gs 1 -1 scale (CMF) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +403 323 m +gs 1 -1 scale (9.3) col0 show gr +/Times-Roman findfont 16.00 scalefont setfont +403 230 m +gs 1 -1 scale (9.1) col0 show gr +$F2psEnd +%%EndDocument + 515 1226 a + endTexFig +0 2658 780 2 v 56 2688 a Fh(6)75 2704 y Fg(Only)13 b(allo)o(w)o(ed)g(b)q(et)o +(w)o(een)i(minim)n(um)10 b(width)j(wires,)h(otherwise)h(use)g(regular)f +(spacing)g(rule.)951 2828 y Fl(17)p eop +%%Page: 18 18 +bop 0 202 a Fo(Ov)n(erglass)287 180 y Fg(7)333 202 y Fo(\(COG\))1706 +318 y Fb(\026)p Fn(m)30 393 y(10.1)72 b(Minim)n(um)18 b(b)r(onding)h(pad)i +(width)636 b(100)20 b Fc(\002)g Fn(100)30 468 y(10.2)72 b(Minim)n(um)18 +b(prob)r(e)h(pad)i(width)731 b(75)20 b Fc(\002)g Fn(75)30 542 +y(10.3)72 b(P)n(ad)20 b(o)n(v)n(erlap)g(of)g(glass)f(op)r(ening)778 +b(6)30 617 y(10.4)72 b(Minim)n(um)18 b(pad)i(spacing)f(to)h(unrelated)g +(metal2)1328 595 y Fg(8)1714 617 y Fn(30)30 692 y(10.5)72 b(Minim)n(um)18 +b(pad)i(spacing)f(to)h(unrelated)g(metal1,)d(p)r(oly)-5 b(,)209 +767 y(electro)r(de)18 b(or)j(activ)n(e)1023 b(15)331 1173 y + 20326563 14471987 0 0 20326563 14471987 startTexFig +331 1173 a +%%BeginDocument: ciffig/glass.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-123.0 306.0 translate 0.900 -0.900 scale +0.500 setlinewidth +n 227.000 116.000 m 219.000 114.000 l 227.000 112.000 l gs 2 setlinejoin col0 s gr +n 219 114 m 359 114 l gs col0 s gr +n 351.000 112.000 m 359.000 114.000 l 351.000 116.000 l gs 2 setlinejoin col0 s gr +n 172.000 139.000 m 174.000 131.000 l 176.000 139.000 l gs 2 setlinejoin col0 s gr +n 174 131 m 174 157 l gs col0 s gr +n 176.000 149.000 m 174.000 157.000 l 172.000 149.000 l gs 2 setlinejoin col0 s gr +n 399.000 341.000 m 391.000 339.000 l 399.000 337.000 l gs 2 setlinejoin col0 s gr +n 391 339 m 427 339 l gs col0 s gr +n 419.000 337.000 m 427.000 339.000 l 419.000 341.000 l gs 2 setlinejoin col0 s gr +n 399.000 231.000 m 391.000 229.000 l 399.000 227.000 l gs 2 setlinejoin col0 s gr +n 391 229 m 437 229 l gs col0 s gr +n 429.000 227.000 m 437.000 229.000 l 429.000 231.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 220 161 m 360 298 l % Polyline +n 219 299 m 359 299 l 359 159 l 219 159 l clp gs 0.40 setgray fill gr +n 429 259 m 479 259 l 479 329 l 429 329 l clp gs 0.95 setgray fill gr +n 439 129 m 479 129 l 479 219 l 439 219 l clp gs 0.85 setgray fill gr +n 359 329 m 389 329 l 389 129 l 359 129 l clp gs 0.85 setgray fill gr +n 219 329 m 359 329 l 359 299 l 219 299 l clp gs 0.85 setgray fill gr +n 219 159 m 359 159 l 359 129 l 219 129 l clp gs 0.85 setgray fill gr +n 189 129 m 219 129 l 219 329 l 189 329 l clp gs 0.85 setgray fill gr +0.500 setlinewidth +n 219 159 m 359 159 l 359 299 l 219 299 l clp gs col0 s gr +/Times-Roman findfont 12.00 scalefont setfont +352 322 m +gs 1 -1 scale (CMS) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +447 323 m +gs 1 -1 scale (CMF) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +448 210 m +gs 1 -1 scale (CMS) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +228 294 m +gs 1 -1 scale (COG) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +394 331 m +gs 1 -1 scale (10.5) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +401 221 m +gs 1 -1 scale (10.4) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +136 151 m +gs 1 -1 scale (10.3) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +291 108 m +gs 1 -1 scale (10.2) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +255 108 m +gs 1 -1 scale (10.1) col0 show gr +$F2psEnd +%%EndDocument + 331 1173 a + endTexFig +0 2608 780 2 v 56 2639 a Fh(7)75 2654 y Fg(Rules)14 b(in)f(this)h(section)h +(are)f(in)f(unit)h(of)f Fa(\026)p Fg(m.)56 2688 y Fh(8)75 2704 +y Fg(And)h(metal3)e(if)h(triple)h(metal)e(used.)951 2828 y +Fl(18)p eop +%%Page: 19 19 +bop 0 198 a Fo(Electro)r(de)21 b(for)j(Capacitor)e(\(CEL)h(-)g(Analog)g +(Option\))30 327 y Fn(11.1)72 b(Minim)n(um)18 b(width)1073 +b(3)30 402 y(11.2)72 b(Minim)n(um)18 b(spacing)1028 b(3)30 +477 y(11.3)72 b(Minim)n(um)18 b(p)r(oly)g(o)n(v)n(erlap)902 +b(2)30 551 y(11.4)72 b(Minim)n(um)18 b(spacing)g(to)i(activ)n(e)f(or)h(w)n +(ell)g(edge)452 b(2)30 626 y(11.5)72 b(Minim)n(um)18 b(spacing)g(to)i(p)r +(oly)f(con)n(tact)613 b(3)256 1225 y + 22694707 11182899 0 0 22694707 11182899 startTexFig +256 1225 a +%%BeginDocument: ciffig/el.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-60.0 256.0 translate 0.900 -0.900 scale +n 119 249 m 389 249 l 389 129 l 119 129 l clp gs 0.85 setgray fill gr +n 249 229 m 329 229 l 329 149 l 249 149 l clp gs 0.70 setgray fill gr +n 139 229 m 219 229 l 219 149 l 139 149 l clp gs 0.70 setgray fill gr +0.500 setlinewidth +n 104 164 m 104 151 l gs col0 s gr +n 102.000 159.000 m 104.000 151.000 l 106.000 159.000 l gs 2 setlinejoin col0 s gr +n 364 264 m 351 264 l gs col0 s gr +n 359.000 266.000 m 351.000 264.000 l 359.000 262.000 l gs 2 setlinejoin col0 s gr +n 314 264 m 327 264 l gs col0 s gr +n 319.000 262.000 m 327.000 264.000 l 319.000 266.000 l gs 2 setlinejoin col0 s gr +n 104 114 m 104 127 l gs col0 s gr +n 106.000 119.000 m 104.000 127.000 l 102.000 119.000 l gs 2 setlinejoin col0 s gr + 1 setlinecap [1 3.000000] 3.000000 setdash +n 349 249 m 429 249 l 429 129 l 349 129 l clp gs col0 s gr + [] 0 setdash 0 setlinecap +n 229.000 116.000 m 221.000 114.000 l 229.000 112.000 l gs 2 setlinejoin col0 s gr +n 221 114 m 247 114 l gs col0 s gr +n 239.000 112.000 m 247.000 114.000 l 239.000 116.000 l gs 2 setlinejoin col0 s gr +n 339.000 116.000 m 331.000 114.000 l 339.000 112.000 l gs 2 setlinejoin col0 s gr +n 331 114 m 357 114 l gs col0 s gr +n 349.000 112.000 m 357.000 114.000 l 349.000 116.000 l gs 2 setlinejoin col0 s gr +n 149.000 266.000 m 141.000 264.000 l 149.000 262.000 l gs 2 setlinejoin col0 s gr +n 141 264 m 217 264 l gs col0 s gr +n 209.000 262.000 m 217.000 264.000 l 209.000 266.000 l gs 2 setlinejoin col0 s gr + [4.000000] 0 setdash +n 159 209 m 309 209 l 309 169 l 159 169 l clp gs col0 s gr + [] 0 setdash +0.000 setlinewidth + [4.000000] 0 setdash +n 169 199 m 189 199 l 189 179 l 169 179 l clp gs 0.00 setgray fill gr + [] 0 setdash +0.500 setlinewidth + [4.000000] 0 setdash +n 349 169 m 449 169 l 449 209 l 349 209 l clp gs col0 s gr + [] 0 setdash +n 359 199 m 379 199 l 379 179 l 359 179 l clp gs 0.00 setgray fill gr +gs col0 s gr +n 279 199 m 299 199 l 299 179 l 279 179 l clp gs 0.00 setgray fill gr +gs col0 s gr +/Times-Roman findfont 12.00 scalefont setfont +256 162 m +gs 1 -1 scale (CEL) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +418 185 m +gs 1 -1 scale (CMF) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +396 243 m +gs 1 -1 scale (CWN) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +270 246 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +144 162 m +gs 1 -1 scale (CEL) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +328 109 m +gs 1 -1 scale (11.5) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +323 284 m +gs 1 -1 scale (11.4) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +66 146 m +gs 1 -1 scale (11.3) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +219 108 m +gs 1 -1 scale (11.2) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +162 284 m +gs 1 -1 scale (11.1) col0 show gr +$F2psEnd +%%EndDocument + 256 1225 a + endTexFig +951 2828 a Fl(19)p eop +%%Page: 20 20 +bop 0 198 a Fo(Electro)r(de)21 b(for)j(T)-6 b(ransistor)24 +b(\(CEL)e(-)h(Analog)g(Option\))30 327 y Fn(12.1)72 b(Minim)n(um)18 +b(width)1073 b(2)30 402 y(12.2)72 b(Minim)n(um)18 b(spacing)1028 +b(3)30 477 y(12.3)72 b(Minim)n(um)18 b(electro)r(de)g(gate)h(o)n(v)n(erlap)h +(of)g(activ)n(e)409 b(2)30 551 y(12.4)72 b(Minim)n(um)18 b(spacing)g(to)i +(activ)n(e)783 b(1)30 626 y(12.5)72 b(Minim)n(um)18 b(spacing)g(or)j(o)n(v)n +(erlap)e(of)h(p)r(oly)547 b(2)30 701 y(12.6)72 b(Minim)n(um)18 +b(spacing)g(to)i(p)r(oly)f(or)i(activ)n(e)d(con)n(tact)367 +b(3)417 1180 y + 17629512 14143079 11314462 18945146 28943974 33088225 startTexFig +417 1180 a +%%BeginDocument: ciffig/el2.ps +/$F2psDict 32 dict def $F2psDict begin $F2psDict /mtrx matrix put + end /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def +$F2psBegin +-20.000000 678.000000 translate +0.900000 -0.900000 scale +1.000 setlinewidth +newpath 472.000 347.000 moveto 474.000 339.000 lineto 476.000 347.000 lineto stroke +newpath 474 339 moveto 474 369 lineto stroke +newpath 476.000 361.000 moveto 474.000 369.000 lineto 472.000 361.000 lineto stroke +newpath 414 414 moveto 399 414 lineto stroke +newpath 407.000 416.000 moveto 399.000 414.000 lineto 407.000 412.000 lineto stroke +newpath 374 414 moveto 389 414 lineto stroke +newpath 381.000 412.000 moveto 389.000 414.000 lineto 381.000 416.000 lineto stroke +newpath 344 334 moveto 344 319 lineto stroke +newpath 342.000 327.000 moveto 344.000 319.000 lineto 346.000 327.000 lineto stroke +newpath 344 284 moveto 344 299 lineto stroke +newpath 346.000 291.000 moveto 344.000 299.000 lineto 342.000 291.000 lineto stroke +newpath 457.000 266.000 moveto 449.000 264.000 lineto 457.000 262.000 lineto stroke +newpath 449 264 moveto 479 264 lineto stroke +newpath 471.000 262.000 moveto 479.000 264.000 lineto 471.000 266.000 lineto stroke +newpath 414 214 moveto 429 214 lineto stroke +newpath 421.000 212.000 moveto 429.000 214.000 lineto 421.000 216.000 lineto stroke +newpath 447.000 216.000 moveto 439.000 214.000 lineto 447.000 212.000 lineto stroke +newpath 439 214 moveto 454 214 lineto stroke +newpath 267.000 246.000 moveto 259.000 244.000 lineto 267.000 242.000 lineto stroke +newpath 259 244 moveto 274 244 lineto stroke +newpath 224 244 moveto 239 244 lineto stroke +newpath 231.000 242.000 moveto 239.000 244.000 lineto 231.000 246.000 lineto stroke +newpath 267.000 396.000 moveto 259.000 394.000 lineto 267.000 392.000 lineto stroke +newpath 259 394 moveto 289 394 lineto stroke +newpath 281.000 392.000 moveto 289.000 394.000 lineto 281.000 396.000 lineto stroke +0.000 setlinewidth + [4.000000] 0 setdash +newpath 399 279 moveto 429 279 lineto 429 319 lineto 399 319 lineto closepath 0.50 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 379 279 moveto 399 279 lineto 399 319 lineto 379 319 lineto closepath 0.70 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 499 289 moveto 509 289 lineto 509 309 lineto 499 309 lineto closepath 0.70 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 479 279 moveto 509 279 lineto 509 289 lineto 479 289 lineto closepath 0.70 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 479 319 moveto 509 319 lineto 509 309 lineto 479 309 lineto closepath 0.70 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 429 319 moveto 479 319 lineto 479 279 lineto 429 279 lineto closepath 0.70 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 449 369 moveto 459 369 lineto 459 389 lineto 449 389 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 429 389 moveto 459 389 lineto 459 399 lineto 429 399 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 429 359 moveto 459 359 lineto 459 369 lineto 429 369 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 399 319 moveto 429 319 lineto 429 399 lineto 399 399 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 399 269 moveto 429 269 lineto 429 279 lineto 399 279 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 399 239 moveto 409 239 lineto 409 259 lineto 399 259 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 429 239 moveto 439 239 lineto 439 259 lineto 429 259 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 399 229 moveto 439 229 lineto 439 239 lineto 399 239 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 399 259 moveto 439 259 lineto 439 269 lineto 399 269 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 409 239 moveto 429 239 lineto 429 259 lineto 409 259 lineto closepath gsave fill grestore [] 0 setdash + [4.000000] 0 setdash +newpath 429 369 moveto 449 369 lineto 449 389 lineto 429 389 lineto closepath gsave fill grestore [] 0 setdash + [4.000000] 0 setdash +newpath 479 289 moveto 499 289 lineto 499 309 lineto 479 309 lineto closepath gsave fill grestore [] 0 setdash +1.000 setlinewidth + [4.000000] 0 setdash +newpath 359 299 moveto 449 299 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 449 339 moveto 449 299 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 389 339 moveto 449 339 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 359 299 moveto 359 339 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 289 339 moveto 359 339 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 389 379 moveto 389 339 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 289 379 moveto 389 379 lineto stroke + [] 0 setdash +0.000 setlinewidth + [4.000000] 0 setdash +newpath 349 349 moveto 369 349 lineto 369 369 lineto 349 369 lineto closepath gsave fill grestore [] 0 setdash + [4.000000] 0 setdash +newpath 309 349 moveto 329 349 lineto 329 369 lineto 309 369 lineto closepath gsave fill grestore [] 0 setdash +1.000 setlinewidth + [4.000000] 0 setdash +newpath 289 339 moveto 289 379 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 259 259 moveto 239 259 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 259 379 moveto 259 259 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 239 379 moveto 259 379 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 239 259 moveto 239 379 lineto stroke + [] 0 setdash +/fn0.12 /Times-Roman findfont 13.333333 scalefont def +fn0.12 setfont +(CEL) 213 375 moveto 1 -1 scale show 1 -1 scale +/fn0.15 /Times-Roman findfont 16.666667 scalefont def +fn0.15 setfont +(12.6) 480 359 moveto 1 -1 scale show 1 -1 scale +(12.6) 449 259 moveto 1 -1 scale show 1 -1 scale +fn0.12 setfont +(CCA) 430 238 moveto 1 -1 scale show 1 -1 scale +(CCE) 295 347 moveto 1 -1 scale show 1 -1 scale +fn0.15 setfont +(12.2) 259 414 moveto 1 -1 scale show 1 -1 scale +(12.5) 308 315 moveto 1 -1 scale show 1 -1 scale +(12.4) 377 434 moveto 1 -1 scale show 1 -1 scale +(12.3) 419 209 moveto 1 -1 scale show 1 -1 scale +(12.1) 235 238 moveto 1 -1 scale show 1 -1 scale +fn0.12 setfont +(CAA) 403 361 moveto 1 -1 scale show 1 -1 scale +(CPG) 440 294 moveto 1 -1 scale show 1 -1 scale +(CEL) 366 334 moveto 1 -1 scale show 1 -1 scale +showpage +$F2psEnd +%%EndDocument + 417 1180 a + endTexFig +951 2828 a Fl(20)p eop +%%Page: 21 21 +bop 0 198 a Fo(Electro)r(de)21 b(Con)n(tact)i(\(CCE)f(-)h(Analog)g(Option\)) +30 327 y Fn(13.1)72 b(Exact)19 b(con)n(tact)h(size)1017 b(2)19 +b Fc(\002)i Fn(2)30 402 y(13.2)72 b(Minim)n(um)18 b(con)n(tact)h(spacing)818 +b(2)30 477 y(13.3)72 b(Minim)n(um)18 b(electro)r(de)g(o)n(v)n(erlap)h(\(on)i +(capacitor\))391 b(3)30 551 y(13.4)72 b(Minim)n(um)18 b(electro)r(de)g(o)n(v) +n(erlap)h(\(not)i(on)f(capacitor\))285 b(2)30 626 y(13.5)72 +b(Minim)n(um)18 b(spacing)g(to)i(p)r(oly)f(or)i(activ)n(e)576 +b(3)563 1015 y + 13024788 18418892 0 0 13024788 18418892 startTexFig +563 1015 a +%%BeginDocument: ciffig/ec.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-162.0 349.0 translate 0.900 -0.900 scale +n 229 129 m 349 129 l 349 249 l 229 249 l clp gs 0.90 setgray fill gr +n 309 149 m 324 149 l 324 229 l 309 229 l clp gs 0.75 setgray fill gr +n 249 149 m 309 149 l 309 339 l 249 339 l clp gs 0.75 setgray fill gr +0.500 setlinewidth +n 297.000 366.000 m 289.000 364.000 l 297.000 362.000 l gs 2 setlinejoin col0 s gr +n 289 364 m 319 364 l gs 0.85 setgray fill gr +gs col0 s gr +n 311.000 362.000 m 319.000 364.000 l 311.000 366.000 l gs 2 setlinejoin col0 s gr +n 247.000 366.000 m 239.000 364.000 l 247.000 362.000 l gs 2 setlinejoin col0 s gr +n 239 364 m 269 364 l gs 0.85 setgray fill gr +gs col0 s gr +n 261.000 362.000 m 269.000 364.000 l 261.000 366.000 l gs 2 setlinejoin col0 s gr +n 284 94 m 271 94 l gs col0 s gr +n 279.000 96.000 m 271.000 94.000 l 279.000 92.000 l gs 2 setlinejoin col0 s gr +n 234 94 m 247 94 l gs col0 s gr +n 239.000 92.000 m 247.000 94.000 l 239.000 96.000 l gs 2 setlinejoin col0 s gr +n 364 314 m 364 301 l gs col0 s gr +n 362.000 309.000 m 364.000 301.000 l 366.000 309.000 l gs 2 setlinejoin col0 s gr +n 364 264 m 364 277 l gs col0 s gr +n 366.000 269.000 m 364.000 277.000 l 362.000 269.000 l gs 2 setlinejoin col0 s gr +n 364 214 m 364 201 l gs col0 s gr +n 362.000 209.000 m 364.000 201.000 l 366.000 209.000 l gs 2 setlinejoin col0 s gr +n 364 164 m 364 177 l gs col0 s gr +n 366.000 169.000 m 364.000 177.000 l 362.000 169.000 l gs 2 setlinejoin col0 s gr +n 214 194 m 214 181 l gs col0 s gr +n 212.000 189.000 m 214.000 181.000 l 216.000 189.000 l gs 2 setlinejoin col0 s gr +n 214 134 m 214 147 l gs col0 s gr +n 216.000 139.000 m 214.000 147.000 l 212.000 139.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 319 279 m 339 279 l 339 339 l 319 339 l clp gs 0.50 setgray fill gr +n 199 279 m 239 279 l 239 339 l 199 339 l clp gs 0.75 setgray fill gr +0.500 setlinewidth + [4.000000] 0 setdash +n 259 109 m 309 109 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 309 174 m 309 109 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 309 209 m 309 169 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 299 209 m 309 209 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 299 349 m 299 209 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 259 349 m 299 349 l gs col0 s gr + [] 0 setdash + [4.000000] 0 setdash +n 259 349 m 259 109 l gs col0 s gr + [] 0 setdash +0.000 setlinewidth +n 269 319 m 289 319 l 289 299 l 269 299 l clp gs 0.00 setgray fill gr +n 269 279 m 289 279 l 289 259 l 269 259 l clp gs 0.00 setgray fill gr +0.500 setlinewidth +n 279 199 m 299 199 l 299 179 l 279 179 l clp gs 0.00 setgray fill gr +gs col0 s gr +/Times-Roman findfont 15.00 scalefont setfont +238 387 m +gs 1 -1 scale (13.5) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +344 333 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +207 333 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +289 386 m +gs 1 -1 scale (13.5) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +243 89 m +gs 1 -1 scale (13.4) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +179 172 m +gs 1 -1 scale (13.3) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +369 295 m +gs 1 -1 scale (13.2) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +367 196 m +gs 1 -1 scale (13.1) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +272 125 m +gs 1 -1 scale (CMF) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +280 171 m +gs 1 -1 scale (CEL) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +321 144 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +269 333 m +gs 1 -1 scale (CEL) col0 show gr +$F2psEnd +%%EndDocument + 563 1015 a + endTexFig +951 2828 a Fl(21)p eop +%%Page: 22 22 +bop 0 198 a Fo(Via2)23 b(\(CVS)f(-)h(T)-6 b(riple)21 b(Metal)h(Option\))30 +327 y Fn(14.1)72 b(Exact)19 b(size)1228 b(2)19 b Fc(\002)i +Fn(2)30 402 y(14.2)72 b(Minim)n(um)18 b(spacing)1028 b(3)30 +477 y(14.3)72 b(Minim)n(um)18 b(o)n(v)n(erlap)h(b)n(y)h(metal2)754 +b(1)30 551 y(14.4)72 b(Minim)n(um)18 b(spacing)g(to)i(via1)828 +b(2)392 1136 y + 18418892 10985553 0 0 18418892 10985553 startTexFig +392 1136 a +%%BeginDocument: ciffig/via2.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-135.0 225.0 translate 0.900 -0.900 scale +0.500 setlinewidth +n 249.000 176.000 m 241.000 174.000 l 249.000 172.000 l gs 2 setlinejoin col0 s gr +n 241 174 m 267 174 l gs col0 s gr +n 259.000 172.000 m 267.000 174.000 l 259.000 176.000 l gs 2 setlinejoin col0 s gr +n 254 84 m 241 84 l gs col0 s gr +n 249.000 86.000 m 241.000 84.000 l 249.000 82.000 l gs 2 setlinejoin col0 s gr +n 374 84 m 361 84 l gs col0 s gr +n 369.000 86.000 m 361.000 84.000 l 369.000 82.000 l gs 2 setlinejoin col0 s gr +n 424 134 m 424 121 l gs col0 s gr +n 422.000 129.000 m 424.000 121.000 l 426.000 129.000 l gs 2 setlinejoin col0 s gr +n 424 94 m 424 107 l gs col0 s gr +n 426.000 99.000 m 424.000 107.000 l 422.000 99.000 l gs 2 setlinejoin col0 s gr +n 324 84 m 337 84 l gs col0 s gr +n 329.000 82.000 m 337.000 84.000 l 329.000 86.000 l gs 2 setlinejoin col0 s gr +n 204 84 m 217 84 l gs col0 s gr +n 209.000 82.000 m 217.000 84.000 l 209.000 86.000 l gs 2 setlinejoin col0 s gr +n 184 104 m 184 117 l gs col0 s gr +n 186.000 109.000 m 184.000 117.000 l 182.000 109.000 l gs 2 setlinejoin col0 s gr +n 184 154 m 184 141 l gs col0 s gr +n 182.000 149.000 m 184.000 141.000 l 186.000 149.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 209 109 m 349 109 l 349 149 l 209 149 l clp gs 0.90 setgray fill gr +0.500 setlinewidth +n 199 99 m 409 99 l 409 159 l 199 159 l clp gs col0 s gr +0.000 setlinewidth +n 349 109 m 389 109 l 389 249 l 349 249 l clp gs 0.90 setgray fill gr +0.500 setlinewidth +n 359 219 m 379 219 l 379 239 l 359 239 l clp gs 0.00 setgray fill gr +gs col0 s gr +n 359 169 m 379 169 l 379 189 l 359 189 l clp gs 0.00 setgray fill gr +gs col0 s gr +n 359 119 m 379 119 l 379 139 l 359 139 l clp gs 0.00 setgray fill gr +gs col0 s gr +n 319 119 m 339 119 l 339 139 l 319 139 l clp gs 0.30 setgray fill gr +gs col0 s gr +n 269 119 m 289 119 l 289 139 l 269 139 l clp gs 0.30 setgray fill gr +gs col0 s gr +n 219 119 m 239 119 l 239 139 l 219 139 l clp gs 0.30 setgray fill gr +gs col0 s gr +/Times-Roman findfont 12.00 scalefont setfont +384 133 m +gs 1 -1 scale (CVA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +268 114 m +gs 1 -1 scale (CVS) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +386 184 m +gs 1 -1 scale (CVA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +356 210 m +gs 1 -1 scale (CMS) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +199 175 m +gs 1 -1 scale (CMT) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +430 120 m +gs 1 -1 scale (14.3) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +331 78 m +gs 1 -1 scale (14.4) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +213 77 m +gs 1 -1 scale (14.1) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +150 136 m +gs 1 -1 scale (14.1) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +239 195 m +gs 1 -1 scale (14.2) col0 show gr +$F2psEnd +%%EndDocument + 392 1136 a + endTexFig +951 2828 a Fl(22)p eop +%%Page: 23 23 +bop 0 198 a Fo(Metal3)22 b(\(CMT)h(-)f(T)-6 b(riple)22 b(Metal)g(Option\))30 +327 y Fn(15.1)72 b(Minim)n(um)18 b(width)1073 b(6)30 402 y(15.2)72 +b(Minim)n(um)18 b(spacing)g(to)i(metal3)759 b(4)30 477 y(15.3)72 +b(Minim)n(um)18 b(o)n(v)n(erlap)h(of)h(via2)838 b(2)475 1136 +y + 15787622 10327736 0 0 15787622 10327736 startTexFig +475 1136 a +%%BeginDocument: ciffig/metal3.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-133.0 319.0 translate 0.900 -0.900 scale +0.500 setlinewidth +n 182.000 249.000 m 184.000 241.000 l 186.000 249.000 l gs 2 setlinejoin col0 s gr +n 184 241 m 184 277 l gs col0 s gr +n 186.000 269.000 m 184.000 277.000 l 182.000 269.000 l gs 2 setlinejoin col0 s gr +n 374 354 m 374 341 l gs col0 s gr +n 372.000 349.000 m 374.000 341.000 l 376.000 349.000 l gs 2 setlinejoin col0 s gr +n 374 304 m 374 317 l gs col0 s gr +n 376.000 309.000 m 374.000 317.000 l 372.000 309.000 l gs 2 setlinejoin col0 s gr +n 372.000 189.000 m 374.000 181.000 l 376.000 189.000 l gs 2 setlinejoin col0 s gr +n 374 181 m 374 237 l gs col0 s gr +n 376.000 229.000 m 374.000 237.000 l 372.000 229.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 299 319 m 319 319 l 319 299 l 299 299 l clp gs 0.20 setgray fill gr +0.500 setlinewidth +n 199 239 m 359 239 l 359 179 l 199 179 l clp gs col0 s gr +n 199 339 m 359 339 l 359 279 l 199 279 l clp gs col0 s gr +/Times-Roman findfont 15.00 scalefont setfont +382 216 m +gs 1 -1 scale (15.1) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +383 337 m +gs 1 -1 scale (15.3) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +147 266 m +gs 1 -1 scale (15.2) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +206 234 m +gs 1 -1 scale (CMT) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +324 318 m +gs 1 -1 scale (CVS) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +206 333 m +gs 1 -1 scale (CMT) col0 show gr +$F2psEnd +%%EndDocument + 475 1136 a + endTexFig +951 2828 a Fl(23)p eop +%%Page: 24 24 +bop 0 198 a Fo(NPN)23 b(Bip)r(olar)f(T)-6 b(ransistor)23 b(\(CBA)g(-)f +(Analog)i(Option\))30 327 y Fn(16.1)72 b(All)19 b(activ)n(e)g(con)n(tact)1033 +b(2)19 b Fc(\002)i Fn(2)30 402 y(16.2)72 b(Minim)n(um)18 b(select)g(o)n(v)n +(erlap)h(of)h(emitter)f(con)n(tact)383 b(3)30 477 y(16.3)72 +b(Minim)n(um)18 b(pbase)h(o)n(v)n(erlap)h(of)g(emitter)e(select)426 +b(2)30 551 y(16.4)72 b(Minim)n(um)18 b(spacing)g(b)r(et)n(w)n(een)i(emitter)f +(select)f(and)i(base)f(select)12 b(4)30 626 y(16.5)72 b(Minim)n(um)18 +b(pbase)h(o)n(v)n(erlap)h(of)g(base)f(select)502 b(2)30 701 +y(16.6)72 b(Minim)n(um)18 b(select)g(o)n(v)n(erlap)h(of)h(base)g(con)n(tact) +459 b(2)30 775 y(16.7)72 b(Minim)n(um)18 b(n)n(w)n(ell)h(o)n(v)n(erlap)h(of)g +(pbase)647 b(6)30 850 y(16.8)72 b(Minim)n(um)18 b(spacing)g(b)r(et)n(w)n(een) +i(pbase)g(and)g(collector)e(activ)n(e)103 b(4)30 925 y(16.9)72 +b(Minim)n(um)18 b(activ)n(e)g(o)n(v)n(erlap)i(of)g(collector)e(con)n(tact)344 +b(2)30 1000 y(16.10)42 b(Minim)n(um)18 b(n)n(w)n(ell)h(o)n(v)n(erlap)h(of)g +(collector)e(activ)n(e)401 b(3)30 1074 y(16.11)42 b(Minim)n(um)18 +b(select)g(o)n(v)n(erlap)h(of)h(collector)f(activ)n(e)390 b(2)177 +1284 y + 25194414 18484675 7499120 16774348 32693534 35259023 startTexFig +177 1284 a +%%BeginDocument: ciffig/npn3.ps +/$F2psDict 32 dict def $F2psDict begin $F2psDict /mtrx matrix put + end /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def +$F2psBegin +-25.000000 602.000000 translate +0.900000 -0.900000 scale +1.000 setlinewidth +newpath 164 364 moveto 179 364 lineto stroke +newpath 171.000 362.000 moveto 179.000 364.000 lineto 171.000 366.000 lineto stroke +newpath 207.000 366.000 moveto 199.000 364.000 lineto 207.000 362.000 lineto stroke +newpath 199 364 moveto 214 364 lineto stroke +newpath 267.000 156.000 moveto 259.000 154.000 lineto 267.000 152.000 lineto stroke +newpath 259 154 moveto 274 154 lineto stroke +newpath 484 154 moveto 499 154 lineto stroke +newpath 491.000 152.000 moveto 499.000 154.000 lineto 491.000 156.000 lineto stroke +newpath 527.000 156.000 moveto 519.000 154.000 lineto 527.000 152.000 lineto stroke +newpath 519 154 moveto 534 154 lineto stroke +newpath 527.000 366.000 moveto 519.000 364.000 lineto 527.000 362.000 lineto stroke +newpath 519 364 moveto 579 364 lineto stroke +newpath 571.000 362.000 moveto 579.000 364.000 lineto 571.000 366.000 lineto stroke + [4.000000] 0 setdash +newpath 169 109 moveto 579 109 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 169 349 moveto 579 349 lineto stroke + [] 0 setdash +2.000 setlinewidth +newpath 299 169 moveto 299 289 lineto stroke +newpath 519 169 moveto 299 169 lineto stroke +newpath 519 289 moveto 519 169 lineto stroke +newpath 299 289 moveto 519 289 lineto stroke +0.000 setlinewidth + [1 3.000000] 0 setdash +newpath 179 279 moveto 279 279 lineto 279 179 lineto 179 179 lineto closepath 0.75 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash +newpath 479 259 moveto 499 259 lineto 499 199 lineto 479 199 lineto closepath 0.75 setgray + gsave fill grestore 0.00 setgray +newpath 459 219 moveto 479 219 lineto 479 199 lineto 459 199 lineto closepath 0.75 setgray + gsave fill grestore 0.00 setgray +newpath 459 259 moveto 479 259 lineto 479 239 lineto 459 239 lineto closepath 0.75 setgray + gsave fill grestore 0.00 setgray +newpath 439 259 moveto 459 259 lineto 459 199 lineto 439 199 lineto closepath 0.75 setgray + gsave fill grestore 0.00 setgray +newpath 319 269 moveto 349 269 lineto 349 189 lineto 319 189 lineto closepath 0.75 setgray + gsave fill grestore 0.00 setgray +newpath 369 269 moveto 399 269 lineto 399 189 lineto 369 189 lineto closepath 0.75 setgray + gsave fill grestore 0.00 setgray +newpath 349 219 moveto 369 219 lineto 369 189 lineto 349 189 lineto closepath 0.75 setgray + gsave fill grestore 0.00 setgray +newpath 349 269 moveto 369 269 lineto 369 239 lineto 349 239 lineto closepath 0.75 setgray + gsave fill grestore 0.00 setgray +1.000 setlinewidth +newpath 459 239 moveto 479 239 lineto 479 219 lineto 459 219 lineto closepath gsave fill grestore stroke +newpath 349 239 moveto 369 239 lineto 369 219 lineto 349 219 lineto closepath gsave fill grestore stroke +newpath 219 239 moveto 239 239 lineto 239 219 lineto 219 219 lineto closepath gsave fill grestore stroke +newpath 199 259 moveto 199 199 lineto stroke +newpath 259 259 moveto 199 259 lineto stroke +newpath 259 199 moveto 259 259 lineto stroke +newpath 199 199 moveto 259 199 lineto stroke + [4.000000] 0 setdash +newpath 169 109 moveto 169 349 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 579 349 moveto 579 109 lineto stroke + [] 0 setdash +newpath 334 94 moveto 321 94 lineto stroke +newpath 329.000 96.000 moveto 321.000 94.000 lineto 329.000 92.000 lineto stroke +newpath 284 94 moveto 297 94 lineto stroke +newpath 289.000 92.000 moveto 297.000 94.000 lineto 289.000 96.000 lineto stroke +newpath 214 94 moveto 201 94 lineto stroke +newpath 209.000 96.000 moveto 201.000 94.000 lineto 209.000 92.000 lineto stroke +newpath 154 94 moveto 167 94 lineto stroke +newpath 159.000 92.000 moveto 167.000 94.000 lineto 159.000 96.000 lineto stroke +newpath 334 309 moveto 347 309 lineto stroke +newpath 339.000 307.000 moveto 347.000 309.000 lineto 339.000 311.000 lineto stroke +newpath 424 309 moveto 437 309 lineto stroke +newpath 429.000 307.000 moveto 437.000 309.000 lineto 429.000 311.000 lineto stroke +newpath 476 309 moveto 459 309 lineto stroke +newpath 467.000 311.000 moveto 459.000 309.000 lineto 467.000 307.000 lineto stroke +newpath 386 309 moveto 369 309 lineto stroke +newpath 377.000 311.000 moveto 369.000 309.000 lineto 377.000 307.000 lineto stroke +newpath 224 154 moveto 237 154 lineto stroke +newpath 229.000 152.000 moveto 237.000 154.000 lineto 229.000 156.000 lineto stroke +newpath 409.000 156.000 moveto 401.000 154.000 lineto 409.000 152.000 lineto stroke +newpath 401 154 moveto 437 154 lineto stroke +newpath 429.000 152.000 moveto 437.000 154.000 lineto 429.000 156.000 lineto stroke +newpath 329.000 156.000 moveto 321.000 154.000 lineto 329.000 152.000 lineto stroke +newpath 321 154 moveto 347 154 lineto stroke +newpath 339.000 152.000 moveto 347.000 154.000 lineto 339.000 156.000 lineto stroke +newpath 269.000 311.000 moveto 261.000 309.000 lineto 269.000 307.000 lineto stroke +newpath 261 309 moveto 297 309 lineto stroke +newpath 289.000 307.000 moveto 297.000 309.000 lineto 289.000 311.000 lineto stroke +/fn0.12 /Times-Roman findfont 13.333333 scalefont def +fn0.12 setfont +(CCA) 203 214 moveto 1 -1 scale show 1 -1 scale +(CCA) 445 216 moveto 1 -1 scale show 1 -1 scale +(CCA) 334 214 moveto 1 -1 scale show 1 -1 scale +(CWN) 541 341 moveto 1 -1 scale show 1 -1 scale +(CSN) 249 275 moveto 1 -1 scale show 1 -1 scale +(CSN) 368 256 moveto 1 -1 scale show 1 -1 scale +(CSP) 471 255 moveto 1 -1 scale show 1 -1 scale +(CAA) 228 255 moveto 1 -1 scale show 1 -1 scale +(CBA) 486 282 moveto 1 -1 scale show 1 -1 scale +/fn0.15 /Times-Roman findfont 16.666667 scalefont def +fn0.15 setfont +(16.11) 170 385 moveto 1 -1 scale show 1 -1 scale +(16.10) 164 88 moveto 1 -1 scale show 1 -1 scale +(16.9) 234 149 moveto 1 -1 scale show 1 -1 scale +(16.8) 264 329 moveto 1 -1 scale show 1 -1 scale +(16.7) 535 386 moveto 1 -1 scale show 1 -1 scale +(16.6) 433 331 moveto 1 -1 scale show 1 -1 scale +(16.5) 494 148 moveto 1 -1 scale show 1 -1 scale +(16.4) 402 148 moveto 1 -1 scale show 1 -1 scale +(16.3) 294 87 moveto 1 -1 scale show 1 -1 scale +(16.2) 319 148 moveto 1 -1 scale show 1 -1 scale +(16.1) 344 330 moveto 1 -1 scale show 1 -1 scale +showpage +$F2psEnd +%%EndDocument + 177 1284 a + endTexFig +951 2828 a Fl(24)p eop +%%Page: 25 25 +bop 0 198 a Fo(Capacitor)23 b(W)-6 b(ell)21 b(\(CW)n(C)h(-)h(Linear)f +(Capacitor)h(Option\))30 327 y Fn(17.1)72 b(Minim)n(um)18 b(width)1073 +b(10)30 402 y(17.2)72 b(Minim)n(um)18 b(spacing)1028 b(9)30 +477 y(17.3)72 b(Minim)n(um)18 b(spacing)g(to)i(external)f(activ)n(e)552 +b(5)30 551 y(17.4)72 b(Minim)n(um)18 b(o)n(v)n(erlap)h(of)h(activ)n(e)793 +b(3)187 1060 y + 24865505 10590863 0 0 24865505 10590863 startTexFig +187 1060 a +%%BeginDocument: ciffig/cwell.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-117.0 296.0 translate 0.900 -0.900 scale +0.500 setlinewidth +n 249.000 166.000 m 241.000 164.000 l 249.000 162.000 l gs 2 setlinejoin col0 s gr +n 241 164 m 279 164 l gs col0 s gr +n 319 164 m 357 164 l gs col0 s gr +n 349.000 162.000 m 357.000 164.000 l 349.000 166.000 l gs 2 setlinejoin col0 s gr +n 419 294 m 447 294 l gs col0 s gr +n 439.000 292.000 m 447.000 294.000 l 439.000 296.000 l gs 2 setlinejoin col0 s gr +n 369.000 296.000 m 361.000 294.000 l 369.000 292.000 l gs 2 setlinejoin col0 s gr +n 361 294 m 389 294 l gs col0 s gr +n 224 294 m 237 294 l gs col0 s gr +n 229.000 292.000 m 237.000 294.000 l 229.000 296.000 l gs 2 setlinejoin col0 s gr +n 199.000 296.000 m 191.000 294.000 l 199.000 292.000 l gs 2 setlinejoin col0 s gr +n 191 294 m 204 294 l gs col0 s gr +n 249.000 311.000 m 241.000 309.000 l 249.000 307.000 l gs 2 setlinejoin col0 s gr +n 241 309 m 267 309 l gs col0 s gr +n 259.000 307.000 m 267.000 309.000 l 259.000 311.000 l gs 2 setlinejoin col0 s gr +n 239 164 m 239 164 l gs col0 s gr +0.000 setlinewidth +n 269 209 m 319 209 l 319 249 l 269 249 l clp gs 0.75 setgray fill gr +n 129 209 m 189 209 l 189 249 l 129 249 l clp gs 0.75 setgray fill gr +0.500 setlinewidth +n 449 179 m 549 179 l 549 279 l 449 279 l clp gs col0 s gr +n 239 179 m 359 179 l 359 279 l 239 279 l clp gs col0 s gr +/Times-Roman findfont 12.00 scalefont setfont +517 263 m +gs 1 -1 scale (CWP) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +517 275 m +gs 1 -1 scale (CWC) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +158 242 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +517 250 m +gs 1 -1 scale (CWN) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +327 274 m +gs 1 -1 scale (CWC) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +291 242 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 14.00 scalefont setfont +242 328 m +gs 1 -1 scale (17.4) col0 show gr +/Times-Roman findfont 14.00 scalefont setfont +201 288 m +gs 1 -1 scale (17.3) col0 show gr +/Times-Roman findfont 14.00 scalefont setfont +392 289 m +gs 1 -1 scale (17.2) col0 show gr +/Times-Roman findfont 14.00 scalefont setfont +286 160 m +gs 1 -1 scale (17.1) col0 show gr +$F2psEnd +%%EndDocument + 187 1060 a + endTexFig +951 2828 a Fl(25)p eop +%%Page: 26 26 +bop 0 198 a Fo(Linear)23 b(Capacitor)f(\(Linear)h(Capacitor)g(Option\))30 +327 y Fn(18.1)72 b(Minim)n(um)18 b(width)1073 b(3)30 402 y(18.2)72 +b(Minim)n(um)18 b(p)r(oly)g(extension)h(of)h(activ)n(e)603 +b(1)30 477 y(18.3)72 b(Minim)n(um)18 b(activ)n(e)g(o)n(v)n(erlap)i(of)g(p)r +(oly)660 b(3)30 551 y(18.4)72 b(Minim)n(um)18 b(p)r(oly)g(con)n(tact)i(to)g +(activ)n(e)652 b(2)30 626 y(18.5)72 b(Minim)n(um)18 b(activ)n(e)g(con)n(tact) +i(to)g(p)r(oly)652 b(4)362 910 y + 19339837 16116531 0 0 19339837 16116531 startTexFig +362 910 a +%%BeginDocument: ciffig/lcap.ps +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/l {lineto} bind def +/m {moveto} bind def +/s {stroke} bind def +/n {newpath} bind def +/gs {gsave} bind def +/gr {grestore} bind def +/clp {closepath} bind def +/graycol {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul +4 -2 roll mul setrgbcolor} bind def +/col-1 {} def +/col0 {0 0 0 setrgbcolor} bind def +/col1 {0 0 1 setrgbcolor} bind def +/col2 {0 1 0 setrgbcolor} bind def +/col3 {0 1 1 setrgbcolor} bind def +/col4 {1 0 0 setrgbcolor} bind def +/col5 {1 0 1 setrgbcolor} bind def +/col6 {1 1 0 setrgbcolor} bind def +/col7 {1 1 1 setrgbcolor} bind def + end +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +0 setlinecap 0 setlinejoin +-169.0 306.0 translate 0.900 -0.900 scale +n 269 129 m 409 129 l 409 289 l 269 289 l clp gs 0.75 setgray fill gr +0.500 setlinewidth +n 439 319 m 429 319 l gs 0.75 setgray fill gr +gs col0 s gr +n 439 99 m 439 319 l gs 0.75 setgray fill gr +gs col0 s gr +n 429 99 m 439 99 l gs 0.75 setgray fill gr +gs col0 s gr +n 429 99 m 239 99 l gs 0.90 setgray fill gr +gs col0 s gr +n 239 319 m 429 319 l gs 0.90 setgray fill gr +gs col0 s gr +n 239 99 m 239 319 l gs 0.90 setgray fill gr +gs col0 s gr +n 224 274 m 224 287 l gs col0 s gr +n 226.000 279.000 m 224.000 287.000 l 222.000 279.000 l gs 2 setlinejoin col0 s gr +n 224 324 m 224 311 l gs col0 s gr +n 222.000 319.000 m 224.000 311.000 l 226.000 319.000 l gs 2 setlinejoin col0 s gr +n 284 84 m 271 84 l gs col0 s gr +n 279.000 86.000 m 271.000 84.000 l 279.000 82.000 l gs 2 setlinejoin col0 s gr +n 244 84 m 257 84 l gs col0 s gr +n 249.000 82.000 m 257.000 84.000 l 249.000 86.000 l gs 2 setlinejoin col0 s gr +0.000 setlinewidth +n 329 159 m 349 159 l 349 139 l 329 139 l clp gs 0.00 setgray fill gr +n 289 159 m 309 159 l 309 139 l 289 139 l clp gs 0.00 setgray fill gr +0.500 setlinewidth +n 472.000 209.000 m 474.000 201.000 l 476.000 209.000 l gs 2 setlinejoin col0 s gr +n 474 201 m 474 287 l gs col0 s gr +n 476.000 279.000 m 474.000 287.000 l 472.000 279.000 l gs 2 setlinejoin col0 s gr +n 452.000 139.000 m 454.000 131.000 l 456.000 139.000 l gs 2 setlinejoin col0 s gr +n 454 131 m 454 201 l gs col0 s gr +n 456.000 193.000 m 454.000 201.000 l 452.000 193.000 l gs 2 setlinejoin col0 s gr +n 222.000 169.000 m 224.000 161.000 l 226.000 169.000 l gs 2 setlinejoin col0 s gr +n 224 161 m 224 197 l gs col0 s gr +n 226.000 189.000 m 224.000 197.000 l 222.000 189.000 l gs 2 setlinejoin col0 s gr +1.000 setlinewidth + [4.000000] 0 setdash +n 259 199 m 379 199 l 379 339 l 259 339 l clp gs col0 s gr + [] 0 setdash +0.000 setlinewidth +n 349 309 m 369 309 l 369 329 l 349 329 l clp gs 0.00 setgray fill gr +n 309 309 m 329 309 l 329 329 l 309 329 l clp gs 0.00 setgray fill gr +n 269 309 m 289 309 l 289 329 l 269 329 l clp gs 0.00 setgray fill gr +/Times-Roman findfont 12.00 scalefont setfont +277 173 m +gs 1 -1 scale (CCA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +363 114 m +gs 1 -1 scale (CWC) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +373 148 m +gs 1 -1 scale (CAA) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +309 299 m +gs 1 -1 scale (CPG) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +483 252 m +gs 1 -1 scale (18.1) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +464 174 m +gs 1 -1 scale (18.3) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +188 187 m +gs 1 -1 scale (18.5) col0 show gr +/Times-Roman findfont 15.00 scalefont setfont +187 305 m +gs 1 -1 scale (18.4) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +297 253 m +gs 1 -1 scale (capacitor) col0 show gr +/Times-Roman findfont 12.00 scalefont setfont +304 235 m +gs 1 -1 scale (linear) col0 show gr +/Times-Roman findfont 14.00 scalefont setfont +253 77 m +gs 1 -1 scale (18.2) col0 show gr +$F2psEnd +%%EndDocument + 362 910 a + endTexFig +951 2828 a Fl(26)p eop +%%Page: 27 27 +bop 0 202 a Fo(Buried)22 b(Channel)g(CCD)g(\(CCD)g(-)h(Analog)g(Option)1364 +180 y Fg(9)1386 202 y Fo(\))30 318 y Fn(19.1)72 b(Minim)n(um)18 +b(CCD)h(c)n(hannel)h(activ)n(e)f(width)531 b(4)30 393 y(19.2)72 +b(Minim)n(um)18 b(CCD)h(c)n(hannel)h(activ)n(e)f(spacing)486 +b(4)30 468 y(19.3)72 b(Minim)n(um)18 b(CCD)h(implan)n(t)g(o)n(v)n(erlap)h(of) +g(c)n(hannel)g(activ)n(e)202 b(2)30 542 y(19.4)72 b(Minim)n(um)18 +b(outside)h(con)n(tact)h(to)g(CCD)g(implan)n(t)378 b(3)30 617 +y(19.5)72 b(Minim)n(um)18 b(select)g(o)n(v)n(erlap)h(of)h(electro)r(de)f +(\(or)h(p)r(oly\))296 b(2)30 692 y(19.6)72 b(Minim)n(um)18 +b(p)r(oly/electro)r(de)f(o)n(v)n(erlap)i(within)h(c)n(hannel)g(activ)n(e)60 +b(2)30 767 y(19.7)72 b(Minim)n(um)18 b(con)n(tact)h(to)h(c)n(hannel)g +(electro)r(de)e(\(or)j(p)r(oly\))233 b(2)-25 1129 y + 31575244 19142492 4341596 16445440 35916840 35587932 startTexFig +-25 1129 a +%%BeginDocument: ciffig/ccd3.ps +/$F2psDict 32 dict def $F2psDict begin $F2psDict /mtrx matrix put + end /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def +$F2psBegin +-21.000000 639.000000 translate +0.900000 -0.900000 scale +1.000 setlinewidth +newpath 517.000 166.000 moveto 509.000 164.000 lineto 517.000 162.000 lineto stroke +newpath 509 164 moveto 524 164 lineto stroke +newpath 474 164 moveto 489 164 lineto stroke +newpath 481.000 162.000 moveto 489.000 164.000 lineto 481.000 166.000 lineto stroke +newpath 184 394 moveto 199 394 lineto stroke +newpath 191.000 392.000 moveto 199.000 394.000 lineto 191.000 396.000 lineto stroke +newpath 227.000 396.000 moveto 219.000 394.000 lineto 227.000 392.000 lineto stroke +newpath 219 394 moveto 234 394 lineto stroke +newpath 537.000 136.000 moveto 529.000 134.000 lineto 537.000 132.000 lineto stroke +newpath 529 134 moveto 544 134 lineto stroke +newpath 494 134 moveto 509 134 lineto stroke +newpath 501.000 132.000 moveto 509.000 134.000 lineto 501.000 136.000 lineto stroke +newpath 592.000 287.000 moveto 594.000 279.000 lineto 596.000 287.000 lineto stroke +newpath 594 279 moveto 594 319 lineto stroke +newpath 596.000 311.000 moveto 594.000 319.000 lineto 592.000 311.000 lineto stroke +newpath 247.000 356.000 moveto 239.000 354.000 lineto 247.000 352.000 lineto stroke +newpath 239 354 moveto 254 354 lineto stroke +newpath 204 354 moveto 219 354 lineto stroke +newpath 211.000 352.000 moveto 219.000 354.000 lineto 211.000 356.000 lineto stroke +newpath 244 414 moveto 259 414 lineto stroke +newpath 251.000 412.000 moveto 259.000 414.000 lineto 251.000 416.000 lineto stroke +newpath 287.000 416.000 moveto 279.000 414.000 lineto 287.000 412.000 lineto stroke +newpath 279 414 moveto 294 414 lineto stroke +newpath 132.000 247.000 moveto 134.000 239.000 lineto 136.000 247.000 lineto stroke +newpath 134 239 moveto 134 279 lineto stroke +newpath 136.000 271.000 moveto 134.000 279.000 lineto 132.000 271.000 lineto stroke + [1 3.000000] 0 setdash +newpath 459 339 moveto 399 339 lineto stroke + [] 0 setdash + [1 3.000000] 0 setdash +newpath 459 109 moveto 459 339 lineto stroke + [] 0 setdash + [1 3.000000] 0 setdash +newpath 399 109 moveto 459 109 lineto stroke + [] 0 setdash + [1 3.000000] 0 setdash +newpath 369 339 moveto 309 339 lineto stroke + [] 0 setdash + [1 3.000000] 0 setdash +newpath 369 109 moveto 369 339 lineto stroke + [] 0 setdash + [1 3.000000] 0 setdash +newpath 309 109 moveto 369 109 lineto stroke + [] 0 setdash + [1 3.000000] 0 setdash +newpath 279 339 moveto 219 339 lineto stroke + [] 0 setdash + [1 3.000000] 0 setdash +newpath 279 109 moveto 279 339 lineto stroke + [] 0 setdash + [1 3.000000] 0 setdash +newpath 219 109 moveto 279 109 lineto stroke + [] 0 setdash +newpath 439 379 moveto 439 399 lineto 509 399 lineto 509 379 lineto stroke +newpath 349 379 moveto 349 399 lineto 419 399 lineto 419 379 lineto stroke +0.000 setlinewidth + [4.000000] 0 setdash +newpath 489 339 moveto 579 339 lineto 579 179 lineto 489 179 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash + [4.000000] 0 setdash +newpath 149 339 moveto 239 339 lineto 239 179 lineto 149 179 lineto closepath 0.80 setgray + gsave fill grestore 0.00 setgray + [] 0 setdash +newpath 529 309 moveto 549 309 lineto 549 289 lineto 529 289 lineto closepath gsave fill grestore % Polyline +newpath 179 309 moveto 199 309 lineto 199 289 lineto 179 289 lineto closepath gsave fill grestore % Polyline +newpath 179 229 moveto 199 229 lineto 199 209 lineto 179 209 lineto closepath gsave fill grestore [1 3.000000] 0 setdash +newpath 419 149 moveto 439 149 lineto 439 129 lineto 419 129 lineto closepath gsave fill grestore [] 0 setdash + [1 3.000000] 0 setdash +newpath 329 149 moveto 349 149 lineto 349 129 lineto 329 129 lineto closepath gsave fill grestore [] 0 setdash + [1 3.000000] 0 setdash +newpath 239 149 moveto 259 149 lineto 259 129 lineto 239 129 lineto closepath gsave fill grestore [] 0 setdash + [1 3.000000] 0 setdash +newpath 459 389 moveto 479 389 lineto 479 369 lineto 459 369 lineto closepath gsave fill grestore [] 0 setdash + [1 3.000000] 0 setdash +newpath 369 389 moveto 389 389 lineto 389 369 lineto 369 369 lineto closepath gsave fill grestore [] 0 setdash + [1 3.000000] 0 setdash +newpath 279 389 moveto 299 389 lineto 299 369 lineto 279 369 lineto closepath gsave fill grestore [] 0 setdash +newpath 529 229 moveto 549 229 lineto 549 209 lineto 529 209 lineto closepath gsave fill grestore 1.000 setlinewidth +newpath 526.000 361.000 moveto 524.000 369.000 lineto 522.000 361.000 lineto stroke +newpath 524 369 moveto 524 339 lineto stroke +newpath 522.000 347.000 moveto 524.000 339.000 lineto 526.000 347.000 lineto stroke + [1 3.000000] 0 setdash +newpath 219 339 moveto 219 109 lineto stroke + [] 0 setdash + [1 3.000000] 0 setdash +newpath 309 339 moveto 309 109 lineto stroke + [] 0 setdash + [1 3.000000] 0 setdash +newpath 399 339 moveto 399 109 lineto stroke + [] 0 setdash +newpath 259 379 moveto 259 399 lineto 329 399 lineto 329 379 lineto stroke +2.000 setlinewidth + [4.000000] 0 setdash +newpath 579 179 moveto 579 339 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 149 179 moveto 579 179 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 149 339 moveto 579 339 lineto stroke + [] 0 setdash + [4.000000] 0 setdash +newpath 149 179 moveto 149 339 lineto stroke + [] 0 setdash +1.000 setlinewidth +newpath 509 179 moveto 439 179 lineto stroke +newpath 509 379 moveto 509 179 lineto stroke +newpath 439 179 moveto 439 379 lineto stroke +newpath 349 179 moveto 419 179 lineto stroke +newpath 349 379 moveto 349 179 lineto stroke +newpath 419 179 moveto 419 379 lineto stroke +newpath 329 179 moveto 259 179 lineto stroke +newpath 329 379 moveto 329 179 lineto stroke +newpath 259 179 moveto 259 379 lineto stroke +newpath 559 279 moveto 169 279 lineto stroke +newpath 559 319 moveto 559 279 lineto stroke +newpath 169 319 moveto 559 319 lineto stroke +newpath 169 279 moveto 169 319 lineto stroke +newpath 559 199 moveto 169 199 lineto stroke +newpath 169 199 moveto 169 239 lineto 559 239 lineto stroke +newpath 559 199 moveto 559 239 lineto stroke +newpath 134 214 moveto 134 201 lineto stroke +newpath 132.000 209.000 moveto 134.000 201.000 lineto 136.000 209.000 lineto stroke +newpath 134 164 moveto 134 177 lineto stroke +newpath 136.000 169.000 moveto 134.000 177.000 lineto 132.000 169.000 lineto stroke +newpath 592.000 209.000 moveto 594.000 201.000 lineto 596.000 209.000 lineto stroke +newpath 594 201 moveto 594 237 lineto stroke +newpath 596.000 229.000 moveto 594.000 237.000 lineto 592.000 229.000 lineto stroke +newpath 202.000 154.000 moveto 204.000 146.000 lineto 206.000 154.000 lineto stroke +newpath 204 146 moveto 204 177 lineto stroke +newpath 206.000 169.000 moveto 204.000 177.000 lineto 202.000 169.000 lineto stroke +/fn0.15 /Times-Roman findfont 16.666667 scalefont def +fn0.15 setfont +(19.5) 484 159 moveto 1 -1 scale show 1 -1 scale +/fn0.16 /Times-Roman findfont 17.777778 scalefont def +fn0.16 setfont +(19.7) 193 414 moveto 1 -1 scale show 1 -1 scale +(19.7) 505 129 moveto 1 -1 scale show 1 -1 scale +fn0.15 setfont +(19.1) 598 305 moveto 1 -1 scale show 1 -1 scale +(19.4) 531 360 moveto 1 -1 scale show 1 -1 scale +fn0.16 setfont +(19.2) 98 264 moveto 1 -1 scale show 1 -1 scale +/fn0.12 /Times-Roman findfont 13.333333 scalefont def +fn0.12 setfont +(CAA) 277 276 moveto 1 -1 scale show 1 -1 scale +(CSN) 549 334 moveto 1 -1 scale show 1 -1 scale +(CEL) 431 123 moveto 1 -1 scale show 1 -1 scale +(CEL) 343 123 moveto 1 -1 scale show 1 -1 scale +(CPG) 392 395 moveto 1 -1 scale show 1 -1 scale +(CPG) 302 395 moveto 1 -1 scale show 1 -1 scale +(CCD) 548 173 moveto 1 -1 scale show 1 -1 scale +(CEL) 253 123 moveto 1 -1 scale show 1 -1 scale +(CPG) 483 395 moveto 1 -1 scale show 1 -1 scale +(CSN) 153 333 moveto 1 -1 scale show 1 -1 scale +(CAA) 387 236 moveto 1 -1 scale show 1 -1 scale +fn0.15 setfont +(19.6) 254 433 moveto 1 -1 scale show 1 -1 scale +(19.5) 212 374 moveto 1 -1 scale show 1 -1 scale +(19.4) 165 169 moveto 1 -1 scale show 1 -1 scale +(19.3) 96 196 moveto 1 -1 scale show 1 -1 scale +(19.1) 598 225 moveto 1 -1 scale show 1 -1 scale +showpage +$F2psEnd +%%EndDocument + -25 1129 a + endTexFig +0 2658 780 2 v 56 2689 a Fh(9)75 2704 y Fg(Not)14 b(for)f(all)g(pro)q(cesses) +951 2828 y Fl(27)p eop +%%Page: 28 28 +bop 0 203 a Fj(References)0 313 y Fl([1])24 b(Cadence)12 b(Design)h(Systems,) +e(Inc./Calma.)j Fk(GDSII)f(Str)n(e)n(am)h(F)l(ormat)f(Manual)p +Fl(,)h(F)l(eb.)d(1987.)17 b(Release)76 373 y(6.0,)f(Do)q(cumen)o(tation)f +(No.:)21 b(B97E060.)0 475 y([2])j(J.)g(Marshall,)h(M.)e(Gaitan,)k(M.)c +(Zaghloul,)j(D.)e(No)o(v)o(otn)o(y)l(,)g(V.)g(T)o(yree,)g(J.-I.)f(Pi,)j(C.)e +(Pi)q(~)-26 b(n\023)i(a,)26 b(and)76 535 y(W.)c(Hansford.)41 +b(Realizing)22 b(susp)q(ended)h(structures)f(on)i(c)o(hips)e(fabricated)g(b)o +(y)g(CMOS)h(foundry)76 595 y(pro)q(cesses)13 b(through)h(the)f(MOSIS)g +(service.)h(T)l(ec)o(hnical)e(Rep)q(ort)h(NISTIR-5402,)h(National)f +(Institute)76 655 y(of)j(Standards)i(and)f(T)l(ec)o(hnology)l(,)e(U.S.)g +(Departmen)o(t)g(of)i(Commerce,)12 b(Gaithersburg,)17 b(MD,)f(1994.)0 +757 y([3])24 b(C.)16 b(Mead)g(and)h(L.)f(Con)o(w)o(a)o(y)l(.)21 +b Fk(Intr)n(o)n(duction)c(to)h(VLSI)f(Systems)p Fl(.)22 b(Addison-Wesley)l(,) +15 b(1980.)0 859 y([4])24 b(N.)17 b(H.)f(E.)i(W)l(este)f(and)h(K.)g +(Eshraghian.)26 b Fk(Principles)20 b(of)f(CMOS)g(VLSI)g(Design:)25 +b(A)19 b(System)h(Per-)76 919 y(sp)n(e)n(ctive)p Fl(.)i(Addison-Wesley)l(,)15 +b(2nd.)h(edition,)f(1993.)951 2828 y(28)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/scmos/examples/bipolar/README b/scmos/examples/bipolar/README new file mode 100644 index 00000000..adcb002f --- /dev/null +++ b/scmos/examples/bipolar/README @@ -0,0 +1,22 @@ + +SCMOS rules for vertical NPN transistor has been revised from version +6 to 7 due to the requirement to support ORBIT 1.2 micron process. + +If you use the "scmos" technology to load the cell "npn_array.mag", +you'll find the following DRCs: + +N-well overlap of collector must be at least 3 (MOSIS rule #16.11) +Pbase overlap of base contact must be at least 3 (MOSIS rule #16.5) + +The cell "npn_array.mag" is the actual test vehicle for the ORBIT +2.0 micron process, so it should work OK if you target for that +process. It is included here (without modification) to illustrate the +difference between thees processes. + +All other cells have been modified according to the latest SCMOS DRC +rules - revision 7. Please send attention e-mail to mosis@mosis.edu +if you have any problem or comments... + +Jen-I pi@isi.edu ;-) + + diff --git a/scmos/examples/bipolar/guardring-npn.mag b/scmos/examples/bipolar/guardring-npn.mag new file mode 100644 index 00000000..0a801f9f --- /dev/null +++ b/scmos/examples/bipolar/guardring-npn.mag @@ -0,0 +1,82 @@ +magic +tech scmos +timestamp 796597909 +<< nwell >> +rect -28 -20 30 38 +<< metal1 >> +rect -38 41 -35 45 +rect 32 41 33 45 +rect -38 30 -23 34 +rect 21 33 26 34 +rect 21 30 22 33 +rect -8 18 -6 22 +rect 8 21 14 22 +rect 8 18 10 21 +rect -38 7 -1 11 +rect -38 -4 -12 0 +rect -8 -4 -6 0 +rect 8 -3 10 0 +rect 8 -4 14 -3 +rect 21 -15 22 -12 +rect 21 -16 26 -15 +rect -38 -27 -35 -23 +rect 32 -27 33 -23 +<< collector >> +rect -25 34 27 35 +rect -25 30 -23 34 +rect 21 33 27 34 +rect 21 30 22 33 +rect -25 29 22 30 +rect -25 -11 -19 29 +rect 21 -11 22 29 +rect -25 -12 22 -11 +rect -25 -16 -23 -12 +rect 21 -15 22 -12 +rect 26 -15 27 33 +rect 21 -16 27 -15 +rect -25 -17 27 -16 +<< pbase >> +rect -15 22 17 25 +rect -15 14 -12 22 +rect -8 18 -6 22 +rect 8 21 17 22 +rect 8 18 10 21 +rect -8 14 10 18 +rect -15 11 10 14 +rect -15 7 -1 11 +rect 3 7 10 11 +rect -15 4 10 7 +rect -15 -4 -12 4 +rect -8 0 10 4 +rect -8 -4 -6 0 +rect 8 -3 10 0 +rect 14 -3 17 21 +rect 8 -4 17 -3 +rect -15 -7 17 -4 +<< collectorcontact >> +rect -23 30 21 34 +rect -23 -16 21 -12 +rect 22 -15 26 33 +<< emittercontact >> +rect -1 7 3 11 +<< pbasecontact >> +rect -12 14 -8 22 +rect -6 18 8 22 +rect -12 -4 -8 4 +rect -6 -4 8 0 +rect 10 -3 14 21 +<< psubstratepcontact >> +rect -35 41 32 45 +rect -35 -27 32 -23 +rect 33 -27 37 45 +<< psubstratepdiff >> +rect 32 41 33 45 +rect -35 -23 -31 41 +rect 32 -27 33 -23 +<< labels >> +rlabel metal1 -37 9 -37 9 4 EMITTER +rlabel metal1 -37 -2 -37 -2 2 BASE +rlabel metal1 -37 -25 -37 -25 2 GUARDRING +rlabel metal1 -37 43 -37 43 4 GND +rlabel metal1 -37 32 -37 32 4 COLLECTOR +<< end >> diff --git a/scmos/examples/bipolar/large_npn.mag b/scmos/examples/bipolar/large_npn.mag new file mode 100644 index 00000000..489b6e9e --- /dev/null +++ b/scmos/examples/bipolar/large_npn.mag @@ -0,0 +1,442 @@ +magic +tech scmos +timestamp 783737922 +<< nwell >> +rect 18 19 174 135 +<< metal1 >> +rect 0 146 179 155 +rect 15 139 17 143 +rect 44 125 53 127 +rect 57 118 63 146 +rect 67 125 76 127 +rect 116 125 125 127 +rect 129 118 135 146 +rect 175 139 177 143 +rect 139 125 148 127 +rect 21 114 35 118 +rect 50 114 70 118 +rect 85 114 107 118 +rect 122 114 142 118 +rect 157 114 171 118 +rect 21 92 27 114 +rect 44 105 53 107 +rect 57 92 63 114 +rect 67 105 76 107 +rect 93 92 99 114 +rect 116 105 125 107 +rect 129 92 135 114 +rect 139 105 148 107 +rect 165 92 171 114 +rect 21 88 35 92 +rect 50 88 70 92 +rect 85 88 107 92 +rect 122 88 142 92 +rect 157 88 171 92 +rect 21 66 27 88 +rect 44 79 53 81 +rect 57 66 63 88 +rect 67 79 76 81 +rect 93 66 99 88 +rect 116 79 125 81 +rect 129 66 135 88 +rect 139 79 148 81 +rect 165 66 171 88 +rect 21 62 35 66 +rect 50 62 70 66 +rect 85 62 107 66 +rect 122 62 142 66 +rect 157 62 171 66 +rect 21 40 27 62 +rect 44 53 53 55 +rect 57 40 63 62 +rect 67 53 76 55 +rect 93 40 99 62 +rect 116 53 125 55 +rect 129 40 135 62 +rect 139 53 148 55 +rect 165 40 171 62 +rect 21 36 35 40 +rect 50 36 70 40 +rect 85 36 107 40 +rect 122 36 142 40 +rect 157 36 171 40 +rect 21 8 27 36 +rect 44 27 53 29 +rect 67 27 76 29 +rect 93 8 99 36 +rect 116 27 125 29 +rect 139 27 148 29 +rect 165 8 171 36 +rect 181 16 182 143 +rect 177 15 182 16 +rect 180 11 182 15 +rect 0 -1 180 8 +<< metal2 >> +rect 53 139 68 143 +rect 124 139 139 143 +rect 175 139 182 143 +rect -2 125 149 126 +rect -2 121 44 125 +rect 53 121 67 125 +rect 76 121 116 125 +rect 125 121 139 125 +rect 148 121 149 125 +rect -2 120 149 121 +rect -2 112 8 120 +rect -2 111 149 112 +rect -2 107 44 111 +rect 53 107 67 111 +rect 76 107 116 111 +rect 125 107 139 111 +rect 148 107 149 111 +rect -2 106 149 107 +rect -2 86 8 106 +rect -2 85 149 86 +rect -2 81 44 85 +rect 53 81 67 85 +rect 76 81 116 85 +rect 125 81 139 85 +rect 148 81 149 85 +rect -2 80 149 81 +rect -2 60 8 80 +rect -2 59 59 60 +rect -2 55 44 59 +rect 53 55 59 59 +rect -2 54 59 55 +rect 63 59 149 60 +rect 63 55 67 59 +rect 76 55 116 59 +rect 125 55 139 59 +rect 148 55 149 59 +rect 63 54 149 55 +rect -2 34 8 54 +rect -2 33 149 34 +rect -2 29 44 33 +rect 53 29 67 33 +rect 76 29 116 33 +rect 125 29 139 33 +rect 148 29 149 33 +rect -2 28 149 29 +rect -2 12 8 28 +rect 177 15 182 139 +rect 90 11 102 15 +rect 162 11 176 15 +rect 180 11 182 15 +rect 186 11 187 143 +<< collector >> +rect 21 131 171 132 +rect 21 127 22 131 +rect 54 127 66 131 +rect 126 127 138 131 +rect 170 127 171 131 +rect 21 126 171 127 +rect 21 106 27 126 +rect 57 106 63 126 +rect 93 106 99 126 +rect 129 106 135 126 +rect 165 106 171 126 +rect 21 105 171 106 +rect 21 101 30 105 +rect 54 101 66 105 +rect 90 101 102 105 +rect 126 101 138 105 +rect 162 101 171 105 +rect 21 100 171 101 +rect 21 80 27 100 +rect 57 80 63 100 +rect 93 80 99 100 +rect 129 80 135 100 +rect 165 80 171 100 +rect 21 79 171 80 +rect 21 75 30 79 +rect 54 75 66 79 +rect 90 75 102 79 +rect 126 75 138 79 +rect 162 75 171 79 +rect 21 74 171 75 +rect 21 54 27 74 +rect 57 54 63 74 +rect 93 54 99 74 +rect 129 54 135 74 +rect 165 54 171 74 +rect 21 53 171 54 +rect 21 49 30 53 +rect 54 49 66 53 +rect 90 49 102 53 +rect 126 49 138 53 +rect 162 49 171 53 +rect 21 48 171 49 +rect 21 28 27 48 +rect 57 28 63 48 +rect 93 28 99 48 +rect 129 28 135 48 +rect 165 28 171 48 +rect 21 27 171 28 +rect 21 23 30 27 +rect 90 23 102 27 +rect 162 23 171 27 +rect 21 22 171 23 +<< pbase >> +rect 31 118 53 122 +rect 31 114 35 118 +rect 39 114 46 118 +rect 50 114 53 118 +rect 31 110 53 114 +rect 67 118 89 122 +rect 67 114 70 118 +rect 74 114 81 118 +rect 85 114 89 118 +rect 67 110 89 114 +rect 103 118 125 122 +rect 103 114 107 118 +rect 111 114 118 118 +rect 122 114 125 118 +rect 103 110 125 114 +rect 139 118 161 122 +rect 139 114 142 118 +rect 146 114 153 118 +rect 157 114 161 118 +rect 139 110 161 114 +rect 31 92 53 96 +rect 31 88 35 92 +rect 39 88 46 92 +rect 50 88 53 92 +rect 31 84 53 88 +rect 67 92 89 96 +rect 67 88 70 92 +rect 74 88 81 92 +rect 85 88 89 92 +rect 67 84 89 88 +rect 103 92 125 96 +rect 103 88 107 92 +rect 111 88 118 92 +rect 122 88 125 92 +rect 103 84 125 88 +rect 139 92 161 96 +rect 139 88 142 92 +rect 146 88 153 92 +rect 157 88 161 92 +rect 139 84 161 88 +rect 31 66 53 70 +rect 31 62 35 66 +rect 39 62 46 66 +rect 50 62 53 66 +rect 31 58 53 62 +rect 67 66 89 70 +rect 67 62 70 66 +rect 74 62 81 66 +rect 85 62 89 66 +rect 67 58 89 62 +rect 103 66 125 70 +rect 103 62 107 66 +rect 111 62 118 66 +rect 122 62 125 66 +rect 103 58 125 62 +rect 139 66 161 70 +rect 139 62 142 66 +rect 146 62 153 66 +rect 157 62 161 66 +rect 139 58 161 62 +rect 31 40 53 44 +rect 31 36 35 40 +rect 39 36 46 40 +rect 50 36 53 40 +rect 31 32 53 36 +rect 67 40 89 44 +rect 67 36 70 40 +rect 74 36 81 40 +rect 85 36 89 40 +rect 67 32 89 36 +rect 103 40 125 44 +rect 103 36 107 40 +rect 111 36 118 40 +rect 122 36 125 40 +rect 103 32 125 36 +rect 139 40 161 44 +rect 139 36 142 40 +rect 146 36 153 40 +rect 157 36 161 40 +rect 139 32 161 36 +<< collectorcontact >> +rect 22 127 54 131 +rect 66 127 126 131 +rect 138 127 170 131 +rect 30 101 54 105 +rect 66 101 90 105 +rect 102 101 126 105 +rect 138 101 162 105 +rect 30 75 54 79 +rect 66 75 90 79 +rect 102 75 126 79 +rect 138 75 162 79 +rect 30 49 54 53 +rect 66 49 90 53 +rect 102 49 126 53 +rect 138 49 162 53 +rect 30 23 90 27 +rect 102 23 162 27 +<< emittercontact >> +rect 35 114 39 118 +rect 81 114 85 118 +rect 107 114 111 118 +rect 153 114 157 118 +rect 35 88 39 92 +rect 81 88 85 92 +rect 107 88 111 92 +rect 153 88 157 92 +rect 35 62 39 66 +rect 81 62 85 66 +rect 107 62 111 66 +rect 153 62 157 66 +rect 35 36 39 40 +rect 81 36 85 40 +rect 107 36 111 40 +rect 153 36 157 40 +<< pbasecontact >> +rect 46 114 50 118 +rect 70 114 74 118 +rect 118 114 122 118 +rect 142 114 146 118 +rect 46 88 50 92 +rect 70 88 74 92 +rect 118 88 122 92 +rect 142 88 146 92 +rect 46 62 50 66 +rect 70 62 74 66 +rect 118 62 122 66 +rect 142 62 146 66 +rect 46 36 50 40 +rect 70 36 74 40 +rect 118 36 122 40 +rect 142 36 146 40 +<< m2contact >> +rect 17 139 21 143 +rect 25 139 29 143 +rect 33 139 37 143 +rect 41 139 45 143 +rect 49 139 53 143 +rect 44 121 53 125 +rect 68 139 72 143 +rect 76 139 80 143 +rect 84 139 88 143 +rect 92 139 96 143 +rect 100 139 104 143 +rect 108 139 112 143 +rect 116 139 120 143 +rect 67 121 76 125 +rect 116 121 125 125 +rect 139 139 143 143 +rect 147 139 151 143 +rect 155 139 159 143 +rect 163 139 167 143 +rect 171 139 175 143 +rect 139 121 148 125 +rect 44 107 53 111 +rect 67 107 76 111 +rect 116 107 125 111 +rect 139 107 148 111 +rect 44 81 53 85 +rect 67 81 76 85 +rect 116 81 125 85 +rect 139 81 148 85 +rect 44 55 53 59 +rect 67 55 76 59 +rect 116 55 125 59 +rect 139 55 148 59 +rect 44 29 53 33 +rect 67 29 76 33 +rect 30 11 34 15 +rect 38 11 42 15 +rect 46 11 50 15 +rect 54 11 58 15 +rect 62 11 66 15 +rect 70 11 74 15 +rect 78 11 82 15 +rect 86 11 90 15 +rect 116 29 125 33 +rect 139 29 148 33 +rect 102 11 106 15 +rect 110 11 114 15 +rect 118 11 122 15 +rect 126 11 130 15 +rect 134 11 138 15 +rect 142 11 146 15 +rect 150 11 154 15 +rect 158 11 162 15 +rect 176 11 180 15 +rect 182 11 186 143 +<< psubstratepcontact >> +rect 11 12 15 143 +rect 21 139 25 143 +rect 29 139 33 143 +rect 37 139 41 143 +rect 45 139 49 143 +rect 72 139 76 143 +rect 80 139 84 143 +rect 88 139 92 143 +rect 96 139 100 143 +rect 104 139 108 143 +rect 112 139 116 143 +rect 120 139 124 143 +rect 143 139 147 143 +rect 151 139 155 143 +rect 159 139 163 143 +rect 167 139 171 143 +rect 177 16 181 143 +rect 34 11 38 15 +rect 42 11 46 15 +rect 50 11 54 15 +rect 58 11 62 15 +rect 66 11 70 15 +rect 74 11 78 15 +rect 82 11 86 15 +rect 106 11 110 15 +rect 114 11 118 15 +rect 122 11 126 15 +rect 130 11 134 15 +rect 138 11 142 15 +rect 146 11 150 15 +rect 154 11 158 15 +<< psubstratepdiff >> +rect 11 143 181 144 +rect 15 139 21 143 +rect 25 139 29 143 +rect 33 139 37 143 +rect 41 139 45 143 +rect 49 139 72 143 +rect 76 139 80 143 +rect 84 139 88 143 +rect 92 139 96 143 +rect 100 139 104 143 +rect 108 139 112 143 +rect 116 139 120 143 +rect 124 139 143 143 +rect 147 139 151 143 +rect 155 139 159 143 +rect 163 139 167 143 +rect 171 139 177 143 +rect 15 138 177 139 +rect 15 15 181 16 +rect 15 12 34 15 +rect 11 11 34 12 +rect 38 11 42 15 +rect 46 11 50 15 +rect 54 11 58 15 +rect 62 11 66 15 +rect 70 11 74 15 +rect 78 11 82 15 +rect 86 11 106 15 +rect 110 11 114 15 +rect 118 11 122 15 +rect 126 11 130 15 +rect 134 11 138 15 +rect 142 11 146 15 +rect 150 11 154 15 +rect 158 11 181 15 +rect 11 10 181 11 +<< labels >> +rlabel metal1 0 -1 179 8 0 emitter +rlabel metal2 187 13 187 140 7 GND +rlabel metal1 0 146 179 155 0 base +rlabel metal2 -2 13 8 125 0 collector +<< end >> diff --git a/scmos/examples/bipolar/min.mag b/scmos/examples/bipolar/min.mag new file mode 100644 index 00000000..6c426018 --- /dev/null +++ b/scmos/examples/bipolar/min.mag @@ -0,0 +1,33 @@ +magic +tech scmos +timestamp 783737348 +<< nwell >> +rect 5 3 46 27 +<< metal1 >> +rect 9 0 13 13 +rect 22 0 26 13 +rect 33 0 37 13 +<< collector >> +rect 8 17 14 18 +rect 8 13 9 17 +rect 13 13 14 17 +rect 8 12 14 13 +<< pbase >> +rect 18 17 40 21 +rect 18 13 22 17 +rect 26 13 33 17 +rect 37 13 40 17 +rect 18 9 40 13 +<< collectorcontact >> +rect 9 13 13 17 +<< emittercontact >> +rect 22 13 26 17 +<< pbasecontact >> +rect 33 13 37 17 +<< labels >> +rlabel space 0 17 0 17 3 without +rlabel space 0 13 0 13 3 guardring +rlabel metal1 35 1 35 1 5 base +rlabel metal1 24 1 24 1 5 emitter +rlabel metal1 11 1 11 1 5 collector +<< end >> diff --git a/scmos/examples/bipolar/min2b.mag b/scmos/examples/bipolar/min2b.mag new file mode 100644 index 00000000..1c5c8534 --- /dev/null +++ b/scmos/examples/bipolar/min2b.mag @@ -0,0 +1,59 @@ +magic +tech scmos +timestamp 783737384 +<< nwell >> +rect 0 1 58 39 +<< metal1 >> +rect 4 30 8 31 +rect 16 22 20 40 +rect 26 22 32 40 +rect 26 18 27 22 +rect 31 18 32 22 +rect 38 22 42 40 +rect 16 15 20 18 +rect 38 15 42 18 +rect 16 12 42 15 +rect 50 30 54 31 +rect 4 9 8 10 +rect 50 9 54 10 +rect 4 5 5 9 +rect 53 5 54 9 +rect 26 0 32 5 +<< collector >> +rect 3 35 55 36 +rect 3 31 4 35 +rect 12 31 46 35 +rect 54 31 55 35 +rect 3 30 55 31 +rect 3 10 4 30 +rect 8 10 9 30 +rect 49 10 50 30 +rect 54 10 55 30 +rect 3 9 55 10 +rect 3 5 5 9 +rect 53 5 55 9 +rect 3 4 55 5 +<< pbase >> +rect 13 22 45 26 +rect 13 18 16 22 +rect 20 18 27 22 +rect 31 18 38 22 +rect 42 18 45 22 +rect 13 14 45 18 +<< collectorcontact >> +rect 4 31 12 35 +rect 46 31 54 35 +rect 4 10 8 30 +rect 50 10 54 30 +rect 5 5 53 9 +<< emittercontact >> +rect 27 18 31 22 +<< pbasecontact >> +rect 16 18 20 22 +rect 38 18 42 22 +<< labels >> +rlabel metal1 29 1 29 1 1 collector +rlabel metal1 40 39 40 39 1 base +rlabel metal1 29 39 29 39 1 emitter +rlabel metal1 18 39 18 39 1 base +<< end >> diff --git a/scmos/examples/bipolar/min2e.mag b/scmos/examples/bipolar/min2e.mag new file mode 100644 index 00000000..d4bc321c --- /dev/null +++ b/scmos/examples/bipolar/min2e.mag @@ -0,0 +1,61 @@ +magic +tech scmos +timestamp 783737406 +<< nwell >> +rect 0 1 60 39 +<< metal1 >> +rect 4 30 8 31 +rect 16 22 22 40 +rect 16 18 17 22 +rect 21 18 22 22 +rect 16 17 22 18 +rect 27 22 33 40 +rect 27 18 28 22 +rect 32 18 33 22 +rect 27 17 33 18 +rect 38 22 44 40 +rect 38 18 39 22 +rect 43 18 44 22 +rect 38 17 44 18 +rect 52 30 56 31 +rect 4 9 8 10 +rect 52 9 56 10 +rect 27 0 33 5 +<< collector >> +rect 3 35 57 36 +rect 3 31 4 35 +rect 12 31 48 35 +rect 56 31 57 35 +rect 3 30 57 31 +rect 3 10 4 30 +rect 8 10 9 30 +rect 51 10 52 30 +rect 56 10 57 30 +rect 3 9 57 10 +rect 3 5 4 9 +rect 56 5 57 9 +rect 3 4 57 5 +<< pbase >> +rect 13 22 47 26 +rect 13 18 17 22 +rect 21 18 28 22 +rect 32 18 39 22 +rect 43 18 47 22 +rect 13 14 47 18 +<< collectorcontact >> +rect 4 31 12 35 +rect 48 31 56 35 +rect 4 10 8 30 +rect 52 10 56 30 +rect 4 5 56 9 +<< emittercontact >> +rect 17 18 21 22 +rect 39 18 43 22 +<< pbasecontact >> +rect 28 18 32 22 +<< labels >> +rlabel metal1 30 1 30 1 1 collector +rlabel metal1 30 39 30 39 1 base +rlabel metal1 19 39 19 39 1 emitter1 +rlabel metal1 41 39 41 39 1 emitter2 +<< end >> diff --git a/scmos/examples/bipolar/min_npn.mag b/scmos/examples/bipolar/min_npn.mag new file mode 100644 index 00000000..93aebcb2 --- /dev/null +++ b/scmos/examples/bipolar/min_npn.mag @@ -0,0 +1,73 @@ +magic +tech scmos +timestamp 783737496 +<< nwell >> +rect 8 58 49 82 +rect 62 51 100 89 +rect 0 0 48 38 +<< metal1 >> +rect 12 55 16 68 +rect 25 55 29 68 +rect 36 55 40 68 +<< collector >> +rect 65 85 97 86 +rect 65 81 66 85 +rect 96 81 97 85 +rect 65 80 97 81 +rect 11 72 17 73 +rect 11 68 12 72 +rect 16 68 17 72 +rect 11 67 17 68 +rect 65 59 97 60 +rect 65 55 66 59 +rect 96 55 97 59 +rect 65 54 97 55 +rect 3 34 45 35 +rect 3 30 9 34 +rect 37 30 45 34 +rect 3 29 45 30 +rect 3 9 9 29 +rect 39 9 45 29 +rect 3 8 45 9 +rect 3 4 8 8 +rect 39 4 45 8 +rect 3 3 45 4 +<< pbase >> +rect 21 75 33 76 +rect 21 72 43 75 +rect 21 68 25 72 +rect 29 68 36 72 +rect 40 68 43 72 +rect 21 65 43 68 +rect 71 72 93 76 +rect 71 68 75 72 +rect 79 68 86 72 +rect 90 68 93 72 +rect 21 64 33 65 +rect 71 64 93 68 +rect 13 21 35 25 +rect 13 17 17 21 +rect 21 17 28 21 +rect 32 17 35 21 +rect 13 13 35 17 +<< collectorcontact >> +rect 66 81 96 85 +rect 12 68 16 72 +rect 66 55 96 59 +rect 9 30 37 34 +rect 8 4 39 8 +<< emittercontact >> +rect 25 68 29 72 +rect 75 68 79 72 +rect 17 17 21 21 +<< pbasecontact >> +rect 36 68 40 72 +rect 86 68 90 72 +rect 28 17 32 21 +<< labels >> +rlabel space 3 72 3 72 3 without +rlabel space 3 68 3 68 3 guardring +rlabel metal1 12 55 16 55 5 collector +rlabel metal1 25 55 29 55 5 emitter +rlabel metal1 36 55 40 55 5 base +<< end >> diff --git a/scmos/examples/bipolar/npn12_array_core.cif b/scmos/examples/bipolar/npn12_array_core.cif new file mode 100644 index 00000000..3d0f71cc --- /dev/null +++ b/scmos/examples/bipolar/npn12_array_core.cif @@ -0,0 +1,1041 @@ +( @@user : hansford ); +( @@machine : tesla.isi.edu ); +( @@source : npn_array_core.mag ); +( @@tool : Magic 6.4.4 ); +( @@patch : 1 ); +( @@patchnames : release-6.4, linux1 ); +( @@compiled : Thu Sep 22 16:55:06 PDT 1994 ); +( @@technology : scmos ); +( @@version : 8.0.0 ); +( @@techdesc : MOSIS Scalable CMOS Technology for Orbit, AMI, and VTI ); +( @@style : lambda=0.6(gen) ); +( @@date : Fri Oct 7 16:25:52 1994 ); +DS 1 30 2; +9 npn_array_core; +L CWN; + B 216 152 432 456; + B 216 196 1144 482; + B 832 196 2000 482; + B 1540 196 3522 482; + B 480 196 4884 482; + B 304 196 5588 482; +L CMF; + B 16 4 312 574; + B 16 4 648 574; + B 152 16 380 564; + B 88 16 384 508; + B 16 88 348 456; + B 16 68 448 522; + B 32 12 440 482; + B 188 16 562 564; + B 16 28 388 450; + B 16 28 432 462; + B 16 120 476 496; + B 88 16 1096 556; + B 28 16 510 508; + B 104 12 432 430; + B 16 88 516 456; + B 184 16 432 404; + B 16 132 1060 482; + B 16 48 1160 552; + B 32 16 1152 520; + B 16 72 1100 476; + B 16 60 1144 482; + B 16 136 1188 508; + B 16 12 2392 570; + B 28 16 1222 556; + B 104 12 1144 434; + B 16 132 1228 482; + B 184 16 1144 408; + B 800 16 2000 556; + B 16 132 1608 482; + B 720 12 2000 530; + B 16 72 1648 488; + B 16 72 1692 476; + B 16 72 1736 488; + B 16 72 1780 476; + B 16 72 1824 488; + B 16 72 1868 476; + B 16 72 1912 488; + B 16 72 1956 476; + B 16 72 2000 488; + B 16 72 2044 476; + B 16 72 2088 488; + B 16 72 2132 476; + B 16 72 2176 488; + B 16 72 2220 476; + B 16 72 2264 488; + B 16 72 2308 476; + B 648 12 2008 434; + B 700 16 1950 408; + B 16 8 484 392; + B 16 12 1228 394; + B 16 40 2324 408; + B 16 136 2352 456; + B 16 132 2392 482; + B 28 16 2386 408; + B 1412 16 3474 556; + B 16 132 2776 482; + B 16 40 4200 556; + B 1356 12 3530 530; + B 16 72 2816 476; + B 16 72 2860 488; + B 16 72 2904 476; + B 16 72 2948 488; + B 16 72 2992 476; + B 16 72 3036 488; + B 16 72 3080 476; + B 16 72 3124 488; + B 16 72 3168 476; + B 16 72 3212 488; + B 16 72 3256 476; + B 16 72 3300 488; + B 16 72 3344 476; + B 16 72 3388 488; + B 16 72 3432 476; + B 16 72 3476 488; + B 16 72 3520 476; + B 16 72 3564 488; + B 16 72 3608 476; + B 16 72 3652 488; + B 16 72 3696 476; + B 16 72 3740 488; + B 16 72 3784 476; + B 16 72 3828 488; + B 16 72 3872 476; + B 16 72 3920 488; + B 16 72 3964 476; + B 16 72 4008 488; + B 16 72 4052 476; + B 16 72 4096 488; + B 16 72 4140 476; + B 16 72 4184 488; + B 16 136 4228 508; + B 16 12 4788 570; + B 16 12 5436 570; + B 24 16 4264 556; + B 1428 12 3522 434; + B 16 132 4268 482; + B 1508 16 3522 408; + B 448 16 4884 556; + B 296 16 5576 556; + B 16 132 4668 482; + B 368 12 4884 530; + B 28 16 4674 408; + B 16 12 3512 394; + B 16 136 4708 456; + B 16 72 4752 476; + B 16 72 4796 488; + B 16 72 4840 476; + B 16 72 4884 488; + B 16 72 4928 476; + B 16 72 4972 488; + B 16 72 5016 476; + B 16 72 5060 488; + B 296 12 4876 434; + B 16 40 4736 408; + B 16 132 5100 482; + B 352 16 4932 408; + B 16 132 5460 482; + B 192 12 5588 530; + B 16 72 5500 488; + B 16 72 5544 476; + B 16 72 5588 488; + B 16 72 5632 476; + B 120 12 5596 434; + B 176 16 5540 408; + B 16 40 5648 408; + B 16 136 5676 456; + B 16 132 5716 482; + B 28 16 5710 408; +L CAA; + B 192 24 1144 556; + B 192 24 432 508; + B 24 80 348 456; + B 16 16 432 456; + B 24 80 516 456; + B 192 24 432 404; + B 24 124 1060 482; + B 16 16 1144 504; + B 16 16 1144 460; + B 24 124 1228 482; + B 192 24 1144 408; + B 808 24 2000 556; + B 24 124 1608 482; + B 16 16 1692 504; + B 16 16 1780 504; + B 16 16 1868 504; + B 16 16 1956 504; + B 16 16 2044 504; + B 16 16 2132 504; + B 16 16 2220 504; + B 16 16 2308 504; + B 16 16 1692 460; + B 16 16 1780 460; + B 16 16 1868 460; + B 16 16 1956 460; + B 16 16 2044 460; + B 16 16 2132 460; + B 16 16 2220 460; + B 16 16 2308 460; + B 24 124 2392 482; + B 808 24 2000 408; + B 1516 24 3522 556; + B 24 124 2776 482; + B 16 16 2860 504; + B 16 16 2948 504; + B 16 16 3036 504; + B 16 16 3124 504; + B 16 16 3212 504; + B 16 16 3300 504; + B 16 16 3388 504; + B 16 16 3476 504; + B 16 16 3564 504; + B 16 16 3652 504; + B 16 16 3740 504; + B 16 16 3828 504; + B 16 16 3920 504; + B 16 16 4008 504; + B 16 16 4096 504; + B 16 16 4184 504; + B 16 16 2860 460; + B 16 16 2948 460; + B 16 16 3036 460; + B 16 16 3124 460; + B 16 16 3212 460; + B 16 16 3300 460; + B 16 16 3388 460; + B 16 16 3476 460; + B 16 16 3564 460; + B 16 16 3652 460; + B 16 16 3740 460; + B 16 16 3828 460; + B 16 16 3920 460; + B 16 16 4008 460; + B 16 16 4096 460; + B 16 16 4184 460; + B 24 124 4268 482; + B 1516 24 3522 408; + B 456 24 4884 556; + B 24 124 4668 482; + B 16 16 4752 504; + B 16 16 4840 504; + B 16 16 4928 504; + B 16 16 5016 504; + B 16 16 4752 460; + B 16 16 4840 460; + B 16 16 4928 460; + B 16 16 5016 460; + B 24 124 5100 482; + B 456 24 4884 408; + B 280 24 5588 556; + B 24 124 5460 482; + B 16 16 5544 504; + B 16 16 5632 504; + B 16 16 5544 460; + B 16 16 5632 460; + B 24 124 5716 482; + B 280 24 5588 408; +L CCA; + B 8 8 1144 504; + B 8 8 1692 504; + B 8 8 1780 504; + B 8 8 1868 504; + B 8 8 1956 504; + B 8 8 2044 504; + B 8 8 2132 504; + B 8 8 2220 504; + B 8 8 2308 504; + B 8 8 2860 504; + B 8 8 2948 504; + B 8 8 3036 504; + B 8 8 3124 504; + B 8 8 3212 504; + B 8 8 3300 504; + B 8 8 3388 504; + B 8 8 3476 504; + B 8 8 3564 504; + B 8 8 3652 504; + B 8 8 3740 504; + B 8 8 3828 504; + B 8 8 3920 504; + B 8 8 4008 504; + B 8 8 4096 504; + B 8 8 4184 504; + B 8 8 4752 504; + B 8 8 4840 504; + B 8 8 4928 504; + B 8 8 5016 504; + B 8 8 5544 504; + B 8 8 5632 504; + B 8 8 1100 496; + B 8 8 1188 496; + B 8 8 1648 496; + B 8 8 1736 496; + B 8 8 1824 496; + B 8 8 1912 496; + B 8 8 2000 496; + B 8 8 2088 496; + B 8 8 2176 496; + B 8 8 2264 496; + B 8 8 2352 496; + B 8 8 2816 496; + B 8 8 2904 496; + B 8 8 2992 496; + B 8 8 3080 496; + B 8 8 3168 496; + B 8 8 3256 496; + B 8 8 3344 496; + B 8 8 3432 496; + B 8 8 3520 496; + B 8 8 3608 496; + B 8 8 3696 496; + B 8 8 3784 496; + B 8 8 3872 496; + B 8 8 3964 496; + B 8 8 4052 496; + B 8 8 4140 496; + B 8 8 4228 496; + B 8 8 4708 496; + B 8 8 4796 496; + B 8 8 4884 496; + B 8 8 4972 496; + B 8 8 5060 496; + B 8 8 5500 496; + B 8 8 5588 496; + B 8 8 5676 496; + B 8 8 1100 480; + B 8 8 1188 480; + B 8 8 1648 480; + B 8 8 1736 480; + B 8 8 1824 480; + B 8 8 1912 480; + B 8 8 2000 480; + B 8 8 2088 480; + B 8 8 2176 480; + B 8 8 2264 480; + B 8 8 2352 480; + B 8 8 2816 480; + B 8 8 2904 480; + B 8 8 2992 480; + B 8 8 3080 480; + B 8 8 3168 480; + B 8 8 3256 480; + B 8 8 3344 480; + B 8 8 3432 480; + B 8 8 3520 480; + B 8 8 3608 480; + B 8 8 3696 480; + B 8 8 3784 480; + B 8 8 3872 480; + B 8 8 3964 480; + B 8 8 4052 480; + B 8 8 4140 480; + B 8 8 4228 480; + B 8 8 4708 480; + B 8 8 4796 480; + B 8 8 4884 480; + B 8 8 4972 480; + B 8 8 5060 480; + B 8 8 5500 480; + B 8 8 5588 480; + B 8 8 5676 480; + B 8 8 1100 464; + B 8 8 388 456; + B 8 8 432 456; + B 8 8 476 456; + B 8 8 1144 460; + B 8 8 1188 464; + B 8 8 1648 464; + B 8 8 1692 460; + B 8 8 1736 464; + B 8 8 1780 460; + B 8 8 1824 464; + B 8 8 1868 460; + B 8 8 1912 464; + B 8 8 1956 460; + B 8 8 2000 464; + B 8 8 2044 460; + B 8 8 2088 464; + B 8 8 2132 460; + B 8 8 2176 464; + B 8 8 2220 460; + B 8 8 2264 464; + B 8 8 2308 460; + B 8 8 2352 464; + B 8 8 2816 464; + B 8 8 2860 460; + B 8 8 2904 464; + B 8 8 2948 460; + B 8 8 2992 464; + B 8 8 3036 460; + B 8 8 3080 464; + B 8 8 3124 460; + B 8 8 3168 464; + B 8 8 3212 460; + B 8 8 3256 464; + B 8 8 3300 460; + B 8 8 3344 464; + B 8 8 3388 460; + B 8 8 3432 464; + B 8 8 3476 460; + B 8 8 3520 464; + B 8 8 3564 460; + B 8 8 3608 464; + B 8 8 3652 460; + B 8 8 3696 464; + B 8 8 3740 460; + B 8 8 3784 464; + B 8 8 3828 460; + B 8 8 3872 464; + B 8 8 3920 460; + B 8 8 3964 464; + B 8 8 4008 460; + B 8 8 4052 464; + B 8 8 4096 460; + B 8 8 4140 464; + B 8 8 4184 460; + B 8 8 4228 464; + B 8 8 4708 464; + B 8 8 4752 460; + B 8 8 4796 464; + B 8 8 4840 460; + B 8 8 4884 464; + B 8 8 4928 460; + B 8 8 4972 464; + B 8 8 5016 460; + B 8 8 5060 464; + B 8 8 5500 464; + B 8 8 5544 460; + B 8 8 5588 464; + B 8 8 5632 460; + B 8 8 5676 464; +L CCA; + B 8 8 1060 554; + B 8 8 1082 556; + B 8 8 1098 556; + B 8 8 1114 556; + B 8 8 1130 556; + B 8 8 1222 556; + B 8 8 1608 554; + B 8 8 1632 556; + B 8 8 1648 556; + B 8 8 1664 556; + B 8 8 1680 556; + B 8 8 1696 556; + B 8 8 1712 556; + B 8 8 1728 556; + B 8 8 1744 556; + B 8 8 1760 556; + B 8 8 1776 556; + B 8 8 1792 556; + B 8 8 1808 556; + B 8 8 1824 556; + B 8 8 1840 556; + B 8 8 1856 556; + B 8 8 1872 556; + B 8 8 1888 556; + B 8 8 1904 556; + B 8 8 1920 556; + B 8 8 1936 556; + B 8 8 1952 556; + B 8 8 1968 556; + B 8 8 1984 556; + B 8 8 2000 556; + B 8 8 2016 556; + B 8 8 2032 556; + B 8 8 2048 556; + B 8 8 2064 556; + B 8 8 2080 556; + B 8 8 2096 556; + B 8 8 2112 556; + B 8 8 2128 556; + B 8 8 2144 556; + B 8 8 2160 556; + B 8 8 2176 556; + B 8 8 2192 556; + B 8 8 2208 556; + B 8 8 2224 556; + B 8 8 2240 556; + B 8 8 2256 556; + B 8 8 2272 556; + B 8 8 2288 556; + B 8 8 2304 556; + B 8 8 2320 556; + B 8 8 2336 556; + B 8 8 2352 556; + B 8 8 2368 556; + B 8 8 2392 556; + B 8 8 2776 554; + B 8 8 2796 556; + B 8 8 2812 556; + B 8 8 2828 556; + B 8 8 2844 556; + B 8 8 2860 556; + B 8 8 2876 556; + B 8 8 2892 556; + B 8 8 2908 556; + B 8 8 2924 556; + B 8 8 2940 556; + B 8 8 2956 556; + B 8 8 2972 556; + B 8 8 2988 556; + B 8 8 3004 556; + B 8 8 3020 556; + B 8 8 3036 556; + B 8 8 3052 556; + B 8 8 3068 556; + B 8 8 3084 556; + B 8 8 3100 556; + B 8 8 3116 556; + B 8 8 3132 556; + B 8 8 3148 556; + B 8 8 3164 556; + B 8 8 3180 556; + B 8 8 3196 556; + B 8 8 3212 556; + B 8 8 3228 556; + B 8 8 3244 556; + B 8 8 3260 556; + B 8 8 3276 556; + B 8 8 3292 556; + B 8 8 3308 556; + B 8 8 3324 556; + B 8 8 3340 556; + B 8 8 3356 556; + B 8 8 3372 556; + B 8 8 3388 556; + B 8 8 3404 556; + B 8 8 3420 556; + B 8 8 3436 556; + B 8 8 3452 556; + B 8 8 3468 556; + B 8 8 3484 556; + B 8 8 3500 556; + B 8 8 3516 556; + B 8 8 3532 556; + B 8 8 3548 556; + B 8 8 3564 556; + B 8 8 3580 556; + B 8 8 3596 556; + B 8 8 3612 556; + B 8 8 3628 556; + B 8 8 3644 556; + B 8 8 3660 556; + B 8 8 3676 556; + B 8 8 3692 556; + B 8 8 3708 556; + B 8 8 3724 556; + B 8 8 3740 556; + B 8 8 3756 556; + B 8 8 3772 556; + B 8 8 3788 556; + B 8 8 3804 556; + B 8 8 3820 556; + B 8 8 3836 556; + B 8 8 3852 556; + B 8 8 3868 556; + B 8 8 3884 556; + B 8 8 3900 556; + B 8 8 3916 556; + B 8 8 3932 556; + B 8 8 3948 556; + B 8 8 3964 556; + B 8 8 3980 556; + B 8 8 3996 556; + B 8 8 4012 556; + B 8 8 4028 556; + B 8 8 4044 556; + B 8 8 4060 556; + B 8 8 4076 556; + B 8 8 4092 556; + B 8 8 4108 556; + B 8 8 4124 556; + B 8 8 4140 556; + B 8 8 4156 556; + B 8 8 4172 556; + B 8 8 4264 556; + B 8 8 4668 556; + B 8 8 4692 556; + B 8 8 4708 556; + B 8 8 4724 556; + B 8 8 4740 556; + B 8 8 4756 556; + B 8 8 4772 556; + B 8 8 4788 556; + B 8 8 4804 556; + B 8 8 4820 556; + B 8 8 4836 556; + B 8 8 4852 556; + B 8 8 4868 556; + B 8 8 4884 556; + B 8 8 4900 556; + B 8 8 4916 556; + B 8 8 4932 556; + B 8 8 4948 556; + B 8 8 4964 556; + B 8 8 4980 556; + B 8 8 4996 556; + B 8 8 5012 556; + B 8 8 5028 556; + B 8 8 5044 556; + B 8 8 5060 556; + B 8 8 5076 556; + B 8 8 5092 556; + B 8 8 5460 552; + B 8 8 5484 556; + B 8 8 5500 556; + B 8 8 5516 556; + B 8 8 5532 556; + B 8 8 5548 556; + B 8 8 5564 556; + B 8 8 5580 556; + B 8 8 5596 556; + B 8 8 5612 556; + B 8 8 5628 556; + B 8 8 5644 556; + B 8 8 5660 556; + B 8 8 5676 556; + B 8 8 5692 556; + B 8 8 5716 556; + B 8 8 1060 538; + B 8 8 1608 538; + B 8 8 2392 540; + B 8 8 2776 538; + B 8 8 1228 530; + B 8 8 4268 536; + B 8 8 4668 540; + B 8 8 5460 536; + B 8 8 5716 540; + B 8 8 1060 522; + B 8 8 1608 522; + B 8 8 2392 524; + B 8 8 2776 522; + B 8 8 348 506; + B 8 8 370 508; + B 8 8 386 508; + B 8 8 402 508; + B 8 8 418 508; + B 8 8 510 508; + B 8 8 1228 514; + B 8 8 4268 520; + B 8 8 4668 524; + B 8 8 5100 528; + B 8 8 5460 520; + B 8 8 5716 524; + B 8 8 1060 506; + B 8 8 1608 506; + B 8 8 2392 508; + B 8 8 2776 506; + B 8 8 1228 498; + B 8 8 4268 504; + B 8 8 4668 508; + B 8 8 5100 512; + B 8 8 5460 504; + B 8 8 5716 508; + B 8 8 348 490; + B 8 8 1060 490; + B 8 8 1608 490; + B 8 8 2392 492; + B 8 8 2776 490; + B 8 8 516 482; + B 8 8 1228 482; + B 8 8 4268 488; + B 8 8 4668 492; + B 8 8 5100 496; + B 8 8 5460 488; + B 8 8 5716 492; + B 8 8 348 474; + B 8 8 1060 474; + B 8 8 1608 474; + B 8 8 2392 476; + B 8 8 2776 474; + B 8 8 516 466; + B 8 8 1228 466; + B 8 8 4268 472; + B 8 8 4668 476; + B 8 8 5100 480; + B 8 8 5460 472; + B 8 8 5716 476; + B 8 8 348 458; + B 8 8 1060 458; + B 8 8 1608 458; + B 8 8 2392 460; + B 8 8 2776 458; + B 8 8 516 450; + B 8 8 1228 450; + B 8 8 4268 456; + B 8 8 4668 460; + B 8 8 5100 464; + B 8 8 5460 456; + B 8 8 5716 460; + B 8 8 348 442; + B 8 8 1060 442; + B 8 8 1608 442; + B 8 8 2392 444; + B 8 8 2776 442; + B 8 8 516 434; + B 8 8 1228 434; + B 8 8 4268 440; + B 8 8 4668 444; + B 8 8 5100 448; + B 8 8 5460 440; + B 8 8 5716 444; + B 8 8 348 426; + B 8 8 1060 426; + B 8 8 1608 426; + B 8 8 2392 428; + B 8 8 2776 426; + B 8 8 4268 424; + B 8 8 4668 428; + B 8 8 5100 432; + B 8 8 5460 424; + B 8 8 5716 428; + B 8 8 350 404; + B 8 8 366 404; + B 8 8 382 404; + B 8 8 398 404; + B 8 8 414 404; + B 8 8 430 404; + B 8 8 446 404; + B 8 8 462 404; + B 8 8 478 404; + B 8 8 494 404; + B 8 8 510 404; + B 8 8 1060 410; + B 8 8 1082 408; + B 8 8 1098 408; + B 8 8 1114 408; + B 8 8 1130 408; + B 8 8 1146 408; + B 8 8 1162 408; + B 8 8 1178 408; + B 8 8 1194 408; + B 8 8 1210 408; + B 8 8 1226 408; + B 8 8 1608 410; + B 8 8 1632 408; + B 8 8 1648 408; + B 8 8 1664 408; + B 8 8 1680 408; + B 8 8 1696 408; + B 8 8 1712 408; + B 8 8 1728 408; + B 8 8 1744 408; + B 8 8 1760 408; + B 8 8 1776 408; + B 8 8 1792 408; + B 8 8 1808 408; + B 8 8 1824 408; + B 8 8 1840 408; + B 8 8 1856 408; + B 8 8 1872 408; + B 8 8 1888 408; + B 8 8 1904 408; + B 8 8 1920 408; + B 8 8 1936 408; + B 8 8 1952 408; + B 8 8 1968 408; + B 8 8 1984 408; + B 8 8 2000 408; + B 8 8 2016 408; + B 8 8 2032 408; + B 8 8 2048 408; + B 8 8 2064 408; + B 8 8 2080 408; + B 8 8 2096 408; + B 8 8 2112 408; + B 8 8 2128 408; + B 8 8 2144 408; + B 8 8 2160 408; + B 8 8 2176 408; + B 8 8 2192 408; + B 8 8 2208 408; + B 8 8 2224 408; + B 8 8 2240 408; + B 8 8 2256 408; + B 8 8 2272 408; + B 8 8 2288 408; + B 8 8 2386 408; + B 8 8 2776 410; + B 8 8 2800 408; + B 8 8 2816 408; + B 8 8 2832 408; + B 8 8 2848 408; + B 8 8 2864 408; + B 8 8 2880 408; + B 8 8 2896 408; + B 8 8 2912 408; + B 8 8 2928 408; + B 8 8 2944 408; + B 8 8 2960 408; + B 8 8 2976 408; + B 8 8 2992 408; + B 8 8 3008 408; + B 8 8 3024 408; + B 8 8 3040 408; + B 8 8 3056 408; + B 8 8 3072 408; + B 8 8 3088 408; + B 8 8 3104 408; + B 8 8 3120 408; + B 8 8 3136 408; + B 8 8 3152 408; + B 8 8 3168 408; + B 8 8 3184 408; + B 8 8 3200 408; + B 8 8 3216 408; + B 8 8 3232 408; + B 8 8 3248 408; + B 8 8 3264 408; + B 8 8 3280 408; + B 8 8 3296 408; + B 8 8 3312 408; + B 8 8 3328 408; + B 8 8 3344 408; + B 8 8 3360 408; + B 8 8 3376 408; + B 8 8 3392 408; + B 8 8 3408 408; + B 8 8 3424 408; + B 8 8 3440 408; + B 8 8 3456 408; + B 8 8 3472 408; + B 8 8 3488 408; + B 8 8 3504 408; + B 8 8 3520 408; + B 8 8 3536 408; + B 8 8 3552 408; + B 8 8 3568 408; + B 8 8 3584 408; + B 8 8 3600 408; + B 8 8 3616 408; + B 8 8 3632 408; + B 8 8 3648 408; + B 8 8 3664 408; + B 8 8 3680 408; + B 8 8 3696 408; + B 8 8 3712 408; + B 8 8 3728 408; + B 8 8 3744 408; + B 8 8 3760 408; + B 8 8 3776 408; + B 8 8 3792 408; + B 8 8 3808 408; + B 8 8 3824 408; + B 8 8 3840 408; + B 8 8 3856 408; + B 8 8 3872 408; + B 8 8 3888 408; + B 8 8 3904 408; + B 8 8 3920 408; + B 8 8 3936 408; + B 8 8 3952 408; + B 8 8 3968 408; + B 8 8 3984 408; + B 8 8 4000 408; + B 8 8 4016 408; + B 8 8 4032 408; + B 8 8 4048 408; + B 8 8 4064 408; + B 8 8 4080 408; + B 8 8 4096 408; + B 8 8 4112 408; + B 8 8 4128 408; + B 8 8 4144 408; + B 8 8 4160 408; + B 8 8 4176 408; + B 8 8 4192 408; + B 8 8 4208 408; + B 8 8 4224 408; + B 8 8 4240 408; + B 8 8 4268 408; + B 8 8 4672 408; + B 8 8 4764 408; + B 8 8 4780 408; + B 8 8 4796 408; + B 8 8 4812 408; + B 8 8 4828 408; + B 8 8 4844 408; + B 8 8 4860 408; + B 8 8 4876 408; + B 8 8 4892 408; + B 8 8 4908 408; + B 8 8 4924 408; + B 8 8 4940 408; + B 8 8 4956 408; + B 8 8 4972 408; + B 8 8 4988 408; + B 8 8 5004 408; + B 8 8 5020 408; + B 8 8 5036 408; + B 8 8 5052 408; + B 8 8 5068 408; + B 8 8 5084 408; + B 8 8 5100 408; + B 8 8 5460 408; + B 8 8 5486 408; + B 8 8 5502 408; + B 8 8 5518 408; + B 8 8 5534 408; + B 8 8 5550 408; + B 8 8 5566 408; + B 8 8 5582 408; + B 8 8 5598 408; + B 8 8 5614 408; + B 8 8 5710 408; +L CBA; + B 112 48 432 456; + B 112 92 1144 482; + B 728 92 2000 482; + B 1436 92 3522 482; + B 376 92 4884 482; + B 200 92 5588 482; +L CSN; + B 208 40 1144 556; + B 208 40 432 508; + B 40 64 348 456; + B 32 32 432 456; + B 40 64 516 456; + B 208 40 432 404; + B 40 108 1060 482; + B 32 32 1144 504; + B 32 32 1144 460; + B 40 108 1228 482; + B 208 40 1144 408; + B 824 40 2000 556; + B 40 108 1608 482; + B 32 32 1692 504; + B 32 32 1780 504; + B 32 32 1868 504; + B 32 32 1956 504; + B 32 32 2044 504; + B 32 32 2132 504; + B 32 32 2220 504; + B 32 32 2308 504; + B 32 32 1692 460; + B 32 32 1780 460; + B 32 32 1868 460; + B 32 32 1956 460; + B 32 32 2044 460; + B 32 32 2132 460; + B 32 32 2220 460; + B 32 32 2308 460; + B 40 108 2392 482; + B 824 40 2000 408; + B 1532 40 3522 556; + B 40 108 2776 482; + B 32 32 2860 504; + B 32 32 2948 504; + B 32 32 3036 504; + B 32 32 3124 504; + B 32 32 3212 504; + B 32 32 3300 504; + B 32 32 3388 504; + B 32 32 3476 504; + B 32 32 3564 504; + B 32 32 3652 504; + B 32 32 3740 504; + B 32 32 3828 504; + B 32 32 3920 504; + B 32 32 4008 504; + B 32 32 4096 504; + B 32 32 4184 504; + B 32 32 2860 460; + B 32 32 2948 460; + B 32 32 3036 460; + B 32 32 3124 460; + B 32 32 3212 460; + B 32 32 3300 460; + B 32 32 3388 460; + B 32 32 3476 460; + B 32 32 3564 460; + B 32 32 3652 460; + B 32 32 3740 460; + B 32 32 3828 460; + B 32 32 3920 460; + B 32 32 4008 460; + B 32 32 4096 460; + B 32 32 4184 460; + B 40 108 4268 482; + B 1532 40 3522 408; + B 472 40 4884 556; + B 40 108 4668 482; + B 32 32 4752 504; + B 32 32 4840 504; + B 32 32 4928 504; + B 32 32 5016 504; + B 32 32 4752 460; + B 32 32 4840 460; + B 32 32 4928 460; + B 32 32 5016 460; + B 40 108 5100 482; + B 472 40 4884 408; + B 296 40 5588 556; + B 40 108 5460 482; + B 32 32 5544 504; + B 32 32 5632 504; + B 32 32 5544 460; + B 32 32 5632 460; + B 40 108 5716 482; + B 296 40 5588 408; +L CSP; + B 24 24 388 456; + B 24 24 476 456; + B 24 56 1100 480; + B 24 56 1188 480; + B 24 56 1648 480; + B 24 56 1736 480; + B 24 56 1824 480; + B 24 56 1912 480; + B 24 56 2000 480; + B 24 56 2088 480; + B 24 56 2176 480; + B 24 56 2264 480; + B 24 56 2352 480; + B 24 56 2816 480; + B 24 56 2904 480; + B 24 56 2992 480; + B 24 56 3080 480; + B 24 56 3168 480; + B 24 56 3256 480; + B 24 56 3344 480; + B 24 56 3432 480; + B 24 56 3520 480; + B 24 56 3608 480; + B 24 56 3696 480; + B 24 56 3784 480; + B 24 56 3872 480; + B 24 56 3964 480; + B 24 56 4052 480; + B 24 56 4140 480; + B 24 56 4228 480; + B 24 56 4708 480; + B 24 56 4796 480; + B 24 56 4884 480; + B 24 56 4972 480; + B 24 56 5060 480; + B 24 56 5500 480; + B 24 56 5588 480; + B 24 56 5676 480; +94 south_8 5648 388 CMF; +94 south_9 5676 388 CMF; +94 south_6 4708 388 CMF; +94 south_7 4736 388 CMF; +94 south_5 3512 388 CMF; +94 south_3 2324 388 CMF; +94 south_4 2352 388 CMF; +94 south_2 1228 388 CMF; +94 south_1 484 388 CMF; +94 north_3 1160 576 CMF; +94 north_4 1188 576 CMF; +94 north_5 2392 576 CMF; +94 north_6 4200 576 CMF; +94 north_7 4228 576 CMF; +94 north_8 4788 576 CMF; +94 north_9 5436 576 CMF; +94 north_2 648 576 CMF; +94 north_1 312 576 CMF; +DF; +C 1; +End diff --git a/scmos/examples/bipolar/npn_array.mag b/scmos/examples/bipolar/npn_array.mag new file mode 100644 index 00000000..ea26e496 --- /dev/null +++ b/scmos/examples/bipolar/npn_array.mag @@ -0,0 +1,1083 @@ +magic +tech scmos +timestamp 716915316 +<< nwell >> +rect 84 -3742 132 -3710 +rect 262 -3741 310 -3698 +rect 399 -3741 601 -3698 +rect 691 -3741 1070 -3698 +rect 1164 -3741 1278 -3698 +rect 1362 -3741 1432 -3698 +<< metal1 >> +rect -14 -3594 1534 -3586 +rect -14 -3846 -6 -3594 +rect 0 -3603 80 -3600 +rect 0 -3677 3 -3603 +rect 77 -3677 80 -3603 +rect 114 -3616 125 -3594 +rect 118 -3620 121 -3616 +rect 114 -3623 125 -3620 +rect 118 -3627 121 -3623 +rect 114 -3630 125 -3627 +rect 118 -3634 121 -3630 +rect 160 -3603 240 -3600 +rect 0 -3680 80 -3677 +rect 76 -3697 80 -3680 +rect 160 -3677 163 -3603 +rect 237 -3677 240 -3603 +rect 160 -3680 240 -3677 +rect 320 -3603 400 -3600 +rect 320 -3677 323 -3603 +rect 397 -3677 400 -3603 +rect 434 -3616 445 -3594 +rect 438 -3620 441 -3616 +rect 434 -3623 445 -3620 +rect 438 -3627 441 -3623 +rect 434 -3630 445 -3627 +rect 438 -3634 441 -3630 +rect 480 -3603 560 -3600 +rect 320 -3680 400 -3677 +rect 480 -3677 483 -3603 +rect 557 -3677 560 -3603 +rect 480 -3680 560 -3677 +rect 640 -3603 720 -3600 +rect 640 -3677 643 -3603 +rect 717 -3677 720 -3603 +rect 754 -3616 765 -3594 +rect 758 -3620 761 -3616 +rect 754 -3623 765 -3620 +rect 758 -3627 761 -3623 +rect 754 -3630 765 -3627 +rect 758 -3634 761 -3630 +rect 800 -3603 880 -3600 +rect 640 -3680 720 -3677 +rect 800 -3677 803 -3603 +rect 877 -3677 880 -3603 +rect 800 -3680 880 -3677 +rect 960 -3603 1040 -3600 +rect 960 -3677 963 -3603 +rect 1037 -3675 1040 -3603 +rect 1074 -3616 1085 -3594 +rect 1078 -3620 1081 -3616 +rect 1074 -3623 1085 -3620 +rect 1078 -3627 1081 -3623 +rect 1074 -3630 1085 -3627 +rect 1078 -3634 1081 -3630 +rect 1120 -3603 1200 -3600 +rect 1037 -3677 1060 -3675 +rect 960 -3680 1060 -3677 +rect 1120 -3677 1123 -3603 +rect 1197 -3677 1200 -3603 +rect 1120 -3680 1200 -3677 +rect 1280 -3603 1360 -3600 +rect 1280 -3677 1283 -3603 +rect 1357 -3677 1360 -3603 +rect 1394 -3616 1405 -3594 +rect 1475 -3600 1486 -3594 +rect 1398 -3620 1401 -3616 +rect 1394 -3623 1405 -3620 +rect 1398 -3627 1401 -3623 +rect 1394 -3630 1405 -3627 +rect 1398 -3634 1401 -3630 +rect 1440 -3603 1520 -3600 +rect 1280 -3680 1360 -3677 +rect 1440 -3677 1443 -3603 +rect 1517 -3677 1520 -3603 +rect 1440 -3680 1520 -3677 +rect 160 -3697 164 -3680 +rect 320 -3682 325 -3680 +rect 76 -3701 112 -3697 +rect 85 -3716 89 -3715 +rect 108 -3718 112 -3701 +rect 106 -3724 112 -3718 +rect 110 -3728 112 -3724 +rect 115 -3701 164 -3697 +rect 288 -3687 325 -3682 +rect 263 -3700 269 -3699 +rect 115 -3721 119 -3701 +rect 127 -3716 131 -3715 +rect 115 -3724 121 -3721 +rect 115 -3728 117 -3724 +rect 95 -3731 99 -3728 +rect 115 -3731 121 -3728 +rect 95 -3734 121 -3731 +rect 85 -3737 89 -3736 +rect 127 -3737 131 -3736 +rect 85 -3741 86 -3737 +rect 130 -3741 164 -3737 +rect 267 -3703 269 -3700 +rect 288 -3708 292 -3687 +rect 480 -3690 485 -3680 +rect 640 -3687 645 -3680 +rect 284 -3712 292 -3708 +rect 295 -3695 485 -3690 +rect 596 -3692 645 -3687 +rect 872 -3686 880 -3680 +rect 273 -3714 277 -3712 +rect 273 -3730 277 -3726 +rect 284 -3723 288 -3716 +rect 295 -3714 299 -3695 +rect 596 -3699 600 -3692 +rect 872 -3693 1052 -3686 +rect 302 -3703 303 -3699 +rect 307 -3703 309 -3699 +rect 295 -3730 299 -3726 +rect 273 -3733 299 -3730 +rect 305 -3706 309 -3703 +rect 305 -3736 309 -3734 +rect 267 -3740 268 -3736 +rect 308 -3740 309 -3736 +rect 400 -3700 406 -3699 +rect 404 -3703 406 -3700 +rect 594 -3703 596 -3699 +rect 410 -3709 590 -3706 +rect 410 -3714 414 -3709 +rect 410 -3727 414 -3726 +rect 421 -3723 425 -3716 +rect 432 -3714 436 -3709 +rect 432 -3727 436 -3726 +rect 443 -3723 447 -3716 +rect 454 -3714 458 -3709 +rect 454 -3727 458 -3726 +rect 465 -3723 469 -3716 +rect 476 -3714 480 -3709 +rect 476 -3727 480 -3726 +rect 487 -3723 491 -3716 +rect 498 -3714 502 -3709 +rect 498 -3727 502 -3726 +rect 509 -3723 513 -3716 +rect 520 -3714 524 -3709 +rect 520 -3727 524 -3726 +rect 531 -3723 535 -3716 +rect 542 -3714 546 -3709 +rect 542 -3727 546 -3726 +rect 553 -3723 557 -3716 +rect 564 -3714 568 -3709 +rect 564 -3727 568 -3726 +rect 575 -3723 579 -3716 +rect 421 -3730 425 -3727 +rect 443 -3730 447 -3727 +rect 465 -3730 469 -3727 +rect 487 -3730 491 -3727 +rect 509 -3730 513 -3727 +rect 531 -3730 535 -3727 +rect 553 -3730 557 -3727 +rect 575 -3730 579 -3727 +rect 586 -3714 590 -3709 +rect 421 -3733 583 -3730 +rect 404 -3740 406 -3736 +rect 574 -3740 575 -3736 +rect 160 -3760 164 -3741 +rect 305 -3748 309 -3740 +rect 305 -3753 400 -3748 +rect 395 -3760 400 -3753 +rect 579 -3755 583 -3733 +rect 556 -3760 583 -3755 +rect 586 -3755 590 -3726 +rect 596 -3736 600 -3735 +rect 593 -3740 594 -3736 +rect 598 -3740 600 -3736 +rect 692 -3700 697 -3699 +rect 696 -3703 697 -3700 +rect 1048 -3706 1052 -3693 +rect 713 -3709 1052 -3706 +rect 713 -3712 717 -3709 +rect 735 -3712 739 -3709 +rect 757 -3712 761 -3709 +rect 779 -3712 783 -3709 +rect 801 -3712 805 -3709 +rect 823 -3712 827 -3709 +rect 845 -3712 849 -3709 +rect 867 -3712 871 -3709 +rect 889 -3712 893 -3709 +rect 911 -3712 915 -3709 +rect 933 -3712 937 -3709 +rect 955 -3712 959 -3709 +rect 978 -3712 982 -3709 +rect 1000 -3712 1004 -3709 +rect 1022 -3712 1026 -3709 +rect 1044 -3712 1048 -3709 +rect 702 -3714 706 -3712 +rect 702 -3730 706 -3726 +rect 713 -3723 717 -3716 +rect 724 -3714 728 -3712 +rect 724 -3730 728 -3726 +rect 735 -3723 739 -3716 +rect 746 -3714 750 -3712 +rect 746 -3730 750 -3726 +rect 757 -3723 761 -3716 +rect 768 -3714 772 -3712 +rect 768 -3730 772 -3726 +rect 779 -3723 783 -3716 +rect 790 -3714 794 -3712 +rect 790 -3730 794 -3726 +rect 801 -3723 805 -3716 +rect 812 -3714 816 -3712 +rect 812 -3730 816 -3726 +rect 823 -3723 827 -3716 +rect 834 -3714 838 -3712 +rect 834 -3730 838 -3726 +rect 845 -3723 849 -3716 +rect 856 -3714 860 -3712 +rect 856 -3730 860 -3726 +rect 867 -3723 871 -3716 +rect 878 -3714 882 -3712 +rect 878 -3730 882 -3726 +rect 889 -3723 893 -3716 +rect 900 -3714 904 -3712 +rect 900 -3730 904 -3726 +rect 911 -3723 915 -3716 +rect 922 -3714 926 -3712 +rect 922 -3730 926 -3726 +rect 933 -3723 937 -3716 +rect 944 -3714 948 -3712 +rect 944 -3730 948 -3726 +rect 955 -3723 959 -3716 +rect 966 -3714 970 -3712 +rect 966 -3730 970 -3726 +rect 978 -3723 982 -3716 +rect 989 -3714 993 -3712 +rect 989 -3730 993 -3726 +rect 1000 -3723 1004 -3716 +rect 1011 -3714 1015 -3712 +rect 1011 -3730 1015 -3726 +rect 1022 -3723 1026 -3716 +rect 1033 -3714 1037 -3712 +rect 1033 -3730 1037 -3726 +rect 1044 -3723 1048 -3716 +rect 1055 -3714 1060 -3680 +rect 1195 -3699 1200 -3680 +rect 1355 -3699 1360 -3680 +rect 1063 -3703 1064 -3699 +rect 1068 -3703 1069 -3699 +rect 1059 -3726 1060 -3714 +rect 1055 -3730 1060 -3726 +rect 702 -3733 1060 -3730 +rect 1065 -3704 1069 -3703 +rect 696 -3740 698 -3736 +rect 1062 -3740 1065 -3736 +rect 1169 -3703 1171 -3699 +rect 1275 -3703 1277 -3699 +rect 1273 -3706 1277 -3703 +rect 1355 -3700 1369 -3699 +rect 1355 -3705 1363 -3700 +rect 1165 -3736 1169 -3735 +rect 1175 -3709 1267 -3706 +rect 1175 -3714 1179 -3709 +rect 1165 -3740 1166 -3736 +rect 1170 -3740 1172 -3736 +rect 586 -3760 644 -3755 +rect 872 -3760 880 -3740 +rect 1175 -3749 1179 -3726 +rect 1186 -3723 1190 -3716 +rect 1197 -3714 1201 -3709 +rect 1197 -3727 1201 -3726 +rect 1208 -3723 1212 -3716 +rect 1219 -3714 1223 -3709 +rect 1219 -3727 1223 -3726 +rect 1230 -3723 1234 -3716 +rect 1241 -3714 1245 -3709 +rect 1241 -3727 1245 -3726 +rect 1252 -3723 1256 -3716 +rect 1263 -3714 1267 -3709 +rect 1263 -3727 1267 -3726 +rect 1186 -3730 1190 -3727 +rect 1208 -3730 1212 -3727 +rect 1230 -3730 1234 -3727 +rect 1252 -3730 1256 -3727 +rect 1035 -3754 1179 -3749 +rect 1182 -3733 1256 -3730 +rect 1035 -3760 1040 -3754 +rect 1182 -3760 1186 -3733 +rect 1273 -3736 1277 -3734 +rect 1367 -3703 1369 -3700 +rect 1425 -3703 1427 -3699 +rect 1373 -3709 1421 -3706 +rect 1373 -3714 1377 -3709 +rect 1373 -3727 1377 -3726 +rect 1384 -3723 1388 -3716 +rect 1395 -3714 1399 -3709 +rect 1395 -3727 1399 -3726 +rect 1406 -3723 1410 -3716 +rect 1384 -3730 1388 -3727 +rect 1406 -3730 1410 -3727 +rect 1417 -3714 1421 -3709 +rect 1384 -3733 1414 -3730 +rect 1367 -3740 1369 -3736 +rect 1405 -3740 1407 -3736 +rect 1410 -3749 1414 -3733 +rect 1355 -3753 1414 -3749 +rect 1417 -3749 1421 -3726 +rect 1427 -3736 1431 -3735 +rect 1424 -3740 1425 -3736 +rect 1429 -3740 1431 -3736 +rect 1417 -3753 1445 -3749 +rect 1355 -3760 1360 -3753 +rect 0 -3763 80 -3760 +rect 0 -3837 3 -3763 +rect 77 -3837 80 -3763 +rect 0 -3840 80 -3837 +rect 160 -3763 240 -3760 +rect 160 -3837 163 -3763 +rect 237 -3837 240 -3763 +rect 320 -3763 400 -3760 +rect 160 -3840 240 -3837 +rect 278 -3810 281 -3806 +rect 274 -3813 285 -3810 +rect 278 -3817 281 -3813 +rect 274 -3820 285 -3817 +rect 278 -3824 281 -3820 +rect 35 -3846 46 -3840 +rect 274 -3846 285 -3824 +rect 320 -3837 323 -3763 +rect 397 -3837 400 -3763 +rect 320 -3840 400 -3837 +rect 480 -3763 560 -3760 +rect 480 -3837 483 -3763 +rect 557 -3837 560 -3763 +rect 640 -3763 720 -3760 +rect 480 -3840 560 -3837 +rect 598 -3810 601 -3806 +rect 594 -3813 605 -3810 +rect 598 -3817 601 -3813 +rect 594 -3820 605 -3817 +rect 598 -3824 601 -3820 +rect 594 -3846 605 -3824 +rect 640 -3837 643 -3763 +rect 717 -3837 720 -3763 +rect 640 -3840 720 -3837 +rect 800 -3763 880 -3760 +rect 800 -3837 803 -3763 +rect 877 -3837 880 -3763 +rect 960 -3763 1040 -3760 +rect 800 -3840 880 -3837 +rect 918 -3810 921 -3806 +rect 914 -3813 925 -3810 +rect 918 -3817 921 -3813 +rect 914 -3820 925 -3817 +rect 918 -3824 921 -3820 +rect 914 -3846 925 -3824 +rect 960 -3837 963 -3763 +rect 1037 -3837 1040 -3763 +rect 960 -3840 1040 -3837 +rect 1120 -3763 1200 -3760 +rect 1120 -3837 1123 -3763 +rect 1197 -3837 1200 -3763 +rect 1280 -3763 1360 -3760 +rect 1120 -3840 1200 -3837 +rect 1238 -3810 1241 -3806 +rect 1234 -3813 1245 -3810 +rect 1238 -3817 1241 -3813 +rect 1234 -3820 1245 -3817 +rect 1238 -3824 1241 -3820 +rect 1234 -3846 1245 -3824 +rect 1280 -3837 1283 -3763 +rect 1357 -3837 1360 -3763 +rect 1280 -3840 1360 -3837 +rect 1440 -3760 1445 -3753 +rect 1440 -3763 1520 -3760 +rect 1440 -3837 1443 -3763 +rect 1517 -3837 1520 -3763 +rect 1440 -3840 1520 -3837 +rect 1526 -3846 1534 -3594 +rect -14 -3854 1534 -3846 +<< metal2 >> +rect 0 -3603 80 -3600 +rect 0 -3677 3 -3603 +rect 77 -3677 80 -3603 +rect 0 -3680 80 -3677 +rect 160 -3603 240 -3600 +rect 160 -3677 163 -3603 +rect 237 -3677 240 -3603 +rect 160 -3680 240 -3677 +rect 320 -3603 400 -3600 +rect 320 -3677 323 -3603 +rect 397 -3677 400 -3603 +rect 320 -3680 400 -3677 +rect 480 -3603 560 -3600 +rect 480 -3677 483 -3603 +rect 557 -3677 560 -3603 +rect 480 -3680 560 -3677 +rect 640 -3603 720 -3600 +rect 640 -3677 643 -3603 +rect 717 -3677 720 -3603 +rect 640 -3680 720 -3677 +rect 800 -3603 880 -3600 +rect 800 -3677 803 -3603 +rect 877 -3677 880 -3603 +rect 800 -3680 880 -3677 +rect 960 -3603 1040 -3600 +rect 960 -3677 963 -3603 +rect 1037 -3677 1040 -3603 +rect 960 -3680 1040 -3677 +rect 1120 -3603 1200 -3600 +rect 1120 -3677 1123 -3603 +rect 1197 -3677 1200 -3603 +rect 1120 -3680 1200 -3677 +rect 1280 -3603 1360 -3600 +rect 1280 -3677 1283 -3603 +rect 1357 -3677 1360 -3603 +rect 1280 -3680 1360 -3677 +rect 1440 -3603 1520 -3600 +rect 1440 -3677 1443 -3603 +rect 1517 -3677 1520 -3603 +rect 1440 -3680 1520 -3677 +rect 0 -3763 80 -3760 +rect 0 -3837 3 -3763 +rect 77 -3837 80 -3763 +rect 0 -3840 80 -3837 +rect 160 -3763 240 -3760 +rect 160 -3837 163 -3763 +rect 237 -3837 240 -3763 +rect 160 -3840 240 -3837 +rect 320 -3763 400 -3760 +rect 320 -3837 323 -3763 +rect 397 -3837 400 -3763 +rect 320 -3840 400 -3837 +rect 480 -3763 560 -3760 +rect 480 -3837 483 -3763 +rect 557 -3837 560 -3763 +rect 480 -3840 560 -3837 +rect 640 -3763 720 -3760 +rect 640 -3837 643 -3763 +rect 717 -3837 720 -3763 +rect 640 -3840 720 -3837 +rect 800 -3763 880 -3760 +rect 800 -3837 803 -3763 +rect 877 -3837 880 -3763 +rect 800 -3840 880 -3837 +rect 960 -3763 1040 -3760 +rect 960 -3837 963 -3763 +rect 1037 -3837 1040 -3763 +rect 960 -3840 1040 -3837 +rect 1120 -3763 1200 -3760 +rect 1120 -3837 1123 -3763 +rect 1197 -3837 1200 -3763 +rect 1120 -3840 1200 -3837 +rect 1280 -3763 1360 -3760 +rect 1280 -3837 1283 -3763 +rect 1357 -3837 1360 -3763 +rect 1280 -3840 1360 -3837 +rect 1440 -3763 1520 -3760 +rect 1440 -3837 1443 -3763 +rect 1517 -3837 1520 -3763 +rect 1440 -3840 1520 -3837 +<< collector >> +rect 262 -3699 310 -3698 +rect 262 -3700 269 -3699 +rect 84 -3711 132 -3710 +rect 84 -3715 85 -3711 +rect 105 -3715 122 -3711 +rect 131 -3715 132 -3711 +rect 84 -3716 132 -3715 +rect 84 -3736 85 -3716 +rect 89 -3736 90 -3716 +rect 126 -3736 127 -3716 +rect 131 -3736 132 -3716 +rect 84 -3737 132 -3736 +rect 84 -3741 86 -3737 +rect 130 -3741 132 -3737 +rect 262 -3740 263 -3700 +rect 267 -3703 269 -3700 +rect 285 -3703 303 -3699 +rect 307 -3703 310 -3699 +rect 267 -3704 310 -3703 +rect 267 -3735 268 -3704 +rect 304 -3706 310 -3704 +rect 304 -3734 305 -3706 +rect 309 -3734 310 -3706 +rect 304 -3735 310 -3734 +rect 267 -3736 310 -3735 +rect 267 -3740 268 -3736 +rect 308 -3740 310 -3736 +rect 262 -3741 310 -3740 +rect 399 -3699 601 -3698 +rect 399 -3700 406 -3699 +rect 399 -3740 400 -3700 +rect 404 -3703 406 -3700 +rect 594 -3703 596 -3699 +rect 404 -3704 596 -3703 +rect 404 -3735 405 -3704 +rect 595 -3735 596 -3704 +rect 600 -3735 601 -3699 +rect 404 -3736 601 -3735 +rect 404 -3740 406 -3736 +rect 574 -3740 594 -3736 +rect 598 -3740 601 -3736 +rect 399 -3741 601 -3740 +rect 691 -3699 1070 -3698 +rect 691 -3700 697 -3699 +rect 691 -3740 692 -3700 +rect 696 -3703 697 -3700 +rect 1045 -3703 1064 -3699 +rect 1068 -3703 1070 -3699 +rect 696 -3704 1070 -3703 +rect 696 -3735 697 -3704 +rect 1064 -3735 1065 -3704 +rect 696 -3736 1065 -3735 +rect 696 -3740 698 -3736 +rect 1062 -3740 1065 -3736 +rect 1069 -3740 1070 -3704 +rect 691 -3741 1070 -3740 +rect 1164 -3699 1278 -3698 +rect 1164 -3735 1165 -3699 +rect 1169 -3703 1171 -3699 +rect 1275 -3703 1278 -3699 +rect 1169 -3704 1278 -3703 +rect 1169 -3735 1170 -3704 +rect 1272 -3706 1278 -3704 +rect 1272 -3734 1273 -3706 +rect 1277 -3734 1278 -3706 +rect 1272 -3735 1278 -3734 +rect 1164 -3736 1278 -3735 +rect 1164 -3740 1166 -3736 +rect 1170 -3740 1189 -3736 +rect 1277 -3740 1278 -3736 +rect 1164 -3741 1278 -3740 +rect 1362 -3699 1432 -3698 +rect 1362 -3700 1369 -3699 +rect 1362 -3740 1363 -3700 +rect 1367 -3703 1369 -3700 +rect 1425 -3703 1427 -3699 +rect 1367 -3704 1427 -3703 +rect 1367 -3735 1368 -3704 +rect 1426 -3735 1427 -3704 +rect 1431 -3735 1432 -3699 +rect 1367 -3736 1432 -3735 +rect 1367 -3740 1369 -3736 +rect 1405 -3740 1425 -3736 +rect 1429 -3740 1432 -3736 +rect 1362 -3741 1432 -3740 +rect 84 -3742 132 -3741 +<< pbase >> +rect 94 -3724 122 -3720 +rect 94 -3728 95 -3724 +rect 99 -3728 106 -3724 +rect 110 -3728 117 -3724 +rect 121 -3728 122 -3724 +rect 94 -3732 122 -3728 +rect 272 -3712 300 -3708 +rect 272 -3714 284 -3712 +rect 272 -3726 273 -3714 +rect 277 -3716 284 -3714 +rect 288 -3714 300 -3712 +rect 288 -3716 295 -3714 +rect 277 -3723 295 -3716 +rect 277 -3726 284 -3723 +rect 272 -3727 284 -3726 +rect 288 -3726 295 -3723 +rect 299 -3726 300 -3714 +rect 288 -3727 300 -3726 +rect 272 -3731 300 -3727 +rect 409 -3712 591 -3708 +rect 409 -3714 421 -3712 +rect 409 -3726 410 -3714 +rect 414 -3716 421 -3714 +rect 425 -3714 443 -3712 +rect 425 -3716 432 -3714 +rect 414 -3723 432 -3716 +rect 414 -3726 421 -3723 +rect 409 -3727 421 -3726 +rect 425 -3726 432 -3723 +rect 436 -3716 443 -3714 +rect 447 -3714 465 -3712 +rect 447 -3716 454 -3714 +rect 436 -3723 454 -3716 +rect 436 -3726 443 -3723 +rect 425 -3727 443 -3726 +rect 447 -3726 454 -3723 +rect 458 -3716 465 -3714 +rect 469 -3714 487 -3712 +rect 469 -3716 476 -3714 +rect 458 -3723 476 -3716 +rect 458 -3726 465 -3723 +rect 447 -3727 465 -3726 +rect 469 -3726 476 -3723 +rect 480 -3716 487 -3714 +rect 491 -3714 509 -3712 +rect 491 -3716 498 -3714 +rect 480 -3723 498 -3716 +rect 480 -3726 487 -3723 +rect 469 -3727 487 -3726 +rect 491 -3726 498 -3723 +rect 502 -3716 509 -3714 +rect 513 -3714 531 -3712 +rect 513 -3716 520 -3714 +rect 502 -3723 520 -3716 +rect 502 -3726 509 -3723 +rect 491 -3727 509 -3726 +rect 513 -3726 520 -3723 +rect 524 -3716 531 -3714 +rect 535 -3714 553 -3712 +rect 535 -3716 542 -3714 +rect 524 -3723 542 -3716 +rect 524 -3726 531 -3723 +rect 513 -3727 531 -3726 +rect 535 -3726 542 -3723 +rect 546 -3716 553 -3714 +rect 557 -3714 575 -3712 +rect 557 -3716 564 -3714 +rect 546 -3723 564 -3716 +rect 546 -3726 553 -3723 +rect 535 -3727 553 -3726 +rect 557 -3726 564 -3723 +rect 568 -3716 575 -3714 +rect 579 -3714 591 -3712 +rect 579 -3716 586 -3714 +rect 568 -3723 586 -3716 +rect 568 -3726 575 -3723 +rect 557 -3727 575 -3726 +rect 579 -3726 586 -3723 +rect 590 -3726 591 -3714 +rect 579 -3727 591 -3726 +rect 409 -3731 591 -3727 +rect 701 -3712 1060 -3708 +rect 701 -3714 713 -3712 +rect 701 -3726 702 -3714 +rect 706 -3716 713 -3714 +rect 717 -3714 735 -3712 +rect 717 -3716 724 -3714 +rect 706 -3723 724 -3716 +rect 706 -3726 713 -3723 +rect 701 -3727 713 -3726 +rect 717 -3726 724 -3723 +rect 728 -3716 735 -3714 +rect 739 -3714 757 -3712 +rect 739 -3716 746 -3714 +rect 728 -3723 746 -3716 +rect 728 -3726 735 -3723 +rect 717 -3727 735 -3726 +rect 739 -3726 746 -3723 +rect 750 -3716 757 -3714 +rect 761 -3714 779 -3712 +rect 761 -3716 768 -3714 +rect 750 -3723 768 -3716 +rect 750 -3726 757 -3723 +rect 739 -3727 757 -3726 +rect 761 -3726 768 -3723 +rect 772 -3716 779 -3714 +rect 783 -3714 801 -3712 +rect 783 -3716 790 -3714 +rect 772 -3723 790 -3716 +rect 772 -3726 779 -3723 +rect 761 -3727 779 -3726 +rect 783 -3726 790 -3723 +rect 794 -3716 801 -3714 +rect 805 -3714 823 -3712 +rect 805 -3716 812 -3714 +rect 794 -3723 812 -3716 +rect 794 -3726 801 -3723 +rect 783 -3727 801 -3726 +rect 805 -3726 812 -3723 +rect 816 -3716 823 -3714 +rect 827 -3714 845 -3712 +rect 827 -3716 834 -3714 +rect 816 -3723 834 -3716 +rect 816 -3726 823 -3723 +rect 805 -3727 823 -3726 +rect 827 -3726 834 -3723 +rect 838 -3716 845 -3714 +rect 849 -3714 867 -3712 +rect 849 -3716 856 -3714 +rect 838 -3723 856 -3716 +rect 838 -3726 845 -3723 +rect 827 -3727 845 -3726 +rect 849 -3726 856 -3723 +rect 860 -3716 867 -3714 +rect 871 -3714 889 -3712 +rect 871 -3716 878 -3714 +rect 860 -3723 878 -3716 +rect 860 -3726 867 -3723 +rect 849 -3727 867 -3726 +rect 871 -3726 878 -3723 +rect 882 -3716 889 -3714 +rect 893 -3714 911 -3712 +rect 893 -3716 900 -3714 +rect 882 -3723 900 -3716 +rect 882 -3726 889 -3723 +rect 871 -3727 889 -3726 +rect 893 -3726 900 -3723 +rect 904 -3716 911 -3714 +rect 915 -3714 933 -3712 +rect 915 -3716 922 -3714 +rect 904 -3723 922 -3716 +rect 904 -3726 911 -3723 +rect 893 -3727 911 -3726 +rect 915 -3726 922 -3723 +rect 926 -3716 933 -3714 +rect 937 -3714 955 -3712 +rect 937 -3716 944 -3714 +rect 926 -3723 944 -3716 +rect 926 -3726 933 -3723 +rect 915 -3727 933 -3726 +rect 937 -3726 944 -3723 +rect 948 -3716 955 -3714 +rect 959 -3714 978 -3712 +rect 959 -3716 966 -3714 +rect 948 -3723 966 -3716 +rect 948 -3726 955 -3723 +rect 937 -3727 955 -3726 +rect 959 -3726 966 -3723 +rect 970 -3716 978 -3714 +rect 982 -3714 1000 -3712 +rect 982 -3716 989 -3714 +rect 970 -3723 989 -3716 +rect 970 -3726 978 -3723 +rect 959 -3727 978 -3726 +rect 982 -3726 989 -3723 +rect 993 -3716 1000 -3714 +rect 1004 -3714 1022 -3712 +rect 1004 -3716 1011 -3714 +rect 993 -3723 1011 -3716 +rect 993 -3726 1000 -3723 +rect 982 -3727 1000 -3726 +rect 1004 -3726 1011 -3723 +rect 1015 -3716 1022 -3714 +rect 1026 -3714 1044 -3712 +rect 1026 -3716 1033 -3714 +rect 1015 -3723 1033 -3716 +rect 1015 -3726 1022 -3723 +rect 1004 -3727 1022 -3726 +rect 1026 -3726 1033 -3723 +rect 1037 -3716 1044 -3714 +rect 1048 -3714 1060 -3712 +rect 1048 -3716 1055 -3714 +rect 1037 -3723 1055 -3716 +rect 1037 -3726 1044 -3723 +rect 1026 -3727 1044 -3726 +rect 1048 -3726 1055 -3723 +rect 1059 -3726 1060 -3714 +rect 1048 -3727 1060 -3726 +rect 701 -3731 1060 -3727 +rect 1174 -3712 1268 -3708 +rect 1174 -3714 1186 -3712 +rect 1174 -3726 1175 -3714 +rect 1179 -3716 1186 -3714 +rect 1190 -3714 1208 -3712 +rect 1190 -3716 1197 -3714 +rect 1179 -3723 1197 -3716 +rect 1179 -3726 1186 -3723 +rect 1174 -3727 1186 -3726 +rect 1190 -3726 1197 -3723 +rect 1201 -3716 1208 -3714 +rect 1212 -3714 1230 -3712 +rect 1212 -3716 1219 -3714 +rect 1201 -3723 1219 -3716 +rect 1201 -3726 1208 -3723 +rect 1190 -3727 1208 -3726 +rect 1212 -3726 1219 -3723 +rect 1223 -3716 1230 -3714 +rect 1234 -3714 1252 -3712 +rect 1234 -3716 1241 -3714 +rect 1223 -3723 1241 -3716 +rect 1223 -3726 1230 -3723 +rect 1212 -3727 1230 -3726 +rect 1234 -3726 1241 -3723 +rect 1245 -3716 1252 -3714 +rect 1256 -3714 1268 -3712 +rect 1256 -3716 1263 -3714 +rect 1245 -3723 1263 -3716 +rect 1245 -3726 1252 -3723 +rect 1234 -3727 1252 -3726 +rect 1256 -3726 1263 -3723 +rect 1267 -3726 1268 -3714 +rect 1256 -3727 1268 -3726 +rect 1174 -3731 1268 -3727 +rect 1372 -3712 1422 -3708 +rect 1372 -3714 1384 -3712 +rect 1372 -3726 1373 -3714 +rect 1377 -3716 1384 -3714 +rect 1388 -3714 1406 -3712 +rect 1388 -3716 1395 -3714 +rect 1377 -3723 1395 -3716 +rect 1377 -3726 1384 -3723 +rect 1372 -3727 1384 -3726 +rect 1388 -3726 1395 -3723 +rect 1399 -3716 1406 -3714 +rect 1410 -3714 1422 -3712 +rect 1410 -3716 1417 -3714 +rect 1399 -3723 1417 -3716 +rect 1399 -3726 1406 -3723 +rect 1388 -3727 1406 -3726 +rect 1410 -3726 1417 -3723 +rect 1421 -3726 1422 -3714 +rect 1410 -3727 1422 -3726 +rect 1372 -3731 1422 -3727 +<< collectorcontact >> +rect 85 -3715 105 -3711 +rect 122 -3715 131 -3711 +rect 85 -3736 89 -3716 +rect 127 -3736 131 -3716 +rect 86 -3741 130 -3737 +rect 263 -3740 267 -3700 +rect 269 -3703 285 -3699 +rect 303 -3703 307 -3699 +rect 305 -3734 309 -3706 +rect 268 -3740 308 -3736 +rect 400 -3740 404 -3700 +rect 406 -3703 594 -3699 +rect 596 -3735 600 -3699 +rect 406 -3740 574 -3736 +rect 594 -3740 598 -3736 +rect 692 -3740 696 -3700 +rect 697 -3703 1045 -3699 +rect 1064 -3703 1068 -3699 +rect 698 -3740 1062 -3736 +rect 1065 -3740 1069 -3704 +rect 1165 -3735 1169 -3699 +rect 1171 -3703 1275 -3699 +rect 1273 -3734 1277 -3706 +rect 1166 -3740 1170 -3736 +rect 1189 -3740 1277 -3736 +rect 1363 -3740 1367 -3700 +rect 1369 -3703 1425 -3699 +rect 1427 -3735 1431 -3699 +rect 1369 -3740 1405 -3736 +rect 1425 -3740 1429 -3736 +<< emittercontact >> +rect 106 -3728 110 -3724 +rect 284 -3716 288 -3712 +rect 284 -3727 288 -3723 +rect 421 -3716 425 -3712 +rect 421 -3727 425 -3723 +rect 443 -3716 447 -3712 +rect 443 -3727 447 -3723 +rect 465 -3716 469 -3712 +rect 465 -3727 469 -3723 +rect 487 -3716 491 -3712 +rect 487 -3727 491 -3723 +rect 509 -3716 513 -3712 +rect 509 -3727 513 -3723 +rect 531 -3716 535 -3712 +rect 531 -3727 535 -3723 +rect 553 -3716 557 -3712 +rect 553 -3727 557 -3723 +rect 575 -3716 579 -3712 +rect 575 -3727 579 -3723 +rect 713 -3716 717 -3712 +rect 713 -3727 717 -3723 +rect 735 -3716 739 -3712 +rect 735 -3727 739 -3723 +rect 757 -3716 761 -3712 +rect 757 -3727 761 -3723 +rect 779 -3716 783 -3712 +rect 779 -3727 783 -3723 +rect 801 -3716 805 -3712 +rect 801 -3727 805 -3723 +rect 823 -3716 827 -3712 +rect 823 -3727 827 -3723 +rect 845 -3716 849 -3712 +rect 845 -3727 849 -3723 +rect 867 -3716 871 -3712 +rect 867 -3727 871 -3723 +rect 889 -3716 893 -3712 +rect 889 -3727 893 -3723 +rect 911 -3716 915 -3712 +rect 911 -3727 915 -3723 +rect 933 -3716 937 -3712 +rect 933 -3727 937 -3723 +rect 955 -3716 959 -3712 +rect 955 -3727 959 -3723 +rect 978 -3716 982 -3712 +rect 978 -3727 982 -3723 +rect 1000 -3716 1004 -3712 +rect 1000 -3727 1004 -3723 +rect 1022 -3716 1026 -3712 +rect 1022 -3727 1026 -3723 +rect 1044 -3716 1048 -3712 +rect 1044 -3727 1048 -3723 +rect 1186 -3716 1190 -3712 +rect 1186 -3727 1190 -3723 +rect 1208 -3716 1212 -3712 +rect 1208 -3727 1212 -3723 +rect 1230 -3716 1234 -3712 +rect 1230 -3727 1234 -3723 +rect 1252 -3716 1256 -3712 +rect 1252 -3727 1256 -3723 +rect 1384 -3716 1388 -3712 +rect 1384 -3727 1388 -3723 +rect 1406 -3716 1410 -3712 +rect 1406 -3727 1410 -3723 +<< pbasecontact >> +rect 95 -3728 99 -3724 +rect 117 -3728 121 -3724 +rect 273 -3726 277 -3714 +rect 295 -3726 299 -3714 +rect 410 -3726 414 -3714 +rect 432 -3726 436 -3714 +rect 454 -3726 458 -3714 +rect 476 -3726 480 -3714 +rect 498 -3726 502 -3714 +rect 520 -3726 524 -3714 +rect 542 -3726 546 -3714 +rect 564 -3726 568 -3714 +rect 586 -3726 590 -3714 +rect 702 -3726 706 -3714 +rect 724 -3726 728 -3714 +rect 746 -3726 750 -3714 +rect 768 -3726 772 -3714 +rect 790 -3726 794 -3714 +rect 812 -3726 816 -3714 +rect 834 -3726 838 -3714 +rect 856 -3726 860 -3714 +rect 878 -3726 882 -3714 +rect 900 -3726 904 -3714 +rect 922 -3726 926 -3714 +rect 944 -3726 948 -3714 +rect 966 -3726 970 -3714 +rect 989 -3726 993 -3714 +rect 1011 -3726 1015 -3714 +rect 1033 -3726 1037 -3714 +rect 1055 -3726 1059 -3714 +rect 1175 -3726 1179 -3714 +rect 1197 -3726 1201 -3714 +rect 1219 -3726 1223 -3714 +rect 1241 -3726 1245 -3714 +rect 1263 -3726 1267 -3714 +rect 1373 -3726 1377 -3714 +rect 1395 -3726 1399 -3714 +rect 1417 -3726 1421 -3714 +<< m2contact >> +rect 3 -3677 77 -3603 +rect 163 -3677 237 -3603 +rect 323 -3677 397 -3603 +rect 483 -3677 557 -3603 +rect 643 -3677 717 -3603 +rect 803 -3677 877 -3603 +rect 963 -3677 1037 -3603 +rect 1123 -3677 1197 -3603 +rect 1283 -3677 1357 -3603 +rect 1443 -3677 1517 -3603 +rect 3 -3837 77 -3763 +rect 163 -3837 237 -3763 +rect 323 -3837 397 -3763 +rect 483 -3837 557 -3763 +rect 643 -3837 717 -3763 +rect 803 -3837 877 -3763 +rect 963 -3837 1037 -3763 +rect 1123 -3837 1197 -3763 +rect 1283 -3837 1357 -3763 +rect 1443 -3837 1517 -3763 +<< psubstratepcontact >> +rect 114 -3620 118 -3616 +rect 121 -3620 125 -3616 +rect 114 -3627 118 -3623 +rect 121 -3627 125 -3623 +rect 114 -3634 118 -3630 +rect 121 -3634 125 -3630 +rect 434 -3620 438 -3616 +rect 441 -3620 445 -3616 +rect 434 -3627 438 -3623 +rect 441 -3627 445 -3623 +rect 434 -3634 438 -3630 +rect 441 -3634 445 -3630 +rect 754 -3620 758 -3616 +rect 761 -3620 765 -3616 +rect 754 -3627 758 -3623 +rect 761 -3627 765 -3623 +rect 754 -3634 758 -3630 +rect 761 -3634 765 -3630 +rect 1074 -3620 1078 -3616 +rect 1081 -3620 1085 -3616 +rect 1074 -3627 1078 -3623 +rect 1081 -3627 1085 -3623 +rect 1074 -3634 1078 -3630 +rect 1081 -3634 1085 -3630 +rect 1394 -3620 1398 -3616 +rect 1401 -3620 1405 -3616 +rect 1394 -3627 1398 -3623 +rect 1401 -3627 1405 -3623 +rect 1394 -3634 1398 -3630 +rect 1401 -3634 1405 -3630 +rect 274 -3810 278 -3806 +rect 281 -3810 285 -3806 +rect 274 -3817 278 -3813 +rect 281 -3817 285 -3813 +rect 274 -3824 278 -3820 +rect 281 -3824 285 -3820 +rect 594 -3810 598 -3806 +rect 601 -3810 605 -3806 +rect 594 -3817 598 -3813 +rect 601 -3817 605 -3813 +rect 594 -3824 598 -3820 +rect 601 -3824 605 -3820 +rect 914 -3810 918 -3806 +rect 921 -3810 925 -3806 +rect 914 -3817 918 -3813 +rect 921 -3817 925 -3813 +rect 914 -3824 918 -3820 +rect 921 -3824 925 -3820 +rect 1234 -3810 1238 -3806 +rect 1241 -3810 1245 -3806 +rect 1234 -3817 1238 -3813 +rect 1241 -3817 1245 -3813 +rect 1234 -3824 1238 -3820 +rect 1241 -3824 1245 -3820 +<< psubstratepdiff >> +rect 118 -3620 121 -3616 +rect 114 -3623 125 -3620 +rect 118 -3627 121 -3623 +rect 114 -3630 125 -3627 +rect 118 -3634 121 -3630 +rect 438 -3620 441 -3616 +rect 434 -3623 445 -3620 +rect 438 -3627 441 -3623 +rect 434 -3630 445 -3627 +rect 438 -3634 441 -3630 +rect 758 -3620 761 -3616 +rect 754 -3623 765 -3620 +rect 758 -3627 761 -3623 +rect 754 -3630 765 -3627 +rect 758 -3634 761 -3630 +rect 1078 -3620 1081 -3616 +rect 1074 -3623 1085 -3620 +rect 1078 -3627 1081 -3623 +rect 1074 -3630 1085 -3627 +rect 1078 -3634 1081 -3630 +rect 1398 -3620 1401 -3616 +rect 1394 -3623 1405 -3620 +rect 1398 -3627 1401 -3623 +rect 1394 -3630 1405 -3627 +rect 1398 -3634 1401 -3630 +rect 278 -3810 281 -3806 +rect 274 -3813 285 -3810 +rect 278 -3817 281 -3813 +rect 274 -3820 285 -3817 +rect 278 -3824 281 -3820 +rect 598 -3810 601 -3806 +rect 594 -3813 605 -3810 +rect 598 -3817 601 -3813 +rect 594 -3820 605 -3817 +rect 598 -3824 601 -3820 +rect 918 -3810 921 -3806 +rect 914 -3813 925 -3810 +rect 918 -3817 921 -3813 +rect 914 -3820 925 -3817 +rect 918 -3824 921 -3820 +rect 1238 -3810 1241 -3806 +rect 1234 -3813 1245 -3810 +rect 1238 -3817 1241 -3813 +rect 1234 -3820 1245 -3817 +rect 1238 -3824 1241 -3820 +<< glass >> +rect 3 -3677 77 -3603 +rect 163 -3677 237 -3603 +rect 323 -3677 397 -3603 +rect 483 -3677 557 -3603 +rect 643 -3677 717 -3603 +rect 803 -3677 877 -3603 +rect 963 -3677 1037 -3603 +rect 1123 -3677 1197 -3603 +rect 1283 -3677 1357 -3603 +rect 1443 -3677 1517 -3603 +rect 3 -3837 77 -3763 +rect 163 -3837 237 -3763 +rect 323 -3837 397 -3763 +rect 483 -3837 557 -3763 +rect 643 -3837 717 -3763 +rect 803 -3837 877 -3763 +rect 963 -3837 1037 -3763 +rect 1123 -3837 1197 -3763 +rect 1283 -3837 1357 -3763 +rect 1443 -3837 1517 -3763 +<< end >> diff --git a/scmos/examples/bipolar/npn_array16.cif b/scmos/examples/bipolar/npn_array16.cif new file mode 100644 index 00000000..de5b9c9f --- /dev/null +++ b/scmos/examples/bipolar/npn_array16.cif @@ -0,0 +1,8409 @@ +DS 1 40 2; +9 npn_array16; +L CWN; + B 192 128 1296 632; + B 192 172 2008 658; + B 808 172 2864 658; + B 1516 172 4386 658; + B 456 172 5748 658; + B 280 172 6452 658; +L CMS; + B 400 400 264 1056; + B 400 400 1064 1056; + B 400 400 1864 1056; + B 400 400 2664 1056; + B 400 400 3464 1056; + B 400 400 4264 1056; + B 400 400 5064 1056; + B 400 400 5864 1056; + B 400 400 6664 1056; + B 400 400 7464 1056; + B 400 400 264 256; + B 400 400 1064 256; + B 400 400 1864 256; + B 400 400 2664 256; + B 400 400 3464 256; + B 400 400 4264 256; + B 400 400 5064 256; + B 400 400 5864 256; + B 400 400 6664 256; + B 400 400 7464 256; +L CMF; + B 7736 32 3868 1296; + B 32 1248 16 656; + B 400 400 264 1056; + B 44 160 670 1200; + B 400 224 1064 1144; + B 484 20 1106 1022; + B 400 156 1064 934; + B 20 108 258 802; + B 1072 16 784 740; + B 88 16 1248 684; + B 16 88 1212 632; + B 16 68 1312 698; + B 32 12 1304 658; + B 16 28 1252 626; + B 16 28 1296 638; + B 16 400 1340 812; + B 400 400 1864 1056; + B 44 160 2270 1200; + B 400 400 2664 1056; + B 400 400 3464 1056; + B 44 160 3870 1200; + B 400 400 4264 1056; + B 400 400 5064 1056; + B 44 160 5470 1200; + B 400 400 5864 1056; + B 400 400 6664 1056; + B 44 160 7070 1200; + B 64 24 7468 1268; + B 400 400 7464 1056; + B 88 16 1960 732; + B 28 16 1374 684; + B 104 12 1296 606; + B 16 88 1380 632; + B 184 16 1296 580; + B 16 132 1924 658; + B 16 152 2024 780; + B 24 60 2652 826; + B 32 16 2016 696; + B 620 20 2354 786; + B 16 72 1964 652; + B 16 60 2008 658; + B 16 160 2052 696; + B 16 116 3436 798; + B 32 72 4280 820; + B 808 20 4668 774; + B 28 16 2086 732; + B 104 12 2008 610; + B 16 132 2092 658; + B 184 16 2008 584; + B 980 16 2954 732; + B 1412 16 4338 732; + B 16 132 2472 658; + B 720 12 2864 706; + B 16 72 2512 664; + B 16 72 2556 652; + B 16 72 2600 664; + B 16 72 2644 652; + B 16 72 2688 664; + B 16 72 2732 652; + B 16 72 2776 664; + B 16 72 2820 652; + B 16 72 2864 664; + B 16 72 2908 652; + B 16 72 2952 664; + B 16 72 2996 652; + B 16 72 3040 664; + B 16 72 3084 652; + B 16 72 3128 664; + B 16 72 3172 652; + B 648 12 2872 610; + B 700 16 2814 584; + B 16 116 1212 514; + B 16 120 1924 516; + B 16 76 3188 566; + B 472 16 2960 520; + B 20 56 2734 484; + B 400 400 264 256; + B 400 400 1064 256; + B 64 24 252 44; + B 44 160 1462 112; + B 400 400 1864 256; + B 400 400 2664 256; + B 16 404 3216 498; + B 16 132 3256 658; + B 28 16 3250 584; + B 16 132 3640 658; + B 16 52 5064 738; + B 1356 12 4394 706; + B 16 72 3680 652; + B 16 72 3724 664; + B 16 72 3768 652; + B 16 72 3812 664; + B 16 72 3856 652; + B 16 72 3900 664; + B 16 72 3944 652; + B 16 72 3988 664; + B 16 72 4032 652; + B 16 72 4076 664; + B 16 72 4120 652; + B 16 72 4164 664; + B 16 72 4208 652; + B 16 72 4252 664; + B 16 72 4296 652; + B 16 72 4340 664; + B 16 72 4384 652; + B 16 72 4428 664; + B 16 72 4472 652; + B 16 72 4516 664; + B 16 72 4560 652; + B 16 72 4604 664; + B 16 72 4648 652; + B 16 72 4692 664; + B 16 72 4736 652; + B 16 72 4784 664; + B 16 72 4828 652; + B 16 72 4872 664; + B 16 72 4916 652; + B 16 72 4960 664; + B 16 72 5004 652; + B 16 72 5048 664; + B 20 240 5094 736; + B 20 116 5862 798; + B 20 116 6698 798; + B 24 16 5128 732; + B 1432 12 4388 610; + B 16 132 5132 658; + B 1508 16 4386 584; + B 448 16 5748 732; + B 16 132 5532 658; + B 368 12 5748 706; + B 28 16 5538 584; + B 32 120 4276 516; + B 16 212 5572 594; + B 16 72 5616 652; + B 16 72 5660 664; + B 16 72 5704 652; + B 16 72 5748 664; + B 16 72 5792 652; + B 16 72 5836 664; + B 16 72 5880 652; + B 16 72 5924 664; + B 340 16 5410 480; + B 296 12 5740 610; + B 24 16 5252 464; + B 400 160 3464 376; + B 456 16 3436 288; + B 44 160 3062 112; + B 400 224 3464 168; + B 400 400 4264 256; + B 44 160 4662 112; + B 400 400 5064 256; + B 16 368 5600 420; + B 16 132 5964 658; + B 352 16 5796 584; + B 392 16 6512 732; + B 16 132 6324 658; + B 192 12 6452 706; + B 16 72 6364 664; + B 16 72 6408 652; + B 16 72 6452 664; + B 16 72 6496 652; + B 120 12 6460 610; + B 176 16 6404 584; + B 16 148 6512 530; + B 16 160 6540 620; + B 16 132 6580 658; + B 28 16 6574 584; + B 960 16 7012 532; + B 24 68 7480 490; + B 400 220 5864 346; + B 472 16 5828 228; + B 400 164 5864 138; + B 44 160 6262 112; + B 400 400 6664 256; + B 400 400 7464 256; + B 32 1248 7720 656; + B 7736 32 3868 16; +L CAA; + B 44 72 670 1156; + B 44 72 2270 1156; + B 44 72 3870 1156; + B 44 72 5470 1156; + B 44 72 7070 1156; + B 192 24 2008 732; + B 192 24 1296 684; + B 24 80 1212 632; + B 112 48 1296 632; + B 24 80 1380 632; + B 192 24 1296 580; + B 24 124 1924 658; + B 112 92 2008 658; + B 24 124 2092 658; + B 192 24 2008 584; + B 808 24 2864 732; + B 24 124 2472 658; + B 728 92 2864 658; + B 24 124 3256 658; + B 808 24 2864 584; + B 1516 24 4386 732; + B 24 124 3640 658; + B 1436 92 4386 658; + B 24 124 5132 658; + B 1516 24 4386 584; + B 456 24 5748 732; + B 24 124 5532 658; + B 376 92 5748 658; + B 24 124 5964 658; + B 456 24 5748 584; + B 280 24 6452 732; + B 24 124 6324 658; + B 200 92 6452 658; + B 24 124 6580 658; + B 280 24 6452 584; + B 44 72 1462 156; + B 44 72 3062 156; + B 44 72 4662 156; + B 44 72 6262 156; +L CX; + B 200 32 2008 732; + B 200 32 1296 684; + B 32 72 1212 632; + B 32 72 1380 632; + B 200 32 1296 580; + B 32 116 1924 658; + B 32 116 2092 658; + B 200 32 2008 584; + B 816 32 2864 732; + B 32 116 2472 658; + B 32 116 3256 658; + B 816 32 2864 584; + B 1524 32 4386 732; + B 32 116 3640 658; + B 32 116 5132 658; + B 1524 32 4386 584; + B 464 32 5748 732; + B 32 116 5532 658; + B 32 116 5964 658; + B 464 32 5748 584; + B 288 32 6452 732; + B 32 116 6324 658; + B 32 116 6580 658; + B 288 32 6452 584; +L CVA; + B 8 8 84 1236; + B 8 8 104 1236; + B 8 8 124 1236; + B 8 8 144 1236; + B 8 8 164 1236; + B 8 8 184 1236; + B 8 8 204 1236; + B 8 8 224 1236; + B 8 8 244 1236; + B 8 8 264 1236; + B 8 8 284 1236; + B 8 8 304 1236; + B 8 8 324 1236; + B 8 8 344 1236; + B 8 8 364 1236; + B 8 8 384 1236; + B 8 8 404 1236; + B 8 8 424 1236; + B 8 8 444 1236; + B 8 8 884 1236; + B 8 8 904 1236; + B 8 8 924 1236; + B 8 8 944 1236; + B 8 8 964 1236; + B 8 8 984 1236; + B 8 8 1004 1236; + B 8 8 1024 1236; + B 8 8 1044 1236; + B 8 8 1064 1236; + B 8 8 1084 1236; + B 8 8 1104 1236; + B 8 8 1124 1236; + B 8 8 1144 1236; + B 8 8 1164 1236; + B 8 8 1184 1236; + B 8 8 1204 1236; + B 8 8 1224 1236; + B 8 8 1244 1236; + B 8 8 1684 1236; + B 8 8 1704 1236; + B 8 8 1724 1236; + B 8 8 1744 1236; + B 8 8 1764 1236; + B 8 8 1784 1236; + B 8 8 1804 1236; + B 8 8 1824 1236; + B 8 8 1844 1236; + B 8 8 1864 1236; + B 8 8 1884 1236; + B 8 8 1904 1236; + B 8 8 1924 1236; + B 8 8 1944 1236; + B 8 8 1964 1236; + B 8 8 1984 1236; + B 8 8 2004 1236; + B 8 8 2024 1236; + B 8 8 2044 1236; + B 8 8 2484 1236; + B 8 8 2504 1236; + B 8 8 2524 1236; + B 8 8 2544 1236; + B 8 8 2564 1236; + B 8 8 2584 1236; + B 8 8 2604 1236; + B 8 8 2624 1236; + B 8 8 2644 1236; + B 8 8 2664 1236; + B 8 8 2684 1236; + B 8 8 2704 1236; + B 8 8 2724 1236; + B 8 8 2744 1236; + B 8 8 2764 1236; + B 8 8 2784 1236; + B 8 8 2804 1236; + B 8 8 2824 1236; + B 8 8 2844 1236; + B 8 8 3284 1236; + B 8 8 3304 1236; + B 8 8 3324 1236; + B 8 8 3344 1236; + B 8 8 3364 1236; + B 8 8 3384 1236; + B 8 8 3404 1236; + B 8 8 3424 1236; + B 8 8 3444 1236; + B 8 8 3464 1236; + B 8 8 3484 1236; + B 8 8 3504 1236; + B 8 8 3524 1236; + B 8 8 3544 1236; + B 8 8 3564 1236; + B 8 8 3584 1236; + B 8 8 3604 1236; + B 8 8 3624 1236; + B 8 8 3644 1236; + B 8 8 4084 1236; + B 8 8 4104 1236; + B 8 8 4124 1236; + B 8 8 4144 1236; + B 8 8 4164 1236; + B 8 8 4184 1236; + B 8 8 4204 1236; + B 8 8 4224 1236; + B 8 8 4244 1236; + B 8 8 4264 1236; + B 8 8 4284 1236; + B 8 8 4304 1236; + B 8 8 4324 1236; + B 8 8 4344 1236; + B 8 8 4364 1236; + B 8 8 4384 1236; + B 8 8 4404 1236; + B 8 8 4424 1236; + B 8 8 4444 1236; + B 8 8 4884 1236; + B 8 8 4904 1236; + B 8 8 4924 1236; + B 8 8 4944 1236; + B 8 8 4964 1236; + B 8 8 4984 1236; + B 8 8 5004 1236; + B 8 8 5024 1236; + B 8 8 5044 1236; + B 8 8 5064 1236; + B 8 8 5084 1236; + B 8 8 5104 1236; + B 8 8 5124 1236; + B 8 8 5144 1236; + B 8 8 5164 1236; + B 8 8 5184 1236; + B 8 8 5204 1236; + B 8 8 5224 1236; + B 8 8 5244 1236; + B 8 8 5684 1236; + B 8 8 5704 1236; + B 8 8 5724 1236; + B 8 8 5744 1236; + B 8 8 5764 1236; + B 8 8 5784 1236; + B 8 8 5804 1236; + B 8 8 5824 1236; + B 8 8 5844 1236; + B 8 8 5864 1236; + B 8 8 5884 1236; + B 8 8 5904 1236; + B 8 8 5924 1236; + B 8 8 5944 1236; + B 8 8 5964 1236; + B 8 8 5984 1236; + B 8 8 6004 1236; + B 8 8 6024 1236; + B 8 8 6044 1236; + B 8 8 6484 1236; + B 8 8 6504 1236; + B 8 8 6524 1236; + B 8 8 6544 1236; + B 8 8 6564 1236; + B 8 8 6584 1236; + B 8 8 6604 1236; + B 8 8 6624 1236; + B 8 8 6644 1236; + B 8 8 6664 1236; + B 8 8 6684 1236; + B 8 8 6704 1236; + B 8 8 6724 1236; + B 8 8 6744 1236; + B 8 8 6764 1236; + B 8 8 6784 1236; + B 8 8 6804 1236; + B 8 8 6824 1236; + B 8 8 6844 1236; + B 8 8 7284 1236; + B 8 8 7304 1236; + B 8 8 7324 1236; + B 8 8 7344 1236; + B 8 8 7364 1236; + B 8 8 7384 1236; + B 8 8 7404 1236; + B 8 8 7424 1236; + B 8 8 7444 1236; + B 8 8 7464 1236; + B 8 8 7484 1236; + B 8 8 7504 1236; + B 8 8 7524 1236; + B 8 8 7544 1236; + B 8 8 7564 1236; + B 8 8 7584 1236; + B 8 8 7604 1236; + B 8 8 7624 1236; + B 8 8 7644 1236; + B 8 8 84 1216; + B 8 8 104 1216; + B 8 8 124 1216; + B 8 8 144 1216; + B 8 8 164 1216; + B 8 8 184 1216; + B 8 8 204 1216; + B 8 8 224 1216; + B 8 8 244 1216; + B 8 8 264 1216; + B 8 8 284 1216; + B 8 8 304 1216; + B 8 8 324 1216; + B 8 8 344 1216; + B 8 8 364 1216; + B 8 8 384 1216; + B 8 8 404 1216; + B 8 8 424 1216; + B 8 8 444 1216; + B 8 8 884 1216; + B 8 8 904 1216; + B 8 8 924 1216; + B 8 8 944 1216; + B 8 8 964 1216; + B 8 8 984 1216; + B 8 8 1004 1216; + B 8 8 1024 1216; + B 8 8 1044 1216; + B 8 8 1064 1216; + B 8 8 1084 1216; + B 8 8 1104 1216; + B 8 8 1124 1216; + B 8 8 1144 1216; + B 8 8 1164 1216; + B 8 8 1184 1216; + B 8 8 1204 1216; + B 8 8 1224 1216; + B 8 8 1244 1216; + B 8 8 1684 1216; + B 8 8 1704 1216; + B 8 8 1724 1216; + B 8 8 1744 1216; + B 8 8 1764 1216; + B 8 8 1784 1216; + B 8 8 1804 1216; + B 8 8 1824 1216; + B 8 8 1844 1216; + B 8 8 1864 1216; + B 8 8 1884 1216; + B 8 8 1904 1216; + B 8 8 1924 1216; + B 8 8 1944 1216; + B 8 8 1964 1216; + B 8 8 1984 1216; + B 8 8 2004 1216; + B 8 8 2024 1216; + B 8 8 2044 1216; + B 8 8 2484 1216; + B 8 8 2504 1216; + B 8 8 2524 1216; + B 8 8 2544 1216; + B 8 8 2564 1216; + B 8 8 2584 1216; + B 8 8 2604 1216; + B 8 8 2624 1216; + B 8 8 2644 1216; + B 8 8 2664 1216; + B 8 8 2684 1216; + B 8 8 2704 1216; + B 8 8 2724 1216; + B 8 8 2744 1216; + B 8 8 2764 1216; + B 8 8 2784 1216; + B 8 8 2804 1216; + B 8 8 2824 1216; + B 8 8 2844 1216; + B 8 8 3284 1216; + B 8 8 3304 1216; + B 8 8 3324 1216; + B 8 8 3344 1216; + B 8 8 3364 1216; + B 8 8 3384 1216; + B 8 8 3404 1216; + B 8 8 3424 1216; + B 8 8 3444 1216; + B 8 8 3464 1216; + B 8 8 3484 1216; + B 8 8 3504 1216; + B 8 8 3524 1216; + B 8 8 3544 1216; + B 8 8 3564 1216; + B 8 8 3584 1216; + B 8 8 3604 1216; + B 8 8 3624 1216; + B 8 8 3644 1216; + B 8 8 4084 1216; + B 8 8 4104 1216; + B 8 8 4124 1216; + B 8 8 4144 1216; + B 8 8 4164 1216; + B 8 8 4184 1216; + B 8 8 4204 1216; + B 8 8 4224 1216; + B 8 8 4244 1216; + B 8 8 4264 1216; + B 8 8 4284 1216; + B 8 8 4304 1216; + B 8 8 4324 1216; + B 8 8 4344 1216; + B 8 8 4364 1216; + B 8 8 4384 1216; + B 8 8 4404 1216; + B 8 8 4424 1216; + B 8 8 4444 1216; + B 8 8 4884 1216; + B 8 8 4904 1216; + B 8 8 4924 1216; + B 8 8 4944 1216; + B 8 8 4964 1216; + B 8 8 4984 1216; + B 8 8 5004 1216; + B 8 8 5024 1216; + B 8 8 5044 1216; + B 8 8 5064 1216; + B 8 8 5084 1216; + B 8 8 5104 1216; + B 8 8 5124 1216; + B 8 8 5144 1216; + B 8 8 5164 1216; + B 8 8 5184 1216; + B 8 8 5204 1216; + B 8 8 5224 1216; + B 8 8 5244 1216; + B 8 8 5684 1216; + B 8 8 5704 1216; + B 8 8 5724 1216; + B 8 8 5744 1216; + B 8 8 5764 1216; + B 8 8 5784 1216; + B 8 8 5804 1216; + B 8 8 5824 1216; + B 8 8 5844 1216; + B 8 8 5864 1216; + B 8 8 5884 1216; + B 8 8 5904 1216; + B 8 8 5924 1216; + B 8 8 5944 1216; + B 8 8 5964 1216; + B 8 8 5984 1216; + B 8 8 6004 1216; + B 8 8 6024 1216; + B 8 8 6044 1216; + B 8 8 6484 1216; + B 8 8 6504 1216; + B 8 8 6524 1216; + B 8 8 6544 1216; + B 8 8 6564 1216; + B 8 8 6584 1216; + B 8 8 6604 1216; + B 8 8 6624 1216; + B 8 8 6644 1216; + B 8 8 6664 1216; + B 8 8 6684 1216; + B 8 8 6704 1216; + B 8 8 6724 1216; + B 8 8 6744 1216; + B 8 8 6764 1216; + B 8 8 6784 1216; + B 8 8 6804 1216; + B 8 8 6824 1216; + B 8 8 6844 1216; + B 8 8 7284 1216; + B 8 8 7304 1216; + B 8 8 7324 1216; + B 8 8 7344 1216; + B 8 8 7364 1216; + B 8 8 7384 1216; + B 8 8 7404 1216; + B 8 8 7424 1216; + B 8 8 7444 1216; + B 8 8 7464 1216; + B 8 8 7484 1216; + B 8 8 7504 1216; + B 8 8 7524 1216; + B 8 8 7544 1216; + B 8 8 7564 1216; + B 8 8 7584 1216; + B 8 8 7604 1216; + B 8 8 7624 1216; + B 8 8 7644 1216; + B 8 8 84 1196; + B 8 8 104 1196; + B 8 8 124 1196; + B 8 8 144 1196; + B 8 8 164 1196; + B 8 8 184 1196; + B 8 8 204 1196; + B 8 8 224 1196; + B 8 8 244 1196; + B 8 8 264 1196; + B 8 8 284 1196; + B 8 8 304 1196; + B 8 8 324 1196; + B 8 8 344 1196; + B 8 8 364 1196; + B 8 8 384 1196; + B 8 8 404 1196; + B 8 8 424 1196; + B 8 8 444 1196; + B 8 8 884 1196; + B 8 8 904 1196; + B 8 8 924 1196; + B 8 8 944 1196; + B 8 8 964 1196; + B 8 8 984 1196; + B 8 8 1004 1196; + B 8 8 1024 1196; + B 8 8 1044 1196; + B 8 8 1064 1196; + B 8 8 1084 1196; + B 8 8 1104 1196; + B 8 8 1124 1196; + B 8 8 1144 1196; + B 8 8 1164 1196; + B 8 8 1184 1196; + B 8 8 1204 1196; + B 8 8 1224 1196; + B 8 8 1244 1196; + B 8 8 1684 1196; + B 8 8 1704 1196; + B 8 8 1724 1196; + B 8 8 1744 1196; + B 8 8 1764 1196; + B 8 8 1784 1196; + B 8 8 1804 1196; + B 8 8 1824 1196; + B 8 8 1844 1196; + B 8 8 1864 1196; + B 8 8 1884 1196; + B 8 8 1904 1196; + B 8 8 1924 1196; + B 8 8 1944 1196; + B 8 8 1964 1196; + B 8 8 1984 1196; + B 8 8 2004 1196; + B 8 8 2024 1196; + B 8 8 2044 1196; + B 8 8 2484 1196; + B 8 8 2504 1196; + B 8 8 2524 1196; + B 8 8 2544 1196; + B 8 8 2564 1196; + B 8 8 2584 1196; + B 8 8 2604 1196; + B 8 8 2624 1196; + B 8 8 2644 1196; + B 8 8 2664 1196; + B 8 8 2684 1196; + B 8 8 2704 1196; + B 8 8 2724 1196; + B 8 8 2744 1196; + B 8 8 2764 1196; + B 8 8 2784 1196; + B 8 8 2804 1196; + B 8 8 2824 1196; + B 8 8 2844 1196; + B 8 8 3284 1196; + B 8 8 3304 1196; + B 8 8 3324 1196; + B 8 8 3344 1196; + B 8 8 3364 1196; + B 8 8 3384 1196; + B 8 8 3404 1196; + B 8 8 3424 1196; + B 8 8 3444 1196; + B 8 8 3464 1196; + B 8 8 3484 1196; + B 8 8 3504 1196; + B 8 8 3524 1196; + B 8 8 3544 1196; + B 8 8 3564 1196; + B 8 8 3584 1196; + B 8 8 3604 1196; + B 8 8 3624 1196; + B 8 8 3644 1196; + B 8 8 4084 1196; + B 8 8 4104 1196; + B 8 8 4124 1196; + B 8 8 4144 1196; + B 8 8 4164 1196; + B 8 8 4184 1196; + B 8 8 4204 1196; + B 8 8 4224 1196; + B 8 8 4244 1196; + B 8 8 4264 1196; + B 8 8 4284 1196; + B 8 8 4304 1196; + B 8 8 4324 1196; + B 8 8 4344 1196; + B 8 8 4364 1196; + B 8 8 4384 1196; + B 8 8 4404 1196; + B 8 8 4424 1196; + B 8 8 4444 1196; + B 8 8 4884 1196; + B 8 8 4904 1196; + B 8 8 4924 1196; + B 8 8 4944 1196; + B 8 8 4964 1196; + B 8 8 4984 1196; + B 8 8 5004 1196; + B 8 8 5024 1196; + B 8 8 5044 1196; + B 8 8 5064 1196; + B 8 8 5084 1196; + B 8 8 5104 1196; + B 8 8 5124 1196; + B 8 8 5144 1196; + B 8 8 5164 1196; + B 8 8 5184 1196; + B 8 8 5204 1196; + B 8 8 5224 1196; + B 8 8 5244 1196; + B 8 8 5684 1196; + B 8 8 5704 1196; + B 8 8 5724 1196; + B 8 8 5744 1196; + B 8 8 5764 1196; + B 8 8 5784 1196; + B 8 8 5804 1196; + B 8 8 5824 1196; + B 8 8 5844 1196; + B 8 8 5864 1196; + B 8 8 5884 1196; + B 8 8 5904 1196; + B 8 8 5924 1196; + B 8 8 5944 1196; + B 8 8 5964 1196; + B 8 8 5984 1196; + B 8 8 6004 1196; + B 8 8 6024 1196; + B 8 8 6044 1196; + B 8 8 6484 1196; + B 8 8 6504 1196; + B 8 8 6524 1196; + B 8 8 6544 1196; + B 8 8 6564 1196; + B 8 8 6584 1196; + B 8 8 6604 1196; + B 8 8 6624 1196; + B 8 8 6644 1196; + B 8 8 6664 1196; + B 8 8 6684 1196; + B 8 8 6704 1196; + B 8 8 6724 1196; + B 8 8 6744 1196; + B 8 8 6764 1196; + B 8 8 6784 1196; + B 8 8 6804 1196; + B 8 8 6824 1196; + B 8 8 6844 1196; + B 8 8 7284 1196; + B 8 8 7304 1196; + B 8 8 7324 1196; + B 8 8 7344 1196; + B 8 8 7364 1196; + B 8 8 7384 1196; + B 8 8 7404 1196; + B 8 8 7424 1196; + B 8 8 7444 1196; + B 8 8 7464 1196; + B 8 8 7484 1196; + B 8 8 7504 1196; + B 8 8 7524 1196; + B 8 8 7544 1196; + B 8 8 7564 1196; + B 8 8 7584 1196; + B 8 8 7604 1196; + B 8 8 7624 1196; + B 8 8 7644 1196; + B 8 8 84 1176; + B 8 8 104 1176; + B 8 8 124 1176; + B 8 8 144 1176; + B 8 8 164 1176; + B 8 8 184 1176; + B 8 8 204 1176; + B 8 8 224 1176; + B 8 8 244 1176; + B 8 8 264 1176; + B 8 8 284 1176; + B 8 8 304 1176; + B 8 8 324 1176; + B 8 8 344 1176; + B 8 8 364 1176; + B 8 8 384 1176; + B 8 8 404 1176; + B 8 8 424 1176; + B 8 8 444 1176; + B 8 8 884 1176; + B 8 8 904 1176; + B 8 8 924 1176; + B 8 8 944 1176; + B 8 8 964 1176; + B 8 8 984 1176; + B 8 8 1004 1176; + B 8 8 1024 1176; + B 8 8 1044 1176; + B 8 8 1064 1176; + B 8 8 1084 1176; + B 8 8 1104 1176; + B 8 8 1124 1176; + B 8 8 1144 1176; + B 8 8 1164 1176; + B 8 8 1184 1176; + B 8 8 1204 1176; + B 8 8 1224 1176; + B 8 8 1244 1176; + B 8 8 1684 1176; + B 8 8 1704 1176; + B 8 8 1724 1176; + B 8 8 1744 1176; + B 8 8 1764 1176; + B 8 8 1784 1176; + B 8 8 1804 1176; + B 8 8 1824 1176; + B 8 8 1844 1176; + B 8 8 1864 1176; + B 8 8 1884 1176; + B 8 8 1904 1176; + B 8 8 1924 1176; + B 8 8 1944 1176; + B 8 8 1964 1176; + B 8 8 1984 1176; + B 8 8 2004 1176; + B 8 8 2024 1176; + B 8 8 2044 1176; + B 8 8 2484 1176; + B 8 8 2504 1176; + B 8 8 2524 1176; + B 8 8 2544 1176; + B 8 8 2564 1176; + B 8 8 2584 1176; + B 8 8 2604 1176; + B 8 8 2624 1176; + B 8 8 2644 1176; + B 8 8 2664 1176; + B 8 8 2684 1176; + B 8 8 2704 1176; + B 8 8 2724 1176; + B 8 8 2744 1176; + B 8 8 2764 1176; + B 8 8 2784 1176; + B 8 8 2804 1176; + B 8 8 2824 1176; + B 8 8 2844 1176; + B 8 8 3284 1176; + B 8 8 3304 1176; + B 8 8 3324 1176; + B 8 8 3344 1176; + B 8 8 3364 1176; + B 8 8 3384 1176; + B 8 8 3404 1176; + B 8 8 3424 1176; + B 8 8 3444 1176; + B 8 8 3464 1176; + B 8 8 3484 1176; + B 8 8 3504 1176; + B 8 8 3524 1176; + B 8 8 3544 1176; + B 8 8 3564 1176; + B 8 8 3584 1176; + B 8 8 3604 1176; + B 8 8 3624 1176; + B 8 8 3644 1176; + B 8 8 4084 1176; + B 8 8 4104 1176; + B 8 8 4124 1176; + B 8 8 4144 1176; + B 8 8 4164 1176; + B 8 8 4184 1176; + B 8 8 4204 1176; + B 8 8 4224 1176; + B 8 8 4244 1176; + B 8 8 4264 1176; + B 8 8 4284 1176; + B 8 8 4304 1176; + B 8 8 4324 1176; + B 8 8 4344 1176; + B 8 8 4364 1176; + B 8 8 4384 1176; + B 8 8 4404 1176; + B 8 8 4424 1176; + B 8 8 4444 1176; + B 8 8 4884 1176; + B 8 8 4904 1176; + B 8 8 4924 1176; + B 8 8 4944 1176; + B 8 8 4964 1176; + B 8 8 4984 1176; + B 8 8 5004 1176; + B 8 8 5024 1176; + B 8 8 5044 1176; + B 8 8 5064 1176; + B 8 8 5084 1176; + B 8 8 5104 1176; + B 8 8 5124 1176; + B 8 8 5144 1176; + B 8 8 5164 1176; + B 8 8 5184 1176; + B 8 8 5204 1176; + B 8 8 5224 1176; + B 8 8 5244 1176; + B 8 8 5684 1176; + B 8 8 5704 1176; + B 8 8 5724 1176; + B 8 8 5744 1176; + B 8 8 5764 1176; + B 8 8 5784 1176; + B 8 8 5804 1176; + B 8 8 5824 1176; + B 8 8 5844 1176; + B 8 8 5864 1176; + B 8 8 5884 1176; + B 8 8 5904 1176; + B 8 8 5924 1176; + B 8 8 5944 1176; + B 8 8 5964 1176; + B 8 8 5984 1176; + B 8 8 6004 1176; + B 8 8 6024 1176; + B 8 8 6044 1176; + B 8 8 6484 1176; + B 8 8 6504 1176; + B 8 8 6524 1176; + B 8 8 6544 1176; + B 8 8 6564 1176; + B 8 8 6584 1176; + B 8 8 6604 1176; + B 8 8 6624 1176; + B 8 8 6644 1176; + B 8 8 6664 1176; + B 8 8 6684 1176; + B 8 8 6704 1176; + B 8 8 6724 1176; + B 8 8 6744 1176; + B 8 8 6764 1176; + B 8 8 6784 1176; + B 8 8 6804 1176; + B 8 8 6824 1176; + B 8 8 6844 1176; + B 8 8 7284 1176; + B 8 8 7304 1176; + B 8 8 7324 1176; + B 8 8 7344 1176; + B 8 8 7364 1176; + B 8 8 7384 1176; + B 8 8 7404 1176; + B 8 8 7424 1176; + B 8 8 7444 1176; + B 8 8 7464 1176; + B 8 8 7484 1176; + B 8 8 7504 1176; + B 8 8 7524 1176; + B 8 8 7544 1176; + B 8 8 7564 1176; + B 8 8 7584 1176; + B 8 8 7604 1176; + B 8 8 7624 1176; + B 8 8 7644 1176; + B 8 8 84 1156; + B 8 8 104 1156; + B 8 8 124 1156; + B 8 8 144 1156; + B 8 8 164 1156; + B 8 8 184 1156; + B 8 8 204 1156; + B 8 8 224 1156; + B 8 8 244 1156; + B 8 8 264 1156; + B 8 8 284 1156; + B 8 8 304 1156; + B 8 8 324 1156; + B 8 8 344 1156; + B 8 8 364 1156; + B 8 8 384 1156; + B 8 8 404 1156; + B 8 8 424 1156; + B 8 8 444 1156; + B 8 8 884 1156; + B 8 8 904 1156; + B 8 8 924 1156; + B 8 8 944 1156; + B 8 8 964 1156; + B 8 8 984 1156; + B 8 8 1004 1156; + B 8 8 1024 1156; + B 8 8 1044 1156; + B 8 8 1064 1156; + B 8 8 1084 1156; + B 8 8 1104 1156; + B 8 8 1124 1156; + B 8 8 1144 1156; + B 8 8 1164 1156; + B 8 8 1184 1156; + B 8 8 1204 1156; + B 8 8 1224 1156; + B 8 8 1244 1156; + B 8 8 1684 1156; + B 8 8 1704 1156; + B 8 8 1724 1156; + B 8 8 1744 1156; + B 8 8 1764 1156; + B 8 8 1784 1156; + B 8 8 1804 1156; + B 8 8 1824 1156; + B 8 8 1844 1156; + B 8 8 1864 1156; + B 8 8 1884 1156; + B 8 8 1904 1156; + B 8 8 1924 1156; + B 8 8 1944 1156; + B 8 8 1964 1156; + B 8 8 1984 1156; + B 8 8 2004 1156; + B 8 8 2024 1156; + B 8 8 2044 1156; + B 8 8 2484 1156; + B 8 8 2504 1156; + B 8 8 2524 1156; + B 8 8 2544 1156; + B 8 8 2564 1156; + B 8 8 2584 1156; + B 8 8 2604 1156; + B 8 8 2624 1156; + B 8 8 2644 1156; + B 8 8 2664 1156; + B 8 8 2684 1156; + B 8 8 2704 1156; + B 8 8 2724 1156; + B 8 8 2744 1156; + B 8 8 2764 1156; + B 8 8 2784 1156; + B 8 8 2804 1156; + B 8 8 2824 1156; + B 8 8 2844 1156; + B 8 8 3284 1156; + B 8 8 3304 1156; + B 8 8 3324 1156; + B 8 8 3344 1156; + B 8 8 3364 1156; + B 8 8 3384 1156; + B 8 8 3404 1156; + B 8 8 3424 1156; + B 8 8 3444 1156; + B 8 8 3464 1156; + B 8 8 3484 1156; + B 8 8 3504 1156; + B 8 8 3524 1156; + B 8 8 3544 1156; + B 8 8 3564 1156; + B 8 8 3584 1156; + B 8 8 3604 1156; + B 8 8 3624 1156; + B 8 8 3644 1156; + B 8 8 4084 1156; + B 8 8 4104 1156; + B 8 8 4124 1156; + B 8 8 4144 1156; + B 8 8 4164 1156; + B 8 8 4184 1156; + B 8 8 4204 1156; + B 8 8 4224 1156; + B 8 8 4244 1156; + B 8 8 4264 1156; + B 8 8 4284 1156; + B 8 8 4304 1156; + B 8 8 4324 1156; + B 8 8 4344 1156; + B 8 8 4364 1156; + B 8 8 4384 1156; + B 8 8 4404 1156; + B 8 8 4424 1156; + B 8 8 4444 1156; + B 8 8 4884 1156; + B 8 8 4904 1156; + B 8 8 4924 1156; + B 8 8 4944 1156; + B 8 8 4964 1156; + B 8 8 4984 1156; + B 8 8 5004 1156; + B 8 8 5024 1156; + B 8 8 5044 1156; + B 8 8 5064 1156; + B 8 8 5084 1156; + B 8 8 5104 1156; + B 8 8 5124 1156; + B 8 8 5144 1156; + B 8 8 5164 1156; + B 8 8 5184 1156; + B 8 8 5204 1156; + B 8 8 5224 1156; + B 8 8 5244 1156; + B 8 8 5684 1156; + B 8 8 5704 1156; + B 8 8 5724 1156; + B 8 8 5744 1156; + B 8 8 5764 1156; + B 8 8 5784 1156; + B 8 8 5804 1156; + B 8 8 5824 1156; + B 8 8 5844 1156; + B 8 8 5864 1156; + B 8 8 5884 1156; + B 8 8 5904 1156; + B 8 8 5924 1156; + B 8 8 5944 1156; + B 8 8 5964 1156; + B 8 8 5984 1156; + B 8 8 6004 1156; + B 8 8 6024 1156; + B 8 8 6044 1156; + B 8 8 6484 1156; + B 8 8 6504 1156; + B 8 8 6524 1156; + B 8 8 6544 1156; + B 8 8 6564 1156; + B 8 8 6584 1156; + B 8 8 6604 1156; + B 8 8 6624 1156; + B 8 8 6644 1156; + B 8 8 6664 1156; + B 8 8 6684 1156; + B 8 8 6704 1156; + B 8 8 6724 1156; + B 8 8 6744 1156; + B 8 8 6764 1156; + B 8 8 6784 1156; + B 8 8 6804 1156; + B 8 8 6824 1156; + B 8 8 6844 1156; + B 8 8 7284 1156; + B 8 8 7304 1156; + B 8 8 7324 1156; + B 8 8 7344 1156; + B 8 8 7364 1156; + B 8 8 7384 1156; + B 8 8 7404 1156; + B 8 8 7424 1156; + B 8 8 7444 1156; + B 8 8 7464 1156; + B 8 8 7484 1156; + B 8 8 7504 1156; + B 8 8 7524 1156; + B 8 8 7544 1156; + B 8 8 7564 1156; + B 8 8 7584 1156; + B 8 8 7604 1156; + B 8 8 7624 1156; + B 8 8 7644 1156; + B 8 8 84 1136; + B 8 8 104 1136; + B 8 8 124 1136; + B 8 8 144 1136; + B 8 8 164 1136; + B 8 8 184 1136; + B 8 8 204 1136; + B 8 8 224 1136; + B 8 8 244 1136; + B 8 8 264 1136; + B 8 8 284 1136; + B 8 8 304 1136; + B 8 8 324 1136; + B 8 8 344 1136; + B 8 8 364 1136; + B 8 8 384 1136; + B 8 8 404 1136; + B 8 8 424 1136; + B 8 8 444 1136; + B 8 8 884 1136; + B 8 8 904 1136; + B 8 8 924 1136; + B 8 8 944 1136; + B 8 8 964 1136; + B 8 8 984 1136; + B 8 8 1004 1136; + B 8 8 1024 1136; + B 8 8 1044 1136; + B 8 8 1064 1136; + B 8 8 1084 1136; + B 8 8 1104 1136; + B 8 8 1124 1136; + B 8 8 1144 1136; + B 8 8 1164 1136; + B 8 8 1184 1136; + B 8 8 1204 1136; + B 8 8 1224 1136; + B 8 8 1244 1136; + B 8 8 1684 1136; + B 8 8 1704 1136; + B 8 8 1724 1136; + B 8 8 1744 1136; + B 8 8 1764 1136; + B 8 8 1784 1136; + B 8 8 1804 1136; + B 8 8 1824 1136; + B 8 8 1844 1136; + B 8 8 1864 1136; + B 8 8 1884 1136; + B 8 8 1904 1136; + B 8 8 1924 1136; + B 8 8 1944 1136; + B 8 8 1964 1136; + B 8 8 1984 1136; + B 8 8 2004 1136; + B 8 8 2024 1136; + B 8 8 2044 1136; + B 8 8 2484 1136; + B 8 8 2504 1136; + B 8 8 2524 1136; + B 8 8 2544 1136; + B 8 8 2564 1136; + B 8 8 2584 1136; + B 8 8 2604 1136; + B 8 8 2624 1136; + B 8 8 2644 1136; + B 8 8 2664 1136; + B 8 8 2684 1136; + B 8 8 2704 1136; + B 8 8 2724 1136; + B 8 8 2744 1136; + B 8 8 2764 1136; + B 8 8 2784 1136; + B 8 8 2804 1136; + B 8 8 2824 1136; + B 8 8 2844 1136; + B 8 8 3284 1136; + B 8 8 3304 1136; + B 8 8 3324 1136; + B 8 8 3344 1136; + B 8 8 3364 1136; + B 8 8 3384 1136; + B 8 8 3404 1136; + B 8 8 3424 1136; + B 8 8 3444 1136; + B 8 8 3464 1136; + B 8 8 3484 1136; + B 8 8 3504 1136; + B 8 8 3524 1136; + B 8 8 3544 1136; + B 8 8 3564 1136; + B 8 8 3584 1136; + B 8 8 3604 1136; + B 8 8 3624 1136; + B 8 8 3644 1136; + B 8 8 4084 1136; + B 8 8 4104 1136; + B 8 8 4124 1136; + B 8 8 4144 1136; + B 8 8 4164 1136; + B 8 8 4184 1136; + B 8 8 4204 1136; + B 8 8 4224 1136; + B 8 8 4244 1136; + B 8 8 4264 1136; + B 8 8 4284 1136; + B 8 8 4304 1136; + B 8 8 4324 1136; + B 8 8 4344 1136; + B 8 8 4364 1136; + B 8 8 4384 1136; + B 8 8 4404 1136; + B 8 8 4424 1136; + B 8 8 4444 1136; + B 8 8 4884 1136; + B 8 8 4904 1136; + B 8 8 4924 1136; + B 8 8 4944 1136; + B 8 8 4964 1136; + B 8 8 4984 1136; + B 8 8 5004 1136; + B 8 8 5024 1136; + B 8 8 5044 1136; + B 8 8 5064 1136; + B 8 8 5084 1136; + B 8 8 5104 1136; + B 8 8 5124 1136; + B 8 8 5144 1136; + B 8 8 5164 1136; + B 8 8 5184 1136; + B 8 8 5204 1136; + B 8 8 5224 1136; + B 8 8 5244 1136; + B 8 8 5684 1136; + B 8 8 5704 1136; + B 8 8 5724 1136; + B 8 8 5744 1136; + B 8 8 5764 1136; + B 8 8 5784 1136; + B 8 8 5804 1136; + B 8 8 5824 1136; + B 8 8 5844 1136; + B 8 8 5864 1136; + B 8 8 5884 1136; + B 8 8 5904 1136; + B 8 8 5924 1136; + B 8 8 5944 1136; + B 8 8 5964 1136; + B 8 8 5984 1136; + B 8 8 6004 1136; + B 8 8 6024 1136; + B 8 8 6044 1136; + B 8 8 6484 1136; + B 8 8 6504 1136; + B 8 8 6524 1136; + B 8 8 6544 1136; + B 8 8 6564 1136; + B 8 8 6584 1136; + B 8 8 6604 1136; + B 8 8 6624 1136; + B 8 8 6644 1136; + B 8 8 6664 1136; + B 8 8 6684 1136; + B 8 8 6704 1136; + B 8 8 6724 1136; + B 8 8 6744 1136; + B 8 8 6764 1136; + B 8 8 6784 1136; + B 8 8 6804 1136; + B 8 8 6824 1136; + B 8 8 6844 1136; + B 8 8 7284 1136; + B 8 8 7304 1136; + B 8 8 7324 1136; + B 8 8 7344 1136; + B 8 8 7364 1136; + B 8 8 7384 1136; + B 8 8 7404 1136; + B 8 8 7424 1136; + B 8 8 7444 1136; + B 8 8 7464 1136; + B 8 8 7484 1136; + B 8 8 7504 1136; + B 8 8 7524 1136; + B 8 8 7544 1136; + B 8 8 7564 1136; + B 8 8 7584 1136; + B 8 8 7604 1136; + B 8 8 7624 1136; + B 8 8 7644 1136; + B 8 8 84 1116; + B 8 8 104 1116; + B 8 8 124 1116; + B 8 8 144 1116; + B 8 8 164 1116; + B 8 8 184 1116; + B 8 8 204 1116; + B 8 8 224 1116; + B 8 8 244 1116; + B 8 8 264 1116; + B 8 8 284 1116; + B 8 8 304 1116; + B 8 8 324 1116; + B 8 8 344 1116; + B 8 8 364 1116; + B 8 8 384 1116; + B 8 8 404 1116; + B 8 8 424 1116; + B 8 8 444 1116; + B 8 8 884 1116; + B 8 8 904 1116; + B 8 8 924 1116; + B 8 8 944 1116; + B 8 8 964 1116; + B 8 8 984 1116; + B 8 8 1004 1116; + B 8 8 1024 1116; + B 8 8 1044 1116; + B 8 8 1064 1116; + B 8 8 1084 1116; + B 8 8 1104 1116; + B 8 8 1124 1116; + B 8 8 1144 1116; + B 8 8 1164 1116; + B 8 8 1184 1116; + B 8 8 1204 1116; + B 8 8 1224 1116; + B 8 8 1244 1116; + B 8 8 1684 1116; + B 8 8 1704 1116; + B 8 8 1724 1116; + B 8 8 1744 1116; + B 8 8 1764 1116; + B 8 8 1784 1116; + B 8 8 1804 1116; + B 8 8 1824 1116; + B 8 8 1844 1116; + B 8 8 1864 1116; + B 8 8 1884 1116; + B 8 8 1904 1116; + B 8 8 1924 1116; + B 8 8 1944 1116; + B 8 8 1964 1116; + B 8 8 1984 1116; + B 8 8 2004 1116; + B 8 8 2024 1116; + B 8 8 2044 1116; + B 8 8 2484 1116; + B 8 8 2504 1116; + B 8 8 2524 1116; + B 8 8 2544 1116; + B 8 8 2564 1116; + B 8 8 2584 1116; + B 8 8 2604 1116; + B 8 8 2624 1116; + B 8 8 2644 1116; + B 8 8 2664 1116; + B 8 8 2684 1116; + B 8 8 2704 1116; + B 8 8 2724 1116; + B 8 8 2744 1116; + B 8 8 2764 1116; + B 8 8 2784 1116; + B 8 8 2804 1116; + B 8 8 2824 1116; + B 8 8 2844 1116; + B 8 8 3284 1116; + B 8 8 3304 1116; + B 8 8 3324 1116; + B 8 8 3344 1116; + B 8 8 3364 1116; + B 8 8 3384 1116; + B 8 8 3404 1116; + B 8 8 3424 1116; + B 8 8 3444 1116; + B 8 8 3464 1116; + B 8 8 3484 1116; + B 8 8 3504 1116; + B 8 8 3524 1116; + B 8 8 3544 1116; + B 8 8 3564 1116; + B 8 8 3584 1116; + B 8 8 3604 1116; + B 8 8 3624 1116; + B 8 8 3644 1116; + B 8 8 4084 1116; + B 8 8 4104 1116; + B 8 8 4124 1116; + B 8 8 4144 1116; + B 8 8 4164 1116; + B 8 8 4184 1116; + B 8 8 4204 1116; + B 8 8 4224 1116; + B 8 8 4244 1116; + B 8 8 4264 1116; + B 8 8 4284 1116; + B 8 8 4304 1116; + B 8 8 4324 1116; + B 8 8 4344 1116; + B 8 8 4364 1116; + B 8 8 4384 1116; + B 8 8 4404 1116; + B 8 8 4424 1116; + B 8 8 4444 1116; + B 8 8 4884 1116; + B 8 8 4904 1116; + B 8 8 4924 1116; + B 8 8 4944 1116; + B 8 8 4964 1116; + B 8 8 4984 1116; + B 8 8 5004 1116; + B 8 8 5024 1116; + B 8 8 5044 1116; + B 8 8 5064 1116; + B 8 8 5084 1116; + B 8 8 5104 1116; + B 8 8 5124 1116; + B 8 8 5144 1116; + B 8 8 5164 1116; + B 8 8 5184 1116; + B 8 8 5204 1116; + B 8 8 5224 1116; + B 8 8 5244 1116; + B 8 8 5684 1116; + B 8 8 5704 1116; + B 8 8 5724 1116; + B 8 8 5744 1116; + B 8 8 5764 1116; + B 8 8 5784 1116; + B 8 8 5804 1116; + B 8 8 5824 1116; + B 8 8 5844 1116; + B 8 8 5864 1116; + B 8 8 5884 1116; + B 8 8 5904 1116; + B 8 8 5924 1116; + B 8 8 5944 1116; + B 8 8 5964 1116; + B 8 8 5984 1116; + B 8 8 6004 1116; + B 8 8 6024 1116; + B 8 8 6044 1116; + B 8 8 6484 1116; + B 8 8 6504 1116; + B 8 8 6524 1116; + B 8 8 6544 1116; + B 8 8 6564 1116; + B 8 8 6584 1116; + B 8 8 6604 1116; + B 8 8 6624 1116; + B 8 8 6644 1116; + B 8 8 6664 1116; + B 8 8 6684 1116; + B 8 8 6704 1116; + B 8 8 6724 1116; + B 8 8 6744 1116; + B 8 8 6764 1116; + B 8 8 6784 1116; + B 8 8 6804 1116; + B 8 8 6824 1116; + B 8 8 6844 1116; + B 8 8 7284 1116; + B 8 8 7304 1116; + B 8 8 7324 1116; + B 8 8 7344 1116; + B 8 8 7364 1116; + B 8 8 7384 1116; + B 8 8 7404 1116; + B 8 8 7424 1116; + B 8 8 7444 1116; + B 8 8 7464 1116; + B 8 8 7484 1116; + B 8 8 7504 1116; + B 8 8 7524 1116; + B 8 8 7544 1116; + B 8 8 7564 1116; + B 8 8 7584 1116; + B 8 8 7604 1116; + B 8 8 7624 1116; + B 8 8 7644 1116; + B 8 8 84 1096; + B 8 8 104 1096; + B 8 8 124 1096; + B 8 8 144 1096; + B 8 8 164 1096; + B 8 8 184 1096; + B 8 8 204 1096; + B 8 8 224 1096; + B 8 8 244 1096; + B 8 8 264 1096; + B 8 8 284 1096; + B 8 8 304 1096; + B 8 8 324 1096; + B 8 8 344 1096; + B 8 8 364 1096; + B 8 8 384 1096; + B 8 8 404 1096; + B 8 8 424 1096; + B 8 8 444 1096; + B 8 8 884 1096; + B 8 8 904 1096; + B 8 8 924 1096; + B 8 8 944 1096; + B 8 8 964 1096; + B 8 8 984 1096; + B 8 8 1004 1096; + B 8 8 1024 1096; + B 8 8 1044 1096; + B 8 8 1064 1096; + B 8 8 1084 1096; + B 8 8 1104 1096; + B 8 8 1124 1096; + B 8 8 1144 1096; + B 8 8 1164 1096; + B 8 8 1184 1096; + B 8 8 1204 1096; + B 8 8 1224 1096; + B 8 8 1244 1096; + B 8 8 1684 1096; + B 8 8 1704 1096; + B 8 8 1724 1096; + B 8 8 1744 1096; + B 8 8 1764 1096; + B 8 8 1784 1096; + B 8 8 1804 1096; + B 8 8 1824 1096; + B 8 8 1844 1096; + B 8 8 1864 1096; + B 8 8 1884 1096; + B 8 8 1904 1096; + B 8 8 1924 1096; + B 8 8 1944 1096; + B 8 8 1964 1096; + B 8 8 1984 1096; + B 8 8 2004 1096; + B 8 8 2024 1096; + B 8 8 2044 1096; + B 8 8 2484 1096; + B 8 8 2504 1096; + B 8 8 2524 1096; + B 8 8 2544 1096; + B 8 8 2564 1096; + B 8 8 2584 1096; + B 8 8 2604 1096; + B 8 8 2624 1096; + B 8 8 2644 1096; + B 8 8 2664 1096; + B 8 8 2684 1096; + B 8 8 2704 1096; + B 8 8 2724 1096; + B 8 8 2744 1096; + B 8 8 2764 1096; + B 8 8 2784 1096; + B 8 8 2804 1096; + B 8 8 2824 1096; + B 8 8 2844 1096; + B 8 8 3284 1096; + B 8 8 3304 1096; + B 8 8 3324 1096; + B 8 8 3344 1096; + B 8 8 3364 1096; + B 8 8 3384 1096; + B 8 8 3404 1096; + B 8 8 3424 1096; + B 8 8 3444 1096; + B 8 8 3464 1096; + B 8 8 3484 1096; + B 8 8 3504 1096; + B 8 8 3524 1096; + B 8 8 3544 1096; + B 8 8 3564 1096; + B 8 8 3584 1096; + B 8 8 3604 1096; + B 8 8 3624 1096; + B 8 8 3644 1096; + B 8 8 4084 1096; + B 8 8 4104 1096; + B 8 8 4124 1096; + B 8 8 4144 1096; + B 8 8 4164 1096; + B 8 8 4184 1096; + B 8 8 4204 1096; + B 8 8 4224 1096; + B 8 8 4244 1096; + B 8 8 4264 1096; + B 8 8 4284 1096; + B 8 8 4304 1096; + B 8 8 4324 1096; + B 8 8 4344 1096; + B 8 8 4364 1096; + B 8 8 4384 1096; + B 8 8 4404 1096; + B 8 8 4424 1096; + B 8 8 4444 1096; + B 8 8 4884 1096; + B 8 8 4904 1096; + B 8 8 4924 1096; + B 8 8 4944 1096; + B 8 8 4964 1096; + B 8 8 4984 1096; + B 8 8 5004 1096; + B 8 8 5024 1096; + B 8 8 5044 1096; + B 8 8 5064 1096; + B 8 8 5084 1096; + B 8 8 5104 1096; + B 8 8 5124 1096; + B 8 8 5144 1096; + B 8 8 5164 1096; + B 8 8 5184 1096; + B 8 8 5204 1096; + B 8 8 5224 1096; + B 8 8 5244 1096; + B 8 8 5684 1096; + B 8 8 5704 1096; + B 8 8 5724 1096; + B 8 8 5744 1096; + B 8 8 5764 1096; + B 8 8 5784 1096; + B 8 8 5804 1096; + B 8 8 5824 1096; + B 8 8 5844 1096; + B 8 8 5864 1096; + B 8 8 5884 1096; + B 8 8 5904 1096; + B 8 8 5924 1096; + B 8 8 5944 1096; + B 8 8 5964 1096; + B 8 8 5984 1096; + B 8 8 6004 1096; + B 8 8 6024 1096; + B 8 8 6044 1096; + B 8 8 6484 1096; + B 8 8 6504 1096; + B 8 8 6524 1096; + B 8 8 6544 1096; + B 8 8 6564 1096; + B 8 8 6584 1096; + B 8 8 6604 1096; + B 8 8 6624 1096; + B 8 8 6644 1096; + B 8 8 6664 1096; + B 8 8 6684 1096; + B 8 8 6704 1096; + B 8 8 6724 1096; + B 8 8 6744 1096; + B 8 8 6764 1096; + B 8 8 6784 1096; + B 8 8 6804 1096; + B 8 8 6824 1096; + B 8 8 6844 1096; + B 8 8 7284 1096; + B 8 8 7304 1096; + B 8 8 7324 1096; + B 8 8 7344 1096; + B 8 8 7364 1096; + B 8 8 7384 1096; + B 8 8 7404 1096; + B 8 8 7424 1096; + B 8 8 7444 1096; + B 8 8 7464 1096; + B 8 8 7484 1096; + B 8 8 7504 1096; + B 8 8 7524 1096; + B 8 8 7544 1096; + B 8 8 7564 1096; + B 8 8 7584 1096; + B 8 8 7604 1096; + B 8 8 7624 1096; + B 8 8 7644 1096; + B 8 8 84 1076; + B 8 8 104 1076; + B 8 8 124 1076; + B 8 8 144 1076; + B 8 8 164 1076; + B 8 8 184 1076; + B 8 8 204 1076; + B 8 8 224 1076; + B 8 8 244 1076; + B 8 8 264 1076; + B 8 8 284 1076; + B 8 8 304 1076; + B 8 8 324 1076; + B 8 8 344 1076; + B 8 8 364 1076; + B 8 8 384 1076; + B 8 8 404 1076; + B 8 8 424 1076; + B 8 8 444 1076; + B 8 8 884 1076; + B 8 8 904 1076; + B 8 8 924 1076; + B 8 8 944 1076; + B 8 8 964 1076; + B 8 8 984 1076; + B 8 8 1004 1076; + B 8 8 1024 1076; + B 8 8 1044 1076; + B 8 8 1064 1076; + B 8 8 1084 1076; + B 8 8 1104 1076; + B 8 8 1124 1076; + B 8 8 1144 1076; + B 8 8 1164 1076; + B 8 8 1184 1076; + B 8 8 1204 1076; + B 8 8 1224 1076; + B 8 8 1244 1076; + B 8 8 1684 1076; + B 8 8 1704 1076; + B 8 8 1724 1076; + B 8 8 1744 1076; + B 8 8 1764 1076; + B 8 8 1784 1076; + B 8 8 1804 1076; + B 8 8 1824 1076; + B 8 8 1844 1076; + B 8 8 1864 1076; + B 8 8 1884 1076; + B 8 8 1904 1076; + B 8 8 1924 1076; + B 8 8 1944 1076; + B 8 8 1964 1076; + B 8 8 1984 1076; + B 8 8 2004 1076; + B 8 8 2024 1076; + B 8 8 2044 1076; + B 8 8 2484 1076; + B 8 8 2504 1076; + B 8 8 2524 1076; + B 8 8 2544 1076; + B 8 8 2564 1076; + B 8 8 2584 1076; + B 8 8 2604 1076; + B 8 8 2624 1076; + B 8 8 2644 1076; + B 8 8 2664 1076; + B 8 8 2684 1076; + B 8 8 2704 1076; + B 8 8 2724 1076; + B 8 8 2744 1076; + B 8 8 2764 1076; + B 8 8 2784 1076; + B 8 8 2804 1076; + B 8 8 2824 1076; + B 8 8 2844 1076; + B 8 8 3284 1076; + B 8 8 3304 1076; + B 8 8 3324 1076; + B 8 8 3344 1076; + B 8 8 3364 1076; + B 8 8 3384 1076; + B 8 8 3404 1076; + B 8 8 3424 1076; + B 8 8 3444 1076; + B 8 8 3464 1076; + B 8 8 3484 1076; + B 8 8 3504 1076; + B 8 8 3524 1076; + B 8 8 3544 1076; + B 8 8 3564 1076; + B 8 8 3584 1076; + B 8 8 3604 1076; + B 8 8 3624 1076; + B 8 8 3644 1076; + B 8 8 4084 1076; + B 8 8 4104 1076; + B 8 8 4124 1076; + B 8 8 4144 1076; + B 8 8 4164 1076; + B 8 8 4184 1076; + B 8 8 4204 1076; + B 8 8 4224 1076; + B 8 8 4244 1076; + B 8 8 4264 1076; + B 8 8 4284 1076; + B 8 8 4304 1076; + B 8 8 4324 1076; + B 8 8 4344 1076; + B 8 8 4364 1076; + B 8 8 4384 1076; + B 8 8 4404 1076; + B 8 8 4424 1076; + B 8 8 4444 1076; + B 8 8 4884 1076; + B 8 8 4904 1076; + B 8 8 4924 1076; + B 8 8 4944 1076; + B 8 8 4964 1076; + B 8 8 4984 1076; + B 8 8 5004 1076; + B 8 8 5024 1076; + B 8 8 5044 1076; + B 8 8 5064 1076; + B 8 8 5084 1076; + B 8 8 5104 1076; + B 8 8 5124 1076; + B 8 8 5144 1076; + B 8 8 5164 1076; + B 8 8 5184 1076; + B 8 8 5204 1076; + B 8 8 5224 1076; + B 8 8 5244 1076; + B 8 8 5684 1076; + B 8 8 5704 1076; + B 8 8 5724 1076; + B 8 8 5744 1076; + B 8 8 5764 1076; + B 8 8 5784 1076; + B 8 8 5804 1076; + B 8 8 5824 1076; + B 8 8 5844 1076; + B 8 8 5864 1076; + B 8 8 5884 1076; + B 8 8 5904 1076; + B 8 8 5924 1076; + B 8 8 5944 1076; + B 8 8 5964 1076; + B 8 8 5984 1076; + B 8 8 6004 1076; + B 8 8 6024 1076; + B 8 8 6044 1076; + B 8 8 6484 1076; + B 8 8 6504 1076; + B 8 8 6524 1076; + B 8 8 6544 1076; + B 8 8 6564 1076; + B 8 8 6584 1076; + B 8 8 6604 1076; + B 8 8 6624 1076; + B 8 8 6644 1076; + B 8 8 6664 1076; + B 8 8 6684 1076; + B 8 8 6704 1076; + B 8 8 6724 1076; + B 8 8 6744 1076; + B 8 8 6764 1076; + B 8 8 6784 1076; + B 8 8 6804 1076; + B 8 8 6824 1076; + B 8 8 6844 1076; + B 8 8 7284 1076; + B 8 8 7304 1076; + B 8 8 7324 1076; + B 8 8 7344 1076; + B 8 8 7364 1076; + B 8 8 7384 1076; + B 8 8 7404 1076; + B 8 8 7424 1076; + B 8 8 7444 1076; + B 8 8 7464 1076; + B 8 8 7484 1076; + B 8 8 7504 1076; + B 8 8 7524 1076; + B 8 8 7544 1076; + B 8 8 7564 1076; + B 8 8 7584 1076; + B 8 8 7604 1076; + B 8 8 7624 1076; + B 8 8 7644 1076; + B 8 8 84 1056; + B 8 8 104 1056; + B 8 8 124 1056; + B 8 8 144 1056; + B 8 8 164 1056; + B 8 8 184 1056; + B 8 8 204 1056; + B 8 8 224 1056; + B 8 8 244 1056; + B 8 8 264 1056; + B 8 8 284 1056; + B 8 8 304 1056; + B 8 8 324 1056; + B 8 8 344 1056; + B 8 8 364 1056; + B 8 8 384 1056; + B 8 8 404 1056; + B 8 8 424 1056; + B 8 8 444 1056; + B 8 8 884 1056; + B 8 8 904 1056; + B 8 8 924 1056; + B 8 8 944 1056; + B 8 8 964 1056; + B 8 8 984 1056; + B 8 8 1004 1056; + B 8 8 1024 1056; + B 8 8 1044 1056; + B 8 8 1064 1056; + B 8 8 1084 1056; + B 8 8 1104 1056; + B 8 8 1124 1056; + B 8 8 1144 1056; + B 8 8 1164 1056; + B 8 8 1184 1056; + B 8 8 1204 1056; + B 8 8 1224 1056; + B 8 8 1244 1056; + B 8 8 1684 1056; + B 8 8 1704 1056; + B 8 8 1724 1056; + B 8 8 1744 1056; + B 8 8 1764 1056; + B 8 8 1784 1056; + B 8 8 1804 1056; + B 8 8 1824 1056; + B 8 8 1844 1056; + B 8 8 1864 1056; + B 8 8 1884 1056; + B 8 8 1904 1056; + B 8 8 1924 1056; + B 8 8 1944 1056; + B 8 8 1964 1056; + B 8 8 1984 1056; + B 8 8 2004 1056; + B 8 8 2024 1056; + B 8 8 2044 1056; + B 8 8 2484 1056; + B 8 8 2504 1056; + B 8 8 2524 1056; + B 8 8 2544 1056; + B 8 8 2564 1056; + B 8 8 2584 1056; + B 8 8 2604 1056; + B 8 8 2624 1056; + B 8 8 2644 1056; + B 8 8 2664 1056; + B 8 8 2684 1056; + B 8 8 2704 1056; + B 8 8 2724 1056; + B 8 8 2744 1056; + B 8 8 2764 1056; + B 8 8 2784 1056; + B 8 8 2804 1056; + B 8 8 2824 1056; + B 8 8 2844 1056; + B 8 8 3284 1056; + B 8 8 3304 1056; + B 8 8 3324 1056; + B 8 8 3344 1056; + B 8 8 3364 1056; + B 8 8 3384 1056; + B 8 8 3404 1056; + B 8 8 3424 1056; + B 8 8 3444 1056; + B 8 8 3464 1056; + B 8 8 3484 1056; + B 8 8 3504 1056; + B 8 8 3524 1056; + B 8 8 3544 1056; + B 8 8 3564 1056; + B 8 8 3584 1056; + B 8 8 3604 1056; + B 8 8 3624 1056; + B 8 8 3644 1056; + B 8 8 4084 1056; + B 8 8 4104 1056; + B 8 8 4124 1056; + B 8 8 4144 1056; + B 8 8 4164 1056; + B 8 8 4184 1056; + B 8 8 4204 1056; + B 8 8 4224 1056; + B 8 8 4244 1056; + B 8 8 4264 1056; + B 8 8 4284 1056; + B 8 8 4304 1056; + B 8 8 4324 1056; + B 8 8 4344 1056; + B 8 8 4364 1056; + B 8 8 4384 1056; + B 8 8 4404 1056; + B 8 8 4424 1056; + B 8 8 4444 1056; + B 8 8 4884 1056; + B 8 8 4904 1056; + B 8 8 4924 1056; + B 8 8 4944 1056; + B 8 8 4964 1056; + B 8 8 4984 1056; + B 8 8 5004 1056; + B 8 8 5024 1056; + B 8 8 5044 1056; + B 8 8 5064 1056; + B 8 8 5084 1056; + B 8 8 5104 1056; + B 8 8 5124 1056; + B 8 8 5144 1056; + B 8 8 5164 1056; + B 8 8 5184 1056; + B 8 8 5204 1056; + B 8 8 5224 1056; + B 8 8 5244 1056; + B 8 8 5684 1056; + B 8 8 5704 1056; + B 8 8 5724 1056; + B 8 8 5744 1056; + B 8 8 5764 1056; + B 8 8 5784 1056; + B 8 8 5804 1056; + B 8 8 5824 1056; + B 8 8 5844 1056; + B 8 8 5864 1056; + B 8 8 5884 1056; + B 8 8 5904 1056; + B 8 8 5924 1056; + B 8 8 5944 1056; + B 8 8 5964 1056; + B 8 8 5984 1056; + B 8 8 6004 1056; + B 8 8 6024 1056; + B 8 8 6044 1056; + B 8 8 6484 1056; + B 8 8 6504 1056; + B 8 8 6524 1056; + B 8 8 6544 1056; + B 8 8 6564 1056; + B 8 8 6584 1056; + B 8 8 6604 1056; + B 8 8 6624 1056; + B 8 8 6644 1056; + B 8 8 6664 1056; + B 8 8 6684 1056; + B 8 8 6704 1056; + B 8 8 6724 1056; + B 8 8 6744 1056; + B 8 8 6764 1056; + B 8 8 6784 1056; + B 8 8 6804 1056; + B 8 8 6824 1056; + B 8 8 6844 1056; + B 8 8 7284 1056; + B 8 8 7304 1056; + B 8 8 7324 1056; + B 8 8 7344 1056; + B 8 8 7364 1056; + B 8 8 7384 1056; + B 8 8 7404 1056; + B 8 8 7424 1056; + B 8 8 7444 1056; + B 8 8 7464 1056; + B 8 8 7484 1056; + B 8 8 7504 1056; + B 8 8 7524 1056; + B 8 8 7544 1056; + B 8 8 7564 1056; + B 8 8 7584 1056; + B 8 8 7604 1056; + B 8 8 7624 1056; + B 8 8 7644 1056; + B 8 8 84 1036; + B 8 8 104 1036; + B 8 8 124 1036; + B 8 8 144 1036; + B 8 8 164 1036; + B 8 8 184 1036; + B 8 8 204 1036; + B 8 8 224 1036; + B 8 8 244 1036; + B 8 8 264 1036; + B 8 8 284 1036; + B 8 8 304 1036; + B 8 8 324 1036; + B 8 8 344 1036; + B 8 8 364 1036; + B 8 8 384 1036; + B 8 8 404 1036; + B 8 8 424 1036; + B 8 8 444 1036; + B 8 8 884 1036; + B 8 8 904 1036; + B 8 8 924 1036; + B 8 8 944 1036; + B 8 8 964 1036; + B 8 8 984 1036; + B 8 8 1004 1036; + B 8 8 1024 1036; + B 8 8 1044 1036; + B 8 8 1064 1036; + B 8 8 1084 1036; + B 8 8 1104 1036; + B 8 8 1124 1036; + B 8 8 1144 1036; + B 8 8 1164 1036; + B 8 8 1184 1036; + B 8 8 1204 1036; + B 8 8 1224 1036; + B 8 8 1244 1036; + B 8 8 1684 1036; + B 8 8 1704 1036; + B 8 8 1724 1036; + B 8 8 1744 1036; + B 8 8 1764 1036; + B 8 8 1784 1036; + B 8 8 1804 1036; + B 8 8 1824 1036; + B 8 8 1844 1036; + B 8 8 1864 1036; + B 8 8 1884 1036; + B 8 8 1904 1036; + B 8 8 1924 1036; + B 8 8 1944 1036; + B 8 8 1964 1036; + B 8 8 1984 1036; + B 8 8 2004 1036; + B 8 8 2024 1036; + B 8 8 2044 1036; + B 8 8 2484 1036; + B 8 8 2504 1036; + B 8 8 2524 1036; + B 8 8 2544 1036; + B 8 8 2564 1036; + B 8 8 2584 1036; + B 8 8 2604 1036; + B 8 8 2624 1036; + B 8 8 2644 1036; + B 8 8 2664 1036; + B 8 8 2684 1036; + B 8 8 2704 1036; + B 8 8 2724 1036; + B 8 8 2744 1036; + B 8 8 2764 1036; + B 8 8 2784 1036; + B 8 8 2804 1036; + B 8 8 2824 1036; + B 8 8 2844 1036; + B 8 8 3284 1036; + B 8 8 3304 1036; + B 8 8 3324 1036; + B 8 8 3344 1036; + B 8 8 3364 1036; + B 8 8 3384 1036; + B 8 8 3404 1036; + B 8 8 3424 1036; + B 8 8 3444 1036; + B 8 8 3464 1036; + B 8 8 3484 1036; + B 8 8 3504 1036; + B 8 8 3524 1036; + B 8 8 3544 1036; + B 8 8 3564 1036; + B 8 8 3584 1036; + B 8 8 3604 1036; + B 8 8 3624 1036; + B 8 8 3644 1036; + B 8 8 4084 1036; + B 8 8 4104 1036; + B 8 8 4124 1036; + B 8 8 4144 1036; + B 8 8 4164 1036; + B 8 8 4184 1036; + B 8 8 4204 1036; + B 8 8 4224 1036; + B 8 8 4244 1036; + B 8 8 4264 1036; + B 8 8 4284 1036; + B 8 8 4304 1036; + B 8 8 4324 1036; + B 8 8 4344 1036; + B 8 8 4364 1036; + B 8 8 4384 1036; + B 8 8 4404 1036; + B 8 8 4424 1036; + B 8 8 4444 1036; + B 8 8 4884 1036; + B 8 8 4904 1036; + B 8 8 4924 1036; + B 8 8 4944 1036; + B 8 8 4964 1036; + B 8 8 4984 1036; + B 8 8 5004 1036; + B 8 8 5024 1036; + B 8 8 5044 1036; + B 8 8 5064 1036; + B 8 8 5084 1036; + B 8 8 5104 1036; + B 8 8 5124 1036; + B 8 8 5144 1036; + B 8 8 5164 1036; + B 8 8 5184 1036; + B 8 8 5204 1036; + B 8 8 5224 1036; + B 8 8 5244 1036; + B 8 8 5684 1036; + B 8 8 5704 1036; + B 8 8 5724 1036; + B 8 8 5744 1036; + B 8 8 5764 1036; + B 8 8 5784 1036; + B 8 8 5804 1036; + B 8 8 5824 1036; + B 8 8 5844 1036; + B 8 8 5864 1036; + B 8 8 5884 1036; + B 8 8 5904 1036; + B 8 8 5924 1036; + B 8 8 5944 1036; + B 8 8 5964 1036; + B 8 8 5984 1036; + B 8 8 6004 1036; + B 8 8 6024 1036; + B 8 8 6044 1036; + B 8 8 6484 1036; + B 8 8 6504 1036; + B 8 8 6524 1036; + B 8 8 6544 1036; + B 8 8 6564 1036; + B 8 8 6584 1036; + B 8 8 6604 1036; + B 8 8 6624 1036; + B 8 8 6644 1036; + B 8 8 6664 1036; + B 8 8 6684 1036; + B 8 8 6704 1036; + B 8 8 6724 1036; + B 8 8 6744 1036; + B 8 8 6764 1036; + B 8 8 6784 1036; + B 8 8 6804 1036; + B 8 8 6824 1036; + B 8 8 6844 1036; + B 8 8 7284 1036; + B 8 8 7304 1036; + B 8 8 7324 1036; + B 8 8 7344 1036; + B 8 8 7364 1036; + B 8 8 7384 1036; + B 8 8 7404 1036; + B 8 8 7424 1036; + B 8 8 7444 1036; + B 8 8 7464 1036; + B 8 8 7484 1036; + B 8 8 7504 1036; + B 8 8 7524 1036; + B 8 8 7544 1036; + B 8 8 7564 1036; + B 8 8 7584 1036; + B 8 8 7604 1036; + B 8 8 7624 1036; + B 8 8 7644 1036; + B 8 8 84 1016; + B 8 8 104 1016; + B 8 8 124 1016; + B 8 8 144 1016; + B 8 8 164 1016; + B 8 8 184 1016; + B 8 8 204 1016; + B 8 8 224 1016; + B 8 8 244 1016; + B 8 8 264 1016; + B 8 8 284 1016; + B 8 8 304 1016; + B 8 8 324 1016; + B 8 8 344 1016; + B 8 8 364 1016; + B 8 8 384 1016; + B 8 8 404 1016; + B 8 8 424 1016; + B 8 8 444 1016; + B 8 8 884 1016; + B 8 8 904 1016; + B 8 8 924 1016; + B 8 8 944 1016; + B 8 8 964 1016; + B 8 8 984 1016; + B 8 8 1004 1016; + B 8 8 1024 1016; + B 8 8 1044 1016; + B 8 8 1064 1016; + B 8 8 1084 1016; + B 8 8 1104 1016; + B 8 8 1124 1016; + B 8 8 1144 1016; + B 8 8 1164 1016; + B 8 8 1184 1016; + B 8 8 1204 1016; + B 8 8 1224 1016; + B 8 8 1244 1016; + B 8 8 1684 1016; + B 8 8 1704 1016; + B 8 8 1724 1016; + B 8 8 1744 1016; + B 8 8 1764 1016; + B 8 8 1784 1016; + B 8 8 1804 1016; + B 8 8 1824 1016; + B 8 8 1844 1016; + B 8 8 1864 1016; + B 8 8 1884 1016; + B 8 8 1904 1016; + B 8 8 1924 1016; + B 8 8 1944 1016; + B 8 8 1964 1016; + B 8 8 1984 1016; + B 8 8 2004 1016; + B 8 8 2024 1016; + B 8 8 2044 1016; + B 8 8 2484 1016; + B 8 8 2504 1016; + B 8 8 2524 1016; + B 8 8 2544 1016; + B 8 8 2564 1016; + B 8 8 2584 1016; + B 8 8 2604 1016; + B 8 8 2624 1016; + B 8 8 2644 1016; + B 8 8 2664 1016; + B 8 8 2684 1016; + B 8 8 2704 1016; + B 8 8 2724 1016; + B 8 8 2744 1016; + B 8 8 2764 1016; + B 8 8 2784 1016; + B 8 8 2804 1016; + B 8 8 2824 1016; + B 8 8 2844 1016; + B 8 8 3284 1016; + B 8 8 3304 1016; + B 8 8 3324 1016; + B 8 8 3344 1016; + B 8 8 3364 1016; + B 8 8 3384 1016; + B 8 8 3404 1016; + B 8 8 3424 1016; + B 8 8 3444 1016; + B 8 8 3464 1016; + B 8 8 3484 1016; + B 8 8 3504 1016; + B 8 8 3524 1016; + B 8 8 3544 1016; + B 8 8 3564 1016; + B 8 8 3584 1016; + B 8 8 3604 1016; + B 8 8 3624 1016; + B 8 8 3644 1016; + B 8 8 4084 1016; + B 8 8 4104 1016; + B 8 8 4124 1016; + B 8 8 4144 1016; + B 8 8 4164 1016; + B 8 8 4184 1016; + B 8 8 4204 1016; + B 8 8 4224 1016; + B 8 8 4244 1016; + B 8 8 4264 1016; + B 8 8 4284 1016; + B 8 8 4304 1016; + B 8 8 4324 1016; + B 8 8 4344 1016; + B 8 8 4364 1016; + B 8 8 4384 1016; + B 8 8 4404 1016; + B 8 8 4424 1016; + B 8 8 4444 1016; + B 8 8 4884 1016; + B 8 8 4904 1016; + B 8 8 4924 1016; + B 8 8 4944 1016; + B 8 8 4964 1016; + B 8 8 4984 1016; + B 8 8 5004 1016; + B 8 8 5024 1016; + B 8 8 5044 1016; + B 8 8 5064 1016; + B 8 8 5084 1016; + B 8 8 5104 1016; + B 8 8 5124 1016; + B 8 8 5144 1016; + B 8 8 5164 1016; + B 8 8 5184 1016; + B 8 8 5204 1016; + B 8 8 5224 1016; + B 8 8 5244 1016; + B 8 8 5684 1016; + B 8 8 5704 1016; + B 8 8 5724 1016; + B 8 8 5744 1016; + B 8 8 5764 1016; + B 8 8 5784 1016; + B 8 8 5804 1016; + B 8 8 5824 1016; + B 8 8 5844 1016; + B 8 8 5864 1016; + B 8 8 5884 1016; + B 8 8 5904 1016; + B 8 8 5924 1016; + B 8 8 5944 1016; + B 8 8 5964 1016; + B 8 8 5984 1016; + B 8 8 6004 1016; + B 8 8 6024 1016; + B 8 8 6044 1016; + B 8 8 6484 1016; + B 8 8 6504 1016; + B 8 8 6524 1016; + B 8 8 6544 1016; + B 8 8 6564 1016; + B 8 8 6584 1016; + B 8 8 6604 1016; + B 8 8 6624 1016; + B 8 8 6644 1016; + B 8 8 6664 1016; + B 8 8 6684 1016; + B 8 8 6704 1016; + B 8 8 6724 1016; + B 8 8 6744 1016; + B 8 8 6764 1016; + B 8 8 6784 1016; + B 8 8 6804 1016; + B 8 8 6824 1016; + B 8 8 6844 1016; + B 8 8 7284 1016; + B 8 8 7304 1016; + B 8 8 7324 1016; + B 8 8 7344 1016; + B 8 8 7364 1016; + B 8 8 7384 1016; + B 8 8 7404 1016; + B 8 8 7424 1016; + B 8 8 7444 1016; + B 8 8 7464 1016; + B 8 8 7484 1016; + B 8 8 7504 1016; + B 8 8 7524 1016; + B 8 8 7544 1016; + B 8 8 7564 1016; + B 8 8 7584 1016; + B 8 8 7604 1016; + B 8 8 7624 1016; + B 8 8 7644 1016; + B 8 8 84 996; + B 8 8 104 996; + B 8 8 124 996; + B 8 8 144 996; + B 8 8 164 996; + B 8 8 184 996; + B 8 8 204 996; + B 8 8 224 996; + B 8 8 244 996; + B 8 8 264 996; + B 8 8 284 996; + B 8 8 304 996; + B 8 8 324 996; + B 8 8 344 996; + B 8 8 364 996; + B 8 8 384 996; + B 8 8 404 996; + B 8 8 424 996; + B 8 8 444 996; + B 8 8 884 996; + B 8 8 904 996; + B 8 8 924 996; + B 8 8 944 996; + B 8 8 964 996; + B 8 8 984 996; + B 8 8 1004 996; + B 8 8 1024 996; + B 8 8 1044 996; + B 8 8 1064 996; + B 8 8 1084 996; + B 8 8 1104 996; + B 8 8 1124 996; + B 8 8 1144 996; + B 8 8 1164 996; + B 8 8 1184 996; + B 8 8 1204 996; + B 8 8 1224 996; + B 8 8 1244 996; + B 8 8 1684 996; + B 8 8 1704 996; + B 8 8 1724 996; + B 8 8 1744 996; + B 8 8 1764 996; + B 8 8 1784 996; + B 8 8 1804 996; + B 8 8 1824 996; + B 8 8 1844 996; + B 8 8 1864 996; + B 8 8 1884 996; + B 8 8 1904 996; + B 8 8 1924 996; + B 8 8 1944 996; + B 8 8 1964 996; + B 8 8 1984 996; + B 8 8 2004 996; + B 8 8 2024 996; + B 8 8 2044 996; + B 8 8 2484 996; + B 8 8 2504 996; + B 8 8 2524 996; + B 8 8 2544 996; + B 8 8 2564 996; + B 8 8 2584 996; + B 8 8 2604 996; + B 8 8 2624 996; + B 8 8 2644 996; + B 8 8 2664 996; + B 8 8 2684 996; + B 8 8 2704 996; + B 8 8 2724 996; + B 8 8 2744 996; + B 8 8 2764 996; + B 8 8 2784 996; + B 8 8 2804 996; + B 8 8 2824 996; + B 8 8 2844 996; + B 8 8 3284 996; + B 8 8 3304 996; + B 8 8 3324 996; + B 8 8 3344 996; + B 8 8 3364 996; + B 8 8 3384 996; + B 8 8 3404 996; + B 8 8 3424 996; + B 8 8 3444 996; + B 8 8 3464 996; + B 8 8 3484 996; + B 8 8 3504 996; + B 8 8 3524 996; + B 8 8 3544 996; + B 8 8 3564 996; + B 8 8 3584 996; + B 8 8 3604 996; + B 8 8 3624 996; + B 8 8 3644 996; + B 8 8 4084 996; + B 8 8 4104 996; + B 8 8 4124 996; + B 8 8 4144 996; + B 8 8 4164 996; + B 8 8 4184 996; + B 8 8 4204 996; + B 8 8 4224 996; + B 8 8 4244 996; + B 8 8 4264 996; + B 8 8 4284 996; + B 8 8 4304 996; + B 8 8 4324 996; + B 8 8 4344 996; + B 8 8 4364 996; + B 8 8 4384 996; + B 8 8 4404 996; + B 8 8 4424 996; + B 8 8 4444 996; + B 8 8 4884 996; + B 8 8 4904 996; + B 8 8 4924 996; + B 8 8 4944 996; + B 8 8 4964 996; + B 8 8 4984 996; + B 8 8 5004 996; + B 8 8 5024 996; + B 8 8 5044 996; + B 8 8 5064 996; + B 8 8 5084 996; + B 8 8 5104 996; + B 8 8 5124 996; + B 8 8 5144 996; + B 8 8 5164 996; + B 8 8 5184 996; + B 8 8 5204 996; + B 8 8 5224 996; + B 8 8 5244 996; + B 8 8 5684 996; + B 8 8 5704 996; + B 8 8 5724 996; + B 8 8 5744 996; + B 8 8 5764 996; + B 8 8 5784 996; + B 8 8 5804 996; + B 8 8 5824 996; + B 8 8 5844 996; + B 8 8 5864 996; + B 8 8 5884 996; + B 8 8 5904 996; + B 8 8 5924 996; + B 8 8 5944 996; + B 8 8 5964 996; + B 8 8 5984 996; + B 8 8 6004 996; + B 8 8 6024 996; + B 8 8 6044 996; + B 8 8 6484 996; + B 8 8 6504 996; + B 8 8 6524 996; + B 8 8 6544 996; + B 8 8 6564 996; + B 8 8 6584 996; + B 8 8 6604 996; + B 8 8 6624 996; + B 8 8 6644 996; + B 8 8 6664 996; + B 8 8 6684 996; + B 8 8 6704 996; + B 8 8 6724 996; + B 8 8 6744 996; + B 8 8 6764 996; + B 8 8 6784 996; + B 8 8 6804 996; + B 8 8 6824 996; + B 8 8 6844 996; + B 8 8 7284 996; + B 8 8 7304 996; + B 8 8 7324 996; + B 8 8 7344 996; + B 8 8 7364 996; + B 8 8 7384 996; + B 8 8 7404 996; + B 8 8 7424 996; + B 8 8 7444 996; + B 8 8 7464 996; + B 8 8 7484 996; + B 8 8 7504 996; + B 8 8 7524 996; + B 8 8 7544 996; + B 8 8 7564 996; + B 8 8 7584 996; + B 8 8 7604 996; + B 8 8 7624 996; + B 8 8 7644 996; + B 8 8 84 976; + B 8 8 104 976; + B 8 8 124 976; + B 8 8 144 976; + B 8 8 164 976; + B 8 8 184 976; + B 8 8 204 976; + B 8 8 224 976; + B 8 8 244 976; + B 8 8 264 976; + B 8 8 284 976; + B 8 8 304 976; + B 8 8 324 976; + B 8 8 344 976; + B 8 8 364 976; + B 8 8 384 976; + B 8 8 404 976; + B 8 8 424 976; + B 8 8 444 976; + B 8 8 884 976; + B 8 8 904 976; + B 8 8 924 976; + B 8 8 944 976; + B 8 8 964 976; + B 8 8 984 976; + B 8 8 1004 976; + B 8 8 1024 976; + B 8 8 1044 976; + B 8 8 1064 976; + B 8 8 1084 976; + B 8 8 1104 976; + B 8 8 1124 976; + B 8 8 1144 976; + B 8 8 1164 976; + B 8 8 1184 976; + B 8 8 1204 976; + B 8 8 1224 976; + B 8 8 1244 976; + B 8 8 1684 976; + B 8 8 1704 976; + B 8 8 1724 976; + B 8 8 1744 976; + B 8 8 1764 976; + B 8 8 1784 976; + B 8 8 1804 976; + B 8 8 1824 976; + B 8 8 1844 976; + B 8 8 1864 976; + B 8 8 1884 976; + B 8 8 1904 976; + B 8 8 1924 976; + B 8 8 1944 976; + B 8 8 1964 976; + B 8 8 1984 976; + B 8 8 2004 976; + B 8 8 2024 976; + B 8 8 2044 976; + B 8 8 2484 976; + B 8 8 2504 976; + B 8 8 2524 976; + B 8 8 2544 976; + B 8 8 2564 976; + B 8 8 2584 976; + B 8 8 2604 976; + B 8 8 2624 976; + B 8 8 2644 976; + B 8 8 2664 976; + B 8 8 2684 976; + B 8 8 2704 976; + B 8 8 2724 976; + B 8 8 2744 976; + B 8 8 2764 976; + B 8 8 2784 976; + B 8 8 2804 976; + B 8 8 2824 976; + B 8 8 2844 976; + B 8 8 3284 976; + B 8 8 3304 976; + B 8 8 3324 976; + B 8 8 3344 976; + B 8 8 3364 976; + B 8 8 3384 976; + B 8 8 3404 976; + B 8 8 3424 976; + B 8 8 3444 976; + B 8 8 3464 976; + B 8 8 3484 976; + B 8 8 3504 976; + B 8 8 3524 976; + B 8 8 3544 976; + B 8 8 3564 976; + B 8 8 3584 976; + B 8 8 3604 976; + B 8 8 3624 976; + B 8 8 3644 976; + B 8 8 4084 976; + B 8 8 4104 976; + B 8 8 4124 976; + B 8 8 4144 976; + B 8 8 4164 976; + B 8 8 4184 976; + B 8 8 4204 976; + B 8 8 4224 976; + B 8 8 4244 976; + B 8 8 4264 976; + B 8 8 4284 976; + B 8 8 4304 976; + B 8 8 4324 976; + B 8 8 4344 976; + B 8 8 4364 976; + B 8 8 4384 976; + B 8 8 4404 976; + B 8 8 4424 976; + B 8 8 4444 976; + B 8 8 4884 976; + B 8 8 4904 976; + B 8 8 4924 976; + B 8 8 4944 976; + B 8 8 4964 976; + B 8 8 4984 976; + B 8 8 5004 976; + B 8 8 5024 976; + B 8 8 5044 976; + B 8 8 5064 976; + B 8 8 5084 976; + B 8 8 5104 976; + B 8 8 5124 976; + B 8 8 5144 976; + B 8 8 5164 976; + B 8 8 5184 976; + B 8 8 5204 976; + B 8 8 5224 976; + B 8 8 5244 976; + B 8 8 5684 976; + B 8 8 5704 976; + B 8 8 5724 976; + B 8 8 5744 976; + B 8 8 5764 976; + B 8 8 5784 976; + B 8 8 5804 976; + B 8 8 5824 976; + B 8 8 5844 976; + B 8 8 5864 976; + B 8 8 5884 976; + B 8 8 5904 976; + B 8 8 5924 976; + B 8 8 5944 976; + B 8 8 5964 976; + B 8 8 5984 976; + B 8 8 6004 976; + B 8 8 6024 976; + B 8 8 6044 976; + B 8 8 6484 976; + B 8 8 6504 976; + B 8 8 6524 976; + B 8 8 6544 976; + B 8 8 6564 976; + B 8 8 6584 976; + B 8 8 6604 976; + B 8 8 6624 976; + B 8 8 6644 976; + B 8 8 6664 976; + B 8 8 6684 976; + B 8 8 6704 976; + B 8 8 6724 976; + B 8 8 6744 976; + B 8 8 6764 976; + B 8 8 6784 976; + B 8 8 6804 976; + B 8 8 6824 976; + B 8 8 6844 976; + B 8 8 7284 976; + B 8 8 7304 976; + B 8 8 7324 976; + B 8 8 7344 976; + B 8 8 7364 976; + B 8 8 7384 976; + B 8 8 7404 976; + B 8 8 7424 976; + B 8 8 7444 976; + B 8 8 7464 976; + B 8 8 7484 976; + B 8 8 7504 976; + B 8 8 7524 976; + B 8 8 7544 976; + B 8 8 7564 976; + B 8 8 7584 976; + B 8 8 7604 976; + B 8 8 7624 976; + B 8 8 7644 976; + B 8 8 84 956; + B 8 8 104 956; + B 8 8 124 956; + B 8 8 144 956; + B 8 8 164 956; + B 8 8 184 956; + B 8 8 204 956; + B 8 8 224 956; + B 8 8 244 956; + B 8 8 264 956; + B 8 8 284 956; + B 8 8 304 956; + B 8 8 324 956; + B 8 8 344 956; + B 8 8 364 956; + B 8 8 384 956; + B 8 8 404 956; + B 8 8 424 956; + B 8 8 444 956; + B 8 8 884 956; + B 8 8 904 956; + B 8 8 924 956; + B 8 8 944 956; + B 8 8 964 956; + B 8 8 984 956; + B 8 8 1004 956; + B 8 8 1024 956; + B 8 8 1044 956; + B 8 8 1064 956; + B 8 8 1084 956; + B 8 8 1104 956; + B 8 8 1124 956; + B 8 8 1144 956; + B 8 8 1164 956; + B 8 8 1184 956; + B 8 8 1204 956; + B 8 8 1224 956; + B 8 8 1244 956; + B 8 8 1684 956; + B 8 8 1704 956; + B 8 8 1724 956; + B 8 8 1744 956; + B 8 8 1764 956; + B 8 8 1784 956; + B 8 8 1804 956; + B 8 8 1824 956; + B 8 8 1844 956; + B 8 8 1864 956; + B 8 8 1884 956; + B 8 8 1904 956; + B 8 8 1924 956; + B 8 8 1944 956; + B 8 8 1964 956; + B 8 8 1984 956; + B 8 8 2004 956; + B 8 8 2024 956; + B 8 8 2044 956; + B 8 8 2484 956; + B 8 8 2504 956; + B 8 8 2524 956; + B 8 8 2544 956; + B 8 8 2564 956; + B 8 8 2584 956; + B 8 8 2604 956; + B 8 8 2624 956; + B 8 8 2644 956; + B 8 8 2664 956; + B 8 8 2684 956; + B 8 8 2704 956; + B 8 8 2724 956; + B 8 8 2744 956; + B 8 8 2764 956; + B 8 8 2784 956; + B 8 8 2804 956; + B 8 8 2824 956; + B 8 8 2844 956; + B 8 8 3284 956; + B 8 8 3304 956; + B 8 8 3324 956; + B 8 8 3344 956; + B 8 8 3364 956; + B 8 8 3384 956; + B 8 8 3404 956; + B 8 8 3424 956; + B 8 8 3444 956; + B 8 8 3464 956; + B 8 8 3484 956; + B 8 8 3504 956; + B 8 8 3524 956; + B 8 8 3544 956; + B 8 8 3564 956; + B 8 8 3584 956; + B 8 8 3604 956; + B 8 8 3624 956; + B 8 8 3644 956; + B 8 8 4084 956; + B 8 8 4104 956; + B 8 8 4124 956; + B 8 8 4144 956; + B 8 8 4164 956; + B 8 8 4184 956; + B 8 8 4204 956; + B 8 8 4224 956; + B 8 8 4244 956; + B 8 8 4264 956; + B 8 8 4284 956; + B 8 8 4304 956; + B 8 8 4324 956; + B 8 8 4344 956; + B 8 8 4364 956; + B 8 8 4384 956; + B 8 8 4404 956; + B 8 8 4424 956; + B 8 8 4444 956; + B 8 8 4884 956; + B 8 8 4904 956; + B 8 8 4924 956; + B 8 8 4944 956; + B 8 8 4964 956; + B 8 8 4984 956; + B 8 8 5004 956; + B 8 8 5024 956; + B 8 8 5044 956; + B 8 8 5064 956; + B 8 8 5084 956; + B 8 8 5104 956; + B 8 8 5124 956; + B 8 8 5144 956; + B 8 8 5164 956; + B 8 8 5184 956; + B 8 8 5204 956; + B 8 8 5224 956; + B 8 8 5244 956; + B 8 8 5684 956; + B 8 8 5704 956; + B 8 8 5724 956; + B 8 8 5744 956; + B 8 8 5764 956; + B 8 8 5784 956; + B 8 8 5804 956; + B 8 8 5824 956; + B 8 8 5844 956; + B 8 8 5864 956; + B 8 8 5884 956; + B 8 8 5904 956; + B 8 8 5924 956; + B 8 8 5944 956; + B 8 8 5964 956; + B 8 8 5984 956; + B 8 8 6004 956; + B 8 8 6024 956; + B 8 8 6044 956; + B 8 8 6484 956; + B 8 8 6504 956; + B 8 8 6524 956; + B 8 8 6544 956; + B 8 8 6564 956; + B 8 8 6584 956; + B 8 8 6604 956; + B 8 8 6624 956; + B 8 8 6644 956; + B 8 8 6664 956; + B 8 8 6684 956; + B 8 8 6704 956; + B 8 8 6724 956; + B 8 8 6744 956; + B 8 8 6764 956; + B 8 8 6784 956; + B 8 8 6804 956; + B 8 8 6824 956; + B 8 8 6844 956; + B 8 8 7284 956; + B 8 8 7304 956; + B 8 8 7324 956; + B 8 8 7344 956; + B 8 8 7364 956; + B 8 8 7384 956; + B 8 8 7404 956; + B 8 8 7424 956; + B 8 8 7444 956; + B 8 8 7464 956; + B 8 8 7484 956; + B 8 8 7504 956; + B 8 8 7524 956; + B 8 8 7544 956; + B 8 8 7564 956; + B 8 8 7584 956; + B 8 8 7604 956; + B 8 8 7624 956; + B 8 8 7644 956; + B 8 8 84 936; + B 8 8 104 936; + B 8 8 124 936; + B 8 8 144 936; + B 8 8 164 936; + B 8 8 184 936; + B 8 8 204 936; + B 8 8 224 936; + B 8 8 244 936; + B 8 8 264 936; + B 8 8 284 936; + B 8 8 304 936; + B 8 8 324 936; + B 8 8 344 936; + B 8 8 364 936; + B 8 8 384 936; + B 8 8 404 936; + B 8 8 424 936; + B 8 8 444 936; + B 8 8 884 936; + B 8 8 904 936; + B 8 8 924 936; + B 8 8 944 936; + B 8 8 964 936; + B 8 8 984 936; + B 8 8 1004 936; + B 8 8 1024 936; + B 8 8 1044 936; + B 8 8 1064 936; + B 8 8 1084 936; + B 8 8 1104 936; + B 8 8 1124 936; + B 8 8 1144 936; + B 8 8 1164 936; + B 8 8 1184 936; + B 8 8 1204 936; + B 8 8 1224 936; + B 8 8 1244 936; + B 8 8 1684 936; + B 8 8 1704 936; + B 8 8 1724 936; + B 8 8 1744 936; + B 8 8 1764 936; + B 8 8 1784 936; + B 8 8 1804 936; + B 8 8 1824 936; + B 8 8 1844 936; + B 8 8 1864 936; + B 8 8 1884 936; + B 8 8 1904 936; + B 8 8 1924 936; + B 8 8 1944 936; + B 8 8 1964 936; + B 8 8 1984 936; + B 8 8 2004 936; + B 8 8 2024 936; + B 8 8 2044 936; + B 8 8 2484 936; + B 8 8 2504 936; + B 8 8 2524 936; + B 8 8 2544 936; + B 8 8 2564 936; + B 8 8 2584 936; + B 8 8 2604 936; + B 8 8 2624 936; + B 8 8 2644 936; + B 8 8 2664 936; + B 8 8 2684 936; + B 8 8 2704 936; + B 8 8 2724 936; + B 8 8 2744 936; + B 8 8 2764 936; + B 8 8 2784 936; + B 8 8 2804 936; + B 8 8 2824 936; + B 8 8 2844 936; + B 8 8 3284 936; + B 8 8 3304 936; + B 8 8 3324 936; + B 8 8 3344 936; + B 8 8 3364 936; + B 8 8 3384 936; + B 8 8 3404 936; + B 8 8 3424 936; + B 8 8 3444 936; + B 8 8 3464 936; + B 8 8 3484 936; + B 8 8 3504 936; + B 8 8 3524 936; + B 8 8 3544 936; + B 8 8 3564 936; + B 8 8 3584 936; + B 8 8 3604 936; + B 8 8 3624 936; + B 8 8 3644 936; + B 8 8 4084 936; + B 8 8 4104 936; + B 8 8 4124 936; + B 8 8 4144 936; + B 8 8 4164 936; + B 8 8 4184 936; + B 8 8 4204 936; + B 8 8 4224 936; + B 8 8 4244 936; + B 8 8 4264 936; + B 8 8 4284 936; + B 8 8 4304 936; + B 8 8 4324 936; + B 8 8 4344 936; + B 8 8 4364 936; + B 8 8 4384 936; + B 8 8 4404 936; + B 8 8 4424 936; + B 8 8 4444 936; + B 8 8 4884 936; + B 8 8 4904 936; + B 8 8 4924 936; + B 8 8 4944 936; + B 8 8 4964 936; + B 8 8 4984 936; + B 8 8 5004 936; + B 8 8 5024 936; + B 8 8 5044 936; + B 8 8 5064 936; + B 8 8 5084 936; + B 8 8 5104 936; + B 8 8 5124 936; + B 8 8 5144 936; + B 8 8 5164 936; + B 8 8 5184 936; + B 8 8 5204 936; + B 8 8 5224 936; + B 8 8 5244 936; + B 8 8 5684 936; + B 8 8 5704 936; + B 8 8 5724 936; + B 8 8 5744 936; + B 8 8 5764 936; + B 8 8 5784 936; + B 8 8 5804 936; + B 8 8 5824 936; + B 8 8 5844 936; + B 8 8 5864 936; + B 8 8 5884 936; + B 8 8 5904 936; + B 8 8 5924 936; + B 8 8 5944 936; + B 8 8 5964 936; + B 8 8 5984 936; + B 8 8 6004 936; + B 8 8 6024 936; + B 8 8 6044 936; + B 8 8 6484 936; + B 8 8 6504 936; + B 8 8 6524 936; + B 8 8 6544 936; + B 8 8 6564 936; + B 8 8 6584 936; + B 8 8 6604 936; + B 8 8 6624 936; + B 8 8 6644 936; + B 8 8 6664 936; + B 8 8 6684 936; + B 8 8 6704 936; + B 8 8 6724 936; + B 8 8 6744 936; + B 8 8 6764 936; + B 8 8 6784 936; + B 8 8 6804 936; + B 8 8 6824 936; + B 8 8 6844 936; + B 8 8 7284 936; + B 8 8 7304 936; + B 8 8 7324 936; + B 8 8 7344 936; + B 8 8 7364 936; + B 8 8 7384 936; + B 8 8 7404 936; + B 8 8 7424 936; + B 8 8 7444 936; + B 8 8 7464 936; + B 8 8 7484 936; + B 8 8 7504 936; + B 8 8 7524 936; + B 8 8 7544 936; + B 8 8 7564 936; + B 8 8 7584 936; + B 8 8 7604 936; + B 8 8 7624 936; + B 8 8 7644 936; + B 8 8 84 916; + B 8 8 104 916; + B 8 8 124 916; + B 8 8 144 916; + B 8 8 164 916; + B 8 8 184 916; + B 8 8 204 916; + B 8 8 224 916; + B 8 8 244 916; + B 8 8 264 916; + B 8 8 284 916; + B 8 8 304 916; + B 8 8 324 916; + B 8 8 344 916; + B 8 8 364 916; + B 8 8 384 916; + B 8 8 404 916; + B 8 8 424 916; + B 8 8 444 916; + B 8 8 884 916; + B 8 8 904 916; + B 8 8 924 916; + B 8 8 944 916; + B 8 8 964 916; + B 8 8 984 916; + B 8 8 1004 916; + B 8 8 1024 916; + B 8 8 1044 916; + B 8 8 1064 916; + B 8 8 1084 916; + B 8 8 1104 916; + B 8 8 1124 916; + B 8 8 1144 916; + B 8 8 1164 916; + B 8 8 1184 916; + B 8 8 1204 916; + B 8 8 1224 916; + B 8 8 1244 916; + B 8 8 1684 916; + B 8 8 1704 916; + B 8 8 1724 916; + B 8 8 1744 916; + B 8 8 1764 916; + B 8 8 1784 916; + B 8 8 1804 916; + B 8 8 1824 916; + B 8 8 1844 916; + B 8 8 1864 916; + B 8 8 1884 916; + B 8 8 1904 916; + B 8 8 1924 916; + B 8 8 1944 916; + B 8 8 1964 916; + B 8 8 1984 916; + B 8 8 2004 916; + B 8 8 2024 916; + B 8 8 2044 916; + B 8 8 2484 916; + B 8 8 2504 916; + B 8 8 2524 916; + B 8 8 2544 916; + B 8 8 2564 916; + B 8 8 2584 916; + B 8 8 2604 916; + B 8 8 2624 916; + B 8 8 2644 916; + B 8 8 2664 916; + B 8 8 2684 916; + B 8 8 2704 916; + B 8 8 2724 916; + B 8 8 2744 916; + B 8 8 2764 916; + B 8 8 2784 916; + B 8 8 2804 916; + B 8 8 2824 916; + B 8 8 2844 916; + B 8 8 3284 916; + B 8 8 3304 916; + B 8 8 3324 916; + B 8 8 3344 916; + B 8 8 3364 916; + B 8 8 3384 916; + B 8 8 3404 916; + B 8 8 3424 916; + B 8 8 3444 916; + B 8 8 3464 916; + B 8 8 3484 916; + B 8 8 3504 916; + B 8 8 3524 916; + B 8 8 3544 916; + B 8 8 3564 916; + B 8 8 3584 916; + B 8 8 3604 916; + B 8 8 3624 916; + B 8 8 3644 916; + B 8 8 4084 916; + B 8 8 4104 916; + B 8 8 4124 916; + B 8 8 4144 916; + B 8 8 4164 916; + B 8 8 4184 916; + B 8 8 4204 916; + B 8 8 4224 916; + B 8 8 4244 916; + B 8 8 4264 916; + B 8 8 4284 916; + B 8 8 4304 916; + B 8 8 4324 916; + B 8 8 4344 916; + B 8 8 4364 916; + B 8 8 4384 916; + B 8 8 4404 916; + B 8 8 4424 916; + B 8 8 4444 916; + B 8 8 4884 916; + B 8 8 4904 916; + B 8 8 4924 916; + B 8 8 4944 916; + B 8 8 4964 916; + B 8 8 4984 916; + B 8 8 5004 916; + B 8 8 5024 916; + B 8 8 5044 916; + B 8 8 5064 916; + B 8 8 5084 916; + B 8 8 5104 916; + B 8 8 5124 916; + B 8 8 5144 916; + B 8 8 5164 916; + B 8 8 5184 916; + B 8 8 5204 916; + B 8 8 5224 916; + B 8 8 5244 916; + B 8 8 5684 916; + B 8 8 5704 916; + B 8 8 5724 916; + B 8 8 5744 916; + B 8 8 5764 916; + B 8 8 5784 916; + B 8 8 5804 916; + B 8 8 5824 916; + B 8 8 5844 916; + B 8 8 5864 916; + B 8 8 5884 916; + B 8 8 5904 916; + B 8 8 5924 916; + B 8 8 5944 916; + B 8 8 5964 916; + B 8 8 5984 916; + B 8 8 6004 916; + B 8 8 6024 916; + B 8 8 6044 916; + B 8 8 6484 916; + B 8 8 6504 916; + B 8 8 6524 916; + B 8 8 6544 916; + B 8 8 6564 916; + B 8 8 6584 916; + B 8 8 6604 916; + B 8 8 6624 916; + B 8 8 6644 916; + B 8 8 6664 916; + B 8 8 6684 916; + B 8 8 6704 916; + B 8 8 6724 916; + B 8 8 6744 916; + B 8 8 6764 916; + B 8 8 6784 916; + B 8 8 6804 916; + B 8 8 6824 916; + B 8 8 6844 916; + B 8 8 7284 916; + B 8 8 7304 916; + B 8 8 7324 916; + B 8 8 7344 916; + B 8 8 7364 916; + B 8 8 7384 916; + B 8 8 7404 916; + B 8 8 7424 916; + B 8 8 7444 916; + B 8 8 7464 916; + B 8 8 7484 916; + B 8 8 7504 916; + B 8 8 7524 916; + B 8 8 7544 916; + B 8 8 7564 916; + B 8 8 7584 916; + B 8 8 7604 916; + B 8 8 7624 916; + B 8 8 7644 916; + B 8 8 84 896; + B 8 8 104 896; + B 8 8 124 896; + B 8 8 144 896; + B 8 8 164 896; + B 8 8 184 896; + B 8 8 204 896; + B 8 8 224 896; + B 8 8 244 896; + B 8 8 264 896; + B 8 8 284 896; + B 8 8 304 896; + B 8 8 324 896; + B 8 8 344 896; + B 8 8 364 896; + B 8 8 384 896; + B 8 8 404 896; + B 8 8 424 896; + B 8 8 444 896; + B 8 8 884 896; + B 8 8 904 896; + B 8 8 924 896; + B 8 8 944 896; + B 8 8 964 896; + B 8 8 984 896; + B 8 8 1004 896; + B 8 8 1024 896; + B 8 8 1044 896; + B 8 8 1064 896; + B 8 8 1084 896; + B 8 8 1104 896; + B 8 8 1124 896; + B 8 8 1144 896; + B 8 8 1164 896; + B 8 8 1184 896; + B 8 8 1204 896; + B 8 8 1224 896; + B 8 8 1244 896; + B 8 8 1684 896; + B 8 8 1704 896; + B 8 8 1724 896; + B 8 8 1744 896; + B 8 8 1764 896; + B 8 8 1784 896; + B 8 8 1804 896; + B 8 8 1824 896; + B 8 8 1844 896; + B 8 8 1864 896; + B 8 8 1884 896; + B 8 8 1904 896; + B 8 8 1924 896; + B 8 8 1944 896; + B 8 8 1964 896; + B 8 8 1984 896; + B 8 8 2004 896; + B 8 8 2024 896; + B 8 8 2044 896; + B 8 8 2484 896; + B 8 8 2504 896; + B 8 8 2524 896; + B 8 8 2544 896; + B 8 8 2564 896; + B 8 8 2584 896; + B 8 8 2604 896; + B 8 8 2624 896; + B 8 8 2644 896; + B 8 8 2664 896; + B 8 8 2684 896; + B 8 8 2704 896; + B 8 8 2724 896; + B 8 8 2744 896; + B 8 8 2764 896; + B 8 8 2784 896; + B 8 8 2804 896; + B 8 8 2824 896; + B 8 8 2844 896; + B 8 8 3284 896; + B 8 8 3304 896; + B 8 8 3324 896; + B 8 8 3344 896; + B 8 8 3364 896; + B 8 8 3384 896; + B 8 8 3404 896; + B 8 8 3424 896; + B 8 8 3444 896; + B 8 8 3464 896; + B 8 8 3484 896; + B 8 8 3504 896; + B 8 8 3524 896; + B 8 8 3544 896; + B 8 8 3564 896; + B 8 8 3584 896; + B 8 8 3604 896; + B 8 8 3624 896; + B 8 8 3644 896; + B 8 8 4084 896; + B 8 8 4104 896; + B 8 8 4124 896; + B 8 8 4144 896; + B 8 8 4164 896; + B 8 8 4184 896; + B 8 8 4204 896; + B 8 8 4224 896; + B 8 8 4244 896; + B 8 8 4264 896; + B 8 8 4284 896; + B 8 8 4304 896; + B 8 8 4324 896; + B 8 8 4344 896; + B 8 8 4364 896; + B 8 8 4384 896; + B 8 8 4404 896; + B 8 8 4424 896; + B 8 8 4444 896; + B 8 8 4884 896; + B 8 8 4904 896; + B 8 8 4924 896; + B 8 8 4944 896; + B 8 8 4964 896; + B 8 8 4984 896; + B 8 8 5004 896; + B 8 8 5024 896; + B 8 8 5044 896; + B 8 8 5064 896; + B 8 8 5084 896; + B 8 8 5104 896; + B 8 8 5124 896; + B 8 8 5144 896; + B 8 8 5164 896; + B 8 8 5184 896; + B 8 8 5204 896; + B 8 8 5224 896; + B 8 8 5244 896; + B 8 8 5684 896; + B 8 8 5704 896; + B 8 8 5724 896; + B 8 8 5744 896; + B 8 8 5764 896; + B 8 8 5784 896; + B 8 8 5804 896; + B 8 8 5824 896; + B 8 8 5844 896; + B 8 8 5864 896; + B 8 8 5884 896; + B 8 8 5904 896; + B 8 8 5924 896; + B 8 8 5944 896; + B 8 8 5964 896; + B 8 8 5984 896; + B 8 8 6004 896; + B 8 8 6024 896; + B 8 8 6044 896; + B 8 8 6484 896; + B 8 8 6504 896; + B 8 8 6524 896; + B 8 8 6544 896; + B 8 8 6564 896; + B 8 8 6584 896; + B 8 8 6604 896; + B 8 8 6624 896; + B 8 8 6644 896; + B 8 8 6664 896; + B 8 8 6684 896; + B 8 8 6704 896; + B 8 8 6724 896; + B 8 8 6744 896; + B 8 8 6764 896; + B 8 8 6784 896; + B 8 8 6804 896; + B 8 8 6824 896; + B 8 8 6844 896; + B 8 8 7284 896; + B 8 8 7304 896; + B 8 8 7324 896; + B 8 8 7344 896; + B 8 8 7364 896; + B 8 8 7384 896; + B 8 8 7404 896; + B 8 8 7424 896; + B 8 8 7444 896; + B 8 8 7464 896; + B 8 8 7484 896; + B 8 8 7504 896; + B 8 8 7524 896; + B 8 8 7544 896; + B 8 8 7564 896; + B 8 8 7584 896; + B 8 8 7604 896; + B 8 8 7624 896; + B 8 8 7644 896; + B 8 8 84 876; + B 8 8 104 876; + B 8 8 124 876; + B 8 8 144 876; + B 8 8 164 876; + B 8 8 184 876; + B 8 8 204 876; + B 8 8 224 876; + B 8 8 244 876; + B 8 8 264 876; + B 8 8 284 876; + B 8 8 304 876; + B 8 8 324 876; + B 8 8 344 876; + B 8 8 364 876; + B 8 8 384 876; + B 8 8 404 876; + B 8 8 424 876; + B 8 8 444 876; + B 8 8 884 876; + B 8 8 904 876; + B 8 8 924 876; + B 8 8 944 876; + B 8 8 964 876; + B 8 8 984 876; + B 8 8 1004 876; + B 8 8 1024 876; + B 8 8 1044 876; + B 8 8 1064 876; + B 8 8 1084 876; + B 8 8 1104 876; + B 8 8 1124 876; + B 8 8 1144 876; + B 8 8 1164 876; + B 8 8 1184 876; + B 8 8 1204 876; + B 8 8 1224 876; + B 8 8 1244 876; + B 8 8 1684 876; + B 8 8 1704 876; + B 8 8 1724 876; + B 8 8 1744 876; + B 8 8 1764 876; + B 8 8 1784 876; + B 8 8 1804 876; + B 8 8 1824 876; + B 8 8 1844 876; + B 8 8 1864 876; + B 8 8 1884 876; + B 8 8 1904 876; + B 8 8 1924 876; + B 8 8 1944 876; + B 8 8 1964 876; + B 8 8 1984 876; + B 8 8 2004 876; + B 8 8 2024 876; + B 8 8 2044 876; + B 8 8 2484 876; + B 8 8 2504 876; + B 8 8 2524 876; + B 8 8 2544 876; + B 8 8 2564 876; + B 8 8 2584 876; + B 8 8 2604 876; + B 8 8 2624 876; + B 8 8 2644 876; + B 8 8 2664 876; + B 8 8 2684 876; + B 8 8 2704 876; + B 8 8 2724 876; + B 8 8 2744 876; + B 8 8 2764 876; + B 8 8 2784 876; + B 8 8 2804 876; + B 8 8 2824 876; + B 8 8 2844 876; + B 8 8 3284 876; + B 8 8 3304 876; + B 8 8 3324 876; + B 8 8 3344 876; + B 8 8 3364 876; + B 8 8 3384 876; + B 8 8 3404 876; + B 8 8 3424 876; + B 8 8 3444 876; + B 8 8 3464 876; + B 8 8 3484 876; + B 8 8 3504 876; + B 8 8 3524 876; + B 8 8 3544 876; + B 8 8 3564 876; + B 8 8 3584 876; + B 8 8 3604 876; + B 8 8 3624 876; + B 8 8 3644 876; + B 8 8 4084 876; + B 8 8 4104 876; + B 8 8 4124 876; + B 8 8 4144 876; + B 8 8 4164 876; + B 8 8 4184 876; + B 8 8 4204 876; + B 8 8 4224 876; + B 8 8 4244 876; + B 8 8 4264 876; + B 8 8 4284 876; + B 8 8 4304 876; + B 8 8 4324 876; + B 8 8 4344 876; + B 8 8 4364 876; + B 8 8 4384 876; + B 8 8 4404 876; + B 8 8 4424 876; + B 8 8 4444 876; + B 8 8 4884 876; + B 8 8 4904 876; + B 8 8 4924 876; + B 8 8 4944 876; + B 8 8 4964 876; + B 8 8 4984 876; + B 8 8 5004 876; + B 8 8 5024 876; + B 8 8 5044 876; + B 8 8 5064 876; + B 8 8 5084 876; + B 8 8 5104 876; + B 8 8 5124 876; + B 8 8 5144 876; + B 8 8 5164 876; + B 8 8 5184 876; + B 8 8 5204 876; + B 8 8 5224 876; + B 8 8 5244 876; + B 8 8 5684 876; + B 8 8 5704 876; + B 8 8 5724 876; + B 8 8 5744 876; + B 8 8 5764 876; + B 8 8 5784 876; + B 8 8 5804 876; + B 8 8 5824 876; + B 8 8 5844 876; + B 8 8 5864 876; + B 8 8 5884 876; + B 8 8 5904 876; + B 8 8 5924 876; + B 8 8 5944 876; + B 8 8 5964 876; + B 8 8 5984 876; + B 8 8 6004 876; + B 8 8 6024 876; + B 8 8 6044 876; + B 8 8 6484 876; + B 8 8 6504 876; + B 8 8 6524 876; + B 8 8 6544 876; + B 8 8 6564 876; + B 8 8 6584 876; + B 8 8 6604 876; + B 8 8 6624 876; + B 8 8 6644 876; + B 8 8 6664 876; + B 8 8 6684 876; + B 8 8 6704 876; + B 8 8 6724 876; + B 8 8 6744 876; + B 8 8 6764 876; + B 8 8 6784 876; + B 8 8 6804 876; + B 8 8 6824 876; + B 8 8 6844 876; + B 8 8 7284 876; + B 8 8 7304 876; + B 8 8 7324 876; + B 8 8 7344 876; + B 8 8 7364 876; + B 8 8 7384 876; + B 8 8 7404 876; + B 8 8 7424 876; + B 8 8 7444 876; + B 8 8 7464 876; + B 8 8 7484 876; + B 8 8 7504 876; + B 8 8 7524 876; + B 8 8 7544 876; + B 8 8 7564 876; + B 8 8 7584 876; + B 8 8 7604 876; + B 8 8 7624 876; + B 8 8 7644 876; + B 8 8 84 436; + B 8 8 104 436; + B 8 8 124 436; + B 8 8 144 436; + B 8 8 164 436; + B 8 8 184 436; + B 8 8 204 436; + B 8 8 224 436; + B 8 8 244 436; + B 8 8 264 436; + B 8 8 284 436; + B 8 8 304 436; + B 8 8 324 436; + B 8 8 344 436; + B 8 8 364 436; + B 8 8 384 436; + B 8 8 404 436; + B 8 8 424 436; + B 8 8 444 436; + B 8 8 884 436; + B 8 8 904 436; + B 8 8 924 436; + B 8 8 944 436; + B 8 8 964 436; + B 8 8 984 436; + B 8 8 1004 436; + B 8 8 1024 436; + B 8 8 1044 436; + B 8 8 1064 436; + B 8 8 1084 436; + B 8 8 1104 436; + B 8 8 1124 436; + B 8 8 1144 436; + B 8 8 1164 436; + B 8 8 1184 436; + B 8 8 1204 436; + B 8 8 1224 436; + B 8 8 1244 436; + B 8 8 1684 436; + B 8 8 1704 436; + B 8 8 1724 436; + B 8 8 1744 436; + B 8 8 1764 436; + B 8 8 1784 436; + B 8 8 1804 436; + B 8 8 1824 436; + B 8 8 1844 436; + B 8 8 1864 436; + B 8 8 1884 436; + B 8 8 1904 436; + B 8 8 1924 436; + B 8 8 1944 436; + B 8 8 1964 436; + B 8 8 1984 436; + B 8 8 2004 436; + B 8 8 2024 436; + B 8 8 2044 436; + B 8 8 2484 436; + B 8 8 2504 436; + B 8 8 2524 436; + B 8 8 2544 436; + B 8 8 2564 436; + B 8 8 2584 436; + B 8 8 2604 436; + B 8 8 2624 436; + B 8 8 2644 436; + B 8 8 2664 436; + B 8 8 2684 436; + B 8 8 2704 436; + B 8 8 2724 436; + B 8 8 2744 436; + B 8 8 2764 436; + B 8 8 2784 436; + B 8 8 2804 436; + B 8 8 2824 436; + B 8 8 2844 436; + B 8 8 3284 436; + B 8 8 3304 436; + B 8 8 3324 436; + B 8 8 3344 436; + B 8 8 3364 436; + B 8 8 3384 436; + B 8 8 3404 436; + B 8 8 3424 436; + B 8 8 3444 436; + B 8 8 3464 436; + B 8 8 3484 436; + B 8 8 3504 436; + B 8 8 3524 436; + B 8 8 3544 436; + B 8 8 3564 436; + B 8 8 3584 436; + B 8 8 3604 436; + B 8 8 3624 436; + B 8 8 3644 436; + B 8 8 4084 436; + B 8 8 4104 436; + B 8 8 4124 436; + B 8 8 4144 436; + B 8 8 4164 436; + B 8 8 4184 436; + B 8 8 4204 436; + B 8 8 4224 436; + B 8 8 4244 436; + B 8 8 4264 436; + B 8 8 4284 436; + B 8 8 4304 436; + B 8 8 4324 436; + B 8 8 4344 436; + B 8 8 4364 436; + B 8 8 4384 436; + B 8 8 4404 436; + B 8 8 4424 436; + B 8 8 4444 436; + B 8 8 4884 436; + B 8 8 4904 436; + B 8 8 4924 436; + B 8 8 4944 436; + B 8 8 4964 436; + B 8 8 4984 436; + B 8 8 5004 436; + B 8 8 5024 436; + B 8 8 5044 436; + B 8 8 5064 436; + B 8 8 5084 436; + B 8 8 5104 436; + B 8 8 5124 436; + B 8 8 5144 436; + B 8 8 5164 436; + B 8 8 5184 436; + B 8 8 5204 436; + B 8 8 5224 436; + B 8 8 5244 436; + B 8 8 5684 436; + B 8 8 5704 436; + B 8 8 5724 436; + B 8 8 5744 436; + B 8 8 5764 436; + B 8 8 5784 436; + B 8 8 5804 436; + B 8 8 5824 436; + B 8 8 5844 436; + B 8 8 5864 436; + B 8 8 5884 436; + B 8 8 5904 436; + B 8 8 5924 436; + B 8 8 5944 436; + B 8 8 5964 436; + B 8 8 5984 436; + B 8 8 6004 436; + B 8 8 6024 436; + B 8 8 6044 436; + B 8 8 6484 436; + B 8 8 6504 436; + B 8 8 6524 436; + B 8 8 6544 436; + B 8 8 6564 436; + B 8 8 6584 436; + B 8 8 6604 436; + B 8 8 6624 436; + B 8 8 6644 436; + B 8 8 6664 436; + B 8 8 6684 436; + B 8 8 6704 436; + B 8 8 6724 436; + B 8 8 6744 436; + B 8 8 6764 436; + B 8 8 6784 436; + B 8 8 6804 436; + B 8 8 6824 436; + B 8 8 6844 436; + B 8 8 7284 436; + B 8 8 7304 436; + B 8 8 7324 436; + B 8 8 7344 436; + B 8 8 7364 436; + B 8 8 7384 436; + B 8 8 7404 436; + B 8 8 7424 436; + B 8 8 7444 436; + B 8 8 7464 436; + B 8 8 7484 436; + B 8 8 7504 436; + B 8 8 7524 436; + B 8 8 7544 436; + B 8 8 7564 436; + B 8 8 7584 436; + B 8 8 7604 436; + B 8 8 7624 436; + B 8 8 7644 436; + B 8 8 84 416; + B 8 8 104 416; + B 8 8 124 416; + B 8 8 144 416; + B 8 8 164 416; + B 8 8 184 416; + B 8 8 204 416; + B 8 8 224 416; + B 8 8 244 416; + B 8 8 264 416; + B 8 8 284 416; + B 8 8 304 416; + B 8 8 324 416; + B 8 8 344 416; + B 8 8 364 416; + B 8 8 384 416; + B 8 8 404 416; + B 8 8 424 416; + B 8 8 444 416; + B 8 8 884 416; + B 8 8 904 416; + B 8 8 924 416; + B 8 8 944 416; + B 8 8 964 416; + B 8 8 984 416; + B 8 8 1004 416; + B 8 8 1024 416; + B 8 8 1044 416; + B 8 8 1064 416; + B 8 8 1084 416; + B 8 8 1104 416; + B 8 8 1124 416; + B 8 8 1144 416; + B 8 8 1164 416; + B 8 8 1184 416; + B 8 8 1204 416; + B 8 8 1224 416; + B 8 8 1244 416; + B 8 8 1684 416; + B 8 8 1704 416; + B 8 8 1724 416; + B 8 8 1744 416; + B 8 8 1764 416; + B 8 8 1784 416; + B 8 8 1804 416; + B 8 8 1824 416; + B 8 8 1844 416; + B 8 8 1864 416; + B 8 8 1884 416; + B 8 8 1904 416; + B 8 8 1924 416; + B 8 8 1944 416; + B 8 8 1964 416; + B 8 8 1984 416; + B 8 8 2004 416; + B 8 8 2024 416; + B 8 8 2044 416; + B 8 8 2484 416; + B 8 8 2504 416; + B 8 8 2524 416; + B 8 8 2544 416; + B 8 8 2564 416; + B 8 8 2584 416; + B 8 8 2604 416; + B 8 8 2624 416; + B 8 8 2644 416; + B 8 8 2664 416; + B 8 8 2684 416; + B 8 8 2704 416; + B 8 8 2724 416; + B 8 8 2744 416; + B 8 8 2764 416; + B 8 8 2784 416; + B 8 8 2804 416; + B 8 8 2824 416; + B 8 8 2844 416; + B 8 8 3284 416; + B 8 8 3304 416; + B 8 8 3324 416; + B 8 8 3344 416; + B 8 8 3364 416; + B 8 8 3384 416; + B 8 8 3404 416; + B 8 8 3424 416; + B 8 8 3444 416; + B 8 8 3464 416; + B 8 8 3484 416; + B 8 8 3504 416; + B 8 8 3524 416; + B 8 8 3544 416; + B 8 8 3564 416; + B 8 8 3584 416; + B 8 8 3604 416; + B 8 8 3624 416; + B 8 8 3644 416; + B 8 8 4084 416; + B 8 8 4104 416; + B 8 8 4124 416; + B 8 8 4144 416; + B 8 8 4164 416; + B 8 8 4184 416; + B 8 8 4204 416; + B 8 8 4224 416; + B 8 8 4244 416; + B 8 8 4264 416; + B 8 8 4284 416; + B 8 8 4304 416; + B 8 8 4324 416; + B 8 8 4344 416; + B 8 8 4364 416; + B 8 8 4384 416; + B 8 8 4404 416; + B 8 8 4424 416; + B 8 8 4444 416; + B 8 8 4884 416; + B 8 8 4904 416; + B 8 8 4924 416; + B 8 8 4944 416; + B 8 8 4964 416; + B 8 8 4984 416; + B 8 8 5004 416; + B 8 8 5024 416; + B 8 8 5044 416; + B 8 8 5064 416; + B 8 8 5084 416; + B 8 8 5104 416; + B 8 8 5124 416; + B 8 8 5144 416; + B 8 8 5164 416; + B 8 8 5184 416; + B 8 8 5204 416; + B 8 8 5224 416; + B 8 8 5244 416; + B 8 8 5684 416; + B 8 8 5704 416; + B 8 8 5724 416; + B 8 8 5744 416; + B 8 8 5764 416; + B 8 8 5784 416; + B 8 8 5804 416; + B 8 8 5824 416; + B 8 8 5844 416; + B 8 8 5864 416; + B 8 8 5884 416; + B 8 8 5904 416; + B 8 8 5924 416; + B 8 8 5944 416; + B 8 8 5964 416; + B 8 8 5984 416; + B 8 8 6004 416; + B 8 8 6024 416; + B 8 8 6044 416; + B 8 8 6484 416; + B 8 8 6504 416; + B 8 8 6524 416; + B 8 8 6544 416; + B 8 8 6564 416; + B 8 8 6584 416; + B 8 8 6604 416; + B 8 8 6624 416; + B 8 8 6644 416; + B 8 8 6664 416; + B 8 8 6684 416; + B 8 8 6704 416; + B 8 8 6724 416; + B 8 8 6744 416; + B 8 8 6764 416; + B 8 8 6784 416; + B 8 8 6804 416; + B 8 8 6824 416; + B 8 8 6844 416; + B 8 8 7284 416; + B 8 8 7304 416; + B 8 8 7324 416; + B 8 8 7344 416; + B 8 8 7364 416; + B 8 8 7384 416; + B 8 8 7404 416; + B 8 8 7424 416; + B 8 8 7444 416; + B 8 8 7464 416; + B 8 8 7484 416; + B 8 8 7504 416; + B 8 8 7524 416; + B 8 8 7544 416; + B 8 8 7564 416; + B 8 8 7584 416; + B 8 8 7604 416; + B 8 8 7624 416; + B 8 8 7644 416; + B 8 8 84 396; + B 8 8 104 396; + B 8 8 124 396; + B 8 8 144 396; + B 8 8 164 396; + B 8 8 184 396; + B 8 8 204 396; + B 8 8 224 396; + B 8 8 244 396; + B 8 8 264 396; + B 8 8 284 396; + B 8 8 304 396; + B 8 8 324 396; + B 8 8 344 396; + B 8 8 364 396; + B 8 8 384 396; + B 8 8 404 396; + B 8 8 424 396; + B 8 8 444 396; + B 8 8 884 396; + B 8 8 904 396; + B 8 8 924 396; + B 8 8 944 396; + B 8 8 964 396; + B 8 8 984 396; + B 8 8 1004 396; + B 8 8 1024 396; + B 8 8 1044 396; + B 8 8 1064 396; + B 8 8 1084 396; + B 8 8 1104 396; + B 8 8 1124 396; + B 8 8 1144 396; + B 8 8 1164 396; + B 8 8 1184 396; + B 8 8 1204 396; + B 8 8 1224 396; + B 8 8 1244 396; + B 8 8 1684 396; + B 8 8 1704 396; + B 8 8 1724 396; + B 8 8 1744 396; + B 8 8 1764 396; + B 8 8 1784 396; + B 8 8 1804 396; + B 8 8 1824 396; + B 8 8 1844 396; + B 8 8 1864 396; + B 8 8 1884 396; + B 8 8 1904 396; + B 8 8 1924 396; + B 8 8 1944 396; + B 8 8 1964 396; + B 8 8 1984 396; + B 8 8 2004 396; + B 8 8 2024 396; + B 8 8 2044 396; + B 8 8 2484 396; + B 8 8 2504 396; + B 8 8 2524 396; + B 8 8 2544 396; + B 8 8 2564 396; + B 8 8 2584 396; + B 8 8 2604 396; + B 8 8 2624 396; + B 8 8 2644 396; + B 8 8 2664 396; + B 8 8 2684 396; + B 8 8 2704 396; + B 8 8 2724 396; + B 8 8 2744 396; + B 8 8 2764 396; + B 8 8 2784 396; + B 8 8 2804 396; + B 8 8 2824 396; + B 8 8 2844 396; + B 8 8 3284 396; + B 8 8 3304 396; + B 8 8 3324 396; + B 8 8 3344 396; + B 8 8 3364 396; + B 8 8 3384 396; + B 8 8 3404 396; + B 8 8 3424 396; + B 8 8 3444 396; + B 8 8 3464 396; + B 8 8 3484 396; + B 8 8 3504 396; + B 8 8 3524 396; + B 8 8 3544 396; + B 8 8 3564 396; + B 8 8 3584 396; + B 8 8 3604 396; + B 8 8 3624 396; + B 8 8 3644 396; + B 8 8 4084 396; + B 8 8 4104 396; + B 8 8 4124 396; + B 8 8 4144 396; + B 8 8 4164 396; + B 8 8 4184 396; + B 8 8 4204 396; + B 8 8 4224 396; + B 8 8 4244 396; + B 8 8 4264 396; + B 8 8 4284 396; + B 8 8 4304 396; + B 8 8 4324 396; + B 8 8 4344 396; + B 8 8 4364 396; + B 8 8 4384 396; + B 8 8 4404 396; + B 8 8 4424 396; + B 8 8 4444 396; + B 8 8 4884 396; + B 8 8 4904 396; + B 8 8 4924 396; + B 8 8 4944 396; + B 8 8 4964 396; + B 8 8 4984 396; + B 8 8 5004 396; + B 8 8 5024 396; + B 8 8 5044 396; + B 8 8 5064 396; + B 8 8 5084 396; + B 8 8 5104 396; + B 8 8 5124 396; + B 8 8 5144 396; + B 8 8 5164 396; + B 8 8 5184 396; + B 8 8 5204 396; + B 8 8 5224 396; + B 8 8 5244 396; + B 8 8 5684 396; + B 8 8 5704 396; + B 8 8 5724 396; + B 8 8 5744 396; + B 8 8 5764 396; + B 8 8 5784 396; + B 8 8 5804 396; + B 8 8 5824 396; + B 8 8 5844 396; + B 8 8 5864 396; + B 8 8 5884 396; + B 8 8 5904 396; + B 8 8 5924 396; + B 8 8 5944 396; + B 8 8 5964 396; + B 8 8 5984 396; + B 8 8 6004 396; + B 8 8 6024 396; + B 8 8 6044 396; + B 8 8 6484 396; + B 8 8 6504 396; + B 8 8 6524 396; + B 8 8 6544 396; + B 8 8 6564 396; + B 8 8 6584 396; + B 8 8 6604 396; + B 8 8 6624 396; + B 8 8 6644 396; + B 8 8 6664 396; + B 8 8 6684 396; + B 8 8 6704 396; + B 8 8 6724 396; + B 8 8 6744 396; + B 8 8 6764 396; + B 8 8 6784 396; + B 8 8 6804 396; + B 8 8 6824 396; + B 8 8 6844 396; + B 8 8 7284 396; + B 8 8 7304 396; + B 8 8 7324 396; + B 8 8 7344 396; + B 8 8 7364 396; + B 8 8 7384 396; + B 8 8 7404 396; + B 8 8 7424 396; + B 8 8 7444 396; + B 8 8 7464 396; + B 8 8 7484 396; + B 8 8 7504 396; + B 8 8 7524 396; + B 8 8 7544 396; + B 8 8 7564 396; + B 8 8 7584 396; + B 8 8 7604 396; + B 8 8 7624 396; + B 8 8 7644 396; + B 8 8 84 376; + B 8 8 104 376; + B 8 8 124 376; + B 8 8 144 376; + B 8 8 164 376; + B 8 8 184 376; + B 8 8 204 376; + B 8 8 224 376; + B 8 8 244 376; + B 8 8 264 376; + B 8 8 284 376; + B 8 8 304 376; + B 8 8 324 376; + B 8 8 344 376; + B 8 8 364 376; + B 8 8 384 376; + B 8 8 404 376; + B 8 8 424 376; + B 8 8 444 376; + B 8 8 884 376; + B 8 8 904 376; + B 8 8 924 376; + B 8 8 944 376; + B 8 8 964 376; + B 8 8 984 376; + B 8 8 1004 376; + B 8 8 1024 376; + B 8 8 1044 376; + B 8 8 1064 376; + B 8 8 1084 376; + B 8 8 1104 376; + B 8 8 1124 376; + B 8 8 1144 376; + B 8 8 1164 376; + B 8 8 1184 376; + B 8 8 1204 376; + B 8 8 1224 376; + B 8 8 1244 376; + B 8 8 1684 376; + B 8 8 1704 376; + B 8 8 1724 376; + B 8 8 1744 376; + B 8 8 1764 376; + B 8 8 1784 376; + B 8 8 1804 376; + B 8 8 1824 376; + B 8 8 1844 376; + B 8 8 1864 376; + B 8 8 1884 376; + B 8 8 1904 376; + B 8 8 1924 376; + B 8 8 1944 376; + B 8 8 1964 376; + B 8 8 1984 376; + B 8 8 2004 376; + B 8 8 2024 376; + B 8 8 2044 376; + B 8 8 2484 376; + B 8 8 2504 376; + B 8 8 2524 376; + B 8 8 2544 376; + B 8 8 2564 376; + B 8 8 2584 376; + B 8 8 2604 376; + B 8 8 2624 376; + B 8 8 2644 376; + B 8 8 2664 376; + B 8 8 2684 376; + B 8 8 2704 376; + B 8 8 2724 376; + B 8 8 2744 376; + B 8 8 2764 376; + B 8 8 2784 376; + B 8 8 2804 376; + B 8 8 2824 376; + B 8 8 2844 376; + B 8 8 3284 376; + B 8 8 3304 376; + B 8 8 3324 376; + B 8 8 3344 376; + B 8 8 3364 376; + B 8 8 3384 376; + B 8 8 3404 376; + B 8 8 3424 376; + B 8 8 3444 376; + B 8 8 3464 376; + B 8 8 3484 376; + B 8 8 3504 376; + B 8 8 3524 376; + B 8 8 3544 376; + B 8 8 3564 376; + B 8 8 3584 376; + B 8 8 3604 376; + B 8 8 3624 376; + B 8 8 3644 376; + B 8 8 4084 376; + B 8 8 4104 376; + B 8 8 4124 376; + B 8 8 4144 376; + B 8 8 4164 376; + B 8 8 4184 376; + B 8 8 4204 376; + B 8 8 4224 376; + B 8 8 4244 376; + B 8 8 4264 376; + B 8 8 4284 376; + B 8 8 4304 376; + B 8 8 4324 376; + B 8 8 4344 376; + B 8 8 4364 376; + B 8 8 4384 376; + B 8 8 4404 376; + B 8 8 4424 376; + B 8 8 4444 376; + B 8 8 4884 376; + B 8 8 4904 376; + B 8 8 4924 376; + B 8 8 4944 376; + B 8 8 4964 376; + B 8 8 4984 376; + B 8 8 5004 376; + B 8 8 5024 376; + B 8 8 5044 376; + B 8 8 5064 376; + B 8 8 5084 376; + B 8 8 5104 376; + B 8 8 5124 376; + B 8 8 5144 376; + B 8 8 5164 376; + B 8 8 5184 376; + B 8 8 5204 376; + B 8 8 5224 376; + B 8 8 5244 376; + B 8 8 5684 376; + B 8 8 5704 376; + B 8 8 5724 376; + B 8 8 5744 376; + B 8 8 5764 376; + B 8 8 5784 376; + B 8 8 5804 376; + B 8 8 5824 376; + B 8 8 5844 376; + B 8 8 5864 376; + B 8 8 5884 376; + B 8 8 5904 376; + B 8 8 5924 376; + B 8 8 5944 376; + B 8 8 5964 376; + B 8 8 5984 376; + B 8 8 6004 376; + B 8 8 6024 376; + B 8 8 6044 376; + B 8 8 6484 376; + B 8 8 6504 376; + B 8 8 6524 376; + B 8 8 6544 376; + B 8 8 6564 376; + B 8 8 6584 376; + B 8 8 6604 376; + B 8 8 6624 376; + B 8 8 6644 376; + B 8 8 6664 376; + B 8 8 6684 376; + B 8 8 6704 376; + B 8 8 6724 376; + B 8 8 6744 376; + B 8 8 6764 376; + B 8 8 6784 376; + B 8 8 6804 376; + B 8 8 6824 376; + B 8 8 6844 376; + B 8 8 7284 376; + B 8 8 7304 376; + B 8 8 7324 376; + B 8 8 7344 376; + B 8 8 7364 376; + B 8 8 7384 376; + B 8 8 7404 376; + B 8 8 7424 376; + B 8 8 7444 376; + B 8 8 7464 376; + B 8 8 7484 376; + B 8 8 7504 376; + B 8 8 7524 376; + B 8 8 7544 376; + B 8 8 7564 376; + B 8 8 7584 376; + B 8 8 7604 376; + B 8 8 7624 376; + B 8 8 7644 376; + B 8 8 84 356; + B 8 8 104 356; + B 8 8 124 356; + B 8 8 144 356; + B 8 8 164 356; + B 8 8 184 356; + B 8 8 204 356; + B 8 8 224 356; + B 8 8 244 356; + B 8 8 264 356; + B 8 8 284 356; + B 8 8 304 356; + B 8 8 324 356; + B 8 8 344 356; + B 8 8 364 356; + B 8 8 384 356; + B 8 8 404 356; + B 8 8 424 356; + B 8 8 444 356; + B 8 8 884 356; + B 8 8 904 356; + B 8 8 924 356; + B 8 8 944 356; + B 8 8 964 356; + B 8 8 984 356; + B 8 8 1004 356; + B 8 8 1024 356; + B 8 8 1044 356; + B 8 8 1064 356; + B 8 8 1084 356; + B 8 8 1104 356; + B 8 8 1124 356; + B 8 8 1144 356; + B 8 8 1164 356; + B 8 8 1184 356; + B 8 8 1204 356; + B 8 8 1224 356; + B 8 8 1244 356; + B 8 8 1684 356; + B 8 8 1704 356; + B 8 8 1724 356; + B 8 8 1744 356; + B 8 8 1764 356; + B 8 8 1784 356; + B 8 8 1804 356; + B 8 8 1824 356; + B 8 8 1844 356; + B 8 8 1864 356; + B 8 8 1884 356; + B 8 8 1904 356; + B 8 8 1924 356; + B 8 8 1944 356; + B 8 8 1964 356; + B 8 8 1984 356; + B 8 8 2004 356; + B 8 8 2024 356; + B 8 8 2044 356; + B 8 8 2484 356; + B 8 8 2504 356; + B 8 8 2524 356; + B 8 8 2544 356; + B 8 8 2564 356; + B 8 8 2584 356; + B 8 8 2604 356; + B 8 8 2624 356; + B 8 8 2644 356; + B 8 8 2664 356; + B 8 8 2684 356; + B 8 8 2704 356; + B 8 8 2724 356; + B 8 8 2744 356; + B 8 8 2764 356; + B 8 8 2784 356; + B 8 8 2804 356; + B 8 8 2824 356; + B 8 8 2844 356; + B 8 8 3284 356; + B 8 8 3304 356; + B 8 8 3324 356; + B 8 8 3344 356; + B 8 8 3364 356; + B 8 8 3384 356; + B 8 8 3404 356; + B 8 8 3424 356; + B 8 8 3444 356; + B 8 8 3464 356; + B 8 8 3484 356; + B 8 8 3504 356; + B 8 8 3524 356; + B 8 8 3544 356; + B 8 8 3564 356; + B 8 8 3584 356; + B 8 8 3604 356; + B 8 8 3624 356; + B 8 8 3644 356; + B 8 8 4084 356; + B 8 8 4104 356; + B 8 8 4124 356; + B 8 8 4144 356; + B 8 8 4164 356; + B 8 8 4184 356; + B 8 8 4204 356; + B 8 8 4224 356; + B 8 8 4244 356; + B 8 8 4264 356; + B 8 8 4284 356; + B 8 8 4304 356; + B 8 8 4324 356; + B 8 8 4344 356; + B 8 8 4364 356; + B 8 8 4384 356; + B 8 8 4404 356; + B 8 8 4424 356; + B 8 8 4444 356; + B 8 8 4884 356; + B 8 8 4904 356; + B 8 8 4924 356; + B 8 8 4944 356; + B 8 8 4964 356; + B 8 8 4984 356; + B 8 8 5004 356; + B 8 8 5024 356; + B 8 8 5044 356; + B 8 8 5064 356; + B 8 8 5084 356; + B 8 8 5104 356; + B 8 8 5124 356; + B 8 8 5144 356; + B 8 8 5164 356; + B 8 8 5184 356; + B 8 8 5204 356; + B 8 8 5224 356; + B 8 8 5244 356; + B 8 8 5684 356; + B 8 8 5704 356; + B 8 8 5724 356; + B 8 8 5744 356; + B 8 8 5764 356; + B 8 8 5784 356; + B 8 8 5804 356; + B 8 8 5824 356; + B 8 8 5844 356; + B 8 8 5864 356; + B 8 8 5884 356; + B 8 8 5904 356; + B 8 8 5924 356; + B 8 8 5944 356; + B 8 8 5964 356; + B 8 8 5984 356; + B 8 8 6004 356; + B 8 8 6024 356; + B 8 8 6044 356; + B 8 8 6484 356; + B 8 8 6504 356; + B 8 8 6524 356; + B 8 8 6544 356; + B 8 8 6564 356; + B 8 8 6584 356; + B 8 8 6604 356; + B 8 8 6624 356; + B 8 8 6644 356; + B 8 8 6664 356; + B 8 8 6684 356; + B 8 8 6704 356; + B 8 8 6724 356; + B 8 8 6744 356; + B 8 8 6764 356; + B 8 8 6784 356; + B 8 8 6804 356; + B 8 8 6824 356; + B 8 8 6844 356; + B 8 8 7284 356; + B 8 8 7304 356; + B 8 8 7324 356; + B 8 8 7344 356; + B 8 8 7364 356; + B 8 8 7384 356; + B 8 8 7404 356; + B 8 8 7424 356; + B 8 8 7444 356; + B 8 8 7464 356; + B 8 8 7484 356; + B 8 8 7504 356; + B 8 8 7524 356; + B 8 8 7544 356; + B 8 8 7564 356; + B 8 8 7584 356; + B 8 8 7604 356; + B 8 8 7624 356; + B 8 8 7644 356; + B 8 8 84 336; + B 8 8 104 336; + B 8 8 124 336; + B 8 8 144 336; + B 8 8 164 336; + B 8 8 184 336; + B 8 8 204 336; + B 8 8 224 336; + B 8 8 244 336; + B 8 8 264 336; + B 8 8 284 336; + B 8 8 304 336; + B 8 8 324 336; + B 8 8 344 336; + B 8 8 364 336; + B 8 8 384 336; + B 8 8 404 336; + B 8 8 424 336; + B 8 8 444 336; + B 8 8 884 336; + B 8 8 904 336; + B 8 8 924 336; + B 8 8 944 336; + B 8 8 964 336; + B 8 8 984 336; + B 8 8 1004 336; + B 8 8 1024 336; + B 8 8 1044 336; + B 8 8 1064 336; + B 8 8 1084 336; + B 8 8 1104 336; + B 8 8 1124 336; + B 8 8 1144 336; + B 8 8 1164 336; + B 8 8 1184 336; + B 8 8 1204 336; + B 8 8 1224 336; + B 8 8 1244 336; + B 8 8 1684 336; + B 8 8 1704 336; + B 8 8 1724 336; + B 8 8 1744 336; + B 8 8 1764 336; + B 8 8 1784 336; + B 8 8 1804 336; + B 8 8 1824 336; + B 8 8 1844 336; + B 8 8 1864 336; + B 8 8 1884 336; + B 8 8 1904 336; + B 8 8 1924 336; + B 8 8 1944 336; + B 8 8 1964 336; + B 8 8 1984 336; + B 8 8 2004 336; + B 8 8 2024 336; + B 8 8 2044 336; + B 8 8 2484 336; + B 8 8 2504 336; + B 8 8 2524 336; + B 8 8 2544 336; + B 8 8 2564 336; + B 8 8 2584 336; + B 8 8 2604 336; + B 8 8 2624 336; + B 8 8 2644 336; + B 8 8 2664 336; + B 8 8 2684 336; + B 8 8 2704 336; + B 8 8 2724 336; + B 8 8 2744 336; + B 8 8 2764 336; + B 8 8 2784 336; + B 8 8 2804 336; + B 8 8 2824 336; + B 8 8 2844 336; + B 8 8 3284 336; + B 8 8 3304 336; + B 8 8 3324 336; + B 8 8 3344 336; + B 8 8 3364 336; + B 8 8 3384 336; + B 8 8 3404 336; + B 8 8 3424 336; + B 8 8 3444 336; + B 8 8 3464 336; + B 8 8 3484 336; + B 8 8 3504 336; + B 8 8 3524 336; + B 8 8 3544 336; + B 8 8 3564 336; + B 8 8 3584 336; + B 8 8 3604 336; + B 8 8 3624 336; + B 8 8 3644 336; + B 8 8 4084 336; + B 8 8 4104 336; + B 8 8 4124 336; + B 8 8 4144 336; + B 8 8 4164 336; + B 8 8 4184 336; + B 8 8 4204 336; + B 8 8 4224 336; + B 8 8 4244 336; + B 8 8 4264 336; + B 8 8 4284 336; + B 8 8 4304 336; + B 8 8 4324 336; + B 8 8 4344 336; + B 8 8 4364 336; + B 8 8 4384 336; + B 8 8 4404 336; + B 8 8 4424 336; + B 8 8 4444 336; + B 8 8 4884 336; + B 8 8 4904 336; + B 8 8 4924 336; + B 8 8 4944 336; + B 8 8 4964 336; + B 8 8 4984 336; + B 8 8 5004 336; + B 8 8 5024 336; + B 8 8 5044 336; + B 8 8 5064 336; + B 8 8 5084 336; + B 8 8 5104 336; + B 8 8 5124 336; + B 8 8 5144 336; + B 8 8 5164 336; + B 8 8 5184 336; + B 8 8 5204 336; + B 8 8 5224 336; + B 8 8 5244 336; + B 8 8 5684 336; + B 8 8 5704 336; + B 8 8 5724 336; + B 8 8 5744 336; + B 8 8 5764 336; + B 8 8 5784 336; + B 8 8 5804 336; + B 8 8 5824 336; + B 8 8 5844 336; + B 8 8 5864 336; + B 8 8 5884 336; + B 8 8 5904 336; + B 8 8 5924 336; + B 8 8 5944 336; + B 8 8 5964 336; + B 8 8 5984 336; + B 8 8 6004 336; + B 8 8 6024 336; + B 8 8 6044 336; + B 8 8 6484 336; + B 8 8 6504 336; + B 8 8 6524 336; + B 8 8 6544 336; + B 8 8 6564 336; + B 8 8 6584 336; + B 8 8 6604 336; + B 8 8 6624 336; + B 8 8 6644 336; + B 8 8 6664 336; + B 8 8 6684 336; + B 8 8 6704 336; + B 8 8 6724 336; + B 8 8 6744 336; + B 8 8 6764 336; + B 8 8 6784 336; + B 8 8 6804 336; + B 8 8 6824 336; + B 8 8 6844 336; + B 8 8 7284 336; + B 8 8 7304 336; + B 8 8 7324 336; + B 8 8 7344 336; + B 8 8 7364 336; + B 8 8 7384 336; + B 8 8 7404 336; + B 8 8 7424 336; + B 8 8 7444 336; + B 8 8 7464 336; + B 8 8 7484 336; + B 8 8 7504 336; + B 8 8 7524 336; + B 8 8 7544 336; + B 8 8 7564 336; + B 8 8 7584 336; + B 8 8 7604 336; + B 8 8 7624 336; + B 8 8 7644 336; + B 8 8 84 316; + B 8 8 104 316; + B 8 8 124 316; + B 8 8 144 316; + B 8 8 164 316; + B 8 8 184 316; + B 8 8 204 316; + B 8 8 224 316; + B 8 8 244 316; + B 8 8 264 316; + B 8 8 284 316; + B 8 8 304 316; + B 8 8 324 316; + B 8 8 344 316; + B 8 8 364 316; + B 8 8 384 316; + B 8 8 404 316; + B 8 8 424 316; + B 8 8 444 316; + B 8 8 884 316; + B 8 8 904 316; + B 8 8 924 316; + B 8 8 944 316; + B 8 8 964 316; + B 8 8 984 316; + B 8 8 1004 316; + B 8 8 1024 316; + B 8 8 1044 316; + B 8 8 1064 316; + B 8 8 1084 316; + B 8 8 1104 316; + B 8 8 1124 316; + B 8 8 1144 316; + B 8 8 1164 316; + B 8 8 1184 316; + B 8 8 1204 316; + B 8 8 1224 316; + B 8 8 1244 316; + B 8 8 1684 316; + B 8 8 1704 316; + B 8 8 1724 316; + B 8 8 1744 316; + B 8 8 1764 316; + B 8 8 1784 316; + B 8 8 1804 316; + B 8 8 1824 316; + B 8 8 1844 316; + B 8 8 1864 316; + B 8 8 1884 316; + B 8 8 1904 316; + B 8 8 1924 316; + B 8 8 1944 316; + B 8 8 1964 316; + B 8 8 1984 316; + B 8 8 2004 316; + B 8 8 2024 316; + B 8 8 2044 316; + B 8 8 2484 316; + B 8 8 2504 316; + B 8 8 2524 316; + B 8 8 2544 316; + B 8 8 2564 316; + B 8 8 2584 316; + B 8 8 2604 316; + B 8 8 2624 316; + B 8 8 2644 316; + B 8 8 2664 316; + B 8 8 2684 316; + B 8 8 2704 316; + B 8 8 2724 316; + B 8 8 2744 316; + B 8 8 2764 316; + B 8 8 2784 316; + B 8 8 2804 316; + B 8 8 2824 316; + B 8 8 2844 316; + B 8 8 3284 316; + B 8 8 3304 316; + B 8 8 3324 316; + B 8 8 3344 316; + B 8 8 3364 316; + B 8 8 3384 316; + B 8 8 3404 316; + B 8 8 3424 316; + B 8 8 3444 316; + B 8 8 3464 316; + B 8 8 3484 316; + B 8 8 3504 316; + B 8 8 3524 316; + B 8 8 3544 316; + B 8 8 3564 316; + B 8 8 3584 316; + B 8 8 3604 316; + B 8 8 3624 316; + B 8 8 3644 316; + B 8 8 4084 316; + B 8 8 4104 316; + B 8 8 4124 316; + B 8 8 4144 316; + B 8 8 4164 316; + B 8 8 4184 316; + B 8 8 4204 316; + B 8 8 4224 316; + B 8 8 4244 316; + B 8 8 4264 316; + B 8 8 4284 316; + B 8 8 4304 316; + B 8 8 4324 316; + B 8 8 4344 316; + B 8 8 4364 316; + B 8 8 4384 316; + B 8 8 4404 316; + B 8 8 4424 316; + B 8 8 4444 316; + B 8 8 4884 316; + B 8 8 4904 316; + B 8 8 4924 316; + B 8 8 4944 316; + B 8 8 4964 316; + B 8 8 4984 316; + B 8 8 5004 316; + B 8 8 5024 316; + B 8 8 5044 316; + B 8 8 5064 316; + B 8 8 5084 316; + B 8 8 5104 316; + B 8 8 5124 316; + B 8 8 5144 316; + B 8 8 5164 316; + B 8 8 5184 316; + B 8 8 5204 316; + B 8 8 5224 316; + B 8 8 5244 316; + B 8 8 5684 316; + B 8 8 5704 316; + B 8 8 5724 316; + B 8 8 5744 316; + B 8 8 5764 316; + B 8 8 5784 316; + B 8 8 5804 316; + B 8 8 5824 316; + B 8 8 5844 316; + B 8 8 5864 316; + B 8 8 5884 316; + B 8 8 5904 316; + B 8 8 5924 316; + B 8 8 5944 316; + B 8 8 5964 316; + B 8 8 5984 316; + B 8 8 6004 316; + B 8 8 6024 316; + B 8 8 6044 316; + B 8 8 6484 316; + B 8 8 6504 316; + B 8 8 6524 316; + B 8 8 6544 316; + B 8 8 6564 316; + B 8 8 6584 316; + B 8 8 6604 316; + B 8 8 6624 316; + B 8 8 6644 316; + B 8 8 6664 316; + B 8 8 6684 316; + B 8 8 6704 316; + B 8 8 6724 316; + B 8 8 6744 316; + B 8 8 6764 316; + B 8 8 6784 316; + B 8 8 6804 316; + B 8 8 6824 316; + B 8 8 6844 316; + B 8 8 7284 316; + B 8 8 7304 316; + B 8 8 7324 316; + B 8 8 7344 316; + B 8 8 7364 316; + B 8 8 7384 316; + B 8 8 7404 316; + B 8 8 7424 316; + B 8 8 7444 316; + B 8 8 7464 316; + B 8 8 7484 316; + B 8 8 7504 316; + B 8 8 7524 316; + B 8 8 7544 316; + B 8 8 7564 316; + B 8 8 7584 316; + B 8 8 7604 316; + B 8 8 7624 316; + B 8 8 7644 316; + B 8 8 84 296; + B 8 8 104 296; + B 8 8 124 296; + B 8 8 144 296; + B 8 8 164 296; + B 8 8 184 296; + B 8 8 204 296; + B 8 8 224 296; + B 8 8 244 296; + B 8 8 264 296; + B 8 8 284 296; + B 8 8 304 296; + B 8 8 324 296; + B 8 8 344 296; + B 8 8 364 296; + B 8 8 384 296; + B 8 8 404 296; + B 8 8 424 296; + B 8 8 444 296; + B 8 8 884 296; + B 8 8 904 296; + B 8 8 924 296; + B 8 8 944 296; + B 8 8 964 296; + B 8 8 984 296; + B 8 8 1004 296; + B 8 8 1024 296; + B 8 8 1044 296; + B 8 8 1064 296; + B 8 8 1084 296; + B 8 8 1104 296; + B 8 8 1124 296; + B 8 8 1144 296; + B 8 8 1164 296; + B 8 8 1184 296; + B 8 8 1204 296; + B 8 8 1224 296; + B 8 8 1244 296; + B 8 8 1684 296; + B 8 8 1704 296; + B 8 8 1724 296; + B 8 8 1744 296; + B 8 8 1764 296; + B 8 8 1784 296; + B 8 8 1804 296; + B 8 8 1824 296; + B 8 8 1844 296; + B 8 8 1864 296; + B 8 8 1884 296; + B 8 8 1904 296; + B 8 8 1924 296; + B 8 8 1944 296; + B 8 8 1964 296; + B 8 8 1984 296; + B 8 8 2004 296; + B 8 8 2024 296; + B 8 8 2044 296; + B 8 8 2484 296; + B 8 8 2504 296; + B 8 8 2524 296; + B 8 8 2544 296; + B 8 8 2564 296; + B 8 8 2584 296; + B 8 8 2604 296; + B 8 8 2624 296; + B 8 8 2644 296; + B 8 8 2664 296; + B 8 8 2684 296; + B 8 8 2704 296; + B 8 8 2724 296; + B 8 8 2744 296; + B 8 8 2764 296; + B 8 8 2784 296; + B 8 8 2804 296; + B 8 8 2824 296; + B 8 8 2844 296; + B 8 8 3284 296; + B 8 8 3304 296; + B 8 8 3324 296; + B 8 8 3344 296; + B 8 8 3364 296; + B 8 8 3384 296; + B 8 8 3404 296; + B 8 8 3424 296; + B 8 8 3444 296; + B 8 8 3464 296; + B 8 8 3484 296; + B 8 8 3504 296; + B 8 8 3524 296; + B 8 8 3544 296; + B 8 8 3564 296; + B 8 8 3584 296; + B 8 8 3604 296; + B 8 8 3624 296; + B 8 8 3644 296; + B 8 8 4084 296; + B 8 8 4104 296; + B 8 8 4124 296; + B 8 8 4144 296; + B 8 8 4164 296; + B 8 8 4184 296; + B 8 8 4204 296; + B 8 8 4224 296; + B 8 8 4244 296; + B 8 8 4264 296; + B 8 8 4284 296; + B 8 8 4304 296; + B 8 8 4324 296; + B 8 8 4344 296; + B 8 8 4364 296; + B 8 8 4384 296; + B 8 8 4404 296; + B 8 8 4424 296; + B 8 8 4444 296; + B 8 8 4884 296; + B 8 8 4904 296; + B 8 8 4924 296; + B 8 8 4944 296; + B 8 8 4964 296; + B 8 8 4984 296; + B 8 8 5004 296; + B 8 8 5024 296; + B 8 8 5044 296; + B 8 8 5064 296; + B 8 8 5084 296; + B 8 8 5104 296; + B 8 8 5124 296; + B 8 8 5144 296; + B 8 8 5164 296; + B 8 8 5184 296; + B 8 8 5204 296; + B 8 8 5224 296; + B 8 8 5244 296; + B 8 8 5684 296; + B 8 8 5704 296; + B 8 8 5724 296; + B 8 8 5744 296; + B 8 8 5764 296; + B 8 8 5784 296; + B 8 8 5804 296; + B 8 8 5824 296; + B 8 8 5844 296; + B 8 8 5864 296; + B 8 8 5884 296; + B 8 8 5904 296; + B 8 8 5924 296; + B 8 8 5944 296; + B 8 8 5964 296; + B 8 8 5984 296; + B 8 8 6004 296; + B 8 8 6024 296; + B 8 8 6044 296; + B 8 8 6484 296; + B 8 8 6504 296; + B 8 8 6524 296; + B 8 8 6544 296; + B 8 8 6564 296; + B 8 8 6584 296; + B 8 8 6604 296; + B 8 8 6624 296; + B 8 8 6644 296; + B 8 8 6664 296; + B 8 8 6684 296; + B 8 8 6704 296; + B 8 8 6724 296; + B 8 8 6744 296; + B 8 8 6764 296; + B 8 8 6784 296; + B 8 8 6804 296; + B 8 8 6824 296; + B 8 8 6844 296; + B 8 8 7284 296; + B 8 8 7304 296; + B 8 8 7324 296; + B 8 8 7344 296; + B 8 8 7364 296; + B 8 8 7384 296; + B 8 8 7404 296; + B 8 8 7424 296; + B 8 8 7444 296; + B 8 8 7464 296; + B 8 8 7484 296; + B 8 8 7504 296; + B 8 8 7524 296; + B 8 8 7544 296; + B 8 8 7564 296; + B 8 8 7584 296; + B 8 8 7604 296; + B 8 8 7624 296; + B 8 8 7644 296; + B 8 8 84 276; + B 8 8 104 276; + B 8 8 124 276; + B 8 8 144 276; + B 8 8 164 276; + B 8 8 184 276; + B 8 8 204 276; + B 8 8 224 276; + B 8 8 244 276; + B 8 8 264 276; + B 8 8 284 276; + B 8 8 304 276; + B 8 8 324 276; + B 8 8 344 276; + B 8 8 364 276; + B 8 8 384 276; + B 8 8 404 276; + B 8 8 424 276; + B 8 8 444 276; + B 8 8 884 276; + B 8 8 904 276; + B 8 8 924 276; + B 8 8 944 276; + B 8 8 964 276; + B 8 8 984 276; + B 8 8 1004 276; + B 8 8 1024 276; + B 8 8 1044 276; + B 8 8 1064 276; + B 8 8 1084 276; + B 8 8 1104 276; + B 8 8 1124 276; + B 8 8 1144 276; + B 8 8 1164 276; + B 8 8 1184 276; + B 8 8 1204 276; + B 8 8 1224 276; + B 8 8 1244 276; + B 8 8 1684 276; + B 8 8 1704 276; + B 8 8 1724 276; + B 8 8 1744 276; + B 8 8 1764 276; + B 8 8 1784 276; + B 8 8 1804 276; + B 8 8 1824 276; + B 8 8 1844 276; + B 8 8 1864 276; + B 8 8 1884 276; + B 8 8 1904 276; + B 8 8 1924 276; + B 8 8 1944 276; + B 8 8 1964 276; + B 8 8 1984 276; + B 8 8 2004 276; + B 8 8 2024 276; + B 8 8 2044 276; + B 8 8 2484 276; + B 8 8 2504 276; + B 8 8 2524 276; + B 8 8 2544 276; + B 8 8 2564 276; + B 8 8 2584 276; + B 8 8 2604 276; + B 8 8 2624 276; + B 8 8 2644 276; + B 8 8 2664 276; + B 8 8 2684 276; + B 8 8 2704 276; + B 8 8 2724 276; + B 8 8 2744 276; + B 8 8 2764 276; + B 8 8 2784 276; + B 8 8 2804 276; + B 8 8 2824 276; + B 8 8 2844 276; + B 8 8 3284 276; + B 8 8 3304 276; + B 8 8 3324 276; + B 8 8 3344 276; + B 8 8 3364 276; + B 8 8 3384 276; + B 8 8 3404 276; + B 8 8 3424 276; + B 8 8 3444 276; + B 8 8 3464 276; + B 8 8 3484 276; + B 8 8 3504 276; + B 8 8 3524 276; + B 8 8 3544 276; + B 8 8 3564 276; + B 8 8 3584 276; + B 8 8 3604 276; + B 8 8 3624 276; + B 8 8 3644 276; + B 8 8 4084 276; + B 8 8 4104 276; + B 8 8 4124 276; + B 8 8 4144 276; + B 8 8 4164 276; + B 8 8 4184 276; + B 8 8 4204 276; + B 8 8 4224 276; + B 8 8 4244 276; + B 8 8 4264 276; + B 8 8 4284 276; + B 8 8 4304 276; + B 8 8 4324 276; + B 8 8 4344 276; + B 8 8 4364 276; + B 8 8 4384 276; + B 8 8 4404 276; + B 8 8 4424 276; + B 8 8 4444 276; + B 8 8 4884 276; + B 8 8 4904 276; + B 8 8 4924 276; + B 8 8 4944 276; + B 8 8 4964 276; + B 8 8 4984 276; + B 8 8 5004 276; + B 8 8 5024 276; + B 8 8 5044 276; + B 8 8 5064 276; + B 8 8 5084 276; + B 8 8 5104 276; + B 8 8 5124 276; + B 8 8 5144 276; + B 8 8 5164 276; + B 8 8 5184 276; + B 8 8 5204 276; + B 8 8 5224 276; + B 8 8 5244 276; + B 8 8 5684 276; + B 8 8 5704 276; + B 8 8 5724 276; + B 8 8 5744 276; + B 8 8 5764 276; + B 8 8 5784 276; + B 8 8 5804 276; + B 8 8 5824 276; + B 8 8 5844 276; + B 8 8 5864 276; + B 8 8 5884 276; + B 8 8 5904 276; + B 8 8 5924 276; + B 8 8 5944 276; + B 8 8 5964 276; + B 8 8 5984 276; + B 8 8 6004 276; + B 8 8 6024 276; + B 8 8 6044 276; + B 8 8 6484 276; + B 8 8 6504 276; + B 8 8 6524 276; + B 8 8 6544 276; + B 8 8 6564 276; + B 8 8 6584 276; + B 8 8 6604 276; + B 8 8 6624 276; + B 8 8 6644 276; + B 8 8 6664 276; + B 8 8 6684 276; + B 8 8 6704 276; + B 8 8 6724 276; + B 8 8 6744 276; + B 8 8 6764 276; + B 8 8 6784 276; + B 8 8 6804 276; + B 8 8 6824 276; + B 8 8 6844 276; + B 8 8 7284 276; + B 8 8 7304 276; + B 8 8 7324 276; + B 8 8 7344 276; + B 8 8 7364 276; + B 8 8 7384 276; + B 8 8 7404 276; + B 8 8 7424 276; + B 8 8 7444 276; + B 8 8 7464 276; + B 8 8 7484 276; + B 8 8 7504 276; + B 8 8 7524 276; + B 8 8 7544 276; + B 8 8 7564 276; + B 8 8 7584 276; + B 8 8 7604 276; + B 8 8 7624 276; + B 8 8 7644 276; + B 8 8 84 256; + B 8 8 104 256; + B 8 8 124 256; + B 8 8 144 256; + B 8 8 164 256; + B 8 8 184 256; + B 8 8 204 256; + B 8 8 224 256; + B 8 8 244 256; + B 8 8 264 256; + B 8 8 284 256; + B 8 8 304 256; + B 8 8 324 256; + B 8 8 344 256; + B 8 8 364 256; + B 8 8 384 256; + B 8 8 404 256; + B 8 8 424 256; + B 8 8 444 256; + B 8 8 884 256; + B 8 8 904 256; + B 8 8 924 256; + B 8 8 944 256; + B 8 8 964 256; + B 8 8 984 256; + B 8 8 1004 256; + B 8 8 1024 256; + B 8 8 1044 256; + B 8 8 1064 256; + B 8 8 1084 256; + B 8 8 1104 256; + B 8 8 1124 256; + B 8 8 1144 256; + B 8 8 1164 256; + B 8 8 1184 256; + B 8 8 1204 256; + B 8 8 1224 256; + B 8 8 1244 256; + B 8 8 1684 256; + B 8 8 1704 256; + B 8 8 1724 256; + B 8 8 1744 256; + B 8 8 1764 256; + B 8 8 1784 256; + B 8 8 1804 256; + B 8 8 1824 256; + B 8 8 1844 256; + B 8 8 1864 256; + B 8 8 1884 256; + B 8 8 1904 256; + B 8 8 1924 256; + B 8 8 1944 256; + B 8 8 1964 256; + B 8 8 1984 256; + B 8 8 2004 256; + B 8 8 2024 256; + B 8 8 2044 256; + B 8 8 2484 256; + B 8 8 2504 256; + B 8 8 2524 256; + B 8 8 2544 256; + B 8 8 2564 256; + B 8 8 2584 256; + B 8 8 2604 256; + B 8 8 2624 256; + B 8 8 2644 256; + B 8 8 2664 256; + B 8 8 2684 256; + B 8 8 2704 256; + B 8 8 2724 256; + B 8 8 2744 256; + B 8 8 2764 256; + B 8 8 2784 256; + B 8 8 2804 256; + B 8 8 2824 256; + B 8 8 2844 256; + B 8 8 3284 256; + B 8 8 3304 256; + B 8 8 3324 256; + B 8 8 3344 256; + B 8 8 3364 256; + B 8 8 3384 256; + B 8 8 3404 256; + B 8 8 3424 256; + B 8 8 3444 256; + B 8 8 3464 256; + B 8 8 3484 256; + B 8 8 3504 256; + B 8 8 3524 256; + B 8 8 3544 256; + B 8 8 3564 256; + B 8 8 3584 256; + B 8 8 3604 256; + B 8 8 3624 256; + B 8 8 3644 256; + B 8 8 4084 256; + B 8 8 4104 256; + B 8 8 4124 256; + B 8 8 4144 256; + B 8 8 4164 256; + B 8 8 4184 256; + B 8 8 4204 256; + B 8 8 4224 256; + B 8 8 4244 256; + B 8 8 4264 256; + B 8 8 4284 256; + B 8 8 4304 256; + B 8 8 4324 256; + B 8 8 4344 256; + B 8 8 4364 256; + B 8 8 4384 256; + B 8 8 4404 256; + B 8 8 4424 256; + B 8 8 4444 256; + B 8 8 4884 256; + B 8 8 4904 256; + B 8 8 4924 256; + B 8 8 4944 256; + B 8 8 4964 256; + B 8 8 4984 256; + B 8 8 5004 256; + B 8 8 5024 256; + B 8 8 5044 256; + B 8 8 5064 256; + B 8 8 5084 256; + B 8 8 5104 256; + B 8 8 5124 256; + B 8 8 5144 256; + B 8 8 5164 256; + B 8 8 5184 256; + B 8 8 5204 256; + B 8 8 5224 256; + B 8 8 5244 256; + B 8 8 5684 256; + B 8 8 5704 256; + B 8 8 5724 256; + B 8 8 5744 256; + B 8 8 5764 256; + B 8 8 5784 256; + B 8 8 5804 256; + B 8 8 5824 256; + B 8 8 5844 256; + B 8 8 5864 256; + B 8 8 5884 256; + B 8 8 5904 256; + B 8 8 5924 256; + B 8 8 5944 256; + B 8 8 5964 256; + B 8 8 5984 256; + B 8 8 6004 256; + B 8 8 6024 256; + B 8 8 6044 256; + B 8 8 6484 256; + B 8 8 6504 256; + B 8 8 6524 256; + B 8 8 6544 256; + B 8 8 6564 256; + B 8 8 6584 256; + B 8 8 6604 256; + B 8 8 6624 256; + B 8 8 6644 256; + B 8 8 6664 256; + B 8 8 6684 256; + B 8 8 6704 256; + B 8 8 6724 256; + B 8 8 6744 256; + B 8 8 6764 256; + B 8 8 6784 256; + B 8 8 6804 256; + B 8 8 6824 256; + B 8 8 6844 256; + B 8 8 7284 256; + B 8 8 7304 256; + B 8 8 7324 256; + B 8 8 7344 256; + B 8 8 7364 256; + B 8 8 7384 256; + B 8 8 7404 256; + B 8 8 7424 256; + B 8 8 7444 256; + B 8 8 7464 256; + B 8 8 7484 256; + B 8 8 7504 256; + B 8 8 7524 256; + B 8 8 7544 256; + B 8 8 7564 256; + B 8 8 7584 256; + B 8 8 7604 256; + B 8 8 7624 256; + B 8 8 7644 256; + B 8 8 84 236; + B 8 8 104 236; + B 8 8 124 236; + B 8 8 144 236; + B 8 8 164 236; + B 8 8 184 236; + B 8 8 204 236; + B 8 8 224 236; + B 8 8 244 236; + B 8 8 264 236; + B 8 8 284 236; + B 8 8 304 236; + B 8 8 324 236; + B 8 8 344 236; + B 8 8 364 236; + B 8 8 384 236; + B 8 8 404 236; + B 8 8 424 236; + B 8 8 444 236; + B 8 8 884 236; + B 8 8 904 236; + B 8 8 924 236; + B 8 8 944 236; + B 8 8 964 236; + B 8 8 984 236; + B 8 8 1004 236; + B 8 8 1024 236; + B 8 8 1044 236; + B 8 8 1064 236; + B 8 8 1084 236; + B 8 8 1104 236; + B 8 8 1124 236; + B 8 8 1144 236; + B 8 8 1164 236; + B 8 8 1184 236; + B 8 8 1204 236; + B 8 8 1224 236; + B 8 8 1244 236; + B 8 8 1684 236; + B 8 8 1704 236; + B 8 8 1724 236; + B 8 8 1744 236; + B 8 8 1764 236; + B 8 8 1784 236; + B 8 8 1804 236; + B 8 8 1824 236; + B 8 8 1844 236; + B 8 8 1864 236; + B 8 8 1884 236; + B 8 8 1904 236; + B 8 8 1924 236; + B 8 8 1944 236; + B 8 8 1964 236; + B 8 8 1984 236; + B 8 8 2004 236; + B 8 8 2024 236; + B 8 8 2044 236; + B 8 8 2484 236; + B 8 8 2504 236; + B 8 8 2524 236; + B 8 8 2544 236; + B 8 8 2564 236; + B 8 8 2584 236; + B 8 8 2604 236; + B 8 8 2624 236; + B 8 8 2644 236; + B 8 8 2664 236; + B 8 8 2684 236; + B 8 8 2704 236; + B 8 8 2724 236; + B 8 8 2744 236; + B 8 8 2764 236; + B 8 8 2784 236; + B 8 8 2804 236; + B 8 8 2824 236; + B 8 8 2844 236; + B 8 8 3284 236; + B 8 8 3304 236; + B 8 8 3324 236; + B 8 8 3344 236; + B 8 8 3364 236; + B 8 8 3384 236; + B 8 8 3404 236; + B 8 8 3424 236; + B 8 8 3444 236; + B 8 8 3464 236; + B 8 8 3484 236; + B 8 8 3504 236; + B 8 8 3524 236; + B 8 8 3544 236; + B 8 8 3564 236; + B 8 8 3584 236; + B 8 8 3604 236; + B 8 8 3624 236; + B 8 8 3644 236; + B 8 8 4084 236; + B 8 8 4104 236; + B 8 8 4124 236; + B 8 8 4144 236; + B 8 8 4164 236; + B 8 8 4184 236; + B 8 8 4204 236; + B 8 8 4224 236; + B 8 8 4244 236; + B 8 8 4264 236; + B 8 8 4284 236; + B 8 8 4304 236; + B 8 8 4324 236; + B 8 8 4344 236; + B 8 8 4364 236; + B 8 8 4384 236; + B 8 8 4404 236; + B 8 8 4424 236; + B 8 8 4444 236; + B 8 8 4884 236; + B 8 8 4904 236; + B 8 8 4924 236; + B 8 8 4944 236; + B 8 8 4964 236; + B 8 8 4984 236; + B 8 8 5004 236; + B 8 8 5024 236; + B 8 8 5044 236; + B 8 8 5064 236; + B 8 8 5084 236; + B 8 8 5104 236; + B 8 8 5124 236; + B 8 8 5144 236; + B 8 8 5164 236; + B 8 8 5184 236; + B 8 8 5204 236; + B 8 8 5224 236; + B 8 8 5244 236; + B 8 8 5684 236; + B 8 8 5704 236; + B 8 8 5724 236; + B 8 8 5744 236; + B 8 8 5764 236; + B 8 8 5784 236; + B 8 8 5804 236; + B 8 8 5824 236; + B 8 8 5844 236; + B 8 8 5864 236; + B 8 8 5884 236; + B 8 8 5904 236; + B 8 8 5924 236; + B 8 8 5944 236; + B 8 8 5964 236; + B 8 8 5984 236; + B 8 8 6004 236; + B 8 8 6024 236; + B 8 8 6044 236; + B 8 8 6484 236; + B 8 8 6504 236; + B 8 8 6524 236; + B 8 8 6544 236; + B 8 8 6564 236; + B 8 8 6584 236; + B 8 8 6604 236; + B 8 8 6624 236; + B 8 8 6644 236; + B 8 8 6664 236; + B 8 8 6684 236; + B 8 8 6704 236; + B 8 8 6724 236; + B 8 8 6744 236; + B 8 8 6764 236; + B 8 8 6784 236; + B 8 8 6804 236; + B 8 8 6824 236; + B 8 8 6844 236; + B 8 8 7284 236; + B 8 8 7304 236; + B 8 8 7324 236; + B 8 8 7344 236; + B 8 8 7364 236; + B 8 8 7384 236; + B 8 8 7404 236; + B 8 8 7424 236; + B 8 8 7444 236; + B 8 8 7464 236; + B 8 8 7484 236; + B 8 8 7504 236; + B 8 8 7524 236; + B 8 8 7544 236; + B 8 8 7564 236; + B 8 8 7584 236; + B 8 8 7604 236; + B 8 8 7624 236; + B 8 8 7644 236; + B 8 8 84 216; + B 8 8 104 216; + B 8 8 124 216; + B 8 8 144 216; + B 8 8 164 216; + B 8 8 184 216; + B 8 8 204 216; + B 8 8 224 216; + B 8 8 244 216; + B 8 8 264 216; + B 8 8 284 216; + B 8 8 304 216; + B 8 8 324 216; + B 8 8 344 216; + B 8 8 364 216; + B 8 8 384 216; + B 8 8 404 216; + B 8 8 424 216; + B 8 8 444 216; + B 8 8 884 216; + B 8 8 904 216; + B 8 8 924 216; + B 8 8 944 216; + B 8 8 964 216; + B 8 8 984 216; + B 8 8 1004 216; + B 8 8 1024 216; + B 8 8 1044 216; + B 8 8 1064 216; + B 8 8 1084 216; + B 8 8 1104 216; + B 8 8 1124 216; + B 8 8 1144 216; + B 8 8 1164 216; + B 8 8 1184 216; + B 8 8 1204 216; + B 8 8 1224 216; + B 8 8 1244 216; + B 8 8 1684 216; + B 8 8 1704 216; + B 8 8 1724 216; + B 8 8 1744 216; + B 8 8 1764 216; + B 8 8 1784 216; + B 8 8 1804 216; + B 8 8 1824 216; + B 8 8 1844 216; + B 8 8 1864 216; + B 8 8 1884 216; + B 8 8 1904 216; + B 8 8 1924 216; + B 8 8 1944 216; + B 8 8 1964 216; + B 8 8 1984 216; + B 8 8 2004 216; + B 8 8 2024 216; + B 8 8 2044 216; + B 8 8 2484 216; + B 8 8 2504 216; + B 8 8 2524 216; + B 8 8 2544 216; + B 8 8 2564 216; + B 8 8 2584 216; + B 8 8 2604 216; + B 8 8 2624 216; + B 8 8 2644 216; + B 8 8 2664 216; + B 8 8 2684 216; + B 8 8 2704 216; + B 8 8 2724 216; + B 8 8 2744 216; + B 8 8 2764 216; + B 8 8 2784 216; + B 8 8 2804 216; + B 8 8 2824 216; + B 8 8 2844 216; + B 8 8 3284 216; + B 8 8 3304 216; + B 8 8 3324 216; + B 8 8 3344 216; + B 8 8 3364 216; + B 8 8 3384 216; + B 8 8 3404 216; + B 8 8 3424 216; + B 8 8 3444 216; + B 8 8 3464 216; + B 8 8 3484 216; + B 8 8 3504 216; + B 8 8 3524 216; + B 8 8 3544 216; + B 8 8 3564 216; + B 8 8 3584 216; + B 8 8 3604 216; + B 8 8 3624 216; + B 8 8 3644 216; + B 8 8 4084 216; + B 8 8 4104 216; + B 8 8 4124 216; + B 8 8 4144 216; + B 8 8 4164 216; + B 8 8 4184 216; + B 8 8 4204 216; + B 8 8 4224 216; + B 8 8 4244 216; + B 8 8 4264 216; + B 8 8 4284 216; + B 8 8 4304 216; + B 8 8 4324 216; + B 8 8 4344 216; + B 8 8 4364 216; + B 8 8 4384 216; + B 8 8 4404 216; + B 8 8 4424 216; + B 8 8 4444 216; + B 8 8 4884 216; + B 8 8 4904 216; + B 8 8 4924 216; + B 8 8 4944 216; + B 8 8 4964 216; + B 8 8 4984 216; + B 8 8 5004 216; + B 8 8 5024 216; + B 8 8 5044 216; + B 8 8 5064 216; + B 8 8 5084 216; + B 8 8 5104 216; + B 8 8 5124 216; + B 8 8 5144 216; + B 8 8 5164 216; + B 8 8 5184 216; + B 8 8 5204 216; + B 8 8 5224 216; + B 8 8 5244 216; + B 8 8 5684 216; + B 8 8 5704 216; + B 8 8 5724 216; + B 8 8 5744 216; + B 8 8 5764 216; + B 8 8 5784 216; + B 8 8 5804 216; + B 8 8 5824 216; + B 8 8 5844 216; + B 8 8 5864 216; + B 8 8 5884 216; + B 8 8 5904 216; + B 8 8 5924 216; + B 8 8 5944 216; + B 8 8 5964 216; + B 8 8 5984 216; + B 8 8 6004 216; + B 8 8 6024 216; + B 8 8 6044 216; + B 8 8 6484 216; + B 8 8 6504 216; + B 8 8 6524 216; + B 8 8 6544 216; + B 8 8 6564 216; + B 8 8 6584 216; + B 8 8 6604 216; + B 8 8 6624 216; + B 8 8 6644 216; + B 8 8 6664 216; + B 8 8 6684 216; + B 8 8 6704 216; + B 8 8 6724 216; + B 8 8 6744 216; + B 8 8 6764 216; + B 8 8 6784 216; + B 8 8 6804 216; + B 8 8 6824 216; + B 8 8 6844 216; + B 8 8 7284 216; + B 8 8 7304 216; + B 8 8 7324 216; + B 8 8 7344 216; + B 8 8 7364 216; + B 8 8 7384 216; + B 8 8 7404 216; + B 8 8 7424 216; + B 8 8 7444 216; + B 8 8 7464 216; + B 8 8 7484 216; + B 8 8 7504 216; + B 8 8 7524 216; + B 8 8 7544 216; + B 8 8 7564 216; + B 8 8 7584 216; + B 8 8 7604 216; + B 8 8 7624 216; + B 8 8 7644 216; + B 8 8 84 196; + B 8 8 104 196; + B 8 8 124 196; + B 8 8 144 196; + B 8 8 164 196; + B 8 8 184 196; + B 8 8 204 196; + B 8 8 224 196; + B 8 8 244 196; + B 8 8 264 196; + B 8 8 284 196; + B 8 8 304 196; + B 8 8 324 196; + B 8 8 344 196; + B 8 8 364 196; + B 8 8 384 196; + B 8 8 404 196; + B 8 8 424 196; + B 8 8 444 196; + B 8 8 884 196; + B 8 8 904 196; + B 8 8 924 196; + B 8 8 944 196; + B 8 8 964 196; + B 8 8 984 196; + B 8 8 1004 196; + B 8 8 1024 196; + B 8 8 1044 196; + B 8 8 1064 196; + B 8 8 1084 196; + B 8 8 1104 196; + B 8 8 1124 196; + B 8 8 1144 196; + B 8 8 1164 196; + B 8 8 1184 196; + B 8 8 1204 196; + B 8 8 1224 196; + B 8 8 1244 196; + B 8 8 1684 196; + B 8 8 1704 196; + B 8 8 1724 196; + B 8 8 1744 196; + B 8 8 1764 196; + B 8 8 1784 196; + B 8 8 1804 196; + B 8 8 1824 196; + B 8 8 1844 196; + B 8 8 1864 196; + B 8 8 1884 196; + B 8 8 1904 196; + B 8 8 1924 196; + B 8 8 1944 196; + B 8 8 1964 196; + B 8 8 1984 196; + B 8 8 2004 196; + B 8 8 2024 196; + B 8 8 2044 196; + B 8 8 2484 196; + B 8 8 2504 196; + B 8 8 2524 196; + B 8 8 2544 196; + B 8 8 2564 196; + B 8 8 2584 196; + B 8 8 2604 196; + B 8 8 2624 196; + B 8 8 2644 196; + B 8 8 2664 196; + B 8 8 2684 196; + B 8 8 2704 196; + B 8 8 2724 196; + B 8 8 2744 196; + B 8 8 2764 196; + B 8 8 2784 196; + B 8 8 2804 196; + B 8 8 2824 196; + B 8 8 2844 196; + B 8 8 3284 196; + B 8 8 3304 196; + B 8 8 3324 196; + B 8 8 3344 196; + B 8 8 3364 196; + B 8 8 3384 196; + B 8 8 3404 196; + B 8 8 3424 196; + B 8 8 3444 196; + B 8 8 3464 196; + B 8 8 3484 196; + B 8 8 3504 196; + B 8 8 3524 196; + B 8 8 3544 196; + B 8 8 3564 196; + B 8 8 3584 196; + B 8 8 3604 196; + B 8 8 3624 196; + B 8 8 3644 196; + B 8 8 4084 196; + B 8 8 4104 196; + B 8 8 4124 196; + B 8 8 4144 196; + B 8 8 4164 196; + B 8 8 4184 196; + B 8 8 4204 196; + B 8 8 4224 196; + B 8 8 4244 196; + B 8 8 4264 196; + B 8 8 4284 196; + B 8 8 4304 196; + B 8 8 4324 196; + B 8 8 4344 196; + B 8 8 4364 196; + B 8 8 4384 196; + B 8 8 4404 196; + B 8 8 4424 196; + B 8 8 4444 196; + B 8 8 4884 196; + B 8 8 4904 196; + B 8 8 4924 196; + B 8 8 4944 196; + B 8 8 4964 196; + B 8 8 4984 196; + B 8 8 5004 196; + B 8 8 5024 196; + B 8 8 5044 196; + B 8 8 5064 196; + B 8 8 5084 196; + B 8 8 5104 196; + B 8 8 5124 196; + B 8 8 5144 196; + B 8 8 5164 196; + B 8 8 5184 196; + B 8 8 5204 196; + B 8 8 5224 196; + B 8 8 5244 196; + B 8 8 5684 196; + B 8 8 5704 196; + B 8 8 5724 196; + B 8 8 5744 196; + B 8 8 5764 196; + B 8 8 5784 196; + B 8 8 5804 196; + B 8 8 5824 196; + B 8 8 5844 196; + B 8 8 5864 196; + B 8 8 5884 196; + B 8 8 5904 196; + B 8 8 5924 196; + B 8 8 5944 196; + B 8 8 5964 196; + B 8 8 5984 196; + B 8 8 6004 196; + B 8 8 6024 196; + B 8 8 6044 196; + B 8 8 6484 196; + B 8 8 6504 196; + B 8 8 6524 196; + B 8 8 6544 196; + B 8 8 6564 196; + B 8 8 6584 196; + B 8 8 6604 196; + B 8 8 6624 196; + B 8 8 6644 196; + B 8 8 6664 196; + B 8 8 6684 196; + B 8 8 6704 196; + B 8 8 6724 196; + B 8 8 6744 196; + B 8 8 6764 196; + B 8 8 6784 196; + B 8 8 6804 196; + B 8 8 6824 196; + B 8 8 6844 196; + B 8 8 7284 196; + B 8 8 7304 196; + B 8 8 7324 196; + B 8 8 7344 196; + B 8 8 7364 196; + B 8 8 7384 196; + B 8 8 7404 196; + B 8 8 7424 196; + B 8 8 7444 196; + B 8 8 7464 196; + B 8 8 7484 196; + B 8 8 7504 196; + B 8 8 7524 196; + B 8 8 7544 196; + B 8 8 7564 196; + B 8 8 7584 196; + B 8 8 7604 196; + B 8 8 7624 196; + B 8 8 7644 196; + B 8 8 84 176; + B 8 8 104 176; + B 8 8 124 176; + B 8 8 144 176; + B 8 8 164 176; + B 8 8 184 176; + B 8 8 204 176; + B 8 8 224 176; + B 8 8 244 176; + B 8 8 264 176; + B 8 8 284 176; + B 8 8 304 176; + B 8 8 324 176; + B 8 8 344 176; + B 8 8 364 176; + B 8 8 384 176; + B 8 8 404 176; + B 8 8 424 176; + B 8 8 444 176; + B 8 8 884 176; + B 8 8 904 176; + B 8 8 924 176; + B 8 8 944 176; + B 8 8 964 176; + B 8 8 984 176; + B 8 8 1004 176; + B 8 8 1024 176; + B 8 8 1044 176; + B 8 8 1064 176; + B 8 8 1084 176; + B 8 8 1104 176; + B 8 8 1124 176; + B 8 8 1144 176; + B 8 8 1164 176; + B 8 8 1184 176; + B 8 8 1204 176; + B 8 8 1224 176; + B 8 8 1244 176; + B 8 8 1684 176; + B 8 8 1704 176; + B 8 8 1724 176; + B 8 8 1744 176; + B 8 8 1764 176; + B 8 8 1784 176; + B 8 8 1804 176; + B 8 8 1824 176; + B 8 8 1844 176; + B 8 8 1864 176; + B 8 8 1884 176; + B 8 8 1904 176; + B 8 8 1924 176; + B 8 8 1944 176; + B 8 8 1964 176; + B 8 8 1984 176; + B 8 8 2004 176; + B 8 8 2024 176; + B 8 8 2044 176; + B 8 8 2484 176; + B 8 8 2504 176; + B 8 8 2524 176; + B 8 8 2544 176; + B 8 8 2564 176; + B 8 8 2584 176; + B 8 8 2604 176; + B 8 8 2624 176; + B 8 8 2644 176; + B 8 8 2664 176; + B 8 8 2684 176; + B 8 8 2704 176; + B 8 8 2724 176; + B 8 8 2744 176; + B 8 8 2764 176; + B 8 8 2784 176; + B 8 8 2804 176; + B 8 8 2824 176; + B 8 8 2844 176; + B 8 8 3284 176; + B 8 8 3304 176; + B 8 8 3324 176; + B 8 8 3344 176; + B 8 8 3364 176; + B 8 8 3384 176; + B 8 8 3404 176; + B 8 8 3424 176; + B 8 8 3444 176; + B 8 8 3464 176; + B 8 8 3484 176; + B 8 8 3504 176; + B 8 8 3524 176; + B 8 8 3544 176; + B 8 8 3564 176; + B 8 8 3584 176; + B 8 8 3604 176; + B 8 8 3624 176; + B 8 8 3644 176; + B 8 8 4084 176; + B 8 8 4104 176; + B 8 8 4124 176; + B 8 8 4144 176; + B 8 8 4164 176; + B 8 8 4184 176; + B 8 8 4204 176; + B 8 8 4224 176; + B 8 8 4244 176; + B 8 8 4264 176; + B 8 8 4284 176; + B 8 8 4304 176; + B 8 8 4324 176; + B 8 8 4344 176; + B 8 8 4364 176; + B 8 8 4384 176; + B 8 8 4404 176; + B 8 8 4424 176; + B 8 8 4444 176; + B 8 8 4884 176; + B 8 8 4904 176; + B 8 8 4924 176; + B 8 8 4944 176; + B 8 8 4964 176; + B 8 8 4984 176; + B 8 8 5004 176; + B 8 8 5024 176; + B 8 8 5044 176; + B 8 8 5064 176; + B 8 8 5084 176; + B 8 8 5104 176; + B 8 8 5124 176; + B 8 8 5144 176; + B 8 8 5164 176; + B 8 8 5184 176; + B 8 8 5204 176; + B 8 8 5224 176; + B 8 8 5244 176; + B 8 8 5684 176; + B 8 8 5704 176; + B 8 8 5724 176; + B 8 8 5744 176; + B 8 8 5764 176; + B 8 8 5784 176; + B 8 8 5804 176; + B 8 8 5824 176; + B 8 8 5844 176; + B 8 8 5864 176; + B 8 8 5884 176; + B 8 8 5904 176; + B 8 8 5924 176; + B 8 8 5944 176; + B 8 8 5964 176; + B 8 8 5984 176; + B 8 8 6004 176; + B 8 8 6024 176; + B 8 8 6044 176; + B 8 8 6484 176; + B 8 8 6504 176; + B 8 8 6524 176; + B 8 8 6544 176; + B 8 8 6564 176; + B 8 8 6584 176; + B 8 8 6604 176; + B 8 8 6624 176; + B 8 8 6644 176; + B 8 8 6664 176; + B 8 8 6684 176; + B 8 8 6704 176; + B 8 8 6724 176; + B 8 8 6744 176; + B 8 8 6764 176; + B 8 8 6784 176; + B 8 8 6804 176; + B 8 8 6824 176; + B 8 8 6844 176; + B 8 8 7284 176; + B 8 8 7304 176; + B 8 8 7324 176; + B 8 8 7344 176; + B 8 8 7364 176; + B 8 8 7384 176; + B 8 8 7404 176; + B 8 8 7424 176; + B 8 8 7444 176; + B 8 8 7464 176; + B 8 8 7484 176; + B 8 8 7504 176; + B 8 8 7524 176; + B 8 8 7544 176; + B 8 8 7564 176; + B 8 8 7584 176; + B 8 8 7604 176; + B 8 8 7624 176; + B 8 8 7644 176; + B 8 8 84 156; + B 8 8 104 156; + B 8 8 124 156; + B 8 8 144 156; + B 8 8 164 156; + B 8 8 184 156; + B 8 8 204 156; + B 8 8 224 156; + B 8 8 244 156; + B 8 8 264 156; + B 8 8 284 156; + B 8 8 304 156; + B 8 8 324 156; + B 8 8 344 156; + B 8 8 364 156; + B 8 8 384 156; + B 8 8 404 156; + B 8 8 424 156; + B 8 8 444 156; + B 8 8 884 156; + B 8 8 904 156; + B 8 8 924 156; + B 8 8 944 156; + B 8 8 964 156; + B 8 8 984 156; + B 8 8 1004 156; + B 8 8 1024 156; + B 8 8 1044 156; + B 8 8 1064 156; + B 8 8 1084 156; + B 8 8 1104 156; + B 8 8 1124 156; + B 8 8 1144 156; + B 8 8 1164 156; + B 8 8 1184 156; + B 8 8 1204 156; + B 8 8 1224 156; + B 8 8 1244 156; + B 8 8 1684 156; + B 8 8 1704 156; + B 8 8 1724 156; + B 8 8 1744 156; + B 8 8 1764 156; + B 8 8 1784 156; + B 8 8 1804 156; + B 8 8 1824 156; + B 8 8 1844 156; + B 8 8 1864 156; + B 8 8 1884 156; + B 8 8 1904 156; + B 8 8 1924 156; + B 8 8 1944 156; + B 8 8 1964 156; + B 8 8 1984 156; + B 8 8 2004 156; + B 8 8 2024 156; + B 8 8 2044 156; + B 8 8 2484 156; + B 8 8 2504 156; + B 8 8 2524 156; + B 8 8 2544 156; + B 8 8 2564 156; + B 8 8 2584 156; + B 8 8 2604 156; + B 8 8 2624 156; + B 8 8 2644 156; + B 8 8 2664 156; + B 8 8 2684 156; + B 8 8 2704 156; + B 8 8 2724 156; + B 8 8 2744 156; + B 8 8 2764 156; + B 8 8 2784 156; + B 8 8 2804 156; + B 8 8 2824 156; + B 8 8 2844 156; + B 8 8 3284 156; + B 8 8 3304 156; + B 8 8 3324 156; + B 8 8 3344 156; + B 8 8 3364 156; + B 8 8 3384 156; + B 8 8 3404 156; + B 8 8 3424 156; + B 8 8 3444 156; + B 8 8 3464 156; + B 8 8 3484 156; + B 8 8 3504 156; + B 8 8 3524 156; + B 8 8 3544 156; + B 8 8 3564 156; + B 8 8 3584 156; + B 8 8 3604 156; + B 8 8 3624 156; + B 8 8 3644 156; + B 8 8 4084 156; + B 8 8 4104 156; + B 8 8 4124 156; + B 8 8 4144 156; + B 8 8 4164 156; + B 8 8 4184 156; + B 8 8 4204 156; + B 8 8 4224 156; + B 8 8 4244 156; + B 8 8 4264 156; + B 8 8 4284 156; + B 8 8 4304 156; + B 8 8 4324 156; + B 8 8 4344 156; + B 8 8 4364 156; + B 8 8 4384 156; + B 8 8 4404 156; + B 8 8 4424 156; + B 8 8 4444 156; + B 8 8 4884 156; + B 8 8 4904 156; + B 8 8 4924 156; + B 8 8 4944 156; + B 8 8 4964 156; + B 8 8 4984 156; + B 8 8 5004 156; + B 8 8 5024 156; + B 8 8 5044 156; + B 8 8 5064 156; + B 8 8 5084 156; + B 8 8 5104 156; + B 8 8 5124 156; + B 8 8 5144 156; + B 8 8 5164 156; + B 8 8 5184 156; + B 8 8 5204 156; + B 8 8 5224 156; + B 8 8 5244 156; + B 8 8 5684 156; + B 8 8 5704 156; + B 8 8 5724 156; + B 8 8 5744 156; + B 8 8 5764 156; + B 8 8 5784 156; + B 8 8 5804 156; + B 8 8 5824 156; + B 8 8 5844 156; + B 8 8 5864 156; + B 8 8 5884 156; + B 8 8 5904 156; + B 8 8 5924 156; + B 8 8 5944 156; + B 8 8 5964 156; + B 8 8 5984 156; + B 8 8 6004 156; + B 8 8 6024 156; + B 8 8 6044 156; + B 8 8 6484 156; + B 8 8 6504 156; + B 8 8 6524 156; + B 8 8 6544 156; + B 8 8 6564 156; + B 8 8 6584 156; + B 8 8 6604 156; + B 8 8 6624 156; + B 8 8 6644 156; + B 8 8 6664 156; + B 8 8 6684 156; + B 8 8 6704 156; + B 8 8 6724 156; + B 8 8 6744 156; + B 8 8 6764 156; + B 8 8 6784 156; + B 8 8 6804 156; + B 8 8 6824 156; + B 8 8 6844 156; + B 8 8 7284 156; + B 8 8 7304 156; + B 8 8 7324 156; + B 8 8 7344 156; + B 8 8 7364 156; + B 8 8 7384 156; + B 8 8 7404 156; + B 8 8 7424 156; + B 8 8 7444 156; + B 8 8 7464 156; + B 8 8 7484 156; + B 8 8 7504 156; + B 8 8 7524 156; + B 8 8 7544 156; + B 8 8 7564 156; + B 8 8 7584 156; + B 8 8 7604 156; + B 8 8 7624 156; + B 8 8 7644 156; + B 8 8 84 136; + B 8 8 104 136; + B 8 8 124 136; + B 8 8 144 136; + B 8 8 164 136; + B 8 8 184 136; + B 8 8 204 136; + B 8 8 224 136; + B 8 8 244 136; + B 8 8 264 136; + B 8 8 284 136; + B 8 8 304 136; + B 8 8 324 136; + B 8 8 344 136; + B 8 8 364 136; + B 8 8 384 136; + B 8 8 404 136; + B 8 8 424 136; + B 8 8 444 136; + B 8 8 884 136; + B 8 8 904 136; + B 8 8 924 136; + B 8 8 944 136; + B 8 8 964 136; + B 8 8 984 136; + B 8 8 1004 136; + B 8 8 1024 136; + B 8 8 1044 136; + B 8 8 1064 136; + B 8 8 1084 136; + B 8 8 1104 136; + B 8 8 1124 136; + B 8 8 1144 136; + B 8 8 1164 136; + B 8 8 1184 136; + B 8 8 1204 136; + B 8 8 1224 136; + B 8 8 1244 136; + B 8 8 1684 136; + B 8 8 1704 136; + B 8 8 1724 136; + B 8 8 1744 136; + B 8 8 1764 136; + B 8 8 1784 136; + B 8 8 1804 136; + B 8 8 1824 136; + B 8 8 1844 136; + B 8 8 1864 136; + B 8 8 1884 136; + B 8 8 1904 136; + B 8 8 1924 136; + B 8 8 1944 136; + B 8 8 1964 136; + B 8 8 1984 136; + B 8 8 2004 136; + B 8 8 2024 136; + B 8 8 2044 136; + B 8 8 2484 136; + B 8 8 2504 136; + B 8 8 2524 136; + B 8 8 2544 136; + B 8 8 2564 136; + B 8 8 2584 136; + B 8 8 2604 136; + B 8 8 2624 136; + B 8 8 2644 136; + B 8 8 2664 136; + B 8 8 2684 136; + B 8 8 2704 136; + B 8 8 2724 136; + B 8 8 2744 136; + B 8 8 2764 136; + B 8 8 2784 136; + B 8 8 2804 136; + B 8 8 2824 136; + B 8 8 2844 136; + B 8 8 3284 136; + B 8 8 3304 136; + B 8 8 3324 136; + B 8 8 3344 136; + B 8 8 3364 136; + B 8 8 3384 136; + B 8 8 3404 136; + B 8 8 3424 136; + B 8 8 3444 136; + B 8 8 3464 136; + B 8 8 3484 136; + B 8 8 3504 136; + B 8 8 3524 136; + B 8 8 3544 136; + B 8 8 3564 136; + B 8 8 3584 136; + B 8 8 3604 136; + B 8 8 3624 136; + B 8 8 3644 136; + B 8 8 4084 136; + B 8 8 4104 136; + B 8 8 4124 136; + B 8 8 4144 136; + B 8 8 4164 136; + B 8 8 4184 136; + B 8 8 4204 136; + B 8 8 4224 136; + B 8 8 4244 136; + B 8 8 4264 136; + B 8 8 4284 136; + B 8 8 4304 136; + B 8 8 4324 136; + B 8 8 4344 136; + B 8 8 4364 136; + B 8 8 4384 136; + B 8 8 4404 136; + B 8 8 4424 136; + B 8 8 4444 136; + B 8 8 4884 136; + B 8 8 4904 136; + B 8 8 4924 136; + B 8 8 4944 136; + B 8 8 4964 136; + B 8 8 4984 136; + B 8 8 5004 136; + B 8 8 5024 136; + B 8 8 5044 136; + B 8 8 5064 136; + B 8 8 5084 136; + B 8 8 5104 136; + B 8 8 5124 136; + B 8 8 5144 136; + B 8 8 5164 136; + B 8 8 5184 136; + B 8 8 5204 136; + B 8 8 5224 136; + B 8 8 5244 136; + B 8 8 5684 136; + B 8 8 5704 136; + B 8 8 5724 136; + B 8 8 5744 136; + B 8 8 5764 136; + B 8 8 5784 136; + B 8 8 5804 136; + B 8 8 5824 136; + B 8 8 5844 136; + B 8 8 5864 136; + B 8 8 5884 136; + B 8 8 5904 136; + B 8 8 5924 136; + B 8 8 5944 136; + B 8 8 5964 136; + B 8 8 5984 136; + B 8 8 6004 136; + B 8 8 6024 136; + B 8 8 6044 136; + B 8 8 6484 136; + B 8 8 6504 136; + B 8 8 6524 136; + B 8 8 6544 136; + B 8 8 6564 136; + B 8 8 6584 136; + B 8 8 6604 136; + B 8 8 6624 136; + B 8 8 6644 136; + B 8 8 6664 136; + B 8 8 6684 136; + B 8 8 6704 136; + B 8 8 6724 136; + B 8 8 6744 136; + B 8 8 6764 136; + B 8 8 6784 136; + B 8 8 6804 136; + B 8 8 6824 136; + B 8 8 6844 136; + B 8 8 7284 136; + B 8 8 7304 136; + B 8 8 7324 136; + B 8 8 7344 136; + B 8 8 7364 136; + B 8 8 7384 136; + B 8 8 7404 136; + B 8 8 7424 136; + B 8 8 7444 136; + B 8 8 7464 136; + B 8 8 7484 136; + B 8 8 7504 136; + B 8 8 7524 136; + B 8 8 7544 136; + B 8 8 7564 136; + B 8 8 7584 136; + B 8 8 7604 136; + B 8 8 7624 136; + B 8 8 7644 136; + B 8 8 84 116; + B 8 8 104 116; + B 8 8 124 116; + B 8 8 144 116; + B 8 8 164 116; + B 8 8 184 116; + B 8 8 204 116; + B 8 8 224 116; + B 8 8 244 116; + B 8 8 264 116; + B 8 8 284 116; + B 8 8 304 116; + B 8 8 324 116; + B 8 8 344 116; + B 8 8 364 116; + B 8 8 384 116; + B 8 8 404 116; + B 8 8 424 116; + B 8 8 444 116; + B 8 8 884 116; + B 8 8 904 116; + B 8 8 924 116; + B 8 8 944 116; + B 8 8 964 116; + B 8 8 984 116; + B 8 8 1004 116; + B 8 8 1024 116; + B 8 8 1044 116; + B 8 8 1064 116; + B 8 8 1084 116; + B 8 8 1104 116; + B 8 8 1124 116; + B 8 8 1144 116; + B 8 8 1164 116; + B 8 8 1184 116; + B 8 8 1204 116; + B 8 8 1224 116; + B 8 8 1244 116; + B 8 8 1684 116; + B 8 8 1704 116; + B 8 8 1724 116; + B 8 8 1744 116; + B 8 8 1764 116; + B 8 8 1784 116; + B 8 8 1804 116; + B 8 8 1824 116; + B 8 8 1844 116; + B 8 8 1864 116; + B 8 8 1884 116; + B 8 8 1904 116; + B 8 8 1924 116; + B 8 8 1944 116; + B 8 8 1964 116; + B 8 8 1984 116; + B 8 8 2004 116; + B 8 8 2024 116; + B 8 8 2044 116; + B 8 8 2484 116; + B 8 8 2504 116; + B 8 8 2524 116; + B 8 8 2544 116; + B 8 8 2564 116; + B 8 8 2584 116; + B 8 8 2604 116; + B 8 8 2624 116; + B 8 8 2644 116; + B 8 8 2664 116; + B 8 8 2684 116; + B 8 8 2704 116; + B 8 8 2724 116; + B 8 8 2744 116; + B 8 8 2764 116; + B 8 8 2784 116; + B 8 8 2804 116; + B 8 8 2824 116; + B 8 8 2844 116; + B 8 8 3284 116; + B 8 8 3304 116; + B 8 8 3324 116; + B 8 8 3344 116; + B 8 8 3364 116; + B 8 8 3384 116; + B 8 8 3404 116; + B 8 8 3424 116; + B 8 8 3444 116; + B 8 8 3464 116; + B 8 8 3484 116; + B 8 8 3504 116; + B 8 8 3524 116; + B 8 8 3544 116; + B 8 8 3564 116; + B 8 8 3584 116; + B 8 8 3604 116; + B 8 8 3624 116; + B 8 8 3644 116; + B 8 8 4084 116; + B 8 8 4104 116; + B 8 8 4124 116; + B 8 8 4144 116; + B 8 8 4164 116; + B 8 8 4184 116; + B 8 8 4204 116; + B 8 8 4224 116; + B 8 8 4244 116; + B 8 8 4264 116; + B 8 8 4284 116; + B 8 8 4304 116; + B 8 8 4324 116; + B 8 8 4344 116; + B 8 8 4364 116; + B 8 8 4384 116; + B 8 8 4404 116; + B 8 8 4424 116; + B 8 8 4444 116; + B 8 8 4884 116; + B 8 8 4904 116; + B 8 8 4924 116; + B 8 8 4944 116; + B 8 8 4964 116; + B 8 8 4984 116; + B 8 8 5004 116; + B 8 8 5024 116; + B 8 8 5044 116; + B 8 8 5064 116; + B 8 8 5084 116; + B 8 8 5104 116; + B 8 8 5124 116; + B 8 8 5144 116; + B 8 8 5164 116; + B 8 8 5184 116; + B 8 8 5204 116; + B 8 8 5224 116; + B 8 8 5244 116; + B 8 8 5684 116; + B 8 8 5704 116; + B 8 8 5724 116; + B 8 8 5744 116; + B 8 8 5764 116; + B 8 8 5784 116; + B 8 8 5804 116; + B 8 8 5824 116; + B 8 8 5844 116; + B 8 8 5864 116; + B 8 8 5884 116; + B 8 8 5904 116; + B 8 8 5924 116; + B 8 8 5944 116; + B 8 8 5964 116; + B 8 8 5984 116; + B 8 8 6004 116; + B 8 8 6024 116; + B 8 8 6044 116; + B 8 8 6484 116; + B 8 8 6504 116; + B 8 8 6524 116; + B 8 8 6544 116; + B 8 8 6564 116; + B 8 8 6584 116; + B 8 8 6604 116; + B 8 8 6624 116; + B 8 8 6644 116; + B 8 8 6664 116; + B 8 8 6684 116; + B 8 8 6704 116; + B 8 8 6724 116; + B 8 8 6744 116; + B 8 8 6764 116; + B 8 8 6784 116; + B 8 8 6804 116; + B 8 8 6824 116; + B 8 8 6844 116; + B 8 8 7284 116; + B 8 8 7304 116; + B 8 8 7324 116; + B 8 8 7344 116; + B 8 8 7364 116; + B 8 8 7384 116; + B 8 8 7404 116; + B 8 8 7424 116; + B 8 8 7444 116; + B 8 8 7464 116; + B 8 8 7484 116; + B 8 8 7504 116; + B 8 8 7524 116; + B 8 8 7544 116; + B 8 8 7564 116; + B 8 8 7584 116; + B 8 8 7604 116; + B 8 8 7624 116; + B 8 8 7644 116; + B 8 8 84 96; + B 8 8 104 96; + B 8 8 124 96; + B 8 8 144 96; + B 8 8 164 96; + B 8 8 184 96; + B 8 8 204 96; + B 8 8 224 96; + B 8 8 244 96; + B 8 8 264 96; + B 8 8 284 96; + B 8 8 304 96; + B 8 8 324 96; + B 8 8 344 96; + B 8 8 364 96; + B 8 8 384 96; + B 8 8 404 96; + B 8 8 424 96; + B 8 8 444 96; + B 8 8 884 96; + B 8 8 904 96; + B 8 8 924 96; + B 8 8 944 96; + B 8 8 964 96; + B 8 8 984 96; + B 8 8 1004 96; + B 8 8 1024 96; + B 8 8 1044 96; + B 8 8 1064 96; + B 8 8 1084 96; + B 8 8 1104 96; + B 8 8 1124 96; + B 8 8 1144 96; + B 8 8 1164 96; + B 8 8 1184 96; + B 8 8 1204 96; + B 8 8 1224 96; + B 8 8 1244 96; + B 8 8 1684 96; + B 8 8 1704 96; + B 8 8 1724 96; + B 8 8 1744 96; + B 8 8 1764 96; + B 8 8 1784 96; + B 8 8 1804 96; + B 8 8 1824 96; + B 8 8 1844 96; + B 8 8 1864 96; + B 8 8 1884 96; + B 8 8 1904 96; + B 8 8 1924 96; + B 8 8 1944 96; + B 8 8 1964 96; + B 8 8 1984 96; + B 8 8 2004 96; + B 8 8 2024 96; + B 8 8 2044 96; + B 8 8 2484 96; + B 8 8 2504 96; + B 8 8 2524 96; + B 8 8 2544 96; + B 8 8 2564 96; + B 8 8 2584 96; + B 8 8 2604 96; + B 8 8 2624 96; + B 8 8 2644 96; + B 8 8 2664 96; + B 8 8 2684 96; + B 8 8 2704 96; + B 8 8 2724 96; + B 8 8 2744 96; + B 8 8 2764 96; + B 8 8 2784 96; + B 8 8 2804 96; + B 8 8 2824 96; + B 8 8 2844 96; + B 8 8 3284 96; + B 8 8 3304 96; + B 8 8 3324 96; + B 8 8 3344 96; + B 8 8 3364 96; + B 8 8 3384 96; + B 8 8 3404 96; + B 8 8 3424 96; + B 8 8 3444 96; + B 8 8 3464 96; + B 8 8 3484 96; + B 8 8 3504 96; + B 8 8 3524 96; + B 8 8 3544 96; + B 8 8 3564 96; + B 8 8 3584 96; + B 8 8 3604 96; + B 8 8 3624 96; + B 8 8 3644 96; + B 8 8 4084 96; + B 8 8 4104 96; + B 8 8 4124 96; + B 8 8 4144 96; + B 8 8 4164 96; + B 8 8 4184 96; + B 8 8 4204 96; + B 8 8 4224 96; + B 8 8 4244 96; + B 8 8 4264 96; + B 8 8 4284 96; + B 8 8 4304 96; + B 8 8 4324 96; + B 8 8 4344 96; + B 8 8 4364 96; + B 8 8 4384 96; + B 8 8 4404 96; + B 8 8 4424 96; + B 8 8 4444 96; + B 8 8 4884 96; + B 8 8 4904 96; + B 8 8 4924 96; + B 8 8 4944 96; + B 8 8 4964 96; + B 8 8 4984 96; + B 8 8 5004 96; + B 8 8 5024 96; + B 8 8 5044 96; + B 8 8 5064 96; + B 8 8 5084 96; + B 8 8 5104 96; + B 8 8 5124 96; + B 8 8 5144 96; + B 8 8 5164 96; + B 8 8 5184 96; + B 8 8 5204 96; + B 8 8 5224 96; + B 8 8 5244 96; + B 8 8 5684 96; + B 8 8 5704 96; + B 8 8 5724 96; + B 8 8 5744 96; + B 8 8 5764 96; + B 8 8 5784 96; + B 8 8 5804 96; + B 8 8 5824 96; + B 8 8 5844 96; + B 8 8 5864 96; + B 8 8 5884 96; + B 8 8 5904 96; + B 8 8 5924 96; + B 8 8 5944 96; + B 8 8 5964 96; + B 8 8 5984 96; + B 8 8 6004 96; + B 8 8 6024 96; + B 8 8 6044 96; + B 8 8 6484 96; + B 8 8 6504 96; + B 8 8 6524 96; + B 8 8 6544 96; + B 8 8 6564 96; + B 8 8 6584 96; + B 8 8 6604 96; + B 8 8 6624 96; + B 8 8 6644 96; + B 8 8 6664 96; + B 8 8 6684 96; + B 8 8 6704 96; + B 8 8 6724 96; + B 8 8 6744 96; + B 8 8 6764 96; + B 8 8 6784 96; + B 8 8 6804 96; + B 8 8 6824 96; + B 8 8 6844 96; + B 8 8 7284 96; + B 8 8 7304 96; + B 8 8 7324 96; + B 8 8 7344 96; + B 8 8 7364 96; + B 8 8 7384 96; + B 8 8 7404 96; + B 8 8 7424 96; + B 8 8 7444 96; + B 8 8 7464 96; + B 8 8 7484 96; + B 8 8 7504 96; + B 8 8 7524 96; + B 8 8 7544 96; + B 8 8 7564 96; + B 8 8 7584 96; + B 8 8 7604 96; + B 8 8 7624 96; + B 8 8 7644 96; + B 8 8 84 76; + B 8 8 104 76; + B 8 8 124 76; + B 8 8 144 76; + B 8 8 164 76; + B 8 8 184 76; + B 8 8 204 76; + B 8 8 224 76; + B 8 8 244 76; + B 8 8 264 76; + B 8 8 284 76; + B 8 8 304 76; + B 8 8 324 76; + B 8 8 344 76; + B 8 8 364 76; + B 8 8 384 76; + B 8 8 404 76; + B 8 8 424 76; + B 8 8 444 76; + B 8 8 884 76; + B 8 8 904 76; + B 8 8 924 76; + B 8 8 944 76; + B 8 8 964 76; + B 8 8 984 76; + B 8 8 1004 76; + B 8 8 1024 76; + B 8 8 1044 76; + B 8 8 1064 76; + B 8 8 1084 76; + B 8 8 1104 76; + B 8 8 1124 76; + B 8 8 1144 76; + B 8 8 1164 76; + B 8 8 1184 76; + B 8 8 1204 76; + B 8 8 1224 76; + B 8 8 1244 76; + B 8 8 1684 76; + B 8 8 1704 76; + B 8 8 1724 76; + B 8 8 1744 76; + B 8 8 1764 76; + B 8 8 1784 76; + B 8 8 1804 76; + B 8 8 1824 76; + B 8 8 1844 76; + B 8 8 1864 76; + B 8 8 1884 76; + B 8 8 1904 76; + B 8 8 1924 76; + B 8 8 1944 76; + B 8 8 1964 76; + B 8 8 1984 76; + B 8 8 2004 76; + B 8 8 2024 76; + B 8 8 2044 76; + B 8 8 2484 76; + B 8 8 2504 76; + B 8 8 2524 76; + B 8 8 2544 76; + B 8 8 2564 76; + B 8 8 2584 76; + B 8 8 2604 76; + B 8 8 2624 76; + B 8 8 2644 76; + B 8 8 2664 76; + B 8 8 2684 76; + B 8 8 2704 76; + B 8 8 2724 76; + B 8 8 2744 76; + B 8 8 2764 76; + B 8 8 2784 76; + B 8 8 2804 76; + B 8 8 2824 76; + B 8 8 2844 76; + B 8 8 3284 76; + B 8 8 3304 76; + B 8 8 3324 76; + B 8 8 3344 76; + B 8 8 3364 76; + B 8 8 3384 76; + B 8 8 3404 76; + B 8 8 3424 76; + B 8 8 3444 76; + B 8 8 3464 76; + B 8 8 3484 76; + B 8 8 3504 76; + B 8 8 3524 76; + B 8 8 3544 76; + B 8 8 3564 76; + B 8 8 3584 76; + B 8 8 3604 76; + B 8 8 3624 76; + B 8 8 3644 76; + B 8 8 4084 76; + B 8 8 4104 76; + B 8 8 4124 76; + B 8 8 4144 76; + B 8 8 4164 76; + B 8 8 4184 76; + B 8 8 4204 76; + B 8 8 4224 76; + B 8 8 4244 76; + B 8 8 4264 76; + B 8 8 4284 76; + B 8 8 4304 76; + B 8 8 4324 76; + B 8 8 4344 76; + B 8 8 4364 76; + B 8 8 4384 76; + B 8 8 4404 76; + B 8 8 4424 76; + B 8 8 4444 76; + B 8 8 4884 76; + B 8 8 4904 76; + B 8 8 4924 76; + B 8 8 4944 76; + B 8 8 4964 76; + B 8 8 4984 76; + B 8 8 5004 76; + B 8 8 5024 76; + B 8 8 5044 76; + B 8 8 5064 76; + B 8 8 5084 76; + B 8 8 5104 76; + B 8 8 5124 76; + B 8 8 5144 76; + B 8 8 5164 76; + B 8 8 5184 76; + B 8 8 5204 76; + B 8 8 5224 76; + B 8 8 5244 76; + B 8 8 5684 76; + B 8 8 5704 76; + B 8 8 5724 76; + B 8 8 5744 76; + B 8 8 5764 76; + B 8 8 5784 76; + B 8 8 5804 76; + B 8 8 5824 76; + B 8 8 5844 76; + B 8 8 5864 76; + B 8 8 5884 76; + B 8 8 5904 76; + B 8 8 5924 76; + B 8 8 5944 76; + B 8 8 5964 76; + B 8 8 5984 76; + B 8 8 6004 76; + B 8 8 6024 76; + B 8 8 6044 76; + B 8 8 6484 76; + B 8 8 6504 76; + B 8 8 6524 76; + B 8 8 6544 76; + B 8 8 6564 76; + B 8 8 6584 76; + B 8 8 6604 76; + B 8 8 6624 76; + B 8 8 6644 76; + B 8 8 6664 76; + B 8 8 6684 76; + B 8 8 6704 76; + B 8 8 6724 76; + B 8 8 6744 76; + B 8 8 6764 76; + B 8 8 6784 76; + B 8 8 6804 76; + B 8 8 6824 76; + B 8 8 6844 76; + B 8 8 7284 76; + B 8 8 7304 76; + B 8 8 7324 76; + B 8 8 7344 76; + B 8 8 7364 76; + B 8 8 7384 76; + B 8 8 7404 76; + B 8 8 7424 76; + B 8 8 7444 76; + B 8 8 7464 76; + B 8 8 7484 76; + B 8 8 7504 76; + B 8 8 7524 76; + B 8 8 7544 76; + B 8 8 7564 76; + B 8 8 7584 76; + B 8 8 7604 76; + B 8 8 7624 76; + B 8 8 7644 76; +L CCA; + B 8 8 1924 728; + B 8 8 1948 732; + B 8 8 1964 732; + B 8 8 1980 732; + B 8 8 1996 732; + B 8 8 2084 732; + B 8 8 2472 728; + B 8 8 2496 732; + B 8 8 2512 732; + B 8 8 2528 732; + B 8 8 2544 732; + B 8 8 2560 732; + B 8 8 2576 732; + B 8 8 2592 732; + B 8 8 2608 732; + B 8 8 2624 732; + B 8 8 2640 732; + B 8 8 2656 732; + B 8 8 2672 732; + B 8 8 2688 732; + B 8 8 2704 732; + B 8 8 2720 732; + B 8 8 2736 732; + B 8 8 2752 732; + B 8 8 2768 732; + B 8 8 2784 732; + B 8 8 2800 732; + B 8 8 2816 732; + B 8 8 2832 732; + B 8 8 2848 732; + B 8 8 2864 732; + B 8 8 2880 732; + B 8 8 2896 732; + B 8 8 2912 732; + B 8 8 2928 732; + B 8 8 2944 732; + B 8 8 2960 732; + B 8 8 2976 732; + B 8 8 2992 732; + B 8 8 3008 732; + B 8 8 3024 732; + B 8 8 3040 732; + B 8 8 3056 732; + B 8 8 3072 732; + B 8 8 3088 732; + B 8 8 3104 732; + B 8 8 3120 732; + B 8 8 3136 732; + B 8 8 3152 732; + B 8 8 3168 732; + B 8 8 3184 732; + B 8 8 3200 732; + B 8 8 3216 732; + B 8 8 3232 732; + B 8 8 3256 732; + B 8 8 3640 728; + B 8 8 3660 732; + B 8 8 3676 732; + B 8 8 3692 732; + B 8 8 3708 732; + B 8 8 3724 732; + B 8 8 3740 732; + B 8 8 3756 732; + B 8 8 3772 732; + B 8 8 3788 732; + B 8 8 3804 732; + B 8 8 3820 732; + B 8 8 3836 732; + B 8 8 3852 732; + B 8 8 3868 732; + B 8 8 3884 732; + B 8 8 3900 732; + B 8 8 3916 732; + B 8 8 3932 732; + B 8 8 3948 732; + B 8 8 3964 732; + B 8 8 3980 732; + B 8 8 3996 732; + B 8 8 4012 732; + B 8 8 4028 732; + B 8 8 4044 732; + B 8 8 4060 732; + B 8 8 4076 732; + B 8 8 4092 732; + B 8 8 4108 732; + B 8 8 4124 732; + B 8 8 4140 732; + B 8 8 4156 732; + B 8 8 4172 732; + B 8 8 4188 732; + B 8 8 4204 732; + B 8 8 4220 732; + B 8 8 4236 732; + B 8 8 4252 732; + B 8 8 4268 732; + B 8 8 4284 732; + B 8 8 4300 732; + B 8 8 4316 732; + B 8 8 4332 732; + B 8 8 4348 732; + B 8 8 4364 732; + B 8 8 4380 732; + B 8 8 4396 732; + B 8 8 4412 732; + B 8 8 4428 732; + B 8 8 4444 732; + B 8 8 4460 732; + B 8 8 4476 732; + B 8 8 4492 732; + B 8 8 4508 732; + B 8 8 4524 732; + B 8 8 4540 732; + B 8 8 4556 732; + B 8 8 4572 732; + B 8 8 4588 732; + B 8 8 4604 732; + B 8 8 4620 732; + B 8 8 4636 732; + B 8 8 4652 732; + B 8 8 4668 732; + B 8 8 4684 732; + B 8 8 4700 732; + B 8 8 4716 732; + B 8 8 4732 732; + B 8 8 4748 732; + B 8 8 4764 732; + B 8 8 4780 732; + B 8 8 4796 732; + B 8 8 4812 732; + B 8 8 4828 732; + B 8 8 4844 732; + B 8 8 4860 732; + B 8 8 4876 732; + B 8 8 4892 732; + B 8 8 4908 732; + B 8 8 4924 732; + B 8 8 4940 732; + B 8 8 4956 732; + B 8 8 4972 732; + B 8 8 4988 732; + B 8 8 5004 732; + B 8 8 5020 732; + B 8 8 5036 732; + B 8 8 5128 732; + B 8 8 5532 732; + B 8 8 5556 732; + B 8 8 5572 732; + B 8 8 5588 732; + B 8 8 5604 732; + B 8 8 5620 732; + B 8 8 5636 732; + B 8 8 5652 732; + B 8 8 5668 732; + B 8 8 5684 732; + B 8 8 5700 732; + B 8 8 5716 732; + B 8 8 5732 732; + B 8 8 5748 732; + B 8 8 5764 732; + B 8 8 5780 732; + B 8 8 5796 732; + B 8 8 5812 732; + B 8 8 5828 732; + B 8 8 5844 732; + B 8 8 5860 732; + B 8 8 5876 732; + B 8 8 5892 732; + B 8 8 5908 732; + B 8 8 5924 732; + B 8 8 5940 732; + B 8 8 5956 732; + B 8 8 6324 728; + B 8 8 6348 732; + B 8 8 6364 732; + B 8 8 6380 732; + B 8 8 6396 732; + B 8 8 6412 732; + B 8 8 6428 732; + B 8 8 6444 732; + B 8 8 6460 732; + B 8 8 6476 732; + B 8 8 6492 732; + B 8 8 6508 732; + B 8 8 6524 732; + B 8 8 6540 732; + B 8 8 6556 732; + B 8 8 6580 732; + B 8 8 1924 712; + B 8 8 2472 712; + B 8 8 3256 716; + B 8 8 3640 712; + B 8 8 5132 712; + B 8 8 5532 716; + B 8 8 6324 712; + B 8 8 6580 716; + B 8 8 2092 704; + B 8 8 1924 696; + B 8 8 2472 696; + B 8 8 3256 700; + B 8 8 3640 696; + B 8 8 5132 696; + B 8 8 5532 700; + B 8 8 5964 704; + B 8 8 6324 696; + B 8 8 6580 700; + B 8 8 1212 680; + B 8 8 1232 684; + B 8 8 1248 684; + B 8 8 1264 684; + B 8 8 1280 684; + B 8 8 1372 684; + B 8 8 2092 688; + B 8 8 1924 680; + B 8 8 2008 680; + B 8 8 2472 680; + B 8 8 2556 680; + B 8 8 2644 680; + B 8 8 2732 680; + B 8 8 2820 680; + B 8 8 2908 680; + B 8 8 2996 680; + B 8 8 3084 680; + B 8 8 3172 680; + B 8 8 3256 684; + B 8 8 3640 680; + B 8 8 3724 680; + B 8 8 3812 680; + B 8 8 3900 680; + B 8 8 3988 680; + B 8 8 4076 680; + B 8 8 4164 680; + B 8 8 4252 680; + B 8 8 4340 680; + B 8 8 4428 680; + B 8 8 4516 680; + B 8 8 4604 680; + B 8 8 4692 680; + B 8 8 4784 680; + B 8 8 4872 680; + B 8 8 4960 680; + B 8 8 5048 680; + B 8 8 5132 680; + B 8 8 5532 684; + B 8 8 5964 688; + B 8 8 5616 680; + B 8 8 5704 680; + B 8 8 5792 680; + B 8 8 5880 680; + B 8 8 6324 680; + B 8 8 6408 680; + B 8 8 6496 680; + B 8 8 6580 684; + B 8 8 1964 672; + B 8 8 2052 672; + B 8 8 2092 672; + B 8 8 2512 672; + B 8 8 2600 672; + B 8 8 2688 672; + B 8 8 2776 672; + B 8 8 2864 672; + B 8 8 2952 672; + B 8 8 3040 672; + B 8 8 3128 672; + B 8 8 3216 672; + B 8 8 1212 664; + B 8 8 1924 664; + B 8 8 2472 664; + B 8 8 3256 668; + B 8 8 3680 672; + B 8 8 3768 672; + B 8 8 3856 672; + B 8 8 3944 672; + B 8 8 4032 672; + B 8 8 4120 672; + B 8 8 4208 672; + B 8 8 4296 672; + B 8 8 4384 672; + B 8 8 4472 672; + B 8 8 4560 672; + B 8 8 4648 672; + B 8 8 4736 672; + B 8 8 4828 672; + B 8 8 4916 672; + B 8 8 5004 672; + B 8 8 5092 672; + B 8 8 3640 664; + B 8 8 5132 664; + B 8 8 5532 668; + B 8 8 5572 672; + B 8 8 5660 672; + B 8 8 5748 672; + B 8 8 5836 672; + B 8 8 5924 672; + B 8 8 5964 672; + B 8 8 6364 672; + B 8 8 6452 672; + B 8 8 6540 672; + B 8 8 6324 664; + B 8 8 6580 668; + B 8 8 1212 648; + B 8 8 1380 652; + B 8 8 1964 656; + B 8 8 2052 656; + B 8 8 2092 656; + B 8 8 2512 656; + B 8 8 2600 656; + B 8 8 2688 656; + B 8 8 2776 656; + B 8 8 2864 656; + B 8 8 2952 656; + B 8 8 3040 656; + B 8 8 3128 656; + B 8 8 3216 656; + B 8 8 1924 648; + B 8 8 2472 648; + B 8 8 3256 652; + B 8 8 3680 656; + B 8 8 3768 656; + B 8 8 3856 656; + B 8 8 3944 656; + B 8 8 4032 656; + B 8 8 4120 656; + B 8 8 4208 656; + B 8 8 4296 656; + B 8 8 4384 656; + B 8 8 4472 656; + B 8 8 4560 656; + B 8 8 4648 656; + B 8 8 4736 656; + B 8 8 4828 656; + B 8 8 4916 656; + B 8 8 5004 656; + B 8 8 5092 656; + B 8 8 3640 648; + B 8 8 5132 648; + B 8 8 5532 652; + B 8 8 5572 656; + B 8 8 5660 656; + B 8 8 5748 656; + B 8 8 5836 656; + B 8 8 5924 656; + B 8 8 5964 656; + B 8 8 6364 656; + B 8 8 6452 656; + B 8 8 6540 656; + B 8 8 6324 648; + B 8 8 6580 652; + B 8 8 1212 632; + B 8 8 1252 632; + B 8 8 1296 632; + B 8 8 1340 632; + B 8 8 1380 636; + B 8 8 1964 640; + B 8 8 1924 632; + B 8 8 2008 636; + B 8 8 2052 640; + B 8 8 2092 640; + B 8 8 2512 640; + B 8 8 2472 632; + B 8 8 2556 636; + B 8 8 2600 640; + B 8 8 2644 636; + B 8 8 2688 640; + B 8 8 2732 636; + B 8 8 2776 640; + B 8 8 2820 636; + B 8 8 2864 640; + B 8 8 2908 636; + B 8 8 2952 640; + B 8 8 2996 636; + B 8 8 3040 640; + B 8 8 3084 636; + B 8 8 3128 640; + B 8 8 3172 636; + B 8 8 3216 640; + B 8 8 3256 636; + B 8 8 3680 640; + B 8 8 3640 632; + B 8 8 3724 636; + B 8 8 3768 640; + B 8 8 3812 636; + B 8 8 3856 640; + B 8 8 3900 636; + B 8 8 3944 640; + B 8 8 3988 636; + B 8 8 4032 640; + B 8 8 4076 636; + B 8 8 4120 640; + B 8 8 4164 636; + B 8 8 4208 640; + B 8 8 4252 636; + B 8 8 4296 640; + B 8 8 4340 636; + B 8 8 4384 640; + B 8 8 4428 636; + B 8 8 4472 640; + B 8 8 4516 636; + B 8 8 4560 640; + B 8 8 4604 636; + B 8 8 4648 640; + B 8 8 4692 636; + B 8 8 4736 640; + B 8 8 4784 636; + B 8 8 4828 640; + B 8 8 4872 636; + B 8 8 4916 640; + B 8 8 4960 636; + B 8 8 5004 640; + B 8 8 5048 636; + B 8 8 5092 640; + B 8 8 5132 632; + B 8 8 5532 636; + B 8 8 5572 640; + B 8 8 5616 636; + B 8 8 5660 640; + B 8 8 5704 636; + B 8 8 5748 640; + B 8 8 5792 636; + B 8 8 5836 640; + B 8 8 5880 636; + B 8 8 5924 640; + B 8 8 5964 640; + B 8 8 6364 640; + B 8 8 6324 632; + B 8 8 6408 636; + B 8 8 6452 640; + B 8 8 6496 636; + B 8 8 6540 640; + B 8 8 6580 636; + B 8 8 1212 616; + B 8 8 1380 620; + B 8 8 2092 624; + B 8 8 1924 616; + B 8 8 2472 616; + B 8 8 3256 620; + B 8 8 3640 616; + B 8 8 5132 616; + B 8 8 5532 620; + B 8 8 5964 624; + B 8 8 6324 616; + B 8 8 6580 620; + B 8 8 1212 600; + B 8 8 1380 604; + B 8 8 2092 608; + B 8 8 1924 600; + B 8 8 2472 600; + B 8 8 3256 604; + B 8 8 3640 600; + B 8 8 5132 600; + B 8 8 5532 604; + B 8 8 5964 608; + B 8 8 6324 600; + B 8 8 6580 604; + B 8 8 1216 580; + B 8 8 1232 580; + B 8 8 1248 580; + B 8 8 1264 580; + B 8 8 1280 580; + B 8 8 1296 580; + B 8 8 1312 580; + B 8 8 1328 580; + B 8 8 1344 580; + B 8 8 1360 580; + B 8 8 1376 580; + B 8 8 1924 584; + B 8 8 1944 584; + B 8 8 1960 584; + B 8 8 1976 584; + B 8 8 1992 584; + B 8 8 2008 584; + B 8 8 2024 584; + B 8 8 2040 584; + B 8 8 2056 584; + B 8 8 2072 584; + B 8 8 2088 584; + B 8 8 2472 584; + B 8 8 2496 584; + B 8 8 2512 584; + B 8 8 2528 584; + B 8 8 2544 584; + B 8 8 2560 584; + B 8 8 2576 584; + B 8 8 2592 584; + B 8 8 2608 584; + B 8 8 2624 584; + B 8 8 2640 584; + B 8 8 2656 584; + B 8 8 2672 584; + B 8 8 2688 584; + B 8 8 2704 584; + B 8 8 2720 584; + B 8 8 2736 584; + B 8 8 2752 584; + B 8 8 2768 584; + B 8 8 2784 584; + B 8 8 2800 584; + B 8 8 2816 584; + B 8 8 2832 584; + B 8 8 2848 584; + B 8 8 2864 584; + B 8 8 2880 584; + B 8 8 2896 584; + B 8 8 2912 584; + B 8 8 2928 584; + B 8 8 2944 584; + B 8 8 2960 584; + B 8 8 2976 584; + B 8 8 2992 584; + B 8 8 3008 584; + B 8 8 3024 584; + B 8 8 3040 584; + B 8 8 3056 584; + B 8 8 3072 584; + B 8 8 3088 584; + B 8 8 3104 584; + B 8 8 3120 584; + B 8 8 3136 584; + B 8 8 3152 584; + B 8 8 3248 584; + B 8 8 3640 584; + B 8 8 3664 584; + B 8 8 3680 584; + B 8 8 3696 584; + B 8 8 3712 584; + B 8 8 3728 584; + B 8 8 3744 584; + B 8 8 3760 584; + B 8 8 3776 584; + B 8 8 3792 584; + B 8 8 3808 584; + B 8 8 3824 584; + B 8 8 3840 584; + B 8 8 3856 584; + B 8 8 3872 584; + B 8 8 3888 584; + B 8 8 3904 584; + B 8 8 3920 584; + B 8 8 3936 584; + B 8 8 3952 584; + B 8 8 3968 584; + B 8 8 3984 584; + B 8 8 4000 584; + B 8 8 4016 584; + B 8 8 4032 584; + B 8 8 4048 584; + B 8 8 4064 584; + B 8 8 4080 584; + B 8 8 4096 584; + B 8 8 4112 584; + B 8 8 4128 584; + B 8 8 4144 584; + B 8 8 4160 584; + B 8 8 4176 584; + B 8 8 4192 584; + B 8 8 4208 584; + B 8 8 4224 584; + B 8 8 4240 584; + B 8 8 4256 584; + B 8 8 4272 584; + B 8 8 4288 584; + B 8 8 4304 584; + B 8 8 4320 584; + B 8 8 4336 584; + B 8 8 4352 584; + B 8 8 4368 584; + B 8 8 4384 584; + B 8 8 4400 584; + B 8 8 4416 584; + B 8 8 4432 584; + B 8 8 4448 584; + B 8 8 4464 584; + B 8 8 4480 584; + B 8 8 4496 584; + B 8 8 4512 584; + B 8 8 4528 584; + B 8 8 4544 584; + B 8 8 4560 584; + B 8 8 4576 584; + B 8 8 4592 584; + B 8 8 4608 584; + B 8 8 4624 584; + B 8 8 4640 584; + B 8 8 4656 584; + B 8 8 4672 584; + B 8 8 4688 584; + B 8 8 4704 584; + B 8 8 4720 584; + B 8 8 4736 584; + B 8 8 4752 584; + B 8 8 4768 584; + B 8 8 4784 584; + B 8 8 4800 584; + B 8 8 4816 584; + B 8 8 4832 584; + B 8 8 4848 584; + B 8 8 4864 584; + B 8 8 4880 584; + B 8 8 4896 584; + B 8 8 4912 584; + B 8 8 4928 584; + B 8 8 4944 584; + B 8 8 4960 584; + B 8 8 4976 584; + B 8 8 4992 584; + B 8 8 5008 584; + B 8 8 5024 584; + B 8 8 5040 584; + B 8 8 5056 584; + B 8 8 5072 584; + B 8 8 5088 584; + B 8 8 5104 584; + B 8 8 5132 584; + B 8 8 5536 584; + B 8 8 5628 584; + B 8 8 5644 584; + B 8 8 5660 584; + B 8 8 5676 584; + B 8 8 5692 584; + B 8 8 5708 584; + B 8 8 5724 584; + B 8 8 5740 584; + B 8 8 5756 584; + B 8 8 5772 584; + B 8 8 5788 584; + B 8 8 5804 584; + B 8 8 5820 584; + B 8 8 5836 584; + B 8 8 5852 584; + B 8 8 5868 584; + B 8 8 5884 584; + B 8 8 5900 584; + B 8 8 5916 584; + B 8 8 5932 584; + B 8 8 5948 584; + B 8 8 5964 584; + B 8 8 6324 584; + B 8 8 6348 584; + B 8 8 6364 584; + B 8 8 6380 584; + B 8 8 6396 584; + B 8 8 6412 584; + B 8 8 6428 584; + B 8 8 6444 584; + B 8 8 6460 584; + B 8 8 6476 584; + B 8 8 6572 584; +L CCA; + B 8 8 656 1184; + B 8 8 684 1184; + B 8 8 2256 1184; + B 8 8 2284 1184; + B 8 8 3856 1184; + B 8 8 3884 1184; + B 8 8 5456 1184; + B 8 8 5484 1184; + B 8 8 7056 1184; + B 8 8 7084 1184; + B 8 8 656 1156; + B 8 8 684 1156; + B 8 8 2256 1156; + B 8 8 2284 1156; + B 8 8 3856 1156; + B 8 8 3884 1156; + B 8 8 5456 1156; + B 8 8 5484 1156; + B 8 8 7056 1156; + B 8 8 7084 1156; + B 8 8 656 1128; + B 8 8 684 1128; + B 8 8 2256 1128; + B 8 8 2284 1128; + B 8 8 3856 1128; + B 8 8 3884 1128; + B 8 8 5456 1128; + B 8 8 5484 1128; + B 8 8 7056 1128; + B 8 8 7084 1128; + B 8 8 1448 184; + B 8 8 1476 184; + B 8 8 3048 184; + B 8 8 3076 184; + B 8 8 4648 184; + B 8 8 4676 184; + B 8 8 6248 184; + B 8 8 6276 184; + B 8 8 1448 156; + B 8 8 1476 156; + B 8 8 3048 156; + B 8 8 3076 156; + B 8 8 4648 156; + B 8 8 4676 156; + B 8 8 6248 156; + B 8 8 6276 156; + B 8 8 1448 128; + B 8 8 1476 128; + B 8 8 3048 128; + B 8 8 3076 128; + B 8 8 4648 128; + B 8 8 4676 128; + B 8 8 6248 128; + B 8 8 6276 128; +L CBA; + B 112 48 1296 632; + B 112 92 2008 658; + B 728 92 2864 658; + B 1436 92 4386 658; + B 376 92 5748 658; + B 200 92 6452 658; +L CSN; + B 88 4 1972 750; + B 112 36 1960 730; + B 40 28 2084 738; + B 800 4 2876 750; + B 1416 4 4348 750; + B 48 12 2088 718; + B 88 4 1256 702; + B 108 36 1246 682; + B 40 32 1372 688; + B 48 8 1376 668; + B 40 64 1212 632; + B 40 64 1380 632; + B 208 16 1296 592; + B 40 108 1924 658; + B 40 108 2092 658; + B 208 16 2008 596; + B 824 36 2864 730; + B 40 108 2472 658; + B 40 108 3256 658; + B 204 4 1294 582; + B 200 20 1296 570; + B 204 24 2006 576; + B 720 40 2812 584; + B 48 20 3252 594; + B 1436 36 4338 730; + B 40 20 5128 742; + B 44 20 5130 722; + B 40 108 3640 658; + B 40 108 5132 658; + B 40 20 3248 574; + B 1532 40 4386 584; + B 464 28 5744 738; + B 272 4 6464 750; + B 472 12 5748 718; + B 40 108 5532 658; + B 40 108 5964 658; + B 44 20 5534 594; + B 40 20 5536 574; + B 376 40 5796 584; + B 296 36 6452 730; + B 40 108 6324 658; + B 40 108 6580 658; + B 192 40 6400 584; + B 48 20 6576 594; + B 40 20 6572 574; +L CSN; + B 208 40 2008 732; + B 208 40 1296 684; + B 40 64 1212 632; + B 32 32 1296 632; + B 40 64 1380 632; + B 208 40 1296 580; + B 40 108 1924 658; + B 32 32 2008 680; + B 32 32 2008 636; + B 40 108 2092 658; + B 208 40 2008 584; + B 824 40 2864 732; + B 40 108 2472 658; + B 32 32 2556 680; + B 32 32 2644 680; + B 32 32 2732 680; + B 32 32 2820 680; + B 32 32 2908 680; + B 32 32 2996 680; + B 32 32 3084 680; + B 32 32 3172 680; + B 32 32 2556 636; + B 32 32 2644 636; + B 32 32 2732 636; + B 32 32 2820 636; + B 32 32 2908 636; + B 32 32 2996 636; + B 32 32 3084 636; + B 32 32 3172 636; + B 40 108 3256 658; + B 824 40 2864 584; + B 1532 40 4386 732; + B 40 108 3640 658; + B 32 32 3724 680; + B 32 32 3812 680; + B 32 32 3900 680; + B 32 32 3988 680; + B 32 32 4076 680; + B 32 32 4164 680; + B 32 32 4252 680; + B 32 32 4340 680; + B 32 32 4428 680; + B 32 32 4516 680; + B 32 32 4604 680; + B 32 32 4692 680; + B 32 32 4784 680; + B 32 32 4872 680; + B 32 32 4960 680; + B 32 32 5048 680; + B 32 32 3724 636; + B 32 32 3812 636; + B 32 32 3900 636; + B 32 32 3988 636; + B 32 32 4076 636; + B 32 32 4164 636; + B 32 32 4252 636; + B 32 32 4340 636; + B 32 32 4428 636; + B 32 32 4516 636; + B 32 32 4604 636; + B 32 32 4692 636; + B 32 32 4784 636; + B 32 32 4872 636; + B 32 32 4960 636; + B 32 32 5048 636; + B 40 108 5132 658; + B 1532 40 4386 584; + B 472 40 5748 732; + B 40 108 5532 658; + B 32 32 5616 680; + B 32 32 5704 680; + B 32 32 5792 680; + B 32 32 5880 680; + B 32 32 5616 636; + B 32 32 5704 636; + B 32 32 5792 636; + B 32 32 5880 636; + B 40 108 5964 658; + B 472 40 5748 584; + B 296 40 6452 732; + B 40 108 6324 658; + B 32 32 6408 680; + B 32 32 6496 680; + B 32 32 6408 636; + B 32 32 6496 636; + B 40 108 6580 658; + B 296 40 6452 584; +L CSP; + B 60 88 670 1156; + B 60 88 2270 1156; + B 60 88 3870 1156; + B 60 88 5470 1156; + B 60 88 7070 1156; + B 24 24 1252 632; + B 24 24 1340 632; + B 24 56 1964 656; + B 24 56 2052 656; + B 24 56 2512 656; + B 24 56 2600 656; + B 24 56 2688 656; + B 24 56 2776 656; + B 24 56 2864 656; + B 24 56 2952 656; + B 24 56 3040 656; + B 24 56 3128 656; + B 24 56 3216 656; + B 24 56 3680 656; + B 24 56 3768 656; + B 24 56 3856 656; + B 24 56 3944 656; + B 24 56 4032 656; + B 24 56 4120 656; + B 24 56 4208 656; + B 24 56 4296 656; + B 24 56 4384 656; + B 24 56 4472 656; + B 24 56 4560 656; + B 24 56 4648 656; + B 24 56 4736 656; + B 24 56 4828 656; + B 24 56 4916 656; + B 24 56 5004 656; + B 24 56 5092 656; + B 24 56 5572 656; + B 24 56 5660 656; + B 24 56 5748 656; + B 24 56 5836 656; + B 24 56 5924 656; + B 24 56 6364 656; + B 24 56 6452 656; + B 24 56 6540 656; + B 60 88 1462 156; + B 60 88 3062 156; + B 60 88 4662 156; + B 60 88 6262 156; +L COG; + B 376 376 264 1056; + B 376 376 1064 1056; + B 376 376 1864 1056; + B 376 376 2664 1056; + B 376 376 3464 1056; + B 376 376 4264 1056; + B 376 376 5064 1056; + B 376 376 5864 1056; + B 376 376 6664 1056; + B 376 376 7464 1056; + B 376 376 264 256; + B 376 376 1064 256; + B 376 376 1864 256; + B 376 376 2664 256; + B 376 376 3464 256; + B 376 376 4264 256; + B 376 376 5064 256; + B 376 376 5864 256; + B 376 376 6664 256; + B 376 376 7464 256; +DF; +C 1; +End diff --git a/scmos/examples/bipolar/npn_array20.cif b/scmos/examples/bipolar/npn_array20.cif new file mode 100644 index 00000000..1efa9a40 --- /dev/null +++ b/scmos/examples/bipolar/npn_array20.cif @@ -0,0 +1,397 @@ +DS1 100/4; C2 T0 15360 ; DF; DS2 100/4; C3 ; C4 ; C5 ; +C6 ; C7 ; C8 ; C9 ; C10 ; C11 ; LCOG; B296 296 160 -14560; +B296 296 800 -14560; B296 296 1440 -14560; B296 296 2080 -14560; +B296 296 2720 -14560; B296 296 3360 -14560; B296 296 4000 -14560; +B296 296 4640 -14560; DF; DS11 100/4; LCCA; B8 8 3964 -14804; +B8 8 3948 -14804; B8 8 3932 -14804; B8 8 3916 -14804; +B8 8 3900 -14804; B8 8 3884 -14804; B8 8 3868 -14804; +B8 8 3852 -14804; B8 8 3836 -14804; B8 8 3820 -14804; +B8 8 3804 -14804; B8 8 3788 -14804; B8 8 3772 -14804; +B8 8 3756 -14804; B8 8 3740 -14804; B8 8 3724 -14804; +B8 8 3708 -14804; B8 8 3692 -14804; B8 8 3676 -14804; +B8 8 3660 -14804; B8 8 3644 -14804; B8 8 3628 -14804; +B8 8 3612 -14804; B8 8 3596 -14804; B8 8 3580 -14804; +B8 8 3564 -14804; B8 8 3548 -14804; B8 8 3532 -14804; +B8 8 3516 -14804; B8 8 3500 -14804; B8 8 3484 -14804; +B8 8 3468 -14804; B8 8 3452 -14804; B8 8 3436 -14804; +B8 8 3420 -14804; B8 8 3404 -14804; B8 8 3388 -14804; +B8 8 3372 -14804; B8 8 3356 -14804; B8 8 3340 -14804; +B8 8 3324 -14804; B8 8 3308 -14804; B8 8 3292 -14804; +B8 8 3276 -14804; B8 8 3260 -14804; B8 8 3244 -14804; +B8 8 3228 -14804; B8 8 3212 -14804; B8 8 3196 -14804; +B8 8 3180 -14804; B8 8 3164 -14804; B8 8 3148 -14804; +B8 8 3132 -14804; B8 8 3116 -14804; B8 8 3100 -14804; +B8 8 3084 -14804; B8 8 3068 -14804; B8 8 3052 -14804; +B8 8 3036 -14804; B8 8 3020 -14804; B8 8 3004 -14804; +B8 8 2988 -14804; B8 8 2972 -14804; B8 8 2956 -14804; +B8 8 2940 -14804; B8 8 2924 -14804; B8 8 2908 -14804; +B8 8 2892 -14804; B8 8 2876 -14804; B8 8 2860 -14804; +B8 8 2844 -14804; B8 8 2828 -14804; B8 8 2812 -14804; +B8 8 2796 -14804; B8 8 2776 -14806; B8 8 2392 -14804; +B8 8 2368 -14804; B8 8 2352 -14804; B8 8 2336 -14804; +B8 8 2320 -14804; B8 8 2304 -14804; B8 8 2288 -14804; +B8 8 2272 -14804; B8 8 2256 -14804; B8 8 2240 -14804; +B8 8 2224 -14804; B8 8 2208 -14804; B8 8 2192 -14804; +B8 8 2176 -14804; B8 8 2160 -14804; B8 8 2144 -14804; +B8 8 2128 -14804; B8 8 2112 -14804; B8 8 2096 -14804; +B8 8 2080 -14804; B8 8 2064 -14804; B8 8 2048 -14804; +B8 8 2032 -14804; B8 8 2016 -14804; B8 8 2000 -14804; +B8 8 1984 -14804; B8 8 1968 -14804; B8 8 1952 -14804; +B8 8 1936 -14804; B8 8 1920 -14804; B8 8 1904 -14804; +B8 8 1888 -14804; B8 8 1872 -14804; B8 8 1856 -14804; +B8 8 1840 -14804; B8 8 1824 -14804; B8 8 1808 -14804; +B8 8 1792 -14804; B8 8 1776 -14804; B8 8 1760 -14804; +B8 8 1744 -14804; B8 8 1728 -14804; B8 8 1712 -14804; +B8 8 1696 -14804; B8 8 1680 -14804; B8 8 1664 -14804; +B8 8 1648 -14804; B8 8 1632 -14804; B8 8 1608 -14806; +B8 8 1222 -14804; B8 8 1132 -14804; B8 8 1116 -14804; +B8 8 1100 -14804; B8 8 1084 -14804; B8 8 1060 -14806; +DF; DS10 100/4; LCCA; B8 8 3608 -14862; B8 8 3564 -14856; +B8 8 3520 -14862; B8 8 3476 -14856; B8 8 3432 -14862; +B8 8 3388 -14856; B8 8 3344 -14862; B8 8 3300 -14856; +B8 8 3256 -14862; B8 8 3212 -14856; B8 8 3168 -14862; +B8 8 3124 -14856; B8 8 3080 -14862; B8 8 3036 -14856; +B8 8 2992 -14862; B8 8 2948 -14856; B8 8 2904 -14862; +B8 8 2860 -14856; B8 8 2816 -14862; B8 8 2392 -14868; +B8 8 1608 -14870; B8 8 1060 -14870; B8 8 348 -14870; +B8 8 2352 -14862; B8 8 2776 -14854; B8 8 2392 -14852; +B8 8 2308 -14856; B8 8 2264 -14862; B8 8 2220 -14856; +B8 8 2176 -14862; B8 8 2132 -14856; B8 8 2088 -14862; +B8 8 2044 -14856; B8 8 2000 -14862; B8 8 1956 -14856; +B8 8 1912 -14862; B8 8 1868 -14856; B8 8 1824 -14862; +B8 8 1780 -14856; B8 8 1736 -14862; B8 8 1692 -14856; +B8 8 1648 -14862; B8 8 1228 -14862; B8 8 1188 -14862; +B8 8 1608 -14854; B8 8 1144 -14856; B8 8 1100 -14862; +B8 8 1060 -14854; B8 8 5716 -14836; B8 8 5460 -14838; +B8 8 5100 -14830; B8 8 4668 -14836; B8 8 4268 -14840; +B8 8 1228 -14846; B8 8 510 -14852; B8 8 418 -14852; +B8 8 402 -14852; B8 8 386 -14852; B8 8 370 -14852; B8 8 348 -14854; +B8 8 2776 -14838; B8 8 2392 -14836; B8 8 1608 -14838; +B8 8 1060 -14838; B8 8 5716 -14820; B8 8 5460 -14822; +B8 8 4668 -14820; B8 8 4268 -14824; B8 8 1228 -14830; +B8 8 2776 -14822; B8 8 2392 -14820; B8 8 1608 -14822; +B8 8 1060 -14822; B8 8 5716 -14804; B8 8 5692 -14804; +B8 8 5676 -14804; B8 8 5660 -14804; B8 8 5644 -14804; +B8 8 5628 -14804; B8 8 5612 -14804; B8 8 5596 -14804; +B8 8 5580 -14804; B8 8 5564 -14804; B8 8 5548 -14804; +B8 8 5532 -14804; B8 8 5516 -14804; B8 8 5500 -14804; +B8 8 5484 -14804; B8 8 5460 -14806; B8 8 5094 -14804; +B8 8 5078 -14804; B8 8 5062 -14804; B8 8 5046 -14804; +B8 8 5030 -14804; B8 8 5014 -14804; B8 8 4998 -14804; +B8 8 4982 -14804; B8 8 4966 -14804; B8 8 4950 -14804; +B8 8 4934 -14804; B8 8 4918 -14804; B8 8 4902 -14804; +B8 8 4886 -14804; B8 8 4870 -14804; B8 8 4854 -14804; +B8 8 4838 -14804; B8 8 4822 -14804; B8 8 4806 -14804; +B8 8 4790 -14804; B8 8 4774 -14804; B8 8 4758 -14804; +B8 8 4742 -14804; B8 8 4726 -14804; B8 8 4710 -14804; +B8 8 4694 -14804; B8 8 4668 -14804; B8 8 4264 -14804; +B8 8 4172 -14804; B8 8 4156 -14804; B8 8 4140 -14804; +B8 8 4124 -14804; B8 8 4108 -14804; B8 8 4092 -14804; +B8 8 4076 -14804; B8 8 4060 -14804; B8 8 4044 -14804; +B8 8 4028 -14804; B8 8 4012 -14804; B8 8 3996 -14804; +B8 8 3980 -14804; DF; DS9 100/4; LCCA; B8 8 3920 -14900; +B8 8 3872 -14894; B8 8 3828 -14900; B8 8 3784 -14894; +B8 8 3740 -14900; B8 8 3696 -14894; B8 8 3652 -14900; +B8 8 3608 -14894; B8 8 3564 -14900; B8 8 3520 -14894; +B8 8 3476 -14900; B8 8 3432 -14894; B8 8 3388 -14900; +B8 8 3344 -14894; B8 8 3300 -14900; B8 8 3256 -14894; +B8 8 3212 -14900; B8 8 3168 -14894; B8 8 3124 -14900; +B8 8 3080 -14894; B8 8 3036 -14900; B8 8 2992 -14894; +B8 8 2948 -14900; B8 8 2904 -14894; B8 8 2860 -14900; +B8 8 2776 -14902; B8 8 2816 -14894; B8 8 2392 -14900; +B8 8 2352 -14894; B8 8 2308 -14900; B8 8 2264 -14894; +B8 8 2220 -14900; B8 8 2176 -14894; B8 8 2132 -14900; +B8 8 2088 -14894; B8 8 2044 -14900; B8 8 2000 -14894; +B8 8 1956 -14900; B8 8 1912 -14894; B8 8 1868 -14900; +B8 8 1824 -14894; B8 8 1780 -14900; B8 8 1736 -14894; +B8 8 1692 -14900; B8 8 1608 -14902; B8 8 1648 -14894; +B8 8 1228 -14894; B8 8 1188 -14894; B8 8 1144 -14900; +B8 8 1060 -14902; B8 8 1100 -14894; B8 8 516 -14898; +B8 8 476 -14904; B8 8 432 -14904; B8 8 388 -14904; B8 8 348 -14902; +B8 8 2776 -14886; B8 8 5716 -14868; B8 8 5460 -14870; +B8 8 5676 -14862; B8 8 5716 -14852; B8 8 5632 -14856; +B8 8 5588 -14862; B8 8 5544 -14856; B8 8 5500 -14862; +B8 8 5100 -14862; B8 8 5060 -14862; B8 8 5460 -14854; +B8 8 5016 -14856; B8 8 4972 -14862; B8 8 4928 -14856; +B8 8 4884 -14862; B8 8 4840 -14856; B8 8 4796 -14862; +B8 8 4752 -14856; B8 8 4708 -14862; B8 8 4668 -14868; +B8 8 4268 -14872; B8 8 4228 -14878; B8 8 4140 -14878; +B8 8 4052 -14878; B8 8 3964 -14878; B8 8 3872 -14878; +B8 8 3784 -14878; B8 8 3696 -14878; B8 8 3608 -14878; +B8 8 3520 -14878; B8 8 3432 -14878; B8 8 3344 -14878; +B8 8 3256 -14878; B8 8 3168 -14878; B8 8 3080 -14878; +B8 8 2992 -14878; B8 8 2904 -14878; B8 8 2816 -14878; +B8 8 2392 -14884; B8 8 1608 -14886; B8 8 1060 -14886; +B8 8 2352 -14878; B8 8 2264 -14878; B8 8 2176 -14878; +B8 8 2088 -14878; B8 8 2000 -14878; B8 8 1912 -14878; +B8 8 1824 -14878; B8 8 1736 -14878; B8 8 1648 -14878; +B8 8 1228 -14878; B8 8 1188 -14878; B8 8 1100 -14878; +B8 8 516 -14882; B8 8 348 -14886; B8 8 2776 -14870; +B8 8 5100 -14846; B8 8 4668 -14852; B8 8 4268 -14856; +B8 8 4228 -14862; B8 8 4184 -14856; B8 8 4140 -14862; +B8 8 4096 -14856; B8 8 4052 -14862; B8 8 4008 -14856; +B8 8 3964 -14862; B8 8 3920 -14856; B8 8 3872 -14862; +B8 8 3828 -14856; B8 8 3784 -14862; B8 8 3740 -14856; +B8 8 3696 -14862; B8 8 3652 -14856; DF; DS8 100/4; LCCA; +B8 8 2776 -14950; B8 8 2386 -14952; B8 8 2288 -14952; +B8 8 2272 -14952; B8 8 2256 -14952; B8 8 2240 -14952; +B8 8 2224 -14952; B8 8 2208 -14952; B8 8 2192 -14952; +B8 8 2176 -14952; B8 8 2160 -14952; B8 8 2144 -14952; +B8 8 2128 -14952; B8 8 2112 -14952; B8 8 2096 -14952; +B8 8 2080 -14952; B8 8 2064 -14952; B8 8 2048 -14952; +B8 8 2032 -14952; B8 8 2016 -14952; B8 8 2000 -14952; +B8 8 1984 -14952; B8 8 1968 -14952; B8 8 1952 -14952; +B8 8 1936 -14952; B8 8 1920 -14952; B8 8 1904 -14952; +B8 8 1888 -14952; B8 8 1872 -14952; B8 8 1856 -14952; +B8 8 1840 -14952; B8 8 1824 -14952; B8 8 1808 -14952; +B8 8 1792 -14952; B8 8 1776 -14952; B8 8 1760 -14952; +B8 8 1744 -14952; B8 8 1728 -14952; B8 8 1712 -14952; +B8 8 1696 -14952; B8 8 1680 -14952; B8 8 1664 -14952; +B8 8 1648 -14952; B8 8 1632 -14952; B8 8 1608 -14950; +B8 8 1226 -14952; B8 8 1210 -14952; B8 8 1194 -14952; +B8 8 1178 -14952; B8 8 1162 -14952; B8 8 1146 -14952; +B8 8 1130 -14952; B8 8 1114 -14952; B8 8 1098 -14952; +B8 8 1082 -14952; B8 8 1060 -14950; B8 8 512 -14956; +B8 8 496 -14956; B8 8 480 -14956; B8 8 464 -14956; B8 8 448 -14956; +B8 8 432 -14956; B8 8 416 -14956; B8 8 400 -14956; B8 8 384 -14956; +B8 8 368 -14956; B8 8 352 -14956; B8 8 5716 -14932; +B8 8 5460 -14934; B8 8 5100 -14926; B8 8 4668 -14932; +B8 8 4268 -14936; B8 8 2776 -14934; B8 8 2392 -14932; +B8 8 1608 -14934; B8 8 1060 -14934; B8 8 5716 -14916; +B8 8 5460 -14918; B8 8 5100 -14910; B8 8 4668 -14916; +B8 8 4268 -14920; B8 8 1228 -14926; B8 8 516 -14930; +B8 8 348 -14934; B8 8 2776 -14918; B8 8 2392 -14916; +B8 8 1608 -14918; B8 8 1060 -14918; B8 8 5716 -14900; +B8 8 5676 -14894; B8 8 5632 -14900; B8 8 5588 -14894; +B8 8 5544 -14900; B8 8 5460 -14902; B8 8 5500 -14894; +B8 8 5100 -14894; B8 8 5060 -14894; B8 8 5016 -14900; +B8 8 4972 -14894; B8 8 4928 -14900; B8 8 4884 -14894; +B8 8 4840 -14900; B8 8 4796 -14894; B8 8 4752 -14900; +B8 8 4708 -14894; B8 8 4668 -14900; B8 8 4268 -14904; +B8 8 1228 -14910; B8 8 516 -14914; B8 8 348 -14918; +B8 8 5716 -14884; B8 8 5460 -14886; B8 8 5676 -14878; +B8 8 5588 -14878; B8 8 5500 -14878; B8 8 5100 -14878; +B8 8 5060 -14878; B8 8 4972 -14878; B8 8 4884 -14878; +B8 8 4796 -14878; B8 8 4708 -14878; B8 8 4668 -14884; +B8 8 4268 -14888; B8 8 4228 -14894; B8 8 4184 -14900; +B8 8 4140 -14894; B8 8 4096 -14900; B8 8 4052 -14894; +B8 8 4008 -14900; B8 8 3964 -14894; DF; DS7 100/4; LCVA; +B288 288 4000 -15200; B288 288 4640 -15200; B288 288 5280 -15200; +B288 288 5920 -15200; LCCA; B8 8 5710 -14952; B8 8 5614 -14952; +B8 8 5598 -14952; B8 8 5582 -14952; B8 8 5566 -14952; +B8 8 5550 -14952; B8 8 5534 -14952; B8 8 5518 -14952; +B8 8 5502 -14952; B8 8 5486 -14952; B8 8 5460 -14950; +B8 8 5100 -14952; B8 8 5084 -14952; B8 8 5068 -14952; +B8 8 5052 -14952; B8 8 5036 -14952; B8 8 5020 -14952; +B8 8 5004 -14952; B8 8 4988 -14952; B8 8 4972 -14952; +B8 8 4956 -14952; B8 8 4940 -14952; B8 8 4924 -14952; +B8 8 4908 -14952; B8 8 4892 -14952; B8 8 4876 -14952; +B8 8 4860 -14952; B8 8 4844 -14952; B8 8 4828 -14952; +B8 8 4812 -14952; B8 8 4796 -14952; B8 8 4780 -14952; +B8 8 4764 -14952; B8 8 4674 -14952; B8 8 4268 -14952; +B8 8 4242 -14952; B8 8 4226 -14952; B8 8 4210 -14952; +B8 8 4194 -14952; B8 8 4178 -14952; B8 8 4162 -14952; +B8 8 4146 -14952; B8 8 4130 -14952; B8 8 4114 -14952; +B8 8 4098 -14952; B8 8 4082 -14952; B8 8 4066 -14952; +B8 8 4050 -14952; B8 8 4034 -14952; B8 8 4018 -14952; +B8 8 4002 -14952; B8 8 3986 -14952; B8 8 3970 -14952; +B8 8 3954 -14952; B8 8 3938 -14952; B8 8 3922 -14952; +B8 8 3906 -14952; B8 8 3890 -14952; B8 8 3874 -14952; +B8 8 3858 -14952; B8 8 3842 -14952; B8 8 3826 -14952; +B8 8 3810 -14952; B8 8 3794 -14952; B8 8 3778 -14952; +B8 8 3762 -14952; B8 8 3746 -14952; B8 8 3730 -14952; +B8 8 3714 -14952; B8 8 3698 -14952; B8 8 3682 -14952; +B8 8 3666 -14952; B8 8 3650 -14952; B8 8 3634 -14952; +B8 8 3618 -14952; B8 8 3602 -14952; B8 8 3586 -14952; +B8 8 3570 -14952; B8 8 3554 -14952; B8 8 3538 -14952; +B8 8 3522 -14952; B8 8 3506 -14952; B8 8 3490 -14952; +B8 8 3474 -14952; B8 8 3458 -14952; B8 8 3442 -14952; +B8 8 3426 -14952; B8 8 3410 -14952; B8 8 3394 -14952; +B8 8 3378 -14952; B8 8 3362 -14952; B8 8 3346 -14952; +B8 8 3330 -14952; B8 8 3314 -14952; B8 8 3298 -14952; +B8 8 3282 -14952; B8 8 3266 -14952; B8 8 3250 -14952; +B8 8 3234 -14952; B8 8 3218 -14952; B8 8 3202 -14952; +B8 8 3186 -14952; B8 8 3170 -14952; B8 8 3154 -14952; +B8 8 3138 -14952; B8 8 3122 -14952; B8 8 3106 -14952; +B8 8 3090 -14952; B8 8 3074 -14952; B8 8 3058 -14952; +B8 8 3042 -14952; B8 8 3026 -14952; B8 8 3010 -14952; +B8 8 2994 -14952; B8 8 2978 -14952; B8 8 2962 -14952; +B8 8 2946 -14952; B8 8 2930 -14952; B8 8 2914 -14952; +B8 8 2898 -14952; B8 8 2882 -14952; B8 8 2866 -14952; +B8 8 2850 -14952; B8 8 2834 -14952; B8 8 2818 -14952; +B8 8 2802 -14952; DF; DS6 100/4; LCSN; B40 108 5100 -14878; +B40 108 4668 -14878; B472 40 4884 -14804; B1532 40 3522 -14952; +B40 108 4268 -14878; B40 108 2776 -14878; B48 40 4264 -14804; +B1436 40 3474 -14804; B52 40 2386 -14952; B724 40 1950 -14952; +B40 108 2392 -14878; B40 108 1608 -14878; B824 40 2000 -14804; +B208 40 1144 -14952; B40 108 1228 -14878; B40 108 1060 -14878; +B208 40 432 -14956; B40 64 516 -14904; B40 64 348 -14904; +B52 40 510 -14852; B112 40 384 -14852; B52 40 1222 -14804; +B112 40 1096 -14804; B84 20 5662 -14962; B20 16 5470 -14960; +B84 20 4722 -14962; B20 16 4258 -14960; B20 16 2786 -14960; +B88 20 2336 -14962; B20 16 1618 -14960; B20 16 1070 -14960; +B272 20 5596 -14942; B464 20 4884 -14942; B1492 20 3522 -14942; +B800 20 2008 -14942; B184 20 1152 -14942; B200 20 432 -14946; +B20 108 5706 -14878; B32 32 5632 -14900; B32 32 5544 -14900; +B32 32 5632 -14856; B32 32 5544 -14856; B20 108 5470 -14878; +B20 108 5090 -14878; B32 32 5016 -14900; B32 32 4928 -14900; +B32 32 4840 -14900; B32 32 4752 -14900; B32 32 5016 -14856; +B32 32 4928 -14856; B32 32 4840 -14856; B32 32 4752 -14856; +B20 108 4678 -14878; B20 108 4258 -14878; B32 32 4184 -14900; +B32 32 4096 -14900; B32 32 4008 -14900; B32 32 3920 -14900; +B32 32 3828 -14900; B32 32 3740 -14900; B32 32 3652 -14900; +B32 32 3564 -14900; B32 32 3476 -14900; B32 32 3388 -14900; +B32 32 3300 -14900; B32 32 3212 -14900; B32 32 3124 -14900; +B32 32 3036 -14900; B32 32 2948 -14900; B32 32 2860 -14900; +B32 32 4184 -14856; B32 32 4096 -14856; B32 32 4008 -14856; +B32 32 3920 -14856; B32 32 3828 -14856; B32 32 3740 -14856; +B32 32 3652 -14856; B32 32 3564 -14856; B32 32 3476 -14856; +B32 32 3388 -14856; B32 32 3300 -14856; B32 32 3212 -14856; +B32 32 3124 -14856; B32 32 3036 -14856; B32 32 2948 -14856; +B32 32 2860 -14856; B20 108 2786 -14878; B256 20 5588 -14814; +B448 20 4892 -14814; B1508 20 3530 -14814; B20 16 5706 -14796; +B20 16 5470 -14796; B20 16 4678 -14796; B88 20 4216 -14794; +B20 16 2786 -14796; B20 108 2382 -14878; B32 32 2308 -14900; +B32 32 2220 -14900; B32 32 2132 -14900; B32 32 2044 -14900; +B32 32 1956 -14900; B32 32 1868 -14900; B32 32 1780 -14900; +B32 32 1692 -14900; B32 32 2308 -14856; B32 32 2220 -14856; +B32 32 2132 -14856; B32 32 2044 -14856; B32 32 1956 -14856; +B32 32 1868 -14856; B32 32 1780 -14856; B32 32 1692 -14856; +B20 108 1618 -14878; B20 108 1218 -14878; B32 32 1144 -14900; +B32 32 1144 -14856; B20 108 1070 -14878; B20 60 506 -14906; +B32 32 432 -14904; B36 4 514 -14874; B20 64 358 -14904; +B184 20 440 -14862; B84 20 462 -14842; B20 16 358 -14844; +B784 20 2000 -14814; B184 20 1152 -14814; B20 16 2382 -14796; +B20 16 1618 -14796; B84 20 1174 -14794; B24 16 1072 -14796; +DF; DS5 100/4; LCSP; B60 88 478 -14500; B60 88 1758 -14500; +B60 88 3038 -14500; B60 88 4318 -14500; B60 88 5598 -14500; +B24 24 388 -14904; B24 24 476 -14904; B24 68 1100 -14878; +B24 68 1188 -14878; B24 68 1648 -14878; B24 68 1736 -14878; +B24 68 1824 -14878; B24 68 1912 -14878; B24 68 2000 -14878; +B24 68 2088 -14878; B24 68 2176 -14878; B24 68 2264 -14878; +B24 68 2352 -14878; B24 68 2816 -14878; B24 68 2904 -14878; +B24 68 2992 -14878; B24 68 3080 -14878; B24 68 3168 -14878; +B24 68 3256 -14878; B24 68 3344 -14878; B24 68 3432 -14878; +B24 68 3520 -14878; B24 68 3608 -14878; B24 68 3696 -14878; +B24 68 3784 -14878; B24 68 3872 -14878; B24 68 3964 -14878; +B24 68 4052 -14878; B24 68 4140 -14878; B24 68 4228 -14878; +B24 68 4708 -14878; B24 68 4796 -14878; B24 68 4884 -14878; +B24 68 4972 -14878; B24 68 5060 -14878; B24 68 5500 -14878; +B24 68 5588 -14878; B24 68 5676 -14878; B60 88 1118 -15260; +B60 88 2398 -15260; B60 88 3678 -15260; B60 88 4958 -15260; +LCCA; B8 8 464 -14472; B8 8 492 -14472; B8 8 1744 -14472; +B8 8 1772 -14472; B8 8 3024 -14472; B8 8 3052 -14472; +B8 8 4304 -14472; B8 8 4332 -14472; B8 8 5584 -14472; +B8 8 5612 -14472; B8 8 464 -14500; B8 8 492 -14500; +B8 8 1744 -14500; B8 8 1772 -14500; B8 8 3024 -14500; +B8 8 3052 -14500; B8 8 4304 -14500; B8 8 4332 -14500; +B8 8 5584 -14500; B8 8 5612 -14500; B8 8 464 -14528; +B8 8 492 -14528; B8 8 1744 -14528; B8 8 1772 -14528; +B8 8 3024 -14528; B8 8 3052 -14528; B8 8 4304 -14528; +B8 8 4332 -14528; B8 8 5584 -14528; B8 8 5612 -14528; +B8 8 1104 -15232; B8 8 1132 -15232; B8 8 2384 -15232; +B8 8 2412 -15232; B8 8 3664 -15232; B8 8 3692 -15232; +B8 8 4944 -15232; B8 8 4972 -15232; B8 8 1104 -15260; +B8 8 1132 -15260; B8 8 2384 -15260; B8 8 2412 -15260; +B8 8 3664 -15260; B8 8 3692 -15260; B8 8 4944 -15260; +B8 8 4972 -15260; B8 8 1104 -15288; B8 8 1132 -15288; +B8 8 2384 -15288; B8 8 2412 -15288; B8 8 3664 -15288; +B8 8 3692 -15288; B8 8 4944 -15288; B8 8 4972 -15288; +LCVA; B288 288 160 -14560; B288 288 800 -14560; B288 288 1440 -14560; +B288 288 2080 -14560; B288 288 2720 -14560; B288 288 3360 -14560; +B288 288 4000 -14560; B288 288 4640 -14560; B288 288 5280 -14560; +B288 288 5920 -14560; B288 288 160 -15200; B288 288 800 -15200; +B288 288 1440 -15200; B288 288 2080 -15200; B288 288 2720 -15200; +B288 288 3360 -15200; LCBA; B200 92 5588 -14878; B376 92 4884 -14878; +B1436 92 3522 -14878; B728 92 2000 -14878; B112 92 1144 -14878; +B112 48 432 -14904; LCSN; B52 40 5710 -14952; B200 40 5540 -14952; +B40 108 5716 -14878; B40 108 5460 -14878; B296 40 5588 -14804; +B376 40 4932 -14952; B52 40 4674 -14952; DF; DS4 100/4; +LCMF; B368 12 4884 -14830; B16 132 4668 -14878; B448 16 4884 -14804; +B1508 16 3522 -14952; B16 132 4268 -14878; B1432 12 3524 -14926; +B24 16 4264 -14804; B20 76 5430 -14758; B20 76 4790 -14758; +B20 200 4230 -14820; B16 72 4184 -14872; B16 72 4140 -14884; +B16 72 4096 -14872; B16 72 4052 -14884; B16 72 4008 -14872; +B16 72 3964 -14884; B16 72 3920 -14872; B16 72 3872 -14884; +B16 72 3828 -14872; B16 72 3784 -14884; B16 72 3740 -14872; +B16 72 3696 -14884; B16 72 3652 -14872; B16 72 3608 -14884; +B16 72 3564 -14872; B16 72 3520 -14884; B16 72 3476 -14872; +B16 72 3432 -14884; B16 72 3388 -14872; B16 72 3344 -14884; +B16 72 3300 -14872; B16 72 3256 -14884; B16 72 3212 -14872; +B16 72 3168 -14884; B16 72 3124 -14872; B16 72 3080 -14884; +B16 72 3036 -14872; B16 72 2992 -14884; B16 72 2948 -14872; +B16 72 2904 -14884; B16 72 2860 -14872; B16 72 2816 -14884; +B1356 12 3530 -14830; B16 52 4200 -14798; B16 132 2776 -14878; +B1412 16 3474 -14804; B28 16 2386 -14952; B16 132 2392 -14878; +B16 184 2352 -14928; B108 20 2278 -15030; B16 88 2324 -14976; +B20 28 1590 -15026; B380 20 1410 -15002; B16 32 1228 -14976; +B16 76 648 -15002; B700 16 1950 -14952; B648 12 2008 -14926; +B16 72 2308 -14884; B16 72 2264 -14872; B16 72 2220 -14884; +B16 72 2176 -14872; B16 72 2132 -14884; B16 72 2088 -14872; +B16 72 2044 -14884; B16 72 2000 -14872; B16 72 1956 -14884; +B16 72 1912 -14872; B16 72 1868 -14884; B16 72 1824 -14872; +B16 72 1780 -14884; B16 72 1736 -14872; B16 72 1692 -14884; +B16 72 1648 -14872; B720 12 2000 -14830; B16 132 1608 -14878; +B800 16 2000 -14804; B184 16 1144 -14952; B316 16 498 -14956; +B16 132 1228 -14878; B104 12 1144 -14926; B28 16 1222 -14804; +B720 28 3848 -14758; B16 28 2392 -14782; B16 140 1188 -14850; +B16 60 1144 -14878; B16 72 1100 -14884; B32 24 3504 -14732; +B196 20 2482 -14758; B760 20 1560 -14770; B32 16 1152 -14840; +B20 28 2570 -14734; B20 40 1930 -14740; B16 84 1160 -14790; +B16 132 1060 -14878; B16 88 516 -14904; B104 12 432 -14930; +B28 16 510 -14852; B88 16 1096 -14804; B16 120 476 -14864; +B16 28 432 -14898; B16 28 388 -14910; B148 20 1226 -14738; +B188 16 562 -14796; B32 12 440 -14878; B16 68 448 -14838; +B16 88 348 -14904; B88 16 384 -14852; B152 16 380 -14796; +B20 8 1290 -14724; B16 68 648 -14754; B320 320 5920 -14560; +B44 24 5922 -14388; B44 160 5598 -14456; B320 320 5280 -14560; +B320 320 4640 -14560; B400 20 4040 -14710; B44 160 4318 -14456; +B320 300 4000 -14550; B320 320 3360 -14560; B44 160 3038 -14456; +B320 320 2720 -14560; B320 320 2080 -14560; B44 160 1758 -14456; +B320 320 1440 -14560; B320 320 800 -14560; B16 68 312 -14754; +B44 160 478 -14456; B320 320 160 -14560; B32 1008 -40 -14880; +B6192 32 3040 -14360; DF; DS3 100/4; LCOG; B296 296 5280 -14560; +B296 296 5920 -14560; B296 296 160 -15200; B296 296 800 -15200; +B296 296 1440 -15200; B296 296 2080 -15200; B296 296 2720 -15200; +B296 296 3360 -15200; B296 296 4000 -15200; B296 296 4640 -15200; +B296 296 5280 -15200; B296 296 5920 -15200; LCAA; B44 72 478 -14500; +B44 72 1758 -14500; B44 72 3038 -14500; B44 72 4318 -14500; +B44 72 5598 -14500; B192 24 1144 -14804; B192 24 432 -14852; +B24 80 348 -14904; B112 48 432 -14904; B24 80 516 -14904; +B192 24 432 -14956; B24 124 1060 -14878; B112 92 1144 -14878; +B24 124 1228 -14878; B192 24 1144 -14952; B808 24 2000 -14804; +B24 124 1608 -14878; B728 92 2000 -14878; B24 124 2392 -14878; +B808 24 2000 -14952; B1516 24 3522 -14804; B24 124 2776 -14878; +B1436 92 3522 -14878; B24 124 4268 -14878; B1516 24 3522 -14952; +B456 24 4884 -14804; B24 124 4668 -14878; B376 92 4884 -14878; +B24 124 5100 -14878; B456 24 4884 -14952; B280 24 5588 -14804; +B24 124 5460 -14878; B200 92 5588 -14878; B24 124 5716 -14878; +B280 24 5588 -14952; B44 72 1118 -15260; B44 72 2398 -15260; +B44 72 3678 -15260; B44 72 4958 -15260; LCMS; B320 320 160 -14560; +B320 320 800 -14560; B320 320 1440 -14560; B320 320 2080 -14560; +B320 320 2720 -14560; B320 320 3360 -14560; B320 320 4000 -14560; +B320 320 4640 -14560; B320 320 5280 -14560; B320 320 5920 -14560; +B320 320 160 -15200; B320 320 800 -15200; B320 320 1440 -15200; +B320 320 2080 -15200; B320 320 2720 -15200; B320 320 3360 -15200; +B320 320 4000 -15200; B320 320 4640 -15200; B320 320 5280 -15200; +B320 320 5920 -15200; LCWN; B280 172 5588 -14878; B456 172 4884 -14878; +B1516 172 3522 -14878; B808 172 2000 -14878; B192 172 1144 -14878; +B192 128 432 -14904; LCMF; B6192 32 3040 -15400; B32 1008 6120 -14880; +B320 320 5920 -15200; B20 28 5770 -15026; B320 320 5280 -15200; +B44 160 4958 -15304; B320 320 4640 -15200; B320 320 4000 -15200; +B44 160 3678 -15304; B320 320 3360 -15200; B320 320 2720 -15200; +B44 160 2398 -15304; B320 320 2080 -15200; B320 320 1440 -15200; +B44 160 1118 -15304; B44 24 162 -15372; B320 320 800 -15200; +B320 320 160 -15200; B20 28 5430 -15026; B112 16 5724 -15004; +B28 16 5710 -14952; B16 132 5716 -14878; B16 160 5676 -14916; +B236 16 5538 -15004; B16 64 5648 -14964; B176 16 5540 -14952; +B120 12 5596 -14926; B16 72 5632 -14884; B16 72 5588 -14872; +B16 72 5544 -14884; B16 72 5500 -14872; B192 12 5588 -14830; +B16 124 5460 -14882; B352 16 4932 -14952; B48 8 5444 -14816; +B304 16 5572 -14804; B16 132 5100 -14878; B16 108 4736 -14986; +B20 24 4150 -15028; B296 12 4876 -14926; B576 20 4428 -15006; +B16 72 5060 -14872; B16 72 5016 -14884; B16 72 4972 -14872; +B16 72 4928 -14884; B16 72 4884 -14872; B16 72 4840 -14884; +B16 72 4796 -14872; B16 72 4752 -14884; B16 160 4708 -14916; +B32 80 3504 -15000; B232 20 2460 -15030; B28 16 4674 -14952; +DF; C1 ; E diff --git a/scmos/examples/bipolar/pbase-resis.mag b/scmos/examples/bipolar/pbase-resis.mag new file mode 100644 index 00000000..c2c5671e --- /dev/null +++ b/scmos/examples/bipolar/pbase-resis.mag @@ -0,0 +1,146 @@ +magic +tech scmos +timestamp 801255023 +<< nwell >> +rect -4 52 96 140 +rect 0 -2 92 43 +<< metal1 >> +rect 21 124 39 128 +rect 65 124 83 128 +rect 10 110 28 114 +rect 54 110 72 114 +rect -5 75 17 79 +rect 43 75 61 79 +rect 83 65 87 75 +rect -5 61 6 65 +rect 32 61 50 65 +rect 76 61 87 65 +rect 78 34 92 35 +rect 78 30 79 34 +rect 83 30 92 34 +rect 78 29 92 30 +rect 0 11 14 12 +rect 0 7 9 11 +rect 13 7 14 11 +rect 0 6 14 7 +<< pbase >> +rect 14 128 24 131 +rect 14 124 17 128 +rect 21 124 24 128 +rect 14 121 24 124 +rect 36 128 46 131 +rect 36 124 39 128 +rect 43 124 46 128 +rect 36 121 46 124 +rect 58 128 68 131 +rect 58 124 61 128 +rect 65 124 68 128 +rect 58 121 68 124 +rect 80 128 90 131 +rect 80 124 83 128 +rect 87 124 90 128 +rect 80 121 90 124 +rect 3 114 13 117 +rect 3 110 6 114 +rect 10 110 13 114 +rect 3 107 13 110 +rect 6 68 10 107 +rect 17 82 21 121 +rect 25 114 35 117 +rect 25 110 28 114 +rect 32 110 35 114 +rect 25 107 35 110 +rect 14 79 24 82 +rect 14 75 17 79 +rect 21 75 24 79 +rect 14 72 24 75 +rect 28 68 32 107 +rect 39 82 43 121 +rect 47 114 57 117 +rect 47 110 50 114 +rect 54 110 57 114 +rect 47 107 57 110 +rect 36 79 46 82 +rect 36 75 39 79 +rect 43 75 46 79 +rect 36 72 46 75 +rect 50 68 54 107 +rect 61 82 65 121 +rect 69 114 79 117 +rect 69 110 72 114 +rect 76 110 79 114 +rect 69 107 79 110 +rect 58 79 68 82 +rect 58 75 61 79 +rect 65 75 68 79 +rect 58 72 68 75 +rect 72 68 76 107 +rect 83 82 87 121 +rect 80 79 90 82 +rect 80 75 83 79 +rect 87 75 90 79 +rect 80 72 90 75 +rect 3 65 13 68 +rect 3 61 6 65 +rect 10 61 13 65 +rect 3 58 13 61 +rect 25 65 35 68 +rect 25 61 28 65 +rect 32 61 35 65 +rect 25 58 35 61 +rect 47 65 57 68 +rect 47 61 50 65 +rect 54 61 57 65 +rect 47 58 57 61 +rect 69 65 79 68 +rect 69 61 72 65 +rect 76 61 79 65 +rect 69 58 79 61 +rect 9 33 24 37 +rect 9 14 13 33 +rect 6 11 16 14 +rect 6 7 9 11 +rect 13 7 16 11 +rect 6 4 16 7 +rect 20 8 24 33 +rect 28 33 40 37 +rect 28 8 32 33 +rect 20 4 32 8 +rect 36 8 40 33 +rect 44 33 56 37 +rect 44 8 48 33 +rect 36 4 48 8 +rect 52 8 56 33 +rect 60 33 72 37 +rect 60 8 64 33 +rect 52 4 64 8 +rect 68 8 72 33 +rect 76 34 86 37 +rect 76 30 79 34 +rect 83 30 86 34 +rect 76 27 86 30 +rect 79 8 83 27 +rect 68 4 83 8 +<< pbasecontact >> +rect 17 124 21 128 +rect 39 124 43 128 +rect 61 124 65 128 +rect 83 124 87 128 +rect 6 110 10 114 +rect 28 110 32 114 +rect 17 75 21 79 +rect 50 110 54 114 +rect 39 75 43 79 +rect 72 110 76 114 +rect 61 75 65 79 +rect 83 75 87 79 +rect 6 61 10 65 +rect 28 61 32 65 +rect 50 61 54 65 +rect 72 61 76 65 +rect 9 7 13 11 +rect 79 30 83 34 +<< labels >> +rlabel metal1 2 9 2 9 3 a +rlabel metal1 90 32 90 32 7 b +<< end >> diff --git a/scmos/examples/bipolar/vertical-pnp.mag b/scmos/examples/bipolar/vertical-pnp.mag new file mode 100644 index 00000000..e9846e82 --- /dev/null +++ b/scmos/examples/bipolar/vertical-pnp.mag @@ -0,0 +1,24 @@ +magic +tech scmos +timestamp 801256319 +<< nwell >> +rect 0 -1 20 13 +<< metal1 >> +rect -1 4 5 8 +rect 17 4 21 8 +<< pdcontact >> +rect 5 4 9 8 +<< psubstratepcontact >> +rect -7 16 27 20 +rect -7 -8 27 -4 +<< nsubstratencontact >> +rect 13 4 17 8 +<< psubstratepdiff >> +rect -7 -4 -3 16 +rect 23 -4 27 16 +<< labels >> +rlabel metal1 21 6 21 6 3 base +rlabel metal1 -1 6 -1 6 7 emitter +rlabel psubstratepcontact 10 18 10 18 1 collector +rlabel psubstratepcontact 10 -6 10 -6 5 collector +<< end >> diff --git a/scmos/examples/ccd/ccd.mag b/scmos/examples/ccd/ccd.mag new file mode 100644 index 00000000..45e638eb --- /dev/null +++ b/scmos/examples/ccd/ccd.mag @@ -0,0 +1,70 @@ +magic +tech scmos +timestamp 783829926 +<< error_p >> +rect 0 -12 41 -10 +rect -2 -16 0 -12 +rect 41 -16 43 -12 +rect 0 -18 41 -16 +<< polysilicon >> +rect 12 6 15 14 +rect 21 6 24 14 +rect 30 6 35 14 +rect 10 4 17 6 +rect 10 0 11 4 +rect 15 0 17 4 +rect 19 4 26 6 +rect 19 0 20 4 +rect 24 0 26 4 +rect 28 4 35 6 +rect 28 0 29 4 +rect 33 0 35 4 +<< electrode >> +rect 6 20 12 21 +rect 6 16 7 20 +rect 11 16 12 20 +rect 6 14 12 16 +rect 15 20 21 21 +rect 15 16 16 20 +rect 20 16 21 20 +rect 15 14 21 16 +rect 24 20 30 21 +rect 24 16 25 20 +rect 29 16 30 20 +rect 24 14 30 16 +rect 6 6 10 14 +rect 17 6 19 14 +rect 26 6 28 14 +<< capacitor >> +rect 10 6 12 14 +rect 15 6 17 14 +rect 19 6 21 14 +rect 24 6 26 14 +rect 28 6 30 14 +<< bccdiffusion >> +rect 6 8 35 12 +rect 0 -16 41 -12 +<< nbccdiffusion >> +rect 4 8 6 12 +rect 35 8 37 12 +rect 4 -8 6 -4 +rect 35 -8 37 -4 +<< polycontact >> +rect 11 0 15 4 +rect 20 0 24 4 +rect 29 0 33 4 +<< electrodecontact >> +rect 7 16 11 20 +rect 16 16 20 20 +rect 25 16 29 20 +<< nbccdiffcontact >> +rect 0 8 4 12 +rect 37 8 41 12 +rect 0 -8 4 -4 +rect 37 -8 41 -4 +<< labels >> +rlabel space -5 -7 -5 -7 3 layer +rlabel space -5 -5 -5 -5 3 active +rlabel space -5 -13 -5 -13 3 well +rlabel space -5 -15 -5 -15 3 layer +<< end >> diff --git a/scmos/examples/ccd/ccd_array.mag b/scmos/examples/ccd/ccd_array.mag new file mode 100644 index 00000000..92428767 --- /dev/null +++ b/scmos/examples/ccd/ccd_array.mag @@ -0,0 +1,673 @@ +magic +tech scmos +timestamp 813531883 +<< polysilicon >> +rect -51 5 -48 15 +rect -40 13 -34 15 +rect -32 13 -25 15 +rect -23 13 -16 15 +rect -14 13 -7 15 +rect -5 13 2 15 +rect 4 13 11 15 +rect 13 13 20 15 +rect 22 13 29 15 +rect 31 13 38 15 +rect 40 13 47 15 +rect 49 13 56 15 +rect 58 13 65 15 +rect 67 13 74 15 +rect 76 13 83 15 +rect 85 13 92 15 +rect 94 13 101 15 +rect 103 13 110 15 +rect 112 13 119 15 +rect 121 13 128 15 +rect 130 13 137 15 +rect 139 13 146 15 +rect 148 13 155 15 +rect 157 13 164 15 +rect 166 13 173 15 +rect 175 13 182 15 +rect 184 13 191 15 +rect 193 13 200 15 +rect 202 13 209 15 +rect 211 13 218 15 +rect 220 13 227 15 +rect -40 5 -36 13 +rect -30 5 -27 13 +rect -21 5 -18 13 +rect -12 5 -9 13 +rect -3 5 0 13 +rect 6 5 9 13 +rect 15 5 18 13 +rect 24 5 27 13 +rect 33 5 36 13 +rect 42 5 45 13 +rect 51 5 54 13 +rect 60 5 63 13 +rect 69 5 72 13 +rect 78 5 81 13 +rect 87 5 90 13 +rect 96 5 99 13 +rect 105 5 108 13 +rect 114 5 117 13 +rect 123 5 126 13 +rect 132 5 135 13 +rect 141 5 144 13 +rect 150 5 153 13 +rect 159 5 162 13 +rect 168 5 171 13 +rect 177 5 180 13 +rect 186 5 189 13 +rect 195 5 198 13 +rect 204 5 207 13 +rect 213 5 216 13 +rect 222 5 225 13 +rect 239 5 242 15 +<< electrode >> +rect -34 5 -32 13 +rect -25 5 -23 13 +rect -16 5 -14 13 +rect -7 5 -5 13 +rect 2 5 4 13 +rect 11 5 13 13 +rect 20 5 22 13 +rect 29 5 31 13 +rect 38 5 40 13 +rect 47 5 49 13 +rect 56 5 58 13 +rect 65 5 67 13 +rect 74 5 76 13 +rect 83 5 85 13 +rect 92 5 94 13 +rect 101 5 103 13 +rect 110 5 112 13 +rect 119 5 121 13 +rect 128 5 130 13 +rect 137 5 139 13 +rect 146 5 148 13 +rect 155 5 157 13 +rect 164 5 166 13 +rect 173 5 175 13 +rect 182 5 184 13 +rect 191 5 193 13 +rect 200 5 202 13 +rect 209 5 211 13 +rect 218 5 220 13 +rect 227 5 231 13 +rect -36 3 -30 5 +rect -36 -1 -35 3 +rect -31 -1 -30 3 +rect -36 -2 -30 -1 +rect -27 3 -21 5 +rect -27 -1 -26 3 +rect -22 -1 -21 3 +rect -27 -2 -21 -1 +rect -18 3 -12 5 +rect -18 -1 -17 3 +rect -13 -1 -12 3 +rect -18 -2 -12 -1 +rect -9 3 -3 5 +rect -9 -1 -8 3 +rect -4 -1 -3 3 +rect -9 -2 -3 -1 +rect 0 3 6 5 +rect 0 -1 1 3 +rect 5 -1 6 3 +rect 0 -2 6 -1 +rect 9 3 15 5 +rect 9 -1 10 3 +rect 14 -1 15 3 +rect 9 -2 15 -1 +rect 18 3 24 5 +rect 18 -1 19 3 +rect 23 -1 24 3 +rect 18 -2 24 -1 +rect 27 3 33 5 +rect 27 -1 28 3 +rect 32 -1 33 3 +rect 27 -2 33 -1 +rect 36 3 42 5 +rect 36 -1 37 3 +rect 41 -1 42 3 +rect 36 -2 42 -1 +rect 45 3 51 5 +rect 45 -1 46 3 +rect 50 -1 51 3 +rect 45 -2 51 -1 +rect 54 3 60 5 +rect 54 -1 55 3 +rect 59 -1 60 3 +rect 54 -2 60 -1 +rect 63 3 69 5 +rect 63 -1 64 3 +rect 68 -1 69 3 +rect 63 -2 69 -1 +rect 72 3 78 5 +rect 72 -1 73 3 +rect 77 -1 78 3 +rect 72 -2 78 -1 +rect 81 3 87 5 +rect 81 -1 82 3 +rect 86 -1 87 3 +rect 81 -2 87 -1 +rect 90 3 96 5 +rect 90 -1 91 3 +rect 95 -1 96 3 +rect 90 -2 96 -1 +rect 99 3 105 5 +rect 99 -1 100 3 +rect 104 -1 105 3 +rect 99 -2 105 -1 +rect 108 3 114 5 +rect 108 -1 109 3 +rect 113 -1 114 3 +rect 108 -2 114 -1 +rect 117 3 123 5 +rect 117 -1 118 3 +rect 122 -1 123 3 +rect 117 -2 123 -1 +rect 126 3 132 5 +rect 126 -1 127 3 +rect 131 -1 132 3 +rect 126 -2 132 -1 +rect 135 3 141 5 +rect 135 -1 136 3 +rect 140 -1 141 3 +rect 135 -2 141 -1 +rect 144 3 150 5 +rect 144 -1 145 3 +rect 149 -1 150 3 +rect 144 -2 150 -1 +rect 153 3 159 5 +rect 153 -1 154 3 +rect 158 -1 159 3 +rect 153 -2 159 -1 +rect 162 3 168 5 +rect 162 -1 163 3 +rect 167 -1 168 3 +rect 162 -2 168 -1 +rect 171 3 177 5 +rect 171 -1 172 3 +rect 176 -1 177 3 +rect 171 -2 177 -1 +rect 180 3 186 5 +rect 180 -1 181 3 +rect 185 -1 186 3 +rect 180 -2 186 -1 +rect 189 3 195 5 +rect 189 -1 190 3 +rect 194 -1 195 3 +rect 189 -2 195 -1 +rect 198 3 204 5 +rect 198 -1 199 3 +rect 203 -1 204 3 +rect 198 -2 204 -1 +rect 207 3 213 5 +rect 207 -1 208 3 +rect 212 -1 213 3 +rect 207 -2 213 -1 +rect 216 3 222 5 +rect 216 -1 217 3 +rect 221 -1 222 3 +rect 216 -2 222 -1 +rect 225 3 231 5 +rect 225 -1 226 3 +rect 230 -1 231 3 +rect 225 -2 231 -1 +<< capacitor >> +rect -36 5 -34 13 +rect -32 5 -30 13 +rect -27 5 -25 13 +rect -23 5 -21 13 +rect -18 5 -16 13 +rect -14 5 -12 13 +rect -9 5 -7 13 +rect -5 5 -3 13 +rect 0 5 2 13 +rect 4 5 6 13 +rect 9 5 11 13 +rect 13 5 15 13 +rect 18 5 20 13 +rect 22 5 24 13 +rect 27 5 29 13 +rect 31 5 33 13 +rect 36 5 38 13 +rect 40 5 42 13 +rect 45 5 47 13 +rect 49 5 51 13 +rect 54 5 56 13 +rect 58 5 60 13 +rect 63 5 65 13 +rect 67 5 69 13 +rect 72 5 74 13 +rect 76 5 78 13 +rect 81 5 83 13 +rect 85 5 87 13 +rect 90 5 92 13 +rect 94 5 96 13 +rect 99 5 101 13 +rect 103 5 105 13 +rect 108 5 110 13 +rect 112 5 114 13 +rect 117 5 119 13 +rect 121 5 123 13 +rect 126 5 128 13 +rect 130 5 132 13 +rect 135 5 137 13 +rect 139 5 141 13 +rect 144 5 146 13 +rect 148 5 150 13 +rect 153 5 155 13 +rect 157 5 159 13 +rect 162 5 164 13 +rect 166 5 168 13 +rect 171 5 173 13 +rect 175 5 177 13 +rect 180 5 182 13 +rect 184 5 186 13 +rect 189 5 191 13 +rect 193 5 195 13 +rect 198 5 200 13 +rect 202 5 204 13 +rect 207 5 209 13 +rect 211 5 213 13 +rect 216 5 218 13 +rect 220 5 222 13 +rect 225 5 227 13 +<< metal1 >> +rect -84 -19 -81 21 +rect -77 -11 -74 29 +rect -70 -3 -67 37 +rect -56 19 -53 42 +rect -40 19 -37 37 +rect -31 19 -28 22 +rect -22 19 -19 29 +rect -13 19 -10 37 +rect -4 19 -1 22 +rect 5 19 8 29 +rect 14 19 17 37 +rect 23 19 26 22 +rect 32 19 35 29 +rect 41 19 44 37 +rect 50 19 53 22 +rect 59 19 62 29 +rect 68 19 71 37 +rect 77 19 80 22 +rect 86 19 89 29 +rect 95 19 98 37 +rect 104 19 107 22 +rect 113 19 116 29 +rect 122 19 125 37 +rect 131 19 134 22 +rect 140 19 143 29 +rect 149 19 152 37 +rect 158 19 161 22 +rect 167 19 170 29 +rect 176 19 179 37 +rect 185 19 188 22 +rect 194 19 197 29 +rect 203 19 206 37 +rect 212 19 215 22 +rect 221 19 224 29 +rect 228 19 231 37 +rect 244 19 247 42 +rect -56 16 -52 19 +rect 243 16 247 19 +rect -60 7 -57 11 +rect -60 5 -53 7 +rect -60 1 -57 5 +rect -60 -7 -53 1 +rect -84 -22 -82 -19 +rect -64 -23 -53 -7 +rect -46 -23 -43 7 +rect -35 -11 -32 -1 +rect -26 -4 -23 -1 +rect -17 -19 -14 -1 +rect -8 -11 -5 -1 +rect 1 -4 4 -1 +rect 10 -19 13 -1 +rect 19 -11 22 -1 +rect 28 -4 31 -1 +rect 37 -19 40 -1 +rect 46 -11 49 -1 +rect 55 -4 58 -1 +rect 64 -19 67 -1 +rect 73 -11 76 -1 +rect 82 -4 85 -1 +rect 91 -19 94 -1 +rect 100 -11 103 -1 +rect 109 -4 112 -1 +rect 118 -19 121 -1 +rect 127 -11 130 -1 +rect 136 -4 139 -1 +rect 145 -19 148 -1 +rect 154 -11 157 -1 +rect 163 -4 166 -1 +rect 172 -19 175 -1 +rect 181 -11 184 -1 +rect 190 -4 193 -1 +rect 199 -19 202 -1 +rect 208 -11 211 -1 +rect 217 -4 220 -1 +rect 226 -19 229 -1 +rect 234 -23 237 7 +rect 248 7 251 11 +rect 244 5 251 7 +rect 248 1 251 5 +rect 244 -7 251 1 +rect 258 -3 261 37 +rect 244 -23 255 -7 +rect 265 -11 268 29 +rect 272 -19 275 21 +<< metal2 >> +rect -66 37 -40 40 +rect -36 37 -13 40 +rect -9 37 14 40 +rect 18 37 41 40 +rect 45 37 68 40 +rect 72 37 95 40 +rect 99 37 122 40 +rect 126 37 149 40 +rect 153 37 176 40 +rect 180 37 203 40 +rect 207 37 227 40 +rect 231 37 257 40 +rect -73 30 -22 33 +rect -18 30 5 33 +rect 9 30 32 33 +rect 36 30 59 33 +rect 63 30 86 33 +rect 90 30 113 33 +rect 117 30 140 33 +rect 144 30 167 33 +rect 171 30 194 33 +rect 198 30 221 33 +rect 225 30 264 33 +rect -80 22 -31 25 +rect -27 22 -4 25 +rect 0 22 23 25 +rect 27 22 50 25 +rect 54 22 77 25 +rect 81 22 104 25 +rect 108 22 131 25 +rect 135 22 158 25 +rect 162 22 185 25 +rect 189 22 212 25 +rect 216 22 271 25 +rect -64 5 255 18 +rect -64 1 -57 5 +rect -53 1 244 5 +rect 248 1 255 5 +rect -67 -7 -26 -4 +rect -22 -7 1 -4 +rect 5 -7 28 -4 +rect 32 -7 55 -4 +rect 59 -7 82 -4 +rect 86 -7 109 -4 +rect 113 -7 136 -4 +rect 140 -7 163 -4 +rect 167 -7 190 -4 +rect 194 -7 217 -4 +rect 221 -7 258 -4 +rect -74 -15 -35 -12 +rect -31 -15 -8 -12 +rect -4 -15 19 -12 +rect 23 -15 46 -12 +rect 50 -15 73 -12 +rect 77 -15 100 -12 +rect 104 -15 127 -12 +rect 131 -15 154 -12 +rect 158 -15 181 -12 +rect 185 -15 208 -12 +rect 212 -15 265 -12 +rect -78 -22 -17 -19 +rect -13 -22 10 -19 +rect 14 -22 37 -19 +rect 41 -22 64 -19 +rect 68 -22 91 -19 +rect 95 -22 118 -19 +rect 122 -22 145 -19 +rect 149 -22 172 -19 +rect 176 -22 199 -19 +rect 203 -22 226 -19 +rect 230 -22 271 -19 +<< bccdiffusion >> +rect -51 7 -48 11 +rect -40 7 231 11 +rect 239 7 242 11 +<< nbccdiffusion >> +rect -53 7 -51 11 +rect -48 7 -46 11 +rect -42 7 -40 11 +rect 231 7 233 11 +rect 237 7 239 11 +rect 242 7 244 11 +<< polycontact >> +rect -52 15 -48 19 +rect -40 15 -36 19 +rect -31 15 -27 19 +rect -22 15 -18 19 +rect -13 15 -9 19 +rect -4 15 0 19 +rect 5 15 9 19 +rect 14 15 18 19 +rect 23 15 27 19 +rect 32 15 36 19 +rect 41 15 45 19 +rect 50 15 54 19 +rect 59 15 63 19 +rect 68 15 72 19 +rect 77 15 81 19 +rect 86 15 90 19 +rect 95 15 99 19 +rect 104 15 108 19 +rect 113 15 117 19 +rect 122 15 126 19 +rect 131 15 135 19 +rect 140 15 144 19 +rect 149 15 153 19 +rect 158 15 162 19 +rect 167 15 171 19 +rect 176 15 180 19 +rect 185 15 189 19 +rect 194 15 198 19 +rect 203 15 207 19 +rect 212 15 216 19 +rect 221 15 225 19 +rect 239 15 243 19 +<< electrodecontact >> +rect -35 -1 -31 3 +rect -26 -1 -22 3 +rect -17 -1 -13 3 +rect -8 -1 -4 3 +rect 1 -1 5 3 +rect 10 -1 14 3 +rect 19 -1 23 3 +rect 28 -1 32 3 +rect 37 -1 41 3 +rect 46 -1 50 3 +rect 55 -1 59 3 +rect 64 -1 68 3 +rect 73 -1 77 3 +rect 82 -1 86 3 +rect 91 -1 95 3 +rect 100 -1 104 3 +rect 109 -1 113 3 +rect 118 -1 122 3 +rect 127 -1 131 3 +rect 136 -1 140 3 +rect 145 -1 149 3 +rect 154 -1 158 3 +rect 163 -1 167 3 +rect 172 -1 176 3 +rect 181 -1 185 3 +rect 190 -1 194 3 +rect 199 -1 203 3 +rect 208 -1 212 3 +rect 217 -1 221 3 +rect 226 -1 230 3 +<< nbccdiffcontact >> +rect -57 7 -53 11 +rect -46 7 -42 11 +rect 233 7 237 11 +rect 244 7 248 11 +<< m2contact >> +rect -70 37 -66 41 +rect -77 29 -73 33 +rect -84 21 -80 25 +rect -40 37 -36 41 +rect -13 37 -9 41 +rect 14 37 18 41 +rect 41 37 45 41 +rect 68 37 72 41 +rect 95 37 99 41 +rect 122 37 126 41 +rect 149 37 153 41 +rect 176 37 180 41 +rect 203 37 207 41 +rect 227 37 231 41 +rect -22 29 -18 33 +rect -31 22 -27 26 +rect 5 29 9 33 +rect -4 22 0 26 +rect 32 29 36 33 +rect 23 22 27 26 +rect 59 29 63 33 +rect 50 22 54 26 +rect 86 29 90 33 +rect 77 22 81 26 +rect 113 29 117 33 +rect 104 22 108 26 +rect 140 29 144 33 +rect 131 22 135 26 +rect 167 29 171 33 +rect 158 22 162 26 +rect 194 29 198 33 +rect 185 22 189 26 +rect 221 29 225 33 +rect 212 22 216 26 +rect 257 37 261 41 +rect -71 -7 -67 -3 +rect -57 1 -53 5 +rect -78 -15 -74 -11 +rect -82 -23 -78 -19 +rect -26 -8 -22 -4 +rect -35 -15 -31 -11 +rect 1 -8 5 -4 +rect -8 -15 -4 -11 +rect 28 -8 32 -4 +rect 19 -15 23 -11 +rect 55 -8 59 -4 +rect 46 -15 50 -11 +rect 82 -8 86 -4 +rect 73 -15 77 -11 +rect 109 -8 113 -4 +rect 100 -15 104 -11 +rect 136 -8 140 -4 +rect 127 -15 131 -11 +rect 163 -8 167 -4 +rect 154 -15 158 -11 +rect 190 -8 194 -4 +rect 181 -15 185 -11 +rect 217 -8 221 -4 +rect 208 -15 212 -11 +rect -17 -23 -13 -19 +rect 10 -23 14 -19 +rect 37 -23 41 -19 +rect 64 -23 68 -19 +rect 91 -23 95 -19 +rect 118 -23 122 -19 +rect 145 -23 149 -19 +rect 172 -23 176 -19 +rect 199 -23 203 -19 +rect 226 -23 230 -19 +rect 244 1 248 5 +rect 264 29 268 33 +rect 258 -7 262 -3 +rect 271 21 275 25 +rect 265 -15 269 -11 +rect 271 -23 275 -19 +<< psubstratepcontact >> +rect -64 -7 -60 11 +rect 251 -7 255 11 +<< psubstratepdiff >> +rect -64 21 255 27 +rect -64 11 -60 21 +rect 251 11 255 21 +rect -60 -7 251 -3 +rect -64 -9 255 -7 +<< labels >> +rlabel metal2 -35 30 -32 33 0 c2 +rlabel metal2 -8 30 -5 33 0 c2 +rlabel metal2 19 30 22 33 0 c2 +rlabel metal2 46 30 49 33 0 c2 +rlabel metal2 73 30 76 33 0 c2 +rlabel metal2 100 30 103 33 0 c2 +rlabel metal2 127 30 130 33 0 c2 +rlabel metal2 154 30 157 33 0 c2 +rlabel metal2 181 30 184 33 0 c2 +rlabel metal2 208 30 211 33 0 c2 +rlabel metal2 -35 37 -32 40 0 c1 +rlabel metal2 -8 37 -5 40 0 c1 +rlabel metal2 19 37 22 40 0 c1 +rlabel metal2 46 37 49 40 0 c1 +rlabel metal2 73 37 76 40 0 c1 +rlabel metal2 100 37 103 40 0 c1 +rlabel metal2 127 37 130 40 0 c1 +rlabel metal2 154 37 157 40 0 c1 +rlabel metal2 181 37 184 40 0 c1 +rlabel metal2 208 37 211 40 0 c1 +rlabel metal2 -35 22 -32 25 0 c3 +rlabel metal2 -8 22 -5 25 0 c3 +rlabel metal2 19 22 22 25 0 c3 +rlabel metal2 46 22 49 25 0 c3 +rlabel metal2 73 22 76 25 0 c3 +rlabel metal2 100 22 103 25 0 c3 +rlabel metal2 127 22 130 25 0 c3 +rlabel metal2 154 22 157 25 0 c3 +rlabel metal2 181 22 184 25 0 c3 +rlabel metal2 208 22 211 25 0 c3 +rlabel metal2 -39 -7 -36 -4 0 c1 +rlabel metal2 -12 -7 -9 -4 0 c1 +rlabel metal2 15 -7 18 -4 0 c1 +rlabel metal2 42 -7 45 -4 0 c1 +rlabel metal2 69 -7 72 -4 0 c1 +rlabel metal2 96 -7 99 -4 0 c1 +rlabel metal2 123 -7 126 -4 0 c1 +rlabel metal2 150 -7 153 -4 0 c1 +rlabel metal2 177 -7 180 -4 0 c1 +rlabel metal2 204 -7 207 -4 0 c1 +rlabel metal2 -39 -15 -36 -12 0 c2 +rlabel metal2 -12 -15 -9 -12 0 c2 +rlabel metal2 15 -15 18 -12 0 c2 +rlabel metal2 42 -15 45 -12 0 c2 +rlabel metal2 69 -15 72 -12 0 c2 +rlabel metal2 96 -15 99 -12 0 c2 +rlabel metal2 123 -15 126 -12 0 c2 +rlabel metal2 150 -15 153 -12 0 c2 +rlabel metal2 177 -15 180 -12 0 c2 +rlabel metal2 204 -15 207 -12 0 c2 +rlabel metal2 -39 -22 -36 -19 0 c3 +rlabel metal2 -12 -22 -9 -19 0 c3 +rlabel metal2 15 -22 18 -19 0 c3 +rlabel metal2 42 -22 45 -19 0 c3 +rlabel metal2 69 -22 72 -19 0 c3 +rlabel metal2 96 -22 99 -19 0 c3 +rlabel metal2 123 -22 126 -19 0 c3 +rlabel metal2 150 -22 153 -19 0 c3 +rlabel metal2 177 -22 180 -19 0 c3 +rlabel metal2 204 -22 207 -19 0 c3 +rlabel metal2 222 -22 225 -19 0 c3 +rlabel metal2 222 -15 225 -12 0 c2 +rlabel metal2 222 -7 225 -4 0 c1 +rlabel metal2 235 37 238 40 0 c1 +rlabel metal2 235 22 238 25 0 c3 +rlabel metal2 235 30 238 33 0 c2 +rlabel polycontact 239 15 243 19 0 reset +rlabel nbccdiffcontact 244 7 248 11 0 GND +rlabel nbccdiffcontact -46 7 -42 11 0 input +rlabel polycontact -52 15 -48 19 0 reset +rlabel nbccdiffcontact -57 7 -53 11 0 GND +rlabel nbccdiffcontact 233 7 237 11 0 output +<< end >> diff --git a/scmos/examples/ccd/qq.cif b/scmos/examples/ccd/qq.cif new file mode 100644 index 00000000..0e4380ae --- /dev/null +++ b/scmos/examples/ccd/qq.cif @@ -0,0 +1,659 @@ +( @@user : pi ); +( @@machine : dirac.isi.edu ); +( @@source : ccd_array.mag ); +( @@tool : Magic 6.4.4 ); +( @@patch : 1 ); +( @@patchnames : release-6.4, linux1 ); +( @@compiled : Fri Jan 13 16:46:31 PST 1995 ); +( @@technology : scmos ); +( @@version : 8.2.7 ); +( @@techdesc : MOSIS Scalable CMOS Technology for Standard Rules ); +( @@style : lambda=1.0(gen) ); +( @@date : Wed Dec 13 10:30:30 1995 ); +DS 1 50 2; +9 ccd_array; +L CWP; + B 1300 48 382 96; + B 40 72 -248 36; + B 40 72 1012 36; + B 1300 48 382 -24; +L CMS; + B 16 4 -272 162; + B 16 4 -152 162; + B 16 4 -44 162; + B 16 4 64 162; + B 16 4 172 162; + B 16 4 280 162; + B 16 4 388 162; + B 16 4 496 162; + B 16 4 604 162; + B 16 4 712 162; + B 16 4 820 162; + B 16 4 916 162; + B 16 4 1036 162; + B 1324 12 382 154; + B 1380 12 382 126; + B 16 4 -300 118; + B 16 4 -80 118; + B 16 4 28 118; + B 16 4 136 118; + B 16 4 244 118; + B 16 4 352 118; + B 16 4 460 118; + B 16 4 568 118; + B 16 4 676 118; + B 16 4 784 118; + B 16 4 892 118; + B 16 4 1064 118; + B 16 4 -116 102; + B 16 4 -8 102; + B 16 4 100 102; + B 16 4 208 102; + B 16 4 316 102; + B 16 4 424 102; + B 16 4 532 102; + B 16 4 640 102; + B 16 4 748 102; + B 16 4 856 102; + B 1436 12 382 94; + B 16 4 -328 86; + B 16 4 1092 86; + B 1276 68 382 38; + B 16 4 -276 -14; + B 16 4 1040 -14; + B 1332 12 382 -22; + B 16 4 -96 -30; + B 16 4 12 -30; + B 16 4 120 -30; + B 16 4 228 -30; + B 16 4 336 -30; + B 16 4 444 -30; + B 16 4 552 -30; + B 16 4 660 -30; + B 16 4 768 -30; + B 16 4 876 -30; + B 16 4 -304 -46; + B 16 4 -132 -46; + B 16 4 -24 -46; + B 16 4 84 -46; + B 16 4 192 -46; + B 16 4 300 -46; + B 16 4 408 -46; + B 16 4 516 -46; + B 16 4 624 -46; + B 16 4 732 -46; + B 16 4 840 -46; + B 16 4 1068 -46; + B 1388 12 382 -54; + B 1428 12 386 -82; + B 16 4 -320 -90; + B 16 4 -60 -90; + B 16 4 48 -90; + B 16 4 156 -90; + B 16 4 264 -90; + B 16 4 372 -90; + B 16 4 480 -90; + B 16 4 588 -90; + B 16 4 696 -90; + B 16 4 804 -90; + B 16 4 912 -90; + B 16 4 1092 -90; +L CMF; + B 16 16 -272 156; + B 16 16 -300 124; + B 16 16 -328 92; + B 12 160 -330 4; + B 12 160 -302 36; + B 12 160 -274 68; + B 12 92 -218 122; + B 16 16 -152 156; + B 16 16 -44 156; + B 16 16 64 156; + B 16 16 172 156; + B 16 16 280 156; + B 16 16 388 156; + B 16 16 496 156; + B 16 16 604 156; + B 16 16 712 156; + B 16 16 820 156; + B 16 16 916 156; + B 12 72 -154 112; + B 16 16 -80 124; + B 16 16 -116 96; + B 12 12 -118 82; + B 12 40 -82 96; + B 12 72 -46 112; + B 16 16 28 124; + B 16 16 -8 96; + B 12 12 -10 82; + B 12 40 26 96; + B 12 72 62 112; + B 16 16 136 124; + B 16 16 100 96; + B 12 12 98 82; + B 12 40 134 96; + B 12 72 170 112; + B 16 16 244 124; + B 16 16 208 96; + B 12 12 206 82; + B 12 40 242 96; + B 12 72 278 112; + B 16 16 352 124; + B 16 16 316 96; + B 12 12 314 82; + B 12 40 350 96; + B 12 72 386 112; + B 16 16 460 124; + B 16 16 424 96; + B 12 12 422 82; + B 12 40 458 96; + B 12 72 494 112; + B 16 16 568 124; + B 16 16 532 96; + B 12 12 530 82; + B 12 40 566 96; + B 12 72 602 112; + B 16 16 676 124; + B 16 16 640 96; + B 12 12 638 82; + B 12 40 674 96; + B 12 72 710 112; + B 16 16 784 124; + B 16 16 748 96; + B 12 12 746 82; + B 12 40 782 96; + B 12 72 818 112; + B 16 16 892 124; + B 16 16 856 96; + B 12 12 854 82; + B 12 40 890 96; + B 12 72 918 112; + B 12 92 982 122; + B 16 16 1036 156; + B 32 12 -208 70; + B 16 4 -200 62; + B 16 16 -152 68; + B 16 16 -116 68; + B 16 16 -80 68; + B 16 16 -44 68; + B 16 16 -8 68; + B 16 16 28 68; + B 16 16 64 68; + B 16 16 100 68; + B 16 16 136 68; + B 16 16 172 68; + B 16 16 208 68; + B 16 16 244 68; + B 16 16 280 68; + B 16 16 316 68; + B 16 16 352 68; + B 16 16 388 68; + B 16 16 424 68; + B 16 16 460 68; + B 16 16 496 68; + B 16 16 532 68; + B 16 16 568 68; + B 16 16 604 68; + B 16 16 640 68; + B 16 16 676 68; + B 16 16 712 68; + B 16 16 748 68; + B 16 16 784 68; + B 16 16 820 68; + B 16 16 856 68; + B 16 16 892 68; + B 32 12 972 70; + B 16 4 964 62; + B 16 16 -276 -20; + B 16 16 -304 -52; + B 24 12 -324 -82; + B 16 4 -320 -90; + B 44 136 -234 -24; + B 16 16 -176 36; + B 16 16 940 36; + B 12 120 -178 -32; + B 16 16 -132 4; + B 16 16 -96 4; + B 16 16 -60 4; + B 16 16 -24 4; + B 16 16 12 4; + B 16 16 48 4; + B 16 16 84 4; + B 16 16 120 4; + B 16 16 156 4; + B 16 16 192 4; + B 16 16 228 4; + B 16 16 264 4; + B 16 16 300 4; + B 16 16 336 4; + B 16 16 372 4; + B 16 16 408 4; + B 16 16 444 4; + B 16 16 480 4; + B 16 16 516 4; + B 16 16 552 4; + B 16 16 588 4; + B 16 16 624 4; + B 16 16 660 4; + B 16 16 696 4; + B 16 16 732 4; + B 16 16 768 4; + B 16 16 804 4; + B 16 16 840 4; + B 16 16 876 4; + B 16 16 912 4; + B 12 40 -134 -24; + B 12 12 -98 -10; + B 16 16 -96 -24; + B 16 16 -132 -52; + B 12 72 -62 -40; + B 12 40 -26 -24; + B 12 12 10 -10; + B 16 16 12 -24; + B 16 16 -24 -52; + B 12 72 46 -40; + B 12 40 82 -24; + B 12 12 118 -10; + B 16 16 120 -24; + B 16 16 84 -52; + B 12 72 154 -40; + B 12 40 190 -24; + B 12 12 226 -10; + B 16 16 228 -24; + B 16 16 192 -52; + B 12 72 262 -40; + B 12 40 298 -24; + B 12 12 334 -10; + B 16 16 336 -24; + B 16 16 300 -52; + B 12 72 370 -40; + B 12 40 406 -24; + B 12 12 442 -10; + B 16 16 444 -24; + B 16 16 408 -52; + B 12 72 478 -40; + B 12 40 514 -24; + B 12 12 550 -10; + B 16 16 552 -24; + B 16 16 516 -52; + B 12 72 586 -40; + B 12 40 622 -24; + B 12 12 658 -10; + B 16 16 660 -24; + B 16 16 624 -52; + B 12 72 694 -40; + B 12 40 730 -24; + B 12 12 766 -10; + B 16 16 768 -24; + B 16 16 732 -52; + B 12 72 802 -40; + B 12 40 838 -24; + B 12 12 874 -10; + B 16 16 876 -24; + B 16 16 840 -52; + B 12 72 910 -40; + B 16 16 -60 -84; + B 16 16 48 -84; + B 16 16 156 -84; + B 16 16 264 -84; + B 16 16 372 -84; + B 16 16 480 -84; + B 16 16 588 -84; + B 16 16 696 -84; + B 16 16 804 -84; + B 16 16 912 -84; + B 12 120 942 -32; + B 44 136 998 -24; + B 12 160 1038 68; + B 16 16 1064 124; + B 16 16 1040 -20; + B 12 160 1066 36; + B 16 16 1092 92; + B 16 16 1068 -52; + B 12 160 1094 4; + B 16 16 1092 -84; +L CPG; + B 16 16 -200 68; + B 12 40 -198 40; + B 16 16 -152 68; + B 16 16 -116 68; + B 16 16 -80 68; + B 16 16 -44 68; + B 16 16 -8 68; + B 16 16 28 68; + B 16 16 64 68; + B 16 16 100 68; + B 16 16 136 68; + B 16 16 172 68; + B 16 16 208 68; + B 16 16 244 68; + B 16 16 280 68; + B 16 16 316 68; + B 16 16 352 68; + B 16 16 388 68; + B 16 16 424 68; + B 16 16 460 68; + B 16 16 496 68; + B 16 16 532 68; + B 16 16 568 68; + B 16 16 604 68; + B 16 16 640 68; + B 16 16 676 68; + B 16 16 712 68; + B 16 16 748 68; + B 16 16 784 68; + B 16 16 820 68; + B 16 16 856 68; + B 16 16 892 68; + B 16 16 964 68; + B 24 40 -148 40; + B 28 40 -114 40; + B 28 40 -78 40; + B 28 40 -42 40; + B 28 40 -6 40; + B 28 40 30 40; + B 28 40 66 40; + B 28 40 102 40; + B 28 40 138 40; + B 28 40 174 40; + B 28 40 210 40; + B 28 40 246 40; + B 28 40 282 40; + B 28 40 318 40; + B 28 40 354 40; + B 28 40 390 40; + B 28 40 426 40; + B 28 40 462 40; + B 28 40 498 40; + B 28 40 534 40; + B 28 40 570 40; + B 28 40 606 40; + B 28 40 642 40; + B 28 40 678 40; + B 28 40 714 40; + B 28 40 750 40; + B 28 40 786 40; + B 28 40 822 40; + B 28 40 858 40; + B 28 40 894 40; + B 12 40 962 40; +L CAA; + B 1276 24 382 96; + B 16 96 -248 36; + B 1220 16 382 36; + B 16 96 1012 36; + B 1276 24 382 -24; +L CVA; + B 8 8 -272 156; + B 8 8 -152 156; + B 8 8 -44 156; + B 8 8 64 156; + B 8 8 172 156; + B 8 8 280 156; + B 8 8 388 156; + B 8 8 496 156; + B 8 8 604 156; + B 8 8 712 156; + B 8 8 820 156; + B 8 8 916 156; + B 8 8 1036 156; + B 8 8 -300 124; + B 8 8 -80 124; + B 8 8 28 124; + B 8 8 136 124; + B 8 8 244 124; + B 8 8 352 124; + B 8 8 460 124; + B 8 8 568 124; + B 8 8 676 124; + B 8 8 784 124; + B 8 8 892 124; + B 8 8 1064 124; + B 8 8 -328 92; + B 8 8 -116 96; + B 8 8 -8 96; + B 8 8 100 96; + B 8 8 208 96; + B 8 8 316 96; + B 8 8 424 96; + B 8 8 532 96; + B 8 8 640 96; + B 8 8 748 96; + B 8 8 856 96; + B 8 8 1092 92; + B 8 8 -220 12; + B 8 8 984 12; + B 8 8 -276 -20; + B 8 8 -96 -24; + B 8 8 12 -24; + B 8 8 120 -24; + B 8 8 228 -24; + B 8 8 336 -24; + B 8 8 444 -24; + B 8 8 552 -24; + B 8 8 660 -24; + B 8 8 768 -24; + B 8 8 876 -24; + B 8 8 1040 -20; + B 8 8 -304 -52; + B 8 8 -132 -52; + B 8 8 -24 -52; + B 8 8 84 -52; + B 8 8 192 -52; + B 8 8 300 -52; + B 8 8 408 -52; + B 8 8 516 -52; + B 8 8 624 -52; + B 8 8 732 -52; + B 8 8 840 -52; + B 8 8 1068 -52; + B 8 8 -320 -84; + B 8 8 -60 -84; + B 8 8 48 -84; + B 8 8 156 -84; + B 8 8 264 -84; + B 8 8 372 -84; + B 8 8 480 -84; + B 8 8 588 -84; + B 8 8 696 -84; + B 8 8 804 -84; + B 8 8 912 -84; + B 8 8 1092 -84; +L CEL; + B 24 60 -132 22; + B 24 60 -96 22; + B 24 60 -60 22; + B 24 60 -24 22; + B 24 60 12 22; + B 24 60 48 22; + B 24 60 84 22; + B 24 60 120 22; + B 24 60 156 22; + B 24 60 192 22; + B 24 60 228 22; + B 24 60 264 22; + B 24 60 300 22; + B 24 60 336 22; + B 24 60 372 22; + B 24 60 408 22; + B 24 60 444 22; + B 24 60 480 22; + B 24 60 516 22; + B 24 60 552 22; + B 24 60 588 22; + B 24 60 624 22; + B 24 60 660 22; + B 24 60 696 22; + B 24 60 732 22; + B 24 60 768 22; + B 24 60 804 22; + B 24 60 840 22; + B 24 60 876 22; + B 24 60 912 22; +L CCE; + B 8 8 -132 4; + B 8 8 -96 4; + B 8 8 -60 4; + B 8 8 -24 4; + B 8 8 12 4; + B 8 8 48 4; + B 8 8 84 4; + B 8 8 120 4; + B 8 8 156 4; + B 8 8 192 4; + B 8 8 228 4; + B 8 8 264 4; + B 8 8 300 4; + B 8 8 336 4; + B 8 8 372 4; + B 8 8 408 4; + B 8 8 444 4; + B 8 8 480 4; + B 8 8 516 4; + B 8 8 552 4; + B 8 8 588 4; + B 8 8 624 4; + B 8 8 660 4; + B 8 8 696 4; + B 8 8 732 4; + B 8 8 768 4; + B 8 8 804 4; + B 8 8 840 4; + B 8 8 876 4; + B 8 8 912 4; +L CCA; + B 8 8 -220 36; + B 8 8 -176 36; + B 8 8 940 36; + B 8 8 984 36; +L CCA; + B 8 8 -248 32; + B 8 8 1012 32; + B 8 8 -248 16; + B 8 8 1012 16; + B 8 8 -248 0; + B 8 8 1012 0; + B 8 8 -248 -16; + B 8 8 1012 -16; +L CCP; + B 8 8 -200 68; + B 8 8 -152 68; + B 8 8 -116 68; + B 8 8 -80 68; + B 8 8 -44 68; + B 8 8 -8 68; + B 8 8 28 68; + B 8 8 64 68; + B 8 8 100 68; + B 8 8 136 68; + B 8 8 172 68; + B 8 8 208 68; + B 8 8 244 68; + B 8 8 280 68; + B 8 8 316 68; + B 8 8 352 68; + B 8 8 388 68; + B 8 8 424 68; + B 8 8 460 68; + B 8 8 496 68; + B 8 8 532 68; + B 8 8 568 68; + B 8 8 604 68; + B 8 8 640 68; + B 8 8 676 68; + B 8 8 712 68; + B 8 8 748 68; + B 8 8 784 68; + B 8 8 820 68; + B 8 8 856 68; + B 8 8 892 68; + B 8 8 964 68; +L CSN; + B 84 32 -194 36; + B 84 32 958 36; +L CSP; + B 1292 40 382 96; + B 32 24 -248 64; + B 32 24 1012 64; + B 28 32 -250 36; + B 28 32 1014 36; + B 32 24 -248 8; + B 32 24 1012 8; + B 1292 40 382 -24; +L CCD; + B 1236 32 382 36; +94 c2 -134 126 CMS; +94 c2 -26 126 CMS; +94 c2 82 126 CMS; +94 c2 190 126 CMS; +94 c2 298 126 CMS; +94 c2 406 126 CMS; +94 c2 514 126 CMS; +94 c2 622 126 CMS; +94 c2 730 126 CMS; +94 c2 838 126 CMS; +94 c1 -134 154 CMS; +94 c1 -26 154 CMS; +94 c1 82 154 CMS; +94 c1 190 154 CMS; +94 c1 298 154 CMS; +94 c1 406 154 CMS; +94 c1 514 154 CMS; +94 c1 622 154 CMS; +94 c1 730 154 CMS; +94 c1 838 154 CMS; +94 c3 -134 94 CMS; +94 c3 -26 94 CMS; +94 c3 82 94 CMS; +94 c3 190 94 CMS; +94 c3 298 94 CMS; +94 c3 406 94 CMS; +94 c3 514 94 CMS; +94 c3 622 94 CMS; +94 c3 730 94 CMS; +94 c3 838 94 CMS; +94 c1 -150 -22 CMS; +94 c1 -42 -22 CMS; +94 c1 66 -22 CMS; +94 c1 174 -22 CMS; +94 c1 282 -22 CMS; +94 c1 390 -22 CMS; +94 c1 498 -22 CMS; +94 c1 606 -22 CMS; +94 c1 714 -22 CMS; +94 c1 822 -22 CMS; +94 c2 -150 -54 CMS; +94 c2 -42 -54 CMS; +94 c2 66 -54 CMS; +94 c2 174 -54 CMS; +94 c2 282 -54 CMS; +94 c2 390 -54 CMS; +94 c2 498 -54 CMS; +94 c2 606 -54 CMS; +94 c2 714 -54 CMS; +94 c2 822 -54 CMS; +94 c3 -150 -82 CMS; +94 c3 -42 -82 CMS; +94 c3 66 -82 CMS; +94 c3 174 -82 CMS; +94 c3 282 -82 CMS; +94 c3 390 -82 CMS; +94 c3 498 -82 CMS; +94 c3 606 -82 CMS; +94 c3 714 -82 CMS; +94 c3 822 -82 CMS; +94 c3 894 -82 CMS; +94 c2 894 -54 CMS; +94 c1 894 -22 CMS; +94 c1 946 154 CMS; +94 c3 946 94 CMS; +94 c2 946 126 CMS; +94 reset 964 68; +94 GND 984 36; +94 input -176 36; +94 reset -200 68; +94 GND -220 36; +94 output 940 36; +DF; +C 1; +End diff --git a/scmos/examples/float_gate/float_gate.mag b/scmos/examples/float_gate/float_gate.mag new file mode 100644 index 00000000..354d903d --- /dev/null +++ b/scmos/examples/float_gate/float_gate.mag @@ -0,0 +1,61 @@ +magic +tech scmos +timestamp 697876971 +<< polysilicon >> +rect 0 16 2 18 +rect 6 16 10 18 +rect 24 16 29 18 +rect 31 16 38 18 +rect 40 16 42 18 +<< poly2 >> +rect 10 23 24 24 +rect 10 18 11 23 +rect 23 18 24 23 +rect 29 18 31 21 +rect 38 18 40 21 +rect 10 11 11 16 +rect 23 11 24 16 +rect 29 14 31 16 +rect 38 14 40 16 +rect 10 10 24 11 +rect 27 13 33 14 +rect 10 8 16 10 +rect 27 9 28 13 +rect 32 9 33 13 +rect 27 8 33 9 +rect 36 13 42 14 +rect 36 9 37 13 +rect 41 9 42 13 +rect 36 8 42 9 +rect 10 4 11 8 +rect 15 4 16 8 +rect 10 3 16 4 +<< capacitor >> +rect 11 18 23 23 +rect 10 16 24 18 +rect 29 16 31 18 +rect 38 16 40 18 +rect 11 11 23 16 +<< ndiffusion >> +rect 2 18 6 19 +rect 2 15 6 16 +<< ntransistor >> +rect 2 16 6 18 +<< ndcontact >> +rect 2 19 6 23 +rect 2 11 6 15 +<< electrodecontact >> +rect 28 9 32 13 +rect 37 9 41 13 +rect 11 4 15 8 +<< labels >> +rlabel space 2 9 2 9 3 transistor +rlabel space -10 18 -10 18 3 floating +rlabel space -10 16 -10 16 3 gate +rlabel space 27 6 27 6 3 erase +rlabel space 27 4 27 4 3 voltage +rlabel space 36 6 36 6 3 programming +rlabel space 36 4 36 4 3 voltage +rlabel space 10 1 10 1 3 control +rlabel space 10 -1 10 -1 3 gate +<< end >> diff --git a/scmos/examples/linear_capacitor/wellcap.cif b/scmos/examples/linear_capacitor/wellcap.cif new file mode 100644 index 00000000..d5264992 --- /dev/null +++ b/scmos/examples/linear_capacitor/wellcap.cif @@ -0,0 +1,41 @@ +( @@user : pi ); +( @@machine : dirac.isi.edu ); +( @@source : wellcap.mag ); +( @@tool : Magic 6.4.4 ); +( @@patch : 1 ); +( @@patchnames : release-6.4, linux1 ); +( @@compiled : Fri Jan 13 16:46:31 PST 1995 ); +( @@technology : scmos ); +( @@version : 8.2.6 ); +( @@techdesc : MOSIS Scalable CMOS Technology for Tight Metal Rules ); +( @@style : lambda=0.6(gen) ); +( @@date : Fri Jun 2 11:15:52 1995 ); +DS 1 30 2; +9 wellcap; +L CWC; + B 120 96 60 48; +L CMF; + B 96 16 60 76; + B 88 16 52 -4; +L CPG; + B 88 64 52 20; +L CAA; + B 96 72 60 48; +L CCA; + B 8 8 20 76; + B 8 8 36 76; + B 8 8 52 76; + B 8 8 68 76; + B 8 8 84 76; + B 8 8 100 76; +L CCP; + B 8 8 20 -4; + B 8 8 36 -4; + B 8 8 52 -4; + B 8 8 68 -4; + B 8 8 84 -4; +L CSN; + B 112 88 60 48; +DF; +C 1; +End diff --git a/scmos/examples/linear_capacitor/wellcap.mag b/scmos/examples/linear_capacitor/wellcap.mag new file mode 100644 index 00000000..adf3559b --- /dev/null +++ b/scmos/examples/linear_capacitor/wellcap.mag @@ -0,0 +1,18 @@ +magic +tech scmos +timestamp 723775246 +<< capwell >> +rect 0 0 30 24 +<< polysilicon >> +rect 2 3 3 13 +rect 2 1 24 3 +<< wellcapacitor >> +rect 3 3 24 13 +<< ndiffusion >> +rect 3 13 27 17 +rect 24 3 27 13 +<< polycontact >> +rect 2 -3 24 1 +<< ndcontact >> +rect 3 17 27 21 +<< end >> diff --git a/scmos/examples/nist-mems-library/gas-sensor.cif b/scmos/examples/nist-mems-library/gas-sensor.cif new file mode 100644 index 00000000..1163dc1f --- /dev/null +++ b/scmos/examples/nist-mems-library/gas-sensor.cif @@ -0,0 +1,2372 @@ +DS 1 1 2; +9 gas-sensor; +L CMS; + B 2000 5200 5000 50600; + B 2000 5200 47000 50600; + B 2200 200 5100 47900; + B 2200 200 46900 47900; + B 2400 200 5200 47700; + B 2400 200 46800 47700; + B 2600 200 5300 47500; + B 2600 200 46700 47500; + B 2800 200 5400 47300; + B 2800 200 46600 47300; + B 1800 200 6100 47100; + B 1800 200 45900 47100; + B 1800 200 6300 46900; + B 1800 200 45700 46900; + B 1800 200 6500 46700; + B 1800 200 45500 46700; + B 1800 200 6700 46500; + B 1800 200 45300 46500; + B 1800 200 6900 46300; + B 1800 200 45100 46300; + B 1800 200 7100 46100; + B 1800 200 44900 46100; + B 1800 200 7300 45900; + B 1800 200 44700 45900; + B 1800 200 7500 45700; + B 1800 200 44500 45700; + B 1800 200 7700 45500; + B 1800 200 44300 45500; + B 1800 200 7900 45300; + B 1800 200 44100 45300; + B 1800 200 8100 45100; + B 1800 200 43900 45100; + B 1800 200 8300 44900; + B 1800 200 43700 44900; + B 1800 200 8500 44700; + B 1800 200 43500 44700; + B 1800 200 8700 44500; + B 1800 200 43300 44500; + B 1800 200 8900 44300; + B 1800 200 43100 44300; + B 1800 200 9100 44100; + B 1800 200 42900 44100; + B 1800 200 9300 43900; + B 1800 200 42700 43900; + B 1800 200 9500 43700; + B 1800 200 42500 43700; + B 1800 200 9700 43500; + B 1800 200 42300 43500; + B 1800 200 9900 43300; + B 1800 200 42100 43300; + B 1800 200 10100 43100; + B 1800 200 41900 43100; + B 1800 200 10300 42900; + B 1800 200 41700 42900; + B 1800 200 10500 42700; + B 1800 200 41500 42700; + B 1800 200 10700 42500; + B 1800 200 41300 42500; + B 1800 200 10900 42300; + B 1800 200 41100 42300; + B 1800 200 11100 42100; + B 1800 200 40900 42100; + B 1800 200 11300 41900; + B 1800 200 40700 41900; + B 1800 200 11500 41700; + B 1800 200 40500 41700; + B 1800 200 11700 41500; + B 1800 200 40300 41500; + B 1800 200 11900 41300; + B 1800 200 40100 41300; + B 1800 200 12100 41100; + B 1800 200 39900 41100; + B 1800 200 12300 40900; + B 1800 200 39700 40900; + B 1800 200 12500 40700; + B 1800 200 39500 40700; + B 1800 200 12700 40500; + B 1800 200 39300 40500; + B 1800 200 12900 40300; + B 1800 200 39100 40300; + B 1800 200 13100 40100; + B 1800 200 38900 40100; + B 1800 200 13300 39900; + B 1800 200 38700 39900; + B 1800 200 13500 39700; + B 1800 200 38500 39700; + B 1800 200 13700 39500; + B 1800 200 38300 39500; + B 1800 200 13900 39300; + B 1800 200 38100 39300; + B 1800 200 14100 39100; + B 1800 200 37900 39100; + B 1800 200 14300 38900; + B 1800 200 37700 38900; + B 1800 200 14500 38700; + B 1800 200 37500 38700; + B 1800 200 14700 38500; + B 1800 200 37300 38500; + B 1800 200 14900 38300; + B 1800 200 37100 38300; + B 1800 200 15100 38100; + B 1800 200 36900 38100; + B 1800 200 15300 37900; + B 1800 200 36700 37900; + B 1800 200 15500 37700; + B 1800 200 36500 37700; + B 1800 200 15700 37500; + B 1800 200 36300 37500; + B 1800 200 15900 37300; + B 1800 200 36100 37300; + B 1800 200 16100 37100; + B 1800 200 35900 37100; + B 1800 200 16300 36900; + B 1800 200 35700 36900; + B 1800 200 16500 36700; + B 1800 200 35500 36700; + B 1800 200 16700 36500; + B 1800 200 35300 36500; + B 1800 200 16900 36300; + B 1800 200 35100 36300; + B 1800 200 17100 36100; + B 1800 200 34900 36100; + B 1800 200 17300 35900; + B 1800 200 34700 35900; + B 1800 200 17500 35700; + B 1800 200 34500 35700; + B 1800 200 17700 35500; + B 1800 200 34300 35500; + B 1800 200 17900 35300; + B 1800 200 34100 35300; + B 7800 200 21100 35100; + B 7600 200 21200 34900; + B 7400 200 21300 34700; + B 7200 200 21400 34500; + B 7000 6200 21500 31300; + B 7800 200 30900 35100; + B 7600 200 30800 34900; + B 7400 200 30700 34700; + B 7200 200 30600 34500; + B 7000 6200 30500 31300; + B 7000 6200 21500 23100; + B 7200 200 21400 19900; + B 7400 200 21300 19700; + B 7600 200 21200 19500; + B 7800 200 21100 19300; + B 7000 6200 30500 23100; + B 7200 200 30600 19900; + B 7400 200 30700 19700; + B 7600 200 30800 19500; + B 7800 200 30900 19300; + B 1800 200 17900 19100; + B 1800 200 34100 19100; + B 1800 200 17700 18900; + B 1800 200 34300 18900; + B 1800 200 17500 18700; + B 1800 200 34500 18700; + B 1800 200 17300 18500; + B 1800 200 34700 18500; + B 1800 200 17100 18300; + B 1800 200 34900 18300; + B 1800 200 16900 18100; + B 1800 200 35100 18100; + B 1800 200 16700 17900; + B 1800 200 35300 17900; + B 1800 200 16500 17700; + B 1800 200 35500 17700; + B 1800 200 16300 17500; + B 1800 200 35700 17500; + B 1800 200 16100 17300; + B 1800 200 35900 17300; + B 1800 200 15900 17100; + B 1800 200 36100 17100; + B 1800 200 15700 16900; + B 1800 200 36300 16900; + B 1800 200 15500 16700; + B 1800 200 36500 16700; + B 1800 200 15300 16500; + B 1800 200 36700 16500; + B 1800 200 15100 16300; + B 1800 200 36900 16300; + B 1800 200 14900 16100; + B 1800 200 37100 16100; + B 1800 200 14700 15900; + B 1800 200 37300 15900; + B 1800 200 14500 15700; + B 1800 200 37500 15700; + B 1800 200 14300 15500; + B 1800 200 37700 15500; + B 1800 200 14100 15300; + B 1800 200 37900 15300; + B 1800 200 13900 15100; + B 1800 200 38100 15100; + B 1800 200 13700 14900; + B 1800 200 38300 14900; + B 1800 200 13500 14700; + B 1800 200 38500 14700; + B 1800 200 13300 14500; + B 1800 200 38700 14500; + B 1800 200 13100 14300; + B 1800 200 38900 14300; + B 1800 200 12900 14100; + B 1800 200 39100 14100; + B 1800 200 12700 13900; + B 1800 200 39300 13900; + B 1800 200 12500 13700; + B 1800 200 39500 13700; + B 1800 200 12300 13500; + B 1800 200 39700 13500; + B 1800 200 12100 13300; + B 1800 200 39900 13300; + B 1800 200 11900 13100; + B 1800 200 40100 13100; + B 1800 200 11700 12900; + B 1800 200 40300 12900; + B 1800 200 11500 12700; + B 1800 200 40500 12700; + B 1800 200 11300 12500; + B 1800 200 40700 12500; + B 1800 200 11100 12300; + B 1800 200 40900 12300; + B 1800 200 10900 12100; + B 1800 200 41100 12100; + B 1800 200 10700 11900; + B 1800 200 41300 11900; + B 1800 200 10500 11700; + B 1800 200 41500 11700; + B 1800 200 10300 11500; + B 1800 200 41700 11500; + B 1800 200 10100 11300; + B 1800 200 41900 11300; + B 1800 200 9900 11100; + B 1800 200 42100 11100; + B 1800 200 9700 10900; + B 1800 200 42300 10900; + B 1800 200 9500 10700; + B 1800 200 42500 10700; + B 1800 200 9300 10500; + B 1800 200 42700 10500; + B 1800 200 9100 10300; + B 1800 200 42900 10300; + B 1800 200 8900 10100; + B 1800 200 43100 10100; + B 1800 200 8700 9900; + B 1800 200 43300 9900; + B 1800 200 8500 9700; + B 1800 200 43500 9700; + B 1800 200 8300 9500; + B 1800 200 43700 9500; + B 1800 200 8100 9300; + B 1800 200 43900 9300; + B 1800 200 7900 9100; + B 1800 200 44100 9100; + B 1800 200 7700 8900; + B 1800 200 44300 8900; + B 1800 200 7500 8700; + B 1800 200 44500 8700; + B 1800 200 7300 8500; + B 1800 200 44700 8500; + B 1800 200 7100 8300; + B 1800 200 44900 8300; + B 1800 200 6900 8100; + B 1800 200 45100 8100; + B 1800 200 6700 7900; + B 1800 200 45300 7900; + B 1800 200 6500 7700; + B 1800 200 45500 7700; + B 1800 200 6300 7500; + B 1800 200 45700 7500; + B 1800 200 6100 7300; + B 1800 200 45900 7300; + B 2800 200 5400 7100; + B 2800 200 46600 7100; + B 2600 200 5300 6900; + B 2600 200 46700 6900; + B 2400 200 5200 6700; + B 2400 200 46800 6700; + B 2200 200 5100 6500; + B 2200 200 46900 6500; + B 2000 5200 5000 3800; + B 2000 5200 47000 3800; +L CMF; + B 2000 2000 51000 52200; + B 6000 1200 3000 48600; + B 6000 1200 49000 48600; + B 6200 200 3100 47900; + B 6200 200 48900 47900; + B 6400 200 3200 47700; + B 6400 200 48800 47700; + B 6600 200 3300 47500; + B 6600 200 48700 47500; + B 6800 200 3400 47300; + B 6800 200 48600 47300; + B 1800 200 6100 47100; + B 1800 200 45900 47100; + B 1800 200 6300 46900; + B 1800 200 45700 46900; + B 1800 200 6500 46700; + B 1800 200 45500 46700; + B 1800 200 6700 46500; + B 1800 200 45300 46500; + B 1800 200 6900 46300; + B 1800 200 45100 46300; + B 1800 200 7100 46100; + B 1800 200 44900 46100; + B 1800 200 7300 45900; + B 1800 200 44700 45900; + B 1800 200 7500 45700; + B 1800 200 44500 45700; + B 1800 200 7700 45500; + B 1800 200 44300 45500; + B 1800 200 7900 45300; + B 1800 200 44100 45300; + B 1800 200 8100 45100; + B 1800 200 43900 45100; + B 1800 200 8300 44900; + B 1800 200 43700 44900; + B 1800 200 8500 44700; + B 1800 200 43500 44700; + B 1800 200 8700 44500; + B 1800 200 43300 44500; + B 1800 200 8900 44300; + B 1800 200 43100 44300; + B 1800 200 9100 44100; + B 1800 200 42900 44100; + B 1800 200 9300 43900; + B 1800 200 42700 43900; + B 1800 200 9500 43700; + B 1800 200 42500 43700; + B 1800 200 9700 43500; + B 1800 200 42300 43500; + B 1800 200 9900 43300; + B 1800 200 42100 43300; + B 1800 200 10100 43100; + B 1800 200 41900 43100; + B 1800 200 10300 42900; + B 1800 200 41700 42900; + B 1800 200 10500 42700; + B 1800 200 41500 42700; + B 1800 200 10700 42500; + B 1800 200 41300 42500; + B 1800 200 10900 42300; + B 1800 200 41100 42300; + B 1800 200 11100 42100; + B 1800 200 40900 42100; + B 1800 200 11300 41900; + B 1800 200 40700 41900; + B 1800 200 11500 41700; + B 1800 200 40500 41700; + B 1800 200 11700 41500; + B 1800 200 40300 41500; + B 1800 200 11900 41300; + B 1800 200 40100 41300; + B 1800 200 12100 41100; + B 1800 200 39900 41100; + B 1800 200 12300 40900; + B 1800 200 39700 40900; + B 1800 200 12500 40700; + B 1800 200 39500 40700; + B 1800 200 12700 40500; + B 1800 200 39300 40500; + B 1800 200 12900 40300; + B 1800 200 39100 40300; + B 1800 200 13100 40100; + B 1800 200 38900 40100; + B 1800 200 13300 39900; + B 1800 200 38700 39900; + B 1800 200 13500 39700; + B 1800 200 38500 39700; + B 1800 200 13700 39500; + B 1800 200 38300 39500; + B 1800 200 13900 39300; + B 1800 200 38100 39300; + B 1800 200 14100 39100; + B 1800 200 37900 39100; + B 1800 200 14300 38900; + B 1800 200 37700 38900; + B 1800 200 14500 38700; + B 1800 200 37500 38700; + B 1800 200 14700 38500; + B 1800 200 37300 38500; + B 1800 200 14900 38300; + B 1800 200 37100 38300; + B 1800 200 15100 38100; + B 1800 200 36900 38100; + B 1800 200 15300 37900; + B 1800 200 36700 37900; + B 1800 200 15500 37700; + B 1800 200 36500 37700; + B 1800 200 15700 37500; + B 1800 200 36300 37500; + B 1800 200 15900 37300; + B 1800 200 36100 37300; + B 1800 200 16100 37100; + B 1800 200 35900 37100; + B 1800 200 16300 36900; + B 1800 200 35700 36900; + B 1800 200 16500 36700; + B 1800 200 35500 36700; + B 1800 200 16700 36500; + B 1800 200 35300 36500; + B 1800 200 16900 36300; + B 1800 200 35100 36300; + B 19600 200 26000 36100; + B 19200 200 26000 35900; + B 18800 200 26000 35700; + B 18400 200 26000 35500; + B 18000 16400 26000 27200; + B 18400 200 26000 18900; + B 18800 200 26000 18700; + B 19200 200 26000 18500; + B 19600 200 26000 18300; + B 1800 200 16900 18100; + B 1800 200 35100 18100; + B 1800 200 16700 17900; + B 1800 200 35300 17900; + B 1800 200 16500 17700; + B 1800 200 35500 17700; + B 1800 200 16300 17500; + B 1800 200 35700 17500; + B 1800 200 16100 17300; + B 1800 200 35900 17300; + B 1800 200 15900 17100; + B 1800 200 36100 17100; + B 1800 200 15700 16900; + B 1800 200 36300 16900; + B 1800 200 15500 16700; + B 1800 200 36500 16700; + B 1800 200 15300 16500; + B 1800 200 36700 16500; + B 1800 200 15100 16300; + B 1800 200 36900 16300; + B 1800 200 14900 16100; + B 1800 200 37100 16100; + B 1800 200 14700 15900; + B 1800 200 37300 15900; + B 1800 200 14500 15700; + B 1800 200 37500 15700; + B 1800 200 14300 15500; + B 1800 200 37700 15500; + B 1800 200 14100 15300; + B 1800 200 37900 15300; + B 1800 200 13900 15100; + B 1800 200 38100 15100; + B 1800 200 13700 14900; + B 1800 200 38300 14900; + B 1800 200 13500 14700; + B 1800 200 38500 14700; + B 1800 200 13300 14500; + B 1800 200 38700 14500; + B 1800 200 13100 14300; + B 1800 200 38900 14300; + B 1800 200 12900 14100; + B 1800 200 39100 14100; + B 1800 200 12700 13900; + B 1800 200 39300 13900; + B 1800 200 12500 13700; + B 1800 200 39500 13700; + B 1800 200 12300 13500; + B 1800 200 39700 13500; + B 1800 200 12100 13300; + B 1800 200 39900 13300; + B 1800 200 11900 13100; + B 1800 200 40100 13100; + B 1800 200 11700 12900; + B 1800 200 40300 12900; + B 1800 200 11500 12700; + B 1800 200 40500 12700; + B 1800 200 11300 12500; + B 1800 200 40700 12500; + B 1800 200 11100 12300; + B 1800 200 40900 12300; + B 1800 200 10900 12100; + B 1800 200 41100 12100; + B 1800 200 10700 11900; + B 1800 200 41300 11900; + B 1800 200 10500 11700; + B 1800 200 41500 11700; + B 1800 200 10300 11500; + B 1800 200 41700 11500; + B 1800 200 10100 11300; + B 1800 200 41900 11300; + B 1800 200 9900 11100; + B 1800 200 42100 11100; + B 1800 200 9700 10900; + B 1800 200 42300 10900; + B 1800 200 9500 10700; + B 1800 200 42500 10700; + B 1800 200 9300 10500; + B 1800 200 42700 10500; + B 1800 200 9100 10300; + B 1800 200 42900 10300; + B 1800 200 8900 10100; + B 1800 200 43100 10100; + B 1800 200 8700 9900; + B 1800 200 43300 9900; + B 1800 200 8500 9700; + B 1800 200 43500 9700; + B 1800 200 8300 9500; + B 1800 200 43700 9500; + B 1800 200 8100 9300; + B 1800 200 43900 9300; + B 1800 200 7900 9100; + B 1800 200 44100 9100; + B 1800 200 7700 8900; + B 1800 200 44300 8900; + B 1800 200 7500 8700; + B 1800 200 44500 8700; + B 1800 200 7300 8500; + B 1800 200 44700 8500; + B 1800 200 7100 8300; + B 1800 200 44900 8300; + B 1800 200 6900 8100; + B 1800 200 45100 8100; + B 1800 200 6700 7900; + B 1800 200 45300 7900; + B 1800 200 6500 7700; + B 1800 200 45500 7700; + B 1800 200 6300 7500; + B 1800 200 45700 7500; + B 1800 200 6100 7300; + B 1800 200 45900 7300; + B 6800 200 3400 7100; + B 6800 200 48600 7100; + B 6600 200 3300 6900; + B 6600 200 48700 6900; + B 6400 200 3200 6700; + B 6400 200 48800 6700; + B 6200 200 3100 6500; + B 6200 200 48900 6500; + B 6000 1200 3000 5800; + B 6000 1200 49000 5800; + B 2000 3200 1000 1600; +L CPG; + B 2000 200 51000 53100; + B 2200 200 50900 52900; + B 2400 200 50800 52700; + B 2600 200 50700 52500; + B 2800 200 50600 52300; + B 3000 200 50500 52100; + B 3200 200 50400 51900; + B 3400 200 50300 51700; + B 3600 200 50200 51500; + B 3800 200 50100 51300; + B 3800 200 49900 51100; + B 3800 200 49700 50900; + B 3800 200 49500 50700; + B 3800 200 49300 50500; + B 3800 200 49100 50300; + B 3800 200 48900 50100; + B 3800 200 48700 49900; + B 3800 200 48500 49700; + B 3800 200 48300 49500; + B 3800 200 48100 49300; + B 3800 200 47900 49100; + B 3800 200 47700 48900; + B 3800 200 47500 48700; + B 3800 200 47300 48500; + B 3800 200 47100 48300; + B 3800 200 46900 48100; + B 3800 200 46700 47900; + B 3800 200 46500 47700; + B 3800 200 46300 47500; + B 3800 200 46100 47300; + B 3800 200 45900 47100; + B 3800 200 45700 46900; + B 3800 200 45500 46700; + B 3800 200 45300 46500; + B 3800 200 45100 46300; + B 3800 200 44900 46100; + B 3800 200 44700 45900; + B 3800 200 44500 45700; + B 3800 200 44300 45500; + B 3800 200 44100 45300; + B 3800 200 43900 45100; + B 3800 200 43700 44900; + B 3800 200 43500 44700; + B 3800 200 43300 44500; + B 3800 200 43100 44300; + B 3800 200 42900 44100; + B 3800 200 42700 43900; + B 3800 200 42500 43700; + B 3800 200 42300 43500; + B 3800 200 42100 43300; + B 3800 200 41900 43100; + B 3800 200 41700 42900; + B 3800 200 41500 42700; + B 3800 200 41300 42500; + B 3800 200 41100 42300; + B 3800 200 40900 42100; + B 3800 200 40700 41900; + B 3800 200 40500 41700; + B 3800 200 40300 41500; + B 3800 200 40100 41300; + B 3800 200 39900 41100; + B 3800 200 39700 40900; + B 3800 200 39500 40700; + B 3800 200 39300 40500; + B 3800 200 39100 40300; + B 3800 200 38900 40100; + B 3800 200 38700 39900; + B 3800 200 38500 39700; + B 3800 200 38300 39500; + B 3800 200 38100 39300; + B 3800 200 37900 39100; + B 3800 200 37700 38900; + B 3800 200 37500 38700; + B 3800 200 37300 38500; + B 3800 200 37100 38300; + B 3800 200 36900 38100; + B 3800 200 36700 37900; + B 3800 200 36500 37700; + B 3800 200 36300 37500; + B 3800 200 36100 37300; + B 3800 200 35900 37100; + B 3800 200 35700 36900; + B 3800 200 35500 36700; + B 3800 200 35300 36500; + B 3800 200 35100 36300; + B 3800 200 34900 36100; + B 3800 200 34700 35900; + B 3800 200 34500 35700; + B 3800 200 34300 35500; + B 3600 200 34200 35300; + B 17800 200 26900 35100; + B 17600 200 26800 34900; + B 17400 200 26700 34700; + B 17200 200 26600 34500; + B 17000 200 26500 34300; + B 16800 200 26400 34100; + B 16600 200 26300 33900; + B 16400 200 26200 33700; + B 1600 800 18800 33200; + B 16000 1600 26000 32000; + B 1600 800 33200 30800; + B 16000 1600 26000 29600; + B 1600 800 18800 28400; + B 16000 1600 26000 27200; + B 1600 800 33200 26000; + B 16000 1600 26000 24800; + B 1600 800 18800 23600; + B 16000 1600 26000 22400; + B 1600 800 33200 21200; + B 16400 200 25800 20700; + B 16600 200 25700 20500; + B 16800 200 25600 20300; + B 17000 200 25500 20100; + B 17200 200 25400 19900; + B 17400 200 25300 19700; + B 17600 200 25200 19500; + B 17800 200 25100 19300; + B 3600 200 17800 19100; + B 3800 200 17700 18900; + B 3800 200 17500 18700; + B 3800 200 17300 18500; + B 3800 200 17100 18300; + B 3800 200 16900 18100; + B 3800 200 16700 17900; + B 3800 200 16500 17700; + B 3800 200 16300 17500; + B 3800 200 16100 17300; + B 3800 200 15900 17100; + B 3800 200 15700 16900; + B 3800 200 15500 16700; + B 3800 200 15300 16500; + B 3800 200 15100 16300; + B 3800 200 14900 16100; + B 3800 200 14700 15900; + B 3800 200 14500 15700; + B 3800 200 14300 15500; + B 3800 200 14100 15300; + B 3800 200 13900 15100; + B 3800 200 13700 14900; + B 3800 200 13500 14700; + B 3800 200 13300 14500; + B 3800 200 13100 14300; + B 3800 200 12900 14100; + B 3800 200 12700 13900; + B 3800 200 12500 13700; + B 3800 200 12300 13500; + B 3800 200 12100 13300; + B 3800 200 11900 13100; + B 3800 200 11700 12900; + B 3800 200 11500 12700; + B 3800 200 11300 12500; + B 3800 200 11100 12300; + B 3800 200 10900 12100; + B 3800 200 10700 11900; + B 3800 200 10500 11700; + B 3800 200 10300 11500; + B 3800 200 10100 11300; + B 3800 200 9900 11100; + B 3800 200 9700 10900; + B 3800 200 9500 10700; + B 3800 200 9300 10500; + B 3800 200 9100 10300; + B 3800 200 8900 10100; + B 3800 200 8700 9900; + B 3800 200 8500 9700; + B 3800 200 8300 9500; + B 3800 200 8100 9300; + B 3800 200 7900 9100; + B 3800 200 7700 8900; + B 3800 200 7500 8700; + B 3800 200 7300 8500; + B 3800 200 7100 8300; + B 3800 200 6900 8100; + B 3800 200 6700 7900; + B 3800 200 6500 7700; + B 3800 200 6300 7500; + B 3800 200 6100 7300; + B 3800 200 5900 7100; + B 3800 200 5700 6900; + B 3800 200 5500 6700; + B 3800 200 5300 6500; + B 3800 200 5100 6300; + B 3800 200 4900 6100; + B 3800 200 4700 5900; + B 3800 200 4500 5700; + B 3800 200 4300 5500; + B 3800 200 4100 5300; + B 3800 200 3900 5100; + B 3800 200 3700 4900; + B 3800 200 3500 4700; + B 3800 200 3300 4500; + B 3800 200 3100 4300; + B 3800 200 2900 4100; + B 3800 200 2700 3900; + B 3800 200 2500 3700; + B 3800 200 2300 3500; + B 3800 200 2100 3300; + B 3800 200 1900 3100; + B 3600 200 1800 2900; + B 3400 200 1700 2700; + B 3200 200 1600 2500; + B 3000 200 1500 2300; + B 2800 200 1400 2100; + B 2600 200 1300 1900; + B 2400 200 1200 1700; + B 2200 200 1100 1500; + B 2000 200 1000 1300; +L CAA; + B 42000 200 25000 49100; + B 41800 200 24900 48900; + B 41600 200 24800 48700; + B 41400 200 24700 48500; + B 41200 200 24600 48300; + B 41000 200 24500 48100; + B 40800 200 24400 47900; + B 40600 200 24300 47700; + B 40400 200 24200 47500; + B 40200 200 24100 47300; + B 2000 4000 5000 45200; + B 32000 200 26000 47100; + B 200 200 47900 47100; + B 31600 200 26000 46900; + B 400 200 47800 46900; + B 31200 200 26000 46700; + B 600 200 47700 46700; + B 30800 200 26000 46500; + B 800 200 47600 46500; + B 30400 200 26000 46300; + B 1000 200 47500 46300; + B 30000 200 26000 46100; + B 1200 200 47400 46100; + B 29600 200 26000 45900; + B 1400 200 47300 45900; + B 29200 200 26000 45700; + B 1600 200 47200 45700; + B 28800 200 26000 45500; + B 1800 200 47100 45500; + B 28400 200 26000 45300; + B 28000 200 26000 45100; + B 27600 200 26000 44900; + B 27200 200 26000 44700; + B 26800 200 26000 44500; + B 26400 200 26000 44300; + B 26000 200 26000 44100; + B 25600 200 26000 43900; + B 25200 200 26000 43700; + B 24800 200 26000 43500; + B 24400 200 26000 43300; + B 2000 2200 47000 44300; + B 2200 200 5100 43100; + B 24000 200 26000 43100; + B 2200 200 46900 43100; + B 2400 200 5200 42900; + B 23600 200 26000 42900; + B 2400 200 46800 42900; + B 2600 200 5300 42700; + B 23200 200 26000 42700; + B 2600 200 46700 42700; + B 2800 200 5400 42500; + B 22800 200 26000 42500; + B 2800 200 46600 42500; + B 3000 200 5500 42300; + B 22400 200 26000 42300; + B 3000 200 46500 42300; + B 3200 200 5600 42100; + B 22000 200 26000 42100; + B 3200 200 46400 42100; + B 3400 200 5700 41900; + B 21600 200 26000 41900; + B 3400 200 46300 41900; + B 3600 200 5800 41700; + B 21200 200 26000 41700; + B 3600 200 46200 41700; + B 3800 200 5900 41500; + B 20800 200 26000 41500; + B 3800 200 46100 41500; + B 4000 200 6000 41300; + B 20400 200 26000 41300; + B 4000 200 46000 41300; + B 4200 200 6100 41100; + B 20000 200 26000 41100; + B 4200 200 45900 41100; + B 4400 200 6200 40900; + B 19600 200 26000 40900; + B 4400 200 45800 40900; + B 4600 200 6300 40700; + B 19200 200 26000 40700; + B 4600 200 45700 40700; + B 4800 200 6400 40500; + B 18800 200 26000 40500; + B 4800 200 45600 40500; + B 5000 200 6500 40300; + B 18400 200 26000 40300; + B 5000 200 45500 40300; + B 5200 200 6600 40100; + B 18000 200 26000 40100; + B 5200 200 45400 40100; + B 5400 200 6700 39900; + B 17600 200 26000 39900; + B 5400 200 45300 39900; + B 5600 200 6800 39700; + B 17200 200 26000 39700; + B 5600 200 45200 39700; + B 5800 200 6900 39500; + B 16800 200 26000 39500; + B 5800 200 45100 39500; + B 6000 200 7000 39300; + B 16400 200 26000 39300; + B 6000 200 45000 39300; + B 6200 200 7100 39100; + B 16000 200 26000 39100; + B 6200 200 44900 39100; + B 6400 200 7200 38900; + B 15600 200 26000 38900; + B 6400 200 44800 38900; + B 6600 200 7300 38700; + B 15200 200 26000 38700; + B 6600 200 44700 38700; + B 6800 200 7400 38500; + B 14800 200 26000 38500; + B 6800 200 44600 38500; + B 7000 200 7500 38300; + B 14400 200 26000 38300; + B 7000 200 44500 38300; + B 7200 200 7600 38100; + B 14000 200 26000 38100; + B 7200 200 44400 38100; + B 7400 200 7700 37900; + B 13600 200 26000 37900; + B 7400 200 44300 37900; + B 7600 200 7800 37700; + B 13200 200 26000 37700; + B 7600 200 44200 37700; + B 7800 200 7900 37500; + B 12800 200 26000 37500; + B 7800 200 44100 37500; + B 8000 200 8000 37300; + B 12400 200 26000 37300; + B 8000 200 44000 37300; + B 8200 200 8100 37100; + B 8200 200 43900 37100; + B 8400 200 8200 36900; + B 8400 200 43800 36900; + B 8600 200 8300 36700; + B 8600 200 43700 36700; + B 8800 200 8400 36500; + B 8800 200 43600 36500; + B 9000 200 8500 36300; + B 9000 200 43500 36300; + B 9200 200 8600 36100; + B 9200 200 43400 36100; + B 9400 200 8700 35900; + B 9400 200 43300 35900; + B 9600 200 8800 35700; + B 9600 200 43200 35700; + B 9800 200 8900 35500; + B 9800 200 43100 35500; + B 10000 200 9000 35300; + B 10000 200 43000 35300; + B 10200 200 9100 35100; + B 10200 200 42900 35100; + B 10400 200 9200 34900; + B 10400 200 42800 34900; + B 10600 200 9300 34700; + B 10600 200 42700 34700; + B 10800 200 9400 34500; + B 10800 200 42600 34500; + B 11000 200 9500 34300; + B 11000 200 42500 34300; + B 11200 200 9600 34100; + B 11200 200 42400 34100; + B 11400 200 9700 33900; + B 11400 200 42300 33900; + B 11600 200 9800 33700; + B 11600 200 42200 33700; + B 11800 200 9900 33500; + B 11800 200 42100 33500; + B 12000 12400 10000 27200; + B 12000 12400 42000 27200; + B 11800 200 9900 20900; + B 11800 200 42100 20900; + B 11600 200 9800 20700; + B 11600 200 42200 20700; + B 11400 200 9700 20500; + B 11400 200 42300 20500; + B 11200 200 9600 20300; + B 11200 200 42400 20300; + B 11000 200 9500 20100; + B 11000 200 42500 20100; + B 10800 200 9400 19900; + B 10800 200 42600 19900; + B 10600 200 9300 19700; + B 10600 200 42700 19700; + B 10400 200 9200 19500; + B 10400 200 42800 19500; + B 10200 200 9100 19300; + B 10200 200 42900 19300; + B 10000 200 9000 19100; + B 10000 200 43000 19100; + B 9800 200 8900 18900; + B 9800 200 43100 18900; + B 9600 200 8800 18700; + B 9600 200 43200 18700; + B 9400 200 8700 18500; + B 9400 200 43300 18500; + B 9200 200 8600 18300; + B 9200 200 43400 18300; + B 9000 200 8500 18100; + B 9000 200 43500 18100; + B 8800 200 8400 17900; + B 8800 200 43600 17900; + B 8600 200 8300 17700; + B 8600 200 43700 17700; + B 8400 200 8200 17500; + B 8400 200 43800 17500; + B 8200 200 8100 17300; + B 8200 200 43900 17300; + B 8000 200 8000 17100; + B 12400 200 26000 17100; + B 8000 200 44000 17100; + B 7800 200 7900 16900; + B 12800 200 26000 16900; + B 7800 200 44100 16900; + B 7600 200 7800 16700; + B 13200 200 26000 16700; + B 7600 200 44200 16700; + B 7400 200 7700 16500; + B 13600 200 26000 16500; + B 7400 200 44300 16500; + B 7200 200 7600 16300; + B 14000 200 26000 16300; + B 7200 200 44400 16300; + B 7000 200 7500 16100; + B 14400 200 26000 16100; + B 7000 200 44500 16100; + B 6800 200 7400 15900; + B 14800 200 26000 15900; + B 6800 200 44600 15900; + B 6600 200 7300 15700; + B 15200 200 26000 15700; + B 6600 200 44700 15700; + B 6400 200 7200 15500; + B 15600 200 26000 15500; + B 6400 200 44800 15500; + B 6200 200 7100 15300; + B 16000 200 26000 15300; + B 6200 200 44900 15300; + B 6000 200 7000 15100; + B 16400 200 26000 15100; + B 6000 200 45000 15100; + B 5800 200 6900 14900; + B 16800 200 26000 14900; + B 5800 200 45100 14900; + B 5600 200 6800 14700; + B 17200 200 26000 14700; + B 5600 200 45200 14700; + B 5400 200 6700 14500; + B 17600 200 26000 14500; + B 5400 200 45300 14500; + B 5200 200 6600 14300; + B 18000 200 26000 14300; + B 5200 200 45400 14300; + B 5000 200 6500 14100; + B 18400 200 26000 14100; + B 5000 200 45500 14100; + B 4800 200 6400 13900; + B 18800 200 26000 13900; + B 4800 200 45600 13900; + B 4600 200 6300 13700; + B 19200 200 26000 13700; + B 4600 200 45700 13700; + B 4400 200 6200 13500; + B 19600 200 26000 13500; + B 4400 200 45800 13500; + B 4200 200 6100 13300; + B 20000 200 26000 13300; + B 4200 200 45900 13300; + B 4000 200 6000 13100; + B 20400 200 26000 13100; + B 4000 200 46000 13100; + B 3800 200 5900 12900; + B 20800 200 26000 12900; + B 3800 200 46100 12900; + B 3600 200 5800 12700; + B 21200 200 26000 12700; + B 3600 200 46200 12700; + B 3400 200 5700 12500; + B 21600 200 26000 12500; + B 3400 200 46300 12500; + B 3200 200 5600 12300; + B 22000 200 26000 12300; + B 3200 200 46400 12300; + B 3000 200 5500 12100; + B 22400 200 26000 12100; + B 3000 200 46500 12100; + B 2800 200 5400 11900; + B 22800 200 26000 11900; + B 2800 200 46600 11900; + B 2600 200 5300 11700; + B 23200 200 26000 11700; + B 2600 200 46700 11700; + B 2400 200 5200 11500; + B 23600 200 26000 11500; + B 2400 200 46800 11500; + B 2200 200 5100 11300; + B 24000 200 26000 11300; + B 2200 200 46900 11300; + B 2000 2200 5000 10100; + B 24400 200 26000 11100; + B 24800 200 26000 10900; + B 25200 200 26000 10700; + B 25600 200 26000 10500; + B 26000 200 26000 10300; + B 26400 200 26000 10100; + B 26800 200 26000 9900; + B 27200 200 26000 9700; + B 27600 200 26000 9500; + B 28000 200 26000 9300; + B 28400 200 26000 9100; + B 1800 200 4900 8900; + B 28800 200 26000 8900; + B 1600 200 4800 8700; + B 29200 200 26000 8700; + B 1400 200 4700 8500; + B 29600 200 26000 8500; + B 1200 200 4600 8300; + B 30000 200 26000 8300; + B 1000 200 4500 8100; + B 30400 200 26000 8100; + B 800 200 4400 7900; + B 30800 200 26000 7900; + B 600 200 4300 7700; + B 31200 200 26000 7700; + B 400 200 4200 7500; + B 31600 200 26000 7500; + B 200 200 4100 7300; + B 32000 200 26000 7300; + B 2000 4000 47000 9200; + B 40200 200 27900 7100; + B 40400 200 27800 6900; + B 40600 200 27700 6700; + B 40800 200 27600 6500; + B 41000 200 27500 6300; + B 41200 200 27400 6100; + B 41400 200 27300 5900; + B 41600 200 27200 5700; + B 41800 200 27100 5500; + B 42000 200 27000 5300; +L CVA; + B 32000 200 26000 47100; + B 31600 200 26000 46900; + B 31200 200 26000 46700; + B 30800 200 26000 46500; + B 30400 200 26000 46300; + B 30000 200 26000 46100; + B 29600 200 26000 45900; + B 29200 200 26000 45700; + B 28800 200 26000 45500; + B 28400 200 26000 45300; + B 28000 200 26000 45100; + B 27600 200 26000 44900; + B 27200 200 26000 44700; + B 26800 200 26000 44500; + B 26400 200 26000 44300; + B 26000 200 26000 44100; + B 25600 200 26000 43900; + B 25200 200 26000 43700; + B 24800 200 26000 43500; + B 24400 200 26000 43300; + B 200 200 6100 43100; + B 24000 200 26000 43100; + B 200 200 45900 43100; + B 400 200 6200 42900; + B 23600 200 26000 42900; + B 400 200 45800 42900; + B 600 200 6300 42700; + B 23200 200 26000 42700; + B 600 200 45700 42700; + B 800 200 6400 42500; + B 22800 200 26000 42500; + B 800 200 45600 42500; + B 1000 200 6500 42300; + B 22400 200 26000 42300; + B 1000 200 45500 42300; + B 1200 200 6600 42100; + B 22000 200 26000 42100; + B 1200 200 45400 42100; + B 1400 200 6700 41900; + B 21600 200 26000 41900; + B 1400 200 45300 41900; + B 1600 200 6800 41700; + B 21200 200 26000 41700; + B 1600 200 45200 41700; + B 1800 200 6900 41500; + B 20800 200 26000 41500; + B 1800 200 45100 41500; + B 2000 200 7000 41300; + B 20400 200 26000 41300; + B 2000 200 45000 41300; + B 2200 200 7100 41100; + B 20000 200 26000 41100; + B 2200 200 44900 41100; + B 2400 200 7200 40900; + B 19600 200 26000 40900; + B 2400 200 44800 40900; + B 2600 200 7300 40700; + B 19200 200 26000 40700; + B 2600 200 44700 40700; + B 2800 200 7400 40500; + B 18800 200 26000 40500; + B 2800 200 44600 40500; + B 3000 200 7500 40300; + B 18400 200 26000 40300; + B 3000 200 44500 40300; + B 3200 200 7600 40100; + B 18000 200 26000 40100; + B 3200 200 44400 40100; + B 3400 200 7700 39900; + B 17600 200 26000 39900; + B 3400 200 44300 39900; + B 3600 200 7800 39700; + B 17200 200 26000 39700; + B 3600 200 44200 39700; + B 3800 200 7900 39500; + B 16800 200 26000 39500; + B 3800 200 44100 39500; + B 4000 200 8000 39300; + B 16400 200 26000 39300; + B 4000 200 44000 39300; + B 4200 200 8100 39100; + B 16000 200 26000 39100; + B 4200 200 43900 39100; + B 4400 200 8200 38900; + B 15600 200 26000 38900; + B 4400 200 43800 38900; + B 4600 200 8300 38700; + B 15200 200 26000 38700; + B 4600 200 43700 38700; + B 4800 200 8400 38500; + B 14800 200 26000 38500; + B 4800 200 43600 38500; + B 5000 200 8500 38300; + B 14400 200 26000 38300; + B 5000 200 43500 38300; + B 5200 200 8600 38100; + B 14000 200 26000 38100; + B 5200 200 43400 38100; + B 5400 200 8700 37900; + B 13600 200 26000 37900; + B 5400 200 43300 37900; + B 5600 200 8800 37700; + B 13200 200 26000 37700; + B 5600 200 43200 37700; + B 5800 200 8900 37500; + B 12800 200 26000 37500; + B 5800 200 43100 37500; + B 6000 200 9000 37300; + B 12400 200 26000 37300; + B 6000 200 43000 37300; + B 6200 200 9100 37100; + B 6200 200 42900 37100; + B 6400 200 9200 36900; + B 6400 200 42800 36900; + B 6600 200 9300 36700; + B 6600 200 42700 36700; + B 6800 200 9400 36500; + B 6800 200 42600 36500; + B 7000 200 9500 36300; + B 7000 200 42500 36300; + B 7200 200 9600 36100; + B 7200 200 42400 36100; + B 7400 200 9700 35900; + B 7400 200 42300 35900; + B 7600 200 9800 35700; + B 7600 200 42200 35700; + B 7800 200 9900 35500; + B 7800 200 42100 35500; + B 8000 200 10000 35300; + B 8000 200 42000 35300; + B 8200 200 10100 35100; + B 8200 200 41900 35100; + B 8400 200 10200 34900; + B 8400 200 41800 34900; + B 8600 200 10300 34700; + B 8600 200 41700 34700; + B 8800 200 10400 34500; + B 8800 200 41600 34500; + B 9000 200 10500 34300; + B 9000 200 41500 34300; + B 9200 200 10600 34100; + B 9200 200 41400 34100; + B 9400 200 10700 33900; + B 9400 200 41300 33900; + B 9600 200 10800 33700; + B 9600 200 41200 33700; + B 9800 200 10900 33500; + B 9800 200 41100 33500; + B 10000 12400 11000 27200; + B 10000 12400 41000 27200; + B 9800 200 10900 20900; + B 9800 200 41100 20900; + B 9600 200 10800 20700; + B 9600 200 41200 20700; + B 9400 200 10700 20500; + B 9400 200 41300 20500; + B 9200 200 10600 20300; + B 9200 200 41400 20300; + B 9000 200 10500 20100; + B 9000 200 41500 20100; + B 8800 200 10400 19900; + B 8800 200 41600 19900; + B 8600 200 10300 19700; + B 8600 200 41700 19700; + B 8400 200 10200 19500; + B 8400 200 41800 19500; + B 8200 200 10100 19300; + B 8200 200 41900 19300; + B 8000 200 10000 19100; + B 8000 200 42000 19100; + B 7800 200 9900 18900; + B 7800 200 42100 18900; + B 7600 200 9800 18700; + B 7600 200 42200 18700; + B 7400 200 9700 18500; + B 7400 200 42300 18500; + B 7200 200 9600 18300; + B 7200 200 42400 18300; + B 7000 200 9500 18100; + B 7000 200 42500 18100; + B 6800 200 9400 17900; + B 6800 200 42600 17900; + B 6600 200 9300 17700; + B 6600 200 42700 17700; + B 6400 200 9200 17500; + B 6400 200 42800 17500; + B 6200 200 9100 17300; + B 6200 200 42900 17300; + B 6000 200 9000 17100; + B 12400 200 26000 17100; + B 6000 200 43000 17100; + B 5800 200 8900 16900; + B 12800 200 26000 16900; + B 5800 200 43100 16900; + B 5600 200 8800 16700; + B 13200 200 26000 16700; + B 5600 200 43200 16700; + B 5400 200 8700 16500; + B 13600 200 26000 16500; + B 5400 200 43300 16500; + B 5200 200 8600 16300; + B 14000 200 26000 16300; + B 5200 200 43400 16300; + B 5000 200 8500 16100; + B 14400 200 26000 16100; + B 5000 200 43500 16100; + B 4800 200 8400 15900; + B 14800 200 26000 15900; + B 4800 200 43600 15900; + B 4600 200 8300 15700; + B 15200 200 26000 15700; + B 4600 200 43700 15700; + B 4400 200 8200 15500; + B 15600 200 26000 15500; + B 4400 200 43800 15500; + B 4200 200 8100 15300; + B 16000 200 26000 15300; + B 4200 200 43900 15300; + B 4000 200 8000 15100; + B 16400 200 26000 15100; + B 4000 200 44000 15100; + B 3800 200 7900 14900; + B 16800 200 26000 14900; + B 3800 200 44100 14900; + B 3600 200 7800 14700; + B 17200 200 26000 14700; + B 3600 200 44200 14700; + B 3400 200 7700 14500; + B 17600 200 26000 14500; + B 3400 200 44300 14500; + B 3200 200 7600 14300; + B 18000 200 26000 14300; + B 3200 200 44400 14300; + B 3000 200 7500 14100; + B 18400 200 26000 14100; + B 3000 200 44500 14100; + B 2800 200 7400 13900; + B 18800 200 26000 13900; + B 2800 200 44600 13900; + B 2600 200 7300 13700; + B 19200 200 26000 13700; + B 2600 200 44700 13700; + B 2400 200 7200 13500; + B 19600 200 26000 13500; + B 2400 200 44800 13500; + B 2200 200 7100 13300; + B 20000 200 26000 13300; + B 2200 200 44900 13300; + B 2000 200 7000 13100; + B 20400 200 26000 13100; + B 2000 200 45000 13100; + B 1800 200 6900 12900; + B 20800 200 26000 12900; + B 1800 200 45100 12900; + B 1600 200 6800 12700; + B 21200 200 26000 12700; + B 1600 200 45200 12700; + B 1400 200 6700 12500; + B 21600 200 26000 12500; + B 1400 200 45300 12500; + B 1200 200 6600 12300; + B 22000 200 26000 12300; + B 1200 200 45400 12300; + B 1000 200 6500 12100; + B 22400 200 26000 12100; + B 1000 200 45500 12100; + B 800 200 6400 11900; + B 22800 200 26000 11900; + B 800 200 45600 11900; + B 600 200 6300 11700; + B 23200 200 26000 11700; + B 600 200 45700 11700; + B 400 200 6200 11500; + B 23600 200 26000 11500; + B 400 200 45800 11500; + B 200 200 6100 11300; + B 24000 200 26000 11300; + B 200 200 45900 11300; + B 24400 200 26000 11100; + B 24800 200 26000 10900; + B 25200 200 26000 10700; + B 25600 200 26000 10500; + B 26000 200 26000 10300; + B 26400 200 26000 10100; + B 26800 200 26000 9900; + B 27200 200 26000 9700; + B 27600 200 26000 9500; + B 28000 200 26000 9300; + B 28400 200 26000 9100; + B 28800 200 26000 8900; + B 29200 200 26000 8700; + B 29600 200 26000 8500; + B 30000 200 26000 8300; + B 30400 200 26000 8100; + B 30800 200 26000 7900; + B 31200 200 26000 7700; + B 31600 200 26000 7500; + B 32000 200 26000 7300; +L CCA; + B 32000 200 26000 47100; + B 31600 200 26000 46900; + B 31200 200 26000 46700; + B 30800 200 26000 46500; + B 30400 200 26000 46300; + B 30000 200 26000 46100; + B 29600 200 26000 45900; + B 29200 200 26000 45700; + B 28800 200 26000 45500; + B 28400 200 26000 45300; + B 28000 200 26000 45100; + B 27600 200 26000 44900; + B 27200 200 26000 44700; + B 26800 200 26000 44500; + B 26400 200 26000 44300; + B 26000 200 26000 44100; + B 25600 200 26000 43900; + B 25200 200 26000 43700; + B 24800 200 26000 43500; + B 24400 200 26000 43300; + B 200 200 6100 43100; + B 24000 200 26000 43100; + B 200 200 45900 43100; + B 400 200 6200 42900; + B 23600 200 26000 42900; + B 400 200 45800 42900; + B 600 200 6300 42700; + B 23200 200 26000 42700; + B 600 200 45700 42700; + B 800 200 6400 42500; + B 22800 200 26000 42500; + B 800 200 45600 42500; + B 1000 200 6500 42300; + B 22400 200 26000 42300; + B 1000 200 45500 42300; + B 1200 200 6600 42100; + B 22000 200 26000 42100; + B 1200 200 45400 42100; + B 1400 200 6700 41900; + B 21600 200 26000 41900; + B 1400 200 45300 41900; + B 1600 200 6800 41700; + B 21200 200 26000 41700; + B 1600 200 45200 41700; + B 1800 200 6900 41500; + B 20800 200 26000 41500; + B 1800 200 45100 41500; + B 2000 200 7000 41300; + B 20400 200 26000 41300; + B 2000 200 45000 41300; + B 2200 200 7100 41100; + B 20000 200 26000 41100; + B 2200 200 44900 41100; + B 2400 200 7200 40900; + B 19600 200 26000 40900; + B 2400 200 44800 40900; + B 2600 200 7300 40700; + B 19200 200 26000 40700; + B 2600 200 44700 40700; + B 2800 200 7400 40500; + B 18800 200 26000 40500; + B 2800 200 44600 40500; + B 3000 200 7500 40300; + B 18400 200 26000 40300; + B 3000 200 44500 40300; + B 3200 200 7600 40100; + B 18000 200 26000 40100; + B 3200 200 44400 40100; + B 3400 200 7700 39900; + B 17600 200 26000 39900; + B 3400 200 44300 39900; + B 3600 200 7800 39700; + B 17200 200 26000 39700; + B 3600 200 44200 39700; + B 3800 200 7900 39500; + B 16800 200 26000 39500; + B 3800 200 44100 39500; + B 4000 200 8000 39300; + B 16400 200 26000 39300; + B 4000 200 44000 39300; + B 4200 200 8100 39100; + B 16000 200 26000 39100; + B 4200 200 43900 39100; + B 4400 200 8200 38900; + B 15600 200 26000 38900; + B 4400 200 43800 38900; + B 4600 200 8300 38700; + B 15200 200 26000 38700; + B 4600 200 43700 38700; + B 4800 200 8400 38500; + B 14800 200 26000 38500; + B 4800 200 43600 38500; + B 5000 200 8500 38300; + B 14400 200 26000 38300; + B 5000 200 43500 38300; + B 5200 200 8600 38100; + B 14000 200 26000 38100; + B 5200 200 43400 38100; + B 5400 200 8700 37900; + B 13600 200 26000 37900; + B 5400 200 43300 37900; + B 5600 200 8800 37700; + B 13200 200 26000 37700; + B 5600 200 43200 37700; + B 5800 200 8900 37500; + B 12800 200 26000 37500; + B 5800 200 43100 37500; + B 6000 200 9000 37300; + B 12400 200 26000 37300; + B 6000 200 43000 37300; + B 6200 200 9100 37100; + B 6200 200 42900 37100; + B 6400 200 9200 36900; + B 6400 200 42800 36900; + B 6600 200 9300 36700; + B 6600 200 42700 36700; + B 6800 200 9400 36500; + B 6800 200 42600 36500; + B 7000 200 9500 36300; + B 7000 200 42500 36300; + B 7200 200 9600 36100; + B 7200 200 42400 36100; + B 7400 200 9700 35900; + B 7400 200 42300 35900; + B 7600 200 9800 35700; + B 7600 200 42200 35700; + B 7800 200 9900 35500; + B 7800 200 42100 35500; + B 8000 200 10000 35300; + B 8000 200 42000 35300; + B 8200 200 10100 35100; + B 8200 200 41900 35100; + B 8400 200 10200 34900; + B 8400 200 41800 34900; + B 8600 200 10300 34700; + B 8600 200 41700 34700; + B 8800 200 10400 34500; + B 8800 200 41600 34500; + B 9000 200 10500 34300; + B 9000 200 41500 34300; + B 9200 200 10600 34100; + B 9200 200 41400 34100; + B 9400 200 10700 33900; + B 9400 200 41300 33900; + B 9600 200 10800 33700; + B 9600 200 41200 33700; + B 9800 200 10900 33500; + B 9800 200 41100 33500; + B 10000 12400 11000 27200; + B 10000 12400 41000 27200; + B 9800 200 10900 20900; + B 9800 200 41100 20900; + B 9600 200 10800 20700; + B 9600 200 41200 20700; + B 9400 200 10700 20500; + B 9400 200 41300 20500; + B 9200 200 10600 20300; + B 9200 200 41400 20300; + B 9000 200 10500 20100; + B 9000 200 41500 20100; + B 8800 200 10400 19900; + B 8800 200 41600 19900; + B 8600 200 10300 19700; + B 8600 200 41700 19700; + B 8400 200 10200 19500; + B 8400 200 41800 19500; + B 8200 200 10100 19300; + B 8200 200 41900 19300; + B 8000 200 10000 19100; + B 8000 200 42000 19100; + B 7800 200 9900 18900; + B 7800 200 42100 18900; + B 7600 200 9800 18700; + B 7600 200 42200 18700; + B 7400 200 9700 18500; + B 7400 200 42300 18500; + B 7200 200 9600 18300; + B 7200 200 42400 18300; + B 7000 200 9500 18100; + B 7000 200 42500 18100; + B 6800 200 9400 17900; + B 6800 200 42600 17900; + B 6600 200 9300 17700; + B 6600 200 42700 17700; + B 6400 200 9200 17500; + B 6400 200 42800 17500; + B 6200 200 9100 17300; + B 6200 200 42900 17300; + B 6000 200 9000 17100; + B 12400 200 26000 17100; + B 6000 200 43000 17100; + B 5800 200 8900 16900; + B 12800 200 26000 16900; + B 5800 200 43100 16900; + B 5600 200 8800 16700; + B 13200 200 26000 16700; + B 5600 200 43200 16700; + B 5400 200 8700 16500; + B 13600 200 26000 16500; + B 5400 200 43300 16500; + B 5200 200 8600 16300; + B 14000 200 26000 16300; + B 5200 200 43400 16300; + B 5000 200 8500 16100; + B 14400 200 26000 16100; + B 5000 200 43500 16100; + B 4800 200 8400 15900; + B 14800 200 26000 15900; + B 4800 200 43600 15900; + B 4600 200 8300 15700; + B 15200 200 26000 15700; + B 4600 200 43700 15700; + B 4400 200 8200 15500; + B 15600 200 26000 15500; + B 4400 200 43800 15500; + B 4200 200 8100 15300; + B 16000 200 26000 15300; + B 4200 200 43900 15300; + B 4000 200 8000 15100; + B 16400 200 26000 15100; + B 4000 200 44000 15100; + B 3800 200 7900 14900; + B 16800 200 26000 14900; + B 3800 200 44100 14900; + B 3600 200 7800 14700; + B 17200 200 26000 14700; + B 3600 200 44200 14700; + B 3400 200 7700 14500; + B 17600 200 26000 14500; + B 3400 200 44300 14500; + B 3200 200 7600 14300; + B 18000 200 26000 14300; + B 3200 200 44400 14300; + B 3000 200 7500 14100; + B 18400 200 26000 14100; + B 3000 200 44500 14100; + B 2800 200 7400 13900; + B 18800 200 26000 13900; + B 2800 200 44600 13900; + B 2600 200 7300 13700; + B 19200 200 26000 13700; + B 2600 200 44700 13700; + B 2400 200 7200 13500; + B 19600 200 26000 13500; + B 2400 200 44800 13500; + B 2200 200 7100 13300; + B 20000 200 26000 13300; + B 2200 200 44900 13300; + B 2000 200 7000 13100; + B 20400 200 26000 13100; + B 2000 200 45000 13100; + B 1800 200 6900 12900; + B 20800 200 26000 12900; + B 1800 200 45100 12900; + B 1600 200 6800 12700; + B 21200 200 26000 12700; + B 1600 200 45200 12700; + B 1400 200 6700 12500; + B 21600 200 26000 12500; + B 1400 200 45300 12500; + B 1200 200 6600 12300; + B 22000 200 26000 12300; + B 1200 200 45400 12300; + B 1000 200 6500 12100; + B 22400 200 26000 12100; + B 1000 200 45500 12100; + B 800 200 6400 11900; + B 22800 200 26000 11900; + B 800 200 45600 11900; + B 600 200 6300 11700; + B 23200 200 26000 11700; + B 600 200 45700 11700; + B 400 200 6200 11500; + B 23600 200 26000 11500; + B 400 200 45800 11500; + B 200 200 6100 11300; + B 24000 200 26000 11300; + B 200 200 45900 11300; + B 24400 200 26000 11100; + B 24800 200 26000 10900; + B 25200 200 26000 10700; + B 25600 200 26000 10500; + B 26000 200 26000 10300; + B 26400 200 26000 10100; + B 26800 200 26000 9900; + B 27200 200 26000 9700; + B 27600 200 26000 9500; + B 28000 200 26000 9300; + B 28400 200 26000 9100; + B 28800 200 26000 8900; + B 29200 200 26000 8700; + B 29600 200 26000 8500; + B 30000 200 26000 8300; + B 30400 200 26000 8100; + B 30800 200 26000 7900; + B 31200 200 26000 7700; + B 31600 200 26000 7500; + B 32000 200 26000 7300; +L CCP; + B 400 400 51000 52200; + B 400 400 1000 2200; +L CSP; + B 42800 1000 25000 49100; + B 42600 200 24900 48500; + B 42400 200 24800 48300; + B 42200 200 24700 48100; + B 42000 200 24600 47900; + B 41800 200 24500 47700; + B 41600 200 24400 47500; + B 1000 200 47900 47500; + B 41400 200 24300 47300; + B 1200 200 47800 47300; + B 41200 200 24200 47100; + B 1400 200 47700 47100; + B 41000 200 24100 46900; + B 1600 200 47600 46900; + B 2800 38200 5000 27700; + B 1800 200 47500 46700; + B 2000 200 47400 46500; + B 2200 200 47300 46300; + B 2400 200 47200 46100; + B 2600 200 47100 45900; + B 2600 200 4900 8500; + B 2400 200 4800 8300; + B 2200 200 4700 8100; + B 2000 200 4600 7900; + B 1800 200 4500 7700; + B 2800 38200 47000 26700; + B 1600 200 4400 7500; + B 41000 200 27900 7500; + B 1400 200 4300 7300; + B 41200 200 27800 7300; + B 1200 200 4200 7100; + B 41400 200 27700 7100; + B 1000 200 4100 6900; + B 41600 200 27600 6900; + B 41800 200 27500 6700; + B 42000 200 27400 6500; + B 42200 200 27300 6300; + B 42400 200 27200 6100; + B 42600 200 27100 5900; + B 42800 1000 27000 5300; +L COG; + B 32000 200 26000 47100; + B 31600 200 26000 46900; + B 31200 200 26000 46700; + B 30800 200 26000 46500; + B 30400 200 26000 46300; + B 30000 200 26000 46100; + B 29600 200 26000 45900; + B 29200 200 26000 45700; + B 28800 200 26000 45500; + B 28400 200 26000 45300; + B 28000 200 26000 45100; + B 27600 200 26000 44900; + B 27200 200 26000 44700; + B 26800 200 26000 44500; + B 26400 200 26000 44300; + B 26000 200 26000 44100; + B 25600 200 26000 43900; + B 25200 200 26000 43700; + B 24800 200 26000 43500; + B 24400 200 26000 43300; + B 200 200 6100 43100; + B 24000 200 26000 43100; + B 200 200 45900 43100; + B 400 200 6200 42900; + B 23600 200 26000 42900; + B 400 200 45800 42900; + B 600 200 6300 42700; + B 23200 200 26000 42700; + B 600 200 45700 42700; + B 800 200 6400 42500; + B 22800 200 26000 42500; + B 800 200 45600 42500; + B 1000 200 6500 42300; + B 22400 200 26000 42300; + B 1000 200 45500 42300; + B 1200 200 6600 42100; + B 22000 200 26000 42100; + B 1200 200 45400 42100; + B 1400 200 6700 41900; + B 21600 200 26000 41900; + B 1400 200 45300 41900; + B 1600 200 6800 41700; + B 21200 200 26000 41700; + B 1600 200 45200 41700; + B 1800 200 6900 41500; + B 20800 200 26000 41500; + B 1800 200 45100 41500; + B 2000 200 7000 41300; + B 20400 200 26000 41300; + B 2000 200 45000 41300; + B 2200 200 7100 41100; + B 20000 200 26000 41100; + B 2200 200 44900 41100; + B 2400 200 7200 40900; + B 19600 200 26000 40900; + B 2400 200 44800 40900; + B 2600 200 7300 40700; + B 19200 200 26000 40700; + B 2600 200 44700 40700; + B 2800 200 7400 40500; + B 18800 200 26000 40500; + B 2800 200 44600 40500; + B 3000 200 7500 40300; + B 18400 200 26000 40300; + B 3000 200 44500 40300; + B 3200 200 7600 40100; + B 18000 200 26000 40100; + B 3200 200 44400 40100; + B 3400 200 7700 39900; + B 17600 200 26000 39900; + B 3400 200 44300 39900; + B 3600 200 7800 39700; + B 17200 200 26000 39700; + B 3600 200 44200 39700; + B 3800 200 7900 39500; + B 16800 200 26000 39500; + B 3800 200 44100 39500; + B 4000 200 8000 39300; + B 16400 200 26000 39300; + B 4000 200 44000 39300; + B 4200 200 8100 39100; + B 16000 200 26000 39100; + B 4200 200 43900 39100; + B 4400 200 8200 38900; + B 15600 200 26000 38900; + B 4400 200 43800 38900; + B 4600 200 8300 38700; + B 15200 200 26000 38700; + B 4600 200 43700 38700; + B 4800 200 8400 38500; + B 14800 200 26000 38500; + B 4800 200 43600 38500; + B 5000 200 8500 38300; + B 14400 200 26000 38300; + B 5000 200 43500 38300; + B 5200 200 8600 38100; + B 14000 200 26000 38100; + B 5200 200 43400 38100; + B 5400 200 8700 37900; + B 13600 200 26000 37900; + B 5400 200 43300 37900; + B 5600 200 8800 37700; + B 13200 200 26000 37700; + B 5600 200 43200 37700; + B 5800 200 8900 37500; + B 12800 200 26000 37500; + B 5800 200 43100 37500; + B 6000 200 9000 37300; + B 12400 200 26000 37300; + B 6000 200 43000 37300; + B 6200 200 9100 37100; + B 6200 200 42900 37100; + B 6400 200 9200 36900; + B 6400 200 42800 36900; + B 6600 200 9300 36700; + B 6600 200 42700 36700; + B 6800 200 9400 36500; + B 6800 200 42600 36500; + B 7000 200 9500 36300; + B 7000 200 42500 36300; + B 7200 200 9600 36100; + B 7200 200 42400 36100; + B 7400 200 9700 35900; + B 7400 200 42300 35900; + B 7600 200 9800 35700; + B 7600 200 42200 35700; + B 7800 200 9900 35500; + B 7800 200 42100 35500; + B 8000 200 10000 35300; + B 8000 200 42000 35300; + B 8200 200 10100 35100; + B 8200 200 41900 35100; + B 8400 200 10200 34900; + B 8400 200 41800 34900; + B 8600 200 10300 34700; + B 8600 200 41700 34700; + B 8800 200 10400 34500; + B 8800 200 41600 34500; + B 9000 200 10500 34300; + B 9000 200 41500 34300; + B 9200 200 10600 34100; + B 9400 200 10700 33900; + B 9600 200 10800 33700; + B 9800 200 10900 33500; + B 10000 12400 11000 27200; + B 5000 5000 21500 31700; + B 5000 5000 30500 31700; + B 9200 200 41400 34100; + B 9400 200 41300 33900; + B 9600 200 41200 33700; + B 9800 200 41100 33500; + B 9800 200 10900 20900; + B 9600 200 10800 20700; + B 9400 200 10700 20500; + B 9200 200 10600 20300; + B 5000 5000 21500 22700; + B 5000 5000 30500 22700; + B 10000 12400 41000 27200; + B 9800 200 41100 20900; + B 9600 200 41200 20700; + B 9400 200 41300 20500; + B 9200 200 41400 20300; + B 9000 200 10500 20100; + B 9000 200 41500 20100; + B 8800 200 10400 19900; + B 8800 200 41600 19900; + B 8600 200 10300 19700; + B 8600 200 41700 19700; + B 8400 200 10200 19500; + B 8400 200 41800 19500; + B 8200 200 10100 19300; + B 8200 200 41900 19300; + B 8000 200 10000 19100; + B 8000 200 42000 19100; + B 7800 200 9900 18900; + B 7800 200 42100 18900; + B 7600 200 9800 18700; + B 7600 200 42200 18700; + B 7400 200 9700 18500; + B 7400 200 42300 18500; + B 7200 200 9600 18300; + B 7200 200 42400 18300; + B 7000 200 9500 18100; + B 7000 200 42500 18100; + B 6800 200 9400 17900; + B 6800 200 42600 17900; + B 6600 200 9300 17700; + B 6600 200 42700 17700; + B 6400 200 9200 17500; + B 6400 200 42800 17500; + B 6200 200 9100 17300; + B 6200 200 42900 17300; + B 6000 200 9000 17100; + B 12400 200 26000 17100; + B 6000 200 43000 17100; + B 5800 200 8900 16900; + B 12800 200 26000 16900; + B 5800 200 43100 16900; + B 5600 200 8800 16700; + B 13200 200 26000 16700; + B 5600 200 43200 16700; + B 5400 200 8700 16500; + B 13600 200 26000 16500; + B 5400 200 43300 16500; + B 5200 200 8600 16300; + B 14000 200 26000 16300; + B 5200 200 43400 16300; + B 5000 200 8500 16100; + B 14400 200 26000 16100; + B 5000 200 43500 16100; + B 4800 200 8400 15900; + B 14800 200 26000 15900; + B 4800 200 43600 15900; + B 4600 200 8300 15700; + B 15200 200 26000 15700; + B 4600 200 43700 15700; + B 4400 200 8200 15500; + B 15600 200 26000 15500; + B 4400 200 43800 15500; + B 4200 200 8100 15300; + B 16000 200 26000 15300; + B 4200 200 43900 15300; + B 4000 200 8000 15100; + B 16400 200 26000 15100; + B 4000 200 44000 15100; + B 3800 200 7900 14900; + B 16800 200 26000 14900; + B 3800 200 44100 14900; + B 3600 200 7800 14700; + B 17200 200 26000 14700; + B 3600 200 44200 14700; + B 3400 200 7700 14500; + B 17600 200 26000 14500; + B 3400 200 44300 14500; + B 3200 200 7600 14300; + B 18000 200 26000 14300; + B 3200 200 44400 14300; + B 3000 200 7500 14100; + B 18400 200 26000 14100; + B 3000 200 44500 14100; + B 2800 200 7400 13900; + B 18800 200 26000 13900; + B 2800 200 44600 13900; + B 2600 200 7300 13700; + B 19200 200 26000 13700; + B 2600 200 44700 13700; + B 2400 200 7200 13500; + B 19600 200 26000 13500; + B 2400 200 44800 13500; + B 2200 200 7100 13300; + B 20000 200 26000 13300; + B 2200 200 44900 13300; + B 2000 200 7000 13100; + B 20400 200 26000 13100; + B 2000 200 45000 13100; + B 1800 200 6900 12900; + B 20800 200 26000 12900; + B 1800 200 45100 12900; + B 1600 200 6800 12700; + B 21200 200 26000 12700; + B 1600 200 45200 12700; + B 1400 200 6700 12500; + B 21600 200 26000 12500; + B 1400 200 45300 12500; + B 1200 200 6600 12300; + B 22000 200 26000 12300; + B 1200 200 45400 12300; + B 1000 200 6500 12100; + B 22400 200 26000 12100; + B 1000 200 45500 12100; + B 800 200 6400 11900; + B 22800 200 26000 11900; + B 800 200 45600 11900; + B 600 200 6300 11700; + B 23200 200 26000 11700; + B 600 200 45700 11700; + B 400 200 6200 11500; + B 23600 200 26000 11500; + B 400 200 45800 11500; + B 200 200 6100 11300; + B 24000 200 26000 11300; + B 200 200 45900 11300; + B 24400 200 26000 11100; + B 24800 200 26000 10900; + B 25200 200 26000 10700; + B 25600 200 26000 10500; + B 26000 200 26000 10300; + B 26400 200 26000 10100; + B 26800 200 26000 9900; + B 27200 200 26000 9700; + B 27600 200 26000 9500; + B 28000 200 26000 9300; + B 28400 200 26000 9100; + B 28800 200 26000 8900; + B 29200 200 26000 8700; + B 29600 200 26000 8500; + B 30000 200 26000 8300; + B 30400 200 26000 8100; + B 30800 200 26000 7900; + B 31200 200 26000 7700; + B 31600 200 26000 7500; + B 32000 200 26000 7300; +L COP; + B 32000 200 26000 47100; + B 31600 200 26000 46900; + B 31200 200 26000 46700; + B 30800 200 26000 46500; + B 30400 200 26000 46300; + B 30000 200 26000 46100; + B 29600 200 26000 45900; + B 29200 200 26000 45700; + B 28800 200 26000 45500; + B 28400 200 26000 45300; + B 28000 200 26000 45100; + B 27600 200 26000 44900; + B 27200 200 26000 44700; + B 26800 200 26000 44500; + B 26400 200 26000 44300; + B 26000 200 26000 44100; + B 25600 200 26000 43900; + B 25200 200 26000 43700; + B 24800 200 26000 43500; + B 24400 200 26000 43300; + B 200 200 6100 43100; + B 24000 200 26000 43100; + B 200 200 45900 43100; + B 400 200 6200 42900; + B 23600 200 26000 42900; + B 400 200 45800 42900; + B 600 200 6300 42700; + B 23200 200 26000 42700; + B 600 200 45700 42700; + B 800 200 6400 42500; + B 22800 200 26000 42500; + B 800 200 45600 42500; + B 1000 200 6500 42300; + B 22400 200 26000 42300; + B 1000 200 45500 42300; + B 1200 200 6600 42100; + B 22000 200 26000 42100; + B 1200 200 45400 42100; + B 1400 200 6700 41900; + B 21600 200 26000 41900; + B 1400 200 45300 41900; + B 1600 200 6800 41700; + B 21200 200 26000 41700; + B 1600 200 45200 41700; + B 1800 200 6900 41500; + B 20800 200 26000 41500; + B 1800 200 45100 41500; + B 2000 200 7000 41300; + B 20400 200 26000 41300; + B 2000 200 45000 41300; + B 2200 200 7100 41100; + B 20000 200 26000 41100; + B 2200 200 44900 41100; + B 2400 200 7200 40900; + B 19600 200 26000 40900; + B 2400 200 44800 40900; + B 2600 200 7300 40700; + B 19200 200 26000 40700; + B 2600 200 44700 40700; + B 2800 200 7400 40500; + B 18800 200 26000 40500; + B 2800 200 44600 40500; + B 3000 200 7500 40300; + B 18400 200 26000 40300; + B 3000 200 44500 40300; + B 3200 200 7600 40100; + B 18000 200 26000 40100; + B 3200 200 44400 40100; + B 3400 200 7700 39900; + B 17600 200 26000 39900; + B 3400 200 44300 39900; + B 3600 200 7800 39700; + B 17200 200 26000 39700; + B 3600 200 44200 39700; + B 3800 200 7900 39500; + B 16800 200 26000 39500; + B 3800 200 44100 39500; + B 4000 200 8000 39300; + B 16400 200 26000 39300; + B 4000 200 44000 39300; + B 4200 200 8100 39100; + B 16000 200 26000 39100; + B 4200 200 43900 39100; + B 4400 200 8200 38900; + B 15600 200 26000 38900; + B 4400 200 43800 38900; + B 4600 200 8300 38700; + B 15200 200 26000 38700; + B 4600 200 43700 38700; + B 4800 200 8400 38500; + B 14800 200 26000 38500; + B 4800 200 43600 38500; + B 5000 200 8500 38300; + B 14400 200 26000 38300; + B 5000 200 43500 38300; + B 5200 200 8600 38100; + B 14000 200 26000 38100; + B 5200 200 43400 38100; + B 5400 200 8700 37900; + B 13600 200 26000 37900; + B 5400 200 43300 37900; + B 5600 200 8800 37700; + B 13200 200 26000 37700; + B 5600 200 43200 37700; + B 5800 200 8900 37500; + B 12800 200 26000 37500; + B 5800 200 43100 37500; + B 6000 200 9000 37300; + B 12400 200 26000 37300; + B 6000 200 43000 37300; + B 6200 200 9100 37100; + B 6200 200 42900 37100; + B 6400 200 9200 36900; + B 6400 200 42800 36900; + B 6600 200 9300 36700; + B 6600 200 42700 36700; + B 6800 200 9400 36500; + B 6800 200 42600 36500; + B 7000 200 9500 36300; + B 7000 200 42500 36300; + B 7200 200 9600 36100; + B 7200 200 42400 36100; + B 7400 200 9700 35900; + B 7400 200 42300 35900; + B 7600 200 9800 35700; + B 7600 200 42200 35700; + B 7800 200 9900 35500; + B 7800 200 42100 35500; + B 8000 200 10000 35300; + B 8000 200 42000 35300; + B 8200 200 10100 35100; + B 8200 200 41900 35100; + B 8400 200 10200 34900; + B 8400 200 41800 34900; + B 8600 200 10300 34700; + B 8600 200 41700 34700; + B 8800 200 10400 34500; + B 8800 200 41600 34500; + B 9000 200 10500 34300; + B 9000 200 41500 34300; + B 9200 200 10600 34100; + B 9200 200 41400 34100; + B 9400 200 10700 33900; + B 9400 200 41300 33900; + B 9600 200 10800 33700; + B 9600 200 41200 33700; + B 9800 200 10900 33500; + B 9800 200 41100 33500; + B 10000 12400 11000 27200; + B 10000 12400 41000 27200; + B 9800 200 10900 20900; + B 9800 200 41100 20900; + B 9600 200 10800 20700; + B 9600 200 41200 20700; + B 9400 200 10700 20500; + B 9400 200 41300 20500; + B 9200 200 10600 20300; + B 9200 200 41400 20300; + B 9000 200 10500 20100; + B 9000 200 41500 20100; + B 8800 200 10400 19900; + B 8800 200 41600 19900; + B 8600 200 10300 19700; + B 8600 200 41700 19700; + B 8400 200 10200 19500; + B 8400 200 41800 19500; + B 8200 200 10100 19300; + B 8200 200 41900 19300; + B 8000 200 10000 19100; + B 8000 200 42000 19100; + B 7800 200 9900 18900; + B 7800 200 42100 18900; + B 7600 200 9800 18700; + B 7600 200 42200 18700; + B 7400 200 9700 18500; + B 7400 200 42300 18500; + B 7200 200 9600 18300; + B 7200 200 42400 18300; + B 7000 200 9500 18100; + B 7000 200 42500 18100; + B 6800 200 9400 17900; + B 6800 200 42600 17900; + B 6600 200 9300 17700; + B 6600 200 42700 17700; + B 6400 200 9200 17500; + B 6400 200 42800 17500; + B 6200 200 9100 17300; + B 6200 200 42900 17300; + B 6000 200 9000 17100; + B 12400 200 26000 17100; + B 6000 200 43000 17100; + B 5800 200 8900 16900; + B 12800 200 26000 16900; + B 5800 200 43100 16900; + B 5600 200 8800 16700; + B 13200 200 26000 16700; + B 5600 200 43200 16700; + B 5400 200 8700 16500; + B 13600 200 26000 16500; + B 5400 200 43300 16500; + B 5200 200 8600 16300; + B 14000 200 26000 16300; + B 5200 200 43400 16300; + B 5000 200 8500 16100; + B 14400 200 26000 16100; + B 5000 200 43500 16100; + B 4800 200 8400 15900; + B 14800 200 26000 15900; + B 4800 200 43600 15900; + B 4600 200 8300 15700; + B 15200 200 26000 15700; + B 4600 200 43700 15700; + B 4400 200 8200 15500; + B 15600 200 26000 15500; + B 4400 200 43800 15500; + B 4200 200 8100 15300; + B 16000 200 26000 15300; + B 4200 200 43900 15300; + B 4000 200 8000 15100; + B 16400 200 26000 15100; + B 4000 200 44000 15100; + B 3800 200 7900 14900; + B 16800 200 26000 14900; + B 3800 200 44100 14900; + B 3600 200 7800 14700; + B 17200 200 26000 14700; + B 3600 200 44200 14700; + B 3400 200 7700 14500; + B 17600 200 26000 14500; + B 3400 200 44300 14500; + B 3200 200 7600 14300; + B 18000 200 26000 14300; + B 3200 200 44400 14300; + B 3000 200 7500 14100; + B 18400 200 26000 14100; + B 3000 200 44500 14100; + B 2800 200 7400 13900; + B 18800 200 26000 13900; + B 2800 200 44600 13900; + B 2600 200 7300 13700; + B 19200 200 26000 13700; + B 2600 200 44700 13700; + B 2400 200 7200 13500; + B 19600 200 26000 13500; + B 2400 200 44800 13500; + B 2200 200 7100 13300; + B 20000 200 26000 13300; + B 2200 200 44900 13300; + B 2000 200 7000 13100; + B 20400 200 26000 13100; + B 2000 200 45000 13100; + B 1800 200 6900 12900; + B 20800 200 26000 12900; + B 1800 200 45100 12900; + B 1600 200 6800 12700; + B 21200 200 26000 12700; + B 1600 200 45200 12700; + B 1400 200 6700 12500; + B 21600 200 26000 12500; + B 1400 200 45300 12500; + B 1200 200 6600 12300; + B 22000 200 26000 12300; + B 1200 200 45400 12300; + B 1000 200 6500 12100; + B 22400 200 26000 12100; + B 1000 200 45500 12100; + B 800 200 6400 11900; + B 22800 200 26000 11900; + B 800 200 45600 11900; + B 600 200 6300 11700; + B 23200 200 26000 11700; + B 600 200 45700 11700; + B 400 200 6200 11500; + B 23600 200 26000 11500; + B 400 200 45800 11500; + B 200 200 6100 11300; + B 24000 200 26000 11300; + B 200 200 45900 11300; + B 24400 200 26000 11100; + B 24800 200 26000 10900; + B 25200 200 26000 10700; + B 25600 200 26000 10500; + B 26000 200 26000 10300; + B 26400 200 26000 10100; + B 26800 200 26000 9900; + B 27200 200 26000 9700; + B 27600 200 26000 9500; + B 28000 200 26000 9300; + B 28400 200 26000 9100; + B 28800 200 26000 8900; + B 29200 200 26000 8700; + B 29600 200 26000 8500; + B 30000 200 26000 8300; + B 30400 200 26000 8100; + B 30800 200 26000 7900; + B 31200 200 26000 7700; + B 31600 200 26000 7500; + B 32000 200 26000 7300; +L CPS; + B 42000 200 25000 49100; + B 41800 200 24900 48900; + B 41600 200 24800 48700; + B 41400 200 24700 48500; + B 41200 200 24600 48300; + B 41000 200 24500 48100; + B 40800 200 24400 47900; + B 40600 200 24300 47700; + B 40400 200 24200 47500; + B 40200 200 24100 47300; + B 2000 38200 5000 28100; + B 200 200 47900 47100; + B 400 200 47800 46900; + B 600 200 47700 46700; + B 800 200 47600 46500; + B 1000 200 47500 46300; + B 1200 200 47400 46100; + B 1400 200 47300 45900; + B 1600 200 47200 45700; + B 1800 200 47100 45500; + B 1800 200 4900 8900; + B 1600 200 4800 8700; + B 1400 200 4700 8500; + B 1200 200 4600 8300; + B 1000 200 4500 8100; + B 800 200 4400 7900; + B 600 200 4300 7700; + B 400 200 4200 7500; + B 200 200 4100 7300; + B 2000 38200 47000 26300; + B 40200 200 27900 7100; + B 40400 200 27800 6900; + B 40600 200 27700 6700; + B 40800 200 27600 6500; + B 41000 200 27500 6300; + B 41200 200 27400 6100; + B 41400 200 27300 5900; + B 41600 200 27200 5700; + B 41800 200 27100 5500; + B 42000 200 27000 5300; +DF; +C 1; +End diff --git a/scmos/examples/nist-mems-library/gas-sensor.mag b/scmos/examples/nist-mems-library/gas-sensor.mag new file mode 100644 index 00000000..c66cad09 --- /dev/null +++ b/scmos/examples/nist-mems-library/gas-sensor.mag @@ -0,0 +1,1101 @@ +magic +tech scmos +timestamp 760840948 +<< polysilicon >> +rect 250 265 260 266 +rect 249 264 260 265 +rect 248 263 260 264 +rect 247 262 253 263 +rect 246 261 253 262 +rect 245 260 253 261 +rect 244 259 253 260 +rect 257 259 260 263 +rect 243 258 260 259 +rect 242 257 260 258 +rect 241 256 260 257 +rect 240 255 259 256 +rect 239 254 258 255 +rect 238 253 257 254 +rect 237 252 256 253 +rect 236 251 255 252 +rect 235 250 254 251 +rect 234 249 253 250 +rect 233 248 252 249 +rect 232 247 251 248 +rect 231 246 250 247 +rect 230 245 249 246 +rect 229 244 248 245 +rect 228 243 247 244 +rect 227 242 246 243 +rect 226 241 245 242 +rect 225 240 244 241 +rect 224 239 243 240 +rect 223 238 242 239 +rect 222 237 241 238 +rect 221 236 240 237 +rect 220 235 239 236 +rect 219 234 238 235 +rect 218 233 237 234 +rect 217 232 236 233 +rect 216 231 235 232 +rect 215 230 234 231 +rect 214 229 233 230 +rect 213 228 232 229 +rect 212 227 231 228 +rect 211 226 230 227 +rect 210 225 229 226 +rect 209 224 228 225 +rect 208 223 227 224 +rect 207 222 226 223 +rect 206 221 225 222 +rect 205 220 224 221 +rect 204 219 223 220 +rect 203 218 222 219 +rect 202 217 221 218 +rect 201 216 220 217 +rect 200 215 219 216 +rect 199 214 218 215 +rect 198 213 217 214 +rect 197 212 216 213 +rect 196 211 215 212 +rect 195 210 214 211 +rect 194 209 213 210 +rect 193 208 212 209 +rect 192 207 211 208 +rect 191 206 210 207 +rect 190 205 209 206 +rect 189 204 208 205 +rect 188 203 207 204 +rect 187 202 206 203 +rect 186 201 205 202 +rect 185 200 204 201 +rect 184 199 203 200 +rect 183 198 202 199 +rect 182 197 201 198 +rect 181 196 200 197 +rect 180 195 199 196 +rect 179 194 198 195 +rect 178 193 197 194 +rect 177 192 196 193 +rect 176 191 195 192 +rect 175 190 194 191 +rect 174 189 193 190 +rect 173 188 192 189 +rect 172 187 191 188 +rect 171 186 190 187 +rect 170 185 189 186 +rect 169 184 188 185 +rect 168 183 187 184 +rect 167 182 186 183 +rect 166 181 185 182 +rect 165 180 184 181 +rect 164 179 183 180 +rect 163 178 182 179 +rect 162 177 181 178 +rect 162 176 180 177 +rect 90 175 179 176 +rect 90 174 178 175 +rect 90 173 177 174 +rect 90 172 176 173 +rect 90 171 175 172 +rect 90 170 174 171 +rect 90 169 173 170 +rect 90 168 172 169 +rect 90 164 98 168 +rect 90 156 170 164 +rect 162 152 170 156 +rect 90 144 170 152 +rect 90 140 98 144 +rect 90 132 170 140 +rect 162 128 170 132 +rect 90 120 170 128 +rect 90 116 98 120 +rect 90 108 170 116 +rect 162 104 170 108 +rect 88 103 170 104 +rect 87 102 170 103 +rect 86 101 170 102 +rect 85 100 170 101 +rect 84 99 170 100 +rect 83 98 170 99 +rect 82 97 170 98 +rect 81 96 170 97 +rect 80 95 98 96 +rect 79 94 98 95 +rect 78 93 97 94 +rect 77 92 96 93 +rect 76 91 95 92 +rect 75 90 94 91 +rect 74 89 93 90 +rect 73 88 92 89 +rect 72 87 91 88 +rect 71 86 90 87 +rect 70 85 89 86 +rect 69 84 88 85 +rect 68 83 87 84 +rect 67 82 86 83 +rect 66 81 85 82 +rect 65 80 84 81 +rect 64 79 83 80 +rect 63 78 82 79 +rect 62 77 81 78 +rect 61 76 80 77 +rect 60 75 79 76 +rect 59 74 78 75 +rect 58 73 77 74 +rect 57 72 76 73 +rect 56 71 75 72 +rect 55 70 74 71 +rect 54 69 73 70 +rect 53 68 72 69 +rect 52 67 71 68 +rect 51 66 70 67 +rect 50 65 69 66 +rect 49 64 68 65 +rect 48 63 67 64 +rect 47 62 66 63 +rect 46 61 65 62 +rect 45 60 64 61 +rect 44 59 63 60 +rect 43 58 62 59 +rect 42 57 61 58 +rect 41 56 60 57 +rect 40 55 59 56 +rect 39 54 58 55 +rect 38 53 57 54 +rect 37 52 56 53 +rect 36 51 55 52 +rect 35 50 54 51 +rect 34 49 53 50 +rect 33 48 52 49 +rect 32 47 51 48 +rect 31 46 50 47 +rect 30 45 49 46 +rect 29 44 48 45 +rect 28 43 47 44 +rect 27 42 46 43 +rect 26 41 45 42 +rect 25 40 44 41 +rect 24 39 43 40 +rect 23 38 42 39 +rect 22 37 41 38 +rect 21 36 40 37 +rect 20 35 39 36 +rect 19 34 38 35 +rect 18 33 37 34 +rect 17 32 36 33 +rect 16 31 35 32 +rect 15 30 34 31 +rect 14 29 33 30 +rect 13 28 32 29 +rect 12 27 31 28 +rect 11 26 30 27 +rect 10 25 29 26 +rect 9 24 28 25 +rect 8 23 27 24 +rect 7 22 26 23 +rect 6 21 25 22 +rect 5 20 24 21 +rect 4 19 23 20 +rect 3 18 22 19 +rect 2 17 21 18 +rect 1 16 20 17 +rect 0 15 19 16 +rect 0 14 18 15 +rect 0 13 17 14 +rect 0 9 3 13 +rect 7 12 16 13 +rect 7 11 15 12 +rect 7 10 14 11 +rect 7 9 13 10 +rect 0 8 12 9 +rect 0 7 11 8 +rect 0 6 10 7 +<< metal1 >> +rect 250 263 260 266 +rect 250 259 253 263 +rect 257 259 260 263 +rect 250 256 260 259 +rect 0 240 30 246 +rect 230 240 260 246 +rect 0 239 31 240 +rect 229 239 260 240 +rect 0 238 32 239 +rect 228 238 260 239 +rect 0 237 33 238 +rect 227 237 260 238 +rect 0 236 34 237 +rect 226 236 260 237 +rect 26 235 35 236 +rect 225 235 234 236 +rect 27 234 36 235 +rect 224 234 233 235 +rect 28 233 37 234 +rect 223 233 232 234 +rect 29 232 38 233 +rect 222 232 231 233 +rect 30 231 39 232 +rect 221 231 230 232 +rect 31 230 40 231 +rect 220 230 229 231 +rect 32 229 41 230 +rect 219 229 228 230 +rect 33 228 42 229 +rect 218 228 227 229 +rect 34 227 43 228 +rect 217 227 226 228 +rect 35 226 44 227 +rect 216 226 225 227 +rect 36 225 45 226 +rect 215 225 224 226 +rect 37 224 46 225 +rect 214 224 223 225 +rect 38 223 47 224 +rect 213 223 222 224 +rect 39 222 48 223 +rect 212 222 221 223 +rect 40 221 49 222 +rect 211 221 220 222 +rect 41 220 50 221 +rect 210 220 219 221 +rect 42 219 51 220 +rect 209 219 218 220 +rect 43 218 52 219 +rect 208 218 217 219 +rect 44 217 53 218 +rect 207 217 216 218 +rect 45 216 54 217 +rect 206 216 215 217 +rect 46 215 55 216 +rect 205 215 214 216 +rect 47 214 56 215 +rect 204 214 213 215 +rect 48 213 57 214 +rect 203 213 212 214 +rect 49 212 58 213 +rect 202 212 211 213 +rect 50 211 59 212 +rect 201 211 210 212 +rect 51 210 60 211 +rect 200 210 209 211 +rect 52 209 61 210 +rect 199 209 208 210 +rect 53 208 62 209 +rect 198 208 207 209 +rect 54 207 63 208 +rect 197 207 206 208 +rect 55 206 64 207 +rect 196 206 205 207 +rect 56 205 65 206 +rect 195 205 204 206 +rect 57 204 66 205 +rect 194 204 203 205 +rect 58 203 67 204 +rect 193 203 202 204 +rect 59 202 68 203 +rect 192 202 201 203 +rect 60 201 69 202 +rect 191 201 200 202 +rect 61 200 70 201 +rect 190 200 199 201 +rect 62 199 71 200 +rect 189 199 198 200 +rect 63 198 72 199 +rect 188 198 197 199 +rect 64 197 73 198 +rect 187 197 196 198 +rect 65 196 74 197 +rect 186 196 195 197 +rect 66 195 75 196 +rect 185 195 194 196 +rect 67 194 76 195 +rect 184 194 193 195 +rect 68 193 77 194 +rect 183 193 192 194 +rect 69 192 78 193 +rect 182 192 191 193 +rect 70 191 79 192 +rect 181 191 190 192 +rect 71 190 80 191 +rect 180 190 189 191 +rect 72 189 81 190 +rect 179 189 188 190 +rect 73 188 82 189 +rect 178 188 187 189 +rect 74 187 83 188 +rect 177 187 186 188 +rect 75 186 84 187 +rect 176 186 185 187 +rect 76 185 85 186 +rect 175 185 184 186 +rect 77 184 86 185 +rect 174 184 183 185 +rect 78 183 87 184 +rect 173 183 182 184 +rect 79 182 88 183 +rect 172 182 181 183 +rect 80 181 89 182 +rect 171 181 180 182 +rect 81 180 179 181 +rect 82 179 178 180 +rect 83 178 177 179 +rect 84 177 176 178 +rect 85 95 175 177 +rect 84 94 176 95 +rect 83 93 177 94 +rect 82 92 178 93 +rect 81 91 179 92 +rect 80 90 89 91 +rect 171 90 180 91 +rect 79 89 88 90 +rect 172 89 181 90 +rect 78 88 87 89 +rect 173 88 182 89 +rect 77 87 86 88 +rect 174 87 183 88 +rect 76 86 85 87 +rect 175 86 184 87 +rect 75 85 84 86 +rect 176 85 185 86 +rect 74 84 83 85 +rect 177 84 186 85 +rect 73 83 82 84 +rect 178 83 187 84 +rect 72 82 81 83 +rect 179 82 188 83 +rect 71 81 80 82 +rect 180 81 189 82 +rect 70 80 79 81 +rect 181 80 190 81 +rect 69 79 78 80 +rect 182 79 191 80 +rect 68 78 77 79 +rect 183 78 192 79 +rect 67 77 76 78 +rect 184 77 193 78 +rect 66 76 75 77 +rect 185 76 194 77 +rect 65 75 74 76 +rect 186 75 195 76 +rect 64 74 73 75 +rect 187 74 196 75 +rect 63 73 72 74 +rect 188 73 197 74 +rect 62 72 71 73 +rect 189 72 198 73 +rect 61 71 70 72 +rect 190 71 199 72 +rect 60 70 69 71 +rect 191 70 200 71 +rect 59 69 68 70 +rect 192 69 201 70 +rect 58 68 67 69 +rect 193 68 202 69 +rect 57 67 66 68 +rect 194 67 203 68 +rect 56 66 65 67 +rect 195 66 204 67 +rect 55 65 64 66 +rect 196 65 205 66 +rect 54 64 63 65 +rect 197 64 206 65 +rect 53 63 62 64 +rect 198 63 207 64 +rect 52 62 61 63 +rect 199 62 208 63 +rect 51 61 60 62 +rect 200 61 209 62 +rect 50 60 59 61 +rect 201 60 210 61 +rect 49 59 58 60 +rect 202 59 211 60 +rect 48 58 57 59 +rect 203 58 212 59 +rect 47 57 56 58 +rect 204 57 213 58 +rect 46 56 55 57 +rect 205 56 214 57 +rect 45 55 54 56 +rect 206 55 215 56 +rect 44 54 53 55 +rect 207 54 216 55 +rect 43 53 52 54 +rect 208 53 217 54 +rect 42 52 51 53 +rect 209 52 218 53 +rect 41 51 50 52 +rect 210 51 219 52 +rect 40 50 49 51 +rect 211 50 220 51 +rect 39 49 48 50 +rect 212 49 221 50 +rect 38 48 47 49 +rect 213 48 222 49 +rect 37 47 46 48 +rect 214 47 223 48 +rect 36 46 45 47 +rect 215 46 224 47 +rect 35 45 44 46 +rect 216 45 225 46 +rect 34 44 43 45 +rect 217 44 226 45 +rect 33 43 42 44 +rect 218 43 227 44 +rect 32 42 41 43 +rect 219 42 228 43 +rect 31 41 40 42 +rect 220 41 229 42 +rect 30 40 39 41 +rect 221 40 230 41 +rect 29 39 38 40 +rect 222 39 231 40 +rect 28 38 37 39 +rect 223 38 232 39 +rect 27 37 36 38 +rect 224 37 233 38 +rect 26 36 35 37 +rect 225 36 234 37 +rect 0 35 34 36 +rect 226 35 260 36 +rect 0 34 33 35 +rect 227 34 260 35 +rect 0 33 32 34 +rect 228 33 260 34 +rect 0 32 31 33 +rect 229 32 260 33 +rect 0 26 30 32 +rect 230 26 260 32 +rect 0 13 10 16 +rect 0 9 3 13 +rect 7 9 10 13 +rect 0 0 10 9 +<< metal2 >> +rect 20 240 30 266 +rect 230 240 240 266 +rect 20 239 31 240 +rect 229 239 240 240 +rect 20 238 32 239 +rect 228 238 240 239 +rect 20 237 33 238 +rect 227 237 240 238 +rect 20 236 34 237 +rect 226 236 240 237 +rect 26 235 35 236 +rect 225 235 234 236 +rect 27 234 36 235 +rect 224 234 233 235 +rect 28 233 37 234 +rect 223 233 232 234 +rect 29 232 38 233 +rect 222 232 231 233 +rect 30 231 39 232 +rect 221 231 230 232 +rect 31 230 40 231 +rect 220 230 229 231 +rect 32 229 41 230 +rect 219 229 228 230 +rect 33 228 42 229 +rect 218 228 227 229 +rect 34 227 43 228 +rect 217 227 226 228 +rect 35 226 44 227 +rect 216 226 225 227 +rect 36 225 45 226 +rect 215 225 224 226 +rect 37 224 46 225 +rect 214 224 223 225 +rect 38 223 47 224 +rect 213 223 222 224 +rect 39 222 48 223 +rect 212 222 221 223 +rect 40 221 49 222 +rect 211 221 220 222 +rect 41 220 50 221 +rect 210 220 219 221 +rect 42 219 51 220 +rect 209 219 218 220 +rect 43 218 52 219 +rect 208 218 217 219 +rect 44 217 53 218 +rect 207 217 216 218 +rect 45 216 54 217 +rect 206 216 215 217 +rect 46 215 55 216 +rect 205 215 214 216 +rect 47 214 56 215 +rect 204 214 213 215 +rect 48 213 57 214 +rect 203 213 212 214 +rect 49 212 58 213 +rect 202 212 211 213 +rect 50 211 59 212 +rect 201 211 210 212 +rect 51 210 60 211 +rect 200 210 209 211 +rect 52 209 61 210 +rect 199 209 208 210 +rect 53 208 62 209 +rect 198 208 207 209 +rect 54 207 63 208 +rect 197 207 206 208 +rect 55 206 64 207 +rect 196 206 205 207 +rect 56 205 65 206 +rect 195 205 204 206 +rect 57 204 66 205 +rect 194 204 203 205 +rect 58 203 67 204 +rect 193 203 202 204 +rect 59 202 68 203 +rect 192 202 201 203 +rect 60 201 69 202 +rect 191 201 200 202 +rect 61 200 70 201 +rect 190 200 199 201 +rect 62 199 71 200 +rect 189 199 198 200 +rect 63 198 72 199 +rect 188 198 197 199 +rect 64 197 73 198 +rect 187 197 196 198 +rect 65 196 74 197 +rect 186 196 195 197 +rect 66 195 75 196 +rect 185 195 194 196 +rect 67 194 76 195 +rect 184 194 193 195 +rect 68 193 77 194 +rect 183 193 192 194 +rect 69 192 78 193 +rect 182 192 191 193 +rect 70 191 79 192 +rect 181 191 190 192 +rect 71 190 80 191 +rect 180 190 189 191 +rect 72 189 81 190 +rect 179 189 188 190 +rect 73 188 82 189 +rect 178 188 187 189 +rect 74 187 83 188 +rect 177 187 186 188 +rect 75 186 84 187 +rect 176 186 185 187 +rect 76 185 85 186 +rect 175 185 184 186 +rect 77 184 86 185 +rect 174 184 183 185 +rect 78 183 87 184 +rect 173 183 182 184 +rect 79 182 88 183 +rect 172 182 181 183 +rect 80 181 89 182 +rect 171 181 180 182 +rect 81 180 90 181 +rect 170 180 179 181 +rect 82 179 91 180 +rect 169 179 178 180 +rect 83 178 92 179 +rect 168 178 177 179 +rect 84 177 93 178 +rect 167 177 176 178 +rect 85 176 94 177 +rect 166 176 175 177 +rect 86 175 125 176 +rect 87 174 125 175 +rect 88 173 125 174 +rect 89 172 125 173 +rect 90 141 125 172 +rect 135 175 174 176 +rect 135 174 173 175 +rect 135 173 172 174 +rect 135 172 171 173 +rect 135 141 170 172 +rect 90 100 125 131 +rect 89 99 125 100 +rect 88 98 125 99 +rect 87 97 125 98 +rect 86 96 125 97 +rect 135 100 170 131 +rect 135 99 171 100 +rect 135 98 172 99 +rect 135 97 173 98 +rect 135 96 174 97 +rect 85 95 94 96 +rect 166 95 175 96 +rect 84 94 93 95 +rect 167 94 176 95 +rect 83 93 92 94 +rect 168 93 177 94 +rect 82 92 91 93 +rect 169 92 178 93 +rect 81 91 90 92 +rect 170 91 179 92 +rect 80 90 89 91 +rect 171 90 180 91 +rect 79 89 88 90 +rect 172 89 181 90 +rect 78 88 87 89 +rect 173 88 182 89 +rect 77 87 86 88 +rect 174 87 183 88 +rect 76 86 85 87 +rect 175 86 184 87 +rect 75 85 84 86 +rect 176 85 185 86 +rect 74 84 83 85 +rect 177 84 186 85 +rect 73 83 82 84 +rect 178 83 187 84 +rect 72 82 81 83 +rect 179 82 188 83 +rect 71 81 80 82 +rect 180 81 189 82 +rect 70 80 79 81 +rect 181 80 190 81 +rect 69 79 78 80 +rect 182 79 191 80 +rect 68 78 77 79 +rect 183 78 192 79 +rect 67 77 76 78 +rect 184 77 193 78 +rect 66 76 75 77 +rect 185 76 194 77 +rect 65 75 74 76 +rect 186 75 195 76 +rect 64 74 73 75 +rect 187 74 196 75 +rect 63 73 72 74 +rect 188 73 197 74 +rect 62 72 71 73 +rect 189 72 198 73 +rect 61 71 70 72 +rect 190 71 199 72 +rect 60 70 69 71 +rect 191 70 200 71 +rect 59 69 68 70 +rect 192 69 201 70 +rect 58 68 67 69 +rect 193 68 202 69 +rect 57 67 66 68 +rect 194 67 203 68 +rect 56 66 65 67 +rect 195 66 204 67 +rect 55 65 64 66 +rect 196 65 205 66 +rect 54 64 63 65 +rect 197 64 206 65 +rect 53 63 62 64 +rect 198 63 207 64 +rect 52 62 61 63 +rect 199 62 208 63 +rect 51 61 60 62 +rect 200 61 209 62 +rect 50 60 59 61 +rect 201 60 210 61 +rect 49 59 58 60 +rect 202 59 211 60 +rect 48 58 57 59 +rect 203 58 212 59 +rect 47 57 56 58 +rect 204 57 213 58 +rect 46 56 55 57 +rect 205 56 214 57 +rect 45 55 54 56 +rect 206 55 215 56 +rect 44 54 53 55 +rect 207 54 216 55 +rect 43 53 52 54 +rect 208 53 217 54 +rect 42 52 51 53 +rect 209 52 218 53 +rect 41 51 50 52 +rect 210 51 219 52 +rect 40 50 49 51 +rect 211 50 220 51 +rect 39 49 48 50 +rect 212 49 221 50 +rect 38 48 47 49 +rect 213 48 222 49 +rect 37 47 46 48 +rect 214 47 223 48 +rect 36 46 45 47 +rect 215 46 224 47 +rect 35 45 44 46 +rect 216 45 225 46 +rect 34 44 43 45 +rect 217 44 226 45 +rect 33 43 42 44 +rect 218 43 227 44 +rect 32 42 41 43 +rect 219 42 228 43 +rect 31 41 40 42 +rect 220 41 229 42 +rect 30 40 39 41 +rect 221 40 230 41 +rect 29 39 38 40 +rect 222 39 231 40 +rect 28 38 37 39 +rect 223 38 232 39 +rect 27 37 36 38 +rect 224 37 233 38 +rect 26 36 35 37 +rect 225 36 234 37 +rect 20 35 34 36 +rect 226 35 240 36 +rect 20 34 33 35 +rect 227 34 240 35 +rect 20 33 32 34 +rect 228 33 240 34 +rect 20 32 31 33 +rect 229 32 240 33 +rect 20 6 30 32 +rect 230 6 240 32 +<< polycontact >> +rect 253 259 257 263 +rect 3 9 7 13 +<< substrateopen >> +rect 50 235 210 236 +rect 51 234 209 235 +rect 52 233 208 234 +rect 53 232 207 233 +rect 54 231 206 232 +rect 55 230 205 231 +rect 56 229 204 230 +rect 57 228 203 229 +rect 58 227 202 228 +rect 59 226 201 227 +rect 60 225 200 226 +rect 61 224 199 225 +rect 62 223 198 224 +rect 63 222 197 223 +rect 64 221 196 222 +rect 65 220 195 221 +rect 66 219 194 220 +rect 67 218 193 219 +rect 68 217 192 218 +rect 69 216 191 217 +rect 30 215 31 216 +rect 70 215 190 216 +rect 229 215 230 216 +rect 30 214 32 215 +rect 71 214 189 215 +rect 228 214 230 215 +rect 30 213 33 214 +rect 72 213 188 214 +rect 227 213 230 214 +rect 30 212 34 213 +rect 73 212 187 213 +rect 226 212 230 213 +rect 30 211 35 212 +rect 74 211 186 212 +rect 225 211 230 212 +rect 30 210 36 211 +rect 75 210 185 211 +rect 224 210 230 211 +rect 30 209 37 210 +rect 76 209 184 210 +rect 223 209 230 210 +rect 30 208 38 209 +rect 77 208 183 209 +rect 222 208 230 209 +rect 30 207 39 208 +rect 78 207 182 208 +rect 221 207 230 208 +rect 30 206 40 207 +rect 79 206 181 207 +rect 220 206 230 207 +rect 30 205 41 206 +rect 80 205 180 206 +rect 219 205 230 206 +rect 30 204 42 205 +rect 81 204 179 205 +rect 218 204 230 205 +rect 30 203 43 204 +rect 82 203 178 204 +rect 217 203 230 204 +rect 30 202 44 203 +rect 83 202 177 203 +rect 216 202 230 203 +rect 30 201 45 202 +rect 84 201 176 202 +rect 215 201 230 202 +rect 30 200 46 201 +rect 85 200 175 201 +rect 214 200 230 201 +rect 30 199 47 200 +rect 86 199 174 200 +rect 213 199 230 200 +rect 30 198 48 199 +rect 87 198 173 199 +rect 212 198 230 199 +rect 30 197 49 198 +rect 88 197 172 198 +rect 211 197 230 198 +rect 30 196 50 197 +rect 89 196 171 197 +rect 210 196 230 197 +rect 30 195 51 196 +rect 90 195 170 196 +rect 209 195 230 196 +rect 30 194 52 195 +rect 91 194 169 195 +rect 208 194 230 195 +rect 30 193 53 194 +rect 92 193 168 194 +rect 207 193 230 194 +rect 30 192 54 193 +rect 93 192 167 193 +rect 206 192 230 193 +rect 30 191 55 192 +rect 94 191 166 192 +rect 205 191 230 192 +rect 30 190 56 191 +rect 95 190 165 191 +rect 204 190 230 191 +rect 30 189 57 190 +rect 96 189 164 190 +rect 203 189 230 190 +rect 30 188 58 189 +rect 97 188 163 189 +rect 202 188 230 189 +rect 30 187 59 188 +rect 98 187 162 188 +rect 201 187 230 188 +rect 30 186 60 187 +rect 99 186 161 187 +rect 200 186 230 187 +rect 30 185 61 186 +rect 199 185 230 186 +rect 30 184 62 185 +rect 198 184 230 185 +rect 30 183 63 184 +rect 197 183 230 184 +rect 30 182 64 183 +rect 196 182 230 183 +rect 30 181 65 182 +rect 195 181 230 182 +rect 30 180 66 181 +rect 194 180 230 181 +rect 30 179 67 180 +rect 193 179 230 180 +rect 30 178 68 179 +rect 192 178 230 179 +rect 30 177 69 178 +rect 191 177 230 178 +rect 30 176 70 177 +rect 190 176 230 177 +rect 30 175 71 176 +rect 189 175 230 176 +rect 30 174 72 175 +rect 188 174 230 175 +rect 30 173 73 174 +rect 187 173 230 174 +rect 30 172 74 173 +rect 186 172 230 173 +rect 30 171 75 172 +rect 185 171 230 172 +rect 30 170 76 171 +rect 30 169 77 170 +rect 30 168 78 169 +rect 30 167 79 168 +rect 30 105 80 167 +rect 184 170 230 171 +rect 183 169 230 170 +rect 182 168 230 169 +rect 181 167 230 168 +rect 30 104 79 105 +rect 30 103 78 104 +rect 30 102 77 103 +rect 30 101 76 102 +rect 180 105 230 167 +rect 181 104 230 105 +rect 182 103 230 104 +rect 183 102 230 103 +rect 184 101 230 102 +rect 30 100 75 101 +rect 185 100 230 101 +rect 30 99 74 100 +rect 186 99 230 100 +rect 30 98 73 99 +rect 187 98 230 99 +rect 30 97 72 98 +rect 188 97 230 98 +rect 30 96 71 97 +rect 189 96 230 97 +rect 30 95 70 96 +rect 190 95 230 96 +rect 30 94 69 95 +rect 191 94 230 95 +rect 30 93 68 94 +rect 192 93 230 94 +rect 30 92 67 93 +rect 193 92 230 93 +rect 30 91 66 92 +rect 194 91 230 92 +rect 30 90 65 91 +rect 195 90 230 91 +rect 30 89 64 90 +rect 196 89 230 90 +rect 30 88 63 89 +rect 197 88 230 89 +rect 30 87 62 88 +rect 198 87 230 88 +rect 30 86 61 87 +rect 199 86 230 87 +rect 30 85 60 86 +rect 99 85 161 86 +rect 200 85 230 86 +rect 30 84 59 85 +rect 98 84 162 85 +rect 201 84 230 85 +rect 30 83 58 84 +rect 97 83 163 84 +rect 202 83 230 84 +rect 30 82 57 83 +rect 96 82 164 83 +rect 203 82 230 83 +rect 30 81 56 82 +rect 95 81 165 82 +rect 204 81 230 82 +rect 30 80 55 81 +rect 94 80 166 81 +rect 205 80 230 81 +rect 30 79 54 80 +rect 93 79 167 80 +rect 206 79 230 80 +rect 30 78 53 79 +rect 92 78 168 79 +rect 207 78 230 79 +rect 30 77 52 78 +rect 91 77 169 78 +rect 208 77 230 78 +rect 30 76 51 77 +rect 90 76 170 77 +rect 209 76 230 77 +rect 30 75 50 76 +rect 89 75 171 76 +rect 210 75 230 76 +rect 30 74 49 75 +rect 88 74 172 75 +rect 211 74 230 75 +rect 30 73 48 74 +rect 87 73 173 74 +rect 212 73 230 74 +rect 30 72 47 73 +rect 86 72 174 73 +rect 213 72 230 73 +rect 30 71 46 72 +rect 85 71 175 72 +rect 214 71 230 72 +rect 30 70 45 71 +rect 84 70 176 71 +rect 215 70 230 71 +rect 30 69 44 70 +rect 83 69 177 70 +rect 216 69 230 70 +rect 30 68 43 69 +rect 82 68 178 69 +rect 217 68 230 69 +rect 30 67 42 68 +rect 81 67 179 68 +rect 218 67 230 68 +rect 30 66 41 67 +rect 80 66 180 67 +rect 219 66 230 67 +rect 30 65 40 66 +rect 79 65 181 66 +rect 220 65 230 66 +rect 30 64 39 65 +rect 78 64 182 65 +rect 221 64 230 65 +rect 30 63 38 64 +rect 77 63 183 64 +rect 222 63 230 64 +rect 30 62 37 63 +rect 76 62 184 63 +rect 223 62 230 63 +rect 30 61 36 62 +rect 75 61 185 62 +rect 224 61 230 62 +rect 30 60 35 61 +rect 74 60 186 61 +rect 225 60 230 61 +rect 30 59 34 60 +rect 73 59 187 60 +rect 226 59 230 60 +rect 30 58 33 59 +rect 72 58 188 59 +rect 227 58 230 59 +rect 30 57 32 58 +rect 71 57 189 58 +rect 228 57 230 58 +rect 30 56 31 57 +rect 70 56 190 57 +rect 229 56 230 57 +rect 69 55 191 56 +rect 68 54 192 55 +rect 67 53 193 54 +rect 66 52 194 53 +rect 65 51 195 52 +rect 64 50 196 51 +rect 63 49 197 50 +rect 62 48 198 49 +rect 61 47 199 48 +rect 60 46 200 47 +rect 59 45 201 46 +rect 58 44 202 45 +rect 57 43 203 44 +rect 56 42 204 43 +rect 55 41 205 42 +rect 54 40 206 41 +rect 53 39 207 40 +rect 52 38 208 39 +rect 51 37 209 38 +rect 50 36 210 37 +<< pdiffusionstop >> +rect 20 245 230 246 +rect 20 244 229 245 +rect 20 243 228 244 +rect 20 242 227 243 +rect 20 241 226 242 +rect 20 240 225 241 +rect 20 239 224 240 +rect 20 238 223 239 +rect 20 237 222 238 +rect 20 236 221 237 +rect 20 45 30 236 +rect 239 235 240 236 +rect 238 234 240 235 +rect 237 233 240 234 +rect 236 232 240 233 +rect 235 231 240 232 +rect 234 230 240 231 +rect 233 229 240 230 +rect 232 228 240 229 +rect 231 227 240 228 +rect 20 44 29 45 +rect 20 43 28 44 +rect 20 42 27 43 +rect 20 41 26 42 +rect 20 40 25 41 +rect 20 39 24 40 +rect 20 38 23 39 +rect 20 37 22 38 +rect 20 36 21 37 +rect 230 36 240 227 +rect 39 35 240 36 +rect 38 34 240 35 +rect 37 33 240 34 +rect 36 32 240 33 +rect 35 31 240 32 +rect 34 30 240 31 +rect 33 29 240 30 +rect 32 28 240 29 +rect 31 27 240 28 +rect 30 26 240 27 +<< glass >> +rect 95 146 120 171 +rect 140 146 165 171 +rect 95 101 120 126 +rect 140 101 165 126 +<< end >> diff --git a/scmos/examples/nist-mems-library/memslib.cif b/scmos/examples/nist-mems-library/memslib.cif new file mode 100644 index 00000000..fde3825e --- /dev/null +++ b/scmos/examples/nist-mems-library/memslib.cif @@ -0,0 +1,718 @@ +DS 1 1 2; +9 memslib; +L CMF; + B 10000 2000 26000 43000; + B 2000 8000 22000 38000; + B 2000 8000 26000 38000; + B 2000 8000 30000 38000; + B 6000 2000 36000 43000; + B 10000 2000 46000 43000; + B 2000 2000 34000 41000; + B 4000 2000 35000 39000; + B 2000 2000 34000 37000; + B 6000 2000 36000 35000; + B 2000 8000 42000 38000; + B 2000 8000 46000 38000; + B 2000 8000 50000 38000; + B 6000 2000 56000 43000; + B 2000 2000 54000 41000; + B 6000 2000 56000 39000; + B 2000 2000 58000 37000; + B 6000 2000 56000 35000; + B 2000 8000 70000 40000; + B 6000 2000 80000 43000; + B 6000 2000 88000 43000; + B 2000 6000 80000 39000; + B 2000 2000 86000 41000; + B 2000 2000 90000 41000; + B 6000 2000 88000 39000; + B 2000 2000 86000 37000; + B 2000 2000 90000 37000; + B 6000 2000 72000 35000; + B 6000 2000 80000 35000; + B 6000 2000 88000 35000; + B 5000 1000 95500 43500; + B 6000 1000 96000 42500; + B 2000 2000 94000 41000; + B 2000 2000 98000 41000; + B 6000 2000 104000 43000; + B 2000 2000 102000 41000; + B 2000 2000 106000 41000; + B 5000 2000 95500 39000; + B 6000 2000 104000 39000; + B 2000 4000 94000 36000; + B 2000 4000 98000 36000; + B 2000 4000 102000 36000; + B 2000 4000 106000 36000; + B 5000 1000 111500 43500; + B 6000 1000 112000 42500; + B 2000 2000 110000 41000; + B 2000 2000 114000 41000; + B 2000 4000 118000 42000; + B 2000 4000 122000 42000; + B 5000 2000 111500 39000; + B 6000 2000 120000 39000; + B 2000 4000 110000 36000; + B 2000 4000 114000 36000; + B 2000 4000 120000 36000; +L CPG; + B 4000 200 16400 98500; + B 4200 200 16300 98300; + B 4600 200 16300 98100; + B 4800 200 16200 97900; + B 5200 200 16200 97700; + B 5400 200 16100 97500; + B 5800 200 16100 97300; + B 6000 200 16000 97100; + B 6400 200 16000 96900; + B 6600 200 15900 96700; + B 7000 200 15900 96500; + B 7200 200 15800 96300; + B 7600 200 15800 96100; + B 7800 200 15700 95900; + B 8200 200 15700 95700; + B 8400 200 15600 95500; + B 8800 200 15600 95300; + B 9000 200 15500 95100; + B 9400 200 15500 94900; + B 9600 200 15400 94700; + B 10000 400 15400 94400; + B 10200 400 15500 94000; + B 10400 400 15600 93600; + B 10600 400 15700 93200; + B 10800 400 15800 92800; + B 11000 400 15900 92400; + B 11200 200 16000 92100; + B 5200 200 13000 91900; + B 5800 200 18700 91900; + B 5000 200 12900 91700; + B 4800 200 12800 91500; + B 5800 400 18900 91600; + B 4600 200 12700 91300; + B 4400 200 12600 91100; + B 5800 400 19100 91200; + B 4200 200 12500 90900; + B 4000 28200 12400 76700; + B 5800 400 19300 90800; + B 5800 400 19500 90400; + B 5800 400 19700 90000; + B 5800 400 19900 89600; + B 5800 400 20100 89200; + B 5800 400 20300 88800; + B 5800 400 20500 88400; + B 5800 400 20700 88000; + B 5800 400 20900 87600; + B 5800 400 21100 87200; + B 5800 400 21300 86800; + B 5800 400 21500 86400; + B 5800 400 21700 86000; + B 5800 400 21900 85600; + B 5800 400 22100 85200; + B 5800 400 22300 84800; + B 5800 400 22500 84400; + B 5800 400 22700 84000; + B 5800 400 22900 83600; + B 5800 400 23100 83200; + B 5800 400 23300 82800; + B 5800 400 23500 82400; + B 5800 400 23700 82000; + B 5800 400 23900 81600; + B 5800 400 24100 81200; + B 5800 400 24300 80800; + B 5800 400 24500 80400; + B 5800 400 24700 80000; + B 5800 400 24900 79600; + B 5800 400 25100 79200; + B 5800 400 25300 78800; + B 5800 400 25500 78400; + B 5800 400 25700 78000; + B 5800 400 25900 77600; + B 5800 400 26100 77200; + B 5800 400 26300 76800; + B 5800 400 26500 76400; + B 5800 400 26700 76000; + B 5800 400 26900 75600; + B 5800 400 27100 75200; + B 5800 400 27300 74800; + B 5800 400 27500 74400; + B 5800 400 27700 74000; + B 5800 400 27900 73600; + B 5800 400 28100 73200; + B 5800 400 28300 72800; + B 5800 400 28500 72400; + B 5800 400 28700 72000; + B 5800 400 28900 71600; + B 5800 400 29100 71200; + B 5800 400 29300 70800; + B 5800 400 29500 70400; + B 4000 28200 36400 84500; + B 4200 200 36300 70300; + B 5800 400 29700 70000; + B 4400 200 36200 70100; + B 4600 200 36100 69900; + B 5800 400 29900 69600; + B 4800 200 36000 69700; + B 5000 200 35900 69500; + B 5800 200 30100 69300; + B 5200 200 35800 69300; + B 11200 200 32800 69100; + B 11000 400 32900 68800; + B 10800 400 33000 68400; + B 10600 400 33100 68000; + B 10400 400 33200 67600; + B 10200 400 33300 67200; + B 10000 400 33400 66800; + B 4000 28200 44400 84500; + B 44000 200 76400 98500; + B 44200 200 76300 98300; + B 44400 200 76200 98100; + B 44600 200 76100 97900; + B 44800 200 76000 97700; + B 45000 200 75900 97500; + B 45200 200 75800 97300; + B 45400 200 75700 97100; + B 45600 200 75600 96900; + B 45800 200 75500 96700; + B 46000 200 75400 96500; + B 46200 200 75300 96300; + B 46400 200 75200 96100; + B 46600 200 75100 95900; + B 46800 200 75000 95700; + B 47000 200 74900 95500; + B 47200 200 74800 95300; + B 47400 200 74700 95100; + B 47600 200 74600 94900; + B 47800 200 74500 94700; + B 7800 200 54300 94500; + B 7600 200 54200 94300; + B 7400 200 54100 94100; + B 7200 200 54000 93900; + B 7000 200 53900 93700; + B 6800 200 53800 93500; + B 6600 200 53700 93300; + B 6400 200 53600 93100; + B 6200 200 53500 92900; + B 6000 200 53400 92700; + B 5800 200 53300 92500; + B 5600 200 53200 92300; + B 5400 200 53100 92100; + B 5200 200 53000 91900; + B 5000 200 52900 91700; + B 4800 200 52800 91500; + B 4600 200 52700 91300; + B 4400 200 52600 91100; + B 4200 200 52500 90900; + B 4000 4400 52400 88600; + B 4200 200 52500 86300; + B 4400 200 52600 86100; + B 4600 200 52700 85900; + B 4800 200 52800 85700; + B 5000 200 52900 85500; + B 5200 200 53000 85300; + B 5400 200 53100 85100; + B 5600 200 53200 84900; + B 5800 200 53300 84700; + B 6000 200 53400 84500; + B 6200 200 53500 84300; + B 6400 200 53600 84100; + B 6600 200 53700 83900; + B 6800 200 53800 83700; + B 7000 200 53900 83500; + B 7200 200 54000 83300; + B 7400 200 54100 83100; + B 7600 200 54200 82900; + B 7800 200 54300 82700; + B 23800 200 62500 82500; + B 23800 200 62700 82300; + B 23800 200 62900 82100; + B 23800 200 63100 81900; + B 23800 200 63300 81700; + B 23800 200 63500 81500; + B 23800 200 63700 81300; + B 23800 200 63900 81100; + B 23800 200 64100 80900; + B 23800 200 64300 80700; + B 23800 200 64500 80500; + B 23800 200 64700 80300; + B 23800 200 64900 80100; + B 23800 200 65100 79900; + B 23800 200 65300 79700; + B 23800 200 65500 79500; + B 23800 200 65700 79300; + B 23800 200 65900 79100; + B 23800 200 66100 78900; + B 23800 200 66300 78700; + B 7800 200 74500 78500; + B 7600 200 74600 78300; + B 7400 200 74700 78100; + B 7200 200 74800 77900; + B 7000 200 74900 77700; + B 6800 200 75000 77500; + B 6600 200 75100 77300; + B 6400 200 75200 77100; + B 6200 200 75300 76900; + B 6000 200 75400 76700; + B 5800 200 75500 76500; + B 5600 200 75600 76300; + B 5400 200 75700 76100; + B 5200 200 75800 75900; + B 5000 200 75900 75700; + B 4800 200 76000 75500; + B 4600 200 76100 75300; + B 4400 200 76200 75100; + B 4200 200 76300 74900; + B 4000 4400 76400 72600; + B 4200 200 44500 70300; + B 4200 200 76300 70300; + B 4400 200 44600 70100; + B 4400 200 76200 70100; + B 4600 200 44700 69900; + B 4600 200 76100 69900; + B 4800 200 44800 69700; + B 4800 200 76000 69700; + B 5000 200 44900 69500; + B 5000 200 75900 69500; + B 5200 200 45000 69300; + B 5200 200 75800 69300; + B 5400 200 45100 69100; + B 5400 200 75700 69100; + B 5600 200 45200 68900; + B 5600 200 75600 68900; + B 5800 200 45300 68700; + B 5800 200 75500 68700; + B 6000 200 45400 68500; + B 6000 200 75400 68500; + B 6200 200 45500 68300; + B 6200 200 75300 68300; + B 6400 200 45600 68100; + B 6400 200 75200 68100; + B 6600 200 45700 67900; + B 6600 200 75100 67900; + B 6800 200 45800 67700; + B 6800 200 75000 67700; + B 7000 200 45900 67500; + B 7000 200 74900 67500; + B 7200 200 46000 67300; + B 7200 200 74800 67300; + B 7400 200 46100 67100; + B 7400 200 74700 67100; + B 7600 200 46200 66900; + B 7600 200 74600 66900; + B 7800 200 46300 66700; + B 7800 200 74500 66700; + B 9600 200 33400 66500; + B 35800 200 60500 66500; + B 9400 200 33300 66300; + B 35200 200 60400 66300; + B 9000 200 33300 66100; + B 34800 200 60400 66100; + B 8800 200 33200 65900; + B 34400 200 60400 65900; + B 8400 200 33200 65700; + B 34000 200 60400 65700; + B 8200 200 33100 65500; + B 33600 200 60400 65500; + B 7800 200 33100 65300; + B 33200 200 60400 65300; + B 7600 200 33000 65100; + B 32800 200 60400 65100; + B 7200 200 33000 64900; + B 32400 200 60400 64900; + B 7000 200 32900 64700; + B 32000 200 60400 64700; + B 6600 200 32900 64500; + B 31600 200 60400 64500; + B 6400 200 32800 64300; + B 31200 200 60400 64300; + B 6000 200 32800 64100; + B 30800 200 60400 64100; + B 5800 200 32700 63900; + B 30400 200 60400 63900; + B 5400 200 32700 63700; + B 30000 200 60400 63700; + B 5200 200 32600 63500; + B 29600 200 60400 63500; + B 4800 200 32600 63300; + B 29200 200 60400 63300; + B 4600 200 32500 63100; + B 28800 200 60400 63100; + B 4200 200 32500 62900; + B 28400 200 60400 62900; + B 4000 200 32400 62700; + B 28000 200 60400 62700; + B 4000 32000 84400 78600; + B 30000 6000 116600 86800; + B 24000 6000 185600 86800; + B 6000 18000 116600 74800; + B 6000 200 140600 83700; + B 6000 200 164600 83700; + B 6200 200 140700 83500; + B 6200 200 164500 83500; + B 6400 200 140800 83300; + B 6400 200 164400 83300; + B 6600 200 140900 83100; + B 6600 200 164300 83100; + B 6800 200 141000 82900; + B 6800 200 164200 82900; + B 7000 200 141100 82700; + B 7000 200 164100 82700; + B 7200 200 141200 82500; + B 7200 200 164000 82500; + B 7400 200 141300 82300; + B 7400 200 163900 82300; + B 7600 200 141400 82100; + B 7600 200 163800 82100; + B 7800 200 141500 81900; + B 7800 200 163700 81900; + B 8000 200 141600 81700; + B 8000 200 163600 81700; + B 8200 200 141700 81500; + B 8200 200 163500 81500; + B 8400 200 141800 81300; + B 8400 200 163400 81300; + B 8600 200 141900 81100; + B 8600 200 163300 81100; + B 8800 200 142000 80900; + B 8800 200 163200 80900; + B 9000 200 142100 80700; + B 9000 200 163100 80700; + B 9200 200 142200 80500; + B 9200 200 163000 80500; + B 9400 200 142300 80300; + B 9400 200 162900 80300; + B 9600 200 142400 80100; + B 9600 200 162800 80100; + B 9800 200 142500 79900; + B 9800 200 162700 79900; + B 10000 200 142600 79700; + B 10000 200 162600 79700; + B 10200 200 142700 79500; + B 10200 200 162500 79500; + B 10400 200 142800 79300; + B 10400 200 162400 79300; + B 10600 200 142900 79100; + B 10600 200 162300 79100; + B 10800 200 143000 78900; + B 10800 200 162200 78900; + B 11000 200 143100 78700; + B 11000 200 162100 78700; + B 11200 200 143200 78500; + B 11200 200 162000 78500; + B 11400 200 143300 78300; + B 11400 200 161900 78300; + B 11600 200 143400 78100; + B 11600 200 161800 78100; + B 11800 200 143500 77900; + B 11800 200 161700 77900; + B 12000 200 143600 77700; + B 12000 200 161600 77700; + B 12200 200 143700 77500; + B 12200 200 161500 77500; + B 12400 200 143800 77300; + B 12400 200 161400 77300; + B 12600 200 143900 77100; + B 12600 200 161300 77100; + B 12800 200 144000 76900; + B 12800 200 161200 76900; + B 13000 200 144100 76700; + B 13000 200 161100 76700; + B 13200 200 144200 76500; + B 13200 200 161000 76500; + B 13400 200 144300 76300; + B 13400 200 160900 76300; + B 13600 200 144400 76100; + B 13600 200 160800 76100; + B 13800 200 144500 75900; + B 13800 200 160700 75900; + B 14000 200 144600 75700; + B 14000 200 160600 75700; + B 14200 200 144700 75500; + B 14200 200 160500 75500; + B 14400 200 144800 75300; + B 14400 200 160400 75300; + B 14600 200 144900 75100; + B 14600 200 160300 75100; + B 14800 200 145000 74900; + B 14800 200 160200 74900; + B 30000 3000 152600 73300; + B 6000 6000 176600 80800; + B 24000 6000 185600 74800; + B 30000 6000 116600 62800; + B 3000 1000 102100 57300; + B 1000 600 104500 57500; + B 1000 2000 102100 55800; + B 1400 600 104700 56900; + B 1800 600 104900 56300; + B 1000 1800 106500 56900; + B 3000 1000 108900 57300; + B 3000 1000 112300 57300; + B 3000 1000 115700 57300; + B 3000 1000 119100 57300; + B 3000 400 105500 55800; + B 3000 1000 102100 54300; + B 1000 1800 104500 54700; + B 1800 600 106100 55300; + B 1400 600 106300 54700; + B 1000 600 106500 54100; + B 1000 3000 108900 55300; + B 1000 600 111300 56500; + B 2000 1000 111800 55700; + B 1000 400 111300 55000; + B 1000 2000 114700 55800; + B 1000 600 118100 56500; + B 1000 600 120100 56500; + B 1400 1000 116500 55700; + B 1000 400 116700 55000; + B 3000 1000 112300 54300; + B 3000 1000 115700 54300; + B 3000 1000 119100 55700; + B 3000 1000 122500 57300; + B 3000 1000 125900 57300; + B 3000 1000 129300 57300; + B 2000 200 132600 57700; + B 2400 200 132800 57500; + B 2800 600 133000 57100; + B 1000 600 121500 56500; + B 1000 600 123500 56500; + B 3000 1000 122500 55700; + B 2600 200 118900 55100; + B 2800 200 119000 54900; + B 1000 1000 118100 54300; + B 1800 200 119700 54700; + B 1600 200 119800 54500; + B 1400 200 119900 54300; + B 1200 200 120000 54100; + B 1000 200 120100 53900; + B 1000 1400 121500 54500; + B 1000 1400 123500 54500; + B 1000 3000 125900 55300; + B 1000 600 128300 56500; + B 2000 1000 128800 55700; + B 1000 400 128300 55000; + B 1000 2000 132100 55800; + B 1600 200 133800 56700; + B 1200 200 134000 56500; + B 1000 1200 134100 55800; + B 1200 200 134000 55100; + B 1600 200 133800 54900; + B 3000 1000 129300 54300; + B 2800 600 133000 54500; + B 2400 200 132800 54100; + B 2000 200 132600 53900; + B 6000 18000 140600 62800; + B 17600 200 152600 71700; + B 17200 200 152600 71500; + B 16800 200 152600 71300; + B 16400 200 152600 71100; + B 16000 200 152600 70900; + B 15600 200 152600 70700; + B 15200 200 152600 70500; + B 14800 200 152600 70300; + B 14400 200 152600 70100; + B 14000 200 152600 69900; + B 13600 200 152600 69700; + B 13200 200 152600 69500; + B 12800 200 152600 69300; + B 12400 200 152600 69100; + B 12000 200 152600 68900; + B 11600 200 152600 68700; + B 11200 200 152600 68500; + B 10800 200 152600 68300; + B 10400 200 152600 68100; + B 10000 200 152600 67900; + B 9600 200 152600 67700; + B 9200 200 152600 67500; + B 8800 200 152600 67300; + B 8400 200 152600 67100; + B 8000 200 152600 66900; + B 7600 200 152600 66700; + B 7200 200 152600 66500; + B 6800 200 152600 66300; + B 6400 200 152600 66100; + B 6000 200 152600 65900; + B 5600 200 152600 65700; + B 5200 200 152600 65500; + B 4800 200 152600 65300; + B 4400 200 152600 65100; + B 4000 200 152600 64900; + B 3600 200 152600 64700; + B 3200 200 152600 64500; + B 2800 200 152600 64300; + B 2400 200 152600 64100; + B 2000 200 152600 63900; + B 1600 200 152600 63700; + B 1200 200 152600 63500; + B 800 200 152600 63300; + B 400 200 152600 63100; + B 6000 18000 164600 62800; + B 6000 6000 194600 68800; + B 24000 6000 185600 62800; + B 3000 1000 174100 57300; + B 1000 600 176500 57500; + B 1000 600 179500 57500; + B 1400 400 176700 57000; + B 1000 600 173100 56500; + B 1000 200 176900 56700; + B 1400 400 179300 57000; + B 3000 1000 181900 57300; + B 3000 1000 185300 57300; + B 3000 1000 188700 57300; + B 1000 600 191100 57500; + B 1000 600 194100 57500; + B 1000 200 179100 56700; + B 1400 400 177100 56400; + B 3000 1000 174100 55700; + B 1000 200 177300 56100; + B 1400 400 178900 56400; + B 1000 600 180900 56500; + B 1000 200 178700 56100; + B 2400 400 178000 55800; + B 1000 400 175100 55000; + B 1600 600 178000 55300; + B 3000 1000 181900 55700; + B 3000 1000 174100 54300; + B 1000 1200 178100 54400; + B 1000 400 182900 55000; + B 3000 1000 181900 54300; + B 1000 3000 185300 55300; + B 1000 600 187700 56500; + B 1400 600 191300 56900; + B 1400 600 193900 56900; + B 2000 1000 188200 55700; + B 1800 600 191500 56300; + B 1800 600 193700 56300; + B 4000 400 192600 55800; + B 1000 400 187700 55000; + B 3000 1000 188700 54300; + B 1000 1800 191100 54700; + B 1600 600 192600 55300; + B 1000 1800 194100 54700; + B 3000 1000 196500 57300; + B 1000 600 195500 56500; + B 3000 1000 196500 55700; + B 1000 400 197500 55000; + B 3000 1000 196500 54300; + B 1000 600 133700 50500; + B 1000 600 136700 50500; + B 1400 600 133900 49900; + B 1400 600 136500 49900; + B 1800 600 134100 49300; + B 1800 600 136300 49300; + B 4000 400 135200 48800; + B 1000 1800 133700 47700; + B 1600 600 135200 48300; + B 1000 1800 136700 47700; + B 3000 1000 139100 50300; + B 3000 1000 142500 50300; + B 1000 600 138100 49500; + B 1000 600 141500 49500; + B 1000 600 143500 49500; + B 2000 1000 138600 48700; + B 3000 1000 142500 48700; + B 3000 1000 145900 50300; + B 1000 600 144900 49500; + B 3000 1000 145900 48700; + B 1000 400 138100 48000; + B 3000 1000 139100 47300; + B 1000 1400 141500 47500; + B 1000 1400 143500 47500; + B 1000 400 146900 48000; + B 3000 1000 145900 47300; + B 1000 3000 148300 49300; + B 1000 3000 150300 49300; + B 3000 1000 149300 47300; + B 3000 1000 152700 50300; + B 1000 600 151700 49500; + B 1000 600 153700 49500; + B 3000 1000 152700 48700; + B 3000 1000 156300 50300; + B 1000 600 158700 50500; + B 1000 600 161700 50500; + B 1000 600 155300 49500; + B 1400 600 158900 49900; + B 1400 600 161500 49900; + B 2000 1000 155800 48700; + B 1800 600 159100 49300; + B 1800 600 161300 49300; + B 4000 400 160200 48800; + B 2600 200 152500 48100; + B 2800 200 152600 47900; + B 1000 400 155300 48000; + B 1000 1000 151700 47300; + B 1800 200 153300 47700; + B 1600 200 153400 47500; + B 1400 200 153500 47300; + B 1200 200 153600 47100; + B 1000 200 153700 46900; + B 3000 1000 156300 47300; + B 1000 1800 158700 47700; + B 1600 600 160200 48300; + B 1000 1800 161700 47700; + B 3000 1000 164100 50300; + B 1000 600 166500 50500; + B 1000 600 163100 49500; + B 1400 600 166700 49900; + B 2000 1000 163600 48700; + B 1800 600 166900 49300; + B 1000 1800 168500 49900; + B 3000 1000 170900 50300; + B 3000 400 167500 48800; + B 1000 400 163100 48000; + B 3000 1000 164100 47300; + B 1000 1800 166500 47700; + B 1800 600 168100 48300; + B 1400 600 168300 47700; + B 1000 600 168500 47100; + B 1000 3000 170900 48300; +C 2 R 1 0 T -42000 51800; +C 3 R 1 0 T -71800 28400; +C 4 R 1 0 T 92200 2000; +C 5 R 1 0 T 135000 -20000; +C 6 R 1 0 T -86000 -67200; +C 7 R 1 0 T -16000 -73400; +C 8 R 1 0 T 84000 -86000; +C 9 R 1 0 T 144000 -86000; +DF; +DS 9 1 2; +9 gas-sensora; +L CMS; + B 52000 53200 26000 26600; +DF; +DS 8 1 2; +9 micro-hot-platea; +L CMS; + B 52000 53200 26000 26600; +DF; +DS 7 1 2; +9 pixel-160x160a; +L CMS; + B 34000 34000 74600 14600; +DF; +DS 6 1 2; +9 pixel-80x80a; +L CMS; + B 18000 18000 108400 8400; +DF; +DS 5 1 2; +9 thermal-actuatora; +L CMS; + B 18000 44000 9000 22000; +DF; +DS 4 1 2; +9 thermal-convertera; +L CMS; + B 30000 44000 11800 0; +DF; +DS 3 1 2; +9 open-oxide-80x80a; +L CMS; + B 16000 16000 135400 -40400; +DF; +DS 2 1 2; +9 open-80x80a; +L CMS; + B 16000 16000 105600 -39800; +DF; +C 1; +End + diff --git a/scmos/examples/nist-mems-library/memslib.mag b/scmos/examples/nist-mems-library/memslib.mag new file mode 100644 index 00000000..0275e566 --- /dev/null +++ b/scmos/examples/nist-mems-library/memslib.mag @@ -0,0 +1,700 @@ +magic +tech scmos +timestamp 765071885 +<< polysilicon >> +rect 72 492 92 493 +rect 71 491 92 492 +rect 70 490 93 491 +rect 69 489 93 490 +rect 68 488 94 489 +rect 67 487 94 488 +rect 66 486 95 487 +rect 65 485 95 486 +rect 64 484 96 485 +rect 63 483 96 484 +rect 62 482 97 483 +rect 61 481 97 482 +rect 60 480 98 481 +rect 59 479 98 480 +rect 58 478 99 479 +rect 57 477 99 478 +rect 56 476 100 477 +rect 55 475 100 476 +rect 54 474 101 475 +rect 53 473 101 474 +rect 52 471 102 473 +rect 52 469 103 471 +rect 52 467 104 469 +rect 52 465 105 467 +rect 52 463 106 465 +rect 52 461 107 463 +rect 52 460 108 461 +rect 52 459 78 460 +rect 79 459 108 460 +rect 52 458 77 459 +rect 52 457 76 458 +rect 80 457 109 459 +rect 52 456 75 457 +rect 52 455 74 456 +rect 81 455 110 457 +rect 52 454 73 455 +rect 52 313 72 454 +rect 82 453 111 455 +rect 83 451 112 453 +rect 84 449 113 451 +rect 85 447 114 449 +rect 86 445 115 447 +rect 87 443 116 445 +rect 88 441 117 443 +rect 89 439 118 441 +rect 90 437 119 439 +rect 91 435 120 437 +rect 92 433 121 435 +rect 93 431 122 433 +rect 94 429 123 431 +rect 95 427 124 429 +rect 96 425 125 427 +rect 97 423 126 425 +rect 98 421 127 423 +rect 99 419 128 421 +rect 100 417 129 419 +rect 101 415 130 417 +rect 102 413 131 415 +rect 103 411 132 413 +rect 104 409 133 411 +rect 105 407 134 409 +rect 106 405 135 407 +rect 107 403 136 405 +rect 108 401 137 403 +rect 109 399 138 401 +rect 110 397 139 399 +rect 111 395 140 397 +rect 112 393 141 395 +rect 113 391 142 393 +rect 114 389 143 391 +rect 115 387 144 389 +rect 116 385 145 387 +rect 117 383 146 385 +rect 118 381 147 383 +rect 119 379 148 381 +rect 120 377 149 379 +rect 121 375 150 377 +rect 122 373 151 375 +rect 123 371 152 373 +rect 124 369 153 371 +rect 125 367 154 369 +rect 126 365 155 367 +rect 127 363 156 365 +rect 128 361 157 363 +rect 129 359 158 361 +rect 130 357 159 359 +rect 131 355 160 357 +rect 132 353 161 355 +rect 133 351 162 353 +rect 172 352 192 493 +rect 171 351 192 352 +rect 134 349 163 351 +rect 170 350 192 351 +rect 169 349 192 350 +rect 135 347 164 349 +rect 168 348 192 349 +rect 167 347 192 348 +rect 136 346 165 347 +rect 166 346 192 347 +rect 136 345 192 346 +rect 137 343 192 345 +rect 138 341 192 343 +rect 139 339 192 341 +rect 140 337 192 339 +rect 141 335 192 337 +rect 142 333 192 335 +rect 212 352 232 493 +rect 272 492 492 493 +rect 271 491 492 492 +rect 270 490 492 491 +rect 269 489 492 490 +rect 268 488 492 489 +rect 267 487 492 488 +rect 266 486 492 487 +rect 265 485 492 486 +rect 264 484 492 485 +rect 263 483 492 484 +rect 262 482 492 483 +rect 261 481 492 482 +rect 260 480 492 481 +rect 259 479 492 480 +rect 258 478 492 479 +rect 257 477 492 478 +rect 256 476 492 477 +rect 255 475 492 476 +rect 254 474 492 475 +rect 253 473 492 474 +rect 252 472 291 473 +rect 252 471 290 472 +rect 252 470 289 471 +rect 252 469 288 470 +rect 252 468 287 469 +rect 252 467 286 468 +rect 252 466 285 467 +rect 252 465 284 466 +rect 252 464 283 465 +rect 252 463 282 464 +rect 252 462 281 463 +rect 252 461 280 462 +rect 252 460 279 461 +rect 252 459 278 460 +rect 252 458 277 459 +rect 252 457 276 458 +rect 252 456 275 457 +rect 252 455 274 456 +rect 252 454 273 455 +rect 252 432 272 454 +rect 252 431 273 432 +rect 252 430 274 431 +rect 252 429 275 430 +rect 252 428 276 429 +rect 252 427 277 428 +rect 252 426 278 427 +rect 252 425 279 426 +rect 252 424 280 425 +rect 252 423 281 424 +rect 252 422 282 423 +rect 252 421 283 422 +rect 252 420 284 421 +rect 252 419 285 420 +rect 252 418 286 419 +rect 252 417 287 418 +rect 252 416 288 417 +rect 252 415 289 416 +rect 252 414 290 415 +rect 252 413 291 414 +rect 253 412 372 413 +rect 254 411 373 412 +rect 255 410 374 411 +rect 256 409 375 410 +rect 257 408 376 409 +rect 258 407 377 408 +rect 259 406 378 407 +rect 260 405 379 406 +rect 261 404 380 405 +rect 262 403 381 404 +rect 263 402 382 403 +rect 264 401 383 402 +rect 265 400 384 401 +rect 266 399 385 400 +rect 267 398 386 399 +rect 268 397 387 398 +rect 269 396 388 397 +rect 270 395 389 396 +rect 271 394 390 395 +rect 272 393 391 394 +rect 353 392 392 393 +rect 354 391 392 392 +rect 355 390 392 391 +rect 356 389 392 390 +rect 357 388 392 389 +rect 358 387 392 388 +rect 359 386 392 387 +rect 360 385 392 386 +rect 361 384 392 385 +rect 362 383 392 384 +rect 363 382 392 383 +rect 364 381 392 382 +rect 365 380 392 381 +rect 366 379 392 380 +rect 367 378 392 379 +rect 368 377 392 378 +rect 369 376 392 377 +rect 370 375 392 376 +rect 371 374 392 375 +rect 372 352 392 374 +rect 212 351 233 352 +rect 371 351 392 352 +rect 212 350 234 351 +rect 370 350 392 351 +rect 212 349 235 350 +rect 369 349 392 350 +rect 212 348 236 349 +rect 368 348 392 349 +rect 212 347 237 348 +rect 367 347 392 348 +rect 212 346 238 347 +rect 366 346 392 347 +rect 212 345 239 346 +rect 365 345 392 346 +rect 212 344 240 345 +rect 364 344 392 345 +rect 212 343 241 344 +rect 363 343 392 344 +rect 212 342 242 343 +rect 362 342 392 343 +rect 212 341 243 342 +rect 361 341 392 342 +rect 212 340 244 341 +rect 360 340 392 341 +rect 212 339 245 340 +rect 359 339 392 340 +rect 212 338 246 339 +rect 358 338 392 339 +rect 212 337 247 338 +rect 357 337 392 338 +rect 212 336 248 337 +rect 356 336 392 337 +rect 212 335 249 336 +rect 355 335 392 336 +rect 212 334 250 335 +rect 354 334 392 335 +rect 212 333 251 334 +rect 353 333 392 334 +rect 143 332 191 333 +rect 213 332 392 333 +rect 143 331 190 332 +rect 214 331 390 332 +rect 144 330 189 331 +rect 215 330 389 331 +rect 144 329 188 330 +rect 216 329 388 330 +rect 145 328 187 329 +rect 217 328 387 329 +rect 145 327 186 328 +rect 218 327 386 328 +rect 146 326 185 327 +rect 219 326 385 327 +rect 146 325 184 326 +rect 220 325 384 326 +rect 147 324 183 325 +rect 221 324 383 325 +rect 147 323 182 324 +rect 222 323 382 324 +rect 148 322 181 323 +rect 223 322 381 323 +rect 148 321 180 322 +rect 224 321 380 322 +rect 149 320 179 321 +rect 225 320 379 321 +rect 149 319 178 320 +rect 226 319 378 320 +rect 150 318 177 319 +rect 227 318 377 319 +rect 150 317 176 318 +rect 228 317 376 318 +rect 151 316 175 317 +rect 229 316 375 317 +rect 151 315 174 316 +rect 230 315 374 316 +rect 152 314 173 315 +rect 231 314 373 315 +rect 152 313 172 314 +rect 232 313 372 314 +rect 412 313 432 473 +rect 508 419 658 449 +rect 868 419 988 449 +rect 568 329 598 419 +rect 688 418 718 419 +rect 808 418 838 419 +rect 688 417 719 418 +rect 807 417 838 418 +rect 688 416 720 417 +rect 806 416 838 417 +rect 688 415 721 416 +rect 805 415 838 416 +rect 688 414 722 415 +rect 804 414 838 415 +rect 688 413 723 414 +rect 803 413 838 414 +rect 688 412 724 413 +rect 802 412 838 413 +rect 688 411 725 412 +rect 801 411 838 412 +rect 688 410 726 411 +rect 800 410 838 411 +rect 688 409 727 410 +rect 799 409 838 410 +rect 688 408 728 409 +rect 798 408 838 409 +rect 688 407 729 408 +rect 797 407 838 408 +rect 688 406 730 407 +rect 796 406 838 407 +rect 688 405 731 406 +rect 795 405 838 406 +rect 688 404 732 405 +rect 794 404 838 405 +rect 688 403 733 404 +rect 793 403 838 404 +rect 688 402 734 403 +rect 792 402 838 403 +rect 688 401 735 402 +rect 791 401 838 402 +rect 688 400 736 401 +rect 790 400 838 401 +rect 688 399 737 400 +rect 789 399 838 400 +rect 688 398 738 399 +rect 788 398 838 399 +rect 688 397 739 398 +rect 787 397 838 398 +rect 688 396 740 397 +rect 786 396 838 397 +rect 688 395 741 396 +rect 785 395 838 396 +rect 688 394 742 395 +rect 784 394 838 395 +rect 688 393 743 394 +rect 783 393 838 394 +rect 688 392 744 393 +rect 782 392 838 393 +rect 688 391 745 392 +rect 781 391 838 392 +rect 688 390 746 391 +rect 780 390 838 391 +rect 688 389 747 390 +rect 779 389 838 390 +rect 688 388 748 389 +rect 778 388 838 389 +rect 688 387 749 388 +rect 777 387 838 388 +rect 688 386 750 387 +rect 776 386 838 387 +rect 688 385 751 386 +rect 775 385 838 386 +rect 688 384 752 385 +rect 774 384 838 385 +rect 688 383 753 384 +rect 773 383 838 384 +rect 688 382 754 383 +rect 772 382 838 383 +rect 688 381 755 382 +rect 771 381 838 382 +rect 688 380 756 381 +rect 770 380 838 381 +rect 688 379 757 380 +rect 769 379 838 380 +rect 688 378 758 379 +rect 768 378 838 379 +rect 688 377 759 378 +rect 767 377 838 378 +rect 688 376 760 377 +rect 766 376 838 377 +rect 688 375 761 376 +rect 765 375 838 376 +rect 688 374 762 375 +rect 764 374 838 375 +rect 688 359 838 374 +rect 868 389 898 419 +rect 868 359 988 389 +rect 508 299 658 329 +rect 503 284 518 289 +rect 520 286 525 289 +rect 508 274 513 284 +rect 520 283 527 286 +rect 520 280 529 283 +rect 530 280 535 289 +rect 537 284 552 289 +rect 554 284 569 289 +rect 571 284 586 289 +rect 588 284 603 289 +rect 520 278 535 280 +rect 503 269 518 274 +rect 520 269 525 278 +rect 526 275 535 278 +rect 528 272 535 275 +rect 530 269 535 272 +rect 542 269 547 284 +rect 554 281 559 284 +rect 554 276 564 281 +rect 554 274 559 276 +rect 571 274 576 284 +rect 588 281 593 284 +rect 598 281 603 284 +rect 579 276 586 281 +rect 581 274 586 276 +rect 554 269 569 274 +rect 571 269 586 274 +rect 588 276 603 281 +rect 605 284 620 289 +rect 622 284 637 289 +rect 639 284 654 289 +rect 658 288 668 289 +rect 658 287 670 288 +rect 658 284 672 287 +rect 605 281 610 284 +rect 615 281 620 284 +rect 605 276 620 281 +rect 588 275 601 276 +rect 588 274 602 275 +rect 588 269 593 274 +rect 594 273 603 274 +rect 595 272 603 273 +rect 596 271 603 272 +rect 597 270 603 271 +rect 598 269 603 270 +rect 605 269 610 276 +rect 615 269 620 276 +rect 627 269 632 284 +rect 639 281 644 284 +rect 639 276 649 281 +rect 639 274 644 276 +rect 658 274 663 284 +rect 665 283 673 284 +rect 667 282 673 283 +rect 668 276 673 282 +rect 667 275 673 276 +rect 665 274 673 275 +rect 639 269 654 274 +rect 658 271 672 274 +rect 658 270 670 271 +rect 658 269 668 270 +rect 688 269 718 359 +rect 719 358 807 359 +rect 720 357 806 358 +rect 721 356 805 357 +rect 722 355 804 356 +rect 723 354 803 355 +rect 724 353 802 354 +rect 725 352 801 353 +rect 726 351 800 352 +rect 727 350 799 351 +rect 728 349 798 350 +rect 729 348 797 349 +rect 730 347 796 348 +rect 731 346 795 347 +rect 732 345 794 346 +rect 733 344 793 345 +rect 734 343 792 344 +rect 735 342 791 343 +rect 736 341 790 342 +rect 737 340 789 341 +rect 738 339 788 340 +rect 739 338 787 339 +rect 740 337 786 338 +rect 741 336 785 337 +rect 742 335 784 336 +rect 743 334 783 335 +rect 744 333 782 334 +rect 745 332 781 333 +rect 746 331 780 332 +rect 747 330 779 331 +rect 748 329 778 330 +rect 749 328 777 329 +rect 750 327 776 328 +rect 751 326 775 327 +rect 752 325 774 326 +rect 753 324 773 325 +rect 754 323 772 324 +rect 755 322 771 323 +rect 756 321 770 322 +rect 757 320 769 321 +rect 758 319 768 320 +rect 759 318 767 319 +rect 760 317 766 318 +rect 761 316 765 317 +rect 762 315 764 316 +rect 808 269 838 359 +rect 958 329 988 359 +rect 868 299 988 329 +rect 863 284 878 289 +rect 880 286 885 289 +rect 895 286 900 289 +rect 880 284 887 286 +rect 863 281 868 284 +rect 882 283 887 284 +rect 893 284 900 286 +rect 902 284 917 289 +rect 919 284 934 289 +rect 936 284 951 289 +rect 953 286 958 289 +rect 968 286 973 289 +rect 893 283 898 284 +rect 882 281 889 283 +rect 863 276 878 281 +rect 884 280 889 281 +rect 891 281 898 283 +rect 902 281 907 284 +rect 891 280 896 281 +rect 884 278 896 280 +rect 873 274 878 276 +rect 886 275 894 278 +rect 902 276 917 281 +rect 863 269 878 274 +rect 888 269 893 275 +rect 912 274 917 276 +rect 902 269 917 274 +rect 924 269 929 284 +rect 936 281 941 284 +rect 953 283 960 286 +rect 966 283 973 286 +rect 936 276 946 281 +rect 953 280 962 283 +rect 964 280 973 283 +rect 953 278 973 280 +rect 936 274 941 276 +rect 936 269 951 274 +rect 953 269 958 278 +rect 959 275 967 278 +rect 968 269 973 278 +rect 975 284 990 289 +rect 975 281 980 284 +rect 975 276 990 281 +rect 985 274 990 276 +rect 975 269 990 274 +rect 666 251 671 254 +rect 681 251 686 254 +rect 666 248 673 251 +rect 679 248 686 251 +rect 666 245 675 248 +rect 677 245 686 248 +rect 666 243 686 245 +rect 666 234 671 243 +rect 672 240 680 243 +rect 681 234 686 243 +rect 688 249 703 254 +rect 705 249 720 254 +rect 688 246 693 249 +rect 705 246 710 249 +rect 715 246 720 249 +rect 688 241 698 246 +rect 705 241 720 246 +rect 722 249 737 254 +rect 722 246 727 249 +rect 722 241 737 246 +rect 688 239 693 241 +rect 688 234 703 239 +rect 705 234 710 241 +rect 715 234 720 241 +rect 732 239 737 241 +rect 722 234 737 239 +rect 739 239 744 254 +rect 749 239 754 254 +rect 739 234 754 239 +rect 756 249 771 254 +rect 756 246 761 249 +rect 766 246 771 249 +rect 756 241 771 246 +rect 774 249 789 254 +rect 791 251 796 254 +rect 806 251 811 254 +rect 774 246 779 249 +rect 791 248 798 251 +rect 804 248 811 251 +rect 774 241 784 246 +rect 791 245 800 248 +rect 802 245 811 248 +rect 791 243 811 245 +rect 756 240 769 241 +rect 756 239 770 240 +rect 774 239 779 241 +rect 756 234 761 239 +rect 762 238 771 239 +rect 763 237 771 238 +rect 764 236 771 237 +rect 765 235 771 236 +rect 766 234 771 235 +rect 774 234 789 239 +rect 791 234 796 243 +rect 797 240 805 243 +rect 806 234 811 243 +rect 813 249 828 254 +rect 830 251 835 254 +rect 813 246 818 249 +rect 830 248 837 251 +rect 813 241 823 246 +rect 830 245 839 248 +rect 840 245 845 254 +rect 847 249 862 254 +rect 830 243 845 245 +rect 813 239 818 241 +rect 813 234 828 239 +rect 830 234 835 243 +rect 836 240 845 243 +rect 838 237 845 240 +rect 840 234 845 237 +rect 852 234 857 249 +<< metal1 >> +rect 105 210 155 220 +rect 105 170 115 210 +rect 125 170 135 210 +rect 145 170 155 210 +rect 165 210 195 220 +rect 205 210 255 220 +rect 165 200 175 210 +rect 165 190 185 200 +rect 165 180 175 190 +rect 165 170 195 180 +rect 205 170 215 210 +rect 225 170 235 210 +rect 245 170 255 210 +rect 265 210 295 220 +rect 265 200 275 210 +rect 265 190 295 200 +rect 285 180 295 190 +rect 265 170 295 180 +rect 345 180 355 220 +rect 385 210 415 220 +rect 425 210 455 220 +rect 395 180 405 210 +rect 425 200 435 210 +rect 445 200 455 210 +rect 425 190 455 200 +rect 425 180 435 190 +rect 445 180 455 190 +rect 345 170 375 180 +rect 385 170 415 180 +rect 425 170 455 180 +rect 465 215 490 220 +rect 465 210 495 215 +rect 465 200 475 210 +rect 485 200 495 210 +rect 505 210 535 220 +rect 505 200 515 210 +rect 525 200 535 210 +rect 465 190 490 200 +rect 505 190 535 200 +rect 465 170 475 190 +rect 485 170 495 190 +rect 505 170 515 190 +rect 525 170 535 190 +rect 545 215 570 220 +rect 545 210 575 215 +rect 545 200 555 210 +rect 565 200 575 210 +rect 585 200 595 220 +rect 605 200 615 220 +rect 545 190 570 200 +rect 585 190 615 200 +rect 545 170 555 190 +rect 565 170 575 190 +rect 595 170 605 190 +use open-80x80 2_0 +timestamp 760840415 +transform 1 0 -210 0 1 259 +box 488 -239 568 -159 +use open-oxide-80x80 3_0 +timestamp 760840453 +transform 1 0 -359 0 1 142 +box 637 -242 717 -162 +use thermal-converter 4_0 +timestamp 760840748 +transform 1 0 461 0 1 10 +box -16 -110 134 110 +use thermal-actuator 5_0 +timestamp 760840666 +transform 1 0 675 0 1 -100 +box 0 0 90 220 +use pixel-80x80 6_0 +timestamp 760840526 +transform 1 0 -430 0 1 -336 +box 497 -3 587 87 +use pixel-160x160 7_0 +timestamp 760840608 +transform 1 0 -80 0 1 -367 +box 288 -12 458 158 +use micro-hot-plate 8_0 +timestamp 760840982 +transform 1 0 420 0 1 -430 +box 0 0 260 266 +use gas-sensor 9_0 +timestamp 760840948 +transform 1 0 720 0 1 -430 +box 0 0 260 266 +<< end >> diff --git a/scmos/examples/nist-mems-library/micro-hot-plate.cif b/scmos/examples/nist-mems-library/micro-hot-plate.cif new file mode 100644 index 00000000..43f4bc40 --- /dev/null +++ b/scmos/examples/nist-mems-library/micro-hot-plate.cif @@ -0,0 +1,2088 @@ +DS 1 1 2; +9 micro-hot-plate; +L CMF; + B 2000 2000 51000 52200; + B 6000 1200 3000 48600; + B 6000 1200 49000 48600; + B 6200 200 3100 47900; + B 6200 200 48900 47900; + B 6400 200 3200 47700; + B 6400 200 48800 47700; + B 6600 200 3300 47500; + B 6600 200 48700 47500; + B 6800 200 3400 47300; + B 6800 200 48600 47300; + B 1800 200 6100 47100; + B 1800 200 45900 47100; + B 1800 200 6300 46900; + B 1800 200 45700 46900; + B 1800 200 6500 46700; + B 1800 200 45500 46700; + B 1800 200 6700 46500; + B 1800 200 45300 46500; + B 1800 200 6900 46300; + B 1800 200 45100 46300; + B 1800 200 7100 46100; + B 1800 200 44900 46100; + B 1800 200 7300 45900; + B 1800 200 44700 45900; + B 1800 200 7500 45700; + B 1800 200 44500 45700; + B 1800 200 7700 45500; + B 1800 200 44300 45500; + B 1800 200 7900 45300; + B 1800 200 44100 45300; + B 1800 200 8100 45100; + B 1800 200 43900 45100; + B 1800 200 8300 44900; + B 1800 200 43700 44900; + B 1800 200 8500 44700; + B 1800 200 43500 44700; + B 1800 200 8700 44500; + B 1800 200 43300 44500; + B 1800 200 8900 44300; + B 1800 200 43100 44300; + B 1800 200 9100 44100; + B 1800 200 42900 44100; + B 1800 200 9300 43900; + B 1800 200 42700 43900; + B 1800 200 9500 43700; + B 1800 200 42500 43700; + B 1800 200 9700 43500; + B 1800 200 42300 43500; + B 1800 200 9900 43300; + B 1800 200 42100 43300; + B 1800 200 10100 43100; + B 1800 200 41900 43100; + B 1800 200 10300 42900; + B 1800 200 41700 42900; + B 1800 200 10500 42700; + B 1800 200 41500 42700; + B 1800 200 10700 42500; + B 1800 200 41300 42500; + B 1800 200 10900 42300; + B 1800 200 41100 42300; + B 1800 200 11100 42100; + B 1800 200 40900 42100; + B 1800 200 11300 41900; + B 1800 200 40700 41900; + B 1800 200 11500 41700; + B 1800 200 40500 41700; + B 1800 200 11700 41500; + B 1800 200 40300 41500; + B 1800 200 11900 41300; + B 1800 200 40100 41300; + B 1800 200 12100 41100; + B 1800 200 39900 41100; + B 1800 200 12300 40900; + B 1800 200 39700 40900; + B 1800 200 12500 40700; + B 1800 200 39500 40700; + B 1800 200 12700 40500; + B 1800 200 39300 40500; + B 1800 200 12900 40300; + B 1800 200 39100 40300; + B 1800 200 13100 40100; + B 1800 200 38900 40100; + B 1800 200 13300 39900; + B 1800 200 38700 39900; + B 1800 200 13500 39700; + B 1800 200 38500 39700; + B 1800 200 13700 39500; + B 1800 200 38300 39500; + B 1800 200 13900 39300; + B 1800 200 38100 39300; + B 1800 200 14100 39100; + B 1800 200 37900 39100; + B 1800 200 14300 38900; + B 1800 200 37700 38900; + B 1800 200 14500 38700; + B 1800 200 37500 38700; + B 1800 200 14700 38500; + B 1800 200 37300 38500; + B 1800 200 14900 38300; + B 1800 200 37100 38300; + B 1800 200 15100 38100; + B 1800 200 36900 38100; + B 1800 200 15300 37900; + B 1800 200 36700 37900; + B 1800 200 15500 37700; + B 1800 200 36500 37700; + B 1800 200 15700 37500; + B 1800 200 36300 37500; + B 1800 200 15900 37300; + B 1800 200 36100 37300; + B 1800 200 16100 37100; + B 1800 200 35900 37100; + B 1800 200 16300 36900; + B 1800 200 35700 36900; + B 1800 200 16500 36700; + B 1800 200 35500 36700; + B 1800 200 16700 36500; + B 1800 200 35300 36500; + B 1800 200 16900 36300; + B 1800 200 35100 36300; + B 19600 200 26000 36100; + B 19200 200 26000 35900; + B 18800 200 26000 35700; + B 18400 200 26000 35500; + B 18000 16400 26000 27200; + B 18400 200 26000 18900; + B 18800 200 26000 18700; + B 19200 200 26000 18500; + B 19600 200 26000 18300; + B 1800 200 16900 18100; + B 1800 200 35100 18100; + B 1800 200 16700 17900; + B 1800 200 35300 17900; + B 1800 200 16500 17700; + B 1800 200 35500 17700; + B 1800 200 16300 17500; + B 1800 200 35700 17500; + B 1800 200 16100 17300; + B 1800 200 35900 17300; + B 1800 200 15900 17100; + B 1800 200 36100 17100; + B 1800 200 15700 16900; + B 1800 200 36300 16900; + B 1800 200 15500 16700; + B 1800 200 36500 16700; + B 1800 200 15300 16500; + B 1800 200 36700 16500; + B 1800 200 15100 16300; + B 1800 200 36900 16300; + B 1800 200 14900 16100; + B 1800 200 37100 16100; + B 1800 200 14700 15900; + B 1800 200 37300 15900; + B 1800 200 14500 15700; + B 1800 200 37500 15700; + B 1800 200 14300 15500; + B 1800 200 37700 15500; + B 1800 200 14100 15300; + B 1800 200 37900 15300; + B 1800 200 13900 15100; + B 1800 200 38100 15100; + B 1800 200 13700 14900; + B 1800 200 38300 14900; + B 1800 200 13500 14700; + B 1800 200 38500 14700; + B 1800 200 13300 14500; + B 1800 200 38700 14500; + B 1800 200 13100 14300; + B 1800 200 38900 14300; + B 1800 200 12900 14100; + B 1800 200 39100 14100; + B 1800 200 12700 13900; + B 1800 200 39300 13900; + B 1800 200 12500 13700; + B 1800 200 39500 13700; + B 1800 200 12300 13500; + B 1800 200 39700 13500; + B 1800 200 12100 13300; + B 1800 200 39900 13300; + B 1800 200 11900 13100; + B 1800 200 40100 13100; + B 1800 200 11700 12900; + B 1800 200 40300 12900; + B 1800 200 11500 12700; + B 1800 200 40500 12700; + B 1800 200 11300 12500; + B 1800 200 40700 12500; + B 1800 200 11100 12300; + B 1800 200 40900 12300; + B 1800 200 10900 12100; + B 1800 200 41100 12100; + B 1800 200 10700 11900; + B 1800 200 41300 11900; + B 1800 200 10500 11700; + B 1800 200 41500 11700; + B 1800 200 10300 11500; + B 1800 200 41700 11500; + B 1800 200 10100 11300; + B 1800 200 41900 11300; + B 1800 200 9900 11100; + B 1800 200 42100 11100; + B 1800 200 9700 10900; + B 1800 200 42300 10900; + B 1800 200 9500 10700; + B 1800 200 42500 10700; + B 1800 200 9300 10500; + B 1800 200 42700 10500; + B 1800 200 9100 10300; + B 1800 200 42900 10300; + B 1800 200 8900 10100; + B 1800 200 43100 10100; + B 1800 200 8700 9900; + B 1800 200 43300 9900; + B 1800 200 8500 9700; + B 1800 200 43500 9700; + B 1800 200 8300 9500; + B 1800 200 43700 9500; + B 1800 200 8100 9300; + B 1800 200 43900 9300; + B 1800 200 7900 9100; + B 1800 200 44100 9100; + B 1800 200 7700 8900; + B 1800 200 44300 8900; + B 1800 200 7500 8700; + B 1800 200 44500 8700; + B 1800 200 7300 8500; + B 1800 200 44700 8500; + B 1800 200 7100 8300; + B 1800 200 44900 8300; + B 1800 200 6900 8100; + B 1800 200 45100 8100; + B 1800 200 6700 7900; + B 1800 200 45300 7900; + B 1800 200 6500 7700; + B 1800 200 45500 7700; + B 1800 200 6300 7500; + B 1800 200 45700 7500; + B 1800 200 6100 7300; + B 1800 200 45900 7300; + B 6800 200 3400 7100; + B 6800 200 48600 7100; + B 6600 200 3300 6900; + B 6600 200 48700 6900; + B 6400 200 3200 6700; + B 6400 200 48800 6700; + B 6200 200 3100 6500; + B 6200 200 48900 6500; + B 6000 1200 3000 5800; + B 6000 1200 49000 5800; + B 2000 3200 1000 1600; +L CPG; + B 2000 200 51000 53100; + B 2200 200 50900 52900; + B 2400 200 50800 52700; + B 2600 200 50700 52500; + B 2800 200 50600 52300; + B 3000 200 50500 52100; + B 3200 200 50400 51900; + B 3400 200 50300 51700; + B 3600 200 50200 51500; + B 3800 200 50100 51300; + B 3800 200 49900 51100; + B 3800 200 49700 50900; + B 3800 200 49500 50700; + B 3800 200 49300 50500; + B 3800 200 49100 50300; + B 3800 200 48900 50100; + B 3800 200 48700 49900; + B 3800 200 48500 49700; + B 3800 200 48300 49500; + B 3800 200 48100 49300; + B 3800 200 47900 49100; + B 3800 200 47700 48900; + B 3800 200 47500 48700; + B 3800 200 47300 48500; + B 3800 200 47100 48300; + B 3800 200 46900 48100; + B 3800 200 46700 47900; + B 3800 200 46500 47700; + B 3800 200 46300 47500; + B 3800 200 46100 47300; + B 3800 200 45900 47100; + B 3800 200 45700 46900; + B 3800 200 45500 46700; + B 3800 200 45300 46500; + B 3800 200 45100 46300; + B 3800 200 44900 46100; + B 3800 200 44700 45900; + B 3800 200 44500 45700; + B 3800 200 44300 45500; + B 3800 200 44100 45300; + B 3800 200 43900 45100; + B 3800 200 43700 44900; + B 3800 200 43500 44700; + B 3800 200 43300 44500; + B 3800 200 43100 44300; + B 3800 200 42900 44100; + B 3800 200 42700 43900; + B 3800 200 42500 43700; + B 3800 200 42300 43500; + B 3800 200 42100 43300; + B 3800 200 41900 43100; + B 3800 200 41700 42900; + B 3800 200 41500 42700; + B 3800 200 41300 42500; + B 3800 200 41100 42300; + B 3800 200 40900 42100; + B 3800 200 40700 41900; + B 3800 200 40500 41700; + B 3800 200 40300 41500; + B 3800 200 40100 41300; + B 3800 200 39900 41100; + B 3800 200 39700 40900; + B 3800 200 39500 40700; + B 3800 200 39300 40500; + B 3800 200 39100 40300; + B 3800 200 38900 40100; + B 3800 200 38700 39900; + B 3800 200 38500 39700; + B 3800 200 38300 39500; + B 3800 200 38100 39300; + B 3800 200 37900 39100; + B 3800 200 37700 38900; + B 3800 200 37500 38700; + B 3800 200 37300 38500; + B 3800 200 37100 38300; + B 3800 200 36900 38100; + B 3800 200 36700 37900; + B 3800 200 36500 37700; + B 3800 200 36300 37500; + B 3800 200 36100 37300; + B 3800 200 35900 37100; + B 3800 200 35700 36900; + B 3800 200 35500 36700; + B 3800 200 35300 36500; + B 3800 200 35100 36300; + B 3800 200 34900 36100; + B 3800 200 34700 35900; + B 3800 200 34500 35700; + B 3800 200 34300 35500; + B 3600 200 34200 35300; + B 17800 200 26900 35100; + B 17600 200 26800 34900; + B 17400 200 26700 34700; + B 17200 200 26600 34500; + B 17000 200 26500 34300; + B 16800 200 26400 34100; + B 16600 200 26300 33900; + B 16400 200 26200 33700; + B 1600 800 18800 33200; + B 16000 1600 26000 32000; + B 1600 800 33200 30800; + B 16000 1600 26000 29600; + B 1600 800 18800 28400; + B 16000 1600 26000 27200; + B 1600 800 33200 26000; + B 16000 1600 26000 24800; + B 1600 800 18800 23600; + B 16000 1600 26000 22400; + B 1600 800 33200 21200; + B 16400 200 25800 20700; + B 16600 200 25700 20500; + B 16800 200 25600 20300; + B 17000 200 25500 20100; + B 17200 200 25400 19900; + B 17400 200 25300 19700; + B 17600 200 25200 19500; + B 17800 200 25100 19300; + B 3600 200 17800 19100; + B 3800 200 17700 18900; + B 3800 200 17500 18700; + B 3800 200 17300 18500; + B 3800 200 17100 18300; + B 3800 200 16900 18100; + B 3800 200 16700 17900; + B 3800 200 16500 17700; + B 3800 200 16300 17500; + B 3800 200 16100 17300; + B 3800 200 15900 17100; + B 3800 200 15700 16900; + B 3800 200 15500 16700; + B 3800 200 15300 16500; + B 3800 200 15100 16300; + B 3800 200 14900 16100; + B 3800 200 14700 15900; + B 3800 200 14500 15700; + B 3800 200 14300 15500; + B 3800 200 14100 15300; + B 3800 200 13900 15100; + B 3800 200 13700 14900; + B 3800 200 13500 14700; + B 3800 200 13300 14500; + B 3800 200 13100 14300; + B 3800 200 12900 14100; + B 3800 200 12700 13900; + B 3800 200 12500 13700; + B 3800 200 12300 13500; + B 3800 200 12100 13300; + B 3800 200 11900 13100; + B 3800 200 11700 12900; + B 3800 200 11500 12700; + B 3800 200 11300 12500; + B 3800 200 11100 12300; + B 3800 200 10900 12100; + B 3800 200 10700 11900; + B 3800 200 10500 11700; + B 3800 200 10300 11500; + B 3800 200 10100 11300; + B 3800 200 9900 11100; + B 3800 200 9700 10900; + B 3800 200 9500 10700; + B 3800 200 9300 10500; + B 3800 200 9100 10300; + B 3800 200 8900 10100; + B 3800 200 8700 9900; + B 3800 200 8500 9700; + B 3800 200 8300 9500; + B 3800 200 8100 9300; + B 3800 200 7900 9100; + B 3800 200 7700 8900; + B 3800 200 7500 8700; + B 3800 200 7300 8500; + B 3800 200 7100 8300; + B 3800 200 6900 8100; + B 3800 200 6700 7900; + B 3800 200 6500 7700; + B 3800 200 6300 7500; + B 3800 200 6100 7300; + B 3800 200 5900 7100; + B 3800 200 5700 6900; + B 3800 200 5500 6700; + B 3800 200 5300 6500; + B 3800 200 5100 6300; + B 3800 200 4900 6100; + B 3800 200 4700 5900; + B 3800 200 4500 5700; + B 3800 200 4300 5500; + B 3800 200 4100 5300; + B 3800 200 3900 5100; + B 3800 200 3700 4900; + B 3800 200 3500 4700; + B 3800 200 3300 4500; + B 3800 200 3100 4300; + B 3800 200 2900 4100; + B 3800 200 2700 3900; + B 3800 200 2500 3700; + B 3800 200 2300 3500; + B 3800 200 2100 3300; + B 3800 200 1900 3100; + B 3600 200 1800 2900; + B 3400 200 1700 2700; + B 3200 200 1600 2500; + B 3000 200 1500 2300; + B 2800 200 1400 2100; + B 2600 200 1300 1900; + B 2400 200 1200 1700; + B 2200 200 1100 1500; + B 2000 200 1000 1300; +L CAA; + B 42000 200 25000 49100; + B 41800 200 24900 48900; + B 41600 200 24800 48700; + B 41400 200 24700 48500; + B 41200 200 24600 48300; + B 41000 200 24500 48100; + B 40800 200 24400 47900; + B 40600 200 24300 47700; + B 40400 200 24200 47500; + B 40200 200 24100 47300; + B 2000 4000 5000 45200; + B 32000 200 26000 47100; + B 200 200 47900 47100; + B 31600 200 26000 46900; + B 400 200 47800 46900; + B 31200 200 26000 46700; + B 600 200 47700 46700; + B 30800 200 26000 46500; + B 800 200 47600 46500; + B 30400 200 26000 46300; + B 1000 200 47500 46300; + B 30000 200 26000 46100; + B 1200 200 47400 46100; + B 29600 200 26000 45900; + B 1400 200 47300 45900; + B 29200 200 26000 45700; + B 1600 200 47200 45700; + B 28800 200 26000 45500; + B 1800 200 47100 45500; + B 28400 200 26000 45300; + B 28000 200 26000 45100; + B 27600 200 26000 44900; + B 27200 200 26000 44700; + B 26800 200 26000 44500; + B 26400 200 26000 44300; + B 26000 200 26000 44100; + B 25600 200 26000 43900; + B 25200 200 26000 43700; + B 24800 200 26000 43500; + B 24400 200 26000 43300; + B 2000 2200 47000 44300; + B 2200 200 5100 43100; + B 24000 200 26000 43100; + B 2200 200 46900 43100; + B 2400 200 5200 42900; + B 23600 200 26000 42900; + B 2400 200 46800 42900; + B 2600 200 5300 42700; + B 23200 200 26000 42700; + B 2600 200 46700 42700; + B 2800 200 5400 42500; + B 22800 200 26000 42500; + B 2800 200 46600 42500; + B 3000 200 5500 42300; + B 22400 200 26000 42300; + B 3000 200 46500 42300; + B 3200 200 5600 42100; + B 22000 200 26000 42100; + B 3200 200 46400 42100; + B 3400 200 5700 41900; + B 21600 200 26000 41900; + B 3400 200 46300 41900; + B 3600 200 5800 41700; + B 21200 200 26000 41700; + B 3600 200 46200 41700; + B 3800 200 5900 41500; + B 20800 200 26000 41500; + B 3800 200 46100 41500; + B 4000 200 6000 41300; + B 20400 200 26000 41300; + B 4000 200 46000 41300; + B 4200 200 6100 41100; + B 20000 200 26000 41100; + B 4200 200 45900 41100; + B 4400 200 6200 40900; + B 19600 200 26000 40900; + B 4400 200 45800 40900; + B 4600 200 6300 40700; + B 19200 200 26000 40700; + B 4600 200 45700 40700; + B 4800 200 6400 40500; + B 18800 200 26000 40500; + B 4800 200 45600 40500; + B 5000 200 6500 40300; + B 18400 200 26000 40300; + B 5000 200 45500 40300; + B 5200 200 6600 40100; + B 18000 200 26000 40100; + B 5200 200 45400 40100; + B 5400 200 6700 39900; + B 17600 200 26000 39900; + B 5400 200 45300 39900; + B 5600 200 6800 39700; + B 17200 200 26000 39700; + B 5600 200 45200 39700; + B 5800 200 6900 39500; + B 16800 200 26000 39500; + B 5800 200 45100 39500; + B 6000 200 7000 39300; + B 16400 200 26000 39300; + B 6000 200 45000 39300; + B 6200 200 7100 39100; + B 16000 200 26000 39100; + B 6200 200 44900 39100; + B 6400 200 7200 38900; + B 15600 200 26000 38900; + B 6400 200 44800 38900; + B 6600 200 7300 38700; + B 15200 200 26000 38700; + B 6600 200 44700 38700; + B 6800 200 7400 38500; + B 14800 200 26000 38500; + B 6800 200 44600 38500; + B 7000 200 7500 38300; + B 14400 200 26000 38300; + B 7000 200 44500 38300; + B 7200 200 7600 38100; + B 14000 200 26000 38100; + B 7200 200 44400 38100; + B 7400 200 7700 37900; + B 13600 200 26000 37900; + B 7400 200 44300 37900; + B 7600 200 7800 37700; + B 13200 200 26000 37700; + B 7600 200 44200 37700; + B 7800 200 7900 37500; + B 12800 200 26000 37500; + B 7800 200 44100 37500; + B 8000 200 8000 37300; + B 12400 200 26000 37300; + B 8000 200 44000 37300; + B 8200 200 8100 37100; + B 8200 200 43900 37100; + B 8400 200 8200 36900; + B 8400 200 43800 36900; + B 8600 200 8300 36700; + B 8600 200 43700 36700; + B 8800 200 8400 36500; + B 8800 200 43600 36500; + B 9000 200 8500 36300; + B 9000 200 43500 36300; + B 9200 200 8600 36100; + B 9200 200 43400 36100; + B 9400 200 8700 35900; + B 9400 200 43300 35900; + B 9600 200 8800 35700; + B 9600 200 43200 35700; + B 9800 200 8900 35500; + B 9800 200 43100 35500; + B 10000 200 9000 35300; + B 10000 200 43000 35300; + B 10200 200 9100 35100; + B 10200 200 42900 35100; + B 10400 200 9200 34900; + B 10400 200 42800 34900; + B 10600 200 9300 34700; + B 10600 200 42700 34700; + B 10800 200 9400 34500; + B 10800 200 42600 34500; + B 11000 200 9500 34300; + B 11000 200 42500 34300; + B 11200 200 9600 34100; + B 11200 200 42400 34100; + B 11400 200 9700 33900; + B 11400 200 42300 33900; + B 11600 200 9800 33700; + B 11600 200 42200 33700; + B 11800 200 9900 33500; + B 11800 200 42100 33500; + B 12000 12400 10000 27200; + B 12000 12400 42000 27200; + B 11800 200 9900 20900; + B 11800 200 42100 20900; + B 11600 200 9800 20700; + B 11600 200 42200 20700; + B 11400 200 9700 20500; + B 11400 200 42300 20500; + B 11200 200 9600 20300; + B 11200 200 42400 20300; + B 11000 200 9500 20100; + B 11000 200 42500 20100; + B 10800 200 9400 19900; + B 10800 200 42600 19900; + B 10600 200 9300 19700; + B 10600 200 42700 19700; + B 10400 200 9200 19500; + B 10400 200 42800 19500; + B 10200 200 9100 19300; + B 10200 200 42900 19300; + B 10000 200 9000 19100; + B 10000 200 43000 19100; + B 9800 200 8900 18900; + B 9800 200 43100 18900; + B 9600 200 8800 18700; + B 9600 200 43200 18700; + B 9400 200 8700 18500; + B 9400 200 43300 18500; + B 9200 200 8600 18300; + B 9200 200 43400 18300; + B 9000 200 8500 18100; + B 9000 200 43500 18100; + B 8800 200 8400 17900; + B 8800 200 43600 17900; + B 8600 200 8300 17700; + B 8600 200 43700 17700; + B 8400 200 8200 17500; + B 8400 200 43800 17500; + B 8200 200 8100 17300; + B 8200 200 43900 17300; + B 8000 200 8000 17100; + B 12400 200 26000 17100; + B 8000 200 44000 17100; + B 7800 200 7900 16900; + B 12800 200 26000 16900; + B 7800 200 44100 16900; + B 7600 200 7800 16700; + B 13200 200 26000 16700; + B 7600 200 44200 16700; + B 7400 200 7700 16500; + B 13600 200 26000 16500; + B 7400 200 44300 16500; + B 7200 200 7600 16300; + B 14000 200 26000 16300; + B 7200 200 44400 16300; + B 7000 200 7500 16100; + B 14400 200 26000 16100; + B 7000 200 44500 16100; + B 6800 200 7400 15900; + B 14800 200 26000 15900; + B 6800 200 44600 15900; + B 6600 200 7300 15700; + B 15200 200 26000 15700; + B 6600 200 44700 15700; + B 6400 200 7200 15500; + B 15600 200 26000 15500; + B 6400 200 44800 15500; + B 6200 200 7100 15300; + B 16000 200 26000 15300; + B 6200 200 44900 15300; + B 6000 200 7000 15100; + B 16400 200 26000 15100; + B 6000 200 45000 15100; + B 5800 200 6900 14900; + B 16800 200 26000 14900; + B 5800 200 45100 14900; + B 5600 200 6800 14700; + B 17200 200 26000 14700; + B 5600 200 45200 14700; + B 5400 200 6700 14500; + B 17600 200 26000 14500; + B 5400 200 45300 14500; + B 5200 200 6600 14300; + B 18000 200 26000 14300; + B 5200 200 45400 14300; + B 5000 200 6500 14100; + B 18400 200 26000 14100; + B 5000 200 45500 14100; + B 4800 200 6400 13900; + B 18800 200 26000 13900; + B 4800 200 45600 13900; + B 4600 200 6300 13700; + B 19200 200 26000 13700; + B 4600 200 45700 13700; + B 4400 200 6200 13500; + B 19600 200 26000 13500; + B 4400 200 45800 13500; + B 4200 200 6100 13300; + B 20000 200 26000 13300; + B 4200 200 45900 13300; + B 4000 200 6000 13100; + B 20400 200 26000 13100; + B 4000 200 46000 13100; + B 3800 200 5900 12900; + B 20800 200 26000 12900; + B 3800 200 46100 12900; + B 3600 200 5800 12700; + B 21200 200 26000 12700; + B 3600 200 46200 12700; + B 3400 200 5700 12500; + B 21600 200 26000 12500; + B 3400 200 46300 12500; + B 3200 200 5600 12300; + B 22000 200 26000 12300; + B 3200 200 46400 12300; + B 3000 200 5500 12100; + B 22400 200 26000 12100; + B 3000 200 46500 12100; + B 2800 200 5400 11900; + B 22800 200 26000 11900; + B 2800 200 46600 11900; + B 2600 200 5300 11700; + B 23200 200 26000 11700; + B 2600 200 46700 11700; + B 2400 200 5200 11500; + B 23600 200 26000 11500; + B 2400 200 46800 11500; + B 2200 200 5100 11300; + B 24000 200 26000 11300; + B 2200 200 46900 11300; + B 2000 2200 5000 10100; + B 24400 200 26000 11100; + B 24800 200 26000 10900; + B 25200 200 26000 10700; + B 25600 200 26000 10500; + B 26000 200 26000 10300; + B 26400 200 26000 10100; + B 26800 200 26000 9900; + B 27200 200 26000 9700; + B 27600 200 26000 9500; + B 28000 200 26000 9300; + B 28400 200 26000 9100; + B 1800 200 4900 8900; + B 28800 200 26000 8900; + B 1600 200 4800 8700; + B 29200 200 26000 8700; + B 1400 200 4700 8500; + B 29600 200 26000 8500; + B 1200 200 4600 8300; + B 30000 200 26000 8300; + B 1000 200 4500 8100; + B 30400 200 26000 8100; + B 800 200 4400 7900; + B 30800 200 26000 7900; + B 600 200 4300 7700; + B 31200 200 26000 7700; + B 400 200 4200 7500; + B 31600 200 26000 7500; + B 200 200 4100 7300; + B 32000 200 26000 7300; + B 2000 4000 47000 9200; + B 40200 200 27900 7100; + B 40400 200 27800 6900; + B 40600 200 27700 6700; + B 40800 200 27600 6500; + B 41000 200 27500 6300; + B 41200 200 27400 6100; + B 41400 200 27300 5900; + B 41600 200 27200 5700; + B 41800 200 27100 5500; + B 42000 200 27000 5300; +L CVA; + B 32000 200 26000 47100; + B 31600 200 26000 46900; + B 31200 200 26000 46700; + B 30800 200 26000 46500; + B 30400 200 26000 46300; + B 30000 200 26000 46100; + B 29600 200 26000 45900; + B 29200 200 26000 45700; + B 28800 200 26000 45500; + B 28400 200 26000 45300; + B 28000 200 26000 45100; + B 27600 200 26000 44900; + B 27200 200 26000 44700; + B 26800 200 26000 44500; + B 26400 200 26000 44300; + B 26000 200 26000 44100; + B 25600 200 26000 43900; + B 25200 200 26000 43700; + B 24800 200 26000 43500; + B 24400 200 26000 43300; + B 200 200 6100 43100; + B 24000 200 26000 43100; + B 200 200 45900 43100; + B 400 200 6200 42900; + B 23600 200 26000 42900; + B 400 200 45800 42900; + B 600 200 6300 42700; + B 23200 200 26000 42700; + B 600 200 45700 42700; + B 800 200 6400 42500; + B 22800 200 26000 42500; + B 800 200 45600 42500; + B 1000 200 6500 42300; + B 22400 200 26000 42300; + B 1000 200 45500 42300; + B 1200 200 6600 42100; + B 22000 200 26000 42100; + B 1200 200 45400 42100; + B 1400 200 6700 41900; + B 21600 200 26000 41900; + B 1400 200 45300 41900; + B 1600 200 6800 41700; + B 21200 200 26000 41700; + B 1600 200 45200 41700; + B 1800 200 6900 41500; + B 20800 200 26000 41500; + B 1800 200 45100 41500; + B 2000 200 7000 41300; + B 20400 200 26000 41300; + B 2000 200 45000 41300; + B 2200 200 7100 41100; + B 20000 200 26000 41100; + B 2200 200 44900 41100; + B 2400 200 7200 40900; + B 19600 200 26000 40900; + B 2400 200 44800 40900; + B 2600 200 7300 40700; + B 19200 200 26000 40700; + B 2600 200 44700 40700; + B 2800 200 7400 40500; + B 18800 200 26000 40500; + B 2800 200 44600 40500; + B 3000 200 7500 40300; + B 18400 200 26000 40300; + B 3000 200 44500 40300; + B 3200 200 7600 40100; + B 18000 200 26000 40100; + B 3200 200 44400 40100; + B 3400 200 7700 39900; + B 17600 200 26000 39900; + B 3400 200 44300 39900; + B 3600 200 7800 39700; + B 17200 200 26000 39700; + B 3600 200 44200 39700; + B 3800 200 7900 39500; + B 16800 200 26000 39500; + B 3800 200 44100 39500; + B 4000 200 8000 39300; + B 16400 200 26000 39300; + B 4000 200 44000 39300; + B 4200 200 8100 39100; + B 16000 200 26000 39100; + B 4200 200 43900 39100; + B 4400 200 8200 38900; + B 15600 200 26000 38900; + B 4400 200 43800 38900; + B 4600 200 8300 38700; + B 15200 200 26000 38700; + B 4600 200 43700 38700; + B 4800 200 8400 38500; + B 14800 200 26000 38500; + B 4800 200 43600 38500; + B 5000 200 8500 38300; + B 14400 200 26000 38300; + B 5000 200 43500 38300; + B 5200 200 8600 38100; + B 14000 200 26000 38100; + B 5200 200 43400 38100; + B 5400 200 8700 37900; + B 13600 200 26000 37900; + B 5400 200 43300 37900; + B 5600 200 8800 37700; + B 13200 200 26000 37700; + B 5600 200 43200 37700; + B 5800 200 8900 37500; + B 12800 200 26000 37500; + B 5800 200 43100 37500; + B 6000 200 9000 37300; + B 12400 200 26000 37300; + B 6000 200 43000 37300; + B 6200 200 9100 37100; + B 6200 200 42900 37100; + B 6400 200 9200 36900; + B 6400 200 42800 36900; + B 6600 200 9300 36700; + B 6600 200 42700 36700; + B 6800 200 9400 36500; + B 6800 200 42600 36500; + B 7000 200 9500 36300; + B 7000 200 42500 36300; + B 7200 200 9600 36100; + B 7200 200 42400 36100; + B 7400 200 9700 35900; + B 7400 200 42300 35900; + B 7600 200 9800 35700; + B 7600 200 42200 35700; + B 7800 200 9900 35500; + B 7800 200 42100 35500; + B 8000 200 10000 35300; + B 8000 200 42000 35300; + B 8200 200 10100 35100; + B 8200 200 41900 35100; + B 8400 200 10200 34900; + B 8400 200 41800 34900; + B 8600 200 10300 34700; + B 8600 200 41700 34700; + B 8800 200 10400 34500; + B 8800 200 41600 34500; + B 9000 200 10500 34300; + B 9000 200 41500 34300; + B 9200 200 10600 34100; + B 9200 200 41400 34100; + B 9400 200 10700 33900; + B 9400 200 41300 33900; + B 9600 200 10800 33700; + B 9600 200 41200 33700; + B 9800 200 10900 33500; + B 9800 200 41100 33500; + B 10000 12400 11000 27200; + B 10000 12400 41000 27200; + B 9800 200 10900 20900; + B 9800 200 41100 20900; + B 9600 200 10800 20700; + B 9600 200 41200 20700; + B 9400 200 10700 20500; + B 9400 200 41300 20500; + B 9200 200 10600 20300; + B 9200 200 41400 20300; + B 9000 200 10500 20100; + B 9000 200 41500 20100; + B 8800 200 10400 19900; + B 8800 200 41600 19900; + B 8600 200 10300 19700; + B 8600 200 41700 19700; + B 8400 200 10200 19500; + B 8400 200 41800 19500; + B 8200 200 10100 19300; + B 8200 200 41900 19300; + B 8000 200 10000 19100; + B 8000 200 42000 19100; + B 7800 200 9900 18900; + B 7800 200 42100 18900; + B 7600 200 9800 18700; + B 7600 200 42200 18700; + B 7400 200 9700 18500; + B 7400 200 42300 18500; + B 7200 200 9600 18300; + B 7200 200 42400 18300; + B 7000 200 9500 18100; + B 7000 200 42500 18100; + B 6800 200 9400 17900; + B 6800 200 42600 17900; + B 6600 200 9300 17700; + B 6600 200 42700 17700; + B 6400 200 9200 17500; + B 6400 200 42800 17500; + B 6200 200 9100 17300; + B 6200 200 42900 17300; + B 6000 200 9000 17100; + B 12400 200 26000 17100; + B 6000 200 43000 17100; + B 5800 200 8900 16900; + B 12800 200 26000 16900; + B 5800 200 43100 16900; + B 5600 200 8800 16700; + B 13200 200 26000 16700; + B 5600 200 43200 16700; + B 5400 200 8700 16500; + B 13600 200 26000 16500; + B 5400 200 43300 16500; + B 5200 200 8600 16300; + B 14000 200 26000 16300; + B 5200 200 43400 16300; + B 5000 200 8500 16100; + B 14400 200 26000 16100; + B 5000 200 43500 16100; + B 4800 200 8400 15900; + B 14800 200 26000 15900; + B 4800 200 43600 15900; + B 4600 200 8300 15700; + B 15200 200 26000 15700; + B 4600 200 43700 15700; + B 4400 200 8200 15500; + B 15600 200 26000 15500; + B 4400 200 43800 15500; + B 4200 200 8100 15300; + B 16000 200 26000 15300; + B 4200 200 43900 15300; + B 4000 200 8000 15100; + B 16400 200 26000 15100; + B 4000 200 44000 15100; + B 3800 200 7900 14900; + B 16800 200 26000 14900; + B 3800 200 44100 14900; + B 3600 200 7800 14700; + B 17200 200 26000 14700; + B 3600 200 44200 14700; + B 3400 200 7700 14500; + B 17600 200 26000 14500; + B 3400 200 44300 14500; + B 3200 200 7600 14300; + B 18000 200 26000 14300; + B 3200 200 44400 14300; + B 3000 200 7500 14100; + B 18400 200 26000 14100; + B 3000 200 44500 14100; + B 2800 200 7400 13900; + B 18800 200 26000 13900; + B 2800 200 44600 13900; + B 2600 200 7300 13700; + B 19200 200 26000 13700; + B 2600 200 44700 13700; + B 2400 200 7200 13500; + B 19600 200 26000 13500; + B 2400 200 44800 13500; + B 2200 200 7100 13300; + B 20000 200 26000 13300; + B 2200 200 44900 13300; + B 2000 200 7000 13100; + B 20400 200 26000 13100; + B 2000 200 45000 13100; + B 1800 200 6900 12900; + B 20800 200 26000 12900; + B 1800 200 45100 12900; + B 1600 200 6800 12700; + B 21200 200 26000 12700; + B 1600 200 45200 12700; + B 1400 200 6700 12500; + B 21600 200 26000 12500; + B 1400 200 45300 12500; + B 1200 200 6600 12300; + B 22000 200 26000 12300; + B 1200 200 45400 12300; + B 1000 200 6500 12100; + B 22400 200 26000 12100; + B 1000 200 45500 12100; + B 800 200 6400 11900; + B 22800 200 26000 11900; + B 800 200 45600 11900; + B 600 200 6300 11700; + B 23200 200 26000 11700; + B 600 200 45700 11700; + B 400 200 6200 11500; + B 23600 200 26000 11500; + B 400 200 45800 11500; + B 200 200 6100 11300; + B 24000 200 26000 11300; + B 200 200 45900 11300; + B 24400 200 26000 11100; + B 24800 200 26000 10900; + B 25200 200 26000 10700; + B 25600 200 26000 10500; + B 26000 200 26000 10300; + B 26400 200 26000 10100; + B 26800 200 26000 9900; + B 27200 200 26000 9700; + B 27600 200 26000 9500; + B 28000 200 26000 9300; + B 28400 200 26000 9100; + B 28800 200 26000 8900; + B 29200 200 26000 8700; + B 29600 200 26000 8500; + B 30000 200 26000 8300; + B 30400 200 26000 8100; + B 30800 200 26000 7900; + B 31200 200 26000 7700; + B 31600 200 26000 7500; + B 32000 200 26000 7300; +L CCA; + B 32000 200 26000 47100; + B 31600 200 26000 46900; + B 31200 200 26000 46700; + B 30800 200 26000 46500; + B 30400 200 26000 46300; + B 30000 200 26000 46100; + B 29600 200 26000 45900; + B 29200 200 26000 45700; + B 28800 200 26000 45500; + B 28400 200 26000 45300; + B 28000 200 26000 45100; + B 27600 200 26000 44900; + B 27200 200 26000 44700; + B 26800 200 26000 44500; + B 26400 200 26000 44300; + B 26000 200 26000 44100; + B 25600 200 26000 43900; + B 25200 200 26000 43700; + B 24800 200 26000 43500; + B 24400 200 26000 43300; + B 200 200 6100 43100; + B 24000 200 26000 43100; + B 200 200 45900 43100; + B 400 200 6200 42900; + B 23600 200 26000 42900; + B 400 200 45800 42900; + B 600 200 6300 42700; + B 23200 200 26000 42700; + B 600 200 45700 42700; + B 800 200 6400 42500; + B 22800 200 26000 42500; + B 800 200 45600 42500; + B 1000 200 6500 42300; + B 22400 200 26000 42300; + B 1000 200 45500 42300; + B 1200 200 6600 42100; + B 22000 200 26000 42100; + B 1200 200 45400 42100; + B 1400 200 6700 41900; + B 21600 200 26000 41900; + B 1400 200 45300 41900; + B 1600 200 6800 41700; + B 21200 200 26000 41700; + B 1600 200 45200 41700; + B 1800 200 6900 41500; + B 20800 200 26000 41500; + B 1800 200 45100 41500; + B 2000 200 7000 41300; + B 20400 200 26000 41300; + B 2000 200 45000 41300; + B 2200 200 7100 41100; + B 20000 200 26000 41100; + B 2200 200 44900 41100; + B 2400 200 7200 40900; + B 19600 200 26000 40900; + B 2400 200 44800 40900; + B 2600 200 7300 40700; + B 19200 200 26000 40700; + B 2600 200 44700 40700; + B 2800 200 7400 40500; + B 18800 200 26000 40500; + B 2800 200 44600 40500; + B 3000 200 7500 40300; + B 18400 200 26000 40300; + B 3000 200 44500 40300; + B 3200 200 7600 40100; + B 18000 200 26000 40100; + B 3200 200 44400 40100; + B 3400 200 7700 39900; + B 17600 200 26000 39900; + B 3400 200 44300 39900; + B 3600 200 7800 39700; + B 17200 200 26000 39700; + B 3600 200 44200 39700; + B 3800 200 7900 39500; + B 16800 200 26000 39500; + B 3800 200 44100 39500; + B 4000 200 8000 39300; + B 16400 200 26000 39300; + B 4000 200 44000 39300; + B 4200 200 8100 39100; + B 16000 200 26000 39100; + B 4200 200 43900 39100; + B 4400 200 8200 38900; + B 15600 200 26000 38900; + B 4400 200 43800 38900; + B 4600 200 8300 38700; + B 15200 200 26000 38700; + B 4600 200 43700 38700; + B 4800 200 8400 38500; + B 14800 200 26000 38500; + B 4800 200 43600 38500; + B 5000 200 8500 38300; + B 14400 200 26000 38300; + B 5000 200 43500 38300; + B 5200 200 8600 38100; + B 14000 200 26000 38100; + B 5200 200 43400 38100; + B 5400 200 8700 37900; + B 13600 200 26000 37900; + B 5400 200 43300 37900; + B 5600 200 8800 37700; + B 13200 200 26000 37700; + B 5600 200 43200 37700; + B 5800 200 8900 37500; + B 12800 200 26000 37500; + B 5800 200 43100 37500; + B 6000 200 9000 37300; + B 12400 200 26000 37300; + B 6000 200 43000 37300; + B 6200 200 9100 37100; + B 6200 200 42900 37100; + B 6400 200 9200 36900; + B 6400 200 42800 36900; + B 6600 200 9300 36700; + B 6600 200 42700 36700; + B 6800 200 9400 36500; + B 6800 200 42600 36500; + B 7000 200 9500 36300; + B 7000 200 42500 36300; + B 7200 200 9600 36100; + B 7200 200 42400 36100; + B 7400 200 9700 35900; + B 7400 200 42300 35900; + B 7600 200 9800 35700; + B 7600 200 42200 35700; + B 7800 200 9900 35500; + B 7800 200 42100 35500; + B 8000 200 10000 35300; + B 8000 200 42000 35300; + B 8200 200 10100 35100; + B 8200 200 41900 35100; + B 8400 200 10200 34900; + B 8400 200 41800 34900; + B 8600 200 10300 34700; + B 8600 200 41700 34700; + B 8800 200 10400 34500; + B 8800 200 41600 34500; + B 9000 200 10500 34300; + B 9000 200 41500 34300; + B 9200 200 10600 34100; + B 9200 200 41400 34100; + B 9400 200 10700 33900; + B 9400 200 41300 33900; + B 9600 200 10800 33700; + B 9600 200 41200 33700; + B 9800 200 10900 33500; + B 9800 200 41100 33500; + B 10000 12400 11000 27200; + B 10000 12400 41000 27200; + B 9800 200 10900 20900; + B 9800 200 41100 20900; + B 9600 200 10800 20700; + B 9600 200 41200 20700; + B 9400 200 10700 20500; + B 9400 200 41300 20500; + B 9200 200 10600 20300; + B 9200 200 41400 20300; + B 9000 200 10500 20100; + B 9000 200 41500 20100; + B 8800 200 10400 19900; + B 8800 200 41600 19900; + B 8600 200 10300 19700; + B 8600 200 41700 19700; + B 8400 200 10200 19500; + B 8400 200 41800 19500; + B 8200 200 10100 19300; + B 8200 200 41900 19300; + B 8000 200 10000 19100; + B 8000 200 42000 19100; + B 7800 200 9900 18900; + B 7800 200 42100 18900; + B 7600 200 9800 18700; + B 7600 200 42200 18700; + B 7400 200 9700 18500; + B 7400 200 42300 18500; + B 7200 200 9600 18300; + B 7200 200 42400 18300; + B 7000 200 9500 18100; + B 7000 200 42500 18100; + B 6800 200 9400 17900; + B 6800 200 42600 17900; + B 6600 200 9300 17700; + B 6600 200 42700 17700; + B 6400 200 9200 17500; + B 6400 200 42800 17500; + B 6200 200 9100 17300; + B 6200 200 42900 17300; + B 6000 200 9000 17100; + B 12400 200 26000 17100; + B 6000 200 43000 17100; + B 5800 200 8900 16900; + B 12800 200 26000 16900; + B 5800 200 43100 16900; + B 5600 200 8800 16700; + B 13200 200 26000 16700; + B 5600 200 43200 16700; + B 5400 200 8700 16500; + B 13600 200 26000 16500; + B 5400 200 43300 16500; + B 5200 200 8600 16300; + B 14000 200 26000 16300; + B 5200 200 43400 16300; + B 5000 200 8500 16100; + B 14400 200 26000 16100; + B 5000 200 43500 16100; + B 4800 200 8400 15900; + B 14800 200 26000 15900; + B 4800 200 43600 15900; + B 4600 200 8300 15700; + B 15200 200 26000 15700; + B 4600 200 43700 15700; + B 4400 200 8200 15500; + B 15600 200 26000 15500; + B 4400 200 43800 15500; + B 4200 200 8100 15300; + B 16000 200 26000 15300; + B 4200 200 43900 15300; + B 4000 200 8000 15100; + B 16400 200 26000 15100; + B 4000 200 44000 15100; + B 3800 200 7900 14900; + B 16800 200 26000 14900; + B 3800 200 44100 14900; + B 3600 200 7800 14700; + B 17200 200 26000 14700; + B 3600 200 44200 14700; + B 3400 200 7700 14500; + B 17600 200 26000 14500; + B 3400 200 44300 14500; + B 3200 200 7600 14300; + B 18000 200 26000 14300; + B 3200 200 44400 14300; + B 3000 200 7500 14100; + B 18400 200 26000 14100; + B 3000 200 44500 14100; + B 2800 200 7400 13900; + B 18800 200 26000 13900; + B 2800 200 44600 13900; + B 2600 200 7300 13700; + B 19200 200 26000 13700; + B 2600 200 44700 13700; + B 2400 200 7200 13500; + B 19600 200 26000 13500; + B 2400 200 44800 13500; + B 2200 200 7100 13300; + B 20000 200 26000 13300; + B 2200 200 44900 13300; + B 2000 200 7000 13100; + B 20400 200 26000 13100; + B 2000 200 45000 13100; + B 1800 200 6900 12900; + B 20800 200 26000 12900; + B 1800 200 45100 12900; + B 1600 200 6800 12700; + B 21200 200 26000 12700; + B 1600 200 45200 12700; + B 1400 200 6700 12500; + B 21600 200 26000 12500; + B 1400 200 45300 12500; + B 1200 200 6600 12300; + B 22000 200 26000 12300; + B 1200 200 45400 12300; + B 1000 200 6500 12100; + B 22400 200 26000 12100; + B 1000 200 45500 12100; + B 800 200 6400 11900; + B 22800 200 26000 11900; + B 800 200 45600 11900; + B 600 200 6300 11700; + B 23200 200 26000 11700; + B 600 200 45700 11700; + B 400 200 6200 11500; + B 23600 200 26000 11500; + B 400 200 45800 11500; + B 200 200 6100 11300; + B 24000 200 26000 11300; + B 200 200 45900 11300; + B 24400 200 26000 11100; + B 24800 200 26000 10900; + B 25200 200 26000 10700; + B 25600 200 26000 10500; + B 26000 200 26000 10300; + B 26400 200 26000 10100; + B 26800 200 26000 9900; + B 27200 200 26000 9700; + B 27600 200 26000 9500; + B 28000 200 26000 9300; + B 28400 200 26000 9100; + B 28800 200 26000 8900; + B 29200 200 26000 8700; + B 29600 200 26000 8500; + B 30000 200 26000 8300; + B 30400 200 26000 8100; + B 30800 200 26000 7900; + B 31200 200 26000 7700; + B 31600 200 26000 7500; + B 32000 200 26000 7300; +L CCP; + B 400 400 51000 52200; + B 400 400 1000 2200; +L CSP; + B 42800 1000 25000 49100; + B 42600 200 24900 48500; + B 42400 200 24800 48300; + B 42200 200 24700 48100; + B 42000 200 24600 47900; + B 41800 200 24500 47700; + B 41600 200 24400 47500; + B 1000 200 47900 47500; + B 41400 200 24300 47300; + B 1200 200 47800 47300; + B 41200 200 24200 47100; + B 1400 200 47700 47100; + B 41000 200 24100 46900; + B 1600 200 47600 46900; + B 2800 38200 5000 27700; + B 1800 200 47500 46700; + B 2000 200 47400 46500; + B 2200 200 47300 46300; + B 2400 200 47200 46100; + B 2600 200 47100 45900; + B 2600 200 4900 8500; + B 2400 200 4800 8300; + B 2200 200 4700 8100; + B 2000 200 4600 7900; + B 1800 200 4500 7700; + B 2800 38200 47000 26700; + B 1600 200 4400 7500; + B 41000 200 27900 7500; + B 1400 200 4300 7300; + B 41200 200 27800 7300; + B 1200 200 4200 7100; + B 41400 200 27700 7100; + B 1000 200 4100 6900; + B 41600 200 27600 6900; + B 41800 200 27500 6700; + B 42000 200 27400 6500; + B 42200 200 27300 6300; + B 42400 200 27200 6100; + B 42600 200 27100 5900; + B 42800 1000 27000 5300; +L COG; + B 32000 200 26000 47100; + B 31600 200 26000 46900; + B 31200 200 26000 46700; + B 30800 200 26000 46500; + B 30400 200 26000 46300; + B 30000 200 26000 46100; + B 29600 200 26000 45900; + B 29200 200 26000 45700; + B 28800 200 26000 45500; + B 28400 200 26000 45300; + B 28000 200 26000 45100; + B 27600 200 26000 44900; + B 27200 200 26000 44700; + B 26800 200 26000 44500; + B 26400 200 26000 44300; + B 26000 200 26000 44100; + B 25600 200 26000 43900; + B 25200 200 26000 43700; + B 24800 200 26000 43500; + B 24400 200 26000 43300; + B 200 200 6100 43100; + B 24000 200 26000 43100; + B 200 200 45900 43100; + B 400 200 6200 42900; + B 23600 200 26000 42900; + B 400 200 45800 42900; + B 600 200 6300 42700; + B 23200 200 26000 42700; + B 600 200 45700 42700; + B 800 200 6400 42500; + B 22800 200 26000 42500; + B 800 200 45600 42500; + B 1000 200 6500 42300; + B 22400 200 26000 42300; + B 1000 200 45500 42300; + B 1200 200 6600 42100; + B 22000 200 26000 42100; + B 1200 200 45400 42100; + B 1400 200 6700 41900; + B 21600 200 26000 41900; + B 1400 200 45300 41900; + B 1600 200 6800 41700; + B 21200 200 26000 41700; + B 1600 200 45200 41700; + B 1800 200 6900 41500; + B 20800 200 26000 41500; + B 1800 200 45100 41500; + B 2000 200 7000 41300; + B 20400 200 26000 41300; + B 2000 200 45000 41300; + B 2200 200 7100 41100; + B 20000 200 26000 41100; + B 2200 200 44900 41100; + B 2400 200 7200 40900; + B 19600 200 26000 40900; + B 2400 200 44800 40900; + B 2600 200 7300 40700; + B 19200 200 26000 40700; + B 2600 200 44700 40700; + B 2800 200 7400 40500; + B 18800 200 26000 40500; + B 2800 200 44600 40500; + B 3000 200 7500 40300; + B 18400 200 26000 40300; + B 3000 200 44500 40300; + B 3200 200 7600 40100; + B 18000 200 26000 40100; + B 3200 200 44400 40100; + B 3400 200 7700 39900; + B 17600 200 26000 39900; + B 3400 200 44300 39900; + B 3600 200 7800 39700; + B 17200 200 26000 39700; + B 3600 200 44200 39700; + B 3800 200 7900 39500; + B 16800 200 26000 39500; + B 3800 200 44100 39500; + B 4000 200 8000 39300; + B 16400 200 26000 39300; + B 4000 200 44000 39300; + B 4200 200 8100 39100; + B 16000 200 26000 39100; + B 4200 200 43900 39100; + B 4400 200 8200 38900; + B 15600 200 26000 38900; + B 4400 200 43800 38900; + B 4600 200 8300 38700; + B 15200 200 26000 38700; + B 4600 200 43700 38700; + B 4800 200 8400 38500; + B 14800 200 26000 38500; + B 4800 200 43600 38500; + B 5000 200 8500 38300; + B 14400 200 26000 38300; + B 5000 200 43500 38300; + B 5200 200 8600 38100; + B 14000 200 26000 38100; + B 5200 200 43400 38100; + B 5400 200 8700 37900; + B 13600 200 26000 37900; + B 5400 200 43300 37900; + B 5600 200 8800 37700; + B 13200 200 26000 37700; + B 5600 200 43200 37700; + B 5800 200 8900 37500; + B 12800 200 26000 37500; + B 5800 200 43100 37500; + B 6000 200 9000 37300; + B 12400 200 26000 37300; + B 6000 200 43000 37300; + B 6200 200 9100 37100; + B 6200 200 42900 37100; + B 6400 200 9200 36900; + B 6400 200 42800 36900; + B 6600 200 9300 36700; + B 6600 200 42700 36700; + B 6800 200 9400 36500; + B 6800 200 42600 36500; + B 7000 200 9500 36300; + B 7000 200 42500 36300; + B 7200 200 9600 36100; + B 7200 200 42400 36100; + B 7400 200 9700 35900; + B 7400 200 42300 35900; + B 7600 200 9800 35700; + B 7600 200 42200 35700; + B 7800 200 9900 35500; + B 7800 200 42100 35500; + B 8000 200 10000 35300; + B 8000 200 42000 35300; + B 8200 200 10100 35100; + B 8200 200 41900 35100; + B 8400 200 10200 34900; + B 8400 200 41800 34900; + B 8600 200 10300 34700; + B 8600 200 41700 34700; + B 8800 200 10400 34500; + B 8800 200 41600 34500; + B 9000 200 10500 34300; + B 9000 200 41500 34300; + B 9200 200 10600 34100; + B 9200 200 41400 34100; + B 9400 200 10700 33900; + B 9400 200 41300 33900; + B 9600 200 10800 33700; + B 9600 200 41200 33700; + B 9800 200 10900 33500; + B 9800 200 41100 33500; + B 10000 12400 11000 27200; + B 10000 12400 41000 27200; + B 9800 200 10900 20900; + B 9800 200 41100 20900; + B 9600 200 10800 20700; + B 9600 200 41200 20700; + B 9400 200 10700 20500; + B 9400 200 41300 20500; + B 9200 200 10600 20300; + B 9200 200 41400 20300; + B 9000 200 10500 20100; + B 9000 200 41500 20100; + B 8800 200 10400 19900; + B 8800 200 41600 19900; + B 8600 200 10300 19700; + B 8600 200 41700 19700; + B 8400 200 10200 19500; + B 8400 200 41800 19500; + B 8200 200 10100 19300; + B 8200 200 41900 19300; + B 8000 200 10000 19100; + B 8000 200 42000 19100; + B 7800 200 9900 18900; + B 7800 200 42100 18900; + B 7600 200 9800 18700; + B 7600 200 42200 18700; + B 7400 200 9700 18500; + B 7400 200 42300 18500; + B 7200 200 9600 18300; + B 7200 200 42400 18300; + B 7000 200 9500 18100; + B 7000 200 42500 18100; + B 6800 200 9400 17900; + B 6800 200 42600 17900; + B 6600 200 9300 17700; + B 6600 200 42700 17700; + B 6400 200 9200 17500; + B 6400 200 42800 17500; + B 6200 200 9100 17300; + B 6200 200 42900 17300; + B 6000 200 9000 17100; + B 12400 200 26000 17100; + B 6000 200 43000 17100; + B 5800 200 8900 16900; + B 12800 200 26000 16900; + B 5800 200 43100 16900; + B 5600 200 8800 16700; + B 13200 200 26000 16700; + B 5600 200 43200 16700; + B 5400 200 8700 16500; + B 13600 200 26000 16500; + B 5400 200 43300 16500; + B 5200 200 8600 16300; + B 14000 200 26000 16300; + B 5200 200 43400 16300; + B 5000 200 8500 16100; + B 14400 200 26000 16100; + B 5000 200 43500 16100; + B 4800 200 8400 15900; + B 14800 200 26000 15900; + B 4800 200 43600 15900; + B 4600 200 8300 15700; + B 15200 200 26000 15700; + B 4600 200 43700 15700; + B 4400 200 8200 15500; + B 15600 200 26000 15500; + B 4400 200 43800 15500; + B 4200 200 8100 15300; + B 16000 200 26000 15300; + B 4200 200 43900 15300; + B 4000 200 8000 15100; + B 16400 200 26000 15100; + B 4000 200 44000 15100; + B 3800 200 7900 14900; + B 16800 200 26000 14900; + B 3800 200 44100 14900; + B 3600 200 7800 14700; + B 17200 200 26000 14700; + B 3600 200 44200 14700; + B 3400 200 7700 14500; + B 17600 200 26000 14500; + B 3400 200 44300 14500; + B 3200 200 7600 14300; + B 18000 200 26000 14300; + B 3200 200 44400 14300; + B 3000 200 7500 14100; + B 18400 200 26000 14100; + B 3000 200 44500 14100; + B 2800 200 7400 13900; + B 18800 200 26000 13900; + B 2800 200 44600 13900; + B 2600 200 7300 13700; + B 19200 200 26000 13700; + B 2600 200 44700 13700; + B 2400 200 7200 13500; + B 19600 200 26000 13500; + B 2400 200 44800 13500; + B 2200 200 7100 13300; + B 20000 200 26000 13300; + B 2200 200 44900 13300; + B 2000 200 7000 13100; + B 20400 200 26000 13100; + B 2000 200 45000 13100; + B 1800 200 6900 12900; + B 20800 200 26000 12900; + B 1800 200 45100 12900; + B 1600 200 6800 12700; + B 21200 200 26000 12700; + B 1600 200 45200 12700; + B 1400 200 6700 12500; + B 21600 200 26000 12500; + B 1400 200 45300 12500; + B 1200 200 6600 12300; + B 22000 200 26000 12300; + B 1200 200 45400 12300; + B 1000 200 6500 12100; + B 22400 200 26000 12100; + B 1000 200 45500 12100; + B 800 200 6400 11900; + B 22800 200 26000 11900; + B 800 200 45600 11900; + B 600 200 6300 11700; + B 23200 200 26000 11700; + B 600 200 45700 11700; + B 400 200 6200 11500; + B 23600 200 26000 11500; + B 400 200 45800 11500; + B 200 200 6100 11300; + B 24000 200 26000 11300; + B 200 200 45900 11300; + B 24400 200 26000 11100; + B 24800 200 26000 10900; + B 25200 200 26000 10700; + B 25600 200 26000 10500; + B 26000 200 26000 10300; + B 26400 200 26000 10100; + B 26800 200 26000 9900; + B 27200 200 26000 9700; + B 27600 200 26000 9500; + B 28000 200 26000 9300; + B 28400 200 26000 9100; + B 28800 200 26000 8900; + B 29200 200 26000 8700; + B 29600 200 26000 8500; + B 30000 200 26000 8300; + B 30400 200 26000 8100; + B 30800 200 26000 7900; + B 31200 200 26000 7700; + B 31600 200 26000 7500; + B 32000 200 26000 7300; +L COP; + B 32000 200 26000 47100; + B 31600 200 26000 46900; + B 31200 200 26000 46700; + B 30800 200 26000 46500; + B 30400 200 26000 46300; + B 30000 200 26000 46100; + B 29600 200 26000 45900; + B 29200 200 26000 45700; + B 28800 200 26000 45500; + B 28400 200 26000 45300; + B 28000 200 26000 45100; + B 27600 200 26000 44900; + B 27200 200 26000 44700; + B 26800 200 26000 44500; + B 26400 200 26000 44300; + B 26000 200 26000 44100; + B 25600 200 26000 43900; + B 25200 200 26000 43700; + B 24800 200 26000 43500; + B 24400 200 26000 43300; + B 200 200 6100 43100; + B 24000 200 26000 43100; + B 200 200 45900 43100; + B 400 200 6200 42900; + B 23600 200 26000 42900; + B 400 200 45800 42900; + B 600 200 6300 42700; + B 23200 200 26000 42700; + B 600 200 45700 42700; + B 800 200 6400 42500; + B 22800 200 26000 42500; + B 800 200 45600 42500; + B 1000 200 6500 42300; + B 22400 200 26000 42300; + B 1000 200 45500 42300; + B 1200 200 6600 42100; + B 22000 200 26000 42100; + B 1200 200 45400 42100; + B 1400 200 6700 41900; + B 21600 200 26000 41900; + B 1400 200 45300 41900; + B 1600 200 6800 41700; + B 21200 200 26000 41700; + B 1600 200 45200 41700; + B 1800 200 6900 41500; + B 20800 200 26000 41500; + B 1800 200 45100 41500; + B 2000 200 7000 41300; + B 20400 200 26000 41300; + B 2000 200 45000 41300; + B 2200 200 7100 41100; + B 20000 200 26000 41100; + B 2200 200 44900 41100; + B 2400 200 7200 40900; + B 19600 200 26000 40900; + B 2400 200 44800 40900; + B 2600 200 7300 40700; + B 19200 200 26000 40700; + B 2600 200 44700 40700; + B 2800 200 7400 40500; + B 18800 200 26000 40500; + B 2800 200 44600 40500; + B 3000 200 7500 40300; + B 18400 200 26000 40300; + B 3000 200 44500 40300; + B 3200 200 7600 40100; + B 18000 200 26000 40100; + B 3200 200 44400 40100; + B 3400 200 7700 39900; + B 17600 200 26000 39900; + B 3400 200 44300 39900; + B 3600 200 7800 39700; + B 17200 200 26000 39700; + B 3600 200 44200 39700; + B 3800 200 7900 39500; + B 16800 200 26000 39500; + B 3800 200 44100 39500; + B 4000 200 8000 39300; + B 16400 200 26000 39300; + B 4000 200 44000 39300; + B 4200 200 8100 39100; + B 16000 200 26000 39100; + B 4200 200 43900 39100; + B 4400 200 8200 38900; + B 15600 200 26000 38900; + B 4400 200 43800 38900; + B 4600 200 8300 38700; + B 15200 200 26000 38700; + B 4600 200 43700 38700; + B 4800 200 8400 38500; + B 14800 200 26000 38500; + B 4800 200 43600 38500; + B 5000 200 8500 38300; + B 14400 200 26000 38300; + B 5000 200 43500 38300; + B 5200 200 8600 38100; + B 14000 200 26000 38100; + B 5200 200 43400 38100; + B 5400 200 8700 37900; + B 13600 200 26000 37900; + B 5400 200 43300 37900; + B 5600 200 8800 37700; + B 13200 200 26000 37700; + B 5600 200 43200 37700; + B 5800 200 8900 37500; + B 12800 200 26000 37500; + B 5800 200 43100 37500; + B 6000 200 9000 37300; + B 12400 200 26000 37300; + B 6000 200 43000 37300; + B 6200 200 9100 37100; + B 6200 200 42900 37100; + B 6400 200 9200 36900; + B 6400 200 42800 36900; + B 6600 200 9300 36700; + B 6600 200 42700 36700; + B 6800 200 9400 36500; + B 6800 200 42600 36500; + B 7000 200 9500 36300; + B 7000 200 42500 36300; + B 7200 200 9600 36100; + B 7200 200 42400 36100; + B 7400 200 9700 35900; + B 7400 200 42300 35900; + B 7600 200 9800 35700; + B 7600 200 42200 35700; + B 7800 200 9900 35500; + B 7800 200 42100 35500; + B 8000 200 10000 35300; + B 8000 200 42000 35300; + B 8200 200 10100 35100; + B 8200 200 41900 35100; + B 8400 200 10200 34900; + B 8400 200 41800 34900; + B 8600 200 10300 34700; + B 8600 200 41700 34700; + B 8800 200 10400 34500; + B 8800 200 41600 34500; + B 9000 200 10500 34300; + B 9000 200 41500 34300; + B 9200 200 10600 34100; + B 9200 200 41400 34100; + B 9400 200 10700 33900; + B 9400 200 41300 33900; + B 9600 200 10800 33700; + B 9600 200 41200 33700; + B 9800 200 10900 33500; + B 9800 200 41100 33500; + B 10000 12400 11000 27200; + B 10000 12400 41000 27200; + B 9800 200 10900 20900; + B 9800 200 41100 20900; + B 9600 200 10800 20700; + B 9600 200 41200 20700; + B 9400 200 10700 20500; + B 9400 200 41300 20500; + B 9200 200 10600 20300; + B 9200 200 41400 20300; + B 9000 200 10500 20100; + B 9000 200 41500 20100; + B 8800 200 10400 19900; + B 8800 200 41600 19900; + B 8600 200 10300 19700; + B 8600 200 41700 19700; + B 8400 200 10200 19500; + B 8400 200 41800 19500; + B 8200 200 10100 19300; + B 8200 200 41900 19300; + B 8000 200 10000 19100; + B 8000 200 42000 19100; + B 7800 200 9900 18900; + B 7800 200 42100 18900; + B 7600 200 9800 18700; + B 7600 200 42200 18700; + B 7400 200 9700 18500; + B 7400 200 42300 18500; + B 7200 200 9600 18300; + B 7200 200 42400 18300; + B 7000 200 9500 18100; + B 7000 200 42500 18100; + B 6800 200 9400 17900; + B 6800 200 42600 17900; + B 6600 200 9300 17700; + B 6600 200 42700 17700; + B 6400 200 9200 17500; + B 6400 200 42800 17500; + B 6200 200 9100 17300; + B 6200 200 42900 17300; + B 6000 200 9000 17100; + B 12400 200 26000 17100; + B 6000 200 43000 17100; + B 5800 200 8900 16900; + B 12800 200 26000 16900; + B 5800 200 43100 16900; + B 5600 200 8800 16700; + B 13200 200 26000 16700; + B 5600 200 43200 16700; + B 5400 200 8700 16500; + B 13600 200 26000 16500; + B 5400 200 43300 16500; + B 5200 200 8600 16300; + B 14000 200 26000 16300; + B 5200 200 43400 16300; + B 5000 200 8500 16100; + B 14400 200 26000 16100; + B 5000 200 43500 16100; + B 4800 200 8400 15900; + B 14800 200 26000 15900; + B 4800 200 43600 15900; + B 4600 200 8300 15700; + B 15200 200 26000 15700; + B 4600 200 43700 15700; + B 4400 200 8200 15500; + B 15600 200 26000 15500; + B 4400 200 43800 15500; + B 4200 200 8100 15300; + B 16000 200 26000 15300; + B 4200 200 43900 15300; + B 4000 200 8000 15100; + B 16400 200 26000 15100; + B 4000 200 44000 15100; + B 3800 200 7900 14900; + B 16800 200 26000 14900; + B 3800 200 44100 14900; + B 3600 200 7800 14700; + B 17200 200 26000 14700; + B 3600 200 44200 14700; + B 3400 200 7700 14500; + B 17600 200 26000 14500; + B 3400 200 44300 14500; + B 3200 200 7600 14300; + B 18000 200 26000 14300; + B 3200 200 44400 14300; + B 3000 200 7500 14100; + B 18400 200 26000 14100; + B 3000 200 44500 14100; + B 2800 200 7400 13900; + B 18800 200 26000 13900; + B 2800 200 44600 13900; + B 2600 200 7300 13700; + B 19200 200 26000 13700; + B 2600 200 44700 13700; + B 2400 200 7200 13500; + B 19600 200 26000 13500; + B 2400 200 44800 13500; + B 2200 200 7100 13300; + B 20000 200 26000 13300; + B 2200 200 44900 13300; + B 2000 200 7000 13100; + B 20400 200 26000 13100; + B 2000 200 45000 13100; + B 1800 200 6900 12900; + B 20800 200 26000 12900; + B 1800 200 45100 12900; + B 1600 200 6800 12700; + B 21200 200 26000 12700; + B 1600 200 45200 12700; + B 1400 200 6700 12500; + B 21600 200 26000 12500; + B 1400 200 45300 12500; + B 1200 200 6600 12300; + B 22000 200 26000 12300; + B 1200 200 45400 12300; + B 1000 200 6500 12100; + B 22400 200 26000 12100; + B 1000 200 45500 12100; + B 800 200 6400 11900; + B 22800 200 26000 11900; + B 800 200 45600 11900; + B 600 200 6300 11700; + B 23200 200 26000 11700; + B 600 200 45700 11700; + B 400 200 6200 11500; + B 23600 200 26000 11500; + B 400 200 45800 11500; + B 200 200 6100 11300; + B 24000 200 26000 11300; + B 200 200 45900 11300; + B 24400 200 26000 11100; + B 24800 200 26000 10900; + B 25200 200 26000 10700; + B 25600 200 26000 10500; + B 26000 200 26000 10300; + B 26400 200 26000 10100; + B 26800 200 26000 9900; + B 27200 200 26000 9700; + B 27600 200 26000 9500; + B 28000 200 26000 9300; + B 28400 200 26000 9100; + B 28800 200 26000 8900; + B 29200 200 26000 8700; + B 29600 200 26000 8500; + B 30000 200 26000 8300; + B 30400 200 26000 8100; + B 30800 200 26000 7900; + B 31200 200 26000 7700; + B 31600 200 26000 7500; + B 32000 200 26000 7300; +L CPS; + B 42000 200 25000 49100; + B 41800 200 24900 48900; + B 41600 200 24800 48700; + B 41400 200 24700 48500; + B 41200 200 24600 48300; + B 41000 200 24500 48100; + B 40800 200 24400 47900; + B 40600 200 24300 47700; + B 40400 200 24200 47500; + B 40200 200 24100 47300; + B 2000 38200 5000 28100; + B 200 200 47900 47100; + B 400 200 47800 46900; + B 600 200 47700 46700; + B 800 200 47600 46500; + B 1000 200 47500 46300; + B 1200 200 47400 46100; + B 1400 200 47300 45900; + B 1600 200 47200 45700; + B 1800 200 47100 45500; + B 1800 200 4900 8900; + B 1600 200 4800 8700; + B 1400 200 4700 8500; + B 1200 200 4600 8300; + B 1000 200 4500 8100; + B 800 200 4400 7900; + B 600 200 4300 7700; + B 400 200 4200 7500; + B 200 200 4100 7300; + B 2000 38200 47000 26300; + B 40200 200 27900 7100; + B 40400 200 27800 6900; + B 40600 200 27700 6700; + B 40800 200 27600 6500; + B 41000 200 27500 6300; + B 41200 200 27400 6100; + B 41400 200 27300 5900; + B 41600 200 27200 5700; + B 41800 200 27100 5500; + B 42000 200 27000 5300; +DF; +C 1; +End + diff --git a/scmos/examples/nist-mems-library/micro-hot-plate.mag b/scmos/examples/nist-mems-library/micro-hot-plate.mag new file mode 100644 index 00000000..97b0562a --- /dev/null +++ b/scmos/examples/nist-mems-library/micro-hot-plate.mag @@ -0,0 +1,815 @@ +magic +tech scmos +timestamp 760840982 +<< polysilicon >> +rect 250 265 260 266 +rect 249 264 260 265 +rect 248 263 260 264 +rect 247 262 253 263 +rect 246 261 253 262 +rect 245 260 253 261 +rect 244 259 253 260 +rect 257 259 260 263 +rect 243 258 260 259 +rect 242 257 260 258 +rect 241 256 260 257 +rect 240 255 259 256 +rect 239 254 258 255 +rect 238 253 257 254 +rect 237 252 256 253 +rect 236 251 255 252 +rect 235 250 254 251 +rect 234 249 253 250 +rect 233 248 252 249 +rect 232 247 251 248 +rect 231 246 250 247 +rect 230 245 249 246 +rect 229 244 248 245 +rect 228 243 247 244 +rect 227 242 246 243 +rect 226 241 245 242 +rect 225 240 244 241 +rect 224 239 243 240 +rect 223 238 242 239 +rect 222 237 241 238 +rect 221 236 240 237 +rect 220 235 239 236 +rect 219 234 238 235 +rect 218 233 237 234 +rect 217 232 236 233 +rect 216 231 235 232 +rect 215 230 234 231 +rect 214 229 233 230 +rect 213 228 232 229 +rect 212 227 231 228 +rect 211 226 230 227 +rect 210 225 229 226 +rect 209 224 228 225 +rect 208 223 227 224 +rect 207 222 226 223 +rect 206 221 225 222 +rect 205 220 224 221 +rect 204 219 223 220 +rect 203 218 222 219 +rect 202 217 221 218 +rect 201 216 220 217 +rect 200 215 219 216 +rect 199 214 218 215 +rect 198 213 217 214 +rect 197 212 216 213 +rect 196 211 215 212 +rect 195 210 214 211 +rect 194 209 213 210 +rect 193 208 212 209 +rect 192 207 211 208 +rect 191 206 210 207 +rect 190 205 209 206 +rect 189 204 208 205 +rect 188 203 207 204 +rect 187 202 206 203 +rect 186 201 205 202 +rect 185 200 204 201 +rect 184 199 203 200 +rect 183 198 202 199 +rect 182 197 201 198 +rect 181 196 200 197 +rect 180 195 199 196 +rect 179 194 198 195 +rect 178 193 197 194 +rect 177 192 196 193 +rect 176 191 195 192 +rect 175 190 194 191 +rect 174 189 193 190 +rect 173 188 192 189 +rect 172 187 191 188 +rect 171 186 190 187 +rect 170 185 189 186 +rect 169 184 188 185 +rect 168 183 187 184 +rect 167 182 186 183 +rect 166 181 185 182 +rect 165 180 184 181 +rect 164 179 183 180 +rect 163 178 182 179 +rect 162 177 181 178 +rect 162 176 180 177 +rect 90 175 179 176 +rect 90 174 178 175 +rect 90 173 177 174 +rect 90 172 176 173 +rect 90 171 175 172 +rect 90 170 174 171 +rect 90 169 173 170 +rect 90 168 172 169 +rect 90 164 98 168 +rect 90 156 170 164 +rect 162 152 170 156 +rect 90 144 170 152 +rect 90 140 98 144 +rect 90 132 170 140 +rect 162 128 170 132 +rect 90 120 170 128 +rect 90 116 98 120 +rect 90 108 170 116 +rect 162 104 170 108 +rect 88 103 170 104 +rect 87 102 170 103 +rect 86 101 170 102 +rect 85 100 170 101 +rect 84 99 170 100 +rect 83 98 170 99 +rect 82 97 170 98 +rect 81 96 170 97 +rect 80 95 98 96 +rect 79 94 98 95 +rect 78 93 97 94 +rect 77 92 96 93 +rect 76 91 95 92 +rect 75 90 94 91 +rect 74 89 93 90 +rect 73 88 92 89 +rect 72 87 91 88 +rect 71 86 90 87 +rect 70 85 89 86 +rect 69 84 88 85 +rect 68 83 87 84 +rect 67 82 86 83 +rect 66 81 85 82 +rect 65 80 84 81 +rect 64 79 83 80 +rect 63 78 82 79 +rect 62 77 81 78 +rect 61 76 80 77 +rect 60 75 79 76 +rect 59 74 78 75 +rect 58 73 77 74 +rect 57 72 76 73 +rect 56 71 75 72 +rect 55 70 74 71 +rect 54 69 73 70 +rect 53 68 72 69 +rect 52 67 71 68 +rect 51 66 70 67 +rect 50 65 69 66 +rect 49 64 68 65 +rect 48 63 67 64 +rect 47 62 66 63 +rect 46 61 65 62 +rect 45 60 64 61 +rect 44 59 63 60 +rect 43 58 62 59 +rect 42 57 61 58 +rect 41 56 60 57 +rect 40 55 59 56 +rect 39 54 58 55 +rect 38 53 57 54 +rect 37 52 56 53 +rect 36 51 55 52 +rect 35 50 54 51 +rect 34 49 53 50 +rect 33 48 52 49 +rect 32 47 51 48 +rect 31 46 50 47 +rect 30 45 49 46 +rect 29 44 48 45 +rect 28 43 47 44 +rect 27 42 46 43 +rect 26 41 45 42 +rect 25 40 44 41 +rect 24 39 43 40 +rect 23 38 42 39 +rect 22 37 41 38 +rect 21 36 40 37 +rect 20 35 39 36 +rect 19 34 38 35 +rect 18 33 37 34 +rect 17 32 36 33 +rect 16 31 35 32 +rect 15 30 34 31 +rect 14 29 33 30 +rect 13 28 32 29 +rect 12 27 31 28 +rect 11 26 30 27 +rect 10 25 29 26 +rect 9 24 28 25 +rect 8 23 27 24 +rect 7 22 26 23 +rect 6 21 25 22 +rect 5 20 24 21 +rect 4 19 23 20 +rect 3 18 22 19 +rect 2 17 21 18 +rect 1 16 20 17 +rect 0 15 19 16 +rect 0 14 18 15 +rect 0 13 17 14 +rect 0 9 3 13 +rect 7 12 16 13 +rect 7 11 15 12 +rect 7 10 14 11 +rect 7 9 13 10 +rect 0 8 12 9 +rect 0 7 11 8 +rect 0 6 10 7 +<< metal1 >> +rect 250 263 260 266 +rect 250 259 253 263 +rect 257 259 260 263 +rect 250 256 260 259 +rect 0 240 30 246 +rect 230 240 260 246 +rect 0 239 31 240 +rect 229 239 260 240 +rect 0 238 32 239 +rect 228 238 260 239 +rect 0 237 33 238 +rect 227 237 260 238 +rect 0 236 34 237 +rect 226 236 260 237 +rect 26 235 35 236 +rect 225 235 234 236 +rect 27 234 36 235 +rect 224 234 233 235 +rect 28 233 37 234 +rect 223 233 232 234 +rect 29 232 38 233 +rect 222 232 231 233 +rect 30 231 39 232 +rect 221 231 230 232 +rect 31 230 40 231 +rect 220 230 229 231 +rect 32 229 41 230 +rect 219 229 228 230 +rect 33 228 42 229 +rect 218 228 227 229 +rect 34 227 43 228 +rect 217 227 226 228 +rect 35 226 44 227 +rect 216 226 225 227 +rect 36 225 45 226 +rect 215 225 224 226 +rect 37 224 46 225 +rect 214 224 223 225 +rect 38 223 47 224 +rect 213 223 222 224 +rect 39 222 48 223 +rect 212 222 221 223 +rect 40 221 49 222 +rect 211 221 220 222 +rect 41 220 50 221 +rect 210 220 219 221 +rect 42 219 51 220 +rect 209 219 218 220 +rect 43 218 52 219 +rect 208 218 217 219 +rect 44 217 53 218 +rect 207 217 216 218 +rect 45 216 54 217 +rect 206 216 215 217 +rect 46 215 55 216 +rect 205 215 214 216 +rect 47 214 56 215 +rect 204 214 213 215 +rect 48 213 57 214 +rect 203 213 212 214 +rect 49 212 58 213 +rect 202 212 211 213 +rect 50 211 59 212 +rect 201 211 210 212 +rect 51 210 60 211 +rect 200 210 209 211 +rect 52 209 61 210 +rect 199 209 208 210 +rect 53 208 62 209 +rect 198 208 207 209 +rect 54 207 63 208 +rect 197 207 206 208 +rect 55 206 64 207 +rect 196 206 205 207 +rect 56 205 65 206 +rect 195 205 204 206 +rect 57 204 66 205 +rect 194 204 203 205 +rect 58 203 67 204 +rect 193 203 202 204 +rect 59 202 68 203 +rect 192 202 201 203 +rect 60 201 69 202 +rect 191 201 200 202 +rect 61 200 70 201 +rect 190 200 199 201 +rect 62 199 71 200 +rect 189 199 198 200 +rect 63 198 72 199 +rect 188 198 197 199 +rect 64 197 73 198 +rect 187 197 196 198 +rect 65 196 74 197 +rect 186 196 195 197 +rect 66 195 75 196 +rect 185 195 194 196 +rect 67 194 76 195 +rect 184 194 193 195 +rect 68 193 77 194 +rect 183 193 192 194 +rect 69 192 78 193 +rect 182 192 191 193 +rect 70 191 79 192 +rect 181 191 190 192 +rect 71 190 80 191 +rect 180 190 189 191 +rect 72 189 81 190 +rect 179 189 188 190 +rect 73 188 82 189 +rect 178 188 187 189 +rect 74 187 83 188 +rect 177 187 186 188 +rect 75 186 84 187 +rect 176 186 185 187 +rect 76 185 85 186 +rect 175 185 184 186 +rect 77 184 86 185 +rect 174 184 183 185 +rect 78 183 87 184 +rect 173 183 182 184 +rect 79 182 88 183 +rect 172 182 181 183 +rect 80 181 89 182 +rect 171 181 180 182 +rect 81 180 179 181 +rect 82 179 178 180 +rect 83 178 177 179 +rect 84 177 176 178 +rect 85 95 175 177 +rect 84 94 176 95 +rect 83 93 177 94 +rect 82 92 178 93 +rect 81 91 179 92 +rect 80 90 89 91 +rect 171 90 180 91 +rect 79 89 88 90 +rect 172 89 181 90 +rect 78 88 87 89 +rect 173 88 182 89 +rect 77 87 86 88 +rect 174 87 183 88 +rect 76 86 85 87 +rect 175 86 184 87 +rect 75 85 84 86 +rect 176 85 185 86 +rect 74 84 83 85 +rect 177 84 186 85 +rect 73 83 82 84 +rect 178 83 187 84 +rect 72 82 81 83 +rect 179 82 188 83 +rect 71 81 80 82 +rect 180 81 189 82 +rect 70 80 79 81 +rect 181 80 190 81 +rect 69 79 78 80 +rect 182 79 191 80 +rect 68 78 77 79 +rect 183 78 192 79 +rect 67 77 76 78 +rect 184 77 193 78 +rect 66 76 75 77 +rect 185 76 194 77 +rect 65 75 74 76 +rect 186 75 195 76 +rect 64 74 73 75 +rect 187 74 196 75 +rect 63 73 72 74 +rect 188 73 197 74 +rect 62 72 71 73 +rect 189 72 198 73 +rect 61 71 70 72 +rect 190 71 199 72 +rect 60 70 69 71 +rect 191 70 200 71 +rect 59 69 68 70 +rect 192 69 201 70 +rect 58 68 67 69 +rect 193 68 202 69 +rect 57 67 66 68 +rect 194 67 203 68 +rect 56 66 65 67 +rect 195 66 204 67 +rect 55 65 64 66 +rect 196 65 205 66 +rect 54 64 63 65 +rect 197 64 206 65 +rect 53 63 62 64 +rect 198 63 207 64 +rect 52 62 61 63 +rect 199 62 208 63 +rect 51 61 60 62 +rect 200 61 209 62 +rect 50 60 59 61 +rect 201 60 210 61 +rect 49 59 58 60 +rect 202 59 211 60 +rect 48 58 57 59 +rect 203 58 212 59 +rect 47 57 56 58 +rect 204 57 213 58 +rect 46 56 55 57 +rect 205 56 214 57 +rect 45 55 54 56 +rect 206 55 215 56 +rect 44 54 53 55 +rect 207 54 216 55 +rect 43 53 52 54 +rect 208 53 217 54 +rect 42 52 51 53 +rect 209 52 218 53 +rect 41 51 50 52 +rect 210 51 219 52 +rect 40 50 49 51 +rect 211 50 220 51 +rect 39 49 48 50 +rect 212 49 221 50 +rect 38 48 47 49 +rect 213 48 222 49 +rect 37 47 46 48 +rect 214 47 223 48 +rect 36 46 45 47 +rect 215 46 224 47 +rect 35 45 44 46 +rect 216 45 225 46 +rect 34 44 43 45 +rect 217 44 226 45 +rect 33 43 42 44 +rect 218 43 227 44 +rect 32 42 41 43 +rect 219 42 228 43 +rect 31 41 40 42 +rect 220 41 229 42 +rect 30 40 39 41 +rect 221 40 230 41 +rect 29 39 38 40 +rect 222 39 231 40 +rect 28 38 37 39 +rect 223 38 232 39 +rect 27 37 36 38 +rect 224 37 233 38 +rect 26 36 35 37 +rect 225 36 234 37 +rect 0 35 34 36 +rect 226 35 260 36 +rect 0 34 33 35 +rect 227 34 260 35 +rect 0 33 32 34 +rect 228 33 260 34 +rect 0 32 31 33 +rect 229 32 260 33 +rect 0 26 30 32 +rect 230 26 260 32 +rect 0 13 10 16 +rect 0 9 3 13 +rect 7 9 10 13 +rect 0 0 10 9 +<< polycontact >> +rect 253 259 257 263 +rect 3 9 7 13 +<< substrateopen >> +rect 50 235 210 236 +rect 51 234 209 235 +rect 52 233 208 234 +rect 53 232 207 233 +rect 54 231 206 232 +rect 55 230 205 231 +rect 56 229 204 230 +rect 57 228 203 229 +rect 58 227 202 228 +rect 59 226 201 227 +rect 60 225 200 226 +rect 61 224 199 225 +rect 62 223 198 224 +rect 63 222 197 223 +rect 64 221 196 222 +rect 65 220 195 221 +rect 66 219 194 220 +rect 67 218 193 219 +rect 68 217 192 218 +rect 69 216 191 217 +rect 30 215 31 216 +rect 70 215 190 216 +rect 229 215 230 216 +rect 30 214 32 215 +rect 71 214 189 215 +rect 228 214 230 215 +rect 30 213 33 214 +rect 72 213 188 214 +rect 227 213 230 214 +rect 30 212 34 213 +rect 73 212 187 213 +rect 226 212 230 213 +rect 30 211 35 212 +rect 74 211 186 212 +rect 225 211 230 212 +rect 30 210 36 211 +rect 75 210 185 211 +rect 224 210 230 211 +rect 30 209 37 210 +rect 76 209 184 210 +rect 223 209 230 210 +rect 30 208 38 209 +rect 77 208 183 209 +rect 222 208 230 209 +rect 30 207 39 208 +rect 78 207 182 208 +rect 221 207 230 208 +rect 30 206 40 207 +rect 79 206 181 207 +rect 220 206 230 207 +rect 30 205 41 206 +rect 80 205 180 206 +rect 219 205 230 206 +rect 30 204 42 205 +rect 81 204 179 205 +rect 218 204 230 205 +rect 30 203 43 204 +rect 82 203 178 204 +rect 217 203 230 204 +rect 30 202 44 203 +rect 83 202 177 203 +rect 216 202 230 203 +rect 30 201 45 202 +rect 84 201 176 202 +rect 215 201 230 202 +rect 30 200 46 201 +rect 85 200 175 201 +rect 214 200 230 201 +rect 30 199 47 200 +rect 86 199 174 200 +rect 213 199 230 200 +rect 30 198 48 199 +rect 87 198 173 199 +rect 212 198 230 199 +rect 30 197 49 198 +rect 88 197 172 198 +rect 211 197 230 198 +rect 30 196 50 197 +rect 89 196 171 197 +rect 210 196 230 197 +rect 30 195 51 196 +rect 90 195 170 196 +rect 209 195 230 196 +rect 30 194 52 195 +rect 91 194 169 195 +rect 208 194 230 195 +rect 30 193 53 194 +rect 92 193 168 194 +rect 207 193 230 194 +rect 30 192 54 193 +rect 93 192 167 193 +rect 206 192 230 193 +rect 30 191 55 192 +rect 94 191 166 192 +rect 205 191 230 192 +rect 30 190 56 191 +rect 95 190 165 191 +rect 204 190 230 191 +rect 30 189 57 190 +rect 96 189 164 190 +rect 203 189 230 190 +rect 30 188 58 189 +rect 97 188 163 189 +rect 202 188 230 189 +rect 30 187 59 188 +rect 98 187 162 188 +rect 201 187 230 188 +rect 30 186 60 187 +rect 99 186 161 187 +rect 200 186 230 187 +rect 30 185 61 186 +rect 199 185 230 186 +rect 30 184 62 185 +rect 198 184 230 185 +rect 30 183 63 184 +rect 197 183 230 184 +rect 30 182 64 183 +rect 196 182 230 183 +rect 30 181 65 182 +rect 195 181 230 182 +rect 30 180 66 181 +rect 194 180 230 181 +rect 30 179 67 180 +rect 193 179 230 180 +rect 30 178 68 179 +rect 192 178 230 179 +rect 30 177 69 178 +rect 191 177 230 178 +rect 30 176 70 177 +rect 190 176 230 177 +rect 30 175 71 176 +rect 189 175 230 176 +rect 30 174 72 175 +rect 188 174 230 175 +rect 30 173 73 174 +rect 187 173 230 174 +rect 30 172 74 173 +rect 186 172 230 173 +rect 30 171 75 172 +rect 185 171 230 172 +rect 30 170 76 171 +rect 184 170 230 171 +rect 30 169 77 170 +rect 183 169 230 170 +rect 30 168 78 169 +rect 182 168 230 169 +rect 30 167 79 168 +rect 181 167 230 168 +rect 30 105 80 167 +rect 180 105 230 167 +rect 30 104 79 105 +rect 181 104 230 105 +rect 30 103 78 104 +rect 182 103 230 104 +rect 30 102 77 103 +rect 183 102 230 103 +rect 30 101 76 102 +rect 184 101 230 102 +rect 30 100 75 101 +rect 185 100 230 101 +rect 30 99 74 100 +rect 186 99 230 100 +rect 30 98 73 99 +rect 187 98 230 99 +rect 30 97 72 98 +rect 188 97 230 98 +rect 30 96 71 97 +rect 189 96 230 97 +rect 30 95 70 96 +rect 190 95 230 96 +rect 30 94 69 95 +rect 191 94 230 95 +rect 30 93 68 94 +rect 192 93 230 94 +rect 30 92 67 93 +rect 193 92 230 93 +rect 30 91 66 92 +rect 194 91 230 92 +rect 30 90 65 91 +rect 195 90 230 91 +rect 30 89 64 90 +rect 196 89 230 90 +rect 30 88 63 89 +rect 197 88 230 89 +rect 30 87 62 88 +rect 198 87 230 88 +rect 30 86 61 87 +rect 199 86 230 87 +rect 30 85 60 86 +rect 99 85 161 86 +rect 200 85 230 86 +rect 30 84 59 85 +rect 98 84 162 85 +rect 201 84 230 85 +rect 30 83 58 84 +rect 97 83 163 84 +rect 202 83 230 84 +rect 30 82 57 83 +rect 96 82 164 83 +rect 203 82 230 83 +rect 30 81 56 82 +rect 95 81 165 82 +rect 204 81 230 82 +rect 30 80 55 81 +rect 94 80 166 81 +rect 205 80 230 81 +rect 30 79 54 80 +rect 93 79 167 80 +rect 206 79 230 80 +rect 30 78 53 79 +rect 92 78 168 79 +rect 207 78 230 79 +rect 30 77 52 78 +rect 91 77 169 78 +rect 208 77 230 78 +rect 30 76 51 77 +rect 90 76 170 77 +rect 209 76 230 77 +rect 30 75 50 76 +rect 89 75 171 76 +rect 210 75 230 76 +rect 30 74 49 75 +rect 88 74 172 75 +rect 211 74 230 75 +rect 30 73 48 74 +rect 87 73 173 74 +rect 212 73 230 74 +rect 30 72 47 73 +rect 86 72 174 73 +rect 213 72 230 73 +rect 30 71 46 72 +rect 85 71 175 72 +rect 214 71 230 72 +rect 30 70 45 71 +rect 84 70 176 71 +rect 215 70 230 71 +rect 30 69 44 70 +rect 83 69 177 70 +rect 216 69 230 70 +rect 30 68 43 69 +rect 82 68 178 69 +rect 217 68 230 69 +rect 30 67 42 68 +rect 81 67 179 68 +rect 218 67 230 68 +rect 30 66 41 67 +rect 80 66 180 67 +rect 219 66 230 67 +rect 30 65 40 66 +rect 79 65 181 66 +rect 220 65 230 66 +rect 30 64 39 65 +rect 78 64 182 65 +rect 221 64 230 65 +rect 30 63 38 64 +rect 77 63 183 64 +rect 222 63 230 64 +rect 30 62 37 63 +rect 76 62 184 63 +rect 223 62 230 63 +rect 30 61 36 62 +rect 75 61 185 62 +rect 224 61 230 62 +rect 30 60 35 61 +rect 74 60 186 61 +rect 225 60 230 61 +rect 30 59 34 60 +rect 73 59 187 60 +rect 226 59 230 60 +rect 30 58 33 59 +rect 72 58 188 59 +rect 227 58 230 59 +rect 30 57 32 58 +rect 71 57 189 58 +rect 228 57 230 58 +rect 30 56 31 57 +rect 70 56 190 57 +rect 229 56 230 57 +rect 69 55 191 56 +rect 68 54 192 55 +rect 67 53 193 54 +rect 66 52 194 53 +rect 65 51 195 52 +rect 64 50 196 51 +rect 63 49 197 50 +rect 62 48 198 49 +rect 61 47 199 48 +rect 60 46 200 47 +rect 59 45 201 46 +rect 58 44 202 45 +rect 57 43 203 44 +rect 56 42 204 43 +rect 55 41 205 42 +rect 54 40 206 41 +rect 53 39 207 40 +rect 52 38 208 39 +rect 51 37 209 38 +rect 50 36 210 37 +<< pdiffusionstop >> +rect 20 245 230 246 +rect 20 244 229 245 +rect 20 243 228 244 +rect 20 242 227 243 +rect 20 241 226 242 +rect 20 240 225 241 +rect 20 239 224 240 +rect 20 238 223 239 +rect 20 237 222 238 +rect 20 236 221 237 +rect 20 45 30 236 +rect 239 235 240 236 +rect 238 234 240 235 +rect 237 233 240 234 +rect 236 232 240 233 +rect 235 231 240 232 +rect 234 230 240 231 +rect 233 229 240 230 +rect 232 228 240 229 +rect 231 227 240 228 +rect 20 44 29 45 +rect 20 43 28 44 +rect 20 42 27 43 +rect 20 41 26 42 +rect 20 40 25 41 +rect 20 39 24 40 +rect 20 38 23 39 +rect 20 37 22 38 +rect 20 36 21 37 +rect 230 36 240 227 +rect 39 35 240 36 +rect 38 34 240 35 +rect 37 33 240 34 +rect 36 32 240 33 +rect 35 31 240 32 +rect 34 30 240 31 +rect 33 29 240 30 +rect 32 28 240 29 +rect 31 27 240 28 +rect 30 26 240 27 +<< end >> diff --git a/scmos/examples/nist-mems-library/nist_mems_lib.doc b/scmos/examples/nist-mems-library/nist_mems_lib.doc new file mode 100644 index 00000000..0099628a --- /dev/null +++ b/scmos/examples/nist-mems-library/nist_mems_lib.doc @@ -0,0 +1,78 @@ +The following are the cell names and cell descriptions of sample +layouts designed at NIST for micromechanical designs. + + 1. open-80x80 + + A MEMS test structure to check the progress of the EDP etchant + on an intended 80 um x 80 um cavity. This design consists of a + single open tile. + + 2. open-oxide-80x80 + + An additional MEMS test structure to check the progress of + the etchant on an intended 80 um x 80 um cavity with a + trampoline-like suspended oxide. This design consists of + four trapezoidal-shaped open tiles brought together in close + vicinity such that the four cavities merge in the + post-processing etch step creating one large 80 um x 80 um + cavity with a suspended layer of oxide (see fig. 1). + + 3. thermal-converter + + A polysilicon (poly1) heater with a metal1/poly1 thermopile + used as an ac power sensor. + + 4. thermal-actuator + + A cantilever structure consisting of poly1 with metal1 on + top. These are connected at the end of the `diving board' + and, when heated, the diving board bends upward due to the + different thermal expansion coefficients of poly1 and + metal1. + + 5. pixel-80x80 + + A heating element with an 80 um x 80 um cavity. The heating + element is made of meandering polysilicon (poly1) and is + suspended over top of the cavity with its encompassing oxide + after the anisotropic etch. + + 6. pixel-160x160 + + Similar to the above structure but with a 160 um x 160 um + cavity. + + 7. micro-hot-plate + + The microhotplate design consists of: + a. A meandering polysilicon (poly1) heating element with + two external connections. + b. An aluminum (metal1) plate with four external connections + over top of the polysilicon (poly1) heating element. + There is an oxide separating the poly1 and metal1. + The heat is uniformly distributed across this metal1 + plate with the metal1 resistance changing linearly with + temperature. The metal1 sheet resistance at the + various temperatures can be obtained with a + van der Pauw measurement. + + 8. gas-sensor + + The gas sensor design consists of the microhotplate design + above with the addition of two layers: + + a. Four metal2 pads placed in the corners of the metal1 + microhotplate (but not in contact with it). There + are four external metal2 connections. + b. Overglass openings centered on top of the metal2 pads. + The metal2 pads and overglass openings allow a substance + (e.g., tin oxide and palladium) to be placed on top of the + whole pixel. When heated, the resistance of the substance + changes in the presense of certain gases. The metal2 acts + as a van der Pauw sheet resistor so the resistance change + can be measured. This application of the microhotplate is + called a gas sensor. (NIST has a patent pending on this + gas sensor design.) + + + diff --git a/scmos/examples/nist-mems-library/open-80x80.cif b/scmos/examples/nist-mems-library/open-80x80.cif new file mode 100644 index 00000000..d1980fc6 --- /dev/null +++ b/scmos/examples/nist-mems-library/open-80x80.cif @@ -0,0 +1,16 @@ +DS 1 1 2; +9 open-80x80; +L CAA; + B 16000 16000 105600 -39800; +L CVA; + B 16000 16000 105600 -39800; +L CCA; + B 16000 16000 105600 -39800; +L COG; + B 16000 16000 105600 -39800; +L COP; + B 16000 16000 105600 -39800; +DF; +C 1; +End + diff --git a/scmos/examples/nist-mems-library/open-80x80.mag b/scmos/examples/nist-mems-library/open-80x80.mag new file mode 100644 index 00000000..345cfb2d --- /dev/null +++ b/scmos/examples/nist-mems-library/open-80x80.mag @@ -0,0 +1,6 @@ +magic +tech scmos +timestamp 760840415 +<< substrateopen >> +rect 488 -239 568 -159 +<< end >> diff --git a/scmos/examples/nist-mems-library/open-oxide-80x80.cif b/scmos/examples/nist-mems-library/open-oxide-80x80.cif new file mode 100644 index 00000000..bdf1b1d2 --- /dev/null +++ b/scmos/examples/nist-mems-library/open-oxide-80x80.cif @@ -0,0 +1,571 @@ +DS 1 1 2; +9 open-oxide-80x80; +L CAA; + B 12000 200 135400 -32500; + B 11600 200 135400 -32700; + B 11200 200 135400 -32900; + B 10800 200 135400 -33100; + B 10400 200 135400 -33300; + B 10000 200 135400 -33500; + B 9600 200 135400 -33700; + B 9200 200 135400 -33900; + B 8800 200 135400 -34100; + B 8400 200 135400 -34300; + B 200 200 127500 -34500; + B 8000 200 135400 -34500; + B 200 200 143300 -34500; + B 400 200 127600 -34700; + B 7600 200 135400 -34700; + B 400 200 143200 -34700; + B 600 200 127700 -34900; + B 7200 200 135400 -34900; + B 600 200 143100 -34900; + B 800 200 127800 -35100; + B 6800 200 135400 -35100; + B 800 200 143000 -35100; + B 1000 200 127900 -35300; + B 6400 200 135400 -35300; + B 1000 200 142900 -35300; + B 1200 200 128000 -35500; + B 6000 200 135400 -35500; + B 1200 200 142800 -35500; + B 1400 200 128100 -35700; + B 5600 200 135400 -35700; + B 1400 200 142700 -35700; + B 1600 200 128200 -35900; + B 5200 200 135400 -35900; + B 1600 200 142600 -35900; + B 1800 200 128300 -36100; + B 4800 200 135400 -36100; + B 1800 200 142500 -36100; + B 2000 200 128400 -36300; + B 2000 200 142400 -36300; + B 2200 200 128500 -36500; + B 2200 200 142300 -36500; + B 2400 200 128600 -36700; + B 2400 200 142200 -36700; + B 2600 200 128700 -36900; + B 2600 200 142100 -36900; + B 2800 200 128800 -37100; + B 2800 200 142000 -37100; + B 3000 200 128900 -37300; + B 3000 200 141900 -37300; + B 3200 200 129000 -37500; + B 3200 200 141800 -37500; + B 3400 200 129100 -37700; + B 3400 200 141700 -37700; + B 3600 200 129200 -37900; + B 3600 200 141600 -37900; + B 3800 4800 129300 -40400; + B 3800 4800 141500 -40400; + B 3600 200 129200 -42900; + B 3600 200 141600 -42900; + B 3400 200 129100 -43100; + B 3400 200 141700 -43100; + B 3200 200 129000 -43300; + B 3200 200 141800 -43300; + B 3000 200 128900 -43500; + B 3000 200 141900 -43500; + B 2800 200 128800 -43700; + B 2800 200 142000 -43700; + B 2600 200 128700 -43900; + B 2600 200 142100 -43900; + B 2400 200 128600 -44100; + B 2400 200 142200 -44100; + B 2200 200 128500 -44300; + B 2200 200 142300 -44300; + B 2000 200 128400 -44500; + B 2000 200 142400 -44500; + B 1800 200 128300 -44700; + B 4800 200 135400 -44700; + B 1800 200 142500 -44700; + B 1600 200 128200 -44900; + B 5200 200 135400 -44900; + B 1600 200 142600 -44900; + B 1400 200 128100 -45100; + B 5600 200 135400 -45100; + B 1400 200 142700 -45100; + B 1200 200 128000 -45300; + B 6000 200 135400 -45300; + B 1200 200 142800 -45300; + B 1000 200 127900 -45500; + B 6400 200 135400 -45500; + B 1000 200 142900 -45500; + B 800 200 127800 -45700; + B 6800 200 135400 -45700; + B 800 200 143000 -45700; + B 600 200 127700 -45900; + B 7200 200 135400 -45900; + B 600 200 143100 -45900; + B 400 200 127600 -46100; + B 7600 200 135400 -46100; + B 400 200 143200 -46100; + B 200 200 127500 -46300; + B 8000 200 135400 -46300; + B 200 200 143300 -46300; + B 8400 200 135400 -46500; + B 8800 200 135400 -46700; + B 9200 200 135400 -46900; + B 9600 200 135400 -47100; + B 10000 200 135400 -47300; + B 10400 200 135400 -47500; + B 10800 200 135400 -47700; + B 11200 200 135400 -47900; + B 11600 200 135400 -48100; + B 12000 200 135400 -48300; +L CVA; + B 12000 200 135400 -32500; + B 11600 200 135400 -32700; + B 11200 200 135400 -32900; + B 10800 200 135400 -33100; + B 10400 200 135400 -33300; + B 10000 200 135400 -33500; + B 9600 200 135400 -33700; + B 9200 200 135400 -33900; + B 8800 200 135400 -34100; + B 8400 200 135400 -34300; + B 200 200 127500 -34500; + B 8000 200 135400 -34500; + B 200 200 143300 -34500; + B 400 200 127600 -34700; + B 7600 200 135400 -34700; + B 400 200 143200 -34700; + B 600 200 127700 -34900; + B 7200 200 135400 -34900; + B 600 200 143100 -34900; + B 800 200 127800 -35100; + B 6800 200 135400 -35100; + B 800 200 143000 -35100; + B 1000 200 127900 -35300; + B 6400 200 135400 -35300; + B 1000 200 142900 -35300; + B 1200 200 128000 -35500; + B 6000 200 135400 -35500; + B 1200 200 142800 -35500; + B 1400 200 128100 -35700; + B 5600 200 135400 -35700; + B 1400 200 142700 -35700; + B 1600 200 128200 -35900; + B 5200 200 135400 -35900; + B 1600 200 142600 -35900; + B 1800 200 128300 -36100; + B 4800 200 135400 -36100; + B 1800 200 142500 -36100; + B 2000 200 128400 -36300; + B 2000 200 142400 -36300; + B 2200 200 128500 -36500; + B 2200 200 142300 -36500; + B 2400 200 128600 -36700; + B 2400 200 142200 -36700; + B 2600 200 128700 -36900; + B 2600 200 142100 -36900; + B 2800 200 128800 -37100; + B 2800 200 142000 -37100; + B 3000 200 128900 -37300; + B 3000 200 141900 -37300; + B 3200 200 129000 -37500; + B 3200 200 141800 -37500; + B 3400 200 129100 -37700; + B 3400 200 141700 -37700; + B 3600 200 129200 -37900; + B 3600 200 141600 -37900; + B 3800 4800 129300 -40400; + B 3800 4800 141500 -40400; + B 3600 200 129200 -42900; + B 3600 200 141600 -42900; + B 3400 200 129100 -43100; + B 3400 200 141700 -43100; + B 3200 200 129000 -43300; + B 3200 200 141800 -43300; + B 3000 200 128900 -43500; + B 3000 200 141900 -43500; + B 2800 200 128800 -43700; + B 2800 200 142000 -43700; + B 2600 200 128700 -43900; + B 2600 200 142100 -43900; + B 2400 200 128600 -44100; + B 2400 200 142200 -44100; + B 2200 200 128500 -44300; + B 2200 200 142300 -44300; + B 2000 200 128400 -44500; + B 2000 200 142400 -44500; + B 1800 200 128300 -44700; + B 4800 200 135400 -44700; + B 1800 200 142500 -44700; + B 1600 200 128200 -44900; + B 5200 200 135400 -44900; + B 1600 200 142600 -44900; + B 1400 200 128100 -45100; + B 5600 200 135400 -45100; + B 1400 200 142700 -45100; + B 1200 200 128000 -45300; + B 6000 200 135400 -45300; + B 1200 200 142800 -45300; + B 1000 200 127900 -45500; + B 6400 200 135400 -45500; + B 1000 200 142900 -45500; + B 800 200 127800 -45700; + B 6800 200 135400 -45700; + B 800 200 143000 -45700; + B 600 200 127700 -45900; + B 7200 200 135400 -45900; + B 600 200 143100 -45900; + B 400 200 127600 -46100; + B 7600 200 135400 -46100; + B 400 200 143200 -46100; + B 200 200 127500 -46300; + B 8000 200 135400 -46300; + B 200 200 143300 -46300; + B 8400 200 135400 -46500; + B 8800 200 135400 -46700; + B 9200 200 135400 -46900; + B 9600 200 135400 -47100; + B 10000 200 135400 -47300; + B 10400 200 135400 -47500; + B 10800 200 135400 -47700; + B 11200 200 135400 -47900; + B 11600 200 135400 -48100; + B 12000 200 135400 -48300; +L CCA; + B 12000 200 135400 -32500; + B 11600 200 135400 -32700; + B 11200 200 135400 -32900; + B 10800 200 135400 -33100; + B 10400 200 135400 -33300; + B 10000 200 135400 -33500; + B 9600 200 135400 -33700; + B 9200 200 135400 -33900; + B 8800 200 135400 -34100; + B 8400 200 135400 -34300; + B 200 200 127500 -34500; + B 8000 200 135400 -34500; + B 200 200 143300 -34500; + B 400 200 127600 -34700; + B 7600 200 135400 -34700; + B 400 200 143200 -34700; + B 600 200 127700 -34900; + B 7200 200 135400 -34900; + B 600 200 143100 -34900; + B 800 200 127800 -35100; + B 6800 200 135400 -35100; + B 800 200 143000 -35100; + B 1000 200 127900 -35300; + B 6400 200 135400 -35300; + B 1000 200 142900 -35300; + B 1200 200 128000 -35500; + B 6000 200 135400 -35500; + B 1200 200 142800 -35500; + B 1400 200 128100 -35700; + B 5600 200 135400 -35700; + B 1400 200 142700 -35700; + B 1600 200 128200 -35900; + B 5200 200 135400 -35900; + B 1600 200 142600 -35900; + B 1800 200 128300 -36100; + B 4800 200 135400 -36100; + B 1800 200 142500 -36100; + B 2000 200 128400 -36300; + B 2000 200 142400 -36300; + B 2200 200 128500 -36500; + B 2200 200 142300 -36500; + B 2400 200 128600 -36700; + B 2400 200 142200 -36700; + B 2600 200 128700 -36900; + B 2600 200 142100 -36900; + B 2800 200 128800 -37100; + B 2800 200 142000 -37100; + B 3000 200 128900 -37300; + B 3000 200 141900 -37300; + B 3200 200 129000 -37500; + B 3200 200 141800 -37500; + B 3400 200 129100 -37700; + B 3400 200 141700 -37700; + B 3600 200 129200 -37900; + B 3600 200 141600 -37900; + B 3800 4800 129300 -40400; + B 3800 4800 141500 -40400; + B 3600 200 129200 -42900; + B 3600 200 141600 -42900; + B 3400 200 129100 -43100; + B 3400 200 141700 -43100; + B 3200 200 129000 -43300; + B 3200 200 141800 -43300; + B 3000 200 128900 -43500; + B 3000 200 141900 -43500; + B 2800 200 128800 -43700; + B 2800 200 142000 -43700; + B 2600 200 128700 -43900; + B 2600 200 142100 -43900; + B 2400 200 128600 -44100; + B 2400 200 142200 -44100; + B 2200 200 128500 -44300; + B 2200 200 142300 -44300; + B 2000 200 128400 -44500; + B 2000 200 142400 -44500; + B 1800 200 128300 -44700; + B 4800 200 135400 -44700; + B 1800 200 142500 -44700; + B 1600 200 128200 -44900; + B 5200 200 135400 -44900; + B 1600 200 142600 -44900; + B 1400 200 128100 -45100; + B 5600 200 135400 -45100; + B 1400 200 142700 -45100; + B 1200 200 128000 -45300; + B 6000 200 135400 -45300; + B 1200 200 142800 -45300; + B 1000 200 127900 -45500; + B 6400 200 135400 -45500; + B 1000 200 142900 -45500; + B 800 200 127800 -45700; + B 6800 200 135400 -45700; + B 800 200 143000 -45700; + B 600 200 127700 -45900; + B 7200 200 135400 -45900; + B 600 200 143100 -45900; + B 400 200 127600 -46100; + B 7600 200 135400 -46100; + B 400 200 143200 -46100; + B 200 200 127500 -46300; + B 8000 200 135400 -46300; + B 200 200 143300 -46300; + B 8400 200 135400 -46500; + B 8800 200 135400 -46700; + B 9200 200 135400 -46900; + B 9600 200 135400 -47100; + B 10000 200 135400 -47300; + B 10400 200 135400 -47500; + B 10800 200 135400 -47700; + B 11200 200 135400 -47900; + B 11600 200 135400 -48100; + B 12000 200 135400 -48300; +L COG; + B 12000 200 135400 -32500; + B 11600 200 135400 -32700; + B 11200 200 135400 -32900; + B 10800 200 135400 -33100; + B 10400 200 135400 -33300; + B 10000 200 135400 -33500; + B 9600 200 135400 -33700; + B 9200 200 135400 -33900; + B 8800 200 135400 -34100; + B 8400 200 135400 -34300; + B 200 200 127500 -34500; + B 8000 200 135400 -34500; + B 200 200 143300 -34500; + B 400 200 127600 -34700; + B 7600 200 135400 -34700; + B 400 200 143200 -34700; + B 600 200 127700 -34900; + B 7200 200 135400 -34900; + B 600 200 143100 -34900; + B 800 200 127800 -35100; + B 6800 200 135400 -35100; + B 800 200 143000 -35100; + B 1000 200 127900 -35300; + B 6400 200 135400 -35300; + B 1000 200 142900 -35300; + B 1200 200 128000 -35500; + B 6000 200 135400 -35500; + B 1200 200 142800 -35500; + B 1400 200 128100 -35700; + B 5600 200 135400 -35700; + B 1400 200 142700 -35700; + B 1600 200 128200 -35900; + B 5200 200 135400 -35900; + B 1600 200 142600 -35900; + B 1800 200 128300 -36100; + B 4800 200 135400 -36100; + B 1800 200 142500 -36100; + B 2000 200 128400 -36300; + B 2000 200 142400 -36300; + B 2200 200 128500 -36500; + B 2200 200 142300 -36500; + B 2400 200 128600 -36700; + B 2400 200 142200 -36700; + B 2600 200 128700 -36900; + B 2600 200 142100 -36900; + B 2800 200 128800 -37100; + B 2800 200 142000 -37100; + B 3000 200 128900 -37300; + B 3000 200 141900 -37300; + B 3200 200 129000 -37500; + B 3200 200 141800 -37500; + B 3400 200 129100 -37700; + B 3400 200 141700 -37700; + B 3600 200 129200 -37900; + B 3600 200 141600 -37900; + B 3800 4800 129300 -40400; + B 3800 4800 141500 -40400; + B 3600 200 129200 -42900; + B 3600 200 141600 -42900; + B 3400 200 129100 -43100; + B 3400 200 141700 -43100; + B 3200 200 129000 -43300; + B 3200 200 141800 -43300; + B 3000 200 128900 -43500; + B 3000 200 141900 -43500; + B 2800 200 128800 -43700; + B 2800 200 142000 -43700; + B 2600 200 128700 -43900; + B 2600 200 142100 -43900; + B 2400 200 128600 -44100; + B 2400 200 142200 -44100; + B 2200 200 128500 -44300; + B 2200 200 142300 -44300; + B 2000 200 128400 -44500; + B 2000 200 142400 -44500; + B 1800 200 128300 -44700; + B 4800 200 135400 -44700; + B 1800 200 142500 -44700; + B 1600 200 128200 -44900; + B 5200 200 135400 -44900; + B 1600 200 142600 -44900; + B 1400 200 128100 -45100; + B 5600 200 135400 -45100; + B 1400 200 142700 -45100; + B 1200 200 128000 -45300; + B 6000 200 135400 -45300; + B 1200 200 142800 -45300; + B 1000 200 127900 -45500; + B 6400 200 135400 -45500; + B 1000 200 142900 -45500; + B 800 200 127800 -45700; + B 6800 200 135400 -45700; + B 800 200 143000 -45700; + B 600 200 127700 -45900; + B 7200 200 135400 -45900; + B 600 200 143100 -45900; + B 400 200 127600 -46100; + B 7600 200 135400 -46100; + B 400 200 143200 -46100; + B 200 200 127500 -46300; + B 8000 200 135400 -46300; + B 200 200 143300 -46300; + B 8400 200 135400 -46500; + B 8800 200 135400 -46700; + B 9200 200 135400 -46900; + B 9600 200 135400 -47100; + B 10000 200 135400 -47300; + B 10400 200 135400 -47500; + B 10800 200 135400 -47700; + B 11200 200 135400 -47900; + B 11600 200 135400 -48100; + B 12000 200 135400 -48300; +L COP; + B 12000 200 135400 -32500; + B 11600 200 135400 -32700; + B 11200 200 135400 -32900; + B 10800 200 135400 -33100; + B 10400 200 135400 -33300; + B 10000 200 135400 -33500; + B 9600 200 135400 -33700; + B 9200 200 135400 -33900; + B 8800 200 135400 -34100; + B 8400 200 135400 -34300; + B 200 200 127500 -34500; + B 8000 200 135400 -34500; + B 200 200 143300 -34500; + B 400 200 127600 -34700; + B 7600 200 135400 -34700; + B 400 200 143200 -34700; + B 600 200 127700 -34900; + B 7200 200 135400 -34900; + B 600 200 143100 -34900; + B 800 200 127800 -35100; + B 6800 200 135400 -35100; + B 800 200 143000 -35100; + B 1000 200 127900 -35300; + B 6400 200 135400 -35300; + B 1000 200 142900 -35300; + B 1200 200 128000 -35500; + B 6000 200 135400 -35500; + B 1200 200 142800 -35500; + B 1400 200 128100 -35700; + B 5600 200 135400 -35700; + B 1400 200 142700 -35700; + B 1600 200 128200 -35900; + B 5200 200 135400 -35900; + B 1600 200 142600 -35900; + B 1800 200 128300 -36100; + B 4800 200 135400 -36100; + B 1800 200 142500 -36100; + B 2000 200 128400 -36300; + B 2000 200 142400 -36300; + B 2200 200 128500 -36500; + B 2200 200 142300 -36500; + B 2400 200 128600 -36700; + B 2400 200 142200 -36700; + B 2600 200 128700 -36900; + B 2600 200 142100 -36900; + B 2800 200 128800 -37100; + B 2800 200 142000 -37100; + B 3000 200 128900 -37300; + B 3000 200 141900 -37300; + B 3200 200 129000 -37500; + B 3200 200 141800 -37500; + B 3400 200 129100 -37700; + B 3400 200 141700 -37700; + B 3600 200 129200 -37900; + B 3600 200 141600 -37900; + B 3800 4800 129300 -40400; + B 3800 4800 141500 -40400; + B 3600 200 129200 -42900; + B 3600 200 141600 -42900; + B 3400 200 129100 -43100; + B 3400 200 141700 -43100; + B 3200 200 129000 -43300; + B 3200 200 141800 -43300; + B 3000 200 128900 -43500; + B 3000 200 141900 -43500; + B 2800 200 128800 -43700; + B 2800 200 142000 -43700; + B 2600 200 128700 -43900; + B 2600 200 142100 -43900; + B 2400 200 128600 -44100; + B 2400 200 142200 -44100; + B 2200 200 128500 -44300; + B 2200 200 142300 -44300; + B 2000 200 128400 -44500; + B 2000 200 142400 -44500; + B 1800 200 128300 -44700; + B 4800 200 135400 -44700; + B 1800 200 142500 -44700; + B 1600 200 128200 -44900; + B 5200 200 135400 -44900; + B 1600 200 142600 -44900; + B 1400 200 128100 -45100; + B 5600 200 135400 -45100; + B 1400 200 142700 -45100; + B 1200 200 128000 -45300; + B 6000 200 135400 -45300; + B 1200 200 142800 -45300; + B 1000 200 127900 -45500; + B 6400 200 135400 -45500; + B 1000 200 142900 -45500; + B 800 200 127800 -45700; + B 6800 200 135400 -45700; + B 800 200 143000 -45700; + B 600 200 127700 -45900; + B 7200 200 135400 -45900; + B 600 200 143100 -45900; + B 400 200 127600 -46100; + B 7600 200 135400 -46100; + B 400 200 143200 -46100; + B 200 200 127500 -46300; + B 8000 200 135400 -46300; + B 200 200 143300 -46300; + B 8400 200 135400 -46500; + B 8800 200 135400 -46700; + B 9200 200 135400 -46900; + B 9600 200 135400 -47100; + B 10000 200 135400 -47300; + B 10400 200 135400 -47500; + B 10800 200 135400 -47700; + B 11200 200 135400 -47900; + B 11600 200 135400 -48100; + B 12000 200 135400 -48300; +DF; +C 1; +End + diff --git a/scmos/examples/nist-mems-library/open-oxide-80x80.mag b/scmos/examples/nist-mems-library/open-oxide-80x80.mag new file mode 100644 index 00000000..73fc6254 --- /dev/null +++ b/scmos/examples/nist-mems-library/open-oxide-80x80.mag @@ -0,0 +1,117 @@ +magic +tech scmos +timestamp 760840453 +<< substrateopen >> +rect 647 -163 707 -162 +rect 648 -164 706 -163 +rect 649 -165 705 -164 +rect 650 -166 704 -165 +rect 651 -167 703 -166 +rect 652 -168 702 -167 +rect 653 -169 701 -168 +rect 654 -170 700 -169 +rect 655 -171 699 -170 +rect 656 -172 698 -171 +rect 637 -173 638 -172 +rect 657 -173 697 -172 +rect 716 -173 717 -172 +rect 637 -174 639 -173 +rect 658 -174 696 -173 +rect 715 -174 717 -173 +rect 637 -175 640 -174 +rect 659 -175 695 -174 +rect 714 -175 717 -174 +rect 637 -176 641 -175 +rect 660 -176 694 -175 +rect 713 -176 717 -175 +rect 637 -177 642 -176 +rect 661 -177 693 -176 +rect 712 -177 717 -176 +rect 637 -178 643 -177 +rect 662 -178 692 -177 +rect 711 -178 717 -177 +rect 637 -179 644 -178 +rect 663 -179 691 -178 +rect 710 -179 717 -178 +rect 637 -180 645 -179 +rect 664 -180 690 -179 +rect 709 -180 717 -179 +rect 637 -181 646 -180 +rect 665 -181 689 -180 +rect 708 -181 717 -180 +rect 637 -182 647 -181 +rect 707 -182 717 -181 +rect 637 -183 648 -182 +rect 706 -183 717 -182 +rect 637 -184 649 -183 +rect 705 -184 717 -183 +rect 637 -185 650 -184 +rect 704 -185 717 -184 +rect 637 -186 651 -185 +rect 703 -186 717 -185 +rect 637 -187 652 -186 +rect 702 -187 717 -186 +rect 637 -188 653 -187 +rect 701 -188 717 -187 +rect 637 -189 654 -188 +rect 700 -189 717 -188 +rect 637 -190 655 -189 +rect 699 -190 717 -189 +rect 637 -214 656 -190 +rect 698 -214 717 -190 +rect 637 -215 655 -214 +rect 699 -215 717 -214 +rect 637 -216 654 -215 +rect 700 -216 717 -215 +rect 637 -217 653 -216 +rect 701 -217 717 -216 +rect 637 -218 652 -217 +rect 702 -218 717 -217 +rect 637 -219 651 -218 +rect 703 -219 717 -218 +rect 637 -220 650 -219 +rect 704 -220 717 -219 +rect 637 -221 649 -220 +rect 705 -221 717 -220 +rect 637 -222 648 -221 +rect 706 -222 717 -221 +rect 637 -223 647 -222 +rect 707 -223 717 -222 +rect 637 -224 646 -223 +rect 665 -224 689 -223 +rect 708 -224 717 -223 +rect 637 -225 645 -224 +rect 664 -225 690 -224 +rect 709 -225 717 -224 +rect 637 -226 644 -225 +rect 663 -226 691 -225 +rect 710 -226 717 -225 +rect 637 -227 643 -226 +rect 662 -227 692 -226 +rect 711 -227 717 -226 +rect 637 -228 642 -227 +rect 661 -228 693 -227 +rect 712 -228 717 -227 +rect 637 -229 641 -228 +rect 660 -229 694 -228 +rect 713 -229 717 -228 +rect 637 -230 640 -229 +rect 659 -230 695 -229 +rect 714 -230 717 -229 +rect 637 -231 639 -230 +rect 658 -231 696 -230 +rect 715 -231 717 -230 +rect 637 -232 638 -231 +rect 657 -232 697 -231 +rect 716 -232 717 -231 +rect 656 -233 698 -232 +rect 655 -234 699 -233 +rect 654 -235 700 -234 +rect 653 -236 701 -235 +rect 652 -237 702 -236 +rect 651 -238 703 -237 +rect 650 -239 704 -238 +rect 649 -240 705 -239 +rect 648 -241 706 -240 +rect 647 -242 707 -241 +<< end >> diff --git a/scmos/examples/nist-mems-library/pixel-160x160.cif b/scmos/examples/nist-mems-library/pixel-160x160.cif new file mode 100644 index 00000000..587aae56 --- /dev/null +++ b/scmos/examples/nist-mems-library/pixel-160x160.cif @@ -0,0 +1,1601 @@ +DS 1 1 2; +9 pixel-160x160; +L CMF; + B 1400 200 89900 30500; + B 1600 200 89800 30300; + B 1800 200 89700 30100; + B 2000 200 89600 29900; + B 2200 200 89500 29700; + B 2400 200 89400 29500; + B 2400 200 89200 29300; + B 2400 200 89000 29100; + B 2400 200 88800 28900; + B 2400 200 88600 28700; + B 2400 200 88400 28500; + B 2400 200 88200 28300; + B 2400 200 88000 28100; + B 2400 200 87800 27900; + B 2400 200 87600 27700; + B 2400 200 87400 27500; + B 2400 200 87200 27300; + B 2400 200 87000 27100; + B 2400 200 86800 26900; + B 2400 200 86600 26700; + B 2400 200 86400 26500; + B 2400 200 86200 26300; + B 2400 200 86000 26100; + B 2400 200 85800 25900; + B 2400 200 85600 25700; + B 2400 200 85400 25500; + B 2400 200 85200 25300; + B 2400 200 85000 25100; + B 2400 200 84800 24900; + B 2400 200 84600 24700; + B 2400 200 84400 24500; + B 2400 200 84200 24300; + B 2400 200 84000 24100; + B 2400 200 83800 23900; + B 2400 200 83600 23700; + B 2400 200 83400 23500; + B 2400 200 83200 23300; + B 2400 200 83000 23100; + B 2400 200 82800 22900; + B 2400 200 82600 22700; + B 2400 200 82400 22500; + B 2400 200 82200 22300; + B 2400 200 82000 22100; + B 2400 200 81800 21900; + B 2400 200 81600 21700; + B 2400 200 81400 21500; + B 2400 200 81200 21300; + B 2400 200 81000 21100; + B 2400 200 80800 20900; + B 2400 200 80600 20700; + B 2400 200 80400 20500; + B 4800 200 79000 20300; + B 4600 200 78900 20100; + B 4400 200 78800 19900; + B 4200 200 78700 19700; + B 4000 200 78600 19500; + B 3800 200 78500 19300; + B 3600 200 78400 19100; + B 3400 200 78300 18900; + B 3200 200 78200 18700; + B 3800 200 78500 10500; + B 4000 200 78600 10300; + B 4200 200 78700 10100; + B 4400 200 78800 9900; + B 4600 200 78900 9700; + B 4800 200 79000 9500; + B 5000 200 79100 9300; + B 5200 200 79200 9100; + B 2800 200 80600 8900; + B 2800 200 80800 8700; + B 2800 200 81000 8500; + B 2800 200 81200 8300; + B 2800 200 81400 8100; + B 2800 200 81600 7900; + B 2800 200 81800 7700; + B 2800 200 82000 7500; + B 2800 200 82200 7300; + B 2800 200 82400 7100; + B 2800 200 82600 6900; + B 2800 200 82800 6700; + B 2800 200 83000 6500; + B 2800 200 83200 6300; + B 2800 200 83400 6100; + B 2800 200 83600 5900; + B 2800 200 83800 5700; + B 2800 200 84000 5500; + B 2800 200 84200 5300; + B 2800 200 84400 5100; + B 2800 200 84600 4900; + B 2800 200 84800 4700; + B 2800 200 85000 4500; + B 2800 200 85200 4300; + B 2800 200 85400 4100; + B 2800 200 85600 3900; + B 2800 200 85800 3700; + B 2800 200 86000 3500; + B 2800 200 86200 3300; + B 2800 200 86400 3100; + B 2800 200 86600 2900; + B 2800 200 86800 2700; + B 2800 200 87000 2500; + B 2800 200 87200 2300; + B 2800 200 87400 2100; + B 2800 200 87600 1900; + B 2800 200 87800 1700; + B 2800 200 88000 1500; + B 2800 200 88200 1300; + B 2800 200 88400 1100; + B 2800 200 88600 900; + B 2800 200 88800 700; + B 2800 200 89000 500; + B 2800 200 89200 300; + B 2600 200 89300 100; + B 2400 200 89400 -100; + B 2200 200 89500 -300; + B 2000 200 89600 -500; + B 1800 200 89700 -700; + B 1600 200 89800 -900; + B 1400 200 89900 -1100; + B 1200 200 90000 -1300; +L CPG; + B 3000 800 78100 20000; + B 8400 800 75400 19200; + B 800 400 71600 18600; + B 6800 800 74600 18000; + B 800 600 77600 17300; + B 6800 800 74600 16600; + B 800 600 71600 15900; + B 6800 800 74600 15200; + B 800 400 77600 14600; + B 6800 800 74600 14000; + B 800 400 71600 13400; + B 6800 800 74600 12800; + B 800 600 77600 12100; + B 6800 800 74600 11400; + B 800 600 71600 10700; + B 8400 800 75400 10000; + B 3000 600 78100 9300; +L CAA; + B 34000 1000 74600 31100; + B 1000 2800 58100 29200; + B 25800 200 74700 30500; + B 25400 200 74700 30300; + B 25000 200 74700 30100; + B 24600 200 74700 29900; + B 24200 200 74700 29700; + B 23800 200 74700 29500; + B 23400 200 74700 29300; + B 23000 200 74700 29100; + B 22600 200 74700 28900; + B 22200 200 74700 28700; + B 21800 200 74700 28500; + B 21400 200 74700 28300; + B 21000 200 74700 28100; + B 20600 200 74700 27900; + B 1000 2800 91100 29200; + B 1200 200 58200 27700; + B 20200 200 74700 27700; + B 1200 200 91000 27700; + B 1400 200 58300 27500; + B 19800 200 74700 27500; + B 1400 200 90900 27500; + B 1600 200 58400 27300; + B 19400 200 74700 27300; + B 1600 200 90800 27300; + B 1800 200 58500 27100; + B 19000 200 74700 27100; + B 1800 200 90700 27100; + B 2000 200 58600 26900; + B 18600 200 74700 26900; + B 2000 200 90600 26900; + B 2200 200 58700 26700; + B 18200 200 74700 26700; + B 2200 200 90500 26700; + B 2400 200 58800 26500; + B 17800 200 74700 26500; + B 2400 200 90400 26500; + B 2600 200 58900 26300; + B 17400 200 74700 26300; + B 2600 200 90300 26300; + B 2800 200 59000 26100; + B 17000 200 74700 26100; + B 2800 200 90200 26100; + B 3000 200 59100 25900; + B 16600 200 74700 25900; + B 3000 200 90100 25900; + B 3200 200 59200 25700; + B 16200 200 74700 25700; + B 3200 200 90000 25700; + B 3400 200 59300 25500; + B 15800 200 74700 25500; + B 3400 200 89900 25500; + B 3600 200 59400 25300; + B 15400 200 74700 25300; + B 3600 200 89800 25300; + B 3800 200 59500 25100; + B 15000 200 74700 25100; + B 3800 200 89700 25100; + B 4000 200 59600 24900; + B 14600 200 74700 24900; + B 4000 200 89600 24900; + B 4200 200 59700 24700; + B 14200 200 74700 24700; + B 4200 200 89500 24700; + B 4400 200 59800 24500; + B 13800 200 74700 24500; + B 4400 200 89400 24500; + B 4600 200 59900 24300; + B 13400 200 74700 24300; + B 4600 200 89300 24300; + B 4800 200 60000 24100; + B 13000 200 74700 24100; + B 4800 200 89200 24100; + B 5000 200 60100 23900; + B 12600 200 74700 23900; + B 5000 200 89100 23900; + B 5200 200 60200 23700; + B 12200 200 74700 23700; + B 5200 200 89000 23700; + B 5400 200 60300 23500; + B 11800 200 74700 23500; + B 5400 200 88900 23500; + B 5600 200 60400 23300; + B 11400 200 74700 23300; + B 5600 200 88800 23300; + B 5800 200 60500 23100; + B 11000 200 74700 23100; + B 5800 200 88700 23100; + B 6000 200 60600 22900; + B 10600 200 74700 22900; + B 6000 200 88600 22900; + B 6200 200 60700 22700; + B 10200 200 74700 22700; + B 6200 200 88500 22700; + B 6400 200 60800 22500; + B 9800 200 74700 22500; + B 6400 200 88400 22500; + B 6600 200 60900 22300; + B 9400 200 74700 22300; + B 6600 200 88300 22300; + B 6800 200 61000 22100; + B 9000 200 74700 22100; + B 6800 200 88200 22100; + B 7000 200 61100 21900; + B 8600 200 74700 21900; + B 7000 200 88100 21900; + B 7200 200 61200 21700; + B 8200 200 74700 21700; + B 7200 200 88000 21700; + B 7400 200 61300 21500; + B 7800 200 74700 21500; + B 7400 200 87900 21500; + B 7600 200 61400 21300; + B 7400 200 74700 21300; + B 7600 200 87800 21300; + B 7800 200 61500 21100; + B 7000 200 74700 21100; + B 7800 200 87700 21100; + B 8000 200 61600 20900; + B 8000 200 87600 20900; + B 8200 200 61700 20700; + B 8200 200 87500 20700; + B 8400 200 61800 20500; + B 8400 200 87400 20500; + B 8600 200 61900 20300; + B 8600 200 87300 20300; + B 8800 200 62000 20100; + B 8800 200 87200 20100; + B 9000 200 62100 19900; + B 9000 200 87100 19900; + B 9200 200 62200 19700; + B 9200 200 87000 19700; + B 9400 200 62300 19500; + B 9400 200 86900 19500; + B 9600 200 62400 19300; + B 9600 200 86800 19300; + B 9800 200 62500 19100; + B 9800 200 86700 19100; + B 10000 200 62600 18900; + B 10000 200 86600 18900; + B 10200 200 62700 18700; + B 10200 200 86500 18700; + B 10400 200 62800 18500; + B 10400 200 86400 18500; + B 10600 7000 62900 14900; + B 10600 7000 86300 14900; + B 10400 200 62800 11300; + B 10400 200 86400 11300; + B 10200 200 62700 11100; + B 10200 200 86500 11100; + B 10000 200 62600 10900; + B 10000 200 86600 10900; + B 9800 200 62500 10700; + B 9800 200 86700 10700; + B 9600 200 62400 10500; + B 9600 200 86800 10500; + B 9400 200 62300 10300; + B 9400 200 86900 10300; + B 9200 200 62200 10100; + B 9200 200 87000 10100; + B 9000 200 62100 9900; + B 9000 200 87100 9900; + B 8800 200 62000 9700; + B 8800 200 87200 9700; + B 8600 200 61900 9500; + B 8600 200 87300 9500; + B 8400 200 61800 9300; + B 8400 200 87400 9300; + B 8200 200 61700 9100; + B 8200 200 87500 9100; + B 8000 200 61600 8900; + B 8000 200 87600 8900; + B 7800 200 61500 8700; + B 7800 200 87700 8700; + B 7600 200 61400 8500; + B 7600 200 87800 8500; + B 7400 200 61300 8300; + B 7400 200 87900 8300; + B 7200 200 61200 8100; + B 7000 200 74700 8100; + B 7200 200 88000 8100; + B 7000 200 61100 7900; + B 7400 200 74700 7900; + B 7000 200 88100 7900; + B 6800 200 61000 7700; + B 7800 200 74700 7700; + B 6800 200 88200 7700; + B 6600 200 60900 7500; + B 8200 200 74700 7500; + B 6600 200 88300 7500; + B 6400 200 60800 7300; + B 8600 200 74700 7300; + B 6400 200 88400 7300; + B 6200 200 60700 7100; + B 9000 200 74700 7100; + B 6200 200 88500 7100; + B 6000 200 60600 6900; + B 9400 200 74700 6900; + B 6000 200 88600 6900; + B 5800 200 60500 6700; + B 9800 200 74700 6700; + B 5800 200 88700 6700; + B 5600 200 60400 6500; + B 10200 200 74700 6500; + B 5600 200 88800 6500; + B 5400 200 60300 6300; + B 10600 200 74700 6300; + B 5400 200 88900 6300; + B 5200 200 60200 6100; + B 11000 200 74700 6100; + B 5200 200 89000 6100; + B 5000 200 60100 5900; + B 11400 200 74700 5900; + B 5000 200 89100 5900; + B 4800 200 60000 5700; + B 11800 200 74700 5700; + B 4800 200 89200 5700; + B 4600 200 59900 5500; + B 12200 200 74700 5500; + B 4600 200 89300 5500; + B 4400 200 59800 5300; + B 12600 200 74700 5300; + B 4400 200 89400 5300; + B 4200 200 59700 5100; + B 13000 200 74700 5100; + B 4200 200 89500 5100; + B 4000 200 59600 4900; + B 13400 200 74700 4900; + B 4000 200 89600 4900; + B 3800 200 59500 4700; + B 13800 200 74700 4700; + B 3800 200 89700 4700; + B 3600 200 59400 4500; + B 14200 200 74700 4500; + B 3600 200 89800 4500; + B 3400 200 59300 4300; + B 14600 200 74700 4300; + B 3400 200 89900 4300; + B 3200 200 59200 4100; + B 15000 200 74700 4100; + B 3200 200 90000 4100; + B 3000 200 59100 3900; + B 15400 200 74700 3900; + B 3000 200 90100 3900; + B 2800 200 59000 3700; + B 15800 200 74700 3700; + B 2800 200 90200 3700; + B 2600 200 58900 3500; + B 16200 200 74700 3500; + B 2600 200 90300 3500; + B 2400 200 58800 3300; + B 16600 200 74700 3300; + B 2400 200 90400 3300; + B 2200 200 58700 3100; + B 17000 200 74700 3100; + B 2200 200 90500 3100; + B 2000 200 58600 2900; + B 17400 200 74700 2900; + B 2000 200 90600 2900; + B 1800 200 58500 2700; + B 17800 200 74700 2700; + B 1800 200 90700 2700; + B 1600 200 58400 2500; + B 18200 200 74700 2500; + B 1600 200 90800 2500; + B 1400 200 58300 2300; + B 18600 200 74700 2300; + B 1400 200 90900 2300; + B 1200 200 58200 2100; + B 19000 200 74700 2100; + B 1200 200 91000 2100; + B 1000 3400 58100 300; + B 19400 200 74700 1900; + B 19800 200 74700 1700; + B 20200 200 74700 1500; + B 20600 200 74700 1300; + B 21000 200 74700 1100; + B 21400 200 74700 900; + B 21800 200 74700 700; + B 22200 200 74700 500; + B 22600 200 74700 300; + B 23000 200 74700 100; + B 23400 200 74700 -100; + B 23800 200 74700 -300; + B 24200 200 74700 -500; + B 24600 200 74700 -700; + B 25000 200 74700 -900; + B 25400 200 74700 -1100; + B 25800 200 74700 -1300; + B 1000 3400 91100 300; + B 34000 1000 74600 -1900; +L CVA; + B 25800 200 74700 30500; + B 25400 200 74700 30300; + B 25000 200 74700 30100; + B 24600 200 74700 29900; + B 24200 200 74700 29700; + B 23800 200 74700 29500; + B 23400 200 74700 29300; + B 23000 200 74700 29100; + B 22600 200 74700 28900; + B 22200 200 74700 28700; + B 21800 200 74700 28500; + B 21400 200 74700 28300; + B 21000 200 74700 28100; + B 20600 200 74700 27900; + B 200 200 58700 27700; + B 20200 200 74700 27700; + B 200 200 90500 27700; + B 400 200 58800 27500; + B 19800 200 74700 27500; + B 400 200 90400 27500; + B 600 200 58900 27300; + B 19400 200 74700 27300; + B 600 200 90300 27300; + B 800 200 59000 27100; + B 19000 200 74700 27100; + B 800 200 90200 27100; + B 1000 200 59100 26900; + B 18600 200 74700 26900; + B 1000 200 90100 26900; + B 1200 200 59200 26700; + B 18200 200 74700 26700; + B 1200 200 90000 26700; + B 1400 200 59300 26500; + B 17800 200 74700 26500; + B 1400 200 89900 26500; + B 1600 200 59400 26300; + B 17400 200 74700 26300; + B 1600 200 89800 26300; + B 1800 200 59500 26100; + B 17000 200 74700 26100; + B 1800 200 89700 26100; + B 2000 200 59600 25900; + B 16600 200 74700 25900; + B 2000 200 89600 25900; + B 2200 200 59700 25700; + B 16200 200 74700 25700; + B 2200 200 89500 25700; + B 2400 200 59800 25500; + B 15800 200 74700 25500; + B 2400 200 89400 25500; + B 2600 200 59900 25300; + B 15400 200 74700 25300; + B 2600 200 89300 25300; + B 2800 200 60000 25100; + B 15000 200 74700 25100; + B 2800 200 89200 25100; + B 3000 200 60100 24900; + B 14600 200 74700 24900; + B 3000 200 89100 24900; + B 3200 200 60200 24700; + B 14200 200 74700 24700; + B 3200 200 89000 24700; + B 3400 200 60300 24500; + B 13800 200 74700 24500; + B 3400 200 88900 24500; + B 3600 200 60400 24300; + B 13400 200 74700 24300; + B 3600 200 88800 24300; + B 3800 200 60500 24100; + B 13000 200 74700 24100; + B 3800 200 88700 24100; + B 4000 200 60600 23900; + B 12600 200 74700 23900; + B 4000 200 88600 23900; + B 4200 200 60700 23700; + B 12200 200 74700 23700; + B 4200 200 88500 23700; + B 4400 200 60800 23500; + B 11800 200 74700 23500; + B 4400 200 88400 23500; + B 4600 200 60900 23300; + B 11400 200 74700 23300; + B 4600 200 88300 23300; + B 4800 200 61000 23100; + B 11000 200 74700 23100; + B 4800 200 88200 23100; + B 5000 200 61100 22900; + B 10600 200 74700 22900; + B 5000 200 88100 22900; + B 5200 200 61200 22700; + B 10200 200 74700 22700; + B 5200 200 88000 22700; + B 5400 200 61300 22500; + B 9800 200 74700 22500; + B 5400 200 87900 22500; + B 5600 200 61400 22300; + B 9400 200 74700 22300; + B 5600 200 87800 22300; + B 5800 200 61500 22100; + B 9000 200 74700 22100; + B 5800 200 87700 22100; + B 6000 200 61600 21900; + B 8600 200 74700 21900; + B 6000 200 87600 21900; + B 6200 200 61700 21700; + B 8200 200 74700 21700; + B 6200 200 87500 21700; + B 6400 200 61800 21500; + B 7800 200 74700 21500; + B 6400 200 87400 21500; + B 6600 200 61900 21300; + B 7400 200 74700 21300; + B 6600 200 87300 21300; + B 6800 200 62000 21100; + B 7000 200 74700 21100; + B 6800 200 87200 21100; + B 7000 200 62100 20900; + B 7000 200 87100 20900; + B 7200 200 62200 20700; + B 7200 200 87000 20700; + B 7400 200 62300 20500; + B 7400 200 86900 20500; + B 7600 200 62400 20300; + B 7600 200 86800 20300; + B 7800 200 62500 20100; + B 7800 200 86700 20100; + B 8000 200 62600 19900; + B 8000 200 86600 19900; + B 8200 200 62700 19700; + B 8200 200 86500 19700; + B 8400 200 62800 19500; + B 8400 200 86400 19500; + B 8600 200 62900 19300; + B 8600 200 86300 19300; + B 8800 200 63000 19100; + B 8800 200 86200 19100; + B 9000 200 63100 18900; + B 9000 200 86100 18900; + B 9200 200 63200 18700; + B 9200 200 86000 18700; + B 9400 200 63300 18500; + B 9400 200 85900 18500; + B 9600 7000 63400 14900; + B 9600 7000 85800 14900; + B 9400 200 63300 11300; + B 9400 200 85900 11300; + B 9200 200 63200 11100; + B 9200 200 86000 11100; + B 9000 200 63100 10900; + B 9000 200 86100 10900; + B 8800 200 63000 10700; + B 8800 200 86200 10700; + B 8600 200 62900 10500; + B 8600 200 86300 10500; + B 8400 200 62800 10300; + B 8400 200 86400 10300; + B 8200 200 62700 10100; + B 8200 200 86500 10100; + B 8000 200 62600 9900; + B 8000 200 86600 9900; + B 7800 200 62500 9700; + B 7800 200 86700 9700; + B 7600 200 62400 9500; + B 7600 200 86800 9500; + B 7400 200 62300 9300; + B 7400 200 86900 9300; + B 7200 200 62200 9100; + B 7200 200 87000 9100; + B 7000 200 62100 8900; + B 7000 200 87100 8900; + B 6800 200 62000 8700; + B 6800 200 87200 8700; + B 6600 200 61900 8500; + B 6600 200 87300 8500; + B 6400 200 61800 8300; + B 6400 200 87400 8300; + B 6200 200 61700 8100; + B 7000 200 74700 8100; + B 6200 200 87500 8100; + B 6000 200 61600 7900; + B 7400 200 74700 7900; + B 6000 200 87600 7900; + B 5800 200 61500 7700; + B 7800 200 74700 7700; + B 5800 200 87700 7700; + B 5600 200 61400 7500; + B 8200 200 74700 7500; + B 5600 200 87800 7500; + B 5400 200 61300 7300; + B 8600 200 74700 7300; + B 5400 200 87900 7300; + B 5200 200 61200 7100; + B 9000 200 74700 7100; + B 5200 200 88000 7100; + B 5000 200 61100 6900; + B 9400 200 74700 6900; + B 5000 200 88100 6900; + B 4800 200 61000 6700; + B 9800 200 74700 6700; + B 4800 200 88200 6700; + B 4600 200 60900 6500; + B 10200 200 74700 6500; + B 4600 200 88300 6500; + B 4400 200 60800 6300; + B 10600 200 74700 6300; + B 4400 200 88400 6300; + B 4200 200 60700 6100; + B 11000 200 74700 6100; + B 4200 200 88500 6100; + B 4000 200 60600 5900; + B 11400 200 74700 5900; + B 4000 200 88600 5900; + B 3800 200 60500 5700; + B 11800 200 74700 5700; + B 3800 200 88700 5700; + B 3600 200 60400 5500; + B 12200 200 74700 5500; + B 3600 200 88800 5500; + B 3400 200 60300 5300; + B 12600 200 74700 5300; + B 3400 200 88900 5300; + B 3200 200 60200 5100; + B 13000 200 74700 5100; + B 3200 200 89000 5100; + B 3000 200 60100 4900; + B 13400 200 74700 4900; + B 3000 200 89100 4900; + B 2800 200 60000 4700; + B 13800 200 74700 4700; + B 2800 200 89200 4700; + B 2600 200 59900 4500; + B 14200 200 74700 4500; + B 2600 200 89300 4500; + B 2400 200 59800 4300; + B 14600 200 74700 4300; + B 2400 200 89400 4300; + B 2200 200 59700 4100; + B 15000 200 74700 4100; + B 2200 200 89500 4100; + B 2000 200 59600 3900; + B 15400 200 74700 3900; + B 2000 200 89600 3900; + B 1800 200 59500 3700; + B 15800 200 74700 3700; + B 1800 200 89700 3700; + B 1600 200 59400 3500; + B 16200 200 74700 3500; + B 1600 200 89800 3500; + B 1400 200 59300 3300; + B 16600 200 74700 3300; + B 1400 200 89900 3300; + B 1200 200 59200 3100; + B 17000 200 74700 3100; + B 1200 200 90000 3100; + B 1000 200 59100 2900; + B 17400 200 74700 2900; + B 1000 200 90100 2900; + B 800 200 59000 2700; + B 17800 200 74700 2700; + B 800 200 90200 2700; + B 600 200 58900 2500; + B 18200 200 74700 2500; + B 600 200 90300 2500; + B 400 200 58800 2300; + B 18600 200 74700 2300; + B 400 200 90400 2300; + B 200 200 58700 2100; + B 19000 200 74700 2100; + B 200 200 90500 2100; + B 19400 200 74700 1900; + B 19800 200 74700 1700; + B 20200 200 74700 1500; + B 20600 200 74700 1300; + B 21000 200 74700 1100; + B 21400 200 74700 900; + B 21800 200 74700 700; + B 22200 200 74700 500; + B 22600 200 74700 300; + B 23000 200 74700 100; + B 23400 200 74700 -100; + B 23800 200 74700 -300; + B 24200 200 74700 -500; + B 24600 200 74700 -700; + B 25000 200 74700 -900; + B 25400 200 74700 -1100; + B 25800 200 74700 -1300; +L CCA; + B 25800 200 74700 30500; + B 25400 200 74700 30300; + B 25000 200 74700 30100; + B 24600 200 74700 29900; + B 24200 200 74700 29700; + B 23800 200 74700 29500; + B 23400 200 74700 29300; + B 23000 200 74700 29100; + B 22600 200 74700 28900; + B 22200 200 74700 28700; + B 21800 200 74700 28500; + B 21400 200 74700 28300; + B 21000 200 74700 28100; + B 20600 200 74700 27900; + B 200 200 58700 27700; + B 20200 200 74700 27700; + B 200 200 90500 27700; + B 400 200 58800 27500; + B 19800 200 74700 27500; + B 400 200 90400 27500; + B 600 200 58900 27300; + B 19400 200 74700 27300; + B 600 200 90300 27300; + B 800 200 59000 27100; + B 19000 200 74700 27100; + B 800 200 90200 27100; + B 1000 200 59100 26900; + B 18600 200 74700 26900; + B 1000 200 90100 26900; + B 1200 200 59200 26700; + B 18200 200 74700 26700; + B 1200 200 90000 26700; + B 1400 200 59300 26500; + B 17800 200 74700 26500; + B 1400 200 89900 26500; + B 1600 200 59400 26300; + B 17400 200 74700 26300; + B 1600 200 89800 26300; + B 1800 200 59500 26100; + B 17000 200 74700 26100; + B 1800 200 89700 26100; + B 2000 200 59600 25900; + B 16600 200 74700 25900; + B 2000 200 89600 25900; + B 2200 200 59700 25700; + B 16200 200 74700 25700; + B 2200 200 89500 25700; + B 2400 200 59800 25500; + B 15800 200 74700 25500; + B 2400 200 89400 25500; + B 2600 200 59900 25300; + B 15400 200 74700 25300; + B 2600 200 89300 25300; + B 2800 200 60000 25100; + B 15000 200 74700 25100; + B 2800 200 89200 25100; + B 3000 200 60100 24900; + B 14600 200 74700 24900; + B 3000 200 89100 24900; + B 3200 200 60200 24700; + B 14200 200 74700 24700; + B 3200 200 89000 24700; + B 3400 200 60300 24500; + B 13800 200 74700 24500; + B 3400 200 88900 24500; + B 3600 200 60400 24300; + B 13400 200 74700 24300; + B 3600 200 88800 24300; + B 3800 200 60500 24100; + B 13000 200 74700 24100; + B 3800 200 88700 24100; + B 4000 200 60600 23900; + B 12600 200 74700 23900; + B 4000 200 88600 23900; + B 4200 200 60700 23700; + B 12200 200 74700 23700; + B 4200 200 88500 23700; + B 4400 200 60800 23500; + B 11800 200 74700 23500; + B 4400 200 88400 23500; + B 4600 200 60900 23300; + B 11400 200 74700 23300; + B 4600 200 88300 23300; + B 4800 200 61000 23100; + B 11000 200 74700 23100; + B 4800 200 88200 23100; + B 5000 200 61100 22900; + B 10600 200 74700 22900; + B 5000 200 88100 22900; + B 5200 200 61200 22700; + B 10200 200 74700 22700; + B 5200 200 88000 22700; + B 5400 200 61300 22500; + B 9800 200 74700 22500; + B 5400 200 87900 22500; + B 5600 200 61400 22300; + B 9400 200 74700 22300; + B 5600 200 87800 22300; + B 5800 200 61500 22100; + B 9000 200 74700 22100; + B 5800 200 87700 22100; + B 6000 200 61600 21900; + B 8600 200 74700 21900; + B 6000 200 87600 21900; + B 6200 200 61700 21700; + B 8200 200 74700 21700; + B 6200 200 87500 21700; + B 6400 200 61800 21500; + B 7800 200 74700 21500; + B 6400 200 87400 21500; + B 6600 200 61900 21300; + B 7400 200 74700 21300; + B 6600 200 87300 21300; + B 6800 200 62000 21100; + B 7000 200 74700 21100; + B 6800 200 87200 21100; + B 7000 200 62100 20900; + B 7000 200 87100 20900; + B 7200 200 62200 20700; + B 7200 200 87000 20700; + B 7400 200 62300 20500; + B 7400 200 86900 20500; + B 7600 200 62400 20300; + B 7600 200 86800 20300; + B 7800 200 62500 20100; + B 7800 200 86700 20100; + B 8000 200 62600 19900; + B 8000 200 86600 19900; + B 8200 200 62700 19700; + B 8200 200 86500 19700; + B 8400 200 62800 19500; + B 8400 200 86400 19500; + B 8600 200 62900 19300; + B 8600 200 86300 19300; + B 8800 200 63000 19100; + B 8800 200 86200 19100; + B 9000 200 63100 18900; + B 9000 200 86100 18900; + B 9200 200 63200 18700; + B 9200 200 86000 18700; + B 9400 200 63300 18500; + B 9400 200 85900 18500; + B 9600 7000 63400 14900; + B 9600 7000 85800 14900; + B 9400 200 63300 11300; + B 9400 200 85900 11300; + B 9200 200 63200 11100; + B 9200 200 86000 11100; + B 9000 200 63100 10900; + B 9000 200 86100 10900; + B 8800 200 63000 10700; + B 8800 200 86200 10700; + B 8600 200 62900 10500; + B 8600 200 86300 10500; + B 8400 200 62800 10300; + B 8400 200 86400 10300; + B 8200 200 62700 10100; + B 8200 200 86500 10100; + B 8000 200 62600 9900; + B 8000 200 86600 9900; + B 7800 200 62500 9700; + B 7800 200 86700 9700; + B 7600 200 62400 9500; + B 7600 200 86800 9500; + B 7400 200 62300 9300; + B 7400 200 86900 9300; + B 7200 200 62200 9100; + B 7200 200 87000 9100; + B 7000 200 62100 8900; + B 7000 200 87100 8900; + B 6800 200 62000 8700; + B 6800 200 87200 8700; + B 6600 200 61900 8500; + B 6600 200 87300 8500; + B 6400 200 61800 8300; + B 6400 200 87400 8300; + B 6200 200 61700 8100; + B 7000 200 74700 8100; + B 6200 200 87500 8100; + B 6000 200 61600 7900; + B 7400 200 74700 7900; + B 6000 200 87600 7900; + B 5800 200 61500 7700; + B 7800 200 74700 7700; + B 5800 200 87700 7700; + B 5600 200 61400 7500; + B 8200 200 74700 7500; + B 5600 200 87800 7500; + B 5400 200 61300 7300; + B 8600 200 74700 7300; + B 5400 200 87900 7300; + B 5200 200 61200 7100; + B 9000 200 74700 7100; + B 5200 200 88000 7100; + B 5000 200 61100 6900; + B 9400 200 74700 6900; + B 5000 200 88100 6900; + B 4800 200 61000 6700; + B 9800 200 74700 6700; + B 4800 200 88200 6700; + B 4600 200 60900 6500; + B 10200 200 74700 6500; + B 4600 200 88300 6500; + B 4400 200 60800 6300; + B 10600 200 74700 6300; + B 4400 200 88400 6300; + B 4200 200 60700 6100; + B 11000 200 74700 6100; + B 4200 200 88500 6100; + B 4000 200 60600 5900; + B 11400 200 74700 5900; + B 4000 200 88600 5900; + B 3800 200 60500 5700; + B 11800 200 74700 5700; + B 3800 200 88700 5700; + B 3600 200 60400 5500; + B 12200 200 74700 5500; + B 3600 200 88800 5500; + B 3400 200 60300 5300; + B 12600 200 74700 5300; + B 3400 200 88900 5300; + B 3200 200 60200 5100; + B 13000 200 74700 5100; + B 3200 200 89000 5100; + B 3000 200 60100 4900; + B 13400 200 74700 4900; + B 3000 200 89100 4900; + B 2800 200 60000 4700; + B 13800 200 74700 4700; + B 2800 200 89200 4700; + B 2600 200 59900 4500; + B 14200 200 74700 4500; + B 2600 200 89300 4500; + B 2400 200 59800 4300; + B 14600 200 74700 4300; + B 2400 200 89400 4300; + B 2200 200 59700 4100; + B 15000 200 74700 4100; + B 2200 200 89500 4100; + B 2000 200 59600 3900; + B 15400 200 74700 3900; + B 2000 200 89600 3900; + B 1800 200 59500 3700; + B 15800 200 74700 3700; + B 1800 200 89700 3700; + B 1600 200 59400 3500; + B 16200 200 74700 3500; + B 1600 200 89800 3500; + B 1400 200 59300 3300; + B 16600 200 74700 3300; + B 1400 200 89900 3300; + B 1200 200 59200 3100; + B 17000 200 74700 3100; + B 1200 200 90000 3100; + B 1000 200 59100 2900; + B 17400 200 74700 2900; + B 1000 200 90100 2900; + B 800 200 59000 2700; + B 17800 200 74700 2700; + B 800 200 90200 2700; + B 600 200 58900 2500; + B 18200 200 74700 2500; + B 600 200 90300 2500; + B 400 200 58800 2300; + B 18600 200 74700 2300; + B 400 200 90400 2300; + B 200 200 58700 2100; + B 19000 200 74700 2100; + B 200 200 90500 2100; + B 19400 200 74700 1900; + B 19800 200 74700 1700; + B 20200 200 74700 1500; + B 20600 200 74700 1300; + B 21000 200 74700 1100; + B 21400 200 74700 900; + B 21800 200 74700 700; + B 22200 200 74700 500; + B 22600 200 74700 300; + B 23000 200 74700 100; + B 23400 200 74700 -100; + B 23800 200 74700 -300; + B 24200 200 74700 -500; + B 24600 200 74700 -700; + B 25000 200 74700 -900; + B 25400 200 74700 -1100; + B 25800 200 74700 -1300; +L CCP; + B 400 400 77500 19500; + B 400 400 78700 19500; + B 400 400 77500 9900; + B 400 400 78700 9900; +L CSP; + B 34800 1800 74600 31100; + B 1800 31200 58100 14600; + B 1800 31200 91100 14600; + B 34800 1800 74600 -1900; +L COG; + B 25800 200 74700 30500; + B 25400 200 74700 30300; + B 25000 200 74700 30100; + B 24600 200 74700 29900; + B 24200 200 74700 29700; + B 23800 200 74700 29500; + B 23400 200 74700 29300; + B 23000 200 74700 29100; + B 22600 200 74700 28900; + B 22200 200 74700 28700; + B 21800 200 74700 28500; + B 21400 200 74700 28300; + B 21000 200 74700 28100; + B 20600 200 74700 27900; + B 200 200 58700 27700; + B 20200 200 74700 27700; + B 200 200 90500 27700; + B 400 200 58800 27500; + B 19800 200 74700 27500; + B 400 200 90400 27500; + B 600 200 58900 27300; + B 19400 200 74700 27300; + B 600 200 90300 27300; + B 800 200 59000 27100; + B 19000 200 74700 27100; + B 800 200 90200 27100; + B 1000 200 59100 26900; + B 18600 200 74700 26900; + B 1000 200 90100 26900; + B 1200 200 59200 26700; + B 18200 200 74700 26700; + B 1200 200 90000 26700; + B 1400 200 59300 26500; + B 17800 200 74700 26500; + B 1400 200 89900 26500; + B 1600 200 59400 26300; + B 17400 200 74700 26300; + B 1600 200 89800 26300; + B 1800 200 59500 26100; + B 17000 200 74700 26100; + B 1800 200 89700 26100; + B 2000 200 59600 25900; + B 16600 200 74700 25900; + B 2000 200 89600 25900; + B 2200 200 59700 25700; + B 16200 200 74700 25700; + B 2200 200 89500 25700; + B 2400 200 59800 25500; + B 15800 200 74700 25500; + B 2400 200 89400 25500; + B 2600 200 59900 25300; + B 15400 200 74700 25300; + B 2600 200 89300 25300; + B 2800 200 60000 25100; + B 15000 200 74700 25100; + B 2800 200 89200 25100; + B 3000 200 60100 24900; + B 14600 200 74700 24900; + B 3000 200 89100 24900; + B 3200 200 60200 24700; + B 14200 200 74700 24700; + B 3200 200 89000 24700; + B 3400 200 60300 24500; + B 13800 200 74700 24500; + B 3400 200 88900 24500; + B 3600 200 60400 24300; + B 13400 200 74700 24300; + B 3600 200 88800 24300; + B 3800 200 60500 24100; + B 13000 200 74700 24100; + B 3800 200 88700 24100; + B 4000 200 60600 23900; + B 12600 200 74700 23900; + B 4000 200 88600 23900; + B 4200 200 60700 23700; + B 12200 200 74700 23700; + B 4200 200 88500 23700; + B 4400 200 60800 23500; + B 11800 200 74700 23500; + B 4400 200 88400 23500; + B 4600 200 60900 23300; + B 11400 200 74700 23300; + B 4600 200 88300 23300; + B 4800 200 61000 23100; + B 11000 200 74700 23100; + B 4800 200 88200 23100; + B 5000 200 61100 22900; + B 10600 200 74700 22900; + B 5000 200 88100 22900; + B 5200 200 61200 22700; + B 10200 200 74700 22700; + B 5200 200 88000 22700; + B 5400 200 61300 22500; + B 9800 200 74700 22500; + B 5400 200 87900 22500; + B 5600 200 61400 22300; + B 9400 200 74700 22300; + B 5600 200 87800 22300; + B 5800 200 61500 22100; + B 9000 200 74700 22100; + B 5800 200 87700 22100; + B 6000 200 61600 21900; + B 8600 200 74700 21900; + B 6000 200 87600 21900; + B 6200 200 61700 21700; + B 8200 200 74700 21700; + B 6200 200 87500 21700; + B 6400 200 61800 21500; + B 7800 200 74700 21500; + B 6400 200 87400 21500; + B 6600 200 61900 21300; + B 7400 200 74700 21300; + B 6600 200 87300 21300; + B 6800 200 62000 21100; + B 7000 200 74700 21100; + B 6800 200 87200 21100; + B 7000 200 62100 20900; + B 7000 200 87100 20900; + B 7200 200 62200 20700; + B 7200 200 87000 20700; + B 7400 200 62300 20500; + B 7400 200 86900 20500; + B 7600 200 62400 20300; + B 7600 200 86800 20300; + B 7800 200 62500 20100; + B 7800 200 86700 20100; + B 8000 200 62600 19900; + B 8000 200 86600 19900; + B 8200 200 62700 19700; + B 8200 200 86500 19700; + B 8400 200 62800 19500; + B 8400 200 86400 19500; + B 8600 200 62900 19300; + B 8600 200 86300 19300; + B 8800 200 63000 19100; + B 8800 200 86200 19100; + B 9000 200 63100 18900; + B 9000 200 86100 18900; + B 9200 200 63200 18700; + B 9200 200 86000 18700; + B 9400 200 63300 18500; + B 9400 200 85900 18500; + B 9600 7000 63400 14900; + B 9600 7000 85800 14900; + B 9400 200 63300 11300; + B 9400 200 85900 11300; + B 9200 200 63200 11100; + B 9200 200 86000 11100; + B 9000 200 63100 10900; + B 9000 200 86100 10900; + B 8800 200 63000 10700; + B 8800 200 86200 10700; + B 8600 200 62900 10500; + B 8600 200 86300 10500; + B 8400 200 62800 10300; + B 8400 200 86400 10300; + B 8200 200 62700 10100; + B 8200 200 86500 10100; + B 8000 200 62600 9900; + B 8000 200 86600 9900; + B 7800 200 62500 9700; + B 7800 200 86700 9700; + B 7600 200 62400 9500; + B 7600 200 86800 9500; + B 7400 200 62300 9300; + B 7400 200 86900 9300; + B 7200 200 62200 9100; + B 7200 200 87000 9100; + B 7000 200 62100 8900; + B 7000 200 87100 8900; + B 6800 200 62000 8700; + B 6800 200 87200 8700; + B 6600 200 61900 8500; + B 6600 200 87300 8500; + B 6400 200 61800 8300; + B 6400 200 87400 8300; + B 6200 200 61700 8100; + B 7000 200 74700 8100; + B 6200 200 87500 8100; + B 6000 200 61600 7900; + B 7400 200 74700 7900; + B 6000 200 87600 7900; + B 5800 200 61500 7700; + B 7800 200 74700 7700; + B 5800 200 87700 7700; + B 5600 200 61400 7500; + B 8200 200 74700 7500; + B 5600 200 87800 7500; + B 5400 200 61300 7300; + B 8600 200 74700 7300; + B 5400 200 87900 7300; + B 5200 200 61200 7100; + B 9000 200 74700 7100; + B 5200 200 88000 7100; + B 5000 200 61100 6900; + B 9400 200 74700 6900; + B 5000 200 88100 6900; + B 4800 200 61000 6700; + B 9800 200 74700 6700; + B 4800 200 88200 6700; + B 4600 200 60900 6500; + B 10200 200 74700 6500; + B 4600 200 88300 6500; + B 4400 200 60800 6300; + B 10600 200 74700 6300; + B 4400 200 88400 6300; + B 4200 200 60700 6100; + B 11000 200 74700 6100; + B 4200 200 88500 6100; + B 4000 200 60600 5900; + B 11400 200 74700 5900; + B 4000 200 88600 5900; + B 3800 200 60500 5700; + B 11800 200 74700 5700; + B 3800 200 88700 5700; + B 3600 200 60400 5500; + B 12200 200 74700 5500; + B 3600 200 88800 5500; + B 3400 200 60300 5300; + B 12600 200 74700 5300; + B 3400 200 88900 5300; + B 3200 200 60200 5100; + B 13000 200 74700 5100; + B 3200 200 89000 5100; + B 3000 200 60100 4900; + B 13400 200 74700 4900; + B 3000 200 89100 4900; + B 2800 200 60000 4700; + B 13800 200 74700 4700; + B 2800 200 89200 4700; + B 2600 200 59900 4500; + B 14200 200 74700 4500; + B 2600 200 89300 4500; + B 2400 200 59800 4300; + B 14600 200 74700 4300; + B 2400 200 89400 4300; + B 2200 200 59700 4100; + B 15000 200 74700 4100; + B 2200 200 89500 4100; + B 2000 200 59600 3900; + B 15400 200 74700 3900; + B 2000 200 89600 3900; + B 1800 200 59500 3700; + B 15800 200 74700 3700; + B 1800 200 89700 3700; + B 1600 200 59400 3500; + B 16200 200 74700 3500; + B 1600 200 89800 3500; + B 1400 200 59300 3300; + B 16600 200 74700 3300; + B 1400 200 89900 3300; + B 1200 200 59200 3100; + B 17000 200 74700 3100; + B 1200 200 90000 3100; + B 1000 200 59100 2900; + B 17400 200 74700 2900; + B 1000 200 90100 2900; + B 800 200 59000 2700; + B 17800 200 74700 2700; + B 800 200 90200 2700; + B 600 200 58900 2500; + B 18200 200 74700 2500; + B 600 200 90300 2500; + B 400 200 58800 2300; + B 18600 200 74700 2300; + B 400 200 90400 2300; + B 200 200 58700 2100; + B 19000 200 74700 2100; + B 200 200 90500 2100; + B 19400 200 74700 1900; + B 19800 200 74700 1700; + B 20200 200 74700 1500; + B 20600 200 74700 1300; + B 21000 200 74700 1100; + B 21400 200 74700 900; + B 21800 200 74700 700; + B 22200 200 74700 500; + B 22600 200 74700 300; + B 23000 200 74700 100; + B 23400 200 74700 -100; + B 23800 200 74700 -300; + B 24200 200 74700 -500; + B 24600 200 74700 -700; + B 25000 200 74700 -900; + B 25400 200 74700 -1100; + B 25800 200 74700 -1300; +L COP; + B 25800 200 74700 30500; + B 25400 200 74700 30300; + B 25000 200 74700 30100; + B 24600 200 74700 29900; + B 24200 200 74700 29700; + B 23800 200 74700 29500; + B 23400 200 74700 29300; + B 23000 200 74700 29100; + B 22600 200 74700 28900; + B 22200 200 74700 28700; + B 21800 200 74700 28500; + B 21400 200 74700 28300; + B 21000 200 74700 28100; + B 20600 200 74700 27900; + B 200 200 58700 27700; + B 20200 200 74700 27700; + B 200 200 90500 27700; + B 400 200 58800 27500; + B 19800 200 74700 27500; + B 400 200 90400 27500; + B 600 200 58900 27300; + B 19400 200 74700 27300; + B 600 200 90300 27300; + B 800 200 59000 27100; + B 19000 200 74700 27100; + B 800 200 90200 27100; + B 1000 200 59100 26900; + B 18600 200 74700 26900; + B 1000 200 90100 26900; + B 1200 200 59200 26700; + B 18200 200 74700 26700; + B 1200 200 90000 26700; + B 1400 200 59300 26500; + B 17800 200 74700 26500; + B 1400 200 89900 26500; + B 1600 200 59400 26300; + B 17400 200 74700 26300; + B 1600 200 89800 26300; + B 1800 200 59500 26100; + B 17000 200 74700 26100; + B 1800 200 89700 26100; + B 2000 200 59600 25900; + B 16600 200 74700 25900; + B 2000 200 89600 25900; + B 2200 200 59700 25700; + B 16200 200 74700 25700; + B 2200 200 89500 25700; + B 2400 200 59800 25500; + B 15800 200 74700 25500; + B 2400 200 89400 25500; + B 2600 200 59900 25300; + B 15400 200 74700 25300; + B 2600 200 89300 25300; + B 2800 200 60000 25100; + B 15000 200 74700 25100; + B 2800 200 89200 25100; + B 3000 200 60100 24900; + B 14600 200 74700 24900; + B 3000 200 89100 24900; + B 3200 200 60200 24700; + B 14200 200 74700 24700; + B 3200 200 89000 24700; + B 3400 200 60300 24500; + B 13800 200 74700 24500; + B 3400 200 88900 24500; + B 3600 200 60400 24300; + B 13400 200 74700 24300; + B 3600 200 88800 24300; + B 3800 200 60500 24100; + B 13000 200 74700 24100; + B 3800 200 88700 24100; + B 4000 200 60600 23900; + B 12600 200 74700 23900; + B 4000 200 88600 23900; + B 4200 200 60700 23700; + B 12200 200 74700 23700; + B 4200 200 88500 23700; + B 4400 200 60800 23500; + B 11800 200 74700 23500; + B 4400 200 88400 23500; + B 4600 200 60900 23300; + B 11400 200 74700 23300; + B 4600 200 88300 23300; + B 4800 200 61000 23100; + B 11000 200 74700 23100; + B 4800 200 88200 23100; + B 5000 200 61100 22900; + B 10600 200 74700 22900; + B 5000 200 88100 22900; + B 5200 200 61200 22700; + B 10200 200 74700 22700; + B 5200 200 88000 22700; + B 5400 200 61300 22500; + B 9800 200 74700 22500; + B 5400 200 87900 22500; + B 5600 200 61400 22300; + B 9400 200 74700 22300; + B 5600 200 87800 22300; + B 5800 200 61500 22100; + B 9000 200 74700 22100; + B 5800 200 87700 22100; + B 6000 200 61600 21900; + B 8600 200 74700 21900; + B 6000 200 87600 21900; + B 6200 200 61700 21700; + B 8200 200 74700 21700; + B 6200 200 87500 21700; + B 6400 200 61800 21500; + B 7800 200 74700 21500; + B 6400 200 87400 21500; + B 6600 200 61900 21300; + B 7400 200 74700 21300; + B 6600 200 87300 21300; + B 6800 200 62000 21100; + B 7000 200 74700 21100; + B 6800 200 87200 21100; + B 7000 200 62100 20900; + B 7000 200 87100 20900; + B 7200 200 62200 20700; + B 7200 200 87000 20700; + B 7400 200 62300 20500; + B 7400 200 86900 20500; + B 7600 200 62400 20300; + B 7600 200 86800 20300; + B 7800 200 62500 20100; + B 7800 200 86700 20100; + B 8000 200 62600 19900; + B 8000 200 86600 19900; + B 8200 200 62700 19700; + B 8200 200 86500 19700; + B 8400 200 62800 19500; + B 8400 200 86400 19500; + B 8600 200 62900 19300; + B 8600 200 86300 19300; + B 8800 200 63000 19100; + B 8800 200 86200 19100; + B 9000 200 63100 18900; + B 9000 200 86100 18900; + B 9200 200 63200 18700; + B 9200 200 86000 18700; + B 9400 200 63300 18500; + B 9400 200 85900 18500; + B 9600 7000 63400 14900; + B 9600 7000 85800 14900; + B 9400 200 63300 11300; + B 9400 200 85900 11300; + B 9200 200 63200 11100; + B 9200 200 86000 11100; + B 9000 200 63100 10900; + B 9000 200 86100 10900; + B 8800 200 63000 10700; + B 8800 200 86200 10700; + B 8600 200 62900 10500; + B 8600 200 86300 10500; + B 8400 200 62800 10300; + B 8400 200 86400 10300; + B 8200 200 62700 10100; + B 8200 200 86500 10100; + B 8000 200 62600 9900; + B 8000 200 86600 9900; + B 7800 200 62500 9700; + B 7800 200 86700 9700; + B 7600 200 62400 9500; + B 7600 200 86800 9500; + B 7400 200 62300 9300; + B 7400 200 86900 9300; + B 7200 200 62200 9100; + B 7200 200 87000 9100; + B 7000 200 62100 8900; + B 7000 200 87100 8900; + B 6800 200 62000 8700; + B 6800 200 87200 8700; + B 6600 200 61900 8500; + B 6600 200 87300 8500; + B 6400 200 61800 8300; + B 6400 200 87400 8300; + B 6200 200 61700 8100; + B 7000 200 74700 8100; + B 6200 200 87500 8100; + B 6000 200 61600 7900; + B 7400 200 74700 7900; + B 6000 200 87600 7900; + B 5800 200 61500 7700; + B 7800 200 74700 7700; + B 5800 200 87700 7700; + B 5600 200 61400 7500; + B 8200 200 74700 7500; + B 5600 200 87800 7500; + B 5400 200 61300 7300; + B 8600 200 74700 7300; + B 5400 200 87900 7300; + B 5200 200 61200 7100; + B 9000 200 74700 7100; + B 5200 200 88000 7100; + B 5000 200 61100 6900; + B 9400 200 74700 6900; + B 5000 200 88100 6900; + B 4800 200 61000 6700; + B 9800 200 74700 6700; + B 4800 200 88200 6700; + B 4600 200 60900 6500; + B 10200 200 74700 6500; + B 4600 200 88300 6500; + B 4400 200 60800 6300; + B 10600 200 74700 6300; + B 4400 200 88400 6300; + B 4200 200 60700 6100; + B 11000 200 74700 6100; + B 4200 200 88500 6100; + B 4000 200 60600 5900; + B 11400 200 74700 5900; + B 4000 200 88600 5900; + B 3800 200 60500 5700; + B 11800 200 74700 5700; + B 3800 200 88700 5700; + B 3600 200 60400 5500; + B 12200 200 74700 5500; + B 3600 200 88800 5500; + B 3400 200 60300 5300; + B 12600 200 74700 5300; + B 3400 200 88900 5300; + B 3200 200 60200 5100; + B 13000 200 74700 5100; + B 3200 200 89000 5100; + B 3000 200 60100 4900; + B 13400 200 74700 4900; + B 3000 200 89100 4900; + B 2800 200 60000 4700; + B 13800 200 74700 4700; + B 2800 200 89200 4700; + B 2600 200 59900 4500; + B 14200 200 74700 4500; + B 2600 200 89300 4500; + B 2400 200 59800 4300; + B 14600 200 74700 4300; + B 2400 200 89400 4300; + B 2200 200 59700 4100; + B 15000 200 74700 4100; + B 2200 200 89500 4100; + B 2000 200 59600 3900; + B 15400 200 74700 3900; + B 2000 200 89600 3900; + B 1800 200 59500 3700; + B 15800 200 74700 3700; + B 1800 200 89700 3700; + B 1600 200 59400 3500; + B 16200 200 74700 3500; + B 1600 200 89800 3500; + B 1400 200 59300 3300; + B 16600 200 74700 3300; + B 1400 200 89900 3300; + B 1200 200 59200 3100; + B 17000 200 74700 3100; + B 1200 200 90000 3100; + B 1000 200 59100 2900; + B 17400 200 74700 2900; + B 1000 200 90100 2900; + B 800 200 59000 2700; + B 17800 200 74700 2700; + B 800 200 90200 2700; + B 600 200 58900 2500; + B 18200 200 74700 2500; + B 600 200 90300 2500; + B 400 200 58800 2300; + B 18600 200 74700 2300; + B 400 200 90400 2300; + B 200 200 58700 2100; + B 19000 200 74700 2100; + B 200 200 90500 2100; + B 19400 200 74700 1900; + B 19800 200 74700 1700; + B 20200 200 74700 1500; + B 20600 200 74700 1300; + B 21000 200 74700 1100; + B 21400 200 74700 900; + B 21800 200 74700 700; + B 22200 200 74700 500; + B 22600 200 74700 300; + B 23000 200 74700 100; + B 23400 200 74700 -100; + B 23800 200 74700 -300; + B 24200 200 74700 -500; + B 24600 200 74700 -700; + B 25000 200 74700 -900; + B 25400 200 74700 -1100; + B 25800 200 74700 -1300; +L CPS; + B 34000 1000 74600 31100; + B 1000 32000 58100 14600; + B 1000 32000 91100 14600; + B 34000 1000 74600 -1900; +DF; +C 1; +End + diff --git a/scmos/examples/nist-mems-library/pixel-160x160.mag b/scmos/examples/nist-mems-library/pixel-160x160.mag new file mode 100644 index 00000000..9544619c --- /dev/null +++ b/scmos/examples/nist-mems-library/pixel-160x160.mag @@ -0,0 +1,452 @@ +magic +tech scmos +timestamp 760840608 +<< polysilicon >> +rect 383 99 398 102 +rect 383 98 385 99 +rect 356 95 385 98 +rect 389 95 391 99 +rect 395 95 398 99 +rect 356 94 398 95 +rect 356 92 360 94 +rect 356 88 390 92 +rect 386 85 390 88 +rect 356 81 390 85 +rect 356 78 360 81 +rect 356 74 390 78 +rect 386 72 390 74 +rect 356 68 390 72 +rect 356 66 360 68 +rect 356 62 390 66 +rect 386 59 390 62 +rect 356 55 390 59 +rect 356 52 360 55 +rect 356 51 398 52 +rect 356 48 385 51 +rect 383 47 385 48 +rect 389 47 391 51 +rect 395 47 398 51 +rect 383 45 398 47 +<< metal1 >> +rect 446 152 453 153 +rect 445 151 453 152 +rect 444 150 453 151 +rect 443 149 453 150 +rect 442 148 453 149 +rect 441 147 453 148 +rect 440 146 452 147 +rect 439 145 451 146 +rect 438 144 450 145 +rect 437 143 449 144 +rect 436 142 448 143 +rect 435 141 447 142 +rect 434 140 446 141 +rect 433 139 445 140 +rect 432 138 444 139 +rect 431 137 443 138 +rect 430 136 442 137 +rect 429 135 441 136 +rect 428 134 440 135 +rect 427 133 439 134 +rect 426 132 438 133 +rect 425 131 437 132 +rect 424 130 436 131 +rect 423 129 435 130 +rect 422 128 434 129 +rect 421 127 433 128 +rect 420 126 432 127 +rect 419 125 431 126 +rect 418 124 430 125 +rect 417 123 429 124 +rect 416 122 428 123 +rect 415 121 427 122 +rect 414 120 426 121 +rect 413 119 425 120 +rect 412 118 424 119 +rect 411 117 423 118 +rect 410 116 422 117 +rect 409 115 421 116 +rect 408 114 420 115 +rect 407 113 419 114 +rect 406 112 418 113 +rect 405 111 417 112 +rect 404 110 416 111 +rect 403 109 415 110 +rect 402 108 414 109 +rect 401 107 413 108 +rect 400 106 412 107 +rect 399 105 411 106 +rect 398 104 410 105 +rect 397 103 409 104 +rect 396 102 408 103 +rect 383 101 407 102 +rect 383 100 406 101 +rect 383 99 405 100 +rect 383 95 385 99 +rect 389 95 391 99 +rect 395 98 404 99 +rect 395 97 403 98 +rect 395 96 402 97 +rect 395 95 401 96 +rect 383 94 400 95 +rect 383 93 399 94 +rect 383 52 402 53 +rect 383 51 403 52 +rect 383 47 385 51 +rect 389 47 391 51 +rect 395 50 404 51 +rect 395 49 405 50 +rect 395 48 406 49 +rect 395 47 407 48 +rect 383 46 408 47 +rect 383 45 409 46 +rect 396 44 410 45 +rect 397 43 411 44 +rect 398 42 412 43 +rect 399 41 413 42 +rect 400 40 414 41 +rect 401 39 415 40 +rect 402 38 416 39 +rect 403 37 417 38 +rect 404 36 418 37 +rect 405 35 419 36 +rect 406 34 420 35 +rect 407 33 421 34 +rect 408 32 422 33 +rect 409 31 423 32 +rect 410 30 424 31 +rect 411 29 425 30 +rect 412 28 426 29 +rect 413 27 427 28 +rect 414 26 428 27 +rect 415 25 429 26 +rect 416 24 430 25 +rect 417 23 431 24 +rect 418 22 432 23 +rect 419 21 433 22 +rect 420 20 434 21 +rect 421 19 435 20 +rect 422 18 436 19 +rect 423 17 437 18 +rect 424 16 438 17 +rect 425 15 439 16 +rect 426 14 440 15 +rect 427 13 441 14 +rect 428 12 442 13 +rect 429 11 443 12 +rect 430 10 444 11 +rect 431 9 445 10 +rect 432 8 446 9 +rect 433 7 447 8 +rect 434 6 448 7 +rect 435 5 449 6 +rect 436 4 450 5 +rect 437 3 451 4 +rect 438 2 452 3 +rect 439 1 453 2 +rect 440 0 453 1 +rect 441 -1 453 0 +rect 442 -2 453 -1 +rect 443 -3 453 -2 +rect 444 -4 453 -3 +rect 445 -5 453 -4 +rect 446 -6 453 -5 +rect 447 -7 453 -6 +<< polycontact >> +rect 385 95 389 99 +rect 391 95 395 99 +rect 385 47 389 51 +rect 391 47 395 51 +<< substrateopen >> +rect 309 152 438 153 +rect 310 151 437 152 +rect 311 150 436 151 +rect 312 149 435 150 +rect 313 148 434 149 +rect 314 147 433 148 +rect 315 146 432 147 +rect 316 145 431 146 +rect 317 144 430 145 +rect 318 143 429 144 +rect 319 142 428 143 +rect 320 141 427 142 +rect 321 140 426 141 +rect 322 139 425 140 +rect 293 138 294 139 +rect 323 138 424 139 +rect 452 138 453 139 +rect 293 137 295 138 +rect 324 137 423 138 +rect 451 137 453 138 +rect 293 136 296 137 +rect 325 136 422 137 +rect 450 136 453 137 +rect 293 135 297 136 +rect 326 135 421 136 +rect 449 135 453 136 +rect 293 134 298 135 +rect 327 134 420 135 +rect 448 134 453 135 +rect 293 133 299 134 +rect 328 133 419 134 +rect 447 133 453 134 +rect 293 132 300 133 +rect 329 132 418 133 +rect 446 132 453 133 +rect 293 131 301 132 +rect 330 131 417 132 +rect 445 131 453 132 +rect 293 130 302 131 +rect 331 130 416 131 +rect 444 130 453 131 +rect 293 129 303 130 +rect 332 129 415 130 +rect 443 129 453 130 +rect 293 128 304 129 +rect 333 128 414 129 +rect 442 128 453 129 +rect 293 127 305 128 +rect 334 127 413 128 +rect 441 127 453 128 +rect 293 126 306 127 +rect 335 126 412 127 +rect 440 126 453 127 +rect 293 125 307 126 +rect 336 125 411 126 +rect 439 125 453 126 +rect 293 124 308 125 +rect 337 124 410 125 +rect 438 124 453 125 +rect 293 123 309 124 +rect 338 123 409 124 +rect 437 123 453 124 +rect 293 122 310 123 +rect 339 122 408 123 +rect 436 122 453 123 +rect 293 121 311 122 +rect 340 121 407 122 +rect 435 121 453 122 +rect 293 120 312 121 +rect 341 120 406 121 +rect 434 120 453 121 +rect 293 119 313 120 +rect 342 119 405 120 +rect 433 119 453 120 +rect 293 118 314 119 +rect 343 118 404 119 +rect 432 118 453 119 +rect 293 117 315 118 +rect 344 117 403 118 +rect 431 117 453 118 +rect 293 116 316 117 +rect 345 116 402 117 +rect 430 116 453 117 +rect 293 115 317 116 +rect 346 115 401 116 +rect 429 115 453 116 +rect 293 114 318 115 +rect 347 114 400 115 +rect 428 114 453 115 +rect 293 113 319 114 +rect 348 113 399 114 +rect 427 113 453 114 +rect 293 112 320 113 +rect 349 112 398 113 +rect 426 112 453 113 +rect 293 111 321 112 +rect 350 111 397 112 +rect 425 111 453 112 +rect 293 110 322 111 +rect 351 110 396 111 +rect 424 110 453 111 +rect 293 109 323 110 +rect 352 109 395 110 +rect 423 109 453 110 +rect 293 108 324 109 +rect 353 108 394 109 +rect 422 108 453 109 +rect 293 107 325 108 +rect 354 107 393 108 +rect 421 107 453 108 +rect 293 106 326 107 +rect 355 106 392 107 +rect 420 106 453 107 +rect 293 105 327 106 +rect 356 105 391 106 +rect 419 105 453 106 +rect 293 104 328 105 +rect 418 104 453 105 +rect 293 103 329 104 +rect 417 103 453 104 +rect 293 102 330 103 +rect 416 102 453 103 +rect 293 101 331 102 +rect 415 101 453 102 +rect 293 100 332 101 +rect 414 100 453 101 +rect 293 99 333 100 +rect 413 99 453 100 +rect 293 98 334 99 +rect 412 98 453 99 +rect 293 97 335 98 +rect 411 97 453 98 +rect 293 96 336 97 +rect 410 96 453 97 +rect 293 95 337 96 +rect 409 95 453 96 +rect 293 94 338 95 +rect 408 94 453 95 +rect 293 93 339 94 +rect 407 93 453 94 +rect 293 92 340 93 +rect 406 92 453 93 +rect 293 57 341 92 +rect 405 57 453 92 +rect 293 56 340 57 +rect 406 56 453 57 +rect 293 55 339 56 +rect 407 55 453 56 +rect 293 54 338 55 +rect 408 54 453 55 +rect 293 53 337 54 +rect 409 53 453 54 +rect 293 52 336 53 +rect 410 52 453 53 +rect 293 51 335 52 +rect 411 51 453 52 +rect 293 50 334 51 +rect 412 50 453 51 +rect 293 49 333 50 +rect 413 49 453 50 +rect 293 48 332 49 +rect 414 48 453 49 +rect 293 47 331 48 +rect 415 47 453 48 +rect 293 46 330 47 +rect 416 46 453 47 +rect 293 45 329 46 +rect 417 45 453 46 +rect 293 44 328 45 +rect 418 44 453 45 +rect 293 43 327 44 +rect 419 43 453 44 +rect 293 42 326 43 +rect 420 42 453 43 +rect 293 41 325 42 +rect 421 41 453 42 +rect 293 40 324 41 +rect 356 40 391 41 +rect 422 40 453 41 +rect 293 39 323 40 +rect 355 39 392 40 +rect 423 39 453 40 +rect 293 38 322 39 +rect 354 38 393 39 +rect 424 38 453 39 +rect 293 37 321 38 +rect 353 37 394 38 +rect 425 37 453 38 +rect 293 36 320 37 +rect 352 36 395 37 +rect 426 36 453 37 +rect 293 35 319 36 +rect 351 35 396 36 +rect 427 35 453 36 +rect 293 34 318 35 +rect 350 34 397 35 +rect 428 34 453 35 +rect 293 33 317 34 +rect 349 33 398 34 +rect 429 33 453 34 +rect 293 32 316 33 +rect 348 32 399 33 +rect 430 32 453 33 +rect 293 31 315 32 +rect 347 31 400 32 +rect 431 31 453 32 +rect 293 30 314 31 +rect 346 30 401 31 +rect 432 30 453 31 +rect 293 29 313 30 +rect 345 29 402 30 +rect 433 29 453 30 +rect 293 28 312 29 +rect 344 28 403 29 +rect 434 28 453 29 +rect 293 27 311 28 +rect 343 27 404 28 +rect 435 27 453 28 +rect 293 26 310 27 +rect 342 26 405 27 +rect 436 26 453 27 +rect 293 25 309 26 +rect 341 25 406 26 +rect 437 25 453 26 +rect 293 24 308 25 +rect 340 24 407 25 +rect 438 24 453 25 +rect 293 23 307 24 +rect 339 23 408 24 +rect 439 23 453 24 +rect 293 22 306 23 +rect 338 22 409 23 +rect 440 22 453 23 +rect 293 21 305 22 +rect 337 21 410 22 +rect 441 21 453 22 +rect 293 20 304 21 +rect 336 20 411 21 +rect 442 20 453 21 +rect 293 19 303 20 +rect 335 19 412 20 +rect 443 19 453 20 +rect 293 18 302 19 +rect 334 18 413 19 +rect 444 18 453 19 +rect 293 17 301 18 +rect 333 17 414 18 +rect 445 17 453 18 +rect 293 16 300 17 +rect 332 16 415 17 +rect 446 16 453 17 +rect 293 15 299 16 +rect 331 15 416 16 +rect 447 15 453 16 +rect 293 14 298 15 +rect 330 14 417 15 +rect 448 14 453 15 +rect 293 13 297 14 +rect 329 13 418 14 +rect 449 13 453 14 +rect 293 12 296 13 +rect 328 12 419 13 +rect 450 12 453 13 +rect 293 11 295 12 +rect 327 11 420 12 +rect 451 11 453 12 +rect 293 10 294 11 +rect 326 10 421 11 +rect 452 10 453 11 +rect 325 9 422 10 +rect 324 8 423 9 +rect 323 7 424 8 +rect 322 6 425 7 +rect 321 5 426 6 +rect 320 4 427 5 +rect 319 3 428 4 +rect 318 2 429 3 +rect 317 1 430 2 +rect 316 0 431 1 +rect 315 -1 432 0 +rect 314 -2 433 -1 +rect 313 -3 434 -2 +rect 312 -4 435 -3 +rect 311 -5 436 -4 +rect 310 -6 437 -5 +rect 309 -7 438 -6 +<< pdiffusionstop >> +rect 288 153 458 158 +rect 288 -7 293 153 +rect 453 -7 458 153 +rect 288 -12 458 -7 +<< end >> diff --git a/scmos/examples/nist-mems-library/pixel-80x80.cif b/scmos/examples/nist-mems-library/pixel-80x80.cif new file mode 100644 index 00000000..3458c3d2 --- /dev/null +++ b/scmos/examples/nist-mems-library/pixel-80x80.cif @@ -0,0 +1,678 @@ +DS 1 1 2; +9 pixel-80x80; +L CMS; + B 1200 1200 115800 15800; +L CMF; + B 1200 600 115800 16100; + B 1400 200 115700 15700; + B 1600 200 115600 15500; + B 1800 200 115500 15300; + B 1400 200 115100 15100; + B 1400 200 114900 14900; + B 1400 200 114700 14700; + B 1400 200 114500 14500; + B 1400 200 114300 14300; + B 1400 200 114100 14100; + B 1400 200 113900 13900; + B 1400 200 113700 13700; + B 1400 200 113500 13500; + B 1400 200 113300 13300; + B 1400 200 113100 13100; + B 1400 200 112900 12900; + B 1400 200 112700 12700; + B 1400 200 112500 12500; + B 1400 200 112300 12300; + B 1400 200 112100 12100; + B 1400 200 111900 11900; + B 1400 200 111700 11700; + B 1800 200 111300 11500; + B 1600 200 111200 11300; + B 1400 200 111100 11100; + B 1200 1600 111000 10200; + B 1200 1600 111000 6600; + B 1400 200 111100 5700; + B 1600 200 111200 5500; + B 1800 200 111300 5300; + B 1400 200 111700 5100; + B 1400 200 111900 4900; + B 1400 200 112100 4700; + B 1400 200 112300 4500; + B 1400 200 112500 4300; + B 1400 200 112700 4100; + B 1400 200 112900 3900; + B 1400 200 113100 3700; + B 1400 200 113300 3500; + B 1400 200 113500 3300; + B 1400 200 113700 3100; + B 1400 200 113900 2900; + B 1400 200 114100 2700; + B 1400 200 114300 2500; + B 1400 200 114500 2300; + B 1400 200 114700 2100; + B 1400 200 114900 1900; + B 1400 200 115100 1700; + B 1400 200 115300 1500; + B 1400 200 115500 1300; + B 1400 200 115700 1100; + B 1200 200 115800 900; + B 1000 200 115900 700; + B 800 200 116000 500; +L CPG; + B 1200 400 106200 11400; + B 400 5600 105800 8400; + B 400 2200 106600 10100; + B 1200 400 107800 11400; + B 400 2200 107400 10100; + B 1200 400 107000 8800; + B 400 2200 108200 10100; + B 1200 400 109400 11400; + B 400 2200 109000 10100; + B 1200 400 108600 8800; + B 400 2200 109800 10100; + B 1200 2200 111000 10500; + B 800 400 111000 9200; + B 1800 400 110500 8800; + B 1200 400 107000 8000; + B 400 2200 106600 6700; + B 1200 400 106200 5400; + B 400 2200 107400 6700; + B 1200 400 108600 8000; + B 400 2200 108200 6700; + B 1200 400 107800 5400; + B 400 2200 109000 6700; + B 1800 400 110500 8000; + B 400 2200 109800 6700; + B 800 400 111000 7600; + B 1200 400 109400 5400; + B 1200 2200 111000 6300; +L CAA; + B 18000 1000 108400 16900; + B 1000 2000 99900 15400; + B 12000 200 108400 16300; + B 11600 200 108400 16100; + B 11200 200 108400 15900; + B 10800 200 108400 15700; + B 10400 200 108400 15500; + B 10000 200 108400 15300; + B 9600 200 108400 15100; + B 9200 200 108400 14900; + B 8800 200 108400 14700; + B 8400 200 108400 14500; + B 1000 2000 116900 15400; + B 1200 200 100000 14300; + B 8000 200 108400 14300; + B 1200 200 116800 14300; + B 1400 200 100100 14100; + B 7600 200 108400 14100; + B 1400 200 116700 14100; + B 1600 200 100200 13900; + B 7200 200 108400 13900; + B 1600 200 116600 13900; + B 1800 200 100300 13700; + B 6800 200 108400 13700; + B 1800 200 116500 13700; + B 2000 200 100400 13500; + B 6400 200 108400 13500; + B 2000 200 116400 13500; + B 2200 200 100500 13300; + B 6000 200 108400 13300; + B 2200 200 116300 13300; + B 2400 200 100600 13100; + B 5600 200 108400 13100; + B 2400 200 116200 13100; + B 2600 200 100700 12900; + B 5200 200 108400 12900; + B 2600 200 116100 12900; + B 2800 200 100800 12700; + B 4800 200 108400 12700; + B 2800 200 116000 12700; + B 3000 200 100900 12500; + B 3000 200 115900 12500; + B 3200 200 101000 12300; + B 3200 200 115800 12300; + B 3400 200 101100 12100; + B 3400 200 115700 12100; + B 3600 200 101200 11900; + B 3600 200 115600 11900; + B 3800 200 101300 11700; + B 3800 200 115500 11700; + B 4000 200 101400 11500; + B 4000 200 115400 11500; + B 4200 200 101500 11300; + B 4200 200 115300 11300; + B 4400 200 101600 11100; + B 4400 200 115200 11100; + B 4600 200 101700 10900; + B 4600 200 115100 10900; + B 4800 4800 101800 8400; + B 4800 4800 115000 8400; + B 4600 200 101700 5900; + B 4600 200 115100 5900; + B 4400 200 101600 5700; + B 4400 200 115200 5700; + B 4200 200 101500 5500; + B 4200 200 115300 5500; + B 4000 200 101400 5300; + B 4000 200 115400 5300; + B 3800 200 101300 5100; + B 3800 200 115500 5100; + B 3600 200 101200 4900; + B 3600 200 115600 4900; + B 3400 200 101100 4700; + B 3400 200 115700 4700; + B 3200 200 101000 4500; + B 3200 200 115800 4500; + B 3000 200 100900 4300; + B 3000 200 115900 4300; + B 2800 200 100800 4100; + B 4800 200 108400 4100; + B 2800 200 116000 4100; + B 2600 200 100700 3900; + B 5200 200 108400 3900; + B 2600 200 116100 3900; + B 2400 200 100600 3700; + B 5600 200 108400 3700; + B 2400 200 116200 3700; + B 2200 200 100500 3500; + B 6000 200 108400 3500; + B 2200 200 116300 3500; + B 2000 200 100400 3300; + B 6400 200 108400 3300; + B 2000 200 116400 3300; + B 1800 200 100300 3100; + B 6800 200 108400 3100; + B 1800 200 116500 3100; + B 1600 200 100200 2900; + B 7200 200 108400 2900; + B 1600 200 116600 2900; + B 1400 200 100100 2700; + B 7600 200 108400 2700; + B 1400 200 116700 2700; + B 1200 200 100000 2500; + B 8000 200 108400 2500; + B 1200 200 116800 2500; + B 1000 2000 99900 1400; + B 8400 200 108400 2300; + B 8800 200 108400 2100; + B 9200 200 108400 1900; + B 9600 200 108400 1700; + B 10000 200 108400 1500; + B 10400 200 108400 1300; + B 10800 200 108400 1100; + B 11200 200 108400 900; + B 11600 200 108400 700; + B 12000 200 108400 500; + B 1000 2000 116900 1400; + B 18000 1000 108400 -100; +L CVA; + B 12000 200 108400 16300; + B 11600 200 108400 16100; + B 11200 200 108400 15900; + B 10800 200 108400 15700; + B 400 400 115800 15800; + B 10400 200 108400 15500; + B 10000 200 108400 15300; + B 9600 200 108400 15100; + B 9200 200 108400 14900; + B 8800 200 108400 14700; + B 8400 200 108400 14500; + B 200 200 100500 14300; + B 8000 200 108400 14300; + B 200 200 116300 14300; + B 400 200 100600 14100; + B 7600 200 108400 14100; + B 400 200 116200 14100; + B 600 200 100700 13900; + B 7200 200 108400 13900; + B 600 200 116100 13900; + B 800 200 100800 13700; + B 6800 200 108400 13700; + B 800 200 116000 13700; + B 1000 200 100900 13500; + B 6400 200 108400 13500; + B 1000 200 115900 13500; + B 1200 200 101000 13300; + B 6000 200 108400 13300; + B 1200 200 115800 13300; + B 1400 200 101100 13100; + B 5600 200 108400 13100; + B 1400 200 115700 13100; + B 1600 200 101200 12900; + B 5200 200 108400 12900; + B 1600 200 115600 12900; + B 1800 200 101300 12700; + B 4800 200 108400 12700; + B 1800 200 115500 12700; + B 2000 200 101400 12500; + B 2000 200 115400 12500; + B 2200 200 101500 12300; + B 2200 200 115300 12300; + B 2400 200 101600 12100; + B 2400 200 115200 12100; + B 2600 200 101700 11900; + B 2600 200 115100 11900; + B 2800 200 101800 11700; + B 2800 200 115000 11700; + B 3000 200 101900 11500; + B 3000 200 114900 11500; + B 3200 200 102000 11300; + B 3200 200 114800 11300; + B 3400 200 102100 11100; + B 3400 200 114700 11100; + B 3600 200 102200 10900; + B 3600 200 114600 10900; + B 3800 4800 102300 8400; + B 3800 4800 114500 8400; + B 3600 200 102200 5900; + B 3600 200 114600 5900; + B 3400 200 102100 5700; + B 3400 200 114700 5700; + B 3200 200 102000 5500; + B 3200 200 114800 5500; + B 3000 200 101900 5300; + B 3000 200 114900 5300; + B 2800 200 101800 5100; + B 2800 200 115000 5100; + B 2600 200 101700 4900; + B 2600 200 115100 4900; + B 2400 200 101600 4700; + B 2400 200 115200 4700; + B 2200 200 101500 4500; + B 2200 200 115300 4500; + B 2000 200 101400 4300; + B 2000 200 115400 4300; + B 1800 200 101300 4100; + B 4800 200 108400 4100; + B 1800 200 115500 4100; + B 1600 200 101200 3900; + B 5200 200 108400 3900; + B 1600 200 115600 3900; + B 1400 200 101100 3700; + B 5600 200 108400 3700; + B 1400 200 115700 3700; + B 1200 200 101000 3500; + B 6000 200 108400 3500; + B 1200 200 115800 3500; + B 1000 200 100900 3300; + B 6400 200 108400 3300; + B 1000 200 115900 3300; + B 800 200 100800 3100; + B 6800 200 108400 3100; + B 800 200 116000 3100; + B 600 200 100700 2900; + B 7200 200 108400 2900; + B 600 200 116100 2900; + B 400 200 100600 2700; + B 7600 200 108400 2700; + B 400 200 116200 2700; + B 200 200 100500 2500; + B 8000 200 108400 2500; + B 200 200 116300 2500; + B 8400 200 108400 2300; + B 8800 200 108400 2100; + B 9200 200 108400 1900; + B 9600 200 108400 1700; + B 10000 200 108400 1500; + B 10400 200 108400 1300; + B 10800 200 108400 1100; + B 11200 200 108400 900; + B 11600 200 108400 700; + B 12000 200 108400 500; +L CCA; + B 12000 200 108400 16300; + B 11600 200 108400 16100; + B 11200 200 108400 15900; + B 10800 200 108400 15700; + B 10400 200 108400 15500; + B 10000 200 108400 15300; + B 9600 200 108400 15100; + B 9200 200 108400 14900; + B 8800 200 108400 14700; + B 8400 200 108400 14500; + B 200 200 100500 14300; + B 8000 200 108400 14300; + B 200 200 116300 14300; + B 400 200 100600 14100; + B 7600 200 108400 14100; + B 400 200 116200 14100; + B 600 200 100700 13900; + B 7200 200 108400 13900; + B 600 200 116100 13900; + B 800 200 100800 13700; + B 6800 200 108400 13700; + B 800 200 116000 13700; + B 1000 200 100900 13500; + B 6400 200 108400 13500; + B 1000 200 115900 13500; + B 1200 200 101000 13300; + B 6000 200 108400 13300; + B 1200 200 115800 13300; + B 1400 200 101100 13100; + B 5600 200 108400 13100; + B 1400 200 115700 13100; + B 1600 200 101200 12900; + B 5200 200 108400 12900; + B 1600 200 115600 12900; + B 1800 200 101300 12700; + B 4800 200 108400 12700; + B 1800 200 115500 12700; + B 2000 200 101400 12500; + B 2000 200 115400 12500; + B 2200 200 101500 12300; + B 2200 200 115300 12300; + B 2400 200 101600 12100; + B 2400 200 115200 12100; + B 2600 200 101700 11900; + B 2600 200 115100 11900; + B 2800 200 101800 11700; + B 2800 200 115000 11700; + B 3000 200 101900 11500; + B 3000 200 114900 11500; + B 3200 200 102000 11300; + B 3200 200 114800 11300; + B 3400 200 102100 11100; + B 3400 200 114700 11100; + B 3600 200 102200 10900; + B 3600 200 114600 10900; + B 3800 4800 102300 8400; + B 3800 4800 114500 8400; + B 3600 200 102200 5900; + B 3600 200 114600 5900; + B 3400 200 102100 5700; + B 3400 200 114700 5700; + B 3200 200 102000 5500; + B 3200 200 114800 5500; + B 3000 200 101900 5300; + B 3000 200 114900 5300; + B 2800 200 101800 5100; + B 2800 200 115000 5100; + B 2600 200 101700 4900; + B 2600 200 115100 4900; + B 2400 200 101600 4700; + B 2400 200 115200 4700; + B 2200 200 101500 4500; + B 2200 200 115300 4500; + B 2000 200 101400 4300; + B 2000 200 115400 4300; + B 1800 200 101300 4100; + B 4800 200 108400 4100; + B 1800 200 115500 4100; + B 1600 200 101200 3900; + B 5200 200 108400 3900; + B 1600 200 115600 3900; + B 1400 200 101100 3700; + B 5600 200 108400 3700; + B 1400 200 115700 3700; + B 1200 200 101000 3500; + B 6000 200 108400 3500; + B 1200 200 115800 3500; + B 1000 200 100900 3300; + B 6400 200 108400 3300; + B 1000 200 115900 3300; + B 800 200 100800 3100; + B 6800 200 108400 3100; + B 800 200 116000 3100; + B 600 200 100700 2900; + B 7200 200 108400 2900; + B 600 200 116100 2900; + B 400 200 100600 2700; + B 7600 200 108400 2700; + B 400 200 116200 2700; + B 200 200 100500 2500; + B 8000 200 108400 2500; + B 200 200 116300 2500; + B 8400 200 108400 2300; + B 8800 200 108400 2100; + B 9200 200 108400 1900; + B 9600 200 108400 1700; + B 10000 200 108400 1500; + B 10400 200 108400 1300; + B 10800 200 108400 1100; + B 11200 200 108400 900; + B 11600 200 108400 700; + B 12000 200 108400 500; +L CCP; + B 400 400 111000 11000; + B 400 400 111000 10000; + B 400 400 111000 6800; + B 400 400 111000 5800; +L CSP; + B 18800 1800 108400 16900; + B 1800 15200 99900 8400; + B 1800 15200 116900 8400; + B 18800 1800 108400 -100; +L COG; + B 12000 200 108400 16300; + B 11600 200 108400 16100; + B 11200 200 108400 15900; + B 10800 200 108400 15700; + B 10400 200 108400 15500; + B 10000 200 108400 15300; + B 9600 200 108400 15100; + B 9200 200 108400 14900; + B 8800 200 108400 14700; + B 8400 200 108400 14500; + B 200 200 100500 14300; + B 8000 200 108400 14300; + B 200 200 116300 14300; + B 400 200 100600 14100; + B 7600 200 108400 14100; + B 400 200 116200 14100; + B 600 200 100700 13900; + B 7200 200 108400 13900; + B 600 200 116100 13900; + B 800 200 100800 13700; + B 6800 200 108400 13700; + B 800 200 116000 13700; + B 1000 200 100900 13500; + B 6400 200 108400 13500; + B 1000 200 115900 13500; + B 1200 200 101000 13300; + B 6000 200 108400 13300; + B 1200 200 115800 13300; + B 1400 200 101100 13100; + B 5600 200 108400 13100; + B 1400 200 115700 13100; + B 1600 200 101200 12900; + B 5200 200 108400 12900; + B 1600 200 115600 12900; + B 1800 200 101300 12700; + B 4800 200 108400 12700; + B 1800 200 115500 12700; + B 2000 200 101400 12500; + B 2000 200 115400 12500; + B 2200 200 101500 12300; + B 2200 200 115300 12300; + B 2400 200 101600 12100; + B 2400 200 115200 12100; + B 2600 200 101700 11900; + B 2600 200 115100 11900; + B 2800 200 101800 11700; + B 2800 200 115000 11700; + B 3000 200 101900 11500; + B 3000 200 114900 11500; + B 3200 200 102000 11300; + B 3200 200 114800 11300; + B 3400 200 102100 11100; + B 3400 200 114700 11100; + B 3600 200 102200 10900; + B 3600 200 114600 10900; + B 3800 4800 102300 8400; + B 3800 4800 114500 8400; + B 3600 200 102200 5900; + B 3600 200 114600 5900; + B 3400 200 102100 5700; + B 3400 200 114700 5700; + B 3200 200 102000 5500; + B 3200 200 114800 5500; + B 3000 200 101900 5300; + B 3000 200 114900 5300; + B 2800 200 101800 5100; + B 2800 200 115000 5100; + B 2600 200 101700 4900; + B 2600 200 115100 4900; + B 2400 200 101600 4700; + B 2400 200 115200 4700; + B 2200 200 101500 4500; + B 2200 200 115300 4500; + B 2000 200 101400 4300; + B 2000 200 115400 4300; + B 1800 200 101300 4100; + B 4800 200 108400 4100; + B 1800 200 115500 4100; + B 1600 200 101200 3900; + B 5200 200 108400 3900; + B 1600 200 115600 3900; + B 1400 200 101100 3700; + B 5600 200 108400 3700; + B 1400 200 115700 3700; + B 1200 200 101000 3500; + B 6000 200 108400 3500; + B 1200 200 115800 3500; + B 1000 200 100900 3300; + B 6400 200 108400 3300; + B 1000 200 115900 3300; + B 800 200 100800 3100; + B 6800 200 108400 3100; + B 800 200 116000 3100; + B 600 200 100700 2900; + B 7200 200 108400 2900; + B 600 200 116100 2900; + B 400 200 100600 2700; + B 7600 200 108400 2700; + B 400 200 116200 2700; + B 200 200 100500 2500; + B 8000 200 108400 2500; + B 200 200 116300 2500; + B 8400 200 108400 2300; + B 8800 200 108400 2100; + B 9200 200 108400 1900; + B 9600 200 108400 1700; + B 10000 200 108400 1500; + B 10400 200 108400 1300; + B 10800 200 108400 1100; + B 11200 200 108400 900; + B 11600 200 108400 700; + B 12000 200 108400 500; +L COP; + B 12000 200 108400 16300; + B 11600 200 108400 16100; + B 11200 200 108400 15900; + B 10800 200 108400 15700; + B 10400 200 108400 15500; + B 10000 200 108400 15300; + B 9600 200 108400 15100; + B 9200 200 108400 14900; + B 8800 200 108400 14700; + B 8400 200 108400 14500; + B 200 200 100500 14300; + B 8000 200 108400 14300; + B 200 200 116300 14300; + B 400 200 100600 14100; + B 7600 200 108400 14100; + B 400 200 116200 14100; + B 600 200 100700 13900; + B 7200 200 108400 13900; + B 600 200 116100 13900; + B 800 200 100800 13700; + B 6800 200 108400 13700; + B 800 200 116000 13700; + B 1000 200 100900 13500; + B 6400 200 108400 13500; + B 1000 200 115900 13500; + B 1200 200 101000 13300; + B 6000 200 108400 13300; + B 1200 200 115800 13300; + B 1400 200 101100 13100; + B 5600 200 108400 13100; + B 1400 200 115700 13100; + B 1600 200 101200 12900; + B 5200 200 108400 12900; + B 1600 200 115600 12900; + B 1800 200 101300 12700; + B 4800 200 108400 12700; + B 1800 200 115500 12700; + B 2000 200 101400 12500; + B 2000 200 115400 12500; + B 2200 200 101500 12300; + B 2200 200 115300 12300; + B 2400 200 101600 12100; + B 2400 200 115200 12100; + B 2600 200 101700 11900; + B 2600 200 115100 11900; + B 2800 200 101800 11700; + B 2800 200 115000 11700; + B 3000 200 101900 11500; + B 3000 200 114900 11500; + B 3200 200 102000 11300; + B 3200 200 114800 11300; + B 3400 200 102100 11100; + B 3400 200 114700 11100; + B 3600 200 102200 10900; + B 3600 200 114600 10900; + B 3800 4800 102300 8400; + B 3800 4800 114500 8400; + B 3600 200 102200 5900; + B 3600 200 114600 5900; + B 3400 200 102100 5700; + B 3400 200 114700 5700; + B 3200 200 102000 5500; + B 3200 200 114800 5500; + B 3000 200 101900 5300; + B 3000 200 114900 5300; + B 2800 200 101800 5100; + B 2800 200 115000 5100; + B 2600 200 101700 4900; + B 2600 200 115100 4900; + B 2400 200 101600 4700; + B 2400 200 115200 4700; + B 2200 200 101500 4500; + B 2200 200 115300 4500; + B 2000 200 101400 4300; + B 2000 200 115400 4300; + B 1800 200 101300 4100; + B 4800 200 108400 4100; + B 1800 200 115500 4100; + B 1600 200 101200 3900; + B 5200 200 108400 3900; + B 1600 200 115600 3900; + B 1400 200 101100 3700; + B 5600 200 108400 3700; + B 1400 200 115700 3700; + B 1200 200 101000 3500; + B 6000 200 108400 3500; + B 1200 200 115800 3500; + B 1000 200 100900 3300; + B 6400 200 108400 3300; + B 1000 200 115900 3300; + B 800 200 100800 3100; + B 6800 200 108400 3100; + B 800 200 116000 3100; + B 600 200 100700 2900; + B 7200 200 108400 2900; + B 600 200 116100 2900; + B 400 200 100600 2700; + B 7600 200 108400 2700; + B 400 200 116200 2700; + B 200 200 100500 2500; + B 8000 200 108400 2500; + B 200 200 116300 2500; + B 8400 200 108400 2300; + B 8800 200 108400 2100; + B 9200 200 108400 1900; + B 9600 200 108400 1700; + B 10000 200 108400 1500; + B 10400 200 108400 1300; + B 10800 200 108400 1100; + B 11200 200 108400 900; + B 11600 200 108400 700; + B 12000 200 108400 500; +L CPS; + B 18000 1000 108400 16900; + B 1000 16000 99900 8400; + B 1000 16000 116900 8400; + B 18000 1000 108400 -100; +DF; +C 1; +End + diff --git a/scmos/examples/nist-mems-library/pixel-80x80.mag b/scmos/examples/nist-mems-library/pixel-80x80.mag new file mode 100644 index 00000000..3589628f --- /dev/null +++ b/scmos/examples/nist-mems-library/pixel-80x80.mag @@ -0,0 +1,241 @@ +magic +tech scmos +timestamp 760840526 +<< polysilicon >> +rect 528 56 534 58 +rect 528 28 530 56 +rect 532 45 534 56 +rect 536 56 542 58 +rect 536 45 538 56 +rect 532 43 538 45 +rect 540 45 542 56 +rect 544 56 550 58 +rect 544 45 546 56 +rect 540 43 546 45 +rect 548 45 550 56 +rect 552 57 558 58 +rect 552 53 553 57 +rect 557 53 558 57 +rect 552 52 558 53 +rect 552 48 553 52 +rect 557 48 558 52 +rect 552 47 558 48 +rect 553 45 557 47 +rect 548 43 557 45 +rect 532 39 538 41 +rect 532 28 534 39 +rect 528 26 534 28 +rect 536 28 538 39 +rect 540 39 546 41 +rect 540 28 542 39 +rect 536 26 542 28 +rect 544 28 546 39 +rect 548 39 557 41 +rect 548 28 550 39 +rect 553 37 557 39 +rect 544 26 550 28 +rect 552 36 558 37 +rect 552 32 553 36 +rect 557 32 558 36 +rect 552 31 558 32 +rect 552 27 553 31 +rect 557 27 558 31 +rect 552 26 558 27 +<< metal1 >> +rect 576 81 582 82 +rect 576 79 577 81 +rect 575 78 577 79 +rect 574 77 577 78 +rect 581 77 582 81 +rect 573 76 582 77 +rect 572 75 579 76 +rect 571 74 578 75 +rect 570 73 577 74 +rect 569 72 576 73 +rect 568 71 575 72 +rect 567 70 574 71 +rect 566 69 573 70 +rect 565 68 572 69 +rect 564 67 571 68 +rect 563 66 570 67 +rect 562 65 569 66 +rect 561 64 568 65 +rect 560 63 567 64 +rect 559 62 566 63 +rect 558 61 565 62 +rect 557 60 564 61 +rect 556 59 563 60 +rect 555 58 562 59 +rect 552 57 561 58 +rect 552 53 553 57 +rect 557 56 560 57 +rect 557 55 559 56 +rect 557 53 558 55 +rect 552 52 558 53 +rect 552 48 553 52 +rect 557 48 558 52 +rect 552 47 558 48 +rect 552 36 558 37 +rect 552 32 553 36 +rect 557 32 558 36 +rect 552 31 558 32 +rect 552 27 553 31 +rect 557 29 558 31 +rect 557 28 559 29 +rect 557 27 560 28 +rect 552 26 561 27 +rect 555 25 562 26 +rect 556 24 563 25 +rect 557 23 564 24 +rect 558 22 565 23 +rect 559 21 566 22 +rect 560 20 567 21 +rect 561 19 568 20 +rect 562 18 569 19 +rect 563 17 570 18 +rect 564 16 571 17 +rect 565 15 572 16 +rect 566 14 573 15 +rect 567 13 574 14 +rect 568 12 575 13 +rect 569 11 576 12 +rect 570 10 577 11 +rect 571 9 578 10 +rect 572 8 579 9 +rect 573 7 580 8 +rect 574 6 581 7 +rect 575 5 582 6 +rect 576 4 582 5 +rect 577 3 582 4 +rect 578 2 582 3 +<< metal2 >> +rect 576 81 582 82 +rect 576 77 577 81 +rect 581 77 582 81 +rect 576 76 582 77 +<< polycontact >> +rect 553 53 557 57 +rect 553 48 557 52 +rect 553 32 557 36 +rect 553 27 557 31 +<< m2contact >> +rect 577 77 581 81 +<< substrateopen >> +rect 512 81 572 82 +rect 513 80 571 81 +rect 514 79 570 80 +rect 515 78 569 79 +rect 516 77 568 78 +rect 517 76 567 77 +rect 518 75 566 76 +rect 519 74 565 75 +rect 520 73 564 74 +rect 521 72 563 73 +rect 502 71 503 72 +rect 522 71 562 72 +rect 581 71 582 72 +rect 502 70 504 71 +rect 523 70 561 71 +rect 580 70 582 71 +rect 502 69 505 70 +rect 524 69 560 70 +rect 579 69 582 70 +rect 502 68 506 69 +rect 525 68 559 69 +rect 578 68 582 69 +rect 502 67 507 68 +rect 526 67 558 68 +rect 577 67 582 68 +rect 502 66 508 67 +rect 527 66 557 67 +rect 576 66 582 67 +rect 502 65 509 66 +rect 528 65 556 66 +rect 575 65 582 66 +rect 502 64 510 65 +rect 529 64 555 65 +rect 574 64 582 65 +rect 502 63 511 64 +rect 530 63 554 64 +rect 573 63 582 64 +rect 502 62 512 63 +rect 572 62 582 63 +rect 502 61 513 62 +rect 571 61 582 62 +rect 502 60 514 61 +rect 570 60 582 61 +rect 502 59 515 60 +rect 569 59 582 60 +rect 502 58 516 59 +rect 568 58 582 59 +rect 502 57 517 58 +rect 567 57 582 58 +rect 502 56 518 57 +rect 566 56 582 57 +rect 502 55 519 56 +rect 565 55 582 56 +rect 502 54 520 55 +rect 564 54 582 55 +rect 502 30 521 54 +rect 563 30 582 54 +rect 502 29 520 30 +rect 564 29 582 30 +rect 502 28 519 29 +rect 565 28 582 29 +rect 502 27 518 28 +rect 566 27 582 28 +rect 502 26 517 27 +rect 567 26 582 27 +rect 502 25 516 26 +rect 568 25 582 26 +rect 502 24 515 25 +rect 569 24 582 25 +rect 502 23 514 24 +rect 570 23 582 24 +rect 502 22 513 23 +rect 571 22 582 23 +rect 502 21 512 22 +rect 572 21 582 22 +rect 502 20 511 21 +rect 530 20 554 21 +rect 573 20 582 21 +rect 502 19 510 20 +rect 529 19 555 20 +rect 574 19 582 20 +rect 502 18 509 19 +rect 528 18 556 19 +rect 575 18 582 19 +rect 502 17 508 18 +rect 527 17 557 18 +rect 576 17 582 18 +rect 502 16 507 17 +rect 526 16 558 17 +rect 577 16 582 17 +rect 502 15 506 16 +rect 525 15 559 16 +rect 578 15 582 16 +rect 502 14 505 15 +rect 524 14 560 15 +rect 579 14 582 15 +rect 502 13 504 14 +rect 523 13 561 14 +rect 580 13 582 14 +rect 502 12 503 13 +rect 522 12 562 13 +rect 581 12 582 13 +rect 521 11 563 12 +rect 520 10 564 11 +rect 519 9 565 10 +rect 518 8 566 9 +rect 517 7 567 8 +rect 516 6 568 7 +rect 515 5 569 6 +rect 514 4 570 5 +rect 513 3 571 4 +rect 512 2 572 3 +<< pdiffusionstop >> +rect 497 82 587 87 +rect 497 2 502 82 +rect 582 2 587 82 +rect 497 -3 587 2 +<< end >> diff --git a/scmos/examples/nist-mems-library/thermal-actuator.cif b/scmos/examples/nist-mems-library/thermal-actuator.cif new file mode 100644 index 00000000..21a204c3 --- /dev/null +++ b/scmos/examples/nist-mems-library/thermal-actuator.cif @@ -0,0 +1,39 @@ +DS 1 1 2; +9 thermal-actuator; +L CMF; + B 4000 35000 9000 21500; + B 11000 4000 5500 2000; +L CPG; + B 4000 35000 9000 21500; + B 11000 4000 12500 2000; +L CAA; + B 14000 4000 9000 42000; + B 4000 32000 4000 24000; + B 4000 32000 14000 24000; +L CVA; + B 14000 4000 9000 42000; + B 4000 32000 4000 24000; + B 4000 32000 14000 24000; +L CCA; + B 14000 4000 9000 42000; + B 4000 32000 4000 24000; + B 4000 32000 14000 24000; +L CCP; + B 400 400 8600 38400; + B 400 400 9400 38400; + B 400 400 8600 37600; + B 400 400 9400 37600; +L COG; + B 14000 4000 9000 42000; + B 4000 32000 4000 24000; + B 4000 32000 14000 24000; +L COP; + B 14000 4000 9000 42000; + B 4000 32000 4000 24000; + B 4000 32000 14000 24000; +94 Vin 2000 2000; +94 Vout 16000 2000; +DF; +C 1; +End + diff --git a/scmos/examples/nist-mems-library/thermal-actuator.mag b/scmos/examples/nist-mems-library/thermal-actuator.mag new file mode 100644 index 00000000..1be694d8 --- /dev/null +++ b/scmos/examples/nist-mems-library/thermal-actuator.mag @@ -0,0 +1,25 @@ +magic +tech scmos +timestamp 760840666 +<< polysilicon >> +rect 35 194 55 195 +rect 35 186 41 194 +rect 49 186 55 194 +rect 35 20 55 186 +rect 35 0 90 20 +<< metal1 >> +rect 35 194 55 195 +rect 35 186 41 194 +rect 49 186 55 194 +rect 35 20 55 186 +rect 0 0 55 20 +<< polycontact >> +rect 41 186 49 194 +<< substrateopen >> +rect 10 200 80 220 +rect 10 40 30 200 +rect 60 40 80 200 +<< labels >> +rlabel metal1 10 10 10 10 6 Vin +rlabel polysilicon 80 10 80 10 6 Vout +<< end >> diff --git a/scmos/examples/nist-mems-library/thermal-converter.cif b/scmos/examples/nist-mems-library/thermal-converter.cif new file mode 100644 index 00000000..00b17a3b --- /dev/null +++ b/scmos/examples/nist-mems-library/thermal-converter.cif @@ -0,0 +1,487 @@ +DS 1 1 2; +9 thermal-converter; +L CMF; + B 1200 1200 2000 16400; + B 1200 1200 3800 16400; + B 1200 1200 5600 16400; + B 1200 1200 7400 16400; + B 1200 1200 9200 16400; + B 1200 1200 11000 16400; + B 600 600 2300 15500; + B 600 600 4100 15500; + B 600 600 5900 15500; + B 600 600 7700 15500; + B 600 600 9500 15500; + B 1200 1200 800 14600; + B 1200 600 2600 14900; + B 1200 600 4400 14900; + B 1200 600 6200 14900; + B 1200 600 8000 14900; + B 1200 600 9800 14900; + B 600 600 2900 14300; + B 600 600 4700 14300; + B 600 600 6500 14300; + B 600 600 8300 14300; + B 1200 600 1400 13700; + B 1200 600 3200 13700; + B 1200 600 5000 13700; + B 1200 600 6800 13700; + B 1200 600 8600 13700; + B 600 600 1700 13100; + B 600 600 3500 13100; + B 600 600 5300 13100; + B 600 600 7100 13100; + B 1200 600 2000 12500; + B 1200 600 3800 12500; + B 1200 600 5600 12500; + B 1200 600 7400 12500; + B 600 600 2300 11900; + B 600 600 4100 11900; + B 600 600 5900 11900; + B 1200 600 2600 11300; + B 1200 600 4400 11300; + B 1200 600 6200 11300; + B 600 600 2900 10700; + B 600 600 4700 10700; + B 1200 600 3200 10100; + B 1200 600 5000 10100; + B 600 600 3500 9500; + B 1200 600 3800 8900; + B 600 20400 4100 -1600; + B 1200 600 3800 -12100; + B 600 600 3500 -12700; + B 600 22800 5300 -1600; + B 1200 600 3200 -13300; + B 1200 600 5000 -13300; + B 600 600 2900 -13900; + B 600 600 4700 -13900; + B 600 25200 6500 -1600; + B 1200 600 2600 -14500; + B 1200 600 4400 -14500; + B 1200 600 6200 -14500; + B 600 600 2300 -15100; + B 600 600 4100 -15100; + B 600 600 5900 -15100; + B 600 27600 7700 -1600; + B 1800 600 1700 -15700; + B 1200 600 3800 -15700; + B 1200 600 5600 -15700; + B 1200 600 7400 -15700; + B 600 6000 1100 -19000; + B 600 600 3500 -16300; + B 600 600 5300 -16300; + B 600 600 7100 -16300; + B 600 30000 8900 -1600; + B 1800 600 2900 -16900; + B 1200 600 5000 -16900; + B 1200 600 6800 -16900; + B 1200 600 8600 -16900; + B 600 4800 2300 -19600; + B 600 600 4700 -17500; + B 600 600 6500 -17500; + B 600 600 8300 -17500; + B 600 32400 10100 -1600; + B 1200 600 4400 -18100; + B 1200 600 6200 -18100; + B 1200 600 8000 -18100; + B 1200 600 9800 -18100; + B 600 600 4100 -18700; + B 600 600 5900 -18700; + B 600 600 7700 -18700; + B 600 600 9500 -18700; + B 600 34800 11300 -1600; + B 1200 1200 3800 -19600; + B 1200 1200 5600 -19600; + B 1200 1200 7400 -19600; + B 1200 1200 9200 -19600; + B 1200 1200 11000 -19600; + B 1200 1200 12800 16400; + B 1200 1200 14600 16400; + B 1200 1200 16400 16400; + B 1200 1200 18200 16400; + B 1200 1200 20000 16400; + B 1200 1200 21800 16400; + B 600 34800 12500 -1600; + B 600 600 14300 15500; + B 600 600 16100 15500; + B 600 600 17900 15500; + B 600 600 19700 15500; + B 600 600 21500 15500; + B 1200 600 14000 14900; + B 1200 600 15800 14900; + B 1200 600 17600 14900; + B 1200 600 19400 14900; + B 1200 600 21200 14900; + B 600 32400 13700 -1600; + B 600 600 15500 14300; + B 600 600 17300 14300; + B 600 600 19100 14300; + B 600 600 20900 14300; + B 1200 1200 23000 14600; + B 1200 600 15200 13700; + B 1200 600 17000 13700; + B 1200 600 18800 13700; + B 1200 600 20600 13700; + B 1200 600 22400 13700; + B 600 30000 14900 -1600; + B 600 600 16700 13100; + B 600 600 18500 13100; + B 600 600 20300 13100; + B 600 600 22100 13100; + B 1200 600 16400 12500; + B 1200 600 18200 12500; + B 1200 600 20000 12500; + B 1200 600 21800 12500; + B 600 27600 16100 -1600; + B 600 600 17900 11900; + B 600 600 19700 11900; + B 600 600 21500 11900; + B 1200 600 17600 11300; + B 1200 600 19400 11300; + B 1200 600 21200 11300; + B 600 25200 17300 -1600; + B 600 600 19100 10700; + B 600 600 20900 10700; + B 1200 600 18800 10100; + B 1200 600 20600 10100; + B 600 22800 18500 -1600; + B 600 600 20300 9500; + B 1200 600 20000 8900; + B 600 20400 19700 -1600; + B 1200 600 20000 -12100; + B 600 600 20300 -12700; + B 1200 600 18800 -13300; + B 1200 600 20600 -13300; + B 600 600 19100 -13900; + B 600 600 20900 -13900; + B 1200 600 17600 -14500; + B 1200 600 19400 -14500; + B 1200 600 21200 -14500; + B 600 600 17900 -15100; + B 600 600 19700 -15100; + B 600 600 21500 -15100; + B 1200 600 16400 -15700; + B 1200 600 18200 -15700; + B 1200 600 20000 -15700; + B 1200 600 21800 -15700; + B 600 600 16700 -16300; + B 600 600 18500 -16300; + B 600 600 20300 -16300; + B 600 600 22100 -16300; + B 1200 600 15200 -16900; + B 1200 600 17000 -16900; + B 1200 600 18800 -16900; + B 1200 600 20600 -16900; + B 1200 600 22400 -16900; + B 600 600 15500 -17500; + B 600 600 17300 -17500; + B 600 600 19100 -17500; + B 600 600 20900 -17500; + B 600 400 22700 -17400; + B 1200 600 14000 -18100; + B 1200 600 15800 -18100; + B 1200 600 17600 -18100; + B 1200 600 19400 -18100; + B 1200 600 21200 -18100; + B 3000 600 23900 -17900; + B 600 600 14300 -18700; + B 600 600 16100 -18700; + B 600 600 17900 -18700; + B 600 600 19700 -18700; + B 600 600 21500 -18700; + B 1200 1200 12800 -19600; + B 1200 1200 14600 -19600; + B 1200 1200 16400 -19600; + B 1200 1200 18200 -19600; + B 1200 1200 20000 -19600; + B 1200 1200 21800 -19600; + B 1200 1200 23600 -19600; + B 600 1800 23300 -21100; + B 600 3800 25100 -20100; +L CPG; + B 23400 800 11900 17800; + B 800 2200 600 16300; + B 1200 1200 2000 16400; + B 1200 1200 3800 16400; + B 1200 1200 5600 16400; + B 1200 1200 7400 16400; + B 1200 1200 9200 16400; + B 1200 1200 11000 16400; + B 600 600 2300 15500; + B 600 600 4100 15500; + B 600 600 5900 15500; + B 600 600 7700 15500; + B 600 600 9500 15500; + B 1200 1200 800 14600; + B 1200 600 2600 14900; + B 1200 600 4400 14900; + B 1200 600 6200 14900; + B 1200 600 8000 14900; + B 1200 600 9800 14900; + B 600 600 2900 14300; + B 600 600 4700 14300; + B 600 600 6500 14300; + B 600 600 8300 14300; + B 1200 600 3200 13700; + B 1200 600 5000 13700; + B 1200 600 6800 13700; + B 1200 600 8600 13700; + B 600 600 3500 13100; + B 600 600 5300 13100; + B 600 600 7100 13100; + B 1200 600 3800 12500; + B 1200 600 5600 12500; + B 1200 600 7400 12500; + B 600 600 4100 11900; + B 600 600 5900 11900; + B 1200 600 4400 11300; + B 1200 600 6200 11300; + B 600 600 4700 10700; + B 1200 600 5000 10100; + B 600 22800 5300 -1600; + B 1200 600 5000 -13300; + B 600 600 4700 -13900; + B 600 25200 6500 -1600; + B 1200 600 4400 -14500; + B 1200 600 6200 -14500; + B 600 600 4100 -15100; + B 600 600 5900 -15100; + B 600 27600 7700 -1600; + B 1200 600 3800 -15700; + B 1200 600 5600 -15700; + B 1200 600 7400 -15700; + B 600 3000 3500 -17500; + B 600 3000 5300 -17500; + B 600 3000 7100 -17500; + B 600 32400 8900 -2800; + B 600 32400 10100 -1600; + B 600 32400 11300 -400; + B 1200 1200 12800 16400; + B 1200 1200 14600 16400; + B 1200 1200 16400 16400; + B 1200 1200 18200 16400; + B 1200 1200 20000 16400; + B 1200 1200 21800 16400; + B 600 31200 12500 200; + B 600 600 14300 15500; + B 600 600 16100 15500; + B 600 600 17900 15500; + B 600 600 19700 15500; + B 600 600 21500 15500; + B 800 2200 23200 16300; + B 1200 600 14000 14900; + B 1200 600 15800 14900; + B 1200 600 17600 14900; + B 1200 600 19400 14900; + B 1200 600 21200 14900; + B 600 28800 13700 200; + B 600 600 15500 14300; + B 600 600 17300 14300; + B 600 600 19100 14300; + B 600 600 20900 14300; + B 1200 1200 23000 14600; + B 1200 600 15200 13700; + B 1200 600 17000 13700; + B 1200 600 18800 13700; + B 1200 600 20600 13700; + B 600 26400 14900 200; + B 600 600 16700 13100; + B 600 600 18500 13100; + B 600 600 20300 13100; + B 1200 600 16400 12500; + B 1200 600 18200 12500; + B 1200 600 20000 12500; + B 600 24000 16100 200; + B 600 600 17900 11900; + B 600 600 19700 11900; + B 1200 600 17600 11300; + B 1200 600 19400 11300; + B 600 21600 17300 200; + B 600 600 19100 10700; + B 1200 600 18800 10100; + B 600 19200 18500 200; + B 1800 600 19100 -9700; + B 1800 600 17900 -10900; + B 1800 600 16700 -12100; + B 1800 600 15500 -13300; + B 1800 600 14300 -14500; + B 1800 600 13100 -15700; + B 1800 600 11900 -16900; + B 1200 600 10400 -18100; + B 600 600 10700 -18700; + B 600 1800 12500 -18100; + B 600 1800 13700 -16900; + B 600 1800 14900 -15700; + B 600 1800 16100 -14500; + B 600 1800 17300 -13300; + B 600 1800 18500 -12100; + B 600 1800 19700 -10900; + B 1200 600 20000 -12100; + B 600 600 20300 -12700; + B 1200 600 18800 -13300; + B 1200 600 20600 -13300; + B 600 600 19100 -13900; + B 600 600 20900 -13900; + B 1200 600 17600 -14500; + B 1200 600 19400 -14500; + B 1200 600 21200 -14500; + B 600 600 17900 -15100; + B 600 600 19700 -15100; + B 600 600 21500 -15100; + B 1200 600 16400 -15700; + B 1200 600 18200 -15700; + B 1200 600 20000 -15700; + B 1200 600 21800 -15700; + B 600 600 16700 -16300; + B 600 600 18500 -16300; + B 600 600 20300 -16300; + B 600 600 22100 -16300; + B 1200 600 15200 -16900; + B 1200 600 17000 -16900; + B 1200 600 18800 -16900; + B 1200 600 20600 -16900; + B 1200 600 22400 -16900; + B 600 600 15500 -17500; + B 600 600 17300 -17500; + B 600 600 19100 -17500; + B 600 600 20900 -17500; + B 600 400 22700 -17400; + B 1200 600 14000 -18100; + B 1200 600 15800 -18100; + B 1200 600 17600 -18100; + B 1200 600 19400 -18100; + B 1200 600 21200 -18100; + B 1200 600 23000 -17900; + B 600 600 14300 -18700; + B 600 600 16100 -18700; + B 600 600 17900 -18700; + B 600 600 19700 -18700; + B 600 600 21500 -18700; + B 600 800 23300 -18600; + B 1200 1200 3800 -19600; + B 1200 1200 5600 -19600; + B 1200 1200 7400 -19600; + B 1200 1200 9200 -19600; + B 1200 1200 11000 -19600; + B 1200 1200 12800 -19600; + B 1200 1200 14600 -19600; + B 1200 1200 16400 -19600; + B 1200 1200 18200 -19600; + B 1200 1200 20000 -19600; + B 1200 1200 21800 -19600; + B 1200 1200 23600 -19600; +L CAA; + B 30000 3200 11800 20400; + B 2600 5400 -1900 16100; + B 2600 5400 25500 16100; + B 3200 600 -1600 13100; + B 3200 600 25200 13100; + B 3800 1200 -1300 12200; + B 3800 1200 24900 12200; + B 4400 1200 -1000 11000; + B 4400 1200 24600 11000; + B 5000 1200 -700 9800; + B 5000 1200 24300 9800; + B 5600 1200 -400 8600; + B 5600 1200 24000 8600; + B 6400 10000 0 3000; + B 6400 10000 23600 3000; +L CVA; + B 30000 3200 11800 20400; + B 2600 5400 -1900 16100; + B 2600 5400 25500 16100; + B 3200 600 -1600 13100; + B 3200 600 25200 13100; + B 3800 1200 -1300 12200; + B 3800 1200 24900 12200; + B 4400 1200 -1000 11000; + B 4400 1200 24600 11000; + B 5000 1200 -700 9800; + B 5000 1200 24300 9800; + B 5600 1200 -400 8600; + B 5600 1200 24000 8600; + B 6400 10000 0 3000; + B 6400 10000 23600 3000; +L CCA; + B 30000 3200 11800 20400; + B 2600 5400 -1900 16100; + B 2600 5400 25500 16100; + B 3200 600 -1600 13100; + B 3200 600 25200 13100; + B 3800 1200 -1300 12200; + B 3800 1200 24900 12200; + B 4400 1200 -1000 11000; + B 4400 1200 24600 11000; + B 5000 1200 -700 9800; + B 5000 1200 24300 9800; + B 5600 1200 -400 8600; + B 5600 1200 24000 8600; + B 6400 10000 0 3000; + B 6400 10000 23600 3000; +L CCP; + B 400 400 2000 16400; + B 400 400 3800 16400; + B 400 400 5600 16400; + B 400 400 7400 16400; + B 400 400 9200 16400; + B 400 400 11000 16400; + B 400 400 12800 16400; + B 400 400 14600 16400; + B 400 400 16400 16400; + B 400 400 18200 16400; + B 400 400 20000 16400; + B 400 400 21800 16400; + B 400 400 800 14600; + B 400 400 23000 14600; + B 400 400 3800 -19600; + B 400 400 5600 -19600; + B 400 400 7400 -19600; + B 400 400 9200 -19600; + B 400 400 11000 -19600; + B 400 400 12800 -19600; + B 400 400 14600 -19600; + B 400 400 16400 -19600; + B 400 400 18200 -19600; + B 400 400 20000 -19600; + B 400 400 21800 -19600; + B 400 400 23600 -19600; +L COG; + B 30000 3200 11800 20400; + B 2600 5400 -1900 16100; + B 2600 5400 25500 16100; + B 3200 600 -1600 13100; + B 3200 600 25200 13100; + B 3800 1200 -1300 12200; + B 3800 1200 24900 12200; + B 4400 1200 -1000 11000; + B 4400 1200 24600 11000; + B 5000 1200 -700 9800; + B 5000 1200 24300 9800; + B 5600 1200 -400 8600; + B 5600 1200 24000 8600; + B 6400 10000 0 3000; + B 6400 10000 23600 3000; +L COP; + B 30000 3200 11800 20400; + B 2600 5400 -1900 16100; + B 2600 5400 25500 16100; + B 3200 600 -1600 13100; + B 3200 600 25200 13100; + B 3800 1200 -1300 12200; + B 3800 1200 24900 12200; + B 4400 1200 -1000 11000; + B 4400 1200 24600 11000; + B 5000 1200 -700 9800; + B 5000 1200 24300 9800; + B 5600 1200 -400 8600; + B 5600 1200 24000 8600; + B 6400 10000 0 3000; + B 6400 10000 23600 3000; +94 heater2 25100 -21700; +94 heater1 1100 -21700; +94 Vmeas1 2300 -21700; +94 Vmeas2 23300 -21700; +DF; +C 1; +End + diff --git a/scmos/examples/nist-mems-library/thermal-converter.mag b/scmos/examples/nist-mems-library/thermal-converter.mag new file mode 100644 index 00000000..3157fd41 --- /dev/null +++ b/scmos/examples/nist-mems-library/thermal-converter.mag @@ -0,0 +1,578 @@ +magic +tech scmos +timestamp 760840748 +<< polysilicon >> +rect 1 87 118 91 +rect 1 76 5 87 +rect 7 84 13 85 +rect 7 80 8 84 +rect 12 80 13 84 +rect 7 79 13 80 +rect 16 84 22 85 +rect 16 80 17 84 +rect 21 80 22 84 +rect 16 79 22 80 +rect 25 84 31 85 +rect 25 80 26 84 +rect 30 80 31 84 +rect 25 79 31 80 +rect 34 84 40 85 +rect 34 80 35 84 +rect 39 80 40 84 +rect 34 79 40 80 +rect 43 84 49 85 +rect 43 80 44 84 +rect 48 80 49 84 +rect 43 79 49 80 +rect 52 84 58 85 +rect 52 80 53 84 +rect 57 80 58 84 +rect 52 79 58 80 +rect 10 76 13 79 +rect 19 76 22 79 +rect 28 76 31 79 +rect 37 76 40 79 +rect 46 76 49 79 +rect 1 75 7 76 +rect 1 71 2 75 +rect 6 71 7 75 +rect 10 73 16 76 +rect 19 73 25 76 +rect 28 73 34 76 +rect 37 73 43 76 +rect 46 73 52 76 +rect 1 70 7 71 +rect 13 70 16 73 +rect 22 70 25 73 +rect 31 70 34 73 +rect 40 70 43 73 +rect 13 67 19 70 +rect 22 67 28 70 +rect 31 67 37 70 +rect 40 67 46 70 +rect 16 64 19 67 +rect 25 64 28 67 +rect 34 64 37 67 +rect 16 61 22 64 +rect 25 61 31 64 +rect 34 61 40 64 +rect 19 58 22 61 +rect 28 58 31 61 +rect 19 55 25 58 +rect 28 55 34 58 +rect 22 52 25 55 +rect 22 49 28 52 +rect 25 -65 28 49 +rect 22 -68 28 -65 +rect 22 -71 25 -68 +rect 31 -71 34 55 +rect 19 -74 25 -71 +rect 28 -74 34 -71 +rect 19 -77 22 -74 +rect 28 -77 31 -74 +rect 37 -77 40 61 +rect 16 -80 22 -77 +rect 25 -80 31 -77 +rect 34 -80 40 -77 +rect 16 -95 19 -80 +rect 25 -95 28 -80 +rect 34 -95 37 -80 +rect 43 -95 46 67 +rect 49 -89 52 73 +rect 55 -83 58 79 +rect 61 84 67 85 +rect 61 80 62 84 +rect 66 80 67 84 +rect 61 79 67 80 +rect 70 84 76 85 +rect 70 80 71 84 +rect 75 80 76 84 +rect 70 79 76 80 +rect 79 84 85 85 +rect 79 80 80 84 +rect 84 80 85 84 +rect 79 79 85 80 +rect 88 84 94 85 +rect 88 80 89 84 +rect 93 80 94 84 +rect 88 79 94 80 +rect 97 84 103 85 +rect 97 80 98 84 +rect 102 80 103 84 +rect 97 79 103 80 +rect 106 84 112 85 +rect 106 80 107 84 +rect 111 80 112 84 +rect 106 79 112 80 +rect 61 -77 64 79 +rect 70 76 73 79 +rect 79 76 82 79 +rect 88 76 91 79 +rect 97 76 100 79 +rect 106 76 109 79 +rect 114 76 118 87 +rect 67 73 73 76 +rect 76 73 82 76 +rect 85 73 91 76 +rect 94 73 100 76 +rect 103 73 109 76 +rect 112 75 118 76 +rect 67 -71 70 73 +rect 76 70 79 73 +rect 85 70 88 73 +rect 94 70 97 73 +rect 103 70 106 73 +rect 112 71 113 75 +rect 117 71 118 75 +rect 112 70 118 71 +rect 73 67 79 70 +rect 82 67 88 70 +rect 91 67 97 70 +rect 100 67 106 70 +rect 73 -65 76 67 +rect 82 64 85 67 +rect 91 64 94 67 +rect 100 64 103 67 +rect 79 61 85 64 +rect 88 61 94 64 +rect 97 61 103 64 +rect 79 -59 82 61 +rect 88 58 91 61 +rect 97 58 100 61 +rect 85 55 91 58 +rect 94 55 100 58 +rect 85 -53 88 55 +rect 94 52 97 55 +rect 91 49 97 52 +rect 91 -47 94 49 +rect 91 -50 100 -47 +rect 85 -56 94 -53 +rect 79 -62 88 -59 +rect 73 -68 82 -65 +rect 67 -74 76 -71 +rect 61 -80 70 -77 +rect 55 -86 64 -83 +rect 49 -92 55 -89 +rect 52 -95 55 -92 +rect 61 -95 64 -86 +rect 67 -89 70 -80 +rect 73 -83 76 -74 +rect 79 -77 82 -68 +rect 85 -71 88 -62 +rect 91 -65 94 -56 +rect 97 -59 100 -50 +rect 97 -62 103 -59 +rect 100 -65 103 -62 +rect 91 -68 97 -65 +rect 100 -68 106 -65 +rect 94 -71 97 -68 +rect 103 -71 106 -68 +rect 85 -74 91 -71 +rect 94 -74 100 -71 +rect 103 -74 109 -71 +rect 88 -77 91 -74 +rect 97 -77 100 -74 +rect 106 -77 109 -74 +rect 79 -80 85 -77 +rect 88 -80 94 -77 +rect 97 -80 103 -77 +rect 106 -80 112 -77 +rect 82 -83 85 -80 +rect 91 -83 94 -80 +rect 100 -83 103 -80 +rect 109 -83 112 -80 +rect 73 -86 79 -83 +rect 82 -86 88 -83 +rect 91 -86 97 -83 +rect 100 -86 106 -83 +rect 109 -86 115 -83 +rect 76 -89 79 -86 +rect 85 -89 88 -86 +rect 94 -89 97 -86 +rect 103 -89 106 -86 +rect 112 -88 115 -86 +rect 67 -92 73 -89 +rect 76 -92 82 -89 +rect 85 -92 91 -89 +rect 94 -92 100 -89 +rect 103 -92 109 -89 +rect 112 -91 118 -88 +rect 70 -95 73 -92 +rect 79 -95 82 -92 +rect 88 -95 91 -92 +rect 97 -95 100 -92 +rect 106 -95 109 -92 +rect 115 -95 118 -91 +rect 16 -96 22 -95 +rect 16 -100 17 -96 +rect 21 -100 22 -96 +rect 16 -101 22 -100 +rect 25 -96 31 -95 +rect 25 -100 26 -96 +rect 30 -100 31 -96 +rect 25 -101 31 -100 +rect 34 -96 40 -95 +rect 34 -100 35 -96 +rect 39 -100 40 -96 +rect 34 -101 40 -100 +rect 43 -96 49 -95 +rect 43 -100 44 -96 +rect 48 -100 49 -96 +rect 43 -101 49 -100 +rect 52 -96 58 -95 +rect 52 -100 53 -96 +rect 57 -100 58 -96 +rect 52 -101 58 -100 +rect 61 -96 67 -95 +rect 61 -100 62 -96 +rect 66 -100 67 -96 +rect 61 -101 67 -100 +rect 70 -96 76 -95 +rect 70 -100 71 -96 +rect 75 -100 76 -96 +rect 70 -101 76 -100 +rect 79 -96 85 -95 +rect 79 -100 80 -96 +rect 84 -100 85 -96 +rect 79 -101 85 -100 +rect 88 -96 94 -95 +rect 88 -100 89 -96 +rect 93 -100 94 -96 +rect 88 -101 94 -100 +rect 97 -96 103 -95 +rect 97 -100 98 -96 +rect 102 -100 103 -96 +rect 97 -101 103 -100 +rect 106 -96 112 -95 +rect 106 -100 107 -96 +rect 111 -100 112 -96 +rect 106 -101 112 -100 +rect 115 -96 121 -95 +rect 115 -100 116 -96 +rect 120 -100 121 -96 +rect 115 -101 121 -100 +<< metal1 >> +rect 7 84 13 85 +rect 7 80 8 84 +rect 12 80 13 84 +rect 7 79 13 80 +rect 16 84 22 85 +rect 16 80 17 84 +rect 21 80 22 84 +rect 16 79 22 80 +rect 25 84 31 85 +rect 25 80 26 84 +rect 30 80 31 84 +rect 25 79 31 80 +rect 34 84 40 85 +rect 34 80 35 84 +rect 39 80 40 84 +rect 34 79 40 80 +rect 43 84 49 85 +rect 43 80 44 84 +rect 48 80 49 84 +rect 43 79 49 80 +rect 52 84 58 85 +rect 52 80 53 84 +rect 57 80 58 84 +rect 52 79 58 80 +rect 10 76 13 79 +rect 19 76 22 79 +rect 28 76 31 79 +rect 37 76 40 79 +rect 46 76 49 79 +rect 1 75 7 76 +rect 1 71 2 75 +rect 6 71 7 75 +rect 10 73 16 76 +rect 19 73 25 76 +rect 28 73 34 76 +rect 37 73 43 76 +rect 46 73 52 76 +rect 1 70 7 71 +rect 13 70 16 73 +rect 22 70 25 73 +rect 31 70 34 73 +rect 40 70 43 73 +rect 4 67 10 70 +rect 13 67 19 70 +rect 22 67 28 70 +rect 31 67 37 70 +rect 40 67 46 70 +rect 7 64 10 67 +rect 16 64 19 67 +rect 25 64 28 67 +rect 34 64 37 67 +rect 7 61 13 64 +rect 16 61 22 64 +rect 25 61 31 64 +rect 34 61 40 64 +rect 10 58 13 61 +rect 19 58 22 61 +rect 28 58 31 61 +rect 10 55 16 58 +rect 19 55 25 58 +rect 28 55 34 58 +rect 13 52 16 55 +rect 22 52 25 55 +rect 13 49 19 52 +rect 22 49 28 52 +rect 16 46 19 49 +rect 16 43 22 46 +rect 19 -59 22 43 +rect 16 -62 22 -59 +rect 16 -65 19 -62 +rect 25 -65 28 49 +rect 13 -68 19 -65 +rect 22 -68 28 -65 +rect 13 -71 16 -68 +rect 22 -71 25 -68 +rect 31 -71 34 55 +rect 10 -74 16 -71 +rect 19 -74 25 -71 +rect 28 -74 34 -71 +rect 10 -77 13 -74 +rect 19 -77 22 -74 +rect 28 -77 31 -74 +rect 37 -77 40 61 +rect 4 -80 13 -77 +rect 16 -80 22 -77 +rect 25 -80 31 -77 +rect 34 -80 40 -77 +rect 4 -110 7 -80 +rect 16 -83 19 -80 +rect 25 -83 28 -80 +rect 34 -83 37 -80 +rect 43 -83 46 67 +rect 10 -86 19 -83 +rect 22 -86 28 -83 +rect 31 -86 37 -83 +rect 40 -86 46 -83 +rect 10 -110 13 -86 +rect 22 -89 25 -86 +rect 31 -89 34 -86 +rect 40 -89 43 -86 +rect 49 -89 52 73 +rect 19 -92 25 -89 +rect 28 -92 34 -89 +rect 37 -92 43 -89 +rect 46 -92 52 -89 +rect 19 -95 22 -92 +rect 28 -95 31 -92 +rect 37 -95 40 -92 +rect 46 -95 49 -92 +rect 55 -95 58 79 +rect 16 -96 22 -95 +rect 16 -100 17 -96 +rect 21 -100 22 -96 +rect 16 -101 22 -100 +rect 25 -96 31 -95 +rect 25 -100 26 -96 +rect 30 -100 31 -96 +rect 25 -101 31 -100 +rect 34 -96 40 -95 +rect 34 -100 35 -96 +rect 39 -100 40 -96 +rect 34 -101 40 -100 +rect 43 -96 49 -95 +rect 43 -100 44 -96 +rect 48 -100 49 -96 +rect 43 -101 49 -100 +rect 52 -96 58 -95 +rect 52 -100 53 -96 +rect 57 -100 58 -96 +rect 52 -101 58 -100 +rect 61 84 67 85 +rect 61 80 62 84 +rect 66 80 67 84 +rect 61 79 67 80 +rect 70 84 76 85 +rect 70 80 71 84 +rect 75 80 76 84 +rect 70 79 76 80 +rect 79 84 85 85 +rect 79 80 80 84 +rect 84 80 85 84 +rect 79 79 85 80 +rect 88 84 94 85 +rect 88 80 89 84 +rect 93 80 94 84 +rect 88 79 94 80 +rect 97 84 103 85 +rect 97 80 98 84 +rect 102 80 103 84 +rect 97 79 103 80 +rect 106 84 112 85 +rect 106 80 107 84 +rect 111 80 112 84 +rect 106 79 112 80 +rect 61 -95 64 79 +rect 70 76 73 79 +rect 79 76 82 79 +rect 88 76 91 79 +rect 97 76 100 79 +rect 106 76 109 79 +rect 67 73 73 76 +rect 76 73 82 76 +rect 85 73 91 76 +rect 94 73 100 76 +rect 103 73 109 76 +rect 112 75 118 76 +rect 67 -89 70 73 +rect 76 70 79 73 +rect 85 70 88 73 +rect 94 70 97 73 +rect 103 70 106 73 +rect 112 71 113 75 +rect 117 71 118 75 +rect 112 70 118 71 +rect 73 67 79 70 +rect 82 67 88 70 +rect 91 67 97 70 +rect 100 67 106 70 +rect 109 67 115 70 +rect 73 -83 76 67 +rect 82 64 85 67 +rect 91 64 94 67 +rect 100 64 103 67 +rect 109 64 112 67 +rect 79 61 85 64 +rect 88 61 94 64 +rect 97 61 103 64 +rect 106 61 112 64 +rect 79 -77 82 61 +rect 88 58 91 61 +rect 97 58 100 61 +rect 106 58 109 61 +rect 85 55 91 58 +rect 94 55 100 58 +rect 103 55 109 58 +rect 85 -71 88 55 +rect 94 52 97 55 +rect 103 52 106 55 +rect 91 49 97 52 +rect 100 49 106 52 +rect 91 -65 94 49 +rect 100 46 103 49 +rect 97 43 103 46 +rect 97 -59 100 43 +rect 97 -62 103 -59 +rect 100 -65 103 -62 +rect 91 -68 97 -65 +rect 100 -68 106 -65 +rect 94 -71 97 -68 +rect 103 -71 106 -68 +rect 85 -74 91 -71 +rect 94 -74 100 -71 +rect 103 -74 109 -71 +rect 88 -77 91 -74 +rect 97 -77 100 -74 +rect 106 -77 109 -74 +rect 79 -80 85 -77 +rect 88 -80 94 -77 +rect 97 -80 103 -77 +rect 106 -80 112 -77 +rect 82 -83 85 -80 +rect 91 -83 94 -80 +rect 100 -83 103 -80 +rect 109 -83 112 -80 +rect 73 -86 79 -83 +rect 82 -86 88 -83 +rect 91 -86 97 -83 +rect 100 -86 106 -83 +rect 109 -86 115 -83 +rect 76 -89 79 -86 +rect 85 -89 88 -86 +rect 94 -89 97 -86 +rect 103 -89 106 -86 +rect 112 -88 115 -86 +rect 67 -92 73 -89 +rect 76 -92 82 -89 +rect 85 -92 91 -89 +rect 94 -92 100 -89 +rect 103 -92 109 -89 +rect 112 -91 127 -88 +rect 70 -95 73 -92 +rect 79 -95 82 -92 +rect 88 -95 91 -92 +rect 97 -95 100 -92 +rect 106 -95 109 -92 +rect 61 -96 67 -95 +rect 61 -100 62 -96 +rect 66 -100 67 -96 +rect 61 -101 67 -100 +rect 70 -96 76 -95 +rect 70 -100 71 -96 +rect 75 -100 76 -96 +rect 70 -101 76 -100 +rect 79 -96 85 -95 +rect 79 -100 80 -96 +rect 84 -100 85 -96 +rect 79 -101 85 -100 +rect 88 -96 94 -95 +rect 88 -100 89 -96 +rect 93 -100 94 -96 +rect 88 -101 94 -100 +rect 97 -96 103 -95 +rect 97 -100 98 -96 +rect 102 -100 103 -96 +rect 97 -101 103 -100 +rect 106 -96 112 -95 +rect 106 -100 107 -96 +rect 111 -100 112 -96 +rect 106 -101 112 -100 +rect 115 -96 121 -95 +rect 115 -100 116 -96 +rect 120 -100 121 -96 +rect 115 -101 121 -100 +rect 115 -110 118 -101 +rect 124 -110 127 -91 +<< polycontact >> +rect 8 80 12 84 +rect 17 80 21 84 +rect 26 80 30 84 +rect 35 80 39 84 +rect 44 80 48 84 +rect 53 80 57 84 +rect 2 71 6 75 +rect 62 80 66 84 +rect 71 80 75 84 +rect 80 80 84 84 +rect 89 80 93 84 +rect 98 80 102 84 +rect 107 80 111 84 +rect 113 71 117 75 +rect 17 -100 21 -96 +rect 26 -100 30 -96 +rect 35 -100 39 -96 +rect 44 -100 48 -96 +rect 53 -100 57 -96 +rect 62 -100 66 -96 +rect 71 -100 75 -96 +rect 80 -100 84 -96 +rect 89 -100 93 -96 +rect 98 -100 102 -96 +rect 107 -100 111 -96 +rect 116 -100 120 -96 +<< substrateopen >> +rect -16 94 134 110 +rect -16 67 -3 94 +rect 121 67 134 94 +rect -16 64 0 67 +rect 118 64 134 67 +rect -16 58 3 64 +rect 115 58 134 64 +rect -16 52 6 58 +rect 112 52 134 58 +rect -16 46 9 52 +rect 109 46 134 52 +rect -16 40 12 46 +rect 106 40 134 46 +rect -16 -10 16 40 +rect 102 -10 134 40 +<< labels >> +rlabel metal1 125 -109 125 -109 8 heater2 +rlabel metal1 5 -109 5 -109 8 heater1 +rlabel metal1 11 -109 11 -109 8 Vmeas1 +rlabel metal1 116 -109 116 -109 8 Vmeas2 +<< end >> diff --git a/scmos/examples/palette.mag b/scmos/examples/palette.mag new file mode 100644 index 00000000..8ef4b534 --- /dev/null +++ b/scmos/examples/palette.mag @@ -0,0 +1,239 @@ +magic +tech scmos +timestamp 775083658 +<< checkpaint >> +rect 13 38 40 39 +rect 5 37 40 38 +rect 5 36 48 37 +rect -42 32 -18 36 +rect -46 24 -14 32 +rect -54 20 -14 24 +rect -90 -4 -66 20 +rect -60 16 -14 20 +rect -60 5 -6 16 +rect 5 12 62 36 +rect -60 4 -2 5 +rect 5 4 70 12 +rect -60 -4 70 4 +rect -54 -8 70 -4 +rect -51 -20 70 -8 +rect -50 -28 -2 -20 +rect 5 -22 54 -20 +rect 22 -28 54 -22 +rect -50 -30 -10 -28 +<< pwell >> +rect 16 -10 20 -6 +<< nwell >> +rect 0 -10 4 -6 +<< capwell >> +rect 8 -10 12 -6 +<< highvoltnwell >> +rect -8 -10 -4 -6 +<< highvoltpwell >> +rect 24 -10 28 -6 +<< polysilicon >> +rect 0 -2 4 2 +<< electrode >> +rect 8 -2 12 2 +<< capacitor >> +rect 16 -2 20 2 +<< wellcapacitor >> +rect -40 -10 -36 -6 +<< ndiffusion >> +rect -8 -2 -4 2 +<< pdiffusion >> +rect 24 -2 28 2 +<< highvoltndiffusion >> +rect -24 -2 -20 2 +<< highvoltpdiffusion >> +rect 40 -2 44 2 +<< metal1 >> +rect -24 22 -20 26 +<< metal2 >> +rect -8 22 -4 26 +<< metal3 >> +rect 8 22 12 26 +<< ntransistor >> +rect -16 -10 -12 -6 +<< ptransistor >> +rect 32 -10 36 -6 +<< entransistor >> +rect -32 -10 -28 -6 +<< eptransistor >> +rect 48 -10 52 -6 +<< doublentransistor >> +rect -24 -10 -20 -6 +<< doubleptransistor >> +rect 40 -10 44 -6 +<< highvoltntransistor >> +rect -32 -2 -28 2 +<< highvoltptransistor >> +rect 48 -2 52 2 +<< collector >> +rect -24 14 -20 18 +<< emitter >> +rect 8 14 12 18 +<< pbase >> +rect 24 14 28 18 +<< bccdiffusion >> +rect -16 14 -12 18 +<< nbccdiffusion >> +rect -8 14 -4 18 +<< polycontact >> +rect 0 6 4 10 +<< ndcontact >> +rect -8 6 -4 10 +<< pdcontact >> +rect 24 6 28 10 +<< highvoltndcontact >> +rect -32 6 -28 10 +<< highvoltpdcontact >> +rect 48 6 52 10 +<< capcontact >> +rect 16 6 20 10 +<< electrodecontact >> +rect 8 6 12 10 +<< collectorcontact >> +rect -24 6 -20 10 +<< emittercontact >> +rect 16 14 20 18 +<< pbasecontact >> +rect 32 14 36 18 +<< nbccdiffcontact >> +rect 0 14 4 18 +<< m2contact >> +rect -16 22 -12 26 +<< m3contact >> +rect 0 22 4 26 +<< psubstratepcontact >> +rect 32 6 36 10 +<< nsubstratencontact >> +rect -16 6 -12 10 +<< psubstratepdiff >> +rect 32 -2 36 2 +<< nsubstratendiff >> +rect -16 -2 -12 2 +<< highvoltpsubcontact >> +rect 48 22 52 26 +<< highvoltnsubcontact >> +rect -32 22 -28 26 +<< highvoltpsubdiff >> +rect 48 14 52 18 +<< highvoltnsubdiff >> +rect -32 14 -28 18 +<< nplusdoping >> +rect -40 6 -36 10 +<< pplusdoping >> +rect 40 6 44 10 +<< genericcontact >> +rect 32 22 36 26 +<< substrateopen >> +rect 40 22 44 26 +<< pdiffusionstop >> +rect 40 14 44 18 +<< pad >> +rect 16 22 20 26 +<< glass >> +rect 24 22 28 26 +<< labels >> +rlabel metal1 -24 22 -20 22 5 m1 +rlabel m2contact -16 22 -12 22 5 m2c +rlabel metal2 -8 22 -4 22 5 m2 +rlabel capwell 8 -10 12 -10 5 cwell +rlabel nwell 0 -10 4 -10 5 nwell +rlabel ndiffusion -8 -2 -4 -2 5 ndiff +rlabel polysilicon 0 -2 4 -2 5 poly +rlabel electrode 8 -2 12 -2 5 poly2 +rlabel nsubstratendiff -16 -2 -12 -2 5 nsd +rlabel nsubstratencontact -16 6 -12 6 5 nsc +rlabel collectorcontact -24 6 -20 6 5 clc +rlabel ndcontact -8 6 -4 6 5 ndc +rlabel polycontact 0 6 4 6 5 pc +rlabel electrodecontact 8 6 12 6 5 ec +rlabel emitter 8 14 12 14 5 em +rlabel nbccdiffcontact 0 14 4 14 5 nbdc +rlabel nbccdiffusion -8 14 -4 14 5 nbd +rlabel bccdiffusion -16 14 -12 14 5 bd +rlabel collector -24 14 -20 14 5 col +rlabel metal3 8 22 12 22 5 m3 +rlabel m3contact 0 22 4 22 5 m3c +rlabel metal1 -22 24 -22 24 1 1 +rlabel m2contact -14 24 -14 24 1 2 +rlabel metal2 -6 24 -6 24 1 3 +rlabel m3contact 2 24 2 24 1 4 +rlabel metal3 10 24 10 24 1 5 +rlabel collectorcontact -22 8 -22 8 1 21 +rlabel nsubstratencontact -14 8 -14 8 1 22 +rlabel ndcontact -6 8 -6 8 1 23 +rlabel polycontact 2 8 2 8 1 24 +rlabel electrodecontact 10 8 10 8 1 25 +rlabel nsubstratendiff -14 0 -14 0 1 32 +rlabel ndiffusion -6 0 -6 0 1 33 +rlabel polysilicon 2 0 2 0 1 34 +rlabel electrode 10 0 10 0 1 35 +rlabel nwell 2 -8 2 -8 1 44 +rlabel capwell 10 -8 10 -8 1 45 +rlabel collector -22 16 -22 16 1 11 +rlabel bccdiffusion -14 16 -14 16 1 12 +rlabel nbccdiffusion -6 16 -6 16 1 13 +rlabel nbccdiffcontact 2 16 2 16 1 14 +rlabel emitter 10 16 10 16 1 15 +rlabel pad 16 22 20 22 5 pad +rlabel pwell 16 -10 20 -10 5 pwell +rlabel capacitor 16 -2 20 -2 5 cap +rlabel pdiffusion 24 -2 28 -2 5 pdiff +rlabel emittercontact 16 14 20 14 5 emc +rlabel pbase 24 14 28 14 5 pbase +rlabel pbasecontact 32 14 36 14 5 pbc +rlabel psubstratepcontact 32 6 36 6 5 psc +rlabel pdcontact 24 6 28 6 5 pdc +rlabel capcontact 16 6 20 6 5 capc +rlabel psubstratepdiff 32 -2 36 -2 5 psd +rlabel substrateopen 40 22 44 22 5 open +rlabel pdiffusionstop 40 14 44 14 5 pstop +rlabel glass 24 22 28 22 5 glass +rlabel genericcontact 32 22 36 22 5 gc +rlabel pad 18 24 18 24 1 6 +rlabel glass 26 24 26 24 1 7 +rlabel substrateopen 42 24 42 24 1 9 +rlabel capcontact 18 8 18 8 1 26 +rlabel pdcontact 26 8 26 8 1 27 +rlabel psubstratepcontact 34 8 34 8 1 28 +rlabel capacitor 18 0 18 0 1 36 +rlabel pdiffusion 26 0 26 0 1 37 +rlabel psubstratepdiff 34 0 34 0 1 38 +rlabel pwell 18 -8 18 -8 1 46 +rlabel emittercontact 18 16 18 16 1 16 +rlabel pbase 26 16 26 16 1 17 +rlabel pbasecontact 34 16 34 16 1 18 +rlabel pdiffusionstop 42 16 42 16 1 19 +rlabel genericcontact 34 24 34 24 1 8 +rlabel highvoltntransistor -32 -2 -28 -2 5 hnfet +rlabel highvoltndcontact -32 6 -28 6 5 hndc +rlabel highvoltnsubdiff -32 14 -28 14 5 hnsd +rlabel highvoltnsubcontact -32 22 -28 22 5 hnsc +rlabel highvoltpsubcontact 48 22 52 22 5 hpsc +rlabel highvoltpsubdiff 48 14 52 14 5 hpsd +rlabel highvoltpdcontact 48 6 52 6 5 hpdc +rlabel highvoltptransistor 48 -2 52 -2 5 hpfet +rlabel highvoltpwell 24 -10 28 -10 5 hpwell +rlabel doubleptransistor 40 -10 44 -10 5 pffet +rlabel eptransistor 48 -10 52 -10 5 epfet +rlabel doubleptransistor 42 -8 42 -8 1 47 +rlabel eptransistor 50 -8 50 -8 1 48 +rlabel ptransistor 32 -10 36 -10 5 pfet +rlabel ptransistor 34 -8 34 -8 1 39 +rlabel doublentransistor -24 -10 -20 -10 5 nffet +rlabel entransistor -32 -10 -28 -10 5 enfet +rlabel doublentransistor -22 -8 -22 -8 1 43 +rlabel entransistor -30 -8 -30 -8 1 42 +rlabel ntransistor -16 -10 -12 -10 5 nfet +rlabel ntransistor -14 -8 -14 -8 1 31 +rlabel highvoltnwell -8 -10 -4 -10 5 hnwell +rlabel wellcapacitor -40 -10 -36 -10 5 wcap +rlabel wellcapacitor -38 -8 -38 -8 1 41 +rlabel highvoltndiffusion -24 -2 -20 -2 5 hndiff +rlabel highvoltpdiffusion 40 -2 44 -2 5 hpdiff +rlabel pplusdoping 40 6 44 6 5 pdop +rlabel nplusdoping -40 6 -36 6 5 ndop +<< end >> diff --git a/scmos/examples/poly_capacitor/cap_array.mag b/scmos/examples/poly_capacitor/cap_array.mag new file mode 100644 index 00000000..6a12137c --- /dev/null +++ b/scmos/examples/poly_capacitor/cap_array.mag @@ -0,0 +1,180 @@ +magic +tech scmos +timestamp 736115372 +<< capwell >> +rect -3 -3 129 122 +<< polysilicon >> +rect -1 103 0 107 +rect -1 80 0 84 +rect -1 57 0 61 +rect -1 34 0 38 +rect -1 11 0 15 +<< wellcapacitor >> +rect 3 107 23 115 +rect 26 107 46 115 +rect 49 107 69 115 +rect 72 107 92 115 +rect 95 107 115 115 +rect 3 103 115 107 +rect 3 95 23 103 +rect 26 95 46 103 +rect 49 95 69 103 +rect 72 95 92 103 +rect 95 95 115 103 +rect 11 92 15 95 +rect 34 92 38 95 +rect 57 92 61 95 +rect 80 92 84 95 +rect 103 92 107 95 +rect 3 84 23 92 +rect 26 84 46 92 +rect 49 84 69 92 +rect 72 84 92 92 +rect 95 84 115 92 +rect 3 80 115 84 +rect 3 72 23 80 +rect 26 72 46 80 +rect 49 72 69 80 +rect 72 72 92 80 +rect 95 72 115 80 +rect 11 69 15 72 +rect 34 69 38 72 +rect 57 69 61 72 +rect 80 69 84 72 +rect 103 69 107 72 +rect 3 61 23 69 +rect 26 61 46 69 +rect 49 61 69 69 +rect 72 61 92 69 +rect 95 61 115 69 +rect 3 57 115 61 +rect 3 49 23 57 +rect 26 49 46 57 +rect 49 49 69 57 +rect 72 49 92 57 +rect 95 49 115 57 +rect 11 46 15 49 +rect 34 46 38 49 +rect 57 46 61 49 +rect 80 46 84 49 +rect 103 46 107 49 +rect 3 38 23 46 +rect 26 38 46 46 +rect 49 38 69 46 +rect 72 38 92 46 +rect 95 38 115 46 +rect 3 34 115 38 +rect 3 26 23 34 +rect 26 26 46 34 +rect 49 26 69 34 +rect 72 26 92 34 +rect 95 26 115 34 +rect 11 23 15 26 +rect 34 23 38 26 +rect 57 23 61 26 +rect 80 23 84 26 +rect 103 23 107 26 +rect 3 15 23 23 +rect 26 15 46 23 +rect 49 15 69 23 +rect 72 15 92 23 +rect 95 15 115 23 +rect 3 11 115 15 +rect 3 3 23 11 +rect 26 3 46 11 +rect 49 3 69 11 +rect 72 3 92 11 +rect 95 3 115 11 +<< ndiffusion >> +rect 0 115 119 119 +rect 0 107 3 115 +rect 23 107 26 115 +rect 46 107 49 115 +rect 69 107 72 115 +rect 92 107 95 115 +rect 0 95 3 103 +rect 23 95 26 103 +rect 46 95 49 103 +rect 69 95 72 103 +rect 92 95 95 103 +rect 115 95 119 115 +rect 0 92 11 95 +rect 15 92 34 95 +rect 38 92 57 95 +rect 61 92 80 95 +rect 84 92 103 95 +rect 107 92 119 95 +rect 0 84 3 92 +rect 23 84 26 92 +rect 46 84 49 92 +rect 69 84 72 92 +rect 92 84 95 92 +rect 0 72 3 80 +rect 23 72 26 80 +rect 46 72 49 80 +rect 69 72 72 80 +rect 92 72 95 80 +rect 115 72 119 92 +rect 0 69 11 72 +rect 15 69 34 72 +rect 38 69 57 72 +rect 61 69 80 72 +rect 84 69 103 72 +rect 107 69 119 72 +rect 0 61 3 69 +rect 23 61 26 69 +rect 46 61 49 69 +rect 69 61 72 69 +rect 92 61 95 69 +rect 0 49 3 57 +rect 23 49 26 57 +rect 46 49 49 57 +rect 69 49 72 57 +rect 92 49 95 57 +rect 115 49 119 69 +rect 0 46 11 49 +rect 15 46 34 49 +rect 38 46 57 49 +rect 61 46 80 49 +rect 84 46 103 49 +rect 107 46 119 49 +rect 0 38 3 46 +rect 23 38 26 46 +rect 46 38 49 46 +rect 69 38 72 46 +rect 92 38 95 46 +rect 0 26 3 34 +rect 23 26 26 34 +rect 46 26 49 34 +rect 69 26 72 34 +rect 92 26 95 34 +rect 115 26 119 46 +rect 0 23 11 26 +rect 15 23 34 26 +rect 38 23 57 26 +rect 61 23 80 26 +rect 84 23 103 26 +rect 107 23 119 26 +rect 0 15 3 23 +rect 23 15 26 23 +rect 46 15 49 23 +rect 69 15 72 23 +rect 92 15 95 23 +rect 0 3 3 11 +rect 23 3 26 11 +rect 46 3 49 11 +rect 69 3 72 11 +rect 92 3 95 11 +rect 115 3 119 23 +rect 0 0 119 3 +<< ntransistor >> +rect 0 103 3 107 +rect 0 80 3 84 +rect 0 57 3 61 +rect 0 34 3 38 +rect 0 11 3 15 +<< polycontact >> +rect -5 3 -1 115 +<< ndcontact >> +rect 119 0 123 119 +<< end >> diff --git a/scmos/extract_template/scmosExt.tech.in b/scmos/extract_template/scmosExt.tech.in new file mode 100644 index 00000000..9492f356 --- /dev/null +++ b/scmos/extract_template/scmosExt.tech.in @@ -0,0 +1,97 @@ +/* local definitions */ +#define allContM1 ndc/m1,pdc/m1,nwc/m1,pwc/m1 +#define PNplusWOC ndiff,pdiff,nnd/a,ppd/a + +#define CAPP allPoly +#define SSEPP ~(allPoly)/act +#define SSEP1 ~(allMetal1)/m1 +#define SSEP2 ~(allMetal2)/m2 +#define SSEP3 ~(allMetal3)/m3 + + +/* Make sure local cap defs don't appear before regardless of what cpp does*/ +#if defined(M1ContactsAct) \ + || defined (M1Contacts) \ + || defined (PNplusCap) \ + || defined (PolyCap) \ + || defined (M1Cap) \ + || defined (M2Cap) \ + || defined (M3Cap) \ + || defined (M1CapNoDiff) \ + || defined (NdRes) \ + || defined (PdRes) \ + || defined (M1Res) \ + || defined (PolyRes) \ + || defined (M2Res) \ + || defined (M3Res) \ + || defined (nothing) +THERE_IS_AN_ERROR_SOME_LOCAL_CAPACITANCE_DEFINITIONS_HAVE_ALREADY_BEEN_DEFINED +#endif + +/* Local capacitance definitions */ +#define M1ContactsAct ndc,pdc,nwc,pwc,nbdc,capc,ec,clc,emc,pbc +#define M1Contacts M1ContactsAct,pc,via +#define PNplusCap (ndiff,pdiff,em,col,ppd,nnd,M1ContactsAct)/a +#define PolyCap (poly,pc)/a +#define M1Cap (m1,M1Contacts)/m1 +#define M2Cap (m2,m2c,m3c,pad)/m2 +#define M3Cap (m3,m3c,pad)/m3 +#define M1CapNoDiff (m1,pc,via)/m1 +#define NDRes (ndiff,nsd,ndc/act,nsc/act) +#define PDRes (pdiff,psd,pdc/act,psc/act) +#define PolyRes (poly,pc/act,pfet,nfet) +#define M1Res (metal1,m2c/metal1) +#define M2Res (metal2,via/m2,pad) +#define M3Res (metal3,pad/m3,via2/m3) + + +#define nothing + +/* Use macros for planeorder and sideoverlap for backwards compatibility */ +#if defined(V5) + +#define planeOrder(l,ord) planeorder l ord +#define noplaneOrdering noplaneordering +#define sideOverlap(l1,sep,l2,cap,shield)\ + sideoverlap l1 sep l2 cap shield + +#else /* V5 */ + +#define planeOrder(l,ord) +#define noplaneOrdering +#define sideOverlap(l1,sep,l2,cap,shield)\ + sideoverlap l1 sep l2 cap + +#endif /* V5 */ + + +#define extForSpice + +/* + If you are using irsim-9.3 or older then you need to re-include + all the files without defining extForSpice so that the junction + capacitances will be extracted from magic instead of being calculated + from irsim-9.4 based on the values in the prm file and the s/d attributes + produced from magic-6.5 +*/ + +#if defined(STANDARD) /* include ORBIT 2um, AMI 1.6um, HP1.2, and HP1.0/0.8 */ +#include "scmosExt100.tech.in" +#include "scmosExt080.tech.in" +#include "scmosExt060_orb.tech.in" +#include "scmosExt34.tech.in" +#include "scmosExt26b.tech.in" +#endif /* STANDARD */ + +#if defined(TIGHTMETAL) +#include "scmosExt34.tech.in" +#include "scmosExt26b.tech.in" +#include "scmosExt14b-tm.tech.in" +#endif + +#if defined(SUBMICRON) +#include "scmosExt26b-sub.tech.in" +#include "scmosExt14b-sub.tech.in" +#endif + +#include "scmosExtDiag.tech.in" diff --git a/scmos/extract_template/scmosExt060_orb.tech.in b/scmos/extract_template/scmosExt060_orb.tech.in new file mode 100644 index 00000000..9620ffad --- /dev/null +++ b/scmos/extract_template/scmosExt060_orb.tech.in @@ -0,0 +1,111 @@ +/* + This is for HP's CMOS34 1.2 micron CMOS Bulk Process. + Again some parameters are defined by GPP others by Ersatzco + and others are computed. + +*/ +#ifdef extForSpice +style lambda=0.6(orb_scne12) +#else +style lambda_irsim=0.6(orb_scne12) +#endif + + lambda 60 + step 100 + sidehalo 0 + +#ifdef INCLUDE_FET_CAP + areacap allFet 433 +#endif + + /* ------------ diff capacitances ---------------- */ + areacap nwell 35 + perimc nwell ~(nwell) 47 + +#ifdef extForSpice + areacap ndiff,nsd,ndc/a,nsc/a 0 + areacap pdiff,psd,pdc/a,psc/a 0 + + perimc ndiff,nsd,ndc/a,nsc/a space,pwell 0 + perimc pdiff,psd,pdc/a,psc/a space,nwell 0 +#else + areacap ndiff,nsd,ndc/a,nsc/a 185 + areacap pdiff,psd,pdc/a,psc/a 148 + + perimc ndiff,nsd,ndc/a,nsc/a space,pwell 236 + perimc pdiff,psd,pdc/a,psc/a space,nwell 147 +#endif + /* ------------------------------------------------- */ + + + /* ------------ poly capacitances ---------------- */ + areacap PolyCap 29 + overlap PolyCap allWell 29 + + perimc PolyCap ~PolyCap 37 + /* ------------------------------------------------- */ + + /* ------------ metal1 capacitances ---------------- */ + areacap M1Cap 16 + overlap M1Cap allWell 16 PolyCap,PNplusCap + overlap M1Cap PNplusCap 16 + overlap M1Cap PolyCap 19 + + perimc M1Cap ~M1Cap 41 + sideOverlap(M1Cap, ~M1Cap, allWell, 41, (PolyCap,PNplusCap)) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 41, nothing) + /* ------------------------------------------------- */ + + + /* ------------ metal2 capacitances ---------------- */ + areacap M2Cap 10 + overlap M2Cap allWell 10 PolyCap,M1Cap,PNplusCap + overlap M2Cap PNplusCap 10 M1Cap + overlap M2Cap PolyCap 12 M1Cap + overlap M2Cap M1Cap 14 + + perimc M2Cap ~M2Cap 42 + sideOverlap(M2Cap, ~M2Cap, allWell, 42, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, PNplusCap, 42, M1Cap) + /* ------------------------------------------------- */ + + + /* -------------- Fets -----------------------------*/ + /* cscab, cscap defined since extresis needs them */ + device mosfet pfet pfet pdiff,pdc nwell Vdd! 270 623 + device mosfet nfet nfet ndiff,ndc pwell Gnd! 90 623 + + /* ------- Poly-Poly2 Caps and NPN Vertical Bipolars ----------*/ + device capacitor None cap,capc/a poly,pc 90 730 + device bjt npn pbase,pbc/a emit,emc/a nwell + + /* From irsim */ + fetresis nfet linear 9700 + fetresis pfet linear 35700 + /* ------------------------------------------------- */ + + /* -------------- Resistivity (in milliohms per sq) -------*/ + contact pc 4 16210 + contact ec 4 13510 + contact ndc,nsc, 4 56490 + contact pdc,psc, 4 181400 + contact m2c 4 43330 + + + resist ndiff,nsd,ndc/a,nsc/a 43180 + resist pdiff,psd,pdc/a,psc/a 79770 + resist PolyRes 22160 + resist allPoly2 21140 + resist M1Res 51 + resist M2Res 26 + resist nwell 1195000 + /* ------------------------------------------------- */ + + /* Order the planes for correct shielding */ + planeOrder(implant,0) + planeOrder(well,1) + planeOrder(active,2) + planeOrder(metal1,3) + planeOrder(metal2,4) + planeOrder(metal3,5) + planeOrder(oxide,6) diff --git a/scmos/extract_template/scmosExt080.tech.in b/scmos/extract_template/scmosExt080.tech.in new file mode 100644 index 00000000..45572634 --- /dev/null +++ b/scmos/extract_template/scmosExt080.tech.in @@ -0,0 +1,103 @@ +/* + + This is for lambda=0.8um - ie orbit's 2 um technologies. + Needs some more work for parallel coupling capacitances and upwards + fringe. + +*/ +#ifdef extForSpice +style lambda=0.8(scna16_ami) +#else +style lambda_irsim=0.8(scna16_ami) +#endif + + cscale 1 + lambda 80 + step 100 + sidehalo 0 /* no parallel coupling cap */ + +#ifdef INCLUDE_FET_CAP /* Normally off since neither spice or irsim need it */ + areacap allFet 750 /* af/lambda^2 */ +#endif + + +#ifdef extForSpice + areacap (ndiff,nsd,ndc,nsc)/a 0 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 0 + + areacap (pdiff,psd,pdc,psc)/a 0 + perimc (pdiff,psd,pdc,psc)/a space,nwell 0 +#else + areacap (ndiff,nsd,ndc,nsc)/a 172 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 60 + + areacap (pdiff,psd,pdc,psc)/a 200 + perimc (pdiff,psd,pdc,psc)/a space,nwell 68 +#endif + /* ------------------------------------------------------ */ + + /* ------------ poly capacitances ---------------- */ + areacap PolyCap 22 + overlap PolyCap allWell 22 + /* ------------------------------------------------- */ + + + /* NO fringe data avaliable */ + /* ------------ metal1 capacitances ---------------- */ + areacap M1Cap 20 + overlap M1Cap allWell 20 PolyCap,PNplusCap + overlap M1Cap PNplusCap 20 + overlap M1Cap PolyCap 25 + + /* ------------------------------------------------- */ + + + /* ------------ metal2 capacitances ---------------- */ + areacap M2Cap 10 + overlap M2Cap allWell 12 PolyCap,M1Cap,PNplusCap + overlap M2Cap PNplusCap 12 M1Cap + overlap M2Cap PolyCap 11 M1Cap + overlap M2Cap M1Cap 23 + /* ------------------------------------------------- */ + + + /* -------------- Fets -----------------------------*/ + /* cscab, cscap defined since extresis needs them */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 204 450 + fet nfet ndiff,ndc 2 nfet Gnd! pwell 150 450 + fet epfet pdiff,pdc 2 epfet Vdd! nwell 204 450 + fet enfet ndiff,ndc 2 enfet Gnd! pwell 150 450 + + fetresis nfet linear 14100 /* resistance dyn L */ + fetresis pfet linear 48100 /* resistance dyn H */ + fetresis nfet saturation 14100 /* resistance dyn L */ + fetresis pfet saturation 48100 /* resistance dyn H */ + /* ------------------------------------------------- */ + + /* -------------- Resistivity (in milliohms per sq) -------*/ + /* ---- assumed temp 85 C ----- */ + + resist NDRes 51680 + resist PDRes 74800 + resist PolyRes 34780 + resist allPoly2 22400 + resist M1Res 48 + resist M2Res 28 + resist nwell 1446400 + + contact pc 4 61560 + contact ec/a,capc/a 4 12010 + contact ndc,pdc,nsc,psc 4 45780 + contact pdc/a,psc/a 4 32310 + contact m2c 4 37570 + /* ------------------------------------------------- */ + + /* Order the planes for correct shielding */ + planeOrder(implant,0) + planeOrder(well,1) + planeOrder(active,2) + planeOrder(metal1,3) + planeOrder(metal2,4) + planeOrder(metal3,5) + planeOrder(oxide,6) + diff --git a/scmos/extract_template/scmosExt100.tech.in b/scmos/extract_template/scmosExt100.tech.in new file mode 100644 index 00000000..1ba88042 --- /dev/null +++ b/scmos/extract_template/scmosExt100.tech.in @@ -0,0 +1,236 @@ +/* + + This is for lambda=1.0um - ie orbit's 2 um technologies. + Needs some more work for parallel coupling capacitances and upwards + fringe. + +*/ +#ifdef extForSpice +style lambda=1.0(scna20_orb) +#else +style lambda_irsim=1.0(scna20_orb) +#endif + + cscale 1 + lambda 100 + step 100 + sidehalo 0 /* no parallel coupling cap */ + +#ifdef INCLUDE_FET_CAP /* Normally off since neither spice or irsim need it */ + areacap allFet 750 /* af/lambda^2 */ +#endif + + +#ifdef extForSpice + areacap (ndiff,nsd,ndc,nsc)/a 0 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 0 + + areacap (pdiff,psd,pdc,psc)/a 0 + perimc (pdiff,psd,pdc,psc)/a space,nwell 0 +#else + areacap (ndiff,nsd,ndc,nsc)/a 398 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 423 + + areacap (pdiff,psd,pdc,psc)/a 230 + perimc (pdiff,psd,pdc,psc)/a space,nwell 85 +#endif + /* ------------------------------------------------------ */ + + /* ------------ poly capacitances ---------------- */ + areacap PolyCap 39 + areacap cc/a,cap 39 + overlap PolyCap allWell 39 + areacap poly2,ec/a 50 + + perimc PolyCap ~PolyCap 80 + sideOverlap(PolyCap, ~PolyCap, allWell, 80, nothing) + /* ------------------------------------------------- */ + + + /* NO fringe data avaliable */ + /* ------------ metal1 capacitances ---------------- */ + areacap M1Cap 47 + overlap M1Cap allWell 47 PolyCap,PNplusCap + overlap M1Cap PNplusCap 47 + overlap M1Cap PolyCap 30 + overlap M1Cap poly2,cap 40 + + /* ------------------------------------------------- */ + + + /* ------------ metal2 capacitances ---------------- */ + areacap M2Cap 19 + overlap M2Cap allWell 19 PolyCap,M1Cap,PNplusCap + overlap M2Cap PNplusCap 22 M1Cap + overlap M2Cap PolyCap 19 M1Cap + overlap M2Cap poly2 40 M1Cap + overlap M2Cap M1Cap 45 + /* ------------------------------------------------- */ + + + /* -------------- MOSFet Devices -------------------------------*/ + /* syntax: device mosfet */ + /* */ + /* gscap, gccap defined since extresis needs them */ + device mosfet pfet pfet pdiff,pdc nwell Vdd! 204 450 + device mosfet nfet nfet ndiff,ndc pwell Gnd! 150 450 + device mosfet epfet epfet pdiff,pdc nwell Vdd! 204 450 + device mosfet enfet enfet ndiff,ndc pwell Gnd! 150 450 + + /* -------------------- Poly-Poly2 Caps ------------------------*/ + /* syntax: device capacitor */ + /* */ + device capacitor None cap,capc/a poly,pc 120 745 + + /* ---------- NPN Vertical Bipolar Devices -------------*/ + /* syntax: device bjt */ + device bjt npn pbase,pbc/a emit,emc/a nwell + + fetresis nfet linear 14100 /* resistance dyn L */ + fetresis pfet linear 48100 /* resistance dyn H */ + fetresis nfet saturation 14100 /* resistance dyn L */ + fetresis pfet saturation 48100 /* resistance dyn H */ + + fetresis enfet linear 14100 /* resistance dyn L */ + fetresis epfet linear 48100 /* resistance dyn H */ + fetresis enfet saturation 14100 /* resistance dyn L */ + fetresis epfet saturation 48100 /* resistance dyn H */ + /* ------------------------------------------------- */ + + /* -------------- Resistivity (in milliohms per sq) -------*/ + /* ---- assumed temp 85 C ----- */ + + resist NDRes 26670 + resist PDRes 59550 + resist PolyRes 23860 + resist allPoly2 19690 + resist em,emc/a 27260 + resist pbase,pbc/a 2000000 + resist M1Res 49 + resist M2Res 26 + resist nwell 2505830 + + contact pc 4 11000 + contact ec/a,capc/a 4 9000 + contact ndc,pdc,nsc,psc 4 18710 + contact pdc/a,psc/a 4 100560 + contact m2c 4 30 + /* ------------------------------------------------- */ + + /* Order the planes for correct shielding */ + planeOrder(implant,0) + planeOrder(well,1) + planeOrder(active,2) + planeOrder(metal1,3) + planeOrder(metal2,4) + planeOrder(metal3,5) + planeOrder(oxide,6) + + /* Layer widths and thicknesses for inductance extraction */ + /* and 3D rendering */ + height nwell -0.1 0.1 + height ndiff,pdiff,nndiff,ppdiff -0.075 0.075 + height poly,pfet,nfet 0.1 0.05 + height ndc,pdc,nsc,psc 0.001 0.25 + height pc 0.1 0.15 + height m1 0.2 0.05 + height m2c 0.2 0.15 + height m2 0.3 0.05 + +#ifdef extForSpice +style lambdaSp=1.0(scpe20_orb) +#else +style lambda=1.0(scpe20_orb) +#endif + + lambda 100 + step 100 + sidehalo 0 /* no parallel coupling cap */ + +#ifdef INCLUDE_FET_CAP /* Normally off since neither spice or irsim need it */ + areacap allFet 750 /* af/lambda^2 */ +#endif + + +#ifdef extForSpice + areacap (ndiff,nsd,ndc,nsc)/a 0 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 0 + + areacap (pdiff,psd,pdc,psc)/a 0 + perimc (pdiff,psd,pdc,psc)/a space,nwell 0 +#else + areacap (ndiff,nsd,ndc,nsc)/a 398 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 423 + + areacap (pdiff,psd,pdc,psc)/a 230 + perimc (pdiff,psd,pdc,psc)/a space,nwell 85 +#endif + /* ------------------------------------------------------ */ + + /* ------------ poly capacitances ---------------- */ + areacap PolyCap 57 + overlap PolyCap allWell 57 + + perimc PolyCap ~PolyCap 168 + sideOverlap(PolyCap, ~PolyCap, allWell, 168, nothing) + /* ------------------------------------------------- */ + + + /* NO fringe data avaliable */ + /* ------------ metal1 capacitances ---------------- */ + areacap M1Cap 41 + overlap M1Cap allWell 41 PolyCap,PNplusCap + overlap M1Cap PNplusCap 41 + overlap M1Cap PolyCap 33 + overlap M1Cap poly2,cap 45 + + /* ------------------------------------------------- */ + + + /* ------------ metal2 capacitances ---------------- */ + areacap M2Cap 21 + overlap M2Cap allWell 21 PolyCap,M1Cap,PNplusCap + overlap M2Cap PNplusCap 21 M1Cap + overlap M2Cap PolyCap 25 M1Cap + overlap M2Cap M1Cap 33 + /* ------------------------------------------------- */ + + + /* -------------- Fets -----------------------------*/ + /* gscap, gccap defined since extresis needs them */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 204 450 + fet nfet ndiff,ndc 2 nfet Gnd! pwell 150 450 + + fetresis nfet linear 14100 /* resistance dyn L */ + fetresis pfet linear 48100 /* resistance dyn H */ + + fetresis nfet saturation 14100 /* resistance dyn L */ + fetresis pfet saturation 48100 /* resistance dyn H */ + /* ------------------------------------------------- */ + + /* -------------- Resistivity (in milliohms per sq) -------*/ + /* ---- assumed temp 85 C ----- */ + + resist NDRes 26670 + resist PDRes 72860 + resist PolyRes 23860 + resist allPoly2 18540 + resist M1Res 49 + resist M2Res 26 + resist pwell 2128280 + + contact pc 4 12800 + contact ec/a,capc/a 4 8420 + contact (ndc,nsc)/a 4 36660 + contact (psc,pdc)/a 4 56300 + contact m2c 4 30 + /* ------------------------------------------------- */ + + /* Order the planes for correct shielding */ + planeOrder(implant,0) + planeOrder(well,1) + planeOrder(active,2) + planeOrder(metal1,3) + planeOrder(metal2,4) + planeOrder(metal3,5) + planeOrder(oxide,6) diff --git a/scmos/extract_template/scmosExt14b-sub.tech.in b/scmos/extract_template/scmosExt14b-sub.tech.in new file mode 100644 index 00000000..0099dcad --- /dev/null +++ b/scmos/extract_template/scmosExt14b-sub.tech.in @@ -0,0 +1,164 @@ +/* + + This is for HP's CMOS26B 1.0 micron CMOS Bulk Process. + All parameters are defined based on HP's general process + specifications (GPP). Sidewall fringing was taken from + Ersatco fictitious process (johnson,jouppi). + + Upwards fringe caps (eg poly-->m1, poly-->m2) are computed + by the program scaleCap by using the Sakurai/Tamaru formula + based on the known capacitances. +*/ +#ifdef extForSpice +style lambda=0.30 +#else +style lambda_irsim=0.30 +#endif + + lambda 30 + step 100 + sidehalo 10 /* 4 more than min m3 spacing */ + +#ifdef INCLUDE_FET_CAP /* Normally off since neither spice or irsim need it */ + areacap allFet 692 /* af/lambda^2 */ +#endif + + /* ------------ diff capacitances ---------------- */ + areacap nwell 19 /* 208aF/um2*/ + perimc nwell ~(nwell) 60 /* scale the 26b value */ + +#ifdef extForSpice + + areacap (ndiff,nsd,ndc,nsc)/a 0 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 0 + + areacap (pdiff,psd,pdc,psc)/a 0 + perimc (pdiff,psd,pdc,psc)/a space,nwell 0 + +#else + + /* Real perim values increased a little to + compensate for not counting CJGATE */ + areacap (ndiff,nsd,ndc,nsc)/a 23 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 160 + /* field - 320aF/um */ + /* gate - 614aF/um */ + + areacap (pdiff,psd,pdc,psc)/a 52 + perimc (pdiff,psd,pdc,psc)/a space,nwell 90 + /* field - 213aF/um */ + /* gate - 332aF/um */ +#endif + /* ------------------------------------------------------ */ + + /* ------------ poly capacitances ---------------- */ + areacap PolyCap 8.2 + overlap PolyCap allWell 8.2 + + perimc PolyCap ~PolyCap 12.6 + sideOverlap(PolyCap, ~PolyCap, allWell, 12.6, nothing) + sideOverlap(PolyCap, ~PolyCap, M1Cap, 5.7, nothing) + sideOverlap(PolyCap, ~PolyCap, M2Cap, 2.7, M1Cap) + sideOverlap(PolyCap, ~PolyCap, M3Cap, 1.8, (M1Cap,M2Cap)) + + sidewall PolyCap ~PolyCap ~PolyCap PolyCap 7.2 + /* ------------------------------------------------- */ + + + /* ------------ metal1 capacitances ---------------- */ + areacap M1Cap 3.5 + overlap M1Cap allWell 3.5 PolyCap,PNplusCap + overlap M1Cap PNplusCap 5.7 + overlap M1Cap PolyCap 5.7 + + perimc M1Cap ~M1Cap 15 + sideOverlap(M1Cap, ~M1Cap, allWell, 15, (PolyCap,PNplusCap)) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 17.4, nothing) + sideOverlap(M1Cap, ~M1Cap, PolyCap, 17.4, nothing) + sideOverlap(M1Cap, ~M1Cap, M2Cap, 8.7, nothing) + sideOverlap(M1Cap, ~M1Cap, M3Cap, 4.8, M2Cap) + + sidewall M1Cap ~M1Cap ~M1Cap M1Cap 19.2 + /* ------------------------------------------------- */ + + + /* ------------ metal2 capacitances ---------------- */ + areacap M2Cap 1.3 + overlap M2Cap allWell 1.3 PolyCap,M1Cap,PNplusCap + overlap M2Cap PNplusCap 1.5 M1Cap + overlap M2Cap PolyCap 1.5 M1Cap + overlap M2Cap M1Cap 3.5 + + perimc M2Cap ~M2Cap 12.3 + sideOverlap(M2Cap, ~M2Cap, allWell, 12.3, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, PNplusCap, 12.9, M1Cap) + sideOverlap(M2Cap, ~M2Cap, PolyCap, 12.9, M1Cap) + sideOverlap(M2Cap, ~M2Cap, M1Cap, 15, nothing) + sideOverlap(M2Cap, ~M2Cap, M3Cap, 10.8, nothing) + + sidewall M2Cap ~M2Cap ~M2Cap M2Cap 21.6 + /* ------------------------------------------------- */ + + + /* ------------ metal3 capacitances ---------------- */ + areacap M3Cap .81 + overlap M3Cap allWell .81 PolyCap,M1Cap,M2Cap,PNplusCap + overlap M3Cap PNplusCap .88 M1Cap,M2Cap + overlap M3Cap PolyCap .88 M1Cap,M2Cap + overlap M3Cap M1Cap 1.3 M2Cap + overlap M3Cap M2Cap 3.3 + + perimc M3Cap ~M3Cap 12.3 + sideOverlap(M3Cap, ~M3Cap, allWell, 12.3, (PNplusCap,PolyCap,M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, PNplusCap, 12.9, (M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, PolyCap, 12.9, (M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, M1Cap, 15.3, (M2Cap)) + sideOverlap(M3Cap, ~M3Cap, M2Cap, 19.2, nothing) + + sidewall M3Cap ~M3Cap ~M3Cap M3Cap 34.3 + /* ------------------------------------------------- */ + + /* Unchanged yet for .35um*/ + /* -------------- Fets -----------------------------*/ + /* cscab, cscap defined since extresis needs them */ + /* gate cap is actually 982aF/um^2 or .344fF/um*/ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 218 88 + fet nfet ndiff,ndc 2 nfet Gnd! pwell 267 88 + + /* These values are the equivalent resistance that irsim params for + 3.3 V 85C */ + fetresis nfet linear 8500 /* resistance dyn L */ + fetresis pfet linear 24500 /* resistance dyn H */ + + fetresis nfet saturation 8500 /* resistance dyn L */ + fetresis pfet saturation 24500 /* resistance dyn H */ + /* ------------------------------------------------- */ + + /* -------------- Resistivity (in milliohms per sq) -------*/ + /* ---- assumed temp 85 C ----- */ + + resist NDRes 3100 + resist PDRes 2500 + resist PolyRes 7500 /*4400 for W>1.0um*/ + resist M1Res 83 + resist M2Res 84 + resist M3Res 41 + resist nwell 1980000 /*unchanged from 26b*/ + + /* Values are for per contact */ + contact pc 4 10000 /*8k-nom 15k-max*/ + contact ndc,pdc,nsc,psc 4 4500 + contact m2c 4 1000 + contact m3c 4 1000 + /* ------------------------------------------------- */ + + /* Order the planes for correct shielding */ + planeOrder(implant,0) + planeOrder(well,1) + planeOrder(active,2) + planeOrder(metal1,3) + planeOrder(metal2,4) + planeOrder(metal3,5) + planeOrder(oxide,6) + + diff --git a/scmos/extract_template/scmosExt14b-tm.tech.in b/scmos/extract_template/scmosExt14b-tm.tech.in new file mode 100644 index 00000000..3de6d854 --- /dev/null +++ b/scmos/extract_template/scmosExt14b-tm.tech.in @@ -0,0 +1,163 @@ +/* + + This is for HP's CMOS26B 1.0 micron CMOS Bulk Process. + All parameters are defined based on HP's general process + specifications (GPP). Sidewall fringing was taken from + Ersatco fictitious process (johnson,jouppi). + + Upwards fringe caps (eg poly-->m1, poly-->m2) are computed + by the program scaleCap by using the Sakurai/Tamaru formula + based on the known capacitances. +*/ +#ifdef extForSpice +style lambda=0.35 +#else +style lambda_irsim=0.35 +#endif + + lambda 35 + step 100 + sidehalo 10 /* 4 more than min m3 spacing */ + +#ifdef INCLUDE_FET_CAP /* Normally off since neither spice or irsim need it */ + areacap allFet 692 /* af/lambda^2 */ +#endif + + /* ------------ diff capacitances ---------------- */ + areacap nwell 25 /* 208aF/um2*/ + perimc nwell ~(nwell) 70 /* scale the 26b value */ + +#ifdef extForSpice + + areacap (ndiff,nsd,ndc,nsc)/a 0 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 0 + + areacap (pdiff,psd,pdc,psc)/a 0 + perimc (pdiff,psd,pdc,psc)/a space,nwell 0 + +#else + + /* Real perim values increased a little to + compensate for not counting CJGATE */ + areacap (ndiff,nsd,ndc,nsc)/a 31 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 180 + /* field - 320aF/um */ + /* gate - 614aF/um */ + + areacap (pdiff,psd,pdc,psc)/a 71 + perimc (pdiff,psd,pdc,psc)/a space,nwell 100 + /* field - 213aF/um */ + /* gate - 332aF/um */ +#endif + /* ------------------------------------------------------ */ + + /* ------------ poly capacitances ---------------- */ + areacap PolyCap 11.1 + overlap PolyCap allWell 11.1 + + perimc PolyCap ~PolyCap 14.7 + sideOverlap(PolyCap, ~PolyCap, allWell, 14.7, nothing) + sideOverlap(PolyCap, ~PolyCap, M1Cap, 6.7, nothing) + sideOverlap(PolyCap, ~PolyCap, M2Cap, 3.2, M1Cap) + sideOverlap(PolyCap, ~PolyCap, M3Cap, 2.1, (M1Cap,M2Cap)) + + sidewall PolyCap ~PolyCap ~PolyCap PolyCap 8.4 + /* ------------------------------------------------- */ + + + /* ------------ metal1 capacitances ---------------- */ + areacap M1Cap 4.8 + overlap M1Cap allWell 4.8 PolyCap,PNplusCap + overlap M1Cap PNplusCap 7.7 + overlap M1Cap PolyCap 7.7 + + perimc M1Cap ~M1Cap 17.5 + sideOverlap(M1Cap, ~M1Cap, allWell, 17.5, (PolyCap,PNplusCap)) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 20.3, nothing) + sideOverlap(M1Cap, ~M1Cap, PolyCap, 20.3, nothing) + sideOverlap(M1Cap, ~M1Cap, M2Cap, 10.2, nothing) + sideOverlap(M1Cap, ~M1Cap, M3Cap, 5.6, M2Cap) + + sidewall M1Cap ~M1Cap ~M1Cap M1Cap 22.4 + /* ------------------------------------------------- */ + + + /* ------------ metal2 capacitances ---------------- */ + areacap M2Cap 1.8 + overlap M2Cap allWell 1.8 PolyCap,M1Cap,PNplusCap + overlap M2Cap PNplusCap 2.1 M1Cap + overlap M2Cap PolyCap 2.1 M1Cap + overlap M2Cap M1Cap 4.7 + + perimc M2Cap ~M2Cap 14.4 + sideOverlap(M2Cap, ~M2Cap, allWell, 14.4, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, PNplusCap, 15.1, M1Cap) + sideOverlap(M2Cap, ~M2Cap, PolyCap, 15.1, M1Cap) + sideOverlap(M2Cap, ~M2Cap, M1Cap, 17.5, nothing) + sideOverlap(M2Cap, ~M2Cap, M3Cap, 12.6, nothing) + + sidewall M2Cap ~M2Cap ~M2Cap M2Cap 25.2 + /* ------------------------------------------------- */ + + + /* ------------ metal3 capacitances ---------------- */ + areacap M3Cap 1.1 + overlap M3Cap allWell 1.1 PolyCap,M1Cap,M2Cap,PNplusCap + overlap M3Cap PNplusCap 1.2 M1Cap,M2Cap + overlap M3Cap PolyCap 1.2 M1Cap,M2Cap + overlap M3Cap M1Cap 1.8 M2Cap + overlap M3Cap M2Cap 4.5 + + perimc M3Cap ~M3Cap 14.4 + sideOverlap(M3Cap, ~M3Cap, allWell, 14.4, (PNplusCap,PolyCap,M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, PNplusCap, 15.1, (M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, PolyCap, 15.1, (M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, M1Cap, 17.9, (M2Cap)) + sideOverlap(M3Cap, ~M3Cap, M2Cap, 22.4, nothing) + + sidewall M3Cap ~M3Cap ~M3Cap M3Cap 40 + /* ------------------------------------------------- */ + + /* Unchanged yet for .35um*/ + /* -------------- Fets -----------------------------*/ + /* cscab, cscap defined since extresis needs them */ + /* gate cap is actually 982aF/um^2 or .344fF/um*/ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 254 120 + fet nfet ndiff,ndc 2 nfet Gnd! pwell 311 120 + + /* These values are the equivalent resistance that irsim params for + 3.3 V 85C */ + fetresis nfet linear 14285 /* resistance dyn L */ + fetresis pfet linear 40914 /* resistance dyn H */ + + fetresis nfet saturation 14285 /* resistance dyn L */ + fetresis pfet saturation 40914 /* resistance dyn H */ + /* ------------------------------------------------- */ + + /* -------------- Resistivity (in milliohms per sq) -------*/ + /* ---- assumed temp 85 C ----- */ + + resist NDRes 3100 + resist PDRes 2500 + resist PolyRes 7500 /*4400 for W>1.0um*/ + resist M1Res 83 + resist M2Res 84 + resist M3Res 41 + resist nwell 1980000 /*unchanged from 26b*/ + + /* Values are for per contact */ + contact pc 4 10000 /*8k-nom 15k-max*/ + contact ndc,pdc,nsc,psc 4 4500 + contact m2c 4 1000 + contact m3c 4 1000 + /* ------------------------------------------------- */ + + /* Order the planes for correct shielding */ + planeOrder(implant,0) + planeOrder(well,1) + planeOrder(active,2) + planeOrder(metal1,3) + planeOrder(metal2,4) + planeOrder(metal3,5) + planeOrder(oxide,6) + diff --git a/scmos/extract_template/scmosExt26b-sub.tech.in b/scmos/extract_template/scmosExt26b-sub.tech.in new file mode 100644 index 00000000..9bf9de6a --- /dev/null +++ b/scmos/extract_template/scmosExt26b-sub.tech.in @@ -0,0 +1,151 @@ +/* + + This is for HP's CMOS26B 0.8 micron CMOS Bulk Process. + Just a scale of the other file + +*/ +#ifdef extForSpice +style lambda=0.4 +#else +style lambda_irsim=0.4 +#endif + + lambda 40 + step 100 + sidehalo 8 /* 2 more than min m3 spacing */ + +#ifdef INCLUDE_FET_CAP /* Normally off since neither spice or irsim need it */ + areacap allFet 692 /* af/lambda^2 */ +#endif + + /* ------------ diff capacitances ---------------- */ + areacap nwell 26 + perimc nwell ~(nwell) 80 + +#ifdef extForSpice + + areacap (ndiff,nsd,ndc,nsc)/a 0 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 0 + + areacap (pdiff,psd,pdc,psc)/a 0 + perimc (pdiff,psd,pdc,psc)/a space,nwell 0 + +#else + + /* Real perim values increased a little to + compensate for not counting CJGATE */ + areacap (ndiff,nsd,ndc,nsc)/a 26 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 240 + + areacap (pdiff,psd,pdc,psc)/a 136 + perimc (pdiff,psd,pdc,psc)/a space,nwell 160 +#endif + /* ------------------------------------------------------ */ + + /* ------------ poly capacitances ---------------- */ + areacap PolyCap 10 + overlap PolyCap allWell 10 + + perimc PolyCap ~PolyCap 18 + sideOverlap(PolyCap, ~PolyCap, allWell, 18, nothing) + sideOverlap(PolyCap, ~PolyCap, M1Cap, 8, nothing) + sideOverlap(PolyCap, ~PolyCap, M2Cap, 5, M1Cap) + sideOverlap(PolyCap, ~PolyCap, M3Cap, 3, (M1Cap,M2Cap)) + + sidewall PolyCap ~PolyCap ~PolyCap PolyCap 9 + /* ------------------------------------------------- */ + + + /* ------------ metal1 capacitances ---------------- */ + areacap M1Cap 6 + overlap M1Cap allWell 6 PolyCap,PNplusCap + overlap M1Cap PNplusCap 9 + overlap M1Cap PolyCap 9 + + perimc M1Cap ~M1Cap 18 + sideOverlap(M1Cap, ~M1Cap, allWell, 18, (PolyCap,PNplusCap)) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 20, nothing) + sideOverlap(M1Cap, ~M1Cap, PolyCap, 20, nothing) + sideOverlap(M1Cap, ~M1Cap, M2Cap, 10, nothing) + sideOverlap(M1Cap, ~M1Cap, M3Cap, 6, M2Cap) + + sidewall M1Cap ~M1Cap ~M1Cap M1Cap 22 + /* ------------------------------------------------- */ + + + /* ------------ metal2 capacitances ---------------- */ + areacap M2Cap 2.5 + overlap M2Cap allWell 2.5 PolyCap,M1Cap,PNplusCap + overlap M2Cap PNplusCap 3 M1Cap + overlap M2Cap PolyCap 4 M1Cap + overlap M2Cap M1Cap 6 + + perimc M2Cap ~M2Cap 15 + sideOverlap(M2Cap, ~M2Cap, allWell, 15, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, PNplusCap, 16, M1Cap) + sideOverlap(M2Cap, ~M2Cap, PolyCap, 16, M1Cap) + sideOverlap(M2Cap, ~M2Cap, M1Cap, 18, nothing) + sideOverlap(M2Cap, ~M2Cap, M3Cap, 8, nothing) + + sidewall M2Cap ~M2Cap ~M2Cap M2Cap 26 + /* ------------------------------------------------- */ + + + /* ------------ metal3 capacitances ---------------- */ + areacap M3Cap 2 + overlap M3Cap allWell 2 PolyCap,M1Cap,M2Cap,PNplusCap + overlap M3Cap PNplusCap 2 M1Cap,M2Cap + overlap M3Cap PolyCap 2 M1Cap,M2Cap + overlap M3Cap M1Cap 3 M2Cap + overlap M3Cap M2Cap 6 + + perimc M3Cap ~M3Cap 14 + sideOverlap(M3Cap, ~M3Cap, allWell, 14, (PNplusCap,PolyCap,M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, PNplusCap, 14, (M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, PolyCap, 14, (M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, M1Cap, 16, (M2Cap)) + sideOverlap(M3Cap, ~M3Cap, M2Cap, 20, nothing) + + sidewall M3Cap ~M3Cap ~M3Cap M3Cap 40 + /* ------------------------------------------------- */ + + + /* -------------- Fets -----------------------------*/ + /* cscab, cscap defined since extresis needs them */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 204 450 + fet nfet ndiff,ndc 2 nfet Gnd! pwell 150 450 + + /* These values are the equivalent resistance that irsim params for + 3.3 V 125C though. Probably we want to make that 5V, 27C !!!! */ + fetresis nfet linear 14100 /* resistance dyn L */ + fetresis pfet linear 48100 /* resistance dyn H */ + + fetresis nfet saturation 14100 /* resistance dyn L */ + fetresis pfet saturation 48100 /* resistance dyn H */ + /* ------------------------------------------------- */ + + /* -------------- Resistivity (in milliohms per sq) -------*/ + /* ---- assumed temp 85 C ----- */ + + resist NDRes 3800 + resist PDRes 3800 + resist PolyRes 5000 + resist M1Res 81 + resist M2Res 81 + resist M3Res 34 + resist nwell 1980000 + + contact pc 4 15000 + contact ndc,pdc,nsc,psc 4 1500 + contact m2c 4 500 + contact m3c 4 500 + /* ------------------------------------------------- */ + + /* Order the planes for correct shielding */ + planeOrder(implant,0) + planeOrder(well,1) + planeOrder(active,2) + planeOrder(metal1,3) + planeOrder(metal2,4) + planeOrder(metal3,5) + planeOrder(oxide,6) diff --git a/scmos/extract_template/scmosExt26b.tech.in b/scmos/extract_template/scmosExt26b.tech.in new file mode 100644 index 00000000..f9d22162 --- /dev/null +++ b/scmos/extract_template/scmosExt26b.tech.in @@ -0,0 +1,156 @@ +/* + + This is for HP's CMOS26B 1.0 micron CMOS Bulk Process. + All parameters are defined based on HP's general process + specifications (GPP). Sidewall fringing was taken from + Ersatco fictitious process (johnson,jouppi). + + Upwards fringe caps (eg poly-->m1, poly-->m2) are computed + by the program scaleCap by using the Skurai/Tamaru formula + based on the known capacitances. +*/ +#ifdef extForSpice +style lambda=0.5 +#else +style lambda_irsim=0.5 +#endif + + lambda 50 + step 100 + sidehalo 8 /* 2 more than min m3 spacing */ + +#ifdef INCLUDE_FET_CAP /* Normally off since neither spice or irsim need it */ + areacap allFet 692 /* af/lambda^2 */ +#endif + + /* ------------ diff capacitances ---------------- */ + areacap nwell 40 + perimc nwell ~(nwell) 100 + +#ifdef extForSpice + + areacap (ndiff,nsd,ndc,nsc)/a 0 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 0 + + areacap (pdiff,psd,pdc,psc)/a 0 + perimc (pdiff,psd,pdc,psc)/a space,nwell 0 + +#else + + /* Real perim values increased a little to + compensate for not counting CJGATE */ + areacap (ndiff,nsd,ndc,nsc)/a 40 + perimc (ndiff,nsd,ndc,nsc)/a space,pwell 300 /* 250 */ + + areacap (pdiff,psd,pdc,psc)/a 170 + perimc (pdiff,psd,pdc,psc)/a space,nwell 200 /* 160 */ +#endif + /* ------------------------------------------------------ */ + + /* ------------ poly capacitances ---------------- */ + areacap PolyCap 15 + overlap PolyCap allWell 15 + + perimc PolyCap ~PolyCap 22 + sideOverlap(PolyCap, ~PolyCap, allWell, 22, nothing) + sideOverlap(PolyCap, ~PolyCap, M1Cap, 10, nothing) + sideOverlap(PolyCap, ~PolyCap, M2Cap, 6, M1Cap) + sideOverlap(PolyCap, ~PolyCap, M3Cap, 4, (M1Cap,M2Cap)) + + sidewall PolyCap ~PolyCap ~PolyCap PolyCap 11 + /* ------------------------------------------------- */ + + + /* ------------ metal1 capacitances ---------------- */ + areacap M1Cap 8 + overlap M1Cap allWell 8 PolyCap,PNplusCap + overlap M1Cap PNplusCap 14 + overlap M1Cap PolyCap 14 + + perimc M1Cap ~M1Cap 22 + sideOverlap(M1Cap, ~M1Cap, allWell, 22, (PolyCap,PNplusCap)) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 25, nothing) + sideOverlap(M1Cap, ~M1Cap, PolyCap, 25, nothing) + sideOverlap(M1Cap, ~M1Cap, M2Cap, 12, nothing) + sideOverlap(M1Cap, ~M1Cap, M3Cap, 7, M2Cap) + + sidewall M1Cap ~M1Cap ~M1Cap M1Cap 27 + /* ------------------------------------------------- */ + + + /* ------------ metal2 capacitances ---------------- */ + areacap M2Cap 4 + overlap M2Cap allWell 4 PolyCap,M1Cap,PNplusCap + overlap M2Cap PNplusCap 5 M1Cap + overlap M2Cap PolyCap 6 M1Cap + overlap M2Cap M1Cap 9 + + perimc M2Cap ~M2Cap 18 + sideOverlap(M2Cap, ~M2Cap, allWell, 18, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, PNplusCap, 19, M1Cap) + sideOverlap(M2Cap, ~M2Cap, PolyCap, 20, M1Cap) + sideOverlap(M2Cap, ~M2Cap, M1Cap, 23, nothing) + sideOverlap(M2Cap, ~M2Cap, M3Cap, 10, nothing) + + sidewall M2Cap ~M2Cap ~M2Cap M2Cap 33 + /* ------------------------------------------------- */ + + + /* ------------ metal3 capacitances ---------------- */ + areacap M3Cap 3 + overlap M3Cap allWell 3 PolyCap,M1Cap,M2Cap,PNplusCap + overlap M3Cap PNplusCap 3 M1Cap,M2Cap + overlap M3Cap PolyCap 3 M1Cap,M2Cap + overlap M3Cap M1Cap 4 M2Cap + overlap M3Cap M2Cap 9 + + perimc M3Cap ~M3Cap 17 + sideOverlap(M3Cap, ~M3Cap, allWell, 17, (PNplusCap,PolyCap,M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, PNplusCap, 17, (M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, PolyCap, 17, (M1Cap,M2Cap)) + sideOverlap(M3Cap, ~M3Cap, M1Cap, 20, (M2Cap)) + sideOverlap(M3Cap, ~M3Cap, M2Cap, 25, nothing) + + sidewall M3Cap ~M3Cap ~M3Cap M3Cap 50 + /* ------------------------------------------------- */ + + + /* -------------- Fets -----------------------------*/ + /* cscab, cscap defined since extresis needs them */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 204 450 + fet nfet ndiff,ndc 2 nfet Gnd! pwell 150 450 + + /* These values are the equivalent resistance that irsim params for + 3.3 V 125C though. Probably we want to make that 5V, 27C !!!! */ + fetresis nfet linear 14100 /* resistance dyn L */ + fetresis pfet linear 48100 /* resistance dyn H */ + + fetresis nfet saturation 14100 /* resistance dyn L */ + fetresis pfet saturation 48100 /* resistance dyn H */ + /* ------------------------------------------------- */ + + /* -------------- Resistivity (in milliohms per sq) -------*/ + /* ---- assumed temp 85 C ----- */ + + resist NDRes 3800 + resist PDRes 3800 + resist PolyRes 5000 + resist M1Res 81 + resist M2Res 81 + resist M3Res 34 + resist nwell 1980000 + + contact pc 4 15000 + contact ndc,pdc,nsc,psc 4 1500 + contact m2c 4 500 + contact m3c 4 500 + /* ------------------------------------------------- */ + + /* Order the planes for correct shielding */ + planeOrder(implant,0) + planeOrder(well,1) + planeOrder(active,2) + planeOrder(metal1,3) + planeOrder(metal2,4) + planeOrder(metal3,5) + planeOrder(oxide,6) diff --git a/scmos/extract_template/scmosExt34.tech.in b/scmos/extract_template/scmosExt34.tech.in new file mode 100644 index 00000000..2909f0db --- /dev/null +++ b/scmos/extract_template/scmosExt34.tech.in @@ -0,0 +1,119 @@ +/* + This is for HP's CMOS34 1.2 micron CMOS Bulk Process. + Again some parameters are defined by GPP others by Ersatzco + and others are computed. + +*/ +#ifdef extForSpice +style lambda=0.6(hp) +#else +style lambda_irsim=0.6(hp) +#endif + + lambda 60 + step 100 + sidehalo 6 /* 2 more than min m2 spacing */ + +#ifdef INCLUDE_FET_CAP + areacap allFet 433 +#endif + + /* ------------ diff capacitances ---------------- */ + areacap nwell 35 + perimc nwell ~(nwell) 47 + +#ifdef extForSpice + areacap ndiff,nsd,ndc/a,nsc/a 0 + areacap pdiff,psd,pdc/a,psc/a 0 + + perimc ndiff,nsd,ndc/a,nsc/a space,pwell 0 + perimc pdiff,psd,pdc/a,psc/a space,nwell 0 +#else + areacap ndiff,nsd,ndc/a,nsc/a 116 + areacap pdiff,psd,pdc/a,psc/a 187 + /* Real values increased to compensate for not counting CJGATE */ + perimc ndiff,nsd,ndc/a,nsc/a space,pwell 176 /* 156 */ + perimc pdiff,psd,pdc/a,psc/a space,nwell 162 /* 132 */ +#endif + /* ------------------------------------------------- */ + + + /* ------------ poly capacitances ---------------- */ + areacap PolyCap 28 + overlap PolyCap allWell 28 + + perimc PolyCap ~PolyCap 38 + sideOverlap(PolyCap, ~PolyCap, allWell, 38, nothing) + sideOverlap(PolyCap, ~PolyCap, M1Cap, 34, nothing) + sideOverlap(PolyCap, ~PolyCap, M2Cap, 27, M1Cap) + + sidewall PolyCap ~PolyCap ~PolyCap PolyCap 15 + /* ------------------------------------------------- */ + + /* ------------ metal1 capacitances ---------------- */ + areacap M1Cap 18 + overlap M1Cap allWell 18 PolyCap,PNplusCap + overlap M1Cap PNplusCap 46 + overlap M1Cap PolyCap 46 + + perimc M1Cap ~M1Cap 33 + sideOverlap(M1Cap, ~M1Cap, allWell, 33, (PolyCap,PNplusCap)) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 33, nothing) + sideOverlap(M1Cap, ~M1Cap, PolyCap, 33, nothing) + sideOverlap(M1Cap, ~M1Cap, M2Cap, 28, nothing) + + sidewall M1Cap ~M1Cap ~M1Cap M1Cap 27 + /* ------------------------------------------------- */ + + + /* ------------ metal2 capacitances ---------------- */ + areacap M2Cap 9 + overlap M2Cap allWell 9 PolyCap,M1Cap,PNplusCap + overlap M2Cap PNplusCap 12 M1Cap + overlap M2Cap PolyCap 14 M1Cap + overlap M2Cap M1Cap 30 + + perimc M2Cap ~M2Cap 22 + sideOverlap(M2Cap, ~M2Cap, allWell, 22, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, PNplusCap, 20, M1Cap) + sideOverlap(M2Cap, ~M2Cap, PolyCap, 22, M1Cap) + sideOverlap(M2Cap, ~M2Cap, M1Cap, 28, nothing) + + sidewall M2Cap ~M2Cap ~M2Cap M2Cap 33 + /* ------------------------------------------------- */ + + + /* -------------- Fets -----------------------------*/ + /* cscab, cscap defined since extresis needs them */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 270 623 + fet nfet ndiff,ndc 2 nfet Gnd! pwell 90 623 + fet wcap ndiff,ndc 1 wcap Gnd! pwell 300 0 + + /* From irsim */ + fetresis nfet linear 9700 + fetresis pfet linear 35700 + /* ------------------------------------------------- */ + + /* -------------- Resistivity (in milliohms per sq) -------*/ + contact pc 4 16210 + contact ndc,nsc, 4 77000 + contact pdc,psc, 4 44260 + contact m2c 4 150 + + + resist ndiff,nsd,ndc/a,nsc/a 99630 + resist pdiff,psd,pdc/a,psc/a 120000 + resist PolyRes 25000 + resist M1Res 60 + resist M2Res 40 + resist nwell 1500000 + /* ------------------------------------------------- */ + + /* Order the planes for correct shielding */ + planeOrder(implant,0) + planeOrder(well,1) + planeOrder(active,2) + planeOrder(metal1,3) + planeOrder(metal2,4) + planeOrder(metal3,5) + planeOrder(oxide,6) diff --git a/scmos/extract_template/scmosExtDiag.tech.in b/scmos/extract_template/scmosExtDiag.tech.in new file mode 100644 index 00000000..f79503f9 --- /dev/null +++ b/scmos/extract_template/scmosExtDiag.tech.in @@ -0,0 +1,53 @@ +/* DIAGNOSTIC EXTRACTIONS */ + +/* + * The idea here is to simply re-extract caps between nwell and GND + * as a test on whether all wells are plugged (with vdd) + */ +style check_nwell + + lambda 100 + step 100 + + resist nwell 2000000 + areacap nw,nwc,nsd 100 + + + noplaneOrdering /* never do coupling on these styles */ + +style check_pwell + + lambda 100 + step 100 + + resist pwell 2000000 + areacap pw,pwc,psd 100 + + noplaneOrdering + +style check_psubstr +/* The idea here is to simply re-extract caps between + * p_guard_ring and GND as a test + * to verify that the substrate is all contacted to the same ground + * signal (i.e. insure the substrate isn't accidentally a big resistor! + */ + lambda 50 + step 200 + + areacap psd,psc 1000 + + noplaneOrdering + +style check_nsubstr +/* The idea here is to simply re-extract caps between + * n_guard_ring and GND as a test + * to verify that the substrate is all contacted to the same Vcc + * signal (i.e. insure the substrate isn't accidentally a big resistor! + */ + lambda 50 + step 200 + + areacap nsd,nsc 1000 + + noplaneOrdering + diff --git a/scmos/gdsquery.tech.m4 b/scmos/gdsquery.tech.m4 new file mode 100644 index 00000000..e2580cc0 --- /dev/null +++ b/scmos/gdsquery.tech.m4 @@ -0,0 +1,59 @@ +tech + format 28 + gdsquery +end + +version + version 0.1 + description "Minimal technology file for querying an unknown GDS database" +end + +planes +end + +types +end + +contact +end + +styles + styletype mos +end + +compose +end + +connect +end + +cifoutput +style generic + scalefactor 1 +end + +cifinput +style generic + scalefactor 1 +end + +# mzrouter +# end + +drc +end + +extract +end + +# wiring +# end + +# router +# end + +# plowing +# end + +# plot +# end diff --git a/scmos/minimum.tech.m4 b/scmos/minimum.tech.m4 new file mode 100644 index 00000000..412c8f23 --- /dev/null +++ b/scmos/minimum.tech.m4 @@ -0,0 +1,55 @@ +tech + format 28 + minimum +end + +version + version 0.0 + description "Minimum technology file structure" +end + +planes +end + +types +end + +contact +end + +styles + styletype mos +end + +compose +end + +connect +end + +cifoutput +end + +cifinput +end + +# mzrouter +# end + +drc +end + +extract +end + +# wiring +# end + +# router +# end + +# plowing +# end + +# plot +# end diff --git a/scmos/mos.24bit.dstyle b/scmos/mos.24bit.dstyle new file mode 100644 index 00000000..318b0274 --- /dev/null +++ b/scmos/mos.24bit.dstyle @@ -0,0 +1,434 @@ +# +# MOSIS distribution Version 8.2 +# +# This file has been updated by MOSIS to be used for three metal, two poly +# SCMOS technology files. +# +# (C) Copyright 1992, 1993, 1994, 1995 by +# +# Jen-I Pi pi@isi.edu +# The MOSIS Service +# USC Information Sciences Institute +# 4676 Admiralty Way +# Marina del Rey, CA 90292 +# (310) 822-1511 x640 fax (310)823-5624 +# +# All Rights Reserved. +# Last Modified Date: 12/3/03 +# +# Permission to use, copy, modify, and distribute this technology +# file and its associated documentation for any purpose and without +# fee is hereby granted, provided that the above copyright notice +# appears in all copies and that both that copyright notice and this +# permission notice appear in supporting documentation, and that the +# name of the University of Southern California not be used in +# advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. The University of +# Southern California makes no representations about the suitability +# of this technology file for any purpose. This technology file is +# provided "as is" without express or implied warranty and the +# University of Southern California retains the right to change its +# content at any time without notice any other party. +# +# THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS TECHNOLOGY FILE, INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF +# SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS TECHNOLOGY FILE. +# +# This file describes the various display styles that are available +# in Magic. This new file is relatively technology-independent: it +# contains enough different styles to support MOSIS's SCMOS process +# without any changes. Each display style describes a particular +# way of drawing things on the display. See "Magic Maintainer's +# Manual #3: The Display Style and Glyph Files" for details on the +# file format. +# +# Please send bug reports/comments to mosis@mosis.edu :-) +# +# Version keyword replaces the version embedded in the filename. + +version 7 +# +# 24-bit True Color does not use bit planes. The "mask" value is +# irrelevant. +# + +display_styles 24 +# +# The style below means "no color at all". It is special, in that +# it is used by cursors to indicate transparency. +# +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +0 0x00 0 0x00 solid 0 . no_color_at_all +# +# Opaque styles used for drawing and erasing highlights, window borders, +# etc. +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +1 0x20 32 0x00 solid 0 - solid_highlights +2 0x20 32 0x00 stipple 12 - medium_highlights +3 0x20 32 0x00 stipple 9 - pale_highlights +4 0x20 32 0x00 stipple 10 - horiz_highlights +5 0x20 32 0x00 stipple 11 - vert_highlights +6 0x20 32 0xff outline 0 - outline_highlights +7 0x20 32 0xcc outline 0 - dotted_highlights +# +8 0x40 0 0xff outline 0 - erase_box +9 0x7f 0 0x00 solid 0 - erase_highlights +10 0x7f 0 0x00 solid 0 - erase_everything +11 0x3f 0 0x00 solid 0 - erase_all_but_highl +# +12 0x3f 59 0xff outline 0 - labels +13 0x3f 45 0xff outline 0 - ports +14 0x3f 54 0xff outline 0 - port_connections +15 0x3f 35 0xff outline 0 - bounding_boxes +16 0x3f 35 0xaa grid 0 - dotted_grid +17 0x3f 35 0xff grid 0 - solid_grid +18 0x3f 35 0x00 solid 0 - origin_square +19 0x3f 35 0xff outline 0 - draw_tile_details +# +20 0x7f 55 0x00 solid 0 w window_border +21 0x7f 55 0xff stipple 6 - window_elevator +22 0x7f 56 0x00 solid 0 c window_caption +23 0x7f 57 0x00 solid 0 x window_background +# +24 0x7f 58 0x00 solid 0 - color_editing +# +25 0x7f 60 0x00 solid 0 T tk_medium_gray +26 0x7f 62 0x00 solid 0 t tk_light_gray +# +27 0x7f 47 0xff outline 0 - pale_labels +28 0x7f 80 0xff outline 0 - pale_ports +# +# General-purpose opaque colors. These entries define a whole +# bunch of generally-useful colors. +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +29 0x3f 32 0x00 solid 0 W white +30 0x3f 33 0x00 solid 0 - gray1 (pale) +31 0x3f 34 0x00 solid 0 k gray2 (dark) +32 0x3f 35 0x00 solid 0 K black +33 0x3f 36 0x00 solid 0 r red1 (pale) +34 0x3f 37 0x00 solid 0 - red2 (medium) +35 0x3f 38 0x00 solid 0 R red3 (dark) +36 0x3f 39 0x00 solid 0 g green1 (pale) +37 0x3f 40 0x00 solid 0 - green2 (medium) +38 0x3f 41 0x00 solid 0 G green3 (dark) +39 0x3f 42 0x00 solid 0 b blue1 +40 0x3f 43 0x00 solid 0 B blue2 (dark) +41 0x3f 44 0x00 solid 0 - blue3 +42 0x3f 45 0x00 solid 0 p purple1 +43 0x3f 46 0x00 solid 0 P purple2 +44 0x3f 47 0x00 solid 0 y yellow1 +45 0x3f 48 0x00 solid 0 Y yellow2 +46 0x3f 49 0x00 solid 0 o orange1 +47 0x3f 50 0x00 solid 0 O orange2 +48 0x3f 51 0x00 solid 0 - brown1 +49 0x3f 52 0x00 solid 0 - brown2 +50 0x3f 53 0x00 solid 0 - magenta +51 0x3f 54 0x00 solid 0 C cyan +# +#---------------------------------------------------------------------- +# All of the styles above this point are used internally by Magic for +# things like menus, drawing the box, etc. The style numbers must +# match the definitions in misc/style.h. All of the styles below +# this point are used by the technology file, addressed by number. +# Note that the numbers are only for backwards compatibility with +# .tech27 files which specify styles by number. .tech28 files may +# specify styles by name, and numbers may be listed out of order. +# The order in which styles are drawn is the order in which they +# appear in this file. +#---------------------------------------------------------------------- + +layout_styles +# +# Poly-diff styles: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +1 0x07 1 0x00 solid 0 - polysilicon +87 0x07 50 0x00 solid 0 - poly_light +88 0x07 1 0x00 stipple 1 - obspoly +2 0x07 2 0x00 solid 0 - ndiffusion +69 0x07 40 0x00 solid 0 - mvndiff +70 0x07 41 0x00 solid 0 - hvndiff +71 0x07 44 0x00 solid 0 - ncontact +3 0x07 2 0x00 stipple 13 - ndiff_in_nwell +4 0x07 3 0x00 solid 0 - pdiffusion +72 0x07 51 0x00 solid 0 - mvpdiff +73 0x07 52 0x00 solid 0 - hvpdiff +74 0x07 45 0x00 solid 0 - pcontact +5 0x07 3 0x00 stipple 13 - pdiff_in_pwell +6 0x07 4 0x00 solid 0 - ntransistor +7 0x07 2 0x00 stipple 7 - ntransistor_stripes +8 0x07 5 0x00 solid 0 - ptransistor +9 0x07 3 0x00 stipple 5 - ptransistor_stripes +79 0x07 71 0x00 stipple 21 - highvolt_nwell +80 0x07 69 0x00 stipple 22 - highvolt_pwell +83 0x3f 51 0x00 stipple 5 - implant1 +84 0x3f 48 0x00 stipple 5 - implant2 +85 0x3f 38 0x00 stipple 5 - implant3 +86 0x3f 32 0x00 stipple 5 - implant4 +10 0x3f 6 0x00 stipple 7 - cwell +11 0x07 5 0x00 stipple 22 - hvndiff_mask +12 0x07 7 0x00 stipple 7 - nwell +13 0x07 3 0x00 stipple 5 - pwell +14 0x3f 6 0x00 stipple 2 - electrode +15 0x07 3 0x00 stipple 10 - pbase +16 0x07 2 0x00 stipple 17 - emitter +17 0x07 3 0x00 stipple 11 - bccd +18 0x07 4 0x00 stipple 21 - hvpdiff_mask +19 0x07 7 0x00 solid 0 - via +# +# Metal styles: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +20 0x08 8 0x00 stipple 16 - metal1 +21 0x10 16 0x00 stipple 12 - metal2 +22 0x3f 53 0x00 stipple 23 - metal3 +23 0x3f 33 0x00 stipple 20 - metal4 +24 0x3f 44 0x00 stipple 8 - metal5 +25 0x3f 37 0x00 solid 0 - pad4 +26 0x0f 9 0x00 solid 0 - poly_contact +27 0x07 1 0x00 solid 0 - electrode_stripes +28 0x3f 6 0x00 stipple 2 - capacitor +29 0x08 8 0x00 stipple 16 - metal1_alt +# +# Opaque stipples and such for mask display: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +30 0x3f 2 0x00 stipple 22 - ndop_stripes +31 0x3f 3 0x00 stipple 21 - pdop_stripes +35 0x3f 3 0xff stipple 1 - pselect +36 0x3f 2 0xff stipple 15 - nselect +37 0x3f 35 0xff stipple 19 - via2 +38 0x3f 35 0xff stipple 4 - via3 +39 0x3f 35 0xff stipple 5 - via4 +# +40 0x3f 53 0x00 stipple 5 - check_paint +41 0x3f 54 0x00 stipple 7 - check_subcells +42 0x3f 32 0x00 stipple 4 - error_waffle +# +43 0x07 2 0x00 stipple 5 - nselect2 +44 0x07 3 0x00 stipple 7 - pselect2 +45 0x07 35 0x00 solid 0 - comment +46 0x07 42 0x00 stipple 7 - silicide_block +47 0x07 1 0x00 solid 0 - poly_resist +48 0x07 3 0x00 stipple 7 - poly_resist_stripes +49 0x08 8 0x00 stipple 19 - metal1tight +89 0x08 8 0x00 stipple 1 - obsmetal1 +50 0x10 16 0x00 stipple 19 - metal2tight +90 0x10 16 0x00 stipple 1 - obsmetal2 +51 0x3f 53 0x00 stipple 8 - metal3tight +91 0x3f 53 0x00 stipple 1 - obsmetal3 +92 0x3f 33 0x00 stipple 1 - obsmetal4 +93 0x3f 44 0x00 stipple 1 - obsmetal5 +52 0x07 2 0x00 stipple 19 - cwellnsc +53 0x07 7 0x00 stipple 7 - nwell_field_implant +54 0x07 7 0x00 stipple 5 - substrate_field_implant +55 0x3f 43 0xff stipple 35 - via1arrow +81 0x3f 43 0xff stipple 2 - via1 +56 0x3f 53 0xff stipple 36 - via2arrow +82 0x3f 53 0xff stipple 2 - via2alt +57 0x3f 6 0xff stipple 2 - via3alt +58 0x3f 7 0x00 solid 0 - gen_contact +32 0x3f 35 0xff cross 0 - contact_X'es +33 0x3f 35 0xff stipple 2 - contact_waffle +# +64 0x3f 46 0x00 stipple 8 - metal6 +94 0x3f 46 0x00 stipple 1 - obsmetal6 +59 0x3f 32 0xff stipple 2 - via5 +65 0x3f 38 0x00 stipple 9 - metal7 +95 0x3f 38 0x00 stipple 1 - obsmetal7 +60 0x3f 46 0xff stipple 28 - via6 +66 0x3f 34 0x00 stipple 16 - metal8 +96 0x3f 34 0x00 stipple 1 - obsmetal8 +61 0x3f 51 0xff stipple 29 - via7 +75 0x3f 74 0x00 stipple 8 - metal9 +97 0x3f 74 0x00 stipple 1 - obsmetal9 +76 0x3f 7 0xff stipple 30 - via8 +77 0x3f 75 0x00 stipple 9 - metal10 +98 0x3f 75 0x00 stipple 1 - obsmetal10 +78 0x3f 7 0xff stipple 31 - via9 +# +62 0x3f 0 0x00 solid 0 - mim_bottom +63 0x3f 0 0x00 solid 0 - mim_top +34 0x3f 34 0xff stipple 10 - overglass +67 0x3f 9 0x00 outline 0 - subcircuit +68 0x3f 34 0xff stipple 12 - mems +# +#------------------------------------------------------------------ +# All of the styles below this point must duplicate the styles in +# the section above, and represent a version of each previous +# layer to use in non-edit cells ("pale" styles): +#------------------------------------------------------------------ + +pale_styles +# +# Poly-diff styles: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +1 0x07 1 0x00 stipple 14 - polysilicon +87 0x07 49 0x00 solid 0 - poly_light +88 0x07 1 0x00 stipple 1 - obspoly +2 0x07 2 0x00 stipple 14 - ndiffusion +69 0x07 40 0x00 stipple 3 - mvndiff +70 0x07 41 0x00 stipple 3 - hvndiff +71 0x07 44 0x00 stipple 3 - ncontact +3 0x07 2 0x00 stipple 13 - ndiff_in_nwell +4 0x07 3 0x00 stipple 14 - pdiffusion +72 0x07 51 0x00 stipple 25 - mvpdiff +73 0x07 52 0x00 stipple 25 - hvpdiff +74 0x07 45 0x00 stipple 25 - pcontact +5 0x07 3 0x00 stipple 13 - pdiff_in_pwell +6 0x07 4 0x00 stipple 14 - ntransistor +7 0x07 2 0x00 stipple 7 - ntransistor_stripes +8 0x07 5 0x00 stipple 14 - ptransistor +9 0x07 3 0x00 stipple 5 - ptransistor_stripes +79 0x07 71 0x00 stipple 21 - highvolt_nwell +80 0x07 69 0x00 stipple 22 - highvolt_pwell +83 0x3f 51 0x00 stipple 5 - implant1 +84 0x3f 48 0x00 stipple 5 - implant2 +85 0x3f 38 0x00 stipple 5 - implant3 +86 0x3f 32 0x00 stipple 5 - implant4 +10 0x07 6 0x00 stipple 7 - cwell +11 0x07 5 0x00 stipple 22 - hvndiff_mask +12 0x07 7 0x00 stipple 7 - nwell +13 0x07 3 0x00 stipple 5 - pwell +14 0x3f 6 0x00 stipple 2 - electrode +15 0x07 3 0x00 stipple 10 - pbase +16 0x07 2 0x00 stipple 17 - emitter +17 0x07 3 0x00 stipple 11 - bccd +18 0x07 7 0x00 stipple 21 - hvpdiff_mask +19 0x07 7 0x00 stipple 2 - via +# +# Metal styles: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +20 0x08 8 0x00 stipple 16 - metal1 +21 0x10 16 0x00 stipple 12 - metal2 +22 0x3f 53 0x00 stipple 5 - metal3 +23 0x3f 33 0x00 stipple 21 - metal4 +24 0x07 44 0x00 stipple 22 - metal5 +25 0x07 37 0x00 stipple 18 - pad4 +26 0x07 9 0x00 stipple 6 - poly_contact +27 0x07 3 0x00 stipple 9 - electrode_stripes +28 0x07 61 0x00 stipple 2 - capacitor +29 0x08 8 0x00 stipple 16 - metal1_alt +# +# Opaque stipples and such for mask display: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +30 0x3f 2 0x00 stipple 22 - ndop_stripes +31 0x3f 3 0x00 stipple 21 - pdop_stripes +35 0x3f 3 0xff stipple 1 - pselect +36 0x3f 2 0xff stipple 15 - nselect +37 0x3f 35 0xff stipple 19 - via2 +38 0x3f 35 0xff stipple 4 - via3 +39 0x3f 35 0xff stipple 5 - via4 +# +40 0x3f 53 0x00 stipple 5 - check_paint +41 0x3f 54 0x00 stipple 7 - check_subcells +42 0x3f 32 0x00 stipple 4 - error_waffle +# +43 0x07 2 0x00 stipple 5 - nselect2 +44 0x07 3 0x00 stipple 7 - pselect2 +45 0x07 15 0x00 solid 0 - comment +46 0x07 42 0x00 stipple 7 - silicide_block +47 0x07 1 0x00 solid 0 - poly_resist +48 0x07 3 0x00 stipple 7 - poly_resist_stripes +49 0x08 8 0x00 stipple 14 - metal1tight +89 0x08 8 0x00 stipple 1 - obsmetal1 +50 0x10 16 0x00 stipple 5 - metal2tight +90 0x10 16 0x00 stipple 1 - obsmetal2 +51 0x3f 53 0x00 stipple 21 - metal3tight +91 0x3f 53 0x00 stipple 1 - obsmetal3 +92 0x3f 33 0x00 stipple 1 - obsmetal4 +93 0x3f 44 0x00 stipple 1 - obsmetal5 +52 0x07 2 0x00 stipple 13 - cwellnsc +53 0x07 7 0x00 stipple 7 - nwell_field_implant +54 0x07 7 0x00 stipple 5 - substrate_field_implant +55 0x3f 43 0xff stipple 35 - via1arrow +81 0x3f 43 0xff stipple 2 - via1 +56 0x3f 53 0xff stipple 36 - via2arrow +82 0x3f 53 0xff stipple 2 - via2alt +57 0x3f 6 0xff stipple 2 - via3alt +58 0x3f 34 0x00 stipple 1 - gen_contact +32 0x3f 35 0xff cross 0 - contact_X'es +33 0x3f 35 0xff stipple 2 - contact_waffle +# +64 0x3f 46 0x00 stipple 7 - metal6 +94 0x3f 46 0x00 stipple 1 - obsmetal6 +59 0x3f 16 0xff stipple 2 - via5 +65 0x3f 38 0x00 stipple 5 - metal7 +95 0x3f 38 0x00 stipple 1 - obsmetal7 +60 0x3f 46 0xff stipple 28 - via6 +66 0x3f 34 0x00 stipple 10 - metal8 +96 0x3f 34 0x00 stipple 1 - obsmetal8 +61 0x3f 51 0xff stipple 29 - via7 +75 0x3f 76 0x00 stipple 8 - metal9 +97 0x3f 74 0x00 stipple 1 - obsmetal9 +76 0x3f 34 0xff stipple 30 - via8 +77 0x3f 76 0x00 stipple 9 - metal10 +98 0x3f 75 0x00 stipple 1 - obsmetal10 +78 0x3f 34 0xff stipple 31 - via9 +# +62 0x3f 0 0x00 solid 0 - mim_bottom +63 0x3f 0 0x00 solid 0 - mim_top +34 0x3f 34 0xff stipple 10 - overglass +67 0x3f 9 0x00 outline 0 - subcircuit +68 0x3f 33 0x00 stipple 12 - mems +# + +stipples +#-----------------------------------+--------------------------------------- +# hex bit pattern (8x8) description +#-----------------------------------+--------------------------------------- +1 40 00 18 00 18 00 00 00 very sparsed stripes, ll to ur +2 cc cc 00 00 33 33 00 00 coarse knight's move (waffle) +3 ee 77 bb dd ee 77 bb dd all but diagonal stripes, ll to ur +4 00 00 cc cc 00 00 cc cc offset waffle +5 40 20 10 08 04 02 01 80 sparse diagonal stripes, ll to ur +6 aa 55 aa 55 aa 55 aa 55 half 'n half (checkerboard) +7 02 04 08 10 20 40 80 01 sparse diagonal stripes, lr to ul +8 81 03 06 0c 18 30 60 c0 wide sparse diagonal stripes, lr to ul +9 81 c0 60 30 18 0c 06 03 wide sparse diagonal stripes, ll to ur +10 00 00 00 ff 00 00 00 ff horizontal stripes +11 44 44 44 44 44 44 44 44 vertical stripes +12 55 aa 55 aa 55 aa 55 aa complement of half `n half +13 33 33 ff ff cc cc ff ff complement of #2 (coarse knight's move) +14 aa 55 aa 55 aa 55 aa 55 half 'n half (checkerboard) +15 00 01 00 18 00 00 00 18 very sparsed stripes, 11 to ur +16 c0 07 ff ff c0 07 ff ff wide horizontal stripes +17 c7 c7 c7 c7 c7 c7 c7 c7 wide vertical stripes +18 7c 7c 7c 7c 7c 7c 7c 7c wide vertical stripes (reverse of 17) +19 3c c3 42 42 c3 3c 24 24 bubbles +20 24 42 81 81 42 24 18 18 offset diagonal crossex +21 10 20 00 00 00 02 04 08 diagonal dotted line, lr to ul +22 08 04 00 00 00 40 20 10 diagonal dotted line, ll to ur +23 3c 66 c3 81 c3 66 3c 18 dense diagonal crossex +24 c3 3c bd bd 3c c3 db db complement of #19 empty bubbles +25 dd bb 77 ee dd bb 77 ee all but diagonal stripes, lr to ul +26 e2 4e 52 29 94 e4 8e 11 T pattern +27 71 47 41 00 42 72 47 99 sparse offset T pattern +28 99 3c 7e e7 e7 7e 3c 99 alternating diamonds +29 44 88 55 22 44 88 55 22 bricks, ll to ur +30 30 60 c0 c1 63 36 1c 18 bricks, lr to ul +31 55 db 22 db 55 db 22 db linoleum +32 60 c0 81 03 06 0c 18 30 +33 00 00 00 30 60 60 30 00 new gc thin +34 00 02 06 0e 0e 06 02 00 +35 00 7e 3c 18 00 e7 c3 81 arrows pointing up +36 e0 62 26 0e 0e 26 62 e0 arrows pointing left diff --git a/scmos/mos.24bit.std.cmap b/scmos/mos.24bit.std.cmap new file mode 100644 index 00000000..9ae00880 --- /dev/null +++ b/scmos/mos.24bit.std.cmap @@ -0,0 +1,73 @@ +#--------------------------------------- +# Colormap file for X11, 24-bit graphics +#--------------------------------------- +# R G B idx color-name +#--------------------------------------- +200 200 200 0 background_gray +220 95 95 1 poly_red +66 213 66 2 diff_green +202 160 115 3 diff_brown +169 131 101 4 nfet_brown +184 73 83 5 pfet_brown +230 230 0 6 well_yellow +0 0 0 7 contact_black +125 166 250 8 metal_blue +160 48 191 9 pc_purple +190 153 222 16 metal_purple +255 255 255 32 cursor_white +170 170 170 33 pale_gray +145 145 145 34 dark_gray +0 0 0 35 box_black +239 188 198 36 pale_red +239 125 162 37 medium_red +210 0 155 38 dark_red +165 216 175 39 pale_green +124 191 148 40 medium_green +0 181 0 41 dark_green +170 202 242 42 light_blue +0 0 250 43 dark_blue +40 169 166 44 teal_blue +45 94 179 45 deep_purple +167 0 200 46 bright_purple +255 248 179 47 light_yellow +255 255 0 48 bright_yellow +235 198 160 49 yellow_orange +234 132 73 50 medium_orange +198 152 0 51 ochre_brown +139 108 0 52 medium_brown +255 119 202 53 bright_pink +50 228 225 54 port_cyan +120 81 29 55 border_brown +200 230 230 56 caption_blue +180 210 180 57 window_gray +0 0 0 58 +246 246 7 59 label_yellow +180 180 180 60 medium_gray +230 180 50 61 pale_orange +235 235 235 62 light_gray +255 255 255 64 white +210 148 148 65 deep_pink +133 206 133 66 pale_green +201 170 157 67 peach_gray +184 165 150 68 gray_brown +192 136 141 69 rosy_brown +215 215 100 70 pale_ochre +130 130 130 71 gray50 +163 183 225 72 steel_blue +180 124 196 73 medium_purple +137 210 179 74 pale_teal +200 185 255 75 bright_lavender +169 213 198 76 pale_cyan +210 210 230 77 pale_steel +195 176 211 80 pale_purple +185 185 185 97 gray75 +160 160 160 98 gray62 +100 100 100 99 gray40 +220 163 181 101 pale_pink +220 120 200 102 medium_pink +80 175 80 105 sea_green +175 115 175 110 deep_lavender +215 170 90 115 medium_tan +228 160 201 117 light_lavender +215 190 125 125 light_tan +0 0 0 255 diff --git a/scmos/mos.7bit.dstyle b/scmos/mos.7bit.dstyle new file mode 100644 index 00000000..a2766401 --- /dev/null +++ b/scmos/mos.7bit.dstyle @@ -0,0 +1,474 @@ +# +# MOSIS distribution Version 8.2 +# +# jws 1997/06/26: added new styles for m1t-m3t (49-51) +# tim 2002/12/19: redesigned format to eliminate 256 style limit +# +# This file has been updated by MOSIS to be used for three metal, two poly +# SCMOS technology files. +# +# (C) Copyright 1992, 1993, 1994, 1995 by +# +# Jen-I Pi pi@isi.edu +# The MOSIS Service +# USC Information Sciences Institute +# 4676 Admiralty Way +# Marina del Rey, CA 90292 +# (310) 822-1511 x640 fax (310)823-5624 +# +# All Rights Reserved. +# Last Modified Date: 12/03/03 +# +# Permission to use, copy, modify, and distribute this technology +# file and its associated documentation for any purpose and without +# fee is hereby granted, provided that the above copyright notice +# appears in all copies and that both that copyright notice and this +# permission notice appear in supporting documentation, and that the +# name of the University of Southern California not be used in +# advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. The University of +# Southern California makes no representations about the suitability +# of this technology file for any purpose. This technology file is +# provided "as is" without express or implied warranty and the +# University of Southern California retains the right to change its +# content at any time without notice any other party. +# +# THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS TECHNOLOGY FILE, INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF +# SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS TECHNOLOGY FILE. +# +# This file describes the various display styles that are available +# in Magic. This new file is relatively technology-independent: it +# contains enough different styles to support MOSIS's SCMOS process +# without any changes. Each display style describes a particular +# way of drawing things on the display. See "Magic Maintainer's +# Manual #3: The Display Style and Glyph Files" for details on the +# file format. +# +# Please send bug reports/comments to mosis@mosis.edu :-) +# +# Version keyword replaces the version embedded in the filename. + +version 7 +# +# BitPlane Usage: +# +# +# msb lsb +# +-------+-----------+-----------+ +# | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | +# +-------+-----------+-----------+ +# | | | | | \_______/ +# not used -+ | | | | | +# highlights ---+ | | | +---- poly, diff, fets +# opaque/trans. ----+ | +------------ metal1 +# +---------------- metal2 +# +# Bits 0-2 represent the material on the poly-diff plane (poly, +# different flavors of diffusion, different flavors of transistor) +# with mutually-opaque colors. +# +# Bits 3-4 are used for the two metal layers. Each layer has a +# separate bit plane, so the two metal layers are mutually transparent, +# and they are both transparent with respect to the poly-diff layers. +# +# If bit 5 is set, then bits 0-4 are used for one of 32 opaque colors +# which override any other mask information. These colors are used +# for various stipples, contact crosses, etc. They also provide a +# palette of standard colors (red, green, etc.) for use in making +# window borders, menus, etc. The last of these colors to be drawn in +# an area is the one that will appear. +# +# Bit 6 is used for highlights such as the box, the selection, etc. +# It overrides any of the other bits and produces a pure white color. +# +# Bit 7 is not used in this display style file. This is important for +# Sun workstations, since they can't really give Magic all 8 bits. +# For AEDs and other displays, this is a bit wasteful, but still seems +# to work ok. + +display_styles 7 +# +# The style below means "no color at all". It is special, in that +# it is used by cursors to indicate transparency. +# +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +0 0x00 000 0x00 solid 0 . no_color_at_all +# +# Opaque styles used for drawing and erasing highlights, window borders, +# etc. +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +1 0x40 64 0x00 solid 0 - solid_highlights +2 0x40 64 0x00 stipple 12 - medium_highlights +3 0x40 64 0x00 stipple 9 - pale_highlights +4 0x40 64 0x00 stipple 10 - horiz_highlights +5 0x40 64 0x00 stipple 11 - vert_highlights +6 0x40 64 0xff outline 0 - outline_highlights +7 0x40 64 0xcc outline 0 - dotted_highlights +# +8 0x40 0 0xff outline 0 - erase_box +9 0x40 0 0x00 solid 0 - erase_highlights +10 0x7f 0 0x00 solid 0 - erase_everything +11 0x3f 0 0x00 solid 0 - erase_all_but_highl +# +12 0x3f 59 0xff outline 0 - labels +13 0x3f 45 0xff outline 0 - ports +14 0x3f 54 0xff outline 0 - port_connections +15 0x3f 35 0xff outline 0 - bounding_boxes +16 0x3f 35 0xaa grid 0 - dotted_grid +17 0x3f 35 0xff grid 0 - solid_grid +18 0x3f 35 0x00 solid 0 - origin_square +19 0x3f 35 0xff outline 0 - draw_tile_details +# +20 0x7f 55 0x00 solid 0 w window_border +21 0x7f 55 0xff stipple 6 - window_elevator +22 0x7f 56 0x00 solid 0 c window_caption +23 0x7f 57 0x00 solid 0 x window_background +# +24 0x7f 58 0x00 solid 0 - color_editing +# +25 0x7f 60 0x00 solid 0 T tk_medium_gray +26 0x7f 62 0x00 solid 0 t tk_light_gray +# +27 0x7f 47 0xff outline 0 - pale_labels +28 0x7f 53 0xff outline 0 - pale_ports +# +# +# General-purpose opaque colors. These entries define a whole +# bunch of generally-useful colors. +# +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +29 0x3f 32 0x00 solid 0 W white +30 0x3f 33 0x00 solid 0 - gray1 (pale) +31 0x3f 34 0x00 solid 0 k gray2 (dark) +32 0x3f 35 0x00 solid 0 K black +33 0x3f 36 0x00 solid 0 r red1 (pale) +34 0x3f 37 0x00 solid 0 - red2 (medium) +35 0x3f 38 0x00 solid 0 R red3 (dark) +36 0x3f 39 0x00 solid 0 g green1 (pale) +37 0x3f 40 0x00 solid 0 - green2 (medium) +38 0x3f 41 0x00 solid 0 G green3 (dark) +39 0x3f 42 0x00 solid 0 b blue1 +40 0x3f 43 0x00 solid 0 B blue2 (dark) +41 0x3f 44 0x00 solid 0 - blue3 +42 0x3f 45 0x00 solid 0 p purple1 +43 0x3f 46 0x00 solid 0 P purple2 +44 0x3f 47 0x00 solid 0 y yellow1 +45 0x3f 48 0x00 solid 0 Y yellow2 +46 0x3f 49 0x00 solid 0 o orange1 +47 0x3f 50 0x00 solid 0 O orange2 +48 0x3f 51 0x00 solid 0 - brown1 +49 0x3f 52 0x00 solid 0 - brown2 +50 0x3f 53 0x00 solid 0 - magenta +51 0x3f 54 0x00 solid 0 C cyan +# +#---------------------------------------------------------------------- +# All of the styles above this point are used internally by Magic for +# things like menus, drawing the box, etc. The style numbers must +# match the definitions in misc/style.h. All of the styles below +# this point are used by the technology file, addressed by number. +# Note that the numbers are only for backwards compatibility with +# .tech27 files which specify styles by number. .tech28 files may +# specify styles by name, and numbers may be listed out of order. +# The order in which styles are drawn is the order in which they +# appear in this file. +#---------------------------------------------------------------------- + +layout_styles +# +# Poly-diff styles: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +1 0x07 1 0x00 solid 0 - polysilicon +87 0x07 50 0x00 solid 0 - poly_light +88 0x07 1 0x00 stipple 1 - obspoly +2 0x07 2 0x00 solid 0 - ndiffusion +3 0x07 2 0x00 stipple 13 - ndiff_in_nwell +4 0x07 3 0x00 solid 0 - pdiffusion +5 0x07 3 0x00 stipple 13 - pdiff_in_pwell +6 0x07 4 0x00 solid 0 - ntransistor +7 0x07 2 0x00 stipple 7 - ntransistor_stripes +8 0x07 5 0x00 solid 0 - ptransistor +9 0x07 3 0x00 stipple 5 - ptransistor_stripes +10 0x3f 6 0x00 stipple 7 - cwell +11 0x07 5 0x00 stipple 22 - hvndiff_mask +12 0x07 7 0x00 stipple 7 - nwell +13 0x07 3 0x00 stipple 5 - pwell +79 0x07 71 0x00 stipple 21 - highvolt_nwell +80 0x07 69 0x00 stipple 22 - highvolt_pwell +83 0x3f 51 0x00 stipple 5 - implant1 +84 0x3f 48 0x00 stipple 5 - implant2 +85 0x3f 38 0x00 stipple 5 - implant3 +86 0x3f 62 0x00 stipple 5 - implant4 +14 0x3f 6 0x00 stipple 2 - electrode +15 0x07 3 0x00 stipple 10 - pbase +16 0x07 2 0x00 stipple 17 - emitter +17 0x07 3 0x00 stipple 11 - bccd +18 0x07 4 0x00 stipple 21 - hvpdiff_mask +19 0x07 7 0x00 solid 0 - via +# +# Metal styles: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +20 0x08 8 0x00 solid 0 - metal1 +21 0x10 16 0x00 solid 0 - metal2 +22 0x3f 53 0x00 stipple 23 - metal3 +23 0x3f 33 0x00 stipple 20 - metal4 +24 0x3f 44 0x00 stipple 8 - metal5 +25 0x3f 37 0x00 solid 0 - pad4 +26 0x0f 9 0x00 solid 0 - poly_contact +27 0x07 1 0x00 solid 0 - electrode_stripes +28 0x3f 6 0x00 stipple 2 - capacitor +29 0x08 8 0x00 solid 0 - metal1_alt +# +# Opaque stipples and such for mask display: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +30 0x3f 2 0x00 stipple 22 - ndop_stripes +31 0x3f 3 0x00 stipple 21 - pdop_stripes +32 0x3f 7 0xff cross 0 - contact_X'es +33 0x3f 7 0xff stipple 2 - contact_waffle +34 0x3f 34 0xff stipple 10 - overglass +35 0x3f 3 0xff stipple 1 - pselect +36 0x3f 2 0xff stipple 15 - nselect +37 0x3f 46 0xff stipple 19 - via2 +38 0x3f 38 0xff stipple 24 - via3 +39 0x3f 41 0xff stipple 5 - via4 +# +40 0x3f 53 0x00 stipple 5 - check_paint +41 0x3f 54 0x00 stipple 7 - check_subcells +42 0x3f 32 0x00 stipple 4 - error_waffle +43 0x07 2 0x00 stipple 5 - nselect2 +44 0x07 3 0x00 stipple 7 - pselect2 +45 0x07 35 0x00 solid 0 - comment +46 0x07 42 0x00 stipple 7 - silicide_block +47 0x07 1 0x00 solid 0 - poly_resist +48 0x07 3 0x00 stipple 7 - poly_resist_stripes +#jws +49 0x08 8 0x00 stipple 19 - metal1tight +89 0x08 8 0x00 stipple 1 - obsmetal1 +50 0x10 16 0x00 stipple 19 - metal2tight +90 0x10 16 0x00 stipple 1 - obsmetal2 +51 0x3f 53 0x00 stipple 8 - metal3tight +91 0x3f 53 0x00 stipple 1 - obsmetal3 +92 0x3f 33 0x00 stipple 1 - obsmetal4 +93 0x3f 44 0x00 stipple 1 - obsmetal5 +52 0x07 2 0x00 stipple 19 - cwellnsc +53 0x07 7 0x00 stipple 7 - nwell_field_implant +54 0x07 7 0x00 stipple 5 - substrate_field_implant +55 0x3f 43 0xff stipple 35 - via1arrow +81 0x3f 43 0xff stipple 2 - via1 +56 0x3f 53 0xff stipple 36 - via2arrow +82 0x3f 53 0xff stipple 2 - via2alt +57 0x3f 6 0xff stipple 2 - via3alt +58 0x3f 7 0x00 solid 0 - gen_contact +# +59 0x3f 16 0xff stipple 2 - via5 +60 0x3f 46 0xff stipple 28 - via6 +61 0x3f 51 0xff stipple 29 - via7 +76 0x3f 7 0xff stipple 30 - via8 +78 0x3f 7 0xff stipple 31 - via9 +# +64 0x3f 46 0x00 stipple 17 - metal6 +94 0x3f 46 0x00 stipple 1 - obsmetal6 +65 0x3f 38 0x00 stipple 9 - metal7 +95 0x3f 38 0x00 stipple 1 - obsmetal7 +66 0x3f 34 0x00 stipple 16 - metal8 +96 0x3f 34 0x00 stipple 1 - obsmetal8 +75 0x3f 40 0x00 stipple 26 - metal9 +97 0x3f 40 0x00 stipple 1 - obsmetal9 +77 0x3f 42 0x00 stipple 23 - metal10 +98 0x3f 42 0x00 stipple 1 - obsmetal10 +# +62 0x3f 0 0x00 solid 0 - mim_bottom +63 0x3f 0 0x00 solid 0 - mim_top +67 0x07 9 0x00 outline 0 - subcircuit +68 0x3f 34 0xff stipple 12 - mems +# +69 0x3f 40 0x00 stipple 3 - mvndiff +70 0x3f 41 0x00 stipple 3 - hvndiff +71 0x3f 44 0x00 stipple 3 - ncontact +72 0x3f 51 0x00 solid 25 - mvpdiff +73 0x3f 52 0x00 solid 25 - hvpdiff +74 0x3f 45 0x00 solid 25 - pcontact +# +#---------------------------------------------------------------------- +# All of the styles below this point must duplicate the styles in +# the section above, and represent a version of each previous +# layer to use in non-edit cells ("pale" styles): +#---------------------------------------------------------------------- + +pale_styles +# +# Poly-diff styles: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +1 0x07 1 0x00 stipple 14 - polysilicon +87 0x07 49 0x00 solid 0 - poly_light +88 0x07 1 0x00 stipple 1 - obspoly +2 0x07 2 0x00 stipple 14 - ndiffusion +3 0x07 2 0x00 stipple 13 - ndiff_in_nwell +4 0x07 3 0x00 stipple 14 - pdiffusion +5 0x07 3 0x00 stipple 13 - pdiff_in_pwell +6 0x07 4 0x00 stipple 14 - ntransistor +7 0x07 2 0x00 stipple 7 - ntransistor_stripes +8 0x07 5 0x00 stipple 14 - ptransistor +9 0x07 3 0x00 stipple 5 - ptransistor_stripes +10 0x07 6 0x00 stipple 7 - cwell +11 0x07 5 0x00 stipple 22 - hvndiff_mask +12 0x07 7 0x00 stipple 7 - nwell +13 0x07 3 0x00 stipple 5 - pwell +79 0x07 71 0x00 stipple 21 - highvolt_nwell +80 0x07 69 0x00 stipple 22 - highvolt_pwell +83 0x3f 51 0x00 stipple 5 - implant1 +84 0x3f 48 0x00 stipple 5 - implant2 +85 0x3f 38 0x00 stipple 5 - implant3 +86 0x3f 62 0x00 stipple 5 - implant4 +14 0x3f 6 0x00 stipple 2 - electrode +15 0x07 3 0x00 stipple 10 - pbase +16 0x07 2 0x00 stipple 17 - emitter +17 0x07 3 0x00 stipple 11 - bccd +18 0x07 7 0x00 stipple 21 - hvpdiff_mask +19 0x07 7 0x00 stipple 2 - via +# +# Metal styles: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +20 0x08 8 0x00 stipple 14 - metal1 +21 0x10 16 0x00 stipple 14 - metal2 +22 0x3f 53 0x00 stipple 5 - metal3 +23 0x3f 33 0x00 stipple 21 - metal4 +24 0x3f 44 0x00 stipple 22 - metal5 +25 0x3f 37 0x00 stipple 18 - pad4 +26 0x09 9 0x00 stipple 14 - poly_contact +27 0x07 1 0x00 stipple 14 - electrode_stripes +28 0x3f 6 0x00 stipple 2 - capacitor +29 0x08 8 0x00 stipple 14 - metal1_alt +# +# Opaque stipples and such for mask display: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +30 0x3f 2 0x00 stipple 22 - ndop_stripes +31 0x3f 3 0x00 stipple 21 - pdop_stripes +32 0x3f 35 0xff cross 0 - contact_X'es +33 0x3f 35 0xff stipple 2 - contact_waffle +34 0x3f 34 0xff stipple 10 - overglass +35 0x3f 3 0xff stipple 1 - pselect +36 0x3f 2 0xff stipple 15 - nselect +37 0x3f 46 0xff stipple 19 - via2 +38 0x3f 38 0xff stipple 24 - via3 +39 0x3f 41 0xff stipple 5 - via4 +# +40 0x3f 53 0x00 stipple 5 - check_paint +41 0x3f 54 0x00 stipple 7 - check_subcells +42 0x3f 32 0x00 stipple 4 - error_waffle +43 0x07 2 0x00 stipple 5 - nselect2 +44 0x07 3 0x00 stipple 7 - pselect2 +45 0x07 15 0x00 solid 0 - comment +46 0x07 42 0x00 stipple 7 - silicide_block +47 0x07 1 0x00 solid 0 - poly_resist +48 0x07 3 0x00 stipple 7 - poly_resist_stripes +#jws: +49 0x08 8 0x00 stipple 14 - metal1tight +89 0x08 8 0x00 stipple 1 - obsmetal1 +50 0x10 16 0x00 stipple 5 - metal2tight +90 0x10 16 0x00 stipple 1 - obsmetal2 +51 0x3f 53 0x00 stipple 21 - metal3tight +91 0x3f 53 0x00 stipple 1 - obsmetal3 +92 0x3f 33 0x00 stipple 1 - obsmetal4 +93 0x3f 44 0x00 stipple 1 - obsmetal5 +52 0x07 2 0x00 stipple 13 - cwellnsc +53 0x07 7 0x00 stipple 7 - nwell_field_implant +54 0x07 7 0x00 stipple 5 - substrate_field_implant +55 0x3f 43 0x00 stipple 35 - via1arrow +81 0x3f 43 0x00 stipple 2 - via1 +56 0x3f 53 0x00 stipple 36 - via2arrow +82 0x3f 53 0x00 stipple 2 - via2 +57 0x3f 6 0x00 stipple 2 - via3 +58 0x3f 34 0x00 stipple 6 - gen_contact +# +59 0x3f 16 0xff stipple 2 - via5 +60 0x3f 46 0xff stipple 28 - via6 +61 0x3f 51 0xff stipple 29 - via7 +76 0x3f 34 0xff stipple 30 - via8 +78 0x3f 34 0xff stipple 31 - via9 +# +64 0x3f 46 0x00 stipple 11 - metal6 +94 0x3f 46 0x00 stipple 1 - obsmetal6 +65 0x3f 38 0x00 stipple 5 - metal7 +95 0x3f 38 0x00 stipple 1 - obsmetal7 +66 0x3f 34 0x00 stipple 10 - metal8 +96 0x3f 34 0x00 stipple 1 - obsmetal8 +75 0x3f 40 0x00 stipple 27 - metal9 +97 0x3f 40 0x00 stipple 1 - obsmetal9 +77 0x3f 42 0x00 stipple 20 - metal10 +98 0x3f 42 0x00 stipple 1 - obsmetal10 +# +62 0x3f 0 0x00 solid 0 - mim_bottom +63 0x3f 0 0x00 solid 0 - mim_top +67 0x07 9 0x00 outline 0 - subcircuit +68 0x3f 33 0xff stipple 12 - mems +# +69 0x3f 40 0x00 stipple 5 - mvndiff +70 0x3f 41 0x00 stipple 5 - hvndiff +71 0x3f 44 0x00 stipple 5 - ncontact +72 0x3f 51 0x00 stipple 7 - mvpdiff +73 0x3f 52 0x00 stipple 7 - hvpdiff +74 0x3f 45 0x00 stipple 7 - pcontact + +stipples +#-----------------------------------+--------------------------------------- +# hex bit pattern (8x8) description +#-----------------------------------+--------------------------------------- +1 40 00 18 00 18 00 00 00 very sparsed stripes, ll to ur +2 cc cc 00 00 33 33 00 00 coarse knight's move (waffle) +3 ee 77 bb dd ee 77 bb dd all but diagonal stripes, ll to ur +4 00 00 cc cc 00 00 cc cc offset waffle +5 40 20 10 08 04 02 01 80 sparse diagonal stripes, ll to ur +6 aa 55 aa 55 aa 55 aa 55 half 'n half (checkerboard) +7 02 04 08 10 20 40 80 01 sparse diagonal stripes, lr to ul +8 81 03 06 0c 18 30 60 c0 wide sparse diagonal stripes, lr to ul +9 81 c0 60 30 18 0c 06 03 wide sparse diagonal stripes, ll to ur +10 00 00 00 ff 00 00 00 ff horizontal stripes +11 44 44 44 44 44 44 44 44 vertical stripes +12 55 aa 55 aa 55 aa 55 aa complement of half `n half +13 33 33 ff ff cc cc ff ff complement of #2 (coarse knight's move) +14 aa 55 aa 55 aa 55 aa 55 half 'n half (checkerboard) +15 00 01 00 18 00 00 00 18 very sparsed stripes, 11 to ur +16 c0 07 ff ff c0 07 ff ff wide horizontal stripes +17 c7 c7 c7 c7 c7 c7 c7 c7 wide vertical stripes +18 7c 7c 7c 7c 7c 7c 7c 7c wide vertical stripes (reverse of 17) +19 3c c3 42 42 c3 3c 24 24 bubbles +20 24 42 81 81 42 24 18 18 offset diagonal crossex +21 10 20 00 00 00 02 04 08 diagonal dotted line, lr to ul +22 08 04 00 00 00 40 20 10 diagonal dotted line, ll to ur +23 3c 66 c3 81 c3 66 3c 18 dense diagonal crossex +24 c3 3c bd bd 3c c3 db db complement of #19 empty bubbles +25 dd bb 77 ee dd bb 77 ee all but diagonal stripes, lr to ul +26 e2 4e 52 29 94 e4 8e 11 T pattern +27 71 47 41 00 42 72 47 99 sparse offset T pattern +28 99 3c 7e e7 e7 7e 3c 99 alternating diamonds +29 44 88 55 22 44 88 55 22 bricks, ll to ur +30 30 60 c0 c1 63 36 1c 18 bricks, lr to ul +31 55 db 22 db 55 db 22 db linoleum +32 60 c0 81 03 06 0c 18 30 +33 00 00 00 30 60 60 30 00 new gc thin +34 00 02 06 0e 0e 06 02 00 +35 00 7e 3c 18 00 e7 c3 81 arrows pointing up +36 e0 62 26 0e 0e 26 62 e0 arrows pointing left diff --git a/scmos/mos.7bit.mraster.cmap b/scmos/mos.7bit.mraster.cmap new file mode 100644 index 00000000..7d95d90c --- /dev/null +++ b/scmos/mos.7bit.mraster.cmap @@ -0,0 +1,65 @@ +0 0 0 0 +220 95 95 1 +66 213 66 2 +202 160 115 3 +169 131 101 4 +184 73 83 5 +230 230 0 6 +0 0 0 7 +125 166 250 8 +160 48 191 9 +89 162 165 10 +150 153 168 11 +139 117 155 12 +134 102 149 13 +190 190 120 14 +0 0 0 15 +190 153 222 16 +182 94 158 17 +143 161 169 18 +174 140 165 19 +148 114 152 20 +146 118 154 21 +220 204 169 22 +0 0 0 23 +153 130 218 24 +144 40 178 25 +113 143 168 26 +141 132 171 27 +128 121 143 28 +127 111 146 29 +168 156 129 30 +0 0 0 31 +255 223 229 32 +237 163 165 33 +160 207 153 34 +228 187 173 35 +212 176 167 36 +219 154 160 37 +242 214 127 38 +255 223 229 39 +190 189 227 40 +207 145 203 41 +172 188 193 42 +202 185 194 43 +197 171 189 44 +194 165 186 45 +222 199 175 46 +255 223 229 47 +222 185 215 48 +218 162 190 49 +199 188 194 50 +214 180 193 51 +201 170 188 52 +200 171 188 53 +237 204 194 54 +255 223 229 55 +204 176 214 56 +199 142 198 57 +184 181 194 58 +198 177 195 59 +191 173 184 60 +191 169 185 61 +211 186 178 62 +255 223 229 63 +0 0 0 255 diff --git a/scmos/mos.7bit.mraster_dstyle b/scmos/mos.7bit.mraster_dstyle new file mode 100644 index 00000000..db47f7e2 --- /dev/null +++ b/scmos/mos.7bit.mraster_dstyle @@ -0,0 +1,82 @@ +# +# This file describes the various display styles that are available +# in Magic. This new file is relatively technology-independent: it +# contains enough different styles to support MOSIS's SCMOS process +# without any changes. Each display style describes a particular +# way of drawing things on the display. See "Magic Maintainer's +# Manual #3: The Display Style and Glyph Files" for details on the +# file format. +# +# Please send bug reports/comments to mosis@mosis.edu :-) +# + +# BitPlane Usage: +# +# +# msb lsb +# +-------+-----------+-----------+ +# | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | +# +-------+-----------+-----------+ +# | | | | | \_______/ +# not used -+ | | | | | +# highlights ---+ | | | +---- poly, diff, fets +# opaque/trans. ----+ | +------------ metal1 +# +---------------- metal2 +# +# Bits 0-2 represent the material on the poly-diff plane (poly, +# different flavors of diffusion, different flavors of transistor) +# with mutually-opaque colors. +# +# Bits 3-4 are used for the two metal layers. Each layer has a +# separate bit plane, so the two metal layers are mutually transparent, +# and they are both transparent with respect to the poly-diff layers. +# +# If bit 5 is set, then bits 0-4 are used for one of 32 opaque colors +# which override any other mask information. These colors are used +# for various stipples, contact crosses, etc. They also provide a +# palette of standard colors (red, green, etc.) for use in making +# window borders, menus, etc. The last of these colors to be drawn in +# an area is the one that will appear. +# +# Bit 6 is used for highlights such as the box, the selection, etc. +# It overrides any of the other bits and produces a pure white color. +# +# Bit 7 is not used in this display style file. This is important for +# Sun workstations, since they can't really give Magic all 8 bits. +# For AEDs and other displays, this is a bit wasteful, but still seems +# to work ok. + + +display_styles 7 +# +# Poly-diff styles: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +1 7 1 0 solid 0 - polysilicon +2 7 2 0 solid 0 - ndiffusion +3 7 2 0 stipple 13 - ndiff_in_nwell +4 7 3 0 solid 0 - pdiffusion +5 7 3 0 stipple 13 - pdiff_in_pwell +6 7 4 0 solid 0 - ntransistor +7 7 2 0 stipple 7 - ntransistor_stripes +8 7 5 0 solid 0 - ptransistor +9 7 3 0 stipple 5 - ptransistor_stripes +10 63 6 0 stipple 7 - cwell +11 7 5 0 stipple 22 - highvolt_pwell +12 7 7 0 stipple 7 - nwell +13 7 3 0 stipple 5 - pwell +14 63 6 0 stipple 2 - electrode +15 7 3 0 stipple 10 - pbase +16 7 2 0 stipple 17 - emitter +17 7 3 0 stipple 11 - bccd +18 7 4 0 stipple 21 - highvolt_nwell +19 7 7 0 solid 0 - via +# +# Metal styles: +# stipple short long +# num mask color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +20 8 8 0 solid 0 - metal1 +21 16 16 0 solid 0 - metal2 +22 32 32 0 stipple 23 - metal3 diff --git a/scmos/mos.7bit.sgi.cmap b/scmos/mos.7bit.sgi.cmap new file mode 100644 index 00000000..4a7fd760 --- /dev/null +++ b/scmos/mos.7bit.sgi.cmap @@ -0,0 +1,63 @@ +135 135 135 0 +155 30 30 1 +1 148 1 2 +137 95 50 3 +104 66 36 4 +119 8 18 5 +230 230 0 6 +0 0 0 7 +60 101 185 8 +112 0 143 9 +24 97 100 10 +85 88 103 11 +74 52 90 12 +69 37 84 13 +125 125 55 14 +0 0 0 15 +125 88 157 16 +117 29 93 17 +78 96 104 18 +109 75 100 19 +83 49 87 20 +81 53 89 21 +155 139 104 22 +0 0 0 23 +88 65 153 24 +104 0 138 25 +48 78 103 26 +76 67 106 27 +63 56 78 28 +62 46 81 29 +103 91 64 30 +0 0 0 31 +255 255 255 32 +101 101 101 33 +69 69 69 34 +0 0 0 35 +174 123 133 36 +174 60 97 37 +209 0 0 38 +100 151 110 39 +59 126 83 40 +0 181 0 41 +105 137 177 42 +35 85 185 43 +0 0 221 44 +174 75 178 45 +167 0 172 46 +255 248 179 47 +255 255 0 48 +170 133 95 49 +169 99 58 50 +198 152 0 51 +139 108 0 52 +250 0 252 53 +0 250 250 54 +91 52 0 55 +135 165 165 56 +115 145 115 57 +0 0 0 58 +239 239 0 59 +0 0 0 63 +255 255 255 127 +0 0 0 255 diff --git a/scmos/mos.7bit.std.cmap b/scmos/mos.7bit.std.cmap new file mode 100644 index 00000000..34d5c473 --- /dev/null +++ b/scmos/mos.7bit.std.cmap @@ -0,0 +1,69 @@ +#-------------------------------------- +# Colormap file for X11, 8-bit graphics +#-------------------------------------- +200 200 200 0 background_gray +220 95 95 1 poly_red +66 213 66 2 diff_green +202 160 115 3 diff_brown +169 131 101 4 nfet_brown +184 73 83 5 pfet_brown +230 230 0 6 well_yellow +0 0 0 7 contact_black +125 166 250 8 metal_blue +160 48 191 9 pc_purple +89 162 165 10 +150 153 168 11 +139 117 155 12 +134 102 149 13 +190 190 120 14 +0 0 0 15 +190 153 222 16 metal_purple +182 94 158 17 +143 161 169 18 +174 140 165 19 +148 114 152 20 +146 118 154 21 +220 204 169 22 +0 0 0 23 +153 130 218 24 +144 40 178 25 +113 143 168 26 +141 132 171 27 +128 121 143 28 +127 111 146 29 +168 156 129 30 +0 0 0 31 +255 255 255 32 cursor_white +170 170 170 33 pale_gray +145 145 145 34 dark_gray +0 0 0 35 box_black +239 188 198 36 pale_red +239 125 162 37 medium_red +210 0 155 38 dark_red +165 216 175 39 pale_green +124 191 148 40 medium_green +0 181 0 41 dark_green +170 202 242 42 light_blue +0 0 250 43 dark_blue +40 169 166 44 teal_blue +45 94 179 45 deep_purple +167 0 200 46 bright_purple +255 248 179 47 light_yellow +255 255 0 48 bright_yellow +235 198 160 49 yellow_orange +234 132 73 50 medium_orange +198 152 0 51 ochre_brown +139 108 0 52 medium_brown +195 176 211 53 pale_purple +50 228 225 54 port_cyan +120 81 29 55 border_brown +200 230 230 56 caption_blue +180 210 180 57 window_gray +0 0 0 58 +246 246 7 59 label_yellow +180 180 180 60 medium_gray +230 180 50 61 pale_orange +235 235 235 62 light_gray +0 0 0 63 +255 255 255 127 +0 0 0 255 diff --git a/scmos/mos.OpenGL.dstyle b/scmos/mos.OpenGL.dstyle new file mode 100644 index 00000000..282960b7 --- /dev/null +++ b/scmos/mos.OpenGL.dstyle @@ -0,0 +1,377 @@ +# +# Magic distribution Version 7.3 +# +# This file has been updated for 10-metal processes +# +# (C) Copyright 2001-2008 by +# R. Timothy Edwards +# MultiGiG, Inc., Scotts Valley, CA +# +# Last Modified Date: 12/03/03 +# +# This file describes the various display styles that are available +# in Magic. Each display style describes a particular way of drawing +# things on the display. See "Magic Maintainer's Manual #3: The +# Display Style and Glyph Files" for details on the file format. +# The "version" keyword replaces the version embedded in the filename. +# Please send bug reports/comments to tim@opencircuitdesign.com + +version 8 +# +# There is no bit plane usage in OpenGL. +# The "mask" column used by other style files represents +# the degree of opacity in the OpenGL version of magic. +# opaque = 0 is completely transparent (nothing gets drawn), +# while opaque = 120 is completely opaque. Note that these +# numbers are decimal (vs. octal in version 6 and earlier). +# The bit planes argument of the display_styles is set to 24 +# so we don't lose any bits in color definitions. + +display_styles 24 +# +# The style below means "no color at all". It is special, in that +# it is used by cursors to indicate transparency. +# +# num opaque color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +0 0 0 0x00 solid 0 . no_color_at_all +# +# Opaque styles used for drawing and erasing highlights, window borders, +# etc. +# stipple short long +# num opaque color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +1 127 64 0x00 solid 0 - solid_highlights +2 92 64 0x00 stipple 12 - medium_highlights +3 92 64 0x00 stipple 9 - pale_highlights +4 92 64 0x00 stipple 10 - horiz_highlights +5 92 64 0x00 stipple 11 - vert_highlights +6 127 64 0xff outline 0 - outline_highlights +7 92 64 0xcc outline 0 - dotted_highlights +# +8 92 0 0xff outline 0 e erase_box +9 127 0 0x00 solid 0 - erase_highlights +10 127 0 0x00 solid 0 E erase_everything +11 92 0 0x00 solid 0 - erase_all_but_highl +# +12 92 59 0xff outline 0 l labels +13 92 45 0xff outline 0 L ports +14 127 54 0xff outline 0 i port_connections +15 92 35 0xff outline 0 - bounding_boxes +16 92 60 0xff grid 0 - solid_grid +17 92 35 0xaa grid 0 - dotted_grid +18 92 35 0x00 solid 0 - origin_square +19 92 35 0xff outline 0 - draw_tile_details +# +20 127 55 0x00 solid 0 w window_border +21 127 55 0xff stipple 6 - window_elevator +22 127 56 0x00 solid 0 c window_caption +23 127 57 0x00 solid 0 x window_background +# +24 127 58 0x00 solid 0 - color_editing +# +25 127 60 0x00 solid 0 T tk_medium_gray +26 127 62 0x00 solid 0 t tk_light_gray +# +27 127 47 0xff outline 0 - pale_labels +28 127 80 0xff outline 0 - pale_ports +# +# General-purpose opaque colors. These entries define a whole +# bunch of generally-useful colors. +# +# stipple short long +# num opaque color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +29 127 32 0x00 solid 0 W white +30 127 33 0x00 solid 0 - gray1 (pale) +31 127 34 0x00 solid 0 k gray2 (dark) +32 127 35 0x00 solid 0 K black +33 127 36 0x00 solid 0 r red1 (pale) +34 127 37 0x00 solid 0 - red2 (medium) +35 127 38 0x00 solid 0 R red3 (dark) +36 127 39 0x00 solid 0 g green1 (pale) +37 127 40 0x00 solid 0 - green2 (medium) +38 127 41 0x00 solid 0 G green3 (dark) +39 127 42 0x00 solid 0 b blue1 +40 127 43 0x00 solid 0 B blue2 (dark) +41 127 44 0x00 solid 0 - blue3 +42 127 45 0x00 solid 0 p purple1 +43 127 46 0x00 solid 0 P purple2 +44 127 47 0x00 solid 0 y yellow1 +45 127 48 0x00 solid 0 Y yellow2 +46 127 49 0x00 solid 0 o orange1 +47 127 50 0x00 solid 0 O orange2 +48 127 51 0x00 solid 0 n brown1 +49 127 52 0x00 solid 0 N brown2 +50 127 53 0x00 solid 0 m magenta +51 127 54 0x00 solid 0 C cyan +# +#---------------------------------------------------------------------- +# All of the styles above this point are used internally by Magic for +# things like menus, drawing the box, etc. The style numbers and +# number of styles must match the definitions in misc/style.h. +# All of the styles below this point are used by the technology file, +# addressed by name or number. Note that the numbers are only for +# backwards compatibility with .tech27 files which specify styles +# by number only. The order in which styles are drawn is the order +# in which they appear in this file, not the "num" column. The +# ordinal numbering reflects vagaries of the 8-bit-plane setup. +# 24-bit styles have been re-ordered to match the physical vertical +# position of layers in the layout. +#---------------------------------------------------------------------- + +layout_styles +# +# num opaque color outline fill number name name +#---------------------------------------------------------------------- +10 63 6 0x00 stipple 7 - cwell +52 92 2 0x00 stipple 19 - cwellnsc +79 63 4 0x00 stipple 21 - highvolt_nwell +80 63 5 0x00 stipple 22 - highvolt_pwell +12 63 2 0xff stipple 2 - nwell +13 63 3 0xff stipple 2 - pwell +67 120 9 0xff outline 0 - subcircuit +1 120 1 0x00 solid 0 - polysilicon +87 92 50 0x00 solid 0 - poly_light +88 63 1 0x00 stipple 1 - obspoly +2 120 2 0x00 solid 0 - ndiffusion +69 127 40 0x00 solid 0 - mvndiff +70 127 41 0x00 solid 0 - hvndiff +71 127 44 0x00 solid 0 - ncontact +3 120 2 0x00 stipple 13 - ndiff_in_nwell +11 63 5 0x00 stipple 22 - hvndiff_mask +4 120 3 0x00 solid 0 - pdiffusion +72 127 51 0x00 solid 0 - mvpdiff +73 127 52 0x00 solid 0 - hvpdiff +74 127 45 0x00 solid 0 - pcontact +5 120 3 0x00 stipple 13 - pdiff_in_pwell +18 63 4 0x00 stipple 21 - hvpdiff_mask +6 120 4 0x00 solid 0 - ntransistor +7 120 2 0x00 stipple 8 - ntransistor_stripes +8 120 5 0x00 solid 0 - ptransistor +9 120 3 0x00 stipple 9 - ptransistor_stripes +83 20 51 0x00 solid 0 - implant1 +84 20 48 0x00 solid 0 - implant2 +85 30 38 0x00 solid 0 - implant3 +86 30 32 0x00 solid 0 - implant4 +53 92 7 0x00 stipple 7 - nwell_field_implant +54 92 7 0x00 stipple 5 - substrate_field_implant +30 92 2 0x00 stipple 22 - ndop_stripes +31 92 3 0x00 stipple 21 - pdop_stripes +36 92 2 0xff stipple 15 - nselect +35 92 3 0xff stipple 1 - pselect +43 92 2 0x00 stipple 5 - nselect2 +44 92 3 0x00 stipple 7 - pselect2 +47 92 78 0x00 solid 0 - poly_resist +48 92 3 0x00 stipple 7 - poly_resist_stripes +46 92 42 0x00 stipple 7 - silicide_block +14 92 6 0x00 solid 0 - electrode +27 92 3 0x00 stipple 9 - electrode_stripes +28 92 61 0x00 solid 0 - capacitor +15 92 3 0x00 stipple 10 - pbase +16 92 2 0x00 stipple 17 - emitter +17 92 3 0x00 stipple 11 - bccd +20 80 8 0x00 solid 0 - metal1 +29 92 8 0x00 stipple 6 - metal1_alt +49 92 8 0x00 stipple 19 - metal1tight +89 63 8 0x00 stipple 1 - obsmetal1 +26 92 9 0x00 solid 0 - poly_contact +21 80 16 0x00 solid 0 - metal2 +50 92 16 0x00 stipple 19 - metal2tight +90 63 16 0x00 stipple 1 - obsmetal2 +19 92 7 0x00 solid 0 - via +55 120 43 0xff stipple 35 - via1arrow +81 120 43 0xff stipple 2 - via1 +22 80 53 0x00 solid 0 - metal3 +51 92 53 0x00 stipple 8 - metal3tight +91 63 53 0x00 stipple 1 - obsmetal3 +37 92 46 0xff stipple 19 - via2 +56 120 53 0xff stipple 36 - via2arrow +82 120 53 0xff stipple 2 - via2alt +23 80 33 0x00 solid 0 - metal4 +92 63 33 0x00 stipple 1 - obsmetal4 +38 92 38 0xff stipple 24 - via3 +57 92 6 0x00 stipple 2 - via3alt +24 80 44 0x00 solid 0 - metal5 +93 63 44 0x00 stipple 1 - obsmetal5 +39 92 41 0xff stipple 26 - via4 +64 80 46 0x00 solid 0 - metal6 +94 63 46 0x00 stipple 1 - obsmetal6 +59 92 74 0xff stipple 2 - via5 +65 80 38 0x00 solid 0 - metal7 +95 63 38 0x00 stipple 1 - obsmetal7 +60 92 46 0xff stipple 28 - via6 +66 80 34 0x00 solid 0 - metal8 +96 63 34 0x00 stipple 1 - obsmetal8 +61 92 9 0xff stipple 29 - via7 +75 80 74 0x00 solid 0 - metal9 +97 63 74 0x00 stipple 1 - obsmetal9 +76 92 40 0xff stipple 30 - via8 +77 80 75 0x00 solid 0 - metal10 +98 63 75 0x00 stipple 1 - obsmetal10 +78 92 7 0xff stipple 31 - via9 +62 92 38 0x00 stipple 3 - mim_bottom +63 92 34 0x00 stipple 3 - mim_top +58 92 7 0x00 solid 0 - gen_contact +32 92 7 0xff cross 0 - contact_X'es +33 92 7 0xff stipple 2 - contact_waffle +25 92 37 0x00 solid 0 - pad4 +34 92 34 0xff stipple 10 - overglass +68 92 33 0xff solid 0 - mems +40 92 53 0x00 stipple 5 - check_paint +41 92 54 0x00 stipple 7 - check_subcells +42 127 32 0x00 stipple 4 - error_waffle +45 92 35 0x00 solid 0 - comment +# +#---------------------------------------------------------------------- +# All of the styles below this point must duplicate the styles in +# the section above, and represent a version of each previous +# layer to use in non-edit cells ("pale" styles): +#---------------------------------------------------------------------- + +pale_styles +# +# Poly-diff styles: +# stipple short long +# num opaque color outline fill number name name +#---------------------------------------------------------------------- +10 92 70 0x00 stipple 7 - cwell +52 92 2 0x00 stipple 13 - cwellnsc +79 92 71 0x00 stipple 21 - highvolt_nwell +80 92 69 0x00 stipple 22 - highvolt_pwell +12 92 66 0xff stipple 2 - nwell +13 92 67 0xff stipple 2 - pwell +67 92 73 0xff outline 0 - subcircuit +1 92 65 0x00 solid 0 - polysilicon +87 92 49 0x00 solid 0 - poly_light +88 92 65 0x00 stipple 1 - obspoly +2 92 66 0x00 solid 0 - ndiffusion +69 127 40 0x00 stipple 3 - mvndiff +70 127 41 0x00 stipple 3 - hvndiff +71 127 45 0x00 stipple 3 - ncontact +3 92 66 0x00 stipple 13 - ndiff_in_nwell +11 92 69 0x00 stipple 22 - hvndiff_mask +4 92 67 0x00 solid 0 - pdiffusion +72 127 51 0x00 stipple 25 - mvpdiff +73 127 52 0x00 stipple 25 - hvpdiff +74 127 44 0x00 stipple 25 - pcontact +5 92 67 0x00 stipple 13 - pdiff_in_pwell +18 92 71 0x00 stipple 21 - hnpdiff_mask +6 92 68 0x00 solid 0 - ntransistor +7 92 66 0x00 stipple 7 - ntransistor_stripes +8 92 69 0x00 solid 0 - ptransistor +9 92 67 0x00 stipple 5 - ptransistor_stripes +83 10 51 0x00 solid 0 - implant1 +84 10 48 0x00 solid 0 - implant2 +85 15 38 0x00 solid 0 - implant3 +86 15 32 0x00 solid 0 - implant4 +53 92 7 0x00 stipple 7 - nwell_field_implant +54 92 7 0x00 stipple 5 - substrate_field_implant +30 92 66 0x00 stipple 22 - ndop_stripes +31 92 67 0x00 stipple 21 - pdop_stripes +36 92 66 0xff stipple 15 - nselect +35 92 67 0xff stipple 1 - pselect +43 92 2 0x00 stipple 5 - nselect2 +44 92 3 0x00 stipple 7 - pselect2 +47 92 142 0x00 solid 0 - poly_resist +48 92 67 0x00 stipple 7 - poly_resist_stripes +46 92 42 0x00 stipple 7 - silicide_block +14 92 70 0x00 solid 0 - electrode +27 92 67 0x00 stipple 9 - electrode_stripes +28 92 125 0x00 solid 0 - capacitor +15 92 67 0x00 stipple 10 - pbase +16 92 66 0x00 stipple 17 - emitter +17 92 67 0x00 stipple 11 - bccd +20 64 72 0x00 solid 0 - metal1 +29 92 72 0x00 stipple 6 - metal1_alt +49 92 8 0x00 stipple 14 - metal1tight +89 92 72 0x00 stipple 1 - obsmetal1 +26 92 73 0x00 solid 0 - poly_contact +21 64 80 0x00 solid 0 - metal2 +50 92 16 0x00 stipple 5 - metal2tight +90 92 80 0x00 stipple 1 - obsmetal2 +19 92 71 0x00 solid 0 - via +55 92 107 0xff stipple 35 - via1arrow +81 92 107 0xff stipple 2 - via1 +22 64 117 0x00 solid 0 - metal3 +51 92 53 0x00 stipple 21 - metal3tight +91 92 117 0x00 stipple 1 - obsmetal3 +37 92 110 0xff stipple 19 - via2 +56 92 117 0xff stipple 36 - via2arrow +82 92 117 0xff stipple 2 - via2alt +23 64 97 0x00 solid 0 - metal4 +92 92 97 0x00 stipple 1 - obsmetal4 +38 92 102 0xff stipple 24 - via3 +57 92 70 0x00 stipple 2 - via3alt +24 64 108 0x00 solid 0 - metal5 +93 92 108 0x00 stipple 1 - obsmetal5 +39 92 105 0xff stipple 26 - via4 +64 64 110 0x00 solid 0 - metal6 +94 92 110 0x00 stipple 1 - obsmetal6 +59 92 80 0xff stipple 2 - via5 +65 64 102 0x00 solid 0 - metal7 +95 92 102 0x00 stipple 1 - obsmetal7 +60 92 110 0xff stipple 28 - via6 +66 64 98 0x00 solid 0 - metal8 +96 92 98 0x00 stipple 1 - obsmetal8 +61 92 110 0xff stipple 29 - via7 +75 64 76 0x00 solid 0 - metal9 +97 92 76 0x00 stipple 1 - obsmetal9 +76 92 33 0xff stipple 30 - via8 +77 64 77 0x00 solid 0 - metal10 +98 92 77 0x00 stipple 1 - obsmetal10 +78 92 34 0xff stipple 31 - via9 +62 92 102 0x00 stipple 3 - mim_bottom +63 92 98 0x00 stipple 3 - mim_top +58 92 34 0x00 solid 0 - gen_contact +32 92 99 0xff cross 0 - contact_X'es +33 92 99 0xff stipple 2 - contact_waffle +25 92 101 0x00 solid 0 - pad4 +34 92 98 0xff stipple 10 - overglass +68 92 97 0xff solid 0 - mems +40 92 53 0x00 stipple 5 - check_paint +41 92 54 0x00 stipple 7 - check_subcells +42 127 32 0x00 stipple 4 - error_waffle +45 92 15 0x00 solid 0 - comment +#---------------------------------------------------------------------- + +stipples +#------------------------------------------------------------------------- +# hex bit pattern (8x8) description +#------------------------------------------------------------------------- +1 40 00 18 00 18 00 00 00 very sparsed stripes, ll to ur +2 cc cc 00 00 33 33 00 00 coarse knight's move (waffle) +3 ee 77 bb dd ee 77 bb dd all but diagonal stripes, ll to ur +4 00 00 cc cc 00 00 cc cc offset waffle +5 40 20 10 08 04 02 01 80 sparse diagonal stripes, ll to ur +6 aa 55 aa 55 aa 55 aa 55 half 'n half (checkerboard) +7 02 04 08 10 20 40 80 01 sparse diagonal stripes, lr to ul +8 81 03 06 0c 18 30 60 c0 wide sparse diagonal stripes, lr to ul +9 81 c0 60 30 18 0c 06 03 wide sparse diagonal stripes, ll to ur +10 00 00 00 ff 00 00 00 ff horizontal stripes +11 44 44 44 44 44 44 44 44 vertical stripes +12 55 aa 55 aa 55 aa 55 aa complement of half `n half +13 33 33 ff ff cc cc ff ff complement of #2 (coarse knight's move) +14 aa 55 aa 55 aa 55 aa 55 half 'n half (checkerboard) +15 00 01 00 18 00 00 00 18 very sparsed stripes, 11 to ur +16 c0 07 ff ff c0 07 ff ff wide horizontal stripes +17 c7 c7 c7 c7 c7 c7 c7 c7 wide vertical stripes +18 7c 7c 7c 7c 7c 7c 7c 7c wide vertical stripes (reverse of 17) +19 3c c3 42 42 c3 3c 24 24 bubbles +20 24 42 81 81 42 24 18 18 offset diagonal crossex +21 10 20 00 00 00 02 04 08 diagonal dotted line, lr to ul +22 08 04 00 00 00 40 20 10 diagonal dotted line, ll to ur +23 3c 66 c3 81 c3 66 3c 18 dense diagonal crossex +24 c3 3c bd bd 3c c3 db db complement of #19 empty bubbles +25 dd bb 77 ee dd bb 77 ee all but diagonal stripes, lr to ul +26 e2 4e 52 29 94 e4 8e 11 T pattern +27 71 47 41 00 42 72 47 99 sparse offset T pattern +28 99 3c 7e e7 e7 7e 3c 99 alternating diamonds +29 44 88 55 22 44 88 55 22 bricks, ll to ur +30 30 60 c0 c1 63 36 1c 18 bricks, lr to ul +31 55 db 22 db 55 db 22 db linoleum +32 60 c0 81 03 06 0c 18 30 +33 00 00 00 30 60 60 30 00 new gc thin +34 00 02 06 0e 0e 06 02 00 +35 00 7e 3c 18 00 e7 c3 81 arrows pointing up +36 e0 62 26 0e 0e 26 62 e0 arrows pointing left diff --git a/scmos/mos.OpenGL.dstyle.mark b/scmos/mos.OpenGL.dstyle.mark new file mode 100644 index 00000000..e910c808 --- /dev/null +++ b/scmos/mos.OpenGL.dstyle.mark @@ -0,0 +1,365 @@ +# +# MOSIS distribution Version 8.2 +# +# This file has been updated by MOSIS to be used for three metal, two poly +# SCMOS technology files. +# +# (C) Copyright 1992, 1993, 1994, 1995 by +# +# Jen-I Pi pi@isi.edu +# The MOSIS Service +# USC Information Sciences Institute +# 4676 Admiralty Way +# Marina del Rey, CA 90292 +# (310) 822-1511 x640 fax (310)823-5624 +# +# All Rights Reserved. +# Last Modified Date: 03/15/95 +# +# Permission to use, copy, modify, and distribute this technology +# file and its associated documentation for any purpose and without +# fee is hereby granted, provided that the above copyright notice +# appears in all copies and that both that copyright notice and this +# permission notice appear in supporting documentation, and that the +# name of the University of Southern California not be used in +# advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. The University of +# Southern California makes no representations about the suitability +# of this technology file for any purpose. This technology file is +# provided "as is" without express or implied warranty and the +# University of Southern California retains the right to change its +# content at any time without notice any other party. +# +# THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS TECHNOLOGY FILE, INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF +# SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS TECHNOLOGY FILE. +# +# This file describes the various display styles that are available +# in Magic. This new file is relatively technology-independent: it +# contains enough different styles to support MOSIS's SCMOS process +# without any changes. Each display style describes a particular +# way of drawing things on the display. See "Magic Maintainer's +# Manual #3: The Display Style and Glyph Files" for details on the +# file format. +# +# Please send bug reports/comments to mosis@mosis.edu :-) +# +# "version" keyword replaces the version embedded in the filename. + +version 6 +# +# There is no bit plane usage in OpenGL. +# The "mask" column used by other style files represents +# the degree of opacity in the OpenGL version of magic. +# opaque = 000 is completely transparent (nothing gets drawn), +# while opaque = 170 is completely opaque. Note that these +# numbers are octal. The bit planes argument of the +# display_styles is set to 24 so we don't lose any bits in +# color definitions. +# + +display_styles 24 +# +# The style below means "no color at all". It is special, in that +# it is used by cursors to indicate transparency. +# +# num opaque color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +0 177 000 000 solid 0 - no_color_at_all +# +# Opaque styles used for drawing and erasing highlights, window borders, +# etc. +# stipple short long +# num opaque color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +1 177 100 000 solid 0 - solid_highlights +2 134 100 000 stipple 12 - medium_highlights +3 134 100 000 stipple 9 - pale_highlights +4 134 100 000 stipple 10 - horiz_highlights +5 134 100 000 stipple 11 - vert_highlights +6 177 100 377 outline 0 - outline_highlights +7 134 100 314 outline 0 - dotted_highlights +# +8 134 000 377 outline 0 e erase_box +9 177 000 000 solid 0 - erase_highlights +10 177 000 000 solid 0 E erase_everything +11 134 000 000 solid 0 - erase_all_but_highl +# +12 134 073 377 outline 0 l labels +13 134 066 377 outline 0 L ports +14 177 040 377 outline 0 i port_connections +15 134 043 377 outline 0 - bounding_boxes +16 134 074 377 grid 0 - solid_grid +17 134 043 252 grid 0 - dotted_grid +18 134 043 000 solid 0 - origin_square +19 134 043 377 outline 0 - draw_tile_details +# +20 177 067 000 solid 0 w window_border +21 177 067 377 stipple 6 - window_elevator +22 177 070 000 solid 0 c window_caption +23 177 071 000 solid 0 x window_background +# +24 177 072 000 solid 0 - color_editing +# +25 177 074 000 solid 0 T tk_medium_gray +26 177 076 000 solid 0 t tk_light_gray +# +# General-purpose opaque colors. These entries define a whole +# bunch of generally-useful colors. +# +# stipple short long +# num opaque color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +27 177 040 000 solid 0 W white +28 177 041 000 solid 0 - gray1 (pale) +29 177 042 000 solid 0 k gray2 (dark) +30 177 043 000 solid 0 K black +31 177 044 000 solid 0 r red1 (pale) +32 177 045 000 solid 0 - red2 (medium) +33 177 046 000 solid 0 R red3 (dark) +34 177 047 000 solid 0 g green1 (pale) +35 177 050 000 solid 0 - green2 (medium) +36 177 051 000 solid 0 G green3 (dark) +37 177 052 000 solid 0 b blue1 +38 177 053 000 solid 0 B blue2 (dark) +39 177 054 000 solid 0 - blue3 +40 177 055 000 solid 0 p purple1 +41 177 056 000 solid 0 P purple2 +42 177 057 000 solid 0 y yellow1 +43 177 060 000 solid 0 Y yellow2 +44 177 061 000 solid 0 o orange1 +45 177 062 000 solid 0 O orange2 +46 177 063 000 solid 0 n brown1 +47 177 064 000 solid 0 N brown2 +48 177 065 000 solid 0 m magenta +49 177 066 000 solid 0 C cyan +# +#---------------------------------------------------------------------- +# All of the styles above this point are used internally by Magic for +# things like menus, drawing the box, etc. The style numbers and +# number of styles must match the definitions in misc/style.h. +# All of the styles below this point are used by the technology file, +# addressed by name or number. Note that the numbers are only for +# backwards compatibility with .tech27 files which specify styles +# by number only. The order in which styles are drawn is the order +# in which they appear in this file, not the "num" column. The +# ordinal numbering reflects vagaries of the 8-bit-plane setup. +# 24-bit styles have been re-ordered to match the physical vertical +# position of layers in the layout. +#---------------------------------------------------------------------- + +layout_styles +# +# num opaque color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +10 077 006 000 stipple 7 - cwell +52 134 002 000 stipple 19 - cwellnsc +18 077 004 000 stipple 21 - highvolt_nwell +11 077 005 000 stipple 22 - highvolt_pwell +12 077 002 377 stipple 2 - nwell +13 077 003 377 stipple 2 - pwell +67 170 011 377 outline 0 - subcircuit +1 170 001 000 solid 0 - polysilicon +2 170 002 000 solid 0 - ndiffusion +69 177 050 000 solid 0 - mvndiff +70 177 051 000 solid 0 - hvndiff +71 177 054 000 solid 0 - ncontact +3 170 002 000 stipple 13 - ndiff_in_nwell +4 170 003 000 solid 0 - pdiffusion +72 177 063 000 solid 0 - mvpdiff +73 177 064 000 solid 0 - hvpdiff +74 177 055 000 solid 0 - pcontact +5 170 003 000 stipple 13 - pdiff_in_pwell +6 170 004 000 solid 0 - ntransistor +7 170 002 000 stipple 8 - ntransistor_stripes +8 170 005 000 solid 0 - ptransistor +9 170 003 000 stipple 9 - ptransistor_stripes +53 134 007 000 stipple 7 - nwell_field_implant +54 134 007 000 stipple 5 - substrate_field_implant +30 134 002 000 stipple 22 - ndop_stripes +31 134 003 000 stipple 21 - pdop_stripes +36 134 002 377 stipple 15 - nselect +35 134 003 377 stipple 1 - pselect +43 134 002 000 stipple 5 - nselect2 +44 134 003 000 stipple 7 - pselect2 +47 134 001 000 solid 0 - poly_resist +48 134 003 000 stipple 7 - poly_resist_stripes +46 134 052 000 stipple 7 - silicide_block +14 134 006 000 solid 0 - electrode +27 134 003 000 stipple 9 - electrode_stripes +28 134 075 000 solid 0 - capacitor +15 134 003 000 stipple 10 - pbase +16 134 002 000 stipple 17 - emitter +17 134 003 000 stipple 11 - bccd +20 120 010 000 solid 0 - metal1 +29 134 010 000 stipple 6 - metal1_alt +49 134 010 000 stipple 19 - metal1tight +26 134 011 000 solid 0 - poly_contact +21 120 020 000 solid 0 - metal2 +50 134 020 000 stipple 19 - metal2tight +19 134 007 000 solid 0 - via +# MNM hack 9-11-2003 +55 134 143 377 stipple 29 - via1 +22 120 065 000 solid 0 - metal3 +51 134 065 000 stipple 8 - metal3tight +37 134 056 377 stipple 19 - via2 +# MNM hack 9-11-2003 +56 134 143 377 stipple 30 - via2alt +23 120 041 000 solid 0 - metal4 +38 134 046 377 stipple 24 - via3 +57 134 006 000 stipple 2 - via3alt +24 120 054 000 solid 0 - metal5 +39 134 051 377 stipple 5 - via4 +64 120 056 000 solid 0 - metal6 +59 134 020 377 stipple 2 - via5 +65 120 046 000 solid 0 - metal7 +60 134 056 377 stipple 2 - via6 +66 120 042 000 solid 0 - metal8 +61 134 063 377 stipple 2 - via7 +62 134 046 000 stipple 3 - mim_bottom +63 134 042 000 stipple 3 - mim_top +58 134 007 000 solid 0 - gen_contact +32 134 007 377 cross 0 - contact_X'es +33 134 007 377 stipple 2 - contact_waffle +25 134 045 000 solid 0 - pad4 +34 134 042 377 stipple 10 - overglass +68 134 041 377 solid 0 - mems +40 134 065 000 stipple 5 - check_paint +41 134 066 000 stipple 7 - check_subcells +42 177 040 000 stipple 4 - error_waffle +45 134 043 000 solid 0 - comment +# +#---------------------------------------------------------------------- +# All of the styles below this point must duplicate the styles in +# the section above, and represent a version of each previous +# layer to use in non-edit cells ("pale" styles): +#---------------------------------------------------------------------- + +pale_styles +# +# Poly-diff styles: +# stipple short long +# num opaque color outline fill number name name +# ----+------+--------+--------+------+-------+------+-------------- +10 134 106 000 stipple 7 - cwell +52 134 002 000 stipple 13 - cwellnsc +18 134 107 000 stipple 21 - highvolt_nwell +11 134 105 000 stipple 22 - highvolt_pwell +12 134 102 377 stipple 2 - nwell +13 134 103 377 stipple 2 - pwell +67 134 111 377 outline 0 - subcircuit +1 134 101 000 solid 0 - polysilicon +2 134 102 000 solid 0 - ndiffusion +69 177 050 000 stipple 3 - mvndiff +70 177 051 000 stipple 3 - hvndiff +71 177 054 000 stipple 3 - ncontact +3 134 102 000 stipple 13 - ndiff_in_nwell +4 134 103 000 solid 0 - pdiffusion +72 177 063 000 stipple 25 - mvpdiff +73 177 064 000 stipple 25 - hvpdiff +74 177 055 000 stipple 25 - pcontact +5 134 103 000 stipple 13 - pdiff_in_pwell +6 134 104 000 solid 0 - ntransistor +7 134 102 000 stipple 7 - ntransistor_stripes +8 134 105 000 solid 0 - ptransistor +9 134 103 000 stipple 5 - ptransistor_stripes +53 134 007 000 stipple 7 - nwell_field_implant +54 134 007 000 stipple 5 - substrate_field_implant +30 134 102 000 stipple 22 - ndop_stripes +31 134 103 000 stipple 21 - pdop_stripes +36 134 102 377 stipple 15 - nselect +35 134 103 377 stipple 1 - pselect +43 134 002 000 stipple 5 - nselect2 +44 134 003 000 stipple 7 - pselect2 +47 134 001 000 solid 0 - poly_resist +48 134 003 000 stipple 7 - poly_resist_stripes +46 134 052 000 stipple 7 - silicide_block +14 134 106 000 solid 0 - electrode +27 134 103 000 stipple 9 - electrode_stripes +28 134 175 000 solid 0 - capacitor +15 134 103 000 stipple 10 - pbase +16 134 102 000 stipple 17 - emitter +17 134 103 000 stipple 11 - bccd +20 100 110 000 solid 0 - metal1 +29 134 110 000 stipple 6 - metal1_alt +49 134 010 000 stipple 14 - metal1tight +26 134 111 000 solid 0 - poly_contact +21 100 120 000 solid 0 - metal2 +50 134 020 000 stipple 5 - metal2tight +19 134 107 000 solid 0 - via +#55 134 120 000 stipple 2 - via1 +# MNM hack 9-11-2003 +55 134 143 377 stipple 29 - via1 +22 100 165 000 solid 0 - metal3 +51 134 065 000 stipple 21 - metal3tight +37 134 156 377 stipple 19 - via2 +# MNM hack 9-11-2003 +56 134 143 377 stipple 30 - via2alt +23 100 141 000 solid 0 - metal4 +38 134 146 377 stipple 24 - via3 +57 134 106 000 stipple 2 - via3alt +24 100 154 000 solid 0 - metal5 +39 134 151 377 stipple 5 - via4 +64 100 156 000 solid 0 - metal6 +59 134 120 377 stipple 2 - via5 +65 100 146 000 solid 0 - metal7 +60 134 156 377 stipple 2 - via6 +66 100 142 000 solid 0 - metal8 +61 134 163 377 stipple 2 - via7 +62 134 146 000 stipple 3 - mim_bottom +63 134 142 000 stipple 3 - mim_top +58 134 042 000 solid 0 - gen_contact +32 134 143 377 cross 0 - contact_X'es +33 134 143 377 stipple 2 - contact_waffle +25 134 145 000 solid 0 - pad4 +34 134 142 377 stipple 10 - overglass +68 134 141 377 solid 0 - mems +40 134 065 000 stipple 5 - check_paint +41 134 066 000 stipple 7 - check_subcells +42 177 040 000 stipple 4 - error_waffle +45 134 017 000 solid 0 - comment +#---------------------------------------------------------------------- + +stipples +#-----------------------------------+--------------------------------------- +# bit pattern | description +#-----------------------------------+--------------------------------------- +1 100 000 030 000 030 000 000 000 very sparsed stripes, ll to ur +2 314 314 000 000 063 063 000 000 coarse knight's move (waffle) +3 356 167 273 335 356 167 273 335 all but diagonal stripes, ll to ur +4 000 000 314 314 000 000 314 314 offset waffle +5 100 040 020 010 004 002 001 200 sparse diagonal stripes, ll to ur +6 252 125 252 125 252 125 252 125 half 'n half (checkerboard) +7 002 004 010 020 040 100 200 001 sparse diagonal stripes, lr to ul +8 201 003 006 014 030 060 140 300 wide sparse diagonal stripes, lr to ul +9 201 300 140 060 030 014 006 003 wide sparse diagonal stripes, ll to ur +10 000 000 000 377 000 000 000 377 horizontal stripes +11 104 104 104 104 104 104 104 104 vertical stripes +12 125 252 125 252 125 252 125 252 complement of half `n half +13 063 063 777 777 314 314 777 777 complement of #2 (coarse knight's move) +14 252 125 252 125 252 125 252 125 half 'n half (checkerboard) +15 000 001 000 030 000 000 000 030 very sparsed stripes, 11 to ur +16 300 007 377 377 300 007 377 377 wide horizontal stripes +17 307 307 307 307 307 307 307 307 wide vertical stripes +18 174 174 174 174 174 174 174 174 wide vertical stripes (reverse of 17) +19 074 303 102 102 303 074 044 044 bubbles +20 044 102 201 201 102 044 030 030 offset diagonal crossex +21 020 040 000 000 000 002 004 010 diagonal dotted line, lr to ul +22 010 004 000 000 000 100 040 020 diagonal dotted line, ll to ur +23 074 146 303 201 303 146 074 030 dense diagonal crossex +24 703 474 675 675 474 703 733 733 complement of #19 empty bubbles +25 335 273 167 356 335 273 167 356 all but diagonal stripes, lr to ul +# attempt at new styles MNM +26 140 300 201 003 006 014 030 060 +27 000 000 000 060 140 140 060 000 new gc thin +28 000 002 006 016 016 006 002 000 +#29 000 000 000 000 030 074 176 000 +29 000 176 074 030 000 000 000 000 +#30 000 100 140 160 160 140 100 000 +30 000 004 014 034 034 014 004 000 +31 000 176 074 030 000 000 000 000 diff --git a/scmos/mos.OpenGL.std.cmap b/scmos/mos.OpenGL.std.cmap new file mode 100644 index 00000000..6ae3a2f8 --- /dev/null +++ b/scmos/mos.OpenGL.std.cmap @@ -0,0 +1,76 @@ +#--------------------------------------- +# Colormap file for OpenGL graphics +#--------------------------------------- +# R G B idx color-name +#--------------------------------------- +200 200 200 0 background_gray +220 95 95 1 poly_red +66 213 66 2 diff_green +202 160 115 3 diff_brown +169 131 101 4 nfet_brown +184 73 83 5 pfet_brown +230 230 0 6 well_yellow +0 0 0 7 contact_black +125 166 250 8 metal_blue +160 48 191 9 pc_purple +190 153 222 16 metal_purple +255 255 255 32 cursor_white +170 170 170 33 pale_gray +145 145 145 34 dark_gray +0 0 0 35 box_black +239 188 198 36 pale_red +239 125 162 37 medium_red +210 0 155 38 dark_red +165 216 175 39 pale_green +124 191 148 40 medium_green +0 181 0 41 dark_green +170 202 242 42 light_blue +100 150 250 43 bright_blue +40 169 166 44 teal_blue +45 94 179 45 deep_purple +167 0 200 46 bright_purple +255 248 179 47 light_yellow +255 255 0 48 bright_yellow +235 198 160 49 yellow_orange +234 132 73 50 medium_orange +198 152 0 51 ochre_brown +130 90 0 52 medium_brown +245 163 224 53 bright_lavender +50 228 225 54 port_cyan +120 81 29 55 border_brown +200 230 230 56 caption_blue +180 210 180 57 window_gray +0 0 0 58 +246 246 7 59 label_yellow +180 180 180 60 medium_gray +230 180 50 61 pale_orange +235 235 235 62 light_gray +255 255 255 64 white +210 148 148 65 deep_pink +133 206 133 66 pale_green +201 170 157 67 peach_gray +184 165 150 68 gray_brown +192 136 141 69 rosy_brown +215 215 100 70 pale_ochre +130 130 130 71 gray50 +163 183 225 72 steel_blue +180 124 196 73 medium_purple +137 210 179 74 pale_teal +200 185 255 75 bright_lavender2 +169 213 198 76 pale_cyan +210 210 230 77 pale_steel +244 115 105 78 brick_red +195 176 211 80 pale_purple +185 185 185 97 gray75 +160 160 160 98 gray62 +100 100 100 99 gray40 +220 163 181 101 pale_pink +220 120 200 102 medium_pink +80 175 80 105 sea_green +125 180 180 109 medium_steel +175 115 175 110 deep_lavender +215 170 90 115 medium_tan +228 160 201 117 light_lavender +215 190 125 125 light_tan +234 165 155 142 pale_pink2 +0 0 0 255 diff --git a/scmos/rules/all-rules.mag b/scmos/rules/all-rules.mag new file mode 100644 index 00000000..46c917eb --- /dev/null +++ b/scmos/rules/all-rules.mag @@ -0,0 +1,488 @@ +magic +tech scmos +timestamp 783720303 +<< pwell >> +rect 104 132 114 144 +<< nwell >> +rect -9 203 1 219 +rect 10 203 20 219 +rect 150 114 190 138 +<< capwell >> +rect 200 123 216 141 +rect 141 83 151 93 +rect 160 83 170 93 +<< polysilicon >> +rect 65 213 67 218 +rect 103 213 105 218 +rect 65 211 68 213 +rect 76 211 78 213 +rect 92 211 94 213 +rect 102 211 105 213 +rect 119 210 121 217 +rect 202 216 204 219 +rect 165 214 175 215 +rect 165 210 166 214 +rect 174 210 175 214 +rect 190 213 194 215 +rect 208 212 210 219 +rect 65 207 68 209 +rect 76 207 78 209 +rect 92 207 94 209 +rect 102 207 105 209 +rect 119 208 122 210 +rect 132 208 142 210 +rect 152 208 155 210 +rect 165 209 175 210 +rect 219 209 221 212 +rect 65 202 67 207 +rect 103 202 105 207 +rect 153 202 155 208 +rect 219 204 221 205 +rect -1 185 1 187 +rect 31 179 33 181 +rect 37 179 40 181 +rect -1 169 1 179 +rect 38 178 40 179 +rect 38 176 53 178 +rect 106 174 118 176 +rect -1 161 1 163 +rect 89 162 91 168 +rect 81 142 107 144 +rect 81 134 83 142 +rect 91 134 94 142 +rect 102 140 107 142 +rect 130 143 142 145 +rect 102 136 104 140 +rect 102 134 107 136 +rect 81 132 107 134 +rect 130 133 132 143 +rect 140 135 142 143 +rect 138 133 142 135 +rect 97 119 99 121 +rect 102 119 106 121 +rect 104 117 106 119 +rect 139 123 141 130 +rect 202 127 203 130 +rect 213 127 214 130 +rect 202 125 214 127 +rect 97 92 99 94 +rect 102 92 106 94 +rect 104 90 106 92 +rect 201 89 204 97 +rect 210 89 213 97 +rect 219 89 224 97 +rect 199 87 206 89 +rect 199 83 200 87 +rect 204 83 206 87 +rect 208 87 215 89 +rect 208 83 209 87 +rect 213 83 215 87 +rect 217 87 224 89 +rect 217 83 218 87 +rect 222 83 224 87 +<< electrode >> +rect 132 131 138 133 +rect 83 84 85 122 +rect 95 117 97 119 +rect 132 123 133 131 +rect 137 123 138 131 +rect 132 122 138 123 +rect 95 116 99 117 +rect 88 115 99 116 +rect 102 115 104 117 +rect 88 111 89 115 +rect 97 111 98 115 +rect 88 110 98 111 +rect 195 103 201 104 +rect 195 99 196 103 +rect 200 99 201 103 +rect 195 97 201 99 +rect 204 103 210 104 +rect 204 99 205 103 +rect 209 99 210 103 +rect 204 97 210 99 +rect 213 103 219 104 +rect 213 99 214 103 +rect 218 99 219 103 +rect 213 97 219 99 +rect 95 90 97 92 +rect 95 88 99 90 +rect 102 88 104 90 +rect 195 89 199 97 +rect 206 89 208 97 +rect 215 89 217 97 +<< capacitor >> +rect 83 140 91 142 +rect 83 136 85 140 +rect 89 136 91 140 +rect 83 134 91 136 +rect 94 140 102 142 +rect 94 136 96 140 +rect 100 136 102 140 +rect 94 134 102 136 +rect 132 141 140 143 +rect 132 137 134 141 +rect 138 137 140 141 +rect 132 135 140 137 +rect 132 133 138 135 +rect 97 117 99 119 +rect 102 117 104 119 +rect 97 90 99 92 +rect 102 90 104 92 +rect 199 89 201 97 +rect 204 89 206 97 +rect 208 89 210 97 +rect 213 89 215 97 +rect 217 89 219 97 +<< wellcapacitor >> +rect 203 127 213 130 +<< ndiffusion >> +rect 38 213 42 216 +rect 45 213 49 216 +rect 68 214 80 217 +rect 68 213 76 214 +rect 68 209 76 211 +rect 122 213 124 217 +rect 122 210 132 213 +rect 68 204 76 207 +rect 68 201 71 204 +rect 122 202 132 208 +rect 189 205 205 209 +rect 33 181 37 184 +rect 33 178 37 179 +rect -14 168 -1 169 +rect -14 164 -10 168 +rect -2 164 -1 168 +rect -14 163 -1 164 +rect 1 163 5 169 +rect 41 166 44 170 +rect 30 163 44 166 +rect 80 166 83 173 +rect 106 164 118 168 +rect 128 119 131 126 +rect 203 130 213 134 +rect 99 94 102 95 +rect 99 86 102 88 +rect 131 86 136 91 +rect 144 86 148 90 +rect 99 82 100 86 +<< pdiffusion >> +rect 90 214 102 217 +rect 94 213 102 214 +rect 142 217 146 220 +rect 94 209 102 211 +rect 142 213 144 217 +rect 142 210 152 213 +rect 38 200 42 203 +rect 45 200 49 203 +rect 94 204 102 207 +rect 99 201 102 204 +rect 142 202 152 208 +rect 216 205 219 209 +rect 221 205 224 209 +rect -14 184 -1 185 +rect -14 180 -10 184 +rect -2 180 -1 184 +rect -14 179 -1 180 +rect 1 179 5 185 +rect 99 121 102 122 +rect 99 113 102 115 +rect 99 109 100 113 +<< metal1 >> +rect 49 168 53 170 +rect 78 169 88 172 +rect 106 169 109 173 +rect 175 171 179 176 +rect 83 162 93 165 +rect 157 162 160 165 +rect 175 162 179 167 +rect 133 141 137 147 +rect 81 136 85 140 +rect 89 136 96 140 +rect 133 137 134 141 +rect 133 131 137 137 +rect 133 121 137 123 +rect 48 102 63 117 +<< metal2 >> +rect 150 173 161 176 +rect 118 169 136 173 +rect 201 171 205 179 +rect 150 166 156 169 +rect 160 166 161 169 +rect 193 167 205 171 +rect 201 162 205 163 +rect 63 127 73 142 +<< metal3 >> +rect 200 172 214 178 +rect 178 171 194 172 +rect 178 167 179 171 +rect 193 167 194 171 +rect 178 166 194 167 +rect 200 167 214 168 +rect 200 163 201 167 +rect 205 163 214 167 +rect 200 162 214 163 +<< ntransistor >> +rect 68 211 76 213 +rect 68 207 76 209 +rect 122 208 132 210 +rect 33 179 37 181 +rect -1 163 1 169 +rect 99 92 102 94 +<< ptransistor >> +rect 94 211 102 213 +rect 94 207 102 209 +rect 142 208 152 210 +rect 219 205 221 209 +rect -1 179 1 185 +rect 99 119 102 121 +<< entransistor >> +rect 99 88 102 90 +<< eptransistor >> +rect 99 115 102 117 +<< doublentransistor >> +rect 99 90 102 92 +<< doubleptransistor >> +rect 99 117 102 119 +<< collector >> +rect 152 128 158 129 +rect 152 124 153 128 +rect 157 124 158 128 +rect 152 123 158 124 +<< pbase >> +rect 162 128 184 132 +rect 162 124 166 128 +rect 170 124 177 128 +rect 181 124 184 128 +rect 162 120 184 124 +<< bccdiffusion >> +rect 195 91 224 95 +<< nbccdiffusion >> +rect 193 91 195 95 +rect 224 91 226 95 +<< polycontact >> +rect 166 210 174 214 +rect 194 212 198 216 +rect 201 212 205 216 +rect 165 199 175 205 +rect 189 199 205 203 +rect 218 200 222 204 +rect 49 164 53 168 +rect 88 168 92 172 +rect 104 136 108 140 +rect 106 117 110 121 +rect 202 121 214 125 +rect 106 90 110 94 +rect 200 83 204 87 +rect 209 83 213 87 +rect 218 83 222 87 +<< ndcontact >> +rect 124 213 128 217 +rect 33 170 37 178 +rect 41 170 53 174 +rect -10 164 -2 168 +rect 79 162 83 166 +rect 203 134 213 138 +rect 99 95 103 99 +rect 100 82 104 86 +<< pdcontact >> +rect 144 213 148 217 +rect -10 180 -2 184 +rect 99 122 103 126 +rect 100 109 104 113 +<< capcontact >> +rect 85 136 89 140 +rect 96 136 100 140 +rect 134 137 138 141 +<< electrodecontact >> +rect 133 123 137 131 +rect 89 111 97 115 +rect 196 99 200 103 +rect 205 99 209 103 +rect 214 99 218 103 +<< collectorcontact >> +rect 153 124 157 128 +<< emittercontact >> +rect 166 124 170 128 +<< pbasecontact >> +rect 177 124 181 128 +<< nbccdiffcontact >> +rect 189 91 193 95 +rect 226 91 230 95 +<< m2contact >> +rect 109 169 118 173 +rect 136 169 140 173 +rect 156 165 160 169 +rect 175 167 179 171 +<< m3contact >> +rect 179 167 193 171 +rect 201 163 205 167 +<< psubstratepcontact >> +rect 128 213 132 217 +rect 140 169 144 173 +<< nsubstratencontact >> +rect 148 213 152 217 +<< psubstratepdiff >> +rect 53 211 57 216 +rect 135 173 144 174 +rect 135 169 140 173 +rect 135 168 144 169 +<< nsubstratendiff >> +rect 53 200 57 205 +<< pad >> +rect -7 102 33 142 +<< labels >> +rlabel space 163 173 163 176 3 9.1 +rlabel space 165 169 165 173 3 9.2 +rlabel space 163 165 163 166 3 9.3 +rlabel polysilicon 36 179 38 179 1 6b.7 +rlabel ndcontact 34 171 36 173 5 6b.1 +rlabel ndcontact 33 173 33 175 7 6b.3 +rlabel ndiffusion 37 166 42 166 1 6b.4 +rlabel ndcontact 50 171 52 173 1 _ +rlabel ndcontact 46 171 48 173 1 _ +rlabel ndcontact 42 171 44 173 1 _ +rlabel ndcontact 34 175 36 177 1 _ +rlabel ndiffusion 33 177 33 179 7 6b.6 +rlabel polycontact 50 165 52 167 1 _ +rlabel space 53 173 53 176 3 6b.8 +rlabel space 33 166 33 171 7 6b.5 +rlabel space 38 170 38 171 3 6b.2 +rlabel metal1 53 167 53 171 3 6b.9 +rlabel space 34 159 34 159 3 not_enforced +rlabel space 34 161 34 161 3 6b.8 +rlabel metal3 214 172 214 178 3 15.1 +rlabel space 208 168 208 172 3 15.2 +rlabel metal3 192 166 192 168 3 15.3 +rlabel space -7 144 33 144 1 10.1,10.2 +rlabel space 33 110 48 110 1 10.5 +rlabel space 33 132 63 132 1 10.4 +rlabel pad 23 132 23 142 3 10.3 +rlabel capacitor 83 142 91 142 1 11.1 +rlabel polysilicon 91 134 94 134 1 11.2 +rlabel polysilicon 81 142 81 144 7 11.3 +rlabel polysilicon 102 132 104 132 1 11.4 +rlabel polysilicon 102 137 105 137 1 11.5 +rlabel polycontact 105 137 107 139 1 _ +rlabel polycontact 107 118 109 120 1 _ +rlabel polysilicon 104 118 107 118 1 12.6 +rlabel space 94 117 94 119 7 12.5 +rlabel space 98 110 99 110 5 12.4 +rlabel space 85 115 88 115 1 12.2 +rlabel electrode 83 122 85 122 1 12.1 +rlabel m3contact 190 168 192 170 1 14.1 +rlabel m3contact 185 168 187 170 1 _ +rlabel m3contact 187 167 190 167 5 14.2 +rlabel m3contact 180 168 182 170 1 _ +rlabel m2contact 176 168 178 170 1 _ +rlabel metal3 178 171 180 171 1 14.4 +rlabel m3contact 202 164 204 166 1 _ +rlabel metal3 204 162 205 162 5 14.3 +rlabel nwell 158 123 162 123 1 16.2 +rlabel nwell 176 123 182 129 1 _ +rlabel nwell 164 122 172 130 1 _ +rlabel pbase 172 132 176 132 1 16.3 +rlabel pbase 162 132 164 132 1 16.4 +rlabel pbase 180 132 182 132 1 16.5 +rlabel pbasecontact 178 125 180 127 1 _ +rlabel nwell 152 114 158 114 1 16.6 +rlabel nwell 150 131 152 131 1 16.7 +rlabel emittercontact 167 125 169 127 1 16.8 +rlabel pbase 176 120 178 120 1 16.9 +rlabel collectorcontact 154 125 156 127 1 _ +rlabel nwell 156 130 158 130 1 16.10 +rlabel nwell 164 118 167 118 1 16.11 +rlabel polycontact 203 122 205 124 1 _ +rlabel polycontact 207 122 209 124 1 _ +rlabel polycontact 211 122 213 124 1 _ +rlabel space 199 124 199 127 7 18.4 +rlabel space 199 130 199 135 7 18.5 +rlabel capwell 202 141 203 141 1 18.2 +rlabel space 217 127 217 130 3 18.1 +rlabel space 221 130 221 138 3 18.3 +rlabel space 37 213 37 216 3 2.1 +rlabel space 42 212 45 212 1 2.2 +rlabel space 55 208 55 211 3 2.4 +rlabel space 50 208 50 213 3 2.3 +rlabel space 37 208 58 208 5 N-Region +rlabel space 37 208 58 208 1 P-Region +rlabel space 39 203 39 208 3 2.3 +rlabel space 59 205 59 208 3 2.4 +rlabel space 128 218 129 218 1 4.3 +rlabel space 134 210 134 213 3 4.1 +rlabel space 121 218 122 218 1 4.2 +rlabel space 173 216 175 216 1 5a.2 +rlabel polycontact 169 210 171 210 1 5a.3 +rlabel space 164 196 164 196 3 5a.2 +rlabel space 164 194 164 194 3 not_enforced +rlabel polycontact 167 211 169 213 1 _ +rlabel polycontact 171 211 173 213 1 5a.1 +rlabel polycontact 167 201 169 203 1 _ +rlabel polycontact 171 201 173 203 1 _ +rlabel space 80 211 80 213 3 3.1 +rlabel space 79 209 79 211 3 3.2 +rlabel space 80 204 80 207 3 3.4 +rlabel space 76 203 78 203 1 3.3 +rlabel space 67 219 68 219 1 3.5 +rlabel space 90 211 90 213 7 3.1 +rlabel space 91 209 91 211 7 3.2 +rlabel space 90 204 90 207 7 3.4 +rlabel space 92 203 94 203 1 3.3 +rlabel space 102 219 103 219 1 3.5 +rlabel space 197 218 198 218 1 5b.2 +rlabel space 197 212 202 212 1 5b.4 +rlabel space 204 212 208 212 1 5b.5 +rlabel polycontact 192 199 194 199 1 5b.3 +rlabel space 205 202 205 205 3 5b.7 +rlabel space 192 196 192 196 3 5b.7 +rlabel space 192 194 192 194 3 not_enforced +rlabel polycontact 202 200 204 202 1 _ +rlabel polycontact 198 200 200 202 1 _ +rlabel polycontact 194 200 196 202 1 _ +rlabel polycontact 190 200 192 202 1 _ +rlabel polycontact 195 213 197 215 1 5b.1 +rlabel polycontact 202 213 204 215 1 _ +rlabel space 223 203 223 205 3 5b.6 +rlabel space 216 199 216 199 3 (one_contact) +rlabel polycontact 219 201 221 203 1 _ +rlabel space 199 81 201 81 1 19.6 +rlabel space 195 87 197 87 5 19.5 +rlabel space 220 97 220 100 3 19.4 +rlabel space 189 95 189 97 7 19.3 +rlabel space 215 80 217 80 1 19.2 +rlabel space 232 91 232 95 3 19.1 +rlabel space -9 200 1 200 1 1.1 +rlabel space 1 221 10 221 1 1.2 +rlabel pdiffusion -3 182 -1 182 1 6a.4 +rlabel space -9 159 -9 159 3 not_enforced +rlabel space -9 161 -9 161 3 6a.2 +rlabel ndcontact -7 167 -5 167 1 6a.3 +rlabel pdcontact -9 181 -7 181 1 6a.1 +rlabel ndiffusion -10 167 -10 169 7 6a.2 +rlabel space 136 87 141 87 1 17.3 +rlabel capwell 141 83 144 83 5 17.4 +rlabel space 141 94 151 94 1 17.1 +rlabel space 151 87 160 87 1 17.2 +rlabel space 95 162 95 165 3 7.1 +rlabel space 93 168 93 169 3 7.3 +rlabel space 96 165 96 168 3 7.2 +rlabel space 77 165 77 166 7 7.4 +rlabel capcontact 135 138 137 140 1 13.1 +rlabel polysilicon 130 140 130 143 7 13.3 +rlabel space 132 147 134 147 1 13.4 +rlabel nwell 184 114 190 114 5 16.1 +rlabel space 112 162 115 162 1 8.2 +rlabel space 104 168 104 170 7 8.4 +rlabel space 104 172 104 174 7 8.4 +rlabel space 139 175 141 175 1 8.5 +rlabel space 137 166 139 166 5 8.1 +rlabel space 147 169 147 170 3 8.3 +rlabel space 146 172 146 174 3 8.4 +rlabel space 129 114 129 114 3 not_enforced +rlabel space 129 117 129 117 3 13.3,13.5* +rlabel space 142 126 142 128 3 13.2 +rlabel space 138 123 139 123 5 13.d* +rlabel electrodecontact 134 124 136 126 1 _ +rlabel electrodecontact 134 128 136 130 1 _ +rlabel space 131 127 132 127 5 13.5 +<< end >> diff --git a/scmos/rules/rule1.mag b/scmos/rules/rule1.mag new file mode 100644 index 00000000..d9316507 --- /dev/null +++ b/scmos/rules/rule1.mag @@ -0,0 +1,12 @@ +magic +tech scmos +timestamp 736070757 +<< pwell >> +rect -10 0 0 16 +<< nwell >> +rect 0 0 10 16 +rect 19 0 29 16 +<< labels >> +rlabel space 0 -3 10 -3 1 1.1 +rlabel space 10 18 19 18 1 1.2 +<< end >> diff --git a/scmos/rules/rule10.mag b/scmos/rules/rule10.mag new file mode 100644 index 00000000..81a572c3 --- /dev/null +++ b/scmos/rules/rule10.mag @@ -0,0 +1,11 @@ +magic +tech scmos +timestamp 736072873 +<< metal1 >> +rect 54 0 69 15 +rect 115 0 130 30 +<< metal2 >> +rect 130 50 140 90 +<< pad >> +rect 0 0 100 100 +<< end >> diff --git a/scmos/rules/rule11.mag b/scmos/rules/rule11.mag new file mode 100644 index 00000000..097f4fdd --- /dev/null +++ b/scmos/rules/rule11.mag @@ -0,0 +1,28 @@ +magic +tech scmos +timestamp 736072947 +<< nwell >> +rect 12 0 24 12 +<< polysilicon >> +rect 0 19 15 21 +rect 0 13 2 19 +rect 10 13 15 19 +rect 0 10 15 13 +rect 0 2 2 10 +rect 10 8 15 10 +rect 10 4 12 8 +rect 10 2 15 4 +rect 0 0 15 2 +<< capacitor >> +rect 2 13 10 19 +rect 2 8 10 10 +rect 2 4 4 8 +rect 8 4 10 8 +rect 2 2 10 4 +<< metal1 >> +rect -3 4 4 8 +<< polycontact >> +rect 12 4 16 8 +<< capcontact >> +rect 4 4 8 8 +<< end >> diff --git a/scmos/rules/rule12.mag b/scmos/rules/rule12.mag new file mode 100644 index 00000000..eea9ecde --- /dev/null +++ b/scmos/rules/rule12.mag @@ -0,0 +1,59 @@ +magic +tech scmos +timestamp 736073091 +<< polysilicon >> +rect 14 10 16 12 +rect 19 10 23 12 +rect 21 8 23 10 +rect 43 10 45 12 +rect 48 10 52 12 +rect 50 8 52 10 +<< poly2 >> +rect 7 0 9 20 +rect 12 8 14 10 +rect 41 8 43 10 +rect 12 6 16 8 +rect 19 6 21 8 +rect 41 7 45 8 +rect 34 6 45 7 +rect 48 6 50 8 +rect 34 2 35 6 +rect 43 2 44 6 +rect 34 1 44 2 +<< capacitor >> +rect 14 8 16 10 +rect 19 8 21 10 +rect 43 8 45 10 +rect 48 8 50 10 +<< ndiffusion >> +rect 16 12 19 13 +rect 16 4 19 6 +rect 16 0 17 4 +<< pdiffusion >> +rect 45 12 48 13 +rect 45 4 48 6 +rect 45 0 46 4 +<< ntransistor >> +rect 16 10 19 12 +<< ptransistor >> +rect 45 10 48 12 +<< entransistor >> +rect 16 6 19 8 +<< eptransistor >> +rect 45 6 48 8 +<< doublentransistor >> +rect 16 8 19 10 +<< doubleptransistor >> +rect 45 8 48 10 +<< polycontact >> +rect 23 8 27 12 +rect 52 8 56 12 +<< ndcontact >> +rect 16 13 20 17 +rect 17 0 21 4 +<< pdcontact >> +rect 45 13 49 17 +rect 46 0 50 4 +<< electrodecontact >> +rect 35 2 43 6 +<< end >> diff --git a/scmos/rules/rule14.mag b/scmos/rules/rule14.mag new file mode 100644 index 00000000..84485213 --- /dev/null +++ b/scmos/rules/rule14.mag @@ -0,0 +1,42 @@ +magic +tech scmos +timestamp 726211220 +<< metal1 >> +rect 0 19 4 23 +rect 0 15 14 19 +rect 0 9 4 15 +rect 0 0 4 5 +<< metal2 >> +rect 18 15 19 19 +rect 23 15 24 19 +rect 19 14 24 15 +rect 19 10 20 14 +rect 19 9 24 10 +rect 13 5 19 9 +rect 23 5 28 9 +<< metal3 >> +rect 18 19 25 23 +rect 18 15 19 19 +rect 23 15 25 19 +rect 18 14 25 15 +rect 8 10 14 14 +rect 3 9 14 10 +rect 3 5 4 9 +rect 13 5 14 9 +rect 3 4 14 5 +rect 8 0 14 4 +rect 18 10 20 14 +rect 24 10 25 14 +rect 18 9 25 10 +rect 18 5 19 9 +rect 23 5 25 9 +rect 18 0 25 5 +<< m2contact >> +rect 14 15 18 19 +rect 0 5 4 9 +<< m3contact >> +rect 19 15 23 19 +rect 20 10 24 14 +rect 4 5 13 9 +rect 19 5 23 9 +<< end >> diff --git a/scmos/rules/rule15.mag b/scmos/rules/rule15.mag new file mode 100644 index 00000000..8f1cfc33 --- /dev/null +++ b/scmos/rules/rule15.mag @@ -0,0 +1,18 @@ +magic +tech scmos +timestamp 736072621 +<< metal2 >> +rect 1 5 5 16 +rect 5 1 6 5 +rect 1 0 5 1 +<< metal3 >> +rect 0 10 14 16 +rect 0 5 14 6 +rect 0 1 1 5 +rect 5 1 6 5 +rect 10 1 14 5 +rect 0 0 14 1 +<< m3contact >> +rect 1 1 5 5 +rect 6 1 10 5 +<< end >> diff --git a/scmos/rules/rule16.mag b/scmos/rules/rule16.mag new file mode 100644 index 00000000..e7ef3378 --- /dev/null +++ b/scmos/rules/rule16.mag @@ -0,0 +1,82 @@ +magic +tech scmos +timestamp 783738099 +<< nwell >> +rect 2 54 40 59 +rect -1 40 40 54 +rect 2 35 40 40 +rect 49 36 90 60 +rect 49 26 62 27 +rect -1 0 40 24 +rect 49 0 95 26 +<< collector >> +rect 2 49 8 50 +rect 2 45 3 49 +rect 7 45 8 49 +rect 2 44 8 45 +rect 52 50 58 51 +rect 52 46 53 50 +rect 57 46 58 50 +rect 52 45 58 46 +rect 52 23 58 24 +rect 52 19 53 23 +rect 57 19 58 23 +rect 52 18 58 19 +rect 2 14 8 15 +rect 2 10 3 14 +rect 7 10 8 14 +rect 2 9 8 10 +rect 86 15 92 21 +rect 52 13 58 14 +rect 52 9 53 13 +rect 57 9 58 13 +rect 52 8 58 9 +rect 86 6 92 12 +<< emitter >> +rect 66 46 70 50 +<< pbase >> +rect 12 52 24 53 +rect 12 49 34 52 +rect 12 45 16 49 +rect 20 45 27 49 +rect 31 45 34 49 +rect 62 50 84 54 +rect 62 46 66 50 +rect 70 46 77 50 +rect 81 46 84 50 +rect 12 42 34 45 +rect 62 42 84 46 +rect 12 41 25 42 +rect 12 14 34 18 +rect 62 14 82 18 +rect 12 10 16 14 +rect 20 10 27 14 +rect 31 10 34 14 +rect 12 6 34 10 +rect 62 10 66 14 +rect 78 10 82 14 +rect 62 6 82 10 +<< collectorcontact >> +rect 3 45 7 49 +rect 53 46 57 50 +rect 53 19 57 23 +rect 3 10 7 14 +rect 53 9 57 13 +<< emittercontact >> +rect 16 45 20 49 +rect 16 10 20 14 +rect 66 10 78 14 +<< pbasecontact >> +rect 27 45 31 49 +rect 77 46 81 50 +rect 27 10 31 14 +<< labels >> +rlabel pbase 23 15 23 15 1 a +rlabel emittercontact 18 12 18 12 1 b +rlabel emittercontact 18 47 18 47 1 a +rlabel collectorcontact 5 47 5 47 1 c +rlabel pbasecontact 29 47 29 47 1 b +rlabel collector 89 18 89 18 1 d +rlabel collectorcontact 55 48 55 48 1 c +rlabel pbasecontact 79 48 79 48 1 b +<< end >> diff --git a/scmos/rules/rule17.mag b/scmos/rules/rule17.mag new file mode 100644 index 00000000..08be50ec --- /dev/null +++ b/scmos/rules/rule17.mag @@ -0,0 +1,29 @@ +magic +tech scmos +timestamp 736076273 +<< capwell >> +rect 0 0 10 12 +rect 19 0 29 12 +<< polysilicon >> +rect 9 22 12 24 +rect 16 22 21 24 +rect 25 22 28 24 +<< ndiffusion >> +rect 12 24 16 27 +rect 21 24 25 27 +rect 12 17 16 22 +rect 21 21 25 22 +rect 3 3 7 9 +<< ntransistor >> +rect 12 22 16 24 +rect 21 22 25 24 +<< ndcontact >> +rect 21 17 25 21 +rect 31 17 35 21 +<< psubstratepcontact >> +rect -6 15 -2 19 +rect 4 15 8 19 +<< labels >> +rlabel space 14 -5 34 17 1 boundary +rlabel space -3 -3 13 15 1 boundary +<< end >> diff --git a/scmos/rules/rule18.mag b/scmos/rules/rule18.mag new file mode 100644 index 00000000..4d8b6376 --- /dev/null +++ b/scmos/rules/rule18.mag @@ -0,0 +1,28 @@ +magic +tech scmos +timestamp 732461619 +<< capwell >> +rect 0 0 12 26 +rect 21 0 45 26 +<< polysilicon >> +rect 2 4 3 15 +rect 42 13 46 16 +rect 2 2 6 4 +<< wellcapacitor >> +rect 3 4 6 15 +rect 27 16 39 20 +rect 27 13 42 16 +rect 27 6 39 13 +<< ndiffusion >> +rect 3 15 9 19 +rect 6 4 9 15 +rect 24 20 42 23 +rect 24 6 27 20 +rect 39 16 42 20 +rect 39 6 42 13 +rect 24 3 42 6 +<< polycontact >> +rect 2 -2 6 2 +<< ndcontact >> +rect 3 19 9 23 +<< end >> diff --git a/scmos/rules/rule19.mag b/scmos/rules/rule19.mag new file mode 100644 index 00000000..81713833 --- /dev/null +++ b/scmos/rules/rule19.mag @@ -0,0 +1,61 @@ +magic +tech scmos +timestamp 736034963 +<< polysilicon >> +rect 12 -2 15 14 +rect 21 -2 24 14 +rect 30 -2 35 14 +rect 10 -4 17 -2 +rect 10 -8 11 -4 +rect 15 -8 17 -4 +rect 19 -4 26 -2 +rect 19 -8 20 -4 +rect 24 -8 26 -4 +rect 28 -4 35 -2 +rect 28 -8 29 -4 +rect 33 -8 35 -4 +<< poly2 >> +rect 6 20 12 21 +rect 6 16 7 20 +rect 11 16 12 20 +rect 6 14 12 16 +rect 15 20 21 21 +rect 15 16 16 20 +rect 20 16 21 20 +rect 15 14 21 16 +rect 24 20 30 21 +rect 24 16 25 20 +rect 29 16 30 20 +rect 24 14 30 16 +rect 6 -2 10 14 +rect 17 -2 19 14 +rect 26 -2 28 14 +<< capacitor >> +rect 10 -2 12 14 +rect 15 -2 17 14 +rect 19 -2 21 14 +rect 24 -2 26 14 +rect 28 -2 30 14 +<< bccdiffusion >> +rect 15 12 17 14 +rect 6 8 35 12 +rect 6 0 35 4 +<< nbccdiffusion >> +rect 4 8 6 12 +rect 4 0 6 4 +rect 35 8 37 12 +rect 35 0 37 4 +<< polycontact >> +rect 11 -8 15 -4 +rect 20 -8 24 -4 +rect 29 -8 33 -4 +<< electrodecontact >> +rect 7 16 11 20 +rect 16 16 20 20 +rect 25 16 29 20 +<< nbccdiffcontact >> +rect 0 8 4 12 +rect 0 0 4 4 +rect 37 8 41 12 +rect 37 0 41 4 +<< end >> diff --git a/scmos/rules/rule2.mag b/scmos/rules/rule2.mag new file mode 100644 index 00000000..d15bbe94 --- /dev/null +++ b/scmos/rules/rule2.mag @@ -0,0 +1,24 @@ +magic +tech scmos +timestamp 736070890 +<< nwell >> +rect -2 -2 20 8 +<< ndiffusion >> +rect 0 13 4 16 +rect 7 13 11 16 +<< pdiffusion >> +rect 0 0 4 3 +rect 7 0 11 3 +<< psubstratepdiff >> +rect 15 11 18 16 +<< nsubstratendiff >> +rect 15 0 18 5 +<< labels >> +rlabel nwell -1 8 20 8 1 P-Region +rlabel nwell -1 8 20 8 5 N-Region +rlabel space -1 13 -1 16 3 2.1 +rlabel space 4 12 7 12 1 2.2 +rlabel space 17 8 17 11 3 2.4 +rlabel space 12 8 12 13 3 2.3 +rlabel nwell 6 3 6 8 3 2.3 +<< end >> diff --git a/scmos/rules/rule3.mag b/scmos/rules/rule3.mag new file mode 100644 index 00000000..bd6cc56a --- /dev/null +++ b/scmos/rules/rule3.mag @@ -0,0 +1,52 @@ +magic +tech scmos +timestamp 736070986 +<< polysilicon >> +rect -3 12 -1 17 +rect 35 12 37 17 +rect -3 10 0 12 +rect 8 10 10 12 +rect 24 10 26 12 +rect 34 10 37 12 +rect -3 6 0 8 +rect 8 6 10 8 +rect 24 6 26 8 +rect 34 6 37 8 +rect -3 1 -1 6 +rect 35 1 37 6 +<< ndiffusion >> +rect 0 13 12 16 +rect 0 12 8 13 +rect 0 8 8 10 +rect 0 3 8 6 +rect 0 0 3 3 +<< pdiffusion >> +rect 22 13 34 16 +rect 26 12 34 13 +rect 26 8 34 10 +rect 26 3 34 6 +rect 31 0 34 3 +<< ntransistor >> +rect 0 10 8 12 +rect 0 6 8 8 +<< ptransistor >> +rect 26 10 34 12 +rect 26 6 34 8 +<< labels >> +rlabel space 12 10 12 12 3 3.1 +rlabel space 11 8 11 10 3 3.2 +rlabel space 12 3 12 6 3 3.4 +rlabel space -1 18 0 18 1 3.5 +rlabel space 22 10 22 12 7 3.1 +rlabel space 23 8 23 10 7 3.2 +rlabel space 22 3 22 6 7 3.4 +rlabel space 24 2 26 2 1 3.3 +rlabel space -1 -17 34 -2 1 poly +rlabel space 2 -4 2 -4 3 3.1______width______2 +rlabel space 2 -7 2 -7 3 3.2______space______2 +rlabel space 2 -10 2 -10 3 3.3______gate_overlap____2 +rlabel space 2 -13 2 -13 3 3.4______active_overlap__3 +rlabel space 2 -16 2 -16 3 3.5______to_active_____1 +rlabel space 34 18 35 18 1 3.5 +rlabel space 8 2 10 2 1 3.3 +<< end >> diff --git a/scmos/rules/rule4.mag b/scmos/rules/rule4.mag new file mode 100644 index 00000000..36b628bc --- /dev/null +++ b/scmos/rules/rule4.mag @@ -0,0 +1,44 @@ +magic +tech scmos +timestamp 717145414 +<< polysilicon >> +rect -3 8 -1 15 +rect -3 6 0 8 +rect 10 6 20 8 +rect 30 6 33 8 +rect 31 0 33 6 +<< ndiffusion >> +rect 0 15 4 18 +rect 0 11 2 15 +rect 0 8 10 11 +rect 0 5 10 6 +rect 0 1 3 5 +rect 7 1 10 5 +rect 0 0 10 1 +<< pdiffusion >> +rect 20 15 24 18 +rect 20 11 22 15 +rect 20 8 30 11 +rect 20 5 30 6 +rect 20 1 23 5 +rect 27 1 30 5 +rect 20 0 30 1 +<< ntransistor >> +rect 0 6 10 8 +<< ptransistor >> +rect 20 6 30 8 +<< ndcontact >> +rect 2 11 6 15 +rect 3 1 7 5 +<< pdcontact >> +rect 22 11 26 15 +rect 23 1 27 5 +<< psubstratepcontact >> +rect 6 11 10 15 +<< nsubstratencontact >> +rect 26 11 30 15 +<< labels >> +rlabel space -2 -2 0 -2 1 4.2 +rlabel space 6 16 7 16 1 4.3 +rlabel space 12 8 12 11 3 4.1 +<< end >> diff --git a/scmos/rules/rule4_2.mag b/scmos/rules/rule4_2.mag new file mode 100644 index 00000000..89b9d511 --- /dev/null +++ b/scmos/rules/rule4_2.mag @@ -0,0 +1,132 @@ +magic +tech scmos +timestamp 751931635 +<< polysilicon >> +rect 18 73 26 75 +rect 18 72 20 73 +rect 18 52 20 62 +rect 49 60 51 66 +rect 49 58 52 60 +rect 62 58 72 60 +rect 82 58 85 60 +rect 83 51 85 58 +rect 18 41 20 42 +rect 11 39 20 41 +rect 55 32 64 34 +rect 55 31 57 32 +rect -3 17 -1 24 +rect -3 15 0 17 +rect 10 15 20 17 +rect 30 15 33 17 +rect 31 9 33 15 +rect 55 11 57 21 +rect 55 0 57 1 +rect 49 -2 57 0 +<< ndiffusion >> +rect 72 65 82 66 +rect 72 61 75 65 +rect 79 61 82 65 +rect 72 60 82 61 +rect 8 44 11 46 +rect 15 44 18 52 +rect 8 42 18 44 +rect 20 49 26 52 +rect 72 55 82 58 +rect 80 51 82 55 +rect 20 45 21 49 +rect 25 45 26 49 +rect 78 48 82 51 +rect 20 42 26 45 +rect 49 28 55 31 +rect 0 24 4 27 +rect 49 24 50 28 +rect 54 24 55 28 +rect 0 20 2 24 +rect 0 17 10 20 +rect 49 21 55 24 +rect 57 29 67 31 +rect 57 21 60 29 +rect 64 27 67 29 +rect 0 14 10 15 +rect 0 10 3 14 +rect 7 10 10 14 +rect 0 9 10 10 +<< pdiffusion >> +rect 8 64 11 66 +rect 15 64 18 72 +rect 8 62 18 64 +rect 20 69 26 72 +rect 20 65 21 69 +rect 25 65 26 69 +rect 20 62 26 65 +rect 52 65 62 66 +rect 52 61 55 65 +rect 59 61 62 65 +rect 52 60 62 61 +rect 52 55 62 58 +rect 60 51 62 55 +rect 58 48 62 51 +rect 20 24 24 27 +rect 20 20 22 24 +rect 20 17 30 20 +rect 20 14 30 15 +rect 20 10 23 14 +rect 27 10 30 14 +rect 20 9 30 10 +rect 49 8 55 11 +rect 49 4 50 8 +rect 54 4 55 8 +rect 49 1 55 4 +rect 57 9 67 11 +rect 57 1 60 9 +rect 64 7 67 9 +<< ntransistor >> +rect 72 58 82 60 +rect 18 42 20 52 +rect 55 21 57 31 +rect 0 15 10 17 +<< ptransistor >> +rect 18 62 20 72 +rect 52 58 62 60 +rect 20 15 30 17 +rect 55 1 57 11 +<< ndcontact >> +rect 75 61 79 65 +rect 11 44 15 48 +rect 76 51 80 55 +rect 21 45 25 49 +rect 50 24 54 28 +rect 2 20 6 24 +rect 60 25 64 29 +rect 3 10 7 14 +<< pdcontact >> +rect 11 64 15 68 +rect 21 65 25 69 +rect 55 61 59 65 +rect 56 51 60 55 +rect 22 20 26 24 +rect 23 10 27 14 +rect 50 4 54 8 +rect 60 5 64 9 +<< psubstratepcontact >> +rect 11 48 15 52 +rect 72 51 76 55 +rect 6 20 10 24 +rect 60 21 64 25 +<< nsubstratencontact >> +rect 11 68 15 72 +rect 52 51 56 55 +rect 26 20 30 24 +rect 60 1 64 5 +<< labels >> +rlabel space 47 31 47 33 3 4.2 +rlabel space 65 24 65 25 3 4.3 +rlabel space 57 19 60 19 5 4.1 +rlabel space 75 50 76 50 5 4.3 +rlabel space 70 55 70 58 7 4.1 +rlabel space 10 48 10 49 7 4.3 +rlabel space 15 54 18 54 1 4.1 +rlabel space -2 7 0 7 1 4.2 +rlabel space 6 25 7 25 1 4.3 +rlabel space 12 17 12 20 3 4.1 +<< end >> diff --git a/scmos/rules/rule5a.mag b/scmos/rules/rule5a.mag new file mode 100644 index 00000000..72e5bd2f --- /dev/null +++ b/scmos/rules/rule5a.mag @@ -0,0 +1,6 @@ +magic +tech scmos +timestamp 716090279 +<< polycontact >> +rect 0 0 12 4 +<< end >> diff --git a/scmos/rules/rule5b.mag b/scmos/rules/rule5b.mag new file mode 100644 index 00000000..28bb0ee5 --- /dev/null +++ b/scmos/rules/rule5b.mag @@ -0,0 +1,28 @@ +magic +tech scmos +timestamp 736035532 +<< polysilicon >> +rect 13 16 15 19 +rect 1 13 5 15 +rect 19 12 21 19 +rect 31 9 33 12 +rect 31 4 33 5 +<< ndiffusion >> +rect 0 5 16 9 +<< pdiffusion >> +rect 28 5 31 9 +rect 33 5 36 9 +<< ptransistor >> +rect 31 5 33 9 +<< polycontact >> +rect 5 12 9 16 +rect 12 12 16 16 +rect 0 0 16 4 +rect 30 0 34 4 +<< labels >> +rlabel ndiffusion 4 7 4 7 1 a +rlabel ptransistor 32 7 32 7 1 b +rlabel polycontact 32 2 32 2 1 c +rlabel pdiffusion 29 7 29 7 1 f +rlabel polysilicon 20 15 20 15 1 d +<< end >> diff --git a/scmos/rules/rule6a.mag b/scmos/rules/rule6a.mag new file mode 100644 index 00000000..bc69e0b4 --- /dev/null +++ b/scmos/rules/rule6a.mag @@ -0,0 +1,24 @@ +magic +tech scmos +timestamp 715647645 +<< polysilicon >> +rect 9 20 11 22 +rect 9 6 11 16 +rect 9 0 11 2 +<< ndiffusion >> +rect 0 2 4 6 +rect 8 2 9 6 +rect 11 2 15 6 +<< pdiffusion >> +rect 0 16 4 20 +rect 8 16 9 20 +rect 11 16 15 20 +<< ndcontact >> +rect 4 2 8 6 +<< pdcontact >> +rect 4 16 8 20 +<< ntransistor >> +rect 9 2 11 6 +<< ptransistor >> +rect 9 16 11 20 +<< end >> diff --git a/scmos/rules/rule6b.mag b/scmos/rules/rule6b.mag new file mode 100644 index 00000000..34c86435 --- /dev/null +++ b/scmos/rules/rule6b.mag @@ -0,0 +1,23 @@ +magic +tech scmos +timestamp 736071673 +<< polysilicon >> +rect 1 17 3 19 +rect 7 17 10 19 +rect 8 16 10 17 +rect 8 14 23 16 +<< ndiffusion >> +rect 3 19 7 22 +rect 3 16 7 17 +rect 11 4 14 9 +rect 0 1 14 4 +<< metal1 >> +rect 19 7 23 9 +<< ntransistor >> +rect 3 17 7 19 +<< polycontact >> +rect 19 3 23 7 +<< ndcontact >> +rect 3 8 7 16 +rect 11 9 23 13 +<< end >> diff --git a/scmos/rules/rule7.mag b/scmos/rules/rule7.mag new file mode 100644 index 00000000..59ab828b --- /dev/null +++ b/scmos/rules/rule7.mag @@ -0,0 +1,20 @@ +magic +tech scmos +timestamp 715648344 +<< polysilicon >> +rect 11 0 13 6 +<< ndiffusion >> +rect 2 4 5 11 +<< metal1 >> +rect 0 7 10 10 +rect 5 0 15 3 +<< polycontact >> +rect 10 6 14 10 +<< ndcontact >> +rect 1 0 5 4 +<< labels >> +rlabel space 0 3 0 4 7 7.4 +rlabel space 17 0 17 3 3 7.1 +rlabel space 15 6 15 7 3 7.3 +rlabel space 18 3 18 6 3 7.2 +<< end >> diff --git a/scmos/rules/rule8.mag b/scmos/rules/rule8.mag new file mode 100644 index 00000000..62669988 --- /dev/null +++ b/scmos/rules/rule8.mag @@ -0,0 +1,42 @@ +magic +tech scmos +timestamp 772488492 +<< polysilicon >> +rect 0 10 12 12 +<< ndiffusion >> +rect 0 0 12 4 +<< metal1 >> +rect 3 23 7 25 +rect 3 19 4 23 +rect 3 18 7 19 +rect 22 11 23 15 +rect 18 9 23 11 +rect 0 5 3 9 +<< metal2 >> +rect 3 23 7 25 +rect 3 19 4 23 +rect 3 18 7 19 +rect 18 9 22 11 +rect 12 5 20 9 +<< m2contact >> +rect 3 25 7 33 +rect 4 19 10 23 +rect 3 14 7 18 +rect 18 11 22 15 +rect 3 5 12 9 +rect 20 5 24 9 +<< psubstratepcontact >> +rect 24 5 28 9 +<< psubstratepdiff >> +rect 18 9 28 10 +rect 18 5 24 9 +rect 18 4 28 5 +<< labels >> +rlabel space -1 8 -1 10 7 8.4 +rlabel space -1 4 -1 6 7 8.4 +rlabel space 6 -2 9 -2 1 8.2 +rlabel space 23 11 25 11 1 8.5 +rlabel space 30 8 30 10 3 8.4 +rlabel space 31 5 31 6 3 8.3 +rlabel space 21 2 23 2 5 8.1 +<< end >> diff --git a/scmos/rules/rule9.mag b/scmos/rules/rule9.mag new file mode 100644 index 00000000..4c1964ee --- /dev/null +++ b/scmos/rules/rule9.mag @@ -0,0 +1,16 @@ +magic +tech scmos +timestamp 715648933 +<< metal1 >> +rect 7 0 10 3 +<< metal2 >> +rect 0 11 11 14 +rect 0 4 6 7 +rect 10 4 11 7 +<< m2contact >> +rect 6 3 10 7 +<< labels >> +rlabel space 13 11 13 14 3 9.1 +rlabel space 15 7 15 11 3 9.2 +rlabel space 13 3 13 4 3 9.3 +<< end >> diff --git a/scmos/scmos.tech.in b/scmos/scmos.tech.in new file mode 100644 index 00000000..cfce72e7 --- /dev/null +++ b/scmos/scmos.tech.in @@ -0,0 +1,3256 @@ +/* --------------------------------------------------------------------* + * * + * scmos.tech -- MOSIS Scalable CMOS (SCMOS) Magic technology file. * + * * + * MOSIS distribution Version 8.2 * + * * + * Defines the MOSIS 0.6/0.8/1.0/1.2/2.0 micron Scalable CMOS * + * (SCMOS) technology. * + * * + * (C) Copyright 1992, 1993, 1994, 1995 by * + * * + * Jen-I Pi pi@isi.edu * + * The MOSIS Service * + * USC Information Sciences Institute * + * 4676 Admiralty Way * + * Marina del Rey, CA 90292 * + * voice: (310) 822-1511 x640, fax: (310)823-5624 * + * * + * All Rights Reserved. * + * Last Modified Date: 04/26/1995 * + * * + * Permission to use, copy, modify, and distribute this technology * + * file and its associated documentation for any purpose and without * + * fee is hereby granted, provided that the above copyright notice * + * appears in all copies and that both that copyright notice and this * + * permission notice appear in supporting documentation, and that the * + * name of the University of Southern California not be used in * + * advertising or publicity pertaining to distribution of this * + * technology file without specific, written prior permission. * + * The University of Southern California makes no representations * + * about the suitability of this technology file for any purpose. * + * This technology file is provided "as is" without express or implied * + * warranty and the University of Southern California retains the * + * right to change its content at any time without notice any other * + * party. * + * * + * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH * + * REGARD TO THIS TECHNOLOGY FILE, INCLUDING ALL IMPLIED WARRANTIES OF * + * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * + * SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR * + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS TECHNOLOGY FILE. * + * * + * ------------------------------------------------------------------- */ + +/* --------------------------------------------------------------------* + * Some of the characteristics of this technology are: * + * * + * 1. 3 levels of metal - for HP's CMOS26B (lambda=0.5) and CMOS26G * + * (lambda=0.4) and CMOS14TB (lambda=0.35 or 0.3) processes * + * 3 levels of metal stack via - for IBM's CMSX2185 (lambda=0.4) * + * process * + * 2 levels of metal interconnection for all other technologies * + * 2. 2 levels of poly - for ORBIT's low-noise analog process * + * second poly is used for poly-capacitor or electrode fet (efet) * + * 3. Vertical NPN transistor, BCCD device, Floating-gate device for * + * ORBIT's low-noise anaolog process * + * 4. All contacts are composite (with the necessary enclosure) * + * 5. No stacked contacts (all contacts are to 1st-level metal) * + * 6. An open layer is added for fabrication of micromachined devices * + * as in Janet C. Marshall's paper in IEEE Circuit and Devices, * + * Vol. 8, N0. 6, 1992. * + * This layer is currently NOT available for standard MOSIS SCMOS * + * techonology installation. You need to define OPEN with the C- * + * preprocessor for installation. See README file for detail... * + * 7 A pstop layer is used also in micromachineing device fabrication * + * to stop the EDP etchant as used in Marshall's article. * + * 8 A Cap-well (cwell) for HP's CMOS34 (lambda=0.6) process, It is * + * used for consctruction of linear capacitors * + * Must be drawn explicitly * + * 9. Wells (Pwell or Nwell) can be implicit or explicit in the layout * + * and both types of diffusion must have well contacts * + *10. Painting Nwell over N-type diffusion will result in P-type * + * diffusion * + *11. Scalable with Default to be 2.0 micron rules for Nwell process * + *12. Substrate contacts must be 3 units away from gates * + *13. Stacked via supported through special compiled option -DSTACKVIA * + * for IBM process. * + * * + * Revision 8.2.8 (pi) * + * fix CCD CIF input style for "bd" layer. * + * 12/13/95 pi@isi.edu * + * Revision 8.2.7 (pi) * + * Add Magic 6.4.4 new extraction plane orders. * + * 07/25/95 pi@isi.edu * + * Revision 8.2.5 (pi) * + * Fix some typos... * + * 05/12/95 pi@isi.edu * + * Revision 8.2.4 (pi) * + * Fix CBA generation for pbase and add extension rules for pbase * + * as resistors. * + * Gratitude goes to Tetsuya Kajita (kaj@ssac.yamatake.co.jp) * + * 04/26/95 pi@isi.edu * + * Revision 8.2.3 (pi) * + * fix for SUBMICRON DRC rule. * + * Thanks goes to Toby Schaffer (jtschaff@eos.ncsu.edu) * + * 04/06/95 pi@isi.edu * + * Revision 8.2.2 (pi) * + * add XP GDS official number to fix CIF input problem for "pad". * + * Thanks goes to Brian Kingsbury (bedk@ICSI.Berkeley.EDU). * + * 04/03/95 pi@isi.edu * + * Revision 8.2.1 (pi) * + * Some fixes for CMOS14B CIF output section. * + * 03/21/95 pi@isi.edu * + * Revision 8.2.0 (pi) * + * support for HP CMOS26G and CMOS14TB process. * + * 03/15/95 pi@isi.edu * + * Revision 8.1.1 (pi) * + * add connection of "ndiff" to "psd". Thank goes to Alireza Moini* + * (moini@eleceng.adelaide.edu.au). * + * 12/21/94 pi@isi.edu * + * Revision 8.1.0 (pi) * + * major revision of bipolar transistor rules. It now support * + * both ORBIT 2.0 and 1.2 micron processes. NOTE: active layer * + * for pbase is now generated in CIF file explicitly. * + * 10/31/94 pi@isi.edu * + * Revision 8.0.7 (pi) * + * remove both VTI and IBM support * + * 10/10/94 pi@isi.edu * + * Revision 8.0.7 (pi) * + * compose for high-voltage transistors corrected. Thank goes to * + * Bob Durie (bobd@ee.cornell.edu) * + * 8/25/94 pi@isi.edu * + * Revision 8.0.6 (pi) * + * DRC rule 2.2 add allNOhmic to allNOhmic and allPOhmic to * + * allPOhmic rule. Thank goes to Shih-Lien Lu. * + * (sllu@caleb.ECE.ORST.EDU) * + * 6/28/94 pi@isi.edu * + * Revision 8.0.5 (pi) * + * DRC rule 3.5 reverse back to old style to avoid a mischeck on * + * corners. Thank goes to Wen-King Su. * + * (wen-king@vlsi.cs.caltech.edu) * + * 4/20/94 pi@isi.edu * + * Revision 8.0.4 (pi) * + * SCPE20(ORB) extraction P-well sheet resistance fixed. Thank * + * goes to Nagendra Shivakumar (nshivaku@phyast.nhn.uoknor.edu). * + * 3/04/94 pi@isi.edu * + * Revision 8.0.3 (pi) * + * Wellcap drawing problem fixed. Thank goes to Mario Aranha * + * (mario@cad4.lbl.gov). * + * 2/03/94 pi@isi.edu * + * Revision 8.0.2 (pi) * + * CIF read fix for linear capacitor. Thank goes to Issy Kipnis * + * (kipnis@cad4.lbl.gov). * + * 2/03/94 pi@isi.edu * + * Revision 8.0.1 (pi) * + * DRC updates for separate diffusion width check. Thank goes to * + * John Poulton (jp@cs.unc.edu). * + * 10/04/93 pi@isi.edu * + * Revision 8.0.0 (pi) * + * DRC revision 8 installed and layer support for High-Voltage * + * MOSFETs for SCNA16 process. * + * 10/04/93 pi@isi.edu * + * Revision 7.4.0 (pi) * + * Brand new extraction section and other fixes :-) * + * 10/01/93 pi@isi.edu * + * Revision 7.3.3 (pi) * + * pbc surrounding rule fixed. 4.1.c fixed also * + * 6/01/93 pi@isi.edu * + * Revision 7.3.2 (pi) * + * exchnage CCD and CBA calma (GDS) number to the correct setting * + * 4/27/93 pi@isi.edu * + * Revision 7.3.1 (pi) * + * Various DRC rule changes contributed by Barry Boes at AuE * + * (boes@corona.AuE.com). * + * allNDiff/allPOhmic in connection section update, thanks go to * + * Brian Kingsbury from Bekerley (bedk@icsi.berkeley.edu). * + * 3/30/93 pi@isi.edu * + * Revision 7.3.0 (pi) * + * add three new layers intended for ESD preotection devices * + * remove the temporary "pad2" layer, now all pads use "pad" * + * CIFin and CIFout now in templates, thank goes to Shih-Lien Lu * + * at Origon State Univ. sllu@caleb.ECE.ORST.EDU. * + * Some design rule changes (relabeling for doc)... * + * 3/19/93 pi@isi.edu * + * Revision 7.2.2 (pi) * + * change all "bloat-min" select generation back to "bloat-or" * + * restore all lambda=0.8 style since some people use ORBIT's run * + * though MOSIS does NOT provide HP's process anymore * + * 3/09/93 pi@isi.edu * + * Revision 7.2.1 (pi) * + * add missing Cifinput "pbase" layer for lambda=1.0(oldnwell) * + * style. Thank goes to Brian Von Herzen at Synaptics, Inc. * + * 2/18/93 pi@isi.edu * + * Revision 7.2.0 (pi) * + * A serious bug in CIF well generation is fixed... * + * 1/14/93 pi@isi.edu * + * Revision 7.1.4 (pi) * + * Remove lambda=1.5 and lambda=0.8 technology which are not * + * provided by MOSIS any more. * + * 1/12/93 pi@isi.edu * + * Revision 7.1.3 (pi) * + * Add pstop layer and the corresponding CIFin CIFout stuff * + * Reverse the last change about CCA layer under pad for CMOS26B * + * 1/08/93 pi@isi.edu * + * Revision 7.1.2 (pi) * + * Various problem fix... and make the "open" layer as an option * + * Reverse the last change about CCA layer under pad for CMOS26B * + * 12/29/92 pi@isi.edu * + * Revision 7.1.1 (pi) * + * A series bug fix for HP's CMOS26B pad layers - remove CCA CIF * + * layer. Thank goes to ndu@aue.com * + * 12/12/92 pi@isi.edu * + * Revision 7.1.0 (pi) * + * A new layer "open" for micromachined device fabracation. * + * Thanks goes to Janet Marchall from NIST. * + * (marshall@sed.eeel.nist.gov) * + * 12/15/92 pi@isi.edu * + * Revision 7.0.4 (pi) * + * C-preprocessing fix. Thanks goes to Jeffrey C. Gealow form * + * MIT (jgealow@mtl.mit.edu). * + * 10/20/92 pi@isi.edu * + * Revision 7.0.3 (pi) * + * Colorversatec support. Thanks got to Jeffrey C. Gealow form * + * MIT (jgealow@mtl.mit.edu). * + * 10/8/92 pi@isi.edu * + * Revision 7.0.2 (pi) * + * Separate 'spacing allWell...' rule into two rules to avoid * + * well adjacency problem... * + * 10/2/92 pi@isi.edu * + * Revision 7.0.1 (pi) * + * CIFoutput for "pad2" layer, CCA contact fix, CIFinput for HP's * + * 1.0 um process... * + * 9/28/92 pi@isi.edu * + * Revision 7.0 (pi) * + * Major revision which includes * + * HP's cap_well and well-capacitance, NPN & BCCD DRC rules... * + * 9/22/92 pi@isi.edu * + * Revision 6.2.0 (pi) * + * Merging 'scmos26.tech' into scmos.tech * + * 9/7/92 pi@isi.edu * + * Revision 6.1.4 (pi) * + * Select CIF layers generation is revised based on Brian * + * Kingsbury's (bedk@icsi.berkeley.edu) notice of inconsistency * + * 9/4/92 pi@isi.edu * + * Revision 6.1.3 (pi) * + * Install MITRE's (Mike Butler) fix for CIFinput "cap" layer and * + * poly1/poly2 crossing in DRC section * + * 9/3/92 pi@isi.edu * + * Revision 6.1.2 (pi) * + * Fixed metal2 contact on falt surface bug for poly2 layer * + * 8/3/92 pi@lepton.isi.edu * + * Revision 6.1.1 (pi) * + * fixed CIFoutput CSP layer bug for lambda=0.8(gen) technology * + * 4/13/92 pi@lepton.isi.edu * + * Revision 6.1.0 (pi) * + * add implant plane for Buried CCD devices * + * both cifin and cifoutput are changed correspondingly * + * Revision 6.0.2 (pi) * + * remove bug for nbdc not generate CMF in cifoutput section * + * Revision 6.0.1 (sllu) * + * added CX for collector layer * + * Revised for Magic Version 6. * + * Revision 6.0 90/05/11 20:12:34 pi * + * include color versatech support * + * eliminated active2 plane * + * (rule version # 5.01 (S. Lu) = rule 5.0 + mod. for cc spacing * + * (rule version # 5.0 (Shih-Lien Lu sllu@MOSIS.EDU) 8/15/89) * + * (rule 5.0 = rule 4.01 + new layers for analog process * + * (rule 4.01 = rule 4.0 + comments + cifout style lambda=0.8(pwell) * + * (correction made by L. McMurchie of UW) * + * (rule 4.0 = rule 3.1 + new layer : electrode) * + * (rule 3.1 = rule 3.0 + new cifout method for select layers ) * + * (design can be more compact now with this version ) * + * (layout should be upward compatible:: you old layout will not) * + * (flag any drc violations) * + * (rule 3.0 = rule 2.0 + rev #6 + new cifin section for new nwell) * + * * + * (rule version # 2.0 10/28/87) * + * (rule 2.0 = rule 1.9 + modification to extract section * + * (rule 1.9 = rule 1.82 + additions of two more CIF in/output styles * + * (rule 1.82 = rule 1.81+ modification of drc #4.1 & cifoutput of * + * wells * + * (rule 1.81 = rule 1.8 + modification on line 1761 * + * (rule 1.8 = rule 1.7 + Rev 5 of the SCMOS rules) * + * (difference from rule 1.7: * + * (1) well width = 9 lambda * + * (2) N well process accepts both N and P selects * + * ------------------------------------------------------------------- */ + +/* Definition for actives */ +/* NOTE: Some version of cpp may have problem with two consective tabs + * or even two consective space... So we put only single space + * here... */ +#define allNDiff ndiff,ndc/a +#define allPDiff pdiff,pdc/a +#define allNActive ndiff,ndc/a,nfet,enfet,nffet,wcap +#define allPActive pdiff,pdc/a,pfet,epfet,pffet +#define allNOhmic nsd,nsc/a +#define allPOhmic psd,psc/a +#define allOhmic allNOhmic,allPOhmic +#define allBiNDiff emit,emc/a,col,clc/a +#define allBiPDiff pbase,pbc/a +#define allBiDiff allBiNDiff,allBiPDiff +#define allCCDiff bd,nbd,nbdc/a +#define allDiff allNDiff,allPDiff +#define allActive allNActive,allPActive,allOhmic +#define PNplus ndiff,pdiff,ndc/a,pdc/a +#define allHVNDiff hndiff,hndc/a +#define allHVPDiff hpdiff,hpdc/a +#define allHVNOhmic hnsd,hnsc/a +#define allHVPOhmic hpsd,hpsc/a +#define allHVDiff allHVNDiff,allHVPDiff +#define allHVOhmic allHVNOhmic,allHVPOhmic + +/* first poly without those overlapped with the second */ +#define allP poly,pc/a +#define allP1 poly,pc/a,nfet,pfet,wcap +/* all first poly */ +#define allPoly allP1,cap,capc/a,nffet,pffet +/* second poly without those overlapped with the first */ +#define allP2 poly2,ec/a,enfet,epfet +/* all second poly */ +#define allPoly2 allP2,cap,capc/a,nffet,pffet,hnfet,hpfet + +/* MOSFETs */ +#define NFet nfet,enfet,nffet +#define PFet pfet,epfet,pffet +#define allFet NFet,PFet + +/* Definitions for contacts */ +#define DiffCut pdc,ndc,psc,nsc +#define HVDiffCut hpdc,hndc,hpsc,hnsc +#define PolyCut pc +#define CapCut ec,capc +#define BiCut clc,emc,pbc +#define allCut DiffCut,HVDiffCut,PolyCut,CapCut,nbdc + +/* Definitions for metals */ +#define DiffMetal pdc/m1,ndc/m1,psc/m1,nsc/m1 +#define HVDiffMetal hpdc/m1,hndc/m1,hpsc/m1,hnsc/m1 +#define PolyMetal pc/m1,ec/m1,capc/m1 +#define BiMetal clc/m1,emc/m1,pbc/m1 +#define CCDMetal nbdc/m1 +#define allMetal1 DiffMetal,HVDiffMetal,PolyMetal,BiMetal,CCDMetal,m1,m2c/m1,gc +#define allMetal2 m2,m2c/m2,m3c/m2,pad +#define allMetal3 m3,m3c/m3 + +/* All types containing metal, on their respective home planes */ +#define homeMetal1 allCut,m1,m2c,gc + +/* Definitions for wells */ +#define allWell nwell,pwell +#define allNwell nwell,nsc,nsd +#define allPwell pwell,psc,psd +#define allHVNwell hnwell,hnsc,hnsd +#define allHVPwell hpwell,hpsc,hpsd + + +tech + format 28 + scmos +end + +#if V4 || V5 +version + version 8.2.8 +#ifdef SUBMICRON + description "MOSIS Scalable CMOS Technology for HP CMOS26G and CMOS14B processes" +#else /* TIGHTMETAL */ +#ifdef IBMTECH + description "MOSIS Scalable CMOS Technology for IBM" +#else /* IBMTECH */ +#ifdef HPTECH + description "MOSIS Scalable CMOS Technology for Tight Metal Rules" +#else +#ifndef WELL_ROUTE_CHECK + description "MOSIS Scalable CMOS Technology for Standard Rules" +#else + description "MOSIS Scalable CMOS Technology for Standard Rules (No routing through wells)" +#endif +#endif /* HPTECH */ +#endif /* IBMTECH */ +#endif /* TIGHTMETAL */ +end +#endif /* V4 */ + +planes + well,w + implant,i + active,a + metal1,m1 + metal2,m2 +#ifdef STACKVIA + v2oxide,v2x +#endif + metal3,m3 + oxide,ox +end + + +types + /* primary layers -16 */ + + well pwell,pw + well nwell,nw + well capwell,cwell,cw + well highvoltnwell,hvnwell,hnwell,hnw + well highvoltpwell,hvpwell,hpwell,hpw + active polysilicon,red,poly,p + active electrode,poly2,el,p2 + active capacitor,polycap,pcap,cap + active wellcapacitor,wellcap,wcap + active ndiffusion,ndiff,green + active pdiffusion,pdiff,brown + active highvoltndiffusion,hvndiff,hndiff + active highvoltpdiffusion,hvpdiff,hpdiff + metal1 metal1,m1,blue + metal2 metal2,m2,purple + metal3 metal3,m3,cyan + + /* MOSFETs -8 */ + + active ntransistor,nfet + active ptransistor,pfet + active entransistor,enfet + active eptransistor,epfet + active doublentransistor,nfloating-gate,nfloatg,nfg,nffet + active doubleptransistor,pfloating-gate,pfloatg,pfg,pffet + active highvoltntransistor,hvnfet,hnfet + active highvoltptransistor,hvpfet,hpfet + + /* NPN transistor layers -3 */ + + active collector,coll,col,co,cl + active emitter,emit,em + active pbase,pb + + /* layers for BCCD devices -2 */ + + implant bccdiffusion,bd + active nbccdiffusion,nbd + + /* Contacts between interconnection layers -13 */ + + active polycontact,pcontact,polycut,pc + active ndcontact,ndiffcut,ndc + active pdcontact,pdiffcut,pdc + active highvoltndcontact,hndiffcut,hndc + active highvoltpdcontact,hpdiffcut,hpdc + active capcontact,ccontact,capc,cc + active electrodecontact,econtact,ec,poly2contact,p2c + active collectorcontact,colcontact,colc,coc,clc + active emittercontact,emitcontact,emc + active pbasecontact,pbcontact,pbc + active nbccdiffcontact,nbdc + metal1 m2contact,m2cut,m2c,via,v +#ifdef STACKVIA + v2x m3contact,m3cut,m3c,via2,v2 +#else + metal2 m3contact,m3cut,m3c,via2,v2 +#endif + + /* Well contacts -8 */ + /* pohmic and nohmic are included for compatibility */ + /* nwc, pwc, etc ... are included for compatibility */ + + active psubstratepcontact,ppcontact,ppc,pwcontact,pwc,psc + active nsubstratencontact,nncontact,nnc,nwcontact,nwc,nsc + active psubstratepdiff,ppdiff,pohmic,ppd,psd + active nsubstratendiff,nndiff,nohmic,nnd,nsd + + active highvoltpsubcontact,hpwcontact,hpsc + active highvoltnsubcontact,hnwcontact,hnsc + active highvoltpsubdiff,hpohmic,hpsd + active highvoltnsubdiff,hnohmic,hnsd + + /* Special tiles needed for ESD protection design -3 */ + active nplusdoping,ndoping,ndop + active pplusdoping,pdoping,pdop + metal1 genericcontact,gcontact,gc + + /* Special tiles needed for micromachine fab. in CMOS -2 */ + oxide substrateopen,subopen,open + oxide pdiffusionstop,pdiffstop,pstop + + /* Additional stuff, used in pads. -2 */ + + metal2 pad + oxide glass +end + +contact + /* polys */ + ec poly2 metal1 + cc cap metal1 + pc poly metal1 + /* active contacts */ + ndc ndiff metal1 + pdc pdiff metal1 + nsc nsd metal1 + psc psd metal1 + hndc hndiff metal1 + hpdc hpdiff metal1 + hnsc hnsd metal1 + hpsc hpsd metal1 + /* bipolar contacts */ + clc col metal1 + emc emit metal1 + pbc pbase metal1 + /* BCCD contact */ + nbdc nbd metal1 + /* vias */ + m2c metal1 metal2 +#ifdef STACKVIA + m3c metal2 m3c metal3 +#else + m3c metal2 metal3 +#endif +/* + pad metal1 metal2 metal3 + */ + +end + +styles + styletype mos + + /* wells */ + cwell 10 + nwell 12 + pwell 13 + hnwell 18 + hpwell 11 + /* poly */ + poly 1 + poly2 14 + /* diffusions */ + ndiff 2 + pdiff 4 + psd 5 + nsd 3 + hndiff 2 + hndiff 11 + hpdiff 4 + hpdiff 18 + hpsd 5 + hpsd 11 + hnsd 3 + hnsd 18 + ndop 2 + ndop 38 + pdop 4 + pdop 38 + /* transistors */ + nfet 6 + nfet 7 + pfet 8 + pfet 9 + + enfet 6 + enfet 30 +/* enfet 14 */ + epfet 8 + epfet 31 +/* epfet 14 */ + + nffet 6 + nffet 7 +/* nffet 14 */ + nffet 30 + pffet 8 + pffet 9 +/* pffet 14 */ + pffet 31 + + hnfet 6 + hnfet 7 + hnfet 30 + + hpfet 8 + hpfet 9 + hpfet 31 + /* base */ + pbase 15 + pbc 15 + pbc 20 + pbc 32 + /* emitter */ + emit 16 + emc 16 + emc 20 + emc 32 + /* collector */ + col 3 + clc 3 + clc 20 + clc 32 + /* capacitors */ + cap 1 + cap 14 + wcap 6 + wcap 10 + cc 1 + cc 14 + cc 20 + cc 32 + /* metals */ + metal1 20 + metal2 21 + metal3 22 + /* generic contact */ + gc 19 + /* poly contacts */ + pcontact 26 + pcontact 32 + ec 14 + ec 20 + ec 32 + /* diffusion contacts */ + ndc 2 + ndc 20 + ndc 32 + pdc 4 + pdc 20 + pdc 32 + psc 5 + psc 20 + psc 32 + nsc 3 + nsc 20 + nsc 32 + /* high-voltage diffusion contacts */ + hndc 2 + hndc 20 + hndc 32 + hndc 11 + hpdc 4 + hpdc 20 + hpdc 32 + hpdc 18 + hpsc 5 + hpsc 20 + hpsc 32 + hpsc 11 + hnsc 3 + hnsc 20 + hnsc 32 + hnsc 18 + /* vias */ + m2contact 20 + m2contact 21 + m2contact 33 + m3contact 21 + m3contact 22 + m3contact 37 + /* pads and overglass */ + pad 20 + pad 21 + pad 33 + pad 34 + glass 34 + /* CCDs */ + bd 17 + nbd 17 + nbd 3 + nbdc 3 + nbdc 17 + nbdc 20 + nbdc 32 + /* MEMs */ + open 2 + open 20 + pstop 8 + /* System */ + error_p 42 + error_s 42 + error_ps 42 +end + +compose + /* MOSFET combination rules */ + compose nfet poly hndiff + compose pfet poly hpdiff + compose nfet poly ndiff + compose pfet poly pdiff + compose hnfet poly2 hndiff + compose hpfet poly2 hpdiff + compose enfet poly2 ndiff + compose epfet poly2 pdiff + compose nffet nfet poly2 + compose pffet pfet poly2 + compose nffet enfet poly + compose pffet epfet poly + compose cap poly poly2 + /* Transistor combination rules */ + paint clc col clc + paint emc emit emc + paint emc pbase emc + /* Poly2 capacitor combination rules */ + paint poly2 poly cap + paint poly poly2 cap + paint poly cap cap + paint poly2 cap cap + paint cap poly cap + paint cap poly2 cap +/* ILLEGAL declaration by 7.3 standards */ +/* paint poly ec cc */ + paint ec poly cc + /* These rules allow nwell to be painted over an area to + * flip all the p-well types to n-well types. Pwell can be + * painted to flip in the reverse. */ + paint pdc pwell ndc + paint pfet pwell nfet + paint epfet pwell enfet + paint pffet pwell nffet + paint pdiff pwell ndiff + paint nsd pwell psd + paint nsc pwell psc + paint ndc nwell pdc + paint nfet nwell pfet + paint enfet nwell epfet + paint nffet nwell pffet + paint ndiff nwell pdiff + paint psd nwell nsd + paint psc nwell nsc + + paint pdc hpwell hndc + paint epfet hpwell hnfet + paint pffet hpwell hnfet + paint pdiff hpwell hndiff + paint nsd hpwell hpsd + paint nsc hpwell hpsc + paint ndc hnwell hpdc + paint enfet hnwell hpfet + paint nffet hnwell hpfet + paint ndiff hnwell hpdiff + paint psd hnwell hnsd + paint psc hnwell hnsc + /* BCCD layers combination rules */ +/* paint bd ndiff 0 implant */ +/* + erase nbd bd ndiff + erase nbd ndiff bd + erase nbdc/a bd ndc/a +*/ + /* Well capacitor combination rules */ + paint nfet cwell wcap + paint poly wcap wcap + paint ndiff wcap wcap + paint wcap poly wcap + paint wcap ndiff wcap + erase wcap poly ndiff + erase wcap ndiff poly + erase wcap cwell nfet + paint cwell nfet wcap active + erase wcap nfet cwell well + + /* Generic contact */ + paint gc m1 gc + + /* For pads */ + paint pad m1 pad + paint pad m2 pad + paint pad m3 pad + paint pad m2c pad + + /* These rules allow nwell to be painted over an area to + * flip all the p-well types to n-well types. Pwell can be + * painted to flip in the reverse. */ + paint hpdc hpwell hndc + paint hpfet hpwell hnfet + paint hpdiff hpwell hndiff + paint hnsd hpwell hpsd + paint hnsc hpwell hpsc + paint hndc hnwell hpdc + paint hnfet hnwell hpfet + paint hndiff hnwell hpdiff + paint hpsd hnwell hnsd + paint hpsc hnwell hnsc + + paint hpdc pwell ndc + paint hpfet pwell enfet + paint hpdiff pwell ndiff + paint hnsd pwell psd + paint hnsc pwell psc + paint hndc nwell pdc + paint hnfet nwell epfet + paint hndiff nwell pdiff + paint hpsd nwell nsd + paint hpsc nwell nsc + +end + +connect +#ifndef WELL_ROUTE_CHECK +/* This creates a tech file where the wells are not connected therefore + enabling extractions to check whether the wells are used accidentaly + to route signals or power. To check for these cases you have to compare + the netlists generated with the normal tech file with those generated + with the special one (eg. using gemini). +*/ + allNwell allNwell + allPwell allPwell +#endif + allHVNwell allHVNwell + allHVPwell allHVPwell + /* for capacitor-well */ + allNDiff cwell + /* for all metals */ + allMetal1 allMetal1 + allMetal2 allMetal2 + allMetal3 allMetal3 + /* for all polys */ + allP1 allP1 + allPoly2 allPoly2 + /* for all diffusions/well plugs */ + /* Ndiffusion and Ohmic wells dont connect !! */ + /* you get a diode instead */ + allNDiff,ndop allPOhmic,pdop,pstop + allPDiff,pdop,pstop allNOhmic,ndop + allHVNDiff,ndop allHVPOhmic,pdop,pstop + allHVPDiff,pdop,pstop allHVNOhmic,ndop + ndiff ndc + pdiff pdc + hndiff hndc + hpdiff hpdc + /* for BCCD device */ + nbd nbdc + /* for NPN transistor */ + pbase pbc + collector clc,nwell + emitter emc + /* for new generic contact */ + gc allActive,allOhmic,allHVDiff,metal1 + gc allP1 + gc allPoly2 + /* for pad */ + pad allMetal1 + pad allMetal2 + pad allMetal3 + +end + +/* WARNING ::::: automatic generation of wells does not guarantee */ +/* rules on width and spacing of wells are followed !! */ +/* It is strongly recommanded that designers layout their own wells */ + +/* PWELL styles cannot generate CBA and CCD correctly */ +/* BOTH NWELL and GEN can do CCD and CBA */ +/* ONLY GEN can be used for micro-machining fabrication */ + +cifoutput +/* default: fab on 2.0 micron (Nwell) rules each magic unit is 100 */ +/* centimicrons */ +/* SCN technology : Both CSN and CSP are generated to reduce field */ +/* poly sheet resistance */ + +#ifdef STANDARD +#include "cif_template/objs/CIFout" +#endif /* STANDARD */ + +#ifdef TIGHTMETAL +#include "cif_template/objs/TMCIFout" +#endif /* TIGHTMETAL */ + +#ifdef SUBMICRON +#include "cif_template/objs/SUBCIFout" +#endif /* SUBMICRON */ + +#ifdef IBMTECH +#include "cif_template/objs/IBMCIFout" +#endif /* IBMTECH */ + +style plot /* pplot output style */ + scalefactor 100 50 + layer CM2 m2,m2c/m2,pad/m2 + labels m2 + layer CM1 pad + grow 100 + or m1,m2c/m1,pc/m1,ndc/m1,pdc/m1,ppcont/m1,nncont/m1 + labels m1,m2c/m1,pc/m1,ndc/m1,pdc/m1,ppcont/m1,nncont/m1,pad/m1 + layer CP poly,pc/active,nfet,pfet + labels poly,nfet,pfet + layer CND ndiff,ndc,nfet,pwc,psd + labels ndiff + layer CPD pdiff,pdc,pfet,nwc,nsd + labels pdiff + layer CNP + bloat-or nsd,nwc * 150 ndiff,pdiff,ndc/active,pdc/active,ppcont/active,nncont/active,pfet,nfet,psd,nsd 0 + layer CPP + bloat-or psd,pwc * 150 ndiff,pdiff,ndc/active,pdc/active,ppcont/active,nncont/active,pfet,nfet,psd,nsd 0 + layer CV m2c + squares 100 200 300 + layer CC ndc,pdc,pc,pwc,nwc + squares 200 + layer CNW nwell + grow 400 + shrink 400 + layer CG pad + shrink 600 + or glass + labels glass + + +end + +/* -------------------------------------------------------------------- * + * In the CIFinput section, the order of layer specifications is very * + * important. Each layer overrides any of the previous layers. There * + * are places where one layer is generated over an area that is too * + * large, but with the knowledge that later layers will "take over" * + * the extraneous area, leaving the first layer only where it belongs. * + * This happens for various flavors of diffusion, for example. * + * Note: when reading in CMOS, wells are created in the Magic files. * + * They can be eliminated manually if desired. * + * ---------------------------------------------------------------------*/ +cifinput + +#ifdef STANDARD +#include "cif_template/objs/CIFin" +#endif /* STANDARD */ + +#ifdef TIGHTMETAL +#include "cif_template/objs/TMCIFin" +#endif /* TIGHTMETAL */ + +#ifdef SUBMICRON +#include "cif_template/objs/SUBCIFin" +#endif /* SUBMICRON */ + +#ifdef IBMTECH +#include "cif_template/objs/IBMCIFin" +#endif /* IBMTECH */ + +end + +mzrouter + style irouter + layer m2 32 64 256 1 + layer m1 64 32 256 1 + layer poly 128 128 512 1 + contact m2contact metal1 metal2 1024 + contact pcontact metal1 poly 2056 + notactive poly pcontact + style garouter + layer m2 32 64 256 1 + layer m1 64 32 256 1 + contact m2contact metal1 metal2 1024 +end + + +/* SCMOS rules revision 7 */ +drc +/* ---------------------------------------------------------------- */ +/* Well */ +/* ---------------------------------------------------------------- */ + +/* 1.1 */ +/* Now use "edge" for width DRC... A test only for rule1 */ +/* Other rules may follow in the near future... */ +#ifdef SUBMICRON + edge4way (~nwell)/w nwell 12 nwell nwell 12\ + "N-Well width must be at least 12 (MOSIS rule #1.1)" + edge4way (~pwell)/w pwell 12 pwell pwell 12\ + "P-Well width must be at least 12 (MOSIS rule #1.1)" +#else + edge4way (~nwell)/w nwell 10 nwell nwell 10\ + "N-Well width must be at least 10 (MOSIS rule #1.1)" + edge4way (~pwell)/w pwell 10 pwell pwell 10\ + "P-Well width must be at least 10 (MOSIS rule #1.1)" +#endif + +/* original "width" rule which use 'width'command: + width allWell 10 \ + "Well width must be at least 10 (MOSIS rule #1.1)" + */ + +/* 1.2 */ +/* Now use "edge4way" for spacing DRC... A test only for rule1 */ +/* Other rules may follow in the near future... */ +#ifdef SUBMICRON + edge4way nwell ~(nwell)/w 18 (~nwell)/w (~nwell)/w 18\ + "N-Well spacing must be at least 18 (MOSIS rule #1.2)" + edge4way pwell (~pwell)/w 18 (~pwell)/w (~pwell)/w 18\ + "P-Well spacing must be at least 18 (MOSIS rule #1.2)" +#else + edge4way nwell (~nwell)/w 9 (~nwell)/w (~nwell)/w 9\ + "N-Well spacing must be at least 9 (MOSIS rule #1.2)" + edge4way pwell (~pwell)/w 9 (~pwell)/w (~pwell)/w 9\ + "P-Well spacing must be at least 9 (MOSIS rule #1.2)" +#endif + +/* original spacing rule which use 'spacing' command: + spacing allWell allWell 9 touching_ok \ + "Well spacing must be at least 9 (MOSIS rule #1.2)" + */ + +/* NOTE: rule 1.2 is equivalent to the following three rules where + the third is a new one. This rule is added to force designers + to be cautious about the wells... + + spacing nwell nwell 9 touching_ok \ + "N-well spacing must be at least 9 (MOSIS rule #1.2)" + spacing pwell pwell 9 touching_ok \ + "P-well spacing must be at least 9 (MOSIS rule #1.2)" + spacing nwell pwell 9 touching_ok \ + "Well spacing must be at least 9 (MOSIS rule #1.2)" +*/ + +/* 1.3 is not checked */ +/* NOTE: for digital ckts where wells are not explicitly put, * + * auto-generation may not ensure the minimul spacing and width * + * rule: this happens usually when two geometries are in diagonal * + * positions. * + * NOTE: when both pwell and nwell are submitted they cannot * + * overlap this is assured with the compose section - painting one * + * well over another will erase the original well. */ + +/* ---------------------------------------------------------------- */ +/* Active */ +/* ---------------------------------------------------------------- */ + +/* 2.1 */ +/* Test active width separately... */ + width allNActive 3 \ + "N-type Diffusion width must be at least 3 (MOSIS rule #2.1a)" + width allPActive 3 \ + "P-type Diffusion width must be at least 3 (MOSIS rule #2.1b)" + width allOhmic 3 \ + "Ohmic diffusion width must be at least 3 (MOSIS rule #2.1c)" + +/* 2.2 */ + spacing allNActive allNActive 3 touching_ok \ + "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" + spacing allPActive allPActive 3 touching_ok \ + "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" + spacing allNOhmic allNOhmic 3 touching_ok \ + "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" + spacing allPOhmic allPOhmic 3 touching_ok \ + "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" + +/* 2.3 without explicit well definition: 6+6 and 5+5 respectively */ +#ifdef SUBMICRON + spacing allNDiff allPDiff 12 touching_illegal \ + "P-type diffusion must be 12 away from N-type diffusion (MOSIS rule #2.3b)" +#else + spacing allNDiff allPDiff 10 touching_illegal \ + "P-type diffusion must be 10 away from N-type diffusion (MOSIS rule #2.3a)" +#endif + +/* 2.3 + 2.4 without explicit well definition: 6+3 and 5+3 respectively */ +#ifdef SUBMICRON + spacing allNDiff allNOhmic 9 touching_illegal \ + "N-type diffusion must be 9 away from N-substrate contact (MOSIS rule #2.3b,4b)" + spacing allPDiff allPOhmic 9 touching_illegal \ + "P-type diffusion must be 9 away from P-substrate contact (MOSIS rule #2.3b,4b)" +#else + spacing allNDiff allNOhmic 8 touching_illegal \ + "N-type diffusion must be 8 away from N-substrate contact (MOSIS rule #2.3a,4a)" + spacing allPDiff allPOhmic 8 touching_illegal \ + "P-type diffusion must be 8 away from P-substrate contact (MOSIS rule #2.3a,4a)" +#endif + +/* 2.4 3 + 3 */ + spacing allNOhmic allPOhmic 6 touching_illegal \ + "Opposite well contacts must be separated by 6 (MOSIS rule #2.4)" + +/* 2.3 with explicit well: 6 and 5 respectively */ +#ifdef SUBMICRON + spacing allNActive nwell 6 touching_illegal \ + "N-diffusion and N-well must be separated by 6 (MOSIS rule #2.3b)" + spacing allPActive pwell 6 touching_illegal \ + "P-diffusion and P-well must be separated by 6 (MOSIS rule #2.3b)" +#else + spacing allNActive nwell 5 touching_illegal \ + "N-diffusion and N-well must be separated by 5 (MOSIS rule #2.3a)" + spacing allPActive pwell 5 touching_illegal \ + "P-diffusion and P-well must be separated by 5 (MOSIS rule #2.3a)" +#endif + +/* 2.4 with explicit well */ + spacing allNOhmic pwell 3 touching_illegal \ + "N-substrate diffusion and P-well must be separated by 3 (MOSIS rule #2.4)" + spacing allPOhmic nwell 3 touching_illegal \ + "P-substrate diffusion and N-well must be separated by 3 (MOSIS rule #2.4)" + +/* MOSIS extension rule for diffusion and substrate contact of */ +/* opposite type. We could do without this rule, but it is now */ +/* added for safety reason. */ + spacing allNActive allPOhmic 4 touching_ok \ + "Opposite diffusion spacing must be at least 4 (MOSIS extension rule)" + spacing allPActive allNOhmic 4 touching_ok \ + "Opposite diffusion spacing must be at least 4 (MOSIS extension rule)" + +/* ---------------------------------------------------------------- */ +/* Poly */ +/* ---------------------------------------------------------------- */ + +/* 3.1 */ + width allPoly 2 \ + "Polysilicon width must be at least 2 (MOSIS rule #3.1)" + +/* 3.2 */ +#ifdef SUBMICRON + spacing allPoly allPoly 3 touching_ok \ + "Polysilicon spacing must be at least 3 (MOSIS rule #3.2b)" +#else + spacing allPoly allPoly 2 touching_ok \ + "Polysilicon spacing must be at least 2 (MOSIS rule #3.2a)" +#endif + +/* 3.3 */ + edge4way nfet,pfet poly,pc/act 2 poly,pc/act 0 0 \ + "Poly must overhang transistor by at least 2 (MOSIS rule #3.3)" + +/* 3.4 */ + edge4way nfet,enfet ndiff,ndc/a 3 allNActive ndiff,ndc/a 3 \ + "Diffusion must overhang transistor by at least 3 (MOSIS rule #3.4)" + edge4way pfet,epfet pdiff,pdc/a 3 allPActive ndiff,ndc/a 3 \ + "Diffusion must overhang transistor by at least 3 (MOSIS rule #3.4)" + +/* 3.3 + 3.4 */ + edge4way nfet,pfet space 1 poly 0 0 \ + "Transistor overhang is missing (MOSIS rule #3.3,4)" + edge4way enfet,epfet space 1 poly2 0 0 \ + "Transistor overhang is missing (MOSIS rule #3.3,4)" + edge4way nffet,pffet space 1 poly 0 0 \ + "Transistor overhang is missing (MOSIS rule #3.3,4)" + edge4way nffet,pffet space 1 poly2 0 0 \ + "Transistor overhang is missing (MOSIS rule #3.3,4)" + +/* 3.5 */ + edge4way allDiff,allOhmic poly,pc 1 space/a 0 1 \ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" + edge4way poly,pc allDiff,allOhmic 1 space/a 0 1 \ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" + edge poly,pc space/a 1 space/a space/a 1 \ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" + edge allOhmic,allDiff space/a 1 space/a space/a 1 \ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" +/* + These following checks will miss the corner, so we add something above + + edge4way allDiff,allOhmic poly,pc 1 space space 1 \ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5.a)" + spacing allDiff,allOhmic poly,pc 1 touching_illegal \ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5.b)" + */ + +/* Extra transistor rules */ +/* These rules is really NOT necessary because others have already + taken care of it. It is here for future reference... + + edge4way poly,pc/act pfet 3 pfet 0 0 \ + "Transistors must be at least 3 units wide (MOSIS rule #2)" + edge4way poly,pc/act nfet 3 nfet 0 0 \ + "Transistors must be at least 3 units wide (MOSIS rule #2)" +*/ + +/* ---------------------------------------------------------------- */ +/* Select */ +/* ---------------------------------------------------------------- */ +/* 4.1 */ + spacing PFet allNOhmic 3 touching_illegal \ + "Transistors must be separated from substrate contacts by 3 (MOSIS rule #4.1.a)" + spacing NFet allPOhmic 3 touching_illegal \ + "Transistors must be separated from substrate contacts by 3 (MOSIS rule #4.1.b)" + + edge4way allPOhmic space/act 3 ~(NFet)/act allPOhmic,allNDiff 3 \ + "Transistors must be separated from selects(generated by well cont) by 3 (MOSIS rule #4.1.c)" + + edge4way allNOhmic space/act 3 ~(PFet)/act allNOhmic,allPDiff 3 \ + "Transistors must be separated from selects(generated by well cont) by 3 (MOSIS rule #4.1.d)" + + edge4way allPOhmic ~(ndiff,ndc,psc,psd)/act 4 ~(nfet,enfet)/act ~(ndiff,ndc,psc,psd)/act 4 \ + "Transistors must be separated from selects(generated by well cont) by 4 (MOSIS rule #4.1.e)" + + edge4way allNOhmic ~(pdiff,pdc,nsc,nsd)/act 4 ~(pfet,epfet)/act ~(pdiff,pdc,nsc,nsd)/act 4 \ + "Transistors must be separated from selects(generated by well cont) by 4 (MOSIS rule #4.1.f)" + +/* 4.2 */ +/* This one is very difficult.... Most likely done by CIF output */ + edge4way ~(allPActive)/act pdiff,pdc,pfet 4 ~(allNOhmic)/act allPActive 2 \ + "Backedge of diffusion must be 4 from substrate diff (MOSIS rule #4.2.a)" + edge4way ~(allNActive)/act ndiff,ndc,nfet 4 ~(allPOhmic)/act allNActive 2 \ + "Backedge of diffusion must be 4 from substrate diff (MOSIS rule #4.2.b)" + +/* 4.3 -- guaranteed automatically by CIF generator. */ +/* 4.4 -- guaranteed automatically by CIF generator except diag. where + this rule is not crucial */ + + +/* ---------------------------------------------------------------- */ +/* Contact to Poly */ +/* ---------------------------------------------------------------- */ + +/* 5B.1 + 5B.2 + 5B.3 */ + width pc 4 \ + "Poly contact width must be at least 4 (MOSIS rule #5B.1,2,3)" + +/* 5B.4 is guaranteed by 5B.1,2,3 with rule 7.2 (metal1 spacing) */ + +/* 5B.5 -- + * Watch out here: a spacing "touching_ok" rule CANNOT be used here: + * it will miss certain checks. + */ + edge4way allPoly ~(allPoly)/act 3 ~pc/act ~(allPoly)/act 3 \ + "Poly contact must be at least 3 from other poly (MOSIS rule #5B.4,5)" + +/* 5B.6 -- + * This is mostly handled by 3.5 already, but need rule here to handle + * case of pc abutting transistor. + */ + spacing pc allActive 1 touching_illegal \ + "Poly contact must be 1 unit from diffusion (MOSIS rule #5B.6)" + +/* 5B.7 -- not implemented */ + +/* ---------------------------------------------------------------- */ +/* Contact to Active */ +/* ---------------------------------------------------------------- */ + +/* 6B.1 + 6B.2 + 6B.3 */ + width ndc,pdc 4 \ + "Diffusion contact width must be at least 4 (MOSIS rule #6B.1,2,3)" + width nsc,psc 4 \ + "Substrate contact width must be at least 4 (MOSIS rule #6B.1,2,3)" + +/* 6B.2 this is here to explicit check the contact spacing rule 3. */ +#ifdef SUBMICRON + spacing nsc pdc 1 touching_illegal \ + "Substrate contact must be 1 unit from diffusion contact (MOSIS rule #6B.2b)" + spacing psc ndc 1 touching_illegal \ + "Substrate contact must be 1 unit from diffusion contact (MOSIS rule #6B.2b)" +#endif + +/* + edge4way psc (~psc)/a 1 psd psd 1 \ + "Substrate contact must overlapped by diffusion by at least 1 (MOSIS 26G rule)" + edge4way nsc (~nsc)/a 1 nsd nsd 1 \ + "Substrate contact must overlapped by diffusion by at least 1 (MOSIS 26G rule)" +*/ + +/* 6B.4 & 6B.5 -- + * Watch out here: a spacing "touching_ok" rule CANNOT be used here: + * it will miss certain checks. + */ + edge4way allActive ~(allActive)/act 4 ~(ndc,pdc,nsc,psc)/act \ + ~(allActive)/act 4 \ + "Diffusion contacts must be 4 from other diffusions (MOSIS rule #6B.4,5)" + +/* 6B.6 */ + spacing DiffCut allFet 1 touching_illegal \ + "Diffusion contacts cannot touch transistors (MOSIS rule #6B.6)" + +/* 6B.7 */ + spacing DiffCut poly 1 touching_illegal \ + "Diffusion contact to field poly must be at least 1 (MOSIS rule #6B.7)" + +/* 6.8 -- not implemented */ + +/* 6B.9 */ + spacing DiffCut pc/act 2 touching_illegal \ + "Poly contacts must be 2 away from diffusion contacts (MOSIS rule #6B.9)" + +/* ---------------------------------------------------------------- */ +/* Contacts must all be rectangular (no adjacent contacts */ +/* of same type) because of the way their contact is generated by */ +/* CIFoutput section rules. This is handled using the corner checks */ +/* in the rules below. Overlaps between contacts must be exact */ +/* overlaps. The only exception is overpad, which doesn't matter. */ + + edge4way m3c/m3 ~m3c/m3 1 ~m3c/m3 (~m3c,m3c)/m3 1 \ + "Metal3 contacts must be rectangular (Magic rules)" + edge4way m2c/m2 ~m2c/m2 1 ~m2c/m2 (~m2c,m2c)/m2 1 \ + "Metal2 contacts must be rectangular (Magic rules)" + + edge4way ndc/m1 ~ndc/m1 1 ~ndc/m1 (~ndc,ndc)/m1 1 \ + "N-diffusion contacts must be rectangular (Magic rules)" + edge4way pdc/m1 ~pdc/m1 1 ~pdc/m1 (~pdc,pdc)/m1 1 \ + "P-diffusion contacts must be rectangular (Magic rules)" + edge4way psc/m1 ~psc/m1 1 ~psc/m1 (~psc,psc)/m1 1 \ + "P-substrate contacts must be rectangular (Magic rules)" + edge4way nsc/m1 ~nsc/m1 1 ~nsc/m1 (~nsc,nsc)/m1 1 \ + "N-substrate contacts must be rectangular (Magic rules)" + + edge4way pc/m1 ~pc/m1 1 ~pc/m1 (~pc,pc)/m1 1 \ + "Polysilicon contacts must be rectangular (Magic rules)" + edge4way ec/m1 ~ec/m1 1 ~ec/m1 (~ec,ec)/m1 1 \ + "Electrode contacts must be rectangular (Magic rules)" + edge4way cc/m1 ~cc/m1 1 ~cc/m1 (~cc,cc)/m1 1 \ + "Capacitor contacts must be rectangular (Magic rules)" + + edge4way emc/m1 ~emc/m1 1 ~emc/m1 (~emc,emc)/m1 1 \ + "Emitter contacts must be rectangular (Magic rules)" + edge4way clc/m1 ~clc/m1 1 ~clc/m1 (~clc,clc)/m1 1 \ + "Collector contacts must be rectangular (Magic rules)" + edge4way pbc/m1 ~pbc/m1 1 ~pbc/m1 (~pbc,pbc)/m1 1 \ + "P-base Contacts must be rectangular (Magic rules)" + edge4way nbdc/m1 ~nbdc/m1 1 ~nbdc/m1 (~nbdc,nbdc)/m1 1 \ + "CCD-diffusion Contacts must be rectangular (Magic rules)" + +/* ---------------------------------------------------------------- */ +/* Metal 1 */ +/* ---------------------------------------------------------------- */ +/* 7.1 + 7.2 */ + width allMetal1,pad/m1 3 \ + "First-level metal width must be at least 3 (MOSIS rule #7.1)" +#ifdef TIGHTMETAL + spacing allMetal1,pad/m1 allMetal1,pad/m1 2 touching_ok \ + "First-level metal spacing must be at least 2 (MOSIS rule #7.2)" +#else + spacing allMetal1,pad/m1 allMetal1,pad/m1 3 touching_ok \ + "First-level metal spacing must be at least 3 (MOSIS rule #7.2)" +#endif /* TIGHTMETAL */ + +/* 7.3 + 7.4 */ +/* guaranteed with 4x4 poly and diffusion contacts */ + + +/* ---------------------------------------------------------------- */ +/* Via */ +/* ---------------------------------------------------------------- */ + +/* 8.1 + 8.2 + 8.3 */ + width m2c 4 \ + "Contact width must be at least 4 (MOSIS rule #8.1,2,3)" + +/* 8.4 + 8.5 */ +/* Vias have to be on flat surface */ +/* Don't allow poly or diffusion edges underneath metal2 contacts: */ +/* this rule is only valid for standard processes, not for those */ +/* processes use planarized interconnection technology. */ +#ifdef STANDARD + edge4way allPoly ~(allPoly)/a 1 ~m2c/m2 ~(allPoly)/a 1 \ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 + edge4way allPoly2 ~(allPoly2)/a 1 ~m2c/m2 ~(allPoly2)/a 1 \ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 + edge4way allActive ~(allActive)/a 1 ~m2c/m2 ~(allActive)/a 1 \ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 + + edge4way ~(allPoly)/a allPoly 1 ~m2c/m2 allPoly 1 \ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 + edge4way ~(allPoly2)/a allPoly2 1 ~m2c/m2 allPoly2 1 \ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 + edge4way ~(allActive)/a allActive 1 ~m2c/m2 allActive 1 \ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 +#endif /* STANDARD */ + + +/* ---------------------------------------------------------------- */ +/* Metal 2 */ +/* ---------------------------------------------------------------- */ +/* 9.1 */ + width allMetal2 3 \ + "Second-level metal width must be at least 3 (MOSIS rule #9.1)" + +/* 9.2 */ +#ifdef TIGHTMETAL + spacing allMetal2 allMetal2 3 touching_ok \ + "Second-level metal spacing must be at least 3 (MOSIS rule #9.2b)" +#else +#ifdef SUBMICRON + spacing allMetal2 allMetal2 3 touching_ok \ + "Second-level metal spacing must be at least 3 (MOSIS rule #9.2b)" +#else + spacing allMetal2 allMetal2 4 touching_ok \ + "Second-level metal spacing must be at least 4 (MOSIS rule #9.2a)" +#endif /* SUBMICRON */ +#endif /* TIGHTMETAL */ + +/* 9.3 */ +/* achieved with via size of 4x4 */ + + +/* ---------------------------------------------------------------- */ +/* Overglass */ +/* ---------------------------------------------------------------- */ +/* Rules for overglass (10.1-5) are not check because they are */ +/* either */ +/* 1. absolute micron rules, and */ +/* 2. vender/process dependent. */ +/* except the metal overlap of overglass rule (10.3) can be handled */ +/* case by case in CIFoutput section. */ +/* NOTE: glass layer is NOT usually used. Use "pad" layer for pad */ +/* and the corresponding overglass will be generated automatically. */ + +/* MOSIS rules to make sure there are m2 under glass - for those */ +/* users who like to use explicit "glass" layer... */ +/* */ +/* edge4way space glass 1 allMetal2 0 0 \ */ +/* "There must be metal 2 under the glass opening" metal2 */ +/* */ +/* I am removing this rule simply we have metal3 now and there's no */ +/* way to tell which process the pad is intended for. Basically, I */ +/* am enforcing the use of "pad" layer... */ + + + +/* ---------------------------------------------------------------- */ +/* Open and Pstop */ +/* ---------------------------------------------------------------- */ +/* The open layer is actually a combination of overglass and */ +/* contacts to expose the intrinsic silicon surface for future */ +/* etchimg process for micromachining device fabrication. */ +/* Since lots of applications are possible, there is no rules */ +/* enforced by Magic. Designers aimed at micromachining devices */ +/* must do DRC themself :-) */ +/* See the following reference for detail: */ +/* "High-Level CAD Melds Micromachined Devices with Foundaries", */ +/* Janet C. Marshall, M. Parameswaran, Mona E. Zaghloul, and */ +/* Michael Gaitan, IEEE Circuit and Devices, Vol. 8, No. 6, */ +/* pp. 10-17, 1992 */ + + + +/* ---------------------------------------------------------------- */ +/* Poly2 as Capacitor */ +/* ---------------------------------------------------------------- */ +/* 11.1 */ +/* The exact rule asks for 3 lambda minimum width for 'capacitor'. */ +/* But there are overlaps of poly/eletrode structures such that 2 */ +/* is fine, such as the overlaps in floating gates. So we are risk- */ +/* ing a little here... */ + width cap,capc/a 2 \ + "Electrode capacitor width must be at least 3 (MOSIS rule #11.1)" + +/* 11.2 + 12.2 */ + spacing allPoly2 allPoly2 3 touching_ok \ + "Second-level poly spacing must be at least 3 (MOSIS rule #11.2,12.2)" + +/* 11.3 */ + edge4way cap,cc space 1 0 0 0 \ + "Cap must be overlapped by poly or poly2 (MOSIS rule #11.3)" + edge4way cap,cc poly 2 poly poly 2 \ + "Cap must be overlapped by poly or poly2 (MOSIS rule #11.3)" + edge4way cap,cc poly2 2 poly2 poly2 2 \ + "Cap must be overlapped by poly or poly2 (MOSIS rule #11.3)" + +/* 11.4 */ + edge4way nw,pw,cw ~(nw,pw,cw)/w 2 ~(cap,cc)/a ~(nw,pw,cw)/w 2 \ + "Cap must be on a flat surface (MOSIS rule #11.4)" active + edge4way ~(nw,pw,cw)/w nw,pw,cw 2 ~(cap,cc)/a nw,pw,cw 2 \ + "Cap must be on a flat surface (MOSIS rule #11.4)" active + edge4way cap ~(cap)/a 2 allFet,poly,poly2,space/a,cc/a \ + allDiff,poly 2 "Cap must be on a flat surface (MOSIS rule #11.4)" active + +/* 11.5 */ +/* Done by 11.3 and 11.4 */ + + +/* ---------------------------------------------------------------- */ +/* Poly2 as Transistor */ +/* ---------------------------------------------------------------- */ +/* 12.1 */ + width allPoly2 2 \ + "Electrode width must be at least 2 (MOSIS rule #12.1)" + +/* 12.2 */ +/* Done by 11.2 */ + +/* 12.3 */ + edge4way enfet,epfet poly2,ec/a 2 poly2,ec/a 0 0 \ + "Poly2 must overhang transistor by at least 2 (MOSIS rule #12.3)" + edge4way nffet,pffet cap 2 cap 0 0 \ + "Cap must overhang transistor by at least 2 (MOSIS rule #12.3)" + edge4way nffet ~(cap,nffet,enfet,nfet)/a 2 cap 0 0 \ + "Cap must overhang doubletransistor by at least 2 (MOSIS rule #12.3)" + edge4way pffet ~(cap,pffet,epfet,pfet)/a 2 cap 0 0 \ + "Cap must overhang doubletransistor by at least 2 (MOSIS rule #12.3)" + +/* 12.4 */ + edge4way allDiff,allOhmic el 1 space/a 0 1 \ + "Poly2 and diffusion must be separated by at least 1 (MOSIS rule #12.4)" + +/* 12.5 */ + +/* 12.6 */ + spacing allPoly2 pc,ndc,pdc 2 touching_illegal \ + "Poly2 spacing to poly or diffusion contact must be at least 3 (MOSIS rule #12.6)" +/* + edge4way poly2,ec/a epfet 3 epfet 0 0 \ + "Transistors must be at least 3 units wide (MOSIS rule #2)" + edge4way poly2,ec/a enfet 3 enfet 0 0 \ + "Transistors must be at least 3 units wide (MOSIS rule #2)" + edge4way cap,capc/a pffet 3 pffet 0 0 \ + "Transistors must be at least 3 units wide (MOSIS rule #2)" + edge4way cap,capc/a nffet 3 nffet 0 0 \ + "Transistors must be at least 3 units wide (MOSIS rule #2)" +*/ + + +/* ---------------------------------------------------------------- */ +/* Poly2 Contact */ +/* ---------------------------------------------------------------- */ +/* 13.1 + 13.2 */ + width ec,capc 4 \ + "Electrode contact width must be at least 4 (MOSIS rule #13.1)" + +/* 13.3 */ +/* Done by 11.3 */ + +/* 13.4 */ + edge4way ec/a space 1 poly2 poly2 1 \ + "Electrode contact must be overlaped by poly2 (MOSIS rule #13.4)" + edge4way ec/a poly2 1 poly2 poly2 1 \ + "Electrode contact must be overlaped by poly2 by 1 (MOSIS rule #13.4)" + +/* 13.5 */ + edge4way allDiff,allOhmic ec 2 space/a 0 2 \ + "Poly2 and diffusion contact must be separated by at least 2 (MOSIS rule #13.5)" + + +/* ---------------------------------------------------------------- */ +/* Via 2 */ +/* ---------------------------------------------------------------- */ +/* 14.1 + 14.2 + 14.3 */ +/* By CIF output generation */ + width m3c 4 \ + "Third-level metal contact width must be at least 4 (MOSIS rule #14.1,2,3)" + +/* 14.4 */ +/* guaranteed by 4x4 m2c and 4x4 m3c */ +/* Via2, i.e "m3c" can overlap anything except m2c layer */ + + +/* ---------------------------------------------------------------- */ +/* Metal 3 */ +/* ---------------------------------------------------------------- */ +/* 15.1 */ +#ifdef SUBMICRON + width allMetal3 5 \ + "Third-level metal width must be at least 5 (MOSIS rule #15.1b)" +#else + width allMetal3 6 \ + "Third-level metal width must be at least 6 (MOSIS rule #15.1a)" +#endif + +/* 15.2 */ +#ifdef SUBMICRON + spacing allMetal3 allMetal3 3 touching_ok \ + "Third-level metal spacing must be at least 3 from other third-level metal (MOSIS rule #15.2b)" +#else + spacing allMetal3 allMetal3 4 touching_ok \ + "Third-level metal spacing must be at least 4 from other third-level metal (MOSIS rule #15.2a)" +#endif + +/* 15.3 */ + edge4way m3c/m3 ~m3c/m3 1 m3 m3 1 \ + "Mimimum metal3 overlap of via must be at least 1 (MOSIS rule #15.3)" + + +/* ---------------------------------------------------------------- */ +/* NPN Bipolar */ +/* ---------------------------------------------------------------- */ +/* 16.1 */ +/* As always, composite contacts are 4x4, where the actual */ +/* transistor contacts are 2x2 by CIF output generator */ + width clc,pbc,emc 4 \ + "Transistor contact width must be at least 4 (MOSIS rule #16.1)" + +/* 16.2 */ +/* Done by 16.1 4x4 emc and CIF output generation */ + +/* 16.3 */ +/* This rule is guaranteed by the way the CIF output generates */ +/* N-Select for emitter (expand by 2 lambda), so we have Pbase */ +/* overlap of emitter(or emc) by 2+2 =4 */ + edge4way emc/a,emit pbase 4 pbase pbase 4 \ + "Pbase overlap of emitter must be at least 4 (MOSIS rule #16.3)" + +/* 16.4 */ +/* NOTE; NO need to make this an edge rule... */ + spacing pbc emc/a,emit 7 touching_illegal \ + "Base must be 7 (4+2+1) away from emitter (MOSIS rule #16.3,4,11)" + +/* 16.5 */ +/* This rule is guaranteed by requiring that base contact has */ +/* at least 3 (1+2) lambda base enclosure... */ +/* edge4way pbc/a pb,space 3 pb pb,space 3 */ + edge4way pbc (~pbc)/a 3 pb,pbc/a pb,pbc/a 3 \ + "Pbase overlap of base contact must be at least 3 (MOSIS rule #16.5)" + +/* 16.6 */ +/* This rule is guaranteed by the CIF output generation of P-select */ + +/* 16.6 */ +/* This rule is enforced by checking whether collector is out of */ +/* Nwell and the fact that collector width is required to be at */ +/* least 6 */ + width col,clc/a 6 \ + "Collector width must be at least 6 (MOSIS rule #16.6)" + +/* 16.7 */ +/* Explicit Nwell required for Bipolar transistors... */ + edge4way pbase space/a 6 nwell space/a 6 \ + "Nwell overlap of Pbase must be at least 6 (MOSIS rule #16.7)" well + +/* 16.8 */ + edge4way pbase (~pbase)/a 4 ~(col,clc)/a ~(col,clc)/a 4 \ + "Pbase must be at least 4 away from collector (MOSIS rule #16.8)" + +/* 16.9 */ + edge4way clc (~clc)/a 1 col col 1 \ + "Collector overlap of contact must be at least 1 (MOSIS rule #16.9)" + +/* 16.10 */ +/* This rule is guaranteed by making sure that collector is within */ +/* PBase and the corresponding CIF output generation */ + +/* 16.11 */ + edge4way nw ~(nw)/w 3 ~(col,clc)/a ~(nw)/w 3 \ + "N-well overlap of collector must be at least 3 (MOSIS rule #16.11)" active + edge4way ~(nw)/w nw 3 ~(col,clc)/a nw 3 \ + "N-well overlap of collector must be at least 3 (MOSIS rule #16.11)" active + +/* This is a special rule to guarantee the emitter width */ + width em,emc/a 4 \ + "Emitter width must be at least 4 (Magic Bipolar Transistor rule)" + +/* This is a special rule for multi-emitters transistor according */ +/* to rule 16.2 and 2.2 */ + spacing em,emc/a em,emc/a 7 touching_ok \ + "Unrelated emitter must be at least 7 apart (Magic Bipolar transistor rule)" + +/* The following rules are added for pbase resistor implementation. */ +/* They are not in the official SCMOS design rules since I have no */ +/* foundry rules available at this moment and the numbers here is */ +/* considered to be conservative... */ + width pbase,pbc/a 4 \ + "Pbase width must be at least 4 (MOSIS extension rule)" + + spacing pbase,pbc/a pbase,pbc/a 4 touching_ok \ + "Pbase spacing must be at least 4 (MOSIS extension rule)" + +/* ---------------------------------------------------------------- */ +/* Capacitor Well */ +/* ---------------------------------------------------------------- */ +/* These are DRC rules for Capacitor Well (CWell) according to HP's */ +/* 1.2um linear capacitor process pi@isi.edu 9/18/92 */ +/* ---------------------------------------------------------------- */ + +/* 17.1 */ + width cwell 10 \ + "Cap-well width must be at least 10 (MOSIS rule #17.1)" + +/* 17.2 */ + spacing cwell cwell 9 touching_ok \ + "Cap-well spacing must be at least 9 (MOSIS rule #17.2)" + spacing cwell nwell 9 touching_illegal \ + "Cap-well spacing must be at least 9 (MOSIS rule #17.2)" + +/* 17.3 */ + edge4way cwell space 5 ~(allNActive)/a ~(allNActive)/w 5 \ + "Cap-well spacing to external active must be at least 5 (MOSIS rule #17.3)" active + edge4way cwell space 3 ~(allPOhmic)/a ~(allPOhmic)/w 3 \ + "P-substrate diffusion and Cap-well must be separated by 3 (MOSIS rule #17.3)" active + + +/* 17.4 */ +/* Need to do this check from the Cap-well plane - in order Not */ +/* to conflict with the general rules for N-diffusion */ + edge4way space cwell 3 (space,poly,pc)/a 0 0 \ + "Cap-well overlap of diffusion must be at least 3 (MOSIS rule #17.4)" active + +/* ---------------------------------------------------------------- */ +/* Well-capacitor */ +/* ---------------------------------------------------------------- */ +/* These are DRC rules for Well-capacitor (wcap) according to HP's */ +/* 1.2um linear capacitor process pi@isi.edu 9/18/92 */ +/* Rule 18.5 and 18.6 are preliminary, they are conservative here! */ +/* ---------------------------------------------------------------- */ +/* 18.1 */ + width wcap 3 \ + "Well-capacitor must be at least 3 (MOSIS rule #18.1)" + +/* 18.2 */ +/* achieved by rule 3.5 */ + +/* 18.3 */ + edge4way wcap space 1 poly poly 1 \ + "Well-capacitor overhang is missing (MOSIS rule #18.3)" + +/* 18.4 */ + edge4way wcap ndiff 3 ndiff ndiff 3 \ + "N-diffusion overlap of well-capacitor must be at least 3 (MOSIS rule #18.4)" + +/* 18.5 */ +/* achieved by rule 5B.6 */ + spacing wcap pc 2 touching_illegal \ + "Well-capacitor spacing to poly contact must be at least 2 (MOSIS rule #18.5)" + + +/* 18.6 */ +/* similar to rule 6A.4 or 6B.6 */ + spacing wcap ndc 4 touching_illegal \ + "Well-capacitor spacing to diffusion contact must be at least 4 (MOSIS rule #18.6)" + + +/* ---------------------------------------------------------------- */ +/* Buried CCD */ +/* ---------------------------------------------------------------- */ +/* 19.1 */ +/* Have to do it seperately... */ + width nbd,nbdc,bd/a 4 \ + "CCD channel width must be at least 4 (MOSIS rule #19.1)" + width nbdc 4 \ + "CCD contact width must be at least 4 (MOSIS rule #19.1)" + + +/* 19.2 */ +/* The 4 lambda spacing is a conservative guess here... */ +/* This following rule will NOT work! Need to check 2 planes */ +/* separately.... */ +/* + spacing bd/a,nbd,nbdc bd/a,nbd,nbdc 4 touching_ok \ + "CCD channel spacing must be at least 4 (MOSIS rule #19.2)" +*/ + edge4way nbd,nbdc ~(bd,nbd,nbdc)/a 4 (bd,space)/i 0 0 \ + "CCD channel spacing must be at least 4 (MOSIS rule #19.2)" implant + edge4way nbd,nbdc ~(poly,nbd,nbdc)/a 4 ~(poly,nbd,nbdc)/a ~(poly,nbd,nbdc)/a 4 \ + "CCD channel spacing must be at least 4 (MOSIS rule #19.2)" active + +/* 19.3 + 19.4 + 19.5 */ +/* guaranteed by the CIF output generation */ + +/* 19.6 */ +/* This first one check poly and electrode overhang */ + edge4way bd space 2 nbd,poly,cap,el 0 0 \ + "CCD channel overhang is missing (MOSIS rule #19.6)" active +/* There is a problem with capacitor overhang, I have no way to do */ +/* it now... */ + +/* MOSIS extension BCCD layout rule */ + spacing nbdc poly,el 1 touching_illegal \ + "CCD-diffusion contact spacing to poly must be at least 1 (MOSIS CCD rule)" + edge4way nbd poly,el 1 bd 0 0 \ + "Missing Buried CCD Difussion layer (MOSIS CCD rule)" implant + +/* ---------------------------------------------------------------- */ +/* High-Voltage MOSFETs */ +/* ---------------------------------------------------------------- */ +/* These are DRC rules for AMI 1.5 micron process for high-voltage */ +/* MOSFETs pi@isi.edu 10/01/92 */ +/* */ +/* ---------------------------------------------------------------- */ +/* 20.1 */ +/* Well spacing for different potential must be 12 lambda away now. */ +/* These rules correspond to 1.1 + 1.2 rules */ +/* width rule is as usual */ + edge (~hnwell)/w hnwell 10 hnwell hnwell 10\ + "High-Voltage N-Well width must be at least 10 (MOSIS rule #1.1)" + edge (~hpwell)/w hpwell 10 hpwell hpwell 10\ + "High-Voltage P-Well width must be at least 10 (MOSIS rule #1.1)" +/* spacing rules are new */ + edge hnwell space,pw,hpw 9 space,pw,hpw space,pw,hpw 9\ + "High-Voltage N-Well spacing to N-Well must be at least 9 (MOSIS rule #1.2)" + edge hpwell space,nw,hnw 9 space,nw,hnw space,nw,hnw 9\ + "High-Voltage P-Well spacing to P-Well must be at least 9 (MOSIS rule #1.2)" + edge hnwell space,pw,hpw,nw 12 space,pw,hpw,nw space,pw,hpw,nw 12\ + "High-Voltage N-Well spacing must be at least 12 (MOSIS rule #20.1)" + edge hpwell space,nw,hnw,pw 12 space,nw,hnw,pw space,nw,hnw,pw 12\ + "High-Voltage P-Well spacing must be at least 12 (MOSIS rule #20.1)" + +/* 20.2 */ +/* High-Voltage Active spacing must be at least 5 lambda away */ +/* This rule corresponds to 2.2 rule */ +#define allHVNActive hndiff,hndc/a,hnfet +#define allHVPActive hpdiff,hpdc/a,hpfet + edge4way ~(allHVDiff)/a allHVDiff 3 allHVDiff allHVDiff 3\ + "High-Voltage Diffusion width must be at least 3 (MOSIS rule #2.1)" + spacing allHVNActive allHVNActive 5 touching_ok \ + "High-Voltage Diffusion spacing must be at least 5 (MOSIS rule #20.2)" + spacing allHVPActive allHVPActive 5 touching_ok \ + "High-Voltage Diffusion spacing must be at least 5 (MOSIS rule #20.2)" + +/* 20.3 */ +/* High-Voltage transistors spacing to Well edge must be 7 lambda */ +/* This rule corresponds to rule 2.3 */ +/* without explicit well definition */ + spacing hndiff,hndc/a hpdiff,hpdc/a 14 touching_illegal \ + "P-type diffusion must be 14 away from N-type diffusion (MOSIS rule #20.3)" + spacing hndiff,hndc/a allPDiff 12 touching_illegal \ + "P-type diffusion must be 12 away from N-type diffusion (MOSIS rule #20.3+2.3)" + spacing hpdiff,hpdc/a allNDiff 12 touching_illegal \ + "P-type diffusion must be 12 away from N-type diffusion (MOSIS rule #20.3+2.3)" + +/* with explicit well definition */ + spacing hndiff,hnfet,hndc/a hnwell 7 touching_illegal \ + "HVN-diffusion and HVN-well must be separated by 7 (MOSIS rule #20.3)" + spacing hpdiff,hpfet,hpdc/a hpwell 7 touching_illegal \ + "HVP-diffusion and HVP-well must be separated by 7 (MOSIS rule #20.3)" + spacing allNOhmic hpwell 3 touching_illegal \ + "N-substrate diffusion and HVP-well must be separated by 3 (MOSIS rule #2.4+20.3)" + spacing allPOhmic hnwell 3 touching_illegal \ + "P-substrate diffusion and HVN-well must be separated by 3 (MOSIS rule #2.4+20.3)" + +/* 20.4 */ +/* Poly1 must not be used as an transistor for high-voltage design */ +/* guaranteed by the composition rules */ + +/* 20.5 */ +/* High-Voltage Active overlap of contact is now 2 lambda */ +/* This rule corresponds to rule 6B.2 */ + edge (~hndc)/a hndc/a 6 hndc/a hndc/a 6\ + "High-Voltage Diffusion contact width must be at least 6 (MOSIS rule #20.5)" + edge (~hpdc)/a hpdc/a 6 hpdc/a hpdc/a 6\ + "High-Voltage Diffusion contact width must be at least 6 (MOSIS rule #20.5)" + +/* 20.6 */ +/* High-Voltage transistor channel length must be at least 4 lambda */ + edge hpdiff,hpdc/a hpfet 4 hpfet 0 0 \ + "High-Voltage transistor must be at least 4 units long (MOSIS rule #20.6)" + edge hndiff,hndc/a hnfet 4 hnfet 0 0 \ + "High-Voltage transistor must be at least 4 units long (MOSIS rule #20.6)" + + + +/* ---------------------------------------------------------------- */ +/* overlapping rules */ + exact_overlap m3c,m2c,ndc,pdc,pc,psc,nsc,ec,capc,clc,emc,pbc,hndc,hpdc,hnsc,hpsc + no_overlap pfet,nfet pfet,nfet + no_overlap epfet,enfet epfet,enfet + no_overlap pffet,nffet pffet,nffet + no_overlap hpfet,hnfet hpfet,hnfet + +end + + +extract + + + +#ifndef OLD_EXTRACT_STYLE + +#include "scmosExt.tech.in" + +#else +/* In the following, MOSIS provides 9 extraction styles as follows: + + SCNA20(ORB) - ORBIT 2.0 micron low-noise analog N-well CMOS/BJT + process. *default* + SCPE20(ORB) - ORBIT 2.0 micron P-well CMOS/Bulk process. + SCNA16(AMI) - AMI 1.6 micron N-well CMOS/Junction-isolated BJT + process. + SCN12LC(HP) - HP CMOS34 1.2 micron N-well CMOS/Bulk process with + linear capacitor option. + SCNE12(ORB) - ORBIT 1.2 micron 2 poly N/P-well CMOS process. + SCN10(MOT) - MOTOROLA 1.0 micron N-well/P-epi CMOS process. + * Not Available at this moment * + SCN08(HP) - HP CMOS26B 1.0 micron N-well CMOS/Bulk process. + SCN08(IBM) - IBM 0.8 micron N-well CMOS/Bulk process. + * Not Available at this moment * + + Whenever it is available, measured data on MOSIS test structures + is used. Data is obtained from a representitive run (usually the + latest run at the time). If not available, typical (or nominal) + data from vendor wafer specification is used if not specifically + noted. + +*/ + +/* Have to redefine allMetal1 to make it pure metal line here... */ + +#undef allMetal1 +#define allMetal1 m1,m2c/m1 + + +#ifdef STANDARD +style SCNA20(ORB) +/* The following data is obtained from MOSIS run 'n34o' */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + cscale 1 + lambda 100 + step 100 + /* No parallel wire coupling capacitances */ + sidehalo 0 + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 27260 + resist pdiff,psd,pdc/a,psc/a 59550 + resist allPoly 23430 + resist allPoly2 19690 + resist em,emc/a 27260 + resist pbase,pbc/a 2000000 + resist metal1,m2c/metal1 52 + resist metal2,pad 26 + resist nwell 2505830 + + /* Contact resistance (in milliohms per square) */ + contact pc/a 4 11000 + contact ec/a,capc/a 4 9000 + contact ndc/a,nsc/a 4 18710 + contact pdc/a,psc/a 4 100560 + + /* Area parasitic capacitance to substrate (in attofarads per + lambda square) + [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + areacap poly,pc/a 39 + areacap metal1,pad,m2c/metal1 24 + areacap metal2 19 +/* + areacap ndiff,ndc/a 220 + areacap pdiff,pdc/a 270 +*/ + areacap cc/a,cap 39 + areacap poly2,ec/a 50 + + /* Inter-layer capacitance */ + overlap metal1 pdiff,ndiff,psd,nsd 47 + overlap metal2 pdiff,ndiff,psd,nsd 22 metal1 + overlap metal1 poly 30 + overlap metal2 poly 19 metal1 + overlap metal2 metal1 45 + overlap metal1 poly2 40 + + /* Perimeter parasitic capacitances (in attofarads per lambda) + [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] */ +/* + perimc ndiff,ndc/a space,pwell 559 + perimc pdiff,pdc/a space,nwell 402 +*/ + perimc poly,pc/a space,pwell,nwell 80 + + /* Active devices: N-Well process */ + fet pfet pdiff,pdc,pffet 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc,nffet 2 nfet GND! pwell 0 0 + fet epfet pdiff,pdc,pffet 2 epfet Vdd! 0 0 + fet enfet ndiff,ndc,nffet 2 enfet GND! 0 0 + + /* Kludge for MOS capacitance extraction, where source and drain + are connected together */ + fet pfet pdiff,pdc,pffet 1 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc,nffet 1 nfet GND! pwell 0 0 + + /* Electrode capacitance extraction */ + device capacitor None cap,capc/a poly,pc 120 735 + + /* DRAM capacitance extraction */ + device capacitor None wcap ndiff,ndc 300 0 + + /* bipolar NPN extraction */ + device bjt npn emit,emc/a pbase,pbc/a nwell + +style SCPE20(ORB) + +/* The following data is obtained from MOSIS run 'n35s', 6/93 */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + cscale 1 + lambda 100 + step 100 + /* No parallel wire coupling capacitances */ + sidehalo 0 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 26670 + resist pdiff,psd,pdc/a,psc/a 72860 + resist allPoly 23860 + resist allPoly2 18540 + resist metal1,m2c/metal1 49 + resist metal2,pad 26 + resist pwell 2128280 + + /* Contact resistance (in milliohm per contact) */ + contact pc/a 4 12800 + contact ec/a,capc/a 4 8420 + contact ndc/a,nsc/a 4 36660 + contact pdc/a,psc/a 4 56300 + contact m2c/m1 5 30 + + /* Area parasitic capacitance to substrate (in attofarads per + lambda square) + [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + areacap poly,pc/a 57 + areacap allMetal1,DiffMetal,HVDiffMetal 41 + areacap PolyMetal,BiMetal,CCDMetal 41 + areacap allMetal2 21 +/* + areacap ndiff,ndc/a 398 + areacap pdiff,pdc/a 230 +*/ + + /* Inter-layer capacitance */ + overlap metal1 pdiff,ndiff,psd,nsd 36 + overlap metal2 pdiff,ndiff,psd,nsd 16 metal1 + overlap metal1 poly 33 + overlap metal2 poly 15 metal1 + overlap metal2 metal1 29 + overlap metal1 poly2,cap 33 + + /* Perimeter parasitic capacitances (in attofarads per lambda) + [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] */ +/* + perimc ndiff,ndc/a space,pwell 423 + perimc pdiff,pdc/a space,nwell 85 +*/ + perimc poly,pc/a space,pwell,nwell 168 + + /* Active devices: P-Well process */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + + +style SCNA16(AMI) + +/* The following data is obtained from MOSIS run 'n34l', 6/93 */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + cscale 1 + lambda 80 + step 100 + /* No parallel wire coupling capacitances */ + sidehalo 0 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 51680 + resist pdiff,psd,pdc/a,psc/a 74800 + resist allPoly 34780 + resist allPoly2 22400 + resist allMetal1 48 + resist allMetal2 28 + resist nwell 1446400 + + /* Contact resistance (in milliohm per contact) */ + contact pc 4 61560 + contact ec 4 12010 + contact ndc,nsc 4 45780 + contact pdc,psc 4 32310 + contact m2c 5 37570 + + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.8 micron ---> multiplication factor 0.64 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + /* areacap nfet 709 */ + /* areacap pfet 669 */ + areacap poly,pc/a 22 + areacap allMetal1,DiffMetal,HVDiffMetal 15 + areacap PolyMetal,BiMetal,CCDMetal 15 + areacap allMetal2 10 + + /* Inter-layer capacitance */ + overlap allMetal1 ndiff,nsd 27 + overlap allMetal1 pdiff,psd 27 + overlap allMetal2 pdiff,psd 12 metal1 + overlap allMetal1 allPoly 25 + overlap allMetal1 allP2 25 + overlap allMetal2 allPoly 11 metal1 + overlap metal2 metal1 23 + /* Junction capacitance */ +/* + overlap ndiff,ndc/a space,pwell 172 + overlap pdiff,pdc/a space,nwell 200 +*/ + + /* Perimeter parasitic capacitances (in attofarads per lambda) + [ 1 lambda = 0.8 micron ---> multiplication factor 0.8 ] */ +/* + perimc ndiff,ndc/a space,allWell 6 + perimc pdiff,pdc/a space,allWell 68 +*/ + + /* Active devices: N-Well process, */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + + +style SCNE12(ORB) + +/* The following data is obtained from MOSIS run 'n37d', 7/93 */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + cscale 1 + lambda 60 + step 100 + /* No parallel wire coupling capacitances */ + sidehalo 0 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistances (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 43180 + resist pdiff,psd,pdc/a,psc/a 79770 + resist allPoly 22160 + resist allPoly2 21140 + resist allMetal1 51 + resist allMetal2 26 + resist nwell 1195000 + + /* Contact resistances (in milliohm per contact) */ + contact pc 4 13230 + contact ec 4 13510 + contact ndc,nsc 4 56490 + contact pdc,psc 4 181400 + contact m2c 5 43330 + + + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.6 micron ---> multiplication factor 0.36 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + /* areacap nfet 454 */ + /* areacap pfet 368 */ + areacap poly,pc/a 29 + areacap allMetal1,DiffMetal,HVDiffMetal 16 + areacap PolyMetal,BiMetal,CCDMetal 16 + areacap allMetal2 10 + + overlap allMetal1 ndiff,ndc/a 22 + overlap allMetal1 allPoly 19 + overlap allMetal1 allP2 21 + overlap allMetal2 ndiff,ndc/a 8 + overlap allMetal2 allPoly 7 + overlap metal2 metal1 12 + /* Junction capacitance */ + overlap ndiff,ndc/a space,pwell 185 + overlap pdiff,pdc/a space,nwell 148 + + /* Perimeter parasitic capacitances (in attofarads per lambda) + [ 1 lambda = 0.6 micron ---> multiplication factor 0.6 ] */ + perimc allMetal1 space,allWell 41 + perimc allMetal2 space,allWell 42 + /* Junction capacitances */ +/* + perimc ndiff,ndc/a space,pwell 236 + perimc pdiff,pdc/a space,nwell 147 +*/ + + /* No measurements for this run, but leave here for future... + sideoverlap allMetal1 space,allWell PNplus 60 + sideoverlap allMetal2 space,allWell allPoly 60 + sideoverlap allMetal2 space,allWell PNplus 57 + sideoverlap allMetal2 space,allWell allPoly 57 + sideoverlap allMetal2 space,allWell allMetal1 64 + */ + + /* Nwell process, so PMOS has "nwell" defined for analog + designs... */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + + +#endif /* STANDARD */ + +#ifdef TIGHTMETAL +style SCN12LC(HP) + +/* The following data is obtained from MOSIS run 'n36y', 7/93 */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + cscale 1 + lambda 60 + step 100 + /* No parallel wire coupling capacitances */ + sidehalo 0 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nnd,ndc/a,nsc/a 74630 + resist pdiff,ppd,pdc/a,psc/a 109590 + resist poly,pc/a,pfet,nfet 26620 + resist allMetal1 60 + resist allMetal2 39 + resist nwell 1500000 + + /* Contact resistance (in milliohm per contact) */ + contact ndc 4 77000 + contact pdc 4 44260 + contact pc 4 16210 + contact m2c 5 86560 + + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.6 micron ---> multiplication factor 0.36 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + /* areacap nfet 556 */ + /* areacap pfet 489 */ + areacap poly,pc/a 22 + areacap allMetal1,DiffMetal,HVDiffMetal 14 + areacap PolyMetal,BiMetal,CCDMetal 14 + areacap allMetal2 9 + + /* Inter-layer capacitance */ + overlap allMetal1 allPoly 24 + overlap allMetal2 allPoly 7 metal1 + overlap metal2 metal1 14 + /* Junction capacitance */ +/* + overlap ndiff,ndc/a space,pwell 106 + overlap pdiff,pdc/a space,nwell 183 +*/ + + /* Perimeter parasitic capacitances (in attofarads per lambda) + [ 1 lambda = 0.6 micron ---> multiplication factor 0.6 ] */ + /* perimc nfet ndiff 90 */ + /* perimc pfet pdiff 817 */ + /* Junction capacitances */ +/* + perimc ndiff,ndc/a space,allWell 102 + perimc pdiff,pdc/a space,allWell 2 +*/ + + /* Active devices: Nwell process, so PMOS has "nwell" defined + for analog designs... */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + /* Kludge for DRAM capacitance extraction */ + fet wcap ndiff,ndc 1 wcap GND! 300 0 + +/* These stuff are experimental..... + fake npn: + fet emit,emc/a pbase 1 d1np XSLLU! nwell 0 0 + fet fpb nwell 1 d2pn YSLLU! col,clc 0 0 + */ + +/* saturation :: R = V (5V) / Idss + fetresist nfet saturation 12000 + fetresist pfet saturation 28000 + fetresist enfet saturation 12000 + fetresist epfet saturation 28000 + + I am not sure how to do this yet, so I give the same value as + saturation! + + fetresist nfet linear 12000 + fetresist pfet linear 28000 + fetresist enfet linear 12000 + fetresist epfet linear 28000 + */ + + +style SCN08(HP) + +/* The following data is obtained from MOSIS run 'n33h', 7/93 */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + cscale 1 + lambda 50 + step 100 + /* Parallel wire coupling capacitance enabled */ + sidehalo 8 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 2280 + resist pdiff,psd,pdc/a,psc/a 1990 + resist poly 3480 + resist allMetal1 67 + resist allMetal2 65 + resist allMetal3 29 + resist nwell 1265560 + + /* Contact resistance (in milliohm per contact) */ + contact pc 4 1680 + contact ndc,pdc,nsc,psc 4 1100 + contact m2c 5 305 + contact m3c 5 259 + + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.5 micron ---> multiplication factor 0.25 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + /* areacap nfet 457 */ + /* areacap pfet 403 */ + areacap poly,pc/a 16 + areacap allMetal1,DiffMetal,HVDiffMetal 9 + areacap PolyMetal,BiMetal,CCDMetal 9 + areacap allMetal2 5 + areacap allMetal3 4 + + /* Inter-layer capacitance */ + overlap allMetal1 PNplus 13 + overlap allMetal1 allPoly 13 + overlap allMetal2 PNplus 4 + overlap allMetal2 allPoly 4 + overlap allMetal2 allMetal1 6 + overlap allMetal3 PNplus 2 + overlap allMetal3 allPoly 2 + overlap allMetal3 allMetal1 3 + overlap allMetal3 allMetal2 7 + /* Junction capacitance */ + overlap ndiff,ndc/a space,pwell 27 + overlap pdiff,pdc/a space,nwell 148 + + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.5 micron ---> multiplication factor 0.5 ] */ + perimc allMetal1 space,allWell 43 + perimc allMetal2 space,allWell 36 + perimc allMetal3 space,allWell 36 + + sideoverlap allMetal1 space,allWell allPoly 14 + sideoverlap allMetal2 space,allWell allPoly 5 + /* no such data for m2-to-m1, use data from specification file */ + sideoverlap allMetal2 space,allWell allMetal1 13 + sideoverlap allMetal3 space,allWell allPoly 1 + sideoverlap allMetal3 space,allWell allMetal1 4 + sideoverlap allMetal3 space,allWell allMetal2 13 + + /* Active devices: N-well process */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + +#endif /* TIGHTMETAL */ + +#ifdef IBMTECH +style SCN08(IBM) + +/* The following data is obtained from MOSIS run 'n42s', 1/94 */ +/* Last modified by pi@isi.edu, 6/27/94 */ + + cscale 1 + lambda 40 + step 100 + /* Parallel wire coupling capacitance disabled */ + sidehalo 0 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 3300 + resist pdiff,psd,pdc/a,psc/a 3180 + resist poly 3630 + resist allMetal1 43 + resist allMetal2 36 + resist allMetal3 36 + /* not monitored on PCM, use specification value */ + resist nwell 520000 + + /* Contact resistance (in milliohm per contact) */ + contact ndc,nsc 4 2530 + contact pc 4 7510 + contact pdc,psc 4 2160 + contact m2c 5 330 + contact m3c 5 292 + + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.16 ] */ +#endif /* IBMTECH */ + +#ifdef SUBMICRON +style SCN08(HP26G) + +/* The following data is obtained from MOSIS run 'n48r', 10/94 */ +/* Last modified by pi@isi.edu, 11/02/94 */ + + cscale 1 + lambda 40 + step 100 + /* Parallel wire coupling capacitance enabled */ + sidehalo 8 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 2375 + resist pdiff,psd,pdc/a,psc/a 2000 + resist allPoly 2350 + resist allMetal1 70 + resist allMetal2 67 + resist allMetal3 30 + resist nwell 1265000 + + /* Contact resistance (in milliohm per contact) */ + contact pc 4 1250 + contact ndc,nsc 4 1300 + contact pdc,psc 4 1125 + contact m2c 5 430 + contact m3c 5 300 + + /* The following are 10 types of capacitance extracted: + 1. poly to substrate. + 2. metal1 to substrate. + 3. metal1 to poly. + 4. metal2 to substrate. + 5. metal2 to poly. + 6. metal2 to metal1. + 7. metal3 to substrate. + 8. metal3 to poly. + 9. metal3 to metal1. + 10. metal3 to metal2. + + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, + remove the following comment. */ + /* areacap nfet 334 */ + /* areacap pfet 315 */ + + /* Type 1,2,4,7 (to substrate) */ + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.16 ] */ + areacap poly,pc/a 13 + areacap allMetal1,DiffMetal,HVDiffMetal 6 + areacap PolyMetal,BiMetal,CCDMetal 6 + areacap allMetal2 3 + areacap allMetal3 2 + + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.4 ] */ + perimc poly,pc/a ~(poly,pc/a) 19 + perimc allMetal1 ~(allMetal1) 20 + perimc allMetal2 ~(allMetal2) 16 + perimc allMetal3 ~(allMetal3) 14 + + /* Inter-layer capacitance, type 3,5,6,8,9,10 */ + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.16 ] */ + overlap allMetal1 allPoly 9 + overlap allMetal2 allPoly 3 + overlap allMetal2 allMetal1 5 + overlap allMetal3 allPoly 2 + overlap allMetal3 allMetal1 3 + overlap allMetal3 allMetal2 5 + + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.4 ] */ + sideoverlap allMetal1 space,allWell allPoly 23 + sideoverlap allMetal2 space,allWell allPoly 17 + sideoverlap allMetal2 space,allWell allMetal1 19 + sideoverlap allMetal3 space,allWell allPoly 15 + sideoverlap allMetal3 space,allWell allMetal1 17 + sideoverlap allMetal3 space,allWell allMetal2 21 + + /* Cross-couple capacitance */ + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.4 ] */ + sidewall allP ~(allP) ~(allP) allP 11 + sidewall allMetal1 ~(allMetal1) ~(allMetal1) allMetal1 24 + sidewall allMetal2 ~(allMetal2) ~(allMetal2) allMetal2 27 + sidewall allMetal3 ~(allMetal3) ~(allMetal3) allMetal3 39 + + /* Active devices: N-well process */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + + +style SCN06(HP14B) + +/* Not yet.... */ +/* Last modified by pi@isi.edu, 03/10/95 */ + + cscale 1 + lambda 30 + step 100 + /* Parallel wire coupling capacitance enabled */ + sidehalo 8 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 2375 + resist pdiff,psd,pdc/a,psc/a 2000 + resist allPoly 2350 + resist allMetal1 70 + resist allMetal2 67 + resist allMetal3 30 + resist nwell 1265000 + + /* Contact resistance (in milliohm per contact) */ + contact pc 4 1250 + contact ndc,nsc 4 1300 + contact pdc,psc 4 1125 + contact m2c 5 430 + contact m3c 5 300 + + /* The following are 10 types of capacitance extracted: + 1. poly to substrate. + 2. metal1 to substrate. + 3. metal1 to poly. + 4. metal2 to substrate. + 5. metal2 to poly. + 6. metal2 to metal1. + 7. metal3 to substrate. + 8. metal3 to poly. + 9. metal3 to metal1. + 10. metal3 to metal2. + + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, + remove the following comment. */ + /* areacap nfet 334 */ + /* areacap pfet 315 */ + + /* Type 1,2,4,7 (to substrate) */ + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.3 micron ---> multiplication factor 0.09 ] */ + areacap poly,pc/a 7 + areacap allMetal1,DiffMetal,HVDiffMetal 3 + areacap PolyMetal,BiMetal,CCDMetal 3 + areacap allMetal2 1 + areacap allMetal3 1 + + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.3 micron ---> multiplication factor 0.3 ] */ + perimc poly,pc/a ~(poly,pc/a) 14 + perimc allMetal1 ~(allMetal1) 15 + perimc allMetal2 ~(allMetal2) 12 + perimc allMetal3 ~(allMetal3) 10 + + /* Inter-layer capacitance, type 3,5,6,8,9,10 */ + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.3 micron ---> multiplication factor 0.09 ] */ + overlap allMetal1 allPoly 5 + overlap allMetal2 allPoly 2 + overlap allMetal2 allMetal1 3 + overlap allMetal3 allPoly 1 + overlap allMetal3 allMetal1 1 + overlap allMetal3 allMetal2 3 + + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.3 micron ---> multiplication factor 0.3 ] */ + sideoverlap allMetal1 space,allWell allPoly 17 + sideoverlap allMetal2 space,allWell allPoly 14 + sideoverlap allMetal2 space,allWell allMetal1 15 + sideoverlap allMetal3 space,allWell allPoly 11 + sideoverlap allMetal3 space,allWell allMetal1 13 + sideoverlap allMetal3 space,allWell allMetal2 16 + + /* Cross-couple capacitance */ + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.3 micron ---> multiplication factor 0.3 ] */ + sidewall allP ~(allP) ~(allP) allP 9 + sidewall allMetal1 ~(allMetal1) ~(allMetal1) allMetal1 19 + sidewall allMetal2 ~(allMetal2) ~(allMetal2) allMetal2 21 + sidewall allMetal3 ~(allMetal3) ~(allMetal3) allMetal3 31 + + /* Active devices: N-well process */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + +#endif /* SUBMICRON */ + +#endif /* OLD_EXTRACT_STYLE */ +end + + +wiring + contact pdcontact 4 pdiff 0 metal1 0 + contact ndcontact 4 ndiff 0 metal1 0 + contact pcontact 4 poly 0 metal1 0 + contact ec 6 poly2 0 metal1 0 + contact m2contact 4 metal1 0 metal2 0 + contact m3contact 5 metal2 0 metal3 0 +end + +router + layer1 metal1 3 allMetal1 3 + layer2 metal2 3 allMetal2 4 allPoly,allDiff 1 + contacts m2contact 4 + gridspacing 8 +end + +plowing + fixed allFet,glass,pad + covered allFet + drag allFet +end + +plot + /* based on Jeffrey C. Gealow's (jgealow@mtl.mit.edu) contribution */ + style colorversatec + + ndiff,ndc yellow \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA + + ndiff,ndc cyan \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 + + + nsd,nsc,col,clc yellow \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 + + nsd,nsc,col,clc cyan \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 + + + pdiff,pdc yellow \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA + + pdiff,pdc cyan \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 + + pdiff,pdc magenta \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 + + + psd,psc yellow \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 + + psd,psc cyan \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 + + psd,psc magenta \ + 2A2A 0000 A2A2 0000 \ + 2A2A 0000 A2A2 0000 \ + 2A2A 0000 A2A2 0000 \ + 2A2A 0000 A2A2 0000 + + + poly,pc/a magenta \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA + + + poly2,ec/a yellow \ + FFFF FFFF FFFF FFFF \ + FFFF FFFF FFFF FFFF \ + FFFF FFFF FFFF FFFF \ + FFFF FFFF FFFF FFFF + + + nfet yellow \ + 0505 8282 1414 0A0A \ + 5050 2828 4141 A0A0 \ + 0505 8282 1414 0A0A \ + 5050 2828 4141 A0A0 + + nfet cyan \ + 0000 0505 0000 1414 \ + 0000 5050 0000 4141 \ + 0000 0505 0000 1414 \ + 0000 5050 0000 4141 + + nfet magenta \ + 5050 2828 4141 A0A0 \ + 0505 8282 1414 0A0A \ + 5050 2828 4141 A0A0 \ + 0505 8282 1414 0A0A + + + enfet yellow \ + BABA 7575 EAEA D5D5 \ + ABAB 5757 AEAE 5D5D \ + BABA 7575 EAEA D5D5 \ + ABAB 5757 AEAE 5D5D + + enfet cyan \ + 4141 0A0A 0505 2828 \ + 1414 A0A0 5050 8282 \ + 4141 0A0A 0505 2828 \ + 1414 A0A0 5050 8282 + + + nffet yellow \ + 8E8E 0707 8B8B D5D5 \ + E8E8 7070 B8B8 5D5D \ + 8E8E 0707 8B8B D5D5 \ + E8E8 7070 B8B8 5D5D + + nffet cyan \ + 0101 0808 1414 2828 \ + 1010 8080 4141 8282 \ + 0101 0808 1414 2828 \ + 1010 8080 4141 8282 + + nffet magenta \ + 5050 A0A0 4040 0202 \ + 0505 0A0A 0404 2020 \ + 5050 A0A0 4040 0202 \ + 0505 0A0A 0404 2020 + + + pfet yellow \ + 6363 A0A0 5050 2828 \ + 3636 0A0A 0505 8282 \ + 6363 A0A0 5050 2828 \ + 3636 0A0A 0505 8282 + + pfet cyan \ + 0000 5151 0000 5454 \ + 0000 1515 0000 1515 \ + 0000 5151 0000 5454 \ + 0000 1515 0000 1515 + + pfet magenta \ + 9494 0A0A 2525 8282 \ + 4949 A0A0 5252 2828 \ + 9494 0A0A 2525 8282 \ + 4949 A0A0 5252 2828 + + + epfet yellow \ + BCBC 4F4F 2F2F D3D3 \ + CBCB F4F4 F2F2 3D3D \ + BCBC 4F4F 2F2F D3D3 \ + CBCB F4F4 F2F2 3D3D + + epfet cyan \ + 0000 A0A0 0000 2828 \ + 0000 0A0A 0000 8282 \ + 0000 A0A0 0000 2828 \ + 0000 0A0A 0000 8282 + + epfet magenta \ + 4141 0000 5050 0000 \ + 1414 0000 0505 0000 \ + 4141 0000 5050 0000 \ + 1414 0000 0505 0000 + + + pffet yellow \ + 7B7B F0F0 F0F0 E9E9 \ + B7B7 0F0F 0F0F 9E9E \ + 7B7B F0F0 F0F0 E9E9 \ + B7B7 0F0F 0F0F 9E9E + + pffet cyan \ + 0000 0101 0000 1414 \ + 0000 1010 0000 4141 \ + 0000 0101 0000 1414 \ + 0000 1010 0000 4141 + + pffet magenta \ + 8484 0A0A 2525 8282 \ + 4848 A0A0 5252 2828 \ + 8484 0A0A 2525 8282 \ + 4848 A0A0 5252 2828 + + + cap,cc/a yellow \ + 3E3E 7777 E3E3 C1C1 \ + E3E3 7777 3E3E 1C1C \ + 3E3E 7777 E3E3 C1C1 \ + E3E3 7777 3E3E 1C1C + + cap,cc/a magenta \ + 4141 8888 1414 2A2A \ + 1414 8888 4141 A2A2 \ + 4141 8888 1414 2A2A \ + 1414 8888 4141 A2A2 + + + allMetal1 cyan \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 + + + allMetal2 cyan \ + 0000 1111 0000 4444 \ + 0000 1111 0000 4444 \ + 0000 1111 0000 4444 \ + 0000 1111 0000 4444 + + allMetal2 magenta \ + 0000 4444 0000 1111 \ + 0000 4444 0000 1111 \ + 0000 4444 0000 1111 \ + 0000 4444 0000 1111 + + + m2c/m1 black \ + 0000 6666 6666 0000 \ + 0000 9999 9999 0000 \ + 0000 6666 6666 0000 \ + 0000 9999 9999 0000 + + + pad,glass black \ + 0300 0700 0E00 1C00 \ + 3800 7000 E000 C000 \ + 00C0 00E0 0070 0038 \ + 001C 000E 0007 0003 + + + nwell yellow \ + 0800 1000 2000 4000 \ + 8000 0001 0002 0004 \ + 0008 0010 0020 0040 \ + 0080 0010 0200 0400 + + nwell cyan \ + 1000 2000 4000 8000 \ + 0001 0002 0004 0008 \ + 0010 0020 0040 0080 \ + 0100 0200 0400 0800 + + + pwell yellow \ + 1000 0400 0400 0100 \ + 0100 0040 0040 0010 \ + 0010 0004 0004 0001 \ + 0001 4000 4000 1000 + + pwell cyan \ + 0000 0800 0000 0200 \ + 0000 0080 0000 0020 \ + 0000 0008 0000 0002 \ + 0000 8000 0000 2000 + + pwell magenta \ + 0800 0000 0200 0000 \ + 0080 0000 0020 0000 \ + 0008 0000 0002 0000 \ + 8000 0000 2000 0000 + + + bd yellow \ + 4444 8888 4444 8888 \ + 4444 8888 4444 8888 \ + 4444 8888 4444 8888 \ + 4444 8888 4444 8888 + + bd cyan \ + 0000 4444 0000 4444 \ + 0000 4444 0000 4444 \ + 0000 4444 0000 4444 \ + 0000 4444 0000 4444 + + bd magenta \ + 8888 0000 8888 0000 \ + 8888 0000 8888 0000 \ + 8888 0000 8888 0000 \ + 8888 0000 8888 0000 + + + nbd,nbdc yellow \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA + + nbd,nbdc cyan \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 + + nbd,nbdc magenta \ + 8888 0000 8888 0000 \ + 8888 0000 8888 0000 \ + 8888 0000 8888 0000 \ + 8888 0000 8888 0000 + + + em,emc yellow \ + 4444 8888 4444 8888 \ + 4444 8888 4444 8888 \ + 4444 8888 4444 8888 \ + 4444 8888 4444 8888 + + em,emc cyan \ + 0000 4444 0000 4444 \ + 0000 4444 0000 4444 \ + 0000 4444 0000 4444 \ + 0000 4444 0000 4444 + + + pbase,pbc yellow \ + 5555 AAAA 0000 0000 \ + 5555 AAAA 0000 0000 \ + 5555 AAAA 0000 0000 \ + 5555 AAAA 0000 0000 + + pbase,pbc cyan \ + 0000 5555 0000 0000 \ + 0000 5555 0000 0000 \ + 0000 5555 0000 0000 \ + 0000 5555 0000 0000 + + pbase,pbc magenta \ + AAAA 0000 0000 0000 \ + AAAA 0000 0000 0000 \ + AAAA 0000 0000 0000 \ + AAAA 0000 0000 0000 + + + allMetal3 black \ + 0100 0000 0000 0000 \ + 1010 0000 0000 0000 \ + 0001 0000 0000 0000 \ + 1010 0000 0000 0000 + + allMetal3 cyan \ + 0280 0000 0820 0000 \ + 2008 0000 8002 0000 \ + 8002 0000 2008 0000 \ + 0820 0000 0280 0000 + + allMetal3 magenta \ + 0100 06C0 0440 1830 \ + 1010 600C 4004 8003 \ + 0001 C006 4004 3018 \ + 1010 0C60 0440 0380 + + + m3c/m2 black \ + 0820 0820 0820 0FE0 \ + E00F 2008 2008 2008 \ + 2008 2008 2008 E00F \ + 0000 0FE0 0820 0820 + + + error_p,error_s,error_ps black \ + 0000 3C3C 4646 4A4A \ + 5252 6262 3C3C 0000 \ + 0000 3C3C 4646 4A4A \ + 5252 6262 3C3C 0000 + + + magnet yellow \ + AAAA 0000 5555 0000 \ + AAAA 0000 5555 0000 \ + AAAA 0000 5555 0000 \ + AAAA 0000 5555 0000 + + + fence magenta \ + FFFF 0000 0000 0000 \ + 0000 0000 0000 0000 \ + FFFF 0000 0000 0000 \ + 0000 0000 0000 0000 + + + rotate cyan \ + 0000 E0E0 E0E0 E0E0 \ + 0000 0000 0000 0000 \ + 0000 E0E0 E0E0 E0E0 \ + 0000 0000 0000 0000 + + + allCut,BiCut X + + + style versatec + + pfet \ + 07c0 0f80 1f00 3e00 \ + 7c00 f800 f001 e003 \ + c007 800f 001f 003e \ + 00c7 00f8 01f0 03e0 + + + nfet \ + 1f00 0f80 07c0 03e0 \ + 01f0 00f8 007c 003e \ + 001f 800f c007 e003 \ + f001 f800 7c00 3e00 + + + m2c \ + c3c3 c3c3 0000 0000 \ + 0000 0000 c3c3 c3c3 \ + c3c3 c3c3 0000 0000 \ + 0000 0000 c3c3 c3c3 + + + pwell \ + 2020 2020 2020 2020 \ + 2020 2020 2020 2020 \ + 0000 0000 0000 0000 \ + 0000 0000 0000 0000 + + + nwell \ + 0808 0404 0202 0101 \ + 0000 0000 0000 0000 \ + 0808 0404 0202 0101 \ + 0000 0000 0000 0000 + + + allPoly \ + 0808 0400 0202 0101 \ + 8080 4000 2020 1010 \ + 0808 0004 0202 0101 \ + 8080 0040 2020 1010 + + + allMetal1 \ + 8080 0000 0000 0000 \ + 0808 0000 0000 0000 \ + 8080 0000 0000 0000 \ + 0808 0000 0000 0000 + + + pad,glass \ + 0000 0000 1c1c 3e3e \ + 3636 3e3e 1c1c 0000 \ + 0000 0000 1c1c 3e3e \ + 3636 3e3e 1c1c 0000 + + + nsd,nsc,col,clc \ + 0808 1414 2222 4141 \ + 8080 4040 2020 1010 \ + 0808 1414 2222 4141 \ + 8080 4040 2020 1010 + + + allMetal2 \ + 0000 1111 0000 0000 \ + 0000 1111 0000 0000 \ + 0000 1111 0000 0000 \ + 0000 1111 0000 0000 + + + pdiff,pdc,pfet \ + 0000 0808 5555 8080 \ + 0000 8080 5555 0808 \ + 0000 0808 5555 8080 \ + 0000 8080 5555 0808 + + + psd,psc \ + 1414 2222 0000 2222 \ + 4141 2222 0000 2222 \ + 1414 2222 0000 2222 \ + 4141 2222 0000 2222 + + + ndiff,nfet,ndc \ + 0808 1010 2020 4040 \ + 8080 4141 2222 1414 \ + 0808 1010 2020 4040 \ + 8080 4141 2222 1414 + + + allPoly2 \ + 0000 2020 5050 2020 \ + 0000 0202 0505 0202 \ + 0000 2020 5050 2020 \ + 0000 0202 0505 0202 + + + allCut,BiCut X + +/* -------------------------------------------------------------- */ + style gremlin + pfet 9 + nfet 10 + m2c 11 + pwell 15 + nwell 16 + allPoly 19 + allMetal1 22 + pad,glass 23 + nsd,nsc 24 + allMetal2 28 + pdiff,pdc,pfet 29 + psd,psc 30 + ndiff,nfet,ndc 31 + m2c/m1,pc/m1,ndc/m1,pdc/m1,psc/m1,nsc/m1,pad/m1 X +/* -------------------------------------------------------------- */ + style postscript +/* + * stipple definitions for 32x8 bitmaps + * # row1 row2 row3 row4 row5 row6 row7 row8 + */ + 1 C0C0C0C0 C0C0C0C0 00000000 00000000 0C0C0C0C 0C0C0C0C 00000000 00000000 + 2 A0A0A0A0 0A0A0A0A A0A0A0A0 0A0A0A0A A0A0A0A0 0A0A0A0A A0A0A0A0 0A0A0A0A + 3 00030003 000C000C 00300030 00C000C0 03000300 0C000C00 30003000 C000C000 + 4 00000000 00000000 C0C0C0C0 00000000 00000000 00000000 0C0C0C0C 00000000 + 5 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF + 6 07070707 0E0E0E0E 1C1C1C1C 38383838 70707070 E0E0E0E0 C1C1C1C1 83838383 + 7 18181818 30303030 60606060 C0C0C0C0 81818181 03030303 06060606 0C0C0C0C + 8 18181818 0C0C0C0C 06060606 03030303 81818181 C0C0C0C0 60606060 30303030 + 9 18181818 3C3C3C3C 3C3C3C3C 18181818 81818181 C3C3C3C3 C3C3C3C3 81818181 + 10 F0F0F0F0 60606060 06060606 0F0F0F0F 0F0F0F0F 06060606 60606060 F0F0F0F0 + 11 01000080 02000040 0C000030 F000000F 000FF000 00300C00 00400200 00800100 + 12 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 + 13 00000000 00000000 33333333 33333333 00000000 00000000 CCCCCCCC CCCCCCCC +/* + * color definitions in CMYK format + * # C M Y K closest named color in RGB space + */ + 1 47 95 111 0 /* RosyBrown3 */ + 2 223 31 223 0 /* limegreen */ + 3 0 0 0 192 /* gray25 */ + 4 31 111 31 0 /* plum */ + 5 31 111 255 0 /* orange2 */ + 6 63 95 191 0 /* goldenrod3 */ + 7 255 63 255 0 /* green3 */ + 8 0 0 0 127 /* gray50 */ + 9 223 47 223 0 /* limegreen */ + 10 0 255 255 0 /* red */ + 11 0 0 255 0 /* yellow */ + 12 191 127 0 0 /* RoyalBlue1 */ + 13 95 223 63 0 /* DarkOrchid3 */ + 14 0 0 0 255 /* black */ + 15 191 127 63 0 /* steelblue */ + 16 111 151 244 0 /* goldenrod4 */ + 17 23 175 183 0 /* tomato2 */ +/* + * magic layer definitions (plotted top to bottom) + * layer(s) color# stipple# (plus B=box, X=cross & box) + */ + cc,pc,ndc,pdc,psc,nsc 14 X + m2c,pad,glass 14 B + pad,glass 14 11 + m2c 14 13 + m2,m2c,pad 13 10 + pdc,ndc,psc,nsc,hpdc,hndc,hpsc,hnsc,pc,ec,capc,clc,emc,pbc,nbdc,m1,m2c,gc 12 9 + cap,cc,poly2 11 7 + nsd,nsc 7 1 + psd,psc 6 1 + nfet,nffet 9 8 + pfet,wcap,pffet 1 7 + poly,pc,cap,cc 10 5 + nfet 16 5 + pfet,wcap 17 5 + pdiff,pdc,pffet 1 5 + ndiff,ndc,nffet 9 5 + pwell 1 4 + nwell 2 4 + +/* ------------------------------------------------------------------------ */ + style pnm + draw metal1 + draw metal2 + draw polysilicon + draw ndiffusion + draw pdiffusion + draw ntransistor + draw ptransistor + map psubstratepdiff pdiffusion + map nsubstratendiff ndiffusion + map polycontact polysilicon metal1 + map m2contact metal1 metal2 + map m3contact metal2 metal3 + map ndcontact ndiffusion metal1 + map pdcontact pdiffusion metal1 + map nsubstratencontact ndiffusion metal1 + map psubstratepcontact pdiffusion metal1 + +end diff --git a/scmos/test.out b/scmos/test.out new file mode 100644 index 00000000..5213039d --- /dev/null +++ b/scmos/test.out @@ -0,0 +1,3256 @@ +/* --------------------------------------------------------------------* + * * + * scmos.tech -- MOSIS Scalable CMOS (SCMOS) Magic technology file. * + * * + * MOSIS distribution Version 8.2 * + * * + * Defines the MOSIS 0.6/0.8/1.0/1.2/2.0 micron Scalable CMOS * + * (SCMOS) technology. * + * * + * (C) Copyright 1992, 1993, 1994, 1995 by * + * * + * Jen-I Pi pi@isi.edu * + * The MOSIS Service * + * USC Information Sciences Institute * + * 4676 Admiralty Way * + * Marina del Rey, CA 90292 * + * voice: (310) 822-1511 x640, fax: (310)823-5624 * + * * + * All Rights Reserved. * + * Last Modified Date: 04/26/1995 * + * * + * Permission to use, copy, modify, and distribute this technology * + * file and its associated documentation for any purpose and without * + * fee is hereby granted, provided that the above copyright notice * + * appears in all copies and that both that copyright notice and this * + * permission notice appear in supporting documentation, and that the * + * name of the University of Southern California not be used in * + * advertising or publicity pertaining to distribution of this * + * technology file without specific, written prior permission. * + * The University of Southern California makes no representations * + * about the suitability of this technology file for any purpose. * + * This technology file is provided "as is" without express or implied * + * warranty and the University of Southern California retains the * + * right to change its content at any time without notice any other * + * party. * + * * + * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH * + * REGARD TO THIS TECHNOLOGY FILE, INCLUDING ALL IMPLIED WARRANTIES OF * + * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * + * SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR * + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS TECHNOLOGY FILE. * + * * + * ------------------------------------------------------------------- */ + +/* --------------------------------------------------------------------* + * Some of the characteristics of this technology are: * + * * + * 1. 3 levels of metal - for HP's CMOS26B (lambda=0.5) and CMOS26G * + * (lambda=0.4) and CMOS14TB (lambda=0.35 or 0.3) processes * + * 3 levels of metal stack via - for IBM's CMSX2185 (lambda=0.4) * + * process * + * 2 levels of metal interconnection for all other technologies * + * 2. 2 levels of poly - for ORBIT's low-noise analog process * + * second poly is used for poly-capacitor or electrode fet (efet) * + * 3. Vertical NPN transistor, BCCD device, Floating-gate device for * + * ORBIT's low-noise anaolog process * + * 4. All contacts are composite (with the necessary enclosure) * + * 5. No stacked contacts (all contacts are to 1st-level metal) * + * 6. An open layer is added for fabrication of micromachined devices * + * as in Janet C. Marshall's paper in IEEE Circuit and Devices, * + * Vol. 8, N0. 6, 1992. * + * This layer is currently NOT available for standard MOSIS SCMOS * + * techonology installation. You need to define OPEN with the C- * + * preprocessor for installation. See README file for detail... * + * 7 A pstop layer is used also in micromachineing device fabrication * + * to stop the EDP etchant as used in Marshall's article. * + * 8 A Cap-well (cwell) for HP's CMOS34 (lambda=0.6) process, It is * + * used for consctruction of linear capacitors * + * Must be drawn explicitly * + * 9. Wells (Pwell or Nwell) can be implicit or explicit in the layout * + * and both types of diffusion must have well contacts * + *10. Painting Nwell over N-type diffusion will result in P-type * + * diffusion * + *11. Scalable with Default to be 2.0 micron rules for Nwell process * + *12. Substrate contacts must be 3 units away from gates * + *13. Stacked via supported through special compiled option -DSTACKVIA * + * for IBM process. * + * * + * Revision 8.2.8 (pi) * + * fix CCD CIF input style for "bd" layer. * + * 12/13/95 pi@isi.edu * + * Revision 8.2.7 (pi) * + * Add Magic 6.4.4 new extraction plane orders. * + * 07/25/95 pi@isi.edu * + * Revision 8.2.5 (pi) * + * Fix some typos... * + * 05/12/95 pi@isi.edu * + * Revision 8.2.4 (pi) * + * Fix CBA generation for pbase and add extension rules for pbase * + * as resistors. * + * Gratitude goes to Tetsuya Kajita (kaj@ssac.yamatake.co.jp) * + * 04/26/95 pi@isi.edu * + * Revision 8.2.3 (pi) * + * fix for SUBMICRON DRC rule. * + * Thanks goes to Toby Schaffer (jtschaff@eos.ncsu.edu) * + * 04/06/95 pi@isi.edu * + * Revision 8.2.2 (pi) * + * add XP GDS official number to fix CIF input problem for "pad". * + * Thanks goes to Brian Kingsbury (bedk@ICSI.Berkeley.EDU). * + * 04/03/95 pi@isi.edu * + * Revision 8.2.1 (pi) * + * Some fixes for CMOS14B CIF output section. * + * 03/21/95 pi@isi.edu * + * Revision 8.2.0 (pi) * + * support for HP CMOS26G and CMOS14TB process. * + * 03/15/95 pi@isi.edu * + * Revision 8.1.1 (pi) * + * add connection of "ndiff" to "psd". Thank goes to Alireza Moini* + * (moini@eleceng.adelaide.edu.au). * + * 12/21/94 pi@isi.edu * + * Revision 8.1.0 (pi) * + * major revision of bipolar transistor rules. It now support * + * both ORBIT 2.0 and 1.2 micron processes. NOTE: active layer * + * for pbase is now generated in CIF file explicitly. * + * 10/31/94 pi@isi.edu * + * Revision 8.0.7 (pi) * + * remove both VTI and IBM support * + * 10/10/94 pi@isi.edu * + * Revision 8.0.7 (pi) * + * compose for high-voltage transistors corrected. Thank goes to * + * Bob Durie (bobd@ee.cornell.edu) * + * 8/25/94 pi@isi.edu * + * Revision 8.0.6 (pi) * + * DRC rule 2.2 add allNOhmic to allNOhmic and allPOhmic to * + * allPOhmic rule. Thank goes to Shih-Lien Lu. * + * (sllu@caleb.ECE.ORST.EDU) * + * 6/28/94 pi@isi.edu * + * Revision 8.0.5 (pi) * + * DRC rule 3.5 reverse back to old style to avoid a mischeck on * + * corners. Thank goes to Wen-King Su. * + * (wen-king@vlsi.cs.caltech.edu) * + * 4/20/94 pi@isi.edu * + * Revision 8.0.4 (pi) * + * SCPE20(ORB) extraction P-well sheet resistance fixed. Thank * + * goes to Nagendra Shivakumar (nshivaku@phyast.nhn.uoknor.edu). * + * 3/04/94 pi@isi.edu * + * Revision 8.0.3 (pi) * + * Wellcap drawing problem fixed. Thank goes to Mario Aranha * + * (mario@cad4.lbl.gov). * + * 2/03/94 pi@isi.edu * + * Revision 8.0.2 (pi) * + * CIF read fix for linear capacitor. Thank goes to Issy Kipnis * + * (kipnis@cad4.lbl.gov). * + * 2/03/94 pi@isi.edu * + * Revision 8.0.1 (pi) * + * DRC updates for separate diffusion width check. Thank goes to * + * John Poulton (jp@cs.unc.edu). * + * 10/04/93 pi@isi.edu * + * Revision 8.0.0 (pi) * + * DRC revision 8 installed and layer support for High-Voltage * + * MOSFETs for SCNA16 process. * + * 10/04/93 pi@isi.edu * + * Revision 7.4.0 (pi) * + * Brand new extraction section and other fixes :-) * + * 10/01/93 pi@isi.edu * + * Revision 7.3.3 (pi) * + * pbc surrounding rule fixed. 4.1.c fixed also * + * 6/01/93 pi@isi.edu * + * Revision 7.3.2 (pi) * + * exchnage CCD and CBA calma (GDS) number to the correct setting * + * 4/27/93 pi@isi.edu * + * Revision 7.3.1 (pi) * + * Various DRC rule changes contributed by Barry Boes at AuE * + * (boes@corona.AuE.com). * + * allNDiff/allPOhmic in connection section update, thanks go to * + * Brian Kingsbury from Bekerley (bedk@icsi.berkeley.edu). * + * 3/30/93 pi@isi.edu * + * Revision 7.3.0 (pi) * + * add three new layers intended for ESD preotection devices * + * remove the temporary "pad2" layer, now all pads use "pad" * + * CIFin and CIFout now in templates, thank goes to Shih-Lien Lu * + * at Origon State Univ. sllu@caleb.ECE.ORST.EDU. * + * Some design rule changes (relabeling for doc)... * + * 3/19/93 pi@isi.edu * + * Revision 7.2.2 (pi) * + * change all "bloat-min" select generation back to "bloat-or" * + * restore all lambda=0.8 style since some people use ORBIT's run * + * though MOSIS does NOT provide HP's process anymore * + * 3/09/93 pi@isi.edu * + * Revision 7.2.1 (pi) * + * add missing Cifinput "pbase" layer for lambda=1.0(oldnwell) * + * style. Thank goes to Brian Von Herzen at Synaptics, Inc. * + * 2/18/93 pi@isi.edu * + * Revision 7.2.0 (pi) * + * A serious bug in CIF well generation is fixed... * + * 1/14/93 pi@isi.edu * + * Revision 7.1.4 (pi) * + * Remove lambda=1.5 and lambda=0.8 technology which are not * + * provided by MOSIS any more. * + * 1/12/93 pi@isi.edu * + * Revision 7.1.3 (pi) * + * Add pstop layer and the corresponding CIFin CIFout stuff * + * Reverse the last change about CCA layer under pad for CMOS26B * + * 1/08/93 pi@isi.edu * + * Revision 7.1.2 (pi) * + * Various problem fix... and make the "open" layer as an option * + * Reverse the last change about CCA layer under pad for CMOS26B * + * 12/29/92 pi@isi.edu * + * Revision 7.1.1 (pi) * + * A series bug fix for HP's CMOS26B pad layers - remove CCA CIF * + * layer. Thank goes to ndu@aue.com * + * 12/12/92 pi@isi.edu * + * Revision 7.1.0 (pi) * + * A new layer "open" for micromachined device fabracation. * + * Thanks goes to Janet Marchall from NIST. * + * (marshall@sed.eeel.nist.gov) * + * 12/15/92 pi@isi.edu * + * Revision 7.0.4 (pi) * + * C-preprocessing fix. Thanks goes to Jeffrey C. Gealow form * + * MIT (jgealow@mtl.mit.edu). * + * 10/20/92 pi@isi.edu * + * Revision 7.0.3 (pi) * + * Colorversatec support. Thanks got to Jeffrey C. Gealow form * + * MIT (jgealow@mtl.mit.edu). * + * 10/8/92 pi@isi.edu * + * Revision 7.0.2 (pi) * + * Separate 'spacing allWell...' rule into two rules to avoid * + * well adjacency problem... * + * 10/2/92 pi@isi.edu * + * Revision 7.0.1 (pi) * + * CIFoutput for "pad2" layer, CCA contact fix, CIFinput for HP's * + * 1.0 um process... * + * 9/28/92 pi@isi.edu * + * Revision 7.0 (pi) * + * Major revision which includes * + * HP's cap_well and well-capacitance, NPN & BCCD DRC rules... * + * 9/22/92 pi@isi.edu * + * Revision 6.2.0 (pi) * + * Merging 'scmos26.tech' into scmos.tech * + * 9/7/92 pi@isi.edu * + * Revision 6.1.4 (pi) * + * Select CIF layers generation is revised based on Brian * + * Kingsbury's (bedk@icsi.berkeley.edu) notice of inconsistency * + * 9/4/92 pi@isi.edu * + * Revision 6.1.3 (pi) * + * Install MITRE's (Mike Butler) fix for CIFinput "cap" layer and * + * poly1/poly2 crossing in DRC section * + * 9/3/92 pi@isi.edu * + * Revision 6.1.2 (pi) * + * Fixed metal2 contact on falt surface bug for poly2 layer * + * 8/3/92 pi@lepton.isi.edu * + * Revision 6.1.1 (pi) * + * fixed CIFoutput CSP layer bug for lambda=0.8(gen) technology * + * 4/13/92 pi@lepton.isi.edu * + * Revision 6.1.0 (pi) * + * add implant plane for Buried CCD devices * + * both cifin and cifoutput are changed correspondingly * + * Revision 6.0.2 (pi) * + * remove bug for nbdc not generate CMF in cifoutput section * + * Revision 6.0.1 (sllu) * + * added CX for collector layer * + * Revised for Magic Version 6. * + * Revision 6.0 90/05/11 20:12:34 pi * + * include color versatech support * + * eliminated active2 plane * + * (rule version # 5.01 (S. Lu) = rule 5.0 + mod. for cc spacing * + * (rule version # 5.0 (Shih-Lien Lu sllu@MOSIS.EDU) 8/15/89) * + * (rule 5.0 = rule 4.01 + new layers for analog process * + * (rule 4.01 = rule 4.0 + comments + cifout style lambda=0.8(pwell) * + * (correction made by L. McMurchie of UW) * + * (rule 4.0 = rule 3.1 + new layer : electrode) * + * (rule 3.1 = rule 3.0 + new cifout method for select layers ) * + * (design can be more compact now with this version ) * + * (layout should be upward compatible:: you old layout will not) * + * (flag any drc violations) * + * (rule 3.0 = rule 2.0 + rev #6 + new cifin section for new nwell) * + * * + * (rule version # 2.0 10/28/87) * + * (rule 2.0 = rule 1.9 + modification to extract section * + * (rule 1.9 = rule 1.82 + additions of two more CIF in/output styles * + * (rule 1.82 = rule 1.81+ modification of drc #4.1 & cifoutput of * + * wells * + * (rule 1.81 = rule 1.8 + modification on line 1761 * + * (rule 1.8 = rule 1.7 + Rev 5 of the SCMOS rules) * + * (difference from rule 1.7: * + * (1) well width = 9 lambda * + * (2) N well process accepts both N and P selects * + * ------------------------------------------------------------------- */ + +/* Definition for actives */ +/* NOTE: Some version of cpp may have problem with two consective tabs + * or even two consective space... So we put only single space + * here... */ +#define allNDiff ndiff,ndc/a +#define allPDiff pdiff,pdc/a +#define allNActive ndiff,ndc/a,nfet,enfet,nffet,wcap +#define allPActive pdiff,pdc/a,pfet,epfet,pffet +#define allNOhmic nsd,nsc/a +#define allPOhmic psd,psc/a +#define allOhmic allNOhmic,allPOhmic +#define allBiNDiff emit,emc/a,col,clc/a +#define allBiPDiff pbase,pbc/a +#define allBiDiff allBiNDiff,allBiPDiff +#define allCCDiff bd,nbd,nbdc/a +#define allDiff allNDiff,allPDiff +#define allActive allNActive,allPActive,allOhmic +#define PNplus ndiff,pdiff,ndc/a,pdc/a +#define allHVNDiff hndiff,hndc/a +#define allHVPDiff hpdiff,hpdc/a +#define allHVNOhmic hnsd,hnsc/a +#define allHVPOhmic hpsd,hpsc/a +#define allHVDiff allHVNDiff,allHVPDiff +#define allHVOhmic allHVNOhmic,allHVPOhmic + +/* first poly without those overlapped with the second */ +#define allP poly,pc/a +#define allP1 poly,pc/a,nfet,pfet,wcap +/* all first poly */ +#define allPoly allP1,cap,capc/a,nffet,pffet +/* second poly without those overlapped with the first */ +#define allP2 poly2,ec/a,enfet,epfet +/* all second poly */ +#define allPoly2 allP2,cap,capc/a,nffet,pffet,hnfet,hpfet + +/* MOSFETs */ +#define NFet nfet,enfet,nffet +#define PFet pfet,epfet,pffet +#define allFet NFet,PFet + +/* Definitions for contacts */ +#define DiffCut pdc,ndc,psc,nsc +#define HVDiffCut hpdc,hndc,hpsc,hnsc +#define PolyCut pc +#define CapCut ec,capc +#define BiCut clc,emc,pbc +#define allCut DiffCut,HVDiffCut,PolyCut,CapCut,nbdc + +/* Definitions for metals */ +#define DiffMetal pdc/m1,ndc/m1,psc/m1,nsc/m1 +#define HVDiffMetal hpdc/m1,hndc/m1,hpsc/m1,hnsc/m1 +#define PolyMetal pc/m1,ec/m1,capc/m1 +#define BiMetal clc/m1,emc/m1,pbc/m1 +#define CCDMetal nbdc/m1 +#define allMetal1 DiffMetal,HVDiffMetal,PolyMetal,BiMetal,CCDMetal,m1,m2c/m1,gc +#define allMetal2 m2,m2c/m2,m3c/m2,pad +#define allMetal3 m3,m3c/m3 + +/* All types containing metal, on their respective home planes */ +#define homeMetal1 allCut,m1,m2c,gc + +/* Definitions for wells */ +#define allWell nwell,pwell +#define allNwell nwell,nsc,nsd +#define allPwell pwell,psc,psd +#define allHVNwell hnwell,hnsc,hnsd +#define allHVPwell hpwell,hpsc,hpsd + + +tech + format 28 + scmos +end + +#if V4 || V5 +version + version 8.2.8 +#ifdef SUBMICRON + description "MOSIS Scalable CMOS Technology for HP CMOS26G and CMOS14B processes" +#else /* TIGHTMETAL */ +#ifdef IBMTECH + description "MOSIS Scalable CMOS Technology for IBM" +#else /* IBMTECH */ +#ifdef HPTECH + description "MOSIS Scalable CMOS Technology for Tight Metal Rules" +#else +#ifndef WELL_ROUTE_CHECK + description "MOSIS Scalable CMOS Technology for Standard Rules" +#else + description "MOSIS Scalable CMOS Technology for Standard Rules (No routing through wells)" +#endif +#endif /* HPTECH */ +#endif /* IBMTECH */ +#endif /* TIGHTMETAL */ +end +#endif /* V4 */ + +planes + well,w + implant,i + active,a + metal1,m1 + metal2,m2 +#ifdef STACKVIA + v2oxide,v2x +#endif + metal3,m3 + oxide,ox +end + + +types + /* primary layers -16 */ + + well pwell,pw + well nwell,nw + well capwell,cwell,cw + well highvoltnwell,hvnwell,hnwell,hnw + well highvoltpwell,hvpwell,hpwell,hpw + active polysilicon,red,poly,p + active electrode,poly2,el,p2 + active capacitor,polycap,pcap,cap + active wellcapacitor,wellcap,wcap + active ndiffusion,ndiff,green + active pdiffusion,pdiff,brown + active highvoltndiffusion,hvndiff,hndiff + active highvoltpdiffusion,hvpdiff,hpdiff + metal1 metal1,m1,blue + metal2 metal2,m2,purple + metal3 metal3,m3,cyan + + /* MOSFETs -8 */ + + active ntransistor,nfet + active ptransistor,pfet + active entransistor,enfet + active eptransistor,epfet + active doublentransistor,nfloating-gate,nfloatg,nfg,nffet + active doubleptransistor,pfloating-gate,pfloatg,pfg,pffet + active highvoltntransistor,hvnfet,hnfet + active highvoltptransistor,hvpfet,hpfet + + /* NPN transistor layers -3 */ + + active collector,coll,col,co,cl + active emitter,emit,em + active pbase,pb + + /* layers for BCCD devices -2 */ + + implant bccdiffusion,bd + active nbccdiffusion,nbd + + /* Contacts between interconnection layers -13 */ + + active polycontact,pcontact,polycut,pc + active ndcontact,ndiffcut,ndc + active pdcontact,pdiffcut,pdc + active highvoltndcontact,hndiffcut,hndc + active highvoltpdcontact,hpdiffcut,hpdc + active capcontact,ccontact,capc,cc + active electrodecontact,econtact,ec,poly2contact,p2c + active collectorcontact,colcontact,colc,coc,clc + active emittercontact,emitcontact,emc + active pbasecontact,pbcontact,pbc + active nbccdiffcontact,nbdc + metal1 m2contact,m2cut,m2c,via,v +#ifdef STACKVIA + v2x m3contact,m3cut,m3c,via2,v2 +#else + metal2 m3contact,m3cut,m3c,via2,v2 +#endif + + /* Well contacts -8 */ + /* pohmic and nohmic are included for compatibility */ + /* nwc, pwc, etc ... are included for compatibility */ + + active psubstratepcontact,ppcontact,ppc,pwcontact,pwc,psc + active nsubstratencontact,nncontact,nnc,nwcontact,nwc,nsc + active psubstratepdiff,ppdiff,pohmic,ppd,psd + active nsubstratendiff,nndiff,nohmic,nnd,nsd + + active highvoltpsubcontact,hpwcontact,hpsc + active highvoltnsubcontact,hnwcontact,hnsc + active highvoltpsubdiff,hpohmic,hpsd + active highvoltnsubdiff,hnohmic,hnsd + + /* Special tiles needed for ESD protection design -3 */ + active nplusdoping,ndoping,ndop + active pplusdoping,pdoping,pdop + metal1 genericcontact,gcontact,gc + + /* Special tiles needed for micromachine fab. in CMOS -2 */ + oxide substrateopen,subopen,open + oxide pdiffusionstop,pdiffstop,pstop + + /* Additional stuff, used in pads. -2 */ + + metal2 pad + oxide glass +end + +contact + /* polys */ + ec poly2 metal1 + cc cap metal1 + pc poly metal1 + /* active contacts */ + ndc ndiff metal1 + pdc pdiff metal1 + nsc nsd metal1 + psc psd metal1 + hndc hndiff metal1 + hpdc hpdiff metal1 + hnsc hnsd metal1 + hpsc hpsd metal1 + /* bipolar contacts */ + clc col metal1 + emc emit metal1 + pbc pbase metal1 + /* BCCD contact */ + nbdc nbd metal1 + /* vias */ + m2c metal1 metal2 +#ifdef STACKVIA + m3c metal2 m3c metal3 +#else + m3c metal2 metal3 +#endif +/* + pad metal1 metal2 metal3 + */ + +end + +styles + styletype mos + + /* wells */ + cwell 10 + nwell 12 + pwell 13 + hnwell 18 + hpwell 11 + /* poly */ + poly 1 + poly2 14 + /* diffusions */ + ndiff 2 + pdiff 4 + psd 5 + nsd 3 + hndiff 2 + hndiff 11 + hpdiff 4 + hpdiff 18 + hpsd 5 + hpsd 11 + hnsd 3 + hnsd 18 + ndop 2 + ndop 38 + pdop 4 + pdop 38 + /* transistors */ + nfet 6 + nfet 7 + pfet 8 + pfet 9 + + enfet 6 + enfet 30 +/* enfet 14 */ + epfet 8 + epfet 31 +/* epfet 14 */ + + nffet 6 + nffet 7 +/* nffet 14 */ + nffet 30 + pffet 8 + pffet 9 +/* pffet 14 */ + pffet 31 + + hnfet 6 + hnfet 7 + hnfet 30 + + hpfet 8 + hpfet 9 + hpfet 31 + /* base */ + pbase 15 + pbc 15 + pbc 20 + pbc 32 + /* emitter */ + emit 16 + emc 16 + emc 20 + emc 32 + /* collector */ + col 3 + clc 3 + clc 20 + clc 32 + /* capacitors */ + cap 1 + cap 14 + wcap 6 + wcap 10 + cc 1 + cc 14 + cc 20 + cc 32 + /* metals */ + metal1 20 + metal2 21 + metal3 22 + /* generic contact */ + gc 19 + /* poly contacts */ + pcontact 26 + pcontact 32 + ec 14 + ec 20 + ec 32 + /* diffusion contacts */ + ndc 2 + ndc 20 + ndc 32 + pdc 4 + pdc 20 + pdc 32 + psc 5 + psc 20 + psc 32 + nsc 3 + nsc 20 + nsc 32 + /* high-voltage diffusion contacts */ + hndc 2 + hndc 20 + hndc 32 + hndc 11 + hpdc 4 + hpdc 20 + hpdc 32 + hpdc 18 + hpsc 5 + hpsc 20 + hpsc 32 + hpsc 11 + hnsc 3 + hnsc 20 + hnsc 32 + hnsc 18 + /* vias */ + m2contact 20 + m2contact 21 + m2contact 33 + m3contact 21 + m3contact 22 + m3contact 37 + /* pads and overglass */ + pad 20 + pad 21 + pad 33 + pad 34 + glass 34 + /* CCDs */ + bd 17 + nbd 17 + nbd 3 + nbdc 3 + nbdc 17 + nbdc 20 + nbdc 32 + /* MEMs */ + open 2 + open 20 + pstop 8 + /* System */ + error_p 42 + error_s 42 + error_ps 42 +end + +compose + /* MOSFET combination rules */ + compose nfet poly hndiff + compose pfet poly hpdiff + compose nfet poly ndiff + compose pfet poly pdiff + compose hnfet poly2 hndiff + compose hpfet poly2 hpdiff + compose enfet poly2 ndiff + compose epfet poly2 pdiff + compose nffet nfet poly2 + compose pffet pfet poly2 + compose nffet enfet poly + compose pffet epfet poly + compose cap poly poly2 + /* Transistor combination rules */ + paint clc col clc + paint emc emit emc + paint emc pbase emc + /* Poly2 capacitor combination rules */ + paint poly2 poly cap + paint poly poly2 cap + paint poly cap cap + paint poly2 cap cap + paint cap poly cap + paint cap poly2 cap +/* ILLEGAL declaration by 7.3 standards */ +/* paint poly ec cc */ + paint ec poly cc + /* These rules allow nwell to be painted over an area to + * flip all the p-well types to n-well types. Pwell can be + * painted to flip in the reverse. */ + paint pdc pwell ndc + paint pfet pwell nfet + paint epfet pwell enfet + paint pffet pwell nffet + paint pdiff pwell ndiff + paint nsd pwell psd + paint nsc pwell psc + paint ndc nwell pdc + paint nfet nwell pfet + paint enfet nwell epfet + paint nffet nwell pffet + paint ndiff nwell pdiff + paint psd nwell nsd + paint psc nwell nsc + + paint pdc hpwell hndc + paint epfet hpwell hnfet + paint pffet hpwell hnfet + paint pdiff hpwell hndiff + paint nsd hpwell hpsd + paint nsc hpwell hpsc + paint ndc hnwell hpdc + paint enfet hnwell hpfet + paint nffet hnwell hpfet + paint ndiff hnwell hpdiff + paint psd hnwell hnsd + paint psc hnwell hnsc + /* BCCD layers combination rules */ +/* paint bd ndiff 0 implant */ +/* + erase nbd bd ndiff + erase nbd ndiff bd + erase nbdc/a bd ndc/a +*/ + /* Well capacitor combination rules */ + paint nfet cwell wcap + paint poly wcap wcap + paint ndiff wcap wcap + paint wcap poly wcap + paint wcap ndiff wcap + erase wcap poly ndiff + erase wcap ndiff poly + erase wcap cwell nfet + paint cwell nfet wcap active + erase wcap nfet cwell well + + /* Generic contact */ + paint gc m1 gc + + /* For pads */ + paint pad m1 pad + paint pad m2 pad + paint pad m3 pad + paint pad m2c pad + + /* These rules allow nwell to be painted over an area to + * flip all the p-well types to n-well types. Pwell can be + * painted to flip in the reverse. */ + paint hpdc hpwell hndc + paint hpfet hpwell hnfet + paint hpdiff hpwell hndiff + paint hnsd hpwell hpsd + paint hnsc hpwell hpsc + paint hndc hnwell hpdc + paint hnfet hnwell hpfet + paint hndiff hnwell hpdiff + paint hpsd hnwell hnsd + paint hpsc hnwell hnsc + + paint hpdc pwell ndc + paint hpfet pwell enfet + paint hpdiff pwell ndiff + paint hnsd pwell psd + paint hnsc pwell psc + paint hndc nwell pdc + paint hnfet nwell epfet + paint hndiff nwell pdiff + paint hpsd nwell nsd + paint hpsc nwell nsc + +end + +connect +#ifndef WELL_ROUTE_CHECK +/* This creates a tech file where the wells are not connected therefore + enabling extractions to check whether the wells are used accidentaly + to route signals or power. To check for these cases you have to compare + the netlists generated with the normal tech file with those generated + with the special one (eg. using gemini). +*/ + allNwell allNwell + allPwell allPwell +#endif + allHVNwell allHVNwell + allHVPwell allHVPwell + /* for capacitor-well */ + allNDiff cwell + /* for all metals */ + allMetal1 allMetal1 + allMetal2 allMetal2 + allMetal3 allMetal3 + /* for all polys */ + allP1 allP1 + allPoly2 allPoly2 + /* for all diffusions/well plugs */ + /* Ndiffusion and Ohmic wells dont connect !! */ + /* you get a diode instead */ + allNDiff,ndop allPOhmic,pdop,pstop + allPDiff,pdop,pstop allNOhmic,ndop + allHVNDiff,ndop allHVPOhmic,pdop,pstop + allHVPDiff,pdop,pstop allHVNOhmic,ndop + ndiff ndc + pdiff pdc + hndiff hndc + hpdiff hpdc + /* for BCCD device */ + nbd nbdc + /* for NPN transistor */ + pbase pbc + collector clc,nwell + emitter emc + /* for new generic contact */ + gc allActive,allOhmic,allHVDiff,metal1 + gc allP1 + gc allPoly2 + /* for pad */ + pad allMetal1 + pad allMetal2 + pad allMetal3 + +end + +/* WARNING ::::: automatic generation of wells does not guarantee */ +/* rules on width and spacing of wells are followed !! */ +/* It is strongly recommanded that designers layout their own wells */ + +/* PWELL styles cannot generate CBA and CCD correctly */ +/* BOTH NWELL and GEN can do CCD and CBA */ +/* ONLY GEN can be used for micro-machining fabrication */ + +cifoutput +/* default: fab on 2.0 micron (Nwell) rules each magic unit is 100 */ +/* centimicrons */ +/* SCN technology : Both CSN and CSP are generated to reduce field */ +/* poly sheet resistance */ + +#ifdef STANDARD +#include "cif_template/objs/CIFout" +#endif /* STANDARD */ + +#ifdef TIGHTMETAL +#include "cif_template/objs/TMCIFout" +#endif /* TIGHTMETAL */ + +#ifdef SUBMICRON +#include "cif_template/objs/SUBCIFout" +#endif /* SUBMICRON */ + +#ifdef IBMTECH +#include "cif_template/objs/IBMCIFout" +#endif /* IBMTECH */ + +style plot /* pplot output style */ + scalefactor 100 50 + layer CM2 m2,m2c/m2,pad/m2 + labels m2 + layer CM1 pad + grow 100 + or m1,m2c/m1,pc/m1,ndc/m1,pdc/m1,ppcont/m1,nncont/m1 + labels m1,m2c/m1,pc/m1,ndc/m1,pdc/m1,ppcont/m1,nncont/m1,pad/m1 + layer CP poly,pc/active,nfet,pfet + labels poly,nfet,pfet + layer CND ndiff,ndc,nfet,pwc,psd + labels ndiff + layer CPD pdiff,pdc,pfet,nwc,nsd + labels pdiff + layer CNP + bloat-or nsd,nwc * 150 ndiff,pdiff,ndc/active,pdc/active,ppcont/active,nncont/active,pfet,nfet,psd,nsd 0 + layer CPP + bloat-or psd,pwc * 150 ndiff,pdiff,ndc/active,pdc/active,ppcont/active,nncont/active,pfet,nfet,psd,nsd 0 + layer CV m2c + squares 100 200 300 + layer CC ndc,pdc,pc,pwc,nwc + squares 200 + layer CNW nwell + grow 400 + shrink 400 + layer CG pad + shrink 600 + or glass + labels glass + + +end + +/* -------------------------------------------------------------------- * + * In the CIFinput section, the order of layer specifications is very * + * important. Each layer overrides any of the previous layers. There * + * are places where one layer is generated over an area that is too * + * large, but with the knowledge that later layers will "take over" * + * the extraneous area, leaving the first layer only where it belongs. * + * This happens for various flavors of diffusion, for example. * + * Note: when reading in CMOS, wells are created in the Magic files. * + * They can be eliminated manually if desired. * + * ---------------------------------------------------------------------*/ +cifinput + +#ifdef STANDARD +#include "cif_template/objs/CIFin" +#endif /* STANDARD */ + +#ifdef TIGHTMETAL +#include "cif_template/objs/TMCIFin" +#endif /* TIGHTMETAL */ + +#ifdef SUBMICRON +#include "cif_template/objs/SUBCIFin" +#endif /* SUBMICRON */ + +#ifdef IBMTECH +#include "cif_template/objs/IBMCIFin" +#endif /* IBMTECH */ + +end + +mzrouter + style irouter + layer m2 32 64 256 1 + layer m1 64 32 256 1 + layer poly 128 128 512 1 + contact m2contact metal1 metal2 1024 + contact pcontact metal1 poly 2056 + notactive poly pcontact + style garouter + layer m2 32 64 256 1 + layer m1 64 32 256 1 + contact m2contact metal1 metal2 1024 +end + + +/* SCMOS rules revision 7 */ +drc +/* ---------------------------------------------------------------- */ +/* Well */ +/* ---------------------------------------------------------------- */ + +/* 1.1 */ +/* Now use "edge" for width DRC... A test only for rule1 */ +/* Other rules may follow in the near future... */ +#ifdef SUBMICRON + edge4way (~nwell)/w nwell 12 nwell nwell 12\\ + "N-Well width must be at least 12 (MOSIS rule #1.1)" + edge4way (~pwell)/w pwell 12 pwell pwell 12\\ + "P-Well width must be at least 12 (MOSIS rule #1.1)" +#else + edge4way (~nwell)/w nwell 10 nwell nwell 10\\ + "N-Well width must be at least 10 (MOSIS rule #1.1)" + edge4way (~pwell)/w pwell 10 pwell pwell 10\\ + "P-Well width must be at least 10 (MOSIS rule #1.1)" +#endif + +/* original "width" rule which use 'width'command: + width allWell 10 \\ + "Well width must be at least 10 (MOSIS rule #1.1)" + */ + +/* 1.2 */ +/* Now use "edge4way" for spacing DRC... A test only for rule1 */ +/* Other rules may follow in the near future... */ +#ifdef SUBMICRON + edge4way nwell ~(nwell)/w 18 (~nwell)/w (~nwell)/w 18\\ + "N-Well spacing must be at least 18 (MOSIS rule #1.2)" + edge4way pwell (~pwell)/w 18 (~pwell)/w (~pwell)/w 18\\ + "P-Well spacing must be at least 18 (MOSIS rule #1.2)" +#else + edge4way nwell (~nwell)/w 9 (~nwell)/w (~nwell)/w 9\\ + "N-Well spacing must be at least 9 (MOSIS rule #1.2)" + edge4way pwell (~pwell)/w 9 (~pwell)/w (~pwell)/w 9\\ + "P-Well spacing must be at least 9 (MOSIS rule #1.2)" +#endif + +/* original spacing rule which use 'spacing' command: + spacing allWell allWell 9 touching_ok \\ + "Well spacing must be at least 9 (MOSIS rule #1.2)" + */ + +/* NOTE: rule 1.2 is equivalent to the following three rules where + the third is a new one. This rule is added to force designers + to be cautious about the wells... + + spacing nwell nwell 9 touching_ok \\ + "N-well spacing must be at least 9 (MOSIS rule #1.2)" + spacing pwell pwell 9 touching_ok \\ + "P-well spacing must be at least 9 (MOSIS rule #1.2)" + spacing nwell pwell 9 touching_ok \\ + "Well spacing must be at least 9 (MOSIS rule #1.2)" +*/ + +/* 1.3 is not checked */ +/* NOTE: for digital ckts where wells are not explicitly put, * + * auto-generation may not ensure the minimul spacing and width * + * rule: this happens usually when two geometries are in diagonal * + * positions. * + * NOTE: when both pwell and nwell are submitted they cannot * + * overlap this is assured with the compose section - painting one * + * well over another will erase the original well. */ + +/* ---------------------------------------------------------------- */ +/* Active */ +/* ---------------------------------------------------------------- */ + +/* 2.1 */ +/* Test active width separately... */ + width allNActive 3 \\ + "N-type Diffusion width must be at least 3 (MOSIS rule #2.1a)" + width allPActive 3 \\ + "P-type Diffusion width must be at least 3 (MOSIS rule #2.1b)" + width allOhmic 3 \\ + "Ohmic diffusion width must be at least 3 (MOSIS rule #2.1c)" + +/* 2.2 */ + spacing allNActive allNActive 3 touching_ok \\ + "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" + spacing allPActive allPActive 3 touching_ok \\ + "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" + spacing allNOhmic allNOhmic 3 touching_ok \\ + "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" + spacing allPOhmic allPOhmic 3 touching_ok \\ + "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" + +/* 2.3 without explicit well definition: 6+6 and 5+5 respectively */ +#ifdef SUBMICRON + spacing allNDiff allPDiff 12 touching_illegal \\ + "P-type diffusion must be 12 away from N-type diffusion (MOSIS rule #2.3b)" +#else + spacing allNDiff allPDiff 10 touching_illegal \\ + "P-type diffusion must be 10 away from N-type diffusion (MOSIS rule #2.3a)" +#endif + +/* 2.3 + 2.4 without explicit well definition: 6+3 and 5+3 respectively */ +#ifdef SUBMICRON + spacing allNDiff allNOhmic 9 touching_illegal \\ + "N-type diffusion must be 9 away from N-substrate contact (MOSIS rule #2.3b,4b)" + spacing allPDiff allPOhmic 9 touching_illegal \\ + "P-type diffusion must be 9 away from P-substrate contact (MOSIS rule #2.3b,4b)" +#else + spacing allNDiff allNOhmic 8 touching_illegal \\ + "N-type diffusion must be 8 away from N-substrate contact (MOSIS rule #2.3a,4a)" + spacing allPDiff allPOhmic 8 touching_illegal \\ + "P-type diffusion must be 8 away from P-substrate contact (MOSIS rule #2.3a,4a)" +#endif + +/* 2.4 3 + 3 */ + spacing allNOhmic allPOhmic 6 touching_illegal \\ + "Opposite well contacts must be separated by 6 (MOSIS rule #2.4)" + +/* 2.3 with explicit well: 6 and 5 respectively */ +#ifdef SUBMICRON + spacing allNActive nwell 6 touching_illegal \\ + "N-diffusion and N-well must be separated by 6 (MOSIS rule #2.3b)" + spacing allPActive pwell 6 touching_illegal \\ + "P-diffusion and P-well must be separated by 6 (MOSIS rule #2.3b)" +#else + spacing allNActive nwell 5 touching_illegal \\ + "N-diffusion and N-well must be separated by 5 (MOSIS rule #2.3a)" + spacing allPActive pwell 5 touching_illegal \\ + "P-diffusion and P-well must be separated by 5 (MOSIS rule #2.3a)" +#endif + +/* 2.4 with explicit well */ + spacing allNOhmic pwell 3 touching_illegal \\ + "N-substrate diffusion and P-well must be separated by 3 (MOSIS rule #2.4)" + spacing allPOhmic nwell 3 touching_illegal \\ + "P-substrate diffusion and N-well must be separated by 3 (MOSIS rule #2.4)" + +/* MOSIS extension rule for diffusion and substrate contact of */ +/* opposite type. We could do without this rule, but it is now */ +/* added for safety reason. */ + spacing allNActive allPOhmic 4 touching_ok \\ + "Opposite diffusion spacing must be at least 4 (MOSIS extension rule)" + spacing allPActive allNOhmic 4 touching_ok \\ + "Opposite diffusion spacing must be at least 4 (MOSIS extension rule)" + +/* ---------------------------------------------------------------- */ +/* Poly */ +/* ---------------------------------------------------------------- */ + +/* 3.1 */ + width allPoly 2 \\ + "Polysilicon width must be at least 2 (MOSIS rule #3.1)" + +/* 3.2 */ +#ifdef SUBMICRON + spacing allPoly allPoly 3 touching_ok \\ + "Polysilicon spacing must be at least 3 (MOSIS rule #3.2b)" +#else + spacing allPoly allPoly 2 touching_ok \\ + "Polysilicon spacing must be at least 2 (MOSIS rule #3.2a)" +#endif + +/* 3.3 */ + edge4way nfet,pfet poly,pc/act 2 poly,pc/act 0 0 \\ + "Poly must overhang transistor by at least 2 (MOSIS rule #3.3)" + +/* 3.4 */ + edge4way nfet,enfet ndiff,ndc/a 3 allNActive ndiff,ndc/a 3 \\ + "Diffusion must overhang transistor by at least 3 (MOSIS rule #3.4)" + edge4way pfet,epfet pdiff,pdc/a 3 allPActive ndiff,ndc/a 3 \\ + "Diffusion must overhang transistor by at least 3 (MOSIS rule #3.4)" + +/* 3.3 + 3.4 */ + edge4way nfet,pfet space 1 poly 0 0 \\ + "Transistor overhang is missing (MOSIS rule #3.3,4)" + edge4way enfet,epfet space 1 poly2 0 0 \\ + "Transistor overhang is missing (MOSIS rule #3.3,4)" + edge4way nffet,pffet space 1 poly 0 0 \\ + "Transistor overhang is missing (MOSIS rule #3.3,4)" + edge4way nffet,pffet space 1 poly2 0 0 \\ + "Transistor overhang is missing (MOSIS rule #3.3,4)" + +/* 3.5 */ + edge4way allDiff,allOhmic poly,pc 1 space/a 0 1 \\ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" + edge4way poly,pc allDiff,allOhmic 1 space/a 0 1 \\ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" + edge poly,pc space/a 1 space/a space/a 1 \\ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" + edge allOhmic,allDiff space/a 1 space/a space/a 1 \\ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" +/* + These following checks will miss the corner, so we add something above + + edge4way allDiff,allOhmic poly,pc 1 space space 1 \\ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5.a)" + spacing allDiff,allOhmic poly,pc 1 touching_illegal \\ + "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5.b)" + */ + +/* Extra transistor rules */ +/* These rules is really NOT necessary because others have already + taken care of it. It is here for future reference... + + edge4way poly,pc/act pfet 3 pfet 0 0 \\ + "Transistors must be at least 3 units wide (MOSIS rule #2)" + edge4way poly,pc/act nfet 3 nfet 0 0 \\ + "Transistors must be at least 3 units wide (MOSIS rule #2)" +*/ + +/* ---------------------------------------------------------------- */ +/* Select */ +/* ---------------------------------------------------------------- */ +/* 4.1 */ + spacing PFet allNOhmic 3 touching_illegal \\ + "Transistors must be separated from substrate contacts by 3 (MOSIS rule #4.1.a)" + spacing NFet allPOhmic 3 touching_illegal \\ + "Transistors must be separated from substrate contacts by 3 (MOSIS rule #4.1.b)" + + edge4way allPOhmic space/act 3 ~(NFet)/act allPOhmic,allNDiff 3 \\ + "Transistors must be separated from selects(generated by well cont) by 3 (MOSIS rule #4.1.c)" + + edge4way allNOhmic space/act 3 ~(PFet)/act allNOhmic,allPDiff 3 \\ + "Transistors must be separated from selects(generated by well cont) by 3 (MOSIS rule #4.1.d)" + + edge4way allPOhmic ~(ndiff,ndc,psc,psd)/act 4 ~(nfet,enfet)/act ~(ndiff,ndc,psc,psd)/act 4 \\ + "Transistors must be separated from selects(generated by well cont) by 4 (MOSIS rule #4.1.e)" + + edge4way allNOhmic ~(pdiff,pdc,nsc,nsd)/act 4 ~(pfet,epfet)/act ~(pdiff,pdc,nsc,nsd)/act 4 \\ + "Transistors must be separated from selects(generated by well cont) by 4 (MOSIS rule #4.1.f)" + +/* 4.2 */ +/* This one is very difficult.... Most likely done by CIF output */ + edge4way ~(allPActive)/act pdiff,pdc,pfet 4 ~(allNOhmic)/act allPActive 2 \\ + "Backedge of diffusion must be 4 from substrate diff (MOSIS rule #4.2.a)" + edge4way ~(allNActive)/act ndiff,ndc,nfet 4 ~(allPOhmic)/act allNActive 2 \\ + "Backedge of diffusion must be 4 from substrate diff (MOSIS rule #4.2.b)" + +/* 4.3 -- guaranteed automatically by CIF generator. */ +/* 4.4 -- guaranteed automatically by CIF generator except diag. where + this rule is not crucial */ + + +/* ---------------------------------------------------------------- */ +/* Contact to Poly */ +/* ---------------------------------------------------------------- */ + +/* 5B.1 + 5B.2 + 5B.3 */ + width pc 4 \\ + "Poly contact width must be at least 4 (MOSIS rule #5B.1,2,3)" + +/* 5B.4 is guaranteed by 5B.1,2,3 with rule 7.2 (metal1 spacing) */ + +/* 5B.5 -- + * Watch out here: a spacing "touching_ok" rule CANNOT be used here: + * it will miss certain checks. + */ + edge4way allPoly ~(allPoly)/act 3 ~pc/act ~(allPoly)/act 3 \\ + "Poly contact must be at least 3 from other poly (MOSIS rule #5B.4,5)" + +/* 5B.6 -- + * This is mostly handled by 3.5 already, but need rule here to handle + * case of pc abutting transistor. + */ + spacing pc allActive 1 touching_illegal \\ + "Poly contact must be 1 unit from diffusion (MOSIS rule #5B.6)" + +/* 5B.7 -- not implemented */ + +/* ---------------------------------------------------------------- */ +/* Contact to Active */ +/* ---------------------------------------------------------------- */ + +/* 6B.1 + 6B.2 + 6B.3 */ + width ndc,pdc 4 \\ + "Diffusion contact width must be at least 4 (MOSIS rule #6B.1,2,3)" + width nsc,psc 4 \\ + "Substrate contact width must be at least 4 (MOSIS rule #6B.1,2,3)" + +/* 6B.2 this is here to explicit check the contact spacing rule 3. */ +#ifdef SUBMICRON + spacing nsc pdc 1 touching_illegal \\ + "Substrate contact must be 1 unit from diffusion contact (MOSIS rule #6B.2b)" + spacing psc ndc 1 touching_illegal \\ + "Substrate contact must be 1 unit from diffusion contact (MOSIS rule #6B.2b)" +#endif + +/* + edge4way psc (~psc)/a 1 psd psd 1 \\ + "Substrate contact must overlapped by diffusion by at least 1 (MOSIS 26G rule)" + edge4way nsc (~nsc)/a 1 nsd nsd 1 \\ + "Substrate contact must overlapped by diffusion by at least 1 (MOSIS 26G rule)" +*/ + +/* 6B.4 & 6B.5 -- + * Watch out here: a spacing "touching_ok" rule CANNOT be used here: + * it will miss certain checks. + */ + edge4way allActive ~(allActive)/act 4 ~(ndc,pdc,nsc,psc)/act \\ + ~(allActive)/act 4 \\ + "Diffusion contacts must be 4 from other diffusions (MOSIS rule #6B.4,5)" + +/* 6B.6 */ + spacing DiffCut allFet 1 touching_illegal \\ + "Diffusion contacts cannot touch transistors (MOSIS rule #6B.6)" + +/* 6B.7 */ + spacing DiffCut poly 1 touching_illegal \\ + "Diffusion contact to field poly must be at least 1 (MOSIS rule #6B.7)" + +/* 6.8 -- not implemented */ + +/* 6B.9 */ + spacing DiffCut pc/act 2 touching_illegal \\ + "Poly contacts must be 2 away from diffusion contacts (MOSIS rule #6B.9)" + +/* ---------------------------------------------------------------- */ +/* Contacts must all be rectangular (no adjacent contacts */ +/* of same type) because of the way their contact is generated by */ +/* CIFoutput section rules. This is handled using the corner checks */ +/* in the rules below. Overlaps between contacts must be exact */ +/* overlaps. The only exception is overpad, which doesn't matter. */ + + edge4way m3c/m3 ~m3c/m3 1 ~m3c/m3 (~m3c,m3c)/m3 1 \\ + "Metal3 contacts must be rectangular (Magic rules)" + edge4way m2c/m2 ~m2c/m2 1 ~m2c/m2 (~m2c,m2c)/m2 1 \\ + "Metal2 contacts must be rectangular (Magic rules)" + + edge4way ndc/m1 ~ndc/m1 1 ~ndc/m1 (~ndc,ndc)/m1 1 \\ + "N-diffusion contacts must be rectangular (Magic rules)" + edge4way pdc/m1 ~pdc/m1 1 ~pdc/m1 (~pdc,pdc)/m1 1 \\ + "P-diffusion contacts must be rectangular (Magic rules)" + edge4way psc/m1 ~psc/m1 1 ~psc/m1 (~psc,psc)/m1 1 \\ + "P-substrate contacts must be rectangular (Magic rules)" + edge4way nsc/m1 ~nsc/m1 1 ~nsc/m1 (~nsc,nsc)/m1 1 \\ + "N-substrate contacts must be rectangular (Magic rules)" + + edge4way pc/m1 ~pc/m1 1 ~pc/m1 (~pc,pc)/m1 1 \\ + "Polysilicon contacts must be rectangular (Magic rules)" + edge4way ec/m1 ~ec/m1 1 ~ec/m1 (~ec,ec)/m1 1 \\ + "Electrode contacts must be rectangular (Magic rules)" + edge4way cc/m1 ~cc/m1 1 ~cc/m1 (~cc,cc)/m1 1 \\ + "Capacitor contacts must be rectangular (Magic rules)" + + edge4way emc/m1 ~emc/m1 1 ~emc/m1 (~emc,emc)/m1 1 \\ + "Emitter contacts must be rectangular (Magic rules)" + edge4way clc/m1 ~clc/m1 1 ~clc/m1 (~clc,clc)/m1 1 \\ + "Collector contacts must be rectangular (Magic rules)" + edge4way pbc/m1 ~pbc/m1 1 ~pbc/m1 (~pbc,pbc)/m1 1 \\ + "P-base Contacts must be rectangular (Magic rules)" + edge4way nbdc/m1 ~nbdc/m1 1 ~nbdc/m1 (~nbdc,nbdc)/m1 1 \\ + "CCD-diffusion Contacts must be rectangular (Magic rules)" + +/* ---------------------------------------------------------------- */ +/* Metal 1 */ +/* ---------------------------------------------------------------- */ +/* 7.1 + 7.2 */ + width allMetal1,pad/m1 3 \\ + "First-level metal width must be at least 3 (MOSIS rule #7.1)" +#ifdef TIGHTMETAL + spacing allMetal1,pad/m1 allMetal1,pad/m1 2 touching_ok \\ + "First-level metal spacing must be at least 2 (MOSIS rule #7.2)" +#else + spacing allMetal1,pad/m1 allMetal1,pad/m1 3 touching_ok \\ + "First-level metal spacing must be at least 3 (MOSIS rule #7.2)" +#endif /* TIGHTMETAL */ + +/* 7.3 + 7.4 */ +/* guaranteed with 4x4 poly and diffusion contacts */ + + +/* ---------------------------------------------------------------- */ +/* Via */ +/* ---------------------------------------------------------------- */ + +/* 8.1 + 8.2 + 8.3 */ + width m2c 4 \\ + "Contact width must be at least 4 (MOSIS rule #8.1,2,3)" + +/* 8.4 + 8.5 */ +/* Vias have to be on flat surface */ +/* Don't allow poly or diffusion edges underneath metal2 contacts: */ +/* this rule is only valid for standard processes, not for those */ +/* processes use planarized interconnection technology. */ +#ifdef STANDARD + edge4way allPoly ~(allPoly)/a 1 ~m2c/m2 ~(allPoly)/a 1 \\ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 + edge4way allPoly2 ~(allPoly2)/a 1 ~m2c/m2 ~(allPoly2)/a 1 \\ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 + edge4way allActive ~(allActive)/a 1 ~m2c/m2 ~(allActive)/a 1 \\ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 + + edge4way ~(allPoly)/a allPoly 1 ~m2c/m2 allPoly 1 \\ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 + edge4way ~(allPoly2)/a allPoly2 1 ~m2c/m2 allPoly2 1 \\ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 + edge4way ~(allActive)/a allActive 1 ~m2c/m2 allActive 1 \\ + "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 +#endif /* STANDARD */ + + +/* ---------------------------------------------------------------- */ +/* Metal 2 */ +/* ---------------------------------------------------------------- */ +/* 9.1 */ + width allMetal2 3 \\ + "Second-level metal width must be at least 3 (MOSIS rule #9.1)" + +/* 9.2 */ +#ifdef TIGHTMETAL + spacing allMetal2 allMetal2 3 touching_ok \\ + "Second-level metal spacing must be at least 3 (MOSIS rule #9.2b)" +#else +#ifdef SUBMICRON + spacing allMetal2 allMetal2 3 touching_ok \\ + "Second-level metal spacing must be at least 3 (MOSIS rule #9.2b)" +#else + spacing allMetal2 allMetal2 4 touching_ok \\ + "Second-level metal spacing must be at least 4 (MOSIS rule #9.2a)" +#endif /* SUBMICRON */ +#endif /* TIGHTMETAL */ + +/* 9.3 */ +/* achieved with via size of 4x4 */ + + +/* ---------------------------------------------------------------- */ +/* Overglass */ +/* ---------------------------------------------------------------- */ +/* Rules for overglass (10.1-5) are not check because they are */ +/* either */ +/* 1. absolute micron rules, and */ +/* 2. vender/process dependent. */ +/* except the metal overlap of overglass rule (10.3) can be handled */ +/* case by case in CIFoutput section. */ +/* NOTE: glass layer is NOT usually used. Use "pad" layer for pad */ +/* and the corresponding overglass will be generated automatically. */ + +/* MOSIS rules to make sure there are m2 under glass - for those */ +/* users who like to use explicit "glass" layer... */ +/* */ +/* edge4way space glass 1 allMetal2 0 0 \ */ +/* "There must be metal 2 under the glass opening" metal2 */ +/* */ +/* I am removing this rule simply we have metal3 now and there's no */ +/* way to tell which process the pad is intended for. Basically, I */ +/* am enforcing the use of "pad" layer... */ + + + +/* ---------------------------------------------------------------- */ +/* Open and Pstop */ +/* ---------------------------------------------------------------- */ +/* The open layer is actually a combination of overglass and */ +/* contacts to expose the intrinsic silicon surface for future */ +/* etchimg process for micromachining device fabrication. */ +/* Since lots of applications are possible, there is no rules */ +/* enforced by Magic. Designers aimed at micromachining devices */ +/* must do DRC themself :-) */ +/* See the following reference for detail: */ +/* "High-Level CAD Melds Micromachined Devices with Foundaries", */ +/* Janet C. Marshall, M. Parameswaran, Mona E. Zaghloul, and */ +/* Michael Gaitan, IEEE Circuit and Devices, Vol. 8, No. 6, */ +/* pp. 10-17, 1992 */ + + + +/* ---------------------------------------------------------------- */ +/* Poly2 as Capacitor */ +/* ---------------------------------------------------------------- */ +/* 11.1 */ +/* The exact rule asks for 3 lambda minimum width for 'capacitor'. */ +/* But there are overlaps of poly/eletrode structures such that 2 */ +/* is fine, such as the overlaps in floating gates. So we are risk- */ +/* ing a little here... */ + width cap,capc/a 2 \\ + "Electrode capacitor width must be at least 3 (MOSIS rule #11.1)" + +/* 11.2 + 12.2 */ + spacing allPoly2 allPoly2 3 touching_ok \\ + "Second-level poly spacing must be at least 3 (MOSIS rule #11.2,12.2)" + +/* 11.3 */ + edge4way cap,cc space 1 0 0 0 \\ + "Cap must be overlapped by poly or poly2 (MOSIS rule #11.3)" + edge4way cap,cc poly 2 poly poly 2 \\ + "Cap must be overlapped by poly or poly2 (MOSIS rule #11.3)" + edge4way cap,cc poly2 2 poly2 poly2 2 \\ + "Cap must be overlapped by poly or poly2 (MOSIS rule #11.3)" + +/* 11.4 */ + edge4way nw,pw,cw ~(nw,pw,cw)/w 2 ~(cap,cc)/a ~(nw,pw,cw)/w 2 \\ + "Cap must be on a flat surface (MOSIS rule #11.4)" active + edge4way ~(nw,pw,cw)/w nw,pw,cw 2 ~(cap,cc)/a nw,pw,cw 2 \\ + "Cap must be on a flat surface (MOSIS rule #11.4)" active + edge4way cap ~(cap)/a 2 allFet,poly,poly2,space/a,cc/a \\ + allDiff,poly 2 "Cap must be on a flat surface (MOSIS rule #11.4)" active + +/* 11.5 */ +/* Done by 11.3 and 11.4 */ + + +/* ---------------------------------------------------------------- */ +/* Poly2 as Transistor */ +/* ---------------------------------------------------------------- */ +/* 12.1 */ + width allPoly2 2 \\ + "Electrode width must be at least 2 (MOSIS rule #12.1)" + +/* 12.2 */ +/* Done by 11.2 */ + +/* 12.3 */ + edge4way enfet,epfet poly2,ec/a 2 poly2,ec/a 0 0 \\ + "Poly2 must overhang transistor by at least 2 (MOSIS rule #12.3)" + edge4way nffet,pffet cap 2 cap 0 0 \\ + "Cap must overhang transistor by at least 2 (MOSIS rule #12.3)" + edge4way nffet ~(cap,nffet,enfet,nfet)/a 2 cap 0 0 \\ + "Cap must overhang doubletransistor by at least 2 (MOSIS rule #12.3)" + edge4way pffet ~(cap,pffet,epfet,pfet)/a 2 cap 0 0 \\ + "Cap must overhang doubletransistor by at least 2 (MOSIS rule #12.3)" + +/* 12.4 */ + edge4way allDiff,allOhmic el 1 space/a 0 1 \\ + "Poly2 and diffusion must be separated by at least 1 (MOSIS rule #12.4)" + +/* 12.5 */ + +/* 12.6 */ + spacing allPoly2 pc,ndc,pdc 2 touching_illegal \\ + "Poly2 spacing to poly or diffusion contact must be at least 3 (MOSIS rule #12.6)" +/* + edge4way poly2,ec/a epfet 3 epfet 0 0 \\ + "Transistors must be at least 3 units wide (MOSIS rule #2)" + edge4way poly2,ec/a enfet 3 enfet 0 0 \\ + "Transistors must be at least 3 units wide (MOSIS rule #2)" + edge4way cap,capc/a pffet 3 pffet 0 0 \\ + "Transistors must be at least 3 units wide (MOSIS rule #2)" + edge4way cap,capc/a nffet 3 nffet 0 0 \\ + "Transistors must be at least 3 units wide (MOSIS rule #2)" +*/ + + +/* ---------------------------------------------------------------- */ +/* Poly2 Contact */ +/* ---------------------------------------------------------------- */ +/* 13.1 + 13.2 */ + width ec,capc 4 \\ + "Electrode contact width must be at least 4 (MOSIS rule #13.1)" + +/* 13.3 */ +/* Done by 11.3 */ + +/* 13.4 */ + edge4way ec/a space 1 poly2 poly2 1 \\ + "Electrode contact must be overlaped by poly2 (MOSIS rule #13.4)" + edge4way ec/a poly2 1 poly2 poly2 1 \\ + "Electrode contact must be overlaped by poly2 by 1 (MOSIS rule #13.4)" + +/* 13.5 */ + edge4way allDiff,allOhmic ec 2 space/a 0 2 \\ + "Poly2 and diffusion contact must be separated by at least 2 (MOSIS rule #13.5)" + + +/* ---------------------------------------------------------------- */ +/* Via 2 */ +/* ---------------------------------------------------------------- */ +/* 14.1 + 14.2 + 14.3 */ +/* By CIF output generation */ + width m3c 4 \\ + "Third-level metal contact width must be at least 4 (MOSIS rule #14.1,2,3)" + +/* 14.4 */ +/* guaranteed by 4x4 m2c and 4x4 m3c */ +/* Via2, i.e "m3c" can overlap anything except m2c layer */ + + +/* ---------------------------------------------------------------- */ +/* Metal 3 */ +/* ---------------------------------------------------------------- */ +/* 15.1 */ +#ifdef SUBMICRON + width allMetal3 5 \\ + "Third-level metal width must be at least 5 (MOSIS rule #15.1b)" +#else + width allMetal3 6 \\ + "Third-level metal width must be at least 6 (MOSIS rule #15.1a)" +#endif + +/* 15.2 */ +#ifdef SUBMICRON + spacing allMetal3 allMetal3 3 touching_ok \\ + "Third-level metal spacing must be at least 3 from other third-level metal (MOSIS rule #15.2b)" +#else + spacing allMetal3 allMetal3 4 touching_ok \\ + "Third-level metal spacing must be at least 4 from other third-level metal (MOSIS rule #15.2a)" +#endif + +/* 15.3 */ + edge4way m3c/m3 ~m3c/m3 1 m3 m3 1 \\ + "Mimimum metal3 overlap of via must be at least 1 (MOSIS rule #15.3)" + + +/* ---------------------------------------------------------------- */ +/* NPN Bipolar */ +/* ---------------------------------------------------------------- */ +/* 16.1 */ +/* As always, composite contacts are 4x4, where the actual */ +/* transistor contacts are 2x2 by CIF output generator */ + width clc,pbc,emc 4 \\ + "Transistor contact width must be at least 4 (MOSIS rule #16.1)" + +/* 16.2 */ +/* Done by 16.1 4x4 emc and CIF output generation */ + +/* 16.3 */ +/* This rule is guaranteed by the way the CIF output generates */ +/* N-Select for emitter (expand by 2 lambda), so we have Pbase */ +/* overlap of emitter(or emc) by 2+2 =4 */ + edge4way emc/a,emit pbase 4 pbase pbase 4 \\ + "Pbase overlap of emitter must be at least 4 (MOSIS rule #16.3)" + +/* 16.4 */ +/* NOTE; NO need to make this an edge rule... */ + spacing pbc emc/a,emit 7 touching_illegal \\ + "Base must be 7 (4+2+1) away from emitter (MOSIS rule #16.3,4,11)" + +/* 16.5 */ +/* This rule is guaranteed by requiring that base contact has */ +/* at least 3 (1+2) lambda base enclosure... */ +/* edge4way pbc/a pb,space 3 pb pb,space 3 */ + edge4way pbc (~pbc)/a 3 pb,pbc/a pb,pbc/a 3 \\ + "Pbase overlap of base contact must be at least 3 (MOSIS rule #16.5)" + +/* 16.6 */ +/* This rule is guaranteed by the CIF output generation of P-select */ + +/* 16.6 */ +/* This rule is enforced by checking whether collector is out of */ +/* Nwell and the fact that collector width is required to be at */ +/* least 6 */ + width col,clc/a 6 \\ + "Collector width must be at least 6 (MOSIS rule #16.6)" + +/* 16.7 */ +/* Explicit Nwell required for Bipolar transistors... */ + edge4way pbase space/a 6 nwell space/a 6 \\ + "Nwell overlap of Pbase must be at least 6 (MOSIS rule #16.7)" well + +/* 16.8 */ + edge4way pbase (~pbase)/a 4 ~(col,clc)/a ~(col,clc)/a 4 \\ + "Pbase must be at least 4 away from collector (MOSIS rule #16.8)" + +/* 16.9 */ + edge4way clc (~clc)/a 1 col col 1 \\ + "Collector overlap of contact must be at least 1 (MOSIS rule #16.9)" + +/* 16.10 */ +/* This rule is guaranteed by making sure that collector is within */ +/* PBase and the corresponding CIF output generation */ + +/* 16.11 */ + edge4way nw ~(nw)/w 3 ~(col,clc)/a ~(nw)/w 3 \\ + "N-well overlap of collector must be at least 3 (MOSIS rule #16.11)" active + edge4way ~(nw)/w nw 3 ~(col,clc)/a nw 3 \\ + "N-well overlap of collector must be at least 3 (MOSIS rule #16.11)" active + +/* This is a special rule to guarantee the emitter width */ + width em,emc/a 4 \\ + "Emitter width must be at least 4 (Magic Bipolar Transistor rule)" + +/* This is a special rule for multi-emitters transistor according */ +/* to rule 16.2 and 2.2 */ + spacing em,emc/a em,emc/a 7 touching_ok \\ + "Unrelated emitter must be at least 7 apart (Magic Bipolar transistor rule)" + +/* The following rules are added for pbase resistor implementation. */ +/* They are not in the official SCMOS design rules since I have no */ +/* foundry rules available at this moment and the numbers here is */ +/* considered to be conservative... */ + width pbase,pbc/a 4 \\ + "Pbase width must be at least 4 (MOSIS extension rule)" + + spacing pbase,pbc/a pbase,pbc/a 4 touching_ok \\ + "Pbase spacing must be at least 4 (MOSIS extension rule)" + +/* ---------------------------------------------------------------- */ +/* Capacitor Well */ +/* ---------------------------------------------------------------- */ +/* These are DRC rules for Capacitor Well (CWell) according to HP's */ +/* 1.2um linear capacitor process pi@isi.edu 9/18/92 */ +/* ---------------------------------------------------------------- */ + +/* 17.1 */ + width cwell 10 \\ + "Cap-well width must be at least 10 (MOSIS rule #17.1)" + +/* 17.2 */ + spacing cwell cwell 9 touching_ok \\ + "Cap-well spacing must be at least 9 (MOSIS rule #17.2)" + spacing cwell nwell 9 touching_illegal \\ + "Cap-well spacing must be at least 9 (MOSIS rule #17.2)" + +/* 17.3 */ + edge4way cwell space 5 ~(allNActive)/a ~(allNActive)/w 5 \\ + "Cap-well spacing to external active must be at least 5 (MOSIS rule #17.3)" active + edge4way cwell space 3 ~(allPOhmic)/a ~(allPOhmic)/w 3 \\ + "P-substrate diffusion and Cap-well must be separated by 3 (MOSIS rule #17.3)" active + + +/* 17.4 */ +/* Need to do this check from the Cap-well plane - in order Not */ +/* to conflict with the general rules for N-diffusion */ + edge4way space cwell 3 (space,poly,pc)/a 0 0 \\ + "Cap-well overlap of diffusion must be at least 3 (MOSIS rule #17.4)" active + +/* ---------------------------------------------------------------- */ +/* Well-capacitor */ +/* ---------------------------------------------------------------- */ +/* These are DRC rules for Well-capacitor (wcap) according to HP's */ +/* 1.2um linear capacitor process pi@isi.edu 9/18/92 */ +/* Rule 18.5 and 18.6 are preliminary, they are conservative here! */ +/* ---------------------------------------------------------------- */ +/* 18.1 */ + width wcap 3 \\ + "Well-capacitor must be at least 3 (MOSIS rule #18.1)" + +/* 18.2 */ +/* achieved by rule 3.5 */ + +/* 18.3 */ + edge4way wcap space 1 poly poly 1 \\ + "Well-capacitor overhang is missing (MOSIS rule #18.3)" + +/* 18.4 */ + edge4way wcap ndiff 3 ndiff ndiff 3 \\ + "N-diffusion overlap of well-capacitor must be at least 3 (MOSIS rule #18.4)" + +/* 18.5 */ +/* achieved by rule 5B.6 */ + spacing wcap pc 2 touching_illegal \\ + "Well-capacitor spacing to poly contact must be at least 2 (MOSIS rule #18.5)" + + +/* 18.6 */ +/* similar to rule 6A.4 or 6B.6 */ + spacing wcap ndc 4 touching_illegal \\ + "Well-capacitor spacing to diffusion contact must be at least 4 (MOSIS rule #18.6)" + + +/* ---------------------------------------------------------------- */ +/* Buried CCD */ +/* ---------------------------------------------------------------- */ +/* 19.1 */ +/* Have to do it seperately... */ + width nbd,nbdc,bd/a 4 \\ + "CCD channel width must be at least 4 (MOSIS rule #19.1)" + width nbdc 4 \\ + "CCD contact width must be at least 4 (MOSIS rule #19.1)" + + +/* 19.2 */ +/* The 4 lambda spacing is a conservative guess here... */ +/* This following rule will NOT work! Need to check 2 planes */ +/* separately.... */ +/* + spacing bd/a,nbd,nbdc bd/a,nbd,nbdc 4 touching_ok \\ + "CCD channel spacing must be at least 4 (MOSIS rule #19.2)" +*/ + edge4way nbd,nbdc ~(bd,nbd,nbdc)/a 4 (bd,space)/i 0 0 \\ + "CCD channel spacing must be at least 4 (MOSIS rule #19.2)" implant + edge4way nbd,nbdc ~(poly,nbd,nbdc)/a 4 ~(poly,nbd,nbdc)/a ~(poly,nbd,nbdc)/a 4 \\ + "CCD channel spacing must be at least 4 (MOSIS rule #19.2)" active + +/* 19.3 + 19.4 + 19.5 */ +/* guaranteed by the CIF output generation */ + +/* 19.6 */ +/* This first one check poly and electrode overhang */ + edge4way bd space 2 nbd,poly,cap,el 0 0 \\ + "CCD channel overhang is missing (MOSIS rule #19.6)" active +/* There is a problem with capacitor overhang, I have no way to do */ +/* it now... */ + +/* MOSIS extension BCCD layout rule */ + spacing nbdc poly,el 1 touching_illegal \\ + "CCD-diffusion contact spacing to poly must be at least 1 (MOSIS CCD rule)" + edge4way nbd poly,el 1 bd 0 0 \\ + "Missing Buried CCD Difussion layer (MOSIS CCD rule)" implant + +/* ---------------------------------------------------------------- */ +/* High-Voltage MOSFETs */ +/* ---------------------------------------------------------------- */ +/* These are DRC rules for AMI 1.5 micron process for high-voltage */ +/* MOSFETs pi@isi.edu 10/01/92 */ +/* */ +/* ---------------------------------------------------------------- */ +/* 20.1 */ +/* Well spacing for different potential must be 12 lambda away now. */ +/* These rules correspond to 1.1 + 1.2 rules */ +/* width rule is as usual */ + edge (~hnwell)/w hnwell 10 hnwell hnwell 10\\ + "High-Voltage N-Well width must be at least 10 (MOSIS rule #1.1)" + edge (~hpwell)/w hpwell 10 hpwell hpwell 10\\ + "High-Voltage P-Well width must be at least 10 (MOSIS rule #1.1)" +/* spacing rules are new */ + edge hnwell space,pw,hpw 9 space,pw,hpw space,pw,hpw 9\\ + "High-Voltage N-Well spacing to N-Well must be at least 9 (MOSIS rule #1.2)" + edge hpwell space,nw,hnw 9 space,nw,hnw space,nw,hnw 9\\ + "High-Voltage P-Well spacing to P-Well must be at least 9 (MOSIS rule #1.2)" + edge hnwell space,pw,hpw,nw 12 space,pw,hpw,nw space,pw,hpw,nw 12\\ + "High-Voltage N-Well spacing must be at least 12 (MOSIS rule #20.1)" + edge hpwell space,nw,hnw,pw 12 space,nw,hnw,pw space,nw,hnw,pw 12\\ + "High-Voltage P-Well spacing must be at least 12 (MOSIS rule #20.1)" + +/* 20.2 */ +/* High-Voltage Active spacing must be at least 5 lambda away */ +/* This rule corresponds to 2.2 rule */ +#define allHVNActive hndiff,hndc/a,hnfet +#define allHVPActive hpdiff,hpdc/a,hpfet + edge4way ~(allHVDiff)/a allHVDiff 3 allHVDiff allHVDiff 3\\ + "High-Voltage Diffusion width must be at least 3 (MOSIS rule #2.1)" + spacing allHVNActive allHVNActive 5 touching_ok \\ + "High-Voltage Diffusion spacing must be at least 5 (MOSIS rule #20.2)" + spacing allHVPActive allHVPActive 5 touching_ok \\ + "High-Voltage Diffusion spacing must be at least 5 (MOSIS rule #20.2)" + +/* 20.3 */ +/* High-Voltage transistors spacing to Well edge must be 7 lambda */ +/* This rule corresponds to rule 2.3 */ +/* without explicit well definition */ + spacing hndiff,hndc/a hpdiff,hpdc/a 14 touching_illegal \\ + "P-type diffusion must be 14 away from N-type diffusion (MOSIS rule #20.3)" + spacing hndiff,hndc/a allPDiff 12 touching_illegal \\ + "P-type diffusion must be 12 away from N-type diffusion (MOSIS rule #20.3+2.3)" + spacing hpdiff,hpdc/a allNDiff 12 touching_illegal \\ + "P-type diffusion must be 12 away from N-type diffusion (MOSIS rule #20.3+2.3)" + +/* with explicit well definition */ + spacing hndiff,hnfet,hndc/a hnwell 7 touching_illegal \\ + "HVN-diffusion and HVN-well must be separated by 7 (MOSIS rule #20.3)" + spacing hpdiff,hpfet,hpdc/a hpwell 7 touching_illegal \\ + "HVP-diffusion and HVP-well must be separated by 7 (MOSIS rule #20.3)" + spacing allNOhmic hpwell 3 touching_illegal \\ + "N-substrate diffusion and HVP-well must be separated by 3 (MOSIS rule #2.4+20.3)" + spacing allPOhmic hnwell 3 touching_illegal \\ + "P-substrate diffusion and HVN-well must be separated by 3 (MOSIS rule #2.4+20.3)" + +/* 20.4 */ +/* Poly1 must not be used as an transistor for high-voltage design */ +/* guaranteed by the composition rules */ + +/* 20.5 */ +/* High-Voltage Active overlap of contact is now 2 lambda */ +/* This rule corresponds to rule 6B.2 */ + edge (~hndc)/a hndc/a 6 hndc/a hndc/a 6\\ + "High-Voltage Diffusion contact width must be at least 6 (MOSIS rule #20.5)" + edge (~hpdc)/a hpdc/a 6 hpdc/a hpdc/a 6\\ + "High-Voltage Diffusion contact width must be at least 6 (MOSIS rule #20.5)" + +/* 20.6 */ +/* High-Voltage transistor channel length must be at least 4 lambda */ + edge hpdiff,hpdc/a hpfet 4 hpfet 0 0 \\ + "High-Voltage transistor must be at least 4 units long (MOSIS rule #20.6)" + edge hndiff,hndc/a hnfet 4 hnfet 0 0 \\ + "High-Voltage transistor must be at least 4 units long (MOSIS rule #20.6)" + + + +/* ---------------------------------------------------------------- */ +/* overlapping rules */ + exact_overlap m3c,m2c,ndc,pdc,pc,psc,nsc,ec,capc,clc,emc,pbc,hndc,hpdc,hnsc,hpsc + no_overlap pfet,nfet pfet,nfet + no_overlap epfet,enfet epfet,enfet + no_overlap pffet,nffet pffet,nffet + no_overlap hpfet,hnfet hpfet,hnfet + +end + + +extract + + + +#ifndef OLD_EXTRACT_STYLE + +#include "scmosExt.tech.in" + +#else +/* In the following, MOSIS provides 9 extraction styles as follows: + + SCNA20(ORB) - ORBIT 2.0 micron low-noise analog N-well CMOS/BJT + process. *default* + SCPE20(ORB) - ORBIT 2.0 micron P-well CMOS/Bulk process. + SCNA16(AMI) - AMI 1.6 micron N-well CMOS/Junction-isolated BJT + process. + SCN12LC(HP) - HP CMOS34 1.2 micron N-well CMOS/Bulk process with + linear capacitor option. + SCNE12(ORB) - ORBIT 1.2 micron 2 poly N/P-well CMOS process. + SCN10(MOT) - MOTOROLA 1.0 micron N-well/P-epi CMOS process. + * Not Available at this moment * + SCN08(HP) - HP CMOS26B 1.0 micron N-well CMOS/Bulk process. + SCN08(IBM) - IBM 0.8 micron N-well CMOS/Bulk process. + * Not Available at this moment * + + Whenever it is available, measured data on MOSIS test structures + is used. Data is obtained from a representitive run (usually the + latest run at the time). If not available, typical (or nominal) + data from vendor wafer specification is used if not specifically + noted. + +*/ + +/* Have to redefine allMetal1 to make it pure metal line here... */ + +#undef allMetal1 +#define allMetal1 m1,m2c/m1 + + +#ifdef STANDARD +style SCNA20(ORB) +/* The following data is obtained from MOSIS run 'n34o' */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + cscale 1 + lambda 100 + step 100 + /* No parallel wire coupling capacitances */ + sidehalo 0 + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 27260 + resist pdiff,psd,pdc/a,psc/a 59550 + resist allPoly 23430 + resist allPoly2 19690 + resist em,emc/a 27260 + resist pbase,pbc/a 2000000 + resist metal1,m2c/metal1 52 + resist metal2,pad 26 + resist nwell 2505830 + + /* Contact resistance (in milliohms per square) */ + contact pc/a 4 11000 + contact ec/a,capc/a 4 9000 + contact ndc/a,nsc/a 4 18710 + contact pdc/a,psc/a 4 100560 + + /* Area parasitic capacitance to substrate (in attofarads per + lambda square) + [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + areacap poly,pc/a 39 + areacap metal1,pad,m2c/metal1 24 + areacap metal2 19 +/* + areacap ndiff,ndc/a 220 + areacap pdiff,pdc/a 270 +*/ + areacap cc/a,cap 39 + areacap poly2,ec/a 50 + + /* Inter-layer capacitance */ + overlap metal1 pdiff,ndiff,psd,nsd 47 + overlap metal2 pdiff,ndiff,psd,nsd 22 metal1 + overlap metal1 poly 30 + overlap metal2 poly 19 metal1 + overlap metal2 metal1 45 + overlap metal1 poly2 40 + + /* Perimeter parasitic capacitances (in attofarads per lambda) + [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] */ +/* + perimc ndiff,ndc/a space,pwell 559 + perimc pdiff,pdc/a space,nwell 402 +*/ + perimc poly,pc/a space,pwell,nwell 80 + + /* Active devices: N-Well process */ + fet pfet pdiff,pdc,pffet 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc,nffet 2 nfet GND! pwell 0 0 + fet epfet pdiff,pdc,pffet 2 epfet Vdd! 0 0 + fet enfet ndiff,ndc,nffet 2 enfet GND! 0 0 + + /* Kludge for MOS capacitance extraction, where source and drain + are connected together */ + fet pfet pdiff,pdc,pffet 1 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc,nffet 1 nfet GND! pwell 0 0 + + /* Electrode capacitance extraction */ + device capacitor None cap,capc/a poly,pc 120 735 + + /* DRAM capacitance extraction */ + device capacitor None wcap ndiff,ndc 300 0 + + /* bipolar NPN extraction */ + device bjt npn emit,emc/a pbase,pbc/a nwell + +style SCPE20(ORB) + +/* The following data is obtained from MOSIS run 'n35s', 6/93 */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + cscale 1 + lambda 100 + step 100 + /* No parallel wire coupling capacitances */ + sidehalo 0 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 26670 + resist pdiff,psd,pdc/a,psc/a 72860 + resist allPoly 23860 + resist allPoly2 18540 + resist metal1,m2c/metal1 49 + resist metal2,pad 26 + resist pwell 2128280 + + /* Contact resistance (in milliohm per contact) */ + contact pc/a 4 12800 + contact ec/a,capc/a 4 8420 + contact ndc/a,nsc/a 4 36660 + contact pdc/a,psc/a 4 56300 + contact m2c/m1 5 30 + + /* Area parasitic capacitance to substrate (in attofarads per + lambda square) + [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + areacap poly,pc/a 57 + areacap allMetal1,DiffMetal,HVDiffMetal 41 + areacap PolyMetal,BiMetal,CCDMetal 41 + areacap allMetal2 21 +/* + areacap ndiff,ndc/a 398 + areacap pdiff,pdc/a 230 +*/ + + /* Inter-layer capacitance */ + overlap metal1 pdiff,ndiff,psd,nsd 36 + overlap metal2 pdiff,ndiff,psd,nsd 16 metal1 + overlap metal1 poly 33 + overlap metal2 poly 15 metal1 + overlap metal2 metal1 29 + overlap metal1 poly2,cap 33 + + /* Perimeter parasitic capacitances (in attofarads per lambda) + [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] */ +/* + perimc ndiff,ndc/a space,pwell 423 + perimc pdiff,pdc/a space,nwell 85 +*/ + perimc poly,pc/a space,pwell,nwell 168 + + /* Active devices: P-Well process */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + + +style SCNA16(AMI) + +/* The following data is obtained from MOSIS run 'n34l', 6/93 */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + cscale 1 + lambda 80 + step 100 + /* No parallel wire coupling capacitances */ + sidehalo 0 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 51680 + resist pdiff,psd,pdc/a,psc/a 74800 + resist allPoly 34780 + resist allPoly2 22400 + resist allMetal1 48 + resist allMetal2 28 + resist nwell 1446400 + + /* Contact resistance (in milliohm per contact) */ + contact pc 4 61560 + contact ec 4 12010 + contact ndc,nsc 4 45780 + contact pdc,psc 4 32310 + contact m2c 5 37570 + + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.8 micron ---> multiplication factor 0.64 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + /* areacap nfet 709 */ + /* areacap pfet 669 */ + areacap poly,pc/a 22 + areacap allMetal1,DiffMetal,HVDiffMetal 15 + areacap PolyMetal,BiMetal,CCDMetal 15 + areacap allMetal2 10 + + /* Inter-layer capacitance */ + overlap allMetal1 ndiff,nsd 27 + overlap allMetal1 pdiff,psd 27 + overlap allMetal2 pdiff,psd 12 metal1 + overlap allMetal1 allPoly 25 + overlap allMetal1 allP2 25 + overlap allMetal2 allPoly 11 metal1 + overlap metal2 metal1 23 + /* Junction capacitance */ +/* + overlap ndiff,ndc/a space,pwell 172 + overlap pdiff,pdc/a space,nwell 200 +*/ + + /* Perimeter parasitic capacitances (in attofarads per lambda) + [ 1 lambda = 0.8 micron ---> multiplication factor 0.8 ] */ +/* + perimc ndiff,ndc/a space,allWell 6 + perimc pdiff,pdc/a space,allWell 68 +*/ + + /* Active devices: N-Well process, */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + + +style SCNE12(ORB) + +/* The following data is obtained from MOSIS run 'n37d', 7/93 */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + cscale 1 + lambda 60 + step 100 + /* No parallel wire coupling capacitances */ + sidehalo 0 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistances (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 43180 + resist pdiff,psd,pdc/a,psc/a 79770 + resist allPoly 22160 + resist allPoly2 21140 + resist allMetal1 51 + resist allMetal2 26 + resist nwell 1195000 + + /* Contact resistances (in milliohm per contact) */ + contact pc 4 13230 + contact ec 4 13510 + contact ndc,nsc 4 56490 + contact pdc,psc 4 181400 + contact m2c 5 43330 + + + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.6 micron ---> multiplication factor 0.36 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + /* areacap nfet 454 */ + /* areacap pfet 368 */ + areacap poly,pc/a 29 + areacap allMetal1,DiffMetal,HVDiffMetal 16 + areacap PolyMetal,BiMetal,CCDMetal 16 + areacap allMetal2 10 + + overlap allMetal1 ndiff,ndc/a 22 + overlap allMetal1 allPoly 19 + overlap allMetal1 allP2 21 + overlap allMetal2 ndiff,ndc/a 8 + overlap allMetal2 allPoly 7 + overlap metal2 metal1 12 + /* Junction capacitance */ + overlap ndiff,ndc/a space,pwell 185 + overlap pdiff,pdc/a space,nwell 148 + + /* Perimeter parasitic capacitances (in attofarads per lambda) + [ 1 lambda = 0.6 micron ---> multiplication factor 0.6 ] */ + perimc allMetal1 space,allWell 41 + perimc allMetal2 space,allWell 42 + /* Junction capacitances */ +/* + perimc ndiff,ndc/a space,pwell 236 + perimc pdiff,pdc/a space,nwell 147 +*/ + + /* No measurements for this run, but leave here for future... + sideoverlap allMetal1 space,allWell PNplus 60 + sideoverlap allMetal2 space,allWell allPoly 60 + sideoverlap allMetal2 space,allWell PNplus 57 + sideoverlap allMetal2 space,allWell allPoly 57 + sideoverlap allMetal2 space,allWell allMetal1 64 + */ + + /* Nwell process, so PMOS has "nwell" defined for analog + designs... */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + + +#endif /* STANDARD */ + +#ifdef TIGHTMETAL +style SCN12LC(HP) + +/* The following data is obtained from MOSIS run 'n36y', 7/93 */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + cscale 1 + lambda 60 + step 100 + /* No parallel wire coupling capacitances */ + sidehalo 0 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nnd,ndc/a,nsc/a 74630 + resist pdiff,ppd,pdc/a,psc/a 109590 + resist poly,pc/a,pfet,nfet 26620 + resist allMetal1 60 + resist allMetal2 39 + resist nwell 1500000 + + /* Contact resistance (in milliohm per contact) */ + contact ndc 4 77000 + contact pdc 4 44260 + contact pc 4 16210 + contact m2c 5 86560 + + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.6 micron ---> multiplication factor 0.36 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + /* areacap nfet 556 */ + /* areacap pfet 489 */ + areacap poly,pc/a 22 + areacap allMetal1,DiffMetal,HVDiffMetal 14 + areacap PolyMetal,BiMetal,CCDMetal 14 + areacap allMetal2 9 + + /* Inter-layer capacitance */ + overlap allMetal1 allPoly 24 + overlap allMetal2 allPoly 7 metal1 + overlap metal2 metal1 14 + /* Junction capacitance */ +/* + overlap ndiff,ndc/a space,pwell 106 + overlap pdiff,pdc/a space,nwell 183 +*/ + + /* Perimeter parasitic capacitances (in attofarads per lambda) + [ 1 lambda = 0.6 micron ---> multiplication factor 0.6 ] */ + /* perimc nfet ndiff 90 */ + /* perimc pfet pdiff 817 */ + /* Junction capacitances */ +/* + perimc ndiff,ndc/a space,allWell 102 + perimc pdiff,pdc/a space,allWell 2 +*/ + + /* Active devices: Nwell process, so PMOS has "nwell" defined + for analog designs... */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + /* Kludge for DRAM capacitance extraction */ + fet wcap ndiff,ndc 1 wcap GND! 300 0 + +/* These stuff are experimental..... + fake npn: + fet emit,emc/a pbase 1 d1np XSLLU! nwell 0 0 + fet fpb nwell 1 d2pn YSLLU! col,clc 0 0 + */ + +/* saturation :: R = V (5V) / Idss + fetresist nfet saturation 12000 + fetresist pfet saturation 28000 + fetresist enfet saturation 12000 + fetresist epfet saturation 28000 + + I am not sure how to do this yet, so I give the same value as + saturation! + + fetresist nfet linear 12000 + fetresist pfet linear 28000 + fetresist enfet linear 12000 + fetresist epfet linear 28000 + */ + + +style SCN08(HP) + +/* The following data is obtained from MOSIS run 'n33h', 7/93 */ +/* Last modified by pi@isi.edu, 9/29/93 */ + + cscale 1 + lambda 50 + step 100 + /* Parallel wire coupling capacitance enabled */ + sidehalo 8 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 2280 + resist pdiff,psd,pdc/a,psc/a 1990 + resist poly 3480 + resist allMetal1 67 + resist allMetal2 65 + resist allMetal3 29 + resist nwell 1265560 + + /* Contact resistance (in milliohm per contact) */ + contact pc 4 1680 + contact ndc,pdc,nsc,psc 4 1100 + contact m2c 5 305 + contact m3c 5 259 + + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.5 micron ---> multiplication factor 0.25 ] + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, remove the + following comment. */ + /* areacap nfet 457 */ + /* areacap pfet 403 */ + areacap poly,pc/a 16 + areacap allMetal1,DiffMetal,HVDiffMetal 9 + areacap PolyMetal,BiMetal,CCDMetal 9 + areacap allMetal2 5 + areacap allMetal3 4 + + /* Inter-layer capacitance */ + overlap allMetal1 PNplus 13 + overlap allMetal1 allPoly 13 + overlap allMetal2 PNplus 4 + overlap allMetal2 allPoly 4 + overlap allMetal2 allMetal1 6 + overlap allMetal3 PNplus 2 + overlap allMetal3 allPoly 2 + overlap allMetal3 allMetal1 3 + overlap allMetal3 allMetal2 7 + /* Junction capacitance */ + overlap ndiff,ndc/a space,pwell 27 + overlap pdiff,pdc/a space,nwell 148 + + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.5 micron ---> multiplication factor 0.5 ] */ + perimc allMetal1 space,allWell 43 + perimc allMetal2 space,allWell 36 + perimc allMetal3 space,allWell 36 + + sideoverlap allMetal1 space,allWell allPoly 14 + sideoverlap allMetal2 space,allWell allPoly 5 + /* no such data for m2-to-m1, use data from specification file */ + sideoverlap allMetal2 space,allWell allMetal1 13 + sideoverlap allMetal3 space,allWell allPoly 1 + sideoverlap allMetal3 space,allWell allMetal1 4 + sideoverlap allMetal3 space,allWell allMetal2 13 + + /* Active devices: N-well process */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + +#endif /* TIGHTMETAL */ + +#ifdef IBMTECH +style SCN08(IBM) + +/* The following data is obtained from MOSIS run 'n42s', 1/94 */ +/* Last modified by pi@isi.edu, 6/27/94 */ + + cscale 1 + lambda 40 + step 100 + /* Parallel wire coupling capacitance disabled */ + sidehalo 0 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 3300 + resist pdiff,psd,pdc/a,psc/a 3180 + resist poly 3630 + resist allMetal1 43 + resist allMetal2 36 + resist allMetal3 36 + /* not monitored on PCM, use specification value */ + resist nwell 520000 + + /* Contact resistance (in milliohm per contact) */ + contact ndc,nsc 4 2530 + contact pc 4 7510 + contact pdc,psc 4 2160 + contact m2c 5 330 + contact m3c 5 292 + + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.16 ] */ +#endif /* IBMTECH */ + +#ifdef SUBMICRON +style SCN08(HP26G) + +/* The following data is obtained from MOSIS run 'n48r', 10/94 */ +/* Last modified by pi@isi.edu, 11/02/94 */ + + cscale 1 + lambda 40 + step 100 + /* Parallel wire coupling capacitance enabled */ + sidehalo 8 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 2375 + resist pdiff,psd,pdc/a,psc/a 2000 + resist allPoly 2350 + resist allMetal1 70 + resist allMetal2 67 + resist allMetal3 30 + resist nwell 1265000 + + /* Contact resistance (in milliohm per contact) */ + contact pc 4 1250 + contact ndc,nsc 4 1300 + contact pdc,psc 4 1125 + contact m2c 5 430 + contact m3c 5 300 + + /* The following are 10 types of capacitance extracted: + 1. poly to substrate. + 2. metal1 to substrate. + 3. metal1 to poly. + 4. metal2 to substrate. + 5. metal2 to poly. + 6. metal2 to metal1. + 7. metal3 to substrate. + 8. metal3 to poly. + 9. metal3 to metal1. + 10. metal3 to metal2. + + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, + remove the following comment. */ + /* areacap nfet 334 */ + /* areacap pfet 315 */ + + /* Type 1,2,4,7 (to substrate) */ + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.16 ] */ + areacap poly,pc/a 13 + areacap allMetal1,DiffMetal,HVDiffMetal 6 + areacap PolyMetal,BiMetal,CCDMetal 6 + areacap allMetal2 3 + areacap allMetal3 2 + + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.4 ] */ + perimc poly,pc/a ~(poly,pc/a) 19 + perimc allMetal1 ~(allMetal1) 20 + perimc allMetal2 ~(allMetal2) 16 + perimc allMetal3 ~(allMetal3) 14 + + /* Inter-layer capacitance, type 3,5,6,8,9,10 */ + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.16 ] */ + overlap allMetal1 allPoly 9 + overlap allMetal2 allPoly 3 + overlap allMetal2 allMetal1 5 + overlap allMetal3 allPoly 2 + overlap allMetal3 allMetal1 3 + overlap allMetal3 allMetal2 5 + + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.4 ] */ + sideoverlap allMetal1 space,allWell allPoly 23 + sideoverlap allMetal2 space,allWell allPoly 17 + sideoverlap allMetal2 space,allWell allMetal1 19 + sideoverlap allMetal3 space,allWell allPoly 15 + sideoverlap allMetal3 space,allWell allMetal1 17 + sideoverlap allMetal3 space,allWell allMetal2 21 + + /* Cross-couple capacitance */ + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.4 micron ---> multiplication factor 0.4 ] */ + sidewall allP ~(allP) ~(allP) allP 11 + sidewall allMetal1 ~(allMetal1) ~(allMetal1) allMetal1 24 + sidewall allMetal2 ~(allMetal2) ~(allMetal2) allMetal2 27 + sidewall allMetal3 ~(allMetal3) ~(allMetal3) allMetal3 39 + + /* Active devices: N-well process */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + + +style SCN06(HP14B) + +/* Not yet.... */ +/* Last modified by pi@isi.edu, 03/10/95 */ + + cscale 1 + lambda 30 + step 100 + /* Parallel wire coupling capacitance enabled */ + sidehalo 8 + + /* Define plane order first */ +#ifdef V5 + planeorder well 0 + planeorder implant 1 + planeorder active 2 + planeorder metal1 3 + planeorder metal2 4 + planeorder metal3 5 + planeorder oxide 6 +#endif + + /* Sheet resistance (in milliohms per square) */ + resist ndiff,nsd,ndc/a,nsc/a 2375 + resist pdiff,psd,pdc/a,psc/a 2000 + resist allPoly 2350 + resist allMetal1 70 + resist allMetal2 67 + resist allMetal3 30 + resist nwell 1265000 + + /* Contact resistance (in milliohm per contact) */ + contact pc 4 1250 + contact ndc,nsc 4 1300 + contact pdc,psc 4 1125 + contact m2c 5 430 + contact m3c 5 300 + + /* The following are 10 types of capacitance extracted: + 1. poly to substrate. + 2. metal1 to substrate. + 3. metal1 to poly. + 4. metal2 to substrate. + 5. metal2 to poly. + 6. metal2 to metal1. + 7. metal3 to substrate. + 8. metal3 to poly. + 9. metal3 to metal1. + 10. metal3 to metal2. + + NOTE: Since most of the simulation tools have already + included the gate-oxide capacitance, it is NOT + extracted here. If you need it explictly, + remove the following comment. */ + /* areacap nfet 334 */ + /* areacap pfet 315 */ + + /* Type 1,2,4,7 (to substrate) */ + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.3 micron ---> multiplication factor 0.09 ] */ + areacap poly,pc/a 7 + areacap allMetal1,DiffMetal,HVDiffMetal 3 + areacap PolyMetal,BiMetal,CCDMetal 3 + areacap allMetal2 1 + areacap allMetal3 1 + + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.3 micron ---> multiplication factor 0.3 ] */ + perimc poly,pc/a ~(poly,pc/a) 14 + perimc allMetal1 ~(allMetal1) 15 + perimc allMetal2 ~(allMetal2) 12 + perimc allMetal3 ~(allMetal3) 10 + + /* Inter-layer capacitance, type 3,5,6,8,9,10 */ + /* Area parasitic capacitances (in attofarads per lambda square) + [ 1 lambda = 0.3 micron ---> multiplication factor 0.09 ] */ + overlap allMetal1 allPoly 5 + overlap allMetal2 allPoly 2 + overlap allMetal2 allMetal1 3 + overlap allMetal3 allPoly 1 + overlap allMetal3 allMetal1 1 + overlap allMetal3 allMetal2 3 + + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.3 micron ---> multiplication factor 0.3 ] */ + sideoverlap allMetal1 space,allWell allPoly 17 + sideoverlap allMetal2 space,allWell allPoly 14 + sideoverlap allMetal2 space,allWell allMetal1 15 + sideoverlap allMetal3 space,allWell allPoly 11 + sideoverlap allMetal3 space,allWell allMetal1 13 + sideoverlap allMetal3 space,allWell allMetal2 16 + + /* Cross-couple capacitance */ + /* Perimeter parasitic capacitance (in attofarads per lambda) + [ 1 lambda = 0.3 micron ---> multiplication factor 0.3 ] */ + sidewall allP ~(allP) ~(allP) allP 9 + sidewall allMetal1 ~(allMetal1) ~(allMetal1) allMetal1 19 + sidewall allMetal2 ~(allMetal2) ~(allMetal2) allMetal2 21 + sidewall allMetal3 ~(allMetal3) ~(allMetal3) allMetal3 31 + + /* Active devices: N-well process */ + fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 + fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 + +#endif /* SUBMICRON */ + +#endif /* OLD_EXTRACT_STYLE */ +end + + +wiring + contact pdcontact 4 pdiff 0 metal1 0 + contact ndcontact 4 ndiff 0 metal1 0 + contact pcontact 4 poly 0 metal1 0 + contact ec 6 poly2 0 metal1 0 + contact m2contact 4 metal1 0 metal2 0 + contact m3contact 5 metal2 0 metal3 0 +end + +router + layer1 metal1 3 allMetal1 3 + layer2 metal2 3 allMetal2 4 allPoly,allDiff 1 + contacts m2contact 4 + gridspacing 8 +end + +plowing + fixed allFet,glass,pad + covered allFet + drag allFet +end + +plot + /* based on Jeffrey C. Gealow's (jgealow@mtl.mit.edu) contribution */ + style colorversatec + + ndiff,ndc yellow \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA + + ndiff,ndc cyan \\ + 0000 5555 0000 5555 \\ + 0000 5555 0000 5555 \\ + 0000 5555 0000 5555 \\ + 0000 5555 0000 5555 + + + nsd,nsc,col,clc yellow \\ + 1515 2A2A 5151 A2A2 \\ + 1515 2A2A 5151 A2A2 \\ + 1515 2A2A 5151 A2A2 \\ + 1515 2A2A 5151 A2A2 + + nsd,nsc,col,clc cyan \\ + 0000 1515 0000 5151 \\ + 0000 1515 0000 5151 \\ + 0000 1515 0000 5151 \\ + 0000 1515 0000 5151 + + + pdiff,pdc yellow \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA + + pdiff,pdc cyan \\ + 0000 5555 0000 5555 \\ + 0000 5555 0000 5555 \\ + 0000 5555 0000 5555 \\ + 0000 5555 0000 5555 + + pdiff,pdc magenta \\ + AAAA 0000 AAAA 0000 \\ + AAAA 0000 AAAA 0000 \\ + AAAA 0000 AAAA 0000 \\ + AAAA 0000 AAAA 0000 + + + psd,psc yellow \\ + 1515 2A2A 5151 A2A2 \\ + 1515 2A2A 5151 A2A2 \\ + 1515 2A2A 5151 A2A2 \\ + 1515 2A2A 5151 A2A2 + + psd,psc cyan \\ + 0000 1515 0000 5151 \\ + 0000 1515 0000 5151 \\ + 0000 1515 0000 5151 \\ + 0000 1515 0000 5151 + + psd,psc magenta \\ + 2A2A 0000 A2A2 0000 \\ + 2A2A 0000 A2A2 0000 \\ + 2A2A 0000 A2A2 0000 \\ + 2A2A 0000 A2A2 0000 + + + poly,pc/a magenta \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA + + + poly2,ec/a yellow \\ + FFFF FFFF FFFF FFFF \\ + FFFF FFFF FFFF FFFF \\ + FFFF FFFF FFFF FFFF \\ + FFFF FFFF FFFF FFFF + + + nfet yellow \\ + 0505 8282 1414 0A0A \\ + 5050 2828 4141 A0A0 \\ + 0505 8282 1414 0A0A \\ + 5050 2828 4141 A0A0 + + nfet cyan \\ + 0000 0505 0000 1414 \\ + 0000 5050 0000 4141 \\ + 0000 0505 0000 1414 \\ + 0000 5050 0000 4141 + + nfet magenta \\ + 5050 2828 4141 A0A0 \\ + 0505 8282 1414 0A0A \\ + 5050 2828 4141 A0A0 \\ + 0505 8282 1414 0A0A + + + enfet yellow \\ + BABA 7575 EAEA D5D5 \\ + ABAB 5757 AEAE 5D5D \\ + BABA 7575 EAEA D5D5 \\ + ABAB 5757 AEAE 5D5D + + enfet cyan \\ + 4141 0A0A 0505 2828 \\ + 1414 A0A0 5050 8282 \\ + 4141 0A0A 0505 2828 \\ + 1414 A0A0 5050 8282 + + + nffet yellow \\ + 8E8E 0707 8B8B D5D5 \\ + E8E8 7070 B8B8 5D5D \\ + 8E8E 0707 8B8B D5D5 \\ + E8E8 7070 B8B8 5D5D + + nffet cyan \\ + 0101 0808 1414 2828 \\ + 1010 8080 4141 8282 \\ + 0101 0808 1414 2828 \\ + 1010 8080 4141 8282 + + nffet magenta \\ + 5050 A0A0 4040 0202 \\ + 0505 0A0A 0404 2020 \\ + 5050 A0A0 4040 0202 \\ + 0505 0A0A 0404 2020 + + + pfet yellow \\ + 6363 A0A0 5050 2828 \\ + 3636 0A0A 0505 8282 \\ + 6363 A0A0 5050 2828 \\ + 3636 0A0A 0505 8282 + + pfet cyan \\ + 0000 5151 0000 5454 \\ + 0000 1515 0000 1515 \\ + 0000 5151 0000 5454 \\ + 0000 1515 0000 1515 + + pfet magenta \\ + 9494 0A0A 2525 8282 \\ + 4949 A0A0 5252 2828 \\ + 9494 0A0A 2525 8282 \\ + 4949 A0A0 5252 2828 + + + epfet yellow \\ + BCBC 4F4F 2F2F D3D3 \\ + CBCB F4F4 F2F2 3D3D \\ + BCBC 4F4F 2F2F D3D3 \\ + CBCB F4F4 F2F2 3D3D + + epfet cyan \\ + 0000 A0A0 0000 2828 \\ + 0000 0A0A 0000 8282 \\ + 0000 A0A0 0000 2828 \\ + 0000 0A0A 0000 8282 + + epfet magenta \\ + 4141 0000 5050 0000 \\ + 1414 0000 0505 0000 \\ + 4141 0000 5050 0000 \\ + 1414 0000 0505 0000 + + + pffet yellow \\ + 7B7B F0F0 F0F0 E9E9 \\ + B7B7 0F0F 0F0F 9E9E \\ + 7B7B F0F0 F0F0 E9E9 \\ + B7B7 0F0F 0F0F 9E9E + + pffet cyan \\ + 0000 0101 0000 1414 \\ + 0000 1010 0000 4141 \\ + 0000 0101 0000 1414 \\ + 0000 1010 0000 4141 + + pffet magenta \\ + 8484 0A0A 2525 8282 \\ + 4848 A0A0 5252 2828 \\ + 8484 0A0A 2525 8282 \\ + 4848 A0A0 5252 2828 + + + cap,cc/a yellow \\ + 3E3E 7777 E3E3 C1C1 \\ + E3E3 7777 3E3E 1C1C \\ + 3E3E 7777 E3E3 C1C1 \\ + E3E3 7777 3E3E 1C1C + + cap,cc/a magenta \\ + 4141 8888 1414 2A2A \\ + 1414 8888 4141 A2A2 \\ + 4141 8888 1414 2A2A \\ + 1414 8888 4141 A2A2 + + + allMetal1 cyan \\ + AAAA 0000 AAAA 0000 \\ + AAAA 0000 AAAA 0000 \\ + AAAA 0000 AAAA 0000 \\ + AAAA 0000 AAAA 0000 + + + allMetal2 cyan \\ + 0000 1111 0000 4444 \\ + 0000 1111 0000 4444 \\ + 0000 1111 0000 4444 \\ + 0000 1111 0000 4444 + + allMetal2 magenta \\ + 0000 4444 0000 1111 \\ + 0000 4444 0000 1111 \\ + 0000 4444 0000 1111 \\ + 0000 4444 0000 1111 + + + m2c/m1 black \\ + 0000 6666 6666 0000 \\ + 0000 9999 9999 0000 \\ + 0000 6666 6666 0000 \\ + 0000 9999 9999 0000 + + + pad,glass black \\ + 0300 0700 0E00 1C00 \\ + 3800 7000 E000 C000 \\ + 00C0 00E0 0070 0038 \\ + 001C 000E 0007 0003 + + + nwell yellow \\ + 0800 1000 2000 4000 \\ + 8000 0001 0002 0004 \\ + 0008 0010 0020 0040 \\ + 0080 0010 0200 0400 + + nwell cyan \\ + 1000 2000 4000 8000 \\ + 0001 0002 0004 0008 \\ + 0010 0020 0040 0080 \\ + 0100 0200 0400 0800 + + + pwell yellow \\ + 1000 0400 0400 0100 \\ + 0100 0040 0040 0010 \\ + 0010 0004 0004 0001 \\ + 0001 4000 4000 1000 + + pwell cyan \\ + 0000 0800 0000 0200 \\ + 0000 0080 0000 0020 \\ + 0000 0008 0000 0002 \\ + 0000 8000 0000 2000 + + pwell magenta \\ + 0800 0000 0200 0000 \\ + 0080 0000 0020 0000 \\ + 0008 0000 0002 0000 \\ + 8000 0000 2000 0000 + + + bd yellow \\ + 4444 8888 4444 8888 \\ + 4444 8888 4444 8888 \\ + 4444 8888 4444 8888 \\ + 4444 8888 4444 8888 + + bd cyan \\ + 0000 4444 0000 4444 \\ + 0000 4444 0000 4444 \\ + 0000 4444 0000 4444 \\ + 0000 4444 0000 4444 + + bd magenta \\ + 8888 0000 8888 0000 \\ + 8888 0000 8888 0000 \\ + 8888 0000 8888 0000 \\ + 8888 0000 8888 0000 + + + nbd,nbdc yellow \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA \\ + 5555 AAAA 5555 AAAA + + nbd,nbdc cyan \\ + 0000 5555 0000 5555 \\ + 0000 5555 0000 5555 \\ + 0000 5555 0000 5555 \\ + 0000 5555 0000 5555 + + nbd,nbdc magenta \\ + 8888 0000 8888 0000 \\ + 8888 0000 8888 0000 \\ + 8888 0000 8888 0000 \\ + 8888 0000 8888 0000 + + + em,emc yellow \\ + 4444 8888 4444 8888 \\ + 4444 8888 4444 8888 \\ + 4444 8888 4444 8888 \\ + 4444 8888 4444 8888 + + em,emc cyan \\ + 0000 4444 0000 4444 \\ + 0000 4444 0000 4444 \\ + 0000 4444 0000 4444 \\ + 0000 4444 0000 4444 + + + pbase,pbc yellow \\ + 5555 AAAA 0000 0000 \\ + 5555 AAAA 0000 0000 \\ + 5555 AAAA 0000 0000 \\ + 5555 AAAA 0000 0000 + + pbase,pbc cyan \\ + 0000 5555 0000 0000 \\ + 0000 5555 0000 0000 \\ + 0000 5555 0000 0000 \\ + 0000 5555 0000 0000 + + pbase,pbc magenta \\ + AAAA 0000 0000 0000 \\ + AAAA 0000 0000 0000 \\ + AAAA 0000 0000 0000 \\ + AAAA 0000 0000 0000 + + + allMetal3 black \\ + 0100 0000 0000 0000 \\ + 1010 0000 0000 0000 \\ + 0001 0000 0000 0000 \\ + 1010 0000 0000 0000 + + allMetal3 cyan \\ + 0280 0000 0820 0000 \\ + 2008 0000 8002 0000 \\ + 8002 0000 2008 0000 \\ + 0820 0000 0280 0000 + + allMetal3 magenta \\ + 0100 06C0 0440 1830 \\ + 1010 600C 4004 8003 \\ + 0001 C006 4004 3018 \\ + 1010 0C60 0440 0380 + + + m3c/m2 black \\ + 0820 0820 0820 0FE0 \\ + E00F 2008 2008 2008 \\ + 2008 2008 2008 E00F \\ + 0000 0FE0 0820 0820 + + + error_p,error_s,error_ps black \\ + 0000 3C3C 4646 4A4A \\ + 5252 6262 3C3C 0000 \\ + 0000 3C3C 4646 4A4A \\ + 5252 6262 3C3C 0000 + + + magnet yellow \\ + AAAA 0000 5555 0000 \\ + AAAA 0000 5555 0000 \\ + AAAA 0000 5555 0000 \\ + AAAA 0000 5555 0000 + + + fence magenta \\ + FFFF 0000 0000 0000 \\ + 0000 0000 0000 0000 \\ + FFFF 0000 0000 0000 \\ + 0000 0000 0000 0000 + + + rotate cyan \\ + 0000 E0E0 E0E0 E0E0 \\ + 0000 0000 0000 0000 \\ + 0000 E0E0 E0E0 E0E0 \\ + 0000 0000 0000 0000 + + + allCut,BiCut X + + + style versatec + + pfet \\ + 07c0 0f80 1f00 3e00 \\ + 7c00 f800 f001 e003 \\ + c007 800f 001f 003e \\ + 00c7 00f8 01f0 03e0 + + + nfet \\ + 1f00 0f80 07c0 03e0 \\ + 01f0 00f8 007c 003e \\ + 001f 800f c007 e003 \\ + f001 f800 7c00 3e00 + + + m2c \\ + c3c3 c3c3 0000 0000 \\ + 0000 0000 c3c3 c3c3 \\ + c3c3 c3c3 0000 0000 \\ + 0000 0000 c3c3 c3c3 + + + pwell \\ + 2020 2020 2020 2020 \\ + 2020 2020 2020 2020 \\ + 0000 0000 0000 0000 \\ + 0000 0000 0000 0000 + + + nwell \\ + 0808 0404 0202 0101 \\ + 0000 0000 0000 0000 \\ + 0808 0404 0202 0101 \\ + 0000 0000 0000 0000 + + + allPoly \\ + 0808 0400 0202 0101 \\ + 8080 4000 2020 1010 \\ + 0808 0004 0202 0101 \\ + 8080 0040 2020 1010 + + + allMetal1 \\ + 8080 0000 0000 0000 \\ + 0808 0000 0000 0000 \\ + 8080 0000 0000 0000 \\ + 0808 0000 0000 0000 + + + pad,glass \\ + 0000 0000 1c1c 3e3e \\ + 3636 3e3e 1c1c 0000 \\ + 0000 0000 1c1c 3e3e \\ + 3636 3e3e 1c1c 0000 + + + nsd,nsc,col,clc \\ + 0808 1414 2222 4141 \\ + 8080 4040 2020 1010 \\ + 0808 1414 2222 4141 \\ + 8080 4040 2020 1010 + + + allMetal2 \\ + 0000 1111 0000 0000 \\ + 0000 1111 0000 0000 \\ + 0000 1111 0000 0000 \\ + 0000 1111 0000 0000 + + + pdiff,pdc,pfet \\ + 0000 0808 5555 8080 \\ + 0000 8080 5555 0808 \\ + 0000 0808 5555 8080 \\ + 0000 8080 5555 0808 + + + psd,psc \\ + 1414 2222 0000 2222 \\ + 4141 2222 0000 2222 \\ + 1414 2222 0000 2222 \\ + 4141 2222 0000 2222 + + + ndiff,nfet,ndc \\ + 0808 1010 2020 4040 \\ + 8080 4141 2222 1414 \\ + 0808 1010 2020 4040 \\ + 8080 4141 2222 1414 + + + allPoly2 \\ + 0000 2020 5050 2020 \\ + 0000 0202 0505 0202 \\ + 0000 2020 5050 2020 \\ + 0000 0202 0505 0202 + + + allCut,BiCut X + +/* -------------------------------------------------------------- */ + style gremlin + pfet 9 + nfet 10 + m2c 11 + pwell 15 + nwell 16 + allPoly 19 + allMetal1 22 + pad,glass 23 + nsd,nsc 24 + allMetal2 28 + pdiff,pdc,pfet 29 + psd,psc 30 + ndiff,nfet,ndc 31 + m2c/m1,pc/m1,ndc/m1,pdc/m1,psc/m1,nsc/m1,pad/m1 X +/* -------------------------------------------------------------- */ + style postscript +/* + * stipple definitions for 32x8 bitmaps + * # row1 row2 row3 row4 row5 row6 row7 row8 + */ + 1 C0C0C0C0 C0C0C0C0 00000000 00000000 0C0C0C0C 0C0C0C0C 00000000 00000000 + 2 A0A0A0A0 0A0A0A0A A0A0A0A0 0A0A0A0A A0A0A0A0 0A0A0A0A A0A0A0A0 0A0A0A0A + 3 00030003 000C000C 00300030 00C000C0 03000300 0C000C00 30003000 C000C000 + 4 00000000 00000000 C0C0C0C0 00000000 00000000 00000000 0C0C0C0C 00000000 + 5 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF + 6 07070707 0E0E0E0E 1C1C1C1C 38383838 70707070 E0E0E0E0 C1C1C1C1 83838383 + 7 18181818 30303030 60606060 C0C0C0C0 81818181 03030303 06060606 0C0C0C0C + 8 18181818 0C0C0C0C 06060606 03030303 81818181 C0C0C0C0 60606060 30303030 + 9 18181818 3C3C3C3C 3C3C3C3C 18181818 81818181 C3C3C3C3 C3C3C3C3 81818181 + 10 F0F0F0F0 60606060 06060606 0F0F0F0F 0F0F0F0F 06060606 60606060 F0F0F0F0 + 11 01000080 02000040 0C000030 F000000F 000FF000 00300C00 00400200 00800100 + 12 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 + 13 00000000 00000000 33333333 33333333 00000000 00000000 CCCCCCCC CCCCCCCC +/* + * color definitions in CMYK format + * # C M Y K closest named color in RGB space + */ + 1 47 95 111 0 /* RosyBrown3 */ + 2 223 31 223 0 /* limegreen */ + 3 0 0 0 192 /* gray25 */ + 4 31 111 31 0 /* plum */ + 5 31 111 255 0 /* orange2 */ + 6 63 95 191 0 /* goldenrod3 */ + 7 255 63 255 0 /* green3 */ + 8 0 0 0 127 /* gray50 */ + 9 223 47 223 0 /* limegreen */ + 10 0 255 255 0 /* red */ + 11 0 0 255 0 /* yellow */ + 12 191 127 0 0 /* RoyalBlue1 */ + 13 95 223 63 0 /* DarkOrchid3 */ + 14 0 0 0 255 /* black */ + 15 191 127 63 0 /* steelblue */ + 16 111 151 244 0 /* goldenrod4 */ + 17 23 175 183 0 /* tomato2 */ +/* + * magic layer definitions (plotted top to bottom) + * layer(s) color# stipple# (plus B=box, X=cross & box) + */ + cc,pc,ndc,pdc,psc,nsc 14 X + m2c,pad,glass 14 B + pad,glass 14 11 + m2c 14 13 + m2,m2c,pad 13 10 + pdc,ndc,psc,nsc,hpdc,hndc,hpsc,hnsc,pc,ec,capc,clc,emc,pbc,nbdc,m1,m2c,gc 12 9 + cap,cc,poly2 11 7 + nsd,nsc 7 1 + psd,psc 6 1 + nfet,nffet 9 8 + pfet,wcap,pffet 1 7 + poly,pc,cap,cc 10 5 + nfet 16 5 + pfet,wcap 17 5 + pdiff,pdc,pffet 1 5 + ndiff,ndc,nffet 9 5 + pwell 1 4 + nwell 2 4 + +/* ------------------------------------------------------------------------ */ + style pnm + draw metal1 + draw metal2 + draw polysilicon + draw ndiffusion + draw pdiffusion + draw ntransistor + draw ptransistor + map psubstratepdiff pdiffusion + map nsubstratendiff ndiffusion + map polycontact polysilicon metal1 + map m2contact metal1 metal2 + map m3contact metal2 metal3 + map ndcontact ndiffusion metal1 + map pdcontact pdiffusion metal1 + map nsubstratencontact ndiffusion metal1 + map psubstratepcontact pdiffusion metal1 + +end diff --git a/scripts/config.guess b/scripts/config.guess new file mode 100755 index 00000000..dc84c68e --- /dev/null +++ b/scripts/config.guess @@ -0,0 +1,1501 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-11-20' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/scripts/config.log b/scripts/config.log new file mode 100644 index 00000000..cbc6f0ce --- /dev/null +++ b/scripts/config.log @@ -0,0 +1,905 @@ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by configure, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ ./configure + +## --------- ## +## Platform. ## +## --------- ## + +hostname = stravinsky +uname -m = x86_64 +uname -r = 3.18.3-201.fc21.x86_64 +uname -s = Linux +uname -v = #1 SMP Mon Jan 19 15:59:31 UTC 2015 + +/usr/bin/uname -p = x86_64 +/bin/uname -X = unknown + +/bin/arch = x86_64 +/usr/bin/arch -k = unknown +/usr/convex/getsysinfo = unknown +/usr/bin/hostinfo = unknown +/bin/machine = unknown +/usr/bin/oslevel = unknown +/bin/universe = unknown + +PATH: . +PATH: /bin +PATH: /sbin +PATH: /usr/bin +PATH: /usr/sbin +PATH: /usr/local/bin + + +## ----------- ## +## Core tests. ## +## ----------- ## + +configure:2479: checking build system type +configure:2493: result: x86_64-unknown-linux-gnu +configure:2513: checking host system type +configure:2526: result: x86_64-unknown-linux-gnu +configure:2546: checking target system type +configure:2559: result: x86_64-unknown-linux-gnu +configure:2651: checking for gcc +configure:2667: found /bin/gcc +configure:2678: result: gcc +configure:2907: checking for C compiler version +configure:2916: gcc --version >&5 +gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6) +Copyright (C) 2014 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +configure:2927: $? = 0 +configure:2916: gcc -v >&5 +Using built-in specs. +COLLECT_GCC=gcc +COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.9.2/lto-wrapper +Target: x86_64-redhat-linux +Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux +Thread model: posix +gcc version 4.9.2 20150212 (Red Hat 4.9.2-6) (GCC) +configure:2927: $? = 0 +configure:2916: gcc -V >&5 +gcc: error: unrecognized command line option '-V' +gcc: fatal error: no input files +compilation terminated. +configure:2927: $? = 4 +configure:2916: gcc -qversion >&5 +gcc: error: unrecognized command line option '-qversion' +gcc: fatal error: no input files +compilation terminated. +configure:2927: $? = 4 +configure:2947: checking whether the C compiler works +configure:2969: gcc -g conftest.c >&5 +configure:2973: $? = 0 +configure:3021: result: yes +configure:3024: checking for C compiler default output file name +configure:3026: result: a.out +configure:3032: checking for suffix of executables +configure:3039: gcc -o conftest -g conftest.c >&5 +configure:3043: $? = 0 +configure:3065: result: +configure:3087: checking whether we are cross compiling +configure:3095: gcc -o conftest -g conftest.c >&5 +configure:3099: $? = 0 +configure:3106: ./conftest +configure:3110: $? = 0 +configure:3125: result: no +configure:3130: checking for suffix of object files +configure:3152: gcc -c -g conftest.c >&5 +configure:3156: $? = 0 +configure:3177: result: o +configure:3181: checking whether we are using the GNU C compiler +configure:3200: gcc -c -g conftest.c >&5 +configure:3200: $? = 0 +configure:3209: result: yes +configure:3218: checking whether gcc accepts -g +configure:3238: gcc -c -g conftest.c >&5 +configure:3238: $? = 0 +configure:3279: result: yes +configure:3296: checking for gcc option to accept ISO C89 +configure:3359: gcc -c -g conftest.c >&5 +configure:3359: $? = 0 +configure:3372: result: none needed +configure:3397: checking how to run the C preprocessor +configure:3428: gcc -E conftest.c +configure:3428: $? = 0 +configure:3442: gcc -E conftest.c +conftest.c:11:28: fatal error: ac_nonexistent.h: No such file or directory + #include + ^ +compilation terminated. +configure:3442: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define MAGIC_VERSION "8.1" +| #define MAGIC_REVISION "151" +| /* end confdefs.h. */ +| #include +configure:3467: result: gcc -E +configure:3487: gcc -E conftest.c +configure:3487: $? = 0 +configure:3501: gcc -E conftest.c +conftest.c:11:28: fatal error: ac_nonexistent.h: No such file or directory + #include + ^ +compilation terminated. +configure:3501: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define MAGIC_VERSION "8.1" +| #define MAGIC_REVISION "151" +| /* end confdefs.h. */ +| #include +configure:3587: checking for g++ +configure:3603: found /bin/g++ +configure:3614: result: g++ +configure:3641: checking for C++ compiler version +configure:3650: g++ --version >&5 +g++ (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6) +Copyright (C) 2014 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +configure:3661: $? = 0 +configure:3650: g++ -v >&5 +Using built-in specs. +COLLECT_GCC=g++ +COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.9.2/lto-wrapper +Target: x86_64-redhat-linux +Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux +Thread model: posix +gcc version 4.9.2 20150212 (Red Hat 4.9.2-6) (GCC) +configure:3661: $? = 0 +configure:3650: g++ -V >&5 +g++: error: unrecognized command line option '-V' +g++: fatal error: no input files +compilation terminated. +configure:3661: $? = 4 +configure:3650: g++ -qversion >&5 +g++: error: unrecognized command line option '-qversion' +g++: fatal error: no input files +compilation terminated. +configure:3661: $? = 4 +configure:3665: checking whether we are using the GNU C++ compiler +configure:3684: g++ -c conftest.cpp >&5 +configure:3684: $? = 0 +configure:3693: result: yes +configure:3702: checking whether g++ accepts -g +configure:3722: g++ -c -g conftest.cpp >&5 +configure:3722: $? = 0 +configure:3763: result: yes +configure:3787: checking for library containing strerror +configure:3818: gcc -o conftest -g conftest.c >&5 +configure:3818: $? = 0 +configure:3835: result: none required +configure:3857: checking for a BSD-compatible install +configure:3925: result: /bin/install -c +configure:3979: checking for ranlib +configure:3995: found /bin/ranlib +configure:4006: result: ranlib +configure:4033: checking for gm4 +configure:4066: result: no +configure:4033: checking for gnum4 +configure:4066: result: no +configure:4033: checking for m4 +configure:4051: found /bin/m4 +configure:4063: result: /bin/m4 +configure:4104: checking for ld used by GCC +configure:4167: result: /bin/ld +configure:4174: checking if the linker (/bin/ld) is GNU ld +GNU ld version 2.24 +configure:4186: result: yes +configure:4193: checking for grep that handles long lines and -e +configure:4251: result: /bin/grep +configure:4256: checking for egrep +configure:4318: result: /bin/grep -E +configure:4323: checking for ANSI C header files +configure:4343: gcc -c -g conftest.c >&5 +configure:4343: $? = 0 +configure:4416: gcc -o conftest -g conftest.c >&5 +configure:4416: $? = 0 +configure:4416: ./conftest +configure:4416: $? = 0 +configure:4427: result: yes +configure:4440: checking for sys/types.h +configure:4440: gcc -c -g conftest.c >&5 +configure:4440: $? = 0 +configure:4440: result: yes +configure:4440: checking for sys/stat.h +configure:4440: gcc -c -g conftest.c >&5 +configure:4440: $? = 0 +configure:4440: result: yes +configure:4440: checking for stdlib.h +configure:4440: gcc -c -g conftest.c >&5 +configure:4440: $? = 0 +configure:4440: result: yes +configure:4440: checking for string.h +configure:4440: gcc -c -g conftest.c >&5 +configure:4440: $? = 0 +configure:4440: result: yes +configure:4440: checking for memory.h +configure:4440: gcc -c -g conftest.c >&5 +configure:4440: $? = 0 +configure:4440: result: yes +configure:4440: checking for strings.h +configure:4440: gcc -c -g conftest.c >&5 +configure:4440: $? = 0 +configure:4440: result: yes +configure:4440: checking for inttypes.h +configure:4440: gcc -c -g conftest.c >&5 +configure:4440: $? = 0 +configure:4440: result: yes +configure:4440: checking for stdint.h +configure:4440: gcc -c -g conftest.c >&5 +configure:4440: $? = 0 +configure:4440: result: yes +configure:4440: checking for unistd.h +configure:4440: gcc -c -g conftest.c >&5 +configure:4440: $? = 0 +configure:4440: result: yes +configure:4456: checking size of void * +configure:4461: gcc -o conftest -g conftest.c >&5 +configure:4461: $? = 0 +configure:4461: ./conftest +configure:4461: $? = 0 +configure:4475: result: 8 +configure:4489: checking size of unsigned int +configure:4494: gcc -o conftest -g conftest.c >&5 +configure:4494: $? = 0 +configure:4494: ./conftest +configure:4494: $? = 0 +configure:4508: result: 4 +configure:4522: checking size of unsigned long +configure:4527: gcc -o conftest -g conftest.c >&5 +configure:4527: $? = 0 +configure:4527: ./conftest +configure:4527: $? = 0 +configure:4541: result: 8 +configure:4555: checking size of unsigned long long +configure:4560: gcc -o conftest -g conftest.c >&5 +configure:4560: $? = 0 +configure:4560: ./conftest +configure:4560: $? = 0 +configure:4574: result: 8 +configure:4585: checking whether byte ordering is bigendian +configure:4600: gcc -c -g conftest.c >&5 +conftest.c:26:9: error: unknown type name 'not' + not a universal capable compiler + ^ +conftest.c:26:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'universal' + not a universal capable compiler + ^ +conftest.c:26:15: error: unknown type name 'universal' +configure:4600: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define MAGIC_VERSION "8.1" +| #define MAGIC_REVISION "151" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define SIZEOF_VOID_P 8 +| #define SIZEOF_UNSIGNED_INT 4 +| #define SIZEOF_UNSIGNED_LONG 8 +| #define SIZEOF_UNSIGNED_LONG_LONG 8 +| /* end confdefs.h. */ +| #ifndef __APPLE_CC__ +| not a universal capable compiler +| #endif +| typedef int dummy; +| +configure:4645: gcc -c -g conftest.c >&5 +configure:4645: $? = 0 +configure:4663: gcc -c -g conftest.c >&5 +conftest.c: In function 'main': +conftest.c:32:4: error: unknown type name 'not' + not big endian + ^ +conftest.c:32:12: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'endian' + not big endian + ^ +configure:4663: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define MAGIC_VERSION "8.1" +| #define MAGIC_REVISION "151" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define SIZEOF_VOID_P 8 +| #define SIZEOF_UNSIGNED_INT 4 +| #define SIZEOF_UNSIGNED_LONG 8 +| #define SIZEOF_UNSIGNED_LONG_LONG 8 +| /* end confdefs.h. */ +| #include +| #include +| +| int +| main () +| { +| #if BYTE_ORDER != BIG_ENDIAN +| not big endian +| #endif +| +| ; +| return 0; +| } +configure:4791: result: no +configure:4810: checking for ANSI C header files +configure:4914: result: yes +configure:4926: checking for setenv +configure:4926: gcc -o conftest -g conftest.c >&5 +configure:4926: $? = 0 +configure:4926: result: yes +configure:4926: checking for putenv +configure:4926: gcc -o conftest -g conftest.c >&5 +configure:4926: $? = 0 +configure:4926: result: yes +configure:4936: checking for vfork +configure:4936: gcc -o conftest -g conftest.c >&5 +configure:4936: $? = 0 +configure:4936: result: yes +configure:4944: checking sys/mman.h usability +configure:4944: gcc -c -g conftest.c >&5 +configure:4944: $? = 0 +configure:4944: result: yes +configure:4944: checking sys/mman.h presence +configure:4944: gcc -E -x c conftest.c +configure:4944: $? = 0 +configure:4944: result: yes +configure:4944: checking for sys/mman.h +configure:4944: result: yes +configure:4957: checking dirent.h usability +configure:4957: gcc -c -g conftest.c >&5 +configure:4957: $? = 0 +configure:4957: result: yes +configure:4957: checking dirent.h presence +configure:4957: gcc -E -x c conftest.c +configure:4957: $? = 0 +configure:4957: result: yes +configure:4957: checking for dirent.h +configure:4957: result: yes +configure:4970: checking limits.h usability +configure:4970: gcc -c -g conftest.c >&5 +configure:4970: $? = 0 +configure:4970: result: yes +configure:4970: checking limits.h presence +configure:4970: gcc -E -x c conftest.c +configure:4970: $? = 0 +configure:4970: result: yes +configure:4970: checking for limits.h +configure:4970: result: yes +configure:4983: checking param.h usability +configure:4983: gcc -c -g conftest.c >&5 +conftest.c:64:19: fatal error: param.h: No such file or directory + #include + ^ +compilation terminated. +configure:4983: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define MAGIC_VERSION "8.1" +| #define MAGIC_REVISION "151" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define SIZEOF_VOID_P 8 +| #define SIZEOF_UNSIGNED_INT 4 +| #define SIZEOF_UNSIGNED_LONG 8 +| #define SIZEOF_UNSIGNED_LONG_LONG 8 +| #define STDC_HEADERS 1 +| #define HAVE_SETENV 1 +| #define HAVE_PUTENV 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_DIRENT_H 1 +| #define HAVE_LIMITS_H 1 +| /* end confdefs.h. */ +| #include +| #ifdef HAVE_SYS_TYPES_H +| # include +| #endif +| #ifdef HAVE_SYS_STAT_H +| # include +| #endif +| #ifdef STDC_HEADERS +| # include +| # include +| #else +| # ifdef HAVE_STDLIB_H +| # include +| # endif +| #endif +| #ifdef HAVE_STRING_H +| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H +| # include +| # endif +| # include +| #endif +| #ifdef HAVE_STRINGS_H +| # include +| #endif +| #ifdef HAVE_INTTYPES_H +| # include +| #endif +| #ifdef HAVE_STDINT_H +| # include +| #endif +| #ifdef HAVE_UNISTD_H +| # include +| #endif +| #include +configure:4983: result: no +configure:4983: checking param.h presence +configure:4983: gcc -E -x c conftest.c +conftest.c:31:19: fatal error: param.h: No such file or directory + #include + ^ +compilation terminated. +configure:4983: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define MAGIC_VERSION "8.1" +| #define MAGIC_REVISION "151" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define SIZEOF_VOID_P 8 +| #define SIZEOF_UNSIGNED_INT 4 +| #define SIZEOF_UNSIGNED_LONG 8 +| #define SIZEOF_UNSIGNED_LONG_LONG 8 +| #define STDC_HEADERS 1 +| #define HAVE_SETENV 1 +| #define HAVE_PUTENV 1 +| #define HAVE_SYS_MMAN_H 1 +| #define HAVE_DIRENT_H 1 +| #define HAVE_LIMITS_H 1 +| /* end confdefs.h. */ +| #include +configure:4983: result: no +configure:4983: checking for param.h +configure:4983: result: no +configure:4996: checking paths.h usability +configure:4996: gcc -c -g conftest.c >&5 +configure:4996: $? = 0 +configure:4996: result: yes +configure:4996: checking paths.h presence +configure:4996: gcc -E -x c conftest.c +configure:4996: $? = 0 +configure:4996: result: yes +configure:4996: checking for paths.h +configure:4996: result: yes +configure:5007: checking for va_copy +configure:5025: gcc -o conftest -g conftest.c >&5 +configure:5025: $? = 0 +configure:5034: result: yes +configure:5042: checking for __va_copy +configure:5060: gcc -o conftest -g conftest.c >&5 +configure:5060: $? = 0 +configure:5069: result: yes +configure:5283: checking for gcore +configure:5301: found /bin/gcore +configure:5314: result: /bin/gcore +configure:5326: checking for csh +configure:5344: found /bin/csh +configure:5357: result: /bin/csh +configure:5371: checking for X +configure:5510: gcc -o conftest -g conftest.c -lX11 >&5 +configure:5510: $? = 0 +configure:5560: result: libraries , headers +configure:5659: gcc -o conftest -g conftest.c -lX11 >&5 +configure:5659: $? = 0 +configure:5757: checking for gethostbyname +configure:5757: gcc -o conftest -g conftest.c >&5 +configure:5757: $? = 0 +configure:5757: result: yes +configure:5854: checking for connect +configure:5854: gcc -o conftest -g conftest.c >&5 +configure:5854: $? = 0 +configure:5854: result: yes +configure:5903: checking for remove +configure:5903: gcc -o conftest -g conftest.c >&5 +configure:5903: $? = 0 +configure:5903: result: yes +configure:5952: checking for shmat +configure:5952: gcc -o conftest -g conftest.c >&5 +configure:5952: $? = 0 +configure:5952: result: yes +configure:6010: checking for IceConnectionNumber in -lICE +configure:6035: gcc -o conftest -g conftest.c -lICE >&5 +configure:6035: $? = 0 +configure:6044: result: yes +configure:6076: checking for XOpenDevice in -lXi +configure:6101: gcc -o conftest -g conftest.c -lXi >&5 +configure:6101: $? = 0 +configure:6110: result: yes +configure:6116: checking for XmuInternAtom in -lXmu +configure:6141: gcc -o conftest -g conftest.c -lXmu >&5 +configure:6141: $? = 0 +configure:6150: result: yes +configure:6156: checking for XextFindDisplay in -lXext +configure:6181: gcc -o conftest -g conftest.c -lXext >&5 +configure:6181: $? = 0 +configure:6190: result: yes +configure:6270: checking for tclConfig.sh +configure:6344: result: /usr/lib64/tclConfig.sh +configure:6360: checking for tkConfig.sh +configure:6433: result: /usr/lib64/tkConfig.sh +configure:6567: checking for wish executable +configure:6595: result: /usr/bin/wish +configure:6601: checking for tclsh executable +configure:6627: result: /usr/bin/tclsh +configure:7332: checking GL/gl.h usability +configure:7332: gcc -c -g conftest.c >&5 +configure:7332: $? = 0 +configure:7332: result: yes +configure:7332: checking GL/gl.h presence +configure:7332: gcc -E -x c conftest.c +configure:7332: $? = 0 +configure:7332: result: yes +configure:7332: checking for GL/gl.h +configure:7332: result: yes +configure:7350: checking for glXCreateContext in -lGL +configure:7375: gcc -o conftest -g -lm conftest.c -lGL >&5 +configure:7375: $? = 0 +configure:7384: result: yes +configure:7400: checking for gluNewTess in -lGLU +configure:7425: gcc -o conftest -g -lm conftest.c -lGLU -lGL >&5 +configure:7425: $? = 0 +configure:7434: result: yes +configure:8207: creating ./config.status + +## ---------------------- ## +## Running config.status. ## +## ---------------------- ## + +This file was extended by config.status, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = + CONFIG_HEADERS = + CONFIG_LINKS = + CONFIG_COMMANDS = + $ ./config.status + +on stravinsky + +config.status:796: creating defs.mak +config.status:899: WARNING: 'defs.mak.in' seems to ignore the --datarootdir setting + +## ---------------- ## +## Cache variables. ## +## ---------------- ## + +ac_cv_build=x86_64-unknown-linux-gnu +ac_cv_c___va_copy=yes +ac_cv_c_bigendian=no +ac_cv_c_compiler_gnu=yes +ac_cv_c_va_copy=yes +ac_cv_cxx_compiler_gnu=yes +ac_cv_env_CCC_set= +ac_cv_env_CCC_value= +ac_cv_env_CC_set= +ac_cv_env_CC_value= +ac_cv_env_CFLAGS_set=set +ac_cv_env_CFLAGS_value=-g +ac_cv_env_CPPFLAGS_set= +ac_cv_env_CPPFLAGS_value= +ac_cv_env_CPP_set= +ac_cv_env_CPP_value= +ac_cv_env_CXXFLAGS_set= +ac_cv_env_CXXFLAGS_value= +ac_cv_env_CXX_set= +ac_cv_env_CXX_value= +ac_cv_env_LDFLAGS_set= +ac_cv_env_LDFLAGS_value= +ac_cv_env_LIBS_set= +ac_cv_env_LIBS_value= +ac_cv_env_XMKMF_set= +ac_cv_env_XMKMF_value= +ac_cv_env_build_alias_set= +ac_cv_env_build_alias_value= +ac_cv_env_host_alias_set= +ac_cv_env_host_alias_value= +ac_cv_env_target_alias_set= +ac_cv_env_target_alias_value= +ac_cv_func_connect=yes +ac_cv_func_gethostbyname=yes +ac_cv_func_putenv=yes +ac_cv_func_remove=yes +ac_cv_func_setenv=yes +ac_cv_func_shmat=yes +ac_cv_func_vfork=yes +ac_cv_have_x='have_x=yes ac_x_includes='\'''\'' ac_x_libraries='\'''\''' +ac_cv_header_GL_gl_h=yes +ac_cv_header_dirent_h=yes +ac_cv_header_inttypes_h=yes +ac_cv_header_limits_h=yes +ac_cv_header_memory_h=yes +ac_cv_header_param_h=no +ac_cv_header_paths_h=yes +ac_cv_header_stdc=yes +ac_cv_header_stdint_h=yes +ac_cv_header_stdlib_h=yes +ac_cv_header_string_h=yes +ac_cv_header_strings_h=yes +ac_cv_header_sys_mman_h=yes +ac_cv_header_sys_stat_h=yes +ac_cv_header_sys_types_h=yes +ac_cv_header_unistd_h=yes +ac_cv_host=x86_64-unknown-linux-gnu +ac_cv_lib_GLU_gluNewTess=yes +ac_cv_lib_GL_glXCreateContext=yes +ac_cv_lib_ICE_IceConnectionNumber=yes +ac_cv_lib_Xext_XextFindDisplay=yes +ac_cv_lib_Xi_XOpenDevice=yes +ac_cv_lib_Xmu_XmuInternAtom=yes +ac_cv_objext=o +ac_cv_path_CSH=/bin/csh +ac_cv_path_EGREP='/bin/grep -E' +ac_cv_path_GCORE=/bin/gcore +ac_cv_path_GREP=/bin/grep +ac_cv_path_LD=/bin/ld +ac_cv_path_M4=/bin/m4 +ac_cv_path_install='/bin/install -c' +ac_cv_prog_CPP='gcc -E' +ac_cv_prog_ac_ct_CC=gcc +ac_cv_prog_ac_ct_CXX=g++ +ac_cv_prog_ac_ct_RANLIB=ranlib +ac_cv_prog_cc_c89= +ac_cv_prog_cc_g=yes +ac_cv_prog_cxx_g=yes +ac_cv_prog_gnu_ld=yes +ac_cv_search_strerror='none required' +ac_cv_sizeof_unsigned_int=4 +ac_cv_sizeof_unsigned_long=8 +ac_cv_sizeof_unsigned_long_long=8 +ac_cv_sizeof_void_p=8 +ac_cv_target=x86_64-unknown-linux-gnu + +## ----------------- ## +## Output variables. ## +## ----------------- ## + +ALL_TARGET='tcl' +CC='gcc' +CFLAGS='-g -m64 -fPIC' +CPP='gcc -E -x c' +CPPFLAGS='' +CSH='/bin/csh' +CXX='g++' +CXXFLAGS='-g -O2' +DEFS='-DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DMAGIC_VERSION=\"8.1\" -DMAGIC_REVISION=\"151\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_SYS_MMAN_H=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_PATHS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DFILE_LOCKS=1 -DCALMA_MODULE=1 -DCIF_MODULE=1 -DX11_BACKING_STORE=1 -DPLOT_MODULE=1 -DLEF_MODULE=1 -DROUTE_MODULE=1 -DUSE_NEW_MACROS=1 -DHAVE_LIBGL=1 -DHAVE_LIBGLU=1 -DVECTOR_FONTS=1 -DMAGIC_WRAPPER=1 -DTHREE_D=1 -Dlinux=1 -DSYSV=1 -DISC=1' +DEPEND_FLAG='-MM' +ECHO_C='' +ECHO_N='printf' +ECHO_T='' +EGREP='/bin/grep -E' +EXEEXT='' +EXTRA_LIB_SPECS='-ldl' +GCORE='/bin/gcore' +GREP='/bin/grep' +INC_SPECS='' +INSTALL_DATA='${INSTALL} -m 644' +INSTALL_PROGRAM='${INSTALL}' +INSTALL_SCRIPT='${INSTALL}' +INSTALL_TARGET='install-tcl' +LD='/bin/ld' +LDDL_FLAGS='-shared -Wl,-soname,$@ -Wl,--version-script=${MAGICDIR}/magic/symbol.map' +LDFLAGS='' +LD_RUN_PATH='' +LIBOBJS='' +LIBS='-lGLU -lGL ' +LIB_SPECS=' -L/usr/lib64 -ltk8.6 -L/usr/lib64 -ltcl8.6' +LTLIBOBJS='' +M4='/bin/m4' +MAGIC_REVISION='151' +MAGIC_VERSION='8.1' +OA='' +OA_LIBS='' +OBJEXT='o' +PACKAGE='magic' +PACKAGE_BUGREPORT='' +PACKAGE_NAME='' +PACKAGE_STRING='' +PACKAGE_TARNAME='' +PACKAGE_URL='' +PACKAGE_VERSION='' +PATH_SEPARATOR=':' +RANLIB='ranlib' +SCRIPTS='' +SHDLIB_EXT='.so' +SHELL='/bin/sh' +SHLIB_CFLAGS='-Wimplicit-int -fPIC' +SHLIB_LD='' +SHLIB_LIB_SPECS='' +TCLSH_EXE='/usr/bin/tclsh' +TCL_LIB_DIR='/usr/lib' +WISH_EXE='/usr/bin/wish' +XMKMF='' +X_CFLAGS='' +X_EXTRA_LIBS='' +X_LIBS='' +X_PRE_LIBS=' -lSM -lICE' +ac_ct_CC='gcc' +ac_ct_CXX='g++' +bindir='${exec_prefix}/bin' +build='x86_64-unknown-linux-gnu' +build_alias='' +build_cpu='x86_64' +build_os='linux-gnu' +build_vendor='unknown' +cadinstall=' graphics tcltk' +datadir='${datarootdir}' +datarootdir='${prefix}/share' +docdir='${datarootdir}/doc/${PACKAGE}' +dvidir='${docdir}' +exec_prefix='${prefix}' +extra_defs=' -DCAD_DIR=\"${LIBDIR}\" -DBIN_DIR=\"${BINDIR}\" -DTCL_DIR=\"${TCLDIR}\"' +extra_libs=' ${MAGICDIR}/ext2sim/libext2sim.o ${MAGICDIR}/ext2spice/libext2spice.o ${MAGICDIR}/calma/libcalma.o ${MAGICDIR}/cif/libcif.o ${MAGICDIR}/plot/libplot.o ${MAGICDIR}/lef/liblef.o ${MAGICDIR}/extflat/libextflat.o ${MAGICDIR}/garouter/libgarouter.o ${MAGICDIR}/mzrouter/libmzrouter.o ${MAGICDIR}/router/librouter.o ${MAGICDIR}/irouter/libirouter.o ${MAGICDIR}/grouter/libgrouter.o ${MAGICDIR}/gcr/libgcr.o ${MAGICDIR}/tcltk/libtcltk.o' +gr_cflags='' +gr_dflags=' -DX11 -DXLIB -DOGL' +gr_hprog='' +gr_hsrcs='' +gr_libs=' -lX11 -lGL -lGLU -lXi -lXmu -lXext -lm -lstdc++' +gr_srcs=' ${TK_SRCS} ${TOGL_SRCS} ${TKCOMMON_SRCS}' +host='x86_64-unknown-linux-gnu' +host_alias='' +host_cpu='x86_64' +host_os='linux-gnu' +host_vendor='unknown' +htmldir='${docdir}' +includedir='${prefix}/include' +infodir='${datarootdir}/info' +ld_extra_libs='' +ld_extra_objs='' +libdir='${exec_prefix}/lib' +libexecdir='${exec_prefix}/libexec' +localedir='${datarootdir}/locale' +localstatedir='${prefix}/var' +mandir='${datarootdir}/man' +modules=' ext2sim ext2spice calma cif plot lef garouter grouter irouter mzrouter router gcr tcltk' +oldincludedir='/usr/include' +pdfdir='${docdir}' +prefix='/usr/local' +program_transform_name='s,x,x,' +programs=' net2ir tcltk' +psdir='${docdir}' +rl_defs='' +rl_libs='' +sbindir='${exec_prefix}/sbin' +sharedstatedir='${prefix}/com' +sub_extra_libs='' +sysconfdir='${prefix}/etc' +target='x86_64-unknown-linux-gnu' +target_alias='' +target_cpu='x86_64' +target_os='linux-gnu' +target_vendor='unknown' +top_extra_libs='' +unused=' readline lisp' + +## ----------- ## +## confdefs.h. ## +## ----------- ## + +/* confdefs.h */ +#define PACKAGE_NAME "" +#define PACKAGE_TARNAME "" +#define PACKAGE_VERSION "" +#define PACKAGE_STRING "" +#define PACKAGE_BUGREPORT "" +#define PACKAGE_URL "" +#define MAGIC_VERSION "8.1" +#define MAGIC_REVISION "151" +#define STDC_HEADERS 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_UNISTD_H 1 +#define SIZEOF_VOID_P 8 +#define SIZEOF_UNSIGNED_INT 4 +#define SIZEOF_UNSIGNED_LONG 8 +#define SIZEOF_UNSIGNED_LONG_LONG 8 +#define STDC_HEADERS 1 +#define HAVE_SETENV 1 +#define HAVE_PUTENV 1 +#define HAVE_SYS_MMAN_H 1 +#define HAVE_DIRENT_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_PATHS_H 1 +#define HAVE_VA_COPY 1 +#define HAVE___VA_COPY 1 +#define FILE_LOCKS 1 +#define CALMA_MODULE 1 +#define CIF_MODULE 1 +#define X11_BACKING_STORE 1 +#define PLOT_MODULE 1 +#define LEF_MODULE 1 +#define ROUTE_MODULE 1 +#define USE_NEW_MACROS 1 +#define HAVE_LIBGL 1 +#define HAVE_LIBGLU 1 +#define VECTOR_FONTS 1 +#define MAGIC_WRAPPER 1 +#define THREE_D 1 +#define linux 1 +#define SYSV 1 +#define ISC 1 + +configure: exit 0 diff --git a/scripts/config.status b/scripts/config.status new file mode 100755 index 00000000..5ae93182 --- /dev/null +++ b/scripts/config.status @@ -0,0 +1,953 @@ +#! /bin/sh +# Generated by configure. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +# Files that config.status was made for. +config_files=" defs.mak" + +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to the package provider." + +ac_cs_config="'CFLAGS=-g'" +ac_cs_version="\ +config.status +configured by ./configure, generated by GNU Autoconf 2.69, + with options \"$ac_cs_config\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='/home/tim/gitsrc/magic-8.1/scripts' +srcdir='..' +INSTALL='/bin/install -c' +test -n "$AWK" || AWK=awk +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +if $ac_cs_recheck; then + set X /bin/sh './configure' 'CFLAGS=-g' $ac_configure_extra_args --no-create --no-recursion + shift + $as_echo "running CONFIG_SHELL=/bin/sh $*" >&6 + CONFIG_SHELL='/bin/sh' + export CONFIG_SHELL + exec "$@" +fi + +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "defs.mak") CONFIG_FILES="$CONFIG_FILES defs.mak" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +cat >>"$ac_tmp/subs1.awk" <<\_ACAWK && +S["LTLIBOBJS"]="" +S["LIBOBJS"]="" +S["INSTALL_TARGET"]="install-tcl" +S["ALL_TARGET"]="tcl" +S["OA_LIBS"]="" +S["OA"]="" +S["MAGIC_REVISION"]="151" +S["MAGIC_VERSION"]="8.1" +S["LD_RUN_PATH"]="" +S["SHLIB_CFLAGS"]="-Wimplicit-int -fPIC" +S["DEPEND_FLAG"]="-MM" +S["gr_hprog"]="" +S["gr_hsrcs"]="" +S["gr_srcs"]=" ${TK_SRCS} ${TOGL_SRCS} ${TKCOMMON_SRCS}" +S["gr_dflags"]=" -DX11 -DXLIB -DOGL" +S["gr_cflags"]="" +S["rl_libs"]="" +S["rl_defs"]="" +S["cadinstall"]=" graphics tcltk" +S["programs"]=" net2ir tcltk" +S["unused"]=" readline lisp" +S["modules"]=" ext2sim ext2spice calma cif plot lef garouter grouter irouter mzrouter router gcr tcltk" +S["sub_extra_libs"]="" +S["top_extra_libs"]="" +S["ld_extra_objs"]="" +S["ld_extra_libs"]="" +S["extra_defs"]=" -DCAD_DIR=\\\"${LIBDIR}\\\" -DBIN_DIR=\\\"${BINDIR}\\\" -DTCL_DIR=\\\"${TCLDIR}\\\"" +S["extra_libs"]=" ${MAGICDIR}/ext2sim/libext2sim.o ${MAGICDIR}/ext2spice/libext2spice.o ${MAGICDIR}/calma/libcalma.o ${MAGICDIR}/cif/libcif.o ${MAGICDIR}/plot/libplo"\ +"t.o ${MAGICDIR}/lef/liblef.o ${MAGICDIR}/extflat/libextflat.o ${MAGICDIR}/garouter/libgarouter.o ${MAGICDIR}/mzrouter/libmzrouter.o ${MAGICDIR}/rou"\ +"ter/librouter.o ${MAGICDIR}/irouter/libirouter.o ${MAGICDIR}/grouter/libgrouter.o ${MAGICDIR}/gcr/libgcr.o ${MAGICDIR}/tcltk/libtcltk.o" +S["SCRIPTS"]="" +S["PACKAGE"]="magic" +S["gr_libs"]=" -lX11 -lGL -lGLU -lXi -lXmu -lXext -lm -lstdc++" +S["TCL_LIB_DIR"]="/usr/lib" +S["TCLSH_EXE"]="/usr/bin/tclsh" +S["WISH_EXE"]="/usr/bin/wish" +S["LIB_SPECS"]=" -L/usr/lib64 -ltk8.6 -L/usr/lib64 -ltcl8.6" +S["INC_SPECS"]="" +S["EXTRA_LIB_SPECS"]="-ldl" +S["SHLIB_LIB_SPECS"]="" +S["LDDL_FLAGS"]="-shared -Wl,-soname,$@ -Wl,--version-script=${MAGICDIR}/magic/symbol.map" +S["LD"]="/bin/ld" +S["SHLIB_LD"]="" +S["SHDLIB_EXT"]=".so" +S["X_EXTRA_LIBS"]="" +S["X_LIBS"]="" +S["X_PRE_LIBS"]=" -lSM -lICE" +S["X_CFLAGS"]="" +S["XMKMF"]="" +S["CSH"]="/bin/csh" +S["GCORE"]="/bin/gcore" +S["EGREP"]="/bin/grep -E" +S["GREP"]="/bin/grep" +S["M4"]="/bin/m4" +S["RANLIB"]="ranlib" +S["INSTALL_DATA"]="${INSTALL} -m 644" +S["INSTALL_SCRIPT"]="${INSTALL}" +S["INSTALL_PROGRAM"]="${INSTALL}" +S["ac_ct_CXX"]="g++" +S["CXXFLAGS"]="-g -O2" +S["CXX"]="g++" +S["CPP"]="gcc -E -x c" +S["OBJEXT"]="o" +S["EXEEXT"]="" +S["ac_ct_CC"]="gcc" +S["CPPFLAGS"]="" +S["LDFLAGS"]="" +S["CFLAGS"]="-g -m64 -fPIC" +S["CC"]="gcc" +S["target_os"]="linux-gnu" +S["target_vendor"]="unknown" +S["target_cpu"]="x86_64" +S["target"]="x86_64-unknown-linux-gnu" +S["host_os"]="linux-gnu" +S["host_vendor"]="unknown" +S["host_cpu"]="x86_64" +S["host"]="x86_64-unknown-linux-gnu" +S["build_os"]="linux-gnu" +S["build_vendor"]="unknown" +S["build_cpu"]="x86_64" +S["build"]="x86_64-unknown-linux-gnu" +S["target_alias"]="" +S["host_alias"]="" +S["build_alias"]="" +S["LIBS"]="-lGLU -lGL " +S["ECHO_T"]="" +S["ECHO_N"]="-n" +S["ECHO_C"]="" +S["DEFS"]="-DPACKAGE_NAME=\\\"\\\" -DPACKAGE_TARNAME=\\\"\\\" -DPACKAGE_VERSION=\\\"\\\" -DPACKAGE_STRING=\\\"\\\" -DPACKAGE_BUGREPORT=\\\"\\\" -DPACKAGE_URL=\\\"\\\" -DMAGIC_VERSION="\ +"\\\"8.1\\\" -DMAGIC_REVISION=\\\"151\\\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DH"\ +"AVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_"\ +"UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_SYS_MMAN_H=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_PATHS_H=1 -DHAV"\ +"E_VA_COPY=1 -DHAVE___VA_COPY=1 -DFILE_LOCKS=1 -DCALMA_MODULE=1 -DCIF_MODULE=1 -DX11_BACKING_STORE=1 -DPLOT_MODULE=1 -DLEF_MODULE=1 -DROUTE_MODULE=1 "\ +"-DUSE_NEW_MACROS=1 -DHAVE_LIBGL=1 -DHAVE_LIBGLU=1 -DVECTOR_FONTS=1 -DMAGIC_WRAPPER=1 -DTHREE_D=1 -Dlinux=1 -DSYSV=1 -DISC=1" +S["mandir"]="${datarootdir}/man" +S["localedir"]="${datarootdir}/locale" +S["libdir"]="${exec_prefix}/lib" +S["psdir"]="${docdir}" +S["pdfdir"]="${docdir}" +S["dvidir"]="${docdir}" +S["htmldir"]="${docdir}" +S["infodir"]="${datarootdir}/info" +S["docdir"]="${datarootdir}/doc/${PACKAGE}" +S["oldincludedir"]="/usr/include" +S["includedir"]="${prefix}/include" +S["localstatedir"]="${prefix}/var" +S["sharedstatedir"]="${prefix}/com" +S["sysconfdir"]="${prefix}/etc" +S["datadir"]="${datarootdir}" +S["datarootdir"]="${prefix}/share" +S["libexecdir"]="${exec_prefix}/libexec" +S["sbindir"]="${exec_prefix}/sbin" +S["bindir"]="${exec_prefix}/bin" +S["program_transform_name"]="s,x,x," +S["prefix"]="/usr/local" +S["exec_prefix"]="${prefix}" +S["PACKAGE_URL"]="" +S["PACKAGE_BUGREPORT"]="" +S["PACKAGE_STRING"]="" +S["PACKAGE_VERSION"]="" +S["PACKAGE_TARNAME"]="" +S["PACKAGE_NAME"]="" +S["PATH_SEPARATOR"]=":" +S["SHELL"]="/bin/sh" +_ACAWK +cat >>"$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} + ac_datarootdir_hack=' + s&@datadir@&${datarootdir}&g + s&@docdir@&${datarootdir}/doc/${PACKAGE}&g + s&@infodir@&${datarootdir}/info&g + s&@localedir@&${datarootdir}/locale&g + s&@mandir@&${datarootdir}/man&g + s&\${datarootdir}&${prefix}/share&g' ;; +esac +ac_sed_extra=" + +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + + + + esac + +done # for ac_tag + + +as_fn_exit 0 diff --git a/scripts/config.sub b/scripts/config.sub new file mode 100755 index 00000000..12ebc787 --- /dev/null +++ b/scripts/config.sub @@ -0,0 +1,1410 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. + +timestamp='2001-08-13' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dsp16xx \ + | fr30 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el | mips64vr4300 \ + | mips64vr4300el | mips64vr5000 | mips64vr5000el \ + | mipsbe | mipsel | mipsle | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | s390 | s390x \ + | sh | sh[34] | sh[34]eb | shbe | shle \ + | sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 \ + | we32k \ + | x86 | xscale \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alphapca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armv*-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | clipper-* | cray2-* | cydra-* \ + | d10v-* | d30v-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | m32r-* \ + | m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ + | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipsel-* \ + | mipsle-* | mipstx39-* | mipstx39el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | s390-* | s390x-* \ + | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* \ + | t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ + | v850-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xmp-* | xps100-* | xscale-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [cjt]90) + basic_machine=${basic_machine}-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=t3e-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh3eb | sh4eb) + basic_machine=sh-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/scripts/configure b/scripts/configure new file mode 100755 index 00000000..6ee47dcd --- /dev/null +++ b/scripts/configure @@ -0,0 +1,9296 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="magic" +ac_unique_file="rules.mak" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +INSTALL_TARGET +ALL_TARGET +OA_LIBS +OA +MAGIC_REVISION +MAGIC_VERSION +LD_RUN_PATH +SHLIB_CFLAGS +DEPEND_FLAG +gr_hprog +gr_hsrcs +gr_srcs +gr_dflags +gr_cflags +rl_libs +rl_defs +cadinstall +programs +unused +modules +sub_extra_libs +top_extra_libs +ld_extra_objs +ld_extra_libs +extra_defs +extra_libs +SCRIPTS +PACKAGE +gr_libs +TCL_LIB_DIR +TCLSH_EXE +WISH_EXE +LIB_SPECS +INC_SPECS +EXTRA_LIB_SPECS +SHLIB_LIB_SPECS +LDDL_FLAGS +LD +SHLIB_LD +SHDLIB_EXT +X_EXTRA_LIBS +X_LIBS +X_PRE_LIBS +X_CFLAGS +XMKMF +CSH +GCORE +EGREP +GREP +M4 +RANLIB +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +ac_ct_CXX +CXXFLAGS +CXX +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_gnu_ld +with_x +with_interpreter +with_tcl +with_tk +with_tclincls +with_tkincls +with_tcllibs +with_tklibs +with_openaccess +enable_memdebug +enable_modular +enable_locking +enable_calma +enable_cif +enable_client_render +enable_invert_y +enable_framebuffer_backing_store +enable_plot +enable_lef +enable_readline +enable_threads +enable_route +enable_rsim +enable_new_macros +with_opengl +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +CXX +CXXFLAGS +CCC +XMKMF' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-memdebug enable memory debugging + --enable-modular embed ext2sim and ext2spice packages + --disable-locking disable file locking + --disable-calma disable calma package + --disable-cif disable cif package + --disable-client-render disable OpenGL client-side rendering + --enable-invert-y invert screen top to bottom in OpenGL + --enable-framebuffer-backing-store enable OpenGL framebuffer backing store + --disable-plot disable plot package + --disable-lef disable LEF package + --disable-readline disable readline package + --disable-threads disable threaded graphics + --disable-route disable routing package + --disable-rsim disable IRSIM tool + --disable-new-macros disable new macro set + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-x use the X Window System + --with-interpreter=arg enable interpreter (tcl, scheme, or no) + --with-tcl=DIR Find tclConfig.sh in DIR + --with-tk=DIR Find tkConfig.sh in DIR + --with-tclincls=DIR Find tcl.h in DIR + --with-tkincls=DIR Find tk.h in DIR + --with-tcllibs=DIR Find Tcl library in DIR + --with-tklibs=DIR Find Tk library in DIR + --with-openaccess=DIR use OpenAccess libraries in DIR + --with-opengl=DIR use OpenGL include files in DIR + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + XMKMF Path to xmkmf, Makefile generator for X Window System + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 &5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +ac_aux_dir= +for ac_dir in . "$srcdir"/.; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in . \"$srcdir\"/." "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if ${ac_cv_target+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + + +PACKAGE=magic + +MAGIC_VERSION=`cat ../VERSION | cut -d. -f1-2` +MAGIC_REVISION=`cat ../VERSION | cut -d. -f3` +cat >>confdefs.h <<_ACEOF +#define MAGIC_VERSION "${MAGIC_VERSION}" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define MAGIC_REVISION "${MAGIC_REVISION}" +_ACEOF + + +ALL_TARGET="standard" +INSTALL_TARGET="install-magic" + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 +$as_echo_n "checking for library containing strerror... " >&6; } +if ${ac_cv_search_strerror+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char strerror (); +int +main () +{ +return strerror (); + ; + return 0; +} +_ACEOF +for ac_lib in '' cposix; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_strerror=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_strerror+:} false; then : + break +fi +done +if ${ac_cv_search_strerror+:} false; then : + +else + ac_cv_search_strerror=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5 +$as_echo "$ac_cv_search_strerror" >&6; } +ac_res=$ac_cv_search_strerror +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + +for ac_prog in gm4 gnum4 m4 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_M4+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $M4 in + [\\/]* | ?:[\\/]*) + ac_cv_path_M4="$M4" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_M4="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +M4=$ac_cv_path_M4 +if test -n "$M4"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4" >&5 +$as_echo "$M4" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$M4" && break +done +test -n "$M4" || M4="no" + +if test x$M4 = xno; then + as_fn_error $? "M4 is required" "$LINENO" 5 +fi + + +if test "$CPP" = "$CC -E" ; then + CPP="$CPP -x c" +fi + + +#------------------------------------------------------------ +# AC_PROG_LD - find the path to the GNU or non-GNU linker +# (This stuff ripped from libtool) +#------------------------------------------------------------ + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5 +$as_echo_n "checking for ld used by GCC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case "$ac_prog" in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${ac_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$ac_cv_path_LD" +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${ac_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gnu_ld" >&5 +$as_echo "$ac_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$ac_cv_prog_gnu_ld + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5 +$as_echo_n "checking size of void *... " >&6; } +if ${ac_cv_sizeof_void_p+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_void_p" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (void *) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_void_p=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5 +$as_echo "$ac_cv_sizeof_void_p" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_VOID_P $ac_cv_sizeof_void_p +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned int" >&5 +$as_echo_n "checking size of unsigned int... " >&6; } +if ${ac_cv_sizeof_unsigned_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned int))" "ac_cv_sizeof_unsigned_int" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_unsigned_int" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (unsigned int) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_unsigned_int=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_int" >&5 +$as_echo "$ac_cv_sizeof_unsigned_int" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_INT $ac_cv_sizeof_unsigned_int +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5 +$as_echo_n "checking size of unsigned long... " >&6; } +if ${ac_cv_sizeof_unsigned_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_unsigned_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (unsigned long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_unsigned_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long" >&5 +$as_echo "$ac_cv_sizeof_unsigned_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long long" >&5 +$as_echo_n "checking size of unsigned long long... " >&6; } +if ${ac_cv_sizeof_unsigned_long_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long long))" "ac_cv_sizeof_unsigned_long_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_unsigned_long_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (unsigned long long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_unsigned_long_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long_long" >&5 +$as_echo "$ac_cv_sizeof_unsigned_long_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_LONG_LONG $ac_cv_sizeof_unsigned_long_long +_ACEOF + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + + +for ac_func in setenv putenv +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +ac_fn_c_check_func "$LINENO" "vfork" "ac_cv_func_vfork" +if test "x$ac_cv_func_vfork" = xyes; then : + +fi + + +for ac_header in sys/mman.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_mman_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_MMAN_H 1 +_ACEOF + +fi + +done + + +for ac_header in dirent.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "$ac_includes_default" +if test "x$ac_cv_header_dirent_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DIRENT_H 1 +_ACEOF + +fi + +done + + +for ac_header in limits.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" +if test "x$ac_cv_header_limits_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIMITS_H 1 +_ACEOF + +fi + +done + + +for ac_header in param.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "param.h" "ac_cv_header_param_h" "$ac_includes_default" +if test "x$ac_cv_header_param_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PARAM_H 1 +_ACEOF + +fi + +done + + +for ac_header in paths.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "paths.h" "ac_cv_header_paths_h" "$ac_includes_default" +if test "x$ac_cv_header_paths_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PATHS_H 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for va_copy" >&5 +$as_echo_n "checking for va_copy... " >&6; } +if ${ac_cv_c_va_copy+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +va_list ap1, ap2; + va_copy(ap1,ap2); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_c_va_copy="yes" +else + ac_cv_c_va_copy="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_va_copy" >&5 +$as_echo "$ac_cv_c_va_copy" >&6; } +if test "$ac_cv_c_va_copy" = "yes" +then + +$as_echo "#define HAVE_VA_COPY 1" >>confdefs.h + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __va_copy" >&5 +$as_echo_n "checking for __va_copy... " >&6; } +if ${ac_cv_c___va_copy+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +va_list ap1, ap2; + __va_copy(ap1,ap2); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_c___va_copy="yes" +else + ac_cv_c___va_copy="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c___va_copy" >&5 +$as_echo "$ac_cv_c___va_copy" >&6; } +if test "$ac_cv_c___va_copy" = "yes" +then + +$as_echo "#define HAVE___VA_COPY 1" >>confdefs.h + +fi + + + + +case $target in + *x86_64*) ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for built-in roundf" >&5 +$as_echo_n "checking for built-in roundf... " >&6; } +if ${ac_cv_c_roundf+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +float f; + f = roundf(1.5); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_c_roundf="yes" +else + ac_cv_c_roundf="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_roundf" >&5 +$as_echo "$ac_cv_c_roundf" >&6; } + if test "$ac_cv_c_roundf" = "no" + then + # Check fo C99 function from libm + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for roundf in -lm" >&5 +$as_echo_n "checking for roundf in -lm... " >&6; } +if ${ac_cv_lib_m_roundf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char roundf (); +int +main () +{ +return roundf (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_roundf=yes +else + ac_cv_lib_m_roundf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_roundf" >&5 +$as_echo "$ac_cv_lib_m_roundf" >&6; } +if test "x$ac_cv_lib_m_roundf" = xyes; then : + +$as_echo "#define HAVE_ROUNDF 1" >>confdefs.h + +fi + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for built-in round" >&5 +$as_echo_n "checking for built-in round... " >&6; } +if ${ac_cv_c_round+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +double d; + d = round(1.5); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_c_round="yes" +else + ac_cv_c_round="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_round" >&5 +$as_echo "$ac_cv_c_round" >&6; } + if test "$ac_cv_c_round" = "no" + then + # Check fo C99 function from libm + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for round in -lm" >&5 +$as_echo_n "checking for round in -lm... " >&6; } +if ${ac_cv_lib_m_round+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char round (); +int +main () +{ +return round (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_round=yes +else + ac_cv_lib_m_round=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_round" >&5 +$as_echo "$ac_cv_lib_m_round" >&6; } +if test "x$ac_cv_lib_m_round" = xyes; then : + +$as_echo "#define HAVE_ROUND 1" >>confdefs.h + +fi + + fi + ;; +esac + +extra_defs="$extra_defs -DCAD_DIR=\\\"\${LIBDIR}\\\" -DBIN_DIR=\\\"\${BINDIR}\\\"" +X_LIBS= +X_CFLAGS= +CPPFLAGS= +INC_SPECS= +DEPEND_FLAG= +SHLIB_CFLAGS="" +LD_RUN_PATH="" +WISH_EXE="" +TCLSH_EXE="" + +modules="" +unused="" +cadinstall="" +extra_libs="" +top_extra_libs="" +sub_extra_libs="" +ld_extra_libs="" +ld_extra_objs="" +programs="" +rl_defs= +rl_libs= +gr_cflags= +gr_dflags= +gr_libs= +gr_srcs= +gr_hsrcs= +gr_hprog= + +magic_with_tcl="yes" +magic_with_tk="yes" +magic_with_tcl_includes="" +magic_with_tk_includes="" +magic_with_tcl_libraries="" +magic_with_tk_libraries="" + + +usingOGL=1 +use_libglu="-lGLU" +usingTcl=1 +usingOA=0 + + +# Extract the first word of "gcore", so it can be a program name with args. +set dummy gcore; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GCORE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GCORE in + [\\/]* | ?:[\\/]*) + ac_cv_path_GCORE="$GCORE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GCORE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GCORE" && ac_cv_path_GCORE="no" + ;; +esac +fi +GCORE=$ac_cv_path_GCORE +if test -n "$GCORE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GCORE" >&5 +$as_echo "$GCORE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + +# Extract the first word of "csh", so it can be a program name with args. +set dummy csh; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CSH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CSH in + [\\/]* | ?:[\\/]*) + ac_cv_path_CSH="$CSH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CSH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CSH" && ac_cv_path_CSH="no" + ;; +esac +fi +CSH=$ac_cv_path_CSH +if test -n "$CSH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CSH" >&5 +$as_echo "$CSH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +if test "x${CSH}" = "x"; then + as_fn_error $? "cannot find /bin/csh---cannot compile!" "$LINENO" 5 +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 +$as_echo_n "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then : + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : + $as_echo_n "(cached) " >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R7/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R7 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R7/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R7 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # We can compile using X headers with no special include directory. +ac_x_includes= +else + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + LIBS=$ac_save_LIBS +for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 +$as_echo "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 +$as_echo "libraries $x_libraries, headers $x_includes" >&6; } +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + +$as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5 +$as_echo_n "checking whether -R must be followed by a space... " >&6; } + ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" + ac_xsave_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + X_LIBS="$X_LIBS -R$x_libraries" +else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + X_LIBS="$X_LIBS -R $x_libraries" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5 +$as_echo "neither works" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_c_werror_flag=$ac_xsave_c_werror_flag + LIBS=$ac_xsave_LIBS + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn Johnson says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And Karl Berry says + # the Alpha needs dnet_stub (dnet does not exist). + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XOpenDisplay (); +int +main () +{ +return XOpenDisplay (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 +$as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; } +if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dnet_dnet_ntoa=yes +else + ac_cv_lib_dnet_dnet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 +$as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; } +if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 +$as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; } +if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet_stub $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dnet_stub_dnet_ntoa=yes +else + ac_cv_lib_dnet_stub_dnet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 +$as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } +if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +fi + + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_xsave_LIBS" + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to T.E. Dickey. + # The functions gethostbyname, getservbyname, and inet_addr are + # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. + ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" +if test "x$ac_cv_func_gethostbyname" = xyes; then : + +fi + + if test $ac_cv_func_gethostbyname = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 +$as_echo_n "checking for gethostbyname in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nsl_gethostbyname=yes +else + ac_cv_lib_nsl_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 +$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } +if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +fi + + if test $ac_cv_lib_nsl_gethostbyname = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 +$as_echo_n "checking for gethostbyname in -lbsd... " >&6; } +if ${ac_cv_lib_bsd_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bsd_gethostbyname=yes +else + ac_cv_lib_bsd_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 +$as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } +if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" +fi + + fi + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says Simon Leinen: it contains gethostby* + # variants that don't use the name server (or something). -lsocket + # must be given before -lnsl if both are needed. We assume that + # if connect needs -lnsl, so does gethostbyname. + ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" +if test "x$ac_cv_func_connect" = xyes; then : + +fi + + if test $ac_cv_func_connect = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 +$as_echo_n "checking for connect in -lsocket... " >&6; } +if ${ac_cv_lib_socket_connect+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_connect=yes +else + ac_cv_lib_socket_connect=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 +$as_echo "$ac_cv_lib_socket_connect" >&6; } +if test "x$ac_cv_lib_socket_connect" = xyes; then : + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +fi + + fi + + # Guillermo Gomez says -lposix is necessary on A/UX. + ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove" +if test "x$ac_cv_func_remove" = xyes; then : + +fi + + if test $ac_cv_func_remove = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 +$as_echo_n "checking for remove in -lposix... " >&6; } +if ${ac_cv_lib_posix_remove+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char remove (); +int +main () +{ +return remove (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_posix_remove=yes +else + ac_cv_lib_posix_remove=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 +$as_echo "$ac_cv_lib_posix_remove" >&6; } +if test "x$ac_cv_lib_posix_remove" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat" +if test "x$ac_cv_func_shmat" = xyes; then : + +fi + + if test $ac_cv_func_shmat = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 +$as_echo_n "checking for shmat in -lipc... " >&6; } +if ${ac_cv_lib_ipc_shmat+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lipc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shmat (); +int +main () +{ +return shmat (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ipc_shmat=yes +else + ac_cv_lib_ipc_shmat=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 +$as_echo "$ac_cv_lib_ipc_shmat" >&6; } +if test "x$ac_cv_lib_ipc_shmat" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS=$LDFLAGS + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # John Interrante, Karl Berry + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 +$as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; } +if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char IceConnectionNumber (); +int +main () +{ +return IceConnectionNumber (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ICE_IceConnectionNumber=yes +else + ac_cv_lib_ICE_IceConnectionNumber=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 +$as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } +if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then : + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +fi + + LDFLAGS=$ac_save_LDFLAGS + +fi + + +if test "x${X_DISPLAY_MISSING}" = "x"; then + usingX11=1 +else + as_fn_error $? "Unable to find X11---compiling without graphics" "$LINENO" 5 + echo Cannot find X11---will attempt to compile anyway. + echo Graphics options will be NULL only! + if test $usingOGL ; then + echo "Cannot use OpenGL/GLX without X11, disabling." + usingOGL= + fi + if test $usingTcl ; then + echo "Cannot compile TCL version without X11, disabling." + usingTcl= + fi +fi + +# Check for libXi, which is required on some systems but not available on +# others. +use_libxi="" +use_libxmu="" +use_libxext="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XOpenDevice in -lXi" >&5 +$as_echo_n "checking for XOpenDevice in -lXi... " >&6; } +if ${ac_cv_lib_Xi_XOpenDevice+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXi $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XOpenDevice (); +int +main () +{ +return XOpenDevice (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_Xi_XOpenDevice=yes +else + ac_cv_lib_Xi_XOpenDevice=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xi_XOpenDevice" >&5 +$as_echo "$ac_cv_lib_Xi_XOpenDevice" >&6; } +if test "x$ac_cv_lib_Xi_XOpenDevice" = xyes; then : + use_libxi="-lXi" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XmuInternAtom in -lXmu" >&5 +$as_echo_n "checking for XmuInternAtom in -lXmu... " >&6; } +if ${ac_cv_lib_Xmu_XmuInternAtom+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXmu $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XmuInternAtom (); +int +main () +{ +return XmuInternAtom (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_Xmu_XmuInternAtom=yes +else + ac_cv_lib_Xmu_XmuInternAtom=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xmu_XmuInternAtom" >&5 +$as_echo "$ac_cv_lib_Xmu_XmuInternAtom" >&6; } +if test "x$ac_cv_lib_Xmu_XmuInternAtom" = xyes; then : + use_libxmu="-lXmu" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XextFindDisplay in -lXext" >&5 +$as_echo_n "checking for XextFindDisplay in -lXext... " >&6; } +if ${ac_cv_lib_Xext_XextFindDisplay+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXext $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XextFindDisplay (); +int +main () +{ +return XextFindDisplay (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_Xext_XextFindDisplay=yes +else + ac_cv_lib_Xext_XextFindDisplay=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xext_XextFindDisplay" >&5 +$as_echo "$ac_cv_lib_Xext_XextFindDisplay" >&6; } +if test "x$ac_cv_lib_Xext_XextFindDisplay" = xyes; then : + use_libxext="-lXext" +fi + + + +# Check whether --with-interpreter was given. +if test "${with_interpreter+set}" = set; then : + withval=$with_interpreter; + if test "$withval" = "no" -o "$withval" = "NO"; then + usingTcl= + elif test "$withval" = "scheme" -o "$withval" = "SCHEME"; then + usingScheme=1 + usingTcl= + elif test "$withval" != "tcl" -a "$withval" != "TCL"; then + echo "Unknown option to --with-interpreter: Must be scheme, tcl, or no." + exit 1 + fi + +fi + + + +# Check whether --with-tcl was given. +if test "${with_tcl+set}" = set; then : + withval=$with_tcl; + magic_with_tcl=$withval + if test "$withval" = "no" -o "$withval" = "NO"; then + usingTcl= + elif test $usingScheme ; then + echo Attempt to enable both Tcl and Scheme interpreters. + echo Disabling Tcl, and using Scheme instead. + usingTcl= + fi + +fi + + + + +# Check whether --with-tk was given. +if test "${with_tk+set}" = set; then : + withval=$with_tk; magic_with_tk=$withval +fi + + +# Check whether --with-tclincls was given. +if test "${with_tclincls+set}" = set; then : + withval=$with_tclincls; magic_with_tcl_includes=$withval +fi + + +# Check whether --with-tkincls was given. +if test "${with_tkincls+set}" = set; then : + withval=$with_tkincls; magic_with_tk_includes=$withval +fi + + +# Check whether --with-tcllibs was given. +if test "${with_tcllibs+set}" = set; then : + withval=$with_tcllibs; magic_with_tcl_libraries=$withval +fi + + +# Check whether --with-tklibs was given. +if test "${with_tklibs+set}" = set; then : + withval=$with_tklibs; magic_with_tk_libraries=$withval +fi + + +# ----------------------------------------------------------------------- +# Find the Tcl build configuration file "tclConfig.sh" +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + TCL_INC_DIR="." + TK_INC_DIR="." + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclConfig.sh" >&5 +$as_echo_n "checking for tclConfig.sh... " >&6; } + tcl_config_sh="" + + if test "$magic_with_tcl" = "no" ; then + magic_with_tcl="" + elif test "$magic_with_tcl" != "yes" ; then + # + # Verify that a tclConfig.sh file exists in the directory specified + # by --with-tcl. + # + for dir in \ + $magic_with_tcl + do + if test -r "$dir/tclConfig.sh" ; then + tcl_config_sh="$dir/tclConfig.sh" + break + elif test -r "$dir/lib/tclConfig.sh" ; then + tcl_config_sh="$dir/lib/tclConfig.sh" + break + elif test -r "$dir/unix/tclConfig.sh" ; then + tcl_config_sh="$dir/unix/tclConfig.sh" + break + fi + done + else + # + # Otherwise, search for Tcl configuration file. + # + + # 1. Search previously named locations. + + for dir in \ + $prefix \ + $exec_prefix + do + if test -r "$dir/tclConfig.sh" ; then + tcl_config_sh="$dir/tclConfig.sh" + break + elif test -r "$dir/lib/tclConfig.sh" ; then + tcl_config_sh="$dir/lib/tclConfig.sh" + break + elif test -r "$dir/unix/tclConfig.sh" ; then + tcl_config_sh="$dir/unix/tclConfig.sh" + break + fi + done + + # 2. Search standard locations. + # (1/25/05---/usr/lib added for Ubuntu Linux) + # (6/19/06---/usr/lib64 added for 64-bit architectures + + if test "x$tcl_config_sh" = "x" ; then + for dir in \ + `ls -dr /usr/local/tcl/tcl[7-9].[0-9]* 2>/dev/null` \ + /usr/local/tcl \ + /usr/local/lib \ + /usr/lib64 \ + /usr/local \ + `ls -dr /usr/lib/tcl[7-9].[0-9]* 2>/dev/null` \ + /sw/lib \ + /usr + do + if test -r "$dir/tclConfig.sh" ; then + tcl_config_sh="$dir/tclConfig.sh" + break + elif test -r "$dir/lib/tclConfig.sh" ; then + tcl_config_sh="$dir/lib/tclConfig.sh" + break + fi + done + fi + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_config_sh}" >&5 +$as_echo "${tcl_config_sh}" >&6; } + + if test "x$tcl_config_sh" = "x" ; then + echo "Can't find Tcl configuration script \"tclConfig.sh\"" + echo "Reverting to non-Tcl compilation" + usingTcl= + fi +fi + +# ----------------------------------------------------------------------- +# Find the Tk build configuration file "tkConfig.sh" +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tkConfig.sh" >&5 +$as_echo_n "checking for tkConfig.sh... " >&6; } + tk_config_sh="" + if test "$magic_with_tk" != "yes"; then + # + # Verify that a tkConfig.sh file exists in the directory specified + # by --with-tcl or --with-tk. + # + for dir in \ + $magic_with_tk \ + $magic_with_tcl + do + if test -r "$dir/tkConfig.sh" ; then + tk_config_sh="$dir/tkConfig.sh" + break + elif test -r "$dir/lib/tkConfig.sh" ; then + tk_config_sh="$dir/lib/tkConfig.sh" + break + elif test -r "$dir/unix/tkConfig.sh" ; then + tk_config_sh="$dir/unix/tkConfig.sh" + break + fi + done + else + # + # Search for Tk configuration file. + # + + # + # 1. Search previously named locations. + # + for dir in \ + $prefix \ + $exec_prefix + do + if test -r "$dir/tkConfig.sh" ; then + tk_config_sh="$dir/tkConfig.sh" + break + elif test -r "$dir/lib/tkConfig.sh" ; then + tk_config_sh="$dir/lib/tkConfig.sh" + break + elif test -r "$dir/unix/tkConfig.sh" ; then + tk_config_sh="$dir/unix/tkConfig.sh" + break + fi + done + # + # 2. Search standard locations. + # + if test "x$tk_config_sh" = "x" ; then + for dir in \ + `ls -dr /usr/local/tcl/tcl[7-9].[0-9]* 2>/dev/null` \ + `ls -dr /usr/local/tk/tk[7-9].[0-9]* 2>/dev/null` \ + /usr/local/tcl \ + /usr/local/lib \ + /usr/lib64 \ + /usr/local \ + `ls -dr /usr/lib/tcl[7-9].[0-9]* 2>/dev/null` \ + `ls -dr /usr/lib/tk[7-9].[0-9]* 2>/dev/null` \ + /sw/lib \ + ${x_libraries} \ + /usr + do + if test -r "$dir/tkConfig.sh" ; then + tk_config_sh="$dir/tkConfig.sh" + break + elif test -r "$dir/lib/tkConfig.sh" ; then + tk_config_sh="$dir/lib/tkConfig.sh" + break + fi + done + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tk_config_sh}" >&5 +$as_echo "${tk_config_sh}" >&6; } + + if test "x$tk_config_sh" = "x" ; then + echo "can't find Tk configuration script \"tkConfig.sh\"" + echo "Reverting to non-Tcl compilation" + usingTcl= + fi +fi + +# ----------------------------------------------------------------------- +# Source in the Tcl/Tk configuration scripts. +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + . $tcl_config_sh + . $tk_config_sh + + # Should probably trust the config file contents, but this configure + # file checks the Tcl and Tk include and lib directories. Since + # the config file doesn't separate out the libraries from the strings + # passed to the compiler/linker, do it manually here. + # + # Extract TCL_LIB_DIR from TCL_LIB_SPEC + # Extract TK_LIB_DIR from TK_LIB_SPEC + # Extract TCL_INC_DIR from TCL_INCLUDE_SPEC + # Extract TK_INC_DIR from TK_INCLUDE_SPEC + # + # These will be the defaults unless overridden by configure command line + + tmpstr=${TCL_LIB_SPEC#*-L} + TCL_LIB_DIR=${tmpstr% -l*} + tmpstr=${TK_LIB_SPEC#*-L} + TK_LIB_DIR=${tmpstr% -l*} + TCL_INC_DIR=${TCL_INCLUDE_SPEC#*-I} + TK_INC_DIR=${TK_INCLUDE_SPEC#*-I} + + if test "$TCL_VERSION" = "7.6" -a "$TK_VERSION" = "4.2" ; then + : + elif test "$TCL_VERSION" = "7.5" -a "$TK_VERSION" = "4.1" ; then + : + elif test "$TCL_VERSION" = "$TK_VERSION" ; then + : + else + echo "Mismatched Tcl/Tk versions ($TCL_VERSION != $TK_VERSION)" + echo "Reverting to non-Tcl compile" + usingTcl= + fi +fi + +if test $usingTcl ; then + if test "x${magic_with_tcl_includes}" != "x" ; then + if test -r "${magic_with_tcl_includes}/tcl.h" ; then + TCL_INC_DIR=${magic_with_tcl_includes} + else + echo "Can't find tcl.h in \"${magic_with_tcl_includes}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for dir in \ + ${TCL_PREFIX}/include/tcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION} \ + ${TCL_PREFIX}/include \ + ${TCL_SRC_DIR}/generic \ + ${TCL_INC_DIR} + do + if test -r "$dir/tcl.h" ; then + TCL_INC_DIR=$dir + break + fi + done + if test "x${TCL_INC_DIR}" = "x" ; then + echo "Can't find tcl.h header file" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +if test $usingTcl ; then + if test "x${magic_with_tk_includes}" != "x" ; then + if test -r "${magic_with_tk_includes}/tk.h" ; then + TK_INC_DIR=${magic_with_tk_includes} + else + echo "Can't find tk.h in \"${magic_with_tk_includes}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for dir in \ + ${TK_PREFIX}/include/tk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION} \ + ${TK_PREFIX}/include \ + ${TK_SRC_DIR}/generic \ + ${TK_INC_DIR} \ + ${TCL_INC_DIR} + do + if test -r "$dir/tk.h" ; then + TK_INC_DIR=$dir + break + fi + done + if test "x${TK_INC_DIR}" = "x" ; then + echo "Can't find tk.h header file" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +# FIXME -- why are we not using TCL_LIB_FILE FROM tclConfig.sh? +if test $usingTcl ; then + case $target in + *-sunos4*|*-*-netbsd*|NetBSD-*|FreeBSD-*|OpenBSD-*) + TCL_LIB_NAME="tcl${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}" + TK_LIB_NAME="tk${TK_MAJOR_VERSION}${TK_MINOR_VERSION}" + ;; + *) + TCL_LIB_NAME="tcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" + TK_LIB_NAME="tk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}" + ;; + esac + + loclib=`echo ${TCL_LIB_SPEC} | sed -e 's/.*-L//' -e 's/ .*//'` + + if test "x${TCL_LIB_SPEC}" = "x" ; then + TCL_LIB_SPEC="-l${TCL_LIB_NAME}" + fi + if test "x${TK_LIB_SPEC}" = "x" ; then + TK_LIB_SPEC="-l${TK_LIB_NAME}" + fi + +# Find the version of "wish" that corresponds to TCL_EXEC_PREFIX +# We really ought to run "ldd" to confirm that the linked libraries match. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wish executable" >&5 +$as_echo_n "checking for wish executable... " >&6; } + for dir in \ + ${TK_EXEC_PREFIX}/bin \ + ${TK_EXEC_PREFIX} + do + for wishexe in \ + wish-X11 \ + wish \ + wish${TK_VERSION} \ + wish.exe \ + wish${TK_VERSION}.exe + do + if test -r "$dir/$wishexe" ; then + WISH_EXE=$dir/$wishexe + break + fi + done + if test "x${WISH_EXE}" != "x" ; then + break + fi + done + if test "x${WISH_EXE}" = "x" ; then + echo "Warning: Can't find executable for \"wish\". You may have to" + echo "manually set the value for WISH_EXE in the magic startup script." + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${WISH_EXE}" >&5 +$as_echo "${WISH_EXE}" >&6; } + fi + +# Find the version of "tclsh" that corresponds to TCL_EXEC_PREFIX + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh executable" >&5 +$as_echo_n "checking for tclsh executable... " >&6; } + for dir in \ + ${TK_EXEC_PREFIX}/bin \ + ${TK_EXEC_PREFIX} + do + for tclshexe in \ + tclsh \ + tclsh${TK_VERSION} \ + tclsh.exe \ + tclsh${TK_VERSION}.exe + do + if test -r "$dir/$tclshexe" ; then + TCLSH_EXE=$dir/$tclshexe + break + fi + done + if test "x${TCLSH_EXE}" != "x" ; then + break + fi + done + if test "x${TCLSH_EXE}" = "x" ; then + echo "Warning: Can't find executable for \"tclsh\"." + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_EXE}" >&5 +$as_echo "${TCLSH_EXE}" >&6; } + fi + +# Have to define SHDLIB_EXT here even though we have to do it below, too. + case $target in + *-hpux*) + SHDLIB_EXT=".sl" + SHDLIB_EXT_ALT=".sl" + ;; + *cygwin*) + SHDLIB_EXT=".dll" + SHDLIB_EXT_ALT=".dll.a" + ;; + *darwin*) + SHDLIB_EXT=".dylib" + SHDLIB_EXT_ALT=".dylib" + ;; + *) + SHDLIB_EXT=".so" + SHDLIB_EXT_ALT=".so" + ;; + esac + + if test "x${magic_with_tcl_libraries}" != "x" ; then + for libname in \ + "${magic_with_tcl_libraries}/${TCL_LIB_FILE}" \ + "${magic_with_tcl_libraries}/lib${TCL_LIB_NAME}${SHDLIB_EXT}" \ + "${magic_with_tcl_libraries}/lib${TCL_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TCL_LIB_DIR="${magic_with_tcl_libraries}" + break + fi + done + + if test "x${TCL_LIB_DIR}" = "x" ; then + echo "Can't find tcl library in \"${magic_with_tcl_libraries}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for libname in \ + "${loclib:=${TCL_EXEC_PREFIX}/lib}/lib${TCL_LIB_NAME}${SHDLIB_EXT}" \ + "${loclib:=${TCL_EXEC_PREFIX}/lib}/lib${TCL_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TCL_LIB_DIR="${TCL_EXEC_PREFIX}/lib" + break + fi + done + if test "x${TCL_LIB_DIR}" = "x" ; then + echo "Can't find tcl library" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +if test $usingTcl ; then + if test "x${magic_with_tk_libraries}" != "x" ; then + for libname in \ + "${magic_with_tk_libraries}/${TCL_LIB_FILE}" \ + "${magic_with_tk_libraries}/lib${TK_LIB_NAME}${SHDLIB_EXT}" \ + "${magic_with_tk_libraries}/lib${TK_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TK_LIB_DIR="${magic_with_tk_libraries}" + break + fi + done + if test "x${TK_LIB_DIR}" = "x" ; then + echo "Can't find tk library in \"${magic_with_tk_libraries}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for libname in \ + "${loclib:=${TK_EXEC_PREFIX}/lib}/lib${TK_LIB_NAME}${SHDLIB_EXT}" \ + "${loclib:=${TK_EXEC_PREFIX}/lib}/lib${TK_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TK_LIB_DIR="${TK_EXEC_PREFIX}/lib" + break + fi + done + if test "x${TK_LIB_DIR}" = "x" ; then + echo "Can't find tk library" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + + + + + +# Check whether --with-openaccess was given. +if test "${with_openaccess+set}" = set; then : + withval=$with_openaccess; + if test "$withval" = "no" -o "$withval" = "NO" ; then + OA= + OA_LIBS= + unused="$unused oa" + elif test "$withval" = "yes"; then + as_fn_error $? "path to OpenAccess libraries is required" "$LINENO" 5 + OA= + OA_LIBS= + unused="$unused oa" + else + usingOA=1 + OA=${withval} + OA_LIBS="-L\${OA}/lib -loaDB -loaDD -loaTC -loaBase" + OA_LIBS="${OA_LIBS} -lclalite_sh -lcls_sh -lcdsCommon_sh" + $as_echo "#define OPENACCESS 1" >>confdefs.h + + LD_RUN_PATH="-Wl,-rpath=\${OA}/lib" + modules="$modules oa" + extra_libs="$extra_libs \${MAGICDIR}/oa/liboa.o" + fi + +fi + + +# Check whether --enable-memdebug was given. +if test "${enable_memdebug+set}" = set; then : + enableval=$enable_memdebug; +else + enable_memdebug=no +fi + + +if test "x$enable_memdebug" = "xyes" ; then + if test "x$magic_with_tcl" = "x" ; then + LIBS="${LIBS} -lefence" + else + $as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h + + fi +fi + +# Check whether --enable-modular was given. +if test "${enable_modular+set}" = set; then : + enableval=$enable_modular; +else + enable_modular=no +fi + + +if test $usingTcl ; then + if test "x$enable_modular" = "xyes" ; then + programs="$programs ext2sim ext2spice" + $as_echo "#define EXT2SPICE_AUTO 1" >>confdefs.h + + $as_echo "#define EXT2SIM_AUTO 1" >>confdefs.h + + else + modules="$modules ext2sim ext2spice" + extra_libs="$extra_libs \${MAGICDIR}/ext2sim/libext2sim.o" + extra_libs="$extra_libs \${MAGICDIR}/ext2spice/libext2spice.o" + fi +else + programs="$programs ext2sim ext2spice" + $as_echo "#define EXT2SPICE_AUTO 1" >>confdefs.h + + $as_echo "#define EXT2SIM_AUTO 1" >>confdefs.h + +fi + +# Check whether --enable-locking was given. +if test "${enable_locking+set}" = set; then : + enableval=$enable_locking; +else + enable_locking=yes +fi + + +if test "x$enable_locking" = "xyes" ; then + case $target in + *cygwin*) + ;; + *) + $as_echo "#define FILE_LOCKS 1" >>confdefs.h + + ;; + esac +fi + +# Check whether --enable-calma was given. +if test "${enable_calma+set}" = set; then : + enableval=$enable_calma; +else + enable_calma=yes +fi + + +if test "x$enable_calma" = "xyes" ; then + $as_echo "#define CALMA_MODULE 1" >>confdefs.h + + modules="$modules calma" + extra_libs="$extra_libs \${MAGICDIR}/calma/libcalma.o" +else + unused="$unused calma" +fi + +# Check whether --enable-cif was given. +if test "${enable_cif+set}" = set; then : + enableval=$enable_cif; +else + enable_cif=yes +fi + + +if test "x$enable_cif" = "xyes" ; then + $as_echo "#define CIF_MODULE 1" >>confdefs.h + + modules="$modules cif" + extra_libs="$extra_libs \${MAGICDIR}/cif/libcif.o" +else + unused="$unused cif" +fi + +# Check whether --enable-client-render was given. +if test "${enable_client_render+set}" = set; then : + enableval=$enable_client_render; +else + enable_client_render=yes +fi + + +if test "x$enable_client_render" = "xno" ; then + $as_echo "#define OGL_SERVER_SIDE_ONLY 1" >>confdefs.h + +fi + +# Check whether --enable-invert-y was given. +if test "${enable_invert_y+set}" = set; then : + enableval=$enable_invert_y; +else + enable_invert_y=no +fi + + +if test "x$enable_invert_y" = "xyes" ; then + $as_echo "#define OGL_INVERT_Y 1" >>confdefs.h + +fi + +# Check whether --enable-framebuffer-backing-store was given. +if test "${enable_framebuffer_backing_store+set}" = set; then : + enableval=$enable_framebuffer_backing_store; +else + enable_framebuffer_backing_store=no +fi + + +if test "x$enable_framebuffer_backing_store" != "xyes" ; then + $as_echo "#define X11_BACKING_STORE 1" >>confdefs.h + +fi + +# Check whether --enable-plot was given. +if test "${enable_plot+set}" = set; then : + enableval=$enable_plot; +else + enable_plot=yes +fi + + +if test "x$enable_plot" = "xyes" ; then + $as_echo "#define PLOT_MODULE 1" >>confdefs.h + + modules="$modules plot" + extra_libs="$extra_libs \${MAGICDIR}/plot/libplot.o" +else + unused="$unused plot" +fi + +# Check whether --enable-lef was given. +if test "${enable_lef+set}" = set; then : + enableval=$enable_lef; +else + enable_lef=yes +fi + + +if test "x$enable_lef" = "xyes" ; then + $as_echo "#define LEF_MODULE 1" >>confdefs.h + + modules="$modules lef" + extra_libs="$extra_libs \${MAGICDIR}/lef/liblef.o \${MAGICDIR}/extflat/libextflat.o" +else + unused="$unused lef" +fi + +# Check whether --enable-readline was given. +if test "${enable_readline+set}" = set; then : + enableval=$enable_readline; if test $usingTcl ; then + enable_readline=no + fi + +else + if test $usingTcl ; then + enable_readline=no + else + enable_readline=yes + fi + +fi + + +if test "x$enable_readline" = "xyes" ; then + $as_echo "#define USE_READLINE 1" >>confdefs.h + + use_system_readline=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_pre_input_hook in -lreadline" >&5 +$as_echo_n "checking for rl_pre_input_hook in -lreadline... " >&6; } +if ${ac_cv_lib_readline_rl_pre_input_hook+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lreadline $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char rl_pre_input_hook (); +int +main () +{ +return rl_pre_input_hook (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_readline_rl_pre_input_hook=yes +else + ac_cv_lib_readline_rl_pre_input_hook=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_rl_pre_input_hook" >&5 +$as_echo "$ac_cv_lib_readline_rl_pre_input_hook" >&6; } +if test "x$ac_cv_lib_readline_rl_pre_input_hook" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBREADLINE 1 +_ACEOF + + LIBS="-lreadline $LIBS" + +else + use_system_readline=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_username_completion_function in -lreadline" >&5 +$as_echo_n "checking for rl_username_completion_function in -lreadline... " >&6; } +if ${ac_cv_lib_readline_rl_username_completion_function+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lreadline $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char rl_username_completion_function (); +int +main () +{ +return rl_username_completion_function (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_readline_rl_username_completion_function=yes +else + ac_cv_lib_readline_rl_username_completion_function=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_rl_username_completion_function" >&5 +$as_echo "$ac_cv_lib_readline_rl_username_completion_function" >&6; } +if test "x$ac_cv_lib_readline_rl_username_completion_function" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBREADLINE 1 +_ACEOF + + LIBS="-lreadline $LIBS" + +else + use_system_readline=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_filename_completion_function in -lreadline" >&5 +$as_echo_n "checking for rl_filename_completion_function in -lreadline... " >&6; } +if ${ac_cv_lib_readline_rl_filename_completion_function+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lreadline $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char rl_filename_completion_function (); +int +main () +{ +return rl_filename_completion_function (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_readline_rl_filename_completion_function=yes +else + ac_cv_lib_readline_rl_filename_completion_function=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_rl_filename_completion_function" >&5 +$as_echo "$ac_cv_lib_readline_rl_filename_completion_function" >&6; } +if test "x$ac_cv_lib_readline_rl_filename_completion_function" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBREADLINE 1 +_ACEOF + + LIBS="-lreadline $LIBS" + +else + use_system_readline=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_attempted_completion_over in -lreadline" >&5 +$as_echo_n "checking for rl_attempted_completion_over in -lreadline... " >&6; } +if ${ac_cv_lib_readline_rl_attempted_completion_over+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lreadline $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char rl_attempted_completion_over (); +int +main () +{ +return rl_attempted_completion_over (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_readline_rl_attempted_completion_over=yes +else + ac_cv_lib_readline_rl_attempted_completion_over=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_rl_attempted_completion_over" >&5 +$as_echo "$ac_cv_lib_readline_rl_attempted_completion_over" >&6; } +if test "x$ac_cv_lib_readline_rl_attempted_completion_over" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBREADLINE 1 +_ACEOF + + LIBS="-lreadline $LIBS" + +else + use_system_readline=no +fi + + if test $use_system_readline = yes ; then + $as_echo "#define HAVE_READLINE 1" >>confdefs.h + + rl_libs="-lreadline" + else + rl_libs="\${MAGICDIR}/readline/readline/libreadline.a" + CPPFLAGS="$CPPFLAGS -I\${MAGICDIR}/readline" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tgetent in -ltermcap" >&5 +$as_echo_n "checking for tgetent in -ltermcap... " >&6; } +if ${ac_cv_lib_termcap_tgetent+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ltermcap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char tgetent (); +int +main () +{ +return tgetent (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_termcap_tgetent=yes +else + ac_cv_lib_termcap_tgetent=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_termcap_tgetent" >&5 +$as_echo "$ac_cv_lib_termcap_tgetent" >&6; } +if test "x$ac_cv_lib_termcap_tgetent" = xyes; then : + + rl_libs="$rl_libs -ltermcap" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lncurses" >&5 +$as_echo_n "checking for tgetent in -lncurses... " >&6; } +if ${ac_cv_lib_ncurses_tgetent+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lncurses $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char tgetent (); +int +main () +{ +return tgetent (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ncurses_tgetent=yes +else + ac_cv_lib_ncurses_tgetent=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ncurses_tgetent" >&5 +$as_echo "$ac_cv_lib_ncurses_tgetent" >&6; } +if test "x$ac_cv_lib_ncurses_tgetent" = xyes; then : + + rl_libs="$rl_libs -lncurses" + +fi + + +fi + + modules="$modules readline" +else + unused="$unused readline" +fi + +# Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then : + enableval=$enable_threads; if test $usingTcl ; then + enable_threads=no + fi + +else + if test $usingTcl ; then + enable_threads=no + else + enable_threads=yes + fi + +fi + + +if test "x$enable_threads" = "xyes" ; then + usingThreads=1 + $as_echo "#define HAVE_PTHREADS 1" >>confdefs.h + + gr_libs="$gr_libs -lpthread" + gr_srcs="$gr_srcs \${X11THREAD_SRCS}" + gr_hsrcs="" + gr_hprog="" +fi + +# Check whether --enable-route was given. +if test "${enable_route+set}" = set; then : + enableval=$enable_route; +else + enable_route=yes +fi + + +if test "x$enable_route" = "xyes" ; then + $as_echo "#define ROUTE_MODULE 1" >>confdefs.h + + modules="$modules garouter grouter irouter mzrouter router gcr" + programs="$programs net2ir" + extra_libs="$extra_libs \${MAGICDIR}/garouter/libgarouter.o \ + \${MAGICDIR}/mzrouter/libmzrouter.o \${MAGICDIR}/router/librouter.o \ + \${MAGICDIR}/irouter/libirouter.o \${MAGICDIR}/grouter/libgrouter.o \ + \${MAGICDIR}/gcr/libgcr.o" +else + unused="$unused garouter grouter irouter mzrouter router gcr" +fi + +# Check whether --enable-rsim was given. +if test "${enable_rsim+set}" = set; then : + enableval=$enable_rsim; if test $usingTcl ; then + enable_rsim=no + fi + +else + if test $usingTcl ; then + enable_rsim=no + else + enable_rsim=yes + fi + +fi + + +if test "x$enable_rsim" = "xyes" ; then + $as_echo "#define RSIM_MODULE 1" >>confdefs.h + +fi + +# Check whether --enable-new-macros was given. +if test "${enable_new_macros+set}" = set; then : + enableval=$enable_new_macros; +else + enable_new_macros=yes +fi + + +if test "x$enable_new_macros" = "xyes" ; then + $as_echo "#define USE_NEW_MACROS 1" >>confdefs.h + +fi + + +# Check whether --with-opengl was given. +if test "${with_opengl+set}" = set; then : + withval=$with_opengl; + if test "$withval" = "no" -o "$withval" = "NO" ; then + usingOGL= + elif test "$withval" != "no" -a "$withval" != "yes"; then + OGL_INCLUDE_DIR=${withval} + fi + +fi + + + +if test $usingOGL ; then + ac_save_CPPFLAGS="$CPPFLAGS" + if test $OGL_INCLUDE_DIR ; then + CPPFLAGS="$CPPFLAGS -I$OGL_INCLUDE_DIR" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + ac_fn_c_check_header_mongrel "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default" +if test "x$ac_cv_header_GL_gl_h" = xyes; then : + +else + + echo "GL header files not found, disabling OpenGL" + usingOGL= + +fi + + + CPPFLAGS="$ac_save_CPPFLAGS" +fi + +if test $usingOGL ; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS -lm" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glXCreateContext in -lGL" >&5 +$as_echo_n "checking for glXCreateContext in -lGL... " >&6; } +if ${ac_cv_lib_GL_glXCreateContext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGL $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char glXCreateContext (); +int +main () +{ +return glXCreateContext (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_GL_glXCreateContext=yes +else + ac_cv_lib_GL_glXCreateContext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GL_glXCreateContext" >&5 +$as_echo "$ac_cv_lib_GL_glXCreateContext" >&6; } +if test "x$ac_cv_lib_GL_glXCreateContext" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGL 1 +_ACEOF + + LIBS="-lGL $LIBS" + +else + + echo "GL library files not found, disabling OpenGL" + usingOGL= + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gluNewTess in -lGLU" >&5 +$as_echo_n "checking for gluNewTess in -lGLU... " >&6; } +if ${ac_cv_lib_GLU_gluNewTess+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGLU $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gluNewTess (); +int +main () +{ +return gluNewTess (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_GLU_gluNewTess=yes +else + ac_cv_lib_GLU_gluNewTess=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GLU_gluNewTess" >&5 +$as_echo "$ac_cv_lib_GLU_gluNewTess" >&6; } +if test "x$ac_cv_lib_GLU_gluNewTess" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGLU 1 +_ACEOF + + LIBS="-lGLU $LIBS" + +else + + echo "GLU library files not found; disabling font rendering" + use_libglu="" + +fi + + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +fi + +if test "x$use_libglu" != "x" ; then + $as_echo "#define VECTOR_FONTS 1" >>confdefs.h + +fi + +if test $usingOGL ; then + if test $OGL_INCLUDE_DIR ; then + gr_cflags="${gr_cflags} -I${OGL_INCLUDE_DIR}" + fi +fi + + +if test $usingTcl ; then + cadinstall="$cadinstall graphics tcltk" + modules="$modules tcltk" + unused="$unused lisp" + programs="$programs tcltk" + ALL_TARGET="tcl" + INSTALL_TARGET="install-tcl" + $as_echo "#define MAGIC_WRAPPER 1" >>confdefs.h + + extra_libs="$extra_libs \${MAGICDIR}/tcltk/libtcltk.o" + extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\"" +elif test $usingScheme ; then + modules="$modules lisp" + unused="$unused tcltk" + cadinstall="$cadinstall lisp" + extra_libs="$extra_libs \${MAGICDIR}/lisp/liblisp.o" + programs="$programs extcheck graphics" + $as_echo "#define SCHEME_INTERPRETER 1" >>confdefs.h + +else + unused="$unused lisp tcltk" + programs="$programs extcheck graphics" +fi + + +if test $usingTcl ; then + if test $usingX11 ; then + gr_dflags="$gr_dflags -DX11 -DXLIB" + gr_libs="$gr_libs -lX11" + gr_srcs="$gr_srcs \${TK_SRCS}" + fi + if test $usingOGL ; then + $as_echo "#define THREE_D 1" >>confdefs.h + + gr_dflags="$gr_dflags -DOGL" + gr_libs="$gr_libs -lGL ${use_libglu} ${use_libxi} ${use_libxmu} ${use_libxext} -lm" + gr_srcs="$gr_srcs \${TOGL_SRCS}" + if ! test $usingX11 ; then + usingX11=1 + gr_dflags="$gr_dflags -DXLIB" + gr_libs="$gr_libs -lX11" + fi + fi + gr_srcs="$gr_srcs \${TKCOMMON_SRCS}" +else + if test $usingX11 ; then + gr_dflags="$gr_dflags -DX11 -DXLIB" + gr_libs="$gr_libs -lX11" + gr_srcs="$gr_srcs \${X11_SRCS}" + fi + if test $usingOGL ; then + gr_dflags="$gr_dflags -DOGL" + gr_libs="$gr_libs -lGL ${use_libglu} ${use_libxi} ${use_libxmu} ${use_libxext} -lm" + gr_srcs="$gr_srcs \${OGL_SRCS}" + if ! test $usingX11 ; then + usingX11=1 + gr_libs="$gr_libs -lX11" + gr_dflags="$gr_dflags -DXLIB" + fi + fi + if test $usingX11 ; then + if ! test $usingThreads; then + gr_dflags="$gr_dflags -DX11HELP_PROG=\\\"\${X11HELP_PROG}\\\"" + gr_hsrcs="$gr_hsrcs \${X11HELPER_SRCS}" + gr_hprog="$gr_hprog \${X11HELP_PROG}" + fi + fi +fi + + +case $target in + *-linux*) + $as_echo "#define linux 1" >>confdefs.h + + $as_echo "#define SYSV 1" >>confdefs.h + + $as_echo "#define ISC 1" >>confdefs.h + + case $target in + *x86_64*) + CFLAGS="${CFLAGS} -m64 -fPIC" + ;; + esac + if test $usingOGL ; then + gr_libs="$gr_libs -lstdc++" + fi + if test -f /usr/lib/libbsd-compat.a ; then + gr_libs="$gr_libs -lbsd-compat" + elif test -f /usr/lib/libbsd.a ; then + gr_libs="$gr_libs -lbsd" + fi + ;; + *solaris*) + $as_echo "#define SYSV 1" >>confdefs.h + + ;; + *irix*) + $as_echo "#define SYSV 1" >>confdefs.h + + $as_echo "#define IRIX 1" >>confdefs.h + + $as_echo "#define _BSD_SIGNALS 1" >>confdefs.h + + ;; + *sysv*) + $as_echo "#define SYSV 1" >>confdefs.h + + ;; + *cygwin*) + $as_echo "#define CYGWIN 1" >>confdefs.h + + $as_echo "#define i386 1" >>confdefs.h + + ;; + *darwin*) + if test "$CPP" = "cc -E" ; then + CPPFLAGS="$CPPFLAGS -no-cpp-precomp" + fi + ;; +esac + +# ----------------------------------------------------------------------- +# Tcl/Tk configuration +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + +# ----------------------------------------------------------------------- +# +# Tk libraries and header files +# +# ----------------------------------------------------------------------- + if test "${TK_INC_DIR}" != "/usr/include" ; then + INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}" + fi + if test "${TK_LIB_DIR}" = "/usr/lib" -o \ + "${TK_LIB_DIR}" = "/usr/lib64" ; then + LIB_SPECS="${LIB_SPECS} ${TK_LIB_SPEC}" + else + LIB_SPECS="${LIB_SPECS} -L${TK_LIB_DIR} ${TK_LIB_SPEC}" + if test "x${loader_run_path}" = "x" ; then + loader_run_path="${TK_LIB_DIR}" + else + loader_run_path="${TK_LIB_DIR}:${loader_run_path}" + fi + fi + +# ----------------------------------------------------------------------- +# +# Tcl libraries and header files +# +# Add a header file directory specification only if the Tcl headers reside +# in a different directory from Tk's. +# +# +# ----------------------------------------------------------------------- + if test "${TCL_INC_DIR}" != "/usr/include" -a \ + "${TCL_INC_DIR}" != "${TK_INC_DIR}" ; then + INC_SPECS="${INC_SPECS} -I${TCL_INC_DIR}" + fi + + if test "${TCL_LIB_DIR}" = "/usr/lib" -o \ + "${TCL_LIB_DIR}" = "/usr/lib64" -o \ + "${TCL_LIB_DIR}" = "${TK_LIB_DIR}" ; then + LIB_SPECS="${LIB_SPECS} ${TCL_LIB_SPEC}" + else + LIB_SPECS="${LIB_SPECS} -L${TCL_LIB_DIR} ${TCL_LIB_SPEC}" + if test "x${loader_run_path}" = "x" ; then + loader_run_path="${TCL_LIB_DIR}" + else + loader_run_path="${TCL_LIB_DIR}:${loader_run_path}" + fi + fi + +#-------------------------------------------------------------------- +# +# Check if we can generate shared libraries on this system. Set flags +# to generate shared libraries for systems that we know about. Start +# with the values found in tclConfig.sh, make changes as we know about +# the different systems. +# +#-------------------------------------------------------------------- + +# Initialize shared library build variables + + SHLIB_LD="" + LDDL_FLAGS="-shared" + SHDLIB_EXT=".so" + EXTRA_LIB_SPECS="" + + build_shared="yes" + + case $target in + *-aix4.[2-9]*) + # No Position-Independent flags needed + + # Use the installed export file or the one found in the source directory. + + if test -r "${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" ; then + tcl_exp="${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" + else + tcl_exp="${TCL_SRC_DIR}/unix/lib.exp" + fi + if test -r "${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" ; then + tk_exp="${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" + else + tk_exp="${TK_SRC_DIR}/unix/lib.exp" + fi + + full_src_path=`cd ${srcdir}; pwd` + + # Use shell-script to link shared library + LD="${full_src_path}/cf/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry -bI:${tk_exp} -bI:${tcl_exp}" + + SHLIB_LIB_SPECS="${aix_lib_specs} -lc" + + LDFLAGS="-L${loader_run_path}" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-aix*) + # No Position-Independent flags needed + + # Use the installed export file or the one found in the source directory. + + if test -r "${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" ; then + tcl_exp="${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" + else + tcl_exp="${TCL_SRC_DIR}/unix/lib.exp" + fi + if test -r "${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" ; then + tk_exp="${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" + else + tk_exp="${TK_SRC_DIR}/unix/lib.exp" + fi + + full_src_path=`cd ${srcdir}/cf; pwd` + + # Use shell-script to link shared library + + LD="${full_src_path}/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry -bI:${tk_exp} -bI:${tcl_exp}" + SHLIB_LIB_SPECS="${aix_lib_specs} -lc" + LDFLAGS="-L${loader_run_path}" + EXTRA_LIB_SPECS="-lld" + ;; + + *-bsdi2*|*-bsdi3*) + LD="shlicc" + LDDL_FLAGS="-r" + EXTRA_LIB_SPECS="-ldl" + ;; + + *darwin*) + SHDLIB_EXT=".dylib" + LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind" + LDFLAGS="${LDFLAGS} ${LIB_SPECS}" + CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -fno-common" + ;; + + *cygwin*) + SHDLIB_EXT=".dll" + $as_echo "#define USE_DL_IMPORT 1" >>confdefs.h + + LDDL_FLAGS='-shared -Wl,--enable-auto-image-base' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + ld_extra_libs=${LIB_SPECS} + sub_extra_libs='-L${MAGICDIR}/magic -ltclmagic' + ;; + + *-bsdi4*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + LDDL_FLAGS='-shared -Wl,-E -Wl,-soname,$@' + ;; + + *-dgux*) + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-hpux*) + if test "$GCC" = "no" ; then + $as_echo "#define _HPUX_SOURCE 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + found=yes +else + found=no +fi + + if test "${found}" = "yes" ; then + SHLIB_CFLAGS="+z" + LDDL_FLAGS="-b -E -n +s +b,${loader_run_path}:." + SHDLIB_EXT=".sl" + + # The run path is included in both LDFLAGS and LDDL_FLAGS + # because SHLIB_LD is ld and LD is cc/gcc. + + LDFLAGS="-Wl,-E -Wl,+s,+b,${loader_run_path}:." + EXTRA_LIB_SPECS="-ldld" + fi + ;; + + *-irix64-6.5*) + LDDL_FLAGS="-32 -shared -rdata_shared" + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + ;; + + *-irix-56.*|*-irix64-*) + LDDL_FLAGS="-shared -rdata_shared" + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + LDFLAGS="" + if test "$GCC" = "yes" ; then + SHLIB_CFLAGS="-mabi=n32 $SHLIB_CFLAGS" + LDDL_FLAGS="-mabi=n32 $LDDL_FLAGS" + LDFLAGS="-mabi=n32 $LDFLAGS" + else + CFLAGS="-n32 $CFLAGS" + LDFLAGS="-n32 $LDFLAGS" + fi + ;; + + *-linux*) + LDDL_FLAGS='-shared -Wl,-soname,$@' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + LDFLAGS="" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-mp-ras-02*) + SHLIB_CFLAGS="-G -K PIC" + LDDL_FLAGS="" + ;; + + *-mp-ras-*) + SHLIB_CFLAGS="-G -K PIC" + LDDL_FLAGS="-Wl,-Bexport" + ;; + + *-ncr-sysv4-*2*) + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-ncr-sysv4*) + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G -Wl,-Bexport" + + LDFLAGS="-Wl,-Bexport" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-freebsd*) + # Not available on all versions: check for include file. + SHLIB_CFLAGS="-fpic" + LDDL_FLAGS="-shared ${LIB_SPECS}" + CFLAGS="${CFLAGS} -l/usr/X11R6/include" + ;; + + *-netbsd*|*-openbsd*) + # Not available on all versions: check for include file. + ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + test_ok=yes +else + test_ok=no +fi + + + if test "$test_ok" = yes; then + SHLIB_CFLAGS="-fPIC" + LDDL_FLAGS="-shared ${LIB_SPEC}" + fi + ;; + + *-nextstep*) + LDDL_FLAGS="-nostdlib -r" + ;; + + *-osf1-1.012*) + # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 + + # Warning: Ugly Makefile Hack + # Make package name same as library name + + SHLIB_LD='ld -R -export $@:' + ;; + + *-osf1-1.*) + # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 + + SHLIB_CFLAGS="-fpic" + SHLIB_LD="ld -shared" + ;; + + *-osf1V*) + # Digital OSF/1 + + LDDL_FLAGS='-shared -expect_unresolved "*"' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + LDFLAGS="" + ;; + + *-sco*) + # Note, dlopen is available only on SCO 3.2.5 and greater. However, + # this test works, since "uname -s" was non-standard in 3.2.4 and + # below. + + SHLIB_CFLAGS="-Kpic -belf" + LDDL_FLAGS="-G" + LDFLAGS="-belf -Wl,-Bexport" + ;; + + *-sni-sysv*) + + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-sunos4*) + + SHLIB_CFLAGS="-PIC" + LDDL_FLAGS="-assert pure-text" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-solaris2*) + + if test "$with_gnu_ld" = "yes" ; then + LDDL_FLAGS='-shared -Wl,-E -Wl,-soname,$@ ${LIB_SPEC}' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + else + LDDL_FLAGS="-shared -mimpure-text" + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -R ${loader_run_path}" + fi + fi + EXTRA_LIB_SPECS="-ldl" + ;; + + *-mips-dde-sysv*) + + SHLIB_CFLAGS="-KPIC" + LDDL_FLAGS="-G" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-pc-sysv4* | *-unixware-5*) + SHLIB_CFLAGS="-G -KPIC" + LDDL_FLAGS=" -Wl,-Bexport" + ;; + + esac + +# If we're running gcc, then set SHLIB_CFLAGS flags for compiling +# shared libraries for gcc, instead of those of the vendor's compiler. + + if test "$GCC" = "yes" ; then + case $target in + *cygwin*) + ;; + *) + SHLIB_CFLAGS="-Wimplicit-int -fPIC" + ;; + esac + fi + if test "$with_gnu_ld" = "yes" ; then + LDDL_FLAGS="${LDDL_FLAGS} -Wl,--version-script=\${MAGICDIR}/magic/symbol.map" + fi + + + + + + + + + + + + + + + +fi + +if test "$GCC" = "yes" ; then + DEPEND_FLAG="-MM" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ac_config_files="$ac_config_files defs.mak" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "defs.mak") CONFIG_FILES="$CONFIG_FILES defs.mak" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + + +ECHO_N=printf + +echo +echo "-----------------------------------------------------------" +echo "Configuration Summary (principle requirements):" +echo + +${ECHO_N} "X11: " +if test $usingX11 ; then + echo "yes" +else + echo "no" + echo + echo " Magic requires X11 for all graphics operations. Without it," + echo " magic can only be run in batch mode using option '-dnull'." + echo " Generally, not finding X11 means that paths to header files" + echo " and/or libraries are missing or in an unexpected place. Try" + echo " using configure options --x-includes= and --x-libraries=." + echo +fi + +${ECHO_N} "OpenGL: " +if test $usingOGL ; then + echo "yes" + ${ECHO_N} "Vector fonts: " + if test "x$use_libglu" != "x" ; then + echo "yes" + else + echo "no" + fi +else + echo "no" + echo + echo " OpenGL graphics are considerably better than the standard 8-bit" + echo " and 24-bit X11 graphics, provided that you have a video card and" + echo " driver supporting accelerated OpenGL graphics. If you get this" + echo " message, you may need to download OpenGL libraries and header" + echo " files, which are usually available from the video card manufacturer." + echo " Magic with un-accelerated OpenGL, such as using Mesa GL without" + echo " a supported graphics card, is usually a very bad combination." + echo +fi + +if test $usingTcl ; then + ${ECHO_N} "Tcl/Tk: " + echo "yes" +else + if test $usingScheme ; then + ${ECHO_N} "Scheme: " + echo "yes" + else + ${ECHO_N} "Tcl/Tk: " + echo "no" + echo + echo " Without Tcl/Tk, you cannot run the enhanced version of magic" + echo " with the toolbar and menus, and a number of other functions" + echo " are disabled. If you did not specifically disable Tcl/Tk on" + echo " the configure command line, then getting this message means" + echo " that you do not have Tcl/Tk headers and or libraries installed," + echo " or they are not in a standard path. Try using configure options" + echo " --with-tcl= and --with-tk=." + echo + fi +fi + +echo "-----------------------------------------------------------" +echo + +echo "Use 'make' to compile and 'make install' to install." +echo +echo "Errors may not be printed to stdout: see files 'make.log' " +echo " and 'install.log' for complete error summary." +echo +echo "-----------------------------------------------------------" +echo + +cp defs.mak .. diff --git a/scripts/configure.in b/scripts/configure.in new file mode 100644 index 00000000..c650efb4 --- /dev/null +++ b/scripts/configure.in @@ -0,0 +1,1777 @@ +dnl Process this file with autoconf to produce a configure script. +dnl Use autoconf 2.52 or newer. + +AC_INIT(magic,, magic-hackers@csl.cornell.edu) +AC_PREREQ(2.52) +AC_CONFIG_SRCDIR(rules.mak) +AC_CONFIG_AUX_DIR(.) + +AC_CANONICAL_SYSTEM + +dnl pass the version string on the the makefiles +PACKAGE=magic + +MAGIC_VERSION=`cat ../VERSION | cut -d. -f1-2` +MAGIC_REVISION=`cat ../VERSION | cut -d. -f3` +AC_DEFINE_UNQUOTED(MAGIC_VERSION, "${MAGIC_VERSION}") +AC_DEFINE_UNQUOTED(MAGIC_REVISION, "${MAGIC_REVISION}") + +dnl Override default target when compiling under TCL +ALL_TARGET="standard" +INSTALL_TARGET="install-magic" + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_ISC_POSIX +AC_PROG_INSTALL +AC_PROG_RANLIB + +dnl GNU M4 is preferred due to some of the option switches. +AC_PATH_PROGS([M4], [gm4 gnum4 m4], [no]) +if test x$M4 = xno; then + AC_MSG_ERROR([M4 is required]) +fi + +dnl check size of pointer for correct behavior on 64-bit systems +dnl If the C preprocessor is GCC, we need to force the flag to +dnl assert that input files are of type C, or else the preprocessing +dnl stage will not execute correctly on the ".in" files in the scmos +dnl directory. + +if test "$CPP" = "$CC -E" ; then + CPP="$CPP -x c" +fi + +dnl check if the linker is a GNU linker + +#------------------------------------------------------------ +# AC_PROG_LD - find the path to the GNU or non-GNU linker +# (This stuff ripped from libtool) +#------------------------------------------------------------ +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld assume the C compiler uses GNU ld [[default=no]]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +dnl ###not for PostgreSQL### AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case "$ac_prog" in + # Accept absolute paths. +changequote(,)dnl + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' +changequote([,])dnl + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(ac_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$ac_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_PROG_LD_GNU +]) + +AC_DEFUN([AC_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi]) +with_gnu_ld=$ac_cv_prog_gnu_ld +]) + +AC_PROG_LD + +AC_CHECK_SIZEOF([void *], 4) +AC_CHECK_SIZEOF([unsigned int], 4) +AC_CHECK_SIZEOF([unsigned long], 4) +AC_CHECK_SIZEOF([unsigned long long], 8) + +dnl Check byte arrangement for doubleint routines +AC_C_BIGENDIAN + +dnl Check for required header files +AC_HEADER_STDC + +dnl Need either setenv or putenv +AC_CHECK_FUNCS(setenv putenv) + +dnl Check for vfork +AC_CHECK_FUNC(vfork) + +dnl Check for +AC_CHECK_HEADERS(sys/mman.h) + +dnl Check for +AC_CHECK_HEADERS(dirent.h) + +dnl Check for +AC_CHECK_HEADERS(limits.h) + +dnl Check for +AC_CHECK_HEADERS(param.h) + +dnl Check for +AC_CHECK_HEADERS(paths.h) + +dnl Check for va_copy +AC_CACHE_CHECK([for va_copy], ac_cv_c_va_copy, + AC_TRY_LINK( + [#include ], + [va_list ap1, ap2; + va_copy(ap1,ap2); + ], + [ac_cv_c_va_copy="yes"], + [ac_cv_c_va_copy="no"]) + ) +if test "$ac_cv_c_va_copy" = "yes" +then + AC_DEFINE(HAVE_VA_COPY, 1, [Define if we have va_copy]) +fi +AC_CACHE_CHECK([for __va_copy], ac_cv_c___va_copy, + AC_TRY_LINK( + [#include ], + [va_list ap1, ap2; + __va_copy(ap1,ap2); + ], + [ac_cv_c___va_copy="yes"], + [ac_cv_c___va_copy="no"]) + ) +if test "$ac_cv_c___va_copy" = "yes" +then + AC_DEFINE(HAVE___VA_COPY, 1, [Define if we have __va_copy]) +fi + +dnl Check for some C99 functions + +dnl Built-in round/roundf require CFLAGS -std=c99, but this also +dnl requires that all functions be declared explicitly! For now, +dnl built-in functions are disabled, with macros used instead. + +dnl NOTE---Bug in the x86_64 math library; round() and roundf() are incorrect. + +case $target in + *x86_64*) ;; + *) + AC_CACHE_CHECK([for built-in roundf], ac_cv_c_roundf, + AC_TRY_LINK( + [#include ], + [float f; + f = roundf(1.5); + ], + [ac_cv_c_roundf="yes"], + [ac_cv_c_roundf="no"]) + ) + if test "$ac_cv_c_roundf" = "no" + then + # Check fo C99 function from libm + AC_CHECK_LIB([m],[roundf],[AC_DEFINE([HAVE_ROUNDF],[1],["c99 function"])]) + fi + + AC_CACHE_CHECK([for built-in round], ac_cv_c_round, + AC_TRY_LINK( + [#include ], + [double d; + d = round(1.5); + ], + [ac_cv_c_round="yes"], + [ac_cv_c_round="no"]) + ) + if test "$ac_cv_c_round" = "no" + then + # Check fo C99 function from libm + AC_CHECK_LIB([m],[round],[AC_DEFINE([HAVE_ROUND],[1],["c99 function"])]) + fi + ;; +esac + +extra_defs="$extra_defs -DCAD_DIR=\\\"\${LIBDIR}\\\" -DBIN_DIR=\\\"\${BINDIR}\\\"" +X_LIBS= +X_CFLAGS= +CPPFLAGS= +INC_SPECS= +DEPEND_FLAG= +SHLIB_CFLAGS="" +LD_RUN_PATH="" +WISH_EXE="" +TCLSH_EXE="" + +modules="" +unused="" +cadinstall="" +extra_libs="" +top_extra_libs="" +sub_extra_libs="" +ld_extra_libs="" +ld_extra_objs="" +programs="" +rl_defs= +rl_libs= +gr_cflags= +gr_dflags= +gr_libs= +gr_srcs= +gr_hsrcs= +gr_hprog= + +magic_with_tcl="yes" +magic_with_tk="yes" +magic_with_tcl_includes="" +magic_with_tk_includes="" +magic_with_tcl_libraries="" +magic_with_tk_libraries="" + +dnl We will attempt to configure with Tcl/Tk and OpenGL. However, +dnl if checks for the appropriate header and library files fail, +dnl we will revert to non-Tcl and/or non-OpenGL compilation. +dnl Compilation for Tcl/Tk may be explicitly prohibited by using +dnl --with-tcl=no or --with-interpreter=no, and OpenGL may be +dnl disabled with --with-opengl=no + +usingOGL=1 +use_libglu="-lGLU" +usingTcl=1 +usingOA=0 + +dnl Check for gcore, used by niceabort.c + +AC_PATH_PROG(GCORE, gcore, [no]) + +dnl Check for /bin/csh; warn if not available. We should do something +dnl here to get makedbh to run under other common conditions, such as +dnl csh not being in /bin, or only tcsh being available. + +AC_PATH_PROG(CSH, csh, [no]) + +if test "x${CSH}" = "x"; then + AC_MSG_ERROR([cannot find /bin/csh---cannot compile!]) +fi + +dnl Check for X enabled/disabled + +AC_PATH_XTRA + +if test "x${X_DISPLAY_MISSING}" = "x"; then + usingX11=1 +else + AC_MSG_ERROR([Unable to find X11---compiling without graphics]) + echo Cannot find X11---will attempt to compile anyway. + echo Graphics options will be NULL only! + if test $usingOGL ; then + echo "Cannot use OpenGL/GLX without X11, disabling." + usingOGL= + fi + if test $usingTcl ; then + echo "Cannot compile TCL version without X11, disabling." + usingTcl= + fi +fi + +# Check for libXi, which is required on some systems but not available on +# others. +use_libxi="" +use_libxmu="" +use_libxext="" +AC_CHECK_LIB([Xi], [XOpenDevice], use_libxi="-lXi") +AC_CHECK_LIB([Xmu], [XmuInternAtom], use_libxmu="-lXmu") +AC_CHECK_LIB([Xext], [XextFindDisplay], use_libxext="-lXext") + +AC_ARG_WITH(interpreter, +[ --with-interpreter=[arg] enable interpreter (tcl, scheme, or no)], [ + if test "$withval" = "no" -o "$withval" = "NO"; then + usingTcl= + elif test "$withval" = "scheme" -o "$withval" = "SCHEME"; then + usingScheme=1 + usingTcl= + elif test "$withval" != "tcl" -a "$withval" != "TCL"; then + echo "Unknown option to --with-interpreter: Must be scheme, tcl, or no." + exit 1 + fi +], ) + +AC_ARG_WITH(tcl, +[ --with-tcl=DIR Find tclConfig.sh in DIR], [ + magic_with_tcl=$withval + if test "$withval" = "no" -o "$withval" = "NO"; then + usingTcl= + elif test $usingScheme ; then + echo Attempt to enable both Tcl and Scheme interpreters. + echo Disabling Tcl, and using Scheme instead. + usingTcl= + fi +], ) + +dnl ---------------------------------------------------------------- +dnl Do our best to find Tcl/Tk. If we can't, then flag a warning +dnl and don't set the usingTcl variable. +dnl +dnl This has been broken up into a number of sections, each of which +dnl depends independently on the setting of usingTcl. +dnl ---------------------------------------------------------------- + +AC_ARG_WITH(tk, [ --with-tk=DIR Find tkConfig.sh in DIR], + magic_with_tk=$withval) +AC_ARG_WITH(tclincls, [ --with-tclincls=DIR Find tcl.h in DIR], + magic_with_tcl_includes=$withval) +AC_ARG_WITH(tkincls, [ --with-tkincls=DIR Find tk.h in DIR], + magic_with_tk_includes=$withval) +AC_ARG_WITH(tcllibs, [ --with-tcllibs=DIR Find Tcl library in DIR], + magic_with_tcl_libraries=$withval) +AC_ARG_WITH(tklibs, [ --with-tklibs=DIR Find Tk library in DIR], + magic_with_tk_libraries=$withval) + +# ----------------------------------------------------------------------- +# Find the Tcl build configuration file "tclConfig.sh" +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + TCL_INC_DIR="." + TK_INC_DIR="." + + AC_MSG_CHECKING([for tclConfig.sh]) + tcl_config_sh="" + + if test "$magic_with_tcl" = "no" ; then + magic_with_tcl="" + elif test "$magic_with_tcl" != "yes" ; then + # + # Verify that a tclConfig.sh file exists in the directory specified + # by --with-tcl. + # + for dir in \ + $magic_with_tcl + do + if test -r "$dir/tclConfig.sh" ; then + tcl_config_sh="$dir/tclConfig.sh" + break + elif test -r "$dir/lib/tclConfig.sh" ; then + tcl_config_sh="$dir/lib/tclConfig.sh" + break + elif test -r "$dir/unix/tclConfig.sh" ; then + tcl_config_sh="$dir/unix/tclConfig.sh" + break + fi + done + else + # + # Otherwise, search for Tcl configuration file. + # + + # 1. Search previously named locations. + + for dir in \ + $prefix \ + $exec_prefix + do + if test -r "$dir/tclConfig.sh" ; then + tcl_config_sh="$dir/tclConfig.sh" + break + elif test -r "$dir/lib/tclConfig.sh" ; then + tcl_config_sh="$dir/lib/tclConfig.sh" + break + elif test -r "$dir/unix/tclConfig.sh" ; then + tcl_config_sh="$dir/unix/tclConfig.sh" + break + fi + done + + # 2. Search standard locations. + # (1/25/05---/usr/lib added for Ubuntu Linux) + # (6/19/06---/usr/lib64 added for 64-bit architectures + + if test "x$tcl_config_sh" = "x" ; then + for dir in \ + `ls -dr /usr/local/tcl/tcl[[7-9]].[[0-9]]* 2>/dev/null` \ + /usr/local/tcl \ + /usr/local/lib \ + /usr/lib64 \ + /usr/local \ + `ls -dr /usr/lib/tcl[[7-9]].[[0-9]]* 2>/dev/null` \ + /sw/lib \ + /usr + do + if test -r "$dir/tclConfig.sh" ; then + tcl_config_sh="$dir/tclConfig.sh" + break + elif test -r "$dir/lib/tclConfig.sh" ; then + tcl_config_sh="$dir/lib/tclConfig.sh" + break + fi + done + fi + fi + + AC_MSG_RESULT([${tcl_config_sh}]) + + if test "x$tcl_config_sh" = "x" ; then + echo "Can't find Tcl configuration script \"tclConfig.sh\"" + echo "Reverting to non-Tcl compilation" + usingTcl= + fi +fi + +# ----------------------------------------------------------------------- +# Find the Tk build configuration file "tkConfig.sh" +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + + AC_MSG_CHECKING([for tkConfig.sh]) + tk_config_sh="" + if test "$magic_with_tk" != "yes"; then + # + # Verify that a tkConfig.sh file exists in the directory specified + # by --with-tcl or --with-tk. + # + for dir in \ + $magic_with_tk \ + $magic_with_tcl + do + if test -r "$dir/tkConfig.sh" ; then + tk_config_sh="$dir/tkConfig.sh" + break + elif test -r "$dir/lib/tkConfig.sh" ; then + tk_config_sh="$dir/lib/tkConfig.sh" + break + elif test -r "$dir/unix/tkConfig.sh" ; then + tk_config_sh="$dir/unix/tkConfig.sh" + break + fi + done + else + # + # Search for Tk configuration file. + # + + # + # 1. Search previously named locations. + # + for dir in \ + $prefix \ + $exec_prefix + do + if test -r "$dir/tkConfig.sh" ; then + tk_config_sh="$dir/tkConfig.sh" + break + elif test -r "$dir/lib/tkConfig.sh" ; then + tk_config_sh="$dir/lib/tkConfig.sh" + break + elif test -r "$dir/unix/tkConfig.sh" ; then + tk_config_sh="$dir/unix/tkConfig.sh" + break + fi + done + # + # 2. Search standard locations. + # + if test "x$tk_config_sh" = "x" ; then + for dir in \ + `ls -dr /usr/local/tcl/tcl[[7-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr /usr/local/tk/tk[[7-9]].[[0-9]]* 2>/dev/null` \ + /usr/local/tcl \ + /usr/local/lib \ + /usr/lib64 \ + /usr/local \ + `ls -dr /usr/lib/tcl[[7-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr /usr/lib/tk[[7-9]].[[0-9]]* 2>/dev/null` \ + /sw/lib \ + ${x_libraries} \ + /usr + do + if test -r "$dir/tkConfig.sh" ; then + tk_config_sh="$dir/tkConfig.sh" + break + elif test -r "$dir/lib/tkConfig.sh" ; then + tk_config_sh="$dir/lib/tkConfig.sh" + break + fi + done + fi + fi + AC_MSG_RESULT([${tk_config_sh}]) + + if test "x$tk_config_sh" = "x" ; then + echo "can't find Tk configuration script \"tkConfig.sh\"" + echo "Reverting to non-Tcl compilation" + usingTcl= + fi +fi + +# ----------------------------------------------------------------------- +# Source in the Tcl/Tk configuration scripts. +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + . $tcl_config_sh + . $tk_config_sh + + # Should probably trust the config file contents, but this configure + # file checks the Tcl and Tk include and lib directories. Since + # the config file doesn't separate out the libraries from the strings + # passed to the compiler/linker, do it manually here. + # + # Extract TCL_LIB_DIR from TCL_LIB_SPEC + # Extract TK_LIB_DIR from TK_LIB_SPEC + # Extract TCL_INC_DIR from TCL_INCLUDE_SPEC + # Extract TK_INC_DIR from TK_INCLUDE_SPEC + # + # These will be the defaults unless overridden by configure command line + + tmpstr=${TCL_LIB_SPEC#*-L} + TCL_LIB_DIR=${tmpstr% -l*} + tmpstr=${TK_LIB_SPEC#*-L} + TK_LIB_DIR=${tmpstr% -l*} + TCL_INC_DIR=${TCL_INCLUDE_SPEC#*-I} + TK_INC_DIR=${TK_INCLUDE_SPEC#*-I} + + if test "$TCL_VERSION" = "7.6" -a "$TK_VERSION" = "4.2" ; then + : + elif test "$TCL_VERSION" = "7.5" -a "$TK_VERSION" = "4.1" ; then + : + elif test "$TCL_VERSION" = "$TK_VERSION" ; then + : + else + echo "Mismatched Tcl/Tk versions ($TCL_VERSION != $TK_VERSION)" + echo "Reverting to non-Tcl compile" + usingTcl= + fi +fi + +if test $usingTcl ; then + if test "x${magic_with_tcl_includes}" != "x" ; then + if test -r "${magic_with_tcl_includes}/tcl.h" ; then + TCL_INC_DIR=${magic_with_tcl_includes} + else + echo "Can't find tcl.h in \"${magic_with_tcl_includes}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for dir in \ + ${TCL_PREFIX}/include/tcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION} \ + ${TCL_PREFIX}/include \ + ${TCL_SRC_DIR}/generic \ + ${TCL_INC_DIR} + do + if test -r "$dir/tcl.h" ; then + TCL_INC_DIR=$dir + break + fi + done + if test "x${TCL_INC_DIR}" = "x" ; then + echo "Can't find tcl.h header file" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +if test $usingTcl ; then + if test "x${magic_with_tk_includes}" != "x" ; then + if test -r "${magic_with_tk_includes}/tk.h" ; then + TK_INC_DIR=${magic_with_tk_includes} + else + echo "Can't find tk.h in \"${magic_with_tk_includes}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for dir in \ + ${TK_PREFIX}/include/tk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION} \ + ${TK_PREFIX}/include \ + ${TK_SRC_DIR}/generic \ + ${TK_INC_DIR} \ + ${TCL_INC_DIR} + do + if test -r "$dir/tk.h" ; then + TK_INC_DIR=$dir + break + fi + done + if test "x${TK_INC_DIR}" = "x" ; then + echo "Can't find tk.h header file" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +# FIXME -- why are we not using TCL_LIB_FILE FROM tclConfig.sh? +if test $usingTcl ; then + case $target in + *-sunos4*|*-*-netbsd*|NetBSD-*|FreeBSD-*|OpenBSD-*) + TCL_LIB_NAME="tcl${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}" + TK_LIB_NAME="tk${TK_MAJOR_VERSION}${TK_MINOR_VERSION}" + ;; + *) + TCL_LIB_NAME="tcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" + TK_LIB_NAME="tk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}" + ;; + esac + + loclib=`echo ${TCL_LIB_SPEC} | sed -e 's/.*-L//' -e 's/ .*//'` + + if test "x${TCL_LIB_SPEC}" = "x" ; then + TCL_LIB_SPEC="-l${TCL_LIB_NAME}" + fi + if test "x${TK_LIB_SPEC}" = "x" ; then + TK_LIB_SPEC="-l${TK_LIB_NAME}" + fi + +# Find the version of "wish" that corresponds to TCL_EXEC_PREFIX +# We really ought to run "ldd" to confirm that the linked libraries match. + + AC_MSG_CHECKING([for wish executable]) + for dir in \ + ${TK_EXEC_PREFIX}/bin \ + ${TK_EXEC_PREFIX} + do + for wishexe in \ + wish-X11 \ + wish \ + wish${TK_VERSION} \ + wish.exe \ + wish${TK_VERSION}.exe + do + if test -r "$dir/$wishexe" ; then + WISH_EXE=$dir/$wishexe + break + fi + done + if test "x${WISH_EXE}" != "x" ; then + break + fi + done + if test "x${WISH_EXE}" = "x" ; then + echo "Warning: Can't find executable for \"wish\". You may have to" + echo "manually set the value for WISH_EXE in the magic startup script." + AC_MSG_RESULT(no) + else + AC_MSG_RESULT([${WISH_EXE}]) + fi + +# Find the version of "tclsh" that corresponds to TCL_EXEC_PREFIX + + AC_MSG_CHECKING([for tclsh executable]) + for dir in \ + ${TK_EXEC_PREFIX}/bin \ + ${TK_EXEC_PREFIX} + do + for tclshexe in \ + tclsh \ + tclsh${TK_VERSION} \ + tclsh.exe \ + tclsh${TK_VERSION}.exe + do + if test -r "$dir/$tclshexe" ; then + TCLSH_EXE=$dir/$tclshexe + break + fi + done + if test "x${TCLSH_EXE}" != "x" ; then + break + fi + done + if test "x${TCLSH_EXE}" = "x" ; then + echo "Warning: Can't find executable for \"tclsh\"." + AC_MSG_RESULT(no) + else + AC_MSG_RESULT([${TCLSH_EXE}]) + fi + +# Have to define SHDLIB_EXT here even though we have to do it below, too. + case $target in + *-hpux*) + SHDLIB_EXT=".sl" + SHDLIB_EXT_ALT=".sl" + ;; + *cygwin*) + SHDLIB_EXT=".dll" + SHDLIB_EXT_ALT=".dll.a" + ;; + *darwin*) + SHDLIB_EXT=".dylib" + SHDLIB_EXT_ALT=".dylib" + ;; + *) + SHDLIB_EXT=".so" + SHDLIB_EXT_ALT=".so" + ;; + esac + + if test "x${magic_with_tcl_libraries}" != "x" ; then + for libname in \ + "${magic_with_tcl_libraries}/${TCL_LIB_FILE}" \ + "${magic_with_tcl_libraries}/lib${TCL_LIB_NAME}${SHDLIB_EXT}" \ + "${magic_with_tcl_libraries}/lib${TCL_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TCL_LIB_DIR="${magic_with_tcl_libraries}" + break + fi + done + + if test "x${TCL_LIB_DIR}" = "x" ; then + echo "Can't find tcl library in \"${magic_with_tcl_libraries}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for libname in \ + "${loclib:=${TCL_EXEC_PREFIX}/lib}/lib${TCL_LIB_NAME}${SHDLIB_EXT}" \ + "${loclib:=${TCL_EXEC_PREFIX}/lib}/lib${TCL_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TCL_LIB_DIR="${TCL_EXEC_PREFIX}/lib" + break + fi + done + if test "x${TCL_LIB_DIR}" = "x" ; then + echo "Can't find tcl library" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +if test $usingTcl ; then + if test "x${magic_with_tk_libraries}" != "x" ; then + for libname in \ + "${magic_with_tk_libraries}/${TCL_LIB_FILE}" \ + "${magic_with_tk_libraries}/lib${TK_LIB_NAME}${SHDLIB_EXT}" \ + "${magic_with_tk_libraries}/lib${TK_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TK_LIB_DIR="${magic_with_tk_libraries}" + break + fi + done + if test "x${TK_LIB_DIR}" = "x" ; then + echo "Can't find tk library in \"${magic_with_tk_libraries}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for libname in \ + "${loclib:=${TK_EXEC_PREFIX}/lib}/lib${TK_LIB_NAME}${SHDLIB_EXT}" \ + "${loclib:=${TK_EXEC_PREFIX}/lib}/lib${TK_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TK_LIB_DIR="${TK_EXEC_PREFIX}/lib" + break + fi + done + if test "x${TK_LIB_DIR}" = "x" ; then + echo "Can't find tk library" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +dnl ---------------------------------------------------- +dnl End of Tcl/Tk search +dnl ---------------------------------------------------- + +dnl OpenAccess database support. +dnl There should be some checks here to confirm that the libraries +dnl are there, and usable. + +dnl There is no default search path here. Is there a default +dnl installation location for the OpenAccess libraries and include +dnl files? + +AC_ARG_WITH(openaccess, +[ --with-openaccess=DIR use OpenAccess libraries in DIR], [ + if test "$withval" = "no" -o "$withval" = "NO" ; then + OA= + OA_LIBS= + unused="$unused oa" + elif test "$withval" = "yes"; then + AC_MSG_ERROR([path to OpenAccess libraries is required]) + OA= + OA_LIBS= + unused="$unused oa" + else + usingOA=1 + OA=${withval} + OA_LIBS="-L\${OA}/lib -loaDB -loaDD -loaTC -loaBase" + OA_LIBS="${OA_LIBS} -lclalite_sh -lcls_sh -lcdsCommon_sh" + AC_DEFINE(OPENACCESS) + LD_RUN_PATH="-Wl,-rpath=\${OA}/lib" + modules="$modules oa" + extra_libs="$extra_libs \${MAGICDIR}/oa/liboa.o" + fi +]) + +AC_ARG_ENABLE(memdebug, +[ --enable-memdebug enable memory debugging], +[], +[enable_memdebug=no]) + +if test "x$enable_memdebug" = "xyes" ; then + if test "x$magic_with_tcl" = "x" ; then + LIBS="${LIBS} -lefence" + else + AC_DEFINE(TCL_MEM_DEBUG) + fi +fi + +AC_ARG_ENABLE(modular, +[ --enable-modular embed ext2sim and ext2spice packages], +[], +[enable_modular=no]) + +if test $usingTcl ; then + if test "x$enable_modular" = "xyes" ; then + programs="$programs ext2sim ext2spice" + AC_DEFINE(EXT2SPICE_AUTO) + AC_DEFINE(EXT2SIM_AUTO) + else + modules="$modules ext2sim ext2spice" + extra_libs="$extra_libs \${MAGICDIR}/ext2sim/libext2sim.o" + extra_libs="$extra_libs \${MAGICDIR}/ext2spice/libext2spice.o" + fi +else + programs="$programs ext2sim ext2spice" + AC_DEFINE(EXT2SPICE_AUTO) + AC_DEFINE(EXT2SIM_AUTO) +fi + +AC_ARG_ENABLE(locking, +[ --disable-locking disable file locking], +[], +[enable_locking=yes]) + +if test "x$enable_locking" = "xyes" ; then + case $target in + *cygwin*) + ;; + *) + AC_DEFINE(FILE_LOCKS) + ;; + esac +fi + +AC_ARG_ENABLE(calma, +[ --disable-calma disable calma package], +[], +[enable_calma=yes]) + +if test "x$enable_calma" = "xyes" ; then + AC_DEFINE(CALMA_MODULE) + modules="$modules calma" + extra_libs="$extra_libs \${MAGICDIR}/calma/libcalma.o" +else + unused="$unused calma" +fi + +AC_ARG_ENABLE(cif, +[ --disable-cif disable cif package], +[], +[enable_cif=yes]) + +if test "x$enable_cif" = "xyes" ; then + AC_DEFINE(CIF_MODULE) + modules="$modules cif" + extra_libs="$extra_libs \${MAGICDIR}/cif/libcif.o" +else + unused="$unused cif" +fi + +AC_ARG_ENABLE(client-render, +[ --disable-client-render disable OpenGL client-side rendering], +[], +[enable_client_render=yes]) + +if test "x$enable_client_render" = "xno" ; then + AC_DEFINE(OGL_SERVER_SIDE_ONLY) +fi + +AC_ARG_ENABLE(invert-y, +[ --enable-invert-y invert screen top to bottom in OpenGL], +[], +[enable_invert_y=no]) + +if test "x$enable_invert_y" = "xyes" ; then + AC_DEFINE(OGL_INVERT_Y) +fi + +AC_ARG_ENABLE(framebuffer-backing-store, +[ --enable-framebuffer-backing-store enable OpenGL framebuffer backing store], +[], +[enable_framebuffer_backing_store=no]) + +if test "x$enable_framebuffer_backing_store" != "xyes" ; then + AC_DEFINE(X11_BACKING_STORE) +fi + +AC_ARG_ENABLE(plot, +[ --disable-plot disable plot package], +[], +[enable_plot=yes]) + +if test "x$enable_plot" = "xyes" ; then + AC_DEFINE(PLOT_MODULE) + modules="$modules plot" + extra_libs="$extra_libs \${MAGICDIR}/plot/libplot.o" +else + unused="$unused plot" +fi + +AC_ARG_ENABLE(lef, +[ --disable-lef disable LEF package], +[], +[enable_lef=yes]) + +if test "x$enable_lef" = "xyes" ; then + AC_DEFINE(LEF_MODULE) + modules="$modules lef" + extra_libs="$extra_libs \${MAGICDIR}/lef/liblef.o \${MAGICDIR}/extflat/libextflat.o" +else + unused="$unused lef" +fi + +AC_ARG_ENABLE(readline, +[ --disable-readline disable readline package], +[ if test $usingTcl ; then + enable_readline=no + fi +], +[ if test $usingTcl ; then + enable_readline=no + else + enable_readline=yes + fi +]) + +if test "x$enable_readline" = "xyes" ; then + AC_DEFINE(USE_READLINE) + use_system_readline=yes + AC_CHECK_LIB(readline, rl_pre_input_hook,, + use_system_readline=no) + AC_CHECK_LIB(readline, rl_username_completion_function,, + use_system_readline=no) + AC_CHECK_LIB(readline, rl_filename_completion_function,, + use_system_readline=no) + AC_CHECK_LIB(readline, rl_attempted_completion_over,, + use_system_readline=no) + if test $use_system_readline = yes ; then + AC_DEFINE(HAVE_READLINE) + rl_libs="-lreadline" + else + rl_libs="\${MAGICDIR}/readline/readline/libreadline.a" + CPPFLAGS="$CPPFLAGS -I\${MAGICDIR}/readline" + fi + AC_CHECK_LIB(termcap, tgetent, [ + rl_libs="$rl_libs -ltermcap" + ], [ + AC_CHECK_LIB(ncurses, tgetent, [ + rl_libs="$rl_libs -lncurses" + ], ) + ], ) + modules="$modules readline" +else + unused="$unused readline" +fi + +AC_ARG_ENABLE(threads, +[ --disable-threads disable threaded graphics], +[ if test $usingTcl ; then + enable_threads=no + fi +], +[ if test $usingTcl ; then + enable_threads=no + else + enable_threads=yes + fi +]) + +if test "x$enable_threads" = "xyes" ; then + usingThreads=1 + AC_DEFINE(HAVE_PTHREADS) + gr_libs="$gr_libs -lpthread" + gr_srcs="$gr_srcs \${X11THREAD_SRCS}" + gr_hsrcs="" + gr_hprog="" +fi + +AC_ARG_ENABLE(route, +[ --disable-route disable routing package], +[], +[enable_route=yes]) + +if test "x$enable_route" = "xyes" ; then + AC_DEFINE(ROUTE_MODULE) + modules="$modules garouter grouter irouter mzrouter router gcr" + programs="$programs net2ir" + extra_libs="$extra_libs \${MAGICDIR}/garouter/libgarouter.o \ + \${MAGICDIR}/mzrouter/libmzrouter.o \${MAGICDIR}/router/librouter.o \ + \${MAGICDIR}/irouter/libirouter.o \${MAGICDIR}/grouter/libgrouter.o \ + \${MAGICDIR}/gcr/libgcr.o" +else + unused="$unused garouter grouter irouter mzrouter router gcr" +fi + +AC_ARG_ENABLE(rsim, +[ --disable-rsim disable IRSIM tool], +[ if test $usingTcl ; then + enable_rsim=no + fi +], +[ if test $usingTcl ; then + enable_rsim=no + else + enable_rsim=yes + fi +]) + +if test "x$enable_rsim" = "xyes" ; then + AC_DEFINE(RSIM_MODULE) +fi + +AC_ARG_ENABLE(new-macros, +[ --disable-new-macros disable new macro set], +[], +[enable_new_macros=yes]) + +if test "x$enable_new_macros" = "xyes" ; then + AC_DEFINE(USE_NEW_MACROS) +fi + +AC_ARG_WITH(opengl, +[ --with-opengl=DIR use OpenGL include files in DIR], [ + if test "$withval" = "no" -o "$withval" = "NO" ; then + usingOGL= + elif test "$withval" != "no" -a "$withval" != "yes"; then + OGL_INCLUDE_DIR=${withval} + fi +]) + +dnl ---------------------------------------------------------------- +dnl Check for OpenGL headers and libraries, if OpenGL was specified. +dnl If they cannot be found, then disable OpenGL and flag a warning. +dnl ---------------------------------------------------------------- + +if test $usingOGL ; then + ac_save_CPPFLAGS="$CPPFLAGS" + if test $OGL_INCLUDE_DIR ; then + CPPFLAGS="$CPPFLAGS -I$OGL_INCLUDE_DIR" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + AC_CHECK_HEADER(GL/gl.h, , [ + echo "GL header files not found, disabling OpenGL" + usingOGL= + ],) + CPPFLAGS="$ac_save_CPPFLAGS" +fi + +if test $usingOGL ; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS -lm" + AC_CHECK_LIB(GL, glXCreateContext, , [ + echo "GL library files not found, disabling OpenGL" + usingOGL= + ],) + AC_CHECK_LIB(GLU, gluNewTess, , [ + echo "GLU library files not found; disabling font rendering" + use_libglu="" + ],) + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +fi + +if test "x$use_libglu" != "x" ; then + AC_DEFINE(VECTOR_FONTS) +fi + +if test $usingOGL ; then + if test $OGL_INCLUDE_DIR ; then + gr_cflags="${gr_cflags} -I${OGL_INCLUDE_DIR}" + fi +fi + +dnl ---------------------------------------------------------------- +dnl Once we're sure what, if any, interpreter is being compiled, +dnl set all the appropriate definitions. For Tcl/Tk, override +dnl the default install targets: allows compiling tcl version with +dnl "make" instead of requiring "make tcl" +dnl ---------------------------------------------------------------- + +if test $usingTcl ; then + cadinstall="$cadinstall graphics tcltk" + modules="$modules tcltk" + unused="$unused lisp" + programs="$programs tcltk" + ALL_TARGET="tcl" + INSTALL_TARGET="install-tcl" + AC_DEFINE(MAGIC_WRAPPER) + extra_libs="$extra_libs \${MAGICDIR}/tcltk/libtcltk.o" + extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\"" +elif test $usingScheme ; then + modules="$modules lisp" + unused="$unused tcltk" + cadinstall="$cadinstall lisp" + extra_libs="$extra_libs \${MAGICDIR}/lisp/liblisp.o" + programs="$programs extcheck graphics" + AC_DEFINE(SCHEME_INTERPRETER) +else + unused="$unused lisp tcltk" + programs="$programs extcheck graphics" +fi + +dnl ---------------------------------------------------------------- +dnl Handle graphics based on the setting of "usingTcl", "usingX11", +dnl and "usingOGL" +dnl ---------------------------------------------------------------- + +if test $usingTcl ; then + if test $usingX11 ; then + gr_dflags="$gr_dflags -DX11 -DXLIB" + gr_libs="$gr_libs -lX11" + gr_srcs="$gr_srcs \${TK_SRCS}" + fi + if test $usingOGL ; then + AC_DEFINE(THREE_D) + gr_dflags="$gr_dflags -DOGL" + gr_libs="$gr_libs -lGL ${use_libglu} ${use_libxi} ${use_libxmu} ${use_libxext} -lm" + gr_srcs="$gr_srcs \${TOGL_SRCS}" + if ! test $usingX11 ; then + usingX11=1 + gr_dflags="$gr_dflags -DXLIB" + gr_libs="$gr_libs -lX11" + fi + fi + gr_srcs="$gr_srcs \${TKCOMMON_SRCS}" +else + if test $usingX11 ; then + gr_dflags="$gr_dflags -DX11 -DXLIB" + gr_libs="$gr_libs -lX11" + gr_srcs="$gr_srcs \${X11_SRCS}" + fi + if test $usingOGL ; then + gr_dflags="$gr_dflags -DOGL" + gr_libs="$gr_libs -lGL ${use_libglu} ${use_libxi} ${use_libxmu} ${use_libxext} -lm" + gr_srcs="$gr_srcs \${OGL_SRCS}" + if ! test $usingX11 ; then + usingX11=1 + gr_libs="$gr_libs -lX11" + gr_dflags="$gr_dflags -DXLIB" + fi + fi + if test $usingX11 ; then + if ! test $usingThreads; then + gr_dflags="$gr_dflags -DX11HELP_PROG=\\\"\${X11HELP_PROG}\\\"" + gr_hsrcs="$gr_hsrcs \${X11HELPER_SRCS}" + gr_hprog="$gr_hprog \${X11HELP_PROG}" + fi + fi +fi + +dnl ---------------------------------------------------------------- +dnl Define system-specific settings +dnl ---------------------------------------------------------------- + +case $target in + *-linux*) + AC_DEFINE(linux) + AC_DEFINE(SYSV) + dnl Defining "ISC" prevents compiler failure on redefinition of "wchar_t" + AC_DEFINE(ISC) + dnl 64-bit support for AMD Opteron + case $target in + *x86_64*) + CFLAGS="${CFLAGS} -m64 -fPIC" + ;; + esac + if test $usingOGL ; then + gr_libs="$gr_libs -lstdc++" + fi + if test -f /usr/lib/libbsd-compat.a ; then + gr_libs="$gr_libs -lbsd-compat" + elif test -f /usr/lib/libbsd.a ; then + gr_libs="$gr_libs -lbsd" + fi + ;; + *solaris*) + AC_DEFINE(SYSV) + ;; + *irix*) + AC_DEFINE(SYSV) + AC_DEFINE(IRIX) + AC_DEFINE(_BSD_SIGNALS) + ;; + *sysv*) + AC_DEFINE(SYSV) + ;; + *cygwin*) + AC_DEFINE(CYGWIN) + AC_DEFINE(i386) + ;; + *darwin*) + if test "$CPP" = "cc -E" ; then + CPPFLAGS="$CPPFLAGS -no-cpp-precomp" + fi + ;; +esac + +# ----------------------------------------------------------------------- +# Tcl/Tk configuration +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + +# ----------------------------------------------------------------------- +# +# Tk libraries and header files +# +# ----------------------------------------------------------------------- + if test "${TK_INC_DIR}" != "/usr/include" ; then + INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}" + fi + if test "${TK_LIB_DIR}" = "/usr/lib" -o \ + "${TK_LIB_DIR}" = "/usr/lib64" ; then + LIB_SPECS="${LIB_SPECS} ${TK_LIB_SPEC}" + else + LIB_SPECS="${LIB_SPECS} -L${TK_LIB_DIR} ${TK_LIB_SPEC}" + if test "x${loader_run_path}" = "x" ; then + loader_run_path="${TK_LIB_DIR}" + else + loader_run_path="${TK_LIB_DIR}:${loader_run_path}" + fi + fi + +# ----------------------------------------------------------------------- +# +# Tcl libraries and header files +# +# Add a header file directory specification only if the Tcl headers reside +# in a different directory from Tk's. +# +# +# ----------------------------------------------------------------------- + if test "${TCL_INC_DIR}" != "/usr/include" -a \ + "${TCL_INC_DIR}" != "${TK_INC_DIR}" ; then + INC_SPECS="${INC_SPECS} -I${TCL_INC_DIR}" + fi + + if test "${TCL_LIB_DIR}" = "/usr/lib" -o \ + "${TCL_LIB_DIR}" = "/usr/lib64" -o \ + "${TCL_LIB_DIR}" = "${TK_LIB_DIR}" ; then + LIB_SPECS="${LIB_SPECS} ${TCL_LIB_SPEC}" + else + LIB_SPECS="${LIB_SPECS} -L${TCL_LIB_DIR} ${TCL_LIB_SPEC}" + if test "x${loader_run_path}" = "x" ; then + loader_run_path="${TCL_LIB_DIR}" + else + loader_run_path="${TCL_LIB_DIR}:${loader_run_path}" + fi + fi + +#-------------------------------------------------------------------- +# +# Check if we can generate shared libraries on this system. Set flags +# to generate shared libraries for systems that we know about. Start +# with the values found in tclConfig.sh, make changes as we know about +# the different systems. +# +#-------------------------------------------------------------------- + +# Initialize shared library build variables + + SHLIB_LD="" + LDDL_FLAGS="-shared" + SHDLIB_EXT=".so" + EXTRA_LIB_SPECS="" + + build_shared="yes" + + case $target in + *-aix4.[[2-9]]*) + # No Position-Independent flags needed + + # Use the installed export file or the one found in the source directory. + + if test -r "${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" ; then + tcl_exp="${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" + else + tcl_exp="${TCL_SRC_DIR}/unix/lib.exp" + fi + if test -r "${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" ; then + tk_exp="${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" + else + tk_exp="${TK_SRC_DIR}/unix/lib.exp" + fi + + full_src_path=`cd ${srcdir}; pwd` + + # Use shell-script to link shared library + LD="${full_src_path}/cf/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry -bI:${tk_exp} -bI:${tcl_exp}" + + SHLIB_LIB_SPECS="${aix_lib_specs} -lc" + + LDFLAGS="-L${loader_run_path}" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-aix*) + # No Position-Independent flags needed + + # Use the installed export file or the one found in the source directory. + + if test -r "${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" ; then + tcl_exp="${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" + else + tcl_exp="${TCL_SRC_DIR}/unix/lib.exp" + fi + if test -r "${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" ; then + tk_exp="${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" + else + tk_exp="${TK_SRC_DIR}/unix/lib.exp" + fi + + full_src_path=`cd ${srcdir}/cf; pwd` + + # Use shell-script to link shared library + + LD="${full_src_path}/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry -bI:${tk_exp} -bI:${tcl_exp}" + SHLIB_LIB_SPECS="${aix_lib_specs} -lc" + LDFLAGS="-L${loader_run_path}" + EXTRA_LIB_SPECS="-lld" + ;; + + *-bsdi2*|*-bsdi3*) + LD="shlicc" + LDDL_FLAGS="-r" + EXTRA_LIB_SPECS="-ldl" + ;; + + *darwin*) + SHDLIB_EXT=".dylib" + LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind" + LDFLAGS="${LDFLAGS} ${LIB_SPECS}" + CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -fno-common" + ;; + + *cygwin*) + SHDLIB_EXT=".dll" + AC_DEFINE(USE_DL_IMPORT) + LDDL_FLAGS='-shared -Wl,--enable-auto-image-base' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + ld_extra_libs=${LIB_SPECS} + sub_extra_libs='-L${MAGICDIR}/magic -ltclmagic' + ;; + + *-bsdi4*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + LDDL_FLAGS='-shared -Wl,-E -Wl,-soname,$@' + ;; + + *-dgux*) + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-hpux*) + if test "$GCC" = "no" ; then + AC_DEFINE(_HPUX_SOURCE) + fi + AC_CHECK_LIB(dld, shl_load, [found=yes], [found=no]) + if test "${found}" = "yes" ; then + SHLIB_CFLAGS="+z" + LDDL_FLAGS="-b -E -n +s +b,${loader_run_path}:." + SHDLIB_EXT=".sl" + + # The run path is included in both LDFLAGS and LDDL_FLAGS + # because SHLIB_LD is ld and LD is cc/gcc. + + LDFLAGS="-Wl,-E -Wl,+s,+b,${loader_run_path}:." + EXTRA_LIB_SPECS="-ldld" + fi + ;; + + *-irix64-6.5*) + LDDL_FLAGS="-32 -shared -rdata_shared" + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + ;; + + *-irix-[56].*|*-irix64-*) + LDDL_FLAGS="-shared -rdata_shared" + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + LDFLAGS="" + if test "$GCC" = "yes" ; then + SHLIB_CFLAGS="-mabi=n32 $SHLIB_CFLAGS" + LDDL_FLAGS="-mabi=n32 $LDDL_FLAGS" + LDFLAGS="-mabi=n32 $LDFLAGS" + else + CFLAGS="-n32 $CFLAGS" + LDFLAGS="-n32 $LDFLAGS" + fi + ;; + + *-linux*) + LDDL_FLAGS='-shared -Wl,-soname,$@' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + LDFLAGS="" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-mp-ras-02*) + SHLIB_CFLAGS="-G -K PIC" + LDDL_FLAGS="" + ;; + + *-mp-ras-*) + SHLIB_CFLAGS="-G -K PIC" + LDDL_FLAGS="-Wl,-Bexport" + ;; + + *-ncr-sysv4-*2*) + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-ncr-sysv4*) + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G -Wl,-Bexport" + + LDFLAGS="-Wl,-Bexport" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-freebsd*) + # Not available on all versions: check for include file. + SHLIB_CFLAGS="-fpic" + LDDL_FLAGS="-shared ${LIB_SPECS}" + CFLAGS="${CFLAGS} -l/usr/X11R6/include" + ;; + + *-netbsd*|*-openbsd*) + # Not available on all versions: check for include file. + AC_CHECK_HEADER(dlfcn.h, test_ok=yes, test_ok=no) + if test "$test_ok" = yes; then + SHLIB_CFLAGS="-fPIC" + LDDL_FLAGS="-shared ${LIB_SPEC}" + fi + ;; + + *-nextstep*) + LDDL_FLAGS="-nostdlib -r" + ;; + + *-osf1-1.[012]*) + # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 + + # Warning: Ugly Makefile Hack + # Make package name same as library name + + SHLIB_LD='ld -R -export $@:' + ;; + + *-osf1-1.*) + # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 + + SHLIB_CFLAGS="-fpic" + SHLIB_LD="ld -shared" + ;; + + *-osf1V*) + # Digital OSF/1 + + LDDL_FLAGS='-shared -expect_unresolved "*"' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + LDFLAGS="" + ;; + + *-sco*) + # Note, dlopen is available only on SCO 3.2.5 and greater. However, + # this test works, since "uname -s" was non-standard in 3.2.4 and + # below. + + SHLIB_CFLAGS="-Kpic -belf" + LDDL_FLAGS="-G" + LDFLAGS="-belf -Wl,-Bexport" + ;; + + *-sni-sysv*) + + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-sunos4*) + + SHLIB_CFLAGS="-PIC" + LDDL_FLAGS="-assert pure-text" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-solaris2*) + + if test "$with_gnu_ld" = "yes" ; then + LDDL_FLAGS='-shared -Wl,-E -Wl,-soname,$@ ${LIB_SPEC}' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + else + LDDL_FLAGS="-shared -mimpure-text" + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -R ${loader_run_path}" + fi + fi + EXTRA_LIB_SPECS="-ldl" + ;; + + *-mips-dde-sysv*) + + SHLIB_CFLAGS="-KPIC" + LDDL_FLAGS="-G" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-pc-sysv4* | *-unixware-5*) + SHLIB_CFLAGS="-G -KPIC" + LDDL_FLAGS=" -Wl,-Bexport" + ;; + + esac + +# If we're running gcc, then set SHLIB_CFLAGS flags for compiling +# shared libraries for gcc, instead of those of the vendor's compiler. + + if test "$GCC" = "yes" ; then + case $target in + *cygwin*) + ;; + *) + SHLIB_CFLAGS="-Wimplicit-int -fPIC" + ;; + esac + fi + if test "$with_gnu_ld" = "yes" ; then + LDDL_FLAGS="${LDDL_FLAGS} -Wl,--version-script=\${MAGICDIR}/magic/symbol.map" + fi + + AC_SUBST(SHDLIB_EXT) + AC_SUBST(SHLIB_LD) + AC_SUBST(LD) + AC_SUBST(LDDL_FLAGS) + AC_SUBST(SHLIB_LIB_SPECS) + + AC_SUBST(EXTRA_LIB_SPECS) + AC_SUBST(LDFLAGS) + AC_SUBST(INC_SPECS) + AC_SUBST(LIB_SPECS) + AC_SUBST(WISH_EXE) + AC_SUBST(TCLSH_EXE) + AC_SUBST(TCL_LIB_DIR) + +fi + +if test "$GCC" = "yes" ; then + DEPEND_FLAG="-MM" +fi + + +dnl Substitute all variables + +AC_SUBST(gr_libs) +AC_SUBST(PACKAGE) +AC_SUBST(SCRIPTS) +AC_SUBST(extra_libs) +AC_SUBST(extra_defs) +AC_SUBST(ld_extra_libs) +AC_SUBST(ld_extra_objs) +AC_SUBST(top_extra_libs) +AC_SUBST(sub_extra_libs) +AC_SUBST(modules) +AC_SUBST(unused) +AC_SUBST(programs) +AC_SUBST(cadinstall) + +AC_SUBST(rl_defs) +AC_SUBST(rl_libs) + +AC_SUBST(gr_cflags) +AC_SUBST(gr_dflags) +AC_SUBST(gr_libs) +AC_SUBST(gr_srcs) +AC_SUBST(gr_hsrcs) +AC_SUBST(gr_hprog) + +AC_SUBST(X_LIBS) +AC_SUBST(X_CFLAGS) +AC_SUBST(CPPFLAGS) +AC_SUBST(CFLAGS) +AC_SUBST(DEPEND_FLAG) +AC_SUBST(SHLIB_CFLAGS) +AC_SUBST(LD_RUN_PATH) + +AC_SUBST(MAGIC_VERSION) +AC_SUBST(MAGIC_REVISION) + +AC_SUBST(OA) +AC_SUBST(OA_LIBS) + +AC_SUBST(ALL_TARGET) +AC_SUBST(INSTALL_TARGET) + +AC_OUTPUT(defs.mak) + +dnl +dnl Print configuration and report problems + +ECHO_N=printf + +echo +echo "-----------------------------------------------------------" +echo "Configuration Summary (principle requirements):" +echo + +${ECHO_N} "X11: " +if test $usingX11 ; then + echo "yes" +else + echo "no" + echo + echo " Magic requires X11 for all graphics operations. Without it," + echo " magic can only be run in batch mode using option '-dnull'." + echo " Generally, not finding X11 means that paths to header files" + echo " and/or libraries are missing or in an unexpected place. Try" + echo " using configure options --x-includes= and --x-libraries=." + echo +fi + +${ECHO_N} "OpenGL: " +if test $usingOGL ; then + echo "yes" + ${ECHO_N} "Vector fonts: " + if test "x$use_libglu" != "x" ; then + echo "yes" + else + echo "no" + fi +else + echo "no" + echo + echo " OpenGL graphics are considerably better than the standard 8-bit" + echo " and 24-bit X11 graphics, provided that you have a video card and" + echo " driver supporting accelerated OpenGL graphics. If you get this" + echo " message, you may need to download OpenGL libraries and header" + echo " files, which are usually available from the video card manufacturer." + echo " Magic with un-accelerated OpenGL, such as using Mesa GL without" + echo " a supported graphics card, is usually a very bad combination." + echo +fi + +if test $usingTcl ; then + ${ECHO_N} "Tcl/Tk: " + echo "yes" +else + if test $usingScheme ; then + ${ECHO_N} "Scheme: " + echo "yes" + else + ${ECHO_N} "Tcl/Tk: " + echo "no" + echo + echo " Without Tcl/Tk, you cannot run the enhanced version of magic" + echo " with the toolbar and menus, and a number of other functions" + echo " are disabled. If you did not specifically disable Tcl/Tk on" + echo " the configure command line, then getting this message means" + echo " that you do not have Tcl/Tk headers and or libraries installed," + echo " or they are not in a standard path. Try using configure options" + echo " --with-tcl= and --with-tk=." + echo + fi +fi + +echo "-----------------------------------------------------------" +echo + +echo "Use 'make' to compile and 'make install' to install." +echo +echo "Errors may not be printed to stdout: see files 'make.log' " +echo " and 'install.log' for complete error summary." +echo +echo "-----------------------------------------------------------" +echo + +dnl Put "defs.mak" in the top-level directory +cp defs.mak .. diff --git a/scripts/configure.in.orig b/scripts/configure.in.orig new file mode 100644 index 00000000..1bd1efab --- /dev/null +++ b/scripts/configure.in.orig @@ -0,0 +1,1758 @@ +dnl Process this file with autoconf to produce a configure script. +dnl Use autoconf 2.52 or newer. + +AC_INIT(magic,, magic-hackers@csl.cornell.edu) +AC_PREREQ(2.52) +AC_CONFIG_SRCDIR(rules.mak) +AC_CONFIG_AUX_DIR(.) + +AC_CANONICAL_SYSTEM + +dnl pass the version string on the the makefiles +PACKAGE=magic + +MAGIC_VERSION=`cat ../VERSION | cut -d. -f1-2` +MAGIC_REVISION=`cat ../VERSION | cut -d. -f3` +AC_DEFINE_UNQUOTED(MAGIC_VERSION, "${MAGIC_VERSION}") +AC_DEFINE_UNQUOTED(MAGIC_REVISION, "${MAGIC_REVISION}") + +dnl Override default target when compiling under TCL +ALL_TARGET="standard" +INSTALL_TARGET="install-magic" + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_ISC_POSIX +AC_PROG_INSTALL +AC_PROG_RANLIB + +dnl GNU M4 is preferred due to some of the option switches. +AC_PATH_PROGS([M4], [gm4 gnum4 m4], [no]) +if test x$M4 = xno; then + AC_MSG_ERROR([M4 is required]) +fi + +dnl check size of pointer for correct behavior on 64-bit systems +dnl If the C preprocessor is GCC, we need to force the flag to +dnl assert that input files are of type C, or else the preprocessing +dnl stage will not execute correctly on the ".in" files in the scmos +dnl directory. + +if test "$CPP" = "$CC -E" ; then + CPP="$CPP -x c" +fi + +dnl check if the linker is a GNU linker + +#------------------------------------------------------------ +# AC_PROG_LD - find the path to the GNU or non-GNU linker +# (This stuff ripped from libtool) +#------------------------------------------------------------ +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld assume the C compiler uses GNU ld [[default=no]]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +dnl ###not for PostgreSQL### AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case "$ac_prog" in + # Accept absolute paths. +changequote(,)dnl + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' +changequote([,])dnl + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(ac_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$ac_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_PROG_LD_GNU +]) + +AC_DEFUN([AC_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi]) +with_gnu_ld=$ac_cv_prog_gnu_ld +]) + +AC_PROG_LD + +AC_CHECK_SIZEOF([void *], 4) +AC_CHECK_SIZEOF([unsigned int], 4) +AC_CHECK_SIZEOF([unsigned long], 4) +AC_CHECK_SIZEOF([unsigned long long], 8) + +dnl Check byte arrangement for doubleint routines +AC_C_BIGENDIAN + +dnl Check for required header files +AC_HEADER_STDC + +dnl Need either setenv or putenv +AC_CHECK_FUNCS(setenv putenv) + +dnl Check for vfork +AC_CHECK_FUNC(vfork) + +dnl Check for +AC_CHECK_HEADERS(sys/mman.h) + +dnl Check for +AC_CHECK_HEADERS(dirent.h) + +dnl Check for +AC_CHECK_HEADERS(limits.h) + +dnl Check for +AC_CHECK_HEADERS(param.h) + +dnl Check for +AC_CHECK_HEADERS(paths.h) + +dnl Check for va_copy +AC_CACHE_CHECK([for va_copy], ac_cv_c_va_copy, + AC_TRY_LINK( + [#include ], + [va_list ap1, ap2; + va_copy(ap1,ap2); + ], + [ac_cv_c_va_copy="yes"], + [ac_cv_c_va_copy="no"]) + ) +if test "$ac_cv_c_va_copy" = "yes" +then + AC_DEFINE(HAVE_VA_COPY, 1, [Define if we have va_copy]) +fi +AC_CACHE_CHECK([for __va_copy], ac_cv_c___va_copy, + AC_TRY_LINK( + [#include ], + [va_list ap1, ap2; + __va_copy(ap1,ap2); + ], + [ac_cv_c___va_copy="yes"], + [ac_cv_c___va_copy="no"]) + ) +if test "$ac_cv_c___va_copy" = "yes" +then + AC_DEFINE(HAVE___VA_COPY, 1, [Define if we have __va_copy]) +fi + +dnl Check for some C99 functions + +dnl Built-in round/roundf require CFLAGS -std=c99, but this also +dnl requires that all functions be declared explicitly! For now, +dnl built-in functions are disabled, with macros used instead. + +dnl NOTE---Bug in the x86_64 math library; round() and roundf() are incorrect. + +case $target in + *x86_64*) ;; + *) + AC_CACHE_CHECK([for built-in roundf], ac_cv_c_roundf, + AC_TRY_LINK( + [#include ], + [float f; + f = roundf(1.5); + ], + [ac_cv_c_roundf="yes"], + [ac_cv_c_roundf="no"]) + ) + if test "$ac_cv_c_roundf" = "no" + then + # Check fo C99 function from libm + AC_CHECK_LIB([m],[roundf],[AC_DEFINE([HAVE_ROUNDF],[1],["c99 function"])]) + fi + + AC_CACHE_CHECK([for built-in round], ac_cv_c_round, + AC_TRY_LINK( + [#include ], + [double d; + d = round(1.5); + ], + [ac_cv_c_round="yes"], + [ac_cv_c_round="no"]) + ) + if test "$ac_cv_c_round" = "no" + then + # Check fo C99 function from libm + AC_CHECK_LIB([m],[round],[AC_DEFINE([HAVE_ROUND],[1],["c99 function"])]) + fi + ;; +esac + +extra_defs="$extra_defs -DCAD_DIR=\\\"\${LIBDIR}\\\" -DBIN_DIR=\\\"\${BINDIR}\\\"" +X_LIBS= +X_CFLAGS= +CPPFLAGS= +INC_SPECS= +DEPEND_FLAG= +SHLIB_CFLAGS="" +LD_RUN_PATH="" +WISH_EXE="" +TCLSH_EXE="" + +modules="" +unused="" +cadinstall="" +extra_libs="" +top_extra_libs="" +sub_extra_libs="" +ld_extra_libs="" +ld_extra_objs="" +programs="" +rl_defs= +rl_libs= +gr_cflags= +gr_dflags= +gr_libs= +gr_srcs= +gr_hsrcs= +gr_hprog= + +magic_with_tcl="yes" +magic_with_tk="yes" +magic_with_tcl_includes="" +magic_with_tk_includes="" +magic_with_tcl_libraries="" +magic_with_tk_libraries="" + +dnl We will attempt to configure with Tcl/Tk and OpenGL. However, +dnl if checks for the appropriate header and library files fail, +dnl we will revert to non-Tcl and/or non-OpenGL compilation. +dnl Compilation for Tcl/Tk may be explicitly prohibited by using +dnl --with-tcl=no or --with-interpreter=no, and OpenGL may be +dnl disabled with --with-opengl=no + +usingOGL=1 +use_libglu="-lGLU" +usingTcl=1 +usingOA=0 + +dnl Check for gcore, used by niceabort.c + +AC_PATH_PROG(GCORE, gcore, [no]) + +dnl Check for /bin/csh; warn if not available. We should do something +dnl here to get makedbh to run under other common conditions, such as +dnl csh not being in /bin, or only tcsh being available. + +AC_PATH_PROG(CSH, csh, [no]) + +if test "x${CSH}" = "x"; then + AC_MSG_ERROR([cannot find /bin/csh---cannot compile!]) +fi + +dnl Check for X enabled/disabled + +AC_PATH_XTRA + +if test "x${X_DISPLAY_MISSING}" = "x"; then + usingX11=1 +else + AC_MSG_ERROR([Unable to find X11---compiling without graphics]) + echo Cannot find X11---will attempt to compile anyway. + echo Graphics options will be NULL only! + if test $usingOGL ; then + echo "Cannot use OpenGL/GLX without X11, disabling." + usingOGL= + fi + if test $usingTcl ; then + echo "Cannot compile TCL version without X11, disabling." + usingTcl= + fi +fi + +# Check for libXi, which is required on some systems but not available on +# others. +use_libxi="" +use_libxmu="" +use_libxext="" +AC_CHECK_LIB([Xi], [XOpenDevice], use_libxi="-lXi") +AC_CHECK_LIB([Xmu], [XmuInternAtom], use_libxmu="-lXmu") +AC_CHECK_LIB([Xext], [XextFindDisplay], use_libxext="-lXext") + +AC_ARG_WITH(interpreter, +[ --with-interpreter=[arg] enable interpreter (tcl, scheme, or no)], [ + if test "$withval" = "no" -o "$withval" = "NO"; then + usingTcl= + elif test "$withval" = "scheme" -o "$withval" = "SCHEME"; then + usingScheme=1 + usingTcl= + elif test "$withval" != "tcl" -a "$withval" != "TCL"; then + echo "Unknown option to --with-interpreter: Must be scheme, tcl, or no." + exit 1 + fi +], ) + +AC_ARG_WITH(tcl, +[ --with-tcl=DIR Find tclConfig.sh in DIR], [ + magic_with_tcl=$withval + if test "$withval" = "no" -o "$withval" = "NO"; then + usingTcl= + elif test $usingScheme ; then + echo Attempt to enable both Tcl and Scheme interpreters. + echo Disabling Tcl, and using Scheme instead. + usingTcl= + fi +], ) + +dnl ---------------------------------------------------------------- +dnl Do our best to find Tcl/Tk. If we can't, then flag a warning +dnl and don't set the usingTcl variable. +dnl +dnl This has been broken up into a number of sections, each of which +dnl depends independently on the setting of usingTcl. +dnl ---------------------------------------------------------------- + +AC_ARG_WITH(tk, [ --with-tk=DIR Find tkConfig.sh in DIR], + magic_with_tk=$withval) +AC_ARG_WITH(tclincls, [ --with-tclincls=DIR Find tcl.h in DIR], + magic_with_tcl_includes=$withval) +AC_ARG_WITH(tkincls, [ --with-tkincls=DIR Find tk.h in DIR], + magic_with_tk_includes=$withval) +AC_ARG_WITH(tcllibs, [ --with-tcllibs=DIR Find Tcl library in DIR], + magic_with_tcl_libraries=$withval) +AC_ARG_WITH(tklibs, [ --with-tklibs=DIR Find Tk library in DIR], + magic_with_tk_libraries=$withval) + +# ----------------------------------------------------------------------- +# Find the Tcl build configuration file "tclConfig.sh" +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + TCL_INC_DIR="." + TK_INC_DIR="." + + AC_MSG_CHECKING([for tclConfig.sh]) + tcl_config_sh="" + + if test "$magic_with_tcl" = "no" ; then + magic_with_tcl="" + elif test "$magic_with_tcl" != "yes" ; then + # + # Verify that a tclConfig.sh file exists in the directory specified + # by --with-tcl. + # + for dir in \ + $magic_with_tcl + do + if test -r "$dir/tclConfig.sh" ; then + tcl_config_sh="$dir/tclConfig.sh" + break + elif test -r "$dir/lib/tclConfig.sh" ; then + tcl_config_sh="$dir/lib/tclConfig.sh" + break + elif test -r "$dir/unix/tclConfig.sh" ; then + tcl_config_sh="$dir/unix/tclConfig.sh" + break + fi + done + else + # + # Otherwise, search for Tcl configuration file. + # + + # 1. Search previously named locations. + + for dir in \ + $prefix \ + $exec_prefix + do + if test -r "$dir/tclConfig.sh" ; then + tcl_config_sh="$dir/tclConfig.sh" + break + elif test -r "$dir/lib/tclConfig.sh" ; then + tcl_config_sh="$dir/lib/tclConfig.sh" + break + elif test -r "$dir/unix/tclConfig.sh" ; then + tcl_config_sh="$dir/unix/tclConfig.sh" + break + fi + done + + # 2. Search standard locations. + # (1/25/05---/usr/lib added for Ubuntu Linux) + # (6/19/06---/usr/lib64 added for 64-bit architectures + + if test "x$tcl_config_sh" = "x" ; then + for dir in \ + `ls -dr /usr/local/tcl/tcl[[7-9]].[[0-9]]* 2>/dev/null` \ + /usr/local/tcl \ + /usr/local/lib \ + /usr/lib64 \ + /usr/local \ + `ls -dr /usr/lib/tcl[[7-9]].[[0-9]]* 2>/dev/null` \ + /sw/lib \ + /usr + do + if test -r "$dir/tclConfig.sh" ; then + tcl_config_sh="$dir/tclConfig.sh" + break + elif test -r "$dir/lib/tclConfig.sh" ; then + tcl_config_sh="$dir/lib/tclConfig.sh" + break + fi + done + fi + fi + + AC_MSG_RESULT([${tcl_config_sh}]) + + if test "x$tcl_config_sh" = "x" ; then + echo "Can't find Tcl configuration script \"tclConfig.sh\"" + echo "Reverting to non-Tcl compilation" + usingTcl= + fi +fi + +# ----------------------------------------------------------------------- +# Find the Tk build configuration file "tkConfig.sh" +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + + AC_MSG_CHECKING([for tkConfig.sh]) + tk_config_sh="" + if test "$magic_with_tk" != "yes"; then + # + # Verify that a tkConfig.sh file exists in the directory specified + # by --with-tcl or --with-tk. + # + for dir in \ + $magic_with_tk \ + $magic_with_tcl + do + if test -r "$dir/tkConfig.sh" ; then + tk_config_sh="$dir/tkConfig.sh" + break + elif test -r "$dir/lib/tkConfig.sh" ; then + tk_config_sh="$dir/lib/tkConfig.sh" + break + elif test -r "$dir/unix/tkConfig.sh" ; then + tk_config_sh="$dir/unix/tkConfig.sh" + break + fi + done + else + # + # Search for Tk configuration file. + # + + # + # 1. Search previously named locations. + # + for dir in \ + $prefix \ + $exec_prefix + do + if test -r "$dir/tkConfig.sh" ; then + tk_config_sh="$dir/tkConfig.sh" + break + elif test -r "$dir/lib/tkConfig.sh" ; then + tk_config_sh="$dir/lib/tkConfig.sh" + break + elif test -r "$dir/unix/tkConfig.sh" ; then + tk_config_sh="$dir/unix/tkConfig.sh" + break + fi + done + # + # 2. Search standard locations. + # + if test "x$tk_config_sh" = "x" ; then + for dir in \ + `ls -dr /usr/local/tcl/tcl[[7-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr /usr/local/tk/tk[[7-9]].[[0-9]]* 2>/dev/null` \ + /usr/local/tcl \ + /usr/local/lib \ + /usr/lib64 \ + /usr/local \ + `ls -dr /usr/lib/tcl[[7-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr /usr/lib/tk[[7-9]].[[0-9]]* 2>/dev/null` \ + /sw/lib \ + ${x_libraries} \ + /usr + do + if test -r "$dir/tkConfig.sh" ; then + tk_config_sh="$dir/tkConfig.sh" + break + elif test -r "$dir/lib/tkConfig.sh" ; then + tk_config_sh="$dir/lib/tkConfig.sh" + break + fi + done + fi + fi + AC_MSG_RESULT([${tk_config_sh}]) + + if test "x$tk_config_sh" = "x" ; then + echo "can't find Tk configuration script \"tkConfig.sh\"" + echo "Reverting to non-Tcl compilation" + usingTcl= + fi +fi + +# ----------------------------------------------------------------------- +# Source in the Tcl/Tk configuration scripts. +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + . $tcl_config_sh + . $tk_config_sh + + if test "$TCL_VERSION" = "7.6" -a "$TK_VERSION" = "4.2" ; then + : + elif test "$TCL_VERSION" = "7.5" -a "$TK_VERSION" = "4.1" ; then + : + elif test "$TCL_VERSION" = "$TK_VERSION" ; then + : + else + echo "Mismatched Tcl/Tk versions ($TCL_VERSION != $TK_VERSION)" + echo "Reverting to non-Tcl compile" + usingTcl= + fi +fi + +if test $usingTcl ; then + if test "x${magic_with_tcl_includes}" != "x" ; then + if test -r "${magic_with_tcl_includes}/tcl.h" ; then + TCL_INC_DIR=${magic_with_tcl_includes} + else + echo "Can't find tcl.h in \"${magic_with_tcl_includes}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for dir in \ + ${TCL_PREFIX}/include/tcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION} \ + ${TCL_PREFIX}/include \ + ${TCL_SRC_DIR}/generic \ + ${TCL_INC_DIR} + do + if test -r "$dir/tcl.h" ; then + TCL_INC_DIR=$dir + break + fi + done + if test "x${TCL_INC_DIR}" = "x" ; then + echo "Can't find tcl.h header file" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +if test $usingTcl ; then + if test "x${magic_with_tk_includes}" != "x" ; then + if test -r "${magic_with_tk_includes}/tk.h" ; then + TK_INC_DIR=${magic_with_tk_includes} + else + echo "Can't find tk.h in \"${magic_with_tk_includes}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for dir in \ + ${TK_PREFIX}/include/tk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION} \ + ${TK_PREFIX}/include \ + ${TK_SRC_DIR}/generic \ + ${TK_INC_DIR} \ + ${TCL_INC_DIR} + do + if test -r "$dir/tk.h" ; then + TK_INC_DIR=$dir + break + fi + done + if test "x${TK_INC_DIR}" = "x" ; then + echo "Can't find tk.h header file" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +# FIXME -- why are we not using TCL_LIB_FILE FROM tclConfig.sh? +if test $usingTcl ; then + case $target in + *-sunos4*|*-*-netbsd*|NetBSD-*|FreeBSD-*|OpenBSD-*) + TCL_LIB_NAME="tcl${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}" + TK_LIB_NAME="tk${TK_MAJOR_VERSION}${TK_MINOR_VERSION}" + ;; + *) + TCL_LIB_NAME="tcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" + TK_LIB_NAME="tk${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}" + ;; + esac + + loclib=`echo ${TCL_LIB_SPEC} | sed -e 's/.*-L//' -e 's/ .*//'` + + if test "x${TCL_LIB_SPEC}" = "x" ; then + TCL_LIB_SPEC="-l${TCL_LIB_NAME}" + fi + if test "x${TK_LIB_SPEC}" = "x" ; then + TK_LIB_SPEC="-l${TK_LIB_NAME}" + fi + +# Find the version of "wish" that corresponds to TCL_EXEC_PREFIX +# We really ought to run "ldd" to confirm that the linked libraries match. + + AC_MSG_CHECKING([for wish executable]) + for dir in \ + ${TK_EXEC_PREFIX}/bin \ + ${TK_EXEC_PREFIX} + do + for wishexe in \ + wish-X11 \ + wish \ + wish${TK_VERSION} \ + wish.exe \ + wish${TK_VERSION}.exe + do + if test -r "$dir/$wishexe" ; then + WISH_EXE=$dir/$wishexe + break + fi + done + if test "x${WISH_EXE}" != "x" ; then + break + fi + done + if test "x${WISH_EXE}" = "x" ; then + echo "Warning: Can't find executable for \"wish\". You may have to" + echo "manually set the value for WISH_EXE in the magic startup script." + AC_MSG_RESULT(no) + else + AC_MSG_RESULT([${WISH_EXE}]) + fi + +# Find the version of "tclsh" that corresponds to TCL_EXEC_PREFIX + + AC_MSG_CHECKING([for tclsh executable]) + for dir in \ + ${TK_EXEC_PREFIX}/bin \ + ${TK_EXEC_PREFIX} + do + for tclshexe in \ + tclsh \ + tclsh${TK_VERSION} \ + tclsh.exe \ + tclsh${TK_VERSION}.exe + do + if test -r "$dir/$tclshexe" ; then + TCLSH_EXE=$dir/$tclshexe + break + fi + done + if test "x${TCLSH_EXE}" != "x" ; then + break + fi + done + if test "x${TCLSH_EXE}" = "x" ; then + echo "Warning: Can't find executable for \"tclsh\"." + AC_MSG_RESULT(no) + else + AC_MSG_RESULT([${TCLSH_EXE}]) + fi + +# Have to define SHDLIB_EXT here even though we have to do it below, too. + case $target in + *-hpux*) + SHDLIB_EXT=".sl" + SHDLIB_EXT_ALT=".sl" + ;; + *cygwin*) + SHDLIB_EXT=".dll" + SHDLIB_EXT_ALT=".dll.a" + ;; + *darwin*) + SHDLIB_EXT=".dylib" + SHDLIB_EXT_ALT=".dylib" + ;; + *) + SHDLIB_EXT=".so" + SHDLIB_EXT_ALT=".so" + ;; + esac + + if test "x${magic_with_tcl_libraries}" != "x" ; then + for libname in \ + "${magic_with_tcl_libraries}/${TCL_LIB_FILE}" \ + "${magic_with_tcl_libraries}/lib${TCL_LIB_NAME}${SHDLIB_EXT}" \ + "${magic_with_tcl_libraries}/lib${TCL_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TCL_LIB_DIR="${magic_with_tcl_libraries}" + break + fi + done + + if test "x${TCL_LIB_DIR}" = "x" ; then + echo "Can't find tcl library in \"${magic_with_tcl_libraries}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for libname in \ + "${loclib:=${TCL_EXEC_PREFIX}/lib}/lib${TCL_LIB_NAME}${SHDLIB_EXT}" \ + "${loclib:=${TCL_EXEC_PREFIX}/lib}/lib${TCL_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TCL_LIB_DIR="${TCL_EXEC_PREFIX}/lib" + break + fi + done + if test "x${TCL_LIB_DIR}" = "x" ; then + echo "Can't find tcl library" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +if test $usingTcl ; then + if test "x${magic_with_tk_libraries}" != "x" ; then + for libname in \ + "${magic_with_tk_libraries}/${TCL_LIB_FILE}" \ + "${magic_with_tk_libraries}/lib${TK_LIB_NAME}${SHDLIB_EXT}" \ + "${magic_with_tk_libraries}/lib${TK_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TK_LIB_DIR="${magic_with_tk_libraries}" + break + fi + done + if test "x${TK_LIB_DIR}" = "x" ; then + echo "Can't find tk library in \"${magic_with_tk_libraries}\"" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + else + for libname in \ + "${loclib:=${TK_EXEC_PREFIX}/lib}/lib${TK_LIB_NAME}${SHDLIB_EXT}" \ + "${loclib:=${TK_EXEC_PREFIX}/lib}/lib${TK_LIB_NAME}${SHDLIB_EXT_ALT}" + do + if test -r "$libname" ; then + TK_LIB_DIR="${TK_EXEC_PREFIX}/lib" + break + fi + done + if test "x${TK_LIB_DIR}" = "x" ; then + echo "Can't find tk library" + echo "Reverting to non-Tcl compile" + usingTcl= + fi + fi +fi + +dnl ---------------------------------------------------- +dnl End of Tcl/Tk search +dnl ---------------------------------------------------- + +dnl OpenAccess database support. +dnl There should be some checks here to confirm that the libraries +dnl are there, and usable. + +dnl There is no default search path here. Is there a default +dnl installation location for the OpenAccess libraries and include +dnl files? + +AC_ARG_WITH(openaccess, +[ --with-openaccess=DIR use OpenAccess libraries in DIR], [ + if test "$withval" = "no" -o "$withval" = "NO" ; then + OA= + OA_LIBS= + unused="$unused oa" + elif test "$withval" = "yes"; then + AC_MSG_ERROR([path to OpenAccess libraries is required]) + OA= + OA_LIBS= + unused="$unused oa" + else + usingOA=1 + OA=${withval} + OA_LIBS="-L\${OA}/lib -loaDB -loaDD -loaTC -loaBase" + OA_LIBS="${OA_LIBS} -lclalite_sh -lcls_sh -lcdsCommon_sh" + AC_DEFINE(OPENACCESS) + LD_RUN_PATH="-Wl,-rpath=\${OA}/lib" + modules="$modules oa" + extra_libs="$extra_libs \${MAGICDIR}/oa/liboa.o" + fi +]) + +AC_ARG_ENABLE(memdebug, +[ --enable-memdebug enable memory debugging], +[], +[enable_memdebug=no]) + +if test "x$enable_memdebug" = "xyes" ; then + if test "x$magic_with_tcl" = "x" ; then + LIBS="${LIBS} -lefence" + else + AC_DEFINE(TCL_MEM_DEBUG) + fi +fi + +AC_ARG_ENABLE(modular, +[ --enable-modular embed ext2sim and ext2spice packages], +[], +[enable_modular=no]) + +if test $usingTcl ; then + if test "x$enable_modular" = "xyes" ; then + programs="$programs ext2sim ext2spice" + AC_DEFINE(EXT2SPICE_AUTO) + AC_DEFINE(EXT2SIM_AUTO) + else + modules="$modules ext2sim ext2spice" + extra_libs="$extra_libs \${MAGICDIR}/ext2sim/libext2sim.o" + extra_libs="$extra_libs \${MAGICDIR}/ext2spice/libext2spice.o" + fi +else + programs="$programs ext2sim ext2spice" + AC_DEFINE(EXT2SPICE_AUTO) + AC_DEFINE(EXT2SIM_AUTO) +fi + +AC_ARG_ENABLE(locking, +[ --disable-locking disable file locking], +[], +[enable_locking=yes]) + +if test "x$enable_locking" = "xyes" ; then + case $target in + *cygwin*) + ;; + *) + AC_DEFINE(FILE_LOCKS) + ;; + esac +fi + +AC_ARG_ENABLE(calma, +[ --disable-calma disable calma package], +[], +[enable_calma=yes]) + +if test "x$enable_calma" = "xyes" ; then + AC_DEFINE(CALMA_MODULE) + modules="$modules calma" + extra_libs="$extra_libs \${MAGICDIR}/calma/libcalma.o" +else + unused="$unused calma" +fi + +AC_ARG_ENABLE(cif, +[ --disable-cif disable cif package], +[], +[enable_cif=yes]) + +if test "x$enable_cif" = "xyes" ; then + AC_DEFINE(CIF_MODULE) + modules="$modules cif" + extra_libs="$extra_libs \${MAGICDIR}/cif/libcif.o" +else + unused="$unused cif" +fi + +AC_ARG_ENABLE(client-render, +[ --disable-client-render disable OpenGL client-side rendering], +[], +[enable_client_render=yes]) + +if test "x$enable_client_render" = "xno" ; then + AC_DEFINE(OGL_SERVER_SIDE_ONLY) +fi + +AC_ARG_ENABLE(invert-y, +[ --enable-invert-y invert screen top to bottom in OpenGL], +[], +[enable_invert_y=no]) + +if test "x$enable_invert_y" = "xyes" ; then + AC_DEFINE(OGL_INVERT_Y) +fi + +AC_ARG_ENABLE(framebuffer-backing-store, +[ --enable-framebuffer-backing-store enable OpenGL framebuffer backing store], +[], +[enable_framebuffer_backing_store=no]) + +if test "x$enable_framebuffer_backing_store" != "xyes" ; then + AC_DEFINE(X11_BACKING_STORE) +fi + +AC_ARG_ENABLE(plot, +[ --disable-plot disable plot package], +[], +[enable_plot=yes]) + +if test "x$enable_plot" = "xyes" ; then + AC_DEFINE(PLOT_MODULE) + modules="$modules plot" + extra_libs="$extra_libs \${MAGICDIR}/plot/libplot.o" +else + unused="$unused plot" +fi + +AC_ARG_ENABLE(lef, +[ --disable-lef disable LEF package], +[], +[enable_lef=yes]) + +if test "x$enable_lef" = "xyes" ; then + AC_DEFINE(LEF_MODULE) + modules="$modules lef" + extra_libs="$extra_libs \${MAGICDIR}/lef/liblef.o \${MAGICDIR}/extflat/libextflat.o" +else + unused="$unused lef" +fi + +AC_ARG_ENABLE(readline, +[ --disable-readline disable readline package], +[ if test $usingTcl ; then + enable_readline=no + fi +], +[ if test $usingTcl ; then + enable_readline=no + else + enable_readline=yes + fi +]) + +if test "x$enable_readline" = "xyes" ; then + AC_DEFINE(USE_READLINE) + use_system_readline=yes + AC_CHECK_LIB(readline, rl_pre_input_hook,, + use_system_readline=no) + AC_CHECK_LIB(readline, rl_username_completion_function,, + use_system_readline=no) + AC_CHECK_LIB(readline, rl_filename_completion_function,, + use_system_readline=no) + AC_CHECK_LIB(readline, rl_attempted_completion_over,, + use_system_readline=no) + if test $use_system_readline = yes ; then + AC_DEFINE(HAVE_READLINE) + rl_libs="-lreadline" + else + rl_libs="\${MAGICDIR}/readline/readline/libreadline.a" + CPPFLAGS="$CPPFLAGS -I\${MAGICDIR}/readline" + fi + AC_CHECK_LIB(termcap, tgetent, [ + rl_libs="$rl_libs -ltermcap" + ], [ + AC_CHECK_LIB(ncurses, tgetent, [ + rl_libs="$rl_libs -lncurses" + ], ) + ], ) + modules="$modules readline" +else + unused="$unused readline" +fi + +AC_ARG_ENABLE(threads, +[ --disable-threads disable threaded graphics], +[ if test $usingTcl ; then + enable_threads=no + fi +], +[ if test $usingTcl ; then + enable_threads=no + else + enable_threads=yes + fi +]) + +if test "x$enable_threads" = "xyes" ; then + usingThreads=1 + AC_DEFINE(HAVE_PTHREADS) + gr_libs="$gr_libs -lpthread" + gr_srcs="$gr_srcs \${X11THREAD_SRCS}" + gr_hsrcs="" + gr_hprog="" +fi + +AC_ARG_ENABLE(route, +[ --disable-route disable routing package], +[], +[enable_route=yes]) + +if test "x$enable_route" = "xyes" ; then + AC_DEFINE(ROUTE_MODULE) + modules="$modules garouter grouter irouter mzrouter router gcr" + programs="$programs net2ir" + extra_libs="$extra_libs \${MAGICDIR}/garouter/libgarouter.o \ + \${MAGICDIR}/mzrouter/libmzrouter.o \${MAGICDIR}/router/librouter.o \ + \${MAGICDIR}/irouter/libirouter.o \${MAGICDIR}/grouter/libgrouter.o \ + \${MAGICDIR}/gcr/libgcr.o" +else + unused="$unused garouter grouter irouter mzrouter router gcr" +fi + +AC_ARG_ENABLE(rsim, +[ --disable-rsim disable IRSIM tool], +[ if test $usingTcl ; then + enable_rsim=no + fi +], +[ if test $usingTcl ; then + enable_rsim=no + else + enable_rsim=yes + fi +]) + +if test "x$enable_rsim" = "xyes" ; then + AC_DEFINE(RSIM_MODULE) +fi + +AC_ARG_ENABLE(new-macros, +[ --disable-new-macros disable new macro set], +[], +[enable_new_macros=yes]) + +if test "x$enable_new_macros" = "xyes" ; then + AC_DEFINE(USE_NEW_MACROS) +fi + +AC_ARG_WITH(opengl, +[ --with-opengl=DIR use OpenGL include files in DIR], [ + if test "$withval" = "no" -o "$withval" = "NO" ; then + usingOGL= + elif test "$withval" != "no" -a "$withval" != "yes"; then + OGL_INCLUDE_DIR=${withval} + fi +]) + +dnl ---------------------------------------------------------------- +dnl Check for OpenGL headers and libraries, if OpenGL was specified. +dnl If they cannot be found, then disable OpenGL and flag a warning. +dnl ---------------------------------------------------------------- + +if test $usingOGL ; then + ac_save_CPPFLAGS="$CPPFLAGS" + if test $OGL_INCLUDE_DIR ; then + CPPFLAGS="$CPPFLAGS -I$OGL_INCLUDE_DIR" + fi + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + AC_CHECK_HEADER(GL/gl.h, , [ + echo "GL header files not found, disabling OpenGL" + usingOGL= + ],) + CPPFLAGS="$ac_save_CPPFLAGS" +fi + +if test $usingOGL ; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS -lm" + AC_CHECK_LIB(GL, glXCreateContext, , [ + echo "GL library files not found, disabling OpenGL" + usingOGL= + ],) + AC_CHECK_LIB(GLU, gluNewTess, , [ + echo "GLU library files not found; disabling font rendering" + use_libglu="" + ],) + CPPFLAGS="$ac_save_CPPFLAGS" + LDFLAGS="$ac_save_LDFLAGS" +fi + +if test "x$use_libglu" != "x" ; then + AC_DEFINE(VECTOR_FONTS) +fi + +if test $usingOGL ; then + if test $OGL_INCLUDE_DIR ; then + gr_cflags="${gr_cflags} -I${OGL_INCLUDE_DIR}" + fi +fi + +dnl ---------------------------------------------------------------- +dnl Once we're sure what, if any, interpreter is being compiled, +dnl set all the appropriate definitions. For Tcl/Tk, override +dnl the default install targets: allows compiling tcl version with +dnl "make" instead of requiring "make tcl" +dnl ---------------------------------------------------------------- + +if test $usingTcl ; then + cadinstall="$cadinstall graphics tcltk" + modules="$modules tcltk" + unused="$unused lisp" + programs="$programs tcltk" + ALL_TARGET="tcl" + INSTALL_TARGET="install-tcl" + AC_DEFINE(MAGIC_WRAPPER) + extra_libs="$extra_libs \${MAGICDIR}/tcltk/libtcltk.o" + extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\"" +elif test $usingScheme ; then + modules="$modules lisp" + unused="$unused tcltk" + cadinstall="$cadinstall lisp" + extra_libs="$extra_libs \${MAGICDIR}/lisp/liblisp.o" + programs="$programs extcheck graphics" + AC_DEFINE(SCHEME_INTERPRETER) +else + unused="$unused lisp tcltk" + programs="$programs extcheck graphics" +fi + +dnl ---------------------------------------------------------------- +dnl Handle graphics based on the setting of "usingTcl", "usingX11", +dnl and "usingOGL" +dnl ---------------------------------------------------------------- + +if test $usingTcl ; then + if test $usingX11 ; then + gr_dflags="$gr_dflags -DX11 -DXLIB" + gr_libs="$gr_libs -lX11" + gr_srcs="$gr_srcs \${TK_SRCS}" + fi + if test $usingOGL ; then + AC_DEFINE(THREE_D) + gr_dflags="$gr_dflags -DOGL" + gr_libs="$gr_libs -lGL ${use_libglu} ${use_libxi} ${use_libxmu} ${use_libxext} -lm" + gr_srcs="$gr_srcs \${TOGL_SRCS}" + if ! test $usingX11 ; then + usingX11=1 + gr_dflags="$gr_dflags -DXLIB" + gr_libs="$gr_libs -lX11" + fi + fi + gr_srcs="$gr_srcs \${TKCOMMON_SRCS}" +else + if test $usingX11 ; then + gr_dflags="$gr_dflags -DX11 -DXLIB" + gr_libs="$gr_libs -lX11" + gr_srcs="$gr_srcs \${X11_SRCS}" + fi + if test $usingOGL ; then + gr_dflags="$gr_dflags -DOGL" + gr_libs="$gr_libs -lGL ${use_libglu} ${use_libxi} ${use_libxmu} ${use_libxext} -lm" + gr_srcs="$gr_srcs \${OGL_SRCS}" + if ! test $usingX11 ; then + usingX11=1 + gr_libs="$gr_libs -lX11" + gr_dflags="$gr_dflags -DXLIB" + fi + fi + if test $usingX11 ; then + if ! test $usingThreads; then + gr_dflags="$gr_dflags -DX11HELP_PROG=\\\"\${X11HELP_PROG}\\\"" + gr_hsrcs="$gr_hsrcs \${X11HELPER_SRCS}" + gr_hprog="$gr_hprog \${X11HELP_PROG}" + fi + fi +fi + +dnl ---------------------------------------------------------------- +dnl Define system-specific settings +dnl ---------------------------------------------------------------- + +case $target in + *-linux*) + AC_DEFINE(linux) + AC_DEFINE(SYSV) + dnl Defining "ISC" prevents compiler failure on redefinition of "wchar_t" + AC_DEFINE(ISC) + dnl 64-bit support for AMD Opteron + case $target in + *x86_64*) + CFLAGS="${CFLAGS} -m64 -fPIC" + ;; + esac + if test $usingOGL ; then + gr_libs="$gr_libs -lstdc++" + fi + if test -f /usr/lib/libbsd-compat.a ; then + gr_libs="$gr_libs -lbsd-compat" + elif test -f /usr/lib/libbsd.a ; then + gr_libs="$gr_libs -lbsd" + fi + ;; + *solaris*) + AC_DEFINE(SYSV) + ;; + *irix*) + AC_DEFINE(SYSV) + AC_DEFINE(IRIX) + AC_DEFINE(_BSD_SIGNALS) + ;; + *sysv*) + AC_DEFINE(SYSV) + ;; + *cygwin*) + AC_DEFINE(CYGWIN) + AC_DEFINE(i386) + ;; + *darwin*) + if test "$CPP" = "cc -E" ; then + CPPFLAGS="$CPPFLAGS -no-cpp-precomp" + fi + ;; +esac + +# ----------------------------------------------------------------------- +# Tcl/Tk configuration +# ----------------------------------------------------------------------- + +if test $usingTcl ; then + +# ----------------------------------------------------------------------- +# +# Tk libraries and header files +# +# ----------------------------------------------------------------------- + if test "${TK_INC_DIR}" != "/usr/include" ; then + INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}" + fi + if test "${TK_LIB_DIR}" = "/usr/lib" -o \ + "${TK_LIB_DIR}" = "/usr/lib64" ; then + LIB_SPECS="${LIB_SPECS} ${TK_LIB_SPEC}" + else + LIB_SPECS="${LIB_SPECS} -L${TK_LIB_DIR} ${TK_LIB_SPEC}" + if test "x${loader_run_path}" = "x" ; then + loader_run_path="${TK_LIB_DIR}" + else + loader_run_path="${TK_LIB_DIR}:${loader_run_path}" + fi + fi + +# ----------------------------------------------------------------------- +# +# Tcl libraries and header files +# +# Add a header file directory specification only if the Tcl headers reside +# in a different directory from Tk's. +# +# +# ----------------------------------------------------------------------- + if test "${TCL_INC_DIR}" != "/usr/include" -a \ + "${TCL_INC_DIR}" != "${TK_INC_DIR}" ; then + INC_SPECS="${INC_SPECS} -I${TCL_INC_DIR}" + fi + + if test "${TCL_LIB_DIR}" = "/usr/lib" -o \ + "${TCL_LIB_DIR}" = "/usr/lib64" -o \ + "${TCL_LIB_DIR}" = "${TK_LIB_DIR}" ; then + LIB_SPECS="${LIB_SPECS} ${TCL_LIB_SPEC}" + else + LIB_SPECS="${LIB_SPECS} -L${TCL_LIB_DIR} ${TCL_LIB_SPEC}" + if test "x${loader_run_path}" = "x" ; then + loader_run_path="${TCL_LIB_DIR}" + else + loader_run_path="${TCL_LIB_DIR}:${loader_run_path}" + fi + fi + +#-------------------------------------------------------------------- +# +# Check if we can generate shared libraries on this system. Set flags +# to generate shared libraries for systems that we know about. Start +# with the values found in tclConfig.sh, make changes as we know about +# the different systems. +# +#-------------------------------------------------------------------- + +# Initialize shared library build variables + + SHLIB_LD="" + LDDL_FLAGS="-shared" + SHDLIB_EXT=".so" + EXTRA_LIB_SPECS="" + + build_shared="yes" + + case $target in + *-aix4.[[2-9]]*) + # No Position-Independent flags needed + + # Use the installed export file or the one found in the source directory. + + if test -r "${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" ; then + tcl_exp="${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" + else + tcl_exp="${TCL_SRC_DIR}/unix/lib.exp" + fi + if test -r "${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" ; then + tk_exp="${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" + else + tk_exp="${TK_SRC_DIR}/unix/lib.exp" + fi + + full_src_path=`cd ${srcdir}; pwd` + + # Use shell-script to link shared library + LD="${full_src_path}/cf/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry -bI:${tk_exp} -bI:${tcl_exp}" + + SHLIB_LIB_SPECS="${aix_lib_specs} -lc" + + LDFLAGS="-L${loader_run_path}" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-aix*) + # No Position-Independent flags needed + + # Use the installed export file or the one found in the source directory. + + if test -r "${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" ; then + tcl_exp="${TCL_LIB_DIR}/lib${TCL_LIB_NAME}.exp" + else + tcl_exp="${TCL_SRC_DIR}/unix/lib.exp" + fi + if test -r "${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" ; then + tk_exp="${TK_LIB_DIR}/lib${TK_LIB_NAME}.exp" + else + tk_exp="${TK_SRC_DIR}/unix/lib.exp" + fi + + full_src_path=`cd ${srcdir}/cf; pwd` + + # Use shell-script to link shared library + + LD="${full_src_path}/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry -bI:${tk_exp} -bI:${tcl_exp}" + SHLIB_LIB_SPECS="${aix_lib_specs} -lc" + LDFLAGS="-L${loader_run_path}" + EXTRA_LIB_SPECS="-lld" + ;; + + *-bsdi2*|*-bsdi3*) + LD="shlicc" + LDDL_FLAGS="-r" + EXTRA_LIB_SPECS="-ldl" + ;; + + *darwin*) + SHDLIB_EXT=".dylib" + LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind" + LDFLAGS="${LDFLAGS} ${LIB_SPECS}" + CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common" + ;; + + *cygwin*) + SHDLIB_EXT=".dll" + AC_DEFINE(USE_DL_IMPORT) + LDDL_FLAGS='-shared -Wl,--enable-auto-image-base' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + ld_extra_libs=${LIB_SPECS} + sub_extra_libs='-L${MAGICDIR}/magic -ltclmagic' + ;; + + *-bsdi4*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + LDDL_FLAGS='-shared -Wl,-E -Wl,-soname,$@' + ;; + + *-dgux*) + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-hpux*) + if test "$GCC" = "no" ; then + AC_DEFINE(_HPUX_SOURCE) + fi + AC_CHECK_LIB(dld, shl_load, [found=yes], [found=no]) + if test "${found}" = "yes" ; then + SHLIB_CFLAGS="+z" + LDDL_FLAGS="-b -E -n +s +b,${loader_run_path}:." + SHDLIB_EXT=".sl" + + # The run path is included in both LDFLAGS and LDDL_FLAGS + # because SHLIB_LD is ld and LD is cc/gcc. + + LDFLAGS="-Wl,-E -Wl,+s,+b,${loader_run_path}:." + EXTRA_LIB_SPECS="-ldld" + fi + ;; + + *-irix64-6.5*) + LDDL_FLAGS="-32 -shared -rdata_shared" + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + ;; + + *-irix-[56].*|*-irix64-*) + LDDL_FLAGS="-shared -rdata_shared" + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + LDFLAGS="" + if test "$GCC" = "yes" ; then + SHLIB_CFLAGS="-mabi=n32 $SHLIB_CFLAGS" + LDDL_FLAGS="-mabi=n32 $LDDL_FLAGS" + LDFLAGS="-mabi=n32 $LDFLAGS" + else + CFLAGS="-n32 $CFLAGS" + LDFLAGS="-n32 $LDFLAGS" + fi + ;; + + *-linux*) + LDDL_FLAGS='-shared -Wl,-soname,$@' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + LDFLAGS="" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-mp-ras-02*) + SHLIB_CFLAGS="-G -K PIC" + LDDL_FLAGS="" + ;; + + *-mp-ras-*) + SHLIB_CFLAGS="-G -K PIC" + LDDL_FLAGS="-Wl,-Bexport" + ;; + + *-ncr-sysv4-*2*) + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-ncr-sysv4*) + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G -Wl,-Bexport" + + LDFLAGS="-Wl,-Bexport" + EXTRA_LIB_SPECS="-ldl" + ;; + + *-freebsd*) + # Not available on all versions: check for include file. + SHLIB_CFLAGS="-fpic" + LDDL_FLAGS="-shared ${LIB_SPECS}" + CFLAGS="${CFLAGS} -l/usr/X11R6/include" + ;; + + *-netbsd*|*-openbsd*) + # Not available on all versions: check for include file. + AC_CHECK_HEADER(dlfcn.h, test_ok=yes, test_ok=no) + if test "$test_ok" = yes; then + SHLIB_CFLAGS="-fPIC" + LDDL_FLAGS="-shared ${LIB_SPEC}" + fi + ;; + + *-nextstep*) + LDDL_FLAGS="-nostdlib -r" + ;; + + *-osf1-1.[012]*) + # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 + + # Warning: Ugly Makefile Hack + # Make package name same as library name + + SHLIB_LD='ld -R -export $@:' + ;; + + *-osf1-1.*) + # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 + + SHLIB_CFLAGS="-fpic" + SHLIB_LD="ld -shared" + ;; + + *-osf1V*) + # Digital OSF/1 + + LDDL_FLAGS='-shared -expect_unresolved "*"' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + LDFLAGS="" + ;; + + *-sco*) + # Note, dlopen is available only on SCO 3.2.5 and greater. However, + # this test works, since "uname -s" was non-standard in 3.2.4 and + # below. + + SHLIB_CFLAGS="-Kpic -belf" + LDDL_FLAGS="-G" + LDFLAGS="-belf -Wl,-Bexport" + ;; + + *-sni-sysv*) + + SHLIB_CFLAGS="-K PIC" + LDDL_FLAGS="-G" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-sunos4*) + + SHLIB_CFLAGS="-PIC" + LDDL_FLAGS="-assert pure-text" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-solaris2*) + + if test "$with_gnu_ld" = "yes" ; then + LDDL_FLAGS='-shared -Wl,-E -Wl,-soname,$@ ${LIB_SPEC}' + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -Wl,-rpath,${loader_run_path}" + fi + else + LDDL_FLAGS="-shared -mimpure-text" + if test "x${loader_run_path}" != "x" ; then + LD_RUN_PATH="${LD_RUN_PATH} -R ${loader_run_path}" + fi + fi + EXTRA_LIB_SPECS="-ldl" + ;; + + *-mips-dde-sysv*) + + SHLIB_CFLAGS="-KPIC" + LDDL_FLAGS="-G" + + EXTRA_LIB_SPECS="-ldl" + ;; + + *-pc-sysv4* | *-unixware-5*) + SHLIB_CFLAGS="-G -KPIC" + LDDL_FLAGS=" -Wl,-Bexport" + ;; + + esac + +# If we're running gcc, then set SHLIB_CFLAGS flags for compiling +# shared libraries for gcc, instead of those of the vendor's compiler. + + if test "$GCC" = "yes" ; then + case $target in + *cygwin*) + ;; + *) + SHLIB_CFLAGS="-Wimplicit-int -fPIC" + ;; + esac + fi + if test "$with_gnu_ld" = "yes" ; then + LDDL_FLAGS="${LDDL_FLAGS} -Wl,--version-script=\${MAGICDIR}/magic/symbol.map" + fi + + AC_SUBST(SHDLIB_EXT) + AC_SUBST(SHLIB_LD) + AC_SUBST(LD) + AC_SUBST(LDDL_FLAGS) + AC_SUBST(SHLIB_LIB_SPECS) + + AC_SUBST(EXTRA_LIB_SPECS) + AC_SUBST(LDFLAGS) + AC_SUBST(INC_SPECS) + AC_SUBST(LIB_SPECS) + AC_SUBST(WISH_EXE) + AC_SUBST(TCLSH_EXE) + AC_SUBST(TCL_LIB_DIR) + +fi + +if test "$GCC" = "yes" ; then + DEPEND_FLAG="-MM" +fi + + +dnl Substitute all variables + +AC_SUBST(gr_libs) +AC_SUBST(PACKAGE) +AC_SUBST(SCRIPTS) +AC_SUBST(extra_libs) +AC_SUBST(extra_defs) +AC_SUBST(ld_extra_libs) +AC_SUBST(ld_extra_objs) +AC_SUBST(top_extra_libs) +AC_SUBST(sub_extra_libs) +AC_SUBST(modules) +AC_SUBST(unused) +AC_SUBST(programs) +AC_SUBST(cadinstall) + +AC_SUBST(rl_defs) +AC_SUBST(rl_libs) + +AC_SUBST(gr_cflags) +AC_SUBST(gr_dflags) +AC_SUBST(gr_libs) +AC_SUBST(gr_srcs) +AC_SUBST(gr_hsrcs) +AC_SUBST(gr_hprog) + +AC_SUBST(X_LIBS) +AC_SUBST(X_CFLAGS) +AC_SUBST(CPPFLAGS) +AC_SUBST(CFLAGS) +AC_SUBST(DEPEND_FLAG) +AC_SUBST(SHLIB_CFLAGS) +AC_SUBST(LD_RUN_PATH) + +AC_SUBST(MAGIC_VERSION) +AC_SUBST(MAGIC_REVISION) + +AC_SUBST(OA) +AC_SUBST(OA_LIBS) + +AC_SUBST(ALL_TARGET) +AC_SUBST(INSTALL_TARGET) + +AC_OUTPUT(defs.mak) + +dnl +dnl Print configuration and report problems + +ECHO_N=printf + +echo +echo "-----------------------------------------------------------" +echo "Configuration Summary (principle requirements):" +echo + +${ECHO_N} "X11: " +if test $usingX11 ; then + echo "yes" +else + echo "no" + echo + echo " Magic requires X11 for all graphics operations. Without it," + echo " magic can only be run in batch mode using option '-dnull'." + echo " Generally, not finding X11 means that paths to header files" + echo " and/or libraries are missing or in an unexpected place. Try" + echo " using configure options --x-includes= and --x-libraries=." + echo +fi + +${ECHO_N} "OpenGL: " +if test $usingOGL ; then + echo "yes" + ${ECHO_N} "Vector fonts: " + if test "x$use_libglu" != "x" ; then + echo "yes" + else + echo "no" + fi +else + echo "no" + echo + echo " OpenGL graphics are considerably better than the standard 8-bit" + echo " and 24-bit X11 graphics, provided that you have a video card and" + echo " driver supporting accelerated OpenGL graphics. If you get this" + echo " message, you may need to download OpenGL libraries and header" + echo " files, which are usually available from the video card manufacturer." + echo " Magic with un-accelerated OpenGL, such as using Mesa GL without" + echo " a supported graphics card, is usually a very bad combination." + echo +fi + +if test $usingTcl ; then + ${ECHO_N} "Tcl/Tk: " + echo "yes" +else + if test $usingScheme ; then + ${ECHO_N} "Scheme: " + echo "yes" + else + ${ECHO_N} "Tcl/Tk: " + echo "no" + echo + echo " Without Tcl/Tk, you cannot run the enhanced version of magic" + echo " with the toolbar and menus, and a number of other functions" + echo " are disabled. If you did not specifically disable Tcl/Tk on" + echo " the configure command line, then getting this message means" + echo " that you do not have Tcl/Tk headers and or libraries installed," + echo " or they are not in a standard path. Try using configure options" + echo " --with-tcl= and --with-tk=." + echo + fi +fi + +echo "-----------------------------------------------------------" +echo + +echo "Use 'make' to compile and 'make install' to install." +echo +echo "Errors may not be printed to stdout: see files 'make.log' " +echo " and 'install.log' for complete error summary." +echo +echo "-----------------------------------------------------------" +echo + +dnl Put "defs.mak" in the top-level directory +cp defs.mak .. diff --git a/scripts/defs.mak b/scripts/defs.mak new file mode 100644 index 00000000..a63d2e56 --- /dev/null +++ b/scripts/defs.mak @@ -0,0 +1,93 @@ +# defs.mak.in -- +# source file for autoconf-generated "defs.mak" for magic + +# defs.mak. Generated from defs.mak.in by configure. +# Feel free to change the values in here to suit your needs. +# Be aware that running scripts/configure again will overwrite +# any changes! + +SHELL = /bin/sh + +prefix = /usr/local +exec_prefix = ${prefix} +bindir = ${exec_prefix}/bin +libdir = ${exec_prefix}/lib +mandir = ${prefix}/share/man + +SCRIPTS = ${MAGICDIR}/scripts + +INSTALL = /bin/install -c +INSTALL_PROGRAM = ${INSTALL} +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_SCRIPT = ${INSTALL} + +# Override standard "make" target when compiling under TCL +ALL_TARGET = tcl +INSTALL_TARGET = install-tcl + +# Change libdir to install in a different place +BINDIR = ${bindir} +MANDIR = ${mandir} +LIBDIR = ${libdir} +SYSDIR = ${libdir}/magic/sys +SCMDIR = ${libdir}/magic/scm +TCLDIR = ${libdir}/magic/tcl + +MAIN_EXTRA_LIBS = ${MAGICDIR}/ext2sim/libext2sim.o ${MAGICDIR}/ext2spice/libext2spice.o ${MAGICDIR}/calma/libcalma.o ${MAGICDIR}/cif/libcif.o ${MAGICDIR}/plot/libplot.o ${MAGICDIR}/lef/liblef.o ${MAGICDIR}/extflat/libextflat.o ${MAGICDIR}/garouter/libgarouter.o ${MAGICDIR}/mzrouter/libmzrouter.o ${MAGICDIR}/router/librouter.o ${MAGICDIR}/irouter/libirouter.o ${MAGICDIR}/grouter/libgrouter.o ${MAGICDIR}/gcr/libgcr.o ${MAGICDIR}/tcltk/libtcltk.o +LD_EXTRA_LIBS = +LD_SHARED = +TOP_EXTRA_LIBS = +SUB_EXTRA_LIBS = + +MODULES += ext2sim ext2spice calma cif plot lef garouter grouter irouter mzrouter router gcr tcltk +UNUSED_MODULES += readline lisp +PROGRAMS += net2ir tcltk +INSTALL_CAD_DIRS += graphics tcltk + +RM = rm -f +CP = cp +AR = ar +ARFLAGS = crv +LINK = ld -r +LD = /bin/ld +M4 = /bin/m4 +RANLIB = ranlib +SHDLIB_EXT = .so +LDDL_FLAGS = ${LDFLAGS} -shared -Wl,-soname,$@ -Wl,--version-script=${MAGICDIR}/magic/symbol.map +LD_RUN_PATH = +LIB_SPECS = -L/usr/lib64 -ltk8.6 -L/usr/lib64 -ltcl8.6 +WISH_EXE = /usr/bin/wish +TCL_LIB_DIR = /usr/lib +MAGIC_VERSION = 8.1 +MAGIC_REVISION = 151 + +CC = gcc +CPP = gcc -E -x c +CXX = g++ + +CPPFLAGS = -I. -I${MAGICDIR} +DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DBIN_DIR=\"${BINDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DMAGIC_VERSION=\"8.1\" -DMAGIC_REVISION=\"151\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_SYS_MMAN_H=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_PATHS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DFILE_LOCKS=1 -DCALMA_MODULE=1 -DCIF_MODULE=1 -DX11_BACKING_STORE=1 -DPLOT_MODULE=1 -DLEF_MODULE=1 -DROUTE_MODULE=1 -DUSE_NEW_MACROS=1 -DHAVE_LIBGL=1 -DHAVE_LIBGLU=1 -DVECTOR_FONTS=1 -DMAGIC_WRAPPER=1 -DTHREE_D=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DNDEBUG -DGCORE=\"/bin/gcore\" +DFLAGS += -DSHDLIB_EXT=\".so\" +CFLAGS = -g -m64 -fPIC -Wimplicit-int -fPIC + +READLINE_DEFS = +READLINE_LIBS = + +DEPEND_FILE = Depend +DEPEND_FLAG = -MM +EXEEXT = + +GR_CFLAGS = +GR_DFLAGS = -DX11 -DXLIB -DOGL -DNDEBUG +GR_LIBS = -lX11 -lGL -lGLU -lXi -lXmu -lXext -lm -lstdc++ ${X11_LDFLAGS} +GR_SRCS = ${TK_SRCS} ${TOGL_SRCS} ${TKCOMMON_SRCS} +GR_HELPER_SRCS = +GR_HELPER_PROG = + +OA = +OA_LIBS = + +DEPSRCS = ${SRCS} +OBJS = ${SRCS:.c=.o} ${CXXSRCS:.cpp=.o} +LIB_OBJS = ${LIB_SRCS:.c=.o} +CLEANS = ${OBJS} ${LIB_OBJS} lib${MODULE}.a lib${MODULE}.o ${MODULE} diff --git a/scripts/defs.mak.in b/scripts/defs.mak.in new file mode 100755 index 00000000..e949f638 --- /dev/null +++ b/scripts/defs.mak.in @@ -0,0 +1,93 @@ +# defs.mak.in -- +# source file for autoconf-generated "defs.mak" for magic + +# @configure_input@ +# Feel free to change the values in here to suit your needs. +# Be aware that running scripts/configure again will overwrite +# any changes! + +SHELL = @SHELL@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +mandir = @mandir@ + +SCRIPTS = ${MAGICDIR}/scripts + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ + +# Override standard "make" target when compiling under TCL +ALL_TARGET = @ALL_TARGET@ +INSTALL_TARGET = @INSTALL_TARGET@ + +# Change libdir to install in a different place +BINDIR = ${bindir} +MANDIR = ${mandir} +LIBDIR = ${libdir} +SYSDIR = ${libdir}/magic/sys +SCMDIR = ${libdir}/magic/scm +TCLDIR = ${libdir}/magic/tcl + +MAIN_EXTRA_LIBS = @extra_libs@ +LD_EXTRA_LIBS = @ld_extra_libs@ +LD_SHARED = @ld_extra_objs@ +TOP_EXTRA_LIBS = @top_extra_libs@ +SUB_EXTRA_LIBS = @sub_extra_libs@ + +MODULES += @modules@ +UNUSED_MODULES += @unused@ +PROGRAMS += @programs@ +INSTALL_CAD_DIRS += @cadinstall@ + +RM = rm -f +CP = cp +AR = ar +ARFLAGS = crv +LINK = ld -r +LD = @LD@ +M4 = @M4@ +RANLIB = @RANLIB@ +SHDLIB_EXT = @SHDLIB_EXT@ +LDDL_FLAGS = ${LDFLAGS} @LDDL_FLAGS@ +LD_RUN_PATH = @LD_RUN_PATH@ +LIB_SPECS = @LIB_SPECS@ +WISH_EXE = @WISH_EXE@ +TCL_LIB_DIR = @TCL_LIB_DIR@ +MAGIC_VERSION = @MAGIC_VERSION@ +MAGIC_REVISION = @MAGIC_REVISION@ + +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ + +CPPFLAGS = -I. -I${MAGICDIR} @CPPFLAGS@ +DFLAGS = @extra_defs@ @DEFS@ -DNDEBUG -DGCORE=\"@GCORE@\" +DFLAGS += -DSHDLIB_EXT=\"@SHDLIB_EXT@\" +CFLAGS = @CFLAGS@ @SHLIB_CFLAGS@ @INC_SPECS@ + +READLINE_DEFS = @rl_defs@ +READLINE_LIBS = @rl_libs@ + +DEPEND_FILE = Depend +DEPEND_FLAG = @DEPEND_FLAG@ +EXEEXT = @EXEEXT@ + +GR_CFLAGS = @X_CFLAGS@ @gr_cflags@ +GR_DFLAGS = @gr_dflags@ -DNDEBUG +GR_LIBS = @gr_libs@ ${X11_LDFLAGS} @X_LIBS@ +GR_SRCS = @gr_srcs@ +GR_HELPER_SRCS = @gr_hsrcs@ +GR_HELPER_PROG = @gr_hprog@ + +OA = @OA@ +OA_LIBS = @OA_LIBS@ + +DEPSRCS = ${SRCS} +OBJS = ${SRCS:.c=.o} ${CXXSRCS:.cpp=.o} +LIB_OBJS = ${LIB_SRCS:.c=.o} +CLEANS = ${OBJS} ${LIB_OBJS} lib${MODULE}.a lib${MODULE}.o ${MODULE} diff --git a/scripts/install-sh b/scripts/install-sh new file mode 100755 index 00000000..e9de2384 --- /dev/null +++ b/scripts/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/scripts/magic.spec.in b/scripts/magic.spec.in new file mode 100644 index 00000000..3cb5a136 --- /dev/null +++ b/scripts/magic.spec.in @@ -0,0 +1,66 @@ +Name: magic +Version: @VERSION@ +Release: 1 +Summary: Very capable VLSI layout tool +Group: Applications/Engineering +License: GPL +URL: http://www.opencircuitdesign.com/magic/index.html +Source: http://www.opencircuitdesign.com/magic/archive/%{name}-%{version}.tgz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +BuildRequires: libX11-devel, libXi-devel, libXmu-devel, libXext-devel +BuildRequires: tcl-devel, tk-devel, libGL-devel, libGLU-devel, blt, tcsh +Requires: libX11, libXi, libXmu, libXext, tcl, tk, libGL, libGLU, blt + +%description +Magic is a venerable VLSI layout tool, written in the 1980's at Berkeley +by John Ousterhout, now famous primarily for writing the scripting interpreter +language Tcl. Due largely in part to its liberal Berkeley open-source license, +magic has remained popular with universities and small companies. + +The open-source license has allowed VLSI engineers with a bent toward +programming to implement clever ideas and help magic stay abreast of +fabrication technology. However, it is the well thought-out core algorithms +which lend to magic the greatest part of its popularity. Magic is widely cited +as being the easiest tool to use for circuit layout, even for people who +ultimately rely on commercial tools for their product design flow. + +%prep +%setup -q + +%build +%configure \ + --with-tcl=%{_libdir} \ + --with-tk=%{_libdir} \ + --with-tclincls=%{_includedir} \ + --with-tkincls=%{_includedir} \ + --with-tcllibs=%{_libdir} \ + --with-tklibs=%{_libdir} +make + +%install +rm -rf $RPM_BUILD_ROOT +make install DESTDIR=$RPM_BUILD_ROOT + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%doc INSTALL README README.Tcl TODO VERSION +%{_bindir}/magic +%{_bindir}/spice2sim +%{_libdir}/magic/* +%{_mandir}/man1/ext2sim.1.gz +%{_mandir}/man1/ext2spice.1.gz +%{_mandir}/man1/extcheck.1.gz +%{_mandir}/man1/magic.1.gz +%{_mandir}/man5/cmap.5.gz +%{_mandir}/man5/displays.5.gz +%{_mandir}/man5/dlys.5.gz +%{_mandir}/man5/dstyle.5.gz +%{_mandir}/man5/ext.5.gz +%{_mandir}/man5/glyphs.5.gz +%{_mandir}/man5/mag.5.gz +%{_mandir}/man5/net.5.gz +%{_mandir}/man5/sim.5.gz + diff --git a/scripts/makedbh b/scripts/makedbh new file mode 100755 index 00000000..ede6930b --- /dev/null +++ b/scripts/makedbh @@ -0,0 +1,189 @@ +#!/bin/csh -f +# +# makes the "database.h" (1st argument, $1) file from "database.h.in" +# (2nd argument, $2), setting various mask operation definitions +# according to the number of words implied by the value of TT_MAXTYPES + +# The following mess grabs the value of TT_MAXTYPES from database.h.in +# +set maxtypes=`sed -n -e '/^#define[[:space:]]*TT_MAXTYPES/s/#define[[:space:]]*TT_MAXTYPES[[:space:]]*//p' < $1 | sed -e 's/\/\*[[:print:]]*\*\/[[:space:]]*//g' ` +# +# Alternative method works with outdated versions of sed/ed. +# +if ($maxtypes == "") then + set maxtypes=`sed -n -e '/^#define[ ]*TT_MAXTYPES/s/#define[ ]*TT_MAXTYPES[ ]*//p' < $1 | sed -e 's/\/\*.*\*\/[ ]*//g' ` +endif +# +# If we can't generate database.h correctly, nothing is going to compile. +# +if ($maxtypes == "") then + echo "Bad sed script in scripts/makedbh: Cannot generate database/database.h!" + exit +endif + +# Find derived values from bits per word +# Note that bits-per-word should be determined from the compiler, but +# 32 bits per word has always been hardwired into magic. +# +set bpw = 32 + +# @ wordmask=$bpw - 1 +# set wordshift=`echo "c=l($bpw); d=l(2); scale=0; c/d" | bc -l` +# @ maskwords=$maxtypes + $bpw - 1 +# @ maskwords/=$bpw + +@ maskwords=$maxtypes + $bpw - 1 +@ maskwords/=$bpw + + +# Generate the main part of the database.h file from database.h.in +cat $1 > $2 + +# Generate a list of integers from 0 to the value of "maskwords" - 1 +set count="" +@ maskwords-- +while (${maskwords} >= 0) + set count=`echo ${count} ${maskwords}` + @ maskwords-- +end + +# Definitions +set ECHO_N = printf +# echo -n is not POSIX, not portable to newer Bourne-shells + +echo "#define TTMaskZero(m) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " (m)->tt_words[$i] = 0" >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo ", \" >> $2 + endif +end + +echo "#define TTMaskIsZero(m) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " (m)->tt_words[$i] == 0" >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo " && \" >> $2 + endif +end + +echo "#define TTMaskEqual(m, n) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " (m)->tt_words[$i] == (n)->tt_words[$i]" >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo " && \" >> $2 + endif +end + +echo "#define TTMaskIntersect(m, n) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " ((m)->tt_words[$i] & (n)->tt_words[$i])" >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo " || \" >> $2 + endif +end + +echo "#define TTMaskCom(m) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " ((m)->tt_words[$i] = ~(m)->tt_words[$i])" >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo ", \" >> $2 + endif +end + +echo "#define TTMaskCom2(m, n) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " ((m)->tt_words[$i] = ~(n)->tt_words[$i])" >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo ", \" >> $2 + endif +end + +echo "#define TTMaskSetMask(m, n) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " ((m)->tt_words[$i] |= (n)->tt_words[$i])" >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo ", \" >> $2 + endif +end + +echo "#define TTMaskSetMask3(m, n, o) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " ((m)->tt_words[$i] |= (n)->tt_words[$i] | (o)->tt_words[$i])" \ + >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo ", \" >> $2 + endif +end + +echo "#define TTMaskAndMask(m, n) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " ((m)->tt_words[$i] &= (n)->tt_words[$i])" >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo ", \" >> $2 + endif +end + +echo "#define TTMaskAndMask3(m, n, o) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " ((m)->tt_words[$i] = (n)->tt_words[$i] & (o)->tt_words[$i])" \ + >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo ", \" >> $2 + endif +end + +echo "#define TTMaskClearMask(m, n) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " ((m)->tt_words[$i] &= ~(n)->tt_words[$i])" >> $2 + if ($i == 0) then + echo ")" >> $2 + echo "" >> $2 + else + echo ", \" >> $2 + endif +end + +echo "#define TTMaskClearMask3(m, n, o) ( \" >> $2 +foreach i (${count}) + ${ECHO_N} " ((m)->tt_words[$i] = (n)->tt_words[$i] & ~(o)->tt_words[$i])" \ + >> $2 + if ($i == 0) then + echo ")" >> $2 + else + echo ", \" >> $2 + endif +end + +echo "" >> $2 +echo "#endif /* _DATABASE_H */" >> $2 diff --git a/scripts/missing b/scripts/missing new file mode 100755 index 00000000..0a7fb5a2 --- /dev/null +++ b/scripts/missing @@ -0,0 +1,283 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing 0.3 - GNU automake" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then + # We have makeinfo, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + fi + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar ${1+"$@"} && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar ${1+"$@"} && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" ${1+"$@"} && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" ${1+"$@"} && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/scripts/mkdirs b/scripts/mkdirs new file mode 100755 index 00000000..b79d9716 --- /dev/null +++ b/scripts/mkdirs @@ -0,0 +1,32 @@ +#! /bin/sh +# +# mkdirs - a work-alike for `mkdir -p' +# +# Chet Ramey +# chet@po.cwru.edu + +for dir +do + + test -d "$dir" && continue + + tomake=$dir + while test -n "$dir" ; do + # dir=${dir%/*} + # dir=`expr "$dir" ':' '\(/.*\)/[^/]*'` + if dir=`expr "$dir" ':' '\(.*\)/[^/]*'`; then + tomake="$dir $tomake" + else + dir= + fi + done + + for d in $tomake + do + test -d "$d" && continue + echo mkdir "$d" + mkdir "$d" + done +done + +exit 0 diff --git a/scripts/mkinstalldirs b/scripts/mkinstalldirs new file mode 100755 index 00000000..271376f8 --- /dev/null +++ b/scripts/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/scripts/printmans b/scripts/printmans new file mode 100755 index 00000000..05e2e1f5 --- /dev/null +++ b/scripts/printmans @@ -0,0 +1,9 @@ +#!/bin/csh -f + +set cmd=($1) +shift argv + +foreach i ($argv) + echo cat $i \| $cmd + cat $i | $cmd +end diff --git a/select/Depend b/select/Depend new file mode 100644 index 00000000..3f27f390 --- /dev/null +++ b/select/Depend @@ -0,0 +1,28 @@ +selCreate.o: selCreate.c ../utils/magic.h ../utils/malloc.h \ + ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../windows/windows.h ../dbwind/dbwind.h \ + ../utils/undo.h ../commands/commands.h ../select/selInt.h \ + ../select/select.h ../drc/drc.h ../utils/main.h ../utils/signals.h +selDisplay.o: selDisplay.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../windows/windows.h ../graphics/graphics.h ../dbwind/dbwind.h \ + ../utils/styles.h ../textio/textio.h ../utils/signals.h +selEnum.o: selEnum.c ../utils/magic.h ../utils/geometry.h \ + ../database/database.h ../tiles/tile.h ../utils/hash.h \ + ../windows/windows.h ../utils/main.h ../select/select.h \ + ../select/selInt.h ../utils/malloc.h ../textio/textio.h +selOps.o: selOps.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/main.h ../select/select.h ../select/selInt.h \ + ../textio/textio.h ../utils/undo.h ../plow/plow.h ../utils/malloc.h \ + ../drc/drc.h +selUndo.o: selUndo.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../windows/windows.h \ + ../graphics/graphics.h ../dbwind/dbwind.h ../utils/undo.h \ + ../commands/commands.h ../textio/textio.h ../select/select.h \ + ../select/selInt.h +selUnselect.o: selUnselect.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../windows/windows.h ../dbwind/dbwind.h \ + ../commands/commands.h ../utils/main.h ../select/select.h \ + ../select/selInt.h ../utils/malloc.h ../textio/textio.h diff --git a/select/Makefile b/select/Makefile new file mode 100644 index 00000000..abf5c59f --- /dev/null +++ b/select/Makefile @@ -0,0 +1,11 @@ +# +# rcsid="$Header: /usr/cvsroot/magic-8.0/select/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" +# + +MODULE = select +MAGICDIR = .. +SRCS = selCreate.c selDisplay.c selEnum.c selOps.c selUndo.c \ + selUnselect.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/select/selCreate.c b/select/selCreate.c new file mode 100644 index 00000000..e73a67a4 --- /dev/null +++ b/select/selCreate.c @@ -0,0 +1,1390 @@ +/* selCreate.c - + * + * This file provides routines to make selections by copying + * things into a special cell named "__SELECT__". + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/select/selCreate.c,v 1.10 2010/06/24 12:37:56 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/undo.h" +#include "commands/commands.h" +#include "select/selInt.h" +#include "select/select.h" +#include "drc/drc.h" +#include "utils/main.h" +#include "utils/signals.h" + +/* Two cells worth of information are kept around by the selection + * module. SelectDef and SelectUse are for the cells whose contents + * are the current selection. Select2Def and Select2Use provide a + * temporary working space for procedures that manipulate the selection. + * for example, Select2Def is used to hold nets or regions while they + * are being extracted by SelectRegion or SelectNet. Once completely + * extracted, information is copied to SelectDef. Changes to + * SelectDef are undo-able and redo-able (so that the undo package + * can deal with selection changes), but changes to Select2Def are + * not undo-able (undoing is always disabled when the cell is modified). + */ + +global CellDef *SelectDef, *Select2Def; +global CellUse *SelectUse, *Select2Use; + +/* The CellDef below points to the definition FROM which the selection + * is extracted. This is the root definition of a window. Everything + * in the selection must have come from the same place, so we clear the + * selection whenever the user tries to select from a new hierarchy. + */ + +CellDef *SelectRootDef = NULL; + +/* The CellUse below is the last use selected by SelectUse. It is + * kept around to support the "replace" feature of SelectUse. + * + * Procedures which deselect a cell must reset this to null if they + * happen to deselect this usage. (Danger Will Robinson) + */ + +global CellUse *selectLastUse = NULL; + + +/* + * ---------------------------------------------------------------------------- + * + * SelectInit -- + * + * This procedure initializes the selection code by creating + * the selection cells. + * + * Results: + * None. + * + * Side effects: + * The select cells are created if they don't already exist. + * Selection undo-ing is also initialized. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectInit() +{ + static bool initialized = FALSE; + + if (initialized) return; + else initialized = TRUE; + + /* Create the working cells used internally to this module to + * hold selected information. Don't allow any of this to be + * undone, or else it could invalidate all the pointers we + * keep around to the cells. + */ + + UndoDisable(); + SelectDef = DBCellLookDef("__SELECT__"); + if (SelectDef == (CellDef *) NULL) + { + SelectDef = DBCellNewDef("__SELECT__",(char *) NULL); + ASSERT(SelectDef != (CellDef *) NULL, "SelectInit"); + DBCellSetAvail(SelectDef); + SelectDef->cd_flags |= CDINTERNAL; + TTMaskZero(&SelectDef->cd_types); + } + SelectUse = DBCellNewUse(SelectDef, (char *) NULL); + DBSetTrans(SelectUse, &GeoIdentityTransform); + SelectUse->cu_expandMask = CU_DESCEND_SPECIAL; /* This is always expanded. */ + SelectUse->cu_flags = 0; /* never locked down */ + + Select2Def = DBCellLookDef("__SELECT2__"); + if (Select2Def == (CellDef *) NULL) + { + Select2Def = DBCellNewDef("__SELECT2__",(char *) NULL); + ASSERT(Select2Def != (CellDef *) NULL, "SelectInit"); + DBCellSetAvail(Select2Def); + Select2Def->cd_flags |= CDINTERNAL; + } + Select2Use = DBCellNewUse(Select2Def, (char *) NULL); + DBSetTrans(Select2Use, &GeoIdentityTransform); + Select2Use->cu_expandMask = CU_DESCEND_SPECIAL; /* This is always expanded. */ + Select2Use->cu_flags = 0; /* never locked down */ + UndoEnable(); + + SelUndoInit(); +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectClear -- + * + * This procedure clears the current selection. + * + * Results: + * None. + * + * Side effects: + * All information is removed from the select cell, and selection + * information is also taken off the screen. + * + * ---------------------------------------------------------------------------- + */ + +/* The variables below are used to record information about subcells that + * must be cleared from the select cell. + */ + +#define MAXUSES 30 +static CellUse *(selDeleteUses[MAXUSES]); +static int selNDelete; + +void +SelectClear() +{ + SearchContext scx; + Rect r, expand; + extern int selClearFunc(); /* Forward declaration. */ + + if (SelectRootDef == NULL) return; + + scx.scx_area = SelectDef->cd_bbox; + expand = scx.scx_area; + + /* Special handling when the cell is flagged as a net selection */ + + if (SelectUse->cu_flags & CU_SELECT_NET) + { + SelNetRememberForUndo((CellDef *)NULL, (Point *)NULL, + TT_SPACE, FALSE, FALSE); + SelectUse->cu_flags = 0; + DBCellClearDef(SelectDef); + } + else + { + SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL); + SelectUse->cu_flags = 0; + + /* Erase all the paint from the select cell. */ + DBEraseMask(SelectDef, &TiPlaneRect, &DBAllButSpaceBits); + + /* For the line below to work, paint tables need to be set up correctly! */ + /* DBErase(SelectDef, &TiPlaneRect, TT_SPACE); */ + + /* Erase all of the labels from the select cell. */ + + (void) DBEraseLabel(SelectDef, &TiPlaneRect, &DBAllTypeBits, &expand); + + /* Erase all of the subcells from the select cell. This is a bit tricky, + * because we can't erase the subcells while searching for them (it will + * cause problems for the database). The code below first grabs up a + * few subcells, then deletes them, then grabs up a few more, then deletes + * them, and so on until done. + */ + + scx.scx_use = SelectUse; + scx.scx_trans = GeoIdentityTransform; + while (TRUE) + { + int i; + + selNDelete = 0; + (void) DBCellSrArea(&scx, selClearFunc, (ClientData) NULL); + for (i = 0; i < selNDelete; i += 1) + { + DBUnLinkCell(selDeleteUses[i], SelectDef); + DBDeleteCell(selDeleteUses[i]); + (void) DBCellDeleteUse(selDeleteUses[i]); + } + if (selNDelete < MAXUSES) break; + } + selectLastUse = NULL; + + SelRememberForUndo(FALSE, SelectRootDef, &scx.scx_area); + } + + TTMaskZero(&SelectDef->cd_types); + + /* Reset the transform, if we have been moving the selection around */ + GeoTransRect(&SelectUse->cu_transform, &expand, &r); + SelectUse->cu_transform = GeoIdentityTransform; + + /* Erase the selection from the screen. */ + DBWHLRedraw(SelectRootDef, &r, TRUE); + + DBReComputeBbox(SelectDef); + DBWAreaChanged(SelectDef, &expand, DBW_ALLWINDOWS, + (TileTypeBitMask *) NULL); +} + +/* Search function to help clear subcells from the selection. It just + * records information about several subcells (up to MAXUSES). + */ + +int +selClearFunc(scx) + SearchContext *scx; /* Describes a cell that was found. */ +{ + selDeleteUses[selNDelete] = scx->scx_use; + selNDelete += 1; + if (selNDelete == MAXUSES) return 1; + else return 2; +} + + +/* + * ---------------------------------------------------------------------------- + * + * SelectArea -- + * + * This procedure selects all information of given types that + * falls in a given area. + * + * Results: + * None. + * + * Side effects: + * The indicated information is added to the select cell, and + * outlined on the screen. Only information of particular + * types, and in expanded cells (according to xMask) is + * selected. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectArea(scx, types, xMask) + SearchContext *scx; /* Describes the area in which material + * is to be selected. The resulting + * coordinates should map to the coordinates + * of EditRootDef. The cell use should be + * the root of a window. + */ + TileTypeBitMask *types; /* Indicates which layers to select. Can + * include L_CELL and L_LABELS to select + * labels and unexpanded subcells. If L_LABELS + * is specified then all labels touching the + * area are selected. If L_LABELS isn't + * specified, then only labels attached to + * selected material are selected. + */ + int xMask; /* Indicates window (or windows) where cells + * must be expanded for their contents to be + * considered. 0 means treat everything as + * expanded. + */ +{ + Rect labelArea, cellArea; + + /* If the source definition is changing, clear the old selection. */ + + if (SelectRootDef != scx->scx_use->cu_def) + { + if (SelectRootDef != NULL) + SelectClear(); + SelectRootDef = scx->scx_use->cu_def; + SelSetDisplay(SelectUse, SelectRootDef); + } + + SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL); + + /* Select paint. */ + + (void) DBCellCopyAllPaint(scx, types, xMask, SelectUse); + + SelectDef->cd_types = *types; /* Remember what types were requested */ + + /* Select labels. */ + + if (TTMaskHasType(types, L_LABEL)) + (void) DBCellCopyAllLabels(scx, &DBAllTypeBits, xMask, + SelectUse, &labelArea); + else (void) DBCellCopyAllLabels(scx, types, xMask, SelectUse, &labelArea); + + /* Select unexpanded cell uses. */ + + if (TTMaskHasType(types, L_CELL)) + (void) DBCellCopyAllCells(scx, xMask, SelectUse, &cellArea); + else + { + cellArea.r_xbot = 0; + cellArea.r_xtop = -1; + } + + /* Display the new selection. */ + + (void) GeoIncludeAll(&scx->scx_area, &labelArea); + (void) GeoIncludeAll(&cellArea, &labelArea); + SelRememberForUndo(FALSE, SelectRootDef, &labelArea); + DBReComputeBbox(SelectDef); + DBWHLRedraw(SelectRootDef, &labelArea, TRUE); + DBWAreaChanged(SelectDef, &SelectDef->cd_extended, DBW_ALLWINDOWS, + &DBAllButSpaceBits); +} + + +/* + * ---------------------------------------------------------------------------- + * + * selFindChunk -- + * + * This is a recursive procedure to find the largest chunk of + * material in a particular area. It locates a rectangular + * area of given materials whose minimum dimension is as + * large as possible, and whose maximum dimension is also as + * large as possible (but minimum dimension is more important). + * Furthermore, the chunk must lie within a particular area and + * must contain a given area. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +#define MAX_RECURSION_LEVEL 22 + +void +selFindChunk(plane, wrongTypes, searchArea, containedArea, bestMin, + bestMax, bestChunk, level) + Plane *plane; /* Plane on which to hunt for chunk. */ + TileTypeBitMask *wrongTypes; /* Types that are not allowed to be + * part of the chunk. + */ + Rect *searchArea; /* Largest allowable size for the + * chunk. Note: don't overestimate + * this or the procedure will take a + * long time! (it processes every + * tile in this area). + */ + Rect *containedArea; /* The chunk returned must contain + * this entire area. + */ + int *bestMin; /* Largest minimum dimension seen so + * far: skip any chunks that can't + * match this. Updated by this + * procedure. + */ + int *bestMax; /* Largest maximum dimension seen + * so far. + */ + Rect *bestChunk; /* Filled in with largest chunk seen + * so far, if we find one better than + * bestMin and bestMax. + */ + int level; /* Recursion level (to avoid worst- + * case scenarios) + */ +{ + Rect smaller; + int min, max; + extern int selChunkFunc(); + Rect wrong; + + if (level == MAX_RECURSION_LEVEL) return; + + /* If the search area is already smaller than the chunk to beat, + * there's no point in even examining this chunk. + */ + + min = searchArea->r_xtop - searchArea->r_xbot; + max = searchArea->r_ytop - searchArea->r_ybot; + if (min > max) + { + int tmp; + tmp = min; min = max; max = tmp; + } + + if (min < *bestMin) return; + if ((min == *bestMin) && (max <= *bestMax)) return; + + /* At each stage, search the area that's left for material of the + * wrong type. + */ + + if (DBSrPaintArea((Tile *) NULL, plane, searchArea, wrongTypes, + selChunkFunc, (ClientData) &wrong) == 0) + { + /* The area contains nothing but material of the right type, + * so it is now the "chunk to beat". + */ + + *bestMin = min; + *bestMax = max; + *bestChunk = *searchArea; + return; + } + + if (SigInterruptPending) + return; + + /* At this point the current search area contains some material of + * the wrong type. We have to reduce the search area to exclude this + * material. There are two ways that this can be done while still + * producing areas that contain containedArea. Try both of those, + * and repeat the whole thing recursively on the smaller areas. + */ + + /* First, try reducing the x-range. */ + + smaller = *searchArea; + if (wrong.r_xbot >= containedArea->r_xtop) + smaller.r_xtop = wrong.r_xbot; + else if (wrong.r_xtop <= containedArea->r_xbot) + smaller.r_xbot = wrong.r_xtop; + else goto tryY; /* Bad material overlaps containedArea in x. */ + selFindChunk(plane, wrongTypes, &smaller, containedArea, + bestMin, bestMax, bestChunk, level + 1); + + + /* Also try reducing the y-range to see if that works better. */ + + tryY: smaller = *searchArea; + if (wrong.r_ybot >= containedArea->r_ytop) + smaller.r_ytop = wrong.r_ybot; + else if (wrong.r_ytop <= containedArea->r_ybot) + smaller.r_ybot = wrong.r_ytop; + else return; /* Bad material overlaps containedArea in y. */ + selFindChunk(plane, wrongTypes, &smaller, containedArea, + bestMin, bestMax, bestChunk, level + 1); +} + +/* Search function to find split tiles in the area of interest. + */ + +int +selSplitFunc(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + SearchContext *scx = cxp->tc_scx; + Rect *area = (Rect *) cxp->tc_filter->tf_arg; + Rect locarea; + + if (IsSplit(tile)) + { + TiToRect(tile, &locarea); + GeoTransRect(&scx->scx_trans, &locarea, area); + return 1; + } + return 0; +} + +/* This procedure is called for each tile of the wrong type in an + * area that is supposed to contain only tiles of other types. It + * just returns the area of the wrong material and aborts the search. + */ + +int +selChunkFunc(tile, wrong) + Tile *tile; /* The offending tile. */ + Rect *wrong; /* Place to store the tile's area. */ +{ + TiToRect(tile, wrong); + return 1; /* Abort the search. */ +} + + +/* + * ---------------------------------------------------------------------------- + * + * SelectChunk -- + * + * This procedure selects a single rectangular chunk of + * homogeneous material. + * + * Results: + * None. + * + * Side effects: + * More material is added to the select cell and displayed + * on the screen. This procedure finds the largest rectangular + * chunk of material "type" that contains the area given in + * in scx. The material need not all be in one cell, but it + * must all be in cells that are expanded according to "xMask". + * If pArea is given, the rectangle it points to is filled in + * with the area of the chunk that was selected. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectChunk(scx, type, xMask, pArea, less) + SearchContext *scx; /* Area to tree-search for material. The + * transform must map to root coordinates + * of the edit cell. + */ + TileType type; /* The type of material to be considered. */ + int xMask; /* Indicates window (or windows) where cells + * must be expanded for their contents to be + * considered. 0 means treat everything as + * expanded. + */ + Rect *pArea; /* If non-NULL, gets filled in with the area + * of the selection. + */ + bool less; +{ +#define INITIALSIZE 10 + SearchContext newscx; + TileTypeBitMask wrongTypes, typeMask; + TileType ttype; + Rect bestChunk; + int bestMin, bestMax, width, height; + extern int selSplitFunc(); /* Forward reference. */ + + /* If the source definition is changing, clear the old selection. */ + + if (SelectRootDef != scx->scx_use->cu_def) + { + if (SelectRootDef != NULL) + SelectClear(); + SelectRootDef = scx->scx_use->cu_def; + SelSetDisplay(SelectUse, SelectRootDef); + } + + /* The chunk is computed iteratively. First extract a small + * region (defined by INITIALSIZE) into Select2Def. Then find + * the largest chunk in the region. If the chunk touches a + * side of the region, then extract a larger region and try + * again. Keep making the region larger and larger until we + * eventually find a region that completely contains the chunk + * with space left over around the edges. + */ + + UndoDisable(); + TTMaskSetOnlyType(&typeMask, type); + + /* Stacked types containing "type" need to be added to the mask */ + if (DBIsContact(type)) DBMaskAddStacking(&typeMask); + + TTMaskCom2(&wrongTypes, &typeMask); + + newscx = *scx; + + /* If the tile under the area of interest is a split tile, */ + /* then we use that tile as the chunk. This routine should */ + /* work like the while() loop underneath, looking for the */ + /* largest split tile, but this is a minor enhancement. */ + /* *However*, if it is done, the functions */ + /* DBCellCopyManhattanPaint()/dbCopyManhattanPaint() should */ + /* be reconsidered. */ + + if (DBTreeSrTiles(&newscx, &typeMask, 0, selSplitFunc, + (ClientData)&bestChunk) != 0) + { + goto chunkdone; + } + + bestMin = bestMax = 0; + bestChunk = GeoNullRect; + + GEO_EXPAND(&newscx.scx_area, INITIALSIZE, &newscx.scx_area); + while (TRUE) + { + /* Extract a bunch of junk. */ + + DBCellClearDef(Select2Def); + DBCellCopyManhattanPaint(&newscx, &typeMask, xMask, Select2Use); + + /* Now find the best chunk in the area. */ + + selFindChunk(Select2Def->cd_planes[DBPlane(type)], + &wrongTypes, &newscx.scx_area, &scx->scx_area, + &bestMin, &bestMax, &bestChunk, 0); + if (GEO_RECTNULL(&bestChunk)) + { + /* No chunk was found, so return. */ + + UndoEnable(); + if (pArea != NULL) *pArea = bestChunk; + return; + } + + /* If the chunk is completely inside the area we yanked, then we're + * done. + */ + + if (GEO_SURROUND_STRONG(&newscx.scx_area, &bestChunk)) break; + + /* The chunk extends to the edge of the area. Any place that the + * chunk touches an edge, move that edge out by a factor of two. + * Any place it doesn't touch, move the edge in to be just one + * unit out from the chunk. + */ + + width = newscx.scx_area.r_xtop - newscx.scx_area.r_xbot; + height = newscx.scx_area.r_ytop - newscx.scx_area.r_ybot; + + if (bestChunk.r_xbot == newscx.scx_area.r_xbot) + newscx.scx_area.r_xbot -= width; + else newscx.scx_area.r_xbot = bestChunk.r_xbot - 1; + if (bestChunk.r_ybot == newscx.scx_area.r_ybot) + newscx.scx_area.r_ybot -= height; + else newscx.scx_area.r_ybot= bestChunk.r_ybot - 1; + if (bestChunk.r_xtop == newscx.scx_area.r_xtop) + newscx.scx_area.r_xtop += width; + else newscx.scx_area.r_xtop = bestChunk.r_xtop + 1; + if (bestChunk.r_ytop == newscx.scx_area.r_ytop) + newscx.scx_area.r_ytop += height; + else newscx.scx_area.r_ytop = bestChunk.r_ytop + 1; + } + +chunkdone: + + /* Flag the cell as a chunk selection so we can treat */ + /* the contents differently when doing a move op. */ + + SelectUse->cu_flags |= CU_SELECT_CHUNK; + UndoEnable(); + + if (less) + { + SelRemoveArea(&bestChunk, &typeMask); + } + else + { + newscx.scx_area = bestChunk; + + /* Remove any stacked contact types for SelectArea */ + if (DBIsContact(type)) + TTMaskSetOnlyType(&typeMask, type); + + SelectArea(&newscx, &typeMask, xMask); + } + + if (pArea != NULL) *pArea = bestChunk; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectRegion -- + * + * Select an entire region of material, no matter what its + * shape. + * + * Results: + * None. + * + * Side effects: + * This procedure traces out the region consisting entirely + * of type "type", and selects all that material. The search + * starts from "type" material under scx and continues outward + * to get all material in all cells connected to the area under + * scx by material of type "type". If pArea is specified, then + * the rectangle that it points to is filled in with the bounding + * box of the region that was selected. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectRegion(scx, type, xMask, pArea, less) + SearchContext *scx; /* Area to tree-search for material. The + * transform must map to EditRoot coordinates. + */ + TileType type; /* The type of material to be considered. */ + int xMask; /* Indicates window (or windows) where cells + * must be expanded for their contents to be + * considered. 0 means treat everything as + * expanded. + */ + Rect *pArea; /* If non-NULL, points to rectangle to be + * filled in with region's bounding box. + */ + bool less; +{ + TileTypeBitMask connections[TT_MAXTYPES]; + int i; + SearchContext scx2; + + /* If the source definition is changing, clear the old selection. */ + + if (SelectRootDef != scx->scx_use->cu_def) + { + if (SelectRootDef != NULL) + SelectClear(); + SelectRootDef = scx->scx_use->cu_def; + SelSetDisplay(SelectUse, SelectRootDef); + } + + /* Set up a connection table that allows only a particular type + * of material to be considered in the region. + */ + + for (i=0; icd_bbox; + scx2.scx_trans = GeoIdentityTransform; + DBCellCopyAllPaint(&scx2, &DBAllButSpaceAndDRCBits, + 0, SelectUse); + DBCellCopyAllLabels(&scx2, &DBAllTypeBits, CU_DESCEND_SPECIAL, SelectUse, + (Rect *) NULL); + } + + /* Display the new selection. */ + + SelRememberForUndo(FALSE, SelectRootDef, &Select2Def->cd_bbox); + + DBReComputeBbox(SelectDef); + DBComputeUseBbox(SelectUse); + + DBWHLRedraw(SelectRootDef, &Select2Def->cd_extended, TRUE); + DBWAreaChanged(SelectDef, &Select2Def->cd_extended, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + + if (pArea != NULL) *pArea = Select2Def->cd_extended; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectNet -- + * + * This procedure selects an entire electrically-connected net. + * + * Results: + * None. + * + * Side effects: + * Starting from material of type "type" under scx, this procedure + * finds and highlights all material in all expanded cells that + * is electrically-connected to the starting material through a + * chain of expanded cells. If pArea is specified, then the + * rectangle that it points to is filled in with the bounding box + * of the net that was selected. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectNet(scx, type, xMask, pArea, less) + SearchContext *scx; /* Area to tree-search for material. The + * transform must map to EditRoot coordinates. + */ + TileType type; /* The type of material to be considered. */ + int xMask; /* Indicates window (or windows) where cells + * must be expanded for their contents to be + * considered. 0 means treat everything as + * expanded. + */ + Rect *pArea; /* If non-NULL, points to rectangle to be + * filled in with net's bounding box. + */ + bool less; /* Whether to remove material from the + * selection using SelDeleteSel2 + */ +{ + TileTypeBitMask mask; + SearchContext scx2; + Point savePoint = scx->scx_area.r_ll; + + /* If the source definition is changing, clear the old selection. */ + + if (SelectRootDef != scx->scx_use->cu_def) + { + if (SelectRootDef != NULL) + SelectClear(); + SelectRootDef = scx->scx_use->cu_def; + SelSetDisplay(SelectUse, SelectRootDef); + } + + TTMaskZero(&mask); + TTMaskSetType(&mask, type); + + /* Clear out the temporary selection cell and yank all of the + * connected paint into it. + */ + + UndoDisable(); + DBCellClearDef(Select2Def); + DBTreeCopyConnect(scx, &mask, xMask, DBConnectTbl, + &TiPlaneRect, Select2Use); + UndoEnable(); + + /* Network undo method added by Nishit and Tim, July 8-10, 2004 */ + SelNetRememberForUndo(SelectRootDef, &savePoint, type, less, TRUE); + + /* Now transfer what we found into the main selection cell. Pick + * up all the labels that correspond to the selected material. + */ + + UndoDisable(); + if (less) + { + (void) SelRemoveSel2(); + } + else + { + scx2.scx_use = Select2Use; + scx2.scx_area = Select2Def->cd_bbox; + scx2.scx_trans = GeoIdentityTransform; + DBCellCopyAllPaint(&scx2, &DBAllButSpaceAndDRCBits, + 0, SelectUse); + DBCellCopyAllLabels(&scx2, &DBAllTypeBits, CU_DESCEND_SPECIAL, SelectUse, + (Rect *) NULL); + } + + /* Set the cell use flags to mark this as a net selection, */ + /* so we can treat it differently when it comes time to */ + /* unselect it. */ + + SelectUse->cu_flags |= CU_SELECT_NET; + UndoEnable(); + + DBReComputeBbox(SelectDef); + DBComputeUseBbox(SelectUse); + + DBWHLRedraw(SelectRootDef, &Select2Def->cd_extended, TRUE); + DBWAreaChanged(SelectDef, &Select2Def->cd_extended, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + + if (pArea != NULL) *pArea = Select2Def->cd_extended; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectCell -- + * + * Select a subcell by making a copy of it in the __SELECT__ cell. + * + * Results: + * None. + * + * Side effects: + * The given use is copied into the selection. If replace is TRUE, + * then the last subcell to be selected via this procedure is + * deselected. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectCell(use, rootDef, trans, replace) + CellUse *use; /* Cell use to be selected. */ + CellDef *rootDef; /* Root definition of window in which selection + * is being made. + */ + Transform *trans; /* Transform from the coordinates of use's + * definition to the coordinates of rootDef. + */ + bool replace; /* TRUE means deselect the last cell selected + * by this procedure, if it's still selected. + */ +{ + CellUse *newUse; + + /* If the source definition is changing, clear the old selection. */ + + if (SelectRootDef != rootDef) + { + if (SelectRootDef != NULL) + SelectClear(); + SelectRootDef = rootDef; + SelSetDisplay(SelectUse, SelectRootDef); + } + + /* Deselect the last cell selected, if requested. */ + + if (replace && (selectLastUse != NULL)) + { + Rect area; + + SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL); + area = selectLastUse->cu_bbox; + DBUnLinkCell(selectLastUse, SelectDef); + DBDeleteCell(selectLastUse); + (void) DBCellDeleteUse(selectLastUse); + SelRememberForUndo(FALSE, SelectRootDef, &area); + DBWHLRedraw(SelectRootDef, &area, TRUE); + selectLastUse = (CellUse *)NULL; + } + + /* When creating a new use, try to re-use the id from the old + * one. Only create a new one if the old id can't be used. + */ + + newUse = DBCellNewUse(use->cu_def, (char *) use->cu_id); + if (!DBLinkCell(newUse, SelectDef)) + { + freeMagic((char *) newUse->cu_id); + newUse->cu_id = NULL; + (void) DBLinkCell(newUse, SelectDef); + } + + DBSetArray(use, newUse); + DBSetTrans(newUse, trans); + newUse->cu_expandMask = use->cu_expandMask; + newUse->cu_flags = use->cu_flags; + + /* If this cell is already selected, there's nothing more to do. + * Since we didn't change the selection here, be sure NOT to remember + * it for future deselection! + */ + + if (DBCellFindDup(newUse, SelectDef) != NULL) + { + DBUnLinkCell(newUse, SelectDef); + (void) DBCellDeleteUse(newUse); + selectLastUse = (CellUse *) NULL; + return; + } + + SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL); + DBPlaceCell(newUse, SelectDef); + selectLastUse = newUse; + + SelRememberForUndo(FALSE, SelectRootDef, &newUse->cu_bbox); + DBReComputeBbox(SelectDef); + DBWHLRedraw(SelectRootDef, &newUse->cu_bbox, TRUE); + DBWAreaChanged(SelectDef, &newUse->cu_bbox, DBW_ALLWINDOWS, + &DBAllButSpaceBits); +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectAndCopy1 -- + * + * This procedure takes the contents of SelectDef, and makes a + * copy of them in the edit cell. Unlike SelectAndCopy2, the + * original selection is unchanged, and SelectDef is not cleared. + * This allows the implementation of "drag and drop" selections. + * + * Results: + * None. + * + * Side effects: + * The selection is augmented with what's in Select2Def. The caller + * should normally have cleared the selection before calling us. + * The edit cell is modified to include everything that was in + * Select2Def. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectAndCopy1() +{ + SearchContext scx; + Rect editArea; + TileTypeBitMask mask; + + /* Just copy the information in Select2Def twice, once into the + * edit cell and once into the main selection cell. + */ + + scx.scx_use = SelectUse; + scx.scx_area = SelectUse->cu_bbox; + GeoTransTrans(&SelectUse->cu_transform, &RootToEditTransform, &scx.scx_trans); + TTMaskAndMask3(&mask, &DBAllButSpaceAndDRCBits, &DBActiveLayerBits); + (void) DBCellCopyAllPaint(&scx, &mask, CU_DESCEND_SPECIAL, EditCellUse); + (void) DBCellCopyAllLabels(&scx, &DBActiveLayerBits, CU_DESCEND_SPECIAL, + EditCellUse, (Rect *) NULL); + (void) DBCellCopyAllCells(&scx, CU_DESCEND_SPECIAL, EditCellUse, (Rect *) NULL); + GeoTransRect(&scx.scx_trans, &scx.scx_area, &editArea); + DBAdjustLabels(EditCellUse->cu_def, &editArea); + DBWAreaChanged(EditCellUse->cu_def, &editArea, DBW_ALLWINDOWS, + (TileTypeBitMask *) NULL); + DRCCheckThis(EditCellUse->cu_def, TT_CHECKPAINT, &editArea); + DBReComputeBbox(EditCellUse->cu_def); +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectAndCopy2 -- + * + * This procedure is intended for use only within the selection + * module. It takes what's in Select2Def, makes a copy of it in the + * edit cell, and makes the copy the selection. It's used, for + * example, by the transformation and copying routines. + * + * Results: + * None. + * + * Side effects: + * The selection is augmented with what's in Select2Def. The caller + * should normally have cleared the selection before calling us. + * The edit cell is modified to include everything that was in + * Select2Def. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectAndCopy2(newSourceDef) + CellDef *newSourceDef; /* The new selection is to be + * associated with this cell in the + * user's layout. + */ +{ + SearchContext scx; + Rect editArea, labelArea, expanded; + int plane; + void (*savedPaintPlane)(); + extern int selACPaintFunc(); /* Forward reference. */ + extern int selACCellFunc(); + + /* Just copy the information in Select2Def twice, once into the + * edit cell and once into the main selection cell. + */ + + scx.scx_use = Select2Use; + scx.scx_area = Select2Use->cu_bbox; + scx.scx_trans = RootToEditTransform; + savedPaintPlane = DBNewPaintPlane(DBPaintPlaneActive); + (void) DBCellCopyAllPaint(&scx, &DBAllButSpaceAndDRCBits, CU_DESCEND_SPECIAL, + EditCellUse); + DBNewPaintPlane(savedPaintPlane); + (void) DBCellCopyAllLabels(&scx, &DBAllTypeBits, CU_DESCEND_SPECIAL, EditCellUse, + (Rect *) NULL); + (void) DBCellCopyAllCells(&scx, CU_DESCEND_SPECIAL, EditCellUse, (Rect *) NULL); + GeoTransRect(&scx.scx_trans, &scx.scx_area, &editArea); + + DBAdjustLabels(EditCellUse->cu_def, &editArea); + DBWAreaChanged(EditCellUse->cu_def, &editArea, DBW_ALLWINDOWS, + (TileTypeBitMask *) NULL); + DRCCheckThis(EditCellUse->cu_def, TT_CHECKPAINT, &editArea); + DBReComputeBbox(EditCellUse->cu_def); + + SelectRootDef = newSourceDef; + SelSetDisplay(SelectUse, SelectRootDef); + + SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL); + scx.scx_trans = GeoIdentityTransform; + + /* In copying stuff into SelectUse, we have to be careful. The problem + * is that the stuff now in the edit cell may have switched layers. + * (for example, Select2Def might have diff, which got painted + * over poly in the edit cell to form transistor). As a result, we + * use Select2Def to figure out what areas of what planes to put into + * SelectUse, but use the actual tile types from the edit cell. + */ + + for (plane = PL_SELECTBASE; plane < DBNumPlanes; plane++) + { + (void) DBSrPaintArea((Tile *) NULL, Select2Def->cd_planes[plane], + &TiPlaneRect, &DBAllButSpaceAndDRCBits, selACPaintFunc, + (ClientData) plane); + DBMergeNMTiles(Select2Def->cd_planes[plane], &TiPlaneRect, + (PaintUndoInfo *)NULL); + } + + (void) DBCellCopyAllLabels(&scx, &DBAllTypeBits, CU_DESCEND_SPECIAL, + SelectUse, NULL); + + /* We also have to be careful about copying subcells into the + * main selection cell. It might not have been possible to copy + * a subcell into the edit cell (above), because the copying + * would have formed a circularity. In that case, we need to + * drop that subcell from the new selection. The code below just + * copies those that are still in the edit cell. + */ + + (void) SelEnumCells(TRUE, (bool *) NULL, &scx, selACCellFunc, + (ClientData) NULL); + + DBReComputeBbox(SelectDef); + DBComputeUseBbox(SelectUse); + + /* A little hack here: don't do explicit redisplay of the selection, + * or record a very large redisplay area for undo-ing. It's not + * necessary since the layout redisplay also redisplays the highlights. + * If we do it too, then we're just double-displaying and wasting + * time. (note: must record something for undo-ing in order to get + * SelectRootDef set right... just don't pass a redisplay area). + */ + + SelRememberForUndo(FALSE, SelectRootDef, (Rect *) NULL); + DBWAreaChanged(SelectDef, &SelectDef->cd_extended, DBW_ALLWINDOWS, + (TileTypeBitMask *) NULL); +} + +/* Structure to hold information about an edit area, which may be + * a triangular region. + */ +typedef struct { + Rect *editClip; + TileType ttype; +} acparg; + +/* Utility function: for each tile, copy information over its area from + * the given edit cell plane to SelectDef. Always return 0 to keep the + * search alive. + */ + +int +selACPaintFunc(tile, plane) + Tile *tile; /* Tile in Select2Def. */ + int plane; /* Index of plane this tile came from. */ +{ + Rect area, editArea; + acparg selACarg; + int selACPaintFunc2(); /* Forward reference. */ + + TiToRect(tile, &area); + /* we want editClip in root coordinates. . . */ + selACarg.editClip = &area; + GeoTransRect(&RootToEditTransform, &area, &editArea); + + selACarg.ttype = TiGetTypeExact(tile); + + if (IsSplit(tile)) + { + DBSrPaintNMArea((Tile *) NULL, EditCellUse->cu_def->cd_planes[plane], + selACarg.ttype, &editArea, &DBAllButSpaceAndDRCBits, + selACPaintFunc2, (ClientData) &selACarg); + } + else + (void) DBSrPaintArea((Tile *) NULL, EditCellUse->cu_def->cd_planes[plane], + &editArea, &DBAllButSpaceAndDRCBits, selACPaintFunc2, + (ClientData) &selACarg); + return 0; +} + +/* Second-level paint function: just paint the overlap between + * tile and editClip into SelectDef. + * + * This function is like dbCopyAllPaint() but differs just enough + * that a separate function is required. However, much of the code + * could be shared between the two functions if it were properly + * broken out into subroutines. + */ + +int +selACPaintFunc2(tile, selACarg) + Tile *tile; /* Tile in edit cell. */ + acparg *selACarg; /* Contains edit-cell area to clip to + * before painting into selection. + */ +{ + Rect *editClip = selACarg->editClip; + Rect area, selArea; + TileType type = TiGetTypeExact(tile); + TileTypeBitMask tmask, *rmask; + TileType ttype, rtype; + TileType dinfo = selACarg->ttype & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE); + + TiToRect(tile, &area); + GeoTransRect(&EditToRootTransform, &area, &selArea); + + if ((dinfo & TT_DIAGONAL) || (type & TT_DIAGONAL)) + { + /* If the select area is triangular, then we need to */ + /* clip in a more complicated manner. */ + /* Likewise if the edit cell tile is triangular and */ + /* the select area not. */ + + Point points[5]; + Rect rrect, orect; + int np, i, j; + + ttype = (selACarg->ttype & TT_SIDE) ? ((ttype & TT_RIGHTMASK) >> 14) : + ttype & TT_LEFTMASK; + + if (type & TT_DIAGONAL) + rtype = (type & TT_SIDE) ? SplitRightType(tile) : + SplitLeftType(tile); + else + rtype = type; + + if (rtype >= DBNumUserLayers) + { + rmask = DBResidueMask(rtype); + if (TTMaskHasType(rmask, ttype)) + rtype = ttype; + } + + TTMaskSetOnlyType(&tmask, rtype); + + type = (dinfo & TT_SIDE) ? (rtype << 14) : rtype; + type |= dinfo; + + if (dinfo & TT_DIAGONAL) + GrClipTriangle(editClip, &selArea, TRUE, dinfo, points, &np); + else + GrClipTriangle(&selArea, editClip, TRUE, type, points, &np); + + if (np == 0) + return 0; + if (np >= 3) + { + for (i = 0; i < np; i++) + { + j = (i + 1) % np; + if (points[i].p_x != points[j].p_x && points[i].p_y != + points[j].p_y) + { + /* Break out the triangle */ + rrect.r_xbot = points[i].p_x; + rrect.r_xtop = points[j].p_x; + rrect.r_ybot = points[i].p_y; + rrect.r_ytop = points[j].p_y; + GeoCanonicalRect(&rrect, &selArea); + break; + } + } + if (i == np) /* Exactly one Manhattan rectangle */ + { + rrect.r_xbot = points[0].p_x; + rrect.r_xtop = points[2].p_x; + rrect.r_ybot = points[0].p_y; + rrect.r_ytop = points[2].p_y; + GeoCanonicalRect(&rrect, &selArea); + type = rtype; + } + else if (np >= 4) /* Process extra rectangles in the area */ + { + /* "orect" is the bounding box of the polygon returned */ + /* by ClipTriangle. */ + + orect.r_xtop = orect.r_xbot = points[0].p_x; + orect.r_ytop = orect.r_ybot = points[0].p_y; + for (i = 0; i < np; i++) + GeoIncludePoint(&points[i], &orect); + + /* Rectangle to left or right */ + rrect.r_ybot = orect.r_ybot; + rrect.r_ytop = orect.r_ytop; + if (selArea.r_xbot > orect.r_xbot) + { + rrect.r_xbot = orect.r_xbot; + rrect.r_xtop = selArea.r_xbot; + } + else if (selArea.r_xtop < orect.r_xtop) + { + rrect.r_xtop = orect.r_xtop; + rrect.r_xbot = selArea.r_xtop; + } + else + goto topbottom; + + DBPaintValid(SelectDef, &rrect, &tmask, 0); +topbottom: + /* Rectangle to top or bottom */ + rrect.r_xbot = selArea.r_xbot; + rrect.r_xtop = selArea.r_xtop; + if (selArea.r_ybot > orect.r_ybot) + { + rrect.r_ybot = orect.r_ybot; + rrect.r_ytop = selArea.r_ybot; + } + else if (selArea.r_ytop < orect.r_ytop) + { + rrect.r_ytop = orect.r_ytop; + rrect.r_ybot = selArea.r_ytop; + } + else + goto splitdone; + + DBPaintValid(SelectDef, &rrect, &tmask, 0); + } + } + } + else + { + ttype = selACarg->ttype; + + if (type & TT_DIAGONAL) + rtype = (type & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile); + else + rtype = type; + + if (rtype >= DBNumUserLayers) + { + rmask = DBResidueMask(rtype); + if (TTMaskHasType(rmask, ttype)) + rtype = ttype; + } + TTMaskSetOnlyType(&tmask, rtype); + } + GeoClip(&selArea, editClip); /* editClip already in root coords */ + +splitdone: + DBPaintValid(SelectDef, &selArea, &tmask, type); + return 0; +} + +/* Cell search function: invoked for each subcell in Select2Def that's + * also in the edit cell. Make a copy of the cell in SelectDef. + */ + +int +selACCellFunc(selUse, realUse) + CellUse *selUse; /* Use to be copied into SelectDef. This + * is the instance inside Select2Def. + */ + CellUse *realUse; /* The cellUse (in the edit cell) corresponding + * to selUse. We need this in order to use its + * instance id and expand mask in the selection. + */ +{ + CellUse *newUse; + + newUse = DBCellNewUse(selUse->cu_def, realUse->cu_id); + if (!DBLinkCell(newUse, SelectDef)) + { + freeMagic((char *) newUse->cu_id); + newUse->cu_id = NULL; + (void) DBLinkCell(newUse, SelectDef); + } + newUse->cu_expandMask = realUse->cu_expandMask; + newUse->cu_flags = realUse->cu_flags; + DBSetArray(selUse, newUse); + DBSetTrans(newUse, &selUse->cu_transform); + DBPlaceCell(newUse, SelectDef); + return 0; +} + diff --git a/select/selDisplay.c b/select/selDisplay.c new file mode 100644 index 00000000..90b06233 --- /dev/null +++ b/select/selDisplay.c @@ -0,0 +1,443 @@ +/* selDisplay.c - + * + * This file provides routines for displaying the current + * selection on the screen. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/select/selDisplay.c,v 1.5 2010/06/24 12:37:56 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "textio/textio.h" +#include "utils/signals.h" + +/* The current selection is displayed by displaying the outline of + * shapes in one cell as an overlay (using the higlight facilities) + * on top of another cell. The variables below are used to remember + * these two cells. + */ + +static CellUse *selDisUse = NULL; /* Name of cell whose contents are + * highlighted. + */ +static CellDef *selDisRoot = NULL; /* Name of a root cell in a window, + * on top of whose contents selDisUse + * is highlighted. (i.e. determines + * windows in which selection is + * displayed). NULL means no current + * selection. + */ + +/* The following variable is shared between SelRedisplay and the search + * functions that it invokes. It points to the plane indicating which + * highlight areas must be redrawn. + */ + +static Plane *selRedisplayPlane; + +/* + * ---------------------------------------------------------------------------- + * + * SelRedisplay -- + * + * This procedure is called by the highlight code to redraw + * the selection highlights. The caller must have locked + * the window already. Only the highlight code should invoke + * this procedure. Other clients should always call the highlight + * procedures. + * + * Results: + * None. + * + * Side effects: + * Highlights are redrawn, if there is a selection to display + * and if it overlaps any non-space tiles in plane. + * + * ---------------------------------------------------------------------------- + */ + +void +SelRedisplay(window, plane) + MagWindow *window; /* Window in which to redisplay. */ + Plane *plane; /* Non-space tiles on this plane indicate + * which areas must have their highlights + * redrawn. + */ +{ + int i, labelSize; + CellDef *displayDef; + Label *label; + Transform tinv; + Rect planeArea, screenArea, selArea; + SearchContext scx; + DBWclientRec *crec = (DBWclientRec *) window->w_clientData; + + extern int selRedisplayFunc(); /* Forward declaration. */ + extern int selRedisplayCellFunc(); /* Forward declaration. */ + extern int selAlways1(); /* Forward declaration. */ + + /* Make sure that we've got something to show in the area + * being redisplayed. + */ + + if (((CellUse *) (window->w_surfaceID))->cu_def != selDisRoot) return; + displayDef = selDisUse->cu_def; + if (!DBBoundPlane(plane, &planeArea)) return; + GeoInvertTrans(&selDisUse->cu_transform, &tinv); + GeoTransRect(&tinv, &planeArea, &selArea); + if (!GEO_OVERLAP(&displayDef->cd_bbox, &selArea)) + { + /* Check if any labels in the selection overlap */ + for (label = displayDef->cd_labels; label != NULL; label = label->lab_next) + if (label->lab_font >= 0) + if (GEO_OVERLAP(&label->lab_bbox, &selArea)) + break; + + if (label == NULL) return; + } + + /* Redisplay the information on the paint planes. */ + + GrSetStuff(STYLE_OUTLINEHIGHLIGHTS); + selRedisplayPlane = plane; + for (i = PL_SELECTBASE; i < DBNumPlanes; i += 1) + { + (void) DBSrPaintArea((Tile *) NULL, displayDef->cd_planes[i], + &selArea, &DBAllTypeBits, selRedisplayFunc, + (ClientData) window); + } + + /* Redisplay all of the labels in the selection. */ + + labelSize = crec->dbw_labelSize; + if (labelSize < GR_TEXT_SMALL) labelSize = GR_TEXT_SMALL; + + for (label = displayDef->cd_labels; label != NULL; label = label->lab_next) + { + Rect larger, tmpr; + + /* See if the label needs to be redisplayed (make sure we do the + * search with a non-null area, or it will never return "yes"). + */ + + if (label->lab_font < 0) + { + larger = label->lab_rect; + if (larger.r_xbot == larger.r_xtop) + larger.r_xtop += 1; + if (larger.r_ybot == larger.r_ytop) + larger.r_ytop += 1; + if (!DBSrPaintArea((Tile *) NULL, plane, &larger, &DBAllButSpaceBits, + selAlways1, (ClientData) NULL)) + continue; + + GeoTransRect(&selDisUse->cu_transform, &label->lab_rect, &tmpr); + WindSurfaceToScreen(window, &tmpr, &screenArea); + + DBWDrawLabel(label, &screenArea, label->lab_just, + STYLE_OUTLINEHIGHLIGHTS, labelSize, + &crec->dbw_expandAmounts); + } + else + { + DBWDrawFontLabel(label, window, &selDisUse->cu_transform, + STYLE_OUTLINEHIGHLIGHTS); + + /* Disabled for now because there is no routine to compute bbox */ + // GeoTransRect(&selDisUse->cu_transform, &label->lab_bbox, &tmpr); + // WindSurfaceToScreen(window, &tmpr, &screenArea); + // GeoInclude(&screenArea, &crec->dbw_expandAmounts); + } + if (SigInterruptPending) break; + } + + /* Redisplay all of the subcells in the selection. Change the + * clipping rectangle to full-screen or else the cell names won't + * get displayed properly. The search function will clip itself. + * This is the same hack that's in the display module. + */ + + GrClipTo(&GrScreenRect); + scx.scx_use = selDisUse; + scx.scx_area = selArea; + scx.scx_trans = selDisUse->cu_transform; + (void) DBCellSrArea(&scx, selRedisplayCellFunc, (ClientData) window); +} + +/* Function used to see if an area in the selection touches an area + * that's to be redisplayed: it just returns 1 always. + */ + +int +selAlways1() +{ + return 1; +} + +/* Redisplay function for selected paint: draw lines to outline + * material. Only draw lines on boundaries between different + * kinds of material. + */ + +int +selRedisplayFunc(tile, window) + Tile *tile; /* Tile to be drawn on highlight layer. */ + MagWindow *window; /* Window in which to redisplay. */ +{ + Rect area, edge, screenEdge, tmpr; + Tile *neighbor; + TileType loctype, ntype; + Transform *t = &selDisUse->cu_transform; + + TiToRect(tile, &area); + GeoTransRect(t, &area, &tmpr); + + /* Watch for infinities. Because the select use can't be rotated, */ + /* we can just replace infinity markers in tmpr with those in area. */ + + if (area.r_xbot <= MINFINITY + 2) tmpr.r_xbot = area.r_xbot; + if (area.r_xtop >= INFINITY - 2) tmpr.r_xtop = area.r_xtop; + if (area.r_ybot <= MINFINITY + 2) tmpr.r_ybot = area.r_ybot; + if (area.r_ytop >= INFINITY - 2) tmpr.r_ytop = area.r_ytop; + + if (!DBSrPaintArea((Tile *) NULL, selRedisplayPlane, &tmpr, + &DBAllButSpaceBits, selAlways1, (ClientData) NULL)) + return 0; + + /* Go along the tile's bottom border, searching for tiles + * of a different type along that border. If the bottom of + * the tile is at -infinity, then don't do anything. + */ + + if (IsSplit(tile)) + { + /* By definition, split tiles have a different type on the other */ + /* side of the split. So always draw a line on the diagonal. */ + /* Use GrDrawTriangleEdge() so that clipping for area select */ + /* draws the correct line. */ + + WindSurfaceToScreenNoClip(window, &tmpr, &screenEdge); + if (screenEdge.r_ll.p_x != screenEdge.r_ur.p_x && + screenEdge.r_ll.p_y != screenEdge.r_ur.p_y) + GrDrawTriangleEdge(&screenEdge, TiGetTypeExact(tile)); + loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); + } + else + loctype = TiGetTypeExact(tile); + + if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile)))) + goto searchleft; /* nothing on bottom of split */ + + if (area.r_ybot > TiPlaneRect.r_ybot) + { + edge.r_ybot = edge.r_ytop = area.r_ybot; + for (neighbor = LB(tile); LEFT(neighbor) < area.r_xtop; + neighbor = TR(neighbor)) + { + ntype = TiGetTopType(neighbor); + if (ntype == loctype) continue; + edge.r_xbot = LEFT(neighbor); + edge.r_xtop = RIGHT(neighbor); + if (edge.r_xbot < area.r_xbot) edge.r_xbot = area.r_xbot; + if (edge.r_xtop > area.r_xtop) edge.r_xtop = area.r_xtop; + GeoTransRect(t, &edge, &tmpr); + WindSurfaceToScreen(window, &tmpr, &screenEdge); + GrClipLine(screenEdge.r_xbot, screenEdge.r_ybot, + screenEdge.r_xtop, screenEdge.r_ytop); + } + } + + /* Now go along the tile's left border, doing the same thing. Ignore + * edges that are at infinity. + */ + +searchleft: + if (IsSplit(tile) && SplitSide(tile)) return 0; + + if (area.r_xbot > TiPlaneRect.r_xbot) + { + edge.r_xbot = edge.r_xtop = area.r_xbot; + for (neighbor = BL(tile); BOTTOM(neighbor) < area.r_ytop; + neighbor = RT(neighbor)) + { + ntype = TiGetRightType(neighbor); + if (ntype == loctype) continue; + edge.r_ybot = BOTTOM(neighbor); + edge.r_ytop = TOP(neighbor); + if (edge.r_ybot < area.r_ybot) edge.r_ybot = area.r_ybot; + if (edge.r_ytop > area.r_ytop) edge.r_ytop = area.r_ytop; + GeoTransRect(t, &edge, &tmpr); + WindSurfaceToScreen(window, &tmpr, &screenEdge); + GrClipLine(screenEdge.r_xbot, screenEdge.r_ybot, + screenEdge.r_xtop, screenEdge.r_ytop); + } + } + return 0; /* To keep the search from aborting. */ +} + +/* Redisplay function for cells: do what the normal redisplay code does + * in DBWdisplay.c, except draw in the highlight color. + */ + +int +selRedisplayCellFunc(scx, window) + SearchContext *scx; /* Describes cell found. */ + MagWindow *window; /* Window in which to redisplay. */ +{ + Rect tmp, screen; + Point p; + char idName[100]; + + GeoTransRect(&scx->scx_trans, &scx->scx_use->cu_def->cd_bbox, &tmp); + if (!DBSrPaintArea((Tile *) NULL, selRedisplayPlane, &tmp, + &DBAllButSpaceBits, selAlways1, (ClientData) NULL)) + return 0; + WindSurfaceToScreen(window, &tmp, &screen); + GrFastBox(&screen); + + /* Don't futz around with text if the bbox is tiny. */ + + GrLabelSize("BBB", GEO_CENTER, GR_TEXT_SMALL, &tmp); + if (((screen.r_xtop-screen.r_xbot) < tmp.r_xtop) + || ((screen.r_ytop-screen.r_ybot) < tmp.r_ytop)) return 0; + + p.p_x = (screen.r_xbot + screen.r_xtop)/2; + p.p_y = (screen.r_ybot + 2*screen.r_ytop)/3; + GeoClip(&screen, &window->w_screenArea); + GrPutText(scx->scx_use->cu_def->cd_name, STYLE_SOLIDHIGHLIGHTS, &p, + GEO_CENTER, GR_TEXT_LARGE, TRUE, &screen, (Rect *) NULL); + (void) DBPrintUseId(scx, idName, 100, TRUE); + p.p_y = (2*screen.r_ybot + screen.r_ytop)/3; + GrPutText(idName, STYLE_SOLIDHIGHLIGHTS, &p, GEO_CENTER, + GR_TEXT_LARGE, TRUE, &screen, (Rect *) NULL); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelSetDisplay -- + * + * This procedure is called to set up displaying of the selection. + * + * Results: + * None. + * + * Side effects: + * This procedure sets things up so that future calls to the + * highlight code will cause information in selectUse to be + * outlined on top of windows containing displayRoot. This + * procedure should be called whenever either of the two + * cells changes. Note: this procedure does NOT actually + * redisplay anything. The highlight procedures should be + * invoked to do the redisplay. + * + * ---------------------------------------------------------------------------- + */ + +void +SelSetDisplay(selectUse, displayRoot) + CellUse *selectUse; /* Cell whose contents are to be + * highlighted. + */ + CellDef *displayRoot; /* Cell definition on top of whose contents + * the highlights are to be displayed. Must + * be the root cell of a window. May be NULL + * to turn off selection displaying. + */ +{ + static bool firstTime = TRUE; + + if (firstTime) + { + DBWHLAddClient(SelRedisplay); + firstTime = FALSE; + } + selDisUse = selectUse; + selDisRoot = displayRoot; +} + +/*----------------------------------------------------------------------*/ +/* Functions for converting selections to highlight areas */ +/*----------------------------------------------------------------------*/ + +typedef struct { + char *text; + int style; +} FeedLayerData; + +void +SelCopyToFeedback(celldef, seluse, style, text) + CellDef *celldef; /* Cell def to hold feedback */ + CellUse *seluse; /* Cell use holding selection */ + int style; /* Style to use for feedback */ + char *text; /* Text to attach to feedback */ +{ + int selFeedbackFunc(); /* Forward reference */ + int i; + CellDef *saveDef; + FeedLayerData fld; + + if (celldef == NULL) return; + + saveDef = selDisRoot; + selDisRoot = celldef; + + fld.text = text; + fld.style = style; + + UndoDisable(); + for (i = PL_SELECTBASE; i < DBNumPlanes; i += 1) + { + (void) DBSrPaintArea((Tile *) NULL, seluse->cu_def->cd_planes[i], + &TiPlaneRect, &DBAllButSpaceBits, selFeedbackFunc, + (ClientData)&fld); + } + UndoEnable(); + + selDisRoot = saveDef; +} + +/*----------------------------------------------------------------------*/ +/* Callback function per tile of the selection +/*----------------------------------------------------------------------*/ + +int +selFeedbackFunc(tile, fld) + Tile *tile; + FeedLayerData *fld; +{ + Rect area; + + TiToRect(tile, &area); + + DBWFeedbackAdd(&area, fld->text, selDisRoot, 1, fld->style | + (TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE))); + /* (preserve information about the geometry of a diagonal tile) */ + return 0; +} + +/*----------------------------------------------------------------------*/ diff --git a/select/selEnum.c b/select/selEnum.c new file mode 100644 index 00000000..586e0a7c --- /dev/null +++ b/select/selEnum.c @@ -0,0 +1,909 @@ +/* + * selEnum.c -- + * + * This file contains routines to enumerate various pieces of the + * selection, e.g. find all subcells that are in the selection and + * also in the edit cell. The procedures here are used as basic + * building blocks for the selection commands like copy or delete. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/select/selEnum.c,v 1.13 2010/06/24 12:37:56 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "database/database.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "windows/windows.h" +#include "utils/main.h" +#include "select/select.h" +#include "select/selInt.h" +#include "utils/malloc.h" +#include "textio/textio.h" + +/* Structure passed from top-level enumeration procedures to lower-level + * ones: + */ + +struct searg +{ + int (*sea_func)(); /* Client function to call. */ + ClientData sea_cdarg; /* Client data to pass to sea_func. */ + char sea_flags; /* See flag definitions below */ + bool *sea_nonEdit; /* Word to set if non-edit stuff is found. */ + int sea_plane; /* Index of plane currently being searched. */ + Rect sea_rect; /* Area of tile being searched */ + TileType sea_type; /* Type of current piece of selected paint. */ + ExtRectList *sea_rectList; /* List of rectangles found in edit cell. */ + CellUse *sea_use; /* Use that we're looking for an identical + * copy of in the layout. + */ + CellUse *sea_foundUse; /* Use that was found to match sea_use, or else + * NULL. Also used to hold use for foundLabel. + */ + Transform sea_foundTrans; /* Transform from coords of foundUse to root. */ + Label *sea_label; /* Label that we're trying to match in the + * layout. + */ + Label *sea_foundLabel; /* Matching label that was found, or NULL. + * If non_NULL, foundUse and foundTrans + * describe its containing cell. + */ +}; + +/* sea_flags bit definitions */ + +#define SEA_EDIT_ONLY 0x01 /* When set, only consider stuff that is in + * the edit cell. + */ +#define SEA_CHUNK 0x02 /* When set, treat the selection as a chunk + * (affects behavior of SelEnumPaint()) + */ +#define SEA_AREA 0x04 /* When set, treat the selection as an area + * selection with a possibly limited number + * of named types. + */ + +/* + * ---------------------------------------------------------------------------- + * + * SelEnumPaint -- + * + * Find all selected paint, and call the client's procedure for + * all the areas of paint that are found. Only consider paint + * on "layers", and if "editOnly" is TRUE, then only consider + * paint that it is the edit cell. The client procedure must + * be of the form + * + * int + * func(rect, type, clientData) + * Rect *rect; + * TileType type; + * ClientData clientData; + * { + * } + * + * The rect and type parameters identify the paint that was found, + * in root coordinates, and clientData is just the clientData + * argument passed to this procedure. Func should normally return + * 0. If it returns a non-zero return value, then the search + * will be aborted. + * + * Note that the "type" value passed to func() always contains a + * tiletype in the TT_LEFTMASK field regardless of the upper bits + * describing the diagonal of a non-Manhattan tile. The function + * is responsible for shifting the type field up into TT_RIGHTMASK + * if the TT_SIDE bit is set. This method is obscure but usually + * simplifies processing of non-Manhattan tiles in func(). + * + * Results: + * Returns 0 if the search finished normally. Returns 1 if the + * search was aborted. + * + * Side effects: + * If foundNonEdit is non-NULL, its target is set to indicate + * whether there was selected paint from outside the edit cell. + * Otherwise, the only side effects are those of func. + * + * ---------------------------------------------------------------------------- + */ + +int +SelEnumPaint(layers, editOnly, foundNonEdit, func, clientData) + TileTypeBitMask *layers; /* Mask layers to find. */ + bool editOnly; /* TRUE means only find material that is + * both selected and in the edit cell. + */ + bool *foundNonEdit; /* If non-NULL, this word is set to TRUE + * if there's selected paint that's not in + * the edit cell, FALSE otherwise. + */ + int (*func)(); /* Function to call for paint that's found. */ + ClientData clientData; /* Argument to pass through to func. */ +{ + int plane; + struct searg arg; + extern int selEnumPFunc1(); /* Forward declaration. */ + + arg.sea_func = func; + arg.sea_cdarg = clientData; + arg.sea_flags = (editOnly) ? SEA_EDIT_ONLY : 0; + arg.sea_nonEdit = foundNonEdit; + arg.sea_rectList = NULL; + if (foundNonEdit != NULL) *foundNonEdit = FALSE; + + /* First, find all the paint in the selection that has the right + * layers. Use the same procedure as "dbCellUniqueTileSrFunc()" + * so that contacts are not double-counted. + */ + + for (plane = PL_SELECTBASE; plane < DBNumPlanes; plane++) + { + arg.sea_plane = plane; + if (DBSrPaintArea((Tile *) NULL, SelectDef->cd_planes[plane], + &TiPlaneRect, layers, selEnumPFunc1, + (ClientData) &arg) != 0) + return 1; + } + return 0; +} + +/* Search function invoked for each piece of paint on the right layers + * in the select cell. Collect all of the sub-areas of this piece that + * are also in the edit cell, then call the client function for each + * one of them. It's important to collect the pieces first, then call + * the client: if we call the client while the edit cell search is + * underway, the client might trash the tile plane underneath us. + */ + +int +selEnumPFunc1(tile, arg) + Tile *tile; /* Tile of matching type. */ + struct searg *arg; /* Describes the current search. */ +{ + Rect editRect, rootRect; + TileType loctype; + TileTypeBitMask uMask; + extern int selEnumPFunc2(); + + TiToRect(tile, &arg->sea_rect); + + if (IsSplit(tile)) + { + arg->sea_type = TiGetTypeExact(tile) & (TT_DIAGONAL | TT_SIDE | TT_DIRECTION); + if (SplitSide(tile)) + loctype = SplitRightType(tile); + else + loctype = SplitLeftType(tile); + } + else + loctype = TiGetType(tile); + + if (IsSplit(tile)) + arg->sea_type |= loctype; + else + arg->sea_type = loctype; + + /* If the paint doesn't have to be in the edit cell, life's pretty + * simple: just call the client and quit. + */ + + if (!(arg->sea_flags & SEA_EDIT_ONLY)) + { + if ((*arg->sea_func)(&arg->sea_rect, arg->sea_type, arg->sea_cdarg) != 0) + return 1; + return 0; + } + + /* From here to the end of the routine gets tricky. To apply the */ + /* function only to what's in the edit cell, we use the selection */ + /* paint to compare against the edit cell, and apply the function */ + /* to matching paint, ignoring paint from non-edit cells. Because */ + /* the function may alter the edit cell, we must collect a list of */ + /* areas to paint, and apply them one by one without reference to */ + /* any actual tiles. */ + + GeoTransRect(&RootToEditTransform, &arg->sea_rect, &editRect); + arg->sea_rectList = NULL; + + /* If we have selected a chunk, set sea_flags to mark */ + /* this condition (see comments in selEnumPFunc2, below) */ + + if (SelectUse->cu_flags & CU_SELECT_CHUNK) + arg->sea_flags |= SEA_CHUNK; + if (!TTMaskIsZero(&SelectDef->cd_types)) + arg->sea_flags |= SEA_AREA; + + if (IsSplit(tile)) + DBSrPaintNMArea((Tile *)NULL, + EditCellUse->cu_def->cd_planes[arg->sea_plane], + arg->sea_type, &editRect, &DBAllTypeBits, selEnumPFunc2, + (ClientData)arg); + else + DBSrPaintArea((Tile *)NULL, + EditCellUse->cu_def->cd_planes[arg->sea_plane], + &editRect, &DBAllTypeBits, selEnumPFunc2, + (ClientData)arg); + + /* Each rectangle found represents paint that is both in */ + /* the selection and also in the edit cell. Call the */ + /* client for each such area. */ + + while (arg->sea_rectList != NULL) + { + GeoTransRect(&EditToRootTransform, &arg->sea_rectList->r_r, &rootRect); + GeoClip(&rootRect, &arg->sea_rect); + + if ((*arg->sea_func)(&rootRect, arg->sea_rectList->r_type, arg->sea_cdarg) != 0) + return 1; + freeMagic((char *)arg->sea_rectList); + arg->sea_rectList = arg->sea_rectList->r_next; + } + return 0; +} + +/* Second-level paint search function: save around (in edit coords) + * each tile that has the same type as requested in arg. Record if + * any wrong-type tiles are found. + */ + +int +selEnumPFunc2(tile, arg) + Tile *tile; /* Tile found in the edit cell */ + struct searg *arg; /* Describes our search */ +{ + ExtRectList *lr; + int ttype; + TileType seltype; + + if (IsSplit(tile)) + ttype = SplitSide(tile) ? SplitRightType(tile) : SplitLeftType(tile); + else + ttype = TiGetTypeExact(tile); + seltype = arg->sea_type & TT_LEFTMASK; + + /* Handle stacked contact types */ + if ((ttype != seltype) && (ttype >= DBNumUserLayers)) + { + TileTypeBitMask *rmask = DBResidueMask(ttype); + TileType rtype; + for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++) + if (TTMaskHasType(rmask, rtype)) + if (arg->sea_plane == DBPlane(rtype)) + { + ttype = rtype; + break; + } + } + + /* For chunk selection, the types have to match exactly, so we don't + * pick up bits of compatible material in another cell that were not + * intended (a chunk can only exist in one cell) + */ + if (arg->sea_flags & SEA_CHUNK) + if (ttype != seltype) + return 0; + + /* If we selected with "select area ", then the type */ + /* must belong to (after decomposing stacked types). */ + + if (arg->sea_flags & SEA_AREA) + if (ttype != seltype) + if (!TTMaskHasType(&SelectDef->cd_types, ttype)) + return 0; + + /* Check for compatible types. That is: paint X (in use) over Y */ + /* (in select) yields Y means that it is okay to add X to the list. */ + /* Also okay if the X over Y yields a stacking type whose residues */ + /* are X and Y. */ + + if ((ttype != seltype) && (((ttype == TT_SPACE) && + TTMaskHasType(&DBHomePlaneTypes[arg->sea_plane], seltype))) || + (DBPaintResultTbl[arg->sea_plane][ttype][seltype] != seltype)) + { + TileType chktype = DBPaintResultTbl[arg->sea_plane][ttype][seltype]; + TileTypeBitMask *cmask = DBResidueMask(chktype); + + if (chktype < DBNumUserLayers || ((ttype != chktype) + && !TTMaskHasType(cmask, ttype)) + || !TTMaskHasType(cmask, seltype)) + { + if (arg->sea_nonEdit != NULL) *(arg->sea_nonEdit) = TRUE; + } + return 0; + } + + /* Only process contacts once: only process the home plane */ + /* image of any contact type. Stacked contacts are treated */ + /* as whichever residue (contact) is in its home plane. */ + + if (DBIsContact(ttype)) + { + if (ttype < DBNumUserLayers) + { + if (arg->sea_plane != DBPlane(ttype)) return 0; + } + else /* stacked contact type */ + { + TileTypeBitMask *rmask = DBResidueMask(ttype); + TileType rtype; + for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++) + if (TTMaskHasType(rmask, rtype) && + arg->sea_plane == DBPlane(rtype)) + break; + if (rtype == DBNumUserLayers) return 0; + + /* Continue, with the tile type recast as rtype */ + + ttype = rtype; + } + } + + lr = (ExtRectList *)mallocMagic(sizeof(ExtRectList)); + TiToRect(tile, &lr->r_r); + + if (arg->sea_type & TT_DIAGONAL) + { + Point points[5]; + int np, i, j; + Rect area, orect; + + if (!IsSplit(tile)) + { + /* Things get messy here. Clip against the select triangle */ + /* and decompose the result into rectangles and triangles. */ + + GrClipTriangle(&arg->sea_rect, &lr->r_r, TRUE, arg->sea_type, points, &np); + + if (np < 3) + { + freeMagic((char *)lr); + return 0; /* Clipped out of existence */ + } + else + { + for (i = 0; i < np; i++) + { + j = (i + 1) % np; + if (points[i].p_x != points[j].p_x && points[i].p_y != + points[j].p_y) + { + /* Break out the triangle */ + lr->r_r.r_xbot = points[i].p_x; + lr->r_r.r_xtop = points[j].p_x; + lr->r_r.r_ybot = points[i].p_y; + lr->r_r.r_ytop = points[j].p_y; + GeoCanonicalRect(&lr->r_r, &area); + break; + } + } + if (i == np) /* Exactly one Manhattan rectangle */ + { + lr->r_r.r_xbot = points[0].p_x; + lr->r_r.r_xtop = points[2].p_x; + lr->r_r.r_ybot = points[0].p_y; + lr->r_r.r_ytop = points[2].p_y; + GeoCanonicalRect(&lr->r_r, &area); + lr->r_type = ttype; + } + else if (np >= 4) /* Process extra rectangles */ + { + orect.r_xtop = orect.r_xbot = points[0].p_x; + orect.r_ytop = orect.r_ybot = points[0].p_y; + for (i = 0; i < np; i++) + GeoIncludePoint(&points[i], &orect); + + /* Rectangle to right or left */ + lr->r_r.r_ybot = orect.r_ybot; + lr->r_r.r_ytop = orect.r_ytop; + if (area.r_xbot > orect.r_xbot) + { + lr->r_r.r_xbot = orect.r_xbot; + lr->r_r.r_xtop = area.r_xbot; + } + else if (area.r_xtop < orect.r_xtop) + { + lr->r_r.r_xtop = orect.r_xtop; + lr->r_r.r_xbot = area.r_xtop; + } + else + goto topbottom; + + lr->r_type = ttype; + lr->r_next = arg->sea_rectList; + arg->sea_rectList = lr; + lr = (ExtRectList *)mallocMagic(sizeof(ExtRectList)); + lr->r_r = arg->sea_rectList->r_r; +topbottom: + /* Rectangle to top or bottom */ + lr->r_r.r_xbot = area.r_xbot; + lr->r_r.r_xtop = area.r_xtop; + if (area.r_ybot > orect.r_ybot) + { + lr->r_r.r_ybot = orect.r_ybot; + lr->r_r.r_ytop = area.r_ybot; + } + else if (area.r_ytop < orect.r_ytop) + { + lr->r_r.r_ytop = orect.r_ytop; + lr->r_r.r_ybot = area.r_ytop; + } + else + { + lr->r_type = ttype; + goto splitdone; + } + + lr->r_type = ttype; + lr->r_next = arg->sea_rectList; + arg->sea_rectList = lr; + lr = (ExtRectList *)mallocMagic(sizeof(ExtRectList)); + lr->r_r = area; + lr->r_type = arg->sea_type; + } + else + { + lr->r_r = area; + lr->r_type = arg->sea_type; + } + } + } + else + { + /* NOTE: Need general-purpose triangle-triangle */ + /* intersection routine here! However, for most */ + /* purposes, it suffices to copy the tile if the */ + /* triangles are similar and to compute the */ + /* rectangular union are if opposite. */ + if ((arg->sea_type & TT_SIDE) == (TiGetTypeExact(tile) & TT_SIDE)) + lr->r_type = ttype | (arg->sea_type & + (TT_DIAGONAL | TT_SIDE | TT_DIRECTION)); + else + lr->r_type = ttype; + } + } + else + lr->r_type = ttype; + +splitdone: + lr->r_next = arg->sea_rectList; + arg->sea_rectList = lr; + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * SelEnumCells -- + * + * Call a client-supplied procedure for each selected subcell. + * If "editOnly" is TRUE, then only consider selected subcells + * that are children of the edit cell. The client procedure + * must be of the form + * + * int + * func(selUse, realUse, transform, clientData) + * CellUse *selUse; + * CellUse *realUse; + * Transform *transform; + * ClientData clientData; + * { + * } + * + * SelUse is a pointer to a cellUse that's in the selection cell. + * RealUse is a pointer to the corresponding cell that's part of + * the layout. Transform is a transform from the coordinates of + * RealUse to root coordinates. If the cell is an array, only one + * call is made for the entire array, and transform is the transform + * for the root element of the array (array[xlo, ylo]). Func should + * normally return 0. If it returns a non-zero return value, then + * the search will be aborted. + * + * Results: + * Returns 0 if the search finished normally. Returns 1 if the + * search was aborted. + * + * Side effects: + * If foundNonEdit is non-NULL, its target is set to indicate + * whether there were selected cells that weren't children of + * the edit cell. Otherwise, the only side effects are those + * of func. + * + * ---------------------------------------------------------------------------- + */ + +int +SelEnumCells(editOnly, foundNonEdit, scx, func, clientData) + bool editOnly; /* TRUE means only find material that is + * both selected and in the edit cell. + */ + bool *foundNonEdit; /* If non-NULL, this word is set to TRUE + * if there are one or more selected cells + * that aren't children of the edit cell, + * FALSE otherwise. + */ + SearchContext *scx; /* Most clients will provide a NULL value + * here, in which case all the subcells in + * the selection are enumerated. If this + * is non-NULL, it describes a different + * area in which to enumerate subcells. This + * feature is intended primarily for internal + * use within this module. + */ + int (*func)(); /* Function to call for subcells found. */ + ClientData clientData; /* Argument to pass through to func. */ +{ + struct searg arg; + SearchContext scx2; + extern int selEnumCFunc1(); /* Forward reference. */ + + arg.sea_func = func; + arg.sea_cdarg = clientData; + arg.sea_flags = (editOnly) ? SEA_EDIT_ONLY : 0; + arg.sea_nonEdit = foundNonEdit; + if (foundNonEdit != NULL) *foundNonEdit = FALSE; + + /* Find all the subcells that are in the selection. */ + + if (scx != NULL) + scx2 = *scx; + else + { + scx2.scx_use = SelectUse; + scx2.scx_area = TiPlaneRect; + scx2.scx_trans = GeoIdentityTransform; + } + if (DBCellSrArea(&scx2, selEnumCFunc1, (ClientData) &arg) != 0) + return 1; + return 0; +} + +/* The first-level search function: called for each subcell in the + * selection. + */ + +int +selEnumCFunc1(scx, arg) + SearchContext *scx; /* Describes cell that was found. */ + struct searg *arg; /* Describes our search. */ +{ + SearchContext scx2; + extern int selEnumCFunc2(); /* Forward reference. */ + CellUse dummy; + + /* If this cell is the top-level one in its window, we have to + * handle it specially: just look for any use that's a top-level + * use, then call the client for it. + */ + + if (scx->scx_use->cu_def == SelectRootDef) + { + CellUse *parent; + + /* A root use can't ever be a child of the edit cell. */ + + if (arg->sea_flags & SEA_EDIT_ONLY) + { + if (arg->sea_nonEdit != NULL) *(arg->sea_nonEdit) = TRUE; + return 2; + } + + /* Find a top-level use (one with no parent). */ + + for (parent = SelectRootDef->cd_parents; + parent != NULL; + parent = parent->cu_nextuse) + { + if (parent->cu_parent == NULL) break; + } + + if (parent == NULL) + { + TxError("Internal error: couldn't find selected root cell %s.\n", + SelectRootDef->cd_name); + return 2; + } + + /* Call the client. */ + + if ((*arg->sea_func)(scx->scx_use, parent, &GeoIdentityTransform, + arg->sea_cdarg) != 0) + return 1; + return 2; + } + + /* This isn't a top-level cell. Find the instance corresponding + * to this one in the layout. Only search a 1-unit square at the + * cell's lower-left corner in order to cut down the work that + * has to be done. Unfortunately + * we can't use DBTreeSrCells for this, because we don't want to + * look at expanded/unexpanded information. + */ + + scx2.scx_use = &dummy; + dummy.cu_def = SelectRootDef; + dummy.cu_id = NULL; + GeoTransRect(&scx->scx_use->cu_transform, &scx->scx_use->cu_def->cd_bbox, + &scx2.scx_area); + scx2.scx_area.r_xtop = scx2.scx_area.r_xbot + 1; + scx2.scx_area.r_ytop = scx2.scx_area.r_ybot + 1; + scx2.scx_trans = GeoIdentityTransform; + arg->sea_use = scx->scx_use; + arg->sea_foundUse = NULL; + (void) DBCellSrArea(&scx2, selEnumCFunc2, (ClientData) arg); + if (arg->sea_foundUse == NULL) + { + TxError("Internal error: couldn't find selected cell %s.\n", + arg->sea_use->cu_id); + return 2; + } + + /* See whether the cell is a child of the edit cell and + * call the client's procedure if everything's OK. We do the + * call here rather than in selEnumCFunc2 because the client + * could modify the edit cell in a way that would cause the + * search in progress to core dump. By the time we get back + * here, the search is complete so there's no danger. + */ + + if (arg->sea_flags & SEA_EDIT_ONLY) + { + if (!EditCellUse) return 1; + if (arg->sea_foundUse->cu_parent != EditCellUse->cu_def) + { + if (arg->sea_nonEdit != NULL) *(arg->sea_nonEdit) = TRUE; + return 2; + } + } + if ((*arg->sea_func)(scx->scx_use, arg->sea_foundUse, + &arg->sea_foundTrans, arg->sea_cdarg) != 0) + return 1; + return 2; +} + +/* Second-level cell search function: called for each cell in the + * tree of SelectRootDef that touches the lower-left corner of + * the subcell in the selection that we're trying to match. If + * this use is for the same subcell, and has the same transformation + * and array structure, then remember the cell use for the caller + * and abort the search. + */ + +int +selEnumCFunc2(scx, arg) + SearchContext *scx; /* Describes child of edit cell. */ + struct searg *arg; /* Describes what we're looking for. */ +{ + CellUse *use, *selUse; + + use = scx->scx_use; + selUse = arg->sea_use; + if (use->cu_def != selUse->cu_def) goto checkChildren; + if ((scx->scx_trans.t_a != selUse->cu_transform.t_a) + || (scx->scx_trans.t_b != selUse->cu_transform.t_b) + || (scx->scx_trans.t_c != selUse->cu_transform.t_c) + || (scx->scx_trans.t_d != selUse->cu_transform.t_d) + || (scx->scx_trans.t_e != selUse->cu_transform.t_e) + || (scx->scx_trans.t_f != selUse->cu_transform.t_f)) + goto checkChildren; + if ((use->cu_array.ar_xlo != selUse->cu_array.ar_xlo) + || (use->cu_array.ar_ylo != selUse->cu_array.ar_ylo) + || (use->cu_array.ar_xhi != selUse->cu_array.ar_xhi) + || (use->cu_array.ar_yhi != selUse->cu_array.ar_yhi) + || (use->cu_array.ar_xsep != selUse->cu_array.ar_xsep) + || (use->cu_array.ar_ysep != selUse->cu_array.ar_ysep)) + goto checkChildren; + + arg->sea_foundUse = use; + arg->sea_foundTrans = scx->scx_trans; + return 1; + + /* This cell didn't match... see if any of its children do. */ + + checkChildren: + if (DBCellSrArea(scx, selEnumCFunc2, (ClientData) arg) != 0) + return 1; + else return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelEnumLabels -- + * + * Find all selected labels, and call the client's procedure for + * each label found. Only consider labels attached to "layers", + * and if "editOnly" is TRUE, then only consider labels that + * are in the edit cell. The client procedure must be of the + * form + * + * int + * func(label, cellUse, transform, clientData) + * Label *label; + * CellUse *cellUse; + * Transform *transform; + * ClientData clientData; + * { + * } + * + * Label is a pointer to a selected label. It refers to the label + * in cellUse, and transform gives the transform from that + * cell's coordinates to root coordinates. ClientData is just + * the clientData argument passed to this procedure. Func + * should normally return 0. If it returns a non-zero return + * value, then the search will be aborted. + * + * Results: + * Returns 0 if the search finished normally. Returns 1 if the + * search was aborted. + * + * Side effects: + * If foundNonEdit is non-NULL, its target is set to indicate + * whether there was at least one selected label that was not + * in the edit cell. Otherwise, the only side effects are + * those of func. + * + * ---------------------------------------------------------------------------- + */ + +int +SelEnumLabels(layers, editOnly, foundNonEdit, func, clientData) + TileTypeBitMask *layers; /* Find labels on these layers. */ + bool editOnly; /* TRUE means only find labels that are + * both selected and in the edit cell. + */ + bool *foundNonEdit; /* If non-NULL, this word is set to TRUE + * if there are selected labels that aren't + * in the edit cell, FALSE otherwise. + */ + int (*func)(); /* Function to call for each label found. */ + ClientData clientData; /* Argument to pass through to func. */ +{ + Label *selLabel; + CellUse dummy; + SearchContext scx; + struct searg arg; + extern int selEnumLFunc(); /* Forward reference. */ + extern int selEnumLFunc2(); + + if (foundNonEdit != NULL) *foundNonEdit = FALSE; + + /* First of all, search through all of the selected labels. */ + + for (selLabel = SelectDef->cd_labels; selLabel != NULL; + selLabel = selLabel->lab_next) + { + if (!TTMaskHasType(layers, selLabel->lab_type)) continue; + + /* Find the label corresponding to this one in the design. */ + + scx.scx_use = &dummy; + dummy.cu_def = SelectRootDef; + dummy.cu_id = NULL; + GEO_EXPAND(&selLabel->lab_rect, 1, &scx.scx_area); + scx.scx_trans = GeoIdentityTransform; + arg.sea_label = selLabel; + arg.sea_foundLabel = NULL; + (void) DBTreeSrLabels(&scx, &DBAllTypeBits, 0, (TerminalPath *) NULL, + TF_LABEL_ATTACH, selEnumLFunc, (ClientData) &arg); + if (arg.sea_foundLabel == NULL) + { + /* Take a 2nd try with relaxed criteria. We may have */ + /* altered the text or label justification. */ + + DBTreeSrLabels(&scx, &DBAllTypeBits, 0, (TerminalPath *) NULL, + TF_LABEL_ATTACH, selEnumLFunc2, (ClientData) &arg); + if (arg.sea_foundLabel == NULL) + { + TxError("Internal error: couldn't find selected label %s.\n", + selLabel->lab_text); + continue; + } + } + + /* If only edit-cell labels are wanted, check this label's + * parentage. + */ + + if (editOnly && (arg.sea_foundUse->cu_def != EditCellUse->cu_def)) + { + if (foundNonEdit != NULL) *foundNonEdit = TRUE; + continue; + } + + if ((*func)(arg.sea_foundLabel, arg.sea_foundUse, + &arg.sea_foundTrans, clientData) != 0) return 1; + } + + return 0; +} + +/* Search function for label enumeration: make sure that this label + * matches the one we're looking for. If it does, then record + * information about it and return right away. + */ + + /* ARGSUSED */ +int +selEnumLFunc(scx, label, tpath, arg) + SearchContext *scx; /* Describes current cell for search. */ + Label *label; /* Describes label that is in right area + * and has right type. + */ + TerminalPath *tpath; /* Ignored. */ + struct searg *arg; /* Indicates what we're looking for. */ +{ + Rect *want, got; + + GeoTransRect(&scx->scx_trans, &label->lab_rect, &got); + want = &arg->sea_label->lab_rect; + if (want->r_xbot != got.r_xbot) return 0; + if (want->r_ybot != got.r_ybot) return 0; + if (want->r_xtop != got.r_xtop) return 0; + if (want->r_ytop != got.r_ytop) return 0; + if (arg->sea_label->lab_just + != GeoTransPos(&scx->scx_trans, label->lab_just)) return 0; + if (strcmp(label->lab_text, arg->sea_label->lab_text) != 0) return 0; + + arg->sea_foundLabel = label; + arg->sea_foundUse = scx->scx_use; + arg->sea_foundTrans = scx->scx_trans; + return 1; +} + +/* + * selEnumLFunc2() is like selEnumLFunc(), but it allows one of the justification + * or the text string to differ between the source and target labels. This + * prevents magic from failing to find the label if "setlabel text" or + * "setlabel just" is applied to the selection. Both functions are a lousy + * substitute for what ought to be an identifier tag. . . + */ + +int +selEnumLFunc2(scx, label, tpath, arg) + SearchContext *scx; /* Describes current cell for search. */ + Label *label; /* Describes label that is in right area + * and has right type. + */ + TerminalPath *tpath; /* Ignored. */ + struct searg *arg; /* Indicates what we're looking for. */ +{ + Rect *want, got; + int mismatch = 0; + + GeoTransRect(&scx->scx_trans, &label->lab_rect, &got); + want = &arg->sea_label->lab_rect; + if (want->r_xbot != got.r_xbot) return 0; + if (want->r_ybot != got.r_ybot) return 0; + if (want->r_xtop != got.r_xtop) return 0; + if (want->r_ytop != got.r_ytop) return 0; + if (arg->sea_label->lab_just != GeoTransPos(&scx->scx_trans, label->lab_just)) + mismatch++; + if (strcmp(label->lab_text, arg->sea_label->lab_text) != 0) + mismatch++; + + if (mismatch == 2) return 0; + + arg->sea_foundLabel = label; + arg->sea_foundUse = scx->scx_use; + arg->sea_foundTrans = scx->scx_trans; + return 1; +} diff --git a/select/selInt.h b/select/selInt.h new file mode 100644 index 00000000..1dcec61f --- /dev/null +++ b/select/selInt.h @@ -0,0 +1,44 @@ +/* + * selInt.h -- + * + * Contains definitions that are private to the implementation of + * the select module. No other module should need anything in here. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid="$Header: /usr/cvsroot/magic-8.0/select/selInt.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + */ + +#ifndef _SELINT_H +#define _SELINT_H + +#include "utils/magic.h" +#include "database/database.h" + +/* Procedures, variables, and records that are shared between + * files: + */ + +extern int SelRedisplay(); +extern void SelSetDisplay(); +extern void SelUndoInit(); +extern void SelRememberForUndo(); +extern void SelectAndCopy2(); + +extern CellUse *Select2Use; +extern CellDef *Select2Def; + +extern CellUse *selectLastUse; + +#endif /* _SELINT_H */ diff --git a/select/selOps.c b/select/selOps.c new file mode 100644 index 00000000..3dbc92ac --- /dev/null +++ b/select/selOps.c @@ -0,0 +1,1786 @@ +/* + * selOps.c -- + * + * This file contains top-level procedures to manipulate the selection, + * e.g. to delete it, move it, etc. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/select/selOps.c,v 1.11 2010/08/22 21:58:26 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/main.h" +#include "select/select.h" +#include "select/selInt.h" +#include "textio/textio.h" +#include "utils/undo.h" +#include "plow/plow.h" +#include "utils/malloc.h" +#include "drc/drc.h" + +/* The following variables are shared between SelectStretch and the + * search functions that it causes to be invoked. + */ + +static int selStretchX, selStretchY; /* Stretch distances. Only one should + * ever be non-zero. + */ +static TileType selStretchType; /* Type of material being stretched. */ + +typedef struct planeAndArea +{ + int pa_plane; /* Plane of interest */ + Rect *pa_area; /* Area affected */ + TileTypeBitMask *pa_mask; /* Mask used in plane search */ +} planeAndArea; + +/* The following structure type is used to build up a list of areas + * to be painted. It's used to save information while a search of + * the edit cell is in progress: can't do the paints until the + * search has finished. + */ + +typedef struct stretchArea +{ + Rect sa_area; /* Area to be painted. */ + TileType sa_type; /* Type of material to paint. */ + struct stretchArea *sa_next; /* Next element in list. */ +} StretchArea; + +static StretchArea *selStretchList; /* List of areas to paint. */ + +/* + * ---------------------------------------------------------------------------- + * + * SelectDelete -- + * + * Delete everything in the edit cell that's selected. + * + * Results: + * None. + * + * Side effects: + * Stuff is removed from the edit cell. If there's selected + * stuff that isn't in the edit cell, the user is warned. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectDelete(msg, do_clear) + char *msg; /* Some information to print in error messages. + * For example, if called as part of a move procedure, + * supply "moved". This will appear in messages of + * the form "only edit cell information was moved". + */ + bool do_clear; /* If TRUE, clear the select def before returning. */ +{ + bool nonEdit; + Rect editArea; + + extern int selDelPaintFunc(), selDelCellFunc(), selDelLabelFunc(); + + (void) SelEnumPaint(&DBAllButSpaceAndDRCBits, TRUE, &nonEdit, + selDelPaintFunc, (ClientData) NULL); + if (nonEdit) + { + TxError("You selected paint outside the edit cell. Only\n"); + TxError(" the paint in the edit cell was %s.\n", msg); + } + (void) SelEnumCells(TRUE, &nonEdit, (SearchContext *) NULL, + selDelCellFunc, (ClientData) NULL); + if (nonEdit) + { + TxError("You selected one or more subcells that aren't children\n"); + TxError(" of the edit cell. Only those in the edit cell were\n"); + TxError(" %s.\n", msg); + } + (void) SelEnumLabels(&DBAllTypeBits, TRUE, &nonEdit, + selDelLabelFunc, (ClientData) NULL); + if (nonEdit) + { + TxError("You selected one or more labels that aren't in the\n"); + TxError(" edit cell. Only the label(s) in the edit cell\n"); + TxError(" were %s.\n", msg); + } + + DBReComputeBbox(EditCellUse->cu_def); + GeoTransRect(&RootToEditTransform, &SelectDef->cd_extended, &editArea); + DBWAreaChanged(EditCellUse->cu_def, &editArea, DBW_ALLWINDOWS, + (TileTypeBitMask *) NULL); + DRCCheckThis(EditCellUse->cu_def, TT_CHECKPAINT, &editArea); + if (do_clear) SelectClear(); +} + +/* Search function to delete paint. */ + +int +selDelPaintFunc(rect, type) + Rect *rect; /* Area of paint, in root coords. */ + TileType type; /* Type of paint to delete. */ +{ + Rect editRect; + TileTypeBitMask tmask; + TileType dinfo; + + /* Change diagonal side & direction according to the transform */ + + if (type & TT_DIAGONAL) + { + dinfo = DBTransformDiagonal(type, &RootToEditTransform); + TTMaskSetOnlyType(&tmask, type & TT_LEFTMASK); + } + else + { + dinfo = 0; + TTMaskSetOnlyType(&tmask, type); + } + + GeoTransRect(&RootToEditTransform, rect, &editRect); + + DBEraseValid(EditCellUse->cu_def, &editRect, &tmask, dinfo); + return 0; +} + +/* Search function to delete subcell uses. */ + + /* ARGSUSED */ +int +selDelCellFunc(selUse, use) + CellUse *selUse; /* Not used. */ + CellUse *use; /* What to delete. */ +{ + if (use->cu_flags & CU_LOCKED) return 0; + + DBUnLinkCell(use, use->cu_parent); + DBDeleteCell(use); + (void) DBCellDeleteUse(use); + return 0; +} + + +/* Search function to delete labels. Delete any label at the right + * place with the right name, regardless of layer attachment, because + * the selection can differ from the edit cell in this regard. */ + +int +selDelLabelFunc(label) + Label *label; /* Label to delete. */ +{ + DBEraseLabelsByContent(EditCellUse->cu_def, &label->lab_rect, -1, + label->lab_text); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectCopy -- + * + * This procedure makes a copy of the selection. + * + * Results: + * None. + * + * Side effects: + * The selection is copied, with the copy being transformed by + * "transform" relative to the current selection. The copy is + * made the new selection. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectCopy(transform) + Transform *transform; /* How to displace the copy relative + * to the original. This displacement + * is given in root coordinates. + */ +{ + SearchContext scx; + + /* Copy from SelectDef to Select2Def while transforming, then + * let SelectAndCopy2 do the rest of the work. Don't record + * anything involving Select2Def for undo-ing. + */ + + UndoDisable(); + DBCellClearDef(Select2Def); + scx.scx_use = SelectUse; + scx.scx_area = SelectUse->cu_bbox; + GeoTransTrans(transform, &SelectUse->cu_transform, &scx.scx_trans); + (void) DBCellCopyAllPaint(&scx, &DBAllButSpaceAndDRCBits, CU_DESCEND_NO_LOCK, + Select2Use); + (void) DBCellCopyAllLabels(&scx, &DBAllTypeBits, CU_DESCEND_NO_LOCK, Select2Use, + (Rect *) NULL); + (void) DBCellCopyAllCells(&scx, CU_DESCEND_NO_LOCK, Select2Use, (Rect *) NULL); + DBReComputeBbox(Select2Def); + UndoEnable(); + + SelectClear(); + SelectAndCopy2(EditRootDef); +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectFlat -- + * + * This procedure copies the selection into Select2Def, flattening + * it as it copies, then copies the result back into the selection + * cell. + * + * Results: + * None. + * + * Side effects: + * The selection is flattened. No changes are made in the edit cell. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectFlat() +{ + SearchContext scx; + + /* Copy from SelectDef to Select2Def while transforming, then + * let SelectAndCopy2 do the rest of the work. Don't record + * anything involving Select2Def for undo-ing. + */ + + UndoDisable(); + DBCellClearDef(Select2Def); + scx.scx_use = SelectUse; + scx.scx_area = SelectUse->cu_bbox; + GeoTransTrans(&GeoIdentityTransform, &SelectUse->cu_transform, &scx.scx_trans); + DBCellCopyAllPaint(&scx, &DBAllButSpaceAndDRCBits, CU_DESCEND_ALL, Select2Use); + FlatCopyAllLabels(&scx, &DBAllTypeBits, CU_DESCEND_ALL, Select2Use); + DBReComputeBbox(Select2Def); + UndoEnable(); + + /* Move everything from Select2 to Select */ + + SelectClear(); + SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL); + + scx.scx_use = Select2Use; + scx.scx_area = Select2Use->cu_bbox; + GeoTransTrans(&GeoIdentityTransform, &Select2Use->cu_transform, &scx.scx_trans); + + DBCellCopyAllPaint(&scx, &DBAllButSpaceAndDRCBits, CU_DESCEND_SPECIAL, + SelectUse); + DBCellCopyAllLabels(&scx, &DBAllTypeBits, CU_DESCEND_SPECIAL, SelectUse, + (Rect *)NULL); + + SelRememberForUndo(FALSE, SelectRootDef, &SelectUse->cu_bbox); + + /* Redisplay the select cell */ + DBWHLRedraw(SelectRootDef, &SelectDef->cd_extended, TRUE); + DBWAreaChanged(SelectDef, &SelectDef->cd_extended, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + +} + +/* + * ---------------------------------------------------------------------------- + * + * selShortFindPath -- + * + * Trace back through a path found by selShortFindNext from destination + * to source, picking the lowest cost return path, and adding each tile + * found to the linked list. + * + * Algorithm notes (for this and selShortFindNext): Note that by not + * using one of the standard database search routines, TT_SIDE is NOT + * set on any tile. To find out what side we're looking at, we keep + * a record of what direction we were traveling from the previous + * tile. Given this and the diagonal direction, we know the two + * valid sides to search. + * + * ---------------------------------------------------------------------------- + */ + +int +selShortFindPath(tile, pnum, rlist, fdir) + Tile *tile; + int pnum; + ExtRectList **rlist; + int fdir; +{ + Tile *tp, *mintp; + // int mincost = (int)tile->ti_client; + int mincost = INT_MAX; + ExtRectList *newrrec; + int minp, p, mindir; + TileType ttype; + + newrrec = mallocMagic(sizeof(ExtRectList)); + + if (IsSplit(tile)) + { + newrrec->r_type = TiGetTypeExact(tile) & ~TT_SIDE; + switch(fdir) + { + case GEO_NORTH: + ttype = SplitBottomType(tile); + if (!SplitDirection(tile)) newrrec->r_type |= TT_SIDE; + break; + case GEO_SOUTH: + ttype = SplitTopType(tile); + if (SplitDirection(tile)) newrrec->r_type |= TT_SIDE; + break; + case GEO_EAST: + ttype = SplitLeftType(tile); + break; + case GEO_WEST: + ttype = SplitRightType(tile); + newrrec->r_type |= TT_SIDE; + break; + default: + ttype = SplitRightType(tile); + if (ttype == TT_SPACE) + ttype = SplitLeftType(tile); + else + newrrec->r_type |= TT_SIDE; + break; + } + } + else + { + ttype = TiGetTypeExact(tile); + newrrec->r_type = ttype; + } + + /* Add this tile (area and type) to the linked list */ + + TiToRect(tile, &newrrec->r_r); + newrrec->r_next = *rlist; + *rlist = newrrec; + + if ((int)tile->ti_client == 0) return 0; /* We're done */ + // if (mincost == 0) return 0; /* We're done */ + minp = pnum; + + /* Search top */ + if (IsSplit(tile)) + { + if (fdir == GEO_NORTH) goto leftside; + else if (SplitDirection(tile) && fdir == GEO_EAST) goto leftside; + else if (!SplitDirection(tile) && fdir == GEO_WEST) goto leftside; + } + + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + { + if (tp->ti_client == (ClientData)CLIENTDEFAULT) continue; + if ((int)tp->ti_client < mincost) + { + mincost = (int)tp->ti_client; + mintp = tp; + mindir = GEO_NORTH; + } + } + + /* Search left */ +leftside: + if (IsSplit(tile)) + { + if (fdir == GEO_WEST) goto bottomside; + else if (SplitDirection(tile) && fdir == GEO_SOUTH) goto bottomside; + else if (!SplitDirection(tile) && fdir == GEO_NORTH) goto bottomside; + } + + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + { + if (tp->ti_client == (ClientData)CLIENTDEFAULT) continue; + if ((int)tp->ti_client < mincost) + { + mincost = (int)tp->ti_client; + mintp = tp; + mindir = GEO_WEST; + } + } + + /* Search bottom */ +bottomside: + if (IsSplit(tile)) + { + if (fdir == GEO_SOUTH) goto rightside; + else if (SplitDirection(tile) && fdir == GEO_WEST) goto rightside; + else if (!SplitDirection(tile) && fdir == GEO_EAST) goto rightside; + } + + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + { + if (tp->ti_client == (ClientData)CLIENTDEFAULT) continue; + if ((int)tp->ti_client < mincost) + { + mincost = (int)tp->ti_client; + mintp = tp; + mindir = GEO_SOUTH; + } + } + + /* Search right */ +rightside: + if (IsSplit(tile)) + { + if (fdir == GEO_EAST) goto donesides; + else if (SplitDirection(tile) && fdir == GEO_NORTH) goto donesides; + else if (!SplitDirection(tile) && fdir == GEO_SOUTH) goto donesides; + } + + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + { + if (tp->ti_client == (ClientData)CLIENTDEFAULT) continue; + if ((int)tp->ti_client < mincost) + { + mincost = (int)tp->ti_client; + mintp = tp; + mindir = GEO_EAST; + } + } + + /* Search other connecting planes */ +donesides: + if (DBIsContact(ttype)) + { + PlaneMask pmask; + + pmask = DBConnPlanes[ttype]; + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + { + if (PlaneMaskHasPlane(pmask, p) && (p != pnum)) + { + tp = SelectDef->cd_planes[p]->pl_hint; + GOTOPOINT(tp, &tile->ti_ll); + if (tp->ti_client == (ClientData)CLIENTDEFAULT) continue; + if ((int)tp->ti_client < mincost) + { + mincost = (int)tp->ti_client; + mintp = tp; + minp = p; + mindir = GEO_CENTER; + } + } + } + } + + /* If mincost is still set to INT_MAX we have a real serious problem! */ + if (mincost == INT_MAX) return 1; + + /* If no tile had lower cost than this one, then we have an error */ + // if (mincost == (int)tile->ti_client) return 1; + + /* Stopgap measure: Error should not happen, but it does! */ + /* Remove client data of current tile and take minimum. */ + if (mincost == (int)tile->ti_client) TiSetClient(tile, CLIENTDEFAULT); + + /* Now we have the minimum cost neighboring tile; recursively search it */ + + return selShortFindPath(mintp, minp, rlist, mindir); +} + +/* + * ---------------------------------------------------------------------------- + * + * selShortFindNext -- + * + * Recursive function for finding shorts. This routine makes strong + * assumptions; namely, that all non-space material in the cell being + * searched belongs to the same net. The cell searched is always + * SelectDef. + * + * Results: + * Return 0 to keep going; return 1 to stop when the tile contains + * the destination point. + * + * Side effects: + * Each tile visited has its ClientData record set to the current + * cost, in units equal to the steps from the source. + * + * ---------------------------------------------------------------------------- + */ + +int +selShortFindNext(tile, pnum, ldest, cost, best, fdir, mask) + Tile *tile; + int pnum; + Label *ldest; + int cost, *best, fdir; + TileTypeBitMask *mask; +{ + TileType ttype; + TileTypeBitMask *lmask; + Tile *tp; + + if (IsSplit(tile)) + { + switch(fdir) + { + case GEO_NORTH: + ttype = SplitBottomType(tile); + break; + case GEO_SOUTH: + ttype = SplitTopType(tile); + break; + case GEO_EAST: + ttype = SplitLeftType(tile); + break; + case GEO_WEST: + ttype = SplitRightType(tile); + break; + default: + ttype = SplitLeftType(tile); + if (ttype == TT_SPACE) ttype = SplitRightType(tile); + break; + } + } + else + ttype = TiGetTypeExact(tile); + + /* Ignore space tiles */ + if (ttype == TT_SPACE) return 0; + + /* Ignore non-connecting tiles */ + if (!TTMaskHasType(mask, ttype)) return 0; + + /* If this tile is unvisited, or has a lower cost, then return and */ + /* keep going. Otherwise, return 1 to stop the search this direction */ + + if (tile->ti_client == (ClientData)CLIENTDEFAULT) + TiSetClient(tile, cost); + else if ((int)tile->ti_client > cost) + TiSetClient(tile, cost); + else + return 0; + + /* If this tile contains the destination point, do not search further */ + + if ((ttype == ldest->lab_type) && EnclosePoint(tile, &ldest->lab_rect.r_ll)) + { + if (*best >= cost) *best = (cost - 1); + return 0; + } + + /* If we're more costly than the best known path to destination, do */ + /* not search further. */ + + if (cost >= *best) return 0; + lmask = &DBConnectTbl[ttype]; + + /* Search top */ + if (IsSplit(tile)) + { + if (fdir == GEO_NORTH) goto srchleft; + else if (SplitDirection(tile) && fdir == GEO_EAST) goto srchleft; + else if (!SplitDirection(tile) && fdir == GEO_WEST) goto srchleft; + } + + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + { + selShortFindNext(tp, pnum, ldest, cost + 1, best, GEO_NORTH, lmask); + } + + /* Search left */ +srchleft: + if (IsSplit(tile)) + { + if (fdir == GEO_WEST) goto srchbot; + else if (SplitDirection(tile) && fdir == GEO_SOUTH) goto srchbot; + else if (!SplitDirection(tile) && fdir == GEO_NORTH) goto srchbot; + } + + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + { + selShortFindNext(tp, pnum, ldest, cost + 1, best, GEO_WEST, lmask); + } + + /* Search bottom */ +srchbot: + if (IsSplit(tile)) + { + if (fdir == GEO_SOUTH) goto srchright; + else if (SplitDirection(tile) && fdir == GEO_WEST) goto srchright; + else if (!SplitDirection(tile) && fdir == GEO_EAST) goto srchright; + } + + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + { + selShortFindNext(tp, pnum, ldest, cost + 1, best, GEO_SOUTH, lmask); + } + + /* Search right */ +srchright: + if (IsSplit(tile)) + { + if (fdir == GEO_EAST) goto donesrch; + else if (SplitDirection(tile) && fdir == GEO_NORTH) goto donesrch; + else if (!SplitDirection(tile) && fdir == GEO_SOUTH) goto donesrch; + } + + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + { + selShortFindNext(tp, pnum, ldest, cost + 1, best, GEO_EAST, lmask); + } + + /* Search other connecting planes */ +donesrch: + if (DBIsContact(ttype)) + { + PlaneMask pmask; + int p; + + pmask = DBConnPlanes[ttype]; + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + { + if (PlaneMaskHasPlane(pmask, p) && (p != pnum)) + { + tp = SelectDef->cd_planes[p]->pl_hint; + GOTOPOINT(tp, &tile->ti_ll); + selShortFindNext(tp, p, ldest, cost + 1, best, GEO_CENTER, lmask); + } + } + } + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * SelectShort -- + * + * This procedure, given two labels, finds the location of those + * labels in SelectDef. One is marked as source, the other as + * destination. Then the SelectDef paint (which is assumed to be + * a net selection that is all local to SelectDef) is recursively + * searched for connecting material. Each tile ClientData is + * given a cost which is the number of steps from the source. + * At the end, the minimum cost path is traced from the destination + * back to the source, and the path is saved as a linked list and + * passed back to the calling procedure. + * + * Results: + * A linked list of tiles representing the connecting path with the + * fewest steps between source and destination. + * + * Side effects: + * Tile database left with non-default ClientData. It may be necessary + * to re-run the search routine to return all tiles to the default + * ClientData value. + * ---------------------------------------------------------------------------- + */ + +ExtRectList * +SelectShort(char *lab1, char *lab2) +{ + Label *selLabel, *srclab = NULL, *destlab = NULL; + Tile *tile; + Plane *plane; + int pnum, best; + PlaneMask pmask; + ExtRectList *rlist; + + /* Step one: find the tiles containing the labels. If not found, */ + /* return NULL. */ + + for (selLabel = SelectDef->cd_labels; selLabel != NULL; selLabel = + selLabel->lab_next) + { + if ((srclab == NULL) && Match(lab1, selLabel->lab_text)) + srclab = selLabel; + + if ((destlab == NULL) && Match(lab2, selLabel->lab_text)) + destlab = selLabel; + } + + /* Must be able to find both labels */ + if (srclab == NULL || destlab == NULL) return NULL; + + /* Must be able to find tiles associated with each label */ + + pmask = DBTypePlaneMaskTbl[srclab->lab_type]; + for (pnum = PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++) + { + if (PlaneMaskHasPlane(pmask, pnum)) + { + plane = SelectDef->cd_planes[pnum]; + tile = plane->pl_hint; + GOTOPOINT(tile, &srclab->lab_rect.r_ll) + if (TiGetType(tile) == srclab->lab_type) break; + } + } + best = INT_MAX; + selShortFindNext(tile, pnum, &destlab->lab_rect.r_ll, 0, &best, GEO_CENTER, + &DBConnectTbl[srclab->lab_type]); + + /* Now see if destination has been counted */ + + pmask = DBTypePlaneMaskTbl[destlab->lab_type]; + for (pnum = PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++) + { + if (PlaneMaskHasPlane(pmask, pnum)) + { + plane = SelectDef->cd_planes[pnum]; + tile = plane->pl_hint; + GOTOPOINT(tile, &destlab->lab_rect.r_ll) + if (TiGetType(tile) == destlab->lab_type) break; + } + } + + if (tile->ti_client == (ClientData)CLIENTDEFAULT) return NULL; + + /* Now find the shortest path between source and destination */ + rlist = NULL; + selShortFindPath(tile, pnum, &rlist, GEO_CENTER); + + return rlist; +} + + +/* + * ---------------------------------------------------------------------------- + * + * selTransTo2 -- + * + * This local procedure makes a transformed copy of the selection + * in Select2Def, ignoring everything that's not in the edit cell. + * + * Results: + * None. + * + * Side effects: + * Select2Def gets modified to hold the transformed selection. + * Error messages get printed if the selection contains any + * non-edit material. + * + * ---------------------------------------------------------------------------- + */ + +void +selTransTo2(transform) + Transform *transform; /* How to transform stuff before copying + * it to Select2Def. + */ +{ + int selTransPaintFunc(); /* Forward references. */ + int selTransCellFunc(); + int selTransLabelFunc(); + + UndoDisable(); + DBCellClearDef(Select2Def); + (void) SelEnumPaint(&DBAllButSpaceAndDRCBits, TRUE, (bool *) NULL, + selTransPaintFunc, (ClientData) transform); + (void) SelEnumCells(TRUE, (bool *) NULL, (SearchContext *) NULL, + selTransCellFunc, (ClientData) transform); + (void) SelEnumLabels(&DBAllTypeBits, TRUE, (bool *) NULL, + selTransLabelFunc, (ClientData) transform); + DBReComputeBbox(Select2Def); + UndoEnable(); +} + +/* Search function to copy paint. Always return 1 to keep the search alive. */ + +int +selTransPaintFunc(rect, type, transform) + Rect *rect; /* Area of paint. */ + TileType type; /* Type of paint. */ + Transform *transform; /* How to change coords before painting. */ +{ + Rect newarea; + TileType loctype; + + /* Change diagonal direction according to the transform */ + if (type & TT_DIAGONAL) + { + loctype = DBTransformDiagonal(type, transform); + loctype |= (loctype & TT_SIDE) ? (type & TT_LEFTMASK) << 14 : + (type & TT_LEFTMASK); + } + else + loctype = type; + + GeoTransRect(transform, rect, &newarea); + DBPaint(Select2Def, &newarea, loctype); + return 0; +} + +/* Search function to copy subcells. Always return 1 to keep the + * search alive. + */ + + /* ARGSUSED */ +int +selTransCellFunc(selUse, realUse, realTrans, transform) + CellUse *selUse; /* Use from selection. */ + CellUse *realUse; /* Corresponding use from layout (used to + * get id). */ + Transform *realTrans; /* Transform for realUse (ignored). */ + Transform *transform; /* How to change coords of selUse before + * copying. + */ +{ + CellUse *newUse; + Transform newTrans; + + if (selUse->cu_flags & CU_LOCKED) return 0; + + newUse = DBCellNewUse(selUse->cu_def, (char *) realUse->cu_id); + if (!DBLinkCell(newUse, Select2Def)) + { + freeMagic((char *) newUse->cu_id); + newUse->cu_id = NULL; + (void) DBLinkCell(newUse, Select2Def); + } + GeoTransTrans(&selUse->cu_transform, transform, &newTrans); + DBSetArray(selUse, newUse); + DBSetTrans(newUse, &newTrans); + newUse->cu_expandMask = selUse->cu_expandMask; + newUse->cu_flags = selUse->cu_flags; + DBPlaceCell(newUse, Select2Def); + + return 0; +} + +/* Search function to copy labels. Return 0 always to avoid + * aborting search. + */ + + /* ARGSUSED */ +int +selTransLabelFunc(label, cellUse, defTransform, transform) + Label *label; /* Label to copy. This points to label + * in cellDef. + */ + CellUse *cellUse; /* (unused) */ + Transform *defTransform; /* Transform from cellDef to root. */ + Transform *transform; /* How to modify coords before copying to + * Select2Def. + */ +{ + Rect rootArea, finalArea; + int rootJust, finalJust; + Point rootOffset, finalOffset; + int rootRotate, finalRotate; + + GeoTransRect(defTransform, &label->lab_rect, &rootArea); + rootJust = GeoTransPos(defTransform, label->lab_just); + GeoTransPointDelta(defTransform, &label->lab_offset, &rootOffset); + rootRotate = GeoTransAngle(defTransform, label->lab_rotate); + + GeoTransRect(transform, &rootArea, &finalArea); + finalJust = GeoTransPos(transform, rootJust); + GeoTransPointDelta(transform, &rootOffset, &finalOffset); + finalRotate = GeoTransAngle(transform, rootRotate); + + (void) DBPutFontLabel(Select2Def, &finalArea, label->lab_font, + label->lab_size, finalRotate, &finalOffset, finalJust, + label->lab_text, label->lab_type, label->lab_flags); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectTransform -- + * + * This procedure modifies the selection by transforming + * it geometrically. + * + * Results: + * None. + * + * Side effects: + * The selection is modified and redisplayed. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectTransform(transform) + Transform *transform; /* How to displace the selection. + * The transform is in root (user- + * visible) coordinates. + */ +{ + + /* Copy from SelectDef to Select2Def, transforming along the way. */ + + selTransTo2(transform); + + /* Now just delete the selection and recreate it from Select2Def, + * copying into the edit cell along the way. + */ + + SelectDelete("modified", TRUE); + SelectAndCopy2(EditRootDef); +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectExpand -- + * + * Expand all of the selected cells that are unexpanded, and + * unexpand all of those that are expanded. + * + * Results: + * None. + * + * Side effects: + * The contents of the selected cells will become visible or + * invisible on the display in the indicated window(s). + * + * ---------------------------------------------------------------------------- + */ + +void +SelectExpand(mask) + int mask; /* Bits of this word indicate which + * windows the selected cells will be + * expanded in. + */ +{ + extern int selExpandFunc(); /* Forward reference. */ + + (void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL, + selExpandFunc, (ClientData) mask); +} + + /* ARGSUSED */ +int +selExpandFunc(selUse, use, transform, mask) + CellUse *selUse; /* Use from selection. */ + CellUse *use; /* Use to expand (in actual layout). */ + Transform *transform; /* Not used. */ + int mask; /* Windows in which to expand. */ +{ + /* Don't change expansion status of root cell: screws up + * DBWAreaChanged (need to always have at least top-level + * cell be expanded). + */ + + if (use->cu_parent == NULL) + { + TxError("Can't unexpand root cell of window.\n"); + return 0; + } + + /* Be sure to modify the expansion bit in the selection as well as + * the one in the layout in order to keep them consistent. + */ + + if (DBDescendSubcell(use, mask)) + { + DBExpand(selUse, mask, FALSE); + DBExpand(use, mask, FALSE); + DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, + (TileTypeBitMask *) NULL); + } + else + { + DBExpand(selUse, mask, TRUE); + DBExpand(use, mask, TRUE); + DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, &DBAllButSpaceBits); + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectArray -- + * + * Array everything in the selection. Cells get turned into + * arrays, and paint and labels get replicated. + * + * Results: + * None. + * + * Side effects: + * The edit cell is modified in a big way. It's also redisplayed. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectArray(arrayInfo) + ArrayInfo *arrayInfo; /* Describes desired shape of array, all in + * root coordinates. + */ +{ + extern int selArrayPFunc(), selArrayCFunc(), selArrayLFunc(); + + /* The way arraying is done is similar to moving: make an + * arrayed copy of everything in Select2Def, then delete the + * selection, then copy everything back from Select2Def and + * select it. + */ + + UndoDisable(); + DBCellClearDef(Select2Def); + (void) SelEnumPaint(&DBAllButSpaceAndDRCBits, TRUE, (bool *) NULL, + selArrayPFunc, (ClientData) arrayInfo); + (void) SelEnumCells(TRUE, (bool *) NULL, (SearchContext *) NULL, + selArrayCFunc, (ClientData) arrayInfo); + (void) SelEnumLabels(&DBAllTypeBits, TRUE, (bool *) NULL, + selArrayLFunc, (ClientData) arrayInfo); + DBReComputeBbox(Select2Def); + UndoEnable(); + + /* Now just delete the selection and recreate it from Select2Def, + * copying into the edit cell along the way. + */ + + SelectDelete("arrayed", TRUE); + SelectAndCopy2(EditRootDef); +} + +/* Search function for paint. Just make many copies of the paint + * into Select2Def. Always return 0 to keep the search alive. + */ + +int +selArrayPFunc(rect, type, arrayInfo) + Rect *rect; /* Rectangle to be arrayed. */ + TileType type; /* Type of tile. */ + ArrayInfo *arrayInfo; /* How to array. */ +{ + int y, nx, ny; + Rect current; + + nx = arrayInfo->ar_xhi - arrayInfo->ar_xlo; + if (nx < 0) nx = -nx; + ny = arrayInfo->ar_yhi - arrayInfo->ar_ylo; + if (ny < 0) ny = -ny; + + current = *rect; + for ( ; nx >= 0; nx -= 1) + { + current.r_ybot = rect->r_ybot; + current.r_ytop = rect->r_ytop; + for (y = ny; y >= 0; y -= 1) + { + DBPaint(Select2Def, ¤t, type); + current.r_ybot += arrayInfo->ar_ysep; + current.r_ytop += arrayInfo->ar_ysep; + } + current.r_xbot += arrayInfo->ar_xsep; + current.r_xtop += arrayInfo->ar_xsep; + } + return 0; +} + +/* Search function for cells. Just make an arrayed copy of + * each subcell found. + */ + + /* ARGSUSED */ +int +selArrayCFunc(selUse, use, transform, arrayInfo) + CellUse *selUse; /* Use from selection (not used). */ + CellUse *use; /* Use to be copied and arrayed. */ + Transform *transform; /* Transform from use->cu_def to root. */ + ArrayInfo *arrayInfo; /* Array characteristics desired. */ +{ + CellUse *newUse; + Transform tinv, newTrans; + Rect tmp, oldBbox; + + /* When creating a new use, try to re-use the id from the old + * one. Only create a new one if the old id can't be used. + */ + + newUse = DBCellNewUse(use->cu_def, (char *) use->cu_id); + if (!DBLinkCell(newUse, Select2Def)) + { + freeMagic((char *) newUse->cu_id); + newUse->cu_id = NULL; + (void) DBLinkCell(newUse, Select2Def); + } + newUse->cu_expandMask = use->cu_expandMask; + newUse->cu_flags = use->cu_flags; + + DBSetTrans(newUse, transform); + GeoInvertTrans(transform, &tinv); + DBMakeArray(newUse, &tinv, arrayInfo->ar_xlo, + arrayInfo->ar_ylo, arrayInfo->ar_xhi, arrayInfo->ar_yhi, + arrayInfo->ar_xsep, arrayInfo->ar_ysep); + + /* Set the array's transform so that its lower-left corner is in + * the same place that it used to be. + */ + + GeoInvertTrans(&use->cu_transform, &tinv); + GeoTransRect(&tinv, &use->cu_bbox, &tmp); + GeoTransRect(transform, &tmp, &oldBbox); + GeoTranslateTrans(&newUse->cu_transform, + oldBbox.r_xbot - newUse->cu_bbox.r_xbot, + oldBbox.r_ybot - newUse->cu_bbox.r_ybot, + &newTrans); + DBSetTrans(newUse, &newTrans); + + if (DBCellFindDup(newUse, Select2Def) != NULL) + { + DBUnLinkCell(newUse, Select2Def); + (void) DBCellDeleteUse(newUse); + } + else DBPlaceCell(newUse, Select2Def); + + return 0; +} + +/* Search function for labels. Similar to paint search function. */ +/* modified by harry eaton to increment numbers in array labels */ + + /* ARGSUSED */ +int +selArrayLFunc(label, use, transform, arrayInfo) + Label *label; /* Label to be copied and replicated. */ + CellUse *use; /* (unused) */ + Transform *transform; /* Transform from coords of def to root. */ + ArrayInfo *arrayInfo; /* How to replicate. */ +{ + int y, nx, ny, rootJust, rootRotate; + Point rootOffset; + Rect original, current; + char *astr; + int labx, laby, xi, yi, only1; /* numeric parts of label */ + + char *nmPutNums(); /* Forward reference */ + + nx = arrayInfo->ar_xhi - arrayInfo->ar_xlo; + if (nx < 0) nx = -nx; + ny = arrayInfo->ar_yhi - arrayInfo->ar_ylo; + if (ny < 0) ny = -ny; + + GeoTransRect(transform, &label->lab_rect, &original); + rootJust = GeoTransPos(transform, label->lab_just); + rootRotate = GeoTransAngle(transform, label->lab_rotate); + GeoTransPointDelta(transform, &label->lab_offset, &rootOffset); + current = original; + + /* get the existing numbers in the label */ + nmGetNums(label->lab_text, &labx, &laby); + + xi = yi = 0; + if (nx > 0 && ny > 0) + only1 = 0; + else + only1 = 1; + for ( ; nx >= 0; nx -= 1) + { + current.r_ybot = original.r_ybot; + current.r_ytop = original.r_ytop; + for (y = ny; y >= 0; y -= 1) + { + /* Eliminate any duplicate labels. Don't use type in comparing + * for duplicates, because the selection's type could change + * after it gets added to the edit cell. Any label with + * the same text and position is considered a duplicate. + */ + yi = ny - y; + astr = nmPutNums(label->lab_text, labx + xi, laby + yi); + DBEraseLabelsByContent(Select2Def, ¤t, -1, astr); + DBPutFontLabel(Select2Def, ¤t, label->lab_font, + label->lab_size, rootRotate, &rootOffset, + rootJust, astr, label->lab_type, label->lab_flags); + current.r_ybot += arrayInfo->ar_ysep; + current.r_ytop += arrayInfo->ar_ysep; + xi += only1; + } + xi += (1 - only1); + current.r_xbot += arrayInfo->ar_xsep; + current.r_xtop += arrayInfo->ar_xsep; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * SelectStretch -- + * + * Move the selection a given amount in x (or y). While moving, + * erase everything that the selection passes over, and stretch + * material behind the selection. + * + * Results: + * None. + * + * Side effects: + * The edit cell is modified. The selection is also modified + * and redisplayed. + * ---------------------------------------------------------------------------- + */ + +void +SelectStretch(x, y) + int x; /* Amount to move in the x-direction. */ + int y; /* Amount to move in the y-direction. Must + * be zero if x is non-zero. + */ +{ + Transform transform; + int plane; + Rect modifiedArea, editModified; + extern int selStretchEraseFunc(), selStretchFillFunc(); + /* Forward declarations. */ + + if ((x == 0) && (y == 0)) return; + + /* First of all, copy from SelectDef to Select2Def, moving the + * selection along the way. + */ + + GeoTranslateTrans(&GeoIdentityTransform, x, y, &transform); + selTransTo2(&transform); + + /* We're going to modify not just the old selection area or the new + * one, but everything in-between too. Remember this and tell the + * displayer and DRC about it later. + */ + + modifiedArea = Select2Def->cd_extended; + (void) GeoInclude(&SelectDef->cd_extended, &modifiedArea); + GeoTransRect(&RootToEditTransform, &modifiedArea, &editModified); + + /* Delete the selection itself. */ + + SelectDelete("stretched", TRUE); + + /* Next, delete all the material in front of each piece of paint in + * the selection. + */ + + selStretchX = x; + selStretchY = y; + for (plane = PL_SELECTBASE; plane < DBNumPlanes; plane++) + { + (void) DBSrPaintArea((Tile *) NULL, Select2Def->cd_planes[plane], + &TiPlaneRect, &DBAllButSpaceAndDRCBits, selStretchEraseFunc, + (ClientData) &plane); + } + + /* To achieve the stretch affect, fill in material behind the selection + * everywhere that it used to touch other material in the edit cell. + * This code first builds up a list of areas to paint, then paints them + * (can't paint as we go because the new paint interacts with the + * computation of what to stretch). + */ + + selStretchList = NULL; + for (plane = PL_SELECTBASE; plane < DBNumPlanes; plane++) + { + (void) DBSrPaintArea((Tile *) NULL, Select2Def->cd_planes[plane], + &TiPlaneRect, &DBAllButSpaceAndDRCBits, selStretchFillFunc, + (ClientData) &plane); + } + + /* Paint back the areas in the list. */ + + while (selStretchList != NULL) + { + TileTypeBitMask tmask; + TileType type = selStretchList->sa_type; + + TileType tloc; + tloc = (type & TT_DIAGONAL) ? ((type & TT_SIDE) ? + (type & TT_RIGHTMASK) >> 14 : (type & TT_LEFTMASK)) : type; + TTMaskSetOnlyType(&tmask, tloc); + + DBPaintValid(EditCellUse->cu_def, &selStretchList->sa_area, &tmask, type); + freeMagic((char *) selStretchList); + selStretchList = selStretchList->sa_next; + } + + /* Paint the new translated selection back into the edit cell, + * select it again, and tell DRC and display about what we + * changed. + */ + + SelectAndCopy2(EditRootDef); + DBWAreaChanged(EditCellUse->cu_def, &editModified, DBW_ALLWINDOWS, + (TileTypeBitMask *) NULL); + DRCCheckThis(EditCellUse->cu_def, TT_CHECKPAINT, &editModified); +} + +/* + * ---------------------------------------------------------------------------- + * selStretchEraseFunc -- + * + * Called by DBSrPaintArea during stretching for each tile in the + * new selection. Erase the area that the tile swept out as it + * moved. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * The edit cell is modified. + * ---------------------------------------------------------------------------- + */ + +int +selStretchEraseFunc(tile, plane) + Tile *tile; /* Tile being moved in a stretch operation. */ + int *plane; /* Plane of tiles being searched */ +{ + Rect area, editArea; + int planeNum; + planeAndArea pa; + TileType type, t; + TileTypeBitMask tmpmask, mask, *residueMask; + PaintUndoInfo ui; + PaintResultType selStretchEraseTbl[NT]; + extern int selStretchEraseFunc2(); + + if (IsSplit(tile)) + type = (SplitSide(tile)) ? SplitRightType(tile) : + SplitLeftType(tile); + else + type = TiGetType(tile); + + TiToRect(tile, &area); + + /* Compute the area that this tile swept out (the current area is + * its location AFTER moving), and erase everything that was in + * its path. + */ + + if (selStretchX > 0) + area.r_xbot -= selStretchX; + else area.r_xtop -= selStretchX; + if (selStretchY > 0) + area.r_ybot -= selStretchY; + else area.r_ytop -= selStretchY; + + /* Translate into edit coords and erase all material on the + * tile's plane. + */ + + GeoTransRect(&RootToEditTransform, &area, &editArea); + + /* We need to erase all types that interact with "type", *not* all */ + /* types on "plane", due to the way stacked contacts are handled. */ + /* Contacts on different planes may stretch across one another */ + /* without effect, if the types are stackable. Likewise, layer */ + /* types may stretch across contacts for which they are a residue. */ + + planeNum = *plane; + mask = DBPlaneTypes[planeNum]; + if (DBIsContact(type)) + { + for (t = DBNumUserLayers; t < DBNumTypes; t++) + { + if (t == type) continue; + + /* Exclude all contact types for which this type should "pass through" */ + + if (TTMaskHasType(&mask, t)) + { + tmpmask = *DBResidueMask(t); + if (TTMaskHasType(&tmpmask, type)) + { + TTMaskClearType(&tmpmask, type); + TTMaskClearMask(&mask, &tmpmask); + } + } + } + } + + /* For stacked type tiles do not erase common residue + * type of both contacts from layout. + */ + + if (type >= DBNumUserLayers) + { + t = (DBPlaneToResidue(type, planeNum)); + TTMaskClearType(&mask, t); + } + + TTMaskAndMask(&mask, &DBActiveLayerBits); + + /* Erase all tile types specified in the processed mask. + * Erase contacts in mask first using DBErase. This prevents + * contacts from leaving partial images of themselves on other + * planes. Then, remove the non-contact layers on this plane + * only, such that contacts are not disturbed. + */ + + TTMaskZero(&tmpmask); + + selStretchEraseTbl[TT_SPACE] = (PaintResultType)TT_SPACE; + for (t = TT_SPACE + 1; t < DBNumUserLayers; t++) + { + selStretchEraseTbl[t] = (PaintResultType)t; + if (TTMaskHasType(&mask, t)) + { + if (DBIsContact(t)) + { + if (t == type) + DBErase(EditCellUse->cu_def, &editArea, t); + else + TTMaskSetType(&tmpmask, t); + } + else + selStretchEraseTbl[t] = (PaintResultType)TT_SPACE; + } + } + for (; t < DBNumTypes; t++) + selStretchEraseTbl[t] = (PaintResultType)t; + + /* Remove conflicting contact types, where they exist */ + + pa.pa_area = &editArea; + pa.pa_plane = planeNum; + pa.pa_mask = &tmpmask; + DBSrPaintArea((Tile *)NULL, EditCellUse->cu_def->cd_planes[planeNum], + &editArea, &tmpmask, selStretchEraseFunc2, (ClientData)&pa); + + ui.pu_pNum = planeNum; + ui.pu_def = EditCellUse->cu_def; + DBPaintPlane(EditCellUse->cu_def->cd_planes[planeNum], &editArea, + selStretchEraseTbl, &ui); + + return 0; +} + +int +selStretchEraseFunc2(tile, pa) + Tile *tile; + planeAndArea *pa; +{ + if (IsSplit(tile)) + { + if (TTMaskHasType(pa->pa_mask, TiGetLeftType(tile))) + DBErase(EditCellUse->cu_def, pa->pa_area, + DBPlaneToResidue(TiGetLeftType(tile), pa->pa_plane)); + if (TTMaskHasType(pa->pa_mask, TiGetRightType(tile))) + DBErase(EditCellUse->cu_def, pa->pa_area, + DBPlaneToResidue(TiGetRightType(tile), pa->pa_plane)); + } + else + DBErase(EditCellUse->cu_def, pa->pa_area, + DBPlaneToResidue(TiGetType(tile), pa->pa_plane)); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * selStretchFillFunc -- + * + * This function is invoked during stretching for each paint tile in + * the (new) selection. It finds places in where the back-side of this + * tile borders space in the (new) selection, then looks for paint in + * the edit cell that borders the old location of the paint. If the + * selection has been moved away from paint in the edit cell, additional + * material is filled in behind the selection. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Modifies the edit cell by painting material. + * ---------------------------------------------------------------------------- + */ + +int +selStretchFillFunc(tile, plane) + Tile *tile; /* Tile in the old selection. */ + int *plane; /* Plane of tile being searched */ +{ + Rect area; + extern int selStretchFillFunc2(); + + TiToRect(tile, &area); + + /* Check the material just behind this paint (in the sense of the + * stretch direction) for space in the selection and non-space in + * the edit cell. + */ + + if (selStretchX > 0) + { + area.r_xtop = area.r_xbot; + area.r_xbot -= 1; + } + else if (selStretchX < 0) + { + area.r_xbot = area.r_xtop; + area.r_xtop += 1; + } + else if (selStretchY > 0) + { + area.r_ytop = area.r_ybot; + area.r_ybot -= 1; + } + else + { + area.r_ybot = area.r_ytop; + area.r_ytop += 1; + } + + if (IsSplit(tile)) + { + if (selStretchX > 0) + selStretchType = SplitLeftType(tile); + else if (selStretchX < 0) + selStretchType = SplitRightType(tile); + else if (selStretchY > 0) + selStretchType = (SplitDirection(tile) ? SplitLeftType(tile) : + SplitRightType(tile)); + else if (selStretchY < 0) + selStretchType = (SplitDirection(tile) ? SplitRightType(tile) : + SplitLeftType(tile)); + if (selStretchType == TT_SPACE) return 0; + } + else + selStretchType = TiGetType(tile); + + /* The search functions invoked indirectly by the following procedure + * call build up a list of areas to paint. + */ + + (void) DBSrPaintArea((Tile *) NULL, + Select2Def->cd_planes[*plane], &area, + &DBSpaceBits, selStretchFillFunc2, (ClientData) &area); + + return 0; +} + +/* Second-level filling search function: find all of the edit material + * that intersects areas where space borders a selected paint tile. + */ + +int +selStretchFillFunc2(tile, area) + Tile *tile; /* Space tile that borders selected + * paint. + */ + Rect *area; /* A one-unit wide strip along the + * border (i.e. the area in which + * we're interested in space). + */ +{ + Rect spaceArea, editArea; + int pNum; + + extern int selStretchFillFunc3(); + + TiToRect(tile, &spaceArea); + + /* Find out which portion of this space tile borders the selected + * tile, transform it back to coords of the old selection and then + * to edit coords, and find all the edit material that borders the + * selected tile in this area. + */ + + GeoClip(&spaceArea, area); + spaceArea.r_xbot -= selStretchX; + spaceArea.r_xtop -= selStretchX; + spaceArea.r_ybot -= selStretchY; + spaceArea.r_ytop -= selStretchY; + GeoTransRect(&RootToEditTransform, &spaceArea, &editArea); + + for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) + { + if (DBTypeOnPlane(selStretchType, pNum)) + (void) DBSrPaintArea((Tile *) NULL, + EditCellUse->cu_def->cd_planes[pNum], + &editArea, &DBActiveLayerBits, selStretchFillFunc3, + (ClientData) &spaceArea); + } + return 0; +} + +/* OK, now we've found a piece of material in the edit cell that is + * right next to a piece of selected material that's about to move + * away from it. Stretch one or the other to fill the gap. Use the + * material that's moving as the stretch material unless it's a fixed-size + * material and the other stuff is stretchable. + */ + +int +selStretchFillFunc3(tile, area) + Tile *tile; /* Tile of edit material that's about to + * be left behind selection. + */ + Rect *area; /* The border area we're interested in, + * in root coords. + */ +{ + Rect editArea, rootArea; + TileType type, stype; + TileTypeBitMask *mask, *sMask, *tMask; + StretchArea *sa; + + /* Compute the area to be painted. */ + + TiToRect(tile, &editArea); + GeoTransRect(&EditToRootTransform, &editArea, &rootArea); + GeoClip(&rootArea, area); + if (selStretchX > 0) + { + rootArea.r_xbot = rootArea.r_xtop; + rootArea.r_xtop += selStretchX; + } + else if (selStretchX < 0) + { + rootArea.r_xtop = rootArea.r_xbot; + rootArea.r_xbot += selStretchX; + } + else if (selStretchY > 0) + { + rootArea.r_ybot = rootArea.r_ytop; + rootArea.r_ytop += selStretchY; + } + else + { + rootArea.r_ytop = rootArea.r_ybot; + rootArea.r_ybot += selStretchY; + } + GeoTransRect(&RootToEditTransform, &rootArea, &editArea); + + /* Compute the material to be painted. Be careful: for contacts, + * must use the master image. + */ + + if (IsSplit(tile)) + { + if (selStretchX > 0) + type = SplitRightType(tile); + else if (selStretchX < 0) + type = SplitLeftType(tile); + else if (selStretchY > 0) + type = (SplitDirection(tile) ? SplitRightType(tile) : + SplitLeftType(tile)); + else if (selStretchY < 0) + type = (SplitDirection(tile) ? SplitLeftType(tile) : + SplitRightType(tile)); + if (type == TT_SPACE) return 0; /* nothing to stretch */ + } + else + type = TiGetType(tile); + sMask = DBResidueMask(selStretchType); + + /* If have type and stretch type are both contacts (fixed types) */ + /* and there exists a stacking contact type between them, then */ + /* we should be filling in the original type. */ + + if (!DBIsContact(type) || !DBIsContact(selStretchType) || + (((stype = DBTechFindStacking(type, selStretchType)) + < DBNumUserLayers) && (stype >= TT_TECHDEPBASE))) + { + /* If type is a residue of selStretchType then we always */ + /* fill with type. Otherwise, we check the list of plow */ + /* types to see what is and isn't fixed. */ + + if (!TTMaskHasType(sMask, type)) + if (TTMaskHasType(&PlowFixedTypes, type) + || !TTMaskHasType(&PlowFixedTypes, selStretchType)) + type = selStretchType; + } + + /* Otherwise, if we have two fixed types, and they both border the */ + /* selection area (as opposed to overlapping), and they share a */ + /* residue, then the type to paint is the shared residue type. */ + /* We must ignore the case type == selStretchType (fixed by Nishit, */ + /* 6/29/04. */ + + else if (DBIsContact(type) && DBIsContact(selStretchType) + && (type != selStretchType)) + { + if (((selStretchX < 0) && (editArea.r_xtop == area->r_xbot)) || + ((selStretchX > 0) && (editArea.r_xbot == area->r_xtop)) || + ((selStretchY < 0) && (editArea.r_ytop == area->r_ybot)) || + ((selStretchY > 0) && (editArea.r_ybot == area->r_ytop))) + { + TileTypeBitMask rmask; + tMask = DBResidueMask(type); + TTMaskAndMask3(&rmask, tMask, sMask); + for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++) + if (TTMaskHasType(&rmask, type)) + break; + + if (type == DBNumUserLayers) + return 0; /* Types do not share any residues */ + } + } + + /* Save around the area we just found. */ + + sa = (StretchArea *) mallocMagic(sizeof(StretchArea)); + sa->sa_area = editArea; + sa->sa_type = type; + sa->sa_next = selStretchList; + selStretchList = sa; + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectDump -- + * + * Copies an area of one cell into the edit cell, selecting the + * copy so that it can be manipulated later. + * + * Results: + * None. + * + * Side effects: + * The edit cell is modified. + * + * ---------------------------------------------------------------------------- + */ + +void +SelectDump(scx) + SearchContext *scx; /* Describes the cell from which + * material is to be copied, the + * area to copy, and the transform + * to root coordinates in the edit + * cell's window. + */ +{ + /* Copy from the source cell to Select2Def while transforming, + * then let SelectandCopy2 do the rest of the work. Don't + * record any of the Select2Def changes for undo-ing. + */ + + UndoDisable(); + DBCellClearDef(Select2Def); + (void) DBCellCopyAllPaint(scx, &DBAllButSpaceAndDRCBits, CU_DESCEND_SPECIAL, + Select2Use); + (void) DBCellCopyAllLabels(scx, &DBAllTypeBits, CU_DESCEND_SPECIAL, Select2Use, + (Rect *) NULL); + (void) DBCellCopyAllCells(scx, CU_DESCEND_SPECIAL, Select2Use, (Rect *) NULL); + DBReComputeBbox(Select2Def); + UndoEnable(); + + SelectClear(); + SelectAndCopy2(EditRootDef); +} diff --git a/select/selUndo.c b/select/selUndo.c new file mode 100644 index 00000000..d0350498 --- /dev/null +++ b/select/selUndo.c @@ -0,0 +1,451 @@ +/* selUndo.c - + * + * This file provides routines for undo-ing and redo-ing the + * the selection. Most of the undo-ing is handled automatically + * by enabling undo-ing when the selection cell is modified. + * All this file does is record things to be redisplayed, since + * the normal undo package won't handle that. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/select/selUndo.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "dbwind/dbwind.h" +#include "utils/undo.h" +#include "commands/commands.h" +#include "textio/textio.h" +#include "select/select.h" +#include "select/selInt.h" + +/* Each selection modification causes two records of the following + * format to be added to the undo event list. The first record + * is added BEFORE the modification (sue_before is TRUE), and the + * second is added afterwards. The reason for doubling the events + * is that we can't redisplay selection information until after the + * selection has been modified. This requires events to be in + * different places depending on whether we're undo-ing or redo-ing. + */ + +typedef struct +{ + CellDef *sue_def; /* Definition in which selection must be + * redisplayed. + */ + Rect sue_area; /* Area of sue_def in which selection info + * must be redisplayed. + */ + bool sue_before; /* TRUE means this entry was made before + * the selection modifications. FALSE + * means afterwards. + */ +} SelUndoEvent; + +/* Identifier for selection undo records: */ + +UndoType SelUndoClientID; + +/* Network selection differs from other selection modes in two fundamental + * ways: 1) it is almost always done for informational purposes (that is, + * one does not usually copy, move, or stretch the entire network), and + * 2) it usually involves a LOT of tiles. Consequently, it makes sense + * to define a separate "undo" operation for net selection, in which only + * the information needed to reconstruct the event is retained. This + * eliminates the worst problem with selections (as previously handled + * by the SelUndoClient, above), in which querying the power or ground + * network of a large chip gobbles vast amount of memory as magic + * remembers every single tile paint operation. This memory is kept + * "forever" (at least as far as the undo stack depth, which is pretty + * large), and so continued queries on large networks quickly fills up + * memory. SelUndoNetClient is a much more efficient way to handle + * the problem. Although the "undo" command takes time to regenerate + * the network from scratch, use of "undo" on network selections is + * actually rather rare in practice, and the memory savings far outweighs + * the difference in time to regenerate the net. Eliminating the need + * to malloc and fill giant chunks of memory reduces the time required to + * select the network, anyway. + * + * SelUndoNetClient method added by Nishit, July 7-9, 2004 + */ + +typedef struct +{ + CellDef *sue_def; /* Definition in which net selection + * must be redisplayed + */ + Point sue_startpoint; /* One valid coordinate for the net, to + * use as the startpoint for net regeneration + */ + TileType sue_type; /* Type of tile; in conjunction with the + * startpoint, uniquely identifies the net. + */ + bool sue_less; /* value of "less" passed to SelectNet */ + bool sue_before; /* TRUE means this entry was made before + * the net selection. FALSE means it was + * made afterwards. + */ +} SelUndoNetEvent; + +/* Identifier for network selection undo records */ + +UndoType SelUndoNetClientID; + + +/* + * ---------------------------------------------------------------------------- + * + * SelUndoInit -- + * + * Adds us as a client to the undo package. + * + * Results: + * None. + * + * Side effects: + * Adds a new client to the undo package, and sets SelUndoClientID. + * + * ---------------------------------------------------------------------------- + */ + +void +SelUndoInit() +{ + extern void SelUndoForw(), SelUndoBack(); + extern void SelUndoNetForw(), SelUndoNetBack(); + + SelUndoClientID = UndoAddClient((void (*)()) NULL, (void (*)()) NULL, + (UndoEvent *(*)()) NULL, (int (*)()) NULL, SelUndoForw, + SelUndoBack, "selection"); + + if (SelUndoClientID < (UndoType) 0) + TxError("Couldn't add selection as an undo client!\n"); + + /* Special undo client for net selection (Nishit, July 8, 2004) */ + SelUndoNetClientID = UndoAddClient((void (*)()) NULL, (void (*)()) NULL, + (UndoEvent *(*)()) NULL, (int (*)()) NULL, SelUndoNetForw, + SelUndoNetBack, "net selection"); + + if (SelUndoNetClientID < (UndoType) 0) + TxError("Couldn't add net selection as an undo client!\n"); +} + +/* + * ---------------------------------------------------------------------------- + * + * SelRememberForUndo-- + * + * This routine is called twice whenever the selection is modified. + * It must be called once before modifying the selection. In this + * case before is TRUE and the other arguments are arbitrary. It + * must also be called again after the selection is modified. In + * this case before is FALSE and the other fields indicate exactly + * which area was modified. + * + * Results: + * None. + * + * Side effects: + * Adds information to the undo list. + * + * ---------------------------------------------------------------------------- + */ + +void +SelRememberForUndo(before, def, area) + bool before; /* TRUE means caller is about to modify + * the given area of the selection. FALSE + * means the caller has just modified + * the area. + */ + CellDef *def; /* Root definition on top of whom selection + * information was just modified. + */ + Rect *area; /* The area of def where selection info + * changed. This pointer may be NULL, even + * on the second call, if there's no need + * to do redisplay during undo's. This is + * the case if layout information is being + * modified over the area of the selection: + * when layout is redisplayed, selection info + * will automatically be redisplayed too. + */ +{ + SelUndoEvent *sue; + static SelUndoEvent *beforeEvent = NULL; + static Rect nullRect = {0, 0, -1, -1}; + + sue = (SelUndoEvent *) UndoNewEvent(SelUndoClientID, sizeof(SelUndoEvent)); + if (sue == NULL) return; + + /* We don't have complete information when the "before" event is + * created, so save around its address and fill in the event when + * the "after" event is created. + */ + + if (before) + { + sue->sue_before = TRUE; + sue->sue_def = NULL; + + beforeEvent = sue; + } + else + { + if (area == NULL) area = &nullRect; + sue->sue_def = def; + sue->sue_area = *area; + sue->sue_before = before; + + beforeEvent->sue_def = def; + beforeEvent->sue_area = *area; + beforeEvent = NULL; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * SelUndoForw -- + * SelUndoBack -- + * + * Called to process undo redisplay events. The two procedures + * are identical except that each one looks at different events. + * The idea is to do the selection redisplay only AFTER the selection + * has actually been modified. + * + * Results: + * None. + * + * Side effects: + * Highlights (including the selection) are redisplayed. + * + * ---------------------------------------------------------------------------- + */ + +void +SelUndoForw(sue) + SelUndoEvent *sue; /* Event to be redone. */ +{ + if (sue->sue_before) return; + if (sue->sue_def == NULL) return; + SelSetDisplay(SelectUse, sue->sue_def); + SelectRootDef = sue->sue_def; + DBReComputeBbox(SelectDef); + if (sue->sue_area.r_xbot <= sue->sue_area.r_xtop) + DBWHLRedraw(sue->sue_def, &sue->sue_area, TRUE); + DBWAreaChanged(SelectDef, &sue->sue_area, DBW_ALLWINDOWS, + (TileTypeBitMask *) NULL); +} + +void +SelUndoBack(sue) + SelUndoEvent *sue; /* Event to be undone. */ +{ + if (!sue->sue_before) return; + if (sue->sue_def == NULL) return; + SelSetDisplay(SelectUse, sue->sue_def); + SelectRootDef = sue->sue_def; + DBReComputeBbox(SelectDef); + if (sue->sue_area.r_xbot <= sue->sue_area.r_xtop) + DBWHLRedraw(sue->sue_def, &sue->sue_area, TRUE); + DBWAreaChanged(SelectDef, &sue->sue_area, DBW_ALLWINDOWS, + (TileTypeBitMask *) NULL); +} + + +/* BY NP */ +/* The following methods are created for Net selection undo/redo-ing. */ + +/* + * ---------------------------------------------------------------------------- + * + * SelNetRememberForUndo-- + * + * This routine is called once whenever a net selection is created. + * It is called once before the modifications (with "before" TRUE) + * and once afterward ("before" FALSE). In the second case, + * arguments (def, startpoint, type, and less) are ignored. + * + * This routine is called from within a routine (SelectNet) that + * is invoked by the undo mechanism. To avoid corrupting the undo + * stack records, return immediately if selections have been disabled. + * + * Results: + * None. + * + * Side effects: + * Adds information to the undo list. + * + * ---------------------------------------------------------------------------- + */ +void +SelNetRememberForUndo(def, startpoint, type, less, before) + CellDef *def; /* Root definition on top of which selection + * information was just modified. + */ + Point *startpoint; /* Starting point, from where we start + * selecting the network. + */ + TileType type; /* Tile type that uniquely identifies the + * network node at the above startpoint. + */ + bool less; /* Value of "less" passed to SelectNet */ + bool before; /* Does this mark the beginning or end + * of the net selection. + */ +{ + static SelUndoNetEvent *beforeEvent = NULL; + SelUndoNetEvent *sue; + + if (!UndoIsEnabled()) return; + + sue = (SelUndoNetEvent *) UndoNewEvent(SelUndoNetClientID, + sizeof(SelUndoNetEvent)); + if (sue == NULL) return; + + if (before) + { + sue->sue_before = TRUE; + sue->sue_def = def; + sue->sue_startpoint = *startpoint; + sue->sue_less = less; + sue->sue_type = type; + + ASSERT(beforeEvent == NULL, "Forgot to call SelRememberForUndo after"); + beforeEvent = sue; + } + else + { + sue->sue_before = FALSE; + ASSERT(beforeEvent != NULL, "Forgot to call SelRememberForUndo before"); + + sue->sue_def = beforeEvent->sue_def; + sue->sue_startpoint = beforeEvent->sue_startpoint; + sue->sue_less = beforeEvent->sue_less; + sue->sue_type = beforeEvent->sue_type; + + /* Don't set to NULL; it is possible to run through */ + /* this code twice in a row if we "undo" back to, but */ + /* not over, the SelectNet record, and then start */ + /* again. beforeEvent will still be pointing to the */ + /* correct event. */ + /* beforeEvent = NULL; */ + } +} + +/* + * ---------------------------------------------------------------------------- + * + * SelUndoCreateNet -- + * + * ---------------------------------------------------------------------------- + */ + +void +SelUndoCreateNet(sue) + SelUndoNetEvent *sue; /* Event description */ +{ + SearchContext scx; + DBWclientRec *crec; + MagWindow *window; + + scx.scx_area.r_xbot = sue->sue_startpoint.p_x; + scx.scx_area.r_ybot = sue->sue_startpoint.p_y; + scx.scx_area.r_xtop = scx.scx_area.r_xbot + 1; + scx.scx_area.r_ytop = scx.scx_area.r_ybot + 1; + + // window = CmdGetRootPoint((Point *) NULL, &scx.scx_area); + + window = CmdGetRootPoint((Point *) NULL, (Rect *) NULL); + if (window == NULL) return; + scx.scx_use = (CellUse *) window->w_surfaceID; + scx.scx_trans = GeoIdentityTransform; + crec = (DBWclientRec *) window->w_clientData; + + UndoDisable(); + SelectClear(); // Selection should already be clear at this point. + SelectNet(&scx, sue->sue_type, crec->dbw_bitmask, (Rect *) NULL, + sue->sue_less); + UndoEnable(); +} + +/* + * ---------------------------------------------------------------------------- + * + * SelUndoDestroyNet -- + * + * ---------------------------------------------------------------------------- + */ + +void +SelUndoDestroyNet() +{ + UndoDisable(); + SelectClear(); + UndoEnable(); +} + +/* + * ---------------------------------------------------------------------------- + * + * SelUndoNetForw -- + * SelUndoNetBack -- + * + * Called to process redo(undo) redisplay events. These routines + * are symmetric: SelUndoNetForw creates the net on a "before" + * event and erases it on an "after" event. SelUndoNetBack erases + * the net on a "before" event and creates it on an "after" event. + * + * Results: + * None. + * + * Side effects: + * Highlights (including the selection) are redisplayed. + * + * ---------------------------------------------------------------------------- + */ + +void +SelUndoNetForw(sue) + SelUndoNetEvent *sue; /* Event to be redone. */ +{ + if (sue->sue_def == NULL) return; + + if (sue->sue_before) + SelUndoCreateNet(sue); + else + SelUndoDestroyNet(); +} + +void +SelUndoNetBack(sue) + SelUndoNetEvent *sue; /* Event to be redone. */ +{ + if (sue->sue_def == NULL) return; + + if (sue->sue_before) + SelUndoDestroyNet(); + else + SelUndoCreateNet(sue); +} diff --git a/select/selUnselect.c b/select/selUnselect.c new file mode 100644 index 00000000..1656507d --- /dev/null +++ b/select/selUnselect.c @@ -0,0 +1,414 @@ +/* + * selUnselect.c -- + * + * the program you can't see in your mirror. And why + * does it only come around after dark? + * + */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "commands/commands.h" +#include "utils/main.h" +#include "select/select.h" +#include "select/selInt.h" +#include "utils/malloc.h" +#include "textio/textio.h" + + +/* + * ---------------------------------------------------------------------------- + * + * selUnselFunc -- + * + * This function is used by SelRemoveSel2; it is passed to DBSrPaintArea as + * the search function for a search of the select2 cell, and erases + * equivalent areas of paint in the select cell (in effect, it deletes + * the contents of select2 from select). + * + * Results: + * Always returns zero (so the search will continue). + * + * Side effects: + * Paint is removed from the select cell. + * + * ---------------------------------------------------------------------------- + */ + +int +selUnselFunc(tile, arg) + Tile *tile; + ClientData *arg; +{ + TileType type; + Rect rect; + + if ((type = TiGetType(tile)) >= DBNumUserLayers) return 0; + TiToRect(tile, &rect); + DBErase(SelectDef, &rect, type); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * selRemoveCellFunc -- + * + * This procedure hides some (limited number of) cell uses for later + * munging; it is a search procedure for DBCellSrArea. + * + * Results: + * Always aborts array enumeration (we only need one placement in order + * to rip out the whole array). Aborts the search once MAXUNSELUSES + * cell uses have been hidden away. + * + * Side effects: + * Cell uses are entered in the array selRemoveUses; the variable + * selNRemove is incremented. + * + * ---------------------------------------------------------------------------- + */ + +#define MAXUNSELUSES 3 +static CellUse *(selRemoveUses[MAXUNSELUSES]); +static int selNRemove; + +int +selRemoveCellFunc(scx, cdarg) + SearchContext *scx; + Rect *cdarg; + +{ + ASSERT((selNRemove < MAXUNSELUSES) && (selNRemove >= 0), + "selRemoveCellFunc(selNRemove)"); + selRemoveUses[selNRemove] = scx->scx_use; + GeoIncludeAll(&scx->scx_use->cu_bbox, cdarg); + if (++selNRemove >= MAXUNSELUSES) return 1; + else return 2; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelRemoveArea -- + * + * Remove a rectangular chunk of the select cell, possibly masked + * by a user-specified mask (which may include the pseudo-levels + * L_CELL and L_LABEL). + * + * Results: + * None. + * + * Side effects: + * Paint, labels, and/or cell uses may be removed from the select cell. + * The selection highlights are redrawn, and undo checkpoints are saved, + * so this thrilling process may be undone or redone. The select cell's + * bounding box is updated. + * + * ---------------------------------------------------------------------------- + */ + +void +SelRemoveArea(area, mask) + Rect *area; + TileTypeBitMask *mask; +{ + SearchContext scx; + Rect bbox, areaReturn; + + /* get ready; save checkpoint for undo. */ + + SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL); + + /* defenestrate a few labels. Do this before the paint, or */ + /* we will not have a proper calculation of the bounding box */ + /* of the erasure for rendered text. */ + + areaReturn = *area; + if (TTMaskHasType(mask, L_LABEL)) + DBEraseLabel(SelectDef, area, &DBAllTypeBits, &areaReturn); + else + DBEraseLabel(SelectDef, area, mask, &areaReturn); + + /* erase ordinary paint in area */ + + DBEraseMask(SelectDef, area, mask); + + /* now blast away at cells; we do this a tiny bit at a time, as in + selectClear. We search, and remember up to MAXUNSELUSES cell + placements in each search; then we rip out those placements, and + search further. As always, thou shalt not rip out what thou + searchest, or thine database shall be corrupt, and thy name + anathema in the ears of thy mask designers. */ + + bbox = *area; + if (TTMaskHasType(mask, L_CELL)) + { + scx.scx_use = SelectUse; + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = *area; + while (TRUE) + { + int i; + + selNRemove = 0; + (void) DBCellSrArea(&scx, selRemoveCellFunc, (ClientData) &bbox); + for (i = 0; i < selNRemove; i++) + { + if (selectLastUse == selRemoveUses[i]) + selectLastUse = (CellUse *) NULL; + DBUnLinkCell(selRemoveUses[i], SelectDef); + DBDeleteCell(selRemoveUses[i]); + (void) DBCellDeleteUse(selRemoveUses[i]); + } + if (selNRemove < MAXUNSELUSES) break; + } + } + + /* now remember stuff for redo (and fill in info for undo), redraw highlights, + recompute the bounding box on the off chance it has changed, tell the + database we've mucked around with the select cell, then go home. */ + + SelRememberForUndo(FALSE, SelectRootDef, &bbox); + GeoInclude(&areaReturn, &bbox); + DBWHLRedraw(SelectRootDef, &bbox, TRUE); + DBReComputeBbox(SelectDef); + DBWAreaChanged(SelectDef, &bbox, DBW_ALLWINDOWS, (TileTypeBitMask *) NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * selRemoveLabelPaintFunc -- + * + * Put labels in the select2 cell. The SelRemoveSel2 function runs through + * all the labels in the select cell, and calls DBSrPaintArea on select2 for + * each one. If there is (suitable) paint in select2 under the label, this + * function gets called, and places the label in select2. + * + * Results: + * Always returns one (and thus aborts the search). + * + * Side effects: + * Labels may appear in select2. + * + * ---------------------------------------------------------------------------- + */ + +int +selRemoveLabelPaintFunc(tile, label) + Tile *tile; + Label *label; +{ + (void) DBPutFontLabel(Select2Def, &label->lab_rect, label->lab_font, + label->lab_size, label->lab_rotate, &label->lab_offset, + label->lab_just, label->lab_text, label->lab_type, + label->lab_flags); + + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelRemoveSel2 -- + * Run through the select2 cell, removing corresponding paint and labels + * from the select cell. + * + * Results: + * Should always return zero; returns 1 if there is a problem traversing + * select2. + * + * Side effects: + * Paint and labels (but not cell uses) may be deleted from the select + * cell. The calling procedure is responsible for updating highlighting + * and undo information. + * + * Labels may be placed in the select2 cell; SelRemoveSel2 assumes that + * there are no labels in select2 when it is called. + * + * ---------------------------------------------------------------------------- + */ + +int +SelRemoveSel2() + +{ + int plane; + Label *label; + + /* Enumerate paint tiles in select2; selUnselFunc will erase corresponding + pieces in the select cell. */ + + for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++) + { + if (DBSrPaintArea((Tile *) NULL, Select2Def->cd_planes[plane], + &TiPlaneRect, &DBAllButSpaceAndDRCBits, selUnselFunc, + (ClientData) NULL) != 0) + return 1; + } + + /* Enumerate labels in select; selRemoveLabelPaintFunc will place a copy of + the label in select2 if it finds appropriate paint underneath the label. */ + + ASSERT(Select2Def->cd_labels == (Label *) NULL, "SelRemoveSel2 labels"); + + for (label = SelectDef->cd_labels; + label != (Label *) NULL; + label = label->lab_next) + { + Rect area, searchArea; + + if (label->lab_type == TT_SPACE) continue; + area = label->lab_rect; + GEO_EXPAND(&area, 1, &searchArea); + (void) DBSrPaintArea((Tile *) NULL, + Select2Def->cd_planes[DBPlane(label->lab_type)], + &searchArea, &DBConnectTbl[label->lab_type], + selRemoveLabelPaintFunc, + (ClientData) label); + } + + /* Now run through the labels we just copied, and delete them from + the select cell. */ + + for (label = Select2Def->cd_labels; + label != (Label *) NULL; + label = label->lab_next) + DBEraseLabelsByContent(SelectDef, &label->lab_rect, -1, label->lab_text); + return 0; +} + +typedef struct +{ + CellUse *ed_use, *sel_use; + Transform *orient; +} SelRemoveCellArgs; + +/* + * ---------------------------------------------------------------------------- + * + * SelRemoveCellSearchFunc -- + * find the cell use in the select cell which matches a given + * cell use in the root def. + * + * Results: + * Returns 1 to abort the search if it finds a match. Otherwise + * returns zero. + * + * Side effects: + * fills in the sel_use field of its client argument if it finds a match. + * + * ---------------------------------------------------------------------------- + */ + +int +SelRemoveCellSearchFunc(scx, cdarg) + SearchContext *scx; + SelRemoveCellArgs *cdarg; +{ + Transform *et, *st; + + /* To match, cell uses must point to the same cell def. */ + + if (scx->scx_use->cu_def != cdarg->ed_use->cu_def) + return 0; + + /* If these usages are in the same orientation, at the same + location, they match. To check this, we compare the + search context transformation with the transformation + computed earlier for the usage in the edit cell. */ + + st = &scx->scx_trans; + et = cdarg->orient; + if ((st->t_a == et->t_a) && + (st->t_b == et->t_b) && + (st->t_c == et->t_c) && + (st->t_d == et->t_d) && + (st->t_e == et->t_e) && + (st->t_f == et->t_f)) + { + cdarg->sel_use = scx->scx_use; + return 1; + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * SelectRemoveCellUse -- + * remove the cell use in the select cell which matches the given + * use from the root def. + * + * Results: + * Returns 1 if no such use was found; returns zero otherwise. + * + * Side effects: + * If SelectRemoveCellUse returns 1, there are no side effects. + * Otherwise: undo/redo markers will be created, one cell use + * will be deleted from the select cell, the select cell's bounding + * box will be recomputed, the highlights redrawn, and the area + * which had been covered by the cell use will be marked as + * changed. If selectLastUse was pointing to the use, it will + * be set to NULL, so the select cycling code will not try + * to deselect this (now trashed) cell use. + * + * ---------------------------------------------------------------------------- + */ + +int +SelectRemoveCellUse(use, trans) + CellUse *use; + Transform *trans; + +{ + SearchContext scx; + CellUse selectedUse; + SelRemoveCellArgs args; + + /* The search context is the area covered by the cell's bounding box in + the select cell. */ + + scx.scx_use = SelectUse; + GEOTRANSRECT(trans, &use->cu_def->cd_bbox, &scx.scx_area); + scx.scx_trans = GeoIdentityTransform; + args.ed_use = use; + args.orient = trans; + + /* DBCellSrArea will return all of the cells overlapping this box; + often, this is just one cell. If the search runs to completion + (is not aborted), we did not find a match, so we quit, returning + 1 as a failure indication. */ + + if (DBCellSrArea(&scx, SelRemoveCellSearchFunc, (ClientData) &args) == 0) + return 1; + + /* remunge the selectLastUse Horrid Side Effect Pointer */ + + if (selectLastUse == args.sel_use) + selectLastUse = (CellUse *) NULL; + + /* Now remove the cell use (with appropriate undo and database + incantations). */ + + SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL); + DBUnLinkCell(args.sel_use, SelectDef); + DBDeleteCell(args.sel_use); + (void) DBCellDeleteUse(args.sel_use); + SelRememberForUndo(FALSE, SelectRootDef, &scx.scx_area); + DBWHLRedraw(SelectRootDef, &scx.scx_area, TRUE); + DBReComputeBbox(SelectDef); + DBWAreaChanged(SelectDef, &scx.scx_area, + DBW_ALLWINDOWS, (TileTypeBitMask *) NULL); + return 0; +} + diff --git a/select/select.h b/select/select.h new file mode 100644 index 00000000..82f73248 --- /dev/null +++ b/select/select.h @@ -0,0 +1,68 @@ +/* + * select.h -- + * + * Contains definitions for things that are exported by the + * selection module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid="$Header: /usr/cvsroot/magic-8.0/select/select.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + */ + +#ifndef _SELECT_H +#define _SELECT_H + +#include "utils/magic.h" +#include "database/database.h" + +/* Procedures to modify the selection. */ + +extern void SelectArea(); +extern void SelectChunk(); +extern void SelectNet(); +extern void SelectRegion(); +extern void SelectInit(); +extern void SelectClear(); +extern void SelectCell(); +extern void SelRemoveArea(); +extern int SelRemoveSel2(); +extern int SelectRemoveCellUse(); +extern ExtRectList *SelectShort(); + +/* Procedures to enumerate what's in the selection. */ + +extern int SelEnumPaint(); +extern int SelEnumCells(); +extern int SelEnumLabels(); + +/* Procedures to operate on the selection. */ + +extern void SelectDelete(); +extern void SelectCopy(); +extern void SelectTransform(); +extern void SelectExpand(); +extern void SelectStretch(); +extern void SelectArray(); +extern void SelectDump(); + +/* The following is the root cell that contains the current selection. */ + +extern CellDef *SelectRootDef; + +/* The dummy cell that actually holds the selection: */ + +extern CellDef *SelectDef; +extern CellUse *SelectUse; + +#endif /* _SELECT_H */ diff --git a/sim/Depend b/sim/Depend new file mode 100644 index 00000000..c3a6cbf8 --- /dev/null +++ b/sim/Depend @@ -0,0 +1,19 @@ +SimDBstuff.o: SimDBstuff.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../database/databaseInt.h ../textio/textio.h \ + ../utils/signals.h ../utils/malloc.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../sim/sim.h ../windows/windows.h \ + ../dbwind/dbwind.h ../commands/commands.h ../textio/txcommands.h \ + ../utils/styles.h ../graphics/graphics.h +SimSelect.o: SimSelect.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../windows/windows.h ../dbwind/dbwind.h \ + ../utils/undo.h ../commands/commands.h ../select/selInt.h \ + ../utils/main.h ../utils/malloc.h ../utils/signals.h ../sim/sim.h +SimRsim.o: SimRsim.c +SimExtract.o: SimExtract.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/malloc.h ../textio/textio.h \ + ../debug/debug.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../utils/signals.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/styles.h ../utils/stack.h ../sim/sim.h diff --git a/sim/Makefile b/sim/Makefile new file mode 100644 index 00000000..24e9a1f0 --- /dev/null +++ b/sim/Makefile @@ -0,0 +1,10 @@ +# +# rscid $Header: +# + +MODULE = sim +MAGICDIR = .. +SRCS = SimDBstuff.c SimSelect.c SimRsim.c SimExtract.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/sim/SimDBstuff.c b/sim/SimDBstuff.c new file mode 100644 index 00000000..72092caf --- /dev/null +++ b/sim/SimDBstuff.c @@ -0,0 +1,1060 @@ + +/* SimDBstuff.c - + * + * This file contains routines that extract electrically connected + * regions of a layout for Magic. This extractor operates + * hierarchically, across cell boundaries (SimTreeCopyConnect), as + * well as within a single cell (SimSrConnect). + * + * This also contains routines corresponding to those in the DBWind + * module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * University of California + */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "database/databaseInt.h" +#include "textio/textio.h" +#include "utils/signals.h" +#include "utils/malloc.h" +#include "extract/extractInt.h" +#include "sim/sim.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "commands/commands.h" +#include "textio/txcommands.h" +#include "utils/styles.h" +#include "graphics/graphics.h" + +/* The following structure is used to hold several pieces + * of information that must be passed through multiple + * levels of search function. + */ + +struct conSrArg +{ + CellDef *csa_def; /* Definition being searched. */ + Plane *csa_plane; /* Current plane being searched. */ + TileTypeBitMask *csa_connect; /* Table indicating what connects + * to what. + */ + int (*csa_clientFunc)(); /* Client function to call. */ + ClientData csa_clientData; /* Argument for clientFunc. */ + bool csa_clear; /* FALSE means pass 1, TRUE + * means pass 2. + */ + Rect csa_bounds; /* Area that limits search. */ +}; + +/* For SimTreeSrConnect, the extraction proceeds in one pass, copying + * all connected stuff from a hierarchy into a single cell. A list + * is kept to record areas that still have to be searched for + * hierarchical stuff. + */ + +typedef struct +{ + Rect area; /* Area to process */ + TileTypeBitMask *connectMask; /* Connection mask for search */ + TileType dinfo; /* Info about triangular search areas */ +} conSrArea; + +struct conSrArg2 +{ + CellUse *csa2_use; /* Destination use */ + TileTypeBitMask *csa2_connect; /* Table indicating what connects + * to what. + */ + Rect *csa2_bounds; /* Area that limits the search */ + + conSrArea *csa2_list; /* List of areas to process */ + int csa2_top; /* Index of next area to process */ + int csa2_size; /* Max. number bins in area list */ +}; + +#define CSA2_LIST_START_SIZE 256 + +/* Forward declarations */ + +extern char *DBPrintUseId(); +extern int dbcUnconnectFunc(); +extern void SimInitScxStk(); +extern void SimPopScx(); +extern void SimMakePathname(); + +static char bestName[256]; + + +/* + * ---------------------------------------------------------------------------- + * + * SimConnectFunc + * + * This procedure is based upon the function dbcConnectFunc in the + * database module. + * + * This procedure is invoked by SimTreeSrTiles from SimTreeCopyConnect, + * whenever a tile is found that is connected to the current area + * being processed. If the tile overlaps the search area in a non- + * trivial way (i.e. more than a 1x1 square of overlap at a corner) + * then the area of the tile is added onto the list of things to check. + * The "non-trivial" overlap check is needed to prevent caddy-corner + * tiles from being considered as connected. + * + * Results: + * Returns 0 normally, 1 if an abort condition has been encountered. + * + * Side effects: + * Paints into the destination definition. + * + * ---------------------------------------------------------------------------- + */ + +int +SimConnectFunc(tile, cx) + Tile *tile; /* Tile found. */ + TreeContext *cx; /* Describes context of search. The client + * data is a pointer to the list head of + * the conSrArg2's describing the areas + * left to check. + */ +{ + struct conSrArg2 *csa2; + Rect tileArea, *srArea, newarea; + SearchContext *scx = cx->tc_scx; + TileTypeBitMask notConnectMask, *connectMask; + TileType loctype, ctype; + TileType dinfo = 0; + int i, pNum; + static char nodeName[256]; + CellDef *def; + TerminalPath *tpath = cx->tc_filter->tf_tpath; + + TiToRect(tile, &tileArea); + srArea = &scx->scx_area; + + if (((tileArea.r_xbot >= srArea->r_xtop-1) || + (tileArea.r_xtop <= srArea->r_xbot+1)) && + ((tileArea.r_ybot >= srArea->r_ytop-1) || + (tileArea.r_ytop <= srArea->r_ybot+1))) + { + /* If the search area is only one unit wide or tall, then it's + * OK to have only a small overlap. This happens only when + * looking for an initial search tile. + */ + + if (((srArea->r_xtop-1) != srArea->r_xbot) + && ((srArea->r_ytop-1) != srArea->r_ybot)) return 0; + } + GeoTransRect(&scx->scx_trans, &tileArea, &newarea); + + /* Clip the current area down to something that overlaps the + * area of interest. + */ + + csa2 = (struct conSrArg2 *)cx->tc_filter->tf_arg; + GeoClip(&newarea, csa2->csa2_bounds); + if (GEO_RECTNULL(&newarea)) return 0; + + /* Stuff unique to the nodename search follows. */ + + if (tpath != (TerminalPath *)NULL) + { + /* Extract the node name */ + + char *n = tpath->tp_next; + char c = *n; + + SigDisableInterrupts(); + strcpy(nodeName, SimGetNodeName(cx->tc_scx, tile, tpath->tp_first)); + SigEnableInterrupts(); + + *n = c; + + /* save the "best" name for this node */ + + if (bestName[0] == '\0' || efPreferredName(nodeName, bestName)) + strcpy(bestName, nodeName); + } + + loctype = TiGetTypeExact(tile); + + /* Resolve geometric transformations on diagonally-split tiles */ + + if (IsSplit(tile)) + { + dinfo = DBTransformDiagonal(loctype, &scx->scx_trans); + loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); + } + + /* See if the destination cell contains stuff over the whole + * current area (on its home plane) that is connected to it. + * If so, then there's no need to process the current area, + * since any processing that is needed was already done before. + */ + + pNum = DBPlane(loctype); + connectMask = &csa2->csa2_connect[loctype]; + + if (DBIsContact(loctype)) + { + TileTypeBitMask *rMask = DBResidueMask(loctype); + TileTypeBitMask *cMask; + + TTMaskSetOnlyType(¬ConnectMask, loctype); + + /* Differenct contact types may share residues (6/18/04) */ + for (ctype = TT_TECHDEPBASE; ctype < DBNumUserLayers; ctype++) + { + if (DBIsContact(ctype)) + { + cMask = DBResidueMask(ctype); + if (TTMaskIntersect(rMask, cMask)) + TTMaskSetType(¬ConnectMask, ctype); + } + } + + /* The mask of contact types must include all stacked contacts */ + for (ctype = DBNumUserLayers; ctype < DBNumTypes; ctype++) + { + cMask = DBResidueMask(ctype); + if TTMaskHasType(cMask, loctype) + TTMaskSetType(¬ConnectMask, ctype); + } + + TTMaskCom(¬ConnectMask); + } + else + { + TTMaskCom2(¬ConnectMask, connectMask); + } + + def = csa2->csa2_use->cu_def; + if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum], + dinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc, + (ClientData) connectMask) == 0) + return 0; + + /* Paint this tile into the destination cell. */ + + DBNMPaintPlane(def->cd_planes[pNum], dinfo, &newarea, + DBStdPaintTbl(loctype, pNum), (PaintUndoInfo *) NULL); + + /* Since the whole area of this tile hasn't been recorded, + * we must process its area to find any other tiles that + * connect to it. Add each of them to the list of things + * to process. We have to expand the search area by 1 unit + * on all sides because SimTreeSrTiles only returns things + * that overlap the search area, and we want things that + * even just touch. + */ + + /* Only extend those sides bordering the diagonal tile */ + + if (dinfo & TT_DIAGONAL) + { + if (dinfo & TT_SIDE) /* right */ + newarea.r_xtop += 1; + else /* left */ + newarea.r_xbot -= 1; + if (((dinfo & TT_SIDE) >> 1) + == (dinfo & TT_DIRECTION)) /* top */ + newarea.r_ytop += 1; + else /* bottom */ + newarea.r_ybot -= 1; + } + else + { + newarea.r_xbot -= 1; + newarea.r_ybot -= 1; + newarea.r_xtop += 1; + newarea.r_ytop += 1; + } + + /* Abort the name search if the name is in the abort name search table + * or if the name is global and the SimIgnoreGlobals flag is not set. + */ + + if (SimSawAbortString || SigInterruptPending) + return 1; + else if (SimIsGetnode && !SimIgnoreGlobals) + { + i = strlen(nodeName); + if (nodeName[i - 1] == '!') + return 1; + } + + /* Register the area and connection mask as needing to be processed */ + + if (++csa2->csa2_top == csa2->csa2_size) + { + /* Reached list size limit---need to enlarge the list */ + /* Double the size of the list every time we hit the limit */ + + conSrArea *newlist; + int i, lastsize = csa2->csa2_size; + + csa2->csa2_size *= 2; + + newlist = (conSrArea *)mallocMagic(csa2->csa2_size * sizeof(conSrArea)); + for (i = 0; i < lastsize; i++) + { + newlist[i].area = csa2->csa2_list[i].area; + newlist[i].connectMask = csa2->csa2_list[i].connectMask; + newlist[i].dinfo = csa2->csa2_list[i].dinfo; + } + freeMagic((char *)csa2->csa2_list); + csa2->csa2_list = newlist; + } + + csa2->csa2_list[csa2->csa2_top].area = newarea; + csa2->csa2_list[csa2->csa2_top].connectMask = connectMask; + csa2->csa2_list[csa2->csa2_top].dinfo = dinfo; + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * SimTreeCopyConnect + * + * This procedure is very similar to DBTreeCopyConnect. + * + * This procedure copies connected information from a given cell + * hierarchy to a given (flat) cell. Starting from the tile underneath + * the given area, this procedure finds all paint in all cells + * that is connected to that information. All such paint is + * copied into the result cell. If there are several electrically + * distinct nets underneath the given area, one of them is picked + * at more-or-less random. + * + * Modified so the result cell is NOT first cleared of all paint. This + * allows multiple calls, to highlight incomplete routing nets. + * + * Results: + * None. + * + * Side effects: + * The contents of the result cell are modified. + * + * ---------------------------------------------------------------------------- + */ + +#define MAXPATHNAME 256 + +void +SimTreeCopyConnect(scx, mask, xMask, connect, area, destUse, Node_Name) + SearchContext *scx; /* Describes starting area. The + * scx_use field gives the root of + * the hierarchy to search, and the + * scx_area field gives the starting + * area. An initial tile must overlap + * this area. The transform is from + * coords of scx_use to destUse. + */ + TileTypeBitMask *mask; /* Tile types to start from in area. */ + int xMask; /* Information must be expanded in all + * of the windows indicated by this + * mask. Use 0 to consider all info + * regardless of expansion. + */ + TileTypeBitMask *connect; /* Points to table that defines what + * each tile type is considered to + * connect to. Use DBConnectTbl as + * a default. + */ + Rect *area; /* The resulting information is + * clipped to this area. Pass + * TiPlaneRect to get everything. + */ + CellUse *destUse; /* Result use in which to place + * anything connected to material of + * type mask in area of rootUse. + */ + char *Node_Name; /* Name of node returned. + * NOTE: Don't call this "NodeName", + * because that conflicts with reserved + * words in some compilers. + */ +{ + TerminalPath tpath; + char pathName[MAXPATHNAME]; + TileTypeBitMask *newmask; + struct conSrArg2 csa2; + TileType newtype; + + csa2.csa2_use = destUse; + csa2.csa2_bounds = area; + csa2.csa2_connect = connect; + + csa2.csa2_size = CSA2_LIST_START_SIZE; + csa2.csa2_list = (conSrArea *)mallocMagic(CSA2_LIST_START_SIZE + * sizeof(conSrArea)); + csa2.csa2_top = -1; + + tpath.tp_first = tpath.tp_next = pathName; + tpath.tp_last = pathName + MAXPATHNAME; + + pathName[0] = '\0'; + bestName[0] = '\0'; + + (void) SimTreeSrTiles(scx, mask, xMask, &tpath, SimConnectFunc, + (ClientData) &csa2); + while (csa2.csa2_top >= 0) + { + newmask = csa2.csa2_list[csa2.csa2_top].connectMask; + scx->scx_area = csa2.csa2_list[csa2.csa2_top].area; + newtype = csa2.csa2_list[csa2.csa2_top].dinfo; + csa2.csa2_top--; + + if (newtype & TT_DIAGONAL) + SimTreeSrNMTiles(scx, newtype, newmask, xMask, &tpath, + SimConnectFunc, (ClientData) &csa2); + else + SimTreeSrTiles(scx, newmask, xMask, &tpath, SimConnectFunc, + (ClientData) &csa2); + } + freeMagic((char *)csa2.csa2_list); + + /* Recompute the bounding box of the destination and record + * its area for redisplay. + */ + + strcpy(Node_Name, bestName); + DBReComputeBbox(destUse->cu_def); +} + +/* + * ---------------------------------------------------------------------------- + * + * efPreferredName -- + * + * This is the same function used in the ext2sim module. We need this + * function for the rsim interface to Magic. + * + * Determine which of two names is more preferred. The most preferred + * name is a global name. Given two non-global names, the one with the + * fewest pathname components is the most preferred. If the two names + * have equally many pathname components, we choose the shortest. + * + * Results: + * TRUE if 'name1' is preferable to 'name2', FALSE if not. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +efPreferredName(name1, name2) + char *name1, *name2; +{ + int nslashes1, nslashes2; + char *np1, *np2; + + if( name1[0] == '@' && name1[1] == '=' ) + return( TRUE ); + else if( name2[0] == '@' && name2[1] == '=' ) + return( FALSE ); + + for (nslashes1 = 0, np1 = name1; *np1; ) { + if (*np1++ == '/') + nslashes1++; + } + + for (nslashes2 = 0, np2 = name2; *np2; ) { + if (*np2++ == '/') + nslashes2++; + } + + --np1; + --np2; + + if (!SimIgnoreGlobals) + { + /* both are global names */ + if ((*np1 == '!') && (*np2 == '!')) { + /* check # of pathname components */ + if (nslashes1 < nslashes2) return (TRUE); + if (nslashes1 > nslashes2) return (FALSE); + + /* same # of pathname components; check length */ + if (np1 - name1 < np2 - name2) return (TRUE); + if (np1 - name1 > np2 - name2) return (FALSE); + + /* same # of pathname components; same length; use lex order */ + if (strcmp(name1, name2) > 0) + return(TRUE); + else + return(FALSE); + } + if (*np1 == '!') return(TRUE); + if (*np2 == '!') return(FALSE); + } + + /* neither name is global */ + /* chose label over generated name */ + if (*np1 != '#' && *np2 == '#') return (TRUE); + if (*np1 == '#' && *np2 != '#') return (FALSE); + + /* either both are labels or generated names */ + /* check pathname components */ + if (nslashes1 < nslashes2) return (TRUE); + if (nslashes1 > nslashes2) return (FALSE); + + /* same # of pathname components; check length */ + if (np1 - name1 < np2 - name2) return (TRUE); + if (np1 - name1 > np2 - name2) return (FALSE); + + /* same # of pathname components; same length; use lex ordering */ + if (strcmp(name1, name2) > 0) + return(TRUE); + else + return(FALSE); +} + + + +/* + * ---------------------------------------------------------------------------- + * + * SimSrConnect + * + * This is similar to the procedure DBSrConnect, except that the + * marks on each tile in the cell are not erased. + * + * Search through a cell to find all paint that is electrically + * connected to things in a given starting area. + * + * Results: + * 0 is returned if the search finished normally. 1 is returned + * if the search was aborted. + * + * Side effects: + * The search starts from one (random) non-space tile in "startArea" + * that matches the types in the mask parameter. For every paint + * tile that is electrically connected to the initial tile and that + * intersects the rectangle "bounds", func is called. Func should + * have the following form: + * + * int + * func(tile, clientData) + * Tile *tile; + * ClientData clientData; + * { + * } + * + * The clientData passed to func is the same one that was passed + * to us. Func returns 0 under normal conditions; if it returns + * 1 then the search is aborted. + * + * *** WARNING *** + * + * Func should not modify any paint during the search, since this + * will mess up pointers kept by these procedures and likely cause + * a core-dump. + * + * ---------------------------------------------------------------------------- + */ + +int +SimSrConnect(def, startArea, mask, connect, bounds, func, clientData) + CellDef *def; /* Cell definition in which to carry out + * the connectivity search. Only paint + * in this definition is considered. + */ + Rect *startArea; /* Area to search for an initial tile. Only + * tiles OVERLAPPING the area are considered. + * This area should have positive x and y + * dimensions. + */ + TileTypeBitMask *mask; /* Only tiles of one of these types are used + * as initial tiles. + */ + TileTypeBitMask *connect; /* Pointer to a table indicating what tile + * types connect to what other tile types. + * Each entry gives a mask of types that + * connect to tiles of a given type. + */ + Rect *bounds; /* Area, in coords of scx->scx_use->cu_def, + * that limits the search: only tiles + * overalapping this area will be returned. + * Use TiPlaneRect to search everywhere. + */ + int (*func)(); /* Function to apply at each connected tile. */ + ClientData clientData; /* Client data for above function. */ + +{ + struct conSrArg csa; + int startPlane, result; + Tile *startTile; /* Starting tile for search. */ + extern int dbSrConnectFunc(); /* Forward declaration. */ + extern int dbSrConnectStartFunc(); + + result = 0; + csa.csa_def = def; + csa.csa_bounds = *bounds; + + /* Find a starting tile (if there are many tiles underneath the + * starting area, pick any one). The search function just saves + * the tile address and returns. + */ + + startTile = NULL; + for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++) + { + if (DBSrPaintArea((Tile *) NULL, + def->cd_planes[startPlane], startArea, mask, + dbSrConnectStartFunc, (ClientData) &startTile) != 0) break; + } + if (startTile == NULL) return 0; + + /* Pass 1. During this pass the client function gets called. */ + + csa.csa_clientFunc = func; + csa.csa_clientData = clientData; + csa.csa_clear = FALSE; + csa.csa_connect = connect; + csa.csa_plane = def->cd_planes[startPlane]; + if (dbSrConnectFunc(startTile, &csa) != 0) result = 1; + + return result; +} + + +/* + *----------------------------------------------------------------------------- + * + * SimTreeSrTiles + * + * Similar to the procedure DBTreeSrTiles, although having a terminal + * path similar to procedure DBTreeSrLabels. + * + * Recursively search downward from the supplied CellUse for + * all visible paint tiles matching the supplied type mask. + * + * The procedure should be of the following form: + * int + * func(tile, cxp) + * Tile *tile; + * TreeContext *cxp; + * { + * } + * + * The SearchContext is stored in cxp->tc_scx, the user's arg is stored + * in cxp->tc_filter->tf_arg, and the terminal path is stored in + * cxp->tc_filter->tf_tpath. + * + * In the above, the scx transform is the net transform from the coordinates + * of tile to "world" coordinates (or whatever coordinates the initial + * transform supplied to SimTreeSrTiles was a transform to). Func returns + * 0 under normal conditions. If 1 is returned, it is a request to + * abort the search. + * + * *** WARNING *** + * + * The client procedure should not modify any of the paint planes in + * the cells visited by SimTreeSrTiles, because we use DBSrPaintArea + * instead of TiSrArea as our paint-tile enumeration function. + * + * Results: + * 0 is returned if the search finished normally. 1 is returned + * if the search was aborted. + * + * Side effects: + * Whatever side effects are brought about by applying the + * procedure supplied. + * + *----------------------------------------------------------------------------- + */ + +int +SimTreeSrTiles(scx, mask, xMask, tpath, func, cdarg) + SearchContext *scx; /* Pointer to search context specifying + * a cell use to search, an area in the + * coordinates of the cell's def, and a + * transform back to "root" coordinates. + */ + TileTypeBitMask *mask; /* Only tiles with a type for which + * a bit in this mask is on are processed. + */ + int xMask; /* All subcells are visited recursively + * until we encounter uses whose flags, + * when anded with xMask, are not + * equal to xMask. + */ + TerminalPath *tpath; /* Pointer to a structure describing a + * partially filled-in terminal pathname. + * Add new components as encountered. + */ + int (*func)(); /* Function to apply at each qualifying tile */ + ClientData cdarg; /* Client data for above function */ +{ + int SimCellTileSrFunc(); + TreeFilter filter; + + filter.tf_func = func; + filter.tf_arg = cdarg; + filter.tf_mask = mask; + filter.tf_xmask = xMask; + filter.tf_planes = DBTechTypesToPlanes(mask); + filter.tf_tpath = tpath; + filter.tf_dinfo = 0; + + return SimCellTileSrFunc(scx, &filter); +} + +/* + * SimTreeSrNMTiles --- + * This is a variant of the above in which the search is over + * a non-Manhattan triangular area. + */ + +int +SimTreeSrNMTiles(scx, dinfo, mask, xMask, tpath, func, cdarg) + SearchContext *scx; /* Pointer to search context specifying + * a cell use to search, an area in the + * coordinates of the cell's def, and a + * transform back to "root" coordinates. + */ + TileType dinfo; /* Type containing information about the + * triangular area to search. + */ + TileTypeBitMask *mask; /* Only tiles with a type for which + * a bit in this mask is on are processed. + */ + int xMask; /* All subcells are visited recursively + * until we encounter uses whose flags, + * when anded with xMask, are not + * equal to xMask. + */ + TerminalPath *tpath; /* Pointer to a structure describing a + * partially filled-in terminal pathname. + * Add new components as encountered. + */ + int (*func)(); /* Function to apply at each qualifying tile */ + ClientData cdarg; /* Client data for above function */ +{ + int SimCellTileSrFunc(); + TreeFilter filter; + + filter.tf_func = func; + filter.tf_arg = cdarg; + filter.tf_mask = mask; + filter.tf_xmask = xMask; + filter.tf_dinfo = dinfo; + filter.tf_planes = DBTechTypesToPlanes(mask); + filter.tf_tpath = tpath; + + return SimCellTileSrFunc(scx, &filter); +} + +/* + * Filter procedure applied to subcells by SimTreeSrTiles(). + */ + +int +SimCellTileSrFunc(scx, fp) + SearchContext *scx; + TreeFilter *fp; +{ + TreeContext context; + TerminalPath *tp; + CellDef *def = scx->scx_use->cu_def; + int pNum, result; + char *tnext; + + ASSERT(def != (CellDef *) NULL, "SimCellTileSrFunc"); + if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) + return 0; + if ((def->cd_flags & CDAVAILABLE) == 0) + if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + + context.tc_scx = scx; + context.tc_filter = fp; + + /* Create the path prefix */ + /* Don't prepend the "Topmost cell" ID of the top-level cell. */ + + if ((fp->tf_tpath != (TerminalPath *)NULL) + && (scx->scx_use->cu_parent != NULL)) + { + tp = fp->tf_tpath; + tnext = tp->tp_next; + tp->tp_next = DBPrintUseId(scx, tp->tp_next, tp->tp_last - + tp->tp_next, FALSE); + if (tp->tp_next < tp->tp_last) + { + *(tp->tp_next++) = '/'; + *(tp->tp_next) = '\0'; + } + } + + /* + * Apply the function first to any of the tiles in the planes + * for this CellUse's CellDef that match the mask. + */ + + result = 0; + for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) + if (PlaneMaskHasPlane(fp->tf_planes, pNum)) + { + if (fp->tf_dinfo & TT_DIAGONAL) + { + TileType dinfo = DBTransformDiagonal(fp->tf_dinfo, &scx->scx_trans); + if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum], + dinfo, &scx->scx_area, fp->tf_mask, + fp->tf_func, (ClientData) &context)) + { + result = 1; + goto cleanup; + } + } + else + if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], + &scx->scx_area, fp->tf_mask, + fp->tf_func, (ClientData) &context)) + { + result = 1; + goto cleanup; + } + } + + /* + * Now apply ourselves recursively to each of the CellUses + * in our tile plane. + */ + + if (DBCellSrArea(scx, SimCellTileSrFunc, (ClientData) fp)) + result = 1; + +cleanup: + /* Remove the trailing pathname component from the TerminalPath */ + if ((fp->tf_tpath != (TerminalPath *)NULL) + && (scx->scx_use->cu_parent != NULL)) + { + fp->tf_tpath->tp_next = tnext; + *tnext = '\0'; + } + return (result); +} + + +/* + * ---------------------------------------------------------------------------- + * + * SimPutLabel -- + * + * Same as DBPutLabel, except this does not set the cell modified flag. + * + * Place a rectangular label in the database, in a particular cell. + * + * It is the responsibility of higher-level routines to insure that + * the material to which the label is being attached really exists at + * this point in the cell, and that TT_SPACE is used if there is + * no single material covering the label's entire area. The routine + * DBAdjustLabels is useful for this. + * + * Results: + * The return value is the actual alignment position used for + * the label. This may be different from align, if align is + * defaulted. + * + * Side effects: + * Updates the label list in the CellDef to contain the label. + * + * ---------------------------------------------------------------------------- + */ + +int +SimPutLabel(cellDef, rect, align, text, type) + CellDef *cellDef; /* Cell in which label is placed */ + Rect *rect; /* Location of label; see above for description */ + int align; /* Orientation/alignment of text. If this is < 0, + * an orientation will be picked to keep the text + * inside the cell boundary. + */ + char *text; /* Pointer to actual text of label */ + TileType type; /* Type of tile to be labeled */ +{ + Label *lab; + int len, x1, x2, y1, y2, tmp, labx, laby; + + len = strlen(text) + sizeof (Label) - sizeof lab->lab_text + 1; + lab = (Label *) mallocMagic((unsigned) len); + strcpy(lab->lab_text, text); + + /* Pick a nice alignment if the caller didn't give one. If the + * label is more than BORDER units from an edge of the cell, + * use GEO_NORTH. Otherwise, put the label on the opposite side + * from the boundary, so it won't stick out past the edge of + * the cell boundary. + */ + +#define BORDER 5 + if (align < 0) + { + tmp = (cellDef->cd_bbox.r_xtop - cellDef->cd_bbox.r_xbot)/3; + if (tmp > BORDER) tmp = BORDER; + x1 = cellDef->cd_bbox.r_xbot + tmp; + x2 = cellDef->cd_bbox.r_xtop - tmp; + tmp = (cellDef->cd_bbox.r_ytop - cellDef->cd_bbox.r_ybot)/3; + if (tmp > BORDER) tmp = BORDER; + y1 = cellDef->cd_bbox.r_ybot + tmp; + y2 = cellDef->cd_bbox.r_ytop - tmp; + labx = (rect->r_xtop + rect->r_xbot)/2; + laby = (rect->r_ytop + rect->r_ybot)/2; + + if (labx <= x1) + { + if (laby <= y1) align = GEO_NORTHEAST; + else if (laby >= y2) align = GEO_SOUTHEAST; + else align = GEO_EAST; + } + else if (labx >= x2) + { + if (laby <= y1) align = GEO_NORTHWEST; + else if (laby >= y2) align = GEO_SOUTHWEST; + else align = GEO_WEST; + } + else + { + if (laby <= y1) align = GEO_NORTH; + else if (laby >= y2) align = GEO_SOUTH; + else align = GEO_NORTH; + } + } + + lab->lab_just = align; + lab->lab_type = type; + lab->lab_rect = *rect; + lab->lab_next = NULL; + lab->lab_flags = 0; + if (cellDef->cd_labels == NULL) + cellDef->cd_labels = lab; + else + { + ASSERT(cellDef->cd_lastLabel->lab_next == NULL, "SimPutLabel"); + cellDef->cd_lastLabel->lab_next = lab; + } + cellDef->cd_lastLabel = lab; + + DBUndoPutLabel(cellDef, lab); + return align; +} + + +#ifdef RSIM_MODULE + +/* + * ---------------------------------------------------------------------------- + * + * SimRsimHandler + * + * This procedure is the button handler for the rsim tool. + * + * Results: + * None. + * + * Side effects: + * Left button: used to move the whole box by the lower-left corner. + * Right button: used to re-size the box by its upper-right corner. + * If one of the left or right buttons is pushed, then the + * other is pushed, the corner is switched to the nearest + * one to the cursor. This corner is remembered for use + * in box positioning/sizing when both buttons have gone up. + * Middle button: used to display the rsim node values of whatever + * paint is selected. + * + * ---------------------------------------------------------------------------- + */ + +void +SimRsimHandler(w, cmd) + MagWindow *w; /* Window containing cursor. */ + TxCommand *cmd; /* Describes what happened. */ +{ + + static int buttonCorner = TOOL_ILG; + int button = cmd->tx_button; + + if (button == TX_MIDDLE_BUTTON) + { + if (cmd->tx_buttonAction == TX_BUTTON_DOWN) + SimRsimMouse(w); + return; + } + + if (cmd->tx_buttonAction == TX_BUTTON_DOWN) + { + if ((WindNewButtons & (TX_LEFT_BUTTON|TX_RIGHT_BUTTON)) + == (TX_LEFT_BUTTON|TX_RIGHT_BUTTON)) + { + /* Both buttons are now down. In this case, the FIRST + * button pressed determines whether we move or size, + * and the second button is just used as a signal to pick + * the closest corner. + */ + + buttonCorner = ToolGetCorner(&cmd->tx_p); + if (button == TX_LEFT_BUTTON) button = TX_RIGHT_BUTTON; + else button = TX_LEFT_BUTTON; + } + else if (button == TX_LEFT_BUTTON) buttonCorner = TOOL_BL; + else buttonCorner = TOOL_TR; + dbwButtonSetCursor(button, buttonCorner); + } + else + { + /* A button has just come up. If both buttons are down and one + * is released, we just change the cursor to reflect the current + * corner and the remaining button (i.e. move or size box). + */ + + if (WindNewButtons != 0) + { + if (button == TX_LEFT_BUTTON) + dbwButtonSetCursor(TX_RIGHT_BUTTON, buttonCorner); + else dbwButtonSetCursor(TX_LEFT_BUTTON, buttonCorner); + return; + } + + /* The last button has been released. Reset the cursor to normal + * form and then move or size the box. + */ + + GrSetCursor(STYLE_CURS_RSIM); + switch (button) + { + case TX_LEFT_BUTTON: + ToolMoveBox(buttonCorner, &cmd->tx_p, TRUE, (CellDef *) NULL); + break; + case TX_RIGHT_BUTTON: + ToolMoveCorner(buttonCorner, &cmd->tx_p, TRUE, + (CellDef *) NULL); + } + } +} + +#endif diff --git a/sim/SimExtract.c b/sim/SimExtract.c new file mode 100644 index 00000000..5678f360 --- /dev/null +++ b/sim/SimExtract.c @@ -0,0 +1,819 @@ +/* + * SimExtract.c + * + * This file provides routines to extract a single node name from the + * Magic circuit. Some of this code is based on the Magic extract + * module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * of California. + */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" +#include "textio/textio.h" +#include "debug/debug.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/styles.h" +#include "utils/stack.h" +#include "sim/sim.h" + + +/* When performing node name extraction, we mark all tiles of a node + * as we walk through the database. Since nodes can span multiple cells, + * we need to keep a list off all cell definitions which we marked during + * the search so we can erase these marks when we are finished. + */ +typedef struct def_list_elt +{ + CellDef *dl_def; + struct def_list_elt *dl_next; +} DefListElt; + +/* When the node name is extracted, all the labels associated with the + * name are contained in a NodeRegion data structure. We save all the + * node regions created during the name search, freeing them when we are + * finished. + */ + + +static DefListElt *DefList = (DefListElt *) NULL; + /* list of cell defs used in the node name search */ + +static NodeRegion *NodeRegList = (NodeRegion *) NULL; + /* list of the nodes found in the current selection */ + +extern Stack *extNodeStack; + /* stack used to process node tiles */ + +static ExtStyle *simExtStyle = NULL; + + /* + * Mask with a bit set for every type of transistor. + */ +TileTypeBitMask SimTransMask; + /* + * Mask indicating which tile types may form a transistor + * terminal (source/drain). + */ +TileTypeBitMask SimSDMask; + /* + * A mask indicating which tile types may be the active part + * of a transistor. if type 't' is a possible transistor terminal, + * then SimFetMask[t] indicates which tile types to search for the + * 'gate' part. + */ +TileTypeBitMask SimFetMask[TT_MAXTYPES]; + /* + * Mask of planes for which SimFetMask is non-zero. + */ +PlaneMask SimFetPlanes; + + +/* + *---------------------------------------------------------------- + * SimAddDefList -- + * + * This procedure adds a cell definition to the DefList. A cell + * definition is added only if is not already in the list. + * + * Results: + * None. + * + * Side effects: + * The cell may be added to the list. + * + *---------------------------------------------------------------- + */ + +void +SimAddDefList(newdef) + CellDef *newdef; +{ + DefListElt *d; + + /* check to see if the cell def is already in our list */ + + for (d = DefList; d != (DefListElt *) NULL; d = d->dl_next) { + if (d->dl_def == newdef) { + return; + } + } + + /* add the cell def to the list */ + + if (DefList == (DefListElt *) NULL) { + DefList = (DefListElt *) mallocMagic((unsigned) (sizeof(DefListElt))); + DefList->dl_def = newdef; + DefList->dl_next = (DefListElt *) NULL; + return; + } + else { + d = (DefListElt *) mallocMagic((unsigned) (sizeof(DefListElt))); + d->dl_next = DefList; + d->dl_def = newdef; + DefList= d; + } +} + +/* + *---------------------------------------------------------------- + * SimInitDefList + * + * This procedure initializes the cell definition list. Any cell + * definitions in the list have their tiles erased of the marks + * we left during the node name search, and the space in the list + * is freed. + * + * Results: + * None. + * + * Side effects: + * The cell definitions' tiles' marks we left are erased and the + * list is set to NULL. + * + *---------------------------------------------------------------- + */ + +void +SimInitDefList() +{ + DefListElt *p, *q; + + p = q = DefList; + while (p != (DefListElt *) NULL) { + q = p; + p = p->dl_next; + ExtResetTiles(q->dl_def, extUnInit); + freeMagic(q); + } + DefList = (DefListElt *) NULL; +} + + +/* + *---------------------------------------------------------------- + * SimAddNodeList + * + * This procedure prepends a node region to the node region list. + * + * Results: + * None. + * + * Side effects: + * The region next pointer is updated. + * + *---------------------------------------------------------------- + */ + +void +SimAddNodeList(newnode) + NodeRegion *newnode; +{ + if( NodeRegList != (NodeRegion *) NULL ) + newnode->nreg_next = NodeRegList; + NodeRegList = newnode; +} + + + +/* + *---------------------------------------------------------------- + * SimFreeNodeRegs + * + * This procedure frees the label regions stored in the list. + * + * Results: + * None. + * + * Side effects: + * The list is set to NULL. + * + *---------------------------------------------------------------- + */ + +void +SimFreeNodeRegs() +{ + NodeRegion *p, *q; + + if( NodeRegList != (NodeRegion *) NULL ) /* sanity */ + ExtFreeLabRegions((LabRegion *) NodeRegList ); + + NodeRegList = (NodeRegion *) NULL; +} + + +/* + *---------------------------------------------------------------- + * SimInitConnTables -- + * + * Initialize the connectivity tables for finding transistors connected + * to the region being searched. + *---------------------------------------------------------------- + */ +int SimInitConnTables() +{ + int i, t, sd, p; + + SimTransMask = ExtCurStyle->exts_transMask; + + TTMaskZero( &SimSDMask ); + for( t = TT_TECHDEPBASE; t < DBNumTypes; t++ ) + { + for (i = 0; !TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], + TT_SPACE); i++) + { + TTMaskSetMask( &SimSDMask, &ExtCurStyle->exts_transSDTypes[t][i] ); + TTMaskZero( &SimFetMask[t] ); + } + } + + SimFetPlanes = 0; + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + if (TTMaskHasType(&SimTransMask, t)) + { + for (sd = TT_TECHDEPBASE; sd < DBNumTypes; sd++) + { + for (i = 0; !TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], + TT_SPACE); i++) + { + if (TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], sd)) + { + TTMaskSetType(&SimFetMask[sd], t); + SimFetPlanes |= PlaneNumToMaskBit(DBPlane(t)); + } + } + } + } + } + simExtStyle = ExtCurStyle; + return 0; +} + +#define IsTransGate( T ) ( TTMaskHasType( &SimTransMask, T ) ) +#define IsTransTerm( T ) ( TTMaskHasType( &SimSDMask, T ) ) + + +typedef struct +{ + NodeRegion *region; /* Node to which this terminal is connected */ + int pnum; /* Lowest numbered plane in this region */ + Point pos; /* Lower-leftmost point for this node */ +} TransTerm; + + +typedef struct +{ + LabRegion *t_dummy; /* UNUSED */ + int t_pnum; /* Lowest numbered plane in this region */ + int t_type; /* Type of tile that contains lreg_ll */ + Point t_ll; /* Lower-leftmost point of 'gate' region */ + int t_nterm; /* number of terminals (at most 2) */ + bool t_do_terms; /* Set if we should collect terminals */ + TransTerm t_term[10]; /* transistor 'source/drain' terminal(s) */ +} SimTrans; + + +static Tile *gateTile; /* Set to point to a transistor tile + * whose gate is connected to the + * node being searched + */ +static Tile *sdTile; /* Set to point to a transistor tile + * whose source/drain is connected + * to the node being searched + */ +static SimTrans transistor; /* Transistor being extracted */ + + +typedef enum { ND_REGION, ND_NAME } RegOrName; + + +typedef struct /* return value from SimFindOneNode */ +{ + RegOrName nd_what; /* ND_REGION, => region, ND_NAME => nd_name */ + NodeRegion *nd_region; /* The node region extracted */ + char *nd_name; /* The 'final' node name */ +} NodeSpec; + + +/* + *---------------------------------------------------------------- + * SimTxtorLabel -- + * + * Return a string that identifies a node as a function of a transistor + * position. + * + *---------------------------------------------------------------- + */ +char *SimTxtorLabel( nterm, tm, trans ) + int nterm; + Transform *tm; + SimTrans *trans; +{ + static char name[30]; + Rect r1, r2; + + r1.r_ll = trans->t_ll; + r1.r_xtop = r1.r_xbot + 1; + r1.r_ytop = r1.r_ybot + 1; + GeoTransRect( tm, &r1, &r2 ); + if( nterm > 1 ) + nterm = 1; + sprintf( name, "@=%c%d,%d", "gsd"[nterm+1], r2.r_xbot, r2.r_ybot ); + + return( name ); +} + +int SimSDTransFunc( tile, ptile ) + Tile *tile; + Tile **ptile; +{ + *ptile = tile; + return( 1 ); +} + + +int SimTransTerms( bp, trans ) + Boundary *bp; + SimTrans *trans; +{ + TransTerm *term; + Tile *tile = bp->b_outside; + TileType type; + NodeRegion *reg = (NodeRegion *) tile->ti_client; + int pNum; + int i; + + if (IsSplit(tile)) { + switch(bp->b_direction) { + case BD_LEFT: + type = TiGetRightType(tile); + break; + case BD_RIGHT: + type = TiGetLeftType(tile); + break; + case BD_TOP: + type = TiGetBottomType(tile); + break; + case BD_BOTTOM: + type = TiGetTopType(tile); + break; + } + } + else + type = TiGetTypeExact(tile); + + pNum = DBPlane(type); + + for( i = 0; i < trans->t_nterm; i++ ) + { + term = &trans->t_term[i]; + if( term->region == reg ) + { + if( pNum < term->pnum ) + { + term->pnum = pNum; + term->pos = tile->ti_ll; + } + else if( pNum == term->pnum ) + { + if( LEFT(tile) < term->pos.p_x ) + term->pos = tile->ti_ll; + else if( LEFT(tile) == term->pos.p_x && + BOTTOM(tile) < term->pos.p_y ) + term->pos.p_y = BOTTOM(tile); + } + return( 0 ); + } + } + + term = &trans->t_term[ trans->t_nterm++ ]; + term->region = reg; + term->pnum = pNum; + term->pos = tile->ti_ll; + return( 0 ); +} + + +int SimTermNum( trans, reg ) + SimTrans *trans; + NodeRegion *reg; +{ + int i, changed; + TransTerm *p1, *p2, tmp; + + do + { + changed = 0; + for( i = 0; i < trans->t_nterm-1; i++ ) + { + p1 = &(trans->t_term[i]); + p2 = &(trans->t_term[i+1]); + if( p2->pnum > p1->pnum ) + continue; + else if( p2->pnum == p1->pnum ) + { + if( p2->pos.p_x > p1->pos.p_x ) + continue; + else if( p2->pos.p_x == p1->pos.p_x && + p2->pos.p_y > p1->pos.p_y ) + continue; + } + changed = 1; + tmp = *p1; + *p1 = *p2; + *p2 = tmp; + } + } + while( changed ); + + for( i = 0; i < trans->t_nterm; i++ ) + { + if( trans->t_term[i].region == reg ) + return( i ); + } + /* should never get here */ + return( -1 ); +} + + +int +SimTransistorTile(tile, pNum, arg) + Tile *tile; + int pNum; + FindRegion *arg; +{ + int i; + TileType t; + + extSetNodeNum((LabRegion *)&transistor, pNum, tile); + if (transistor.t_do_terms) + { + t = TiGetType(tile); + for (i = 0; !TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], + TT_SPACE); i++) + extEnumTilePerim(tile, ExtCurStyle->exts_transSDTypes[t][i], + SimTransTerms, (ClientData) &transistor ); + } + + return (0); +} + + +int SimFindTxtor( tile, pNum, arg ) + Tile *tile; + int pNum; + FindRegion *arg; +{ + TileType type; + + extSetNodeNum( (LabRegion *) arg->fra_region, pNum, tile ); + + if( ! SimUseCoords ) /* keep searching, forget transistors */ + return( 0 ); + + type = TiGetType( tile ); + + if( IsTransGate( type ) ) + { + gateTile = tile; /* found a transistor gate, stop searching */ + return( 1 ); + } + else if( IsTransTerm( type ) && sdTile == (Tile *) NULL ) + { + Rect area; + + TITORECT( tile, &area ); + GEO_EXPAND( &area, 1, &area ); + for( pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++ ) + if( PlaneMaskHasPlane( SimFetPlanes, pNum ) ) + { + if( DBSrPaintArea((Tile *) NULL, + arg->fra_def->cd_planes[pNum], &area, &SimFetMask[type], + SimSDTransFunc, (ClientData) &sdTile ) ) + break; + } + } + return( 0 ); +} + + +/* + *---------------------------------------------------------------- + * SimFindOneNode + * + * This procedure returns the node region for a tile which lies + * in the node. + * + * Results: + * A pointer to the node's node region data structure is returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------- + */ + +NodeSpec * +SimFindOneNode( sx, tile ) + SearchContext *sx; + Tile *tile; +{ + CellDef *def = sx->scx_use->cu_def; + NodeRegion *reg; + FindRegion arg; + TileType type, loctype; + static NodeSpec ret; + + /* Allocate a new node */ + reg = (NodeRegion *) mallocMagic((unsigned) (sizeof(NodeRegion) )); + reg->nreg_labels = (LabelList *) NULL; + reg->nreg_cap = 0; + reg->nreg_resist = 0; + reg->nreg_pnum = DBNumPlanes; + reg->nreg_next = (NodeRegion *) NULL; + + gateTile = sdTile = (Tile *) NULL; + + /* Find all connected paint in this cell */ + arg.fra_connectsTo = ExtCurStyle->exts_nodeConn; + arg.fra_def = def; + + if (IsSplit(tile)) + type = SplitSide(tile) ? TiGetRightType(tile) : TiGetLeftType(tile); + else + type = TiGetTypeExact(tile); + + arg.fra_pNum = DBPlane(type); + arg.fra_uninit = (ClientData) extUnInit; + arg.fra_region = (Region *) reg; + arg.fra_each = SimFindTxtor; + (void) ExtFindNeighbors( tile, arg.fra_pNum, &arg ); + + if( gateTile != (Tile *) NULL ) + { + /* Determine the transistor position (leftmost-lowest tile) */ + transistor.t_pnum = DBNumPlanes; + transistor.t_do_terms = FALSE; + + gateTile->ti_client = (ClientData) extUnInit; + arg.fra_connectsTo = &SimTransMask; + + if (IsSplit(tile)) + loctype = SplitSide(gateTile) ? TiGetRightType(gateTile) + : TiGetLeftType(gateTile); + else + loctype = TiGetTypeExact(gateTile); + + arg.fra_pNum = DBPlane(loctype); + arg.fra_uninit = (ClientData) extUnInit; + arg.fra_region = (Region *) reg; + arg.fra_each = SimTransistorTile; + (void) ExtFindNeighbors( gateTile, arg.fra_pNum, &arg ); + + /* Unmark current region since not all paint was traced */ + arg.fra_connectsTo = ExtCurStyle->exts_nodeConn; + arg.fra_pNum = DBPlane(type); + arg.fra_uninit = (ClientData) reg; + arg.fra_region = (Region *) extUnInit; + arg.fra_each = (int (*)()) NULL; + (void) ExtFindNeighbors( tile, arg.fra_pNum, &arg ); + + freeMagic( reg ); + + ret.nd_name = SimTxtorLabel( -1, &sx->scx_trans, &transistor ); + ret.nd_what = ND_NAME; + } + else if( sdTile != (Tile *) NULL ) + { + int tNum; + + SimAddNodeList( reg ); + SimAddDefList( def ); + + transistor.t_pnum = DBNumPlanes; + transistor.t_nterm = 0; + transistor.t_do_terms = TRUE; + + /* collect the transistor position, and its terminals */ + arg.fra_connectsTo = &SimTransMask; + + if (IsSplit(tile)) + loctype = SplitSide(sdTile) ? TiGetRightType(sdTile) + : TiGetLeftType(sdTile); + else + loctype = TiGetTypeExact(sdTile); + + arg.fra_pNum = DBPlane(loctype); + arg.fra_uninit = (ClientData) sdTile->ti_client; + arg.fra_region = (Region *) &ret; + arg.fra_each = SimTransistorTile; + (void) ExtFindNeighbors( sdTile, arg.fra_pNum, &arg ); + + /* Unmark the transitor, since its not part of this region */ + arg.fra_region = (Region *) arg.fra_uninit; + arg.fra_uninit = (ClientData) &ret; + arg.fra_each = (int (*)()) NULL; + (void) ExtFindNeighbors( sdTile, arg.fra_pNum, &arg ); + + if( (tNum = SimTermNum( &transistor, reg )) < 0 ) + { + TxPrintf( "\tSimFindOneNode: bad transistor terminal number\n" ); + goto use_name; + } + + ret.nd_name = SimTxtorLabel( tNum, &sx->scx_trans, &transistor ); + ret.nd_what = ND_NAME; + } + else /* no transistors found, get the regions labels */ + { + SimAddNodeList( reg ); + SimAddDefList( def ); + + use_name: + ExtLabelOneRegion( def, ExtCurStyle->exts_nodeConn, reg ); + ret.nd_region = reg; + ret.nd_what = ND_REGION; + } + return( &ret ); +} + + +/* + *---------------------------------------------------------------- + * SimGetNodeName + * + * This procedure uses the Magic circuit extraction code to generate + * the node name. The node is extracted by searching the database + * for all tiles electrically connected to the node. Each tile is + * marked with a pointer to the node region it belongs to. It is + * the node region data structure which contains the labels for a + * node. The "preferred" label for the node is taken, and this + * is combined with the path name to produce the complete node name. + * + * Results: + * A pointer to the node name is returned. This is a pointer to + * statically allocated memory, so subsequent calls to this procedure + * will change the node name the returned pointer references. + * + * Side effects: + * Any node region created is added to the node region list. + *---------------------------------------------------------------- + */ + +char * +SimGetNodeName(sx, tp, path) + SearchContext *sx; /* current search context */ + Tile *tp; /* tile in this cell which is part + * of the node + */ + char *path; /* path name of hierarchy of search */ +{ + CellDef *def = sx->scx_use->cu_def; + NodeRegion *nodeList; + LabelList *ll; + static char nodename[256]; + char buff[256]; + char *text; + char *nname; + + SimSawAbortString = FALSE; + + if( SimUseCoords && simExtStyle != ExtCurStyle ) + SimInitConnTables(); + + /* check to see if this tile has been extracted before */ + + if (tp->ti_client == extUnInit) + { + NodeSpec *ns; + + ns = SimFindOneNode(sx, tp); + if( ns->nd_what == ND_NAME ) + { + SimSawAbortString = TRUE; + return( ns->nd_name ); + } + nodeList = ns->nd_region; + } + else + { + nodeList = (NodeRegion *)(tp->ti_client); + } + + /* generate the node name from the label region and the path name */ + + text = extNodeName((LabRegion *)nodeList); + strcpy(buff, text); + strcpy(nodename, path); + strcat(nodename, text); + + /* check to see if we should abort the search on the node name */ + + if (!SimInitGetnode) { + if (HashLookOnly(&SimGetnodeTbl, buff) != (HashEntry *) NULL) { + SimSawAbortString = TRUE; + if (HashLookOnly(&SimAbortSeenTbl, buff) == (HashEntry *) NULL) { + HashFind(&SimAbortSeenTbl, buff); + TxPrintf("Node name search aborted on \"%s\"\n", buff); + } + } + } + + /* Check whether or not to print out node name aliases. Each alias + * found is hashed in a table in order to suppress printing of + * duplicate aliases. + */ + + if (SimGetnodeAlias && SimIsGetnode) { + if (HashLookOnly(&SimGNAliasTbl, nodename) == (HashEntry *) NULL) { + HashFind(&SimGNAliasTbl, nodename); +#ifdef MAGIC_WRAPPER + Tcl_AppendElement(magicinterp, nodename); +#else + TxPrintf("alias: %s\n", nodename); +#endif + } + } + + /* search the list of all labels for this node, creating the full + * node name and returning the "best" node name found. + */ + for (ll = nodeList->nreg_labels; ll; ll = ll->ll_next) { + if (ll->ll_label->lab_text == text) { + for (ll = ll->ll_next; ll; ll = ll->ll_next) { + nname = ll->ll_label->lab_text; + if (extLabType(nname, LABTYPE_NAME)) { + strcpy(nodename, path); + strcat(nodename, nname); + if (efPreferredName(nname, buff)) { + strcpy(buff, nname); + } + if (SimGetnodeAlias && SimIsGetnode) { + if (HashLookOnly(&SimGNAliasTbl, nodename) + == (HashEntry *) NULL) { + HashFind(&SimGNAliasTbl, nodename); +#ifdef MAGIC_WRAPPER + Tcl_AppendElement(magicinterp, nodename); +#else + TxPrintf("alias: %s\n", nodename); +#endif + } + } + } + } + break; + } + } + strcpy(nodename, path); + strcat(nodename, buff); + return(nodename); +} + +/* + *---------------------------------------------------------------- + * SimGetNodeCleanup + * + * This procedure is called to clean up the data structures and the + * tile database after a node name is extracted. + * + * Results: + * None. + * + * Side effects: + * The node region list and cell def lists are re-initialized. + *---------------------------------------------------------------- + */ + +void +SimGetNodeCleanUp() +{ + SimFreeNodeRegs(); + SimInitDefList(); +} diff --git a/sim/SimRsim.c b/sim/SimRsim.c new file mode 100644 index 00000000..7e5b88f6 --- /dev/null +++ b/sim/SimRsim.c @@ -0,0 +1,939 @@ +/* + * SimRsim.c - + * + * This file provides routines for Magic to communicate with Rsim/Irsim. + * Communications takes place using two pipes, one for Magic to + * send a command to the simulator, the other to get back the reply. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * of California. All rights reserved. + * + */ + +#ifdef RSIM_MODULE + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/stack.h" +#include "utils/geometry.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/signals.h" +#include "utils/styles.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "sim/sim.h" +#include + +static bool InitRsim(); + +#define BUF_SIZE 1024 +#define LINEBUF_SIZE 256 +#define READBUF_SIZE 4096 + LINEBUF_SIZE + +#define E_RUNNING "Simulator already running.\n" +#define E_PIPE1OP "Could not create Magic to Rsim pipe.\n" +#define E_PIPE2OP "Could not create Rsim to Magic pipe.\n" +#define E_NOFORK "Could not fork process.\n" +#define E_NOSTART "Rsim not started.\n" +#define E_PIPERD "Error reading pipe from Rsim.\n" +#define E_PIPEWR "Could not write on pipe to Rsim.\n" + +#define P_READ 0 +#define P_WRITE 1 + +static int status; +static int pipeIn; /* Rsim --> Magic */ +static int pipeOut; /* Magic --> Rsim */ +static char keyBoardBuf[BUF_SIZE]; +static bool RsimJustStarted = TRUE; +static char rsim_prompt[20]; +static int prompt_len; +static int rsim_pid; + +bool SimRsimRunning = FALSE; +bool SimHasCoords = FALSE; +bool SimGetReplyLine(); + +/* Forward declaration */ +void SimStopRsim(); + +/* + *----------------------------------------------------------------------- + * SimGetNodeCommand + * + * This function returns the "full" name of the rsim command if 'cmd' + * should be applied to the selected node(s) or NULL if the command + * should be shipped without any node names. + * + * Results: + * A ptr to the command name or NULL. + * + * Side effects: + * None. + *----------------------------------------------------------------------- + */ + +char * +SimGetNodeCommand(cmd) + char *cmd; +{ + /* This table is used to define which Rsim commands are applied to + * each node in the selection. Depending on the command, you + * woudn't want to send a command to rsim for each node. For example + * given the "s" command (to step the clock), you wouldn't want to + * step the clock once for every node in the selection. + */ + + static char *RsimNodeCommands[] = + { + "?", + "!", + "analyzer", + "d", + "h", + "l", + "path", + "t", + "u", + "w", + "x", + NULL + }; + int cmdNum; + + cmdNum = Lookup( cmd, RsimNodeCommands ); + cmd = (cmdNum >= 0) ? RsimNodeCommands[cmdNum] : (char *) NULL; + + return( cmd ); +} + + +/* + *----------------------------------------------------------------------- + * SimStartRsim + * + * This procedure is used to fork the rsim process. It takes a list of + * arguements to pass to rsim when initiating the fork. The + * environment variable RSIM is first checked to find the pathname for + * rsim/irsim. If this variable does not exist, then BIN_DIR/irsim + * is then used. + * + * Results: + * TRUE if the fork was successful. + * + * Side effects: + * None. + *----------------------------------------------------------------------- + */ + +bool +SimStartRsim(argv) + char *argv[]; /* list of rsim args for the fork */ +{ + + int child; + int magToRsimPipe[2]; + int rsimToMagPipe[2]; + char *getenv(); + char rsimfile[256]; + char *cad = BIN_DIR; + char *src, *dst; + + /* don't start another rsim if one is already running */ + + if (SimRsimRunning) { + TxPrintf(E_RUNNING); + return(FALSE); + } + + /* Create the pipes. One is for Magic sending to rsim, the other + * is for rsim sending to Magic. + */ + + if (pipe(magToRsimPipe) < 0) { + TxPrintf(E_PIPE1OP); + return(FALSE); + } + + if (pipe(rsimToMagPipe) < 0) { + TxPrintf(E_PIPE2OP); + return(FALSE); + } + + /* Look for rsim; check for environ var first; if none, then + * try to open the one located in BIN_DIR. + */ + + src = getenv("RSIM"); + if( src != NULL ) + strcpy(rsimfile, src); + else { + src = cad; + dst = rsimfile; + if (PaExpand(&src, &dst, 100) == -1) { + TxError ("Could not find " BIN_DIR "\n"); + return(FALSE); + } + strcat(rsimfile, "/irsim"); + } +#ifndef NO_ACCESS_CALL + if( access( rsimfile, 1 ) != 0 ) + { + TxPrintf("can not execute '%s'\n", rsimfile ); + return(FALSE); + } +#endif + + + FORK(child); +/* +#ifdef SYSV + child = fork(); +#else + child = vfork(); +#endif +*/ + if (child == -1) { + close(magToRsimPipe[P_READ]); + close(magToRsimPipe[P_WRITE]); + close(rsimToMagPipe[P_READ]); + close(rsimToMagPipe[P_WRITE]); + + TxPrintf(E_NOFORK); + return(FALSE); + } + + if (child > 0) { + + /* This is the parent */ + + SimRsimRunning = TRUE; + close(magToRsimPipe[P_READ]); + close(rsimToMagPipe[P_WRITE]); + pipeIn = rsimToMagPipe[P_READ]; + pipeOut = magToRsimPipe[P_WRITE]; + rsim_pid = child; + } + else { + + int i; + + /* This is the child */ + + close(magToRsimPipe[P_WRITE]); + close(rsimToMagPipe[P_READ]); + + dup2(magToRsimPipe[P_READ], fileno(stdin)); + dup2(rsimToMagPipe[P_WRITE], fileno(stderr)); + dup2(rsimToMagPipe[P_WRITE], fileno(stdout)); + + for( i = 3; i < 15; i++ ) + close( i ); + + /* try our best, folks..... */ + + execvp(rsimfile, argv); + _exit(5); /* pick a number, any number */ + + } + return(FALSE); /* to keep lint happy */ +} + + +/* + *----------------------------------------------------------------------- + * SimConnectRsim + * + * This procedure is called when Magic is sending commands to Rsim and + * awaiting a reply. The reply is retrieved by successive calls + * to SimGetReplyLine() which returns one line of the reply at a time. + * + * Magic sends a command to Rsim through one pipe, and + * Rsim's reply comes back from the other pipe. + * + * Results: + * None. + * + * Side effects: + * The reply generated by Rsim is printed. + * The reply buffer from SimGetReplyLine is statically allocated. + * Subsequent calls will change the contents of this buffer. + * + *----------------------------------------------------------------------- + */ + +void +SimConnectRsim(escRsim) + bool escRsim; /* TRUE if we should escape back to Magic */ +{ + static char HELLO_MSG[] = + "Type \"q\" to quit simulator or \".\" to escape back to Magic.\n"; + + char *replyLine; /* used to hold one line of the Rsim reply */ + + if (!SimRsimRunning) { + TxPrintf(E_NOSTART); + return; + } + + /* read the header of the rsim reply and determine the prompt */ + + if( RsimJustStarted ) { + if( ! InitRsim( escRsim ? NULL : HELLO_MSG ) ) + return; + } + + if (escRsim) { + RsimJustStarted = FALSE; + return; + } + + if (!RsimJustStarted) { + TxPrintf("%s", HELLO_MSG); + } + + + while (TRUE) { + + /* exceptions can toggle this flag. */ + + if (!SimRsimRunning) { + return; + } + TxPrintf("%s", rsim_prompt); + + /* Read the user's command for Rsim */ + + if (TxGetLine(keyBoardBuf, BUF_SIZE) == 0) keyBoardBuf[0] = 0; + + /* prepare the Rsim command string */ + + strcat(keyBoardBuf, "\n"); + + /* check to see if we quit Rsim or escape back to Magic */ + + if ((keyBoardBuf[0] == '.') && (keyBoardBuf[1] == '\n')) { + RsimJustStarted = FALSE; + return; + } + if ((keyBoardBuf[0] == 'q') && (keyBoardBuf[1] == '\n')) { + SimStopRsim(); + return; + } + + /* Send the command to Rsim and get the reply. */ + + if (write(pipeOut, keyBoardBuf, strlen(keyBoardBuf)) < 0) { + TxPrintf(E_PIPEWR); + SimStopRsim(); + return; + } + if (!SimGetReplyLine(&replyLine)) { + return; + } + while (replyLine != NULL) { + TxPrintf("%s\n",replyLine); + if (!SimGetReplyLine(&replyLine)) { + return; + } + } + } +} + + +/* + *----------------------------------------------------------------------- + * InitRsim + * Read the initial header from rsim and determine the prompt. + * The prompt is found by searching for the string enclosed + * the last "\n" and "> ". + * + * Results: + * Returns TRUE if rsim started correctly, else FALSE. + * + * Side effects: + * Sets the rsim prompt and length. + *----------------------------------------------------------------------- + */ + +bool +InitRsim(hello_msg) + char *hello_msg; +{ + char buff[READBUF_SIZE]; + char *last; + int nchars; + bool first_time = TRUE; + + prompt_len = 0; + do + { + nchars = 0; + last = buff; + if( SimFillBuffer( buff, &last, &nchars ) <= 0 ) + { + SimStopRsim(); /* rsim must have died */ + TxPrintf( "\n" ); + return( FALSE ); + } + buff[nchars] = '\0'; + + if( last[-1] == '>' && *last == ' ' ) + { + for( last--; last > buff && last[-1] != '\n'; last-- ); + strcpy( rsim_prompt, last ); + prompt_len = strlen( rsim_prompt ); + *last = '\0'; + } + + if( first_time ) + { + TxPrintf("Be sure your sim file matches the root cell of this window.\n"); + if( hello_msg ) + TxPrintf( "%s", hello_msg ); + first_time = FALSE; + } + if( *buff ) + TxPrintf( "%s", buff ); + + } while( prompt_len == 0 ); + + if( write( pipeOut, "has_coords\n", 11 ) < 0 ) + { + TxPrintf(E_PIPEWR); + SimStopRsim(); + return(FALSE); + } + + SimHasCoords = FALSE; + do + { + if( ! SimGetReplyLine( &last ) ) + return( FALSE ); + + if( last != NULL && strncmp( last, "YES", 3 ) == 0 ) + SimHasCoords = TRUE; + } + while( last ); + + return( TRUE ); +} + + +/* + *----------------------------------------------------------------------- + * SimStopRsim + * + * This procedure is called to kill off the Rsim process. The + * exit condition is checked and a message is printed if necessary. + * + * Results: + * None. + * + * Side effects: + * The child Rsim process is killed. + * + *----------------------------------------------------------------------- + */ + +void +SimStopRsim() +{ + int pid; + + if (SimRsimRunning) { + + /* closing the pipes to Rsim have the effect of killing it */ + + close(pipeOut); + close(pipeIn); + + /* set the Rsim state flags */ + + RsimJustStarted = TRUE; + SimRsimRunning = FALSE; + + kill(rsim_pid, SIGHUP); /* just in case rsim hangs */ + + if (WaitPid (rsim_pid, &status) == -1) + return; + pid = rsim_pid; + + switch (status & 0xFF) { + case 0 : + break; + case 2 : + TxPrintf("Simulator interrupted.\n"); + break; + default : + TxPrintf("Simulator terminated abnormally.\n"); + break; + } + } +} + + +/* + *----------------------------------------------------------------------- + * RsimErrorMsg + * + * This procedure prints out an error message. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------- + */ + +void +RsimErrorMsg() +{ + static char msg[] = "The simulator must be running before this command " + "can be executed. To do\n" + "this enter the command \"rsim \". " + "To escape back to\n" + "Magic enter \".\" in response to the simulator prompt.\n"; + + TxPrintf("%s", msg); +} + + +/* + *----------------------------------------------------------------------- + * SimRsimIt + * + * This procedure takes an Rsim command and a node name to apply + * the command to, constructs a complete Rsim command and sends it + * to Rsim to process. + * + * Results: + * None. + * + * Side effects: + * Everything is set up so that GetReplyLine() should be called + * after this routine to read the Rsim output for each node. + * The reply buffer is statically allocated. Subsequent calls will + * change the contents of this buffer. + * + *----------------------------------------------------------------------- + */ + +void +SimRsimIt(cmd, nodeName) + char *cmd; + char *nodeName; +{ + + static char cmdStr[256]; + static char cleanName[256]; + char *strptr; + + cmdStr[0] = 0; + + if (!SimRsimRunning) { + RsimErrorMsg(); + return; + } + + /* change the node name to a form Rsim will accept. That is: + * if CHANGE_SQBRACKET is defined (it really should not) then + * "[" and "]" in the path name must be changed to a "." Also, the + * trailing "#" of Magic generated node names must also be removed. + */ + + strcpy(cleanName, nodeName); + strptr = cleanName; + while (*strptr != 0) { +#ifdef CHANGE_SQBRACKET + if ((*strptr == '[') || (*strptr == ']')) *strptr = '.'; +#endif + strptr++; + } + if (*--strptr == '#') { + *strptr = 0; + } + sprintf(cmdStr, "%s %s\n", cmd, cleanName); + + /* send the command to Rsim */ + + if (write(pipeOut, cmdStr, strlen(cmdStr)) < 0) { + TxPrintf(E_PIPEWR); + SimStopRsim(); + } +} + + +/* + *----------------------------------------------------------------------- + * SimFillBuffer + * + * This procedure reads characters from Rsim via a pipe and + * places the characters into a buffer pointed by pLastChar. + * It is assumed the buffer is at least READBUF_SIZE charcters + * large, and that charCount contains the number of charcters + * which remain unprocessed in the buffer. + * If an interrupt is received while waiting for input from + * rsim, then the signal is propagated to rsim and we try the + * read again; this should get the simulator to its top level + * command parser (or kill it depending on the simulator). + * + * Results: + * Number of characters read into the buffer. + * + * Side effects: + * pLastChar is updated to point to the last valid character + * in the buffer. charCount is also updated to contain the + * total number of unprocessed characters in the buffer. + * Some i/o may take place. + * + *----------------------------------------------------------------------- + */ + +int +SimFillBuffer(buffHead, pLastChar, charCount) + char *buffHead; /* ptr to start of buffer */ + char **pLastChar; /* used to return ptr to last char + * in the buffer. + */ + int *charCount; /* number of chars in the buffer */ +{ + int charsRead = 0; + char *temp; + int n, nfd; +#if defined(SYSV) || defined(CYGWIN) || defined(__FreeBSD__) || defined(__APPLE__) + fd_set readfds, writefds, exceptfds; +#else + int nr, nex; +#endif /* SYSV */ + + struct timeval timeout; + + /* Set the timeout to 5 seconds so we don't block indefinitely if */ + /* something goes wrong with the pipe. */ + + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + /* read reply from Rsim */ + +#if defined(SYSV) || defined(CYGWIN) || defined(__FreeBSD__) || defined(__APPLE__) + FD_ZERO(&readfds); + FD_ZERO(&exceptfds); +#endif /* SYSV */ + + nfd = pipeIn + 1; + +try_again: + +#if defined(SYSV) || defined(CYGWIN) || defined(__FreeBSD__) || defined(__APPLE__) + FD_SET(pipeIn, &readfds); + FD_ZERO(&writefds); + FD_SET(pipeIn, &exceptfds); + n = select(nfd, &readfds, &writefds, &exceptfds, &timeout); + +#else /* !SYSV */ + nr = nex = 1 << pipeIn; + n = select(nfd, &nr, (int *) NULL, &nex, &timeout); + +#endif + + if (n == 0) + return 0; /* select() timed out */ + + else if (n < 0) + { + if (errno == EINTR) + { + if (SigInterruptPending) + { + kill(rsim_pid, SIGINT); + SigInterruptPending = FALSE; + } + goto try_again; + } + } + + temp = *pLastChar; + charsRead = read(pipeIn, temp, (READBUF_SIZE - 1 - *charCount)); + + if (charsRead > 0) { + temp += charsRead; + if (*charCount == 0) { + temp--; + } + *pLastChar = temp; + *charCount += charsRead; + } + ASSERT(((buffHead + READBUF_SIZE) > *pLastChar), "SimFillBuffer"); + return(charsRead); +} + +/* + *----------------------------------------------------------------------- + * SimShiftChars + * + * This procedure shifts unprocessed charcters in a buffer + * to the beginning of the buffer and updates the head and + * tail pointers to the valid buffer characters. + * + * Results: + * None. + * + * Side effects: + * Valid data in the buffer is shifted to the beginning of + * the buffer. + * + *----------------------------------------------------------------------- + */ + +void +SimShiftChars(buffStart, lineStart, lastChar) + char *buffStart; /* beginning of buffer */ + char **lineStart; /* ptr to first valid char in buffer */ + char **lastChar; /* ptr to last valid char in buffer */ +{ + char *temp; + char *temp1; + + if (buffStart == *lineStart) { + return; + } + + for (temp = buffStart, temp1 = *lineStart; temp1 <= *lastChar;) { + *temp++ = *temp1++; + } + temp--; + *lineStart = buffStart; + *lastChar = temp; +} + +/* + *----------------------------------------------------------------------- + * SimFindNewLine + * + * This procedure searches for a '\n' in the char buffer delimited by + * buffStart and buffEnd. + * + * Results: + * returns a ptr to the '\n' in the buffer. If no '\n' is found, + * NULL is returned. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------- + */ + +char * +SimFindNewLine(buffStart, buffEnd) + char *buffStart; /* first char in buffer */ + char *buffEnd; /* last char in buffer */ +{ + char *sp; + + for (sp = buffStart; sp <= buffEnd; sp++) { + if (*sp == '\n') { + return(sp); + } + } + return(NULL); +} + +/* + *----------------------------------------------------------------------- + * SimGetReplyLine + * + * This procedure returns the next line of an Rsim reply. It does this + * by maintaining a character buffer to read the Rsim reply. This + * buffer is scanned for '\n' which delimit lines, and lines are + * returned from this buffer. This routine automatically refills + * the reply buffer if no '\n' charcters are found. Head and tail + * pointers to the "unprocessed" charcters in the buffer (those + * characters beloning to a reply line in the buffer which has not + * yet been returned) are maintained. + * + * We assume that the longest line Rsim will return is less than + * 256 characters, and that at most 4K characters can be read + * from a pipe in one read call. + * + * Results: + * SimGetReplyLine returns TRUE if replyLine is a valid value, + * otherwise it is FALSE. + * If we find a line containing only the rsim prompt, replyLine + * points to a NULL pointer and TRUE is returned. + * + * Side effects: + * replyLine contains a pointer to the next Rsim reply line. + * The buffer returned by replyLine is statically allcoated, so + * subsequent calls to this routine will change this buffer. + * + *----------------------------------------------------------------------- + */ + +bool +SimGetReplyLine(replyLine) + char **replyLine; +{ + static char simReadBuff[READBUF_SIZE]; /* buffer in which to read the + * rsim reply before processing + * it. This is big enough for + * one incomplete Rsim line + * (256 chars) and for the + * additional read from the + * pipe to complete the line + * (4K chars). + */ + static char *lineStart = simReadBuff; /* points to the first character + * of the next reply line. + */ + static char *lastChar = simReadBuff; /* points the the last valid + * char in the input buffer. + */ + static int charsInBuff = 0; /* number of characters left + * in input buffer to process. + */ + char *strptr; + char *strptr1; + + /* keep reading characters until we have at least enough for a prompt */ + + while (charsInBuff < prompt_len) { + SimShiftChars(simReadBuff, &lineStart, &lastChar); + status = SimFillBuffer(simReadBuff, &lastChar, &charsInBuff); + if (status == 0) { + /* no more characters to read; stop Rsim */ + SimStopRsim(); + *replyLine = NULL; + return(FALSE); + } + if (status < 0) { + TxPrintf(E_PIPERD); + *replyLine = NULL; + return(FALSE); + } + } + + /* check for the prompt at the end of the buffer, if found then + * reset buffer pointers and character count. + */ + + if (!(strncmp(rsim_prompt, lineStart, prompt_len))) { + lineStart = lastChar = simReadBuff; + charsInBuff = 0; + *replyLine = NULL; + return(TRUE); + } + + /* Now try to extract a line out of the buffer. */ + + strptr = SimFindNewLine(lineStart, lastChar); + + if (!strptr) { + + /* haven't found a '\n' in the buffer yet */ + + SimShiftChars(simReadBuff, &lineStart, &lastChar); + strptr1 = lastChar; + + /* keep trying to read characters until we find a '\n'; we + * are assuming rsim reply lines are no more than LINEBUF_SIZE + * characters in length. + */ + + while (TRUE) { + strptr = SimFindNewLine(lineStart, lastChar); + if ((charsInBuff > LINEBUF_SIZE) || (strptr)) { + break; + } + strptr1 = lastChar; + status = SimFillBuffer(simReadBuff, &lastChar, &charsInBuff); + if (status == 0) { + /* no more characters to read; stop Rsim */ + SimStopRsim(); + *replyLine = NULL; + return(FALSE); + } + if (status < 0) { + TxPrintf(E_PIPERD); + *replyLine = NULL; + return(FALSE); + } + } + } + + if (!strptr) { + TxPrintf("Error in SimGetReplyLine -- Rsim line longer than 256 chars\n"); + *replyLine = NULL; + return(FALSE); + } + + *strptr = 0; /* change the '\n' to a NULL */ + strptr1 = lineStart; /* string to return */ + lineStart = strptr + 1; /* start of next line */ + charsInBuff -= (strlen(strptr1) + 1); /* + 1 because of the '\n' */ + if (charsInBuff == 0) { /* reset buffer pointers */ + lineStart = lastChar = simReadBuff; + } + *replyLine = strptr1; + return(TRUE); +} + +/* ---------------------------------------------------------------------------- + * + * SimInit -- + * + * Initialize this module. + * + * Results: + * None. + * + * Side Effects: + * Just initialization. + * + * ---------------------------------------------------------------------------- + */ + +void +SimInit() +{ + static char *rsimdoc = +"You are currently using the \"rsim\" tool. The button actions are:\n\ + left - move the box so its lower-left corner is at cursor position\n\ + right - resize box by moving upper-right corner to cursor position\n\ + middle - display the Rsim node values of the selected paint\n\ +You can move or resize the box by different corners by pressing left\n\ + or right, holding it down, moving the cursor near a different corner\n\ + and clicking the other (left or right) button down then up without\n\ + releasing the initial button. Rsim must already have been started\n\ + to display the node values on the circuit.\n"; + + DBWAddButtonHandler("rsim", SimRsimHandler, STYLE_CURS_RSIM, rsimdoc); +} + +#endif /* RSIM_MODULE */ diff --git a/sim/SimSelect.c b/sim/SimSelect.c new file mode 100644 index 00000000..0320c828 --- /dev/null +++ b/sim/SimSelect.c @@ -0,0 +1,824 @@ +/* SimSelect.c - + * + * This file provides routines to make selections for Rsim by copying + * things into a special cell named "__SELECT__". It is based + * on code in the select module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * of California + */ + +#ifndef lint +static char sccsid[] = "@(#)SimSelect.c 4.14 MAGIC (Berkeley) 10/3/85"; +#endif /* not lint */ + +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "utils/undo.h" +#include "commands/commands.h" +#include "select/selInt.h" +#include "utils/main.h" +#include "utils/malloc.h" +#include "utils/signals.h" +#include "sim/sim.h" + +/* Two cells worth of information are kept around by the selection + * module. SelectDef and SelectUse are for the cells whose contents + * are the current selection. Select2Def and Select2Use provide a + * temporary working space for procedures that manipulate the selection. + * for example, Select2Def is used to hold nets or regions while they + * are being extracted by SelectRegion or SelectNet. Once completely + * extracted, information is copied to SelectDef. Changes to + * SelectDef are undo-able and redo-able (so that the undo package + * can deal with selection changes), but changes to Select2Def are + * not undo-able (undoing is always disabled when the cell is modified). + */ + +extern CellDef *SelectDef, *Select2Def; +extern CellUse *SelectUse, *Select2Use; + +typedef struct def_list_elt +{ + CellDef *dl_def; + struct def_list_elt *dl_next; + bool dl_isMarked; +} SimDefListElt; + +static SimDefListElt *SimCellLabList = (SimDefListElt *) NULL; + /* list of all the cell defs we have + * put RSIM labels in + */ + +/* Data structure for node names extracted from the current selection. For + * each node, save the node name, a tile which lies in the node, and + * the text for the label corresponding to the node's rsim value. + */ + +typedef struct TLE { + char *tl_nodeName; + Tile *tl_nodeTile; + char *tl_simLabel; + struct TLE *tl_next; +} TileListElt; + + +TileListElt *NodeList = (TileListElt *) NULL; + /* list of all nodes in the selected area */ +HashTable SimNodeNameTbl; /* node names found in the selected area */ +HashTable SimGetnodeTbl; /* node names to abort name search on */ +HashTable SimGNAliasTbl; /* node name aliases found during search */ +HashTable SimAbortSeenTbl; /* aborted node names found during search */ + +bool SimRecomputeSel = TRUE; /* selection has changed */ +bool SimInitGetnode = TRUE; /* Getnode called for the 1st time */ +bool SimGetnodeAlias = FALSE; /* if node aliases are to be printed */ +bool SimSawAbortString; /* if saw string to abort name search */ +bool SimIsGetnode; /* true if command was issued from Getnode */ +bool SimUseCoords; /* true if we should use trans. position */ +bool SimIgnoreGlobals = TRUE; /* If FALSE, node names ending in "!" */ + /* are treated as global node names. */ + +#ifndef RSIM_MODULE +bool SimRsimRunning = FALSE; /* Always false if there's no rsim module */ +#endif + +/* + * ---------------------------------------------------------------------------- + * + * SimSelectNode -- + * + * This procedure selects an entire node. It is similar to SelectNet. + * + * Results: + * Returns the node name. + * + * Side effects: + * Starting from material of type "type" under scx, this procedure + * finds all material in all expanded cells that are electrically- + * connected to the starting material through a chain of expanded + * cells. + * + * ---------------------------------------------------------------------------- + */ + +char * +SimSelectNode(scx, type, xMask, buffer) + SearchContext *scx; /* Area to tree-search for material. The + * transform must map to EditRoot coordinates. + */ + TileType type; /* The type of material to be considered. */ + int xMask; /* Indicates window (or windows) where cells + * must be expanded for their contents to be + * considered. 0 means treat everything as + * expanded. + */ + char *buffer; /* buffer to hold node name */ +{ + TileTypeBitMask mask; + char *strptr; + + TTMaskZero(&mask); + TTMaskSetType(&mask, type); + + /* Clear out the temporary selection cell and yank all of the + * connected paint into it. + */ + + UndoDisable(); + DBCellClearDef(Select2Def); + SimTreeCopyConnect(scx, &mask, xMask, DBConnectTbl, + &TiPlaneRect, Select2Use, buffer); + UndoEnable(); + + /* Strip out path if name is global (ends with a "!") */ + /* and flag SimIgnoreGlobals is not set. */ + + if (!SimIgnoreGlobals) + { + strptr = buffer + strlen(buffer) - 1; + if (*strptr == '!') { + *strptr = '\0'; + while (strptr != buffer) { + if (*strptr == '/') { + strptr++; + break; + } + strptr--; + } + } + else { + strptr = buffer; + } + } + else + strptr = buffer; + + return(strptr); +} + +int +NullFunc() +{ + return(0); +} + +/* + * ---------------------------------------------------------------------------- + * SimFreeNodeList + * + * This procedure frees all space allocated for the node list + * data structure. + * + * Results: + * None. + * + * Side effects: + * After the list has been deallocated, the head pointer is set to + * a NULL value. + * ---------------------------------------------------------------------------- + */ + +void +SimFreeNodeList(List) + TileListElt **List; +{ + TileListElt *current; + TileListElt *temp; + + temp = *List; + while (temp != NULL) { + current = temp; + temp = temp->tl_next; + freeMagic(current->tl_nodeName); + freeMagic(current); + } + *List = (TileListElt *) NULL; +} + +TileListElt * +simFreeNodeEntry(list, entry) + TileListElt *list, *entry; +{ + TileListElt *prev, *curr; + + prev = list; + for( curr = prev->tl_next; curr != NULL; prev = curr,curr = curr->tl_next ) + if( curr == entry ) + { + prev->tl_next = curr->tl_next; + freeMagic( entry->tl_nodeName ); + freeMagic( entry ); + return( prev ); /* next element in list */ + } + + /* should never get here */ + return(entry); +} + +/* + * ---------------------------------------------------------------------------- + * SimSelectArea + * + * This procedure checks the current selected paint in the circuit and + * extracts the names of all the nodes in the selected area. + * + * Results: + * Returns a list of node name data structures. + * + * Side Effects: + * The tiles of the selection cell definition are first marked in the + * search algorithm. After finishing the search, these marks are + * erased. + * + * ---------------------------------------------------------------------------- + */ + +TileListElt * +SimSelectArea(Rect *rect) +{ + int plane; + int SimSelectFunc(); + + /* only need to extract node names if the selection has changed or + * if node aliases are to be printed. + */ + + if (SimRecomputeSel || (SimGetnodeAlias && SimIsGetnode)) { + SimFreeNodeList(&NodeList); + HashInit(&SimAbortSeenTbl, 20, HT_STRINGKEYS); + + /* find all nodes in the current selection */ + + for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++) + { + (void) DBSrPaintArea((Tile *) NULL, SelectDef->cd_planes[plane], + &TiPlaneRect, &DBAllButSpaceAndDRCBits, + SimSelectFunc, (ClientData) &NodeList); + } + + HashKill(&SimAbortSeenTbl); + ExtResetTiles(SelectDef, (ClientData) CLIENTDEFAULT); + SimGetNodeCleanUp(); + SimRecomputeSel = FALSE; + } + if (SigInterruptPending) { + + /* if caught an interrupt, be sure to recompute the selection + * next time around. + */ + + SimRecomputeSel = TRUE; + } + return(NodeList); +} + + +/* + * ---------------------------------------------------------------------------- + * SimSelectFunc + * + * This procedure is called for each tile in the current selection. + * It first checks to see if the node the tile belongs to has not + * yet been visited. If it has not been visited, then the node name + * is extracted and all other tiles in the selection which belong to + * this node are marked. + * + * Results: + * Return 0 to keep the search going. + * + * Side effects: + * The tiles in the selection cell definition are left marked. + * It is the responsibility of the calling function to erase these + * tile marks when finished. + * ---------------------------------------------------------------------------- + */ + +int +SimSelectFunc(tile, pHead) + Tile *tile; /* Tile in SelectDef. */ + TileListElt **pHead; /* list of node names found */ +{ + TileTypeBitMask mask; + SearchContext scx; + DBWclientRec *crec; + MagWindow *window; + char nameBuff[256], *nodeName; + TileListElt *newNodeTile; + TileType type; + bool coord; + + window = CmdGetRootPoint((Point *) NULL, &scx.scx_area); + if (window == NULL) return 1; + + /* check to see if the node has already been extracted */ + + if (tile->ti_client == (ClientData) 1) { + return(0); + } + + if (IsSplit(tile)) + { + type = (SplitSide(tile)) ? SplitRightType(tile): + SplitLeftType(tile); + } + else + type = TiGetTypeExact(tile); + + /* get the tile's area, and initialize the tile's search context. */ + + TITORECT(tile, &scx.scx_area); + + /* make sure that search context isn't placed on an empty */ + /* corner of a split tile. */ + if (IsSplit(tile)) + { + if (SplitSide(tile)) + scx.scx_area.r_xbot = scx.scx_area.r_xtop - 1; + if (!(SplitDirection(tile) ^ SplitSide(tile))) + scx.scx_area.r_ybot = scx.scx_area.r_ytop - 1; + } + + scx.scx_area.r_xtop = scx.scx_area.r_xbot + 1; + scx.scx_area.r_ytop = scx.scx_area.r_ybot + 1; + + scx.scx_use = (CellUse *) window->w_surfaceID; + scx.scx_trans = GeoIdentityTransform; + crec = (DBWclientRec *) window->w_clientData; + + TTMaskZero(&mask); + TTMaskSetType(&mask, type); + TTMaskAndMask(&mask, &crec->dbw_visibleLayers); + TTMaskAndMask(&mask, &DBAllButSpaceAndDRCBits); + + /* Check if the area is above a layer which is not visible. */ + + if (TTMaskIsZero(&mask)) { + return(0); + } + + /* mark all other tiles in the selection that are part of this node */ + + SimSrConnect(SelectDef, &scx.scx_area, &DBAllButSpaceAndDRCBits, + DBConnectTbl, &TiPlaneRect, NullFunc, (ClientData) NULL); + + /* Pick a tile type to use for selection. */ + + for (type = TT_TECHDEPBASE; type < DBNumTypes; type += 1) + { + if (TTMaskHasType(&mask, type)) break; + } + + nodeName = SimSelectNode(&scx, type, CU_DESCEND_ALL, nameBuff); + + /* add the node name to the list only if it has not been seen yet */ + + coord = (nodeName[0] == '@' && nodeName[1] == '=') ? TRUE : FALSE; + + if(coord || HashLookOnly(&SimNodeNameTbl, nodeName) == (HashEntry *) NULL) + { + if( ! coord ) + HashFind(&SimNodeNameTbl, nodeName); + newNodeTile = (TileListElt *) mallocMagic((unsigned) (sizeof (TileListElt))); + newNodeTile->tl_nodeName = (char *) mallocMagic((unsigned) (strlen(nodeName) + 1)); + strcpy(newNodeTile->tl_nodeName, nodeName); + newNodeTile->tl_nodeTile = tile; + newNodeTile->tl_next = *pHead; + *pHead = newNodeTile; + } + return(0); +} + +#ifdef RSIM_MODULE + +/* + * ---------------------------------------------------------------------------- + * SimSelection + * + * This procedure applies the specified rsim command to the list of + * nodes in the current selection and also attaches the rsim node + * value string to each node. + * + * Results: + * returns FALSE if no nodes are in the selection. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +SimSelection(cmd) + char *cmd; /* rsim command to apply to the selection */ +{ + static char Hstring[] = "RSIM=1"; + static char Lstring[] = "RSIM=0"; + static char Xstring[] = "RSIM=X"; + static char QUESTstring[] = "?"; + + char timeString[256]; + TileListElt *current, *node_list; + char *replyLine; + char *strPtr; + bool goodReply; + + extern RsimErrorMsg(); + + timeString[0] = 0; + + /* check to see if Rsim has been started yet */ + + if (!SimRsimRunning) { + RsimErrorMsg(); + return(FALSE); + } + + /* get the list of all nodes in the selection */ + + SimIsGetnode = FALSE; + SimUseCoords = SimHasCoords; + + HashInit(&SimNodeNameTbl, 60, HT_STRINGKEYS); + node_list = SimSelectArea((Rect *)NULL); + + if (node_list == (TileListElt *) NULL) { + TxPrintf("You must select paint (rather than a cell) to use Rsim on \ +the selection.\n"); + goto bad; + } + + /* Walk the list of node names, apply the rsim command to each node, + * and then process the results. + */ + + for (current = node_list; current != NULL; current = current->tl_next) + { + current->tl_simLabel = QUESTstring; + SimRsimIt(cmd, current->tl_nodeName); + + if (!SimGetReplyLine(&replyLine)) { + goto bad; + } + + if (!replyLine) { + /* Rsim's reponse to the command was just a prompt. We are done + * with the current node, so process the next node in the + * selection. + */ + continue; + } + + /* check for node names not recognized by Rsim */ + + if (strncmp(replyLine, "time = ", 7) == 0) { + if (timeString[0] == 0) { + strcpy(timeString, replyLine); + } + TxPrintf("%s not recognized in sim file\n", current->tl_nodeName); + while(replyLine) { + /* swallow Rsim reply until no more is left */ + if (!SimGetReplyLine(&replyLine)) { + goto bad; + } + } + continue; + } + + /* update the node value label strings */ + + if (*cmd == 'd') + { + char *name = current->tl_nodeName; + bool coord = (name[0] == '@' && name[1] == '=') ? TRUE : FALSE; + + strPtr = strrchr( replyLine, '=' ); + if( strPtr == NULL ) + strPtr = QUESTstring; + else if( coord ) + { + *strPtr = '\0'; + name = replyLine; + if( HashLookOnly(&SimNodeNameTbl, name) == (HashEntry *) NULL) + { + freeMagic(current->tl_nodeName); + current->tl_nodeName = (char *) mallocMagic((unsigned) (strlen(name) + 1)); + strcpy(current->tl_nodeName, name); + HashFind(&SimNodeNameTbl, current->tl_nodeName); + *strPtr++ = '='; + } + else + { + current = simFreeNodeEntry( node_list, current ); + *strPtr = '='; + } + } + else + strPtr++; + + switch (*strPtr) { + case '1' : + current->tl_simLabel = Hstring; + break; + case '0' : + current->tl_simLabel = Lstring; + break; + case 'X' : + current->tl_simLabel = Xstring; + break; + case '=' : + break; + default : + current->tl_simLabel = QUESTstring; + break; + } + } + + /* read all lines of the Rsim reply */ + + goodReply = TRUE; + for (;replyLine; goodReply = SimGetReplyLine(&replyLine)) { + if (!goodReply) { + goto bad; + } + if (!strncmp(replyLine, "time = ", 7)) { + if (!(timeString[0])) { + strcpy(timeString, replyLine); + } + continue; + } else if( *strPtr != '=' ) { + TxPrintf("%s\n", replyLine); + } + } + } + if (timeString[0] != 0) { + TxPrintf("%s\n", timeString); + } + + HashKill(&SimNodeNameTbl); + return(TRUE); + + bad: + HashKill(&SimNodeNameTbl); + return(FALSE); +} + + +#endif + +/* + * ---------------------------------------------------------------------------- + * SimAddLabels + * + * This procedure adds the node value labels to the Magic database + * so they will be displayed in the layout. + * + * Results: + * None. + * + * Side effects: + * The cell modified flags are deliberately not set when these labels + * are added to the database. + * + * ---------------------------------------------------------------------------- + */ + +void +SimAddLabels(SelectNodeList, rootuse) + TileListElt *SelectNodeList; + CellDef *rootuse; /* the root cell def for the window */ +{ + + TileListElt *current; + Rect selectBox; + int pos; + + /* walk the list of selected nodes, add the node value label to the + * database. + */ + + for (current = SelectNodeList; current != (TileListElt *) NULL; + current = current->tl_next) { + if (*(current->tl_simLabel) == '?') { + continue; + } + TiToRect(current->tl_nodeTile, &selectBox); + pos = SimPutLabel(rootuse, &selectBox, GEO_CENTER, + current->tl_simLabel, TT_SPACE); + DBReComputeBbox(rootuse); + DBWLabelChanged(rootuse, current->tl_simLabel, &selectBox, + pos, DBW_ALLWINDOWS); + } +} + +#ifdef RSIM_MODULE + +/* + * ---------------------------------------------------------------------------- + * SimRsimMouse + * + * This procedure erases the old rsim node labels and display the + * node labels of the current selection. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +SimRsimMouse(w) + MagWindow *w; +{ + + CellUse *cu; + bool sawcell; + SimDefListElt *dummy; + + if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID)) + { + TxError("Put the cursor in a layout window\n"); + return; + } + + cu = (CellUse *)w->w_surfaceID; /* get root cell use for wind */ + + /* check to see if the cell def is already in our list */ + sawcell = FALSE; + for (dummy = SimCellLabList; dummy; dummy = dummy->dl_next) { + if (dummy->dl_def == cu->cu_def) { + sawcell = TRUE; + break; + } + } + + if (!sawcell) { + /* add the cell def to the list */ + if (SimCellLabList == (SimDefListElt *) NULL) { + SimCellLabList = (SimDefListElt *) mallocMagic((unsigned) (sizeof(SimDefListElt))); + SimCellLabList->dl_isMarked = FALSE; + SimCellLabList->dl_def = cu->cu_def; + SimCellLabList->dl_next = (SimDefListElt *) NULL; + dummy = SimCellLabList; + } + else { + dummy = (SimDefListElt *) mallocMagic((unsigned) (sizeof(SimDefListElt))); + dummy->dl_isMarked = FALSE; + dummy->dl_next = SimCellLabList; + dummy->dl_def = cu->cu_def; + SimCellLabList= dummy; + } + } + + SimEraseLabels(); + if (SimSelection("d")) { + dummy->dl_isMarked = TRUE; + SimAddLabels(NodeList, dummy->dl_def); + } +} + +#endif + +/* + * ---------------------------------------------------------------------------- + * SimGetnode + * + * This procedure prints the node names of all selected nodes. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +SimGetnode() +{ + TileListElt *current; + + /* get the list of node names */ + + SimIsGetnode = TRUE; + SimUseCoords = FALSE; + + HashInit(&SimNodeNameTbl, 60, HT_STRINGKEYS); + current = SimSelectArea((Rect *)NULL); + HashKill(&SimNodeNameTbl); + + if (current == (TileListElt *) NULL) { + TxPrintf("You must select paint (not a cell) to use getnode.\n"); + return; + } + + for (; current != (TileListElt *) NULL; current = current->tl_next) + { +#ifdef MAGIC_WRAPPER + /* Return the node name as the result of the command */ + Tcl_AppendElement(magicinterp, current->tl_nodeName); +#else + TxPrintf("node name : %s\n", current->tl_nodeName); +#endif + } +} + +/* + * ---------------------------------------------------------------------------- + * SimGetsnode + * + * This procedure prints the short node names of all selected nodes. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +SimGetsnode() +{ + TileListElt *current; + + /* get the list of node names */ + + SimIsGetnode = TRUE; + SimUseCoords = TRUE; + + HashInit(&SimNodeNameTbl, 60, HT_STRINGKEYS); + current = SimSelectArea((Rect *)NULL); + HashKill(&SimNodeNameTbl); + + if (current == (TileListElt *) NULL) { + TxPrintf("You must select paint (not a cell) to use getnode.\n"); + return; + } + + for (; current != (TileListElt *) NULL; current = current->tl_next) + { +#ifdef MAGIC_WRAPPER + /* Return the node short name as the result of the command */ + Tcl_AppendElement(magicinterp, current->tl_nodeName); +#else + TxPrintf("short node name : %s\n", current->tl_nodeName); +#endif + } +} + + + +/* + * ---------------------------------------------------------------------------- + * SimEraseLabels + * + * This procedure erases the RSIM labels from any cell defs they + * may have been added to. + * + * Results: + * None. + * + * Side effects: + * Removes the RSIM labels from "marked" cell defs. + * + * ---------------------------------------------------------------------------- + */ + +void +SimEraseLabels() +{ + SimDefListElt *p; + + for (p = SimCellLabList; p; p = p->dl_next) { + if (p->dl_isMarked) { + p->dl_isMarked = FALSE; + DBEraseLabelsByContent(p->dl_def, (Rect *)NULL, -1, "RSIM=X"); + DBEraseLabelsByContent(p->dl_def, (Rect *)NULL, -1, "RSIM=1"); + DBEraseLabelsByContent(p->dl_def, (Rect *)NULL, -1, "RSIM=0"); + } + } +} diff --git a/sim/SimSelect.c.new b/sim/SimSelect.c.new new file mode 100644 index 00000000..2dcca425 --- /dev/null +++ b/sim/SimSelect.c.new @@ -0,0 +1,915 @@ +/* SimSelect.c - + * + * This file provides routines to make selections for Rsim by copying + * things into a special cell named "__SELECT__". It is based + * on code in the select module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * of California + */ + +#ifndef lint +static char sccsid[] = "@(#)SimSelect.c 4.14 MAGIC (Berkeley) 10/3/85"; +#endif /* not lint */ + +#include +#ifdef SYSV +#include +#else +#include +#endif + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "undo/undo.h" +#include "commands/commands.h" +#include "select/selInt.h" +#include "main/main.h" +#include "utils/malloc.h" +#include "utils/signals.h" +#include "sim/sim.h" + +/* Two cells worth of information are kept around by the selection + * module. SelectDef and SelectUse are for the cells whose contents + * are the current selection. Select2Def and Select2Use provide a + * temporary working space for procedures that manipulate the selection. + * for example, Select2Def is used to hold nets or regions while they + * are being extracted by SelectRegion or SelectNet. Once completely + * extracted, information is copied to SelectDef. Changes to + * SelectDef are undo-able and redo-able (so that the undo package + * can deal with selection changes), but changes to Select2Def are + * not undo-able (undoing is always disabled when the cell is modified). + */ + +extern CellDef *SelectDef, *Select2Def; +extern CellUse *SelectUse, *Select2Use; + +typedef struct def_list_elt +{ + CellDef *dl_def; + struct def_list_elt *dl_next; + bool dl_isMarked; +} SimDefListElt; + +static SimDefListElt *SimCellLabList = (SimDefListElt *) NULL; + /* list of all the cell defs we have + * put RSIM labels in + */ + +/* Data structure for node names extracted from the current selection. For + * each node, save the node name, a tile which lies in the node, and + * the text for the label corresponding to the node's rsim value. + */ + +typedef struct TLE { + char *tl_nodeName; + Tile *tl_nodeTile; + char *tl_simLabel; + struct TLE *tl_next; +} TileListElt; + + +TileListElt *NodeList = (TileListElt *) NULL; + /* list of all nodes in the selected area */ +HashTable SimNodeNameTbl; /* node names found in the selected area */ +HashTable SimGetnodeTbl; /* node names to abort name search on */ +HashTable SimGNAliasTbl; /* node name aliases found during search */ +HashTable SimAbortSeenTbl; /* aborted node names found during search */ + +bool SimRecomputeSel = TRUE; /* selection has changed */ +bool SimInitGetnode = TRUE; /* Getnode called for the 1st time */ +bool SimGetnodeAlias = FALSE; /* if node aliases are to be printed */ +bool SimSawAbortString; /* if saw string to abort name search */ +bool SimIsGetnode; /* true if command was issued from Getnode */ +bool SimUseCoords; /* true if we should use trans. position */ +bool SimIgnoreGlobals = TRUE; /* If FALSE, node names ending in "!" */ + /* are treated as global node names. */ + +#ifndef RSIM_MODULE +bool SimRsimRunning = FALSE; /* Always false if there's no rsim module */ +#endif + +/* + * ---------------------------------------------------------------------------- + * + * SimSelectNode -- + * + * This procedure selects an entire node. It is similar to SelectNet. + * + * Results: + * Returns the node name. + * + * Side effects: + * Starting from material of type "type" under scx, this procedure + * finds all material in all expanded cells that are electrically- + * connected to the starting material through a chain of expanded + * cells. + * + * ---------------------------------------------------------------------------- + */ + +char * +SimSelectNode(scx, type, xMask, buffer) + SearchContext *scx; /* Area to tree-search for material. The + * transform must map to EditRoot coordinates. + */ + TileType type; /* The type of material to be considered. */ + int xMask; /* Indicates window (or windows) where cells + * must be expanded for their contents to be + * considered. 0 means treat everything as + * expanded. + */ + char *buffer; /* buffer to hold node name */ +{ + TileTypeBitMask mask; + char *strptr; + + TTMaskZero(&mask); + TTMaskSetType(&mask, type); + + /* Clear out the temporary selection cell and yank all of the + * connected paint into it. + */ + + UndoDisable(); + DBCellClearDef(Select2Def); + SimTreeCopyConnect(scx, &mask, xMask, DBConnectTbl, + &TiPlaneRect, Select2Use, buffer); + UndoEnable(); + + /* Strip out path if name is global (ends with a "!") */ + /* and flag SimIgnoreGlobals is not set. */ + + if (!SimIgnoreGlobals) + { + strptr = buffer + strlen(buffer) - 1; + if (*strptr == '!') { + *strptr = '\0'; + while (strptr != buffer) { + if (*strptr == '/') { + strptr++; + break; + } + strptr--; + } + } + else { + strptr = buffer; + } + } + else + strptr = buffer; + + return(strptr); +} + +NullFunc() +{ + return(0); +} + +/* + * ---------------------------------------------------------------------------- + * SimFreeNodeList + * + * This procedure frees all space allocated for the node list + * data structure. + * + * Results: + * None. + * + * Side effects: + * After the list has been deallocated, the head pointer is set to + * a NULL value. + * ---------------------------------------------------------------------------- + */ + +void +SimFreeNodeList(List) + TileListElt **List; +{ + TileListElt *current; + TileListElt *temp; + + temp = *List; + while (temp != NULL) { + current = temp; + temp = temp->tl_next; + freeMagic(current->tl_nodeName); + freeMagic(current); + } + *List = (TileListElt *) NULL; +} + +TileListElt * +simFreeNodeEntry(list, entry) + TileListElt *list, *entry; +{ + TileListElt *prev, *curr; + + prev = list; + for( curr = prev->tl_next; curr != NULL; prev = curr,curr = curr->tl_next ) + if( curr == entry ) + { + prev->tl_next = curr->tl_next; + freeMagic( entry->tl_nodeName ); + freeMagic( entry ); + return( prev ); /* next element in list */ + } + + /* should never get here */ + return(entry); +} + +/* + * ---------------------------------------------------------------------------- + * SimSelectArea + * + * This procedure checks the current selected paint in the circuit and + * extracts the names of all the nodes in the selected area. + * + * Results: + * Returns a list of node name data structures. + * + * Side Effects: + * The tiles of the selection cell definition are first marked in the + * search algorithm. After finishing the search, these marks are + * erased. + * + * ---------------------------------------------------------------------------- + */ + +typedef struct { + TileListElt *NodeList; + MagWindow *window; + SearchContext *scx; +} SimSelData; + + +TileListElt * +SimSelectArea(Rect *rect) +{ + int plane; + int SimSelectFunc(); + SimSelData simseldata; + SearchContext scx; + + /* only need to extract node names if the selection has changed or + * if node aliases are to be printed. + */ + + if (SimRecomputeSel || (SimGetnodeAlias && SimIsGetnode)) { + SimFreeNodeList(&NodeList); + HashInit(&SimAbortSeenTbl, 20, HT_STRINGKEYS); + + /* find all nodes in the current selection */ + + simseldata.NodeList = NodeList; + simseldata.scx = &scx; + simseldata.window = CmdGetRootPoint((Point *) NULL, &scx.scx_area); + if (rect != NULL) scx.scx_area = *rect; + if (simseldata.window != NULL) + { + for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++) + { + (void) DBSrPaintArea((Tile *) NULL, SelectDef->cd_planes[plane], + &TiPlaneRect, &DBAllButSpaceAndDRCBits, + SimSelectFunc, (ClientData) &simseldata); + } + } + + HashKill(&SimAbortSeenTbl); + ExtResetTiles(SelectDef, (ClientData) MINFINITY); + SimGetNodeCleanUp(); + SimRecomputeSel = FALSE; + } + if (SigInterruptPending) { + + /* if caught an interrupt, be sure to recompute the selection + * next time around. + */ + + SimRecomputeSel = TRUE; + } + return(NodeList); +} + + +/* + * ---------------------------------------------------------------------------- + * SimSelectFunc + * + * This procedure is called for each tile in the current selection. + * It first checks to see if the node the tile belongs to has not + * yet been visited. If it has not been visited, then the node name + * is extracted and all other tiles in the selection which belong to + * this node are marked. + * + * Results: + * Return 0 to keep the search going. + * + * Side effects: + * The tiles in the selection cell definition are left marked. + * It is the responsibility of the calling function to erase these + * tile marks when finished. + * ---------------------------------------------------------------------------- + */ + +int +SimSelectFunc(tile, simseldata) + Tile *tile; /* Tile in SelectDef. */ + SimSelData simseldata; + +{ + TileListElt **pHead; /* list of node names found */ + TileTypeBitMask mask; + SearchContext scx; + DBWclientRec *crec; + MagWindow *window; + char nameBuff[256], *nodeName; + TileListElt *newNodeTile; + TileType type; + bool coord; + + window = simseldata->window; + + /* check to see if the node has already been extracted */ + + if (tile->ti_client == (ClientData) 1) { + return(0); + } + +#ifdef NONMANHATTAN + if (IsSplit(tile)) + { + type = (SplitSide(tile)) ? SplitRightType(tile): + SplitLeftType(tile); + } + else +#endif + type = TiGetTypeExact(tile); + + /* get the tile's area, and initialize the tile's search context. */ + + TITORECT(tile, &scx.scx_area); + +#ifdef NONMANHATTAN + /* make sure that search context isn't placed on an empty */ + /* corner of a split tile. */ + if (IsSplit(tile)) + { + if (SplitSide(tile)) + scx.scx_area.r_xbot = scx.scx_area.r_xtop - 1; + if (!(SplitDirection(tile) ^ SplitSide(tile))) + scx.scx_area.r_ybot = scx.scx_area.r_ytop - 1; + } +#endif + + scx.scx_area.r_xtop = scx.scx_area.r_xbot + 1; + scx.scx_area.r_ytop = scx.scx_area.r_ybot + 1; + + scx.scx_use = (CellUse *) window->w_surfaceID; + scx.scx_trans = GeoIdentityTransform; + crec = (DBWclientRec *) window->w_clientData; + + TTMaskZero(&mask); + TTMaskSetType(&mask, type); + TTMaskAndMask(&mask, &crec->dbw_visibleLayers); + TTMaskAndMask(&mask, &DBAllButSpaceAndDRCBits); + + /* Check if the area is above a layer which is not visible. */ + + if (TTMaskIsZero(&mask)) { + return(0); + } + + /* mark all other tiles in the selection that are part of this node */ + + SimSrConnect(SelectDef, &scx.scx_area, &DBAllButSpaceAndDRCBits, + DBConnectTbl, &TiPlaneRect, NullFunc, (ClientData) NULL); + + /* Pick a tile type to use for selection. */ + + for (type = TT_TECHDEPBASE; type < DBNumTypes; type += 1) + { + if (TTMaskHasType(&mask, type)) break; + } + + nodeName = SimSelectNode(&scx, type, 0, nameBuff); + + /* add the node name to the list only if it has not been seen yet */ + + coord = (nodeName[0] == '@' && nodeName[1] == '=') ? TRUE : FALSE; + + if(coord || HashLookOnly(&SimNodeNameTbl, nodeName) == (HashEntry *) NULL) + { + if( ! coord ) + HashFind(&SimNodeNameTbl, nodeName); + newNodeTile = (TileListElt *) mallocMagic((unsigned) (sizeof (TileListElt))); + newNodeTile->tl_nodeName = (char *) mallocMagic((unsigned) (strlen(nodeName) + 1)); + strcpy(newNodeTile->tl_nodeName, nodeName); + newNodeTile->tl_nodeTile = tile; + newNodeTile->tl_next = *pHead; + *pHead = newNodeTile; + } + return(0); +} + +#ifdef RSIM_MODULE + +/* + * ---------------------------------------------------------------------------- + * SimSelection + * + * This procedure applies the specified rsim command to the list of + * nodes in the current selection and also attaches the rsim node + * value string to each node. + * + * Results: + * returns FALSE if no nodes are in the selection. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +SimSelection(cmd) + char *cmd; /* rsim command to apply to the selection */ +{ + static char Hstring[] = "RSIM=1"; + static char Lstring[] = "RSIM=0"; + static char Xstring[] = "RSIM=X"; + static char QUESTstring[] = "?"; + + char timeString[256]; + TileListElt *current, *node_list; + char *replyLine; + char *strPtr; + bool goodReply; + + extern RsimErrorMsg(); + + timeString[0] = 0; + + /* check to see if Rsim has been started yet */ + + if (!SimRsimRunning) { + RsimErrorMsg(); + return(FALSE); + } + + /* get the list of all nodes in the selection */ + + SimIsGetnode = FALSE; + SimUseCoords = SimHasCoords; + + HashInit(&SimNodeNameTbl, 60, HT_STRINGKEYS); + node_list = SimSelectArea((Rect *)NULL); + + if (node_list == (TileListElt *) NULL) { + TxPrintf("You must select paint (rather than a cell) to use Rsim on \ +the selection.\n"); + goto bad; + } + + /* Walk the list of node names, apply the rsim command to each node, + * and then process the results. + */ + + for (current = node_list; current != NULL; current = current->tl_next) + { + current->tl_simLabel = QUESTstring; + SimRsimIt(cmd, current->tl_nodeName); + + if (!SimGetReplyLine(&replyLine)) { + goto bad; + } + + if (!replyLine) { + /* Rsim's reponse to the command was just a prompt. We are done + * with the current node, so process the next node in the + * selection. + */ + continue; + } + + /* check for node names not recognized by Rsim */ + + if (strncmp(replyLine, "time = ", 7) == 0) { + if (timeString[0] == 0) { + strcpy(timeString, replyLine); + } + TxPrintf("%s not recognized in sim file\n", current->tl_nodeName); + while(replyLine) { + /* swallow Rsim reply until no more is left */ + if (!SimGetReplyLine(&replyLine)) { + goto bad; + } + } + continue; + } + + /* update the node value label strings */ + + if (*cmd == 'd') + { + char *name = current->tl_nodeName; + bool coord = (name[0] == '@' && name[1] == '=') ? TRUE : FALSE; + + strPtr = strrchr( replyLine, '=' ); + if( strPtr == NULL ) + strPtr = QUESTstring; + else if( coord ) + { + *strPtr = '\0'; + name = replyLine; + if( HashLookOnly(&SimNodeNameTbl, name) == (HashEntry *) NULL) + { + freeMagic(current->tl_nodeName); + current->tl_nodeName = (char *) mallocMagic((unsigned) (strlen(name) + 1)); + strcpy(current->tl_nodeName, name); + HashFind(&SimNodeNameTbl, current->tl_nodeName); + *strPtr++ = '='; + } + else + { + current = simFreeNodeEntry( node_list, current ); + *strPtr = '='; + } + } + else + strPtr++; + + switch (*strPtr) { + case '1' : + current->tl_simLabel = Hstring; + break; + case '0' : + current->tl_simLabel = Lstring; + break; + case 'X' : + current->tl_simLabel = Xstring; + break; + case '=' : + break; + default : + current->tl_simLabel = QUESTstring; + break; + } + } + + /* read all lines of the Rsim reply */ + + goodReply = TRUE; + for (;replyLine; goodReply = SimGetReplyLine(&replyLine)) { + if (!goodReply) { + goto bad; + } + if (!strncmp(replyLine, "time = ", 7)) { + if (!(timeString[0])) { + strcpy(timeString, replyLine); + } + continue; + } else if( *strPtr != '=' ) { + TxPrintf("%s\n", replyLine); + } + } + } + if (timeString[0] != 0) { + TxPrintf("%s\n", timeString); + } + + HashKill(&SimNodeNameTbl); + return(TRUE); + + bad: + HashKill(&SimNodeNameTbl); + return(FALSE); +} + + +#endif + +/* + * ---------------------------------------------------------------------------- + * SimAddLabels + * + * This procedure adds the node value labels to the Magic database + * so they will be displayed in the layout. + * + * Results: + * None. + * + * Side effects: + * The cell modified flags are deliberately not set when these labels + * are added to the database. + * + * ---------------------------------------------------------------------------- + */ + +void +SimAddLabels(SelectNodeList, rootuse) + TileListElt *SelectNodeList; + CellDef *rootuse; /* the root cell def for the window */ +{ + + TileListElt *current; + Rect selectBox; + int pos; + + /* walk the list of selected nodes, add the node value label to the + * database. + */ + + for (current = SelectNodeList; current != (TileListElt *) NULL; + current = current->tl_next) { + if (*(current->tl_simLabel) == '?') { + continue; + } + TiToRect(current->tl_nodeTile, &selectBox); + pos = SimPutLabel(rootuse, &selectBox, GEO_CENTER, + current->tl_simLabel, TT_SPACE); + DBReComputeBbox(rootuse); + DBWLabelChanged(rootuse, current->tl_simLabel, &selectBox, + pos, DBW_ALLWINDOWS); + } +} + +#ifdef RSIM_MODULE + +/* + * ---------------------------------------------------------------------------- + * SimRsimMouse + * + * This procedure erases the old rsim node labels and display the + * node labels of the current selection. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +SimRsimMouse(w) + MagWindow *w; +{ + + CellUse *cu; + bool sawcell; + SimDefListElt *dummy; + + if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID)) + { + TxError("Put the cursor in a layout window\n"); + return; + } + + cu = (CellUse *)w->w_surfaceID; /* get root cell use for wind */ + + /* check to see if the cell def is already in our list */ + sawcell = FALSE; + for (dummy = SimCellLabList; dummy; dummy = dummy->dl_next) { + if (dummy->dl_def == cu->cu_def) { + sawcell = TRUE; + break; + } + } + + if (!sawcell) { + /* add the cell def to the list */ + if (SimCellLabList == (SimDefListElt *) NULL) { + SimCellLabList = (SimDefListElt *) mallocMagic((unsigned) (sizeof(SimDefListElt))); + SimCellLabList->dl_isMarked = FALSE; + SimCellLabList->dl_def = cu->cu_def; + SimCellLabList->dl_next = (SimDefListElt *) NULL; + dummy = SimCellLabList; + } + else { + dummy = (SimDefListElt *) mallocMagic((unsigned) (sizeof(SimDefListElt))); + dummy->dl_isMarked = FALSE; + dummy->dl_next = SimCellLabList; + dummy->dl_def = cu->cu_def; + SimCellLabList= dummy; + } + } + + SimEraseLabels(); + if (SimSelection("d")) { + dummy->dl_isMarked = TRUE; + SimAddLabels(NodeList, dummy->dl_def); + } +} + +#endif + +/*------------------------------------------------------*/ +/* Experimental for DEF output. . . */ +/* Function "func" is a callback process for each node. */ +/* SimGetnode and SimGetsnode can both be recast as */ +/* operating off of this function. */ +/* */ +/* "func" should be cast as: */ +/* int func(Tile *tile, char *nodeName, ClientData cd); */ +/*------------------------------------------------------*/ + +void +SimProcessNode(func, shortnames, area, clientdata) + ((int *)func)(); + bool shortnames; + Rect *area; + ClientData clientdata; +{ + TileListElt *current; + + /* get the list of node names */ + + SimIsGetnode = TRUE; + SimUseCoords = shortnames; + + HashInit(&SimNodeNameTbl, 60, HT_STRINGKEYS); + current = SimSelectArea(area); + HashKill(&SimNodeNameTbl); + + if (current == (TileListElt *) NULL) { + TxPrintf("You must select paint (not a cell) to use getnode.\n"); + return; + } + + for (; current != (TileListElt *) NULL; current = current->tl_next) + if ((*func)(current->tl_nodeTile, current->tl_nodeName, clientdata) == 1) + break; +} + +/* + * ---------------------------------------------------------------------------- + * SimGetnode + * + * This procedure prints the node names of all selected nodes. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +SimGetnode() +{ + int SimGetnodeFunc(); + SimProcessNode(SimGetnodeFunc, FALSE, NULL, (ClientData)NULL); +} + +void +SimGetsnode() +{ + int SimGetnodeFunc(); + SimProcessNode(SimGetnodeFunc, TRUE, NULL, (ClientData)NULL); +} + +int +SimGetnodeFunc(tile, nodeName, clientdata) + Tile *tile; + char *nodeName; + ClientData clientdata; +{ +#ifdef MAGIC_WRAPPER + /* Return the node name as the result of the command */ + Tcl_AppendElement(magicinterp, nodeName); +#else + TxPrintf("node name : %s\n", nodeName); +#endif + return 0; /* Continue the list */ +} + +void +OLD_SimGetnode() +{ + TileListElt *current; + + /* get the list of node names */ + + SimIsGetnode = TRUE; + SimUseCoords = FALSE; + + HashInit(&SimNodeNameTbl, 60, HT_STRINGKEYS); + current = SimSelectArea((Rect *)NULL); + HashKill(&SimNodeNameTbl); + + if (current == (TileListElt *) NULL) { + TxPrintf("You must select paint (not a cell) to use getnode.\n"); + return; + } + + for (; current != (TileListElt *) NULL; current = current->tl_next) + { +#ifdef MAGIC_WRAPPER + /* Return the node name as the result of the command */ + Tcl_AppendElement(magicinterp, current->tl_nodeName); +#else + TxPrintf("node name : %s\n", current->tl_nodeName); +#endif + } +} + +/* + * ---------------------------------------------------------------------------- + * SimGetsnode + * + * This procedure prints the short node names of all selected nodes. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +OLD_SimGetsnode() +{ + TileListElt *current; + + /* get the list of node names */ + + SimIsGetnode = TRUE; + SimUseCoords = TRUE; + + HashInit(&SimNodeNameTbl, 60, HT_STRINGKEYS); + current = SimSelectArea((Rect *)NULL); + HashKill(&SimNodeNameTbl); + + if (current == (TileListElt *) NULL) { + TxPrintf("You must select paint (not a cell) to use getnode.\n"); + return; + } + + for (; current != (TileListElt *) NULL; current = current->tl_next) + { +#ifdef MAGIC_WRAPPER + /* Return the node short name as the result of the command */ + Tcl_AppendElement(magicinterp, current->tl_nodeName); +#else + TxPrintf("short node name : %s\n", current->tl_nodeName); +#endif + } +} + + + +/* + * ---------------------------------------------------------------------------- + * SimEraseLabels + * + * This procedure erases the RSIM labels from any cell defs they + * may have been added to. + * + * Results: + * None. + * + * Side effects: + * Removes the RSIM labels from "marked" cell defs. + * + * ---------------------------------------------------------------------------- + */ + +void +SimEraseLabels() +{ + SimDefListElt *p; + + for (p = SimCellLabList; p; p = p->dl_next) { + if (p->dl_isMarked) { + p->dl_isMarked = FALSE; + DBEraseLabelsByContent(p->dl_def, (Rect *)NULL, -1, -1, "RSIM=X"); + DBEraseLabelsByContent(p->dl_def, (Rect *)NULL, -1, -1, "RSIM=1"); + DBEraseLabelsByContent(p->dl_def, (Rect *)NULL, -1, -1, "RSIM=0"); + } + } +} diff --git a/sim/sim.h b/sim/sim.h new file mode 100644 index 00000000..f975b079 --- /dev/null +++ b/sim/sim.h @@ -0,0 +1,31 @@ +#ifndef _SIM_H +#define _SIM_H + +#include "utils/magic.h" + +extern char *SimGetNodeCommand(); +extern char *SimGetNodeName(); +extern char *SimSelectNode(); +extern bool SimGetReplyLine(); +extern void SimRsimIt(); +extern void SimEraseLabels(); +extern bool efPreferredName(); +extern void SimRsimHandler(); +extern void SimInit(); + +extern bool SimRecomputeSel; +extern bool SimInitGetnode; +extern bool SimGetnodeAlias; +extern bool SimSawAbortString; +extern bool SimRsimRunning; +extern bool SimIsGetnode; +extern bool SimHasCoords; +extern bool SimUseCoords; +extern bool SimIgnoreGlobals; + +extern HashTable SimNodeNameTbl; +extern HashTable SimGNAliasTbl; +extern HashTable SimGetnodeTbl; +extern HashTable SimAbortSeenTbl; + +#endif /* _SIM_H */ diff --git a/tcltk/Depend b/tcltk/Depend new file mode 100644 index 00000000..d0edf471 --- /dev/null +++ b/tcltk/Depend @@ -0,0 +1,6 @@ +tclmagic.o: tclmagic.c ../tcltk/tclmagic.h ../utils/main.h \ + ../windows/windows.h ../utils/magic.h ../utils/geometry.h \ + ../database/database.h ../tiles/tile.h ../utils/hash.h ../utils/dqueue.h \ + ../commands/commands.h ../utils/utils.h ../textio/textio.h \ + ../textio/txcommands.h ../utils/signals.h ../graphics/graphics.h \ + ../utils/malloc.h ../dbwind/dbwind.h diff --git a/tcltk/Makefile b/tcltk/Makefile new file mode 100644 index 00000000..aafaa8ae --- /dev/null +++ b/tcltk/Makefile @@ -0,0 +1,93 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/tcltk/Makefile,v 1.6 2010/06/24 12:37:56 tim Exp $ +# + +MODULE = tcltk +MAGICDIR = .. +SRCS = tclmagic.c + +include ${MAGICDIR}/defs.mak + +DFLAGS += -DMAGIC_DATE="\"`date`\"" +CLEANS += magic.sh magic.tcl magicexec magicdnull + +TCL_FILES = \ + tkcon.tcl \ + tkshell.tcl \ + wrapper.tcl \ + console.tcl \ + techbuilder.tcl \ + cellmgr.tcl \ + texthelper.tcl \ + tools.tcl \ + mazeroute.tcl \ + strip_reflibs.tcl \ + drc.tcl \ + toolkit.tcl \ + toolkit_rev0.tcl \ + bsitools.tcl \ + socketcmd.tcl \ + magic.tcl + +BIN_FILES = \ + $(DESTDIR)${BINDIR}/magic.sh \ + $(DESTDIR)${BINDIR}/ext2spice.sh \ + $(DESTDIR)${BINDIR}/ext2sim.sh + +tcl-main: magicexec magicdnull magic.tcl magic.sh ext2spice.sh ext2sim.sh + +install-tcl: magicexec magicdnull ${BIN_FILES} ${TCL_FILES} + ${RM} $(DESTDIR)${TCLDIR}/magicexec + ${CP} magicexec $(DESTDIR)${TCLDIR}/magicexec + ${RM} $(DESTDIR)${TCLDIR}/magicdnull + ${CP} magicdnull $(DESTDIR)${TCLDIR}/magicdnull + (cd $(DESTDIR)${TCLDIR}; ${RM} ${TCL_FILES}) + for i in ${TCL_FILES}; do \ + ${CP} $$i $(DESTDIR)${TCLDIR}; done + (cd $(DESTDIR)${TCLDIR}; chmod 0755 tkcon.tcl tkshell.tcl) + +magicexec: magicexec.c ${MAGICDIR}/defs.mak + ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${LDFLAGS} magicexec.c \ + -o magicexec ${LD_RUN_PATH} ${LIBS} ${LIB_SPECS} + +magicdnull: magicdnull.c ${MAGICDIR}/defs.mak + ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${LDFLAGS} magicdnull.c \ + -o magicdnull ${LD_RUN_PATH} ${LIBS} ${LIB_SPECS} + +magic.tcl: magic.tcl.in ${MAGICDIR}/defs.mak + sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \ + -e /MAGIC_VERSION/s%MAGIC_VERSION%${MAGIC_VERSION}%g \ + -e /MAGIC_REVISION/s%MAGIC_REVISION%${MAGIC_REVISION}%g \ + -e /SHDLIB_EXT/s%SHDLIB_EXT%${SHDLIB_EXT}%g magic.tcl.in > magic.tcl + +magic.sh: magic.sh.in ${MAGICDIR}/defs.mak + sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \ + -e /TCLLIB_DIR/s%TCLLIB_DIR%${TCL_LIB_DIR}%g \ + -e /WISH_EXE/s%WISH_EXE%${WISH_EXE}%g magic.sh.in > magic.sh + +ext2spice.sh: ext2spice.sh.in ${MAGICDIR}/defs.mak + sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g ext2spice.sh.in > ext2spice.sh + +ext2sim.sh: ext2sim.sh.in ${MAGICDIR}/defs.mak + sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g ext2sim.sh.in > ext2sim.sh + +$(DESTDIR)${TCLDIR}/%: % + ${RM} $(DESTDIR)${TCLDIR}/$* + ${CP} $* $(DESTDIR)${TCLDIR}/$* + +$(DESTDIR)${BINDIR}/magic.sh: magic.sh + ${RM} $(DESTDIR)${BINDIR}/magic.sh $(DESTDIR)${BINDIR}/magic + ${CP} magic.sh $(DESTDIR)${BINDIR}/magic + (cd $(DESTDIR)${BINDIR}; chmod 0755 magic) + +$(DESTDIR)${BINDIR}/ext2spice.sh: ext2spice.sh + ${RM} $(DESTDIR)${BINDIR}/ext2spice + ${CP} ext2spice.sh $(DESTDIR)${BINDIR}/ext2spice + (cd $(DESTDIR)${BINDIR}; chmod 0755 ext2spice) + +$(DESTDIR)${BINDIR}/ext2sim.sh: ext2sim.sh + ${RM} $(DESTDIR)${BINDIR}/ext2sim + ${CP} ext2sim.sh $(DESTDIR)${BINDIR}/ext2sim + (cd $(DESTDIR)${BINDIR}; chmod 0755 ext2sim) + +include ${MAGICDIR}/rules.mak diff --git a/tcltk/bsitools.tcl b/tcltk/bsitools.tcl new file mode 100644 index 00000000..97e4cff0 --- /dev/null +++ b/tcltk/bsitools.tcl @@ -0,0 +1,34 @@ +###################################################################### +# Visual Menu Helper Functions - Bertrand Irissou +###################################################################### + +### +### Add a menu button to the Magic wrapper window for the toolkit +### +proc magic::add_menu {framename toolname button_text } { + menubutton ${framename}.titlebar.mbuttons.${toolname} \ + -text $button_text \ + -relief raised \ + -menu ${framename}.titlebar.mbuttons.${toolname}.toolmenu \ + -borderwidth 2 + + menu ${framename}.titlebar.mbuttons.${toolname}.toolmenu -tearoff 0 + pack ${framename}.titlebar.mbuttons.${toolname} -side left +} + +### +### Add a command item to the toolkit menu +### +proc magic::add_menu_command {framename toolname button_text command} { + set m ${framename}.titlebar.mbuttons.${toolname}.toolmenu + $m add command -label "$button_text" -command $command +} + +### +### Add a separator to a menu +### +proc magic::add_menu_separator {framename toolname} { + set m ${framename}.titlebar.mbuttons.${toolname}.toolmenu + $m add separator +} + diff --git a/tcltk/cellmgr.tcl b/tcltk/cellmgr.tcl new file mode 100644 index 00000000..1ea0b0db --- /dev/null +++ b/tcltk/cellmgr.tcl @@ -0,0 +1,356 @@ +#------------------------------------------------------ +# Script for generating the "cell manager" window. +# +# Written by Daniel Bearden and Tim Edwards, 2009-2010 +#------------------------------------------------------ + +global Opts + +if {$::tk_version >= 8.5} { + +set Opts(cellmgr) 0 + +magic::tag select "magic::mgrselect %R" +magic::tag load "catch {magic::clearstack}; magic::cellmanager" +magic::tag getcell "magic::cellmanager" + +# Callback to the cell manager + +proc magic::instcallback {command} { + global Opts + + set rpath [ split [.cellmgr.box.view focus] "/"] + set rootdef [lindex $rpath 0] + set cellpath [lrange $rpath 1 end] + set celldef [lrange $rpath end end] + + if { $Opts(target) == "default" } { + set winlist [magic::windownames layout] + set winname [lindex $winlist 0] + } else { + set winname $Opts(target) + } + + if { $cellpath == {} } { + switch $command { + load {$winname load $rootdef} + default { + magic::select top cell + switch $command { + edit {$winname expand; $winname edit} + expand {$winname expand} + zoom {$winname view} + } + } + } + } else { + set celluse [join $cellpath "/"] + set curpath [$winname windowcaption] + set curname [lindex $curpath 2] + set curroot [lindex $curpath 0] + + switch $command { + load {$winname load $celldef} + default { + # Here: need to check first for the select cell belonging to the + # current loaded root cell (get the first use). + set defpath [list $rootdef] + foreach i $cellpath { + lappend defpath [magic::instance list celldef $i] + } + set rootpos [lsearch $defpath $curroot] + if {$rootpos < 0} { + $winname load $rootdef + set rootpos 0 + } + # set usepath [join [lrange $cellpath $rootpos end] "/"] + + set usepath [magic::findinstance .cellmgr.box.view \ + [.cellmgr.box.view selection]] + $winname select cell ${usepath} + + switch $command { + edit {$winname expand; $winname edit} + expand {$winname expand toggle} + zoom {$winname findbox zoom} + } + } + } + } +} + +# The cell manager + +proc magic::makecellmanager { mgrpath } { + + toplevel ${mgrpath} + wm withdraw ${mgrpath} + frame ${mgrpath}.actionbar + frame ${mgrpath}.box + frame ${mgrpath}.target + + ttk::treeview ${mgrpath}.box.view -show tree -selectmode browse \ + -yscrollcommand "${mgrpath}.box.vert set" \ + -xscrollcommand "${mgrpath}.box.vert set" \ + -columns 1 + scrollbar ${mgrpath}.box.vert -orient vertical -command "${mgrpath}.box.view yview" + + pack ${mgrpath}.actionbar -side top -fill x + pack ${mgrpath}.box.view -side left -fill both -expand true + pack ${mgrpath}.box.vert -side right -fill y + pack ${mgrpath}.box -side top -fill both -expand true + pack ${mgrpath}.target -side top -fill x + + button ${mgrpath}.actionbar.done -text "Zoom" -command {magic::instcallback zoom} + button ${mgrpath}.actionbar.edit -text "Edit" -command {magic::instcallback edit} + button ${mgrpath}.actionbar.load -text "Load" -command {magic::instcallback load} + button ${mgrpath}.actionbar.expand -text "Expand" -command \ + {magic::instcallback expand} + + pack ${mgrpath}.actionbar.load -side left + pack ${mgrpath}.actionbar.edit -side left + pack ${mgrpath}.actionbar.expand -side left + pack ${mgrpath}.actionbar.done -side right + + label ${mgrpath}.target.name -text "Target window:" + menubutton ${mgrpath}.target.list -text "default" \ + -menu ${mgrpath}.target.list.winmenu + + pack ${mgrpath}.target.name -side left -padx 2 + pack ${mgrpath}.target.list -side left + + .winmenu clone ${mgrpath}.target.list.winmenu + + #Withdraw the window when the close button is pressed + wm protocol ${mgrpath} WM_DELETE_WINDOW "set Opts(cellmgr) 0 ; \ + wm withdraw ${mgrpath}" + + #------------------------------------------------- + # Callback when a treeview item is opened + #------------------------------------------------- + + bind .cellmgr <> { + set s [.cellmgr.box.view selection] + # puts stdout "open $s" + foreach i [.cellmgr.box.view children $s] { + magic::addlistset $i + .cellmgr.box.view item $i -open false + } + } + + bind .cellmgr <> { + set s [.cellmgr.box.view selection] + # puts stdout "close $s" + foreach i [.cellmgr.box.view children $s] { + foreach j [.cellmgr.box.view children $i] { + .cellmgr.box.view delete $j + } + } + } +} + +proc magic::addlistentry {parent child cinst} { + if {$child != 0} { + set hiername [join [list $parent $child] "/"] + # puts stdout "listentry $hiername" + if {[.cellmgr.box.view exists $hiername] == 0} { + .cellmgr.box.view insert $parent end -id $hiername -text "$child" + .cellmgr.box.view set $hiername 0 "$cinst" + } + } +} + +proc magic::addlistset {item} { + set cellname [.cellmgr.box.view item $item -text] + set cd [magic::cellname list children $cellname] + if {$cd != 0} { + foreach i $cd { + set inst [lindex [magic::cellname list instances $i] 0] + magic::addlistentry $item $i $inst + } + } +} + +#-------------------------------------------------------------- +# Get the hierarchical name of the treeview item corresponding +# to the cell view in the window +#-------------------------------------------------------------- + +proc magic::getwindowitem {} { + set tl [magic::cellname list window] + if {![catch {set editstack}]} { + set tl [concat $editstack $tl] + } + + set pl [magic::cellname list parents [lindex $tl 0]] + while {$pl != {}} { + set tl [concat [lindex $pl 0] $tl] + set pl [magic::cellname list parents [lindex $tl 0]] + } + + set newpl "" + set parent {} + foreach j $tl { + set parent $pl + set pl "${newpl}$j" + + if {[.cellmgr.box.view exists $pl] == 0} { + .cellmgr.box.view insert $parent end -id $pl -text "$j" + set inst [lindex [magic::cellname list instances $j] 0] + .cellmgr.box.view set $pl 0 "$inst" + magic::addlistset $pl + } + .cellmgr.box.view item $pl -open true + set newpl "${pl}/" + } + return $pl +} + +#-------------------------------------------------------------- +# The cell manager window main callback function +#-------------------------------------------------------------- + +proc magic::cellmanager {{option "update"}} { + global editstack + + # Check for existence of the manager widget + if {[catch {wm state .cellmgr}]} { + if {$option == "create"} { + magic::makecellmanager .cellmgr + } else { + return + } + } elseif { $option == "create"} { + return + } + + magic::suspendall + + # determine the full cell heirarchy + set tl [magic::cellname list topcells] + foreach i $tl { + if {[file extension $i] == ".mag"} { + set nameroot [file rootname $i] + } else { + set nameroot $i + } + set nameroot [file tail $nameroot] + + if {[.cellmgr.box.view exists $i] == 0} { + .cellmgr.box.view insert {} end -id $i -text $nameroot + } + magic::addlistset $i + .cellmgr.box.view item $i -open false + } + + # Open view to current cell, generating the hierarchy as necessary. + # Accept the first hierarchy, unless the push/pop stack has been + # used. + + set pl [magic::getwindowitem] + .cellmgr.box.view selection set $pl + .cellmgr.box.view see $pl + + # Generate next level of hierarchy (not open) + + magic::addlistset $pl + .cellmgr.box.view item $pl -open false + + magic::resumeall +} + +#-------------------------------------------------------------- +# Redirect and reformat Tcl output of "select" command +#-------------------------------------------------------------- + +proc magic::mgrselect {{sstr ""}} { + # Make sure we have a valid option, and the cell manager exists. + if {$sstr == ""} { + return + } elseif {[catch {wm state .cellmgr}]} { + return + } + + set savetag [magic::tag select] + magic::tag select {} + .cellmgr.box.view selection remove [.cellmgr.box.view selection] + # puts stdout "selecting $sstr" + + if {[llength $sstr] == 5} { + # sstr is "Topmost cell in the window" + set item [magic::getwindowitem] + } else { + regsub -all {\[.*\]} $sstr {[^a-z]+} gsrch + if {[catch {set item [magic::scantree .cellmgr.box.view $gsrch]}]} { + set item "" + } + } + if {$item != ""} { + .cellmgr.box.view item $item -open false + .cellmgr.box.view selection set $item + if {[wm state .cellmgr] == "normal"} { .cellmgr.box.view see $item } + if {$sstr != ""} { + puts stdout "Selected cell is $item ($sstr)" + } + } + magic::tag select $savetag +} + +#------------------------------------------------------------ +# Given an item in the tree view, return a string of slash- +# separated instances that can be used by "select cell". +# This is effectively the inverse of magic::scantree +#------------------------------------------------------------ + +proc magic::findinstance {tree item} { + set start [magic::getwindowitem] + set start ${start}/ + set pathhead [string first $start $item] + if {$pathhead >= 0} { + set ss [expr {$pathhead -1}] + set sb [expr {[string length $start] + $pathhead}] + set pathtail [string range $item 0 $ss][string range $item $sb end] + set rpath [ split [join $pathtail] "/"] + set cinst "" + while {$rpath != {}} { + set item ${start}[lindex $rpath 0] + set rpath [lrange $rpath 1 end] + if {[string length $cinst] == 0} { + set cinst [$tree set $item 0] + } else { + set cinst ${cinst}/[$tree set $item 0] + } + set start ${item}/ + } + return $cinst + } + return {} +} + +#------------------------------------------------------------ +# Given an item in the form of a string returned by magic's +# "select list" command (list of slash-separated instances), +# find the corresponding tree item. +#------------------------------------------------------------ + +proc magic::scantree {tree item} { + set start [magic::getwindowitem] + set rpath [ split [join $item] "/"] + while {$rpath != {}} { + set pathhead [lindex $rpath 0] + set pathtail [join [lrange $rpath 1 end] "/"] + set cellname [magic::instance list celldef $pathhead] + set item [join [list $start [join $cellname]] "/"] + magic::addlistset $item + $tree set $item 0 $pathhead + $tree item $item -open true + set start $item + set item $pathtail + set rpath [ split [join $item] "/"] + } + $tree item $start -open false + return $start +} + +} ;# (if Tk version 8.5) + diff --git a/tcltk/console.tcl b/tcltk/console.tcl new file mode 100755 index 00000000..40c80c55 --- /dev/null +++ b/tcltk/console.tcl @@ -0,0 +1,135 @@ +# console.tcl: +# +# Defines Procedures which should be defined within the console +# (master) interpreter (i.e., tkcon, if it is executed as a separate +# interpreter). Note that this can always be worked around via the +# "tkcon master" or "tkcon slave" commands, but this method organizes +# things in a more natural way. + +wm geometry . 120x16+150-50 + +proc gettext {{prompt {}} {response {}}} { + + # Differentiate between console command-line and button execution + # (Determines whether to prompt before or after execution) + if {[.text index output] == [.text index end]} { + ::tkcon::Prompt + set mode 1 + } else { + set mode 0 + } + + replaceprompt "?" + if {$prompt != {}} { + .text insert end $prompt {stdout} + } + if {$response != {}} { + set result [tkcon congets $response] + } else { + set result [tkcon congets] + } + tkcon set ::tkcon::OPT(prompt1) "% " + if {$mode == 0} { + ::tkcon::Prompt + } else { + .text mark set output end + tkcon console see output ;# adjust view to encompass newline + update idletasks + } + return $result +} + +slave alias magic::dialog gettext +slave alias magic::consolegeometry wm geometry . +slave alias magic::consolefocus focus -force .text +slave alias magic::suspendout rename temp_puts puts +slave alias magic::resumeout rename puts temp_puts + +# Ensure that destroying the console window queries for saving +# modified layouts rather than forcing an immediate exit. + +wm protocol . WM_DELETE_WINDOW {tkcon slave slave magic::quit} + +proc temp_puts { args } { + # null procedure; output is suspended. +} + +proc magiccolor { ch } { + tkcon slave slave magic::magiccolor $ch +} + +proc replaceprompt { ch } { + tkcon set ::tkcon::OPT(prompt1) "$ch " + .text delete prompt.last-2c + .text insert [.text index prompt.last-1c] $ch {prompt} + .text mark set output [.text index output-1c] +} + +# This procedure repaints the magic console to match the magic colormap. +# It's only called if magic is run in 8-bit (PseudoColor) visual mode. +# This is called from inside magic (graphics/grTk1.c). + +proc repaintconsole {} { + puts stdout "Repainting console in magic layout window colors" + +# Because the console invokes a slave interpreter, we have to evaluate +# magic command "magiccolor" in the slave interpreter. Note that all of +# these colors are short names from the ".dstyle6" file. Long names are +# also acceptable. + + ::set yellow [interp eval $::tkcon::OPT(exec) magiccolor yellow2] + ::set black [interp eval $::tkcon::OPT(exec) magiccolor black] + ::set gray [interp eval $::tkcon::OPT(exec) magiccolor gray2] + ::set green [interp eval $::tkcon::OPT(exec) magiccolor green3] + ::set purple [interp eval $::tkcon::OPT(exec) magiccolor purple1] + ::set border [interp eval $::tkcon::OPT(exec) magiccolor window_border] + ::set blue [interp eval $::tkcon::OPT(exec) magiccolor blue2] + ::set red [interp eval $::tkcon::OPT(exec) magiccolor red3] + ::set bgcolor [interp eval $::tkcon::OPT(exec) magiccolor no_color_at_all] + + tkcon set ::tkcon::COLOR(bg) $bgcolor + tkcon set ::tkcon::COLOR(blink) $yellow + tkcon set ::tkcon::COLOR(cursor) $black + tkcon set ::tkcon::COLOR(disabled) $gray + tkcon set ::tkcon::COLOR(proc) $green + tkcon set ::tkcon::COLOR(var) $purple + tkcon set ::tkcon::COLOR(prompt) $border + tkcon set ::tkcon::COLOR(stdin) $black + tkcon set ::tkcon::COLOR(stdout) $blue + tkcon set ::tkcon::COLOR(stderr) $red + + .text configure -background $bgcolor + .text configure -foreground $black + .text configure -insertbackground $black + + .text tag configure var -background $bgcolor + .text tag configure blink -background $bgcolor + .text tag configure find -background $bgcolor + .text tag configure stdout -background $bgcolor + .text tag configure stderr -background $bgcolor + .text tag configure proc -background $bgcolor + .text tag configure prompt -background $bgcolor + + .text tag configure var -foreground $purple + .text tag configure blink -foreground $yellow + .text tag configure find -foreground $yellow + .text tag configure stdout -foreground $blue + .text tag configure stderr -foreground $red + .text tag configure proc -foreground $green + .text tag configure prompt -foreground $border + + .sy configure -background $bgcolor +} + +# Rewrite the ::tkcon::New procedure so that it does not attempt to +# load a second version of magic into the interpreter, which is fatal. + +rename ::tkcon::New ::tkcon::NewConsole + +proc ::tkcon::New {} { + global argv0 argc argv + + set argc 1 + list set argv $argv0 + ::tkcon::NewConsole +} diff --git a/tcltk/drc.tcl b/tcltk/drc.tcl new file mode 100644 index 00000000..3820b925 --- /dev/null +++ b/tcltk/drc.tcl @@ -0,0 +1,46 @@ +#!/bin/tclsh +#---------------------------------------------- +# Dump a file of DRC errors from magic +#---------------------------------------------- +namespace path {::tcl::mathop ::tcl::mathfunc} + +magic::suspendall +set fout [open "drc.out" w] +set oscale [cif scale out] + +select top cell +set origcell [cellname list self] +drc check +set celllist [drc list count] +puts stdout "celllist is $celllist" +puts stdout "" +flush stdout +foreach pair $celllist { + set cellname [lindex $pair 0] + set count [lindex $pair 1] + puts stdout "loading $cellname" + flush stdout + + load $cellname + select top cell + puts $fout "$cellname $count" + puts $fout "----------------------------------------" + set drcresult [drc listall why] + foreach {errtype coordlist} $drcresult { + puts $fout $errtype + puts $fout "----------------------------------------" + foreach coord $coordlist { + set bllx [* $oscale [lindex $coord 0]] + set blly [* $oscale [lindex $coord 1]] + set burx [* $oscale [lindex $coord 2]] + set bury [* $oscale [lindex $coord 3]] + set coords [format "%.3f %.3f %.3f %.3f" $bllx $blly $burx $bury] + puts $fout "$coords" + } + puts $fout "----------------------------------------" + } + puts $fout "" +} +close $fout +load $origcell +magic::resumeall diff --git a/tcltk/ext2sim.sh b/tcltk/ext2sim.sh new file mode 100644 index 00000000..8bd40c31 --- /dev/null +++ b/tcltk/ext2sim.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Standalone script for ext2sim, for Tcl-based magic 8.0 +# +# Parse arguments. "--" separates arguments to magic +# from arguments to ext2sim. +# +mgargs="" +esargs="" +for i in $@; do + case $i in + --) mgargs="$esargs" + esargs="" ;; + *) esargs="$esargs $i" ;; + esac +done +# +eval /usr/local/lib/magic/tcl/magicdnull -dnull -noconsole -nowrapper $mgargs <= 8.6} { + load -lazy TCL_DIR/tclmagicSHDLIB_EXT +} else { + load TCL_DIR/tclmagicSHDLIB_EXT +} + +# It is important to make sure no magic commands overlap with Tcl built-in +# commands, because otherwise the namespace import will fail. + +proc pushnamespace { name } { + + set y [namespace eval ${name} info commands ::${name}::*] + set z [info commands] + +# Watch especially for magic "wizard" commands, as we don't want to confuse +# the literal "*" with a regular expression *. "regsub" below takes care of it. + + foreach v $y { + regsub -all {\*} $v {\\*} i + set x [namespace tail $i] + if {[lsearch $z $x] < 0} { + namespace import $i + } + } +} + +proc popnamespace { name } { + set z [info commands] + set l [expr [string length ${name}] + 5] + + while {[set v [lsearch $z ${name}_tcl_*]] >= 0} { + set y [lindex $z $v] + set w [string range $y $l end] + interp alias {} ::$w {} + rename ::$y ::$w + puts "Info: replacing ::$w with ::$y" + } + namespace forget ::${name}::* +} + +#---------------------------------------------------------------------- +# Define the drcstate procedure expected by the background DRC code. + +proc magic::drcstate {option} { + # (Null proc---see wrapper.tcl for a useful version) +} + +#----------------------------------------------------------------- +# Define these console routines so that they don't produce errors +# when Magic is run in batch mode + +if {[catch {tkcon title}]} { + proc magic::suspendout {} {} + proc magic::resumeout {} {} + proc magic::dialog {} {} + proc magic::consolegeometry {} {} + proc magic::consolefocus {} {} +} + +#---------------------------------------------------------------------- +# Cross-Application section +#---------------------------------------------------------------------- + +# Check namespaces for existence of other applications +set UsingIRSIM 0 +set UsingXCircuit 0 +set UsingNetgen 0 +set nlist [namespace children] +foreach i $nlist { + switch $i { + ::irsim { set UsingIRSIM 1 } + ::xcircuit { set UsingXCircuit 1 } + ::netgen { set UsingNetgen 1 } + } +} + +# Setup IRSIM assuming that the Tcl version is installed. +# We do not need to rename procedure irsim to NULL because it is +# redefined in a script, which simply overwrites the original. + +proc irsim { args } { + global CAD_ROOT + set irsimscript [glob -nocomplain ${CAD_ROOT}/irsim/tcl/irsim.tcl] + if { ${irsimscript} == {} } { + puts stderr "\"irsim\" requires Tcl-based IRSIM version 9.6 or newer." + puts stderr "Could not find script \"irsim.tcl\". If IRSIM is installed in a" + puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command" + puts stderr "\"source /irsim.tcl\" before doing \"irsim\"." + } else { + source $irsimscript + eval {irsim} $args + } +} + +# Setup Xcircuit assuming that the Tcl version is installed. + +proc xcircuit { args } { + global CAD_ROOT + global argc + global argv + set xcircscript [glob -nocomplain ${CAD_ROOT}/xcircuit*/xcircuit.tcl] + if { ${xcircscript} == {} } { + puts stderr "\"xcircuit\" requires Tcl-based XCircuit version 3.1 or newer." + puts stderr "Could not find script \"xcircuit.tcl\". If XCircuit is installed in a" + puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command" + puts stderr "\"source /xcircuit.tcl\"." + } else { + # if there are multiple installed versions, choose the highest version. + if {[llength $xcircscript] > 1} { + set xcircscript [lindex [lsort -decreasing -dictionary $xcircscript] 0] + } + # execute script in the scope of magic, because its variable space is + # not modularized. + set argv $args + set argc [llength $args] + uplevel #0 source $xcircscript + } +} + +# Setup Netgen assuming that the Tcl version is installed. + +proc netgen { args } { + global CAD_ROOT + global argc + global argv + set netgenscript [glob -nocomplain ${CAD_ROOT}/netgen/tcl/netgen.tcl] + if { ${netgenscript} == {} } { + puts stderr "\"netgen\" requires Tcl-based Netgen version 1.2 or newer." + puts stderr "Could not find script \"netgen.tcl\". If Netgen is installed in a" + puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command" + puts stderr "\"source /netgen.tcl\"." + } else { + set argv $args + set argc [llength $args] + uplevel #0 source $netgenscript + } +} + +# Add the "echo" command + +proc echo {args} { + puts stdout $args +} + +# Parse argument list for "-c[onsole]" and "-now[rapper]". + +set celllist {} +set do_wrapper true +set do_recover false +set argafter {magic::initialize} +set x {} +for {set i 0} {$i < $argc} {incr i 1} { + set x [lindex $argv $i] +# +# Command-line argument handling goes here +# We have to handle all of magic's command line arguments so we can +# figure out if a cell has been named for preloading. +# + switch -regexp -- $x { + ^-now(rap)?(per)?$ { ;# This regexp accepts -now, -nowrap, and -nowrapper + set do_wrapper false + } + ^-dnull { + set do_wrapper false + lappend argafter $x + } + ^-r(e)?(cover)?$ { + set do_recover true + } + ^-rc(file)?$ { + lappend argafter $x + incr i 1 + lappend argafter [lindex $argv $i] + } + ^-d - + ^-g - + ^-m - + ^-i - + ^-T { + lappend argafter $x + incr i 1 + lappend argafter [lindex $argv $i] + } + ^-F { + lappend argafter $x + incr i 1 + lappend argafter [lindex $argv $i] + incr i 1 + lappend argafter [lindex $argv $i] + } + ^--version { + puts stdout "MAGIC_VERSION.MAGIC_REVISION" + exit 0 + } + ^--prefix { + puts stdout $CAD_ROOT + exit 0 + } + ^-D - + ^-n* { + lappend argafter $x + } + default { + lappend celllist $x + lappend argafter $x + } + } +} + +if {$do_wrapper} { + source ${CAD_ROOT}/magic/tcl/wrapper.tcl + lappend argafter "-nowindow" ;# Set no-initial-window option in magic. +} +unset x i do_wrapper +if {[catch {eval $argafter}]} { ;# magic::initialize ${argv} + exit 1 +} + +#---------------------------------------------------------------------- +# Check for presence of padlist manager script and include it + +if {[file exists ${CAD_ROOT}/magic/tcl/padlist.tcl]} { + source ${CAD_ROOT}/magic/tcl/padlist.tcl + set Opts(padlist) 0 +} + +#---------------------------------------------------------------------- +# Check for presence of the miscellaneous tools script and include it + +if {[file exists ${CAD_ROOT}/magic/tcl/tools.tcl]} { + source ${CAD_ROOT}/magic/tcl/tools.tcl + set Opts(tools) 0 +} + +#---------------------------------------------------------------------- +# Check for presence of the mazerouter script and include it + +if {[file exists ${CAD_ROOT}/magic/tcl/mazeroute.tcl]} { + source ${CAD_ROOT}/magic/tcl/mazeroute.tcl + set Opts(mazeroute) 0 +} + +#---------------------------------------------------------------------- +# Check for presence of the toolkit script and include it +# NOTE: This supercedes the older toolkit which is now +# named toolkit_rev0.tcl, and the intermediate bsitools.tcl, +# which are folded into the newer toolkit.tcl. + +if {[file exists ${CAD_ROOT}/magic/tcl/toolkit.tcl]} { + source ${CAD_ROOT}/magic/tcl/toolkit.tcl + set Opts(toolkit) 0 +} + +#---------------------------------------------------------------------- +# Magic start function drops back to interpreter after initialization & setup + +set auto_noexec 1 ;# don't EVER call UNIX commands w/o "shell" in front + +# Have we called magic from tkcon or a clone thereof? If so, set MagicConsole + +if {[lsearch [interp aliases] tkcon] != -1} { + set MagicConsole tkcon + catch {wm withdraw .} + + # Get rid of some overlapping tkcon commands which are not needed. + + if {[lsearch [info commands] orig_edit] < 0} {rename edit orig_edit} + if {[lsearch [info commands] orig_dump] < 0} {rename dump orig_dump} + if {[lsearch [info commands] orig_what] < 0} {rename what orig_what} +} else { + rename unknown tcl_unknown + proc unknown { args } { + # CAD tools special: + # Check for commands which were renamed to tcl_(command) + + set cmd [lindex $args 0] + if {[lsearch [info commands] tcl_$cmd] >= 0} { + set arglist [concat tcl_$cmd [lrange $args 1 end]] + set ret [catch {eval $arglist} result] + if {$ret == 0} { + return $result + } else { + return -code $ret -errorcode $errorCode $result + } + } + return [eval [concat tcl_unknown $args]] + } +} + +# Set up certain commands to act like they do in non-Tcl-based magic; +# These are the commands whose names have been extended so they don't +# conflict with existing Tcl/Tk commands. This renaming & importing +# *requires* the special code in the magic Tcl command dispatcher to +# find and deal with each of these renamed commands! + +if {[lsearch [info commands] orig_clock] < 0} {rename clock orig_clock} +if {[lsearch [info commands] tcl_flush] < 0} {rename flush tcl_flush} +if {[lsearch [info commands] tcl_load] < 0} {rename load tcl_load} +if {[lsearch [info commands] tcl_array] < 0} {rename array tcl_array} +if {[lsearch [info commands] tcl_label] < 0} {catch {rename label tcl_label}} +if {[lsearch [info commands] tcl_grid] < 0} {catch {rename grid tcl_grid}} + +namespace eval magic namespace export * +pushnamespace magic + +#---------------------------------------------------------------------- +# Read system startup files (mostly macro definitions) +# Read user startup file, if any +# Load initial cell, if any + +magic::startup + +if {![catch {set toptitle [wm title .]}]} { + if {[string range $toptitle 0 3] == "wish"} { + wm withdraw . + } + if {[string range $toptitle 0 8] == "magicexec"} { + wm withdraw . + } + unset toptitle +} + +# After loading, magic will wander off and do a complete DRC check +# before executing the rest of the script unless we temporarily +# disable the DRC checker. + +set drcstate [drc status] +drc off + +# Initial window for wrapper, if defined. +# empty string is equivalent to passing NULL cell name. +# +# If a startup file has created a window, then don't make another one. + +if {[info commands magic::openwrapper] != {}} { + if {[windownames layout] == {}} { + set winname [magic::openwrapper] + magic::techmanager initall + magic::scrollupdate $winname + + foreach cellname $celllist { + set fext [file extension $cellname] + puts stdout "handling file entry $cellname extension $fext" + switch $fext { + .lef - + .LEF {lef read $cellname} + .def - + .DEF {def read $cellname} + .gds - + .GDS - + .gds2 - + .GDS2 - + .gdsii - + .GDSII {gds read $cellname} + .cif - + .CIF {cif read $cellname} + .tcl {source $cellname} + .mag - + "" {magic::load $cellname} + default {puts stderr "don't know how to load file $cellname"} + } + } + } +} else { + # Initial geometry handler for the default window, non-wrapper version + catch {wm geometry .magic1 ${Opts(geometry)}} +} + +# Print the technology name and description +puts stdout "Using technology \"[tech name]\", version [lindex [tech version] 0]" + +# Set a box, and set the view; if no cell has been loaded, choose a default +# view. +if {![box exists]} { + box 0 0 1 1 ;# create a unit box +} +if {[llength $celllist] > 0} { + view +} else { + view -9 -9 10 10 +} + +# The Tcl version handles the "-r" on the command line by calling +# command crash recover. + +if {$do_recover} {crash recover} + +# Unset global TCL variables so they don't conflict with magic nodes. +unset celllist nlist do_recover + +if {$drcstate == 1} { + drc on +} +unset drcstate diff --git a/tcltk/magicdnull.c b/tcltk/magicdnull.c new file mode 100644 index 00000000..e5c83743 --- /dev/null +++ b/tcltk/magicdnull.c @@ -0,0 +1,52 @@ +/*----------------------------------------------------------------------*/ +/* magicdnull.c */ +/* */ +/* See comments for "magicexec.c". This has the same function as */ +/* magicexec.c, but does not initialize the Tk package. This avoids */ +/* bringing up a default window when "magic -dnull -noconsole" is */ +/* called, running more efficiently when used in batch mode. */ +/*----------------------------------------------------------------------*/ + +#include + +#include + +/*----------------------------------------------------------------------*/ +/* Application initiation. This is exactly like the AppInit routine */ +/* for "wish", minus the cruft, but with "tcl_rcFileName" set to */ +/* "magic.tcl" instead of "~/.wishrc". */ +/*----------------------------------------------------------------------*/ + +int +magic_AppInit(interp) + Tcl_Interp *interp; +{ + if (Tcl_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + + /* This is where we replace the home ".tclshrc" file with */ + /* magic's startup script. */ + + Tcl_SetVar(interp, "tcl_rcFileName", TCL_DIR "/magic.tcl", TCL_GLOBAL_ONLY); + + /* Additional variable can be used to tell if magic is in batch mode */ + Tcl_SetVar(interp, "batch_mode", "true", TCL_GLOBAL_ONLY); + + return TCL_OK; +} + +/*----------------------------------------------------------------------*/ +/* The main procedure; replacement for "tclsh". */ +/*----------------------------------------------------------------------*/ + +int +main(argc, argv) + int argc; + char **argv; +{ + Tcl_Main(argc, argv, magic_AppInit); + return 0; +} + +/*----------------------------------------------------------------------*/ diff --git a/tcltk/magicexec.c b/tcltk/magicexec.c new file mode 100644 index 00000000..73abbd3a --- /dev/null +++ b/tcltk/magicexec.c @@ -0,0 +1,79 @@ +/*----------------------------------------------------------------------*/ +/* magicexec.c */ +/* */ +/* Written by R. Timothy Edwards for MultiGiG, Inc., July 2004 */ +/* This file mainly lifted from the main application routine for */ +/* "wish" from the Tk distribution. */ +/* */ +/* This is a compact re-write of the "wish" executable that calls */ +/* Tk_MainEx with application-specific processing. Specifically, */ +/* "wish" doesn't allow the startup script (~/.wishrc) to be renamed. */ +/* However, for magic running as an extension of Tcl, we want to source */ +/* the magic.tcl file instead of ~/.wishrc. So, all this file really */ +/* does is to set the Tcl variable "tcl_rcFileName" to magic.tcl, so */ +/* that it will be processed as the startup script, followed by a drop */ +/* back to the Tcl interpreter command-line main loop. */ +/* */ +/* This is a standalone executable. However, it is only called when */ +/* "-noconsole" is specified on the UNIX command-line. When the */ +/* console is used, the console is capable of sourcing the magic.tcl */ +/* script itself, and so it uses "wish" as the executable. However, */ +/* the console redirects standard input, so it prevents magic from */ +/* being used in a batch processing mode. Thus, to batch-process with */ +/* magic, use "magic -noc -d NULL < script.tcl" or, interactively, */ +/* "magic -noc -d NULL << EOF" followed by commands entered from stdin */ +/* and ending with "EOF". */ +/* */ +/* The "magicexec" method replaces the former use of "wish" with the */ +/* "magic" script setting HOME to point to the directory containing */ +/* ".wishrc", a symbolic link to "magic.tcl". That failed to work on */ +/* remote systems because the $HOME environment variable is also used */ +/* to find the user's .Xauthority file to authenticate the X11 */ +/* connection. */ +/*----------------------------------------------------------------------*/ + +#include + +#include +#include + +/*----------------------------------------------------------------------*/ +/* Application initiation. This is exactly like the AppInit routine */ +/* for "wish", minus the cruft, but with "tcl_rcFileName" set to */ +/* "magic.tcl" instead of "~/.wishrc". */ +/*----------------------------------------------------------------------*/ + +int +magic_AppInit(interp) + Tcl_Interp *interp; +{ + if (Tcl_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + + if (Tk_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); + + /* This is where we replace the home ".wishrc" file with */ + /* magic's startup script. */ + + Tcl_SetVar(interp, "tcl_rcFileName", TCL_DIR "/magic.tcl", TCL_GLOBAL_ONLY); + return TCL_OK; +} + +/*----------------------------------------------------------------------*/ +/* The main procedure; replacement for "wish". */ +/*----------------------------------------------------------------------*/ + +int +main(argc, argv) + int argc; + char **argv; +{ + Tk_Main(argc, argv, magic_AppInit); + return 0; +} + +/*----------------------------------------------------------------------*/ diff --git a/tcltk/magicps.pro b/tcltk/magicps.pro new file mode 100644 index 00000000..f16abb87 --- /dev/null +++ b/tcltk/magicps.pro @@ -0,0 +1,70 @@ +%%BeginProlog +% +% PostScript prolog for output from magic plot +% Version: 1.0 +% written by Tim Edwards 4/05/00 JHU Applied Physics Laboratory +% +%%BeginResource: procset MAGICproc 1.0 1 +% supporting definitions + +/MAGICsave save def + +/bop { 1 setlinecap 0 setlinejoin 6 setmiterlimit 0 setgray } def +/ninit { /nChars matrix currentmatrix dup 0 get 0 eq {1} {0} + ifelse get abs 72 8.5 mul mul 64 div ceiling cvi def } def +/minit { 1 1 dtransform abs dup 1 exch div /onePix exch def + dup /resY exch def 1 exch div /iresY exch def + abs dup /resX exch def 1 exch div /iresX exch def + /bX 64 iresX mul def /bY 64 iresY mul def + /pattFont StipplePattern definefont pop + /patterns /pattFont findfont [iresX 64 mul 0 0 iresY 64 mul 0 0] makefont def + /ca nChars 1 add string def + } def +/StipplePattern 45 dict def +StipplePattern begin + /FontType 3 def + /FontMatrix [1 0 0 1 0 0] def + /FontBBox [0 0 1 1] def + /Encoding 256 array def + /PattName (P0) def + /tmpStr 1 string def + /NoPatt {<00>} def + 0 1 255 { Encoding exch /NoPatt put } for + /BuildChar { + 1 0 0 0 1 1 setcachedevice exch begin Encoding exch get load + 64 64 true [64 0 0 64 0 0] 5 -1 roll imagemask end } def +end +/dp { StipplePattern begin dup 30 tmpStr cvrs PattName exch 1 exch + putinterval PattName cvn dup Encoding exch 4 -1 roll exch put exch + store end } def +/sf { findfont exch scalefont setfont } bind def +/sp { patterns setfont 2 setlinewidth } def +/lb { gsave translate 0 0 moveto /just exch def gsave dup true charpath + flattenpath pathbbox grestore exch 4 -1 roll exch sub 3 1 roll sub + just 4 and 0 gt {just 8 and 0 eq {0.5 mul} if}{pop 0} ifelse exch + just 1 and 0 gt {just 2 and 0 eq {0.5 mul} if}{pop 0} ifelse exch + rmoveto show grestore } def +/sl { 0 1 nChars { exch dup 3 1 roll ca 3 1 roll put } for pop } def +/sc { setcmykcolor } bind def +/l1 { onePix setlinewidth } def +/l2 { onePix 2 mul setlinewidth } def +/l3 { onePix 3 mul setlinewidth } def +/ml { moveto lineto stroke } bind def +/vl { moveto 0 exch rlineto stroke } bind def +/hl { moveto 0 rlineto stroke } bind def +/mr { rectstroke } bind def +/mx { 4 copy rectstroke 4 -1 roll 4 -1 roll 4 copy moveto rlineto stroke + 3 -1 roll dup neg 4 1 roll add moveto rlineto stroke } bind def +/pl { gsave translate /d exch def 0 d neg moveto 0 d lineto stroke + d neg 0 moveto d 0 lineto stroke grestore } bind def +/bx { x resX mul cvi 63 not and dup iresX mul exch + w resX mul sub abs 63 add cvi 64 idiv /w exch def + y resY mul cvi 63 not and dup iresY mul exch + h resY mul sub abs 63 add cvi 64 idiv /h exch def + /ch ca 0 w getinterval def + moveto h { ch gsave show grestore 0 bY rmoveto } repeat grestore } def +/fb {/h exch def /w exch def /y exch def /x exch def gsave newpath + x y moveto w y lineto w h lineto x h lineto closepath clip bx } def +/tb {1 sub 3 1 roll gsave newpath moveto {lineto} repeat closepath clip pathbbox + /h exch def /w exch def /y exch def /x exch def bx } def + diff --git a/tcltk/mazeroute.tcl b/tcltk/mazeroute.tcl new file mode 100644 index 00000000..59e81a97 --- /dev/null +++ b/tcltk/mazeroute.tcl @@ -0,0 +1,675 @@ +#----------------------------------------------------------------- +# mazeroute.tcl +#----------------------------------------------------------------- +# Defines procedure "mazeroute ", requiring a .net file as +# an argument. Attempts a single-pass maze route of the contents +# of the netlist. +#----------------------------------------------------------------- + +global Opts + +proc mazeroute {netfile} { + if [catch {open $netfile r} fnet] { + set netname [file rootname $netfile] + if [catch {open ${netfile}.net r} fnet] { + puts stderr "Can't read netlist file $netfile" + return 1; + } + } + # 1st line of the netlist file is throw-away + gets $fnet line + + set destnet {} + while {[gets $fnet line] >= 0} { + if {$line == ""} { + set destnet {} + } elseif {$destnet == {}} { + set destnet $line + } else { + set startnet $line + iroute route -dlabel $destnet -slabel $startnet -timeout 3 + set destnet $startnet + } + } +} + +#----------------------------------------------------------------- +# Interactive mazerouter GUI. Shows a list of nets from the +# selected netlist. Allows one to select the order of routing, +# route individual nets, rip up individual nets, etc. +# +# This GUI more or less replaces the "specialopen netlist" window. +#----------------------------------------------------------------- + +proc genmazehelper {} { + global Opts + set Opts(preproutes) 0 + set Opts(fenced) 0 + + if {![catch {wm deiconify .mazehelper ; raise .mazehelper}]} {return} + + toplevel .mazehelper + wm protocol .mazehelper WM_DELETE_WINDOW {destroy .mazehelper} + + frame .mazehelper.mazemenu + frame .mazehelper.unrouted + frame .mazehelper.transfer + frame .mazehelper.routed + + pack .mazehelper.mazemenu -side top -anchor w + + button .mazehelper.mazemenu.load -text "Load" -command {loadnetlist} + label .mazehelper.mazemenu.netlist -text "(no netlist loaded)" + button .mazehelper.mazemenu.fence -text "Fence" -command {buildfence} + button .mazehelper.mazemenu.sort -text "Sort" -command {sortnets} + button .mazehelper.mazemenu.params -text "Params" -command {genmazeparams} + + pack .mazehelper.mazemenu.load -side left + pack .mazehelper.mazemenu.netlist -side left -fill x -expand true + pack .mazehelper.mazemenu.fence -side left + pack .mazehelper.mazemenu.sort -side left + pack .mazehelper.mazemenu.params -side left + + label .mazehelper.unrouted.title -text "Unrouted:" + listbox .mazehelper.unrouted.contents -background white -selectmode extended + + label .mazehelper.routed.title -text "Routed:" + listbox .mazehelper.routed.contents -background white -selectmode extended + + button .mazehelper.transfer.ripup -text "<--" -command {ripupnet} + button .mazehelper.transfer.route -text "-->" -command {routenet} + + pack .mazehelper.transfer.ripup -side top + pack .mazehelper.transfer.route -side top + + pack .mazehelper.unrouted.title -side top + pack .mazehelper.unrouted.contents -side top -fill both -expand true + + pack .mazehelper.routed.title -side top + pack .mazehelper.routed.contents -side top -fill both -expand true + + pack .mazehelper.unrouted -side left -fill both -expand true + pack .mazehelper.transfer -side left + pack .mazehelper.routed -side left -fill both -expand true + +} + +#----------------------------------------------------------------- +# Route parameters (to be completed) +#----------------------------------------------------------------- + +proc genmazeparams {} { + global Opts + + if {![catch {wm deiconify .mazeparams ; raise .mazeparams}]} {return} + + toplevel .mazeparams + wm protocol .mazeparams WM_DELETE_WINDOW {destroy .mazeparams} + + set routeparams {layer active width hCost vCost jogCost hintCost overCost} + set curRparams [iroute layers -list] + + set contparams {contact active width cost} + set curCparams [iroute contact -list] + + set k 0 + label .mazeparams.t1 -text "Layer" + label .mazeparams.t2 -text "Active" + label .mazeparams.t3 -text "Width" + label .mazeparams.t4 -text "Horizontal Cost" + label .mazeparams.t5 -text "Vertical Cost" + label .mazeparams.t6 -text "Jog Cost" + label .mazeparams.t7 -text "Hint Cost" + label .mazeparams.t8 -text "Overroute Cost" + foreach layer $curRparams { + incr k + label .mazeparams.r${k}0 -text [lindex $layer 0] + checkbox .mazeparams.r${k}1 + for {set j 2} {$j < 8} {incr j} { + entry .mazeparams.r${k}${j} -text [lindex $contact $j] + } + } + incr k + label .mazeparams.t1 -text "Contact" + label .mazeparams.t2 -text "Active" + label .mazeparams.t3 -text "Size" + label .mazeparams.t4 -text "Cost" + foreach contact $curCparams { + incr k + label .mazeparams.r${k}0 -text [lindex $contact 0] + checkbox .mazeparams.r${k}1 + for {set j 2} {$j < 4} {incr j} { + entry .mazeparams.r${k}${j} -text [lindex $contact $j] + } + } +} + +#----------------------------------------------------------------- +# Load a magic-style netlist +#----------------------------------------------------------------- + +proc loadnetlist { {netfile {}} } { + global Opts + + if {$netfile == {}} { + set netfile [ tk_getOpenFile -filetypes \ + {{NET {.net {.net}}} {"All files" {*}}}] + } + + if [catch {open $netfile r} fnet] { + set netname [file rootname $netfile] + if [catch {open ${netfile}.net r} fnet] { + puts stderr "Can't read netlist file $netfile" + return 1; + } + } + + # Clear out the listbox contents. + .mazehelper.unrouted.contents delete 0 end + .mazehelper.routed.contents delete 0 end + set $Opts(preproutes) 0 + + # 1st line of the netlist file is throw-away + gets $fnet line + + set currentnet {} + while {[gets $fnet line] >= 0} { + if {$line == ""} { + if {[llength $currentnet] > 0} { + .mazehelper.unrouted.contents insert end $currentnet + set currentnet {} + } + } else { + lappend currentnet $line + } + } + + # Make sure final net gets added. . . + + if {[llength $currentnet] > 0} { + .mazehelper.unrouted.contents insert end $currentnet + } + + .mazehelper.mazemenu.netlist configure -text [file tail $netfile] + + # Verify all unrouted nets (check if any are already routed) + + .mazehelper.unrouted.contents select set 0 end + verifynet unrouted quiet + .mazehelper.unrouted.contents select clear 0 end + + close $fnet +} + +#----------------------------------------------------------------- +# Place a contact on each network endpoint. Aids in preventing +# the router from routing over pins by blocking access to the +# space over every pin that will be routed to. +# +# Changed 9/25/06---contact only in subcells. +# Changed 9/26/06---use obstruction layer, not contacts +#----------------------------------------------------------------- + +proc obstructendpoints {} { + global Opts + set Opts(preproutes) 1 + + box values 0 0 0 0 + foreach net [.mazehelper.unrouted.contents get 0 end] { + foreach endpoint $net { + set layer [goto $endpoint] + # Ignore via layers; these are already obstructed for our purposes. + if {[string first metal $layer] == 0} { + set lnum [string range $layer 5 end] + incr lnum + set obslayer obsm${lnum} + set viasize [tech drc width m${lnum}c] + + box size ${viasize}i ${viasize}i + paint $obslayer + } + } + } +} + +#----------------------------------------------------------------- +# Free the obstruction above endpoints for each endpoint in the +# current network. +#----------------------------------------------------------------- + +proc freeendpoints {net} { + box values 0 0 0 0 + foreach endpoint $net { + if {[string first / $endpoint] > 0} { + set layer [goto $endpoint] + if {[string first metal $layer] == 0} { + set lnum [string range $layer 5 end] + incr lnum + set obslayer obsm${lnum} + set viasize [tech drc width m${lnum}c] + box size ${viasize}i ${viasize}i + erase $obslayer + } + } + } +} + +#----------------------------------------------------------------- +# Free the obstruction above each pin in the current network. +#----------------------------------------------------------------- + +proc freepinobstructions {net} { + box values 0 0 0 0 + foreach endpoint $net { + if {[string first / $endpoint] <= 0} { + set layer [goto $endpoint] + if {[string first metal $layer] == 0} { + set lnum [string range $layer 5 end] + incr lnum + set obslayer obsm${lnum} + set viasize [tech drc width m${lnum}c] + box size ${viasize}i ${viasize}i + erase $obslayer + } + } + } +} + +#----------------------------------------------------------------- +# Sorting routine for two pins---sort by leftmost pin position. +#----------------------------------------------------------------- + +proc sortpinslr {pina pinb} { + goto $pina + set xa [lindex [box values] 0] + goto $pinb + set xb [lindex [box values] 0] + if {$xa > $xb} {return 1} else {return -1} +} + +#----------------------------------------------------------------- +# Sort a net so that the endpoints are ordered left to right +#----------------------------------------------------------------- + +proc sortnetslr {} { + set allnets [.mazehelper.unrouted.contents get 0 end] + .mazehelper.unrouted.contents delete 0 end + magic::suspendall + foreach net $allnets { + set netafter [lsort -command sortpinslr $net] + .mazehelper.unrouted.contents insert 0 $netafter + } + magic::resumeall +} + +#----------------------------------------------------------------- +# Procedure to find the leftmost point of a net. +#----------------------------------------------------------------- + +proc getnetleft {net} { + foreach endpoint $net { + set layer [goto $endpoint] + set xtest [lindex [box values] 0] + if [catch {if {$xtest < $xmin} {set xmin $xtest}}] {set xmin $xtest} + } + return $xmin +} + +#----------------------------------------------------------------- +# Procedure to compare nets according to the number of nodes +#----------------------------------------------------------------- + +proc routecomp {a b} { + set alen [llength $a] + set blen [llength $b] + if {$alen > $blen} { + return -1 + } elseif {$alen < $blen} { + return 1 + } else { + # Sort by leftmost route. + set aleft [getnetleft $a] + set bleft [getnetleft $b] + if {$aleft > $bleft} {return 1} else {return -1} + } +} + +#----------------------------------------------------------------- +# Sort unrouted nets from longest to shortest +#----------------------------------------------------------------- + +proc sortnets {} { + set listbefore [.mazehelper.unrouted.contents get 0 end] + .mazehelper.unrouted.contents delete 0 end + magic::suspendall + set listafter [lsort -command routecomp $listbefore] + foreach net $listafter { + .mazehelper.unrouted.contents insert end $net + } + magic::resumeall +} + +#----------------------------------------------------------------- +# Disassemble all networks into 2-point routes +#----------------------------------------------------------------- + +proc disassemble {} { + set allnets [.mazehelper.unrouted.contents get 0 end] + .mazehelper.unrouted.contents delete 0 end + foreach net $allnets { + for {set i 1} {$i < [llength $net]} {incr i} { + set j $i + incr j -1 + set newnet [lrange $net $j $i] + .mazehelper.unrouted.contents insert end $newnet + } + } +} + +#----------------------------------------------------------------- +# Fence the area around the cell +#----------------------------------------------------------------- + +proc buildfence {} { + global Opts + + pushbox + if {$Opts(fenced) == 0} { + select top cell + box grow c 1i + set ibounds [box values] + set illx [lindex $ibounds 0] + set illy [lindex $ibounds 1] + set iurx [lindex $ibounds 2] + set iury [lindex $ibounds 3] + box grow c 10i + set obounds [box values] + set ollx [lindex $obounds 0] + set olly [lindex $obounds 1] + set ourx [lindex $obounds 2] + set oury [lindex $obounds 3] + box values ${ollx}i ${iury}i ${ourx}i ${oury}i + paint fence + box values ${ollx}i ${olly}i ${ourx}i ${illy}i + paint fence + box values ${ollx}i ${olly}i ${illx}i ${oury}i + paint fence + box values ${iurx}i ${olly}i ${ourx}i ${oury}i + paint fence + set Opts(fenced) 1 + } else { + select top cell + box grow c 12i + erase fence + set Opts(fenced) 0 + } + popbox +} + +#----------------------------------------------------------------- +# Load a list of failed routes +#----------------------------------------------------------------- + +proc loadfailed { {netfile {}} } { + + if {$netfile == {}} { + set netfile [ tk_getOpenFile -filetypes \ + {{FAILED {.failed {.failed}}} {"All files" {*}}}] + } + + if [catch {open $netfile r} fnet] { + set netname [file rootname $netfile] + if [catch {open ${netfile}.failed r} fnet] { + puts stderr "Can't read file of failed routes $netfile" + return 1; + } + } + + # Clear out the listbox contents. + .mazehelper.unrouted.contents delete 0 end + .mazehelper.routed.contents delete 0 end + + + # Read each line into the "unrouted" list. + while {[gets $fnet line] >= 0} { + .mazehelper.unrouted.contents insert end $line + } + + .mazehelper.mazemenu.netlist configure -text $netfile + + close $fnet +} + +#----------------------------------------------------------------- +# Save the list of failed routes +#----------------------------------------------------------------- + +proc savefailed { {netfile {}} } { + + set netfile [.mazehelper.mazemenu.netlist cget -text] + if {$netfile == {}} { + set netfile [ tk_getOpenFile -filetypes \ + {{FAILED {.failed {.failed}}} {"All files" {*}}}] + } else { + set netname [file rootname $netfile] + set netname ${netname}.failed + } + + if [catch {open $netfile w} fnet] { + set netname [file rootname $netfile] + if [catch {open ${netfile}.failed w} fnet] { + puts stderr "Can't write file of failed routes $netfile" + return 1; + } + } + + foreach net [.mazehelper.unrouted.contents get 0 end] { + puts $fnet "$net" + } + + close $fnet +} + +#----------------------------------------------------------------- +# Get the selected network and maze route it +#----------------------------------------------------------------- + +proc routenet {} { + global Opts + + set drcstate [drc status] + drc off + + # Prepare routes by placing an obstruction layer on each pin + # Only do this if we have defined obstruction layers! + + if {$Opts(preproutes) == 0} { + set allLayers [tech layers *] + if {[lsearch $allLayers obs*] >= 0} { + magic::suspendall + obstructendpoints + magic::resumeall + } + } + + set unroutable {} + set sellist [.mazehelper.unrouted.contents curselection] + set startidx [lindex $sellist 0] + while {[llength $sellist] > 0} { + set cidx [lindex $sellist 0] + set rlist [.mazehelper.unrouted.contents get $cidx] + if {$Opts(preproutes) == 1} {freeendpoints $rlist} + for {set i 1} {$i < [llength $rlist]} {incr i} { + set j $i + incr j -1 + set startnet [lindex $rlist $j] + set destnet [lindex $rlist $i] + set rresult [iroute route -slabel $startnet -dlabel $destnet -timeout 3] + + # break on any failure + if {$rresult != "Route success" && \ + $rresult != "Route best before interrupt" && \ + $rresult != "Route already routed"} { + break + } else { + set rresult "success" + } + } + + .mazehelper.unrouted.contents delete $cidx $cidx + if {$rresult == "success"} { + .mazehelper.routed.contents insert end $rlist + } else { + # scramble list; we may have better luck routing in a different order + set rfirst [lindex $rlist 0] + set rlist [lrange $rlist 1 end] + lappend rlist $rfirst + lappend unroutable $rlist + } + set sellist [.mazehelper.unrouted.contents curselection] + if {$Opts(preproutes) == 1} {freepinobstructions $rlist} + } + .mazehelper.unrouted.contents selection set $startidx + foreach badnet $unroutable { + .mazehelper.unrouted.contents insert $startidx $badnet + } + + if {$drcstate == 1} {drc on} +} + +#----------------------------------------------------------------- +# Get the selected network and remove it +#----------------------------------------------------------------- + +proc ripupnet {} { + set sellist [.mazehelper.routed.contents curselection] + set startidx [lindex $sellist 0] + while {[llength $sellist] > 0} { + set cidx [lindex $sellist 0] + set rlist [.mazehelper.routed.contents get $cidx] + set netname [lindex $rlist 0] + select clear + set layertype [goto $netname] + select more box ${layertype},connect ;# chunk + select more box ${layertype},connect ;# region + select more box ${layertype},connect ;# net + delete + + .mazehelper.routed.contents delete $cidx $cidx + .mazehelper.unrouted.contents insert end $rlist + + set sellist [.mazehelper.routed.contents curselection] + } + .mazehelper.routed.contents selection set $startidx +} + +#----------------------------------------------------------------- +# Get the selected network and verify the route +#----------------------------------------------------------------- + +proc verifynet { {column routed} {infolevel verbose} } { + set sellist [.mazehelper.${column}.contents curselection] + set startidx [lindex $sellist 0] + magic::suspendall + while {$sellist != {}} { + set cidx [lindex $sellist 0] + set errors 0 + set rlist [.mazehelper.${column}.contents get $cidx] + set netname [lindex $rlist 0] + select clear + set layertype [goto $netname] + if {$layertype == {}} { + incr errors + } else { + select more box ${layertype},connect ;# chunk + select more box ${layertype},connect ;# region + select more box ${layertype},connect ;# net + set sellist [what -list] + set sellabels [lindex $sellist 1] + set labellist {} + foreach label $sellabels { + set labtext [lindex $label 0] + set labinst [lindex $label 2] + if {$labinst == {}} { + set labname ${labtext} + } else { + set labname ${labinst}/${labtext} + } + lappend labellist $labname + } + + # Backslash substitute brackets prior to using lsearch, or this won't work + # on such labels. Hopefully this won't confuse things. . . + set newrlist [string map {\[ < \] >} $rlist] + set newlabellist [string map {\[ < \] >} $labellist] + + # Compare labellist to rlist---they are supposed to be the same! + + foreach entry $newlabellist { + if {[lsearch $newrlist $entry] < 0} { + if {"$infolevel" == "verbose"} { + puts stderr "ERROR: Net entry $entry in layout is not in the netlist!" + } + incr errors + } + } + foreach entry $newrlist { + if {[lsearch $newlabellist $entry] < 0} { + if {"$infolevel" == "verbose"} { + puts stderr "ERROR: Net entry $entry in netlist is not in the layout!" + } + incr errors + } + } + if {$errors == 0 && "$infolevel" == "verbose"} {puts stdout "VERIFIED"} + } + + # If column is "routed" and we're not verified, move to "unrouted". + # If column is "unrouted" and we're verified, move to "routed". + + if {"$column" == "routed"} { + if {$errors > 0} { + .mazehelper.routed.contents delete $cidx $cidx + .mazehelper.unrouted.contents insert end $rlist + } else { + .mazehelper.routed.contents selection clear $cidx + incr startidx + } + } else { + if {$errors == 0} { + .mazehelper.unrouted.contents delete $cidx $cidx + .mazehelper.routed.contents insert end $rlist + } else { + .mazehelper.unrouted.contents selection clear $cidx + incr startidx + } + } + + # Get the selection list again + set sellist [.mazehelper.${column}.contents curselection] + } + magic::resumeall + .mazehelper.${column}.contents selection set $startidx +} + +#----------------------------------------------------------------- +# Reset the maze helper, deleting all routes. +#----------------------------------------------------------------- + +proc resetmazehelper {} { + .mazehelper.routed.contents delete 0 end + .mazehelper.unrouted.contents delete 0 end +} + +#----------------------------------------------------------------- +# Add the "mazehelper" function to the Magic Options +#----------------------------------------------------------------- + +proc addmazehelper {optmenu} { + global Opts + $optmenu add check -label "Maze Router" -variable Opts(mazeroute) -command \ + {if {$Opts(mazeroute) == 0} {destroy .mazehelper} else {genmazehelper}} +} + +#----------------------------------------------------------------- + diff --git a/tcltk/socketcmd.tcl b/tcltk/socketcmd.tcl new file mode 100644 index 00000000..24545a54 --- /dev/null +++ b/tcltk/socketcmd.tcl @@ -0,0 +1,27 @@ +#------------------------------------------------------------- +# socketcmd.tcl --- +# +# Method to pass commands to magic through a socket +# From the client side, use "set chan [socket 0.0.0.0 12946]" +# and pass commands with "puts $chan {magic command}" and +# "flush $chan". +#------------------------------------------------------------- + +set commPort 12946 + +proc handleComm {chan} { + if {[gets $chan line] >= 0} { + puts $line + eval $line + } + if {[eof $chan]} { + close $chan + } +} + +proc acceptComm {chan addr port} { + fconfigure $chan -blocking 0 -buffering line -translation crlf + fileevent $chan readable [list handleComm $chan] +} + +socket -server acceptComm $commPort diff --git a/tcltk/strip_reflibs.tcl b/tcltk/strip_reflibs.tcl new file mode 100755 index 00000000..516f4ea3 --- /dev/null +++ b/tcltk/strip_reflibs.tcl @@ -0,0 +1,41 @@ +#!/usr/local/bin/tclsh +# +# Strip GDS cell references from magic files. +# +# This is necessary to make sure that no geometry goes into the output +# for files swapped between Cadence and Magic. To import into Magic +# from Cadence, "Retain Reference Library" should be FALSE, so that +# Magic gets all of the cell contents. Then run this file on the +# resulting Magic database directory, and read back into Cadence using +# "Retain Reference Library" = TRUE. This will prevent Cadence from +# generating local copies of every cell, instead retaining the original +# library definition. +# +# 1. delete lines beginning "string GDS_START" +# 2. delete lines beginning "string GDS_END" +# 3. do NOT delete "string GDS_FILE" lines. +# +# Note that if all cells are treated as library references, then the +# GDS file itself does not need to exist. + +foreach fname [glob *.mag] { + if [catch {open $fname r} fIn] { + puts stdout "Error: can't open file $fname" + } else { + set fOut [open tmp.mag w] + while {[gets $fIn line] >= 0} { + if [regexp {^string GDS_} $line] { + if [regexp {^string GDS_START} $line ] { + } elseif [regexp {^string GDS_END} $line] { + } else { + puts $fOut $line + } + } else { + puts $fOut $line + } + } + close $fIn + close $fOut + file rename -force tmp.mag $fname + } +} diff --git a/tcltk/tclmagic.c b/tcltk/tclmagic.c new file mode 100644 index 00000000..781e4456 --- /dev/null +++ b/tcltk/tclmagic.c @@ -0,0 +1,1245 @@ +/*----------------------------------------------------------------------*/ +/* tclmagic.c --- Creates the interpreter-wrapped version of magic. */ +/* */ +/* Written by Tim Edwards August 2002 */ +/* */ +/* Note that this file is tied to Tcl. The original version (from */ +/* around April 2002) relied on SWIG, the only differences being */ +/* as few %{ ... %} boundaries and the replacement of the */ +/* Tclmagic_Init function header with "%init %{", and call the */ +/* file "tclmagic.i". However, the rest of the associated wrapper */ +/* code got so dependent on Tcl commands that there is no longer any */ +/* point in using SWIG. */ +/* */ +/* When using SWIG, the Makefile requires: */ +/* */ +/* tclmagic.c: tclmagic.i */ +/* swig -tcl8 -o tclmagic.c tclmagic.i */ +/* */ +/*----------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/main.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "utils/dqueue.h" +#include "database/database.h" +#include "windows/windows.h" +#include "commands/commands.h" +#include "utils/utils.h" +#include "textio/textio.h" +#include "textio/txcommands.h" +#include "utils/signals.h" +#include "graphics/graphics.h" +#include "utils/malloc.h" +#include "dbwind/dbwind.h" + +/* + * String containing the version number of magic. Don't change the string + * here, nor its format. It is updated by the Makefile in this directory. + */ + +char *MagicVersion = MAGIC_VERSION; +char *MagicRevision = MAGIC_REVISION; +char *MagicCompileTime = MAGIC_DATE; + +Tcl_Interp *magicinterp; +Tcl_Interp *consoleinterp; + +HashTable txTclTagTable; + +Tcl_ChannelType inChannel; + +/* Forward declarations */ + +int TerminalInputProc(ClientData, char *, int, int *); +void TxFlushErr(); +void TxFlushOut(); +void RegisterTkCommands(); + +/*--------------------------------------------------------------*/ +/* Verify if a command has a tag callback. */ +/*--------------------------------------------------------------*/ + +int +TagVerify(keyword) + char *keyword; +{ + char *croot, *postcmd; + HashEntry *entry; + + /* Skip over namespace qualifier, if any */ + + croot = keyword; + if (!strncmp(croot, "::", 2)) croot += 2; + if (!strncmp(croot, "magic::", 7)) croot += 7; + + entry = HashLookOnly(&txTclTagTable, croot); + postcmd = (entry) ? (char *)HashGetValue(entry) : NULL; + return (postcmd) ? TRUE : FALSE; +} + +/*--------------------------------------------------------------*/ +/* Find any tags associated with a command and execute them. */ +/*--------------------------------------------------------------*/ + +static int +TagCallback(interp, tkpath, argc, argv) + Tcl_Interp *interp; + char *tkpath; + int argc; /* original command's number of arguments */ + char *argv[]; /* original command's argument list */ +{ + int argidx, result = TCL_OK; + char *postcmd, *substcmd, *newcmd, *sptr, *sres; + char *croot; + HashEntry *entry; + Tcl_SavedResult state; + bool reset = FALSE; + int cmdnum; + + /* No command, no action */ + + if (argc == 0) return TCL_OK; + + /* Skip over namespace qualifier, if any */ + + croot = argv[0]; + if (!strncmp(croot, "::", 2)) croot += 2; + if (!strncmp(croot, "magic::", 7)) croot += 7; + + entry = HashLookOnly(&txTclTagTable, croot); + postcmd = (entry) ? (char *)HashGetValue(entry) : NULL; + + if (postcmd) + { + /* The Tag callback should not increase the command number */ + /* sequence, so save it now and restore it before returning. */ + cmdnum = TxCommandNumber; + + substcmd = (char *)mallocMagic(strlen(postcmd) + 1); + strcpy(substcmd, postcmd); + sptr = substcmd; + + /*--------------------------------------------------------------*/ + /* Parse "postcmd" for Tk-substitution escapes */ + /* Allowed escapes are: */ + /* %W substitute the tk path of the layout window */ + /* %r substitute the previous Tcl result string */ + /* %R substitute the previous Tcl result string and */ + /* reset the Tcl result. */ + /* %[0-5] substitute the argument to the original command */ + /* %% substitute a single percent character */ + /* %* (all others) no action: print as-is. */ + /*--------------------------------------------------------------*/ + + while ((sptr = strchr(sptr, '%')) != NULL) + { + switch (*(sptr + 1)) + { + case 'W': + + /* In the case of the %W escape, first we see if a Tk */ + /* path has been passed in the argument. If not, get */ + /* the window path if there is only one window. */ + /* Otherwise, the window is unknown so we substitute */ + /* a null list "{}". */ + + if (tkpath == NULL) + { + MagWindow *w = NULL; + windCheckOnlyWindow(&w, DBWclientID); + if (w != NULL && !(w->w_flags & WIND_OFFSCREEN)) + { + Tk_Window tkwind = (Tk_Window) w->w_grdata; + if (tkwind != NULL) tkpath = Tk_PathName(tkwind); + } + } + if (tkpath == NULL) + newcmd = (char *)mallocMagic(strlen(substcmd) + 2); + else + newcmd = (char *)mallocMagic(strlen(substcmd) + strlen(tkpath)); + + strcpy(newcmd, substcmd); + + if (tkpath == NULL) + strcpy(newcmd + (int)(sptr - substcmd), "{}"); + else + strcpy(newcmd + (int)(sptr - substcmd), tkpath); + + strcat(newcmd, sptr + 2); + freeMagic(substcmd); + substcmd = newcmd; + sptr = substcmd; + break; + + case 'R': + reset = TRUE; + case 'r': + sres = (char *)Tcl_GetStringResult(magicinterp); + newcmd = (char *)mallocMagic(strlen(substcmd) + + strlen(sres) + 1); + strcpy(newcmd, substcmd); + sprintf(newcmd + (int)(sptr - substcmd), "\"%s\"", sres); + strcat(newcmd, sptr + 2); + freeMagic(substcmd); + substcmd = newcmd; + sptr = substcmd; + + break; + + case '0': case '1': case '2': case '3': case '4': case '5': + argidx = (int)(*(sptr + 1) - '0'); + if ((argidx >= 0) && (argidx < argc)) + { + newcmd = (char *)mallocMagic(strlen(substcmd) + + strlen(argv[argidx])); + strcpy(newcmd, substcmd); + strcpy(newcmd + (int)(sptr - substcmd), argv[argidx]); + strcat(newcmd, sptr + 2); + freeMagic(substcmd); + substcmd = newcmd; + sptr = substcmd; + } + else if (argidx >= argc) + { + newcmd = (char *)mallocMagic(strlen(substcmd) + 1); + strcpy(newcmd, substcmd); + strcpy(newcmd + (int)(sptr - substcmd), sptr + 2); + freeMagic(substcmd); + substcmd = newcmd; + sptr = substcmd; + } + else sptr++; + break; + + case '%': + newcmd = (char *)mallocMagic(strlen(substcmd) + 1); + strcpy(newcmd, substcmd); + strcpy(newcmd + (int)(sptr - substcmd), sptr + 1); + freeMagic(substcmd); + substcmd = newcmd; + sptr = substcmd; + break; + + default: + break; + } + } + + /* fprintf(stderr, "Substituted tag callback is \"%s\"\n", substcmd); */ + /* fflush(stderr); */ + + Tcl_SaveResult(interp, &state); + result = Tcl_EvalEx(interp, substcmd, -1, 0); + if ((result == TCL_OK) && (reset == FALSE)) + Tcl_RestoreResult(interp, &state); + else + Tcl_DiscardResult(&state); + + freeMagic(substcmd); + TxCommandNumber = cmdnum; /* restore original value */ + } + return result; +} + +/*--------------------------------------------------------------*/ +/* Add a command tag callback */ +/*--------------------------------------------------------------*/ + +static int +AddCommandTag(ClientData clientData, + Tcl_Interp *interp, int argc, char *argv[]) +{ + HashEntry *entry; + char *hstring; + + if (argc != 2 && argc != 3) + return TCL_ERROR; + + entry = HashFind(&txTclTagTable, argv[1]); + + if (entry == NULL) return TCL_ERROR; + + hstring = (char *)HashGetValue(entry); + + if (argc == 2) + { + Tcl_SetResult(magicinterp, hstring, NULL); + return TCL_OK; + } + + if (hstring != NULL) freeMagic(hstring); + + if (strlen(argv[2]) == 0) + { + HashSetValue(entry, NULL); + } + else + { + hstring = StrDup((char **)NULL, argv[2]); + HashSetValue(entry, hstring); + } + return TCL_OK; +} + +/*--------------------------------------------------------------*/ +/* Dispatch a command from Tcl */ +/* See TxTclDispatch() in textio/txCommands.c */ +/*--------------------------------------------------------------*/ + +static int +_tcl_dispatch(ClientData clientData, + Tcl_Interp *interp, int argc, char *argv[]) +{ + int wval; + int result, idx; + Tcl_Obj *objv0; + char *argv0, *tkwind; + + /* Check command (argv[0]) against known conflicting */ + /* command names. If the command is potentially a */ + /* Tcl/Tk command, try it as such, first. If a Tcl */ + /* error is returned, then try it as a magic */ + /* command. Note that the other way (try the magic */ + /* command first) would necessitate setting Tcl */ + /* results for every magic command. Too much work. */ + + static char *conflicts[] = + { + "clockwise", "flush", "load", "label", "array", "grid", NULL + }; + static char *resolutions[] = + { + "orig_clock", "tcl_flush", "tcl_load", "tcl_label", "tcl_array", + "tcl_grid", NULL + }; + + typedef enum + { + IDX_CLOCK, IDX_FLUSH, IDX_LOAD, IDX_LABEL, IDX_ARRAY, + IDX_GRID + } conflictCommand; + + /* Skip any "::" namespace prefix before parsing */ + argv0 = argv[0]; + if (!strncmp(argv0, "::", 2)) argv0 += 2; + + objv0 = Tcl_NewStringObj(argv0, strlen(argv0)); + if (Tcl_GetIndexFromObj(interp, objv0, (CONST84 char **)conflicts, + "overloaded command", 0, &idx) == TCL_OK) + { + int i; + Tcl_Obj **objv = (Tcl_Obj **)Tcl_Alloc(argc * sizeof(Tcl_Obj *)); + + /* Create a Tcl_Obj array suitable for calling Tcl_EvalObjv. */ + /* The first argument is changed from the magic command name to */ + /* "tcl" + the command name. This assumes that all conflicting */ + /* command names have been so renamed in the startup script! */ + + objv[0] = Tcl_NewStringObj(resolutions[idx], strlen(resolutions[idx])); + Tcl_IncrRefCount(objv[0]); + + for (i = 1; i < argc; i++) + { + objv[i] = Tcl_NewStringObj(argv[i], strlen(argv[i])); + Tcl_IncrRefCount(objv[i]); + } + + result = Tcl_EvalObjv(interp, argc, objv, 0); + + for (i = 0; i < argc; i++) + Tcl_DecrRefCount(objv[i]); + Tcl_Free((char *)objv); + + if (result == TCL_OK) + return result; + + /* The rule is to execute Magic commands for any Tcl command */ + /* with the same name that returns an error. However, this */ + /* rule hangs magic when the "load" command is used on a shared */ + /* object file that fails to load properly. So if the filename */ + /* has an extension which is not ".mag", we will return the */ + /* error. */ + + /* Updated 1/20/2015: Need to check for a '.' AFTER the last */ + /* slash, so as to avoid problems with ./, ../, etc. */ + + if (idx == IDX_LOAD) + { + char *dotptr, *slashptr; + if (argc >= 2) + { + slashptr = strrchr(argv[1], '/'); + if (slashptr == NULL) + slashptr = argv[1]; + else + slashptr++; + + if ((dotptr = strrchr(slashptr, '.')) != NULL) + if (strcmp(dotptr + 1, "mag")) + return result; + } + } + } + Tcl_ResetResult(interp); + + if (TxInputRedirect == TX_INPUT_REDIRECTED) + TxInputRedirect = TX_INPUT_PENDING_RESET; + + wval = TxTclDispatch(clientData, argc, argv, TRUE); + + if (TxInputRedirect == TX_INPUT_PENDING_RESET) + TxInputRedirect = TX_INPUT_NORMAL; + + /* If the command did not pass through _tk_dispatch, but the command was */ + /* entered by key redirection from a window, then TxInputRedirect will be */ + /* set to TX_INPUT_PROCESSING and the window ID will have been set by */ + /* TxSetPoint(). Do our level best to find the Tk window name. */ + + if (TxInputRedirect == TX_INPUT_PROCESSING) + { + if (GrWindowNamePtr) + { + MagWindow *mw = WindSearchWid(TxGetPoint(NULL)); + if (mw != NULL) + tkwind = (*GrWindowNamePtr)(mw); + else + tkwind = NULL; + } + else + tkwind = NULL; + } + else + tkwind = NULL; + + // Pass back an error if TxTclDispatch failed + if (wval != 0) return TCL_ERROR; + + return TagCallback(interp, tkwind, argc, argv); +} + +/*--------------------------------------------------------------*/ +/* Dispatch a window-related command. The first argument is */ +/* the window to which the command should be directed, so we */ +/* determine which window this is, set "TxCurCommand" values */ +/* to point to the window, then dispatch the command. */ +/*--------------------------------------------------------------*/ + +static int +_tk_dispatch(ClientData clientData, + Tcl_Interp *interp, int argc, char *argv[]) +{ + int id; + char *tkpath; + char *arg0; + Point txp; + + if (GrWindowIdPtr) + { + /* Key macros set the point from the graphics module code but */ + /* set up the command to be dispatched via _tk_dispatch(). */ + /* Therefore it is necessary to check if a point position */ + /* has already been set for this command. If not, then the */ + /* command was probably called from the command entry window, */ + /* so we choose an arbitrary point which is somewhere in the */ + /* window, so that command functions have a point of reference. */ + + id = (*GrWindowIdPtr)(argv[0]); + + if (TxGetPoint(&txp) != id) + { + /* This is a point in the window, inside the */ + /* scrollbars if they are managed by magic. */ + + txp.p_x = 20; + txp.p_y = 20; + } + TxSetPoint(txp.p_x, txp.p_y, id); + arg0 = argv[0]; + argc--; + argv++; + } + + TxTclDispatch(clientData, argc, argv, FALSE); + + /* Get pathname of window and pass to TagCallback */ + return TagCallback(interp, arg0, argc, argv); +} + +/*--------------------------------------------------------------*/ +/* Set up a window to use commands via _tk_dispatch */ +/*--------------------------------------------------------------*/ + +void +MakeWindowCommand(char *wname, MagWindow *mw) +{ + char *tclcmdstr; + + Tcl_CreateCommand(magicinterp, wname, (Tcl_CmdProc *)_tk_dispatch, + (ClientData)mw, (Tcl_CmdDeleteProc *) NULL); + + /* Force the window manager to use magic's "close" command to close */ + /* down a window. */ + + tclcmdstr = (char *)mallocMagic(52 + 2 * strlen(wname)); + sprintf(tclcmdstr, "wm protocol %s WM_DELETE_WINDOW " + "{magic::closewindow %s}", wname, wname); + Tcl_EvalEx(magicinterp, tclcmdstr, -1, 0); + freeMagic(tclcmdstr); +} + +/*------------------------------------------------------*/ +/* Main startup procedure */ +/*------------------------------------------------------*/ + +static int +_magic_initialize(ClientData clientData, + Tcl_Interp *interp, int argc, char *argv[]) +{ + WindClient client; + int n, i; + char keyword[100]; + char *kwptr = keyword + 7; + char **commandTable; + int result; + + /* Is magic being executed in a slave interpreter? */ + + if ((consoleinterp = Tcl_GetMaster(interp)) == NULL) + consoleinterp = interp; + + // Force tkcon to send output to terminal during initialization + else + { + RuntimeFlags |= (MAIN_TK_CONSOLE | MAIN_TK_PRINTF); + Tcl_Eval(consoleinterp, "rename ::puts ::unused_puts\n"); + Tcl_Eval(consoleinterp, "rename ::tkcon_tcl_puts ::puts\n"); + } + + /* Did we start in the same interpreter as we initialized? */ + if (magicinterp != interp) + { + TxError("Warning: Switching interpreters. Tcl-magic is not set up " + "to handle this.\n"); + magicinterp = interp; + } + + if (mainInitBeforeArgs(argc, argv) != 0) goto magicfatal; + if (mainDoArgs(argc, argv) != 0) goto magicfatal; + + // Redirect output back to the console + if (TxTkConsole) + { + RuntimeFlags &= ~MAIN_TK_PRINTF; + Tcl_Eval(consoleinterp, "rename ::puts ::tkcon_tcl_puts\n"); + Tcl_Eval(consoleinterp, "rename ::unused_puts ::puts\n"); + } + + /* Identify version and revision */ + + TxPrintf("\nMagic %s revision %s - Compiled on %s.\n", MagicVersion, + MagicRevision, MagicCompileTime); + TxPrintf("Starting magic under Tcl interpreter\n"); + if (TxTkConsole) + TxPrintf("Using Tk console window\n"); + else + TxPrintf("Using the terminal as the console.\n"); + TxFlushOut(); + + if (mainInitAfterArgs() != 0) goto magicfatal; + + /* Registration of commands is performed after calling the */ + /* start function, not after initialization, as the command */ + /* modularization requires magic initialization to get a */ + /* valid DBWclientID, windClientID, etc. */ + + sprintf(keyword, "magic::"); + + /* Work through all the known clients, and register the */ + /* commands of all of them. */ + + client = (WindClient)NULL; + while ((client = WindNextClient(client)) != NULL) + { + commandTable = WindGetCommandTable(client); + for (n = 0; commandTable[n] != NULL; n++) + { + sscanf(commandTable[n], "%s ", kwptr); /* get first word */ + Tcl_CreateCommand(interp, keyword, (Tcl_CmdProc *)_tcl_dispatch, + (ClientData)NULL, (Tcl_CmdDeleteProc *) NULL); + } + } + + /* Extra commands provided by the Tk graphics routines */ + /* (See graphics/grTkCommon.c) */ + /* (Unless "-dnull" option has been given) */ + + if (strcmp(MainDisplayType, "NULL")) + RegisterTkCommands(interp); + + /* Set up the console so that its menu option File->Exit */ + /* calls magic's exit routine first. This should not be */ + /* done in console.tcl, or else it puts the console in a */ + /* state where it is difficult to exit, if magic doesn't */ + /* start up correctly. */ + + if (TxTkConsole) + { + Tcl_Eval(consoleinterp, "rename ::exit ::quit\n"); + Tcl_Eval(consoleinterp, "proc ::exit args {slave eval quit}\n"); + } + + return TCL_OK; + +magicfatal: + TxResetTerminal(); + Tcl_SetResult(interp, "Magic initialization encountered a fatal error.", NULL); + return TCL_ERROR; +} + +/*--------------------------------------------------------------*/ + +typedef struct FileState { + Tcl_Channel channel; + int fd; + int validMask; +} FileState; + +/*--------------------------------------------------------------*/ +/* "Wizard" command for manipulating run-time flags. */ +/*--------------------------------------------------------------*/ + +static int +_magic_flags(ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) +{ + int index, index2; + bool value; + static char *flagOptions[] = {"debug", "recover", "silent", + "window", "console", "printf", (char *)NULL}; + static char *yesNo[] = {"off", "no", "false", "0", "on", "yes", + "true", "1", (char *)NULL}; + + if ((objc != 2) && (objc != 3)) { + Tcl_WrongNumArgs(interp, 1, objv, "flag ?value?"); + return TCL_ERROR; + } + if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)flagOptions, + "option", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (objc == 2) { + switch (index) { + case 0: + value = (RuntimeFlags & MAIN_DEBUG) ? TRUE : FALSE; + break; + case 1: + value = (RuntimeFlags & MAIN_RECOVER) ? TRUE : FALSE; + break; + case 2: + value = (RuntimeFlags & MAIN_SILENT) ? TRUE : FALSE; + break; + case 3: + value = (RuntimeFlags & MAIN_MAKE_WINDOW) ? TRUE : FALSE; + break; + case 4: + value = (RuntimeFlags & MAIN_TK_CONSOLE) ? TRUE : FALSE; + break; + case 5: + value = (RuntimeFlags & MAIN_TK_PRINTF) ? TRUE : FALSE; + break; + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value)); + } + else { + if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)yesNo, + "value", 0, &index2) != TCL_OK) + return TCL_ERROR; + + value = (index2 > 3) ? TRUE : FALSE; + switch (index) { + case 0: + if (value == TRUE) + RuntimeFlags |= MAIN_DEBUG; + else + RuntimeFlags &= ~MAIN_DEBUG; + break; + case 1: + if (value == TRUE) + RuntimeFlags |= MAIN_RECOVER; + else + RuntimeFlags &= ~MAIN_RECOVER; + break; + case 2: + if (value == TRUE) + RuntimeFlags |= MAIN_SILENT; + else + RuntimeFlags &= ~MAIN_SILENT; + break; + case 3: + if (value == TRUE) + RuntimeFlags |= MAIN_MAKE_WINDOW; + else + RuntimeFlags &= ~MAIN_MAKE_WINDOW; + break; + case 4: + if (value == TRUE) + RuntimeFlags |= MAIN_TK_CONSOLE; + else + RuntimeFlags &= ~MAIN_TK_CONSOLE; + break; + case 5: + if (value == TRUE) + RuntimeFlags |= MAIN_TK_PRINTF; + else + RuntimeFlags &= ~MAIN_TK_PRINTF; + break; + } + } + return TCL_OK; +} + +/*--------------------------------------------------------------*/ +/* Post-initialization: read in the magic startup files and */ +/* load any initial layout. Note that this is not done via */ +/* script, but probably should be. */ +/*--------------------------------------------------------------*/ + +static int +_magic_startup(ClientData clientData, + Tcl_Interp *interp, int argc, char *argv[]) +{ + /* Execute contents of startup files and load any initial cell */ + + if (mainInitFinal() != 0) + { + /* We don't want mainInitFinal errors to return TCL_ERROR from */ + /* magic::start; otherwise, the window won't come up. As long */ + /* as we have successfully passed mainInitAfterArgs(), magic is */ + /* fundamentally sound. */ + + Tcl_SetResult(interp, + "Magic encountered problems with the startup files.", + NULL); + } + + TxResetTerminal(); + + if (TxTkConsole) + { + Tcl_EvalEx(consoleinterp, "tkcon set ::tkcon::OPT(showstatusbar) 1", -1, 0); + TxSetPrompt('%'); + } + else + { + Tcl_Channel oldchannel; + Tcl_ChannelType *stdChannel; + FileState *fsPtr, *fsOrig; + + /* Use the terminal. */ + /* Replace the input proc for stdin with our own. */ + + oldchannel = Tcl_GetStdChannel(TCL_STDIN); // Get existing stdin + fsOrig = Tcl_GetChannelInstanceData(oldchannel); + + /* Copy the structure from the old to the new channel */ + stdChannel = (Tcl_ChannelType *)Tcl_GetChannelType(oldchannel); + memcpy(&inChannel, stdChannel, sizeof(Tcl_ChannelType)); + inChannel.inputProc = TerminalInputProc; + + fsPtr = (FileState *)Tcl_Alloc(sizeof(FileState)); + fsPtr->validMask = fsOrig->validMask; + fsPtr->fd = fsOrig->fd; + fsPtr->channel = Tcl_CreateChannel(&inChannel, "stdin", + (ClientData)fsPtr, TCL_READABLE); + + Tcl_SetStdChannel(fsPtr->channel, TCL_STDIN); // Apply new stdin + Tcl_RegisterChannel(NULL, fsPtr->channel); + } + + return TCL_OK; +} + +/*--------------------------------------------------------------*/ +/* Tk version of TxDialog */ +/*--------------------------------------------------------------*/ + +int +TxDialog(prompt, responses, defresp) + char *prompt; + char *(responses[]); + int defresp; +{ + Tcl_Obj *objPtr; + int code, result, pos; + char *evalstr, *newstr; + + /* Ensure that use of TxPrintString doesn't overwrite the */ + /* value of prompt my making a copy of it. */ + /* 5/11/05---use Tcl_escape() to do the duplication; this */ + /* ensures that cell names with special characters like '$' */ + /* will be handled properly. */ + + newstr = Tcl_escape(prompt); + /* newstr = StrDup((char **)NULL, prompt); */ + evalstr = TxPrintString("tk_dialog .dialog \"Dialog\"" + " \"%s\" {} %d ", newstr, defresp); + /* freeMagic(newstr); */ + Tcl_Free(newstr); /* Tcl_escape() uses Tcl_Alloc() */ + + for (pos = 0; responses[pos] != 0; pos++) + { + newstr = StrDup((char **)NULL, evalstr); + evalstr = TxPrintString("%s \"%s\" ", newstr, + responses[pos]); + freeMagic(newstr); + } + + Tcl_EvalEx(magicinterp, evalstr, -1, 0); + objPtr = Tcl_GetObjResult(magicinterp); + result = Tcl_GetIntFromObj(magicinterp, objPtr, &code); + + if (result == TCL_OK) return code; + else return -1; +} + +/*--------------------------------------------------------------*/ +/* TxUseMore and TxStopMore are dummy functions, although they */ +/* could be used to set up a top-level window containing the */ +/* result (redefine "puts" to write to the window). */ +/*--------------------------------------------------------------*/ + +void +TxUseMore() +{ +} + +/*--------------------------------------------------------------*/ + +void +TxStopMore() +{ +} + +/*--------------------------------------------------------------*/ +/* Set the prompt, if we are using the TkCon console */ +/*--------------------------------------------------------------*/ + +extern char txPromptChar; + +void +TxSetPrompt(ch) + char ch; +{ + Tcl_SavedResult state; + char promptline[16]; + + if (TxTkConsole) + { + sprintf(promptline, "replaceprompt %c", ch); + Tcl_SaveResult(consoleinterp, &state); + Tcl_EvalEx(consoleinterp, promptline, 15, 0); + Tcl_RestoreResult(consoleinterp, &state); + } +} + +/*--------------------------------------------------------------*/ +/* Get a line from stdin (Tcl replacement for Tx function) */ +/*--------------------------------------------------------------*/ + +char * +TxGetLinePfix(dest, maxChars, prefix) + char *dest; + int maxChars; + char *prefix; +{ + Tcl_Obj *objPtr; + int charsStored, length; + char *string; + + if (TxTkConsole) + { + /* Use dialog function (must be defined in magic.tcl!) */ + if (prefix != NULL) + { + string = Tcl_Alloc(20 + strlen(prefix)); + sprintf(string, "magic::dialog \"\" \"%s\"\n", prefix); + Tcl_EvalEx(magicinterp, string, -1, 0); + Tcl_Free(string); + } + else + Tcl_EvalEx(magicinterp, "magic::dialog", 13, 0); + } + else + { + if (prefix != NULL) + { + TxPrintf("%s", prefix); + TxFlushOut(); + } + Tcl_EvalEx(magicinterp, "gets stdin", 10, 0); + } + + objPtr = Tcl_GetObjResult(magicinterp); + string = Tcl_GetStringFromObj(objPtr, &length); + + if (length > 0) + if (*(string + length - 1) == '\n') + length--; + + if (length == 0) + return NULL; + else if (length >= maxChars) + length = (maxChars - 1); + + strncpy(dest, string, length); + *(dest + length) = '\0'; + return dest; +} + +/*--------------------------------------------------------------*/ +/* Parse a file. This is a skeleton version of the TxDispatch */ +/* routine in textio/txCommands.c */ +/*--------------------------------------------------------------*/ + +void +TxDispatch(f) + FILE *f; /* Under Tcl, we never call this with NULL */ +{ + if (f == NULL) + { + TxError("Error: TxDispatch(NULL) was called\n"); + } + while (!feof(f)) + { + if (SigInterruptPending) + { + TxError("Read-in of file aborted.\n"); + SigInterruptPending = FALSE; + return; + } + txGetFileCommand(f, NULL); + } +} + +/*--------------------------------------------------------------*/ +/* Send a command line which was collected by magic's TxEvent */ +/* handler to the interpreter's event queue. */ +/*--------------------------------------------------------------*/ + +void +TxParseString(str, q, event) + char *str; + caddr_t q; /* unused */ + caddr_t event; /* always NULL (ignored) */ +{ + char *reply; + + Tcl_EvalEx(magicinterp, str, -1, 0); + + reply = (char *)Tcl_GetStringResult(magicinterp); + + if (strlen(reply) > 0) + TxPrintf("%s: %s\n", str, reply); +} + +/*--------------------------------------------------------------*/ +/* Replacement for TxFlush(): use Tcl interpreter */ +/* If we just call "flush", _tcl_dispatch gets called, and */ +/* bad things will happen. */ +/*--------------------------------------------------------------*/ + +void +TxFlushErr() +{ + Tcl_SavedResult state; + + Tcl_SaveResult(magicinterp, &state); + Tcl_EvalEx(magicinterp, "::tcl_flush stderr", 18, 0); + Tcl_RestoreResult(magicinterp, &state); +} + +/*--------------------------------------------------------------*/ + +void +TxFlushOut() +{ + Tcl_SavedResult state; + + Tcl_SaveResult(magicinterp, &state); + Tcl_EvalEx(magicinterp, "::tcl_flush stdout", 18, 0); + Tcl_RestoreResult(magicinterp, &state); +} + +/*--------------------------------------------------------------*/ + +void +TxFlush() +{ + TxFlushOut(); + TxFlushErr(); +} + +/*--------------------------------------------------------------*/ +/* Tcl_printf() replaces vfprintf() for use by every Tx output */ +/* function (namely, TxError() for stderr and TxPrintf() for */ +/* stdout). It changes the result to a Tcl "puts" call, which */ +/* can be changed inside Tcl, as, for example, by TkCon. */ +/* */ +/* 6/17/04---Routine extended to escape double-dollar-sign '$$' */ +/* which is used by some tools when generating via cells. */ +/* */ +/* 12/23/16---Noted that using consoleinterp simply prevents */ +/* the output from being redirected to another window such as */ +/* the command entry window. Split off another bit TxTkOutput */ +/* from TxTkConsole and set it to zero by default. The */ +/* original behavior can be restored using the *flags wizard */ +/* command (*flags printf true). */ +/*--------------------------------------------------------------*/ + +int +Tcl_printf(FILE *f, char *fmt, va_list args_in) +{ + va_list args; + static char outstr[128] = "puts -nonewline std"; + char *outptr, *bigstr = NULL, *finalstr = NULL; + int i, nchars, result, escapes = 0, limit; + Tcl_Interp *printinterp = (TxTkOutput) ? consoleinterp : magicinterp; + + strcpy (outstr + 19, (f == stderr) ? "err \"" : "out \""); + + va_copy(args, args_in); + outptr = outstr; + nchars = vsnprintf(outptr + 24, 102, fmt, args); + va_end(args); + + if (nchars >= 102) + { + va_copy(args, args_in); + bigstr = Tcl_Alloc(nchars + 26); + strncpy(bigstr, outptr, 24); + outptr = bigstr; + vsnprintf(outptr + 24, nchars + 2, fmt, args); + va_end(args); + } + else if (nchars == -1) nchars = 126; + + for (i = 24; *(outptr + i) != '\0'; i++) + { + if (*(outptr + i) == '\"' || *(outptr + i) == '[' || + *(outptr + i) == ']' || *(outptr + i) == '\\') + escapes++; + else if (*(outptr + i) == '$' && *(outptr + i + 1) == '$') + escapes += 2; + } + + if (escapes > 0) + { + /* "+ 4" required to process "$$...$$"; haven't figured out why. */ + finalstr = Tcl_Alloc(nchars + escapes + 26 + 4); + strncpy(finalstr, outptr, 24); + escapes = 0; + for (i = 24; *(outptr + i) != '\0'; i++) + { + if (*(outptr + i) == '\"' || *(outptr + i) == '[' || + *(outptr + i) == ']' || *(outptr + i) == '\\') + { + *(finalstr + i + escapes) = '\\'; + escapes++; + } + else if (*(outptr + i) == '$' && *(outptr + i + 1) == '$') + { + *(finalstr + i + escapes) = '\\'; + *(finalstr + i + escapes + 1) = '$'; + *(finalstr + i + escapes + 2) = '\\'; + escapes += 2; + i++; + } + *(finalstr + i + escapes) = *(outptr + i); + } + outptr = finalstr; + } + + *(outptr + 24 + nchars + escapes) = '\"'; + *(outptr + 25 + nchars + escapes) = '\0'; + + result = Tcl_EvalEx(printinterp, outptr, -1, 0); + + if (bigstr != NULL) Tcl_Free(bigstr); + if (finalstr != NULL) Tcl_Free(finalstr); + + return result; +} + +/*--------------------------------------------------------------*/ +/* Tcl_escape() takes a string as input and produces a string */ +/* in which characters are escaped as necessary to make them */ +/* printable from Tcl. The new string is allocated by */ +/* Tcl_Alloc() which needs to be free'd with Tcl_Free(). */ +/* */ +/* 6/17/04---extended like Tcl_printf to escape double-dollar- */ +/* sign ('$$') in names. */ +/*--------------------------------------------------------------*/ + +char * +Tcl_escape(instring) + char *instring; +{ + char *newstr; + int nchars = 0; + int escapes = 0; + int i; + + for (i = 0; *(instring + i) != '\0'; i++) + { + nchars++; + if (*(instring + i) == '\"' || *(instring + i) == '[' || + *(instring + i) == ']') + escapes++; + + else if (*(instring + i) == '$' && *(instring + i + 1) == '$') + escapes += 2; + } + + newstr = Tcl_Alloc(nchars + escapes + 1); + escapes = 0; + for (i = 0; *(instring + i) != '\0'; i++) + { + if (*(instring + i) == '\"' || *(instring + i) == '[' || + *(instring + i) == ']') + { + *(newstr + i + escapes) = '\\'; + escapes++; + } + else if (*(instring + i) == '$' && *(instring + i + 1) == '$') + { + *(newstr + i + escapes) = '\\'; + *(newstr + i + escapes + 1) = '$'; + *(newstr + i + escapes + 2) = '\\'; + escapes += 2; + i++; + } + *(newstr + i + escapes) = *(instring + i); + } + *(newstr + i + escapes) = '\0'; + return newstr; +} + +/*--------------------------------------------------------------*/ + +int +TerminalInputProc(instanceData, buf, toRead, errorCodePtr) + ClientData instanceData; + char *buf; + int toRead; + int *errorCodePtr; +{ + FileState *fsPtr = (FileState *)instanceData; + int bytesRead, i, tlen; + char *locbuf; + + *errorCodePtr = 0; + + TxInputRedirect = TX_INPUT_NORMAL; + if (TxBuffer != NULL) { + tlen = strlen(TxBuffer); + if (tlen < toRead) { + strcpy(buf, TxBuffer); + Tcl_Free(TxBuffer); + TxBuffer = NULL; + return tlen; + } + else { + strncpy(buf, TxBuffer, toRead); + locbuf = Tcl_Alloc(tlen - toRead + 1); + strcpy(locbuf, TxBuffer + toRead); + Tcl_Free(TxBuffer); + TxBuffer = locbuf; + return toRead; + } + } + + while (1) { + bytesRead = read(fsPtr->fd, buf, (size_t) toRead); + if (bytesRead > -1) + return bytesRead; + + // Ignore interrupts, which may be generated by new + // terminal windows (added by Tim, 9/30/2014) + + if (errno != EINTR) break; + } + *errorCodePtr = errno; + + return -1; +} + +/*--------------------------------------------------------------*/ + +int +Tclmagic_Init(interp) + Tcl_Interp *interp; +{ + char *cadroot; + + /* Sanity check! */ + if (interp == NULL) return TCL_ERROR; + + /* Remember the interpreter */ + magicinterp = interp; + + if (Tcl_InitStubs(interp, "8.1", 0) == NULL) return TCL_ERROR; + + /* Initialization and Startup commands */ + Tcl_CreateCommand(interp, "magic::initialize", (Tcl_CmdProc *)_magic_initialize, + (ClientData)NULL, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, "magic::startup", (Tcl_CmdProc *)_magic_startup, + (ClientData)NULL, (Tcl_CmdDeleteProc *) NULL); + + /* Initialize the command-tag callback feature */ + + HashInit(&txTclTagTable, 10, HT_STRINGKEYS); + Tcl_CreateCommand(interp, "magic::tag", (Tcl_CmdProc *)AddCommandTag, + (ClientData)NULL, (Tcl_CmdDeleteProc *) NULL); + + /* Add "*flags" command for manipulating run-time flags */ + Tcl_CreateObjCommand(interp, "magic::*flags", (Tcl_ObjCmdProc *)_magic_flags, + (ClientData)NULL, (Tcl_CmdDeleteProc *) NULL); + + /* Add the magic TCL directory to the Tcl library search path */ + + Tcl_Eval(interp, "lappend auto_path " TCL_DIR ); + + /* Set $CAD_ROOT as a Tcl variable */ + + cadroot = getenv("CAD_ROOT"); + if (cadroot == NULL) cadroot = CAD_DIR; + + Tcl_SetVar(interp, "CAD_ROOT", cadroot, TCL_GLOBAL_ONLY); + + Tcl_PkgProvide(interp, "Tclmagic", MAGIC_VERSION); + return TCL_OK; +} + +/*--------------------------------------------------------------*/ +/* Define a "safe init" function for those platforms that */ +/* require it. */ +/*--------------------------------------------------------------*/ + +int +Tclmagic_SafeInit(interp) + Tcl_Interp *interp; +{ + return Tclmagic_Init(interp); +} diff --git a/tcltk/tclmagic.h b/tcltk/tclmagic.h new file mode 100644 index 00000000..7c4271e9 --- /dev/null +++ b/tcltk/tclmagic.h @@ -0,0 +1,34 @@ +/* + * tclmagic.h -- + * + * Header file for including Tcl/Tk stuff. Note that this must be + * included prior to all the other magic include files; otherwise + * the definition for "ClientData" is in conflict. + */ + +#ifndef _TCLMAGIC_H +#define _TCLMAGIC_H + +#ifdef MAGIC_WRAPPER + +#include +#include + +/* Externally-defined global variables */ + +extern Tcl_Interp *magicinterp; +extern Tcl_Interp *consoleinterp; + +/* Forward declaration of procedures */ + +extern char *Tcl_escape(); +extern int TagVerify(); + +/* Backward compatibility issues */ +#ifndef CONST84 +#define CONST84 /* indicates something was changed to "const" */ + /* in Tcl version 8.4. */ +#endif + +#endif /* MAGIC_WRAPPER */ +#endif /* _TCLMAGIC_H */ diff --git a/tcltk/techbuilder.tcl b/tcltk/techbuilder.tcl new file mode 100644 index 00000000..b3d0e247 --- /dev/null +++ b/tcltk/techbuilder.tcl @@ -0,0 +1,113 @@ +# +# The long-awaited Technology File Builder Wizard +# + +# Needs BLT to build tab windows +package require BLT + +toplevel .techwizard +blt::tabset .techwizard.parts -relief sunken -borderwidth 2 + +magic::windowcaption off +magic::windowscrollbars off + +frame .techwizard.parts.layers +frame .techwizard.parts.drc + +magic::openwindow tech_layers .techwizard.parts.layers.layout +magic::openwindow drc_rules .techwizard.parts.drc.layout + +frame .techwizard.parts.layers.funcs +label .techwizard.parts.layers.funcs.prompt -text "Add:" +label .techwizard.parts.layers.funcs.prompt2 -text "Plane:" +entry .techwizard.parts.layers.funcs.lname +menubutton .techwizard.parts.layers.funcs.planes -text "(choose one)" \ + -relief groove +pack .techwizard.parts.layers.funcs.prompt -side left -padx 5 +pack .techwizard.parts.layers.funcs.lname -side left -expand true -fill x +pack .techwizard.parts.layers.funcs.prompt2 -side left -padx 5 +pack .techwizard.parts.layers.funcs.planes -side left -pady 5 + +pack .techwizard.parts.layers.layout -side top -expand true -fill both +pack .techwizard.parts.layers.funcs -side top -fill x + +frame .techwizard.parts.drc.funcs +button .techwizard.parts.drc.funcs.last -text "Last" +button .techwizard.parts.drc.funcs.next -text "Next" +pack .techwizard.parts.drc.funcs.last -side left +pack .techwizard.parts.drc.funcs.next -side left +pack .techwizard.parts.drc.layout -side top -expand true -fill both +pack .techwizard.parts.drc.funcs -side top -fill x + +frame .techwizard.parts.tech +frame .techwizard.parts.tech.tinfo +label .techwizard.parts.tech.tinfo.tname -text "Technology name:" \ + -foreground sienna4 +entry .techwizard.parts.tech.tinfo.tentry -width 50 +bind .techwizard.parts.tech.tinfo.tentry { \ + .techwizard.parts.tech.tinfo.tset configure -text \ + [.techwizard.parts.tech.tinfo.tentry get]; \ + pack forget .techwizard.parts.tech.tinfo.tentry; \ + } +button .techwizard.parts.tech.tinfo.tset -text "[magic::tech name]" \ + -relief groove \ + -foreground green4 \ + -command { \ + pack .techwizard.parts.tech.tinfo.tentry -side left -expand true; \ + } +pack .techwizard.parts.tech.tinfo.tname -side left +pack .techwizard.parts.tech.tinfo.tset -side left +pack .techwizard.parts.tech.tinfo -side top + +frame .techwizard.parts.planes +::set pnames [magic::tech planes] +::set j 0 +foreach i $pnames { + entry .techwizard.parts.planes.e$i -width 50 + bind .techwizard.parts.planes.e$i \ + ".techwizard.parts.planes.p$i configure -text \ + [.techwizard.parts.planes.e$i get]; \ + ::grid forget .techwizard.parts.planes.e$i" + button .techwizard.parts.planes.p$i -text "$i" \ + -foreground green4 \ + -relief groove \ + -command "::grid .techwizard.parts.planes.e$i -row $j -column 1 -sticky news" + ::grid .techwizard.parts.planes.p$i -row $j -column 0 -sticky news + incr j +} +::unset pnames +::unset j + +.techwizard.parts configure -tiers 2 +.techwizard.parts insert end "tech" "planes" "layers" "connect" "compose" \ + "cifinput" "cifoutput" "extract" "drc" \ + "wiring" "router" "plowing" "plot" + +.techwizard.parts tab configure "layers" -window .techwizard.parts.layers -fill both +.techwizard.parts tab configure "drc" -window .techwizard.parts.drc -fill both +.techwizard.parts tab configure "tech" -window .techwizard.parts.tech +.techwizard.parts tab configure "planes" -window .techwizard.parts.planes + +# Add styles to layout for selection + +::set i 0 +::set j 0 +::set k 50 +while { $k <= 127 } { + ::set rx [expr $i + 8] + ::set ry [expr $j + 8] + .techwizard.parts.layers.layout element add rect style$k $k $i $j $rx $ry + incr k + incr i 10 + if {$i >= 80} {::set i 0; incr j 10} +} +catch {.techwizard.parts.layers.layout box -100 -10 90 90} +catch {.techwizard.parts.layers.layout findbox zoom} +catch {.techwizard.parts.layers.layout box -100 -10 -10 90} + +.techwizard.parts.layers.layout element add text ltitle black 40 85 "Layer Styles" + +# To do: Add all existing layers and draw their styles + +pack .techwizard.parts -fill both -expand true +wm geometry .techwizard 800x500 diff --git a/tcltk/texthelper.tcl b/tcltk/texthelper.tcl new file mode 100644 index 00000000..a0259d99 --- /dev/null +++ b/tcltk/texthelper.tcl @@ -0,0 +1,396 @@ +# Text helper window + +set textdefaults [dict create \ + text "" \ + font "FreeSans" \ + size "1" \ + just "center" \ + rotate "0" \ + offset "0 0" \ + port "0" \ +] + +proc magic::make_texthelper { mgrpath } { + global typedflt typesticky typeport + toplevel ${mgrpath} + wm withdraw ${mgrpath} + + frame ${mgrpath}.title + frame ${mgrpath}.text + frame ${mgrpath}.font + frame ${mgrpath}.size + frame ${mgrpath}.just + frame ${mgrpath}.rotate + frame ${mgrpath}.offset + frame ${mgrpath}.layer + frame ${mgrpath}.port + + frame ${mgrpath}.buttonbar + + label ${mgrpath}.title.tlab -text "New label: " + + label ${mgrpath}.text.tlab -text "Text string: " + label ${mgrpath}.font.tlab -text "Font: " + label ${mgrpath}.size.tlab -text "Size (um): " + label ${mgrpath}.just.tlab -text "Justification: " + label ${mgrpath}.rotate.tlab -text "Rotation: " + label ${mgrpath}.offset.tlab -text "Offset from reference: " + label ${mgrpath}.layer.tlab -text "Attach to layer: " + label ${mgrpath}.port.tlab -text "Port: " + + entry ${mgrpath}.text.tent -background white + entry ${mgrpath}.size.tent -background white + entry ${mgrpath}.rotate.tent -background white + entry ${mgrpath}.offset.tent -background white + entry ${mgrpath}.layer.tent -background white + entry ${mgrpath}.port.tent -background white + + set typedflt 1 + set typesticky 0 + set typeport 0 + checkbutton ${mgrpath}.layer.btn1 -text "default" -variable typedflt \ + -command [subst {if {\$typedflt} {pack forget ${mgrpath}.layer.tent \ + } else {pack forget ${mgrpath}.layer.btn2; \ + pack ${mgrpath}.layer.tent -side left -fill x -expand true; \ + pack ${mgrpath}.layer.btn2 -side left}}] + checkbutton ${mgrpath}.layer.btn2 -text "sticky" -variable typesticky + checkbutton ${mgrpath}.port.btn -text "enable" -variable typeport \ + -command [subst {if {\$typeport} { + ${mgrpath}.port.tent delete 0 end; \ + ${mgrpath}.port.tent insert 0 \[expr {\[port last\] + 1}\]; \ + pack ${mgrpath}.port.tent \ + -side left -fill x -expand true } else { pack forget \ + ${mgrpath}.port.tent }}] + + menubutton ${mgrpath}.just.btn -text "default" -menu ${mgrpath}.just.btn.menu + menubutton ${mgrpath}.font.btn -text "default" -menu ${mgrpath}.font.btn.menu + + button ${mgrpath}.buttonbar.cancel -text "Cancel" -command "wm withdraw ${mgrpath}" + button ${mgrpath}.buttonbar.apply -text "Apply" + button ${mgrpath}.buttonbar.okay -text "Okay" + + pack ${mgrpath}.title.tlab + pack ${mgrpath}.text.tlab -side left + pack ${mgrpath}.text.tent -side right -fill x -expand true + pack ${mgrpath}.font.tlab -side left + pack ${mgrpath}.font.btn -side left + pack ${mgrpath}.size.tlab -side left + pack ${mgrpath}.size.tent -side right -fill x -expand true + pack ${mgrpath}.just.tlab -side left + pack ${mgrpath}.just.btn -side left + pack ${mgrpath}.rotate.tlab -side left + pack ${mgrpath}.rotate.tent -side right -fill x -expand true + pack ${mgrpath}.offset.tlab -side left + pack ${mgrpath}.offset.tent -side right -fill x -expand true + pack ${mgrpath}.layer.tlab -side left + pack ${mgrpath}.layer.btn1 -side left + pack ${mgrpath}.layer.btn2 -side left + pack ${mgrpath}.port.tlab -side left + pack ${mgrpath}.port.btn -side left + + pack ${mgrpath}.buttonbar.apply -side left + pack ${mgrpath}.buttonbar.okay -side left + pack ${mgrpath}.buttonbar.cancel -side right + + pack ${mgrpath}.title -side top + pack ${mgrpath}.text -side top -anchor w -expand true + pack ${mgrpath}.font -side top -anchor w + pack ${mgrpath}.size -side top -anchor w -expand true + pack ${mgrpath}.just -side top -anchor w + pack ${mgrpath}.rotate -side top -anchor w -expand true + pack ${mgrpath}.offset -side top -anchor w -expand true + pack ${mgrpath}.layer -side top -anchor w -expand true + pack ${mgrpath}.port -side top -anchor w -expand true + pack ${mgrpath}.buttonbar -side bottom -fill x -expand true + + # Create menus for Font and Justification records + + menu ${mgrpath}.just.btn.menu -tearoff 0 + menu ${mgrpath}.font.btn.menu -tearoff 0 + + ${mgrpath}.just.btn.menu add command -label "default" -command \ + "${mgrpath}.just.btn config -text default" + ${mgrpath}.just.btn.menu add command -label "N" -command \ + "${mgrpath}.just.btn config -text N" + ${mgrpath}.just.btn.menu add command -label "NE" -command \ + "${mgrpath}.just.btn config -text NE" + ${mgrpath}.just.btn.menu add command -label "E" -command \ + "${mgrpath}.just.btn config -text E" + ${mgrpath}.just.btn.menu add command -label "SE" -command \ + "${mgrpath}.just.btn config -text SE" + ${mgrpath}.just.btn.menu add command -label "S" -command \ + "${mgrpath}.just.btn config -text S" + ${mgrpath}.just.btn.menu add command -label "SW" -command \ + "${mgrpath}.just.btn config -text SW" + ${mgrpath}.just.btn.menu add command -label "W" -command \ + "${mgrpath}.just.btn config -text W" + ${mgrpath}.just.btn.menu add command -label "NW" -command \ + "${mgrpath}.just.btn config -text NW" + ${mgrpath}.just.btn.menu add command -label "center" -command \ + "${mgrpath}.just.btn config -text center" + + set flist [magic::setlabel fontlist] + ${mgrpath}.font.btn.menu add command -label default -command \ + "${mgrpath}.font.btn config -text default" + foreach i $flist { + ${mgrpath}.font.btn.menu add command -label $i -command \ + "${mgrpath}.font.btn config -text $i" + } + + # Set up tag callbacks + + magic::tag select "[magic::tag select]; magic::update_texthelper" +} + +# For all editable selected labels, fill in entries in the +# texthelper window + +proc magic::analyze_labels {} { + global typedflt typesticky typeport + + # Pick up values from the first entry returned + + set tval [lindex [setlabel text] 0] + set jval [lindex [setlabel justify] 0] + set fval [lindex [setlabel font] 0] + set rval [lindex [setlabel rotate] 0] + set oval [lindex [setlabel offset] 0] + set lval [lindex [setlabel layer] 0] + set kval [lindex [setlabel sticky] 0] + set pval [lindex [port index] 0] + + # Rescale internal units to microns + set sval [lindex [setlabel size] 0] + set sscale [cif scale out] + set tmp_pre $::tcl_precision + set ::tcl_precision 3 + set sval [expr $sscale * $sval] + set ::tcl_precision $tmp_pre + + .texthelper.text.tent delete 0 end + .texthelper.text.tent insert 0 $tval + set jbtn [string map {NORTH N WEST W SOUTH S EAST E CENTER center} $jval] + .texthelper.just.btn.menu invoke $jbtn + .texthelper.font.btn.menu invoke $fval + .texthelper.size.tent delete 0 end + .texthelper.size.tent insert 0 $sval + .texthelper.offset.tent delete 0 end + .texthelper.offset.tent insert 0 [join $oval] + .texthelper.rotate.tent delete 0 end + .texthelper.rotate.tent insert 0 $rval + .texthelper.layer.tent delete 0 end + .texthelper.layer.tent insert 0 $lval + if {${pval} >= 0} { + set typeport 1 + .texthelper.port.tent delete 0 end + .texthelper.port.tent insert 0 $pval + pack .texthelper.port.tent -side left -fill x -expand true + } else { + set typeport 0 + .texthelper.port.tent delete 0 end + pack forget .texthelper.port.tent + } + + set typesticky $kval + if {$lval == ""} { + set typedflt 1 + pack forget .texthelper.layer.tent + } else { + set typedflt 0 + pack forget .texthelper.layer.btn2 + pack .texthelper.layer.tent -side left -fill x -expand true + pack .texthelper.layer.btn2 -side left + } +} + + +proc magic::change_label {} { + global typedflt typesticky typeport + + # Check to see if there really was a selection, or if + # something got unselected + + if {[setlabel text] == ""} { + magic::make_new_label + return + } + + set ltext [.texthelper.text.tent get] + set lfont [.texthelper.font.btn cget -text] + set lsize [.texthelper.size.tent get] + set lrot [.texthelper.rotate.tent get] + set loff [.texthelper.offset.tent get] + set ljust [.texthelper.just.btn cget -text] + set ltype [.texthelper.layer.tent get] + set lport [.texthelper.port.tent get] + + if {$ltext != ""} { + setlabel text $ltext + } + if {$lfont != ""} { + if {$lfont == "default"} { + setlabel font -1 + } else { + setlabel font $lfont + } + } + if {$ljust != ""} { + if {$ljust == "default"} { + setlabel justify -1 + } else { + setlabel justify $ljust + } + } + if {$lsize != ""} { + setlabel size ${lsize}um + } + if {$loff != ""} { + set oldsnap [snap list] + snap internal + setlabel offset [join $loff] + snap $oldsnap + } + if {$lrot != ""} { + setlabel rotate $lrot + } + if {$ltype != ""} { + setlabel layer $ltype + } + setlabel sticky $typesticky +} + +proc magic::make_new_label {} { + global typedflt typesticky textdefaults typeport + + set ltext [.texthelper.text.tent get] + set lfont [.texthelper.font.btn cget -text] + set lsize [.texthelper.size.tent get] + set lrot [.texthelper.rotate.tent get] + set loff [.texthelper.offset.tent get] + set ljust [.texthelper.just.btn cget -text] + set ltype [.texthelper.layer.tent get] + set lport [.texthelper.port.tent get] + + # Apply values back to window defaults + dict set textdefaults text $ltext + dict set textdefaults font $lfont + dict set textdefaults size $lsize + dict set textdefaults rotate $lrot + dict set textdefaults offset $loff + dict set textdefaults just $ljust + + if {$ltext == ""} return ;# don't generate null label strings! + + if {$lfont == {} || $lfont == "default"} { + label $ltext $ljust + return + } + + if {$lsize == "0" || $lsize == ""} {set lsize 1} + if {$lrot == ""} {set lrot 0} + if {$loff == ""} {set loff "0 0"} + + if {$typedflt == 1 || $ltype == ""} { + if {$ljust == "default"} { + label $ltext $lfont ${lsize}um $lrot [join $loff] + } else { + label $ltext $lfont ${lsize}um $lrot [join $loff] $ljust + } + } else { + if {$typesticky == 1} {set ltype "-$ltype"} + if {$ljust == "default"} { + label $ltext $lfont ${lsize}um $lrot [join $loff] center $ltype + } else { + label $ltext $lfont ${lsize}um $lrot [join $loff] $ljust $ltype + } + } + if {$typeport == 1 && $lport != ""} { + port make $lport + } else { + port remove + } + + # puts stdout "label $ltext $lfont $lsize $lrot $loff $ljust" +} + +#-------------------------------------------------------------------- +# Update and redisplay the text helper +#-------------------------------------------------------------------- + +proc magic::update_texthelper {} { + global CAD_ROOT + global textdefaults + + if {[info level] > 1} { + return + } + if {[catch {set tstate [wm state .texthelper]}]} { + magic::make_texthelper .texthelper + } else { + if {$tstate == "withdrawn"} {return} + } + + # Update: Determine if a label has been selected or not. If so, + # analyze the label list to determine which properties are common + # to all the selected labels + + set splist [lindex [what -list] 1] + + # Reduce list to what's editable + set slist [] + foreach sitem $splist { + set scell [lindex $sitem 2] + if {$scell == {}} { + lappend slist $sitem + } + } + + if {$slist == {}} { + .texthelper.title.tlab configure -text "New label: " + .texthelper.text.tent delete 0 end + .texthelper.text.tent insert 0 [dict get $textdefaults text] + + set deffont [dict get $textdefaults font] + set found 0 + for {set i 0} {$i <= [.texthelper.font.btn.menu index end]} {incr i} { + set btnname [.texthelper.font.btn.menu entrycget $i -label] + if {$btnname == $deffont} {.texthelper.font.btn.menu invoke $i} + set found 1 + } + if {$found == 0} {.texthelper.font.btn.menu invoke 0} + + set defjust [dict get $textdefaults just] + set found 0 + for {set i 0} {$i <= [.texthelper.just.btn.menu index end]} {incr i} { + set btnname [.texthelper.just.btn.menu entrycget $i -label] + if {$btnname == $defjust} {.texthelper.just.btn.menu invoke $i} + set found 1 + } + if {$found == 0} {.texthelper.just.btn.menu invoke 0} + + .texthelper.size.tent delete 0 end + .texthelper.size.tent insert 0 [dict get $textdefaults size] + .texthelper.rotate.tent delete 0 end + .texthelper.rotate.tent insert 0 [dict get $textdefaults rotate] + .texthelper.offset.tent delete 0 end + .texthelper.offset.tent insert 0 [dict get $textdefaults offset] + set pval [port last] + incr pval + .texthelper.port.tent delete 0 end + .texthelper.port.tent insert 0 $pval + .texthelper.buttonbar.apply configure -command magic::make_new_label + .texthelper.buttonbar.okay configure -command \ + "magic::make_new_label ; wm withdraw .texthelper" + } else { + if {[llength $slist] == 1} { + .texthelper.title.tlab configure -text "Selected label: " + } else { + .texthelper.title.tlab configure -text "Selected labels: " + } + magic::analyze_labels + .texthelper.buttonbar.apply configure -command magic::change_label + .texthelper.buttonbar.okay configure -command \ + "magic::change_label ; wm withdraw .texthelper" + } +} + diff --git a/tcltk/tkcon.tcl b/tcltk/tkcon.tcl new file mode 100755 index 00000000..a4efbbb3 --- /dev/null +++ b/tcltk/tkcon.tcl @@ -0,0 +1,5330 @@ +#!/bin/sh +# \ +exec ${MAGIC_WISH:=wish} "$0" ${1+"$@"} + +# +## tkcon.tcl +## Enhanced Tk Console, part of the VerTcl system +## +## Originally based off Brent Welch's Tcl Shell Widget +## (from "Practical Programming in Tcl and Tk") +## +## Thanks to the following (among many) for early bug reports & code ideas: +## Steven Wahl , Jan Nijtmans +## Crimmins , Wart +## +## Copyright 1995-2001 Jeffrey Hobbs +## Initiated: Thu Aug 17 15:36:47 PDT 1995 +## +## jeff.hobbs@acm.org, jeff@hobbs.org +## +## source standard_disclaimer.tcl +## source bourbon_ware.tcl +## + +# Proxy support for retrieving the current version of Tkcon. +# +# Mon Jun 25 12:19:56 2001 - Pat Thoyts +# +# In your tkcon.cfg or .tkconrc file put your proxy details into the +# `proxy' member of the `PRIV' array. e.g.: +# +# set ::tkcon::PRIV(proxy) wwwproxy:8080 +# +# If you want to be prompted for proxy authentication details (eg for +# an NT proxy server) make the second element of this variable non-nil - eg: +# +# set ::tkcon::PRIV(proxy) {wwwproxy:8080 1} +# +# Or you can set the above variable from within tkcon by calling +# +# tkcon master set ::tkcon:PRIV(proxy) wwwproxy:8080 +# + +if {$tcl_version < 8.0} { + return -code error "tkcon requires at least Tcl/Tk8" +} else { + # Prevent breaking on version 8.5.2 + # package require -exact Tk $tcl_version + package require Tk $tcl_version +} + +catch {package require bogus-package-name} +foreach pkg [info loaded {}] { + set file [lindex $pkg 0] + set name [lindex $pkg 1] + if {![catch {set version [package require $name]}]} { + if {[string match {} [package ifneeded $name $version]]} { + package ifneeded $name $version [list load $file $name] + } + } +} +catch {unset pkg file name version} + +# Tk 8.4 makes previously exposed stuff private. +# FIX: Update tkcon to not rely on the private Tk code. +# +if {![llength [info globals tkPriv]]} { + ::tk::unsupported::ExposePrivateVariable tkPriv +} +foreach cmd {SetCursor UpDownLine Transpose ScrollPages} { + if {![llength [info commands tkText$cmd]]} { + ::tk::unsupported::ExposePrivateCommand tkText$cmd + } +} + +# Initialize the ::tkcon namespace +# +namespace eval ::tkcon { + # The OPT variable is an array containing most of the optional + # info to configure. COLOR has the color data. + variable OPT + variable COLOR + + # PRIV is used for internal data that only tkcon should fiddle with. + variable PRIV + set PRIV(WWW) [info exists embed_args] +} + +## ::tkcon::Init - inits tkcon +# +# Calls: ::tkcon::InitUI +# Outputs: errors found in tkcon's resource file +## +proc ::tkcon::Init {} { + variable OPT + variable COLOR + variable PRIV + global tcl_platform env argc argv tcl_interactive errorInfo + + if {![info exists argv]} { + set argv {} + set argc 0 + } + + set tcl_interactive 1 + + if {[info exists PRIV(name)]} { + set title $PRIV(name) + } else { + MainInit + # some main initialization occurs later in this proc, + # to go after the UI init + set MainInit 1 + set title Main + } + + ## + ## When setting up all the default values, we always check for + ## prior existence. This allows users who embed tkcon to modify + ## the initial state before tkcon initializes itself. + ## + + # bg == {} will get bg color from the main toplevel (in InitUI) + foreach {key default} { + bg {} + blink \#FFFF00 + cursor \#000000 + disabled \#4D4D4D + proc \#008800 + var \#FFC0D0 + prompt \#8F4433 + stdin \#000000 + stdout \#0000FF + stderr \#FF0000 + } { + if {![info exists COLOR($key)]} { set COLOR($key) $default } + } + + foreach {key default} { + autoload {} + blinktime 500 + blinkrange 1 + buffer 512 + calcmode 0 + cols 80 + debugPrompt {(level \#$level) debug [history nextid] > } + dead {} + expandorder {Pathname Variable Procname} + font {} + history 48 + hoterrors 1 + library {} + lightbrace 1 + lightcmd 1 + maineval {} + maxmenu 15 + nontcl 0 + prompt1 {ignore this, it's set below} + rows 20 + scrollypos right + showmenu 1 + showmultiple 1 + showstatusbar 0 + slaveeval {} + slaveexit close + subhistory 1 + gc-delay 60000 + gets {congets} + usehistory 1 + + exec slave + } { + if {![info exists OPT($key)]} { set OPT($key) $default } + } + + foreach {key default} { + app {} + appname {} + apptype slave + namesp :: + cmd {} + cmdbuf {} + cmdsave {} + event 1 + deadapp 0 + deadsock 0 + debugging 0 + displayWin . + histid 0 + find {} + find,case 0 + find,reg 0 + errorInfo {} + showOnStartup 1 + slavealias { edit more less tkcon } + slaveprocs { + alias clear dir dump echo idebug lremove + tkcon_puts tkcon_gets observe observe_var unalias which what + } + version 2.3 + RCS {RCS: @(#) $Id: tkcon.tcl,v 1.2 2008/09/03 17:32:42 tim Exp $} + HEADURL {http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/tkcon/tkcon/tkcon.tcl?rev=HEAD} + docs "http://tkcon.sourceforge.net/" + email {jeff@hobbs.org} + root . + } { + if {![info exists PRIV($key)]} { set PRIV($key) $default } + } + + ## NOTES FOR STAYING IN PRIMARY INTERPRETER: + ## + ## If you set ::tkcon::OPT(exec) to {}, then instead of a multiple + ## interp model, you get tkcon operating in the main interp by default. + ## This can be useful when attaching to programs that like to operate + ## in the main interpter (for example, based on special wish'es). + ## You can set this from the command line with -exec "" + ## A side effect is that all tkcon command line args will be used + ## by the first console only. + #set OPT(exec) {} + + if {$PRIV(WWW)} { + lappend PRIV(slavealias) history + set OPT(prompt1) {[history nextid] % } + } else { + lappend PRIV(slaveprocs) tcl_unknown unknown + set OPT(prompt1) {([file tail [pwd]]) [history nextid] % } + } + + ## If we are using the default '.' toplevel, and there appear to be + ## children of '.', then make sure we use a disassociated toplevel. + if {$PRIV(root) == "." && [llength [winfo children .]]} { + set PRIV(root) .tkcon + } + + ## Do platform specific configuration here, other than defaults + ### Use tkcon.cfg filename for resource filename on non-unix systems + ### Determine what directory the resource file should be in + switch $tcl_platform(platform) { + macintosh { + if {![interp issafe]} {cd [file dirname [info script]]} + set envHome PREF_FOLDER + set rcfile tkcon.cfg + set histfile magic_tkcon.hst + catch {console hide} + } + windows { + set envHome HOME + set rcfile tkcon.cfg + set histfile magic_tkcon.hst + } + unix { + set envHome HOME + set rcfile .tkconrc + set histfile .magic_tkcon_hst + } + } + if {[info exists env($envHome)]} { + if {![info exists PRIV(rcfile)]} { + set PRIV(rcfile) [file join $env($envHome) $rcfile] + } + if {![info exists PRIV(histfile)]} { + set PRIV(histfile) [file join $env($envHome) $histfile] + } + } + + ## Handle command line arguments before sourcing resource file to + ## find if resource file is being specified (let other args pass). + if {[set i [lsearch -exact $argv -rcfile]] != -1} { + set PRIV(rcfile) [lindex $argv [incr i]] + } + + if {!$PRIV(WWW) && [file exists $PRIV(rcfile)]} { + set code [catch {uplevel \#0 [list source $PRIV(rcfile)]} err] + } + + if {[info exists env(TK_CON_LIBRARY)]} { + lappend ::auto_path $env(TK_CON_LIBRARY) + } else { + lappend ::auto_path $OPT(library) + } + + if {![info exists ::tcl_pkgPath]} { + set dir [file join [file dirname [info nameofexec]] lib] + if {[llength [info commands @scope]]} { + set dir [file join $dir itcl] + } + catch {source [file join $dir pkgIndex.tcl]} + } + catch {tclPkgUnknown dummy-name dummy-version} + + ## Handle rest of command line arguments after sourcing resource file + ## and slave is created, but before initializing UI or setting packages. + set slaveargs {} + set slavefiles {} + set truth {^(1|yes|true|on)$} + for {set i 0} {$i < $argc} {incr i} { + set arg [lindex $argv $i] + if {[string match {-*} $arg]} { + set val [lindex $argv [incr i]] + ## Handle arg based options + switch -glob -- $arg { + -- - -argv { + set argv [concat -- [lrange $argv $i end]] + set argc [llength $argv] + break + } + -color-* { set COLOR([string range $arg 7 end]) $val } + -exec { set OPT(exec) $val } + -main - -e - -eval { append OPT(maineval) \n$val\n } + -package - -load { lappend OPT(autoload) $val } + -slave { append OPT(slaveeval) \n$val\n } + -nontcl { set OPT(nontcl) [regexp -nocase $truth $val]} + -root { set PRIV(root) $val } + -font { set OPT(font) $val } + -rcfile {} + default { lappend slaveargs $arg; incr i -1 } + } + } elseif {[file isfile $arg]} { + lappend slavefiles $arg + } else { + lappend slaveargs $arg + } + } + + ## Create slave executable + if {[string compare {} $OPT(exec)]} { + uplevel \#0 ::tkcon::InitSlave $OPT(exec) $slaveargs + } else { + set argc [llength $slaveargs] + set argv $slaveargs + uplevel \#0 $slaveargs + } + + ## Attach to the slave, EvalAttached will then be effective + Attach $PRIV(appname) $PRIV(apptype) + InitUI $title + + ## swap puts and gets with the tkcon versions to make sure all + ## input and output is handled by tkcon + if {![catch {rename ::puts ::tkcon_tcl_puts}]} { + interp alias {} ::puts {} ::tkcon_puts + } + if {($OPT(gets) != "") && ![catch {rename ::gets ::tkcon_tcl_gets}]} { + interp alias {} ::gets {} ::tkcon_gets + } + + EvalSlave history keep $OPT(history) + if {[info exists MainInit]} { + # Source history file only for the main console, as all slave + # consoles will adopt from the main's history, but still + # keep separate histories + if {!$PRIV(WWW) && $OPT(usehistory) && [file exists $PRIV(histfile)]} { + puts -nonewline "loading history file ... " + # The history file is built to be loaded in and + # understood by tkcon + if {[catch {uplevel \#0 [list source $PRIV(histfile)]} herr]} { + puts stderr "error:\n$herr" + append PRIV(errorInfo) $errorInfo\n + } + set PRIV(event) [EvalSlave history nextid] + puts "[expr {$PRIV(event)-1}] events added" + } + } + + ## Autoload specified packages in slave + set pkgs [EvalSlave package names] + foreach pkg $OPT(autoload) { + puts -nonewline "autoloading package \"$pkg\" ... " + if {[lsearch -exact $pkgs $pkg]>-1} { + if {[catch {EvalSlave package require [list $pkg]} pkgerr]} { + puts stderr "error:\n$pkgerr" + append PRIV(errorInfo) $errorInfo\n + } else { puts "OK" } + } else { + puts stderr "error: package does not exist" + } + } + + ## Evaluate maineval in slave + if {[string compare {} $OPT(maineval)] && \ + [catch {uplevel \#0 $OPT(maineval)} merr]} { + puts stderr "error in eval:\n$merr" + append PRIV(errorInfo) $errorInfo\n + } + + ## Source extra command line argument files into slave executable + foreach fn $slavefiles { + puts -nonewline "slave sourcing \"$fn\" ... " + if {[catch {EvalSlave source [list $fn]} fnerr]} { + puts stderr "error:\n$fnerr" + append PRIV(errorInfo) $errorInfo\n + } else { puts "OK" } + } + + ## Evaluate slaveeval in slave + if {[string compare {} $OPT(slaveeval)] && \ + [catch {interp eval $OPT(exec) $OPT(slaveeval)} serr]} { + puts stderr "error in slave eval:\n$serr" + append PRIV(errorInfo) $errorInfo\n + } + ## Output any error/output that may have been returned from rcfile + if {[info exists code] && $code && [string compare {} $err]} { + puts stderr "error in $PRIV(rcfile):\n$err" + append PRIV(errorInfo) $errorInfo + } + if {[string compare {} $OPT(exec)]} { + StateCheckpoint [concat $PRIV(name) $OPT(exec)] slave + } + StateCheckpoint $PRIV(name) slave + + Prompt "$title console display active (Tcl$::tcl_patchLevel / Tk$::tk_patchLevel)\n" +} + +## ::tkcon::InitSlave - inits the slave by placing key procs and aliases in it +## It's arg[cv] are based on passed in options, while argv0 is the same as +## the master. tcl_interactive is the same as the master as well. +# ARGS: slave - name of slave to init. If it does not exist, it is created. +# args - args to pass to a slave as argv/argc +## +proc ::tkcon::InitSlave {slave args} { + variable OPT + variable COLOR + variable PRIV + global argv0 tcl_interactive tcl_library env auto_path + + if {[string match {} $slave]} { + return -code error "Don't init the master interpreter, goofball" + } + if {![interp exists $slave]} { interp create $slave } + if {[interp eval $slave info command source] == ""} { + $slave alias source SafeSource $slave + $slave alias load SafeLoad $slave + $slave alias open SafeOpen $slave + $slave alias file file + interp eval $slave [dump var -nocomplain tcl_library auto_path env] + interp eval $slave { catch {source [file join $tcl_library init.tcl]} } + interp eval $slave { catch unknown } + } + $slave alias exit exit + interp eval $slave { + # Do package require before changing around puts/gets + catch {package require bogus-package-name} + catch {rename ::puts ::tkcon_tcl_puts} + } + foreach cmd $PRIV(slaveprocs) { $slave eval [dump proc $cmd] } + foreach cmd $PRIV(slavealias) { $slave alias $cmd $cmd } + interp alias $slave ::ls $slave ::dir -full + interp alias $slave ::puts $slave ::tkcon_puts + if {$OPT(gets) != ""} { + interp eval $slave { catch {rename ::gets ::tkcon_tcl_gets} } + interp alias $slave ::gets $slave ::tkcon_gets + } + if {[info exists argv0]} {interp eval $slave [list set argv0 $argv0]} + interp eval $slave set tcl_interactive $tcl_interactive \; \ + set auto_path [list $auto_path] \; \ + set argc [llength $args] \; \ + set argv [list $args] \; { + if {![llength [info command bgerror]]} { + proc bgerror err { + global errorInfo + set body [info body bgerror] + rename ::bgerror {} + if {[auto_load bgerror]} { return [bgerror $err] } + proc bgerror err $body + tkcon bgerror $err $errorInfo + } + } + } + + foreach pkg [lremove [package names] Tcl] { + foreach v [package versions $pkg] { + interp eval $slave [list package ifneeded $pkg $v \ + [package ifneeded $pkg $v]] + } + } +} + +## ::tkcon::InitInterp - inits an interpreter by placing key +## procs and aliases in it. +# ARGS: name - interp name +# type - interp type (slave|interp) +## +proc ::tkcon::InitInterp {name type} { + variable OPT + variable PRIV + + ## Don't allow messing up a local master interpreter + if {[string match namespace $type] || ([string match slave $type] && \ + [regexp {^([Mm]ain|Slave[0-9]+)$} $name])} return + set old [Attach] + set oldname $PRIV(namesp) + catch { + Attach $name $type + EvalAttached { catch {rename ::puts ::tkcon_tcl_puts} } + foreach cmd $PRIV(slaveprocs) { EvalAttached [dump proc $cmd] } + switch -exact $type { + slave { + foreach cmd $PRIV(slavealias) { + Main interp alias $name ::$cmd $PRIV(name) ::$cmd + } + } + interp { + set thistkcon [tk appname] + foreach cmd $PRIV(slavealias) { + EvalAttached "proc $cmd args { send [list $thistkcon] $cmd \$args }" + } + } + } + ## Catch in case it's a 7.4 (no 'interp alias') interp + EvalAttached { + catch {interp alias {} ::ls {} ::dir -full} + if {[catch {interp alias {} ::puts {} ::tkcon_puts}]} { + catch {rename ::tkcon_puts ::puts} + } + } + if {$OPT(gets) != ""} { + EvalAttached { + catch {rename ::gets ::tkcon_tcl_gets} + if {[catch {interp alias {} ::gets {} ::tkcon_gets}]} { + catch {rename ::tkcon_gets ::gets} + } + } + } + return + } {err} + eval Attach $old + AttachNamespace $oldname + if {[string compare {} $err]} { return -code error $err } +} + +## ::tkcon::InitUI - inits UI portion (console) of tkcon +## Creates all elements of the console window and sets up the text tags +# ARGS: root - widget pathname of the tkcon console root +# title - title for the console root and main (.) windows +# Calls: ::tkcon::InitMenus, ::tkcon::Prompt +## +proc ::tkcon::InitUI {title} { + variable OPT + variable PRIV + variable COLOR + + set root $PRIV(root) + if {[string match . $root]} { set w {} } else { set w [toplevel $root] } + if {!$PRIV(WWW)} { + wm withdraw $root + wm protocol $root WM_DELETE_WINDOW exit + } + set PRIV(base) $w + + ## Text Console + set PRIV(console) [set con $w.text] + text $con -wrap char -yscrollcommand [list $w.sy set] \ + -foreground $COLOR(stdin) \ + -insertbackground $COLOR(cursor) + $con mark set output 1.0 + $con mark set limit 1.0 + if {[string compare {} $COLOR(bg)]} { + $con configure -background $COLOR(bg) + } + set COLOR(bg) [$con cget -background] + if {[string compare {} $OPT(font)]} { + ## Set user-requested font, if any + $con configure -font $OPT(font) + } else { + ## otherwise make sure the font is monospace + set font [$con cget -font] + if {![font metrics $font -fixed]} { + font create tkconfixed -family Courier -size 12 + $con configure -font tkconfixed + } + } + set OPT(font) [$con cget -font] + if {!$PRIV(WWW)} { + $con configure -setgrid 1 -width $OPT(cols) -height $OPT(rows) + } + bindtags $con [list $con TkConsole TkConsolePost $root all] + ## Menus + ## catch against use in plugin + if {[catch {menu $w.mbar} PRIV(menubar)]} { + set PRIV(menubar) [frame $w.mbar -relief raised -bd 1] + } + ## Scrollbar + set PRIV(scrolly) [scrollbar $w.sy -takefocus 0 -bd 1 \ + -command [list $con yview]] + + InitMenus $PRIV(menubar) $title + Bindings + + if {$OPT(showmenu)} { + $root configure -menu $PRIV(menubar) + } + pack $w.sy -side $OPT(scrollypos) -fill y + pack $con -fill both -expand 1 + + set PRIV(statusbar) [set sbar [frame $w.sbar]] + label $sbar.attach -relief sunken -bd 1 -anchor w \ + -textvariable ::tkcon::PRIV(StatusAttach) + label $sbar.mode -relief sunken -bd 1 -anchor w \ + -textvariable ::tkcon::PRIV(StatusMode) + label $sbar.cursor -relief sunken -bd 1 -anchor w -width 6 \ + -textvariable ::tkcon::PRIV(StatusCursor) + grid $sbar.attach $sbar.mode $sbar.cursor -sticky news -padx 1 + grid columnconfigure $sbar 0 -weight 1 + grid columnconfigure $sbar 1 -weight 1 + grid columnconfigure $sbar 2 -weight 0 + + if {$OPT(showstatusbar)} { + pack $sbar -side bottom -fill x -before $::tkcon::PRIV(scrolly) + } + + foreach col {prompt stdout stderr stdin proc} { + $con tag configure $col -foreground $COLOR($col) + } + $con tag configure var -background $COLOR(var) + $con tag raise sel + $con tag configure blink -background $COLOR(blink) + $con tag configure find -background $COLOR(blink) + + if {!$PRIV(WWW)} { + wm title $root "tkcon $PRIV(version) $title" + bind $con { + scan [wm geometry [winfo toplevel %W]] "%%dx%%d" \ + ::tkcon::OPT(cols) ::tkcon::OPT(rows) + } + if {$PRIV(showOnStartup)} { wm deiconify $root } + } + if {$PRIV(showOnStartup)} { focus -force $PRIV(console) } + if {$OPT(gc-delay)} { + after $OPT(gc-delay) ::tkcon::GarbageCollect + } +} + +## ::tkcon::GarbageCollect - do various cleanup ops periodically to our setup +## +proc ::tkcon::GarbageCollect {} { + variable OPT + variable PRIV + + set w $PRIV(console) + ## Remove error tags that no longer span anything + ## Make sure the tag pattern matches the unique tag prefix + foreach tag [$w tag names] { + if {[string match _tag* $tag] && ![llength [$w tag ranges $tag]]} { + $w tag delete $tag + } + } + if {$OPT(gc-delay)} { + after $OPT(gc-delay) ::tkcon::GarbageCollect + } +} + +## ::tkcon::Eval - evaluates commands input into console window +## This is the first stage of the evaluating commands in the console. +## They need to be broken up into consituent commands (by ::tkcon::CmdSep) in +## case a multiple commands were pasted in, then each is eval'ed (by +## ::tkcon::EvalCmd) in turn. Any uncompleted command will not be eval'ed. +# ARGS: w - console text widget +# Calls: ::tkcon::CmdGet, ::tkcon::CmdSep, ::tkcon::EvalCmd +## +proc ::tkcon::Eval {w} { + set incomplete [CmdSep [CmdGet $w] cmds last] + $w mark set insert end-1c + $w insert end \n + if {[llength $cmds]} { + foreach c $cmds {EvalCmd $w $c} + $w insert insert $last {} + } elseif {!$incomplete} { + EvalCmd $w $last + } + $w see insert +} + +## ::tkcon::EvalCmd - evaluates a single command, adding it to history +# ARGS: w - console text widget +# cmd - the command to evaluate +# Calls: ::tkcon::Prompt +# Outputs: result of command to stdout (or stderr if error occured) +# Returns: next event number +## +proc ::tkcon::EvalCmd {w cmd} { + variable OPT + variable PRIV + + $w mark set output end + if {[string compare {} $cmd]} { + set code 0 + if {$OPT(subhistory)} { + set ev [EvalSlave history nextid] + incr ev -1 + if {[string match !! $cmd]} { + set code [catch {EvalSlave history event $ev} cmd] + if {!$code} {$w insert output $cmd\n stdin} + } elseif {[regexp {^!(.+)$} $cmd dummy event]} { + ## Check last event because history event is broken + set code [catch {EvalSlave history event $ev} cmd] + if {!$code && ![string match ${event}* $cmd]} { + set code [catch {EvalSlave history event $event} cmd] + } + if {!$code} {$w insert output $cmd\n stdin} + } elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$} $cmd dummy old new]} { + set code [catch {EvalSlave history event $ev} cmd] + if {!$code} { + regsub -all -- $old $cmd $new cmd + $w insert output $cmd\n stdin + } + } elseif {$OPT(calcmode) && ![catch {expr $cmd} err]} { + EvalSlave history add $cmd + set cmd $err + set code -1 + } + } + if {$code} { + $w insert output $cmd\n stderr + } else { + ## We are about to evaluate the command, so move the limit + ## mark to ensure that further s don't cause double + ## evaluation of this command - for cases like the command + ## has a vwait or something in it + $w mark set limit end + if {$OPT(nontcl) && [string match interp $PRIV(apptype)]} { + set code [catch {EvalSend $cmd} res] + if {$code == 1} { + set PRIV(errorInfo) "Non-Tcl errorInfo not available" + } + } elseif {[string match socket $PRIV(apptype)]} { + set code [catch {EvalSocket $cmd} res] + if {$code == 1} { + set PRIV(errorInfo) "Socket-based errorInfo not available" + } + } else { + set code [catch {EvalAttached $cmd} res] + if {$code == 1} { + if {[catch {EvalAttached [list set errorInfo]} err]} { + set PRIV(errorInfo) "Error getting errorInfo:\n$err" + } else { + set PRIV(errorInfo) $err + } + } + } + EvalSlave history add $cmd + if {$code} { + if {$OPT(hoterrors)} { + set tag [UniqueTag $w] + $w insert output $res [list stderr $tag] \n stderr + $w tag bind $tag \ + [list $w tag configure $tag -underline 1] + $w tag bind $tag \ + [list $w tag configure $tag -underline 0] + $w tag bind $tag \ + "if {!\[info exists tkPriv(mouseMoved)\] || !\$tkPriv(mouseMoved)} \ + {[list edit -attach [Attach] -type error -- $PRIV(errorInfo)]}" + } else { + $w insert output $res\n stderr + } + } elseif {[string compare {} $res]} { + $w insert output $res\n stdout + } + } + } + Prompt + set PRIV(event) [EvalSlave history nextid] +} + +## ::tkcon::EvalSlave - evaluates the args in the associated slave +## args should be passed to this procedure like they would be at +## the command line (not like to 'eval'). +# ARGS: args - the command and args to evaluate +## +proc ::tkcon::EvalSlave args { + interp eval $::tkcon::OPT(exec) $args +} + +## ::tkcon::EvalOther - evaluate a command in a foreign interp or slave +## without attaching to it. No check for existence is made. +# ARGS: app - interp/slave name +# type - (slave|interp) +## +proc ::tkcon::EvalOther { app type args } { + if {[string compare slave $type]==0} { + return [Slave $app $args] + } else { + return [uplevel 1 send [list $app] $args] + } +} + +## ::tkcon::EvalSend - sends the args to the attached interpreter +## Varies from 'send' by determining whether attachment is dead +## when an error is received +# ARGS: cmd - the command string to send across +# Returns: the result of the command +## +proc ::tkcon::EvalSend cmd { + variable OPT + variable PRIV + + if {$PRIV(deadapp)} { + if {[lsearch -exact [winfo interps] $PRIV(app)]<0} { + return + } else { + set PRIV(appname) [string range $PRIV(appname) 5 end] + set PRIV(deadapp) 0 + Prompt "\n\"$PRIV(app)\" alive\n" [CmdGet $PRIV(console)] + } + } + set code [catch {send -displayof $PRIV(displayWin) $PRIV(app) $cmd} result] + if {$code && [lsearch -exact [winfo interps] $PRIV(app)]<0} { + ## Interpreter disappeared + if {[string compare leave $OPT(dead)] && \ + ([string match ignore $OPT(dead)] || \ + [tk_dialog $PRIV(base).dead "Dead Attachment" \ + "\"$PRIV(app)\" appears to have died.\ + \nReturn to primary slave interpreter?" questhead 0 OK No])} { + set PRIV(appname) "DEAD:$PRIV(appname)" + set PRIV(deadapp) 1 + } else { + set err "Attached Tk interpreter \"$PRIV(app)\" died." + Attach {} + set PRIV(deadapp) 0 + EvalSlave set errorInfo $err + } + Prompt \n [CmdGet $PRIV(console)] + } + return -code $code $result +} + +## ::tkcon::EvalSocket - sends the string to an interpreter attached via +## a tcp/ip socket +## +## In the EvalSocket case, ::tkcon::PRIV(app) is the socket id +## +## Must determine whether socket is dead when an error is received +# ARGS: cmd - the data string to send across +# Returns: the result of the command +## +proc ::tkcon::EvalSocket cmd { + variable OPT + variable PRIV + global tcl_version + + if {$PRIV(deadapp)} { + if {![info exists PRIV(app)] || \ + [catch {eof $PRIV(app)} eof] || $eof} { + return + } else { + set PRIV(appname) [string range $PRIV(appname) 5 end] + set PRIV(deadapp) 0 + Prompt "\n\"$PRIV(app)\" alive\n" [CmdGet $PRIV(console)] + } + } + # Sockets get \'s interpreted, so that users can + # send things like \n\r or explicit hex values + set cmd [subst -novariables -nocommands $cmd] + #puts [list $PRIV(app) $cmd] + set code [catch {puts $PRIV(app) $cmd ; flush $PRIV(app)} result] + if {$code && [eof $PRIV(app)]} { + ## Interpreter died or disappeared + puts "$code eof [eof $PRIV(app)]" + EvalSocketClosed + } + return -code $code $result +} + +## ::tkcon::EvalSocketEvent - fileevent command for an interpreter attached +## via a tcp/ip socket +## Must determine whether socket is dead when an error is received +# ARGS: args - the args to send across +# Returns: the result of the command +## +proc ::tkcon::EvalSocketEvent {} { + variable PRIV + + if {[gets $PRIV(app) line] == -1} { + if {[eof $PRIV(app)]} { + EvalSocketClosed + } + return + } + puts $line +} + +## ::tkcon::EvalSocketClosed - takes care of handling a closed eval socket +## +# ARGS: args - the args to send across +# Returns: the result of the command +## +proc ::tkcon::EvalSocketClosed {} { + variable OPT + variable PRIV + + catch {close $PRIV(app)} + if {[string compare leave $OPT(dead)] && \ + ([string match ignore $OPT(dead)] || \ + [tk_dialog $PRIV(base).dead "Dead Attachment" \ + "\"$PRIV(app)\" appears to have died.\ + \nReturn to primary slave interpreter?" questhead 0 OK No])} { + set PRIV(appname) "DEAD:$PRIV(appname)" + set PRIV(deadapp) 1 + } else { + set err "Attached Tk interpreter \"$PRIV(app)\" died." + Attach {} + set PRIV(deadapp) 0 + EvalSlave set errorInfo $err + } + Prompt \n [CmdGet $PRIV(console)] +} + +## ::tkcon::EvalNamespace - evaluates the args in a particular namespace +## This is an override for ::tkcon::EvalAttached for when the user wants +## to attach to a particular namespace of the attached interp +# ARGS: attached +# namespace the namespace to evaluate in +# args the args to evaluate +# RETURNS: the result of the command +## +proc ::tkcon::EvalNamespace { attached namespace args } { + if {[llength $args]} { + uplevel \#0 $attached \ + [list [concat [list namespace eval $namespace] $args]] + } +} + + +## ::tkcon::Namespaces - return all the namespaces descendent from $ns +## +# +## +proc ::tkcon::Namespaces {{ns ::} {l {}}} { + if {[string compare {} $ns]} { lappend l $ns } + foreach i [EvalAttached [list namespace children $ns]] { + set l [Namespaces $i $l] + } + return $l +} + +## ::tkcon::CmdGet - gets the current command from the console widget +# ARGS: w - console text widget +# Returns: text which compromises current command line +## +proc ::tkcon::CmdGet w { + if {![llength [$w tag nextrange prompt limit end]]} { + $w tag add stdin limit end-1c + return [$w get limit end-1c] + } +} + +## ::tkcon::CmdSep - separates multiple commands into a list and remainder +# ARGS: cmd - (possible) multiple command to separate +# list - varname for the list of commands that were separated. +# last - varname of any remainder (like an incomplete final command). +# If there is only one command, it's placed in this var. +# Returns: constituent command info in varnames specified by list & rmd. +## +proc ::tkcon::CmdSep {cmd list last} { + upvar 1 $list cmds $last inc + set inc {} + set cmds {} + foreach c [split [string trimleft $cmd] \n] { + if {[string compare $inc {}]} { + append inc \n$c + } else { + append inc [string trimleft $c] + } + if {[info complete $inc] && ![regexp {[^\\]\\$} $inc]} { + if {[regexp "^\[^#\]" $inc]} {lappend cmds $inc} + set inc {} + } + } + set i [string compare $inc {}] + if {!$i && [string compare $cmds {}] && ![string match *\n $cmd]} { + set inc [lindex $cmds end] + set cmds [lreplace $cmds end end] + } + return $i +} + +## ::tkcon::CmdSplit - splits multiple commands into a list +# ARGS: cmd - (possible) multiple command to separate +# Returns: constituent commands in a list +## +proc ::tkcon::CmdSplit {cmd} { + set inc {} + set cmds {} + foreach cmd [split [string trimleft $cmd] \n] { + if {[string compare {} $inc]} { + append inc \n$cmd + } else { + append inc [string trimleft $cmd] + } + if {[info complete $inc] && ![regexp {[^\\]\\$} $inc]} { + #set inc [string trimright $inc] + if {[regexp "^\[^#\]" $inc]} {lappend cmds $inc} + set inc {} + } + } + if {[regexp "^\[^#\]" $inc]} {lappend cmds $inc} + return $cmds +} + +## ::tkcon::UniqueTag - creates a uniquely named tag, reusing names +## Called by ::tkcon::EvalCmd +# ARGS: w - text widget +# Outputs: tag name guaranteed unique in the widget +## +proc ::tkcon::UniqueTag {w} { + set tags [$w tag names] + set idx 0 + while {[lsearch -exact $tags _tag[incr idx]] != -1} {} + return _tag$idx +} + +## ::tkcon::ConstrainBuffer - This limits the amount of data in the text widget +## Called by ::tkcon::Prompt and in tkcon proc buffer/console switch cases +# ARGS: w - console text widget +# size - # of lines to constrain to +# Outputs: may delete data in console widget +## +proc ::tkcon::ConstrainBuffer {w size} { + if {[$w index end] > $size} { + $w delete 1.0 [expr {int([$w index end])-$size}].0 + } +} + +## ::tkcon::Prompt - displays the prompt in the console widget +# ARGS: w - console text widget +# Outputs: prompt (specified in ::tkcon::OPT(prompt1)) to console +## +proc ::tkcon::Prompt {{pre {}} {post {}} {prompt {}}} { + variable OPT + variable PRIV + + set w $PRIV(console) + if {[string compare {} $pre]} { $w insert end $pre stdout } + set i [$w index end-1c] + if {!$OPT(showstatusbar)} { + if {[string compare {} $PRIV(appname)]} { + $w insert end ">$PRIV(appname)< " prompt + } + if {[string compare :: $PRIV(namesp)]} { + $w insert end "<$PRIV(namesp)> " prompt + } + } + if {[string compare {} $prompt]} { + $w insert end $prompt prompt + } else { + $w insert end [EvalSlave subst $OPT(prompt1)] prompt + } + $w mark set output $i + $w mark set insert end + $w mark set limit insert + $w mark gravity limit left + if {[string compare {} $post]} { $w insert end $post stdin } + ConstrainBuffer $w $OPT(buffer) + set ::tkcon::PRIV(StatusCursor) [$w index insert] + $w see end +} + +## ::tkcon::About - gives about info for tkcon +## +proc ::tkcon::About {} { + variable OPT + variable PRIV + variable COLOR + + set w $PRIV(base).about + if {[winfo exists $w]} { + wm deiconify $w + } else { + global tk_patchLevel tcl_patchLevel tcl_version + toplevel $w + wm title $w "About tkcon v$PRIV(version)" + button $w.b -text Dismiss -command [list wm withdraw $w] + text $w.text -height 9 -bd 1 -width 60 \ + -foreground $COLOR(stdin) \ + -background $COLOR(bg) \ + -font $OPT(font) + pack $w.b -fill x -side bottom + pack $w.text -fill both -side left -expand 1 + $w.text tag config center -justify center + $w.text tag config title -justify center -font {Courier -18 bold} + # strip down the RCS info displayed in the about box + regexp {,v ([0-9\./: ]*)} $PRIV(RCS) -> RCS + $w.text insert 1.0 "About tkcon v$PRIV(version)" title \ + "\n\nCopyright 1995-2001 Jeffrey Hobbs, $PRIV(email)\ + \nRelease Info: v$PRIV(version), CVS v$RCS\ + \nDocumentation available at:\n$PRIV(docs)\ + \nUsing: Tcl v$tcl_patchLevel / Tk v$tk_patchLevel" center + $w.text config -state disabled + } +} + +## ::tkcon::InitMenus - inits the menubar and popup for the console +# ARGS: w - console text widget +## +proc ::tkcon::InitMenus {w title} { + variable OPT + variable PRIV + variable COLOR + global tcl_platform + + if {[catch {menu $w.pop -tearoff 0}]} { + label $w.label -text "Menus not available in plugin mode" + pack $w.label + return + } + menu $w.context -tearoff 0 -disabledforeground $COLOR(disabled) + set PRIV(context) $w.context + set PRIV(popup) $w.pop + + proc MenuButton {w m l} { + $w add cascade -label $m -underline 0 -menu $w.$l + return $w.$l + } + + foreach m [list File Console Edit Interp Prefs History Help] { + set l [string tolower $m] + MenuButton $w $m $l + $w.pop add cascade -label $m -underline 0 -menu $w.pop.$l + } + + ## File Menu + ## + foreach m [list [menu $w.file -disabledforeground $COLOR(disabled)] \ + [menu $w.pop.file -disabledforeground $COLOR(disabled)]] { + $m add command -label "Load File" -underline 0 -command ::tkcon::Load + $m add cascade -label "Save ..." -underline 0 -menu $m.save + $m add separator + $m add command -label "Quit" -underline 0 -accel Ctrl-q -command exit + + ## Save Menu + ## + set s $m.save + menu $s -disabledforeground $COLOR(disabled) -tearoff 0 + $s add command -label "All" -underline 0 \ + -command {::tkcon::Save {} all} + $s add command -label "History" -underline 0 \ + -command {::tkcon::Save {} history} + $s add command -label "Stdin" -underline 3 \ + -command {::tkcon::Save {} stdin} + $s add command -label "Stdout" -underline 3 \ + -command {::tkcon::Save {} stdout} + $s add command -label "Stderr" -underline 3 \ + -command {::tkcon::Save {} stderr} + } + + ## Console Menu + ## + foreach m [list [menu $w.console -disabledfore $COLOR(disabled)] \ + [menu $w.pop.console -disabledfore $COLOR(disabled)]] { + $m add command -label "$title Console" -state disabled + $m add command -label "New Console" -underline 0 -accel Ctrl-N \ + -command ::tkcon::New + $m add command -label "Close Console" -underline 0 -accel Ctrl-w \ + -command ::tkcon::Destroy + $m add command -label "Clear Console" -underline 1 -accel Ctrl-l \ + -command { clear; ::tkcon::Prompt } + if {[string match unix $tcl_platform(platform)]} { + $m add separator + $m add command -label "Make Xauth Secure" -und 5 \ + -command ::tkcon::XauthSecure + } + $m add separator + $m add cascade -label "Attach To ..." -underline 0 -menu $m.attach + + ## Attach Console Menu + ## + set sub [menu $m.attach -disabledforeground $COLOR(disabled)] + $sub add cascade -label "Interpreter" -underline 0 -menu $sub.apps + $sub add cascade -label "Namespace" -underline 1 -menu $sub.name + $sub add cascade -label "Socket" -underline 1 -menu $sub.sock \ + -state [expr {([info tclversion] < 8.3)?"disabled":"normal"}] + + ## Attach Console Menu + ## + menu $sub.apps -disabledforeground $COLOR(disabled) \ + -postcommand [list ::tkcon::AttachMenu $sub.apps] + + ## Attach Namespace Menu + ## + menu $sub.name -disabledforeground $COLOR(disabled) -tearoff 0 \ + -postcommand [list ::tkcon::NamespaceMenu $sub.name] + + if {$::tcl_version >= 8.3} { + # This uses [file channels] to create the menu, so we only + # want it for newer versions of Tcl. + + ## Attach Socket Menu + ## + menu $sub.sock -disabledforeground $COLOR(disabled) -tearoff 0 \ + -postcommand [list ::tkcon::SocketMenu $sub.sock] + } + + ## Attach Display Menu + ## + if {![string compare "unix" $tcl_platform(platform)]} { + $sub add cascade -label "Display" -und 1 -menu $sub.disp + menu $sub.disp -disabledforeground $COLOR(disabled) \ + -tearoff 0 \ + -postcommand [list ::tkcon::DisplayMenu $sub.disp] + } + } + + ## Edit Menu + ## + set text $PRIV(console) + foreach m [list [menu $w.edit] [menu $w.pop.edit]] { + $m add command -label "Cut" -underline 2 -accel Ctrl-x \ + -command [list ::tkcon::Cut $text] + $m add command -label "Copy" -underline 0 -accel Ctrl-c \ + -command [list ::tkcon::Copy $text] + $m add command -label "Paste" -underline 0 -accel Ctrl-v \ + -command [list ::tkcon::Paste $text] + $m add separator + $m add command -label "Find" -underline 0 -accel Ctrl-F \ + -command [list ::tkcon::FindBox $text] + } + + ## Interp Menu + ## + foreach m [list $w.interp $w.pop.interp] { + menu $m -disabledforeground $COLOR(disabled) \ + -postcommand [list ::tkcon::InterpMenu $m] + } + + ## Prefs Menu + ## + foreach m [list [menu $w.prefs] [menu $w.pop.prefs]] { + $m add check -label "Brace Highlighting" \ + -underline 0 -variable ::tkcon::OPT(lightbrace) + $m add check -label "Command Highlighting" \ + -underline 0 -variable ::tkcon::OPT(lightcmd) + $m add check -label "History Substitution" \ + -underline 0 -variable ::tkcon::OPT(subhistory) + $m add check -label "Hot Errors" \ + -underline 0 -variable ::tkcon::OPT(hoterrors) + $m add check -label "Non-Tcl Attachments" \ + -underline 0 -variable ::tkcon::OPT(nontcl) + $m add check -label "Calculator Mode" \ + -underline 1 -variable ::tkcon::OPT(calcmode) + $m add check -label "Show Multiple Matches" \ + -underline 0 -variable ::tkcon::OPT(showmultiple) + $m add check -label "Show Menubar" \ + -underline 5 -variable ::tkcon::OPT(showmenu) \ + -command {$::tkcon::PRIV(root) configure -menu [expr \ + {$::tkcon::OPT(showmenu) ? $::tkcon::PRIV(menubar) : {}}]} + $m add check -label "Show Statusbar" \ + -underline 5 -variable ::tkcon::OPT(showstatusbar) \ + -command { + if {$::tkcon::OPT(showstatusbar)} { + pack $::tkcon::PRIV(statusbar) -side bottom -fill x \ + -before $::tkcon::PRIV(scrolly) + } else { pack forget $::tkcon::PRIV(statusbar) } + } + $m add cascade -label "Scrollbar" -underline 2 -menu $m.scroll + + ## Scrollbar Menu + ## + set m [menu $m.scroll -tearoff 0] + $m add radio -label "Left" -value left \ + -variable ::tkcon::OPT(scrollypos) \ + -command { pack config $::tkcon::PRIV(scrolly) -side left } + $m add radio -label "Right" -value right \ + -variable ::tkcon::OPT(scrollypos) \ + -command { pack config $::tkcon::PRIV(scrolly) -side right } + } + + ## History Menu + ## + foreach m [list $w.history $w.pop.history] { + menu $m -disabledforeground $COLOR(disabled) \ + -postcommand [list ::tkcon::HistoryMenu $m] + } + + ## Help Menu + ## + foreach m [list [menu $w.help] [menu $w.pop.help]] { + $m add command -label "About " -underline 0 -accel Ctrl-A \ + -command ::tkcon::About + $m add command -label "Retrieve Latest Version" -underline 0 \ + -command ::tkcon::Retrieve + } +} + +## ::tkcon::HistoryMenu - dynamically build the menu for attached interpreters +## +# ARGS: m - menu widget +## +proc ::tkcon::HistoryMenu m { + variable PRIV + + if {![winfo exists $m]} return + set id [EvalSlave history nextid] + if {$PRIV(histid)==$id} return + set PRIV(histid) $id + $m delete 0 end + while {($id>1) && ($id>$PRIV(histid)-10) && \ + ![catch {EvalSlave history event [incr id -1]} tmp]} { + set lbl $tmp + if {[string len $lbl]>32} { set lbl [string range $tmp 0 28]... } + $m add command -label "$id: $lbl" -command " + $::tkcon::PRIV(console) delete limit end + $::tkcon::PRIV(console) insert limit [list $tmp] + $::tkcon::PRIV(console) see end + ::tkcon::Eval $::tkcon::PRIV(console)" + } +} + +## ::tkcon::InterpMenu - dynamically build the menu for attached interpreters +## +# ARGS: w - menu widget +## +proc ::tkcon::InterpMenu w { + variable OPT + variable PRIV + variable COLOR + + if {![winfo exists $w]} return + $w delete 0 end + foreach {app type} [Attach] break + $w add command -label "[string toupper $type]: $app" -state disabled + if {($OPT(nontcl) && [string match interp $type]) || $PRIV(deadapp)} { + $w add separator + $w add command -state disabled -label "Communication disabled to" + $w add command -state disabled -label "dead or non-Tcl interps" + return + } + + ## Show Last Error + ## + $w add separator + $w add command -label "Show Last Error" \ + -command [list tkcon error $app $type] + + ## Packages Cascaded Menu + ## + $w add separator + $w add cascade -label Packages -underline 0 -menu $w.pkg + set m $w.pkg + if {![winfo exists $m]} { + menu $m -tearoff no -disabledforeground $COLOR(disabled) \ + -postcommand [list ::tkcon::PkgMenu $m $app $type] + } + + ## State Checkpoint/Revert + ## + $w add separator + $w add command -label "Checkpoint State" \ + -command [list ::tkcon::StateCheckpoint $app $type] + $w add command -label "Revert State" \ + -command [list ::tkcon::StateRevert $app $type] + $w add command -label "View State Change" \ + -command [list ::tkcon::StateCompare $app $type] + + ## Init Interp + ## + $w add separator + $w add command -label "Send tkcon Commands" \ + -command [list ::tkcon::InitInterp $app $type] +} + +## ::tkcon::PkgMenu - fill in in the applications sub-menu +## with a list of all the applications that currently exist. +## +proc ::tkcon::PkgMenu {m app type} { + # just in case stuff has been added to the auto_path + # we have to make sure that the errorInfo doesn't get screwed up + EvalAttached { + set __tkcon_error $errorInfo + catch {package require bogus-package-name} + set errorInfo ${__tkcon_error} + unset __tkcon_error + } + $m delete 0 end + foreach pkg [EvalAttached [list info loaded {}]] { + set loaded([lindex $pkg 1]) [package provide $pkg] + } + foreach pkg [lremove [EvalAttached {package names}] Tcl] { + set version [EvalAttached [list package provide $pkg]] + if {[string compare {} $version]} { + set loaded($pkg) $version + } elseif {![info exists loaded($pkg)]} { + set loadable($pkg) [list package require $pkg] + } + } + foreach pkg [EvalAttached {info loaded}] { + set pkg [lindex $pkg 1] + if {![info exists loaded($pkg)] && ![info exists loadable($pkg)]} { + set loadable($pkg) [list load {} $pkg] + } + } + set npkg 0 + foreach pkg [lsort -dictionary [array names loadable]] { + foreach v [EvalAttached [list package version $pkg]] { + set brkcol [expr {([incr npkg]%16)==0}] + $m add command -label "Load $pkg ($v)" -command \ + "::tkcon::EvalOther [list $app] $type $loadable($pkg) $v" \ + -columnbreak $brkcol + } + } + if {[info exists loaded] && [info exists loadable]} { + $m add separator + } + foreach pkg [lsort -dictionary [array names loaded]] { + $m add command -label "${pkg}$loaded($pkg) Loaded" -state disabled + } +} + +## ::tkcon::AttachMenu - fill in in the applications sub-menu +## with a list of all the applications that currently exist. +## +proc ::tkcon::AttachMenu m { + variable OPT + variable PRIV + + array set interps [set tmp [Interps]] + foreach {i j} $tmp { set tknames($j) {} } + + $m delete 0 end + set cmd {::tkcon::Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]} + $m add radio -label {None (use local slave) } -accel Ctrl-1 \ + -variable ::tkcon::PRIV(app) \ + -value [concat $::tkcon::PRIV(name) $::tkcon::OPT(exec)] \ + -command "::tkcon::Attach {}; $cmd" + $m add separator + $m add command -label "Foreign Tk Interpreters" -state disabled + foreach i [lsort [lremove [winfo interps] [array names tknames]]] { + $m add radio -label $i -variable ::tkcon::PRIV(app) -value $i \ + -command "::tkcon::Attach [list $i] interp; $cmd" + } + $m add separator + + $m add command -label "tkcon Interpreters" -state disabled + foreach i [lsort [array names interps]] { + if {[string match {} $interps($i)]} { set interps($i) "no Tk" } + if {[regexp {^Slave[0-9]+} $i]} { + set opts [list -label "$i ($interps($i))" \ + -variable ::tkcon::PRIV(app) -value $i \ + -command "::tkcon::Attach [list $i] slave; $cmd"] + if {[string match $PRIV(name) $i]} { + append opts " -accel Ctrl-2" + } + eval $m add radio $opts + } else { + set name [concat Main $i] + if {[string match Main $name]} { + $m add radio -label "$name ($interps($i))" -accel Ctrl-3 \ + -variable ::tkcon::PRIV(app) -value Main \ + -command "::tkcon::Attach [list $name] slave; $cmd" + } else { + $m add radio -label "$name ($interps($i))" \ + -variable ::tkcon::PRIV(app) -value $i \ + -command "::tkcon::Attach [list $name] slave; $cmd" + } + } + } +} + +## Displays Cascaded Menu +## +proc ::tkcon::DisplayMenu m { + $m delete 0 end + set cmd {::tkcon::Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]} + + $m add command -label "New Display" -command ::tkcon::NewDisplay + foreach disp [Display] { + $m add separator + $m add command -label $disp -state disabled + set res [Display $disp] + set win [lindex $res 0] + foreach i [lsort [lindex $res 1]] { + $m add radio -label $i -variable ::tkcon::PRIV(app) -value $i \ + -command "::tkcon::Attach [list $i] [list dpy:$win]; $cmd" + } + } +} + +## Sockets Cascaded Menu +## +proc ::tkcon::SocketMenu m { + $m delete 0 end + set cmd {::tkcon::Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]} + + $m add command -label "Create Connection" \ + -command "::tkcon::NewSocket; $cmd" + foreach sock [file channels sock*] { + $m add radio -label $sock -variable ::tkcon::PRIV(app) -value $sock \ + -command "::tkcon::Attach $sock socket; $cmd" + } +} + +## Namepaces Cascaded Menu +## +proc ::tkcon::NamespaceMenu m { + variable PRIV + variable OPT + + $m delete 0 end + if {($PRIV(deadapp) || [string match socket $PRIV(apptype)] || \ + ($OPT(nontcl) && [string match interp $PRIV(apptype)]))} { + $m add command -label "No Namespaces" -state disabled + return + } + + ## Same command as for ::tkcon::AttachMenu items + set cmd {::tkcon::Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]} + + set names [lsort [Namespaces ::]] + if {[llength $names] > $OPT(maxmenu)} { + $m add command -label "Attached to $PRIV(namesp)" -state disabled + $m add command -label "List Namespaces" \ + -command [list ::tkcon::NamespacesList $names] + } else { + foreach i $names { + if {[string match :: $i]} { + $m add radio -label "Main" -value $i \ + -variable ::tkcon::PRIV(namesp) \ + -command "::tkcon::AttachNamespace [list $i]; $cmd" + } else { + $m add radio -label $i -value $i \ + -variable ::tkcon::PRIV(namesp) \ + -command "::tkcon::AttachNamespace [list $i]; $cmd" + } + } + } +} + +## Namepaces List +## +proc ::tkcon::NamespacesList {names} { + variable PRIV + + set f $PRIV(base).namespaces + catch {destroy $f} + toplevel $f + listbox $f.names -width 30 -height 15 -selectmode single \ + -yscrollcommand [list $f.scrollv set] \ + -xscrollcommand [list $f.scrollh set] + scrollbar $f.scrollv -command [list $f.names yview] + scrollbar $f.scrollh -command [list $f.names xview] -orient horizontal + frame $f.buttons + button $f.cancel -text "Cancel" -command [list destroy $f] + + grid $f.names $f.scrollv -sticky nesw + grid $f.scrollh -sticky ew + grid $f.buttons -sticky nesw + grid $f.cancel -in $f.buttons -pady 6 + + grid columnconfigure $f 0 -weight 1 + grid rowconfigure $f 0 -weight 1 + #fill the listbox + foreach i $names { + if {[string match :: $i]} { + $f.names insert 0 Main + } else { + $f.names insert end $i + } + } + #Bindings + bind $f.names { + ## Catch in case the namespace disappeared on us + catch { ::tkcon::AttachNamespace [%W get [%W nearest %y]] } + ::tkcon::Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)] + destroy [winfo toplevel %W] + } +} + +# ::tkcon::XauthSecure -- +# +# This removes all the names in the xhost list, and secures +# the display for Tk send commands. Of course, this prevents +# what might have been otherwise allowable X connections +# +# Arguments: +# none +# Results: +# Returns nothing +# +proc ::tkcon::XauthSecure {} { + global tcl_platform + + if {[string compare unix $tcl_platform(platform)]} { + # This makes no sense outside of Unix + return + } + set hosts [exec xhost] + # the first line is info only + foreach host [lrange [split $hosts \n] 1 end] { + exec xhost -$host + } + exec xhost - + tk_messageBox -title "Xhost secured" -message "Xhost secured" -icon info +} + +## ::tkcon::FindBox - creates minimal dialog interface to ::tkcon::Find +# ARGS: w - text widget +# str - optional seed string for ::tkcon::PRIV(find) +## +proc ::tkcon::FindBox {w {str {}}} { + variable PRIV + + set base $PRIV(base).find + if {![winfo exists $base]} { + toplevel $base + wm withdraw $base + wm title $base "tkcon Find" + + pack [frame $base.f] -fill x -expand 1 + label $base.f.l -text "Find:" + entry $base.f.e -textvariable ::tkcon::PRIV(find) + pack [frame $base.opt] -fill x + checkbutton $base.opt.c -text "Case Sensitive" \ + -variable ::tkcon::PRIV(find,case) + checkbutton $base.opt.r -text "Use Regexp" -variable ::tkcon::PRIV(find,reg) + pack $base.f.l -side left + pack $base.f.e $base.opt.c $base.opt.r -side left -fill both -expand 1 + pack [frame $base.sep -bd 2 -relief sunken -height 4] -fill x + pack [frame $base.btn] -fill both + button $base.btn.fnd -text "Find" -width 6 + button $base.btn.clr -text "Clear" -width 6 + button $base.btn.dis -text "Dismiss" -width 6 + eval pack [winfo children $base.btn] -padx 4 -pady 2 \ + -side left -fill both + + focus $base.f.e + + bind $base.f.e [list $base.btn.fnd invoke] + bind $base.f.e [list $base.btn.dis invoke] + } + $base.btn.fnd config -command "::tkcon::Find [list $w] \$::tkcon::PRIV(find) \ + -case \$::tkcon::PRIV(find,case) -reg \$::tkcon::PRIV(find,reg)" + $base.btn.clr config -command " + [list $w] tag remove find 1.0 end + set ::tkcon::PRIV(find) {} + " + $base.btn.dis config -command " + [list $w] tag remove find 1.0 end + wm withdraw [list $base] + " + if {[string compare {} $str]} { + set PRIV(find) $str + $base.btn.fnd invoke + } + + if {[string compare normal [wm state $base]]} { + wm deiconify $base + } else { raise $base } + $base.f.e select range 0 end +} + +## ::tkcon::Find - searches in text widget $w for $str and highlights it +## If $str is empty, it just deletes any highlighting +# ARGS: w - text widget +# str - string to search for +# -case TCL_BOOLEAN whether to be case sensitive DEFAULT: 0 +# -regexp TCL_BOOLEAN whether to use $str as pattern DEFAULT: 0 +## +proc ::tkcon::Find {w str args} { + $w tag remove find 1.0 end + set truth {^(1|yes|true|on)$} + set opts {} + foreach {key val} $args { + switch -glob -- $key { + -c* { if {[regexp -nocase $truth $val]} { set case 1 } } + -r* { if {[regexp -nocase $truth $val]} { lappend opts -regexp } } + default { return -code error "Unknown option $key" } + } + } + if {![info exists case]} { lappend opts -nocase } + if {[string match {} $str]} return + $w mark set findmark 1.0 + while {[string compare {} [set ix [eval $w search $opts -count numc -- \ + [list $str] findmark end]]]} { + $w tag add find $ix ${ix}+${numc}c + $w mark set findmark ${ix}+1c + } + $w tag configure find -background $::tkcon::COLOR(blink) + catch {$w see find.first} + return [expr {[llength [$w tag ranges find]]/2}] +} + +## ::tkcon::Attach - called to attach tkcon to an interpreter +# ARGS: name - application name to which tkcon sends commands +# This is either a slave interperter name or tk appname. +# type - (slave|interp) type of interpreter we're attaching to +# slave means it's a tkcon interpreter +# interp means we'll need to 'send' to it. +# Results: ::tkcon::EvalAttached is recreated to evaluate in the +# appropriate interpreter +## +proc ::tkcon::Attach {{name } {type slave}} { + variable PRIV + variable OPT + + if {[llength [info level 0]] == 1} { + # no args were specified, return the attach info instead + if {[string match {} $PRIV(appname)]} { + return [list [concat $PRIV(name) $OPT(exec)] $PRIV(apptype)] + } else { + return [list $PRIV(appname) $PRIV(apptype)] + } + } + set path [concat $PRIV(name) $OPT(exec)] + + set PRIV(displayWin) . + if {[string match namespace $type]} { + return [uplevel 1 ::tkcon::AttachNamespace $name] + } elseif {[string match dpy:* $type]} { + set PRIV(displayWin) [string range $type 4 end] + } elseif {[string match sock* $type]} { + global tcl_version + if {[catch {eof $name} res]} { + return -code error "No known channel \"$name\"" + } elseif {$res} { + catch {close $name} + return -code error "Channel \"$name\" returned EOF" + } + set app $name + set type socket + } elseif {[string compare {} $name]} { + array set interps [Interps] + if {[string match {[Mm]ain} [lindex $name 0]]} { + set name [lrange $name 1 end] + } + if {[string match $path $name]} { + set name {} + set app $path + set type slave + } elseif {[info exists interps($name)]} { + if {[string match {} $name]} { set name Main; set app Main } + set type slave + } elseif {[interp exists $name]} { + set name [concat $PRIV(name) $name] + set type slave + } elseif {[interp exists [concat $OPT(exec) $name]]} { + set name [concat $path $name] + set type slave + } elseif {[lsearch -exact [winfo interps] $name] > -1} { + if {[EvalSlave info exists tk_library] \ + && [string match $name [EvalSlave tk appname]]} { + set name {} + set app $path + set type slave + } elseif {[set i [lsearch -exact \ + [Main set ::tkcon::PRIV(interps)] $name]] != -1} { + set name [lindex [Main set ::tkcon::PRIV(slaves)] $i] + if {[string match {[Mm]ain} $name]} { set app Main } + set type slave + } else { + set type interp + } + } else { + return -code error "No known interpreter \"$name\"" + } + } else { + set app $path + } + if {![info exists app]} { set app $name } + array set PRIV [list app $app appname $name apptype $type deadapp 0] + + ## ::tkcon::EvalAttached - evaluates the args in the attached interp + ## args should be passed to this procedure as if they were being + ## passed to the 'eval' procedure. This procedure is dynamic to + ## ensure evaluation occurs in the right interp. + # ARGS: args - the command and args to evaluate + ## + switch -glob -- $type { + slave { + if {[string match {} $name]} { + interp alias {} ::tkcon::EvalAttached {} \ + ::tkcon::EvalSlave uplevel \#0 + } elseif {[string match Main $PRIV(app)]} { + interp alias {} ::tkcon::EvalAttached {} ::tkcon::Main + } elseif {[string match $PRIV(name) $PRIV(app)]} { + interp alias {} ::tkcon::EvalAttached {} uplevel \#0 + } else { + interp alias {} ::tkcon::EvalAttached {} \ + ::tkcon::Slave $::tkcon::PRIV(app) + } + } + sock* { + interp alias {} ::tkcon::EvalAttached {} \ + ::tkcon::EvalSlave uplevel \#0 + # The file event will just puts whatever data is found + # into the interpreter + fconfigure $name -buffering line -blocking 0 + fileevent $name readable ::tkcon::EvalSocketEvent + } + dpy:* - + interp { + if {$OPT(nontcl)} { + interp alias {} ::tkcon::EvalAttached {} ::tkcon::EvalSlave + set PRIV(namesp) :: + } else { + interp alias {} ::tkcon::EvalAttached {} ::tkcon::EvalSend + } + } + default { + return -code error "[lindex [info level 0] 0] did not specify\ + a valid type: must be slave or interp" + } + } + if {[string match slave $type] || \ + (!$OPT(nontcl) && [regexp {^(interp|dpy)} $type])} { + set PRIV(namesp) :: + } + set PRIV(StatusAttach) "$PRIV(app) ($PRIV(apptype))" + return +} + +## ::tkcon::AttachNamespace - called to attach tkcon to a namespace +# ARGS: name - namespace name in which tkcon should eval commands +# Results: ::tkcon::EvalAttached will be modified +## +proc ::tkcon::AttachNamespace { name } { + variable PRIV + variable OPT + + if {($OPT(nontcl) && [string match interp $PRIV(apptype)]) \ + || [string match socket $PRIV(apptype)] \ + || $PRIV(deadapp)} { + return -code error "can't attach to namespace in attached environment" + } + if {[string match Main $name]} {set name ::} + if {[string compare {} $name] && \ + [lsearch [Namespaces ::] $name] == -1} { + return -code error "No known namespace \"$name\"" + } + if {[regexp {^(|::)$} $name]} { + ## If name=={} || ::, we want the primary namespace + set alias [interp alias {} ::tkcon::EvalAttached] + if {[string match ::tkcon::EvalNamespace* $alias]} { + eval [list interp alias {} ::tkcon::EvalAttached {}] \ + [lindex $alias 1] + } + set name :: + } else { + interp alias {} ::tkcon::EvalAttached {} ::tkcon::EvalNamespace \ + [interp alias {} ::tkcon::EvalAttached] [list $name] + } + set PRIV(namesp) $name + set PRIV(StatusAttach) "$PRIV(app) $PRIV(namesp) ($PRIV(apptype))" +} + +## ::tkcon::NewSocket - called to create a socket to connect to +# ARGS: none +# Results: It will create a socket, and attach if requested +## +proc ::tkcon::NewSocket {} { + variable PRIV + + set t $PRIV(base).newsock + if {![winfo exists $t]} { + toplevel $t + wm withdraw $t + wm title $t "tkcon Create Socket" + label $t.lhost -text "Host: " + entry $t.host -width 20 + label $t.lport -text "Port: " + entry $t.port -width 4 + button $t.ok -text "OK" -command {set ::tkcon::PRIV(grab) 1} + bind $t.host [list focus $t.port] + bind $t.port [list focus $t.ok] + bind $t.ok [list $t.ok invoke] + grid $t.lhost $t.host $t.lport $t.port -sticky ew + grid $t.ok - - - -sticky ew + grid columnconfig $t 1 -weight 1 + grid rowconfigure $t 1 -weight 1 + wm transient $t $PRIV(root) + wm geometry $t +[expr {([winfo screenwidth $t]-[winfo \ + reqwidth $t]) / 2}]+[expr {([winfo \ + screenheight $t]-[winfo reqheight $t]) / 2}] + } + #$t.host delete 0 end + #$t.port delete 0 end + wm deiconify $t + raise $t + grab $t + focus $t.host + vwait ::tkcon::PRIV(grab) + grab release $t + wm withdraw $t + set host [$t.host get] + set port [$t.port get] + if {$host == ""} { return } + if {[catch { + set sock [socket $host $port] + } err]} { + tk_messageBox -title "Socket Connection Error" \ + -message "Unable to connect to \"$host:$port\":\n$err" \ + -icon error -type ok + } else { + Attach $sock socket + } +} + +## ::tkcon::Load - sources a file into the console +## The file is actually sourced in the currently attached's interp +# ARGS: fn - (optional) filename to source in +# Returns: selected filename ({} if nothing was selected) +## +proc ::tkcon::Load { {fn ""} } { + set types { + {{Tcl Files} {.tcl .tk}} + {{Text Files} {.txt}} + {{All Files} *} + } + if { + [string match {} $fn] && + ([catch {tk_getOpenFile -filetypes $types \ + -title "Source File"} fn] || [string match {} $fn]) + } { return } + EvalAttached [list source $fn] +} + +## ::tkcon::Save - saves the console or other widget buffer to a file +## This does not eval in a slave because it's not necessary +# ARGS: w - console text widget +# fn - (optional) filename to save to +## +proc ::tkcon::Save { {fn ""} {type ""} {opt ""} {mode w} } { + variable PRIV + + if {![regexp -nocase {^(all|history|stdin|stdout|stderr|widget)$} $type]} { + array set s { 0 All 1 History 2 Stdin 3 Stdout 4 Stderr 5 Cancel } + ## Allow user to specify what kind of stuff to save + set type [tk_dialog $PRIV(base).savetype "Save Type" \ + "What part of the text do you want to save?" \ + questhead 0 $s(0) $s(1) $s(2) $s(3) $s(4) $s(5)] + if {$type == 5 || $type == -1} return + set type $s($type) + } + if {[string match {} $fn]} { + set types { + {{Tcl Files} {.tcl .tk}} + {{Text Files} {.txt}} + {{All Files} *} + } + if {[catch {tk_getSaveFile -defaultextension .tcl -filetypes $types \ + -title "Save $type"} fn] || [string match {} $fn]} return + } + set type [string tolower $type] + switch $type { + stdin - stdout - stderr { + set data {} + foreach {first last} [$PRIV(console) tag ranges $type] { + lappend data [$PRIV(console) get $first $last] + } + set data [join $data \n] + } + history { set data [tkcon history] } + all - default { set data [$PRIV(console) get 1.0 end-1c] } + widget { + set data [$opt get 1.0 end-1c] + } + } + if {[catch {open $fn $mode} fid]} { + return -code error "Save Error: Unable to open '$fn' for writing\n$fid" + } + puts -nonewline $fid $data + close $fid +} + +## ::tkcon::MainInit +## This is only called for the main interpreter to include certain procs +## that we don't want to include (or rather, just alias) in slave interps. +## +proc ::tkcon::MainInit {} { + variable PRIV + + if {![info exists PRIV(slaves)]} { + array set PRIV [list slave 0 slaves Main name {} \ + interps [list [tk appname]]] + } + interp alias {} ::tkcon::Main {} ::tkcon::InterpEval Main + interp alias {} ::tkcon::Slave {} ::tkcon::InterpEval + + proc ::tkcon::GetSlaveNum {} { + set i -1 + while {[interp exists Slave[incr i]]} { + # oh my god, an empty loop! + } + return $i + } + + ## ::tkcon::New - create new console window + ## Creates a slave interpreter and sources in this script. + ## All other interpreters also get a command to eval function in the + ## new interpreter. + ## + proc ::tkcon::New {} { + variable PRIV + global argv0 argc argv + + set tmp [interp create Slave[GetSlaveNum]] + lappend PRIV(slaves) $tmp + load {} Tk $tmp + lappend PRIV(interps) [$tmp eval [list tk appname \ + "[tk appname] $tmp"]] + if {[info exist argv0]} {$tmp eval [list set argv0 $argv0]} + $tmp eval set argc $argc + $tmp eval [list set argv $argv] + $tmp eval [list namespace eval ::tkcon {}] + $tmp eval [list set ::tkcon::PRIV(name) $tmp] + $tmp eval [list set ::tkcon::PRIV(SCRIPT) $::tkcon::PRIV(SCRIPT)] + $tmp alias exit ::tkcon::Exit $tmp + $tmp alias ::tkcon::Destroy ::tkcon::Destroy $tmp + $tmp alias ::tkcon::New ::tkcon::New + $tmp alias ::tkcon::Main ::tkcon::InterpEval Main + $tmp alias ::tkcon::Slave ::tkcon::InterpEval + $tmp alias ::tkcon::Interps ::tkcon::Interps + $tmp alias ::tkcon::NewDisplay ::tkcon::NewDisplay + $tmp alias ::tkcon::Display ::tkcon::Display + $tmp alias ::tkcon::StateCheckpoint ::tkcon::StateCheckpoint + $tmp alias ::tkcon::StateCleanup ::tkcon::StateCleanup + $tmp alias ::tkcon::StateCompare ::tkcon::StateCompare + $tmp alias ::tkcon::StateRevert ::tkcon::StateRevert + $tmp eval { + if [catch {source -rsrc tkcon}] { source $::tkcon::PRIV(SCRIPT) } + } + return $tmp + } + + ## ::tkcon::Exit - full exit OR destroy slave console + ## This proc should only be called in the main interpreter from a slave. + ## The master determines whether we do a full exit or just kill the slave. + ## + proc ::tkcon::Exit {slave args} { + variable PRIV + variable OPT + + ## Slave interpreter exit request + if {[string match exit $OPT(slaveexit)]} { + ## Only exit if it specifically is stated to do so + uplevel 1 exit $args + } + ## Otherwise we will delete the slave interp and associated data + set name [InterpEval $slave] + set PRIV(interps) [lremove $PRIV(interps) [list $name]] + set PRIV(slaves) [lremove $PRIV(slaves) [list $slave]] + interp delete $slave + StateCleanup $slave + return + } + + ## ::tkcon::Destroy - destroy console window + ## This proc should only be called by the main interpreter. If it is + ## called from there, it will ask before exiting tkcon. All others + ## (slaves) will just have their slave interpreter deleted, closing them. + ## + proc ::tkcon::Destroy {{slave {}}} { + variable PRIV + + if {[string match {} $slave]} { + ## Main interpreter close request + if {[tk_dialog $PRIV(base).destroyme {Quit tkcon?} \ + {Closing the Main console will quit tkcon} \ + warning 0 "Don't Quit" "Quit tkcon"]} exit + } else { + ## Slave interpreter close request + set name [InterpEval $slave] + set PRIV(interps) [lremove $PRIV(interps) [list $name]] + set PRIV(slaves) [lremove $PRIV(slaves) [list $slave]] + interp delete $slave + } + StateCleanup $slave + return + } + + ## We want to do a couple things before exiting... + if {[catch {rename ::exit ::tkcon::FinalExit} err]} { + puts stderr "tkcon might panic:\n$err" + } + proc ::exit args { + if {$::tkcon::OPT(usehistory)} { + if {[catch {open $::tkcon::PRIV(histfile) w} fid]} { + puts stderr "unable to save history file:\n$fid" + # pause a moment, because we are about to die finally... + after 1000 + } else { + set max [::tkcon::EvalSlave history nextid] + set id [expr {$max - $::tkcon::OPT(history)}] + if {$id < 1} { set id 1 } + ## FIX: This puts history in backwards!! + while {($id < $max) && \ + ![catch {::tkcon::EvalSlave history event $id} cmd]} { + if {[string compare {} $cmd]} { + puts $fid "::tkcon::EvalSlave history add [list $cmd]" + } + incr id + } + close $fid + } + } + uplevel 1 ::tkcon::FinalExit $args + } + + ## ::tkcon::InterpEval - passes evaluation to another named interpreter + ## If the interpreter is named, but no args are given, it returns the + ## [tk appname] of that interps master (not the associated eval slave). + ## + proc ::tkcon::InterpEval {{slave {}} args} { + variable PRIV + + if {[string match {} $slave]} { + return $PRIV(slaves) + } elseif {[string match {[Mm]ain} $slave]} { + set slave {} + } + if {[llength $args]} { + return [interp eval $slave uplevel \#0 $args] + } else { + return [interp eval $slave tk appname] + } + } + + proc ::tkcon::Interps {{ls {}} {interp {}}} { + if {[string match {} $interp]} { lappend ls {} [tk appname] } + foreach i [interp slaves $interp] { + if {[string compare {} $interp]} { set i "$interp $i" } + if {[string compare {} [interp eval $i package provide Tk]]} { + lappend ls $i [interp eval $i tk appname] + } else { + lappend ls $i {} + } + set ls [Interps $ls $i] + } + return $ls + } + + proc ::tkcon::Display {{disp {}}} { + variable DISP + + set res {} + if {$disp != ""} { + if {![info exists DISP($disp)]} { return } + return [list $DISP($disp) [winfo interps -displayof $DISP($disp)]] + } + return [lsort -dictionary [array names DISP]] + } + + proc ::tkcon::NewDisplay {} { + variable PRIV + variable DISP + + set t $PRIV(base).newdisp + if {![winfo exists $t]} { + toplevel $t + wm withdraw $t + wm title $t "tkcon Attach to Display" + label $t.gets -text "New Display: " + entry $t.data -width 32 + button $t.ok -text "OK" -command {set ::tkcon::PRIV(grab) 1} + bind $t.data [list $t.ok invoke] + bind $t.ok [list $t.ok invoke] + grid $t.gets $t.data -sticky ew + grid $t.ok - -sticky ew + grid columnconfig $t 1 -weight 1 + grid rowconfigure $t 1 -weight 1 + wm transient $t $PRIV(root) + wm geometry $t +[expr {([winfo screenwidth $t]-[winfo \ + reqwidth $t]) / 2}]+[expr {([winfo \ + screenheight $t]-[winfo reqheight $t]) / 2}] + } + $t.data delete 0 end + wm deiconify $t + raise $t + grab $t + focus $t.data + vwait ::tkcon::PRIV(grab) + grab release $t + wm withdraw $t + set disp [$t.data get] + if {$disp == ""} { return } + regsub -all {\.} [string tolower $disp] ! dt + set dt $PRIV(base).$dt + destroy $dt + if {[catch { + toplevel $dt -screen $disp + set interps [winfo interps -displayof $dt] + if {![llength $interps]} { + error "No other Tk interpreters on $disp" + } + send -displayof $dt [lindex $interps 0] [list info tclversion] + } err]} { + global env + if {[info exists env(DISPLAY)]} { + set myd $env(DISPLAY) + } else { + set myd "myDisplay:0" + } + tk_messageBox -title "Display Connection Error" \ + -message "Unable to connect to \"$disp\":\n$err\ + \nMake sure you have xauth-based permissions\ + (xauth add $myd . `mcookie`), and xhost is disabled\ + (xhost -) on \"$disp\"" \ + -icon error -type ok + destroy $dt + return + } + set DISP($disp) $dt + wm withdraw $dt + bind $dt [subst {catch {unset ::tkcon::DISP($disp)}}] + tk_messageBox -title "$disp Connection" \ + -message "Connected to \"$disp\", found:\n[join $interps \n]" \ + -type ok + } + + ## + ## The following state checkpoint/revert procedures are very sketchy + ## and prone to problems. They do not track modifications to currently + ## existing procedures/variables, and they can really screw things up + ## if you load in libraries (especially Tk) between checkpoint and + ## revert. Only with this knowledge in mind should you use these. + ## + + ## ::tkcon::StateCheckpoint - checkpoints the current state of the system + ## This allows you to return to this state with ::tkcon::StateRevert + # ARGS: + ## + proc ::tkcon::StateCheckpoint {app type} { + variable CPS + variable PRIV + + if {[info exists CPS($type,$app,cmd)] && \ + [tk_dialog $PRIV(base).warning "Overwrite Previous State?" \ + "Are you sure you want to lose previously checkpointed\ + state of $type \"$app\"?" questhead 1 "Do It" "Cancel"]} return + set CPS($type,$app,cmd) [EvalOther $app $type info commands *] + set CPS($type,$app,var) [EvalOther $app $type info vars *] + return + } + + ## ::tkcon::StateCompare - compare two states and output difference + # ARGS: + ## + proc ::tkcon::StateCompare {app type {verbose 0}} { + variable CPS + variable PRIV + variable OPT + variable COLOR + + if {![info exists CPS($type,$app,cmd)]} { + return -code error \ + "No previously checkpointed state for $type \"$app\"" + } + set w $PRIV(base).compare + if {[winfo exists $w]} { + $w.text config -state normal + $w.text delete 1.0 end + } else { + toplevel $w + frame $w.btn + scrollbar $w.sy -takefocus 0 -bd 1 -command [list $w.text yview] + text $w.text -yscrollcommand [list $w.sy set] -height 12 \ + -foreground $COLOR(stdin) \ + -background $COLOR(bg) \ + -insertbackground $COLOR(cursor) \ + -font $OPT(font) + pack $w.btn -side bottom -fill x + pack $w.sy -side right -fill y + pack $w.text -fill both -expand 1 + button $w.btn.close -text "Dismiss" -width 11 \ + -command [list destroy $w] + button $w.btn.check -text "Recheckpoint" -width 11 + button $w.btn.revert -text "Revert" -width 11 + button $w.btn.expand -text "Verbose" -width 11 + button $w.btn.update -text "Update" -width 11 + pack $w.btn.check $w.btn.revert $w.btn.expand $w.btn.update \ + $w.btn.close -side left -fill x -padx 4 -pady 2 -expand 1 + $w.text tag config red -foreground red + } + wm title $w "Compare State: $type [list $app]" + + $w.btn.check config \ + -command "::tkcon::StateCheckpoint [list $app] $type; \ + ::tkcon::StateCompare [list $app] $type $verbose" + $w.btn.revert config \ + -command "::tkcon::StateRevert [list $app] $type; \ + ::tkcon::StateCompare [list $app] $type $verbose" + $w.btn.update config -command [info level 0] + if {$verbose} { + $w.btn.expand config -text Brief \ + -command [list ::tkcon::StateCompare $app $type 0] + } else { + $w.btn.expand config -text Verbose \ + -command [list ::tkcon::StateCompare $app $type 1] + } + ## Don't allow verbose mode unless 'dump' exists in $app + ## We're assuming this is tkcon's dump command + set hasdump [llength [EvalOther $app $type info commands dump]] + if {$hasdump} { + $w.btn.expand config -state normal + } else { + $w.btn.expand config -state disabled + } + + set cmds [lremove [EvalOther $app $type info commands *] \ + $CPS($type,$app,cmd)] + set vars [lremove [EvalOther $app $type info vars *] \ + $CPS($type,$app,var)] + + if {$hasdump && $verbose} { + set cmds [EvalOther $app $type eval dump c -nocomplain $cmds] + set vars [EvalOther $app $type eval dump v -nocomplain $vars] + } + $w.text insert 1.0 "NEW COMMANDS IN \"$app\":\n" red \ + $cmds {} "\n\nNEW VARIABLES IN \"$app\":\n" red $vars {} + + raise $w + $w.text config -state disabled + } + + ## ::tkcon::StateRevert - reverts interpreter to previous state + # ARGS: + ## + proc ::tkcon::StateRevert {app type} { + variable CPS + variable PRIV + + if {![info exists CPS($type,$app,cmd)]} { + return -code error \ + "No previously checkpointed state for $type \"$app\"" + } + if {![tk_dialog $PRIV(base).warning "Revert State?" \ + "Are you sure you want to revert the state in $type \"$app\"?"\ + questhead 1 "Do It" "Cancel"]} { + foreach i [lremove [EvalOther $app $type info commands *] \ + $CPS($type,$app,cmd)] { + catch {EvalOther $app $type rename $i {}} + } + foreach i [lremove [EvalOther $app $type info vars *] \ + $CPS($type,$app,var)] { + catch {EvalOther $app $type unset $i} + } + } + } + + ## ::tkcon::StateCleanup - cleans up state information in master array + # + ## + proc ::tkcon::StateCleanup {args} { + variable CPS + + if {![llength $args]} { + foreach state [array names CPS slave,*] { + if {![interp exists [string range $state 6 end]]} { + unset CPS($state) + } + } + } else { + set app [lindex $args 0] + set type [lindex $args 1] + if {[regexp {^(|slave)$} $type]} { + foreach state [array names CPS "slave,$app\[, \]*"] { + if {![interp exists [string range $state 6 end]]} { + unset CPS($state) + } + } + } else { + catch {unset CPS($type,$app)} + } + } + } +} + +## ::tkcon::Event - get history event, search if string != {} +## look forward (next) if $int>0, otherwise look back (prev) +# ARGS: W - console widget +## +proc ::tkcon::Event {int {str {}}} { + if {!$int} return + + variable PRIV + set w $PRIV(console) + + set nextid [EvalSlave history nextid] + if {[string compare {} $str]} { + ## String is not empty, do an event search + set event $PRIV(event) + if {$int < 0 && $event == $nextid} { set PRIV(cmdbuf) $str } + set len [string len $PRIV(cmdbuf)] + incr len -1 + if {$int > 0} { + ## Search history forward + while {$event < $nextid} { + if {[incr event] == $nextid} { + $w delete limit end + $w insert limit $PRIV(cmdbuf) + break + } elseif { + ![catch {EvalSlave history event $event} res] && + [set p [string first $PRIV(cmdbuf) $res]] > -1 + } { + set p2 [expr {$p + [string length $PRIV(cmdbuf)]}] + $w delete limit end + $w insert limit $res + Blink $w "limit + $p c" "limit + $p2 c" + break + } + } + set PRIV(event) $event + } else { + ## Search history reverse + while {![catch {EvalSlave history event [incr event -1]} res]} { + if {[set p [string first $PRIV(cmdbuf) $res]] > -1} { + set p2 [expr {$p + [string length $PRIV(cmdbuf)]}] + $w delete limit end + $w insert limit $res + set PRIV(event) $event + Blink $w "limit + $p c" "limit + $p2 c" + break + } + } + } + } else { + ## String is empty, just get next/prev event + if {$int > 0} { + ## Goto next command in history + if {$PRIV(event) < $nextid} { + $w delete limit end + if {[incr PRIV(event)] == $nextid} { + $w insert limit $PRIV(cmdbuf) + } else { + $w insert limit [EvalSlave history event $PRIV(event)] + } + } + } else { + ## Goto previous command in history + if {$PRIV(event) == $nextid} { + set PRIV(cmdbuf) [CmdGet $w] + } + if {[catch {EvalSlave history event [incr PRIV(event) -1]} res]} { + incr PRIV(event) + } else { + $w delete limit end + $w insert limit $res + } + } + } + $w mark set insert end + $w see end +} + +## ::tkcon::ErrorHighlight - magic error highlighting +## beware: voodoo included +# ARGS: +## +proc ::tkcon::ErrorHighlight w { + variable COLOR + + ## do voodoo here + set app [Attach] + # we have to pull the text out, because text regexps are screwed on \n's. + set info [$w get 1.0 end-1c] + # Check for specific line error in a proc + set exp(proc) "\"(\[^\"\]+)\"\n\[\t \]+\\\(procedure \"(\[^\"\]+)\"" + # Check for too few args to a proc + set exp(param) "parameter \"(\[^\"\]+)\" to \"(\[^\"\]+)\"" + set start 1.0 + while { + [regexp -indices -- $exp(proc) $info junk what cmd] || + [regexp -indices -- $exp(param) $info junk what cmd] + } { + foreach {w0 w1} $what {c0 c1} $cmd {break} + set what [string range $info $w0 $w1] + set cmd [string range $info $c0 $c1] + if {[string match *::* $cmd]} { + set res [uplevel 1 ::tkcon::EvalOther $app namespace eval \ + [list [namespace qualifiers $cmd] \ + [list info procs [namespace tail $cmd]]]] + } else { + set res [uplevel 1 ::tkcon::EvalOther $app info procs [list $cmd]] + } + if {[llength $res]==1} { + set tag [UniqueTag $w] + $w tag add $tag $start+${c0}c $start+1c+${c1}c + $w tag configure $tag -foreground $COLOR(stdout) + $w tag bind $tag [list $w tag configure $tag -underline 1] + $w tag bind $tag [list $w tag configure $tag -underline 0] + $w tag bind $tag "if {!\$tkPriv(mouseMoved)} \ + {[list edit -attach $app -type proc -find $what -- $cmd]}" + } + set info [string range $info $c1 end] + set start [$w index $start+${c1}c] + } + ## Next stage, check for procs that start a line + set start 1.0 + set exp(cmd) "^\"\[^\" \t\n\]+" + while { + [string compare {} [set ix \ + [$w search -regexp -count numc -- $exp(cmd) $start end]]] + } { + set start [$w index $ix+${numc}c] + # +1c to avoid the first quote + set cmd [$w get $ix+1c $start] + if {[string match *::* $cmd]} { + set res [uplevel 1 ::tkcon::EvalOther $app namespace eval \ + [list [namespace qualifiers $cmd] \ + [list info procs [namespace tail $cmd]]]] + } else { + set res [uplevel 1 ::tkcon::EvalOther $app info procs [list $cmd]] + } + if {[llength $res]==1} { + set tag [UniqueTag $w] + $w tag add $tag $ix+1c $start + $w tag configure $tag -foreground $COLOR(proc) + $w tag bind $tag [list $w tag configure $tag -underline 1] + $w tag bind $tag [list $w tag configure $tag -underline 0] + $w tag bind $tag "if {!\$tkPriv(mouseMoved)} \ + {[list edit -attach $app -type proc -- $cmd]}" + } + } +} + +## tkcon - command that allows control over the console +## This always exists in the main interpreter, and is aliased into +## other connected interpreters +# ARGS: totally variable, see internal comments +## +proc tkcon {cmd args} { + global errorInfo + + switch -glob -- $cmd { + buf* { + ## 'buffer' Sets/Query the buffer size + if {[llength $args]} { + if {[regexp {^[1-9][0-9]*$} $args]} { + set ::tkcon::OPT(buffer) $args + # catch in case the console doesn't exist yet + catch {::tkcon::ConstrainBuffer $::tkcon::PRIV(console) \ + $::tkcon::OPT(buffer)} + } else { + return -code error "buffer must be a valid integer" + } + } + return $::tkcon::OPT(buffer) + } + bg* { + ## 'bgerror' Brings up an error dialog + set errorInfo [lindex $args 1] + bgerror [lindex $args 0] + } + cl* { + ## 'close' Closes the console + ::tkcon::Destroy + } + cons* { + ## 'console' - passes the args to the text widget of the console. + set result [uplevel 1 $::tkcon::PRIV(console) $args] + ::tkcon::ConstrainBuffer $::tkcon::PRIV(console) \ + $::tkcon::OPT(buffer) + return $result + } + congets { + ## 'congets' a replacement for [gets stdin] + # Use the 'gets' alias of 'tkcon_gets' command instead of + # calling the *get* methods directly for best compatability + if {[llength $args] > 1} { + return -code error "wrong # args: must be \"tkcon congets [pfix]\"" + } + tkcon show + set old [bind TkConsole <>] + bind TkConsole <> { set ::tkcon::PRIV(wait) 0 } + set w $::tkcon::PRIV(console) + # Make sure to move the limit to get the right data + $w mark set insert end + if {[llength $args]} { + $w mark set limit insert + $w insert end $args + } else { + $w mark set limit insert + } + $w see end + vwait ::tkcon::PRIV(wait) + set line [::tkcon::CmdGet $w] + $w insert end \n + bind TkConsole <> $old + return $line + } + getc* { + ## 'getcommand' a replacement for [gets stdin] + ## This forces a complete command to be input though + if {[llength $args]} { + return -code error "wrong # args: must be \"tkcon getcommand\"" + } + tkcon show + set old [bind TkConsole <>] + bind TkConsole <> { set ::tkcon::PRIV(wait) 0 } + set w $::tkcon::PRIV(console) + # Make sure to move the limit to get the right data + $w mark set insert end + $w mark set limit insert + $w see end + vwait ::tkcon::PRIV(wait) + set line [::tkcon::CmdGet $w] + $w insert end \n + while {![info complete $line] || [regexp {[^\\]\\$} $line]} { + vwait ::tkcon::PRIV(wait) + set line [::tkcon::CmdGet $w] + $w insert end \n + $w see end + } + bind TkConsole <> $old + return $line + } + get - gets { + ## 'gets' - a replacement for [gets stdin] + ## This pops up a text widget to be used for stdin (local grabbed) + if {[llength $args]} { + return -code error "wrong # args: should be \"tkcon gets\"" + } + set t $::tkcon::PRIV(base).gets + if {![winfo exists $t]} { + toplevel $t + wm withdraw $t + wm title $t "tkcon gets stdin request" + label $t.gets -text "\"gets stdin\" request:" + text $t.data -width 32 -height 5 -wrap none \ + -xscrollcommand [list $t.sx set] \ + -yscrollcommand [list $t.sy set] + scrollbar $t.sx -orient h -takefocus 0 -highlightthick 0 \ + -command [list $t.data xview] + scrollbar $t.sy -orient v -takefocus 0 -highlightthick 0 \ + -command [list $t.data yview] + button $t.ok -text "OK" -command {set ::tkcon::PRIV(grab) 1} + bind $t.ok { %W invoke } + grid $t.gets - -sticky ew + grid $t.data $t.sy -sticky news + grid $t.sx -sticky ew + grid $t.ok - -sticky ew + grid columnconfig $t 0 -weight 1 + grid rowconfig $t 1 -weight 1 + wm transient $t $::tkcon::PRIV(root) + wm geometry $t +[expr {([winfo screenwidth $t]-[winfo \ + reqwidth $t]) / 2}]+[expr {([winfo \ + screenheight $t]-[winfo reqheight $t]) / 2}] + } + $t.data delete 1.0 end + wm deiconify $t + raise $t + grab $t + focus $t.data + vwait ::tkcon::PRIV(grab) + grab release $t + wm withdraw $t + return [$t.data get 1.0 end-1c] + } + err* { + ## Outputs stack caused by last error. + ## error handling with pizazz (but with pizza would be nice too) + if {[llength $args]==2} { + set app [lindex $args 0] + set type [lindex $args 1] + if {[catch {::tkcon::EvalOther $app $type set errorInfo} info]} { + set info "error getting info from $type $app:\n$info" + } + } else { + set info $::tkcon::PRIV(errorInfo) + } + if {[string match {} $info]} { set info "errorInfo empty" } + ## If args is empty, the -attach switch just ignores it + edit -attach $args -type error -- $info + } + fi* { + ## 'find' string + ::tkcon::Find $::tkcon::PRIV(console) $args + } + fo* { + ## 'font' ?fontname? - gets/sets the font of the console + if {[llength $args]} { + if {[info exists ::tkcon::PRIV(console)] && \ + [winfo exists $::tkcon::PRIV(console)]} { + $::tkcon::PRIV(console) config -font $args + set ::tkcon::OPT(font) [$::tkcon::PRIV(console) cget -font] + } else { + set ::tkcon::OPT(font) $args + } + } + return $::tkcon::OPT(font) + } + hid* - with* { + ## 'hide' 'withdraw' - hides the console. + wm withdraw $::tkcon::PRIV(root) + } + his* { + ## 'history' + set sub {\2} + if {[string match -new* $args]} { append sub "\n"} + set h [::tkcon::EvalSlave history] + regsub -all "( *\[0-9\]+ |\t)(\[^\n\]*\n?)" $h $sub h + return $h + } + ico* { + ## 'iconify' - iconifies the console with 'iconify'. + wm iconify $::tkcon::PRIV(root) + } + mas* - eval { + ## 'master' - evals contents in master interpreter + uplevel \#0 $args + } + set { + ## 'set' - set (or get, or unset) simple vars (not whole arrays) + ## from the master console interpreter + ## possible formats: + ## tkcon set + ## tkcon set + ## tkcon set w + ## tkcon set u + ## tkcon set r + if {[llength $args]==5} { + ## This is for use w/ 'tkcon upvar' and only works with slaves + foreach {var i var1 var2 op} $args break + if {[string compare {} $var2]} { append var1 "($var2)" } + switch $op { + u { uplevel \#0 [list unset $var] } + w { + return [uplevel \#0 [list set $var \ + [interp eval $i [list set $var1]]]] + } + r { + return [interp eval $i [list set $var1 \ + [uplevel \#0 [list set $var]]]] + } + } + } elseif {[llength $args] == 1} { + upvar \#0 [lindex $args 0] var + if {[array exists var]} { + return [array get var] + } else { + return $var + } + } + return [uplevel \#0 set $args] + } + append { + ## Modify a var in the master environment using append + return [uplevel \#0 append $args] + } + lappend { + ## Modify a var in the master environment using lappend + return [uplevel \#0 lappend $args] + } + sh* - dei* { + ## 'show|deiconify' - deiconifies the console. + wm deiconify $::tkcon::PRIV(root) + raise $::tkcon::PRIV(root) + focus -force $::tkcon::PRIV(console) + } + ti* { + ## 'title' ?title? - gets/sets the console's title + if {[llength $args]} { + return [wm title $::tkcon::PRIV(root) [join $args]] + } else { + return [wm title $::tkcon::PRIV(root)] + } + } + upv* { + ## 'upvar' masterVar slaveVar + ## link slave variable slaveVar to the master variable masterVar + ## only works masters<->slave + set masterVar [lindex $args 0] + set slaveVar [lindex $args 1] + if {[info exists $masterVar]} { + interp eval $::tkcon::OPT(exec) \ + [list set $slaveVar [set $masterVar]] + } else { + catch {interp eval $::tkcon::OPT(exec) [list unset $slaveVar]} + } + interp eval $::tkcon::OPT(exec) \ + [list trace variable $slaveVar rwu \ + [list tkcon set $masterVar $::tkcon::OPT(exec)]] + return + } + v* { + return $::tkcon::PRIV(version) + } + default { + ## tries to determine if the command exists, otherwise throws error + set new ::tkcon::[string toupper \ + [string index $cmd 0]][string range $cmd 1 end] + if {[llength [info command $new]]} { + uplevel \#0 $new $args + } else { + return -code error "bad option \"$cmd\": must be\ + [join [lsort [list attach close console destroy \ + font hide iconify load main master new save show \ + slave deiconify version title bgerror]] {, }]" + } + } + } +} + +## +## Some procedures to make up for lack of built-in shell commands +## + +## tkcon_puts - +## This allows me to capture all stdout/stderr to the console window +## This will be renamed to 'puts' at the appropriate time during init +## +# ARGS: same as usual +# Outputs: the string with a color-coded text tag +## +proc tkcon_puts args { + set len [llength $args] + foreach {arg1 arg2 arg3} $args { break } + + if {$len == 1} { + set sarg $arg1 + set nl 1 + set farg stdout + } elseif {$len == 2} { + if {![string compare $arg1 -nonewline]} { + set sarg $arg2 + set farg stdout + set nl 0 + } elseif {![string compare $arg1 stdout] \ + || ![string compare $arg1 stderr]} { + set sarg $arg2 + set farg $arg1 + set nl 1 + } else { + set len 0 + } + } elseif {$len == 3} { + if {![string compare $arg1 -nonewline] \ + && (![string compare $arg2 stdout] \ + || ![string compare $arg2 stderr])} { + set sarg $arg3 + set farg $arg2 + set nl 0 + } elseif {(![string compare $arg1 stdout] \ + || ![string compare $arg1 stderr]) \ + && ![string compare $arg3 nonewline]} { + set sarg $arg2 + set farg $arg1 + set nl 0 + } else { + set len 0 + } + } else { + set len 0 + } + + ## $len == 0 means it wasn't handled by tkcon above. + ## + + if {$len != 0} { + + ## "poor man's" \r substitution---erase everything on the output + ## line and print from character after the \r + + set rpt [string last \r $sarg] + if {$rpt >= 0} { + tkcon console delete "insert linestart" "insert lineend" + set sarg [string range $sarg [expr {$rpt + 1}] end] + } + + set bpt [string first \b $sarg] + if {$bpt >= 0} { + set narg [string range $sarg [expr {$bpt + 1}] end] + set sarg [string range $sarg 0 [expr {$bpt - 1}]] + set nl 0 + } + + + if {$nl == 0} { + tkcon console insert output $sarg $farg + } else { + tkcon console insert output "$sarg\n" $farg + } + + if {$bpt >= 0} { + tkcon console delete "insert -1 char" insert + if {$nl == 0} { + tkcon_puts $farg $narg nonewline + } else { + tkcon_puts $farg $narg + } + } + + } else { + global errorCode errorInfo + if {[catch "tkcon_tcl_puts $args" msg]} { + regsub tkcon_tcl_puts $msg puts msg + regsub -all tkcon_tcl_puts $errorInfo puts errorInfo + return -code error $msg + } + return $msg + } + + ## WARNING: This update should behave well because it uses idletasks, + ## however, if there are weird looping problems with events, or + ## hanging in waits, try commenting this out. + if {$len} { + tkcon console see output + update idletasks + } +} + +## tkcon_gets - +## This allows me to capture all stdin input without needing to stdin +## This will be renamed to 'gets' at the appropriate time during init +## +# ARGS: same as gets +# Outputs: same as gets +## +proc tkcon_gets args { + set len [llength $args] + if {$len != 1 && $len != 2} { + return -code error \ + "wrong # args: should be \"gets channelId ?varName?\"" + } + if {[string compare stdin [lindex $args 0]]} { + return [uplevel 1 tkcon_tcl_gets $args] + } + set gtype [tkcon set ::tkcon::OPT(gets)] + if {$gtype == ""} { set gtype congets } + set data [tkcon $gtype] + if {$len == 2} { + upvar 1 [lindex $args 1] var + set var $data + return [string length $data] + } + return $data +} + +## edit - opens a file/proc/var for reading/editing +## +# Arguments: +# type proc/file/var +# what the actual name of the item +# Returns: nothing +## +proc edit {args} { + array set opts {-find {} -type {} -attach {}} + while {[string match -* [lindex $args 0]]} { + switch -glob -- [lindex $args 0] { + -f* { set opts(-find) [lindex $args 1] } + -a* { set opts(-attach) [lindex $args 1] } + -t* { set opts(-type) [lindex $args 1] } + -- { set args [lreplace $args 0 0]; break } + default {return -code error "unknown option \"[lindex $args 0]\""} + } + set args [lreplace $args 0 1] + } + # determine who we are dealing with + if {[llength $opts(-attach)]} { + foreach {app type} $opts(-attach) {break} + } else { + foreach {app type} [tkcon attach] {break} + } + + set word [lindex $args 0] + if {[string match {} $opts(-type)]} { + if {[llength [::tkcon::EvalOther $app $type info commands [list $word]]]} { + set opts(-type) "proc" + } elseif {[llength [::tkcon::EvalOther $app $type info vars [list $word]]]} { + set opts(-type) "var" + } elseif {[::tkcon::EvalOther $app $type file isfile [list $word]]} { + set opts(-type) "file" + } + } + if {[string compare $opts(-type) {}]} { + # Create unique edit window toplevel + set w $::tkcon::PRIV(base).__edit + set i 0 + while {[winfo exists $w[incr i]]} {} + append w $i + toplevel $w + wm withdraw $w + if {[string length $word] > 12} { + wm title $w "tkcon Edit: [string range $word 0 9]..." + } else { + wm title $w "tkcon Edit: $word" + } + + text $w.text -wrap none \ + -xscrollcommand [list $w.sx set] \ + -yscrollcommand [list $w.sy set] \ + -foreground $::tkcon::COLOR(stdin) \ + -background $::tkcon::COLOR(bg) \ + -insertbackground $::tkcon::COLOR(cursor) \ + -font $::tkcon::OPT(font) + scrollbar $w.sx -orient h -takefocus 0 -bd 1 \ + -command [list $w.text xview] + scrollbar $w.sy -orient v -takefocus 0 -bd 1 \ + -command [list $w.text yview] + + set menu [menu $w.mbar] + $w configure -menu $menu + + ## File Menu + ## + set m [menu [::tkcon::MenuButton $menu File file]] + $m add command -label "Save As..." -underline 0 \ + -command [list ::tkcon::Save {} widget $w.text] + $m add command -label "Append To..." -underline 0 \ + -command [list ::tkcon::Save {} widget $w.text a+] + $m add separator + $m add command -label "Dismiss" -underline 0 -accel "Ctrl-w" \ + -command [list destroy $w] + bind $w [list destroy $w] + bind $w <$::tkcon::PRIV(meta)-w> [list destroy $w] + + ## Edit Menu + ## + set text $w.text + set m [menu [::tkcon::MenuButton $menu Edit edit]] + $m add command -label "Cut" -underline 2 \ + -command [list tk_textCut $text] + $m add command -label "Copy" -underline 0 \ + -command [list tk_textCopy $text] + $m add command -label "Paste" -underline 0 \ + -command [list tk_textPaste $text] + $m add separator + $m add command -label "Find" -underline 0 \ + -command [list ::tkcon::FindBox $text] + + ## Send To Menu + ## + set m [menu [::tkcon::MenuButton $menu "Send To..." send]] + $m add command -label "Send To $app" -underline 0 \ + -command "::tkcon::EvalOther [list $app] $type \ + eval \[$w.text get 1.0 end-1c\]" + set other [tkcon attach] + if {[string compare $other [list $app $type]]} { + $m add command -label "Send To [lindex $other 0]" \ + -command "::tkcon::EvalOther $other \ + eval \[$w.text get 1.0 end-1c\]" + } + + grid $w.text - $w.sy -sticky news + grid $w.sx - -sticky ew + grid columnconfigure $w 0 -weight 1 + grid columnconfigure $w 1 -weight 1 + grid rowconfigure $w 0 -weight 1 + } else { + return -code error "unrecognized type '$word'" + } + switch -glob -- $opts(-type) { + proc* { + $w.text insert 1.0 \ + [::tkcon::EvalOther $app $type dump proc [list $word]] + } + var* { + $w.text insert 1.0 \ + [::tkcon::EvalOther $app $type dump var [list $word]] + } + file { + $w.text insert 1.0 [::tkcon::EvalOther $app $type eval \ + [subst -nocommands { + set __tkcon(fid) [open $word r] + set __tkcon(data) [read \$__tkcon(fid)] + close \$__tkcon(fid) + after 1000 unset __tkcon + return \$__tkcon(data) + } + ]] + } + error* { + $w.text insert 1.0 [join $args \n] + ::tkcon::ErrorHighlight $w.text + } + default { + $w.text insert 1.0 [join $args \n] + } + } + wm deiconify $w + focus $w.text + if {[string compare $opts(-find) {}]} { + ::tkcon::Find $w.text $opts(-find) -case 1 + } +} +interp alias {} ::more {} ::edit +interp alias {} ::less {} ::edit + +## echo +## Relaxes the one string restriction of 'puts' +# ARGS: any number of strings to output to stdout +## +proc echo args { puts [concat $args] } + +## clear - clears the buffer of the console (not the history though) +## This is executed in the parent interpreter +## +proc clear {{pcnt 100}} { + if {![regexp {^[0-9]*$} $pcnt] || $pcnt < 1 || $pcnt > 100} { + return -code error \ + "invalid percentage to clear: must be 1-100 (100 default)" + } elseif {$pcnt == 100} { + tkcon console delete 1.0 end + } else { + set tmp [expr {$pcnt/100.0*[tkcon console index end]}] + tkcon console delete 1.0 "$tmp linestart" + } +} + +## alias - akin to the csh alias command +## If called with no args, then it dumps out all current aliases +## If called with one arg, returns the alias of that arg (or {} if none) +# ARGS: newcmd - (optional) command to bind alias to +# args - command and args being aliased +## +proc alias {{newcmd {}} args} { + if {[string match {} $newcmd]} { + set res {} + foreach a [interp aliases] { + lappend res [list $a -> [interp alias {} $a]] + } + return [join $res \n] + } elseif {![llength $args]} { + interp alias {} $newcmd + } else { + eval interp alias [list {} $newcmd {}] $args + } +} + +## unalias - unaliases an alias'ed command +# ARGS: cmd - command to unbind as an alias +## +proc unalias {cmd} { + interp alias {} $cmd {} +} + +## dump - outputs variables/procedure/widget info in source'able form. +## Accepts glob style pattern matching for the names +# +# ARGS: type - type of thing to dump: must be variable, procedure, widget +# +# OPTS: -nocomplain +# don't complain if no items of the specified type are found +# -filter pattern +# specifies a glob filter pattern to be used by the variable +# method as an array filter pattern (it filters down for +# nested elements) and in the widget method as a config +# option filter pattern +# -- forcibly ends options recognition +# +# Returns: the values of the requested items in a 'source'able form +## +proc dump {type args} { + set whine 1 + set code ok + if {![llength $args]} { + ## If no args, assume they gave us something to dump and + ## we'll try anything + set args $type + set type any + } + while {[string match -* [lindex $args 0]]} { + switch -glob -- [lindex $args 0] { + -n* { set whine 0; set args [lreplace $args 0 0] } + -f* { set fltr [lindex $args 1]; set args [lreplace $args 0 1] } + -- { set args [lreplace $args 0 0]; break } + default {return -code error "unknown option \"[lindex $args 0]\""} + } + } + if {$whine && ![llength $args]} { + return -code error "wrong \# args: [lindex [info level 0] 0] type\ + ?-nocomplain? ?-filter pattern? ?--? pattern ?pattern ...?" + } + set res {} + switch -glob -- $type { + c* { + # command + # outputs commands by figuring out, as well as possible, what it is + # this does not attempt to auto-load anything + foreach arg $args { + if {[llength [set cmds [info commands $arg]]]} { + foreach cmd [lsort $cmds] { + if {[lsearch -exact [interp aliases] $cmd] > -1} { + append res "\#\# ALIAS: $cmd =>\ + [interp alias {} $cmd]\n" + } elseif { + [llength [info procs $cmd]] || + ([string match *::* $cmd] && + [llength [namespace eval [namespace qual $cmd] \ + info procs [namespace tail $cmd]]]) + } { + if {[catch {dump p -- $cmd} msg] && $whine} { + set code error + } + append res $msg\n + } else { + append res "\#\# COMMAND: $cmd\n" + } + } + } elseif {$whine} { + append res "\#\# No known command $arg\n" + set code error + } + } + } + v* { + # variable + # outputs variables value(s), whether array or simple. + if {![info exists fltr]} { set fltr * } + foreach arg $args { + if {![llength [set vars [uplevel 1 info vars [list $arg]]]]} { + if {[uplevel 1 info exists $arg]} { + set vars $arg + } elseif {$whine} { + append res "\#\# No known variable $arg\n" + set code error + continue + } else { continue } + } + foreach var [lsort $vars] { + if {[uplevel 1 [list info locals $var]] == ""} { + # use the proper scope of the var, but + # namespace which won't id locals correctly + set var [uplevel 1 \ + [list namespace which -variable $var]] + } + upvar 1 $var v + if {[array exists v] || [catch {string length $v}]} { + set nst {} + append res "array set [list $var] \{\n" + if {[array size v]} { + foreach i [lsort [array names v $fltr]] { + upvar 0 v\($i\) __a + if {[array exists __a]} { + append nst "\#\# NESTED ARRAY ELEM: $i\n" + append nst "upvar 0 [list $var\($i\)] __a;\ + [dump v -filter $fltr __a]\n" + } else { + append res " [list $i]\t[list $v($i)]\n" + } + } + } else { + ## empty array + append res " empty array\n" + append nst "unset [list $var](empty)\n" + } + append res "\}\n$nst" + } else { + append res [list set $var $v]\n + } + } + } + } + p* { + # procedure + foreach arg $args { + if { + ![llength [set procs [info proc $arg]]] && + ([string match *::* $arg] && + [llength [set ps [namespace eval \ + [namespace qualifier $arg] \ + info procs [namespace tail $arg]]]]) + } { + set procs {} + set namesp [namespace qualifier $arg] + foreach p $ps { + lappend procs ${namesp}::$p + } + } + if {[llength $procs]} { + foreach p [lsort $procs] { + set as {} + foreach a [info args $p] { + if {[info default $p $a tmp]} { + lappend as [list $a $tmp] + } else { + lappend as $a + } + } + append res [list proc $p $as [info body $p]]\n + } + } elseif {$whine} { + append res "\#\# No known proc $arg\n" + set code error + } + } + } + w* { + # widget + ## The user should have Tk loaded + if {![llength [info command winfo]]} { + return -code error "winfo not present, cannot dump widgets" + } + if {![info exists fltr]} { set fltr .* } + foreach arg $args { + if {[llength [set ws [info command $arg]]]} { + foreach w [lsort $ws] { + if {[winfo exists $w]} { + if {[catch {$w configure} cfg]} { + append res "\#\# Widget $w\ + does not support configure method" + set code error + } else { + append res "\#\# [winfo class $w]\ + $w\n$w configure" + foreach c $cfg { + if {[llength $c] != 5} continue + ## Check to see that the option does + ## not match the default, then check + ## the item against the user filter + if {[string compare [lindex $c 3] \ + [lindex $c 4]] && \ + [regexp -nocase -- $fltr $c]} { + append res " \\\n\t[list [lindex $c 0]\ + [lindex $c 4]]" + } + } + append res \n + } + } + } + } elseif {$whine} { + append res "\#\# No known widget $arg\n" + set code error + } + } + } + a* { + ## see if we recognize it, other complain + if {[regexp {(var|com|proc|widget)} \ + [set types [uplevel 1 what $args]]]} { + foreach type $types { + if {[regexp {(var|com|proc|widget)} $type]} { + append res "[uplevel 1 dump $type $args]\n" + } + } + } else { + set res "dump was unable to resolve type for \"$args\"" + set code error + } + } + default { + return -code error "bad [lindex [info level 0] 0] option\ + \"$type\": must be variable, command, procedure,\ + or widget" + } + } + return -code $code [string trimright $res \n] +} + +## idebug - interactive debugger +# +# idebug body ?level? +# +# Prints out the body of the command (if it is a procedure) at the +# specified level. level defaults to the current level. +# +# idebug break +# +# Creates a breakpoint within a procedure. This will only trigger +# if idebug is on and the id matches the pattern. If so, TkCon will +# pop to the front with the prompt changed to an idebug prompt. You +# are given the basic ability to observe the call stack an query/set +# variables or execute Tcl commands at any level. A separate history +# is maintained in debugging mode. +# +# idebug echo|{echo ?id?} ?args? +# +# Behaves just like "echo", but only triggers when idebug is on. +# You can specify an optional id to further restrict triggering. +# If no id is specified, it defaults to the name of the command +# in which the call was made. +# +# idebug id ?id? +# +# Query or set the idebug id. This id is used by other idebug +# methods to determine if they should trigger or not. The idebug +# id can be a glob pattern and defaults to *. +# +# idebug off +# +# Turns idebug off. +# +# idebug on ?id? +# +# Turns idebug on. If 'id' is specified, it sets the id to it. +# +# idebug puts|{puts ?id?} args +# +# Behaves just like "puts", but only triggers when idebug is on. +# You can specify an optional id to further restrict triggering. +# If no id is specified, it defaults to the name of the command +# in which the call was made. +# +# idebug show type ?level? ?VERBOSE? +# +# 'type' must be one of vars, locals or globals. This method +# will output the variables/locals/globals present in a particular +# level. If VERBOSE is added, then it actually 'dump's out the +# values as well. 'level' defaults to the level in which this +# method was called. +# +# idebug trace ?level? +# +# Prints out the stack trace from the specified level up to the top +# level. 'level' defaults to the current level. +# +## +proc idebug {opt args} { + global IDEBUG + + if {![info exists IDEBUG(on)]} { + array set IDEBUG { on 0 id * debugging 0 } + } + set level [expr {[info level]-1}] + switch -glob -- $opt { + on { + if {[llength $args]} { set IDEBUG(id) $args } + return [set IDEBUG(on) 1] + } + off { return [set IDEBUG(on) 0] } + id { + if {![llength $args]} { + return $IDEBUG(id) + } else { return [set IDEBUG(id) $args] } + } + break { + if {!$IDEBUG(on) || $IDEBUG(debugging) || \ + ([llength $args] && \ + ![string match $IDEBUG(id) $args]) || [info level]<1} { + return + } + set IDEBUG(debugging) 1 + puts stderr "idebug at level \#$level: [lindex [info level -1] 0]" + set tkcon [llength [info command tkcon]] + if {$tkcon} { + tkcon master eval set ::tkcon::OPT(prompt2) \$::tkcon::OPT(prompt1) + tkcon master eval set ::tkcon::OPT(prompt1) \$::tkcon::OPT(debugPrompt) + set slave [tkcon set ::tkcon::OPT(exec)] + set event [tkcon set ::tkcon::PRIV(event)] + tkcon set ::tkcon::OPT(exec) [tkcon master interp create debugger] + tkcon set ::tkcon::PRIV(event) 1 + } + set max $level + while 1 { + set err {} + if {$tkcon} { + # tkcon's overload of gets is advanced enough to not need + # this, but we get a little better control this way. + tkcon evalSlave set level $level + tkcon prompt + set line [tkcon getcommand] + tkcon console mark set output end + } else { + puts -nonewline stderr "(level \#$level) debug > " + gets stdin line + while {![info complete $line]} { + puts -nonewline "> " + append line "\n[gets stdin]" + } + } + if {[string match {} $line]} continue + set key [lindex $line 0] + if {![regexp {^([#-]?[0-9]+)} [lreplace $line 0 0] lvl]} { + set lvl \#$level + } + set res {}; set c 0 + switch -- $key { + + { + ## Allow for jumping multiple levels + if {$level < $max} { + idebug trace [incr level] $level 0 VERBOSE + } + } + - { + ## Allow for jumping multiple levels + if {$level > 1} { + idebug trace [incr level -1] $level 0 VERBOSE + } + } + . { set c [catch {idebug trace $level $level 0 VERBOSE} res] } + v { set c [catch {idebug show vars $lvl } res] } + V { set c [catch {idebug show vars $lvl VERBOSE} res] } + l { set c [catch {idebug show locals $lvl } res] } + L { set c [catch {idebug show locals $lvl VERBOSE} res] } + g { set c [catch {idebug show globals $lvl } res] } + G { set c [catch {idebug show globals $lvl VERBOSE} res] } + t { set c [catch {idebug trace 1 $max $level } res] } + T { set c [catch {idebug trace 1 $max $level VERBOSE} res]} + b { set c [catch {idebug body $lvl} res] } + o { set res [set IDEBUG(on) [expr {!$IDEBUG(on)}]] } + h - ? { + puts stderr " + Move down in call stack + - Move up in call stack + . Show current proc name and params + + v Show names of variables currently in scope + V Show names of variables currently in scope with values + l Show names of local (transient) variables + L Show names of local (transient) variables with values + g Show names of declared global variables + G Show names of declared global variables with values + t Show a stack trace + T Show a verbose stack trace + + b Show body of current proc + o Toggle on/off any further debugging + c,q Continue regular execution (Quit debugger) + h,? Print this help + default Evaluate line at current level (\#$level)" + } + c - q break + default { set c [catch {uplevel \#$level $line} res] } + } + if {$tkcon} { + tkcon set ::tkcon::PRIV(event) \ + [tkcon evalSlave eval history add [list $line]\ + \; history nextid] + } + if {$c} { + puts stderr $res + } elseif {[string compare {} $res]} { + puts $res + } + } + set IDEBUG(debugging) 0 + if {$tkcon} { + tkcon master interp delete debugger + tkcon master eval set ::tkcon::OPT(prompt1) \$::tkcon::OPT(prompt2) + tkcon set ::tkcon::OPT(exec) $slave + tkcon set ::tkcon::PRIV(event) $event + tkcon prompt + } + } + bo* { + if {[regexp {^([#-]?[0-9]+)} $args level]} { + return [uplevel $level {dump c -no [lindex [info level 0] 0]}] + } + } + t* { + if {[llength $args]<2} return + set min [set max [set lvl $level]] + set exp {^#?([0-9]+)? ?#?([0-9]+) ?#?([0-9]+)? ?(VERBOSE)?} + if {![regexp $exp $args junk min max lvl verbose]} return + for {set i $max} { + $i>=$min && ![catch {uplevel \#$i info level 0} info] + } {incr i -1} { + if {$i==$lvl} { + puts -nonewline stderr "* \#$i:\t" + } else { + puts -nonewline stderr " \#$i:\t" + } + set name [lindex $info 0] + if {[string compare VERBOSE $verbose] || \ + ![llength [info procs $name]]} { + puts $info + } else { + puts "proc $name {[info args $name]} { ... }" + set idx 0 + foreach arg [info args $name] { + if {[string match args $arg]} { + puts "\t$arg = [lrange $info [incr idx] end]" + break + } else { + puts "\t$arg = [lindex $info [incr idx]]" + } + } + } + } + } + s* { + #var, local, global + set level \#$level + if {![regexp {^([vgl][^ ]*) ?([#-]?[0-9]+)? ?(VERBOSE)?} \ + $args junk type level verbose]} return + switch -glob -- $type { + v* { set vars [uplevel $level {lsort [info vars]}] } + l* { set vars [uplevel $level {lsort [info locals]}] } + g* { set vars [lremove [uplevel $level {info vars}] \ + [uplevel $level {info locals}]] } + } + if {[string match VERBOSE $verbose]} { + return [uplevel $level dump var -nocomplain $vars] + } else { + return $vars + } + } + e* - pu* { + if {[llength $opt]==1 && [catch {lindex [info level -1] 0} id]} { + set id [lindex [info level 0] 0] + } else { + set id [lindex $opt 1] + } + if {$IDEBUG(on) && [string match $IDEBUG(id) $id]} { + if {[string match e* $opt]} { + puts [concat $args] + } else { eval puts $args } + } + } + default { + return -code error "bad [lindex [info level 0] 0] option \"$opt\",\ + must be: [join [lsort [list on off id break print body\ + trace show puts echo]] {, }]" + } + } +} + +## observe - like trace, but not +# ARGS: opt - option +# name - name of variable or command +## +proc observe {opt name args} { + global tcl_observe + switch -glob -- $opt { + co* { + if {[regexp {^(catch|lreplace|set|puts|for|incr|info|uplevel)$} \ + $name]} { + return -code error "cannot observe \"$name\":\ + infinite eval loop will occur" + } + set old ${name}@ + while {[llength [info command $old]]} { append old @ } + rename $name $old + set max 4 + regexp {^[0-9]+} $args max + ## idebug trace could be used here + proc $name args " + for {set i \[info level\]; set max \[expr \[info level\]-$max\]} { + \$i>=\$max && !\[catch {uplevel \#\$i info level 0} info\] + } {incr i -1} { + puts -nonewline stderr \" \#\$i:\t\" + puts \$info + } + uplevel \[lreplace \[info level 0\] 0 0 $old\] + " + set tcl_observe($name) $old + } + cd* { + if {[info exists tcl_observe($name)] && [catch { + rename $name {} + rename $tcl_observe($name) $name + unset tcl_observe($name) + } err]} { return -code error $err } + } + ci* { + ## What a useless method... + if {[info exists tcl_observe($name)]} { + set i $tcl_observe($name) + set res "\"$name\" observes true command \"$i\"" + while {[info exists tcl_observe($i)]} { + append res "\n\"$name\" observes true command \"$i\"" + set i $tcl_observe($name) + } + return $res + } + } + va* - vd* { + set type [lindex $args 0] + set args [lrange $args 1 end] + if {![regexp {^[rwu]} $type type]} { + return -code error "bad [lindex [info level 0] 0] $opt type\ + \"$type\", must be: read, write or unset" + } + if {![llength $args]} { set args observe_var } + uplevel 1 [list trace $opt $name $type $args] + } + vi* { + uplevel 1 [list trace vinfo $name] + } + default { + return -code error "bad [lindex [info level 0] 0] option\ + \"[lindex $args 0]\", must be: [join [lsort \ + [list command cdelete cinfo variable vdelete vinfo]] {, }]" + } + } +} + +## observe_var - auxilary function for observing vars, called by trace +## via observe +# ARGS: name - variable name +# el - array element name, if any +# op - operation type (rwu) +## +proc observe_var {name el op} { + if {[string match u $op]} { + if {[string compare {} $el]} { + puts "unset \"${name}($el)\"" + } else { + puts "unset \"$name\"" + } + } else { + upvar 1 $name $name + if {[info exists ${name}($el)]} { + puts [dump v ${name}($el)] + } else { + puts [dump v $name] + } + } +} + +## which - tells you where a command is found +# ARGS: cmd - command name +# Returns: where command is found (internal / external / unknown) +## +proc which cmd { + ## This tries to auto-load a command if not recognized + set types [uplevel 1 [list what $cmd 1]] + if {[llength $types]} { + set out {} + + foreach type $types { + switch -- $type { + alias { set res "$cmd: aliased to [alias $cmd]" } + procedure { set res "$cmd: procedure" } + command { set res "$cmd: internal command" } + executable { lappend out [auto_execok $cmd] } + variable { lappend out "$cmd: $type" } + } + if {[info exists res]} { + global auto_index + if {[info exists auto_index($cmd)]} { + ## This tells you where the command MIGHT have come from - + ## not true if the command was redefined interactively or + ## existed before it had to be auto_loaded. This is just + ## provided as a hint at where it MAY have come from + append res " ($auto_index($cmd))" + } + lappend out $res + unset res + } + } + return [join $out \n] + } else { + return -code error "$cmd: command not found" + } +} + +## what - tells you what a string is recognized as +# ARGS: str - string to id +# Returns: id types of command as list +## +proc what {str {autoload 0}} { + set types {} + if {[llength [info commands $str]] || ($autoload && \ + [auto_load $str] && [llength [info commands $str]])} { + if {[lsearch -exact [interp aliases] $str] > -1} { + lappend types "alias" + } elseif { + [llength [info procs $str]] || + ([string match *::* $str] && + [llength [namespace eval [namespace qualifier $str] \ + info procs [namespace tail $str]]]) + } { + lappend types "procedure" + } else { + lappend types "command" + } + } + if {[llength [uplevel 1 info vars $str]]} { + upvar 1 $str var + if {[array exists var]} { + lappend types array variable + } else { + lappend types scalar variable + } + } + if {[file isdirectory $str]} { + lappend types "directory" + } + if {[file isfile $str]} { + lappend types "file" + } + if {[llength [info commands winfo]] && [winfo exists $str]} { + lappend types "widget" + } + if {[string compare {} [auto_execok $str]]} { + lappend types "executable" + } + return $types +} + +## dir - directory list +# ARGS: args - names/glob patterns of directories to list +# OPTS: -all - list hidden files as well (Unix dot files) +# -long - list in full format "permissions size date filename" +# -full - displays / after directories and link paths for links +# Returns: a directory listing +## +proc dir {args} { + array set s { + all 0 full 0 long 0 + 0 --- 1 --x 2 -w- 3 -wx 4 r-- 5 r-x 6 rw- 7 rwx + } + while {[string match \-* [lindex $args 0]]} { + set str [lindex $args 0] + set args [lreplace $args 0 0] + switch -glob -- $str { + -a* {set s(all) 1} -f* {set s(full) 1} + -l* {set s(long) 1} -- break + default { + return -code error "unknown option \"$str\",\ + should be one of: -all, -full, -long" + } + } + } + set sep [string trim [file join . .] .] + if {![llength $args]} { set args . } + if {$::tcl_version >= 8.3} { + # Newer glob args allow safer dir processing. The user may still + # want glob chars, but really only for file matching. + foreach arg $args { + if {[file isdirectory $arg]} { + if {$s(all)} { + lappend out [list $arg [lsort \ + [glob -nocomplain -directory $arg .* *]]] + } else { + lappend out [list $arg [lsort \ + [glob -nocomplain -directory $arg *]]] + } + } else { + set dir [file dirname $arg] + lappend out [list $dir$sep [lsort \ + [glob -nocomplain -directory $dir [file tail $arg]]]] + } + } + } else { + foreach arg $args { + if {[file isdirectory $arg]} { + set arg [string trimright $arg $sep]$sep + if {$s(all)} { + lappend out [list $arg [lsort [glob -nocomplain -- $arg.* $arg*]]] + } else { + lappend out [list $arg [lsort [glob -nocomplain -- $arg*]]] + } + } else { + lappend out [list [file dirname $arg]$sep \ + [lsort [glob -nocomplain -- $arg]]] + } + } + } + if {$s(long)} { + set old [clock scan {1 year ago}] + set fmt "%s%9d %s %s\n" + foreach o $out { + set d [lindex $o 0] + append res $d:\n + foreach f [lindex $o 1] { + file lstat $f st + set f [file tail $f] + if {$s(full)} { + switch -glob $st(type) { + d* { append f $sep } + l* { append f "@ -> [file readlink $d$sep$f]" } + default { if {[file exec $d$sep$f]} { append f * } } + } + } + if {[string match file $st(type)]} { + set mode - + } else { + set mode [string index $st(type) 0] + } + foreach j [split [format %03o [expr {$st(mode)&0777}]] {}] { + append mode $s($j) + } + if {$st(mtime)>$old} { + set cfmt {%b %d %H:%M} + } else { + set cfmt {%b %d %Y} + } + append res [format $fmt $mode $st(size) \ + [clock format $st(mtime) -format $cfmt] $f] + } + append res \n + } + } else { + foreach o $out { + set d [lindex $o 0] + append res "$d:\n" + set i 0 + foreach f [lindex $o 1] { + if {[string len [file tail $f]] > $i} { + set i [string len [file tail $f]] + } + } + set i [expr {$i+2+$s(full)}] + set j 80 + ## This gets the number of cols in the tkcon console widget + if {[llength [info commands tkcon]]} { + set j [expr {[tkcon master set ::tkcon::OPT(cols)]/$i}] + } + set k 0 + foreach f [lindex $o 1] { + set f [file tail $f] + if {$s(full)} { + switch -glob [file type $d$sep$f] { + d* { append f $sep } + l* { append f @ } + default { if {[file exec $d$sep$f]} { append f * } } + } + } + append res [format "%-${i}s" $f] + if {$j == 0 || [incr k]%$j == 0} { + set res [string trimright $res]\n + } + } + append res \n\n + } + } + return [string trimright $res] +} +interp alias {} ::ls {} ::dir -full + +## lremove - remove items from a list +# OPTS: +# -all remove all instances of each item +# -glob remove all instances matching glob pattern +# -regexp remove all instances matching regexp pattern +# ARGS: l a list to remove items from +# args items to remove (these are 'join'ed together) +## +proc lremove {args} { + array set opts {-all 0 pattern -exact} + while {[string match -* [lindex $args 0]]} { + switch -glob -- [lindex $args 0] { + -a* { set opts(-all) 1 } + -g* { set opts(pattern) -glob } + -r* { set opts(pattern) -regexp } + -- { set args [lreplace $args 0 0]; break } + default {return -code error "unknown option \"[lindex $args 0]\""} + } + set args [lreplace $args 0 0] + } + set l [lindex $args 0] + foreach i [join [lreplace $args 0 0]] { + if {[set ix [lsearch $opts(pattern) $l $i]] == -1} continue + set l [lreplace $l $ix $ix] + if {$opts(-all)} { + while {[set ix [lsearch $opts(pattern) $l $i]] != -1} { + set l [lreplace $l $ix $ix] + } + } + } + return $l +} + +if {!$::tkcon::PRIV(WWW)} {; + +## Unknown changed to get output into tkcon window +# unknown: +# Invoked automatically whenever an unknown command is encountered. +# Works through a list of "unknown handlers" that have been registered +# to deal with unknown commands. Extensions can integrate their own +# handlers into the 'unknown' facility via 'unknown_handler'. +# +# If a handler exists that recognizes the command, then it will +# take care of the command action and return a valid result or a +# Tcl error. Otherwise, it should return "-code continue" (=2) +# and responsibility for the command is passed to the next handler. +# +# Arguments: +# args - A list whose elements are the words of the original +# command, including the command name. + +proc unknown args { + global unknown_handler_order unknown_handlers errorInfo errorCode + + # + # Be careful to save error info now, and restore it later + # for each handler. Some handlers generate their own errors + # and disrupt handling. + # + set savedErrorCode $errorCode + set savedErrorInfo $errorInfo + + if {![info exists unknown_handler_order] || \ + ![info exists unknown_handlers]} { + set unknown_handlers(tcl) tcl_unknown + set unknown_handler_order tcl + } + + foreach handler $unknown_handler_order { + set status [catch {uplevel 1 $unknown_handlers($handler) $args} result] + + if {$status == 1} { + # + # Strip the last five lines off the error stack (they're + # from the "uplevel" command). + # + set new [split $errorInfo \n] + set new [join [lrange $new 0 [expr {[llength $new]-6}]] \n] + return -code $status -errorcode $errorCode \ + -errorinfo $new $result + + } elseif {$status != 4} { + return -code $status $result + } + + set errorCode $savedErrorCode + set errorInfo $savedErrorInfo + } + + set name [lindex $args 0] + return -code error "invalid command name \"$name\"" +} + +# tcl_unknown: +# Invoked when a Tcl command is invoked that doesn't exist in the +# interpreter: +# +# 1. See if the autoload facility can locate the command in a +# Tcl script file. If so, load it and execute it. +# 2. If the command was invoked interactively at top-level: +# (a) see if the command exists as an executable UNIX program. +# If so, "exec" the command. +# (b) see if the command requests csh-like history substitution +# in one of the common forms !!, !, or ^old^new. If +# so, emulate csh's history substitution. +# (c) see if the command is a unique abbreviation for another +# command. If so, invoke the command. +# +# Arguments: +# args - A list whose elements are the words of the original +# command, including the command name. + +proc tcl_unknown args { + global auto_noexec auto_noload env unknown_pending tcl_interactive + global errorCode errorInfo + + # If the command word has the form "namespace inscope ns cmd" + # then concatenate its arguments onto the end and evaluate it. + + set cmd [lindex $args 0] + if {[regexp "^namespace\[ \t\n\]+inscope" $cmd] && [llength $cmd] == 4} { + set arglist [lrange $args 1 end] + set ret [catch {uplevel 1 $cmd $arglist} result] + if {$ret == 0} { + return $result + } else { + return -code $ret -errorcode $errorCode $result + } + } + + # CAD tools special: + # Check for commands which were renamed to tcl_(command) + + if {[lsearch [info commands] tcl_$cmd] >= 0} { + set arglist [concat tcl_$cmd [lrange $args 1 end]] + set ret [catch {eval $arglist} result] + if {$ret == 0} { + return $result + } else { + return -code $ret -errorcode $errorCode $result + } + } + + # Save the values of errorCode and errorInfo variables, since they + # may get modified if caught errors occur below. The variables will + # be restored just before re-executing the missing command. + + set savedErrorCode $errorCode + set savedErrorInfo $errorInfo + set name [lindex $args 0] + if {![info exists auto_noload]} { + # + # Make sure we're not trying to load the same proc twice. + # + if {[info exists unknown_pending($name)]} { + return -code error "self-referential recursion in \"unknown\" for command \"$name\"" + } + set unknown_pending($name) pending + if {[llength [info args auto_load]]==1} { + set ret [catch {auto_load $name} msg] + } else { + set ret [catch {auto_load $name [uplevel 1 {namespace current}]} msg] + } + unset unknown_pending($name) + if {$ret} { + return -code $ret -errorcode $errorCode \ + "error while autoloading \"$name\": $msg" + } + # + # Avoid problems with renaming "array"! (for tcl-based magic only) + # + set arraycmd array + if {[lsearch [info commands] tcl_array] >= 0} {set arraycmd tcl_array} + + if {![$arraycmd size unknown_pending]} { unset unknown_pending } + if {$msg} { + set errorCode $savedErrorCode + set errorInfo $savedErrorInfo + set code [catch {uplevel 1 $args} msg] + if {$code == 1} { + # + # Strip the last five lines off the error stack (they're + # from the "uplevel" command). + # + + set new [split $errorInfo \n] + set new [join [lrange $new 0 [expr {[llength $new]-6}]] \n] + return -code error -errorcode $errorCode \ + -errorinfo $new $msg + } else { + return -code $code $msg + } + } + } + if {[info level] == 1 && [string match {} [info script]] \ + && [info exists tcl_interactive] && $tcl_interactive} { + if {![info exists auto_noexec]} { + set new [auto_execok $name] + if {[string compare {} $new]} { + set errorCode $savedErrorCode + set errorInfo $savedErrorInfo + return [uplevel 1 exec $new [lrange $args 1 end]] + #return [uplevel exec >&@stdout <@stdin $new [lrange $args 1 end]] + } + } + set errorCode $savedErrorCode + set errorInfo $savedErrorInfo + ## + ## History substitution moved into ::tkcon::EvalCmd + ## + set ret [catch {set cmds [info commands $name*]} msg] + if {[string compare $name "::"] == 0} { + set name "" + } + if {$ret != 0} { + return -code $ret -errorcode $errorCode \ + "error in unknown while checking if \"$name\" is a unique command abbreviation: $msg" + } + set cmds [info commands $name*] + if {[llength $cmds] == 1} { + return [uplevel 1 [lreplace $args 0 0 $cmds]] + } + if {[llength $cmds]} { + if {$name == ""} { + return -code error "empty command name \"\"" + } else { + return -code error \ + "ambiguous command name \"$name\": [lsort $cmds]" + } + } + ## We've got nothing so far + ## Check and see if Tk wasn't loaded, but it appears to be a Tk cmd + if {![uplevel \#0 info exists tk_version]} { + lappend tkcmds bell bind bindtags button \ + canvas checkbutton clipboard destroy \ + entry event focus font frame grab grid image \ + label listbox lower menu menubutton message \ + option pack place radiobutton raise \ + scale scrollbar selection send spinbox \ + text tk tkwait toplevel winfo wm + if {[lsearch -exact $tkcmds $name] >= 0 && \ + [tkcon master tk_messageBox -icon question -parent . \ + -title "Load Tk?" -type retrycancel -default retry \ + -message "This appears to be a Tk command, but Tk\ + has not yet been loaded. Shall I retry the command\ + with loading Tk first?"] == "retry"} { + return [uplevel 1 "load {} Tk; $args"] + } + } + } + return -code continue +} + +} ; # end exclusionary code for WWW + +proc ::tkcon::Bindings {} { + variable PRIV + global tcl_platform tk_version + + #----------------------------------------------------------------------- + # Elements of tkPriv that are used in this file: + # + # char - Character position on the line; kept in order + # to allow moving up or down past short lines while + # still remembering the desired position. + # mouseMoved - Non-zero means the mouse has moved a significant + # amount since the button went down (so, for example, + # start dragging out a selection). + # prevPos - Used when moving up or down lines via the keyboard. + # Keeps track of the previous insert position, so + # we can distinguish a series of ups and downs, all + # in a row, from a new up or down. + # selectMode - The style of selection currently underway: + # char, word, or line. + # x, y - Last known mouse coordinates for scanning + # and auto-scanning. + #----------------------------------------------------------------------- + + switch -glob $tcl_platform(platform) { + win* { set PRIV(meta) Alt } + mac* { set PRIV(meta) Command } + default { set PRIV(meta) Meta } + } + + ## Get all Text bindings into TkConsole + foreach ev [bind Text] { bind TkConsole $ev [bind Text $ev] } + ## We really didn't want the newline insertion + bind TkConsole {} + + ## in 8.6b3, the virtual events <> and <> + # mess up our history feature + bind TkConsole <> {} + bind TkConsole <> {} + + ## Now make all our virtual event bindings + foreach {ev key} [subst -nocommand -noback { + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> <$PRIV(meta)-i> + <> + <> <$PRIV(meta)-o> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + <> + }] { + event add $ev $key + ## Make sure the specific key won't be defined + bind TkConsole $key {} + } + + ## Make the ROOT bindings + bind $PRIV(root) <> exit + bind $PRIV(root) <> { ::tkcon::New } + bind $PRIV(root) <> { ::tkcon::Destroy } + bind $PRIV(root) <> { ::tkcon::About } + bind $PRIV(root) <> { ::tkcon::Help } + bind $PRIV(root) <> { ::tkcon::FindBox $::tkcon::PRIV(console) } + bind $PRIV(root) <> { + ::tkcon::Attach {} + ::tkcon::Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)] + } + bind $PRIV(root) <> { + if {[string compare {} $::tkcon::PRIV(name)]} { + ::tkcon::Attach $::tkcon::PRIV(name) + } else { + ::tkcon::Attach Main + } + ::tkcon::Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)] + } + bind $PRIV(root) <> { + ::tkcon::Attach Main + ::tkcon::Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)] + } + bind $PRIV(root) <> { + ::tkcon::PopupMenu %X %Y + } + + ## Menu items need null TkConsolePost bindings to avoid the TagProc + ## + foreach ev [bind $PRIV(root)] { + bind TkConsolePost $ev { + # empty + } + } + + + # ::tkcon::ClipboardKeysyms -- + # This procedure is invoked to identify the keys that correspond to + # the copy, cut, and paste functions for the clipboard. + # + # Arguments: + # copy - Name of the key (keysym name plus modifiers, if any, + # such as "Meta-y") used for the copy operation. + # cut - Name of the key used for the cut operation. + # paste - Name of the key used for the paste operation. + + proc ::tkcon::ClipboardKeysyms {copy cut paste} { + bind TkConsole <$copy> {::tkcon::Copy %W} + bind TkConsole <$cut> {::tkcon::Cut %W} + bind TkConsole <$paste> {::tkcon::Paste %W} + } + + proc ::tkcon::GetSelection {w} { + if { + ![catch {selection get -displayof $w -type UTF8_STRING} txt] || + ![catch {selection get -displayof $w} txt] || + ![catch {selection get -displayof $w -selection CLIPBOARD} txt] + } { + return $txt + } + return -code error "could not find default selection" + } + + proc ::tkcon::Cut w { + if {[string match $w [selection own -displayof $w]]} { + clipboard clear -displayof $w + catch { + set txt [selection get -displayof $w] + clipboard append -displayof $w $txt + if {[$w compare sel.first >= limit]} { + $w delete sel.first sel.last + } + } + } + } + proc ::tkcon::Copy w { + if {[string match $w [selection own -displayof $w]]} { + clipboard clear -displayof $w + catch { + set txt [selection get -displayof $w] + clipboard append -displayof $w $txt + } + } + } + proc ::tkcon::Paste w { + if {![catch {GetSelection $w} txt]} { + if {[$w compare insert < limit]} { $w mark set insert end } + $w insert insert $txt + $w see insert + if {[string match *\n* $txt]} { ::tkcon::Eval $w } + } + } + + ## Redefine for TkConsole what we need + ## + event delete <> + ::tkcon::ClipboardKeysyms + + bind TkConsole { + catch { ::tkcon::Insert %W [::tkcon::GetSelection %W] } + } + + bind TkConsole {+ + catch { + eval %W tag remove sel [%W tag nextrange prompt sel.first sel.last] + eval %W tag remove sel sel.last-1c + %W mark set insert sel.first + } + } + + ## binding editor needed + ## binding for .tkconrc + + bind TkConsole <> { + if {[%W compare insert > limit]} {::tkcon::Expand %W path} + break + } + bind TkConsole <> { + if {[%W compare insert > limit]} {::tkcon::Expand %W proc} + } + bind TkConsole <> { + if {[%W compare insert > limit]} {::tkcon::Expand %W var} + } + bind TkConsole <> { + if {[%W compare insert > limit]} {::tkcon::Expand %W} + } + bind TkConsole <> { + if {[%W compare insert >= limit]} { + ::tkcon::Insert %W \t + } + } + bind TkConsole <> { + if {[%W compare insert >= limit]} { + ::tkcon::Insert %W \n + } + } + bind TkConsole <> { + ::tkcon::Eval %W + } + bind TkConsole { + if {[llength [%W tag nextrange sel 1.0 end]] \ + && [%W compare sel.first >= limit]} { + %W delete sel.first sel.last + } elseif {[%W compare insert >= limit]} { + %W delete insert + %W see insert + } + } + bind TkConsole { + if {[llength [%W tag nextrange sel 1.0 end]] \ + && [%W compare sel.first >= limit]} { + %W delete sel.first sel.last + } elseif {[%W compare insert != 1.0] && [%W compare insert > limit]} { + %W delete insert-1c + %W see insert + } + } + bind TkConsole [bind TkConsole ] + + bind TkConsole { + ::tkcon::Insert %W %A + } + + bind TkConsole { + if {[%W compare {limit linestart} == {insert linestart}]} { + tkTextSetCursor %W limit + } else { + tkTextSetCursor %W {insert linestart} + } + } + bind TkConsole [bind TkConsole ] + bind TkConsole { + if {[%W compare insert < limit]} break + %W delete insert + } + bind TkConsole { + if {[%W compare insert < limit]} break + if {[%W compare insert == {insert lineend}]} { + %W delete insert + } else { + %W delete insert {insert lineend} + } + } + bind TkConsole <> { + ## Clear console buffer, without losing current command line input + set ::tkcon::PRIV(tmp) [::tkcon::CmdGet %W] + clear + ::tkcon::Prompt {} $::tkcon::PRIV(tmp) + } + bind TkConsole <> { + if {[%W compare {insert linestart} != {limit linestart}]} { + tkTextSetCursor %W [tkTextUpDownLine %W -1] + } else { + ::tkcon::Event -1 + } + } + bind TkConsole <> { + if {[%W compare {insert linestart} != {end-1c linestart}]} { + tkTextSetCursor %W [tkTextUpDownLine %W 1] + } else { + ::tkcon::Event 1 + } + } + bind TkConsole <> { ::tkcon::Event 1 } + bind TkConsole <> { ::tkcon::Event -1 } + bind TkConsole <> { + ::tkcon::Event -1 [::tkcon::CmdGet %W] + } + bind TkConsole <> { + ::tkcon::Event 1 [::tkcon::CmdGet %W] + } + bind TkConsole <> { + ## Transpose current and previous chars + if {[%W compare insert > "limit+1c"]} { tkTextTranspose %W } + } + bind TkConsole <> { + ## Clear command line (Unix shell staple) + %W delete limit end + } + bind TkConsole <> { + ## Save command buffer (swaps with current command) + set ::tkcon::PRIV(tmp) $::tkcon::PRIV(cmdsave) + set ::tkcon::PRIV(cmdsave) [::tkcon::CmdGet %W] + if {[string match {} $::tkcon::PRIV(cmdsave)]} { + set ::tkcon::PRIV(cmdsave) $::tkcon::PRIV(tmp) + } else { + %W delete limit end-1c + } + ::tkcon::Insert %W $::tkcon::PRIV(tmp) + %W see end + } + catch {bind TkConsole { tkTextScrollPages %W -1 }} + catch {bind TkConsole { tkTextScrollPages %W -1 }} + catch {bind TkConsole { tkTextScrollPages %W 1 }} + catch {bind TkConsole { tkTextScrollPages %W 1 }} + bind TkConsole <$PRIV(meta)-d> { + if {[%W compare insert >= limit]} { + %W delete insert {insert wordend} + } + } + bind TkConsole <$PRIV(meta)-BackSpace> { + if {[%W compare {insert -1c wordstart} >= limit]} { + %W delete {insert -1c wordstart} insert + } + } + bind TkConsole <$PRIV(meta)-Delete> { + if {[%W compare insert >= limit]} { + %W delete insert {insert wordend} + } + } + bind TkConsole { + if { + (!$tkPriv(mouseMoved) || $tk_strictMotif) && + ![catch {::tkcon::GetSelection %W} ::tkcon::PRIV(tmp)] + } { + if {[%W compare @%x,%y < limit]} { + %W insert end $::tkcon::PRIV(tmp) + } else { + %W insert @%x,%y $::tkcon::PRIV(tmp) + } + if {[string match *\n* $::tkcon::PRIV(tmp)]} {::tkcon::Eval %W} + } + } + + ## + ## End TkConsole bindings + ## + + ## + ## Bindings for doing special things based on certain keys + ## + bind TkConsolePost { + if {$::tkcon::OPT(lightbrace) && $::tkcon::OPT(blinktime)>99 && \ + [string compare \\ [%W get insert-2c]]} { + ::tkcon::MatchPair %W \( \) limit + } + set ::tkcon::PRIV(StatusCursor) [%W index insert] + } + bind TkConsolePost { + if {$::tkcon::OPT(lightbrace) && $::tkcon::OPT(blinktime)>99 && \ + [string compare \\ [%W get insert-2c]]} { + ::tkcon::MatchPair %W \[ \] limit + } + set ::tkcon::PRIV(StatusCursor) [%W index insert] + } + bind TkConsolePost { + if {$::tkcon::OPT(lightbrace) && $::tkcon::OPT(blinktime)>99 && \ + [string compare \\ [%W get insert-2c]]} { + ::tkcon::MatchPair %W \{ \} limit + } + set ::tkcon::PRIV(StatusCursor) [%W index insert] + } + bind TkConsolePost { + if {$::tkcon::OPT(lightbrace) && $::tkcon::OPT(blinktime)>99 && \ + [string compare \\ [%W get insert-2c]]} { + ::tkcon::MatchQuote %W limit + } + set ::tkcon::PRIV(StatusCursor) [%W index insert] + } + + bind TkConsolePost { + if {$::tkcon::OPT(lightcmd) && [string compare {} %A]} { + ::tkcon::TagProc %W + } + set ::tkcon::PRIV(StatusCursor) [%W index insert] + } + + bind TkConsolePost { + set ::tkcon::PRIV(StatusCursor) [%W index insert] + } + bind TkConsolePost { + set ::tkcon::PRIV(StatusCursor) [%W index insert] + } + +} + +## +# ::tkcon::PopupMenu - what to do when the popup menu is requested +## +proc ::tkcon::PopupMenu {X Y} { + variable PRIV + + set w $PRIV(console) + if {[string compare $w [winfo containing $X $Y]]} { + tk_popup $PRIV(popup) $X $Y + return + } + set x [expr {$X-[winfo rootx $w]}] + set y [expr {$Y-[winfo rooty $w]}] + if {[llength [set tags [$w tag names @$x,$y]]]} { + if {[lsearch -exact $tags "proc"] >= 0} { + lappend type "proc" + foreach {first last} [$w tag prevrange proc @$x,$y] { + set word [$w get $first $last]; break + } + } + if {[lsearch -exact $tags "var"] >= 0} { + lappend type "var" + foreach {first last} [$w tag prevrange var @$x,$y] { + set word [$w get $first $last]; break + } + } + } + if {![info exists type]} { + set exp "(^|\[^\\\\\]\[ \t\n\r\])" + set exp2 "\[\[\\\\\\?\\*\]" + set i [$w search -backwards -regexp $exp @$x,$y "@$x,$y linestart"] + if {[string compare {} $i]} { + if {![string match *.0 $i]} {append i +2c} + if {[string compare {} \ + [set j [$w search -regexp $exp $i "$i lineend"]]]} { + append j +1c + } else { + set j "$i lineend" + } + regsub -all $exp2 [$w get $i $j] {\\\0} word + set word [string trim $word {\"$[]{}',?#*}] + if {[llength [EvalAttached [list info commands $word]]]} { + lappend type "proc" + } + if {[llength [EvalAttached [list info vars $word]]]} { + lappend type "var" + } + if {[EvalAttached [list file isfile $word]]} { + lappend type "file" + } + } + } + if {![info exists type] || ![info exists word]} { + tk_popup $PRIV(popup) $X $Y + return + } + $PRIV(context) delete 0 end + $PRIV(context) add command -label "$word" -state disabled + $PRIV(context) add separator + set app [Attach] + if {[lsearch $type proc] != -1} { + $PRIV(context) add command -label "View Procedure" \ + -command [list edit -attach $app -type proc -- $word] + } + if {[lsearch $type var] != -1} { + $PRIV(context) add command -label "View Variable" \ + -command [list edit -attach $app -type var -- $word] + } + if {[lsearch $type file] != -1} { + $PRIV(context) add command -label "View File" \ + -command [list edit -attach $app -type file -- $word] + } + tk_popup $PRIV(context) $X $Y +} + +## ::tkcon::TagProc - tags a procedure in the console if it's recognized +## This procedure is not perfect. However, making it perfect wastes +## too much CPU time... +## +proc ::tkcon::TagProc w { + set exp "\[^\\\\\]\[\[ \t\n\r\;{}\"\$\]" + set i [$w search -backwards -regexp $exp insert-1c limit-1c] + if {[string compare {} $i]} {append i +2c} else {set i limit} + regsub -all "\[\[\\\\\\?\\*\]" [$w get $i "insert-1c wordend"] {\\\0} c + if {[llength [EvalAttached [list info commands $c]]]} { + $w tag add proc $i "insert-1c wordend" + } else { + $w tag remove proc $i "insert-1c wordend" + } + if {[llength [EvalAttached [list info vars $c]]]} { + $w tag add var $i "insert-1c wordend" + } else { + $w tag remove var $i "insert-1c wordend" + } +} + +## ::tkcon::MatchPair - blinks a matching pair of characters +## c2 is assumed to be at the text index 'insert'. +## This proc is really loopy and took me an hour to figure out given +## all possible combinations with escaping except for escaped \'s. +## It doesn't take into account possible commenting... Oh well. If +## anyone has something better, I'd like to see/use it. This is really +## only efficient for small contexts. +# ARGS: w - console text widget +# c1 - first char of pair +# c2 - second char of pair +# Calls: ::tkcon::Blink +## +proc ::tkcon::MatchPair {w c1 c2 {lim 1.0}} { + if {[string compare {} [set ix [$w search -back $c1 insert $lim]]]} { + while { + [string match {\\} [$w get $ix-1c]] && + [string compare {} [set ix [$w search -back $c1 $ix-1c $lim]]] + } {} + set i1 insert-1c + while {[string compare {} $ix]} { + set i0 $ix + set j 0 + while {[string compare {} [set i0 [$w search $c2 $i0 $i1]]]} { + append i0 +1c + if {[string match {\\} [$w get $i0-2c]]} continue + incr j + } + if {!$j} break + set i1 $ix + while {$j && [string compare {} \ + [set ix [$w search -back $c1 $ix $lim]]]} { + if {[string match {\\} [$w get $ix-1c]]} continue + incr j -1 + } + } + if {[string match {} $ix]} { set ix [$w index $lim] } + } else { set ix [$w index $lim] } + if {$::tkcon::OPT(blinkrange)} { + Blink $w $ix [$w index insert] + } else { + Blink $w $ix $ix+1c [$w index insert-1c] [$w index insert] + } +} + +## ::tkcon::MatchQuote - blinks between matching quotes. +## Blinks just the quote if it's unmatched, otherwise blinks quoted string +## The quote to match is assumed to be at the text index 'insert'. +# ARGS: w - console text widget +# Calls: ::tkcon::Blink +## +proc ::tkcon::MatchQuote {w {lim 1.0}} { + set i insert-1c + set j 0 + while {[string compare [set i [$w search -back \" $i $lim]] {}]} { + if {[string match {\\} [$w get $i-1c]]} continue + if {!$j} {set i0 $i} + incr j + } + if {$j&1} { + if {$::tkcon::OPT(blinkrange)} { + Blink $w $i0 [$w index insert] + } else { + Blink $w $i0 $i0+1c [$w index insert-1c] [$w index insert] + } + } else { + Blink $w [$w index insert-1c] [$w index insert] + } +} + +## ::tkcon::Blink - blinks between n index pairs for a specified duration. +# ARGS: w - console text widget +# i1 - start index to blink region +# i2 - end index of blink region +# dur - duration in usecs to blink for +# Outputs: blinks selected characters in $w +## +proc ::tkcon::Blink {w args} { + eval [list $w tag add blink] $args + after $::tkcon::OPT(blinktime) [list $w] tag remove blink $args + return +} + + +## ::tkcon::Insert +## Insert a string into a text console at the point of the insertion cursor. +## If there is a selection in the text, and it covers the point of the +## insertion cursor, then delete the selection before inserting. +# ARGS: w - text window in which to insert the string +# s - string to insert (usually just a single char) +# Outputs: $s to text widget +## +proc ::tkcon::Insert {w s} { + if {[string match {} $s] || [string match disabled [$w cget -state]]} { + return + } + if {[$w comp insert < limit]} { + $w mark set insert end + } + if {[llength [$w tag ranges sel]] && \ + [$w comp sel.first <= insert] && [$w comp sel.last >= insert]} { + $w delete sel.first sel.last + } + $w insert insert $s + $w see insert +} + +## ::tkcon::Expand - +# ARGS: w - text widget in which to expand str +# type - type of expansion (path / proc / variable) +# Calls: ::tkcon::Expand(Pathname|Procname|Variable) +# Outputs: The string to match is expanded to the longest possible match. +# If ::tkcon::OPT(showmultiple) is non-zero and the user longest +# match equaled the string to expand, then all possible matches +# are output to stdout. Triggers bell if no matches are found. +# Returns: number of matches found +## +proc ::tkcon::Expand {w {type ""}} { + set exp "\[^\\\\\]\[\[ \t\n\r\\\{\"$\]" + set tmp [$w search -backwards -regexp $exp insert-1c limit-1c] + if {[string compare {} $tmp]} {append tmp +2c} else {set tmp limit} + if {[$w compare $tmp >= insert]} return + set str [$w get $tmp insert] + switch -glob $type { + pa* { set res [ExpandPathname $str] } + pr* { set res [ExpandProcname $str] } + v* { set res [ExpandVariable $str] } + default { + set res {} + foreach t $::tkcon::OPT(expandorder) { + if {![catch {Expand$t $str} res] && \ + [string compare {} $res]} break + } + } + } + set len [llength $res] + if {$len} { + $w delete $tmp insert + $w insert $tmp [lindex $res 0] + if {$len > 1} { + if {$::tkcon::OPT(showmultiple) && \ + ![string compare [lindex $res 0] $str]} { + puts stdout [lsort [lreplace $res 0 0]] + } + } + } else { bell } + return [incr len -1] +} + +## ::tkcon::ExpandPathname - expand a file pathname based on $str +## This is based on UNIX file name conventions +# ARGS: str - partial file pathname to expand +# Calls: ::tkcon::ExpandBestMatch +# Returns: list containing longest unique match followed by all the +# possible further matches +## +proc ::tkcon::ExpandPathname str { + set pwd [EvalAttached pwd] + # Cause a string like {C:/Program\ Files/} to become "C:/Program Files/" + regsub -all {\\([][ ])} $str {\1} str + if {[catch {EvalAttached [list cd [file dirname $str]]} err]} { + return -code error $err + } + set dir [file tail $str] + ## Check to see if it was known to be a directory and keep the trailing + ## slash if so (file tail cuts it off) + if {[string match */ $str]} { append dir / } + # Create a safely glob-able name + regsub -all {([][])} $dir {\\\1} safedir + if {[catch {lsort [EvalAttached [list glob $safedir*]]} m]} { + set match {} + } else { + if {[llength $m] > 1} { + global tcl_platform + if {[string match windows $tcl_platform(platform)]} { + ## Windows is screwy because it's case insensitive + set tmp [ExpandBestMatch [string tolower $m] \ + [string tolower $dir]] + ## Don't change case if we haven't changed the word + if {[string length $dir]==[string length $tmp]} { + set tmp $dir + } + } else { + set tmp [ExpandBestMatch $m $dir] + } + if {[string match */* $str]} { + set tmp [string trimright [file dirname $str] /]/$tmp + } + regsub -all {([^\\])([][ ])} $tmp {\1\\\2} tmp + set match [linsert $m 0 $tmp] + } else { + ## This may look goofy, but it handles spaces in path names + eval append match $m + if {[file isdirectory $match]} {append match /} + if {[string match */* $str]} { + set match [string trimright [file dirname $str] /]/$match + } + regsub -all {([^\\])([][ ])} $match {\1\\\2} match + ## Why is this one needed and the ones below aren't!! + set match [list $match] + } + } + EvalAttached [list cd $pwd] + return $match +} + +## ::tkcon::ExpandProcname - expand a tcl proc name based on $str +# ARGS: str - partial proc name to expand +# Calls: ::tkcon::ExpandBestMatch +# Returns: list containing longest unique match followed by all the +# possible further matches +## +proc ::tkcon::ExpandProcname str { + set match [EvalAttached [list info commands $str*]] + if {[llength $match] == 0} { + set ns [EvalAttached \ + "namespace children \[namespace current\] [list $str*]"] + if {[llength $ns]==1} { + set match [EvalAttached [list info commands ${ns}::*]] + } else { + set match $ns + } + } + if {[llength $match] > 1} { + regsub -all {([^\\]) } [ExpandBestMatch $match $str] {\1\\ } str + set match [linsert $match 0 $str] + } else { + regsub -all {([^\\]) } $match {\1\\ } match + } + return $match +} + +## ::tkcon::ExpandVariable - expand a tcl variable name based on $str +# ARGS: str - partial tcl var name to expand +# Calls: ::tkcon::ExpandBestMatch +# Returns: list containing longest unique match followed by all the +# possible further matches +## +proc ::tkcon::ExpandVariable str { + if {[regexp {([^\(]*)\((.*)} $str junk ary str]} { + ## Looks like they're trying to expand an array. + set match [EvalAttached [list array names $ary $str*]] + if {[llength $match] > 1} { + set vars $ary\([ExpandBestMatch $match $str] + foreach var $match {lappend vars $ary\($var\)} + return $vars + } else {set match $ary\($match\)} + ## Space transformation avoided for array names. + } else { + set match [EvalAttached [list info vars $str*]] + if {[llength $match] > 1} { + regsub -all {([^\\]) } [ExpandBestMatch $match $str] {\1\\ } str + set match [linsert $match 0 $str] + } else { + regsub -all {([^\\]) } $match {\1\\ } match + } + } + return $match +} + +## ::tkcon::ExpandBestMatch2 - finds the best unique match in a list of names +## Improves upon the speed of the below proc only when $l is small +## or $e is {}. $e is extra for compatibility with proc below. +# ARGS: l - list to find best unique match in +# Returns: longest unique match in the list +## +proc ::tkcon::ExpandBestMatch2 {l {e {}}} { + set s [lindex $l 0] + if {[llength $l]>1} { + set i [expr {[string length $s]-1}] + foreach l $l { + while {$i>=0 && [string first $s $l]} { + set s [string range $s 0 [incr i -1]] + } + } + } + return $s +} + +## ::tkcon::ExpandBestMatch - finds the best unique match in a list of names +## The extra $e in this argument allows us to limit the innermost loop a +## little further. This improves speed as $l becomes large or $e becomes long. +# ARGS: l - list to find best unique match in +# e - currently best known unique match +# Returns: longest unique match in the list +## +proc ::tkcon::ExpandBestMatch {l {e {}}} { + set ec [lindex $l 0] + if {[llength $l]>1} { + set e [string length $e]; incr e -1 + set ei [string length $ec]; incr ei -1 + foreach l $l { + while {$ei>=$e && [string first $ec $l]} { + set ec [string range $ec 0 [incr ei -1]] + } + } + } + return $ec +} + +# Here is a group of functions that is only used when Tkcon is +# executed in a safe interpreter. It provides safe versions of +# missing functions. For example: +# +# - "tk appname" returns "tkcon.tcl" but cannot be set +# - "toplevel" is equivalent to 'frame', only it is automatically +# packed. +# - The 'source', 'load', 'open', 'file' and 'exit' functions are +# mapped to corresponding functions in the parent interpreter. +# +# Further on, Tk cannot be really loaded. Still the safe 'load' +# provedes a speciall case. The Tk can be divided into 4 groups, +# that each has a safe handling procedure. +# +# - "::tkcon::SafeItem" handles commands like 'button', 'canvas' ...... +# Each of these functions has the window name as first argument. +# - "::tkcon::SafeManage" handles commands like 'pack', 'place', 'grid', +# 'winfo', which can have multiple window names as arguments. +# - "::tkcon::SafeWindow" handles all windows, such as '.'. For every +# window created, a new alias is formed which also is handled by +# this function. +# - Other (e.g. bind, bindtag, image), which need their own function. +# +## These functions courtesy Jan Nijtmans (nijtmans@nici.kun.nl) +## +if {[string compare [info command tk] tk]} { + proc tk {option args} { + if {![string match app* $option]} { + error "wrong option \"$option\": should be appname" + } + return "tkcon.tcl" + } +} + +if {[string compare [info command toplevel] toplevel]} { + proc toplevel {name args} { + eval frame $name $args + pack $name + } +} + +proc ::tkcon::SafeSource {i f} { + set fd [open $f r] + set r [read $fd] + close $fd + if {[catch {interp eval $i $r} msg]} { + error $msg + } +} + +proc ::tkcon::SafeOpen {i f {m r}} { + set fd [open $f $m] + interp transfer {} $fd $i + return $fd +} + +proc ::tkcon::SafeLoad {i f p} { + global tk_version tk_patchLevel tk_library auto_path + if {[string compare $p Tk]} { + load $f $p $i + } else { + foreach command {button canvas checkbutton entry frame label + listbox message radiobutton scale scrollbar spinbox text toplevel} { + $i alias $command ::tkcon::SafeItem $i $command + } + $i alias image ::tkcon::SafeImage $i + foreach command {pack place grid destroy winfo} { + $i alias $command ::tkcon::SafeManage $i $command + } + if {[llength [info command event]]} { + $i alias event ::tkcon::SafeManage $i $command + } + frame .${i}_dot -width 300 -height 300 -relief raised + pack .${i}_dot -side left + $i alias tk tk + $i alias bind ::tkcon::SafeBind $i + $i alias bindtags ::tkcon::SafeBindtags $i + $i alias . ::tkcon::SafeWindow $i {} + foreach var {tk_version tk_patchLevel tk_library auto_path} { + $i eval set $var [list [set $var]] + } + $i eval { + package provide Tk $tk_version + if {[lsearch -exact $auto_path $tk_library] < 0} { + lappend auto_path $tk_library + } + } + return "" + } +} + +proc ::tkcon::SafeSubst {i a} { + set arg1 "" + foreach {arg value} $a { + if {![string compare $arg -textvariable] || + ![string compare $arg -variable]} { + set newvalue "[list $i] $value" + global $newvalue + if {[interp eval $i info exists $value]} { + set $newvalue [interp eval $i set $value] + } else { + catch {unset $newvalue} + } + $i eval trace variable $value rwu \{[list tkcon set $newvalue $i]\} + set value $newvalue + } elseif {![string compare $arg -command]} { + set value [list $i eval $value] + } + lappend arg1 $arg $value + } + return $arg1 +} + +proc ::tkcon::SafeItem {i command w args} { + set args [::tkcon::SafeSubst $i $args] + set code [catch "$command [list .${i}_dot$w] $args" msg] + $i alias $w ::tkcon::SafeWindow $i $w + regsub -all .${i}_dot $msg {} msg + return -code $code $msg +} + +proc ::tkcon::SafeManage {i command args} { + set args1 "" + foreach arg $args { + if {[string match . $arg]} { + set arg .${i}_dot + } elseif {[string match .* $arg]} { + set arg ".${i}_dot$arg" + } + lappend args1 $arg + } + set code [catch "$command $args1" msg] + regsub -all .${i}_dot $msg {} msg + return -code $code $msg +} + +# +# FIX: this function doesn't work yet if the binding starts with '+'. +# +proc ::tkcon::SafeBind {i w args} { + if {[string match . $w]} { + set w .${i}_dot + } elseif {[string match .* $w]} { + set w ".${i}_dot$w" + } + if {[llength $args] > 1} { + set args [list [lindex $args 0] \ + "[list $i] eval [list [lindex $args 1]]"] + } + set code [catch "bind $w $args" msg] + if {[llength $args] <2 && $code == 0} { + set msg [lindex $msg 3] + } + return -code $code $msg +} + +proc ::tkcon::SafeImage {i option args} { + set code [catch "image $option $args" msg] + if {[string match cr* $option]} { + $i alias $msg $msg + } + return -code $code $msg +} + +proc ::tkcon::SafeBindtags {i w {tags {}}} { + if {[string match . $w]} { + set w .${i}_dot + } elseif {[string match .* $w]} { + set w ".${i}_dot$w" + } + set newtags {} + foreach tag $tags { + if {[string match . $tag]} { + lappend newtags .${i}_dot + } elseif {[string match .* $tag]} { + lappend newtags ".${i}_dot$tag" + } else { + lappend newtags $tag + } + } + if {[string match $tags {}]} { + set code [catch {bindtags $w} msg] + regsub -all \\.${i}_dot $msg {} msg + } else { + set code [catch {bindtags $w $newtags} msg] + } + return -code $code $msg +} + +proc ::tkcon::SafeWindow {i w option args} { + if {[string match conf* $option] && [llength $args] > 1} { + set args [::tkcon::SafeSubst $i $args] + } elseif {[string match itemco* $option] && [llength $args] > 2} { + set args "[list [lindex $args 0]] [::tkcon::SafeSubst $i [lrange $args 1 end]]" + } elseif {[string match cr* $option]} { + if {[llength $args]%2} { + set args "[list [lindex $args 0]] [::tkcon::SafeSubst $i [lrange $args 1 end]]" + } else { + set args [::tkcon::SafeSubst $i $args] + } + } elseif {[string match bi* $option] && [llength $args] > 2} { + set args [list [lindex $args 0] [lindex $args 1] "[list $i] eval [list [lindex $args 2]]"] + } + set code [catch ".${i}_dot$w $option $args" msg] + if {$code} { + regsub -all .${i}_dot $msg {} msg + } elseif {[string match conf* $option] || [string match itemco* $option]} { + if {[llength $args] == 1} { + switch -- $args { + -textvariable - -variable { + set msg "[lrange $msg 0 3] [list [lrange [lindex $msg 4] 1 end]]" + } + -command - updatecommand { + set msg "[lrange $msg 0 3] [list [lindex [lindex $msg 4] 2]]" + } + } + } elseif {[llength $args] == 0} { + set args1 "" + foreach el $msg { + switch -- [lindex $el 0] { + -textvariable - -variable { + set el "[lrange $el 0 3] [list [lrange [lindex $el 4] 1 end]]" + } + -command - updatecommand { + set el "[lrange $el 0 3] [list [lindex [lindex $el 4] 2]]" + } + } + lappend args1 $el + } + set msg $args1 + } + } elseif {[string match cg* $option] || [string match itemcg* $option]} { + switch -- $args { + -textvariable - -variable { + set msg [lrange $msg 1 end] + } + -command - updatecommand { + set msg [lindex $msg 2] + } + } + } elseif {[string match bi* $option]} { + if {[llength $args] == 2 && $code == 0} { + set msg [lindex $msg 2] + } + } + return -code $code $msg +} + +proc ::tkcon::RetrieveFilter {host} { + variable PRIV + set result {} + if {[info exists PRIV(proxy)]} { + if {![regexp "^(localhost|127\.0\.0\.1)" $host]} { + set result [lrange [split [lindex $PRIV(proxy) 0] :] 0 1] + } + } + return $result +} + +proc ::tkcon::RetrieveAuthentication {} { + package require Tk + if {[catch {package require base64}]} { + if {[catch {package require Trf}]} { + error "base64 support not available" + } else { + set local64 "base64 -mode enc" + } + } else { + set local64 "base64::encode" + } + + set dlg [toplevel .auth] + wm title $dlg "Authenticating Proxy Configuration" + set f1 [frame ${dlg}.f1] + set f2 [frame ${dlg}.f2] + button $f2.b -text "OK" -command "destroy $dlg" + pack $f2.b -side right + label $f1.l2 -text "Username" + label $f1.l3 -text "Password" + entry $f1.e2 -textvariable "[namespace current]::conf_userid" + entry $f1.e3 -textvariable "[namespace current]::conf_passwd" -show * + grid $f1.l2 -column 0 -row 0 -sticky e + grid $f1.l3 -column 0 -row 1 -sticky e + grid $f1.e2 -column 1 -row 0 -sticky news + grid $f1.e3 -column 1 -row 1 -sticky news + grid columnconfigure $f1 1 -weight 1 + pack $f2 -side bottom -fill x + pack $f1 -side top -anchor n -fill both -expand 1 + tkwait window $dlg + set result {} + if {[info exists [namespace current]::conf_userid]} { + set data [subst $[namespace current]::conf_userid] + append data : [subst $[namespace current]::conf_passwd] + set data [$local64 $data] + set result [list "Proxy-Authorization" "Basic $data"] + } + unset [namespace current]::conf_passwd + return $result +} + +proc ::tkcon::Retrieve {} { + # A little bit'o'magic to grab the latest tkcon from CVS and + # save it locally. It doesn't support proxies though... + variable PRIV + + set defExt "" + if {[string match "windows" $::tcl_platform(platform)]} { + set defExt ".tcl" + } + set file [tk_getSaveFile -title "Save Latest tkcon to ..." \ + -defaultextension $defExt \ + -initialdir [file dirname $PRIV(SCRIPT)] \ + -initialfile [file tail $PRIV(SCRIPT)] \ + -parent $PRIV(root) \ + -filetypes {{"Tcl Files" {.tcl .tk}} {"All Files" {*.*}}}] + if {[string compare $file ""]} { + package require http 2 + set token [::http::geturl $PRIV(HEADURL) -timeout 30000] + ::http::wait $token + set code [catch { + if {[::http::status $token] == "ok"} { + set fid [open $file w] + # We don't want newline mode to change + fconfigure $fid -translation binary + set data [::http::data $token] + puts -nonewline $fid $data + close $fid + regexp {Id: tkcon.tcl,v (\d+\.\d+)} $data -> rcsVersion + regexp {version\s+(\d+\.\d[^\n]*)} $data -> tkconVersion + } + } err] + ::http::cleanup $token + if {$code} { + return -code error $err + } elseif {[tk_messageBox -type yesno -icon info -parent $PRIV(root) \ + -title "Retrieved tkcon v$tkconVersion, RCS $rcsVersion" \ + -message "Successfully retrieved tkcon v$tkconVersion,\ + RCS $rcsVersion. Shall I resource (not restart) this\ + version now?"] == "yes"} { + set PRIV(SCRIPT) $file + set PRIV(version) $tkconVersion.$rcsVersion + ::tkcon::Resource + } + } +} + +## ::tkcon::Resource - re'source's this script into current console +## Meant primarily for my development of this program. It follows +## links until the ultimate source is found. +## +set ::tkcon::PRIV(SCRIPT) [info script] +if {!$::tkcon::PRIV(WWW) && [string compare $::tkcon::PRIV(SCRIPT) {}]} { + # we use a catch here because some wrap apps choke on 'file type' + # because TclpLstat wasn't wrappable until 8.4. + catch { + while {[string match link [file type $::tkcon::PRIV(SCRIPT)]]} { + set link [file readlink $::tkcon::PRIV(SCRIPT)] + if {[string match relative [file pathtype $link]]} { + set ::tkcon::PRIV(SCRIPT) \ + [file join [file dirname $::tkcon::PRIV(SCRIPT)] $link] + } else { + set ::tkcon::PRIV(SCRIPT) $link + } + } + catch {unset link} + if {[string match relative [file pathtype $::tkcon::PRIV(SCRIPT)]]} { + set ::tkcon::PRIV(SCRIPT) [file join [pwd] $::tkcon::PRIV(SCRIPT)] + } + } +} + +proc ::tkcon::Resource {} { + uplevel \#0 { + if {[catch {source -rsrc tkcon}]} { source $::tkcon::PRIV(SCRIPT) } + } + Bindings + InitSlave $::tkcon::OPT(exec) +} + +## Initialize only if we haven't yet +## +if {![info exists ::tkcon::PRIV(root)] || \ + ![winfo exists $::tkcon::PRIV(root)]} { + ::tkcon::Init +} diff --git a/tcltk/tkshell.tcl b/tcltk/tkshell.tcl new file mode 100755 index 00000000..c040aea1 --- /dev/null +++ b/tcltk/tkshell.tcl @@ -0,0 +1,202 @@ +#!/usr/bin/wish +# +# A Tcl shell in a text widget +# Brent Welch, from "Practical Programming in Tcl and Tk" +# + +package provide tkshell 1.0 + +# "namespace eval" is needed to force the creation of the namespace, +# even if it doesn't actually evaluate anything. Otherwise, the use +# of "proc tkshell::..." generates an undefined namespace error. + +namespace eval tkshell { + variable tkhist + variable tkpos + variable tkprompt +} + +#----------------------------------------------- +# Create a simple text widget with a Y scrollbar +#----------------------------------------------- + +proc tkshell::YScrolled_Text { f args } { + frame $f + eval {text $f.text -wrap none \ + -yscrollcommand [list $f.yscroll set]} $args + scrollbar $f.yscroll -orient vertical \ + -command [list $f.text yview] + grid $f.text $f.yscroll -sticky news + grid rowconfigure $f 0 -weight 1 + grid columnconfigure $f 0 -weight 1 + return $f.text +} + +#--------------------------------------------------------- +# Window command history management +#--------------------------------------------------------- + +proc tkshell::history {win dir} { + variable tkhist + variable tkpos + + set hlen [llength $tkhist($win)] + set pos [expr $tkpos($win) + $dir] + + set hidx [expr $hlen - $pos - 1] + + if {$hidx < 0} {return} + if {$hidx > $hlen} {return} + + set tkpos($win) $pos + + $win delete limit insert + $win insert insert [lindex $tkhist($win) $hidx] +} + +#--------------------------------------------------------- +# Create the shell window in Tk +#--------------------------------------------------------- + +proc tkshell::MakeEvaluator {{t .eval} {prompt "tcl>"} {prefix ""}} { + variable tkhist + variable tkpos + variable tkprompt + + # Create array for command history + set tkhist($t) {} + set tkpos($t) -1 + set tkprompt($t) $prompt + + # Text tags give script output, command errors, command + # results, and the prompt a different appearance + + $t tag configure prompt -foreground brown3 + $t tag configure result -foreground purple + $t tag configure stderr -foreground red + $t tag configure stdout -foreground blue + + # Insert the prompt and initialize the limit mark + + $t insert insert "${prompt} " prompt + $t mark set limit insert + $t mark gravity limit left + + # Key bindings that limit input and eval things. The break in + # the bindings skips the default Text binding for the event. + + bind $t "tkshell::EvalTypein $t $prefix $prompt; break" + bind $t { + if {[%W tag nextrange sel 1.0 end] != ""} { + %W delete sel.first sel.last + } elseif {[%W compare insert > limit]} { + %W delete insert-1c + %W see insert + } + break + } + bind $t { + tkshell::history %W 1 + break + } + bind $t { + tkshell::history %W -1 + break + + } + bind $t { + if [%W compare insert < limit] { + %W mark set insert end + } + } +} + +#----------------------------------------------------------- +# Evaluate everything between limit and end as a Tcl command +#----------------------------------------------------------- + +proc tkshell::EvalTypein {t prefix prompt} { + variable tkhist + set savecommand [$t get limit end-1c] + $t insert insert \n + set command [$t get limit end] + if [info complete $command] { + lappend tkhist($t) $savecommand + set tkshell::tkpos($t) -1 + $t mark set limit insert + tkshell::Eval $t $prefix $prompt $command + } +} + +#----------------------------------------------------------- +# Evaluate a command and display its result +#----------------------------------------------------------- + +proc tkshell::Eval {t prefix prompt command} { + global Opts + $t mark set insert end + set fullcommand "${prefix} " + append fullcommand $command + if [catch {eval $fullcommand} result] { + $t insert insert $result error + } else { + $t insert insert $result result + } + if {[$t compare insert != "insert linestart"]} { + $t insert insert \n + } + $t insert insert "${prompt} " prompt + $t see insert + $t mark set limit insert + if {"$prefix" != ""} { + catch {if {$Opts(redirect) == 1} {focus $prefix ; \ + unset Opts(redirect)}} + magic::macro XK_period "$fullcommand" + } + return +} + +#-------------------------------------------------------------- +# This "puts" alias puts stdout and stderr into the text widget +#-------------------------------------------------------------- + +proc tkshell::PutsTkShell {args} { + global Opts + variable tkprompt + set t ${Opts(focus)}.pane.bot.eval + if {[llength $args] > 3} { + error "invalid arguments" + } + set newline "\n" + if {[string match "-nonewline" [lindex $args 0]]} { + set newline "" + set args [lreplace $args 0 0] + } + if {[llength $args] == 1} { + set chan stdout + set string [lindex $args 0]$newline + } else { + set chan [lindex $args 0] + set string [lindex $args 1]$newline + } + if [regexp (stdout|stderr) $chan] { + # ${t}.text delete "current linestart+1c" limit-1c ;# testing! + ${t}.text mark gravity limit right + ${t}.text insert limit $string $chan + ${t}.text see limit + ${t}.text mark gravity limit left + # if {![catch {set prompt $tkprompt(${t}.text)}]} { + # ${t}.text insert insert "${prompt} " prompt ;# testing! + # } + } else { + ::tkcon_puts -nonewline $chan $string + } +} + +#-------------------------------------------------------------- +# A few lines is all that's needed to run this thing. +#-------------------------------------------------------------- +# tkshell::YScrolled_Text .eval -width 90 -height 5 +# pack .eval -fill both -expand true +# tkshell::MakeEvaluator .eval.text "magic> " +#-------------------------------------------------------------- diff --git a/tcltk/toolkit.tcl b/tcltk/toolkit.tcl new file mode 100644 index 00000000..7412277a --- /dev/null +++ b/tcltk/toolkit.tcl @@ -0,0 +1,838 @@ +#----------------------------------------------------- +# Magic/TCL general-purpose toolkit procedures +#----------------------------------------------------- +# Tim Edwards +# February 11, 2007 +# Revision 0 +# December 15, 2016 +# Revision 1 +#-------------------------------------------------------------- +# Sets up the environment for a toolkit. The toolkit must +# supply a namespace that is the "library name". For each +# parameter-defined device ("gencell") type, the toolkit must +# supply five procedures: +# +# 1. ${library}::${gencell_type}_defaults {} +# 2. ${library}::${gencell_type}_convert {parameters} +# 3. ${library}::${gencell_type}_dialog {parameters} +# 4. ${library}::${gencell_type}_check {parameters} +# 5. ${library}::${gencell_type}_draw {parameters} +# +# The first defines the parameters used by the gencell, and +# declares default parameters to use when first generating +# the window that prompts for the device parameters prior to +# creating the device. The second converts between parameters +# in a SPICE netlist and parameters used by the dialog, +# performing units conversion and parameter name conversion as +# needed. The third builds the dialog window for entering +# device parameters. The fourth checks the parameters for +# legal values. The fifth draws the device. +# +# If "library" is not specified then it defaults to "toolkit". +# Otherwise, where specified, the name "gencell_fullname" +# is equivalent to "${library}::${gencell_type}" +# +# Each gencell is defined by cell properties as created by +# the "cellname property" command. Specific properties used +# by the toolkit are: +# +# library --- name of library (see above, default "toolkit") +# gencell --- base name of gencell (gencell_type, above) +# parameters --- list of gencell parameter-value pairs +#-------------------------------------------------------------- + +# Initialize toolkit menus to the wrapper window + +global Opts + +#---------------------------------------------------------------- +# Add a menu button to the Magic wrapper window for the toolkit +#---------------------------------------------------------------- + +proc magic::add_toolkit_menu {framename button_text {library toolkit}} { + menubutton ${framename}.titlebar.mbuttons.${library} \ + -text $button_text \ + -relief raised \ + -menu ${framename}.titlebar.mbuttons.${library}.toolmenu \ + -borderwidth 2 + + menu ${framename}.titlebar.mbuttons.${library}.toolmenu -tearoff 0 + pack ${framename}.titlebar.mbuttons.${library} -side left +} + +#----------------------------------------------------------------- +# Add a menu item to the toolkit menu calling the default function +#----------------------------------------------------------------- + +proc magic::add_toolkit_button {framename button_text gencell_type \ + {library toolkit} args} { + set m ${framename}.titlebar.mbuttons.${library}.toolmenu + $m add command -label "$button_text" -command \ + "magic::gencell $library::$gencell_type {} $args" +} + +#---------------------------------------------------------------- +# Add a menu item to the toolkit menu that calls the provided +# function +#---------------------------------------------------------------- + +proc magic::add_toolkit_command {framename button_text \ + command {library toolkit} args} { + set m ${framename}.titlebar.mbuttons.${library}.toolmenu + $m add command -label "$button_text" -command "$command $args" +} + +#---------------------------------------------------------------- +# Add a separator to the toolkit menu +#---------------------------------------------------------------- + +proc magic::add_toolkit_separator {framename {library toolkit}} { + set m ${framename}.titlebar.mbuttons.${library}.toolmenu + $m add separator +} + +#----------------------------------------------------- +# Add "Ctrl-P" key callback for device selection +#----------------------------------------------------- + +magic::macro ^P "magic::gencell {} ; raise .params" + +#------------------------------------------------------------- +# Add tag callback to select to update the gencell window +#------------------------------------------------------------- + +magic::tag select "[magic::tag select]; magic::gencell_update %1" + +#------------------------------------------------------------- +# gencell +# +# Main routine to call a cell from either a menu button or +# from a script or command line. The name of the device +# is required, followed by the name of the instance, followed +# by an optional list of parameters. Handling depends on +# instname and args: +# +# gencell_name is either the name of an instance or the name +# of the gencell in the form ::. +# +# name args action +#----------------------------------------------------------------- +# none empty interactive, new device w/defaults +# none specified interactive, new device w/parameters +# instname empty interactive, edit device +# instname specified non-interactive, change device +# device empty non-interactive, new device w/defaults +# device specified non-interactive, new device w/parameters +# +#------------------------------------------------------------- +# Also, if instname is empty and gencell_name is not specified, +# and if a device is selected in the layout, then gencell +# behaves like line 3 above (instname exists, args is empty). +# Note that macro Ctrl-P calls gencell this way. If gencell_name +# is not specified and nothing is selected, then gencell{} +# does nothing. +# +# "args" must be a list of the cell parameters in key:value pairs, +# and an odd number is not legal; the exception is that if the +# first argument is "-spice", then the list of parameters is +# expected to be in the format used in a SPICE netlist, and the +# parameter names and values will be treated accordingly. +#------------------------------------------------------------- + +proc magic::gencell {gencell_name {instname {}} args} { + + # Pull "-spice" out of args, if it is the first argument + if {[lindex $args 0] == "-spice"} { + set spicemode 1 + set args [lrange $args 1 end] + } else { + set spicemode 0 + } + set argpar [dict create {*}$args] + + if {$gencell_name == {}} { + # Find selected item (to-do: handle multiple selections) + + set wlist [what -list] + set clist [lindex $wlist 2] + set ccell [lindex $clist 0] + set ginst [lindex $ccell 0] + set gname [lindex $ccell 1] + set library [cellname list property $gname library] + if {$library == {}} { + set library toolkit + } + set gencell_type [cellname list property $gname gencell] + if {$gencell_type == {}} { + if {![regexp {^(.*)_[0-9]*$} $gname valid gencell_type]} { + # Error message + error "No gencell device is selected!" + } + } + # need to incorporate argpar? + set parameters [cellname list property $gname parameters] + set parameters [magic::gencell_defaults $gencell_type $library $parameters] + magic::gencell_dialog $ginst $gencell_type $library $parameters + } else { + # Parse out library name from gencell_name, otherwise default + # library is assumed to be "toolkit". + if {[regexp {^([^:]+)::([^:]+)$} $gencell_name valid library gencell_type] \ + == 0} { + set library "toolkit" + set gencell_type $gencell_name + } + + if {$instname == {}} { + # Case: Interactive, new device with parameters in args (if any) + if {$spicemode == 1} { + # Legal not to have a *_convert routine + if {[info commands ${library}::${gencell_type}_convert] != ""} { + set argpar [${library}::${gencell_type}_convert $argpar] + } + } + set parameters [magic::gencell_defaults $gencell_type $library $argpar] + magic::gencell_dialog {} $gencell_type $library $parameters + } else { + # Check if instance exists or not in the cell + set cellname [instance list celldef $instname] + + if {$cellname != ""} { + # Case: Change existing instance, parameters in args (if any) + select cell $instname + set devparms [cellname list property $gencell_type parameters] + set parameters [magic::gencell_defaults $gencell_type $library $devparms] + if {[dict exists $parameters nocell]} { + set arcount [array -list count] + set arpitch [array -list pitch] + + dict set parameters nx [lindex $arcount 1] + dict set parameters ny [lindex $arcount 3] + dict set parameters pitchx $delx + dict set parameters pitchy $dely + } + if {[dict size $argpar] == 0} { + # No changes entered on the command line, so start dialog + magic::gencell_dialog $instname $gencell_type $library $parameters + } else { + # Apply specified changes without invoking the dialog + if {$spicemode == 1} { + set argpar [${library}::${gencell_type}_convert $argpar] + } + set parameters [dict merge $parameters $argpar] + magic::gencell_change $instname $gencell_type $library $parameters + } + } else { + # Case: Non-interactive, create new device with parameters + # in args (if any) + if {$spicemode == 1} { + set argpar [${library}::${gencell_type}_convert $argpar] + } + set parameters [magic::gencell_defaults $gencell_type $library $argpar] + set inst_defaultname [magic::gencell_create \ + $gencell_type $library $parameters] + select cell $inst_defaultname + identify $instname + } + } + } +} + +#------------------------------------------------------------- +# gencell_getparams +# +# Go through the parameter window and collect all of the +# named parameters and their values. Return the result as +# a dictionary. +#------------------------------------------------------------- + +proc magic::gencell_getparams {} { + set parameters [dict create] + set slist [grid slaves .params.edits] + foreach s $slist { + if {[regexp {^.params.edits.(.*)_ent$} $s valid pname] != 0} { + set value [subst \$magic::${pname}_val] + } elseif {[regexp {^.params.edits.(.*)_chk$} $s valid pname] != 0} { + set value [subst \$magic::${pname}_val] + } elseif {[regexp {^.params.edits.(.*)_sel$} $s valid pname] != 0} { + set value [subst \$magic::${pname}_val] + } + dict set parameters $pname $value + } + return $parameters +} + +#------------------------------------------------------------- +# gencell_setparams +# +# Fill in values in the dialog from a set of parameters +#------------------------------------------------------------- + +proc magic::gencell_setparams {parameters} { + if {[catch {set state [wm state .params]}]} {return} + set slist [grid slaves .params.edits] + foreach s $slist { + if {[regexp {^.params.edits.(.*)_ent$} $s valid pname] != 0} { + set value [dict get $parameters $pname] + set magic::${pname}_val $value + } elseif {[regexp {^.params.edits.(.*)_chk$} $s valid pname] != 0} { + set value [dict get $parameters $pname] + set magic::${pname}_val $value + } elseif {[regexp {^.params.edits.(.*)_sel$} $s valid pname] != 0} { + set value [dict get $parameters $pname] + set magic::${pname}_val $value + } elseif {[regexp {^.params.edits.(.*)_txt$} $s valid pname] != 0} { + if {[dict exists $parameters $pname]} { + set value [dict get $parameters $pname] + .params.edits.${pname}_txt configure -text $value + } + } + } +} + +#------------------------------------------------------------- +# gencell_change +# +# Redraw a gencell with new parameters. +#------------------------------------------------------------- + +proc magic::gencell_change {instname gencell_type library parameters} { + global Opts + suspendall + + set newinstname $instname + if {$parameters == {}} { + # Get device defaults + set pdefaults [${library}::${gencell_type}_defaults] + # Pull user-entered values from dialog + set parameters [dict merge $pdefaults [magic::gencell_getparams]] + set newinstname [.params.title.ient get] + if {$newinstname == "(default)"} {set newinstname $instname} + if {$newinstname == $instname} {set newinstname $instname} + if {[instance list exists $newinstname] != ""} {set newinstname $instname} + } + if {[catch {set parameters [${library}::${gencell_type}_check $parameters]} \ + checkerr]} { + puts stderr $checkerr + } + magic::gencell_setparams $parameters + + set gname [instance list celldef $instname] + + # Guard against instance having been deleted + if {$gname == ""} { + resumeall + return + } + + set snaptype [snap list] + snap internal + set savebox [box values] + + catch {setpoint 0 0 $Opts(focus)} + if [dict exists $parameters nocell] { + select cell $instname + delete + if {[catch {set newinst [${library}::${gencell_type}_draw $parameters]} \ + drawerr]} { + puts stderr $drawerr + } + select cell $newinst + } else { + pushstack $gname + select cell + tech unlock * + erase * + if {[catch {${library}::${gencell_type}_draw $parameters} drawerr]} { + puts stderr $drawerr + } + property parameters $parameters + tech revert + popstack + select cell $instname + } + identify $newinstname + eval "box values $savebox" + snap $snaptype + resumeall + redraw +} + +#------------------------------------------------------------- +# Assign a unique name for a gencell +# +# Note: This depends on the unlikelihood of the name +# existing in a cell on disk. Only cells in memory are +# checked for name collisions. Since the names will go +# into SPICE netlists, names must be unique when compared +# in a case-insensitive manner. Using base-36 (alphabet and +# numbers), each gencell name with 6 randomized characters +# has a 1 in 4.6E-10 chance of reappearing. +#------------------------------------------------------------- + +proc magic::get_gencell_name {gencell_type} { + while {true} { + set postfix "" + for {set i 0} {$i < 6} {incr i} { + set pint [expr 48 + int(rand() * 36)] + if {$pint > 57} {set pint [expr $pint + 39]} + append postfix [format %c $pint] + } + if {[cellname list exists ${gencell_type}_$postfix] == 0} {break} + } + return ${gencell_type}_$postfix +} + +#------------------------------------------------------------- +# gencell_create +# +# Instantiate a new gencell called $gname. If $gname +# does not already exist, create it by calling its +# drawing routine. +# +# Don't rely on pushbox/popbox since we don't know what +# the drawing routine is going to do to the stack! +#------------------------------------------------------------- + +proc magic::gencell_create {gencell_type library parameters} { + global Opts + suspendall + + set newinstname "" + + # Get device defaults + set pdefaults [${library}::${gencell_type}_defaults] + if {$parameters == {}} { + # Pull user-entered values from dialog + set parameters [dict merge $pdefaults [magic::gencell_getparams]] + set newinstname [.params.title.ient get] + if {$newinstname == "(default)"} {set newinstname ""} + if {[instance list exists $newinstname] != ""} {set newinstname ""} + } else { + set parameters [dict merge $pdefaults $parameters] + } + + if {[catch {set parameters [${library}::${gencell_type}_check $parameters]} \ + checkerr]} { + puts stderr $checkerr + } + magic::gencell_setparams $parameters + + set snaptype [snap list] + snap internal + set savebox [box values] + + catch {setpoint 0 0 $Opts(focus)} + if [dict exists $parameters nocell] { + if {[catch {set instname [${library}::${gencell_type}_draw $parameters]} \ drawerr]} { + puts stderr $drawerr + } + set gname [instance list celldef $instname] + eval "box values $savebox" + } else { + set gname [magic::get_gencell_name ${gencell_type}] + cellname create $gname + pushstack $gname + if {[catch {${library}::${gencell_type}_draw $parameters} drawerr]} { + puts stderr $drawerr + } + property library $library + property gencell $gencell_type + property parameters $parameters + popstack + eval "box values $savebox" + set instname [getcell $gname] + expand + } + if {$newinstname != ""} { + identify $newinstname + set instname $newinstname + } + snap $snaptype + resumeall + redraw + return $instname +} + +#----------------------------------------------------- +# Add a standard entry parameter to the gencell window +#----------------------------------------------------- + +proc magic::add_entry {pname ptext parameters} { + + if [dict exists $parameters $pname] { + set value [dict get $parameters $pname] + } else { + set value "" + } + + set numrows [lindex [grid size .params.edits] 1] + label .params.edits.${pname}_lab -text $ptext + entry .params.edits.${pname}_ent -background white -textvariable magic::${pname}_val + grid .params.edits.${pname}_lab -row $numrows -column 0 \ + -sticky ens -ipadx 5 -ipady 2 + grid .params.edits.${pname}_ent -row $numrows -column 1 \ + -sticky ewns -ipadx 5 -ipady 2 + .params.edits.${pname}_ent insert end $value + set magic::${pname}_val $value +} + +#---------------------------------------------------------- +# Default entry callback, without any dependencies. Each +# parameter changed +#---------------------------------------------------------- + +proc magic::add_check_callbacks {gencell_type library} { + set wlist [winfo children .params.edits] + foreach w $wlist { + if {[regexp {\.params\.edits\.(.+)_ent} $w valid pname]} { + # Add callback on enter or focus out + bind $w \ + "magic::update_dialog {} $pname $gencell_type $library" + bind $w \ + "magic::update_dialog {} $pname $gencell_type $library" + } + } +} + +#---------------------------------------------------------- +# Add a dependency between entries. When one updates, the +# others will be recomputed according to the callback +# function. +# +# The callback function is passed the value of all +# parameters for the device, overridden by the values +# in the dialog. The routine computes the dependent +# values and writes them back to the parameter dictionary. +# The callback function must return the modified parameters +# dictionary. +# +# Also handle dependencies on checkboxes and selection lists +#---------------------------------------------------------- + +proc magic::add_dependency {callback gencell_type library args} { + if {[llength $args] == 0} { + # If no arguments are given, do for all parameters + set parameters ${library}::${gencell_type}_defaults + magic::add_dependency $callback $gencell_type $library \ + {*}[dict keys $parameters] + return + } + set clist [winfo children .params.edits] + foreach pname $args { + if {[lsearch $clist .params.edits.${pname}_ent] >= 0} { + # Add callback on enter or focus out + bind .params.edits.${pname}_ent \ + "magic::update_dialog $callback $pname $gencell_type $library" + bind .params.edits.${pname}_ent \ + "magic::update_dialog $callback $pname $gencell_type $library" + } elseif {[lsearch $clist .params.edits.${pname}_chk] >= 0} { + # Add callback on checkbox change state + .params.edits.${pname}_chk configure -command \ + "magic::update_dialog $callback $pname $gencell_type $library" + } elseif {[lsearch $clist .params.edits.${pname}_sel] >= 0} { + set smenu .params.edits.${pname}_sel.menu + set sitems [${smenu} index end] + for {set idx 0} {$idx <= $sitems} {incr idx} { + set curcommand [${smenu} entrycget $idx -command] + ${smenu} entryconfigure $idx -command "$curcommand ; \ + magic::update_dialog $callback $pname $gencell_type $library" + } + } + } +} + +#---------------------------------------------------------- +# Execute callback procedure, then run bounds checks +#---------------------------------------------------------- + +proc magic::update_dialog {callback pname gencell_type library} { + set pdefaults [${library}::${gencell_type}_defaults] + set parameters [dict merge $pdefaults [magic::gencell_getparams]] + if {$callback != {}} { + set parameters [$callback $pname $parameters] + } + if {[catch {set parameters [${library}::${gencell_type}_check $parameters]} \ + checkerr]} { + puts stderr $checkerr + } + magic::gencell_setparams $parameters +} + +#---------------------------------------------------------- +# Add a standard checkbox parameter to the gencell window +#---------------------------------------------------------- + +proc magic::add_checkbox {pname ptext parameters} { + + if [dict exists $parameters $pname] { + set value [dict get $parameters $pname] + } else { + set value "" + } + + set numrows [lindex [grid size .params.edits] 1] + label .params.edits.${pname}_lab -text $ptext + checkbutton .params.edits.${pname}_chk -variable magic::${pname}_val + grid .params.edits.${pname}_lab -row $numrows -column 0 -sticky ens + grid .params.edits.${pname}_chk -row $numrows -column 1 -sticky wns + set magic::${pname}_val $value +} + +#---------------------------------------------------------- +# Add a message box (informational, not editable) to the +# gencell window. Note that the text does not have to be +# in the parameter list, as it can be upated through the +# textvariable name. +#---------------------------------------------------------- + +proc magic::add_message {pname ptext parameters {color blue}} { + + if [dict exists $parameters $pname] { + set value [dict get $parameters $pname] + } else { + set value "" + } + + set numrows [lindex [grid size .params.edits] 1] + label .params.edits.${pname}_lab -text $ptext + label .params.edits.${pname}_txt -text $value \ + -foreground $color -textvariable magic::${pname}_val + grid .params.edits.${pname}_lab -row $numrows -column 0 -sticky ens + grid .params.edits.${pname}_txt -row $numrows -column 1 -sticky wns +} + +#---------------------------------------------------------- +# Add a selectable-list parameter to the gencell window +#---------------------------------------------------------- + +proc magic::add_selectlist {pname ptext all_values parameters} { + + if [dict exists $parameters $pname] { + set value [dict get $parameters $pname] + } else { + set value "" + } + + set numrows [lindex [grid size .params.edits] 1] + label .params.edits.${pname}_lab -text $ptext + menubutton .params.edits.${pname}_sel -menu .params.edits.${pname}_sel.menu \ + -relief groove -text ${value} + grid .params.edits.${pname}_lab -row $numrows -column 0 -sticky ens + grid .params.edits.${pname}_sel -row $numrows -column 1 -sticky wns + menu .params.edits.${pname}_sel.menu -tearoff 0 + foreach item ${all_values} { + .params.edits.${pname}_sel.menu add radio -label $item \ + -variable magic::${pname}_val -value $item \ + -command ".params.edits.${pname}_sel configure -text $item" + } + set magic::${pname}_val $value +} + +#------------------------------------------------------------- +# gencell_defaults --- +# +# Set all parameters for a device. Start by calling the base +# device's default value list to generate a dictionary. Then +# parse all values passed in 'parameters', overriding any +# defaults with the passed values. +#------------------------------------------------------------- + +proc magic::gencell_defaults {gencell_type library parameters} { + set basedict [${library}::${gencell_type}_defaults] + set newdict [dict merge $basedict $parameters] + return $newdict +} + +#------------------------------------------------------------- +# Command tag callback on "select". "select cell" should +# cause the parameter dialog window to update to reflect the +# selected cell. If a cell is unselected, then revert to the +# default 'Create' window. +#------------------------------------------------------------- + +proc magic::gencell_update {{command {}}} { + if {[info level] <= 1} { + if {![catch {set state [wm state .params]}]} { + if {[wm state .params] == "normal"} { + if {$command == "cell"} { + # If multiple devices are selected, choose the first in + # the list returned by "what -list". + set instname [lindex [lindex [lindex [what -list] 2] 0] 0] + magic::gencell_dialog $instname {} {} {} + } + } + } + } +} + +#------------------------------------------------------------- +# gencell_dialog --- +# +# Create the dialog window for entering device parameters. The +# general procedure then calls the dialog setup for the specific +# device. +# +# 1) If gname is NULL and gencell_type is set, then we +# create a new cell of type gencell_type. +# 2) If gname is non-NULL, then we edit the existing +# cell of type $gname. +# 3) If gname is non-NULL and gencell_type or library +# is NULL or unspecified, then we derive the gencell_type +# and library from the existing cell's property strings +# +# The device setup should be built using the API that defines +# these procedures: +# +# magic::add_entry Single text entry window +# magic::add_checkbox Single checkbox +# magic::add_selectlist Pull-down menu with list of selections +# +#------------------------------------------------------------- + +proc magic::gencell_dialog {instname gencell_type library parameters} { + if {$gencell_type == {}} { + # Revert to default state for the device that was previously + # shown in the parameter window. + if {![catch {set state [wm state .params]}]} { + if {$instname == {}} { + set devstr [.params.title.lab1 cget -text] + if {$devstr == "Edit device:"} { + set gencell_type [.params.title.lab2 cget -text] + set library [.params.title.lab4 cget -text] + } else { + return + } + } + } + } + + if {$instname != {}} { + # Remove any array component of the instance name + set instname [string map {\\ ""} $instname] + if {[regexp {^(.*)\[[0-9,]+\]$} $instname valid instroot]} { + set instname $instroot + } + set gname [instance list celldef [subst $instname]] + if {$gencell_type == {}} { + set gencell_type [cellname list property $gname gencell] + } + if {$library == {}} { + set library [cellname list property $gname library] + } + if {$parameters == {}} { + set parameters [cellname list property $gname parameters] + } + if {$gencell_type == {} || $library == {}} {return} + + if {$parameters == {}} { + set parameters [${library}::${gencell_type}_defaults] + } + + # If the default parameters contain "nocell", then set the + # standard parameters for fixed devices from the instance + if {[dict exists $parameters nocell]} { + select cell $instname + set arcount [array -list count] + set arpitch [array -list pitch] + + dict set parameters nx [expr [lindex $arcount 1] - [lindex $arcount 0] + 1] + dict set parameters ny [expr [lindex $arcount 3] - [lindex $arcount 2] + 1] + dict set parameters pitchx [lindex $arpitch 0] + dict set parameters pitchy [lindex $arpitch 1] + } + set ttext "Edit device" + set itext $instname + } else { + set parameters [magic::gencell_defaults $gencell_type $library $parameters] + set gname "(default)" + set itext "(default)" + set ttext "New device" + } + + # Destroy children, not the top-level window, or else window keeps + # bouncing around every time something is changed. + if {[catch {toplevel .params}]} { + .params.title.lab1 configure -text "${ttext}:" + .params.title.lab2 configure -text "$gencell_type" + .params.title.lab4 configure -text "$library" + .params.title.glab configure -foreground blue -text "$gname" + .params.title.ient delete 0 end + .params.title.ient insert 0 "$itext" + foreach child [winfo children .params.edits] { + destroy $child + } + foreach child [winfo children .params.buttons] { + destroy $child + } + } else { + frame .params.title + label .params.title.lab1 -text "${ttext}:" + label .params.title.lab2 -foreground blue -text "$gencell_type" + label .params.title.lab3 -text "Library:" + label .params.title.lab4 -foreground blue -text "$library" + label .params.title.clab -text "Cellname:" + label .params.title.glab -foreground blue -text "$gname" + label .params.title.ilab -text "Instance:" + entry .params.title.ient -foreground brown -background white + .params.title.ient insert 0 "$itext" + ttk::separator .params.sep + frame .params.edits + frame .params.buttons + + grid .params.title.lab1 -padx 5 -row 0 -column 0 + grid .params.title.lab2 -padx 5 -row 0 -column 1 -sticky w + grid .params.title.lab3 -padx 5 -row 0 -column 2 + grid .params.title.lab4 -padx 5 -row 0 -column 3 -sticky w + + grid .params.title.clab -padx 5 -row 1 -column 0 + grid .params.title.glab -padx 5 -row 1 -column 1 -sticky w + grid .params.title.ilab -padx 5 -row 1 -column 2 + grid .params.title.ient -padx 5 -row 1 -column 3 -sticky ew + grid columnconfigure .params.title 3 -weight 1 + + pack .params.title -fill x -expand true + pack .params.sep -fill x -expand true + pack .params.edits -side top -fill both -expand true -ipadx 5 + pack .params.buttons -fill x + + grid columnconfigure .params.edits 1 -weight 1 + } + + if {$instname == {}} { + button .params.buttons.apply -text "Create" -command \ + [subst {set inst \[magic::gencell_create \ + $gencell_type $library {}\] ; \ + magic::gencell_dialog \$inst $gencell_type $library {} }] + button .params.buttons.okay -text "Create and Close" -command \ + [subst {set inst \[magic::gencell_create \ + $gencell_type $library {}\] ; \ + magic::gencell_dialog \$inst $gencell_type $library {} ; \ + destroy .params}] + } else { + button .params.buttons.apply -text "Apply" -command \ + "magic::gencell_change $instname $gencell_type $library {}" + button .params.buttons.okay -text "Okay" -command \ + "magic::gencell_change $instname $gencell_type $library {} ;\ + destroy .params" + } + button .params.buttons.reset -text "Reset" -command \ + "magic::gencell_dialog {} ${gencell_type} ${library} {}" + button .params.buttons.close -text "Close" -command {destroy .params} + + pack .params.buttons.apply -padx 5 -ipadx 5 -ipady 2 -side left + pack .params.buttons.okay -padx 5 -ipadx 5 -ipady 2 -side left + pack .params.buttons.close -padx 5 -ipadx 5 -ipady 2 -side right + pack .params.buttons.reset -padx 5 -ipadx 5 -ipady 2 -side right + + # Invoke the callback procedure that creates the parameter entries + + ${library}::${gencell_type}_dialog $parameters + + # Add standard callback to all entry fields to run parameter bounds checks + magic::add_check_callbacks $gencell_type $library + + # Make sure the window is raised + raise .params +} + +#------------------------------------------------------------- diff --git a/tcltk/toolkit_rev0.tcl b/tcltk/toolkit_rev0.tcl new file mode 100644 index 00000000..3fab0f10 --- /dev/null +++ b/tcltk/toolkit_rev0.tcl @@ -0,0 +1,284 @@ +#----------------------------------------------------- +# Magic/TCL general-purpose toolkit procedures +#----------------------------------------------------- +# Tim Edwards +# February 11, 2007 +# Revision 0 +#-------------------------------------------------------------- +# Sets up the environment for a toolkit. The toolkit must +# supply a namespace that is the "library name". For each +# parameter-defined device ("gencell") type, the toolkit must +# supply three procedures: +# +# 1. ${library}::${gencell_type}_params {gname} {...} +# 2. ${library}::${gencell_type}_check {gname} {...} +# 3. ${library}::${gencell_type}_draw {gname} {...} +# +# The first defines the parameters used by the gencell, and +# declares default parameters to use when first generating +# the window that prompts for the device parameters prior to +# creating the device. The second checks the parameters for +# legal values. The third draws the device. +#-------------------------------------------------------------- + +# Initialize toolkit menus to the wrapper window + +global Opts + +#---------------------------------------------------------------- +# Add a menu button to the Magic wrapper window for the toolkit +#---------------------------------------------------------------- + +proc magic::add_toolkit_menu {framename button_text} { + menubutton ${framename}.titlebar.mbuttons.toolkit \ + -text $button_text \ + -relief raised \ + -menu ${framename}.titlebar.mbuttons.toolkit.toolmenu \ + -borderwidth 2 + + menu ${framename}.titlebar.mbuttons.toolkit.toolmenu -tearoff 0 + pack ${framename}.titlebar.mbuttons.toolkit -side left +} + +#---------------------------------------------------------------- +# Add a menu item to the toolkit menu +#---------------------------------------------------------------- + +proc magic::add_toolkit_button {framename button_text gencell_type library} { + set m ${framename}.titlebar.mbuttons.toolkit.toolmenu + $m add command -label "$button_text" -command \ + "magic::gencell_params {} $gencell_type $library" +} + +#----------------------------------------------------- +# Device selection +#----------------------------------------------------- + +proc magic::gen_params {} { + + # Find selected item (to-do: handle multiple selections) + set wlist [what -list] + set clist [lindex $wlist 2] + set ccell [lindex $clist 0] + set cdef [lindex $ccell 1] + if {[regexp {^(.*_[0-9]*)$} $cdef valid gname] != 0} { + set library [cellname property $gname library] + if {$library == {}} { + error "Gencell has no associated library!" + } else { + regexp {^(.*)_[0-9]*$} $cdef valid gencell_type + magic::gencell_params $gname $gencell_type $library + } + } else { + # Error message + error "No gencell device is selected!" + } +} + +#----------------------------------------------------- +# Add "Ctrl-P" key callback for device selection +#----------------------------------------------------- + +magic::macro ^P magic::gen_params + +#------------------------------------------------------------- +# gencell_setparams +# +# Go through the parameter window and collect all of the +# named parameters and their values, and generate the +# associated properties in celldef "$gname". +#------------------------------------------------------------- + +proc magic::gencell_setparams {gname} { + set slist [grid slaves .params.edits] + foreach s $slist { + if {[regexp {^.params.edits.(.*)_ent$} $s valid pname] != 0} { + set value [$s get] + cellname property $gname $pname $value + } + } +} + +#------------------------------------------------------------- +# gencell_getparam +# +# Go through the parameter window, find the named parameter, +# and return its value. +#------------------------------------------------------------- + +proc magic::gencell_getparam {gname pname} { + set slist [grid slaves .params.edits] + foreach s $slist { + if {[regexp {^.params.edits.(.*)_ent$} $s valid ptest] != 0} { + if {$pname == $ptest} { + return [$s get] + } + } + } +} + +#------------------------------------------------------------- +# gencell_change +# +# Redraw a gencell with new parameters. +#------------------------------------------------------------- + +proc magic::gencell_change {gname gencell_type library} { + if {[cellname list exists $gname] != 0} { + if {[eval "${library}::${gencell_type}_check $gname"]} { + suspendall + pushstack $gname + select cell + erase * + magic::gencell_draw $gname $gencell_type $library + popstack + resumeall + } else { + error "Parameter out of range!" + } + } else { + error "Cell $gname does not exist!" + } +} + +#------------------------------------------------------------- +# gencell_create +# +# Instantiate a new gencell called $gname. If $gname +# does not already exist, create it by calling its +# drawing routine. +# +# Don't rely on pushbox/popbox since we don't know what +# the drawing routine is going to do to the stack! +#------------------------------------------------------------- + +proc magic::gencell_create {gname gencell_type library} { + suspendall + if {[cellname list exists $gname] == 0} { + cellname create $gname + set snaptype [snap list] + snap internal + set savebox [box values] + pushstack $gname + magic::gencell_draw $gname $gencell_type $library + popstack + eval "box values $savebox" + snap $snaptype + } + getcell $gname + expand + resumeall +} + +#------------------------------------------------------------- +#------------------------------------------------------------- + +proc magic::gencell_check {gname gencell_type library} { + return [eval "${library}::${gencell_type}_check $gname"] +} + +#------------------------------------------------------------- +#------------------------------------------------------------- + +proc magic::gencell_draw {gname gencell_type library} { + + # Set the parameters passed from the window text entries + magic::gencell_setparams $gname + + # Call the draw routine + eval "${library}::${gencell_type}_draw $gname" + + # Find the namespace of the draw procedure and set propery "library" + cellname property $gname library $library +} + +#----------------------------------------------------- +# Add a standard parameter to the gencell window +#----------------------------------------------------- + +proc magic::add_param {gname pname ptext default_value} { + + # Check if the parameter exists. If so, override the default + # value with the current value. + + set value {} + if {[cellname list exists $gname] != 0} { + set value [cellname property $gname $pname] + } + if {$value == {}} {set value $default_value} + + set numrows [lindex [grid size .params.edits] 0] + label .params.edits.${pname}_lab -text $ptext + entry .params.edits.${pname}_ent -background white + grid .params.edits.${pname}_lab -row $numrows -column 0 + grid .params.edits.${pname}_ent -row $numrows -column 1 + .params.edits.${pname}_ent insert end $value +} + +#----------------------------------------------------- +# Update the properties of a cell +#----------------------------------------------------- + +proc magic::update_params {gname ptext default_value} { +} + +#------------------------------------------------------------- +# gencell_params --- +# 1) If gname is NULL and gencell_type is set, then we +# create a new cell of type gencell_type. +# 2) If gname is non-NULL, then we edit the existing +# cell of type $gname. +# 3) If gname is non-NULL and gencell_type or library +# is NULL or unspecified, then we derive the gencell_type +# and library from the existing cell's property strings +#------------------------------------------------------------- + +proc magic::gencell_params {gname {gencell_type {}} {library {}}} { + + if {$gname == {}} { + set pidx 1 + while {[cellname list exists ${gencell_type}_$pidx] != 0} { + incr pidx + } + set gname ${gencell_type}_$pidx + + set ttext "New device" + set btext "Create" + set bcmd "magic::gencell_create $gname $gencell_type $library" + } else { + if {$gencell_type == {}} { + set gencell_type [cellname property ${gname} gencell] + } + if {$library == {}} { + set library [cellname property ${gname} library] + } + + set ttext "Edit device" + set btext "Apply" + set bcmd "magic::gencell_change $gname $gencell_type $library" + } + + catch {destroy .params} + toplevel .params + label .params.title -text "$ttext $gname" + frame .params.edits + frame .params.buttons + pack .params.title + pack .params.edits + pack .params.buttons + + button .params.buttons.apply \ + -text "$btext" \ + -command [subst { $bcmd ; \ + .params.buttons.apply configure -text Apply}] + button .params.buttons.close -text "Close" -command {destroy .params} + + pack .params.buttons.apply -padx 10 -side left + pack .params.buttons.close -padx 10 -side right + + # Invoke the callback procedure that creates the parameter entries + + eval "${library}::${gencell_type}_params $gname" +} + +#------------------------------------------------------------- diff --git a/tcltk/tools.tcl b/tcltk/tools.tcl new file mode 100644 index 00000000..3b20f7ba --- /dev/null +++ b/tcltk/tools.tcl @@ -0,0 +1,696 @@ +#------------------------------------------------------- +# Useful tools for the Tcl-based version of magic +#------------------------------------------------------- +# This file is included by wrapper.tcl if it is found +# in the magic install directory. +#------------------------------------------------------- + +# Suspend and resume drawing in windows +# Modified 8/17/04 so that calls to suspendall and resumeall +# may nest. +# Modified 11/23/16 +# Modified 12/30/16 to add automatic button accelerator text + +proc magic::suspendall {} { + global Winopts + if {[info commands winfo] != ""} { + foreach window [magic::windownames layout] { + set framename [winfo toplevel $window] + if {$framename == "."} { + set framename $window + } + if {[incr Winopts(${framename},suspend)] == 1} { + $window update suspend + } + } + } +} + +proc magic::resumeall {} { + global Winopts + if {[info commands winfo] != ""} { + foreach window [magic::windownames layout] { + set framename [winfo toplevel $window] + if {$framename == "."} { + set framename $window + } + if {$Winopts($framename,suspend) <= 0} { + error "resume called without suspend" + } else { + incr Winopts($framename,suspend) -1 + if { $Winopts(${framename},suspend) <= 0 } { + unset Winopts(${framename},suspend) + $window update resume + } + } + } + } +} + +#-------------------------------------------------------------------------- +# Crash backups. Create a new crash recovery backup every 10 minutes, or +# at the interval specified by Opts(backupinterval) +#-------------------------------------------------------------------------- + +proc magic::makecrashbackup {} { + global Opts + + crash save + if {$Opts(backupinterval) > 0} { + after $Opts(backupinterval) magic::makecrashbackup + } +} + +proc magic::crashbackups {{option start}} { + global Opts + + switch -exact $option { + start { + if {[catch set Opts(backupinterval)]} { + set Opts(backupinterval) 600000 + } + after $Opts(backupinterval) magic::makecrashbackup + } + stop - + cancel { + after cancel magic::makecrashbackup + } + } +} + +#-------------------------------------------------------------------------- +# Push and Pop---Treat the edit hierarchy like a stack. +#-------------------------------------------------------------------------- + +proc magic::pushstack {{name ""}} { + global editstack + if {$name == ""} { + # no cell selected, so see if we can select one + set selected [what -list] + if {[llength [lindex $selected 2]] == 0} { + pushbox + select cell + popbox + } + set name [cellname list self] + } + + if {$name == ""} { + error "No cell to push!" + } elseif {[llength $name] > 1} { + error "Too many cells selected!" + } + if {[catch {lindex $editstack end}]} { + set editstack {} + } + lappend editstack [view get] + lappend editstack [cellname list window] + set ltag [tag load] + tag load {} + load $name + catch {magic::cellmanager} + catch {magic::captions} + tag load $ltag + return +} + +proc magic::popstack {} { + global editstack + if {[llength $editstack] == 0} { + error "No subcell stack!" + } else { + set ltag [tag load] + tag load {} + load [lindex $editstack end] + view [lindex $editstack end-1] + tag load $ltag + set editstack [lrange $editstack 0 end-2] + catch {magic::cellmanager} + catch {magic::captions} + } + return +} + +proc magic::clearstack {} { + global editstack + set editstack {} +} + +# More stacking stuff---stacked box values + +#--------------------------------------------------------------------- +# pushbox -- +# Remember the current box values +# +#--------------------------------------------------------------------- + +proc magic::pushbox {{values {}}} { + global boxstack + set snaptype [snap list] + snap internal + if {[catch {set boxstack}]} { + set boxstack {} + } + if {$values == {}} { + lappend boxstack [box values] + } else { + lappend boxstack $values + } + snap $snaptype + return +} + +#--------------------------------------------------------------------- +# popbox -- +# Recall the last pushed box position +# +# Option "type" may be empty, or "size" or "position" to pop a specific +# box size or position without affecting the other box parameters. +#--------------------------------------------------------------------- + +proc magic::popbox {{type values}} { + global boxstack + set snaptype [snap list] + snap internal + if {[catch {set boxstack}]} { + error "No stack" + } elseif {$boxstack == {}} { + error "Empty stack" + } + set b [lindex $boxstack end] + switch -exact $type { + values { + box values [lindex $b 0] [lindex $b 1] [lindex $b 2] [lindex $b 3] + } + size { + box size [expr {[lindex $b 2] - [lindex $b 0]}] \ + [expr {[lindex $b 3] - [lindex $b 1]}] + } + position { + box position [lindex $b 0] [lindex $b 1] + } + } + set boxstack [lrange $boxstack 0 end-1] + snap $snaptype + return $b +} + +#--------------------------------------------------------------------- +# peekbox -- +# Shell procedure that calls popbox but follows by pushing the +# popped value back onto the stack, resulting in a "peek" mode. +# +# Options are the same as for "popbox" (see above). +#--------------------------------------------------------------------- + +proc magic::peekbox {{type values}} { + global bidx + if {![catch {set b [magic::popbox $type]}]} { + magic::pushbox $b + } else { + error "No stack" + } + return $b +} + +#--------------------------------------------------------------------- +# Automatic handling of menu button accelerator text +#--------------------------------------------------------------------- + +proc magic::button_auto_bind_text {framename} { + set macrolist [string trimleft [string trimright \ + [string map {magic:: {}} [macro list -reverse]]]] + set macrodict [dict create {*}${macrolist}] + set menutop [winfo children ${framename}.titlebar.mbuttons] + foreach menub $menutop { + set menuw [lindex [winfo children $menub] 0] + set items [$menuw index end] + for {set i 0} {$i <= $items} {incr i} { + set itype [$menuw type $i] + if {$itype == "command"} { + set icmd [string trimleft [string trimright \ + [string map {magic:: {}} [$menuw entrycget $i -command]]]] + if {![catch {set keyname [dict get $macrodict $icmd]}]} { + set canonname [string map \ + {Control_ ^ XK_ {} less < more > comma , question ?}\ + $keyname] + $menuw entryconfigure $i -accelerator "(${canonname})" + } else { + $menuw entryconfigure $i -accelerator "" + } + } + } + } +} + +#--------------------------------------------------------------------- +# Text auto-increment and auto-decrement +#--------------------------------------------------------------------- + +proc magic::autoincr {{amount 1}} { + set mtext [macro list .] + set num [regexp -inline {[+-]*[[:digit:]]+} $mtext] + if {$num != ""} { + incr num $amount + regsub {[+-]*[[:digit:]]+} $mtext $num mtext + eval $mtext + macro . "$mtext" + } +} + +magic::macro XK_plus {magic::autoincr 1} +magic::macro XK_minus {magic::autoincr -1} + +#--------------------------------------------------------------------- +# The following several routines are designed to aid in generating +# documentation for technology files, or to generate design rule +# documents using magic layout windows in a Tk tabbed-window +# framework. +#--------------------------------------------------------------------- + +#--------------------------------------------------------------------- +# Ruler generation using the "element" command +# A line with arrows is drawn showing the dimension of the cursor box. +# The text of "text", if non-NULL, is placed in the middle of the +# ruler area. The orientation of "orient" describes whether the +# ruler is a vertical or horizontal measurement. By default, the +# longest dimension of the box is the orientation. +#--------------------------------------------------------------------- + +proc magic::ruler {{text {}} {orient auto}} { + global Opts + + if {[catch {set Opts(rulers)}]} { + set Opts(rulers) 0 + } else { + incr Opts(rulers) + } + + set bv [box values] + set llx [lindex $bv 0] + set lly [lindex $bv 1] + set urx [lindex $bv 2] + set ury [lindex $bv 3] + + set width [expr {[lindex $bv 2] - [lindex $bv 0]}] + set height [expr {[lindex $bv 3] - [lindex $bv 1]}] + if {$orient == "auto"} { + if {$width > $height} { + set orient "horizontal" + } else { + set orient "vertical" + } + } + + if {[llength $text] > 0} { + if {$orient == "horizontal"} { + set tclr 4 + } else { + set tclr 2 + } + } else { + set tclr 0 + } + + set mmx [expr {($llx + $urx) / 2}] + set mmy [expr {($lly + $ury) / 2}] + + if {$orient == "horizontal"} { + element add line l1_$Opts(rulers) black $llx $lly $llx $ury + element add line l4_$Opts(rulers) black $urx $lly $urx $ury + + set mmx1 [expr {$mmx - $tclr}] + set mmx2 [expr {$mmx + $tclr}] + if {$mmx1 == $llx} {set mmx1 [expr {$llx - 2}]} + if {$mmx2 == $urx} {set mmx2 [expr {$urx + 2}]} + + element add line l2_$Opts(rulers) black $llx $mmy $mmx1 $mmy + element add line l3_$Opts(rulers) black $mmx2 $mmy $urx $mmy + + if {$tclr > 0} { + element add text t_$Opts(rulers) black $mmx $mmy $text + } + if {$llx < $mmx1} { + element configure l2_$Opts(rulers) flags arrowleft + } else { + element configure l2_$Opts(rulers) flags arrowright + } + if {$urx > $mmx2} { + element configure l3_$Opts(rulers) flags arrowright + } else { + element configure l3_$Opts(rulers) flags arrowleft + } + + } else { + element add line l1_$Opts(rulers) black $llx $lly $urx $lly + element add line l4_$Opts(rulers) black $llx $ury $urx $ury + + set mmy1 [expr {$mmy - $tclr}] + set mmy2 [expr {$mmy + $tclr}] + if {$mmy1 == $lly} {set mmy1 [expr {$lly - 2}]} + if {$mmy2 == $ury} {set mmy2 [expr {$ury + 2}]} + + element add line l2_$Opts(rulers) black $mmx $lly $mmx $mmy1 + element add line l3_$Opts(rulers) black $mmx $mmy2 $mmx $ury + + if {$tclr > 0} { + element add text t_$Opts(rulers) black $mmx $mmy $text + } + if {$lly < $mmy1} { + element configure l2_$Opts(rulers) flags arrowbottom + } else { + element configure l2_$Opts(rulers) flags arrowtop + } + if {$ury > $mmy2} { + element configure l3_$Opts(rulers) flags arrowtop + } else { + element configure l3_$Opts(rulers) flags arrowbottom + } + } +} + +#--------------------------------------------------------------------- +# Automatic measurement ruler +#--------------------------------------------------------------------- + +proc magic::measure {{orient auto}} { + + set scale [cif scale out] + + set bv [box values] + set llx [lindex $bv 0] + set lly [lindex $bv 1] + set urx [lindex $bv 2] + set ury [lindex $bv 3] + + set width [expr {[lindex $bv 2] - [lindex $bv 0]}] + set height [expr {[lindex $bv 3] - [lindex $bv 1]}] + if {$orient == "auto"} { + if {$width > $height} { + set orient "horizontal" + } else { + set orient "vertical" + } + } + + if {$orient == "horizontal"} { + set tval [expr {$scale * $width}] + } else { + set tval [expr {$scale * $height}] + } + set text [format "%g um" $tval] + ruler $text $orient +} + +#--------------------------------------------------------------------- +# Remove all rulers (this should probably be refined to remove +# just the rulers under the box). +#--------------------------------------------------------------------- + +proc magic::unmeasure {} { + set blist [element inbox] + set mlist {} + foreach m $blist { + switch -regexp $m { + l[1-4]_[0-9] { + lappend mlist [string range $m 3 end] + } + t_[0-9] { + lappend mlist [string range $m 2 end] + } + } + } + set blist [lsort -unique $mlist] + foreach m $blist { + element delete t_$m + element delete l1_$m + element delete l2_$m + element delete l3_$m + element delete l4_$m + } +} + +#--------------------------------------------------------------------- +# Key generation for annotating layouts. +#--------------------------------------------------------------------- + +proc magic::genkey {layer {keysize 4}} { + global Opts + + box size $keysize $keysize + paint $layer + if {[catch {set Opts(keys)}]} { + set Opts(keys) 0 + } else { + incr Opts(keys) + } + # eval "element add rectangle keyrect$Opts(keys) subcircuit [box values]" + + box move e $keysize + set bv [box values] + set cx [expr {([lindex $bv 2] + [lindex $bv 0]) / 2}] + set cy [expr {([lindex $bv 3] + [lindex $bv 1]) / 2}] + element add text key$Opts(keys) white $cx $cy $layer + element configure key$Opts(keys) flags east +} + +#--------------------------------------------------------------------- +# Because this file is read prior to setting the magic command +# names in Tcl, we cannot run the magic commands here. Create +# a procedure to enable the commands, then run that procedure +# from the system .magic script. +#--------------------------------------------------------------------- + +proc magic::enable_tools {} { + global Opts + + # Set keystrokes for push and pop + magic::macro XK_greater {magic::pushstack [cellname list self]} + magic::macro XK_less {magic::popstack} + + # Set keystrokes for the "tool" command. + magic::macro space {magic::tool} + magic::macro Shift_space {magic::tool box} + + set Opts(tool) box + set Opts(motion) {} + set Opts(origin) {0 0} + set Opts(backupinterval) 60000 + magic::crashbackups start +} + +#--------------------------------------------------------------------- +# routine which tracks wire generation +#--------------------------------------------------------------------- + +proc magic::trackwire {window {option {}}} { + global Opts + if {$Opts(motion) == {}} { + if {$option == "done"} { + wire switch + } elseif {$option == "pick"} { + puts stdout $window + wire type + set Opts(motion) [bind ${window} ] + bind ${window} [subst {$Opts(motion); *bypass wire show}] + if {$Opts(motion) == {}} {set Opts(motion) "null"} + cursor 21 + } + } else { + if {$option != "cancel"} { + wire leg + } + if {$option == "done" || $option == "cancel"} { + select clear + if {$Opts(motion) == "null"} { + bind ${window} {} + } else { + bind ${window} "$Opts(motion)" + } + set Opts(motion) {} + cursor 19 + } + } +} + +#--------------------------------------------------------------------- +# routine which tracks a selection pick +#--------------------------------------------------------------------- + +proc magic::keepselect {window} { + global Opts + if {$Opts(motion) == {}} { + box move bl cursor + } else { + select keep + } +} + +proc magic::startselect {window {option {}}} { + global Opts + if {$Opts(motion) == {}} { + if {$option == "pick"} { + select pick + } else { + set slist [what -list] + if {$slist == {{} {} {}}} { + select nocycle + } + } + set Opts(origin) [cursor] + set Opts(motion) [bind ${window} ] + bind ${window} [subst {$Opts(motion); set p \[cursor\]; \ + set x \[expr {\[lindex \$p 0\] - [lindex $Opts(origin) 0]}\]i; \ + set y \[expr {\[lindex \$p 1\] - [lindex $Opts(origin) 1]}\]i; \ + *bypass select move \${x} \${y}}] + if {$Opts(motion) == {}} {set Opts(motion) "null"} + cursor 21 + } else { + if {$Opts(motion) == "null"} { + bind ${window} {} + } else { + bind ${window} "$Opts(motion)" + } + copy center 0 + set Opts(motion) {} + cursor 22 + } +} + +proc magic::cancelselect {window} { + global Opts + if {$Opts(motion) == {}} { + box corner ur cursor + } else { + if {$Opts(motion) == "null"} { + bind ${window} {} + } else { + bind ${window} "$Opts(motion)" + } + select clear + set Opts(motion) {} + cursor 22 + } +} + +#--------------------------------------------------------------------- +# tool --- A scripted replacement for the "tool" +# command, as handling of button events has been modified +# to act like the handling of key events, so the "tool" +# command just swaps macros for the buttons. +# +# Added By NP 10/27/2004 +#--------------------------------------------------------------------- + +proc magic::tool {{type next}} { + global Opts + + # Don't attempt to switch tools while a selection drag is active + if {$Opts(motion) != {}} { + return + } + + if {$type == "next"} { + switch $Opts(tool) { + box { set type wiring } + wiring { set type netlist } + netlist { set type pick } + pick { set type box } + } + } + switch $type { + info { + # print information about the current tool. + puts stdout "Current tool is $Opts(tool)." + puts stdout "Button command bindings:" + if {[llength [macro Button1]] > 0} { + macro Button1 + } + if {[llength [macro Button2]] > 0} { + macro Button2 + } + if {[llength [macro Button3]] > 0} { + macro Button3 + } + if {[llength [macro Shift_Button1]] > 0} { + macro Shift_Button1 + } + if {[llength [macro Shift_Button2]] > 0} { + macro Shift_Button2 + } + if {[llength [macro Shift_Button3]] > 0} { + macro Shift_Button3 + } + if {[llength [macro Control_Button1]] > 0} { + macro Control_Button1 + } + if {[llength [macro Control_Button2]] > 0} { + macro Control_Button2 + } + if {[llength [macro Control_Button3]] > 0} { + macro Control_Button3 + } + } + box { + puts stdout {Switching to BOX tool.} + set Opts(tool) box + cursor 0 ;# sets the cursor + macro Button1 "box move bl cursor; magic::boxview %W %1" + macro Shift_Button1 "box corner bl cursor; magic::boxview %W %1" + macro Button2 "paint cursor" + macro Shift_Button2 "erase cursor" + macro Button3 "box corner ur cursor" + macro Shift_Button3 "box move ur cursor; magic::boxview %W %1" + macro Button4 "scroll u .05 w; magic::boxview %W %1" + macro Button5 "scroll d .05 w; magic::boxview %W %1" + macro Shift_XK_Pointer_Button4 "scroll r .05 w; magic::boxview %W %1" + macro Shift_XK_Pointer_Button5 "scroll l .05 w; magic::boxview %W %1" + + } + wiring { + puts stdout {Switching to WIRING tool.} + set Opts(tool) wiring + cursor 19 ;# sets the cursor + macro Button1 "magic::trackwire %W pick" + macro Button2 "magic::trackwire %W done" + macro Button3 "magic::trackwire %W cancel" + macro Shift_Button1 "wire incr type" + macro Shift_Button2 "wire switch" + macro Shift_Button3 "wire decr type" + macro Button4 "wire incr width" + macro Button5 "wire decr width" + + } + netlist { + puts stdout {Switching to NETLIST tool.} + set Opts(tool) netlist + cursor 18 ;# sets the cursor + macro Button1 "netlist select" + macro Button2 "netlist join" + macro Button3 "netlist terminal" + # Remove shift-button bindings + macro Shift_Button1 "" + macro Shift_Button2 "" + macro Shift_Button3 "" + macro Button4 "scroll u .05 w" + macro Button5 "scroll d .05 w" + } + pick { + puts stdout {Switching to PICK tool.} + set Opts(tool) pick + cursor 22 ;# set the cursor + macro Button1 "magic::keepselect %W" + macro Shift_Button2 "magic::startselect %W copy" + macro Button2 "magic::startselect %W pick" + macro Button3 "magic::cancelselect %W" + macro Shift_Button1 "box corner bl cursor" + macro Shift_Button3 "box move ur cursor" + macro Button4 "scroll u .05 w" + macro Button5 "scroll d .05 w" + } + } + + # Update window captions with the new tool info + catch {magic::captions} + return +} diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl new file mode 100644 index 00000000..8d7e3582 --- /dev/null +++ b/tcltk/wrapper.tcl @@ -0,0 +1,1586 @@ +# This is the "Magic wrapper". +# It's main purpose is to redefine the "openwindow" command in magic so that +# opening a new window creates a window wrapped by a GUI interface. +# +# Written by Tim Edwards, August 23, 2002. + +# revision A: proof-of-concept. Add whatever you want to this basic wrapper. +# revision B: Adds Tk scrollbars and caption +# revision C: Adds a layer manager toolbar on the left side +# revision D: Adds a menubar on top with cell and tech manager tools + +global lwindow +global tk_version +global Glyph +global Opts +global Winopts + +set tk_version $::tk_version +# Simple console commands (like TkCon, but much simpler) + +if {[lsearch [namespace children] ::tkshell] < 0} { + catch {source ${CAD_ROOT}/magic/tcl/tkshell.tcl} +} + +# Button images + +set Glyph(up) [image create bitmap \ + -file ${CAD_ROOT}/magic/tcl/bitmaps/up.xbm \ + -background gray -foreground steelblue] +set Glyph(down) [image create bitmap \ + -file ${CAD_ROOT}/magic/tcl/bitmaps/down.xbm \ + -background gray -foreground steelblue] +set Glyph(left) [image create bitmap \ + -file ${CAD_ROOT}/magic/tcl/bitmaps/left.xbm \ + -background gray -foreground steelblue] +set Glyph(right) [image create bitmap \ + -file ${CAD_ROOT}/magic/tcl/bitmaps/right.xbm \ + -background gray -foreground steelblue] +set Glyph(zoom) [image create bitmap \ + -file ${CAD_ROOT}/magic/tcl/bitmaps/zoom.xbm \ + -background gray -foreground steelblue] +set Glyph(lock) [image create bitmap \ + -file ${CAD_ROOT}/magic/tcl/bitmaps/lock.xbm \ + -background gray80 -foreground steelblue4] + +# Menu button callback functions + +proc magic::promptload {type} { + global CAD_ROOT + + switch $type { + cif { set Layoutfilename [ tk_getOpenFile -filetypes \ + {{CIF {.cif {.cif}}} {"All files" {*}}}] + if {$Layoutfilename != ""} { + set cifname [file tail [file root $Layoutfilename]] + magic::cellname create cif_temp + magic::load cif_temp + magic::cif read [file root $Layoutfilename] + set childcells [magic::cellname list children cif_temp] + magic::load [lindex $childcells 0] + magic::cellname delete cif_temp -noprompt + if {[llength $childcells] > 1} { + puts stdout "Cells read from GDS file: $childcells" + } + } + } + gds { set Layoutfilename [ tk_getOpenFile -filetypes \ + {{GDS {.gds .strm .cal {.gds .strm .cal}}} {"All files" {*}}}] + if {$Layoutfilename != ""} { + set origlist [magic::cellname list top] + magic::gds read [file root $Layoutfilename] + set newlist [magic::cellname list top] + + # Find entries in newlist that are not in origlist. + # If there's only one, load it into the window. + + set newtopcells {} + foreach n $newlist { + if {[lsearch $origlist $n] < 0} { + lappend newtopcells $n + } + } + if {[llength $newtopcells] == 1} { + magic::load [lindex $newtopcells 0] + } elseif {[llength $newtopcells] != 0} { + puts stdout "Top-level cells read from GDS file: $newtopcells" + } + } + } + magic { set Layoutfilename [ tk_getOpenFile -filetypes \ + {{Magic {.mag {.mag}}} {"All files" {*}}}] + if {$Layoutfilename != ""} { + magic::load [file root $Layoutfilename] + } + } + + getcell { set Layoutfilename [ tk_getOpenFile -filetypes \ + {{Magic {.mag {.mag}}} {"All files" {*}}}] + if {$Layoutfilename != ""} { + set fdir [file dirname $Layoutfilename] + set lidx [lsearch [path search] $fdir] + if {$lidx < 0} {path search +$fdir} + magic::getcell [file tail $Layoutfilename] + + # Append path to cell search path if it's not there already + + if {[string index $Layoutfilename 0] != "/"} { + set $Layoutfilename "./$Layoutfilename" + } + set sidx [string last "/" $Layoutfilename] + if {$sidx > 0} { + set cellpath [string range $Layoutfilename 0 $sidx] + magic::path cell +$cellpath + } + } + } + } +} + +proc magic::promptsave {type} { + global CAD_ROOT + + switch $type { + cif { set Layoutfilename [ tk_getSaveFile -filetypes \ + {{CIF {.cif {.cif}}} {"All files" {*}}}] + if {$Layoutfilename != ""} { + magic::cif write $Layoutfilename + } + } + gds { set Layoutfilename [ tk_getSaveFile -filetypes \ + {{GDS {.gds .strm .cal {.gds .strm .cal}}} {"All files" {*}}}] + if {$Layoutfilename != ""} { + magic::gds write $Layoutfilename + } + } + force - + magic { + set CellList [ magic::cellname list window ] + if {[lsearch $CellList "(UNNAMED)"] >= 0} { + set Layoutfilename [ tk_getSaveFile -filetypes \ + {{Magic {.mag {.mag}}} {"All files" {*}}} \ + -title "Save cell (UNNAMED) as:" ] + if {$Layoutfilename != ""} { + set cellpath [file dirname $Layoutfilename] + if {$cellpath == [pwd]} { + set Layoutfilename [file tail $Layoutfilename] + } else { + magic::path cell +$cellpath + } + magic::save $Layoutfilename + } + } + if {$type == "force"} { + magic::writeall force + } else { + magic::writeall + } + } + } +} + +# Window to prompt for a new cell + +proc magic::prompt_dialog { type } { + global Opts + + if {[catch {toplevel .dialog}]} { + foreach child [winfo children .dialog] { + destroy $child + } + } + + frame .dialog.titlebar + frame .dialog.text + frame .dialog.bbar + + switch $type { + new { + label .dialog.titlebar.title -text "Create new cell" -foreground blue + button .dialog.bbar.okay -text "Okay" -command {load $Opts(cell_name); \ + lower .dialog} + set Opts(cell_name) "(UNNAMED)" + } + save { + label .dialog.titlebar.title -text "Save cell as..." -foreground blue + button .dialog.bbar.okay -text "Okay" -command {save $Opts(cell_name); \ + lower .dialog} + set Opts(cell_name) [cellname list window] + } + } + pack .dialog.titlebar.title + + label .dialog.text.tlabel -text "Cell name:" -foreground brown + entry .dialog.text.tentry -background white -textvariable Opts(cell_name) + + pack .dialog.text.tlabel -side left + pack .dialog.text.tentry -side left + + button .dialog.bbar.cancel -text "Cancel" -command "lower .dialog" + + pack .dialog.bbar.okay -side left + pack .dialog.bbar.cancel -side right + + pack .dialog.titlebar -side top -ipadx 2 -ipady 2 + pack .dialog.text -side top -fill both -expand true + pack .dialog.bbar -side top -fill x -ipadx 5 + + bind .dialog.text.tentry {.dialog.bbar.okay invoke} + + raise .dialog +} + +# Callback functions used by the DRC. + +proc magic::drcupdate { option } { + global Opts + if {[info level] <= 1} { + switch $option { + on {set Opts(drc) 1} + off {set Opts(drc) 0} + } + } +} + +proc magic::drcstate { status } { + set winlist [*bypass windownames layout] + foreach lwin $winlist { + set framename [winfo parent $lwin] + if {$framename == "."} {return} + switch $status { + idle { + set dct [*bypass drc list count total] + if {$dct > 0} { + ${framename}.titlebar.drcbutton configure -selectcolor red + } else { + ${framename}.titlebar.drcbutton configure -selectcolor green + } + ${framename}.titlebar.drcbutton configure -text "DRC=$dct" + } + busy { ${framename}.titlebar.drcbutton configure -selectcolor yellow } + } + } +} + +# Create the menu of windows. This is kept separate from the cell manager, +# and linked into it by the "clone" command. + +menu .winmenu -tearoff 0 + +proc magic::setgrid {gridsize} { + set techlambda [magic::tech lambda] + set tech1 [lindex $techlambda 1] + set tech0 [lindex $techlambda 0] + set tscale [expr {$tech1 / $tech0}] + set lambdaout [expr {[magic::cif scale output] * $tscale}] + set gridlambda [expr {$gridsize/$lambdaout}] + magic::grid ${gridlambda}l + magic::snap on +} + +# Technology manager callback functions + +proc magic::techparseunits {} { + set techlambda [magic::tech lambda] + set tech1 [lindex $techlambda 1] + set tech0 [lindex $techlambda 0] + + set target0 [.techmgr.lambda1.lval0 get] + set target1 [.techmgr.lambda1.lval1 get] + + set newval0 [expr {$target0 * $tech0}] + set newval1 [expr {$target1 * $tech1}] + + magic::scalegrid $newval1 $newval0 + magic::techmanager update +} + +# The technology manager + +proc magic::maketechmanager { mgrpath } { + toplevel $mgrpath + wm withdraw $mgrpath + + frame ${mgrpath}.title + label ${mgrpath}.title.tlab -text "Technology: " + menubutton ${mgrpath}.title.tname -text "(none)" -foreground red3 \ + -menu ${mgrpath}.title.tname.menu + label ${mgrpath}.title.tvers -text "" -foreground blue + label ${mgrpath}.subtitle -text "" -foreground sienna4 + + frame ${mgrpath}.lambda0 + label ${mgrpath}.lambda0.llab -text "Microns per lambda (CIF): " + label ${mgrpath}.lambda0.lval -text "1" -foreground blue + + frame ${mgrpath}.lambda1 + label ${mgrpath}.lambda1.llab -text "Internal units per lambda: " + entry ${mgrpath}.lambda1.lval0 -foreground red3 -background white -width 3 + label ${mgrpath}.lambda1.ldiv -text " / " + entry ${mgrpath}.lambda1.lval1 -foreground red3 -background white -width 3 + + frame ${mgrpath}.cif0 + label ${mgrpath}.cif0.llab -text "CIF input style: " + menubutton ${mgrpath}.cif0.lstyle -text "" -foreground blue \ + -menu ${mgrpath}.cif0.lstyle.menu + label ${mgrpath}.cif0.llab2 -text " Microns/lambda=" + label ${mgrpath}.cif0.llambda -text "" -foreground red3 + + frame ${mgrpath}.cif1 + label ${mgrpath}.cif1.llab -text "CIF output style: " + menubutton ${mgrpath}.cif1.lstyle -text "" -foreground blue \ + -menu ${mgrpath}.cif1.lstyle.menu + label ${mgrpath}.cif1.llab2 -text " Microns/lambda=" + label ${mgrpath}.cif1.llambda -text "" -foreground red3 + + frame ${mgrpath}.extract + label ${mgrpath}.extract.llab -text "Extract style: " + menubutton ${mgrpath}.extract.lstyle -text "" -foreground blue \ + -menu ${mgrpath}.extract.lstyle.menu + + frame ${mgrpath}.drc + label ${mgrpath}.drc.llab -text "DRC style: " + menubutton ${mgrpath}.drc.lstyle -text "" -foreground blue \ + -menu ${mgrpath}.drc.lstyle.menu + + pack ${mgrpath}.title.tlab -side left + pack ${mgrpath}.title.tname -side left + pack ${mgrpath}.title.tvers -side left + pack ${mgrpath}.lambda0.llab -side left + pack ${mgrpath}.lambda0.lval -side left + pack ${mgrpath}.lambda1.llab -side left + pack ${mgrpath}.lambda1.lval0 -side left + pack ${mgrpath}.lambda1.ldiv -side left + pack ${mgrpath}.lambda1.lval1 -side left + pack ${mgrpath}.cif0.llab -side left + pack ${mgrpath}.cif0.lstyle -side left + pack ${mgrpath}.cif0.llab2 -side left + pack ${mgrpath}.cif0.llambda -side left + pack ${mgrpath}.cif1.llab -side left + pack ${mgrpath}.cif1.lstyle -side left + pack ${mgrpath}.cif1.llab2 -side left + pack ${mgrpath}.cif1.llambda -side left + pack ${mgrpath}.extract.llab -side left + pack ${mgrpath}.extract.lstyle -side left + pack ${mgrpath}.drc.llab -side left + pack ${mgrpath}.drc.lstyle -side left + + pack ${mgrpath}.title -side top -fill x + pack ${mgrpath}.subtitle -side top -fill x + pack ${mgrpath}.lambda0 -side top -fill x + pack ${mgrpath}.lambda1 -side top -fill x + pack ${mgrpath}.cif0 -side top -fill x + pack ${mgrpath}.cif1 -side top -fill x + pack ${mgrpath}.extract -side top -fill x + + bind ${mgrpath}.lambda1.lval0 magic::techparseunits + bind ${mgrpath}.lambda1.lval1 magic::techparseunits + + #Withdraw the window when the close button is pressed + wm protocol ${mgrpath} WM_DELETE_WINDOW "set Opts(techmgr) 0 ; wm withdraw ${mgrpath}" +} + +# Generate the cell manager + +catch {source ${CAD_ROOT}/magic/tcl/cellmgr.tcl} + +# Generate the text helper + +catch {source ${CAD_ROOT}/magic/tcl/texthelper.tcl} + +# Create or redisplay the technology manager + +proc magic::techmanager {{option "update"}} { + global CAD_ROOT + + if {[catch {wm state .techmgr}]} { + if {$option == "create"} { + magic::maketechmanager .techmgr + } else { + return + } + } elseif { $option == "create"} { + return + } + + if {$option == "create"} { + menu .techmgr.title.tname.menu -tearoff 0 + menu .techmgr.cif0.lstyle.menu -tearoff 0 + menu .techmgr.cif1.lstyle.menu -tearoff 0 + menu .techmgr.extract.lstyle.menu -tearoff 0 + menu .techmgr.drc.lstyle.menu -tearoff 0 + + } + + if {$option == "init"} { + .techmgr.title.tname.menu delete 0 end + .techmgr.cif0.lstyle.menu delete 0 end + .techmgr.cif1.lstyle.menu delete 0 end + .techmgr.extract.lstyle.menu delete 0 end + .techmgr.drc.lstyle.menu delete 0 end + } + + if {$option == "init" || $option == "create"} { + set tlist [magic::cif listall istyle] + foreach i $tlist { + .techmgr.cif0.lstyle.menu add command -label $i -command \ + "magic::cif istyle $i ; \ + magic::techmanager update" + } + + set tlist [magic::cif listall ostyle] + foreach i $tlist { + .techmgr.cif1.lstyle.menu add command -label $i -command \ + "magic::cif ostyle $i ; \ + magic::techmanager update" + } + + set tlist [magic::extract listall style] + foreach i $tlist { + .techmgr.extract.lstyle.menu add command -label $i -command \ + "magic::extract style $i ; \ + magic::techmanager update" + } + + set tlist [magic::drc listall style] + foreach i $tlist { + .techmgr.drc.lstyle.menu add command -label $i -command \ + "magic::drc style $i ; \ + magic::techmanager update" + } + + set dirlist [subst [magic::path sys]] + set tlist {} + foreach i $dirlist { + lappend tlist [glob -nocomplain ${i}/*.tech] + lappend tlist [glob -nocomplain ${i}/*.tech27] + } + foreach i [join $tlist] { + set j [file tail [file rootname ${i}]] + .techmgr.title.tname.menu add command -label $j -command \ + "magic::tech load $j ; \ + magic::techmanager update" + } + } + + set techlambda [magic::tech lambda] + set tech1 [lindex $techlambda 1] + set tech0 [lindex $techlambda 0] + set tscale [expr {$tech1 / $tech0}] + + .techmgr.title.tname configure -text [magic::tech name] + set techstuff [magic::tech version] + .techmgr.title.tvers configure -text "(version [lindex $techstuff 0])" + .techmgr.subtitle configure -text [lindex $techstuff 1] + set lotext [format "%g" [expr {[magic::cif scale output] * $tscale}]] + .techmgr.lambda0.lval configure -text $lotext + .techmgr.cif0.lstyle configure -text [magic::cif list istyle] + set litext [format "%g" [expr {[magic::cif scale input] * $tscale}]] + .techmgr.cif0.llambda configure -text $litext + .techmgr.cif1.lstyle configure -text [magic::cif list ostyle] + .techmgr.cif1.llambda configure -text $lotext + .techmgr.extract.lstyle configure -text [magic::extract list style] + .techmgr.drc.lstyle configure -text [magic::drc list style] + + .techmgr.lambda1.lval0 delete 0 end + .techmgr.lambda1.lval1 delete 0 end + .techmgr.lambda1.lval0 insert end $tech1 + .techmgr.lambda1.lval1 insert end $tech0 +} + +proc magic::captions {{subcommand {}}} { + global Opts + + if {$subcommand != {} && $subcommand != "writeable" && $subcommand != "load"} { + return + } + set winlist [magic::windownames layout] + foreach winpath $winlist { + set framename [winfo parent $winpath] + set caption [$winpath windowcaption] + set subcaption1 [lindex $caption 0] + set techname [tech name] + if {[catch {set Opts(tool)}]} { + set Opts(tool) unknown + } + if {[lindex $caption 1] == "EDITING"} { + set subcaption2 [lindex $caption 2] + } else { + # set subcaption2 [join [lrange $caption 1 end]] + set subcaption2 $caption + } + ${framename}.titlebar.caption configure -text \ + "Loaded: ${subcaption1} Editing: ${subcaption2} Tool: $Opts(tool) \ + Technology: ${techname}" + } +} + +# Allow captioning in the title window by tagging the "load" and "edit" commands +# Note that the "box" tag doesn't apply to mouse-button events, so this function +# is duplicated by Tk binding of mouse events in the layout window. + +magic::tag load "[magic::tag load]; magic::captions" +magic::tag edit "magic::captions" +magic::tag save "magic::captions" +magic::tag down "magic::captions" +magic::tag box "magic::boxview %W %1" +magic::tag move "magic::boxview %W" +magic::tag scroll "magic::scrollupdate %W" +magic::tag view "magic::scrollupdate %W" +magic::tag zoom "magic::scrollupdate %W" +magic::tag findbox "magic::scrollupdate %W" +magic::tag see "magic::toolupdate %W %1 %2" +magic::tag tech "magic::techrebuild %W %1; magic::captions %1" +magic::tag drc "magic::drcupdate %1" +magic::tag path "magic::techmanager update" +magic::tag cellname "magic::mgrupdate %W %1" +magic::tag cif "magic::mgrupdate %W %1" +magic::tag gds "magic::mgrupdate %W %1" + +# This should be a list. . . do be done later +set lwindow 0 +set owindow 0 + +set Opts(techmgr) 0 +set Opts(target) default +set Opts(netlist) 0 +set Opts(colormap) 0 +set Opts(wind3d) 0 +set Opts(crosshair) 0 +set Opts(hidelocked) 0 +set Opts(hidespecial) 0 +set Opts(toolbar) 0 +set Opts(drc) 1 +set Opts(autobuttontext) 1 + +# Update cell and tech managers in response to a cif or gds read command + +proc magic::mgrupdate {win {cmdstr ""}} { + if {${cmdstr} == "read"} { + catch {magic::cellmanager} + magic::captions + magic::techmanager update + } elseif {${cmdstr} == "delete" || ${cmdstr} == "rename"} { + catch {magic::cellmanager} + magic::captions + } elseif {${cmdstr} == "writeable"} { + magic::captions + } +} + +# Set default width and height to be 3/4 of the screen size. +set Opts(geometry) \ +"[expr 3 * [winfo screenwidth .] / 4]x[expr 3 * [winfo screenheight .] \ +/ 4]+100+100" + +# Procedures for the layout scrollbars, which are made from canvas +# objects to avoid the problems associated with Tk's stupid scrollbar +# implementation. + +# Repainting function for scrollbars, title, etc., to match the magic +# Change the colormap (most useful in 8-bit PseudoColor) + +proc magic::repaintwrapper { win } { + set bgcolor [magic::magiccolor -] + ${win}.xscroll configure -background $bgcolor + ${win}.xscroll configure -highlightbackground $bgcolor + ${win}.xscroll configure -highlightcolor [magic::magiccolor K] + + ${win}.yscroll configure -background $bgcolor + ${win}.yscroll configure -highlightbackground $bgcolor + ${win}.yscroll configure -highlightcolor [magic::magiccolor K] + + ${win}.titlebar.caption configure -background [magic::magiccolor w] + ${win}.titlebar.caption configure -foreground [magic::magiccolor c] + + ${win}.titlebar.message configure -background [magic::magiccolor w] + ${win}.titlebar.message configure -foreground [magic::magiccolor c] + + ${win}.titlebar.pos configure -background [magic::magiccolor w] + ${win}.titlebar.pos configure -foreground [magic::magiccolor c] + +} + +# Coordinate display callback function +# Because "box" calls "box", use the "info level" command to avoid +# infinite recursion. + +proc magic::boxview {win {cmdstr ""}} { + if {${cmdstr} == "exists" || ${cmdstr} == "help" || ${cmdstr} == ""} { + # do nothing. . . informational only, no change to the box + } elseif {[info level] <= 1} { + # For NULL window, find all layout windows and apply update to each. + if {$win == {}} { + set winlist [magic::windownames layout] + foreach lwin $winlist { + magic::boxview $lwin + } + return + } + + set framename [winfo parent $win] + if {$framename == "."} {return} + if {[catch {set cr [cif scale out]}]} {return} + set bval [${win} box values] + set bllx [expr {[lindex $bval 0] * $cr }] + set blly [expr {[lindex $bval 1] * $cr }] + set burx [expr {[lindex $bval 2] * $cr }] + set bury [expr {[lindex $bval 3] * $cr }] + if {[expr {$bllx == int($bllx)}]} {set bllx [expr {int($bllx)}]} + if {[expr {$blly == int($blly)}]} {set blly [expr {int($blly)}]} + if {[expr {$burx == int($burx)}]} {set burx [expr {int($burx)}]} + if {[expr {$bury == int($bury)}]} {set bury [expr {int($bury)}]} + set titletext [format "box (%+g %+g) to (%+g %+g) microns" \ + $bllx $blly $burx $bury] + ${framename}.titlebar.pos configure -text $titletext + } +} + +proc magic::cursorview {win} { + global Opts + if {$win == {}} { + return + } + set framename [winfo parent $win] + if {[catch {set cr [cif scale out]}]} {return} + if {$cr == 0} {return} + set olst [${win} cursor internal] + + set olstx [expr [lindex $olst 0]] + set olsty [expr [lindex $olst 1]] + + if {$Opts(crosshair)} { + *bypass crosshair ${olstx}i ${olsty}i + } + + # Use catch, because occasionally this fails on startup + if {[catch { + set olstx [expr $olstx * $cr] + set olsty [expr $olsty * $cr] + }]} {return} + + if {[${win} box exists]} { + set dlst [${win} box position] + set dx [expr {$olstx - ([lindex $dlst 0]) * $cr }] + set dy [expr {$olsty - ([lindex $dlst 1]) * $cr }] + if {[expr {$dx == int($dx)}]} {set dx [expr {int($dx)}]} + if {[expr {$dy == int($dy)}]} {set dy [expr {int($dy)}]} + set titletext [format "(%+g %+g) %+g %+g microns" $olstx $olsty $dx $dy] + ${framename}.titlebar.pos configure -text $titletext + } else { + set titletext [format "(%+g %+g) microns" $olstx $olsty] + ${framename}.titlebar.pos configure -text $titletext + } +} + +proc magic::toolupdate {win {yesno "yes"} {layerlist "none"}} { + global Winopts + + if {$win == {}} { + set win [magic::windownames] + } + + # Wind3d has a "see" function, so make sure this is not a 3d window + if {$win == [magic::windownames wind3d]} { + return + } + + set topname [winfo toplevel $win] + set framename [winfo parent $win] + + # Don't do anything if toolbar is not present + if { $Winopts(${topname},toolbar) == 0 } { return } + + if {$layerlist == "none"} { + set layerlist $yesno + set yesno "yes" + } + if {$layerlist == "*"} { + set layerlist [magic::tech layer "*"] + } + + # Change from comma-separated list to Tcl list + set layerlist [string map {, " "} $layerlist] + + foreach layer $layerlist { + switch $layer { + none {set canon ""} + allSame {set canon ""} + "*" {set canon ""} + "$" {set canon ""} + connect {set canon ""} + errors {set canon $layer} + subcell {set canon $layer} + labels {set canon $layer} + default {set canon [magic::tech layer $layer]} + } + + # Layers may not be in the toolbar if "hidelocked" or + # "hidespecial" is used, so catch each configure command. + + if {$canon != ""} { + if {$yesno == "yes"} { + catch {${framename}.toolbar.b$canon configure -image img_$canon} + catch {${framename}.toolbar.p$canon configure -image pale_$canon} + } else { + catch {${framename}.toolbar.b$canon configure -image img_space} + catch {${framename}.toolbar.p$canon configure -image img_space} + } + } + } +} + +# Generate the toolbar images for a technology + +proc magic::maketoolimages {} { + + # Generate a layer image for "space" that will be used when layers are + # invisible. + + image create layer img_space -name none + + set all_layers [concat {errors labels subcell} [magic::tech layer "*"]] + + foreach layername $all_layers { + image create layer img_$layername -name $layername + image create layer pale_$layername -name $layername \ + -disabled true -icon 23 + } +} + +# Generate the toolbar for the wrapper + +proc magic::maketoolbar { framename } { + global Opts + global Winopts + + # Don't do anything if in suspend mode + set topname [winfo toplevel $framename] + if {[info exists Winopts(${topname},suspend)]} { + if { $Winopts(${topname},suspend) > 0} { return } + } + + if {$Opts(toolbar) == 0} { + magic::maketoolimages + set Opts(toolbar) 1 + } + + # Destroy any existing toolbar before starting + set alltools [winfo children ${framename}.toolbar] + foreach i $alltools { + destroy $i + } + + # All toolbar commands will be passed to the appropriate window + set win ${framename}.magic + + # Generate layer images and buttons for toolbar + if {$Opts(hidespecial) == 0} { + set special_layers {errors labels subcell} + } else { + set special_layers {} + } + + if {$Opts(hidelocked) == 0} { + set all_layers [concat $special_layers [magic::tech layer "*"]] + } else { + set all_layers [concat $special_layers [magic::tech unlocked]] + } + foreach layername $all_layers { + button ${framename}.toolbar.b$layername -image img_$layername -command \ + "$win see $layername" + + # Bindings: Entering the button puts the canonical layer name in the + # message window. + bind ${framename}.toolbar.b$layername \ + [subst {focus %W ; ${framename}.titlebar.message configure \ + -text "$layername"}] + bind ${framename}.toolbar.b$layername \ + [subst {${framename}.titlebar.message configure -text ""}] + + # 3rd mouse button makes layer invisible; 1st mouse button restores it. + # 2nd mouse button paints the layer color. Key "p" also does paint, esp. + # for users with 2-button mice. Key "e" erases, as does Shift-Button-2. + + bind ${framename}.toolbar.b$layername \ + "$win paint $layername" + bind ${framename}.toolbar.b$layername \ + "$win paint $layername" + bind ${framename}.toolbar.b$layername \ + "$win erase $layername" + bind ${framename}.toolbar.b$layername \ + "$win erase $layername" + bind ${framename}.toolbar.b$layername \ + "$win see no $layername" + bind ${framename}.toolbar.b$layername \ + "$win select more area $layername" + bind ${framename}.toolbar.b$layername \ + "$win select less area $layername" + } + + # Create an additional set of layers and buttons in the "disabled" style + # These buttons can be swapped in place of the regular buttons when the + # layer is locked. They define no bindings except "u" for "unlock", + # and the button bindings (see, see no) + + foreach layername $all_layers { + button ${framename}.toolbar.p$layername -image pale_$layername -command \ + "$win see $layername" + bind ${framename}.toolbar.p$layername \ + "$win see no $layername" + bind ${framename}.toolbar.p$layername \ + [subst {focus %W ; ${framename}.titlebar.message configure \ + -text "$layername (locked)"}] + bind ${framename}.toolbar.p$layername \ + [subst {${framename}.titlebar.message configure -text ""}] + } + + # Figure out how many columns we need to fit all the layer buttons inside + # the toolbar without going outside the window area. + + set locklist [tech locked] + set ncols 0 + while {1} { + incr ncols + set i 0 + set j 0 + foreach layername $all_layers { + if {[lsearch $locklist $layername] >= 0} { + grid ${framename}.toolbar.p$layername -row $i -column $j -sticky news + } else { + grid ${framename}.toolbar.b$layername -row $i -column $j -sticky news + } + bind ${framename}.toolbar.p$layername \ + "$win tech unlock $layername ; \ + grid forget ${framename}.toolbar.p$layername ; \ + grid ${framename}.toolbar.b$layername \ + -row $i -column $j -sticky news" + bind ${framename}.toolbar.b$layername \ + "$win tech lock $layername ; \ + grid forget ${framename}.toolbar.b$layername ; \ + grid ${framename}.toolbar.p$layername \ + -row $i -column $j -sticky news" + incr j + if {$j == $ncols} { + set j 0 + incr i + } + } + + # Make sure that window has been created so we will get the correct + # height value. + + update idletasks + set winheight [expr {[winfo height ${framename}] - \ + [winfo height ${framename}.titlebar]}] + set toolheight [lindex [grid bbox ${framename}.toolbar] 3] + if {$toolheight <= $winheight} {break} + } +} + +# Delete and rebuild the toolbar buttons in response to a "tech load" +# command. + +proc magic::techrebuild {winpath {cmdstr ""}} { + global Opts + + # For NULL window, find all layout windows and apply update to each. + if {$winpath == {}} { + set winlist [magic::windownames layout] + foreach lwin $winlist { + magic::techrebuild $lwin $cmdstr + } + return + } + + set framename [winfo parent $winpath] + if {${cmdstr} == "load"} { + set Opts(toolbar) 0 + maketoolbar ${framename} + magic::techmanager init + } elseif {${cmdstr} == "lock" || ${cmdstr} == "unlock" || ${cmdstr} == "revert"} { + maketoolbar ${framename} + } +} + +# Scrollbar callback procs + +# Procedure to return the effective X and Y scrollbar bounds for the +# current view in magic (in pixels) + +proc magic::setscrollvalues {win} { + set svalues [${win} view get] + set bvalues [${win} view bbox] + + set framename [winfo parent ${win}] + if {$framename == "."} {return} + + set bwidth [expr {[lindex $bvalues 2] - [lindex $bvalues 0]}] + set bheight [expr {[lindex $bvalues 3] - [lindex $bvalues 1]}] + + set wwidth [winfo width ${framename}.xscroll.bar] ;# horizontal scrollbar + set wheight [winfo height ${framename}.yscroll.bar] ;# vertical scrollbar + + # Note that adding 0.0 here forces floating-point + + set xscale [expr {(0.0 + $wwidth) / $bwidth}] + set yscale [expr {(0.0 + $wheight) / $bheight}] + + set xa [expr {$xscale * ([lindex $svalues 0] - [lindex $bvalues 0]) }] + set xb [expr {$xscale * ([lindex $svalues 2] - [lindex $bvalues 0]) }] + set ya [expr {$yscale * ([lindex $svalues 1] - [lindex $bvalues 1]) }] + set yb [expr {$yscale * ([lindex $svalues 3] - [lindex $bvalues 1]) }] + + # Magic's Y axis is inverted with respect to X11 window coordinates + set ya [expr { $wheight - $ya }] + set yb [expr { $wheight - $yb }] + + ${framename}.xscroll.bar coords slider $xa 2 $xb 15 + ${framename}.yscroll.bar coords slider 2 $ya 15 $yb + + set xb [expr { 1 + ($xa + $xb) / 2 }] + set xa [expr { $xb - 2 }] + ${framename}.xscroll.bar coords centre $xa 4 $xb 13 + + set yb [expr { 1 + ($ya + $yb) / 2 }] + set ya [expr { $yb - 2 }] + ${framename}.yscroll.bar coords centre 4 $ya 13 $yb +} + +# Procedure to update scrollbars in response to an internal command +# "view" calls "view", so avoid infinite recursion. + +proc magic::scrollupdate {win} { + + if {[info level] <= 1} { + + # For NULL window, find current window + if {$win == {}} { + set win [magic::windownames] + } + + # Make sure we're not a 3D window, which doesn't take window commands + # This is only necessary because the 3D window declares a "view" + # command, too. + + if {$win != [magic::windownames wind3d]} { + magic::setscrollvalues $win + } + } +} + +# scrollview: update the magic display to match the +# scrollbar positions. + +proc magic::scrollview { w win orient } { + global scale + set v1 $scale($orient,origin) + set v2 $scale($orient,update) + set delta [expr {$v2 - $v1}] + + set bvalues [${win} view bbox] + set wvalues [${win} windowpositions] + + # Note that adding 0.000 in expression forces floating-point + + if {"$orient" == "x"} { + + set bwidth [expr {[lindex $bvalues 2] - [lindex $bvalues 0]}] + set wwidth [expr {0.000 + [lindex $wvalues 2] - [lindex $wvalues 0]}] + set xscale [expr {$bwidth / $wwidth}] + ${win} scroll e [expr {$delta * $xscale}]i + + } else { + + set bheight [expr {[lindex $bvalues 3] - [lindex $bvalues 1]}] + set wheight [expr {0.000 + [lindex $wvalues 3] - [lindex $wvalues 1]}] + set yscale [expr {$bheight / $wheight}] + ${win} scroll s [expr {$delta * $yscale}]i + } +} + +# setscroll: get the current cursor position and save it as a +# reference point. + +proc magic::setscroll { w v orient } { + global scale + set scale($orient,origin) $v + set scale($orient,update) $v +} + +proc magic::dragscroll { w v orient } { + global scale + set v1 $scale($orient,update) + set scale($orient,update) $v + set delta [expr {$v - $v1}] + + if { "$orient" == "x" } { + $w move slider $delta 0 + $w move centre $delta 0 + } else { + $w move slider 0 $delta + $w move centre 0 $delta + } +} + +# Scrollbar generator for the wrapper window + +proc magic::makescrollbar { fname orient win } { + global scale + global Glyph + + set scale($orient,update) 0 + set scale($orient,origin) 0 + + # To be done: add glyphs for the arrows + + if { "$orient" == "x" } { + canvas ${fname}.bar -height 13 -relief sunken -borderwidth 1 + button ${fname}.lb -image $Glyph(left) -borderwidth 1 \ + -command "${win} scroll left .1 w" + button ${fname}.ub -image $Glyph(right) -borderwidth 1 \ + -command "${win} scroll right .1 w" + pack ${fname}.lb -side left + pack ${fname}.bar -fill $orient -expand true -side left + pack ${fname}.ub -side right + } else { + canvas ${fname}.bar -width 13 -relief sunken -borderwidth 1 + button ${fname}.lb -image $Glyph(down) -borderwidth 1 \ + -command "${win} scroll down .1 w" + button ${fname}.ub -image $Glyph(up) -borderwidth 1 \ + -command "${win} scroll up .1 w" + pack ${fname}.ub + pack ${fname}.bar -fill $orient -expand true + pack ${fname}.lb + } + + # Create the bar which controls the scrolling and bind actions to it + ${fname}.bar create rect 2 2 15 15 -fill steelblue -width 0 -tag slider + ${fname}.bar bind slider "magic::setscroll %W %$orient $orient" + ${fname}.bar bind slider "magic::scrollview %W $win $orient" + ${fname}.bar bind slider "magic::dragscroll %W %$orient $orient" + + # Create a small mark in the center of the scrolling rectangle which aids + # in determining how much the window is being scrolled when the full + # scrollbar extends past the window edges. + ${fname}.bar create rect 4 4 13 13 -fill black -width 0 -tag centre + ${fname}.bar bind centre "magic::setscroll %W %$orient $orient" + ${fname}.bar bind centre "magic::scrollview %W $win $orient" + ${fname}.bar bind centre "magic::dragscroll %W %$orient $orient" +} + +# Save all and quit. If something bad happens like an attempt to +# write cells into an unwriteable directory, then "cellname list modified" +# will contain a list of cells, so prompt to quit with the option to cancel. +# If there are no remaining modified and unsaved cells, then just exit. +# Because cell "(UNNAMED)" is not written by "writeall force", if that is +# the only modified cell, then prompt to change its name and save; then quit. + +proc magic::saveallandquit {} { + magic::promptsave force + set modlist [magic::cellname list modified] + if {$modlist == {}} { + magic::quit -noprompt + } else { + magic::quit + } +} + +# Create the wrapper and open up a layout window in it. + +proc magic::openwrapper {{cell ""} {framename ""}} { + global lwindow + global owindow + global tk_version + global Glyph + global Opts + global Winopts + + # Disallow scrollbars and title caption on windows---we'll do these ourselves + + if {$lwindow == 0} { + windowcaption off + windowscrollbars off + windowborder off + } + + if {$framename == ""} { + incr lwindow + set framename .layout${lwindow} + } + set winname ${framename}.pane.top.magic + + toplevel $framename + tkwait visibility $framename + + # Resize the window + if {[catch {wm geometry ${framename} $Winopts(${framename},geometry)}]} { + catch {wm geometry ${framename} $Opts(geometry)} + } + + # Create a paned window top--bottom inside the top level window to accomodate + # a resizable command entry window at the bottom. Sashwidth is zero by default + # but is resized by enabling the command entry window. + + panedwindow ${framename}.pane -orient vertical -sashrelief groove -sashwidth 6 + + frame ${framename}.pane.top + frame ${framename}.pane.bot + + set layoutframe ${framename}.pane.top + + ${framename}.pane add ${framename}.pane.top + ${framename}.pane add ${framename}.pane.bot + ${framename}.pane paneconfigure ${framename}.pane.top -stretch always + ${framename}.pane paneconfigure ${framename}.pane.bot -hide true + + pack ${framename}.pane -side top -fill both -expand true + + frame ${layoutframe}.xscroll -height 13 + frame ${layoutframe}.yscroll -width 13 + + magic::makescrollbar ${layoutframe}.xscroll x ${winname} + magic::makescrollbar ${layoutframe}.yscroll y ${winname} + button ${layoutframe}.zb -image $Glyph(zoom) -borderwidth 1 -command "${winname} zoom 2" + + # Add bindings for mouse buttons 2 and 3 to the zoom button + bind ${layoutframe}.zb "${winname} zoom 0.5" + bind ${layoutframe}.zb "${winname} view" + + frame ${layoutframe}.titlebar + label ${layoutframe}.titlebar.caption -text "Loaded: none Editing: none Tool: box" \ + -foreground white -background sienna4 -anchor w -padx 15 + label ${layoutframe}.titlebar.message -text "" -foreground white \ + -background sienna4 -anchor w -padx 5 + label ${layoutframe}.titlebar.pos -text "" -foreground white \ + -background sienna4 -anchor w -padx 5 + + # Menu buttons + frame ${layoutframe}.titlebar.mbuttons + +# File + menubutton ${layoutframe}.titlebar.mbuttons.file -text File -relief raised \ + -menu ${layoutframe}.titlebar.mbuttons.file.toolmenu -borderwidth 2 +# Edit + menubutton ${layoutframe}.titlebar.mbuttons.edit -text Edit -relief raised \ + -menu ${layoutframe}.titlebar.mbuttons.edit.toolmenu -borderwidth 2 +# Cell + menubutton ${layoutframe}.titlebar.mbuttons.cell -text Cell -relief raised \ + -menu ${layoutframe}.titlebar.mbuttons.cell.toolmenu -borderwidth 2 +# Window + menubutton ${layoutframe}.titlebar.mbuttons.win -text Window -relief raised \ + -menu ${layoutframe}.titlebar.mbuttons.win.toolmenu -borderwidth 2 +# Layers + menubutton ${layoutframe}.titlebar.mbuttons.layers -text Layers -relief raised \ + -menu ${layoutframe}.titlebar.mbuttons.layers.toolmenu -borderwidth 2 +# DRC + menubutton ${layoutframe}.titlebar.mbuttons.drc -text Drc -relief raised \ + -menu ${layoutframe}.titlebar.mbuttons.drc.toolmenu -borderwidth 2 +# Netlist +# menubutton ${layoutframe}.titlebar.mbuttons.netlist -text Neltist -relief raised \ +# -menu ${layoutframe}.titlebar.mbuttons.netlist.netlistmenu -borderwidth 2 +# Help +# menubutton ${layoutframe}.titlebar.mbuttons.help -text Help -relief raised \ +# -menu ${layoutframe}.titlebar.mbuttons.help.helpmenu -borderwidth 2 +# Options + menubutton ${layoutframe}.titlebar.mbuttons.opts -text Options -relief raised \ + -menu ${layoutframe}.titlebar.mbuttons.opts.toolmenu -borderwidth 2 + pack ${layoutframe}.titlebar.mbuttons.file -side left + pack ${layoutframe}.titlebar.mbuttons.edit -side left + pack ${layoutframe}.titlebar.mbuttons.cell -side left + pack ${layoutframe}.titlebar.mbuttons.win -side left + pack ${layoutframe}.titlebar.mbuttons.layers -side left + pack ${layoutframe}.titlebar.mbuttons.drc -side left +# pack ${layoutframe}.titlebar.mbuttons.netlist -side left +# pack ${layoutframe}.titlebar.mbuttons.help -side left + pack ${layoutframe}.titlebar.mbuttons.opts -side left + + # DRC status button + checkbutton ${layoutframe}.titlebar.drcbutton -text "DRC" -anchor w \ + -borderwidth 2 -variable Opts(drc) \ + -foreground white -background sienna4 -selectcolor green \ + -command [subst { if { \$Opts(drc) } { drc on } else { drc off } }] + + magic::openwindow $cell $winname + + # Create toolbar frame. Make sure it has the same visual and depth as + # the layout window, so there will be no problem using the GCs from the + # layout window to paint into the toolbar. + frame ${layoutframe}.toolbar \ + -visual "[winfo visual ${winname}] [winfo depth ${winname}]" + + # Repaint to magic colors + magic::repaintwrapper ${layoutframe} + + grid ${layoutframe}.titlebar -row 0 -column 0 -columnspan 3 -sticky news + grid ${layoutframe}.yscroll -row 1 -column 0 -sticky ns + grid $winname -row 1 -column 1 -sticky news + grid ${layoutframe}.zb -row 2 -column 0 + grid ${layoutframe}.xscroll -row 2 -column 1 -sticky ew + # The toolbar is not attached by default + + grid rowconfigure ${layoutframe} 1 -weight 1 + grid columnconfigure ${layoutframe} 1 -weight 1 + + grid ${layoutframe}.titlebar.mbuttons -row 0 -column 0 -sticky news + grid ${layoutframe}.titlebar.drcbutton -row 0 -column 1 -sticky news + grid ${layoutframe}.titlebar.caption -row 0 -column 2 -sticky news + grid ${layoutframe}.titlebar.message -row 0 -column 3 -sticky news + grid ${layoutframe}.titlebar.pos -row 0 -column 4 -sticky news + grid columnconfigure ${layoutframe}.titlebar 2 -weight 1 + + bind $winname "focus %W ; set Opts(focus) $framename" + + # Note: Tk binding bypasses the event proc, so it is important to + # set the current point; otherwise, the cursor will report the + # wrong position and/or the wrong window. HOWEVER we should wrap + # this command with the "bypass" command such that it does not + # reset any current input redirection to the terminal. + + bind ${winname} "*bypass setpoint %x %y ${winname}; \ + magic::cursorview ${winname}" + + set Winopts(${framename},toolbar) 1 + set Winopts(${framename},cmdentry) 0 + +# ################################# +# File +# ################################# + set m [menu ${layoutframe}.titlebar.mbuttons.file.toolmenu -tearoff 0] + $m add command -label "Open..." -command {magic::promptload magic} + # $m add command -label "Save" -command {magic::save } + $m add command -label "Save..." -command {magic::promptsave magic} + # $m add command -label "Save as..." -command {echo "not implemented"} + # $m add command -label "Save selection..." -command {echo "not implemented"} + $m add separator + $m add command -label "Flush changes" -command {magic::flush} + $m add separator + # $m add command -label "Read CIF" -command {magic::promptload cif} + $m add command -label "Read GDS" -command {magic::promptload gds} + # $m add separator + # $m add command -label "Write CIF" -command {magic::promptsave cif} + $m add command -label "Write GDS" -command {magic::promptsave gds} + # $m add separator + # $m add command -label "Print..." -command {echo "not implemented"} + $m add separator + $m add command -label "Save All and Quit" -command {magic::saveallandquit} + $m add command -label "Quit" -command {magic::quit} + +# ################################# +# Edit +# ################################# + + set m [menu ${layoutframe}.titlebar.mbuttons.edit.toolmenu -tearoff 0] + # $m add command -label "Cut" -command {echo "not implemented"} + # $m add command -label "Copy" -command {echo "not implemented"} + # $m add command -label "Paste" -command {echo "not implemented"} + $m add command -label "Delete" -command {delete} + $m add separator + $m add command -label "Select Area" -command {select area} + $m add command -label "Select Clear" -command {select clear} + $m add separator + $m add command -label "Undo" -command {magic::undo} + $m add command -label "Redo" -command {magic::redo} + # $m add command -label "Repeat Last" -command {echo "not implemented"} + $m add separator + $m add command -label "Rotate 90 degree" -command {magic::clock} + $m add command -label "Mirror Up/Down" -command {magic::upsidedown} + $m add command -label "Mirror Left/Right" -command {magic::sideways} + $m add separator + $m add command -label "Move Right" -command {move right 1} + $m add command -label "Move Left" -command {move left 1} + $m add command -label "Move Up" -command {move up 1} + $m add command -label "Move Down" -command {move down 1} + $m add separator + $m add command -label "Stretch Right" -command {stretch right 1} + $m add command -label "Stretch Left" -command {stretch left 1} + $m add command -label "Stretch Up" -command {stretch up 1} + $m add command -label "Stretch Down" -command {stretch down 1} + $m add separator + $m add command -label "Text ..." \ + -command [subst {magic::update_texthelper; \ + wm deiconify .texthelper ; raise .texthelper}] + +# ################################# +# Cell +# ################################# + set m [menu ${layoutframe}.titlebar.mbuttons.cell.toolmenu -tearoff 0] + $m add command -label "New..." -command {magic::prompt_dialog new} + $m add command -label "Save as..." -command {magic::prompt_dialog save} + $m add command -label "Select" -command {magic::select cell} + $m add command -label "Place Instance" -command {magic::promptload getcell} + # $m add command -label "Rename" -command {echo "not implemented"} + $m add separator + $m add command -label "Down hierarchy" -command {magic::pushstack} + $m add command -label "Up hierarchy" -command {magic::popstack} + $m add separator + $m add command -label "Edit" -command {magic::edit} + $m add separator + $m add command -label "Delete" -command \ + {magic::cellname delete [magic::cellname list window]} + $m add separator + $m add command -label "Expand Toggle" -command {magic::expand toggle} + $m add command -label "Expand" -command {magic::expand} + $m add command -label "Unexpand" -command {magic::unexpand} + $m add separator + $m add command -label "Lock Cell" -command {magic::instance lock} + $m add command -label "Unlock Cell" -command {magic::instance unlock} + +# ################################# +# Window +# ################################# + set m [menu ${layoutframe}.titlebar.mbuttons.win.toolmenu -tearoff 0] + $m add command -label "Clone" -command \ + {magic::openwrapper [magic::cellname list window]} + $m add command -label "New" -command "magic::openwrapper" + $m add command -label "Set Editable" -command \ + "pushbox ; select top cell ; edit ; popbox" + $m add command -label "Close" -command "closewrapper ${framename}" + $m add separator + $m add command -label "Full View" -command {magic::view} + $m add command -label "Redraw" -command {magic::redraw} + $m add command -label "Zoom Out" -command {magic::zoom 2} + $m add command -label "Zoom In" -command {magic::zoom 0.5} + $m add command -label "Zoom Box" -command {magic::findbox zoom} + $m add separator + $m add command -label "Grid on" -command {magic::grid on} + $m add command -label "Grid off" -command {magic::grid off} + $m add command -label "Snap-to-grid on" -command {magic::snap on} + $m add command -label "Snap-to-grid off" -command {magic::snap off} + $m add command -label "Measure box" -command {magic::box } + $m add separator + $m add command -label "Set grid 0.05um" -command {magic::grid 0.05um} + $m add command -label "Set grid 0.10um" -command {magic::grid 0.10um} + $m add command -label "Set grid 0.50um" -command {magic::grid 0.50um} + $m add command -label "Set grid 1.00um" -command {magic::grid 1.00um} + $m add command -label "Set grid 5.00um" -command {magic::grid 5.00um} + $m add command -label "Set grid 10.0um" -command {magic::grid 10.0um} + # $m add command -label "Set grid ..." -command {echo "not implemented"} + +# ################################# +# Layers +# ################################# + set m [menu ${layoutframe}.titlebar.mbuttons.layers.toolmenu -tearoff 0] + $m add command -label "Protect Base Layers" -command {magic::tech revert} + $m add command -label "Unlock Base Layers" -command {magic::tech unlock *} + $m add separator + $m add command -label "Clear Feedback" -command {magic::feedback clear} + $m add separator + +# ################################# +# DRC +# ################################# + set m [menu ${layoutframe}.titlebar.mbuttons.drc.toolmenu -tearoff 0] + # $m add command -label "DRC On" -command {drc on} + # $m add command -label "DRC Off" -command {drc off} + # $m add separator + $m add command -label "DRC update" -command {drc check; drc why} + $m add command -label "DRC report" -command {drc why} + $m add command -label "DRC Find next error" -command {drc find; findbox zoom} + $m add separator + $m add command -label "DRC Fast" -command {drc style drc(fast)} + $m add command -label "DRC Complete" -command {drc style drc(full)} + + set m [menu ${layoutframe}.titlebar.mbuttons.opts.toolmenu -tearoff 0] + $m add check -label "Toolbar" -variable Winopts(${framename},toolbar) \ + -command [subst {if { \$Winopts(${framename},toolbar) } { \ + magic::maketoolbar ${layoutframe} ; \ + grid ${layoutframe}.toolbar -row 1 -column 2 -rowspan 2 -sticky new ; \ + } else { \ + grid forget ${layoutframe}.toolbar } }] + + $m add check -label "Toolbar Hide Locked" \ + -variable Opts(hidelocked) \ + -command "magic::maketoolbar ${layoutframe}" + + .winmenu add radio -label ${framename} -variable Opts(target) -value ${winname} + if {$tk_version >= 8.5} { + $m add check -label "Cell Manager" -variable Opts(cellmgr) \ + -command [subst { magic::cellmanager create; \ + if { \$Opts(cellmgr) } { \ + wm deiconify .cellmgr ; raise .cellmgr \ + } else { \ + wm withdraw .cellmgr } }] + .winmenu entryconfigure last -command ".cellmgr.target.list configure \ + -text ${framename}" + } + + $m add check -label "Tech Manager" -variable Opts(techmgr) \ + -command [subst { magic::techmanager create; \ + if { \$Opts(techmgr) } { \ + wm deiconify .techmgr ; raise .techmgr \ + } else { \ + wm withdraw .techmgr } }] + + $m add check -label "Netlist Window" -variable Opts(netlist) \ + -command [subst { if { \[windownames netlist\] != {}} { \ + set Opts(netlist) 0 ; closewindow \[windownames netlist\] \ + } else { \ + set Opts(netlist) 1 ; specialopen netlist \ + } }] + + $m add check -label "Colormap Window" -variable Opts(colormap) \ + -command [subst { if { \[windownames color\] != {}} { \ + set Opts(colormap) 0 ; closewindow \[windownames color\] \ + } else { \ + set Opts(colormap) 1 ; specialopen color \ + } }] + + $m add check -label "3D Display" -variable Opts(wind3d) \ + -command [subst { if { \[windownames wind3d\] != {}} { \ + set Opts(wind3d) 0 ; .render.magic closewindow ; \ + destroy .render \ + } else { \ + set Opts(wind3d) 1 ; \ + magic::render3d \[${winname} cellname list window\] \ + } }] + + $m add check -label "Window Command Entry" \ + -variable Winopts(${framename},cmdentry) \ + -command [subst { if { \$Winopts(${framename},cmdentry) } { \ + addcommandentry $framename \ + } else { \ + deletecommandentry $framename } }] + + $m add check -label "Crosshair" \ + -variable Opts(crosshair) \ + -command "if {$Opts(crosshair) == 0} {crosshair off}" + + catch {addmazehelper $m} + + # Set the default view + + update idletasks + ${winname} magic::view + + magic::captions + + # If the toolbar is turned on, invoke the toolbar button + if { $Winopts(${framename},toolbar) == 1} { + magic::maketoolbar ${layoutframe} + grid ${layoutframe}.toolbar -row 1 -column 2 -rowspan 2 -sticky new + } + + # Remove "open" and "close" macros so they don't generate non-GUI + # windows or (worse) blow away the window inside the GUI frame + + if {[magic::macro list o] == "openwindow"} { + magic::macro o \ + "incr owindow ;\ + set rpt \[cursor screen\] ;\ + set rptx \[lindex \$rpt 0\] ;\ + set rpty \[lindex \$rpt 1\] ;\ + set Winopts(.owindow\$owindow,geometry) 500x500+\$rptx+\$rpty ;\ + openwrapper \[\$Opts(focus).magic cellname list window\] \ + .owindow\$owindow ;\ + .owindow\$owindow.magic view \[box values\]" + } + if {[magic::macro list O] == "closewindow"} { + magic::macro O "closewrapper \$Opts(focus)" + } + + # Make sure that closing from the window manager is equivalent to + # the command "closewrapper" + wm protocol ${framename} WM_DELETE_WINDOW "closewrapper ${framename}" + + # If the variable $Opts(callback) is defined, then attempt to execute it. + catch {eval $Opts(callback)} + + # If the variable $Winopts(callback) is defined, then attempt to execute it. + catch {eval $Winopts(${framename}, callback)} + + # Since one purpose of the window callback is to customize the menus, + # run the automatic generation of accelerator key text at the end. + # This can be subverted by setting Opts(autobuttontext) to 0, e.g., + # to put it at the top of the Winopts callback and then generate + # override values for specific buttons. + if {$Opts(autobuttontext)} { + catch {magic::button_auto_bind_text $layoutframe} + } + return ${winname} +} + +# Delete the wrapper and the layout window in it. + +proc magic::closewrapper { framename } { + global tk_version + global Opts + + # Remove this window from the target list in .winmenu + # (used by, e.g., cellmanager) + + set layoutframe ${framename}.pane.top + if { $Opts(target) == "${layoutframe}.magic" } { + set Opts(target) "default" + if {$tk_version >= 8.5} { + if {![catch {wm state .cellmgr}]} { + .cellmgr.target.list configure -text "default" + } + } + } + + set idx [.winmenu index $framename] + .winmenu delete $idx + + ${layoutframe}.magic magic::closewindow + destroy $framename +} + +# This procedure adds a command-line entry window to the bottom of +# a wrapper window (rudimentary functionality---incomplete) + +proc magic::addcommandentry { framename } { + set commandframe ${framename}.pane.bot + if {![winfo exists ${commandframe}.eval]} { + tkshell::YScrolled_Text ${commandframe}.eval -height 5 + tkshell::MakeEvaluator ${commandframe}.eval.text \ + "${framename}>" ${framename}.pane.top.magic + pack ${commandframe}.eval -side top -fill both -expand true + ${framename}.pane paneconfigure ${framename}.pane.bot -stretch never + ${framename}.pane paneconfigure ${framename}.pane.bot -minsize 50 + } + set entercmd [bind ${framename}.pane.top.magic ] + set bindstr "$entercmd ; macro XK_colon \"set Opts(redirect) 1;\ + focus ${commandframe}.eval.text\";\ + alias puts tkshell::PutsTkShell" + bind ${commandframe}.eval \ + "focus ${commandframe}.eval.text ; set Opts(focus) $framename ;\ + catch {unset Opts(redirect)}" + bind ${framename}.pane.top.magic $bindstr + # Make command entry window visible + ${framename}.pane paneconfigure ${framename}.pane.bot -hide false +} + +# Remove the command entry window from the bottom of a frame. + +proc magic::deletecommandentry { framename } { + set commandframe ${framename}.pane.bot + ::grid forget ${commandframe}.eval + # Remove the last bindings for + set bindstr [bind ${framename}.pane.top.magic ] + set i [string first "; macro" $bindstr] + set bindstr [string range $bindstr 0 $i-1] + bind ${framename}.pane.top.magic $bindstr + # Restore the keybinding for colon + imacro XK_colon ":" + # Restore the alias for "puts" + alias puts ::tkcon_puts + # Make command entry window invisible + ${framename}.pane paneconfigure ${framename}.pane.bot -hide true +} + +namespace import magic::openwrapper +puts "Use openwrapper to create a new GUI-based layout window" +namespace import magic::closewrapper +puts "Use closewrapper to remove a new GUI-based layout window" + +# Create a simple wrapper for the 3D window. . . this can be +# greatly expanded upon. + +proc magic::render3d {{cell ""}} { + global Opts + + toplevel .render + tkwait visibility .render + magic::specialopen wind3d $cell .render.magic + .render.magic cutbox box + set Opts(cutbox) 1 + wm protocol .render WM_DELETE_WINDOW "set Opts(wind3d) 0 ; \ + .render.magic closewindow ; destroy .render" + + frame .render.title + pack .render.title -expand true -fill x -side top + checkbutton .render.title.cutbox -text "Cutbox" -variable Opts(cutbox) \ + -foreground white -background sienna4 -anchor w -padx 15 \ + -command [subst { if { \$Opts(cutbox) } { .render.magic cutbox box \ + } else { \ + .render.magic cutbox none } }] + + if {$cell == ""} {set cell default} + label .render.title.msg -text "3D Rendering window Cell: $cell" \ + -foreground white -background sienna4 -anchor w -padx 15 + pack .render.title.cutbox -side left + pack .render.title.msg -side right -fill x -expand true + pack .render.magic -expand true -fill both -side bottom + bind .render.magic {focus %W} +} + diff --git a/textio/Depend b/textio/Depend new file mode 100644 index 00000000..a2fd88ff --- /dev/null +++ b/textio/Depend @@ -0,0 +1,22 @@ +txCommands.o: txCommands.c ../utils/magsgtty.h ../utils/magic.h \ + ../textio/textio.h ../utils/geometry.h ../textio/txcommands.h \ + ../textio/textioInt.h ../utils/macros.h ../utils/hash.h \ + ../windows/windows.h ../tiles/tile.h ../database/database.h \ + ../dbwind/dbwind.h ../drc/drc.h ../utils/signals.h \ + ../graphics/graphics.h ../utils/dqueue.h ../utils/malloc.h \ + ../utils/utils.h ../lisp/lisp.h +txInput.o: txInput.c ../utils/magsgtty.h ../utils/magic.h ../utils/main.h \ + ../windows/windows.h ../utils/geometry.h ../database/database.h \ + ../tiles/tile.h ../utils/hash.h ../textio/textio.h \ + ../textio/txcommands.h ../textio/textioInt.h ../utils/dqueue.h \ + ../utils/macros.h ../graphics/graphics.h ../database/databaseInt.h \ + ../cif/CIFint.h ../cif/CIFread.h +txMain.o: txMain.c ../utils/magsgtty.h ../utils/magic.h \ + ../textio/textio.h ../utils/geometry.h ../textio/txcommands.h \ + ../textio/textioInt.h ../windows/windows.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../dbwind/dbwind.h +txMore.o: txMore.c ../utils/magic.h +txOutput.o: txOutput.c ../utils/magsgtty.h ../utils/magic.h \ + ../textio/textio.h ../utils/geometry.h ../textio/txcommands.h \ + ../textio/textioInt.h ../windows/windows.h ../graphics/graphics.h \ + ../utils/paths.h ../utils/utils.h ../utils/malloc.h diff --git a/textio/Makefile b/textio/Makefile new file mode 100644 index 00000000..acae76bc --- /dev/null +++ b/textio/Makefile @@ -0,0 +1,10 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/textio/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +MODULE = textio +MAGICDIR = .. +SRCS = txCommands.c txInput.c txMain.c txMore.c txOutput.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/textio/textio.h b/textio/textio.h new file mode 100644 index 00000000..e62d91d2 --- /dev/null +++ b/textio/textio.h @@ -0,0 +1,108 @@ +/* + * textio.h -- + * + * Routines in the textio module + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * Needs: + * stdio.h + * magic.h + * + * rcsid $Header: /usr/cvsroot/magic-8.0/textio/textio.h,v 1.2 2008/02/18 01:01:35 tim Exp $ + */ + +#ifndef _TEXTIO_H +#define _TEXTIO_H + +#include "utils/magic.h" + +#ifdef MAGIC_WRAPPER +extern char *TxBuffer; +extern unsigned char TxInputRedirect; + +#define TX_INPUT_NORMAL 0 /* keys translated as macros */ +#define TX_INPUT_REDIRECTED 1 /* keys redirected to terminal */ +#define TX_INPUT_PROCESSING 2 /* executing a command via redirection */ +#define TX_INPUT_PENDING_RESET 3 /* about to switch back to state 0 */ + +#endif + +extern int TxCurButtons; + +/* These should really be defined by the application, not hard-coded */ +#define TX_LONG_CMD ':' /* Way of invoking a long command. */ +#define TX_LONG_CMD2 ';' /* Alternate way of invoking a long command. */ + +/* + * Procedure to print text on stdout and stderr. + */ + +#ifdef MAGIC_WRAPPER +#define Vfprintf Tcl_printf +#else +#define Vfprintf vfprintf +#endif /* MAGIC_WRAPPER */ + +/* printing procedures */ +extern bool TxPrintOn(); /* enables TxPrintf output */ +extern bool TxPrintOff(); /* disables TxPrintf output */ +extern void TxFlush(); +extern void TxFlushOut(); +extern void TxFlushErr(); +extern void TxVisChar(); +extern void TxUseMore(); +extern void TxStopMore(); + +/* printing procedures with variable arguments lists */ +extern void TxError(char *, ...); +extern void TxPrintf(char *, ...); +extern char *TxPrintString(char *, ...); + +/* input procedures */ +extern char *TxGetLinePrompt(); +extern char *TxGetLine(); +extern int TxGetChar(); +extern int TxDialog(); + +/* prompting procedures */ +extern void TxSetPrompt(); +extern void TxPrompt(); +extern void TxPromptOnNewLine(); +extern void TxUnPrompt(); +extern void TxRestorePrompt(); +extern void TxReprint(); + +/* terminal-state procedures */ +extern void TxSetTerminal(); +extern void TxResetTerminal(); +extern char TxEOFChar; /* The current EOF character */ +extern char TxInterruptChar; /* The current interrupt character */ + +/* command procedures */ +extern void TxDispatch(); + +/* variables that tell if stdin and stdout are to a terminal */ +extern bool TxStdinIsatty; +extern bool TxStdoutIsatty; +#define TxInteractive (TxStdinIsatty && TxStdoutIsatty) + +/* Misc procs */ +void TxInit(); +#ifdef USE_READLINE +void TxInitReadline(); +#endif + +#define TX_MAX_OPEN_FILES 20 + +#endif /* _TEXTIO_H */ diff --git a/textio/textioInt.h b/textio/textioInt.h new file mode 100644 index 00000000..dd22c40b --- /dev/null +++ b/textio/textioInt.h @@ -0,0 +1,57 @@ +/* + * textioInt.h -- + * + * INTERNAL definitions for the textio module + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid $Header: /usr/cvsroot/magic-8.0/textio/textioInt.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _TEXTIOINT_H +#define _TEXTIOINT_H + +#include "textio/textio.h" +#include "textio/txcommands.h" + +extern bool txHavePrompt; + +typedef struct { + fd_set tx_fdmask; /* A mask of the file descriptors for this + * device. + */ + void (*tx_inputProc)(); /* A procedure that fetches events and stores + * them in the input queue via TxAddEvent(). + */ + ClientData tx_cdata; /* Data to be passed back to caller. */ +} txInputDevRec; + +#define TX_PROMPT '>' +#define TX_CMD_PROMPT ":" + +/* all of the state associated with a tty terminal */ +#if !defined(SYSV) && !defined(CYGWIN) +typedef struct { + struct sgttyb tx_i_sgtty; + struct tchars tx_i_tchars; +} txTermState; +#endif /* SYSV */ + +extern bool TxGetInputEvent(); + +/* Routines with variable argument lists */ + +extern void txFprintfBasic(FILE *, ...); + +#endif /* _TEXTIOINT_H */ diff --git a/textio/txCommands.c b/textio/txCommands.c new file mode 100644 index 00000000..e3f4c869 --- /dev/null +++ b/textio/txCommands.c @@ -0,0 +1,1491 @@ +/* + * txCommands.c -- + * + * Reads commands from devices and sends them to the window package, + * which sends them to a particular window. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/textio/txCommands.c,v 1.6 2009/09/11 16:09:49 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include + +#include "utils/magsgtty.h" +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "textio/txcommands.h" +#include "textio/textioInt.h" +#include "utils/macros.h" +#include "windows/windows.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "dbwind/dbwind.h" +#include "drc/drc.h" +#include "utils/signals.h" +#include "graphics/graphics.h" +#include "utils/dqueue.h" +#include "utils/malloc.h" +#include "utils/utils.h" +#include "lisp/lisp.h" + +/* Turning this flag on prints out input events and commands as they + * are processed. + */ + +bool TxDebug = FALSE; + +/* A mask of the file descriptors for all input devices. + */ +static fd_set txInputDescriptors; + +/* A table of all input devices. + */ +static txInputDevRec txInputDevice[TX_MAX_OPEN_FILES]; +static int txLastInputEntry = -1; + +/* The current point -- reset by the 'setpoint' command and for each + * interactive command. Calls to TxClearPoint clear previous setpoints, + * + * Each input point is associated with a window, as windows may use + * different coordinate systems. + * + * Also, keep around the last input event. + */ +static bool txHaveCurrentPoint = FALSE; +static Point txCurrentPoint = {100, 100}; +static int txCurrentWindowID = WIND_UNKNOWN_WINDOW; +TxInputEvent txLastEvent; + + +/* Input queues. We have an input queue for low-level input events, and + * a queue for assembled interactive commands and file commands. Also, there + * are free lists for these structures. + */ + +#ifdef MAGIC_WRAPPER +extern void send_interpreter(char *); + +char *TxBuffer; /* For use with special stdin processing */ +unsigned char TxInputRedirect; /* For redirecting Tk events to the terminal */ +#endif + +DQueue txInputEvents; +DQueue txFreeEvents; +int txNumInputEvents; /* Number of events recieved by Magic so far. */ + +DQueue txFreeCommands; + +/* A zero time value, used for doing a poll via 'select()'. + */ + +static struct timeval txZeroTime; + + +/* Mask of buttons down, as of the last command in the queue (not the last + * command executed). + */ +int TxCurButtons = 0; + +/* + * Commands are numbered sequentially starting at zero. This number says + * which command we are collecting or executing. + */ + +int TxCommandNumber = 0; + +/* + * The "cmd" structure is shared by lisp and eval using this pointer + */ +static TxCommand *lisp_cur_cmd = NULL; + +/* + * ---------------------------------------------------------------------------- + * + * FD_IsZero -- + * FD_OrSet -- + * + * Routines for manipulating set of file descriptors. + * + * ---------------------------------------------------------------------------- + */ + +bool +FD_IsZero(fdmask) + fd_set fdmask; +{ + int i; + for (i = 0; i <= TX_MAX_OPEN_FILES; i++) + if (FD_ISSET(i, &fdmask)) return FALSE; + return TRUE; +} + +void +FD_OrSet(fdmask, dst) + fd_set fdmask; + fd_set *dst; +{ + int i; + for (i = 0; i <= TX_MAX_OPEN_FILES; i++) + if (FD_ISSET(i, &fdmask)) FD_SET(i, dst); +} + +/* + * ---------------------------------------------------------------------------- + * + * TxReleaseButton -- + * + * Pretend that a certain button is up, even though we think that it is + * down. Used only in rare circumstances, such as when SunWindows + * reads a button push behind our back. + * + * Results: + * None. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +TxReleaseButton(but) + int but; +{ + TxCurButtons &= ~but; +} + +/* + * ---------------------------------------------------------------------------- + * + * TxPrintEvent -- + * + * Print an event's contents to stderr. + * + * Results: + * None. + * + * Side Effects: + * Text appears on the terminal. + * + * ---------------------------------------------------------------------------- + */ + +void +TxPrintEvent(event) + TxInputEvent *event; +{ + TxError("Input event at 0x%x\n ", event); + if (event->txe_button == TX_EOF) { + TxError("EOF event"); + } else if (event->txe_button == TX_BYPASS) { + TxError("Bypass event"); + } else if (event->txe_button == TX_CHARACTER) { + char *strc = MacroName(event->txe_ch); + TxError("Character '%s'", strc); + freeMagic(strc); + } else { + switch (event->txe_button) { + case TX_LEFT_BUTTON: {TxError("Left button"); break;}; + case TX_MIDDLE_BUTTON: {TxError("Middle button"); break;}; + case TX_RIGHT_BUTTON: {TxError("Right button"); break;}; + default: {TxError("UNKNOWN button"); break;}; + } + switch (event->txe_buttonAction) { + case TX_BUTTON_UP: {TxError(" up"); break;}; + case TX_BUTTON_DOWN: {TxError(" down"); break;}; + default: {TxError(" UNKNOWN-ACTION"); break;}; + } + } + TxError(" at (%d, %d)\n Window: ", event->txe_p.p_x, event->txe_p.p_y); + switch (event->txe_wid) { + case WIND_UNKNOWN_WINDOW: {TxError("unknown\n"); break;}; + case WIND_NO_WINDOW: {TxError("none\n"); break;}; + default: {TxError("%d\n", event->txe_wid); break;}; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * TxPrintCommand -- + * + * Print a command's contents to stderr. + * + * Results: + * None. + * + * Side Effects: + * Text appears on the terminal. + * Repaired so that unprintable text does NOT appear (March 2000, Tim) + * + * ---------------------------------------------------------------------------- + */ + +void +TxPrintCommand(cmd) + TxCommand *cmd; +{ + int i, j; + char TxTemp[200]; + + TxError("Command at 0x%x\n ", cmd); + if (cmd->tx_button == TX_CHARACTER) { + TxError("Text command with %d words: ", cmd->tx_argc); + for (i = 0; i < cmd->tx_argc; i++) { + for (j = 0; cmd->tx_argv[i][j] && (j < 199); j++) + TxTemp[j] = isprint(cmd->tx_argv[i][j]) ? cmd->tx_argv[i][j] : '*'; + TxTemp[j] = '\0'; + TxError(" \"%s\"", TxTemp); + } + } else { + switch (cmd->tx_button) { + case TX_LEFT_BUTTON: {TxError("Left button"); break;}; + case TX_MIDDLE_BUTTON: {TxError("Middle button"); break;}; + case TX_RIGHT_BUTTON: {TxError("Right button"); break;}; + default: {TxError("UNKNOWN button"); break;}; + } + switch (cmd->tx_buttonAction) { + case TX_BUTTON_UP: {TxError(" up"); break;}; + case TX_BUTTON_DOWN: {TxError(" down"); break;}; + default: {TxError(" UNKNOWN-ACTION"); break;}; + } + } + TxError(" at (%d, %d)\n Window: ", cmd->tx_p.p_x, cmd->tx_p.p_y); + switch (cmd->tx_wid) { + case WIND_UNKNOWN_WINDOW: {TxError("unknown\n"); break;}; + case WIND_NO_WINDOW: {TxError("none\n"); break;}; + default: {TxError("%d\n", cmd->tx_wid); break;}; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * TxNewEvent -- + * + * Get a new event, ready to be filled in. + * + * Results: + * A pointer to a new event. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +TxInputEvent * +TxNewEvent() +{ + TxInputEvent *event; + event = (TxInputEvent *) DQPopFront(&txFreeEvents); + if (event == NULL) event = (TxInputEvent *) mallocMagic(sizeof(TxInputEvent)); + event->txe_button = TX_CHARACTER; + event->txe_buttonAction = TX_BUTTON_UP; + event->txe_wid = WIND_UNKNOWN_WINDOW; + event->txe_p.p_x = GR_CURSOR_X; + event->txe_p.p_y = GR_CURSOR_Y; + event->txe_ch = 0; + return event; +} + +/* + * ---------------------------------------------------------------------------- + * + * TxAddEvent -- + * + * Add a new event into our input queue. + * + * Results: + * None. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +TxAddEvent(event) + TxInputEvent *event; +{ + ASSERT(event != NULL, "TxAddEvent"); + DQPushRear(&txInputEvents, (ClientData) event); + txNumInputEvents++; +} + +/* + * ---------------------------------------------------------------------------- + * + * TxFreeEvent -- + * + * Free an event. + * + * Results: + * None. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +TxFreeEvent(event) + TxInputEvent *event; +{ + ASSERT(event != NULL, "TxFreeEvent"); + DQPushRear(&txFreeEvents, (ClientData) event); +} + +/* + * ---------------------------------------------------------------------------- + * + * TxNewCommand -- + * + * Get a new command, ready to be filled in. + * + * Results: + * A pointer to a new command. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +TxCommand * +TxNewCommand() +{ + TxCommand *command; + command = (TxCommand *) DQPopFront(&txFreeCommands); + if (command == NULL) + command = (TxCommand *) mallocMagic(sizeof(TxCommand)); + command->tx_button = TX_CHARACTER; + return command; +} + + +/* + * ---------------------------------------------------------------------------- + * + * TxFreeCommand -- + * + * Free a command. + * + * Results: + * None. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +TxFreeCommand(command) + TxCommand *command; +{ + ASSERT(command != NULL, "TxFreeCommand"); +#ifdef MAGIC_WRAPPER + /* No Tx Queue in MAGIC_WRAPPER; call is just to free memory */ + freeMagic((char *)command); +#else + DQPushRear(&txFreeCommands, (ClientData) command); +#endif +} + +/* + * ---------------------------------------------------------------------------- + * TxAddInputDevice -- + * TxAdd1InputDevice -- + * + * Add a device which is able to deliever commands to magic. + * The caller must ensure that SIGIO signals will be send whenever + * this file descriptor becomes ready. + * + * The usual form of inputProc is: + * + * proc(fd, cdata) + * int fd; -- file descriptor that is ready + * ClientData; -- ClientData as passed to TxAddInputDevice() + * { + * TxInputEvent *event; + * event = TxNewEvent(); + * -- read fd here, and fill in event + * TxAddEvent(event); + * -- might do this more than once for multiple events + * } + * + * Results: + * None. + * + * Side effects: + * Modifies internal tables. + * ---------------------------------------------------------------------------- + */ + +void +TxAddInputDevice(fdmask, inputProc, cdata) + fd_set fdmask; /* A mask of file descriptors that this + * device will handle. + */ + void (*inputProc)(); /* A routine to call. This routine will + * be passed a single file descriptor that + * is ready, and should read that file and + * add events(s) by calling TxNewEvent() + * followed by TxAddEvent(). + */ + ClientData cdata; /* Will be passed back to the proc whenever + * it is called. + */ +{ + int i; + TxDeleteInputDevice(fdmask); + if (txLastInputEntry + 1 == TX_MAX_OPEN_FILES) + { + TxError("Too many input devices.\n"); + return; + } + txLastInputEntry++; + txInputDevice[txLastInputEntry].tx_fdmask = fdmask; + txInputDevice[txLastInputEntry].tx_inputProc = inputProc; + txInputDevice[txLastInputEntry].tx_cdata = cdata; + FD_OrSet(fdmask, &txInputDescriptors); +} + +void +TxAdd1InputDevice(fd, inputProc, cdata) + int fd; + void (*inputProc)(); + ClientData cdata; +{ + fd_set fs; + FD_ZERO(&fs); + FD_SET(fd, &fs); + TxAddInputDevice(fs, inputProc, cdata); +} + +/* + * ---------------------------------------------------------------------------- + * TxDeleteInputDevice -- + * + * Delete an input device from our tables. + * + * Results: + * None. + * + * Side effects: + * modifies internal tables. + * ---------------------------------------------------------------------------- + */ + +void +TxDeleteInputDevice(fdmask) + fd_set fdmask; /* A mask of file descriptors that are + * no longer active. + */ +{ + int i; + + for (i = 0; i <= TX_MAX_OPEN_FILES; i++) + if (FD_ISSET(i, &fdmask)) TxDelete1InputDevice(i); +} + +void +TxDelete1InputDevice(fd) + int fd; +{ + int i, j; + + for (i = 0; i <= txLastInputEntry; i++) + { + FD_CLR(fd, &(txInputDevice[i].tx_fdmask)); + if (FD_IsZero(txInputDevice[i].tx_fdmask)) + { + for (j = i+1; j <= txLastInputEntry; j++) + txInputDevice[j-1] = txInputDevice[j]; + txLastInputEntry--; + } + } + FD_CLR(fd, &txInputDescriptors); +} + + +/* + * ---------------------------------------------------------------------------- + * TxSetPoint -- + * + * Set the point and window that will be used for the next command. + * + * Results: + * None. + * + * Side effects: + * Changes global set point variables. + * ---------------------------------------------------------------------------- + */ + +void +TxSetPoint(x, y, wid) + int x, y, wid; +{ + txHaveCurrentPoint = TRUE; + txCurrentPoint.p_x = x; + txCurrentPoint.p_y = y; + txCurrentWindowID = wid; +} + +/* + * ---------------------------------------------------------------------------- + * TxGetPoint -- + * + * Return the window ID and set the point (if non-NULL) set for the + * next command. + * + * Results: + * integer ID of the current window, or -1 if txHaveCurrentPoint is + * TX_POINT_CLEAR + * + * Side effects: + * Current point goes into + * + * ---------------------------------------------------------------------------- + */ + +int +TxGetPoint(tx_p) + Point *tx_p; +{ + if (txHaveCurrentPoint) + { + if (tx_p != (Point *)NULL) + *tx_p = txCurrentPoint; + return txCurrentWindowID; + } + return -1; +} + +/* + * ---------------------------------------------------------------------------- + * TxClearPoint -- + * + * Clear the point that will be used for the next command, forcing it to + * be read from the mouse or button push. + * + * Results: + * None. + * + * Side effects: + * Nullifies the effect of any previous TxSetPoint() call. + * ---------------------------------------------------------------------------- + */ + +void +TxClearPoint() +{ + txHaveCurrentPoint = FALSE; +} + +static FILE *txLogFile = NULL; +bool txLogUpdate; + +/* + * ---------------------------------------------------------------------------- + * TxLogCommands -- + * + * Log all further commands to the given file name. If the file is NULL, + * turn off logging. + * + * Results: + * None. + * + * Side effects: + * File IO. + * ---------------------------------------------------------------------------- + */ + +void +TxLogCommands(fileName, update) + char *fileName; + bool update; /* Request a screen update after each command */ +{ + if (txLogFile != NULL) + { + (void) fclose(txLogFile); + txLogFile = NULL; + } + if (fileName == NULL) return; + + txLogUpdate = update; + txLogFile = fopen(fileName, "w"); + if (txLogFile == NULL) + TxError("Could not open file '%s' for writing.\n", fileName); +} + +/* + * ---------------------------------------------------------------------------- + * txLogCommand -- + * + * Log a command in the log file. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +txLogCommand(cmd) + TxCommand *cmd; +{ + static char *txButTable[] = + { + "left", + "middle", + "right", + 0 + }; + static char *txActTable[] = + { + "down", + "up", + 0 + }; + + if (txLogFile == (FILE *) NULL) return; + + if (cmd->tx_wid >= 0) { + /* Command has a window associated with it. */ + fprintf(txLogFile, ":setpoint %d %d %d\n", + cmd->tx_p.p_x, cmd->tx_p.p_y, cmd->tx_wid); + } else { + /* No window associated with the command. */ + fprintf(txLogFile, ":setpoint %d %d\n", + cmd->tx_p.p_x, cmd->tx_p.p_y); + } + + if (cmd->tx_argc > 0) + { + int i; + fprintf(txLogFile, ":%s", cmd->tx_argv[0]); + for (i = 1; i < cmd->tx_argc; i++) + { + fprintf(txLogFile, " '%s'", cmd->tx_argv[i]); + } + fprintf(txLogFile, "\n"); + } + else if (cmd->tx_button == TX_CHARACTER) { + /* its a no-op command */ + return; + } + else { + int but, act; + + switch(cmd->tx_button) { + case TX_LEFT_BUTTON: { but = 0; break; }; + case TX_MIDDLE_BUTTON: { but = 1; break; }; + case TX_RIGHT_BUTTON: { but = 2; break; }; + default: {ASSERT(FALSE, "txLogCommand"); break; }; + } + switch(cmd->tx_buttonAction) { + case TX_BUTTON_DOWN: { act = 0; break; }; + case TX_BUTTON_UP: { act = 1; break; }; + default: {ASSERT(FALSE, "txLogCommand"); break; }; + } + + fprintf(txLogFile, ":pushbutton %s %s\n", + txButTable[but], txActTable[act]); + } + if (txLogUpdate) + fprintf(txLogFile, ":updatedisplay\n"); + (void) fflush(txLogFile); +} + +/* + * ---------------------------------------------------------------------------- + * + * TxGetInputEvent -- + * + * Get some events and put them into the event queue. If returnOnSigWinch + * is on, we will return early if some event (such as a SigWinch) requires + * immediate attention. In that case, the input event queue may be empty + * even if block is TRUE. + * + * Results: + * "TRUE" if it got some input. + * + * Side Effects: + * Some IO may be done, and things may appear in the event queue. + * + * ---------------------------------------------------------------------------- + */ + +bool +TxGetInputEvent(block, returnOnSigWinch) + bool block; /* If TRUE, we will wait for an event. Otherwise, we + * just poll. + */ + bool returnOnSigWinch; + /* If we get a Sig-Winch signal, should we abondon + * our quest to read an input event and return + * immediately instead? + */ +{ + + struct timeval *waitTime; + fd_set inputs; + int numReady; + bool gotSome; + int i, fd, lastNum; + + ASSERT(!FD_IsZero(txInputDescriptors), "TxGetInputEvent"); + + if (block) + waitTime = NULL; + else + waitTime = &txZeroTime; + + gotSome = FALSE; + do { + do + { + if (returnOnSigWinch && SigGotSigWinch) return gotSome; + inputs = txInputDescriptors; + numReady = select(TX_MAX_OPEN_FILES, &inputs, (fd_set *)NULL, + (fd_set *)NULL, waitTime); + if (numReady <= 0) FD_ZERO(&inputs); /* no fd is ready */ + } while ((numReady <= 0) && (errno == EINTR)); + + if ((numReady < 0) && (errno != EINTR)) + { + perror("magic"); + } + + for (i = 0; i <= txLastInputEntry; i++) + { + /* This device has data on its file descriptor, call + * it so that it can add events to the input queue. + */ + for (fd = 0; fd < TX_MAX_OPEN_FILES; fd++) { + if (FD_ISSET(fd, &inputs) && + FD_ISSET(fd, &(txInputDevice[i].tx_fdmask))) { + lastNum = txNumInputEvents; + (*(txInputDevice[i].tx_inputProc)) + (fd, txInputDevice[i].tx_cdata); + FD_CLR(fd, &inputs); + /* Did this driver choose to add an event? */ + if (txNumInputEvents != lastNum) gotSome = TRUE; + } + } + } + /* + * At this point we have handled all the bits in 'inputs' -- almost. + * It is possible for an input handler to remove or add other handlers + * via calls to TxDeleteDevice or TxAddDevice. Therefore, there may be + * bits in inputs that haven't been turned off. + */ + } while (block && !gotSome); + return gotSome; +} + +#ifndef MAGIC_WRAPPER + +/* + * ---------------------------------------------------------------------------- + * + * TxParseString -- + * + * Parse a string into commands, and add them to the rear of a queue. + * The commands in the queue should eventually be freed by the caller + * via TxFreeCommand(). + * + * Results: + * None. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +TxParseString(str, q, event) + char *str; /* The string to be parsed. */ + DQueue *q; /* Add to the tail of this queue. */ + TxInputEvent *event; /* An event to supply the point, window ID, + * etc. . If NULL, we will use the last + * event processed. + */ +{ + char *remainder; + TxCommand *cmd; + + if (event == NULL) event = &txLastEvent; + + remainder = str; + while (remainder != NULL) { + /* Parse a single command. */ + cmd = TxNewCommand(); + strncpy(cmd->tx_argstring, remainder, TX_MAX_CMDLEN); + cmd->tx_argstring[TX_MAX_CMDLEN - 1] = '\0'; + + if (ParsSplit(cmd->tx_argstring, TX_MAXARGS, + &(cmd->tx_argc), cmd->tx_argv, &remainder) ) + { + if (event == NULL) event = &txLastEvent; + cmd->tx_button = TX_CHARACTER; + cmd->tx_p = event->txe_p; + cmd->tx_wid = event->txe_wid; + DQPushRear(q, (ClientData) cmd); + } + else + { + TxError("Unable to completely parse command line '%s'\n", + str); + TxFreeCommand(cmd); + return; + } + } +} + +#endif /* !MAGIC_WRAPPER */ + +/* + * ---------------------------------------------------------------------------- + * txGetInteractiveCommand: + * + * Get one or more commands from one of the interactive input devices, + * and put it into the input queue. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +txGetInteractiveCommand(block, queue) + bool block; /* If TRUE, then wait until we have a command. + * If FALSE, then get one only if input is + * available. + */ + DQueue *queue; /* Queue to receive the new commands. */ +{ + static char inputLine[TX_MAX_CMDLEN] = ""; + TxInputEvent *event; + TxCommand *cmd; + int ch; + + /* Get one new event and return (except for text commands, then collect + * an entire line. + */ + if (DQIsEmpty(&txInputEvents)) TxGetInputEvent(block, TRUE); + if (DQIsEmpty(&txInputEvents)) return; + + event = (TxInputEvent *) DQPopFront(&txInputEvents); + txLastEvent = *event; + if (TxDebug) TxPrintEvent(event); + ASSERT(event != NULL, "txGetInteractiveCommand"); + + if (event->txe_button == TX_EOF) { + /* We have an end of file. Put it at the end of our command queue, + * but only if we are waiting for a command. We don't want to + * put in EOF's if we are just polling. + */ + if (block) + { + cmd = TxNewCommand(); + cmd->tx_button = TX_EOF; + cmd->tx_p = event->txe_p; + cmd->tx_wid = event->txe_wid; + cmd->tx_argc = 0; + cmd->tx_argv[0] = NULL; + DQPushRear(queue, (ClientData) cmd); + } + TxFreeEvent(event); + } else if ((TxCurButtons != 0) && (event->txe_button == TX_CHARACTER)) { + /* We have a keyboard character, but buttons are still down. + * Push fake button up commands into the queue in front of this + * event, so that all buttons will be up by the time that we get + * to the character event. This is needed to avoid strange things + * when the user pushes a buttons down on a Sun 160 (or other device + * with a non-Magic window package) and then releases it outside of + * the Magic windows. + */ + TxInputEvent *newEvent; + int ourbuts; + + ourbuts = TxCurButtons; + DQPushFront(&txInputEvents, event); + while (ourbuts != 0) { + newEvent = TxNewEvent(); + newEvent->txe_p = event->txe_p; + newEvent->txe_wid = event->txe_wid; + /* Get rightmost '1' bit of ourbuts. */ + newEvent->txe_button = LAST_BIT_OF(ourbuts); + newEvent->txe_buttonAction = TX_BUTTON_UP; + newEvent->txe_ch = 0; + ourbuts &= ~newEvent->txe_button; + DQPushFront(&txInputEvents, newEvent); + } + /* Now, go around the loop and process these things just like + * the user had typed them. + */ + } else if (event->txe_button == TX_CHARACTER) { + /* We have a text command, go into text collection mode */ + + /* need to check for long command or macro, then assemble line */ + ch = event->txe_ch; + TxFreeEvent(event); + if ((ch == (int)TX_LONG_CMD) || (ch == (int)TX_LONG_CMD2)) + { + (void) TxGetLinePrompt(inputLine, TX_MAX_CMDLEN, TX_CMD_PROMPT); + if (inputLine[0] != '\0') MacroDefine(DBWclientID, (int)'.', + inputLine, NULL, FALSE); + TxParseString(inputLine, queue, (TxInputEvent* ) NULL); + } + else + { + bool iMacro; /* Interactive macro */ + char *macroDef; + + macroDef = MacroRetrieve(DBWclientID, ch, &iMacro); + if (macroDef == NULL) + { + /* Cases macroDef may be NULL: */ + /* 1) Return 2) Ctrl-C 3) Invalid macro */ + + if (ch == (int)'\n') + { + if (TxInteractive) TxPrintf("%c\n", TX_PROMPT); + } + else + { + /* not a valid command */ + char *vis = MacroName(ch); + TxError("Unknown macro or short command: '%s'\n", vis); + freeMagic(vis); + } + } + else + { + if (iMacro) + { + (void) TxGetLineWPrompt(inputLine, + TX_MAX_CMDLEN, TX_CMD_PROMPT, macroDef); + if (inputLine[0] != '\0') MacroDefine(DBWclientID, (int)'.', + inputLine, NULL, FALSE); + TxParseString(inputLine, queue, (TxInputEvent *) NULL); + } + else + { + TxParseString(macroDef, queue, (TxInputEvent *) NULL); + } + freeMagic(macroDef); + } + } + } else if ((event->txe_button & TX_LEFT_BUTTON) || + (event->txe_button & TX_MIDDLE_BUTTON) || + (event->txe_button & TX_RIGHT_BUTTON)) { + /* We have a button command, but ignore double ups & downs. */ + int oldButtons; + oldButtons = TxCurButtons; + if (event->txe_buttonAction == TX_BUTTON_UP) + TxCurButtons &= ~(event->txe_button); + else + TxCurButtons |= event->txe_button; + if (oldButtons == TxCurButtons) { + TxFreeEvent(event); + } else { + /* We have a valid button command. */ + cmd = TxNewCommand(); + cmd->tx_button = event->txe_button; + cmd->tx_buttonAction = event->txe_buttonAction; + cmd->tx_p = event->txe_p; + cmd->tx_wid = event->txe_wid; + cmd->tx_argc = 0; + cmd->tx_argv[0] = NULL; + DQPushRear(queue, (ClientData) cmd); + TxFreeEvent(event); + } + } else { /* TX_BYPASS */ + /* Ignore this event */ + TxFreeEvent(event); + } +} + +/* + * ---------------------------------------------------------------------------- + * txGetFileCommand -- + * + * Get a line from a file and stick the commands into the input queue. + * + * Results: + * None. + * + * Side effects: + * Reads the file and puts a command into the queue. + * ---------------------------------------------------------------------------- + */ + +void +txGetFileCommand(f, queue) + FILE *f; /* File to read. */ + DQueue *queue; /* Queue to receive the new commands. */ +{ + char inputLine[TX_MAX_CMDLEN]; + char *linep; + char *current; + int spaceleft; + + /* Generate a line by patching together successive lines ending + * in '\'. + */ + + do { + current = inputLine; + spaceleft = TX_MAX_CMDLEN - 1; + + while (TRUE) + { + if (fgets(current, spaceleft, f) == NULL) + return; + + while (*current != 0) + { + current++; + spaceleft--; + } + if ((*(current-1) != '\n') || (*(current-2) != '\\')) goto gotline; + current--; + spaceleft++; + } + + gotline: *current = 0; + + /* If the line is empty, or contains a hash mark as + * the first non-blank character, then skip over it. + */ + + current = inputLine; + while (isspace(*current)) current++; + } while ((*current == 0) || (*current == '#')); + + linep = inputLine; + +#ifdef MAGIC_WRAPPER + /* Don't muck with Tcl's interpretation of semicolon as a */ + /* comment character. Watch for single-colon entries for */ + /* backwards-compatibility with the old format, but watch */ + /* for the double-colon, which is a Tcl namespace marker. */ + + if ((inputLine[0] == ':') && (inputLine[1] != ':')) linep++; +#else + if ((inputLine[0] == ':') || (inputLine[1] == ';')) linep++; +#endif + + TxParseString(linep, queue, (TxInputEvent *) NULL); +} + +#ifdef MAGIC_WRAPPER + +/* + * ---------------------------------------------------------------------------- + * TxTclDispatch: + * + * Command dispatcher which relies on the Tcl interpreter for most + * of the work. Replaces TxDispatch except for file input during + * startup. + * + * ---------------------------------------------------------------------------- + */ + +int +TxTclDispatch(clientData, argc, argv, quiet) + ClientData clientData; + int argc; + char *argv[]; + bool quiet; +{ + int result; + int n, asize; + TxCommand *tclcmd; + unsigned char lastdrc; + + if (argc > TX_MAXARGS) + { + TxError("Error: number of command arguments exceeds %d!\n", TX_MAXARGS); + return -1; + } + + SigIOReady = FALSE; + if (SigInterruptOnSigIO >= 0) SigInterruptOnSigIO = 1; + SigInterruptPending = FALSE; + + tclcmd = TxNewCommand(); + tclcmd->tx_argc = argc; + + asize = 0; + for (n = 0; n < argc; n++) + { + if (asize + strlen(argv[n]) >= TX_MAX_CMDLEN) + { + TxError("Error: command length exceeds %d characters!\n", TX_MAX_CMDLEN); + TxFreeCommand(tclcmd); + return -1; + } + strcpy(&tclcmd->tx_argstring[asize], argv[n]); + tclcmd->tx_argv[n] = &tclcmd->tx_argstring[asize]; + asize += (1 + strlen(argv[n])); + } + tclcmd->tx_p = txCurrentPoint; + if (txHaveCurrentPoint) + tclcmd->tx_wid = txCurrentWindowID; + else + tclcmd->tx_wid = WIND_UNKNOWN_WINDOW; + + /* Prevent DRCContinuous from running in the middle of a command */ + /* (Note that Tcl_CancelIdleCall() does *not* work. . .) */ + + lastdrc = DRCBackGround; + if (DRCBackGround != DRC_SET_OFF) DRCBackGround = DRC_NOT_SET; + + result = WindSendCommand((MagWindow *)clientData, tclcmd, quiet); + + TxFreeCommand(tclcmd); + + // Don't update the command number on bypass commands, or else + // the selection mechanism gets broken by the background DRC. + + if (argc > 0 && strcmp(argv[0], "*bypass")) TxCommandNumber++; + + if (SigInterruptPending) + TxPrintf("[Interrupted]\n"); + + if (result == 0) WindUpdate(); + + SigInterruptPending = FALSE; + if (SigInterruptOnSigIO >= 0) SigInterruptOnSigIO = 0; + SigIOReady = FALSE; + + /* Force a break of DRCContinuous() so we don't run DRC on an */ + /* invalid database. */ + + /* Avoid breaking on "*bypass" commands. Technically, one could */ + /* set up a command to *bypass that alters the database and crashes */ + /* magic. This is a total hack. We should flag an invalid */ + /* database instead. */ + + if (DRCBackGround == DRC_NOT_SET) DRCBackGround = lastdrc; + if (argc > 0 && strcmp(argv[0], "*bypass") && strcmp(argv[0], "windownames")) + DRCBreak(); + + /* Reinstate the idle call */ + if (result == 0) Tcl_DoWhenIdle(DRCContinuous, (ClientData)NULL); + return result; +} +#else /* !MAGIC_WRAPPER */ + +/* + * ---------------------------------------------------------------------------- + * TxDispatch: + * + * Read input from the interactive devices (keyboard or mouse) or from + * a file. Send a command off to WindSendCommand for processing, and + * then repeat. + * + * Results: + * None. + * + * Side effects: + * Commands are read and executed, one per cycle of this procedure's loop. + * ---------------------------------------------------------------------------- + */ + +void +TxDispatch(f) + FILE *f; /* Read commands from this file instead of + * from the mouse or keyboard. + */ +{ + bool inFile; + DQueue inputCommands; /* A queue of commands from our input + * sources. + */ + + DQInit(&inputCommands, 4); + + inFile = (f != (FILE *) NULL); + + while (TRUE) + { + if (!inFile) + { + /* Update the screen info of the window package and all of + * its clients. If there's already input waiting, skip this... + * it can get done at the end, after all pending commands have + * been processed. + */ + if (SigInterruptOnSigIO >= 0) SigInterruptOnSigIO = 0; + SigInterruptPending = FALSE; + txGetInteractiveCommand(FALSE, &inputCommands); + if (DQIsEmpty(&inputCommands)) + { + WindUpdate(); + if (SigInterruptPending) + TxPrintf("[Redisplay Interrupted]\n"); + txGetInteractiveCommand(FALSE, &inputCommands); + } + + /* Give the DRC a chance to work. */ + if (!SigGotSigWinch && DQIsEmpty(&inputCommands)) { + if (DRCHasWork) { + TxSetPrompt(']'); + TxPrompt(); + (void) GrEnableTablet(); + GrFlush(); + + /* Call background DRC. + * It will return if it is not enabled, there is no work to + * be done, or it learns that the user has entered a + * command. + */ + SigIOReady = FALSE; + if (SigInterruptOnSigIO >= 0) SigInterruptOnSigIO = 1; + SigInterruptPending = FALSE; + DRCContinuous(); + TxUnPrompt(); + + SigIOReady = FALSE; + if (SigInterruptOnSigIO >= 0) SigInterruptOnSigIO = 0; + SigInterruptPending = FALSE; + (void) GrDisableTablet(); + WindUpdate(); + if (SigInterruptPending) + TxPrintf("[DRC Redisplay Interrupted]\n"); + } + TxSetPrompt(TX_PROMPT); + TxPrompt(); + (void) GrEnableTablet(); + GrFlush(); + + txGetInteractiveCommand(TRUE, &inputCommands); + + TxUnPrompt(); + (void) GrDisableTablet(); + GrFlush(); + SigInterruptPending = FALSE; + SigIOReady = FALSE; + } + } + else + { + if (feof(f)) goto done; + if (SigInterruptPending && inFile) + { + TxPrintf("[Read-in of command file aborted]\n"); + goto done; + } + if (!SigGotSigWinch) txGetFileCommand(f, &inputCommands); + } + + if (SigGotSigWinch) { + /* WindUpdate will take care of SigWinch and set it to FALSE */ + WindUpdate(); + } + + /* Now send off the commands in the queue. */ + while (!DQIsEmpty(&inputCommands)) + { + TxCommand *cmd; + + cmd = (TxCommand *) DQPopFront(&inputCommands); + if (TxDebug) TxPrintCommand(cmd); + if (cmd->tx_button == TX_EOF) + { + /* End of our input stream. */ + TxError("EOF encountered on input stream -- Magic exiting.\n"); + MainExit(1); + } + + /**** + ASSERT(cmd->tx_p.p_x > 0 && cmd->tx_p.p_x < 10000, "TxDispatch"); + ASSERT(cmd->tx_p.p_y > 0 && cmd->tx_p.p_y < 10000, "TxDispatch"); + ****/ + + /* force the point, if that was requested */ + if (txHaveCurrentPoint) { + cmd->tx_p = txCurrentPoint; + cmd->tx_wid = txCurrentWindowID; + if (!inFile) txHaveCurrentPoint = FALSE; + }; + + /**** + ASSERT(cmd->tx_argc >= 0 && cmd->tx_argc <= TX_MAXARGS, + "TxDispatch"); + if (cmd->tx_argc != 0) { + ASSERT(cmd->tx_button == TX_CHARACTER, "TxDispatch"); + } + else { + ASSERT((cmd->tx_buttonAction == TX_BUTTON_DOWN) || \ + (cmd->tx_buttonAction == TX_BUTTON_UP), + "TxDispatch"); + ASSERT((cmd->tx_button == TX_LEFT_BUTTON) || \ + (cmd->tx_button == TX_MIDDLE_BUTTON) || \ + (cmd->tx_button == TX_RIGHT_BUTTON) || \ + (cmd->tx_button == TX_CHARACTER), + "TxDispatch"); + }; + ****/ + if (!inFile && (txLogFile != NULL)) txLogCommand(cmd); + + /* + * Add lisp interpreter here. We trap the character + * commands and call the lisp interpreter that traps + * any lisp-like behavior and returns a stream of "cmd" + * functions which are then sent to the appropriate window + * using the usual WindSendCommand() call. + * + * (rajit@cs.caltech.edu) + */ +#ifdef SCHEME_INTERPRETER + if (cmd->tx_button == TX_CHARACTER) + { + lisp_cur_cmd = cmd; + LispEvaluate (cmd->tx_argc, cmd->tx_argv, inFile); + TxFreeCommand (cmd); + lisp_cur_cmd = NULL; + } + else { +#endif + (void) WindSendCommand((MagWindow *) NULL, cmd, FALSE); + TxFreeCommand(cmd); + TxCommandNumber++; + +#ifdef SCHEME_INTERPRETER + } +#endif + } + /* ?? */ + WindUpdate(); + + } /* while */ + +done: + while (!DQIsEmpty(&inputCommands)) + TxFreeCommand((TxCommand *) DQPopFront(&inputCommands)); + DQFree(&inputCommands); +} + +#endif /* !MAGIC_WRAPPER */ + +/* + * ---------------------------------------------------------------------------- + * + * txCommandsInit -- + * + * Initialize the things in this file + * + * Results: + * None. + * + * Side Effects: + * Variables are set up. + * + * ---------------------------------------------------------------------------- + */ + +void +txCommandsInit() +{ + txZeroTime.tv_sec = 0; + txZeroTime.tv_usec = 0; + FD_ZERO(&txInputDescriptors); + DQInit(&txInputEvents, 4); + DQInit(&txFreeEvents, 4); + DQInit(&txFreeCommands, 4); +} + +#ifdef SCHEME_INTERPRETER + +/* + * ---------------------------------------------------------------------------- + * + * txLispDispatch -- + * + * Send command to magic window. + * + * Results: + * Returns TRUE on success, FALSE on failure. + * + * Side Effects: + * whatever the command does. + * + * ---------------------------------------------------------------------------- + */ + +bool +TxLispDispatch (argc,argv,trace, inFile) + int argc; + char **argv; + int trace; + int inFile; +{ + TxCommand *cmd = lisp_cur_cmd; + int i,j,k; + bool ret; + Point tx_p; + int wid; + + cmd->tx_argc = argc; + for (i=0,j=0; i < argc; i++) { + cmd->tx_argv[i] = cmd->tx_argstring+j; + k=0; + while (cmd->tx_argstring[j] = argv[i][k]) + j++,k++; + j++; + } + tx_p = cmd->tx_p; + wid = cmd->tx_wid; + if (txHaveCurrentPoint) { + cmd->tx_p = txCurrentPoint; + cmd->tx_wid = txCurrentWindowID; + if (!inFile) txHaveCurrentPoint = FALSE; + } + if (trace) + TxPrintCommand (cmd); + ret = WindSendCommand((MagWindow *) NULL, cmd, FALSE); + /* restore the original values */ + cmd->tx_p = tx_p; + cmd->tx_wid = wid; + TxCommandNumber++; + return ret; +} + +#endif /* SCHEME_INTERPRETER */ diff --git a/textio/txInput.c b/textio/txInput.c new file mode 100644 index 00000000..6338ae43 --- /dev/null +++ b/textio/txInput.c @@ -0,0 +1,1419 @@ +/* + * txInput.c -- + * + * Handles 'stdin' and terminal driver settings. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/textio/txInput.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "utils/magsgtty.h" +#include "utils/magic.h" +#include "utils/magsgtty.h" +#include "utils/main.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "textio/txcommands.h" +#include "textio/textioInt.h" +#include "utils/dqueue.h" +#include "utils/macros.h" +#include "utils/hash.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "database/databaseInt.h" +#include "cif/CIFint.h" +#include "cif/CIFread.h" + +#ifdef USE_READLINE +#ifdef HAVE_READLINE +#include +#include +#else +#include "readline/readline/readline.h" +#include "readline/readline/history.h" +#endif + +int TxPrefix(void); + +/* Globally keep track of the imacro string, if any; */ +/* the readline callback takes no parameters. */ +char *_rl_prefix; + +/* Custom completer function */ +char **magic_completion_function(char *, int, int); + +/* match generators */ +char *list_completion_function(char *, int); +char *macro_completion_function(char *, int); +char *cellname_completion_function(char *, int); +char *istyle_completion_function(char *, int); +char *ostyle_completion_function(char *, int); + +/* match list generators */ +void make_techtype_list(void); +void update_cellname_hash(void); + +char **completion_list; +char **magic_command_list = (char **)NULL; +char **magic_techtype_list = (char **)NULL; +HashTable cellname_hash; + +static int interactive_flag; + +char *magic_direction_list[] = { + "bottom", "down", "e", "east", "left", "n", "north", "right", + "s", "south", "top", "up", "w", "west", (char *)NULL }; + +#define COMMAND_COMPL 0 +#define MACRO_COMPL 1 +#define IMACRO_COMPL 2 +#define LAYER_COMPL 3 +#define PLANE_COMPL 4 +#define FILE_COMPL 5 +#define CELL_COMPL 6 +#define ARGS_COMPL 7 +#define ISTYLE_COMPL 8 +#define OSTYLE_COMPL 9 +#define DIRECT_COMPL 10 + +/* Can only accommodate 32 arg options, increase as necessary */ +static struct cmd_spec { + char *cmd; + int type; + char *args[32]; +} magic_cmd_spec[] = { + { "", COMMAND_COMPL, {(char *)NULL} }, + { "help", COMMAND_COMPL, {(char *)NULL} }, + + { "shell", FILE_COMPL, {(char *)NULL} }, + { "addpath", FILE_COMPL, {(char *)NULL} }, + { "path", FILE_COMPL, {(char *)NULL} }, + { "logcommands", FILE_COMPL, {(char *)NULL} }, + { "startrsim", FILE_COMPL, {(char *)NULL} }, + { "rsim", FILE_COMPL, {(char *)NULL} }, + { "source", FILE_COMPL, {(char *)NULL} }, + { "save", FILE_COMPL, {(char *)NULL} }, + + { "getcell", CELL_COMPL, {(char *)NULL} }, + { "child", CELL_COMPL, {(char *)NULL} }, + { "parent", CELL_COMPL, {(char *)NULL} }, + { "dump", CELL_COMPL, {(char *)NULL} }, + { "list", CELL_COMPL, {(char *)NULL} }, + { "load", CELL_COMPL, {(char *)NULL} }, + { "xload", CELL_COMPL, {(char *)NULL} }, + + { "macro", MACRO_COMPL, {(char *)NULL} }, + { "imacro", IMACRO_COMPL, {(char *)NULL} }, + { "see*", LAYER_COMPL, {(char *)NULL} }, + { "paint", LAYER_COMPL, {(char *)NULL} }, + + { "*extract", ARGS_COMPL, {"clrdebug", "clrlength", "driver", "interactions", + "intercount", "parents", "receiver", "setdebug", + "showdebug", "showparents", "showtech", "stats", + "step", "times", (char *)NULL} }, + + { "*garoute", ARGS_COMPL, {"clrdebug", "setdebug", "showdebug", (char *)NULL} }, + { "*groute", ARGS_COMPL, {"clrdebug", "onlynet", "setdebug", "showdebug", + "sides", (char *)NULL} }, + { "*iroute", ARGS_COMPL, {"debug", "help", "parms", (char *)NULL} }, + { "*malloc", ARGS_COMPL, {"all", "off", "on", "only", "watch", "unwatch", (char *)NULL} }, + { "*mzroute", ARGS_COMPL, {"debug", "dumpEstimates", "dumpTags", "help", + "numberLine", "parms", "plane", "version", (char *)NULL} }, + + { "*plow", ARGS_COMPL, {"help", "clrdebug", "jogreduce", "lwidth", "lshadow", + "mergedown", "mergeup", "move", "outline", "plow", + "print", "random", "setdebug", "shadow", "showdebug", + "split", "techshow", "trail", "whenbot", "whentop", + "width", (char *)NULL} }, + { "*plow lwidth", LAYER_COMPL, { (char *)NULL } }, + { "*plow width", LAYER_COMPL, { (char *)NULL } }, + { "*plow lshadow", LAYER_COMPL, { (char *)NULL } }, + { "*plow shadow", LAYER_COMPL, { (char *)NULL } }, + { "*plow techshow", FILE_COMPL, { (char *)NULL } }, + { "*plow outline", DIRECT_COMPL, { (char *)NULL } }, + { "*plow plow", DIRECT_COMPL, { (char *)NULL } }, + + { "*profile", ARGS_COMPL, {"on", "off", (char *)NULL} }, + { "*watch", PLANE_COMPL, {(char *)NULL} }, + { "*watch*", ARGS_COMPL, {"demo", "types", (char *)NULL} }, + + { "calma", ARGS_COMPL, {"help", "flatten", "labels", "lower", "noflatten", + "nolabels", "nolower", "read", "write", (char *)NULL} }, + { "calma read", FILE_COMPL, { (char *)NULL } }, + { "calma write", FILE_COMPL, { (char *)NULL } }, + + { "cif", ARGS_COMPL, {"help", "arealabels", "idcell", "istyle", "prefix", + "ostyle", "read", "see", "statistics", "write", "flat", (char *)NULL} }, + { "cif read", FILE_COMPL, { (char *)NULL } }, + { "cif flat", FILE_COMPL, { (char *)NULL } }, + { "cif write", FILE_COMPL, { (char *)NULL } }, + { "cif idcell", ARGS_COMPL, { "yes", "no", (char *)NULL } }, + { "cif arealabels", ARGS_COMPL, { "yes", "no", (char *)NULL } }, + { "cif prefix", FILE_COMPL, { (char *)NULL } }, + { "cif see", LAYER_COMPL, { (char *)NULL } }, + { "cif istyle", ISTYLE_COMPL, { (char *)NULL } }, + { "cif ostyle", OSTYLE_COMPL, { (char *)NULL } }, + + { "copy", DIRECT_COMPL, { (char *)NULL } }, + { "move", DIRECT_COMPL, { (char *)NULL } }, + { "stretch", DIRECT_COMPL, { (char *)NULL } }, + + { "drc", ARGS_COMPL, {"help", "catchup", "check", "count", "find", "off", + "on", "printrules", "rulestats", "statistics", "why", (char *)NULL} }, + { "drc printrules", FILE_COMPL, { (char *)NULL } }, + + { "ext", ARGS_COMPL, {"help", "all", "cell", "do", "length", "no", "parents", + "showparents", "style", "unique", "warn", (char *)NULL} }, + { "ext style", OSTYLE_COMPL, { (char *)NULL } }, + + { "feedback", ARGS_COMPL, {"help", "add", "clear", "count", "find", "save", + "why", "fill", (char *)NULL} }, + { "feedback save", FILE_COMPL, { (char *)NULL } }, + + { "garoute", ARGS_COMPL, {"help", "channel", "generate", "nowarn", "route", + "reset", "warn", (char *)NULL} }, + { "getnode", ARGS_COMPL, {"alias", "fast", "abort", (char *)NULL} }, + + { "iroute", ARGS_COMPL, {"help", "contacts", "layers", "route", + "saveParameters", "search", "spacings", "verbosity", + "version", "wizard", (char *)NULL} }, + { "iroute help", ARGS_COMPL, {"contacts", "layers", "route", + "saveParameters", "search", "spacings", "verbosity", + "version", "wizard", (char *)NULL} }, + + { "plot", ARGS_COMPL, {"help", "postscript", "gremlin", "versatec", "pnm", + "parameters", (char *)NULL} }, + { "plot postscript", FILE_COMPL, { (char *)NULL } }, + { "plot gremlin", FILE_COMPL, { (char *)NULL } }, + { "plot versatec", FILE_COMPL, { (char *)NULL } }, + { "plot pnm", FILE_COMPL, { (char *)NULL } }, + + { "plow", ARGS_COMPL, {"help", "boundary", "horizon", "jogs", "selection", + "straighten", "noboundary", "nojogs", "nostraighten", (char *)NULL} }, + { "plow selection", DIRECT_COMPL, { (char *)NULL } }, + + { "route", ARGS_COMPL, {"help", "end", "jog", "metal", "netlist", "obstacle", + "origin", "stats", "settings", "steady", "tech", + "vias", "viamin", (char *)NULL} }, + { "route netlist", FILE_COMPL, { (char *)NULL } }, + + { "select", ARGS_COMPL, {"help", "more", "less", "area", "visible", "cell", + "clear", "save", "box", (char *)NULL} }, + { "select save", FILE_COMPL, { (char *)NULL } }, + { "select more", ARGS_COMPL, { "area", "visible", "cell", "box", (char *)NULL } }, + { "select less", ARGS_COMPL, { "area", "visible", "cell", "box", (char *)NULL } }, + { "select more area", LAYER_COMPL, { (char *)NULL } }, + { "select less area", LAYER_COMPL, { (char *)NULL } }, + { "select more visible", LAYER_COMPL, { (char *)NULL } }, + { "select less visible", LAYER_COMPL, { (char *)NULL } }, + { "select more cell", CELL_COMPL, { (char *)NULL } }, + { "select less cell", CELL_COMPL, { (char *)NULL } }, + { "select more box", LAYER_COMPL, { (char *)NULL } }, + { "select less box", LAYER_COMPL, { (char *)NULL } }, + + { "send", ARGS_COMPL, {"netlist", "color", "layout", +#ifdef THREE_D + "wind3d", +#endif + (char *)NULL} }, + { "snap", ARGS_COMPL, {"on", "off", (char *)NULL} }, + { "tool", ARGS_COMPL, {"box", "wiring", "netlist", "rsim", (char *)NULL} }, + { "wire", ARGS_COMPL, {"help", "horizontal", "leg", "switch", "type", + "vertical", (char *)NULL} }, + { "wire type", LAYER_COMPL, { (char *)NULL } }, + { "wire switch", LAYER_COMPL, { (char *)NULL } }, + +#ifdef USE_READLINE + { "history", ARGS_COMPL, {"n", "r", "help", (char *)NULL} }, +#endif + { (char *)NULL , 0, {(char *)NULL} } +}; +#endif + + +/* Characters for input processing. Set to -1 if not defined */ + +char *TxGetLinePfix(); + +char txEraseChar = -1; /* Erase line (e.g. ^H) */ +char txKillChar = -1; /* Kill line (e.g. ^U or ^X) */ +char txWordChar = -1; /* Erase a word (e.g. ^W) */ +char txReprintChar = -1; /* Reprint the line (e.g. ^R */ +char txLitChar = -1; /* Literal next character (e.g. ^V */ +char txBreakChar = -1; /* Break to a new line (normally -1) */ +char TxEOFChar = -1; /* The current EOF character (e.g. ^D) */ +char TxInterruptChar = -1; /* The current interrupt character (e.g. ^C) */ + +static char txPromptChar; /* the current prompt */ +bool txHavePrompt = FALSE; /* is a prompt on the screen? */ + +char *txReprint1 = NULL; +char *txReprint2 = NULL; + +/* + * ---------------------------------------------------------------------------- + * + * TxReprint -- + * + * Reprint the current input line. Used for ^R and after ^Z. + * + * Results: + * None. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +TxReprint() +{ + (void) txFprintfBasic(stdout, "\n"); + if (txReprint1 != NULL) (void) txFprintfBasic(stdout, "%s", txReprint1); + if (txReprint2 != NULL) (void) txFprintfBasic(stdout, "%s", txReprint2); + (void) fflush(stdout); +} + +#ifndef MAGIC_WRAPPER + +/* + * ---------------------------------------------------------------------------- + * TxDialog -- + * + * Interactive input with a prompt and a fixed set of responses + * + * Results: + * Returns the index of the response chosen. If no response is given, + * returns the default value. + * + * Side effects: + * Terminal input and output (stdout, stdin). + * + * ---------------------------------------------------------------------------- + */ + +int +TxDialog(prompt, responses, deflt) + char *prompt; + char *(responses[]); + int deflt; +{ + int code; + int maxresp; + char ans[100]; + + /* Find size of valid response set */ + for (maxresp = 0; responses[maxresp] != NULL; maxresp++); + + /* Get input until something matches one of the responses */ + do + { + TxPrintf("%s ", prompt); + if ((deflt >= 0) && (deflt < maxresp)) + TxPrintf("[%s] ", responses[deflt]); + TxFlushOut(); + + if (TxGetLine(ans, sizeof ans) == NULL || (ans[0] == '\0')) + { + code = deflt; + break; + } + } while ((code = Lookup(ans, responses)) < 0); + + return code; +} + + +/* + * ---------------------------------------------------------------------------- + * TxSetPrompt -- + * + * Set the current prompt. + * + * Results: + * None. + * + * Side effects: + * You can guess. + * ---------------------------------------------------------------------------- + */ + +void +TxSetPrompt(ch) + char ch; +{ + txPromptChar = ch; +} + +#endif + + +/* + * ---------------------------------------------------------------------------- + * TxPrompt -- + * + * Put up the prompt which was set by TxSetPrompt. + * + * Results: + * None. + * + * Side effects: + * You can guess. + * ---------------------------------------------------------------------------- + */ + +void +TxPrompt() +{ + static char lastPromptChar; + static char prompts[2]; + + if (txHavePrompt && (lastPromptChar == txPromptChar)) return; + + (void) fflush(stderr); + if (txHavePrompt) TxUnPrompt(); + + prompts[0] = txPromptChar; + prompts[1] = '\0'; + + txReprint1 = prompts; + if (TxInteractive) txFprintfBasic(stdout, "%s", txReprint1); + (void) fflush(stdout); + txHavePrompt = TRUE; + lastPromptChar = txPromptChar; +} + + +/* + * ---------------------------------------------------------------------------- + * TxRestorePrompt -- + * + * The prompt was erased for some reason. Restore it. + * + * Results: + * None. + * + * Side effects: + * You can guess. + * ---------------------------------------------------------------------------- + */ + +void +TxRestorePrompt() +{ + if (txHavePrompt) + { + txHavePrompt = FALSE; + TxPrompt(); + } +} + + +/* + * ---------------------------------------------------------------------------- + * TxUnPrompt -- + * + * Erase the prompt. + * + * Results: + * None. + * + * Side effects: + * You can guess. + * ---------------------------------------------------------------------------- + */ + + +void +TxUnPrompt() +{ + int i, tlen; + + if (txHavePrompt) + { + (void) fflush(stderr); + if (TxInteractive) + { + tlen = strlen(txReprint1); + for (i = 0; i < tlen; i++) + fputc('\b', stdout); + for (i = 0; i < tlen; i++) + fputc(' ', stdout); + for (i = 0; i < tlen; i++) + fputc('\b', stdout); + } + (void) fflush(stdout); + txReprint1 = NULL; + txHavePrompt = FALSE; + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * TxGetChar -- + * + * Get a single character from the input stream (terminal or whatever). + * + * Results: + * One character, or EOF. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +TxGetChar() +{ + int ch; + extern DQueue txInputEvents, txFreeEvents; + extern TxInputEvent txLastEvent; + TxInputEvent *event; + while (TRUE) { + /* Get an input character. Don't let TxGetInputEvent return + * because of a SigWinch or whatever. It would be nice to process + * SigWinches in a middle of text input, but that is difficult + * to do since SigWinches are processed in the normal + * command-interpretation process. Thus, we delay the processing + * until after the text is collected. + */ + if (DQIsEmpty(&txInputEvents)) TxGetInputEvent(TRUE, FALSE); + event = (TxInputEvent *) DQPopFront(&txInputEvents); + ASSERT(event != NULL, "TxGetChar"); + txLastEvent = *event; + if (event->txe_button == TX_EOF) { + ch = EOF; + goto gotone; + } + if (event->txe_button == TX_CHARACTER) { + ch = TranslateChar(event->txe_ch); + goto gotone; + } + DQPushRear(&txFreeEvents, (ClientData) event); + } + +gotone: + DQPushRear(&txFreeEvents, (ClientData) event); + return ch; +} + + +#ifdef USE_READLINE +#undef free +/* + * ---------------------------------------------------------------------------- + * TxPrefix -- + * Instantiation of the readline function *rl_pre_input_hook(), executed + * between the prompt and the input (readline v4.1). Prepends the text + * of an interactive macro (if non-NULL) to the command line. + * + * ---------------------------------------------------------------------------- + */ +int +TxPrefix(void) +{ + if (_rl_prefix != NULL) + rl_insert_text(_rl_prefix); + rl_redisplay(); +} + +/* + * ---------------------------------------------------------------------------- + * + * magic_completion_function -- + * + * Command-name completion function for use with "readline" package. + * + * ---------------------------------------------------------------------------- + */ + +char ** +magic_completion_function(char *text, int start, int end) +{ + CPFunction *completion_func = (CPFunction *)NULL; + char **matches, **tokens; + char *line = strdup(rl_line_buffer); + int i; + + for (i = start; i >= 0; i--) + if( isspace(line[i]) || line[i] == ';' ) + break; + line[i+1] = '\0'; + + if ((tokens = history_tokenize(line)) != NULL ) + { + int entry, start_token, num_tokens; + + num_tokens = 0; + while (tokens[num_tokens] != (char *)NULL ) + num_tokens++; + + for (start_token = num_tokens - 1; start_token >= 0; start_token--) + if (tokens[start_token][0] == ';') + break; + + start_token++; + + line[0] = '\0'; + for (i = start_token; i < num_tokens; i++) + { + strcat(line, tokens[i]); + if (i < (num_tokens - 1)) + strcat(line, " "); + } + + entry = LookupStructFull(line, (char **)&magic_cmd_spec, + sizeof(struct cmd_spec)); + + if (entry == -1 && num_tokens >= 1) + { + sprintf(line, "%s*", tokens[0]); + entry = LookupStructFull(line, (char **)&magic_cmd_spec, + sizeof(struct cmd_spec)); + } + + if (entry >= 0) + { + switch (magic_cmd_spec[entry].type) + { + case COMMAND_COMPL: + completion_func = list_completion_function; + completion_list = magic_command_list; + break; + case MACRO_COMPL: + completion_func = macro_completion_function; + interactive_flag = 0; + break; + case IMACRO_COMPL: + completion_func = macro_completion_function; + interactive_flag = 1; + break; + case LAYER_COMPL: + completion_func = list_completion_function; + if (magic_techtype_list == (char **)NULL) + make_techtype_list(); + completion_list = magic_techtype_list; + break; + case PLANE_COMPL: + completion_func = list_completion_function; + completion_list = DBPlaneLongNameTbl; + break; + case FILE_COMPL: + completion_func = (text[0] == '~') ? + rl_username_completion_function : + rl_filename_completion_function; + break; + case CELL_COMPL: + update_cellname_hash(); + completion_func = cellname_completion_function; + break; + case ARGS_COMPL: + completion_func = list_completion_function; + completion_list = magic_cmd_spec[entry].args; + break; + case ISTYLE_COMPL: + completion_func = istyle_completion_function; + break; + case OSTYLE_COMPL: + completion_func = ostyle_completion_function; + break; + case DIRECT_COMPL: + completion_func = list_completion_function; + completion_list = magic_direction_list; + break; + } + } + + for (i = 0; i < num_tokens; i++) + free(tokens[i]); + + free(tokens); + + } + else + { + completion_func = list_completion_function; + completion_list = magic_command_list; + } + + free(line); + + matches = (completion_func) ? rl_completion_matches(text, completion_func) + : (char **)NULL; + + /* If we match nothing, inhibit any matching, except when matching files */ + + rl_attempted_completion_over = (matches == (char **)NULL && + completion_func != rl_username_completion_function && + completion_func != rl_filename_completion_function); + return matches; +} + +/* + * ---------------------------------------------------------------------------- + * + * update_cellname_hash -- + * + * Update the hash table of cell names so it can be used by the + * cellname completion function. + * + * ---------------------------------------------------------------------------- + */ +void +update_cellname_hash(void) +{ + extern char *nextName(char **, char *, char *, int); + extern char *Path; + char *path = Path; + char *dirname = strdup(Path); + + while (nextName(&path, "", dirname, strlen(Path))) + { + DIR *dir; + + if (strlen(dirname) == 0) + strcpy(dirname, "."); + + dir = opendir(dirname); + + if (dir != NULL) + { + struct dirent *dirent; + while ((dirent = readdir(dir)) != (struct dirent *)NULL) + { + char *base; + if ((base = (char *)strstr(dirent->d_name, DBSuffix)) + != (char *)NULL && base[strlen(DBSuffix)] == '\0') + { + *base = '\0'; + if (strlen(dirent->d_name) > 0) + HashFind(&cellname_hash, dirent->d_name); + } + } + closedir(dir); + } + } + free(dirname); +} + +/* + * ---------------------------------------------------------------------------- + * + * istyle_completion_function -- + * + * CIF input style completion function for use with "readline" package. + * + * ---------------------------------------------------------------------------- + */ +char * +istyle_completion_function(char *text, int state) +{ + extern CIFReadKeep *cifReadStyleList; + static CIFReadKeep *style; + static int len; + + if (state == 0) + { + style = cifReadStyleList; + len = strlen(text); + } + + for (; style != NULL; style = style->crs_next) + { + if (strncmp(style->crs_name, text, len) == 0) + { + char *name = style->crs_name; + style = style->crs_next; + return strdup(name); + } + } + return (char *)NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * ostyle_completion_function -- + * + * CIF output style completion function for use with "readline" package. + * + * ---------------------------------------------------------------------------- + */ +char * +ostyle_completion_function(char *text, int state) +{ + extern CIFKeep *CIFStyleList; + static CIFKeep *style; + static int len; + + if (state == 0) + { + style = CIFStyleList; + len = strlen(text); + } + + for (; style != NULL; style = style->cs_next) + { + if (strncmp(style->cs_name, text, len) == 0) + { + char *name = style->cs_name; + style = style->cs_next; + return strdup(name); + } + } + return (char *)NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * cellname_completion_function -- + * + name completion function for use with "readline" package. + * + * ---------------------------------------------------------------------------- + */ +char * +cellname_completion_function(char *text, int state) +{ + extern HashTable dbCellDefTable; + static int len; + static HashSearch hs, db_hs; + HashEntry *he; + + if (state == 0) + { + len = strlen(text); + HashStartSearch(&hs); + HashStartSearch(&db_hs); + } + + while ((he = HashNext(&cellname_hash, &hs)) != (HashEntry *)NULL ) + { + if (strncmp(he->h_key.h_name, text, len) == 0) + return strdup(he->h_key.h_name); + } + + /* Also complete cells that are in main memory only */ + + while ((he = HashNext(&dbCellDefTable, &db_hs)) != (HashEntry *)NULL) + { + CellDef *cd = (CellDef *)HashGetValue(he); + if (cd && !(cd->cd_flags & CDINTERNAL) + && strcmp(cd->cd_name, UNNAMED) != 0 + && strncmp(cd->cd_name, text, len) == 0) + return strdup(cd->cd_name); + } + return (char *)NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * macro_completion_function -- + * + * Macro completion function for use with "readline" package. + * + * ---------------------------------------------------------------------------- + */ +char * +macro_completion_function(char *text, int state) +{ + extern HashTable MacroClients; + static HashSearch hs, mc_hs; + static int len; + macrodef *macro; + HashEntry *he; + + if (state == 0) + { + len = strlen(text); + HashStartSearch(&hs); + } + + while ((he = HashNext(&MacroClients, &hs)) != (HashEntry *)NULL ) + { + HashTable *ht = (HashTable *)HashGetValue(he); + HashEntry *hm; + + if (state == 0) + HashStartSearch(&mc_hs); + + while ((hm = HashNext(ht, &mc_hs)) != (HashEntry *)NULL ) + { + macro = (macrodef *)HashGetValue(hm); + if ((macro->interactive == TRUE && interactive_flag == 1) || + (macro->interactive == FALSE && interactive_flag == 0)) + { + char *macro_name = MacroName(macro->macrotext); + if (strncmp(macro_name, text, len) == 0) + return strdup(macro_name); + } + } + } + return (char *)NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * list_completion_function -- + * + * List completion function for use with "readline" package. + * + * ---------------------------------------------------------------------------- + */ +char * +list_completion_function(char *text, int state) +{ + static int list_index, len; + char *match; + + /* If this is a new word to complete, initialize now. This includes + * saving the length of TEXT for efficiency, and initializing the index + * variable to 0. + */ + + if (state == 0) + { + list_index = 0; + len = strlen(text); + } + + /* Return the next name which partially matches from the command list. */ + + while ((match = completion_list[list_index]) != (char *)NULL) + { + list_index++; + + if (strncmp(match, text, len) == 0) + return strdup(match); + } + return (char *)NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * make_techtype_list -- + * + * Generate list of predefined types for use with completion function + * + * ---------------------------------------------------------------------------- + */ +void +make_techtype_list(void) +{ + int i, techdep_layers = DBNumUserLayers - TT_TECHDEPBASE; + + magic_techtype_list = (char **)mallocMagic(sizeof(char *) + * (techdep_layers + 8 + 2 + 1)); + + for (i = 0; i < techdep_layers; i++) + magic_techtype_list[i] = DBTypeLongNameTbl[i+TT_TECHDEPBASE]; + + magic_techtype_list[i++] = (char *)"magnet"; + magic_techtype_list[i++] = (char *)"fence"; + magic_techtype_list[i++] = (char *)"rotate"; + magic_techtype_list[i++] = (char *)"subcircuit"; + magic_techtype_list[i++] = (char *)"$"; + magic_techtype_list[i++] = (char *)"*"; + magic_techtype_list[i++] = (char *)"errors"; + magic_techtype_list[i++] = (char *)"labels"; + magic_techtype_list[i++] = (char *)"subcell"; + + magic_techtype_list[i++] = (char *)"no"; + magic_techtype_list[i++] = (char *)"allSame"; + + magic_techtype_list[i] = (char *)NULL; +} + +#define free You_should_use_the_Magic_procedure_freeMagic +#endif + +/* + * ---------------------------------------------------------------------------- + * + * TxGetLineWPrompt -- + * + * Just like the following TxGetLine proc, but it prompts first. It + * is an advantage to have this proc put out the prompt, since that + * way if the user suspends Magic and then continues it the prompt will + * reappear in the proper fashion. + * + * Results: + * A char pointer or NULL (see TxGetLine). + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +char * +TxGetLineWPrompt(dest, maxChars, prompt, prefix) + char *dest; + int maxChars; + char *prompt; + char *prefix; +{ + char *res, *hist_res, *tmp; + int return_nothing = 0; + + if (txHavePrompt) TxUnPrompt(); +#ifndef USE_READLINE + /* without GNU readline */ + + if (prompt != NULL) TxPrintf("%s", prompt); + txReprint1 = prompt; + + res = TxGetLinePfix(&dest[0], maxChars, prefix); + txReprint1 = NULL; +#else + _rl_prefix = prefix; + TxResetTerminal (); + + if (prompt != NULL) { + res = readline (prompt); + } else { + res = readline (TX_CMD_PROMPT); + } + + hist_res = (char *)NULL; + + if (res && *res && !StrIsWhite(res, FALSE) ) { + /* The history_expand() function from Readline can return 4 values: */ + /* -1 - There was an error in expansion. Command not added to history. */ + /* This is the same behavior as tcsh. */ + /* 0 - No expansion possible. Just a normal command. Add command to history, */ + /* return and execute. */ + /* 1 - Expansion took place. Assign $command to expansion and proceed. */ + /* 2 - Expansion took place (eg. :p modifier was used). Display exspansion */ + /* but don't execute. Expanded command implicitly added to history by */ + /* history_expand(). */ + switch( history_expand(res, &hist_res) ) { + case -1: + TxError("%s\n", hist_res); + return_nothing = 1; + break; + case 0: + add_history(res); + break; + case 1: + tmp = res; + res = hist_res; + hist_res = tmp; + add_history(res); + break; + case 2: + TxPrintf("%s\n", hist_res); + return_nothing = 1; + break; + } + } + + if (res) { + if (strlen (res) >= maxChars) { + TxPrintf ("WARNING: input string too long; truncated"); + res[maxChars-1] = '\0'; + } + if( return_nothing ) { + dest[0] = '\0'; + } else { + strcpy (dest, res); + } +#undef free + free (res); + if( hist_res != (char *)NULL ) free(hist_res); +#define free You_should_use_the_Magic_procedure_freeMagic + res = dest; + } + TxSetTerminal (); +#endif + return res; +} + +/* + * ---------------------------------------------------------------------------- + */ + +char * +TxGetLinePrompt(dest, maxChars, prompt) + char *dest; + int maxChars; + char *prompt; +{ + return TxGetLineWPrompt(dest, maxChars, prompt, NULL); +} + +#ifndef MAGIC_WRAPPER + + +/* + * ---------------------------------------------------------------------------- + * TxGetLinePfix: + * + * Reads a line from the input queue (terminal or whatever). + * + * Results: + * A char pointer to the string is returned. + * If an end-of-file is typed, returns (char *) NULL and + * stores in the string any characters recieved up to that point. + * + * Side effects: + * The input stream is read, and 'dest' is filled in with up to maxChars-1 + * characters. Up to maxChars of the 'dest' may be changed during the + * input process, however, since a '\0' is added at the end. There is no + * newline at the end of 'dest'. + * ---------------------------------------------------------------------------- + */ + +char * +TxGetLinePfix(dest, maxChars, prefix) + char *dest; + int maxChars; + char *prefix; +{ + int i; + char *ret; + int ch; + bool literal; + + if (maxChars < 1) return dest; + if (txHavePrompt) TxUnPrompt(); + ret = dest; + dest[0] = '\0'; + txReprint2 = dest; + +#define TX_ERASE() ( (i>0) ?(i--, TxPrintf("\b \b"), 0) :0) + + (void) fflush(stderr); + literal = FALSE; + i = 0; + if (prefix != NULL) + { + while (prefix[i] != '\0') { + if (i >= maxChars - 1) break; + dest[i] = prefix[i]; + txFprintfBasic(stdout, "%c", prefix[i]); + i++; + } + } + while (TRUE) { + dest[i] = '\0'; + if (i >= maxChars - 1) break; + (void) fflush(stdout); + ch = TxGetChar(); + if (ch == EOF || ch == -1 || ch == TxEOFChar) { + TxError("\nEOF encountered on input stream.\n"); + ret = NULL; + break; + } else if (literal) { + literal = FALSE; + dest[i] = ch; + txFprintfBasic(stdout, "%c", ch); + i++; + } else if (ch == '\n' || ch == txBreakChar) { + break; + } else if (ch == '\t') { + while (TRUE) { + dest[i] = ' '; + txFprintfBasic(stdout, " "); + i++; + if (((i + strlen(txReprint1)) % 8) == 0) break; + } + } else if (ch == txEraseChar) { + TX_ERASE(); + } else if (ch == txKillChar) { + while (i > 0) TX_ERASE(); + } else if (ch == txWordChar) { + while (i > 0 && isspace(dest[i-1])) TX_ERASE(); + while (i > 0 && !isspace(dest[i-1])) TX_ERASE(); + } else if (ch == txReprintChar) { + TxReprint(); + } else if (ch == txLitChar) { + literal = TRUE; + } else { + dest[i] = ch; + txFprintfBasic(stdout, "%c", ch); + i++; + } + } + txFprintfBasic(stdout, "\n"); + txHavePrompt = FALSE; + txReprint2 = NULL; + + return ret; +} + +#endif + +/* + * ---------------------------------------------------------------------------- + * TxGetLine: + */ + +char * +TxGetLine(dest, maxChars) + char *dest; + int maxChars; +{ + return TxGetLinePfix(dest, maxChars, NULL); +} + + +/* + * ---------------------------------------------------------------------------- + * txGetTermState: + * + * Read the state of the terminal and driver. + * + * Results: + * none. + * + * Side effects: + * The passed structure is filled in. + * ---------------------------------------------------------------------------- + */ + +#if defined(SYSV) || defined(CYGWIN) + +void +txGetTermState(buf) + struct termio *buf; + +{ + ioctl( fileno( stdin ), TCGETA, buf); +} + +#else + +void +txGetTermState(buf) + txTermState *buf; +{ + ASSERT(TxStdinIsatty, "txGetTermState"); + /* save the current terminal characteristics */ + (void) ioctl(fileno(stdin), TIOCGETP, (char *) &(buf->tx_i_sgtty) ); + (void) ioctl(fileno(stdin), TIOCGETC, (char *) &(buf->tx_i_tchars) ); +} +#endif /* SYSV */ + + +/* + * ---------------------------------------------------------------------------- + * txSetTermState: + * + * Set the state of the terminal and driver. + * + * Results: + * none. + * + * Side effects: + * The terminal driver is set up. + * ---------------------------------------------------------------------------- + */ + +void +txSetTermState(buf) +#if defined(SYSV) || defined(CYGWIN) + struct termio *buf; +#else + txTermState *buf; +#endif /* SYSV */ +{ +#if defined(SYSV) || defined(CYGWIN) + ioctl( fileno(stdin), TCSETAF, buf ); +#else + /* set the current terminal characteristics */ + (void) ioctl(fileno(stdin), TIOCSETN, (char *) &(buf->tx_i_sgtty) ); + (void) ioctl(fileno(stdin), TIOCSETC, (char *) &(buf->tx_i_tchars) ); +#endif /* SYSV */ +} + + + +/* + * ---------------------------------------------------------------------------- + * txInitTermRec: + * + * Sets the terminal record that it has echo turned off, + * cbreak on, and no EOFs the way we like it. + * + * Results: + * None. + * + * Side effects: + * The passed terminal record is modified. + * No terminal modes are actually changed. + * ---------------------------------------------------------------------------- + */ + +void +txInitTermRec(buf) +#if defined(SYSV) || defined(CYGWIN) + struct termio *buf; +#else + txTermState *buf; +#endif /* SYSV */ +{ +#if defined(SYSV) || defined(CYGWIN) + buf->c_lflag = ISIG; /* raw: no echo and no processing, allow signals */ + buf->c_cc[ VMIN ] = 1; + buf->c_cc[ VTIME ] = 0; +#else + /* set things up for us, turn off echo, turn on cbreak, no EOF */ + buf->tx_i_sgtty.sg_flags |= CBREAK; + buf->tx_i_sgtty.sg_flags &= ~ECHO; + buf->tx_i_tchars.t_eofc = -1; + +#endif /* SYSV */ +} + + + +#if defined(SYSV) || defined(CYGWIN) +struct termio closeTermState; +#else +static txTermState closeTermState; +#endif /* SYSV */ + +static bool haveCloseState = FALSE; + +/* + * ---------------------------------------------------------------------------- + * txSaveTerm: + * + * Save the terminal characteristics so they can be restored when + * magic leaves. + * + * + * Results: + * none. + * + * Side effects: + * a global variable is set. + * ---------------------------------------------------------------------------- + */ + +void +txSaveTerm() +{ +#if defined(SYSV) || defined(CYGWIN) + ioctl( fileno( stdin ), TCGETA, &closeTermState); + txEraseChar = closeTermState.c_cc[VERASE]; + txKillChar = closeTermState.c_cc[VKILL]; + TxEOFChar = closeTermState.c_cc[VEOF]; + TxInterruptChar = closeTermState.c_cc[VINTR]; + haveCloseState = TRUE; +#else + struct ltchars lt; + txGetTermState(&closeTermState); + (void) ioctl(fileno(stdin), TIOCGLTC, (char *) <); + txEraseChar = closeTermState.tx_i_sgtty.sg_erase; + txKillChar = closeTermState.tx_i_sgtty.sg_kill; + txWordChar = lt.t_werasc; + txReprintChar = lt.t_rprntc; + txLitChar = lt.t_lnextc; + txBreakChar = closeTermState.tx_i_tchars.t_brkc; + TxEOFChar = closeTermState.tx_i_tchars.t_eofc; + TxInterruptChar = closeTermState.tx_i_tchars.t_intrc; + haveCloseState = TRUE; +#endif /* SYSV */ +} + + +/* + * ---------------------------------------------------------------------------- + * TxSetTerminal: + * + * Sets the terminal up the way we like it. + * + * Results: + * none. + * + * Side effects: + * The terminal modes are changed. + * ---------------------------------------------------------------------------- + */ + +void +TxSetTerminal() +{ +#if defined(SYSV) || defined(CYGWIN) + struct termio buf; +#else + txTermState buf; +#endif /* SYSV */ + +#ifdef MAGIC_WRAPPER + /* If using Tk console, don't mess with the terminal settings; */ + /* Otherwise, this prevents running magic in the terminal background. */ + if (TxTkConsole) return; +#endif + + if (TxStdinIsatty) + { + if (!haveCloseState) txSaveTerm(); + buf = closeTermState; + txInitTermRec(&buf); + txSetTermState(&buf); + } +} + + +/* + * ---------------------------------------------------------------------------- + * TxResetTerminal: + * + * Returns the terminal to the way it was when Magic started up. + * + * Results: + * none. + * + * Side effects: + * The terminal modes are changed. + * ---------------------------------------------------------------------------- + */ + +void +TxResetTerminal() +{ + +#ifdef MAGIC_WRAPPER + /* If using Tk console, don't mess with the terminal settings; */ + /* Otherwise, this prevents running magic in the terminal background. */ + if (TxTkConsole) return; +#endif + + if (TxStdinIsatty && haveCloseState) txSetTermState(&closeTermState); +} diff --git a/textio/txMain.c b/textio/txMain.c new file mode 100644 index 00000000..92a241f8 --- /dev/null +++ b/textio/txMain.c @@ -0,0 +1,171 @@ +/* + * txMain.c -- + * + * This module handles output to the text terminal as well as + * collecting input and sending the commands to the window package. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/textio/txMain.c,v 1.2 2010/03/08 13:33:34 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magsgtty.h" +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "textio/txcommands.h" +#include "textio/textioInt.h" +#include "windows/windows.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "dbwind/dbwind.h" + +/* Global variables that indicate if we are reading or writing to a tty. + */ +global bool TxStdinIsatty; +global bool TxStdoutIsatty; + +#ifdef USE_READLINE +#ifdef HAVE_READLINE +#include +#include +#else +#include "readline/readline.h" +#include "readline/history.h" +#endif + +int TxPrefix(void); +char **magic_completion_function(char *, int, int); +extern HashTable cellname_hash; + +/* The readline completion function requires a command list containing */ +/* just the command name (without the accompanying help text line) */ +extern char **magic_command_list; + +#endif + + +/* + * ---------------------------------------------------------------------------- + * TxInit: + * + * Initialize this module. + * + * + * Results: + * None. + * + * Side effects: + * misc. + * ---------------------------------------------------------------------------- + */ + +void +TxInit() +{ + static char sebuf[BUFSIZ]; + + setbuf(stderr, sebuf); + setbuf(stdin, (char *) NULL); /* required for LPENDIN in textio to work */ + TxStdinIsatty = (isatty(fileno(stdin))); + +#ifdef MAGIC_WRAPPER + TxStdoutIsatty = 0; /* Tx loop is non-interactive */ +#else + TxStdoutIsatty = (isatty(fileno(stdout))); +#endif + + txCommandsInit(); +} + +#ifdef USE_READLINE + +void +TxInitReadline() +{ + int i, j; + char **commandTable; + char nobell[] = "set bell-style none"; + + rl_getc_function = TxGetChar; + rl_pre_input_hook = TxPrefix; + rl_readline_name = "magic"; + + /* the default behavior is for no terminal bell to ever ring */ + rl_parse_and_bind(nobell); + + /* read ~/.inputrc (or whatever INPUTRC is set to) to allow users to override */ + rl_read_init_file(NULL); + + /* removed "=" and "(" because styles contain them */ + rl_completer_word_break_characters = " \t\n\"\\'`@$><;|&{"; + + rl_attempted_completion_function = (CPPFunction *)magic_completion_function; + HashInit(&cellname_hash, 128, HT_STRINGKEYS); + + i = j = 0; + commandTable = WindGetCommandTable(DBWclientID); + while(commandTable[i++] != (char *)NULL ) { + j++; + } + i = 0; + commandTable = WindGetCommandTable(windClientID); + while(commandTable[i++] != (char *)NULL ) { + j++; + } + + magic_command_list = (char **)mallocMagic(sizeof(char *) * (j + 1)); + + i = j = 0; + commandTable = WindGetCommandTable(DBWclientID); + while( commandTable[i] != (char *)NULL ) { + int k = 0; + while( !isspace(commandTable[i][k]) && (commandTable[i][k] != '\0') ) { + k++; + } + if( k > 0 ) { + magic_command_list[j] = (char *)mallocMagic((k+1)*sizeof(char)); + strncpy(magic_command_list[j], commandTable[i], k); + magic_command_list[j][k] = '\0'; + j++; + } + i++; + } + i = 0; + commandTable = WindGetCommandTable(windClientID); + while( commandTable[i] != (char *)NULL ) { + int k = 0; + while( !isspace(commandTable[i][k]) && (commandTable[i][k] != '\0') ) { + k++; + } + if( k > 0 ) { + magic_command_list[j] = (char *)mallocMagic((k+1)*sizeof(char)); + strncpy(magic_command_list[j], commandTable[i], k); + magic_command_list[j][k] = '\0'; + j++; + } + i++; + } + magic_command_list[j] = (char *)NULL; + rl_completion_query_items = MAX(j+1, 250); +} + +#endif + diff --git a/textio/txMore.c b/textio/txMore.c new file mode 100644 index 00000000..1b0bb048 --- /dev/null +++ b/textio/txMore.c @@ -0,0 +1,53 @@ +/* txMore.c - + * + * Routine to pause until user hits `return' + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/textio/txMore.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" + + +/* + * ---------------------------------------------------------------------------- + * + * TxMore -- + * + * Wait for the user to hit a carriage-return. + * + * Results: + * None. + * + * Side effects: + * Prints a " --more--" prompt. + * + * ---------------------------------------------------------------------------- + */ + +void +TxMore(mesg) + char *mesg; +{ + char prompt[512]; + char line[512]; + + (void) sprintf(prompt, "%s --more-- (Hit to continue)", mesg); + (void) TxGetLinePrompt(line, sizeof line, prompt); +} diff --git a/textio/txOutput.c b/textio/txOutput.c new file mode 100644 index 00000000..a7880118 --- /dev/null +++ b/textio/txOutput.c @@ -0,0 +1,492 @@ +/* + * txOutput.c -- + * + * Handles 'stdout' and 'stderr' output. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/textio/txOutput.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#ifndef SYSV +#include +#endif /* SYSV */ +#include +#include + +#include "utils/magsgtty.h" +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "textio/txcommands.h" +#include "textio/textioInt.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "utils/paths.h" +#include "utils/utils.h" +#include "utils/malloc.h" + +/* When a pipe has been opened to "more", the following variables + * keep track of the file and process. The "TxMoreFile" variable is + * public so that routines like vfprintf() can check it to see if it + * is NULL or not. It is guaranteed to be NULL if we don't want to send + * stuff through more. + */ + +FILE * TxMoreFile = NULL; +static int txMorePid; +static bool txPrintFlag = TRUE; + + +/* + * ---------------------------------------------------------------------------- + * txFprintfBasic: + * + * Textio's own version of printf. Not to be used outside of this module. + * + * Tricks: + * Called with a variable number of arguments -- may not be portable. + * + * Results: + * None. + * + * Side effects: + * text appears on stdout on the text terminal + * + * Note: + * Many thanks to Paul Chow at Stanford for getting this to run on + * a Pyramid machine. + * ---------------------------------------------------------------------------- + */ + +void +txFprintfBasic(FILE *f, ...) +{ + va_list args; + char *fmt; + + va_start(args, f); + fmt = va_arg(args, char *); + Vfprintf(f, fmt, args); + va_end(args); +} + + +/* + * ---------------------------------------------------------------------------- + * TxPrintf: + * + * Magic's own version of printf + * + * Tricks: + * Called with a variable number of arguments -- may not be portable. + * + * Results: + * None. + * + * Side effects: + * text appears on stdout on the text terminal + * + * Note: + * Many thanks to Paul Chow at Stanford for getting this to run on + * a Pyramid machine. + * ---------------------------------------------------------------------------- + */ + +void +TxPrintf(char *fmt, ...) +{ + va_list args; + FILE *f; + + if (txPrintFlag) + { + if (TxMoreFile != NULL) + { + f = TxMoreFile; + } + else + { + f = stdout; + } + + if (txHavePrompt) + { + TxUnPrompt(); + va_start(args, fmt); + Vfprintf(f, fmt, args); + va_end(args); + TxPrompt(); + } + else + { + va_start(args, fmt); + Vfprintf(f, fmt, args); + va_end(args); + } + + return; + } +} + +/* + * ---------------------------------------------------------------------------- + * TxPrintString -- + * + * A version of printf which writes output into a string. + * + * Results: + * A string which is valid until the next call to TxPrintString(). + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +char * +TxPrintString(char *fmt, ...) +{ + va_list args; + static char *outstr = NULL; + static int outlen; + int nchars; + + if (outstr == NULL) + { + outlen = 100; + outstr = (char *) mallocMagic((unsigned) (outlen + 1)); + } + + va_start(args, fmt); + nchars = vsnprintf(outstr, outlen, fmt, args); + va_end(args); + + if (nchars >= outlen) + { + outlen = nchars + 1; + freeMagic(outstr); + outstr = (char *) mallocMagic((unsigned) (outlen + 1)); + va_start(args, fmt); + vsnprintf(outstr, outlen, fmt, args); + va_end(args); + } + if (nchars == -1) + return NULL; + + return outstr; +} + + +/* + * ---------------------------------------------------------------------------- + * TxPrintOn -- + * + * Enables TxPrintf() output. + * + * Results: + * Previous value of flag. + * + * ---------------------------------------------------------------------------- + */ + +bool +TxPrintOn() +{ + bool oldValue = txPrintFlag; + + txPrintFlag = TRUE; + + return oldValue; +} + + +/* + * ---------------------------------------------------------------------------- + * TxPrintOff -- + * + * Disables TxPrintf() output. + * + * Results: + * Previous value of flag. + * + * ---------------------------------------------------------------------------- + */ + +bool +TxPrintOff() +{ + bool oldValue = txPrintFlag; + + txPrintFlag = FALSE; + + return oldValue; +} + +#ifndef MAGIC_WRAPPER + + +/* + * ---------------------------------------------------------------------------- + * TxFlush -- + * + * Flush the standard out and error out. + * + * Results: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +TxFlushErr() +{ + (void) fflush(stderr); +} + +/*----------------------------------------------------------------------------*/ + +void +TxFlushOut() +{ + (void) fflush(stdout); +} + +/*----------------------------------------------------------------------------*/ + +void +TxFlush() +{ + TxFlushOut(); + TxFlushErr(); +} + +#endif + + +/* + * ---------------------------------------------------------------------------- + * TxError: + * + * Magic's own version of printf, but it goes to stderr + * + * Tricks: + * Called with a variable number of arguments -- may not be portable. + * + * Results: + * None. + * + * Side effects: + * text appears on stderr on the text terminal + * + * Note: + * Many thanks to Paul Chow at Stanford for getting this to run on + * a Pyramid machine. + * ---------------------------------------------------------------------------- + */ + +void +TxError(char *fmt, ...) +{ + va_list args; + FILE *f; + + TxFlushOut(); + if (TxMoreFile != NULL) + f = TxMoreFile; + else + f = stderr; + va_start(args, fmt); + if (txHavePrompt) + { + TxUnPrompt(); + Vfprintf(f, fmt, args); + TxPrompt(); + } + else { + Vfprintf(f, fmt, args); + } + va_end(args); + TxFlushErr(); +} + +#ifndef MAGIC_WRAPPER + + +/* + * ---------------------------------------------------------------------------- + * + * TxUseMore -- + * + * This procedure forks a "more" process and causes TxError and TxPrintf + * to send output through it. + * + * Results: + * None. + * + * Side effects: + * A file is opened. When the caller is finished with output, + * it must call TxStopMore to clean up the process. + * + * ---------------------------------------------------------------------------- + */ + +void +TxUseMore() +{ + int pipeEnds[2]; + int moreRunning = TRUE; + static int moreMsg = FALSE; + char *pagername, *pagerpath, *useenv = NULL; + extern char *getenv(); + struct stat buf; + + ASSERT(TxMoreFile == NULL, "TxUseMore"); + + /* Determine if "more" executable exists and is world executable */ + /* before attempting a fork. Check environment variable PAGER */ + /* first before defaulting to the built-in value PAGERDIR */ + /* (see utils/paths.h). */ + + if ((useenv = getenv("PAGER")) == NULL) + { + pagerpath = (char *) mallocMagic((unsigned) (strlen(PAGERDIR) + 1)); + strcpy(pagerpath, PAGERDIR); + } + else + pagerpath = useenv; + + if ((stat(pagerpath, &buf) < 0) || !(buf.st_mode & S_IXOTH)) + { + if (!moreMsg) + { + TxError("Couldn't execute %s to filter output.\nTry setting " + "environment variable PAGER to your favorite pager\n\n", + pagerpath); + moreMsg = TRUE; + } + goto done; + } + + pipe(pipeEnds); + FORK(txMorePid); + + /* In the child process, move the pipe input to standard input, + * delete the output stream, and then run "more". + */ + + if (txMorePid == 0) + { + char *argv[100]; + close(pipeEnds[1]); + dup2(pipeEnds[0], 0); + if ((pagername = strrchr(pagerpath, '/')) != (char *) 0) + pagername++; + else + pagername = pagerpath; + execl(pagerpath, pagername, 0); + + /* Something went very wrong if it gets here. */ + + _exit(-1); + } + + /* This is the parent process. Close the input descriptor and make + * an official FILE for the output descriptor. + */ + + close(pipeEnds[0]); + TxMoreFile = fdopen(pipeEnds[1], "w"); + +done: + if (useenv == NULL) freeMagic(pagerpath); + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * TxStopMore -- + * + * Close the pipe connecting us to a "more" process and wait for + * the "more" process to die. + * + * Results: + * None. + * + * Side effects: + * The connection to more is closed. + * + * ---------------------------------------------------------------------------- + */ + +void +TxStopMore() +{ + /* TxMoreFile may be NULL if the "more" executable was not found */ + if (TxMoreFile == NULL) return; + + /* Close the pipe. */ + ASSERT(txMorePid != 0, "TxStopMore"); + fclose(TxMoreFile); + TxMoreFile = NULL; + + /* Wait until there are no child processes left. This is a bit + * of a kludge, and may screw up if other child processes are + * created for other purposes at the same time, but I can't see + * any way around it. + */ + + WaitPid (txMorePid, 0); + txMorePid = 0; +} + +#endif /* !MAGIC_WRAPPER */ + +#ifdef NEED_VFPRINTF + +int +vfprintf(FILR *iop, char *fmt, va_list args_in) +{ + va_list ap; + int len; +#if defined(MIPSEB) && defined(SYSTYPE_BSD43) + unsigned char localbuf[BUFSIZ]; +#else + char localbuf[BUFSIZ]; +#endif + + va_copy(ap, args_in); + if (iop->_flag & _IONBF) { + iop->_flag &= ~_IONBF; + iop->_ptr = iop->_base = localbuf; + len = _doprnt(fmt, ap, iop); + (void) fflush(iop); + iop->_flag |= _IONBF; + iop->_base = NULL; + iop->_bufsiz = 0; + iop->_cnt = 0; + } else + len = _doprnt(fmt, ap, iop); + + va_end(ap); + return (ferror(iop) ? EOF : len); +} +#endif /* NEED_VFPRINTF */ + diff --git a/textio/txcommands.h b/textio/txcommands.h new file mode 100644 index 00000000..1cc7a3b3 --- /dev/null +++ b/textio/txcommands.h @@ -0,0 +1,163 @@ +/* + * txcommands.h -- + * + * Declarations for textio command routines. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/textio/txcommands.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _TXCOMMANDS_H +#define _TXCOMMANDS_H + +#include "utils/magic.h" +#include "utils/geometry.h" + +/* Structure of one Magic command. All commands are in the same format. + * Commands are tagged with the point and window at which the command was + * invoked. + */ + +/* The definitions below should be made variable. Especially with the + * Tcl/Tk version of magic, it is possible to auto-generate very long + * commands such as, for example, "polygon" + */ + +#define TX_MAXARGS 200 +#define TX_MAX_CMDLEN 2048 + +typedef struct { /* A command -- either a button push or + * a textual command. + */ + Point tx_p; /* The location of the pointing device + * when this command was invoked. + */ + int tx_button; /* The event type (button number). + * See below. + */ + int tx_buttonAction; /* The action of the button (if any), such as + * TX_BUTTON_UP, DOWN + */ + int tx_argc; /* The number of textual command words, + * including the command itself. 0 means + * no textual command. + */ + char *tx_argv[TX_MAXARGS]; /* An array of pointers to the words (if any) + * that make up the command. + */ + int tx_wid; /* The ID of the window that this command + * is destined for. The point 'tx_p' is + * in this window's coordinate system. + * (See windows.h for window IDs.) + */ + char tx_argstring[TX_MAX_CMDLEN]; + /* The storage used for the command line. + * Tx_argv[] points into this. + */ +} TxCommand; + +/* Structure of one low-level input event. This can be either a button event + * (such as a button down or a button up) or a keyboard event (such as a + * character typed. + */ + +typedef struct { + Point txe_p; /* The point at which this action took place.*/ + int txe_wid; /* The window that the event occured in (see + * windows.h for details, may be defaulted to + * WIND_UNKNOWN_WINDOW by some low-level + * device drivers). + */ + int txe_button; /* The event type. */ + int txe_buttonAction; /* The button action, if a button. */ + int txe_ch; /* The character typed, if a character. */ +} TxInputEvent; + +/* Event types (button numbers) in the above structures, carefully chosen so + * there is 1 bit per event (as they are used elsewhere in masks). + */ +#define TX_CHARACTER 0x00 +#define TX_NO_BUTTON 0x00 /* for backward compat. only */ +#define TX_LEFT_BUTTON 0x01 +#define TX_MIDDLE_BUTTON 0x02 +#define TX_RIGHT_BUTTON 0x04 +#define TX_EXPOSE 0x08 /* graphics commands for separate */ +#define TX_CONFIGURE 0x10 /* graphics event loops. */ +#define TX_CREATE 0x20 +#define TX_BYPASS 0x40 /* Input line is ready, but needs + * and event to trigger the callback + */ +#define TX_EOF 0x80 /* Never leaves this module, it is + * filtered out. + */ +#define TX_BUTTON_4 0x100 /* For scroll wheels and such */ +#define TX_BUTTON_5 0x200 /* For scroll wheels and such */ + +#ifdef MAGIC_WRAPPER +extern TxCommand TxCurCommand; +#endif + +/* Button actions for the above structures. + */ +#define TX_BUTTON_DOWN 0 +#define TX_BUTTON_UP 1 +#define TX_KEY_DOWN 2 + +/* procedures to help in making device command routines */ + +extern TxCommand *TxDeviceStdin(); +extern TxCommand *TxButtonMaskToCommand(); +extern void TxAddInputDevice(); /* Can read multiple file desc. */ +extern void TxAdd1InputDevice(); /* Can read only 1 file desc. */ +extern void TxDeleteInputDevice(); +extern void TxDelete1InputDevice(); + +/* Routines to manipulate the current point. Only really used for command + * scripts. + */ +extern void TxSetPoint(); +extern int TxGetPoint(); +extern void TxClearPoint(); + +/* Routine to set up command logging. + */ +extern void TxLogCommands(); + + +/* Routines for handling input events. A typical device driver in the + * graphics module will get one or more free events via TxNewEvent() and + * then put them in the input queue via TxAddEvent(). + */ + +extern TxInputEvent *TxNewEvent(); +extern void TxAddEvent(); +extern void TxPrintEvent(); +extern void TxFreeEvent(); +extern void TxReleaseButton(); + +/* Routines for dealing with commands. Usually only used within this + * module, although they may be used elsewhere. + */ +extern void TxPrintCommand(); +extern TxCommand *TxNewCommand(); +extern void TxFreeCommand(); +extern void TxParseString(); +extern void TxDispatch(); +extern int TxCommandNumber; /* Serial number of current command. */ + +#ifdef MAGIC_WRAPPER +extern int TxTclDispatch(); +#endif + +#endif /* _TXCOMMANDS_H */ diff --git a/tiles/Depend b/tiles/Depend new file mode 100644 index 00000000..3c04a383 --- /dev/null +++ b/tiles/Depend @@ -0,0 +1,5 @@ +tile.o: tile.c ../utils/magic.h ../utils/malloc.h ../utils/geometry.h \ + ../tiles/tile.h +search.o: search.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h +search2.o: search2.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/signals.h diff --git a/tiles/Makefile b/tiles/Makefile new file mode 100644 index 00000000..2bd943b3 --- /dev/null +++ b/tiles/Makefile @@ -0,0 +1,10 @@ +# +# rcsid "$Header: /usr/cvsroot/magic-8.0/tiles/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" +# + +MODULE = tiles +MAGICDIR = .. +SRCS = tile.c search.c search2.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/tiles/search.c b/tiles/search.c new file mode 100644 index 00000000..bd3bd4ad --- /dev/null +++ b/tiles/search.c @@ -0,0 +1,63 @@ +/* + * search.c -- + * + * Point searching. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/tiles/search.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" + + +/* + * -------------------------------------------------------------------- + * + * TiSrPoint -- + * + * Search for a point. + * + * Results: + * A pointer to the tile containing the point. + * The bottom and left edge of a tile are considered part of + * the tile; the top and right edge are not. + * + * Side effects: + * Updates the hint tile in the supplied plane to point + * to the tile found. + * + * -------------------------------------------------------------------- + */ + +Tile * +TiSrPoint(hintTile, plane, point) + Tile * hintTile; /* Pointer to tile at which to begin search. + * If this is NULL, use the hint tile stored + * with the plane instead. + */ + Plane * plane; /* Plane (containing hint tile pointer) */ + Point * point; /* Point for which to search */ +{ + Tile *tp = (hintTile) ? hintTile : plane->pl_hint; + + GOTOPOINT(tp, point); + plane->pl_hint = tp; + return(tp); +} diff --git a/tiles/search2.c b/tiles/search2.c new file mode 100644 index 00000000..8739f3ef --- /dev/null +++ b/tiles/search2.c @@ -0,0 +1,234 @@ +/* + * search2.c -- + * + * Area searching. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/tiles/search2.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/signals.h" + +/* -------------------- Local function headers ------------------------ */ + +int tiSrAreaEnum(); + +/* + * -------------------------------------------------------------------- + * + * TiSrArea -- + * + * Find all tiles contained in or incident upon a given area. + * Applies the given procedure to all tiles found. The procedure + * should be of the following form: + * + * int + * func(tile, cdata) + * Tile *tile; + * ClientData cdata; + * { + * } + * + * Func normally should return 0. If it returns 1 then the search + * will be aborted. + * + * THIS PROCEDURE IS OBSOLETE EXCEPT FOR THE SUBCELL PLANE. USE + * DBSrPaintArea() IF YOU WANT TO SEARCH FOR PAINT TILES. + * + * Results: + * 0 is returned if the search completed normally. 1 is returned + * if it aborted. + * + * Side effects: + * Whatever side effects result from application of the + * supplied procedure. + * + * NOTE: + * The procedure called is free to do anything it wishes to tiles + * which have already been visited in the area search, but it must + * not affect anything about tiles not visited other than possibly + * corner stitches to tiles already visited. + * + * ************************************************************************* + * ************************************************************************* + * **** **** + * **** WARNING **** + * **** **** + * **** This code is INCREDIBLY sensitive to modification! **** + * **** Change it only with the utmost caution, or you'll **** + * **** be verrry sorry! **** + * **** **** + * ************************************************************************* + * ************************************************************************* + * + * -------------------------------------------------------------------- + */ + +int +TiSrArea(hintTile, plane, rect, func, arg) + Tile *hintTile; /* Tile at which to begin search, if not NULL. + * If this is NULL, use the hint tile supplied + * with plane. + */ + Plane *plane; /* Plane in which tiles lie. This is used to + * provide a hint tile in case hintTile == NULL. + * The hint tile in the plane is updated to be + * the last tile visited in the area enumeration. + */ + Rect *rect;/* Area to search */ + int (*func)(); /* Function to apply at each tile */ + ClientData arg; /* Additional argument to pass to (*func)() */ +{ + Point here; + Tile *tp, *enumTR, *enumTile; + int enumRight, enumBottom; + + /* + * We will scan from top to bottom along the left hand edge + * of the search area, searching for tiles. Each tile we + * find in this search will be enumerated. + */ + + here.p_x = rect->r_xbot; + here.p_y = rect->r_ytop - 1; + enumTile = hintTile ? hintTile : plane->pl_hint; + GOTOPOINT(enumTile, &here); + plane->pl_hint = enumTile; + + while (here.p_y >= rect->r_ybot) + { + if (SigInterruptPending) return 1; + /* + * Find the tile (tp) immediately below the one to be + * enumerated (enumTile). This must be done before we enumerate + * the tile, as the filter function applied to enumerate + * it can result in its deallocation or modification in + * some other way. + */ + here.p_y = BOTTOM(enumTile) - 1; + tp = enumTile; + GOTOPOINT(tp, &here); + plane->pl_hint = tp; + + enumRight = RIGHT(enumTile); + enumBottom = BOTTOM(enumTile); + enumTR = TR(enumTile); + if ((*func)(enumTile, arg)) return 1; + + /* + * If the right boundary of the tile being enumerated is + * inside of the search area, recursively enumerate + * tiles to its right. + */ + + if (enumRight < rect->r_xtop) + if (tiSrAreaEnum(enumTR, enumBottom, rect, func, arg)) + return 1; + enumTile = tp; + } + return 0; +} + +/* + * -------------------------------------------------------------------- + * + * tiSrAreaEnum -- + * + * Perform the recursive edge search of the tile which has just been + * enumerated in an area search. The arguments passed are the RT + * corner stitch and bottom coordinate of the tile just enumerated. + * + * Results: + * 0 is returned if the search completed normally, 1 if + * it was aborted. + * + * Side effects: + * Attempts to enumerate recursively each tile found in walking + * along the right edge of the tile just enumerated. Whatever + * side effects occur result from the application of the client's + * filter function. + * + * -------------------------------------------------------------------- + */ + +int +tiSrAreaEnum(enumRT, enumBottom, rect, func, arg) + Tile *enumRT; /* TR corner stitch of tile just enumerated */ + int enumBottom; /* Bottom coordinate of tile just enumerated */ + Rect *rect; /* Area to search */ + int (*func)(); /* Function to apply at each tile */ + ClientData arg; /* Additional argument to pass to (*func)() */ +{ + Tile *tp, *tpLB, *tpTR; + int tpRight, tpNextTop, tpBottom, srchBottom; + int atBottom = (enumBottom <= rect->r_ybot); + + + /* + * Begin examination of tiles along right edge. + * A tile to the right of the one being enumerated is enumerable if: + * - its bottom lies at or above that of the tile being enumerated, or, + * - the bottom of the tile being enumerated lies at or below the + * bottom of the search rectangle. + */ + + if ((srchBottom = enumBottom) < rect->r_ybot) + srchBottom = rect->r_ybot; + + for (tp = enumRT, tpNextTop = TOP(tp); tpNextTop > srchBottom; tp = tpLB) + { + if (SigInterruptPending) return 1; + + /* + * Since the client's filter function may result in this tile + * being deallocated or otherwise modified, we must extract + * all the information we will need from the tile before we + * apply the filter function. + */ + + tpLB = LB(tp); + tpNextTop = TOP(tpLB); /* Since TOP(tpLB) comes from tp */ + + if (BOTTOM(tp) < rect->r_ytop && (atBottom || BOTTOM(tp) >= enumBottom)) + { + /* + * We extract more information from the tile, which we will use + * after applying the filter function. + */ + + tpRight = RIGHT(tp); + tpBottom = BOTTOM(tp); + tpTR = TR(tp); + if ((*func)(tp, arg)) return 1; + + /* + * If the right boundary of the tile being enumerated is + * inside of the search area, recursively enumerate + * tiles to its right. + */ + + if (tpRight < rect->r_xtop) + if (tiSrAreaEnum(tpTR, tpBottom, rect, func, arg)) + return 1; + } + } + return 0; +} diff --git a/tiles/tile.c b/tiles/tile.c new file mode 100644 index 00000000..e08cb782 --- /dev/null +++ b/tiles/tile.c @@ -0,0 +1,828 @@ +/* + * tile.c -- + * + * Basic tile manipulation + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/tiles/tile.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/geometry.h" +#include "tiles/tile.h" + +/* + * Debugging version of TiSetBody() macro in tile.h + * Includes sanity check that a tile at "infinity" + * is not being set to a type other than space. + */ +/* +void +TiSetBody(tp, b) + Tile *tp; + ClientData b; +{ + if (b != (ClientData)0 && b != (ClientData)(-1)) + if (RIGHT(tp) == INFINITY || TOP(tp) == INFINITY || + LEFT(tp) == MINFINITY || BOTTOM(tp) == MINFINITY) + TxError("Error: Tile at infinity set to non-space value %d\n", (int)b); + tp->ti_body = b; +} +*/ + +/* + * Rectangle that defines the maximum extent of any plane. + * No tile created by the user should ever extend outside of + * this area. + */ + +global Rect TiPlaneRect = { MINFINITY+2, MINFINITY+2, INFINITY-2, INFINITY-2 }; + +#ifdef HAVE_SYS_MMAN_H + +global Tile *TileStoreFreeList = NULL; +global Tile *TileStoreFreeList_end = NULL; + +/* The new Tile Allocation scheme (Magic 8.0) */ + +static void *_block_begin = NULL; +static void *_current_ptr = NULL; +static void *_block_end = NULL; + +#endif /* HAVE_SYS_MMAN_H */ + + +/* + * -------------------------------------------------------------------- + * + * TiNewPlane -- + * + * Allocate and initialize a new tile plane. + * + * Results: + * A newly allocated Plane with all corner stitches set + * appropriately. + * + * Side effects: + * Adjusts the corner stitches of the Tile supplied to + * point to the appropriate bounding tile in the newly + * created Plane. + * + * -------------------------------------------------------------------- + */ + +Plane * +TiNewPlane(tile) + Tile *tile;/* Tile to become initial tile of plane. + * May be NULL. + */ +{ + Plane *newplane; + static Tile *infinityTile = (Tile *) NULL; + + newplane = (Plane *) mallocMagic((unsigned) (sizeof (Plane))); + newplane->pl_top = TiAlloc(); + newplane->pl_right = TiAlloc(); + newplane->pl_bottom = TiAlloc(); + newplane->pl_left = TiAlloc(); + + /* + * Since the lower left coordinates of the TR and RT + * stitches of a tile are used to determine its upper right, + * we must give the boundary tiles a meaningful TR and RT. + * To make certain that these tiles don't have zero width + * or height, we use a dummy tile at (INFINITY+1,INFINITY+1). + */ + + if (infinityTile == (Tile *) NULL) + { + infinityTile = TiAlloc(); + LEFT(infinityTile) = INFINITY+1; + BOTTOM(infinityTile) = INFINITY+1; + } + + if (tile) + { + RT(tile) = newplane->pl_top; + TR(tile) = newplane->pl_right; + LB(tile) = newplane->pl_bottom; + BL(tile) = newplane->pl_left; + } + + LEFT(newplane->pl_bottom) = MINFINITY; + BOTTOM(newplane->pl_bottom) = MINFINITY; + RT(newplane->pl_bottom) = tile; + TR(newplane->pl_bottom) = newplane->pl_right; + LB(newplane->pl_bottom) = BADTILE; + BL(newplane->pl_bottom) = newplane->pl_left; + TiSetBody(newplane->pl_bottom, -1); + + LEFT(newplane->pl_top) = MINFINITY; + BOTTOM(newplane->pl_top) = INFINITY; + RT(newplane->pl_top) = infinityTile; + TR(newplane->pl_top) = newplane->pl_right; + LB(newplane->pl_top) = tile; + BL(newplane->pl_top) = newplane->pl_left; + TiSetBody(newplane->pl_top, -1); + + LEFT(newplane->pl_left) = MINFINITY; + BOTTOM(newplane->pl_left) = MINFINITY; + RT(newplane->pl_left) = newplane->pl_top; + TR(newplane->pl_left) = tile; + LB(newplane->pl_left) = newplane->pl_bottom; + BL(newplane->pl_left) = BADTILE; + TiSetBody(newplane->pl_left, -1); + + LEFT(newplane->pl_right) = INFINITY; + BOTTOM(newplane->pl_right) = MINFINITY; + RT(newplane->pl_right) = newplane->pl_top; + TR(newplane->pl_right) = infinityTile; + LB(newplane->pl_right) = newplane->pl_bottom; + BL(newplane->pl_right) = tile; + TiSetBody(newplane->pl_right, -1); + + newplane->pl_hint = tile; + return (newplane); +} + +/* + * -------------------------------------------------------------------- + * + * TiFreePlane -- + * + * Free the storage associated with a tile plane. + * Only the plane itself and its four border tiles are deallocated. + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * + * -------------------------------------------------------------------- + */ + +void +TiFreePlane(plane) + Plane *plane; /* Plane to be freed */ +{ + TiFree(plane->pl_left); + TiFree(plane->pl_right); + TiFree(plane->pl_top); + TiFree(plane->pl_bottom); + freeMagic((char *) plane); +} + +/* + * -------------------------------------------------------------------- + * + * TiToRect -- + * + * Convert a tile to a rectangle. + * + * Results: + * None. + * + * Side effects: + * Sets *rect to the bounding box for the supplied tile. + * + * -------------------------------------------------------------------- + */ + +void +TiToRect(tile, rect) + Tile *tile; /* Tile whose bounding box is to be stored in *rect */ + Rect *rect; /* Pointer to rect to be set to bounding box */ +{ + rect->r_xbot = LEFT(tile); + rect->r_xtop = RIGHT(tile); + rect->r_ybot = BOTTOM(tile); + rect->r_ytop = TOP(tile); +} + +/* + * -------------------------------------------------------------------- + * + * TiSplitX -- + * + * Given a tile and an X coordinate, split the tile into two + * along a line running vertically through the given coordinate. + * + * Results: + * Returns the new tile resulting from the splitting, which + * is the tile occupying the right-hand half of the original + * tile. + * + * Side effects: + * Modifies the corner stitches in the database to reflect + * the presence of two tiles in place of the original one. + * + * -------------------------------------------------------------------- + */ + +Tile * +TiSplitX(tile, x) + Tile *tile; /* Tile to be split */ + int x; /* X coordinate of split */ +{ + Tile *newtile; + Tile *tp; + + ASSERT(x > LEFT(tile) && x < RIGHT(tile), "TiSplitX"); + + newtile = TiAlloc(); + TiSetClient(newtile, CLIENTDEFAULT); + TiSetBody(newtile, 0); + + LEFT(newtile) = x; + BOTTOM(newtile) = BOTTOM(tile); + BL(newtile) = tile; + TR(newtile) = TR(tile); + RT(newtile) = RT(tile); + + /* + * Adjust corner stitches along the right edge + */ + + for (tp = TR(tile); BL(tp) == tile; tp = LB(tp)) + BL(tp) = newtile; + TR(tile) = newtile; + + /* + * Adjust corner stitches along the top edge + */ + + for (tp = RT(tile); LEFT(tp) >= x; tp = BL(tp)) + LB(tp) = newtile; + RT(tile) = tp; + + /* + * Adjust corner stitches along the bottom edge + */ + + for (tp = LB(tile); RIGHT(tp) <= x; tp = TR(tp)) + /* nothing */; + LB(newtile) = tp; + while (RT(tp) == tile) + { + RT(tp) = newtile; + tp = TR(tp); + } + + return (newtile); +} + +/* + * -------------------------------------------------------------------- + * + * TiSplitY -- + * + * Given a tile and a Y coordinate, split the tile into two + * along a horizontal line running through the given coordinate. + * + * Results: + * Returns the new tile resulting from the splitting, which + * is the tile occupying the top half of the original + * tile. + * + * Side effects: + * Modifies the corner stitches in the database to reflect + * the presence of two tiles in place of the original one. + * + * -------------------------------------------------------------------- + */ + +Tile * +TiSplitY(tile, y) + Tile *tile; /* Tile to be split */ + int y; /* Y coordinate of split */ +{ + Tile *newtile; + Tile *tp; + + ASSERT(y > BOTTOM(tile) && y < TOP(tile), "TiSplitY"); + + newtile = TiAlloc(); + TiSetClient(newtile, CLIENTDEFAULT); + TiSetBody(newtile, 0); + + LEFT(newtile) = LEFT(tile); + BOTTOM(newtile) = y; + LB(newtile) = tile; + RT(newtile) = RT(tile); + TR(newtile) = TR(tile); + + /* + * Adjust corner stitches along top edge + */ + + for (tp = RT(tile); LB(tp) == tile; tp = BL(tp)) + LB(tp) = newtile; + RT(tile) = newtile; + + /* + * Adjust corner stitches along right edge + */ + + for (tp = TR(tile); BOTTOM(tp) >= y; tp = LB(tp)) + BL(tp) = newtile; + TR(tile) = tp; + + /* + * Adjust corner stitches along left edge + */ + + for (tp = BL(tile); TOP(tp) <= y; tp = RT(tp)) + /* nothing */; + BL(newtile) = tp; + while (TR(tp) == tile) + { + TR(tp) = newtile; + tp = RT(tp); + } + + return (newtile); +} + +/* + * -------------------------------------------------------------------- + * + * TiSplitX_Left -- + * + * Given a tile and an X coordinate, split the tile into two + * along a line running vertically through the given coordinate. + * Intended for use when plowing to the left. + * + * Results: + * Returns the new tile resulting from the splitting, which + * is the tile occupying the left-hand half of the original + * tile. + * + * Side effects: + * Modifies the corner stitches in the database to reflect + * the presence of two tiles in place of the original one. + * + * -------------------------------------------------------------------- + */ + +Tile * +TiSplitX_Left(tile, x) + Tile *tile; /* Tile to be split */ + int x; /* X coordinate of split */ +{ + Tile *newtile; + Tile *tp; + + ASSERT(x > LEFT(tile) && x < RIGHT(tile), "TiSplitX"); + + newtile = TiAlloc(); + TiSetClient(newtile, CLIENTDEFAULT); + TiSetBody(newtile, 0); + + LEFT(newtile) = LEFT(tile); + LEFT(tile) = x; + BOTTOM(newtile) = BOTTOM(tile); + + BL(newtile) = BL(tile); + LB(newtile) = LB(tile); + TR(newtile) = tile; + BL(tile) = newtile; + + /* Adjust corner stitches along the left edge */ + for (tp = BL(newtile); TR(tp) == tile; tp = RT(tp)) + TR(tp) = newtile; + + /* Adjust corner stitches along the top edge */ + for (tp = RT(tile); LEFT(tp) >= x; tp = BL(tp)) + /* nothing */; + RT(newtile) = tp; + for ( ; LB(tp) == tile; tp = BL(tp)) + LB(tp) = newtile; + + /* Adjust corner stitches along the bottom edge */ + for (tp = LB(tile); RIGHT(tp) <= x; tp = TR(tp)) + RT(tp) = newtile; + LB(tile) = tp; + + return (newtile); +} + +/* + * -------------------------------------------------------------------- + * + * TiSplitY_Bottom -- + * + * Given a tile and a Y coordinate, split the tile into two + * along a horizontal line running through the given coordinate. + * Used when plowing down. + * + * Results: + * Returns the new tile resulting from the splitting, which + * is the tile occupying the bottom half of the original + * tile. + * + * Side effects: + * Modifies the corner stitches in the database to reflect + * the presence of two tiles in place of the original one. + * + * -------------------------------------------------------------------- + */ + +Tile * +TiSplitY_Bottom(tile, y) + Tile *tile; /* Tile to be split */ + int y; /* Y coordinate of split */ +{ + Tile *newtile; + Tile *tp; + + ASSERT(y > BOTTOM(tile) && y < TOP(tile), "TiSplitY"); + + newtile = TiAlloc(); + TiSetClient(newtile, CLIENTDEFAULT); + TiSetBody(newtile, 0); + + LEFT(newtile) = LEFT(tile); + BOTTOM(newtile) = BOTTOM(tile); + BOTTOM(tile) = y; + + RT(newtile) = tile; + LB(newtile) = LB(tile); + BL(newtile) = BL(tile); + LB(tile) = newtile; + + /* Adjust corner stitches along bottom edge */ + for (tp = LB(newtile); RT(tp) == tile; tp = TR(tp)) + RT(tp) = newtile; + + /* Adjust corner stitches along right edge */ + for (tp = TR(tile); BOTTOM(tp) >= y; tp = LB(tp)) + /* nothing */; + TR(newtile) = tp; + for ( ; BL(tp) == tile; tp = LB(tp)) + BL(tp) = newtile; + + /* Adjust corner stitches along left edge */ + for (tp = BL(tile); TOP(tp) <= y; tp = RT(tp)) + TR(tp) = newtile; + BL(tile) = tp; + + return (newtile); +} + +/* + * -------------------------------------------------------------------- + * + * TiJoinX -- + * + * Given two tiles sharing an entire common vertical edge, replace + * them with a single tile occupying the union of their areas. + * + * Results: + * None. + * + * Side effects: + * The first tile is simply relinked to reflect its new size. + * The second tile is deallocated. Corner stitches in the + * neighboring tiles are updated to reflect the new structure. + * If the hint tile pointer in the supplied plane pointed to + * the second tile, it is adjusted to point instead to the + * first. + * + * -------------------------------------------------------------------- + */ + +void +TiJoinX(tile1, tile2, plane) + Tile *tile1; /* First tile, remains allocated after call */ + Tile *tile2; /* Second tile, deallocated by call */ + Plane *plane; /* Plane in which hint tile is updated */ +{ + Tile *tp; + + /* + * Basic algorithm: + * + * Update all the corner stitches in the neighbors of tile2 + * to point to tile1. + * Update the corner stitches of tile1 along the shared edge + * to be those of tile2. + * Change the bottom or left coordinate of tile1 if appropriate. + * Deallocate tile2. + */ + + ASSERT(BOTTOM(tile1)==BOTTOM(tile2) && TOP(tile1)==TOP(tile2), "TiJoinX"); + ASSERT(LEFT(tile1)==RIGHT(tile2) || RIGHT(tile1)==LEFT(tile2), "TiJoinX"); + + /* + * Update stitches along top of tile + */ + + for (tp = RT(tile2); LB(tp) == tile2; tp = BL(tp)) + LB(tp) = tile1; + + /* + * Update stitches along bottom of tile + */ + + for (tp = LB(tile2); RT(tp) == tile2; tp = TR(tp)) + RT(tp) = tile1; + + /* + * Update stitches along either left or right, depending + * on relative position of the two tiles. + */ + + ASSERT(LEFT(tile1) != LEFT(tile2), "TiJoinX"); + if (LEFT(tile1) < LEFT(tile2)) + { + for (tp = TR(tile2); BL(tp) == tile2; tp = LB(tp)) + BL(tp) = tile1; + TR(tile1) = TR(tile2); + RT(tile1) = RT(tile2); + } + else + { + for (tp = BL(tile2); TR(tp) == tile2; tp = RT(tp)) + TR(tp) = tile1; + BL(tile1) = BL(tile2); + LB(tile1) = LB(tile2); + LEFT(tile1) = LEFT(tile2); + } + + if (plane->pl_hint == tile2) + plane->pl_hint = tile1; + TiFree(tile2); +} + +/* + * -------------------------------------------------------------------- + * + * TiJoinY -- + * + * Given two tiles sharing an entire common horizontal edge, replace + * them with a single tile occupying the union of their areas. + * + * Results: + * None. + * + * Side effects: + * The first tile is simply relinked to reflect its new size. + * The second tile is deallocated. Corner stitches in the + * neighboring tiles are updated to reflect the new structure. + * If the hint tile pointer in the supplied plane pointed to + * the second tile, it is adjusted to point instead to the + * first. + * + * -------------------------------------------------------------------- + */ + +void +TiJoinY(tile1, tile2, plane) + Tile *tile1; /* First tile, remains allocated after call */ + Tile *tile2; /* Second tile, deallocated by call */ + Plane *plane; /* Plane in which hint tile is updated */ +{ + Tile *tp; + + /* + * Basic algorithm: + * + * Update all the corner stitches in the neighbors of tile2 + * to point to tile1. + * Update the corner stitches of tile1 along the shared edge + * to be those of tile2. + * Change the bottom or left coordinate of tile1 if appropriate. + * Deallocate tile2. + */ + + ASSERT(LEFT(tile1)==LEFT(tile2) && RIGHT(tile1)==RIGHT(tile2), "TiJoinY"); + ASSERT(TOP(tile1)==BOTTOM(tile2) || BOTTOM(tile1)==TOP(tile2), "TiJoinY"); + + /* + * Update stitches along right of tile. + */ + + for (tp = TR(tile2); BL(tp) == tile2; tp = LB(tp)) + BL(tp) = tile1; + + /* + * Update stitches along left of tile. + */ + + for (tp = BL(tile2); TR(tp) == tile2; tp = RT(tp)) + TR(tp) = tile1; + + /* + * Update stitches along either top or bottom, depending + * on relative position of the two tiles. + */ + + ASSERT(BOTTOM(tile1) != BOTTOM(tile2), "TiJoinY"); + if (BOTTOM(tile1) < BOTTOM(tile2)) + { + for (tp = RT(tile2); LB(tp) == tile2; tp = BL(tp)) + LB(tp) = tile1; + RT(tile1) = RT(tile2); + TR(tile1) = TR(tile2); + } + else + { + for (tp = LB(tile2); RT(tp) == tile2; tp = TR(tp)) + RT(tp) = tile1; + LB(tile1) = LB(tile2); + BL(tile1) = BL(tile2); + BOTTOM(tile1) = BOTTOM(tile2); + } + + if (plane->pl_hint == tile2) + plane->pl_hint = tile1; + TiFree(tile2); +} + +#ifdef HAVE_SYS_MMAN_H + +/* MMAP the tile store */ +static signed char +mmapTileStore() +{ + int prot = PROT_READ | PROT_WRITE; + int flags = MAP_ANON | MAP_PRIVATE; + unsigned long map_len = TILE_STORE_BLOCK_SIZE; + + _block_begin = mmap(NULL, map_len, prot, flags, -1, 0); + if (_block_begin == MAP_FAILED) + { + TxError("TileStore: Unable to mmap ANON SEGMENT\n"); + _exit(1); + } + _block_end = (void *) ((unsigned long) _block_begin + map_len); + _current_ptr = _block_begin; + return 0; +} + +Tile * +getTileFromTileStore() +{ + Tile *_return_tile = NULL; + + if (!_block_begin && !_block_end) + { + mmapTileStore(); + } + + /* Check if we can get the tile from the + * Free list + */ + + if (TileStoreFreeList) + { + _return_tile = TileStoreFreeList; + TileStoreFreeList = (Tile *)TileStoreFreeList->ti_client; + return _return_tile; + } + + /* Get it from the mmap */ + + if (((unsigned long)_current_ptr + sizeof(Tile)) + > (unsigned long)_block_end) + { + mmapTileStore(); + } + _current_ptr = (void *)((unsigned long)_current_ptr + sizeof(Tile)); + + if ((unsigned long)_current_ptr > (unsigned long) _block_end) + { + fprintf(stderr,"TileStore: internal assertion failure..."); + _exit(1); + } + return (Tile *)((unsigned long)_current_ptr - sizeof(Tile)); +} + +static void +TileStoreFree(ptr) + Tile *ptr; +{ + if (!TileStoreFreeList_end || !TileStoreFreeList) + { + TileStoreFreeList_end = ptr; + ptr->ti_client = (unsigned long)0; + TileStoreFreeList = TileStoreFreeList_end; + } + else + { + TileStoreFreeList_end->ti_client = (unsigned long)ptr; + TileStoreFreeList_end = ptr; + TileStoreFreeList_end->ti_client = (unsigned long) 0; + } +} + +Tile * +TiAlloc() +{ + Tile *newtile; + + newtile = getTileFromTileStore(); + TiSetClient(newtile, CLIENTDEFAULT); + TiSetBody(newtile, 0); + return (newtile); +} + +void +TiFree(tp) + Tile *tp; +{ + TileStoreFree(tp); +} + +#else + +/* + * -------------------------------------------------------------------- + * + * TiAlloc --- + * + * Memory allocation for tiles + * + * Results: + * Pointer to an initialized memory location for a tile. + * + * -------------------------------------------------------------------- + */ + +Tile * +TiAlloc() +{ + Tile *newtile; + + newtile = (Tile *) mallocMagic((unsigned) (sizeof (Tile))); + TiSetClient(newtile, CLIENTDEFAULT); + TiSetBody(newtile, 0); + return (newtile); +} + +/* + * -------------------------------------------------------------------- + * + * TiFree --- + * + * Release memory allocation for tiles + * + * Results: + * None. + * + * -------------------------------------------------------------------- + */ + +void +TiFree(tp) + Tile *tp; +{ + freeMagic((char *)tp); +} + +#endif /* !HAVE_SYS_MMAN_H */ + +/* ==================================================================== */ +/* */ +/* DEBUGGING PROCEDURES */ +/* */ +/* ==================================================================== */ + +void +tiPrint(tp) + Tile *tp; +{ + printf("tp=%p LL=(%d,%d) body=0x%"DLONG_PREFIX"x\n", + tp, LEFT(tp), BOTTOM(tp), (dlong) tp->ti_body); + printf("BL=%p LB=%p RT=%p TR=%p\n", BL(tp), LB(tp), RT(tp), TR(tp)); +} + +void +tiPrintAll(tp) + Tile *tp; +{ + tiPrint(tp); + printf("UR=(%d,%d)\n", RIGHT(tp), TOP(tp)); + + /* The following is for plowing debugging */ + printf("LEAD=%d\n", (int) tp->ti_client); +} diff --git a/tiles/tile.h b/tiles/tile.h new file mode 100644 index 00000000..3be991b7 --- /dev/null +++ b/tiles/tile.h @@ -0,0 +1,323 @@ +/* + * tile.h -- + * + * Definitions of the basic tile structures + * The definitions in this file are all that is visible to + * the Ti (tile) modules. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/tiles/tile.h,v 1.3 2010/06/24 12:37:57 tim Exp $" + */ + +#ifndef _TILES_H +#define _TILES_H + +#ifndef _MAGIC_H +#include "utils/magic.h" +#endif +#ifndef _GEOMETRY_H +#include "utils/geometry.h" +#endif + +/* + * A tile is the basic unit used for representing both space and + * solid area in a plane. It has the following structure: + * + * RT + * ^ + * | + * ------------------------- + * | | ---> TR + * | | + * | | + * | (lower left) | + * BL <--- ------------------------- + * | + * v + * LB + * + * The (x, y) coordinates of the lower left corner of the tile are stored, + * along with four "corner stitches": RT, TR, BL, LB. + * + * Space tiles are distinguished at a higher level by having a distinguished + * tile body. + */ + +typedef struct tile +{ + ClientData ti_body; /* Body of tile */ + struct tile *ti_lb; /* Left bottom corner stitch */ + struct tile *ti_bl; /* Bottom left corner stitch */ + struct tile *ti_tr; /* Top right corner stitch */ + struct tile *ti_rt; /* Right top corner stitch */ + Point ti_ll; /* Lower left coordinate */ + ClientData ti_client; /* This space for hire. Warning: the default + * value for this field, to which all users + * should return it when done, is CLNTDEFAULT + * instead of NULL. + */ +} Tile; + + /* + * The following macros make it appear as though both + * the lower left and upper right coordinates of a tile + * are stored inside it. + */ + +#ifdef HAVE_SYS_MMAN_H +#include +#include + +/* This is an on-demand Free List management */ +typedef Tile *TileStore; + +/* Page size is 4KB so we mmap a segment equal to 64 pages */ +#define TILE_STORE_BLOCK_SIZE (4 * 1024 * 64) + +extern Tile *TileStoreFreeList; +extern Tile *TileStoreFreeList_end; + +#endif /* HAVE_SYS_MMAN_H */ + +#define BOTTOM(tp) ((tp)->ti_ll.p_y) +#define LEFT(tp) ((tp)->ti_ll.p_x) +#define TOP(tp) (BOTTOM(RT(tp))) +#define RIGHT(tp) (LEFT(TR(tp))) + +#define LB(tp) ((tp)->ti_lb) +#define BL(tp) ((tp)->ti_bl) +#define TR(tp) ((tp)->ti_tr) +#define RT(tp) ((tp)->ti_rt) + + +/* ----------------------- Tile planes -------------------------------- */ + +/* + * A plane of tiles consists of the four special tiles needed to + * surround all internal tiles on all sides. Logically, these + * tiles appear as below, except for the fact that all are located + * off at infinity. + * + * -------------------------------------- + * |\ /| + * | \ / | + * | \ TOP / | + * | \ / | + * | \ / | + * | -------------------------- | + * | | | | + * |LEFT | |RIGHT| + * | | | | + * | -------------------------- | + * | / \ | + * | / \ | + * | / BOTTOM \ | + * | / \ | + * |/ \| + * -------------------------------------- + */ + +typedef struct +{ + Tile *pl_left; /* Left pseudo-tile */ + Tile *pl_top; /* Top pseudo-tile */ + Tile *pl_right; /* Right pseudo-tile */ + Tile *pl_bottom; /* Bottom pseudo-tile */ + Tile *pl_hint; /* Pointer to a "hint" at which to + * begin searching. + */ +} Plane; + +/* + * The following coordinate, INFINITY, is used to represent a + * tile location outside of the tile plane. + * + * It must be possible to represent INFINITY+1 as well as + * INFINITY. + * + * Also, because locations involving INFINITY may be transformed, + * it is desirable that additions and subtractions of small integers + * from either INFINITY or MINFINITY not cause overflow. + * + * Consequently, we define INFINITY to be the largest integer + * representable in wordsize - 2 bits. + */ + +#undef INFINITY +#define INFINITY ((1 << (8*sizeof (int) - 2)) - 4) +#define MINFINITY (-INFINITY) + +/* CLIENTDEFAULT differs from MINFINITY on 64-bit systems, where it */ +/* prevents problems arising from MINFINITY being two different values */ +/* depending on whether it is cast into a 32 or a 64 bit word. */ + +#define CLIENTMAX (((pointertype)1 << (8 * sizeof(pointertype) - 2)) - 4) +#define CLIENTDEFAULT (-CLIENTMAX) + +/* ------------------------ Flags, etc -------------------------------- */ + +#define BADTILE ((Tile *) -1) /* Invalid tile pointer */ + +/* ============== Function headers and external interface ============= */ + +/* + * The following macros and procedures should be all that are + * ever needed by modules other than the tile module. + */ + +extern Plane *TiNewPlane(Tile *); +extern void TiFreePlane(Plane *); +extern void TiToRect(Tile *, Rect *); +extern Tile *TiSplitX(Tile *, int); +extern Tile *TiSplitY(Tile *, int); +extern Tile *TiSplitX_Left(Tile *, int); +extern Tile *TiSplitY_Bottom(Tile *, int); +extern void TiJoinX(Tile *, Tile *, Plane *); +extern void TiJoinY(Tile *, Tile *, Plane *); +extern int TiSrArea(); +extern Tile *TiSrPoint(Tile *, Plane *, Point *); + +#define TiBottom(tp) (BOTTOM(tp)) +#define TiLeft(tp) (LEFT(tp)) +#define TiTop(tp) (TOP(tp)) +#define TiRight(tp) (RIGHT(tp)) + +/* + * For the following to work, the caller must include database.h + * (to get the definition of TileType). + */ + +/* + * Non-Manhattan split tiles are defined as follows: + * d = SplitDirection, s = SplitSide + * + * d=1 d=0 + * +---+ +---+ + * |\XX| | /| + * | \X| | /X| s=1 + * | \| |/XX| + * +---+ +---+ + * 0x7 0x6 + * + * +---+ +---+ + * |\ | |XX/| + * |X\ | |X/ | s=0 + * |XX\| |/ | + * +---+ +---+ + * 0x5 0x4 + * + */ + +#define TiGetType(tp) ((TileType)(spointertype)((tp)->ti_body) & TT_LEFTMASK) +#define TiGetTypeExact(tp) ((TileType)(spointertype) (tp)->ti_body) +#define SplitDirection(tp) ((TileType)(spointertype)((tp)->ti_body) & TT_DIRECTION ? 1 : 0) +#define SplitSide(tp) ((TileType)(spointertype)((tp)->ti_body) & TT_SIDE ? 1 : 0) +#define IsSplit(tp) ((TileType)(spointertype)((tp)->ti_body) & TT_DIAGONAL ? TRUE : FALSE) + +#define SplitLeftType(tp) ((TileType)(spointertype)((tp)->ti_body) & TT_LEFTMASK) +#define SplitRightType(tp) (((TileType)(spointertype)((tp)->ti_body) & TT_RIGHTMASK) >> 14) +#define SplitTopType(tp) (((TileType)(spointertype)((tp)->ti_body) & TT_DIRECTION) ? \ + SplitRightType(tp) : SplitLeftType(tp)) +#define SplitBottomType(tp) (((TileType)(spointertype)((tp)->ti_body) & TT_DIRECTION) ? \ + SplitLeftType(tp) : SplitRightType(tp)) + +#define TiGetLeftType(tp) SplitLeftType(tp) +#define TiGetRightType(tp) ((IsSplit(tp)) ? SplitRightType(tp) : TiGetType(tp)) +#define TiGetTopType(tp) ((IsSplit(tp)) ? SplitTopType(tp) : TiGetType(tp)) +#define TiGetBottomType(tp) ((IsSplit(tp)) ? SplitBottomType(tp) : TiGetType(tp)) + +#define TiGetBody(tp) ((tp)->ti_body) +/* See diagnostic subroutine version in tile.c */ +#define TiSetBody(tp, b) ((tp)->ti_body = (ClientData)(pointertype) (b)) +#define TiGetClient(tp) ((tp)->ti_client) +#define TiSetClient(tp,b) ((tp)->ti_client = (ClientData)(pointertype) (b)) + +Tile *TiAlloc(void); +void TiFree(Tile *); + +#define EnclosePoint(tile,point) ((LEFT(tile) <= (point)->p_x ) && \ + ((point)->p_x < RIGHT(tile)) && \ + (BOTTOM(tile) <= (point)->p_y ) && \ + ((point)->p_y < TOP(tile) )) + +#define EnclosePoint4Sides(tile,point) ((LEFT(tile) <= (point)->p_x ) && \ + ((point)->p_x <= RIGHT(tile)) && \ + (BOTTOM(tile) <= (point)->p_y ) && \ + ((point)->p_y <= TOP(tile) )) + +/* The four macros below are for finding next tile RIGHT, UP, LEFT or DOWN + * from current tile at a given coordinate value. + * + * For example, NEXT_TILE_RIGHT points tResult to tile to right of t + * at y-coordinate y. + */ + +#define NEXT_TILE_RIGHT(tResult, t, y) \ + for ((tResult) = TR(t); BOTTOM(tResult) > (y); (tResult) = LB(tResult)) \ + /* Nothing */; + +#define NEXT_TILE_UP(tResult, t, x) \ + for ((tResult) = RT(t); LEFT(tResult) > (x); (tResult) = BL(tResult)) \ + /* Nothing */; + +#define NEXT_TILE_LEFT(tResult, t, y) \ + for ((tResult) = BL(t); TOP(tResult) <= (y); (tResult) = RT(tResult)) \ + /* Nothing */; + +#define NEXT_TILE_DOWN(tResult, t, x) \ + for ((tResult) = LB(t); RIGHT(tResult) <= (x); (tResult) = TR(tResult)) \ + /* Nothing */; + +#define TiSrPointNoHint(plane, point) (TiSrPoint((Tile *) NULL, plane, point)) + +/* + * GOTOPOINT is used whenever a macroized version of TiSrPoint is + * needed. + */ + +#define GOTOPOINT(tp, p) \ + { \ + if ((p)->p_y < BOTTOM(tp)) \ + do tp = LB(tp); while ((p)->p_y < BOTTOM(tp)); \ + else \ + while ((p)->p_y >= TOP(tp)) tp = RT(tp); \ + if ((p)->p_x < LEFT(tp)) \ + do \ + { \ + do tp = BL(tp); while ((p)->p_x < LEFT(tp)); \ + if ((p)->p_y < TOP(tp)) break; \ + do tp = RT(tp); while ((p)->p_y >= TOP(tp)); \ + } \ + while ((p)->p_x < LEFT(tp)); \ + else \ + while ((p)->p_x >= RIGHT(tp)) \ + { \ + do tp = TR(tp); while ((p)->p_x >= RIGHT(tp)); \ + if ((p)->p_y >= BOTTOM(tp)) break; \ + do tp = LB(tp); while ((p)->p_y < BOTTOM(tp)); \ + } \ + } + +/* Fill in the bounding rectangle for a tile */ +#define TITORECT(tp, rp) \ + ((rp)->r_xbot = LEFT(tp), (rp)->r_ybot = BOTTOM(tp), \ + (rp)->r_xtop = RIGHT(tp), (rp)->r_ytop = TOP(tp)) + +extern Rect TiPlaneRect; /* Rectangle large enough to force area + * search to visit every tile in the + * plane. This is the largest rectangle + * that should ever be painted in a plane. + */ + +#endif /* _TILES_H */ diff --git a/utils/Depend b/utils/Depend new file mode 100644 index 00000000..8e4f10c3 --- /dev/null +++ b/utils/Depend @@ -0,0 +1,73 @@ +args.o: args.c ../utils/magic.h ../utils/utils.h +child.o: child.c ../utils/utils.h ../utils/magic.h ../utils/malloc.h +dqueue.o: dqueue.c ../utils/magic.h ../utils/dqueue.h ../utils/malloc.h +finddisp.o: finddisp.c ../utils/magic.h ../utils/utils.h +flock.o: flock.c ../utils/magic.h ../utils/hash.h ../utils/geometry.h \ + ../tiles/tile.h ../database/database.h ../windows/windows.h \ + ../utils/malloc.h +flsbuf.o: flsbuf.c +fraction.o: fraction.c ../utils/magic.h ../utils/geometry.h +geometry.o: geometry.c ../utils/magic.h ../utils/geometry.h \ + ../utils/utils.h ../textio/textio.h ../tiles/tile.h +getrect.o: getrect.c ../utils/magic.h ../utils/geometry.h +hash.o: hash.c ../utils/magic.h ../utils/hash.h ../utils/malloc.h +heap.o: heap.c ../utils/magic.h ../utils/geometry.h ../utils/heap.h \ + ../utils/utils.h ../utils/malloc.h +list.o: list.c ../utils/magic.h ../utils/utils.h ../utils/malloc.h \ + ../utils/list.h +lookup.o: lookup.c ../utils/magic.h ../utils/utils.h +lookupany.o: lookupany.c +lookupfull.o: lookupfull.c ../utils/magic.h +macros.o: macros.c ../utils/magic.h ../utils/utils.h ../utils/hash.h \ + ../utils/malloc.h ../utils/macros.h ../windows/windows.h \ + ../utils/geometry.h +main.o: main.c ../utils/main.h ../windows/windows.h ../utils/magic.h \ + ../utils/geometry.h ../database/database.h ../tiles/tile.h \ + ../utils/hash.h ../utils/malloc.h ../utils/magsgtty.h ../utils/macros.h \ + ../textio/textio.h ../textio/txcommands.h ../utils/tech.h ../drc/drc.h \ + ../graphics/graphics.h ../dbwind/dbwind.h ../commands/commands.h \ + ../utils/signals.h ../utils/utils.h ../utils/runstats.h ../cif/cif.h \ + ../router/router.h ../lef/lef.h ../extract/extract.h ../utils/undo.h \ + ../netmenu/netmenu.h ../plow/plow.h ../utils/paths.h ../wiring/wiring.h \ + ../plot/plot.h ../sim/sim.h ../utils/list.h ../mzrouter/mzrouter.h \ + ../lisp/lisp.h ../graphics/wind3d.h +malloc.o: malloc.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/malloc.h +match.o: match.c ../utils/magic.h ../textio/textio.h +maxrect.o: maxrect.c ../utils/maxrect.h ../database/database.h \ + ../tiles/tile.h ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/malloc.h +netlist.o: netlist.c ../utils/magic.h ../utils/geometry.h ../utils/hash.h \ + ../utils/heap.h ../tiles/tile.h ../database/database.h \ + ../utils/netlist.h ../utils/signals.h ../textio/textio.h \ + ../utils/malloc.h ../utils/styles.h +niceabort.o: niceabort.c ../utils/magic.h ../textio/textio.h \ + ../utils/utils.h ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../windows/windows.h ../utils/main.h +parser.o: parser.c ../utils/magic.h ../textio/textio.h +path.o: path.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/hash.h \ + ../utils/malloc.h ../utils/utils.h +pathvisit.o: pathvisit.c ../utils/magic.h ../utils/hash.h \ + ../utils/malloc.h ../utils/pathvisit.h ../utils/utils.h +port.o: port.c ../utils/magic.h ../utils/hash.h ../utils/malloc.h +printstuff.o: printstuff.c ../utils/magic.h ../utils/geometry.h +signals.o: signals.c ../utils/main.h ../windows/windows.h \ + ../utils/magic.h ../utils/geometry.h ../database/database.h \ + ../tiles/tile.h ../utils/hash.h ../utils/magsgtty.h ../textio/textio.h \ + ../utils/signals.h ../graphics/graphics.h +stack.o: stack.c ../utils/magic.h ../utils/utils.h ../utils/stack.h \ + ../utils/malloc.h +strdup.o: strdup.c ../utils/magic.h ../utils/malloc.h +runstats.o: runstats.c ../utils/magic.h ../utils/runstats.h +set.o: set.c ../utils/magic.h ../utils/utils.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h ../utils/list.h +show.o: show.c ../utils/magic.h ../utils/geometry.h ../windows/windows.h \ + ../graphics/graphics.h ../utils/hash.h ../tiles/tile.h \ + ../database/database.h ../dbwind/dbwind.h +tech.o: tech.c ../utils/magic.h ../utils/geometry.h ../utils/utils.h \ + ../utils/tech.h ../textio/textio.h ../windows/windows.h \ + ../utils/malloc.h +touchtypes.o: touchtypes.c ../utils/magic.h ../utils/geometry.h \ + ../utils/geofast.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h +undo.o: undo.c ../utils/magic.h ../utils/utils.h ../utils/malloc.h \ + ../utils/undo.h diff --git a/utils/LIBdbio.c b/utils/LIBdbio.c new file mode 100644 index 00000000..b3e4a0e8 --- /dev/null +++ b/utils/LIBdbio.c @@ -0,0 +1,58 @@ +/* + * LIBdbio.c -- + * + * File that only goes in libmagicutils.a to define procedures + * referenced from dbio that might not be defined elsewhere. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] = "$Header: /usr/cvsroot/magic-8.0/utils/LIBdbio.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" + + +/* + * ---------------------------------------------------------------------------- + * + * flock_open + * + * Like standard flock_open, except that it is always called read-only, + * so it simply calls a normal fopen(). + * + * Results: + * Returns a pointer to the opened file + * + * Side effects: + * None + * + * ---------------------------------------------------------------------------- + */ + +FILE * +flock_open(filename, mode, is_locked) + char *filename; + char *mode; + bool *is_locked; +{ + FILE *f; + + if (is_locked) *is_locked = FALSE; + f = fopen(filename, mode); + return(f); +} diff --git a/utils/LIBmain.c b/utils/LIBmain.c new file mode 100644 index 00000000..f9da78c2 --- /dev/null +++ b/utils/LIBmain.c @@ -0,0 +1,76 @@ +/* + * LIBmain.c -- + * + * File that only goes in libmagicutils.a to define procedures + * referenced from main that might not be defined elsewhere. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] = "$Header: /usr/cvsroot/magic-8.0/utils/LIBmain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + + +/* + * ---------------------------------------------------------------------------- + * + * MainExit -- + * + * Exit. + * + * Results: + * None. + * + * Side effects: + * Exits. + * + * ---------------------------------------------------------------------------- + */ + +void +MainExit(code) + int code; +{ + exit (code); +} + +char AbortMessage[500] = ""; + + +/* + * ---------------------------------------------------------------------------- + * + * niceabort -- + * + * Simple version of niceabort, which dumps core and terminates the program. + * Magic uses the more complex version found in misc/niceabort.c. + * + * Results: + * None. + * + * Side effects: + * Dumps core and exits. + * ---------------------------------------------------------------------------- + */ + +void +niceabort() +{ + fprintf(stderr, "A major internal inconsistency has been detected:\n"); + fprintf(stderr, " %s\n\n", AbortMessage); + abort(); /* core dump! */ +} diff --git a/utils/LIBtextio.c b/utils/LIBtextio.c new file mode 100644 index 00000000..f23cbfaf --- /dev/null +++ b/utils/LIBtextio.c @@ -0,0 +1,141 @@ +/* + * LIBtextio.c -- + * + * File that only goes in libmagicutils.a to define procedures + * referenced from textio that might not be defined elsewhere. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] = "$Header: /usr/cvsroot/magic-8.0/utils/LIBtextio.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +/* + * ---------------------------------------------------------------------------- + * + * TxGetLine -- + * + * Like fgets() from standard input. + * + * Results: + * Returns a pointer to 'buf' if successful, or NULL on EOF. + * + * Side effects: + * Fills in 'buf' with the next line from the standard input. + * + * ---------------------------------------------------------------------------- + */ + +char * +TxGetLine(buf, size) + char *buf; + int size; +{ + return (fgets(buf, size, stdin)); +} + + +/* + * ---------------------------------------------------------------------------- + * + * TxFlushErr, TxFlush -- + * + * Like fflush(stderr), fflush(stdout). + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +TxFlushErr() +{ + (void) fflush(stderr); +} + +void +TxFlush() +{ + (void) fflush(stderr); + (void) fflush(stdout); +} + + +/* + * ---------------------------------------------------------------------------- + * + * TxError -- + * + * Like fprintf(stderr, ...) + * + * Results: + * None. + * + * Side effects: + * Writes to the standard error. + * + * ---------------------------------------------------------------------------- + */ + +void +TxError(char *fmt, ...) +{ + va_list ap; + + (void) fflush(stdout); + (void) fflush(stderr); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + (void) fflush(stderr); +} + + +/* + * ---------------------------------------------------------------------------- + * + * TxPrintf -- + * + * Like printf(...) + * + * Results: + * None. + * + * Side effects: + * Writes to the standard output. + * + * ---------------------------------------------------------------------------- + */ + +void +TxPrintf(char *fmt, ...) +{ + va_list ap; + + (void) fflush(stderr); + (void) fflush(stdout); + va_start(ap, fmt); + vfprintf(stdout, fmt, ap); + va_end(ap); + (void) fflush(stdout); +} + + diff --git a/utils/Makefile b/utils/Makefile new file mode 100644 index 00000000..642267dc --- /dev/null +++ b/utils/Makefile @@ -0,0 +1,21 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/utils/Makefile,v 1.2 2008/12/04 16:21:44 tim Exp $ +# + +MODULE = utils +MAGICDIR = .. +LIB_SRCS = LIBdbio.c LIBmain.c LIBtextio.c +SRCS = args.c child.c dqueue.c finddisp.c flock.c flsbuf.c fraction.c \ + geometry.c getrect.c hash.c heap.c list.c lookup.c lookupany.c \ + lookupfull.c macros.c main.c malloc.c match.c maxrect.c netlist.c \ + niceabort.c parser.c path.c pathvisit.c port.c printstuff.c \ + signals.c stack.c strdup.c runstats.c set.c show.c tech.c \ + touchtypes.c undo.c + +include ${MAGICDIR}/defs.mak + +# The following required to pass XLIB to the macros.c routines. +DFLAGS += ${GR_DFLAGS} +CFLAGS += ${GR_CFLAGS} + +include ${MAGICDIR}/rules.mak diff --git a/utils/args.c b/utils/args.c new file mode 100644 index 00000000..efea39cd --- /dev/null +++ b/utils/args.c @@ -0,0 +1,75 @@ +/* + * args.c -- + * + * Procedures to assist in command-line argument processing. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/args.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/utils.h" + +/* + * ---------------------------------------------------------------------------- + * + * ArgStr -- + * + * Process a single argument that is supposed to have a string value. + * A string argument can appear in two ways: + * + * -avalue (a single element of argv) + * -a value (two elements of argv) + * + * Both are recognized. + * + * Results: + * Returns a pointer to the value, or NULL if there wasn't one. + * + * Side effects: + * Complains if there was no value. + * Leaves *pargc and *pargv updated if the string was in the + * next element of argv. + * + * ---------------------------------------------------------------------------- + */ + +char * +ArgStr(pargc, pargv, argType) + int *pargc; + char ***pargv; + char *argType; /* For error messages: what the following string is + * supposed to be interpreted as. + */ +{ + char **argv = *pargv; + char *result; + + if (argv[0][2]) + return (&argv[0][2]); + + if ((*pargc)-- > 0) + { + result = *++argv; + *pargv = argv; + return (result); + } + + TxError("-%c requires a following %s\n", argv[0][1], argType); + return (NULL); +} diff --git a/utils/child.c b/utils/child.c new file mode 100644 index 00000000..0dccf3cf --- /dev/null +++ b/utils/child.c @@ -0,0 +1,264 @@ +/************************************************************************* + * + * (c) 1997 California Institute of Technology + * Department of Computer Science + * Pasadena, CA 91125. + * All Rights Reserved + * + * $Id: child.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + *************************************************************************/ +#include +#include +#ifndef SYSV +#include +#endif /* SYSV */ +#include + +#include "utils/utils.h" +#include "utils/malloc.h" + + +/*------------------------------------------------------------------------ + * Internal list management + *------------------------------------------------------------------------*/ + +struct Wait_List { + int pid; + int status; + int pending; + struct Wait_List *next; +}; + +static struct Wait_List *wl = NULL; + +static +void +make_finished (pid, status) + int pid; + int *status; +{ + struct Wait_List *l; + + l = wl; + while (l) { + if (l->pid == pid) { + l->pending = 0; + l->status = *status; + return; + } + l = l->next; + } + return; +} + +static +void +add_pending_to_list (pid) + int pid; +{ + struct Wait_List *l; + + l = (struct Wait_List *) mallocMagic((unsigned)(sizeof(struct Wait_List))); + l->next = wl; + l->pid = pid; + l->status = -1; + l->pending = 1; + wl = l; + return; +} + +static +int +find_pid (pid,status) + int pid; + int *status; +{ + struct Wait_List *l; + l = wl; + while (l) { + if (l->pid == pid) { + *status = l->status; + return l->pending; + } + l = l->next; + } + return -1; +} + +static +int +get_next (status) + int *status; +{ + struct Wait_List *l, *prev; + int pid; + + prev = NULL; + l = wl; + while (l) { + if (!l->pending) { + pid = l->pid; + *status = l->status; + if (prev) + prev->next = l->next; + else + wl = l->next; + freeMagic(l); + return pid; + } + prev = l; + l = l->next; + } + return -1; +} + +static +void +delete_from_list (pid) + int pid; +{ + struct Wait_List *l, *prev; + + prev = NULL; + l = wl; + while (l) { + if (l->pid == pid) { + if (prev) + prev->next = l->next; + else + wl = l->next; + freeMagic(l); + return; + } + prev = l; + l = l->next; + } +} + + + +/*------------------------------------------------------------------------ + * + * Wait -- + * + * Wait for a process to terminate. Returns the pid that you waited + * for, along with the exit status in *status. + * + * Returns -1 on an attempt to wait for a pid which wasn't ever + * forked. + * + * If you want to wait for a particular pid, use WaitPid instead + * of Wait. + * + * Results: + * The pid that finished, along with the status. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +int +Wait (status) + int *status; +{ + int pid; + int p_status = 0; + + pid = get_next(&p_status); + if (pid != -1) { + if (status) + *status = p_status; + return pid; + } + if (wl) { + do { + pid = wait(&p_status); + } while (pid < 0 && errno == EINTR); + delete_from_list (pid); + if (status) + *status = p_status; + return pid; + } + else + /* nothing to wait for */ + return -1; +} + + +/*------------------------------------------------------------------------ + * + * WaitPid -- + * + * Wait for a particular process to terminate. + * + * Returns -1 on an attempt to wait for a pid which wasn't ever + * forked. + * + * If you want to wait for a particular pid, use WaitPid instead + * of Wait. + * + * Results: + * The pid that finished, along with the status. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +int +WaitPid (pid,status) + int pid; + int *status; +{ + int stat; + int n_pid, n_status; + + stat = find_pid (pid,&n_status); + if (stat == -1) + return -1; + if (stat == 0) { + delete_from_list (pid); + if (status) + *status = n_status; + return 1; + } + do { + do { + n_pid = wait(&n_status); + } while (n_pid < 0 && errno == EINTR); + make_finished (n_pid, &n_status); + } while (n_pid != pid && n_pid != -1); + if (n_pid == -1) return -1; + delete_from_list (pid); + if (status) + *status = n_status; + return 1; +} + + +/*------------------------------------------------------------------------ + * + * ForkChildAdd -- + * + * Fork, along with updating the wait list structure. + * + * Results: + * The pid that finished, along with the status. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +void +ForkChildAdd (pid) + int pid; +{ + add_pending_to_list (pid); +} + diff --git a/utils/displays.proto b/utils/displays.proto new file mode 100644 index 00000000..5c9f701c --- /dev/null +++ b/utils/displays.proto @@ -0,0 +1,2 @@ +/dev/ttyp2 graphicsPort ourMon ourType 1234 +/dev/ttyx2 graphicsPort2 ourMon2 ourType2 12345 diff --git a/utils/dqueue.c b/utils/dqueue.c new file mode 100644 index 00000000..ae81cb0b --- /dev/null +++ b/utils/dqueue.c @@ -0,0 +1,260 @@ +/* + * dqueue.c -- + * + * Routines for double ended queues. See 'dqueue.h'. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/dqueue.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/dqueue.h" +#include "utils/malloc.h" + +/* + * ---------------------------------------------------------------------------- + * + * DQInit -- + * + * Initialize a new queue to have a certain capacity. + * + * Results: + * None. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +DQInit(q, capacity) + DQueue *q; + int capacity; +{ + if (capacity < 1) capacity = 1; + q->dq_data = (ClientData *) mallocMagic((unsigned)((capacity+1) * sizeof (ClientData))); + q->dq_size = 0; + q->dq_maxSize = capacity; + q->dq_front = 0; /* next slot in front is loc 0 */ + q->dq_rear = 1; /* next slot in rear is loc 1 */ +} + + +/* + * ---------------------------------------------------------------------------- + * + * DQFree -- + * + * Free up a queue. + * + * Results: + * None. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +DQFree(q) + DQueue *q; +{ + freeMagic((char *) q->dq_data); +} + +/* + * ---------------------------------------------------------------------------- + * + * DQPushFront & DQPushRear -- + * + * Push a new element onto one end of the DQueue. + * + * Results: + * None. + * + * Side Effects: + * Puts an element in the queue. + * + * ---------------------------------------------------------------------------- + */ + +void +DQPushFront(q, elem) + DQueue *q; + ClientData elem; +{ + if (q->dq_size == q->dq_maxSize) DQChangeSize(q, 2 * q->dq_maxSize); + q->dq_data[q->dq_front] = elem; + q->dq_front--; + if (q->dq_front < 0) q->dq_front = q->dq_maxSize; + q->dq_size++; +} + +void +DQPushRear(q, elem) + DQueue *q; + ClientData elem; +{ + if (q->dq_size == q->dq_maxSize) DQChangeSize(q, 2 * q->dq_maxSize); + q->dq_data[q->dq_rear] = elem; + q->dq_rear++; + if (q->dq_rear > q->dq_maxSize) q->dq_rear = 0; + q->dq_size++; +} + +/* + * ---------------------------------------------------------------------------- + * + * DQPopFront & DQPopRear -- + * + * Pop an element from one end of the queue. + * + * Results: + * The element, or NULL if there is none. + * + * Side Effects: + * Removes the element from the queue. + * + * ---------------------------------------------------------------------------- + */ + +ClientData +DQPopFront(q) + DQueue *q; +{ + if (q->dq_size == 0) return (ClientData) NULL; + q->dq_size--; + q->dq_front++; + if (q->dq_front > q->dq_maxSize) q->dq_front = 0; + return q->dq_data[q->dq_front]; +} + +ClientData +DQPopRear(q) + DQueue *q; +{ + if (q->dq_size == 0) return (ClientData) NULL; + q->dq_size--; + q->dq_rear--; + if (q->dq_rear < 0) q->dq_rear = q->dq_maxSize; + return q->dq_data[q->dq_rear]; +} + + +/* + * ---------------------------------------------------------------------------- + * + * DQChangeSize -- + * + * Change the size of a DQueue -- either increase or decrease. + * + * Results: + * None + * + * Side Effects: + * The DQueue changes size. + * + * ---------------------------------------------------------------------------- + */ + +void +DQChangeSize(q, newSize) + DQueue *q; + int newSize; +{ + DQueue newq; + + if (newSize < q->dq_size) newSize = q->dq_size; + DQInit(&newq, newSize); + DQCopy(&newq, q); + freeMagic((char *) q->dq_data); + q->dq_data = newq.dq_data; + q->dq_maxSize = newq.dq_maxSize; + q->dq_front = newq.dq_front; + q->dq_rear = newq.dq_rear; +} + + +/* + * ---------------------------------------------------------------------------- + * + * DQCopy -- + * + * Copy one DQueue into another. + * + * Results: + * None. + * + * Side Effects: + * Elements (ClientData pointers) are copied. + * + * ---------------------------------------------------------------------------- + */ + +void +DQCopy(dst, src) + DQueue *dst; /* The destination queue */ + DQueue *src; /* The source queue */ +{ + int i; + dst->dq_size = 0; + i = src->dq_front; + while (dst->dq_size != src->dq_size) { + i = i + 1; + if (i > src->dq_maxSize) i = 0; + DQPushRear(dst, src->dq_data[i]); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * Main -- + * + * Test out this module. + * + * Results: + * None. + * + * Side Effects: + * Stuff on the screen. + * + * ---------------------------------------------------------------------------- + */ + +/**** +void +main() +{ + int i; + DQueue q; + DQInit(&q, 0); + for (i = 0; i < 10; i++) DQPushFront(&q, (ClientData) i); + while (!DQIsEmpty(&q)) printf("got %d\n", (int) DQPopRear(&q)); + DQFree(&q); + printf("-------\n"); + DQInit(&q, 0); + for (i = 0; i < 10; i++) DQPushFront(&q, (ClientData) i); + for (i = 0; i < 10000; i++) DQPushRear(&q, DQPopFront(&q)); + for (i = 0; i < 10000; i++) DQPushFront(&q, DQPopRear(&q)); + while (!DQIsEmpty(&q)) printf("got %d\n", (int) DQPopFront(&q)); +} +****/ diff --git a/utils/dqueue.h b/utils/dqueue.h new file mode 100644 index 00000000..a877b7b7 --- /dev/null +++ b/utils/dqueue.h @@ -0,0 +1,55 @@ +/* + * dqueue.h -- + * + * Utility module for double ended queues (dqueus). + * DQueues are stored in a malloced array which grows when it overflows. + * The head of the queue grows towards lower addresses, and the tail grows + * up. The array is treated like a cirular ring of size dq_maxSize. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/utils/dqueue.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + * + */ + +#ifndef _DQUEUE_H +#define _DQUEUE_H + +#include "utils/magic.h" + +/* The dqueue structure, to be manipulated only by the + * procedures declared in this file. + */ +typedef struct { + int dq_size; /* number of elements in this dqueue */ + int dq_maxSize; /* max capacity of this dqueue */ + int dq_front; /* next empty location at head of dqueue */ + int dq_rear; /* next empty location at tail of dqueue */ + ClientData *dq_data; /* points to an array (filled in by DQInit) */ +} DQueue; + + +/* Housekeeping for DQueues */ +extern void DQInit(); /* Sets up data in an already allocated DQueue */ +extern void DQFree(); +extern void DQChangeSize(); +extern void DQCopy(); +#define DQIsEmpty(q) ((q)->dq_size == 0) + +/* Adding and deleting */ +extern void DQPushFront(); +extern void DQPushRear(); +extern ClientData DQPopFront(); +extern ClientData DQPopRear(); + +#endif /* _DQUEUE_H */ diff --git a/utils/finddisp.c b/utils/finddisp.c new file mode 100644 index 00000000..33255492 --- /dev/null +++ b/utils/finddisp.c @@ -0,0 +1,123 @@ +/* + * finddisplay.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains a single routine that will find the correct + * graphics display to use from the current terminal and return + * parameters for the display, such as its type and the location + * of the tablet port. It is used as part of the Caesar design + * system. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/finddisp.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/utils.h" + +/* Import from library routines: */ + +extern char *ttyname(); + + +/* + * ---------------------------------------------------------------------------- + * FindDisplay -- + * + * This procedure locates information about the color display + * to use from a given terminal (determined by tty or the name + * of the standard input file) by looking in the file passed. + * + * Results: + * None. + * + * Side effects: + * The parameters pDisplayPort, pTabletPort, pDisType, and + * pMonType all point to strings that are modified. *pDisplayPort + * is filled with the name of the port that connects to the graphics + * display. *pTabletPort is filled in with the name of the port to be + * used to receive characters from the tablet. *pDisType is filled + * in with the name of the type of display ("OGL", etc.), and + * *pMonType is filled in with the name of the monitor type attached + * to the display (used to select color maps). + * + * If the file is not found or if there is not a suitable line then + * nothing is modified. + * + * File format: + * Each line in the displays file contains up to five strings + * which are, in order, the name of a text terminal, the name + * of the corresponding graphics display port, the monitor type + * attached to that display, the name of the display type, and + * the name of the tablet port to use for that display. The + * tablet port can be omitted, in which case the display port + * is used. + * ---------------------------------------------------------------------------- + */ + +void +FindDisplay(tty, file, path, pDisplayPort, pTabletPort, pDisType, pMonType) + char *tty; /* Terminal for which display info is desired. + * If NULL, used device on stdin. + */ + char *file; /* Name of file in which to find info. */ + char *path; /* Path to use for lookup. */ + char **pDisplayPort; /* Will be filled in with the name of the + * port for the graphics display. + */ + char **pTabletPort; /* Will be filled in with the name of the + * tablet. */ + char **pDisType; /* Will be filled in with the display type. */ + char **pMonType; /* Will be filled in with the monitor type. */ + +{ + int i; + char line[100], name1[100]; + static char name2[100], mon[100], dType[100], tabletPort[100]; + FILE *f; + + if (tty == NULL) tty = ttyname(fileno(stdin)); + if (tty == NULL) return; + f = PaOpen(file, "r", (char *) NULL, path, (char *) NULL, (char **) NULL); + if (f == NULL) return; + while (1) + { + if (fgets(line, 99, f) == NULL) + { + (void) fclose(f); + return; + } + i = sscanf(line, "%99s %99s %99s %99s %99s", name1, name2, + mon, dType, tabletPort); + if (i < 4) + { + (void) fclose(f); + return; + } + if (strcmp(name1, tty) == 0) + { + (void) fclose(f); + *pDisplayPort = name2; + *pMonType = mon; + *pDisType = dType; + if (i >= 5) *pTabletPort = tabletPort; + else *pTabletPort = name2; + return; + } + } +} diff --git a/utils/flock.c b/utils/flock.c new file mode 100644 index 00000000..5437d4c4 --- /dev/null +++ b/utils/flock.c @@ -0,0 +1,170 @@ +/* + *------------------------------------------------------------------------- + * flock.c -- + * + * File opening with file locks (used by utils/path.c and database/DBio.c) + * + * Original implementation by Michael Godfrey, Stanford University. + * Implementation using "lockf" by Stefan Jones, MultiGiG, Inc., + * September 2005 (magic 7.3.102_lockf, finally corrected and implemented + * as magic 7.3.119) + *------------------------------------------------------------------------- + */ + +#ifdef FILE_LOCKS + +#include +#include + +#include "utils/magic.h" +#include "utils/hash.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "windows/windows.h" +#include "utils/malloc.h" + +/* + *------------------------------------------------------------------------- + * Below are the service routines for file locking. + * + * The original file locking mechanism (Michael Godfrey) used common files. + * However, this has the drawback of requiring extraneous directories, and + * orphaned lock files will remain after a program crash. + * + * The lockf solution (Stefan Jones) has the drawback that in order to + * hold a lock, the file descriptor must be left open. This leaves the + * possibility that we may exceed the maximum number of file descriptors + * per process. Because this solution is the simplest, it is implemented + * here. + * + * For future reference, the best file locking system (?) would use + * signaling via fcntl(F_NOTIFY). The locking mechanism goes like this: + * + * 1. process X requests an attributes notification on each directory that + * it reads a file from. + * + * 2. process X reads file A for editing. + * + * 3. process Y requests an attributes notification on each directory that + * it reads a file from. + * + * 4. process Y reads file A, thus changing its access time attribute. + * process Y sets the cell as read/write. + * + * 5. process X receives a signal. It checks the cell that is being + * accessed. If the cell has been modified, it sets a lock on + * file A. Opening file A to set the lock modifies its access time. + * If the cell has not been modified, it sets the cell to read-only. + * + * 6. process Y receives a signal. It checks the cell that is being + * accessed. If the cell has not yet been modified, it sets the + * cell to read-only. If the cell has been modified (less likely, + * but possible if process X was doing something time-consuming and + * uninterruptable and didn't process the signal for a while), then + * process Y attempts to set a lock. If the lock fails, then a + * warning is issued. + * + * It is possible for either X or Y to win the race if both processes + * modified the file right after opening. However, this rare condition + * is unlikely to be a serious problem, and prevents a process from + * having to hold open many file descriptors. + * + *------------------------------------------------------------------------- + */ + +#include +#include +#include + +/* + *------------------------------------------------------------------------- + * flock_open -- + * + * Open a file with "lockf" file locking method. + * + * Results -- + * Pointer to FILE that was opened, or NULL if an error occurred. + * + * Side effects -- + * System I/O + *------------------------------------------------------------------------- + */ + +FILE *flock_open(filename, mode, is_locked) + char *filename; + char *mode; + bool *is_locked; +{ + FILE *f = NULL, *tmp; + struct flock fl; + + if (is_locked) *is_locked = FALSE; + + /* If is_locked is NULL, then a lock is not requested, so just do */ + /* a normal fopen() and return. */ + + if (is_locked == NULL) return fopen(filename, mode); + + /* Diagnostic */ + /* TxPrintf("Opening file <%s>\n", filename); */ + + tmp = fopen(filename, "r+"); + if (tmp == NULL) + { + if (is_locked) *is_locked = TRUE; + f = fopen(filename, "r"); + goto done; + } + + fl.l_len = 0; + fl.l_start = 0; + fl.l_whence = SEEK_SET; + fl.l_type = F_WRLCK; + fl.l_pid = getpid(); + + if (fcntl(fileno(tmp), F_GETLK, &fl)) + { + perror(filename); + f = fopen(filename, mode); + goto done; + } + fclose(tmp); + + if (fl.l_type == F_UNLCK) + { + fl.l_len = 0; + fl.l_start = 0; + fl.l_whence = SEEK_SET; + fl.l_type = F_WRLCK; + fl.l_pid = getpid(); + + f = fopen(filename, "r+"); + if (fcntl(fileno(f), F_SETLK, &fl)) + { + perror(filename); + } + else + { + /* Diagnostic */ + /* TxPrintf("Obtained lock on file <%s> (fd=%d)\n", filename, fileno(f)); */ + } + } + else + { + /* Don't know why PID is not set by F_GETLK as advertised? */ + if (fl.l_pid == 0) + TxPrintf("File <%s> is already locked by another process." + " Opening read-only.\n", filename); + else + TxPrintf("File <%s> is already locked by pid %d. Opening read-only.\n", + filename, (int)fl.l_pid); + if (is_locked) *is_locked = TRUE; + f = fopen(filename, "r"); + } + +done: + return f; +} + +#endif /* FILE_LOCKS */ diff --git a/utils/flsbuf.c b/utils/flsbuf.c new file mode 100644 index 00000000..33b46c36 --- /dev/null +++ b/utils/flsbuf.c @@ -0,0 +1,202 @@ +/* NOTE: THIS CODE ONLY WORKS FOR THE VAX IMPLEMENTATION OF 4.2 BSD */ + +/* flsbuf.c -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file is a modified version of the standard system + * routine, the big difference being that it can deal gracefully + * with interrupts that cause I/O to be incomplete. The version + * from which this file is taken is: + * @(#)flsbuf.c 4.5 (Berkeley) 12/16/82 + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/flsbuf.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + + +/* NOTE: do not move the #ifdef vax up since the loader doesn't like files + * with no symbols. + */ + +#if (defined(vax) && defined(BSD4_2)) + +#include +#include +#include + +/* + * To prevent infinite loops if every attempt to write is + * interrupted, we only retry an interrupted write a fixed number + * of times, NWRITEATTEMPTS + */ + +#define NWRITEATTEMPTS 10 + +/* NOTE: we use the stdio version of malloc here! */ +char *malloc(); + +int +_flsbuf(c, iop) + unsigned c; + FILE *iop; +{ + char *base; + n, rn; + ntries; + char c1; + int size; + struct stat stbuf; + + if (iop->_flag & _IORW) { + iop->_flag |= _IOWRT; + iop->_flag &= ~_IOEOF; + } + + if ((iop->_flag&_IOWRT)==0) + return(EOF); +tryagain: + if (iop->_flag&_IOLBF) { + base = iop->_base; + *iop->_ptr++ = c; + if (iop->_ptr >= base+iop->_bufsiz || c == '\n') { + rn = iop->_ptr - base; + iop->_ptr = base; + ntries = NWRITEATTEMPTS; + for (n=0; (rn > 0) && (n >= 0) && (ntries-- > 0); + rn -= n, base += n) + n = write(fileno(iop), base, rn); + } else + n = 0; + iop->_cnt = 0; + } else if (iop->_flag&_IONBF) { + c1 = c; + ntries = NWRITEATTEMPTS; + while ((n = write(fileno(iop), &c1, 1)) == 0 && ntries-- > 0) + ; + iop->_cnt = 0; + } else { + if ((base=iop->_base)==NULL) { + if (fstat(fileno(iop), &stbuf) < 0 || + stbuf.st_blksize <= NULL) + size = BUFSIZ; + else + size = stbuf.st_blksize; + if ((iop->_base=base=malloc(size)) == NULL) { + iop->_flag |= _IONBF; + goto tryagain; + } + iop->_flag |= _IOMYBUF; + iop->_bufsiz = size; + if (iop==stdout && isatty(fileno(stdout))) { + iop->_flag |= _IOLBF; + iop->_ptr = base; + goto tryagain; + } + rn = n = 0; + } else if ((rn = n = iop->_ptr - base) > 0) { + iop->_ptr = base; + ntries = NWRITEATTEMPTS; + for (n=0; (rn > 0) && (n >= 0) && (ntries-- > 0); + rn -= n, base += n) + n = write(fileno(iop), base, rn); + base = iop->_ptr; + } + iop->_cnt = iop->_bufsiz-1; + *base++ = c; + iop->_ptr = base; + } + if (n < 0) { + iop->_flag |= _IOERR; + return(EOF); + } + return(c); +} + +int +fflush(iop) + struct _iobuf *iop; +{ + char *base; + n, rn; + ntries; + + if ((iop->_flag&(_IONBF|_IOWRT))==_IOWRT + && (base=iop->_base)!=NULL && (rn=iop->_ptr-base)>0) { + iop->_ptr = base; + iop->_cnt = (iop->_flag&(_IOLBF|_IONBF)) ? 0 : iop->_bufsiz; + ntries = NWRITEATTEMPTS; + for (n = 0; (n >= 0) && (rn > 0) && (ntries-- > 0); + base += n, rn -= n) + n = write(fileno(iop), base, rn); + if (n < 0) { + iop->_flag |= _IOERR; + return(EOF); + } + } + return(0); +} + +int +fclose(iop) + struct _iobuf *iop; +{ + int r; + + r = EOF; + if (iop->_flag&(_IOREAD|_IOWRT|_IORW) && (iop->_flag&_IOSTRG)==0) { + r = fflush(iop); + if (close(fileno(iop)) < 0) + r = EOF; + if (iop->_flag&_IOMYBUF) + free(iop->_base); + } + iop->_cnt = 0; + iop->_base = (char *)NULL; + iop->_ptr = (char *)NULL; + iop->_bufsiz = 0; + iop->_flag = 0; + iop->_file = 0; + return(r); +} + +/* + * Flush buffers on exit. Note: this procedure should only be present + * in 4.2 Unix. In 4.3 it will be ifdef'ed out. + */ + +#ifdef BSD4_2 +void +_cleanup() +{ + struct _iobuf *iop; + extern struct _iobuf *_lastbuf; + + for (iop = _iob; iop < _lastbuf; iop++) + fclose(iop); +} +#endif /* BSD4_2 */ + +#else /* vax */ + +/* Dummy proc just so the file will have a proc in it to make things easier + * on the linker. + */ + +void +dummyFlsbuf() +{ +} + +#endif /* vax */ diff --git a/utils/fraction.c b/utils/fraction.c new file mode 100644 index 00000000..50f014a6 --- /dev/null +++ b/utils/fraction.c @@ -0,0 +1,97 @@ +/* + * fraction.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains procedures for handling fractions + * Written by R. Timothy Edwards + * Johns Hopkins University Applied Physics Laboratory + * and MultiGiG Ltd. + * January, 2002 + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/fraction.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" + +/* + * ---------------------------------------------------------------------------- + * + * FindGCF -- + * + * Your basic greatest-common-factor routine. Something I invented + * one day as a teenager but is generally attributed to Euclid, or + * something like that. + * + * Results: + * The greatest (positive) common factor of the two integer arguments + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +FindGCF(a, b) + int a, b; +{ + int a_mod_b, bp; + + bp = abs(b); + if ((a_mod_b = (abs(a)) % bp) == 0) return (bp); + else return (FindGCF(bp, a_mod_b)); +} + +/* + * ---------------------------------------------------------------------------- + * + * ReduceFraction -- + * + * Fraction reducer + * + * + * Results: + * None + * + * Side effects: + * The fraction (*n / *d) as represented by integer pointer arguments + * n and d is reduced by the greatest common factor (GCF) of both. + * + * ---------------------------------------------------------------------------- + */ + +void +ReduceFraction(n, d) + int *n, *d; +{ + int c; + + c = FindGCF(*n, *d); + + if (c != 0) + { + *n /= c; + *d /= c; + } + return; +} + diff --git a/utils/geofast.h b/utils/geofast.h new file mode 100644 index 00000000..78aaa9e1 --- /dev/null +++ b/utils/geofast.h @@ -0,0 +1,189 @@ +/* + * geofast.h -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains macros for fast geometrical operations: + * clipping and transforms. For transforms, it works when they + * all have unit scale factors, so we can avoid multiplication. + * This wins a factor of 5 on machines like Suns. In addition, + * of course, each is a macro rather than a procedure call; + * the net effect is about a 5x speedup on a VAX and a 7-8x + * speedup on a Sun. + */ + +/* rcsid "$Header: /usr/cvsroot/magic-8.0/utils/geofast.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" */ + +/* ---------------------------- Clipping ------------------------------ */ + +/* + * GEOCLIP(r, area) Rect *r, area; + * clips the rectangle 'r' against the area 'area'. + */ + +#define GEOCLIP(r, area) \ + if (1) { \ + if ((r)->r_xbot < (area)->r_xbot) (r)->r_xbot = (area)->r_xbot; \ + if ((r)->r_ybot < (area)->r_ybot) (r)->r_ybot = (area)->r_ybot; \ + if ((r)->r_xtop > (area)->r_xtop) (r)->r_xtop = (area)->r_xtop; \ + if ((r)->r_ytop > (area)->r_ytop) (r)->r_ytop = (area)->r_ytop; \ + } else + +/* --------------------- Transforming rectangles ---------------------- */ + +/* + * The GEOTRANSRECT(t, r1, r2) macro has the same effect as the + * following code. It assumes that t_a, t_b, t_d, t_e are all + * chosen from -1, 0, 1, so it can't handle scaling. + * + * int x1, y1, x2, y2; + * x1 = r1->r_xbot*t->t_a + r1->r_ybot*t->t_b + t->t_c; + * y1 = r1->r_xbot*t->t_d + r1->r_ybot*t->t_e + t->t_f; + * x2 = r1->r_xtop*t->t_a + r1->r_ytop*t->t_b + t->t_c; + * y2 = r1->r_xtop*t->t_d + r1->r_ytop*t->t_e + t->t_f; + * + * if (x1 < x2) r2->r_xbot = x1, r2->r_xtop = x2; + * else r2->r_xbot = x2, r2->r_xtop = x1; + * + * if (y1 < y2) r2->r_ybot = y1, r2->r_ytop = y2; + * else r2->r_ybot = y2, r2->r_ytop = y1; + * + * We make use of the fact that if t_a != 0 for one of our transforms, + * then t_e != 0 also, and t_b = t_d = 0. + */ + +#define transRectX(r1, r2, RBOT, RTOP, ta, tc) \ + if (ta > 0) \ + r2->r_xbot = r1->RBOT + tc, r2->r_xtop = r1->RTOP + tc; \ + else \ + r2->r_xtop = tc - r1->RBOT, r2->r_xbot = tc - r1->RTOP; + +#define transRectY(r1, r2, RBOT, RTOP, ta, tc) \ + if (ta > 0) \ + r2->r_ybot = r1->RBOT + tc, r2->r_ytop = r1->RTOP + tc; \ + else \ + r2->r_ytop = tc - r1->RBOT, r2->r_ybot = tc - r1->RTOP; + +#define GEOTRANSRECT(at, ar1, ar2) \ + if (1) { \ + Transform *xt = (at); \ + Rect *xr1 = (ar1), *xr2 = (ar2); \ + if (xt->t_a) \ + { \ + transRectX(xr1, xr2, r_xbot, r_xtop, xt->t_a, xt->t_c); \ + transRectY(xr1, xr2, r_ybot, r_ytop, xt->t_e, xt->t_f); \ + } \ + else \ + { \ + transRectX(xr1, xr2, r_ybot, r_ytop, xt->t_b, xt->t_c); \ + transRectY(xr1, xr2, r_xbot, r_xtop, xt->t_d, xt->t_f); \ + } \ + } else + +/* --------------------- Transforming transforms ---------------------- */ + +/* + * The GEOTRANSTRANS(first, second, net) macro has the same effect + * as the following code. It assumes that the t_a, t_b, t_d, and t_f + * fields of 'second' are chosen from -1, 0, 1, so it can't handle scaling. + * + * net->t_a = first->t_a*second->t_a + first->t_d*second->t_b; + * net->t_b = first->t_b*second->t_a + first->t_e*second->t_b; + * net->t_c = first->t_c*second->t_a + first->t_f*second->t_b + second->t_c; + * net->t_d = first->t_a*second->t_d + first->t_d*second->t_e; + * net->t_e = first->t_b*second->t_d + first->t_e*second->t_e; + * net->t_f = first->t_c*second->t_d + first->t_f*second->t_e + second->t_f; + */ + +#define transTransAC(t1, net, ta, tc, da, db, dc) \ + ((ta > 0) \ + ? (net->t_a = t1->da, net->t_b = t1->db, net->t_c = t1->dc + tc) \ + : (net->t_a = -t1->da, net->t_b = -t1->db, net->t_c = tc - t1->dc)) + +#define transTransDF(t1, net, ta, tc, da, db, dc) \ + ((ta > 0) \ + ? (net->t_d = t1->da, net->t_e = t1->db, net->t_f = t1->dc + tc) \ + : (net->t_d = -t1->da, net->t_e = -t1->db, net->t_f = tc - t1->dc)) + +#define GEOTRANSTRANS(xt1, xt2, xnet) \ + if (1) { \ + Transform *_t1 = (xt1), *_t2 = (xt2), *_net = (xnet); \ + if (_t2->t_a) \ + transTransAC(_t1, _net, _t2->t_a, _t2->t_c, t_a, t_b, t_c); \ + else \ + transTransAC(_t1, _net, _t2->t_b, _t2->t_c, t_d, t_e, t_f); \ + if (_t2->t_d) \ + transTransDF(_t1, _net, _t2->t_d, _t2->t_f, t_a, t_b, t_c); \ + else \ + transTransDF(_t1, _net, _t2->t_e, _t2->t_f, t_d, t_e, t_f); \ + } else + +/* ----------------------- Inverting transforms ----------------------- */ + +/* + * The GEOINVERTTRANS(t, inv) macro has the same effect as the following + * code. The code assumes that t_a, t_b, t_c, and t_d are one of + * -1, 1, or 0, so it can't invert scaled transforms (but neither can + * the normal GeoInvertTrans, anyway). + * + * Transform t3; + * + * t3.t_a = t->t_a; + * t3.t_b = t->t_d; + * t3.t_d = t->t_b; + * t3.t_e = t->t_e; + * t3.t_c = t3.t_f = 0; + * GeoTransTranslate(-t->t_c, -t->t_f, &t3, inv); + * + * where GeoTranslateTrans(x, y, t, net) is + * + * net->t_a = t->t_a; + * net->t_b = t->t_b; + * net->t_d = t->t_d; + * net->t_e = t->t_e; + * net->t_c = x*t->t_a + y*t->t_b + t->t_c; + * net->t_f = x*t->t_d + y*t->t_e + t->t_f; + */ + +/* + * GEOINVERTTRANS(t, tinv) inverts Transform t into tinv + * without multiplication. + * + * tMul(c, a) implements (a*c) without multiplication, + * assuming that each of a, c are chosen from 0, -1, 1. + */ +#define tMul(c, a) \ + ((a) ? ((a) > 0 ? (c) : -(c)) : 0) + +#define GEOINVERTTRANS(t, inv) \ + if (1) { \ + Transform *xt = (t), *xinv = (inv); \ + xinv->t_a = xt->t_a; \ + xinv->t_b = xt->t_d; \ + xinv->t_d = xt->t_b; \ + xinv->t_e = xt->t_e; \ + xinv->t_c = - tMul(xt->t_c, xinv->t_a) - tMul(xt->t_f, xinv->t_b); \ + xinv->t_f = - tMul(xt->t_c, xinv->t_d) - tMul(xt->t_f, xinv->t_e); \ + } else + +/* + * GEOTRANSTRANSLATE(x, y, t, tresult) transforms an (x, y) translation + * by the transform t, resulting in the transform tresult. + */ +#define GEOTRANSTRANSLATE(x, y, t, tresult) \ + { \ + Transform *xt = (t); \ + *(tresult) = (*xt); \ + (tresult)->t_c += tMul(x, xt->t_a) + tMul(y, xt->t_b); \ + (tresult)->t_f += tMul(x, xt->t_d) + tMul(y, xt->t_e); \ + } diff --git a/utils/geometry.c b/utils/geometry.c new file mode 100644 index 00000000..4f6761c0 --- /dev/null +++ b/utils/geometry.c @@ -0,0 +1,1086 @@ +/* geometry.c -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains a bunch of utility routines for manipulating + * boxes, points, and transforms. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/geometry.c,v 1.5 2008/12/11 14:11:46 tim Exp $"; +#endif /* not lint */ + +#include +#include /* For atan2() function */ + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/utils.h" +#include "textio/textio.h" + +#include "tiles/tile.h" /* test only! */ + +/* + *------------------------------------------------------------------- + * Declarations of exported transforms: + *------------------------------------------------------------------- + */ + +global Transform GeoIdentityTransform = { 1, 0, 0, 0, 1, 0 }; +global Transform GeoUpsideDownTransform = { 1, 0, 0, 0, -1, 0 }; +global Transform GeoSidewaysTransform = { -1, 0, 0, 0, 1, 0 }; +global Transform Geo90Transform = { 0, 1, 0, -1, 0, 0 }; +global Transform Geo180Transform = { -1, 0, 0, 0, -1, 0 }; +global Transform Geo270Transform = { 0, -1, 0, 1, 0, 0 }; + +/* + * Additional Transforms (Reflections at 45 and 135 degrees) + */ + +global Transform GeoRef45Transform = { 0, 1, 0, 1, 0, 0 }; +global Transform GeoRef135Transform = { 0, -1, 0, -1, 0, 0 }; + +/* + *------------------------------------------------------------------- + * Declaration of the table of opposite directions: + *------------------------------------------------------------------- + */ +global int GeoOppositePos[] = +{ + GEO_CENTER, /* GEO_CENTER */ + GEO_SOUTH, /* GEO_NORTH */ + GEO_SOUTHWEST, /* GEO_NORTHEAST */ + GEO_WEST, /* GEO_EAST */ + GEO_NORTHWEST, /* GEO_SOUTHEAST */ + GEO_NORTH, /* GEO_SOUTH */ + GEO_NORTHEAST, /* GEO_SOUTHWEST */ + GEO_EAST, /* GEO_WEST */ + GEO_SOUTHEAST, /* GEO_NORTHWEST */ +}; + +/* + *------------------------------------------------------------------- + * Declarations of exported variables: + *------------------------------------------------------------------- + */ + +global Rect GeoNullRect = { 0, 0, 0, 0 }; +global Point GeoOrigin = { 0, 0 }; + + +/*------------------------------------------------------------------- + * GeoTransPoint -- + * Transforms a point from one coordinate system to another. + * + * Results: None. + * + * Side Effects: + * P2 is set to contain the coordinates that result from transforming + * p1 by t. + *------------------------------------------------------------------- + */ + +void +GeoTransPoint(t, p1, p2) + Transform *t; /* A description of the mapping from the + * coordinate system of p1 to that of p2. + */ + Point *p1, *p2; /* Pointers to two points; p1 is the old + * point, and p2 will contain the transformed + * point. + */ + +{ + p2->p_x = p1->p_x*t->t_a + p1->p_y*t->t_b + t->t_c; + p2->p_y = p1->p_x*t->t_d + p1->p_y*t->t_e + t->t_f; +} + +/* + *------------------------------------------------------------------- + * + * GeoTransPointDelta -- + * + * Transforms a point from one coordinate system to another. This + * differs from GeoTransPoint in that translation is ignored. It + * applies flips and rotations, and so is appropriate to calculate + * how an offset value (delta distance) transforms through the + * hierarchy. + * + * Results: + * None. + * + * Side Effects: + * P2 is set to contain the coordinates that result from transforming + * p1 by t. + *------------------------------------------------------------------- + */ +void +GeoTransPointDelta(t, p1, p2) + Transform *t; /* A description of the mapping from the + * coordinate system of p1 to that of p2. + */ + Point *p1, *p2; /* Pointers to two points; p1 is the old + * point, and p2 will contain the transformed + * point. + */ + +{ + p2->p_x = p1->p_x * t->t_a + p1->p_y * t->t_b; + p2->p_y = p1->p_x * t->t_d + p1->p_y * t->t_e; +} + +/* + *------------------------------------------------------------------- + * Determine how an angle changes through transformation via a + * tranformation matrix. Expects the transformations to be in + * multiples of 90 degrees, plus possible flipping. Expects an + * angle between 0 and 360 and returns an angle between 0 and + * 360. + *------------------------------------------------------------------- + */ + +int +GeoTransAngle(t, a) + Transform *t; /* Transformation matrix */ + int a; /* Angle to transform */ +{ + bool flip = FALSE; + int asave = a; + + /* Rotate according to the standard transforms */ + + if (t->t_a == 0 && t->t_e == 0) + { + if (t->t_b > 0) + a += 90; + else + a += 270; + if (t->t_b == t->t_d) + flip = TRUE; + } + else + { + if (t->t_a < 0) + a += 180; + if (t->t_a != t->t_e) + flip = TRUE; + } + if (a > 360) a -= 360; + if (flip) + { + if (asave > 90 && asave < 270) + a = 360 - a; + else + a = -a; + } + if (a < 0) a += 360; + return a; +} + + +/*------------------------------------------------------------------- + * GeoTransRect -- + * Transforms a rectangle from one coordinate system to another. + * + * Results: None. + * + * Side Effects: + * R2 is set to contain the coordinates that result from transforming + * r1 by t. + *------------------------------------------------------------------- + */ + +void +GeoTransRect(t, r1, r2) + Transform *t; /* A description of the mapping from the + * coordinate system of r1 to that of r2. + */ + Rect *r1, *r2; /* Pointers to two rectangles, r1 is the old + * rectangle, r2 will contain the transformed + * rectangle. + */ + +{ + int x1, y1, x2, y2; + x1 = r1->r_xbot*t->t_a + r1->r_ybot*t->t_b + t->t_c; + y1 = r1->r_xbot*t->t_d + r1->r_ybot*t->t_e + t->t_f; + x2 = r1->r_xtop*t->t_a + r1->r_ytop*t->t_b + t->t_c; + y2 = r1->r_xtop*t->t_d + r1->r_ytop*t->t_e + t->t_f; + + /* Because of rotations, xbot and xtop may have to be switched, and + * the same for ybot and ytop. + */ + + if (x1 < x2) + { + r2->r_xbot = x1; + r2->r_xtop = x2; + } + else + { + r2->r_xbot = x2; + r2->r_xtop = x1; + } + if (y1 < y2) + { + r2->r_ybot = y1; + r2->r_ytop = y2; + } + else + { + r2->r_ybot = y2; + r2->r_ytop = y1; + } +} + +/*------------------------------------------------------------------- + * GeoTranslateTrans -- + * Translate a transform by the indicated (x, y) amount. + * + * Results: None. + * + * Side Effects: + * Trans2 is set to the result of transforming trans1 by + * a translation of (x, y). + *------------------------------------------------------------------- + */ + +void +GeoTranslateTrans(trans1, x, y, trans2) + Transform *trans1; /* Transform to be translated */ + int x, y; /* Amount by which to translated */ + Transform *trans2; /* Result transform */ +{ + trans2->t_a = trans1->t_a; + trans2->t_b = trans1->t_b; + trans2->t_d = trans1->t_d; + trans2->t_e = trans1->t_e; + + trans2->t_c = trans1->t_c + x; + trans2->t_f = trans1->t_f + y; +} + +/*------------------------------------------------------------------- + * GeoTransTranslate -- + * Transform a translation by the indicated (x, y) amount. + * + * This is the dual of GeoTranslateTrans, in that if + * Tinv is the inverse of T, + * + * GeoTransTranslate(T, x, y) * GeoTranslateTrans(Tinv, -x, -y) + * is the identity transform. + * + * Results: None. + * + * Side Effects: + * Trans2 is set to the result of transforming a translation + * of (x, y) by trans1. + *------------------------------------------------------------------- + */ + +void +GeoTransTranslate(x, y, trans1, trans2) + int x, y; /* Amount of translation */ + Transform *trans1; /* Transform to be applied to translation */ + Transform *trans2; /* Result transform */ +{ + trans2->t_a = trans1->t_a; + trans2->t_b = trans1->t_b; + trans2->t_d = trans1->t_d; + trans2->t_e = trans1->t_e; + + trans2->t_c = x*trans1->t_a + y*trans1->t_b + trans1->t_c; + trans2->t_f = x*trans1->t_d + y*trans1->t_e + trans1->t_f; +} + + +/*------------------------------------------------------------------- + * GeoTransTrans -- + * This routine transforms a transform. + * + * Results: None. + * + * Side Effects: + * The transform referred to by net is set to produce a geometrical + * transformation equivalent in effect to the application of transform + * first, followed by the application of transform second. + *------------------------------------------------------------------- + */ + +void +GeoTransTrans(first, second, net) + Transform *first; /* Pointers to three transforms */ + Transform *second; + Transform *net; +{ + net->t_a = first->t_a*second->t_a + first->t_d*second->t_b; + net->t_b = first->t_b*second->t_a + first->t_e*second->t_b; + net->t_c = first->t_c*second->t_a + first->t_f*second->t_b + second->t_c; + net->t_d = first->t_a*second->t_d + first->t_d*second->t_e; + net->t_e = first->t_b*second->t_d + first->t_e*second->t_e; + net->t_f = first->t_c*second->t_d + first->t_f*second->t_e + second->t_f; +} + + +/*------------------------------------------------------------------- + * GeoNameToPos -- + * Map the name of a position into an integer position parameter. + * Position names may be unique abbreviations for direction names. + * + * Results: + * Returns a position parameter (0 - 8, corresponding to GEO_CENTER + * through GEO_NORTHWEST), -1 if the position name was ambiguous, + * and -2 if it was unrecognized. + * + * Side Effects: None. + *------------------------------------------------------------------- + */ + +int +GeoNameToPos(name, manhattan, verbose) + char *name; + bool manhattan; /* If TRUE, only Manhattan directions (up, down, + * left, right, and their synonyms) are allowed. + */ + bool verbose; /* If TRUE, we print an error message and list + * valid directions. + */ +{ + static struct pos + { + char *pos_name; + int pos_value; + bool pos_manhattan; + } + positions[] = + { + "bl", GEO_SOUTHWEST, FALSE, + "bottom", GEO_SOUTH, TRUE, + "br", GEO_SOUTHEAST, FALSE, + "center", GEO_CENTER, FALSE, + "d", GEO_SOUTH, TRUE, + "dl", GEO_SOUTHWEST, FALSE, + "down", GEO_SOUTH, TRUE, + "dr", GEO_SOUTHEAST, FALSE, + "e", GEO_EAST, TRUE, + "east", GEO_EAST, TRUE, + "left", GEO_WEST, TRUE, + "n", GEO_NORTH, TRUE, + "ne", GEO_NORTHEAST, FALSE, + "north", GEO_NORTH, TRUE, + "northeast", GEO_NORTHEAST, FALSE, + "northwest", GEO_NORTHWEST, FALSE, + "nw", GEO_NORTHWEST, FALSE, + "right", GEO_EAST, TRUE, + "s", GEO_SOUTH, TRUE, + "se", GEO_SOUTHEAST, FALSE, + "south", GEO_SOUTH, TRUE, + "southeast", GEO_SOUTHEAST, FALSE, + "southwest", GEO_SOUTHWEST, FALSE, + "sw", GEO_SOUTHWEST, FALSE, + "tl", GEO_NORTHWEST, FALSE, + "top", GEO_NORTH, TRUE, + "tr", GEO_NORTHEAST, FALSE, + "u", GEO_NORTH, TRUE, + "ul", GEO_NORTHWEST, FALSE, + "up", GEO_NORTH, TRUE, + "ur", GEO_NORTHEAST, FALSE, + "w", GEO_WEST, TRUE, + "west", GEO_WEST, TRUE, + 0 + }; + struct pos *pp; + char *fmt; + int pos; + + pos = LookupStruct(name, (LookupTable *) positions, sizeof positions[0]); + + if ((pos >= 0) && (!manhattan || positions[pos].pos_manhattan)) + return positions[pos].pos_value; + if (!verbose) + { + if (pos < 0) return pos; + else return -2; + } + if (pos < 0) + { + switch (pos) + { + case -1: + TxError("\"%s\" is ambiguous.\n", name); + break; + case -2: + TxError("\"%s\" is not a valid direction or position.\n", + name); + break; + } + } + else + { + TxError("\"%s\" is not a Manhattan direction or position.\n", name); + pos = -2; + } + TxError("Legal directions/positions are:\n\t"); + for (fmt = "%s", pp = positions; pp->pos_name; pp++) + { + if (manhattan && !pp->pos_manhattan) + continue; + TxError(fmt, pp->pos_name); + fmt = ",%s"; + } + TxError("\n"); + return (pos); +} + + +/* + * ---------------------------------------------------------------------------- + * + * GeoPosToName -- + * + * Given a geometric name, return its position name. + * + * Results: + * Pointer to a static string holding the position name. + * NOTE: you'd better not try to alter the returned string! + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ +char * +GeoPosToName(pos) + int pos; +{ + switch(pos) + { + case GEO_CENTER: return("CENTER"); + case GEO_NORTH: return("NORTH"); + case GEO_NORTHEAST: return("NORTHEAST"); + case GEO_EAST: return("EAST"); + case GEO_SOUTHEAST: return("SOUTHEAST"); + case GEO_SOUTH: return("SOUTH"); + case GEO_SOUTHWEST: return("SOUTHWEST"); + case GEO_WEST: return("WEST"); + case GEO_NORTHWEST: return("NORTHWEST"); + default: return("*ILLEGAL*"); + } +} + +/*------------------------------------------------------------------- + * GeoTransPos -- + * This routine computes the transform of a relative position. + * + * Results: + * The return value is a position equal to the position parameter + * transformed by t. + * + * Side Effects: None. + *------------------------------------------------------------------- + */ + +int +GeoTransPos(t, pos) + Transform *t; /* Transform to be applied. */ + int pos; /* Position to which it is to be applied. */ + +{ + if ((pos <= 0) || (pos > 8)) return pos; + + /* Handle rotation first, using modulo arithmetic. */ + + pos -= 1; + if (t->t_a <= 0) + { + if (t->t_a < 0) pos += 4; + else if (t->t_b < 0) pos += 6; + else pos += 2; + } + while (pos >= 8) pos -= 8; + pos += 1; + + /* Handle mirroring across the x-axis on a case-by-case basis. */ + + if ((t->t_a != t->t_e) || ((t->t_a == 0) && (t->t_b == t->t_d))) + { + switch (pos) + { + case GEO_NORTH: pos = GEO_SOUTH; break; + case GEO_NORTHEAST: pos = GEO_SOUTHEAST; break; + case GEO_EAST: break; + case GEO_SOUTHEAST: pos = GEO_NORTHEAST; break; + case GEO_SOUTH: pos = GEO_NORTH; break; + case GEO_SOUTHWEST: pos = GEO_NORTHWEST; break; + case GEO_WEST: break; + case GEO_NORTHWEST: pos = GEO_SOUTHWEST; break; + } + } + return pos; +} + + +/*------------------------------------------------------------------- + * GeoInvertTrans -- + * This routine computes the inverse of a transform. + * + * Results: None. + * + * Side Effects: + * The transform pointed to by inverse is overwritten with + * the inverse transform of t. Note: this method of inversion + * only works for rotations that are multiples of 90 degrees with + * unit scale factor. Beware any changes to this! + *------------------------------------------------------------------- + */ + +void +GeoInvertTrans(t, inverse) + Transform *t; /* Pointer to a transform */ + Transform *inverse; /* Place to store the inverse */ + +{ + Transform t2, t3; + t2.t_a = t2.t_e = 1; + t2.t_b = t2.t_d = 0; + t2.t_c = -t->t_c; + t2.t_f = -t->t_f; + t3.t_a = t->t_a; + t3.t_b = t->t_d; + t3.t_d = t->t_b; + t3.t_e = t->t_e; + t3.t_c = t3.t_f = 0; + GeoTransTrans(&t2, &t3, inverse); +} + + +/*------------------------------------------------------------------- + * GeoInclude -- + * This routine includes one rectangle into another by expanding + * the second. + * + * Results: + * TRUE is returned if the destination had to be enlarged. + * + * Side Effects: + * The destination is enlarged (if necessary) so that it completely + * contains the area of both the original src and dst rectangles. + *------------------------------------------------------------------- + */ + +bool +GeoInclude(src, dst) + Rect *src, *dst; +{ + int value; + + if (GEO_RECTNULL(src)) return FALSE; + else if (GEO_RECTNULL(dst)) + { + *dst = *src; + return TRUE; + } + + value = FALSE; + if (dst->r_xbot > src->r_xbot) + { + dst->r_xbot = src->r_xbot; + value = TRUE; + } + if (dst->r_ybot > src->r_ybot) + { + dst->r_ybot = src->r_ybot; + value = TRUE; + } + if (dst->r_xtop < src->r_xtop) + { + dst->r_xtop = src->r_xtop; + value = TRUE; + } + if (dst->r_ytop < src->r_ytop) + { + dst->r_ytop = src->r_ytop; + value = TRUE; + } + return value; +} + + +/*------------------------------------------------------------------- + * GeoIncludeAll -- + * This routine includes one rectangle into another by expanding + * the second. This routine differs from GeoInclude in that zero- + * size source rectangles are processed. The source or destination + * rectangle is considered to be NULL only if its lower-left corner + * is above or to the right of its upper right corner. In this + * case, the other rectangle is the result. + * + * Results: + * TRUE is returned if the destination is enlarged; otherwise FALSE. + * + * Side Effects: + * The destination is enlarged (if necessary) so that it completely + * contains the area of both the original src and dst rectangles. + *------------------------------------------------------------------- + */ + +bool +GeoIncludeAll(src, dst) + Rect *src, *dst; +{ + bool value; + + if ((dst->r_xbot > dst->r_xtop) || (dst->r_ybot > dst->r_ytop)) + { + *dst = *src; + return TRUE; + } + + if ((src->r_xbot > src->r_xtop) || (src->r_ybot > src->r_ytop)) + return FALSE; + + value = FALSE; + if (dst->r_xbot > src->r_xbot) + { + dst->r_xbot = src->r_xbot; + value = TRUE; + } + if (dst->r_ybot > src->r_ybot) + { + dst->r_ybot = src->r_ybot; + value = TRUE; + } + if (dst->r_xtop < src->r_xtop) + { + dst->r_xtop = src->r_xtop; + value = TRUE; + } + if (dst->r_ytop < src->r_ytop) + { + dst->r_ytop = src->r_ytop; + value = TRUE; + } + return value; +} + + +/*------------------------------------------------------------------- + * GeoIncludePoint -- + * This routine includes a point into a rectangle by expanding + * the rectangle if necessary. If the destination rectangle has + * its lower left corner above or to the right of its upper right + * corner, then use the source point to initialize the destination + * rectangle. + * + * Results: + * None. + * + * Side Effects: + * The destination is enlarged (if necessary) so that it completely + * contains the area of both the original src and dst. + *------------------------------------------------------------------- + */ + +void +GeoIncludePoint(src, dst) + Point *src; + Rect *dst; +{ + if ((dst->r_xbot > dst->r_xtop) || (dst->r_ybot > dst->r_ytop)) + { + dst->r_ll = *src; + dst->r_ur = *src; + } + else + { + if (dst->r_xbot > src->p_x) + dst->r_xbot = src->p_x; + if (dst->r_ybot > src->p_y) + dst->r_ybot = src->p_y; + if (dst->r_xtop < src->p_x) + dst->r_xtop = src->p_x; + if (dst->r_ytop < src->p_y) + dst->r_ytop = src->p_y; + } +} + + +/*------------------------------------------------------------------- + * GeoClip -- + * clips one rectangle against another. + * + * Results: None. + * + * Side Effects: + * Rectangle r is clipped so that it includes only the + * intersection area between r and area. The rectangle + * may end up being turned inside out (xbot>xtop) if + * there was absolutely no intersection between the two + * boxes. + *------------------------------------------------------------------- + */ + +void +GeoClip(r, area) + Rect *r; /* Rectangle to be clipped. */ + Rect *area; /* Area against which to be clipped. */ + +{ + if (r->r_xbot < area->r_xbot) r->r_xbot = area->r_xbot; + if (r->r_ybot < area->r_ybot) r->r_ybot = area->r_ybot; + if (r->r_xtop > area->r_xtop) r->r_xtop = area->r_xtop; + if (r->r_ytop > area->r_ytop) r->r_ytop = area->r_ytop; +} + +/*------------------------------------------------------------------- + * GeoClipPoint -- + * Clips one point against a rectangle, moving the point into + * the rectangle if needed. + * + * Results: None. + * + * Side Effects: + * Point p is clipped so that it lies within or on the rectangle. + *------------------------------------------------------------------- + */ + +void +GeoClipPoint(p, area) + Point *p; /* Point to be clipped. */ + Rect *area; /* Area against which to be clipped. */ +{ + if (p->p_x < area->r_xbot) p->p_x = area->r_xbot; + if (p->p_y < area->r_ybot) p->p_y = area->r_ybot; + if (p->p_x > area->r_xtop) p->p_x = area->r_xtop; + if (p->p_y > area->r_ytop) p->p_y = area->r_ytop; +} + +/* + * ---------------------------------------------------------------------------- + * GeoDisjoint -- + * + * Clip a rectanglular area against a clipping box, applying the + * supplied procedure to each rectangular region in "area" which + * falls outside "clipbox". This works in tile space, where a + * rectangle is assumed to contain its lower x- and y-coordinates + * but not its upper coordinates. It does NOT work in pixel space + * (think about this carefully before using it for pixels!). + * + * The procedure should be of the form: + * bool func(box, cdarg) + * Rect * box; + * ClientData cdarg; + * + * Results: + * Return TRUE unless the supplied function returns FALSE. + * + * Side effects: + * The side effects of the invoked procedure. + * ---------------------------------------------------------------------------- + */ + +bool +GeoDisjoint(area, clipBox, func, cdarg) + Rect * area; + Rect * clipBox; + bool (*func) (); + ClientData cdarg; +{ + Rect ok, rArea; + bool result; + +#define NULLBOX(R) ((R.r_xbot>R.r_xtop)||(R.r_ybot>R.r_ytop)) + + ASSERT((area!=(Rect *) NULL), "GeoDisjoint"); + if((clipBox==(Rect *) NULL)||(!GEO_OVERLAP(area, clipBox))) + { + /* Since there is no overlap, all of "area" may be processed. */ + + result= (*func)(area, cdarg); + return(result); + } + + /* Do the disjoint operation in four steps, one for each side + * of clipBox. In each step, divide the area being clipped + * into one piece that is DEFINITELY outside clipBox, and one + * piece left to check some more. + */ + + /* Top edge of clipBox: */ + + rArea = *area; + result = TRUE; + if (clipBox->r_ytop < rArea.r_ytop) + { + ok = rArea; + rArea.r_ytop = ok.r_ybot = clipBox->r_ytop; + if (!(*func)(&ok, cdarg)) result = FALSE; + } + + /* Bottom edge of clipBox: */ + + if (clipBox->r_ybot > rArea.r_ybot) + { + ok = rArea; + rArea.r_ybot = ok.r_ytop = clipBox->r_ybot; + if (!(*func)(&ok, cdarg)) result = FALSE; + } + + /* Right edge of clipBox: */ + + if (clipBox->r_xtop < rArea.r_xtop) + { + ok = rArea; + rArea.r_xtop = ok.r_xbot = clipBox->r_xtop; + if (!(*func)(&ok, cdarg)) result = FALSE; + } + + /* Left edge of clipBox: */ + + if (clipBox->r_xbot > rArea.r_xbot) + { + ok = rArea; + rArea.r_xbot = ok.r_xtop = clipBox->r_xbot; + if (!(*func)(&ok, cdarg)) result = FALSE; + } + + /* Just throw away what's left of the area being clipped, since + * it overlaps the clipBox. + */ + + return result; +} /*GeoDisjoint*/ + + +bool +GeoDummyFunc(box, cdarg) + Rect * box; + ClientData cdarg; +{ + return TRUE; +} + + +/*------------------------------------------------------------------- + * GeoCanonicalRect -- + * Turns a rectangle into a canonical form in which the + * lower left is really below and to the left of the upper right. + * + * Results: None. + * + * Side Effects: + * Rectangle rnew is set to the canonical form of rectangle r. + *------------------------------------------------------------------- + */ + +void +GeoCanonicalRect(r, rnew) + Rect *r; + Rect *rnew; +{ + if (r->r_xbot > r->r_xtop) + { + rnew->r_xbot = r->r_xtop; + rnew->r_xtop = r->r_xbot; + } + else + { + rnew->r_xbot = r->r_xbot; + rnew->r_xtop = r->r_xtop; + } + + if (r->r_ybot > r->r_ytop) + { + rnew->r_ybot = r->r_ytop; + rnew->r_ytop = r->r_ybot; + } + else + { + rnew->r_ybot = r->r_ybot; + rnew->r_ytop = r->r_ytop; + } +} + +/*------------------------------------------------------------------- + * GeoScale -- + * + * Returns the scale factor associated with a transform. + * + * Results: + * Scale factor. + * + * Side Effects: + * None. + *------------------------------------------------------------------- + */ + +int +GeoScale(t) + Transform *t; +{ + int scale; + + scale = t->t_a; + if (scale == 0) + scale = t->t_b; + + if (scale < 0) + scale = (-scale); + + return (scale); +} + +/*------------------------------------------------------------------- + * GeoScaleTrans -- + * Scale a transform by the indicated magnification. + * + * Results: None. + * + * Side Effects: + * Trans2 is set to the result of scaling trans1 by (integer) + * magnification m. Non-integer magnifications are not + * handled. + *------------------------------------------------------------------- + */ + +void +GeoScaleTrans(trans1, m, trans2) + Transform *trans1; /* Transform to be scaled */ + int m; /* Amount by which to scale */ + Transform *trans2; /* Result transform */ +{ + trans2->t_a = trans1->t_a * m; + trans2->t_b = trans1->t_b * m; + trans2->t_c = trans1->t_c * m; + trans2->t_d = trans1->t_d * m; + trans2->t_e = trans1->t_e * m; + trans2->t_f = trans1->t_f * m; +} + + +/*------------------------------------------------------------------- + * GeoRectPointSide -- + * + * Returns the side of the rect on which a point lies. + * + * Results: + * A direction, or GEO_CENTER if the point is off the boundary. + * + * Side Effects: + * None. + *------------------------------------------------------------------- + */ + +int +GeoRectPointSide(r, p) + Rect * r; + Point * p; +{ + if(r->r_xbot == p->p_x) return GEO_WEST; + else + if(r->r_xtop == p->p_x) return GEO_EAST; + else + if(r->r_ybot == p->p_y) return GEO_SOUTH; + else + if(r->r_ytop == p->p_y) return GEO_NORTH; + else + return(GEO_CENTER); +} + +/*------------------------------------------------------------------- + * GeoRectRectSide -- + * + * Returns the side of the first rect on which the second one + * lies. + * + * Results: + * A direction, or GEO_CENTER if the rects don't share some + * coordinate. Note, this won't detect the case where the + * rectangles don't touch but do share some coordinate. + * + * Side Effects: + * None. + *------------------------------------------------------------------- + */ + +int +GeoRectRectSide(r0, r1) + Rect * r0; + Rect * r1; +{ + if(r0->r_xbot == r1->r_xtop) return GEO_WEST; + else + if(r0->r_xtop == r1->r_xbot) return GEO_EAST; + else + if(r0->r_ybot == r1->r_ytop) return GEO_SOUTH; + else + if(r0->r_ytop == r1->r_ybot) return GEO_NORTH; + else + return(GEO_CENTER); +} + +/* ---------------------------------------------------------------------------- + * + * GeoDecomposeTransform -- + * + * Break a transform up into an optional mirror followed by an optional + * rotation. Translation is ignored. Maybe someone will add this at + * a later date. + * + * Results: + * None. + * + * Side Effects: + * Modifies 'angle' and 'upsidedown' parameters. + * + * ---------------------------------------------------------------------------- + */ + +void +GeoDecomposeTransform(t, upsidedown, angle) + Transform *t; + bool *upsidedown; /* Set to TRUE iff we should flip upsidedown + * before rotating. + */ + int *angle; /* Amount to rotate. + * Will be 0, 90, 180, or 270. + */ +{ + Transform notrans; /* Transform without any translation -- includes + * both rotation and mirroring. + */ + Transform rotonly; /* Version of above with only rotation. */ + + notrans = *t; + notrans.t_c = 0; + notrans.t_f = 0; + + /* Compute rotations and flips. */ + *upsidedown = ((notrans.t_a == 0) ^ + (notrans.t_b == notrans.t_d) ^ (notrans.t_a == notrans.t_e)); + if (*upsidedown) + GeoTransTrans(¬rans, &GeoUpsideDownTransform, &rotonly); + else + rotonly = notrans; + /* Verify no flipping. */ + ASSERT(rotonly.t_a == rotonly.t_e, "GeoDecomposeTransform"); + + *angle = 0; + if (rotonly.t_b != 0) + { + *angle += 90; + if (*upsidedown) *angle += 180; + } + if ((rotonly.t_a < 0) || (rotonly.t_b < 0)) *angle += 180; + if (*angle > 270) *angle -= 360; +} diff --git a/utils/geometry.h b/utils/geometry.h new file mode 100644 index 00000000..02a79df9 --- /dev/null +++ b/utils/geometry.h @@ -0,0 +1,214 @@ +/* geometry.h -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This module contains the basic definitions for geometrical + * elements: points, rectangles, and transforms. + */ + +/* rcsid "$Header: /usr/cvsroot/magic-8.0/utils/geometry.h,v 1.2 2009/09/10 20:32:55 tim Exp $" */ + +#ifndef _GEOMETRY_H +#define _GEOMETRY_H 1 + +/*------------------------------------------------------------------- + * Structure definition for Point (an x,y pair). + *------------------------------------------------------------------- + */ + +typedef struct +{ + int p_x; + int p_y; +} Point; + +/*------------------------------------------------------------------- + * Structure definition for rectangles. A rectangle is defined + * by the coordinates of its lower-left and upper-right corners. + * Most routines that manipulate rectangles require the first + * point to really be the lower-left one, so be careful about this. + * A null rectangle is indicated by making both x-coordinates the + * same. + *------------------------------------------------------------------- + */ + +typedef struct +{ + Point r_ll; /* Lower-left corner of rectangle. */ + Point r_ur; /* Upper-right corner of rectangle. */ +} Rect; + +#define r_xbot r_ll.p_x +#define r_ybot r_ll.p_y +#define r_xtop r_ur.p_x +#define r_ytop r_ur.p_y + +typedef struct _linkedRect /* A linked rectangle */ +{ + Rect r_r; /* A rectangle. */ + int r_type; /* Tile type of rectangle */ + struct _linkedRect *r_next; /* Pointer to another linked rectangle */ +} LinkedRect; + +/*------------------------------------------------------------------- + * Structure definition for geometrical transformers. They are + * stored in the form described by Newman and Sproull on page 57. + * Magic allows only 90 degree orientations, and normally there + * is no scaling (scaling only occurs when transforming to pixel + * coordinates). Thus the elements a, b, d, and e always have + * one of the following forms, where S is the scaling factor: + * + * S 0 0 -S -S 0 0 S S 0 0 S -S 0 0 -S + * 0 S S 0 0 -S -S 0 0 -S S 0 0 S -S 0 + * + * The first four forms correspond to clockwise rotations of 0, 90, + * 180, and 270 degrees, and the second four correspond to the same + * four orientations flipped upside down (mirror across the x-axis + * after rotating). + *------------------------------------------------------------------- + */ + +typedef struct +{ + int t_a, t_b, t_c, t_d, t_e, t_f; +} Transform; + +/*------------------------------------------------------------------- + * Definitions for positions. Positions are small integers + * used to select where text gets placed, relative to a point. + *------------------------------------------------------------------- + */ + +#define GEO_CENTER 0 +#define GEO_NORTH 1 +#define GEO_NORTHEAST 2 +#define GEO_EAST 3 +#define GEO_SOUTHEAST 4 +#define GEO_SOUTH 5 +#define GEO_SOUTHWEST 6 +#define GEO_WEST 7 +#define GEO_NORTHWEST 8 + + +/* See if two points are equal */ +#define GEO_SAMEPOINT(p1, p2) ((p1).p_x == (p2).p_x && (p1).p_y == (p2).p_y) + +/* See if two rects are equal */ +#define GEO_SAMERECT(r1, r2) \ + (GEO_SAMEPOINT((r1).r_ll, (r2).r_ll) && GEO_SAMEPOINT((r1).r_ur, (r2).r_ur)) + +/*------------------------------------------------------------------- + * The following macros are predicates to see if two + * rectangles overlap or touch. + *------------------------------------------------------------------- + */ + +/* see if the rectangles overlap (the overlap contains some area) */ + +#define GEO_OVERLAP(r1, r2) \ + (((r1)->r_xbot < (r2)->r_xtop) && ((r2)->r_xbot < (r1)->r_xtop) \ + && ((r1)->r_ybot < (r2)->r_ytop) && ((r2)->r_ybot < (r1)->r_ytop)) + +/* see if the rectangles touch (share part of a side) or overlap */ + +#define GEO_TOUCH(r1, r2) \ + (((r1)->r_xbot <= (r2)->r_xtop) && ((r2)->r_xbot <= (r1)->r_xtop) \ + && ((r1)->r_ybot <= (r2)->r_ytop) && ((r2)->r_ybot <= (r1)->r_ytop)) + +/* see if rectangle r1 completely surrounds rectangle r2. Touching between + * r2 and r1 IS allowed. + */ + +#define GEO_SURROUND(r1,r2) \ + ( ((r2)->r_xbot >= (r1)->r_xbot) && ((r2)->r_xtop <= (r1)->r_xtop) \ + && ((r2)->r_ybot >= (r1)->r_ybot) && ((r2)->r_ytop <= (r1)->r_ytop) ) + +/* see if rectangle r1 completely surrounds rectangle r2 WITHOUT touching it. + */ + +#define GEO_SURROUND_STRONG(r1,r2) \ + ( ((r2)->r_xbot > (r1)->r_xbot) && ((r2)->r_xtop < (r1)->r_xtop) \ + && ((r2)->r_ybot > (r1)->r_ybot) && ((r2)->r_ytop < (r1)->r_ytop) ) + +/* See if point p in inside of or on the border of r */ +#define GEO_ENCLOSE(p, r) \ + ( ((p)->p_x <= (r)->r_xtop) && ((p)->p_x >= (r)->r_xbot) && \ + ((p)->p_y <= (r)->r_ytop) && ((p)->p_y >= (r)->r_ybot) ) + +/* See if a label is in a given area */ +#define GEO_LABEL_IN_AREA(lab,area) \ + (GEO_SURROUND(area, lab) || \ + (GEO_RECTNULL(area) && GEO_TOUCH(lab, area) && \ + !(GEO_SURROUND_STRONG(lab, area)))) + +/* See if a rectangle has no area. */ + +#define GEO_RECTNULL(r) \ + (((r)->r_xbot >= (r)->r_xtop) || ((r)->r_ybot >= (r)->r_ytop)) + +/* Expand a rectangular area by a given amount. */ + +#define GEO_EXPAND(src, amount, dst) \ +{ \ + (dst)->r_xbot = (src)->r_xbot - amount; \ + (dst)->r_ybot = (src)->r_ybot - amount; \ + (dst)->r_xtop = (src)->r_xtop + amount; \ + (dst)->r_ytop = (src)->r_ytop + amount; \ +} + +/* Sizes of rectangles. */ +#define GEO_WIDTH(r) ((r)->r_xtop - (r)->r_xbot) +#define GEO_HEIGHT(r) ((r)->r_ytop - (r)->r_ybot) + + +/*------------------------------------------------------------------- + * Declarations for exported procedures: + *------------------------------------------------------------------- + */ + +extern int GeoNameToPos(char *, bool, bool); +extern char * GeoPosToName(int); +extern void GeoTransRect(Transform *, Rect *, Rect *), GeoTransTrans(Transform *, Transform *, Transform *); +extern void GeoTransPoint(Transform *, Point *, Point *), GeoInvertTrans(Transform *, Transform *); +extern void GeoTranslateTrans(Transform *, int, int, Transform *); +extern void GeoTransTranslate(int, int, Transform *, Transform *); +extern int GeoTransPos(Transform *, int); +extern bool GeoInclude(Rect *, Rect *), GeoIncludeAll(Rect *, Rect *); +extern void GeoClip(Rect *, Rect *); +extern void GeoClipPoint(Point *, Rect *); +extern int GeoRectPointSide(Rect *, Point *); +extern int GeoRectRectSide(Rect *, Rect *); +extern void GeoIncludePoint(Point *, Rect *); +extern void GeoDecomposeTransform(Transform *, bool *, int *); + +/* + *------------------------------------------------------------------- + * Declarations of exported transforms and rectangles: + *------------------------------------------------------------------- + */ + +extern Transform GeoIdentityTransform; +extern Transform GeoUpsideDownTransform; +extern Transform GeoSidewaysTransform; +extern Transform Geo90Transform; +extern Transform Geo180Transform; +extern Transform Geo270Transform; +extern Transform GeoRef45Transform; +extern Transform GeoRef135Transform; + +extern Rect GeoNullRect; +extern Point GeoOrigin; + +extern int GeoOppositePos[]; + +#endif /* _GEOMETRY_H */ diff --git a/utils/getrect.c b/utils/getrect.c new file mode 100644 index 00000000..c51cf273 --- /dev/null +++ b/utils/getrect.c @@ -0,0 +1,132 @@ +/* + * getrect.c - + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * Lawrence Livermore National Laboratory + * + * This file contains a procedure, GetRect(), for gobbling up + * four integers from an input file. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/getrect.c,v 1.3 2010/06/24 12:37:58 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" + +/* + * ---------------------------------------------------------------------------- + * + * GetRect -- + * + * Parse a rectangle from a file and fill in the supplied rect struct. + * We assume that the rectangle consists of four decimal numbers, each + * separated from the next by a single space, and terminated by a newline. + * + * ESTHETIC WARNING: + * The algorithm used here is gross but extremely fast. + * + * Results: + * FALSE on end of file or error, TRUE otherwise. + * If nonmanhattan extensions are enabled, it returns a + * direction result for triangles. + * + * Side effects: + * Fills in the contents of *rect. + * + * ---------------------------------------------------------------------------- + */ + +#define RECTBUFTHRESHOLD 100 + +int +GetRect(fin, skip, rect, scalen, scaled) + FILE *fin; + int skip; /* Number of bytes to skip before rect */ + Rect *rect; /* Pointer to rectangle to be filled in */ + int scalen; /* Scale up by this amount */ + int scaled; /* Scale down by this amount */ +{ + int n, c; + char *cp; + bool isNegative; + int dir = 0x1; + + while (skip-- > 0) + (void) getc(fin); + + if (isNegative = ((c = getc(fin)) == '-')) c = getc(fin); + for (n = 0; isdigit(c); n = n * 10 + c - '0', c = getc(fin)) + /* Nothing */; + rect->r_xbot = isNegative ? -n : n; + if (!isspace(c)) goto bad; + while ((c = getc(fin)) != EOF && isspace(c)) /* Nothing */; + + if (isNegative = (c == '-')) c = getc(fin); + for (n = 0; isdigit(c); n = n * 10 + c - '0', c = getc(fin)) + /* Nothing */; + rect->r_ybot = isNegative ? -n : n; + if (!isspace(c)) goto bad; + while ((c = getc(fin)) != EOF && isspace(c)) /* Nothing */; + + if (isNegative = (c == '-')) c = getc(fin); + for (n = 0; isdigit(c); n = n * 10 + c - '0', c = getc(fin)) + /* Nothing */; + rect->r_xtop = isNegative ? -n : n; + if (!isspace(c)) goto bad; + while ((c = getc(fin)) != EOF && isspace(c)) /* Nothing */; + + if (isNegative = (c == '-')) c = getc(fin); + for (n = 0; isdigit(c); n = n * 10 + c - '0', c = getc(fin)) + /* Nothing */; + rect->r_ytop = isNegative ? -n : n; + + if (scalen > 1) + { + rect->r_xbot *= scalen; + rect->r_ybot *= scalen; + rect->r_xtop *= scalen; + rect->r_ytop *= scalen; + } + if (scaled > 1) + { + rect->r_xbot /= scaled; + rect->r_ybot /= scaled; + rect->r_xtop /= scaled; + rect->r_ytop /= scaled; + } + + while (c != EOF && c != '\n') + { + c = getc(fin); + switch ((char)c) + { + case 's': + dir |= 0x2; + break; + case 'e': + dir |= 0x4; + break; + } + } + return dir; + +bad: + while (c != EOF && c != '\n') + c = getc(fin); + return (FALSE); +} diff --git a/utils/hash.c b/utils/hash.c new file mode 100644 index 00000000..e6c12aed --- /dev/null +++ b/utils/hash.c @@ -0,0 +1,691 @@ +/* hash.c -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This module contains routines to manipulate a hash table. + * See hash.h for a definition of the structure of the hash + * table. Hash tables grow automatically as the amount of + * information increases. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/hash.c,v 1.2 2009/05/13 15:03:18 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/hash.h" +#include "utils/malloc.h" + +/* Used before it's defined: */ +void rebuild(); + +/* + * The following defines the ratio of # entries to # buckets + * at which we rebuild the table to make it larger. + */ +static int rebuildLimit = 3; + +/* + * An invalid pointer, guaranteed to cause a coredump if + * we try to indirect through it. This should help catch + * attempts to indirect through stale pointers. + */ +#define NIL ((HashEntry *) (1<<29)) + + +/*--------------------------------------------------------- + * + * HashInit -- + * HashInitClient -- + * + * These procedures simply set up the hash table. The standard + * way of initializing the hash table is to use HashInit(), but + * if it's desired to provide the hash module with procedures to + * use for comparing and copying hash table keys, use HashInitClient(). + * + * The number of buckets in the table at the start is 'nBuckets', + * which is automatically rounded up to a power of two. This isn't + * a limit on the number of buckets the table will eventually contain, + * though, since more buckets are automatically created if the table + * gets too full (the number of buckets increases by 4x). + * + * Results: + * None. + * + * Side Effects: + * Memory is allocated for the initial bucket area. + * + * Table Organization: + * Tables can be organized in either of four ways, depending + * on the type of comparison keys as specified by ptrKeys. + * + * HT_STRINGKEYS: + * Keys are NULL-terminated; their address is passed to + * HashFind as a (char *). + * + * HT_WORDKEYS: + * These are any 32-bit word, passed to HashFind as a (char *). + * + * HT_STRUCTKEYS: + * Actually, any value of ptrKeys >= HT_STRUCTKEYS means + * that keys are ptrKeys-word values whose ADDRESS is + * passed to HashFind as a (char *). + * + * HT_CLIENTKEYS: + * Like HT_WORDKEYS, these are also 32-bit values, passed + * to HashFind as a (char *). However, they are compared + * and copied using user-supplied procedures passed to + * HashInitClient() when the hash table was created. + * (Note that hash tables with keys of type HT_CLIENTKEYS + * can ONLY be created using HashInitClient()). + * + * Single-word values, a la HT_WORDKEYS, are fastest but most + * restrictive. + * + * Client procedures: + * Four client procedures are provided to HashInitClient() + * for use in dealing with HT_CLIENTKEYS data. They should + * be of the following form: + * + * Compare two hash keys; return 0 if equal, 1 if not. If this + * procedure is NULL, comparison is just 32-bit comparison of + * k1 and k2. + * + * int + * (*compareFn)(k1, k2) + * char *k1, *k2; + * { + * } + * + * Create a copy of a hash key for storing in a newly created + * hash entry. If this procedure is NULL, the key is stored + * without being copied. + * + * char * + * (*copyFn)(key) + * char *key; + * { + * } + * + * Produce a single 32-bit integer for a key value that will + * then be randomized by the hashing function. If NULL, then + * the key itself is used as the 32-bit integer. + * + * int + * (*hashFn)(key) + * char *key; + * { + * } + * + * Free a key that had been allocated with (*copyFn)(). + * If NULL, then nothing is done. + * + * int + * (*killFn)(key) + * char *key; + * { + * } + * + *--------------------------------------------------------- + */ + +void +HashInit(table, nBuckets, ptrKeys) + HashTable *table; /* Table to be initialized */ + int nBuckets; /* How many buckets to create for starters */ + int ptrKeys; /* See comments above */ +{ + ASSERT(ptrKeys != HT_CLIENTKEYS, "HashInit: should use HashInitClient"); + HashInitClient(table, nBuckets, ptrKeys, + (int (*)()) NULL, (char *(*)()) NULL, + (int (*)()) NULL, (int (*)()) NULL); +} + +void +HashInitClient(table, nBuckets, ptrKeys, compareFn, copyFn, hashFn, killFn) + HashTable *table; /* Table to be initialized */ + int nBuckets; /* How many buckets to create for starters */ + int ptrKeys; /* See comments above */ + int (*compareFn)(); /* Function to compare two keys */ + char *(*copyFn)(); /* Function to copy a key */ + int (*hashFn)(); /* For hashing */ + int (*killFn)(); /* For hashing */ +{ + HashEntry ** ptr; + int i; + + table->ht_nEntries = 0; + table->ht_ptrKeys = ptrKeys; + table->ht_compareFn = compareFn; + table->ht_copyFn = copyFn; + table->ht_hashFn = hashFn; + table->ht_killFn = killFn; + + /* Round up the size to a power of two */ + if (nBuckets < 0) nBuckets = -nBuckets; + table->ht_size = 2; + table->ht_mask = 1; + table->ht_downShift = 29; + while (table->ht_size < nBuckets) + { + table->ht_size <<= 1; + table->ht_mask = (table->ht_mask<<1) + 1; + table->ht_downShift--; + } + + /* Allocate and initialize the buckets */ + table->ht_table = (HashEntry **) mallocMagic( + (unsigned) (sizeof (HashEntry *) * table->ht_size)); + ptr = table->ht_table; + for (i = 0; i < table->ht_size; i++) + *ptr++ = NIL; +} + +/*--------------------------------------------------------- + * + * hash -- + * + * This is a local procedure to compute a hash table + * bucket address based on a key value. + * + * Results: + * The return value is an integer between 0 and size-1. + * + * Side Effects: + * None. + * + * Design: + * The randomizing code is stolen straight from the rand() + * library routine. + * + *--------------------------------------------------------- + */ + +int +hash(table, key) + HashTable *table; + char *key; +{ + unsigned *up; + int i, j; + + i = 0; + switch (table->ht_ptrKeys) + { + /* Add up the characters as though this were a number */ + case HT_STRINGKEYS: + while (*key != 0) i = (i*10) + (*key++ - '0'); + break; + + /* Map the key into another 32-bit value if necessary */ + case HT_CLIENTKEYS: + if (table->ht_hashFn) + { + i = (*(table->ht_hashFn))(key); + break; + } + /* Fall through to ... */ + + /* Just use the 32-bit key value */ + case HT_WORDKEYS: + i = (spointertype) key; + break; + + /* Special case for two-word structs */ + case HT_STRUCTKEYS: + i = ((unsigned *) key)[0] + ((unsigned *) key)[1]; + break; + + /* General case of multi-word structs */ + default: + j = table->ht_ptrKeys; + up = (unsigned *) key; + do { i += *up++; } while (--j); + break; + } + + /* Randomize! */ + return ((i*1103515245 + 12345) >> table->ht_downShift) & table->ht_mask; +} + +/*--------------------------------------------------------- + * + * HashLookOnly -- + * + * Searches a hash table for an entry corresponding to key. + * + * Results: + * The return value is a pointer to the entry for key, + * if key was present in the table. If key was not + * present, NULL is returned. + * + * Side Effects: + * None. + * + *--------------------------------------------------------- + */ + +HashEntry * +HashLookOnly(table, key) + HashTable *table; /* Hash table to search. */ + char *key; /* Interpreted according to table->ht_ptrKeys + * as described in HashInit()'s comments. + */ +{ + HashEntry *h; + unsigned *up, *kp; + int n; + int bucket; + + bucket = hash(table, key); + h = *(table->ht_table + bucket); + while (h != NIL) + { + switch (table->ht_ptrKeys) + { + case HT_STRINGKEYS: + if (strcmp(h->h_key.h_name, key) == 0) return h; + break; + case HT_CLIENTKEYS: + if (table->ht_compareFn) + { + if ((*table->ht_compareFn)(h->h_key.h_ptr, key) == 0) + return h; + break; + } + /* Fall through to ... */ + case HT_WORDKEYS: + if (h->h_key.h_ptr == key) return h; + break; + case HT_STRUCTKEYS: + up = h->h_key.h_words; + kp = (unsigned *) key; + if (*up++ == *kp++ && *up == *kp) return h; + break; + default: + n = table->ht_ptrKeys; + up = h->h_key.h_words; + kp = (unsigned *) key; + do { if (*up++ != *kp++) goto next; } while (--n); + return h; + } +next: + h = h->h_next; + } + + /* The desired entry isn't there */ + return ((HashEntry *) NULL); +} + +/*--------------------------------------------------------- + * + * HashFind -- + * + * Searches a hash table for an entry corresponding to + * key. If no entry is found, then one is created. + * + * Results: + * The return value is a pointer to the entry for key. + * If the entry is a new one, then the h_pointer field + * of the entry we return is zero. + * + * Side Effects: + * Memory is allocated, and the hash buckets may be modified. + * + *--------------------------------------------------------- + */ + +HashEntry * +HashFind(table, key) + HashTable *table; /* Hash table to search. */ + char *key; /* Interpreted according to table->ht_ptrKeys + * as described in HashInit()'s comments. + */ +{ + unsigned *up, *kp; + HashEntry *h; + int n; + int bucket; + + bucket = hash(table, key); + h = *(table->ht_table + bucket); + while (h != NIL) + { + switch (table->ht_ptrKeys) + { + case HT_STRINGKEYS: + if (strcmp(h->h_key.h_name, key) == 0) return h; + break; + case HT_CLIENTKEYS: + if (table->ht_compareFn) + { + if ((*table->ht_compareFn)(h->h_key.h_ptr, key) == 0) + return h; + break; + } + /* Fall through to ... */ + case HT_WORDKEYS: + if (h->h_key.h_ptr == key) return h; + break; + case HT_STRUCTKEYS: + up = h->h_key.h_words; + kp = (unsigned *) key; + if (*up++ == *kp++ && *up == *kp) return h; + break; + default: + n = table->ht_ptrKeys; + up = h->h_key.h_words; + kp = (unsigned *) key; + do { if (*up++ != *kp++) goto next; } while (--n); + return h; + } +next: + h = h->h_next; + } + + /* + * The desired entry isn't there. Before allocating a new entry, + * see if we're overloading the buckets. If so, then make a + * bigger table (4x as big). + */ + if (table->ht_nEntries >= rebuildLimit*table->ht_size) + { + rebuild(table); + bucket = hash(table, key); + } + table->ht_nEntries += 1; + + /* + * Now allocate a new entry. The size of the HashEntry allocated + * depends on the size of the key: for multi-word keys or string + * keys longer than 3 bytes, there will be extra space at the end + * of the HashEntry to hold the key. + */ + switch (table->ht_ptrKeys) + { + case HT_STRINGKEYS: + h = (HashEntry *) mallocMagic((unsigned) (sizeof(HashEntry)+strlen(key)-3)); + (void) strcpy(h->h_key.h_name, key); + break; + case HT_CLIENTKEYS: + if (table->ht_copyFn) + { + h = (HashEntry *) mallocMagic((unsigned) (sizeof (HashEntry))); + h->h_key.h_ptr = (*table->ht_copyFn)(key); + break; + } + /* Fall through to ... */ + case HT_WORDKEYS: + h = (HashEntry *) mallocMagic((unsigned) (sizeof (HashEntry))); + h->h_key.h_ptr = key; + break; + case HT_STRUCTKEYS: + h = (HashEntry *) mallocMagic( + (unsigned) (sizeof (HashEntry) + sizeof (unsigned))); + up = h->h_key.h_words; + kp = (unsigned *) key; + *up++ = *kp++; + *up = *kp; + break; + default: + n = table->ht_ptrKeys; + h = (HashEntry *) mallocMagic( + (unsigned) (sizeof(HashEntry) + (n-1) * sizeof (unsigned))); + up = h->h_key.h_words; + kp = (unsigned *) key; + do { *up++ = *kp++; } while (--n); + break; + } + + h->h_pointer = 0; + h->h_next = *(table->ht_table + bucket); + *(table->ht_table + bucket) = h; + return h; +} + +/*--------------------------------------------------------- + * + * rebuild -- + * + * This local routine makes a new hash table that + * is 4x larger than the old one. + * + * Results: + * None. + * + * Side Effects: + * The entire hash table is moved, so any bucket numbers + * from the old table are invalid. + * + *--------------------------------------------------------- + */ + +void +rebuild(table) + HashTable *table; /* Table to be enlarged. */ +{ + HashEntry **oldTable, **old2, *h, *next; + int oldSize, bucket; + + oldTable = table->ht_table; + old2 = oldTable; + oldSize = table->ht_size; + + /* Build a new table 4 times as large as the old one. */ + HashInitClient(table, table->ht_size*4, table->ht_ptrKeys, + table->ht_compareFn, table->ht_copyFn, + table->ht_hashFn, table->ht_killFn); + for ( ; oldSize > 0; oldSize--) + { + h = *old2++; + while (h != NIL) + { + next = h->h_next; + switch (table->ht_ptrKeys) + { + case HT_STRINGKEYS: + bucket = hash(table, h->h_key.h_name); + break; + case HT_WORDKEYS: + case HT_CLIENTKEYS: + bucket = hash(table, h->h_key.h_ptr); + break; + default: + bucket = hash(table, (char *) h->h_key.h_words); + break; + } + h->h_next = *(table->ht_table + bucket); + *(table->ht_table + bucket) = h; + table->ht_nEntries += 1; + h = next; + } + } + + freeMagic((char *) oldTable); +} + +/*--------------------------------------------------------- + * + * HashStats -- + * + * This routine merely prints statistics about the + * current bucket situation. + * + * Results: + * None. + * + * Side Effects: + * Junk gets printed. + * + *--------------------------------------------------------- + */ + +#define MAXCOUNT 15 + +void +HashStats(table) + HashTable *table; +{ + int count[MAXCOUNT], overflow, i, j; + HashEntry *h; + + overflow = 0; + for (i = 0; i < MAXCOUNT; i++) count[i] = 0; + for (i = 0; i < table->ht_size; i++) + { + j = 0; + for (h = *(table->ht_table+i); h != NIL; h = h->h_next) + j++; + if (j < MAXCOUNT) count[j]++; + else overflow++; + } + + for (i = 0; i < MAXCOUNT; i++) + printf("# of buckets with %d entries: %d.\n", i, count[i]); + printf("# of buckets with >%d entries: %d.\n", MAXCOUNT-1, overflow); +} + +/*--------------------------------------------------------- + * + * HashStartSearch -- + * + * This procedure sets things up for a complete search + * of all entries recorded in the hash table. + * + * Results: + * None. + * + * Side Effects: + * The information in hs is initialized so that successive + * calls to HashNext will return successive HashEntry's + * from the table. + *--------------------------------------------------------- + */ + +void +HashStartSearch(hs) + HashSearch *hs; /* Area in which to keep state about search.*/ +{ + hs->hs_nextIndex = 0; + hs->hs_h = NIL; +} + +/*--------------------------------------------------------- + * + * HashNext -- + * + * This procedure returns successive entries in the + * hash table. + * + * Results: + * The return value is a pointer to the next HashEntry + * in the table, or NULL when the end of the table is + * reached. + * + * Side Effects: + * The information in hs is modified to advance to the + * next entry. + * + *--------------------------------------------------------- + */ + +HashEntry * +HashNext(table, hs) + HashTable *table; /* Table to be searched. */ + HashSearch *hs; /* Area used to keep state about search. */ +{ + HashEntry *h; + + while (hs->hs_h == NIL) + { + if (hs->hs_nextIndex >= table->ht_size) return NULL; + hs->hs_h = *(table->ht_table + hs->hs_nextIndex); + hs->hs_nextIndex += 1; + } + h = hs->hs_h; + hs->hs_h = h->h_next; + return h; +} + +/*--------------------------------------------------------- + * + * HashKill -- + * + * This routine removes everything from a hash table + * and frees up the memory space it occupied. + * + * Results: + * None. + * + * Side Effects: + * Lots of memory is freed up. + *--------------------------------------------------------- + */ + +void +HashKill(table) + HashTable *table; /* Hash table whose space is to be freed */ +{ + HashEntry *h, **hp, **hend; + int (*killFn)() = (int (*)()) NULL; + + if (table->ht_ptrKeys == HT_CLIENTKEYS) killFn = table->ht_killFn; + for (hp = table->ht_table, hend = &hp[table->ht_size]; hp < hend; hp++) + for (h = *hp; h != NIL; h = h->h_next) + { + freeMagic((char *) h); + if (killFn) + (*killFn)(h->h_key.h_ptr); + } + freeMagic((char *) table->ht_table); + + /* + * Set up the hash table to cause memory faults on any future + * access attempts until re-initialization. + */ + table->ht_table = (HashEntry **) (1<<29); +} + +/*--------------------------------------------------------- + * + * HashFreeKill --- + * + * This routine removes everything from a hash table + * and frees up the memory space it occupied along with + * the stuff pointed by h_pointer + * + * Results: + * None. + * + * Side Effects: + * Lots of memory is freed up. + *--------------------------------------------------------- + */ +void +HashFreeKill(table) +HashTable *table; +{ + HashSearch hs; + HashEntry *he; + void *p; + + HashStartSearch(&hs); + while (he = HashNext(table, &hs)) { + p = HashGetValue(he); + freeMagic(p); + } + HashKill(table); +} diff --git a/utils/hash.h b/utils/hash.h new file mode 100644 index 00000000..12e32e6f --- /dev/null +++ b/utils/hash.h @@ -0,0 +1,135 @@ +/* hash.h -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains definitions used by the hash module, + * which maintains hash tables. + */ + +/* rcsid "$Header: /usr/cvsroot/magic-8.0/utils/hash.h,v 1.2 2009/09/10 20:32:55 tim Exp $" */ + +#ifndef _HASH_H +#define _HASH_H + +/*--------------------------------------------------------- + * This first stuff should only be used internally + * in the hash routines. + *--------------------------------------------------------- + */ + +/* The following defines one entry in the hash table. */ + +typedef struct h1 +{ + char *h_pointer; /* Pointer to anything. */ + struct h1 *h_next; /* Next element, zero for end. */ + union + { + char *h_ptr; /* One-word key value to identify entry. */ + unsigned h_words[1]; /* N-word key value. Note: the actual + * size may be longer if necessary to hold + * the entire key. + */ + char h_name[4]; /* Text name of this entry. Note: the + * actual size may be longer if necessary + * to hold the whole string. This MUST be + * the last entry in the structure!!! + */ + } h_key; +} HashEntry; + +/* A hash table consists of an array of pointers to hash + * lists: + */ + +typedef struct h3 +{ + HashEntry **ht_table; /* Pointer to array of pointers. */ + int ht_size; /* Actual size of array. */ + int ht_nEntries; /* Number of entries in the table. */ + int ht_downShift; /* Shift count, used in hashing function. */ + int ht_mask; /* Used to select bits for hashing. */ + int ht_ptrKeys; /* See below */ + + /* Used if ht_ptrKeys == HT_CLIENTKEYS */ + char *(*ht_copyFn)(); /* Used for copying a key value */ + int (*ht_compareFn)(); /* Used for comparing two keys for equality */ + int (*ht_hashFn)(); /* Hash function */ + int (*ht_killFn)(); /* Used to kill an entry */ +} HashTable; + +/* + * Values for ht_ptrKeys. + * + * HT_STRINGKEYS means that keys are NULL-terminated strings stored + * in the variable-sized array h_key.h_name at the end of a HashEntry. + * + * HT_WORDKEYS and HT_CLIENTKEYS both mean that the value is stored + * in h_key.h_ptr; with HT_WORDKEYS it is treated as a one-word value, + * while with HT_CLIENTKEYS it is interpreted by user-supplied procedures + * (and hence it can be a pointer). + * + * Finally, values of ht_ptrKeys of HT_STRUCTKEYS or greater mean + * that the key consists of ht_ptrKeys 32-bit words of data, stored + * in the variable-sized array h_key.h_words. + */ +#define HT_CLIENTKEYS -1 +#define HT_STRINGKEYS 0 +#define HT_WORDKEYS 1 +#define HT_STRUCTKEYS 2 + +/* + * Default initial size (number of buckets) in a hash table. + * May be passed to HashInit() or HashInitClient(). + */ +#define HT_DEFAULTSIZE 32 + +/* The following structure is used by the searching routines + * to record where we are in the search. + */ + +typedef struct h2 +{ + int hs_nextIndex; /* Next bucket to check (after current). */ + HashEntry * hs_h; /* Next entry to check in current bucket. */ +} HashSearch; + +/*--------------------------------------------------------- + * The following procedure declarations and macros + * are the only things that should be needed outside + * the implementation code. + *--------------------------------------------------------- + */ + +extern void HashInit(HashTable *, int, int), HashInitClient(), HashStats(), HashKill(), + HashFreeKill(); +extern HashEntry *HashFind(HashTable *, char *); +extern HashEntry *HashLookOnly(HashTable *, char *); +extern void HashStartSearch(HashSearch *); +extern HashEntry *HashNext(HashTable *, HashSearch *); + +/* char * HashGetValue(h); HashEntry *h; */ + +#define HashGetValue(h) ((h)->h_pointer) + +/* HashSetValue(h, val); HashEntry *h; char *val; */ + +#define HashSetValue(h, val) ((h)->h_pointer = (char *) (val)) + +/* HashSize(n) returns the number of words in an object of n bytes */ +#define HashSize(n) (((n) + sizeof (unsigned) - 1) / sizeof (unsigned)) + +/* HashGetNumEntries(ht); HashTable *ht ; returns number of entries in table */ +#define HashGetNumEntries(ht) ((ht)->ht_nEntries) + +#endif /* _HASH_H */ diff --git a/utils/heap.c b/utils/heap.c new file mode 100644 index 00000000..cc4f4cf2 --- /dev/null +++ b/utils/heap.c @@ -0,0 +1,556 @@ +/* + * heap.c - + * + * Routines to create and manipulate heaps. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/heap.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/heap.h" +#include "utils/utils.h" +#include "utils/malloc.h" + +#define heapLeft(used,i) ((used) < ( (i)<<1) ? 0 : (i)+(i) ) +#define heapRight(used,i) ((used) < (((i)<<1)+1) ? 0 : (i)+(i)+1) + +#define KEY_LESS_COND(t, l, i1, i2, stmt) \ + switch (t) { \ + case HE_INT: if (l[i1].he_int < l[i2].he_int) stmt; \ + break; \ + case HE_DLONG: if ((l[i1].he_dlong < l[i2].he_dlong)) stmt; \ + break; \ + case HE_DOUBLE: if (l[i1].he_double < l[i2].he_double) stmt; \ + break; \ + case HE_FLOAT: if (l[i1].he_float < l[i2].he_float) stmt; \ + break; \ + } + +#define KEY_LE_COND(t, l, i1, i2, stmt) \ + switch (t) { \ + case HE_INT: if (l[i1].he_int <= l[i2].he_int) stmt; \ + break; \ + case HE_DLONG: if ((l[i1].he_dlong <=l[i2].he_dlong)) stmt; \ + break; \ + case HE_DOUBLE: if (l[i1].he_double <= l[i2].he_double) stmt; \ + break; \ + case HE_FLOAT: if (l[i1].he_float <= l[i2].he_float) stmt; \ + break; \ + } + +#define KEY_GREATER_COND(t, l, i1, i2, stmt) \ + switch (t) { \ + case HE_INT: if (l[i1].he_int > l[i2].he_int) stmt; \ + break; \ + case HE_DLONG:if(l[i1].he_dlong > l[i2].he_dlong) stmt; \ + break; \ + case HE_DOUBLE: if (l[i1].he_double > l[i2].he_double) stmt; \ + break; \ + case HE_FLOAT: if (l[i1].he_float > l[i2].he_float) stmt; \ + break; \ + } + +#define KEY_GE_COND(t, l, i1, i2, stmt) \ + switch (t) { \ + case HE_INT: if (l[i1].he_int >= l[i2].he_int) stmt; \ + break; \ + case HE_DLONG: if ((l[i1].he_dlong >= l[i2].he_dlong)) stmt; \ + break; \ + case HE_DOUBLE: if (l[i1].he_double >= l[i2].he_double) stmt; \ + break; \ + case HE_FLOAT: if (l[i1].he_float >= l[i2].he_float) stmt; \ + break; \ + } + +/* Forward declarations */ + +extern void heapify(); + + +/* + * ---------------------------------------------------------------------------- + * + * HeapInit -- + * HeapInitType -- + * + * Initialize a heap. The first form is a heap with integer keys; the + * second allows specification of the type of key to use. + * + * Note that with this addressing scheme it is necessary to allocate + * 2**n + 1 locations for the heap block, location 0 being unused. + * + * Results: + * None. + * + * Side effects: + * Allocates storage for the heap. Initializes the fields in the heap + * struct. Memory is allocated. + * + * ---------------------------------------------------------------------------- + */ + +void +HeapInit(heap, size, descending, stringIds) + Heap *heap; /* Pointer to a heap struct */ + int size; /* Initial size of heap */ + int descending; /* TRUE if largest on top */ + int stringIds; /* TRUE if entry id's are strings */ +{ + HeapInitType(heap, size, descending, stringIds, HE_INT); +} + +void +HeapInitType(heap, size, descending, stringIds, keyType) + Heap *heap; /* Pointer to a heap struct */ + int size; /* Initial size of heap */ + int descending; /* TRUE if largest on top */ + int stringIds; /* TRUE if entry id's are strings */ + int keyType; /* Type of keys to use */ +{ + if (size < 0) size = -size; + heap->he_size = 2; + while (size > heap->he_size) + heap->he_size <<= 1; + heap->he_used = 0; + heap->he_built = 0; + heap->he_big = descending; + heap->he_stringId = stringIds; + + /* + * Add 2 to the size because location 0 is used as a temporary, + * and location (2**n) + 1 is the last leaf + */ + switch (heap->he_keyType = keyType) + { + case HE_INT: + case HE_DLONG: + case HE_FLOAT: + case HE_DOUBLE: + break; + default: + TxError("Unsupported key type: %d\n", keyType); + break; + } + + heap->he_list = (HeapEntry *) mallocMagic((unsigned) ((heap->he_size+2) + * sizeof (HeapEntry))); + ASSERT(heap->he_list != NULL, "Malloc failed in HeapInit"); +} + +/* + * ---------------------------------------------------------------------------- + * + * HeapKill -- + * + * Deallocate all storage associated with the heap. + * + * Results: + * None. + * + * Side effects: + * Storage is freed. Fields in the heap record are reset. If func is + * not NULL then call it with each heap element before freeing the heap + * entry. + * + * ---------------------------------------------------------------------------- + */ + +void +HeapKill(heap, func) + Heap *heap; /* The heap being killed */ + void (*func)(); /* Some function to free each id element */ +{ + int i; + + /* + * Free used locations except 0, since that location is reserved to pass + * back values. + */ + if (func) + for (i = 1; i <= heap->he_used; i++) + (*func) (heap, i); + freeMagic((char *) heap->he_list); + heap->he_list = NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * HeapFreeIdFunc -- + * + * Supplied function to HeapKill. Frees the referenced entry id if it + * is a string, otherwise do nothing. + * + * Results: + * None. + * + * Side effects: + * Memory is freed. + * + * ---------------------------------------------------------------------------- + */ + +void +HeapFreeIdFunc(heap, i) + Heap *heap; /* The heap in which the free is performed */ + int i; /* The index of the entry whose id gets freed */ +{ + if (heap->he_stringId) + freeMagic(heap->he_list[i].he_id); +} + +/* + * ---------------------------------------------------------------------------- + * + * HeapRemoveTop -- + * Delete the top element from the heap. + * + * Results: + * Pointer to the removed heap element, which is the same as the entry + * pointer passed to the function from outside, or NULL if no entries + * remain. + * + * Side effects: + * If the heap has been touched, restore the heap property before removing + * the top element. + * + * ---------------------------------------------------------------------------- + */ + +HeapEntry * +HeapRemoveTop(heap, entry) + Heap *heap; /* The heap from which the top is removed */ + HeapEntry *entry; /* Return the value in this struct */ +{ + int i; + + if (heap->he_used == 0) + return (HeapEntry *) NULL; + + if (!heap->he_built) + for (i = heap->he_used; i > 0; i--) + heapify(heap, i); + + heap->he_built = heap->he_used; + *entry = heap->he_list[1]; + heap->he_list[1] = heap->he_list[heap->he_used]; + heap->he_used--; + heapify(heap, 1); + return entry; +} + +/* + * ---------------------------------------------------------------------------- + * + * HeapLookAtTop -- + * + * Return pointer to top element, but don't remove it. + * + * Results: + * Pointer to the top heap element, or NULL if heap is empty. + * + * Side effects: + * If the heap has been touched, restore the heap property before + * returning the top element. + * + * ---------------------------------------------------------------------------- + */ + +HeapEntry * +HeapLookAtTop(heap) + Heap *heap; +{ + int i; + + if (heap->he_used == 0) + return (HeapEntry *) NULL; + + if (!heap->he_built) + for (i = heap->he_used; i > 0; i--) + heapify(heap, i); + + heap->he_built = heap->he_used; + return &heap->he_list[1]; +} + +/* + * ---------------------------------------------------------------------------- + * + * heapify -- + * + * Restore the heap property to the heap, where the root has changed. + * + * Results: + * None. + * + * Side effects: + * Things get shuffled around in the heap. Location 0 is trashed. + * + * ---------------------------------------------------------------------------- + */ + +void +heapify(heap, root) + Heap *heap; + int root; +{ + HeapEntry *list = heap->he_list; + int x, r, used = heap->he_used; + int keyType = heap->he_keyType; + + if (heap->he_big) + { + /* Biggest one on the top of the heap */ + while (1) + { + if ((x = heapLeft(used, root)) == 0) break; + if (r = heapRight(used, root)) + KEY_LESS_COND(keyType, list, x, r, x = r); + + KEY_LE_COND(keyType, list, x, root, return); + *list = list[root]; + list[root] = list[x]; + list[x] = *list; + root = x; + } + } + else + { + /* Smallest one on the top of the heap */ + while (1) + { + if ((x = heapLeft(used, root)) == 0) break; + if (r = heapRight(used, root)) + KEY_GREATER_COND(keyType, list, x, r, x = r); + KEY_GE_COND(keyType, list, x, root, return); + *list = list[root]; + list[root] = list[x]; + list[x] = *list; + root = x; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * HeapAdd -- + * + * Add an item to the bottom of the heap. Restore the heap structure + * by propagating the item upwards. + * + * Results: + * None. + * + * Side effects: + * Things get shuffled around in the heap. + * Free the old block and allocate a larger block if necessary. + * + * Warning: + * Something awful may happen if the id value was declared a string in + * HeapInit and you provide something else. + * + * Note: + * Because throwing pointers to indeterminate types (int, float, etc.) + * into the second argument produces results with unititialized fields, + * use of HeapAdd() is now deprecated, in favor of the determinate-type + * versions HeapAddInt, etc. (see below). These routines also protect + * against writing any data type into a heap initialized as a different + * data type. + * + * ---------------------------------------------------------------------------- + */ + +void +HeapAdd(heap, pKey, id) + Heap *heap; + union heUnion *pKey; + char *id; +{ + HeapEntry *list = heap->he_list; + int i, cmp, keyType; + + keyType = heap->he_keyType; + if (heap->he_used == heap->he_size) + { + HeapEntry *new; + + /* Need to recopy to a larger area */ + new = (HeapEntry *) mallocMagic((unsigned) ((2 * heap->he_size + 2) + * sizeof (HeapEntry))); + bcopy((char *) list, (char *) new, + (heap->he_size + 2) * sizeof (HeapEntry)); + freeMagic((char *) heap->he_list); + heap->he_list = list = new; + heap->he_size *= 2; + } + + i = ++heap->he_used; + list[i].he_union = *pKey; + if (heap->he_stringId) list[i].he_id = StrDup((char **) NULL, id); + else list[i].he_id = id; + + if (heap->he_built) + { + if (heap->he_big) + { + /* Biggest on the top */ + while (1) + { + /* If odd then new entry is the right half of a pair */ + cmp = i; + if (i & 1) + KEY_LE_COND(keyType, list, i, i-1, cmp = i-1); + + /* Find parent. If 0 then at the root so quit */ + if ((i >>= 1) == 0) return; + KEY_LE_COND(keyType, list, cmp, i, return); + list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0]; + heapify(heap, cmp); + } + } + else + { + /* Smallest on top */ + while (1) + { + /* If odd then new entry is the right half of a pair */ + cmp = i; + if (i & 1) + KEY_GE_COND(keyType, list, i, i-1, cmp = i-1); + + /* Find parent. If 0 then at the root so quit */ + if ((i >>= 1) == 0) return; + KEY_GE_COND(keyType, list, cmp, i, return); + list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0]; + heapify(heap, cmp); + } + } + } +} + +/* + * ---------------------------------------------------------------------------- + * HeapAddInt, HeapAddDLong, HeapAddFloat, HeapAddDouble -- + * + * Type-determinate versions of HeapAdd(). Note that unlike HeapAdd(), + * the second argument is the value, not a pointer to the value. + * + * ---------------------------------------------------------------------------- + */ +void +HeapAddInt(heap, data, id) + Heap *heap; + int data; + char *id; +{ + union heUnion pKey; + + ASSERT(heap->he_keyType == HE_INT, + "Attempt to add type int to non-int heap."); + pKey.hu_int = data; + HeapAdd(heap, &pKey, id); +} + +void +HeapAddDLong(heap, data, id) + Heap *heap; + dlong data; + char *id; +{ + union heUnion pKey; + + ASSERT(heap->he_keyType == HE_DLONG, + "Attempt to add type double long to non-double long heap."); + pKey.hu_dlong = data; + HeapAdd(heap, &pKey, id); +} + +void +HeapAddFloat(heap, data, id) + Heap *heap; + float data; + char *id; +{ + union heUnion pKey; + + ASSERT(heap->he_keyType == HE_FLOAT, + "Attempt to add type float to non-float heap."); + pKey.hu_float = data; + HeapAdd(heap, &pKey, id); +} + +void +HeapAddDouble(heap, data, id) + Heap *heap; + double data; + char *id; +{ + union heUnion pKey; + + ASSERT(heap->he_keyType == HE_DOUBLE, + "Attempt to add type double to non-double heap."); + pKey.hu_double = data; + HeapAdd(heap, &pKey, id); +} + + +/* + * ---------------------------------------------------------------------------- + * + * HeapDump -- + * Dump the contents of the heap for debugging purposes. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +HeapDump(heap) + Heap *heap; +{ + int i; + + if (heap->he_big) printf("Heap with biggest on the top\n"); + else printf("Heap with smallest on the top\n"); + + for (i = 1; i <= heap->he_used; i++) + { + printf("[%d]: Key ", i); + switch (heap->he_keyType) + { + case HE_INT: printf("%d", heap->he_list[i].he_int); break; + case HE_FLOAT: printf("%f", heap->he_list[i].he_float); break; + case HE_DOUBLE: printf("%f", heap->he_list[i].he_double); break; + case HE_DLONG: printf("%"DLONG_PREFIX"d", heap->he_list[i].he_dlong); break; + } + if (heap->he_stringId == TRUE) + printf("//id %s; ", heap->he_list[i].he_id); + else + printf("//id %p; ", heap->he_list[i].he_id); + } + printf("\n"); +} diff --git a/utils/heap.h b/utils/heap.h new file mode 100644 index 00000000..268279e3 --- /dev/null +++ b/utils/heap.h @@ -0,0 +1,143 @@ +/* + * heap.h -- + * + * Routines to create and maintain heaps. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/utils/heap.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; + * + * This heap supports the creation and manipulation of heaps. Features are: + * - Ascending and descending heaps. + * - Heaps are managed as arrays. Left and right children are accessed + * via address computation. + * - Heap areas are automatically resized when full. + * - The heap is sorted just prior to the first removal from the heap. + * - After the first removal, additions to the heap are merged into + * existing heap one at a time. + * - A variety of types of key are supported: + * long + * dlong + * float + * double + * + * #include "heap.h" + * #include + * main() + * { + * Heap * h; + * HeapEntry * e; + * int key; + * + * HeapInit(&h, 1024, 0, FALSE); + * HeapAdd(&h, 0, 0); + * HeapDump(&h); + * e=HeapRemoveTop(&h); + * HeapDump(&h); + * while(1) + * { + * fprintf(stderr, "Key: "); + * scanf("%d", &key); + * if(key==0) break; + * HeapAdd(&h, key, 0); + * HeapDump(&h); + * } + * while((e=HeapRemoveTop(&h))!=(HeapEntry *) NULL) + * { + * printf("Got heap key %d\n", e->he_key); + * HeapDump(&h); + * } + * HeapKill(&h, NULL); + * } + */ + + +#ifndef _HEAP_H +#define _HEAP_H + +#include "utils/geometry.h" + +/* DATA STRUCTURES */ + +/* + * A heap entry has some key value on which the entry is sorted, and some + * identifying data associated with the key. + */ +typedef struct +{ + char *he_id; /* One word value to identify the entry */ + + /* + * Key value. + * The element of the following union that is active depends on the + * way the Heap was initialized in the call to HeapInit() or + * HeapInitType(). + */ + union heUnion + { + int hu_int; + dlong hu_dlong; + float hu_float; + double hu_double; + } he_union; +} HeapEntry; + +#define he_int he_union.hu_int +#define he_dlong he_union.hu_dlong +#define he_float he_union.hu_float +#define he_double he_union.hu_double + +#define HESIZE(n) (sizeof (char *) + (n)) + +/* These define the kind of key used in the heap */ +#define HE_INT 1 +#define HE_DLONG 2 +#define HE_FLOAT 3 +#define HE_DOUBLE 4 + +/* A heap is an array with size set to some power of 2. Links are implicit: + * the left child of a node n is 2n, and the right child is 2n+1. 'build' + * keeps track of the last child participating in a rebuild operation. If + * entries have been added since the last rebuild, then process those children. + * The he_stringId flag enables automatically copies character string id's + * during calls to HeapAdd. If the id is actually a pointer to a struct, you + * must pass a pointer to a copy and set he_stringId to FALSE. + */ +typedef struct +{ + HeapEntry *he_list; /* Pointer to array of entries */ + int he_size; /* Size of the array of entries */ + int he_used; /* Number of locations used */ + int he_built; /* Size when heap was last built*/ + int he_stringId; /* TRUE=>HeapEntry id is string */ + int he_big; /* TRUE if largest at the root */ + int he_keyType; /* See type of Heap above */ +} Heap; + +/* PROCEDURES */ +extern void HeapInit(Heap *, int, int, int); +extern void HeapInitType(Heap *, int, int, int, int); +extern void HeapKill(Heap *, void (*)()); +extern void HeapFreeIdFunc(Heap *, int); +extern HeapEntry *HeapRemoveTop(Heap *, HeapEntry *); +extern HeapEntry *HeapLookAtTop(Heap *); +extern void HeapAdd(Heap *, union heUnion *, char *); +extern void HeapAddInt(Heap *, int, char *); +extern void HeapAddDLong(Heap *, dlong, char *); +extern void HeapAddFloat(Heap *, float, char *); +extern void HeapAddDouble(Heap *, double, char *); +extern void HeapDump(Heap *); + +#define HEAP_EMPTY(h) ((h)->he_used == 0) + +#endif /* _HEAP_H */ diff --git a/utils/list.c b/utils/list.c new file mode 100644 index 00000000..9f10d0fa --- /dev/null +++ b/utils/list.c @@ -0,0 +1,182 @@ +/* list.c - + * + * Routines to create and manipulate lisp style lists. + * A separate structure is used to link list elements together. + * Thus list elements do not require pointers and can be anything. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/list.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/utils.h" +#include "utils/malloc.h" +#include "utils/list.h" + + +/* ---------------------------------------------------------------------------- + * ListPop -- + * Returns top data item on list, deallocates top list element, and + * points list pointer to tail of list. + * + * Results: + * First data item on list. + * + * Side effects: + * Deallocates head of list, and changes pointer to tail of list. + * ---------------------------------------------------------------------------- + */ + +ClientData +ListPop(listPP) + List ** listPP; /* Pointer to pointer to list to pop */ +{ + List *head = *listPP; + ClientData result = LIST_FIRST(head); + + (*listPP) = LIST_TAIL(head); + freeMagic((char *) head); + + return result; +} + + +/* ---------------------------------------------------------------------------- + * ListContainsP -- + * Check if list contains given element. + * + * Results: + * TRUE if element in list. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +bool +ListContainsP(element,list) + ClientData element; /* element to check for */ + List *list; /* List to search */ +{ + for(;list!=NULL && LIST_FIRST(list)!=element; list=LIST_TAIL(list)) + ; /* Null body */ + + return list!=NULL; +} + +/* ---------------------------------------------------------------------------- + * ListDealloc -- + * Deallocate list strucs in list. + * + * Results: + * None. + * + * Side effects: + * Storage reclaimed. + * + * NOTE: Remember to set pointers to lists to null after deallocating + * the list (if pointers are to be used again)! + * ---------------------------------------------------------------------------- + */ + +void +ListDealloc(list) + List *list; /* List to free */ +{ + for(;list!=NULL; list=LIST_TAIL(list)) + freeMagic((char *) list); + + return; +} + + +/* ---------------------------------------------------------------------------- + * ListDeallocC -- + * Deallocate list strucs in list AND CONTENTS of list. + * + * Results: + * None. + * + * Side effects: + * Storage reclaimed. + * + * NOTE: Remember to set pointers to lists to null after deallocating + * the list (if pointers are to be used again)! + * ---------------------------------------------------------------------------- + */ + +void +ListDeallocC(list) + List *list; /* List to free */ +{ + for(;list!=NULL; list=LIST_TAIL(list)) + { + freeMagic((char *) LIST_FIRST(list)); + freeMagic((char *) list); + } + + return; +} + +/* ---------------------------------------------------------------------------- + * ListLength -- + * Count number of elements in list. + * + * Results: + * Returns number of elements in list + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +int +ListLength(list) + List *list; /* List to search */ +{ + int count = 0; + + for(;list!=NULL; list=LIST_TAIL(list)) + count++; + + return count; +} + +/* ---------------------------------------------------------------------------- + * ListReverse -- + * Make reversed copy of list. + * + * Results: + * Pointer to reverse copy of list. + * + * Side effects: + * Allocates and builds new list. + * ---------------------------------------------------------------------------- + */ + +List * +ListReverse(list) + List *list; /* List to search */ +{ + List *revList = NULL; + + for(; list!=NULL; list=LIST_TAIL(list)) + LIST_ADD(LIST_FIRST(list),revList); + + return revList; +} diff --git a/utils/list.h b/utils/list.h new file mode 100644 index 00000000..8e124a08 --- /dev/null +++ b/utils/list.h @@ -0,0 +1,74 @@ +/* + * list.h -- + * Structure and macros for mantaining and manipulating linked lists + * of arbitrary things. + * These lists are lisp like, i.e. list pointers are in separate strucutures + * rather than in the strucs being linked. + * (Equivalent to lisp lists.) + * + * Global definitions for all MAGIC modules + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * Needs to include and + * + * rcsid $Header: /usr/cvsroot/magic-8.0/utils/list.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _LIST_H +#define _LIST_H + +#include "utils/magic.h" + +/* --------------------- Lists (Lisp like) ---------------------------- */ + +/* structure to make lists of anything - used to link together other strucs + * "externally", i.e. with out useing pointers inside the strucs. + */ +typedef struct +list +{ + ClientData list_first; + struct list *list_tail; +} List; + +/* -------------------- Functions (exported by list.c) ---------------- */ +extern ClientData ListPop(); /* usage ListPop(&&List) */ +extern bool ListContainsP(); /* usage: ListContainsP(ClientData,&List) */ +extern int ListLength(); /* usage: ListLength(&List) */ +extern void ListDealloc(); /* usage: ListDealloc(&List) */ +extern void ListDeallocC(); /* usage: ListDeallocC(&List) */ +extern List *ListReverse(); /* usage: ListReverse(&List) */ + +/* --------------------- Macros for Lists ----------------------------- */ +#define LIST_FIRST(l) ((l)->list_first) +#define LIST_TAIL(l) ((l)->list_tail) +#define LIST_ADD(i,l) \ + if(TRUE) \ + { \ + List * LIST_l; \ + LIST_l = (List *) mallocMagic((unsigned) (sizeof(List))); \ + LIST_l->list_first = (ClientData) (i); \ + LIST_l->list_tail = (l); \ + (l) = LIST_l; \ + } else +#define LIST_COPY(l,lnew) \ + if(TRUE) \ + { \ + List * LIST_intermediate; \ + LIST_intermediate = ListReverse(l); \ + (lnew) = ListReverse(LIST_intermediate); \ + ListDealloc(LIST_intermediate); \ + } else + +#endif /* _LIST_H */ diff --git a/utils/lookup.c b/utils/lookup.c new file mode 100644 index 00000000..f0e03d6b --- /dev/null +++ b/utils/lookup.c @@ -0,0 +1,224 @@ +/* lookup.c -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains a single routine used to look up a string in + * a table, allowing unique abbreviations. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/lookup.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/utils.h" + + +/*--------------------------------------------------------- + * Lookup -- + * Searches a table of strings to find one that matches a given + * string. It's useful mostly for command lookup. + * + * Only the portion of a string in the table up to the first + * blank character is considered significant for matching. + * + * Results: + * If str is the same as + * or an unambiguous abbreviation for one of the entries + * in table, then the index of the matching entry is returned. + * If str is not the same as any entry in the table, but + * an abbreviation for more than one entry, + * then -1 is returned. If str doesn't match any entry, then + * -2 is returned. Case differences are ignored. + * + * NOTE: + * Table entries need no longer be in alphabetical order + * and they need not be lower case. The irouter command parsing + * depends on these features. + * + * Side Effects: + * None. + *--------------------------------------------------------- + */ + +int +Lookup(str, table) +char *str; /* Pointer to a string to be looked up */ +char *(table[]); /* Pointer to an array of string pointers + * which are the valid commands. + * The end of + * the table is indicated by a NULL string. + */ +{ + int match = -2; /* result, initialized to -2 = no match */ + int pos; + int ststart = 0; + +#ifdef MAGIC_WRAPPER + static char *namespace = "::magic::"; + + /* Skip over prefix of qualified namespaces "::magic::" and "magic::" */ + for (pos = 0; pos < 9; pos++) + if ((str[pos] != namespace[pos]) || (str[pos] == '\0')) break; + if (pos == 9) ststart = 9; + else + { + for (pos = 0; pos < 7; pos++) + if ((str[pos] != namespace[pos + 2]) || (str[pos] == '\0')) break; + if (pos == 7) ststart = 7; + } +#endif + + /* search for match */ + for(pos=0; table[pos]!=NULL; pos++) + { + char *tabc = table[pos]; + char *strc = &(str[ststart]); + while(*strc!='\0' && *tabc!=' ' && + ((*tabc==*strc) || + (isupper(*tabc) && islower(*strc) && (tolower(*tabc)== *strc))|| + (islower(*tabc) && isupper(*strc) && (toupper(*tabc)== *strc)) )) + { + strc++; + tabc++; + } + + + if(*strc=='\0') + { + /* entry matches */ + if(*tabc==' ' || *tabc=='\0') + { + /* exact match - record it and terminate search */ + match = pos; + break; + } + else if (match == -2) + { + /* inexact match and no previous match - record this one + * and continue search */ + match = pos; + } + else + { + /* previous match, so string is ambiguous unless exact + * match exists. Mark ambiguous for now, and continue + * search. + */ + match = -1; + } + } + } + return(match); +} + + +/*--------------------------------------------------------- + * + * LookupStruct -- + * + * Searches a table of structures, each of which contains a string + * pointer as its first element, in a manner similar to that of Lookup() + * above. Each structure in the table has the following form: + * + * struct + * { + * char *string; + * ... rest of structure + * }; + * + * The 'string' field of each structure is matched against the + * argument 'str'. The size of a single structure is given by + * the argument 'size'. + * + * Results: + * If str is the same as + * or an unambiguous abbreviation for one of the entries + * in table, then the index of the matching entry is returned. + * If str is not the same as any entry in the table, but + * an abbreviation for more than one entry, + * then -1 is returned. If str doesn't match any entry, then + * -2 is returned. Case differences are ignored. + * + * NOTE: Table entries need no longer be in alphabetical order + * and they need not be lower case. The irouter command parsing + * depends on these features. + * + * Side Effects: + * None. + * + *--------------------------------------------------------- + */ + +int +LookupStruct(str, table, size) + char str[]; /* Pointer to a string to be looked up */ + char **table; /* Pointer to an array of structs containing string + * pointers to valid commands. + * The last table entry should have a NULL + * string pointer. + */ + int size; /* The size, in bytes, of each table entry */ +{ + int match = -2; /* result, initialized to -2 = no match */ + char **entry; + int pos; + char *tabc , *strc ; + + /* search for match */ + for (entry = table, pos = 0; *entry != NULL; ) + { + tabc = *entry; + strc = str; + while(*strc!='\0' && *tabc!=' ' && + ((*tabc== *strc) || + (isupper(*tabc) && islower(*strc) && (tolower(*tabc)== *strc))|| + (islower(*tabc) && isupper(*strc) && (toupper(*tabc)== *strc)) )) + { + strc++; + tabc++; + } + + if(*strc=='\0') + { + /* entry matches */ + if(*tabc==' ' || *tabc=='\0') + { + /* exact match - record it and terminate search */ + match = pos; + break; + } + else if (match == -2) + { + /* in exact match and no previous match - record this one + * and continue search */ + match = pos; + } + else + { + /* previous match, so string is ambiguous unless exact + * match exists. Mark ambiguous for now, and continue + * search. + */ + match = -1; + } + } + pos++; + entry = (char **)((long)entry + (long) size); + } + return(match); +} + diff --git a/utils/lookupany.c b/utils/lookupany.c new file mode 100644 index 00000000..e9bad6c1 --- /dev/null +++ b/utils/lookupany.c @@ -0,0 +1,59 @@ +/* + * lookupany.c -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * Full rights reserved. + * + * This file contains a single routine used to find a string in a + * table which contains the supplied character. + */ + +#include + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/lookupany.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + + +/* + * ---------------------------------------------------------------------------- + * LookupAny -- + * + * Look up a single character in a table of pointers to strings. The last + * entry in the string table must be a NULL pointer. + * The index of the first string in the table containing the indicated + * character is returned. + * + * Results: + * Index of the name supplied in the table, or -1 if the name + * is not found. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +LookupAny(c, table) + char c; + char **table; +{ + char **tp; + + for (tp = table; *tp; tp++) + if (strchr(*tp, c) != (char *) 0) + return (tp - table); + + return (-1); +} diff --git a/utils/lookupfull.c b/utils/lookupfull.c new file mode 100644 index 00000000..3156d8ad --- /dev/null +++ b/utils/lookupfull.c @@ -0,0 +1,128 @@ +/* + * lookupfull.c -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * Full rights reserved. + * + * This file contains a single routine used to look up a string in + * a table with no abbreviations allowed. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/lookupfull.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" + + +/* + * ---------------------------------------------------------------------------- + * LookupFull -- + * + * Look up a string in a table of pointers to strings. The last + * entry in the string table must be a NULL pointer. + * This is much simpler than Lookup() in that it does not + * allow abbreviations. It does, however, ignore case. + * + * Results: + * Index of the name supplied in the table, or -1 if the name + * is not found. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +LookupFull(name, table) + char *name; + char **table; +{ + char **tp; + + for (tp = table; *tp; tp++) + { + if (strcmp(name, *tp) == 0) + return (tp - table); + else + { + char *sptr, *tptr; + for (sptr = name, tptr = *tp; ((*sptr != '\0') && (*tptr != '\0')); + sptr++, tptr++) + if (toupper(*sptr) != toupper(*tptr)) + break; + if ((*sptr == '\0') && (*tptr == '\0')) + return (tp - table); + } + } + + return (-1); +} + +/*--------------------------------------------------------- + * + * LookupStructFull -- + * + * Searches a table of structures, each of which contains a string + * pointer as its first element, in a manner similar to that of Lookup() + * above. Each structure in the table has the following form: + * + * struct + * { + * char *string; + * ... rest of structure + * }; + * + * The 'string' field of each structure is matched against the + * argument 'str'. The size of a single structure is given by + * the argument 'size'. + * + * This is much simpler than LookupStruct() in that it does not + * allow abbreviations. + * + * Results: + * Index of the name supplied in the table, or -1 if the name + * is not found. + * + * Side Effects: + * None. + * + *--------------------------------------------------------- + */ + +int +LookupStructFull(str, table, size) + char str[]; /* Pointer to a string to be looked up */ + char **table; /* Pointer to an array of structs containing string + * pointers to valid commands. + * The last table entry should have a NULL + * string pointer. + */ + int size; /* The size, in bytes, of each table entry */ +{ + char **entry; + int pos; + + for(entry=table, pos=0; *entry!=NULL; pos++) { + if( strcmp(str, *entry) == 0 ) { + return pos; + } + entry = (char **)((long)entry + (long)size); + } + + return -1; +} diff --git a/utils/macros.c b/utils/macros.c new file mode 100644 index 00000000..b8a1678d --- /dev/null +++ b/utils/macros.c @@ -0,0 +1,657 @@ +/* + * macros.c -- + * + * Defines and retrieves macros + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/macros.c,v 1.2 2010/06/24 12:37:58 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#ifdef XLIB +#include +#include +#include +#endif + +#include "utils/magic.h" +#include "utils/main.h" +#include "utils/utils.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "utils/macros.h" +#include "windows/windows.h" + +/* Define the macro client table */ + +HashTable MacroClients; + +/* + *--------------------------------------------------------- + * MacroInit --- + * + * Initialize the macro hash table + * + * Results: + * None. + * + * Side Effects: + * Memory allocated for the hash table MacroClients. + * + *--------------------------------------------------------- + */ + +void +MacroInit() +{ + HashInit(&MacroClients, 4, HT_WORDKEYS); +} + +/* + *--------------------------------------------------------- + * MacroDefine --- + * + * This procedure defines a macro. + * + * Results: + * None. + * + * Side Effects: + * The string passed is copied and considered to be the + * macro definition for the character. + *--------------------------------------------------------- + */ + +void +MacroDefine(client, xc, str, help, imacro) + WindClient client; /* window client type */ + int xc; /* full (X11) keycode of macro with modifiers */ + char *str; /* ...and the string to be attached to it */ + char *help; /* ...and/or the help text for the macro */ + bool imacro; /* is this an interactive macro? */ +{ + HashEntry *h; + HashTable *clienttable, newTable; + macrodef *oldMacro, *newMacro; + + /* If a macro exists, delete the old string and redefine it */ + h = HashFind(&MacroClients, (char *)client); + clienttable = (HashTable *)HashGetValue(h); + if (clienttable == NULL) + { + clienttable = (HashTable *)mallocMagic(sizeof(HashTable)); + HashInit(clienttable, 32, HT_WORDKEYS); + HashSetValue(h, clienttable); + } + h = HashFind(clienttable, (char *)((ClientData)xc)); + oldMacro = (macrodef *)HashGetValue(h); + if (oldMacro != NULL) + { + if (oldMacro->macrotext != NULL) + freeMagic(oldMacro->macrotext); + if (oldMacro->helptext != NULL) { + freeMagic(oldMacro->helptext); + oldMacro->helptext = NULL; + } + newMacro = oldMacro; + } + else + newMacro = (macrodef *)mallocMagic(sizeof(macrodef)); + + HashSetValue(h, newMacro); + newMacro->interactive = imacro; + newMacro->macrotext = StrDup((char **)NULL, str); + if (help != NULL) + newMacro->helptext = StrDup((char **)NULL, help); + else + newMacro->helptext = NULL; +} + +/* + *--------------------------------------------------------- + * MacroDefineHelp --- + * + * This procedure defines the help text for a macro. + * A macro must already exist for the specified key. + * + * Results: + * None. + * + * Side Effects: + * The string passed is copied and considered to be the + * macro definition for the character. + *--------------------------------------------------------- + */ + +void +MacroDefineHelp(client, xc, help) + WindClient client; /* window client type */ + int xc; /* full (X11) keycode of macro with modifiers */ + char *help; /* ...and/or the help text for the macro */ +{ + HashEntry *h; + HashTable *clienttable; + macrodef *curMacro; + + /* If a macro exists, delete the old string and redefine it */ + h = HashFind(&MacroClients, (char *)client); + clienttable = (HashTable *)HashGetValue(h); + if (clienttable == NULL) return; + + h = HashFind(clienttable, (char *)((ClientData)xc)); + curMacro = (macrodef *)HashGetValue(h); + if (curMacro == NULL) return; + + if (curMacro->helptext != NULL) + freeMagic(curMacro->helptext); + + if (help == NULL) + curMacro->helptext = NULL; + else + curMacro->helptext = StrDup((char **)NULL, help); +} + +/*--------------------------------------------------------- + * MacroRetrieve: + * This procedure retrieves a macro. + * + * Results: + * A pointer to a new Malloc'ed string is returned. + * This structure should be freed when the caller is + * done with it. + * + * Side Effects: + * None. + *--------------------------------------------------------- + */ + +char * +MacroRetrieve(client, xc, iReturn) + WindClient client; /* window client type */ + int xc; /* the extended name of the macro */ + bool *iReturn; /* TRUE if macro is interactive */ +{ + HashEntry *h; + HashTable *clienttable; + macrodef *cMacro; + + /* If a macro exists, delete the old string and redefine it */ + h = HashLookOnly(&MacroClients, (char *)client); + if (h != NULL) + { + clienttable = (HashTable *)HashGetValue(h); + if (clienttable != NULL) + { + h = HashLookOnly(clienttable, (char *)((ClientData)xc)); + if (h != NULL) + { + cMacro = (macrodef *)HashGetValue(h); + if (cMacro != NULL) + { + if (iReturn != NULL) + *iReturn = cMacro->interactive; + return StrDup((char **)NULL, cMacro->macrotext); + } + } + } + } + if (iReturn != NULL) *iReturn = FALSE; + return (char *)NULL; +} + +/*--------------------------------------------------------- + * MacroRetrieveHelp: + * This procedure retrieves the help text for a macro. + * + * Results: + * A pointer to a new Malloc'ed string is returned. + * This structure should be freed when the caller is + * done with it. + * + * Side Effects: + * None. + *--------------------------------------------------------- + */ + +char * +MacroRetrieveHelp(client, xc) + WindClient client; /* window client type */ + int xc; /* the extended name of the macro */ +{ + HashEntry *h; + HashTable *clienttable; + macrodef *cMacro; + + /* If a macro exists, delete the old string and redefine it */ + h = HashLookOnly(&MacroClients, (char *)client); + if (h != NULL) + { + clienttable = (HashTable *)HashGetValue(h); + if (clienttable != NULL) + { + h = HashLookOnly(clienttable, (char *)((ClientData)xc)); + if (h != NULL) + { + cMacro = (macrodef *)HashGetValue(h); + if (cMacro != NULL) + if (cMacro->helptext != NULL) + return StrDup((char **)NULL, cMacro->helptext); + } + } + } + return (char *)NULL; +} + +/*--------------------------------------------------------- + * MacroSubsitute: + * Make a substitution of one string for another + * in a macro string. This is really just a string + * manipulation; it doesn't have anything specifically + * to do with macros. + * + * Results: + * A new string pointer to the macro contents. + * + * Side Effects: + * None. + *--------------------------------------------------------- + */ + +char * +MacroSubstitute(macrostr, searchstr, replacestr) + char *macrostr; + char *searchstr; + char *replacestr; +{ + char *found, *last, *new; + int expand, length, oldlength, srchsize; + + if (macrostr == (char *)NULL) return NULL; + + oldlength = strlen(macrostr); + srchsize = strlen(searchstr); + expand = strlen(replacestr) - srchsize; + last = macrostr; + length = oldlength; + while ((found = strstr(last, searchstr)) != NULL) + { + length += expand; + last = found + srchsize; + } + if (length > oldlength) + { + new = (char *)mallocMagic(length + 1); + *new = '\0'; + last = macrostr; + while ((found = strstr(last, searchstr)) != NULL) + { + *found = '\0'; + strcat(new, last); + strcat(new, replacestr); + last = found + srchsize; + } + strcat(new, last); + freeMagic(macrostr); + return new; + } + else + return macrostr; +} + + +/*--------------------------------------------------------- + * MacroDelete: + * This procedure deletes a macro. + * + * Results: None. + * + * Side Effects: + * The string that defines a macro is deleted. This means + * that if anybody still has a pointer to that string + * they are in trouble. + *--------------------------------------------------------- + */ + +void +MacroDelete(client, xc) + WindClient client; /* window client type */ + int xc; /* the extended name of the macro */ +{ + HashEntry *h; + HashTable *clienttable; + macrodef *cMacro; + + h = HashLookOnly(&MacroClients, (char *)client); + if (h != NULL) + { + clienttable = (HashTable *)HashGetValue(h); + if (clienttable != NULL) + { + h = HashLookOnly(clienttable, (char *)((ClientData)xc)); + if (h != NULL) + { + cMacro = (macrodef *)HashGetValue(h); + if (cMacro != NULL) + { + if (cMacro->macrotext != NULL) + freeMagic(cMacro->macrotext); + if (cMacro->helptext != NULL) + freeMagic(cMacro->helptext); + HashSetValue(h, NULL); + freeMagic(cMacro); + } + } + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * MacroName -- + * Convert an extended keycode to a string. + * + * Results: + * The string. + * + * Side effects: + * The string is malloc'ed from memory, and must be free'd later. + * ---------------------------------------------------------------------------- + */ + +char * +MacroName(xc) + int xc; +{ + char *vis; + static char hex[17] = "0123456789ABCDEF"; + +#ifdef XLIB + char *str; + extern Display *grXdpy; + KeySym ks = xc & 0xffff; + int kmod = xc >> 16; + + str = NULL; + if (grXdpy != NULL) { + ks = xc & 0xffff; + if (ks != NoSymbol) str = XKeysymToString(ks); + } + if (str != NULL) + { + vis = (char *) mallocMagic( sizeof(char) * (strlen(str) + 32) ); + vis[0] = '\0'; + if (kmod & Mod1Mask) strcat(vis, "Meta_"); + if (kmod & ControlMask) strcat(vis, "Control_"); + if (kmod & LockMask) strcat(vis, "Capslock_"); + if (kmod & ShiftMask) strcat(vis, "Shift_"); + strcat(vis, "XK_"); + strcat(vis, str); + return (vis); + } +#endif + + vis = (char *) mallocMagic( sizeof(char) * 6 ); + if (xc < (int)' ') + { + vis[0] = '^'; + vis[1] = (char)xc + '@'; + vis[2] = '\0'; + } + else if (xc == 0x7F) + { + vis[0] = '<'; + vis[1] = 'd'; + vis[2] = 'e'; + vis[3] = 'l'; + vis[4] = '>'; + vis[5] = '\0'; + } + else if (xc < 0x80) + { + vis[0] = (char)xc; + vis[1] = '\0'; + } + else + { + vis = (char *) mallocMagic( sizeof(char) * 8 ); + vis[0] = '0'; + vis[1] = 'x'; +#ifdef XLIB + vis[2] = hex[ (kmod & 0xf)]; +#else + vis[2] = '0'; +#endif + vis[3] = hex[ (xc & 0x0f000) >> 12]; + vis[4] = hex[ (xc & 0x00f00) >> 8]; + vis[5] = hex[ (xc & 0x000f0) >> 4]; + vis[6] = hex[ (xc & 0x0000f) ]; + vis[7] = '\0'; + } + return(vis); +} + + +/* + * ---------------------------------------------------------------------------- + * MacroKey: + * Convert a string to an extended keycode. + * + * Results: + * An extended macro name. + * + * Side effects: + * If the display being used is not X11, a warning is printed the + * first time this function is called. + * ---------------------------------------------------------------------------- + */ + +int +MacroKey(str, verbose) + char *str; + int *verbose; +{ + static int warn = 1; + +#ifdef XLIB + int kc; + char *vis; + extern Display *grXdpy; + KeySym ks; + int kmod = 0; + + *verbose = 1; + if (grXdpy != NULL) + { + vis = str; + while( (*vis) != '\0' ) + { + if (!strncmp(vis, "Meta_", 5)) + { + kmod |= Mod1Mask; + vis += 5; + } + else if (!strncmp(vis, "Alt_", 4)) + { + kmod |= Mod1Mask; + vis += 4; + } + else if (!strncmp(vis, "Control_", 8)) + { + kmod |= ControlMask; + vis += 8; + } + else if (((*vis) == '^') && (*(vis + 1) != '\0')) + { + kmod |= ControlMask; + vis++; + } + else if (!strncmp(vis, "Capslock_", 9)) + { + kmod |= LockMask; + vis += 9; + } + else if (!strncmp(vis, "Shift_", 6)) + { + kmod |= ShiftMask; + vis += 6; + } + else if (*vis == '\'') + { + // If single quotes are used to protect the integrity + // of the macro character, strip them now. + + char *aptr = strrchr(vis, '\''); + if (aptr != NULL && aptr != vis) + { + vis++; + *aptr = '\0'; + } + else break; // Don't hang on an unmatched quote + } + else break; + } + if (!strncmp(vis, "XK_", 3)) vis += 3; + + /* We're converting all ASCII back into X Keycodes */ + /* The original macro (.magicrc) file format allows */ + /* embedded control characters, so we have to handle */ + /* those. For regular ASCII characters, the keysym = */ + /* the ASCII value. */ + + if ((*(vis + 1)) == '\0') + { + /* single ASCII character handling */ + + char tc = *vis; + + /* Revert Control and Shift characters to ASCII */ + /* unless other modifiers are present. Always make */ + /* characters with Control and Shift uppercase. */ + + if (kmod & (ControlMask | ShiftMask)) + { + tc = toupper(tc); + if (kmod & ShiftMask) + kc = (int)tc; + else if (kmod & ControlMask) + kc = (int)(tc - 'A' + 1); + + if (!(kmod & (Mod1Mask | LockMask))) + if (!(kmod & ShiftMask) || !(kmod & ControlMask)) + kmod = 0; + } + else + kc = (int)tc; + } + else if (!strncmp(vis, "", 5)) + /* Because, weirdly, there is no keysymdef for the "Delete" key */ + kc = (int)0x7f; + else + { + /* X11 keysym name handling */ + + /* If macro "Button" is used, then prepend */ + /* "Pointer" to match the keysymdef. */ + /* (Added by NP 10/20/04) */ + + char *pointerStr = NULL; + if (!strncmp(vis, "Button", 6)) + { + pointerStr = (char *)mallocMagic(9 + strlen(str)); + strcpy(pointerStr, "Pointer_"); + strcat(pointerStr, vis); + vis = pointerStr; + } + ks = XStringToKeysym(vis); + kc = (ks != NoSymbol) ? ks & 0xffff : 0; + if (pointerStr != NULL) freeMagic(pointerStr); + } + return (kc | (kmod << 16)); + } +#endif + + *verbose = 1; + if (strlen(str) == 1) + { + return (int)str[0]; + } + else if (strlen(str) == 2 && *str == '^') + { + return (int)str[1] - 'A' + 1; + } + if (warn) + { + if (strcasecmp(MainDisplayType, "NULL") || (TxTkConsole == TRUE)) + TxPrintf("Extended macros are unavailable" + " with graphics type \"%s\".\n", MainDisplayType); + } + warn = 0; + *verbose = 0; + return(0); +} + + +/* + * ---------------------------------------------------------------------------- + * CommandLineTranslate + * Convert X11 definitions to readline controls + * + * Results: + * A converted character (integer) + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +int +TranslateChar(key) + int key; +{ + int rval = key; + +#ifdef XLIB + switch (key) + { + case XK_Left: + rval = (int)'\002'; /* Ctrl-B */ + break; + case XK_Right: + rval = (int)'\006'; /* Ctrl-F */ + break; + case XK_Up: + rval = (int)'\020'; /* Ctrl-P */ + break; + case XK_Down: + rval = (int)'\016'; /* Ctrl-N */ + break; + case XK_BackSpace: + case XK_Delete: + rval = (int)'\010'; /* Ctrl-H */ + break; + case XK_Home: + rval = (int)'\001'; /* Ctrl-A */ + break; + case XK_End: + rval = (int)'\005'; /* Ctrl-E */ + break; + } +#endif + return rval; +} diff --git a/utils/macros.h b/utils/macros.h new file mode 100644 index 00000000..2c9dfda1 --- /dev/null +++ b/utils/macros.h @@ -0,0 +1,54 @@ +/* + * macros.h -- + * + * Routines to define and retrieve macros + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/utils/macros.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + */ + +#ifndef _MACROS_H +#define _MACROS_H + +#include "utils/magic.h" +#include "utils/hash.h" + +/* + * Macro data structure + */ + +typedef struct { + char *macrotext; + bool interactive; + char *helptext; +} macrodef; + +/* macro directory */ +extern HashTable MacroClients; + +/* procedures */ +extern void MacroInit(); +extern void MacroDefine(); +extern void MacroDefineHelp(); +extern void MacroDefineInt(); +extern char *MacroRetrieve(); /* returns a malloc'ed string */ +extern char *MacroRetrieveHelp(); /* returns a malloc'ed string */ +extern char *MacroSubstitute(); /* returns a malloc'ed string */ +extern void MacroDelete(); +extern char *MacroName(); /* returns a malloc'ed string */ +extern int MacroKey(); +extern int MacroCode(); + +#endif /* _MACROS_H */ diff --git a/utils/magic.h b/utils/magic.h new file mode 100644 index 00000000..394d188c --- /dev/null +++ b/utils/magic.h @@ -0,0 +1,212 @@ +/* + * magic.h -- + * + * Global definitions for all MAGIC modules + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid="$Header" + */ + +#ifndef _MAGIC_H +#define _MAGIC_H + +#include +#include +#include + +/* ------------------- Universal pointer typecast --------------------- */ + +/* Set default value for backwards compatibility with non-autoconf make */ +#ifndef SIZEOF_VOID_P +#define SIZEOF_VOID_P SIZEOF_UNSIGNED_INT +#endif + +#if SIZEOF_VOID_P == SIZEOF_UNSIGNED_INT +typedef unsigned int pointertype; +typedef signed int spointertype; +#elif SIZEOF_VOID_P == SIZEOF_UNSIGNED_LONG +typedef unsigned long pointertype; +typedef signed long spointertype; +#else +ERROR: Cannot compile without knowing the size of a pointer. See utils/magic.h +#endif + +typedef int64_t dlong; +#define DLONG_MAX INT64_MAX +#define DLONG_MIN INT64_MIN +#define DLONG_PREFIX "ll" + +/* --------------------- Universal pointer type ----------------------- */ + +#ifndef _CLIENTDATA +typedef pointertype ClientData; +#endif + +/* --------------------------- Booleans ------------------------------- */ + +typedef unsigned char bool; + +#ifndef TRUE +#define TRUE ((bool)1) +#endif +#ifndef FALSE +#define FALSE ((bool)0) +#endif + +/* ----------------------- Simple functions --------------------------- */ + +#ifndef MAX +#define MAX(a,b) (((a) < (b)) ? (b) : (a)) +#endif + +#ifndef MIN +#define MIN(a,b) (((a) > (b)) ? (b) : (a)) +#endif + +#define ABS(x) (((x) >= 0) ? (x) : -(x)) +#define ABSDIFF(x,y) (((x) < (y)) ? (y) - (x) : (x) - (y)) +#define ODD(i) (i&1) +#define EVEN(i) (!(i&1)) + +/*----------------------------------------------------------------------*/ +/* Round to nearest integer---use c99 functions if available from the */ +/* math library (checked by "configure"), otherwise use the macro */ +/* definitions below. */ +/*----------------------------------------------------------------------*/ + +#ifndef HAVE_ROUND +#define round(a) (((a) < 0) ? (int)((a) - 0.5) : (int)((a) + 0.5)) +#endif + +#ifndef HAVE_ROUNDF +#define roundf(x) ((float)((int)((float)(x) + ((x < 0) ? -0.5 : 0.5)))) +#endif + +/* -------------------------- Search paths ---------------------------- */ + +extern char *CellLibPath; /* Path for finding cells. */ +extern char *SysLibPath; /* Path for finding system + * files like color maps, styles, etc. + */ + +/* --------------------- Debugging and assertions --------------------- */ + +/* To enable assertions, undefine NDEBUG in file defs.mak */ + +#include +#define ASSERT(p, where) assert(p) /* "where" is ignored */ + +/* ------------------------ Malloc/free ------------------------------- */ + +/* + * Magic has its own versions of malloc() and free(), called mallocMagic() + * and freeMagic(). Magic procedures should ONLY use these procedures. + * Just for the sake of robustness, though, we define malloc and free + * here to error strings. + */ +#define malloc You_should_use_the_Magic_procedure_mallocMagic_instead +#define free You_should_use_the_Magic_procedure_freeMagic_instead +#define calloc You_should_use_the_Magic_procedure_callocMagic_instead + +/* ---------- Flag for global variables (for readability) ------------- */ + +#define global /* Nothing */ + +/* ------------ Globally-used strings. -------------------------------- */ + +extern char *MagicVersion; +extern char *MagicRevision; +extern char *MagicCompileTime; +extern char AbortMessage[]; + +/* ---------------- Start of Machine Configuration Section ----------------- */ + + /* ------- Configuration: Handle Missing Routines/Definitions ------- */ + +/* System V is missing some BSDisms. */ +#ifdef SYSV +# ifndef bcopy +# define bcopy(a, b, c) memcpy(b, a, c) +# endif +# ifndef bzero +# define bzero(a, b) memset(a, 0, b) +# endif +# ifndef bcmp +# define bcmp(a, b, c) memcmp(b, a, c) +# endif +#endif + +/* Some machines need vfprintf(). (A temporary MIPS bug?) (see txOutput.c) */ +#if (defined(MIPSEB) && defined(SYSTYPE_BSD43)) || ibm032 +# define NEED_VFPRINTF +#endif + +/* Some machines expect signal handlers to return an "int". But most machines + * expect them to return a "void". If your machine expects an "int", put in + * an "ifdef" below. + */ + +#if (defined(MIPSEB) && defined(SYSTYPE_BSD43)) || ibm032 +# define SIG_RETURNS_INT +#endif + +/* + * Linux + */ +#ifdef linux +#define sigvec sigaction +#define sv_handler sa_handler +#endif + +/* + * Irix + */ +#ifdef sgi +#define vfork fork +#endif + + +/* + * Select system call + * + * Note: Errors here may be caused by not including + * before "magic.h" (deprecated; more modern usage is + */ +#include +#ifndef FD_SET +#define fd_set int +#define FD_SET(n, p) ((*(p)) |= (1 << (n))) +#define FD_CLR(n, p) ((*(p)) &= ~(1 << (n))) +#define FD_ISSET(n, p) ((*(p)) & (1 << (n))) +#define FD_ZERO(p) (*(p) = 0) +#endif + +/* + * Handling of VA_COPY. These variables are set by the configuration + * script. Some systems define va_copy, some define __va_copy, and + * some don't define it at all. It is assumed that systems which do + * not define it at all allow arguments to be copied with "=". + */ + +#ifndef HAVE_VA_COPY + #ifdef HAVE___VA_COPY + #define va_copy(a, b) __va_copy(a, b) + #else + #define va_copy(a, b) a = b + #endif +#endif + +/* ------------------ End of Machine Configuration Section ----------------- */ + +#endif /* _MAGIC_H */ diff --git a/utils/magsgtty.h b/utils/magsgtty.h new file mode 100644 index 00000000..839ce532 --- /dev/null +++ b/utils/magsgtty.h @@ -0,0 +1,34 @@ +/* + * magsgtty.h -- + * + * Magic's own sgtty.h file. For porting + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + */ + +#ifndef _MAGSGTTY_H +#define _MAGSGTTY_H + +#if !defined(SYSV) && !defined(CYGWIN) +# ifdef ALPHA +# undef MAX +# undef MIN +# endif +#include +#else +#include +#endif + +#endif /* _MAGSGTTY_H */ diff --git a/utils/main.c b/utils/main.c new file mode 100644 index 00000000..17ef3604 --- /dev/null +++ b/utils/main.c @@ -0,0 +1,1236 @@ +/* + * main.c -- + * + * The topmost module of the Magic VLSI tool. This module + * initializes the other modules and then calls the 'textio' + * module to read and execute commands. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/main.c,v 1.2 2008/02/07 17:33:19 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/main.h" +#include "utils/magic.h" +#include "utils/malloc.h" +#include "utils/magsgtty.h" +#include "utils/hash.h" +#include "utils/macros.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "textio/txcommands.h" +#include "tiles/tile.h" +#include "utils/tech.h" +#include "database/database.h" +#include "drc/drc.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "dbwind/dbwind.h" +#include "commands/commands.h" +#include "utils/signals.h" +#include "utils/utils.h" +#include "utils/runstats.h" +#include "cif/cif.h" +#ifdef ROUTE_MODULE +#include "router/router.h" +#endif +#ifdef LEF_MODULE +#include "lef/lef.h" +#endif +#include "extract/extract.h" +#include "utils/undo.h" +#include "netmenu/netmenu.h" +#include "plow/plow.h" +#include "utils/paths.h" +#include "wiring/wiring.h" +#ifdef PLOT_MODULE +#include "plot/plot.h" +#endif +#include "sim/sim.h" +#include "utils/list.h" +#ifdef ROUTE_MODULE +#include "mzrouter/mzrouter.h" +#endif +#include "lisp/lisp.h" +#ifdef THREE_D +#include "graphics/wind3d.h" +#endif + + +/* + * Global data structures + * + */ + +global char *Path = NULL; /* Search path */ +global char *CellLibPath = NULL; /* Used to find cells. */ +global char *SysLibPath = NULL; /* Used to find color maps, styles, */ + /* technologies, etc. */ + +/* + * Flag that tells if various options have been set on the command line + * (see utils.h for explanation of individual flags). + */ + +global short RuntimeFlags = MAIN_MAKE_WINDOW; + +/* + * See the file main.h for a description of the information kept + * pertaining to the edit cell. + */ + +global CellUse *EditCellUse = NULL; +global CellDef *EditRootDef = NULL; +global Transform EditToRootTransform; +global Transform RootToEditTransform; + + +/* + * data structures local to main.c + * + */ + +/* the filename specified on the command line */ +static char *MainFileName = NULL; + +/* RC file specified on the command line */ +static char *RCFileName = NULL; + +/* Definition of file types that magic can read */ +#define FN_MAGIC_DB 0 +#define FN_LEF_FILE 1 +#define FN_DEF_FILE 2 +#define FN_GDS_FILE 3 +#define FN_CIF_FILE 4 +#define FN_TCL_SCRIPT 5 + +/* List of filenames specified on the command line */ +typedef struct filename { + char *fn; + unsigned char fn_type; + struct filename *fn_prev; +} FileName; +FileName *CurrentName; + +/* tech name specified on the command line */ +static char *TechDefault = NULL; + +/* the filename for the graphics and mouse ports */ +global char *MainGraphicsFile = NULL; +global char *MainMouseFile = NULL; + +/* information about the color display. */ +global char *MainDisplayType = NULL; +global char *MainMonType = NULL; + + +/* Copyright notice for the binary file. */ +global char *MainCopyright = "\n--- MAGIC: Copyright (C) 1985, 1990 " + "Regents of the University of California. ---\n"; + +/* Forward declarations */ +char *mainArg(); + + +/* + * ---------------------------------------------------------------------------- + * MainExit: + * + * Magic's own exit procedure + * + * Results: + * None. + * + * Side effects: + * We exit. + * ---------------------------------------------------------------------------- + */ + +void +MainExit(errNum) + int errNum; +{ +#ifdef MOCHA + MochaExit(errNum); +#endif + if (GrClosePtr != NULL) /* We are not guarenteed that everthing will + * be initialized already! + */ + GrClose(); + + DBRemoveBackup(); + + TxFlush(); + TxResetTerminal(); + +#ifdef MAGIC_WRAPPER + + // NOTE: This needs to be done in conjunction with the following + // commands in the console: + // (1) tkcon eval rename ::exit ::quit + // (2) tkcon eval proc::exit args {slave eval quit} + // + // The lines above redirect tkcon's "exit" routine to be named + // "quit" (in the console, not the slave!). Because the tkcon + // File->Exit callback is set to eval "exit", we then can create + // a new proc called "exit" in the console that runs "quit" in + // the slave (magic), and will therefore do the usual checks to + // save work before exiting; if all responses are to exit without + // saving, then it finally gets to here, where it runs the (renamed) + // "quit" command in tkcon. That will ensure that tkcon runs + // various cleanup activities such as saving the command-line + // history file before the final (!) exit. + + if (TxTkConsole) + Tcl_Eval(magicinterp, "catch {tkcon eval quit}\n"); +#endif + + exit(errNum); +} + +/* + * ---------------------------------------------------------------------------- + * + * mainDoArgs: + * + * Process command line arguments + * + * Results: + * Return 0 on success, 1 on failure + * + * Side effects: + * Global variables are modified + * + * Notes: + * In order to work properly with the -F flag, we need to + * use StrDup() to make copies of any arguments we want + * to be visible when we restart a frozen file. + * + * ---------------------------------------------------------------------------- + */ + +int +mainDoArgs(argc, argv) + int argc; + char **argv; +{ + bool haveDashI = FALSE; + char *cp; + + /* Startup filename (may be changed with the "-rcfile" option or */ + /* the "-norcfile" option). */ + + RCFileName = StrDup((char **) NULL, ".magicrc"); + + while (--argc > 0) + { + argv++; + if (**argv == '-') + { + switch (argv[0][1]) + { + case 'g': + if ((cp = mainArg(&argc, &argv, "tty name")) == NULL) + return 1; + MainGraphicsFile = StrDup((char **) NULL, cp); + if (!haveDashI) + MainMouseFile = MainGraphicsFile; + break; + + case 'i': + haveDashI = TRUE; + if ((cp = mainArg(&argc, &argv, "tty name")) == NULL) + return 1; + MainMouseFile = StrDup((char **) NULL, cp); + break; + + case 'd': + if ((cp = mainArg(&argc, &argv, "display type")) ==NULL) + return 1; + MainDisplayType = StrDup((char **) NULL, cp); + break; + + case 'm': + if ((cp = mainArg(&argc, &argv, "monitor type")) ==NULL) + return 1; + MainMonType = StrDup((char **) NULL, cp); + break; + + /* + * Declare the technology. + */ + case 'T': + if ((cp = mainArg(&argc, &argv, "technology")) == NULL) + return 1; + TechDefault = StrDup((char **) NULL, cp); + TechOverridesDefault = TRUE; + break; + + /* + * -r or -re or -recover: Recover a crash file. + * -rc or -rcfile: Declare a specific startup file to read. + */ + case 'r': + if ((strlen(argv[0]) <= 2) || argv[0][2] == 'e') + RuntimeFlags |= MAIN_RECOVER; + else if ((argc > 1) && (argv[0][2] == 'c')) + { + argv[0][2] = '\0'; + if ((cp = mainArg(&argc, &argv, "startup file")) == NULL) + return 1; + RCFileName = StrDup((char **) NULL, cp); + } + else + { + TxError("Unknown option: '%s'\n", *argv); + return 1; + } + break; + + /* + * We are being debugged. + */ + case 'D': + RuntimeFlags |= MAIN_DEBUG; + break; + +#ifdef MAGIC_WRAPPER + /* + * "-w" for wrapper * implies -nowindow (no initial window) + */ + case 'w': + RuntimeFlags &= ~MAIN_MAKE_WINDOW; + break; + /* + * No initial window / no console options / no startup file read. + */ + case 'n': + if (strlen(argv[0]) < 4) + { + TxError("Ambiguous option %s: use -nowindow, -noconsole, " + "or -norcfile\n", argv[0]); + return 1; + } + else if (argv[0][3] == 'c') + RuntimeFlags &= ~MAIN_TK_CONSOLE; + else if (argv[0][3] == 'w') + RuntimeFlags &= ~MAIN_MAKE_WINDOW; + else if (argv[0][3] == 'r') + { + freeMagic(RCFileName); + RCFileName = NULL; + } + else + { + TxError("Unknown option: '%s'\n", *argv); + return 1; + } + break; +#endif + default: + TxError("Unknown option: '%s'\n", *argv); + TxError("Usage: magic [-g gPort] [-d devType] [-m monType] " + "[-i tabletPort] [-D] [-F objFile saveFile]\n" + "[-T technology] [-rcfile startupFile | -norcfile]" +#ifdef MAGIC_WRAPPER + "[-noconsole] [-nowindow] [-wrapper] " +#endif + "[file]\n"); + return 1; + } + } + else if (MakeMainWindow) + { + if (MainFileName == NULL) { + MainFileName = StrDup((char **) NULL, *argv); + CurrentName = (FileName *) mallocMagic(sizeof(FileName)); + CurrentName->fn = MainFileName; + CurrentName->fn_prev = (FileName *) NULL; + CurrentName->fn_type = FN_MAGIC_DB; + } + else + { + FileName *temporary; + + temporary = (FileName *) mallocMagic(sizeof(FileName)); + temporary->fn = StrDup((char **) NULL, *argv); + temporary->fn_prev = CurrentName; + temporary->fn_type = FN_MAGIC_DB; + CurrentName = temporary; + } + + /* Remove suffix if the file name already has it */ + { + char *c,*d; + + for(c = CurrentName->fn; (*c) != '\0'; c++); + for(d = DBSuffix; (*d) != '\0'; d++); + while( (*c) == (*d) ) { + if (c == MainFileName) break; + if (d == DBSuffix) { + (*c) = '\0'; + break; + } + c--; + d--; + } + + // Additional checks + if ((c = strrchr(CurrentName->fn, '.')) != NULL) + { +#ifdef LEF_MODULE + if (!strcasecmp(c, ".lef")) + CurrentName->fn_type = FN_LEF_FILE; + else if (!strcasecmp(c, ".def")) + CurrentName->fn_type = FN_DEF_FILE; +#endif +#ifdef CIF_MODULE + if (!strcasecmp(c, ".cif")) + CurrentName->fn_type = FN_CIF_FILE; + else if (!strncasecmp(c, ".gds", 3)) + CurrentName->fn_type = FN_GDS_FILE; +#endif +#ifdef MAGIC_WRAPPER + if (!strcasecmp(c, ".tcl")) + CurrentName->fn_type = FN_TCL_SCRIPT; +#endif + } + } + } + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * mainArg -- + * + * Pull off an argument from the (argc, argv) pair and also check + * to make sure it's not another flag (i.e, it doesn't begin with + * a '-'). + * + * Results: + * Return pointer to the argument string. + * + * Side effects: + * See the comments in ArgStr() in the utils module -- they + * apply here. + * + * ---------------------------------------------------------------------------- + */ + +char * +mainArg(pargc, pargv, mesg) + int *pargc; + char ***pargv; + char *mesg; +{ + char option, *cp; + + option = (*pargv)[0][1]; + cp = ArgStr(pargc, pargv, mesg); + if (cp == NULL) + return (char *) NULL; + + if (*cp == '-') + { + TxError("Bad name after '-%c' option: '%s'\n", option, cp); + return (char *) NULL; + } + return cp; +} + + +/* + * ---------------------------------------------------------------------------- + * mainInitBeforeArgs: + * + * Initializes things before argument processing. + * + * Results: + * 0 on success. As written, there are no failure modes. + * + * Side effects: + * All sorts of initialization. Most initialization, however, is done + * in 'mainInitAfterArgs'. + * ---------------------------------------------------------------------------- + */ + +int +mainInitBeforeArgs(argc, argv) + int argc; + char *argv[]; +{ + TechOverridesDefault = FALSE; + if (Path == NULL) + Path = StrDup((char **) NULL, "."); + + /* initialize text display */ + TxInit(); + TxSetTerminal(); + +#ifdef SCHEME_INTERPRETER + /* Initialize Lisp module. (rajit@cs.caltch.edu) */ + LispInit(); +#endif + + /* + * Get preliminary info on the graphics display. + * This may be overriden later. + */ + GrGuessDisplayType(&MainGraphicsFile, &MainMouseFile, + &MainDisplayType, &MainMonType); + FindDisplay((char *)NULL, "displays", CAD_LIB_PATH, &MainGraphicsFile, + &MainMouseFile, &MainDisplayType, &MainMonType); + + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * mainInitAfterArgs: + * + * Initializes things after argument processing. + * + * Results: + * Status: 0 = success, 1 = failure to set graphics display, + * 2 = failure to load technology file. + * + * Side effects: + * All sorts of initialization. + * ---------------------------------------------------------------------------- + */ + +int +mainInitAfterArgs() +{ + int (*nullProc)() = 0; + SectionID sec_tech, sec_planes, sec_types, sec_aliases; + SectionID sec_styles; + SectionID sec_connect, sec_contact, sec_compose; + SectionID sec_cifinput, sec_cifoutput; + SectionID sec_drc, sec_extract, sec_wiring, sec_router; + SectionID sec_plow, sec_plot, sec_mzrouter; + + DBTypeInit(); + MacroInit(); + +#ifdef LEF_MODULE + /* Pre-techfile-loading intialization of the LEF module */ + LefInit(); +#endif + +#ifdef OPENACCESS + OAInit(); +#endif + + /* + * Setup path names for system directory searches + */ + + StrDup(&SysLibPath, MAGIC_SYS_PATH); + + if (TechFileName != NULL) + { + CellLibPath = (char *)mallocMagic(strlen(MAGIC_LIB_PATH) + + strlen(TechFileName) - 1); + sprintf(CellLibPath, MAGIC_LIB_PATH, TechFileName); + } + else + CellLibPath = StrDup((char **)NULL, MAGIC_LIB_PATH); + + if (MainGraphicsFile == NULL) MainGraphicsFile = "/dev/null"; + if (MainMouseFile == NULL) MainMouseFile = MainGraphicsFile; + +#ifdef MAGIC_WRAPPER + /* Check for batch mode operation and disable interrupts in */ + /* batch mode by not calling SigInit(). */ + if (Tcl_GetVar(magicinterp, "batch_mode", TCL_GLOBAL_ONLY) != NULL) + SigInit(1); + else +#endif + + /* catch signals, must come after mainDoArgs & before SigWatchFile */ + SigInit(0); + + /* set up graphics */ + if ( !GrSetDisplay(MainDisplayType, MainGraphicsFile, MainMouseFile) ) + { + return 1; + } + + /* initialize technology */ + TechInit(); + TechAddClient("tech", DBTechInit, DBTechSetTech, nullProc, + (SectionID) 0, &sec_tech, FALSE); + TechAddClient("version", DBTechInitVersion, DBTechSetVersion, nullProc, + (SectionID) 0, (int *)0, TRUE); + TechAddClient("planes", DBTechInitPlane, DBTechAddPlane, nullProc, + (SectionID) 0, &sec_planes, FALSE); + TechAddClient("types", DBTechInitType, DBTechAddType, DBTechFinalType, + sec_planes, &sec_types, FALSE); + + TechAddClient("styles", nullProc, DBWTechAddStyle, nullProc, + sec_types, &sec_styles, FALSE); + + TechAddClient("contact", DBTechInitContact, + DBTechAddContact, DBTechFinalContact, + sec_types|sec_planes, &sec_contact, FALSE); + + TechAddAlias("contact", "images"); + TechAddClient("aliases", nullProc, DBTechAddAlias, nullProc, + sec_planes|sec_types|sec_contact, &sec_aliases, TRUE); + + TechAddClient("compose", DBTechInitCompose, + DBTechAddCompose, DBTechFinalCompose, + sec_types|sec_planes|sec_contact, &sec_compose, FALSE); + + TechAddClient("connect", DBTechInitConnect, + DBTechAddConnect, DBTechFinalConnect, + sec_types|sec_planes|sec_contact, &sec_connect, FALSE); + +#ifdef CIF_MODULE + TechAddClient("cifoutput", CIFTechStyleInit, CIFTechLine, CIFTechFinal, + (SectionID) 0, &sec_cifoutput, FALSE); + + TechAddClient("cifinput", CIFReadTechStyleInit, CIFReadTechLine, + CIFReadTechFinal, (SectionID) 0, &sec_cifinput, FALSE); +#else + TechAddClient("cifoutput", nullProc,nullProc,nullProc, + (SectionID) 0, &sec_cifoutput, FALSE); + + TechAddClient("cifinput", nullProc,nullProc,nullProc, + (SectionID) 0, &sec_cifinput, FALSE); +#endif +#ifdef ROUTE_MODULE + TechAddClient("mzrouter", MZTechInit, MZTechLine, MZTechFinal, + sec_types|sec_planes, &sec_mzrouter, TRUE); +#else + TechAddClient("mzrouter", nullProc,nullProc,nullProc, + sec_types|sec_planes, &sec_mzrouter, TRUE); +#endif + TechAddClient("drc", DRCTechStyleInit, DRCTechLine, DRCTechFinal, + sec_types|sec_planes, &sec_drc, FALSE); + +#ifdef LEF_MODULE + TechAddClient("lef", LefTechInit, LefTechLine, nullProc, + sec_types|sec_planes, (SectionID *) 0, TRUE); +#endif + +#ifdef NO_EXT + TechAddClient("extract", nullProc, nullProc,nullProc, + sec_types|sec_connect, &sec_extract, FALSE); +#else + TechAddClient("extract", nullProc, ExtTechLine, ExtTechFinal, + sec_types|sec_connect, &sec_extract, FALSE); +#endif + + TechAddClient("wiring", WireTechInit, WireTechLine, WireTechFinal, + sec_types, &sec_wiring, TRUE); + +#ifdef ROUTE_MODULE + TechAddClient("router", RtrTechInit, RtrTechLine, RtrTechFinal, + sec_types, &sec_router, TRUE); +#else + TechAddClient("router", nullProc,nullProc,nullProc, + sec_types, &sec_router, TRUE); +#endif + TechAddClient("plowing", PlowTechInit, PlowTechLine, PlowTechFinal, + sec_types|sec_connect|sec_contact, &sec_plow, TRUE); +#ifdef PLOT_MODULE + TechAddClient("plot", PlotTechInit, PlotTechLine, PlotTechFinal, + sec_types, &sec_plot, TRUE); +#else + TechAddClient("plot", nullProc,nullProc,nullProc, + sec_types, &sec_plot, TRUE); +#endif + + /* Load minimum technology file needed to keep things from */ + /* crashing during initialization. */ + + if (!TechLoad("minimum", 0)) + { + TxError("Cannot load technology \"minimum\" for initialization\n"); + return 2; + } + + /* The minimum tech has been loaded only to keep the database from */ + /* becoming corrupted during initialization. Free the tech file */ + /* name so that a "real" technology file can be forced to replace */ + /* it in mainInitFinal(). */ + + if (TechFileName != NULL) + { + freeMagic(TechFileName); + TechFileName = NULL; + } + + /* initialize the undo package */ + (void) UndoInit((char *) NULL, (char *) NULL); + + /* initialize windows */ + WindInit(); + + /* initialize commands */ + CmdInit(); + + /* Initialize the interface between windows and its clients */ + DBWinit(); +#ifdef USE_READLINE + TxInitReadline(); +#endif + CMWinit(); +#ifdef THREE_D + W3Dinit(); +#endif + + /* Initialize the circuit extractor */ +#ifndef NO_EXT + ExtInit(); +#endif + + /* Initialize plowing */ + PlowInit(); + + /* Initialize selection */ + SelectInit(); + + /* Initialize the wiring module */ + WireInit(); + +#ifdef ROUTE_MODULE + /* Initialize the netlist menu */ + NMinit(); +#endif + + /* Initialize the design-rule checker */ + DRCInit(); + + /* Initialize the maze router */ +#ifdef ROUTE_MODULE + MZInit(); + + /* Initialize the interactive router - + * NOTE the mzrouter must be initialized prior to the irouter + * so that default parameters will be completely setup + */ + IRDebugInit(); + IRAfterTech(); +#endif + + PlowAfterTech(); /* Copies DRC rule information into plow database */ + + /* Initialize the Sim Module (the part of it which involves (i)rsim) */ +#if !defined(NO_SIM_MODULE) && defined(RSIM_MODULE) + SimInit(); +#endif + + TxSetPoint(GR_CURSOR_X, GR_CURSOR_Y, WIND_UNKNOWN_WINDOW); + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * mainInitFinal: + * + * Final initialization; reads startup files and any initial file + * specified. + * + * Results: + * Return 0 on success. As written, there is no failure mode. + * + * Side effects: + * All sorts of initialization. + * ---------------------------------------------------------------------------- + */ + +int +mainInitFinal() +{ + char *home, cwd[512]; + char startupFileName[256]; + FILE *f; + char *rname; + int result; + +#ifdef MAGIC_WRAPPER + + /* Read in system pre-startup file, if it exists. */ + + /* Use PaOpen first to perform variable substitutions, and */ + /* return the actual filename in rname. */ + + f = PaOpen(MAGIC_PRE_DOT, "r", (char *) NULL, ".", + (char *) NULL, (char **) &rname); + if (f != NULL) + { + fclose(f); + result = Tcl_EvalFile(magicinterp, rname); + if (result != TCL_OK) + { + TxError("Error parsing pre-startup file \"%s\": %s\n", rname, + Tcl_GetStringResult(magicinterp)); + Tcl_ResetResult(magicinterp); + } + } +#endif /* MAGIC_WRAPPER */ + + // Make a first attempt to load the technology if specified on the + // command line with the -T option. This will preempt most other + // ways that the technology file is determined. If the technology + // specified cannot be loaded, then the forced override is revoked. + + if ((TechFileName == NULL) && (TechDefault != NULL) && TechOverridesDefault) + { + if (!TechLoad(TechDefault, -2)) + { + TxError("Failed to load technology \"%s\"\n", TechDefault); + TechOverridesDefault = FALSE; + } + else if (!TechLoad(TechDefault, 0)) + { + TxError("Error loading technology \"%s\"\n", TechDefault); + TechOverridesDefault = FALSE; + } + } + +#ifndef MAGIC_WRAPPER + + // Let the wrapper script be responsible for formatting and + // printing the technology file informaiton. + + if (DBTechName != 0) { + TxPrintf("Using technology \"%s\"", DBTechName); + if (DBTechVersion != 0) TxPrintf(", version %s.", DBTechVersion); + TxPrintf("\n"); + } + if (DBTechDescription != 0) TxPrintf("%s\n", DBTechDescription); +#endif + +#ifdef MAGIC_WRAPPER + /* Read in system startup file, if it exists. */ + + /* Use PaOpen first to perform variable substitutions, and */ + /* return the actual filename in rname. */ + + f = PaOpen(MAGIC_SYS_DOT, "r", (char *) NULL, ".", + (char *) NULL, (char **) &rname); + if (f != NULL) + { + fclose(f); + result = Tcl_EvalFile(magicinterp, rname); + if (result != TCL_OK) + { + TxError("Error parsing system startup file \"%s\": %s\n", rname, + Tcl_GetStringResult(magicinterp)); + Tcl_ResetResult(magicinterp); + } + } + +#else /* !MAGIC_WRAPPER */ + + f = PaOpen(MAGIC_SYS_DOT, "r", (char *) NULL, ".", + (char *) NULL, (char **) NULL); + if (f != NULL) + { + TxDispatch(f); + (void) fclose(f); + } + +#endif /* !MAGIC_WRAPPER */ + + /* + * Strive for a wee bit more parallelism; let the graphics + * display run while we're reading in startup files & initial cell. + */ + + GrFlush(); + + /* Ignore this whole section if we have received the -norc option */ + if (RCFileName != NULL) + { + + /* Read in user's startup files, if there are any. */ + /* If the "-rcfile" option has been used, and it doesn't specify */ + /* a full path, then look for this file in the home directory too. */ + + home = getenv("HOME"); + +#ifdef MAGIC_WRAPPER + + if (home != NULL && (RCFileName[0] != '/')) + { + Tcl_Channel fc; + + (void) sprintf(startupFileName, "%s/%s", home, RCFileName); + + fc = Tcl_OpenFileChannel(magicinterp, startupFileName, "r", 0); + if (fc != NULL) + { + Tcl_Close(magicinterp, fc); + result = Tcl_EvalFile(magicinterp, startupFileName); + if (result != TCL_OK) + { + TxError("Error parsing user \"%s\": %s\n", RCFileName, + Tcl_GetStringResult(magicinterp)); + Tcl_ResetResult(magicinterp); + } + } + else + { + /* Try the (deprecated) name ".magic" */ + (void) sprintf(startupFileName, "%s/.magic", home); + fc = Tcl_OpenFileChannel(magicinterp, startupFileName, "r", 0); + if (fc != NULL) + { + TxPrintf("Note: Use of the file name \"~/.magic\" is deprecated." + " Please change this to \"~/.magicrc\".\n"); + + Tcl_Close(magicinterp, fc); + result = Tcl_EvalFile(magicinterp, startupFileName); + + if (result != TCL_OK) + { + TxError("Error parsing user \".magic\": %s\n", + Tcl_GetStringResult(magicinterp)); + Tcl_ResetResult(magicinterp); + } + } + } + } + + if (getcwd(cwd, 512) == NULL || strcmp(cwd, home)) + { + /* Read in the .magicrc file from the current directory, if */ + /* different from HOME. */ + + Tcl_Channel fc; + + fc = Tcl_OpenFileChannel(magicinterp, RCFileName, "r", 0); + if (fc != NULL) + { + Tcl_Close(magicinterp, fc); + result = Tcl_EvalFile(magicinterp, RCFileName); + + if (result != TCL_OK) + { + // Print error message but continue anyway + + TxError("Error parsing \"%s\": %s\n", RCFileName, + Tcl_GetStringResult(magicinterp)); + Tcl_ResetResult(magicinterp); + TxPrintf("Bad local startup file \"%s\", continuing without.\n", + RCFileName); + } + } + else + { + /* Try the (deprecated) name ".magic" */ + + Tcl_ResetResult(magicinterp); + fc = Tcl_OpenFileChannel(magicinterp, ".magic", "r", 0); + if (fc != NULL) + { + Tcl_Close(magicinterp, fc); + + TxPrintf("Note: Use of the file name \".magic\" is deprecated." + " Please change this to \".magicrc\".\n"); + + result = Tcl_EvalFile(magicinterp, ".magic"); + + if (result != TCL_OK) + { + // Print error message but continue anyway + + TxError("Error parsing local \".magic\": %s\n", + Tcl_GetStringResult(magicinterp)); + Tcl_ResetResult(magicinterp); + TxPrintf("Bad local startup file \".magic\"," + " continuing without.\n"); + } + } + else + { + /* Try the alternative name "magic_setup" */ + + Tcl_ResetResult(magicinterp); + + fc = Tcl_OpenFileChannel(magicinterp, "magic_setup", "r", 0); + if (fc != NULL) + { + Tcl_Close(magicinterp, fc); + + result = Tcl_EvalFile(magicinterp, "magic_setup"); + if (result != TCL_OK) + { + TxError("Error parsing local \"magic_setup\": %s\n", + Tcl_GetStringResult(magicinterp)); + TxError("%s\n", Tcl_GetStringResult(magicinterp)); + Tcl_ResetResult(magicinterp); // Still not an error + TxPrintf("Bad local startup file \"magic_setup\"," + " continuing without.\n"); + } + } + } + } + } + +#else /* !MAGIC_WRAPPER */ + + if (home != NULL && (RCFileName[0] != '/')) + { + (void) sprintf(startupFileName, "%s/%s", home, RCFileName); + + + f = PaOpen(startupFileName, "r", (char *) NULL, ".", + (char *) NULL, (char **) NULL); + + if ((f == NULL) && (!strcmp(RCFileName, ".magicrc"))) + { + /* Try the (deprecated) name ".magic" */ + (void) sprintf(startupFileName, "%s/.magic", home); + f = PaOpen(startupFileName, "r", (char *) NULL, ".", + (char *) NULL, (char **) NULL); + if (f != NULL) + TxPrintf("Note: Use of the file name \"~/.magic\" is deprecated." + " Please change this to \"~/.magicrc\".\n"); + } + + if (f != NULL) + { + TxDispatch(f); + (void) fclose(f); + } + } + + /* Read in any startup file in the current directory, or one that was */ + /* specified on the commandline by the "-rcfile " option. */ + + f = PaOpen(RCFileName, "r", (char *) NULL, ".", + (char *) NULL, (char **) NULL); + + /* Again, check for the deprecated name ".magic" */ + if (f == NULL) + { + if (!strcmp(RCFileName, ".magicrc")) + { + f = PaOpen(".magic", "r", (char *) NULL, ".", + (char *) NULL, (char **) NULL); + if (f != NULL) + TxPrintf("Note: Use of the file name \"./.magic\" is deprecated." + " Please change this to \"./.magicrc\".\n"); + + else + f = PaOpen("magic_setup", "r", (char *) NULL, ".", + (char *) NULL, (char **) NULL); + } + else + TxError("Startup file \"%s\" not found or unreadable!\n", RCFileName); + } + + if (f != NULL) + { + TxDispatch(f); + fclose(f); + } + +#endif /* !MAGIC_WRAPPER */ + + } + + /* We are done forcing the "tech load" command to be ignored */ + TechOverridesDefault = FALSE; + + /* If no technology has been specified yet, try to read one from + * the initial cell, or else assign a default. + */ + + if ((TechFileName == NULL) && (TechDefault == NULL) && (MainFileName != NULL)) + StrDup(&TechDefault, DBGetTech(MainFileName)); + + /* Load the technology file. If any startup file loaded a */ + /* technology file, then "TechFileName" will be set, and we */ + /* should not override it. */ + + if ((TechFileName == NULL) && (TechDefault != NULL)) + { + if (!TechLoad(TechDefault, -2)) + TxError("Failed to load technology \"%s\"\n", TechDefault); + else if (!TechLoad(TechDefault, 0)) + TxError("Error loading technology \"%s\"\n", TechDefault); + } + + if (TechDefault != NULL) + { + freeMagic(TechDefault); + TechDefault = NULL; + } + + /* If that failed, then load the "minimum" technology again and */ + /* keep it. It's not very useful, but it will keep everything */ + /* up and running. In the worst case, if site.pre has removed the */ + /* standard locations from the system path, then magic will exit. */ + + if (TechFileName == NULL) + if (!TechLoad("minimum", 0)) + return -1; + +#ifdef SCHEME_INTERPRETER + /* Pass technology name to Lisp interpreter (rajit@cs.caltech.edu) */ + LispSetTech (TechFileName); +#endif + + /* + * Recover crash files from the temp directory if we have specified + * the -r option on the command line (non-tcl version. Tcl version + * uses the command-line command crashrecover. + */ + + if (mainRecover && MakeMainWindow) + { + DBFileRecovery(); + } + + /* + * Bring in a new cell or cells to start up if one was given + * on the command line + */ + + else if (MainFileName && MakeMainWindow) + { + FileName *temporary; + + while(CurrentName != NULL) + { + temporary = CurrentName; + CurrentName = temporary->fn_prev; + TxPrintf("Loading \"%s\" from command line.\n", temporary->fn); + switch (temporary->fn_type) + { + case FN_MAGIC_DB: + DBWreload(temporary->fn); + break; +#ifdef LEF_MODULE + case FN_LEF_FILE: + LefRead(temporary->fn, FALSE); + break; + case FN_DEF_FILE: + DefRead(temporary->fn); + break; +#endif +#ifdef MAGIC_WRAPPER + case FN_TCL_SCRIPT: + result = Tcl_EvalFile(magicinterp, temporary->fn); + if (result != TCL_OK) + { + TxError("Error parsing \"%s\": %s\n", + temporary->fn, + Tcl_GetStringResult(magicinterp)); + Tcl_ResetResult(magicinterp); + } + break; +#endif + } + freeMagic(temporary); + } + } + + /* Create an initial box. */ + + if (MakeMainWindow && EditCellUse) + DBWSetBox(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox); + + /* Set the initial fence for undo-ing: don't want to be able to + * undo past this point. + */ + UndoFlush(); + TxClearPoint(); + + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * mainFinish: + * + * Finish up things for Magic. This routine is NOT called on an + * error exit. + * + * Results: + * None. + * + * Side effects: + * Various things, such as stopping measurement gathering. + * ---------------------------------------------------------------------------- + */ + +void +mainFinished() +{ + /* Close up things */ + MainExit(0); +} + +/*--------------------------------------------------------------------------- + * magicMain: + * + * Top-level procedure of the Magic Layout System. There is purposely + * not much in here so that we have more flexibility. Also, it is + * not called 'main' so that other programs that use Magic may do + * something else. + * + * Results: + * None. + * + * Side Effects: + * None. + * + * Note: Try not to add code to this procedure. Add it instead to one of the + * procedures that it calls. + * + *---------------------------------------------------------------------------- + */ + +void +magicMain(argc, argv) + int argc; + char *argv[]; +{ + int rstatus; + + if ((rstatus = mainInitBeforeArgs(argc, argv)) != 0) MainExit(rstatus); + if ((rstatus = mainDoArgs(argc, argv)) != 0) MainExit(rstatus); + if ((rstatus = mainInitAfterArgs()) != 0) MainExit(rstatus); + if ((rstatus = mainInitFinal()) != 0) MainExit(rstatus); + TxDispatch( (FILE *) NULL); + mainFinished(); +} + + + diff --git a/utils/main.h b/utils/main.h new file mode 100644 index 00000000..74cb41ff --- /dev/null +++ b/utils/main.h @@ -0,0 +1,99 @@ +/* + * main.h -- + * + * Header file containing global variables for all MAGIC modules and a + * couple of global procedures. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid="$Header: /usr/cvsroot/magic-8.0/utils/main.h,v 1.2 2009/09/10 20:32:55 tim Exp $" + */ + +#ifndef _MAIN_H +#define _MAIN_H + +#include "windows/windows.h" +#include "database/database.h" + +/* global data structures */ + +extern char *Path; /* Search path */ +extern char *CellLibPath; /* Library search path for cells */ +extern char *SysLibPath; /* Library search path for tech files, + * etc. + */ +extern char *MainMouseFile; /* The filename of the mouse */ +extern char *MainGraphicsFile; /* The filename of the display */ +extern char *MainDisplayType; +extern char *MainMonType; + +extern FILE *mouseStream; /* the mouse file */ +extern FILE *graphicsStream; /* the graphics file */ + +extern short RuntimeFlags; /* A number of flags, defined below */ + +/* + * RuntimeFlags bits: + */ + +#define MAIN_DEBUG 0x1 /* Produce debugging output */ +#define MAIN_RECOVER 0x2 /* Recover crash files */ +#define MAIN_SILENT 0x4 /* Output as little as possible, + * for batch mode + */ +#define MAIN_MAKE_WINDOW 0x8 /* True if we are to produce a window + * on startup. + */ +#define MAIN_TK_CONSOLE 0x10 /* True if the Tcl version is running + * via the "tkcon" console window. + */ +#define MAIN_TK_PRINTF 0x20 /* Set to 0 to redirect output from the + * console back to the terminal. + */ +/* + * Macros which convert the RuntimeFlags bits to their original use as + * bool types. + */ +#define mainDebug (((RuntimeFlags & MAIN_DEBUG) > 0) ? TRUE : FALSE) +#define mainRecover (((RuntimeFlags & MAIN_RECOVER) > 0) ? TRUE : FALSE) +#define MakeMainWindow (((RuntimeFlags & MAIN_MAKE_WINDOW) > 0) ? TRUE : FALSE) +#define TxTkConsole (((RuntimeFlags & MAIN_TK_CONSOLE) > 0) ? TRUE : FALSE) +#define TxTkOutput (((RuntimeFlags & MAIN_TK_PRINTF) > 0) ? TRUE : FALSE) +#define MainSilent (((RuntimeFlags & MAIN_SILENT) > 0) ? TRUE : FALSE) + +/* + * The following information is kept about the Edit cell: + * + * EditCellUse pointer to the CellUse from which the edit + * cell was selected. + * EditRootDef pointer to root def of window in which edit cell + * was selected. + * EditToRootTransform transform from coordinates of the Def of edit cell + * to those of EditRootDef. + * RootToEditTransform transform from coordinates EditRootDef to those + * of the Def of the edit cell. + */ + +extern CellUse *EditCellUse; +extern CellDef *EditRootDef; +extern Transform EditToRootTransform; +extern Transform RootToEditTransform; + +/* global procedures */ + +extern void MainExit(int); /* a way of exiting that cleans up after itself */ +// These are not declared anywhere +// extern bool MainLoadStyles(), MainLoadCursors(); /* Used during init & reset */ + +#endif /* _MAIN_H */ diff --git a/utils/malloc.c b/utils/malloc.c new file mode 100644 index 00000000..d095a502 --- /dev/null +++ b/utils/malloc.c @@ -0,0 +1,162 @@ +/* + * malloc.c -- + * + * Memory allocator. + * Magic no longer contains its own version of malloc(), as all modern + * operating systems have implementations which are as good or better. + * + * The main thing this file does is to define mallocMagic and friends. + * freeMagic frees the previously requested memory item, not the one + * passed as the argument. This allows efficient coding of loops which + * run through linked lists and process and free them at the same time. + * + * ALWAYS use mallocMagic() with freeMagic() and NEVER mix them with + * malloc() and free(). + * + * Malloc trace routines have been removed. There are standard methods + * to trace memory allocation and magic doesn't need its own built-in + * method. + * + * The Tcl/Tk version of magic makes use of Tcl_Alloc() and Tcl_Free() + * which allows the Tcl/Tk version to trace memory using Tcl's methods. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/malloc.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/malloc.h" + +/* Normally we're supposed to warn against the use of standard malloc() */ +/* and free(), but obviously that doesn't apply to this file. */ + +#undef malloc +#undef free + +/* Imports */ + +extern void TxError(); +extern char *TxGetLine(); + +/* + * Magic may reference an object after it is free'ed, but only one object. + * This is a change from previous versions of Magic, which needed to reference + * an arbitrary number of objects before the next call to malloc. Only then + * would no further references would be made to free'ed storage. + */ + +/* Delay free'ing by one call, to accommodate Magic's needs. */ +static char *freeDelayedItem = NULL; + +/* Local definitions */ + +#ifdef MAGIC_WRAPPER +#ifdef TCL_MEM_DEBUG +#define MallocRoutine(a) ckalloc(a) +#define FreeRoutine(a) ckfree(a) +#else +#define MallocRoutine(a) Tcl_Alloc(a) +#define FreeRoutine(a) Tcl_Free(a) +#endif +#else +#define MallocRoutine(a) malloc(a) +#define FreeRoutine(a) free(a) +#endif + +/* + *--------------------------------------------------------------------- + * mallocMagic() -- + * + * memory allocator with support for one-delayed-item free'ing + *--------------------------------------------------------------------- + */ + +void * +mallocMagic(nbytes) + unsigned int nbytes; +{ + void *p; + + if (freeDelayedItem) + { + /* fprintf(stderr, "freed 0x%x (delayed)\n", freeDelayedItem); fflush(stderr); */ + + FreeRoutine(freeDelayedItem); + freeDelayedItem=NULL; + } + + if ((p = (void *)MallocRoutine(nbytes)) != NULL) + { + /* fprintf(stderr, "alloc'd %u bytes at 0x%x\n", nbytes, p); fflush(stderr); */ + + return p; + } + else + { + ASSERT(FALSE, "Can't allocate any more memory.\n"); + } + return NULL; +} + +/* + *--------------------------------------------------------------------- + * freeMagic() -- + * + * one-delayed-item memory deallocation + *--------------------------------------------------------------------- + */ + +void +freeMagic(cp) + void *cp; +{ + if (cp == NULL) + TxError("freeMagic called with NULL argument.\n"); + if (freeDelayedItem) + { + /* fprintf(stderr, "freed 0x%x\n", freeDelayedItem); fflush(stderr); */ + + FreeRoutine(freeDelayedItem); + } + freeDelayedItem=cp; +} + +/* + *--------------------------------------------------------------------- + * callocMagic() -- + * + * allocate memory and initialize it to all zero bytes. + *--------------------------------------------------------------------- + */ + +void * +callocMagic(nbytes) + unsigned int nbytes; +{ + void *cp; + + cp = mallocMagic(nbytes); + bzero(cp, (int) nbytes); + + return (cp); +} + diff --git a/utils/malloc.h b/utils/malloc.h new file mode 100644 index 00000000..d1c7a2ee --- /dev/null +++ b/utils/malloc.h @@ -0,0 +1,29 @@ +/* + * malloc.h -- + * + * See malloc.c for a description of magic's allocation functions. + * Magic's built-in malloc() function has been removed. + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/utils/malloc.h,v 1.2 2009/09/10 20:32:55 tim Exp $" + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef _MALLOC_H +#define _MALLOC_H + +extern void *mallocMagic(unsigned int); +extern void *callocMagic(unsigned int); +extern void freeMagic(void *); + +#endif diff --git a/utils/match.c b/utils/match.c new file mode 100644 index 00000000..74d7dbf3 --- /dev/null +++ b/utils/match.c @@ -0,0 +1,136 @@ +/* match.c - + * + * String matching operations. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/match.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "textio/textio.h" + +/* + * ---------------------------------------------------------------------------- + * + * Match -- + * + * Sees if two strings match, using csh-like pattern matching. + * + * Results: + * TRUE is returned if the two strings match, FALSE is returned + * if they don't. The first string, pattern, can contain the + * special characters *, ?, \, and [], which are matched as by + * the csh. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +Match(pattern, string) + char *pattern; /* csh-like pattern. */ + char *string; /* String to check for match against pattern.*/ +{ + char c2; + + while (TRUE) + { + /* See if we're at the end of both pattern and string. If + * so, we succeeded. If we're at the end of pattern, but not + * of string, we failed. + */ + + if (*pattern == 0) + { + if (*string == 0) return TRUE; + else return FALSE; + } + if ((*string == 0) && (*pattern != '*')) return FALSE; + + /* Check for a "*" as the next pattern character. It matches + * any substring. We handle this by calling ourselves + * recursively for each postfix of string, until either we + * match or we reach the end of the string. + */ + + if (*pattern == '*') + { + pattern += 1; + if (*pattern == 0) return TRUE; + while (*string != 0) + { + if (Match(pattern, string)) return TRUE; + string += 1; + } + return FALSE; + } + + /* Check for a "?" as the next pattern character. It matches + * any single character. + */ + + if (*pattern == '?') goto thisCharOK; + + /* Check for a "[" as the next pattern character. It is followed + * by a list of characters that are acceptable, or by a range + * (two characters separated by "-"). + */ + + if (*pattern == '[') + { + pattern += 1; + while (TRUE) + { + if ((*pattern == ']') || (*pattern == 0)) return FALSE; + if (*pattern == *string) break; + if (pattern[1] == '-') + { + c2 = pattern[2]; + if (c2 == 0) return FALSE; + if ((*pattern <= *string) && (c2 >= *string)) break; + if ((*pattern >= *string) && (c2 <= *string)) break; + pattern += 2; + } + pattern += 1; + } + while ((*pattern != ']') && (*pattern != 0)) pattern += 1; + goto thisCharOK; + } + + /* If the next pattern character is '\', just strip off the '\' + * so we do exact matching on the character that follows. + */ + + if (*pattern == '\\') + { + pattern += 1; + if (*pattern == 0) return FALSE; + } + + /* There's no special character. Just make sure that the next + * characters of each string match. + */ + + if (*pattern != *string) return FALSE; + + thisCharOK: pattern += 1; + string += 1; + } +} diff --git a/utils/maxrect.c b/utils/maxrect.c new file mode 100644 index 00000000..75a1f78a --- /dev/null +++ b/utils/maxrect.c @@ -0,0 +1,340 @@ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/maxrect.c,v 1.4 2010/09/24 19:53:20 tim Exp $"; +#endif + +#include +#include +#include /* for memcpy() */ + +#include "utils/maxrect.h" +#include "utils/malloc.h" + +/* + *------------------------------------------------------------------------- + * + * genCanonicalMaxwidth - checks to see that at least one dimension of a + * rectangular region does not exceed some amount. Searches on all + * tiles of types in "mask", unless mask is NULL, in which case it + * searches over all tiles whose client record matches that of the + * start tile. + * + * Side Effects: + * None. + * + *------------------------------------------------------------------------- + */ + +MaxRectsData * +genCanonicalMaxwidth(bbox, starttile, plane, mask) + Rect *bbox; /* Bounding box of geometry to search */ + Tile *starttile; /* Any point in the geometry to search */ + Plane *plane; /* Plane being searched */ + TileTypeBitMask *mask; /* Mask of types to check */ +{ + int s; + Tile *tile, *tp; + TileTypeBitMask wrongtypes; + static MaxRectsData *mrd = (MaxRectsData *)NULL; + Rect boundorig; + + /* Generate an initial array size of 8 for rlist and swap. */ + if (mrd == (MaxRectsData *)NULL) + { + mrd = (MaxRectsData *)mallocMagic(sizeof(MaxRectsData)); + mrd->rlist = (Rect *)mallocMagic(8 * sizeof(Rect)); + mrd->swap = (Rect *)mallocMagic(8 * sizeof(Rect)); + mrd->listdepth = 8; + } + if (mask == NULL) + mrd->match = starttile->ti_client; + else + mrd->match = CLIENTDEFAULT; + + mrd->rlist[0] = *bbox; + boundorig = *bbox; + + /* Do an area search on boundrect to find all materials not */ + /* in oktypes. Each such tile clips or subdivides */ + /* boundrect. Due to the way FindMaxRects is written for */ + /* the DRC maxwidth rule, maxdist = 1 is required to avoid */ + /* creating degenerate (zero size) areas. */ + + mrd->entries = 1; + mrd->maxdist = 1; + if (mask != NULL) + TTMaskCom2(&wrongtypes, mask); + else + TTMaskSetMask(&wrongtypes, &DBAllTypeBits); + + DBSrPaintArea(starttile, plane, &boundorig, &wrongtypes, FindMaxRects, mrd); + if (mrd->entries == 0) + return NULL; + else + return (MaxRectsData *)mrd; +} + +/* + *------------------------------------------------------------------------- + * + * FindMaxRects --- + * + * Procedure used to split an area up into multiple sets of possible + * convex rectangles. + * + * Results: + * Return 0 to keep the search going. + * + * Side effects: + * Adds data to structure mrd; possibly expanding its memory allocation. + * + * Notes: + * This routine does *not* handle non-Manhattan geometry. + * + *------------------------------------------------------------------------- + */ + +int +FindMaxRects(tile, mrd) + Tile *tile; + MaxRectsData *mrd; +{ + Rect area; + Rect *rlist, *sr, *tmp; + int s, entries; + + if (mrd->match != CLIENTDEFAULT) + if (tile->ti_client == mrd->match) + return 0; + + entries = 0; + TiToRect(tile, &area); + + rlist = mrd->swap; + for (s = 0; s < mrd->entries; s++) + { + /* Watch out for (M)INFINITY values! */ + + sr = &(mrd->rlist[s]); + if (GEO_OVERLAP(sr, &area)) + { + /* Top */ + if (area.r_ytop < INFINITY - 2) + if (sr->r_ytop >= area.r_ytop + mrd->maxdist) + { + rlist[entries] = *sr; + rlist[entries].r_ybot = area.r_ytop; + entries++; + } + /* Bottom */ + if (area.r_ybot > MINFINITY + 2) + if (sr->r_ybot <= area.r_ybot - mrd->maxdist) + { + rlist[entries] = *sr; + rlist[entries].r_ytop = area.r_ybot; + entries++; + } + /* Left */ + if (area.r_xbot > MINFINITY + 2) + if (sr->r_xbot <= area.r_xbot - mrd->maxdist) + { + rlist[entries] = *sr; + rlist[entries].r_xtop = area.r_xbot; + entries++; + } + /* Right */ + if (area.r_xtop < INFINITY - 2) + if (sr->r_xtop >= area.r_xtop + mrd->maxdist) + { + rlist[entries] = *sr; + rlist[entries].r_xbot = area.r_xtop; + entries++; + } + + } + else + { + /* Copy sr to the new list */ + rlist[entries] = *sr; + entries++; + } + + /* If we have more rectangles than we allocated space for, */ + /* double the list size and continue. */ + + if (entries > (mrd->listdepth - 4)) // was entries == mrd->listdepth + { + Rect *newrlist; + + mrd->listdepth <<= 1; /* double the list size */ + + newrlist = (Rect *)mallocMagic(mrd->listdepth * sizeof(Rect)); + memcpy((void *)newrlist, (void *)mrd->rlist, + (size_t)mrd->entries * sizeof(Rect)); + // for (s = 0; s < entries; s++) + // newrlist[s] = mrd->rlist[s]; + freeMagic(mrd->rlist); + mrd->rlist = newrlist; + + newrlist = (Rect *)mallocMagic(mrd->listdepth * sizeof(Rect)); + memcpy((void *)newrlist, (void *)mrd->swap, + (size_t)entries * sizeof(Rect)); + // for (s = 0; s < entries; s++) + // newrlist[s] = mrd->swap[s]; + freeMagic(mrd->swap); + mrd->swap = newrlist; + + rlist = mrd->swap; + } + } + + /* Sort areas and remove areas enclosed by other areas */ + /* Is this routine too time-consuming (short answer: yes)? */ + +/* + for (s = 0; s < entries - 1; s++) + { + int r, t; + for (t = s + 1, r = 0; t < entries; t++) + { + if (GEO_SURROUND(&rlist[t], &rlist[s])) + { + rlist[s] = rlist[t]; + r++; + } + else if (GEO_SURROUND(&rlist[s], &rlist[t])) + r++; + else if (r > 0) + rlist[t - r] = rlist[t]; + } + entries -= r; + } +*/ + + /* copy rlist back to mrd by swapping "rlist" and "swap" */ + mrd->entries = entries; + tmp = mrd->rlist; + mrd->rlist = rlist; + mrd->swap = tmp; + + if (entries > 0) + return 0; /* keep the search going */ + else + return 1; /* no more max size areas; stop the search */ +} + +/* + *------------------------------------------------------------------------- + * + * FindMaxRectangle --- + * + * This is a general-purpose routine to be called from anywhere + * that expands an area to the largest area rectangle containing + * tiles connected to the given types list. It can be called, for + * example, from the router code to expand a point label into the + * maximum size rectangular terminal. + * + * Results: + * Pointer to a rectangle containing the maximum size area found. + * This pointer should not be deallocated! + * + *------------------------------------------------------------------------- + */ + +Rect * +FindMaxRectangle(bbox, startpoint, plane, expandtypes) + Rect *bbox; /* bounding box of area searched */ + Point *startpoint; + Plane *plane; /* plane of types to expand */ + TileTypeBitMask *expandtypes; /* types to expand in */ +{ + MaxRectsData *mrd; + Tile *starttile; + TileType tt; + int rectArea; + int maxarea = 0; + int s, sidx = -1; + + /* Find tile in def that surrounds or touches startpoint */ + starttile = plane->pl_hint; + GOTOPOINT(starttile, startpoint); + mrd = genCanonicalMaxwidth(bbox, starttile, plane, NULL); + + /* Return only the largest rectangle found */ + + for (s = 0; s < mrd->entries; s++) + { + rectArea = (mrd->rlist[s].r_xtop - mrd->rlist[s].r_xbot) * + (mrd->rlist[s].r_ytop - mrd->rlist[s].r_ybot); + if (rectArea > maxarea) + { + maxarea = rectArea; + sidx = s; + } + } + + if (sidx < 0) + { + Rect origrect; + + TiToRect(starttile, &origrect); + sidx = 0; + mrd->rlist[0] = origrect; + } + return &(mrd->rlist[sidx]); +} + +/* + *------------------------------------------------------------------------- + * + * FindMaxRectangle2 --- + * + * This routine differs from FindMaxRectangle in passing a starting + * tile to the routine + * + * Results: + * Pointer to a rectangle containing the maximum size area found. + * This pointer should not be deallocated! + * + *------------------------------------------------------------------------- + */ + +Rect * +FindMaxRectangle2(bbox, starttile, plane) + Rect *bbox; /* bounding box of area searched */ + Tile *starttile; /* use this tile to start */ + Plane *plane; /* plane of types to expand */ +{ + MaxRectsData *mrd; + TileType tt; + int rectArea; + int maxarea = 0; + int s, sidx = -1; + + /* Find tile in def that surrounds or touches startpoint */ + mrd = genCanonicalMaxwidth(bbox, starttile, plane, NULL); + + /* Return only the largest rectangle found */ + + for (s = 0; s < mrd->entries; s++) + { + rectArea = (mrd->rlist[s].r_xtop - mrd->rlist[s].r_xbot) * + (mrd->rlist[s].r_ytop - mrd->rlist[s].r_ybot); + if (rectArea > maxarea) + { + maxarea = rectArea; + sidx = s; + } + } + + if (sidx < 0) + { + Rect origrect; + + TiToRect(starttile, &origrect); + sidx = 0; + mrd->rlist[0] = origrect; + } + return &(mrd->rlist[sidx]); +} + diff --git a/utils/maxrect.h b/utils/maxrect.h new file mode 100644 index 00000000..20bbe2c8 --- /dev/null +++ b/utils/maxrect.h @@ -0,0 +1,51 @@ +/* + * maxrect.h -- + * + * Definitions needed for finding maximum-area rectangles + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * Needs to include: magic.h database.h + * + * rcsid $Header: /usr/cvsroot/magic-8.0/utils/maxrect.h,v 1.1 2008/12/04 16:21:44 tim Exp $ + */ + +#ifndef _MAXRECT_H +#define _MAXRECT_H + +#include "database/database.h" + +/* Data structure to keep a record of multiple rectangular regions, + * used by the widespacing rule + */ + +typedef struct { + Rect *rlist; + Rect *swap; + int entries; + int maxdist; + int listdepth; + ClientData match; +} MaxRectsData; + +extern MaxRectsData *genCanonicalMaxwidth(); + +/* + * Exported procedures + */ + +extern Rect *FindMaxRectangle(); +extern Rect *FindMaxRectangle2(); +extern int FindMaxRects(); + +#endif /* _MAXRECT_H */ diff --git a/utils/netlist.c b/utils/netlist.c new file mode 100644 index 00000000..edeba540 --- /dev/null +++ b/utils/netlist.c @@ -0,0 +1,394 @@ +/* + * netlist.c + * + * This code is responsible for building up the internal representation + * of a netlist, finding all locations for each terminal, and sorting + * the nets of a netlist into order of increasing area on a Heap. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/netlist.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* lint */ + +#include +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/heap.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "utils/netlist.h" +#include "utils/signals.h" +#include "textio/textio.h" +#include "utils/malloc.h" +#include "utils/styles.h" + +/* Compute the "cost" of a net from the bounding rect for all its terminals */ +#define NETSIZE(r) ((int)((r)->r_xtop - (r)->r_xbot + (r)->r_ytop - (r)->r_ybot)) + +/* Forward declarations */ +int nlTermFunc(), nlLabelFunc(); + +/* + * ---------------------------------------------------------------------------- + * + * NLBuild -- + * + * Build an internal NLNetList structure from the information + * in the current netlist. We call the netmenu module to enumerate + * the names of all the terminals in each net, and then search + * the layout rooted at 'rootUse' for all occurrences of each + * terminal label. + * + * Results: + * Returns the number of nets in the netlist. + * + * Side effects: + * Fills in the NLNetList pointed to by netList. + * The HashTable netList->nnl_names is initialized; + * it is indexed by the name of a terminal and each entry + * so found points to the NLTerm struct with that name. + * + * ---------------------------------------------------------------------------- + */ + +int +NLBuild(rootUse, netList) + CellUse *rootUse; /* Cell searched for terminals */ + NLNetList *netList; /* Netlist to build */ +{ + NLTerm *term; + NLNet *net; + + netList->nnl_nets = (NLNet *) NULL; + HashInit(&netList->nnl_names, 128, 0); + + /* Build list of all nets and terminals, but don't assign locations */ + (void) NMEnumNets(nlTermFunc, (ClientData) netList); + + /* Count the number of nets */ + netList->nnl_numNets = 0; + for (net = netList->nnl_nets; net; net = net->nnet_next) + netList->nnl_numNets++; + if (SigInterruptPending) goto done; + + /* Now find all the occurrences of each terminal */ + for (net = netList->nnl_nets; net; net = net->nnet_next) + for (term = net->nnet_terms; term; term = term->nterm_next) + (void) DBSrLabelLoc(rootUse, term->nterm_name, nlLabelFunc, + (ClientData) term); + + /* + * Sanity checking and error reporting. + * Complain if no occurrences were found for a terminal, or + * if a net had only a single terminal in it. + */ + for (net = netList->nnl_nets; net; net = net->nnet_next) + { + char mesg[256]; + int nterms = 0; + Rect r; + + for (term = net->nnet_terms; term; term = term->nterm_next) + { + /* Complain if terminal couldn't be found */ + if (term->nterm_locs == NULL) + TxError("Terminal %s couldn't be found\n", term->nterm_name); + nterms++; + } + + /* Complain if only one terminal in net */ + if (nterms == 1) + { + (void) sprintf(mesg, "Net %s has only one terminal", + net->nnet_terms->nterm_name); + if ( net->nnet_terms->nterm_locs ) + { + GEO_EXPAND(&net->nnet_terms->nterm_locs->nloc_rect, 1, &r); + DBWFeedbackAdd(&r, mesg, rootUse->cu_def, 1, + STYLE_PALEHIGHLIGHTS); + } + } + } + +done: + return (netList->nnl_numNets); +} + +/* + * ---------------------------------------------------------------------------- + * + * nlTermFunc -- + * + * Called for each terminal in each net. If the first terminal + * in the net, allocate a new NLNet and prepend to netList->nnl_nets. + * In any case, allocate a new NLTerm and prepend to the net on the + * head of netList->nnl_nets (the new net allocated above if the + * first terminal in the net). + * + * Results: + * Always returns 0. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +nlTermFunc(name, firstInNet, netList) + char *name; + bool firstInNet; + NLNetList *netList; +{ + NLNet *net; + NLTerm *term; + HashEntry *he; + + if (firstInNet) + { + net = (NLNet *) mallocMagic((unsigned) (sizeof (NLNet))); + bzero( (char *) net, sizeof(*net)); + net->nnet_terms = (NLTerm *) NULL; + net->nnet_next = netList->nnl_nets; + net->nnet_area = GeoNullRect; + net->nnet_cdata = (ClientData) NULL; + netList->nnl_nets = net; + } + else net = netList->nnl_nets; + + /* Find hash entry for this terminal */ + he = HashFind(&netList->nnl_names, name); + if (HashGetValue(he)) + TxError("Warning: terminal %s appears in more than one net\n", name); + + term = (NLTerm *) mallocMagic((unsigned) (sizeof (NLTerm))); + term->nterm_locs = (NLTermLoc *) NULL; + term->nterm_net = net; + term->nterm_name = he->h_key.h_name; + term->nterm_next = net->nnet_terms; + term->nterm_flags = 0; + net->nnet_terms = term; + + HashSetValue(he, (ClientData) term); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * nlLabelFunc -- + * + * Called for each occurrence of each label named in a netlist. + * Allocates a new NLTermLoc for this label and prepends it to + * the list for 'term'. + * + * Results: + * Always returns 0. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +int +nlLabelFunc(area, name, label, term) + Rect *area; /* Root coords of label */ + char *name; /* Same as term->nterm_name (UNUSED) */ + Label *label; /* Label within scx->scx_use->cu_def */ + NLTerm *term; /* Prepend new NLTermLoc to this terminal */ +{ + NLTermLoc *loc; + + loc = (NLTermLoc *) mallocMagic((unsigned) (sizeof (NLTermLoc))); + loc->nloc_term = term; + loc->nloc_rect = *area; + loc->nloc_label = label; + + /* Uninitialized */ + loc->nloc_dir = -1; + loc->nloc_pin = (struct pin *) NULL; + loc->nloc_chan = (struct chan *) NULL; + loc->nloc_stem = TiPlaneRect.r_ll; + + loc->nloc_region = (struct region *) NULL; + loc->nloc_czone = (struct czone *) NULL; + loc->nloc_stemcost = 0; + + /* Link into term's list */ + loc->nloc_next = term->nterm_locs; + term->nterm_locs = loc; + + (void) GeoInclude(&loc->nloc_rect, &term->nterm_net->nnet_area); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * NLFree -- + * + * Free the storage in the NLNetList that was allocated + * by glBuildNetList() above. + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * + * ---------------------------------------------------------------------------- + */ + +void +NLFree(netList) + NLNetList *netList; +{ + NLTermLoc *loc; + NLTerm *term; + NLNet *net; + + for (net = netList->nnl_nets; net; net = net->nnet_next) + { + for (term = net->nnet_terms; term; term = term->nterm_next) + { + for (loc = term->nterm_locs; loc; loc = loc->nloc_next) + freeMagic((char *) loc); + freeMagic((char *) term); + } + freeMagic((char *) net); + } + + HashKill(&netList->nnl_names); +} + +/* + * ---------------------------------------------------------------------------- + * + * NLSort -- + * + * Build a heap of nets, ordered with smallest area first. + * Nets with only one terminal are not added to the heap. + * + * Results: + * None. + * + * Side effects: + * Initializes and builds the heap netHeap, which is + * sorted in order of increasing area. + * + * ---------------------------------------------------------------------------- + */ + +void +NLSort(netList, netHeap) + NLNetList *netList; + Heap *netHeap; +{ + NLTermLoc *loc; + NLTerm *term; + NLNet *net; + int nterms; + Rect r; + + HeapInit(netHeap, 128, FALSE, FALSE); + for (net = netList->nnl_nets; net; net = net->nnet_next) + { + /* Skip nets with only one terminal */ + if (net->nnet_terms == NULL || net->nnet_terms->nterm_next == NULL) + continue; + + /* Find bounding box around all terminals in this net */ + nterms = 0; + for (term = net->nnet_terms; term; term = term->nterm_next) + if (loc = term->nterm_locs) + { + for ( ; loc; loc = loc->nloc_next) + { + if (nterms++ == 0) r = loc->nloc_rect; + else (void) GeoInclude(&loc->nloc_rect, &r); + } + } + + /* Add it to the heap if non-degenerate */ + if (nterms >= 2) + { + HeapAddInt(netHeap, NETSIZE(&r), (char *)net); + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * NLNetName -- + * + * Given a pointer to a net, return the name of some terminal associated + * with the net. + * + * Kludge: it's possible, when debugging the channel router, that the + * nets it passes aren't pointers to real NLNets at all, but simply + * small integers. We're clever enough to try to recognize this by + * comparing net with _etext; if it's earlier, we assume it's a small + * integer and not a NLNet pointer. + * + * Results: + * Pointer to the name of the net. + * + * Side effects: + * If the net appears to have no terminal names, return a + * pointer to a statically allocated string that contains + * the hex address of the net structure. + * + * ---------------------------------------------------------------------------- + */ + +char * +NLNetName(net) + NLNet *net; +{ + static char tempId[100]; +#if defined(linux) || defined(CYGWIN) + extern int etext asm("etext"); +#elif defined(__APPLE__) + int etext; +#else + extern int etext; +#endif + NLTerm *term; + + if (net == (NLNet *) NULL) + return "(NULL)"; + + /* Handle case of small integers, for debugging the channel router */ + if (net <= (NLNet *)(&etext)) + { + (void) sprintf(tempId, "#%"DLONG_PREFIX"d", (dlong) net); + return tempId; + } + + term = net->nnet_terms; + if (term == NULL || term->nterm_name == NULL) + { + (void) sprintf(tempId, "[%p]", net); + return tempId; + } + + return term->nterm_name; +} + diff --git a/utils/netlist.h b/utils/netlist.h new file mode 100644 index 00000000..7d0a56c5 --- /dev/null +++ b/utils/netlist.h @@ -0,0 +1,126 @@ +/* + * netlist.h -- + * + * This file defines the structures that represent netlists. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * RCSID $Header: /usr/cvsroot/magic-8.0/utils/netlist.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _RMNETLIST_H +#define _RMNETLIST_H + +#include "utils/geometry.h" +#include "utils/magic.h" +#include "database/database.h" + +/* --------------------------- Netlists ------------------------------- */ + +/* + * Nets and terminals. + * The current netlist is read into these structures so + * it can be worked with more conveniently and so its + * components can be given unique names. + */ +typedef struct nlTermLoc +{ + /* Set prior to stem assignment */ + struct nlTermLoc *nloc_next; /* Next location in list */ + struct nlTerm *nloc_term; /* Back pointer to term */ + Rect nloc_rect; /* Location of terminal itself */ + Label *nloc_label; /* Points to original label */ + + /* Set during stem assignment */ + Point nloc_stem; /* Point on channel boundary */ + int nloc_dir; /* Direction from label to nloc_stem */ + struct chan *nloc_chan; /* Contains nloc_stem */ + struct pin *nloc_pin; /* Pin on nloc_chan boundary */ + + struct region *nloc_region; /* Region containing stem */ + struct czone *nloc_czone; /* Range containing point */ + int nloc_stemcost; /* Cost of stem */ + int nloc_flags; /* Flags */ +} NLTermLoc; + +#define NLOC_TERM 001 /* Location used in steiner in net */ + + /* + * Each NLTerm corresponds to a name, but that name may + * have several locations if the label appears in several + * places inside a cell. It points back to the net to + * to which it belongs. The name nterm_name points to + * the key in the glnl_names hash table, so it shouldn't + * be freed explicitly. + */ +typedef struct nlTerm +{ + struct nlTerm *nterm_next; /* Next terminal in net */ + char *nterm_name; /* Name of this terminal */ + struct nlTermLoc *nterm_locs; /* List of equivalent locations */ + struct nlNet *nterm_net; /* Back pointer to net */ + int nterm_flags; /* See below */ +} NLTerm; + + /* Flags for above */ +#define RTERM_ISDRIVER 0x0001 /* Term is a transmission line driver */ + + /* + * Each NLNet consists of several terminals; in order to be + * of interest to the router, it must contain at least two. + */ +typedef struct nlNet +{ + struct nlNet *nnet_next; /* Next net in netlist */ + struct nlTerm *nnet_terms; /* List of terminals */ + Rect nnet_area; /* Bounding box for net's terms */ + ClientData nnet_cdata; /* For hire */ + + /******************************************************************** + New Info for Area Router + *********************************************************************/ + int nnet_cost; /* Cost of steiner tree */ + int nnet_complexity;/* Complexity of steiner tree */ + struct segment *nnet_segm; /* List of steiner segments */ + struct via *nnet_vias; /* List of vias */ + struct nlNet *nnet_stack; /* Queue of nets */ + struct czlist *nnet_czlist; /* Czone list */ + int nnet_attempts; /* Iteration count */ + int nnet_state; /* Routing stats */ + int nnet_flags; /* Flags */ + struct svi *nnet_svi; /* Maze route/sever info */ +} NLNet; + +#define NT_ROUTED 001 /* Net successfully routed */ +#define NT_FAILED 002 /* Net unsuccessfully routed */ +#define NT_SEVERED 004 /* Net has been severed */ + + /* + * A NLNetList contains a list of nets, along with the + * table that maps from signal names to terminals. + */ +typedef struct +{ + struct nlNet *nnl_nets; /* List of nets */ + int nnl_numNets; /* # of nets in list (redundant, since + * the list is NULL-terminated, but it + * is convenient). + */ + HashTable nnl_names; /* Maps names to NLTerms */ +} NLNetList; + +/* Exports */ +extern char *NLNetName(); + +#endif /* _RMNETLIST_H */ diff --git a/utils/niceabort.c b/utils/niceabort.c new file mode 100644 index 00000000..a8885a15 --- /dev/null +++ b/utils/niceabort.c @@ -0,0 +1,211 @@ +/* + * niceabort.c -- + * + * Nice version of abort which dumps core without actually + * killing the running job. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/niceabort.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include /* for getpid(), sleep() */ +#include +#include /* for chmod() */ + + +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/utils.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "windows/windows.h" +#include "utils/main.h" + +#define CRASHDIR "CAD_DIR/lib/magic/crash" + +/* + * Command used to mail core dump messages. The '%s' is filled in with the + * name of a file to be mailed. + */ +#define MAIL_COMMAND "/bin/mail magiccrash < %s" + + +/* The following array is used to hold information about the + * assertion that failed. + */ + +char AbortMessage[200]; +bool AbortFatal = FALSE; + +/* For lint */ +time_t time(); +char *ctime(); + +void +DumpCore() +{ + int parentPid = getpid(); + int cpid, gcpid, wpid; + FILE *commentFile, *crashFile; + time_t now; + char pidString[20], line[150], command[200], tempName[200], *crashDir; + + TxPrintf("Please wait while magic generates a core image of itself....\n"); + sprintf(pidString, "%d", parentPid); + FORK_f (cpid); + if (cpid < 0) + { + perror("fork"); + return; + } + + /* Child */ + + if (cpid == 0) + { + /* + * Suspend the parent to make it as easy as + * possible for gcore to make a core image. + */ + kill(SIGSTOP, parentPid); + FORK_vf(gcpid); + if (gcpid < 0) + perror("vfork"); + else + { + if (gcpid == 0) + { + execl(GCORE, "gcore", pidString, NULL); + exit (1); + } + WaitPid (gcpid,0); +/* while ((wpid = wait(0)) != gcpid && wpid != -1) */ + /* Nothing */; + } + /* + * Resume the parent + */ + kill(SIGCONT, parentPid); + exit (0); + } + + WaitPid (cpid,0); +/* while ((wpid = wait(0)) != cpid && wpid != -1) */ + /* Nothing */; + + /* + * We use PaOpen merely to to tilde expansion on CRASHDIR, + * to find the real name of the directory into which we want + * to place the crash dump. + */ + + if (crashFile = PaOpen(CRASHDIR, "r", "", ".", "", &crashDir)) + { + (void) fclose(crashFile); + + (void) sprintf(command, "mv core.%s %s", pidString, crashDir); + system(command); + TxPrintf(".... done\n"); + (void) sprintf(tempName, "%s/core.%s", crashDir, pidString); + (void) chmod(tempName, 0644); + + TxPrintf("Please type a description of the problem, so the\n"); + TxPrintf("magic maintainers will know what went wrong.\n"); + TxPrintf("Terminate your description with a dot on a line\n"); + TxPrintf("by itself (\".\"):\n\n"); + + (void) sprintf(tempName, "%s/comments.%s", crashDir, pidString); + commentFile = fopen(tempName, "w"); + if (commentFile == (FILE *) NULL) return; + (void) chmod(tempName, 0644); + + time(&now); + fprintf(commentFile, "~s -- Magic crashed %24.24s --\n", ctime(&now)); + fputs(MagicVersion, commentFile); + fprintf(commentFile, "%s\n", AbortMessage); + while (TxGetLine(line, sizeof line) != NULL) + { + /* + * We would use EOF to end the message, but there is no EOF when + * magic is running unless it is accepting input from a + * command file. + */ + if (strcmp(line, ".") == 0) + break; + fprintf(commentFile, "%s\n", line); + } + fclose(commentFile); + sprintf(command, MAIL_COMMAND, tempName); + system(command); + + TxPrintf("Thank you.\n"); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * niceabort -- + * + * Nice version of abort which dumps core (using gcore) without actually + * killing the running job. + * + * Results: + * None. + * + * Side effects: + * The first time we are called, we dump a core image; on successive + * calls, we don't bother to dump core. + * ---------------------------------------------------------------------------- + */ + +void +niceabort() +{ + static int timesCalled = 0; + + timesCalled++; + TxPrintf("-------------------- Error #%d\n", timesCalled); + if (timesCalled > 10) + { + TxPrintf("\nAbort called more than 10 times -- things are really hosed!\n"); + TxPrintf("Recommendation:\n"); + TxPrintf(" 1) Copy all your files to another directory.\n"); + TxPrintf(" 2) Send magic a SIGTERM signal and it will ATTEMPT to write out your files.\n"); + TxPrintf(" (It might trash them, though.)\n"); + TxPrintf("Magic going to sleep now for 10 hours -- please kill me.\n"); + sleep(3600); + } + + TxPrintf("Magic has encountered a major internal inconsistency:\n\n"); + TxPrintf(" %s\n", AbortMessage); + + if (AbortFatal) { + TxPrintf("Magic can't recover from this error. Goodbye.\n\n"); + } else { + TxPrintf("It will try to recover, but you should save all your\n"); + TxPrintf("files as soon as possible and quit magic.\n\n"); + } + TxPrintf("--------------------\n"); + +} diff --git a/utils/parser.c b/utils/parser.c new file mode 100644 index 00000000..7019cd1b --- /dev/null +++ b/utils/parser.c @@ -0,0 +1,170 @@ +/* + * parser.c -- + * + * Handles textual parsing. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/parser.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "textio/textio.h" + +#define ISEND(ch) ((ch == '\0') || (ch == ';')) + + +/* + * ---------------------------------------------------------------------------- + * ParsSplit: + * + * Take a string and split it into argc, argv format. + * The result of this split is stored back into the original string, + * and an array of pointers is set up to index into it. Note that + * the contents of the original string are lost. + * + * rajit@cs.caltech.edu: changed it so that quotes typed in by the + * user remain there. + * + * Results: + * TRUE if everything went OK. + * FALSE otherwise. + * + * Side effects: + * argc is filled in, str is changed, argv[] is changed to point into str + * ---------------------------------------------------------------------------- + */ + +bool +ParsSplit(str, maxArgc, argc, argv, remainder) + char *str; + int maxArgc; + int *argc; + char **argv; + char **remainder; +{ + char **largv; + char *newstrp; + char *strp; + char terminator; + + *argc = 0; + largv = argv; + newstrp = str; + strp = str; + + while (isspace(*strp) && (!ISEND(*strp)) ) strp++; + + terminator = *strp; + *largv = strp; + while (!ISEND(*strp)) + { + /* + * hackhackhackhackhack + * rajit@cs.caltech.edu + * okay. so we're changing what ' ' can be used for. + * One can only have a _SINGLE_ character between the + * two quotes. i.e. ' ' are used to quote characters. + */ +#ifdef SCHEME_INTERPRETER + if (*strp == '\'' && *(strp+1) && *(strp+2) == '\'') + { + strp++; + *newstrp++ = *strp++; + strp++; + } + /* + * rajit@cs.caltech.edu + * keep " " around strings to distinguish symbols from strings. + * the lisp evaluator strips these quotes after parsing the + * string. + */ + else if (*strp == '"') +#else + if (*strp == '"' || *strp == '\'') +#endif + { + char compare; + +#ifdef SCHEME_INTERPRETER + *newstrp++ = *strp; +#endif + compare = *strp++; + while ( (*strp != compare) && (*strp != '\0')) + { + if (*strp == '\\') +#ifndef SCHEME_INTERPRETER + strp++; +#else + *newstrp++ = *strp++; +#endif + *newstrp++ = *strp++; + } + if (*strp == compare) +#ifndef SCHEME_INTERPRETER + strp++; +#else + *newstrp++ = *strp++; +#endif + else +#ifndef SCHEME_INTERPRETER + TxError("Unmatched %c in string, %s.\n", compare, + "I'll pretend that there is one at the end"); +#else + { + TxError ("Unmatched %c in string.\n", compare); + return FALSE; + } +#endif + } + else + *newstrp++ = *strp++; + if (isspace(*strp) || (ISEND(*strp))) + { + while (isspace(*strp) && (!ISEND(*strp))) strp++; + terminator = *strp; + *newstrp++ = '\0'; + (*argc)++; + if (*argc < maxArgc) + { + *++largv = newstrp; + } + else + { + TxError("Too many arguments.\n"); + *remainder = NULL; + return FALSE; + } + } + } + + ASSERT(remainder != (char **) NULL, "ParsSplit"); + + if (terminator != '\0') + { + /* save other commands (those after the ';') for later parsing */ + strp++; + while (isspace(*strp) && (!ISEND(*strp))) strp++; + *remainder = strp; + } + else + *remainder = NULL; + + return TRUE; +} diff --git a/utils/parsetest.c b/utils/parsetest.c new file mode 100644 index 00000000..112c28f6 --- /dev/null +++ b/utils/parsetest.c @@ -0,0 +1,37 @@ + +#include +#include "textio/textio.h" + +#ifndef lint +static char rcsid[] = "$Header: /usr/cvsroot/magic-8.0/utils/parsetest.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +main() +{ + char str[100]; + char *args[4]; + int argCount; + + TxInitTerm(); + + strcpy(str, ""); + + while (strcmp(str,"q") != 0) + { + int i; + + TxPrintf("-->"); + TxGetLine(str, 99); + TxPrintf("Line is '%s'\n", str); + if (!ParsSplit(str, 3, &argCount, args)) + TxError("Parser failed\n"); + + TxPrintf("ARgc = %d\n", argCount); + for (i = 0; i < argCount; i++) + { + TxPrintf(" arg %d: '%s'\n", i, args[i]); + } + } + + TxCloseTerm(); +} diff --git a/utils/path.c b/utils/path.c new file mode 100644 index 00000000..b7f315ad --- /dev/null +++ b/utils/path.c @@ -0,0 +1,692 @@ +/* path.c + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains routines that implement a path mechanism, whereby + * several places may be searched for files. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/path.c,v 1.3 2009/05/13 15:03:18 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "utils/utils.h" + +/* Library routines: */ + +/* extern char *getenv(); */ +/* extern char *strcmp(); */ + +/* A hash table is used to keep track of the logins and variable expansions we've + * already looked up. + */ + +static HashTable expansionTable; +static bool noTable = TRUE; + +/* Limit on how long a single file name may be: */ + +#define MAXSIZE MAXPATHLEN + +/*------------------------------------------------------------------- + * PaAppend -- + * Add a string to the designated path variable. + * + * pathptr is a pointer to the path variable; srcptr is the + * newstring is the new string to append to the path. + */ +void +PaAppend(char **pathptr, char *newstring) +{ + int oldlength, addlength; + char *new; + + oldlength = strlen(*pathptr); + addlength = strlen(newstring); + new = (char *)mallocMagic((unsigned) (oldlength + addlength + 2)); + (void) strcpy(new, *pathptr); + new[oldlength] = ' '; + (void) strcpy(new + oldlength + 1, newstring); + freeMagic(*pathptr); + *pathptr = new; +} + + +/*------------------------------------------------------------------- + * PaExpand -- + * This routine converts tilde notation and environment variable + * notation into standard directory names. + * + * Results: + * If the conversion was done successfully, then the return value + * is the number of bytes of space left in the destination area. + * If a user name couldn't be found in the password file, then + * -1 is returned. + * + * Side Effects: + * If the first character of the string indicated by psource is a + * tilde ("~") then the subsequent user name is converted to a login + * directory name and stored in the string indicated by dest. Then + * remaining characters in the file name at psource are copied to + * pdest (the file name is terminated by white space, a null character, + * or a colon) and psource is updated. Upon return, psource points + * to the terminating character in the source file name, and pdest + * points to the null character terminating the expanded name. + * If a tilde cannot be converted because the user name cannot + * be found, psource is still advanced past the current entry, but + * nothing is stored at the destination. At most size characters + * (including the terminating null character) will be stored at pdest. + * Note: the name "~" with no user name expands to the home directory. + * + * If the first character of the string indicated by psource is a + * dollar sign ("$") then the subsequent name is converted to the + * expansion of the indicated environment variable. If the environment + * variable does not exist and the indicated name is "CAD_ROOT", then + * we substitute the value of CAD_DIR passed down from the Makefile. + * Otherwise, we return error status -1. + * + *------------------------------------------------------------------- + */ + +int +PaExpand(psource, pdest, size) + char **psource; /* Pointer to a pointer to the source string */ + char **pdest; /* Pointer to a ptr to dest string area. */ + int size; /* Number of bytes available at pdest */ + +{ + char *ps, *pd; + struct passwd *passwd, *getpwnam(); + char expandName[100], *string, *newEntry; + HashEntry *h; + int i, length; + + size -= 1; + ps = *psource; + if (*ps == '~') + { + /* Strip off the login name from the front of the file name. */ + + pd = expandName; + for (i=0; ; i++) + { + *pd = *++ps; + if (isspace(*pd) || (*pd=='\0') || (*pd=='/') || (*pd==':')) + break; + if (i < 99) pd++; + } + *pd = '\0'; + + /* Lookup the login name in the hash table. Create a hash + * table if we don't have one already. + */ + + if (noTable) + { + HashInit(&expansionTable, 16, 0); + noTable = FALSE; + } + h = HashFind(&expansionTable, expandName); + string = HashGetValue(h); + if (string != 0) goto gotname; + + /* We haven't seen this name before. Look it up in the + * password file. If the name is "~", then just use the + * home directory. + */ + + if (strcmp(expandName, "") == 0) + string = getenv("HOME"); + else + { + string = NULL; + passwd = getpwnam(expandName); + if (passwd != NULL) string = passwd->pw_dir; + } + if (string != NULL) + { + newEntry = (char *) mallocMagic((unsigned) (strlen(string) + 1)); + (void) strcpy(newEntry, string); + HashSetValue(h, newEntry); + } + else + { + /* No login entry. Skip the rest of the file name. */ + + while ((*ps != '\0') && !isspace(*ps) && (*ps != ':')) ps++; + *psource = ps; + return -1; + } + + gotname: length = strlen(string); + if (length > size) length = size; + (void) strncpy(*pdest, string, length+1); + size -= length; + pd = *pdest+length; + } + else if (*ps == '$') /* (Possible) environment variable expansion */ + { + char saveChar; + + pd = expandName; + for (i=0; ; i++) + { + *pd = *++ps; + if (isspace(*pd) || (*pd=='\0') || (*pd=='/') || (*pd==':')) + break; + if (i < 99) pd++; + } + saveChar = *pd; + *pd = '\0'; + + /* Lookup the environment variable in the hash table. Make a new + * table if we don't have one already. + */ + + if (noTable) + { + HashInit(&expansionTable, 16, 0); + noTable = FALSE; + } + h = HashFind(&expansionTable, expandName); + string = HashGetValue(h); + if (string != 0) goto gotvar; + + /* We haven't seen this name before. Get it with "getenv". + */ + +#ifdef MAGIC_WRAPPER + string = (char *)Tcl_GetVar(magicinterp, expandName, TCL_GLOBAL_ONLY); +#else + string = getenv(expandName); +#endif + + if (string == NULL) + { + /* Check for CAD_ROOT = CAD_DIR, the only internal variable */ + /* recognized (this is passed down from the Makefile) */ + + if (!strcmp(expandName, "CAD_ROOT")) + string = CAD_DIR; + else + { + *pd = saveChar; + ps = *psource; + goto noexpand; + } + } + + newEntry = (char *) mallocMagic((unsigned) (strlen(string) + 1)); + (void) strcpy(newEntry, string); + HashSetValue(h, newEntry); + + gotvar: length = strlen(string); + if (length > size) length = size; + (void) strncpy(*pdest, string, length+1); + size -= length; + pd = *pdest+length; + } + else + { + /* No tilde or variable to expand. As a minor convenience, check + * to see if the first two characters of the name are "./". If so, + * then just skip over them. + */ + +noexpand: + while (ps[0] == '.') + { + if (ps[1] == '/') ps += 2; + else + { + if ((ps[1] == 0) || (ps[1] == ':') || isspace(ps[1])) + ps += 1; + break; + } + } + pd = *pdest; + } + + /* Copy the rest of the directory name from the source to the dest. */ + + while ((*ps != '\0') && !isspace(*ps) && (*ps != ':')) + if (size > 0) + { + *pd++ = *ps++; + size--; + } + else ps++; + *pd = 0; + *psource = ps; + *pdest = pd; + return size; +} + + +/* ---------------------------------------------------------------------------- + * nextName -- + * This local procedure is used to step through a path, adding a + * directory name from the path to a file name. + * + * Results: + * The return value is a pointer to a path-extended name, or + * NULL if the end of the path has been reached. If a tilde + * couldn't be expanded, then a zero-length string is returned. + * + * Side effects: + * The pointer at *ppath is updated to refer to the terminating + * character of the path entry used this time. + * ---------------------------------------------------------------------------- + */ + +char * +nextName(ppath, file, dest, size) + char **ppath; /* Pointer to a pointer to the next + * entry in the path. + */ + char *file; /* Pointer to a file name. */ + char *dest; /* Place to build result name. */ + int size; /* Size of result area. */ + +{ + char *p; + + /* Don't bother with NULL paths */ + if (*ppath == 0) return NULL; + + /* Skip leading blanks and colons. Then make sure that there's + * another entry in the path. + */ + while (isspace(**ppath) || (**ppath == ':')) *ppath += 1; + if (**ppath == 0) return NULL; + + /* Grab the next directory name and terminate it with a slash if + * there isn't one there already. + */ + + p = dest; + dest[size-1] = 0; + size = PaExpand(ppath, &p, size); + if (**ppath) *ppath += 1; /* Skip the terminating character. */ + if (size < 0) + { + dest[0] = 0; + return dest; + } + if ((p != dest) && (*(p-1) != '/')) + { + *p++ = '/'; + size -= 1; + } + if (size < strlen(file)) strncpy(p, file, size); + else strcpy(p, file); + return dest; +} + +/*------------------------------------------------------------------- + * PaLockOpen -- + * This routine does a file lookup using the current path and + * supplying a default extension. + * + * Results: + * A pointer to a FILE, or NULL if the file couldn't be found. + * + * Side Effects: + * If ext is specified, then it is tacked onto the end of + * the given file name. If the first character of the + * file name is "~" or "/" or if nosearch is TRUE, then we try + * to look up the file with the original name, doing tilde + * expansion of course and returning that result. If none of + * these conditions is met, we go through the path trying to + * look up the file once for each path entry by prepending the + * path entry to the original file name. This concatenated name + * is stored in a static string and made available to the caller + * through prealName if the open succeeds. If the entire path is + * tried, and still nothing works, then we try each entry in the + * library path next. + * Note: the static string will be trashed on the next call to this + * routine. Also, note that no individual file name is allowed to + * be more than MAXSIZE characters long. Excess characters are lost. + * + * Path Format: + * A path is a string containing directory names separated by + * colons or white space. Tilde notation may be used within paths. + *------------------------------------------------------------------- + */ + +FILE * +PaLockOpen(file, mode, ext, path, library, pRealName, is_locked) + char *file; /* Name of the file to be opened. */ + char *mode; /* The file mode, as given to fopen. */ + char *ext; /* The extension to be added to the file name, + * or NULL. Note: this string must include + * the dot (or whatever separator you use). + */ + char *path; /* A search path: a list of directory names + * separated by colons or blanks. To use + * only the working directory, use "." for + * the path. + */ + char *library; /* A 2nd path containing library names. Can be + * NULL to indicate no library. + */ + char **pRealName; /* Pointer to a location that will be filled + * in with the address of the real name of + * the file that was successfully opened. + * If NULL, then nothing is stored. + */ + bool *is_locked; /* Pointer to a location to store the result + * of the attempt to grab an advisory lock + * on the file. If NULL, then nothing is + * stored. + */ +{ + char extendedName[MAXSIZE], *p1, *p2; + static char realName[MAXSIZE]; + int length, extLength, i; + FILE *f; + + if (file == NULL) return (FILE *) NULL; + if (file[0] == '\0') return (FILE *) NULL; + if (pRealName != NULL) (*pRealName) = realName; + + /* See if we must supply an extension. */ + + length = strlen(file); + if (length >= MAXSIZE) length = MAXSIZE - 1; + if (ext != NULL) + { + (void) strncpy(extendedName, file, length + 1); + i = MAXSIZE - 1 - length; + extLength = strlen(ext); + if (extLength > i) extLength = i; + + /* (Modified by Tim, 1/13/2015; assume that "file" has */ + /* the extension already stripped, therefore always add */ + /* the extension if one is specified. This allows the */ + /* code to distinguish between, say, "a.mag" and */ + /* "a.mag.mag".) */ + + /* If the extension is already on the name, don't add it */ + // if ((length < extLength) || ((extLength > 0) + // && (strcmp(ext, file + length - extLength)))) + + (void) strncpy(&(extendedName[length]), ext, extLength + 1); + + extendedName[MAXSIZE-1] = '\0'; + file = extendedName; + } + + /* If the first character of the file name is a tilde or dollar sign, + * do tilde or environment variable expansion but don't touch a search + * path. + */ + + if (file[0] == '~' || file[0] == '$') + { + p1 = realName; + p2 = file; + if (PaExpand(&p2, &p1, MAXSIZE) < 0) return NULL; + +#ifndef FILE_LOCKS + return fopen(realName, mode); +#else + return flock_open(realName, mode, is_locked); +#endif + } + + /* If we were already given a full rooted file name, + * or a relative pathname, just use it. + */ + + if (file[0] == '/' + || (file[0] == '.' && (strcmp(file, ".") == 0 + || strncmp(file, "./", 2) == 0 + || strcmp(file, "..") == 0 + || strncmp(file, "../", 3) == 0))) + { + (void) strncpy(realName, file, MAXSIZE-1); + realName[MAXSIZE-1] = '\0'; +#ifndef FILE_LOCKS + return fopen(realName, mode); +#else + return flock_open(realName, mode, is_locked); +#endif + } + + /* Now try going through the path, one entry at a time. */ + + while (nextName(&path, file, realName, MAXSIZE) != NULL) + { + if (*realName == 0) continue; +#ifndef FILE_LOCKS + f = fopen(realName, mode); +#else + f = flock_open(realName, mode, is_locked); +#endif + if (f != NULL) return f; + + // If any error other than "file not found" occurred, + // then halt immediately. + if (errno != ENOENT) return NULL; + } + + /* We've tried the path and that didn't work. Now go through + * the library area, one entry at a time. + */ + + if (library == NULL) return NULL; + while (nextName(&library, file, realName, MAXSIZE) != NULL) + { +#ifndef FILE_LOCKS + f = fopen(realName, mode); +#else + f = flock_open(realName, mode, is_locked); +#endif + if (f != NULL) return f; + + // If any error other than "file not found" occurred, + // then halt immediately. + if (errno != ENOENT) return NULL; + } + + return NULL; +} + +/* + *------------------------------------------------------------------- + * PaOpen -- + * This is a wrapper for PaLockOpen() that is backwardly- + * compatible with the original (non-file-locking) PaOpen(), + * and is here because it's a pain to add an extra argument + * to every call to PaOpen() when only .mag files are locked. + * + * Results: + * See PaLockOpen() + * + * Side Effects: + * See PaLockOpen() + * + *------------------------------------------------------------------- + */ + +FILE * +PaOpen(file, mode, ext, path, library, pRealName) + char *file; /* Name of the file to be opened. */ + char *mode; /* The file mode, as given to fopen. */ + char *ext; /* The extension to be added to the file name, + * or NULL. Note: this string must include + * the dot (or whatever separator you use). + */ + char *path; /* A search path: a list of directory names + * separated by colons or blanks. To use + * only the working directory, use "." for + * the path. + */ + char *library; /* A 2nd path containing library names. Can be + * NULL to indicate no library. + */ + char **pRealName; /* Pointer to a location that will be filled + * in with the address of the real name of + * the file that was successfully opened. + * If NULL, then nothing is stored. + */ +{ + return PaLockOpen(file, mode, ext, path, library, pRealName, NULL); +} + +/* + * ---------------------------------------------------------------------------- + * PaSubsWD -- + * + * Replaces all uses of the working directory in a path + * by some fixed directory. + * + * Results: + * The return result is a path that is just like the path + * argument except that every implicit or explicit use of + * the working directory is replaced by the newWD argument. + * The result is a static array, which will be trashed on + * the next call to this procedure. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +char * +PaSubsWD(path, newWD) +char *path; /* Path in which to substitute. */ +char *newWD; /* New working directory to be used. Must + * end in a slash. + */ + +{ +#define NEWPATHSIZE 1000 + static char newPath[NEWPATHSIZE]; + char *pOld, *pNew, *pWD; + int spaceLeft; + + pOld = path; + pNew = newPath; + spaceLeft = NEWPATHSIZE; + + while (TRUE) + { + /* Scan through the old path, copying separators to the new + * path until getting the first character of the directory. + */ + + while (isspace(*pOld) || (*pOld == ':')) + { + if (spaceLeft <= 0) goto subsDone; + spaceLeft -= 1; + *pNew++ = *pOld++; + } + + /* If the first character of the directory isn't a "/", "$", or "~", + * then add in the new directory name in front of it in newPath. + */ + + if ((*pOld != '/') && (*pOld != '~') && (*pOld != '$') && (*pOld != 0)) + { + pWD = newWD; + while (*pWD != 0) + { + if (spaceLeft <= 0) goto subsDone; + spaceLeft -= 1; + *pNew++ = *pWD++; + } + } + + /* Add in the rest of the path entry from the old path to the new. */ + + while ((!isspace(*pOld)) && (*pOld != ':') && (*pOld != 0)) + { + if (spaceLeft <= 0) goto subsDone; + spaceLeft -= 1; + *pNew++ = *pOld++; + } + + /* See if we're done. */ + + if (*pOld == 0) break; + } + + subsDone: if (spaceLeft > 0) *pNew = 0; + else newPath[NEWPATHSIZE-1] = 0; + return newPath; +} + +/* + * ---------------------------------------------------------------------------- + * PaEnum -- + * + * Call a client procedure with each directory in a path + * prepended to a filename. The client procedure is as + * follows: + * + * int + * (*proc)(name, cdata) + * char *name; /# A directory in the path prepended to + * # a file name. + * #/ + * ClientData *cdata; /# Provided by caller #/ + * { + * } + * + * The client procedure should return 0 normally, or 1 to abort + * the path enumeration. If a directory in the search path + * refers to a non-existent user name (using the ~user syntax), + * we skip that component. + * + * Results: + * Returns 0 if all the clients returned 0, or 1 if + * some client returned 1. When a client returns 1 + * we abort the enumeration. + * + * Side effects: + * Calls the client procedure. + * + * ---------------------------------------------------------------------------- + */ + +int +PaEnum(path, file, proc, cdata) + char *path; /* Search path */ + char *file; /* Each element of the search path is prepended to + * this file name and passed to the client. + */ + int (*proc)(); /* Client procedure */ + ClientData cdata; /* Passed to (*proc)() */ +{ + char component[MAXSIZE], *next; + + while (next = nextName(&path, file, component, sizeof component)) + if (next[0] && (*proc)(next, cdata)) + return (1); + + return (0); +} diff --git a/utils/paths.h b/utils/paths.h new file mode 100644 index 00000000..87ab80da --- /dev/null +++ b/utils/paths.h @@ -0,0 +1,74 @@ +/* + * paths.h -- + * + * Definitions of Unix filename paths used by Magic and related utility + * programs. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid="$Header" + */ + +#ifndef _PATHS_H +#define _PATHS_H + +/* + * Paths used by 'ext2sim' and 'magicusage'. + * + */ + +#define EXT_PATH "$CAD_ROOT/magic/%s $CAD_ROOT/magic/tutorial" +#define DOT_MAGIC_PATH "$CAD_ROOT/magic/sys ~ ." + +/* + * Paths used by 'magic'. + * + */ +#define MAGIC_CMOS_PATH "$CAD_ROOT/magic/cmos $CAD_ROOT/magic/tutorial" +#define MAGIC_NMOS_PATH "$CAD_ROOT/magic/nmos $CAD_ROOT/magic/tutorial" +#define MAGIC_SYS_PATH ". $CAD_ROOT/magic/sys $CAD_ROOT/magic/sys/current" +#define MAGIC_SYS_DOT "$CAD_ROOT/magic/sys/.magicrc" +#define MAGIC_PRE_DOT "$CAD_ROOT/magic/sys/.initrc" +#define MAGIC_LIB_PATH "$CAD_ROOT/magic/%s $CAD_ROOT/magic/tutorial" +#define HELPER_PATH ". BIN_DIR" /* Used by graphics drivers */ + +/* + * Path to default pager + */ +#ifdef SYSV +# ifdef hpux +# define PAGERDIR "/usr/bin/more" +# else +# ifdef linux +# define PAGERDIR "/bin/more" +# else +# define PAGERDIR "/usr/bin/pg" +# endif +# endif +#else +# if defined(linux) || defined(__FreeBSD__) +# define PAGERDIR "/usr/bin/more" +# elif defined(CYGWIN) +# define PAGERDIR "./less" +# else +# define PAGERDIR "/usr/ucb/more" +# endif +#endif + +/* + * Other common paths. + */ +#define CAD_LIB_PATH ". $CAD_ROOT/" + +#endif /* _PATHS_H */ diff --git a/utils/pathvisit.c b/utils/pathvisit.c new file mode 100644 index 00000000..a56bd675 --- /dev/null +++ b/utils/pathvisit.c @@ -0,0 +1,299 @@ +/* + * pathvisit.c + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains several procedures to implement a means of scanning + * all files in a search path, calling client procedures when lines match + * a specified pattern. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/pathvisit.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/hash.h" +#include "utils/malloc.h" +#include "utils/pathvisit.h" +#include "utils/utils.h" + + +/* + * ------------------------------------------------------------------- + * + * PaVisitInit -- + * + * Return a newly allocated client structure that may be passed to + * PaVisitAddClient and PaVisitFiles. + * + * Results: + * Returns a pointer to a newly allocated PaVisit struct. + * + * Side Effects: + * Allocates memory. + * PaVisitFree should be called when done. + * + * ------------------------------------------------------------------- + */ + +PaVisit * +PaVisitInit() +{ + PaVisit *pv; + + pv = (PaVisit *) mallocMagic((unsigned) (sizeof (PaVisit))); + pv->pv_first = pv->pv_last = (PaVisitClient *) NULL; + return (pv); +} + +/* + * ------------------------------------------------------------------- + * + * PaVisitFree -- + * + * Frees all memory associated with the argument PaVisit struct. + * + * Results: + * None. + * + * Side Effects: + * Deallocates memory. + * + * ------------------------------------------------------------------- + */ + +void +PaVisitFree(pv) + PaVisit *pv; +{ + PaVisitClient *pvc; + + for (pvc = pv->pv_first; pvc; pvc = pvc->pvc_next) + { + if (pvc->pvc_keyword) + freeMagic(pvc->pvc_keyword); + freeMagic((char *) pvc); + } + + freeMagic((char *) pv); +} + +/* + * ------------------------------------------------------------------- + * + * PaVisitAddClient -- + * + * Add keywords and client procedures to the list that will be applied + * by PaVisitFiles. For each line in the files found by PaVisitFiles + * that matches this keyword, we call the client procedure: + * + * (*proc)(line, cdata) + * char *line; + * ClientData cdata; + * { + * } + * + * This procedure should return 0 if PaVisitFiles should continue + * processing, 1 if PaVisitFiles should stop processing completely, + * and 2 if PaVisitFiles should stop processing just this file but + * continue to the next file in the list. + * + * Results: + * None. + * + * Side Effects: + * Modifies the PaVisit struct pointed to by 'pv' by adding a + * new client to its list. + * + * ------------------------------------------------------------------- + */ + +void +PaVisitAddClient(pv, keyword, proc, cdata) + PaVisit *pv; + char *keyword; + int (*proc)(); + ClientData cdata; +{ + PaVisitClient *pvc; + + pvc = (PaVisitClient *) mallocMagic((unsigned) (sizeof (PaVisitClient))); + pvc->pvc_keyword = StrDup((char **) NULL, keyword); + pvc->pvc_proc = proc; + pvc->pvc_cdata = cdata; + pvc->pvc_next = (PaVisitClient *) NULL; + if (pv->pv_last) + { + pv->pv_last->pvc_next = pvc; + pv->pv_last = pvc; + } + else + { + pv->pv_first = pv->pv_last = pvc; + } +} + +/* + * ------------------------------------------------------------------- + * + * PaVisitFiles -- + * + * PaVisitFiles will be used to visit all files in a search path. + * For each such file, all lines matching one of the keywords supplied + * to PaVisitAddClient will be passed along to a client procedure that + * corresponds to that keyword. + * + * Lines in each of the input files that end in a backslash have the + * following line appended to them and the backslash ignored. + * + * Results: + * Returns 0 if all files were visited. Returns 1 if some + * client aborted the search by returning 1. + * + * Side Effects: + * Applies all the client procedures in the PaVisitClient + * list of pv to each line matching one of the client patterns. + * + * ------------------------------------------------------------------- + */ + +int +PaVisitFiles(path, file, pv) + char *path; /* Colon or space separated list of directories to + * search for the file 'file'. If 'file' does not + * exist in a given directory, that directory is + * skipped. + */ + char *file; /* If 'file' exists in a directory of 'path' we + * open it and match each line against the list + * of clients pointed to by 'pv'. + */ + PaVisit *pv; +{ + int paVisitFilesProc(); + + /* Do no work if degenerate */ + if (pv->pv_first == (PaVisitClient *) NULL) + return (0); + + return (PaEnum(path, file, paVisitFilesProc, (ClientData) pv)); +} + +/* + * + * paVisitFilesProc -- + * + * Process each file in the path supplied to PaVisitFiles above. + * If the file 'name' exists, we open it and process each line + * as described in PaVisitFiles above. + * + * Results: + * Returns 0 if the file 'name' doesn't exist, or if it does + * exist and all the clients returned 0. If a client returns + * 2, we abort processing this file but still return 0. If a + * client returns 1, we abort processing and return 1 to abort + * the remainder of the path search. + * + * Side Effects: + * Applies all the client procedures in the PaVisitClient + * list of pv to each line matching one of the client patterns. + * + * ------------------------------------------------------------------- + */ + +int +paVisitFilesProc(name, pv) + char *name; /* Full filename */ + PaVisit *pv; /* Points to list of clients */ +{ + char *lp; + char line[BUFSIZ+2]; + int code = 0; + FILE *f; + + f = fopen(name, "r"); + if (f == NULL) + return (0); + + lp = line; + while (fgets(lp, BUFSIZ - (lp - line), f)) + { + while (*lp && *lp != '\n') + { + if (*lp++ == '\\' && *lp == '\n') + { + *--lp = '\0'; + goto next; + } + } + *lp = '\0'; + if (code = paVisitProcess(lp = line, pv)) + break; +next: ; + } + + if (lp != line) + code = paVisitProcess(line, pv); + + (void) fclose(f); + if (code == 1) + return (1); + return (0); +} + +/* + * ------------------------------------------------------------------- + * + * paVisitProcess -- + * + * Process an extended line from an input file. If the initial part + * (up to the first white space) matches one of the keywords in the + * client list pv->pv_first, we apply the associated procedure. + * + * Results: + * Returns the result of applying the first client procedure + * that returns a non-zero result, or zero if all clients + * return zero. If there is no match, we return 0. + * + * Side Effects: + * Applies all the client procedures in the PaVisitClient + * whose keywords match 'line'. + * + * ------------------------------------------------------------------- + */ + +int +paVisitProcess(line, pv) + char *line; + PaVisit *pv; +{ + PaVisitClient *pvc; + char *cp; + int code = 0, len; + + for (cp = line; *cp && !isspace(*cp); cp++) + /* Nothing */; + len = cp - line; + + for (pvc = pv->pv_first; pvc; pvc = pvc->pvc_next) + if (len > 0 && strncmp(line, pvc->pvc_keyword, len) == 0) + if (code = (*pvc->pvc_proc)(line, pvc->pvc_cdata)) + break; + + return (code); +} diff --git a/utils/pathvisit.h b/utils/pathvisit.h new file mode 100644 index 00000000..eeda3452 --- /dev/null +++ b/utils/pathvisit.h @@ -0,0 +1,44 @@ +/* + * pathvisit.h -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file defines the PaVisit structure used by pathvisit.c. + */ + +/* rcsid "$Header: /usr/cvsroot/magic-8.0/utils/pathvisit.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" */ + +#ifndef _PATHVISIT_H +#define _PATHVISIT_H + +/* Each client will match words beginning with a particular keyword */ +typedef struct pvc +{ + struct pvc *pvc_next; /* Next client in list */ + char *pvc_keyword; /* Initial keyword */ + int (*pvc_proc)(); /* Procedure to call for lines matching + * pvc_keyword. + */ + ClientData pvc_cdata; /* Client data passed to above procedure */ +} PaVisitClient; + +/* Each of these has a list of the above clients */ +typedef struct +{ + PaVisitClient *pv_first; /* First client in list */ + PaVisitClient *pv_last; /* Last client in list */ +} PaVisit; + +PaVisit *PaVisitInit(); + +#endif /* _PATHVISIT_H */ diff --git a/utils/port.c b/utils/port.c new file mode 100644 index 00000000..7b54fad4 --- /dev/null +++ b/utils/port.c @@ -0,0 +1,54 @@ +/* port.c + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file contains routines that are needed when porting between machines. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/port.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/hash.h" +#include "utils/malloc.h" + +/*------------------------------------------------------------------- + * MagAtof -- + * Magic's own atof function. + * Convert a string to a single-precision floating point number. + * + * Results: + * A floating point number. + * + * Special Features: + * No error is produced if the string isn't a valid number. + *------------------------------------------------------------------- + */ + +float +MagAtof(s) + char *s; +{ +#ifdef linux + float flt; + if (sscanf(s, "%f", &flt) == 1) return flt; + else return (float)(-1.0); +#else + return (float)atof(s); +#endif +} diff --git a/utils/printstuff.c b/utils/printstuff.c new file mode 100644 index 00000000..81477c15 --- /dev/null +++ b/utils/printstuff.c @@ -0,0 +1,24 @@ +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/printstuff.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" + +void +PrintTrans(t) + Transform *t; +{ + printf("Translate: (%d, %d)\n", t->t_c, t->t_f); + printf("%d\t%d\n", t->t_a, t->t_d); + printf("%d\t%d\n", t->t_b, t->t_e); +} + +void +PrintRect(r) + Rect *r; +{ + printf("(%d,%d) :: (%d,%d)\n", r->r_xbot, r->r_ybot, r->r_xtop, r->r_ytop); +} diff --git a/utils/runstats.c b/utils/runstats.c new file mode 100644 index 00000000..602618b5 --- /dev/null +++ b/utils/runstats.c @@ -0,0 +1,219 @@ +/* + * runstats.c - + * + * This file provides a single procedure that returns a string + * containing the amount of user and system time used so far, + * as well as the size of the data area. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/runstats.c,v 1.2 2009/05/13 15:03:18 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "utils/magic.h" +#include "utils/runstats.h" + +/* Library imports: */ + +#ifndef __APPLE__ +extern char *sbrk(); +extern int end; +#else +#ifndef CYGWIN +extern void *sbrk(); +int end; +#endif +#endif + +/* + * ---------------------------------------------------------------------------- + * + * RunStats -- + * + * This procedure collects information about the process. + * Depending on the flags provided, the following information is + * returned: + * + * RS_TCUM -- cumulative user and system time + * RS_TINCR -- difference between current cumulative user and system + * time and that when RunStats was last called with RS_TINCR + * as a flag. + * RS_MEM -- number of bytes in the heap area. + * + * Results: + * The return value is a string of the form "[ ... ...]", + * where contains the information specified by the flags. + * Times are of the form "mins:secsu mins:secss", where the first + * time is the amount of user-space CPU time this process has + * used, and the second time is the amount of system time used. + * Memory is specified by a string of the form "Nk", where N + * is the number of kilobytes of heap area used so far. + * + * Side Effects: + * If RS_TINCR is specified, the parameters lastt and deltat + * are set (if they are both non-NULL). Both point to tms structs; + * the one pointed to by deltat is set to the difference between + * the current user/system time and the time given in the tms struct + * pointed to by lastt; the one pointed to by lastt is then set to + * the current user/system time. + * + * ---------------------------------------------------------------------------- + */ + +char * +RunStats(flags, lastt, deltat) + int flags; + struct tms *lastt, *deltat; +{ + struct tms buffer; + static char string[100]; + int umins, usecs, smins, ssecs, udsecs, sdsecs; + pointertype size; + char *sp = string; + + *sp = '\0'; + times(&buffer); + if (flags & RS_TCUM) + { + umins = buffer.tms_utime; + umins = (umins+30)/60; + usecs = umins % 60; + umins = umins/60; + smins = buffer.tms_stime; + smins = (smins+30)/60; + ssecs = smins % 60; + smins = smins/60; + sprintf(sp, "%d:%02du %d:%02ds", umins, usecs, smins, ssecs); + while (*sp) sp++; + } + + if (flags & RS_TINCR) + { + umins = buffer.tms_utime - lastt->tms_utime; + udsecs = umins % 6; + umins = (umins+30)/60; + usecs = umins % 60; + umins = umins/60; + smins = buffer.tms_stime - lastt->tms_stime; + sdsecs = smins % 6; + smins = (smins+30)/60; + ssecs = smins % 60; + smins = smins/60; + + if (deltat != (struct tms *) NULL) + { + deltat->tms_utime = buffer.tms_utime - lastt->tms_utime; + deltat->tms_stime = buffer.tms_stime - lastt->tms_stime; + lastt->tms_utime = buffer.tms_utime; + lastt->tms_stime = buffer.tms_stime; + } + + if (sp != string) + *sp++ = ' '; + sprintf(sp, "%d:%02d.%du %d:%02d.%ds", umins, usecs, udsecs, + smins, ssecs, sdsecs); + while (*sp) sp++; + } + +#ifndef CYGWIN + // Ignoring this under cygwin instead of trying to find a workaround + if (flags & RS_MEM) + { + size = (((pointertype)sbrk(0) - (pointertype) &end) + 512)/1024; + if (sp != string) + *sp++ = ' '; + sprintf(sp, "%dk", (int)size); + } +#endif + + return (string); +} + +/* + * ---------------------------------------------------------------------------- + * + * RunStatsRealTime -- + * + * Reports the real time, both since the first invocation and incremental + * since the last invocation. + * + * Results: + * A statically allocated string of the form: + * x:xx.x x:xx.x + * where the first number is the amount of elapsed real time since the + * first call to this routine, and the second is the amount of elapsed + * real time since the lastest call to this routine. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +char * +RunStatsRealTime() +{ + struct timeval curtime; + static struct timeval firsttime, lasttime; + static int havetime = 0; + long totm, tots, tott, incm, incs, inct; + struct timezone dummyz; + static char buf[50]; + + gettimeofday(&curtime, &dummyz); + if (!havetime) + { + havetime = 1; + firsttime = curtime; + lasttime = curtime; + } + + /* + * Compute time differences in minutes, seconds, and tenths. + */ + + totm = (curtime.tv_sec - firsttime.tv_sec) / 60; + tots = (curtime.tv_sec - firsttime.tv_sec) % 60; + tott = curtime.tv_usec - firsttime.tv_usec; + + while (tott < 0) { tots--; tott += 1000000; } + while (tots < 0) { tots += 60; totm--; } + tott = (tott + 50000) / 100000; + while (tott >= 10) { tott -= 10; tots++; } + while (tots >= 60) { tots -= 60; totm++; } + + incm = (curtime.tv_sec - lasttime.tv_sec) / 60; + incs = (curtime.tv_sec - lasttime.tv_sec) % 60; + inct = curtime.tv_usec - lasttime.tv_usec; + + while (inct < 0) { incs--; inct += 1000000; } + while (incs < 0) { incs += 60; incm--; } + inct = (inct + 50000) / 100000; + while (inct >= 10) { inct -= 10; incs++; } + while (incs >= 60) { incs -= 60; incm++; } + + sprintf(buf, "%ld:%02ld.%ld %ld:%02ld.%ld", + totm, tots, tott, incm, incs, inct); + + lasttime = curtime; + + return buf; +} + diff --git a/utils/runstats.h b/utils/runstats.h new file mode 100644 index 00000000..219534bf --- /dev/null +++ b/utils/runstats.h @@ -0,0 +1,31 @@ +/* + * runstats.h -- + * + * Flags to RunStats() + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/utils/runstats.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + */ + +#ifndef _RUNSTATS_H +#define _RUNSTATS_H + +#define RS_TCUM 01 /* Cumulative user and system time */ +#define RS_TINCR 02 /* User and system time since last call */ +#define RS_MEM 04 /* Size of heap area */ + +extern char *RunStats(); +extern char *RunStatsRealTime(); + +#endif /* _RUNSTATS_H */ diff --git a/utils/set.c b/utils/set.c new file mode 100644 index 00000000..c91532da --- /dev/null +++ b/utils/set.c @@ -0,0 +1,198 @@ +/* set.c - + * + * Generic routines for setting (from a string) and printing + * parameter values. Error messages are printed for invalid + * input strings. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/set.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/utils.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/list.h" + + +/* + * ---------------------------------------------------------------------------- + * + * SetNoisy -- + * + * Set parameter and print current value. + * + * Results: + * None. SetNoisyBool() now returns -2 on error, -1 ambiguous + * (but what's ambiguous about true/false??), 0 on success. All + * of these routines should do the same! + * + * Side effects: + * If valueS is a nonnull string, interpret as and set parm + * accordingly. + * + * If valueS is null, the parameter value is left unaltered. + * + * If file is nonnull parameter value is written to file. + * + * If file is null, parameter value is written to magic text window via + * TxPrintf + * + * ---------------------------------------------------------------------------- + */ + +/* SetNoisyInt -- */ +void +SetNoisyInt(parm,valueS,file) + int *parm; + char *valueS; + FILE *file; +{ + + /* If value not null, set parm */ + if (valueS) + { + if(!StrIsInt(valueS)) + { + TxError("Noninteger value for integer parameter (\"%.20s\") ignored.\n", + valueS); + } + else + { + *parm = atoi(valueS); + } + } + + /* Print parm value */ + if(file) + fprintf(file,"%8d ", *parm); + else + TxPrintf("%8d ", *parm); + + return; +} + +/* SetNoisyBool -- */ + +int +SetNoisyBool(parm,valueS,file) + bool *parm; + char *valueS; + FILE *file; +{ + int n, which, result; + + /* Bool string Table */ + static struct + { + char *bS_name; /* name */ + bool bS_value; /* procedure processing this parameter */ + } boolStrings[] = { + "yes", TRUE, + "no", FALSE, + "true", TRUE, + "false", FALSE, + "1", TRUE, + "0", FALSE, + "on", TRUE, + "off", FALSE, + 0 + }; + + /* If value not null, set parm */ + if (valueS) + { + /* Lookup value string in boolString table */ + which = LookupStruct( + valueS, + (LookupTable *) boolStrings, + sizeof boolStrings[0]); + + /* Process result of lookup */ + if (which >= 0) + { + /* string found - set parm */ + *parm = boolStrings[which].bS_value; + result = 0; + } + else if (which == -1) + { + /* ambiguous boolean value - complain */ + TxError("Ambiguous boolean value: \"%s\"\n", + valueS); + result = -1; + } + else + { + TxError("Unrecognized boolean value: \"%s\"\n", valueS); + TxError("Valid values are: "); + for (n = 0; boolStrings[n].bS_name; n++) + TxError(" %s", boolStrings[n].bS_name); + TxError("\n"); + result = -2; + } + } + + /* Print parm value */ + if(file) + fprintf(file,"%8.8s ", *parm ? "YES" : "NO"); + else + TxPrintf("%8.8s ", *parm ? "YES" : "NO"); + + return result; +} + +/* SetNoisyDI -- */ +/* double size non-negative integer */ +void +SetNoisyDI(parm,valueS,file) + dlong *parm; /* BY NP */ + char *valueS; + FILE *file; +{ + /* If value not null, set parm */ + if (valueS) + { + if(!StrIsInt(valueS)) + { + TxError("Noninteger value for integer parameter (\"%.20s\") ignored.\n", + valueS); + } + else + { + /* BY NP */ + *parm = (dlong)atoi(valueS); + } + } + + /* Print parm value */ + { + if(file) + { + fprintf(file,"%.0f ", (double) (*parm)); /* BY NP */ + } + else + { + TxPrintf("%.0f ", (double) (*parm)); /* BY NP */ + } + } + return; +} diff --git a/utils/show.c b/utils/show.c new file mode 100644 index 00000000..8d373d47 --- /dev/null +++ b/utils/show.c @@ -0,0 +1,91 @@ +/* show.c - + * + * Routines for displaying rects with highlights etc. Useful for + * debugging. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/show.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "utils/hash.h" +#include "tiles/tile.h" +#include "database/database.h" +#include "dbwind/dbwind.h" + + +/* + * ---------------------------------------------------------------------------- + * + * ShowRect -- + * + * Show an area in the cell 'def', for debugging the maze router. + * In this implementation, the area is only displayed in windows + * where 'def' is the root cell. + * + * Results: + * None. + * + * Side effects: + * See above. + * Because this procedure bypasses the normal display package, + * it can leave data on the screen messed up. Callers should + * use styles that affect only the highlight layer to minimize + * the amount of damage. + * + * ---------------------------------------------------------------------------- + */ + +int ShowRectStyle; +CellDef *ShowRectDef; + +void +ShowRect(def, r, style) + CellDef *def; /* The area is in this def */ + Rect *r; /* Display this area (in coords of def above) */ + int style; /* in this style */ +{ + int ShowRectFunc(); + + ShowRectDef = def; + ShowRectStyle = style; + (void) WindSearch(DBWclientID, (ClientData) NULL, r, ShowRectFunc, + (ClientData) r); +} + +int +ShowRectFunc(w, r) + MagWindow *w; + Rect *r; +{ + Rect screenRect; + + /* Skip if desired def is not root of window */ + if (((CellUse *) w->w_surfaceID)->cu_def != ShowRectDef) + return (0); + + WindSurfaceToScreen(w, r, &screenRect); + GrLock(w, TRUE); + GrClipBox(&screenRect, ShowRectStyle); + GrUnlock(w); + (void) GrFlush(); + return (0); +} diff --git a/utils/signals.c b/utils/signals.c new file mode 100644 index 00000000..dcc547bd --- /dev/null +++ b/utils/signals.c @@ -0,0 +1,693 @@ +/* + * signals.c -- + * + * Handles signals, such as stop, start, interrupt. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/signals.c,v 1.2 2010/03/08 13:33:34 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include /* for getpid() */ +#include + +#include "utils/main.h" + +#ifndef SIGEMT +#define SIGEMT 7 /* EMT instruction (SIGUNUSED) */ +#endif + +#ifndef SIGBUS +#define SIGBUS 10 /* bus error (SIGUSR1) */ +#endif + +#ifndef SIGSYS +#define SIGSYS 12 /* bad argument to system call (SIGUSR2) */ +#endif + +#if !defined(SIGIOT) && defined(SIGABRT) +#define SIGIOT SIGABRT /* io-trap signal redefined */ +#endif + +#ifdef linux +#if SIGBUS == SIGUNUSED +#undef SIGBUS +#define SIGBUS SIGUSR1 +#endif + +#if SIGSYS == SIGUNUSED +#undef SIGSYS +#define SIGSYS SIGUSR2 +#endif +#endif + +#include + +#include "utils/magic.h" +#include "utils/magsgtty.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "utils/signals.h" +#include "windows/windows.h" +#include "graphics/graphics.h" + + +#ifndef FASYNC +# define FASYNC 00100 /* kludge for SUN2s */ +#endif + +/* specially imported */ +extern bool DBWriteBackup(); + +/* macs support BSD4.2 signals, so turn off the SYSV flag for this module */ +#ifdef __APPLE__ +#undef SYSV +#endif + +void sigSetAction(int, sigRetVal (*)(int)); + +/* becomes true when we get an interrupt */ +global bool SigInterruptPending = FALSE; + +/* Becomes true when IO is possible on one of the files passed to SigWatchFile. + * Spurious signals are sometimes generated -- use select() to make + * sure that what you want is really there. + */ +global bool SigIOReady = FALSE; + +/* If set to 1, we will set SigInterruptPending whenever we set SigIOReady. */ +/* If set to -1, then SigInterruptPending is never set */ +global char SigInterruptOnSigIO; + +/* + * Set to true when we recieve a SIGWINCH/SIGWINDOW signal + * (indicating that a window has changed size or otherwise needs attention). + */ +global bool SigGotSigWinch = FALSE; + + +/* + * Local data structures + */ +static bool sigInterruptReceived = FALSE; +static int sigNumDisables = 0; + +/*--------------------------------------------------------- + * While we can conveniently run Ctrl-C interrupts from + * the terminal at any time, we can't do this from the + * window in Tcl/Tk because the GUI event handler is not + * a separate process. So we run a timer process during + * WindUpdate() which periodically processes Tk events + * in the window. + * + * This timer can be set for "secs" second intervals. If + * "secs" is zero, it defaults to a 1/4 second interval. + *--------------------------------------------------------- + */ + +void +SigSetTimer(int secs) +{ + struct itimerval subsecond; /* one-quarter second interval */ + + /* + if (GrDisplayStatus == DISPLAY_IDLE) + fprintf(stderr, "Timer start\n"); + else + fprintf(stderr, "Timer repeat\n"); + fflush(stderr); + */ + + subsecond.it_interval.tv_sec = 0; + subsecond.it_interval.tv_usec = 0; + subsecond.it_value.tv_sec = secs; + subsecond.it_value.tv_usec = (secs == 0) ? 250000 : 0; + + setitimer(ITIMER_REAL, &subsecond, NULL); +} + +/*---------------------------*/ +/* Remove any existing timer */ +/*---------------------------*/ + +void +SigRemoveTimer() +{ + struct itimerval zero; /* zero time to stop the timer */ + + /* fprintf(stderr, "Timer stop\n"); fflush(stderr); */ + + zero.it_value.tv_sec = 0; + zero.it_value.tv_usec = 0; + zero.it_interval.tv_sec = 0; + zero.it_interval.tv_usec = 0; + + setitimer(ITIMER_REAL, &zero, NULL); +} + +sigRetVal +sigOnAlarm(int signo) +{ + if (GrDisplayStatus == DISPLAY_IN_PROGRESS) + GrDisplayStatus = DISPLAY_BREAK_PENDING; + + sigReturn; +} + +/*-----------------------------------------*/ +/* Set timer to act as a display interrupt */ +/*-----------------------------------------*/ + +void +SigTimerDisplay() +{ + sigSetAction(SIGALRM, sigOnAlarm); +} + +/*------------------------------------------*/ +/* Set timer to act like a Ctrl-C interrupt */ +/*------------------------------------------*/ + +void +SigTimerInterrupts() +{ + sigSetAction(SIGALRM, sigOnInterrupt); +} + +/*--------------------------------------------------------- + * sigOnStop: + * This procedure handles stop signals. + * + * Results: + * sigReturn result (see signals.h) + * + * Side Effects: + * The text display is reset, and we stop + *--------------------------------------------------------- + */ + +sigRetVal +sigOnStop(int signo) +{ + /* fix things up */ + TxResetTerminal(); + GrStop(); + + /* restore the default action and resend the signal */ + + sigSetAction(SIGTSTP, SIG_DFL); + kill(getpid(), +#ifdef linux + SIGSTOP +#else + SIGTSTP +#endif + ); + + /* -- we stop here -- */ + + /* NOTE: The following code really belongs in a routine that is + * called in response to a SIGCONT signal, but it doesn't seem to + * work that way. Maybe there is a Unix bug with this??? + */ + + GrResume(); + TxSetTerminal(); + TxReprint(); + + /* catch future stops now that we have finished resuming */ + + sigSetAction(SIGTSTP, sigOnStop); + sigReturn; +} + +/* + *--------------------------------------------------------- + * SigCheckProcess --- + * + * Check if a process exists by sending it a signal. + * Perhaps there are better ways to do this? + * + * Results: + * TRUE if the process exists, FALSE if not. + * + * Side effects: + * Whatever happens when the process gets SIGCONT; + * hopefully nothing. + *--------------------------------------------------------- + */ + +bool +SigCheckProcess(pid) + int pid; +{ + int result; + result = kill((pid_t)pid, SIGCONT); + + if (result == 0) return TRUE; + else return FALSE; +} + +/*--------------------------------------------------------- + * sigEnableInterrupts: + * This procedure reenables our handling of interrupts. + * + * Results: None. + * + * Side Effects: + * None. + *--------------------------------------------------------- + */ + +void +SigEnableInterrupts() +{ + /*sigNumDisables--;*/ + if (sigNumDisables == 1) + { + SigInterruptPending = sigInterruptReceived; + sigInterruptReceived = FALSE; + } + sigNumDisables--; +} + + +/*--------------------------------------------------------- + * sigDisableInterrupts: + * This procedure disables our handling of interrupts. + * + * Results: None. + * + * Side Effects: + * None. + *--------------------------------------------------------- + */ + +void +SigDisableInterrupts() +{ + sigNumDisables++; + if (sigNumDisables == 1) + { + sigInterruptReceived = SigInterruptPending; + SigInterruptPending = FALSE; + } + /*sigNumDisables++;*/ +} + + +/* + * ---------------------------------------------------------------------------- + * SigWatchFile -- + * + * Take interrupts on a given IO stream. + * + * Results: + * None. + * + * Side effects: + * SigIOReady will be set when the IO stream becomes ready. It is + * the responsibility of the client to clear that flag when needed. + * ---------------------------------------------------------------------------- + */ + +void +SigWatchFile(filenum, filename) + int filenum; /* A file descriptor number */ + char *filename; /* Used to recognize special files that + * don't support a full range of fcntl + * calls (such as windows: /dev/winXX). + */ +{ + int flags; + bool iswindow; + + iswindow = (filename && (strncmp(filename, "/dev/win", 8) == 0)); + + flags = fcntl(filenum, F_GETFL, 0); + if (flags == -1) + { + perror("(Magic) SigWatchFile1"); + return; + } + + if (!mainDebug) + { + /* turn on FASYNC */ +#ifndef SYSV +#ifdef F_SETOWN + if (!iswindow) + { + if (fcntl(filenum, F_SETOWN, -getpid()) == -1) + perror("(Magic) SigWatchFile2"); + } +#endif +#endif /* SYSV */ +#ifdef FASYNC + if (fcntl(filenum, F_SETFL, flags | FASYNC) == -1) + perror("(Magic) SigWatchFile3"); +#else +# ifdef FIOASYNC + flags = 1; + if (ioctl(filenum, FIOASYNC, &flags) == -1) + perror("(Magic) SigWatchFile3a"); +# endif +#endif + } + else + { +#ifdef FASYNC + /* turn off FASYNC */ + if (fcntl(filenum, F_SETFL, flags & (~FASYNC)) == -1) + perror("(Magic) SigWatchFile4"); +#else +# ifdef FIOASYNC + flags = 0; + if (ioctl(filenum, FIOASYNC, &flags) == -1) + perror("(Magic) SigWatchFile3b"); +# endif +#endif + } +} + + +/* + * ---------------------------------------------------------------------------- + * SigUnWatchFile -- + * + * Do not take interrupts on a given IO stream. + * + * Results: + * None. + * + * Side effects: + * SigIOReady will be not set when the IO stream becomes ready. + * ---------------------------------------------------------------------------- + */ + /*ARGSUSED*/ + +void +SigUnWatchFile(filenum, filename) + int filenum; /* A file descriptor number */ + char *filename; /* Used to recognize special files that + * don't support a full range of fcntl + * calls (such as windows: /dev/winXX). + */ +{ + int flags; + + flags = fcntl(filenum, F_GETFL, 0); + if (flags == -1) + { + perror("(Magic) SigUnWatchFile1"); + return; + } + +#ifdef FASYNC + /* turn off FASYNC */ + if (fcntl(filenum, F_SETFL, flags & (~FASYNC)) == -1) + perror("(Magic) SigUnWatchFile4"); +#else +# ifdef FIOASYNC + flags = 0; + if (ioctl(filenum, FIOASYNC, &flags) == -1) + perror("(Magic) SigWatchFile3"); +# endif +#endif +} + + +/*--------------------------------------------------------- + * sigOnInterrupt: + * This procedure handles interupt signals. + * + * Results: + * sigReturn result (see signals.h) + * + * Side Effects: + * A global flag is set + *--------------------------------------------------------- + */ + +sigRetVal +sigOnInterrupt(int signo) +{ + if (sigNumDisables != 0) + sigInterruptReceived = TRUE; + else + SigInterruptPending = TRUE; + sigReturn; +} + + +/* + * ---------------------------------------------------------------------------- + * sigOnTerm: + * + * Catch the terminate (SIGTERM) signal. + * Force all modified cells to be written to disk (in new files, + * of course). + * + * Results: + * Function does not return. + * + * Side effects: + * Writes cells out to disk (by calling DBWriteBackup()). + * Exits. + * ---------------------------------------------------------------------------- + */ + +sigRetVal +sigOnTerm(int signo) +{ + DBWriteBackup(NULL); + exit (1); +} + + + +/* + * ---------------------------------------------------------------------------- + * sigOnWinch -- + * + * A window has changed size or otherwise needs attention. + * + * Results: + * sigReturn result (see signals.h) + * + * Side effects: + * Sets a global flag. + * ---------------------------------------------------------------------------- + */ + +sigRetVal +sigOnWinch(int signo) +{ + SigGotSigWinch = TRUE; + sigReturn; +} + +/* + * ---------------------------------------------------------------------------- + * sigIO -- + * + * Some IO device is ready (probably the keyboard or the mouse). + * + * Results: + * sigReturn result (see signals.h) + * + * Side effects: + * Sets a global flag. + * ---------------------------------------------------------------------------- + */ + +sigRetVal +sigIO(int signo) +{ + SigIOReady = TRUE; + if (SigInterruptOnSigIO == 1) sigOnInterrupt(0); + sigReturn; +} + +/* + * ---------------------------------------------------------------------------- + * + * sigCrash -- + * + * Something when wrong, reset the terminal and die. + * + * Results: + * Function never returns. + * + * Side Effects: + * We die. + * + * ---------------------------------------------------------------------------- + */ + +sigRetVal +sigCrash(signum) + int signum; +{ + static int magicNumber = 1239987; + char *msg; + extern bool AbortFatal; + +#ifndef linux + if (magicNumber == 1239987) { + /* Things aren't screwed up that badly, try to reset the terminal */ + magicNumber = 0; + switch (signum) { + case SIGILL: {msg = "Illegal Instruction"; break;}; + case SIGTRAP: {msg = "Instruction Trap"; break;}; + case SIGIOT: {msg = "IO Trap"; break;}; + case SIGEMT: {msg = "EMT Trap"; break;}; + case SIGFPE: {msg = "Floating Point Exception"; break;}; + case SIGBUS: {msg = "Bus Error"; break;}; + case SIGSEGV: {msg = "Segmentation Violation"; break;}; + case SIGSYS: {msg = "Bad System Call"; break;}; + default: {msg = "Unknown signal"; break;}; + }; + strcpy(AbortMessage, msg); + AbortFatal = TRUE; + niceabort(); + TxResetTerminal(); + } +#else + if (magicNumber == 1239987) { + magicNumber = 0; + /* Don't use switch statement. These values aren't mutually exclusive + * under Linux. + */ + if (signum == SIGILL) msg = "Illegal Instruction"; + else if (signum == SIGTRAP) msg = "Instruction Trap"; + else if (signum == SIGIOT) msg = "IO Trap"; + else if (signum == SIGEMT) msg = "EMT Trap"; + else if (signum == SIGFPE) msg = "Floating Point Exception"; + else if (signum == SIGBUS) msg = "Bus Error"; + else if (signum == SIGSEGV) msg = "Segmentation Violation"; + else if (signum == SIGSYS) msg = "Bad System Call"; + else msg = "Unknown signal"; + strcpy(AbortMessage, msg); + AbortFatal = TRUE; + niceabort(); + TxResetTerminal(); + } +#endif + + /* Crash & burn */ + magicNumber = 0; + exit(12); +} + + +/* + * ---------------------------------------------------------------------------- + * SigInit: + * + * Set up signal handling for all signals. + * + * Results: + * None. + * + * Side effects: + * Signal handling is set up. + * ---------------------------------------------------------------------------- + */ + +void +SigInit(batchmode) + int batchmode; +{ + /* fprintf(stderr, "Establishing signal handlers.\n"); fflush(stderr); */ + + if (batchmode) + { + SigInterruptOnSigIO = -1; + } + else + { + SigInterruptOnSigIO = 0; + sigSetAction(SIGINT, sigOnInterrupt); + sigSetAction(SIGTERM, sigOnTerm); + } + + /* Under Tcl, sigOnStop just causes Tcl to hang forever. So don't */ + /* set any new actions. */ + +#ifndef MAGIC_WRAPPER +#ifdef SIGTSTP + sigSetAction(SIGTSTP, sigOnStop); +#endif + +#ifdef SIGWINCH + sigSetAction(SIGWINCH, sigOnWinch); +#endif + +#ifdef SIGWINDOW + sigSetAction(SIGWINDOW, sigOnWinch); +#endif +#endif /* MAGIC_WRAPPER */ + + if (!mainDebug ) + { + sigSetAction(SIGIO, sigIO); +#ifdef MAGIC_WRAPPER + if (batchmode == 0) + SigTimerDisplay(); + else + sigSetAction(SIGALRM, SIG_IGN); +#else + sigSetAction(SIGALRM, SIG_IGN); +#endif + + sigSetAction(SIGPIPE, SIG_IGN); + +#ifdef SIGPOLL + if (SIGIO != SIGPOLL) + { + sigSetAction(SIGPOLL, SIG_IGN); + } +#endif + } + +#if !defined(SYSV) && !defined(CYGWIN) + sigsetmask(0); +#endif +} + +void +sigSetAction(int signo, sigRetVal (*handler)(int)) +{ +#if defined(SYSV) || defined(CYGWIN) || defined(__NetBSD__) + struct sigaction sa; + + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(signo, &sa, (struct sigaction *)NULL); +#else + struct sigvec sv; + + sv.sv_handler = handler; + sv.sv_mask = 0; + sv.sv_flags = 0; + sigvec(signo, &sv, (struct sigvec *)NULL); +#endif +} diff --git a/utils/signals.h b/utils/signals.h new file mode 100644 index 00000000..41cf7929 --- /dev/null +++ b/utils/signals.h @@ -0,0 +1,59 @@ +/* + * signals.h -- + * + * Routines to signals, such as handle keyboard interrupts + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * + * rcsid[]="$Header: /usr/cvsroot/magic-8.0/utils/signals.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; + */ + +#ifndef _MAGSIGNAL_H +#define _MAGSIGNAL_H + +#include "utils/magic.h" + +/* Some machines have signal handlers returning an int, while other machines + * have it returning a void. If you have a machine that requires ints put + * it in the list of machines in utils/magic.h. + */ +#ifdef SIG_RETURNS_INT +#define sigRetVal int +#define sigReturn return 0 +#else +#define sigRetVal void +#define sigReturn return +#endif + +/* data structures */ +extern bool SigInterruptPending; +extern bool SigIOReady; +extern char SigInterruptOnSigIO; +extern bool SigGotSigWinch; + +/* procedures */ +extern void SigInit(); +extern void SigDisableInterrupts(); +extern void SigEnableInterrupts(); +extern void SigWatchFile(); +extern void SigUnWatchFile(); +extern bool SigCheckProcess(); + +extern void SigSetTimer(); +extern void SigTimerInterrupts(); +extern void SigTimerDisplay(); + +extern sigRetVal sigOnInterrupt(); + +#endif /* _MAGSIGNAL_H */ diff --git a/utils/stack.c b/utils/stack.c new file mode 100644 index 00000000..bcbd9697 --- /dev/null +++ b/utils/stack.c @@ -0,0 +1,289 @@ +/* + * stack.c -- + * + * General purpose stack manipulation routines. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/stack.c,v 1.2 2010/06/24 12:37:58 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/utils.h" +#include "utils/stack.h" +#include "utils/malloc.h" + +bool stackCopyStr; + +/* + * ---------------------------------------------------------------------------- + * StackNew -- + * + * Allocate and initialize a new Stack. + * + * Results: + * Returns a pointer to a newly heap-allocated and initialized + * stack, with its growth increment set to the specified + * size (in entries). + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +Stack * +StackNew(sincr) + int sincr; /* Number of entries by which to grow storage area */ +{ + Stack *stack; + + stack = (Stack *) mallocMagic((unsigned) (sizeof (Stack))); + stack->st_incr = sincr; + stack->st_body = (struct stackBody *) mallocMagic((unsigned) (stackSize(sincr))); + stack->st_ptr = stack->st_body->sb_data; + stack->st_body->sb_next = NULL; + + return (stack); +} + +/* + * ---------------------------------------------------------------------------- + * StackFree -- + * + * Deallocate a Stack. + * + * Results: + * None. + * + * Side effects: + * Deallocates all memory currently assigned to the Stack. + * + * ---------------------------------------------------------------------------- + */ + +void +StackFree(stack) + Stack *stack; +{ + struct stackBody *stackp, *stacknext; + + for (stackp = stack->st_body; stackp != NULL; stackp = stacknext) + { + stacknext = stackp->sb_next; + freeMagic((char *) stackp); + } + + freeMagic((char *) stack); +} + +/* + * ---------------------------------------------------------------------------- + * StackPush -- + * + * Push a new element on to a stack. + * + * Results: + * None. + * + * Side effects: + * The argument stack is updated to reflect the new + * item placed upon it. + * + * ---------------------------------------------------------------------------- + */ +void +StackPush(arg, stack) + ClientData arg; + Stack *stack; +{ + struct stackBody *bodyNew; + + if (stack->st_ptr >= &stack->st_body->sb_data[stack->st_incr]) + { + bodyNew = (struct stackBody *) mallocMagic((unsigned) (stackSize(stack->st_incr))); + bodyNew->sb_next = stack->st_body; + stack->st_ptr = bodyNew->sb_data; + stack->st_body = bodyNew; + } + + *(stack->st_ptr++) = arg; +} + +/* + * ---------------------------------------------------------------------------- + * StackPop -- + * + * Pop the top element from a Stack and return it. + * + * Results: + * Top element from stack. + * If the stack is already empty, returns NULL. + * Callers should probably avoid popping from an empty + * stack. + * + * Side effects: + * Updates the stack to reflect the result of popping its top. + * + * ---------------------------------------------------------------------------- + */ + +ClientData +StackPop(stack) + Stack *stack; +{ + struct stackBody *bodyOld; + + if (stackBodyEmpty(stack)) + { + bodyOld = stack->st_body; + if (bodyOld->sb_next == NULL) + return ((ClientData) NULL); + stack->st_body = bodyOld->sb_next; + stack->st_ptr = &stack->st_body->sb_data[stack->st_incr]; + freeMagic((char *) bodyOld); + } + + return (*--(stack->st_ptr)); +} + +/* + * ---------------------------------------------------------------------------- + * StackLook -- + * + * Return the top element from a Stack, but don't pop it off. + * + * Results: + * Top element from stack. + * If the stack is already empty, returns NULL. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +ClientData +StackLook(stack) + Stack *stack; +{ + struct stackBody *bodyNext; + + if (stackBodyEmpty(stack)) + { + bodyNext = stack->st_body->sb_next; + if (bodyNext == NULL) + return ((ClientData) NULL); + return (bodyNext->sb_data[stack->st_incr - 1]); + } + + return ( *(stack->st_ptr - 1) ); +} + +/* + * ---------------------------------------------------------------------------- + * + * StackEnum -- + * + * Enumerate all elements on the stack. Call the supplied function + * for each occurrence. + * + * The supplied function is of the form: + * int func(stackItem, i, clientData) + * ClientData stackItem; Item put on the stack + * int i; Index of the item on stack + * ClientData cd; Points to whatever you want + * The function normally returns 0. The enumeration terminates if it + * returns anything else. + * + * Results: + * None. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ +void +StackEnum(stack, func, cd) + Stack * stack; + int (* func)(); + ClientData cd; +{ + int i, j; + struct stackBody * sb; + + i=1; + for(sb=stack->st_body; sb!=(struct stackBody *) NULL; sb=sb->sb_next) + { + for(j=0; j<=stack->st_incr; j++) + { + if( &(sb->sb_data[j]) == stack->st_ptr ) return; + if((*func)(sb->sb_data[j], i, cd)) return; + i++; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * + * StackCopy -- + * + * Make a copy of a stack. + * + * Results: + * None. + * + * Side effects: + * Memory may get allocated if the copystr parameter says to copy + * strings rather than pointers to them. + * dest gets a copy of src. If dest is non-null, it gets freed. + * + * ---------------------------------------------------------------------------- + */ +void +StackCopy(src, dest, copystr) + Stack * src, ** dest; + bool copystr; +{ + int stackCopyFn(); + + stackCopyStr=copystr; + if(*dest!=(Stack *) NULL) + StackFree(*dest); + if(src==(Stack *) NULL) + *dest = src; + else + { + *dest = StackNew(src->st_incr); + StackEnum(src, stackCopyFn, (ClientData) * dest); + } +} + +/*ARGSUSED*/ +int +stackCopyFn(stackItem, i, cd) + ClientData stackItem; + int i; + ClientData cd; +{ + if(stackCopyStr) + StackPush((ClientData) StrDup((char **) NULL, (char *)stackItem), (Stack *) cd); + else + StackPush(stackItem, (Stack *) cd); + return(0); +} diff --git a/utils/stack.h b/utils/stack.h new file mode 100644 index 00000000..3e80dd58 --- /dev/null +++ b/utils/stack.h @@ -0,0 +1,83 @@ +/* + * stack.h -- + * + * General purpose stack manipulation routines. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * Needs to include magic.h + * + * sccsid @(#)stack.h 4.1 MAGIC (Berkeley) 7/4/85 + */ + +#ifndef _STACK_H +#define _STACK_H + +#include "utils/magic.h" + +struct stackBody +{ + struct stackBody *sb_next; /* Next block on stack chain */ + ClientData sb_data[1]; /* Size determined when malloc'd */ +}; + +/* + * The following macro determines the size of the region to malloc + * for a stack body able to hold sincr elements. + */ + +#define sHDRSIZE (sizeof (struct stackBody *)) +#define stackSize(sincr) (sHDRSIZE + (sizeof (ClientData)) * (sincr)) + +typedef struct stack +{ + int st_incr; /* Amount by which to grow stack */ + ClientData *st_ptr; /* Stack pointer */ + struct stackBody *st_body; /* First stack block on chain */ +} Stack; + +/* --------------------- Procedure headers ---------------------------- */ + +Stack *StackNew(); +ClientData StackPop(); +ClientData StackLook(); +void StackPush(); +void StackFree(); +void StackEnum(); +void StackCopy(); + +#define stackBodyEmpty(st) ((st)->st_ptr <= (st)->st_body->sb_data) + +/* + * bool StackEmpty(st) Stack *st; returns TRUE if stack is empty + */ +#define StackEmpty(st) (stackBodyEmpty(st) && (st)->st_body->sb_next == NULL) + +/* + * Macro interfaces to StackLook(), StackPop(), and StackPush(). + */ +#define STACKLOOK(st) \ + (stackBodyEmpty(st) ? StackLook(st) : *((st)->st_ptr - 1)) + +#define STACKPOP(st) \ + (stackBodyEmpty(st) ? StackPop(st) : *--((st)->st_ptr)) + +#define STACKPUSH(a, st) \ + if (1) { \ + if ((st)->st_ptr >= &(st)->st_body->sb_data[(st)->st_incr]) \ + StackPush(a, st); \ + else \ + *((st)->st_ptr++) = (ClientData)(pointertype) (a); \ + } else + +#endif /* _STACK_H */ diff --git a/utils/strdup.c b/utils/strdup.c new file mode 100644 index 00000000..54cee6d2 --- /dev/null +++ b/utils/strdup.c @@ -0,0 +1,166 @@ +/* + * strdup.c -- + * + * Return a malloc'd copy of a string. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/strdup.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include /* for strtod */ +#include +#include + +#include "utils/magic.h" +#include "utils/malloc.h" + + +/* + * ---------------------------------------------------------------------------- + * StrDup -- + * + * Return a malloc'd copy of a string. + * + * Results: + * Returns a pointer to a newly malloc'd character array just + * large enough to hold the supplied string and its trailing + * null byte, which contains a copy of the supplied string. + * + * Side effects: + * malloc's a character array large enough to hold str, and + * copies str into it, unless str is NULL. If str is NULL, no + * malloc is done. Also, if oldstr is non-NULL, then a) if + * *oldstr is not NULL, frees the storage allocated to oldstr, + * and b) sets *oldstr to the new string allocated, or to + * NULL if str is NULL. + * ---------------------------------------------------------------------------- + */ + +char * +StrDup(oldstr, str) + char **oldstr; + char *str; +{ + char *newstr; + + if (str != NULL) + { + newstr = (char *) mallocMagic((unsigned) (strlen(str) + 1)); + (void) strcpy(newstr, str); + } + else newstr = NULL; + if (oldstr != (char **) NULL) + { + if (*oldstr != NULL) + freeMagic(*oldstr); + *oldstr = newstr; + } + + return (newstr); +} + + +/* + * ---------------------------------------------------------------------------- + * StrIsWhite: + * + * Check to see if a string is all white space or is a comment. + * + * Results: + * True if it is all white, false otherwise. + * + * Side effects: + * none. + * ---------------------------------------------------------------------------- + */ + +bool +StrIsWhite(line, commentok) + char *line; + bool commentok; /* TRUE means # comments are considered all-white */ +{ + if ( (*line == '#') && commentok) + return TRUE; + while(*line) + { + if ( !isspace(*line) && (*line != '\n') ) + return FALSE; + line++; + } + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * + * StrIsInt -- + * + * Check a string for being an integer. + * + * Results: + * TRUE if the string is a well-formed integer, FALSE otherwise. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +StrIsInt(s) + char *s; +{ + if (*s == '-' || *s == '+') s++; + while (*s) + if (!isdigit(*s++)) + return (FALSE); + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * StrIsNumeric -- + * + * Check a string for being any numeric value. + * + * Results: + * TRUE if the string can be interpreted as a numeric value, + * FALSE otherwise. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +bool +StrIsNumeric(s) + char *s; +{ + double result; + char *endptr; + + result = strtod(s, &endptr); + + if (endptr == s) return FALSE; + + return TRUE; +} + diff --git a/utils/styles.h b/utils/styles.h new file mode 100644 index 00000000..31cecb1b --- /dev/null +++ b/utils/styles.h @@ -0,0 +1,202 @@ +/* + * styles.h -- + * + * Definitions of styles used for system purposes. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid: $Header: /usr/cvsroot/magic-8.0/utils/styles.h,v 1.2 2008/12/11 04:20:14 tim Exp $ + */ + +#ifndef _STYLES_H +#define _STYLES_H 1 + +/* Styles are divided into three parts: 1) system styles, used for + * purposes such as drawing and erasing tools, window borders, etc., + * 2) Styles used to draw the layout, and 3) "Pale" styles duplicating + * all entries in (2) for drawing areas of the layout not currently + * begin edited. + * + * The system styles are predefined, so they can be accessed from the + * source code by preprocessor macros. + * + * STYLE_SOLIDHIGHLIGHTS: used to draw solid highlight areas. + * STYLE_MEDIUMHIGHLIGHTS: used to draw highlights in a medium-weight stipple. + * STYLE_PALEHIGHLIGHTS: used to draw highlights in a pale stipple. + * STYLE_HORIZHIGLIGHTS: used to draw highlights with horizontal lines. + * STYLE_VERTHIGLIGHTS: used to draw highlights with vertical lines. + * STYLE_OUTLINEHIGHLIGHTS: used to draw highlights as solid box outlines. + * STYLE_DOTTEDHIGLIGHTS: used to draw highlights with dotted box outlines. + * STYLE_ERASEBOX: used to erase the box from the screen. + * STYLE_ERASEHIGHLIGHTS: used to erase all highlights from an area. + * STYLE_ERASEALL: used to erase all information from the screen. + * STYLE_ERASEALLBUTTOOLS: used to erase everything but the tools. + * STYLE_LABEL: used to draw labels. + * STYLE_PORT: used to draw ports. + * STYLE_PORT_CONNECT: used to draw the connecting boundary on ports. + * STYLE_BBOX: used to draw cell bounding boxes and names. + * STYLE_GRID: used to draw grid on the screen (dotted lines). + * STYLE_SOLIDGRID: an alternate grid, drawn with solid lines. + * STYLE_ORIGIN: used to display a box at origin of edit cell. + * STYLE_DRAWTILE: used to draw tiles for *watch command. + * STYLE_BORDER: used to draw borders around windows. + * STYLE_ELEVATOR used by the window package to draw the elevator + * (slug) in the scroll bars. + * STYLE_CAPTION: used to draw window captions. + * STYLE_BACKGROUND: used to draw the areas outside of windows. + * STYLE_CMEDIT used to display the color being edited by the + * colormap editor. + * STYLE_WHITE, etc. used to generate common colors, for use in + * menus. Most colors have several styles, + * corresponding to different saturation levels. + * These colors are numbered where 1 corresponds + * to a very pale color and a large number is used + * for a highly saturated (rich) color. Unnumbered + * colors correspond to the most saturated ones. + * + * If any of the style numbers below are changed, all of the display styles + * files must be modified so that they agree. + */ + +/* Transparency */ + +#define STYLE_TRANSPARENT 0 + +/* Styles for drawing and erasing highlights: */ + +#define STYLE_SOLIDHIGHLIGHTS 1 +#define STYLE_MEDIUMHIGHLIGHTS 2 +#define STYLE_PALEHIGHLIGHTS 3 +#define STYLE_HORIZHIGHLIGHTS 4 +#define STYLE_VERTHIGHLIGHTS 5 +#define STYLE_OUTLINEHIGHLIGHTS 6 +#define STYLE_DOTTEDHIGHLIGHTS 7 +#define STYLE_ERASEBOX 8 +#define STYLE_ERASEHIGHLIGHTS 9 +#define STYLE_ERASEALL 10 +#define STYLE_ERASEALLBUTTOOLS 11 + +/* Other miscellaneous styles */ + +#define STYLE_LABEL 12 +#define STYLE_PORT 13 +#define STYLE_PORT_CONNECT 14 +#define STYLE_BBOX 15 +#define STYLE_GRID 16 +#define STYLE_SOLIDGRID 17 +#define STYLE_ORIGIN 18 +#define STYLE_DRAWTILE 19 +#define STYLE_BORDER 20 +#define STYLE_ELEVATOR 21 +#define STYLE_CAPTION 22 +#define STYLE_BACKGROUND 23 +#define STYLE_CMEDIT 24 + +/* Colors used by Tcl/Tk */ + +#define TK_MEDIUM_GRAY 25 +#define TK_LIGHT_GRAY 26 + +#define STYLE_LABEL_PALE 27 +#define STYLE_PORT_PALE 28 + +/* Assortment of solid colors */ + +#define STYLE_WHITE 29 +#define STYLE_GRAY1 30 +#define STYLE_GRAY2 31 +#define STYLE_GRAY 31 +#define STYLE_BLACK 32 +#define STYLE_RED1 33 +#define STYLE_PINK 33 +#define STYLE_RED2 34 +#define STYLE_RED3 35 +#define STYLE_RED 35 +#define STYLE_GREEN1 36 +#define STYLE_GREEN2 37 +#define STYLE_GREEN3 38 +#define STYLE_GREEN 38 +#define STYLE_BLUE1 39 +#define STYLE_BLUE2 40 +#define STYLE_BLUE3 41 +#define STYLE_BLUE 41 +#define STYLE_PURPLE1 42 +#define STYLE_PURPLE2 43 +#define STYLE_PURPLE 43 +#define STYLE_YELLOW1 44 +#define STYLE_YELLOW2 45 +#define STYLE_YELLOW 45 +#define STYLE_ORANGE1 46 +#define STYLE_ORANGE2 47 +#define STYLE_ORANGE 47 +#define STYLE_BROWN1 48 +#define STYLE_BROWN2 49 +#define STYLE_BROWN 49 +#define STYLE_MAGENTA 50 +#define STYLE_CYAN 51 + +/* Mark the number after all the built-in styles as the */ +/* beginning of the styles used by the technology files */ + +#define TECHBEGINSTYLES 52 + + +/* + * Here are the cursors defined in the standard styles file. + * + */ + +/* misc patterns */ +#define STYLE_CURS_NORMAL 0 +#define STYLE_CURS_STAR 1 + +/* corners */ +#define STYLE_CURS_LLCORNER 2 +#define STYLE_CURS_LRCORNER 3 +#define STYLE_CURS_ULCORNER 4 +#define STYLE_CURS_URCORNER 5 + +/* boxes */ +#define STYLE_CURS_LLBOX 6 +#define STYLE_CURS_LRBOX 7 +#define STYLE_CURS_ULBOX 8 +#define STYLE_CURS_URBOX 9 + +/* entire windows */ +#define STYLE_CURS_LLWIND 10 +#define STYLE_CURS_LRWIND 11 +#define STYLE_CURS_ULWIND 12 +#define STYLE_CURS_URWIND 13 + +/* corners of windows */ +#define STYLE_CURS_LLWINDCORN 14 +#define STYLE_CURS_LRWINDCORN 15 +#define STYLE_CURS_ULWINDCORN 16 +#define STYLE_CURS_URWINDCORN 17 + +/* netlist editing icon */ +#define STYLE_CURS_NET 18 + +/* wiring icon */ +#define STYLE_CURS_ARROW 19 + +/* irouting icon */ +#define STYLE_CURS_IROUTE 20 + +/* rsim icon */ +#define STYLE_CURS_RSIM 21 + +/* pick icon */ +#define STYLE_CURS_PICK 22 + +#endif /* _STYLES_H */ diff --git a/utils/tech.c b/utils/tech.c new file mode 100644 index 00000000..41b6d7fd --- /dev/null +++ b/utils/tech.c @@ -0,0 +1,992 @@ +/* + * tech.c -- + * + * Read in a technology file. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/tech.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include "database/database.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/utils.h" +#include "utils/tech.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "utils/malloc.h" + +global int TechFormatVersion; +global bool TechOverridesDefault; + +/* Define a file stack so that "include" calls can be nested */ + +typedef struct FStack /* Linked FILE * pointers */ +{ + FILE *file; + struct FStack *next; /* Pointer to another linked rectangle */ +} filestack; + +int techLineNumber; +char *TechFileName = NULL; + +#define iseol(c) ((c) == EOF || (c) == '\n') + +/* + * Each client of the technology module must make itself known by + * a call to TechAddClient(). These calls provide both the names + * of the sections of the technology file, as well as the procedures + * to be invoked with lines in these sections. + * + * The following table is used to record clients of the technology + * module. + */ + + typedef struct tC + { + bool (*tc_proc)(); /* Procedure to be called for each + * line in section. + */ + void (*tc_init)(); /* Procedure to be called before any + * lines in a section are processed. + */ + void (*tc_final)(); /* Procedure to be called after all + * lines in section have been processed. + */ + struct tC *tc_next; /* Next client in section */ + } techClient; + + typedef struct + { + char *ts_name; /* Name of section */ + char *ts_alias; /* Alternative name of section */ + techClient *ts_clients; /* Pointer to list of clients */ + bool ts_read; /* Flag: TRUE if section was read */ + bool ts_optional; /* Flag: TRUE if section is optional */ + SectionID ts_thisSect; /* SectionID of this section */ + SectionID ts_prevSects; /* Mask of sections that must be + * read in before this one. The + * mask is constructed from the + * section identifiers set by + * TechAddClient(). + */ + } techSection; + +#define MAXSECTIONS (8 * sizeof (int)) /* Not easily changeable */ +#define MAXARGS 30 +#define MAXLINESIZE 1024 + +#define SectionToMaskBit(s) (1 << (s)) +#define SectionMaskHasSection(m, s) (m & SectionToMaskBit(s)) + +int techSectionNum; /* ID of next new section */ +SectionID techSectionMask; /* Mask of sections already read */ + +techSection techSectionTable[MAXSECTIONS]; +techSection *techSectionFree; /* Pointer to next free section */ +techSection *techCurrentSection; /* Pointer to current section */ + +techSection *techFindSection(); + +/* + * ---------------------------------------------------------------------------- + * + * TechSectionGetMask -- + * + * Get the SectionID mask for a specific section (specified by name). The + * returned mask is inverted; that is, it is a mask containing bits + * representing all the client sections except for the one sepcified. + * This return value can be passed to TechLoad to re-read a specific + * section. + * + * Results: + * Returns the inverted mask for the selected section ID. + * + * Side effects: + * If "depend" is non-NULL, the SectionID to which it points will be + * set to a mask representing the mask of sections which depend on + * the indicated section; that is, those sections which will be + * invalidated if the indicated section is altered in any way. + * + * ---------------------------------------------------------------------------- + */ + +SectionID +TechSectionGetMask(sectionName, depend) + char *sectionName; + SectionID *depend; +{ + techSection *tsp, *thissect; + SectionID invid = 0; + SectionID selected; + + thissect = techFindSection(sectionName); + if (thissect == NULL) return -1; + + selected = thissect->ts_thisSect; + + for (tsp = techSectionTable; tsp < techSectionFree; tsp++) + { + if (tsp != thissect) + { + invid |= tsp->ts_thisSect; + if (tsp->ts_prevSects & thissect->ts_thisSect) + if (depend != NULL) *depend != tsp->ts_thisSect; + } + } + return invid; +} + +/* + * ---------------------------------------------------------------------------- + * + * TechInit -- + * + * Initialize the technology module. + * + * Results: + * None. + * + * Side effects: + * Initializes the technology read-in module. + * This function must be called before any other functions in + * this module are called. It is called exactly once at the start + * of a magic session. + * + * ---------------------------------------------------------------------------- + */ + +void +TechInit() +{ + techCurrentSection = (techSection *) NULL; + techSectionFree = techSectionTable; + techSectionNum = 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * TechAddAlias -- + * + * Add an alternative name (alias) for a technology file section which + * may be used in place of the primary name. + * + * This has been added mainly to handle sections which have been + * expanded beyond their original definition such that the section + * name is no longer appropriate. Case in point: the "images" + * section is broader in scope than the "contact" section, but + * because contacts are a subset of images in version 7.3, it is + * preferable to have an "images" section instead of a "contacts" + * section, with allowances for backwards compatibility. + * + * Results: + * None. + * + * Side effects: + * Allocates string memory. + * + * ---------------------------------------------------------------------------- + */ + +void +TechAddAlias(primaryName, alias) + char *primaryName; + char *alias; +{ + techSection *tsp; + + tsp = techFindSection(primaryName); + if (tsp == (techSection *) NULL) + { + TxError("Unknown technology file section \"%s\" requested.\n", + primaryName); + } + else + { + if (tsp->ts_alias != NULL) + freeMagic(tsp->ts_alias); + tsp->ts_alias = StrDup((char **)NULL, alias); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * changePlanesFunc() --- + * + * This function hacks the existing layout database in case a tech file + * is loaded which contains more or fewer planes than the exisiting + * technology. This is doing nothing fancy; it is simply making sure + * that all memory allocation is accounted for. + * + * As a note for future implementation, it would be helpful to keep the + * old plane name definitions around and try to match up the old and new + * planes, so that it is possible to load a technology file which matches + * the existing technology except for the addition or subtraction of one + * or more planes (e.g., extra metal layer option) without completely + * invalidating an existing layout. + * + * As written, this function is inherently dangerous. It is intended for + * use when loading a new tech file when there is no layout, just empty + * tile planes. + * ---------------------------------------------------------------------------- + */ + +int +changePlanesFunc(cellDef, arg) + CellDef *cellDef; + int *arg; +{ + int oldnumplanes = *arg; + int pNum; + + if (oldnumplanes < DBNumPlanes) + { + /* New planes to be added */ + for (pNum = oldnumplanes; pNum < DBNumPlanes; pNum++) + { + cellDef->cd_planes[pNum] = DBNewPlane((ClientData) TT_SPACE); + } + } + else + { + /* Old planes to be subtracted */ + for (pNum = DBNumPlanes; pNum < oldnumplanes; pNum++) + { + DBFreePaintPlane(cellDef->cd_planes[pNum]); + TiFreePlane(cellDef->cd_planes[pNum]); + cellDef->cd_planes[pNum] = (Plane *) NULL; + } + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * TechAddClient -- + * + * Add a client to the technology module. + * + * Results: + * None. + * + * Side effects: + * Identifies "sectionName" as a valid name for a section of a .tech + * file, and specifies that init() is the procedure to be called when + * a new technology is loaded, proc() as the procedure to be called + * for each line in the given section, and final() as the procedure to + * be called after the last line in the given section. + * + * The init() procedure takes no arguments. + * The proc() procedure should be of the following form: + * bool + * proc(sectionName, argc, argv) + * char *sectionName; + * int argc; + * char *argv[]; + * { + * } + * The final() procedure takes no arguments. + * + * The argument prevSections should be a mask of the SectionID's + * of all sections that must be read in before this one. + * + * If the argument 'pSectionID' is non-NULL, it should point to + * an int that will be set to the sectionID of this section. + * + * It is legal for several procedures to be associated with a given + * sectionName; this is accomplished through successive calls to + * TechAddClient with the same sectionName. The procedures will + * be invoked in the order in which they were handed to TechAddClient(). + * + * If the procedure given is NULL for init(), proc(), or final(), no + * procedure is invoked. + * + * ---------------------------------------------------------------------------- + */ + +void +TechAddClient(sectionName, init, proc, final, prevSections, pSectionID, opt) + char *sectionName; + void (*init)(); + bool (*proc)(); + void (*final)(); + SectionID prevSections; + SectionID *pSectionID; + bool opt; /* optional section */ +{ + techSection *tsp; + techClient *tcp, *tcl; + + tsp = techFindSection(sectionName); + if (tsp == (techSection *) NULL) + { + tsp = techSectionFree++; + ASSERT(tsp < &techSectionTable[MAXSECTIONS], "TechAddClient"); + tsp->ts_name = StrDup((char **) NULL, sectionName); + tsp->ts_alias = NULL; + tsp->ts_clients = (techClient *) NULL; + tsp->ts_thisSect = SectionToMaskBit(techSectionNum); + tsp->ts_prevSects = (SectionID) 0; + tsp->ts_optional = opt; + techSectionNum++; + } + + tsp->ts_prevSects |= prevSections; + if (pSectionID) + *pSectionID = tsp->ts_thisSect; + + tcp = (techClient *) mallocMagic(sizeof (techClient)); + ASSERT(tcp != (techClient *) NULL, "TechAddClient"); + tcp->tc_init = init; + tcp->tc_proc = proc; + tcp->tc_final = final; + tcp->tc_next = (techClient *) NULL; + + if (tsp->ts_clients == (techClient *) NULL) + tsp->ts_clients = tcp; + else + { + for (tcl = tsp->ts_clients; tcl->tc_next; tcl = tcl->tc_next) + /* Nothing */; + tcl->tc_next = tcp; + } +} + +/* + * ---------------------------------------------------------------------------- + * TechLoad -- + * + * Initialize technology description information from a file. + * + * Results: + * TRUE if technology is successfully initialized (all required + * sections present and error free); FALSE otherwise. Unrecognized + * sections cause an error message to be printed, but do not otherwise + * affect the result returned by TechLoad(). + * + * Side effects: + * Calls technology initialization routines of other modules + * to initialize technology-specific information. + * + * ---------------------------------------------------------------------------- + */ + +bool +TechLoad(filename, initmask) + char *filename; + SectionID initmask; +{ + FILE *tf; + techSection *tsp; + techClient *tcp; + char suffix[20], line[MAXLINESIZE], *realname; + char *argv[MAXARGS]; + SectionID mask, badMask; + int argc, s; + bool retval, skip; + filestack *fstack, *newstack; + filestack topfile; + + fstack = NULL; + techLineNumber = 0; + badMask = (SectionID) 0; + int saveNumPlanes; + + int changePlanesFunc(); /* forward declaration */ + int checkForPaintFunc(); /* forward declaration */ + + if (initmask == -1) + { + TxError("Invalid technology file section requested.\n"); + return (FALSE); + } + + /* If NULL is passed to argument "filename", this is a reload and */ + /* we should read TechFileName verbatim. */ + + if ((filename == NULL) && (TechFileName != NULL)) + { + tf = PaOpen(TechFileName, "r", (char *)NULL, ".", SysLibPath, &realname); + if (tf == (FILE *) NULL) + { + TxError("Could not find file '%s' in any of these " + "directories:\n %s\n", + TechFileName, SysLibPath); + return (FALSE); + } + } + else + { + char *sptr, *dptr; + + /* TECH_VERSION in the filename is deprecated as of magic version */ + /* 7.2.27; TECH_VERSION is no longer defined in the utils/Makefile. */ + /* It has been changed to TECH_FORMAT_VERSION, left at version 27, */ + /* and placed in utils/tech.h. It is needed for backward */ + /* compatibility with *.tech27 files, of which there are many. */ + + (void) sprintf(suffix, ".tech"); + + /* Added 1/20/2015 to correspond to change to PaLockOpen(); */ + /* Always strip suffix from filename when suffix is specified. */ + + sptr = strrchr(filename, '/'); + if (sptr == NULL) + sptr = filename; + else + sptr++; + + dptr = strrchr(sptr, '.'); + if ((dptr != NULL) && !strncmp(dptr, suffix, strlen(suffix))) + *dptr = '\0'; + + tf = PaOpen(filename, "r", suffix, ".", SysLibPath, &realname); + if (tf == (FILE *) NULL) + { + /* Try looking for tech files from the last version to */ + /* put the version number into the filename itself. */ + + (void) sprintf(suffix, ".tech%d", TECH_FORMAT_VERSION); + + tf = PaOpen(filename, "r", suffix, ".", SysLibPath, &realname); + if (tf == (FILE *) NULL) + { + TxError("Could not find file '%s.tech' in any of these " + "directories:\n %s\n", + filename, SysLibPath); + return (FALSE); + } + } + StrDup(&TechFileName, realname); + + // In case filename is not a temporary string, put it back the + // way it was. + if (dptr != NULL) *dptr = '.'; + } + + topfile.file = tf; + topfile.next = NULL; + fstack = &topfile; + + // If TechLoad is called with initmask == -2, test that the file + // exists and is readable, and that the first non-comment line + // is the keyword "tech". + + if (initmask == -2) + { + argc = techGetTokens(line, sizeof line, &fstack, argv); + fclose(tf); + if (argc != 1) return (FALSE); + if (strcmp(argv[0], "tech")) return (FALSE); + return (TRUE); + } + + /* + * Mark all sections as being unread. + */ + techSectionMask = initmask; + for (tsp = techSectionTable; tsp < techSectionFree; tsp++) + { + tsp->ts_read = FALSE; + } + + /* + * Run section initializations if this is not a reload. + * CIF istyle, CIF ostyle, and extract sections need calls + * to the init functions which clean up memory devoted to + * remembering all the styles. + */ + + if (filename != NULL) + { +#ifdef CIF_MODULE + CIFTechInit(); + CIFReadTechInit(); +#endif + ExtTechInit(); + DRCTechInit(); + MZTechInit(); + + /* Changing number of planes requires handling on every */ + /* celldef. So we need to save the original number of */ + /* planes to see if it shrinks or expands. */ + + + saveNumPlanes = DBNumPlanes; + } + + /* + * Sections in a technology file begin with a single line containing + * the keyword identifying the section, and end with a single line + * containing the keyword "end". + */ + + retval = TRUE; + skip = FALSE; + while ((argc = techGetTokens(line, sizeof line, &fstack, argv)) >= 0) + { + /* Check for file inclusions (can be nested) */ + if ((argc > 1) && (!strcmp(argv[0], "include"))) + { + char *sptr; + + tf = PaOpen(argv[1], "r", suffix, ".", SysLibPath, NULL); + if (tf != NULL) + { + newstack = (filestack *)mallocMagic(sizeof(filestack)); + newstack->file = tf; + newstack->next = fstack; + fstack = newstack; + continue; + } + + /* Check the directory from which the tech file */ + /* itself was read. */ + + if ((sptr = strrchr(TechFileName, '/')) != NULL) + { + *sptr = '\0'; + tf = PaOpen(argv[1], "r", suffix, TechFileName, NULL, NULL); + *sptr = '/'; + if (tf != NULL) + { + newstack = (filestack *)mallocMagic(sizeof(filestack)); + newstack->file = tf; + newstack->next = fstack; + fstack = newstack; + continue; + } + } + TechError("Warning: Couldn't find include file %s\n", argv[1]); + } + + if (!skip && techCurrentSection == NULL) + { + if (argc != 1) + { + TechError("Bad section header line\n"); + goto skipsection; + } + + tsp = techFindSection(argv[0]); + if (tsp == (techSection *) NULL) + { + TechError("Unrecognized section name: %s\n", argv[0]); + goto skipsection; + } + else if (initmask & tsp->ts_thisSect) + { + skip = TRUE; + continue; + } + if (mask = (tsp->ts_prevSects & ~techSectionMask)) + { + techSection *sp; + + TechError("Section %s appears too early.\n", argv[0]); + TxError("\tMissing prerequisite sections:\n"); + for (sp = techSectionTable; sp < techSectionFree; sp++) + if (mask & sp->ts_thisSect) + TxError("\t\t%s\n", sp->ts_name); + goto skipsection; + } + techCurrentSection = tsp; + + /* Invoke initialization routines for all clients that + * provided them. + */ + + for (tcp = techCurrentSection->ts_clients; + tcp != NULL; + tcp = tcp->tc_next) + { + if (tcp->tc_init) + (void) (*tcp->tc_init)(); + } + continue; + } + + /* At the end of the section, invoke the finalization routine + * of the client's, if there is one. + */ + + if (argc == 1 && strcmp(argv[0], "end") == 0) + { + if (!skip) + { + techSectionMask |= techCurrentSection->ts_thisSect; + techCurrentSection->ts_read = TRUE; + for (tcp = techCurrentSection->ts_clients; + tcp != NULL; + tcp = tcp->tc_next) + { + if (tcp->tc_final) + (*tcp->tc_final)(); + } + } + techCurrentSection = (techSection *) NULL; + skip = FALSE; + continue; + } + + if (!skip) + for (tcp = techCurrentSection->ts_clients; + tcp != NULL; + tcp = tcp->tc_next) + if (tcp->tc_proc) + { + if (!(*tcp->tc_proc)(techCurrentSection->ts_name,argc,argv)) + { + retval = FALSE; + badMask |= techCurrentSection->ts_thisSect; + } + } + continue; + +skipsection: + TxError("[Skipping to \"end\"]\n"); + skip = TRUE; + } + + if (badMask) + { + TxError("The following sections of %s contained errors:\n", TechFileName); + for (s = 0; s < techSectionNum; s++) + if (SectionMaskHasSection(badMask, s)) + TxError(" %s\n", techSectionTable[s].ts_name); + } + + for (tsp = techSectionTable; tsp < techSectionFree; tsp++) + { + if (!(initmask & tsp->ts_thisSect)) + { + if (!tsp->ts_read && !tsp->ts_optional) + { + TxError("Section \"%s\" was missing from %s.\n", + tsp->ts_name, TechFileName); + retval = FALSE; + } + } + } + + /* In case we hit an error in an included file. . . */ + while ((fstack != NULL) && (fstack != &topfile)) + { + fclose(fstack->file); + freeMagic(fstack); + fstack = fstack->next; + } + if (fstack) fclose(fstack->file); + + /* Note: If filename is NULL, then individual sections are */ + /* being reloaded, and it is the responsibility of the */ + /* calling routine to invoke any exit function specific to */ + /* that section (e.g., DRCTechScale() when loading a new */ + /* DRC style). */ + + if ((filename != NULL) && (retval == TRUE)) + { + /* If internal scalefactor is not the default 1:1, then we */ + /* need to scale the techfile numbers accordingly. */ + + if ((DBLambda[0] != 1) || (DBLambda[1] != 1)) + { + int d = DBLambda[0]; + int n = DBLambda[1]; + + CIFTechInputScale(d, n, TRUE); + CIFTechOutputScale(d, n); + DRCTechScale(d, n); + ExtTechScale(d, n); + WireTechScale(d, n); +#ifdef LEF_MODULE + LefTechScale(d, n); +#endif +#ifdef ROUTE_MODULE + RtrTechScale(d, n); +#endif + TxPrintf("Scaled tech values by %d / %d to" + " match internal grid scaling\n", n, d); + + /* Check if we're below the scale set by cifoutput gridlimit */ + if (CIFTechLimitScale(1, 1)) + TxError("WARNING: Current grid scale is smaller" + " than the minimum for the process!\n"); + } + + /* Post-technology reading routines */ + +#ifdef ROUTE_MODULE + MZAfterTech(); + IRAfterTech(); + GAMazeInitParms(); +#endif + PlowAfterTech(); + + if (DBCellSrDefs(0, checkForPaintFunc, (ClientData)&saveNumPlanes)) + { + if (saveNumPlanes != DBNumPlanes) + TxError("Warning: Number of planes has changed. "); + TxError("Existing layout may be invalid.\n"); + } + if (saveNumPlanes != DBNumPlanes) + DBCellSrDefs(0, changePlanesFunc, (ClientData) &saveNumPlanes); + } + else if (retval == FALSE) + { + /* On error, remove any existing technology file name */ + freeMagic(TechFileName); + TechFileName = NULL; + } + + return (retval); +} + +/* + * ---------------------------------------------------------------------------- + * + * TechError -- + * + * Print an error message referring to a given line number in the + * technology module. + * + * Results: + * None. + * + * Side effects: + * Prints an error message. + * + * ---------------------------------------------------------------------------- + */ + +void +TechPrintLine() +{ + char *section; + + if (techCurrentSection) + section = techCurrentSection->ts_name; + else + section = "(none)"; + + TxError("%s: line %d: section %s:\n\t", + TechFileName, techLineNumber, section); +} + +void +TechError(char *fmt, ...) +{ + va_list args; + + TechPrintLine(); + va_start(args, fmt); + Vfprintf(stderr, fmt, args); + va_end(args); +} + + +/* ================== Functions local to this module ================== */ + +/* + * ---------------------------------------------------------------------------- + * + * techFindSection -- + * + * Return a pointer to the entry in techSectionTable for the section + * of the given name. + * + * Results: + * A pointer to the new entry, or NULL if none could be found. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +techSection * +techFindSection(sectionName) + char *sectionName; +{ + techSection *tsp; + + for (tsp = techSectionTable; tsp < techSectionFree; tsp++) + { + if (!strcmp(tsp->ts_name, sectionName)) + return (tsp); + else if (tsp->ts_alias != NULL) + { + if (!strcmp(tsp->ts_alias, sectionName)) + return (tsp); + } + } + return ((techSection *) NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * techGetTokens -- + * + * Read a line from the technology file and split it up into tokens. + * Blank lines are ignored. Lines ending in backslash are joined + * to their successor lines. + * We assume that all macro definition and comment elimination has + * been done by the C preprocessor. + * + * Results: + * Returns the number of tokens into which the line was split, or + * -1 on end of file. Never returns 0. + * + * Side effects: + * Copies the line just read into 'line'. The trailing newline + * is turned into a '\0'. The line is broken into tokens which + * are then placed into argv. + * + * ---------------------------------------------------------------------------- + */ + +int +techGetTokens(line, size, fstack, argv) + char *line; /* Character array into which line is read */ + int size; /* Size of character array */ + filestack **fstack; /* Open technology file on top of stack */ + char *argv[]; /* Vector of tokens built by techGetTokens() */ +{ + char *get, *put, *getp; + bool inquote; + int argc = 0; + int currspace; /* chars remaining before end of line[size] */ + FILE *file; /* Current technology file */ + + file = (*fstack)->file; + + /* Read one line into the buffer, joining lines when they end + * in backslashes. + */ + + /* Code revision (MDG, Stanford): Prevent the 1024-character limit due */ + /* to unconditional decrement of size. Long comment lists could cause */ + /* infinite looping. New code interprets first non-space character '#' */ + /* as a comment character, rather than requiring it to be in the first */ + /* column. */ + + /* Code revision (RTE, Open Circuit Design): Handle DOS-style CR/LF */ + /* Code revision (RTE, Open Circuit Design): Handle "include" files */ + +start: + get = line; + currspace = size; + while (currspace > 0) + { + techLineNumber += 1; + while (fgets(get, currspace, file) == NULL) { + if ((*fstack)->next != NULL) + { + fclose((*fstack)->file); + *fstack = (*fstack)->next; + file = (*fstack)->file; + } + else + return (-1); + } + getp = get; + while(isspace(*getp)) getp++; + if (*getp == '#') continue; + for (put = get; *put != '\n'; put++) currspace -= 1; + if (put != get) + { + put--; + if (*put == 0xd) put--; /* Handle DOS-style CR/LF */ + if (*put == '\\') + { + get = put; + continue; + } + put++; + } + *put= '\0'; + break; + } + if (currspace == 0) TechError("long line truncated\n"); + + get = put = line; + + while (*get != '\0') + { + /* Skip leading blanks */ + + while (isspace(*get)) get++; + + /* Beginning of the token is here. */ + + argv[argc] = put = get; + if (*get == '"') + { + get++; + inquote = TRUE; + } else inquote = FALSE; + + /* + * Grab up characters to the end of the token. Any character + * preceded by a backslash is taken literally. + */ + + while (*get != '\0') + { + if (inquote) + { + if (*get == '"') break; + } + else if (isspace(*get)) break; + + if (*get == '\\') /* Process quoted characters literally */ + { + get += 1; + if (*get == '\0') break; + } + + /* Copy into token receiving area */ + *put++ = *get++; + } + + /* + * If we got no characters in the token, we must have been at + * the end of the line. + */ + if (get == argv[argc]) + break; + + /* Terminate the token and advance over the terminating character. */ + + if (*get != '\0') get++; /* Careful! could be at end of line! */ + *put++ = '\0'; + argc++; + } + + if (argc == 0) + goto start; + + return (argc); +} diff --git a/utils/tech.h b/utils/tech.h new file mode 100644 index 00000000..7c3a495f --- /dev/null +++ b/utils/tech.h @@ -0,0 +1,58 @@ +/* + * tech.h -- + * + * Interface to technology module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/utils/tech.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $" + */ + +#ifndef _TECH_H +#define _TECH_H + +#include "utils/magic.h" + +typedef int SectionID; /* Mask set by TechAddClient */ + +/* Techfile section status: needed for switching between extract and */ +/* cif styles when only one style is kept in memory at any given time. */ +/* TECH_SUSPENDED is added so that style variants can be merged together*/ +/* in a style section, and will set TECH_SUSPEND when reading a portion */ +/* of the style that does not pertain to the specific variant we want. */ + +#define TECH_NOT_LOADED 0 +#define TECH_LOADED 1 +#define TECH_PENDING ((char)-1) +#define TECH_SUSPENDED ((char)-2) + +/* The last format version which was included in the file name */ +#define TECH_FORMAT_VERSION 27 + +/* The format version of the tech file currently active */ +extern int TechFormatVersion; + +/* ----------------- Exported variables ---------------- */ + +extern char *TechFileName; /* Full path and file name of technology file */ +extern bool TechOverridesDefault; /* Set TRUE if technology was specified on + * the command line. + */ + +/* ----------------- Exported procedures ---------------- */ + +extern void TechError(char *, ...); +extern void TechAddClient(); +extern void TechAddAlias(); + +#endif /* _TECH_H */ diff --git a/utils/touchingtypes.h b/utils/touchingtypes.h new file mode 100644 index 00000000..d155dfb3 --- /dev/null +++ b/utils/touchingtypes.h @@ -0,0 +1,27 @@ +/* + * touchingtypes.h -- + * Header, types TouchingTypes() function. + * (TouchingTypes() returns mask of types touching a given point.) + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/utils/touchingtypes.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _TOUCHINGTYPES_H +#define _TOUCHINGTYPES_H + +/* -------------------- Functions (exported by touching.c) ---------------- */ +extern TileTypeBitMask TouchingTypes(); + +#endif /* _TOUCHINGTYPES_H */ diff --git a/utils/touchtypes.c b/utils/touchtypes.c new file mode 100644 index 00000000..e1b91cf3 --- /dev/null +++ b/utils/touchtypes.c @@ -0,0 +1,203 @@ +/* touchingtypes.c -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * Lawrence Livermore National Laboratory + * All rights reserved. + * + * Function to return mask of all tiletypes touching a given point. + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/touchtypes.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/geofast.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" + +/* ----------------------- Structs local to this file ------------------- */ + +typedef struct touchingfuncparms +{ + Point tfp_point; + TileTypeBitMask tfp_types; +} TouchingFuncParms; + + +/* + * ---------------------------------------------------------------------------- + * + * TouchingTypes -- + * + * Generate mask of all types touching or covering a given point. + * + * Results: + * Mask of all types touching or covering a given point in cellUse or + * expanded subcell. If an unexpanded subcell is + * covering or touching point TT_SUBCELL is included in the result as + * well. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ +TileTypeBitMask +TouchingTypes(cellUse, expansionMask, point) + CellUse *cellUse; + int expansionMask; + Point *point; +{ + int touchingTypesFunc(); + int touchingSubcellsFunc(); + TouchingFuncParms parms; + + /* Search unit radius rectangle around point for paint tiles + * (in cellUse or subcells expanded in cmd window) containing or + * touching point + */ + { + SearchContext scx; + + scx.scx_area.r_ll = *point; + scx.scx_area.r_ur = *point; + scx.scx_area.r_ll.p_x -= 1; + scx.scx_area.r_ll.p_y -= 1; + scx.scx_area.r_ur.p_x += 1; + scx.scx_area.r_ur.p_y += 1; + + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = cellUse; + + parms.tfp_point = *point; + TTMaskZero(&(parms.tfp_types)); + + DBTreeSrTiles( + &scx, + &DBAllButSpaceAndDRCBits, + expansionMask, + touchingTypesFunc, + (ClientData) &parms); + } + + /* Now check for presence of unexpanded subcells */ + { + SearchContext scx; + + scx.scx_area.r_ll = *point; + scx.scx_area.r_ur = *point; + scx.scx_area.r_ll.p_x -= 1; + scx.scx_area.r_ll.p_y -= 1; + scx.scx_area.r_ur.p_x += 1; + scx.scx_area.r_ur.p_y += 1; + + scx.scx_trans = GeoIdentityTransform; + scx.scx_use = cellUse; + + DBTreeSrCells( + &scx, + expansionMask, + touchingSubcellsFunc, + (ClientData) &parms); + } + + return(parms.tfp_types); +} + + +/* + * --------------------------------------------------------------------- + * + * touchingTypesFunc -- + * + * Called by DBTreeSrTiles on behalf of touchingTypes above, to check if + * tile touches point. + * + * Results: + * Returns 0 to continue search. + * + * Side effects: + * Sets tile type in mask if tile touches point. + * + * --------------------------------------------------------------------- + */ + +int +touchingTypesFunc(tile, cxp) + Tile *tile; + TreeContext *cxp; +{ + SearchContext *scx = cxp->tc_scx; + Rect r, rDest; + TouchingFuncParms *parms = (TouchingFuncParms *) (cxp->tc_filter->tf_arg); + + /* Transform to result coordinates */ + TITORECT(tile, &r); + GEOCLIP(&r, &scx->scx_area); + GEOTRANSRECT(&scx->scx_trans, &r, &rDest); + + if(GEO_ENCLOSE(&(parms->tfp_point), &rDest)) + TTMaskSetType(&(parms->tfp_types),TiGetType(tile)); + + /* return 0 to continue search */ + return(0); +} + + +/* + * --------------------------------------------------------------------- + * + * touchingSubcellsFunc -- + * + * Called by DBTreeSrCells on behalf of touchingTypes above, to check if + * subcell touches point. + * + * Results: + * Returns 0 if subcell doesn't touch point (to continue search) + * Returns 1 on match (to terminate search) + * + * Side effects: + * Sets TT_SUBCELL in mask if subcell touches point. + * + * --------------------------------------------------------------------- + */ + +int +touchingSubcellsFunc(scx, cdarg) + SearchContext *scx; + ClientData cdarg; +{ + Rect r, rDest; + TouchingFuncParms *parms = (TouchingFuncParms *) cdarg; + + /* Transform bounding box to result coordinates */ + r = scx->scx_use->cu_def->cd_bbox; + GEOTRANSRECT(&scx->scx_trans, &r, &rDest); + + if(GEO_ENCLOSE(&(parms->tfp_point), &rDest)) + { + /* touching subcell found, mark in types mask, and terminate search */ + TTMaskSetType(&(parms->tfp_types),TT_SUBCELL); + return 1; /* 1 = abort search */ + } + else + { + /* subcell doesn't touch point after all, continue search */ + return 0; /* 0 = continue search */ + } +} diff --git a/utils/undo.c b/utils/undo.c new file mode 100644 index 00000000..7bd52672 --- /dev/null +++ b/utils/undo.c @@ -0,0 +1,973 @@ +/* + * undo.c -- + * + * Undo/redo module. + * + * The undo package records a series of invertible editing events + * in a log maintained in main memory. + * + * The current state may be rewound back toward the time the editing + * session began, and it may be replayed forward as well. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/undo.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/utils.h" +#include "utils/malloc.h" +#include "utils/undo.h" + +/* ------------------------------------------------------------------------ */ + +/* + * CONFIGURATION INFORMATION + */ + +#define MAXUNDOCLIENTS 50 /* Maximum number of calls to UndoAddClient */ + + /* + * MAXCOMMANDS is the maximum number of delimited event sequences + * ("commands") retained in main memory. LOWCOMMANDS is a low-water + * mark for the number of commands in memory; whenever we free up + * commands, we do so until there are no more than LOWCOMMANDS in + * main memory. + * + * >>>>> In the current implementation, these two are the same <<<<< + */ + +#define MAXCOMMANDS 1000 +#define LOWCOMMANDS 1000 /* Must be > 0 ! */ + +/* ------------------------------------------------------------------------ */ + +/* + * The following structure describes the basic information + * required by the undo package for each event it stores. + * This information is NOT intended to be visible to any of + * the clients of the undo package and is susceptible to being + * changed arbitrarily. + * + * To enforce the absolute ignorance of undo's clients, when + * we allocate an internalUndoEvent, we only give the client + * a pointer to the iue_client part, which is of a size determined + * by the client when it calls UndoNewEvent(). This pointer is + * what the client sees as an (UndoEvent *) (really a (char *)). + */ + + typedef struct ue + { + UndoType iue_type; /* Event type */ + struct ue *iue_back; /* Previous event on list */ + struct ue *iue_forw; /* Next event on list */ + int iue_client; /* Client data area. This is merely a + * dummy placeholder; the actual size + * of one of these structures is + * determined at the time of + * UndoNewEvent(). + */ + } internalUndoEvent; + +#define UT_DELIM (-1) + +/* + * The following macro is used to compute the number of bytes we must + * allocate in order to give the user an UndoEvent capable of holding + * n bytes. + */ + +#define undoSize(n) (sizeof (struct ue) + (n) \ + - sizeof (((struct ue *) 0)->iue_client)) + +/* + * Mapping between internal and external undo event pointers. + * When the undo package hands an (UndoEvent *) to a client, it is + * really a pointer to the iue_client part of the structure + * above. + */ + +#define CLIENTOFFSET ((int) &((internalUndoEvent) 0)->iue_client) +#define undoExport(p) ((UndoEvent *) (&(p)->iue_client)) +#define undoImport(p) ((internalUndoEvent) (((char *) (p)) - CLIENTOFFSET)) + +/* + * The following table is used to record the information about clients + * of the undo package. The number of such clients is stored in + * undoNumClients. + */ + + typedef struct + { + char *uc_name; /* Name (for error messages) */ + void (*uc_init)(); /* Called before playing log */ + void (*uc_done)(); /* Called after playing log */ + void (*uc_forw)(); /* Play event forward */ + void (*uc_back)(); /* Play event backward */ + } undoClient; + +undoClient undoClientTable[MAXUNDOCLIENTS]; +int undoNumClients = 0; + +/* + * undoState is used by UndoNewEvent() to figure out the context from which + * it was called in order that it may link the newly allocated event + * in the appropriate way. Events are only linked in when the state + * is US_APPEND. The only reason for having two other states instead + * of one is for ease in debugging. + * UndoDisableCount counts the number of times UndoDisable() has been called. + */ + +#define US_APPEND 0 /* Normal state: appending to log */ +#define US_FORWARD 1 /* Playing log forward */ +#define US_BACKWARD 2 /* Playing log backward */ + +int undoState = US_APPEND; +global int UndoDisableCount = 0; + +/* + * Log of events kept in main memory. + * + * undoLogHead Pointer to first entry stored in main memory. + * - NULL, indicating no events are in memory + * - a pointer to the first event of a command + * undoLogTail Pointer to last entry stored in main memory. + * - Undefined (if undoLogHead == NULL) + * - a pointer to a UT_DELIM event if + * undoNumRecentEvents == 0 + * - a pointer to a non-UT_DELIM event if + * undoNumRecentEvents != 0 + * undoLogCur Pointer to "current" event, ie, one after which + * next event will be added. + * - NULL if at beginning of event list + * - a pointer to a UT_DELIM event if + * undoNumRecentEvents == 0 + * - a pointer to a non-UT_DELIM event if + * undoNumRecentEvents != 0 + * + * undoNumRecentEvents + * Number of events written since last call to + * UndoNext(). + * undoNumCommands + * Number of complete commands in main memory. + */ + +internalUndoEvent *undoLogCur; +internalUndoEvent *undoLogHead; +internalUndoEvent *undoLogTail; +int undoNumRecentEvents; +int undoNumCommands; + +/* + * ============================================================================ + * + * The following collection of procedures completely defines + * the interface the undo package presents to its clients. + * + * ============================================================================ + */ + +extern internalUndoEvent *undoGetForw(); +extern internalUndoEvent *undoGetBack(); +extern void undoFreeHead(); +extern void undoMemTruncate(); + +/* + * ---------------------------------------------------------------------------- + * + * UndoInit -- + * + * Initialize the undo package. + * Opens the given file as an undo log. + * One of several modes may be specified. In all cases, the log file + * is opened so that playback will commence from the beginning of the + * file. + * + * "r" The log file is opened for playback only; no new events + * may be played out to the file. + * This mode is intended for use in recovering from a crash + * without clobbering the crash log. + * + * "w" The log file is created afresh and is available to the + * undo package for use in logging events. + * This is the normal mode for starting a new session. + * + * "rw" The log file is opened for playback and logging. + * Any new events written before the entire log has played + * forward will cause the remaining events in the log to be + * truncated. + * This is the normal mode for crash recovery. + * + * Results: + * TRUE if the log file could be successfully created/opened, FALSE + * if an error was encountered. In the latter case, the external + * variable errno is set to the UNIX error encountered. + * + * Side effects: + * Initializes all the variables in the undo package. + * + * ---------------------------------------------------------------------------- + */ + +bool +UndoInit(logFileName, mode) + char *logFileName; /* Name of log file. This may contain tilde + * abbreviations. + */ + char *mode; /* Mode for opening. Must be "r", "rw", or "w" */ +{ + UndoDisableCount = 0; + undoLogTail = NULL; + undoLogCur = NULL; + undoNumRecentEvents = 0; + undoNumCommands = 0; + + /* + * Deallocate any events stored in main memory + */ + + while (undoLogHead != (internalUndoEvent *) NULL) + { + freeMagic((char *) undoLogHead); + undoLogHead = undoLogHead->iue_forw; + } + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * UndoAddClient -- + * + * Used by a client to make itself known to the undo package. + * The client must supply the following information: + * + * 1. A procedure to call before starting an undo or redo + * operation. + * + * 2. A procedure to call upon completion of an undo or + * redo operation. + * + * 3. A procedure to parse a line in the undo log file and + * return a filled-in UndoEvent (allocated, of course, + * by a call to UndoNewEvent()) that is the internal + * representation of the event externally represented + * by the supplied line of text from the log file. + * + * UndoEvent * + * readEvent(line) + * char *line; + * { + * } + * + * 4. A procedure to fill in a line (null-terminated with + * no newlines embedded or trailing) with the external + * representation of an event based on an UndoEvent + * supplied to it. This prodedure returns the number + * of bytes it stored in the line (which must be less + * than a constant, UNDOLINESIZE). + * + * int + * writeEvent(event, line) + * UndoEvent *event; + * char *line; + * { + * } + * + * If either readEvent or writeEvent are NULL, a default procedure + * is used which simply uses the same internal and external representation + * for the undo event (ie, a text string). + * + * 5. A procedure to play an event forward. + * + * void + * forwEvent(event) + * UndoEvent *event; + * { + * } + * + * 6. A procedure to play an event backward. + * + * void + * backEvent(event) + * UndoEvent *event; + * { + * } + * + * 7. A client name, for error messages. This is a character + * string. + * + * Results: + * Returns an UndoType which must be passed in future calls + * to UndoNewEvent(). If -1 is returned, this means that there + * are too many clients of the undo package. + * + * Side effects: + * Initializes local state in the undo package. + * + * ---------------------------------------------------------------------------- + */ + +UndoType +UndoAddClient(init, done, readEvent, writeEvent, forwEvent, backEvent, name) + void (*init)(); + void (*done)(); + UndoEvent *(*readEvent)(); + int (*writeEvent)(); + void (*forwEvent)(), (*backEvent)(); + char *name; +{ + if (undoNumClients >= MAXUNDOCLIENTS) + return ((UndoType) -1); + + undoClientTable[undoNumClients].uc_name = StrDup((char **) NULL, name); + undoClientTable[undoNumClients].uc_forw = forwEvent; + undoClientTable[undoNumClients].uc_back = backEvent; + undoClientTable[undoNumClients].uc_init = init; + undoClientTable[undoNumClients].uc_done = done; + + return (undoNumClients++); +} + +/* + * ---------------------------------------------------------------------------- + * + * UndoFlush -- + * + * Flush the current undo list. + * + * Results: + * None. + * + * Side effects: + * Deletes everything from the undo list. + * + * ---------------------------------------------------------------------------- + */ + +void +UndoFlush() +{ + if (undoLogHead == (internalUndoEvent *) NULL) + return; + + while (undoLogTail != undoLogHead) + { + freeMagic((char *) undoLogTail); + undoLogTail = undoLogTail->iue_back; + ASSERT(undoLogTail != (internalUndoEvent *) NULL, "UndoFlush"); + } + freeMagic((char *) undoLogHead); + + undoLogHead = undoLogTail = undoLogCur = (internalUndoEvent *) NULL; + undoNumCommands = 0; + undoNumRecentEvents = 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * UndoDisable -- + * + * Turn the undo package off. + * Future calls to UndoNewEvent() will return NULL, and future calls + * to UndoIsEnabled() will return FALSE, until the next call to + * UndoEnable(); + * + * Results: + * None. + * + * Side effects: + * Disables undoing until the next call to UndoEnable(). + * + * ---------------------------------------------------------------------------- + */ + +void +UndoDisable() +{ + UndoDisableCount++; +} + +/* + * ---------------------------------------------------------------------------- + * + * UndoEnable -- + * + * Turn the undo package on. + * Re-enables the undo package after a call to UndoDisable(). + * + * Results: + * None. + * + * Side effects: + * Re-enables undoing. + * + * ---------------------------------------------------------------------------- + */ + +void +UndoEnable() +{ + if (UndoDisableCount > 0) + UndoDisableCount--; +} + +/* + * ---------------------------------------------------------------------------- + * + * UndoNewEvent -- + * + * Return a pointer to a new UndoEvent of the specified type and capable + * of holding size bytes of client data. + * + * Results: + * A pointer to a new UndoEvent. + * + * WARNING: + * The pointer to the new UndoEvent must not be retained past the + * next call to any of the routines in the undo package, as the + * event is liable to be reallocated. + * + * Side effects: + * Appends the event read to the undo list in the appropriate place, + * depending on the context from which it was called. If called by + * a client under normal circumstances, appends the event to the end + * of the undo log. If called by the readEvent() procedure during + * replaying of the undo log, places the event at whichever end of + * the log is appropriate to the operation (back/forw) being performed. + * + * ---------------------------------------------------------------------------- + */ + +UndoEvent * +UndoNewEvent(clientType, size) + UndoType clientType; /* Type of event to allocate */ + unsigned int size; /* Number of bytes of client data to allocate */ +{ + internalUndoEvent *iup; + int usize; + + if (UndoDisableCount > 0) + return ((UndoEvent *) NULL); + + usize = undoSize(size); + iup = (internalUndoEvent *) mallocMagic((unsigned) usize); + ASSERT(clientType >= 0 && clientType < undoNumClients, "UndoNewEvent"); + iup->iue_type = clientType; + if (undoState == US_APPEND) + { + /* + * Normal state: + * Append the new event after the event pointed to by + * undoLogCur. + */ + iup->iue_forw = (internalUndoEvent *) NULL; + iup->iue_back = undoLogCur; + if (undoLogCur == (internalUndoEvent *) NULL) + { + if (undoLogHead != (internalUndoEvent *) NULL) + undoMemTruncate(); + undoLogHead = undoLogCur = undoLogTail = iup; + } + else + { + if (undoLogCur->iue_forw != (internalUndoEvent *) NULL) + undoMemTruncate(); + undoLogCur->iue_forw = iup; + undoLogCur = undoLogTail = iup; + } + undoNumRecentEvents++; + } + + return (undoExport(iup)); +} + +/* + * ---------------------------------------------------------------------------- + * + * UndoNext -- + * + * Delimit a sequence of operations to the undo package with an event + * delimiter. + * + * Results: + * None. + * + * Side effects: + * Appends a marker to the undo list signifying the boundary of + * a unit of events. UndoBackward() and UndoForward() operate in + * terms of complete units of this sort. + * + * ---------------------------------------------------------------------------- + */ + +void +UndoNext() +{ + internalUndoEvent *iup; + int usize; + + if (UndoDisableCount > 0 || undoNumRecentEvents == 0) + return; + + undoNumRecentEvents = 0; + undoNumCommands++; + usize = undoSize(0); + iup = (internalUndoEvent *) mallocMagic((unsigned) usize); + iup->iue_type = UT_DELIM; + iup->iue_back = undoLogTail; + iup->iue_forw = (internalUndoEvent *) NULL; + if (undoLogTail != (internalUndoEvent *) NULL) + undoLogTail->iue_forw = iup; + undoLogCur = undoLogTail = iup; + if (undoNumCommands >= MAXCOMMANDS) + undoFreeHead(); +} + +/* + * ---------------------------------------------------------------------------- + * + * UndoBackward -- + * + * Play the undo log backward n events. + * + * Results: + * The number of events actually played backward. Normally, this + * will be equal to n unless we encounter the beginning of the log. + * + * Side effects: + * Applies the client backEvent() procedures to each event encountered + * in playing the log backward. + * + * ---------------------------------------------------------------------------- + */ + +int +UndoBackward(n) + int n; /* Number of events to unplay */ +{ + internalUndoEvent *iup; + int client, count; + +#ifdef MAGIC_WRAPPER + /* This condition appears to happen just prior to a program */ + /* crash, apparently due to a race condition which is */ + /* difficult to reproduce. Tcl_DoOneEvent() inside the */ + /* DRCContinuous routine is implicated. Can't find the */ + /* error source, but refusing to execute the undo command */ + /* appears to prevent it. */ + + if (UndoDisableCount > 0) + { + TxError("Attempted undo with undo disabled. . . abort function.\n"); + return 0; + } +#endif + + /* Call the initialization routines of all clients */ + for (client = 0; client < undoNumClients; client++) + if (undoClientTable[client].uc_init) + (*undoClientTable[client].uc_init)(); + + iup = undoLogCur; + undoNumRecentEvents = 0; + UndoDisableCount++; + for (count = 0; (count < n) && (iup != NULL); count++) + { + do + { + if (iup->iue_type != UT_DELIM) + if (undoClientTable[iup->iue_type].uc_back != NULL) + (*undoClientTable[iup->iue_type].uc_back)(undoExport(iup)); + + /* fprintf(stderr, "Undo record: type=%d back=0x%x, forw=0x%x\n", + * iup->iue_type, iup->iue_back, iup->iue_forw); + * fprintf(stderr, " UndoDisableCount = %d, undoNumRecentEvents = %d\n", + * UndoDisableCount, undoNumRecentEvents); + * fflush(stderr); + */ + + iup = undoGetBack(iup); + } + while ((iup != (internalUndoEvent *) NULL) && (iup->iue_type != UT_DELIM)); + } + UndoDisableCount--; + + undoLogCur = iup; + + /* fprintf(stderr, "UndoBackward: undoLogCur set to 0x%x\n", undoLogCur); + * fflush(stderr); + */ + + /* Call the termination routines of all clients */ + for (client = 0; client < undoNumClients; client++) + if (undoClientTable[client].uc_done) + (*undoClientTable[client].uc_done)(); + return (count); +} + +/* + * ---------------------------------------------------------------------------- + * + * UndoForward -- + * + * Play the undo log forward n events. + * + * Results: + * The number of events actually played forward. Normally, this + * will be equal to n unless we encounter the end of the log. + * + * Side effects: + * Applies the client forwEvent() procedures to each event encountered + * in playing the log forward. + * + * ---------------------------------------------------------------------------- + */ + +int +UndoForward(n) + int n; /* Number of events to replay */ +{ + internalUndoEvent *iup; + int count, client; + + /* Call the initialization routines of all clients */ + for (client = 0; client < undoNumClients; client++) + if (undoClientTable[client].uc_init) + (*undoClientTable[client].uc_init)(); + + count = 0; + iup = undoGetForw(undoLogCur); + if (iup == NULL) goto done; + + undoNumRecentEvents = 0; + UndoDisableCount++; + for ( ; count < n; count++) + { + do + { + if (iup->iue_type != UT_DELIM) + if (undoClientTable[iup->iue_type].uc_forw != NULL) + (*undoClientTable[iup->iue_type].uc_forw)(undoExport(iup)); + iup = undoGetForw(iup); + } + while (iup != (internalUndoEvent *) NULL && iup->iue_type != UT_DELIM); + if (iup == (internalUndoEvent *) NULL) + { + iup = undoLogTail; + break; + } + } + UndoDisableCount--; + + undoLogCur = iup; + +done: + /* Call the termination routines of all clients */ + for (client = 0; client < undoNumClients; client++) + if (undoClientTable[client].uc_done) + (*undoClientTable[client].uc_done)(); + return (count); +} + +/* + * ============================================================================ + * + * All of the remaining procedures in the file are invisible + * to the clients of the undo package and should not be used. + * + * ============================================================================ + */ + + +/* + * ---------------------------------------------------------------------------- + * + * undoGetForw -- + * + * Return a pointer to the next undo event in the list. + * + * Results: + * A pointer to an undo event. + * + * Side effects: + * None. + * + * Directly modifies: + * undoLogHead, undoLogTail + * undoNumCommands + * undoNumRecentEvents = 0 + * + * Indirectly modifies: + * Nothing. + * + * ---------------------------------------------------------------------------- + */ + +internalUndoEvent * +undoGetForw(iup) + internalUndoEvent *iup; +{ + if (iup != (internalUndoEvent *) NULL) + { + /* + * Return the next event in memory if there is one. + */ + if (iup->iue_forw != (internalUndoEvent *) NULL) + return (iup->iue_forw); + } + else + { + /* + * A NULL initial iup means to start at the very beginning of + * the main-memory undo list. If there is anything there, return + * it; otherwise return NULL. + */ + if (undoLogHead != (internalUndoEvent *) NULL) + return (undoLogHead); + } + + return ((internalUndoEvent *) NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * undoGetBack -- + * + * Return a pointer to the previous undo event in the list. + * + * Results: + * A pointer to an undo event. + * + * Side effects: + * None. + * + * Directly modifies: + * + * Indirectly modifies: + * + * ---------------------------------------------------------------------------- + */ + +internalUndoEvent * +undoGetBack(iup) + internalUndoEvent *iup; +{ + if (iup == (internalUndoEvent *) NULL) return (iup); + if (iup->iue_back != (internalUndoEvent *) NULL) return (iup->iue_back); + return ((internalUndoEvent *) NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * undoFreeHead -- + * + * Free up space by throwing away events from the front of the in-memory + * event list until the total number of in-memory commands falls below + * LOWCOMMANDS + * + * Results: + * None. + * + * Side effects: + * Deallocates events from the front of the in-memory event list. + * Updates undoLogHead, undoNumCommands. + * Guaranteed to leave undoLogHead pointing to the first event + * in a command (not of type UT_DELIM). + * + * WARNING: + * It is important that undoLogCur point beyond the region + * to be freed. Also, it is important that the in-core list + * be terminated by an UT_DELIM event. + * + * ---------------------------------------------------------------------------- + */ + +void +undoFreeHead() +{ + if (undoNumCommands <= LOWCOMMANDS) + return; + + while (undoNumCommands > LOWCOMMANDS) + { + do + { + ASSERT(undoLogHead != undoLogCur, "undoFreeHead"); + freeMagic((char *) undoLogHead); + undoLogHead = undoLogHead->iue_forw; + ASSERT(undoLogHead != (internalUndoEvent *) NULL, "undoFreeHead"); + } + while (undoLogHead->iue_type != UT_DELIM); + undoNumCommands--; + } + freeMagic((char *) undoLogHead); + undoLogHead = undoLogHead->iue_forw; + undoLogHead->iue_back = (internalUndoEvent *) NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * undoMemTruncate -- + * + * Delete events in memory which are later than the current event. + * NOTE: This expects to be called only when undoNumRecentEvents == 0. + * + * Results: + * None. + * + * Side effects: + * Truncates the event list so there are no events past undoLogCur. + * + * Updates undoLogTail. + * + * ---------------------------------------------------------------------------- + */ + +void +undoMemTruncate() +{ + internalUndoEvent *up; + + /* + * If there are events forward of the current event that + * will get overwritten by the new event, delete them from + * memory. + */ + + if (undoLogCur == (internalUndoEvent *) NULL) + { + /* + * Delete ALL events from memory + */ + up = undoLogHead; + while (up != (internalUndoEvent *) NULL) + { + freeMagic((char *) up); + up = up->iue_forw; + } + undoLogTail = undoLogHead = (internalUndoEvent *) NULL; + undoNumCommands = 0; + } + else + { + ASSERT(undoLogCur->iue_type == UT_DELIM, "undoMemTruncate"); + /* + * Delete only some of the events in main memory. + */ + up = undoLogCur->iue_forw; + while (up != (internalUndoEvent *) NULL) + { + if (up->iue_type == UT_DELIM) + undoNumCommands--; + freeMagic((char *) up); + up = up->iue_forw; + } + undoLogCur->iue_forw = (internalUndoEvent *) NULL; + undoLogTail = undoLogCur; + } + +} + +/* + * ============================================================================ + * + * DEBUGGING PROCEDURES + * + * ============================================================================ + */ + +void +undoPrintEvent(iup) + internalUndoEvent *iup; +{ + char *client_name; + if (iup->iue_type < 0) + client_name = "(delimiter)"; + else + client_name = undoClientTable[iup->iue_type].uc_name; + + (void) TxPrintf("0x%x: \t%s \tf=0x%x \tb=0x%x\n", + iup, client_name, iup->iue_forw, iup->iue_back); +} + +/* Print events forward from "iup". If n is 0 or negative, print to */ +/* the end of the stack. Otherwise, print the next n events. */ + +void +undoPrintForw(iup, n) + internalUndoEvent *iup; + int n; +{ + int i = 0; + + (void) TxPrintf("head=0x%x\ttail=0x%x\tcur=0x%x\n", + undoLogHead, undoLogTail, undoLogCur); + if (iup == (internalUndoEvent *) NULL) + iup = undoLogHead; + while (iup != (internalUndoEvent *) NULL) + { + undoPrintEvent(iup); + iup = iup->iue_forw; + i++; + if (i == n) break; + } +} + +/* Print events backward from "iup". If n is 0 or negative, print to */ +/* the beginning of the stack. Otherwise, print the previous n events. */ + +void +undoPrintBack(iup, n) + internalUndoEvent *iup; + int n; +{ + int i = 0; + + (void) TxPrintf("head=0x%x\ttail=0x%x\tcur=0x%x\n", + undoLogHead, undoLogTail, undoLogCur); + if (iup == (internalUndoEvent *) NULL) + iup = undoLogTail; + while (iup != (internalUndoEvent *) NULL) + { + undoPrintEvent(iup); + iup = iup->iue_back; + i++; + if (i == n) break; + } +} + +/* Called from windUndoCmd() or windRedoCmd() with n either positive, */ +/* or negative with 1 offset to differentiate between n = 0 (forward) */ +/* and n = 0 (backward). */ + +void +UndoStackTrace(n) + int n; +{ + if (n < 0) + undoPrintBack(undoLogCur, -(n + 1)); + else + undoPrintForw(undoLogCur, n); +} + diff --git a/utils/undo.h b/utils/undo.h new file mode 100644 index 00000000..29bf4abb --- /dev/null +++ b/utils/undo.h @@ -0,0 +1,93 @@ +/* + * undo.h -- + * + * Exported definitions for the undo/redo module. + * The undo/redo module is designed to be as client-independent + * as possible. Communication to and from clients is by means + * of objects, allocated by the undo package, known as UndoEvents. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid "$Header: /usr/cvsroot/magic-8.0/utils/undo.h,v 1.2 2009/09/10 20:32:55 tim Exp $" + */ + +#ifndef _UNDO_H +#define _UNDO_H + +#include "utils/magic.h" + +/* -------------------- Exported definitions -------------------------- */ + +typedef int UndoType; /* Type of undo event */ +typedef char UndoEvent; /* Externally visible undo event */ + +#define UNDOLINESIZE 300 /* Maximum number of characters in external + * representation of undo event. + */ + +/* + * Procedures for manipulating undo events. + * + * UndoInit -- start up the undo package and assign a log file. + * UndoAddClient -- used by a client to inform the undo package of + * its existence and to obtain an UndoType used in + * all future interactions with undo. + * UndoIsEnabled -- returns TRUE if the undo package is turned on, + * and FALSE if it is disabled. + * UndoNewEvent -- returns a new UndoEvent which the client may load + * with its own data. The event is appended to the + * undo log. The client should not retain this + * new event past the next call to the undo package. + * If undoing is disabled, returns NULL. + * UndoNext -- used by a client to inform the undo package that + * all events since the last call to UndoNext are + * to be treated as a single unit by UndoForward() + * and UndoBackward(). + * UndoBackward -- play the undo log backward N units (until the prev- + * ious call to UndoNext()). + * UndoForward -- play the undo log forward N units. + * UndoDisable -- turn off the undo package until the next UndoEnable. + * UndoEnable -- turn the undo package back on. + * UndoFlush -- throw away all undo information. + */ + +extern bool UndoInit(char *, char *); +extern UndoType UndoAddClient(); +extern UndoEvent *UndoNewEvent(UndoType, unsigned int); +/* extern UndoEvent *UndoCopyEvent(); */ +extern void UndoNext(void); +extern int UndoBackward(int), UndoForward(int); +extern void UndoDisable(void), UndoEnable(void); +extern void UndoFlush(void); +extern void UndoStackTrace(int); + +/* + * ---------------------------------------------------------------------------- + * + * UndoIsEnabled -- + * + * Test whether the undo package is enabled. + * + * Results: + * Returns TRUE if undoing is enabled, FALSE otherwise. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +extern int UndoDisableCount; +#define UndoIsEnabled() (UndoDisableCount == 0) + +#endif /* _UNDO_H */ diff --git a/utils/utils.h b/utils/utils.h new file mode 100644 index 00000000..94cc2b94 --- /dev/null +++ b/utils/utils.h @@ -0,0 +1,90 @@ +/* utils.h -- + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * This file just defines all the features available from the + * Magic utility routines. + */ + +/* rcsid "$Header: /usr/cvsroot/magic-8.0/utils/utils.h,v 1.2 2009/09/10 20:32:55 tim Exp $" */ + +#ifndef _UTILS_H +#define _UTILS_H 1 + +#include "utils/magic.h" + +/* + * Cast second argument to LookupStruct() to (LookupTable *) to + * make lint very happy. + */ +typedef struct +{ + char *d_str; +} LookupTable; + +/* The following stuff just defines the global routines provided + * by files other than hash and stack and geometry. + */ + +extern int Lookup(); +extern int LookupAny(char, char **); +extern int LookupFull(char *, char **); +extern int LookupStruct(); +extern int LookupStructFull(); +extern int PaExpand(char **, char **, int); +extern char *nextName(); +extern FILE *PaOpen(char *, char *, char *, char *, char *, char **); +extern FILE *PaLockOpen(char *, char *, char *, char *, char *, char **, bool *); +extern char *StrDup(char **, char *); +extern int Match(); +extern char *ArgStr(); +extern bool StrIsWhite(char *, bool); +extern bool StrIsInt(char *); +extern bool StrIsNumeric(char *); + +extern int SetNoisyBool(bool *, char *, FILE *); + +#ifdef FILE_LOCKS +extern FILE *flock_open(); +#endif + +/* The following macro takes an integer and returns another integer that + * is the same as the first except that all the '1' bits are turned off, + * except for the rightmost '1' bit. + * + * Examples: 01010100 --> 00000100 + * 1111 --> 0001 + * 0111011100 --> 0000000100 + */ +#define LAST_BIT_OF(x) ((x) & ~((x) - 1)) + +extern float MagAtof(); + +extern int Wait(); +extern int WaitPid(); + + +#define FORK_f(pid) do { pid = fork(); if (pid > 0) ForkChildAdd (pid); } while (0) +#define FORK_vf(pid) do { pid = vfork(); if (pid > 0) ForkChildAdd (pid); } while (0) + +#if defined(SYSV) || defined(CYGWIN) || defined(__APPLE__) + +#define FORK(pid) FORK_f(pid) + +#else + +#define FORK(pid) FORK_vf(pid) + +#endif + +#endif /* _UTILS_H */ diff --git a/windows/Depend b/windows/Depend new file mode 100644 index 00000000..17fdaf7b --- /dev/null +++ b/windows/Depend @@ -0,0 +1,54 @@ +windClient.o: windClient.c ../utils/magic.h ../textio/textio.h \ + ../utils/geometry.h ../windows/windows.h ../graphics/glyphs.h \ + ../windows/windInt.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/main.h ../utils/macros.h \ + ../utils/utils.h ../utils/malloc.h ../graphics/graphics.h \ + ../utils/styles.h ../textio/txcommands.h ../utils/undo.h +windCmdAM.o: windCmdAM.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../textio/textio.h ../utils/geometry.h ../windows/windows.h \ + ../utils/malloc.h ../utils/runstats.h ../utils/macros.h ../utils/hash.h \ + ../utils/signals.h ../graphics/graphics.h ../utils/styles.h \ + ../textio/txcommands.h ../graphics/glyphs.h ../windows/windInt.h \ + ../tiles/tile.h ../database/database.h ../dbwind/dbwind.h \ + ../utils/utils.h +windCmdNR.o: windCmdNR.c ../utils/magic.h ../textio/textio.h \ + ../utils/geometry.h ../windows/windows.h ../graphics/glyphs.h \ + ../windows/windInt.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/main.h ../utils/tech.h \ + ../utils/runstats.h ../utils/undo.h ../utils/utils.h \ + ../graphics/graphics.h ../textio/txcommands.h ../dbwind/dbwind.h +windCmdSZ.o: windCmdSZ.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../textio/textio.h ../utils/geometry.h ../tiles/tile.h \ + ../windows/windows.h ../graphics/glyphs.h ../windows/windInt.h \ + ../utils/undo.h ../utils/utils.h ../utils/signals.h \ + ../textio/txcommands.h ../utils/hash.h ../database/database.h \ + ../dbwind/dbwind.h ../graphics/graphics.h +windSend.o: windSend.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../textio/textio.h ../utils/geometry.h ../windows/windows.h \ + ../graphics/glyphs.h ../windows/windInt.h ../utils/stack.h \ + ../utils/utils.h ../utils/signals.h ../textio/txcommands.h +windDebug.o: windDebug.c ../utils/magic.h ../utils/geometry.h \ + ../windows/windows.h ../graphics/glyphs.h ../windows/windInt.h \ + ../textio/textio.h ../textio/txcommands.h +windDisp.o: windDisp.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/utils.h ../textio/textio.h ../utils/geometry.h \ + ../graphics/glyphs.h ../windows/windows.h ../windows/windInt.h \ + ../graphics/graphics.h ../utils/styles.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/undo.h ../utils/signals.h \ + ../utils/malloc.h +windMain.o: windMain.c ../utils/magic.h ../utils/geometry.h \ + ../graphics/glyphs.h ../windows/windows.h ../windows/windInt.h \ + ../utils/stack.h ../tiles/tile.h ../utils/hash.h ../database/database.h \ + ../textio/textio.h ../graphics/graphics.h ../utils/malloc.h \ + ../utils/utils.h ../textio/txcommands.h +windMove.o: windMove.c ../utils/magic.h ../textio/textio.h \ + ../utils/geometry.h ../windows/windows.h ../graphics/graphics.h \ + ../graphics/glyphs.h ../windows/windInt.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../utils/malloc.h +windSearch.o: windSearch.c ../utils/magic.h ../utils/geometry.h \ + ../windows/windows.h ../graphics/glyphs.h ../windows/windInt.h +windTrans.o: windTrans.c ../utils/magic.h ../utils/geometry.h \ + ../windows/windows.h ../graphics/glyphs.h ../windows/windInt.h +windView.o: windView.c ../utils/magic.h ../utils/geometry.h \ + ../windows/windows.h ../graphics/glyphs.h ../graphics/graphics.h \ + ../windows/windInt.h ../textio/textio.h diff --git a/windows/Makefile b/windows/Makefile new file mode 100644 index 00000000..0b310026 --- /dev/null +++ b/windows/Makefile @@ -0,0 +1,27 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/windows/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +MODULE = windows +MAGICDIR = .. +SRCS = windClient.c windCmdAM.c windCmdNR.c windCmdSZ.c \ + windSend.c windDebug.c windDisp.c windMain.c windMove.c \ + windSearch.c windTrans.c windView.c + +GLYPHS = windows7.glyphs windows11.glyphs windows14.glyphs windows22.glyphs +FONTS = vfont.B.12 vfont.I.12 vfont.R.8 + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak + +install-tcl: + @echo --- installing glyphs to $(DESTDIR)${SYSDIR} + for i in ${GLYPHS} ${FONTS}; do \ + (cd $(DESTDIR)${SYSDIR} && ${RM} $$i); \ + ${CP} $$i $(DESTDIR)${SYSDIR}; done + +install: + @echo --- installing glyphs to $(DESTDIR)${SYSDIR} + for i in ${GLYPHS} ${FONTS}; do \ + (cd $(DESTDIR)${SYSDIR} && ${RM} $$i); \ + ${CP} $$i $(DESTDIR)${SYSDIR}; done diff --git a/windows/vfont.B.12 b/windows/vfont.B.12 new file mode 100644 index 0000000000000000000000000000000000000000..1342574e770669c8c81f2fa9ef8efaa659e33cdd GIT binary patch literal 9038 zcmeHMO>87b6@KmBb$kD&ytZe?c1(8y5+DU7xj-hQH65XZ1c9QJIOKv9qzEE7O_W1= zwZn9+B4s)4A|wz4b2XX=;fwHw)&>{}_0tlqYDa#SQL~%J5xR;sf;(JvyvtGy9 ztQ90K+x4nlQ(g7mtM^y0%5m`c(qr^lTBNs1fJ5AGx-D-J> z*3b%q!Qwo0ikTaG~-AmsOUZjR=^@BNT>NC~cX?k+%7&YG?&dku6sV~sdjjFytuS`8eP1pMM)C06U9Lz7!J5$fma%7uLdNSlz zwbZ27!f(^^4EO#2pV=c#ta5PdIDO{GEH&OAo<2+b98e05t^sL(lR|U z9nsWLp7FKmBdi(BI5Qp6l;hy*)1RYy@Sl2G}z%FKA&#Yx}aCVlrDn2uPl&+wMzf8XRG2^!zljG@hjL`vj zx0G4g6RI2OKI96xtas0k0B!UXeccl}vnsJtR6GTZworxD=Pb|Kd0X$`J=8llxPcyE z15RL0U}uhaHYh5))~|NBs7YDtuN75RC8Zw~s)AAn-GoYpz(A-;2vA9+5+NB9N@7ad zR9G;f$U$HgAaoE}1rWR7cz{`L2i-{Jktz#QQC?A5k!c42-3|eM3|2+$gxWE++tf~} z-6fa~TaQhHtu)kWsL}|slBGCr1h|S+EM%Gx*v*;Ufe{sKuPD=^?B+RO(8)_WTSk2o z?P#)^3gtj{3Yizwt)Kw#xqlU-CEU7-9@AE(TSbScQ@V%s35B8qPg!>Il<9U@$0*v+ zj-m|-2sRyDr{Fq;s}3$gh8hsPO3?~~NU>xEsI@508CE)!0t`b-Q?BW(gQ%qBP0BJV zGP#*4z-}gOi;5OyElNs?;2)NvOfo#GqDRzAk0|S4_fdsemg{W)xGpoqHw3p8Lb#%w$Pj!vyk?>cWh7EjTZwBcX)Vn~%S5FPb!bM|YAMy+LV!6c zyOHUIx{7oqwsm`3b^9tWB;tz!BxHmv6P0K0^=?!`ck?oDHc18kwAuNcsUe?W}z*NUJbfjz4ri@zULY>DBR1n&Yh5MjFy*@qz(5|TGRY=|%* z#Z7M{oj^f(I#BjywYeqNt<(rtK$1BmP_|2$A0Rd%9JZWV*mWHgB~?8_oP!lk7@*Mc z;G}3G*@2`J%6b$TcsE4|z?UeA5UNAkUvDX3Aet>%;3L|1VHpU8PuGmJB0cDx{!~)-A z9gwYK39~Q&{?BIB<0*`1&tNx9b%kmtD#?^Uh;%w?Ih$e|OsEBW#3rT*e(S>DBnIC4 z+c`Ba2`ho9GhQQB2g|`PtQgD1qM@o-;0yw339=H5+W+`|KYcVDbHNLc zGA>Maa`ZOp1nXJAcZ|Z=q-=Ndwu#H66j%`?3eqLQndEYlo(~?p*F{&^jk*}hfucsa zwe-TyF1@(ED|fE$$c?KTa+B+MUw6-M%9pNf(u*5gbQVU^0@4(fXTw-1+|}5z(18!& z&_l&`4nU$9tTKeFGQ7YLT~HB1LafN;l8>mcn*bm~Cm$qL25D=ANHs7PQ4&f5g*&Loh3;tF2p8jqwlU{U zi`5ZQv)h&2lqlM4n-_GU6Y2TSK>>aNZx!%5!SRem7Nf%01&jlM##b1&xQxo*;iNDQ zKZiXN?&|Qs%Gk$%n;`0a!vCnB9YFvX+fCr3jYc*H_ZD(odnDAjRtRIGx{klwYgFU9 zgW7+UYUfZ3t})fJQAM6w!^XqazJ;VMutK(ka-drRU|O}(LAO;)TeWtpmb7XD@J1~v zYoUXntN{p+b1YFU$X{HNoHrxk4ZPp6@#IJ@DK}$48$Ax3UAbf$nL2!S>~~mxd62K& zbaTO`cRTU2ogb2)v!y92lU*{I(1{rHV-d_HMQ^wy5kU_T#s>sACiwBbkN1Q(geeIV zfh92@+<8D?32@Y{7^uQgC#iHQbRKCFYUEEQ&^c)Y(G0O2%){tF8apnm3-fbt{=SJdU4t?)FFcPVf;eQ9*oeDSY;d?Jl#n<~$#f*Uj^|-p6KyM^bEpOI zK$fn?_!s;nrvEV~gr zXq1@cM&n$Q;EalsTFilrleYpyspkR^!jO-}B~BBW>>(0wAl!npg8=w(b%ER?WVs=| zVPHwShPx}{D+vs+G6p|52_q5Z*dcLVU|M6ZEhm`?XY8Z&o3-y!*?sS5S0;sQCvuz# zPa(tq~Ckz1Ha2Lnk30-oTvqY-nNgqfz(!wMttSc_KHXOAM`inc19VH5d-32g- zk7(d0E=MwV%IvrW!jvfAMT(aQ<1Qj59e5vaU^56{uoA$+Yu-LfCJ2%gi9&@BxH;`p-|h^ z^7cGJs<#xYDvN_mvQ+^i-zY*ZATqg8JXFhFQ&xwRFq>0v??H^U=}-0to+7J5y2%H9 zjSn-2v-yJ@Co@&y9ClSEI2t?G$NPiid=H3bRbH94j>{OgZ&DbNk&6+xdqb51&S!OSV}QHkb|~Wz2^JCy>~a)gZv$XA0}S{^12769 zn(S(!k_7QH!Iqxd_8as0x1W6>5} zQ3`8CoaVX9cJe%pYi+!^$90viYi}xaaGU3ho-{Xkni{+&J?P5hN}*TInH4igbuZUR HiTL+l($Sky literal 0 HcmV?d00001 diff --git a/windows/vfont.I.12 b/windows/vfont.I.12 new file mode 100644 index 0000000000000000000000000000000000000000..a6b08b2ace12d20ef1c1ad130390ab12f52a0a0e GIT binary patch literal 9231 zcmeHMU5q5xRsL>QPgn15O?U77bXU)oyL;Cl@?e=F8`-sZ*zRD5M8pC`K}rO%sAZ(s z5`vVo0k_F$=dQ3B6ZZZNYf6pl%h0L}e}CM*4Zo|FP}#?kGXC(e_I33~q=J(be7xXlrz-ev zVF~qX2SF7-DEu^5%ahu1-02-bh0n+?n|1uw!Y9!v zjKfu!h0k%^LDWQ4`WS2DXbtB|KI&JmbM8Z>`?#aGR;u{At4*s_3`=XMU%y^o!cqSW zmN9Ou;a=ZIVPWha#n1ai(F|q!3%-YflD1FzKZ{lMRIZcSzgPDvIS# zprH=P%l&1?0ein%mKo#vD*iFAv3K=|jFY(!9FcLO<|_W&wT;>KU#?AhfAVMzRkeTY zD7r^iP+d4+?bAosu}peRJax2%>b~&&jl;J8JbI_d;P^5c$At31T7=IXlhvm6I{xxl z%Gx9fQ4FN*trHF0?`o5^5PuNly$$?eR;%Ne7V~jU{PCjeZLeXxNE=d(6+ zu6AQ>72nBgX#+ls3Xh@USX$GO!{pjMtPui~#)W!!}0uB-}`X=M>n{j7`&7V*n<*UNFw z)TQ@;ZU0d3agE8T+p*XX4yIv1xOgGi8aVQT12C&Vcb`#@GA zR&q=Oz;cj74m2T@Np7M(qdnawl7=A3?alBCf5*fT5g=`kJ^oW%yQ&fSM9xS&x2{{; ztvg#g<@&d-ZO8-H#(Zr}9=Nu8$J)DGN!I^9@#fkWT5b`4`#O9wQBmI_a_^p?R@3R2 ze2^C(4xJ2GpUXjbv4XeAg8V2ai^>P#E#~BKv$*@|UOM3Ot=fvlm$N zk;=<9wR@Fdnz{nhb}uIp1Y7|DWr1e2Gy|jWgDaux7~GwjpbrlU4Y# zqE)`|f5_SiE&P#{cd*vQIc;?Q7=2E6xm%w$$y^y2(#q>A%KXMC^b{ zrDNJinMi30o??%DL=^`Sm{vy#w!Vq2M}XG_)W1Vb;XM!U5%>?HL}$2++onU#qWKUq z8VRjq%Z!kYU`KQ~8kN$CM{r|GNCG4gk`PIPBu0{9`i0^2^&wu0)srzT&yz4h@3HhU z8WV|!6~vL)AT7|gho(9*z?O}-Y?h{kVK22fXZ>B{4>a~P9t6Gs{3d!AkZvLyp}UVZ zcQL(X7k>wz4!wse;g((W-7c)#MUUp{`+lWT34$;TYjI4gVH7c%e@Af`$DNpZPE8N$ z5>ydhfKn(B!~$W8S`V@Dry~M(K&9X@8QYy2!fb2}<&GPhax79!JH$ubSkP}CHtNsP z(y2H&m6d-jEB{;?+=t42@E?cA*f@cD2CA*qae+cjpE`**PU6jzc;P|ZcRx1!U@$3b z38Y#*^@J`g?4wjH@x~OO7?RmIqfe$_K;&+@JBCm&R7qS%M(kx!7oUb#;ND6Bf?^qA z5F+FLdL;`@heZoG4V;6py#s6mF9I+5c=Z^D4cNQ9VOoiM>#>Q?=&XsfB@vNe&cZ$z zUL6eEuyGd0snJ|JM2r+hX%9XsY>3z-jWHQYT`_oPk@gOY+zD8f!7_;qzpLcrZW6T0 zt>tm+hl@iQPkZ|Gb6=+8_~_c}!z*OC#Sx_bLt!cb+Wye4ywTdUllBZ_xv{nfG7G+q zNZxaDF9Kx<|FknM;(8Pqa=;!gOqJw4oTee>tOnXs+E<3M3_w3NAxx|YI&+YEI`tqx zhZ3IxT|P~aWjJF|C6O3I?{7+P6RgNXN**wLlw9H7d{7cFnL<)PNXMktmxQMbu<(o! zT$idZdd&IN9q1JLf~N;h;o=0EC+pOxi?)EYh_oVL$vc#Rr*Xkag7TnL9CWx3k37Qo z=vB~*(04X1gMFTIzzN`P;PYa1bS?2g>YSR45Qj)Z@bnZOb0DXwfIns|BUO=ZX)fR+ zjJs8Y3_|nO-^POvQ$nwWUV=X3I#s|UZA-%%PxnL#3|Ne$ZsW-ar~eceN|1o!!8$P9 zMG3|!%dR8M@TgM)N&V`MPOrgq!7;i3O`a%0@=R_iT4y5ME*H!NOIt|hd&)r9G!h9oMqINb=44ylo*g{NnWrf!|KO|mpGp^a=nned$A zFzZn#Qf@x^@lPM5;saz1HZjWSaj}>UR0Mp?md3*_LJuh zMjfX%h9BC!cUkkxsaw~vMz>a{yZw3r}lE zr~Zh!C~0#)V!o+EPUSDz7rPP{66;gCPval)R}#Dc9&Kul5(7(=4G(IHCF5U~DV@P| zLN>RwvZR&J?JIJM)4yuD6{ZkFC0MR-E6g|+3!{wIhw!yqo4Y5ZG(8udEInfej5`w2 zbjc&2LdHCVWTzxaK~_FOO}v=afOi{x8sXv4!;WUm76k=Qt&M*fPqd?@OLcd6X9Lv=ueImuS#LMWa?;iOA$oJo@_^T_%TAj_AiCwLIuVMTW{ZZZsz_m&=kvzy4A2hx~E|5pn=Z+{t4Qb)=nW zMZ6A6{GH>w{Y9()37>-<{qlzXkDtKsZe(ZYd_Lx>qyV)D zHEKLWhY$;-ZuMRYle+9pP8~u)?Bg(uPu1AvSG^FLH^@*iz2N_<5EVfKj>_OQK`ufa z1oXQe0uB1XqRZJ1xnjaQjV^>yS>TRZ_@Ov?sFQp)jbH7>PxpQ*)P&Pb{oy9=I)RU@ zVY7w)NAM62Wd~$bc%{5L@Wyl#=B9}04oQ)*Mp7lloQNJCQL;Q#UDhUPuh^K_*9qcj z;_Vu^mq^_z3ba7E7OCGdu?7o?uv0zekr&8O#-vIPC%+`=rdNjd`|zFx=j6KZG>u~h z{#+ONmbXZMI#F5 zQQI}XZI9N&emM(m*-|VfFQJWX_AvX!g(xZ~EqFQy|MHxry0FAhW%&W&?JRML^ilJ$ zW65)iB;~A}hBmRoftg|`3x#Q%$s+uk!xM=T@H13mwB+WiB>o#Yt_ajx4t=LSYA^>2 z@|*)%%;B8Id5!C{AOsAJf5TK4b!CCyJap*0G|QKdAu;b*E?tUSa;u3pkcG`qdW67M$stRlzx z(<0psy`i`DHYDvW(Q|m#hd~^~m9%OZ=|q#WM_F%JVowm4#kevS>xxmXcv{M3eowl> zAUXUI3^Pi$5p;EQw~hu#+}60e(@toV+qoV6+CbX@>=l?XuN=Zs{;@!Kk+fZkte(-# zEepS#;j&wFz2)l*-KxDjcrLrVGmM|mHhxN(nBTSKGo)b3tCD3rvyqRT(8qxJ=YZn6 zLQRZY{P5P+8?TuSYqw3x={`XjLPco-?^57hio7Qy@99vDJkz%8NfKsZ8d?@3C1J@@ zXT9FQ_^%Ix%_QiDwJfR)nROGyQk6iWEFtrr&Ah+2UfVFZ_zpz14w!Tiyg_?!{jQ{* zwbB;vFXBb{I(@D)><%f2Togv}BU*Jd+sCfn*wfnsJfYze-cC8s+^F4NMAEIooLf~lF>Fx#?JET@Zsh>1+?lv}u|jX2i^KdqkAkMQViA?_mE(1dhb+ih5% zpya|z1rP%N5}{IkvU<f>I6Nyy3sHeP7 z+Xs1y4U|c@mFYY|P_v`=2Kw~@4qnD+{C@VsEouJiy4rClJ+8zZVzdE|mpQdqGPWX}**JNGOdz=gGmN~PBH}N!%Z*7tf Wac5E6(zOk0b{Ok^s@qmq&3^+XVmVU) literal 0 HcmV?d00001 diff --git a/windows/vfont.R.8 b/windows/vfont.R.8 new file mode 100644 index 0000000000000000000000000000000000000000..b300a2cbee73d35b3019d0f33a4d653b812f1b48 GIT binary patch literal 5538 zcmeHLO^h5z6@K%x)3Y-@(>)IM_B!pIUK>n=7Sd}=sG}r16Dd+SSop#LA%V&`L=m=> zvG~a%mfec8I3}{>2rm2_!YwEVSViPOgix7{uw^ZAkPtCHNh$=S5Mj|FQZkEsy7^x9 z&g>71IC61)y)$3Gs(SV6y{cC=J5~5@y-RnHM_WrkP9bv~3V@t-bLP4vs7%()%x%$w zV1>fKY0$$|qViy{_XBi_Dl|SIt3qc+>`@A#CEd4|o*A)M$Rekoj@RfljNYtd^*U7w z6>{EB$0}qOJaUt)(WDO=mV(_=n4(rXu$%Om!VI;>*uHZk_S}eVoyY%&zgBRlSs092 zbR(ZptxoS2c$R6?q1%fG$u01V?k%!+Q+V>TBleBr7&-58-?PODYE=gC(Dw{Wt2J6F z*2uY;)NOj9xStv{K;PdMD^x6Vk3STP92vCxQ?W!vW5MgiDcF)U92(?fVB7;GwlAqS zX{KZ>fb7_aoi1??_WhHFv86v6)m|B~w??d59%{LxT&J2D_h`9EHDlF%WuF>YC7314 z25j>wBTFHBBJYbCJ(IINx6$P?dx+!vH^WlLrTUohTGOSE<_xmqBiWe^=FoR?)@sr7 z8*C4~GS*^`SF7|^F2h=@RgAutOEWoZH0YB#+p~vy8?`O^cFr)`Pe<%`m5-1+##WJK zv|v{p%o+TA{|0N)Lpf{hq4S23>(H~-QJx#dcy%PpjErE*k*d)LEuX3mqkpQ(@krsJ zZy6b{gCF9r{x4ol&sNPIgin7A)-)^Ux#~Vdf#Y_?=*yt*?ObLzh{khII&^T{w1X@f zcX^+WkJBf{1NbI`>|xW6qwr*2YgOs{<9o@eWR)uYB(H@9zZqxmW~lx1_%x3@v6o6U z*35k;4P#sGtQpO)<+x#Kvq_KS?J&1*=Iy|KP&4bVR->Pdv|P(s!=}IH4Dr3WA!|~r zo@;K|S4bsk!KX)#LhPXKy!5k}L&cAX5uTnkEaWDb7XdCn}0nC@2t=WjYYz zzdh^gv2~IBfsWqMp=tI%+ed5X&Yt^wWE0~t`AFSs|2?vZI#tqrGb@ zudZAVf4`EgEXDJ2M?11jOY#l%ntok8ZSY5}b*4JfrVcI94S5Y%BgU`g4Y?%e%t)~x zdtnrYVJ{S+npLwh)0wsaN4J4F-RbwV&`Phyv4^%?#HejQORTlZnr+*@7kRx<_Y{mw z)I#Q8_E#e-oa(jXk}j!LmFcBj^lIo;!_p-JJ$Z8VmuJsbL`9Ul<*u!4Rh3Keq@0v3 z%Jfk>LQm)RuKs)3xAg@OE%joKkIE>$Co{w;ZmCc~y|O zd{UF_d2cOT78lfY*|VXcWpKOS^!>D- z>z5V2JgU zfB;Yh>pD^>!Oi(=2t)3cZHnfvdz&R~%P%RVmC%B8L6u~aB32a0pf4_}Clpo#hU6xs z99fbW10!ixt53jPFa;Qs4R*Mkl_%tVGK&i^u^=tIq`Jh&=nV>qWg###BnhWi5s5lHw_|HxP^w@`>hMmgLtr`wOklz_#2K5Su1KpV1wR z&o3u1{v5#~QxumGg`1H%dIe=+pn1|jNIqFqP%uB_u;gtCE2T@lyiTH7#J=NxKBSuF z=uvq|DyiX$l4NaFfJ@a(p`@nfLt9iH_~%PUE*w2Sd;aM8BWs^Oo?;N&k1SOrjn9m#oaCzk0&x&W*pc*z`;gqWV1mWSvt-AQ+2jbg&uOgVzm zk&$fZ2&0iQopeGw^g}=LqnSHqP)^SrJACZ$g~JyPG3@n@UJTs`m~lVm9(F(M9(ro} zsp*%4m*Ku1Mi2Y0MF$iz0#DaN6gMC|GyR?k!`4v3W`uIn8ZfwUR~-*|kF3nEgfVm| z{PSWS2(c{UZOekUvoc{8!9s9P5;^oW?26nG^9ZP=uwKnOyQZ%%BCjt8L+tc0zjq{j zTip#|HT0s;7nX$Qsvg6&T|2ac3Zq-_`kQB61kIBbmo@Y4A@E+pDqk~NMO_JF8k?@WZ2v3NV;h9~He_>FGM*)&yrr-9R z6p{JvQoUHYoJ^EdszWD`<_fZdWPx{iNxiA(L=2@vOekM_J={j}5_(uQ6Ud>nQm|1n z-`Yam1zBmh&+*;HDQ#MCD->i_H5Cv0WypJsyx&xN!gbS)5nMNEiK|qU1Izae` z7xBqIczSkucI~z+`>*W(^i + +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/glyphs.h" +#include "windows/windInt.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/main.h" +#include "utils/macros.h" +#include "utils/utils.h" +#include "utils/malloc.h" +#include "graphics/graphics.h" +#include "utils/styles.h" +#include "textio/txcommands.h" +#include "utils/undo.h" + +/* The following defines are used to indicate corner positions + * of the box: + */ + +#define WIND_BL 0 +#define WIND_BR 1 +#define WIND_TR 2 +#define WIND_TL 3 +#define WIND_ILG -1 + +/* our window client ID */ +global WindClient windClientID = (WindClient) NULL; + +extern int windBorderCmd(); +extern int windCaptionCmd(), windCrashCmd(), windCursorCmd(); +extern int windFilesCmd(), windCloseCmd(), windOpenCmd(); +extern int windQuitCmd(), windRedrawCmd(); +extern int windResetCmd(), windSpecialOpenCmd(); +extern int windOverCmd(), windUnderCmd(), windDebugCmd(); +extern int windDumpCmd(), windHelpCmd(); +extern int windMacroCmd(), windIntMacroCmd(); +extern int windLogCommandsCmd(), windUpdateCmd(), windSleepCmd(); +extern int windSetpointCmd(); +extern int windPushbuttonCmd(); +extern int windPauseCmd(), windGrstatsCmd(); +extern int windGrowCmd(); +extern int windUndoCmd(), windRedoCmd(); +extern int windCenterCmd(), windScrollCmd(); +extern int windVersionCmd(), windViewCmd(), windXviewCmd(), windZoomCmd(); +extern int windScrollBarsCmd(), windPositionsCmd(); +extern int windNamesCmd(); + + +#ifdef MAGIC_WRAPPER +extern int windBypassCmd(); +#else +extern int windEchoCmd(), windSourceCmd(), windSendCmd(); +#endif + +static Rect windFrameRect; +static MagWindow *windFrameWindow; +static int windButton = TX_LEFT_BUTTON; +static int windCorner = WIND_ILG; /* Nearest corner when button went + * down. + */ + + +/* + * ---------------------------------------------------------------------------- + * windButtonSetCursor -- + * + * Used to set the programmable cursor for a particular + * button state. + * + * Results: + * None. + * + * Side effects: + * Selects and sets a programmable cursor based on the given + * button (for sizing or moving) and corner. + * ---------------------------------------------------------------------------- + */ + +void +windButtonSetCursor(button, corner) + int button; /* Button that is down. */ + int corner; /* Corner to be displayed in cursor. */ +{ + switch (corner) + { + case WIND_BL: + if (button == TX_LEFT_BUTTON) + GrSetCursor(STYLE_CURS_LLWIND); + else + GrSetCursor(STYLE_CURS_LLWINDCORN); + break; + case WIND_BR: + if (button == TX_LEFT_BUTTON) + GrSetCursor(STYLE_CURS_LRWIND); + else + GrSetCursor(STYLE_CURS_LRWINDCORN); + break; + case WIND_TL: + if (button == TX_LEFT_BUTTON) + GrSetCursor(STYLE_CURS_ULWIND); + else + GrSetCursor(STYLE_CURS_ULWINDCORN); + break; + case WIND_TR: + if (button == TX_LEFT_BUTTON) + GrSetCursor(STYLE_CURS_URWIND); + else + GrSetCursor(STYLE_CURS_URWINDCORN); + break; + } +} + + +/* + * ---------------------------------------------------------------------------- + * windGetCorner -- + * + * Returns the corner of the window closest to a given screen location. + * + * Results: + * An integer value is returned, indicating the corner closest to + * the given screen location. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +int +windGetCorner(screenPoint, screenRect) + Point *screenPoint; + Rect *screenRect; + +{ + Rect r; + + /* Find out which corner is closest. Consider only the + * intersection of the box with the window (otherwise it + * may not be possible to select off-screen corners. + */ + + r = *screenRect; + GeoClip(&r, &GrScreenRect); + if (screenPoint->p_x < ((r.r_xbot + r.r_xtop)/2)) + { + if (screenPoint->p_y < ((r.r_ybot + r.r_ytop)/2)) + return WIND_BL; + else + return WIND_TL; + } + else + { + if (screenPoint->p_y < ((r.r_ybot + r.r_ytop)/2)) + return WIND_BR; + else + return WIND_TR; + } +} + +/* + * ---------------------------------------------------------------------------- + * windMoveRect -- + * + * Repositions a rectangle by one of its corners. + * + * Results: + * None. + * + * Side effects: + * The rectangle is changed so that the given corner is at the + * given position. + * ---------------------------------------------------------------------------- + */ + +void +windMoveRect(wholeRect, corner, p, rect) + bool wholeRect; /* move the whole thing? or just a corner? */ + int corner; /* Specifies a corner in the format + * returned by ToolGetCorner. + */ + Point *p; /* New position of corner, in screen + * coordinates. + */ + Rect *rect; +{ + int x, y, tmp; + + /* Move the rect. If an illegal corner is specified, then + * move by the bottom-left corner. + */ + + if (wholeRect) + { + switch (corner) + { + case WIND_BL: + x = p->p_x - rect->r_xbot; + y = p->p_y - rect->r_ybot; + break; + case WIND_BR: + x = p->p_x - rect->r_xtop; + y = p->p_y - rect->r_ybot; + break; + case WIND_TR: + x = p->p_x - rect->r_xtop; + y = p->p_y - rect->r_ytop; + break; + case WIND_TL: + x = p->p_x - rect->r_xbot; + y = p->p_y - rect->r_ytop; + break; + default: + x = p->p_x - rect->r_xbot; + y = p->p_y - rect->r_ybot; + break; + } + rect->r_xbot += x; + rect->r_ybot += y; + rect->r_xtop += x; + rect->r_ytop += y; + } + else + { + switch (corner) + { + case WIND_BL: + rect->r_xbot = p->p_x; + rect->r_ybot = p->p_y; + break; + case WIND_BR: + rect->r_xtop = p->p_x; + rect->r_ybot = p->p_y; + break; + case WIND_TR: + rect->r_xtop = p->p_x; + rect->r_ytop = p->p_y; + break; + case WIND_TL: + rect->r_xbot = p->p_x; + rect->r_ytop = p->p_y; + break; + } + + /* If the movement turned the box inside out, turn it right + * side out again. + */ + + if (rect->r_xbot > rect->r_xtop) + { + tmp = rect->r_xtop; + rect->r_xtop = rect->r_xbot; + rect->r_xbot = tmp; + } + if (rect->r_ybot > rect->r_ytop) + { + tmp = rect->r_ytop; + rect->r_ytop = rect->r_ybot; + rect->r_ybot = tmp; + } + + } +} + + +/* + * ---------------------------------------------------------------------------- + * Button Routines -- + * + * This page contains a set of routines to handle the puck + * buttons within the window border. + * + * Results: + * None. + * + * Side effects: + * Left button: used to move the whole window by the lower-left corner. + * Right button: used to re-size the window by its upper-right corner. + * If one of the left or right buttons is pushed, then the + * other is pushed, the corner is switched to the nearest + * one to the cursor. This corner is remembered for use + * in box positioning/sizing when both buttons have gone up. + * Bottom button: Center the view on the point where the crosshair is + * at when the button is released. + * ---------------------------------------------------------------------------- + */ + +void +windFrameDown(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (WindOldButtons == 0) + { + windFrameRect = w->w_frameArea; + windFrameWindow = w; + windButton = cmd->tx_button; + } +#define BOTHBUTTONS (TX_LEFT_BUTTON | TX_RIGHT_BUTTON) + if ((WindNewButtons & BOTHBUTTONS) == BOTHBUTTONS) + { + windCorner = windGetCorner(&(cmd->tx_p), &(windFrameWindow->w_frameArea)); + } + else if (cmd->tx_button == TX_LEFT_BUTTON) + { + windCorner = WIND_BL; + windButtonSetCursor(windButton, windCorner); + } + else if (cmd->tx_button == TX_RIGHT_BUTTON) + { + windCorner = WIND_TR; + windButtonSetCursor(windButton, windCorner); + } +} + + /*ARGSUSED*/ +void +windFrameUp(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (WindNewButtons == 0) + { + GrSetCursor(STYLE_CURS_NORMAL); + switch (cmd->tx_button) + { + case TX_LEFT_BUTTON: + case TX_RIGHT_BUTTON: + windMoveRect( (windButton == TX_LEFT_BUTTON), + windCorner, &(cmd->tx_p), &windFrameRect); + WindReframe(windFrameWindow, &windFrameRect, FALSE, + (windButton == TX_LEFT_BUTTON) ); + break; + } + } + else + { + /* If both buttons are down and one is released, we just change + * the cursor to reflect the current corner and the remaining + * button (i.e. move or size window). + */ + + windCorner = windGetCorner(&(cmd->tx_p), &(windFrameWindow->w_frameArea)); + windButtonSetCursor(windButton, windCorner); + } +} + +/* + * ---------------------------------------------------------------------------- + * windFrameButtons -- + * + * Handle button pushes to the window frame area (zoom and scroll) + * Always handle scroll bars ourselves, even if there is an external + * window package. BUT---in the Tcl/Tk version of Magic, the + * window does not set WIND_SCROLLBARS, causing this routine to be + * bypassed. + * + * Results: + * TRUE if the button was pushed in the frame and handled by one + * of the button handler routines, FALSE if not. + * + * Side effects: + * Depends upon where the button was pushed. + * ---------------------------------------------------------------------------- + */ + +bool +windFrameButtons(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + extern void windBarLocations(); + + Rect leftBar, botBar, up, down, right, left, zoom; + Point p; + + if (w == NULL) return FALSE; + p.p_x = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + p.p_y = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + + if ((w->w_flags & WIND_SCROLLBARS) != 0) + { + windBarLocations(w, &leftBar, &botBar, &up, &down, &right, &left, &zoom); + if (cmd->tx_button == TX_MIDDLE_BUTTON) { + if (GEO_ENCLOSE(&cmd->tx_p, &leftBar)) + { + /* move elevator */ + p.p_x = 0; + p.p_y = w->w_bbox->r_ybot + + ((w->w_bbox->r_ytop - w->w_bbox->r_ybot) * + (cmd->tx_p.p_y - leftBar.r_ybot)) + / (leftBar.r_ytop - leftBar.r_ybot) - + (w->w_surfaceArea.r_ytop + w->w_surfaceArea.r_ybot)/2; + WindScroll(w, &p, (Point *) NULL); + return TRUE; + } + else if (GEO_ENCLOSE(&cmd->tx_p, &botBar)) + { + /* move elevator */ + p.p_y = 0; + p.p_x = w->w_bbox->r_xbot + + ((w->w_bbox->r_xtop - w->w_bbox->r_xbot) * + (cmd->tx_p.p_x - botBar.r_xbot)) + / (botBar.r_xtop - botBar.r_xbot) - + (w->w_surfaceArea.r_xtop + w->w_surfaceArea.r_xbot)/2; + WindScroll(w, &p, (Point *) NULL); + return TRUE; + } + else if (GEO_ENCLOSE(&cmd->tx_p, &up)) + { + /* scroll up */ + p.p_y = -p.p_y; + p.p_x = 0; + WindScroll(w, (Point *) NULL, &p); + return TRUE; + } + else if (GEO_ENCLOSE(&cmd->tx_p, &down)) + { + /* scroll down */ + p.p_x = 0; + WindScroll(w, (Point *) NULL, &p); + return TRUE; + } + else if (GEO_ENCLOSE(&cmd->tx_p, &right)) + { + /* scroll right */ + p.p_x = -p.p_x; + p.p_y = 0; + WindScroll(w, (Point *) NULL, &p); + return TRUE; + } + else if (GEO_ENCLOSE(&cmd->tx_p, &left)) + { + /* scroll left */ + p.p_y = 0; + WindScroll(w, (Point *) NULL, &p); + return TRUE; + } + } + if (GEO_ENCLOSE(&cmd->tx_p, &zoom)) { + /* zoom in, out, or view */ + switch (cmd->tx_button) + { + case TX_LEFT_BUTTON: + WindZoom(w, 2.0); + break; + case TX_MIDDLE_BUTTON: + WindView(w); + break; + case TX_RIGHT_BUTTON: + WindZoom(w, 0.5); + break; + } + return TRUE; + } + } + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * windClientButtons -- + * + * Handle button pushes to the window border. + * + * Results: + * None. + * + * Side effects: + * depends upon where the button was pushed. + * ---------------------------------------------------------------------------- + */ + +void +windClientButtons(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + /* + * Is this an initial 'down push' in a non-iconic window? If so, we + * will initiate some user-interaction sequence, such as moving the corner + * of the window or growing it to full-screen size. + * + * (An 'iconic' window is one that is closed down to an icon -- this + * currently only happens when we are using the Sun window package, but + * in the future it might happen in other cases too.) + * + */ + + if ((WindOldButtons == 0) && ((w->w_flags & WIND_ISICONIC) == 0)) + { + /* single button down */ + Point p; + Rect caption; + + windFrameWindow = NULL; + if (w == NULL) return; + p.p_x = w->w_screenArea.r_xtop - w->w_screenArea.r_xbot; + p.p_y = w->w_screenArea.r_ytop - w->w_screenArea.r_ybot; + caption = w->w_allArea; + if ((w->w_flags & WIND_CAPTION) != 0) + caption.r_ybot = caption.r_ytop - TOP_BORDER(w) + 1; + else + caption.r_ybot = caption.r_ytop; + + /* Handle 'grow' for our window package. */ + if (WindPackageType == WIND_MAGIC_WINDOWS) + { + if ((cmd->tx_button == TX_MIDDLE_BUTTON) && + GEO_ENCLOSE(&cmd->tx_p, &caption)) + { + WindFullScreen(w); + return; + } + } + if (windFrameButtons(w, cmd)) return; + + /* Otherwise, continue onward */ + } + + /* + * At this point, we have decided that the button was not an initial + * button push for Magic's window package. Maybe an external window + * package wants it, or maybe it is a continuation of a previous Magic + * sequence (such as moving a corner of a window). + */ + switch ( WindPackageType ) + { + case WIND_X_WINDOWS: + break; + + default: + /* Magic Windows */ + if (cmd->tx_button == TX_MIDDLE_BUTTON) + return; + if ((cmd->tx_buttonAction == TX_BUTTON_UP) && + (windFrameWindow == NULL)) + return; + + /* no special area or else an up push -- reframe window */ + switch (cmd->tx_buttonAction) + { + case TX_BUTTON_DOWN: + windFrameDown(w, cmd); + break; + case TX_BUTTON_UP: + windFrameUp(w, cmd); + break; + default: + TxError("windClientButtons() failed!\n"); + break; + } + } +} + +/* + * ---------------------------------------------------------------------------- + * WindButtonInFrame -- + * + * To be called from the graphics packages. Handle button pushes to + * the window frame area (zoom and scroll) by calling windFrameButtons() + * if it appears to be appropriate for this MagWindow structure. + * This bypasses the key macro handler, thus hard-coding the button + * actions for the frame. + * + * Results: + * TRUE if the button was pushed in the frame and handled by one + * of the button handler routines, FALSE if not. + * + * Side effects: + * Depends upon where the button was pushed. + * ---------------------------------------------------------------------------- + */ + +bool +WindButtonInFrame(w, x, y, b) + MagWindow *w; + int x; + int y; + int b; +{ + TxCommand cmd; + cmd.tx_p.p_x = x; + cmd.tx_p.p_y = y; + cmd.tx_button = b; + if (windFrameButtons(w, &cmd)) + { + WindUpdate(); + return TRUE; + } + return FALSE; +} + + +/* + * ---------------------------------------------------------------------------- + * + * windClientInterp + * + * Window's command interpreter. + * Dispatches to long commands, providing them with the window and command + * we are passed. + * + * Results: + * none. + * + * Side effects: + * Whatever occur as a result of executing the long + * command supplied. + * + * ---------------------------------------------------------------------------- + */ + +void +windCmdInterp(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int cmdNum; + + switch (cmd->tx_button) + { + case TX_LEFT_BUTTON: + case TX_RIGHT_BUTTON: + case TX_MIDDLE_BUTTON: + windClientButtons(w, cmd); + break; + case TX_NO_BUTTON: + if (WindExecute(w, windClientID, cmd) >= 0) + UndoNext(); + break; + default: + ASSERT(FALSE, "windCmdInterp"); + break; + } +} + + +/* + * ---------------------------------------------------------------------------- + * windCmdInit -- + * + * Initialize the window client. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windClientInit() +{ + windClientID = WindAddClient(WINDOW_CLIENT, ( bool (*)() ) NULL, + ( bool (*)() ) NULL, ( void (*)() ) NULL, windCmdInterp, + ( void (*)() ) NULL, ( bool (*)() ) NULL, ( void (*)() ) NULL, + (GrGlyph *) NULL); + + /* Set up all of the window commands */ + +#ifdef MAGIC_WRAPPER + WindAddCommand(windClientID, + "*bypass command run command independently of the command line", + windBypassCmd, FALSE); +#endif + WindAddCommand(windClientID, + "*crash cause a core dump", + windCrashCmd, FALSE); + WindAddCommand(windClientID, + "*files print out currently open files", + windFilesCmd, FALSE); + WindAddCommand(windClientID, + "*grstats print out stats on graphics", + windGrstatsCmd, FALSE); + WindAddCommand(windClientID, + "*pause [args] print args and wait for ", + windPauseCmd, FALSE); + WindAddCommand(windClientID, + "*winddebug set debugging mode", + windDebugCmd, FALSE); + WindAddCommand(windClientID, + "*winddump print out debugging info", + windDumpCmd, FALSE); + + WindAddCommand(windClientID, + "center [x y] center window on the cursor or indicated coordinate", + windCenterCmd, FALSE); + WindAddCommand(windClientID, + "closewindow [name] close a window", + windCloseCmd, FALSE); + WindAddCommand(windClientID, + "cursor return magic coordinates of the cursor", + windCursorCmd, FALSE); + WindAddCommand(windClientID, + "grow blow a window up to full-screen size or back again", + windGrowCmd, FALSE); + WindAddCommand(windClientID, + "help [pattern] print out synopses for all commands valid\n\ + in the current window (or just those\n\ + containing pattern)", + windHelpCmd, FALSE); + WindAddCommand(windClientID, + "imacro [char [string]] define or print an interactive macro called char", + windIntMacroCmd, FALSE); + WindAddCommand(windClientID, + "logcommands [file [update]]\n\ + log all commands into a file", + windLogCommandsCmd, FALSE); + WindAddCommand(windClientID, + "macro [char [string]] define or print a macro called char", + windMacroCmd, FALSE); + WindAddCommand(windClientID, + "openwindow [cell][name]\n\ + open a new window with indicated name, bound to indicated cell", + windOpenCmd, FALSE); + WindAddCommand(windClientID, + "over move a window over (on top of) the rest", + windOverCmd, FALSE); + WindAddCommand(windClientID, + "pushbutton button act push a mouse button", + windPushbuttonCmd, FALSE); + WindAddCommand(windClientID, + "redo [count] redo commands", + windRedoCmd, FALSE); + WindAddCommand(windClientID, + "redraw redraw the display", + windRedrawCmd, FALSE); + WindAddCommand(windClientID, + "reset reset the display", + windResetCmd, FALSE); + WindAddCommand(windClientID, + "scroll dir [amount] scroll the window", + windScrollCmd, FALSE); + WindAddCommand(windClientID, + "setpoint [x y [WID]] force to cursor (point) to x,y in window WID", + windSetpointCmd, FALSE); + WindAddCommand(windClientID, + "sleep seconds sleep for a number of seconds", + windSleepCmd, FALSE); + WindAddCommand(windClientID, + "specialopen [coords] type [args]\n\ + open a special window", + windSpecialOpenCmd, FALSE); + WindAddCommand(windClientID, + "quit exit magic", + windQuitCmd, FALSE); + WindAddCommand(windClientID, + "underneath move a window underneath the rest", + windUnderCmd, FALSE); + WindAddCommand(windClientID, + "undo [count] undo commands", + windUndoCmd, FALSE); + WindAddCommand(windClientID, +#ifdef MAGIC_WRAPPER + "updatedisplay [suspend|resume]\n\ + force display update, or suspend/resume updates", +#else + "updatedisplay force the display to be updated", +#endif + windUpdateCmd, FALSE); + WindAddCommand(windClientID, + "version print out version info", + windVersionCmd, FALSE); + WindAddCommand(windClientID, + "view [get] zoom window out so everything is visible", + windViewCmd, FALSE); + WindAddCommand(windClientID, + "windowborder [on|off] toggle border drawing for new windows", + windBorderCmd, FALSE); + WindAddCommand(windClientID, + "windowcaption [on|off] toggle title caption for new windows", + windCaptionCmd, FALSE); + WindAddCommand(windClientID, + "windowscrollbars [on|off]\n\ + toggle scroll bars for new windows", + windScrollBarsCmd, FALSE); + WindAddCommand(windClientID, + "windowpositions [file] print out window positions", + windPositionsCmd, FALSE); + WindAddCommand(windClientID, + "xview zoom window out so everything is unexpanded", + windXviewCmd, FALSE); + WindAddCommand(windClientID, + "zoom amount zoom window by amount", + windZoomCmd, FALSE); + WindAddCommand(windClientID, + "windownames [all|type] get name of current or all windows", + windNamesCmd, FALSE); +#ifndef MAGIC_WRAPPER + WindAddCommand(windClientID, + "echo [-n] [strings] print text on the terminal", + windEchoCmd, FALSE); + WindAddCommand(windClientID, + "send type command send a command to a certain window type", + windSendCmd, FALSE); + WindAddCommand(windClientID, + "source filename read in commands from file", + windSourceCmd, FALSE); +#endif +} diff --git a/windows/windCmdAM.c b/windows/windCmdAM.c new file mode 100644 index 00000000..82e838fe --- /dev/null +++ b/windows/windCmdAM.c @@ -0,0 +1,1234 @@ +/* windCmdAM.c - + * + * This file contains Magic command routines for those commands + * that are valid in all windows. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windCmdAM.c,v 1.2 2008/12/11 04:20:15 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for round() function */ + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "utils/malloc.h" +#include "utils/runstats.h" +#include "utils/macros.h" +#include "utils/signals.h" +#include "graphics/graphics.h" +#include "utils/styles.h" +#include "textio/txcommands.h" +#include "graphics/glyphs.h" +#include "windows/windInt.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "dbwind/dbwind.h" +#include "utils/utils.h" +#include "cif/cif.h" + +/* Forward declarations */ +void windDoMacro(); + +/* + * ---------------------------------------------------------------------------- + * + * windBorderCmd -- + * + * Change the flag which says whether new windows will have a border. + * + * Usage: + * windborder [on|off] + * + * Results: + * None. + * + * Side effects: + * A flag is changed. + * In Tcl, if no options are presented, the border status is returned + * in the command exit status. + * + * ---------------------------------------------------------------------------- + */ + +void +windBorderCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int place; + bool value; + static char *onoff[] = {"on", "off", 0}; + static bool truth[] = {TRUE, FALSE}; + + if (cmd->tx_argc > 2) goto usage; + else if (cmd->tx_argc == 1) + { + if (w == (MagWindow *)NULL) + { + TxError("No window specified for caption command\n"); + goto usage; + } + + value = (w->w_flags & WIND_BORDER) ? 0 : 1; + +#ifdef MAGIC_WRAPPER + Tcl_SetResult(magicinterp, onoff[value], TCL_STATIC); +#else + TxPrintf("Window border is %s\n", onoff[value]); +#endif + return; + } + + place = Lookup(cmd->tx_argv[1], onoff); + if (place < 0) + goto usage; + + if (truth[place]) + { + WindDefaultFlags |= WIND_BORDER; + TxPrintf("New windows will have a border.\n"); + } + else { + WindDefaultFlags &= ~WIND_BORDER; + TxPrintf("New windows will not have a border.\n"); + } + return; + + usage: + TxError("Usage: %s [on|off]\n", cmd->tx_argv[0]); + return; +} +/* + * ---------------------------------------------------------------------------- + * + * windCaptionCmd -- + * + * Change the flag which says whether new windows will have a title caption. + * + * Usage: + * windcaption [on|off] + * + * Results: + * None. + * + * Side effects: + * A flag is changed. + * In Tcl, if no options are presented, the window title caption is + * returned in the command status. + * + * ---------------------------------------------------------------------------- + */ + +void +windCaptionCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int place; + Rect ts; + static char *onoff[] = {"on", "off", 0}; + static bool truth[] = {TRUE, FALSE}; + + if (cmd->tx_argc > 2) goto usage; + else if (cmd->tx_argc == 1) + { + if (w == (MagWindow *)NULL) + { + TxError("No window specified for caption command\n"); + goto usage; + } + +#ifdef MAGIC_WRAPPER + Tcl_SetResult(magicinterp, w->w_caption, TCL_STATIC); +#else + TxPrintf("Window caption is \"%s\"\n", w->w_caption); +#endif + return; + } + + place = Lookup(cmd->tx_argv[1], onoff); + if (place < 0) + goto usage; + + if (truth[place]) + { + WindDefaultFlags |= WIND_CAPTION; + TxPrintf("New windows will have a title caption.\n"); + } + else { + WindDefaultFlags &= ~WIND_CAPTION; + TxPrintf("New windows will not have a title caption.\n"); + } + return; + + usage: + TxError("Usage: %s [on|off]\n", cmd->tx_argv[0]); + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * windCenterCmd -- + * + * Implement the "center" command. + * Move a window's view to center the point underneath the cursor, or to + * the specified coordinate (in surface units). + * + * Usage: + * center [x y] + * center horizontal|vertical f + * + * Results: + * None. + * + * Side effects: + * The view in the window underneath the cursor is changed + * to center the point underneath the cursor. + * + * ---------------------------------------------------------------------------- + */ + +void +windCenterCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + Point rootPoint; + Rect newArea, oldArea; + + if (w == NULL) + { + TxError("Point to a window first.\n"); + return; + } + + if (cmd->tx_argc == 1) + { + if ((w->w_flags & WIND_SCROLLABLE) == 0) + { + TxError("Sorry, can't scroll this window.\n"); + return; + } + WindPointToSurface(w, &cmd->tx_p, &rootPoint, (Rect *) NULL); + } + else if (cmd->tx_argc == 3) + { + if ((w->w_flags & WIND_SCROLLABLE) == 0) + { + TxError("Sorry, can't scroll this window.\n"); + return; + } + if (cmd->tx_argv[1][0] == 'h' || cmd->tx_argv[1][0] == 'v') + { + double frac; + + if (!StrIsNumeric(cmd->tx_argv[2])) + { + TxError("Must specify a fractional value.\n"); + return; + } + frac = atof(cmd->tx_argv[2]); + if (cmd->tx_argv[1][0] == 'h') + { + rootPoint.p_y = 0; + rootPoint.p_x = w->w_bbox->r_xbot + frac * + (w->w_bbox->r_xtop - w->w_bbox->r_xbot) - + (w->w_surfaceArea.r_xtop + w->w_surfaceArea.r_xbot)/2; + } + else + { + rootPoint.p_x = 0; + rootPoint.p_y = w->w_bbox->r_ybot + frac * + (w->w_bbox->r_ytop - w->w_bbox->r_ybot) - + (w->w_surfaceArea.r_ytop + w->w_surfaceArea.r_ybot)/2; + } + WindScroll(w, &rootPoint, (Point *)NULL); + return; + } + else + { + if (!StrIsInt(cmd->tx_argv[1]) || !StrIsInt(cmd->tx_argv[2])) + { + TxError("Coordinates must be integer values\n"); + return; + } + rootPoint.p_x = atoi(cmd->tx_argv[1]); + rootPoint.p_y = atoi(cmd->tx_argv[2]); + } + } + else + { + TxError("Usage: center [x y]\n"); + TxError(" center horizontal|vertical f\n"); + return; + } + + oldArea = w->w_surfaceArea; + newArea.r_xbot = rootPoint.p_x - (oldArea.r_xtop - oldArea.r_xbot)/2; + newArea.r_xtop = newArea.r_xbot - oldArea.r_xbot + oldArea.r_xtop; + newArea.r_ybot = rootPoint.p_y - (oldArea.r_ytop - oldArea.r_ybot)/2; + newArea.r_ytop = newArea.r_ybot - oldArea.r_ybot + oldArea.r_ytop; + + WindMove(w, &newArea); +} + + +/* + * ---------------------------------------------------------------------------- + * windCloseCmd -- + * + * Close the window that is pointed at. + * + * Results: + * None. + * + * Side effects: + * The window is closed, and the client is notified. The client may + * refuse to have the window closed, in which case nothing happens. + * ---------------------------------------------------------------------------- + */ + +void +windCloseCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if ((cmd->tx_argc == 2) && GrWindowNamePtr) + { + char *mwname; + + for (w = windTopWindow; w != (MagWindow *)NULL; w = w->w_nextWindow) + { + mwname = (*GrWindowNamePtr)(w); + if (!strcmp(mwname, cmd->tx_argv[1])) + break; + } + if (w == NULL) + { + TxError("Window named %s cannot be found\n", cmd->tx_argv[1]); + return; + } + } + + if (w == (MagWindow *) NULL) + { + TxError("Point to a window first\n"); + return; + } + if (!WindDelete(w)) + { + TxError("Unable to close that window\n"); + return; + } +} + +#ifdef MAGIC_WRAPPER +/* + * ---------------------------------------------------------------------------- + * windBypassCmd -- + * + * Run a magic command independently of the command line. That is, + * if a command is being typed on the command line, the input + * redirection will not be reset by the execution of this command. + * To avoid having such commands interfere with the selection + * mechanism, save and restore the command count. + * + * Results: + * None. + * + * Side effects: + * + * + * ---------------------------------------------------------------------------- + */ + +void +windBypassCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int saveCount; + + if (cmd->tx_argc == 1) + { + TxError("Usage: *bypass \n"); + return; + } + + /* Dispatch the referenced command */ + saveCount = TxCommandNumber; + TxTclDispatch((ClientData)w, cmd->tx_argc - 1, cmd->tx_argv + 1, FALSE); + TxCommandNumber = saveCount; + if (TxInputRedirect == TX_INPUT_PENDING_RESET) + TxInputRedirect = TX_INPUT_REDIRECTED; +} + +#endif /* MAGIC_WRAPPER */ + +/* + * ---------------------------------------------------------------------------- + * windCrashCmd -- + * + * Generate a core dump. + * + * Results: + * None. + * + * Side effects: + * Dumps core by calling niceabort(). + * + * ---------------------------------------------------------------------------- + */ + +void +windCrashCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (cmd->tx_argc != 1) + { + TxError("Usage: *crash\n"); + return; + } + + TxPrintf("OK -- crashing...\n"); + TxFlush(); + niceabort(); +} + + +/* + * ---------------------------------------------------------------------------- + * windCursorCmd -- + * + * Report the cursor position in Magic (internal) coordinates + * If an argument of a number is given, then the cursor icon + * is changed to the glyph of that number. + * + * Results: + * None. + * + * Side effects: + * Prints coordinates (non-Tcl version) + * Return value set to the cursor position as a list (Tcl version) + * ---------------------------------------------------------------------------- + */ + +void +windCursorCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + Point p_in, p_out; + int resulttype = DBW_SNAP_INTERNAL; + double cursx, cursy, oscale; + DBWclientRec *crec; + +#ifdef MAGIC_WRAPPER + Tcl_Obj *listxy; +#endif + + if (cmd->tx_argc == 2) + { + if (StrIsInt(cmd->tx_argv[1])) + { + if (GrSetCursorPtr != NULL) + (*GrSetCursorPtr)(atoi(cmd->tx_argv[1])); + return; + } + else if (*cmd->tx_argv[1] == 'l') + { + resulttype = DBW_SNAP_LAMBDA; + } + else if (*cmd->tx_argv[1] == 'u') + { + resulttype = DBW_SNAP_USER; + } + else if (*cmd->tx_argv[1] == 'm') + { + resulttype = DBW_SNAP_MICRONS; + } + else if (*cmd->tx_argv[1] == 'w') + { + resulttype = -1; // Use this value for "window" + } + else if (*cmd->tx_argv[1] == 's') + { + resulttype = -2; // Use this value for "screen" + } + else if (*cmd->tx_argv[1] != 'i') + { + TxError("Usage: cursor glyphnum\n"); + TxError(" (or): cursor [internal | lambda | microns | user | window]\n"); + return; + } + } + + if (GrGetCursorPosPtr == NULL) + return; + + if (resulttype == -2) + GrGetCursorRootPos(w, &p_in); + else + GrGetCursorPos(w, &p_in); + + if (resulttype >= 0) + { + WindPointToSurface(w, &p_in, &p_out, (Rect *)NULL); + + /* Snap the cursor position if snap is in effect */ + if (DBWSnapToGrid != DBW_SNAP_INTERNAL) + ToolSnapToGrid(w, &p_out, (Rect *)NULL); + } + + /* Transform the result to declared units with option "lambda" or "grid" */ + switch (resulttype) { + case -2: + case -1: + cursx = (double)p_in.p_x; + cursy = (double)p_in.p_y; + break; + case DBW_SNAP_INTERNAL: + cursx = (double)p_out.p_x; + cursy = (double)p_out.p_y; + break; + case DBW_SNAP_LAMBDA: + cursx = (double)(p_out.p_x * DBLambda[0]) / (double)DBLambda[1]; + cursy = (double)(p_out.p_y * DBLambda[0]) / (double)DBLambda[1]; + break; + case DBW_SNAP_MICRONS: + oscale = (double)CIFGetOutputScale(1000); + cursx = (double)(p_out.p_x * oscale); + cursy = (double)(p_out.p_y * oscale); + break; + case DBW_SNAP_USER: + crec = (DBWclientRec *)w->w_clientData; + cursx = (double)((p_out.p_x - crec->dbw_gridRect.r_xbot) + / (crec->dbw_gridRect.r_xtop - crec->dbw_gridRect.r_xbot)); + cursy = (double)((p_out.p_y - crec->dbw_gridRect.r_ybot) + / (crec->dbw_gridRect.r_ytop - crec->dbw_gridRect.r_ybot)); + break; + } + +#ifdef MAGIC_WRAPPER + listxy = Tcl_NewListObj(0, NULL); + if ((cursx == round(cursx)) && (cursy == round(cursy))) + { + Tcl_ListObjAppendElement(magicinterp, listxy, Tcl_NewIntObj((int)cursx)); + Tcl_ListObjAppendElement(magicinterp, listxy, Tcl_NewIntObj((int)cursy)); + } + else + { + Tcl_ListObjAppendElement(magicinterp, listxy, Tcl_NewDoubleObj(cursx)); + Tcl_ListObjAppendElement(magicinterp, listxy, Tcl_NewDoubleObj(cursy)); + } + Tcl_SetObjResult(magicinterp, listxy); +#else + TxPrintf("%g %g\n", cursx, cursy); +#endif +} + +/* + * ---------------------------------------------------------------------------- + * windDebugCmd -- + * + * Change to a new debugging mode. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windDebugCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (cmd->tx_argc != 1) goto usage; + windPrintCommands = !windPrintCommands; + TxError("Window command debugging set to %s\n", + (windPrintCommands ? "TRUE" : "FALSE")); + return; + +usage: + TxError("Usage: *winddebug\n"); +} + +/* + * ---------------------------------------------------------------------------- + * windDumpCmd -- + * + * Dump out debugging info. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windDumpCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + (void) windDump(); +} + +#ifndef MAGIC_WRAPPER + +/* + * ---------------------------------------------------------------------------- + * + * windEchoCmd -- + * + * Echo the arguments + * + * Results: + * None. + * + * Side effects: + * Text may appear on the terminal + * + * ---------------------------------------------------------------------------- + */ + +void +windEchoCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int i; + bool newline = TRUE; + + for (i = 1; i < cmd->tx_argc; i++) + { + if (i != 1) + TxPrintf(" "); + if ( (i == 1) && (strcmp(cmd->tx_argv[i], "-n") == 0) ) + newline = FALSE; + else + TxPrintf("%s", cmd->tx_argv[i]); + } + + if (newline) + TxPrintf("\n"); + TxFlush(); +} + +#endif + + +/* + * ---------------------------------------------------------------------------- + * + * windFilesCmd -- + * + * Find out what files are currently open. + * + * Usage: + * *files + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + /*ARGSUSED*/ + +void +windFilesCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ +#define NUM_FD 20 /* max number of open files per process */ + int fd; + struct stat buf; + int unopen, open; + + open = unopen = 0; + for (fd = 0; fd < NUM_FD; fd++) { + if (fstat(fd, &buf) != 0) { + if (errno == EBADF) + unopen++; + else + TxError("file descriptor %d: %s\n", fd, strerror(errno)); + } + else { + char *type; + switch (buf.st_mode & S_IFMT) { + case S_IFDIR: {type = "directory"; break;} + case S_IFCHR: {type = "character special"; break;} + case S_IFBLK: {type = "block special"; break;} + case S_IFREG: {type = "regular"; break;} + case S_IFLNK: {type = "symbolic link"; break;} + case S_IFSOCK: {type = "socket"; break;} + default: {type = "unknown"; break;} + } + TxError("file descriptor %d: open (type: '%s', inode number %ld)\n", + fd, type, buf.st_ino); + open++; + } + } + TxError("%d open files, %d unopened file descriptors left\n", open, unopen); +} + + +/* + * ---------------------------------------------------------------------------- + * + * windGrowCmd -- + * + * Grow a window to full-screen size or back to previous size. + * + * Results: + * None. + * + * Side effects: + * Text may appear on the terminal + * + * ---------------------------------------------------------------------------- + */ + +void +windGrowCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (w == NULL) + { + TxError("Point to a window first.\n"); + return; + }; + + WindFullScreen(w); +} + + +/* + * ---------------------------------------------------------------------------- + * windGrstatsCmd -- + * + * Take statistics on the graphics code. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windGrstatsCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + char *RunStats(), *rstatp; + static struct tms tlast, tdelta; + int i, style, count; + int us; + extern int GrNumClipBoxes; + int usPerRect, rectsPerSec; + + if (cmd->tx_argc < 2 || cmd->tx_argc > 3) + { + TxError("Usage: grstats num [ style ]\n"); + return; + } + + if (!StrIsInt(cmd->tx_argv[1]) || + (cmd->tx_argc == 3 && !StrIsInt(cmd->tx_argv[2]))) + { + TxError("Count & style must be numeric\n"); + return; + } + if (w == (MagWindow *) NULL) + { + TxError("Point to a window first.\n"); + return; + } + + count = atoi(cmd->tx_argv[1]); + if (cmd->tx_argc == 3) + style = atoi(cmd->tx_argv[2]); + else + style = -1; + + WindUpdate(); + + if (style >= 0) + GrLock(w, TRUE); + + (void) RunStats(RS_TINCR, &tlast, &tdelta); + GrNumClipBoxes = 0; + for (i = 0; i < count; i++) + { + if (SigInterruptPending) + break; + if (style < 0) + { + WindAreaChanged(w, (Rect *) NULL); + WindUpdate(); + } + else + { + Rect r; +#define GRSIZE 15 +#define GRSPACE 20 + r.r_xbot = w->w_screenArea.r_xbot - GRSIZE/2; + r.r_ybot = w->w_screenArea.r_ybot - GRSIZE/2; + r.r_xtop = r.r_xbot + GRSIZE - 1; + r.r_ytop = r.r_ybot + GRSIZE - 1; + GrClipBox(&w->w_screenArea, STYLE_ERASEALL); + GrSetStuff(style); + while (r.r_xbot <= w->w_screenArea.r_xtop) + { + while (r.r_ybot <= w->w_screenArea.r_ytop) + { + GrFastBox(&r); + r.r_ybot += GRSPACE; + r.r_ytop += GRSPACE; + } + r.r_xbot += GRSPACE; + r.r_xtop += GRSPACE; + r.r_ybot = w->w_screenArea.r_ybot - GRSIZE/2; + r.r_ytop = r.r_ybot + GRSIZE - 1; + } + } + } + rstatp = RunStats(RS_TINCR, &tlast, &tdelta); + + us = tdelta.tms_utime * (1000000 / 60); + usPerRect = us / MAX(1, GrNumClipBoxes); + rectsPerSec = 1000000 / MAX(1, usPerRect); + TxPrintf("[%s]\n%d rectangles, %d uS, %d uS/rectangle, %d rects/sec\n", + rstatp, GrNumClipBoxes, us, usPerRect, rectsPerSec); + + if (style >= 0) + GrUnlock(w); +} + + +/* + * ---------------------------------------------------------------------------- + * windHelpCmd -- + * + * Just a dummy proc. (Only for this particular, global, client) + * This is just here so that there is an entry in our help table! + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windHelpCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + ASSERT(FALSE, windHelpCmd); +} + +static char *logKeywords[] = + { + "update", + 0 + }; + +/* + * ---------------------------------------------------------------------------- + * windLogCommandsCmd -- + * + * Log the commands and button pushes in a file. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windLogCommandsCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + char *fileName; + bool update; + + if ((cmd->tx_argc < 1) || (cmd->tx_argc > 3)) goto usage; + + update = FALSE; + + if (cmd->tx_argc == 1) + fileName = NULL; + else + fileName = cmd->tx_argv[1]; + + if (cmd->tx_argc == 3) { + int i; + i = Lookup(cmd->tx_argv[cmd->tx_argc - 1], logKeywords); + if (i != 0) goto usage; + update = TRUE; + } + + TxLogCommands(fileName, update); + return; + +usage: + TxError("Usage: %s [filename [update]]\n", cmd->tx_argv[0]); +} + +/* + * ---------------------------------------------------------------------------- + * + * windIntMacroCmd -- + * + * Define a new interactive macro. + * + * Results: + * None. + * + * Side effects: + * Calls windDoMacro. + * + * ---------------------------------------------------------------------------- + */ + +void +windIntMacroCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + windDoMacro(w, cmd, TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * + * windMacroCmd -- + * + * Define a new macro. + * + * Results: + * None. + * + * Side effects: + * Calls windDoMacro + * + * ---------------------------------------------------------------------------- + */ + +void +windMacroCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + windDoMacro(w, cmd, FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * + * windDoMacro -- + * + * Working function for CmdIntMacro and CmdMacro + * + * Results: + * None. + * + * Side effects: + * Causes the macro package to define a new macro. + * + * ---------------------------------------------------------------------------- + */ + +void +windDoMacro(w, cmd, interactive) + MagWindow *w; + TxCommand *cmd; + bool interactive; +{ + char *cp, *cn; + char nulltext[] = ""; + char ch; + int ct, argstart, verbose; + bool any, iReturn; + bool do_list = FALSE; + bool do_help = FALSE; + bool do_reverse = FALSE; + char *searchterm = NULL; + macrodef *cMacro; + HashTable *clienttable; + HashEntry *h; + HashSearch hs; + WindClient wc; + + /* If the first argument is a window name, we attempt to */ + /* retrieve a client ID from it. This overrides the actual */ + /* window the command was called from, so technically we */ + /* can define macros for clients from inside other clients. */ + /* The main use, though, is to define macros for a client */ + /* from a script, rc file, or command-line. */ + /* Default to the layout window if the command has no */ + /* associated window. */ + + argstart = 1; + if (cmd->tx_argc == 1) + wc = DBWclientID; /* Added by NP 11/15/04 */ + else if (cmd->tx_argc > 1) + wc = WindGetClient(cmd->tx_argv[1], TRUE); + + while (cmd->tx_argc > argstart) + { + if (!strcmp(cmd->tx_argv[argstart], "list")) + { + do_list = TRUE; + argstart++; + } + else if (!strcmp(cmd->tx_argv[argstart], "help")) + { + do_help = TRUE; + argstart++; + } + else if (!strcmp(cmd->tx_argv[argstart], "search")) + { + if (cmd->tx_argc > (argstart + 1)) + { + argstart++; + searchterm = cmd->tx_argv[argstart]; + } + argstart++; + } + else if (!strcmp(cmd->tx_argv[argstart], "-reverse")) + { + do_reverse = TRUE; + argstart++; + } + else break; + } + + /* If client wasn't specified, use window default, else use */ + /* DBW client. */ + + if (wc == (WindClient)NULL) + { + if (w != NULL) + wc = w->w_client; + else + wc = DBWclientID; + + if (cmd->tx_argc > (argstart + 1)) + { + /* The first argument, if there is one after resolving */ + /* all of the optional arugments, should be a key. */ + /* If it doesn't look like one, then check if the */ + /* next argument looks like a key, which would indicate */ + /* an unregistered client as the first argument. A */ + /* macro retrieved from an unregistered client returns */ + /* nothing but does not generate an error. */ + + if (MacroKey(cmd->tx_argv[argstart], &verbose) == 0) + if (MacroKey(cmd->tx_argv[argstart + 1], &verbose) != 0) + { + wc = 0; + argstart++; + } + } + } + else + argstart++; + + if (cmd->tx_argc == argstart) + { + h = HashLookOnly(&MacroClients, wc); + if (h == NULL) + return; + else + { + clienttable = (HashTable *)HashGetValue(h); + if (clienttable == (HashTable *)NULL) + { + TxError("No such client.\n"); + return; + } + } + + any = FALSE; + ch = 0; + HashStartSearch(&hs); + while (TRUE) + { + h = HashNext(clienttable, &hs); + if (h == NULL) break; + cMacro = (macrodef *) HashGetValue(h); + if (cMacro == (macrodef *)NULL) break; + cn = MacroName((spointertype)h->h_key.h_ptr); + + /* "imacro list" returns only interactive macros. */ + if (interactive && !cMacro->interactive) continue; + + if (do_help) + cp = cMacro->helptext; + else + cp = cMacro->macrotext; + + if (cp == (char *)NULL) cp = (char *)(&nulltext[0]); + + if (searchterm != NULL) + { + /* Refine results by keyword search */ + if (!strstr(cp, searchterm)) continue; + } + + if (do_list) + { +#ifdef MAGIC_WRAPPER + // NOTE: Putting cp before cn makes it easier to + // generate a reverse lookup hash table for matching + // against menu items, to automatically generate + // the "accelerator" text. + if (do_reverse) + Tcl_AppendElement(magicinterp, cp); + Tcl_AppendElement(magicinterp, cn); + if (!do_reverse) + Tcl_AppendElement(magicinterp, cp); +#else + TxPrintf("%s = \"%s\"\n", cn, cp); +#endif + } + else + { + if (cMacro->interactive) + TxPrintf("Interactive macro '%s' contains \"%s\"\n", + cn, cp); + else + TxPrintf("Macro '%s' contains \"%s\"\n", cn, cp); + } + freeMagic(cn); + any = TRUE; + } + if (!any) + { + if (!do_list) TxPrintf("No macros are defined for this client.\n"); + } + return; + } + else if (cmd->tx_argc == (argstart + 1)) + { + ct = MacroKey(cmd->tx_argv[argstart], &verbose); + if (ct == 0) + { + if (verbose) + TxError("Unrecognized macro name %s\n", cmd->tx_argv[argstart]); + return; + } + if (do_help) + cp = MacroRetrieveHelp(wc, ct); + else + cp = MacroRetrieve(wc, ct, &iReturn); + if (cp != NULL) + { + cn = MacroName(ct); + if (do_list) + { +#ifdef MAGIC_WRAPPER + Tcl_SetResult(magicinterp, cp, TCL_VOLATILE); +#else + TxPrintf("%s\n", cp); +#endif + } + else + { + if (iReturn) + { + TxPrintf("Interactive macro '%s' contains \"%s\"\n", + cn, cp); + } + else + { + TxPrintf("Macro '%s' contains \"%s\"\n", + cn, cp); + } + } + freeMagic(cp); + freeMagic(cn); + } + return; + } + else if (cmd->tx_argc == (argstart + 2)) + { + int verbose; + ct = MacroKey(cmd->tx_argv[argstart], &verbose); + if (ct == 0) + { + if (verbose) + TxError("Unrecognized macro name %s\n", cmd->tx_argv[argstart]); + return; + } + argstart++; + if (cmd->tx_argv[argstart][0] == '\0') MacroDelete(wc, ct); + else if (do_help) + MacroDefineHelp(wc, ct, cmd->tx_argv[argstart]); + else if (interactive) + MacroDefine(wc, ct, cmd->tx_argv[argstart], NULL, TRUE); + else + MacroDefine(wc, ct, cmd->tx_argv[argstart], NULL, FALSE); + return; + } + else if (cmd->tx_argc == (argstart + 3)) + { + int verbose; + ct = MacroKey(cmd->tx_argv[argstart], &verbose); + if (ct == 0) + { + if (verbose) + TxError("Unrecognized macro name %s\n", cmd->tx_argv[argstart]); + return; + } + argstart++; + if (cmd->tx_argv[argstart][0] == '\0') MacroDelete(wc, ct); + else if (interactive) MacroDefine(wc, ct, cmd->tx_argv[argstart], + cmd->tx_argv[argstart + 1], TRUE); + else MacroDefine(wc, ct, cmd->tx_argv[argstart], + cmd->tx_argv[argstart + 1], FALSE); + return; + } + + TxError("Usage: %s [macro_name [string] [help_text]]\n", cmd->tx_argv[0]); +} diff --git a/windows/windCmdNR.c b/windows/windCmdNR.c new file mode 100644 index 00000000..84615eae --- /dev/null +++ b/windows/windCmdNR.c @@ -0,0 +1,442 @@ +/* windCmdNR.c - + * + * This file contains Magic command routines for those commands + * that are valid in all windows. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windCmdNR.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/glyphs.h" +#include "windows/windInt.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/main.h" +#include "utils/tech.h" +#include "utils/runstats.h" +#include "utils/undo.h" +#include "utils/utils.h" +#include "graphics/graphics.h" +#include "textio/txcommands.h" +#include "dbwind/dbwind.h" + + +/* + * ---------------------------------------------------------------------------- + * windOpenCmd -- + * + * Open a new window at the cursor position. Give it a default size, + * and default client, and pass the command line args off to the client. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windOpenCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + Rect area; + Point frame; + WindClient wc; + + if ( w == (MagWindow *) NULL ) + { + frame.p_x = (GrScreenRect.r_xtop - GrScreenRect.r_xbot) / 2; + frame.p_y = (GrScreenRect.r_ytop - GrScreenRect.r_ybot) / 2; + } + else + windScreenToFrame(w, &cmd->tx_p, &frame); + + area.r_xbot = frame.p_x - CREATE_WIDTH/2; + area.r_xtop = frame.p_x + CREATE_WIDTH/2; + area.r_ybot = frame.p_y - CREATE_HEIGHT/2; + area.r_ytop = frame.p_y + CREATE_HEIGHT/2; + + wc = WindGetClient(DEFAULT_CLIENT, TRUE); + ASSERT(wc != (WindClient) NULL, "windOpenCmd"); + + if (WindCreate(wc, &area, TRUE, cmd->tx_argc - 1, cmd->tx_argv + 1) == + (MagWindow *) NULL) + { + TxError("Could not create window\n"); + } +} + + +/* + * ---------------------------------------------------------------------------- + * windOverCmd -- + * + * Move a window over (on top of) the other windows. + * + * Results: + * None. + * + * Side effects: + * Screen updates. + * ---------------------------------------------------------------------------- + */ + +void +windOverCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (cmd->tx_argc != 1) + { + TxError("Usage: %s\n", cmd->tx_argv[0]); + } + if (w == (MagWindow *) NULL) + { + TxError("Point to a window first\n"); + return; + } + WindOver(w); +} + + +/* + * ---------------------------------------------------------------------------- + * + * windPauseCmd -- + * + * Print out the arguments and wait for or a command. + * + * Usage: + * *pause [args] + * + * Results: + * None. + * + * Side effects: + * prints its args. + * + * ---------------------------------------------------------------------------- + */ + +void +windPauseCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int i; + static char ssline[TX_MAX_CMDLEN]; + + WindUpdate(); + GrFlush(); + + for (i = 1; i < cmd->tx_argc; i++) + { + TxPrintf(cmd->tx_argv[i]); + TxPrintf(" "); + if (i+1 == cmd->tx_argc) TxPrintf(" "); + } + + TxPrintf("Pausing: type to continue: "); + (void) TxGetLine(ssline, 98); +} + + +char *butTable[] = +{ + "left", + "middle", + "right", + 0 +}; + +char *actTable[] = +{ + "down", + "up", + 0 +}; + +/* + * ---------------------------------------------------------------------------- + * windPushbuttonCmd -- + * + * Pretend that a button was pushed + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windPushbuttonCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int but, act; + static TxCommand txcmd; + + if (cmd->tx_argc != 3) goto badusage; + + but = Lookup(cmd->tx_argv[1], butTable); + if (but < 0) goto badusage; + act = Lookup(cmd->tx_argv[2], actTable); + if (act < 0) goto badusage; + + switch (but) + { + case 0: + txcmd.tx_button = TX_LEFT_BUTTON; + break; + case 1: + txcmd.tx_button = TX_MIDDLE_BUTTON; + break; + case 2: + txcmd.tx_button = TX_RIGHT_BUTTON; + break; + } + + if (act == 0) + txcmd.tx_buttonAction = TX_BUTTON_DOWN; + else + txcmd.tx_buttonAction = TX_BUTTON_UP; + + txcmd.tx_argc = 0; + txcmd.tx_p = cmd->tx_p; + txcmd.tx_wid = cmd->tx_wid; + (void) WindSendCommand(w, &txcmd, FALSE); + return; + +badusage: + TxError("Usage: %s button action\n", cmd->tx_argv[0]); + return; +} + + +/* + * ---------------------------------------------------------------------------- + * WindQuitCmd -- + * + * Leave the system, but first notify all clients. + * + * Results: + * None. + * + * Side effects: + * the system may exit. + * ---------------------------------------------------------------------------- + */ + +void +windQuitCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + clientRec *cr; + bool checkfirst = TRUE; + + if (cmd->tx_argc == 2) + if (!strcmp(cmd->tx_argv[1], "-noprompt")) + checkfirst = FALSE; + + if (checkfirst) + for (cr = windFirstClientRec; cr != (clientRec *) NULL; + cr = cr->w_nextClient) + if (cr->w_exit != NULL) + if (!(*(cr->w_exit))()) + return; + + MainExit(0); +} + + +/* + * ---------------------------------------------------------------------------- + * + * windRedoCmd + * + * Implement the "redo" command. + * + * Usage: + * redo [count] + * + * If a count is supplied, the last count events are redone. The default + * count if none is given is 1. + * + * Results: + * None. + * + * Side effects: + * Calls the undo module. + * + * ---------------------------------------------------------------------------- + */ + +void +windRedoCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int count; + + if (cmd->tx_argc > 3) + { + TxError("Usage: redo [count]\n"); + return; + } + else if (cmd->tx_argc == 3) + { + if (strncmp(cmd->tx_argv[1], "print", 5)) + { + TxError("Usage: redo print count\n"); + return; + } + else if (!StrIsInt(cmd->tx_argv[2])) + { + TxError("Usage: redo print count\n"); + return; + } + else + { + /* Implement redo stack trace */ + UndoStackTrace(atoi(cmd->tx_argv[2])); + return; + } + } + else if (cmd->tx_argc == 2) + { + if (!StrIsInt(cmd->tx_argv[1])) + { + TxError("Count must be numeric\n"); + return; + } + count = atoi(cmd->tx_argv[1]); + if (count < 0) + { + TxError("Count must be a positive integer\n"); + return; + } + } + else + count = 1; + + if (count == 0) + { + UndoDisable(); + } + else + { + if (UndoForward(count) == 0) + TxPrintf("Nothing more to redo\n"); + } +} + + +/* + * ---------------------------------------------------------------------------- + * windRedrawCmd -- + * + * Redraw the screen. + * + * Results: + * None. + * + * Side effects: + * The screen is redrawn by calling the window package's clients. + * ---------------------------------------------------------------------------- + */ + +void +windRedrawCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + WindAreaChanged((MagWindow *) NULL, (Rect *) NULL); +} + + +/* + * ---------------------------------------------------------------------------- + * windResetCmd -- + * + * Re-initialize the graphics device. + * + * Usage: + * reset + * + * Results: + * None. + * + * Side effects: + * The graphics file is closed and reopened, and the display is reset. + * ---------------------------------------------------------------------------- + */ + +void +windResetCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (cmd->tx_argc != 1) + { + TxError("Usage: %s\n", cmd->tx_argv[0]); + return; + } + + if (WindPackageType != WIND_MAGIC_WINDOWS) + { + TxError("The :reset command doesn't make sense unless you are\nusing a serial-line graphics terminal.\n"); + return; + } + + GrClose(); + + /* open files */ + if (!GrSetDisplay(MainDisplayType, MainGraphicsFile, MainMouseFile)) + { + TxError("Unable to set up graphics display.\n"); + return; + } + + if (GrReadCMap(DBWStyleType, (char *)NULL, MainMonType, ".", + SysLibPath) == 0) return; + if (GrLoadStyles(DBWStyleType, ".", SysLibPath) != 0) return; + + DBWTechInitStyles(); + + if (!GrLoadCursors(".", SysLibPath)) return; + + GrSetCursor(0); + + WindAreaChanged((MagWindow *) NULL, (Rect *) NULL); +} + diff --git a/windows/windCmdSZ.c b/windows/windCmdSZ.c new file mode 100644 index 00000000..fb3f0e36 --- /dev/null +++ b/windows/windCmdSZ.c @@ -0,0 +1,1243 @@ +/* windCmdSZ.c - + * + * This file contains Magic command routines for those commands + * that are valid in all windows. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windCmdSZ.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include /* for sleep() */ +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "windows/windows.h" +#include "graphics/glyphs.h" +#include "windows/windInt.h" +#include "utils/undo.h" +#include "utils/utils.h" +#include "utils/signals.h" +#include "textio/txcommands.h" +#include "utils/hash.h" +#include "database/database.h" +#include "dbwind/dbwind.h" +#include "graphics/graphics.h" + + +/* + * ---------------------------------------------------------------------------- + * + * windScrollCmd -- + * + * Scroll the view around + * + * Usage: + * scroll dir [amount [units]] + * + * Results: + * None. + * + * Side effects: + * The window underneath the cursor is changed. + * Note: behavior has been changed from original. To have "amount" + * parsed as a fractional scroll amount, "units" *must* be declared + * as "w". Otherwise, no units implies that "amount" is an absolute + * value. + * + * + * ---------------------------------------------------------------------------- + */ + +void +windScrollCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + Rect r; + int xsize, ysize; + Point p; + int pos, locargc = cmd->tx_argc; + float amount; + bool doFractional = FALSE; + + if ( (cmd->tx_argc < 2) || (cmd->tx_argc > 4) ) + { + TxError("Usage: %s direction [amount [units]]\n", cmd->tx_argv[0]); + return; + } + + if (w == NULL) + { + TxError("Point to a window first.\n"); + return; + } + + if ((w->w_flags & WIND_SCROLLABLE) == 0) { + TxError("Sorry, can't scroll this window.\n"); + return; + }; + + pos = GeoNameToPos(cmd->tx_argv[1], FALSE, TRUE); + if (pos < 0 || pos == GEO_CENTER) + return; + + if (cmd->tx_argc == 2) /* default = half-screen pan */ + { + r = w->w_screenArea; + amount = 0.5; + doFractional = TRUE; + } + else if (cmd->tx_argc == 4) + { + char unitc = cmd->tx_argv[3][0]; + + if (unitc == 'w') + r = w->w_screenArea; + else if (unitc == 'l') + r = *(w->w_bbox); + else + { + TxError("Usage: %s direction [amount [units]]\n", cmd->tx_argv[0]); + TxError(" 'units' must be one of 'w' (window) or 'l' (layout);\n"); + return; + } + + if (sscanf(cmd->tx_argv[2], "%f", &amount) != 1) + { + TxError("Usage: %s direction [amount [units]]\n", cmd->tx_argv[0]); + TxError(" 'amount' is a fractional value.\n"); + return; + } + doFractional = TRUE; + } + + if (doFractional) + { + xsize = (r.r_xtop - r.r_xbot) * amount; + ysize = (r.r_ytop - r.r_ybot) * amount; + } + else + { + /* Alternate syntax: parse for integer coordinate amount to scroll */ + xsize = cmdParseCoord(w, cmd->tx_argv[2], TRUE, TRUE); + ysize = cmdParseCoord(w, cmd->tx_argv[2], TRUE, FALSE); + } + + p.p_x = 0; + p.p_y = 0; + + switch (pos) + { + case GEO_NORTH: + p.p_y = -ysize; + break; + case GEO_SOUTH: + p.p_y = ysize; + break; + case GEO_EAST: + p.p_x = -xsize; + break; + case GEO_WEST: + p.p_x = xsize; + break; + case GEO_NORTHEAST: + p.p_x = -xsize; + p.p_y = -ysize; + break; + case GEO_NORTHWEST: + p.p_x = xsize; + p.p_y = -ysize; + break; + case GEO_SOUTHEAST: + p.p_x = -xsize; + p.p_y = ysize; + break; + case GEO_SOUTHWEST: + p.p_x = xsize; + p.p_y = ysize; + break; + } + + if (doFractional) + WindScroll(w, (Point *) NULL, &p); + else + { + /* Direction is reversed w/respect to above call to WindScroll() */ + p.p_x = -p.p_x; + p.p_y = -p.p_y; + WindScroll(w, &p, (Point *) NULL); + } + + return; +} + +/* + * ---------------------------------------------------------------------------- + * windSetpointCmd -- + * + * Use the x, y specified as the location of the point tool for the + * next command. + * + * Results: + * None. Under the Tcl interpreter, returns the screen and layout + * coordinates as a list of four integers: sx sy lx ly. + * + * Side effects: + * global variables. + * ---------------------------------------------------------------------------- + */ + +void +windSetpointCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int wid; + Point rootPoint; +#ifdef MAGIC_WRAPPER + char *ptstr; +#endif + + if ((cmd->tx_argc != 4) && (cmd->tx_argc != 3) && (cmd->tx_argc != 1)) + goto usage; + if ((cmd->tx_argc != 1) && ! + (StrIsInt(cmd->tx_argv[1]) && StrIsInt(cmd->tx_argv[2])) ) + goto usage; + + if (cmd->tx_argc == 4) { + if (StrIsInt(cmd->tx_argv[3])) + wid = atoi(cmd->tx_argv[3]); + else if (GrWindowIdPtr) + wid = (*GrWindowIdPtr)(cmd->tx_argv[3]); + else + wid = WIND_UNKNOWN_WINDOW; + } + else if (w != NULL) + wid = w->w_wid; + else { + windCheckOnlyWindow(&w, DBWclientID); + if (w != NULL) + wid = w->w_wid; + else + wid = WIND_UNKNOWN_WINDOW; + } + + /* Ensure a valid window, if possible */ + if (w == NULL) w = WindSearchWid(wid); + + if (cmd->tx_argc == 1) + { + if (w != (MagWindow *) NULL) + { + WindPointToSurface(w, &cmd->tx_p, &rootPoint, (Rect *) NULL); + +#ifdef MAGIC_WRAPPER + ptstr = (char *)Tcl_Alloc(50); + sprintf(ptstr, "%d %d %d %d", cmd->tx_p.p_x, cmd->tx_p.p_y, + rootPoint.p_x, rootPoint.p_y); + Tcl_SetResult(magicinterp, ptstr, TCL_DYNAMIC); +#else + TxPrintf("Point is at screen coordinates (%d, %d) in window %d.\n", + cmd->tx_p.p_x, cmd->tx_p.p_y, w->w_wid); + TxPrintf("Point is at layout coordinates (%d, %d)\n", + rootPoint.p_x, rootPoint.p_y); +#endif + } else { + TxPrintf("Point is at screen coordinates (%d, %d).\n", + cmd->tx_p.p_x, cmd->tx_p.p_y); + } + } + else { + int yval; + + yval = atoi(cmd->tx_argv[2]); + + /* Reinterpret coordinates according to the graphics package */ + switch (WindPackageType) + { + case WIND_X_WINDOWS: + /* Windows have origin at lower-left corner */ + yval = w->w_allArea.r_ytop - yval; + break; + } + TxSetPoint(atoi(cmd->tx_argv[1]), yval, wid); + } + return; + +usage: + TxError("Usage: %s [x y [window ID|name]]\n", cmd->tx_argv[0]); +} + +int +windSetPrintProc(name, val) + char *name; + char *val; +{ + TxPrintf("%s = \"%s\"\n", name, val); + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * windSleepCmd -- + * + * Take a nap. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windSleepCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int time; + + if (cmd->tx_argc != 2) + { + TxError("Usage: %s seconds\n", cmd->tx_argv[0]); + return; + } + + time = atoi(cmd->tx_argv[1]); + for ( ; time > 1; time--) + { + sleep(1); + if (SigInterruptPending) return; + } +} + +#ifndef MAGIC_WRAPPER + + +/* + * ---------------------------------------------------------------------------- + * + * windSourceCmd -- + * + * Implement the "source" command. + * Process a file as a list of commands. + * + * Usage: + * source filename + * + * Results: + * None. + * + * Side effects: + * Whatever the commands request. + * + * ---------------------------------------------------------------------------- + */ + +void +windSourceCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + FILE *f; + + if (cmd->tx_argc != 2) + { + TxError("Usage: %s filename\n", cmd->tx_argv[0]); + return; + } + + f = PaOpen(cmd->tx_argv[1], "r", (char *) NULL, ".", + SysLibPath, (char **) NULL); + if (f == NULL) + TxError("Couldn't read from %s.\n", cmd->tx_argv[1]); + else { + TxDispatch(f); + (void) fclose(f); + }; +} + +#endif + +/* + * ---------------------------------------------------------------------------- + * windSpecialOpenCmd -- + * + * Open a new window at the cursor position. Give it a default size, + * and take the client's name from the command line. Pass the rest of + * the command arguments off to the client. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windSpecialOpenCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + WindClient wc; + Rect area; + bool haveCoords; + char *client; + + haveCoords = FALSE; + + if (cmd->tx_argc < 2) goto usage; + haveCoords = StrIsInt(cmd->tx_argv[1]); + if (haveCoords && ( + (cmd->tx_argc < 6) || + !StrIsInt(cmd->tx_argv[2]) || + !StrIsInt(cmd->tx_argv[3]) || + !StrIsInt(cmd->tx_argv[4]) + )) goto usage; + if (haveCoords) + client = cmd->tx_argv[5]; + else + client = cmd->tx_argv[1]; + + wc = WindGetClient(client, FALSE); + /* clients whose names begin with '*' are hidden */ + if ((wc == (WindClient) NULL) || (client[0] == '*')) goto usage; + + if (haveCoords) { + area.r_xbot = atoi(cmd->tx_argv[1]); + area.r_ybot = atoi(cmd->tx_argv[2]); + area.r_xtop = MAX(atoi(cmd->tx_argv[3]), area.r_xbot + WIND_MIN_WIDTH); + area.r_ytop = MAX(atoi(cmd->tx_argv[4]), area.r_ybot + WIND_MIN_HEIGHT); + /* Assume that the client will print an error message if it fails */ + (void) WindCreate(wc, &area, FALSE, cmd->tx_argc - 6, cmd->tx_argv + 6); + } + else { + area.r_xbot = cmd->tx_p.p_x - CREATE_WIDTH/2; + area.r_xtop = cmd->tx_p.p_x + CREATE_WIDTH/2; + area.r_ybot = cmd->tx_p.p_y - CREATE_HEIGHT/2; + area.r_ytop = cmd->tx_p.p_y + CREATE_HEIGHT/2; + /* Assume that the client will print an error message if it fails */ + (void) WindCreate(wc, &area, TRUE, cmd->tx_argc - 2, cmd->tx_argv + 2); + } + + return; + +usage: + TxPrintf("Usage: specialopen [leftx bottomy rightx topy] type [args]\n"); + TxPrintf("Valid window types are:\n"); + WindPrintClientList(FALSE); + return; +} + +/* + * ---------------------------------------------------------------------------- + * windNamesCmd -- + * + * Register or retrieve the name associated with the layout window + * + * Results: + * Returns the name as a Tcl string result. If "all" is selected, + * or if w is NULL and cannot be determined, returns a list of all + * window names. The first argument may also be a window client + * type, in which case only windows of that type are returned. + * + * Note: + * This routine can easily be made "generic", not Tcl-specific. + * However, of the graphics interfaces available, only Tcl/Tk keeps + * track of windows by name. + * + * ---------------------------------------------------------------------------- + */ + +void +windNamesCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + bool doforall = FALSE; + WindClient wc = (WindClient)NULL; + MagWindow *sw; + + if (cmd->tx_argc > 2) + { + TxError("Usage: windownames [all | client_type]\n"); + return; + } + if (cmd->tx_argc == 2) + { + if (!strncmp(cmd->tx_argv[1], "all", 3)) + doforall = TRUE; + else + { + wc = WindGetClient(cmd->tx_argv[1], FALSE); + if (wc == (WindClient) NULL) + { + TxError("Usage: windownames [all | client_type]\n"); + TxPrintf("Valid window types are:\n"); + WindPrintClientList(FALSE); + return; + } + doforall = TRUE; + } + } + + if (cmd->tx_argc == 1) + { + wc = DBWclientID; + windCheckOnlyWindow(&w, wc); + if (w == (MagWindow *)NULL) + doforall = TRUE; + } + +#ifdef MAGIC_WRAPPER + if (doforall == TRUE) + { + Tcl_Obj *tlist; + + tlist = Tcl_NewListObj(0, NULL); + for (sw = windTopWindow; sw != NULL; sw = sw->w_nextWindow) + if ((wc == NULL) || (sw->w_client == wc)) + { + if (GrWindowNamePtr) + Tcl_ListObjAppendElement(magicinterp, tlist, + Tcl_NewStringObj((*GrWindowNamePtr)(sw), -1)); + else + Tcl_ListObjAppendElement(magicinterp, tlist, + Tcl_NewIntObj(sw->w_wid)); + } + Tcl_SetObjResult(magicinterp, tlist); + } + else + { + if (GrWindowNamePtr) + Tcl_SetResult(magicinterp, (*GrWindowNamePtr)(w), NULL); + else + Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(w->w_wid)); + } +#else + if (doforall == TRUE) + { + if (GrWindowNamePtr) + TxPrintf("Window ID Window Name\n"); + else + TxPrintf("Window ID\n"); + for (sw = windTopWindow; sw != NULL; sw = sw->w_nextWindow) + if ((wc == (WindClient)NULL) || (sw->w_client == wc)) + { + if (GrWindowNamePtr) + TxPrintf("%d %s\n", sw->w_wid, (*GrWindowNamePtr)(sw)); + else + TxPrintf("%d\n", sw->w_wid); + } + } + else + { + if (GrWindowNamePtr) + TxPrintf("Window ID = %d, Name = %s\n", w->w_wid, + (*GrWindowNamePtr)(w)); + else + TxPrintf("Window ID = %d\n", w->w_wid); + } +#endif /* !MAGIC_WRAPPER */ +} + + +/* + * ---------------------------------------------------------------------------- + * windUnderCmd -- + * + * Move a window underneath the other windows. + * + * Results: + * None. + * + * Side effects: + * Screen updates. + * ---------------------------------------------------------------------------- + */ + +void +windUnderCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (cmd->tx_argc != 1) + { + TxError("Usage: %s\n", cmd->tx_argv[0]); + } + if (w == NULL) + { + TxError("Point to a window first.\n"); + return; + } + WindUnder(w); +} + + +/* + * ---------------------------------------------------------------------------- + * + * windUndoCmd + * + * Implement the "undo" command. + * + * Usage: + * undo [count] + * + * If a count is supplied, the last count events are undone. The default + * count if none is given is 1. + * + * Results: + * None. + * + * Side effects: + * Calls the undo module. + * + * ---------------------------------------------------------------------------- + */ + +void +windUndoCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int count; + + if (cmd->tx_argc > 3) + { + TxError("Usage: undo [count]\n"); + TxError(" undo print [count]\n"); + TxError(" undo enable|disable\n"); + return; + } + else if (cmd->tx_argc == 3) + { + if (strncmp(cmd->tx_argv[1], "print", 5)) + { + TxError("Usage: undo print count\n"); + return; + } + else if (!StrIsInt(cmd->tx_argv[2])) + { + TxError("Usage: undo print count\n"); + return; + } + else + { + /* Implement undo stack trace */ + UndoStackTrace((-1) - atoi(cmd->tx_argv[2])); + return; + } + } + else if (cmd->tx_argc == 2) + { + if (!StrIsInt(cmd->tx_argv[1])) + { + if (!strcmp(cmd->tx_argv[1], "enable")) + UndoEnable(); + else if (!strcmp(cmd->tx_argv[1], "disable")) + UndoDisable(); + else + TxError("Option must be a count (integer)\n"); + return; + } + count = atoi(cmd->tx_argv[1]); + if (count < 0) + { + TxError("Count must be a positive integer\n"); + return; + } + } + else + count = 1; + + if (count == 0) + { + UndoEnable(); + } + else + { + if (UndoBackward(count) == 0) + TxPrintf("Nothing more to undo\n"); + } +} + + +/* + * ---------------------------------------------------------------------------- + * windUpdateCmd -- + * + * Force an update of the graphics screen. This is usually only called + * from command scripts. + * + * Results: + * None. + * + * Side effects: + * Display updates. + * ---------------------------------------------------------------------------- + */ + +void +windUpdateCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (cmd->tx_argc == 1) + WindUpdate(); +#ifdef MAGIC_WRAPPER + else if (cmd->tx_argc > 2) + goto badusage; + else if (!strcmp(cmd->tx_argv[1], "suspend")) + GrDisplayStatus = DISPLAY_SUSPEND; + else if (!strcmp(cmd->tx_argv[1], "resume")) + GrDisplayStatus = DISPLAY_IDLE; + else + goto badusage; +#else + else if (cmd->tx_argc >= 2) + goto badusage; +#endif + return; + +badusage: + TxError("Usage: %s [suspend | resume]\n", cmd->tx_argv[0]); + return; +} + +/* + * ---------------------------------------------------------------------------- + * + * windVersionCmd -- + * + * Print version information. + * + * Usage: + * version + * + * Results: + * None. + * + * Side effects: + * Prints on stdout. + * + * ---------------------------------------------------------------------------- + */ + +void +windVersionCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (cmd->tx_argc != 1) { + TxError("Usage: %s\n", cmd->tx_argv[0]); + return; + } + + TxPrintf("Version %s revision %s. Compiled on %s.\n", + MagicVersion, MagicRevision, MagicCompileTime); +} + +/* + * ---------------------------------------------------------------------------- + * + * windViewCmd -- + * + * Implement the "View" command. + * Change the view in the selected window so everything is visible. + * + * Usage: + * view + * + * Results: + * None. + * + * Side effects: + * The window underneath the cursor is changed. + * In Tcl version, if supplied with the argument "get", the + * interpreter return value is set to the current view position. + * + * ---------------------------------------------------------------------------- + */ + +void +windViewCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + if (w == NULL) + return; + + if (cmd->tx_argc == 1) + { + if ((w->w_flags & WIND_SCROLLABLE) == 0) { + TxError("Sorry, can't zoom out this window.\n"); + return; + } + WindView(w); + } + else if (cmd->tx_argc == 2) + { +#ifdef MAGIC_WRAPPER + Tcl_Obj *listxy, *fval; + + listxy = Tcl_NewListObj(0, NULL); +#endif + + if (!strncmp(cmd->tx_argv[1], "get", 3)) + { +#ifndef MAGIC_WRAPPER + TxPrintf("(%d, %d) to (%d, %d)\n", + w->w_surfaceArea.r_xbot, w->w_surfaceArea.r_ybot, + w->w_surfaceArea.r_xtop, w->w_surfaceArea.r_ytop); +#else + Tcl_ListObjAppendElement(magicinterp, listxy, + Tcl_NewIntObj((int)w->w_surfaceArea.r_xbot)); + Tcl_ListObjAppendElement(magicinterp, listxy, + Tcl_NewIntObj((int)w->w_surfaceArea.r_ybot)); + Tcl_ListObjAppendElement(magicinterp, listxy, + Tcl_NewIntObj((int)w->w_surfaceArea.r_xtop)); + Tcl_ListObjAppendElement(magicinterp, listxy, + Tcl_NewIntObj((int)w->w_surfaceArea.r_ytop)); + Tcl_SetObjResult(magicinterp, listxy); +#endif + } + else if (!strncmp(cmd->tx_argv[1], "bbox", 4)) + { +#ifndef MAGIC_WRAPPER + TxPrintf("(%d, %d) to (%d, %d)\n", + w->w_bbox->r_xbot, w->w_bbox->r_ybot, + w->w_bbox->r_xtop, w->w_bbox->r_ytop); +#else + Tcl_ListObjAppendElement(magicinterp, listxy, + Tcl_NewIntObj((int)w->w_bbox->r_xbot)); + Tcl_ListObjAppendElement(magicinterp, listxy, + Tcl_NewIntObj((int)w->w_bbox->r_ybot)); + Tcl_ListObjAppendElement(magicinterp, listxy, + Tcl_NewIntObj((int)w->w_bbox->r_xtop)); + Tcl_ListObjAppendElement(magicinterp, listxy, + Tcl_NewIntObj((int)w->w_bbox->r_ytop)); + Tcl_SetObjResult(magicinterp, listxy); +#endif + } + else + { + char *sptr, *pptr; + Rect r; + + // Parse out coordinates where all coordinates have been + // put into a single string argument, as happens when the + // coordinates are a Tcl list, e.g., from "[box values]" + + sptr = cmd->tx_argv[1]; + if ((pptr = strchr(sptr, ' ')) == NULL) return; + *pptr++ = '\0'; + r.r_xbot = cmdParseCoord(w, sptr, FALSE, TRUE); + + sptr = pptr; + if ((pptr = strchr(sptr, ' ')) == NULL) return; + *pptr++ = '\0'; + r.r_ybot = cmdParseCoord(w, sptr, FALSE, TRUE); + + sptr = pptr; + if ((pptr = strchr(sptr, ' ')) == NULL) return; + *pptr++ = '\0'; + r.r_xtop = cmdParseCoord(w, sptr, FALSE, TRUE); + r.r_ytop = cmdParseCoord(w, pptr, FALSE, TRUE); + + /* Redisplay */ + WindMove(w, &r); + } + } + else if (cmd->tx_argc == 5) + { + Rect r; + r.r_xbot = cmdParseCoord(w, cmd->tx_argv[1], FALSE, TRUE); + r.r_ybot = cmdParseCoord(w, cmd->tx_argv[2], FALSE, FALSE); + r.r_xtop = cmdParseCoord(w, cmd->tx_argv[3], FALSE, TRUE); + r.r_ytop = cmdParseCoord(w, cmd->tx_argv[4], FALSE, FALSE); + + /* Redisplay */ + WindMove(w, &r); + } + else + { + TxError("Usage: view [get|bbox|llx lly urx ury]\n"); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * windXviewCmd -- + * + * Implement the "Xview" command. + * Change the view in the selected window so everything is visible, but + * not expanded. + * + * Usage: + * xview + * + * Results: + * None. + * + * Side effects: + * The window underneath the cursor is changed. The root cell of the + * window is unexpanded. + * + * ---------------------------------------------------------------------------- + */ + +void +windXviewCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + CellUse *celluse; + int ViewUnexpandFunc(); + + if (w == NULL) + return; + + if ((w->w_flags & WIND_SCROLLABLE) == 0) { + TxError("Sorry, can't zoom out this window.\n"); + return; + }; + + celluse = (CellUse *) (w->w_surfaceID); + DBExpandAll(celluse, &(celluse->cu_bbox), + ((DBWclientRec *)w->w_clientData)->dbw_bitmask, FALSE, + ViewUnexpandFunc, + (ClientData)(pointertype) (((DBWclientRec *)w->w_clientData)->dbw_bitmask)); + + WindView(w); +} + +/* This function is called for each cell whose expansion status changed. + * It forces the cells area to be redisplayed, then returns 0 to keep + * looking for more cells to unexpand. + */ + +int +ViewUnexpandFunc(use, windowMask) + CellUse *use; /* Use that was just unexpanded. */ + int windowMask; /* Window where it was unexpanded. */ +{ + if (use->cu_parent == NULL) return 0; + DBWAreaChanged(use->cu_parent, &use->cu_bbox, windowMask, + (TileTypeBitMask *) NULL); + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * windScrollBarsCmd -- + * + * Change the flag which says whether new windows will have scroll bars. + * + * Usage: + * windscrollbars [on|off] + * + * Results: + * None. + * + * Side effects: + * A flag is changed. + * + * ---------------------------------------------------------------------------- + */ + +void +windScrollBarsCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int place; + static char *onoff[] = {"on", "off", 0}; + static bool truth[] = {TRUE, FALSE}; + + if (cmd->tx_argc != 2) goto usage; + + place = Lookup(cmd->tx_argv[1], onoff); + if (place < 0) goto usage; + + if (truth[place]) + { + WindDefaultFlags |= WIND_SCROLLBARS; + TxPrintf("New windows will have scroll bars.\n"); + } + else + { + WindDefaultFlags &= ~WIND_SCROLLBARS; + TxPrintf("New windows will not have scroll bars.\n"); + } + return; + + usage: + TxError("Usage: %s [on|off]\n", cmd->tx_argv[0]); + return; +} + +#ifndef MAGIC_WRAPPER + + +/* + * ---------------------------------------------------------------------------- + * + * windSendCmd -- + * + * Send a command to a certain window type. If possible we will pass a + * arbitrarily chosen window of that type down to the client. + * + * Usage: + * send type command + * + * Results: + * None. + * + * Side effects: + * Whatever the client does + * + * ---------------------------------------------------------------------------- + */ + +void +windSendCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + MagWindow *toWindow; + WindClient client; + TxCommand newcmd; + extern int windSendCmdFunc(); + + if (cmd->tx_argc < 3) goto usage; + if (cmd->tx_argv[1][0] == '*') goto usage; /* hidden window client */ + + client = WindGetClient(cmd->tx_argv[1], FALSE); + if (client == (WindClient) NULL) goto usage; + toWindow = (MagWindow *) NULL; + (void) WindSearch(client, (ClientData) NULL, (Rect *) NULL, + windSendCmdFunc, (ClientData) &toWindow); + { + int i; + newcmd = *cmd; + newcmd.tx_argc -= 2; + for (i = 0; i < newcmd.tx_argc; i++) { + newcmd.tx_argv[i] = newcmd.tx_argv[i + 2]; + }; + } + newcmd.tx_wid = WIND_UNKNOWN_WINDOW; + if (toWindow != NULL) newcmd.tx_wid = toWindow->w_wid; + (void) WindSendCommand(toWindow, &newcmd, FALSE); + return; + + usage: + TxError("Usage: send type command\n"); + TxPrintf("Valid window types are:\n"); + WindPrintClientList(FALSE); + return; +} + +int +windSendCmdFunc(w, cd) + MagWindow *w; + ClientData cd; +{ + *((MagWindow **) cd) = w; + return 1; +} + +#endif + +/* Structure used by "position" command to pass to WindSearch */ +/* as client data. */ + +typedef struct _cdwpos { + FILE *file; + bool doFrame; +} cdwpos; + + +/* + * ---------------------------------------------------------------------------- + * + * windPositionsCmd -- + * + * Print out the positions of the windows. + * + * Usage: + * windowpositions [file] + * + * Results: + * None. + * + * Side effects: + * A file is written. + * + * ---------------------------------------------------------------------------- + */ + +void +windPositionsCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + extern int windPositionsFunc(); + char *filename = NULL; + cdwpos windpos; + + windpos.doFrame = FALSE; + windpos.file = stdout; + + if (cmd->tx_argc > 3) goto usage; + if (cmd->tx_argc > 1) + { + if (!strncmp(cmd->tx_argv[1], "frame", 5)) + { + windpos.doFrame = TRUE; + if (cmd->tx_argc == 3) + filename = cmd->tx_argv[2]; + } + else if (cmd->tx_argc == 2) + filename = cmd->tx_argv[1]; + else + goto usage; + } + + if (filename) { + windpos.file = fopen(filename, "w"); + if (windpos.file == (FILE *) NULL) + { + TxError("Could not open file %s for writing.\n", filename); + return; + }; + } + (void) WindSearch((WindClient) NULL, (ClientData) NULL, (Rect *) NULL, + windPositionsFunc, (ClientData) &windpos); + if (filename) (void) fclose(windpos.file); + return; + +usage: + TxError("Usage: windowpositions [file]\n"); + return; +} + +int +windPositionsFunc(w, cdata) + MagWindow *w; + ClientData cdata; +{ + cdwpos *windpos = (cdwpos *)cdata; + Rect r; + + if (windpos->doFrame) + r = w->w_frameArea; + else + r = w->w_screenArea; + + if (windpos->file == stdout) +#ifdef MAGIC_WRAPPER + { + Tcl_Obj *lobj; + + lobj = Tcl_NewListObj(0, NULL); + + Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_xbot)); + Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_ybot)); + Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_xtop)); + Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_ytop)); + Tcl_ListObjAppendElement(magicinterp, lobj, + Tcl_NewStringObj(((clientRec *)w->w_client)->w_clientName, + strlen(((clientRec *)w->w_client)->w_clientName))); + Tcl_SetObjResult(magicinterp, lobj); + } +#else + TxPrintf("specialopen %d %d %d %d %s\n", + r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop, + ((clientRec *) w->w_client)->w_clientName); +#endif + else + fprintf((FILE *)cdata, "specialopen %d %d %d %d %s\n", + r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop, + ((clientRec *) w->w_client)->w_clientName); + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * windZoomCmd -- + * + * Implement the "zoom" command. + * Change the view in the selected window by the given scale factor. + * + * Usage: + * zoom amount + * + * Results: + * None. + * + * Side effects: + * The window underneath the cursor is changed. + * + * ---------------------------------------------------------------------------- + */ + +void +windZoomCmd(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + float factor; + + if (w == NULL) + return; + + if ((w->w_flags & WIND_SCROLLABLE) == 0) { + TxError("Sorry, can't zoom this window.\n"); + return; + }; + + if (cmd->tx_argc != 2) + { + TxError("Usage: %s factor\n", cmd->tx_argv[0]); + return; + } + + factor = MagAtof(cmd->tx_argv[1]); + if ((factor <= 0) || (factor >= 20)) + { + TxError("zoom factor must be between 0 and 20.\n"); + return; + } + + WindZoom(w, factor); +} diff --git a/windows/windDebug.c b/windows/windDebug.c new file mode 100644 index 00000000..ef024466 --- /dev/null +++ b/windows/windDebug.c @@ -0,0 +1,179 @@ + +/* windDebug.c - + * + * Print out the window package's internal data structures. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windDebug.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/glyphs.h" +#include "windows/windInt.h" +#include "textio/textio.h" +#include "textio/txcommands.h" + + + +/* + * ---------------------------------------------------------------------------- + * windPrintWindow -- + * + * Print out the window data structure. + * + * Results: + * None. + * + * Side effects: + * Text appears on the text terminal. + * ---------------------------------------------------------------------------- + */ + +void +windPrintWindow(w) + MagWindow *w; +{ + LinkedRect *lr; + + TxPrintf("\nWindow %d: '%s'\n", w->w_wid, w->w_caption); + TxPrintf(" Client %x Surface %x \n", w->w_client, w->w_surfaceID); + + TxPrintf(" All area (%d, %d) (%d, %d)\n", + w->w_allArea.r_xbot, w->w_allArea.r_ybot, + w->w_allArea.r_xtop, w->w_allArea.r_ytop); + TxPrintf(" Screen area (%d, %d) (%d, %d)\n", + w->w_screenArea.r_xbot, w->w_screenArea.r_ybot, + w->w_screenArea.r_xtop, w->w_screenArea.r_ytop); + TxPrintf(" Frame area (%d, %d) (%d, %d)\n", + w->w_frameArea.r_xbot, w->w_frameArea.r_ybot, + w->w_frameArea.r_xtop, w->w_frameArea.r_ytop); + + if (w->w_clipAgainst == NULL) + TxPrintf(" No areas obscure the window.\n"); + else + TxPrintf(" These areas obscure the window:\n"); + for (lr = w->w_clipAgainst; lr != NULL; lr = lr->r_next) + { + TxPrintf(" (%d, %d) (%d, %d) \n", lr->r_r.r_xbot, lr->r_r.r_ybot, + lr->r_r.r_xtop, lr->r_r.r_ytop); + } + + TxPrintf(" Surface area (%d, %d) (%d, %d) \n", + w->w_surfaceArea.r_xbot, w->w_surfaceArea.r_ybot, + w->w_surfaceArea.r_xtop, w->w_surfaceArea.r_ytop); + TxPrintf(" Origin (%d, %d)\n", w->w_origin.p_x, w->w_origin.p_y); + TxPrintf(" Scale %d\n", w->w_scale); +} + +/* + * ---------------------------------------------------------------------------- + * windDump -- + * + * Print out all the tables and windows. + * + * Results: + * None. + * + * Side effects: + * Lots of text is dumped to the text terminal. + * ---------------------------------------------------------------------------- + */ + +void +windDump() +{ + MagWindow *w; + clientRec *rc; + + TxPrintf("\n\n------------ Clients ----------\n"); + for (rc = windFirstClientRec; rc != (clientRec * ) NULL; + rc = rc->w_nextClient) + { + TxPrintf("'%10s' %x %x %x %x\n", rc->w_clientName, + rc->w_create, rc->w_delete, + rc->w_redisplay, rc->w_command); + } + + TxPrintf("\n"); + for (w = windTopWindow; w != (MagWindow *) NULL; w = w->w_nextWindow) + { + windPrintWindow(w); + } + +} + + +/* + * ---------------------------------------------------------------------------- + * windPrintCommand -- + * + * Print out a command. + * + * Results: + * None. + * + * Side effects: + * Text appears on the text terminal. + * ---------------------------------------------------------------------------- + */ + +void +windPrintCommand(cmd) + TxCommand *cmd; +{ + if (cmd->tx_button == TX_NO_BUTTON) + { + int i; + + for (i = 0; i < cmd->tx_argc; i++) + { + TxPrintf(" '%s'", cmd->tx_argv[i]); + } + } + else + { + switch (cmd->tx_button) + { + case TX_LEFT_BUTTON: + TxPrintf("Left"); + break; + case TX_RIGHT_BUTTON: + TxPrintf("Right"); + break; + case TX_MIDDLE_BUTTON: + TxPrintf("Middle"); + break; + default: + TxPrintf("STRANGE"); + break; + } + TxPrintf(" button "); + switch (cmd->tx_buttonAction) + { + case TX_BUTTON_DOWN: + TxPrintf("down"); + break; + case TX_BUTTON_UP: + TxPrintf("up"); + break; + } + } + TxPrintf(" at (%d, %d)\n", cmd->tx_p.p_x, cmd->tx_p.p_y); +} diff --git a/windows/windDisp.c b/windows/windDisp.c new file mode 100644 index 00000000..47643959 --- /dev/null +++ b/windows/windDisp.c @@ -0,0 +1,984 @@ +/* windDisplay.c - + * + * Display the borders of the window, including the caption area. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windDisp.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/utils.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "graphics/glyphs.h" +#include "windows/windows.h" +#include "windows/windInt.h" +#include "graphics/graphics.h" +#include "utils/styles.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/undo.h" +#include "utils/signals.h" +#include "utils/malloc.h" + +/* The following Plane is used to keep track of areas of the + * screen that have changed. ERROR_P tiles are used to record + * areas of the screen (in pixels) that must be redisplayed. + * + * If windows have speparate coordinate spaces (as on a SUN), this plane + * is ignored and the one in w->w_redrawAreas is used instead. + */ + +global Plane *windRedisplayArea = NULL; +static Plane *windCurRedrawPlane = NULL; /* used for sharing between procs */ +static LinkedRect *windCoveredAreas = NULL; +global GrGlyphs *windGlyphs = NULL; + +/* windCaptionPixels is the height of the caption strip. It is internal to + * this module. + */ + +int windCaptionPixels = 0; + +/* Are the windows in their own coordinate system? + */ +bool windSomeSeparateRedisplay = FALSE; + +/* + * ---------------------------------------------------------------------------- + * + * windCheckOnlyWindow -- + * + * Check if the TopWindow is the only window---if so, we shouldn't + * generate bothersome messages about the cursor not being in a window, + * because there is no confusion. + * + * We want to make sure that we don't count windows which are not of + * the same client type. + * + * ---------------------------------------------------------------------------- + */ + +int +windCheckOnlyWindow(MagWindow **w, WindClient client) +{ + MagWindow *sw, *tw; + int wct = 0; + + if (*w != NULL) return 0; + + if (windTopWindow != NULL) + { + for (sw = windTopWindow; sw != NULL; sw = sw->w_nextWindow) + { + if (sw->w_client == client) + { + wct++; + tw = sw; + } + } + if (wct == 1) *w = tw; + } + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * windFreeList -- + * + * Free up a list of linked rectangles. + * + * Results: + * None. + * + * Side effects: + * Storage is reclaimed. The original pointer is NULLed out. + * ---------------------------------------------------------------------------- + */ + +void +windFreeList(llr) + LinkedRect **llr; /* A pointer to a list of linked rectangles */ +{ + LinkedRect *lr, *freelr; + + lr = *llr; + while (lr != (LinkedRect *) NULL) + { + freelr = lr; + lr = lr->r_next; + freeMagic( (char *) freelr); + } + + *llr = (LinkedRect *) NULL; +} + + + +/* + * ---------------------------------------------------------------------------- + * windReClip -- + * + * Traverse the linked list of windows, updating w_clipAgainst + * for each window. + * + * Results: + * None. + * + * Side effects: + * Changes w_clipAgainst for some windows. + * ---------------------------------------------------------------------------- + */ + +void +windReClip() +{ + MagWindow *w1, *w2; + + /* an O(n**2) operation!! */ + windFreeList(&windCoveredAreas); + + for (w1 = windBottomWindow; w1 != (MagWindow *) NULL; w1 = w1->w_prevWindow) + { + LinkedRect *tmp; + + /* add window onto windCoveredAreas */ + tmp = (LinkedRect *) mallocMagic((unsigned) (sizeof (LinkedRect))); + tmp->r_next = windCoveredAreas; + tmp->r_r = w1->w_frameArea; + windCoveredAreas = tmp; + + /* free up the old clipping areas and make new ones */ + windFreeList( &(w1->w_clipAgainst) ); + w1->w_clipAgainst = (LinkedRect *) NULL; + + /* Leave w_clipAgainst to be NULL if we are using some other + * window package, because that package will handle overlapping + * windows. + */ + if (WindPackageType == WIND_MAGIC_WINDOWS) { + for (w2 = w1->w_prevWindow; w2 != (MagWindow *) NULL; + w2 = w2->w_prevWindow) + { + if ( GEO_TOUCH( &(w1->w_frameArea), &(w2->w_frameArea) )) + { + tmp = (LinkedRect *) mallocMagic((unsigned) (sizeof (LinkedRect))); + tmp->r_next = w1->w_clipAgainst; + tmp->r_r = w2->w_frameArea; + w1->w_clipAgainst = tmp; + } + } + } + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * WindSeparateRedisplay -- + * + * Tells the window manager to record redisplay areas for this window + * separately -- probably because the window has its own separate + * coordinate system. (Used on the Sun with Suntools or X.) + * + * Results: + * None. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +void +WindSeparateRedisplay(w) + MagWindow *w; +{ + windSomeSeparateRedisplay = TRUE; + if (w->w_redrawAreas != (ClientData)NULL) return; + w->w_redrawAreas = (ClientData) DBNewPlane((ClientData) TT_SPACE); +} + + +/* + * ---------------------------------------------------------------------------- + * WindIconChanged -- + * + * Mark the icon for this window as needing to be redisplayed. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +WindIconChanged(w) + MagWindow *w; +{ + ASSERT(w != NULL, "WindIconChanged"); + w->w_flags |= WIND_REDRAWICON; +} + + +/* + * ---------------------------------------------------------------------------- + * WindAreaChanged -- + * + * Notify the window package that a certain area of the screen has + * changed, and now needs to be redrawn. + * + * Results: + * None. + * + * Side effects: + * The area is noted as having changed in window w. When + * WindUpdate is called, this area will be redisplayed, but + * only in w. If w is NULL, then this area will be redisplayed + * in all windows. If area is NULL, then the whole area of + * the window will be redisplayed. If both are NULL, then + * the whole screen will be redisplayed. + * ---------------------------------------------------------------------------- + */ + +void +WindAreaChanged(w, area) + MagWindow *w; /* The window that changed. */ + Rect *area; /* The area in screen coordinates. + * NULL means the whole screen. Caller + * should clip this rectangle to the area + * of the window. + */ +{ + Rect biggerArea; + int windChangedFunc(); /* Forward declaration. */ + + if (w == NULL) { + if (windSomeSeparateRedisplay) { + MagWindow *nw; + for (nw = windTopWindow; nw != NULL; nw = nw->w_nextWindow) + WindAreaChanged(nw, area); + return; + } else + windCurRedrawPlane = windRedisplayArea; + } else { + if (w->w_redrawAreas != (ClientData)NULL) + windCurRedrawPlane = (Plane *) w->w_redrawAreas; + else + windCurRedrawPlane = windRedisplayArea; + } + + if (area == (Rect *) NULL) + { + /* Everything changed -- all the window's area as well as the icon. */ + if (w != (MagWindow *) NULL) { + area = &w->w_allArea; + WindIconChanged(w); + } else { + MagWindow *nw; + area = &GrScreenRect; + for (nw = windTopWindow; nw != NULL; nw = nw->w_nextWindow) + WindIconChanged(nw); + } + } + + /* We have to increase the upper x- and y-coordinates of + * the redisplay area by one. This is because a pixel is + * considered to include its entire area (up to the beginning + * of the next pixel). Without this code and corresponding + * hacks in WindUpdate and windBackgroundFunc, little slivers + * get left lying around. + */ + + biggerArea = *area; + biggerArea.r_xtop += 1; + biggerArea.r_ytop += 1; + + /* If no window is given, or if the window is unobscured, + * then just paint an error tile over the area to be redisplayed. + * Otherwise, clip the area against all the obscuring areas + * for the window. Be careful to keep undo away from this. + */ + + UndoDisable(); + if ((w == NULL) || (w->w_clipAgainst == NULL)) + DBPaintPlane(windCurRedrawPlane, &biggerArea, + DBStdPaintTbl(TT_ERROR_P, PL_DRC_ERROR), (PaintUndoInfo *) NULL); + else + { + (void) GeoDisjoint(&biggerArea, &w->w_clipAgainst->r_r, windChangedFunc, + (ClientData) w->w_clipAgainst->r_next); + } + UndoEnable(); + + /* If the area is NULL or encompasses the whole screen area, and */ + /* there is no backing store, then we should create it so that it */ + /* will be copied into on the next display redraw. */ + + if ((w != NULL) && (w->w_backingStore == (ClientData)NULL) && + (!(w->w_flags & WIND_OBSCURED)) && (GrCreateBackingStorePtr != NULL)) + if ((area == (Rect *)NULL) || GEO_SURROUND(&biggerArea, &w->w_screenArea)) + (*GrCreateBackingStorePtr)(w); +} + +int +windChangedFunc(area, next) + Rect *area; /* Area that is still unobscured. */ + LinkedRect *next; /* Next obscuring area. */ +{ + /* If we're at the end of obscuring areas, paint an error + * tile to mark what's to be redisplayed. Otherwise, + * clip against the next obscuring area. + */ + + if (next == NULL) + DBPaintPlane(windCurRedrawPlane, area, + DBStdPaintTbl(TT_ERROR_P, PL_DRC_ERROR), (PaintUndoInfo *) NULL); + else (void) GeoDisjoint(area, &next->r_r, windChangedFunc, + (ClientData) next->r_next); + return 0; +} + + + + +/* + * ---------------------------------------------------------------------------- + * windBarLocations -- + * + * Find the scroll bars and icons in the window. + * Each argument must point to a different piece of memory. + * + * Results: + * None. + * + * Side effects: + * Returns a bunch of rectangles describing the locations of things. + * See comments next to the argument list for details. + * ---------------------------------------------------------------------------- + */ + +void +windBarLocations(w, leftBar, botBar, up, down, right, left, zoom) + MagWindow *w; /* The window under consideration. */ + /* The following are rectangles that will be filled + * in by this procedure. The values will be in the + * same coordinate sytem as w->w_allArea. + */ + Rect *leftBar; /* The location of the left scrollbar area (not the + * bar itself). + */ + Rect *botBar; /* The location of the bottom scrollbar area. */ + Rect *up; /* The location of the 'up arrow' icon above the + * left scroll bar. + */ + Rect *down; /* The location of the 'down arrow' icon below the + * left scroll bar. + */ + Rect *right; /* The location of the 'right arrow' icon to the right + * of the bottom scroll bar. + */ + Rect *left; /* The location of the 'left arrow' icon to the left of + * the bottom scroll bar. + */ + Rect *zoom; /* The location of the 'zoom' icon in the lower-left + * corner of the window. + */ +{ + /* left scroll bar area */ + leftBar->r_xbot = w->w_allArea.r_xbot + THIN_LINE; + leftBar->r_ybot = w->w_allArea.r_ybot + THIN_LINE + WindScrollBarWidth + + BOT_BORDER(w); + leftBar->r_xtop = leftBar->r_xbot + WindScrollBarWidth - GrPixelCorrect; + leftBar->r_ytop = w->w_allArea.r_ytop - THIN_LINE - WindScrollBarWidth - + TOP_BORDER(w); + + /* bottom scroll bar area */ + botBar->r_ybot = w->w_allArea.r_ybot + THIN_LINE; + botBar->r_xbot = w->w_allArea.r_xbot + THIN_LINE + WindScrollBarWidth + + LEFT_BORDER(w); + botBar->r_ytop = botBar->r_ybot + WindScrollBarWidth - GrPixelCorrect; + botBar->r_xtop = w->w_allArea.r_xtop - THIN_LINE - WindScrollBarWidth - + RIGHT_BORDER(w); + + /* border icons */ + down->r_xbot = up->r_xbot = leftBar->r_xbot; + down->r_xtop = up->r_xtop = leftBar->r_xtop; + up->r_ybot = leftBar->r_ytop + THIN_LINE + 1; + up->r_ytop = up->r_ybot + WindScrollBarWidth - 1; + down->r_ytop = leftBar->r_ybot - THIN_LINE - 1; + down->r_ybot = down->r_ytop - WindScrollBarWidth + 1; + + left->r_ybot = right->r_ybot = botBar->r_ybot; + left->r_ytop = right->r_ytop = botBar->r_ytop; + right->r_xbot = botBar->r_xtop + THIN_LINE + 1; + right->r_xtop = right->r_xbot + WindScrollBarWidth - 1; + left->r_xtop = botBar->r_xbot - THIN_LINE - 1; + left->r_xbot = left->r_xtop - WindScrollBarWidth + 1; + + zoom->r_xbot = w->w_allArea.r_xbot + THIN_LINE; + zoom->r_ybot = w->w_allArea.r_ybot + THIN_LINE; + zoom->r_xtop = zoom->r_xbot + WindScrollBarWidth - 1; + zoom->r_ytop = zoom->r_ybot + WindScrollBarWidth - 1; +} + + +/* + * ---------------------------------------------------------------------------- + * WindDrawBorder -- + * + * Draw the border of windows. A window lock is created & then destroyed. + * + * Results: + * None. + * + * Side effects: + * Redisplays the scroll bar & caption areas of a window's border. + * ---------------------------------------------------------------------------- + */ + +void +WindDrawBorder(w, clip) + MagWindow *w; + Rect *clip; +{ + Rect r; + Rect leftBar, botBar, up, down, left, right, zoom; + Rect leftElev, botElev; + int bar, bbox, viewl, viewu; + Point capp; + Rect capr; + + GrLock(w, FALSE); + GrClipTo(clip); + + + /* Redisplay the caption if it overlaps the area. */ + + capr = w->w_allArea; + capr.r_ybot = capr.r_ytop - TOP_BORDER(w) + GrPixelCorrect; + capp.p_x = (capr.r_xbot + capr.r_xtop) / 2; + capp.p_y = (capr.r_ybot + capr.r_ytop + 1) / 2; + if (GEO_TOUCH(&capr, clip)) { + if (w->w_flags & WIND_BORDER) + GrClipBox(&capr, STYLE_BORDER); + if ((w->w_flags & WIND_CAPTION) && (w->w_caption != NULL)) { + (void) GrPutText(w->w_caption, STYLE_CAPTION, &capp, + GEO_CENTER, GR_TEXT_DEFAULT, FALSE, &capr, + (Rect *) NULL); + } + } + + if ((w->w_flags & WIND_BORDER) != 0) + { + /* right border */ + r = w->w_allArea; + r.r_xbot = w->w_allArea.r_xtop - RIGHT_BORDER(w) + GrPixelCorrect; + r.r_ytop = w->w_allArea.r_ytop - TOP_BORDER(w); + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + + if ((w->w_flags & WIND_SCROLLBARS) == 0) + { + /* windows without scroll bars */ + + /* left border */ + r = w->w_allArea; + r.r_xtop = w->w_allArea.r_xbot + LEFT_BORDER(w) - GrPixelCorrect; + r.r_ytop = w->w_allArea.r_ytop - TOP_BORDER(w); + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + + /* bottom border */ + r = w->w_allArea; + r.r_ytop = w->w_allArea.r_ybot + BOT_BORDER(w) - GrPixelCorrect; + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + } + } + + if ((w->w_flags & WIND_SCROLLBARS) != 0) + { + /* windows with scroll bars */ + + /* left vertical lines */ + r = w->w_allArea; + r.r_ytop = w->w_allArea.r_ytop - TOP_BORDER(w); + r.r_xtop = r.r_xbot + THIN_LINE - GrPixelCorrect; + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + r.r_xbot += WindScrollBarWidth + THIN_LINE; + r.r_xtop = r.r_xbot + THIN_LINE - GrPixelCorrect; + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + + /* bottom horizontal lines */ + r = w->w_allArea; + r.r_ytop = r.r_ybot + THIN_LINE - GrPixelCorrect; + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + r.r_ybot += WindScrollBarWidth + THIN_LINE; + r.r_ytop = r.r_ybot + THIN_LINE - GrPixelCorrect; + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + + /* scroll bars */ + windBarLocations(w, &leftBar, &botBar, &up, &down, &right, &left, &zoom); + GrClipBox(&leftBar, STYLE_CAPTION); + GrClipBox(&botBar, STYLE_CAPTION); + + if (w->w_bbox == NULL) { + TxError("Warning: scroll bars but no w->w_bbox!\n"); + TxError("Report this to a magic implementer.\n"); + goto leave; + }; + + /* left scroll bar */ + bar = MAX(1, leftBar.r_ytop - leftBar.r_ybot + 1); + bbox = MAX(1, w->w_bbox->r_ytop - w->w_bbox->r_ybot + 1); + viewl = w->w_surfaceArea.r_ybot - w->w_bbox->r_ybot + 1; + viewu = w->w_surfaceArea.r_ytop - w->w_bbox->r_ybot + 1; + leftElev.r_xbot = leftBar.r_xbot + 2; + leftElev.r_xtop = leftBar.r_xtop - 3 + GrPixelCorrect; + leftElev.r_ybot = (bar * viewl) / bbox + leftBar.r_ybot; + leftElev.r_ytop = (bar * viewu) / bbox + leftBar.r_ybot; + leftElev.r_ytop = MIN(leftElev.r_ytop, leftBar.r_ytop - 2); + leftElev.r_ybot = MIN(leftElev.r_ybot, leftElev.r_ytop - 3); + leftElev.r_ybot = MAX(leftElev.r_ybot, leftBar.r_ybot + 2); + leftElev.r_ytop = MAX(leftElev.r_ytop, leftElev.r_ybot + 1 + + GrPixelCorrect + GrPixelCorrect); + GrClipBox(&leftElev, STYLE_ELEVATOR); + r.r_xbot = leftBar.r_xbot; + r.r_xtop = leftBar.r_xtop; + r.r_ybot = leftBar.r_ybot - THIN_LINE; + r.r_ytop = leftBar.r_ybot - GrPixelCorrect; + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + r.r_ybot = leftBar.r_ytop + GrPixelCorrect; + r.r_ytop = leftBar.r_ytop + THIN_LINE; + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + + + /* bottom scroll bar */ + bar = MAX(1, botBar.r_xtop - botBar.r_xbot + 1); + bbox = MAX(1, w->w_bbox->r_xtop - w->w_bbox->r_xbot + 1); + viewl = w->w_surfaceArea.r_xbot - w->w_bbox->r_xbot + 1; + viewu = w->w_surfaceArea.r_xtop - w->w_bbox->r_xbot + 1; + botElev.r_ybot = botBar.r_ybot + 2; + botElev.r_ytop = botBar.r_ytop - 3 + GrPixelCorrect; + botElev.r_xbot = (bar * viewl) / bbox + botBar.r_xbot; + botElev.r_xtop = (bar * viewu) / bbox + botBar.r_xbot; + botElev.r_xtop = MIN(botElev.r_xtop, botBar.r_xtop - 2); + botElev.r_xbot = MIN(botElev.r_xbot, botElev.r_xtop - 3); + botElev.r_xbot = MAX(botElev.r_xbot, botBar.r_xbot + 2); + botElev.r_xtop = MAX(botElev.r_xtop, botElev.r_xbot + 1 + + GrPixelCorrect + GrPixelCorrect); + GrClipBox(&botElev, STYLE_ELEVATOR); + r.r_ybot = botBar.r_ybot; + r.r_ytop = botBar.r_ytop; + r.r_xbot = botBar.r_xbot - THIN_LINE; + r.r_xtop = botBar.r_xbot - GrPixelCorrect; + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + r.r_xbot = botBar.r_xtop + GrPixelCorrect; + r.r_xtop = botBar.r_xtop + THIN_LINE; + if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); + + /* icons */ + GrDrawGlyph(windGlyphs->gr_glyph[0], &(up.r_ll)); + GrDrawGlyph(windGlyphs->gr_glyph[1], &(down.r_ll)); + GrDrawGlyph(windGlyphs->gr_glyph[2], &(left.r_ll)); + GrDrawGlyph(windGlyphs->gr_glyph[3], &(right.r_ll)); + GrDrawGlyph(windGlyphs->gr_glyph[4], &(zoom.r_ll)); + } + +leave: + GrUnlock(w); +} + + + +/* + * ---------------------------------------------------------------------------- + * WindCaption -- + * + * Set the caption on the window. + * + * Results: + * None. + * + * Side effects: + * The caption is changed in the data structure and is redisplayed on the + * screen (if any of it is visible). If anything overlaps the caption and + * the caption was redisplayed then the overlap material will be + * redisplayed. + * + * If the new caption is identical to the old then only redisplay is done. + * ---------------------------------------------------------------------------- + */ + +void +WindCaption(w, caption) + MagWindow *w; + char *caption; /* The string that is to be copied into the caption. + * (The string is copied, not just pointed at.) + */ +{ + Rect r; + + if (w->w_caption != caption) + (void) StrDup( &(w->w_caption), caption); + r = w->w_allArea; + r.r_ybot = r.r_ytop - TOP_BORDER(w) + 1; + WindAreaChanged(w, &r); + if (GrUpdateIconPtr)(*GrUpdateIconPtr)(w,w->w_caption); +} + + + +/* + * ---------------------------------------------------------------------------- + * windNewView -- + * + * The window's view has moved -- update the scroll bars. + * + * Results: + * None. + * + * Side effects: + * Records areas for redisplay. + * ---------------------------------------------------------------------------- + */ + +void +windNewView(w) + MagWindow *w; +{ + Rect leftBar, botBar, up, down, right, left, zoom; + + if ((w->w_flags & WIND_SCROLLBARS) != 0) + { + windBarLocations(w, &leftBar, &botBar, &up, &down, &right, &left, &zoom); + WindAreaChanged(w, &leftBar); + WindAreaChanged(w, &botBar); + } +} + + +/* + * ---------------------------------------------------------------------------- + * WindRedisplay -- + * + * Redisplay the entire window, including the border areas. + * Called without any window locks. + * + * Results: + * None. + * + * Side effects: + * Areas of the screen will be redrawn. + * ---------------------------------------------------------------------------- + */ + +void +WindRedisplay(w) + MagWindow *w; +{ + WindAreaChanged(w, &(w->w_allArea)); +} + +/* + * ---------------------------------------------------------------------------- + * windRedrawIcon -- + * + * Redraw a windows icon. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windRedrawIcon(w) + MagWindow *w; +{ + Point p; + clientRec *cl; + char *name; + + /* Prepare for graphics. */ + cl = (clientRec *) w->w_client; + GrLock(w, FALSE); + + GrClipBox(&w->w_allArea, STYLE_ERASEALL); + if (cl->w_icon != NULL) { + /* Draw the glyph */ + GrDrawGlyph(cl->w_icon, &(w->w_allArea.r_ll)); + } + + /* Now label the icon */ + if (w->w_iconname != NULL) + name = w->w_iconname; + else + name = cl->w_clientName; + p.p_y = w->w_allArea.r_ybot; + p.p_x = (w->w_allArea.r_xbot + w->w_allArea.r_xtop) / 2; + GrPutText(name, STYLE_BORDER, &p, GEO_NORTH, GR_TEXT_SMALL, TRUE, + &w->w_allArea, (Rect *) NULL); + + /* We are done */ + w->w_flags &= ~WIND_REDRAWICON; + GrUnlock(w); +} + + +/* + * ---------------------------------------------------------------------------- + * WindUpdate -- + * + * Update the screen areas that were previously passed to WindAreaChanged. + * Calls clients without any window locks. + * + * Results: + * None. + * + * Side effects: + * Clients will be called to update portions of the screen. + * ---------------------------------------------------------------------------- + */ + +bool WindAnotherUpdatePlease; + +void +WindUpdate() +{ + clientRec *cr; + MagWindow *w; + TileTypeBitMask windTileMask; + extern int windUpdateFunc(); /* Forward declaration. */ + extern int windBackgroundFunc(); /* Forward declaration. */ + Rect r; + + WindAnotherUpdatePlease = FALSE; + + /* First, if there was a SigWinch (as on a Sun160), then call the + * graphics module so that it can record additional areas to be + * redisplayed. + */ + if (SigGotSigWinch) { + SigGotSigWinch = FALSE; + if (GrDamagedPtr != NULL) (*GrDamagedPtr)(); + } + +#ifdef MAGIC_WRAPPER + /* Honor the display redraw suspension state */ + if (GrDisplayStatus == DISPLAY_SUSPEND) return; + GrDisplayStatus = DISPLAY_IN_PROGRESS; + SigSetTimer(0); +#endif + + TTMaskSetOnlyType(&windTileMask, TT_ERROR_P); + + /* Make a scan through each of the windows, in order from top + * down. For each window, redisplay the areas of that window + * that have changed, then erase the area of that window from + * the redisplay plane. Since our window areas INCLUDE their + * border pixels on both sides, expand the area on the top and + * right sides before erasing. Without this expansion, and + * corresponding hacks in WindAreaChanged and windBackgroundFunc, + * slivers will accidentally be left undisplayed. + */ + + UndoDisable(); + for (w = windTopWindow; w != NULL; w = w->w_nextWindow) + { + if (w->w_flags & WIND_ISICONIC) { + if (w->w_flags & WIND_REDRAWICON) windRedrawIcon(w); + } else { + if (w->w_redrawAreas == (ClientData)NULL) + windCurRedrawPlane = windRedisplayArea; + else + windCurRedrawPlane = (Plane *) w->w_redrawAreas; + + (void) DBSrPaintArea((Tile *) NULL, + windCurRedrawPlane, &w->w_allArea, &windTileMask, + windUpdateFunc, (ClientData) w); + + if (windCurRedrawPlane == windRedisplayArea) { + /* Erase this window from our list, since we have redrawn it. + */ + r = w->w_allArea; + r.r_xtop += 1; + r.r_ytop += 1; + DBPaintPlane(windRedisplayArea, &r, + DBStdEraseTbl(TT_ERROR_P, PL_DRC_ERROR), + (PaintUndoInfo *) NULL); + } else { + /* We are finished with this window's redisplay plane. Clear + * any remaining redisplay tiles, as we may have interrupted + * the redislay and don't want this stuff any more. + */ + DBClearPaintPlane(windCurRedrawPlane); + } + } + } + + if (WindPackageType == WIND_MAGIC_WINDOWS) + { + /* For any tiles left that intersect the screen, draw the background + * color (there are no windows over these tiles). + */ + (void) DBSrPaintArea((Tile *) NULL, + windRedisplayArea, &GrScreenRect, &windTileMask, + windBackgroundFunc, (ClientData) NULL); + + /* Clear any remaining redisplay tiles, as we may have interrupted + * the redislay and don't want this stuff any more. + */ + DBClearPaintPlane(windRedisplayArea); + }; + + UndoEnable(); + + /* Now give the clients a chance to update anything that they wish */ + for (cr = windFirstClientRec; cr != (clientRec *) NULL; + cr = cr->w_nextClient) + { + if (cr->w_update != NULL) + (*(cr->w_update)) (); + } + GrFlush(); + +#ifdef MAGIC_WRAPPER + SigRemoveTimer(); + GrDisplayStatus = DISPLAY_IDLE; +#endif + + /* See comment in windows.h */ + if (WindAnotherUpdatePlease) WindUpdate(); +} + +/* + * ---------------------------------------------------------------------------- + * + * windUpdateFunc -- + * + * This procedure is invoked during WindUpdate for each tile that + * intersects a particular window. If the tile type is TT_ERROR_P + * then the intersection between the tile and the window is + * redisplayed. + * + * Results: + * Always returns 0 to keep the search from aborting. + * + * Side effects: + * Information is redisplayed on the screen. + * + * ---------------------------------------------------------------------------- + */ + +int +windUpdateFunc(tile, w) + Tile *tile; /* Tile in the redisplay plane. */ + MagWindow *w; /* Window we're currently interested in. */ +{ + Rect area; + + /* If this is a space tile, there's nothing to do. */ + + if (TiGetType(tile) == TT_SPACE) return 0; + + TiToRect(tile, &area); + GeoClip(&area, &w->w_allArea); + GeoClip(&area, &GrScreenRect); + if ((area.r_xbot > area.r_xtop) || (area.r_ybot > area.r_ytop)) + /* nothing to display */ + return 0; + + /* Skip the border stuff if it isn't going to change. This + * test has to be especially tricky because of the decision + * that pixel at (0,0) extends from (0,0) up to but not including + * (1,1). + */ + + if (!((w->w_screenArea.r_xbot <= area.r_xbot) + && (w->w_screenArea.r_xtop+1 >= area.r_xtop) + && (w->w_screenArea.r_ybot <= area.r_ybot) + && (w->w_screenArea.r_ytop+1 >= area.r_ytop))) { + /* Redisplay the border areas. */ + WindDrawBorder(w, &area); + }; + + /* Now call the client to redisplay the interior of the window. */ + if (GEO_TOUCH(&(w->w_screenArea), &area)) + { + Rect clientArea; + + WindScreenToSurface(w, &area, &clientArea); + GeoClip(&area, &w->w_screenArea); + if ( ((clientRec *) (w->w_client))->w_redisplay != NULL) + { + (*(( (clientRec *) (w->w_client))->w_redisplay)) + (w, &clientArea, &area); + } + } + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * windBackgroundFunc -- + * + * Called for each tile left after redisplaying all of the windows. + * This procedure just draws the background colors in any remaining + * areas that have changed. + * + * Results: + * Always returns 0 to keep the search from aborting. + * + * Side effects: + * The background color gets drawn on the screen. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +windBackgroundFunc(tile, notUsed) + Tile *tile; + ClientData notUsed; +{ + Rect area; + + if (TiGetType(tile) == (TileType) TT_SPACE) return 0; + TiToRect(tile, &area); + + /* Since windows include their border pixels, we have to be + * a bit careful. If the upper or right edge of the area isn't + * the edge of the screen, it is a window. In that case, decrement + * the coordinate so we don't overwrite the edge of the window. + */ + + if (area.r_xtop < GrScreenRect.r_xtop) area.r_xtop -= 1; + if (area.r_ytop < GrScreenRect.r_ytop) area.r_ytop -= 1; + GrLock(GR_LOCK_SCREEN, FALSE); + GrClipBox(&area, STYLE_BACKGROUND); + GrUnlock(GR_LOCK_SCREEN); + return 0; +} diff --git a/windows/windInt.h b/windows/windInt.h new file mode 100644 index 00000000..f9e5b018 --- /dev/null +++ b/windows/windInt.h @@ -0,0 +1,86 @@ +/* + * windInt.h -- + * + * Internal definitions for the window package. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/windows/windInt.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + */ + +#ifndef _WINDINT_H +#define _WINDINT_H + +#include "windows/windows.h" +#include "graphics/glyphs.h" + +/* ----------------- data structures ----------------- */ +typedef struct WIND_S3 { + char *w_clientName; + bool (*w_create)(); + bool (*w_delete)(); + void (*w_redisplay)(); + void (*w_command)(); + void (*w_update)(); + bool (*w_exit)(); + void (*w_reposition)(); /* called when a window moves or changes size */ + GrGlyph *w_icon; + char **w_commandTable; + void (**w_functionTable)(); + struct WIND_S3 *w_nextClient; +} clientRec; + +/* ----------------- variables ----------------- */ +extern MagWindow *windTopWindow; +extern MagWindow *windBottomWindow; +extern clientRec *windFirstClientRec; +extern char *butTable[]; +extern char *actTable[]; +extern bool windPrintCommands; + +/* ----------------- procedures ----------------- */ +extern void windDisplayArea(); +extern void windPrintCommand(); +extern void windSetPoint(); +extern void windDump(); +extern void windClientInit(); +extern MagWindow *windSearchPoint(); + +/* ----------------- constants ----------------- */ + +/* the width of window borders */ +extern int windCaptionPixels; +#define THIN_LINE (((w)->w_flags & WIND_BORDER) ? 2 : 0) +#define TOP_BORDER(w) (((w)->w_flags & WIND_CAPTION) \ + ? windCaptionPixels : 2*THIN_LINE) +#define BOT_BORDER(w) (((w)->w_flags & WIND_SCROLLBARS) \ + ? 2*THIN_LINE + WindScrollBarWidth : 2*THIN_LINE) +#define LEFT_BORDER(w) (((w)->w_flags & WIND_SCROLLBARS) \ + ? 2*THIN_LINE + WindScrollBarWidth : 2*THIN_LINE) +#define RIGHT_BORDER(w) 2*THIN_LINE + +/* Always leave room for the borders plus 25 pixels */ +#define WIND_MIN_WIDTH (6*THIN_LINE + 3*WindScrollBarWidth + 25) +#define WIND_MIN_HEIGHT (windCaptionPixels + 4*THIN_LINE + \ + 3*WindScrollBarWidth + 25) + +#define DEFAULT_CLIENT "layout" +#define WINDOW_CLIENT "*window" + +/* Default size for new windows. */ + +#define CREATE_HEIGHT 300 +#define CREATE_WIDTH 300 + +#endif /* _WINDINT_H */ diff --git a/windows/windMain.c b/windows/windMain.c new file mode 100644 index 00000000..ca9adb93 --- /dev/null +++ b/windows/windMain.c @@ -0,0 +1,574 @@ +/* windMain.c - + * + * This package implements overlapping windows for the + * Magic VLSI layout system. + * + * Design: + * Windows are structures that are kept in a doubly linked list. + * Windows near the front of the list are on top of windows further + * towards the tail of the list. Each window has some information + * about what is in the window, as well as the size of the window + * (both unclipped and clipped to accommodate windows that overlay it). + * Transforms control what portion of the window's contents show up + * on the screen, and at what magnification. + * + * Each window is owned by a client (the database, a menu package, etc.). + * The window package is notified of a new client by the AddClient + * call. The client supplies routines to redisplay the contents of + * a window, and to do other things with the window (such as delete it). + * Each window is a view onto a surface maintained by the client. The + * client may be asked to redisplay any part of this surface at any time. + * The client must also supply each window with an ID that uniquely + * identifies the surface. + * + * There are currently two types of window packages supported: Magic + * windows (implemented here) and Sun Windows. In Magic windows, all + * windows use the screen's coordinate system. In Sun Windows, each + * window has it's own coordinate system with (0, 0) being at the lower + * left corner. Also, under Sun Windows some of the screen managment + * stuff (such as clipping to obscuring areas and drawing of the + * screen background color) is ignored by us. + * + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windMain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "graphics/glyphs.h" +#include "windows/windows.h" +#include "windows/windInt.h" +#include "utils/stack.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "textio/textio.h" +#include "graphics/graphics.h" +#include "utils/malloc.h" +#include "utils/utils.h" +#include "textio/txcommands.h" + +/* The type of windows that this package will implement */ +int WindPackageType = WIND_MAGIC_WINDOWS; + +/* The size of our scroll bars -- may be set externally (see windows.h) + */ +int WindScrollBarWidth = 7; + +/* ------ Internal variables that are global within the window package ----- */ +clientRec *windFirstClientRec = NULL; /* the head of the linked list + * of clients + */ +MagWindow *windTopWindow = NULL; /* the topmost window */ +MagWindow *windBottomWindow = NULL; /* ...and the bottom window */ +extern Plane *windRedisplayArea; /* See windDisplay.c for details. */ + + +/* + * ---------------------------------------------------------------------------- + * WindInit -- + * + * Initialize the window package. No windows are created, but the + * package will be initialized so that it can do these things in the + * future. + * + * Results: + * None. + * + * Side effects: + * Variables internal to the window package are initialized. + * ---------------------------------------------------------------------------- + */ + +void +WindInit() +{ + extern Stack *windGrabberStack; + Rect ts; + char glyphName[30]; + + windClientInit(); + windGrabberStack = StackNew(2); + windRedisplayArea = DBNewPlane((ClientData) TT_SPACE); + + sprintf(glyphName, "windows%d", WindScrollBarWidth); + if (!GrReadGlyphs(glyphName, ".", SysLibPath, &windGlyphs)) + MainExit(1); + GrTextSize("XWyqP", GR_TEXT_DEFAULT, &ts); + windCaptionPixels = ts.r_ytop - ts.r_ybot + 3; + WindAreaChanged((MagWindow *) NULL, (Rect *) NULL); +} + + +/* + * ---------------------------------------------------------------------------- + * WindAddClient -- + * + * Add a new client of the window package. The client must supply a + * set of routines, as described below. + * + * Results: + * A unique ID (of type WindClient) is returned. + * This is used to identify the client in future calls to the window + * package. + * + * Routines supplied: + * + * ( A new window was just created for this client. Do things to + * initialize the window, such as filling in the caption and making + * the contents be empty. The client may refuse to create a new + * window by returning FALSE, otherwise the client should return + * TRUE. The client will get passed argc and argv, with the command + * name stripped off. The client may do whatever it wants with this. + * It may even modify parts of the window record -- such as changing + * the window's location on the screen.) + * + * bool + * create(w, argc, argv) + * MagWindow *w; + * int argc; + * char *argv[]; + * { + * } + * + * ( One of the client's windows is about to be deleted. Do whatever + * needs to be done, such as freeing up dynamically allocated data + * structures. Fields manipulated by the window package, such as + * the caption, should not be freed by the client. The client should + * normally return TRUE. If the client returns FALSE, the window + * manager will refuse the request to delete the window.) + * + * bool + * delete(w) + * MagWindow *w; + * { + * } + * + * ( Redisplay an area of the screen. The client is passed the window, + * the area in his coordinate system, and a clipping rectangle in + * screen coordinates. ) + * + * redisplay(w, clientArea, screenArea) + * MagWindow *w; + * Rect *clientArea, *screenArea; + * { + * } + * + * + * ( The window is about to be moved or resized. This procedure will + * be called twice. + * + * The first time (with 'final' == FALSE), the window + * will be passed in 'w' as it is now and a suggested new w_screenarea + * is passed in 'newpos'. The client is free to modify 'newpos' to + * be whatever screen location it desires. The routine should not + * pass 'w' to any window procedure such as windMove since 'w' has + * the old transform, etc. instead of the new one. + * + * On the second call ('final' == TRUE), the window 'w' has all of + * it's fields updated, newpos is equal to w->w_frameArea, and the + * client is free to do things like windMove which require a window + * as an argument. It should not modify newpos. + * + * reposition(w, newpos, final) + * MagWindow *w; + * Rect *newpos -- new w_framearea (screen area of window) + * bool final; + * { + * } + * + * + * ( A command has been issued to this window. The client should + * process it. It is split into Unix-style argc and argv words. ) + * + * command(w, client, cmd) + * MagWindow *w; + * TxCommand *cmd; + * { + * } + * + * ( A command has just finished. Update any screen info that may have + * been changed as a result. ) + * + * update() + * { + * } + * + * Side effects: + * Internal tables are expanded to include the new client. + * ---------------------------------------------------------------------------- + */ + +WindClient +WindAddClient(clientName, create, delete, redisplay, command, update, + exitproc, reposition, icon) + char *clientName; /* A textual name for the client. This + * name will be visable in the user + * interface as the name to use to switch + * a window over to a new client + */ + bool (*create)(); + bool (*delete)(); + void (*redisplay)(); + void (*command)(); + void (*update)(); + bool (*exitproc)(); + void (*reposition)(); + GrGlyph *icon; /* An icon to draw when the window is closed. + * (currently for Sun Windows only). + */ +{ + clientRec *res; + + ASSERT( (clientName != NULL), "WindAddClient"); + ASSERT( (command != NULL), "WindAddClient"); + + res = (clientRec *) mallocMagic(sizeof(clientRec)); + res->w_clientName = clientName; + res->w_create = create; + res->w_delete = delete; + res->w_redisplay = redisplay; + res->w_command = command; + res->w_update = update; + res->w_exit = exitproc; + res->w_reposition = reposition; + res->w_icon = icon; + res->w_nextClient = windFirstClientRec; + + /* The command and function tables are dynamically allocated. */ + /* Commands and functions should be registered with the client */ + /* using the WindAddCommand() function. */ + + res->w_commandTable = (char **)mallocMagic(sizeof(char *)); + *(res->w_commandTable) = NULL; + res->w_functionTable = (void (**)())mallocMagic(sizeof(void (*)())); + *(res->w_functionTable) = NULL; + + windFirstClientRec = res; + + return (WindClient) res; +} + + +/* + * ---------------------------------------------------------------------------- + * WindGetClient -- + * + * Looks up the unique ID of a client of the window package. + * + * Results: + * A variable of type WindClient is returned if the client was found, + * otherwise NULL is returned. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +WindClient +WindGetClient(clientName, exact) + char *clientName; /* the textual name of the client */ + bool exact; /* must the name be exact, or are abbreviations allowed */ +{ + clientRec *cr, *found; + int length; + + /* Accept only an exact match */ + + if (exact) + { + for (cr = windFirstClientRec; cr != (clientRec *) NULL; + cr = cr->w_nextClient) + if (!strcmp(clientName, cr->w_clientName)) + return (WindClient)cr; + return (WindClient) NULL; + } + + /* Accept any unique abbreviation */ + + found = NULL; + length = strlen(clientName); + for (cr = windFirstClientRec; cr != (clientRec *) NULL; + cr = cr->w_nextClient) + { + if (!strncmp(clientName, cr->w_clientName, length)) + { + if (found != NULL) return (WindClient) NULL; + found = cr; + } + } + + return (WindClient) found; +} + +/* + * ---------------------------------------------------------------------------- + * WindNextClient -- + * + * Return the w_nextClient record to the caller as a WindClient + * variable. If "client" is 0, pass the first client record. + * This allows the calling routine to enumerate all the known + * clients. + * + * Results: + * Type WindClient is returned. If the end of the list is + * reached, (WindClient)NULL (0) is returned. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +WindClient +WindNextClient(client) + WindClient client; +{ + clientRec *cr = (clientRec *)client; + int length; + + if (cr == NULL) + return (WindClient)windFirstClientRec; + else + return (WindClient)(cr->w_nextClient); +} + +/* + * ---------------------------------------------------------------------------- + * WindPrintClientList -- + * + * Print the name of each client of the window package. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +WindPrintClientList(wizard) + bool wizard; /* If true print the names of ALL clients, even those + * that don't have user-visable windows */ +{ + clientRec *cr; + + for (cr = windFirstClientRec; cr != (clientRec *) NULL; + cr = cr->w_nextClient) { + if (wizard || (cr->w_clientName[0] != '*')) + TxError(" %s\n", cr->w_clientName); + } +} + +/* + * ---------------------------------------------------------------------------- + * WindExecute -- + * + * Execute the command associated with a windClient + * + * Results: + * Returns the command index on success. Returns -1 if the + * command was not found in the client's command list. Returns + * -2 if the procedure was sent an empty command. + * + * Side effects: + * Whatever is done by the command execution. + * + * ---------------------------------------------------------------------------- + */ + +int +WindExecute(w, rc, cmd) + MagWindow *w; + WindClient rc; + TxCommand *cmd; +{ + int cmdNum; + clientRec *client = (clientRec *) rc; + char **commandTable = client->w_commandTable; + void (**functionTable)() = client->w_functionTable; + + if (cmd->tx_argc > 0) + { + cmdNum = Lookup(cmd->tx_argv[0], commandTable); + + if (cmdNum >= 0) + { + (*functionTable[cmdNum])(w, cmd); + return cmdNum; + } + return -1; + } + return -2; +} + +/* + * ---------------------------------------------------------------------------- + * WindAddCommand -- + * + * Add a command to the indicated client. The command is passed + * in "text", which also contains the (1-line) help text for the + * command. "func" is a function pointer, and "volatile" is TRUE + * if the command "text" is dynamically allocated and must be + * copied before adding to the client. + * + * Results: + * None + * + * Side effects: + * The memory allocated to the command and function pointers may + * be reallocated and the entries in the client record updated. + * + * ---------------------------------------------------------------------------- + */ + +void +WindAddCommand(rc, text, func, dynamic) + WindClient rc; + char *text; + void (*func)(); + bool dynamic; +{ + int cidx, numCommands = 0; + clientRec *client = (clientRec *) rc; + char **commandTable = client->w_commandTable; + void (**functionTable)() = client->w_functionTable; + char **newcmdTable; + void (**newfnTable)(); + + /* Find the number of commands and functions, increment by one, and */ + /* Allocate a new array of pointers. */ + + while (commandTable[numCommands] != NULL) numCommands++; + numCommands++; + + newcmdTable = (char **)mallocMagic((numCommands + 1) * sizeof(char *)); + newfnTable = (void (**)())mallocMagic((numCommands + 1) * sizeof(void (*)())); + + /* Copy the old values, inserting the new command in alphabetical */ + /* order. */ + + for (cidx = 0; (commandTable[cidx] != NULL) && + (strcmp(commandTable[cidx], text) < 0); cidx++) + { + newcmdTable[cidx] = commandTable[cidx]; + newfnTable[cidx] = functionTable[cidx]; + } + + if (dynamic) + newcmdTable[cidx] = StrDup(NULL, text); + else + newcmdTable[cidx] = text; + newfnTable[cidx] = func; + + for (; commandTable[cidx] != NULL; cidx++) + { + newcmdTable[cidx + 1] = commandTable[cidx]; + newfnTable[cidx + 1] = functionTable[cidx]; + } + + newcmdTable[cidx + 1] = NULL; + + /* Release memory for the original pointers, and replace the */ + /* pointers in the client record. */ + + freeMagic(commandTable); + freeMagic(functionTable); + + client->w_commandTable = newcmdTable; + client->w_functionTable = newfnTable; +} + +/* + * ---------------------------------------------------------------------------- + * WindReplaceCommand -- + * + * Change the function for the indicated command. This routine + * is mainly used by the Tcl module interface, where commands + * are registered with the command interpreter pointing to an + * "auto" function which loads the module, then calls this routine + * to replace the auto-load function with the real one. + * + * Note that this routine matches to the length of "command", then + * checks one character beyond in the command table to ensure that + * we don't inadvertently change a command which happens to be a + * substring of the intended command. In cases where this is + * intended (e.g., "ext" and "extract"), the routine must be called + * separately for each command string. + * + * Results: + * 0 on success, -1 if the command was not found. + * + * Side effects: + * The clientRec structure for the DBWind interface is altered. + * + * ---------------------------------------------------------------------------- + */ + +int +WindReplaceCommand(rc, command, newfunc) + WindClient rc; + char *command; + void (*newfunc)(); +{ + int cidx, clen; + clientRec *client = (clientRec *) rc; + char **commandTable = client->w_commandTable; + void (**functionTable)() = client->w_functionTable; + + clen = strlen(command); + + for (cidx = 0; commandTable[cidx] != NULL; cidx++) + if (!strncmp(commandTable[cidx], command, clen)) + if (!isalnum(*(commandTable[cidx] + clen))) + { + functionTable[cidx] = newfunc; + return 0; + } + + return -1; +} + +/* + * ---------------------------------------------------------------------------- + * WindGetCommandTable -- + * + * For functions wishing to parse the command table of a client + * directly, this routine returns a pointer to the top of the + * table. The only purpose of this routine is to export the + * w_commandTable value inside the clientRec structure, which is + * not itself exported. + * + * Results: + * A pointer to the top of the command table of the indicated + * client. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +char ** +WindGetCommandTable(rc) + WindClient rc; +{ + clientRec *client = (clientRec *) rc; + return client->w_commandTable; +} diff --git a/windows/windMove.c b/windows/windMove.c new file mode 100644 index 00000000..063a64f7 --- /dev/null +++ b/windows/windMove.c @@ -0,0 +1,855 @@ +/* windMove.c - + * + * This file contains the functions which move windows around on + * the screen. It does not contain the functions that change the + * contents of the windows. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windMove.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/graphics.h" +#include "graphics/glyphs.h" +#include "windows/windInt.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/malloc.h" + +/* The following own variable is used to pass information between + * WindReframe and windFindUnobscured. + */ + +static MagWindow *sharedW; + +/* + * By default, new windows have scroll bars, border, a title caption, + * and allow standard window commands. + */ +int WindDefaultFlags = WIND_SCROLLBARS | WIND_CAPTION | + WIND_BORDER | WIND_COMMANDS | + WIND_SCROLLABLE; + +/* + * A mask of the current window IDs, as well as a limit on the number of + * windows we can create. + */ + +int windWindowMask = 0; /* One bit per window ID */ +int windMaxWindows = 32; /* May be decreased via the WIND_MAX_WINDOWS() macro */ +int windCurNumWindows = 0; + + +/* + * ---------------------------------------------------------------------------- + * windUnlink -- + * + * Unlink a window from the doubly linked list of windows. + * + * Results: + * None. + * + * Side effects: + * The window is unlinked. + * ---------------------------------------------------------------------------- + */ + +void +windUnlink(w) + MagWindow *w; +{ + ASSERT(w != (MagWindow *) NULL, "windUnlink"); + ASSERT(windTopWindow != (MagWindow *) NULL, "windUnlink"); + ASSERT(windBottomWindow != (MagWindow *) NULL, "windUnlink"); + ASSERT(windTopWindow->w_prevWindow == (MagWindow *) NULL, "windUnlink"); + ASSERT(windBottomWindow->w_nextWindow == (MagWindow *) NULL, "windUnlink"); + + if ( (windTopWindow == w) || (windBottomWindow == w) ) + { + if (windTopWindow == w) + { + windTopWindow = w->w_nextWindow; + if (windTopWindow != (MagWindow *) NULL) + windTopWindow->w_prevWindow = (MagWindow *) NULL; + } + if (windBottomWindow == w) + { + windBottomWindow = w->w_prevWindow; + if (windBottomWindow != (MagWindow *) NULL) + windBottomWindow->w_nextWindow = (MagWindow *) NULL; + } + } + else + { + w->w_nextWindow->w_prevWindow = w->w_prevWindow; + w->w_prevWindow->w_nextWindow = w->w_nextWindow; + } + + w->w_nextWindow = (MagWindow *) NULL; + w->w_prevWindow = (MagWindow *) NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * windFree -- + * + * This local procedure does the dirty work of freeing up + * memory in a window. + * + * Results: + * None. + * + * Side effects: + * All storage associated with w is returned to the free pool. + * + * ---------------------------------------------------------------------------- + */ + +void +windFree(w) + MagWindow *w; +{ + windWindowMask &= ~(1 << w->w_wid); + windCurNumWindows--; + if (w->w_caption != (char *) NULL) freeMagic(w->w_caption); + if (w->w_iconname != (char *) NULL) freeMagic(w->w_iconname); + if (GrFreeBackingStorePtr != NULL) (*GrFreeBackingStorePtr)(w); + if (w->w_redrawAreas != (ClientData) NULL) { + DBFreePaintPlane( (Plane *) w->w_redrawAreas); + TiFreePlane( (Plane *) w->w_redrawAreas); + } + freeMagic( (char *) w); +} + +/* + * ---------------------------------------------------------------------------- + * WindSetWindowAreas -- + * + * Given the location of the window on the screen, compute w->w_allArea + * and w->w_screenArea in the window's own coordinate system. + * + * Results: + * None. + * + * Side effects: + * Modifies w->w_allArea and w->w_screenArea. + * ---------------------------------------------------------------------------- + */ + +void +WindSetWindowAreas(w) + MagWindow *w; +{ + switch ( WindPackageType ) + { + case WIND_X_WINDOWS: + /* Windows have origin at lower-left corner */ + w->w_allArea.r_xbot = w->w_allArea.r_ybot = 0; + w->w_allArea.r_xtop = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; + w->w_allArea.r_ytop = w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; + break; + + default: + /* Windows are all in the same coordinate system */ + w->w_allArea = w->w_frameArea; + } + WindOutToIn(w, &w->w_allArea, &w->w_screenArea); +} + + +/* + * ---------------------------------------------------------------------------- + * windSetWindowPosition -- + * + * (deprecated function) + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windSetWindowPosition(w) + MagWindow *w; +{ +} + +/* + * ---------------------------------------------------------------------------- + * WindDelete -- + * + * Delete a window. + * + * Results: + * TRUE if the window was deleted, FALSE otherwise. + * + * Side effects: + * The window disappears from the sreen. The window's client is notified + * that this is about to happen, and it may refuse to let it happen. + * ---------------------------------------------------------------------------- + */ + +bool +WindDelete(w) + MagWindow *w; +{ + clientRec *cr; + + ASSERT(w != (MagWindow *) NULL, "WindDelete"); + + cr = (clientRec *) w->w_client; + if ( (cr->w_delete == NULL) || (*(cr->w_delete))(w) ) + { + WindAreaChanged(w, &(w->w_allArea) ); + if (GrDeleteWindowPtr != NULL) (*GrDeleteWindowPtr)(w); + windUnlink(w); + windReClip(); + windFree(w); + return TRUE; + } + else + return FALSE; +} + + +/* + * ---------------------------------------------------------------------------- + * WindCreate -- + * + * Create a new window for the specified client. + * + * Results: + * A pointer to the new window, or NULL if one couldn't be created. + * + * Side effects: + * An empty window is created, and it is displayed. + * The new window is place on top of all the other + * windows. + * ---------------------------------------------------------------------------- + */ + +MagWindow * +WindCreate(client, frameArea, isHint, argc, argv) + WindClient client; /* The client that will control this window */ + Rect *frameArea; /* The area that the window is to occupy */ + bool isHint; /* TRUE if the above rectangle is only a + * hint and it is OK for a window package to + * override it to maintain a consistent + * user interface. + */ + int argc; /* Passed to the client */ + char *argv[]; +{ + MagWindow *w; + clientRec *cr; + bool OK; + int id; + + if (windCurNumWindows + 1 > windMaxWindows) { + TxError("Can't have more than %d windows.\n", windMaxWindows); + return NULL; + } + windCurNumWindows++; + + cr = (clientRec *) client; + + /* initialize the window */ + w = (MagWindow *) mallocMagic( sizeof(MagWindow) ); + w->w_client = client; + w->w_flags = WindDefaultFlags; + w->w_clipAgainst = (LinkedRect *) NULL; + w->w_caption = (char *) NULL; + w->w_stippleOrigin.p_x = 0; + w->w_stippleOrigin.p_y = 0; + w->w_bbox = NULL; + w->w_grdata = (ClientData) NULL; + w->w_backingStore = (ClientData)NULL; + w->w_redrawAreas = (ClientData) NULL; + w->w_iconname = NULL; + for (id = 0; ((1 << id) & windWindowMask) != 0; id++) /* advance id */ ; + windWindowMask |= (1 << id); + w->w_wid = id; + + /* locate window on the screen */ + if (frameArea == (Rect *) NULL) + { + switch ( WindPackageType ) + { + case WIND_X_WINDOWS: + /* + * Create default size window in upper left corner + * of screen. + */ + w->w_frameArea.r_xbot = GrScreenRect.r_xbot; + w->w_frameArea.r_ytop = GrScreenRect.r_ytop; + w->w_frameArea.r_xtop = + (GrScreenRect.r_xtop - GrScreenRect.r_xbot) / 2; + w->w_frameArea.r_ybot = + (GrScreenRect.r_ytop - GrScreenRect.r_ybot) / 2; + break; + + default: + w->w_frameArea = GrScreenRect; + } + } + else + w->w_frameArea = *frameArea; + + WindSetWindowAreas(w); + + /* now link the window in on top */ + w->w_nextWindow = windTopWindow; + w->w_prevWindow = (MagWindow *) NULL; + if (windTopWindow == (MagWindow *) NULL) + windBottomWindow = w; + else + windTopWindow->w_prevWindow = w; + windTopWindow = w; + + /* notify the client */ + OK = ((cr->w_create == NULL) || (*(cr->w_create))(w, argc, argv)); + +#ifdef THREE_D + if (strcmp(cr->w_clientName, "wind3d")) +#endif + + if (OK && (GrCreateWindowPtr != NULL)) + OK = (*GrCreateWindowPtr)(w, (argc > 1) ? argv[1] : NULL); + + if (OK) + { + WindSetWindowAreas(w); + windSetWindowPosition(w); + WindAreaChanged(w, &(w->w_allArea)); + } + else + { + /* the client refused the new window */ + windUnlink(w); + windFree(w); + w = (MagWindow *) NULL; + } + windReClip(); + if ((GrCreateBackingStorePtr != NULL) && (w != NULL) && + (!(w->w_flags & WIND_OBSCURED))) + (*GrCreateBackingStorePtr)(w); + + return w; +} + +/* + * ---------------------------------------------------------------------------- + * + * WindOutToIn and WindInToOut -- + * + * The two procedures on this page translate from window inside + * area (the area used to display the surface) to window + * outside area (the total area of the window including caption), + * and vice versa. + * + * Results: + * None. + * + * Side effects: + * Each procedure modifies its third parameter. WindOutToIn + * fills in the third parameter with the inside area of the + * window whose outside area is out, and WindInToOut does the + * opposite. + * + * ---------------------------------------------------------------------------- + */ + +void +WindOutToIn(w, out, in) + MagWindow *w; /* Window under consideration */ + Rect *out; /* Pointer to rectangle of outside area of + * a window. + */ + Rect *in; /* Pointer to rectangle to be filled in with + * inside area corresponding to out. + */ +{ + *in = *out; + in->r_xbot += LEFT_BORDER(w); + in->r_xtop -= RIGHT_BORDER(w); + in->r_ybot += BOT_BORDER(w); + in->r_ytop -= TOP_BORDER(w); +} + +void WindInToOut(w, in, out) + MagWindow *w; /* Window under consideration */ + Rect *in; /* Pointer to rectangle of outside area of + * a window. + */ + Rect *out; /* Pointer to rectangle to be filled in with + * inside area corresponding to out. + */ +{ + *out = *in; + out->r_xbot -= LEFT_BORDER(w); + out->r_xtop += RIGHT_BORDER(w); + out->r_ybot -= BOT_BORDER(w); + out->r_ytop += TOP_BORDER(w); +} + + +/* + * ---------------------------------------------------------------------------- + * WindUnder -- + * + * Move a window underneath the rest. + * + * Results: + * None. + * + * Side effects: + * The window is moved so that it is underneath the rest. This will + * cause portions of uncovered windows to be redisplayed. + * ---------------------------------------------------------------------------- + */ + +void +WindUnder(w) + MagWindow *w; /* the window to be moved */ +{ + Rect area; + MagWindow *w2; + + switch ( WindPackageType ) + { + case WIND_X_WINDOWS: + if ( GrUnderWindowPtr ) + (*GrUnderWindowPtr)(w); + break; + default: + /* Mark for redisplay all the areas that this window + * currently obscures. + */ + + for (w2 = w->w_nextWindow; w2 != NULL; w2 = w2->w_nextWindow) + { + area = w2->w_allArea; + GeoClip(&area, &w->w_allArea); + if ((area.r_xbot <= area.r_xtop) && (area.r_ybot <= area.r_ytop)) + WindAreaChanged(w, &area); + } + + /* take the window out of the linked list */ + windUnlink(w); + + /* now link it back in at the bottom */ + w->w_prevWindow = windBottomWindow; + if (windBottomWindow != (MagWindow *) NULL) + windBottomWindow->w_nextWindow = w; + else + windTopWindow = w; + windBottomWindow = w; + + windReClip(); + } +} + + +/* + * ---------------------------------------------------------------------------- + * WindOver -- + * + * Move a window so that it is over (on top of) the other windows. + * + * Results: + * None. + * + * Side effects: + * The window is moved to the top. This may obscure some other windows. + * The window that is moved will be redisplayed. + * ---------------------------------------------------------------------------- + */ + +void +WindOver(w) + MagWindow *w; /* the window to be moved */ +{ + LinkedRect *r; + Rect area; + + switch ( WindPackageType ) + { + case WIND_X_WINDOWS: + if ( GrOverWindowPtr ) + (*GrOverWindowPtr)(w); + break; + + default: + /* Mark for redisplay all of the areas of the screen that + * currently obscure this window. + */ + + for (r = w->w_clipAgainst; r != NULL; r = r->r_next) + { + area = r->r_r; + GeoClip(&area, &w->w_frameArea); + if ((area.r_xbot <= area.r_xtop) && (area.r_ybot <= area.r_ytop)) + WindAreaChanged((MagWindow *) NULL, &area); + } + + /* take the window out of the linked list */ + windUnlink(w); + + /* now link it back in at the top */ + w->w_nextWindow = windTopWindow; + if (windTopWindow != (MagWindow *) NULL) + windTopWindow->w_prevWindow = w; + else + windBottomWindow = w; + windTopWindow = w; + + windReClip(); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * windFindUnobscured -- + * + * Locates one portion of a rectangle that is unobscured, if + * any part of the rectangle is unobscured. Used only by + * WindReframe. + * + * Results: + * Always returns TRUE. + * + * Side effects: + * The caller must place in the shared variable sharedW the + * name of a window, or NULL. That window, and all windows + * above it, are checked to see if any obscure area. If + * there is any unobscured part of area, it is placed in + * okArea. If several distinct parts of area are unobscured, + * one, but only one, of them will be placed in okArea. + * + * ---------------------------------------------------------------------------- + */ + +int +windFindUnobscured(area, okArea) + Rect *area; /* Area that may be obscured. */ + Rect *okArea; /* Modified to contain one of the + * unobscured areas. + */ +{ + MagWindow *w; + w = sharedW; + if (w == NULL) + { + *okArea = *area; + return FALSE; + } + sharedW = w->w_prevWindow; + (void) GeoDisjoint(area, &w->w_frameArea, + windFindUnobscured, (ClientData) okArea); + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * WindReframe -- + * + * Change the size or location of a window. + * + * Results: + * None. + * + * Side effects: + * The window is moved, and areas of the screen are marked for + * redisplay. This routine tries to be tricky in order to avoid + * massive redisplay for small changes. + * ---------------------------------------------------------------------------- + */ + +void +WindReframe(w, r, inside, move) + MagWindow *w; /* the window to be reframed */ + Rect *r; /* the new location in screen coordinates */ + bool inside; /* TRUE if the rectangle is the screen location of + * the inside of the window, FALSE if the above + * rectangle includes border areas. + */ + bool move; /* Move the coordinate system of the window the same + * amount as the lower left corner of the window? + */ +{ + Rect newFrameArea; /* New w_frameArea. */ + Rect dontRedisplay; /* Used to record an area that does + * not have to be redisplayed. + */ + int xmove, ymove; /* Distance window is moving. */ + extern int windReframeFunc(); /* Forward declaration. */ + clientRec *cr; + + cr = (clientRec *) w->w_client; + + /* Ensure that the new window size is not inside out and has some size to + * it. Compute the new w_frameArea (in newFrameArea). + */ + + GeoCanonicalRect(r, &newFrameArea); + if (inside) WindInToOut(w, &newFrameArea, &newFrameArea); + + if ((w->w_flags & WIND_ISICONIC) == 0) { + /* Not iconic -- enforce a minimum size */ + newFrameArea.r_xtop = MAX(newFrameArea.r_xtop, + newFrameArea.r_xbot + WIND_MIN_WIDTH); + newFrameArea.r_ytop = MAX(newFrameArea.r_ytop, + newFrameArea.r_ybot + WIND_MIN_HEIGHT); + } + + /* Give the client a chance to modify the change. */ + if (cr->w_reposition != NULL) + (*(cr->w_reposition))(w, &newFrameArea, FALSE); + + + /* If the window coordinates are moving, update the transform + * so that the lower-left corner of the window remains at the + * same location in surface coordinates. + */ + + if (move) + { + xmove = newFrameArea.r_xbot - w->w_frameArea.r_xbot; + w->w_origin.p_x += xmove << SUBPIXELBITS; + ymove = newFrameArea.r_ybot - w->w_frameArea.r_ybot; + w->w_origin.p_y += ymove << SUBPIXELBITS; + w->w_stippleOrigin.p_x += xmove; + w->w_stippleOrigin.p_y += ymove; + } + + switch ( WindPackageType ) + { + case WIND_X_WINDOWS: + break; + + default: + /* Now comes the tricky part: figuring out what to redisplay. + * The simple way out is to force redisplay at both the old and + * new window positions. Naturally this code is going to be more + * ambitious. There are two steps. First, figure out what piece + * of the old window must be redisplayed, then move the window, + * then figure out what pieces of the new window must be redisplayed. + * If the window coordinates aren't moving, then any screen area + * common to the old and new positions needn't be redisplayed, + * since its contents won't change. + */ + + if (!move) + { + /* Compute the intersection of the old and new areas in + * dontRedisplay. Mark old areas outside of this common area as + * needing to be redisplayed. + */ + WindOutToIn(w, &newFrameArea, &dontRedisplay); + GeoClip(&dontRedisplay, &w->w_screenArea); + (void) GeoDisjoint(&w->w_frameArea, &dontRedisplay, windReframeFunc, + (ClientData) w); + } + else + { + /* Record the entire old area as needing to be redisplayed. */ + + WindAreaChanged(w, &w->w_allArea); + dontRedisplay = w->w_allArea; + } + } + + /* At this point, we've recorded any old area that needs to be + * redisplayed. + */ + + w->w_frameArea = newFrameArea; + WindSetWindowAreas(w); + windSetWindowPosition(w); + windFixSurfaceArea(w); + windReClip(); + + switch (WindPackageType) + { + case WIND_X_WINDOWS: + /* Regenerate backing store, if enabled */ + if ((GrCreateBackingStorePtr != NULL) && + (!(w->w_flags & WIND_OBSCURED))) + (*GrCreateBackingStorePtr)(w); + break; + + default: + /* Now that the window has been moved, record any of the new area that + * has to be redisplayed. + */ + + (void) GeoDisjoint(&w->w_allArea, &dontRedisplay, windReframeFunc, + (ClientData) w); + } + + /* Give the client a chance to do things like windMove(). + */ + if (cr->w_reposition != NULL) + (*(cr->w_reposition))(w, &newFrameArea, TRUE); +} + +int +windReframeFunc(area, w) + Rect *area; /* Area to redisplay. */ + MagWindow *w; /* Window in which to redisplay. */ + +{ + WindAreaChanged(w, area); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * WindFullScreen -- + * + * This procedure blows a window up so it's on top of all the others + * and is full-screen. Or, if the window was already full-screen, + * it is put back where it came from before it was made full-screen. + * + * Results: + * None. + * + * Side effects: + * The window's size and location are changed. + * + * ---------------------------------------------------------------------------- + */ + +void +WindFullScreen(w) + MagWindow *w; /* Window to be blown up or shrunk back. */ +{ + int i; + MagWindow *w2; + Rect newFrameArea; + clientRec *cr; + int newDepth; + + cr = (clientRec *) w->w_client; + + /* Compute default new location. */ + + if (w->w_flags & WIND_FULLSCREEN) + newFrameArea = w->w_oldArea; + else + newFrameArea = GrScreenRect; + + /* Give the client a chance to modify newFrameArea. */ + + if (cr->w_reposition != NULL) + (*(cr->w_reposition))(w, &newFrameArea, FALSE); + + /* + * Now, actually modify the window and its position. + */ + + /* Compute new stuff. */ + + if (w->w_flags & WIND_FULLSCREEN) + { + newDepth = w->w_oldDepth; + w->w_flags &= ~WIND_FULLSCREEN; + } + else + { + newDepth = 0; + w->w_flags |= WIND_FULLSCREEN; + + /* Record old depth and area. */ + + w->w_oldArea = w->w_frameArea; + w->w_oldDepth = 0; + for (w2 = windTopWindow; w2 != w; w2 = w2->w_nextWindow) + { + ASSERT(w2 != (MagWindow *) NULL, "WindFullScreen"); + w->w_oldDepth += 1; + } + } + + + /* Change the view and screen location. */ + w->w_frameArea = newFrameArea; + WindSetWindowAreas(w); + windSetWindowPosition(w); + WindMove(w, &w->w_surfaceArea); + + /* Move the window to the proper depth. */ + if (windTopWindow != (MagWindow *) NULL) + { + if (newDepth == 0) + { + switch ( WindPackageType ) + { + case WIND_X_WINDOWS: + break; + + default: + WindOver(w); + } + } + else + { + windUnlink(w); + w2 = windTopWindow; + for (i=1; iw_nextWindow != NULL) w2 = w2->w_nextWindow; + w->w_nextWindow = w2->w_nextWindow; + w->w_prevWindow = w2; + w2->w_nextWindow = w; + if (w->w_nextWindow == NULL) + windBottomWindow = w; + else + w->w_nextWindow->w_prevWindow = w; + windReClip(); + } + } + + /* Notify the client. */ + if (cr->w_reposition != NULL) + (*(cr->w_reposition))(w, &newFrameArea, TRUE); + + /* Record new display areas. */ + switch (WindPackageType) + { + case WIND_X_WINDOWS: + if (GrConfigureWindowPtr != NULL) + (*GrConfigureWindowPtr)(w); + if (GrCreateBackingStorePtr != NULL && + (!(w->w_flags & WIND_OBSCURED))) + (*GrCreateBackingStorePtr)(w); + break; + default: + WindAreaChanged((MagWindow *) NULL, (Rect *) NULL); + } +} diff --git a/windows/windSearch.c b/windows/windSearch.c new file mode 100644 index 00000000..33734a73 --- /dev/null +++ b/windows/windSearch.c @@ -0,0 +1,203 @@ + +/* windSearch.c - + * + * Functions to find & enumerate windows. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windSearch.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/glyphs.h" +#include "windows/windInt.h" + + +/* + * ---------------------------------------------------------------------------- + * windSearchPoint -- + * + * Find the window that is displayed at a given screen point. + * + * Results: + * A pointer to the window that contains the point, or NULL if no + * window fits the bill. This routine is dangerous, since in some + * window packages more that one window may contain that point. In + * particular, under Sun Windows ALL windows contain the point (0, 0). + * + * If 'inside' is non-NULL, it points to a boolean variable which will be + * set to TRUE if the point is in the interior of the window, and FALSE + * if it is in the border of the window. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +MagWindow * +windSearchPoint(p, inside) + Point *p; /* A point in screen coordinates */ + bool *inside; /* A pointer to a boolean variable that is set to + * TRUE if the point is in the interior of the window, + * and FALSE if it is in the border. If this pointer + * is NULL then 'inside' is not filled in. + */ +{ + MagWindow *w; + + for(w = windTopWindow; w != (MagWindow *) NULL; w = w->w_nextWindow) + { + if (GEO_ENCLOSE(p, &(w->w_allArea) )) + { + if (inside != (bool *) NULL) + *inside = GEO_ENCLOSE(p, &(w->w_screenArea) ); + return w; + } + } + + return (MagWindow *) NULL; +} + + +/* + * ---------------------------------------------------------------------------- + * + * WindSearchWid -- + * + * Find a window given its window ID. + * + * Results: + * A pointer to the window, of NULL if not found.. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +MagWindow * +WindSearchWid(wid) + int wid; +{ + MagWindow *w; + for(w = windTopWindow; w != (MagWindow *) NULL; w = w->w_nextWindow) { + if (w->w_wid == wid) return w; + } + return NULL; +} + +/* + * ---------------------------------------------------------------------------- + * + * WindSearchData -- + * + * Find a window with a matching w_grdata record. + * + * Results: + * A pointer to the window, of NULL if not found.. + * + * Side Effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +MagWindow * +WindSearchData(grdata) + ClientData grdata; +{ + MagWindow *w; + for(w = windTopWindow; w != (MagWindow *) NULL; w = w->w_nextWindow) { + if (w->w_grdata == grdata) return w; + } + return NULL; +} + +/* + * ---------------------------------------------------------------------------- + * WindSearch -- + * + * Search for all of the client's windows that contain a particular + * surface area, whether exposed or not. + * + * Results: + * None. + * + * Side effects: + * Calls the function 'func' for each window that matches. 'func' should + * be of the form + * + * int func(window, clientData) + * MagWindow *window; + * ClientData clientData; + * { + * } + * + * Window is the window that matched the search, and clientData is the + * clientData parameter supplied to this procedure. + * If the function returns a non-zero value the search is aborted, and + * that value is returned. Otherwise the search continues and 0 is + * returned. + * ---------------------------------------------------------------------------- + */ + +int +WindSearch(client, surfaceID, surfaceArea, func, clientData) + WindClient client; /* Search for the windows that belong to + * this client. NULL means all clients. + */ + ClientData surfaceID; /* The unique ID of the surface that we + * are looking for. If NULL then look for + * any surface. + */ + Rect *surfaceArea; /* The area that we are looking for in surface + * coordinates. If NULL then match without + * regard to the area in the window. + */ + int (*func)(); /* The function to call with each window + * that matches. + */ + ClientData clientData; /* The client data to be passed to the caller's + * function. + */ +{ + MagWindow *w; + int res = 0; + + for (w = windTopWindow; w != (MagWindow *) NULL; w = w->w_nextWindow) + { + if ( ((client == (WindClient) NULL) || (w->w_client == client)) && + ((surfaceID == (ClientData) NULL) || + (w->w_surfaceID == surfaceID)) ) + { + if (surfaceArea == (Rect *) NULL) + { + res = (*func)(w, clientData); + if (res != 0) return res; + continue; /* continue on to next window */ + } + else if (GEO_TOUCH(surfaceArea, &(w->w_surfaceArea) )) + { + res = (*func)(w, clientData); + if (res != 0) return res; + } + } + } + return 0; +} diff --git a/windows/windSend.c b/windows/windSend.c new file mode 100644 index 00000000..9cde9d96 --- /dev/null +++ b/windows/windSend.c @@ -0,0 +1,434 @@ +/* windSend.c - + * + * Send button pushes and commands to the window's command + * interpreters. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windSend.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "textio/textio.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/glyphs.h" +#include "windows/windInt.h" +#include "utils/stack.h" +#include "utils/utils.h" +#include "utils/signals.h" +#include "textio/txcommands.h" + +clientRec *windClient = NULL; + +bool windPrintCommands = FALSE; /* debugging flag */ + +global TxCommand *WindCurrentCmd; /* The current command. + */ +global MagWindow *WindCurrentWindow; /* The window at which the current command + * was invoked. + */ + +global int WindOldButtons; /* The buttons for the last command */ +global int WindNewButtons; /* The buttons this time */ + +static WindClient windGrabber = (WindClient) NULL; + /* If this variable is non-null then send + * all commands to it + */ + +Stack *windGrabberStack = NULL; + +/* Forward declarations */ + +extern void WindGrabInput(); +extern void WindReleaseInput(); +extern void windHelp(); + + +/* + * ---------------------------------------------------------------------------- + * WindSendCommand -- + * + * Send a command to a window to be executed. If the window passed is + * NULL then whatever window is at the point given in the command is + * used. + * + * Results: + * 0 if the command was able to be processed. + * -1 on an ambiguous command error. + * -2 on an unknown command error. + * -3 on other error. + * + * Side effects: + * Whatever the window wishes to do with the command. + * ---------------------------------------------------------------------------- + */ + +int +WindSendCommand(w, cmd, quiet) + MagWindow *w; + TxCommand *cmd; /* A pointer to a command */ + bool quiet; /* Don't print error/warning messages if this is set */ +{ + int windCmdNum, clientCmdNum; + clientRec *rc; + bool inside; /* tells us if we are inside of a window */ + + /* This thing is a horrendous mess. Changing WindClient to */ + /* MagWindow in the arguments list is a big help, but the */ + /* following code should be simplified. Namely, w == 0 */ + /* only when the command comes from the command line. */ + /* Tcl/Tk commands and graphics are set up to supply a */ + /* valid w. Under normal conditions, we should not need to */ + /* guess what the client is. */ + + /* The big problem here is that all windows are expected */ + /* to take windClient commands---but that prevents setting */ + /* up windows which don't. This should be handled better, */ + /* probably at the low level of the MagWindow structure */ + /* itself. */ + + if (windClient == (clientRec *) NULL) + windClient = (clientRec *) WindGetClient(WINDOW_CLIENT, TRUE); + + /* ignore no-op commands */ + if ( (cmd->tx_button == TX_NO_BUTTON) && (cmd->tx_argc == 0) ) + { + return 0; + } + + inside = FALSE; + ASSERT( (cmd->tx_button == TX_NO_BUTTON) || (cmd->tx_argc == 0), + "WindSendCommand"); + + WindOldButtons = WindNewButtons; + if (cmd->tx_button == TX_NO_BUTTON) + { + if (windClient == (clientRec *)NULL) return -2; + + /* If window commands are disallowed by the client (set by */ + /* the client's WIND_COMMANDS flag), report no command. */ + + if ((w != NULL) && !(w->w_flags & WIND_COMMANDS)) + windCmdNum = -2; + else + windCmdNum = Lookup(cmd->tx_argv[0], windClient->w_commandTable); + } + else + { + if (cmd->tx_buttonAction == TX_BUTTON_DOWN) + WindNewButtons |= cmd->tx_button; + else + WindNewButtons &= ~(cmd->tx_button); + } + + /* If we were passed a NULL MagWindow pointer, try to determine the */ + /* window from the command's window ID number. */ + + if (w == (MagWindow *)NULL) + { + if (cmd->tx_wid == WIND_UNKNOWN_WINDOW) + { + w = windSearchPoint( &(cmd->tx_p), &inside); + if (w != NULL) + cmd->tx_wid = w->w_wid; + } + else if (cmd->tx_wid >= 0) + w = WindSearchWid(cmd->tx_wid); + } + + if (w != (MagWindow *) NULL) + { + inside = GEO_ENCLOSE(&cmd->tx_p, &w->w_screenArea); + if ((!inside) && (w->w_flags & WIND_COMMANDS)) + rc = windClient; /* Handles border regions */ + else + rc = (clientRec *) w->w_client; + } + else + /* Can't determine a window---assume a windowless layout client */ + rc = (clientRec *) WindGetClient(DEFAULT_CLIENT, TRUE); + + if (windGrabber != (WindClient) NULL) + { + /* this client wants to hog all commands */ + rc = (clientRec *) windGrabber; + } + + /* At this point, the command is all set up and ready to send to + * the client. + */ + ASSERT(rc != (clientRec *) NULL, "WindSendCommand"); + if (windPrintCommands) + { + TxPrintf("Sending command:\n"); + windPrintCommand(cmd); + } + WindCurrentCmd = cmd; + WindCurrentWindow = w; + + if (cmd->tx_button == TX_NO_BUTTON) + { + clientCmdNum = Lookup(cmd->tx_argv[0], rc->w_commandTable); + + if ((clientCmdNum == -1) || (windCmdNum == -1)) + { + if (quiet == FALSE) + TxError("That command abbreviation is ambiguous.\n"); + return -1; + } + if ((windCmdNum == -2) && (clientCmdNum == -2)) + { + /* Not a valid command. Help the user out by telling him + * what might be wrong. And also print out the command! + */ + if (quiet == FALSE) + { + TxError("Unknown command:"); + windPrintCommand(cmd); + if (WindNewButtons != 0) + { + char *bname = "unknown"; + if (WindNewButtons & TX_LEFT_BUTTON) bname = "left"; + else if (WindNewButtons & TX_RIGHT_BUTTON) bname = "right"; + else if (WindNewButtons & TX_MIDDLE_BUTTON) bname = "middle"; + + TxError( "'%s' window is waiting for %s button to be released.\n", + rc->w_clientName, bname); + } + return -3; + } + else if (windGrabber != (WindClient) NULL) + { + if (quiet == FALSE) + TxError( "'%s' window is grabbing all input.\n", rc->w_clientName); + return -3; + } + + if (quiet == FALSE) + TxError("Did you point to the correct window?\n"); + return -2; + } + + /* intercept 'help' */ + if ((windCmdNum >= 0) && + (strncmp(windClient->w_commandTable[windCmdNum], + "help", 4) == 0) ) + { + TxUseMore(); + windHelp(cmd, "Global", windClient->w_commandTable); + if (rc != windClient) + windHelp(cmd, rc->w_clientName, rc->w_commandTable); + TxStopMore(); + return 0; + } + + /* If both command tables point to window commands, */ + /* only do the command once. */ + + if (rc == windClient) clientCmdNum = -2; + + /* Ambiguity resolution. If only one client reports a */ + /* valid command, then execute it. If both clients */ + /* report a valid command, then compare them against */ + /* each other so that a full command name will take */ + /* precedence over an ambiguous command abbreviation. */ + /* Finally, if this doesn't resolve the command, the */ + /* registered client takes precedence over the general- */ + /* purpose window client, allowing clients to override */ + /* the general-purpose functions (like "zoom" and */ + /* "view", for instance). This is the reverse of how */ + /* it was implemented prior to magic-7.3.61, but that */ + /* makes no sense. */ + + if ((windCmdNum < 0) && (clientCmdNum >= 0)) + (*(rc->w_command))(w, cmd); + else if ((windCmdNum >= 0) && (clientCmdNum < 0)) + (*(windClient->w_command))(w, cmd); + else if ((windCmdNum >= 0) && (clientCmdNum >= 0)) + { + char *(ownTable[3]); + int ownCmdNum; + + ownTable[0] = rc->w_commandTable[clientCmdNum]; + ownTable[1] = windClient->w_commandTable[windCmdNum]; + ownTable[2] = NULL; + ownCmdNum = Lookup(cmd->tx_argv[0], ownTable); + ASSERT(ownCmdNum != -2, "WindSendCommand"); + if (ownCmdNum == -1) + { + if (quiet == FALSE) + TxError("That command abbreviation is ambiguous\n"); + return -1; + } + if (ownCmdNum == 0) + (*(rc->w_command))(w, cmd); + else + (*(windClient->w_command))(w, cmd); + } + } + else + { + /* A button has been pushed. + * If there were no buttons pressed on the last command + * now there are, and direct all future button pushes to this + * client until all buttons are up again. + */ + + /* windClient is responsible for processing actions in the */ + /* window border, assuming that the window handles its own */ + /* borders. Scrollbars are only available on the layout */ + /* window, which is the "default" client. So we check for a */ + /* position in the border region, and launch the window client */ + /* if it is. */ + + if (WindOldButtons == 0) WindGrabInput((WindClient) rc); + else if (WindNewButtons == 0) WindReleaseInput((WindClient) rc); + (*(rc->w_command))(w, cmd); + } + + /* A client may modify WindNewButtons & WindOldButtons in rare cases, + * so we better check again. + */ + if ((WindNewButtons == 0) && (windGrabber != (WindClient) NULL)) + WindReleaseInput((WindClient) rc); + + return 0; +} + + + + +/* + * ---------------------------------------------------------------------------- + * WindGrabInput -- + * + * Grab all input -- that is, send all further commands to the + * specified client. + * + * Results: + * None. + * + * Side effects: + * pushes old grabber onto a stack. + * ---------------------------------------------------------------------------- + */ + +void +WindGrabInput(client) + WindClient client; +{ + ASSERT( client != NULL, "WindGrabInput"); + StackPush( (ClientData) windGrabber, windGrabberStack); + windGrabber = client; +} + + + +/* + * ---------------------------------------------------------------------------- + * WindReleaseInput -- + * + * Stop grabbing the input (the inverse of WindGrabInput). + * + * Results: + * None. + * + * Side effects: + * The previous grabber (if any) is restored. + * ---------------------------------------------------------------------------- + */ + +void +WindReleaseInput(client) + WindClient client; +{ + ASSERT( client == windGrabber, "WindReleaseInput"); + windGrabber = (WindClient) StackPop(windGrabberStack); +} + + +/* + * ---------------------------------------------------------------------------- + * windHelp -- + * + * Print out help information for a client. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +windHelp(cmd, name, table) + TxCommand *cmd; /* Information about command options. */ + char *name; /* Name of client for whom help is being + * printed. + */ + char *table[]; /* Client's command table. */ +{ + static char *capName = NULL; + static char patString[200], *pattern; + bool wiz; + char **tp; +#define WIZARD_CHAR '*' + + if (cmd->tx_argc > 2) + { + TxError("Usage: help [pattern]\n"); + return; + } + + if (SigInterruptPending) return; + (void) StrDup(&capName, name); + if (islower(capName[0])) capName[0] += 'A' - 'a'; + + TxPrintf("\n"); + if ((cmd->tx_argc == 2) && strcmp(cmd->tx_argv[1], "wizard") == 0) + { + pattern = "*"; + wiz = TRUE; + TxPrintf("Wizard %s Commands\n", capName); + TxPrintf("----------------------\n"); + } + else + { + if (cmd->tx_argc == 2) + { + pattern = patString; + (void) sprintf(patString, "*%.195s*", cmd->tx_argv[1]); + } + else + pattern = "*"; + wiz = FALSE; + TxPrintf("%s Commands\n", capName); + TxPrintf("---------------\n"); + } + for (tp = table; *tp != (char *) NULL; tp++) + { + if (SigInterruptPending) return; + if (Match(pattern, *tp) && (wiz ^ (**tp != WIZARD_CHAR)) ) + TxPrintf("%s\n", *tp); + } +} diff --git a/windows/windTrans.c b/windows/windTrans.c new file mode 100644 index 00000000..d77e0e54 --- /dev/null +++ b/windows/windTrans.c @@ -0,0 +1,374 @@ + +/* windTransform.c - + * + * Routines to transform from screen coords to surface coords and the + * other way. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windTrans.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include "utils/magic.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/glyphs.h" +#include "windows/windInt.h" + + +/* + * ---------------------------------------------------------------------------- + * WindScreenToSurface -- + * + * Convert a rectangle in screen coordinates to surface coords. + * + * Results: + * None. + * + * Side effects: + * Returns a rectangle that is big enough to fully contain everything + * that is displayed in the screen rectangle. + * ---------------------------------------------------------------------------- + */ + +void +WindScreenToSurface(w, screen, surface) + MagWindow *w; /* Window in whose coordinates screen is + * is defined. + */ + Rect *screen; /* A rectangle in screen coordinates */ + Rect *surface; /* A pointer to a rectangle to be filled + * in with a rectangle in surface coords that + * is big enough to contain everything + * displayed within the screen rectangle. + */ +{ + Rect r; + WindPointToSurface(w, &(screen->r_ll), (Point *) NULL, surface); + WindPointToSurface(w, &(screen->r_ur), (Point *) NULL, &r); + surface->r_ur = r.r_ur; +} + + +/* + * ---------------------------------------------------------------------------- + * WindPointToSurface -- + * + * Take a point in screen coordinates and find the nearest point + * in surface coordinates. Also return a box in surface coords + * that completely surrounds the pixel. + * + * Results: + * None. + * + * Side effects: + * The parameters surfaceBox and surfacePoint are modified, if + * they are non-NULL. The box is always at least 1x1, but it + * will be larger if the scale is so coarse that a single screen + * coordinate is more than one surface coordinate. In this case + * the box is large enough to include every surface coordinate + * that can map to the given pixel (this feature is essential + * if WindScreenToSurface is to use this routine). + * + * ---------------------------------------------------------------------------- + */ + +void +WindPointToSurface(w, screenPoint, surfacePoint, surfaceBox) + MagWindow *w; /* Window in whose coordinate system the + * transformation is to be done. + */ + Point *screenPoint; /* The point in screen coordinates. */ + Point *surfacePoint;/* Filled in with the nearest surface coordinate. + * Nothing is filled in if the pointer is NULL. + */ + Rect *surfaceBox; /* Filled in with a box in surface coordinates that + * surrounds the point. It is not filled in if this + * is a NULL pointer. + */ +{ + int tmp, adjust, unitsPerPixel; + + /* Do the inverse transformation twice, once with rounding for + * the point and once with truncation for the box. + */ + + unitsPerPixel = SUBPIXEL/w->w_scale; + + if (surfaceBox != NULL) + { + tmp = (SUBPIXEL*screenPoint->p_x) - w->w_origin.p_x; + if (tmp < 0) tmp -= w->w_scale-1; + surfaceBox->r_xbot = w->w_surfaceArea.r_xbot + tmp/w->w_scale; + surfaceBox->r_xtop = surfaceBox->r_xbot + unitsPerPixel + 1; + + tmp = (SUBPIXEL*screenPoint->p_y) - w->w_origin.p_y; + if (tmp < 0) tmp -= w->w_scale-1; + surfaceBox->r_ybot = w->w_surfaceArea.r_ybot + tmp/w->w_scale; + surfaceBox->r_ytop = surfaceBox->r_ybot + unitsPerPixel + 1; + } + + if (surfacePoint != NULL) + { + adjust = w->w_scale/2; + tmp = (SUBPIXEL*screenPoint->p_x) - w->w_origin.p_x; + if (tmp >= 0) tmp += adjust; + else tmp -= adjust; + surfacePoint->p_x = w->w_surfaceArea.r_xbot + tmp/w->w_scale; + + tmp = (SUBPIXEL*screenPoint->p_y) - w->w_origin.p_y; + if (tmp >= 0) tmp += adjust; + else tmp -= adjust; + surfacePoint->p_y = w->w_surfaceArea.r_ybot + tmp/w->w_scale; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * WindSurfaceToScreen -- + * + * This procedure transforms a rectangle in surface coordinates + * to a rectangle in the screen coordinates of a particular window. + * + * Results: + * None. + * + * Side effects: + * The rectangle pointed to by screen is filled in with the + * coordinates (in pixels) of the screen area corresponding + * to surface. A pixel is included in screen if it is + * touched in any way by surface. If any of the edges of + * screen is outside w->w_surfaceArea, the corresponding + * edge of the result will also be outside w->w_screenArea. + * + * Design Note: + * This procedure is trickier than it looks, for a couple of + * reasons having to do with numerical accuracy. The + * transformation is done in units of 1/SUBPIXEL pixel (fix-point + * arithmetic), in order to avoid accumulated round-off error + * when there are fractional pixels per surface unit. Furthermore, + * it's important that the transformation to screen units NOT be + * done with a procedure like GeoTransRect. The reason is that + * GeoTransRect does the multiplication before the addition or + * subtraction, which can result in arithmeic overflow. We use + * a different form for the transform here, in terms of an origin + * and a scale, with the translation done FIRST and multiplication + * later. This, combined with the clipping to w->w_surfaceArea, + * guarantees numerical accuracy as long as surface coordinates + * fit into an integer and SUBPIXEL*screenSize fits into an integer. + * + * ---------------------------------------------------------------------------- + */ + +void +WindSurfaceToScreen(w, surface, screen) + MagWindow *w; /* Window in whose coordinate system the + * transform is to be done. + */ + Rect *surface; /* Rectangle in surface coordinates of w. */ + Rect *screen; /* Rectangle filled in with screen coordinates + * (in w) of surface. + */ +{ + int tmp; + + /* Do the four coordinates one at a time. */ + + /* The apparently redundant clipping (also done later by the box */ + /* drawing routine) is necessary for two reasons: 1) it prevents */ + /* having to do a multiply and shift function for any box extending */ + /* outside the viewport, and more critically 2) it prevents integer */ + /* overflow when a tile extends very far out of the viewport. */ + + tmp = surface->r_xbot; + if (tmp > w->w_surfaceArea.r_xtop) + screen->r_xbot = w->w_screenArea.r_xtop + 1; + else + { + tmp -= w->w_surfaceArea.r_xbot; + if (tmp < 0) + screen->r_xbot = w->w_screenArea.r_xbot - 1; + else screen->r_xbot = (w->w_origin.p_x + (tmp * w->w_scale)) >> SUBPIXELBITS; + } + + tmp = surface->r_ybot; + if (tmp > w->w_surfaceArea.r_ytop) + screen->r_ybot = w->w_screenArea.r_ytop + 1; + else + { + tmp -= w->w_surfaceArea.r_ybot; + if (tmp < 0) + screen->r_ybot = w->w_screenArea.r_ybot - 1; + else screen->r_ybot = (w->w_origin.p_y + (tmp * w->w_scale)) >> SUBPIXELBITS; + } + + tmp = surface->r_xtop; + if (tmp > w->w_surfaceArea.r_xtop) + screen->r_xtop = w->w_screenArea.r_xtop + 1; + else + { + tmp -= w->w_surfaceArea.r_xbot; + if (tmp < 0) + screen->r_xtop = w->w_screenArea.r_xbot - 1; + else screen->r_xtop = (w->w_origin.p_x + (tmp * w->w_scale)) >> SUBPIXELBITS; + } + + tmp = surface->r_ytop; + if (tmp > w->w_surfaceArea.r_ytop) + screen->r_ytop = w->w_screenArea.r_ytop + 1; + else + { + tmp -= w->w_surfaceArea.r_ybot; + if (tmp < 0) + screen->r_ytop = w->w_screenArea.r_ybot - 1; + else screen->r_ytop = (w->w_origin.p_y + (tmp * w->w_scale)) >> SUBPIXELBITS; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * WindSurfaceToScreenNoClip -- + * + * This procedure is like WindSurfaceToScreen except that it + * does not clip to the window boundary. This is necessary for + * non-Manhattan tiles to make sure they are not clipped. + * However, this routine is also useful for Manhattan geometry + * when, for example, determining the transformation of a unit + * coordinate. + * + * We convert to type double long because at close-in scales, large + * values of w_scale can cause integer overflow on 32-bit integers. + * + * Results: + * None. + * + * Side effects: + * Pointer argument "screen" is filled with the transformed + * coordinates. + * + * ---------------------------------------------------------------------------- + */ + +void +WindSurfaceToScreenNoClip(w, surface, screen) + MagWindow *w; + Rect *surface; + Rect *screen; +{ + dlong tmp, dval; + + tmp = (dlong)(surface->r_xbot - w->w_surfaceArea.r_xbot); + dval = (dlong)w->w_origin.p_x + (tmp * (dlong)w->w_scale); + screen->r_xbot = (int)(dval >> SUBPIXELBITS); + tmp = surface->r_ybot - w->w_surfaceArea.r_ybot; + dval = (dlong)w->w_origin.p_y + (tmp * (dlong)w->w_scale); + screen->r_ybot = (int)(dval >> SUBPIXELBITS); + tmp = surface->r_xtop - w->w_surfaceArea.r_xbot; + dval = (dlong)w->w_origin.p_x + (tmp * (dlong)w->w_scale); + screen->r_xtop = (int)(dval >> SUBPIXELBITS); + tmp = surface->r_ytop - w->w_surfaceArea.r_ybot; + dval = (dlong)w->w_origin.p_y + (tmp * (dlong)w->w_scale); + screen->r_ytop = (int)(dval >> SUBPIXELBITS); +} + + +/* + * ---------------------------------------------------------------------------- + * + * WindPointToScreen -- + * + * This is just like WindSurfaceToScreen, except it transforms a + * point instead of a rectangle. + * + * Results: + * None. + * + * Side effects: + * Screen is modified to contain screen coordinates. They may be + * clipped just as in WindSurfaceToScreen. + * + * ---------------------------------------------------------------------------- + */ + +void +WindPointToScreen(w, surface, screen) + MagWindow *w; /* Window in whose coordinate system the + * transform is to be done. + */ + Point *surface; /* Point in surface coordinates of w. */ + Point *screen; /* Point filled in with screen coordinates + * (in w) of surface. + */ +{ + int tmp; + + /* Do the coordinates one at a time. */ + + tmp = surface->p_x; + if (tmp > w->w_surfaceArea.r_xtop) + tmp = w->w_surfaceArea.r_xtop; + tmp -= w->w_surfaceArea.r_xbot; + if (tmp < 0) tmp = 0; + screen->p_x = (w->w_origin.p_x + (tmp*w->w_scale)) >> SUBPIXELBITS; + + tmp = surface->p_y; + if (tmp > w->w_surfaceArea.r_ytop) + tmp = w->w_surfaceArea.r_ytop; + tmp -= w->w_surfaceArea.r_ybot; + if (tmp < 0) tmp = 0; + screen->p_y = (w->w_origin.p_y + (tmp*w->w_scale)) >> SUBPIXELBITS; +} + +/* + * ---------------------------------------------------------------------------- + * + * windScreenToFrame -- + * + * Transform a point from screen coordinates to frame coordinates. + * + * Results: + * None. + * + * Side effects: + * Frame is filled in with the frame coordinates corresponding to + * the screen coordinates. + * + * ---------------------------------------------------------------------------- + */ + +void +windScreenToFrame(w, screen, frame) + MagWindow *w; /* Window in whose coordinate system the + * transform is to be done. + */ + Point *screen; /* Point in screen coordinates of w. */ + Point *frame; /* Point filled in with frame coordinates. + */ +{ + switch ( WindPackageType ) + { + case WIND_X_WINDOWS: + frame->p_x = screen->p_x + w->w_frameArea.r_xbot; + frame->p_y = screen->p_y + w->w_frameArea.r_ybot; + break; + + default: + /* WIND_MAGIC_WINDOWS */ + *frame = *screen; + } +} diff --git a/windows/windView.c b/windows/windView.c new file mode 100644 index 00000000..9b98d76e --- /dev/null +++ b/windows/windView.c @@ -0,0 +1,505 @@ +/* windView.c - + * + * Routines in this file control what is viewed in the contents + * of the windows. This includes things like pan, zoom, and loading + * of windows. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windView.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "windows/windows.h" +#include "graphics/glyphs.h" +#include "graphics/graphics.h" +#include "windows/windInt.h" +#include "textio/textio.h" + +extern void windNewView(); + + +/* + * ---------------------------------------------------------------------------- + * + * windFixSurfaceArea -- + * + * When a window's surface or screen area has been changed, + * this procedure is usually called to fix up w->w_surfaceArea and + * w_origin. Before calling this procedure, w->w_origin gives the + * screen location of w_surfaceArea.r_ll in SUBPIXEL of a pixel and + * w->w_scale is correct, but w->w_surfaceArea may no longer be a + * slight overlap of w->w_screenArea as it should be. This procedure + * regenerates w->w_surfaceArea to correspond to w->w_screenArea and + * changes w->w_origin to correspond to w->w_surfaceArea.r_ll again. + * + * Results: + * None. + * + * Side effects: + * w->w_origin and w->w_surfaceArea are modified. + * + * ---------------------------------------------------------------------------- + */ + +void +windFixSurfaceArea(w) + MagWindow *w; /* Window to fix up. */ +{ + Rect newArea, tmp; + + GEO_EXPAND(&w->w_screenArea, 1, &tmp); + WindScreenToSurface(w, &tmp, &newArea); + w->w_origin.p_x += (newArea.r_xbot - w->w_surfaceArea.r_xbot) * w->w_scale; + w->w_origin.p_y += (newArea.r_ybot - w->w_surfaceArea.r_ybot) * w->w_scale; + w->w_surfaceArea = newArea; +} + + +/* + * ---------------------------------------------------------------------------- + * + * WindUnload -- + * + * Remove a client with the indicated surfaceID and reset the window + * to default cell (UNKNOWN). + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +WindUnload(surfaceID) + ClientData surfaceID; /* A unique ID for this surface */ +{ + MagWindow *mw; + + for (mw = windTopWindow; mw != NULL; mw = mw->w_nextWindow) + if (mw->w_surfaceID == surfaceID) + DBWloadWindow(mw, (char *)NULL, TRUE, FALSE); +} + +/* + * ---------------------------------------------------------------------------- + * WindLoad -- + * + * Load a new client surface into a window. An initial surface area + * must be specified -- this is the area that will be visible in + * the window initially. + * + * Results: + * True if everything went well, false if the client does not + * own the window. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +bool +WindLoad(w, client, surfaceID, surfaceArea) + MagWindow *w; + WindClient client; /* The unique identifier of the client */ + ClientData surfaceID; /* A unique ID for this surface */ + Rect *surfaceArea; /* The area that should appear in the window */ +{ + if (client != w->w_client) return FALSE; + + w->w_surfaceID = surfaceID; + WindMove(w, surfaceArea); + return TRUE; +} + + +/* + * ---------------------------------------------------------------------------- + * WindMove -- + * + * Move the surface under the window so that the given area is visible + * and as large as possible. + * + * Results: + * None. + * + * Side effects: + * The window will be now view a different portion of the clients area. + * The client may be called to redisplay the areas that moved. + * ---------------------------------------------------------------------------- + */ + +void +WindMove(w, surfaceArea) + MagWindow *w; /* the window to be panned */ + Rect *surfaceArea; /* The area to be viewed */ +{ + int size, xscale, yscale; + int halfSizePixels, halfSizeUnits; + + /* Compute the scale factor from world coordinates to 1/SUBPIXEL + * of a pixel. To be sure that surfaceArea will all fit in the + * window, compute the scale twice, once using the y-dimension + * alone, and once using x alone. Then use the smaller scale factor. + */ + + size = (surfaceArea->r_xtop - surfaceArea->r_xbot + 1); + xscale = ((dlong)(w->w_screenArea.r_xtop - + w->w_screenArea.r_xbot + 1) * SUBPIXEL) / size; + + size = (surfaceArea->r_ytop - surfaceArea->r_ybot + 1); + yscale = ((w->w_screenArea.r_ytop - + w->w_screenArea.r_ybot + 1) * SUBPIXEL) / size; + + w->w_scale = MIN(xscale, yscale); + if (w->w_scale < 1) + { + /* If this message appears, then it is likely that the */ + /* definition for SUBPIXELBITS should be increased. */ + + TxError("Warning: At minimum scale!\n"); + w->w_scale = 1; + } + + /* Recompute w->surfaceArea and w->w_origin, which determine the + * screen-surface mapping along with w->w_scale. In order to + * center surfaceArea in the window, compute the windows's half-size + * in units of SUBPIXEL of a pixel and in units. Be sure to round + * things up so that w->w_surfaceArea actually overlaps the window + * slightly. + */ + + halfSizePixels = (w->w_screenArea.r_xtop - w->w_screenArea.r_xbot) * HSUBPIXEL; + halfSizeUnits = (halfSizePixels / w->w_scale) + 1; + w->w_surfaceArea.r_xbot = (surfaceArea->r_xbot + surfaceArea->r_xtop) / 2 + - halfSizeUnits; + w->w_surfaceArea.r_xtop = w->w_surfaceArea.r_xbot + 2 * halfSizeUnits + 1; + w->w_origin.p_x = + ((w->w_screenArea.r_xtop + w->w_screenArea.r_xbot) * HSUBPIXEL) - + (halfSizeUnits * w->w_scale); + + halfSizePixels = (w->w_screenArea.r_ytop - w->w_screenArea.r_ybot) * HSUBPIXEL; + halfSizeUnits = (halfSizePixels/w->w_scale) + 1; + w->w_surfaceArea.r_ybot = (surfaceArea->r_ybot + surfaceArea->r_ytop) / 2 + - halfSizeUnits; + w->w_surfaceArea.r_ytop = w->w_surfaceArea.r_ybot + 2 * halfSizeUnits + 1; + w->w_origin.p_y = + ((w->w_screenArea.r_ytop + w->w_screenArea.r_ybot) * HSUBPIXEL) - + (halfSizeUnits * w->w_scale); + + WindAreaChanged(w, &(w->w_screenArea)); + windNewView(w); +} + + +/* + * ---------------------------------------------------------------------------- + * WindZoom -- + * + * Zoom a window. The window will stay centered about the same point + * as it is currently. A factor greater than 1 increases the scale + * of the window (higher magnification), while a factor smaller than 1 + * results in a lower scale (lower magnification). + * + * Results: + * None. + * + * Side effects: + * The window will be now view a different portion of the client's area. + * The client may be called to redisplay part of the screen. + * ---------------------------------------------------------------------------- + */ + +void +WindZoom(w, factor) + MagWindow *w; /* the window to be zoomed */ + float factor; /* The amount to zoom by (1 is no change), + * greater than 1 is a larger magnification + * (zoom in), and less than 1 is less mag. + * (zoom out) ) + */ +{ + int centerx, centery; + Rect newArea; + + centerx = (w->w_surfaceArea.r_xbot + w->w_surfaceArea.r_xtop) / 2; + centery = (w->w_surfaceArea.r_ybot + w->w_surfaceArea.r_ytop) / 2; + + newArea.r_xbot = centerx - (centerx - w->w_surfaceArea.r_xbot) * factor; + newArea.r_xtop = centerx + (w->w_surfaceArea.r_xtop - centerx) * factor; + newArea.r_ybot = centery - (centery - w->w_surfaceArea.r_ybot) * factor; + newArea.r_ytop = centery + (w->w_surfaceArea.r_ytop - centery) * factor; + + WindMove(w, &newArea); +} + +/* + * ---------------------------------------------------------------------------- + * + * WindScale -- + * + * Zoom all viewing windows by the given factor. Because this is done + * in conjunction with rescaling the geometry, we don't preserve the + * center position like WindZoom() does. The net effect is that the + * image in the window doesn't appear to change. + * + * Results: + * None. + * + * Side effects: + * All windows will be now view a different portion of the client's area. + * + * ---------------------------------------------------------------------------- + */ + +void +WindScale(scalen, scaled) + int scalen, scaled; +{ + extern void DBScalePoint(); + MagWindow *w2; + Rect newArea; + + for (w2 = windTopWindow; w2 != NULL; w2 = w2->w_nextWindow) + { + newArea.r_xbot = w2->w_surfaceArea.r_xbot; + newArea.r_xtop = w2->w_surfaceArea.r_xtop; + newArea.r_ybot = w2->w_surfaceArea.r_ybot; + newArea.r_ytop = w2->w_surfaceArea.r_ytop; + DBScalePoint(&newArea.r_ll, scalen, scaled); + DBScalePoint(&newArea.r_ur, scalen, scaled); + WindMove(w2, &newArea); + } +} + + +/* + * ---------------------------------------------------------------------------- + * + * WindView -- + * + * Change the view in the selected window to just contain the + * bounding box for that window. + * + * + * Results: + * None. + * + * Side effects: + * The window underneath the cursor is changed. + * + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ + +void +WindView(w) + MagWindow *w; +{ + Rect bbox; +#define SLOP 10 /* Amount of border (in fraction of a screenfull) + * to add. + */ + if (w == NULL) + return; + + if (w->w_bbox == NULL) { + TxError("Can't do 'view' because w_bbox is NULL.\n"); + TxError("Report this to a magic implementer.\n"); + return; + }; + + bbox = *(w->w_bbox); + bbox.r_xbot -= (bbox.r_xtop - bbox.r_xbot + 1) / SLOP; + bbox.r_xtop += (bbox.r_xtop - bbox.r_xbot + 1) / SLOP; + bbox.r_ybot -= (bbox.r_ytop - bbox.r_ybot + 1) / SLOP; + bbox.r_ytop += (bbox.r_ytop - bbox.r_ybot + 1) / SLOP; + + WindMove(w, &bbox); +} + +/* + * ---------------------------------------------------------------------------- + * + * WindScroll -- + * + * Scroll the view around. + * + * Results: + * None. + * + * Side effects: + * The window underneath the cursor is changed. The offset can + * be specified either in screen coordinates or surface coordinates + * or both. + * + * ---------------------------------------------------------------------------- + */ + +void +WindScroll(w, surfaceOffset, screenOffset) + MagWindow *w; + Point *surfaceOffset; /* An offset in surface coordinates. The + * screen point that used to display surface + * point (0,0) will now display surface point + * surfaceOffset. Can be NULL to indicate + * no offset. + */ + Point *screenOffset; /* An additional offset in screen coordinates. + * Can be NULL to indicate no offset. If + * non-NULL, then after scrolling according + * to surfaceOffset, the view is adjusted again + * so that the surface unit that used to be + * displayed at (0,0) will now be displayed + * at screenOffset. Be careful to make sure + * the coordinates in here are relatively + * small (e.g. the same order as the screen + * size), or else there may be arithmetic + * overflow and unexpected results. Use only + * surfaceOffset if you're going to be + * scrolling a long distance. + */ +{ + Rect screenorigin; + bool useBackingStore = FALSE; + Point moveorigin; + Rect refresh, norefresh; + + WindSurfaceToScreenNoClip(w, &GeoNullRect, &screenorigin); + + if (surfaceOffset != NULL) + { + w->w_surfaceArea.r_xbot += surfaceOffset->p_x; + w->w_surfaceArea.r_ybot += surfaceOffset->p_y; + w->w_surfaceArea.r_xtop += surfaceOffset->p_x; + w->w_surfaceArea.r_ytop += surfaceOffset->p_y; + } + + /* Screen offsets are trickier. Divide up into a whole-unit part + * (which is applied to w->w_surfaceArea) and a fractional-unit + * part (which is applied to w->w_origin. Then readjust both to + * make sure that w->w_surfaceArea still overlaps the window area + * on all sides. + */ + + if (screenOffset != NULL) + { + int units, pixels; + + pixels = screenOffset->p_x * SUBPIXEL; + units = pixels/w->w_scale; + w->w_surfaceArea.r_xbot -= units; + w->w_surfaceArea.r_xtop -= units; + w->w_origin.p_x += pixels - (w->w_scale*units); + + pixels = screenOffset->p_y * SUBPIXEL; + units = pixels/w->w_scale; + w->w_surfaceArea.r_ybot -= units; + w->w_surfaceArea.r_ytop -= units; + w->w_origin.p_y += pixels - (w->w_scale*units); + } + + /* For now, we forget about using backing store in the case */ + /* of diagonal scrolls. Ideally, we would want to register */ + /* two rectangles for the window redraw in this case. */ + + if (w->w_backingStore != (ClientData)NULL) + { + if (surfaceOffset) + if (surfaceOffset->p_x == 0 || surfaceOffset->p_y == 0) + useBackingStore = TRUE; + if (screenOffset) + if (screenOffset->p_x == 0 || screenOffset->p_y == 0) + if (useBackingStore == FALSE) + useBackingStore = TRUE; + } + windFixSurfaceArea(w); + + /* Finally, if we are going to use backing store, we ought */ + /* to adjust the screen movement to the nearest multiple of */ + /* 8 so that stipples will remain aligned. This must be */ + /* done after windFixSurfaceArea(), but cannot screw up the */ + /* coordinate system, so we do windFixSurfaceArea() again. */ + + if (useBackingStore) + { + int units, pixels; + + WindSurfaceToScreenNoClip(w, &GeoNullRect, &refresh); + moveorigin.p_x = refresh.r_xbot - screenorigin.r_xbot; + moveorigin.p_y = refresh.r_ybot - screenorigin.r_ybot; + + pixels = (moveorigin.p_x % 8) * SUBPIXEL; + units = pixels/w->w_scale; + w->w_surfaceArea.r_xbot += units; + w->w_surfaceArea.r_xtop += units; + w->w_origin.p_x -= (pixels - (w->w_scale*units)); + + pixels = (moveorigin.p_y % 8) * SUBPIXEL; + units = pixels/w->w_scale; + w->w_surfaceArea.r_ybot += units; + w->w_surfaceArea.r_ytop += units; + w->w_origin.p_y -= (pixels - (w->w_scale*units)); + + moveorigin.p_x -= (moveorigin.p_x % 8); + moveorigin.p_y -= (moveorigin.p_y % 8); + + windFixSurfaceArea(w); + } + + /* If we have backing store available, shift the contents. */ + + if (useBackingStore) + { + refresh = w->w_screenArea; + norefresh = w->w_screenArea; + if (moveorigin.p_x > 0) + { + refresh.r_xtop = moveorigin.p_x + w->w_screenArea.r_xbot; + norefresh.r_xbot = refresh.r_xtop; + } + else if (moveorigin.p_x < 0) + { + refresh.r_xbot = refresh.r_xtop + moveorigin.p_x; + norefresh.r_xtop += moveorigin.p_x; + } + if (moveorigin.p_y > 0) + { + refresh.r_ytop = moveorigin.p_y + w->w_screenArea.r_ybot; + norefresh.r_ybot = refresh.r_ytop; + } + else if (moveorigin.p_y < 0) + { + refresh.r_ybot = refresh.r_ytop + moveorigin.p_y; + norefresh.r_ytop += moveorigin.p_y; + } + + (*GrScrollBackingStorePtr)(w, &moveorigin); + (*GrGetBackingStorePtr)(w, &norefresh); + WindAreaChanged(w, &refresh); + /* Update highlights over entire screen area */ + DBWHLRedrawPrepWindow(w, &(w->w_surfaceArea)); + } + else + WindAreaChanged(w, &(w->w_screenArea)); + + windNewView(w); +} diff --git a/windows/windows.h b/windows/windows.h new file mode 100644 index 00000000..5332fcd1 --- /dev/null +++ b/windows/windows.h @@ -0,0 +1,330 @@ +/* + * windows.h -- + * + * Interface definitions for Magic's window manager. This + * package manages a set of overlapping windows. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/windows/windows.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + * + */ + +#ifndef _WINDOWS_H +#define _WINDOWS_H + +#include "utils/magic.h" +#include "utils/geometry.h" + +/* SUBPIXELBITS represents a fixed-point shift for representing the */ +/* scale factor between the screen and the layout. It is only */ +/* necessary that the screen resolution * SUBPIXEL does not overflow */ +/* type (int). The original value of 12 has become too small for */ +/* large chips on nanometer grids, so it has been upped to 16. */ + +#define SUBPIXELBITS 16 +#define SUBPIXEL (1 << SUBPIXELBITS) +#define HSUBPIXEL (1 << (SUBPIXELBITS - 1)) + +typedef ClientData WindClient; /* A unique ID of a client of the + * window package. The value 'NULL' is + * indicates an invalid value. + */ + +/* + * The following structure describes a window. Windows are overlapping + * rectangles. Each window contains a 'surface', whose contents are maintained + * by a client of the window package. The client is responsible for redrawing + * the surface when requested. The window package maintains the transform + * from surface coordinates to screen coordinates and also controls which + * portion of the surface is currently visable in the window. See the + * comments in windMain.c and above the proc 'WindAddClient' for more info. + * + * To see an example of a simple window client, look at the colormap window + * located in 'cmwind/CMWmain.c'. A more complex window is the layout window, + * located in 'dbwind/DBWprocs.c'. + * + * The following key letters in parens after a field indicate who should + * read & write it: + * + * P - Private (window package use only). + * R - Read-only (clients should not modify this, but may read it). + * W - Writable by client at any time. + * C - Writable by the client only during window creation time (in the + * create proc passed to WindAddClient) and readable at all times. + * L - Writable by the client at creation time and when the window is + * loaded with a new surface. + * G - Private to the graphics module. + * + * The comments below often mention a procedure that sets a given field. This + * is the normal procedure used to set the field, but there may be other seldom + * used procs in the window package that set the field. + */ +typedef struct WIND_S1 { + struct WIND_S1 *w_nextWindow; /* A doubly-linked list (P) */ + struct WIND_S1 *w_prevWindow; /* A doubly-linked list (P) */ + ClientData w_clientData; /* Used by the client an any manner (W) */ + WindClient w_client; /* The client of this window (R) */ + char *w_caption; /* The caption at the top of the window. (R) + * Set via WindCaption(). + */ + ClientData w_surfaceID; /* A unique ID for this surface, other than + * NULL. (R) + * Set via WindLoad(). + */ + Rect w_allArea; /* The entire area of the window in the screen + * coordinates for the window, including the + * border and obscured areas. (R) + * + * If we are using Magic's window package, + * then this field is equal to w_frameArea + * since all windows share the same coordinate + * system. In SunWindows, the lower-left + * corner of this area is at (0, 0) because + * each Sun window has it's own coordinate + * system with the origin in the lower left + * corner. + * + * This field is recomputed by WindReframe(). + */ + Rect w_frameArea; /* The location of the window on the screen (C) + * If a window's create proc modifies this, it + * needs to set w_allArea and w_screenArea by + * calling WindSetWindowAreas(). + * + * Also, see comments for w_allArea. + * + * This field is initialized to a reasonable + * value at window creation time, but the + * 'reposition' proc passed to WindAddClient + * has a way of overriding it. + */ + Rect w_screenArea; /* The area of the window in the screen + * coordinates of the window -- not including + * the border but including obscured areas. (R) + * + * This field is recomputed by WindReframe(). + */ + Rect w_surfaceArea; /* An area in surface coordinates that + * is large enough to contain everything + * displayed in w_screenArea plus at least + * one pixel of border on all sides. (R) + * This field, and w_origin and w_scale below, + * are modified by procedures that move and + * scroll windows, e.g. WindMove and WindScroll. + */ + Point w_origin; /* This screen point, in 1/SUBPIXEL pixels, + * corresponds to w_surfaceArea.r_ll. + * Used to transform between surface and screen + * coordinates. (R) + */ + int w_scale; /* Defines how many 1/SUBPIXEL of a pixel + * correspond to 1 world unit. Used to + * transform between surface and screen + * coordinates. (R) + */ + LinkedRect *w_clipAgainst; /* A linked list of areas which obscure + * portions of this window. (R) + * Normally clients just pass this down to the + * graphics package. + * Changed via WindOver(), WindUnder(), and + * WindFullScreen(). + */ + Point w_stippleOrigin; /* A point that serves as the origin (in screen + * coordinates) of stipple patterns within + * this window. (R) + * This field is maintained for the benifit of + * device drivers, but is often unused. + */ + int w_flags; /* A collection of flag bits: + * + * WIND_SCROLLABLE (C) + * WIND_SCROLLBARS (C) + * WIND_CAPTION (C) + * WIND_BORDER (C) + * WIND_COMMANDS (C) + * WIND_FULLSCREEN (P) + * WIND_OFFSCREEN (P) + * WIND_ISICONIC (P) + * WIND_REDRAWICON (P) + * WIND_OBSCURED (G) + * + * Note: It is an error for a client to set + * WIND_SCROLLBARS but not WIND_SCROLLABLE. + * If WIND_SCROLLABLE is set, then the client + * must fill in the pointer w_bbox; + */ + Rect w_oldArea; /* If the window has been blown up to full- + * screen size, this records its old area so + * it can be shrunk back later. (P) + */ + int w_oldDepth; /* If the window is full-screen, this records + * its old depth on the list of windows, so + * it can be put back where it came from. (P) + */ + Rect *w_bbox; /* A pointer to the bounding box of the stuff + * in this window. Used for WindView() and for + * scroll bars. (L) + * This MUST be set if WIND_SCROLLABLE is set. + */ + int w_wid; /* The window ID for this window. Windows are + * assigned small non-negative integers for + * easy reference. (R) + * Set at window creation time. + */ + ClientData w_grdata; /* Data private to the graphics package. (G) + * Often used to contain variables needed to + * interface to SUNs window package. + */ + ClientData w_backingStore; /* Specific data private to the graphics + * package. Used to save and restore the + * image under the cursor for fast redraw. + */ + char *w_iconname; /* Short name for the icon. */ + ClientData w_redrawAreas; /* List of areas that need to be redrawn. (P) + * Set by WindAreaChanged(), cleared by + * WindUpdate(). Initialized by + * WindSeparateRedisplay(). + */ +} MagWindow; + + +/* Window flags, for w->w_flags */ +#define WIND_FULLSCREEN 0x001 /* Set if the window has been blown up to + * full-screen size. + */ +#define WIND_OFFSCREEN 0x002 /* Set if the window is to be rendered off- + * screen (i.e., onto a pixmap) + */ +#define WIND_COMMANDS 0x004 /* Set if the window accepts the standard + * set of window commands + */ +#define WIND_SCROLLABLE 0x008 /* Set if the window can scroll & zoom. */ +#define WIND_SCROLLBARS 0x010 /* Set if the window has scroll bars. */ +#define WIND_CAPTION 0x020 /* Set if the window displays its own caption. */ +#define WIND_BORDER 0x040 /* Set if the window should display a border + * (includes scrollbars and caption area) + */ +#define WIND_ISICONIC 0x080 /* Set if the window is closed down to an + * icon (on Suns only) + */ +#define WIND_REDRAWICON 0x100 /* The icon needs to be redrawn. */ +#define WIND_OBSCURED 0x200 /* The window is partially or fully obscured */ + + +/* Special values for Window IDs. Some procedures that expect a Window ID will + * also accept one of these flags instead. + */ +#define WIND_UNKNOWN_WINDOW -2 /* We should pick one by looking at + * the location of the point. + */ +#define WIND_NO_WINDOW -3 /* Use NULL for the window */ + +/* utility procs & special stuff */ +extern MagWindow *WindCreate(); +extern WindClient WindGetClient(); +extern WindClient WindNextClient(); +extern WindClient WindAddClient(); +extern void WindInit(); +extern void WindUpdate(); +extern void WindDrawBorder(); +extern void WindOutToIn(); +extern void WindInToOut(); +extern void WindSetWindowAreas(); +extern void windFixSurfaceArea(); +extern int WindExecute(); +extern void WindAddCommand(); +extern int WindReplaceCommand(); +extern char **WindGetCommandTable(); +extern int windCheckOnlyWindow(MagWindow **, WindClient); + + +/* searching procs */ +extern int WindSearch(); +extern MagWindow *WindSearchWid(); +extern MagWindow *WindSearchData(); + + +/* procs for moving the surface inside of a window (changing the view) */ +extern void WindZoom(); +extern void WindMove(); +extern void WindView(); +extern void WindScroll(); + + +/* procs for moving the window itself */ +extern void WindOver(); +extern void WindUnder(); +extern void WindReframe(); +extern void WindFullScreen(); + + +/* procs to transform into and out of screen coordinates */ + +extern void WindScreenToSurface(); +extern void WindSurfaceToScreen(); +extern void WindPointToSurface(); +extern void WindPointToScreen(); +extern void WindSurfaceToScreenNoClip(); + +/* procs to change things or inform the window manager about changes */ +extern void WindCaption(); +extern void WindAreaChanged(); +extern void WindIconChanged(); +extern bool WindLoad(); +extern void WindSeparateRedisplay(); + +/* handler for window buttons in the scrollbar/zoom (non-wrapper) frame */ +extern bool WindButtonInFrame(); + +/* interface variables */ +extern int WindDefaultFlags; /* Mask of properties applied to new windows */ +extern int WindNewButtons; /* A mask of the buttons that are down now. */ +extern int WindOldButtons; /* The buttons that were down on the previous + * command. + */ +extern Point WindCommandPoint; /* The point for the current command. */ +extern bool WindAnotherUpdatePlease; /* Set by a client during redisplay if it + * discovers that more stuff needs to be + * displayed, and wants the window package + * to do another WindUpdate(). Used by + * dbwind in dbwhlRedrawFunc() when it suddenly + * discovers that drawing feedback areas + * requires that all the mask geometry be + * redrawn. + */ + +/* Macro to set the maximum number of windows */ +#define WIND_MAX_WINDOWS(x) (windMaxWindows = MIN(windMaxWindows, (x))) +extern int windMaxWindows; /* Use above macro, never increase this! */ + +/* The type of windows that we will implement. This variable must be set by + * the graphics package before WindInit() is called. + */ +extern int WindPackageType; +#define WIND_MAGIC_WINDOWS 0 +#define WIND_X_WINDOWS 1 + +/* Scroll bar width. + * May be set by the graphics package before WindInit() is called. + * If the width is XX, the window package tries to load glyphs from + * the file 'windowsXX.glyphs' located in $CAD_ROOT/magic/sys. This file + * contains the arrow for the scroll bars, and those icons should be of + * this width. + */ +extern int WindScrollBarWidth; + +/* Global identifier for the window client structure */ +extern WindClient windClientID; + +#endif /* _WINDOWS_H */ diff --git a/windows/windows11.glyphs b/windows/windows11.glyphs new file mode 100644 index 00000000..076394f5 --- /dev/null +++ b/windows/windows11.glyphs @@ -0,0 +1,74 @@ +# +# 11-pixel sized glyphs for the window package +# +# rcsid $Header: /usr/cvsroot/magic-8.0/windows/windows11.glyphs,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +# syntax of first line: size +size 5 11 11 + +#up +W W W W W W W W W W W +W W W W W K W W W W W +W W W W K K K W W W W +W W W K K K K K W W W +W W K K K K K K K W W +W K K K K K K K K K W +W W W W K K K W W W W +W W W W K K K W W W W +W W W W K K K W W W W +W W W W K K K W W W W +W W W W W W W W W W W + + +#down +W W W W W W W W W W W +W W W W K K K W W W W +W W W W K K K W W W W +W W W W K K K W W W W +W W W W K K K W W W W +W K K K K K K K K K W +W W K K K K K K K W W +W W W K K K K K W W W +W W W W K K K W W W W +W W W W W K W W W W W +W W W W W W W W W W W + +#left +W W W W W W W W W W W +W W W W W K W W W W W +W W W W K K W W W W W +W W W K K K W W W W W +W W K K K K K K K K W +W K K K K K K K K K W +W W K K K K K K K K W +W W W K K K W W W W W +W W W W K K W W W W W +W W W W W K W W W W W +W W W W W W W W W W W + +#right +W W W W W W W W W W W +W W W W W K W W W W W +W W W W W K K W W W W +W W W W W K K K W W W +W K K K K K K K K W W +W K K K K K K K K K W +W K K K K K K K K W W +W W W W W K K K W W W +W W W W W K K W W W W +W W W W W K W W W W W +W W W W W W W W W W W + +#zoom +W W W W W W W W W W W +W W W W W W W W W W W +W W K K K K K K K W W +W W K W W W W W K W W +W W K W W W W W K W W +W W K W W K W W K W W +W W K W W W W W K W W +W W K W W W W W K W W +W W K K K K K K K W W +W W W W W W W W W W W +W W W W W W W W W W W diff --git a/windows/windows14.glyphs b/windows/windows14.glyphs new file mode 100644 index 00000000..eb7fd35f --- /dev/null +++ b/windows/windows14.glyphs @@ -0,0 +1,89 @@ +# +# 14-pixel wide glyphs for the window package +# +# rcsid $Header: /usr/cvsroot/magic-8.0/windows/windows14.glyphs,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# +# + +# syntax of first line: size +size 5 14 14 + +#up +W W W W W W W W W W W W W W +W W W W W W K K W W W W W W +W W W W W K K K K W W W W W +W W W W K K K K K K W W W W +W W W K K K K K K K K W W W +W W K K K K K K K K K K W W +W K K K K K K K K K K K K W +K K K K K K K K K K K K K K +W W W W K K K K K K W W W W +W W W W K K K K K K W W W W +W W W W K K K K K K W W W W +W W W W K K K K K K W W W W +W W W W K K K K K K W W W W +W W W W W W W W W W W W W W + +#down +W W W W W W W W W W W W W W +W W W W K K K K K K W W W W +W W W W K K K K K K W W W W +W W W W K K K K K K W W W W +W W W W K K K K K K W W W W +W W W W K K K K K K W W W W +K K K K K K K K K K K K K K +W K K K K K K K K K K K K W +W W K K K K K K K K K K W W +W W W K K K K K K K K W W W +W W W W K K K K K K W W W W +W W W W W K K K K W W W W W +W W W W W W K K W W W W W W +W W W W W W W W W W W W W W + +#left +W W W W W W W K W W W W W W +W W W W W W K K W W W W W W +W W W W W K K K W W W W W W +W W W W K K K K W W W W W W +W W W K K K K K K K K K K W +W W K K K K K K K K K K K W +W K K K K K K K K K K K K W +W K K K K K K K K K K K K W +W W K K K K K K K K K K K W +W W W K K K K K K K K K K W +W W W W K K K K W W W W W W +W W W W W K K K W W W W W W +W W W W W W K K W W W W W W +W W W W W W W K W W W W W W + +#right +W W W W W W K W W W W W W W +W W W W W W K K W W W W W W +W W W W W W K K K W W W W W +W W W W W W K K K K W W W W +W K K K K K K K K K K W W W +W K K K K K K K K K K K W W +W K K K K K K K K K K K K W +W K K K K K K K K K K K K W +W K K K K K K K K K K K W W +W K K K K K K K K K K W W W +W W W W W W K K K K W W W W +W W W W W W K K K W W W W W +W W W W W W K K W W W W W W +W W W W W W K W W W W W W W + +#zoom +W W W W W W W W W W W W W W +W W W W W W W W W W W W W W +W W K K K K K K K K K K W W +W W K K K K K K K K K K W W +W W K K W W W W W W K K W W +W W K K W W W W W W K K W W +W W K K W W K K W W K K W W +W W K K W W K K W W K K W W +W W K K W W W W W W K K W W +W W K K W W W W W W K K W W +W W K K K K K K K K K K W W +W W K K K K K K K K K K W W +W W W W W W W W W W W W W W +W W W W W W W W W W W W W W diff --git a/windows/windows22.glyphs b/windows/windows22.glyphs new file mode 100644 index 00000000..cbc83883 --- /dev/null +++ b/windows/windows22.glyphs @@ -0,0 +1,128 @@ +# +# 22-pixel sized glyphs for the Window package +# +# rcsid $Header: /usr/cvsroot/magic-8.0/windows/windows22.glyphs,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +# syntax of first line: size +size 5 22 22 + +#up +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W K K W W W W W W W W W W +W W W W W W W W W K K K K W W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W K K K K K K K K W W W W W W W +W W W W W W K K K K K K K K K K W W W W W W +W W W W W K K K K K K K K K K K K W W W W W +W W W W K K K K K K K K K K K K K K W W W W +W W W K K K K K K K K K K K K K K K K W W W +W W K K K K K K K K K K K K K K K K K K W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W + +#down +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W K K K K K K K K K K K K K K K K K K W W +W W W K K K K K K K K K K K K K K K K W W W +W W W W K K K K K K K K K K K K K K W W W W +W W W W W K K K K K K K K K K K K W W W W W +W W W W W W K K K K K K K K K K W W W W W W +W W W W W W W K K K K K K K K W W W W W W W +W W W W W W W W K K K K K K W W W W W W W W +W W W W W W W W W K K K K W W W W W W W W W +W W W W W W W W W W K K W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W + +#left +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W K W W W W W W W W W W +W W W W W W W W W W K K W W W W W W W W W W +W W W W W W W W W K K K W W W W W W W W W W +W W W W W W W W K K K K W W W W W W W W W W +W W W W W W W K K K K K W W W W W W W W W W +W W W W W W K K K K K K W W W W W W W W W W +W W W W W K K K K K K K K K K K K K K K W W +W W W W K K K K K K K K K K K K K K K K W W +W W W K K K K K K K K K K K K K K K K K W W +W W W K K K K K K K K K K K K K K K K K W W +W W W W K K K K K K K K K K K K K K K K W W +W W W W W K K K K K K K K K K K K K K K W W +W W W W W W K K K K K K W W W W W W W W W W +W W W W W W W K K K K K W W W W W W W W W W +W W W W W W W W K K K K W W W W W W W W W W +W W W W W W W W W K K K W W W W W W W W W W +W W W W W W W W W W K K W W W W W W W W W W +W W W W W W W W W W W K W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W + +#right +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W K W W W W W W W W W W W +W W W W W W W W W W K K W W W W W W W W W W +W W W W W W W W W W K K K W W W W W W W W W +W W W W W W W W W W K K K K W W W W W W W W +W W W W W W W W W W K K K K K W W W W W W W +W W W W W W W W W W K K K K K K W W W W W W +W W K K K K K K K K K K K K K K K W W W W W +W W K K K K K K K K K K K K K K K K W W W W +W W K K K K K K K K K K K K K K K K K W W W +W W K K K K K K K K K K K K K K K K K W W W +W W K K K K K K K K K K K K K K K K W W W W +W W K K K K K K K K K K K K K K K W W W W W +W W W W W W W W W W K K K K K K W W W W W W +W W W W W W W W W W K K K K K W W W W W W W +W W W W W W W W W W K K K K W W W W W W W W +W W W W W W W W W W K K K W W W W W W W W W +W W W W W W W W W W K K W W W W W W W W W W +W W W W W W W W W W K W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W + +#zoom +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W K K K K K K K K K K K K K K W W W W +W W W W K K K K K K K K K K K K K K W W W W +W W W W K K W W W W W W W W W W K K W W W W +W W W W K K W W W W W W W W W W K K W W W W +W W W W K K W W W W W W W W W W K K W W W W +W W W W K K W W W W W W W W W W K K W W W W +W W W W K K W W W W K K W W W W K K W W W W +W W W W K K W W W W K K W W W W K K W W W W +W W W W K K W W W W W W W W W W K K W W W W +W W W W K K W W W W W W W W W W K K W W W W +W W W W K K W W W W W W W W W W K K W W W W +W W W W K K W W W W W W W W W W K K W W W W +W W W W K K K K K K K K K K K K K K W W W W +W W W W K K K K K K K K K K K K K K W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W +W W W W W W W W W W W W W W W W W W W W W W diff --git a/windows/windows7.glyphs b/windows/windows7.glyphs new file mode 100644 index 00000000..c0db64a2 --- /dev/null +++ b/windows/windows7.glyphs @@ -0,0 +1,54 @@ +# +# 7-pixel wide glyphs for the window package +# +# rcsid $Header: /usr/cvsroot/magic-8.0/windows/windows7.glyphs,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# +# + +# syntax of first line: size +size 5 7 7 + +#up +W W W K W W W +W W K K K W W +W K K K K K W +K K K K K K K +W W K K K W W +W W K K K W W +W W K K K W W + +#down +W W K K K W W +W W K K K W W +W W K K K W W +K K K K K K K +W K K K K K W +W W K K K W W +W W W K W W W + +#left +W W W K W W W +W W K K W W W +W K K K K K K +K K K K K K K +W K K K K K K +W W K K W W W +W W W K W W W + +#right +W W W K W W W +W W W K K W W +K K K K K K W +K K K K K K K +K K K K K K W +W W W K K W W +W W W K W W W + +#zoom +W W W W W W W +W K K K K K W +W K W W W K W +W K W K W K W +W K W W W K W +W K K K K K W +W W W W W W W diff --git a/wiring/Depend b/wiring/Depend new file mode 100644 index 00000000..876f6e3c --- /dev/null +++ b/wiring/Depend @@ -0,0 +1,13 @@ +wireOps.o: wireOps.c ../utils/magic.h ../utils/geometry.h ../tiles/tile.h \ + ../utils/hash.h ../database/database.h ../select/select.h \ + ../textio/textio.h ../windows/windows.h ../dbwind/dbwind.h ../drc/drc.h \ + ../utils/main.h ../wiring/wiring.h ../wiring/wireInt.h \ + ../textio/txcommands.h ../utils/styles.h +wireTech.o: wireTech.c ../utils/magic.h ../utils/utils.h \ + ../utils/geometry.h ../tiles/tile.h ../utils/hash.h \ + ../database/database.h ../utils/tech.h ../wiring/wiring.h \ + ../utils/malloc.h +wireUndo.o: wireUndo.c ../utils/magic.h ../utils/geometry.h \ + ../tiles/tile.h ../utils/hash.h ../database/database.h ../utils/tech.h \ + ../wiring/wiring.h ../wiring/wireInt.h ../textio/textio.h \ + ../utils/undo.h diff --git a/wiring/Makefile b/wiring/Makefile new file mode 100644 index 00000000..b921fde6 --- /dev/null +++ b/wiring/Makefile @@ -0,0 +1,10 @@ +# +# rcsid $Header: /usr/cvsroot/magic-8.0/wiring/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ +# + +MODULE = wiring +MAGICDIR = .. +SRCS = wireOps.c wireTech.c wireUndo.c + +include ${MAGICDIR}/defs.mak +include ${MAGICDIR}/rules.mak diff --git a/wiring/wireInt.h b/wiring/wireInt.h new file mode 100644 index 00000000..ed5d5b4f --- /dev/null +++ b/wiring/wireInt.h @@ -0,0 +1,39 @@ +/* + * wireInt.h -- + * + * Contains definitions for things that are used by more than + * one file in the wiring module, but aren't exported. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/wiring/wireInt.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ + */ + +#ifndef _WIREINT_H +#define _WIREINT_H + +#include "utils/magic.h" +#include "database/database.h" + +/* Undo-able wiring parameters: */ + +extern TileType WireType; +extern int WireWidth; +extern int WireLastDir; + +/* Undo procedure: */ + +extern void WireRememberForUndo(); +extern void WireUndoInit(); + +#endif /* _WIREINT_H */ diff --git a/wiring/wireOps.c b/wiring/wireOps.c new file mode 100644 index 00000000..b7464377 --- /dev/null +++ b/wiring/wireOps.c @@ -0,0 +1,916 @@ +/* + * wireOps.c -- + * + * This file contains the basic procedures that provide a wiring-style + * interface for Magic. The procedures do things like select a wiring + * material and thickness, add a leg to a wire, etc. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/wiring/wireOps.c,v 1.2 2008/09/05 13:56:25 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "select/select.h" +#include "textio/textio.h" +#include "windows/windows.h" +#include "dbwind/dbwind.h" +#include "drc/drc.h" +#include "utils/main.h" +#include "wiring/wiring.h" +#include "wiring/wireInt.h" +#include "textio/txcommands.h" +#include "utils/styles.h" + +/* The following variables define the state of the wiring interface. */ + +TileType WireType = TT_SELECTBASE-1; /* Type of material currently selected + * for wiring. + */ +int WireWidth; /* Thickness of material to use for wiring. */ +int WireLastDir; /* Last direction in which a wire was run. */ + +/* The following variable is used to communicate the desired root cellDef + * between wireFindRootUse and wireFindRootFunc. + */ + +static CellDef *wireDesiredDef; + +/* + * ---------------------------------------------------------------------------- + * wireFindRootUse -- + * + * This is a utility procedure to find a window containing a particular + * definition as its root. + * + * Results: + * The return value is the root use of a window, such that the + * use is an instance of rootDef. If the definition isn't the + * root of any window then NULL is returned. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +CellUse * +wireFindRootUse(rootDef) + CellDef *rootDef; /* Root definition for which a root use + * is desired. + */ +{ + CellUse *result; + extern int wireFindRootFunc(); + + result = NULL; + wireDesiredDef = rootDef; + (void) WindSearch(DBWclientID, (ClientData) NULL, (Rect *) NULL, + wireFindRootFunc, (ClientData) &result); + return result; +} + +/* The following search function is called for each window. If the + * window's root is wireDesiredDef, then cellUsePtr is filled in + * with the window's root cellUse (and the search is aborted). + */ + +int +wireFindRootFunc(window, cellUsePtr) + MagWindow *window; /* A layout window. */ + CellUse **cellUsePtr; /* Pointer to cellUse pointer. */ +{ + CellUse *use; + + use = (CellUse *) window->w_surfaceID; + if (use->cu_def != wireDesiredDef) return 0; + *cellUsePtr = use; + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * WirePickType -- + * + * This procedure establishes a new material for future wiring, and + * terminates any wires in progress. + * + * Results: + * None. + * + * Side effects: + * The current wire type and width are modified. If type is + * less than zero, then a new type and width are picked based + * on what's under the cursor, and this piece is also selected + * as a chunk. Otherwise, the parameters determine the new + * type and width. + * ---------------------------------------------------------------------------- + */ + +void +WirePickType(type, width) + TileType type; /* New type of material to use for wiring. + * If less than zero, then pick a new type + * based on what's underneath the cursor. + */ + int width; /* Width to use for future wiring. If type + * is less than zero then this parameter is + * ignored and the width of the material + * underneath the cursor is used. + */ +{ + MagWindow *w; + Point point; + Rect chunk, box; + SearchContext scx; + DBWclientRec *crec; + TileTypeBitMask mask; + int height; + + if (type >= 0) + { + WireType = type; + WireWidth = width; + WireLastDir = -1; + WireRememberForUndo(); + return; + } + + /* Find what layers are visible underneath the point. Pick one of + * them as the material to select. If there are several, cycle + * through them one at a time, starting from the last selected type + * so each type gets a chance. + */ + + w = ToolGetPoint(&point, &scx.scx_area); + if (w == NULL) + { + TxError("Can't use cursor to select wiring material unless\n"); + TxError(" cursor is in a layout window.\n"); + return; + } + scx.scx_use = (CellUse *) w->w_surfaceID; + scx.scx_trans = GeoIdentityTransform; + crec = (DBWclientRec *) w->w_clientData; + DBSeeTypesAll(scx.scx_use, &scx.scx_area, crec->dbw_bitmask, &mask); + TTMaskAndMask(&mask, &crec->dbw_visibleLayers); + TTMaskAndMask(&mask, &DBAllButSpaceAndDRCBits); + if (TTMaskIsZero(&mask)) + { + TxError("There's no material visible underneath the cursor.\n"); + return; + } + for (WireType += 1; ; WireType += 1) + { + if (WireType >= DBNumUserLayers) + WireType = TT_SELECTBASE; + if (TTMaskHasType(&mask, WireType)) break; + } + + /* Now select a chunk underneath the cursor of the particular type. */ + + SelectClear(); + SelectChunk(&scx, WireType, crec->dbw_bitmask, &chunk, FALSE); + WireWidth = chunk.r_xtop - chunk.r_xbot; + height = chunk.r_ytop - chunk.r_ybot; + if (height < WireWidth) WireWidth = height; + + /* Set the box and the selection to a square chunk that indicates the + * wire width. + */ + + if (WireWidth & 1) + { + GEO_EXPAND(&scx.scx_area, WireWidth/2, &box); + } + else + { + box.r_xbot = point.p_x - WireWidth/2; + box.r_ybot = point.p_y - WireWidth/2; + box.r_xtop = box.r_xbot + WireWidth; + box.r_ytop = box.r_ybot + WireWidth; + } + if (box.r_xbot < chunk.r_xbot) + { + box.r_xbot = chunk.r_xbot; + box.r_xtop = box.r_xbot + WireWidth; + } + if (box.r_ybot < chunk.r_ybot) + { + box.r_ybot = chunk.r_ybot; + box.r_ytop = box.r_ybot + WireWidth; + } + if (box.r_xtop > chunk.r_xtop) + { + box.r_xtop = chunk.r_xtop; + box.r_xbot = box.r_xtop - WireWidth; + } + if (box.r_ytop > chunk.r_ytop) + { + box.r_ytop = chunk.r_ytop; + box.r_ybot = box.r_ytop - WireWidth; + } + SelectClear(); + scx.scx_area = box; + TTMaskSetOnlyType(&mask, WireType); + SelectArea(&scx, &mask, crec->dbw_bitmask); + DBWSetBox(scx.scx_use->cu_def, &box); + TxPrintf("Using %s wires %d units wide.\n", + DBTypeLongName(WireType), WireWidth); + + WireLastDir = -1; + WireRememberForUndo(); +} + +/* + * ---------------------------------------------------------------------------- + * WireGetWidth, WireGetType -- + * + * Two routines used to query the internal values of the wiring + * mechanism. + * + * ---------------------------------------------------------------------------- + */ + +int +WireGetWidth() +{ + return WireWidth; +} + +TileType +WireGetType() +{ + return WireType; +} + +/* + * ---------------------------------------------------------------------------- + * WireAddLeg -- + * + * This procedure adds a new leg to the current wire in the current + * wiring material (set by WirePickType). The new leg will abut rect + * and extend to either point's x-coordinate or its y-coordinate, + * whichever results in a longer wire. Direction can be used to + * force the wire to run in a particular direction. + * + * Results: + * None. + * + * Side effects: + * The edit cell is modified to contain more material. + * ---------------------------------------------------------------------------- + */ + +void +WireAddLeg(rect, point, direction) + Rect *rect; /* Describes the current (last-painted) leg + * of the wire, in root coordinates. If NULL, + * then the box is used for this. + */ + Point *point; /* Describes where to paint the wire to, in + * root coordinates. If NULL, then the cursor + * location is used as the point. + */ + int direction; /* Which direction to run the wire, in root + * coords. If WIRE_CHOOSE, then pick a + * direction based on point. If WIRE_VERTICAL + * or WIRE_HORIZONTAL, then run the wire in + * the indicated direction. + */ +{ + Rect current, new, leg, editArea; + CellDef *boxRootDef; + SearchContext scx; + Point cursorPos; + TileTypeBitMask mask; + + if (WireType == 0) + { + TxError("Can't add a new wire leg: no wiring material selected.\n"); + return; + } + + /* If rect isn't supplied, use the box. */ + + if (rect == NULL) + { + rect = ¤t; + if (!ToolGetBox(&boxRootDef, rect)) + { + TxError("No box! Before wiring a leg, you must set the box\n"); + TxError(" to indicate where the leg starts.\n"); + return; + } + if (boxRootDef != EditRootDef) + { + TxError("The box must be on the edit cell so it can be used\n"); + TxError(" as the starting point for a wire leg.\n"); + return; + } + } + + /* If no point is supplied, read it from the cursor location. */ + + if (point == NULL) + { + MagWindow *w; + w = ToolGetPoint(&cursorPos, (Rect *) NULL); + if ((w == NULL) || + (((CellUse *) w->w_surfaceID)->cu_def != EditRootDef)) + { + TxError("Before wiring, must place cursor over edit cell to\n"); + TxError(" indicate endpoint of new wire leg.\n"); + return; + } + point = &cursorPos; + } + + /* If the caller didn't provide a direction, then pick the opposite + * direction (if this isn't the first leg of the wire), or pick + * the direction that results in the largest amount of wiring (if + * this is the first leg). + */ + + if (direction == WIRE_CHOOSE) + { + int delx, dely; + delx = point->p_x - rect->r_xtop; + if (delx < 0) + { + delx = rect->r_xbot - point->p_x; + if (delx < 0) delx = 0; + } + dely = point->p_y - rect->r_ytop; + if (dely < 0) + { + dely = rect->r_ybot - point->p_y; + if (dely < 0) dely = 0; + } + if (delx > dely) direction = WIRE_HORIZONTAL; + else direction = WIRE_VERTICAL; + } + + /* Now compute the area to paint. */ + + if (direction == WIRE_HORIZONTAL) + { + /* The new leg will be horizontal. First compute its span in + * x, then its span in y. + */ + + if (point->p_x > rect->r_xtop) + { + new.r_xbot = rect->r_xtop; + new.r_xtop = point->p_x; + WireLastDir = GEO_EAST; + } + else if (point->p_x < rect->r_xbot) + { + new.r_xtop = rect->r_xbot; + new.r_xbot = point->p_x; + WireLastDir = GEO_WEST; + } + else return; /* Nothing to paint! */ + + /* Hook the segment up to the nearest point along the box + * to where we are. Usually the box is exactly as wide as + * the wires so there's no real choice. + */ + + new.r_ybot = point->p_y - WireWidth/2; + if (new.r_ybot < rect->r_ybot) + new.r_ybot = rect->r_ybot; + else if (new.r_ybot > rect->r_ytop - WireWidth) + new.r_ybot = rect->r_ytop - WireWidth; + new.r_ytop = new.r_ybot + WireWidth; + } + else + { + /* The new wire segment is vertical. See comments above (this + * code is just like what's up there). + */ + + if (point->p_y > rect->r_ytop) + { + new.r_ybot = rect->r_ytop; + new.r_ytop = point->p_y; + WireLastDir = GEO_NORTH; + } + else if (point->p_y < rect->r_ybot) + { + new.r_ytop = rect->r_ybot; + new.r_ybot = point->p_y; + WireLastDir = GEO_SOUTH; + } + else return; /* Nothing to paint! */ + + new.r_xbot = point->p_x - WireWidth/2; + if (new.r_xbot < rect->r_xbot) + new.r_xbot = rect->r_xbot; + if (new.r_xbot > rect->r_xtop - WireWidth) + new.r_xbot = rect->r_xtop - WireWidth; + new.r_xtop = new.r_xbot + WireWidth; + } + + /* Paint the new leg and select it. */ + + GeoTransRect(&RootToEditTransform, &new, &editArea); + TTMaskSetOnlyType(&mask, WireType); + DBPaintValid(EditCellUse->cu_def, &editArea, &mask, 0); + DBAdjustLabels(EditCellUse->cu_def, &editArea); + DBWAreaChanged(EditCellUse->cu_def, &editArea, DBW_ALLWINDOWS, &mask); + DRCCheckThis(EditCellUse->cu_def, TT_CHECKPAINT, &editArea); + DBReComputeBbox(EditCellUse->cu_def); + + /* Select the new wire leg, if the edit cell is visible in any + * windows. + */ + + scx.scx_use = wireFindRootUse(EditRootDef); + if (scx.scx_use != NULL) + { + SelectClear(); + scx.scx_area = new; + scx.scx_trans = GeoIdentityTransform; + SelectChunk(&scx, WireType, 0, &leg, FALSE); + } + + /* Make the box a square at the tip of the new are just painted. */ + + switch (WireLastDir) + { + case GEO_NORTH: + if (leg.r_ybot < new.r_ybot) + new.r_ybot = leg.r_ybot; + if ((new.r_ytop - new.r_ybot) > WireWidth) + new.r_ybot = new.r_ytop - WireWidth; + break; + case GEO_SOUTH: + if (leg.r_ytop > new.r_ytop) + new.r_ytop = leg.r_ytop; + if ((new.r_ytop - new.r_ybot) > WireWidth) + new.r_ytop = new.r_ybot + WireWidth; + break; + case GEO_EAST: + if (leg.r_xbot < new.r_xbot) + new.r_xbot = leg.r_xbot; + if ((new.r_xtop - new.r_xbot) > WireWidth) + new.r_xbot = new.r_xtop - WireWidth; + break; + case GEO_WEST: + if (leg.r_xtop > new.r_xtop) + new.r_xtop = leg.r_xtop; + if ((new.r_xtop - new.r_xbot) > WireWidth) + new.r_xtop = new.r_xbot + WireWidth; + break; + } + DBWSetBox(EditRootDef, &new); + WireRememberForUndo(); +} + +/* + * ---------------------------------------------------------------------------- + * WireShowLeg -- + * + * This procedure adds a new leg to the current wire in the current + * wiring material (set by WirePickType). Unlike WireAddLeg(), the + * wire is painted into the selection def, not the edit def. This + * allows the selection to be updated with cursor movement, showing + * where magic is going to place the next wire leg. + * Also, we do not print error messages, as this function may be + * called several times per second. + * + * Results: + * None. + * + * Side effects: + * The selection cell is cleared and painted. + * ---------------------------------------------------------------------------- + */ + +void +WireShowLeg() +{ + Rect current, new, leg, editArea, *rect = ¤t; + CellDef *boxRootDef; + SearchContext scx; + Point cursorPos, *point = &cursorPos; + TileTypeBitMask mask; + int direction = WIRE_CHOOSE; + int delx, dely; + MagWindow *w; + + if (WireType == 0) return; + + /* get the cursor box position. */ + + rect = ¤t; + if (!ToolGetBox(&boxRootDef, rect)) return; + if (boxRootDef != EditRootDef) return; + + /* get the cursor location. */ + + w = ToolGetPoint(&cursorPos, (Rect *) NULL); + if ((w == NULL) || + (((CellUse *) w->w_surfaceID)->cu_def != EditRootDef)) + return; + + /* Pick the opposite direction (if this isn't the first leg of the + * wire), or pick the direction that results in the largest amount + * of wiring (if this is the first leg). + */ + + delx = point->p_x - rect->r_xtop; + if (delx < 0) + { + delx = rect->r_xbot - point->p_x; + if (delx < 0) delx = 0; + } + dely = point->p_y - rect->r_ytop; + if (dely < 0) + { + dely = rect->r_ybot - point->p_y; + if (dely < 0) dely = 0; + } + if (delx > dely) direction = WIRE_HORIZONTAL; + else direction = WIRE_VERTICAL; + + /* Now compute the area to paint. */ + + if (direction == WIRE_HORIZONTAL) + { + /* The new leg will be horizontal. First compute its span in + * x, then its span in y. + */ + + if (point->p_x > rect->r_xtop) + { + new.r_xbot = rect->r_xtop; + new.r_xtop = point->p_x; + WireLastDir = GEO_EAST; + } + else if (point->p_x < rect->r_xbot) + { + new.r_xtop = rect->r_xbot; + new.r_xbot = point->p_x; + WireLastDir = GEO_WEST; + } + else return; /* Nothing to paint! */ + + /* Hook the segment up to the nearest point along the box + * to where we are. Usually the box is exactly as wide as + * the wires so there's no real choice. + */ + + new.r_ybot = point->p_y - WireWidth/2; + if (new.r_ybot < rect->r_ybot) + new.r_ybot = rect->r_ybot; + else if (new.r_ybot > rect->r_ytop - WireWidth) + new.r_ybot = rect->r_ytop - WireWidth; + new.r_ytop = new.r_ybot + WireWidth; + } + else + { + /* The new wire segment is vertical. See comments above (this + * code is just like what's up there). + */ + + if (point->p_y > rect->r_ytop) + { + new.r_ybot = rect->r_ytop; + new.r_ytop = point->p_y; + WireLastDir = GEO_NORTH; + } + else if (point->p_y < rect->r_ybot) + { + new.r_ytop = rect->r_ybot; + new.r_ybot = point->p_y; + WireLastDir = GEO_SOUTH; + } + else return; /* Nothing to paint! */ + + new.r_xbot = point->p_x - WireWidth/2; + if (new.r_xbot < rect->r_xbot) + new.r_xbot = rect->r_xbot; + if (new.r_xbot > rect->r_xtop - WireWidth) + new.r_xbot = rect->r_xtop - WireWidth; + new.r_xtop = new.r_xbot + WireWidth; + } + + /* Clear any old selection. Ignore the Undo mechanism so */ + /* we don't continuously record uncommitted routes. */ + + UndoDisable(); + SelectClear(); + + /* Paint the new leg into the selection box. */ + + TTMaskSetOnlyType(&mask, WireType); + DBPaintValid(SelectDef, &new, &mask, 0); + DBAdjustLabels(SelectDef, &new); + DBWAreaChanged(SelectDef, &new, DBW_ALLWINDOWS, &mask); + DBReComputeBbox(SelectDef); + DBWHLRedraw(SelectRootDef, &new, TRUE); + DBWAreaChanged(SelectDef, &SelectDef->cd_bbox, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + UndoEnable(); +} + +/* + * ---------------------------------------------------------------------------- + * WireAddContact -- + * + * This procedure places a contact at the end of the current wire + * leg in order to switch layers, and records a new routing layer + * and width. + * + * Results: + * None. + * + * Side effects: + * A contact is placed, and the current wire type and width are + * modified. The contact type is chosen based on information + * from the technology file and the new and old routing layers. + * ---------------------------------------------------------------------------- + */ + +void +WireAddContact(newType, newWidth) + TileType newType; /* New type of material to use for wiring. + * If less than zero, pick a new type based + * on what's underneath the cursor. + */ + int newWidth; /* New width to use for future wiring. If + * newType is less than zero, then this + * parameter is ignored and the width of + * the material underneath the cursor is + * used. + */ +{ + Rect oldLeg, contactArea, tmp, tmp2, editArea; + CellDef *boxRootDef; + TileType oldType; + TileTypeBitMask mask, allmask; + int oldOverlap, newOverlap, i, totalSize, oldDir; + Contact *contact; + SearchContext scx; + + /* First of all, find out the location of the last wire leg, + * which is marked by the box. + */ + + if (!ToolGetBox(&boxRootDef, &oldLeg)) + { + TxError("No box! To place a contact, you must first use\n"); + TxError(" the box to mark the previous leg of the wire,\n"); + TxError(" at the end of which the contact will be placed.\n"); + return; + } + if (boxRootDef != EditRootDef) + { + TxError("The box must be on the edit cell; it marks the wire\n"); + TxError(" leg at the end of which a contact will be placed.\n"); + return; + } + + oldType = WireType; + oldDir = WireLastDir; + + /* Now find a new type and width. If the type is the same, then + * there's no need to add a contact. + */ + + WirePickType(newType, newWidth); + if (WireType == oldType) + { + TxError("The new wiring layer is the same as the old one, so\n"); + TxError(" there's no need for a contact.\n"); + return; + } + + /* Choose a contact type. */ + + for (contact = WireContacts; contact != NULL; contact = contact->con_next) + { + if ((contact->con_layer1 == oldType) && + (contact->con_layer2 == WireType)) + { + oldOverlap = contact->con_surround1; + newOverlap = contact->con_surround2; + goto gotContact; + } + if ((contact->con_layer2 == oldType) && + (contact->con_layer1 == WireType)) + { + oldOverlap = contact->con_surround2; + newOverlap = contact->con_surround1; + goto gotContact; + } + } + TxError("Sorry, but the technology file doesn't define a contact\n"); + TxError(" between \"%s\" and \"%s\".\n", DBTypeLongName(oldType), + DBTypeLongName(WireType)); + return; + + /* Compute the contact's bounding box, including surrounds. The idea here + * is to center the contact at the end of the leg. With the edge of + * the surround corresponding to the old layer just lining up with + * the end of the leg. The contact may have to be wider than the leg. + * However, if the wire is very wide, make the contact so it won't + * extend past the edge of the wire. + */ + + gotContact: + totalSize = contact->con_size + 2*oldOverlap; + contactArea = oldLeg; + if ((contactArea.r_xtop - contactArea.r_xbot) < totalSize) + { + contactArea.r_xbot -= (totalSize - (contactArea.r_xtop + - contactArea.r_xbot))/2; + contactArea.r_xtop = contactArea.r_xbot + totalSize; + } + if ((contactArea.r_ytop - contactArea.r_ybot) < totalSize) + { + contactArea.r_ybot -= (totalSize - (contactArea.r_ytop + - contactArea.r_ybot))/2; + contactArea.r_ytop = contactArea.r_ybot + totalSize; + } + + switch (oldDir) + { + case GEO_NORTH: + i = contactArea.r_ytop - totalSize; + if (i > contactArea.r_ybot) + contactArea.r_ybot = i; + break; + case GEO_SOUTH: + i = contactArea.r_ybot + totalSize; + if (i < contactArea.r_ytop) + contactArea.r_ytop = i; + break; + case GEO_EAST: + i = contactArea.r_xtop - totalSize; + if (i > contactArea.r_xbot) + contactArea.r_xbot = i; + break; + case GEO_WEST: + i = contactArea.r_xbot + totalSize; + if (i < contactArea.r_xtop) + contactArea.r_xtop = i; + break; + } + + /* Paint the contact and its surrounding areas. */ + + GeoTransRect(&RootToEditTransform, &contactArea, &editArea); + GEO_EXPAND(&editArea, -oldOverlap, &tmp); + TTMaskSetOnlyType(&mask, contact->con_type); + TTMaskSetOnlyType(&allmask, contact->con_type); + DBPaintValid(EditCellUse->cu_def, &tmp, &mask, 0); + if (contact->con_surround1 != 0) + { + TTMaskSetOnlyType(&mask, contact->con_layer1); + TTMaskSetType(&allmask, contact->con_layer1); + GEO_EXPAND(&tmp, contact->con_surround1, &tmp2); + (void) GeoInclude(&tmp2, &editArea); + DBPaintValid(EditCellUse->cu_def, &tmp2, &mask, 0); + } + if (contact->con_surround2 != 0) + { + TTMaskSetOnlyType(&mask, contact->con_layer2); + TTMaskSetType(&allmask, contact->con_layer2); + GEO_EXPAND(&tmp, contact->con_surround2, &tmp2); + (void) GeoInclude(&tmp2, &editArea); + DBPaintValid(EditCellUse->cu_def, &tmp2, &mask, 0); + } + + DBAdjustLabels(EditCellUse->cu_def, &editArea); + DBWAreaChanged(EditCellUse->cu_def, &editArea, DBW_ALLWINDOWS, &allmask); + DRCCheckThis(EditCellUse->cu_def, TT_CHECKPAINT, &editArea); + DBReComputeBbox(EditCellUse->cu_def); + + /* Select the contact and its surrounds, if the edit cell is + * in a window. + */ + + SelectClear(); + scx.scx_use = wireFindRootUse(EditRootDef); + if (scx.scx_use != NULL) + { + scx.scx_trans = GeoIdentityTransform; + GEO_EXPAND(&contactArea, -oldOverlap, &tmp); + scx.scx_area = tmp; + TTMaskSetOnlyType(&mask, contact->con_type); + SelectArea(&scx, &mask, 0); + if (contact->con_surround1 != 0) + { + GEO_EXPAND(&tmp, contact->con_surround1, &scx.scx_area); + TTMaskSetOnlyType(&mask, contact->con_layer1); + SelectArea(&scx, &mask, 0); + } + if (contact->con_surround2 != 0) + { + GEO_EXPAND(&tmp, contact->con_surround2, &scx.scx_area); + TTMaskSetOnlyType(&mask, contact->con_layer2); + SelectArea(&scx, &mask, 0); + } + } + + /* Place the box over the overlap area of the new routing material. */ + + GEO_EXPAND(&tmp, newOverlap, &tmp2); + DBWSetBox(EditRootDef, &tmp2); +} + +/* + * ---------------------------------------------------------------------------- + * + * WireButtonProc -- + * + * This procedure implements a button-based wiring interface. It + * is registered as a client of the dbwind button manager and is + * called automatically by dbwind when buttons are pushed and this + * handler is the active one. + * + * Results: + * None. + * + * Side effects: + * Left button: same as ":wire type" (pick wiring layer and width) + * Right button: same as ":wire leg" (add a new leg to the wire) + * Middle button: same as ":wire switch" (place contact to new layer) + * + * ---------------------------------------------------------------------------- + */ + +void +WireButtonProc(w, cmd) + MagWindow *w; /* Window in which button was pushed. */ + TxCommand *cmd; /* Describes exactly what happened. */ +{ + /* We do commands on the down-pushes and ignore the releases. */ + + if (cmd->tx_buttonAction != TX_BUTTON_DOWN) + return; + + switch (cmd->tx_button) + { + case TX_LEFT_BUTTON: + WirePickType(-1, 0); + break; + case TX_RIGHT_BUTTON: + WireAddLeg((Rect *) NULL, (Point *) NULL, WIRE_CHOOSE); + break; + case TX_MIDDLE_BUTTON: + WireAddContact(-1, 0); + break; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * WireInit -- + * + * This procedure is called when Magic starts up to initialize + * the wiring module. + * + * Results: + * None. + * + * Side effects: + * Registers various things with various managers. + * + * ---------------------------------------------------------------------------- + */ + +void +WireInit() +{ + static char *doc = +"You are currently using the \"wiring\" tool. The button actions are:\n\ + left - pick a wiring layer and width (same as \":wire type\")\n\ + right - add a leg to the wire (same as \":wire leg\")\n\ + middle - place a contact to switch layers (same as \":wire switch\")\n"; + + WireUndoInit(); + DBWAddButtonHandler("wiring", WireButtonProc, STYLE_CURS_ARROW, doc); +} diff --git a/wiring/wireTech.c b/wiring/wireTech.c new file mode 100644 index 00000000..5c8af8d9 --- /dev/null +++ b/wiring/wireTech.c @@ -0,0 +1,205 @@ +/* + * wireTech.c -- + * + * This file contains procedures that parse the wiring sections of + * technology files. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/wiring/wireTech.c,v 1.2 2009/05/13 15:03:19 tim Exp $"; +#endif /* not lint */ + +#include +#include +#include + +#include "utils/magic.h" +#include "utils/utils.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/tech.h" +#include "wiring/wiring.h" +#include "utils/malloc.h" + +/* Linked list to store contact information collected by this module: */ +Contact *WireContacts; + + +/* + * ---------------------------------------------------------------------------- + * WireTechInit -- + * + * Called once at beginning of technology file read-in to initialize + * data structures. + * + * Results: + * None. + * + * Side effects: + * Clears out the contact table. + * ---------------------------------------------------------------------------- + */ + +void +WireTechInit() +{ + Contact *contact; + int i; + + while (WireContacts != NULL) + { + freeMagic((char *) WireContacts); + WireContacts = WireContacts->con_next; + } +} + +/* + * ---------------------------------------------------------------------------- + * WireTechLine -- + * + * This procedure is invoked by the technology module once for + * each line in the "wiring" section of the technology file. + * + * Results: + * Always returns TRUE (otherwise the technology module would + * abort Magic with a fatal error). + * + * Side effects: + * Builds up the contact table, prints error messages if necessary. + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +bool +WireTechLine(sectionName, argc, argv) + char *sectionName; /* Name of this section (unused). */ + int argc; /* Number of arguments on line. */ + char *argv[]; /* Pointers to fields of line. */ +{ + Contact *new; + + if (strcmp(argv[0], "contact") != 0) + { + TechError("Unknown wiring keyword: %s. Line ignored.\n", argv[0]); + return TRUE; + } + if (argc != 7) + { + TechError("\"contact\" lines must have exactly 7 arguments.\n"); + return TRUE; + } + + new = (Contact *) mallocMagic(sizeof(Contact)); + new->con_type = DBTechNoisyNameType(argv[1]); + new->con_layer1 = DBTechNoisyNameType(argv[3]); + new->con_layer2 = DBTechNoisyNameType(argv[5]); + if ((new->con_type < 0) || (new->con_layer1 < 0) || (new->con_layer2 < 0)) + { + errorReturn: + freeMagic((char *) new); + return TRUE; + } + + if (!StrIsInt(argv[2])) + { + TechError("3rd field must be an integer.\n"); + goto errorReturn; + } + else new->con_size = atoi(argv[2]); + if (!StrIsInt(argv[4])) + { + TechError("5th field must be an integer.\n"); + goto errorReturn; + } + else new->con_surround1 = atoi(argv[4]); + if (!StrIsInt(argv[6])) + { + TechError("6th field must be an integer.\n"); + goto errorReturn; + } + else new->con_surround2 = atoi(argv[6]); + + new->con_next = WireContacts; + WireContacts = new; + + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * WireTechFinal -- + * + * This procedure is called by the technology module after all the + * lines of the tech file have been read. It doesn't do anything + * right now. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +WireTechFinal() +{ + /* Debugging code to print info about layers: */ + +/* + Contact *con; + + for (con = WireContacts; con != NULL; con = con->con_next) + { + TxPrintf("Contact type \"%s\", size %d connects\n", + DBTypeLongName(con->con_type), con->con_size); + TxPrintf(" \"%s\" (overlap %d) and\n", + DBTypeLongName(con->con_layer1), con->con_surround1); + TxPrintf(" \"%s\" (overlap %d)\n", + DBTypeLongName(con->con_layer2), con->con_surround2); + } +*/ +} + +/* + *---------------------------------------------------------------------------- + * WireTechScale -- + * + * Change parameters of the wiring section as required when + * redefining magic's internal grid relative to the technology lambda. + * + *---------------------------------------------------------------------------- + */ + +void +WireTechScale(scalen, scaled) + int scalen, scaled; +{ + Contact *con; + + for (con = WireContacts; con != NULL; con = con->con_next) + { + con->con_size *= scaled; + con->con_size /= scalen; + + con->con_surround1 *= scaled; + con->con_surround1 /= scalen; + + con->con_surround2 *= scaled; + con->con_surround2 /= scalen; + } +} diff --git a/wiring/wireTech.c.new b/wiring/wireTech.c.new new file mode 100644 index 00000000..4c69735e --- /dev/null +++ b/wiring/wireTech.c.new @@ -0,0 +1,204 @@ +/* + * wireTech.c -- + * + * This file contains procedures that parse the wiring sections of + * technology files. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[]="$Header: /usr/cvsroot/magic-8.0/wiring/wireTech.c.new,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "tech/tech.h" +#include "wiring/wiring.h" +#include "utils/malloc.h" + +/* Linked list to store contact information collected by this module: */ +Contact *WireContacts; + + +/* + * ---------------------------------------------------------------------------- + * WireTechInit -- + * + * Called once at beginning of technology file read-in to initialize + * data structures. + * + * Results: + * None. + * + * Side effects: + * Clears out the contact table. + * ---------------------------------------------------------------------------- + */ + +void +WireTechInit() +{ + Contact *contact; + int i; + + while (WireContacts != NULL) + { + freeMagic((char *) WireContacts); + WireContacts = WireContacts->con_next; + } +} + +/* + * ---------------------------------------------------------------------------- + * WireTechLine -- + * + * This procedure is invoked by the technology module once for + * each line in the "wiring" section of the technology file. + * + * Results: + * Always returns TRUE (otherwise the technology module would + * abort Magic with a fatal error). + * + * Side effects: + * Builds up the contact table, prints error messages if necessary. + * ---------------------------------------------------------------------------- + */ + + /* ARGSUSED */ +bool +WireTechLine(sectionName, argc, argv) + char *sectionName; /* Name of this section (unused). */ + int argc; /* Number of arguments on line. */ + char *argv[]; /* Pointers to fields of line. */ +{ + Contact *new; + + if (strcmp(argv[0], "contact") != 0) + { + TechError("Unknown wiring keyword: %s. Line ignored.\n", argv[0]); + return TRUE; + } + if (argc != 7) + { + TechError("\"contact\" lines must have exactly 7 arguments.\n"); + return TRUE; + } + + new = (Contact *) mallocMagic(sizeof(Contact)); + new->con_type = DBTechNoisyNameType(argv[1]); + new->con_layer1 = DBTechNoisyNameType(argv[3]); + new->con_layer2 = DBTechNoisyNameType(argv[5]); + if ((new->con_type < 0) || (new->con_layer1 < 0) || (new->con_layer2 < 0)) + { + errorReturn: + freeMagic((char *) new); + return TRUE; + } + + if (!StrIsInt(argv[2])) + { + TechError("3rd field must be an integer.\n"); + goto errorReturn; + } + else new->con_size = atoi(argv[2]); + if (!StrIsInt(argv[4])) + { + TechError("5th field must be an integer.\n"); + goto errorReturn; + } + else new->con_surround1 = atoi(argv[4]); + if (!StrIsInt(argv[6])) + { + TechError("6th field must be an integer.\n"); + goto errorReturn; + } + else new->con_surround2 = atoi(argv[6]); + + new->con_next = WireContacts; + WireContacts = new; + + return TRUE; +} + +/* + * ---------------------------------------------------------------------------- + * WireTechFinal -- + * + * This procedure is called by the technology module after all the + * lines of the tech file have been read. It doesn't do anything + * right now. + * + * Results: + * None. + * + * Side effects: + * None. + * ---------------------------------------------------------------------------- + */ + +void +WireTechFinal() +{ + /* Debugging code to print info about layers: */ + +/* + Contact *con; + + for (con = WireContacts; con != NULL; con = con->con_next) + { + TxPrintf("Contact type \"%s\", size %d connects\n", + DBTypeLongName(con->con_type), con->con_size); + TxPrintf(" \"%s\" (overlap %d) and\n", + DBTypeLongName(con->con_layer1), con->con_surround1); + TxPrintf(" \"%s\" (overlap %d)\n", + DBTypeLongName(con->con_layer2), con->con_surround2); + } +*/ +} + +/* + *---------------------------------------------------------------------------- + * WireTechScale -- + * + * Change parameters of the wiring section as required when + * redefining magic's internal grid relative to the technology lambda. + * + *---------------------------------------------------------------------------- + */ + +int +WireTechScale(scalen, scaled) + int scalen, scaled; +{ + Contact *con; + + for (con = WireContacts; con != NULL; con = con->con_next) + { + con->con_size *= scalen; + con->con_size /= scaled; + + con->con_surround1 *= scalen; + con->con_surround1 /= scaled; + + con->con_surround2 *= scalen; + con->con_surround2 /= scaled; + } +} + diff --git a/wiring/wireUndo.c b/wiring/wireUndo.c new file mode 100644 index 00000000..75173110 --- /dev/null +++ b/wiring/wireUndo.c @@ -0,0 +1,162 @@ +/* + * wireUndo.c -- + * + * This file contains procedures that implement undo for wiring procedures + * such as setting the current wire width. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/wiring/wireUndo.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; +#endif /* not lint */ + +#include + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "utils/tech.h" +#include "wiring/wiring.h" +#include "wiring/wireInt.h" +#include "textio/textio.h" +#include "utils/undo.h" + +/* The following declaration is for records used to hold undo + * information for wiring commands such as changing the current + * layer. Only the wire-module-specific stuff needs to be undone + * here: other stuff, such as selecting the current wire leg + * and actually painting the wires, is undone in other modules. + */ + +typedef struct +{ + TileType wue_oldType; /* Previous type of wiring material. */ + TileType wue_newType; /* New type of wiring material. */ + int wue_oldWidth; /* Previous width of wiring material. */ + int wue_newWidth; /* New width of wiring material. */ + int wue_oldDir; /* Previous direction for wiring. */ + int wue_newDir; /* New direction for wiring. */ +} WireUndoEvent; + +/* Identifier for wiring undo records. */ + +UndoType WireUndoClientID; + +/* The following statics are used to remember the last values for the + * wiring variables that were remembered by the undo package, so we + * know what the values USED to be before the current round of changes. + */ + +static TileType wireOldType = TT_SPACE; /* Last type that we remembered. */ +static int wireOldWidth = 2; /* Last width that we remembered. */ +static int wireOldDir = GEO_NORTH; /* Last direction */ + + +/* + * ---------------------------------------------------------------------------- + * WireUndoInit -- + * + * Adds us as a client to the undo package. + * + * Results: + * None. + * + * Side effects: + * Adds a new client to the undo package, and sets WireUndoClientID. + * ---------------------------------------------------------------------------- + */ + +void +WireUndoInit() +{ + extern void WireUndoForw(), WireUndoBack(); + + WireUndoClientID = UndoAddClient((void (*)()) NULL, (void (*)()) NULL, + (UndoEvent *(*)()) NULL, (int (*)()) NULL, WireUndoForw, + WireUndoBack, "wiring parameters"); + if (WireUndoClientID < (UndoType) 0) + TxError("Couldn't add wiring as an undo client!\n"); +} + +/* + * ---------------------------------------------------------------------------- + * WireRememberForUndo -- + * + * Whenever anybody in the wiring module changes the wiring parameters + * (the static variables declared at the beginning of wireOps.c), + * they're supposed to call this routine just after the changes so + * that we can record information for undoing. + * + * Results: + * None. + * + * Side effects: + * Adds information to the undo list. The stuff that's remembered + * is just exactly the stuff defined + * ---------------------------------------------------------------------------- + */ + +void +WireRememberForUndo() +{ + WireUndoEvent *wue; + + wue = (WireUndoEvent *) UndoNewEvent(WireUndoClientID, + sizeof(WireUndoEvent)); + if (wue == NULL) return; + + wue->wue_oldType = wireOldType; + wue->wue_newType = wireOldType = WireType; + wue->wue_oldWidth = wireOldWidth; + wue->wue_newWidth = wireOldWidth = WireWidth; + wue->wue_oldDir = wireOldDir; + wue->wue_newDir = wireOldDir = WireLastDir; +} + +/* + * ---------------------------------------------------------------------------- + * WireUndoForw -- + * WireUndoBack -- + * + * These two routines are called by the undo package to process + * undo events. WireUndoForw processes events during redo's and + * WireUndoBack processes events during undo's + * + * Results: + * None. + * + * Side effects: + * Wiring parameters are modified. + * ---------------------------------------------------------------------------- + */ + +void +WireUndoForw(wue) + WireUndoEvent *wue; /* Event to be redone. */ +{ + WireType = wireOldType = wue->wue_newType; + WireWidth = wireOldWidth = wue->wue_newWidth; + WireLastDir = wireOldDir = wue->wue_newDir; +} + +void +WireUndoBack(wue) + WireUndoEvent *wue; /* Event to be undone. */ +{ + WireType = wireOldType = wue->wue_oldType; + WireWidth = wireOldWidth = wue->wue_oldWidth; + WireLastDir = wireOldDir = wue->wue_oldDir; +} diff --git a/wiring/wiring.h b/wiring/wiring.h new file mode 100644 index 00000000..022596e4 --- /dev/null +++ b/wiring/wiring.h @@ -0,0 +1,94 @@ +/* + * wiring.h -- + * + * Contains definitions for things that are exported by the + * wiring module. + * + * ********************************************************************* + * * Copyright (C) 1985, 1990 Regents of the University of California. * + * * Permission to use, copy, modify, and distribute this * + * * software and its documentation for any purpose and without * + * * fee is hereby granted, provided that the above copyright * + * * notice appear in all copies. The University of California * + * * makes no representations about the suitability of this * + * * software for any purpose. It is provided "as is" without * + * * express or implied warranty. Export of this software outside * + * * of the United States of America may require an export license. * + * ********************************************************************* + * + * rcsid $Header: /usr/cvsroot/magic-8.0/wiring/wiring.h,v 1.2 2008/09/05 13:56:25 tim Exp $ + */ + +#ifndef _WIRING_H +#define _WIRING_H + +#include "utils/magic.h" +#include "database/database.h" + +/* Table that defines the shape of contacts and the layers that they + * connect. This definition allows some layers to extend around the + * contact, to support technologies where the contact pads are different + * sizes for the different layers that the contact connects. + */ + +typedef struct _Contact *ContactPtr; + +typedef struct _Contact +{ + TileType con_type; /* Type of material that forms core of + * contact. + */ + int con_size; /* Minimum size of this contact (size of + * minimum con_type area). + */ + TileType con_layer1; /* First of two layers that the contact + * really isn't a contact. + */ + int con_surround1; /* How much additional material of type + * con_layer1 must be painted around the + * edge of the contact. + */ + TileType con_layer2; /* Same information for second layer that + * the contact connects. + */ + int con_surround2; + + ContactPtr con_next; /* Pointer to next contact record */ +} Contact; + +extern Contact *WireContacts; /* Points to all the contacts that are + * defined. */ + +/* Types defining the current state of the wiring tool */ +extern TileType WireType; /* Type of material currently selected + * for wiring. + */ +extern int WireWidth; /* Thickness of material to use for wiring. */ + +/* Procedures for placing wires: */ + +extern void WirePickType(); +extern void WireAddLeg(); +extern void WireAddContact(); +extern void WireShowLeg(); +extern int WireGetWidth(); +extern TileType WireGetType(); + +/* Legal values for the "direction" parameter to WireAddLeg: */ + +#define WIRE_CHOOSE 0 +#define WIRE_HORIZONTAL 1 +#define WIRE_VERTICAL 2 + +/* Procedures for reading the technology file: */ + +extern void WireTechInit(); +extern bool WireTechLine(); +extern void WireTechFinal(); +extern void WireTechScale(); + +/* Initialization: */ + +extern void WireInit(); + +#endif /* _WIRING_H */
' . + &t2h_anchor('', $href, $entry) . + '  ' . + $descr . + "
' . + $entry . + '' . $descr . + "